From ef4122213c440c55d32c097c08e52170f4b4346a Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Mon, 6 Aug 2012 15:35:40 +0100 Subject: enables configurable minimum sizes for physical & non-physical prims --- OpenSim/Region/Framework/Scenes/Scene.cs | 31 ++++++++++- OpenSim/Region/Framework/Scenes/SceneGraph.cs | 9 ++-- .../Region/Framework/Scenes/SceneObjectGroup.cs | 60 +++++++++++++++++++--- OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | 13 +++-- .../Shared/Api/Implementation/LSL_Api.cs | 28 +++------- 5 files changed, 101 insertions(+), 40 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 0e5ddfd..d2d6aba 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -103,8 +103,26 @@ namespace OpenSim.Region.Framework.Scenes /// public bool CollidablePrims { get; private set; } + /// + /// Minimum value of the size of a non-physical prim in each axis + /// + public float m_minNonphys = 0.01f; + + /// + /// Maximum value of the size of a non-physical prim in each axis + /// public float m_maxNonphys = 256; + + /// + /// Minimum value of the size of a physical prim in each axis + /// + public float m_minPhys = 0.01f; + + /// + /// Maximum value of the size of a physical prim in each axis + /// public float m_maxPhys = 10; + public bool m_clampPrimSize; public bool m_trustBinaries; public bool m_allowScriptCrossings; @@ -721,14 +739,25 @@ namespace OpenSim.Region.Framework.Scenes PhysicalPrims = startupConfig.GetBoolean("physical_prim", PhysicalPrims); CollidablePrims = startupConfig.GetBoolean("collidable_prim", CollidablePrims); + m_minNonphys = startupConfig.GetFloat("NonphysicalPrimMin", m_minNonphys); + if (RegionInfo.NonphysPrimMin > 0) + { + m_minNonphys = RegionInfo.NonphysPrimMin; + } + m_maxNonphys = startupConfig.GetFloat("NonphysicalPrimMax", m_maxNonphys); if (RegionInfo.NonphysPrimMax > 0) { m_maxNonphys = RegionInfo.NonphysPrimMax; } - m_maxPhys = startupConfig.GetFloat("PhysicalPrimMax", m_maxPhys); + m_minPhys = startupConfig.GetFloat("PhysicalPrimMin", m_minPhys); + if (RegionInfo.PhysPrimMin > 0) + { + m_minPhys = RegionInfo.PhysPrimMin; + } + m_maxPhys = startupConfig.GetFloat("PhysicalPrimMax", m_maxPhys); if (RegionInfo.PhysPrimMax > 0) { m_maxPhys = RegionInfo.PhysPrimMax; diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs index 13842ad..b6339fb 100644 --- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs +++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs @@ -375,12 +375,9 @@ namespace OpenSim.Region.Framework.Scenes { Vector3 scale = part.Shape.Scale; - if (scale.X > m_parentScene.m_maxNonphys) - scale.X = m_parentScene.m_maxNonphys; - if (scale.Y > m_parentScene.m_maxNonphys) - scale.Y = m_parentScene.m_maxNonphys; - if (scale.Z > m_parentScene.m_maxNonphys) - scale.Z = m_parentScene.m_maxNonphys; + scale.X = Math.Max(m_parentScene.m_minNonphys, Math.Min(m_parentScene.m_maxNonphys, scale.X)); + scale.Y = Math.Max(m_parentScene.m_minNonphys, Math.Min(m_parentScene.m_maxNonphys, scale.Y)); + scale.Z = Math.Max(m_parentScene.m_minNonphys, Math.Min(m_parentScene.m_maxNonphys, scale.Z)); part.Shape.Scale = scale; } diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index 5f90035..f6c725b 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -2674,17 +2674,17 @@ namespace OpenSim.Region.Framework.Scenes RootPart.StoreUndoState(true); - scale.X = Math.Min(scale.X, Scene.m_maxNonphys); - scale.Y = Math.Min(scale.Y, Scene.m_maxNonphys); - scale.Z = Math.Min(scale.Z, Scene.m_maxNonphys); + scale.X = Math.Max(Scene.m_minNonphys, Math.Min(Scene.m_maxNonphys, scale.X)); + scale.Y = Math.Max(Scene.m_minNonphys, Math.Min(Scene.m_maxNonphys, scale.Y)); + scale.Z = Math.Max(Scene.m_minNonphys, Math.Min(Scene.m_maxNonphys, scale.Z)); PhysicsActor pa = m_rootPart.PhysActor; if (pa != null && pa.IsPhysical) { - scale.X = Math.Min(scale.X, Scene.m_maxPhys); - scale.Y = Math.Min(scale.Y, Scene.m_maxPhys); - scale.Z = Math.Min(scale.Z, Scene.m_maxPhys); + scale.X = Math.Max(Scene.m_minPhys, Math.Min(Scene.m_maxPhys, scale.X)); + scale.Y = Math.Max(Scene.m_minPhys, Math.Min(Scene.m_maxPhys, scale.Y)); + scale.Z = Math.Max(Scene.m_minPhys, Math.Min(Scene.m_maxPhys, scale.Z)); } float x = (scale.X / RootPart.Scale.X); @@ -2716,6 +2716,14 @@ namespace OpenSim.Region.Framework.Scenes y *= a; z *= a; } + else if (oldSize.X * x < m_scene.m_minPhys) + { + f = m_scene.m_minPhys / oldSize.X; + a = f / x; + x *= a; + y *= a; + z *= a; + } if (oldSize.Y * y > m_scene.m_maxPhys) { @@ -2725,6 +2733,14 @@ namespace OpenSim.Region.Framework.Scenes y *= a; z *= a; } + else if (oldSize.Y * y < m_scene.m_minPhys) + { + f = m_scene.m_minPhys / oldSize.Y; + a = f / y; + x *= a; + y *= a; + z *= a; + } if (oldSize.Z * z > m_scene.m_maxPhys) { @@ -2734,6 +2750,14 @@ namespace OpenSim.Region.Framework.Scenes y *= a; z *= a; } + else if (oldSize.Z * z < m_scene.m_minPhys) + { + f = m_scene.m_minPhys / oldSize.Z; + a = f / z; + x *= a; + y *= a; + z *= a; + } } else { @@ -2745,6 +2769,14 @@ namespace OpenSim.Region.Framework.Scenes y *= a; z *= a; } + else if (oldSize.X * x < m_scene.m_minNonphys) + { + f = m_scene.m_minNonphys / oldSize.X; + a = f / x; + x *= a; + y *= a; + z *= a; + } if (oldSize.Y * y > m_scene.m_maxNonphys) { @@ -2754,6 +2786,14 @@ namespace OpenSim.Region.Framework.Scenes y *= a; z *= a; } + else if (oldSize.Y * y < m_scene.m_minNonphys) + { + f = m_scene.m_minNonphys / oldSize.Y; + a = f / y; + x *= a; + y *= a; + z *= a; + } if (oldSize.Z * z > m_scene.m_maxNonphys) { @@ -2763,6 +2803,14 @@ namespace OpenSim.Region.Framework.Scenes y *= a; z *= a; } + else if (oldSize.Z * z < m_scene.m_minNonphys) + { + f = m_scene.m_minNonphys / oldSize.Z; + a = f / z; + x *= a; + y *= a; + z *= a; + } } // obPart.IgnoreUndoUpdate = false; diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index 4c87639..cd75224 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -2368,17 +2368,16 @@ namespace OpenSim.Region.Framework.Scenes /// public void Resize(Vector3 scale) { - scale.X = Math.Min(scale.X, ParentGroup.Scene.m_maxNonphys); - scale.Y = Math.Min(scale.Y, ParentGroup.Scene.m_maxNonphys); - scale.Z = Math.Min(scale.Z, ParentGroup.Scene.m_maxNonphys); + scale.X = Math.Max(ParentGroup.Scene.m_minNonphys, Math.Min(ParentGroup.Scene.m_maxNonphys, scale.X)); + scale.Y = Math.Max(ParentGroup.Scene.m_minNonphys, Math.Min(ParentGroup.Scene.m_maxNonphys, scale.Y)); + scale.Z = Math.Max(ParentGroup.Scene.m_minNonphys, Math.Min(ParentGroup.Scene.m_maxNonphys, scale.Z)); PhysicsActor pa = PhysActor; - if (pa != null && pa.IsPhysical) { - scale.X = Math.Min(scale.X, ParentGroup.Scene.m_maxPhys); - scale.Y = Math.Min(scale.Y, ParentGroup.Scene.m_maxPhys); - scale.Z = Math.Min(scale.Z, ParentGroup.Scene.m_maxPhys); + scale.X = Math.Max(ParentGroup.Scene.m_minPhys, Math.Min(ParentGroup.Scene.m_maxPhys, scale.X)); + scale.Y = Math.Max(ParentGroup.Scene.m_minPhys, Math.Min(ParentGroup.Scene.m_maxPhys, scale.Y)); + scale.Z = Math.Max(ParentGroup.Scene.m_minPhys, Math.Min(ParentGroup.Scene.m_maxPhys, scale.Z)); } // m_log.DebugFormat("[SCENE OBJECT PART]: Resizing {0} {1} to {2}", Name, LocalId, scale); diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 55567d1..a7852ec 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -1343,31 +1343,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (part == null || part.ParentGroup.IsDeleted) return; - if (scale.x < 0.01) - scale.x = 0.01; - if (scale.y < 0.01) - scale.y = 0.01; - if (scale.z < 0.01) - scale.z = 0.01; - + // First we need to check whether or not we need to clamp the size of a physics-enabled prim PhysicsActor pa = part.ParentGroup.RootPart.PhysActor; - if (pa != null && pa.IsPhysical) { - if (scale.x > World.m_maxPhys) - scale.x = World.m_maxPhys; - if (scale.y > World.m_maxPhys) - scale.y = World.m_maxPhys; - if (scale.z > World.m_maxPhys) - scale.z = World.m_maxPhys; + scale.x = Math.Max(World.m_minPhys, Math.Min(World.m_maxPhys, scale.x)); + scale.y = Math.Max(World.m_minPhys, Math.Min(World.m_maxPhys, scale.y)); + scale.z = Math.Max(World.m_minPhys, Math.Min(World.m_maxPhys, scale.z)); } - if (scale.x > World.m_maxNonphys) - scale.x = World.m_maxNonphys; - if (scale.y > World.m_maxNonphys) - scale.y = World.m_maxNonphys; - if (scale.z > World.m_maxNonphys) - scale.z = World.m_maxNonphys; + // Next we clamp the scale to the non-physical min/max + scale.x = Math.Max(World.m_minNonphys, Math.Min(World.m_maxNonphys, scale.x)); + scale.y = Math.Max(World.m_minNonphys, Math.Min(World.m_maxNonphys, scale.y)); + scale.z = Math.Max(World.m_minNonphys, Math.Min(World.m_maxNonphys, scale.z)); Vector3 tmp = part.Scale; tmp.X = (float)scale.x; -- cgit v1.1 From 376441e5507052b36279279f64896542d44ec12a Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Wed, 15 Aug 2012 16:27:30 -0700 Subject: BulletSim: make it so objects in a linkset do not generate collisions with each other. --- OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs | 7 +++++++ OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | 10 ++++++++++ OpenSim/Region/Physics/BulletSPlugin/BSScene.cs | 12 ++++++++++-- 3 files changed, 27 insertions(+), 2 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs index 087b9bb..1b3ba3f 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs @@ -42,6 +42,9 @@ public class BSLinkset private BSScene m_physicsScene; public BSScene PhysicsScene { get { return m_physicsScene; } } + static int m_nextLinksetID = 1; + public int LinksetID { get; private set; } + // The children under the root in this linkset private List m_children; @@ -74,6 +77,10 @@ public class BSLinkset public BSLinkset(BSScene scene, BSPrim parent) { // A simple linkset of one (no children) + LinksetID = m_nextLinksetID++; + // We create LOTS of linksets. + if (m_nextLinksetID < 0) + m_nextLinksetID = 1; m_physicsScene = scene; m_linksetRoot = parent; m_children = new List(); diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index 9c20004..c157669 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs @@ -1353,6 +1353,7 @@ public sealed class BSPrim : PhysicsActor } // I've collided with something + // Called at taint time from within the Step() function CollisionEventUpdate collisionCollection; public void Collide(uint collidingWith, ActorTypes type, OMV.Vector3 contactPoint, OMV.Vector3 contactNormal, float pentrationDepth) { @@ -1366,6 +1367,15 @@ public sealed class BSPrim : PhysicsActor } // DetailLog("{0},BSPrim.Collison,call,with={1}", LocalID, collidingWith); + BSPrim collidingWithPrim; + if (_scene.Prims.TryGetValue(collidingWith, out collidingWithPrim)) + { + // prims in the same linkset cannot collide with each other + if (this.Linkset.LinksetID == collidingWithPrim.Linkset.LinksetID) + { + return; + } + } // if someone is subscribed to collision events.... if (_subscribedEventsMs != 0) { diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs index a31c578..0a0e27e 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs @@ -78,10 +78,16 @@ public class BSScene : PhysicsScene, IPhysicsParameters public string BulletSimVersion = "?"; private Dictionary m_avatars = new Dictionary(); + public Dictionary Characters { get { return m_avatars; } } + private Dictionary m_prims = new Dictionary(); + public Dictionary Prims { get { return m_prims; } } + private HashSet m_avatarsWithCollisions = new HashSet(); private HashSet m_primsWithCollisions = new HashSet(); + private List m_vehicles = new List(); + private float[] m_heightMap; private float m_waterLevel; private uint m_worldID; @@ -429,13 +435,13 @@ public class BSScene : PhysicsScene, IPhysicsParameters { numSubSteps = BulletSimAPI.PhysicsStep(m_worldID, timeStep, m_maxSubSteps, m_fixedTimeStep, out updatedEntityCount, out updatedEntitiesPtr, out collidersCount, out collidersPtr); - // DetailLog("{0},Simulate,call, substeps={1}, updates={2}, colliders={3}", DetailLogZero, numSubSteps, updatedEntityCount, collidersCount); + DetailLog("{0},Simulate,call, substeps={1}, updates={2}, colliders={3}", DetailLogZero, numSubSteps, updatedEntityCount, collidersCount); } catch (Exception e) { m_log.WarnFormat("{0},PhysicsStep Exception: substeps={1}, updates={2}, colliders={3}, e={4}", LogHeader, numSubSteps, updatedEntityCount, collidersCount, e); // DetailLog("{0},PhysicsStepException,call, substeps={1}, updates={2}, colliders={3}", DetailLogZero, numSubSteps, updatedEntityCount, collidersCount); - // updatedEntityCount = 0; + updatedEntityCount = 0; collidersCount = 0; } @@ -534,6 +540,8 @@ public class BSScene : PhysicsScene, IPhysicsParameters else if (m_avatars.ContainsKey(collidingWith)) type = ActorTypes.Agent; + DetailLog("{0},BSScene.SendCollision,collide,id={1},with={2}", DetailLogZero, localID, collidingWith); + BSPrim prim; if (m_prims.TryGetValue(localID, out prim)) { prim.Collide(collidingWith, type, collidePoint, collideNormal, penitration); -- cgit v1.1 From 57a98796693cdd34efefbc9235b5d0aa765db095 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Wed, 15 Aug 2012 16:39:00 -0700 Subject: Correct an exception report in SceneObjectPart so it outputs the stack. --- OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index cd75224..bd6369c 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -733,7 +733,7 @@ namespace OpenSim.Region.Framework.Scenes } catch (Exception e) { - m_log.Error("[SCENEOBJECTPART]: GROUP POSITION. " + e.Message); + m_log.ErrorFormat("[SCENEOBJECTPART]: GROUP POSITION. {0}", e); } } -- cgit v1.1 From e9ea911563362c4766d34cd948a2915beac06124 Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Fri, 17 Aug 2012 16:53:36 +0100 Subject: adding a clip method to handle Vector3 objects to enable a minor amount of refactoring --- .../Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 11 +++++------ 1 file changed, 5 insertions(+), 6 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 a7852ec..b7b5e8e 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -4019,9 +4019,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public void llSetText(string text, LSL_Vector color, double alpha) { m_host.AddScriptLPS(1); - Vector3 av3 = new Vector3(Util.Clip((float)color.x, 0.0f, 1.0f), - Util.Clip((float)color.y, 0.0f, 1.0f), - Util.Clip((float)color.z, 0.0f, 1.0f)); + Vector3 av3 = Util.Clip(new Vector3((float)color.x, (float)color.y, + (float)color.z), 0.0f, 1.0f); m_host.SetText(text.Length > 254 ? text.Remove(254) : text, av3, Util.Clip((float)alpha, 0.0f, 1.0f)); //m_host.ParentGroup.HasGroupChanged = true; //m_host.ParentGroup.ScheduleGroupForFullUpdate(); @@ -7635,9 +7634,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api string primText = rules.GetLSLStringItem(idx++); LSL_Vector primTextColor = rules.GetVector3Item(idx++); LSL_Float primTextAlpha = rules.GetLSLFloatItem(idx++); - Vector3 av3 = new Vector3(Util.Clip((float)primTextColor.x, 0.0f, 1.0f), - Util.Clip((float)primTextColor.y, 0.0f, 1.0f), - Util.Clip((float)primTextColor.z, 0.0f, 1.0f)); + Vector3 av3 = Util.Clip(new Vector3((float)primTextColor.x, + (float)primTextColor.y, + (float)primTextColor.z), 0.0f, 1.0f); part.SetText(primText, av3, Util.Clip((float)primTextAlpha, 0.0f, 1.0f)); break; -- cgit v1.1 From e31e23d68d9935457ad86559bea37b2b4a63a8dc Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Wed, 15 Aug 2012 16:49:05 -0700 Subject: BulletSim: in BSDynamics, merge 'flags' and 'hoverFlags' as they are defined for the same bits and it makes the code less complicated. --- OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs | 178 +++------------------ 1 file changed, 20 insertions(+), 158 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs index 5a9f135..78bfa05 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs @@ -74,7 +74,6 @@ namespace OpenSim.Region.Physics.BulletSPlugin // HOVER_UP_ONLY // LIMIT_MOTOR_UP // LIMIT_ROLL_ONLY - private VehicleFlag m_Hoverflags = (VehicleFlag)0; private Vector3 m_BlockingEndPoint = Vector3.Zero; private Quaternion m_RollreferenceFrame = Quaternion.Identity; // Linear properties @@ -281,157 +280,20 @@ namespace OpenSim.Region.Physics.BulletSPlugin internal void ProcessVehicleFlags(int pParam, bool remove) { DetailLog("{0},ProcessVehicleFlags,param={1},remove={2}", m_prim.LocalID, pParam, remove); + VehicleFlag parm = (VehicleFlag)pParam; if (remove) { if (pParam == -1) { m_flags = (VehicleFlag)0; - m_Hoverflags = (VehicleFlag)0; - return; } - if ((pParam & (int)VehicleFlag.HOVER_GLOBAL_HEIGHT) == (int)VehicleFlag.HOVER_GLOBAL_HEIGHT) - { - if ((m_Hoverflags & VehicleFlag.HOVER_GLOBAL_HEIGHT) != (VehicleFlag)0) - m_Hoverflags &= ~(VehicleFlag.HOVER_GLOBAL_HEIGHT); - } - if ((pParam & (int)VehicleFlag.HOVER_TERRAIN_ONLY) == (int)VehicleFlag.HOVER_TERRAIN_ONLY) - { - if ((m_Hoverflags & VehicleFlag.HOVER_TERRAIN_ONLY) != (VehicleFlag)0) - m_Hoverflags &= ~(VehicleFlag.HOVER_TERRAIN_ONLY); - } - if ((pParam & (int)VehicleFlag.HOVER_UP_ONLY) == (int)VehicleFlag.HOVER_UP_ONLY) - { - if ((m_Hoverflags & VehicleFlag.HOVER_UP_ONLY) != (VehicleFlag)0) - m_Hoverflags &= ~(VehicleFlag.HOVER_UP_ONLY); - } - if ((pParam & (int)VehicleFlag.HOVER_WATER_ONLY) == (int)VehicleFlag.HOVER_WATER_ONLY) - { - if ((m_Hoverflags & VehicleFlag.HOVER_WATER_ONLY) != (VehicleFlag)0) - m_Hoverflags &= ~(VehicleFlag.HOVER_WATER_ONLY); - } - if ((pParam & (int)VehicleFlag.LIMIT_MOTOR_UP) == (int)VehicleFlag.LIMIT_MOTOR_UP) - { - if ((m_flags & VehicleFlag.LIMIT_MOTOR_UP) != (VehicleFlag)0) - m_flags &= ~(VehicleFlag.LIMIT_MOTOR_UP); - } - if ((pParam & (int)VehicleFlag.LIMIT_ROLL_ONLY) == (int)VehicleFlag.LIMIT_ROLL_ONLY) - { - if ((m_flags & VehicleFlag.LIMIT_ROLL_ONLY) != (VehicleFlag)0) - m_flags &= ~(VehicleFlag.LIMIT_ROLL_ONLY); - } - if ((pParam & (int)VehicleFlag.MOUSELOOK_BANK) == (int)VehicleFlag.MOUSELOOK_BANK) - { - if ((m_flags & VehicleFlag.MOUSELOOK_BANK) != (VehicleFlag)0) - m_flags &= ~(VehicleFlag.MOUSELOOK_BANK); - } - if ((pParam & (int)VehicleFlag.MOUSELOOK_STEER) == (int)VehicleFlag.MOUSELOOK_STEER) - { - if ((m_flags & VehicleFlag.MOUSELOOK_STEER) != (VehicleFlag)0) - m_flags &= ~(VehicleFlag.MOUSELOOK_STEER); - } - if ((pParam & (int)VehicleFlag.NO_DEFLECTION_UP) == (int)VehicleFlag.NO_DEFLECTION_UP) - { - if ((m_flags & VehicleFlag.NO_DEFLECTION_UP) != (VehicleFlag)0) - m_flags &= ~(VehicleFlag.NO_DEFLECTION_UP); - } - if ((pParam & (int)VehicleFlag.CAMERA_DECOUPLED) == (int)VehicleFlag.CAMERA_DECOUPLED) - { - if ((m_flags & VehicleFlag.CAMERA_DECOUPLED) != (VehicleFlag)0) - m_flags &= ~(VehicleFlag.CAMERA_DECOUPLED); - } - if ((pParam & (int)VehicleFlag.NO_X) == (int)VehicleFlag.NO_X) - { - if ((m_flags & VehicleFlag.NO_X) != (VehicleFlag)0) - m_flags &= ~(VehicleFlag.NO_X); - } - if ((pParam & (int)VehicleFlag.NO_Y) == (int)VehicleFlag.NO_Y) - { - if ((m_flags & VehicleFlag.NO_Y) != (VehicleFlag)0) - m_flags &= ~(VehicleFlag.NO_Y); - } - if ((pParam & (int)VehicleFlag.NO_Z) == (int)VehicleFlag.NO_Z) - { - if ((m_flags & VehicleFlag.NO_Z) != (VehicleFlag)0) - m_flags &= ~(VehicleFlag.NO_Z); - } - if ((pParam & (int)VehicleFlag.LOCK_HOVER_HEIGHT) == (int)VehicleFlag.LOCK_HOVER_HEIGHT) - { - if ((m_Hoverflags & VehicleFlag.LOCK_HOVER_HEIGHT) != (VehicleFlag)0) - m_Hoverflags &= ~(VehicleFlag.LOCK_HOVER_HEIGHT); - } - if ((pParam & (int)VehicleFlag.NO_DEFLECTION) == (int)VehicleFlag.NO_DEFLECTION) - { - if ((m_flags & VehicleFlag.NO_DEFLECTION) != (VehicleFlag)0) - m_flags &= ~(VehicleFlag.NO_DEFLECTION); - } - if ((pParam & (int)VehicleFlag.LOCK_ROTATION) == (int)VehicleFlag.LOCK_ROTATION) + else { - if ((m_flags & VehicleFlag.LOCK_ROTATION) != (VehicleFlag)0) - m_flags &= ~(VehicleFlag.LOCK_ROTATION); + m_flags &= ~parm; } } - else - { - if ((pParam & (int)VehicleFlag.HOVER_GLOBAL_HEIGHT) == (int)VehicleFlag.HOVER_GLOBAL_HEIGHT) - { - m_Hoverflags |= (VehicleFlag.HOVER_GLOBAL_HEIGHT | m_flags); - } - if ((pParam & (int)VehicleFlag.HOVER_TERRAIN_ONLY) == (int)VehicleFlag.HOVER_TERRAIN_ONLY) - { - m_Hoverflags |= (VehicleFlag.HOVER_TERRAIN_ONLY | m_flags); - } - if ((pParam & (int)VehicleFlag.HOVER_UP_ONLY) == (int)VehicleFlag.HOVER_UP_ONLY) - { - m_Hoverflags |= (VehicleFlag.HOVER_UP_ONLY | m_flags); - } - if ((pParam & (int)VehicleFlag.HOVER_WATER_ONLY) == (int)VehicleFlag.HOVER_WATER_ONLY) - { - m_Hoverflags |= (VehicleFlag.HOVER_WATER_ONLY | m_flags); - } - if ((pParam & (int)VehicleFlag.LIMIT_MOTOR_UP) == (int)VehicleFlag.LIMIT_MOTOR_UP) - { - m_flags |= (VehicleFlag.LIMIT_MOTOR_UP | m_flags); - } - if ((pParam & (int)VehicleFlag.MOUSELOOK_BANK) == (int)VehicleFlag.MOUSELOOK_BANK) - { - m_flags |= (VehicleFlag.MOUSELOOK_BANK | m_flags); - } - if ((pParam & (int)VehicleFlag.MOUSELOOK_STEER) == (int)VehicleFlag.MOUSELOOK_STEER) - { - m_flags |= (VehicleFlag.MOUSELOOK_STEER | m_flags); - } - if ((pParam & (int)VehicleFlag.NO_DEFLECTION_UP) == (int)VehicleFlag.NO_DEFLECTION_UP) - { - m_flags |= (VehicleFlag.NO_DEFLECTION_UP | m_flags); - } - if ((pParam & (int)VehicleFlag.CAMERA_DECOUPLED) == (int)VehicleFlag.CAMERA_DECOUPLED) - { - m_flags |= (VehicleFlag.CAMERA_DECOUPLED | m_flags); - } - if ((pParam & (int)VehicleFlag.NO_X) == (int)VehicleFlag.NO_X) - { - m_flags |= (VehicleFlag.NO_X); - } - if ((pParam & (int)VehicleFlag.NO_Y) == (int)VehicleFlag.NO_Y) - { - m_flags |= (VehicleFlag.NO_Y); - } - if ((pParam & (int)VehicleFlag.NO_Z) == (int)VehicleFlag.NO_Z) - { - m_flags |= (VehicleFlag.NO_Z); - } - if ((pParam & (int)VehicleFlag.LOCK_HOVER_HEIGHT) == (int)VehicleFlag.LOCK_HOVER_HEIGHT) - { - m_Hoverflags |= (VehicleFlag.LOCK_HOVER_HEIGHT); - } - if ((pParam & (int)VehicleFlag.NO_DEFLECTION) == (int)VehicleFlag.NO_DEFLECTION) - { - m_flags |= (VehicleFlag.NO_DEFLECTION); - } - if ((pParam & (int)VehicleFlag.LOCK_ROTATION) == (int)VehicleFlag.LOCK_ROTATION) - { - m_flags |= (VehicleFlag.LOCK_ROTATION); - } + else { + m_flags |= parm; } }//end ProcessVehicleFlags @@ -478,10 +340,10 @@ namespace OpenSim.Region.Physics.BulletSPlugin // m_bankingMix = 1; // m_bankingTimescale = 10; // m_referenceFrame = Quaternion.Identity; - m_Hoverflags &= + m_flags |= (VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.LIMIT_ROLL_ONLY | VehicleFlag.LIMIT_MOTOR_UP); + m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT | VehicleFlag.HOVER_UP_ONLY); - m_flags |= (VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.LIMIT_ROLL_ONLY | VehicleFlag.LIMIT_MOTOR_UP); break; case Vehicle.TYPE_CAR: m_linearFrictionTimescale = new Vector3(100, 2, 1000); @@ -506,10 +368,10 @@ namespace OpenSim.Region.Physics.BulletSPlugin // m_bankingMix = 1; // m_bankingTimescale = 1; // m_referenceFrame = Quaternion.Identity; - m_Hoverflags &= ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT); m_flags |= (VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.LIMIT_ROLL_ONLY | VehicleFlag.LIMIT_MOTOR_UP); - m_Hoverflags |= (VehicleFlag.HOVER_UP_ONLY); + m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT); + m_flags |= (VehicleFlag.HOVER_UP_ONLY); break; case Vehicle.TYPE_BOAT: m_linearFrictionTimescale = new Vector3(10, 3, 2); @@ -534,12 +396,12 @@ namespace OpenSim.Region.Physics.BulletSPlugin // m_bankingMix = 0.8f; // m_bankingTimescale = 1; // m_referenceFrame = Quaternion.Identity; - m_Hoverflags &= ~(VehicleFlag.HOVER_TERRAIN_ONLY | + m_flags &= ~(VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT | VehicleFlag.HOVER_UP_ONLY); m_flags &= ~(VehicleFlag.LIMIT_ROLL_ONLY); m_flags |= (VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.LIMIT_MOTOR_UP); - m_Hoverflags |= (VehicleFlag.HOVER_WATER_ONLY); + m_flags |= (VehicleFlag.HOVER_WATER_ONLY); break; case Vehicle.TYPE_AIRPLANE: m_linearFrictionTimescale = new Vector3(200, 10, 5); @@ -564,7 +426,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin // m_bankingMix = 0.7f; // m_bankingTimescale = 2; // m_referenceFrame = Quaternion.Identity; - m_Hoverflags &= ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | + m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT | VehicleFlag.HOVER_UP_ONLY); m_flags &= ~(VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.LIMIT_MOTOR_UP); m_flags |= (VehicleFlag.LIMIT_ROLL_ONLY); @@ -592,11 +454,11 @@ namespace OpenSim.Region.Physics.BulletSPlugin // m_bankingMix = 0.7f; // m_bankingTimescale = 5; // m_referenceFrame = Quaternion.Identity; - m_Hoverflags &= ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | + m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.HOVER_UP_ONLY); m_flags &= ~(VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.LIMIT_MOTOR_UP); m_flags |= (VehicleFlag.LIMIT_ROLL_ONLY); - m_Hoverflags |= (VehicleFlag.HOVER_GLOBAL_HEIGHT); + m_flags |= (VehicleFlag.HOVER_GLOBAL_HEIGHT); break; } }//end SetDefaultsForType @@ -736,28 +598,28 @@ namespace OpenSim.Region.Physics.BulletSPlugin } // Check if hovering - if ((m_Hoverflags & (VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT)) != 0) + if ((m_flags & (VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT)) != 0) { // We should hover, get the target height - if ((m_Hoverflags & VehicleFlag.HOVER_WATER_ONLY) != 0) + if ((m_flags & VehicleFlag.HOVER_WATER_ONLY) != 0) { m_VhoverTargetHeight = m_prim.Scene.GetWaterLevel() + m_VhoverHeight; } - if ((m_Hoverflags & VehicleFlag.HOVER_TERRAIN_ONLY) != 0) + if ((m_flags & VehicleFlag.HOVER_TERRAIN_ONLY) != 0) { m_VhoverTargetHeight = m_prim.Scene.GetTerrainHeightAtXY(pos.X, pos.Y) + m_VhoverHeight; } - if ((m_Hoverflags & VehicleFlag.HOVER_GLOBAL_HEIGHT) != 0) + if ((m_flags & VehicleFlag.HOVER_GLOBAL_HEIGHT) != 0) { m_VhoverTargetHeight = m_VhoverHeight; } - if ((m_Hoverflags & VehicleFlag.HOVER_UP_ONLY) != 0) + if ((m_flags & VehicleFlag.HOVER_UP_ONLY) != 0) { // If body is aready heigher, use its height as target height if (pos.Z > m_VhoverTargetHeight) m_VhoverTargetHeight = pos.Z; } - if ((m_Hoverflags & VehicleFlag.LOCK_HOVER_HEIGHT) != 0) + if ((m_flags & VehicleFlag.LOCK_HOVER_HEIGHT) != 0) { if ((pos.Z - m_VhoverTargetHeight) > .2 || (pos.Z - m_VhoverTargetHeight) < -.2) { -- cgit v1.1 From 8eda290262bb7049aa55a7df2bdb1565bad85a99 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Fri, 17 Aug 2012 09:37:02 -0700 Subject: BulletSim: comments and parameter changes in dynamics engine. --- OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs | 50 ++++++++++++---------- OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | 6 +-- 2 files changed, 30 insertions(+), 26 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs index 78bfa05..d7213fc 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs @@ -57,6 +57,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin private int frcount = 0; // Used to limit dynamics debug output to // every 100th frame + private BSScene m_physicsScene; private BSPrim m_prim; // the prim this dynamic controller belongs to // Vehicle properties @@ -123,15 +124,16 @@ namespace OpenSim.Region.Physics.BulletSPlugin private float m_verticalAttractionEfficiency = 1.0f; // damped private float m_verticalAttractionTimescale = 500f; // Timescale > 300 means no vert attractor. - public BSDynamics(BSPrim myPrim) + public BSDynamics(BSScene myScene, BSPrim myPrim) { + m_physicsScene = myScene; m_prim = myPrim; m_type = Vehicle.TYPE_NONE; } internal void ProcessFloatVehicleParam(Vehicle pParam, float pValue, float timestep) { - DetailLog("{0},ProcessFloatVehicleParam,param={1},val={2}", m_prim.LocalID, pParam, pValue); + VDetailLog("{0},ProcessFloatVehicleParam,param={1},val={2}", m_prim.LocalID, pParam, pValue); switch (pParam) { case Vehicle.ANGULAR_DEFLECTION_EFFICIENCY: @@ -230,7 +232,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin internal void ProcessVectorVehicleParam(Vehicle pParam, Vector3 pValue, float timestep) { - DetailLog("{0},ProcessVectorVehicleParam,param={1},val={2}", m_prim.LocalID, pParam, pValue); + VDetailLog("{0},ProcessVectorVehicleParam,param={1},val={2}", m_prim.LocalID, pParam, pValue); switch (pParam) { case Vehicle.ANGULAR_FRICTION_TIMESCALE: @@ -265,7 +267,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin internal void ProcessRotationVehicleParam(Vehicle pParam, Quaternion pValue) { - DetailLog("{0},ProcessRotationalVehicleParam,param={1},val={2}", m_prim.LocalID, pParam, pValue); + VDetailLog("{0},ProcessRotationalVehicleParam,param={1},val={2}", m_prim.LocalID, pParam, pValue); switch (pParam) { case Vehicle.REFERENCE_FRAME: @@ -279,7 +281,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin internal void ProcessVehicleFlags(int pParam, bool remove) { - DetailLog("{0},ProcessVehicleFlags,param={1},remove={2}", m_prim.LocalID, pParam, remove); + VDetailLog("{0},ProcessVehicleFlags,param={1},remove={2}", m_prim.LocalID, pParam, remove); VehicleFlag parm = (VehicleFlag)pParam; if (remove) { @@ -297,9 +299,9 @@ namespace OpenSim.Region.Physics.BulletSPlugin } }//end ProcessVehicleFlags - internal void ProcessTypeChange(Vehicle pType) + internal void ProcessTypeChange(Vehicle pType, float stepSize) { - DetailLog("{0},ProcessTypeChange,type={1}", m_prim.LocalID, pType); + VDetailLog("{0},ProcessTypeChange,type={1}", m_prim.LocalID, pType); // Set Defaults For Type m_type = pType; switch (pType) @@ -475,7 +477,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin MoveAngular(pTimestep); LimitRotation(pTimestep); - DetailLog("{0},BSDynamics.Step,done,pos={1},force={2},velocity={3},angvel={4}", + VDetailLog("{0},BSDynamics.Step,done,pos={1},force={2},velocity={3},angvel={4}", m_prim.LocalID, m_prim.Position, m_prim.Force, m_prim.Velocity, m_prim.RotationalVelocity); }// end Step @@ -519,7 +521,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin */ - DetailLog("{0},MoveLinear,nonZero,origdir={1},origvel={2},add={3},decay={4},dir={5},vel={6}", + VDetailLog("{0},MoveLinear,nonZero,origdir={1},origvel={2},add={3},decay={4},dir={5},vel={6}", m_prim.LocalID, origDir, origVel, addAmount, decayfraction, m_linearMotorDirection, m_lastLinearVelocityVector); } else @@ -531,7 +533,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin m_lastLinearVelocityVector = Vector3.Zero; } - // convert requested object velocity to world-referenced vector + // convert requested object velocity to object relative vector Quaternion rotq = m_prim.Orientation; m_dir = m_lastLinearVelocityVector * rotq; @@ -584,7 +586,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin if (changed) { m_prim.Position = pos; - DetailLog("{0},MoveLinear,blockingEndPoint,block={1},origPos={2},pos={3}", + VDetailLog("{0},MoveLinear,blockingEndPoint,block={1},origPos={2},pos={3}", m_prim.LocalID, m_BlockingEndPoint, posChange, pos); } } @@ -594,7 +596,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin { pos.Z = m_prim.Scene.GetTerrainHeightAtXYZ(pos) + 2; m_prim.Position = pos; - DetailLog("{0},MoveLinear,terrainHeight,pos={1}", m_prim.LocalID, pos); + VDetailLog("{0},MoveLinear,terrainHeight,pos={1}", m_prim.LocalID, pos); } // Check if hovering @@ -641,7 +643,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin } } - DetailLog("{0},MoveLinear,hover,pos={1},dir={2},height={3},target={4}", m_prim.LocalID, pos, m_dir, m_VhoverHeight, m_VhoverTargetHeight); + VDetailLog("{0},MoveLinear,hover,pos={1},dir={2},height={3},target={4}", m_prim.LocalID, pos, m_dir, m_VhoverHeight, m_VhoverTargetHeight); // m_VhoverEfficiency = 0f; // 0=boucy, 1=Crit.damped // m_VhoverTimescale = 0f; // time to acheive height @@ -677,7 +679,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin { grav.Z = (float)(grav.Z * 1.037125); } - DetailLog("{0},MoveLinear,limitMotorUp,grav={1}", m_prim.LocalID, grav); + VDetailLog("{0},MoveLinear,limitMotorUp,grav={1}", m_prim.LocalID, grav); //End Experimental Values } if ((m_flags & (VehicleFlag.NO_X)) != 0) @@ -706,7 +708,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin Vector3 decayamount = Vector3.One / (m_linearFrictionTimescale / pTimestep); m_lastLinearVelocityVector -= m_lastLinearVelocityVector * decayamount; - DetailLog("{0},MoveLinear,done,pos={1},vel={2},force={3},decay={4}", + VDetailLog("{0},MoveLinear,done,pos={1},vel={2},force={3},decay={4}", m_prim.LocalID, m_lastPositionVector, m_dir, grav, decayamount); } // end MoveLinear() @@ -732,13 +734,13 @@ namespace OpenSim.Region.Physics.BulletSPlugin // There are m_angularMotorApply steps. Vector3 origAngularVelocity = m_angularMotorVelocity; // ramp up to new value - // current velocity += error / (time to get there / step interval) + // current velocity += error / (time to get there / step interval) // requested speed - last motor speed m_angularMotorVelocity.X += (m_angularMotorDirection.X - m_angularMotorVelocity.X) / (m_angularMotorTimescale / pTimestep); m_angularMotorVelocity.Y += (m_angularMotorDirection.Y - m_angularMotorVelocity.Y) / (m_angularMotorTimescale / pTimestep); m_angularMotorVelocity.Z += (m_angularMotorDirection.Z - m_angularMotorVelocity.Z) / (m_angularMotorTimescale / pTimestep); - DetailLog("{0},MoveAngular,angularMotorApply,apply={1},origvel={2},dir={3},vel={4}", + VDetailLog("{0},MoveAngular,angularMotorApply,apply={1},origvel={2},dir={3},vel={4}", m_prim.LocalID,m_angularMotorApply,origAngularVelocity, m_angularMotorDirection, m_angularMotorVelocity); m_angularMotorApply--; // This is done so that if script request rate is less than phys frame rate the expected @@ -749,6 +751,8 @@ namespace OpenSim.Region.Physics.BulletSPlugin // No motor recently applied, keep the body velocity // and decay the velocity m_angularMotorVelocity -= m_angularMotorVelocity / (m_angularMotorDecayTimescale / pTimestep); + if (m_angularMotorVelocity.LengthSquared() < 0.00001) + m_angularMotorVelocity = Vector3.Zero; } // end motor section // Vertical attractor section @@ -786,7 +790,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin vertattr.X += bounce * angularVelocity.X; vertattr.Y += bounce * angularVelocity.Y; - DetailLog("{0},MoveAngular,verticalAttraction,verterr={1},bounce={2},vertattr={3}", + VDetailLog("{0},MoveAngular,verticalAttraction,verterr={1},bounce={2},vertattr={3}", m_prim.LocalID, verterr, bounce, vertattr); } // else vertical attractor is off @@ -804,13 +808,13 @@ namespace OpenSim.Region.Physics.BulletSPlugin { m_lastAngularVelocity.X = 0; m_lastAngularVelocity.Y = 0; - DetailLog("{0},MoveAngular,noDeflectionUp,lastAngular={1}", m_prim.LocalID, m_lastAngularVelocity); + VDetailLog("{0},MoveAngular,noDeflectionUp,lastAngular={1}", m_prim.LocalID, m_lastAngularVelocity); } if (m_lastAngularVelocity.ApproxEquals(Vector3.Zero, 0.01f)) { m_lastAngularVelocity = Vector3.Zero; // Reduce small value to zero. - DetailLog("{0},MoveAngular,zeroSmallValues,lastAngular={1}", m_prim.LocalID, m_lastAngularVelocity); + VDetailLog("{0},MoveAngular,zeroSmallValues,lastAngular={1}", m_prim.LocalID, m_lastAngularVelocity); } // apply friction @@ -820,7 +824,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin // Apply to the body m_prim.RotationalVelocity = m_lastAngularVelocity; - DetailLog("{0},MoveAngular,done,decay={1},lastAngular={2}", m_prim.LocalID, decayamount, m_lastAngularVelocity); + VDetailLog("{0},MoveAngular,done,decay={1},lastAngular={2}", m_prim.LocalID, decayamount, m_lastAngularVelocity); } //end MoveAngular internal void LimitRotation(float timestep) @@ -867,11 +871,11 @@ namespace OpenSim.Region.Physics.BulletSPlugin if (changed) m_prim.Orientation = m_rot; - DetailLog("{0},LimitRotation,done,changed={1},orig={2},new={3}", m_prim.LocalID, changed, rotq, m_rot); + VDetailLog("{0},LimitRotation,done,changed={1},orig={2},new={3}", m_prim.LocalID, changed, rotq, m_rot); } // Invoke the detailed logger and output something if it's enabled. - private void DetailLog(string msg, params Object[] args) + private void VDetailLog(string msg, params Object[] args) { if (m_prim.Scene.VehicleLoggingEnabled) m_prim.Scene.PhysicsLogging.Write(msg, args); diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index c157669..b918f84 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs @@ -141,8 +141,8 @@ public sealed class BSPrim : PhysicsActor _friction = _scene.Params.defaultFriction; // TODO: compute based on object material _density = _scene.Params.defaultDensity; // TODO: compute based on object material _restitution = _scene.Params.defaultRestitution; - _linkset = new BSLinkset(_scene, this); // a linkset of one - _vehicle = new BSDynamics(this); // add vehicleness + _linkset = new BSLinkset(Scene, this); // a linkset of one + _vehicle = new BSDynamics(Scene, this); // add vehicleness _mass = CalculateMass(); // do the actual object creation at taint time DetailLog("{0},BSPrim.constructor,call", LocalID); @@ -354,7 +354,7 @@ public sealed class BSPrim : PhysicsActor { // Done at taint time so we're sure the physics engine is not using the variables // Vehicle code changes the parameters for this vehicle type. - _vehicle.ProcessTypeChange(type); + _vehicle.ProcessTypeChange(type, Scene.LastSimulatedTimestep); // Tell the scene about the vehicle so it will get processing each frame. _scene.VehicleInSceneTypeChanged(this, type); }); -- cgit v1.1 From ccc69d66a135e149dbe9c6b70df0c8efe1265f65 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Fri, 17 Aug 2012 10:40:34 -0700 Subject: BulletSim: add parameters and functionality to specify the mesh level of detail for large meshes. Remove parameter and code for DetailLog (conditional logging into regular log file). --- OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs | 14 ------ OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | 14 +++--- OpenSim/Region/Physics/BulletSPlugin/BSScene.cs | 54 +++++++++++------------ 3 files changed, 34 insertions(+), 48 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs index 1b3ba3f..a075995 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs @@ -265,7 +265,6 @@ public class BSLinkset BSPrim childx = child; m_physicsScene.TaintedObject("AddChildToLinkset", delegate() { - // DebugLog("{0}: AddChildToLinkset: adding child {1} to {2}", LogHeader, child.LocalID, m_linksetRoot.LocalID); // DetailLog("{0},AddChildToLinkset,taint,child={1}", m_linksetRoot.LocalID, child.LocalID); PhysicallyLinkAChildToRoot(rootx, childx); // build the physical binding between me and the child }); @@ -294,7 +293,6 @@ public class BSLinkset BSPrim childx = child; m_physicsScene.TaintedObject("RemoveChildFromLinkset", delegate() { - // DebugLog("{0}: RemoveChildFromLinkset: Removing constraint to {1}", LogHeader, child.LocalID); // DetailLog("{0},RemoveChildFromLinkset,taint,child={1}", m_linksetRoot.LocalID, child.LocalID); PhysicallyUnlinkAChildFromRoot(rootx, childx); @@ -326,7 +324,6 @@ public class BSLinkset // create a constraint that allows no freedom of movement between the two objects // http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818 - // DebugLog("{0}: CreateLinkset: Adding a constraint between root prim {1} and child prim {2}", LogHeader, LocalID, childPrim.LocalID); DetailLog("{0},PhysicallyLinkAChildToRoot,taint,root={1},child={2},rLoc={3},cLoc={4},midLoc={5}", rootPrim.LocalID, rootPrim.LocalID, childPrim.LocalID, rootPrim.Position, childPrim.Position, midPoint); BS6DofConstraint constrain = new BS6DofConstraint( @@ -350,7 +347,6 @@ public class BSLinkset // create a constraint that allows no freedom of movement between the two objects // http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818 - // DebugLog("{0}: CreateLinkset: Adding a constraint between root prim {1} and child prim {2}", LogHeader, LocalID, childPrim.LocalID); DetailLog("{0},PhysicallyLinkAChildToRoot,taint,root={1},child={2}", rootPrim.LocalID, rootPrim.LocalID, childPrim.LocalID); BS6DofConstraint constrain = new BS6DofConstraint( PhysicsScene.World, rootPrim.Body, childPrim.Body, @@ -389,8 +385,6 @@ public class BSLinkset // Called at taint time! private void PhysicallyUnlinkAChildFromRoot(BSPrim rootPrim, BSPrim childPrim) { - // DebugLog("{0}: PhysicallyUnlinkAChildFromRoot: RemoveConstraint between root prim {1} and child prim {2}", - // LogHeader, rootPrim.LocalID, childPrim.LocalID); DetailLog("{0},PhysicallyUnlinkAChildFromRoot,taint,root={1},child={2}", rootPrim.LocalID, rootPrim.LocalID, childPrim.LocalID); // Find the constraint for this link and get rid of it from the overall collection and from my list @@ -404,20 +398,12 @@ public class BSLinkset // Called at taint time! private void PhysicallyUnlinkAllChildrenFromRoot(BSPrim rootPrim) { - // DebugLog("{0}: PhysicallyUnlinkAllChildren:", LogHeader); DetailLog("{0},PhysicallyUnlinkAllChildren,taint", rootPrim.LocalID); m_physicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.Body); } // Invoke the detailed logger and output something if it's enabled. - private void DebugLog(string msg, params Object[] args) - { - if (m_physicsScene.ShouldDebugLog) - m_physicsScene.Logger.DebugFormat(msg, args); - } - - // Invoke the detailed logger and output something if it's enabled. private void DetailLog(string msg, params Object[] args) { m_physicsScene.PhysicsLogging.Write(msg, args); diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index b918f84..48cd89b 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs @@ -42,8 +42,6 @@ public sealed class BSPrim : PhysicsActor private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private static readonly string LogHeader = "[BULLETS PRIM]"; - private void DebugLog(string mm, params Object[] xx) { if (_scene.ShouldDebugLog) m_log.DebugFormat(mm, xx); } - private IMesh _mesh; private PrimitiveBaseShape _pbs; private ShapeData.PhysicsShapeType _shapeType; @@ -232,7 +230,6 @@ public sealed class BSPrim : PhysicsActor BSPrim parent = obj as BSPrim; if (parent != null) { - DebugLog("{0}: link {1}/{2} to {3}", LogHeader, _avName, _localID, parent.LocalID); BSPrim parentBefore = _linkset.LinksetRoot; int childrenBefore = _linkset.NumberOfChildren; @@ -248,8 +245,6 @@ public sealed class BSPrim : PhysicsActor public override void delink() { // TODO: decide if this parent checking needs to happen at taint time // Race condition here: if link() and delink() in same simulation tick, the delink will not happen - DebugLog("{0}: delink {1}/{2}. Parent={3}", LogHeader, _avName, _localID, - _linkset.LinksetRoot._avName+"/"+_linkset.LinksetRoot.LocalID.ToString()); BSPrim parentBefore = _linkset.LinksetRoot; int childrenBefore = _linkset.NumberOfChildren; @@ -1042,7 +1037,14 @@ public sealed class BSPrim : PhysicsActor // No locking here because this is done when we know physics is not simulating private void CreateGeomMesh() { - float lod = _pbs.SculptEntry ? _scene.SculptLOD : _scene.MeshLOD; + // level of detail based on size and type of the object + float lod = _scene.MeshLOD; + if (_pbs.SculptEntry) + lod = _scene.SculptLOD; + float maxAxis = Math.Max(_size.X, Math.Max(_size.Y, _size.Z)); + if (maxAxis > _scene.MeshMegaPrimThreshold) + lod = _scene.MeshMegaPrimLOD; + ulong newMeshKey = (ulong)_pbs.GetMeshKey(_size, lod); // m_log.DebugFormat("{0}: CreateGeomMesh: lID={1}, oldKey={2}, newKey={3}", LogHeader, _localID, _meshKey, newMeshKey); diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs index 0a0e27e..d901ff0 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs @@ -73,8 +73,6 @@ public class BSScene : PhysicsScene, IPhysicsParameters private static readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); private static readonly string LogHeader = "[BULLETS SCENE]"; - public void DebugLog(string mm, params Object[] xx) { if (ShouldDebugLog) m_log.DebugFormat(mm, xx); } - public string BulletSimVersion = "?"; private Dictionary m_avatars = new Dictionary(); @@ -101,16 +99,11 @@ public class BSScene : PhysicsScene, IPhysicsParameters private int m_detailedStatsStep = 0; public IMesher mesher; - private float m_meshLOD; - public float MeshLOD - { - get { return m_meshLOD; } - } - private float m_sculptLOD; - public float SculptLOD - { - get { return m_sculptLOD; } - } + // Level of Detail values kept as float because that's what the Meshmerizer wants + public float MeshLOD { get; private set; } + public float MeshMegaPrimLOD { get; private set; } + public float MeshMegaPrimThreshold { get; private set; } + public float SculptLOD { get; private set; } private BulletSim m_worldSim; public BulletSim World @@ -185,8 +178,9 @@ public class BSScene : PhysicsScene, IPhysicsParameters ConfigurationParameters[] m_params; GCHandle m_paramsHandle; - public bool ShouldDebugLog { get; private set; } - + // Handle to the callback used by the unmanaged code to call into the managed code. + // Used for debug logging. + // Need to store the handle in a persistant variable so it won't be freed. private BulletSimAPI.DebugLogCallback m_DebugLogCallbackHandle; // Sometimes you just have to log everything. @@ -905,16 +899,26 @@ public class BSScene : PhysicsScene, IPhysicsParameters (s) => { return s.NumericBool(s._forceSimplePrimMeshing); }, (s,p,l,v) => { s._forceSimplePrimMeshing = s.BoolNumeric(v); } ), - new ParameterDefn("MeshLOD", "Level of detail to render meshes (32, 16, 8 or 4. 32=most detailed)", + new ParameterDefn("MeshLevelOfDetail", "Level of detail to render meshes (32, 16, 8 or 4. 32=most detailed)", 8f, - (s,cf,p,v) => { s.m_meshLOD = cf.GetInt(p, (int)v); }, - (s) => { return (float)s.m_meshLOD; }, - (s,p,l,v) => { s.m_meshLOD = (int)v; } ), - new ParameterDefn("SculptLOD", "Level of detail to render sculpties (32, 16, 8 or 4. 32=most detailed)", + (s,cf,p,v) => { s.MeshLOD = (float)cf.GetInt(p, (int)v); }, + (s) => { return s.MeshLOD; }, + (s,p,l,v) => { s.MeshLOD = v; } ), + new ParameterDefn("MeshLevelOfDetailMegaPrim", "Level of detail to render meshes larger than threshold meters", + 16f, + (s,cf,p,v) => { s.MeshMegaPrimLOD = (float)cf.GetInt(p, (int)v); }, + (s) => { return s.MeshMegaPrimLOD; }, + (s,p,l,v) => { s.MeshMegaPrimLOD = v; } ), + new ParameterDefn("MeshLevelOfDetailMegaPrimThreshold", "Size (in meters) of a mesh before using MeshMegaPrimLOD", + 10f, + (s,cf,p,v) => { s.MeshMegaPrimThreshold = (float)cf.GetInt(p, (int)v); }, + (s) => { return s.MeshMegaPrimThreshold; }, + (s,p,l,v) => { s.MeshMegaPrimThreshold = v; } ), + new ParameterDefn("SculptLevelOfDetail", "Level of detail to render sculpties (32, 16, 8 or 4. 32=most detailed)", 32f, - (s,cf,p,v) => { s.m_sculptLOD = cf.GetInt(p, (int)v); }, - (s) => { return (float)s.m_sculptLOD; }, - (s,p,l,v) => { s.m_sculptLOD = (int)v; } ), + (s,cf,p,v) => { s.SculptLOD = (float)cf.GetInt(p, (int)v); }, + (s) => { return s.SculptLOD; }, + (s,p,l,v) => { s.SculptLOD = v; } ), new ParameterDefn("MaxSubStep", "In simulation step, maximum number of substeps", 10f, @@ -1145,12 +1149,6 @@ public class BSScene : PhysicsScene, IPhysicsParameters (s,cf,p,v) => { s.m_detailedStatsStep = cf.GetInt(p, (int)v); }, (s) => { return (float)s.m_detailedStatsStep; }, (s,p,l,v) => { s.m_detailedStatsStep = (int)v; } ), - new ParameterDefn("ShouldDebugLog", "Enables detailed DEBUG log statements", - ConfigurationParameters.numericFalse, - (s,cf,p,v) => { s.ShouldDebugLog = cf.GetBoolean(p, s.BoolNumeric(v)); }, - (s) => { return s.NumericBool(s.ShouldDebugLog); }, - (s,p,l,v) => { s.ShouldDebugLog = s.BoolNumeric(v); } ), - }; // Convert a boolean to our numeric true and false values -- cgit v1.1 From 5c192b9bab4eb3e921f54a94125215c3683f2eca Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Fri, 17 Aug 2012 13:26:18 -0700 Subject: Modify order of code so SOP doesn't set the physics actor flying property multiple times every time Update is called. This eliminates zillions of settings which is better for BulletSim. The should be no functionality change. --- OpenSim/Region/Framework/Scenes/ScenePresence.cs | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index 548dfd3..98afb75 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -1385,17 +1385,22 @@ namespace OpenSim.Region.Framework.Scenes bool DCFlagKeyPressed = false; Vector3 agent_control_v3 = Vector3.Zero; - bool oldflying = Flying; + bool newFlying = actor.Flying; if (ForceFly) - actor.Flying = true; + newFlying = true; else if (FlyDisabled) - actor.Flying = false; + newFlying = false; else - actor.Flying = ((flags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0); - - if (actor.Flying != oldflying) - update_movementflag = true; + newFlying = ((flags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0); + + if (actor.Flying != newFlying) + { + // Note: ScenePresence.Flying is actually fetched from the physical actor + // so setting PhysActor.Flying here also sets the ScenePresence's value. + actor.Flying = newFlying; + update_movementflag = true; + } if (ParentID == 0) { -- cgit v1.1 From 03d76e94034bbaa82d1872284d1fadbaa263411d Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Fri, 17 Aug 2012 13:30:46 -0700 Subject: BulletSim: restore most of the Detail logging statements. Will have no effect on non-logging running. Capture region name that is passed to the physics engine and use it for detail logging file name prefix. Fix problem with avatars dropping when flying across region boundries. --- .../Region/Physics/BulletSPlugin/BSCharacter.cs | 21 +++++----- OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs | 8 ++-- OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | 46 +++++++++++----------- OpenSim/Region/Physics/BulletSPlugin/BSScene.cs | 16 ++++++-- 4 files changed, 51 insertions(+), 40 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs index e2f7af9..1b23a36 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs @@ -124,10 +124,14 @@ public class BSCharacter : PhysicsActor // do actual create at taint time _scene.TaintedObject("BSCharacter.create", delegate() { + DetailLog("{0},BSCharacter.create", _localID); BulletSimAPI.CreateObject(parent_scene.WorldID, shapeData); + // Set the buoyancy for flying. This will be refactored when all the settings happen in C# + BulletSimAPI.SetObjectBuoyancy(_scene.WorldID, LocalID, _buoyancy); + m_body = new BulletBody(LocalID, BulletSimAPI.GetBodyHandle2(_scene.World.Ptr, LocalID)); - // avatars get all collisions no matter what + // avatars get all collisions no matter what (makes walking on ground and such work) BulletSimAPI.AddToCollisionFlags2(Body.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); }); @@ -137,7 +141,7 @@ public class BSCharacter : PhysicsActor // called when this character is being destroyed and the resources should be released public void Destroy() { - // DetailLog("{0},BSCharacter.Destroy", LocalID); + DetailLog("{0},BSCharacter.Destroy", LocalID); _scene.TaintedObject("BSCharacter.destroy", delegate() { BulletSimAPI.DestroyObject(_scene.WorldID, _localID); @@ -319,14 +323,13 @@ public class BSCharacter : PhysicsActor public override bool Flying { get { return _flying; } set { - if (_flying != value) - { - _flying = value; - // simulate flying by changing the effect of gravity - this.Buoyancy = ComputeBuoyancyFromFlying(_flying); - } + _flying = value; + // simulate flying by changing the effect of gravity + this.Buoyancy = ComputeBuoyancyFromFlying(_flying); } } + // Flying is implimented by changing the avatar's buoyancy. + // Would this be done better with a vehicle type? private float ComputeBuoyancyFromFlying(bool ifFlying) { return ifFlying ? 1f : 0f; } @@ -488,11 +491,9 @@ public class BSCharacter : PhysicsActor // Avatars don't report their changes the usual way. Changes are checked for in the heartbeat loop. // base.RequestPhysicsterseUpdate(); - /* DetailLog("{0},BSCharacter.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5}", LocalID, entprop.Position, entprop.Rotation, entprop.Velocity, entprop.Acceleration, entprop.RotationalVelocity); - */ } // Called by the scene when a collision with this object is reported diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs index a075995..9e3f0db 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs @@ -265,7 +265,7 @@ public class BSLinkset BSPrim childx = child; m_physicsScene.TaintedObject("AddChildToLinkset", delegate() { - // DetailLog("{0},AddChildToLinkset,taint,child={1}", m_linksetRoot.LocalID, child.LocalID); + DetailLog("{0},AddChildToLinkset,taint,child={1}", m_linksetRoot.LocalID, child.LocalID); PhysicallyLinkAChildToRoot(rootx, childx); // build the physical binding between me and the child }); } @@ -293,7 +293,7 @@ public class BSLinkset BSPrim childx = child; m_physicsScene.TaintedObject("RemoveChildFromLinkset", delegate() { - // DetailLog("{0},RemoveChildFromLinkset,taint,child={1}", m_linksetRoot.LocalID, child.LocalID); + DetailLog("{0},RemoveChildFromLinkset,taint,child={1}", m_linksetRoot.LocalID, child.LocalID); PhysicallyUnlinkAChildFromRoot(rootx, childx); }); @@ -332,10 +332,10 @@ public class BSLinkset true, true ); - /* NOTE: attempt to build constraint with full frame computation, etc. + /* NOTE: below is an attempt to build constraint with full frame computation, etc. * Using the midpoint is easier since it lets the Bullet code use the transforms * of the objects. - * Code left here as an example. + * Code left as a warning to future programmers. // ================================================================================== // relative position normalized to the root prim OMV.Quaternion invThisOrientation = OMV.Quaternion.Inverse(rootPrim.Orientation); diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index 48cd89b..a6bc8e2 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs @@ -191,7 +191,7 @@ public sealed class BSPrim : PhysicsActor { _mass = CalculateMass(); // changing size changes the mass BulletSimAPI.SetObjectScaleMass(_scene.WorldID, _localID, _scale, (IsPhysical ? _mass : 0f), IsPhysical); - // DetailLog("{0}: BSPrim.setSize: size={1}, mass={2}, physical={3}", LocalID, _size, _mass, IsPhysical); + DetailLog("{0}: BSPrim.setSize: size={1}, mass={2}, physical={3}", LocalID, _size, _mass, IsPhysical); RecreateGeomAndObject(); }); } @@ -275,7 +275,7 @@ public sealed class BSPrim : PhysicsActor public override void LockAngularMotion(OMV.Vector3 axis) { - // DetailLog("{0},BSPrim.LockAngularMotion,call,axis={1}", LocalID, axis); + DetailLog("{0},BSPrim.LockAngularMotion,call,axis={1}", LocalID, axis); return; } @@ -294,7 +294,7 @@ public sealed class BSPrim : PhysicsActor // TODO: what does it mean to set the position of a child prim?? Rebuild the constraint? _scene.TaintedObject("BSPrim.setPosition", delegate() { - // DetailLog("{0},BSPrim.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation); + DetailLog("{0},BSPrim.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation); BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation); }); } @@ -331,7 +331,7 @@ public sealed class BSPrim : PhysicsActor _force = value; _scene.TaintedObject("BSPrim.setForce", delegate() { - // DetailLog("{0},BSPrim.setForce,taint,force={1}", LocalID, _force); + DetailLog("{0},BSPrim.setForce,taint,force={1}", LocalID, _force); // BulletSimAPI.SetObjectForce(_scene.WorldID, _localID, _force); BulletSimAPI.SetObjectForce2(Body.Ptr, _force); }); @@ -409,7 +409,7 @@ public sealed class BSPrim : PhysicsActor _velocity = value; _scene.TaintedObject("BSPrim.setVelocity", delegate() { - // DetailLog("{0},BSPrim.SetVelocity,taint,vel={1}", LocalID, _velocity); + DetailLog("{0},BSPrim.SetVelocity,taint,vel={1}", LocalID, _velocity); BulletSimAPI.SetObjectVelocity(_scene.WorldID, LocalID, _velocity); }); } @@ -417,7 +417,7 @@ public sealed class BSPrim : PhysicsActor public override OMV.Vector3 Torque { get { return _torque; } set { _torque = value; - // DetailLog("{0},BSPrim.SetTorque,call,torque={1}", LocalID, _torque); + DetailLog("{0},BSPrim.SetTorque,call,torque={1}", LocalID, _torque); } } public override float CollisionScore { @@ -444,7 +444,7 @@ public sealed class BSPrim : PhysicsActor _scene.TaintedObject("BSPrim.setOrientation", delegate() { // _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID); - // DetailLog("{0},BSPrim.setOrientation,taint,pos={1},orient={2}", LocalID, _position, _orientation); + DetailLog("{0},BSPrim.setOrientation,taint,pos={1},orient={2}", LocalID, _position, _orientation); BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation); }); } @@ -496,13 +496,15 @@ public sealed class BSPrim : PhysicsActor _linkset.Refresh(this); CollisionFlags cf = BulletSimAPI.GetCollisionFlags2(Body.Ptr); - // DetailLog("{0},BSPrim.SetObjectDynamic,taint,static={1},solid={2},mass={3}, cf={4}", LocalID, IsStatic, IsSolid, mass, cf); + DetailLog("{0},BSPrim.SetObjectDynamic,taint,static={1},solid={2},mass={3}, cf={4}", LocalID, IsStatic, IsSolid, mass, cf); } // prims don't fly public override bool Flying { get { return _flying; } - set { _flying = value; } + set { + _flying = value; + } } public override bool SetAlwaysRun { get { return _setAlwaysRun; } @@ -553,7 +555,7 @@ public sealed class BSPrim : PhysicsActor // m_log.DebugFormat("{0}: RotationalVelocity={1}", LogHeader, _rotationalVelocity); _scene.TaintedObject("BSPrim.setRotationalVelocity", delegate() { - // DetailLog("{0},BSPrim.SetRotationalVel,taint,rotvel={1}", LocalID, _rotationalVelocity); + DetailLog("{0},BSPrim.SetRotationalVel,taint,rotvel={1}", LocalID, _rotationalVelocity); BulletSimAPI.SetObjectAngularVelocity(_scene.WorldID, LocalID, _rotationalVelocity); }); } @@ -570,7 +572,7 @@ public sealed class BSPrim : PhysicsActor _buoyancy = value; _scene.TaintedObject("BSPrim.setBuoyancy", delegate() { - // DetailLog("{0},BSPrim.SetBuoyancy,taint,buoy={1}", LocalID, _buoyancy); + DetailLog("{0},BSPrim.SetBuoyancy,taint,buoy={1}", LocalID, _buoyancy); BulletSimAPI.SetObjectBuoyancy(_scene.WorldID, _localID, _buoyancy); }); } @@ -633,17 +635,17 @@ public sealed class BSPrim : PhysicsActor } m_accumulatedForces.Clear(); } - // DetailLog("{0},BSPrim.AddObjectForce,taint,force={1}", LocalID, _force); + DetailLog("{0},BSPrim.AddObjectForce,taint,force={1}", LocalID, _force); BulletSimAPI.AddObjectForce2(Body.Ptr, fSum); }); } public override void AddAngularForce(OMV.Vector3 force, bool pushforce) { - // DetailLog("{0},BSPrim.AddAngularForce,call,angForce={1},push={2}", LocalID, force, pushforce); + DetailLog("{0},BSPrim.AddAngularForce,call,angForce={1},push={2}", LocalID, force, pushforce); // m_log.DebugFormat("{0}: AddAngularForce. f={1}, push={2}", LogHeader, force, pushforce); } public override void SetMomentum(OMV.Vector3 momentum) { - // DetailLog("{0},BSPrim.SetMomentum,call,mom={1}", LocalID, momentum); + DetailLog("{0},BSPrim.SetMomentum,call,mom={1}", LocalID, momentum); } public override void SubscribeEvents(int ms) { _subscribedEventsMs = ms; @@ -987,7 +989,7 @@ public sealed class BSPrim : PhysicsActor // m_log.DebugFormat("{0}: CreateGeom: Defaulting to sphere of size {1}", LogHeader, _size); if (forceRebuild || (_shapeType != ShapeData.PhysicsShapeType.SHAPE_SPHERE)) { - // DetailLog("{0},BSPrim.CreateGeom,sphere (force={1}", LocalID, forceRebuild); + DetailLog("{0},BSPrim.CreateGeom,sphere (force={1}", LocalID, forceRebuild); _shapeType = ShapeData.PhysicsShapeType.SHAPE_SPHERE; // Bullet native objects are scaled by the Bullet engine so pass the size in _scale = _size; @@ -1001,7 +1003,7 @@ public sealed class BSPrim : PhysicsActor // m_log.DebugFormat("{0}: CreateGeom: Defaulting to box. lid={1}, type={2}, size={3}", LogHeader, LocalID, _shapeType, _size); if (forceRebuild || (_shapeType != ShapeData.PhysicsShapeType.SHAPE_BOX)) { - // DetailLog("{0},BSPrim.CreateGeom,box (force={1})", LocalID, forceRebuild); + DetailLog("{0},BSPrim.CreateGeom,box (force={1})", LocalID, forceRebuild); _shapeType = ShapeData.PhysicsShapeType.SHAPE_BOX; _scale = _size; // TODO: do we need to check for and destroy a mesh or hull that might have been left from before? @@ -1051,12 +1053,12 @@ public sealed class BSPrim : PhysicsActor // if this new shape is the same as last time, don't recreate the mesh if (_meshKey == newMeshKey) return; - // DetailLog("{0},BSPrim.CreateGeomMesh,create,key={1}", LocalID, newMeshKey); + DetailLog("{0},BSPrim.CreateGeomMesh,create,key={1}", LocalID, newMeshKey); // Since we're recreating new, get rid of any previously generated shape if (_meshKey != 0) { // m_log.DebugFormat("{0}: CreateGeom: deleting old mesh. lID={1}, Key={2}", LogHeader, _localID, _meshKey); - // DetailLog("{0},BSPrim.CreateGeomMesh,deleteOld,key={1}", LocalID, _meshKey); + DetailLog("{0},BSPrim.CreateGeomMesh,deleteOld,key={1}", LocalID, _meshKey); BulletSimAPI.DestroyMesh(_scene.WorldID, _meshKey); _mesh = null; _meshKey = 0; @@ -1086,7 +1088,7 @@ public sealed class BSPrim : PhysicsActor _shapeType = ShapeData.PhysicsShapeType.SHAPE_MESH; // meshes are already scaled by the meshmerizer _scale = new OMV.Vector3(1f, 1f, 1f); - // DetailLog("{0},BSPrim.CreateGeomMesh,done", LocalID); + DetailLog("{0},BSPrim.CreateGeomMesh,done", LocalID); return; } @@ -1100,13 +1102,13 @@ public sealed class BSPrim : PhysicsActor // if the hull hasn't changed, don't rebuild it if (newHullKey == _hullKey) return; - // DetailLog("{0},BSPrim.CreateGeomHull,create,oldKey={1},newKey={2}", LocalID, _hullKey, newHullKey); + DetailLog("{0},BSPrim.CreateGeomHull,create,oldKey={1},newKey={2}", LocalID, _hullKey, newHullKey); // Since we're recreating new, get rid of any previously generated shape if (_hullKey != 0) { // m_log.DebugFormat("{0}: CreateGeom: deleting old hull. Key={1}", LogHeader, _hullKey); - // DetailLog("{0},BSPrim.CreateGeomHull,deleteOldHull,key={1}", LocalID, _hullKey); + DetailLog("{0},BSPrim.CreateGeomHull,deleteOldHull,key={1}", LocalID, _hullKey); BulletSimAPI.DestroyHull(_scene.WorldID, _hullKey); _hullKey = 0; } @@ -1200,7 +1202,7 @@ public sealed class BSPrim : PhysicsActor _shapeType = ShapeData.PhysicsShapeType.SHAPE_HULL; // meshes are already scaled by the meshmerizer _scale = new OMV.Vector3(1f, 1f, 1f); - // DetailLog("{0},BSPrim.CreateGeomHull,done", LocalID); + DetailLog("{0},BSPrim.CreateGeomHull,done", LocalID); return; } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs index d901ff0..56924aa 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs @@ -73,6 +73,9 @@ public class BSScene : PhysicsScene, IPhysicsParameters private static readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); private static readonly string LogHeader = "[BULLETS SCENE]"; + // The name of the region we're working for. + public string RegionName { get; private set; } + public string BulletSimVersion = "?"; private Dictionary m_avatars = new Dictionary(); @@ -196,6 +199,8 @@ public class BSScene : PhysicsScene, IPhysicsParameters public BSScene(string identifier) { m_initialized = false; + // we are passed the name of the region we're working for. + RegionName = identifier; } public override void Initialise(IMesher meshmerizer, IConfigSource config) @@ -281,10 +286,13 @@ public class BSScene : PhysicsScene, IPhysicsParameters // Very detailed logging for physics debugging m_physicsLoggingEnabled = pConfig.GetBoolean("PhysicsLoggingEnabled", false); m_physicsLoggingDir = pConfig.GetString("PhysicsLoggingDir", "."); - m_physicsLoggingPrefix = pConfig.GetString("PhysicsLoggingPrefix", "physics-"); + m_physicsLoggingPrefix = pConfig.GetString("PhysicsLoggingPrefix", "physics-%REGIONNAME%-"); m_physicsLoggingFileMinutes = pConfig.GetInt("PhysicsLoggingFileMinutes", 5); // Very detailed logging for vehicle debugging m_vehicleLoggingEnabled = pConfig.GetBoolean("VehicleLoggingEnabled", false); + + // Do any replacements in the parameters + m_physicsLoggingPrefix = m_physicsLoggingPrefix.Replace("%REGIONNAME%", RegionName); } } } @@ -362,7 +370,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters BSPrim bsprim = prim as BSPrim; if (bsprim != null) { - // DetailLog("{0},RemovePrim,call", bsprim.LocalID); + DetailLog("{0},RemovePrim,call", bsprim.LocalID); // m_log.DebugFormat("{0}: RemovePrim. id={1}/{2}", LogHeader, bsprim.Name, bsprim.LocalID); try { @@ -388,7 +396,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters if (!m_initialized) return null; - // DetailLog("{0},AddPrimShape,call", localID); + DetailLog("{0},AddPrimShape,call", localID); BSPrim prim = new BSPrim(localID, primName, this, position, size, rotation, pbs, isPhysical); lock (m_prims) m_prims.Add(localID, prim); @@ -534,7 +542,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters else if (m_avatars.ContainsKey(collidingWith)) type = ActorTypes.Agent; - DetailLog("{0},BSScene.SendCollision,collide,id={1},with={2}", DetailLogZero, localID, collidingWith); + // DetailLog("{0},BSScene.SendCollision,collide,id={1},with={2}", DetailLogZero, localID, collidingWith); BSPrim prim; if (m_prims.TryGetValue(localID, out prim)) { -- cgit v1.1 From 0860a0d856ee667bf20db074b778f2518c4d061c Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 17 Aug 2012 22:30:01 +0100 Subject: minor: Make xengine debug message on script load a scripting loading message instead. This is more useful if compilation fails due to an uncatchable exception since we know what was being compiled. --- OpenSim/Region/ScriptEngine/XEngine/XEngine.cs | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs index 2dba029..1571fb4 100644 --- a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs +++ b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs @@ -982,10 +982,12 @@ namespace OpenSim.Region.ScriptEngine.XEngine return false; } - UUID assetID = item.AssetID; + m_log.DebugFormat( + "[XEngine] Loading script {0}.{1}, item UUID {2}, prim UUID {3} @ {4}.{5}", + part.ParentGroup.RootPart.Name, item.Name, itemID, part.UUID, + part.ParentGroup.RootPart.AbsolutePosition, part.ParentGroup.Scene.RegionInfo.RegionName); - //m_log.DebugFormat("[XEngine] Compiling script {0} ({1} on object {2})", - // item.Name, itemID.ToString(), part.ParentGroup.RootPart.Name); + UUID assetID = item.AssetID; ScenePresence presence = m_Scene.GetScenePresence(item.OwnerID); @@ -1164,10 +1166,10 @@ namespace OpenSim.Region.ScriptEngine.XEngine stateSource, m_MaxScriptQueue); // if (DebugLevel >= 1) - m_log.DebugFormat( - "[XEngine] Loaded script {0}.{1}, item UUID {2}, prim UUID {3} @ {4}.{5}", - part.ParentGroup.RootPart.Name, item.Name, itemID, part.UUID, - part.ParentGroup.RootPart.AbsolutePosition, part.ParentGroup.Scene.RegionInfo.RegionName); +// m_log.DebugFormat( +// "[XEngine] Loaded script {0}.{1}, item UUID {2}, prim UUID {3} @ {4}.{5}", +// part.ParentGroup.RootPart.Name, item.Name, itemID, part.UUID, +// part.ParentGroup.RootPart.AbsolutePosition, part.ParentGroup.Scene.RegionInfo.RegionName); if (presence != null) { -- cgit v1.1 From 7243d4f84248092eb5fe4ebe3673501bc84ce250 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Fri, 17 Aug 2012 14:45:18 -0700 Subject: BulletSim: Properly regenerate hulls when objects made physical. This fixes the problem of non-base shapes (cubes and spheres) falling through the terrain. --- OpenSim/Region/Framework/Scenes/ScenePresence.cs | 16 +++++------ OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | 34 +++++++++++++++++------- 2 files changed, 33 insertions(+), 17 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index 98afb75..65d526f 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -1392,14 +1392,14 @@ namespace OpenSim.Region.Framework.Scenes else if (FlyDisabled) newFlying = false; else - newFlying = ((flags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0); - - if (actor.Flying != newFlying) - { - // Note: ScenePresence.Flying is actually fetched from the physical actor - // so setting PhysActor.Flying here also sets the ScenePresence's value. - actor.Flying = newFlying; - update_movementflag = true; + newFlying = ((flags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0); + + if (actor.Flying != newFlying) + { + // Note: ScenePresence.Flying is actually fetched from the physical actor + // so setting PhysActor.Flying here also sets the ScenePresence's value. + actor.Flying = newFlying; + update_movementflag = true; } if (ParentID == 0) diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index a6bc8e2..d3f1e9c 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs @@ -481,11 +481,8 @@ public sealed class BSPrim : PhysicsActor // No locking here because only called when it is safe private void SetObjectDynamic() { - // RA: remove this for the moment. - // The problem is that dynamic objects are hulls so if we are becoming physical - // the shape has to be checked and possibly built. - // Maybe a VerifyCorrectPhysicalShape() routine? - // RecreateGeomAndObject(); + // If it's becoming dynamic, it will need hullness + VerifyCorrectPhysicalShape(); // Bullet wants static objects to have a mass of zero float mass = IsStatic ? 0f : _mass; @@ -1214,6 +1211,27 @@ public sealed class BSPrim : PhysicsActor return; } + private void VerifyCorrectPhysicalShape() + { + if (IsStatic) + { + // if static, we don't need a hull so, if there is one, rebuild without it + if (_hullKey != 0) + { + RecreateGeomAndObject(); + } + } + else + { + // if not static, it will need a hull to efficiently collide with things + if (_hullKey == 0) + { + RecreateGeomAndObject(); + } + + } + } + // Create an object in Bullet if it has not already been created // No locking here because this is done when the physics engine is not simulating // Returns 'true' if an object was actually created. @@ -1338,10 +1356,8 @@ public sealed class BSPrim : PhysicsActor _acceleration = entprop.Acceleration; _rotationalVelocity = entprop.RotationalVelocity; - // m_log.DebugFormat("{0}: RequestTerseUpdate. id={1}, ch={2}, pos={3}, rot={4}, vel={5}, acc={6}, rvel={7}", - // LogHeader, LocalID, changed, _position, _orientation, _velocity, _acceleration, _rotationalVelocity); - // DetailLog("{0},BSPrim.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5}", - // LocalID, _position, _orientation, _velocity, _acceleration, _rotationalVelocity); + DetailLog("{0},BSPrim.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5}", + LocalID, _position, _orientation, _velocity, _acceleration, _rotationalVelocity); base.RequestPhysicsterseUpdate(); } -- cgit v1.1 From 74f5253a366cefa5222a813f4ed349db93c08acc Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Thu, 16 Aug 2012 15:32:20 +0100 Subject: attempt to handle InvalidCastException in a manner similar to Second Life --- .../ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 4 ++++ OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs | 15 +++++++++++++-- 2 files changed, 17 insertions(+), 2 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 b7b5e8e..255fc8e 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -7674,6 +7674,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } } } + catch (InvalidCastException e) + { + ShoutError(e.Message); + } finally { if (positionChanged) diff --git a/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs b/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs index d848b2a..562433d 100644 --- a/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs +++ b/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs @@ -560,12 +560,23 @@ namespace OpenSim.Region.ScriptEngine.Shared else if (m_data[itemIndex] is LSL_Types.LSLString) return new LSLInteger(m_data[itemIndex].ToString()); else - throw new InvalidCastException(); + throw new InvalidCastException(string.Format( + "{0} expected but {1} given", + typeof(LSL_Types.LSLInteger).Name, + m_data[itemIndex] != null ? + m_data[itemIndex].GetType().Name : "null")); } public LSL_Types.Vector3 GetVector3Item(int itemIndex) { - return (LSL_Types.Vector3)m_data[itemIndex]; + if(m_data[itemIndex] is LSL_Types.Vector3) + return (LSL_Types.Vector3)m_data[itemIndex]; + else + throw new InvalidCastException(string.Format( + "{0} expected but {1} given", + typeof(LSL_Types.Vector3).Name, + m_data[itemIndex] != null ? + m_data[itemIndex].GetType().Name : "null")); } public LSL_Types.Quaternion GetQuaternionItem(int itemIndex) -- cgit v1.1 From 466d684fbe26b4ea24a0003120d7a875fbbca037 Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Wed, 1 Aug 2012 15:18:02 +0100 Subject: implemented --- OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | 50 ++++++++++++++++++++++ .../Shared/Api/Implementation/LSL_Api.cs | 13 ++++++ .../Shared/Api/Runtime/LSL_Constants.cs | 1 + 3 files changed, 64 insertions(+) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index bd6369c..e84ab05 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -4236,6 +4236,56 @@ namespace OpenSim.Region.Framework.Scenes ScheduleFullUpdate(); } + public void UpdateSlice(float begin, float end) + { + if (end < begin) + { + float temp = begin; + begin = end; + end = temp; + } + end = Math.Min(1f, Math.Max(0f, end)); + begin = Math.Min(Math.Min(1f, Math.Max(0f, begin)), end - 0.02f); + if (begin < 0.02f && end < 0.02f) + { + begin = 0f; + end = 0.02f; + } + + ushort uBegin = (ushort)(50000.0 * begin); + ushort uEnd = (ushort)(50000.0 * (1f - end)); + bool updatePossiblyNeeded = false; + if (GetPrimType() == PrimType.SPHERE) + { + if (m_shape.ProfileBegin != uBegin || m_shape.ProfileEnd != uEnd) + { + m_shape.ProfileBegin = uBegin; + m_shape.ProfileEnd = uEnd; + updatePossiblyNeeded = true; + } + } + else if (m_shape.PathBegin != uBegin || m_shape.PathEnd != uEnd) + { + m_shape.PathBegin = uBegin; + m_shape.PathEnd = uEnd; + updatePossiblyNeeded = true; + } + + if (updatePossiblyNeeded && ParentGroup != null) + { + ParentGroup.HasGroupChanged = true; + } + if (updatePossiblyNeeded && PhysActor != null) + { + PhysActor.Shape = m_shape; + ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(PhysActor); + } + if (updatePossiblyNeeded) + { + ScheduleFullUpdate(); + } + } + /// /// If the part is a sculpt/mesh, retrieve the mesh data and reinsert it into the shape so that the physics /// engine can use it. diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 255fc8e..75491da 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -7666,6 +7666,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api LSL_Float gain = rules.GetLSLFloatItem(idx++); TargetOmega(part, axis, (double)spinrate, (double)gain); break; + case (int)ScriptBaseClass.PRIM_SLICE: + if (remain < 1) + return; + LSL_Vector slice = rules.GetVector3Item(idx++); + part.UpdateSlice((float)slice.x, (float)slice.y); + break; case (int)ScriptBaseClass.PRIM_LINK_TARGET: if (remain < 3) // setting to 3 on the basis that parsing any usage of PRIM_LINK_TARGET that has nothing following it is pointless. return null; @@ -8340,6 +8346,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api case (int)ScriptBaseClass.PRIM_POS_LOCAL: res.Add(new LSL_Vector(GetPartLocalPos(part))); break; + case (int)ScriptBaseClass.PRIM_SLICE: + res.Add(new LSL_Vector( + (part.GetPrimType() == PrimType.SPHERE ? part.Shape.ProfileBegin : part.Shape.PathBegin) / 50000.0, + 1 - (part.GetPrimType() == PrimType.SPHERE ? part.Shape.ProfileEnd : part.Shape.PathEnd) / 50000.0, + 0 + )); + break; } } return res; diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs index e1c054d..cad8518 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs @@ -328,6 +328,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase public const int PRIM_OMEGA = 32; public const int PRIM_POS_LOCAL = 33; public const int PRIM_LINK_TARGET = 34; + public const int PRIM_SLICE = 35; public const int PRIM_TEXGEN_DEFAULT = 0; public const int PRIM_TEXGEN_PLANAR = 1; -- cgit v1.1 From 7068fddd2fffe356869171ed67be473f7a701470 Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Thu, 2 Aug 2012 09:28:32 +0100 Subject: fixing bug that get/set the wrong property for prim types other than sphere & box --- OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | 3 ++- OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 6 ++++-- 2 files changed, 6 insertions(+), 3 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index e84ab05..53b4f7e 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -4255,7 +4255,8 @@ namespace OpenSim.Region.Framework.Scenes ushort uBegin = (ushort)(50000.0 * begin); ushort uEnd = (ushort)(50000.0 * (1f - end)); bool updatePossiblyNeeded = false; - if (GetPrimType() == PrimType.SPHERE) + PrimType primType = GetPrimType(); + if (primType == PrimType.SPHERE || primType == PrimType.TORUS || primType == PrimType.TUBE || primType == PrimType.RING) { if (m_shape.ProfileBegin != uBegin || m_shape.ProfileEnd != uEnd) { diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 75491da..31d1660 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -8347,9 +8347,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api res.Add(new LSL_Vector(GetPartLocalPos(part))); break; case (int)ScriptBaseClass.PRIM_SLICE: + PrimType prim_type = part.GetPrimType(); + bool useProfileBeginEnd = (prim_type == PrimType.SPHERE || prim_type == PrimType.TORUS || prim_type == PrimType.TUBE || prim_type == PrimType.RING); res.Add(new LSL_Vector( - (part.GetPrimType() == PrimType.SPHERE ? part.Shape.ProfileBegin : part.Shape.PathBegin) / 50000.0, - 1 - (part.GetPrimType() == PrimType.SPHERE ? part.Shape.ProfileEnd : part.Shape.PathEnd) / 50000.0, + (useProfileBeginEnd ? part.Shape.ProfileBegin : part.Shape.PathBegin) / 50000.0, + 1 - (useProfileBeginEnd ? part.Shape.ProfileEnd : part.Shape.PathEnd) / 50000.0, 0 )); break; -- cgit v1.1 From 28d0aff2e395ae3ef85586cf65bd90395eb5c895 Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Thu, 16 Aug 2012 09:35:27 +0100 Subject: adding null return to fix building --- OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (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 31d1660..6a2b829 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -7668,7 +7668,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api break; case (int)ScriptBaseClass.PRIM_SLICE: if (remain < 1) - return; + return null; LSL_Vector slice = rules.GetVector3Item(idx++); part.UpdateSlice((float)slice.x, (float)slice.y); break; -- cgit v1.1 From 5d7751da891360c665622562f06a15e02fea4922 Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Sat, 18 Aug 2012 01:17:01 +0100 Subject: refactoring for Vector3 operator & constructor tweaks --- .../Shared/Api/Implementation/LSL_Api.cs | 107 +++++++++------------ .../Shared/Api/Implementation/LS_Api.cs | 8 +- .../Shared/Api/Implementation/MOD_Api.cs | 7 +- .../Shared/Api/Implementation/OSSL_Api.cs | 22 ++--- .../Api/Implementation/Plugins/SensorRepeat.cs | 9 +- OpenSim/Region/ScriptEngine/Shared/Helpers.cs | 28 ++---- OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs | 39 ++++++++ .../Region/ScriptEngine/XEngine/EventManager.cs | 20 ++-- OpenSim/Region/ScriptEngine/XEngine/XEngine.cs | 4 +- 9 files changed, 119 insertions(+), 125 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 fceae02..bca9a75 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -1097,9 +1097,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public LSL_Float llGround(LSL_Vector offset) { m_host.AddScriptLPS(1); - Vector3 pos = m_host.GetWorldPosition() + new Vector3((float)offset.x, - (float)offset.y, - (float)offset.z); + Vector3 pos = m_host.GetWorldPosition() + (Vector3)offset; //Get the slope normal. This gives us the equation of the plane tangent to the slope. LSL_Vector vsn = llGroundNormal(offset); @@ -1387,7 +1385,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (face == ScriptBaseClass.ALL_SIDES) face = SceneObjectPart.ALL_SIDES; - m_host.SetFaceColor(new Vector3((float)color.x, (float)color.y, (float)color.z), face); + m_host.SetFaceColor(color, face); } public void SetTexGen(SceneObjectPart part, int face,int style) @@ -1974,7 +1972,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api bool sameParcel = here.GlobalID == there.GlobalID; - if (!sameParcel && !World.Permissions.CanRezObject(m_host.ParentGroup.PrimCount, m_host.ParentGroup.OwnerID, new Vector3((float)pos.x, (float)pos.y, (float)pos.z))) + if (!sameParcel && !World.Permissions.CanRezObject( + m_host.ParentGroup.PrimCount, m_host.ParentGroup.OwnerID, pos)) { return 0; } @@ -2034,13 +2033,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if ((targetPos.z < ground) && disable_underground_movement && m_host.ParentGroup.AttachmentPoint == 0) targetPos.z = ground; SceneObjectGroup parent = part.ParentGroup; - LSL_Vector real_vec = !adjust ? targetPos : SetPosAdjust(currentPos, targetPos); - parent.UpdateGroupPosition(new Vector3((float)real_vec.x, (float)real_vec.y, (float)real_vec.z)); + parent.UpdateGroupPosition(!adjust ? targetPos : + SetPosAdjust(currentPos, targetPos)); } else { - LSL_Vector rel_vec = !adjust ? targetPos : SetPosAdjust(currentPos, targetPos); - part.OffsetPosition = new Vector3((float)rel_vec.x, (float)rel_vec.y, (float)rel_vec.z); + part.OffsetPosition = !adjust ? targetPos : SetPosAdjust( + currentPos, targetPos); SceneObjectGroup parent = part.ParentGroup; parent.HasGroupChanged = true; parent.ScheduleGroupForTerseUpdate(); @@ -2084,7 +2083,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api // m_log.DebugFormat("[LSL API]: Returning {0} in GetPartLocalPos()", pos); - return new LSL_Vector(pos.X, pos.Y, pos.Z); + return new LSL_Vector(pos); } public void llSetRot(LSL_Rotation rot) @@ -2198,7 +2197,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (local != 0) force *= llGetRot(); - m_host.ParentGroup.RootPart.SetForce(new Vector3((float)force.x, (float)force.y, (float)force.z)); + m_host.ParentGroup.RootPart.SetForce(force); } } @@ -2210,10 +2209,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (!m_host.ParentGroup.IsDeleted) { - Vector3 tmpForce = m_host.ParentGroup.RootPart.GetForce(); - force.x = tmpForce.X; - force.y = tmpForce.Y; - force.z = tmpForce.Z; + force = m_host.ParentGroup.RootPart.GetForce(); } return force; @@ -2222,8 +2218,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public LSL_Integer llTarget(LSL_Vector position, double range) { m_host.AddScriptLPS(1); - return m_host.ParentGroup.registerTargetWaypoint( - new Vector3((float)position.x, (float)position.y, (float)position.z), (float)range); + return m_host.ParentGroup.registerTargetWaypoint(position, + (float)range); } public void llTargetRemove(int number) @@ -2248,7 +2244,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public void llMoveToTarget(LSL_Vector target, double tau) { m_host.AddScriptLPS(1); - m_host.MoveToTarget(new Vector3((float)target.x, (float)target.y, (float)target.z), (float)tau); + m_host.MoveToTarget(target, (float)tau); } public void llStopMoveToTarget() @@ -2261,7 +2257,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { m_host.AddScriptLPS(1); //No energy force yet - Vector3 v = new Vector3((float)force.x, (float)force.y, (float)force.z); + Vector3 v = force; if (v.Length() > 20000.0f) { v.Normalize(); @@ -2273,13 +2269,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public void llApplyRotationalImpulse(LSL_Vector force, int local) { m_host.AddScriptLPS(1); - m_host.ApplyAngularImpulse(new Vector3((float)force.x, (float)force.y, (float)force.z), local != 0); + m_host.ApplyAngularImpulse(force, local != 0); } public void llSetTorque(LSL_Vector torque, int local) { m_host.AddScriptLPS(1); - m_host.SetAngularImpulse(new Vector3((float)torque.x, (float)torque.y, (float)torque.z), local != 0); + m_host.SetAngularImpulse(torque, local != 0); } public LSL_Vector llGetTorque() @@ -2830,13 +2826,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api return; } - Vector3 llpos = new Vector3((float)pos.x, (float)pos.y, (float)pos.z); - Vector3 llvel = new Vector3((float)vel.x, (float)vel.y, (float)vel.z); - // need the magnitude later // float velmag = (float)Util.GetMagnitude(llvel); - SceneObjectGroup new_group = World.RezObject(m_host, item, llpos, Rot2Quaternion(rot), llvel, param); + SceneObjectGroup new_group = World.RezObject(m_host, item, pos, Rot2Quaternion(rot), vel, param); // If either of these are null, then there was an unknown error. if (new_group == null) @@ -2857,10 +2850,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api PhysicsActor pa = new_group.RootPart.PhysActor; - if (pa != null && pa.IsPhysical && llvel != Vector3.Zero) + if (pa != null && pa.IsPhysical && (Vector3)vel != Vector3.Zero) { //Recoil. - llApplyImpulse(new LSL_Vector(llvel.X * groupmass, llvel.Y * groupmass, llvel.Z * groupmass), 0); + llApplyImpulse(vel * groupmass, 0); } // Variable script delay? (see (http://wiki.secondlife.com/wiki/LSL_Delay) }); @@ -3381,7 +3374,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api protected void TargetOmega(SceneObjectPart part, LSL_Vector axis, double spinrate, double gain) { - part.UpdateAngularVelocity(new Vector3((float)(axis.x * spinrate), (float)(axis.y * spinrate), (float)(axis.z * spinrate))); + part.UpdateAngularVelocity(axis * spinrate); } public LSL_Integer llGetStartParameter() @@ -3588,7 +3581,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api List parts = GetLinkParts(linknumber); foreach (SceneObjectPart part in parts) - part.SetFaceColor(new Vector3((float)color.x, (float)color.y, (float)color.z), face); + part.SetFaceColor(color, face); } public void llCreateLink(string target, int parent) @@ -4019,8 +4012,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public void llSetText(string text, LSL_Vector color, double alpha) { m_host.AddScriptLPS(1); - Vector3 av3 = Util.Clip(new Vector3((float)color.x, (float)color.y, - (float)color.z), 0.0f, 1.0f); + Vector3 av3 = Util.Clip(color, 0.0f, 1.0f); m_host.SetText(text.Length > 254 ? text.Remove(254) : text, av3, Util.Clip((float)alpha, 0.0f, 1.0f)); //m_host.ParentGroup.HasGroupChanged = true; //m_host.ParentGroup.ScheduleGroupForFullUpdate(); @@ -4217,14 +4209,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api ScriptSleep(5000); } - public void llTeleportAgent(string agent, string destination, LSL_Vector pos, LSL_Vector lookAt) + public void llTeleportAgent(string agent, string destination, LSL_Vector targetPos, LSL_Vector targetLookAt) { m_host.AddScriptLPS(1); UUID agentId = new UUID(); - Vector3 targetPos = new Vector3((float)pos.x, (float)pos.y, (float)pos.z); - Vector3 targetLookAt = new Vector3((float)lookAt.x, (float)lookAt.y, (float)lookAt.z); - if (UUID.TryParse(agent, out agentId)) { ScenePresence presence = World.GetScenePresence(agentId); @@ -4253,15 +4242,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } } - public void llTeleportAgentGlobalCoords(string agent, LSL_Vector global_coords, LSL_Vector pos, LSL_Vector lookAt) + public void llTeleportAgentGlobalCoords(string agent, LSL_Vector global_coords, LSL_Vector targetPos, LSL_Vector targetLookAt) { m_host.AddScriptLPS(1); UUID agentId = new UUID(); ulong regionHandle = Utils.UIntsToLong((uint)global_coords.x, (uint)global_coords.y); - Vector3 targetPos = new Vector3((float)pos.x, (float)pos.y, (float)pos.z); - Vector3 targetLookAt = new Vector3((float)lookAt.x, (float)lookAt.y, (float)lookAt.z); if (UUID.TryParse(agent, out agentId)) { ScenePresence presence = World.GetScenePresence(agentId); @@ -4545,7 +4532,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api distance_attenuation = 1f / normalized_units; } - Vector3 applied_linear_impulse = new Vector3((float)impulse.x, (float)impulse.y, (float)impulse.z); + Vector3 applied_linear_impulse = impulse; { float impulse_length = applied_linear_impulse.Length(); @@ -6044,9 +6031,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api //Plug the x,y coordinates of the slope normal into the equation of the plane to get //the height of that point on the plane. The resulting vector gives the slope. - Vector3 vsl = new Vector3(); - vsl.X = (float)vsn.x; - vsl.Y = (float)vsn.y; + Vector3 vsl = vsn; vsl.Z = (float)(((vsn.x * vsn.x) + (vsn.y * vsn.y)) / (-1 * vsn.z)); vsl.Normalize(); //Normalization might be overkill here @@ -6057,9 +6042,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public LSL_Vector llGroundNormal(LSL_Vector offset) { m_host.AddScriptLPS(1); - Vector3 pos = m_host.GetWorldPosition() + new Vector3((float)offset.x, - (float)offset.y, - (float)offset.z); + Vector3 pos = m_host.GetWorldPosition() + (Vector3)offset; // Clamp to valid position if (pos.X < 0) pos.X = 0; @@ -6512,8 +6495,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (!m_host.ParentGroup.IsDeleted) { - m_host.ParentGroup.RootPart.SetVehicleVectorParam(param, - new Vector3((float)vec.x, (float)vec.y, (float)vec.z)); + m_host.ParentGroup.RootPart.SetVehicleVectorParam(param, vec); } } @@ -6555,7 +6537,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (rot.s == 0 && rot.x == 0 && rot.y == 0 && rot.z == 0) rot.z = 1; // ZERO_ROTATION = 0,0,0,1 - part.SitTargetPosition = new Vector3((float)offset.x, (float)offset.y, (float)offset.z); + part.SitTargetPosition = offset; part.SitTargetOrientation = Rot2Quaternion(rot); part.ParentGroup.HasGroupChanged = true; } @@ -6659,13 +6641,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public void llSetCameraEyeOffset(LSL_Vector offset) { m_host.AddScriptLPS(1); - m_host.SetCameraEyeOffset(new Vector3((float)offset.x, (float)offset.y, (float)offset.z)); + m_host.SetCameraEyeOffset(offset); } public void llSetCameraAtOffset(LSL_Vector offset) { m_host.AddScriptLPS(1); - m_host.SetCameraAtOffset(new Vector3((float)offset.x, (float)offset.y, (float)offset.z)); + m_host.SetCameraAtOffset(offset); } public LSL_String llDumpList2String(LSL_List src, string seperator) @@ -6687,7 +6669,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public LSL_Integer llScriptDanger(LSL_Vector pos) { m_host.AddScriptLPS(1); - bool result = World.ScriptDanger(m_host.LocalId, new Vector3((float)pos.x, (float)pos.y, (float)pos.z)); + bool result = World.ScriptDanger(m_host.LocalId, pos); if (result) { return 1; @@ -7515,7 +7497,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api LSL_Vector color=rules.GetVector3Item(idx++); double alpha=(double)rules.GetLSLFloatItem(idx++); - part.SetFaceColor(new Vector3((float)color.x, (float)color.y, (float)color.z), face); + part.SetFaceColor(color, face); SetAlpha(part, alpha, face); break; @@ -7634,9 +7616,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api string primText = rules.GetLSLStringItem(idx++); LSL_Vector primTextColor = rules.GetVector3Item(idx++); LSL_Float primTextAlpha = rules.GetLSLFloatItem(idx++); - Vector3 av3 = Util.Clip(new Vector3((float)primTextColor.x, - (float)primTextColor.y, - (float)primTextColor.z), 0.0f, 1.0f); + Vector3 av3 = Util.Clip(primTextColor, 0.0f, 1.0f); part.SetText(primText, av3, Util.Clip((float)primTextAlpha, 0.0f, 1.0f)); break; @@ -7691,11 +7671,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (part.ParentGroup.RootPart == part) { SceneObjectGroup parent = part.ParentGroup; - parent.UpdateGroupPosition(new Vector3((float)currentPosition.x, (float)currentPosition.y, (float)currentPosition.z)); + parent.UpdateGroupPosition(currentPosition); } else { - part.OffsetPosition = new Vector3((float)currentPosition.x, (float)currentPosition.y, (float)currentPosition.z); + part.OffsetPosition = currentPosition; SceneObjectGroup parent = part.ParentGroup; parent.HasGroupChanged = true; parent.ScheduleGroupForTerseUpdate(); @@ -7932,8 +7912,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (part != null) { Vector3 halfSize = part.Scale / 2.0f; - LSL_Vector lower = new LSL_Vector(halfSize.X * -1.0f, halfSize.Y * -1.0f, halfSize.Z * -1.0f); - LSL_Vector upper = new LSL_Vector(halfSize.X, halfSize.Y, halfSize.Z); + LSL_Vector lower = (new LSL_Vector(halfSize)) * -1.0f; + LSL_Vector upper = new LSL_Vector(halfSize); result.Add(lower); result.Add(upper); return result; @@ -9943,9 +9923,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api ScenePresence avatar = World.GetScenePresence(detectedParams.Key); if (avatar != null) { - avatar.ControllingClient.SendScriptTeleportRequest(m_host.Name, simname, - new Vector3((float)pos.x, (float)pos.y, (float)pos.z), - new Vector3((float)lookAt.x, (float)lookAt.y, (float)lookAt.z)); + avatar.ControllingClient.SendScriptTeleportRequest(m_host.Name, + simname, pos, lookAt); } ScriptSleep(1000); } @@ -11143,8 +11122,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api m_host.AddScriptLPS(1); - Vector3 rayStart = new Vector3((float)start.x, (float)start.y, (float)start.z); - Vector3 rayEnd = new Vector3((float)end.x, (float)end.y, (float)end.z); + Vector3 rayStart = start; + Vector3 rayEnd = end; Vector3 dir = rayEnd - rayStart; float dist = Vector3.Mag(dir); diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LS_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LS_Api.cs index 795de80..ceb4660 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LS_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LS_Api.cs @@ -304,7 +304,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api case (int)ScriptBaseClass.WL_CLOUD_DETAIL_XY_DENSITY: idx++; iV = rules.GetVector3Item(idx); - wl.cloudDetailXYDensity = new Vector3((float)iV.x, (float)iV.y, (float)iV.z); + wl.cloudDetailXYDensity = iV; break; case (int)ScriptBaseClass.WL_CLOUD_SCALE: idx++; @@ -329,7 +329,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api case (int)ScriptBaseClass.WL_CLOUD_XY_DENSITY: idx++; iV = rules.GetVector3Item(idx); - wl.cloudXYDensity = new Vector3((float)iV.x, (float)iV.y, (float)iV.z); + wl.cloudXYDensity = iV; break; case (int)ScriptBaseClass.WL_DENSITY_MULTIPLIER: idx++; @@ -384,7 +384,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api case (int)ScriptBaseClass.WL_REFLECTION_WAVELET_SCALE: idx++; iV = rules.GetVector3Item(idx); - wl.reflectionWaveletScale = new Vector3((float)iV.x, (float)iV.y, (float)iV.z); + wl.reflectionWaveletScale = iV; break; case (int)ScriptBaseClass.WL_REFRACT_SCALE_ABOVE: idx++; @@ -422,7 +422,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api case (int)ScriptBaseClass.WL_WATER_COLOR: idx++; iV = rules.GetVector3Item(idx); - wl.waterColor = new Vector3((float)iV.x, (float)iV.y, (float)iV.z); + wl.waterColor = iV; break; case (int)ScriptBaseClass.WL_WATER_FOG_DENSITY_EXPONENT: idx++; diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs index 7844c75..929948b 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs @@ -343,8 +343,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { if (type == typeof(OpenMetaverse.Vector3)) { - LSL_Vector vect = (LSL_Vector)lslparm; - return new OpenMetaverse.Vector3((float)vect.x,(float)vect.y,(float)vect.z); + return (OpenMetaverse.Vector3)((LSL_Vector)lslparm); } } @@ -372,8 +371,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } else if (plist[i] is LSL_Vector) { - LSL_Vector vect = (LSL_Vector)plist[i]; - result[i] = new OpenMetaverse.Vector3((float)vect.x,(float)vect.y,(float)vect.z); + result[i] = (OpenMetaverse.Vector3)( + (LSL_Vector)plist[i]); } else MODError("unknown LSL list element type"); diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs index 859ee93..eff1598 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs @@ -773,10 +773,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api // We will launch the teleport on a new thread so that when the script threads are terminated // before teleport in ScriptInstance.GetXMLState(), we don't end up aborting the one doing the teleporting. - Util.FireAndForget( - o => World.RequestTeleportLocation(presence.ControllingClient, regionName, - new Vector3((float)position.x, (float)position.y, (float)position.z), - new Vector3((float)lookat.x, (float)lookat.y, (float)lookat.z), (uint)TPFlags.ViaLocation)); + Util.FireAndForget(o => World.RequestTeleportLocation( + presence.ControllingClient, regionName, position, + lookat, (uint)TPFlags.ViaLocation)); ScriptSleep(5000); @@ -819,10 +818,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api // We will launch the teleport on a new thread so that when the script threads are terminated // before teleport in ScriptInstance.GetXMLState(), we don't end up aborting the one doing the teleporting. - Util.FireAndForget( - o => World.RequestTeleportLocation(presence.ControllingClient, regionHandle, - new Vector3((float)position.x, (float)position.y, (float)position.z), - new Vector3((float)lookat.x, (float)lookat.y, (float)lookat.z), (uint)TPFlags.ViaLocation)); + Util.FireAndForget(o => World.RequestTeleportLocation( + presence.ControllingClient, regionHandle, + position, lookat, (uint)TPFlags.ViaLocation)); ScriptSleep(5000); @@ -2329,7 +2327,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api ownerID = m_host.OwnerID; UUID x = module.CreateNPC(firstname, lastname, - new Vector3((float) position.x, (float) position.y, (float) position.z), + position, ownerID, senseAsAgent, World, @@ -2446,7 +2444,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api return new LSL_Vector(0, 0, 0); } - public void osNpcMoveTo(LSL_Key npc, LSL_Vector position) + public void osNpcMoveTo(LSL_Key npc, LSL_Vector pos) { CheckThreatLevel(ThreatLevel.High, "osNpcMoveTo"); m_host.AddScriptLPS(1); @@ -2461,7 +2459,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (!module.CheckPermissions(npcId, m_host.OwnerID)) return; - Vector3 pos = new Vector3((float) position.x, (float) position.y, (float) position.z); module.MoveToTarget(npcId, World, pos, false, true, false); } } @@ -2481,11 +2478,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (!module.CheckPermissions(npcId, m_host.OwnerID)) return; - Vector3 pos = new Vector3((float)target.x, (float)target.y, (float)target.z); module.MoveToTarget( new UUID(npc.m_string), World, - pos, + target, (options & ScriptBaseClass.OS_NPC_NO_FLY) != 0, (options & ScriptBaseClass.OS_NPC_LAND_AT_TARGET) != 0, (options & ScriptBaseClass.OS_NPC_RUNNING) != 0); diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs index a626be8..7162226 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs @@ -428,9 +428,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins try { Vector3 diff = toRegionPos - fromRegionPos; - LSL_Types.Vector3 obj_dir = new LSL_Types.Vector3(diff.X, diff.Y, diff.Z); - double dot = LSL_Types.Vector3.Dot(forward_dir, obj_dir); - double mag_obj = LSL_Types.Vector3.Mag(obj_dir); + double dot = LSL_Types.Vector3.Dot(forward_dir, diff); + double mag_obj = LSL_Types.Vector3.Mag(diff); ang_obj = Math.Acos(dot / (mag_fwd * mag_obj)); } catch @@ -560,8 +559,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins double ang_obj = 0; try { - Vector3 diff = toRegionPos - fromRegionPos; - LSL_Types.Vector3 obj_dir = new LSL_Types.Vector3(diff.X, diff.Y, diff.Z); + LSL_Types.Vector3 obj_dir = new LSL_Types.Vector3( + toRegionPos - fromRegionPos); double dot = LSL_Types.Vector3.Dot(forward_dir, obj_dir); double mag_obj = LSL_Types.Vector3.Mag(obj_dir); ang_obj = Math.Acos(dot / (mag_fwd * mag_obj)); diff --git a/OpenSim/Region/ScriptEngine/Shared/Helpers.cs b/OpenSim/Region/ScriptEngine/Shared/Helpers.cs index 0108f44..5a58f73 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Helpers.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Helpers.cs @@ -160,11 +160,11 @@ namespace OpenSim.Region.ScriptEngine.Shared else { // Set the values from the touch data provided by the client - touchST = new LSL_Types.Vector3(value.STCoord.X, value.STCoord.Y, value.STCoord.Z); - touchUV = new LSL_Types.Vector3(value.UVCoord.X, value.UVCoord.Y, value.UVCoord.Z); - touchNormal = new LSL_Types.Vector3(value.Normal.X, value.Normal.Y, value.Normal.Z); - touchBinormal = new LSL_Types.Vector3(value.Binormal.X, value.Binormal.Y, value.Binormal.Z); - touchPos = new LSL_Types.Vector3(value.Position.X, value.Position.Y, value.Position.Z); + touchST = new LSL_Types.Vector3(value.STCoord); + touchUV = new LSL_Types.Vector3(value.UVCoord); + touchNormal = new LSL_Types.Vector3(value.Normal); + touchBinormal = new LSL_Types.Vector3(value.Binormal); + touchPos = new LSL_Types.Vector3(value.Position); touchFace = value.FaceIndex; } } @@ -181,19 +181,13 @@ namespace OpenSim.Region.ScriptEngine.Shared Name = presence.Firstname + " " + presence.Lastname; Owner = Key; - Position = new LSL_Types.Vector3( - presence.AbsolutePosition.X, - presence.AbsolutePosition.Y, - presence.AbsolutePosition.Z); + Position = new LSL_Types.Vector3(presence.AbsolutePosition); Rotation = new LSL_Types.Quaternion( presence.Rotation.X, presence.Rotation.Y, presence.Rotation.Z, presence.Rotation.W); - Velocity = new LSL_Types.Vector3( - presence.Velocity.X, - presence.Velocity.Y, - presence.Velocity.Z); + Velocity = new LSL_Types.Vector3(presence.Velocity); if (presence.PresenceType != PresenceType.Npc) { @@ -241,16 +235,12 @@ namespace OpenSim.Region.ScriptEngine.Shared } } - Position = new LSL_Types.Vector3(part.AbsolutePosition.X, - part.AbsolutePosition.Y, - part.AbsolutePosition.Z); + Position = new LSL_Types.Vector3(part.AbsolutePosition); Quaternion wr = part.ParentGroup.GroupRotation; Rotation = new LSL_Types.Quaternion(wr.X, wr.Y, wr.Z, wr.W); - Velocity = new LSL_Types.Vector3(part.Velocity.X, - part.Velocity.Y, - part.Velocity.Z); + Velocity = new LSL_Types.Vector3(part.Velocity); } } diff --git a/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs b/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs index 562433d..d18efe0 100644 --- a/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs +++ b/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs @@ -31,6 +31,11 @@ using System.Globalization; using System.Text.RegularExpressions; using OpenSim.Framework; +using OpenMetaverse; +using OMV_Vector3 = OpenMetaverse.Vector3; +using OMV_Vector3d = OpenMetaverse.Vector3d; +using OMV_Quaternion = OpenMetaverse.Quaternion; + namespace OpenSim.Region.ScriptEngine.Shared { [Serializable] @@ -54,6 +59,20 @@ namespace OpenSim.Region.ScriptEngine.Shared z = (float)vector.z; } + public Vector3(OMV_Vector3 vector) + { + x = vector.X; + y = vector.Y; + z = vector.Z; + } + + public Vector3(OMV_Vector3d vector) + { + x = vector.X; + y = vector.Y; + z = vector.Z; + } + public Vector3(double X, double Y, double Z) { x = X; @@ -109,6 +128,26 @@ namespace OpenSim.Region.ScriptEngine.Shared return new list(new object[] { vec }); } + public static implicit operator OMV_Vector3(Vector3 vec) + { + return new OMV_Vector3((float)vec.x, (float)vec.y, (float)vec.z); + } + + public static implicit operator Vector3(OMV_Vector3 vec) + { + return new Vector3(vec); + } + + public static implicit operator OMV_Vector3d(Vector3 vec) + { + return new OMV_Vector3d(vec.x, vec.y, vec.z); + } + + public static implicit operator Vector3(OMV_Vector3d vec) + { + return new Vector3(vec); + } + public static bool operator ==(Vector3 lhs, Vector3 rhs) { return (lhs.x == rhs.x && lhs.y == rhs.y && lhs.z == rhs.z); diff --git a/OpenSim/Region/ScriptEngine/XEngine/EventManager.cs b/OpenSim/Region/ScriptEngine/XEngine/EventManager.cs index 5c4174e..a1ad07d 100644 --- a/OpenSim/Region/ScriptEngine/XEngine/EventManager.cs +++ b/OpenSim/Region/ScriptEngine/XEngine/EventManager.cs @@ -152,9 +152,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine det[0] = new DetectParams(); det[0].Key = remoteClient.AgentId; det[0].Populate(myScriptEngine.World); - det[0].OffsetPos = new LSL_Types.Vector3(offsetPos.X, - offsetPos.Y, - offsetPos.Z); + det[0].OffsetPos = offsetPos; if (originalID == 0) { @@ -298,9 +296,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine foreach (DetectedObject detobj in col.Colliders) { DetectParams d = new DetectParams(); - d.Position = new LSL_Types.Vector3(detobj.posVector.X, - detobj.posVector.Y, - detobj.posVector.Z); + d.Position = detobj.posVector; d.Populate(myScriptEngine.World); det.Add(d); myScriptEngine.PostObjectEvent(localID, new EventParams( @@ -318,9 +314,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine foreach (DetectedObject detobj in col.Colliders) { DetectParams d = new DetectParams(); - d.Position = new LSL_Types.Vector3(detobj.posVector.X, - detobj.posVector.Y, - detobj.posVector.Z); + d.Position = detobj.posVector; d.Populate(myScriptEngine.World); det.Add(d); myScriptEngine.PostObjectEvent(localID, new EventParams( @@ -337,9 +331,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine foreach (DetectedObject detobj in col.Colliders) { DetectParams d = new DetectParams(); - d.Position = new LSL_Types.Vector3(detobj.posVector.X, - detobj.posVector.Y, - detobj.posVector.Z); + d.Position = detobj.posVector; d.Populate(myScriptEngine.World); det.Add(d); myScriptEngine.PostObjectEvent(localID, new EventParams( @@ -381,8 +373,8 @@ namespace OpenSim.Region.ScriptEngine.XEngine myScriptEngine.PostObjectEvent(localID, new EventParams( "at_target", new object[] { new LSL_Types.LSLInteger(handle), - new LSL_Types.Vector3(targetpos.X,targetpos.Y,targetpos.Z), - new LSL_Types.Vector3(atpos.X,atpos.Y,atpos.Z) }, + new LSL_Types.Vector3(targetpos), + new LSL_Types.Vector3(atpos) }, new DetectParams[0])); } diff --git a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs index 1571fb4..a05650a 100644 --- a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs +++ b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs @@ -1467,7 +1467,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine else if (p[i] is string) lsl_p[i] = new LSL_Types.LSLString((string)p[i]); else if (p[i] is Vector3) - lsl_p[i] = new LSL_Types.Vector3(((Vector3)p[i]).X, ((Vector3)p[i]).Y, ((Vector3)p[i]).Z); + lsl_p[i] = new LSL_Types.Vector3((Vector3)p[i]); else if (p[i] is Quaternion) lsl_p[i] = new LSL_Types.Quaternion(((Quaternion)p[i]).X, ((Quaternion)p[i]).Y, ((Quaternion)p[i]).Z, ((Quaternion)p[i]).W); else if (p[i] is float) @@ -1493,7 +1493,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine else if (p[i] is string) lsl_p[i] = new LSL_Types.LSLString((string)p[i]); else if (p[i] is Vector3) - lsl_p[i] = new LSL_Types.Vector3(((Vector3)p[i]).X, ((Vector3)p[i]).Y, ((Vector3)p[i]).Z); + lsl_p[i] = new LSL_Types.Vector3((Vector3)p[i]); else if (p[i] is Quaternion) lsl_p[i] = new LSL_Types.Quaternion(((Quaternion)p[i]).X, ((Quaternion)p[i]).Y, ((Quaternion)p[i]).Z, ((Quaternion)p[i]).W); else if (p[i] is float) -- cgit v1.1 From 2a70afeca2a1ba452660ee2669aa4033a91143bb Mon Sep 17 00:00:00 2001 From: Melanie Date: Sat, 18 Aug 2012 14:00:10 +0100 Subject: Fix the whitespace formatting error introduced by the last patch --- OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 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 bca9a75..7671e54 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -2038,8 +2038,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } else { - part.OffsetPosition = !adjust ? targetPos : SetPosAdjust( - currentPos, targetPos); + part.OffsetPosition = !adjust ? targetPos : + SetPosAdjust(currentPos, targetPos); SceneObjectGroup parent = part.ParentGroup; parent.HasGroupChanged = true; parent.ScheduleGroupForTerseUpdate(); -- cgit v1.1 From 2b0c8bc48008b8ce38c99d5c3135633b0d4f8e87 Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Sat, 18 Aug 2012 14:49:10 +0100 Subject: Implementing operators & constructors for Quaternion --- OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs b/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs index d18efe0..bdc7d70 100644 --- a/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs +++ b/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs @@ -361,6 +361,14 @@ namespace OpenSim.Region.ScriptEngine.Shared s = 1; } + public Quaternion(OMV_Quaternion rot) + { + x = rot.X; + y = rot.Y; + z = rot.Z; + s = rot.W; + } + #endregion #region Overriders @@ -407,6 +415,16 @@ namespace OpenSim.Region.ScriptEngine.Shared return new list(new object[] { r }); } + public static implicit operator OMV_Quaternion(Quaternion rot) + { + return new OMV_Quaternion((float)rot.x, (float)rot.y, (float)rot.z, (float)rot.s); + } + + public static implicit operator Quaternion(OMV_Quaternion rot) + { + return new Quaternion(rot); + } + public static bool operator ==(Quaternion lhs, Quaternion rhs) { // Return true if the fields match: -- cgit v1.1 From 52d7af05bcc5141eef42115e0ac5bca53163717f Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Sat, 18 Aug 2012 14:54:13 +0100 Subject: adding missing refactor for LSL_Vector --- OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (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 7671e54..4d542d50 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -10536,7 +10536,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } break; case ScriptBaseClass.OBJECT_VELOCITY: - ret.Add(new LSL_Vector(obj.Velocity.X, obj.Velocity.Y, obj.Velocity.Z)); + ret.Add(new LSL_Vector(obj.Velocity)); break; case ScriptBaseClass.OBJECT_OWNER: ret.Add(new LSL_String(obj.OwnerID.ToString())); -- cgit v1.1 From fb84ff96a9ac7df564fb8f8242e0ff0d2638b438 Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Sat, 18 Aug 2012 15:04:07 +0100 Subject: implicit operators mean one does not need to instantiate new objects manually --- OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 5 ++--- OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs | 7 +++---- 2 files changed, 5 insertions(+), 7 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 4d542d50..87298e3 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -2231,8 +2231,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public LSL_Integer llRotTarget(LSL_Rotation rot, double error) { m_host.AddScriptLPS(1); - return m_host.ParentGroup.registerRotTargetWaypoint( - new Quaternion((float)rot.x, (float)rot.y, (float)rot.z, (float)rot.s), (float)error); + return m_host.ParentGroup.registerRotTargetWaypoint(rot, (float)error); } public void llRotTargetRemove(int number) @@ -10531,7 +10530,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api else rot = obj.GetWorldRotation(); - LSL_Rotation objrot = new LSL_Rotation(rot.X, rot.Y, rot.Z, rot.W); + LSL_Rotation objrot = new LSL_Rotation(rot); ret.Add(objrot); } break; diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs index 929948b..84cf6ca 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs @@ -333,8 +333,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { if (type == typeof(OpenMetaverse.Quaternion)) { - LSL_Rotation rot = (LSL_Rotation)lslparm; - return new OpenMetaverse.Quaternion((float)rot.x,(float)rot.y,(float)rot.z,(float)rot.s); + return (OpenMetaverse.Quaternion)((LSL_Rotation)lslparm); } } @@ -366,8 +365,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api result[i] = new UUID((LSL_Key)plist[i]); else if (plist[i] is LSL_Rotation) { - LSL_Rotation rot = (LSL_Rotation)plist[i]; - result[i] = new OpenMetaverse.Quaternion((float)rot.x,(float)rot.y,(float)rot.z,(float)rot.s); + result[i] = (OpenMetaverse.Quaternion)( + (LSL_Rotation)plist[i]); } else if (plist[i] is LSL_Vector) { -- cgit v1.1 From ffdde05bb7d3d2ca71807c3197411bf66c29aa45 Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Sat, 18 Aug 2012 15:10:44 +0100 Subject: constructor means not having to manually refer to individual properties --- .../ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs | 4 ++-- OpenSim/Region/ScriptEngine/XEngine/EventManager.cs | 4 ++-- OpenSim/Region/ScriptEngine/XEngine/XEngine.cs | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs index 7162226..24cceea 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs @@ -351,7 +351,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins q = avatar.Rotation * q; } - LSL_Types.Quaternion r = new LSL_Types.Quaternion(q.X, q.Y, q.Z, q.W); + LSL_Types.Quaternion r = new LSL_Types.Quaternion(q); LSL_Types.Vector3 forward_dir = (new LSL_Types.Vector3(1, 0, 0) * r); double mag_fwd = LSL_Types.Vector3.Mag(forward_dir); @@ -478,7 +478,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins q = avatar.Rotation * q; } - LSL_Types.Quaternion r = new LSL_Types.Quaternion(q.X, q.Y, q.Z, q.W); + LSL_Types.Quaternion r = new LSL_Types.Quaternion(q); LSL_Types.Vector3 forward_dir = (new LSL_Types.Vector3(1, 0, 0) * r); double mag_fwd = LSL_Types.Vector3.Mag(forward_dir); bool attached = (SensePoint.ParentGroup.AttachmentPoint != 0); diff --git a/OpenSim/Region/ScriptEngine/XEngine/EventManager.cs b/OpenSim/Region/ScriptEngine/XEngine/EventManager.cs index a1ad07d..cee10df 100644 --- a/OpenSim/Region/ScriptEngine/XEngine/EventManager.cs +++ b/OpenSim/Region/ScriptEngine/XEngine/EventManager.cs @@ -391,8 +391,8 @@ namespace OpenSim.Region.ScriptEngine.XEngine myScriptEngine.PostObjectEvent(localID, new EventParams( "at_rot_target", new object[] { new LSL_Types.LSLInteger(handle), - new LSL_Types.Quaternion(targetrot.X,targetrot.Y,targetrot.Z,targetrot.W), - new LSL_Types.Quaternion(atrot.X,atrot.Y,atrot.Z,atrot.W) }, + new LSL_Types.Quaternion(targetrot), + new LSL_Types.Quaternion(atrot) }, new DetectParams[0])); } diff --git a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs index a05650a..53f899a 100644 --- a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs +++ b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs @@ -1469,7 +1469,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine else if (p[i] is Vector3) lsl_p[i] = new LSL_Types.Vector3((Vector3)p[i]); else if (p[i] is Quaternion) - lsl_p[i] = new LSL_Types.Quaternion(((Quaternion)p[i]).X, ((Quaternion)p[i]).Y, ((Quaternion)p[i]).Z, ((Quaternion)p[i]).W); + lsl_p[i] = new LSL_Types.Quaternion((Quaternion)p[i]); else if (p[i] is float) lsl_p[i] = new LSL_Types.LSLFloat((float)p[i]); else @@ -1495,7 +1495,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine else if (p[i] is Vector3) lsl_p[i] = new LSL_Types.Vector3((Vector3)p[i]); else if (p[i] is Quaternion) - lsl_p[i] = new LSL_Types.Quaternion(((Quaternion)p[i]).X, ((Quaternion)p[i]).Y, ((Quaternion)p[i]).Z, ((Quaternion)p[i]).W); + lsl_p[i] = new LSL_Types.Quaternion((Quaternion)p[i]); else if (p[i] is float) lsl_p[i] = new LSL_Types.LSLFloat((float)p[i]); else -- cgit v1.1 From ca33619e11d6b370793ffd70dd8a0baefa88f5d1 Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Sat, 18 Aug 2012 15:18:31 +0100 Subject: Rot2Quaternion is now redundant --- .../Shared/Api/Implementation/LSL_Api.cs | 21 ++++++++++----------- .../Shared/Api/Implementation/OSSL_Api.cs | 2 +- 2 files changed, 11 insertions(+), 12 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 87298e3..7009548 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -2094,7 +2094,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (m_host.ParentID == 0) { // special case: If we are root, rotate complete SOG to new rotation - SetRot(m_host, Rot2Quaternion(rot)); + SetRot(m_host, rot); } else { @@ -2102,7 +2102,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api SceneObjectPart rootPart = m_host.ParentGroup.RootPart; if (rootPart != null) // better safe than sorry { - SetRot(m_host, rootPart.RotationOffset * Rot2Quaternion(rot)); + SetRot(m_host, rootPart.RotationOffset * (Quaternion)rot); } } @@ -2112,7 +2112,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public void llSetLocalRot(LSL_Rotation rot) { m_host.AddScriptLPS(1); - SetRot(m_host, Rot2Quaternion(rot)); + SetRot(m_host, rot); ScriptSleep(200); } @@ -2828,7 +2828,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api // need the magnitude later // float velmag = (float)Util.GetMagnitude(llvel); - SceneObjectGroup new_group = World.RezObject(m_host, item, pos, Rot2Quaternion(rot), vel, param); + SceneObjectGroup new_group = World.RezObject(m_host, item, pos, rot, vel, param); // If either of these are null, then there was an unknown error. if (new_group == null) @@ -2897,7 +2897,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } else { - m_host.StartLookAt(Rot2Quaternion(rot), (float)strength, (float)damping); + m_host.StartLookAt(rot, (float)strength, (float)damping); } } @@ -3292,7 +3292,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } else { - m_host.RotLookAt(Rot2Quaternion(target), (float)strength, (float)damping); + m_host.RotLookAt(target, (float)strength, (float)damping); } } @@ -6506,7 +6506,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (!m_host.ParentGroup.IsDeleted) { - m_host.ParentGroup.RootPart.SetVehicleRotationParam(param, Rot2Quaternion(rot)); + m_host.ParentGroup.RootPart.SetVehicleRotationParam(param, rot); } } @@ -7316,13 +7316,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (part.ParentID == 0) { // special case: If we are root, rotate complete SOG to new rotation - SetRot(part, Rot2Quaternion(q)); + SetRot(part, q); } else { // we are a child. The rotation values will be set to the one of root modified by rot, as in SL. Don't ask. SceneObjectPart rootPart = part.ParentGroup.RootPart; - SetRot(part, rootPart.RotationOffset * Rot2Quaternion(q)); + SetRot(part, rootPart.RotationOffset * (Quaternion)q); } break; @@ -7634,8 +7634,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api case (int)ScriptBaseClass.PRIM_ROT_LOCAL: if (remain < 1) return null; - LSL_Rotation lr = rules.GetQuaternionItem(idx++); - SetRot(part, Rot2Quaternion(lr)); + SetRot(part, rules.GetQuaternionItem(idx++)); break; case (int)ScriptBaseClass.PRIM_OMEGA: if (remain < 3) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs index eff1598..8936cb2 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs @@ -2533,7 +2533,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api ScenePresence sp = World.GetScenePresence(npcId); if (sp != null) - sp.Rotation = LSL_Api.Rot2Quaternion(rotation); + sp.Rotation = rotation; } } -- cgit v1.1 From d72d59905668d881c98f35c7f0c9783d6744084d Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Sat, 18 Aug 2012 15:19:15 +0100 Subject: integrating redundant code into operator --- .../ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 14 +------------- OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs | 7 ++++++- 2 files changed, 7 insertions(+), 14 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 7009548..4645e7a 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -330,14 +330,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api return key; } - // convert a LSL_Rotation to a Quaternion - public static Quaternion Rot2Quaternion(LSL_Rotation r) - { - Quaternion q = new Quaternion((float)r.x, (float)r.y, (float)r.z, (float)r.s); - q.Normalize(); - return q; - } - //These are the implementations of the various ll-functions used by the LSL scripts. public LSL_Float llSin(double f) { @@ -6532,12 +6524,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api protected void SitTarget(SceneObjectPart part, LSL_Vector offset, LSL_Rotation rot) { - // LSL quaternions can normalize to 0, normal Quaternions can't. - if (rot.s == 0 && rot.x == 0 && rot.y == 0 && rot.z == 0) - rot.z = 1; // ZERO_ROTATION = 0,0,0,1 - part.SitTargetPosition = offset; - part.SitTargetOrientation = Rot2Quaternion(rot); + part.SitTargetOrientation = rot; part.ParentGroup.HasGroupChanged = true; } diff --git a/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs b/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs index bdc7d70..9d9df9c 100644 --- a/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs +++ b/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs @@ -417,7 +417,12 @@ namespace OpenSim.Region.ScriptEngine.Shared public static implicit operator OMV_Quaternion(Quaternion rot) { - return new OMV_Quaternion((float)rot.x, (float)rot.y, (float)rot.z, (float)rot.s); + // LSL quaternions can normalize to 0, normal Quaternions can't. + if (rot.s == 0 && rot.x == 0 && rot.y == 0 && rot.z == 0) + rot.z = 1; // ZERO_ROTATION = 0,0,0,1 + OMV_Quaternion omvrot = new OMV_Quaternion((float)rot.x, (float)rot.y, (float)rot.z, (float)rot.s); + omvrot.Normalize(); + return omvrot; } public static implicit operator Quaternion(OMV_Quaternion rot) -- cgit v1.1 From 8769e4ee731cfc83afec7ca4994113c2b04d7ba4 Mon Sep 17 00:00:00 2001 From: Melanie Date: Sat, 18 Aug 2012 19:08:38 +0100 Subject: Add a reference to OpenMetaverseType.dll to compiled script assemblies. --- OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs | 2 ++ 1 file changed, 2 insertions(+) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs b/OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs index 17a0d69..03be2ab 100644 --- a/OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs +++ b/OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs @@ -546,6 +546,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools "OpenSim.Region.ScriptEngine.Shared.dll")); parameters.ReferencedAssemblies.Add(Path.Combine(rootPath, "OpenSim.Region.ScriptEngine.Shared.Api.Runtime.dll")); + parameters.ReferencedAssemblies.Add(Path.Combine(rootPath, + "OpenMetaverseTypes.dll")); if (lang == enumCompileType.yp) { -- cgit v1.1 From dd0556abc9a88121ac91cd86c60a51aac9c726e5 Mon Sep 17 00:00:00 2001 From: Melanie Date: Sun, 19 Aug 2012 22:05:38 +0100 Subject: Fix llDialog responses so that they can be heard throughout the region. This now conforms to the behaviour in SL. --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 01ceeed..22b3d35 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -5810,7 +5810,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP args.Channel = ch; args.From = String.Empty; args.Message = Utils.BytesToString(msg); - args.Type = ChatTypeEnum.Shout; + args.Type = ChatTypeEnum.Region; //Behaviour in SL is that the response can be heard from any distance args.Position = new Vector3(); args.Scene = Scene; args.Sender = this; -- cgit v1.1 From 9aec62f0ac7ce0e074ee77e687d26c5414190162 Mon Sep 17 00:00:00 2001 From: Melanie Date: Mon, 20 Aug 2012 15:35:06 +0200 Subject: Fix scripted detach of temp attachments --- .../Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs index f107be1..d6ad07e 100644 --- a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs @@ -458,10 +458,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments public void DetachSingleAttachmentToInv(IScenePresence sp, SceneObjectGroup so) { - // As per Linden spec, detach (take) is disabled for temp attachs - if (so.FromItemID == UUID.Zero) - return; - lock (sp.AttachmentsSyncLock) { // Save avatar attachment information @@ -976,7 +972,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments ScenePresence sp = m_scene.GetScenePresence(remoteClient.AgentId); SceneObjectGroup group = m_scene.GetGroupByPrim(objectLocalID); - if (sp != null && group != null) + if (sp != null && group != null && group.FromItemID != UUID.Zero) DetachSingleAttachmentToInv(sp, group); } @@ -994,7 +990,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments foreach (SceneObjectGroup group in attachments) { - if (group.FromItemID == itemID) + if (group.FromItemID == itemID && group.FromItemID != UUID.Zero) { DetachSingleAttachmentToInv(sp, group); return; -- cgit v1.1 From bcbd450fe441e94d6c0f547055b4e95f75a5b0d0 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Mon, 20 Aug 2012 20:24:54 +0100 Subject: Add --force flag to "kick user" console command to allow bypassing of recent race condition checks. This is to allow a second attempt to remove an avatar even if "show connections" shows them as already inactive (i.e. close has already been attempted once). You should only attempt --force if a normal kick fails. This is partly for diagnostics as we have seen some connections occasionally remain on lbsa plaza even if they are registered as inactive. This is not a permanent solution and may not work anyway - the ultimate solution is to stop this problem from happening in the first place. --- OpenSim/Region/Application/OpenSim.cs | 24 +++++++++++++++------- .../Caps/EventQueue/Tests/EventQueueTests.cs | 2 +- .../Region/ClientStack/Linden/UDP/LLClientView.cs | 14 ++++++++----- .../Attachments/Tests/AttachmentsModuleTests.cs | 2 +- .../EntityTransfer/EntityTransferModule.cs | 2 +- .../Simulation/LocalSimulationConnector.cs | 2 +- OpenSim/Region/Framework/Scenes/Scene.cs | 9 +++++--- .../Scenes/Tests/ScenePresenceAgentTests.cs | 2 +- .../Server/IRCClientView.cs | 5 +++++ .../Region/OptionalModules/World/NPC/NPCAvatar.cs | 5 +++++ .../Shared/Api/Implementation/OSSL_Api.cs | 4 ++-- 11 files changed, 49 insertions(+), 22 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Application/OpenSim.cs b/OpenSim/Region/Application/OpenSim.cs index 6bbab35..1fc11f5 100644 --- a/OpenSim/Region/Application/OpenSim.cs +++ b/OpenSim/Region/Application/OpenSim.cs @@ -35,6 +35,7 @@ using System.Text; using System.Text.RegularExpressions; using System.Timers; using log4net; +using NDesk.Options; using Nini.Config; using OpenMetaverse; using OpenSim.Framework; @@ -310,8 +311,11 @@ namespace OpenSim "Change the scale of a named prim", HandleEditScale); m_console.Commands.AddCommand("Users", false, "kick user", - "kick user [message]", - "Kick a user off the simulator", KickUserCommand); + "kick user [--force] [message]", + "Kick a user off the simulator", + "The --force option will kick the user without any checks to see whether it's already in the process of closing\n" + + "Only use this option if you are sure the avatar is inactive and a normal kick user operation does not removed them", + KickUserCommand); m_console.Commands.AddCommand("Users", false, "show users", "show users [full]", @@ -453,11 +457,17 @@ namespace OpenSim /// name of avatar to kick private void KickUserCommand(string module, string[] cmdparams) { - if (cmdparams.Length < 4) + bool force = false; + + OptionSet options = new OptionSet().Add("f|force", delegate (string v) { force = v != null; }); + + List mainParams = options.Parse(cmdparams); + + if (mainParams.Count < 4) return; string alert = null; - if (cmdparams.Length > 4) + if (mainParams.Count > 4) alert = String.Format("\n{0}\n", String.Join(" ", cmdparams, 4, cmdparams.Length - 4)); IList agents = SceneManager.GetCurrentSceneAvatars(); @@ -466,8 +476,8 @@ namespace OpenSim { RegionInfo regionInfo = presence.Scene.RegionInfo; - if (presence.Firstname.ToLower().Contains(cmdparams[2].ToLower()) && - presence.Lastname.ToLower().Contains(cmdparams[3].ToLower())) + if (presence.Firstname.ToLower().Contains(mainParams[2].ToLower()) && + presence.Lastname.ToLower().Contains(mainParams[3].ToLower())) { MainConsole.Instance.Output( String.Format( @@ -480,7 +490,7 @@ namespace OpenSim else presence.ControllingClient.Kick("\nThe OpenSim manager kicked you out.\n"); - presence.Scene.IncomingCloseAgent(presence.UUID); + presence.Scene.IncomingCloseAgent(presence.UUID, force); } } diff --git a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/Tests/EventQueueTests.cs b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/Tests/EventQueueTests.cs index cd70410..d604cf6 100644 --- a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/Tests/EventQueueTests.cs +++ b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/Tests/EventQueueTests.cs @@ -94,7 +94,7 @@ namespace OpenSim.Region.ClientStack.Linden.Tests UUID spId = TestHelpers.ParseTail(0x1); SceneHelpers.AddScenePresence(m_scene, spId); - m_scene.IncomingCloseAgent(spId); + m_scene.IncomingCloseAgent(spId, false); // TODO: Add more assertions for the other aspects of event queues Assert.That(MainServer.Instance.GetPollServiceHandlerKeys().Count, Is.EqualTo(0)); diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 22b3d35..148d0e0 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -487,16 +487,20 @@ namespace OpenSim.Region.ClientStack.LindenUDP #region Client Methods - /// - /// Close down the client view - /// public void Close() { + Close(false); + } + + public void Close(bool force) + { // We lock here to prevent race conditions between two threads calling close simultaneously (e.g. // a simultaneous relog just as a client is being closed out due to no packet ack from the old connection. lock (CloseSyncLock) { - if (!IsActive) + // We still perform a force close inside the sync lock since this is intended to attempt close where + // there is some unidentified connection problem, not where we have issues due to deadlock + if (!IsActive && !force) return; IsActive = false; @@ -11989,7 +11993,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP { Kick(reason); Thread.Sleep(1000); - Close(); + Disconnect(); } public void Disconnect() diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs index 1d13f75..82c6390 100644 --- a/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs +++ b/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs @@ -461,7 +461,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests SceneObjectGroup rezzedAtt = presence.GetAttachments()[0]; - scene.IncomingCloseAgent(presence.UUID); + scene.IncomingCloseAgent(presence.UUID, false); // Check that we can't retrieve this attachment from the scene. Assert.That(scene.GetSceneObjectGroup(rezzedAtt.UUID), Is.Null); diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs index 46738f6..c63b0a4 100644 --- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs +++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs @@ -644,7 +644,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer // an agent cannot teleport back to this region if it has teleported away. Thread.Sleep(2000); - sp.Scene.IncomingCloseAgent(sp.UUID); + sp.Scene.IncomingCloseAgent(sp.UUID, false); } else { diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs index 09a3bd6..1e52d37 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs @@ -312,7 +312,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation // "[LOCAL SIMULATION CONNECTOR]: Found region {0} {1} to send AgentUpdate", // s.RegionInfo.RegionName, destination.RegionHandle); - Util.FireAndForget(delegate { m_scenes[destination.RegionID].IncomingCloseAgent(id); }); + Util.FireAndForget(delegate { m_scenes[destination.RegionID].IncomingCloseAgent(id, false); }); return true; } diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index d2d6aba..ad74189 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -4116,16 +4116,19 @@ namespace OpenSim.Region.Framework.Scenes /// /// Tell a single agent to disconnect from the region. /// - /// /// - public bool IncomingCloseAgent(UUID agentID) + /// + /// Force the agent to close even if it might be in the middle of some other operation. You do not want to + /// force unless you are absolutely sure that the agent is dead and a normal close is not working. + /// + public bool IncomingCloseAgent(UUID agentID, bool force) { //m_log.DebugFormat("[SCENE]: Processing incoming close agent for {0}", agentID); ScenePresence presence = m_sceneGraph.GetScenePresence(agentID); if (presence != null) { - presence.ControllingClient.Close(); + presence.ControllingClient.Close(force); return true; } diff --git a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs index 5758869..5faf131 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs @@ -141,7 +141,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests TestScene scene = new SceneHelpers().SetupScene(); ScenePresence sp = SceneHelpers.AddScenePresence(scene, TestHelpers.ParseTail(0x1)); - scene.IncomingCloseAgent(sp.UUID); + scene.IncomingCloseAgent(sp.UUID, false); Assert.That(scene.GetScenePresence(sp.UUID), Is.Null); Assert.That(scene.AuthenticateHandler.GetAgentCircuitData(sp.UUID), Is.Null); diff --git a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs index bae25cd..e93bd7c 100644 --- a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs +++ b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs @@ -886,6 +886,11 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server public void Close() { + Close(false); + } + + public void Close(bool force) + { Disconnect(); } diff --git a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs index 67989ba..a8e4d90 100644 --- a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs +++ b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs @@ -901,6 +901,11 @@ namespace OpenSim.Region.OptionalModules.World.NPC public void Close() { + Close(false); + } + + public void Close(bool force) + { // Remove ourselves from the scene m_scene.RemoveClient(AgentId, false); } diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs index 8936cb2..1e8b51b 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs @@ -2877,7 +2877,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api avatar.SpeedModifier = (float)SpeedModifier; } - public void osKickAvatar(string FirstName,string SurName,string alert) + public void osKickAvatar(string FirstName, string SurName, string alert) { CheckThreatLevel(ThreatLevel.Severe, "osKickAvatar"); m_host.AddScriptLPS(1); @@ -2891,7 +2891,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api sp.ControllingClient.Kick(alert); // ...and close on our side - sp.Scene.IncomingCloseAgent(sp.UUID); + sp.Scene.IncomingCloseAgent(sp.UUID, false); } }); } -- cgit v1.1 From 812c498ef4da06d8c842e53e16e22c45e2fecbc2 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Mon, 20 Aug 2012 21:58:18 +0100 Subject: When loading an OAR, validate any group UUIDs and properly reconstruct parcel access lists. If a group UUID is present that is not on this simulator then the object or parcel is no longer group owned. This is a change from previous behaviour where such invalid UUIDs were kept. This is an adaptation of patch 0002 from http://opensimulator.org/mantis/view.php?id=6105 by Oren Hurvitz of Kitely. My adaptations are formatting only, apart from the notices about parcel owner IDs not being saved since this has now been fixed. Thanks Oren. --- .../World/Archiver/ArchiveReadRequest.cs | 63 +++++++++++++++++++++- 1 file changed, 62 insertions(+), 1 deletion(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs index 2b61800..433166d 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs @@ -97,6 +97,13 @@ namespace OpenSim.Region.CoreModules.World.Archiver } } + /// + /// Used to cache lookups for valid groups. + /// + private IDictionary m_validGroupUuids = new Dictionary(); + + private IGroupsModule m_groupsModule; + public ArchiveReadRequest(Scene scene, string loadPath, bool merge, bool skipAssets, Guid requestId) { m_scene = scene; @@ -120,6 +127,8 @@ namespace OpenSim.Region.CoreModules.World.Archiver // Zero can never be a valid user id m_validUserUuids[UUID.Zero] = false; + + m_groupsModule = m_scene.RequestModuleInterface(); } public ArchiveReadRequest(Scene scene, Stream loadStream, bool merge, bool skipAssets, Guid requestId) @@ -132,6 +141,8 @@ namespace OpenSim.Region.CoreModules.World.Archiver // Zero can never be a valid user id m_validUserUuids[UUID.Zero] = false; + + m_groupsModule = m_scene.RequestModuleInterface(); } /// @@ -302,6 +313,9 @@ namespace OpenSim.Region.CoreModules.World.Archiver if (!ResolveUserUuid(part.LastOwnerID)) part.LastOwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner; + if (!ResolveGroupUuid(part.GroupID)) + part.GroupID = UUID.Zero; + // And zap any troublesome sit target information // part.SitTargetOrientation = new Quaternion(0, 0, 0, 1); // part.SitTargetPosition = new Vector3(0, 0, 0); @@ -318,13 +332,18 @@ namespace OpenSim.Region.CoreModules.World.Archiver { kvp.Value.OwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner; } + if (kvp.Value.CreatorData == null || kvp.Value.CreatorData == string.Empty) { if (!ResolveUserUuid(kvp.Value.CreatorID)) kvp.Value.CreatorID = m_scene.RegionInfo.EstateSettings.EstateOwner; } + if (UserManager != null) UserManager.AddUser(kvp.Value.CreatorID, kvp.Value.CreatorData); + + if (!ResolveGroupUuid(kvp.Value.GroupID)) + kvp.Value.GroupID = UUID.Zero; } } } @@ -364,9 +383,27 @@ namespace OpenSim.Region.CoreModules.World.Archiver foreach (string serialisedParcel in serialisedParcels) { LandData parcel = LandDataSerializer.Deserialize(serialisedParcel); + + // Validate User and Group UUID's + if (!ResolveUserUuid(parcel.OwnerID)) parcel.OwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner; - + + if (!ResolveGroupUuid(parcel.GroupID)) + { + parcel.GroupID = UUID.Zero; + parcel.IsGroupOwned = false; + } + + List accessList = new List(); + foreach (LandAccessEntry entry in parcel.ParcelAccessList) + { + if (ResolveUserUuid(entry.AgentID)) + accessList.Add(entry); + // else, drop this access rule + } + parcel.ParcelAccessList = accessList; + // m_log.DebugFormat( // "[ARCHIVER]: Adding parcel {0}, local id {1}, area {2}", // parcel.Name, parcel.LocalID, parcel.Area); @@ -401,6 +438,30 @@ namespace OpenSim.Region.CoreModules.World.Archiver } /// + /// Look up the given group id to check whether it's one that is valid for this grid. + /// + /// + /// + private bool ResolveGroupUuid(UUID uuid) + { + if (uuid == UUID.Zero) + return true; // this means the object has no group + + if (!m_validGroupUuids.ContainsKey(uuid)) + { + bool exists; + + if (m_groupsModule == null) + exists = false; + else + exists = (m_groupsModule.GetGroupRecord(uuid) != null); + + m_validGroupUuids.Add(uuid, exists); + } + + return m_validGroupUuids[uuid]; + } + /// Load an asset /// /// -- cgit v1.1 From e6fb45859775d0c53de0bcdfc48fad51866d318b Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Mon, 20 Aug 2012 22:18:29 +0100 Subject: no-op change for cia.vc test --- OpenSim/Region/Application/OpenSim.cs | 1 + 1 file changed, 1 insertion(+) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Application/OpenSim.cs b/OpenSim/Region/Application/OpenSim.cs index 1fc11f5..769eea8 100644 --- a/OpenSim/Region/Application/OpenSim.cs +++ b/OpenSim/Region/Application/OpenSim.cs @@ -420,6 +420,7 @@ namespace OpenSim { RunCommandScript(m_shutdownCommandsFile); } + base.ShutdownSpecific(); } -- cgit v1.1 From aee4353e9cf811bd66a17f292c6f17c9495831fc Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Fri, 17 Aug 2012 14:47:53 +0100 Subject: fix typo --- OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index 53b4f7e..0535dcb 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -2858,7 +2858,7 @@ namespace OpenSim.Region.Framework.Scenes public void SetFaceColor(Vector3 color, int face) { // The only way to get a deep copy/ If we don't do this, we can - // mever detect color changes further down. + // never detect color changes further down. Byte[] buf = Shape.Textures.GetBytes(); Primitive.TextureEntry tex = new Primitive.TextureEntry(buf, 0, buf.Length); Color4 texcolor; -- cgit v1.1 From b863a15a820be7c3b86b27ef24944d6a85fa5360 Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Fri, 17 Aug 2012 15:09:52 +0100 Subject: single operation for PRIM_COLOR --- OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | 49 ++++++++++++++++++++++ .../Shared/Api/Implementation/LSL_Api.cs | 3 +- 2 files changed, 50 insertions(+), 2 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index 0535dcb..6741e5e 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -2896,6 +2896,55 @@ namespace OpenSim.Region.Framework.Scenes } /// + /// Set the color & alpha of prim faces + /// + /// + /// + /// + public void SetFaceColorAlpha(int face, Vector3 color, double alpha) + { + // The only way to get a deep copy/ If we don't do this, we can + // never detect color changes further down. + Byte[] buf = Shape.Textures.GetBytes(); + Primitive.TextureEntry tex = new Primitive.TextureEntry(buf, 0, buf.Length); + Color4 texcolor; + if (face >= 0 && face < GetNumberOfSides()) + { + texcolor = tex.CreateFace((uint)face).RGBA; + texcolor.R = Util.Clip((float)color.X, 0.0f, 1.0f); + texcolor.G = Util.Clip((float)color.Y, 0.0f, 1.0f); + texcolor.B = Util.Clip((float)color.Z, 0.0f, 1.0f); + texcolor.A = Util.Clip((float)alpha, 0.0f, 1.0f); + tex.FaceTextures[face].RGBA = texcolor; + UpdateTextureEntry(tex.GetBytes()); + return; + } + else if (face == ALL_SIDES) + { + for (uint i = 0; i < GetNumberOfSides(); i++) + { + if (tex.FaceTextures[i] != null) + { + texcolor = tex.FaceTextures[i].RGBA; + texcolor.R = Util.Clip((float)color.X, 0.0f, 1.0f); + texcolor.G = Util.Clip((float)color.Y, 0.0f, 1.0f); + texcolor.B = Util.Clip((float)color.Z, 0.0f, 1.0f); + texcolor.A = Util.Clip((float)alpha, 0.0f, 1.0f); + tex.FaceTextures[i].RGBA = texcolor; + } + texcolor = tex.DefaultTexture.RGBA; + texcolor.R = Util.Clip((float)color.X, 0.0f, 1.0f); + texcolor.G = Util.Clip((float)color.Y, 0.0f, 1.0f); + texcolor.B = Util.Clip((float)color.Z, 0.0f, 1.0f); + texcolor.A = Util.Clip((float)alpha, 0.0f, 1.0f); + tex.DefaultTexture.RGBA = texcolor; + } + UpdateTextureEntry(tex.GetBytes()); + return; + } + } + + /// /// Get the number of sides that this part has. /// /// diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 4645e7a..dbbfbd3 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -7484,8 +7484,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api LSL_Vector color=rules.GetVector3Item(idx++); double alpha=(double)rules.GetLSLFloatItem(idx++); - part.SetFaceColor(color, face); - SetAlpha(part, alpha, face); + part.SetFaceColorAlpha(face, new Vector3((float)color.x, (float)color.y, (float)color.z), alpha); break; -- cgit v1.1 From ede3b9ab07dc1ed4a51684b7257cbb4d76e9bdfd Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Mon, 20 Aug 2012 09:26:26 +0100 Subject: making use of implicit operators and Util.Clip handling of Vector3 --- OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | 47 ++++++++++++---------- .../Shared/Api/Implementation/LSL_Api.cs | 2 +- 2 files changed, 27 insertions(+), 22 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index 6741e5e..098b2d9 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -2857,6 +2857,8 @@ namespace OpenSim.Region.Framework.Scenes /// public void SetFaceColor(Vector3 color, int face) { + Vector3 clippedColor = Util.Clip(color, 0.0f, 1.0f); + // The only way to get a deep copy/ If we don't do this, we can // never detect color changes further down. Byte[] buf = Shape.Textures.GetBytes(); @@ -2865,9 +2867,9 @@ namespace OpenSim.Region.Framework.Scenes if (face >= 0 && face < GetNumberOfSides()) { texcolor = tex.CreateFace((uint)face).RGBA; - texcolor.R = Util.Clip((float)color.X, 0.0f, 1.0f); - texcolor.G = Util.Clip((float)color.Y, 0.0f, 1.0f); - texcolor.B = Util.Clip((float)color.Z, 0.0f, 1.0f); + texcolor.R = clippedColor.X; + texcolor.G = clippedColor.Y; + texcolor.B = clippedColor.Z; tex.FaceTextures[face].RGBA = texcolor; UpdateTextureEntry(tex.GetBytes()); return; @@ -2879,15 +2881,15 @@ namespace OpenSim.Region.Framework.Scenes if (tex.FaceTextures[i] != null) { texcolor = tex.FaceTextures[i].RGBA; - texcolor.R = Util.Clip((float)color.X, 0.0f, 1.0f); - texcolor.G = Util.Clip((float)color.Y, 0.0f, 1.0f); - texcolor.B = Util.Clip((float)color.Z, 0.0f, 1.0f); + texcolor.R = clippedColor.X; + texcolor.G = clippedColor.Y; + texcolor.B = clippedColor.Z; tex.FaceTextures[i].RGBA = texcolor; } texcolor = tex.DefaultTexture.RGBA; - texcolor.R = Util.Clip((float)color.X, 0.0f, 1.0f); - texcolor.G = Util.Clip((float)color.Y, 0.0f, 1.0f); - texcolor.B = Util.Clip((float)color.Z, 0.0f, 1.0f); + texcolor.R = clippedColor.X; + texcolor.G = clippedColor.Y; + texcolor.B = clippedColor.Z; tex.DefaultTexture.RGBA = texcolor; } UpdateTextureEntry(tex.GetBytes()); @@ -2903,6 +2905,9 @@ namespace OpenSim.Region.Framework.Scenes /// public void SetFaceColorAlpha(int face, Vector3 color, double alpha) { + Vector3 clippedColor = Util.Clip(color, 0.0f, 1.0f); + float clippedAlpha = Util.Clip((float)alpha, 0.0f, 1.0f); + // The only way to get a deep copy/ If we don't do this, we can // never detect color changes further down. Byte[] buf = Shape.Textures.GetBytes(); @@ -2911,10 +2916,10 @@ namespace OpenSim.Region.Framework.Scenes if (face >= 0 && face < GetNumberOfSides()) { texcolor = tex.CreateFace((uint)face).RGBA; - texcolor.R = Util.Clip((float)color.X, 0.0f, 1.0f); - texcolor.G = Util.Clip((float)color.Y, 0.0f, 1.0f); - texcolor.B = Util.Clip((float)color.Z, 0.0f, 1.0f); - texcolor.A = Util.Clip((float)alpha, 0.0f, 1.0f); + texcolor.R = clippedColor.X; + texcolor.G = clippedColor.Y; + texcolor.B = clippedColor.Z; + texcolor.A = clippedAlpha; tex.FaceTextures[face].RGBA = texcolor; UpdateTextureEntry(tex.GetBytes()); return; @@ -2926,17 +2931,17 @@ namespace OpenSim.Region.Framework.Scenes if (tex.FaceTextures[i] != null) { texcolor = tex.FaceTextures[i].RGBA; - texcolor.R = Util.Clip((float)color.X, 0.0f, 1.0f); - texcolor.G = Util.Clip((float)color.Y, 0.0f, 1.0f); - texcolor.B = Util.Clip((float)color.Z, 0.0f, 1.0f); - texcolor.A = Util.Clip((float)alpha, 0.0f, 1.0f); + texcolor.R = clippedColor.X; + texcolor.G = clippedColor.Y; + texcolor.B = clippedColor.Z; + texcolor.A = clippedAlpha; tex.FaceTextures[i].RGBA = texcolor; } texcolor = tex.DefaultTexture.RGBA; - texcolor.R = Util.Clip((float)color.X, 0.0f, 1.0f); - texcolor.G = Util.Clip((float)color.Y, 0.0f, 1.0f); - texcolor.B = Util.Clip((float)color.Z, 0.0f, 1.0f); - texcolor.A = Util.Clip((float)alpha, 0.0f, 1.0f); + texcolor.R = clippedColor.X; + texcolor.G = clippedColor.Y; + texcolor.B = clippedColor.Z; + texcolor.A = clippedAlpha; tex.DefaultTexture.RGBA = texcolor; } UpdateTextureEntry(tex.GetBytes()); diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index dbbfbd3..0cbb317 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -7484,7 +7484,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api LSL_Vector color=rules.GetVector3Item(idx++); double alpha=(double)rules.GetLSLFloatItem(idx++); - part.SetFaceColorAlpha(face, new Vector3((float)color.x, (float)color.y, (float)color.z), alpha); + part.SetFaceColorAlpha(face, color, alpha); break; -- cgit v1.1 From 481c00f50a1961ac77e800d64a68e9c30a4b69de Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Mon, 20 Aug 2012 09:31:29 +0100 Subject: refactoring out SetFaceColor --- OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | 67 +++++----------------- .../Shared/Api/Implementation/LSL_Api.cs | 4 +- 2 files changed, 17 insertions(+), 54 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index 098b2d9..2a9ee3a 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -2851,62 +2851,16 @@ namespace OpenSim.Region.Framework.Scenes } /// - /// Set the color of prim faces - /// - /// - /// - public void SetFaceColor(Vector3 color, int face) - { - Vector3 clippedColor = Util.Clip(color, 0.0f, 1.0f); - - // The only way to get a deep copy/ If we don't do this, we can - // never detect color changes further down. - Byte[] buf = Shape.Textures.GetBytes(); - Primitive.TextureEntry tex = new Primitive.TextureEntry(buf, 0, buf.Length); - Color4 texcolor; - if (face >= 0 && face < GetNumberOfSides()) - { - texcolor = tex.CreateFace((uint)face).RGBA; - texcolor.R = clippedColor.X; - texcolor.G = clippedColor.Y; - texcolor.B = clippedColor.Z; - tex.FaceTextures[face].RGBA = texcolor; - UpdateTextureEntry(tex.GetBytes()); - return; - } - else if (face == ALL_SIDES) - { - for (uint i = 0; i < GetNumberOfSides(); i++) - { - if (tex.FaceTextures[i] != null) - { - texcolor = tex.FaceTextures[i].RGBA; - texcolor.R = clippedColor.X; - texcolor.G = clippedColor.Y; - texcolor.B = clippedColor.Z; - tex.FaceTextures[i].RGBA = texcolor; - } - texcolor = tex.DefaultTexture.RGBA; - texcolor.R = clippedColor.X; - texcolor.G = clippedColor.Y; - texcolor.B = clippedColor.Z; - tex.DefaultTexture.RGBA = texcolor; - } - UpdateTextureEntry(tex.GetBytes()); - return; - } - } - - /// /// Set the color & alpha of prim faces /// /// /// /// - public void SetFaceColorAlpha(int face, Vector3 color, double alpha) + public void SetFaceColorAlpha(int face, Vector3 color, double ?alpha) { Vector3 clippedColor = Util.Clip(color, 0.0f, 1.0f); - float clippedAlpha = Util.Clip((float)alpha, 0.0f, 1.0f); + float clippedAlpha = alpha.HasValue ? + Util.Clip((float)alpha.Value, 0.0f, 1.0f) : 0; // The only way to get a deep copy/ If we don't do this, we can // never detect color changes further down. @@ -2919,7 +2873,10 @@ namespace OpenSim.Region.Framework.Scenes texcolor.R = clippedColor.X; texcolor.G = clippedColor.Y; texcolor.B = clippedColor.Z; - texcolor.A = clippedAlpha; + if (alpha.HasValue) + { + texcolor.A = clippedAlpha; + } tex.FaceTextures[face].RGBA = texcolor; UpdateTextureEntry(tex.GetBytes()); return; @@ -2934,14 +2891,20 @@ namespace OpenSim.Region.Framework.Scenes texcolor.R = clippedColor.X; texcolor.G = clippedColor.Y; texcolor.B = clippedColor.Z; - texcolor.A = clippedAlpha; + if (alpha.HasValue) + { + texcolor.A = clippedAlpha; + } tex.FaceTextures[i].RGBA = texcolor; } texcolor = tex.DefaultTexture.RGBA; texcolor.R = clippedColor.X; texcolor.G = clippedColor.Y; texcolor.B = clippedColor.Z; - texcolor.A = clippedAlpha; + if (alpha.HasValue) + { + texcolor.A = clippedAlpha; + } tex.DefaultTexture.RGBA = texcolor; } UpdateTextureEntry(tex.GetBytes()); diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 0cbb317..8140416 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -1377,7 +1377,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (face == ScriptBaseClass.ALL_SIDES) face = SceneObjectPart.ALL_SIDES; - m_host.SetFaceColor(color, face); + m_host.SetFaceColorAlpha(face, color, null); } public void SetTexGen(SceneObjectPart part, int face,int style) @@ -3572,7 +3572,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api List parts = GetLinkParts(linknumber); foreach (SceneObjectPart part in parts) - part.SetFaceColor(color, face); + part.SetFaceColorAlpha(face, color, null); } public void llCreateLink(string target, int parent) -- cgit v1.1 From 9925317239b9b7cfe90d682aaf4657cb70ff3b7d Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Tue, 21 Aug 2012 22:21:35 +0100 Subject: Fix bug in SoundModule.PlayAttachedSound() where every sound update to an avatar would base its gain calculation on the previous avatar's gain, instead of the original input gain This is similar to commit d89faa which fixed the same kind of bug in TriggerSound() --- OpenSim/Region/CoreModules/World/Sound/SoundModule.cs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/World/Sound/SoundModule.cs b/OpenSim/Region/CoreModules/World/Sound/SoundModule.cs index 14c1a39..a2f0950 100644 --- a/OpenSim/Region/CoreModules/World/Sound/SoundModule.cs +++ b/OpenSim/Region/CoreModules/World/Sound/SoundModule.cs @@ -85,13 +85,15 @@ namespace OpenSim.Region.CoreModules.World.Sound dis = 0; } + float thisSpGain; + // Scale by distance if (radius == 0) - gain = (float)((double)gain * ((100.0 - dis) / 100.0)); + thisSpGain = (float)((double)gain * ((100.0 - dis) / 100.0)); else - gain = (float)((double)gain * ((radius - dis) / radius)); + thisSpGain = (float)((double)gain * ((radius - dis) / radius)); - sp.ControllingClient.SendPlayAttachedSound(soundID, objectID, ownerID, (float)gain, flags); + sp.ControllingClient.SendPlayAttachedSound(soundID, objectID, ownerID, thisSpGain, flags); }); } -- cgit v1.1 From 1369058280c4cf399d46df1508b80cad99f1247e Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Wed, 22 Aug 2012 23:04:17 +0100 Subject: Lock disposal of separate gdi+ objects under different threads since this prevents malloc heap corruption seen under Ubuntu 10.04.1 and 11.04 - probably a libcairo issue In testing, it appears that if multiple threads dispose of separate GDI+ objects simultaneously, the native malloc heap can become corrupted, possibly due to a double free(). This may be due to bugs in the underlying libcairo used by mono's libgdiplus.dll on Linux/OSX. These problems were seen with both libcario 1.10.2-6.1ubuntu3 and 1.8.10-2ubuntu1. They go away if disposal is perfomed under lock. --- .../Scripting/VectorRender/VectorRenderModule.cs | 68 +++++++++++++--------- 1 file changed, 42 insertions(+), 26 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs b/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs index ca320e1..c48a703 100644 --- a/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs +++ b/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs @@ -308,36 +308,44 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender try { - if (alpha == 256) - bitmap = new Bitmap(width, height, PixelFormat.Format32bppRgb); - else - bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); - - graph = Graphics.FromImage(bitmap); - - // this is really just to save people filling the - // background color in their scripts, only do when fully opaque - if (alpha >= 255) + // XXX: In testing, it appears that if multiple threads dispose of separate GDI+ objects simultaneously, + // the native malloc heap can become corrupted, possibly due to a double free(). This may be due to + // bugs in the underlying libcairo used by mono's libgdiplus.dll on Linux/OSX. These problems were + // seen with both libcario 1.10.2-6.1ubuntu3 and 1.8.10-2ubuntu1. They go away if disposal is perfomed + // under lock. + lock (this) { - using (SolidBrush bgFillBrush = new SolidBrush(bgColor)) + if (alpha == 256) + bitmap = new Bitmap(width, height, PixelFormat.Format32bppRgb); + else + bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); + + graph = Graphics.FromImage(bitmap); + + // this is really just to save people filling the + // background color in their scripts, only do when fully opaque + if (alpha >= 255) { - graph.FillRectangle(bgFillBrush, 0, 0, width, height); + using (SolidBrush bgFillBrush = new SolidBrush(bgColor)) + { + graph.FillRectangle(bgFillBrush, 0, 0, width, height); + } } - } - - for (int w = 0; w < bitmap.Width; w++) - { - if (alpha <= 255) + + for (int w = 0; w < bitmap.Width; w++) { - for (int h = 0; h < bitmap.Height; h++) + if (alpha <= 255) { - bitmap.SetPixel(w, h, Color.FromArgb(alpha, bitmap.GetPixel(w, h))); + for (int h = 0; h < bitmap.Height; h++) + { + bitmap.SetPixel(w, h, Color.FromArgb(alpha, bitmap.GetPixel(w, h))); + } } } + + GDIDraw(data, graph, altDataDelim); } - GDIDraw(data, graph, altDataDelim); - byte[] imageJ2000 = new byte[0]; try @@ -355,11 +363,19 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender } finally { - if (graph != null) - graph.Dispose(); - - if (bitmap != null) - bitmap.Dispose(); + // XXX: In testing, it appears that if multiple threads dispose of separate GDI+ objects simultaneously, + // the native malloc heap can become corrupted, possibly due to a double free(). This may be due to + // bugs in the underlying libcairo used by mono's libgdiplus.dll on Linux/OSX. These problems were + // seen with both libcario 1.10.2-6.1ubuntu3 and 1.8.10-2ubuntu1. They go away if disposal is perfomed + // under lock. + lock (this) + { + if (graph != null) + graph.Dispose(); + + if (bitmap != null) + bitmap.Dispose(); + } } } -- cgit v1.1 From 4820dfd733a5b6dae54e120cfb1486643765bb3e Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Tue, 21 Aug 2012 12:30:47 +0100 Subject: this should be an if-else block in case the non-phys min/max are smaller than the physical min/max --- .../Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 12 +++++++----- 1 file changed, 7 insertions(+), 5 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 8140416..0d275f7 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -1341,11 +1341,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api scale.y = Math.Max(World.m_minPhys, Math.Min(World.m_maxPhys, scale.y)); scale.z = Math.Max(World.m_minPhys, Math.Min(World.m_maxPhys, scale.z)); } - - // Next we clamp the scale to the non-physical min/max - scale.x = Math.Max(World.m_minNonphys, Math.Min(World.m_maxNonphys, scale.x)); - scale.y = Math.Max(World.m_minNonphys, Math.Min(World.m_maxNonphys, scale.y)); - scale.z = Math.Max(World.m_minNonphys, Math.Min(World.m_maxNonphys, scale.z)); + else + { + // If not physical, then we clamp the scale to the non-physical min/max + scale.x = Math.Max(World.m_minNonphys, Math.Min(World.m_maxNonphys, scale.x)); + scale.y = Math.Max(World.m_minNonphys, Math.Min(World.m_maxNonphys, scale.y)); + scale.z = Math.Max(World.m_minNonphys, Math.Min(World.m_maxNonphys, scale.z)); + } Vector3 tmp = part.Scale; tmp.X = (float)scale.x; -- cgit v1.1 From aede42b87559aa1f8f3197b53b9bf5c2b547701a Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Thu, 23 Aug 2012 23:13:53 +0100 Subject: If a script state save fails for some reason on shutdown/region removal, get xengine to spit out some useful information and continue to save other script states --- OpenSim/Region/ScriptEngine/XEngine/XEngine.cs | 27 ++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs index 53f899a..5a3f002 100644 --- a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs +++ b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs @@ -589,7 +589,19 @@ namespace OpenSim.Region.ScriptEngine.XEngine if (m_Assemblies.ContainsKey(instance.AssetID)) { string assembly = m_Assemblies[instance.AssetID]; - instance.SaveState(assembly); + + try + { + instance.SaveState(assembly); + } + catch (Exception e) + { + m_log.Error( + string.Format( + "[XEngine]: Failed final state save for script {0}.{1}, item UUID {2}, prim UUID {3} in {4}. Exception ", + instance.PrimName, instance.ScriptName, instance.ItemID, instance.ObjectID, World.Name) + , e); + } } // Clear the event queue and abort the instance thread @@ -707,7 +719,18 @@ namespace OpenSim.Region.ScriptEngine.XEngine assembly = m_Assemblies[i.AssetID]; } - i.SaveState(assembly); + try + { + i.SaveState(assembly); + } + catch (Exception e) + { + m_log.Error( + string.Format( + "[XEngine]: Failed to save state of script {0}.{1}, item UUID {2}, prim UUID {3} in {4}. Exception ", + i.PrimName, i.ScriptName, i.ItemID, i.ObjectID, World.Name) + , e); + } } instances.Clear(); -- cgit v1.1 From 4f3fabae5bec8a71f9953ef9f4c247e086e4757f Mon Sep 17 00:00:00 2001 From: TBG Renfold Date: Thu, 9 Aug 2012 18:03:26 +0100 Subject: Adds osGetHealth. Returns the amount of health (in an integer) that an avatar has left in the scene. If an avatar is not found or safe is enabled on a region, -1 is returned. Example usage: default { touch_end(integer _t) { key agentID = llDetectedKey(0); osCauseDamage(agentID, 50); llSay(0, llKey2Name(agentID) + " has " + (string)osGetHealth(agentID) + "% health left."); } } --- .../Shared/Api/Implementation/OSSL_Api.cs | 21 +++++++++++++++++++++ .../ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs | 1 + .../ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs | 7 ++++++- 3 files changed, 28 insertions(+), 1 deletion(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs index 1e8b51b..3d233d7 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs @@ -2895,6 +2895,27 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } }); } + + public LSL_Float osGetHealth(string avatar) + { + CheckThreatLevel(ThreatLevel.None, "osGetHealth"); + m_host.AddScriptLPS(1); + + UUID avatarId = new UUID(avatar); + Vector3 pos = m_host.GetWorldPosition(); + + LSL_Float health = new LSL_Float(-1); + ScenePresence presence = World.GetScenePresence(avatarId); + if (presence != null) + { + LandData land = World.GetLandData((float)pos.X, (float)pos.Y); + if ((land.Flags & (uint)ParcelFlags.AllowDamage) == (uint)ParcelFlags.AllowDamage) + { + health = presence.Health; + } + } + return health; + } public void osCauseDamage(string avatar, double damage) { diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs index 1f000a3..9ad1c22 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs @@ -258,6 +258,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces int osGetSimulatorMemory(); void osKickAvatar(string FirstName,string SurName,string alert); void osSetSpeed(string UUID, LSL_Float SpeedModifier); + LSL_Float osGetHealth(string avatar); void osCauseHealing(string avatar, double healing); void osCauseDamage(string avatar, double damage); LSL_List osGetPrimitiveParams(LSL_Key prim, LSL_List rules); diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs index 94405d2..e9131e4 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs @@ -865,7 +865,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase { m_OSSL_Functions.osSetSpeed(UUID, SpeedModifier); } - + + public LSL_Float osGetHealth(string avatar) + { + return m_OSSL_Functions.osGetHealth(avatar); + } + public void osCauseDamage(string avatar, double damage) { m_OSSL_Functions.osCauseDamage(avatar, damage); -- cgit v1.1 From a3cbda0d74a14c05acf04adaaa5b9ff30c6d9fa5 Mon Sep 17 00:00:00 2001 From: TBG Renfold Date: Fri, 10 Aug 2012 01:29:41 +0100 Subject: Removed land checking as suggested by SignpostMarv. Now whatever remaining health the avatar has is displayed (float). This will be 100% (100.000000) if no damage has occurred (as what the viewer should really be seeing anyway). Returns -1.000000 if the avatar is not found. --- .../ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs index 3d233d7..5e7c2d9 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs @@ -2901,19 +2901,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api CheckThreatLevel(ThreatLevel.None, "osGetHealth"); m_host.AddScriptLPS(1); - UUID avatarId = new UUID(avatar); - Vector3 pos = m_host.GetWorldPosition(); - LSL_Float health = new LSL_Float(-1); - ScenePresence presence = World.GetScenePresence(avatarId); - if (presence != null) - { - LandData land = World.GetLandData((float)pos.X, (float)pos.Y); - if ((land.Flags & (uint)ParcelFlags.AllowDamage) == (uint)ParcelFlags.AllowDamage) - { - health = presence.Health; - } - } + ScenePresence presence = World.GetScenePresence(new UUID(avatar)); + if (presence != null) health = presence.Health; return health; } -- cgit v1.1 From c55768466626336849c650349b335365c41359e5 Mon Sep 17 00:00:00 2001 From: Melanie Date: Fri, 24 Aug 2012 00:15:30 +0100 Subject: Fix bad child prim permissions that can make objects change perms after rezzing Port from Avination --- OpenSim/Region/Framework/Scenes/Scene.Inventory.cs | 3 +++ OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs | 18 +++++++++++++++--- OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | 21 +++++++++++++++++++++ 3 files changed, 39 insertions(+), 3 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs index 7e31d60..675c64d 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs @@ -1943,6 +1943,9 @@ namespace OpenSim.Region.Framework.Scenes deleteIDs.Add(localID); deleteGroups.Add(grp); + // If child prims have invalid perms, fix them + grp.AdjustChildPrimPermissions(); + if (remoteClient == null) { // Autoreturn has a null client. Nothing else does. So diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index f6c725b..b4a155e 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -2131,6 +2131,9 @@ namespace OpenSim.Region.Framework.Scenes // Can't do this yet since backup still makes use of the root part without any synchronization // objectGroup.m_rootPart = null; + // If linking prims with different permissions, fix them + AdjustChildPrimPermissions(); + AttachToBackup(); // Here's the deal, this is ABSOLUTELY CRITICAL so the physics scene gets the update about the @@ -2622,12 +2625,21 @@ namespace OpenSim.Region.Framework.Scenes } } + public void AdjustChildPrimPermissions() + { + ForEachPart(part => + { + if (part != RootPart) + part.ClonePermissions(RootPart); + }); + } + public void UpdatePermissions(UUID AgentID, byte field, uint localID, uint mask, byte addRemTF) { - SceneObjectPart[] parts = m_parts.GetArray(); - for (int i = 0; i < parts.Length; i++) - parts[i].UpdatePermissions(AgentID, field, localID, mask, addRemTF); + RootPart.UpdatePermissions(AgentID, field, localID, mask, addRemTF); + + AdjustChildPrimPermissions(); HasGroupChanged = true; diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index 2a9ee3a..411dcc7 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -3890,6 +3890,27 @@ namespace OpenSim.Region.Framework.Scenes } } + public void ClonePermissions(SceneObjectPart source) + { + bool update = false; + + if (BaseMask != source.BaseMask || + OwnerMask != source.OwnerMask || + GroupMask != source.GroupMask || + EveryoneMask != source.EveryoneMask || + NextOwnerMask != source.NextOwnerMask) + update = true; + + BaseMask = source.BaseMask; + OwnerMask = source.OwnerMask; + GroupMask = source.GroupMask; + EveryoneMask = source.EveryoneMask; + NextOwnerMask = source.NextOwnerMask; + + if (update) + SendFullUpdateToAllClients(); + } + public bool IsHingeJoint() { // For now, we use the NINJA naming scheme for identifying joints. -- cgit v1.1 From 2ad9d656b3a1a0c519c9599d7680f98eba7e82b8 Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Fri, 10 Aug 2012 15:58:29 +0100 Subject: implementing function to allow scripts to self-replicate as if the owner duplicated them, using the same script delay as llRezObject() --- .../Shared/Api/Implementation/OSSL_Api.cs | 50 ++++++++++++++++++++++ .../ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs | 7 +++ .../ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs | 5 +++ 3 files changed, 62 insertions(+) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs index 5e7c2d9..119c2ac 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs @@ -3344,5 +3344,55 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api return new LSL_Key(m_host.ParentGroup.FromPartID.ToString()); } + + public void osRezDuplicate(LSL_Vector offset, LSL_Rotation rot) + { + CheckThreatLevel(ThreatLevel.High, "osRezDuplicate"); + m_host.AddScriptLPS(1); + + Vector3 v = new Vector3((float)offset.x, (float)offset.y, (float)offset.z); + Quaternion r = new Quaternion( + (float)rot.x, + (float)rot.y, + (float)rot.z, + (float)rot.s + ); + + Vector3 destination = m_host.ParentGroup.AbsolutePosition + v; + + if (!World.Permissions.CanRezObject( + m_host.ParentGroup.PrimCount, + m_host.OwnerID, + destination + )) + { + OSSLShoutError("Cannot duplicate object to destination, owner cannot rez objects at destination parcel."); + + ScriptSleep(100); + } + else + { + SceneObjectGroup duplicate = World.SceneGraph.DuplicateObject( + m_host.ParentGroup.LocalId, + v, + m_host.ParentGroup.RootPart.GetEffectiveObjectFlags(), + m_host.OwnerID, + m_host.GroupID, + r + ); + + m_ScriptEngine.PostObjectEvent(m_host.LocalId, new EventParams( + "object_rez", new Object[] { + new LSL_String( + duplicate.RootPart.UUID.ToString()) }, + new DetectParams[0])); + + ScriptSleep(100); + m_ScriptEngine.PostObjectEvent(duplicate.LocalId, new EventParams( + "on_rez", new Object[]{ + new LSL_Integer(0)}, + new DetectParams[0])); + } + } } } \ No newline at end of file diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs index 9ad1c22..8c90df4 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs @@ -306,5 +306,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces /// /// Rezzing object key or NULL_KEY if rezzed by agent or otherwise unknown. LSL_Key osGetRezzingObject(); + + /// + /// Duplicates an object as if the owner duplicated it. + /// + /// + /// + void osRezDuplicate(vector offset, rotation rot); } } diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs index e9131e4..9a2f859 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs @@ -955,5 +955,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase { return m_OSSL_Functions.osGetRezzingObject(); } + + public void osRezDuplicate(vector offset, rotation rot) + { + m_OSSL_Functions.osRezDuplicate(offset, rot); + } } } -- cgit v1.1 From a08687aef35079f6c2884d3ae6fd8307ca8a6b0d Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 24 Aug 2012 01:18:35 +0100 Subject: Revert "implementing function to allow scripts to self-replicate as if the owner duplicated them, using the same script delay as llRezObject()" This reverts commit 2ad9d656b3a1a0c519c9599d7680f98eba7e82b8. Reverted pending consideration of associated issues. --- .../Shared/Api/Implementation/OSSL_Api.cs | 50 ---------------------- .../ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs | 7 --- .../ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs | 5 --- 3 files changed, 62 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs index 119c2ac..5e7c2d9 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs @@ -3344,55 +3344,5 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api return new LSL_Key(m_host.ParentGroup.FromPartID.ToString()); } - - public void osRezDuplicate(LSL_Vector offset, LSL_Rotation rot) - { - CheckThreatLevel(ThreatLevel.High, "osRezDuplicate"); - m_host.AddScriptLPS(1); - - Vector3 v = new Vector3((float)offset.x, (float)offset.y, (float)offset.z); - Quaternion r = new Quaternion( - (float)rot.x, - (float)rot.y, - (float)rot.z, - (float)rot.s - ); - - Vector3 destination = m_host.ParentGroup.AbsolutePosition + v; - - if (!World.Permissions.CanRezObject( - m_host.ParentGroup.PrimCount, - m_host.OwnerID, - destination - )) - { - OSSLShoutError("Cannot duplicate object to destination, owner cannot rez objects at destination parcel."); - - ScriptSleep(100); - } - else - { - SceneObjectGroup duplicate = World.SceneGraph.DuplicateObject( - m_host.ParentGroup.LocalId, - v, - m_host.ParentGroup.RootPart.GetEffectiveObjectFlags(), - m_host.OwnerID, - m_host.GroupID, - r - ); - - m_ScriptEngine.PostObjectEvent(m_host.LocalId, new EventParams( - "object_rez", new Object[] { - new LSL_String( - duplicate.RootPart.UUID.ToString()) }, - new DetectParams[0])); - - ScriptSleep(100); - m_ScriptEngine.PostObjectEvent(duplicate.LocalId, new EventParams( - "on_rez", new Object[]{ - new LSL_Integer(0)}, - new DetectParams[0])); - } - } } } \ No newline at end of file diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs index 8c90df4..9ad1c22 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs @@ -306,12 +306,5 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces /// /// Rezzing object key or NULL_KEY if rezzed by agent or otherwise unknown. LSL_Key osGetRezzingObject(); - - /// - /// Duplicates an object as if the owner duplicated it. - /// - /// - /// - void osRezDuplicate(vector offset, rotation rot); } } diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs index 9a2f859..e9131e4 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs @@ -955,10 +955,5 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase { return m_OSSL_Functions.osGetRezzingObject(); } - - public void osRezDuplicate(vector offset, rotation rot) - { - m_OSSL_Functions.osRezDuplicate(offset, rot); - } } } -- cgit v1.1 From d188272462f2c8d3e67aead26bb5b15ab243cdab Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Fri, 24 Aug 2012 13:52:30 +0100 Subject: refactoring using List.ConvertAll --- .../Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 11 +++++------ 1 file changed, 5 insertions(+), 6 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 0d275f7..a98fb04 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -5170,17 +5170,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { string ret = String.Empty; - int x = 0; m_host.AddScriptLPS(1); if (src.Data.Length > 0) { - ret = src.Data[x++].ToString(); - for (; x < src.Data.Length; x++) - { - ret += ", "+src.Data[x].ToString(); - } + ret = string.Join(", ", + (new List(src.Data)).ConvertAll(o => + { + return o.ToString(); + }).ToArray()); } return ret; -- cgit v1.1 From 582a256646d1093b2c8889d89dbaa88f1c5fc81d Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Fri, 24 Aug 2012 13:53:53 +0100 Subject: immediately returning the string.Join operation instead of checking if the list has members --- .../ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 16 +++++----------- 1 file changed, 5 insertions(+), 11 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 a98fb04..bbbc6cc 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -5169,20 +5169,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public LSL_String llList2CSV(LSL_List src) { - string ret = String.Empty; m_host.AddScriptLPS(1); - if (src.Data.Length > 0) - { - ret = string.Join(", ", - (new List(src.Data)).ConvertAll(o => - { - return o.ToString(); - }).ToArray()); - } - - return ret; + return string.Join(", ", + (new List(src.Data)).ConvertAll(o => + { + return o.ToString(); + }).ToArray()); } /// -- cgit v1.1 From 67477290ad34f7350495c2787022eed5d1d535d8 Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Fri, 24 Aug 2012 13:56:42 +0100 Subject: stripping superfluous whitespace Signed-off-by: Melanie --- OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 3 --- 1 file changed, 3 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 bbbc6cc..2bfb9b3 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -5165,11 +5165,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api /// separated list. There is a space after /// each comma. /// - public LSL_String llList2CSV(LSL_List src) { - - m_host.AddScriptLPS(1); return string.Join(", ", -- cgit v1.1 From cd325fdf021be20876340c85201efbd8e918028a Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 24 Aug 2012 21:36:20 +0100 Subject: Pass the "attachToBackup" bool given to SceneGraph.AddNewSceneObject() down into the 3-parameter AddNewSceneObject() method instead of always hardcoding true. This doesn't affect any core OpenSimulator code since all callers were passing true anyway But it allows region modules to create objects that are never persisted. --- OpenSim/Region/Framework/Scenes/SceneGraph.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs index b6339fb..209a770 100644 --- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs +++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs @@ -300,7 +300,7 @@ namespace OpenSim.Region.Framework.Scenes public bool AddNewSceneObject( SceneObjectGroup sceneObject, bool attachToBackup, Vector3? pos, Quaternion? rot, Vector3 vel) { - AddNewSceneObject(sceneObject, true, false); + AddNewSceneObject(sceneObject, attachToBackup, false); if (pos != null) sceneObject.AbsolutePosition = (Vector3)pos; -- cgit v1.1 From 476996bee86702227eedd3c953000891027faac4 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 24 Aug 2012 22:38:07 +0100 Subject: If a connecting scene presence is replacing an existing scene presence then bypass close checks. --- OpenSim/Region/Framework/Scenes/Scene.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index ad74189..2b4dea4 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -3562,7 +3562,7 @@ namespace OpenSim.Region.Framework.Scenes "[SCENE]: Existing root scene presence detected for {0} {1} in {2} when connecting. Removing existing presence.", sp.Name, sp.UUID, RegionInfo.RegionName); - sp.ControllingClient.Close(); + sp.ControllingClient.Close(true); sp = null; } -- cgit v1.1 From ba58331b29225ead620087ca4ff3bae4a905994d Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 24 Aug 2012 22:56:05 +0100 Subject: Extend "Restarting scripts in attachments" debug log message to show actual name of user and the region they are in --- OpenSim/Region/Framework/Scenes/ScenePresence.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index 65d526f..5bf69ad 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -891,7 +891,9 @@ namespace OpenSim.Region.Framework.Scenes { if (wasChild && HasAttachments()) { - m_log.DebugFormat("[SCENE PRESENCE]: Restarting scripts in attachments..."); + m_log.DebugFormat( + "[SCENE PRESENCE]: Restarting scripts in attachments for {0} in {1}", Name, Scene.Name); + // Resume scripts foreach (SceneObjectGroup sog in m_attachments) { -- cgit v1.1 From f3a5e3a02b5422fad607695aac0bffd17152434b Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Sat, 25 Aug 2012 00:42:32 +0100 Subject: Log initial script startup info notice when xengine actually starts to do this for debugging purposes, rather than before it actually starts to do this. --- OpenSim/Region/Framework/Scenes/Scene.Inventory.cs | 2 +- OpenSim/Region/ScriptEngine/XEngine/XEngine.cs | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs index 675c64d..3b59dc4 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs @@ -93,7 +93,7 @@ namespace OpenSim.Region.Framework.Scenes /// public void StartScripts() { - m_log.InfoFormat("[SCENE]: Starting scripts in {0}, please wait.", RegionInfo.RegionName); +// m_log.InfoFormat("[SCENE]: Starting scripts in {0}, please wait.", RegionInfo.RegionName); IScriptModule[] engines = RequestModuleInterfaces(); diff --git a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs index 5a3f002..0460f22 100644 --- a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs +++ b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs @@ -923,6 +923,8 @@ namespace OpenSim.Region.ScriptEngine.XEngine // This delay exists to stop mono problems where script compilation and startup would stop the sim // working properly for the session. System.Threading.Thread.Sleep(m_StartDelay); + + m_log.InfoFormat("[XEngine]: Performing initial script startup on {0}", m_Scene.Name); } object[] o; @@ -938,13 +940,13 @@ namespace OpenSim.Region.ScriptEngine.XEngine if (m_InitialStartup) if (scriptsStarted % 50 == 0) m_log.InfoFormat( - "[XEngine]: Started {0} scripts in {1}", scriptsStarted, m_Scene.RegionInfo.RegionName); + "[XEngine]: Started {0} scripts in {1}", scriptsStarted, m_Scene.Name); } } if (m_InitialStartup) m_log.InfoFormat( - "[XEngine]: Completed starting {0} scripts on {1}", scriptsStarted, m_Scene.RegionInfo.RegionName); + "[XEngine]: Completed starting {0} scripts on {1}", scriptsStarted, m_Scene.Name); // NOTE: Despite having a lockless queue, this lock is required // to make sure there is never no compile thread while there -- cgit v1.1 From e04047152f2d3ea7f52f746ab2ddac3328c8e97d Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Sat, 25 Aug 2012 00:49:38 +0100 Subject: minor: Fix bad log message for failure to create an inventory folder --- OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs b/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs index 2701d6e..6e53951 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs @@ -468,7 +468,7 @@ namespace OpenSim.Region.Framework.Scenes if (!InventoryService.AddFolder(folder)) { m_log.WarnFormat( - "[AGENT INVENTORY]: Failed to move create folder for user {0} {1}", + "[AGENT INVENTORY]: Failed to create folder for user {0} {1}", remoteClient.Name, remoteClient.AgentId); } } -- cgit v1.1 From 3d504261b0e189f8111912a3fff9d45579c04eed Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Fri, 24 Aug 2012 16:35:59 +0100 Subject: renaming to be similar to equivalent Set command --- .../Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 10 +++++----- .../Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs | 4 ++-- OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs | 2 +- 3 files changed, 8 insertions(+), 8 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 2bfb9b3..c706f48 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -7910,7 +7910,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public LSL_List llGetPrimitiveParams(LSL_List rules) { m_host.AddScriptLPS(1); - return GetLinkPrimitiveParams(m_host, rules); + return GetPrimParams(m_host, rules); } public LSL_List llGetLinkPrimitiveParams(int linknumber, LSL_List rules) @@ -7923,14 +7923,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api foreach (var part in parts) { - LSL_List partRes = GetLinkPrimitiveParams(part, rules); + LSL_List partRes = GetPrimParams(part, rules); res += partRes; } return res; } - public LSL_List GetLinkPrimitiveParams(SceneObjectPart part, LSL_List rules) + public LSL_List GetPrimParams(SceneObjectPart part, LSL_List rules) { LSL_List res = new LSL_List(); int idx=0; @@ -10752,7 +10752,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } } - public LSL_List GetLinkPrimitiveParamsEx(LSL_Key prim, LSL_List rules) + public LSL_List GetPrimitiveParamsEx(LSL_Key prim, LSL_List rules) { SceneObjectPart obj = World.GetSceneObjectPart(new UUID(prim)); if (obj == null) @@ -10761,7 +10761,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (obj.OwnerID != m_host.OwnerID) return new LSL_List(); - return GetLinkPrimitiveParams(obj, rules); + return GetPrimParams(obj, rules); } public void print(string str) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs index 5e7c2d9..c277708 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs @@ -2250,7 +2250,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api List parts = ((LSL_Api)m_LSL_Api).GetLinkParts(linknumber); foreach (SceneObjectPart part in parts) { - retVal += ((LSL_Api)m_LSL_Api).GetLinkPrimitiveParams(part, rules); + retVal += ((LSL_Api)m_LSL_Api).GetPrimParams(part, rules); } return retVal; } @@ -2965,7 +2965,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api m_host.AddScriptLPS(1); InitLSL(); - return m_LSL_Api.GetLinkPrimitiveParamsEx(prim, rules); + return m_LSL_Api.GetPrimitiveParamsEx(prim, rules); } public void osSetPrimitiveParams(LSL_Key prim, LSL_List rules) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs index 3fb463b..cd58614 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs @@ -425,6 +425,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces void print(string str); void SetPrimitiveParamsEx(LSL_Key prim, LSL_List rules); - LSL_List GetLinkPrimitiveParamsEx(LSL_Key prim, LSL_List rules); + LSL_List GetPrimitiveParamsEx(LSL_Key prim, LSL_List rules); } } -- cgit v1.1 From a8044999fb056de0a815093953f82b33d540dd6f Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Fri, 24 Aug 2012 16:41:43 +0100 Subject: use SceneObjectPart instead of var --- OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 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 c706f48..03b5982 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -5828,7 +5828,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api List parts = GetLinkParts(linknumber); - foreach (var part in parts) + foreach (SceneObjectPart part in parts) { SetTextureAnim(part, mode, face, sizex, sizey, start, length, rate); } @@ -6190,7 +6190,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api List parts = GetLinkParts(linknumber); - foreach (var part in parts) + foreach (SceneObjectPart part in parts) { SetParticleSystem(part, rules); } @@ -7921,7 +7921,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api LSL_List res = new LSL_List(); - foreach (var part in parts) + foreach (SceneObjectPart part in parts) { LSL_List partRes = GetPrimParams(part, rules); res += partRes; -- cgit v1.1 From 2a2e120470ea530ea0a6f035c5cf28247f94532c Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Fri, 24 Aug 2012 17:02:13 +0100 Subject: since we will be making the Get return type the remaining ruleset as with the Set return type, we need to move the original return type to a ref param --- .../Shared/Api/Implementation/LSL_Api.cs | 38 ++++++++++++---------- .../Shared/Api/Implementation/OSSL_Api.cs | 2 +- 2 files changed, 22 insertions(+), 18 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 03b5982..6e46992 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -7910,7 +7910,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public LSL_List llGetPrimitiveParams(LSL_List rules) { m_host.AddScriptLPS(1); - return GetPrimParams(m_host, rules); + + LSL_List result = new LSL_List(); + + GetPrimParams(m_host, rules, ref result); + + return result; } public LSL_List llGetLinkPrimitiveParams(int linknumber, LSL_List rules) @@ -7923,16 +7928,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api foreach (SceneObjectPart part in parts) { - LSL_List partRes = GetPrimParams(part, rules); - res += partRes; + GetPrimParams(part, rules, ref res); } return res; } - public LSL_List GetPrimParams(SceneObjectPart part, LSL_List rules) + public void GetPrimParams(SceneObjectPart part, LSL_List rules, ref LSL_List res) { - LSL_List res = new LSL_List(); int idx=0; while (idx < rules.Length) { @@ -8077,7 +8080,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api case (int)ScriptBaseClass.PRIM_TEXTURE: if (remain < 1) - return res; + return; int face = (int)rules.GetLSLIntegerItem(idx++); Primitive.TextureEntry tex = part.Shape.Textures; @@ -8117,7 +8120,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api case (int)ScriptBaseClass.PRIM_COLOR: if (remain < 1) - return res; + return; face=(int)rules.GetLSLIntegerItem(idx++); @@ -8146,7 +8149,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api case (int)ScriptBaseClass.PRIM_BUMP_SHINY: if (remain < 1) - return res; + return; face=(int)rules.GetLSLIntegerItem(idx++); @@ -8177,7 +8180,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api case (int)ScriptBaseClass.PRIM_FULLBRIGHT: if (remain < 1) - return res; + return; face=(int)rules.GetLSLIntegerItem(idx++); @@ -8219,7 +8222,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api case (int)ScriptBaseClass.PRIM_TEXGEN: if (remain < 1) - return res; + return; face=(int)rules.GetLSLIntegerItem(idx++); @@ -8260,7 +8263,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api case (int)ScriptBaseClass.PRIM_GLOW: if (remain < 1) - return res; + return; face=(int)rules.GetLSLIntegerItem(idx++); @@ -8314,7 +8317,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api break; } } - return res; } public LSL_List llGetPrimMediaParams(int face, LSL_List rules) @@ -10755,13 +10757,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public LSL_List GetPrimitiveParamsEx(LSL_Key prim, LSL_List rules) { SceneObjectPart obj = World.GetSceneObjectPart(new UUID(prim)); - if (obj == null) - return new LSL_List(); - if (obj.OwnerID != m_host.OwnerID) - return new LSL_List(); + LSL_List result = new LSL_List(); - return GetPrimParams(obj, rules); + if (obj != null && obj.OwnerID != m_host.OwnerID) + { + GetPrimParams(obj, rules, ref result); + } + + return result; } public void print(string str) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs index c277708..a391b73 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs @@ -2250,7 +2250,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api List parts = ((LSL_Api)m_LSL_Api).GetLinkParts(linknumber); foreach (SceneObjectPart part in parts) { - retVal += ((LSL_Api)m_LSL_Api).GetPrimParams(part, rules); + ((LSL_Api)m_LSL_Api).GetPrimParams(part, rules, ref retVal); } return retVal; } -- cgit v1.1 From 5203665bb2d68c6a4e0ea3180334b607db6ab1ce Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Fri, 24 Aug 2012 17:25:37 +0100 Subject: refactoring to local variable for cleaner code --- OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs index a391b73..927f37c 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs @@ -2246,11 +2246,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api CheckThreatLevel(ThreatLevel.High, "osGetLinkPrimitiveParams"); m_host.AddScriptLPS(1); InitLSL(); + // One needs to cast m_LSL_Api because we're using functions not + // on the ILSL_Api interface. + LSL_Api LSL_Api = (LSL_Api)m_LSL_Api; LSL_List retVal = new LSL_List(); - List parts = ((LSL_Api)m_LSL_Api).GetLinkParts(linknumber); + List parts = LSL_Api.GetLinkParts(linknumber); foreach (SceneObjectPart part in parts) { - ((LSL_Api)m_LSL_Api).GetPrimParams(part, rules, ref retVal); + LSL_Api.GetPrimParams(part, rules, ref retVal); } return retVal; } -- cgit v1.1 From 58714b0aca71ce026226c6f76753905877792caf Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Fri, 24 Aug 2012 17:44:28 +0100 Subject: minor formatting --- OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 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 6e46992..0f0eac6 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -7238,10 +7238,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api foreach (SceneObjectPart part in parts) remaining = SetPrimParams(part, rules); - while(remaining != null && remaining.Length > 2) + while (remaining != null && remaining.Length > 2) { linknumber = remaining.GetLSLIntegerItem(0); - rules = remaining.GetSublist(1,-1); + rules = remaining.GetSublist(1, -1); parts = GetLinkParts(linknumber); foreach (SceneObjectPart part in parts) -- cgit v1.1 From 6e86b230120776a7da4727dd1aedeca6b91e3169 Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Fri, 24 Aug 2012 17:44:39 +0100 Subject: implementing PRIM_LINK_TARGET on GetPrimParams ala SetPrimParams --- .../Shared/Api/Implementation/LSL_Api.cs | 58 ++++++++++++++++++---- .../Shared/Api/Implementation/OSSL_Api.cs | 13 ++++- 2 files changed, 60 insertions(+), 11 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 0f0eac6..b001c51 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -7913,7 +7913,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api LSL_List result = new LSL_List(); - GetPrimParams(m_host, rules, ref result); + LSL_List remaining = GetPrimParams(m_host, rules, ref result); + + while (remaining != null && remaining.Length > 2) + { + int linknumber = remaining.GetLSLIntegerItem(0); + rules = remaining.GetSublist(1, -1); + List parts = GetLinkParts(linknumber); + + foreach (SceneObjectPart part in parts) + remaining = GetPrimParams(part, rules, ref result); + } return result; } @@ -7925,16 +7935,27 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api List parts = GetLinkParts(linknumber); LSL_List res = new LSL_List(); + LSL_List remaining = null; foreach (SceneObjectPart part in parts) { - GetPrimParams(part, rules, ref res); + remaining = GetPrimParams(part, rules, ref res); + } + + while (remaining != null && remaining.Length > 2) + { + linknumber = remaining.GetLSLIntegerItem(0); + rules = remaining.GetSublist(1, -1); + parts = GetLinkParts(linknumber); + + foreach (SceneObjectPart part in parts) + remaining = GetPrimParams(part, rules, ref res); } return res; } - public void GetPrimParams(SceneObjectPart part, LSL_List rules, ref LSL_List res) + public LSL_List GetPrimParams(SceneObjectPart part, LSL_List rules, ref LSL_List res) { int idx=0; while (idx < rules.Length) @@ -8080,7 +8101,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api case (int)ScriptBaseClass.PRIM_TEXTURE: if (remain < 1) - return; + return null; int face = (int)rules.GetLSLIntegerItem(idx++); Primitive.TextureEntry tex = part.Shape.Textures; @@ -8120,7 +8141,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api case (int)ScriptBaseClass.PRIM_COLOR: if (remain < 1) - return; + return null; face=(int)rules.GetLSLIntegerItem(idx++); @@ -8149,7 +8170,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api case (int)ScriptBaseClass.PRIM_BUMP_SHINY: if (remain < 1) - return; + return null; face=(int)rules.GetLSLIntegerItem(idx++); @@ -8180,7 +8201,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api case (int)ScriptBaseClass.PRIM_FULLBRIGHT: if (remain < 1) - return; + return null; face=(int)rules.GetLSLIntegerItem(idx++); @@ -8222,7 +8243,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api case (int)ScriptBaseClass.PRIM_TEXGEN: if (remain < 1) - return; + return null; face=(int)rules.GetLSLIntegerItem(idx++); @@ -8263,7 +8284,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api case (int)ScriptBaseClass.PRIM_GLOW: if (remain < 1) - return; + return null; face=(int)rules.GetLSLIntegerItem(idx++); @@ -8315,8 +8336,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api 0 )); break; + case (int)ScriptBaseClass.PRIM_LINK_TARGET: + if(remain < 3) + return null; + + return rules.GetSublist(idx, -1); } } + + return null; } public LSL_List llGetPrimMediaParams(int face, LSL_List rules) @@ -10762,7 +10790,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (obj != null && obj.OwnerID != m_host.OwnerID) { - GetPrimParams(obj, rules, ref result); + LSL_List remaining = GetPrimParams(obj, rules, ref result); + + while (remaining != null && remaining.Length > 2) + { + int linknumber = remaining.GetLSLIntegerItem(0); + rules = remaining.GetSublist(1, -1); + List parts = GetLinkParts(linknumber); + + foreach (SceneObjectPart part in parts) + remaining = GetPrimParams(part, rules, ref result); + } } return result; diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs index 927f37c..1afa4fb 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs @@ -2250,10 +2250,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api // on the ILSL_Api interface. LSL_Api LSL_Api = (LSL_Api)m_LSL_Api; LSL_List retVal = new LSL_List(); + LSL_List remaining = null; List parts = LSL_Api.GetLinkParts(linknumber); foreach (SceneObjectPart part in parts) { - LSL_Api.GetPrimParams(part, rules, ref retVal); + remaining = LSL_Api.GetPrimParams(part, rules, ref retVal); + } + + while (remaining != null && remaining.Length > 2) + { + linknumber = remaining.GetLSLIntegerItem(0); + rules = remaining.GetSublist(1, -1); + parts = LSL_Api.GetLinkParts(linknumber); + + foreach (SceneObjectPart part in parts) + remaining = LSL_Api.GetPrimParams(part, rules, ref retVal); } return retVal; } -- cgit v1.1 From 1eb1c1bd4bc972e2df301b9dafb40fbb2f37b40c Mon Sep 17 00:00:00 2001 From: Melanie Date: Sat, 25 Aug 2012 18:19:51 +0100 Subject: renaming to be similar to equivalent Set command Conflicts: OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs --- OpenSim/Region/Framework/Scenes/Scene.cs | 2 +- .../ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 14 +++++++------- .../ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs | 4 ++-- .../Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs | 2 +- 4 files changed, 11 insertions(+), 11 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index fcc2953..5b529c3 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -3737,7 +3737,7 @@ namespace OpenSim.Region.Framework.Scenes "[SCENE]: Existing root scene presence detected for {0} {1} in {2} when connecting. Removing existing presence.", sp.Name, sp.UUID, RegionInfo.RegionName); - sp.ControllingClient.Close(true); + sp.ControllingClient.Close(true, true); sp = null; } diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 5386a28..c8b6a7e 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -8821,7 +8821,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public LSL_List llGetPrimitiveParams(LSL_List rules) { m_host.AddScriptLPS(1); - return GetLinkPrimitiveParams(m_host, rules); + return GetPrimParams(m_host, rules); } public LSL_List llGetLinkPrimitiveParams(int linknumber, LSL_List rules) @@ -8840,7 +8840,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { foreach (var part in parts) { - LSL_List partRes = GetLinkPrimitiveParams(part, rules); + LSL_List partRes = GetPrimParams(part, rules); res += partRes; } } @@ -8848,14 +8848,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { foreach (ScenePresence avatar in avatars) { - LSL_List avaRes = GetLinkPrimitiveParams(avatar, rules); + LSL_List avaRes = GetPrimParams(avatar, rules); res += avaRes; } } return res; } - public LSL_List GetLinkPrimitiveParams(ScenePresence avatar, LSL_List rules) + public LSL_List GetPrimParams(ScenePresence avatar, LSL_List rules) { // avatars case // replies as SL wiki @@ -9116,7 +9116,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api return res; } - public LSL_List GetLinkPrimitiveParams(SceneObjectPart part, LSL_List rules) + public LSL_List GetPrimParams(SceneObjectPart part, LSL_List rules) { LSL_List res = new LSL_List(); int idx=0; @@ -12104,7 +12104,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } } - public LSL_List GetLinkPrimitiveParamsEx(LSL_Key prim, LSL_List rules) + public LSL_List GetPrimitiveParamsEx(LSL_Key prim, LSL_List rules) { SceneObjectPart obj = World.GetSceneObjectPart(new UUID(prim)); if (obj == null) @@ -12113,7 +12113,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (obj.OwnerID != m_host.OwnerID) return new LSL_List(); - return GetLinkPrimitiveParams(obj, rules); + return GetPrimParams(obj, rules); } public LSL_Integer llGetLinkNumberOfSides(LSL_Integer link) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs index a81c39c..7b71a24 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs @@ -2261,7 +2261,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api List parts = ((LSL_Api)m_LSL_Api).GetLinkParts(linknumber); foreach (SceneObjectPart part in parts) { - retVal += ((LSL_Api)m_LSL_Api).GetLinkPrimitiveParams(part, rules); + retVal += ((LSL_Api)m_LSL_Api).GetPrimParams(part, rules); } return retVal; } @@ -3013,7 +3013,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api m_host.AddScriptLPS(1); InitLSL(); - return m_LSL_Api.GetLinkPrimitiveParamsEx(prim, rules); + return m_LSL_Api.GetPrimitiveParamsEx(prim, rules); } public void osSetPrimitiveParams(LSL_Key prim, LSL_List rules) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs index af35258..e08328f 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs @@ -430,7 +430,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces void llSetPhysicsMaterial(int material_bits, float material_gravity_modifier, float material_restitution, float material_friction, float material_density); void SetPrimitiveParamsEx(LSL_Key prim, LSL_List rules); - LSL_List GetLinkPrimitiveParamsEx(LSL_Key prim, LSL_List rules); void llSetKeyframedMotion(LSL_List frames, LSL_List options); + LSL_List GetPrimitiveParamsEx(LSL_Key prim, LSL_List rules); } } -- cgit v1.1 From af6b2420718447a534e1ceedea366fc1dbf29dd7 Mon Sep 17 00:00:00 2001 From: Melanie Date: Sat, 25 Aug 2012 18:24:52 +0100 Subject: use SceneObjectPart instead of var Conflicts: OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs --- .../ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 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 c8b6a7e..7b52ea3 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -6252,19 +6252,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api m_host.AddScriptLPS(1); List parts = GetLinkParts(linknumber); - if (parts.Count > 0) + + try { - try - { - foreach (var part in parts) - { - SetTextureAnim(part, mode, face, sizex, sizey, start, length, rate); - } - } - finally + foreach (SceneObjectPart part in parts) { + SetTextureAnim(part, mode, face, sizex, sizey, start, length, rate); } } + finally + { + } } private void SetTextureAnim(SceneObjectPart part, int mode, int face, int sizex, int sizey, double start, double length, double rate) @@ -6658,7 +6656,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api List parts = GetLinkParts(linknumber); - foreach (var part in parts) + foreach (SceneObjectPart part in parts) { SetParticleSystem(part, rules); } -- cgit v1.1 From 5f1021faa6b8196878604ea2f8af57bceeb41ba6 Mon Sep 17 00:00:00 2001 From: Melanie Date: Sat, 25 Aug 2012 18:28:05 +0100 Subject: Temprary restructure to avoid conflicts --- .../Shared/Api/Implementation/LSL_Api.cs | 366 ++++++++++----------- 1 file changed, 183 insertions(+), 183 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 7b52ea3..2bdb485 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -7817,189 +7817,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api return new Vector3((float)x, (float)y, (float)z); } - protected LSL_List SetPrimParams(ScenePresence av, LSL_List rules) - { - //This is a special version of SetPrimParams to deal with avatars which are sat on the linkset. - - int idx = 0; - - bool positionChanged = false; - Vector3 finalPos = Vector3.Zero; - - try - { - while (idx < rules.Length) - { - int code = rules.GetLSLIntegerItem(idx++); - - int remain = rules.Length - idx; - - switch (code) - { - case (int)ScriptBaseClass.PRIM_POSITION: - case (int)ScriptBaseClass.PRIM_POS_LOCAL: - { - if (remain < 1) - return null; - - LSL_Vector v; - v = rules.GetVector3Item(idx++); - - SceneObjectPart part = World.GetSceneObjectPart(av.ParentID); - if (part == null) - break; - - LSL_Rotation localRot = ScriptBaseClass.ZERO_ROTATION; - LSL_Vector localPos = ScriptBaseClass.ZERO_VECTOR; - if (part.LinkNum > 1) - { - localRot = GetPartLocalRot(part); - localPos = GetPartLocalPos(part); - } - - v -= localPos; - v /= localRot; - - LSL_Vector sitOffset = (llRot2Up(new LSL_Rotation(av.Rotation.X, av.Rotation.Y, av.Rotation.Z, av.Rotation.W)) * av.Appearance.AvatarHeight * 0.02638f); - - v = v + 2 * sitOffset; - - av.OffsetPosition = new Vector3((float)v.x, (float)v.y, (float)v.z); - av.SendAvatarDataToAllAgents(); - - } - break; - - case (int)ScriptBaseClass.PRIM_ROT_LOCAL: - case (int)ScriptBaseClass.PRIM_ROTATION: - { - if (remain < 1) - return null; - - LSL_Rotation r; - r = rules.GetQuaternionItem(idx++); - - SceneObjectPart part = World.GetSceneObjectPart(av.ParentID); - if (part == null) - break; - - LSL_Rotation localRot = ScriptBaseClass.ZERO_ROTATION; - LSL_Vector localPos = ScriptBaseClass.ZERO_VECTOR; - - if (part.LinkNum > 1) - localRot = GetPartLocalRot(part); - - r = r * llGetRootRotation() / localRot; - av.Rotation = new Quaternion((float)r.x, (float)r.y, (float)r.z, (float)r.s); - av.SendAvatarDataToAllAgents(); - } - break; - - // parse rest doing nothing but number of parameters error check - case (int)ScriptBaseClass.PRIM_SIZE: - case (int)ScriptBaseClass.PRIM_MATERIAL: - case (int)ScriptBaseClass.PRIM_PHANTOM: - case (int)ScriptBaseClass.PRIM_PHYSICS: - case (int)ScriptBaseClass.PRIM_PHYSICS_SHAPE_TYPE: - case (int)ScriptBaseClass.PRIM_TEMP_ON_REZ: - case (int)ScriptBaseClass.PRIM_NAME: - case (int)ScriptBaseClass.PRIM_DESC: - if (remain < 1) - return null; - idx++; - break; - - case (int)ScriptBaseClass.PRIM_GLOW: - case (int)ScriptBaseClass.PRIM_FULLBRIGHT: - case (int)ScriptBaseClass.PRIM_TEXGEN: - if (remain < 2) - return null; - idx += 2; - break; - - case (int)ScriptBaseClass.PRIM_TYPE: - if (remain < 3) - return null; - code = (int)rules.GetLSLIntegerItem(idx++); - remain = rules.Length - idx; - switch (code) - { - case (int)ScriptBaseClass.PRIM_TYPE_BOX: - case (int)ScriptBaseClass.PRIM_TYPE_CYLINDER: - case (int)ScriptBaseClass.PRIM_TYPE_PRISM: - if (remain < 6) - return null; - idx += 6; - break; - - case (int)ScriptBaseClass.PRIM_TYPE_SPHERE: - if (remain < 5) - return null; - idx += 5; - break; - - case (int)ScriptBaseClass.PRIM_TYPE_TORUS: - case (int)ScriptBaseClass.PRIM_TYPE_TUBE: - case (int)ScriptBaseClass.PRIM_TYPE_RING: - if (remain < 11) - return null; - idx += 11; - break; - - case (int)ScriptBaseClass.PRIM_TYPE_SCULPT: - if (remain < 2) - return null; - idx += 2; - break; - } - break; - - case (int)ScriptBaseClass.PRIM_COLOR: - case (int)ScriptBaseClass.PRIM_TEXT: - case (int)ScriptBaseClass.PRIM_BUMP_SHINY: - case (int)ScriptBaseClass.PRIM_OMEGA: - if (remain < 3) - return null; - idx += 3; - break; - - case (int)ScriptBaseClass.PRIM_TEXTURE: - case (int)ScriptBaseClass.PRIM_POINT_LIGHT: - case (int)ScriptBaseClass.PRIM_PHYSICS_MATERIAL: - if (remain < 5) - return null; - idx += 5; - break; - - case (int)ScriptBaseClass.PRIM_FLEXIBLE: - if (remain < 7) - return null; - - idx += 7; - break; - - case (int)ScriptBaseClass.PRIM_LINK_TARGET: - if (remain < 3) // setting to 3 on the basis that parsing any usage of PRIM_LINK_TARGET that has nothing following it is pointless. - return null; - - return rules.GetSublist(idx, -1); - } - } - } - - finally - { - if (positionChanged) - { - av.OffsetPosition = finalPos; -// av.SendAvatarDataToAllAgents(); - av.SendTerseUpdateToAllClients(); - positionChanged = false; - } - } - return null; - } - protected LSL_List SetPrimParams(SceneObjectPart part, LSL_List rules) { if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted) @@ -13152,5 +12969,188 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api m_Notecards.Remove(key); } } + + protected LSL_List SetPrimParams(ScenePresence av, LSL_List rules) + { + //This is a special version of SetPrimParams to deal with avatars which are sat on the linkset. + + int idx = 0; + + bool positionChanged = false; + Vector3 finalPos = Vector3.Zero; + + try + { + while (idx < rules.Length) + { + int code = rules.GetLSLIntegerItem(idx++); + + int remain = rules.Length - idx; + + switch (code) + { + case (int)ScriptBaseClass.PRIM_POSITION: + case (int)ScriptBaseClass.PRIM_POS_LOCAL: + { + if (remain < 1) + return null; + + LSL_Vector v; + v = rules.GetVector3Item(idx++); + + SceneObjectPart part = World.GetSceneObjectPart(av.ParentID); + if (part == null) + break; + + LSL_Rotation localRot = ScriptBaseClass.ZERO_ROTATION; + LSL_Vector localPos = ScriptBaseClass.ZERO_VECTOR; + if (part.LinkNum > 1) + { + localRot = GetPartLocalRot(part); + localPos = GetPartLocalPos(part); + } + + v -= localPos; + v /= localRot; + + LSL_Vector sitOffset = (llRot2Up(new LSL_Rotation(av.Rotation.X, av.Rotation.Y, av.Rotation.Z, av.Rotation.W)) * av.Appearance.AvatarHeight * 0.02638f); + + v = v + 2 * sitOffset; + + av.OffsetPosition = new Vector3((float)v.x, (float)v.y, (float)v.z); + av.SendAvatarDataToAllAgents(); + + } + break; + + case (int)ScriptBaseClass.PRIM_ROT_LOCAL: + case (int)ScriptBaseClass.PRIM_ROTATION: + { + if (remain < 1) + return null; + + LSL_Rotation r; + r = rules.GetQuaternionItem(idx++); + + SceneObjectPart part = World.GetSceneObjectPart(av.ParentID); + if (part == null) + break; + + LSL_Rotation localRot = ScriptBaseClass.ZERO_ROTATION; + LSL_Vector localPos = ScriptBaseClass.ZERO_VECTOR; + + if (part.LinkNum > 1) + localRot = GetPartLocalRot(part); + + r = r * llGetRootRotation() / localRot; + av.Rotation = new Quaternion((float)r.x, (float)r.y, (float)r.z, (float)r.s); + av.SendAvatarDataToAllAgents(); + } + break; + + // parse rest doing nothing but number of parameters error check + case (int)ScriptBaseClass.PRIM_SIZE: + case (int)ScriptBaseClass.PRIM_MATERIAL: + case (int)ScriptBaseClass.PRIM_PHANTOM: + case (int)ScriptBaseClass.PRIM_PHYSICS: + case (int)ScriptBaseClass.PRIM_PHYSICS_SHAPE_TYPE: + case (int)ScriptBaseClass.PRIM_TEMP_ON_REZ: + case (int)ScriptBaseClass.PRIM_NAME: + case (int)ScriptBaseClass.PRIM_DESC: + if (remain < 1) + return null; + idx++; + break; + + case (int)ScriptBaseClass.PRIM_GLOW: + case (int)ScriptBaseClass.PRIM_FULLBRIGHT: + case (int)ScriptBaseClass.PRIM_TEXGEN: + if (remain < 2) + return null; + idx += 2; + break; + + case (int)ScriptBaseClass.PRIM_TYPE: + if (remain < 3) + return null; + code = (int)rules.GetLSLIntegerItem(idx++); + remain = rules.Length - idx; + switch (code) + { + case (int)ScriptBaseClass.PRIM_TYPE_BOX: + case (int)ScriptBaseClass.PRIM_TYPE_CYLINDER: + case (int)ScriptBaseClass.PRIM_TYPE_PRISM: + if (remain < 6) + return null; + idx += 6; + break; + + case (int)ScriptBaseClass.PRIM_TYPE_SPHERE: + if (remain < 5) + return null; + idx += 5; + break; + + case (int)ScriptBaseClass.PRIM_TYPE_TORUS: + case (int)ScriptBaseClass.PRIM_TYPE_TUBE: + case (int)ScriptBaseClass.PRIM_TYPE_RING: + if (remain < 11) + return null; + idx += 11; + break; + + case (int)ScriptBaseClass.PRIM_TYPE_SCULPT: + if (remain < 2) + return null; + idx += 2; + break; + } + break; + + case (int)ScriptBaseClass.PRIM_COLOR: + case (int)ScriptBaseClass.PRIM_TEXT: + case (int)ScriptBaseClass.PRIM_BUMP_SHINY: + case (int)ScriptBaseClass.PRIM_OMEGA: + if (remain < 3) + return null; + idx += 3; + break; + + case (int)ScriptBaseClass.PRIM_TEXTURE: + case (int)ScriptBaseClass.PRIM_POINT_LIGHT: + case (int)ScriptBaseClass.PRIM_PHYSICS_MATERIAL: + if (remain < 5) + return null; + idx += 5; + break; + + case (int)ScriptBaseClass.PRIM_FLEXIBLE: + if (remain < 7) + return null; + + idx += 7; + break; + + case (int)ScriptBaseClass.PRIM_LINK_TARGET: + if (remain < 3) // setting to 3 on the basis that parsing any usage of PRIM_LINK_TARGET that has nothing following it is pointless. + return null; + + return rules.GetSublist(idx, -1); + } + } + } + + finally + { + if (positionChanged) + { + av.OffsetPosition = finalPos; +// av.SendAvatarDataToAllAgents(); + av.SendTerseUpdateToAllClients(); + positionChanged = false; + } + } + return null; + } } } -- cgit v1.1 From 681066050c2f7019d1b425c86f7985d7650d8226 Mon Sep 17 00:00:00 2001 From: Melanie Date: Sat, 25 Aug 2012 18:32:59 +0100 Subject: Also move the other avatar based overload out of harms way --- .../Shared/Api/Implementation/LSL_Api.cs | 1430 ++++++++++---------- 1 file changed, 715 insertions(+), 715 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 2bdb485..64f145b 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -8670,75 +8670,142 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api return res; } - public LSL_List GetPrimParams(ScenePresence avatar, LSL_List rules) + public LSL_List GetPrimParams(SceneObjectPart part, LSL_List rules) { - // avatars case - // replies as SL wiki - LSL_List res = new LSL_List(); -// SceneObjectPart sitPart = avatar.ParentPart; // most likelly it will be needed - SceneObjectPart sitPart = World.GetSceneObjectPart(avatar.ParentID); // maybe better do this expensive search for it in case it's gone?? - - int idx = 0; + int idx=0; while (idx < rules.Length) { - int code = (int)rules.GetLSLIntegerItem(idx++); - int remain = rules.Length - idx; + int code=(int)rules.GetLSLIntegerItem(idx++); + int remain=rules.Length-idx; switch (code) { case (int)ScriptBaseClass.PRIM_MATERIAL: - res.Add(new LSL_Integer((int)SOPMaterialData.SopMaterial.Flesh)); + res.Add(new LSL_Integer(part.Material)); break; case (int)ScriptBaseClass.PRIM_PHYSICS: + if ((part.GetEffectiveObjectFlags() & (uint)PrimFlags.Physics) != 0) + res.Add(new LSL_Integer(1)); + else res.Add(new LSL_Integer(0)); break; case (int)ScriptBaseClass.PRIM_TEMP_ON_REZ: + if ((part.GetEffectiveObjectFlags() & (uint)PrimFlags.TemporaryOnRez) != 0) + res.Add(new LSL_Integer(1)); + else res.Add(new LSL_Integer(0)); break; case (int)ScriptBaseClass.PRIM_PHANTOM: + if ((part.GetEffectiveObjectFlags() & (uint)PrimFlags.Phantom) != 0) + res.Add(new LSL_Integer(1)); + else res.Add(new LSL_Integer(0)); break; case (int)ScriptBaseClass.PRIM_POSITION: - - Vector3 pos = avatar.OffsetPosition; - - Vector3 sitOffset = (Zrot(avatar.Rotation)) * (avatar.Appearance.AvatarHeight * 0.02638f *2.0f); - pos -= sitOffset; - - if( sitPart != null) - pos = sitPart.GetWorldPosition() + pos * sitPart.GetWorldRotation(); - - res.Add(new LSL_Vector(pos.X,pos.Y,pos.Z)); + LSL_Vector v = new LSL_Vector(part.AbsolutePosition.X, + part.AbsolutePosition.Y, + part.AbsolutePosition.Z); + res.Add(v); break; case (int)ScriptBaseClass.PRIM_SIZE: - // as in llGetAgentSize above - res.Add(new LSL_Vector(0.45f, 0.6f, avatar.Appearance.AvatarHeight)); + res.Add(new LSL_Vector(part.Scale.X, + part.Scale.Y, + part.Scale.Z)); break; case (int)ScriptBaseClass.PRIM_ROTATION: - Quaternion rot = avatar.Rotation; - if (sitPart != null) - { - rot = sitPart.GetWorldRotation() * rot; // apply sit part world rotation - } - - res.Add(new LSL_Rotation (rot.X, rot.Y, rot.Z, rot.W)); + res.Add(GetPartRot(part)); break; case (int)ScriptBaseClass.PRIM_TYPE: - res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TYPE_BOX)); - res.Add(new LSL_Integer(ScriptBaseClass.PRIM_HOLE_DEFAULT)); - res.Add(new LSL_Vector(0f,1.0f,0f)); - res.Add(new LSL_Float(0.0f)); - res.Add(new LSL_Vector(0, 0, 0)); - res.Add(new LSL_Vector(1.0f,1.0f,0f)); - res.Add(new LSL_Vector(0, 0, 0)); + // implementing box + PrimitiveBaseShape Shape = part.Shape; + int primType = (int)part.GetPrimType(); + res.Add(new LSL_Integer(primType)); + double topshearx = (double)(sbyte)Shape.PathShearX / 100.0; // Fix negative values for PathShearX + double topsheary = (double)(sbyte)Shape.PathShearY / 100.0; // and PathShearY. + switch (primType) + { + case ScriptBaseClass.PRIM_TYPE_BOX: + case ScriptBaseClass.PRIM_TYPE_CYLINDER: + case ScriptBaseClass.PRIM_TYPE_PRISM: + res.Add(new LSL_Integer(Shape.ProfileCurve) & 0xf0); // Isolate hole shape nibble. + res.Add(new LSL_Vector(Shape.ProfileBegin / 50000.0, 1 - Shape.ProfileEnd / 50000.0, 0)); + res.Add(new LSL_Float(Shape.ProfileHollow / 50000.0)); + res.Add(new LSL_Vector(Shape.PathTwistBegin / 100.0, Shape.PathTwist / 100.0, 0)); + res.Add(new LSL_Vector(1 - (Shape.PathScaleX / 100.0 - 1), 1 - (Shape.PathScaleY / 100.0 - 1), 0)); + res.Add(new LSL_Vector(topshearx, topsheary, 0)); + break; + + case ScriptBaseClass.PRIM_TYPE_SPHERE: + res.Add(new LSL_Integer(Shape.ProfileCurve) & 0xf0); // Isolate hole shape nibble. + res.Add(new LSL_Vector(Shape.PathBegin / 50000.0, 1 - Shape.PathEnd / 50000.0, 0)); + res.Add(new LSL_Float(Shape.ProfileHollow / 50000.0)); + res.Add(new LSL_Vector(Shape.PathTwistBegin / 100.0, Shape.PathTwist / 100.0, 0)); + res.Add(new LSL_Vector(Shape.ProfileBegin / 50000.0, 1 - Shape.ProfileEnd / 50000.0, 0)); + break; + + case ScriptBaseClass.PRIM_TYPE_SCULPT: + res.Add(Shape.SculptTexture.ToString()); + res.Add(new LSL_Integer(Shape.SculptType)); + break; + + case ScriptBaseClass.PRIM_TYPE_RING: + case ScriptBaseClass.PRIM_TYPE_TUBE: + case ScriptBaseClass.PRIM_TYPE_TORUS: + // holeshape + res.Add(new LSL_Integer(Shape.ProfileCurve) & 0xf0); // Isolate hole shape nibble. + + // cut + res.Add(new LSL_Vector(Shape.PathBegin / 50000.0, 1 - Shape.PathEnd / 50000.0, 0)); + + // hollow + res.Add(new LSL_Float(Shape.ProfileHollow / 50000.0)); + + // twist + res.Add(new LSL_Vector(Shape.PathTwistBegin / 100.0, Shape.PathTwist / 100.0, 0)); + + // vector holesize + res.Add(new LSL_Vector(1 - (Shape.PathScaleX / 100.0 - 1), 1 - (Shape.PathScaleY / 100.0 - 1), 0)); + + // vector topshear + res.Add(new LSL_Vector(topshearx, topsheary, 0)); + + // vector profilecut + res.Add(new LSL_Vector(Shape.ProfileBegin / 50000.0, 1 - Shape.ProfileEnd / 50000.0, 0)); + + // vector tapera + res.Add(new LSL_Vector(Shape.PathTaperX / 100.0, Shape.PathTaperY / 100.0, 0)); + + // float revolutions + res.Add(new LSL_Float(Math.Round(Shape.PathRevolutions * 0.015d, 2, MidpointRounding.AwayFromZero)) + 1.0d); + // Slightly inaccurate, because an unsigned byte is being used to represent + // the entire range of floating-point values from 1.0 through 4.0 (which is how + // SL does it). + // + // Using these formulas to store and retrieve PathRevolutions, it is not + // possible to use all values between 1.00 and 4.00. For instance, you can't + // represent 1.10. You can represent 1.09 and 1.11, but not 1.10. So, if you + // use llSetPrimitiveParams to set revolutions to 1.10 and then retreive them + // with llGetPrimitiveParams, you'll retrieve 1.09. You can also see a similar + // behavior in the viewer as you cannot set 1.10. The viewer jumps to 1.11. + // In SL, llSetPrimitveParams and llGetPrimitiveParams can set and get a value + // such as 1.10. So, SL must store and retreive the actual user input rather + // than only storing the encoded value. + + // float radiusoffset + res.Add(new LSL_Float(Shape.PathRadiusOffset / 100.0)); + + // float skew + res.Add(new LSL_Float(Shape.PathSkew / 100.0)); + break; + } break; case (int)ScriptBaseClass.PRIM_TEXTURE: @@ -8746,24 +8813,37 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api return res; int face = (int)rules.GetLSLIntegerItem(idx++); + Primitive.TextureEntry tex = part.Shape.Textures; if (face == ScriptBaseClass.ALL_SIDES) { - for (face = 0; face < 21; face++) + for (face = 0 ; face < GetNumberOfSides(part); face++) { - res.Add(new LSL_String("")); - res.Add(new LSL_Vector(0,0,0)); - res.Add(new LSL_Vector(0,0,0)); - res.Add(new LSL_Float(0.0)); + Primitive.TextureEntryFace texface = tex.GetFace((uint)face); + + res.Add(new LSL_String(texface.TextureID.ToString())); + res.Add(new LSL_Vector(texface.RepeatU, + texface.RepeatV, + 0)); + res.Add(new LSL_Vector(texface.OffsetU, + texface.OffsetV, + 0)); + res.Add(new LSL_Float(texface.Rotation)); } } else { - if (face >= 0 && face < 21) + if (face >= 0 && face < GetNumberOfSides(part)) { - res.Add(new LSL_String("")); - res.Add(new LSL_Vector(0,0,0)); - res.Add(new LSL_Vector(0,0,0)); - res.Add(new LSL_Float(0.0)); + Primitive.TextureEntryFace texface = tex.GetFace((uint)face); + + res.Add(new LSL_String(texface.TextureID.ToString())); + res.Add(new LSL_Vector(texface.RepeatU, + texface.RepeatV, + 0)); + res.Add(new LSL_Vector(texface.OffsetU, + texface.OffsetV, + 0)); + res.Add(new LSL_Float(texface.Rotation)); } } break; @@ -8772,20 +8852,28 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (remain < 1) return res; - face = (int)rules.GetLSLIntegerItem(idx++); + face=(int)rules.GetLSLIntegerItem(idx++); + tex = part.Shape.Textures; + Color4 texcolor; if (face == ScriptBaseClass.ALL_SIDES) { - for (face = 0; face < 21; face++) + for (face = 0 ; face < GetNumberOfSides(part); face++) { - res.Add(new LSL_Vector(0,0,0)); - res.Add(new LSL_Float(0)); + texcolor = tex.GetFace((uint)face).RGBA; + res.Add(new LSL_Vector(texcolor.R, + texcolor.G, + texcolor.B)); + res.Add(new LSL_Float(texcolor.A)); } } else { - res.Add(new LSL_Vector(0,0,0)); - res.Add(new LSL_Float(0)); + texcolor = tex.GetFace((uint)face).RGBA; + res.Add(new LSL_Vector(texcolor.R, + texcolor.G, + texcolor.B)); + res.Add(new LSL_Float(texcolor.A)); } break; @@ -8794,18 +8882,54 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api return res; face = (int)rules.GetLSLIntegerItem(idx++); + tex = part.Shape.Textures; + int shiny; if (face == ScriptBaseClass.ALL_SIDES) { - for (face = 0; face < 21; face++) + for (face = 0; face < GetNumberOfSides(part); face++) { - res.Add(new LSL_Integer(ScriptBaseClass.PRIM_SHINY_NONE)); - res.Add(new LSL_Integer(ScriptBaseClass.PRIM_BUMP_NONE)); + Shininess shinyness = tex.GetFace((uint)face).Shiny; + if (shinyness == Shininess.High) + { + shiny = ScriptBaseClass.PRIM_SHINY_HIGH; + } + else if (shinyness == Shininess.Medium) + { + shiny = ScriptBaseClass.PRIM_SHINY_MEDIUM; + } + else if (shinyness == Shininess.Low) + { + shiny = ScriptBaseClass.PRIM_SHINY_LOW; + } + else + { + shiny = ScriptBaseClass.PRIM_SHINY_NONE; + } + res.Add(new LSL_Integer(shiny)); + res.Add(new LSL_Integer((int)tex.GetFace((uint)face).Bump)); } } else { - res.Add(new LSL_Integer(ScriptBaseClass.PRIM_SHINY_NONE)); - res.Add(new LSL_Integer(ScriptBaseClass.PRIM_BUMP_NONE)); + Shininess shinyness = tex.GetFace((uint)face).Shiny; + if (shinyness == Shininess.High) + { + shiny = ScriptBaseClass.PRIM_SHINY_HIGH; + } + else if (shinyness == Shininess.Medium) + { + shiny = ScriptBaseClass.PRIM_SHINY_MEDIUM; + } + else if (shinyness == Shininess.Low) + { + shiny = ScriptBaseClass.PRIM_SHINY_LOW; + } + else + { + shiny = ScriptBaseClass.PRIM_SHINY_NONE; + } + res.Add(new LSL_Integer(shiny)); + res.Add(new LSL_Integer((int)tex.GetFace((uint)face).Bump)); } break; @@ -8814,27 +8938,52 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api return res; face = (int)rules.GetLSLIntegerItem(idx++); + tex = part.Shape.Textures; + int fullbright; if (face == ScriptBaseClass.ALL_SIDES) { - for (face = 0; face < 21; face++) + for (face = 0; face < GetNumberOfSides(part); face++) { - res.Add(new LSL_Integer(ScriptBaseClass.FALSE)); + if (tex.GetFace((uint)face).Fullbright == true) + { + fullbright = ScriptBaseClass.TRUE; + } + else + { + fullbright = ScriptBaseClass.FALSE; + } + res.Add(new LSL_Integer(fullbright)); } } else { - res.Add(new LSL_Integer(ScriptBaseClass.FALSE)); - } + if (tex.GetFace((uint)face).Fullbright == true) + { + fullbright = ScriptBaseClass.TRUE; + } + else + { + fullbright = ScriptBaseClass.FALSE; + } + res.Add(new LSL_Integer(fullbright)); + } break; case (int)ScriptBaseClass.PRIM_FLEXIBLE: - res.Add(new LSL_Integer(0)); - res.Add(new LSL_Integer(0));// softness - res.Add(new LSL_Float(0.0f)); // gravity - res.Add(new LSL_Float(0.0f)); // friction - res.Add(new LSL_Float(0.0f)); // wind - res.Add(new LSL_Float(0.0f)); // tension - res.Add(new LSL_Vector(0f,0f,0f)); + PrimitiveBaseShape shape = part.Shape; + + if (shape.FlexiEntry) + res.Add(new LSL_Integer(1)); // active + else + res.Add(new LSL_Integer(0)); + res.Add(new LSL_Integer(shape.FlexiSoftness));// softness + res.Add(new LSL_Float(shape.FlexiGravity)); // gravity + res.Add(new LSL_Float(shape.FlexiDrag)); // friction + res.Add(new LSL_Float(shape.FlexiWind)); // wind + res.Add(new LSL_Float(shape.FlexiTension)); // tension + res.Add(new LSL_Vector(shape.FlexiForceX, // force + shape.FlexiForceY, + shape.FlexiForceZ)); break; case (int)ScriptBaseClass.PRIM_TEXGEN: @@ -8843,25 +8992,47 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api return res; face = (int)rules.GetLSLIntegerItem(idx++); + tex = part.Shape.Textures; if (face == ScriptBaseClass.ALL_SIDES) { - for (face = 0; face < 21; face++) + for (face = 0; face < GetNumberOfSides(part); face++) { + if (tex.GetFace((uint)face).TexMapType == MappingType.Planar) + { + res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_PLANAR)); + } + else + { res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_DEFAULT)); + } } } else { + if (tex.GetFace((uint)face).TexMapType == MappingType.Planar) + { + res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_PLANAR)); + } + else + { res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_DEFAULT)); + } } break; case (int)ScriptBaseClass.PRIM_POINT_LIGHT: - res.Add(new LSL_Integer(0)); - res.Add(new LSL_Vector(0f,0f,0f)); - res.Add(new LSL_Float(0f)); // intensity - res.Add(new LSL_Float(0f)); // radius - res.Add(new LSL_Float(0f)); // falloff + shape = part.Shape; + + if (shape.LightEntry) + res.Add(new LSL_Integer(1)); // active + else + res.Add(new LSL_Integer(0)); + res.Add(new LSL_Vector(shape.LightColorR, // color + shape.LightColorG, + shape.LightColorB)); + res.Add(new LSL_Float(shape.LightIntensity)); // intensity + res.Add(new LSL_Float(shape.LightRadius)); // radius + res.Add(new LSL_Float(shape.LightFalloff)); // falloff break; case (int)ScriptBaseClass.PRIM_GLOW: @@ -8869,591 +9040,159 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api return res; face = (int)rules.GetLSLIntegerItem(idx++); + tex = part.Shape.Textures; + float primglow; if (face == ScriptBaseClass.ALL_SIDES) { - for (face = 0; face < 21; face++) + for (face = 0; face < GetNumberOfSides(part); face++) { - res.Add(new LSL_Float(0f)); + primglow = tex.GetFace((uint)face).Glow; + res.Add(new LSL_Float(primglow)); } } else { - res.Add(new LSL_Float(0f)); + primglow = tex.GetFace((uint)face).Glow; + res.Add(new LSL_Float(primglow)); } break; case (int)ScriptBaseClass.PRIM_TEXT: - res.Add(new LSL_String("")); - res.Add(new LSL_Vector(0f,0f,0f)); - res.Add(new LSL_Float(1.0f)); + Color4 textColor = part.GetTextColor(); + res.Add(new LSL_String(part.Text)); + res.Add(new LSL_Vector(textColor.R, + textColor.G, + textColor.B)); + res.Add(new LSL_Float(textColor.A)); break; case (int)ScriptBaseClass.PRIM_NAME: - res.Add(new LSL_String(avatar.Name)); + res.Add(new LSL_String(part.Name)); break; case (int)ScriptBaseClass.PRIM_DESC: - res.Add(new LSL_String("")); + res.Add(new LSL_String(part.Description)); break; - case (int)ScriptBaseClass.PRIM_ROT_LOCAL: - Quaternion lrot = avatar.Rotation; - - if (sitPart != null && sitPart != sitPart.ParentGroup.RootPart) - { - lrot = sitPart.RotationOffset * lrot; // apply sit part rotation offset - } - res.Add(new LSL_Rotation(lrot.X, lrot.Y, lrot.Z, lrot.W)); + case (int)ScriptBaseClass.PRIM_ROT_LOCAL: + res.Add(new LSL_Rotation(part.RotationOffset.X, part.RotationOffset.Y, part.RotationOffset.Z, part.RotationOffset.W)); break; case (int)ScriptBaseClass.PRIM_POS_LOCAL: - Vector3 lpos = avatar.OffsetPosition; // pos relative to sit part - Vector3 lsitOffset = (Zrot(avatar.Rotation)) * (avatar.Appearance.AvatarHeight * 0.02638f * 2.0f); - lpos -= lsitOffset; - - if (sitPart != null && sitPart != sitPart.ParentGroup.RootPart) - { - lpos = sitPart.OffsetPosition + (lpos * sitPart.RotationOffset); // make it relative to root prim - } - res.Add(new LSL_Vector(lpos.X,lpos.Y,lpos.Z)); + res.Add(new LSL_Vector(GetPartLocalPos(part))); break; - case (int)ScriptBaseClass.PRIM_LINK_TARGET: if (remain < 3) // setting to 3 on the basis that parsing any usage of PRIM_LINK_TARGET that has nothing following it is pointless. return res; LSL_Integer new_linknumber = rules.GetLSLIntegerItem(idx++); LSL_List new_rules = rules.GetSublist(idx, -1); - - res += llGetLinkPrimitiveParams((int)new_linknumber, new_rules); - return res; + LSL_List tres = llGetLinkPrimitiveParams((int)new_linknumber, new_rules); + res += tres; + return res; + case (int)ScriptBaseClass.PRIM_SLICE: + PrimType prim_type = part.GetPrimType(); + bool useProfileBeginEnd = (prim_type == PrimType.SPHERE || prim_type == PrimType.TORUS || prim_type == PrimType.TUBE || prim_type == PrimType.RING); + res.Add(new LSL_Vector( + (useProfileBeginEnd ? part.Shape.ProfileBegin : part.Shape.PathBegin) / 50000.0, + 1 - (useProfileBeginEnd ? part.Shape.ProfileEnd : part.Shape.PathEnd) / 50000.0, + 0 + )); + break; } } return res; } - public LSL_List GetPrimParams(SceneObjectPart part, LSL_List rules) + public LSL_List llGetPrimMediaParams(int face, LSL_List rules) + { + m_host.AddScriptLPS(1); + ScriptSleep(1000); + return GetPrimMediaParams(m_host, face, rules); + } + + public LSL_List llGetLinkMedia(LSL_Integer link, LSL_Integer face, LSL_List rules) + { + m_host.AddScriptLPS(1); + ScriptSleep(1000); + if (link == ScriptBaseClass.LINK_ROOT) + return GetPrimMediaParams(m_host.ParentGroup.RootPart, face, rules); + else if (link == ScriptBaseClass.LINK_THIS) + return GetPrimMediaParams(m_host, face, rules); + else + { + SceneObjectPart part = m_host.ParentGroup.GetLinkNumPart(link); + if (null != part) + return GetPrimMediaParams(part, face, rules); + } + + return new LSL_List(); + } + + private LSL_List GetPrimMediaParams(SceneObjectPart part, int face, LSL_List rules) { + // LSL Spec http://wiki.secondlife.com/wiki/LlGetPrimMediaParams says to fail silently if face is invalid + // TODO: Need to correctly handle case where a face has no media (which gives back an empty list). + // Assuming silently fail means give back an empty list. Ideally, need to check this. + if (face < 0 || face > part.GetNumberOfSides() - 1) + return new LSL_List(); + + IMoapModule module = m_ScriptEngine.World.RequestModuleInterface(); + if (null == module) + return new LSL_List(); + + MediaEntry me = module.GetMediaEntry(part, face); + + // As per http://wiki.secondlife.com/wiki/LlGetPrimMediaParams + if (null == me) + return new LSL_List(); + LSL_List res = new LSL_List(); - int idx=0; - while (idx < rules.Length) + + for (int i = 0; i < rules.Length; i++) { - int code=(int)rules.GetLSLIntegerItem(idx++); - int remain=rules.Length-idx; + int code = (int)rules.GetLSLIntegerItem(i); switch (code) { - case (int)ScriptBaseClass.PRIM_MATERIAL: - res.Add(new LSL_Integer(part.Material)); + case ScriptBaseClass.PRIM_MEDIA_ALT_IMAGE_ENABLE: + // Not implemented + res.Add(new LSL_Integer(0)); break; - case (int)ScriptBaseClass.PRIM_PHYSICS: - if ((part.GetEffectiveObjectFlags() & (uint)PrimFlags.Physics) != 0) - res.Add(new LSL_Integer(1)); + case ScriptBaseClass.PRIM_MEDIA_CONTROLS: + if (me.Controls == MediaControls.Standard) + res.Add(new LSL_Integer(ScriptBaseClass.PRIM_MEDIA_CONTROLS_STANDARD)); else - res.Add(new LSL_Integer(0)); + res.Add(new LSL_Integer(ScriptBaseClass.PRIM_MEDIA_CONTROLS_MINI)); break; - case (int)ScriptBaseClass.PRIM_TEMP_ON_REZ: - if ((part.GetEffectiveObjectFlags() & (uint)PrimFlags.TemporaryOnRez) != 0) - res.Add(new LSL_Integer(1)); - else - res.Add(new LSL_Integer(0)); + case ScriptBaseClass.PRIM_MEDIA_CURRENT_URL: + res.Add(new LSL_String(me.CurrentURL)); break; - case (int)ScriptBaseClass.PRIM_PHANTOM: - if ((part.GetEffectiveObjectFlags() & (uint)PrimFlags.Phantom) != 0) - res.Add(new LSL_Integer(1)); - else - res.Add(new LSL_Integer(0)); + case ScriptBaseClass.PRIM_MEDIA_HOME_URL: + res.Add(new LSL_String(me.HomeURL)); break; - case (int)ScriptBaseClass.PRIM_POSITION: - LSL_Vector v = new LSL_Vector(part.AbsolutePosition.X, - part.AbsolutePosition.Y, - part.AbsolutePosition.Z); - res.Add(v); + case ScriptBaseClass.PRIM_MEDIA_AUTO_LOOP: + res.Add(me.AutoLoop ? ScriptBaseClass.TRUE : ScriptBaseClass.FALSE); break; - case (int)ScriptBaseClass.PRIM_SIZE: - res.Add(new LSL_Vector(part.Scale.X, - part.Scale.Y, - part.Scale.Z)); + case ScriptBaseClass.PRIM_MEDIA_AUTO_PLAY: + res.Add(me.AutoPlay ? ScriptBaseClass.TRUE : ScriptBaseClass.FALSE); break; - case (int)ScriptBaseClass.PRIM_ROTATION: - res.Add(GetPartRot(part)); + case ScriptBaseClass.PRIM_MEDIA_AUTO_SCALE: + res.Add(me.AutoScale ? ScriptBaseClass.TRUE : ScriptBaseClass.FALSE); break; - case (int)ScriptBaseClass.PRIM_TYPE: - // implementing box - PrimitiveBaseShape Shape = part.Shape; - int primType = (int)part.GetPrimType(); - res.Add(new LSL_Integer(primType)); - double topshearx = (double)(sbyte)Shape.PathShearX / 100.0; // Fix negative values for PathShearX - double topsheary = (double)(sbyte)Shape.PathShearY / 100.0; // and PathShearY. - switch (primType) - { - case ScriptBaseClass.PRIM_TYPE_BOX: - case ScriptBaseClass.PRIM_TYPE_CYLINDER: - case ScriptBaseClass.PRIM_TYPE_PRISM: - res.Add(new LSL_Integer(Shape.ProfileCurve) & 0xf0); // Isolate hole shape nibble. - res.Add(new LSL_Vector(Shape.ProfileBegin / 50000.0, 1 - Shape.ProfileEnd / 50000.0, 0)); - res.Add(new LSL_Float(Shape.ProfileHollow / 50000.0)); - res.Add(new LSL_Vector(Shape.PathTwistBegin / 100.0, Shape.PathTwist / 100.0, 0)); - res.Add(new LSL_Vector(1 - (Shape.PathScaleX / 100.0 - 1), 1 - (Shape.PathScaleY / 100.0 - 1), 0)); - res.Add(new LSL_Vector(topshearx, topsheary, 0)); - break; - - case ScriptBaseClass.PRIM_TYPE_SPHERE: - res.Add(new LSL_Integer(Shape.ProfileCurve) & 0xf0); // Isolate hole shape nibble. - res.Add(new LSL_Vector(Shape.PathBegin / 50000.0, 1 - Shape.PathEnd / 50000.0, 0)); - res.Add(new LSL_Float(Shape.ProfileHollow / 50000.0)); - res.Add(new LSL_Vector(Shape.PathTwistBegin / 100.0, Shape.PathTwist / 100.0, 0)); - res.Add(new LSL_Vector(Shape.ProfileBegin / 50000.0, 1 - Shape.ProfileEnd / 50000.0, 0)); - break; + case ScriptBaseClass.PRIM_MEDIA_AUTO_ZOOM: + res.Add(me.AutoZoom ? ScriptBaseClass.TRUE : ScriptBaseClass.FALSE); + break; - case ScriptBaseClass.PRIM_TYPE_SCULPT: - res.Add(Shape.SculptTexture.ToString()); - res.Add(new LSL_Integer(Shape.SculptType)); - break; - - case ScriptBaseClass.PRIM_TYPE_RING: - case ScriptBaseClass.PRIM_TYPE_TUBE: - case ScriptBaseClass.PRIM_TYPE_TORUS: - // holeshape - res.Add(new LSL_Integer(Shape.ProfileCurve) & 0xf0); // Isolate hole shape nibble. - - // cut - res.Add(new LSL_Vector(Shape.PathBegin / 50000.0, 1 - Shape.PathEnd / 50000.0, 0)); - - // hollow - res.Add(new LSL_Float(Shape.ProfileHollow / 50000.0)); - - // twist - res.Add(new LSL_Vector(Shape.PathTwistBegin / 100.0, Shape.PathTwist / 100.0, 0)); - - // vector holesize - res.Add(new LSL_Vector(1 - (Shape.PathScaleX / 100.0 - 1), 1 - (Shape.PathScaleY / 100.0 - 1), 0)); - - // vector topshear - res.Add(new LSL_Vector(topshearx, topsheary, 0)); - - // vector profilecut - res.Add(new LSL_Vector(Shape.ProfileBegin / 50000.0, 1 - Shape.ProfileEnd / 50000.0, 0)); - - // vector tapera - res.Add(new LSL_Vector(Shape.PathTaperX / 100.0, Shape.PathTaperY / 100.0, 0)); - - // float revolutions - res.Add(new LSL_Float(Math.Round(Shape.PathRevolutions * 0.015d, 2, MidpointRounding.AwayFromZero)) + 1.0d); - // Slightly inaccurate, because an unsigned byte is being used to represent - // the entire range of floating-point values from 1.0 through 4.0 (which is how - // SL does it). - // - // Using these formulas to store and retrieve PathRevolutions, it is not - // possible to use all values between 1.00 and 4.00. For instance, you can't - // represent 1.10. You can represent 1.09 and 1.11, but not 1.10. So, if you - // use llSetPrimitiveParams to set revolutions to 1.10 and then retreive them - // with llGetPrimitiveParams, you'll retrieve 1.09. You can also see a similar - // behavior in the viewer as you cannot set 1.10. The viewer jumps to 1.11. - // In SL, llSetPrimitveParams and llGetPrimitiveParams can set and get a value - // such as 1.10. So, SL must store and retreive the actual user input rather - // than only storing the encoded value. - - // float radiusoffset - res.Add(new LSL_Float(Shape.PathRadiusOffset / 100.0)); - - // float skew - res.Add(new LSL_Float(Shape.PathSkew / 100.0)); - break; - } - break; - - case (int)ScriptBaseClass.PRIM_TEXTURE: - if (remain < 1) - return res; - - int face = (int)rules.GetLSLIntegerItem(idx++); - Primitive.TextureEntry tex = part.Shape.Textures; - if (face == ScriptBaseClass.ALL_SIDES) - { - for (face = 0 ; face < GetNumberOfSides(part); face++) - { - Primitive.TextureEntryFace texface = tex.GetFace((uint)face); - - res.Add(new LSL_String(texface.TextureID.ToString())); - res.Add(new LSL_Vector(texface.RepeatU, - texface.RepeatV, - 0)); - res.Add(new LSL_Vector(texface.OffsetU, - texface.OffsetV, - 0)); - res.Add(new LSL_Float(texface.Rotation)); - } - } - else - { - if (face >= 0 && face < GetNumberOfSides(part)) - { - Primitive.TextureEntryFace texface = tex.GetFace((uint)face); - - res.Add(new LSL_String(texface.TextureID.ToString())); - res.Add(new LSL_Vector(texface.RepeatU, - texface.RepeatV, - 0)); - res.Add(new LSL_Vector(texface.OffsetU, - texface.OffsetV, - 0)); - res.Add(new LSL_Float(texface.Rotation)); - } - } - break; - - case (int)ScriptBaseClass.PRIM_COLOR: - if (remain < 1) - return res; - - face=(int)rules.GetLSLIntegerItem(idx++); - - tex = part.Shape.Textures; - Color4 texcolor; - if (face == ScriptBaseClass.ALL_SIDES) - { - for (face = 0 ; face < GetNumberOfSides(part); face++) - { - texcolor = tex.GetFace((uint)face).RGBA; - res.Add(new LSL_Vector(texcolor.R, - texcolor.G, - texcolor.B)); - res.Add(new LSL_Float(texcolor.A)); - } - } - else - { - texcolor = tex.GetFace((uint)face).RGBA; - res.Add(new LSL_Vector(texcolor.R, - texcolor.G, - texcolor.B)); - res.Add(new LSL_Float(texcolor.A)); - } - break; - - case (int)ScriptBaseClass.PRIM_BUMP_SHINY: - if (remain < 1) - return res; - face = (int)rules.GetLSLIntegerItem(idx++); - - tex = part.Shape.Textures; - int shiny; - if (face == ScriptBaseClass.ALL_SIDES) - { - for (face = 0; face < GetNumberOfSides(part); face++) - { - Shininess shinyness = tex.GetFace((uint)face).Shiny; - if (shinyness == Shininess.High) - { - shiny = ScriptBaseClass.PRIM_SHINY_HIGH; - } - else if (shinyness == Shininess.Medium) - { - shiny = ScriptBaseClass.PRIM_SHINY_MEDIUM; - } - else if (shinyness == Shininess.Low) - { - shiny = ScriptBaseClass.PRIM_SHINY_LOW; - } - else - { - shiny = ScriptBaseClass.PRIM_SHINY_NONE; - } - res.Add(new LSL_Integer(shiny)); - res.Add(new LSL_Integer((int)tex.GetFace((uint)face).Bump)); - } - } - else - { - Shininess shinyness = tex.GetFace((uint)face).Shiny; - if (shinyness == Shininess.High) - { - shiny = ScriptBaseClass.PRIM_SHINY_HIGH; - } - else if (shinyness == Shininess.Medium) - { - shiny = ScriptBaseClass.PRIM_SHINY_MEDIUM; - } - else if (shinyness == Shininess.Low) - { - shiny = ScriptBaseClass.PRIM_SHINY_LOW; - } - else - { - shiny = ScriptBaseClass.PRIM_SHINY_NONE; - } - res.Add(new LSL_Integer(shiny)); - res.Add(new LSL_Integer((int)tex.GetFace((uint)face).Bump)); - } - break; - - case (int)ScriptBaseClass.PRIM_FULLBRIGHT: - if (remain < 1) - return res; - face = (int)rules.GetLSLIntegerItem(idx++); - - tex = part.Shape.Textures; - int fullbright; - if (face == ScriptBaseClass.ALL_SIDES) - { - for (face = 0; face < GetNumberOfSides(part); face++) - { - if (tex.GetFace((uint)face).Fullbright == true) - { - fullbright = ScriptBaseClass.TRUE; - } - else - { - fullbright = ScriptBaseClass.FALSE; - } - res.Add(new LSL_Integer(fullbright)); - } - } - else - { - if (tex.GetFace((uint)face).Fullbright == true) - { - fullbright = ScriptBaseClass.TRUE; - } - else - { - fullbright = ScriptBaseClass.FALSE; - } - res.Add(new LSL_Integer(fullbright)); - } - break; - - case (int)ScriptBaseClass.PRIM_FLEXIBLE: - PrimitiveBaseShape shape = part.Shape; - - if (shape.FlexiEntry) - res.Add(new LSL_Integer(1)); // active - else - res.Add(new LSL_Integer(0)); - res.Add(new LSL_Integer(shape.FlexiSoftness));// softness - res.Add(new LSL_Float(shape.FlexiGravity)); // gravity - res.Add(new LSL_Float(shape.FlexiDrag)); // friction - res.Add(new LSL_Float(shape.FlexiWind)); // wind - res.Add(new LSL_Float(shape.FlexiTension)); // tension - res.Add(new LSL_Vector(shape.FlexiForceX, // force - shape.FlexiForceY, - shape.FlexiForceZ)); - break; - - case (int)ScriptBaseClass.PRIM_TEXGEN: - // (PRIM_TEXGEN_DEFAULT, PRIM_TEXGEN_PLANAR) - if (remain < 1) - return res; - face = (int)rules.GetLSLIntegerItem(idx++); - - tex = part.Shape.Textures; - if (face == ScriptBaseClass.ALL_SIDES) - { - for (face = 0; face < GetNumberOfSides(part); face++) - { - if (tex.GetFace((uint)face).TexMapType == MappingType.Planar) - { - res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_PLANAR)); - } - else - { - res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_DEFAULT)); - } - } - } - else - { - if (tex.GetFace((uint)face).TexMapType == MappingType.Planar) - { - res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_PLANAR)); - } - else - { - res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_DEFAULT)); - } - } - break; - - case (int)ScriptBaseClass.PRIM_POINT_LIGHT: - shape = part.Shape; - - if (shape.LightEntry) - res.Add(new LSL_Integer(1)); // active - else - res.Add(new LSL_Integer(0)); - res.Add(new LSL_Vector(shape.LightColorR, // color - shape.LightColorG, - shape.LightColorB)); - res.Add(new LSL_Float(shape.LightIntensity)); // intensity - res.Add(new LSL_Float(shape.LightRadius)); // radius - res.Add(new LSL_Float(shape.LightFalloff)); // falloff - break; - - case (int)ScriptBaseClass.PRIM_GLOW: - if (remain < 1) - return res; - face = (int)rules.GetLSLIntegerItem(idx++); - - tex = part.Shape.Textures; - float primglow; - if (face == ScriptBaseClass.ALL_SIDES) - { - for (face = 0; face < GetNumberOfSides(part); face++) - { - primglow = tex.GetFace((uint)face).Glow; - res.Add(new LSL_Float(primglow)); - } - } - else - { - primglow = tex.GetFace((uint)face).Glow; - res.Add(new LSL_Float(primglow)); - } - break; - - case (int)ScriptBaseClass.PRIM_TEXT: - Color4 textColor = part.GetTextColor(); - res.Add(new LSL_String(part.Text)); - res.Add(new LSL_Vector(textColor.R, - textColor.G, - textColor.B)); - res.Add(new LSL_Float(textColor.A)); - break; - - case (int)ScriptBaseClass.PRIM_NAME: - res.Add(new LSL_String(part.Name)); - break; - - case (int)ScriptBaseClass.PRIM_DESC: - res.Add(new LSL_String(part.Description)); - break; - - case (int)ScriptBaseClass.PRIM_ROT_LOCAL: - res.Add(new LSL_Rotation(part.RotationOffset.X, part.RotationOffset.Y, part.RotationOffset.Z, part.RotationOffset.W)); - break; - - case (int)ScriptBaseClass.PRIM_POS_LOCAL: - res.Add(new LSL_Vector(GetPartLocalPos(part))); - break; - case (int)ScriptBaseClass.PRIM_LINK_TARGET: - if (remain < 3) // setting to 3 on the basis that parsing any usage of PRIM_LINK_TARGET that has nothing following it is pointless. - return res; - LSL_Integer new_linknumber = rules.GetLSLIntegerItem(idx++); - LSL_List new_rules = rules.GetSublist(idx, -1); - LSL_List tres = llGetLinkPrimitiveParams((int)new_linknumber, new_rules); - res += tres; - return res; - case (int)ScriptBaseClass.PRIM_SLICE: - PrimType prim_type = part.GetPrimType(); - bool useProfileBeginEnd = (prim_type == PrimType.SPHERE || prim_type == PrimType.TORUS || prim_type == PrimType.TUBE || prim_type == PrimType.RING); - res.Add(new LSL_Vector( - (useProfileBeginEnd ? part.Shape.ProfileBegin : part.Shape.PathBegin) / 50000.0, - 1 - (useProfileBeginEnd ? part.Shape.ProfileEnd : part.Shape.PathEnd) / 50000.0, - 0 - )); - break; - } - } - return res; - } - - public LSL_List llGetPrimMediaParams(int face, LSL_List rules) - { - m_host.AddScriptLPS(1); - ScriptSleep(1000); - return GetPrimMediaParams(m_host, face, rules); - } - - public LSL_List llGetLinkMedia(LSL_Integer link, LSL_Integer face, LSL_List rules) - { - m_host.AddScriptLPS(1); - ScriptSleep(1000); - if (link == ScriptBaseClass.LINK_ROOT) - return GetPrimMediaParams(m_host.ParentGroup.RootPart, face, rules); - else if (link == ScriptBaseClass.LINK_THIS) - return GetPrimMediaParams(m_host, face, rules); - else - { - SceneObjectPart part = m_host.ParentGroup.GetLinkNumPart(link); - if (null != part) - return GetPrimMediaParams(part, face, rules); - } - - return new LSL_List(); - } - - private LSL_List GetPrimMediaParams(SceneObjectPart part, int face, LSL_List rules) - { - // LSL Spec http://wiki.secondlife.com/wiki/LlGetPrimMediaParams says to fail silently if face is invalid - // TODO: Need to correctly handle case where a face has no media (which gives back an empty list). - // Assuming silently fail means give back an empty list. Ideally, need to check this. - if (face < 0 || face > part.GetNumberOfSides() - 1) - return new LSL_List(); - - IMoapModule module = m_ScriptEngine.World.RequestModuleInterface(); - if (null == module) - return new LSL_List(); - - MediaEntry me = module.GetMediaEntry(part, face); - - // As per http://wiki.secondlife.com/wiki/LlGetPrimMediaParams - if (null == me) - return new LSL_List(); - - LSL_List res = new LSL_List(); - - for (int i = 0; i < rules.Length; i++) - { - int code = (int)rules.GetLSLIntegerItem(i); - - switch (code) - { - case ScriptBaseClass.PRIM_MEDIA_ALT_IMAGE_ENABLE: - // Not implemented - res.Add(new LSL_Integer(0)); - break; - - case ScriptBaseClass.PRIM_MEDIA_CONTROLS: - if (me.Controls == MediaControls.Standard) - res.Add(new LSL_Integer(ScriptBaseClass.PRIM_MEDIA_CONTROLS_STANDARD)); - else - res.Add(new LSL_Integer(ScriptBaseClass.PRIM_MEDIA_CONTROLS_MINI)); - break; - - case ScriptBaseClass.PRIM_MEDIA_CURRENT_URL: - res.Add(new LSL_String(me.CurrentURL)); - break; - - case ScriptBaseClass.PRIM_MEDIA_HOME_URL: - res.Add(new LSL_String(me.HomeURL)); - break; - - case ScriptBaseClass.PRIM_MEDIA_AUTO_LOOP: - res.Add(me.AutoLoop ? ScriptBaseClass.TRUE : ScriptBaseClass.FALSE); - break; - - case ScriptBaseClass.PRIM_MEDIA_AUTO_PLAY: - res.Add(me.AutoPlay ? ScriptBaseClass.TRUE : ScriptBaseClass.FALSE); - break; - - case ScriptBaseClass.PRIM_MEDIA_AUTO_SCALE: - res.Add(me.AutoScale ? ScriptBaseClass.TRUE : ScriptBaseClass.FALSE); - break; - - case ScriptBaseClass.PRIM_MEDIA_AUTO_ZOOM: - res.Add(me.AutoZoom ? ScriptBaseClass.TRUE : ScriptBaseClass.FALSE); - break; - - case ScriptBaseClass.PRIM_MEDIA_FIRST_CLICK_INTERACT: - res.Add(me.InteractOnFirstClick ? ScriptBaseClass.TRUE : ScriptBaseClass.FALSE); - break; + case ScriptBaseClass.PRIM_MEDIA_FIRST_CLICK_INTERACT: + res.Add(me.InteractOnFirstClick ? ScriptBaseClass.TRUE : ScriptBaseClass.FALSE); + break; case ScriptBaseClass.PRIM_MEDIA_WIDTH_PIXELS: res.Add(new LSL_Integer(me.Width)); @@ -13015,142 +12754,403 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api LSL_Vector sitOffset = (llRot2Up(new LSL_Rotation(av.Rotation.X, av.Rotation.Y, av.Rotation.Z, av.Rotation.W)) * av.Appearance.AvatarHeight * 0.02638f); - v = v + 2 * sitOffset; + v = v + 2 * sitOffset; + + av.OffsetPosition = new Vector3((float)v.x, (float)v.y, (float)v.z); + av.SendAvatarDataToAllAgents(); + + } + break; + + case (int)ScriptBaseClass.PRIM_ROT_LOCAL: + case (int)ScriptBaseClass.PRIM_ROTATION: + { + if (remain < 1) + return null; + + LSL_Rotation r; + r = rules.GetQuaternionItem(idx++); + + SceneObjectPart part = World.GetSceneObjectPart(av.ParentID); + if (part == null) + break; + + LSL_Rotation localRot = ScriptBaseClass.ZERO_ROTATION; + LSL_Vector localPos = ScriptBaseClass.ZERO_VECTOR; + + if (part.LinkNum > 1) + localRot = GetPartLocalRot(part); + + r = r * llGetRootRotation() / localRot; + av.Rotation = new Quaternion((float)r.x, (float)r.y, (float)r.z, (float)r.s); + av.SendAvatarDataToAllAgents(); + } + break; + + // parse rest doing nothing but number of parameters error check + case (int)ScriptBaseClass.PRIM_SIZE: + case (int)ScriptBaseClass.PRIM_MATERIAL: + case (int)ScriptBaseClass.PRIM_PHANTOM: + case (int)ScriptBaseClass.PRIM_PHYSICS: + case (int)ScriptBaseClass.PRIM_PHYSICS_SHAPE_TYPE: + case (int)ScriptBaseClass.PRIM_TEMP_ON_REZ: + case (int)ScriptBaseClass.PRIM_NAME: + case (int)ScriptBaseClass.PRIM_DESC: + if (remain < 1) + return null; + idx++; + break; + + case (int)ScriptBaseClass.PRIM_GLOW: + case (int)ScriptBaseClass.PRIM_FULLBRIGHT: + case (int)ScriptBaseClass.PRIM_TEXGEN: + if (remain < 2) + return null; + idx += 2; + break; + + case (int)ScriptBaseClass.PRIM_TYPE: + if (remain < 3) + return null; + code = (int)rules.GetLSLIntegerItem(idx++); + remain = rules.Length - idx; + switch (code) + { + case (int)ScriptBaseClass.PRIM_TYPE_BOX: + case (int)ScriptBaseClass.PRIM_TYPE_CYLINDER: + case (int)ScriptBaseClass.PRIM_TYPE_PRISM: + if (remain < 6) + return null; + idx += 6; + break; + + case (int)ScriptBaseClass.PRIM_TYPE_SPHERE: + if (remain < 5) + return null; + idx += 5; + break; + + case (int)ScriptBaseClass.PRIM_TYPE_TORUS: + case (int)ScriptBaseClass.PRIM_TYPE_TUBE: + case (int)ScriptBaseClass.PRIM_TYPE_RING: + if (remain < 11) + return null; + idx += 11; + break; + + case (int)ScriptBaseClass.PRIM_TYPE_SCULPT: + if (remain < 2) + return null; + idx += 2; + break; + } + break; + + case (int)ScriptBaseClass.PRIM_COLOR: + case (int)ScriptBaseClass.PRIM_TEXT: + case (int)ScriptBaseClass.PRIM_BUMP_SHINY: + case (int)ScriptBaseClass.PRIM_OMEGA: + if (remain < 3) + return null; + idx += 3; + break; + + case (int)ScriptBaseClass.PRIM_TEXTURE: + case (int)ScriptBaseClass.PRIM_POINT_LIGHT: + case (int)ScriptBaseClass.PRIM_PHYSICS_MATERIAL: + if (remain < 5) + return null; + idx += 5; + break; + + case (int)ScriptBaseClass.PRIM_FLEXIBLE: + if (remain < 7) + return null; + + idx += 7; + break; + + case (int)ScriptBaseClass.PRIM_LINK_TARGET: + if (remain < 3) // setting to 3 on the basis that parsing any usage of PRIM_LINK_TARGET that has nothing following it is pointless. + return null; + + return rules.GetSublist(idx, -1); + } + } + } + + finally + { + if (positionChanged) + { + av.OffsetPosition = finalPos; +// av.SendAvatarDataToAllAgents(); + av.SendTerseUpdateToAllClients(); + positionChanged = false; + } + } + return null; + } + + public LSL_List GetPrimParams(ScenePresence avatar, LSL_List rules) + { + // avatars case + // replies as SL wiki + + LSL_List res = new LSL_List(); +// SceneObjectPart sitPart = avatar.ParentPart; // most likelly it will be needed + SceneObjectPart sitPart = World.GetSceneObjectPart(avatar.ParentID); // maybe better do this expensive search for it in case it's gone?? + + int idx = 0; + while (idx < rules.Length) + { + int code = (int)rules.GetLSLIntegerItem(idx++); + int remain = rules.Length - idx; + + switch (code) + { + case (int)ScriptBaseClass.PRIM_MATERIAL: + res.Add(new LSL_Integer((int)SOPMaterialData.SopMaterial.Flesh)); + break; + + case (int)ScriptBaseClass.PRIM_PHYSICS: + res.Add(new LSL_Integer(0)); + break; + + case (int)ScriptBaseClass.PRIM_TEMP_ON_REZ: + res.Add(new LSL_Integer(0)); + break; + + case (int)ScriptBaseClass.PRIM_PHANTOM: + res.Add(new LSL_Integer(0)); + break; + + case (int)ScriptBaseClass.PRIM_POSITION: + + Vector3 pos = avatar.OffsetPosition; + + Vector3 sitOffset = (Zrot(avatar.Rotation)) * (avatar.Appearance.AvatarHeight * 0.02638f *2.0f); + pos -= sitOffset; + + if( sitPart != null) + pos = sitPart.GetWorldPosition() + pos * sitPart.GetWorldRotation(); + + res.Add(new LSL_Vector(pos.X,pos.Y,pos.Z)); + break; + + case (int)ScriptBaseClass.PRIM_SIZE: + // as in llGetAgentSize above + res.Add(new LSL_Vector(0.45f, 0.6f, avatar.Appearance.AvatarHeight)); + break; + + case (int)ScriptBaseClass.PRIM_ROTATION: + Quaternion rot = avatar.Rotation; + if (sitPart != null) + { + rot = sitPart.GetWorldRotation() * rot; // apply sit part world rotation + } + + res.Add(new LSL_Rotation (rot.X, rot.Y, rot.Z, rot.W)); + break; + + case (int)ScriptBaseClass.PRIM_TYPE: + res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TYPE_BOX)); + res.Add(new LSL_Integer(ScriptBaseClass.PRIM_HOLE_DEFAULT)); + res.Add(new LSL_Vector(0f,1.0f,0f)); + res.Add(new LSL_Float(0.0f)); + res.Add(new LSL_Vector(0, 0, 0)); + res.Add(new LSL_Vector(1.0f,1.0f,0f)); + res.Add(new LSL_Vector(0, 0, 0)); + break; + + case (int)ScriptBaseClass.PRIM_TEXTURE: + if (remain < 1) + return res; + + int face = (int)rules.GetLSLIntegerItem(idx++); + if (face == ScriptBaseClass.ALL_SIDES) + { + for (face = 0; face < 21; face++) + { + res.Add(new LSL_String("")); + res.Add(new LSL_Vector(0,0,0)); + res.Add(new LSL_Vector(0,0,0)); + res.Add(new LSL_Float(0.0)); + } + } + else + { + if (face >= 0 && face < 21) + { + res.Add(new LSL_String("")); + res.Add(new LSL_Vector(0,0,0)); + res.Add(new LSL_Vector(0,0,0)); + res.Add(new LSL_Float(0.0)); + } + } + break; + + case (int)ScriptBaseClass.PRIM_COLOR: + if (remain < 1) + return res; - av.OffsetPosition = new Vector3((float)v.x, (float)v.y, (float)v.z); - av.SendAvatarDataToAllAgents(); + face = (int)rules.GetLSLIntegerItem(idx++); + if (face == ScriptBaseClass.ALL_SIDES) + { + for (face = 0; face < 21; face++) + { + res.Add(new LSL_Vector(0,0,0)); + res.Add(new LSL_Float(0)); } - break; + } + else + { + res.Add(new LSL_Vector(0,0,0)); + res.Add(new LSL_Float(0)); + } + break; - case (int)ScriptBaseClass.PRIM_ROT_LOCAL: - case (int)ScriptBaseClass.PRIM_ROTATION: + case (int)ScriptBaseClass.PRIM_BUMP_SHINY: + if (remain < 1) + return res; + face = (int)rules.GetLSLIntegerItem(idx++); + + if (face == ScriptBaseClass.ALL_SIDES) + { + for (face = 0; face < 21; face++) { - if (remain < 1) - return null; + res.Add(new LSL_Integer(ScriptBaseClass.PRIM_SHINY_NONE)); + res.Add(new LSL_Integer(ScriptBaseClass.PRIM_BUMP_NONE)); + } + } + else + { + res.Add(new LSL_Integer(ScriptBaseClass.PRIM_SHINY_NONE)); + res.Add(new LSL_Integer(ScriptBaseClass.PRIM_BUMP_NONE)); + } + break; - LSL_Rotation r; - r = rules.GetQuaternionItem(idx++); + case (int)ScriptBaseClass.PRIM_FULLBRIGHT: + if (remain < 1) + return res; + face = (int)rules.GetLSLIntegerItem(idx++); - SceneObjectPart part = World.GetSceneObjectPart(av.ParentID); - if (part == null) - break; + if (face == ScriptBaseClass.ALL_SIDES) + { + for (face = 0; face < 21; face++) + { + res.Add(new LSL_Integer(ScriptBaseClass.FALSE)); + } + } + else + { + res.Add(new LSL_Integer(ScriptBaseClass.FALSE)); + } + break; - LSL_Rotation localRot = ScriptBaseClass.ZERO_ROTATION; - LSL_Vector localPos = ScriptBaseClass.ZERO_VECTOR; + case (int)ScriptBaseClass.PRIM_FLEXIBLE: + res.Add(new LSL_Integer(0)); + res.Add(new LSL_Integer(0));// softness + res.Add(new LSL_Float(0.0f)); // gravity + res.Add(new LSL_Float(0.0f)); // friction + res.Add(new LSL_Float(0.0f)); // wind + res.Add(new LSL_Float(0.0f)); // tension + res.Add(new LSL_Vector(0f,0f,0f)); + break; - if (part.LinkNum > 1) - localRot = GetPartLocalRot(part); + case (int)ScriptBaseClass.PRIM_TEXGEN: + // (PRIM_TEXGEN_DEFAULT, PRIM_TEXGEN_PLANAR) + if (remain < 1) + return res; + face = (int)rules.GetLSLIntegerItem(idx++); - r = r * llGetRootRotation() / localRot; - av.Rotation = new Quaternion((float)r.x, (float)r.y, (float)r.z, (float)r.s); - av.SendAvatarDataToAllAgents(); + if (face == ScriptBaseClass.ALL_SIDES) + { + for (face = 0; face < 21; face++) + { + res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_DEFAULT)); } - break; + } + else + { + res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_DEFAULT)); + } + break; - // parse rest doing nothing but number of parameters error check - case (int)ScriptBaseClass.PRIM_SIZE: - case (int)ScriptBaseClass.PRIM_MATERIAL: - case (int)ScriptBaseClass.PRIM_PHANTOM: - case (int)ScriptBaseClass.PRIM_PHYSICS: - case (int)ScriptBaseClass.PRIM_PHYSICS_SHAPE_TYPE: - case (int)ScriptBaseClass.PRIM_TEMP_ON_REZ: - case (int)ScriptBaseClass.PRIM_NAME: - case (int)ScriptBaseClass.PRIM_DESC: - if (remain < 1) - return null; - idx++; - break; + case (int)ScriptBaseClass.PRIM_POINT_LIGHT: + res.Add(new LSL_Integer(0)); + res.Add(new LSL_Vector(0f,0f,0f)); + res.Add(new LSL_Float(0f)); // intensity + res.Add(new LSL_Float(0f)); // radius + res.Add(new LSL_Float(0f)); // falloff + break; - case (int)ScriptBaseClass.PRIM_GLOW: - case (int)ScriptBaseClass.PRIM_FULLBRIGHT: - case (int)ScriptBaseClass.PRIM_TEXGEN: - if (remain < 2) - return null; - idx += 2; - break; + case (int)ScriptBaseClass.PRIM_GLOW: + if (remain < 1) + return res; + face = (int)rules.GetLSLIntegerItem(idx++); - case (int)ScriptBaseClass.PRIM_TYPE: - if (remain < 3) - return null; - code = (int)rules.GetLSLIntegerItem(idx++); - remain = rules.Length - idx; - switch (code) + if (face == ScriptBaseClass.ALL_SIDES) + { + for (face = 0; face < 21; face++) { - case (int)ScriptBaseClass.PRIM_TYPE_BOX: - case (int)ScriptBaseClass.PRIM_TYPE_CYLINDER: - case (int)ScriptBaseClass.PRIM_TYPE_PRISM: - if (remain < 6) - return null; - idx += 6; - break; - - case (int)ScriptBaseClass.PRIM_TYPE_SPHERE: - if (remain < 5) - return null; - idx += 5; - break; + res.Add(new LSL_Float(0f)); + } + } + else + { + res.Add(new LSL_Float(0f)); + } + break; - case (int)ScriptBaseClass.PRIM_TYPE_TORUS: - case (int)ScriptBaseClass.PRIM_TYPE_TUBE: - case (int)ScriptBaseClass.PRIM_TYPE_RING: - if (remain < 11) - return null; - idx += 11; - break; + case (int)ScriptBaseClass.PRIM_TEXT: + res.Add(new LSL_String("")); + res.Add(new LSL_Vector(0f,0f,0f)); + res.Add(new LSL_Float(1.0f)); + break; - case (int)ScriptBaseClass.PRIM_TYPE_SCULPT: - if (remain < 2) - return null; - idx += 2; - break; - } - break; + case (int)ScriptBaseClass.PRIM_NAME: + res.Add(new LSL_String(avatar.Name)); + break; - case (int)ScriptBaseClass.PRIM_COLOR: - case (int)ScriptBaseClass.PRIM_TEXT: - case (int)ScriptBaseClass.PRIM_BUMP_SHINY: - case (int)ScriptBaseClass.PRIM_OMEGA: - if (remain < 3) - return null; - idx += 3; - break; + case (int)ScriptBaseClass.PRIM_DESC: + res.Add(new LSL_String("")); + break; - case (int)ScriptBaseClass.PRIM_TEXTURE: - case (int)ScriptBaseClass.PRIM_POINT_LIGHT: - case (int)ScriptBaseClass.PRIM_PHYSICS_MATERIAL: - if (remain < 5) - return null; - idx += 5; - break; + case (int)ScriptBaseClass.PRIM_ROT_LOCAL: + Quaternion lrot = avatar.Rotation; - case (int)ScriptBaseClass.PRIM_FLEXIBLE: - if (remain < 7) - return null; + if (sitPart != null && sitPart != sitPart.ParentGroup.RootPart) + { + lrot = sitPart.RotationOffset * lrot; // apply sit part rotation offset + } + res.Add(new LSL_Rotation(lrot.X, lrot.Y, lrot.Z, lrot.W)); + break; - idx += 7; - break; + case (int)ScriptBaseClass.PRIM_POS_LOCAL: + Vector3 lpos = avatar.OffsetPosition; // pos relative to sit part + Vector3 lsitOffset = (Zrot(avatar.Rotation)) * (avatar.Appearance.AvatarHeight * 0.02638f * 2.0f); + lpos -= lsitOffset; - case (int)ScriptBaseClass.PRIM_LINK_TARGET: - if (remain < 3) // setting to 3 on the basis that parsing any usage of PRIM_LINK_TARGET that has nothing following it is pointless. - return null; + if (sitPart != null && sitPart != sitPart.ParentGroup.RootPart) + { + lpos = sitPart.OffsetPosition + (lpos * sitPart.RotationOffset); // make it relative to root prim + } + res.Add(new LSL_Vector(lpos.X,lpos.Y,lpos.Z)); + break; - return rules.GetSublist(idx, -1); - } - } - } + case (int)ScriptBaseClass.PRIM_LINK_TARGET: + if (remain < 3) // setting to 3 on the basis that parsing any usage of PRIM_LINK_TARGET that has nothing following it is pointless. + return res; + LSL_Integer new_linknumber = rules.GetLSLIntegerItem(idx++); + LSL_List new_rules = rules.GetSublist(idx, -1); - finally - { - if (positionChanged) - { - av.OffsetPosition = finalPos; -// av.SendAvatarDataToAllAgents(); - av.SendTerseUpdateToAllClients(); - positionChanged = false; + res += llGetLinkPrimitiveParams((int)new_linknumber, new_rules); + return res; } } - return null; + return res; } } } -- cgit v1.1 From 86d4e45f4d5ce7de4a2043dfe753f620925e28c4 Mon Sep 17 00:00:00 2001 From: Melanie Date: Sat, 25 Aug 2012 21:03:47 +0100 Subject: since we will be making the Get return type the remaining ruleset as with the Set return type, we need to move the original return type to a ref param Conflicts: OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs --- .../Shared/Api/Implementation/LSL_Api.cs | 274 +++++++++++---------- .../Shared/Api/Implementation/OSSL_Api.cs | 2 +- 2 files changed, 139 insertions(+), 137 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 64f145b..fbb91ce 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -8636,7 +8636,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public LSL_List llGetPrimitiveParams(LSL_List rules) { m_host.AddScriptLPS(1); - return GetPrimParams(m_host, rules); + + LSL_List result = new LSL_List(); + + GetPrimParams(m_host, rules, ref result); + + return result; } public LSL_List llGetLinkPrimitiveParams(int linknumber, LSL_List rules) @@ -8655,24 +8660,22 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { foreach (var part in parts) { - LSL_List partRes = GetPrimParams(part, rules); - res += partRes; + GetPrimParams(part, rules, ref res); } } if (avatars.Count > 0) { foreach (ScenePresence avatar in avatars) { - LSL_List avaRes = GetPrimParams(avatar, rules); - res += avaRes; + GetPrimParams(avatar, rules, ref res); } + // TODO: FINISH MERGE } return res; } - public LSL_List GetPrimParams(SceneObjectPart part, LSL_List rules) + public void GetPrimParams(SceneObjectPart part, LSL_List rules, ref LSL_List res) { - LSL_List res = new LSL_List(); int idx=0; while (idx < rules.Length) { @@ -8810,7 +8813,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api case (int)ScriptBaseClass.PRIM_TEXTURE: if (remain < 1) - return res; + return; int face = (int)rules.GetLSLIntegerItem(idx++); Primitive.TextureEntry tex = part.Shape.Textures; @@ -8850,7 +8853,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api case (int)ScriptBaseClass.PRIM_COLOR: if (remain < 1) - return res; + return; face=(int)rules.GetLSLIntegerItem(idx++); @@ -8879,7 +8882,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api case (int)ScriptBaseClass.PRIM_BUMP_SHINY: if (remain < 1) - return res; + return; face = (int)rules.GetLSLIntegerItem(idx++); tex = part.Shape.Textures; @@ -8935,7 +8938,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api case (int)ScriptBaseClass.PRIM_FULLBRIGHT: if (remain < 1) - return res; + return; face = (int)rules.GetLSLIntegerItem(idx++); tex = part.Shape.Textures; @@ -8989,7 +8992,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api case (int)ScriptBaseClass.PRIM_TEXGEN: // (PRIM_TEXGEN_DEFAULT, PRIM_TEXGEN_PLANAR) if (remain < 1) - return res; + return; face = (int)rules.GetLSLIntegerItem(idx++); tex = part.Shape.Textures; @@ -9037,7 +9040,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api case (int)ScriptBaseClass.PRIM_GLOW: if (remain < 1) - return res; + return; face = (int)rules.GetLSLIntegerItem(idx++); tex = part.Shape.Textures; @@ -9083,12 +9086,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api break; case (int)ScriptBaseClass.PRIM_LINK_TARGET: if (remain < 3) // setting to 3 on the basis that parsing any usage of PRIM_LINK_TARGET that has nothing following it is pointless. - return res; + return; LSL_Integer new_linknumber = rules.GetLSLIntegerItem(idx++); LSL_List new_rules = rules.GetSublist(idx, -1); LSL_List tres = llGetLinkPrimitiveParams((int)new_linknumber, new_rules); res += tres; - return res; + return; case (int)ScriptBaseClass.PRIM_SLICE: PrimType prim_type = part.GetPrimType(); bool useProfileBeginEnd = (prim_type == PrimType.SPHERE || prim_type == PrimType.TORUS || prim_type == PrimType.TUBE || prim_type == PrimType.RING); @@ -9100,7 +9103,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api break; } } - return res; } public LSL_List llGetPrimMediaParams(int face, LSL_List rules) @@ -11661,13 +11663,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public LSL_List GetPrimitiveParamsEx(LSL_Key prim, LSL_List rules) { SceneObjectPart obj = World.GetSceneObjectPart(new UUID(prim)); - if (obj == null) - return new LSL_List(); - if (obj.OwnerID != m_host.OwnerID) - return new LSL_List(); + LSL_List result = new LSL_List(); - return GetPrimParams(obj, rules); + if (obj != null && obj.OwnerID != m_host.OwnerID) + { + GetPrimParams(obj, rules, ref result); + } + + return result; } public LSL_Integer llGetLinkNumberOfSides(LSL_Integer link) @@ -12604,110 +12608,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } } } - } - - public class NotecardCache - { - protected class Notecard - { - public string[] text; - public DateTime lastRef; - } - - protected static Dictionary m_Notecards = - new Dictionary(); - - public static void Cache(UUID assetID, string text) - { - CacheCheck(); - - lock (m_Notecards) - { - if (m_Notecards.ContainsKey(assetID)) - return; - - Notecard nc = new Notecard(); - nc.lastRef = DateTime.Now; - nc.text = SLUtil.ParseNotecardToList(text).ToArray(); - m_Notecards[assetID] = nc; - } - } - - public static bool IsCached(UUID assetID) - { - lock (m_Notecards) - { - return m_Notecards.ContainsKey(assetID); - } - } - - public static int GetLines(UUID assetID) - { - if (!IsCached(assetID)) - return -1; - - lock (m_Notecards) - { - m_Notecards[assetID].lastRef = DateTime.Now; - return m_Notecards[assetID].text.Length; - } - } - - /// - /// Get a notecard line. - /// - /// - /// Lines start at index 0 - /// - public static string GetLine(UUID assetID, int lineNumber) - { - if (lineNumber < 0) - return ""; - - string data; - - if (!IsCached(assetID)) - return ""; - - lock (m_Notecards) - { - m_Notecards[assetID].lastRef = DateTime.Now; - - if (lineNumber >= m_Notecards[assetID].text.Length) - return "\n\n\n"; - - data = m_Notecards[assetID].text[lineNumber]; - - return data; - } - } - - /// - /// Get a notecard line. - /// - /// - /// Lines start at index 0 - /// Maximum length of the returned line. Longer lines will be truncated - /// - public static string GetLine(UUID assetID, int lineNumber, int maxLength) - { - string line = GetLine(assetID, lineNumber); - - if (line.Length > maxLength) - line = line.Substring(0, maxLength); - - return line; - } - - public static void CacheCheck() - { - foreach (UUID key in new List(m_Notecards.Keys)) - { - Notecard nc = m_Notecards[key]; - if (nc.lastRef.AddSeconds(30) < DateTime.Now) - m_Notecards.Remove(key); - } - } protected LSL_List SetPrimParams(ScenePresence av, LSL_List rules) { @@ -12892,12 +12792,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api return null; } - public LSL_List GetPrimParams(ScenePresence avatar, LSL_List rules) + public void GetPrimParams(ScenePresence avatar, LSL_List rules, ref LSL_List res) { // avatars case // replies as SL wiki - LSL_List res = new LSL_List(); // SceneObjectPart sitPart = avatar.ParentPart; // most likelly it will be needed SceneObjectPart sitPart = World.GetSceneObjectPart(avatar.ParentID); // maybe better do this expensive search for it in case it's gone?? @@ -12965,7 +12864,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api case (int)ScriptBaseClass.PRIM_TEXTURE: if (remain < 1) - return res; + return; int face = (int)rules.GetLSLIntegerItem(idx++); if (face == ScriptBaseClass.ALL_SIDES) @@ -12992,7 +12891,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api case (int)ScriptBaseClass.PRIM_COLOR: if (remain < 1) - return res; + return; face = (int)rules.GetLSLIntegerItem(idx++); @@ -13013,7 +12912,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api case (int)ScriptBaseClass.PRIM_BUMP_SHINY: if (remain < 1) - return res; + return; face = (int)rules.GetLSLIntegerItem(idx++); if (face == ScriptBaseClass.ALL_SIDES) @@ -13033,7 +12932,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api case (int)ScriptBaseClass.PRIM_FULLBRIGHT: if (remain < 1) - return res; + return; face = (int)rules.GetLSLIntegerItem(idx++); if (face == ScriptBaseClass.ALL_SIDES) @@ -13062,7 +12961,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api case (int)ScriptBaseClass.PRIM_TEXGEN: // (PRIM_TEXGEN_DEFAULT, PRIM_TEXGEN_PLANAR) if (remain < 1) - return res; + return; face = (int)rules.GetLSLIntegerItem(idx++); if (face == ScriptBaseClass.ALL_SIDES) @@ -13088,7 +12987,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api case (int)ScriptBaseClass.PRIM_GLOW: if (remain < 1) - return res; + return; face = (int)rules.GetLSLIntegerItem(idx++); if (face == ScriptBaseClass.ALL_SIDES) @@ -13142,15 +13041,118 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api case (int)ScriptBaseClass.PRIM_LINK_TARGET: if (remain < 3) // setting to 3 on the basis that parsing any usage of PRIM_LINK_TARGET that has nothing following it is pointless. - return res; + return; LSL_Integer new_linknumber = rules.GetLSLIntegerItem(idx++); LSL_List new_rules = rules.GetSublist(idx, -1); res += llGetLinkPrimitiveParams((int)new_linknumber, new_rules); - return res; + return; } } - return res; + } + } + + public class NotecardCache + { + protected class Notecard + { + public string[] text; + public DateTime lastRef; + } + + protected static Dictionary m_Notecards = + new Dictionary(); + + public static void Cache(UUID assetID, string text) + { + CacheCheck(); + + lock (m_Notecards) + { + if (m_Notecards.ContainsKey(assetID)) + return; + + Notecard nc = new Notecard(); + nc.lastRef = DateTime.Now; + nc.text = SLUtil.ParseNotecardToList(text).ToArray(); + m_Notecards[assetID] = nc; + } + } + + public static bool IsCached(UUID assetID) + { + lock (m_Notecards) + { + return m_Notecards.ContainsKey(assetID); + } + } + + public static int GetLines(UUID assetID) + { + if (!IsCached(assetID)) + return -1; + + lock (m_Notecards) + { + m_Notecards[assetID].lastRef = DateTime.Now; + return m_Notecards[assetID].text.Length; + } + } + + /// + /// Get a notecard line. + /// + /// + /// Lines start at index 0 + /// + public static string GetLine(UUID assetID, int lineNumber) + { + if (lineNumber < 0) + return ""; + + string data; + + if (!IsCached(assetID)) + return ""; + + lock (m_Notecards) + { + m_Notecards[assetID].lastRef = DateTime.Now; + + if (lineNumber >= m_Notecards[assetID].text.Length) + return "\n\n\n"; + + data = m_Notecards[assetID].text[lineNumber]; + + return data; + } + } + + /// + /// Get a notecard line. + /// + /// + /// Lines start at index 0 + /// Maximum length of the returned line. Longer lines will be truncated + /// + public static string GetLine(UUID assetID, int lineNumber, int maxLength) + { + string line = GetLine(assetID, lineNumber); + + if (line.Length > maxLength) + line = line.Substring(0, maxLength); + + return line; + } + + public static void CacheCheck() + { + foreach (UUID key in new List(m_Notecards.Keys)) + { + Notecard nc = m_Notecards[key]; + if (nc.lastRef.AddSeconds(30) < DateTime.Now) + m_Notecards.Remove(key); + } } } } diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs index 7b71a24..efd1f39 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs @@ -2261,7 +2261,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api List parts = ((LSL_Api)m_LSL_Api).GetLinkParts(linknumber); foreach (SceneObjectPart part in parts) { - retVal += ((LSL_Api)m_LSL_Api).GetPrimParams(part, rules); + ((LSL_Api)m_LSL_Api).GetPrimParams(part, rules, ref retVal); } return retVal; } -- cgit v1.1 From 3d8f393fbe0072d93fc8303741420bb36c844d44 Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Fri, 24 Aug 2012 17:25:37 +0100 Subject: refactoring to local variable for cleaner code --- OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs index efd1f39..43cfea2 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs @@ -2257,11 +2257,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api CheckThreatLevel(ThreatLevel.High, "osGetLinkPrimitiveParams"); m_host.AddScriptLPS(1); InitLSL(); + // One needs to cast m_LSL_Api because we're using functions not + // on the ILSL_Api interface. + LSL_Api LSL_Api = (LSL_Api)m_LSL_Api; LSL_List retVal = new LSL_List(); - List parts = ((LSL_Api)m_LSL_Api).GetLinkParts(linknumber); + List parts = LSL_Api.GetLinkParts(linknumber); foreach (SceneObjectPart part in parts) { - ((LSL_Api)m_LSL_Api).GetPrimParams(part, rules, ref retVal); + LSL_Api.GetPrimParams(part, rules, ref retVal); } return retVal; } -- cgit v1.1 From bc4bda4441c51779b94307ad60782b037f0a3f2c Mon Sep 17 00:00:00 2001 From: Melanie Date: Sat, 25 Aug 2012 21:08:33 +0100 Subject: Minor formatting cleanup --- OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 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 fbb91ce..ed3c2a4 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -7735,10 +7735,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api remaining = SetPrimParams((ScenePresence)part, rules); } - while((object)remaining != null && remaining.Length > 2) + while ((object)remaining != null && remaining.Length > 2) { linknumber = remaining.GetLSLIntegerItem(0); - rules = remaining.GetSublist(1,-1); + rules = remaining.GetSublist(1, -1); parts.Clear(); prims = GetLinkParts(linknumber); avatars = GetLinkAvatars(linknumber); -- cgit v1.1 From e90168c7382f7750faa001542652e2316841c961 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Mon, 27 Aug 2012 22:42:40 +0100 Subject: Add VectorRenderModuleTests.TestRepeatDraw() --- .../VectorRender/Tests/VectorRenderModuleTests.cs | 59 ++++++++++++++++++---- 1 file changed, 48 insertions(+), 11 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/Scripting/VectorRender/Tests/VectorRenderModuleTests.cs b/OpenSim/Region/CoreModules/Scripting/VectorRender/Tests/VectorRenderModuleTests.cs index 9787c8c..f9b5a59 100644 --- a/OpenSim/Region/CoreModules/Scripting/VectorRender/Tests/VectorRenderModuleTests.cs +++ b/OpenSim/Region/CoreModules/Scripting/VectorRender/Tests/VectorRenderModuleTests.cs @@ -45,31 +45,68 @@ using OpenSim.Tests.Common.Mock; namespace OpenSim.Region.CoreModules.Scripting.VectorRender.Tests { [TestFixture] - public class VectorRenderModuleTests + public class VectorRenderModuleTests : OpenSimTestCase { + Scene m_scene; + DynamicTextureModule m_dtm; + VectorRenderModule m_vrm; + + [SetUp] + public void SetUp() + { + m_scene = new SceneHelpers().SetupScene(); + m_dtm = new DynamicTextureModule(); + m_vrm = new VectorRenderModule(); + SceneHelpers.SetupSceneModules(m_scene, m_dtm, m_vrm); + } + [Test] public void TestDraw() { TestHelpers.InMethod(); - Scene scene = new SceneHelpers().SetupScene(); - DynamicTextureModule dtm = new DynamicTextureModule(); - VectorRenderModule vrm = new VectorRenderModule(); - SceneHelpers.SetupSceneModules(scene, dtm, vrm); - - SceneObjectGroup so = SceneHelpers.AddSceneObject(scene); + SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene); UUID originalTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID; - dtm.AddDynamicTextureData( - scene.RegionInfo.RegionID, + m_dtm.AddDynamicTextureData( + m_scene.RegionInfo.RegionID, so.UUID, - vrm.GetContentType(), + m_vrm.GetContentType(), "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;", "", 0); - Assert.That(originalTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID)); } + + [Test] + public void TestRepeatDraw() + { + TestHelpers.InMethod(); + + string dtText = "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;"; + + SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene); + + m_dtm.AddDynamicTextureData( + m_scene.RegionInfo.RegionID, + so.UUID, + m_vrm.GetContentType(), + dtText, + "", + 0); + + UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID; + + m_dtm.AddDynamicTextureData( + m_scene.RegionInfo.RegionID, + so.UUID, + m_vrm.GetContentType(), + dtText, + "", + 0); + + Assert.That(firstDynamicTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID)); + } } } \ No newline at end of file -- cgit v1.1 From 3082fdd0f6d73fa07fe2266170fcd3e5e572f2a2 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Mon, 27 Aug 2012 22:58:20 +0100 Subject: Add VectorRenderModuleTests.TestRepeatDrawContainingImage() --- .../VectorRender/Tests/VectorRenderModuleTests.cs | 31 ++++++++++++++++++++++ 1 file changed, 31 insertions(+) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/Scripting/VectorRender/Tests/VectorRenderModuleTests.cs b/OpenSim/Region/CoreModules/Scripting/VectorRender/Tests/VectorRenderModuleTests.cs index f9b5a59..21e1d54 100644 --- a/OpenSim/Region/CoreModules/Scripting/VectorRender/Tests/VectorRenderModuleTests.cs +++ b/OpenSim/Region/CoreModules/Scripting/VectorRender/Tests/VectorRenderModuleTests.cs @@ -108,5 +108,36 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender.Tests Assert.That(firstDynamicTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID)); } + + [Test] + public void TestRepeatDrawContainingImage() + { + TestHelpers.InMethod(); + + string dtText + = "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World; Image http://localhost/shouldnotexist.png"; + + SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene); + + m_dtm.AddDynamicTextureData( + m_scene.RegionInfo.RegionID, + so.UUID, + m_vrm.GetContentType(), + dtText, + "", + 0); + + UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID; + + m_dtm.AddDynamicTextureData( + m_scene.RegionInfo.RegionID, + so.UUID, + m_vrm.GetContentType(), + dtText, + "", + 0); + + Assert.That(firstDynamicTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID)); + } } } \ No newline at end of file -- cgit v1.1 From 4e26d039d6ffe03ae9509120015b39692bad44f9 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Mon, 27 Aug 2012 23:03:21 +0100 Subject: Add VectorRenderModule.TestRepeatSameDrawDifferentExtraParams() --- .../VectorRender/Tests/VectorRenderModuleTests.cs | 34 ++++++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/Scripting/VectorRender/Tests/VectorRenderModuleTests.cs b/OpenSim/Region/CoreModules/Scripting/VectorRender/Tests/VectorRenderModuleTests.cs index 21e1d54..180ea9f 100644 --- a/OpenSim/Region/CoreModules/Scripting/VectorRender/Tests/VectorRenderModuleTests.cs +++ b/OpenSim/Region/CoreModules/Scripting/VectorRender/Tests/VectorRenderModuleTests.cs @@ -80,7 +80,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender.Tests } [Test] - public void TestRepeatDraw() + public void TestRepeatSameDraw() { TestHelpers.InMethod(); @@ -110,7 +110,37 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender.Tests } [Test] - public void TestRepeatDrawContainingImage() + public void TestRepeatSameDrawDifferentExtraParams() + { + TestHelpers.InMethod(); + + string dtText = "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;"; + + SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene); + + m_dtm.AddDynamicTextureData( + m_scene.RegionInfo.RegionID, + so.UUID, + m_vrm.GetContentType(), + dtText, + "", + 0); + + UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID; + + m_dtm.AddDynamicTextureData( + m_scene.RegionInfo.RegionID, + so.UUID, + m_vrm.GetContentType(), + dtText, + "alpha:250", + 0); + + Assert.That(firstDynamicTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID)); + } + + [Test] + public void TestRepeatSameDrawContainingImage() { TestHelpers.InMethod(); -- cgit v1.1 From ab9bfe5156d955ca02b7cfcb0ccb5919f6b0743d Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Mon, 27 Aug 2012 23:06:37 +0100 Subject: minor: Simplify return of vector render module name and some very minor removal of unncessary syntax clutter --- .../CoreModules/Scripting/VectorRender/VectorRenderModule.cs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs b/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs index c48a703..f988c0e 100644 --- a/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs +++ b/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs @@ -47,7 +47,6 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - private string m_name = "VectorRenderModule"; private Scene m_scene; private IDynamicTextureManager m_textureManager; private Graphics m_graph; @@ -61,12 +60,12 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender public string GetContentType() { - return ("vector"); + return "vector"; } public string GetName() { - return m_name; + return Name; } public bool SupportsAsynchronous() @@ -152,7 +151,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender public string Name { - get { return m_name; } + get { return "VectorRenderModule"; } } public bool IsSharedModule -- cgit v1.1 From a6d689c529e443df58eb218ccb512c516fb7cc81 Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Sun, 26 Aug 2012 22:52:33 +0100 Subject: refactoring to assign the first argument to a variable --- OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs b/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs index 3f848ed..3546654 100644 --- a/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs +++ b/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs @@ -1176,7 +1176,8 @@ namespace OpenSim.Region.CoreModules.World.Terrain private void InterfaceRunPluginEffect(Object[] args) { - if ((string) args[0] == "list") + string firstArg = (string)args[0]; + if (firstArg == "list") { m_log.Info("List of loaded plugins"); foreach (KeyValuePair kvp in m_plugineffects) @@ -1185,14 +1186,14 @@ namespace OpenSim.Region.CoreModules.World.Terrain } return; } - if ((string) args[0] == "reload") + if (firstArg == "reload") { LoadPlugins(); return; } - if (m_plugineffects.ContainsKey((string) args[0])) + if (m_plugineffects.ContainsKey(firstArg)) { - m_plugineffects[(string) args[0]].RunEffect(m_channel); + m_plugineffects[firstArg].RunEffect(m_channel); CheckForTerrainUpdates(); } else -- cgit v1.1 From 72c2d13ac6e350317b59b04bca9c79f371f0528a Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Sun, 26 Aug 2012 22:53:59 +0100 Subject: refactoring to load from self (fixes ChanneDigger being absent) --- .../Region/CoreModules/World/Terrain/TerrainModule.cs | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs b/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs index 3546654..620d3b5 100644 --- a/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs +++ b/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs @@ -414,6 +414,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain private void LoadPlugins() { m_plugineffects = new Dictionary(); + LoadPlugins(Assembly.GetCallingAssembly()); string plugineffectsPath = "Terrain"; // Load the files in the Terrain/ dir @@ -427,6 +428,16 @@ namespace OpenSim.Region.CoreModules.World.Terrain try { Assembly library = Assembly.LoadFrom(file); + LoadPlugins(library); + } + catch (BadImageFormatException) + { + } + } + } + + private void LoadPlugins(Assembly library) + { foreach (Type pluginType in library.GetTypes()) { try @@ -453,11 +464,6 @@ namespace OpenSim.Region.CoreModules.World.Terrain { } } - } - catch (BadImageFormatException) - { - } - } } public void InstallPlugin(string pluginName, ITerrainEffect effect) -- cgit v1.1 From e916b1399f08e726302f576d1653dc7edc445217 Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Mon, 27 Aug 2012 01:50:53 +0100 Subject: formatting --- .../CoreModules/World/Terrain/TerrainModule.cs | 44 +++++++++++----------- 1 file changed, 22 insertions(+), 22 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs b/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs index 620d3b5..4694b14 100644 --- a/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs +++ b/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs @@ -438,32 +438,32 @@ namespace OpenSim.Region.CoreModules.World.Terrain private void LoadPlugins(Assembly library) { - foreach (Type pluginType in library.GetTypes()) - { - try - { - if (pluginType.IsAbstract || pluginType.IsNotPublic) - continue; + foreach (Type pluginType in library.GetTypes()) + { + try + { + if (pluginType.IsAbstract || pluginType.IsNotPublic) + continue; - string typeName = pluginType.Name; + string typeName = pluginType.Name; - if (pluginType.GetInterface("ITerrainEffect", false) != null) - { - ITerrainEffect terEffect = (ITerrainEffect) Activator.CreateInstance(library.GetType(pluginType.ToString())); + if (pluginType.GetInterface("ITerrainEffect", false) != null) + { + ITerrainEffect terEffect = (ITerrainEffect)Activator.CreateInstance(library.GetType(pluginType.ToString())); - InstallPlugin(typeName, terEffect); - } - else if (pluginType.GetInterface("ITerrainLoader", false) != null) - { - ITerrainLoader terLoader = (ITerrainLoader) Activator.CreateInstance(library.GetType(pluginType.ToString())); - m_loaders[terLoader.FileExtension] = terLoader; - m_log.Info("L ... " + typeName); - } - } - catch (AmbiguousMatchException) - { - } + InstallPlugin(typeName, terEffect); + } + else if (pluginType.GetInterface("ITerrainLoader", false) != null) + { + ITerrainLoader terLoader = (ITerrainLoader)Activator.CreateInstance(library.GetType(pluginType.ToString())); + m_loaders[terLoader.FileExtension] = terLoader; + m_log.Info("L ... " + typeName); } + } + catch (AmbiguousMatchException) + { + } + } } public void InstallPlugin(string pluginName, ITerrainEffect effect) -- cgit v1.1 From 1e18f0f26aeb45ff9d0097206fec3910fb2291c8 Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Thu, 23 Aug 2012 13:59:06 +0100 Subject: copying documentation from http://opensimulator.org/wiki/Threat_level --- .../ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs | 59 ++++++++++++++++++++++ 1 file changed, 59 insertions(+) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs index 9ad1c22..ce1845c 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs @@ -40,16 +40,75 @@ using LSL_Key = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString; namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces { + /// + /// To permit region owners to enable the extended scripting functionality + /// of OSSL, without allowing malicious scripts to access potentially + /// troublesome functions, each OSSL function is assigned a threat level, + /// and access to the functions is granted or denied based on a default + /// threshold set in OpenSim.ini (which can be overridden for individual + /// functions on a case-by-case basis) + /// public enum ThreatLevel { + // Not documented, presumably means permanently disabled ? NoAccess = -1, + + /// + /// Function is no threat at all. It doesn't constitute a threat to + /// either users or the system and has no known side effects. + /// None = 0, + + /// + /// Abuse of this command can cause a nuisance to the region operator, + /// such as log message spew. + /// Nuisance = 1, + + /// + /// Extreme levels of abuse of this function can cause impaired + /// functioning of the region, or very gullible users can be tricked + /// into experiencing harmless effects. + /// VeryLow = 2, + + /// + /// Intentional abuse can cause crashes or malfunction under certain + /// circumstances, which can be easily rectified; or certain users can + /// be tricked into certain situations in an avoidable manner. + /// Low = 3, + + /// + /// Intentional abuse can cause denial of service and crashes with + /// potential of data or state loss; or trusting users can be tricked + /// into embarrassing or uncomfortable situations. + /// Moderate = 4, + + /// + /// Casual abuse can cause impaired functionality or temporary denial + /// of service conditions. Intentional abuse can easily cause crashes + /// with potential data loss, or can be used to trick experienced and + /// cautious users into unwanted situations, or changes global data + /// permanently and without undo ability. + /// High = 5, + + /// + /// Even normal use may, depending on the number of instances, or + /// frequency of use, result in severe service impairment or crash + /// with loss of data, or can be used to cause unwanted or harmful + /// effects on users without giving the user a means to avoid it. + /// VeryHigh = 6, + + /// + /// Even casual use is a danger to region stability, or function allows + /// console or OS command execution, or function allows taking money + /// without consent, or allows deletion or modification of user data, + /// or allows the compromise of sensitive data by design. + /// Severe = 7 }; -- cgit v1.1 From aa44df9c04658cfa0af9a0f203faea5e493c6f25 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Tue, 28 Aug 2012 20:35:17 +0100 Subject: Add IDynamicTextureManager.ConvertData() to match AsyncConvertData(). Remove mismatching ConvertStream() where there is no AsyncConvertStream and neither IDynamicTextureManager implementer implements this method. --- .../CoreModules/Scripting/LoadImageURL/LoadImageURLModule.cs | 2 +- .../CoreModules/Scripting/VectorRender/VectorRenderModule.cs | 11 ++++++----- OpenSim/Region/Framework/Interfaces/IDynamicTextureManager.cs | 2 +- 3 files changed, 8 insertions(+), 7 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/Scripting/LoadImageURL/LoadImageURLModule.cs b/OpenSim/Region/CoreModules/Scripting/LoadImageURL/LoadImageURLModule.cs index 6f83948..6e38b3f 100644 --- a/OpenSim/Region/CoreModules/Scripting/LoadImageURL/LoadImageURLModule.cs +++ b/OpenSim/Region/CoreModules/Scripting/LoadImageURL/LoadImageURLModule.cs @@ -72,7 +72,7 @@ namespace OpenSim.Region.CoreModules.Scripting.LoadImageURL return null; } - public byte[] ConvertStream(Stream data, string extraParams) + public byte[] ConvertData(string bodyData, string extraParams) { return null; } diff --git a/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs b/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs index f988c0e..3a758c5 100644 --- a/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs +++ b/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs @@ -78,9 +78,9 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender return null; } - public byte[] ConvertStream(Stream data, string extraParams) + public byte[] ConvertData(string bodyData, string extraParams) { - return null; + return Draw(bodyData, extraParams); } public bool AsyncConvertUrl(UUID id, string url, string extraParams) @@ -90,7 +90,8 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender public bool AsyncConvertData(UUID id, string bodyData, string extraParams) { - Draw(bodyData, id, extraParams); + // XXX: This isn't actually being done asynchronously! + m_textureManager.ReturnData(id, ConvertData(bodyData, extraParams)); return true; } @@ -161,7 +162,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender #endregion - private void Draw(string data, UUID id, string extraParams) + private byte[] Draw(string data, string extraParams) { // We need to cater for old scripts that didnt use extraParams neatly, they use either an integer size which represents both width and height, or setalpha // we will now support multiple comma seperated params in the form width:256,height:512,alpha:255 @@ -358,7 +359,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender e.Message, e.StackTrace); } - m_textureManager.ReturnData(id, imageJ2000); + return imageJ2000; } finally { diff --git a/OpenSim/Region/Framework/Interfaces/IDynamicTextureManager.cs b/OpenSim/Region/Framework/Interfaces/IDynamicTextureManager.cs index 8954513..773ba73 100644 --- a/OpenSim/Region/Framework/Interfaces/IDynamicTextureManager.cs +++ b/OpenSim/Region/Framework/Interfaces/IDynamicTextureManager.cs @@ -114,7 +114,7 @@ namespace OpenSim.Region.Framework.Interfaces string GetContentType(); bool SupportsAsynchronous(); byte[] ConvertUrl(string url, string extraParams); - byte[] ConvertStream(Stream data, string extraParams); + byte[] ConvertData(string bodyData, string extraParams); bool AsyncConvertUrl(UUID id, string url, string extraParams); bool AsyncConvertData(UUID id, string bodyData, string extraParams); void GetDrawStringSize(string text, string fontName, int fontSize, -- cgit v1.1 From c1cece4b82d24a17a09b66c9ec3975190cc05d95 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Tue, 28 Aug 2012 23:06:53 +0100 Subject: Add experimental DynamicTextureModule.ReuseTextures flag, currently only configurable on compile. Disabled (status quo) by default. This flag makes the dynamic texture module reuse cache previously dynamically generated textures given the same input commands and extra params for 24 hours. This occurs as long as those commands would always generate the same texture (e.g. they do not contain commands to fetch data from the web). This makes texture changing faster as a viewer-cached texture uuid is sent and may reduce simulator load in regions with generation of lots of dynamic textures. A downside is that this stops expiry of old temporary dynamic textures from the cache, Another downside is that a jpeg2000 generation that partially failed is currently not regenerated until restart or after 24 hours. --- .../DynamicTexture/DynamicTextureModule.cs | 169 +++++++++++++++------ .../Scripting/LoadImageURL/LoadImageURLModule.cs | 10 +- .../VectorRender/Tests/VectorRenderModuleTests.cs | 125 ++++++++++++++- .../Scripting/VectorRender/VectorRenderModule.cs | 48 +++++- .../Framework/Interfaces/IDynamicTextureManager.cs | 14 +- 5 files changed, 310 insertions(+), 56 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs b/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs index 18bd018..13b7498 100644 --- a/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs +++ b/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs @@ -49,6 +49,11 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture public const int DISP_EXPIRE = 1; public const int DISP_TEMP = 2; + /// + /// If true then where possible dynamic textures are reused. + /// + public bool ReuseTextures { get; set; } + private Dictionary RegisteredScenes = new Dictionary(); private Dictionary RenderPlugins = @@ -56,6 +61,15 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture private Dictionary Updaters = new Dictionary(); + /// + /// Record dynamic textures that we can reuse for a given data and parameter combination rather than + /// regenerate. + /// + /// + /// Key is string.Format("{0}{1}", data + /// + private Cache m_reuseableDynamicTextures; + #region IDynamicTextureManager Members public void RegisterRender(string handleType, IDynamicTextureRender render) @@ -71,7 +85,8 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture /// /// /// - public void ReturnData(UUID id, byte[] data) + /// True if the data generated can be reused for subsequent identical requests + public void ReturnData(UUID id, byte[] data, bool isReuseable) { DynamicTextureUpdater updater = null; @@ -88,7 +103,11 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture if (RegisteredScenes.ContainsKey(updater.SimUUID)) { Scene scene = RegisteredScenes[updater.SimUUID]; - updater.DataReceived(data, scene); + UUID newTextureID = updater.DataReceived(data, scene); + + if (ReuseTextures && isReuseable && !updater.BlendWithOldTexture) + m_reuseableDynamicTextures.Store( + GenerateReusableTextureKey(updater.BodyData, updater.Params), newTextureID); } } @@ -169,6 +188,11 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture { if (RenderPlugins.ContainsKey(contentType)) { + // If we want to reuse dynamic textures then we have to ignore any request from the caller to expire + // them. + if (ReuseTextures) + disp = disp & ~DISP_EXPIRE; + DynamicTextureUpdater updater = new DynamicTextureUpdater(); updater.SimUUID = simID; updater.PrimID = primID; @@ -183,21 +207,49 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture updater.Url = "Local image"; updater.Disp = disp; - lock (Updaters) + object reusableTextureUUID = null; + + if (ReuseTextures) + reusableTextureUUID + = m_reuseableDynamicTextures.Get(GenerateReusableTextureKey(data, extraParams)); + + // We cannot reuse a dynamic texture if the data is going to be blended with something already there. + if (reusableTextureUUID == null || updater.BlendWithOldTexture) { - if (!Updaters.ContainsKey(updater.UpdaterID)) + lock (Updaters) { - Updaters.Add(updater.UpdaterID, updater); + if (!Updaters.ContainsKey(updater.UpdaterID)) + { + Updaters.Add(updater.UpdaterID, updater); + } + } + + RenderPlugins[contentType].AsyncConvertData(updater.UpdaterID, data, extraParams); + } + else + { + // No need to add to updaters as the texture is always the same. Not that this functionality + // apppears to be implemented anyway. + if (RegisteredScenes.ContainsKey(updater.SimUUID)) + { + SceneObjectPart part = RegisteredScenes[updater.SimUUID].GetSceneObjectPart(updater.PrimID); + + if (part != null) + updater.UpdatePart(part, (UUID)reusableTextureUUID); } } - RenderPlugins[contentType].AsyncConvertData(updater.UpdaterID, data, extraParams); return updater.UpdaterID; } return UUID.Zero; } + private string GenerateReusableTextureKey(string data, string extraParams) + { + return string.Format("{0}{1}", data, extraParams); + } + public void GetDrawStringSize(string contentType, string text, string fontName, int fontSize, out double xSize, out double ySize) { @@ -224,6 +276,12 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture public void PostInitialise() { +// ReuseTextures = true; + if (ReuseTextures) + { + m_reuseableDynamicTextures = new Cache(CacheMedium.Memory, CacheStrategy.Conservative); + m_reuseableDynamicTextures.DefaultTTL = new TimeSpan(24, 0, 0); + } } public void Close() @@ -269,9 +327,60 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture } /// + /// Update the given part with the new texture. + /// + /// + /// The old texture UUID. + /// + public UUID UpdatePart(SceneObjectPart part, UUID textureID) + { + UUID oldID; + + lock (part) + { + // mostly keep the values from before + Primitive.TextureEntry tmptex = part.Shape.Textures; + + // FIXME: Need to return the appropriate ID if only a single face is replaced. + oldID = tmptex.DefaultTexture.TextureID; + + if (Face == ALL_SIDES) + { + oldID = tmptex.DefaultTexture.TextureID; + tmptex.DefaultTexture.TextureID = textureID; + } + else + { + try + { + Primitive.TextureEntryFace texface = tmptex.CreateFace((uint)Face); + texface.TextureID = textureID; + tmptex.FaceTextures[Face] = texface; + } + catch (Exception) + { + tmptex.DefaultTexture.TextureID = textureID; + } + } + + // I'm pretty sure we always want to force this to true + // I'm pretty sure noone whats to set fullbright true if it wasn't true before. + // tmptex.DefaultTexture.Fullbright = true; + + part.UpdateTextureEntry(tmptex.GetBytes()); + } + + return oldID; + } + + /// /// Called once new texture data has been received for this updater. /// - public void DataReceived(byte[] data, Scene scene) + /// + /// + /// True if the data given is reuseable. + /// The asset UUID given to the incoming data. + public UUID DataReceived(byte[] data, Scene scene) { SceneObjectPart part = scene.GetSceneObjectPart(PrimID); @@ -281,7 +390,8 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture String.Format("DynamicTextureModule: Error preparing image using URL {0}", Url); scene.SimChat(Utils.StringToBytes(msg), ChatTypeEnum.Say, 0, part.ParentGroup.RootPart.AbsolutePosition, part.Name, part.UUID, false); - return; + + return UUID.Zero; } byte[] assetData = null; @@ -323,52 +433,23 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture cacheLayerDecode = null; } - UUID oldID = UUID.Zero; - - lock (part) - { - // mostly keep the values from before - Primitive.TextureEntry tmptex = part.Shape.Textures; - - // remove the old asset from the cache - oldID = tmptex.DefaultTexture.TextureID; - - if (Face == ALL_SIDES) - { - tmptex.DefaultTexture.TextureID = asset.FullID; - } - else - { - try - { - Primitive.TextureEntryFace texface = tmptex.CreateFace((uint)Face); - texface.TextureID = asset.FullID; - tmptex.FaceTextures[Face] = texface; - } - catch (Exception) - { - tmptex.DefaultTexture.TextureID = asset.FullID; - } - } - - // I'm pretty sure we always want to force this to true - // I'm pretty sure noone whats to set fullbright true if it wasn't true before. - // tmptex.DefaultTexture.Fullbright = true; - - part.UpdateTextureEntry(tmptex.GetBytes()); - } + UUID oldID = UpdatePart(part, asset.FullID); if (oldID != UUID.Zero && ((Disp & DISP_EXPIRE) != 0)) { - if (oldAsset == null) oldAsset = scene.AssetService.Get(oldID.ToString()); + if (oldAsset == null) + oldAsset = scene.AssetService.Get(oldID.ToString()); + if (oldAsset != null) { - if (oldAsset.Temporary == true) + if (oldAsset.Temporary) { scene.AssetService.Delete(oldID.ToString()); } } } + + return asset.FullID; } private byte[] BlendTextures(byte[] frontImage, byte[] backImage, bool setNewAlpha, byte newAlpha) diff --git a/OpenSim/Region/CoreModules/Scripting/LoadImageURL/LoadImageURLModule.cs b/OpenSim/Region/CoreModules/Scripting/LoadImageURL/LoadImageURLModule.cs index 6e38b3f..2b3a0f2 100644 --- a/OpenSim/Region/CoreModules/Scripting/LoadImageURL/LoadImageURLModule.cs +++ b/OpenSim/Region/CoreModules/Scripting/LoadImageURL/LoadImageURLModule.cs @@ -67,6 +67,12 @@ namespace OpenSim.Region.CoreModules.Scripting.LoadImageURL return true; } +// public bool AlwaysIdenticalConversion(string bodyData, string extraParams) +// { +// // We don't support conversion of body data. +// return false; +// } + public byte[] ConvertUrl(string url, string extraParams) { return null; @@ -236,9 +242,11 @@ namespace OpenSim.Region.CoreModules.Scripting.LoadImageURL stream.Close(); } } + m_log.DebugFormat("[LOADIMAGEURLMODULE] Returning {0} bytes of image data for request {1}", imageJ2000.Length, state.RequestID); - m_textureManager.ReturnData(state.RequestID, imageJ2000); + + m_textureManager.ReturnData(state.RequestID, imageJ2000, false); } #region Nested type: RequestState diff --git a/OpenSim/Region/CoreModules/Scripting/VectorRender/Tests/VectorRenderModuleTests.cs b/OpenSim/Region/CoreModules/Scripting/VectorRender/Tests/VectorRenderModuleTests.cs index 180ea9f..b50c0bd 100644 --- a/OpenSim/Region/CoreModules/Scripting/VectorRender/Tests/VectorRenderModuleTests.cs +++ b/OpenSim/Region/CoreModules/Scripting/VectorRender/Tests/VectorRenderModuleTests.cs @@ -51,12 +51,15 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender.Tests DynamicTextureModule m_dtm; VectorRenderModule m_vrm; - [SetUp] - public void SetUp() + private void SetupScene(bool reuseTextures) { m_scene = new SceneHelpers().SetupScene(); + m_dtm = new DynamicTextureModule(); + m_dtm.ReuseTextures = reuseTextures; + m_vrm = new VectorRenderModule(); + SceneHelpers.SetupSceneModules(m_scene, m_dtm, m_vrm); } @@ -65,6 +68,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender.Tests { TestHelpers.InMethod(); + SetupScene(false); SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene); UUID originalTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID; @@ -86,6 +90,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender.Tests string dtText = "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;"; + SetupScene(false); SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene); m_dtm.AddDynamicTextureData( @@ -116,6 +121,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender.Tests string dtText = "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;"; + SetupScene(false); SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene); m_dtm.AddDynamicTextureData( @@ -147,6 +153,121 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender.Tests string dtText = "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World; Image http://localhost/shouldnotexist.png"; + SetupScene(false); + SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene); + + m_dtm.AddDynamicTextureData( + m_scene.RegionInfo.RegionID, + so.UUID, + m_vrm.GetContentType(), + dtText, + "", + 0); + + UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID; + + m_dtm.AddDynamicTextureData( + m_scene.RegionInfo.RegionID, + so.UUID, + m_vrm.GetContentType(), + dtText, + "", + 0); + + Assert.That(firstDynamicTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID)); + } + + [Test] + public void TestDrawReusingTexture() + { + TestHelpers.InMethod(); + + SetupScene(true); + SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene); + UUID originalTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID; + + m_dtm.AddDynamicTextureData( + m_scene.RegionInfo.RegionID, + so.UUID, + m_vrm.GetContentType(), + "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;", + "", + 0); + + Assert.That(originalTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID)); + } + + [Test] + public void TestRepeatSameDrawReusingTexture() + { + TestHelpers.InMethod(); + + string dtText = "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;"; + + SetupScene(true); + SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene); + + m_dtm.AddDynamicTextureData( + m_scene.RegionInfo.RegionID, + so.UUID, + m_vrm.GetContentType(), + dtText, + "", + 0); + + UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID; + + m_dtm.AddDynamicTextureData( + m_scene.RegionInfo.RegionID, + so.UUID, + m_vrm.GetContentType(), + dtText, + "", + 0); + + Assert.That(firstDynamicTextureID, Is.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID)); + } + + [Test] + public void TestRepeatSameDrawDifferentExtraParamsReusingTexture() + { + TestHelpers.InMethod(); + + string dtText = "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;"; + + SetupScene(true); + SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene); + + m_dtm.AddDynamicTextureData( + m_scene.RegionInfo.RegionID, + so.UUID, + m_vrm.GetContentType(), + dtText, + "", + 0); + + UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID; + + m_dtm.AddDynamicTextureData( + m_scene.RegionInfo.RegionID, + so.UUID, + m_vrm.GetContentType(), + dtText, + "alpha:250", + 0); + + Assert.That(firstDynamicTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID)); + } + + [Test] + public void TestRepeatSameDrawContainingImageReusingTexture() + { + TestHelpers.InMethod(); + + string dtText + = "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World; Image http://localhost/shouldnotexist.png"; + + SetupScene(true); SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene); m_dtm.AddDynamicTextureData( diff --git a/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs b/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs index 3a758c5..4268f2e 100644 --- a/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs +++ b/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs @@ -30,6 +30,7 @@ using System.Drawing; using System.Drawing.Imaging; using System.Globalization; using System.IO; +using System.Linq; using System.Net; using Nini.Config; using OpenMetaverse; @@ -73,6 +74,12 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender return true; } +// public bool AlwaysIdenticalConversion(string bodyData, string extraParams) +// { +// string[] lines = GetLines(bodyData); +// return lines.Any((str, r) => str.StartsWith("Image")); +// } + public byte[] ConvertUrl(string url, string extraParams) { return null; @@ -80,7 +87,13 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender public byte[] ConvertData(string bodyData, string extraParams) { - return Draw(bodyData, extraParams); + bool reuseable; + return Draw(bodyData, extraParams, out reuseable); + } + + private byte[] ConvertData(string bodyData, string extraParams, out bool reuseable) + { + return Draw(bodyData, extraParams, out reuseable); } public bool AsyncConvertUrl(UUID id, string url, string extraParams) @@ -91,7 +104,11 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender public bool AsyncConvertData(UUID id, string bodyData, string extraParams) { // XXX: This isn't actually being done asynchronously! - m_textureManager.ReturnData(id, ConvertData(bodyData, extraParams)); + bool reuseable; + byte[] data = ConvertData(bodyData, extraParams, out reuseable); + + m_textureManager.ReturnData(id, data, reuseable); + return true; } @@ -162,7 +179,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender #endregion - private byte[] Draw(string data, string extraParams) + private byte[] Draw(string data, string extraParams, out bool reuseable) { // We need to cater for old scripts that didnt use extraParams neatly, they use either an integer size which represents both width and height, or setalpha // we will now support multiple comma seperated params in the form width:256,height:512,alpha:255 @@ -343,7 +360,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender } } - GDIDraw(data, graph, altDataDelim); + GDIDraw(data, graph, altDataDelim, out reuseable); } byte[] imageJ2000 = new byte[0]; @@ -434,8 +451,21 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender } */ - private void GDIDraw(string data, Graphics graph, char dataDelim) + /// + /// Split input data into discrete command lines. + /// + /// + /// + /// + private string[] GetLines(string data, char dataDelim) { + char[] lineDelimiter = { dataDelim }; + return data.Split(lineDelimiter); + } + + private void GDIDraw(string data, Graphics graph, char dataDelim, out bool reuseable) + { + reuseable = true; Point startPoint = new Point(0, 0); Point endPoint = new Point(0, 0); Pen drawPen = null; @@ -450,11 +480,9 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender myFont = new Font(fontName, fontSize); myBrush = new SolidBrush(Color.Black); - char[] lineDelimiter = {dataDelim}; char[] partsDelimiter = {','}; - string[] lines = data.Split(lineDelimiter); - foreach (string line in lines) + foreach (string line in GetLines(data, dataDelim)) { string nextLine = line.Trim(); //replace with switch, or even better, do some proper parsing @@ -485,6 +513,10 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender } else if (nextLine.StartsWith("Image")) { + // We cannot reuse any generated texture involving fetching an image via HTTP since that image + // can change. + reuseable = false; + float x = 0; float y = 0; GetParams(partsDelimiter, ref nextLine, 5, ref x, ref y); diff --git a/OpenSim/Region/Framework/Interfaces/IDynamicTextureManager.cs b/OpenSim/Region/Framework/Interfaces/IDynamicTextureManager.cs index 773ba73..1a3bcbb 100644 --- a/OpenSim/Region/Framework/Interfaces/IDynamicTextureManager.cs +++ b/OpenSim/Region/Framework/Interfaces/IDynamicTextureManager.cs @@ -33,7 +33,7 @@ namespace OpenSim.Region.Framework.Interfaces public interface IDynamicTextureManager { void RegisterRender(string handleType, IDynamicTextureRender render); - void ReturnData(UUID id, byte[] data); + void ReturnData(UUID id, byte[] data, bool isReuseable); UUID AddDynamicTextureURL(UUID simID, UUID primID, string contentType, string url, string extraParams, int updateTimer); @@ -113,6 +113,18 @@ namespace OpenSim.Region.Framework.Interfaces string GetName(); string GetContentType(); bool SupportsAsynchronous(); + +// /// +// /// Return true if converting the input body and extra params data will always result in the same byte[] array +// /// +// /// +// /// This method allows the caller to use a previously generated asset if it has one. +// /// +// /// +// /// +// /// +// bool AlwaysIdenticalConversion(string bodyData, string extraParams); + byte[] ConvertUrl(string url, string extraParams); byte[] ConvertData(string bodyData, string extraParams); bool AsyncConvertUrl(UUID id, string url, string extraParams); -- cgit v1.1 From 7ea832d47c827ad9ef8eb0ce24702fbee585b1ee Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Wed, 29 Aug 2012 02:01:43 +0100 Subject: Fix regression introduced in a0d178b2 (Sat Aug 25 02:00:17 2012) where folders with asset type of 'Folder' and 'Unknown' were accidentally treated as system folders. This prevented more than one additional ordinary folder from being created in the base "My Inventory" user folder. Added regression test for this case. Switched tests to use XInventoryService with mostly implemented TestXInventoryDataPlugin rather than InventoryService Disabled TestLoadIarV0_1SameNameCreator() since this has not been working for a very long time (ever since XInventoryService) started being used since it doesnt' preserve creator data in the same way as InventoryService did and so effectively lost the OSPAs. However, nobody noticed/complained about this issue and OSPAs have been superseded by HG like creator information via the --home save oar/iar switch. --- .../Archiver/Tests/InventoryArchiverTests.cs | 64 +++++++++++----------- .../Framework/Scenes/Tests/UserInventoryTests.cs | 36 +++++++++++- 2 files changed, 66 insertions(+), 34 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs index b112b6d..12a05b3 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs @@ -350,38 +350,38 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests Assert.That(sog1.RootPart.CreatorID, Is.EqualTo(m_uaLL1.PrincipalID)); } - /// - /// Test loading a V0.1 OpenSim Inventory Archive (subject to change since there is no fixed format yet) where - /// an account exists with the same name as the creator, though not the same id. - /// - [Test] - public void TestLoadIarV0_1SameNameCreator() - { - TestHelpers.InMethod(); -// log4net.Config.XmlConfigurator.Configure(); - - UserAccountHelpers.CreateUserWithInventory(m_scene, m_uaMT, "meowfood"); - UserAccountHelpers.CreateUserWithInventory(m_scene, m_uaLL2, "hampshire"); - - m_archiverModule.DearchiveInventory(m_uaMT.FirstName, m_uaMT.LastName, "/", "meowfood", m_iarStream); - InventoryItemBase foundItem1 - = InventoryArchiveUtils.FindItemByPath(m_scene.InventoryService, m_uaMT.PrincipalID, m_item1Name); - - Assert.That( - foundItem1.CreatorId, Is.EqualTo(m_uaLL2.PrincipalID.ToString()), - "Loaded item non-uuid creator doesn't match original"); - Assert.That( - foundItem1.CreatorIdAsUuid, Is.EqualTo(m_uaLL2.PrincipalID), - "Loaded item uuid creator doesn't match original"); - Assert.That(foundItem1.Owner, Is.EqualTo(m_uaMT.PrincipalID), - "Loaded item owner doesn't match inventory reciever"); - - AssetBase asset1 = m_scene.AssetService.Get(foundItem1.AssetID.ToString()); - string xmlData = Utils.BytesToString(asset1.Data); - SceneObjectGroup sog1 = SceneObjectSerializer.FromOriginalXmlFormat(xmlData); - - Assert.That(sog1.RootPart.CreatorID, Is.EqualTo(m_uaLL2.PrincipalID)); - } +// /// +// /// Test loading a V0.1 OpenSim Inventory Archive (subject to change since there is no fixed format yet) where +// /// an account exists with the same name as the creator, though not the same id. +// /// +// [Test] +// public void TestLoadIarV0_1SameNameCreator() +// { +// TestHelpers.InMethod(); +// TestHelpers.EnableLogging(); +// +// UserAccountHelpers.CreateUserWithInventory(m_scene, m_uaMT, "meowfood"); +// UserAccountHelpers.CreateUserWithInventory(m_scene, m_uaLL2, "hampshire"); +// +// m_archiverModule.DearchiveInventory(m_uaMT.FirstName, m_uaMT.LastName, "/", "meowfood", m_iarStream); +// InventoryItemBase foundItem1 +// = InventoryArchiveUtils.FindItemByPath(m_scene.InventoryService, m_uaMT.PrincipalID, m_item1Name); +// +// Assert.That( +// foundItem1.CreatorId, Is.EqualTo(m_uaLL2.PrincipalID.ToString()), +// "Loaded item non-uuid creator doesn't match original"); +// Assert.That( +// foundItem1.CreatorIdAsUuid, Is.EqualTo(m_uaLL2.PrincipalID), +// "Loaded item uuid creator doesn't match original"); +// Assert.That(foundItem1.Owner, Is.EqualTo(m_uaMT.PrincipalID), +// "Loaded item owner doesn't match inventory reciever"); +// +// AssetBase asset1 = m_scene.AssetService.Get(foundItem1.AssetID.ToString()); +// string xmlData = Utils.BytesToString(asset1.Data); +// SceneObjectGroup sog1 = SceneObjectSerializer.FromOriginalXmlFormat(xmlData); +// +// Assert.That(sog1.RootPart.CreatorID, Is.EqualTo(m_uaLL2.PrincipalID)); +// } /// /// Test loading a V0.1 OpenSim Inventory Archive (subject to change since there is no fixed format yet) where diff --git a/OpenSim/Region/Framework/Scenes/Tests/UserInventoryTests.cs b/OpenSim/Region/Framework/Scenes/Tests/UserInventoryTests.cs index 44d2d45..9457ebb 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/UserInventoryTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/UserInventoryTests.cs @@ -50,9 +50,41 @@ using OpenSim.Tests.Common.Mock; namespace OpenSim.Region.Framework.Tests { [TestFixture] - public class UserInventoryTests + public class UserInventoryTests : OpenSimTestCase { [Test] + public void TestCreateInventoryFolders() + { + TestHelpers.InMethod(); +// TestHelpers.EnableLogging(); + + // For this test both folders will have the same name which is legal in SL user inventories. + string foldersName = "f1"; + + Scene scene = new SceneHelpers().SetupScene(); + UserAccount user1 = UserAccountHelpers.CreateUserWithInventory(scene, TestHelpers.ParseTail(1001)); + + UserInventoryHelpers.CreateInventoryFolder(scene.InventoryService, user1.PrincipalID, foldersName); + + List oneFolder + = UserInventoryHelpers.GetInventoryFolders(scene.InventoryService, user1.PrincipalID, foldersName); + + Assert.That(oneFolder.Count, Is.EqualTo(1)); + InventoryFolderBase firstRetrievedFolder = oneFolder[0]; + Assert.That(firstRetrievedFolder.Name, Is.EqualTo(foldersName)); + + UserInventoryHelpers.CreateInventoryFolder(scene.InventoryService, user1.PrincipalID, foldersName); + + List twoFolders + = UserInventoryHelpers.GetInventoryFolders(scene.InventoryService, user1.PrincipalID, foldersName); + + Assert.That(twoFolders.Count, Is.EqualTo(2)); + Assert.That(twoFolders[0].Name, Is.EqualTo(foldersName)); + Assert.That(twoFolders[1].Name, Is.EqualTo(foldersName)); + Assert.That(twoFolders[0].ID, Is.Not.EqualTo(twoFolders[1].ID)); + } + + [Test] public void TestGiveInventoryItem() { TestHelpers.InMethod(); @@ -83,7 +115,7 @@ namespace OpenSim.Region.Framework.Tests public void TestGiveInventoryFolder() { TestHelpers.InMethod(); -// log4net.Config.XmlConfigurator.Configure(); +// TestHelpers.EnableLogging(); Scene scene = new SceneHelpers().SetupScene(); UserAccount user1 = UserAccountHelpers.CreateUserWithInventory(scene, TestHelpers.ParseTail(1001)); -- cgit v1.1 From 3bf7bd6359ffbbc2a00b6870b72cc78287a70bc7 Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Tue, 28 Aug 2012 03:21:04 +0100 Subject: track originating IScriptApi method for SL-like error messages. Will add rule number tracking in next commit. --- .../Shared/Api/Implementation/LSL_Api.cs | 26 +++++++++++++--------- .../Shared/Api/Implementation/OSSL_Api.cs | 2 +- .../ScriptEngine/Shared/Api/Interface/ILSL_Api.cs | 2 +- 3 files changed, 17 insertions(+), 13 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 b001c51..709cac2 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -7208,7 +7208,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { m_host.AddScriptLPS(1); - setLinkPrimParams(ScriptBaseClass.LINK_THIS, rules); + setLinkPrimParams(ScriptBaseClass.LINK_THIS, rules, "llSetPrimitiveParams"); ScriptSleep(200); } @@ -7217,7 +7217,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { m_host.AddScriptLPS(1); - setLinkPrimParams(linknumber, rules); + setLinkPrimParams(linknumber, rules, "llSetLinkPrimitiveParams"); ScriptSleep(200); } @@ -7226,17 +7226,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { m_host.AddScriptLPS(1); - setLinkPrimParams(linknumber, rules); + setLinkPrimParams(linknumber, rules, "llSetLinkPrimitiveParamsFast"); } - protected void setLinkPrimParams(int linknumber, LSL_List rules) + protected void setLinkPrimParams(int linknumber, LSL_List rules, string originFunc) { List parts = GetLinkParts(linknumber); LSL_List remaining = null; foreach (SceneObjectPart part in parts) - remaining = SetPrimParams(part, rules); + remaining = SetPrimParams(part, rules, originFunc); while (remaining != null && remaining.Length > 2) { @@ -7245,13 +7245,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api parts = GetLinkParts(linknumber); foreach (SceneObjectPart part in parts) - remaining = SetPrimParams(part, rules); + remaining = SetPrimParams(part, rules, originFunc); } } - protected LSL_List SetPrimParams(SceneObjectPart part, LSL_List rules) + protected LSL_List SetPrimParams(SceneObjectPart part, LSL_List rules, string originFunc) { int idx = 0; + int idxStart = 0; bool positionChanged = false; LSL_Vector currentPosition = GetPartLocalPos(part); @@ -7263,6 +7264,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api int code = rules.GetLSLIntegerItem(idx++); int remain = rules.Length - idx; + idxStart = idx; int face; LSL_Vector v; @@ -7639,7 +7641,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } catch (InvalidCastException e) { - ShoutError(e.Message); + ShoutError(string.Format( + "{0} error running rule #{1}: arg #{2} ", + originFunc, "unknown", idx - idxStart) + e.Message); } finally { @@ -10761,7 +10765,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api return tid.ToString(); } - public void SetPrimitiveParamsEx(LSL_Key prim, LSL_List rules) + public void SetPrimitiveParamsEx(LSL_Key prim, LSL_List rules, string originFunc) { SceneObjectPart obj = World.GetSceneObjectPart(new UUID(prim)); if (obj == null) @@ -10770,14 +10774,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (obj.OwnerID != m_host.OwnerID) return; - LSL_List remaining = SetPrimParams(obj, rules); + LSL_List remaining = SetPrimParams(obj, rules, originFunc); while ((object)remaining != null && remaining.Length > 2) { LSL_Integer newLink = remaining.GetLSLIntegerItem(0); LSL_List newrules = remaining.GetSublist(1, -1); foreach(SceneObjectPart part in GetLinkParts(obj, newLink)){ - remaining = SetPrimParams(part, newrules); + remaining = SetPrimParams(part, newrules, originFunc); } } } diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs index 1afa4fb..09fcf50 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs @@ -2988,7 +2988,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api m_host.AddScriptLPS(1); InitLSL(); - m_LSL_Api.SetPrimitiveParamsEx(prim, rules); + m_LSL_Api.SetPrimitiveParamsEx(prim, rules, "osSetPrimitiveParams"); } /// diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs index cd58614..e97ff9d 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs @@ -424,7 +424,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces LSL_String llXorBase64StringsCorrect(string str1, string str2); void print(string str); - void SetPrimitiveParamsEx(LSL_Key prim, LSL_List rules); + void SetPrimitiveParamsEx(LSL_Key prim, LSL_List rules, string originFunc); LSL_List GetPrimitiveParamsEx(LSL_Key prim, LSL_List rules); } } -- cgit v1.1 From 0c3061f973417ecce8f412c82139cfad82504921 Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Tue, 28 Aug 2012 03:40:27 +0100 Subject: implementing rule tracking --- .../ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 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 709cac2..ae92716 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -7234,9 +7234,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api List parts = GetLinkParts(linknumber); LSL_List remaining = null; + uint rulesParsed = 0; foreach (SceneObjectPart part in parts) - remaining = SetPrimParams(part, rules, originFunc); + remaining = SetPrimParams(part, rules, originFunc, ref rulesParsed); while (remaining != null && remaining.Length > 2) { @@ -7245,11 +7246,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api parts = GetLinkParts(linknumber); foreach (SceneObjectPart part in parts) - remaining = SetPrimParams(part, rules, originFunc); + remaining = SetPrimParams(part, rules, originFunc, ref rulesParsed); } } - protected LSL_List SetPrimParams(SceneObjectPart part, LSL_List rules, string originFunc) + protected LSL_List SetPrimParams(SceneObjectPart part, LSL_List rules, string originFunc, ref uint rulesParsed) { int idx = 0; int idxStart = 0; @@ -7261,6 +7262,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { while (idx < rules.Length) { + ++rulesParsed; int code = rules.GetLSLIntegerItem(idx++); int remain = rules.Length - idx; @@ -7643,7 +7645,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { ShoutError(string.Format( "{0} error running rule #{1}: arg #{2} ", - originFunc, "unknown", idx - idxStart) + e.Message); + originFunc, rulesParsed, idx - idxStart) + e.Message); } finally { @@ -10774,14 +10776,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (obj.OwnerID != m_host.OwnerID) return; - LSL_List remaining = SetPrimParams(obj, rules, originFunc); + uint rulesParsed = 0; + LSL_List remaining = SetPrimParams(obj, rules, originFunc, ref rulesParsed); while ((object)remaining != null && remaining.Length > 2) { LSL_Integer newLink = remaining.GetLSLIntegerItem(0); LSL_List newrules = remaining.GetSublist(1, -1); foreach(SceneObjectPart part in GetLinkParts(obj, newLink)){ - remaining = SetPrimParams(part, newrules, originFunc); + remaining = SetPrimParams(part, newrules, originFunc, ref rulesParsed); } } } -- cgit v1.1 From 3d736d575ff9670ac813f13eb1cff07dea10328b Mon Sep 17 00:00:00 2001 From: Mic Bowman Date: Wed, 29 Aug 2012 14:56:51 -0700 Subject: This partially implements the LSL function to set the response type for an HTTP request. Since the "official" LSL function limits the use of the response type, it is implemented as osSetContentType with a string for the content mime type and a threat level of high. With this function you should be able to implement rather functional media-on-a-prim application with much less difficulty. --- .../CoreModules/Scripting/LSLHttp/UrlModule.cs | 20 +++++++++++++++++++- OpenSim/Region/Framework/Interfaces/IUrlModule.cs | 2 ++ .../Shared/Api/Implementation/OSSL_Api.cs | 18 +++++++++++++++++- .../ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs | 6 ++++++ .../ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs | 5 +++++ 5 files changed, 49 insertions(+), 2 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs b/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs index 05d54f0..53a9679 100644 --- a/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs +++ b/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs @@ -84,6 +84,7 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp public string body; public int responseCode; public string responseBody; + public string responseType = "text/plain"; //public ManualResetEvent ev; public bool requestDone; public int startTime; @@ -302,6 +303,22 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp } } + public void HttpContentType(UUID request, string type) + { + lock (m_UrlMap) + { + if (m_RequestMap.ContainsKey(request)) + { + UrlData urlData = m_RequestMap[request]; + urlData.requests[request].responseType = type; + } + else + { + m_log.Info("[HttpRequestHandler] There is no http-in request with id " + request.ToString()); + } + } + } + public void HttpResponse(UUID request, int status, string body) { lock (m_UrlMap) @@ -504,7 +521,8 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp //put response response["int_response_code"] = requestData.responseCode; response["str_response_string"] = requestData.responseBody; - response["content_type"] = "text/plain"; + response["content_type"] = requestData.responseType; + // response["content_type"] = "text/plain"; response["keepalive"] = false; response["reusecontext"] = false; diff --git a/OpenSim/Region/Framework/Interfaces/IUrlModule.cs b/OpenSim/Region/Framework/Interfaces/IUrlModule.cs index 457444c..79e9f9d 100644 --- a/OpenSim/Region/Framework/Interfaces/IUrlModule.cs +++ b/OpenSim/Region/Framework/Interfaces/IUrlModule.cs @@ -39,6 +39,8 @@ namespace OpenSim.Region.Framework.Interfaces UUID RequestSecureURL(IScriptModule engine, SceneObjectPart host, UUID itemID); void ReleaseURL(string url); void HttpResponse(UUID request, int status, string body); + void HttpContentType(UUID request, string type); + string GetHttpHeader(UUID request, string header); int GetFreeUrls(); diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs index 09fcf50..e245684 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs @@ -140,12 +140,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api internal float m_ScriptDistanceFactor = 1.0f; internal Dictionary m_FunctionPerms = new Dictionary(); + protected IUrlModule m_UrlModule = null; + public void Initialize(IScriptEngine ScriptEngine, SceneObjectPart host, TaskInventoryItem item) { m_ScriptEngine = ScriptEngine; m_host = host; m_item = item; + m_UrlModule = m_ScriptEngine.World.RequestModuleInterface(); + if (m_ScriptEngine.Config.GetBoolean("AllowOSFunctions", false)) m_OSFunctionsEnabled = true; @@ -3358,5 +3362,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api return new LSL_Key(m_host.ParentGroup.FromPartID.ToString()); } - } + + /// + /// Sets the response type for an HTTP request/response + /// + /// + public void osSetContentType(LSL_Key id, string type) + { + CheckThreatLevel(ThreatLevel.High,"osSetResponseType"); + if (m_UrlModule != null) + m_UrlModule.HttpContentType(new UUID(id),type); + } + + } } \ No newline at end of file diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs index ce1845c..06729ab 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs @@ -365,5 +365,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces /// /// Rezzing object key or NULL_KEY if rezzed by agent or otherwise unknown. LSL_Key osGetRezzingObject(); + + /// + /// Sets the response type for an HTTP request/response + /// + /// + void osSetContentType(LSL_Key id, string type); } } diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs index e9131e4..ba1ade2 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs @@ -955,5 +955,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase { return m_OSSL_Functions.osGetRezzingObject(); } + + public void osSetContentType(LSL_Key id, string type) + { + m_OSSL_Functions.osSetContentType(id,type); + } } } -- cgit v1.1 From 6b277394c080f5ad50d07e94f3e21340da4913b3 Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Wed, 29 Aug 2012 17:21:01 +0100 Subject: refactoring as the list funcs either skip invalid values or recall ToDoubleList --- .../Shared/Api/Implementation/LSL_Api.cs | 23 +++++++++++----------- 1 file changed, 11 insertions(+), 12 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 ae92716..45286c0 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -10119,31 +10119,30 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public LSL_Float llListStatistics(int operation, LSL_List src) { m_host.AddScriptLPS(1); - LSL_List nums = LSL_List.ToDoubleList(src); switch (operation) { case ScriptBaseClass.LIST_STAT_RANGE: - return nums.Range(); + return src.Range(); case ScriptBaseClass.LIST_STAT_MIN: - return nums.Min(); + return src.Min(); case ScriptBaseClass.LIST_STAT_MAX: - return nums.Max(); + return src.Max(); case ScriptBaseClass.LIST_STAT_MEAN: - return nums.Mean(); + return src.Mean(); case ScriptBaseClass.LIST_STAT_MEDIAN: - return nums.Median(); + return LSL_List.ToDoubleList(src).Median(); case ScriptBaseClass.LIST_STAT_NUM_COUNT: - return nums.NumericLength(); + return src.NumericLength(); case ScriptBaseClass.LIST_STAT_STD_DEV: - return nums.StdDev(); + return src.StdDev(); case ScriptBaseClass.LIST_STAT_SUM: - return nums.Sum(); + return src.Sum(); case ScriptBaseClass.LIST_STAT_SUM_SQUARES: - return nums.SumSqrs(); + return src.SumSqrs(); case ScriptBaseClass.LIST_STAT_GEOMETRIC_MEAN: - return nums.GeometricMean(); + return src.GeometricMean(); case ScriptBaseClass.LIST_STAT_HARMONIC_MEAN: - return nums.HarmonicMean(); + return src.HarmonicMean(); default: return 0.0; } -- cgit v1.1 From c76c63725bedb1f7e22dba23d3a8034885ff60e5 Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Wed, 29 Aug 2012 17:21:16 +0100 Subject: fixing bug where last element in list is ignored --- OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs b/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs index 9d9df9c..fcb98a5 100644 --- a/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs +++ b/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs @@ -1137,7 +1137,7 @@ namespace OpenSim.Region.ScriptEngine.Shared { list ret = new list(); double entry; - for (int i = 0; i < src.Data.Length - 1; i++) + for (int i = 0; i < src.Data.Length; i++) { if (double.TryParse(src.Data[i].ToString(), NumberStyles.Float, Culture.NumberFormatInfo, out entry)) { -- cgit v1.1 From d89b974680af52a2d950237962240dde82ff4a85 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Thu, 30 Aug 2012 22:28:45 +0100 Subject: If the compile-time DynamicTextureModule.ReuseTextures flag is set, check metadata still exists for any reused asset in case some other process has removed it from the cache. --- .../DynamicTexture/DynamicTextureModule.cs | 102 ++++++++++++--------- 1 file changed, 59 insertions(+), 43 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs b/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs index 13b7498..f169117 100644 --- a/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs +++ b/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs @@ -186,63 +186,79 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture public UUID AddDynamicTextureData(UUID simID, UUID primID, string contentType, string data, string extraParams, int updateTimer, bool SetBlending, int disp, byte AlphaValue, int face) { - if (RenderPlugins.ContainsKey(contentType)) - { - // If we want to reuse dynamic textures then we have to ignore any request from the caller to expire - // them. - if (ReuseTextures) - disp = disp & ~DISP_EXPIRE; + if (!RenderPlugins.ContainsKey(contentType)) + return UUID.Zero; - DynamicTextureUpdater updater = new DynamicTextureUpdater(); - updater.SimUUID = simID; - updater.PrimID = primID; - updater.ContentType = contentType; - updater.BodyData = data; - updater.UpdateTimer = updateTimer; - updater.UpdaterID = UUID.Random(); - updater.Params = extraParams; - updater.BlendWithOldTexture = SetBlending; - updater.FrontAlpha = AlphaValue; - updater.Face = face; - updater.Url = "Local image"; - updater.Disp = disp; + Scene scene; + RegisteredScenes.TryGetValue(simID, out scene); + + if (scene == null) + return UUID.Zero; - object reusableTextureUUID = null; + SceneObjectPart part = scene.GetSceneObjectPart(primID); - if (ReuseTextures) - reusableTextureUUID - = m_reuseableDynamicTextures.Get(GenerateReusableTextureKey(data, extraParams)); + if (part == null) + return UUID.Zero; + + // If we want to reuse dynamic textures then we have to ignore any request from the caller to expire + // them. + if (ReuseTextures) + disp = disp & ~DISP_EXPIRE; + + DynamicTextureUpdater updater = new DynamicTextureUpdater(); + updater.SimUUID = simID; + updater.PrimID = primID; + updater.ContentType = contentType; + updater.BodyData = data; + updater.UpdateTimer = updateTimer; + updater.UpdaterID = UUID.Random(); + updater.Params = extraParams; + updater.BlendWithOldTexture = SetBlending; + updater.FrontAlpha = AlphaValue; + updater.Face = face; + updater.Url = "Local image"; + updater.Disp = disp; + + object objReusableTextureUUID = null; + + if (ReuseTextures && !updater.BlendWithOldTexture) + { + string reuseableTextureKey = GenerateReusableTextureKey(data, extraParams); + objReusableTextureUUID = m_reuseableDynamicTextures.Get(reuseableTextureKey); - // We cannot reuse a dynamic texture if the data is going to be blended with something already there. - if (reusableTextureUUID == null || updater.BlendWithOldTexture) + if (objReusableTextureUUID != null) { - lock (Updaters) + // If something else has removed this temporary asset from the cache, detect and invalidate + // our cached uuid. + if (scene.AssetService.GetMetadata(objReusableTextureUUID.ToString()) == null) { - if (!Updaters.ContainsKey(updater.UpdaterID)) - { - Updaters.Add(updater.UpdaterID, updater); - } + m_reuseableDynamicTextures.Invalidate(reuseableTextureKey); + objReusableTextureUUID = null; } - - RenderPlugins[contentType].AsyncConvertData(updater.UpdaterID, data, extraParams); } - else + } + + // We cannot reuse a dynamic texture if the data is going to be blended with something already there. + if (objReusableTextureUUID == null) + { + lock (Updaters) { - // No need to add to updaters as the texture is always the same. Not that this functionality - // apppears to be implemented anyway. - if (RegisteredScenes.ContainsKey(updater.SimUUID)) + if (!Updaters.ContainsKey(updater.UpdaterID)) { - SceneObjectPart part = RegisteredScenes[updater.SimUUID].GetSceneObjectPart(updater.PrimID); - - if (part != null) - updater.UpdatePart(part, (UUID)reusableTextureUUID); + Updaters.Add(updater.UpdaterID, updater); } } - return updater.UpdaterID; + RenderPlugins[contentType].AsyncConvertData(updater.UpdaterID, data, extraParams); } - - return UUID.Zero; + else + { + // No need to add to updaters as the texture is always the same. Not that this functionality + // apppears to be implemented anyway. + updater.UpdatePart(part, (UUID)objReusableTextureUUID); + } + + return updater.UpdaterID; } private string GenerateReusableTextureKey(string data, string extraParams) -- cgit v1.1 From 3ed0d79b00c313eacb2a7df7d5519e840d2fc5c4 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Thu, 30 Aug 2012 22:57:40 +0100 Subject: Make ReuseDynamicTextures an experimental config setting in [Textures]. Default is false, as before. If true, this setting reuses dynamically generated textures (i.e. created through osSetDynamicTextureData() and similar OSSL functions) where possible rather than always regenerating them. This results in much quicker updates viewer-side but may bloat the asset cache (though this is fixable). Also, sometimes issue have been seen where dynamic textures do not transfer to the viewer properly (permanently blurry). If this happens and that flag is set then they are not regenerated, the viewer has to clear cache or wait for 24 hours before all cached uuids are invalidated. CUrrently experimental. Default is false, as before. --- .../CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs b/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs index f169117..3eedf49 100644 --- a/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs +++ b/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs @@ -283,6 +283,10 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture public void Initialise(Scene scene, IConfigSource config) { + IConfig texturesConfig = config.Configs["Textures"]; + if (texturesConfig != null) + ReuseTextures = texturesConfig.GetBoolean("ReuseDynamicTextures", false); + if (!RegisteredScenes.ContainsKey(scene.RegionInfo.RegionID)) { RegisteredScenes.Add(scene.RegionInfo.RegionID, scene); @@ -292,7 +296,6 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture public void PostInitialise() { -// ReuseTextures = true; if (ReuseTextures) { m_reuseableDynamicTextures = new Cache(CacheMedium.Memory, CacheStrategy.Conservative); -- cgit v1.1 From 68814f904e1f0c5be961791f3f475dcda4a88248 Mon Sep 17 00:00:00 2001 From: Melanie Date: Fri, 31 Aug 2012 00:37:27 +0100 Subject: Replace SendBannedUserList with Avination's version. Untested in core. Not even test compiled. --- .../Region/ClientStack/Linden/UDP/LLClientView.cs | 57 ++++++++++++---------- 1 file changed, 32 insertions(+), 25 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 148d0e0..d05ffea 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -4451,37 +4451,44 @@ namespace OpenSim.Region.ClientStack.LindenUDP if (bl[i].BannedUserID == UUID.Zero) continue; BannedUsers.Add(bl[i].BannedUserID); - } - EstateOwnerMessagePacket packet = new EstateOwnerMessagePacket(); - packet.AgentData.TransactionID = UUID.Random(); - packet.AgentData.AgentID = AgentId; - packet.AgentData.SessionID = SessionId; - packet.MethodData.Invoice = invoice; - packet.MethodData.Method = Utils.StringToBytes("setaccess"); + if (BannedUsers.Count >= 50 || (i == (bl.Length - 1) && BannedUsers.Count > 0)) + { + EstateOwnerMessagePacket packet = new EstateOwnerMessagePacket(); + packet.AgentData.TransactionID = UUID.Random(); + packet.AgentData.AgentID = AgentId; + packet.AgentData.SessionID = SessionId; + packet.MethodData.Invoice = invoice; + packet.MethodData.Method = Utils.StringToBytes("setaccess"); - EstateOwnerMessagePacket.ParamListBlock[] returnblock = new EstateOwnerMessagePacket.ParamListBlock[6 + BannedUsers.Count]; + EstateOwnerMessagePacket.ParamListBlock[] returnblock = new EstateOwnerMessagePacket.ParamListBlock[6 + BannedUsers.Count]; - for (int i = 0; i < (6 + BannedUsers.Count); i++) - { - returnblock[i] = new EstateOwnerMessagePacket.ParamListBlock(); - } - int j = 0; + int j; + for (j = 0; j < (6 + BannedUsers.Count); j++) + { + returnblock[j] = new EstateOwnerMessagePacket.ParamListBlock(); + } + j = 0; - returnblock[j].Parameter = Utils.StringToBytes(estateID.ToString()); j++; - returnblock[j].Parameter = Utils.StringToBytes(((int)Constants.EstateAccessCodex.EstateBans).ToString()); j++; - returnblock[j].Parameter = Utils.StringToBytes("0"); j++; - returnblock[j].Parameter = Utils.StringToBytes("0"); j++; - returnblock[j].Parameter = Utils.StringToBytes(BannedUsers.Count.ToString()); j++; - returnblock[j].Parameter = Utils.StringToBytes("0"); j++; + returnblock[j].Parameter = Utils.StringToBytes(estateID.ToString()); j++; + returnblock[j].Parameter = Utils.StringToBytes(((int)Constants.EstateAccessCodex.EstateBans).ToString()); j++; + returnblock[j].Parameter = Utils.StringToBytes("0"); j++; + returnblock[j].Parameter = Utils.StringToBytes("0"); j++; + returnblock[j].Parameter = Utils.StringToBytes(BannedUsers.Count.ToString()); j++; + returnblock[j].Parameter = Utils.StringToBytes("0"); j++; - foreach (UUID banned in BannedUsers) - { - returnblock[j].Parameter = banned.GetBytes(); j++; + foreach (UUID banned in BannedUsers) + { + returnblock[j].Parameter = banned.GetBytes(); j++; + } + packet.ParamList = returnblock; + packet.Header.Reliable = true; + OutPacket(packet, ThrottleOutPacketType.Task); + + BannedUsers.Clear(); + } } - packet.ParamList = returnblock; - packet.Header.Reliable = false; - OutPacket(packet, ThrottleOutPacketType.Task); + } public void SendRegionInfoToEstateMenu(RegionInfoForEstateMenuArgs args) -- cgit v1.1 From 3c019bea8c006c6d09e6fa5583f60e01a87b766b Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Thu, 30 Aug 2012 15:55:03 +0100 Subject: Implementing a vastly simpler means of allowing region modules to access GetLinkParts than mantis 6236 --- OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (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 45286c0..be22cb4 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -247,7 +247,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api return GetLinkParts(m_host, linkType); } - private List GetLinkParts(SceneObjectPart part, int linkType) + public static List GetLinkParts(SceneObjectPart part, int linkType) { List ret = new List(); ret.Add(part); -- cgit v1.1 From 973f2e8be540163e12dd8d85fffad3acd96fe212 Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Fri, 31 Aug 2012 12:50:32 +0100 Subject: adding documentation to script invokation methods --- .../Framework/Interfaces/IScriptModuleComms.cs | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Framework/Interfaces/IScriptModuleComms.cs b/OpenSim/Region/Framework/Interfaces/IScriptModuleComms.cs index ed71a95..ff8213c 100644 --- a/OpenSim/Region/Framework/Interfaces/IScriptModuleComms.cs +++ b/OpenSim/Region/Framework/Interfaces/IScriptModuleComms.cs @@ -46,9 +46,31 @@ namespace OpenSim.Region.Framework.Interfaces /// event ScriptCommand OnScriptCommand; + /// + /// Register an instance method as a script call by method name + /// + /// + /// void RegisterScriptInvocation(object target, string method); + + /// + /// Register an instance method as a script call by method info + /// + /// + /// void RegisterScriptInvocation(object target, MethodInfo method); + + /// + /// Register one or more instance methods as script calls by method name + /// + /// + /// void RegisterScriptInvocation(object target, string[] methods); + + /// + /// Returns an array of all registered script calls + /// + /// Delegate[] GetScriptInvocationList(); Delegate LookupScriptInvocation(string fname); -- cgit v1.1 From dff746df7be488d8ff35c91a974f406216222423 Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Fri, 31 Aug 2012 12:56:30 +0100 Subject: moving code that will be common into private static method --- .../Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/OptionalModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs b/OpenSim/Region/OptionalModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs index 705a847..de0e864 100644 --- a/OpenSim/Region/OptionalModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs +++ b/OpenSim/Region/OptionalModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs @@ -130,10 +130,17 @@ namespace OpenSim.Region.OptionalModules.Scripting.ScriptModuleComms m_scriptModule.PostScriptEvent(script, "link_message", args); } - public void RegisterScriptInvocation(object target, string meth) + private static MethodInfo GetMethodInfoFromType(object target, string meth) { MethodInfo mi = target.GetType().GetMethod(meth, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance); + + return mi; + } + + public void RegisterScriptInvocation(object target, string meth) + { + MethodInfo mi = GetMethodInfoFromType(target, meth); if (mi == null) { m_log.WarnFormat("[MODULE COMMANDS] Failed to register method {0}",meth); -- cgit v1.1 From 05648c2c4ad1283f5bd975c4a50ca5a949e67994 Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Fri, 31 Aug 2012 12:57:51 +0100 Subject: changing to use Type argument instead of object --- .../Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/OptionalModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs b/OpenSim/Region/OptionalModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs index de0e864..21aab84 100644 --- a/OpenSim/Region/OptionalModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs +++ b/OpenSim/Region/OptionalModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs @@ -130,9 +130,9 @@ namespace OpenSim.Region.OptionalModules.Scripting.ScriptModuleComms m_scriptModule.PostScriptEvent(script, "link_message", args); } - private static MethodInfo GetMethodInfoFromType(object target, string meth) + private static MethodInfo GetMethodInfoFromType(Type target, string meth) { - MethodInfo mi = target.GetType().GetMethod(meth, + MethodInfo mi = target.GetMethod(meth, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance); return mi; @@ -140,7 +140,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.ScriptModuleComms public void RegisterScriptInvocation(object target, string meth) { - MethodInfo mi = GetMethodInfoFromType(target, meth); + MethodInfo mi = GetMethodInfoFromType(target.GetType(), meth); if (mi == null) { m_log.WarnFormat("[MODULE COMMANDS] Failed to register method {0}",meth); -- cgit v1.1 From 7a9eee8538f474a617a379a66854fe5fa6cb68cd Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Fri, 31 Aug 2012 12:59:07 +0100 Subject: no need to assign result to GetMethodInfoFromType --- .../Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/OptionalModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs b/OpenSim/Region/OptionalModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs index 21aab84..bbf0dac 100644 --- a/OpenSim/Region/OptionalModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs +++ b/OpenSim/Region/OptionalModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs @@ -132,10 +132,8 @@ namespace OpenSim.Region.OptionalModules.Scripting.ScriptModuleComms private static MethodInfo GetMethodInfoFromType(Type target, string meth) { - MethodInfo mi = target.GetMethod(meth, + return target.GetMethod(meth, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance); - - return mi; } public void RegisterScriptInvocation(object target, string meth) -- cgit v1.1 From bcf944db4846b42a302e443050132aaea4b4d4d6 Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Fri, 31 Aug 2012 13:01:07 +0100 Subject: assign binding flags to variable --- .../Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/OptionalModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs b/OpenSim/Region/OptionalModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs index bbf0dac..50d04cd 100644 --- a/OpenSim/Region/OptionalModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs +++ b/OpenSim/Region/OptionalModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs @@ -132,8 +132,10 @@ namespace OpenSim.Region.OptionalModules.Scripting.ScriptModuleComms private static MethodInfo GetMethodInfoFromType(Type target, string meth) { + BindingFlags getMethodFlags = + BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance; return target.GetMethod(meth, - BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance); + getMethodFlags); } public void RegisterScriptInvocation(object target, string meth) -- cgit v1.1 From e6f43023b6fe682971b78175fbb694c18848eff0 Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Fri, 31 Aug 2012 13:09:15 +0100 Subject: adding support for finding static methods --- .../Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/OptionalModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs b/OpenSim/Region/OptionalModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs index 50d04cd..19130bd 100644 --- a/OpenSim/Region/OptionalModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs +++ b/OpenSim/Region/OptionalModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs @@ -130,17 +130,23 @@ namespace OpenSim.Region.OptionalModules.Scripting.ScriptModuleComms m_scriptModule.PostScriptEvent(script, "link_message", args); } - private static MethodInfo GetMethodInfoFromType(Type target, string meth) + private static MethodInfo GetMethodInfoFromType(Type target, string meth, bool searchInstanceMethods) { BindingFlags getMethodFlags = - BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance; + BindingFlags.NonPublic | BindingFlags.Public; + + if (searchInstanceMethods) + getMethodFlags |= BindingFlags.Instance; + else + getMethodFlags |= BindingFlags.Static; + return target.GetMethod(meth, getMethodFlags); } public void RegisterScriptInvocation(object target, string meth) { - MethodInfo mi = GetMethodInfoFromType(target.GetType(), meth); + MethodInfo mi = GetMethodInfoFromType(target.GetType(), meth, true); if (mi == null) { m_log.WarnFormat("[MODULE COMMANDS] Failed to register method {0}",meth); -- cgit v1.1 From 4c58c1b116d99b72d7c579f2bd2cc87d55b71451 Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Fri, 31 Aug 2012 13:10:17 +0100 Subject: formatting --- .../Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/OptionalModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs b/OpenSim/Region/OptionalModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs index 19130bd..d785a24 100644 --- a/OpenSim/Region/OptionalModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs +++ b/OpenSim/Region/OptionalModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs @@ -140,8 +140,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.ScriptModuleComms else getMethodFlags |= BindingFlags.Static; - return target.GetMethod(meth, - getMethodFlags); + return target.GetMethod(meth, getMethodFlags); } public void RegisterScriptInvocation(object target, string meth) -- cgit v1.1 From 8cd415c2b0e7bb7989c64ac17cfaa1b892128b87 Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Fri, 31 Aug 2012 13:10:23 +0100 Subject: formatting --- .../Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/OptionalModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs b/OpenSim/Region/OptionalModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs index d785a24..77d7e0a 100644 --- a/OpenSim/Region/OptionalModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs +++ b/OpenSim/Region/OptionalModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs @@ -148,7 +148,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.ScriptModuleComms MethodInfo mi = GetMethodInfoFromType(target.GetType(), meth, true); if (mi == null) { - m_log.WarnFormat("[MODULE COMMANDS] Failed to register method {0}",meth); + m_log.WarnFormat("[MODULE COMMANDS] Failed to register method {0}", meth); return; } -- cgit v1.1 From 7e41559917dbdd9ff1f70765a5a33e2e8f67e9a3 Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Fri, 31 Aug 2012 13:13:57 +0100 Subject: using specific type instead of var --- .../Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/OptionalModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs b/OpenSim/Region/OptionalModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs index 77d7e0a..6231624 100644 --- a/OpenSim/Region/OptionalModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs +++ b/OpenSim/Region/OptionalModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs @@ -166,7 +166,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.ScriptModuleComms m_log.DebugFormat("[MODULE COMMANDS] Register method {0} from type {1}", mi.Name, target.GetType().Name); Type delegateType; - var typeArgs = mi.GetParameters() + List typeArgs = mi.GetParameters() .Select(p => p.ParameterType) .ToList(); -- cgit v1.1 From b62557978058512ed5b9c3387a507b51365cb8c4 Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Fri, 31 Aug 2012 13:17:13 +0100 Subject: moving assignment to new line to make next commit easier to read in diffs --- .../Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/OptionalModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs b/OpenSim/Region/OptionalModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs index 6231624..bbaac3e 100644 --- a/OpenSim/Region/OptionalModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs +++ b/OpenSim/Region/OptionalModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs @@ -180,7 +180,8 @@ namespace OpenSim.Region.OptionalModules.Scripting.ScriptModuleComms delegateType = Expression.GetFuncType(typeArgs.ToArray()); } - Delegate fcall = Delegate.CreateDelegate(delegateType, target, mi); + Delegate fcall; + fcall = Delegate.CreateDelegate(delegateType, target, mi); lock (m_scriptInvocation) { -- cgit v1.1 From 794c5f5a6d464357101d3da649815251abdc9e10 Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Fri, 31 Aug 2012 13:50:46 +0100 Subject: adding support for static method script invocations --- OpenSim/Region/Framework/Interfaces/IScriptModuleComms.cs | 11 +++++++++-- .../ScriptModuleComms/ScriptModuleCommsModule.cs | 15 +++++++++++++++ 2 files changed, 24 insertions(+), 2 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Framework/Interfaces/IScriptModuleComms.cs b/OpenSim/Region/Framework/Interfaces/IScriptModuleComms.cs index ff8213c..dae7c00 100644 --- a/OpenSim/Region/Framework/Interfaces/IScriptModuleComms.cs +++ b/OpenSim/Region/Framework/Interfaces/IScriptModuleComms.cs @@ -54,9 +54,9 @@ namespace OpenSim.Region.Framework.Interfaces void RegisterScriptInvocation(object target, string method); /// - /// Register an instance method as a script call by method info + /// Register a static or instance method as a script call by method info /// - /// + /// If target is a Type object, will assume method is static. /// void RegisterScriptInvocation(object target, MethodInfo method); @@ -68,6 +68,13 @@ namespace OpenSim.Region.Framework.Interfaces void RegisterScriptInvocation(object target, string[] methods); /// + /// Register one or more static methods as script calls by method name + /// + /// + /// + void RegisterScriptInvocation(Type target, string[] methods); + + /// /// Returns an array of all registered script calls /// /// diff --git a/OpenSim/Region/OptionalModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs b/OpenSim/Region/OptionalModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs index bbaac3e..d6d96c9 100644 --- a/OpenSim/Region/OptionalModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs +++ b/OpenSim/Region/OptionalModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs @@ -181,7 +181,10 @@ namespace OpenSim.Region.OptionalModules.Scripting.ScriptModuleComms } Delegate fcall; + if (!(target is Type)) fcall = Delegate.CreateDelegate(delegateType, target, mi); + else + fcall = Delegate.CreateDelegate(delegateType, (Type)target, mi.Name); lock (m_scriptInvocation) { @@ -196,6 +199,18 @@ namespace OpenSim.Region.OptionalModules.Scripting.ScriptModuleComms m_scriptInvocation[fcall.Method.Name] = new ScriptInvocationData(fcall.Method.Name, fcall, parmTypes, fcall.Method.ReturnType); } } + + public void RegisterScriptInvocation(Type target, string[] methods) + { + foreach (string method in methods) + { + MethodInfo mi = GetMethodInfoFromType(target, method, false); + if (mi == null) + m_log.WarnFormat("[MODULE COMMANDS] Failed to register method {0}", method); + else + RegisterScriptInvocation(target, mi); + } + } public Delegate[] GetScriptInvocationList() { -- cgit v1.1 From 054db94d5d14fdd50cb2ca9a95a8d5cac2ab234a Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Fri, 31 Aug 2012 13:51:00 +0100 Subject: formatting --- .../Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/OptionalModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs b/OpenSim/Region/OptionalModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs index d6d96c9..8d100e8 100644 --- a/OpenSim/Region/OptionalModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs +++ b/OpenSim/Region/OptionalModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs @@ -172,12 +172,12 @@ namespace OpenSim.Region.OptionalModules.Scripting.ScriptModuleComms if (mi.ReturnType == typeof(void)) { - delegateType = Expression.GetActionType(typeArgs.ToArray()); + delegateType = Expression.GetActionType(typeArgs.ToArray()); } else { - typeArgs.Add(mi.ReturnType); - delegateType = Expression.GetFuncType(typeArgs.ToArray()); + typeArgs.Add(mi.ReturnType); + delegateType = Expression.GetFuncType(typeArgs.ToArray()); } Delegate fcall; @@ -188,13 +188,13 @@ namespace OpenSim.Region.OptionalModules.Scripting.ScriptModuleComms lock (m_scriptInvocation) { - ParameterInfo[] parameters = fcall.Method.GetParameters (); + ParameterInfo[] parameters = fcall.Method.GetParameters(); if (parameters.Length < 2) // Must have two UUID params return; // Hide the first two parameters Type[] parmTypes = new Type[parameters.Length - 2]; - for (int i = 2 ; i < parameters.Length ; i++) + for (int i = 2; i < parameters.Length; i++) parmTypes[i - 2] = parameters[i].ParameterType; m_scriptInvocation[fcall.Method.Name] = new ScriptInvocationData(fcall.Method.Name, fcall, parmTypes, fcall.Method.ReturnType); } -- cgit v1.1 From dac31303b720310598f51d5ff31355e08c7e4fac Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Fri, 31 Aug 2012 15:19:26 +0100 Subject: Type.Type is RuntimeType --- .../Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/OptionalModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs b/OpenSim/Region/OptionalModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs index 8d100e8..23cc633 100644 --- a/OpenSim/Region/OptionalModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs +++ b/OpenSim/Region/OptionalModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs @@ -163,7 +163,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.ScriptModuleComms public void RegisterScriptInvocation(object target, MethodInfo mi) { - m_log.DebugFormat("[MODULE COMMANDS] Register method {0} from type {1}", mi.Name, target.GetType().Name); + m_log.DebugFormat("[MODULE COMMANDS] Register method {0} from type {1}", mi.Name, (target is Type) ? ((Type)target).Name : target.GetType().Name); Type delegateType; List typeArgs = mi.GetParameters() -- cgit v1.1 From 0376b8ddbc4101627aa045a1deb18202fb51fffe Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Fri, 24 Aug 2012 10:10:55 -0700 Subject: BulletSim: add new interface for mesh, hull and terrain creation that will move nearly all of the logic into the C# code. --- .../Region/Physics/BulletSPlugin/BulletSimAPI.cs | 27 ++++++++++++++++------ 1 file changed, 20 insertions(+), 7 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs index 504bd3c..dab2420 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs @@ -392,23 +392,36 @@ public static extern int PhysicsStep2(IntPtr world, float timeStep, int maxSubSt [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern bool PushUpdate2(IntPtr obj); -/* +// ===================================================================================== +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern IntPtr CreateMeshShape2(IntPtr world, + int indicesCount, [MarshalAs(UnmanagedType.LPArray)] int[] indices, + int verticesCount, [MarshalAs(UnmanagedType.LPArray)] float[] vertices ); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern IntPtr CreateHullShape2(IntPtr world, + int hullCount, [MarshalAs(UnmanagedType.LPArray)] float[] hulls); + [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern IntPtr CreateMesh2(IntPtr world, int indicesCount, int* indices, int verticesCount, float* vertices ); +public static extern IntPtr BuildHullShape2(IntPtr world, IntPtr meshShape); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern bool BuildHull2(IntPtr world, IntPtr mesh); +public static extern IntPtr BuildNativeShape2(IntPtr world, + float shapeType, float collisionMargin, Vector3 scale); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern bool ReleaseHull2(IntPtr world, IntPtr mesh); +public static extern bool DeleteCollisionShape2(IntPtr world, IntPtr shape); +// ===================================================================================== [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern bool DestroyMesh2(IntPtr world, IntPtr mesh); +public static extern IntPtr CreateGroundPlaneBody2(uint id, Vector3 center, float collisionMargin); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern IntPtr CreateObject2(IntPtr world, ShapeData shapeData); -*/ +public static extern IntPtr CreateTerrainBody2(uint id, + Vector3 minCoords, Vector3 maxCoords, float collisionMargin, + [MarshalAs(UnmanagedType.LPArray)] float[] heightMap); +// ===================================================================================== [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern IntPtr Create6DofConstraint2(IntPtr world, IntPtr obj1, IntPtr obj2, Vector3 frame1loc, Quaternion frame1rot, -- cgit v1.1 From 7b6987ce83d16871f6070f3cc7d56280ad3d5dbe Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Fri, 24 Aug 2012 12:58:42 -0700 Subject: BulletSim: unify physical objects under BSPhysObjects. Now BSScene and BSLinkset only know of BSPhysObject's and there is only one list to search in BSScene. --- .../Region/Physics/BulletSPlugin/BSCharacter.cs | 31 +++-- OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs | 50 ++++---- .../Region/Physics/BulletSPlugin/BSPhysObject.cs | 58 +++++++++ OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | 84 ++++++------- OpenSim/Region/Physics/BulletSPlugin/BSScene.cs | 137 +++++++++------------ 5 files changed, 200 insertions(+), 160 deletions(-) create mode 100755 OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs index 1b23a36..784076d 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs @@ -34,7 +34,7 @@ using OpenSim.Region.Physics.Manager; namespace OpenSim.Region.Physics.BulletSPlugin { -public class BSCharacter : PhysicsActor +public class BSCharacter : BSPhysObject { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private static readonly string LogHeader = "[BULLETS CHAR]"; @@ -74,11 +74,8 @@ public class BSCharacter : PhysicsActor private bool _kinematic; private float _buoyancy; - private BulletBody m_body; - public BulletBody Body { - get { return m_body; } - set { m_body = value; } - } + public override BulletBody Body { get; set; } + public override BSLinkset Linkset { get; set; } private int _subscribedEventsMs = 0; private int _nextCollisionOkTime = 0; @@ -108,6 +105,8 @@ public class BSCharacter : PhysicsActor _density = _scene.Params.avatarDensity; ComputeAvatarVolumeAndMass(); // set _avatarVolume and _mass based on capsule size, _density and _scale + Linkset = new BSLinkset(_scene, this); + ShapeData shapeData = new ShapeData(); shapeData.ID = _localID; shapeData.Type = ShapeData.PhysicsShapeType.SHAPE_AVATAR; @@ -130,7 +129,7 @@ public class BSCharacter : PhysicsActor // Set the buoyancy for flying. This will be refactored when all the settings happen in C# BulletSimAPI.SetObjectBuoyancy(_scene.WorldID, LocalID, _buoyancy); - m_body = new BulletBody(LocalID, BulletSimAPI.GetBodyHandle2(_scene.World.Ptr, LocalID)); + Body = new BulletBody(LocalID, BulletSimAPI.GetBodyHandle2(_scene.World.Ptr, LocalID)); // avatars get all collisions no matter what (makes walking on ground and such work) BulletSimAPI.AddToCollisionFlags2(Body.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); }); @@ -139,7 +138,7 @@ public class BSCharacter : PhysicsActor } // called when this character is being destroyed and the resources should be released - public void Destroy() + public override void Destroy() { DetailLog("{0},BSCharacter.Destroy", LocalID); _scene.TaintedObject("BSCharacter.destroy", delegate() @@ -245,6 +244,10 @@ public class BSCharacter : PhysicsActor return _mass; } } + + // used when we only want this prim's mass and not the linkset thing + public override float MassRaw { get {return _mass; } } + public override Vector3 Force { get { return _force; } set { @@ -448,6 +451,12 @@ public class BSCharacter : PhysicsActor }); } } + + public override void ZeroMotion() + { + return; + } + // Stop collision events public override void UnSubscribeEvents() { _subscribedEventsMs = 0; @@ -481,7 +490,7 @@ public class BSCharacter : PhysicsActor // The physics engine says that properties have updated. Update same and inform // the world that things have changed. - public void UpdateProperties(EntityProperties entprop) + public override void UpdateProperties(EntityProperties entprop) { _position = entprop.Position; _orientation = entprop.Rotation; @@ -500,7 +509,7 @@ public class BSCharacter : PhysicsActor // The collision, if it should be reported to the character, is placed in a collection // that will later be sent to the simulator when SendCollisions() is called. CollisionEventUpdate collisionCollection = null; - public void Collide(uint collidingWith, ActorTypes type, Vector3 contactPoint, Vector3 contactNormal, float pentrationDepth) + public override void Collide(uint collidingWith, BSPhysObject collidee, ActorTypes type, Vector3 contactPoint, Vector3 contactNormal, float pentrationDepth) { // m_log.DebugFormat("{0}: Collide: ms={1}, id={2}, with={3}", LogHeader, _subscribedEventsMs, LocalID, collidingWith); @@ -525,7 +534,7 @@ public class BSCharacter : PhysicsActor } } - public void SendCollisions() + public override void SendCollisions() { /* if (collisionCollection != null && collisionCollection.Count > 0) diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs index 9e3f0db..b04e1b6 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs @@ -36,8 +36,8 @@ public class BSLinkset { private static string LogHeader = "[BULLETSIM LINKSET]"; - private BSPrim m_linksetRoot; - public BSPrim LinksetRoot { get { return m_linksetRoot; } } + private BSPhysObject m_linksetRoot; + public BSPhysObject LinksetRoot { get { return m_linksetRoot; } } private BSScene m_physicsScene; public BSScene PhysicsScene { get { return m_physicsScene; } } @@ -46,7 +46,7 @@ public class BSLinkset public int LinksetID { get; private set; } // The children under the root in this linkset - private List m_children; + private List m_children; // We lock the diddling of linkset classes to prevent any badness. // This locks the modification of the instances of this class. Changes @@ -74,7 +74,7 @@ public class BSLinkset get { return ComputeLinksetGeometricCenter(); } } - public BSLinkset(BSScene scene, BSPrim parent) + public BSLinkset(BSScene scene, BSPhysObject parent) { // A simple linkset of one (no children) LinksetID = m_nextLinksetID++; @@ -83,14 +83,14 @@ public class BSLinkset m_nextLinksetID = 1; m_physicsScene = scene; m_linksetRoot = parent; - m_children = new List(); + m_children = new List(); m_mass = parent.MassRaw; } // Link to a linkset where the child knows the parent. // Parent changing should not happen so do some sanity checking. // We return the parent's linkset so the child can track its membership. - public BSLinkset AddMeToLinkset(BSPrim child) + public BSLinkset AddMeToLinkset(BSPhysObject child) { lock (m_linksetActivityLock) { @@ -102,7 +102,7 @@ public class BSLinkset // Remove a child from a linkset. // Returns a new linkset for the child which is a linkset of one (just the // orphened child). - public BSLinkset RemoveMeFromLinkset(BSPrim child) + public BSLinkset RemoveMeFromLinkset(BSPhysObject child) { lock (m_linksetActivityLock) { @@ -129,7 +129,7 @@ public class BSLinkset } // Return 'true' if the passed object is the root object of this linkset - public bool IsRoot(BSPrim requestor) + public bool IsRoot(BSPhysObject requestor) { return (requestor.LocalID == m_linksetRoot.LocalID); } @@ -140,12 +140,12 @@ public class BSLinkset public bool HasAnyChildren { get { return (m_children.Count > 0); } } // Return 'true' if this child is in this linkset - public bool HasChild(BSPrim child) + public bool HasChild(BSPhysObject child) { bool ret = false; lock (m_linksetActivityLock) { - foreach (BSPrim bp in m_children) + foreach (BSPhysObject bp in m_children) { if (child.LocalID == bp.LocalID) { @@ -160,7 +160,7 @@ public class BSLinkset private float ComputeLinksetMass() { float mass = m_linksetRoot.MassRaw; - foreach (BSPrim bp in m_children) + foreach (BSPhysObject bp in m_children) { mass += bp.MassRaw; } @@ -174,7 +174,7 @@ public class BSLinkset lock (m_linksetActivityLock) { - foreach (BSPrim bp in m_children) + foreach (BSPhysObject bp in m_children) { com += bp.Position * bp.MassRaw; totalMass += bp.MassRaw; @@ -192,7 +192,7 @@ public class BSLinkset lock (m_linksetActivityLock) { - foreach (BSPrim bp in m_children) + foreach (BSPhysObject bp in m_children) { com += bp.Position * bp.MassRaw; } @@ -204,7 +204,7 @@ public class BSLinkset // When physical properties are changed the linkset needs to recalculate // its internal properties. - public void Refresh(BSPrim requestor) + public void Refresh(BSPhysObject requestor) { // If there are no children, there aren't any constraints to recompute if (!HasAnyChildren) @@ -230,7 +230,7 @@ public class BSLinkset float linksetMass = LinksetMass; lock (m_linksetActivityLock) { - foreach (BSPrim child in m_children) + foreach (BSPhysObject child in m_children) { BSConstraint constrain; if (m_physicsScene.Constraints.TryGetConstraint(LinksetRoot.Body, child.Body, out constrain)) @@ -255,14 +255,14 @@ public class BSLinkset // I am the root of a linkset and a new child is being added // Called while LinkActivity is locked. - private void AddChildToLinkset(BSPrim child) + private void AddChildToLinkset(BSPhysObject child) { if (!HasChild(child)) { m_children.Add(child); - BSPrim rootx = LinksetRoot; // capture the root as of now - BSPrim childx = child; + BSPhysObject rootx = LinksetRoot; // capture the root as of now + BSPhysObject childx = child; m_physicsScene.TaintedObject("AddChildToLinkset", delegate() { DetailLog("{0},AddChildToLinkset,taint,child={1}", m_linksetRoot.LocalID, child.LocalID); @@ -277,7 +277,7 @@ public class BSLinkset // it's still connected to the linkset. // Normal OpenSimulator operation will never do this because other SceneObjectPart information // has to be updated also (like pointer to prim's parent). - private void RemoveChildFromOtherLinkset(BSPrim pchild) + private void RemoveChildFromOtherLinkset(BSPhysObject pchild) { pchild.Linkset = new BSLinkset(m_physicsScene, pchild); RemoveChildFromLinkset(pchild); @@ -285,12 +285,12 @@ public class BSLinkset // I am the root of a linkset and one of my children is being removed. // Safe to call even if the child is not really in my linkset. - private void RemoveChildFromLinkset(BSPrim child) + private void RemoveChildFromLinkset(BSPhysObject child) { if (m_children.Remove(child)) { - BSPrim rootx = LinksetRoot; // capture the root as of now - BSPrim childx = child; + BSPhysObject rootx = LinksetRoot; // capture the root as of now + BSPhysObject childx = child; m_physicsScene.TaintedObject("RemoveChildFromLinkset", delegate() { DetailLog("{0},RemoveChildFromLinkset,taint,child={1}", m_linksetRoot.LocalID, child.LocalID); @@ -310,7 +310,7 @@ public class BSLinkset // Create a constraint between me (root of linkset) and the passed prim (the child). // Called at taint time! - private void PhysicallyLinkAChildToRoot(BSPrim rootPrim, BSPrim childPrim) + private void PhysicallyLinkAChildToRoot(BSPhysObject rootPrim, BSPhysObject childPrim) { // Zero motion for children so they don't interpolate childPrim.ZeroMotion(); @@ -383,7 +383,7 @@ public class BSLinkset // Remove linkage between myself and a particular child // Called at taint time! - private void PhysicallyUnlinkAChildFromRoot(BSPrim rootPrim, BSPrim childPrim) + private void PhysicallyUnlinkAChildFromRoot(BSPhysObject rootPrim, BSPhysObject childPrim) { DetailLog("{0},PhysicallyUnlinkAChildFromRoot,taint,root={1},child={2}", rootPrim.LocalID, rootPrim.LocalID, childPrim.LocalID); @@ -396,7 +396,7 @@ public class BSLinkset // Remove linkage between myself and any possible children I might have // Called at taint time! - private void PhysicallyUnlinkAllChildrenFromRoot(BSPrim rootPrim) + private void PhysicallyUnlinkAllChildrenFromRoot(BSPhysObject rootPrim) { DetailLog("{0},PhysicallyUnlinkAllChildren,taint", rootPrim.LocalID); diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs new file mode 100755 index 0000000..6e205a9 --- /dev/null +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs @@ -0,0 +1,58 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyrightD + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +using System; +using System.Collections.Generic; +using System.Text; + +using OMV = OpenMetaverse; +using OpenSim.Framework; +using OpenSim.Region.Physics.Manager; + +namespace OpenSim.Region.Physics.BulletSPlugin +{ +// Class to wrap all objects. +// The rest of BulletSim doesn't need to keep checking for avatars or prims +// unless the difference is significant. +public abstract class BSPhysObject : PhysicsActor +{ + public abstract BSLinkset Linkset { get; set; } + + public abstract void Collide(uint collidingWith, BSPhysObject collidee, ActorTypes type, + OMV.Vector3 contactPoint, OMV.Vector3 contactNormal, float pentrationDepth); + public abstract void SendCollisions(); + + // Return the object mass without calculating it or side effects + public abstract float MassRaw { get; } + + public abstract BulletBody Body { get; set; } + public abstract void ZeroMotion(); + + public abstract void UpdateProperties(EntityProperties entprop); + + public abstract void Destroy(); +} +} diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index d3f1e9c..036fd4f 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs @@ -37,7 +37,7 @@ using OpenSim.Region.Physics.ConvexDecompositionDotNet; namespace OpenSim.Region.Physics.BulletSPlugin { [Serializable] -public sealed class BSPrim : PhysicsActor +public sealed class BSPrim : BSPhysObject { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private static readonly string LogHeader = "[BULLETS PRIM]"; @@ -88,23 +88,14 @@ public sealed class BSPrim : PhysicsActor private float _buoyancy; // Membership in a linkset is controlled by this class. - private BSLinkset _linkset; - public BSLinkset Linkset - { - get { return _linkset; } - set { _linkset = value; } - } + public override BSLinkset Linkset { get; set; } private int _subscribedEventsMs = 0; private int _nextCollisionOkTime = 0; long _collidingStep; long _collidingGroundStep; - private BulletBody m_body; - public BulletBody Body { - get { return m_body; } - set { m_body = value; } - } + public override BulletBody Body { get; set; } private BSDynamics _vehicle; @@ -139,7 +130,7 @@ public sealed class BSPrim : PhysicsActor _friction = _scene.Params.defaultFriction; // TODO: compute based on object material _density = _scene.Params.defaultDensity; // TODO: compute based on object material _restitution = _scene.Params.defaultRestitution; - _linkset = new BSLinkset(Scene, this); // a linkset of one + Linkset = new BSLinkset(Scene, this); // a linkset of one _vehicle = new BSDynamics(Scene, this); // add vehicleness _mass = CalculateMass(); // do the actual object creation at taint time @@ -151,23 +142,23 @@ public sealed class BSPrim : PhysicsActor // Get the pointer to the physical body for this object. // At the moment, we're still letting BulletSim manage the creation and destruction // of the object. Someday we'll move that into the C# code. - m_body = new BulletBody(LocalID, BulletSimAPI.GetBodyHandle2(_scene.World.Ptr, LocalID)); + Body = new BulletBody(LocalID, BulletSimAPI.GetBodyHandle2(_scene.World.Ptr, LocalID)); }); } // called when this prim is being destroyed and we should free all the resources - public void Destroy() + public override void Destroy() { // m_log.DebugFormat("{0}: Destroy, id={1}", LogHeader, LocalID); // Undo any links between me and any other object - BSPrim parentBefore = _linkset.LinksetRoot; - int childrenBefore = _linkset.NumberOfChildren; + BSPhysObject parentBefore = Linkset.LinksetRoot; + int childrenBefore = Linkset.NumberOfChildren; - _linkset = _linkset.RemoveMeFromLinkset(this); + Linkset = Linkset.RemoveMeFromLinkset(this); DetailLog("{0},BSPrim.Destroy,call,parentBefore={1},childrenBefore={2},parentAfter={3},childrenAfter={4}", - LocalID, parentBefore.LocalID, childrenBefore, _linkset.LinksetRoot.LocalID, _linkset.NumberOfChildren); + LocalID, parentBefore.LocalID, childrenBefore, Linkset.LinksetRoot.LocalID, Linkset.NumberOfChildren); // Undo any vehicle properties this.VehicleType = (int)Vehicle.TYPE_NONE; @@ -230,13 +221,13 @@ public sealed class BSPrim : PhysicsActor BSPrim parent = obj as BSPrim; if (parent != null) { - BSPrim parentBefore = _linkset.LinksetRoot; - int childrenBefore = _linkset.NumberOfChildren; + BSPhysObject parentBefore = Linkset.LinksetRoot; + int childrenBefore = Linkset.NumberOfChildren; - _linkset = parent.Linkset.AddMeToLinkset(this); + Linkset = parent.Linkset.AddMeToLinkset(this); DetailLog("{0},BSPrim.link,call,parentBefore={1}, childrenBefore=={2}, parentAfter={3}, childrenAfter={4}", - LocalID, parentBefore.LocalID, childrenBefore, _linkset.LinksetRoot.LocalID, _linkset.NumberOfChildren); + LocalID, parentBefore.LocalID, childrenBefore, Linkset.LinksetRoot.LocalID, Linkset.NumberOfChildren); } return; } @@ -246,13 +237,13 @@ public sealed class BSPrim : PhysicsActor // TODO: decide if this parent checking needs to happen at taint time // Race condition here: if link() and delink() in same simulation tick, the delink will not happen - BSPrim parentBefore = _linkset.LinksetRoot; - int childrenBefore = _linkset.NumberOfChildren; + BSPhysObject parentBefore = Linkset.LinksetRoot; + int childrenBefore = Linkset.NumberOfChildren; - _linkset = _linkset.RemoveMeFromLinkset(this); + Linkset = Linkset.RemoveMeFromLinkset(this); DetailLog("{0},BSPrim.delink,parentBefore={1},childrenBefore={2},parentAfter={3},childrenAfter={4}, ", - LocalID, parentBefore.LocalID, childrenBefore, _linkset.LinksetRoot.LocalID, _linkset.NumberOfChildren); + LocalID, parentBefore.LocalID, childrenBefore, Linkset.LinksetRoot.LocalID, Linkset.NumberOfChildren); return; } @@ -260,7 +251,7 @@ public sealed class BSPrim : PhysicsActor // Do it to the properties so the values get set in the physics engine. // Push the setting of the values to the viewer. // Called at taint time! - public void ZeroMotion() + public override void ZeroMotion() { _velocity = OMV.Vector3.Zero; _acceleration = OMV.Vector3.Zero; @@ -281,7 +272,7 @@ public sealed class BSPrim : PhysicsActor public override OMV.Vector3 Position { get { - if (!_linkset.IsRoot(this)) + if (!Linkset.IsRoot(this)) // child prims move around based on their parent. Need to get the latest location _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID); @@ -306,23 +297,23 @@ public sealed class BSPrim : PhysicsActor { get { - return _linkset.LinksetMass; + return Linkset.LinksetMass; } } // used when we only want this prim's mass and not the linkset thing - public float MassRaw { get { return _mass; } } + public override float MassRaw { get { return _mass; } } // Is this used? public override OMV.Vector3 CenterOfMass { - get { return _linkset.CenterOfMass; } + get { return Linkset.CenterOfMass; } } // Is this used? public override OMV.Vector3 GeometricCenter { - get { return _linkset.GeometricCenter; } + get { return Linkset.GeometricCenter; } } public override OMV.Vector3 Force { @@ -431,7 +422,7 @@ public sealed class BSPrim : PhysicsActor } public override OMV.Quaternion Orientation { get { - if (!_linkset.IsRoot(this)) + if (!Linkset.IsRoot(this)) { // Children move around because tied to parent. Get a fresh value. _orientation = BulletSimAPI.GetObjectOrientation(_scene.WorldID, LocalID); @@ -490,7 +481,7 @@ public sealed class BSPrim : PhysicsActor BulletSimAPI.SetObjectProperties(_scene.WorldID, LocalID, IsStatic, IsSolid, SubscribedEvents(), mass); // recompute any linkset parameters - _linkset.Refresh(this); + Linkset.Refresh(this); CollisionFlags cf = BulletSimAPI.GetCollisionFlags2(Body.Ptr); DetailLog("{0},BSPrim.SetObjectDynamic,taint,static={1},solid={2},mass={3}, cf={4}", LocalID, IsStatic, IsSolid, mass, cf); @@ -1299,7 +1290,7 @@ public sealed class BSPrim : PhysicsActor const float ACCELERATION_TOLERANCE = 0.01f; const float ROTATIONAL_VELOCITY_TOLERANCE = 0.01f; - public void UpdateProperties(EntityProperties entprop) + public override void UpdateProperties(EntityProperties entprop) { /* UpdatedProperties changed = 0; @@ -1347,7 +1338,7 @@ public sealed class BSPrim : PhysicsActor // Don't check for damping here -- it's done in BulletSim and SceneObjectPart. // Updates only for individual prims and for the root object of a linkset. - if (_linkset.IsRoot(this)) + if (Linkset.IsRoot(this)) { // Assign to the local variables so the normal set action does not happen _position = entprop.Position; @@ -1375,7 +1366,7 @@ public sealed class BSPrim : PhysicsActor // I've collided with something // Called at taint time from within the Step() function CollisionEventUpdate collisionCollection; - public void Collide(uint collidingWith, ActorTypes type, OMV.Vector3 contactPoint, OMV.Vector3 contactNormal, float pentrationDepth) + public override void Collide(uint collidingWith, BSPhysObject collidee, ActorTypes type, OMV.Vector3 contactPoint, OMV.Vector3 contactNormal, float pentrationDepth) { // m_log.DebugFormat("{0}: Collide: ms={1}, id={2}, with={3}", LogHeader, _subscribedEventsMs, LocalID, collidingWith); @@ -1387,18 +1378,15 @@ public sealed class BSPrim : PhysicsActor } // DetailLog("{0},BSPrim.Collison,call,with={1}", LocalID, collidingWith); - BSPrim collidingWithPrim; - if (_scene.Prims.TryGetValue(collidingWith, out collidingWithPrim)) + + // prims in the same linkset cannot collide with each other + if (collidee != null && (this.Linkset.LinksetID == collidee.Linkset.LinksetID)) { - // prims in the same linkset cannot collide with each other - if (this.Linkset.LinksetID == collidingWithPrim.Linkset.LinksetID) - { - return; - } + return; } - // if someone is subscribed to collision events.... - if (_subscribedEventsMs != 0) { + // if someone has subscribed for collision events.... + if (SubscribedEvents()) { // throttle the collisions to the number of milliseconds specified in the subscription int nowTime = _scene.SimulationNowTime; if (nowTime >= _nextCollisionOkTime) { @@ -1412,7 +1400,7 @@ public sealed class BSPrim : PhysicsActor } // The scene is telling us it's time to pass our collected collisions into the simulator - public void SendCollisions() + public override void SendCollisions() { if (collisionCollection != null && collisionCollection.Count > 0) { diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs index 56924aa..ce64b9b 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs @@ -78,14 +78,12 @@ public class BSScene : PhysicsScene, IPhysicsParameters public string BulletSimVersion = "?"; - private Dictionary m_avatars = new Dictionary(); - public Dictionary Characters { get { return m_avatars; } } - - private Dictionary m_prims = new Dictionary(); - public Dictionary Prims { get { return m_prims; } } + public Dictionary PhysObjects = new Dictionary(); + private HashSet m_objectsWithCollisions = new HashSet(); + // Following is a kludge and can be removed when avatar animation updating is + // moved to a better place. private HashSet m_avatarsWithCollisions = new HashSet(); - private HashSet m_primsWithCollisions = new HashSet(); private List m_vehicles = new List(); @@ -235,7 +233,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters // BulletSimVersion = BulletSimAPI.GetVersion(); // m_log.WarnFormat("{0}: BulletSim.dll version='{1}'", LogHeader, BulletSimVersion); - // if Debug, enable logging from the unmanaged code + // If Debug logging level, enable logging from the unmanaged code if (m_log.IsDebugEnabled || PhysicsLogging.Enabled) { m_log.DebugFormat("{0}: Initialize: Setting debug callback for unmanaged code", LogHeader); @@ -243,13 +241,14 @@ public class BSScene : PhysicsScene, IPhysicsParameters m_DebugLogCallbackHandle = new BulletSimAPI.DebugLogCallback(BulletLoggerPhysLog); else m_DebugLogCallbackHandle = new BulletSimAPI.DebugLogCallback(BulletLogger); - // the handle is saved in a variable to make sure it doesn't get freed after this call + // The handle is saved in a variable to make sure it doesn't get freed after this call BulletSimAPI.SetDebugLogCallback(m_DebugLogCallbackHandle); } _taintedObjects = new List(); mesher = meshmerizer; + // The bounding box for the simulated world Vector3 worldExtent = new Vector3(Constants.RegionSize, Constants.RegionSize, 8192f); @@ -337,7 +336,11 @@ public class BSScene : PhysicsScene, IPhysicsParameters if (!m_initialized) return null; BSCharacter actor = new BSCharacter(localID, avName, this, position, size, isFlying); - lock (m_avatars) m_avatars.Add(localID, actor); + lock (PhysObjects) PhysObjects.Add(localID, actor); + + // Remove kludge someday + lock (m_avatarsWithCollisions) m_avatarsWithCollisions.Add(actor); + return actor; } @@ -352,7 +355,9 @@ public class BSScene : PhysicsScene, IPhysicsParameters { try { - lock (m_avatars) m_avatars.Remove(actor.LocalID); + lock (PhysObjects) PhysObjects.Remove(actor.LocalID); + // Remove kludge someday + lock (m_avatarsWithCollisions) m_avatarsWithCollisions.Remove(bsactor); } catch (Exception e) { @@ -374,7 +379,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters // m_log.DebugFormat("{0}: RemovePrim. id={1}/{2}", LogHeader, bsprim.Name, bsprim.LocalID); try { - lock (m_prims) m_prims.Remove(bsprim.LocalID); + lock (PhysObjects) PhysObjects.Remove(bsprim.LocalID); } catch (Exception e) { @@ -399,7 +404,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters DetailLog("{0},AddPrimShape,call", localID); BSPrim prim = new BSPrim(localID, primName, this, position, size, rotation, pbs, isPhysical); - lock (m_prims) m_prims.Add(localID, prim); + lock (PhysObjects) PhysObjects.Add(localID, prim); return prim; } @@ -470,19 +475,16 @@ public class BSScene : PhysicsScene, IPhysicsParameters // The above SendCollision's batch up the collisions on the objects. // Now push the collisions into the simulator. - foreach (BSPrim bsp in m_primsWithCollisions) + foreach (BSPhysObject bsp in m_objectsWithCollisions) bsp.SendCollisions(); - m_primsWithCollisions.Clear(); + m_objectsWithCollisions.Clear(); // This is a kludge to get avatar movement updated. - // Don't send collisions only if there were collisions -- send everytime. // ODE sends collisions even if there are none and this is used to update // avatar animations and stuff. - // foreach (BSCharacter bsc in m_avatarsWithCollisions) - // bsc.SendCollisions(); - foreach (KeyValuePair kvp in m_avatars) - kvp.Value.SendCollisions(); - m_avatarsWithCollisions.Clear(); + foreach (BSPhysObject bpo in m_avatarsWithCollisions) + bpo.SendCollisions(); + // m_avatarsWithCollisions.Clear(); // If any of the objects had updated properties, tell the object it has been changed by the physics engine if (updatedEntityCount > 0) @@ -490,16 +492,10 @@ public class BSScene : PhysicsScene, IPhysicsParameters for (int ii = 0; ii < updatedEntityCount; ii++) { EntityProperties entprop = m_updateArray[ii]; - BSPrim prim; - if (m_prims.TryGetValue(entprop.ID, out prim)) - { - prim.UpdateProperties(entprop); - continue; - } - BSCharacter actor; - if (m_avatars.TryGetValue(entprop.ID, out actor)) + BSPhysObject pobj; + if (PhysObjects.TryGetValue(entprop.ID, out pobj)) { - actor.UpdateProperties(entprop); + pobj.UpdateProperties(entprop); continue; } } @@ -529,33 +525,36 @@ public class BSScene : PhysicsScene, IPhysicsParameters } // Something has collided - private void SendCollision(uint localID, uint collidingWith, Vector3 collidePoint, Vector3 collideNormal, float penitration) + private void SendCollision(uint localID, uint collidingWith, Vector3 collidePoint, Vector3 collideNormal, float penetration) { if (localID == TERRAIN_ID || localID == GROUNDPLANE_ID) { return; // don't send collisions to the terrain } + BSPhysObject collider = PhysObjects[localID]; + // TODO: as of this code, terrain was not in the physical object list. + // When BSTerrain is created and it will be in the list, we can remove + // the possibility that it's not there and just fetch the collidee. + BSPhysObject collidee = null; + ActorTypes type = ActorTypes.Prim; if (collidingWith == TERRAIN_ID || collidingWith == GROUNDPLANE_ID) + { type = ActorTypes.Ground; - else if (m_avatars.ContainsKey(collidingWith)) - type = ActorTypes.Agent; + } + else + { + collidee = PhysObjects[collidingWith]; + if (collidee is BSCharacter) + type = ActorTypes.Agent; + } // DetailLog("{0},BSScene.SendCollision,collide,id={1},with={2}", DetailLogZero, localID, collidingWith); - BSPrim prim; - if (m_prims.TryGetValue(localID, out prim)) { - prim.Collide(collidingWith, type, collidePoint, collideNormal, penitration); - m_primsWithCollisions.Add(prim); - return; - } - BSCharacter actor; - if (m_avatars.TryGetValue(localID, out actor)) { - actor.Collide(collidingWith, type, collidePoint, collideNormal, penitration); - m_avatarsWithCollisions.Add(actor); - return; - } + collider.Collide(collidingWith, collidee, type, collidePoint, collideNormal, penetration); + m_objectsWithCollisions.Add(collider); + return; } @@ -605,17 +604,11 @@ public class BSScene : PhysicsScene, IPhysicsParameters // make sure no stepping happens while we're deleting stuff m_initialized = false; - foreach (KeyValuePair kvp in m_avatars) - { - kvp.Value.Destroy(); - } - m_avatars.Clear(); - - foreach (KeyValuePair kvp in m_prims) + foreach (KeyValuePair kvp in PhysObjects) { kvp.Value.Destroy(); } - m_prims.Clear(); + PhysObjects.Clear(); // Now that the prims are all cleaned up, there should be no constraints left if (m_constraintCollection != null) @@ -996,42 +989,42 @@ public class BSScene : PhysicsScene, IPhysicsParameters 0f, (s,cf,p,v) => { s.m_params[0].linearDamping = cf.GetFloat(p, v); }, (s) => { return s.m_params[0].linearDamping; }, - (s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].linearDamping, p, l, v); } ), + (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].linearDamping, p, l, v); } ), new ParameterDefn("AngularDamping", "Factor to damp angular movement per second (0.0 - 1.0)", 0f, (s,cf,p,v) => { s.m_params[0].angularDamping = cf.GetFloat(p, v); }, (s) => { return s.m_params[0].angularDamping; }, - (s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].angularDamping, p, l, v); } ), + (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].angularDamping, p, l, v); } ), new ParameterDefn("DeactivationTime", "Seconds before considering an object potentially static", 0.2f, (s,cf,p,v) => { s.m_params[0].deactivationTime = cf.GetFloat(p, v); }, (s) => { return s.m_params[0].deactivationTime; }, - (s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].deactivationTime, p, l, v); } ), + (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].deactivationTime, p, l, v); } ), new ParameterDefn("LinearSleepingThreshold", "Seconds to measure linear movement before considering static", 0.8f, (s,cf,p,v) => { s.m_params[0].linearSleepingThreshold = cf.GetFloat(p, v); }, (s) => { return s.m_params[0].linearSleepingThreshold; }, - (s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].linearSleepingThreshold, p, l, v); } ), + (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].linearSleepingThreshold, p, l, v); } ), new ParameterDefn("AngularSleepingThreshold", "Seconds to measure angular movement before considering static", 1.0f, (s,cf,p,v) => { s.m_params[0].angularSleepingThreshold = cf.GetFloat(p, v); }, (s) => { return s.m_params[0].angularSleepingThreshold; }, - (s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].angularSleepingThreshold, p, l, v); } ), + (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].angularSleepingThreshold, p, l, v); } ), new ParameterDefn("CcdMotionThreshold", "Continuious collision detection threshold (0 means no CCD)" , 0f, // set to zero to disable (s,cf,p,v) => { s.m_params[0].ccdMotionThreshold = cf.GetFloat(p, v); }, (s) => { return s.m_params[0].ccdMotionThreshold; }, - (s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].ccdMotionThreshold, p, l, v); } ), + (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].ccdMotionThreshold, p, l, v); } ), new ParameterDefn("CcdSweptSphereRadius", "Continuious collision detection test radius" , 0f, (s,cf,p,v) => { s.m_params[0].ccdSweptSphereRadius = cf.GetFloat(p, v); }, (s) => { return s.m_params[0].ccdSweptSphereRadius; }, - (s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].ccdSweptSphereRadius, p, l, v); } ), + (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].ccdSweptSphereRadius, p, l, v); } ), new ParameterDefn("ContactProcessingThreshold", "Distance between contacts before doing collision check" , 0.1f, (s,cf,p,v) => { s.m_params[0].contactProcessingThreshold = cf.GetFloat(p, v); }, (s) => { return s.m_params[0].contactProcessingThreshold; }, - (s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].contactProcessingThreshold, p, l, v); } ), + (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].contactProcessingThreshold, p, l, v); } ), new ParameterDefn("TerrainFriction", "Factor to reduce movement against terrain surface" , 0.5f, @@ -1052,32 +1045,32 @@ public class BSScene : PhysicsScene, IPhysicsParameters 0.5f, (s,cf,p,v) => { s.m_params[0].avatarFriction = cf.GetFloat(p, v); }, (s) => { return s.m_params[0].avatarFriction; }, - (s,p,l,v) => { s.UpdateParameterAvatars(ref s.m_params[0].avatarFriction, p, l, v); } ), + (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarFriction, p, l, v); } ), new ParameterDefn("AvatarDensity", "Density of an avatar. Changed on avatar recreation.", 60f, (s,cf,p,v) => { s.m_params[0].avatarDensity = cf.GetFloat(p, v); }, (s) => { return s.m_params[0].avatarDensity; }, - (s,p,l,v) => { s.UpdateParameterAvatars(ref s.m_params[0].avatarDensity, p, l, v); } ), + (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarDensity, p, l, v); } ), new ParameterDefn("AvatarRestitution", "Bouncyness. Changed on avatar recreation.", 0f, (s,cf,p,v) => { s.m_params[0].avatarRestitution = cf.GetFloat(p, v); }, (s) => { return s.m_params[0].avatarRestitution; }, - (s,p,l,v) => { s.UpdateParameterAvatars(ref s.m_params[0].avatarRestitution, p, l, v); } ), + (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarRestitution, p, l, v); } ), new ParameterDefn("AvatarCapsuleRadius", "Radius of space around an avatar", 0.37f, (s,cf,p,v) => { s.m_params[0].avatarCapsuleRadius = cf.GetFloat(p, v); }, (s) => { return s.m_params[0].avatarCapsuleRadius; }, - (s,p,l,v) => { s.UpdateParameterAvatars(ref s.m_params[0].avatarCapsuleRadius, p, l, v); } ), + (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarCapsuleRadius, p, l, v); } ), new ParameterDefn("AvatarCapsuleHeight", "Default height of space around avatar", 1.5f, (s,cf,p,v) => { s.m_params[0].avatarCapsuleHeight = cf.GetFloat(p, v); }, (s) => { return s.m_params[0].avatarCapsuleHeight; }, - (s,p,l,v) => { s.UpdateParameterAvatars(ref s.m_params[0].avatarCapsuleHeight, p, l, v); } ), + (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarCapsuleHeight, p, l, v); } ), new ParameterDefn("AvatarContactProcessingThreshold", "Distance from capsule to check for collisions", 0.1f, (s,cf,p,v) => { s.m_params[0].avatarContactProcessingThreshold = cf.GetFloat(p, v); }, (s) => { return s.m_params[0].avatarContactProcessingThreshold; }, - (s,p,l,v) => { s.UpdateParameterAvatars(ref s.m_params[0].avatarContactProcessingThreshold, p, l, v); } ), + (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarContactProcessingThreshold, p, l, v); } ), new ParameterDefn("MaxPersistantManifoldPoolSize", "Number of manifolds pooled (0 means default of 4096)", @@ -1264,18 +1257,10 @@ public class BSScene : PhysicsScene, IPhysicsParameters } // check to see if we are updating a parameter for a particular or all of the prims - protected void UpdateParameterPrims(ref float loc, string parm, uint localID, float val) - { - List operateOn; - lock (m_prims) operateOn = new List(m_prims.Keys); - UpdateParameterSet(operateOn, ref loc, parm, localID, val); - } - - // check to see if we are updating a parameter for a particular or all of the avatars - protected void UpdateParameterAvatars(ref float loc, string parm, uint localID, float val) + protected void UpdateParameterObject(ref float loc, string parm, uint localID, float val) { List operateOn; - lock (m_avatars) operateOn = new List(m_avatars.Keys); + lock (PhysObjects) operateOn = new List(PhysObjects.Keys); UpdateParameterSet(operateOn, ref loc, parm, localID, val); } -- cgit v1.1 From 7c140570db3b01eb83efc0d42a47715d3047e376 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Sat, 25 Aug 2012 23:18:46 -0700 Subject: BulletSim: Changes to terrain storage and management so mega-regions work. Moved all terrain code out of BSScene and into new BSTerrainManager. Added logic to manage multiple terrains for mega-regions. Added new functions to BulletSimAPI to match the library. Moved all of the terrain creation and setup logic from C++ code to C# code. The unused code has not yet been removed from either place. Soon. Moved checks for avatar above ground and in bounds into BSCharacter. --- .../Region/Physics/BulletSPlugin/BSCharacter.cs | 37 ++- .../Region/Physics/BulletSPlugin/BSConstraint.cs | 3 +- OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs | 9 +- .../Region/Physics/BulletSPlugin/BSPhysObject.cs | 118 ++++---- OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | 2 +- OpenSim/Region/Physics/BulletSPlugin/BSScene.cs | 245 ++++++++-------- .../Physics/BulletSPlugin/BSTerrainManager.cs | 307 +++++++++++++++++++++ .../Region/Physics/BulletSPlugin/BulletSimAPI.cs | 61 +++- 8 files changed, 597 insertions(+), 185 deletions(-) create mode 100755 OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs index 784076d..e76d8a4 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs @@ -226,16 +226,37 @@ public class BSCharacter : BSPhysObject bool ret = false; // If below the ground, move the avatar up - float terrainHeight = Scene.GetTerrainHeightAtXYZ(_position); - if (_position.Z < terrainHeight) + float terrainHeight = Scene.TerrainManager.GetTerrainHeightAtXYZ(_position); + if (Position.Z < terrainHeight) { - DetailLog("{0},BSCharacter.PositionAdjustUnderGround,call,pos={1},orient={2}", LocalID, _position, _orientation); - _position.Z = terrainHeight + 2.0f; + DetailLog("{0},BSCharacter.PositionAdjustUnderGround,call,pos={1},terrain={2}", LocalID, _position, terrainHeight); + Vector3 newPos = _position; + newPos.Z = terrainHeight + 2.0f; + _position = newPos; ret = true; } // TODO: check for out of bounds + return ret; + } + // A version of the sanity check that also makes sure a new position value is + // pushed back to the physics engine. This routine would be used by anyone + // who is not already pushing the value. + private bool PositionSanityCheck2() + { + bool ret = false; + if (PositionSanityCheck()) + { + // The new position value must be pushed into the physics engine but we can't + // just assign to "Position" because of potential call loops. + _scene.TaintedObject("BSCharacter.PositionSanityCheck", delegate() + { + DetailLog("{0},BSCharacter.PositionSanityCheck,taint,pos={1},orient={2}", LocalID, _position, _orientation); + BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation); + }); + ret = true; + } return ret; } @@ -500,9 +521,13 @@ public class BSCharacter : BSPhysObject // Avatars don't report their changes the usual way. Changes are checked for in the heartbeat loop. // base.RequestPhysicsterseUpdate(); - DetailLog("{0},BSCharacter.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5}", + // Do some sanity checking for the avatar. Make sure it's above ground and inbounds. + PositionSanityCheck2(); + + float heightHere = Scene.TerrainManager.GetTerrainHeightAtXYZ(_position); // just for debug + DetailLog("{0},BSCharacter.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5},terrain={6}", LocalID, entprop.Position, entprop.Rotation, entprop.Velocity, - entprop.Acceleration, entprop.RotationalVelocity); + entprop.Acceleration, entprop.RotationalVelocity, heightHere); } // Called by the scene when a collision with this object is reported diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs b/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs index 25084d8..d9270d1 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs @@ -48,11 +48,10 @@ public abstract class BSConstraint : IDisposable { if (m_enabled) { - // BulletSimAPI.RemoveConstraint(m_world.ID, m_body1.ID, m_body2.ID); + m_enabled = false; bool success = BulletSimAPI.DestroyConstraint2(m_world.Ptr, m_constraint.Ptr); m_world.scene.DetailLog("{0},BSConstraint.Dispose,taint,body1={1},body2={2},success={3}", BSScene.DetailLogZero, m_body1.ID, m_body2.ID, success); m_constraint.Ptr = System.IntPtr.Zero; - m_enabled = false; } } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs index d7213fc..8169e99 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs @@ -465,6 +465,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin } }//end SetDefaultsForType + // One step of the vehicle properties for the next 'pTimestep' seconds. internal void Step(float pTimestep) { if (m_type == Vehicle.TYPE_NONE) return; @@ -592,9 +593,9 @@ namespace OpenSim.Region.Physics.BulletSPlugin } // If below the terrain, move us above the ground a little. - if (pos.Z < m_prim.Scene.GetTerrainHeightAtXYZ(pos)) + if (pos.Z < m_prim.Scene.TerrainManager.GetTerrainHeightAtXYZ(pos)) { - pos.Z = m_prim.Scene.GetTerrainHeightAtXYZ(pos) + 2; + pos.Z = m_prim.Scene.TerrainManager.GetTerrainHeightAtXYZ(pos) + 2; m_prim.Position = pos; VDetailLog("{0},MoveLinear,terrainHeight,pos={1}", m_prim.LocalID, pos); } @@ -609,7 +610,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin } if ((m_flags & VehicleFlag.HOVER_TERRAIN_ONLY) != 0) { - m_VhoverTargetHeight = m_prim.Scene.GetTerrainHeightAtXY(pos.X, pos.Y) + m_VhoverHeight; + m_VhoverTargetHeight = m_prim.Scene.TerrainManager.GetTerrainHeightAtXY(pos.X, pos.Y) + m_VhoverHeight; } if ((m_flags & VehicleFlag.HOVER_GLOBAL_HEIGHT) != 0) { @@ -673,7 +674,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin { grav.Z = (float)(grav.Z * 1.125); } - float terraintemp = m_prim.Scene.GetTerrainHeightAtXYZ(pos); + float terraintemp = m_prim.Scene.TerrainManager.GetTerrainHeightAtXYZ(pos); float postemp = (pos.Z - terraintemp); if (postemp > 2.5f) { diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs index 6e205a9..ef463ca 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs @@ -1,58 +1,60 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyrightD - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -using System; -using System.Collections.Generic; -using System.Text; - -using OMV = OpenMetaverse; -using OpenSim.Framework; -using OpenSim.Region.Physics.Manager; - -namespace OpenSim.Region.Physics.BulletSPlugin -{ -// Class to wrap all objects. -// The rest of BulletSim doesn't need to keep checking for avatars or prims -// unless the difference is significant. -public abstract class BSPhysObject : PhysicsActor -{ - public abstract BSLinkset Linkset { get; set; } - - public abstract void Collide(uint collidingWith, BSPhysObject collidee, ActorTypes type, - OMV.Vector3 contactPoint, OMV.Vector3 contactNormal, float pentrationDepth); - public abstract void SendCollisions(); - - // Return the object mass without calculating it or side effects - public abstract float MassRaw { get; } - - public abstract BulletBody Body { get; set; } - public abstract void ZeroMotion(); - - public abstract void UpdateProperties(EntityProperties entprop); - - public abstract void Destroy(); -} -} +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyrightD + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +using System; +using System.Collections.Generic; +using System.Text; + +using OMV = OpenMetaverse; +using OpenSim.Framework; +using OpenSim.Region.Physics.Manager; + +namespace OpenSim.Region.Physics.BulletSPlugin +{ +// Class to wrap all objects. +// The rest of BulletSim doesn't need to keep checking for avatars or prims +// unless the difference is significant. +public abstract class BSPhysObject : PhysicsActor +{ + public abstract BSLinkset Linkset { get; set; } + + public abstract void Collide(uint collidingWith, BSPhysObject collidee, ActorTypes type, + OMV.Vector3 contactPoint, OMV.Vector3 contactNormal, float pentrationDepth); + public abstract void SendCollisions(); + + // Return the object mass without calculating it or side effects + public abstract float MassRaw { get; } + + public abstract BulletBody Body { get; set; } + public abstract void ZeroMotion(); + + public virtual void StepVehicle(float timeStep) { } + + public abstract void UpdateProperties(EntityProperties entprop); + + public abstract void Destroy(); +} +} diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index 036fd4f..6bfce5c 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs @@ -377,7 +377,7 @@ public sealed class BSPrim : BSPhysObject // Called each simulation step to advance vehicle characteristics. // Called from Scene when doing simulation step so we're in taint processing time. - public void StepVehicle(float timeStep) + public override void StepVehicle(float timeStep) { if (IsPhysical) _vehicle.Step(timeStep); diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs index ce64b9b..f80304d 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs @@ -39,8 +39,6 @@ using log4net; using OpenMetaverse; // TODOs for BulletSim (for BSScene, BSPrim, BSCharacter and BulletSim) -// Debug linkset -// Test with multiple regions in one simulator // Adjust character capsule size when height is adjusted (ScenePresence.SetHeight) // Test sculpties // Compute physics FPS reasonably @@ -54,10 +52,8 @@ using OpenMetaverse; // Use collision masks for collision with terrain and phantom objects // Check out llVolumeDetect. Must do something for that. // Should prim.link() and prim.delink() membership checking happen at taint time? -// changing the position and orientation of a linked prim must rebuild the constraint with the root. // Mesh sharing. Use meshHash to tell if we already have a hull of that shape and only create once // Do attachments need to be handled separately? Need collision events. Do not collide with VolumeDetect -// Implement the genCollisions feature in BulletSim::SetObjectProperties (don't pass up unneeded collisions) // Implement LockAngularMotion // Decide if clearing forces is the right thing to do when setting position (BulletSim::SetObjectTranslation) // Does NeedsMeshing() really need to exclude all the different shapes? @@ -85,18 +81,15 @@ public class BSScene : PhysicsScene, IPhysicsParameters // moved to a better place. private HashSet m_avatarsWithCollisions = new HashSet(); - private List m_vehicles = new List(); - - private float[] m_heightMap; - private float m_waterLevel; - private uint m_worldID; - public uint WorldID { get { return m_worldID; } } + // List of all the objects that have vehicle properties and should be called + // to update each physics step. + private List m_vehicles = new List(); // let my minuions use my logger public ILog Logger { get { return m_log; } } - private bool m_initialized = false; - + // If non-zero, the number of simulation steps between calls to the physics + // engine to output detailed physics stats. Debug logging level must be on also. private int m_detailedStatsStep = 0; public IMesher mesher; @@ -106,29 +99,31 @@ public class BSScene : PhysicsScene, IPhysicsParameters public float MeshMegaPrimThreshold { get; private set; } public float SculptLOD { get; private set; } - private BulletSim m_worldSim; - public BulletSim World - { - get { return m_worldSim; } - } - private BSConstraintCollection m_constraintCollection; - public BSConstraintCollection Constraints - { - get { return m_constraintCollection; } - } + public uint WorldID { get; private set; } + public BulletSim World { get; private set; } + + // All the constraints that have been allocated in this instance. + public BSConstraintCollection Constraints { get; private set; } + // Simulation parameters private int m_maxSubSteps; private float m_fixedTimeStep; private long m_simulationStep = 0; public long SimulationStep { get { return m_simulationStep; } } + // The length of the last timestep we were asked to simulate. + // This is used by the vehicle code. Since the vehicle code is called + // once per simulation step, its constants need to be scaled by this. public float LastSimulatedTimestep { get; private set; } // A value of the time now so all the collision and update routines do not have to get their own - // Set to 'now' just before all the prims and actors are called for collisions and updates - private int m_simulationNowTime; - public int SimulationNowTime { get { return m_simulationNowTime; } } + // Set to 'now' just before all the prims and actors are called for collisions and updates + public int SimulationNowTime { get; private set; } + + // True if initialized and ready to do simulation steps + private bool m_initialized = false; + // Pinned memory used to pass step information between managed and unmanaged private int m_maxCollisionsPerFrame; private CollisionDesc[] m_collisionArray; private GCHandle m_collisionArrayPinnedHandle; @@ -145,6 +140,10 @@ public class BSScene : PhysicsScene, IPhysicsParameters public const uint TERRAIN_ID = 0; // OpenSim senses terrain with a localID of zero public const uint GROUNDPLANE_ID = 1; + public const uint CHILDTERRAIN_ID = 2; // Terrain allocated based on our mega-prim childre start here + + private float m_waterLevel; + public BSTerrainManager TerrainManager { get; private set; } public ConfigurationParameters Params { @@ -155,12 +154,12 @@ public class BSScene : PhysicsScene, IPhysicsParameters get { return new Vector3(0f, 0f, Params.gravity); } } - private float m_maximumObjectMass; - public float MaximumObjectMass - { - get { return m_maximumObjectMass; } - } + public float MaximumObjectMass { get; private set; } + // When functions in the unmanaged code must be called, it is only + // done at a known time just before the simulation step. The taint + // system saves all these function calls and executes them in + // order before the simulation. public delegate void TaintCallback(); private struct TaintCallbackEntry { @@ -176,6 +175,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters private Object _taintLock = new Object(); // A pointer to an instance if this structure is passed to the C++ code + // Used to pass basic configuration values to the unmanaged code. ConfigurationParameters[] m_params; GCHandle m_paramsHandle; @@ -189,11 +189,11 @@ public class BSScene : PhysicsScene, IPhysicsParameters private bool m_physicsLoggingEnabled; private string m_physicsLoggingDir; private string m_physicsLoggingPrefix; - private int m_physicsLoggingFileMinutes; - - private bool m_vehicleLoggingEnabled; - public bool VehicleLoggingEnabled { get { return m_vehicleLoggingEnabled; } } + private int m_physicsLoggingFileMinutes; + // 'true' of the vehicle code is to log lots of details + public bool VehicleLoggingEnabled { get; private set; } + #region Construction and Initialization public BSScene(string identifier) { m_initialized = false; @@ -216,6 +216,9 @@ public class BSScene : PhysicsScene, IPhysicsParameters m_updateArray = new EntityProperties[m_maxUpdatesPerFrame]; m_updateArrayPinnedHandle = GCHandle.Alloc(m_updateArray, GCHandleType.Pinned); + mesher = meshmerizer; + _taintedObjects = new List(); + // Enable very detailed logging. // By creating an empty logger when not logging, the log message invocation code // can be left in and every call doesn't have to check for null. @@ -228,11 +231,6 @@ public class BSScene : PhysicsScene, IPhysicsParameters PhysicsLogging = new Logging.LogWriter(); } - // Get the version of the DLL - // TODO: this doesn't work yet. Something wrong with marshaling the returned string. - // BulletSimVersion = BulletSimAPI.GetVersion(); - // m_log.WarnFormat("{0}: BulletSim.dll version='{1}'", LogHeader, BulletSimVersion); - // If Debug logging level, enable logging from the unmanaged code if (m_log.IsDebugEnabled || PhysicsLogging.Enabled) { @@ -245,22 +243,32 @@ public class BSScene : PhysicsScene, IPhysicsParameters BulletSimAPI.SetDebugLogCallback(m_DebugLogCallbackHandle); } - _taintedObjects = new List(); - - mesher = meshmerizer; + // Get the version of the DLL + // TODO: this doesn't work yet. Something wrong with marshaling the returned string. + // BulletSimVersion = BulletSimAPI.GetVersion(); + // m_log.WarnFormat("{0}: BulletSim.dll version='{1}'", LogHeader, BulletSimVersion); - // The bounding box for the simulated world + // The bounding box for the simulated world. The origin is 0,0,0 unless we're + // a child in a mega-region. + // Turns out that Bullet really doesn't care about the extents of the simulated + // area. It tracks active objects no matter where they are. Vector3 worldExtent = new Vector3(Constants.RegionSize, Constants.RegionSize, 8192f); // m_log.DebugFormat("{0}: Initialize: Calling BulletSimAPI.Initialize.", LogHeader); - m_worldID = BulletSimAPI.Initialize(worldExtent, m_paramsHandle.AddrOfPinnedObject(), + WorldID = BulletSimAPI.Initialize(worldExtent, m_paramsHandle.AddrOfPinnedObject(), m_maxCollisionsPerFrame, m_collisionArrayPinnedHandle.AddrOfPinnedObject(), m_maxUpdatesPerFrame, m_updateArrayPinnedHandle.AddrOfPinnedObject()); // Initialization to support the transition to a new API which puts most of the logic // into the C# code so it is easier to modify and add to. - m_worldSim = new BulletSim(m_worldID, this, BulletSimAPI.GetSimHandle2(m_worldID)); - m_constraintCollection = new BSConstraintCollection(World); + World = new BulletSim(WorldID, this, BulletSimAPI.GetSimHandle2(WorldID)); + + Constraints = new BSConstraintCollection(World); + + // Note: choose one of the two following lines + // BulletSimAPI.CreateInitialGroundPlaneAndTerrain(WorldID); + TerrainManager = new BSTerrainManager(this); + TerrainManager.CreateInitialGroundPlaneAndTerrain(); m_initialized = true; } @@ -288,7 +296,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters m_physicsLoggingPrefix = pConfig.GetString("PhysicsLoggingPrefix", "physics-%REGIONNAME%-"); m_physicsLoggingFileMinutes = pConfig.GetInt("PhysicsLoggingFileMinutes", 5); // Very detailed logging for vehicle debugging - m_vehicleLoggingEnabled = pConfig.GetBoolean("VehicleLoggingEnabled", false); + VehicleLoggingEnabled = pConfig.GetBoolean("VehicleLoggingEnabled", false); // Do any replacements in the parameters m_physicsLoggingPrefix = m_physicsLoggingPrefix.Replace("%REGIONNAME%", RegionName); @@ -323,6 +331,38 @@ public class BSScene : PhysicsScene, IPhysicsParameters PhysicsLogging.Write("[BULLETS UNMANAGED]:" + msg); } + public override void Dispose() + { + // m_log.DebugFormat("{0}: Dispose()", LogHeader); + + // make sure no stepping happens while we're deleting stuff + m_initialized = false; + + TerrainManager.ReleaseGroundPlaneAndTerrain(); + + foreach (KeyValuePair kvp in PhysObjects) + { + kvp.Value.Destroy(); + } + PhysObjects.Clear(); + + // Now that the prims are all cleaned up, there should be no constraints left + if (Constraints != null) + { + Constraints.Dispose(); + Constraints = null; + } + + // Anything left in the unmanaged code should be cleaned out + BulletSimAPI.Shutdown(WorldID); + + // Not logging any more + PhysicsLogging.Close(); + } + #endregion // Construction and Initialization + + #region Prim and Avatar addition and removal + public override PhysicsActor AddAvatar(string avName, Vector3 position, Vector3 size, bool isFlying) { m_log.ErrorFormat("{0}: CALL TO AddAvatar in BSScene. NOT IMPLEMENTED", LogHeader); @@ -413,6 +453,9 @@ public class BSScene : PhysicsScene, IPhysicsParameters // information call is not needed. public override void AddPhysicsActorTaint(PhysicsActor prim) { } + #endregion // Prim and Avatar addition and removal + + #region Simulation // Simulate one timestep public override float Simulate(float timeStep) { @@ -428,7 +471,8 @@ public class BSScene : PhysicsScene, IPhysicsParameters int simulateStartTime = Util.EnvironmentTickCount(); - // update the prim states while we know the physics engine is not busy + // update the prim states while we know the physics engine is not busy + int numTaints = _taintedObjects.Count; ProcessTaints(); // Some of the prims operate with special vehicle properties @@ -440,14 +484,17 @@ public class BSScene : PhysicsScene, IPhysicsParameters int numSubSteps = 0; try { - numSubSteps = BulletSimAPI.PhysicsStep(m_worldID, timeStep, m_maxSubSteps, m_fixedTimeStep, + numSubSteps = BulletSimAPI.PhysicsStep(WorldID, timeStep, m_maxSubSteps, m_fixedTimeStep, out updatedEntityCount, out updatedEntitiesPtr, out collidersCount, out collidersPtr); - DetailLog("{0},Simulate,call, substeps={1}, updates={2}, colliders={3}", DetailLogZero, numSubSteps, updatedEntityCount, collidersCount); + DetailLog("{0},Simulate,call, nTaints= {1}, substeps={2}, updates={3}, colliders={4}", + DetailLogZero, numTaints, numSubSteps, updatedEntityCount, collidersCount); } catch (Exception e) { - m_log.WarnFormat("{0},PhysicsStep Exception: substeps={1}, updates={2}, colliders={3}, e={4}", LogHeader, numSubSteps, updatedEntityCount, collidersCount, e); - // DetailLog("{0},PhysicsStepException,call, substeps={1}, updates={2}, colliders={3}", DetailLogZero, numSubSteps, updatedEntityCount, collidersCount); + m_log.WarnFormat("{0},PhysicsStep Exception: nTaints={1}, substeps={2}, updates={3}, colliders={4}, e={5}", + LogHeader, numTaints, numSubSteps, updatedEntityCount, collidersCount, e); + DetailLog("{0},PhysicsStepException,call, nTaints={1}, substeps={2}, updates={3}, colliders={4}", + DetailLogZero, numTaints, numSubSteps, updatedEntityCount, collidersCount); updatedEntityCount = 0; collidersCount = 0; } @@ -456,7 +503,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters // Don't have to use the pointers passed back since we know it is the same pinned memory we passed in // Get a value for 'now' so all the collision and update routines don't have to get their own - m_simulationNowTime = Util.EnvironmentTickCount(); + SimulationNowTime = Util.EnvironmentTickCount(); // If there were collisions, process them by sending the event to the prim. // Collisions must be processed before updates. @@ -527,7 +574,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters // Something has collided private void SendCollision(uint localID, uint collidingWith, Vector3 collidePoint, Vector3 collideNormal, float penetration) { - if (localID == TERRAIN_ID || localID == GROUNDPLANE_ID) + if (localID <= TerrainManager.HighestTerrainID) { return; // don't send collisions to the terrain } @@ -539,7 +586,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters BSPhysObject collidee = null; ActorTypes type = ActorTypes.Prim; - if (collidingWith == TERRAIN_ID || collidingWith == GROUNDPLANE_ID) + if (collidingWith <= TerrainManager.HighestTerrainID) { type = ActorTypes.Ground; } @@ -558,28 +605,14 @@ public class BSScene : PhysicsScene, IPhysicsParameters return; } + #endregion // Simulation + public override void GetResults() { } - public override void SetTerrain(float[] heightMap) { - m_heightMap = heightMap; - this.TaintedObject("BSScene.SetTerrain", delegate() - { - BulletSimAPI.SetHeightmap(m_worldID, m_heightMap); - }); - } + #region Terrain - // Someday we will have complex terrain with caves and tunnels - // For the moment, it's flat and convex - public float GetTerrainHeightAtXYZ(Vector3 loc) - { - return GetTerrainHeightAtXY(loc.X, loc.Y); - } - - public float GetTerrainHeightAtXY(float tX, float tY) - { - if (tX < 0 || tX >= Constants.RegionSize || tY < 0 || tY >= Constants.RegionSize) - return 30; - return m_heightMap[((int)tX) * Constants.RegionSize + ((int)tY)]; + public override void SetTerrain(float[] heightMap) { + TerrainManager.SetTerrain(heightMap); } public override void SetWaterLevel(float baseheight) @@ -595,35 +628,29 @@ public class BSScene : PhysicsScene, IPhysicsParameters public override void DeleteTerrain() { // m_log.DebugFormat("{0}: DeleteTerrain()", LogHeader); + } + + // Although no one seems to check this, I do support combining. + public override bool SupportsCombining() + { + return TerrainManager.SupportsCombining(); } - - public override void Dispose() - { - // m_log.DebugFormat("{0}: Dispose()", LogHeader); - - // make sure no stepping happens while we're deleting stuff - m_initialized = false; - - foreach (KeyValuePair kvp in PhysObjects) - { - kvp.Value.Destroy(); - } - PhysObjects.Clear(); - - // Now that the prims are all cleaned up, there should be no constraints left - if (m_constraintCollection != null) - { - m_constraintCollection.Dispose(); - m_constraintCollection = null; - } - - // Anything left in the unmanaged code should be cleaned out - BulletSimAPI.Shutdown(WorldID); - - // Not logging any more - PhysicsLogging.Close(); + // This call says I am a child to region zero in a mega-region. 'pScene' is that + // of region zero, 'offset' is my offset from regions zero's origin, and + // 'extents' is the largest XY that is handled in my region. + public override void Combine(PhysicsScene pScene, Vector3 offset, Vector3 extents) + { + TerrainManager.Combine(pScene, offset, extents); + } + + // Unhook all the combining that I know about. + public override void UnCombine(PhysicsScene pScene) + { + TerrainManager.UnCombine(pScene); } + #endregion // Terrain + public override Dictionary GetTopColliders() { return new Dictionary(); @@ -833,14 +860,14 @@ public class BSScene : PhysicsScene, IPhysicsParameters // no locking because only called when physics engine is not busy private void ProcessVehicles(float timeStep) { - foreach (BSPrim prim in m_vehicles) + foreach (BSPhysObject pobj in m_vehicles) { - prim.StepVehicle(timeStep); + pobj.StepVehicle(timeStep); } } #endregion Vehicles - #region Parameters + #region INI and command line parameter processing delegate void ParamUser(BSScene scene, IConfig conf, string paramName, float val); delegate float ParamGet(BSScene scene); @@ -943,9 +970,9 @@ public class BSScene : PhysicsScene, IPhysicsParameters (s,p,l,v) => { s.m_maxUpdatesPerFrame = (int)v; } ), new ParameterDefn("MaxObjectMass", "Maximum object mass (10000.01)", 10000.01f, - (s,cf,p,v) => { s.m_maximumObjectMass = cf.GetFloat(p, v); }, - (s) => { return (float)s.m_maximumObjectMass; }, - (s,p,l,v) => { s.m_maximumObjectMass = v; } ), + (s,cf,p,v) => { s.MaximumObjectMass = cf.GetFloat(p, v); }, + (s) => { return (float)s.MaximumObjectMass; }, + (s,p,l,v) => { s.MaximumObjectMass = v; } ), new ParameterDefn("PID_D", "Derivitive factor for motion smoothing", 2200f, @@ -1207,6 +1234,8 @@ public class BSScene : PhysicsScene, IPhysicsParameters private PhysParameterEntry[] SettableParameters = new PhysParameterEntry[1]; + // This creates an array in the correct format for returning the list of + // parameters. This is used by the 'list' option of the 'physics' command. private void BuildParameterTable() { if (SettableParameters.Length < ParameterDefinitions.Length) @@ -1283,7 +1312,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters TaintedObject("BSScene.UpdateParameterSet", delegate() { foreach (uint lID in objectIDs) { - BulletSimAPI.UpdateParameter(m_worldID, lID, xparm, xval); + BulletSimAPI.UpdateParameter(WorldID, lID, xparm, xval); } }); break; @@ -1301,7 +1330,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters string xparm = parm.ToLower(); float xval = val; TaintedObject("BSScene.TaintedUpdateParameter", delegate() { - BulletSimAPI.UpdateParameter(m_worldID, xlocalID, xparm, xval); + BulletSimAPI.UpdateParameter(WorldID, xlocalID, xparm, xval); }); } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs new file mode 100755 index 0000000..28c1940 --- /dev/null +++ b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs @@ -0,0 +1,307 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyrightD + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +using System; +using System.Collections.Generic; +using System.Text; + +using OpenSim.Framework; +using OpenSim.Region.Framework; +using OpenSim.Region.CoreModules; +using OpenSim.Region.Physics.Manager; + +using Nini.Config; +using log4net; + +using OpenMetaverse; + +namespace OpenSim.Region.Physics.BulletSPlugin +{ +public class BSTerrainManager +{ + static string LogHeader = "[BULLETSIM TERRAIN MANAGER]"; + + BSScene m_physicsScene; + + private BulletBody m_groundPlane; + + // If doing mega-regions, if we're region zero we will be managing multiple + // region terrains since region zero does the physics for the whole mega-region. + private Dictionary m_terrains; + private Dictionary m_heightMaps; + + // If we are doing mega-regions, terrains are added from TERRAIN_ID to m_terrainCount. + // This is incremented before assigning to new region so it is the last ID allocated. + private uint m_terrainCount = BSScene.CHILDTERRAIN_ID - 1; + public uint HighestTerrainID { get {return m_terrainCount; } } + + // If doing mega-regions, this holds our offset from region zero of + // the mega-regions. "parentScene" points to the PhysicsScene of region zero. + private Vector3 m_worldOffset = Vector3.Zero; + public Vector2 WorldExtents = new Vector2((int)Constants.RegionSize, (int)Constants.RegionSize); + private PhysicsScene m_parentScene = null; + + public BSTerrainManager(BSScene physicsScene) + { + m_physicsScene = physicsScene; + m_terrains = new Dictionary(); + m_heightMaps = new Dictionary(); + } + + // Create the initial instance of terrain and the underlying ground plane. + // The objects are allocated in the unmanaged space and the pointers are tracked + // by the managed code. + // The terrains and the groundPlane are not added to the list of PhysObjects. + // This is called from the initialization routine so we presume it is + // safe to call Bullet in real time. We hope no one is moving around prim yet. + public void CreateInitialGroundPlaneAndTerrain() + { + // The ground plane is here to catch things that are trying to drop to negative infinity + m_groundPlane = new BulletBody(BSScene.GROUNDPLANE_ID, + BulletSimAPI.CreateGroundPlaneBody2(BSScene.GROUNDPLANE_ID, 1f, 0.4f)); + BulletSimAPI.AddObjectToWorld2(m_physicsScene.World.Ptr, m_groundPlane.Ptr); + + Vector3 minTerrainCoords = new Vector3(0f, 0f, 24f); + Vector3 maxTerrainCoords = new Vector3(Constants.RegionSize, Constants.RegionSize, 25f); + int totalHeights = (int)maxTerrainCoords.X * (int)maxTerrainCoords.Y; + float[] initialMap = new float[totalHeights]; + for (int ii = 0; ii < totalHeights; ii++) + { + initialMap[ii] = 25f; + } + CreateNewTerrainSegment(BSScene.TERRAIN_ID, initialMap, minTerrainCoords, maxTerrainCoords); + } + + public void ReleaseGroundPlaneAndTerrain() + { + if (BulletSimAPI.RemoveObjectFromWorld2(m_physicsScene.World.Ptr, m_groundPlane.Ptr)) + { + BulletSimAPI.DestroyObject2(m_physicsScene.World.Ptr, m_groundPlane.Ptr); + } + m_groundPlane.Ptr = IntPtr.Zero; + + foreach (KeyValuePair kvp in m_terrains) + { + if (BulletSimAPI.RemoveObjectFromWorld2(m_physicsScene.World.Ptr, kvp.Value.Ptr)) + { + BulletSimAPI.DestroyObject2(m_physicsScene.World.Ptr, kvp.Value.Ptr); + BulletSimAPI.ReleaseHeightmapInfo2(m_heightMaps[kvp.Key].Ptr); + } + } + m_terrains.Clear(); + m_heightMaps.Clear(); + } + + // Create a new terrain description. This is used for mega-regions where + // the children of region zero give region zero all of the terrain + // segments since region zero does all the physics for the mega-region. + // Call at taint time!! + public void CreateNewTerrainSegment(uint id, float[] heightMap, Vector3 minCoords, Vector3 maxCoords) + { + // The Z coordinates are recalculated to be the min and max height of the terrain + // itself. The caller may have passed us the real region extent. + float minZ = float.MaxValue; + float maxZ = float.MinValue; + int hSize = heightMap.Length; + for (int ii = 0; ii < hSize; ii++) + { + minZ = heightMap[ii] < minZ ? heightMap[ii] : minZ; + maxZ = heightMap[ii] > maxZ ? heightMap[ii] : maxZ; + } + minCoords.Z = minZ; + maxCoords.Z = maxZ; + // If the terrain is flat, make a difference so we get a good bounding box + if (minZ == maxZ) + minZ -= 0.2f; + Vector2 terrainRegionBase = new Vector2(minCoords.X, minCoords.Y); + + // Create the heightmap data structure in the unmanaged space + BulletHeightMapInfo mapInfo = new BulletHeightMapInfo( + BulletSimAPI.CreateHeightmap2(minCoords, maxCoords, heightMap), heightMap); + mapInfo.terrainRegionBase = terrainRegionBase; + mapInfo.maxRegionExtent = maxCoords; + mapInfo.minZ = minZ; + mapInfo.maxZ = maxZ; + mapInfo.sizeX = maxCoords.X - minCoords.X; + mapInfo.sizeY = maxCoords.Y - minCoords.Y; + + DetailLog("{0},BSScene.CreateNewTerrainSegment,call,minZ={1},maxZ={2},hMapPtr={3},minC={4},maxC={5}", + BSScene.DetailLogZero, minZ, maxZ, mapInfo.Ptr, minCoords, maxCoords); + // Create the terrain body from that heightmap + BulletBody terrainBody = new BulletBody(id, BulletSimAPI.CreateTerrainBody2(id, mapInfo.Ptr, 0.01f)); + + BulletSimAPI.SetFriction2(terrainBody.Ptr, m_physicsScene.Params.terrainFriction); + BulletSimAPI.SetHitFraction2(terrainBody.Ptr, m_physicsScene.Params.terrainHitFraction); + BulletSimAPI.SetRestitution2(terrainBody.Ptr, m_physicsScene.Params.terrainRestitution); + BulletSimAPI.SetCollisionFlags2(terrainBody.Ptr, CollisionFlags.CF_STATIC_OBJECT); + BulletSimAPI.Activate2(terrainBody.Ptr, true); + + // Add the new terrain to the dynamics world + BulletSimAPI.AddObjectToWorld2(m_physicsScene.World.Ptr, terrainBody.Ptr); + BulletSimAPI.UpdateSingleAabb2(m_physicsScene.World.Ptr, terrainBody.Ptr); + + + // Add the created terrain to the management set. If we are doing mega-regions, + // the terrains of our children will be added. + m_terrains.Add(terrainRegionBase, terrainBody); + m_heightMaps.Add(terrainRegionBase, mapInfo); + } + + public void SetTerrain(float[] heightMap) { + if (m_worldOffset != Vector3.Zero && m_parentScene != null) + { + // If doing the mega-prim stuff and we are the child of the zero region, + // the terrain is really added to our parent + if (m_parentScene is BSScene) + { + ((BSScene)m_parentScene).TerrainManager.SetTerrain(heightMap, m_worldOffset); + } + } + else + { + // if not doing the mega-prim thing, just change the terrain + SetTerrain(heightMap, m_worldOffset); + } + } + + private void SetTerrain(float[] heightMap, Vector3 tOffset) + { + float minZ = float.MaxValue; + float maxZ = float.MinValue; + + // Copy heightMap local and compute some statistics. + // Not really sure if we need to do this deep copy but, given + // the magic that happens to make the closure for taint + // below, I don't want there to be any problem with sharing + // locations of there are multiple calls to this routine + // within one tick. + int heightMapSize = heightMap.Length; + float[] localHeightMap = new float[heightMapSize]; + for (int ii = 0; ii < heightMapSize; ii++) + { + float height = heightMap[ii]; + if (height < minZ) minZ = height; + if (height > maxZ) maxZ = height; + localHeightMap[ii] = height; + } + + Vector2 terrainRegionBase = new Vector2(tOffset.X, tOffset.Y); + BulletHeightMapInfo mapInfo; + if (m_heightMaps.TryGetValue(terrainRegionBase, out mapInfo)) + { + // If this is terrain we know about, it's easy to update + mapInfo.heightMap = localHeightMap; + m_physicsScene.TaintedObject("BSScene.SetTerrain:UpdateExisting", delegate() + { + DetailLog("{0},SetTerrain:UpdateExisting,baseX={1},baseY={2},minZ={3},maxZ={4}", + BSScene.DetailLogZero, tOffset.X, tOffset.Y, minZ, maxZ); + BulletSimAPI.UpdateHeightMap2(m_physicsScene.World.Ptr, mapInfo.Ptr, mapInfo.heightMap); + }); + } + else + { + // Our mega-prim child is giving us a new terrain to add to the phys world + uint newTerrainID = ++m_terrainCount; + + Vector3 minCoords = tOffset; + minCoords.Z = minZ; + Vector3 maxCoords = new Vector3(tOffset.X + Constants.RegionSize, + tOffset.Y + Constants.RegionSize, + maxZ); + m_physicsScene.TaintedObject("BSScene.SetTerrain:NewTerrain", delegate() + { + DetailLog("{0},SetTerrain:NewTerrain,baseX={1},baseY={2}", BSScene.DetailLogZero, tOffset.X, tOffset.Y); + CreateNewTerrainSegment(newTerrainID, heightMap, minCoords, maxCoords); + }); + } + } + + // Someday we will have complex terrain with caves and tunnels + // For the moment, it's flat and convex + public float GetTerrainHeightAtXYZ(Vector3 loc) + { + return GetTerrainHeightAtXY(loc.X, loc.Y); + } + + // Given an X and Y, find the height of the terrain. + // Since we could be handling multiple terrains for a mega-region, + // the base of the region is calcuated assuming all regions are + // the same size and that is the default. + // Once the heightMapInfo is found, we have all the information to + // compute the offset into the array. + public float GetTerrainHeightAtXY(float tX, float tY) + { + float ret = 30f; + + int offsetX = ((int)(tX / (int)Constants.RegionSize)) * (int)Constants.RegionSize; + int offsetY = ((int)(tY / (int)Constants.RegionSize)) * (int)Constants.RegionSize; + Vector2 terrainBaseXY = new Vector2(offsetX, offsetY); + + BulletHeightMapInfo mapInfo; + if (m_heightMaps.TryGetValue(terrainBaseXY, out mapInfo)) + { + float regionX = tX - offsetX; + float regionY = tY - offsetY; + regionX = regionX > mapInfo.sizeX ? 0 : regionX; + regionY = regionY > mapInfo.sizeY ? 0 : regionY; + ret = mapInfo.heightMap[(int)(regionX * mapInfo.sizeX + regionY)]; + } + else + { + m_physicsScene.Logger.ErrorFormat("{0} GetTerrainHeightAtXY: terrain not found: x={1}, y={2}", + LogHeader, tX, tY); + } + return ret; + } + + // Although no one seems to check this, I do support combining. + public bool SupportsCombining() + { + return true; + } + // This call says I am a child to region zero in a mega-region. 'pScene' is that + // of region zero, 'offset' is my offset from regions zero's origin, and + // 'extents' is the largest XY that is handled in my region. + public void Combine(PhysicsScene pScene, Vector3 offset, Vector3 extents) + { + m_worldOffset = offset; + WorldExtents = new Vector2(extents.X, extents.Y); + m_parentScene = pScene; + } + + // Unhook all the combining that I know about. + public void UnCombine(PhysicsScene pScene) + { + // Just like ODE, for the moment a NOP + } + + + private void DetailLog(string msg, params Object[] args) + { + m_physicsScene.PhysicsLogging.Write(msg, args); + } +} +} diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs index dab2420..3b319fb 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs @@ -33,6 +33,9 @@ using OpenMetaverse; namespace OpenSim.Region.Physics.BulletSPlugin { // Classes to allow some type checking for the API +// These hold pointers to allocated objects in the unmanaged space. + +// The physics engine controller class created at initialization public struct BulletSim { public BulletSim(uint id, BSScene bss, IntPtr xx) { ID = id; scene = bss; Ptr = xx; } @@ -42,6 +45,7 @@ public struct BulletSim public IntPtr Ptr; } +// An allocated Bullet btRigidBody public struct BulletBody { public BulletBody(uint id, IntPtr xx) { ID = id; Ptr = xx; } @@ -49,12 +53,35 @@ public struct BulletBody public uint ID; } +// An allocated Bullet btConstraint public struct BulletConstraint { public BulletConstraint(IntPtr xx) { Ptr = xx; } public IntPtr Ptr; } +// An allocated HeightMapThing which hold various heightmap info +// Made a class rather than a struct so there would be only one +// instance of this and C# will pass around pointers rather +// than making copies. +public class BulletHeightMapInfo +{ + public BulletHeightMapInfo(IntPtr xx, float[] hm) { + Ptr = xx; + heightMap = hm; + terrainRegionBase = new Vector2(0f, 0f); + maxRegionExtent = new Vector3(100f, 100f, 25f); + minZ = maxZ = 0f; + sizeX = sizeY = 256f; + } + public IntPtr Ptr; + public float[] heightMap; + public Vector2 terrainRegionBase; + public Vector3 maxRegionExtent; + public float sizeX, sizeY; + public float minZ, maxZ; +} + // =============================================================================== [StructLayout(LayoutKind.Sequential)] public struct ConvexHull @@ -231,6 +258,9 @@ public static extern uint Initialize(Vector3 maxPosition, IntPtr parms, int maxUpdates, IntPtr updateArray); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern void CreateInitialGroundPlaneAndTerrain(uint worldID); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern void SetHeightmap(uint worldID, [MarshalAs(UnmanagedType.LPArray)] float[] heightMap); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] @@ -414,12 +444,23 @@ public static extern bool DeleteCollisionShape2(IntPtr world, IntPtr shape); // ===================================================================================== [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern IntPtr CreateGroundPlaneBody2(uint id, Vector3 center, float collisionMargin); +public static extern IntPtr CreateGroundPlaneBody2(uint id, float height, float collisionMargin); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern IntPtr CreateTerrainBody2(uint id, - Vector3 minCoords, Vector3 maxCoords, float collisionMargin, - [MarshalAs(UnmanagedType.LPArray)] float[] heightMap); + IntPtr heightMapInfo, + float collisionMargin); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern IntPtr CreateHeightmap2(Vector3 minCoords, Vector3 maxCoords, + [MarshalAs(UnmanagedType.LPArray)] float[] heightMap); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern bool ReleaseHeightmapInfo2(IntPtr heightMapInfo); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern void UpdateHeightMap2(IntPtr world, IntPtr heightMapInfo, + [MarshalAs(UnmanagedType.LPArray)] float[] heightMap); // ===================================================================================== [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] @@ -473,11 +514,16 @@ public static extern bool SetConstraintParam2(IntPtr constrain, ConstraintParams [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern bool DestroyConstraint2(IntPtr world, IntPtr constrain); +// ===================================================================================== [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern Vector3 AddObjectToWorld2(IntPtr world, IntPtr obj); +public static extern bool AddObjectToWorld2(IntPtr world, IntPtr obj); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern Vector3 RemoveObjectFromWorld2(IntPtr world, IntPtr obj); +public static extern bool RemoveObjectFromWorld2(IntPtr world, IntPtr obj); + +// ===================================================================================== +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern void Activate2(IntPtr obj, bool forceActivation); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern Vector3 GetPosition2(IntPtr obj); @@ -522,6 +568,9 @@ public static extern bool SetContactProcessingThreshold2(IntPtr obj, float val); public static extern bool SetFriction2(IntPtr obj, float val); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern bool SetHitFraction2(IntPtr obj, float val); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern bool SetRestitution2(IntPtr obj, float val); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] @@ -564,7 +613,7 @@ public static extern bool SetMargin2(IntPtr obj, float val); public static extern bool UpdateSingleAabb2(IntPtr world, IntPtr obj); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern bool DestroyObject2(IntPtr world, uint id); +public static extern bool DestroyObject2(IntPtr world, IntPtr obj); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern void DumpPhysicsStatistics2(IntPtr sim); -- cgit v1.1 From d3adf9b2b3bd8e0e76168cd6eb6414f3123c5f02 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Sat, 25 Aug 2012 23:25:29 -0700 Subject: BulletSim: fix line endings. --- OpenSim/Region/Physics/BulletSPlugin/BSScene.cs | 44 ++++++++++++------------- 1 file changed, 22 insertions(+), 22 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs index f80304d..7b4802e 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs @@ -102,7 +102,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters public uint WorldID { get; private set; } public BulletSim World { get; private set; } - // All the constraints that have been allocated in this instance. + // All the constraints that have been allocated in this instance. public BSConstraintCollection Constraints { get; private set; } // Simulation parameters @@ -117,7 +117,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters public float LastSimulatedTimestep { get; private set; } // A value of the time now so all the collision and update routines do not have to get their own - // Set to 'now' just before all the prims and actors are called for collisions and updates + // Set to 'now' just before all the prims and actors are called for collisions and updates public int SimulationNowTime { get; private set; } // True if initialized and ready to do simulation steps @@ -140,8 +140,8 @@ public class BSScene : PhysicsScene, IPhysicsParameters public const uint TERRAIN_ID = 0; // OpenSim senses terrain with a localID of zero public const uint GROUNDPLANE_ID = 1; - public const uint CHILDTERRAIN_ID = 2; // Terrain allocated based on our mega-prim childre start here - + public const uint CHILDTERRAIN_ID = 2; // Terrain allocated based on our mega-prim childre start here + private float m_waterLevel; public BSTerrainManager TerrainManager { get; private set; } @@ -189,8 +189,8 @@ public class BSScene : PhysicsScene, IPhysicsParameters private bool m_physicsLoggingEnabled; private string m_physicsLoggingDir; private string m_physicsLoggingPrefix; - private int m_physicsLoggingFileMinutes; - // 'true' of the vehicle code is to log lots of details + private int m_physicsLoggingFileMinutes; + // 'true' of the vehicle code is to log lots of details public bool VehicleLoggingEnabled { get; private set; } #region Construction and Initialization @@ -266,7 +266,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters Constraints = new BSConstraintCollection(World); // Note: choose one of the two following lines - // BulletSimAPI.CreateInitialGroundPlaneAndTerrain(WorldID); + // BulletSimAPI.CreateInitialGroundPlaneAndTerrain(WorldID); TerrainManager = new BSTerrainManager(this); TerrainManager.CreateInitialGroundPlaneAndTerrain(); @@ -471,7 +471,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters int simulateStartTime = Util.EnvironmentTickCount(); - // update the prim states while we know the physics engine is not busy + // update the prim states while we know the physics engine is not busy int numTaints = _taintedObjects.Count; ProcessTaints(); @@ -611,7 +611,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters #region Terrain - public override void SetTerrain(float[] heightMap) { + public override void SetTerrain(float[] heightMap) { TerrainManager.SetTerrain(heightMap); } @@ -628,25 +628,25 @@ public class BSScene : PhysicsScene, IPhysicsParameters public override void DeleteTerrain() { // m_log.DebugFormat("{0}: DeleteTerrain()", LogHeader); - } - - // Although no one seems to check this, I do support combining. - public override bool SupportsCombining() - { - return TerrainManager.SupportsCombining(); + } + + // Although no one seems to check this, I do support combining. + public override bool SupportsCombining() + { + return TerrainManager.SupportsCombining(); } // This call says I am a child to region zero in a mega-region. 'pScene' is that // of region zero, 'offset' is my offset from regions zero's origin, and // 'extents' is the largest XY that is handled in my region. public override void Combine(PhysicsScene pScene, Vector3 offset, Vector3 extents) - { + { TerrainManager.Combine(pScene, offset, extents); - } - - // Unhook all the combining that I know about. - public override void UnCombine(PhysicsScene pScene) - { - TerrainManager.UnCombine(pScene); + } + + // Unhook all the combining that I know about. + public override void UnCombine(PhysicsScene pScene) + { + TerrainManager.UnCombine(pScene); } #endregion // Terrain -- cgit v1.1 From ae852bb8738c7bce60c8fee9fbf6038288bd9363 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Wed, 29 Aug 2012 09:20:09 -0700 Subject: BulletSim: clean up some variable naming for consistancy. Update DLL API for new terrain and shape/body pattern methods. Terrain creation and modification uses new shape/body pattern. Move debug logging callback set to initialization call so logging is per physics engine. --- .../Region/Physics/BulletSPlugin/BSCharacter.cs | 78 ++++++------ OpenSim/Region/Physics/BulletSPlugin/BSScene.cs | 13 +- .../Physics/BulletSPlugin/BSTerrainManager.cs | 139 +++++++++++++++------ .../Region/Physics/BulletSPlugin/BulletSimAPI.cs | 55 +++++--- 4 files changed, 183 insertions(+), 102 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs index e76d8a4..fa21233 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs @@ -39,8 +39,7 @@ public class BSCharacter : BSPhysObject private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private static readonly string LogHeader = "[BULLETS CHAR]"; - private BSScene _scene; - public BSScene Scene { get { return _scene; } } + public BSScene Scene { get; private set; } private String _avName; // private bool _stopped; private Vector3 _size; @@ -92,7 +91,7 @@ public class BSCharacter : BSPhysObject { _localID = localID; _avName = avName; - _scene = parent_scene; + Scene = parent_scene; _position = pos; _size = size; _flying = isFlying; @@ -101,11 +100,11 @@ public class BSCharacter : BSPhysObject _buoyancy = ComputeBuoyancyFromFlying(isFlying); // The dimensions of the avatar capsule are kept in the scale. // Physics creates a unit capsule which is scaled by the physics engine. - _scale = new Vector3(_scene.Params.avatarCapsuleRadius, _scene.Params.avatarCapsuleRadius, size.Z); - _density = _scene.Params.avatarDensity; + _scale = new Vector3(Scene.Params.avatarCapsuleRadius, Scene.Params.avatarCapsuleRadius, size.Z); + _density = Scene.Params.avatarDensity; ComputeAvatarVolumeAndMass(); // set _avatarVolume and _mass based on capsule size, _density and _scale - Linkset = new BSLinkset(_scene, this); + Linkset = new BSLinkset(Scene, this); ShapeData shapeData = new ShapeData(); shapeData.ID = _localID; @@ -117,19 +116,19 @@ public class BSCharacter : BSPhysObject shapeData.Mass = _mass; shapeData.Buoyancy = _buoyancy; shapeData.Static = ShapeData.numericFalse; - shapeData.Friction = _scene.Params.avatarFriction; - shapeData.Restitution = _scene.Params.avatarRestitution; + shapeData.Friction = Scene.Params.avatarFriction; + shapeData.Restitution = Scene.Params.avatarRestitution; // do actual create at taint time - _scene.TaintedObject("BSCharacter.create", delegate() + Scene.TaintedObject("BSCharacter.create", delegate() { DetailLog("{0},BSCharacter.create", _localID); - BulletSimAPI.CreateObject(parent_scene.WorldID, shapeData); + BulletSimAPI.CreateObject(Scene.WorldID, shapeData); // Set the buoyancy for flying. This will be refactored when all the settings happen in C# - BulletSimAPI.SetObjectBuoyancy(_scene.WorldID, LocalID, _buoyancy); + BulletSimAPI.SetObjectBuoyancy(Scene.WorldID, LocalID, _buoyancy); - Body = new BulletBody(LocalID, BulletSimAPI.GetBodyHandle2(_scene.World.Ptr, LocalID)); + Body = new BulletBody(LocalID, BulletSimAPI.GetBodyHandle2(Scene.World.Ptr, LocalID)); // avatars get all collisions no matter what (makes walking on ground and such work) BulletSimAPI.AddToCollisionFlags2(Body.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); }); @@ -141,9 +140,9 @@ public class BSCharacter : BSPhysObject public override void Destroy() { DetailLog("{0},BSCharacter.Destroy", LocalID); - _scene.TaintedObject("BSCharacter.destroy", delegate() + Scene.TaintedObject("BSCharacter.destroy", delegate() { - BulletSimAPI.DestroyObject(_scene.WorldID, _localID); + BulletSimAPI.DestroyObject(Scene.WorldID, _localID); }); } @@ -172,9 +171,9 @@ public class BSCharacter : BSPhysObject ComputeAvatarVolumeAndMass(); - _scene.TaintedObject("BSCharacter.setSize", delegate() + Scene.TaintedObject("BSCharacter.setSize", delegate() { - BulletSimAPI.SetObjectScaleMass(_scene.WorldID, LocalID, _scale, _mass, true); + BulletSimAPI.SetObjectScaleMass(Scene.WorldID, LocalID, _scale, _mass, true); }); } @@ -203,17 +202,17 @@ public class BSCharacter : BSPhysObject public override Vector3 Position { get { - // _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID); + // _position = BulletSimAPI.GetObjectPosition(Scene.WorldID, _localID); return _position; } set { _position = value; PositionSanityCheck(); - _scene.TaintedObject("BSCharacter.setPosition", delegate() + Scene.TaintedObject("BSCharacter.setPosition", delegate() { DetailLog("{0},BSCharacter.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation); - BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation); + BulletSimAPI.SetObjectTranslation(Scene.WorldID, _localID, _position, _orientation); }); } } @@ -229,10 +228,8 @@ public class BSCharacter : BSPhysObject float terrainHeight = Scene.TerrainManager.GetTerrainHeightAtXYZ(_position); if (Position.Z < terrainHeight) { - DetailLog("{0},BSCharacter.PositionAdjustUnderGround,call,pos={1},terrain={2}", LocalID, _position, terrainHeight); - Vector3 newPos = _position; - newPos.Z = terrainHeight + 2.0f; - _position = newPos; + DetailLog("{0},BSCharacter.PositionAdjustUnderGround,call,pos={1},terrain={2}", LocalID, _position, terrainHeight); + _position.Z = terrainHeight + 2.0f; ret = true; } @@ -250,10 +247,10 @@ public class BSCharacter : BSPhysObject { // The new position value must be pushed into the physics engine but we can't // just assign to "Position" because of potential call loops. - _scene.TaintedObject("BSCharacter.PositionSanityCheck", delegate() + Scene.TaintedObject("BSCharacter.PositionSanityCheck", delegate() { DetailLog("{0},BSCharacter.PositionSanityCheck,taint,pos={1},orient={2}", LocalID, _position, _orientation); - BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation); + BulletSimAPI.SetObjectTranslation(Scene.WorldID, _localID, _position, _orientation); }); ret = true; } @@ -301,10 +298,10 @@ public class BSCharacter : BSPhysObject set { _velocity = value; // m_log.DebugFormat("{0}: set velocity = {1}", LogHeader, _velocity); - _scene.TaintedObject("BSCharacter.setVelocity", delegate() + Scene.TaintedObject("BSCharacter.setVelocity", delegate() { DetailLog("{0},BSCharacter.setVelocity,taint,vel={1}", LocalID, _velocity); - BulletSimAPI.SetObjectVelocity(_scene.WorldID, _localID, _velocity); + BulletSimAPI.SetObjectVelocity(Scene.WorldID, _localID, _velocity); }); } } @@ -327,10 +324,10 @@ public class BSCharacter : BSPhysObject set { _orientation = value; // m_log.DebugFormat("{0}: set orientation to {1}", LogHeader, _orientation); - _scene.TaintedObject("BSCharacter.setOrientation", delegate() + Scene.TaintedObject("BSCharacter.setOrientation", delegate() { - // _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID); - BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation); + // _position = BulletSimAPI.GetObjectPosition(Scene.WorldID, _localID); + BulletSimAPI.SetObjectTranslation(Scene.WorldID, _localID, _position, _orientation); }); } } @@ -367,11 +364,11 @@ public class BSCharacter : BSPhysObject set { _throttleUpdates = value; } } public override bool IsColliding { - get { return (_collidingStep == _scene.SimulationStep); } + get { return (_collidingStep == Scene.SimulationStep); } set { _isColliding = value; } } public override bool CollidingGround { - get { return (_collidingGroundStep == _scene.SimulationStep); } + get { return (_collidingGroundStep == Scene.SimulationStep); } set { _collidingGround = value; } } public override bool CollidingObj { @@ -393,10 +390,10 @@ public class BSCharacter : BSPhysObject public override float Buoyancy { get { return _buoyancy; } set { _buoyancy = value; - _scene.TaintedObject("BSCharacter.setBuoyancy", delegate() + Scene.TaintedObject("BSCharacter.setBuoyancy", delegate() { DetailLog("{0},BSCharacter.setBuoyancy,taint,buoy={1}", LocalID, _buoyancy); - BulletSimAPI.SetObjectBuoyancy(_scene.WorldID, LocalID, _buoyancy); + BulletSimAPI.SetObjectBuoyancy(Scene.WorldID, LocalID, _buoyancy); }); } } @@ -440,7 +437,7 @@ public class BSCharacter : BSPhysObject _force.Y += force.Y; _force.Z += force.Z; // m_log.DebugFormat("{0}: AddForce. adding={1}, newForce={2}", LogHeader, force, _force); - _scene.TaintedObject("BSCharacter.AddForce", delegate() + Scene.TaintedObject("BSCharacter.AddForce", delegate() { DetailLog("{0},BSCharacter.setAddForce,taint,addedForce={1}", LocalID, _force); BulletSimAPI.AddObjectForce2(Body.Ptr, _force); @@ -524,10 +521,9 @@ public class BSCharacter : BSPhysObject // Do some sanity checking for the avatar. Make sure it's above ground and inbounds. PositionSanityCheck2(); - float heightHere = Scene.TerrainManager.GetTerrainHeightAtXYZ(_position); // just for debug + float heightHere = Scene.TerrainManager.GetTerrainHeightAtXYZ(_position); // only for debug DetailLog("{0},BSCharacter.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5},terrain={6}", - LocalID, entprop.Position, entprop.Rotation, entprop.Velocity, - entprop.Acceleration, entprop.RotationalVelocity, heightHere); + LocalID, _position, _orientation, _velocity, _acceleration, _rotationalVelocity, heightHere); } // Called by the scene when a collision with this object is reported @@ -539,16 +535,16 @@ public class BSCharacter : BSPhysObject // m_log.DebugFormat("{0}: Collide: ms={1}, id={2}, with={3}", LogHeader, _subscribedEventsMs, LocalID, collidingWith); // The following makes IsColliding() and IsCollidingGround() work - _collidingStep = _scene.SimulationStep; + _collidingStep = Scene.SimulationStep; if (collidingWith == BSScene.TERRAIN_ID || collidingWith == BSScene.GROUNDPLANE_ID) { - _collidingGroundStep = _scene.SimulationStep; + _collidingGroundStep = Scene.SimulationStep; } // DetailLog("{0},BSCharacter.Collison,call,with={1}", LocalID, collidingWith); // throttle collisions to the rate specified in the subscription if (_subscribedEventsMs != 0) { - int nowTime = _scene.SimulationNowTime; + int nowTime = Scene.SimulationNowTime; if (nowTime >= _nextCollisionOkTime) { _nextCollisionOkTime = nowTime + _subscribedEventsMs; diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs index 7b4802e..2f55ba4 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs @@ -232,15 +232,15 @@ public class BSScene : PhysicsScene, IPhysicsParameters } // If Debug logging level, enable logging from the unmanaged code + m_DebugLogCallbackHandle = null; if (m_log.IsDebugEnabled || PhysicsLogging.Enabled) { m_log.DebugFormat("{0}: Initialize: Setting debug callback for unmanaged code", LogHeader); if (PhysicsLogging.Enabled) + // The handle is saved in a variable to make sure it doesn't get freed after this call m_DebugLogCallbackHandle = new BulletSimAPI.DebugLogCallback(BulletLoggerPhysLog); else m_DebugLogCallbackHandle = new BulletSimAPI.DebugLogCallback(BulletLogger); - // The handle is saved in a variable to make sure it doesn't get freed after this call - BulletSimAPI.SetDebugLogCallback(m_DebugLogCallbackHandle); } // Get the version of the DLL @@ -257,7 +257,8 @@ public class BSScene : PhysicsScene, IPhysicsParameters // m_log.DebugFormat("{0}: Initialize: Calling BulletSimAPI.Initialize.", LogHeader); WorldID = BulletSimAPI.Initialize(worldExtent, m_paramsHandle.AddrOfPinnedObject(), m_maxCollisionsPerFrame, m_collisionArrayPinnedHandle.AddrOfPinnedObject(), - m_maxUpdatesPerFrame, m_updateArrayPinnedHandle.AddrOfPinnedObject()); + m_maxUpdatesPerFrame, m_updateArrayPinnedHandle.AddrOfPinnedObject(), + m_DebugLogCallbackHandle); // Initialization to support the transition to a new API which puts most of the logic // into the C# code so it is easier to modify and add to. @@ -265,8 +266,6 @@ public class BSScene : PhysicsScene, IPhysicsParameters Constraints = new BSConstraintCollection(World); - // Note: choose one of the two following lines - // BulletSimAPI.CreateInitialGroundPlaneAndTerrain(WorldID); TerrainManager = new BSTerrainManager(this); TerrainManager.CreateInitialGroundPlaneAndTerrain(); @@ -378,7 +377,9 @@ public class BSScene : PhysicsScene, IPhysicsParameters BSCharacter actor = new BSCharacter(localID, avName, this, position, size, isFlying); lock (PhysObjects) PhysObjects.Add(localID, actor); - // Remove kludge someday + // TODO: Remove kludge someday. + // We must generate a collision for avatars whether they collide or not. + // This is required by OpenSim to update avatar animations, etc. lock (m_avatarsWithCollisions) m_avatarsWithCollisions.Add(actor); return actor; diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs index 28c1940..733d9c2 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs @@ -44,8 +44,22 @@ public class BSTerrainManager { static string LogHeader = "[BULLETSIM TERRAIN MANAGER]"; + // These height values are fractional so the odd values will be + // noticable when debugging. + public const float HEIGHT_INITIALIZATION = 24.987f; + public const float HEIGHT_INITIAL_LASTHEIGHT = 24.876f; + public const float HEIGHT_GETHEIGHT_RET = 24.765f; + + // If the min and max height are equal, we reduce the min by this + // amount to make sure that a bounding box is built for the terrain. + public const float HEIGHT_EQUAL_FUDGE = 0.2f; + + public const float TERRAIN_COLLISION_MARGIN = 0.2f; + + // The scene that I am part of BSScene m_physicsScene; + // The ground plane created to keep thing from falling to infinity. private BulletBody m_groundPlane; // If doing mega-regions, if we're region zero we will be managing multiple @@ -53,6 +67,10 @@ public class BSTerrainManager private Dictionary m_terrains; private Dictionary m_heightMaps; + // True of the terrain has been modified. + // Used to force recalculation of terrain height after terrain has been modified + private bool m_terrainModified; + // If we are doing mega-regions, terrains are added from TERRAIN_ID to m_terrainCount. // This is incremented before assigning to new region so it is the last ID allocated. private uint m_terrainCount = BSScene.CHILDTERRAIN_ID - 1; @@ -69,6 +87,7 @@ public class BSTerrainManager m_physicsScene = physicsScene; m_terrains = new Dictionary(); m_heightMaps = new Dictionary(); + m_terrainModified = false; } // Create the initial instance of terrain and the underlying ground plane. @@ -80,17 +99,18 @@ public class BSTerrainManager public void CreateInitialGroundPlaneAndTerrain() { // The ground plane is here to catch things that are trying to drop to negative infinity + BulletShape groundPlaneShape = new BulletShape(BulletSimAPI.CreateGroundPlaneShape2(BSScene.GROUNDPLANE_ID, 1f, TERRAIN_COLLISION_MARGIN)); m_groundPlane = new BulletBody(BSScene.GROUNDPLANE_ID, - BulletSimAPI.CreateGroundPlaneBody2(BSScene.GROUNDPLANE_ID, 1f, 0.4f)); + BulletSimAPI.CreateBodyWithDefaultMotionState2(groundPlaneShape.Ptr, Vector3.Zero, Quaternion.Identity)); BulletSimAPI.AddObjectToWorld2(m_physicsScene.World.Ptr, m_groundPlane.Ptr); - Vector3 minTerrainCoords = new Vector3(0f, 0f, 24f); - Vector3 maxTerrainCoords = new Vector3(Constants.RegionSize, Constants.RegionSize, 25f); + Vector3 minTerrainCoords = new Vector3(0f, 0f, HEIGHT_INITIALIZATION - HEIGHT_EQUAL_FUDGE); + Vector3 maxTerrainCoords = new Vector3(Constants.RegionSize, Constants.RegionSize, HEIGHT_INITIALIZATION); int totalHeights = (int)maxTerrainCoords.X * (int)maxTerrainCoords.Y; float[] initialMap = new float[totalHeights]; for (int ii = 0; ii < totalHeights; ii++) { - initialMap[ii] = 25f; + initialMap[ii] = HEIGHT_INITIALIZATION; } CreateNewTerrainSegment(BSScene.TERRAIN_ID, initialMap, minTerrainCoords, maxTerrainCoords); } @@ -108,7 +128,7 @@ public class BSTerrainManager if (BulletSimAPI.RemoveObjectFromWorld2(m_physicsScene.World.Ptr, kvp.Value.Ptr)) { BulletSimAPI.DestroyObject2(m_physicsScene.World.Ptr, kvp.Value.Ptr); - BulletSimAPI.ReleaseHeightmapInfo2(m_heightMaps[kvp.Key].Ptr); + BulletSimAPI.ReleaseHeightMapInfo2(m_heightMaps[kvp.Key].Ptr); } } m_terrains.Clear(); @@ -128,30 +148,41 @@ public class BSTerrainManager int hSize = heightMap.Length; for (int ii = 0; ii < hSize; ii++) { - minZ = heightMap[ii] < minZ ? heightMap[ii] : minZ; - maxZ = heightMap[ii] > maxZ ? heightMap[ii] : maxZ; + float height = heightMap[ii]; + if (height < minZ) minZ = height; + if (height > maxZ) maxZ = height; } + // If the terrain is flat, make a difference so we get a bounding box + if (minZ == maxZ) + minZ -= HEIGHT_EQUAL_FUDGE; + minCoords.Z = minZ; maxCoords.Z = maxZ; - // If the terrain is flat, make a difference so we get a good bounding box - if (minZ == maxZ) - minZ -= 0.2f; Vector2 terrainRegionBase = new Vector2(minCoords.X, minCoords.Y); // Create the heightmap data structure in the unmanaged space - BulletHeightMapInfo mapInfo = new BulletHeightMapInfo( - BulletSimAPI.CreateHeightmap2(minCoords, maxCoords, heightMap), heightMap); + BulletHeightMapInfo mapInfo = new BulletHeightMapInfo(id, heightMap, + BulletSimAPI.CreateHeightMapInfo2(id, minCoords, maxCoords, heightMap, TERRAIN_COLLISION_MARGIN)); mapInfo.terrainRegionBase = terrainRegionBase; - mapInfo.maxRegionExtent = maxCoords; + mapInfo.minCoords = minCoords; + mapInfo.maxCoords = maxCoords; mapInfo.minZ = minZ; mapInfo.maxZ = maxZ; mapInfo.sizeX = maxCoords.X - minCoords.X; mapInfo.sizeY = maxCoords.Y - minCoords.Y; + Vector3 centerPos; + centerPos.X = minCoords.X + (mapInfo.sizeX / 2f); + centerPos.Y = minCoords.Y + (mapInfo.sizeY / 2f); + centerPos.Z = minZ + (maxZ - minZ) / 2f; + DetailLog("{0},BSScene.CreateNewTerrainSegment,call,minZ={1},maxZ={2},hMapPtr={3},minC={4},maxC={5}", BSScene.DetailLogZero, minZ, maxZ, mapInfo.Ptr, minCoords, maxCoords); - // Create the terrain body from that heightmap - BulletBody terrainBody = new BulletBody(id, BulletSimAPI.CreateTerrainBody2(id, mapInfo.Ptr, 0.01f)); + // Create the terrain shape from the mapInfo + BulletShape terrainShape = new BulletShape(BulletSimAPI.CreateTerrainShape2(mapInfo.Ptr)); + + BulletBody terrainBody = new BulletBody(id, BulletSimAPI.CreateBodyWithDefaultMotionState2(terrainShape.Ptr, + centerPos, Quaternion.Identity)); BulletSimAPI.SetFriction2(terrainBody.Ptr, m_physicsScene.Params.terrainFriction); BulletSimAPI.SetHitFraction2(terrainBody.Ptr, m_physicsScene.Params.terrainHitFraction); @@ -163,11 +194,12 @@ public class BSTerrainManager BulletSimAPI.AddObjectToWorld2(m_physicsScene.World.Ptr, terrainBody.Ptr); BulletSimAPI.UpdateSingleAabb2(m_physicsScene.World.Ptr, terrainBody.Ptr); - // Add the created terrain to the management set. If we are doing mega-regions, // the terrains of our children will be added. m_terrains.Add(terrainRegionBase, terrainBody); m_heightMaps.Add(terrainRegionBase, mapInfo); + + m_terrainModified = true; } public void SetTerrain(float[] heightMap) { @@ -191,34 +223,57 @@ public class BSTerrainManager { float minZ = float.MaxValue; float maxZ = float.MinValue; + Vector2 terrainRegionBase = new Vector2(tOffset.X, tOffset.Y); - // Copy heightMap local and compute some statistics. - // Not really sure if we need to do this deep copy but, given - // the magic that happens to make the closure for taint - // below, I don't want there to be any problem with sharing - // locations of there are multiple calls to this routine - // within one tick. int heightMapSize = heightMap.Length; - float[] localHeightMap = new float[heightMapSize]; for (int ii = 0; ii < heightMapSize; ii++) { float height = heightMap[ii]; if (height < minZ) minZ = height; if (height > maxZ) maxZ = height; - localHeightMap[ii] = height; } - Vector2 terrainRegionBase = new Vector2(tOffset.X, tOffset.Y); + // The shape of the terrain is from its base to its extents. + Vector3 minCoords, maxCoords; + minCoords = tOffset; + minCoords.Z = minZ; + maxCoords = tOffset; + maxCoords.X += Constants.RegionSize; + maxCoords.Y += Constants.RegionSize; + maxCoords.Z = maxZ; + + BulletBody terrainBody; BulletHeightMapInfo mapInfo; if (m_heightMaps.TryGetValue(terrainRegionBase, out mapInfo)) { + terrainBody = m_terrains[terrainRegionBase]; + // Copy heightMap local and compute some statistics. + for (int ii = 0; ii < heightMapSize; ii++) + { + mapInfo.heightMap[ii] = heightMap[ii]; + } + // If this is terrain we know about, it's easy to update - mapInfo.heightMap = localHeightMap; m_physicsScene.TaintedObject("BSScene.SetTerrain:UpdateExisting", delegate() { DetailLog("{0},SetTerrain:UpdateExisting,baseX={1},baseY={2},minZ={3},maxZ={4}", BSScene.DetailLogZero, tOffset.X, tOffset.Y, minZ, maxZ); - BulletSimAPI.UpdateHeightMap2(m_physicsScene.World.Ptr, mapInfo.Ptr, mapInfo.heightMap); + // Fill the existing height map info with the new location and size information + BulletSimAPI.FillHeightMapInfo2(mapInfo.Ptr, mapInfo.ID, minCoords, maxCoords, mapInfo.heightMap, TERRAIN_COLLISION_MARGIN); + + // Create a terrain shape based on the new info + BulletShape terrainShape = new BulletShape(BulletSimAPI.CreateTerrainShape2(mapInfo.Ptr)); + + // Swap the shape in the terrain body (this also deletes the old shape) + bool success = BulletSimAPI.ReplaceBodyShape2(m_physicsScene.World.Ptr, terrainBody.Ptr, terrainShape.Ptr); + + if (!success) + { + DetailLog("{0},SetTerrain:UpdateExisting,Failed", BSScene.DetailLogZero); + m_physicsScene.Logger.ErrorFormat("{0} Failed updating terrain heightmap. Region={1}", + LogHeader, m_physicsScene.RegionName); + + } }); } else @@ -226,11 +281,6 @@ public class BSTerrainManager // Our mega-prim child is giving us a new terrain to add to the phys world uint newTerrainID = ++m_terrainCount; - Vector3 minCoords = tOffset; - minCoords.Z = minZ; - Vector3 maxCoords = new Vector3(tOffset.X + Constants.RegionSize, - tOffset.Y + Constants.RegionSize, - maxZ); m_physicsScene.TaintedObject("BSScene.SetTerrain:NewTerrain", delegate() { DetailLog("{0},SetTerrain:NewTerrain,baseX={1},baseY={2}", BSScene.DetailLogZero, tOffset.X, tOffset.Y); @@ -240,9 +290,9 @@ public class BSTerrainManager } // Someday we will have complex terrain with caves and tunnels - // For the moment, it's flat and convex public float GetTerrainHeightAtXYZ(Vector3 loc) { + // For the moment, it's flat and convex return GetTerrainHeightAtXY(loc.X, loc.Y); } @@ -252,9 +302,19 @@ public class BSTerrainManager // the same size and that is the default. // Once the heightMapInfo is found, we have all the information to // compute the offset into the array. + private float lastHeightTX = 999999f; + private float lastHeightTY = 999999f; + private float lastHeight = HEIGHT_INITIAL_LASTHEIGHT; public float GetTerrainHeightAtXY(float tX, float tY) { - float ret = 30f; + // You'd be surprized at the number of times this routine is called + // with the same parameters as last time. + if (!m_terrainModified && lastHeightTX == tX && lastHeightTY == tY) + return lastHeight; + + lastHeightTX = tX; + lastHeightTY = tY; + float ret = HEIGHT_GETHEIGHT_RET; int offsetX = ((int)(tX / (int)Constants.RegionSize)) * (int)Constants.RegionSize; int offsetY = ((int)(tY / (int)Constants.RegionSize)) * (int)Constants.RegionSize; @@ -265,15 +325,20 @@ public class BSTerrainManager { float regionX = tX - offsetX; float regionY = tY - offsetY; - regionX = regionX > mapInfo.sizeX ? 0 : regionX; - regionY = regionY > mapInfo.sizeY ? 0 : regionY; - ret = mapInfo.heightMap[(int)(regionX * mapInfo.sizeX + regionY)]; + if (regionX > mapInfo.sizeX) regionX = 0; + if (regionY > mapInfo.sizeY) regionY = 0; + int mapIndex = (int)regionY * (int)mapInfo.sizeY + (int)regionX; + ret = mapInfo.heightMap[mapIndex]; + m_terrainModified = false; + DetailLog("{0},BSTerrainManager.GetTerrainHeightAtXY,bX={1},baseY={2},szX={3},szY={4},regX={5},regY={6},index={7},ht={8}", + BSScene.DetailLogZero, offsetX, offsetY, mapInfo.sizeX, mapInfo.sizeY, regionX, regionY, mapIndex, ret); } else { m_physicsScene.Logger.ErrorFormat("{0} GetTerrainHeightAtXY: terrain not found: x={1}, y={2}", LogHeader, tX, tY); } + lastHeight = ret; return ret; } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs index 3b319fb..804d2ea 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs @@ -38,13 +38,19 @@ namespace OpenSim.Region.Physics.BulletSPlugin { // The physics engine controller class created at initialization public struct BulletSim { - public BulletSim(uint id, BSScene bss, IntPtr xx) { ID = id; scene = bss; Ptr = xx; } - public uint ID; + public BulletSim(uint worldId, BSScene bss, IntPtr xx) { worldID = worldId; scene = bss; Ptr = xx; } + public uint worldID; // The scene is only in here so very low level routines have a handle to print debug/error messages public BSScene scene; public IntPtr Ptr; } +public struct BulletShape +{ + public BulletShape(IntPtr xx) { Ptr = xx; } + public IntPtr Ptr; +} + // An allocated Bullet btRigidBody public struct BulletBody { @@ -66,18 +72,22 @@ public struct BulletConstraint // than making copies. public class BulletHeightMapInfo { - public BulletHeightMapInfo(IntPtr xx, float[] hm) { + public BulletHeightMapInfo(uint id, float[] hm, IntPtr xx) { + ID = id; Ptr = xx; heightMap = hm; terrainRegionBase = new Vector2(0f, 0f); - maxRegionExtent = new Vector3(100f, 100f, 25f); + minCoords = new Vector3(100f, 100f, 25f); + maxCoords = new Vector3(101f, 101f, 26f); minZ = maxZ = 0f; sizeX = sizeY = 256f; } + public uint ID; public IntPtr Ptr; public float[] heightMap; public Vector2 terrainRegionBase; - public Vector3 maxRegionExtent; + public Vector3 minCoords; + public Vector3 maxCoords; public float sizeX, sizeY; public float minZ, maxZ; } @@ -248,6 +258,10 @@ public enum ConstraintParamAxis : int // =============================================================================== static class BulletSimAPI { +// Link back to the managed code for outputting log messages +[UnmanagedFunctionPointer(CallingConvention.Cdecl)] +public delegate void DebugLogCallback([MarshalAs(UnmanagedType.LPStr)]string msg); + [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] [return: MarshalAs(UnmanagedType.LPStr)] public static extern string GetVersion(); @@ -255,7 +269,8 @@ public static extern string GetVersion(); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern uint Initialize(Vector3 maxPosition, IntPtr parms, int maxCollisions, IntPtr collisionArray, - int maxUpdates, IntPtr updateArray); + int maxUpdates, IntPtr updateArray, + DebugLogCallback logRoutine); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern void CreateInitialGroundPlaneAndTerrain(uint worldID); @@ -372,8 +387,6 @@ public static extern Vector3 RecoverFromPenetration(uint worldID, uint id); public static extern void DumpBulletStatistics(); // Log a debug message -[UnmanagedFunctionPointer(CallingConvention.Cdecl)] -public delegate void DebugLogCallback([MarshalAs(UnmanagedType.LPStr)]string msg); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern void SetDebugLogCallback(DebugLogCallback callback); @@ -407,7 +420,7 @@ public static extern IntPtr Initialize2(Vector3 maxPosition, IntPtr parms, public static extern bool UpdateParameter2(IntPtr world, uint localID, String parm, float value); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void SetHeightmap2(IntPtr world, float[] heightmap); +public static extern void SetHeightMap2(IntPtr world, float[] heightmap); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern void Shutdown2(IntPtr sim); @@ -442,25 +455,31 @@ public static extern IntPtr BuildNativeShape2(IntPtr world, [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern bool DeleteCollisionShape2(IntPtr world, IntPtr shape); +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern IntPtr CreateBodyFromShape2(IntPtr sim, IntPtr shape, Vector3 pos, Quaternion rot); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern IntPtr CreateBodyWithDefaultMotionState2(IntPtr shape, Vector3 pos, Quaternion rot); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern bool ReplaceBodyShape2(IntPtr sim, IntPtr obj, IntPtr shape); // ===================================================================================== [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern IntPtr CreateGroundPlaneBody2(uint id, float height, float collisionMargin); +public static extern IntPtr CreateHeightMapInfo2(uint id, Vector3 minCoords, Vector3 maxCoords, + [MarshalAs(UnmanagedType.LPArray)] float[] heightMap, float collisionMargin); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern IntPtr CreateTerrainBody2(uint id, - IntPtr heightMapInfo, - float collisionMargin); +public static extern IntPtr FillHeightMapInfo2(IntPtr mapInfo, uint id, Vector3 minCoords, Vector3 maxCoords, + [MarshalAs(UnmanagedType.LPArray)] float[] heightMap, float collisionMargin); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern IntPtr CreateHeightmap2(Vector3 minCoords, Vector3 maxCoords, - [MarshalAs(UnmanagedType.LPArray)] float[] heightMap); +public static extern bool ReleaseHeightMapInfo2(IntPtr heightMapInfo); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern bool ReleaseHeightmapInfo2(IntPtr heightMapInfo); +public static extern IntPtr CreateGroundPlaneShape2(uint id, float height, float collisionMargin); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void UpdateHeightMap2(IntPtr world, IntPtr heightMapInfo, - [MarshalAs(UnmanagedType.LPArray)] float[] heightMap); +public static extern IntPtr CreateTerrainShape2(IntPtr mapInfo); // ===================================================================================== [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -- cgit v1.1 From ffdc7987207de279116a077e2042ed3a1f381a5f Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Fri, 31 Aug 2012 11:33:36 -0700 Subject: BulletSim: Update BulletSimAPI to match the DLL interface. Major rework of terrain management which finally makes mega-regions work. Update heightmap of terrain by rebuilding the terrain's body and shape. There is a problem with just replacing the shape so this workaround will do for the moment but it will need to be resolved for mesh and hull switching. --- .../Region/Physics/BulletSPlugin/BSCharacter.cs | 2 +- OpenSim/Region/Physics/BulletSPlugin/BSScene.cs | 2 +- .../Physics/BulletSPlugin/BSTerrainManager.cs | 356 +++++++++++++-------- .../Region/Physics/BulletSPlugin/BulletSimAPI.cs | 8 +- 4 files changed, 231 insertions(+), 137 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs index fa21233..747ae71 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs @@ -228,7 +228,7 @@ public class BSCharacter : BSPhysObject float terrainHeight = Scene.TerrainManager.GetTerrainHeightAtXYZ(_position); if (Position.Z < terrainHeight) { - DetailLog("{0},BSCharacter.PositionAdjustUnderGround,call,pos={1},terrain={2}", LocalID, _position, terrainHeight); + DetailLog("{0},BSCharacter.PositionAdjustUnderGround,call,pos={1},terrain={2}", LocalID, _position, terrainHeight); _position.Z = terrainHeight + 2.0f; ret = true; } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs index 2f55ba4..4a468af 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs @@ -1070,7 +1070,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters (s) => { return s.m_params[0].terrainRestitution; }, (s,p,l,v) => { s.m_params[0].terrainRestitution = v; s.TaintedUpdateParameter(p,l,v); } ), new ParameterDefn("AvatarFriction", "Factor to reduce movement against an avatar. Changed on avatar recreation.", - 0.5f, + 0.2f, (s,cf,p,v) => { s.m_params[0].avatarFriction = cf.GetFloat(p, v); }, (s) => { return s.m_params[0].avatarFriction; }, (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarFriction, p, l, v); } ), diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs index 733d9c2..ab45f8f 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs @@ -54,17 +54,19 @@ public class BSTerrainManager // amount to make sure that a bounding box is built for the terrain. public const float HEIGHT_EQUAL_FUDGE = 0.2f; - public const float TERRAIN_COLLISION_MARGIN = 0.2f; + public const float TERRAIN_COLLISION_MARGIN = 0.0f; + + // Until the whole simulator is changed to pass us the region size, we rely on constants. + public Vector3 DefaultRegionSize = new Vector3(Constants.RegionSize, Constants.RegionSize, 0f); // The scene that I am part of - BSScene m_physicsScene; + private BSScene m_physicsScene; // The ground plane created to keep thing from falling to infinity. private BulletBody m_groundPlane; // If doing mega-regions, if we're region zero we will be managing multiple // region terrains since region zero does the physics for the whole mega-region. - private Dictionary m_terrains; private Dictionary m_heightMaps; // True of the terrain has been modified. @@ -78,16 +80,22 @@ public class BSTerrainManager // If doing mega-regions, this holds our offset from region zero of // the mega-regions. "parentScene" points to the PhysicsScene of region zero. - private Vector3 m_worldOffset = Vector3.Zero; - public Vector2 WorldExtents = new Vector2((int)Constants.RegionSize, (int)Constants.RegionSize); - private PhysicsScene m_parentScene = null; + private Vector3 m_worldOffset; + // If the parent region (region 0), this is the extent of the combined regions + // relative to the origin of region zero + private Vector3 m_worldMax; + private PhysicsScene m_parentScene; public BSTerrainManager(BSScene physicsScene) { m_physicsScene = physicsScene; - m_terrains = new Dictionary(); m_heightMaps = new Dictionary(); m_terrainModified = false; + + // Assume one region of default size + m_worldOffset = Vector3.Zero; + m_worldMax = new Vector3(DefaultRegionSize.X, DefaultRegionSize.Y, 4096f); + m_parentScene = null; } // Create the initial instance of terrain and the underlying ground plane. @@ -95,7 +103,7 @@ public class BSTerrainManager // by the managed code. // The terrains and the groundPlane are not added to the list of PhysObjects. // This is called from the initialization routine so we presume it is - // safe to call Bullet in real time. We hope no one is moving around prim yet. + // safe to call Bullet in real time. We hope no one is moving prims around yet. public void CreateInitialGroundPlaneAndTerrain() { // The ground plane is here to catch things that are trying to drop to negative infinity @@ -105,125 +113,91 @@ public class BSTerrainManager BulletSimAPI.AddObjectToWorld2(m_physicsScene.World.Ptr, m_groundPlane.Ptr); Vector3 minTerrainCoords = new Vector3(0f, 0f, HEIGHT_INITIALIZATION - HEIGHT_EQUAL_FUDGE); - Vector3 maxTerrainCoords = new Vector3(Constants.RegionSize, Constants.RegionSize, HEIGHT_INITIALIZATION); + Vector3 maxTerrainCoords = new Vector3(DefaultRegionSize.X, DefaultRegionSize.Y, HEIGHT_INITIALIZATION); int totalHeights = (int)maxTerrainCoords.X * (int)maxTerrainCoords.Y; float[] initialMap = new float[totalHeights]; for (int ii = 0; ii < totalHeights; ii++) { initialMap[ii] = HEIGHT_INITIALIZATION; } - CreateNewTerrainSegment(BSScene.TERRAIN_ID, initialMap, minTerrainCoords, maxTerrainCoords); + UpdateOrCreateTerrain(BSScene.TERRAIN_ID, initialMap, minTerrainCoords, maxTerrainCoords, true); } + // Release all the terrain structures we might have allocated public void ReleaseGroundPlaneAndTerrain() { - if (BulletSimAPI.RemoveObjectFromWorld2(m_physicsScene.World.Ptr, m_groundPlane.Ptr)) + if (m_groundPlane.Ptr != IntPtr.Zero) { - BulletSimAPI.DestroyObject2(m_physicsScene.World.Ptr, m_groundPlane.Ptr); - } - m_groundPlane.Ptr = IntPtr.Zero; - - foreach (KeyValuePair kvp in m_terrains) - { - if (BulletSimAPI.RemoveObjectFromWorld2(m_physicsScene.World.Ptr, kvp.Value.Ptr)) + if (BulletSimAPI.RemoveObjectFromWorld2(m_physicsScene.World.Ptr, m_groundPlane.Ptr)) { - BulletSimAPI.DestroyObject2(m_physicsScene.World.Ptr, kvp.Value.Ptr); - BulletSimAPI.ReleaseHeightMapInfo2(m_heightMaps[kvp.Key].Ptr); + BulletSimAPI.DestroyObject2(m_physicsScene.World.Ptr, m_groundPlane.Ptr); } + m_groundPlane.Ptr = IntPtr.Zero; } - m_terrains.Clear(); - m_heightMaps.Clear(); + + ReleaseTerrain(); } - // Create a new terrain description. This is used for mega-regions where - // the children of region zero give region zero all of the terrain - // segments since region zero does all the physics for the mega-region. - // Call at taint time!! - public void CreateNewTerrainSegment(uint id, float[] heightMap, Vector3 minCoords, Vector3 maxCoords) + // Release all the terrain we have allocated + public void ReleaseTerrain() { - // The Z coordinates are recalculated to be the min and max height of the terrain - // itself. The caller may have passed us the real region extent. - float minZ = float.MaxValue; - float maxZ = float.MinValue; - int hSize = heightMap.Length; - for (int ii = 0; ii < hSize; ii++) + foreach (KeyValuePair kvp in m_heightMaps) { - float height = heightMap[ii]; - if (height < minZ) minZ = height; - if (height > maxZ) maxZ = height; + if (BulletSimAPI.RemoveObjectFromWorld2(m_physicsScene.World.Ptr, kvp.Value.terrainBody.Ptr)) + { + BulletSimAPI.DestroyObject2(m_physicsScene.World.Ptr, kvp.Value.terrainBody.Ptr); + BulletSimAPI.ReleaseHeightMapInfo2(kvp.Value.Ptr); + } } - // If the terrain is flat, make a difference so we get a bounding box - if (minZ == maxZ) - minZ -= HEIGHT_EQUAL_FUDGE; - - minCoords.Z = minZ; - maxCoords.Z = maxZ; - Vector2 terrainRegionBase = new Vector2(minCoords.X, minCoords.Y); - - // Create the heightmap data structure in the unmanaged space - BulletHeightMapInfo mapInfo = new BulletHeightMapInfo(id, heightMap, - BulletSimAPI.CreateHeightMapInfo2(id, minCoords, maxCoords, heightMap, TERRAIN_COLLISION_MARGIN)); - mapInfo.terrainRegionBase = terrainRegionBase; - mapInfo.minCoords = minCoords; - mapInfo.maxCoords = maxCoords; - mapInfo.minZ = minZ; - mapInfo.maxZ = maxZ; - mapInfo.sizeX = maxCoords.X - minCoords.X; - mapInfo.sizeY = maxCoords.Y - minCoords.Y; - - Vector3 centerPos; - centerPos.X = minCoords.X + (mapInfo.sizeX / 2f); - centerPos.Y = minCoords.Y + (mapInfo.sizeY / 2f); - centerPos.Z = minZ + (maxZ - minZ) / 2f; - - DetailLog("{0},BSScene.CreateNewTerrainSegment,call,minZ={1},maxZ={2},hMapPtr={3},minC={4},maxC={5}", - BSScene.DetailLogZero, minZ, maxZ, mapInfo.Ptr, minCoords, maxCoords); - // Create the terrain shape from the mapInfo - BulletShape terrainShape = new BulletShape(BulletSimAPI.CreateTerrainShape2(mapInfo.Ptr)); - - BulletBody terrainBody = new BulletBody(id, BulletSimAPI.CreateBodyWithDefaultMotionState2(terrainShape.Ptr, - centerPos, Quaternion.Identity)); - - BulletSimAPI.SetFriction2(terrainBody.Ptr, m_physicsScene.Params.terrainFriction); - BulletSimAPI.SetHitFraction2(terrainBody.Ptr, m_physicsScene.Params.terrainHitFraction); - BulletSimAPI.SetRestitution2(terrainBody.Ptr, m_physicsScene.Params.terrainRestitution); - BulletSimAPI.SetCollisionFlags2(terrainBody.Ptr, CollisionFlags.CF_STATIC_OBJECT); - BulletSimAPI.Activate2(terrainBody.Ptr, true); - - // Add the new terrain to the dynamics world - BulletSimAPI.AddObjectToWorld2(m_physicsScene.World.Ptr, terrainBody.Ptr); - BulletSimAPI.UpdateSingleAabb2(m_physicsScene.World.Ptr, terrainBody.Ptr); - - // Add the created terrain to the management set. If we are doing mega-regions, - // the terrains of our children will be added. - m_terrains.Add(terrainRegionBase, terrainBody); - m_heightMaps.Add(terrainRegionBase, mapInfo); - - m_terrainModified = true; + m_heightMaps.Clear(); } + // The simulator wants to set a new heightmap for the terrain. public void SetTerrain(float[] heightMap) { if (m_worldOffset != Vector3.Zero && m_parentScene != null) { + // If a child of a mega-region, we shouldn't have any terrain allocated for us + ReleaseGroundPlaneAndTerrain(); // If doing the mega-prim stuff and we are the child of the zero region, - // the terrain is really added to our parent + // the terrain is added to our parent if (m_parentScene is BSScene) { - ((BSScene)m_parentScene).TerrainManager.SetTerrain(heightMap, m_worldOffset); + DetailLog("{0},SetTerrain.ToParent,offset={1},worldMax={2}", + BSScene.DetailLogZero, m_worldOffset, m_worldMax); + ((BSScene)m_parentScene).TerrainManager.UpdateOrCreateTerrain(BSScene.CHILDTERRAIN_ID, + heightMap, m_worldOffset, m_worldOffset+DefaultRegionSize, false); } } else { - // if not doing the mega-prim thing, just change the terrain - SetTerrain(heightMap, m_worldOffset); + // If not doing the mega-prim thing, just change the terrain + DetailLog("{0},SetTerrain.Existing", BSScene.DetailLogZero); + + UpdateOrCreateTerrain(BSScene.TERRAIN_ID, heightMap, m_worldOffset, m_worldOffset+DefaultRegionSize, false); } } - private void SetTerrain(float[] heightMap, Vector3 tOffset) + // If called with no mapInfo for the terrain, this will create a new mapInfo and terrain + // based on the passed information. The 'id' should be either the terrain id or + // BSScene.CHILDTERRAIN_ID. If the latter, a new child terrain ID will be allocated and used. + // The latter feature is for creating child terrains for mega-regions. + // If called with a mapInfo in m_heightMaps but the terrain has no body yet (mapInfo.terrainBody.Ptr == 0) + // then a new body and shape is created and the mapInfo is filled. + // This call is used for doing the initial terrain creation. + // If called with a mapInfo in m_heightMaps and there is an existing terrain body, a new + // terrain shape is created and added to the body. + // This call is most often used to update the heightMap and parameters of the terrain. + // The 'doNow' boolean says whether to do all the unmanaged activities right now (like when + // calling this routine from initialization or taint-time routines) or whether to delay + // all the unmanaged activities to taint-time. + private void UpdateOrCreateTerrain(uint id, float[] heightMap, Vector3 minCoords, Vector3 maxCoords, bool doNow) { + DetailLog("{0},BSTerrainManager.UpdateOrCreateTerrain,call,minC={1},maxC={2},doNow={3}", + BSScene.DetailLogZero, minCoords, maxCoords, doNow); + float minZ = float.MaxValue; float maxZ = float.MinValue; - Vector2 terrainRegionBase = new Vector2(tOffset.X, tOffset.Y); + Vector2 terrainRegionBase = new Vector2(minCoords.X, minCoords.Y); int heightMapSize = heightMap.Length; for (int ii = 0; ii < heightMapSize; ii++) @@ -234,58 +208,162 @@ public class BSTerrainManager } // The shape of the terrain is from its base to its extents. - Vector3 minCoords, maxCoords; - minCoords = tOffset; minCoords.Z = minZ; - maxCoords = tOffset; - maxCoords.X += Constants.RegionSize; - maxCoords.Y += Constants.RegionSize; maxCoords.Z = maxZ; - BulletBody terrainBody; BulletHeightMapInfo mapInfo; if (m_heightMaps.TryGetValue(terrainRegionBase, out mapInfo)) { - terrainBody = m_terrains[terrainRegionBase]; - // Copy heightMap local and compute some statistics. - for (int ii = 0; ii < heightMapSize; ii++) - { - mapInfo.heightMap[ii] = heightMap[ii]; - } - // If this is terrain we know about, it's easy to update - m_physicsScene.TaintedObject("BSScene.SetTerrain:UpdateExisting", delegate() + + mapInfo.heightMap = heightMap; + mapInfo.minCoords = minCoords; + mapInfo.maxCoords = maxCoords; + mapInfo.minZ = minZ; + mapInfo.maxZ = maxZ; + mapInfo.sizeX = maxCoords.X - minCoords.X; + mapInfo.sizeY = maxCoords.Y - minCoords.Y; + DetailLog("{0},UpdateOrCreateTerrain:UpdateExisting,call,terrainBase={1},minC={2}, maxC={3}, szX={4}, szY={5}", + BSScene.DetailLogZero, terrainRegionBase, mapInfo.minCoords, mapInfo.maxCoords, mapInfo.sizeX, mapInfo.sizeY); + + BSScene.TaintCallback rebuildOperation = delegate() { - DetailLog("{0},SetTerrain:UpdateExisting,baseX={1},baseY={2},minZ={3},maxZ={4}", - BSScene.DetailLogZero, tOffset.X, tOffset.Y, minZ, maxZ); - // Fill the existing height map info with the new location and size information - BulletSimAPI.FillHeightMapInfo2(mapInfo.Ptr, mapInfo.ID, minCoords, maxCoords, mapInfo.heightMap, TERRAIN_COLLISION_MARGIN); + if (m_parentScene != null) + { + // It's possible that Combine() was called after this code was queued. + // If we are a child of combined regions, we don't create any terrain for us. + DetailLog("{0},UpdateOrCreateTerrain:AmACombineChild,taint", BSScene.DetailLogZero); - // Create a terrain shape based on the new info - BulletShape terrainShape = new BulletShape(BulletSimAPI.CreateTerrainShape2(mapInfo.Ptr)); + // Get rid of any terrain that may have been allocated for us. + ReleaseGroundPlaneAndTerrain(); - // Swap the shape in the terrain body (this also deletes the old shape) - bool success = BulletSimAPI.ReplaceBodyShape2(m_physicsScene.World.Ptr, terrainBody.Ptr, terrainShape.Ptr); + // I hate doing this, but just bail + return; + } - if (!success) + if (mapInfo.terrainBody.Ptr != IntPtr.Zero) { - DetailLog("{0},SetTerrain:UpdateExisting,Failed", BSScene.DetailLogZero); - m_physicsScene.Logger.ErrorFormat("{0} Failed updating terrain heightmap. Region={1}", - LogHeader, m_physicsScene.RegionName); - + // Updating an existing terrain. + DetailLog("{0},UpdateOrCreateTerrain:UpdateExisting,taint,terrainBase={1},minC={2}, maxC={3}, szX={4}, szY={5}", + BSScene.DetailLogZero, terrainRegionBase, mapInfo.minCoords, mapInfo.maxCoords, mapInfo.sizeX, mapInfo.sizeY); + + // Remove from the dynamics world because we're going to mangle this object + BulletSimAPI.RemoveObjectFromWorld2(m_physicsScene.World.Ptr, mapInfo.terrainBody.Ptr); + + // Get rid of the old terrain + BulletSimAPI.DestroyObject2(m_physicsScene.World.Ptr, mapInfo.terrainBody.Ptr); + BulletSimAPI.ReleaseHeightMapInfo2(mapInfo.Ptr); + mapInfo.Ptr = IntPtr.Zero; + + /* + // NOTE: This routine is half here because I can't get the terrain shape replacement + // to work. In the short term, the above three lines completely delete the old + // terrain and the code below recreates one from scratch. + // Hopefully the Bullet community will help me out on this one. + + // First, release the old collision shape (there is only one terrain) + BulletSimAPI.DeleteCollisionShape2(m_physicsScene.World.Ptr, mapInfo.terrainShape.Ptr); + + // Fill the existing height map info with the new location and size information + BulletSimAPI.FillHeightMapInfo2(m_physicsScene.World.Ptr, mapInfo.Ptr, mapInfo.ID, + mapInfo.minCoords, mapInfo.maxCoords, mapInfo.heightMap, TERRAIN_COLLISION_MARGIN); + + // Create a terrain shape based on the new info + mapInfo.terrainShape = new BulletShape(BulletSimAPI.CreateTerrainShape2(mapInfo.Ptr)); + + // Stuff the shape into the existing terrain body + BulletSimAPI.SetBodyShape2(m_physicsScene.World.Ptr, mapInfo.terrainBody.Ptr, mapInfo.terrainShape.Ptr); + */ } - }); + // else + { + // Creating a new terrain. + DetailLog("{0},UpdateOrCreateTerrain:CreateNewTerrain,taint,baseX={1},baseY={2},minZ={3},maxZ={4}", + BSScene.DetailLogZero, mapInfo.minCoords.X, mapInfo.minCoords.Y, minZ, maxZ); + + mapInfo.ID = id; + mapInfo.Ptr = BulletSimAPI.CreateHeightMapInfo2(m_physicsScene.World.Ptr, mapInfo.ID, + mapInfo.minCoords, mapInfo.maxCoords, mapInfo.heightMap, TERRAIN_COLLISION_MARGIN); + + // The terrain object initial position is at the center of the object + Vector3 centerPos; + centerPos.X = minCoords.X + (mapInfo.sizeX / 2f); + centerPos.Y = minCoords.Y + (mapInfo.sizeY / 2f); + centerPos.Z = minZ + ((maxZ - minZ) / 2f); + + // Create the terrain shape from the mapInfo + mapInfo.terrainShape = new BulletShape(BulletSimAPI.CreateTerrainShape2(mapInfo.Ptr)); + + mapInfo.terrainBody = new BulletBody(mapInfo.ID, + BulletSimAPI.CreateBodyWithDefaultMotionState2(mapInfo.terrainShape.Ptr, + centerPos, Quaternion.Identity)); + } + + // Make sure the entry is in the heightmap table + m_heightMaps[terrainRegionBase] = mapInfo; + + // Set current terrain attributes + BulletSimAPI.SetFriction2(mapInfo.terrainBody.Ptr, m_physicsScene.Params.terrainFriction); + BulletSimAPI.SetHitFraction2(mapInfo.terrainBody.Ptr, m_physicsScene.Params.terrainHitFraction); + BulletSimAPI.SetRestitution2(mapInfo.terrainBody.Ptr, m_physicsScene.Params.terrainRestitution); + BulletSimAPI.SetCollisionFlags2(mapInfo.terrainBody.Ptr, CollisionFlags.CF_STATIC_OBJECT); + + BulletSimAPI.SetMassProps2(mapInfo.terrainBody.Ptr, 0f, Vector3.Zero); + BulletSimAPI.UpdateInertiaTensor2(mapInfo.terrainBody.Ptr); + + // Return the new terrain to the world of physical objects + BulletSimAPI.AddObjectToWorld2(m_physicsScene.World.Ptr, mapInfo.terrainBody.Ptr); + + // redo its bounding box now that it is in the world + BulletSimAPI.UpdateSingleAabb2(m_physicsScene.World.Ptr, mapInfo.terrainBody.Ptr); + + // Make sure the new shape is processed. + BulletSimAPI.Activate2(mapInfo.terrainBody.Ptr, true); + }; + + // There is the option to do the changes now (we're already in 'taint time'), or + // to do the Bullet operations later. + if (doNow) + rebuildOperation(); + else + m_physicsScene.TaintedObject("BSScene.UpdateOrCreateTerrain:UpdateExisting", rebuildOperation); } else { - // Our mega-prim child is giving us a new terrain to add to the phys world - uint newTerrainID = ++m_terrainCount; + // We don't know about this terrain so either we are creating a new terrain or + // our mega-prim child is giving us a new terrain to add to the phys world - m_physicsScene.TaintedObject("BSScene.SetTerrain:NewTerrain", delegate() + // if this is a child terrain, calculate a unique terrain id + uint newTerrainID = id; + if (newTerrainID >= BSScene.CHILDTERRAIN_ID) + newTerrainID = ++m_terrainCount; + + float[] heightMapX = heightMap; + Vector3 minCoordsX = minCoords; + Vector3 maxCoordsX = maxCoords; + + DetailLog("{0},UpdateOrCreateTerrain:NewTerrain,call,id={1}, minC={2}, maxC={3}", + BSScene.DetailLogZero, newTerrainID, minCoords, minCoords); + + // Code that must happen at taint-time + BSScene.TaintCallback createOperation = delegate() { - DetailLog("{0},SetTerrain:NewTerrain,baseX={1},baseY={2}", BSScene.DetailLogZero, tOffset.X, tOffset.Y); - CreateNewTerrainSegment(newTerrainID, heightMap, minCoords, maxCoords); - }); + DetailLog("{0},UpdateOrCreateTerrain:NewTerrain,taint,baseX={1},baseY={2}", BSScene.DetailLogZero, minCoords.X, minCoords.Y); + // Create a new mapInfo that will be filled with the new info + mapInfo = new BulletHeightMapInfo(id, heightMapX, + BulletSimAPI.CreateHeightMapInfo2(m_physicsScene.World.Ptr, newTerrainID, + minCoordsX, maxCoordsX, heightMapX, TERRAIN_COLLISION_MARGIN)); + // Put the unfilled heightmap info into the collection of same + m_heightMaps.Add(terrainRegionBase, mapInfo); + // Build the terrain + UpdateOrCreateTerrain(newTerrainID, heightMap, minCoords, maxCoords, true); + }; + + // If already in taint-time, just call Bullet. Otherwise queue the operations for the safe time. + if (doNow) + createOperation(); + else + m_physicsScene.TaintedObject("BSScene.UpdateOrCreateTerrain:NewTerrain", createOperation); } } @@ -316,8 +394,8 @@ public class BSTerrainManager lastHeightTY = tY; float ret = HEIGHT_GETHEIGHT_RET; - int offsetX = ((int)(tX / (int)Constants.RegionSize)) * (int)Constants.RegionSize; - int offsetY = ((int)(tY / (int)Constants.RegionSize)) * (int)Constants.RegionSize; + int offsetX = ((int)(tX / (int)DefaultRegionSize.X)) * (int)DefaultRegionSize.X; + int offsetY = ((int)(tY / (int)DefaultRegionSize.Y)) * (int)DefaultRegionSize.Y; Vector2 terrainBaseXY = new Vector2(offsetX, offsetY); BulletHeightMapInfo mapInfo; @@ -335,8 +413,8 @@ public class BSTerrainManager } else { - m_physicsScene.Logger.ErrorFormat("{0} GetTerrainHeightAtXY: terrain not found: x={1}, y={2}", - LogHeader, tX, tY); + m_physicsScene.Logger.ErrorFormat("{0} GetTerrainHeightAtXY: terrain not found: region={1}, x={2}, y={3}", + LogHeader, m_physicsScene.RegionName, tX, tY); } lastHeight = ret; return ret; @@ -347,20 +425,34 @@ public class BSTerrainManager { return true; } - // This call says I am a child to region zero in a mega-region. 'pScene' is that - // of region zero, 'offset' is my offset from regions zero's origin, and - // 'extents' is the largest XY that is handled in my region. + + // This routine is called two ways: + // One with 'offset' and 'pScene' zero and null but 'extents' giving the maximum + // extent of the combined regions. This is to inform the parent of the size + // of the combined regions. + // and one with 'offset' as the offset of the child region to the base region, + // 'pScene' pointing to the parent and 'extents' of zero. This informs the + // child of its relative base and new parent. public void Combine(PhysicsScene pScene, Vector3 offset, Vector3 extents) { m_worldOffset = offset; - WorldExtents = new Vector2(extents.X, extents.Y); + m_worldMax = extents; m_parentScene = pScene; + if (pScene != null) + { + // We are a child. + // We want m_worldMax to be the highest coordinate of our piece of terrain. + m_worldMax = offset + DefaultRegionSize; + } + DetailLog("{0},BSTerrainManager.Combine,offset={1},extents={2},wOffset={3},wMax={4}", + BSScene.DetailLogZero, offset, extents, m_worldOffset, m_worldMax); } // Unhook all the combining that I know about. public void UnCombine(PhysicsScene pScene) { // Just like ODE, for the moment a NOP + DetailLog("{0},BSTerrainManager.UnCombine", BSScene.DetailLogZero); } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs index 804d2ea..a0bad3a 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs @@ -90,6 +90,8 @@ public class BulletHeightMapInfo public Vector3 maxCoords; public float sizeX, sizeY; public float minZ, maxZ; + public BulletShape terrainShape; + public BulletBody terrainBody; } // =============================================================================== @@ -462,14 +464,14 @@ public static extern IntPtr CreateBodyFromShape2(IntPtr sim, IntPtr shape, Vecto public static extern IntPtr CreateBodyWithDefaultMotionState2(IntPtr shape, Vector3 pos, Quaternion rot); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern bool ReplaceBodyShape2(IntPtr sim, IntPtr obj, IntPtr shape); +public static extern bool SetBodyShape2(IntPtr sim, IntPtr obj, IntPtr shape); // ===================================================================================== [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern IntPtr CreateHeightMapInfo2(uint id, Vector3 minCoords, Vector3 maxCoords, +public static extern IntPtr CreateHeightMapInfo2(IntPtr sim, uint id, Vector3 minCoords, Vector3 maxCoords, [MarshalAs(UnmanagedType.LPArray)] float[] heightMap, float collisionMargin); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern IntPtr FillHeightMapInfo2(IntPtr mapInfo, uint id, Vector3 minCoords, Vector3 maxCoords, +public static extern IntPtr FillHeightMapInfo2(IntPtr sim, IntPtr mapInfo, uint id, Vector3 minCoords, Vector3 maxCoords, [MarshalAs(UnmanagedType.LPArray)] float[] heightMap, float collisionMargin); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -- cgit v1.1 From f7b88d1c40ba06c62491d8d32809fe6c1c4d360d Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Sun, 2 Sep 2012 13:43:16 +0100 Subject: made setting rotation match Second Life --- .../Shared/Api/Implementation/LSL_Api.cs | 33 +--------------------- 1 file changed, 1 insertion(+), 32 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 be22cb4..9f952d1 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -2083,23 +2083,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public void llSetRot(LSL_Rotation rot) { m_host.AddScriptLPS(1); - - // try to let this work as in SL... - if (m_host.ParentID == 0) - { - // special case: If we are root, rotate complete SOG to new rotation SetRot(m_host, rot); - } - else - { - // we are a child. The rotation values will be set to the one of root modified by rot, as in SL. Don't ask. - SceneObjectPart rootPart = m_host.ParentGroup.RootPart; - if (rootPart != null) // better safe than sorry - { - SetRot(m_host, rootPart.RotationOffset * (Quaternion)rot); - } - } - ScriptSleep(200); } @@ -7292,22 +7276,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api break; case (int)ScriptBaseClass.PRIM_ROTATION: + case (int)ScriptBaseClass.PRIM_ROT_LOCAL: if (remain < 1) return null; LSL_Rotation q = rules.GetQuaternionItem(idx++); - // try to let this work as in SL... - if (part.ParentID == 0) - { - // special case: If we are root, rotate complete SOG to new rotation SetRot(part, q); - } - else - { - // we are a child. The rotation values will be set to the one of root modified by rot, as in SL. Don't ask. - SceneObjectPart rootPart = part.ParentGroup.RootPart; - SetRot(part, rootPart.RotationOffset * (Quaternion)q); - } break; @@ -7614,11 +7588,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api string primDesc = rules.GetLSLStringItem(idx++); part.Description = primDesc; break; - case (int)ScriptBaseClass.PRIM_ROT_LOCAL: - if (remain < 1) - return null; - SetRot(part, rules.GetQuaternionItem(idx++)); - break; case (int)ScriptBaseClass.PRIM_OMEGA: if (remain < 3) return null; -- cgit v1.1 From a3d140b57c5e2ae0f3334d59b82e116d40199b49 Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Sun, 2 Sep 2012 13:45:42 +0100 Subject: no need to assign rotation to a variable now --- OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 3 +-- 1 file changed, 1 insertion(+), 2 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 9f952d1..6f4bc8b 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -7280,8 +7280,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (remain < 1) return null; - LSL_Rotation q = rules.GetQuaternionItem(idx++); - SetRot(part, q); + SetRot(part, rules.GetQuaternionItem(idx++)); break; -- cgit v1.1 From fb211c64fd9d335f4879549023870b1e28416f74 Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Sun, 2 Sep 2012 13:47:18 +0100 Subject: formatting --- OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 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 6f4bc8b..1d2ef40 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -2083,7 +2083,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public void llSetRot(LSL_Rotation rot) { m_host.AddScriptLPS(1); - SetRot(m_host, rot); + SetRot(m_host, rot); ScriptSleep(200); } @@ -7280,7 +7280,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (remain < 1) return null; - SetRot(part, rules.GetQuaternionItem(idx++)); + SetRot(part, rules.GetQuaternionItem(idx++)); break; -- cgit v1.1 From 359f9efc768d701460491b64b75660bf3c145419 Mon Sep 17 00:00:00 2001 From: Melanie Date: Mon, 3 Sep 2012 21:51:54 +0100 Subject: Revert "formatting" This reverts commit fb211c64fd9d335f4879549023870b1e28416f74. --- OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 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 1d2ef40..6f4bc8b 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -2083,7 +2083,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public void llSetRot(LSL_Rotation rot) { m_host.AddScriptLPS(1); - SetRot(m_host, rot); + SetRot(m_host, rot); ScriptSleep(200); } @@ -7280,7 +7280,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (remain < 1) return null; - SetRot(part, rules.GetQuaternionItem(idx++)); + SetRot(part, rules.GetQuaternionItem(idx++)); break; -- cgit v1.1 From 29218cdb3169b70e047acc372433769ece3ffae1 Mon Sep 17 00:00:00 2001 From: Melanie Date: Mon, 3 Sep 2012 21:52:03 +0100 Subject: Revert "no need to assign rotation to a variable now" This reverts commit a3d140b57c5e2ae0f3334d59b82e116d40199b49. --- OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (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 6f4bc8b..9f952d1 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -7280,7 +7280,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (remain < 1) return null; - SetRot(part, rules.GetQuaternionItem(idx++)); + LSL_Rotation q = rules.GetQuaternionItem(idx++); + SetRot(part, q); break; -- cgit v1.1 From d297eb39e57f9dc70abe43839e263af19b5777e2 Mon Sep 17 00:00:00 2001 From: Melanie Date: Mon, 3 Sep 2012 21:52:12 +0100 Subject: Revert "made setting rotation match Second Life" Second Life seems to have introduced a bug, as we have confirmation that SL behavior changed recently and changed in contradiction to their stated intention This appears to be another of the bugs SL is notorious for. Signpost and I have decided to back this out until SL's intention becomes clear. This reverts commit f7b88d1c40ba06c62491d8d32809fe6c1c4d360d. --- .../Shared/Api/Implementation/LSL_Api.cs | 33 +++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) (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 9f952d1..be22cb4 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -2083,7 +2083,23 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public void llSetRot(LSL_Rotation rot) { m_host.AddScriptLPS(1); + + // try to let this work as in SL... + if (m_host.ParentID == 0) + { + // special case: If we are root, rotate complete SOG to new rotation SetRot(m_host, rot); + } + else + { + // we are a child. The rotation values will be set to the one of root modified by rot, as in SL. Don't ask. + SceneObjectPart rootPart = m_host.ParentGroup.RootPart; + if (rootPart != null) // better safe than sorry + { + SetRot(m_host, rootPart.RotationOffset * (Quaternion)rot); + } + } + ScriptSleep(200); } @@ -7276,12 +7292,22 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api break; case (int)ScriptBaseClass.PRIM_ROTATION: - case (int)ScriptBaseClass.PRIM_ROT_LOCAL: if (remain < 1) return null; LSL_Rotation q = rules.GetQuaternionItem(idx++); + // try to let this work as in SL... + if (part.ParentID == 0) + { + // special case: If we are root, rotate complete SOG to new rotation SetRot(part, q); + } + else + { + // we are a child. The rotation values will be set to the one of root modified by rot, as in SL. Don't ask. + SceneObjectPart rootPart = part.ParentGroup.RootPart; + SetRot(part, rootPart.RotationOffset * (Quaternion)q); + } break; @@ -7588,6 +7614,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api string primDesc = rules.GetLSLStringItem(idx++); part.Description = primDesc; break; + case (int)ScriptBaseClass.PRIM_ROT_LOCAL: + if (remain < 1) + return null; + SetRot(part, rules.GetQuaternionItem(idx++)); + break; case (int)ScriptBaseClass.PRIM_OMEGA: if (remain < 3) return null; -- cgit v1.1 From 574a6e35807d522a211f05d2370da2a31277051a Mon Sep 17 00:00:00 2001 From: Melanie Date: Mon, 3 Sep 2012 21:53:46 +0100 Subject: Revert "formatting" This reverts commit fb211c64fd9d335f4879549023870b1e28416f74. --- OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 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 dda8257..89bd6ac 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -2314,7 +2314,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public void llSetRot(LSL_Rotation rot) { m_host.AddScriptLPS(1); - SetRot(m_host, rot); + SetRot(m_host, rot); ScriptSleep(200); } @@ -7850,7 +7850,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (remain < 1) return null; - SetRot(part, rules.GetQuaternionItem(idx++)); + SetRot(part, rules.GetQuaternionItem(idx++)); break; -- cgit v1.1 From f32c74b2ffdeb439b3e939a3e21fe210af717af4 Mon Sep 17 00:00:00 2001 From: Melanie Date: Mon, 3 Sep 2012 21:53:55 +0100 Subject: Revert "no need to assign rotation to a variable now" This reverts commit a3d140b57c5e2ae0f3334d59b82e116d40199b49. --- OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (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 89bd6ac..c47893e 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -7850,7 +7850,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (remain < 1) return null; - SetRot(part, rules.GetQuaternionItem(idx++)); + LSL_Rotation q = rules.GetQuaternionItem(idx++); + SetRot(part, q); break; -- cgit v1.1 From 72d20b794a245f0e9b9e1f968b50067db2910b6c Mon Sep 17 00:00:00 2001 From: Melanie Date: Mon, 3 Sep 2012 21:54:02 +0100 Subject: Revert "made setting rotation match Second Life" This reverts commit f7b88d1c40ba06c62491d8d32809fe6c1c4d360d. --- .../Shared/Api/Implementation/LSL_Api.cs | 33 +++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) (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 c47893e..efeca26 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -2314,7 +2314,23 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public void llSetRot(LSL_Rotation rot) { m_host.AddScriptLPS(1); + + // try to let this work as in SL... + if (m_host.ParentID == 0) + { + // special case: If we are root, rotate complete SOG to new rotation SetRot(m_host, rot); + } + else + { + // we are a child. The rotation values will be set to the one of root modified by rot, as in SL. Don't ask. + SceneObjectPart rootPart = m_host.ParentGroup.RootPart; + if (rootPart != null) // better safe than sorry + { + SetRot(m_host, rootPart.RotationOffset * (Quaternion)rot); + } + } + ScriptSleep(200); } @@ -7846,12 +7862,22 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api break; case (int)ScriptBaseClass.PRIM_ROTATION: - case (int)ScriptBaseClass.PRIM_ROT_LOCAL: if (remain < 1) return null; LSL_Rotation q = rules.GetQuaternionItem(idx++); + // try to let this work as in SL... + if (part.ParentID == 0) + { + // special case: If we are root, rotate complete SOG to new rotation SetRot(part, q); + } + else + { + // we are a child. The rotation values will be set to the one of root modified by rot, as in SL. Don't ask. + SceneObjectPart rootPart = part.ParentGroup.RootPart; + SetRot(part, rootPart.RotationOffset * (Quaternion)q); + } break; @@ -8188,6 +8214,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api string primDesc = rules.GetLSLStringItem(idx++); part.Description = primDesc; break; + case (int)ScriptBaseClass.PRIM_ROT_LOCAL: + if (remain < 1) + return null; + SetRot(part, rules.GetQuaternionItem(idx++)); + break; case (int)ScriptBaseClass.PRIM_OMEGA: if (remain < 3) return null; -- cgit v1.1 From 663bfbb372218af6e2a854a011152c9efdb82eaa Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Sat, 1 Sep 2012 02:18:36 +0100 Subject: although the attachmentPoint argument is a uint, zero is not a valid attachment point --- OpenSim/Region/Framework/Scenes/ScenePresence.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index 5bf69ad..22d3289 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -3418,7 +3418,9 @@ namespace OpenSim.Region.Framework.Scenes public List GetAttachments(uint attachmentPoint) { List attachments = new List(); - + + if (attachmentPoint >= 0) + { lock (m_attachments) { foreach (SceneObjectGroup so in m_attachments) @@ -3427,6 +3429,7 @@ namespace OpenSim.Region.Framework.Scenes attachments.Add(so); } } + } return attachments; } -- cgit v1.1 From 8d431c63594b7576fe295d50658531e81df2ac4e Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Sat, 1 Sep 2012 02:20:07 +0100 Subject: formatting --- OpenSim/Region/Framework/Scenes/ScenePresence.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index 22d3289..1222ac6 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -3421,15 +3421,15 @@ namespace OpenSim.Region.Framework.Scenes if (attachmentPoint >= 0) { - lock (m_attachments) - { - foreach (SceneObjectGroup so in m_attachments) + lock (m_attachments) { - if (attachmentPoint == so.AttachmentPoint) - attachments.Add(so); + foreach (SceneObjectGroup so in m_attachments) + { + if (attachmentPoint == so.AttachmentPoint) + attachments.Add(so); + } } } - } return attachments; } -- cgit v1.1 From a858c5daee64223355de04b77746142be0f5795f Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Sat, 1 Sep 2012 02:39:49 +0100 Subject: implementing a function to get the number of attachments worn --- .../Shared/Api/Implementation/OSSL_Api.cs | 38 ++++++++++++++++++++++ .../ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs | 10 ++++++ .../ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs | 7 ++++ 3 files changed, 55 insertions(+) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs index e245684..57f1e65 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs @@ -3313,6 +3313,44 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api ((LSL_Api)m_LSL_Api).DetachFromAvatar(); } + public LSL_List osGetNumberOfAttachments(LSL_Key avatar, LSL_List attachmentPoints) + { + CheckThreatLevel(ThreatLevel.Moderate, "osGetNumberOfAttachments"); + + m_host.AddScriptLPS(1); + + UUID targetUUID; + ScenePresence target; + LSL_List resp = new LSL_List(); + + if (attachmentPoints.Length >= 1 && UUID.TryParse(avatar.ToString(), out targetUUID) && World.TryGetScenePresence(targetUUID, out target)) + { + foreach (object point in attachmentPoints.Data) + { + LSL_Integer ipoint = new LSL_Integer( + (point is LSL_Integer || point is int || point is uint) ? + (int)point : + 0 + ); + resp.Add(ipoint); + if (ipoint == 0) + { + // indicates zero attachments + resp.Add(new LSL_Integer(0)); + } + else + { + // gets the number of attachments on the attachment point + resp.Add(new LSL_Integer(target.GetAttachments((uint)ipoint).Count)); + } + } + } + + return resp; + } + + #endregion + /// /// Checks if thing is a UUID. /// diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs index 06729ab..6db6443 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs @@ -192,6 +192,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces /// Nothing happens if the object is not attached. void osForceDetachFromAvatar(); + /// + /// Returns a strided list of the specified attachment points and the number of attachments on those points. + /// + /// avatar UUID + /// list of ATTACH_* constants + /// + LSL_List osGetNumberOfAttachments(LSL_Key avatar, LSL_List attachmentPoints); + + #endregion + //texture draw functions string osMovePen(string drawList, int x, int y); string osDrawLine(string drawList, int startX, int startY, int endX, int endY); diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs index ba1ade2..230c378 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs @@ -311,6 +311,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase m_OSSL_Functions.osForceDetachFromAvatar(); } + public LSL_List osGetNumberOfAttachments(LSL_Key avatar, LSL_List attachmentPoints) + { + return m_OSSL_Functions.osGetNumberOfAttachments(avatar, attachmentPoints); + } + + #endregion + // Texture Draw functions public string osMovePen(string drawList, int x, int y) -- cgit v1.1 From d4b8a13a1d63c950feba694eca53df06f2cc5792 Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Sat, 1 Sep 2012 02:43:04 +0100 Subject: refactoring the grunt work of MessageObject into a private method with a UUID argument --- OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs index 57f1e65..82114b3 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs @@ -1673,6 +1673,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api return; } + MessageObject(objUUID, message); + } + + private void MessageObject(UUID objUUID, string message) + { object[] resobj = new object[] { new LSL_Types.LSLString(m_host.UUID.ToString()), new LSL_Types.LSLString(message) }; SceneObjectPart sceneOP = World.GetSceneObjectPart(objUUID); -- cgit v1.1 From ff867b59cf59fdab19413cd46f3dd04058fbf3c7 Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Sat, 1 Sep 2012 02:44:11 +0100 Subject: Implementing functing to send messages directly to attachments --- .../Shared/Api/Implementation/OSSL_Api.cs | 131 +++++++++++++++++++++ .../ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs | 13 ++ .../Shared/Api/Runtime/LSL_Constants.cs | 52 ++++++++ .../ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs | 5 + 4 files changed, 201 insertions(+) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs index 82114b3..8e80b4c 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs @@ -3354,6 +3354,137 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api return resp; } + public void osMessageAttachments(LSL_Key avatar, string message, LSL_List attachmentPoints, int options) + { + CheckThreatLevel(ThreatLevel.Moderate, "osMessageAttachments"); + m_host.AddScriptLPS(1); + + UUID targetUUID; + ScenePresence target; + + if (attachmentPoints.Length >= 1 && UUID.TryParse(avatar.ToString(), out targetUUID) && World.TryGetScenePresence(targetUUID, out target)) + { + List aps = new List(); + foreach (object point in attachmentPoints.Data) + { + int ipoint; + if (int.TryParse(point.ToString(), out ipoint)) + { + aps.Add(ipoint); + } + } + + List attachments = new List(); + + bool msgAll = aps.Contains(ScriptBaseClass.OS_ATTACH_MSG_ALL); + bool invertPoints = (options & ScriptBaseClass.OS_ATTACH_MSG_INVERT_POINTS) != 0; + + if (msgAll && invertPoints) + { + return; + } + else if (msgAll || invertPoints) + { + attachments = target.GetAttachments(); + } + else + { + foreach (int point in aps) + { + if (point > 0) + { + attachments.AddRange(target.GetAttachments((uint)point)); + } + } + } + + // if we have no attachments at this point, exit now + if (attachments.Count == 0) + { + return; + } + + List ignoreThese = new List(); + + if (invertPoints) + { + foreach (SceneObjectGroup attachment in attachments) + { + if (aps.Contains((int)attachment.AttachmentPoint)) + { + ignoreThese.Add(attachment); + } + } + } + + foreach (SceneObjectGroup attachment in ignoreThese) + { + attachments.Remove(attachment); + } + ignoreThese.Clear(); + + // if inverting removed all attachments to check, exit now + if (attachments.Count < 1) + { + return; + } + + if ((options & ScriptBaseClass.OS_ATTACH_MSG_OBJECT_CREATOR) != 0) + { + foreach (SceneObjectGroup attachment in attachments) + { + if (attachment.RootPart.CreatorID != m_host.CreatorID) + { + ignoreThese.Add(attachment); + } + } + + foreach (SceneObjectGroup attachment in ignoreThese) + { + attachments.Remove(attachment); + } + ignoreThese.Clear(); + + // if filtering by same object creator removed all + // attachments to check, exit now + if (attachments.Count == 0) + { + return; + } + } + + if ((options & ScriptBaseClass.OS_ATTACH_MSG_SCRIPT_CREATOR) != 0) + { + foreach (SceneObjectGroup attachment in attachments) + { + if (attachment.RootPart.CreatorID != m_item.CreatorID) + { + ignoreThese.Add(attachment); + } + } + + foreach (SceneObjectGroup attachment in ignoreThese) + { + attachments.Remove(attachment); + } + ignoreThese.Clear(); + + // if filtering by object creator must match originating + // script creator removed all attachments to check, + // exit now + if (attachments.Count == 0) + { + return; + } + } + + foreach (SceneObjectGroup attachment in attachments) + { + MessageObject(attachment.RootPart.UUID, message); + } + } + } + #endregion /// diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs index 6db6443..bde7a8e 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs @@ -200,6 +200,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces /// LSL_List osGetNumberOfAttachments(LSL_Key avatar, LSL_List attachmentPoints); + /// + /// Sends a specified message to the specified avatar's attachments on + /// the specified attachment points. + /// + /// + /// Behaves as osMessageObject(), without the sending script needing to know the attachment keys in advance. + /// + /// avatar UUID + /// message string + /// list of ATTACH_* constants, or -1 for all attachments. If -1 is specified and OS_ATTACH_MSG_INVERT_POINTS is present in flags, no action is taken. + /// flags further constraining the attachments to deliver the message to. + void osMessageAttachments(LSL_Key avatar, string message, LSL_List attachmentPoints, int flags); + #endregion //texture draw functions diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs index cad8518..60a7e14 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs @@ -237,6 +237,58 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase public const int ATTACH_HUD_BOTTOM = 37; public const int ATTACH_HUD_BOTTOM_RIGHT = 38; + #region osMessageAttachments constants + + /// + /// Instructs osMessageAttachements to send the message to attachments + /// on every point. + /// + /// + /// One might expect this to be named OS_ATTACH_ALL, but then one might + /// also expect functions designed to attach or detach or get + /// attachments to work with it too. Attaching a no-copy item to + /// many attachments could be dangerous. + /// when combined with OS_ATTACH_MSG_INVERT_POINTS, will prevent the + /// message from being sent. + /// if combined with OS_ATTACH_MSG_OBJECT_CREATOR or + /// OS_ATTACH_MSG_SCRIPT_CREATOR, could result in no message being + /// sent- this is expected behaviour. + /// + public const int OS_ATTACH_MSG_ALL = -65535; + + /// + /// Instructs osMessageAttachements to invert how the attachment points + /// list should be treated (e.g. go from inclusive operation to + /// exclusive operation). + /// + /// + /// This might be used if you want to deliver a message to one set of + /// attachments and a different message to everything else. With + /// this flag, you only need to build one explicit list for both calls. + /// + public const int OS_ATTACH_MSG_INVERT_POINTS = 1; + + /// + /// Instructs osMessageAttachments to only send the message to + /// attachments with a CreatorID that matches the host object CreatorID + /// + /// + /// This would be used if distributed in an object vendor/updater server. + /// + public const int OS_ATTACH_MSG_OBJECT_CREATOR = 2; + + /// + /// Instructs osMessageAttachments to only send the message to + /// attachments with a CreatorID that matches the sending script CreatorID + /// + /// + /// This might be used if the script is distributed independently of a + /// containing object. + /// + public const int OS_ATTACH_MSG_SCRIPT_CREATOR = 4; + + #endregion + public const int LAND_LEVEL = 0; public const int LAND_RAISE = 1; public const int LAND_LOWER = 2; diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs index 230c378..08ebfd6 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs @@ -316,6 +316,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase return m_OSSL_Functions.osGetNumberOfAttachments(avatar, attachmentPoints); } + public void osMessageAttachments(LSL_Key avatar, string message, LSL_List attachmentPoints, int flags) + { + m_OSSL_Functions.osMessageAttachments(avatar, message, attachmentPoints, flags); + } + #endregion // Texture Draw functions -- cgit v1.1 From 07dbe46ba3c2b949c9da34eaa80d7e1afd68fece Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Sat, 1 Sep 2012 02:45:07 +0100 Subject: wrapping attachment functions in a region --- OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs | 2 ++ OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs | 2 +- OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs index 8e80b4c..2e1e5b6 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs @@ -3229,6 +3229,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } } + #region Attachment commands + public void osForceAttachToAvatar(int attachmentPoint) { CheckThreatLevel(ThreatLevel.High, "osForceAttachToAvatar"); diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs index bde7a8e..3985e66 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs @@ -157,7 +157,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces void osAvatarPlayAnimation(string avatar, string animation); void osAvatarStopAnimation(string avatar, string animation); - // Attachment commands + #region Attachment commands /// /// Attach the object containing this script to the avatar that owns it without asking for PERMISSION_ATTACH diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs index 08ebfd6..52ca3da 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs @@ -289,7 +289,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase m_OSSL_Functions.osAvatarStopAnimation(avatar, animation); } - // Avatar functions + #region Attachment commands public void osForceAttachToAvatar(int attachmentPoint) { -- cgit v1.1 From 641b08aa781fcf4c1bf6d8425c98a302f96a8b88 Mon Sep 17 00:00:00 2001 From: Mic Bowman Date: Wed, 5 Sep 2012 09:13:16 -0700 Subject: Enables cast from int to float for MOD* functions; Thanks SignpostMarv! --- OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs index 84cf6ca..cde2d9f 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs @@ -310,7 +310,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api // ---------- Integer ---------- else if (lslparm is LSL_Integer) { - if (type == typeof(int)) + if (type == typeof(int) || type == typeof(float)) return (int)(LSL_Integer)lslparm; } -- cgit v1.1 From a0d0c9f751f45d54772af2e33866b27c9be33511 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Thu, 6 Sep 2012 00:11:47 +0100 Subject: If the GetTexture capability receives a request for a range of data beyond that of an otherwise valid asset, return HTTP PartialContent rather than RequestedRangeNotSatisfiable. This is because recent viewers (3.2.1, 3.3.4) and probably earlier ones using the http GetTexture capability will sometimes make such invalid range requests. This appears to happen if the viewer's estimate of texture sizes at discard levels > 0 (chiefly 2) exceeds the total texture size. I believe this does not normally happen but can occur for dynamic textures with are large but mainly blank. If this happens, returning a RequestedRangeNotSatisfiable will cause the viewer to not render the texture at the final resolution. However, returning a PartialContent (or OK) even with 0 data will allow the viewer to render the final texture. --- .../Scripting/DynamicTexture/DynamicTextureModule.cs | 16 +++++++++++++--- .../Scripting/VectorRender/VectorRenderModule.cs | 20 ++++++++++++++++++++ 2 files changed, 33 insertions(+), 3 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs b/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs index 3eedf49..e09f1a9 100644 --- a/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs +++ b/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs @@ -42,7 +42,7 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture { public class DynamicTextureModule : IRegionModule, IDynamicTextureManager { - //private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); +// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private const int ALL_SIDES = -1; @@ -249,10 +249,18 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture } } +// m_log.DebugFormat( +// "[DYNAMIC TEXTURE MODULE]: Requesting generation of new dynamic texture for {0} in {1}", +// part.Name, part.ParentGroup.Scene.Name); + RenderPlugins[contentType].AsyncConvertData(updater.UpdaterID, data, extraParams); } else { +// m_log.DebugFormat( +// "[DYNAMIC TEXTURE MODULE]: Reusing cached texture {0} for {1} in {2}", +// objReusableTextureUUID, part.Name, part.ParentGroup.Scene.Name); + // No need to add to updaters as the texture is always the same. Not that this functionality // apppears to be implemented anyway. updater.UpdatePart(part, (UUID)objReusableTextureUUID); @@ -448,8 +456,10 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture IJ2KDecoder cacheLayerDecode = scene.RequestModuleInterface(); if (cacheLayerDecode != null) { - cacheLayerDecode.Decode(asset.FullID, asset.Data); - cacheLayerDecode = null; + if (!cacheLayerDecode.Decode(asset.FullID, asset.Data)) + m_log.WarnFormat( + "[DYNAMIC TEXTURE MODULE]: Decoding of dynamically generated asset {0} for {1} in {2} failed", + asset.ID, part.Name, part.ParentGroup.Scene.Name); } UUID oldID = UpdatePart(part, asset.FullID); diff --git a/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs b/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs index 4268f2e..0e7051e 100644 --- a/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs +++ b/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs @@ -46,6 +46,11 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender { public class VectorRenderModule : IRegionModule, IDynamicTextureRender { + // These fields exist for testing purposes, please do not remove. +// private static bool s_flipper; +// private static byte[] s_asset1Data; +// private static byte[] s_asset2Data; + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private Scene m_scene; @@ -161,6 +166,13 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender { m_textureManager.RegisterRender(GetContentType(), this); } + + // This code exists for testing purposes, please do not remove. +// s_asset1Data = m_scene.AssetService.Get("00000000-0000-1111-9999-000000000001").Data; +// s_asset1Data = m_scene.AssetService.Get("9f4acf0d-1841-4e15-bdb8-3a12efc9dd8f").Data; + + // Terrain dirt - smallest bin/assets file (6004 bytes) +// s_asset2Data = m_scene.AssetService.Get("b8d3965a-ad78-bf43-699b-bff8eca6c975").Data; } public void Close() @@ -364,6 +376,14 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender } byte[] imageJ2000 = new byte[0]; + + // This code exists for testing purposes, please do not remove. +// if (s_flipper) +// imageJ2000 = s_asset1Data; +// else +// imageJ2000 = s_asset2Data; +// +// s_flipper = !s_flipper; try { -- cgit v1.1 From 5eb2526e889cd49d1c77e6e057f847cfd990268f Mon Sep 17 00:00:00 2001 From: BlueWall Date: Thu, 6 Sep 2012 05:13:10 -0400 Subject: 0006270: Warp3D leaks memory on mono based systems Thanks Hiro Lecker for a patch to reduce memory useage with Warp3D map module --- OpenSim/Region/CoreModules/World/Warp3DMap/Warp3DImageModule.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/World/Warp3DMap/Warp3DImageModule.cs b/OpenSim/Region/CoreModules/World/Warp3DMap/Warp3DImageModule.cs index 9002a9f..ed9b127 100644 --- a/OpenSim/Region/CoreModules/World/Warp3DMap/Warp3DImageModule.cs +++ b/OpenSim/Region/CoreModules/World/Warp3DMap/Warp3DImageModule.cs @@ -208,6 +208,9 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap bitmap = ImageUtils.ResizeImage(origBitmap, viewport.Width, viewport.Height); } + GC.Collect(); + m_log.Debug("[WARP 3D IMAGE MODULE]: GC.Collect()"); + return bitmap; } @@ -673,4 +676,4 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap return result; } } -} \ No newline at end of file +} -- cgit v1.1 From d2e79e26d7ea99b222a9c432b3727c558cd39f6e Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Thu, 6 Sep 2012 10:40:37 +0100 Subject: adding utility method for getting SceneObjectPart from scene Signed-off-by: BlueWall --- OpenSim/Region/Framework/Scenes/Scene.cs | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 2b4dea4..1771bf9 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -4613,6 +4613,18 @@ namespace OpenSim.Region.Framework.Scenes } /// + /// Attempt to get a prim via its UUID + /// + /// + /// + /// + public bool TryGetSceneObjectPart(UUID fullID, out SceneObjectPart sop) + { + sop = GetSceneObjectPart(fullID); + return sop != null; + } + + /// /// Get a scene object group that contains the prim with the given local id /// /// -- cgit v1.1 From 4215877b4848bd185ec20b50118b36b53cbfd604 Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Thu, 6 Sep 2012 10:40:26 +0100 Subject: adding utility method for getting SceneObjectGroup from scene Signed-off-by: BlueWall --- OpenSim/Region/Framework/Scenes/Scene.cs | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 1771bf9..a2d553d 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -4582,6 +4582,18 @@ namespace OpenSim.Region.Framework.Scenes } /// + /// Attempt to get the SOG via its UUID + /// + /// + /// + /// + public bool TryGetSceneObjectGroup(UUID fullID, out SceneObjectGroup sog) + { + sog = GetSceneObjectGroup(fullID); + return sog != null; + } + + /// /// Get a prim by name from the scene (will return the first /// found, if there are more than one prim with the same name) /// -- cgit v1.1 From 8f02fd926e14dfad7f5eb77a67a6701f449511e0 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Thu, 6 Sep 2012 22:12:05 +0100 Subject: If reusing dynamic textures, do not reuse small data length textures that fall below current viewer discard level 2 thresholds. Viewer LL 3.3.4 and before sometimes fail to properly redisplay dynamic textures that have a small data length compared to pixel size when pulled from cache. This appears to happen when the data length is smaller than the estimate discard level 2 size the viewer uses when making this GetTexture request. This commit works around this by always regenerating dynamic textures that fall below this threshold rather than reusing them if ReuseDynamicTextures = true This can be controlled by the [Textures] ReuseDynamicLowDataTextures config setting which defaults to false. --- .../DynamicTexture/DynamicTextureModule.cs | 59 ++++++++++++++++++---- .../Scripting/LoadImageURL/LoadImageURLModule.cs | 41 +++++++++------ .../VectorRender/Tests/VectorRenderModuleTests.cs | 42 +++++++++++++++ .../Scripting/VectorRender/VectorRenderModule.cs | 24 ++++----- .../Grid/Tests/GridConnectorsTests.cs | 2 +- .../World/Archiver/Tests/ArchiverTests.cs | 2 +- .../Framework/Interfaces/IDynamicTextureManager.cs | 57 +++++++++++++++++++-- 7 files changed, 181 insertions(+), 46 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs b/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs index e09f1a9..1f340df 100644 --- a/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs +++ b/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs @@ -42,7 +42,7 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture { public class DynamicTextureModule : IRegionModule, IDynamicTextureManager { -// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private const int ALL_SIDES = -1; @@ -54,6 +54,17 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture /// public bool ReuseTextures { get; set; } + /// + /// If false, then textures which have a low data size are not reused when ReuseTextures = true. + /// + /// + /// LL viewers 3.3.4 and before appear to not fully render textures pulled from the viewer cache if those + /// textures have a relatively high pixel surface but a small data size. Typically, this appears to happen + /// if the data size is smaller than the viewer's discard level 2 size estimate. So if this is setting is + /// false, textures smaller than the calculation in IsSizeReuseable are always regenerated rather than reused + /// to work around this problem. + public bool ReuseLowDataTextures { get; set; } + private Dictionary RegisteredScenes = new Dictionary(); private Dictionary RenderPlugins = @@ -83,18 +94,17 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture /// /// Called by code which actually renders the dynamic texture to supply texture data. /// - /// - /// - /// True if the data generated can be reused for subsequent identical requests - public void ReturnData(UUID id, byte[] data, bool isReuseable) + /// + /// + public void ReturnData(UUID updaterId, IDynamicTexture texture) { DynamicTextureUpdater updater = null; lock (Updaters) { - if (Updaters.ContainsKey(id)) + if (Updaters.ContainsKey(updaterId)) { - updater = Updaters[id]; + updater = Updaters[updaterId]; } } @@ -103,11 +113,16 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture if (RegisteredScenes.ContainsKey(updater.SimUUID)) { Scene scene = RegisteredScenes[updater.SimUUID]; - UUID newTextureID = updater.DataReceived(data, scene); + UUID newTextureID = updater.DataReceived(texture.Data, scene); - if (ReuseTextures && isReuseable && !updater.BlendWithOldTexture) + if (ReuseTextures + && !updater.BlendWithOldTexture + && texture.IsReuseable + && (ReuseLowDataTextures || IsDataSizeReuseable(texture))) + { m_reuseableDynamicTextures.Store( - GenerateReusableTextureKey(updater.BodyData, updater.Params), newTextureID); + GenerateReusableTextureKey(texture.InputCommands, texture.InputParams), newTextureID); + } } } @@ -123,6 +138,27 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture } } + /// + /// Determines whether the texture is reuseable based on its data size. + /// + /// + /// This is a workaround for a viewer bug where very small data size textures relative to their pixel size + /// are not redisplayed properly when pulled from cache. The calculation here is based on the typical discard + /// level of 2, a 'rate' of 0.125 and 4 components (which makes for a factor of 0.5). + /// + /// + private bool IsDataSizeReuseable(IDynamicTexture texture) + { +// Console.WriteLine("{0} {1}", texture.Size.Width, texture.Size.Height); + int discardLevel2DataThreshold = (int)Math.Ceiling((texture.Size.Width >> 2) * (texture.Size.Height >> 2) * 0.5); + +// m_log.DebugFormat( +// "[DYNAMIC TEXTURE MODULE]: Discard level 2 threshold {0}, texture data length {1}", +// discardLevel2DataThreshold, texture.Data.Length); + + return discardLevel2DataThreshold < texture.Data.Length; + } + public UUID AddDynamicTextureURL(UUID simID, UUID primID, string contentType, string url, string extraParams, int updateTimer) { @@ -293,7 +329,10 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture { IConfig texturesConfig = config.Configs["Textures"]; if (texturesConfig != null) + { ReuseTextures = texturesConfig.GetBoolean("ReuseDynamicTextures", false); + ReuseLowDataTextures = texturesConfig.GetBoolean("ReuseDynamicLowDataTextures", false); + } if (!RegisteredScenes.ContainsKey(scene.RegionInfo.RegionID)) { diff --git a/OpenSim/Region/CoreModules/Scripting/LoadImageURL/LoadImageURLModule.cs b/OpenSim/Region/CoreModules/Scripting/LoadImageURL/LoadImageURLModule.cs index 2b3a0f2..45e6527 100644 --- a/OpenSim/Region/CoreModules/Scripting/LoadImageURL/LoadImageURLModule.cs +++ b/OpenSim/Region/CoreModules/Scripting/LoadImageURL/LoadImageURLModule.cs @@ -32,6 +32,7 @@ using System.Net; using Nini.Config; using OpenMetaverse; using OpenMetaverse.Imaging; +using OpenSim.Region.CoreModules.Scripting.DynamicTexture; using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Scenes; using log4net; @@ -73,12 +74,12 @@ namespace OpenSim.Region.CoreModules.Scripting.LoadImageURL // return false; // } - public byte[] ConvertUrl(string url, string extraParams) + public IDynamicTexture ConvertUrl(string url, string extraParams) { return null; } - public byte[] ConvertData(string bodyData, string extraParams) + public IDynamicTexture ConvertData(string bodyData, string extraParams) { return null; } @@ -171,11 +172,11 @@ namespace OpenSim.Region.CoreModules.Scripting.LoadImageURL private void HttpRequestReturn(IAsyncResult result) { - RequestState state = (RequestState) result.AsyncState; WebRequest request = (WebRequest) state.Request; Stream stream = null; byte[] imageJ2000 = new byte[0]; + Size newSize = new Size(0, 0); try { @@ -188,37 +189,43 @@ namespace OpenSim.Region.CoreModules.Scripting.LoadImageURL try { Bitmap image = new Bitmap(stream); - Size newsize; // TODO: make this a bit less hard coded if ((image.Height < 64) && (image.Width < 64)) { - newsize = new Size(32, 32); + newSize.Width = 32; + newSize.Height = 32; } else if ((image.Height < 128) && (image.Width < 128)) { - newsize = new Size(64, 64); + newSize.Width = 64; + newSize.Height = 64; } else if ((image.Height < 256) && (image.Width < 256)) { - newsize = new Size(128, 128); + newSize.Width = 128; + newSize.Height = 128; } else if ((image.Height < 512 && image.Width < 512)) { - newsize = new Size(256, 256); + newSize.Width = 256; + newSize.Height = 256; } else if ((image.Height < 1024 && image.Width < 1024)) { - newsize = new Size(512, 512); + newSize.Width = 512; + newSize.Height = 512; } else { - newsize = new Size(1024, 1024); + newSize.Width = 1024; + newSize.Height = 1024; } - Bitmap resize = new Bitmap(image, newsize); - - imageJ2000 = OpenJPEG.EncodeFromImage(resize, true); + using (Bitmap resize = new Bitmap(image, newSize)) + { + imageJ2000 = OpenJPEG.EncodeFromImage(resize, true); + } } catch (Exception) { @@ -233,7 +240,6 @@ namespace OpenSim.Region.CoreModules.Scripting.LoadImageURL } catch (WebException) { - } finally { @@ -243,10 +249,13 @@ namespace OpenSim.Region.CoreModules.Scripting.LoadImageURL } } - m_log.DebugFormat("[LOADIMAGEURLMODULE] Returning {0} bytes of image data for request {1}", + m_log.DebugFormat("[LOADIMAGEURLMODULE]: Returning {0} bytes of image data for request {1}", imageJ2000.Length, state.RequestID); - m_textureManager.ReturnData(state.RequestID, imageJ2000, false); + m_textureManager.ReturnData( + state.RequestID, + new OpenSim.Region.CoreModules.Scripting.DynamicTexture.DynamicTexture( + request.RequestUri, null, imageJ2000, newSize, false)); } #region Nested type: RequestState diff --git a/OpenSim/Region/CoreModules/Scripting/VectorRender/Tests/VectorRenderModuleTests.cs b/OpenSim/Region/CoreModules/Scripting/VectorRender/Tests/VectorRenderModuleTests.cs index b50c0bd..41baccc 100644 --- a/OpenSim/Region/CoreModules/Scripting/VectorRender/Tests/VectorRenderModuleTests.cs +++ b/OpenSim/Region/CoreModules/Scripting/VectorRender/Tests/VectorRenderModuleTests.cs @@ -57,6 +57,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender.Tests m_dtm = new DynamicTextureModule(); m_dtm.ReuseTextures = reuseTextures; +// m_dtm.ReuseLowDataTextures = reuseTextures; m_vrm = new VectorRenderModule(); @@ -201,6 +202,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender.Tests public void TestRepeatSameDrawReusingTexture() { TestHelpers.InMethod(); +// TestHelpers.EnableLogging(); string dtText = "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;"; @@ -228,6 +230,46 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender.Tests Assert.That(firstDynamicTextureID, Is.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID)); } + /// + /// Test a low data dynamically generated texture such that it is treated as a low data texture that causes + /// problems for current viewers. + /// + /// + /// As we do not set DynamicTextureModule.ReuseLowDataTextures = true in this test, it should not reuse the + /// texture + /// + [Test] + public void TestRepeatSameDrawLowDataTexture() + { + TestHelpers.InMethod(); +// TestHelpers.EnableLogging(); + + string dtText = "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;"; + + SetupScene(true); + SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene); + + m_dtm.AddDynamicTextureData( + m_scene.RegionInfo.RegionID, + so.UUID, + m_vrm.GetContentType(), + dtText, + "1024", + 0); + + UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID; + + m_dtm.AddDynamicTextureData( + m_scene.RegionInfo.RegionID, + so.UUID, + m_vrm.GetContentType(), + dtText, + "1024", + 0); + + Assert.That(firstDynamicTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID)); + } + [Test] public void TestRepeatSameDrawDifferentExtraParamsReusingTexture() { diff --git a/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs b/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs index 0e7051e..d82551e 100644 --- a/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs +++ b/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs @@ -35,6 +35,7 @@ using System.Net; using Nini.Config; using OpenMetaverse; using OpenMetaverse.Imaging; +using OpenSim.Region.CoreModules.Scripting.DynamicTexture; using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Scenes; using log4net; @@ -85,20 +86,14 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender // return lines.Any((str, r) => str.StartsWith("Image")); // } - public byte[] ConvertUrl(string url, string extraParams) + public IDynamicTexture ConvertUrl(string url, string extraParams) { return null; } - public byte[] ConvertData(string bodyData, string extraParams) + public IDynamicTexture ConvertData(string bodyData, string extraParams) { - bool reuseable; - return Draw(bodyData, extraParams, out reuseable); - } - - private byte[] ConvertData(string bodyData, string extraParams, out bool reuseable) - { - return Draw(bodyData, extraParams, out reuseable); + return Draw(bodyData, extraParams); } public bool AsyncConvertUrl(UUID id, string url, string extraParams) @@ -109,10 +104,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender public bool AsyncConvertData(UUID id, string bodyData, string extraParams) { // XXX: This isn't actually being done asynchronously! - bool reuseable; - byte[] data = ConvertData(bodyData, extraParams, out reuseable); - - m_textureManager.ReturnData(id, data, reuseable); + m_textureManager.ReturnData(id, ConvertData(bodyData, extraParams)); return true; } @@ -191,7 +183,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender #endregion - private byte[] Draw(string data, string extraParams, out bool reuseable) + private IDynamicTexture Draw(string data, string extraParams) { // We need to cater for old scripts that didnt use extraParams neatly, they use either an integer size which represents both width and height, or setalpha // we will now support multiple comma seperated params in the form width:256,height:512,alpha:255 @@ -334,6 +326,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender Bitmap bitmap = null; Graphics graph = null; + bool reuseable = false; try { @@ -396,7 +389,8 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender e.Message, e.StackTrace); } - return imageJ2000; + return new OpenSim.Region.CoreModules.Scripting.DynamicTexture.DynamicTexture( + data, extraParams, imageJ2000, new Size(width, height), reuseable); } finally { diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/Tests/GridConnectorsTests.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/Tests/GridConnectorsTests.cs index b286d17..57ae549 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/Tests/GridConnectorsTests.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/Tests/GridConnectorsTests.cs @@ -43,7 +43,7 @@ using OpenSim.Tests.Common; namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid.Tests { [TestFixture] - public class GridConnectorsTests + public class GridConnectorsTests : OpenSimTestCase { LocalGridServicesConnector m_LocalConnector; private void SetUp() diff --git a/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs b/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs index 5deaf52..904110e 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs @@ -51,7 +51,7 @@ using RegionSettings = OpenSim.Framework.RegionSettings; namespace OpenSim.Region.CoreModules.World.Archiver.Tests { [TestFixture] - public class ArchiverTests + public class ArchiverTests : OpenSimTestCase { private Guid m_lastRequestId; private string m_lastErrorMessage; diff --git a/OpenSim/Region/Framework/Interfaces/IDynamicTextureManager.cs b/OpenSim/Region/Framework/Interfaces/IDynamicTextureManager.cs index 1a3bcbb..6df5cc2 100644 --- a/OpenSim/Region/Framework/Interfaces/IDynamicTextureManager.cs +++ b/OpenSim/Region/Framework/Interfaces/IDynamicTextureManager.cs @@ -25,6 +25,8 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +using System; +using System.Drawing; using System.IO; using OpenMetaverse; @@ -33,7 +35,14 @@ namespace OpenSim.Region.Framework.Interfaces public interface IDynamicTextureManager { void RegisterRender(string handleType, IDynamicTextureRender render); - void ReturnData(UUID id, byte[] data, bool isReuseable); + + /// + /// Used by IDynamicTextureRender implementations to return renders + /// + /// + /// + /// + void ReturnData(UUID id, IDynamicTexture texture); UUID AddDynamicTextureURL(UUID simID, UUID primID, string contentType, string url, string extraParams, int updateTimer); @@ -125,11 +134,53 @@ namespace OpenSim.Region.Framework.Interfaces // /// // bool AlwaysIdenticalConversion(string bodyData, string extraParams); - byte[] ConvertUrl(string url, string extraParams); - byte[] ConvertData(string bodyData, string extraParams); + IDynamicTexture ConvertUrl(string url, string extraParams); + IDynamicTexture ConvertData(string bodyData, string extraParams); + bool AsyncConvertUrl(UUID id, string url, string extraParams); bool AsyncConvertData(UUID id, string bodyData, string extraParams); + void GetDrawStringSize(string text, string fontName, int fontSize, out double xSize, out double ySize); } + + public interface IDynamicTexture + { + /// + /// Input commands used to generate this data. + /// + /// + /// Null if input commands were not used. + /// + string InputCommands { get; } + + /// + /// Uri used to generate this data. + /// + /// + /// Null if a uri was not used. + /// + Uri InputUri { get; } + + /// + /// Extra input params used to generate this data. + /// + string InputParams { get; } + + /// + /// Texture data. + /// + byte[] Data { get; } + + /// + /// Size of texture. + /// + Size Size { get; } + + /// + /// Signal whether the texture is reuseable (i.e. whether the same input data will always generate the same + /// texture). + /// + bool IsReuseable { get; } + } } -- cgit v1.1 From d2b00749ef71729555d393da7fef1dcdb84f5cbc Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Thu, 6 Sep 2012 23:14:48 +0100 Subject: Add missing DynamicTexture.cs file from last commit --- .../Scripting/DynamicTexture/DynamicTexture.cs | 61 ++++++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTexture.cs (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTexture.cs b/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTexture.cs new file mode 100644 index 0000000..fce9490 --- /dev/null +++ b/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTexture.cs @@ -0,0 +1,61 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Drawing; +using OpenSim.Region.Framework.Interfaces; + +namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture +{ + public class DynamicTexture : IDynamicTexture + { + public string InputCommands { get; private set; } + public Uri InputUri { get; private set; } + public string InputParams { get; private set; } + public byte[] Data { get; private set; } + public Size Size { get; private set; } + public bool IsReuseable { get; private set; } + + public DynamicTexture(string inputCommands, string inputParams, byte[] data, Size size, bool isReuseable) + { + InputCommands = inputCommands; + InputParams = inputParams; + Data = data; + Size = size; + IsReuseable = isReuseable; + } + + public DynamicTexture(Uri inputUri, string inputParams, byte[] data, Size size, bool isReuseable) + { + InputUri = inputUri; + InputParams = inputParams; + Data = data; + Size = size; + IsReuseable = isReuseable; + } + } +} \ No newline at end of file -- cgit v1.1 From 288baaecaf4933568c53fc052314599d1520bbed Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 7 Sep 2012 00:46:24 +0100 Subject: Add warning chevrons around the GC.Collect added to Warp3DImageModule in commit 5eb2526 Manually calling GC.Collect() really shouldnt' be necessary and is generally regarded as a bad idea. A GC should occur anyway pretty shortly afterwards. However, can leave this in development code for now to see if it does actually make a significant difference rather than simply doing a GC a little earlier. --- OpenSim/Region/CoreModules/World/Warp3DMap/Warp3DImageModule.cs | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/World/Warp3DMap/Warp3DImageModule.cs b/OpenSim/Region/CoreModules/World/Warp3DMap/Warp3DImageModule.cs index ed9b127..2d762fb 100644 --- a/OpenSim/Region/CoreModules/World/Warp3DMap/Warp3DImageModule.cs +++ b/OpenSim/Region/CoreModules/World/Warp3DMap/Warp3DImageModule.cs @@ -208,6 +208,10 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap bitmap = ImageUtils.ResizeImage(origBitmap, viewport.Width, viewport.Height); } + // XXX: It shouldn't really be necesary to force a GC here as one should occur anyway pretty shortly + // afterwards. It's generally regarded as a bad idea to manually GC. If Warp3D is using lots of memory + // then this may be some issue with the Warp3D code itself, though it's also quite possible that generating + // this map tile simply takes a lot of memory. GC.Collect(); m_log.Debug("[WARP 3D IMAGE MODULE]: GC.Collect()"); -- cgit v1.1 From 2ec34580ce3807cede97539488237040e1a8a6cc Mon Sep 17 00:00:00 2001 From: BlueWall Date: Fri, 7 Sep 2012 10:13:51 -0400 Subject: Move addin information to CoreModulePlugin.addin.xml Move the addin information from attributes in the source file to the CoreModulePlugin.xml, which is the standard. This will help us automate addin version dependency information when we make new OpenSim releases. --- OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs | 6 +----- OpenSim/Region/CoreModules/Asset/Tests/FlotsamAssetCacheTests.cs | 2 +- OpenSim/Region/CoreModules/Resources/CoreModulePlugin.addin.xml | 1 + 3 files changed, 3 insertions(+), 6 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs index fab489d..4bce416 100644 --- a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs +++ b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs @@ -49,12 +49,8 @@ using OpenSim.Region.Framework.Scenes; using OpenSim.Services.Interfaces; -[assembly: Addin("FlotsamAssetCache", "1.1")] -[assembly: AddinDependency("OpenSim", "0.5")] - -namespace Flotsam.RegionModules.AssetCache +namespace OpenSim.Region.CoreModules.Asset { - [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] public class FlotsamAssetCache : ISharedRegionModule, IImprovedAssetCache, IAssetService { private static readonly ILog m_log = diff --git a/OpenSim/Region/CoreModules/Asset/Tests/FlotsamAssetCacheTests.cs b/OpenSim/Region/CoreModules/Asset/Tests/FlotsamAssetCacheTests.cs index c91b25f..9276d1a 100644 --- a/OpenSim/Region/CoreModules/Asset/Tests/FlotsamAssetCacheTests.cs +++ b/OpenSim/Region/CoreModules/Asset/Tests/FlotsamAssetCacheTests.cs @@ -35,7 +35,7 @@ using Nini.Config; using NUnit.Framework; using OpenMetaverse; using OpenMetaverse.Assets; -using Flotsam.RegionModules.AssetCache; +using OpenSim.Region.CoreModules.Asset; using OpenSim.Framework; using OpenSim.Region.Framework.Scenes; using OpenSim.Region.Framework.Scenes.Serialization; diff --git a/OpenSim/Region/CoreModules/Resources/CoreModulePlugin.addin.xml b/OpenSim/Region/CoreModules/Resources/CoreModulePlugin.addin.xml index 424e0ab..a09945e 100644 --- a/OpenSim/Region/CoreModules/Resources/CoreModulePlugin.addin.xml +++ b/OpenSim/Region/CoreModules/Resources/CoreModulePlugin.addin.xml @@ -34,6 +34,7 @@ + -- cgit v1.1 From 1f18ce516fe203aaa7a51d3f70d7fff5f6c8a423 Mon Sep 17 00:00:00 2001 From: BlueWall Date: Fri, 7 Sep 2012 11:04:00 -0400 Subject: Move addin information to RegionCombinerModule.addin.xml Move addin information from attributes to RegionCombinerModule.addin.xml to aid in automation of addin dependency tracking. --- .../Region/RegionCombinerModule/RegionCombinerModule.cs | 4 +--- .../Resources/RegionCombinerModule.addin.xml | 14 ++++++++++++++ 2 files changed, 15 insertions(+), 3 deletions(-) create mode 100644 OpenSim/Region/RegionCombinerModule/Resources/RegionCombinerModule.addin.xml (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/RegionCombinerModule/RegionCombinerModule.cs b/OpenSim/Region/RegionCombinerModule/RegionCombinerModule.cs index 3144d76..7a49cd8 100644 --- a/OpenSim/Region/RegionCombinerModule/RegionCombinerModule.cs +++ b/OpenSim/Region/RegionCombinerModule/RegionCombinerModule.cs @@ -39,11 +39,9 @@ using OpenSim.Framework.Console; using OpenSim.Region.Physics.Manager; using Mono.Addins; -[assembly: Addin("RegionCombinerModule", "0.1")] -[assembly: AddinDependency("OpenSim", "0.5")] + namespace OpenSim.Region.RegionCombinerModule { - [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] public class RegionCombinerModule : ISharedRegionModule, IRegionCombinerModule { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); diff --git a/OpenSim/Region/RegionCombinerModule/Resources/RegionCombinerModule.addin.xml b/OpenSim/Region/RegionCombinerModule/Resources/RegionCombinerModule.addin.xml new file mode 100644 index 0000000..6101e63 --- /dev/null +++ b/OpenSim/Region/RegionCombinerModule/Resources/RegionCombinerModule.addin.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + -- cgit v1.1 From 550f6c4ad22b28f7d1722a92472827c199152893 Mon Sep 17 00:00:00 2001 From: BlueWall Date: Fri, 7 Sep 2012 11:39:30 -0400 Subject: Revert "Move addin information to RegionCombinerModule.addin.xml" This reverts commit ab446bc692782b75fd27105fc3370a16b4fc17d8. Need to look into this --- .../Region/RegionCombinerModule/RegionCombinerModule.cs | 4 +++- .../Resources/RegionCombinerModule.addin.xml | 14 -------------- 2 files changed, 3 insertions(+), 15 deletions(-) delete mode 100644 OpenSim/Region/RegionCombinerModule/Resources/RegionCombinerModule.addin.xml (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/RegionCombinerModule/RegionCombinerModule.cs b/OpenSim/Region/RegionCombinerModule/RegionCombinerModule.cs index 7a49cd8..3144d76 100644 --- a/OpenSim/Region/RegionCombinerModule/RegionCombinerModule.cs +++ b/OpenSim/Region/RegionCombinerModule/RegionCombinerModule.cs @@ -39,9 +39,11 @@ using OpenSim.Framework.Console; using OpenSim.Region.Physics.Manager; using Mono.Addins; - +[assembly: Addin("RegionCombinerModule", "0.1")] +[assembly: AddinDependency("OpenSim", "0.5")] namespace OpenSim.Region.RegionCombinerModule { + [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] public class RegionCombinerModule : ISharedRegionModule, IRegionCombinerModule { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); diff --git a/OpenSim/Region/RegionCombinerModule/Resources/RegionCombinerModule.addin.xml b/OpenSim/Region/RegionCombinerModule/Resources/RegionCombinerModule.addin.xml deleted file mode 100644 index 6101e63..0000000 --- a/OpenSim/Region/RegionCombinerModule/Resources/RegionCombinerModule.addin.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - -- cgit v1.1 From 717b11856ed61b9322503fcb6700e3c66d3a697e Mon Sep 17 00:00:00 2001 From: BlueWall Date: Fri, 7 Sep 2012 12:54:12 -0400 Subject: Move addin attributes to RegionCombinerModule.addin.xml Will help in automation of setting version info for addin dependencies. --- .../Region/RegionCombinerModule/RegionCombinerModule.cs | 3 --- .../Resources/RegionCombinerModule.addin.xml | 14 ++++++++++++++ 2 files changed, 14 insertions(+), 3 deletions(-) create mode 100644 OpenSim/Region/RegionCombinerModule/Resources/RegionCombinerModule.addin.xml (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/RegionCombinerModule/RegionCombinerModule.cs b/OpenSim/Region/RegionCombinerModule/RegionCombinerModule.cs index 3144d76..190fca0 100644 --- a/OpenSim/Region/RegionCombinerModule/RegionCombinerModule.cs +++ b/OpenSim/Region/RegionCombinerModule/RegionCombinerModule.cs @@ -39,11 +39,8 @@ using OpenSim.Framework.Console; using OpenSim.Region.Physics.Manager; using Mono.Addins; -[assembly: Addin("RegionCombinerModule", "0.1")] -[assembly: AddinDependency("OpenSim", "0.5")] namespace OpenSim.Region.RegionCombinerModule { - [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] public class RegionCombinerModule : ISharedRegionModule, IRegionCombinerModule { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); diff --git a/OpenSim/Region/RegionCombinerModule/Resources/RegionCombinerModule.addin.xml b/OpenSim/Region/RegionCombinerModule/Resources/RegionCombinerModule.addin.xml new file mode 100644 index 0000000..13cb8b6 --- /dev/null +++ b/OpenSim/Region/RegionCombinerModule/Resources/RegionCombinerModule.addin.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + -- cgit v1.1 From 76dc29dc379036aa44f1ef78782f7ac94760a80f Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Fri, 31 Aug 2012 13:32:22 -0700 Subject: BulletSim: Modify collision flag calls to return the current flags. Track current collision flags in BSPrim. Add BulletSimAPI calls for saving and restoring rigidBodies using construction information structure. --- OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | 9 +++++---- OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs | 16 +++++++++++++--- 2 files changed, 18 insertions(+), 7 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index 6bfce5c..6fcd416 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs @@ -94,6 +94,7 @@ public sealed class BSPrim : BSPhysObject private int _nextCollisionOkTime = 0; long _collidingStep; long _collidingGroundStep; + CollisionFlags m_currentCollisionFlags = 0; public override BulletBody Body { get; set; } @@ -143,6 +144,7 @@ public sealed class BSPrim : BSPhysObject // At the moment, we're still letting BulletSim manage the creation and destruction // of the object. Someday we'll move that into the C# code. Body = new BulletBody(LocalID, BulletSimAPI.GetBodyHandle2(_scene.World.Ptr, LocalID)); + m_currentCollisionFlags = BulletSimAPI.GetCollisionFlags2(Body.Ptr); }); } @@ -483,8 +485,7 @@ public sealed class BSPrim : BSPhysObject // recompute any linkset parameters Linkset.Refresh(this); - CollisionFlags cf = BulletSimAPI.GetCollisionFlags2(Body.Ptr); - DetailLog("{0},BSPrim.SetObjectDynamic,taint,static={1},solid={2},mass={3}, cf={4}", LocalID, IsStatic, IsSolid, mass, cf); + DetailLog("{0},BSPrim.SetObjectDynamic,taint,static={1},solid={2},mass={3}, cf={4}", LocalID, IsStatic, IsSolid, mass, m_currentCollisionFlags); } // prims don't fly @@ -644,7 +645,7 @@ public sealed class BSPrim : BSPhysObject Scene.TaintedObject("BSPrim.SubscribeEvents", delegate() { - BulletSimAPI.AddToCollisionFlags2(Body.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); + m_currentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(Body.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); }); } } @@ -652,7 +653,7 @@ public sealed class BSPrim : BSPhysObject _subscribedEventsMs = 0; Scene.TaintedObject("BSPrim.UnSubscribeEvents", delegate() { - BulletSimAPI.RemoveFromCollisionFlags2(Body.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); + m_currentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(Body.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); }); } public override bool SubscribedEvents() { diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs index a0bad3a..d28c14b 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs @@ -461,10 +461,20 @@ public static extern bool DeleteCollisionShape2(IntPtr world, IntPtr shape); public static extern IntPtr CreateBodyFromShape2(IntPtr sim, IntPtr shape, Vector3 pos, Quaternion rot); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern IntPtr CreateBodyFromShapeAndInfo2(IntPtr sim, IntPtr shape, IntPtr constructionInfo); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern IntPtr CreateBodyWithDefaultMotionState2(IntPtr shape, Vector3 pos, Quaternion rot); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern bool SetBodyShape2(IntPtr sim, IntPtr obj, IntPtr shape); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern IntPtr AllocateBodyInfo2(IntPtr obj); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern void ReleaseBodyInfo2(IntPtr obj); + // ===================================================================================== [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern IntPtr CreateHeightMapInfo2(IntPtr sim, uint id, Vector3 minCoords, Vector3 maxCoords, @@ -604,13 +614,13 @@ public static extern bool SetInterpolation2(IntPtr obj, Vector3 lin, Vector3 ang public static extern CollisionFlags GetCollisionFlags2(IntPtr obj); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern IntPtr SetCollisionFlags2(IntPtr obj, CollisionFlags flags); +public static extern CollisionFlags SetCollisionFlags2(IntPtr obj, CollisionFlags flags); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern IntPtr AddToCollisionFlags2(IntPtr obj, CollisionFlags flags); +public static extern CollisionFlags AddToCollisionFlags2(IntPtr obj, CollisionFlags flags); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern IntPtr RemoveFromCollisionFlags2(IntPtr obj, CollisionFlags flags); +public static extern CollisionFlags RemoveFromCollisionFlags2(IntPtr obj, CollisionFlags flags); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern bool SetMassProps2(IntPtr obj, float mass, Vector3 inertia); -- cgit v1.1 From 189f51233e48026347a3443628350044e4b6fe8a Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Fri, 31 Aug 2012 13:39:29 -0700 Subject: BulletSim: PhysicsActorType() now returns the correct value rather than 'unknown'. --- OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs | 1 + OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs index 747ae71..dc2b595 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs @@ -92,6 +92,7 @@ public class BSCharacter : BSPhysObject _localID = localID; _avName = avName; Scene = parent_scene; + _physicsActorType = (int)ActorTypes.Agent; _position = pos; _size = size; _flying = isFlying; diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index 6fcd416..de182f8 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs @@ -114,6 +114,7 @@ public sealed class BSPrim : BSPhysObject // m_log.DebugFormat("{0}: BSPrim creation of {1}, id={2}", LogHeader, primName, localID); _localID = localID; _avName = primName; + _physicsActorType = (int)ActorTypes.Prim; _scene = parent_scene; _position = pos; _size = size; @@ -444,8 +445,7 @@ public sealed class BSPrim : BSPhysObject } public override int PhysicsActorType { get { return _physicsActorType; } - set { _physicsActorType = value; - } + set { _physicsActorType = value; } } public override bool IsPhysical { get { return _isPhysical; } -- cgit v1.1 From 3c097cb7a9634f711fffb56c0a6912487694aa53 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Thu, 6 Sep 2012 08:05:53 -0700 Subject: BulletSim: Add some comments (gasp) and log messages. --- OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs | 4 ++++ OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs | 4 ++-- OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | 5 +++++ OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs | 4 ++-- 4 files changed, 13 insertions(+), 4 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs b/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs index d9270d1..2e15ced 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs @@ -98,6 +98,10 @@ public abstract class BSConstraint : IDisposable { // m_world.scene.PhysicsLogging.Write("{0},BSConstraint.RecomputeConstraintVariables,taint,enabling,A={1},B={2}", // BSScene.DetailLogZero, Body1.ID, Body2.ID); + + // Setting an object's mass to zero (making it static like when it's selected) + // automatically disables the constraints. + // If enabled, be sure to set the constraint itself to enabled. BulletSimAPI.SetConstraintEnable2(m_constraint.Ptr, m_world.scene.NumericBool(true)); } else diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs index b04e1b6..3111258 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs @@ -245,8 +245,8 @@ public class BSLinkset // their constraints have not been created yet. // Caused by the fact that m_children is built at run time but building constraints // happens at taint time. - // m_physicsScene.Logger.ErrorFormat("[BULLETSIM LINKSET] RecomputeLinksetConstraintVariables: constraint not found for root={0}, child={1}", - // m_linksetRoot.Body.ID, child.Body.ID); + // m_physicsScene.Logger.ErrorFormat("{0} RecomputeLinksetConstraintVariables: constraint not found for root={1}, child={2}", + // LogHeader, m_linksetRoot.Body.ID, child.Body.ID); } } } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index de182f8..01f231b 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs @@ -472,6 +472,10 @@ public sealed class BSPrim : BSPhysObject // Make gravity work if the object is physical and not selected // No locking here because only called when it is safe + // There are three flags we're interested in: + // IsStatic: Object does not move, otherwise the object has mass and moves + // isSolid: other objects bounce off of this object + // collisionEvents: whether this object returns collision events private void SetObjectDynamic() { // If it's becoming dynamic, it will need hullness @@ -481,6 +485,7 @@ public sealed class BSPrim : BSPhysObject float mass = IsStatic ? 0f : _mass; BulletSimAPI.SetObjectProperties(_scene.WorldID, LocalID, IsStatic, IsSolid, SubscribedEvents(), mass); + m_currentCollisionFlags = BulletSimAPI.GetCollisionFlags2(Body.Ptr); // recompute any linkset parameters Linkset.Refresh(this); diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs index ab45f8f..4285073 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs @@ -408,8 +408,8 @@ public class BSTerrainManager int mapIndex = (int)regionY * (int)mapInfo.sizeY + (int)regionX; ret = mapInfo.heightMap[mapIndex]; m_terrainModified = false; - DetailLog("{0},BSTerrainManager.GetTerrainHeightAtXY,bX={1},baseY={2},szX={3},szY={4},regX={5},regY={6},index={7},ht={8}", - BSScene.DetailLogZero, offsetX, offsetY, mapInfo.sizeX, mapInfo.sizeY, regionX, regionY, mapIndex, ret); + // DetailLog("{0},BSTerrainManager.GetTerrainHeightAtXY,bX={1},baseY={2},szX={3},szY={4},regX={5},regY={6},index={7},ht={8}", + // BSScene.DetailLogZero, offsetX, offsetY, mapInfo.sizeX, mapInfo.sizeY, regionX, regionY, mapIndex, ret); } else { -- cgit v1.1 From 126eae71009001c5455e4896cf12317422bbac51 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Fri, 7 Sep 2012 15:46:14 -0700 Subject: BulletSim: Add Bullet body and shape to BSPhysObject and rename 'Body' to 'BSBody' for disambiguation when reading code. Complete the API2 interface so nearly all methods on bullet classes are available to the managed code. The efficient single call simulation step is kept in place while all other creation/destruction/parameterization can be done in the managed code. --- .../Region/Physics/BulletSPlugin/BSCharacter.cs | 11 +- OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs | 10 +- .../Region/Physics/BulletSPlugin/BSPhysObject.cs | 6 +- OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | 96 ++++- .../Physics/BulletSPlugin/BSTerrainManager.cs | 4 +- .../Region/Physics/BulletSPlugin/BulletSimAPI.cs | 440 +++++++++++++++++++-- 6 files changed, 505 insertions(+), 62 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs index dc2b595..fa22c78 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs @@ -73,7 +73,8 @@ public class BSCharacter : BSPhysObject private bool _kinematic; private float _buoyancy; - public override BulletBody Body { get; set; } + public override BulletBody BSBody { get; set; } + public override BulletShape BSShape { get; set; } public override BSLinkset Linkset { get; set; } private int _subscribedEventsMs = 0; @@ -129,9 +130,9 @@ public class BSCharacter : BSPhysObject // Set the buoyancy for flying. This will be refactored when all the settings happen in C# BulletSimAPI.SetObjectBuoyancy(Scene.WorldID, LocalID, _buoyancy); - Body = new BulletBody(LocalID, BulletSimAPI.GetBodyHandle2(Scene.World.Ptr, LocalID)); + BSBody = new BulletBody(LocalID, BulletSimAPI.GetBodyHandle2(Scene.World.Ptr, LocalID)); // avatars get all collisions no matter what (makes walking on ground and such work) - BulletSimAPI.AddToCollisionFlags2(Body.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); + BulletSimAPI.AddToCollisionFlags2(BSBody.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); }); return; @@ -441,7 +442,7 @@ public class BSCharacter : BSPhysObject Scene.TaintedObject("BSCharacter.AddForce", delegate() { DetailLog("{0},BSCharacter.setAddForce,taint,addedForce={1}", LocalID, _force); - BulletSimAPI.AddObjectForce2(Body.Ptr, _force); + BulletSimAPI.SetObjectForce2(BSBody.Ptr, _force); }); } else @@ -466,7 +467,7 @@ public class BSCharacter : BSPhysObject Scene.TaintedObject("BSCharacter.SubscribeEvents", delegate() { - BulletSimAPI.AddToCollisionFlags2(Body.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); + BulletSimAPI.AddToCollisionFlags2(BSBody.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); }); } } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs index 3111258..5f6601d 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs @@ -233,7 +233,7 @@ public class BSLinkset foreach (BSPhysObject child in m_children) { BSConstraint constrain; - if (m_physicsScene.Constraints.TryGetConstraint(LinksetRoot.Body, child.Body, out constrain)) + if (m_physicsScene.Constraints.TryGetConstraint(LinksetRoot.BSBody, child.BSBody, out constrain)) { // DetailLog("{0},BSLinkset.RecomputeLinksetConstraintVariables,taint,child={1},mass={2},A={3},B={4}", // LinksetRoot.LocalID, child.LocalID, linksetMass, constrain.Body1.ID, constrain.Body2.ID); @@ -327,7 +327,7 @@ public class BSLinkset DetailLog("{0},PhysicallyLinkAChildToRoot,taint,root={1},child={2},rLoc={3},cLoc={4},midLoc={5}", rootPrim.LocalID, rootPrim.LocalID, childPrim.LocalID, rootPrim.Position, childPrim.Position, midPoint); BS6DofConstraint constrain = new BS6DofConstraint( - m_physicsScene.World, rootPrim.Body, childPrim.Body, + m_physicsScene.World, rootPrim.BSBody, childPrim.BSBody, midPoint, true, true @@ -388,10 +388,10 @@ public class BSLinkset DetailLog("{0},PhysicallyUnlinkAChildFromRoot,taint,root={1},child={2}", rootPrim.LocalID, rootPrim.LocalID, childPrim.LocalID); // Find the constraint for this link and get rid of it from the overall collection and from my list - m_physicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.Body, childPrim.Body); + m_physicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.BSBody, childPrim.BSBody); // Make the child refresh its location - BulletSimAPI.PushUpdate2(childPrim.Body.Ptr); + BulletSimAPI.PushUpdate2(childPrim.BSBody.Ptr); } // Remove linkage between myself and any possible children I might have @@ -400,7 +400,7 @@ public class BSLinkset { DetailLog("{0},PhysicallyUnlinkAllChildren,taint", rootPrim.LocalID); - m_physicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.Body); + m_physicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.BSBody); } // Invoke the detailed logger and output something if it's enabled. diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs index ef463ca..e411fcb 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs @@ -48,7 +48,11 @@ public abstract class BSPhysObject : PhysicsActor // Return the object mass without calculating it or side effects public abstract float MassRaw { get; } - public abstract BulletBody Body { get; set; } + // Reference to the physical body (btCollisionObject) of this object + public abstract BulletBody BSBody { get; set; } + // Reference to the physical shape (btCollisionShape) of this object + public abstract BulletShape BSShape { get; set; } + public abstract void ZeroMotion(); public virtual void StepVehicle(float timeStep) { } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index 01f231b..6d0af63 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs @@ -96,7 +96,8 @@ public sealed class BSPrim : BSPhysObject long _collidingGroundStep; CollisionFlags m_currentCollisionFlags = 0; - public override BulletBody Body { get; set; } + public override BulletBody BSBody { get; set; } + public override BulletShape BSShape { get; set; } private BSDynamics _vehicle; @@ -144,8 +145,9 @@ public sealed class BSPrim : BSPhysObject // Get the pointer to the physical body for this object. // At the moment, we're still letting BulletSim manage the creation and destruction // of the object. Someday we'll move that into the C# code. - Body = new BulletBody(LocalID, BulletSimAPI.GetBodyHandle2(_scene.World.Ptr, LocalID)); - m_currentCollisionFlags = BulletSimAPI.GetCollisionFlags2(Body.Ptr); + BSBody = new BulletBody(LocalID, BulletSimAPI.GetBodyHandle2(_scene.World.Ptr, LocalID)); + BSShape = new BulletShape(BulletSimAPI.GetCollisionShape2(BSBody.Ptr)); + m_currentCollisionFlags = BulletSimAPI.GetCollisionFlags2(BSBody.Ptr); }); } @@ -261,10 +263,10 @@ public sealed class BSPrim : BSPhysObject _rotationalVelocity = OMV.Vector3.Zero; // Zero some other properties directly into the physics engine - BulletSimAPI.SetVelocity2(Body.Ptr, OMV.Vector3.Zero); - BulletSimAPI.SetAngularVelocity2(Body.Ptr, OMV.Vector3.Zero); - BulletSimAPI.SetInterpolation2(Body.Ptr, OMV.Vector3.Zero, OMV.Vector3.Zero); - BulletSimAPI.ClearForces2(Body.Ptr); + BulletSimAPI.SetLinearVelocity2(BSBody.Ptr, OMV.Vector3.Zero); + BulletSimAPI.SetAngularVelocity2(BSBody.Ptr, OMV.Vector3.Zero); + BulletSimAPI.SetInterpolationVelocity2(BSBody.Ptr, OMV.Vector3.Zero, OMV.Vector3.Zero); + BulletSimAPI.ClearForces2(BSBody.Ptr); } public override void LockAngularMotion(OMV.Vector3 axis) @@ -327,7 +329,7 @@ public sealed class BSPrim : BSPhysObject { DetailLog("{0},BSPrim.setForce,taint,force={1}", LocalID, _force); // BulletSimAPI.SetObjectForce(_scene.WorldID, _localID, _force); - BulletSimAPI.SetObjectForce2(Body.Ptr, _force); + BulletSimAPI.SetObjectForce2(BSBody.Ptr, _force); }); } } @@ -472,10 +474,11 @@ public sealed class BSPrim : BSPhysObject // Make gravity work if the object is physical and not selected // No locking here because only called when it is safe - // There are three flags we're interested in: - // IsStatic: Object does not move, otherwise the object has mass and moves - // isSolid: other objects bounce off of this object - // collisionEvents: whether this object returns collision events + // There are four flags we're interested in: + // IsStatic: Object does not move, otherwise the object has mass and moves + // isSolid: other objects bounce off of this object + // isVolumeDetect: other objects pass through but can generate collisions + // collisionEvents: whether this object returns collision events private void SetObjectDynamic() { // If it's becoming dynamic, it will need hullness @@ -485,14 +488,68 @@ public sealed class BSPrim : BSPhysObject float mass = IsStatic ? 0f : _mass; BulletSimAPI.SetObjectProperties(_scene.WorldID, LocalID, IsStatic, IsSolid, SubscribedEvents(), mass); - m_currentCollisionFlags = BulletSimAPI.GetCollisionFlags2(Body.Ptr); + /* + BulletSimAPI.RemoveObjectFromWorld2(Scene.World.Ptr, BSBody.Ptr); + + // Set up the object physicalness (static or dynamic) + MakeDynamic(); + + // Make solid or not and arrange for collisions, etc + MakeSolid(); - // recompute any linkset parameters + m_currentCollisionFlags = BulletSimAPI.GetCollisionFlags2(BSBody.Ptr); + + BulletSimAPI.AddObjectToWorld2(Scene.World.Ptr, BSBody.Ptr); + */ + + // Recompute any linkset parameters. + // When going from non-physical to physical, this re-enables the constraints that + // had been automatically disabled when the mass was set to zero. Linkset.Refresh(this); DetailLog("{0},BSPrim.SetObjectDynamic,taint,static={1},solid={2},mass={3}, cf={4}", LocalID, IsStatic, IsSolid, mass, m_currentCollisionFlags); } + // "Making dynamic" means changing to and from static. + // When static, gravity does not effect the object and it is fixed in space. + // When dynamic, the object can fall and be pushed by others. + // This is independent of its 'solidness' which controls what passes through + // this object and what interacts with it. + private void MakeDynamic() + { + if (IsStatic) + { + // Become a Bullet 'static' object type + BulletSimAPI.AddToCollisionFlags2(BSBody.Ptr, CollisionFlags.CF_STATIC_OBJECT); + // Stop all movement + BulletSimAPI.ClearAllForces2(BSBody.Ptr); + // Mass is zero which disables a bunch of physics stuff in Bullet + BulletSimAPI.SetMassProps2(BSBody.Ptr, 0f, OMV.Vector3.Zero); + // There is no inertia in a static object + BulletSimAPI.UpdateInertiaTensor2(BSBody.Ptr); + // The activation state is 'sleeping' so Bullet will not try to act on it + BulletSimAPI.ForceActivationState2(BSBody.Ptr, ActivationState.ISLAND_SLEEPING); + } + else + { + // Not a Bullet static object + BulletSimAPI.RemoveFromCollisionFlags2(BSBody.Ptr, CollisionFlags.CF_STATIC_OBJECT); + // A dynamic object has mass + BulletSimAPI.SetMassProps2(BSBody.Ptr, _mass, OMV.Vector3.Zero); + // The shape is interesting and has mass and a center of gravity + IntPtr collisionShapePtr = BulletSimAPI.GetCollisionShape2(BSBody.Ptr); + BulletSimAPI.CalculateLocalInertia2(collisionShapePtr, _mass, OMV.Vector3.Zero); + // Inertia is based on our new mass + BulletSimAPI.UpdateInertiaTensor2(BSBody.Ptr); + // Force activation of the object so Bullet will act on it. + BulletSimAPI.Activate2(BSBody.Ptr, true); + } + } + + private void MakeSolid() + { + } + // prims don't fly public override bool Flying { get { return _flying; } @@ -615,7 +672,7 @@ public sealed class BSPrim : BSPhysObject } else { - m_log.WarnFormat("{0}: Got a NaN force applied to a Character", LogHeader); + m_log.WarnFormat("{0}: Got a NaN force applied to a prim. LocalID={1}", LogHeader, LocalID); return; } _scene.TaintedObject("BSPrim.AddForce", delegate() @@ -630,7 +687,8 @@ public sealed class BSPrim : BSPhysObject m_accumulatedForces.Clear(); } DetailLog("{0},BSPrim.AddObjectForce,taint,force={1}", LocalID, _force); - BulletSimAPI.AddObjectForce2(Body.Ptr, fSum); + // For unknown reason, "ApplyCentralForce" is really additive. + BulletSimAPI.ApplyCentralForce2(BSBody.Ptr, fSum); }); } @@ -650,7 +708,7 @@ public sealed class BSPrim : BSPhysObject Scene.TaintedObject("BSPrim.SubscribeEvents", delegate() { - m_currentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(Body.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); + m_currentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(BSBody.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); }); } } @@ -658,7 +716,7 @@ public sealed class BSPrim : BSPhysObject _subscribedEventsMs = 0; Scene.TaintedObject("BSPrim.UnSubscribeEvents", delegate() { - m_currentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(Body.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); + m_currentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(BSBody.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); }); } public override bool SubscribedEvents() { @@ -1243,7 +1301,7 @@ public sealed class BSPrim : BSPhysObject bool ret = BulletSimAPI.CreateObject(_scene.WorldID, shape); // the CreateObject() may have recreated the rigid body. Make sure we have the latest. - Body = new BulletBody(LocalID, BulletSimAPI.GetBodyHandle2(_scene.World.Ptr, LocalID)); + BSBody = new BulletBody(LocalID, BulletSimAPI.GetBodyHandle2(_scene.World.Ptr, LocalID)); return ret; } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs index 4285073..47d7199 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs @@ -403,8 +403,8 @@ public class BSTerrainManager { float regionX = tX - offsetX; float regionY = tY - offsetY; - if (regionX > mapInfo.sizeX) regionX = 0; - if (regionY > mapInfo.sizeY) regionY = 0; + if (regionX >= mapInfo.sizeX || regionX < 0f) regionX = 0; + if (regionY >= mapInfo.sizeY || regionY < 0f) regionY = 0; int mapIndex = (int)regionY * (int)mapInfo.sizeY + (int)regionX; ret = mapInfo.heightMap[mapIndex]; m_terrainModified = false; diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs index d28c14b..e579cf2 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs @@ -218,7 +218,20 @@ public struct ConfigurationParameters public const float numericFalse = 0f; } -// Values used by Bullet and BulletSim to control collisions + +// The states a bullet collision object can have +public enum ActivationState : uint +{ + ACTIVE_TAG = 1, + ISLAND_SLEEPING, + WANTS_DEACTIVATION, + DISABLE_DEACTIVATION, + DISABLE_SIMULATION +} + +// Values used by Bullet and BulletSim to control object properties. +// Bullet's "CollisionFlags" has more to do with operations on the +// object (if collisions happen, if gravity effects it, ...). public enum CollisionFlags : uint { CF_STATIC_OBJECT = 1 << 0, @@ -233,8 +246,75 @@ public enum CollisionFlags : uint BS_VOLUME_DETECT_OBJECT = 1 << 11, BS_PHANTOM_OBJECT = 1 << 12, BS_PHYSICAL_OBJECT = 1 << 13, + BS_TERRAIN_OBJECT = 1 << 14, + BS_NONE = 0, + BS_ALL = 0xFFFFFFFF +}; + +// Values for collisions groups and masks +public enum CollisionFilterGroups : uint +{ + NoneFilter = 0, + DefaultFilter = 1 << 0, + StaticFilter = 1 << 1, + KinematicFilter = 1 << 2, + DebrisFilter = 1 << 3, + SensorTrigger = 1 << 4, + CharacterFilter = 1 << 5, + AllFilter = 0xFFFFFFFF, + // Filter groups defined by BulletSim + GroundPlaneFilter = 1 << 10, + TerrainFilter = 1 << 11, + RaycastFilter = 1 << 12, + SolidFilter = 1 << 13, }; + // For each type, we first clear and then set the collision flags +public enum ClearCollisionFlag : uint +{ + Terrain = CollisionFlags.BS_ALL, + Phantom = CollisionFlags.BS_ALL, + VolumeDetect = CollisionFlags.BS_ALL, + PhysicalObject = CollisionFlags.BS_ALL, + StaticObject = CollisionFlags.BS_ALL +} + +public enum SetCollisionFlag : uint +{ + Terrain = CollisionFlags.CF_STATIC_OBJECT + | CollisionFlags.BS_TERRAIN_OBJECT, + Phantom = CollisionFlags.CF_STATIC_OBJECT + | CollisionFlags.BS_PHANTOM_OBJECT + | CollisionFlags.CF_NO_CONTACT_RESPONSE, + VolumeDetect = CollisionFlags.CF_STATIC_OBJECT + | CollisionFlags.BS_VOLUME_DETECT_OBJECT + | CollisionFlags.CF_NO_CONTACT_RESPONSE, + PhysicalObject = CollisionFlags.BS_PHYSICAL_OBJECT, + StaticObject = CollisionFlags.CF_STATIC_OBJECT, +} + +// Collision filters used for different types of objects +public enum SetCollisionFilter : uint +{ + Terrain = CollisionFilterGroups.AllFilter, + Phantom = CollisionFilterGroups.GroundPlaneFilter + | CollisionFilterGroups.TerrainFilter, + VolumeDetect = CollisionFilterGroups.AllFilter, + PhysicalObject = CollisionFilterGroups.AllFilter, + StaticObject = CollisionFilterGroups.AllFilter, +} + +// Collision masks used for different types of objects +public enum SetCollisionMask : uint +{ + Terrain = CollisionFilterGroups.AllFilter, + Phantom = CollisionFilterGroups.GroundPlaneFilter + | CollisionFilterGroups.TerrainFilter, + VolumeDetect = CollisionFilterGroups.AllFilter, + PhysicalObject = CollisionFilterGroups.AllFilter, + StaticObject = CollisionFilterGroups.AllFilter +} + // CFM controls the 'hardness' of the constraint. 0=fixed, 0..1=violatable. Default=0 // ERP controls amount of correction per tick. Usable range=0.1..0.8. Default=0.2. public enum ConstraintParams : int @@ -347,6 +427,7 @@ public static extern bool SetObjectVelocity(uint worldID, uint id, Vector3 veloc [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern bool SetObjectAngularVelocity(uint worldID, uint id, Vector3 angularVelocity); +// Set the current force acting on the object [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern bool SetObjectForce(uint worldID, uint id, Vector3 force); @@ -403,6 +484,7 @@ public static extern void SetDebugLogCallback(DebugLogCallback callback); // The names have a "2" tacked on. This will be removed as the C# code gets rebuilt // and the old code is removed. +// Functions use while converting from API1 to API2. Can be removed when totally converted. [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern IntPtr GetSimHandle2(uint worldID); @@ -413,6 +495,7 @@ public static extern IntPtr GetBodyHandleWorldID2(uint worldID, uint id); public static extern IntPtr GetBodyHandle2(IntPtr world, uint id); // =============================================================================== +// Initialization and simulation [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern IntPtr Initialize2(Vector3 maxPosition, IntPtr parms, int maxCollisions, IntPtr collisionArray, @@ -438,6 +521,7 @@ public static extern int PhysicsStep2(IntPtr world, float timeStep, int maxSubSt public static extern bool PushUpdate2(IntPtr obj); // ===================================================================================== +// Mesh, hull, shape and body creation helper routines [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern IntPtr CreateMeshShape2(IntPtr world, int indicesCount, [MarshalAs(UnmanagedType.LPArray)] int[] indices, @@ -467,15 +551,19 @@ public static extern IntPtr CreateBodyFromShapeAndInfo2(IntPtr sim, IntPtr shape public static extern IntPtr CreateBodyWithDefaultMotionState2(IntPtr shape, Vector3 pos, Quaternion rot); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern bool SetBodyShape2(IntPtr sim, IntPtr obj, IntPtr shape); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern IntPtr AllocateBodyInfo2(IntPtr obj); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern void ReleaseBodyInfo2(IntPtr obj); +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern void DestroyObject2(IntPtr sim, IntPtr obj); + // ===================================================================================== +// Terrain creation and helper routines +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern void DumpMapInfo(IntPtr sim, IntPtr manInfo); + [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern IntPtr CreateHeightMapInfo2(IntPtr sim, uint id, Vector3 minCoords, Vector3 maxCoords, [MarshalAs(UnmanagedType.LPArray)] float[] heightMap, float collisionMargin); @@ -494,6 +582,7 @@ public static extern IntPtr CreateGroundPlaneShape2(uint id, float height, float public static extern IntPtr CreateTerrainShape2(IntPtr mapInfo); // ===================================================================================== +// Constraint creation and helper routines [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern IntPtr Create6DofConstraint2(IntPtr world, IntPtr obj1, IntPtr obj2, Vector3 frame1loc, Quaternion frame1rot, @@ -546,69 +635,145 @@ public static extern bool SetConstraintParam2(IntPtr constrain, ConstraintParams public static extern bool DestroyConstraint2(IntPtr world, IntPtr constrain); // ===================================================================================== +// btCollisionWorld entries +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern void UpdateSingleAabb2(IntPtr world, IntPtr obj); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern void UpdateAabbs2(IntPtr world); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern bool GetForceUpdateAllAabbs2(IntPtr world); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern void SetForceUpdateAllAabbs2(IntPtr world, bool force); + +// ===================================================================================== +// btDynamicsWorld entries [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern bool AddObjectToWorld2(IntPtr world, IntPtr obj); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern bool RemoveObjectFromWorld2(IntPtr world, IntPtr obj); +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern bool AddConstraintToWorld2(IntPtr world, IntPtr constrain, bool disableCollisionsBetweenLinkedObjects); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern bool RemoveConstraintFromWorld2(IntPtr world, IntPtr constrain); // ===================================================================================== +// btCollisionObject entries +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern Vector3 GetAnisotripicFriction2(IntPtr constrain); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern Vector3 SetAnisotripicFriction2(IntPtr constrain, Vector3 frict); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern bool HasAnisotripicFriction2(IntPtr constrain); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern void SetContactProcessingThreshold2(IntPtr obj, float val); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern float GetContactProcessingThreshold2(IntPtr obj); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern bool IsStaticObject2(IntPtr obj); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern bool IsKinematicObject2(IntPtr obj); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern bool IsStaticOrKinematicObject2(IntPtr obj); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern bool HasContactResponse2(IntPtr obj); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern void SetCollisionShape2(IntPtr sim, IntPtr obj, IntPtr shape); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern IntPtr GetCollisionShape2(IntPtr obj); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern int GetActivationState2(IntPtr obj); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern void SetActivationState2(IntPtr obj, int state); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern void SetDeactivationTime2(IntPtr obj, float dtime); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern float GetDeactivationTime2(IntPtr obj); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern void ForceActivationState2(IntPtr obj, ActivationState state); + [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern void Activate2(IntPtr obj, bool forceActivation); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern Vector3 GetPosition2(IntPtr obj); +public static extern bool IsActive2(IntPtr obj); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern Quaternion GetOrientation2(IntPtr obj); +public static extern void SetRestitution2(IntPtr obj, float val); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern bool SetTranslation2(IntPtr obj, Vector3 position, Quaternion rotation); +public static extern float GetRestitution2(IntPtr obj); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern bool SetVelocity2(IntPtr obj, Vector3 velocity); +public static extern void SetFriction2(IntPtr obj, float val); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern bool SetAngularVelocity2(IntPtr obj, Vector3 angularVelocity); +public static extern float GetFriction2(IntPtr obj); + /* Haven't defined the type 'Transform' [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern bool SetObjectForce2(IntPtr obj, Vector3 force); +public static extern Transform GetWorldTransform2(IntPtr obj); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern bool AddObjectForce2(IntPtr obj, Vector3 force); +public static extern void setWorldTransform2(IntPtr obj, Transform trans); + */ [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern bool SetCcdMotionThreshold2(IntPtr obj, float val); +public static extern Vector3 GetPosition2(IntPtr obj); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern bool SetCcdSweepSphereRadius2(IntPtr obj, float val); +public static extern Quaternion GetOrientation2(IntPtr obj); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern bool SetDamping2(IntPtr obj, float lin_damping, float ang_damping); +public static extern void SetTranslation2(IntPtr obj, Vector3 position, Quaternion rotation); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern bool SetDeactivationTime2(IntPtr obj, float val); +public static extern IntPtr GetBroadphaseHandle2(IntPtr obj); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern bool SetSleepingThresholds2(IntPtr obj, float lin_threshold, float ang_threshold); +public static extern void SetBroadphaseHandle2(IntPtr obj, IntPtr handle); + /* [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern bool SetContactProcessingThreshold2(IntPtr obj, float val); +public static extern Transform GetInterpolationWorldTransform2(IntPtr obj); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern bool SetFriction2(IntPtr obj, float val); +public static extern void SetInterpolationWorldTransform2(IntPtr obj, Transform trans); + */ [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern bool SetHitFraction2(IntPtr obj, float val); +public static extern void SetInterpolationLinearVelocity2(IntPtr obj, Vector3 vel); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern bool SetRestitution2(IntPtr obj, float val); +public static extern void SetInterpolationAngularVelocity2(IntPtr obj, Vector3 vel); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern bool SetLinearVelocity2(IntPtr obj, Vector3 val); +public static extern void SetInterpolationVelocity2(IntPtr obj, Vector3 linearVel, Vector3 angularVel); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern bool SetInterpolation2(IntPtr obj, Vector3 lin, Vector3 ang); +public static extern float GetHitFraction2(IntPtr obj); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern void SetHitFraction2(IntPtr obj, float val); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern CollisionFlags GetCollisionFlags2(IntPtr obj); @@ -623,30 +788,245 @@ public static extern CollisionFlags AddToCollisionFlags2(IntPtr obj, CollisionFl public static extern CollisionFlags RemoveFromCollisionFlags2(IntPtr obj, CollisionFlags flags); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern bool SetMassProps2(IntPtr obj, float mass, Vector3 inertia); +public static extern float GetCcdMotionThreshold2(IntPtr obj); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern void SetCcdMotionThreshold2(IntPtr obj, float val); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern float GetCcdSweepSphereRadius2(IntPtr obj); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern void SetCcdSweepSphereRadius2(IntPtr obj, float val); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern IntPtr GetUserPointer2(IntPtr obj); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern void SetUserPointer2(IntPtr obj, IntPtr val); + +// ===================================================================================== +// btRigidBody entries +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern void ApplyGravity2(IntPtr obj); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern void SetGravity2(IntPtr obj, Vector3 val); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern Vector3 GetGravity2(IntPtr obj); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern void SetDamping2(IntPtr obj, float lin_damping, float ang_damping); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern float GetLinearDamping2(IntPtr obj); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern float GetAngularDamping2(IntPtr obj); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern float GetLinearSleepingThreshold2(IntPtr obj); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern float GetAngularSleepingThreshold2(IntPtr obj); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern void ApplyDamping2(IntPtr obj, float timeStep); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern void SetMassProps2(IntPtr obj, float mass, Vector3 inertia); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern bool UpdateInertiaTensor2(IntPtr obj); +public static extern Vector3 GetLinearFactor2(IntPtr obj); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern bool SetGravity2(IntPtr obj, Vector3 val); +public static extern void SetLinearFactor2(IntPtr obj, Vector3 factor); + /* [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern IntPtr ClearForces2(IntPtr obj); +public static extern void SetCenterOfMassTransform2(IntPtr obj, Transform trans); + */ [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern IntPtr ClearAllForces2(IntPtr obj); +public static extern void SetCenterOfMassByPosRot2(IntPtr obj, Vector3 pos, Quaternion rot); +// Add a force to the object as if its mass is one. [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern bool SetMargin2(IntPtr obj, float val); +public static extern void ApplyCentralForce2(IntPtr obj, Vector3 force); +// Set the force being applied to the object as if its mass is one. [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern bool UpdateSingleAabb2(IntPtr world, IntPtr obj); +public static extern void SetObjectForce2(IntPtr obj, Vector3 force); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern bool DestroyObject2(IntPtr world, IntPtr obj); +public static extern Vector3 GetTotalForce2(IntPtr obj); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern Vector3 GetTotalTorque2(IntPtr obj); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern Vector3 GetInvInertiaDiagLocal2(IntPtr obj); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern void SetInvInertiaDiagLocal2(IntPtr obj, Vector3 inert); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern void SetSleepingThresholds2(IntPtr obj, float lin_threshold, float ang_threshold); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern void ApplyTorque2(IntPtr obj, Vector3 torque); + +// Apply force at the given point. Will add torque to the object. +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern void ApplyForce2(IntPtr obj, Vector3 force, Vector3 pos); + +// Apply impulse to the object. Same as "ApplycentralForce" but force scaled by object's mass. +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern void ApplyCentralImpulse2(IntPtr obj, Vector3 imp); + +// Apply impulse to the object's torque. Force is scaled by object's mass. +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern void ApplyTorqueImpulse2(IntPtr obj, Vector3 imp); + +// Apply impulse at the point given. For is scaled by object's mass and effects both linear and angular forces. +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern void ApplyImpulse2(IntPtr obj, Vector3 imp, Vector3 pos); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern void ClearForces2(IntPtr obj); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern void ClearAllForces2(IntPtr obj); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern void UpdateInertiaTensor2(IntPtr obj); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern Vector3 GetCenterOfMassPosition2(IntPtr obj); + + /* +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern Transform GetCenterOfMassTransform2(IntPtr obj); + */ + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern Vector3 GetLinearVelocity2(IntPtr obj); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern Vector3 GetAngularVelocity2(IntPtr obj); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern void SetLinearVelocity2(IntPtr obj, Vector3 val); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern void SetAngularVelocity2(IntPtr obj, Vector3 angularVelocity); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern Vector3 GetVelocityInLocalPoint2(IntPtr obj, Vector3 pos); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern void Translate2(IntPtr obj, Vector3 trans); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern void UpdateDeactivation2(IntPtr obj, float timeStep); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern bool WantsSleeping2(IntPtr obj); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern void SetAngularFactor2(IntPtr obj, float factor); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern void SetAngularFactorV2(IntPtr obj, Vector3 factor); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern Vector3 GetAngularFactor2(IntPtr obj); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern bool IsInWorld2(IntPtr obj); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern void AddConstraintRef2(IntPtr obj, IntPtr constrain); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern void RemoveConstraintRef2(IntPtr obj, IntPtr constrain); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern IntPtr GetConstraintRef2(IntPtr obj, int index); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern int GetNumConstraintRefs2(IntPtr obj); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern Vector3 GetDeltaLinearVelocity2(IntPtr obj); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern Vector3 GetDeltaAngularVelocity2(IntPtr obj); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern Vector3 GetPushVelocity2(IntPtr obj); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern Vector3 GetTurnVelocity2(IntPtr obj); + +// ===================================================================================== +// btCollisionShape entries + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern float GetAngularMotionDisc2(IntPtr shape); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern float GetContactBreakingThreshold2(IntPtr shape, float defaultFactor); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern bool IsPolyhedral2(IntPtr shape); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern bool IsConvex2d2(IntPtr shape); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern bool IsConvex2(IntPtr shape); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern bool IsNonMoving2(IntPtr shape); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern bool IsConcave2(IntPtr shape); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern bool IsCompound2(IntPtr shape); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern bool IsSoftBody2(IntPtr shape); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern bool IsInfinite2(IntPtr shape); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern void SetLocalScaling2(IntPtr shape, Vector3 scale); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern Vector3 GetLocalScaling2(IntPtr shape); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern void CalculateLocalInertia2(IntPtr shape, float mass, Vector3 inertia); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern int GetShapeType2(IntPtr shape); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern void SetMargin2(IntPtr shape, float val); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern float GetMargin2(IntPtr shape); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern void SetCollisionFilterMask(IntPtr shape, uint filter, uint mask); + +// ===================================================================================== +// Debugging +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern void DumpPhysicsStatistics2(IntPtr sim); } -- cgit v1.1 From 874bde366aa3f834957f757aa56a7634becb4415 Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Thu, 6 Sep 2012 10:54:45 +0100 Subject: 4096 is used in various places as the maximum height of a region, refactoring to be a constant --- OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (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 be22cb4..83c9739 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -1948,7 +1948,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api pos.x > (Constants.RegionSize + 10) || // return FALSE if more than 10 meters into a east-adjacent region. pos.y < -10.0 || // return FALSE if more than 10 meters into a south-adjacent region. pos.y > (Constants.RegionSize + 10) || // return FALSE if more than 10 meters into a north-adjacent region. - pos.z > 4096 // return FALSE if altitude than 4096m + pos.z > Constants.RegionHeight // return FALSE if altitude than 4096m ) ) { -- cgit v1.1 From e041f09750419f60c819ee7e7a99044fe43a811c Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Thu, 6 Sep 2012 11:45:52 +0100 Subject: refactoring to allow Scene.GetLandData to accept Vector3 as an argument. Note that the prior work on LSL_Vector implicit operators means one does not need to explicitly cast a LSL_Vector to Vector3 --- OpenSim/Region/Framework/Scenes/Scene.cs | 10 ++++++++++ .../Voice/FreeSwitchVoice/FreeSwitchVoiceModule.cs | 2 +- .../Avatar/Voice/VivoxVoice/VivoxVoiceModule.cs | 2 +- .../ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 18 +++++++++--------- .../ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs | 2 +- 5 files changed, 22 insertions(+), 12 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index a2d553d..ff3d3af 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -4334,6 +4334,16 @@ namespace OpenSim.Region.Framework.Scenes return LandChannel.GetLandObject(x, y).LandData; } + /// + /// Get LandData by position. + /// + /// + /// + public LandData GetLandData(Vector3 pos) + { + return GetLandData(pos.X, pos.Y); + } + public LandData GetLandData(uint x, uint y) { m_log.DebugFormat("[SCENE]: returning land for {0},{1}", x, y); diff --git a/OpenSim/Region/OptionalModules/Avatar/Voice/FreeSwitchVoice/FreeSwitchVoiceModule.cs b/OpenSim/Region/OptionalModules/Avatar/Voice/FreeSwitchVoice/FreeSwitchVoiceModule.cs index 7fafdc6..37ab35a 100644 --- a/OpenSim/Region/OptionalModules/Avatar/Voice/FreeSwitchVoice/FreeSwitchVoiceModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/Voice/FreeSwitchVoice/FreeSwitchVoiceModule.cs @@ -447,7 +447,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.FreeSwitchVoice // settings allow voice, then whether parcel allows // voice, if all do retrieve or obtain the parcel // voice channel - LandData land = scene.GetLandData(avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y); + LandData land = scene.GetLandData(avatar.AbsolutePosition); //m_log.DebugFormat("[FreeSwitchVoice][PARCELVOICE]: region \"{0}\": Parcel \"{1}\" ({2}): avatar \"{3}\": request: {4}, path: {5}, param: {6}", // scene.RegionInfo.RegionName, land.Name, land.LocalID, avatarName, request, path, param); diff --git a/OpenSim/Region/OptionalModules/Avatar/Voice/VivoxVoice/VivoxVoiceModule.cs b/OpenSim/Region/OptionalModules/Avatar/Voice/VivoxVoice/VivoxVoiceModule.cs index a36fd74..c5fcef4 100644 --- a/OpenSim/Region/OptionalModules/Avatar/Voice/VivoxVoice/VivoxVoiceModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/Voice/VivoxVoice/VivoxVoiceModule.cs @@ -623,7 +623,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice // settings allow voice, then whether parcel allows // voice, if all do retrieve or obtain the parcel // voice channel - LandData land = scene.GetLandData(avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y); + LandData land = scene.GetLandData(avatar.AbsolutePosition); m_log.DebugFormat("[VivoxVoice][PARCELVOICE]: region \"{0}\": Parcel \"{1}\" ({2}): avatar \"{3}\": request: {4}, path: {5}, param: {6}", scene.RegionInfo.RegionName, land.Name, land.LocalID, avatarName, request, path, param); diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 83c9739..11826bd 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -1959,8 +1959,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api // this could possibly be done in the above else-if block, but we're doing the check here to keep the code easier to read. Vector3 objectPos = m_host.ParentGroup.RootPart.AbsolutePosition; - LandData here = World.GetLandData((float)objectPos.X, (float)objectPos.Y); - LandData there = World.GetLandData((float)pos.x, (float)pos.y); + LandData here = World.GetLandData(objectPos); + LandData there = World.GetLandData(pos); // we're only checking prim limits if it's moving to a different parcel under the assumption that if the object got onto the parcel without exceeding the prim limits. @@ -9770,20 +9770,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api switch ((ParcelMediaCommandEnum) aList.Data[i]) { case ParcelMediaCommandEnum.Url: - list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).MediaURL)); + list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition).MediaURL)); break; case ParcelMediaCommandEnum.Desc: - list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).Description)); + list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition).Description)); break; case ParcelMediaCommandEnum.Texture: - list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).MediaID.ToString())); + list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition).MediaID.ToString())); break; case ParcelMediaCommandEnum.Type: - list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).MediaType)); + list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition).MediaType)); break; case ParcelMediaCommandEnum.Size: - list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).MediaWidth)); - list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).MediaHeight)); + list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition).MediaWidth)); + list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition).MediaHeight)); break; default: ParcelMediaCommandEnum mediaCommandEnum = ParcelMediaCommandEnum.Url; @@ -10398,7 +10398,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public LSL_List llGetParcelDetails(LSL_Vector pos, LSL_List param) { m_host.AddScriptLPS(1); - LandData land = World.GetLandData((float)pos.x, (float)pos.y); + LandData land = World.GetLandData(pos); if (land == null) { return new LSL_List(0); diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs index 2e1e5b6..8b73cd9 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs @@ -2941,7 +2941,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api ScenePresence presence = World.GetScenePresence(avatarId); if (presence != null) { - LandData land = World.GetLandData((float)pos.X, (float)pos.Y); + LandData land = World.GetLandData(pos); if ((land.Flags & (uint)ParcelFlags.AllowDamage) == (uint)ParcelFlags.AllowDamage) { float health = presence.Health; -- cgit v1.1 From 783ee949ea9b9bfe309e542a74bb0712f3b65d00 Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Sat, 8 Sep 2012 13:48:07 +0100 Subject: implementing per-region configuration of limits on the number of prims one can have in a linkset Applied with changes - patch was based on a repo different from core Signed-off-by: Melanie --- OpenSim/Region/Framework/Scenes/Scene.cs | 11 +++++++++++ OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs | 18 ++++++++++++++++++ 2 files changed, 29 insertions(+) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index ff3d3af..c2c0b96 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -123,6 +123,11 @@ namespace OpenSim.Region.Framework.Scenes /// public float m_maxPhys = 10; + /// + /// Max prims an object will hold + /// + public int m_linksetCapacity = 0; + public bool m_clampPrimSize; public bool m_trustBinaries; public bool m_allowScriptCrossings; @@ -772,6 +777,12 @@ namespace OpenSim.Region.Framework.Scenes m_clampPrimSize = true; } + m_linksetCapacity = startupConfig.GetInt("LinksetPrims", m_linksetCapacity); + if (RegionInfo.LinksetCapacity > 0) + { + m_linksetCapacity = RegionInfo.LinksetCapacity; + } + m_useTrashOnDelete = startupConfig.GetBoolean("UseTrashOnDelete", m_useTrashOnDelete); m_trustBinaries = startupConfig.GetBoolean("TrustBinaries", m_trustBinaries); m_allowScriptCrossings = startupConfig.GetBoolean("AllowScriptCrossing", m_allowScriptCrossings); diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index b4a155e..e528288 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -2014,6 +2014,24 @@ namespace OpenSim.Region.Framework.Scenes if (objectGroup == this) return; + // If the configured linkset capacity is greater than zero, + // and the new linkset would have a prim count higher than this + // value, do not link it. + if (m_scene.m_linksetCapacity > 0 && + (PrimCount + objectGroup.PrimCount) > + m_scene.m_linksetCapacity) + { + m_log.DebugFormat( + "[SCENE OBJECT GROUP]: Cannot link group with root" + + " part {0}, {1} ({2} prims) to group with root part" + + " {3}, {4} ({5} prims) because the new linkset" + + " would exceed the configured maximum of {6}", + objectGroup.RootPart.Name, objectGroup.RootPart.UUID, + objectGroup.PrimCount, RootPart.Name, RootPart.UUID, + PrimCount, m_scene.m_linksetCapacity); + return; + } + // 'linkPart' == the root of the group being linked into this group SceneObjectPart linkPart = objectGroup.m_rootPart; -- cgit v1.1 From 8321ecb7a26f443a0f137457da5b6e780a824c6c Mon Sep 17 00:00:00 2001 From: BlueWall Date: Sun, 9 Sep 2012 13:50:44 -0400 Subject: Revert "Move addin information to CoreModulePlugin.addin.xml" This reverts commit 2ec34580ce3807cede97539488237040e1a8a6cc. Moving the attributes for mono addins back to the source file - this also fixes http://opensimulator.org/mantis/view.php?id=6278. --- OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs | 6 +++++- OpenSim/Region/CoreModules/Asset/Tests/FlotsamAssetCacheTests.cs | 2 +- OpenSim/Region/CoreModules/Resources/CoreModulePlugin.addin.xml | 1 - 3 files changed, 6 insertions(+), 3 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs index 4bce416..fab489d 100644 --- a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs +++ b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs @@ -49,8 +49,12 @@ using OpenSim.Region.Framework.Scenes; using OpenSim.Services.Interfaces; -namespace OpenSim.Region.CoreModules.Asset +[assembly: Addin("FlotsamAssetCache", "1.1")] +[assembly: AddinDependency("OpenSim", "0.5")] + +namespace Flotsam.RegionModules.AssetCache { + [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] public class FlotsamAssetCache : ISharedRegionModule, IImprovedAssetCache, IAssetService { private static readonly ILog m_log = diff --git a/OpenSim/Region/CoreModules/Asset/Tests/FlotsamAssetCacheTests.cs b/OpenSim/Region/CoreModules/Asset/Tests/FlotsamAssetCacheTests.cs index 9276d1a..c91b25f 100644 --- a/OpenSim/Region/CoreModules/Asset/Tests/FlotsamAssetCacheTests.cs +++ b/OpenSim/Region/CoreModules/Asset/Tests/FlotsamAssetCacheTests.cs @@ -35,7 +35,7 @@ using Nini.Config; using NUnit.Framework; using OpenMetaverse; using OpenMetaverse.Assets; -using OpenSim.Region.CoreModules.Asset; +using Flotsam.RegionModules.AssetCache; using OpenSim.Framework; using OpenSim.Region.Framework.Scenes; using OpenSim.Region.Framework.Scenes.Serialization; diff --git a/OpenSim/Region/CoreModules/Resources/CoreModulePlugin.addin.xml b/OpenSim/Region/CoreModules/Resources/CoreModulePlugin.addin.xml index a09945e..424e0ab 100644 --- a/OpenSim/Region/CoreModules/Resources/CoreModulePlugin.addin.xml +++ b/OpenSim/Region/CoreModules/Resources/CoreModulePlugin.addin.xml @@ -34,7 +34,6 @@ - -- cgit v1.1 From bf56b30024f9ee945bba2836dcd9d092ed71330b Mon Sep 17 00:00:00 2001 From: BlueWall Date: Sun, 9 Sep 2012 14:30:59 -0400 Subject: Adjust namespce of FlotsamCache Place FloatsamCache in the same namespace as our other core asset caches --- OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs | 2 +- OpenSim/Region/CoreModules/Asset/Tests/FlotsamAssetCacheTests.cs | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs index fab489d..5d8a278 100644 --- a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs +++ b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs @@ -52,7 +52,7 @@ using OpenSim.Services.Interfaces; [assembly: Addin("FlotsamAssetCache", "1.1")] [assembly: AddinDependency("OpenSim", "0.5")] -namespace Flotsam.RegionModules.AssetCache +namespace OpenSim.Region.CoreModules.Asset { [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] public class FlotsamAssetCache : ISharedRegionModule, IImprovedAssetCache, IAssetService diff --git a/OpenSim/Region/CoreModules/Asset/Tests/FlotsamAssetCacheTests.cs b/OpenSim/Region/CoreModules/Asset/Tests/FlotsamAssetCacheTests.cs index c91b25f..1c2bfd0 100644 --- a/OpenSim/Region/CoreModules/Asset/Tests/FlotsamAssetCacheTests.cs +++ b/OpenSim/Region/CoreModules/Asset/Tests/FlotsamAssetCacheTests.cs @@ -35,7 +35,6 @@ using Nini.Config; using NUnit.Framework; using OpenMetaverse; using OpenMetaverse.Assets; -using Flotsam.RegionModules.AssetCache; using OpenSim.Framework; using OpenSim.Region.Framework.Scenes; using OpenSim.Region.Framework.Scenes.Serialization; -- cgit v1.1 From 8db5d79f4bc3590edfb8bee7918d3bbb1e286dcb Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Mon, 10 Sep 2012 12:18:40 +0100 Subject: passing in the function name to MOD_Api.ConvertFromLSL for more user-friendly error messages --- OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs index cde2d9f..6809c09 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs @@ -254,7 +254,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api object[] convertedParms = new object[parms.Length]; for (int i = 0; i < parms.Length; i++) - convertedParms[i] = ConvertFromLSL(parms[i],signature[i]); + convertedParms[i] = ConvertFromLSL(parms[i],signature[i], fname); // now call the function, the contract with the function is that it will always return // non-null but don't trust it completely @@ -294,7 +294,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api /// /// - protected object ConvertFromLSL(object lslparm, Type type) + protected object ConvertFromLSL(object lslparm, Type type, string fname) { // ---------- String ---------- if (lslparm is LSL_String) @@ -374,14 +374,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api (LSL_Vector)plist[i]); } else - MODError("unknown LSL list element type"); + MODError(String.Format("{0}: unknown LSL list element type", fname)); } return result; } } - MODError(String.Format("parameter type mismatch; expecting {0}",type.Name)); + MODError(String.Format("{1}: parameter type mismatch; expecting {0}",type.Name, fname)); return null; } -- cgit v1.1 From e3993eefa5f9e2d968bb3ff627b5102224b62c3d Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Tue, 11 Sep 2012 19:59:44 +0100 Subject: Documenting some of the events on OpenSim.Region.Framework.Scenes.EventManager (OnFrame) --- OpenSim/Region/Framework/Scenes/EventManager.cs | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Framework/Scenes/EventManager.cs b/OpenSim/Region/Framework/Scenes/EventManager.cs index 4d65be9..6769fc9 100644 --- a/OpenSim/Region/Framework/Scenes/EventManager.cs +++ b/OpenSim/Region/Framework/Scenes/EventManager.cs @@ -47,6 +47,14 @@ namespace OpenSim.Region.Framework.Scenes public delegate void OnFrameDelegate(); + /// + /// Triggered on each sim frame. + /// + /// + /// This gets triggered in + /// Core uses it for things like Sun, Wind & Clouds + /// The MRM module also uses it. + /// public event OnFrameDelegate OnFrame; public delegate void ClientMovement(ScenePresence client); -- cgit v1.1 From 44349f742e309df65a4a100b004053b4262e9ade Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Tue, 11 Sep 2012 20:00:14 +0100 Subject: documentation (OnClientMovement) --- OpenSim/Region/Framework/Scenes/EventManager.cs | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Framework/Scenes/EventManager.cs b/OpenSim/Region/Framework/Scenes/EventManager.cs index 6769fc9..c9be46d 100644 --- a/OpenSim/Region/Framework/Scenes/EventManager.cs +++ b/OpenSim/Region/Framework/Scenes/EventManager.cs @@ -59,6 +59,13 @@ namespace OpenSim.Region.Framework.Scenes public delegate void ClientMovement(ScenePresence client); + /// + /// Trigerred when an agent moves. + /// + /// + /// This gets triggered in + /// prior to + /// public event ClientMovement OnClientMovement; public delegate void OnTerrainTaintedDelegate(); -- cgit v1.1 From ed5f574356ed5fa290599fa7c852c06370c16747 Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Tue, 11 Sep 2012 20:00:30 +0100 Subject: documentation (OnTerrainTainted) --- OpenSim/Region/Framework/Scenes/EventManager.cs | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Framework/Scenes/EventManager.cs b/OpenSim/Region/Framework/Scenes/EventManager.cs index c9be46d..b2960e7 100644 --- a/OpenSim/Region/Framework/Scenes/EventManager.cs +++ b/OpenSim/Region/Framework/Scenes/EventManager.cs @@ -70,6 +70,13 @@ namespace OpenSim.Region.Framework.Scenes public delegate void OnTerrainTaintedDelegate(); + /// + /// Triggered if the terrain has been edited + /// + /// + /// This gets triggered in + /// after it determines that an update has been made. + /// public event OnTerrainTaintedDelegate OnTerrainTainted; public delegate void OnTerrainTickDelegate(); -- cgit v1.1 From fd8a7e64b90aa02897ff145d527e96e98936d3ca Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Tue, 11 Sep 2012 20:01:00 +0100 Subject: documentation (OnTerrainTick) --- OpenSim/Region/Framework/Scenes/EventManager.cs | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Framework/Scenes/EventManager.cs b/OpenSim/Region/Framework/Scenes/EventManager.cs index b2960e7..6dc8865 100644 --- a/OpenSim/Region/Framework/Scenes/EventManager.cs +++ b/OpenSim/Region/Framework/Scenes/EventManager.cs @@ -81,6 +81,13 @@ namespace OpenSim.Region.Framework.Scenes public delegate void OnTerrainTickDelegate(); + /// + /// Triggered if the terrain has been edited + /// + /// + /// This gets triggered in + /// but is used by core solely to update the physics engine. + /// public event OnTerrainTickDelegate OnTerrainTick; public delegate void OnBackupDelegate(ISimulationDataService datastore, bool forceBackup); -- cgit v1.1 From 5e51f16cebb0df15d79f69eda52ebe0916c20c2d Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Tue, 11 Sep 2012 20:01:31 +0100 Subject: documentation (OnBackup) --- OpenSim/Region/Framework/Scenes/EventManager.cs | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Framework/Scenes/EventManager.cs b/OpenSim/Region/Framework/Scenes/EventManager.cs index 6dc8865..8b5936f 100644 --- a/OpenSim/Region/Framework/Scenes/EventManager.cs +++ b/OpenSim/Region/Framework/Scenes/EventManager.cs @@ -92,6 +92,13 @@ namespace OpenSim.Region.Framework.Scenes public delegate void OnBackupDelegate(ISimulationDataService datastore, bool forceBackup); + /// + /// Triggered when a region is backed up/persisted to storage + /// + /// + /// This gets triggered in + /// and is fired before the persistence occurs. + /// public event OnBackupDelegate OnBackup; public delegate void OnClientConnectCoreDelegate(IClientCore client); -- cgit v1.1 From 0a22e78f591b905a92e9c5e2cf57d50d281e11f6 Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Tue, 11 Sep 2012 20:02:00 +0100 Subject: documentation (OnClientConnect) --- OpenSim/Region/Framework/Scenes/EventManager.cs | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Framework/Scenes/EventManager.cs b/OpenSim/Region/Framework/Scenes/EventManager.cs index 8b5936f..0daecaf 100644 --- a/OpenSim/Region/Framework/Scenes/EventManager.cs +++ b/OpenSim/Region/Framework/Scenes/EventManager.cs @@ -103,6 +103,15 @@ namespace OpenSim.Region.Framework.Scenes public delegate void OnClientConnectCoreDelegate(IClientCore client); + /// + /// Triggered when a new client connects to the scene. + /// + /// + /// This gets triggered in , + /// which checks if an instance of + /// also implements and as such, + /// is not triggered by NPCs. + /// public event OnClientConnectCoreDelegate OnClientConnect; public delegate void OnNewClientDelegate(IClientAPI client); -- cgit v1.1 From 0760121eb989734e86d216e7a02123895f016795 Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Tue, 11 Sep 2012 20:02:19 +0100 Subject: documentation (OnNewPresence) --- OpenSim/Region/Framework/Scenes/EventManager.cs | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Framework/Scenes/EventManager.cs b/OpenSim/Region/Framework/Scenes/EventManager.cs index 0daecaf..744c4a1 100644 --- a/OpenSim/Region/Framework/Scenes/EventManager.cs +++ b/OpenSim/Region/Framework/Scenes/EventManager.cs @@ -132,6 +132,13 @@ namespace OpenSim.Region.Framework.Scenes public delegate void OnNewPresenceDelegate(ScenePresence presence); + /// + /// Triggered when a new presence is added to the scene + /// + /// + /// Triggered in which is used by both + /// users and NPCs + /// public event OnNewPresenceDelegate OnNewPresence; public delegate void OnRemovePresenceDelegate(UUID agentId); -- cgit v1.1 From 97b8739c1d1aefb99526ae5baa0abb628e477061 Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Tue, 11 Sep 2012 20:02:32 +0100 Subject: documentation (OnRemovePresence) --- OpenSim/Region/Framework/Scenes/EventManager.cs | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Framework/Scenes/EventManager.cs b/OpenSim/Region/Framework/Scenes/EventManager.cs index 744c4a1..c66ef42 100644 --- a/OpenSim/Region/Framework/Scenes/EventManager.cs +++ b/OpenSim/Region/Framework/Scenes/EventManager.cs @@ -143,6 +143,13 @@ namespace OpenSim.Region.Framework.Scenes public delegate void OnRemovePresenceDelegate(UUID agentId); + /// + /// Triggered when a presence is removed from the scene + /// + /// + /// Triggered in which is used by both + /// users and NPCs + /// public event OnRemovePresenceDelegate OnRemovePresence; public delegate void OnParcelPrimCountUpdateDelegate(); -- cgit v1.1 From ad1b9bbba6bc4831ccb63d3d5fc1c7c10515fcc4 Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Tue, 11 Sep 2012 20:02:48 +0100 Subject: documentation (OnSceneObjectPartCopy) --- OpenSim/Region/Framework/Scenes/EventManager.cs | 3 +++ 1 file changed, 3 insertions(+) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Framework/Scenes/EventManager.cs b/OpenSim/Region/Framework/Scenes/EventManager.cs index c66ef42..9bdaecf 100644 --- a/OpenSim/Region/Framework/Scenes/EventManager.cs +++ b/OpenSim/Region/Framework/Scenes/EventManager.cs @@ -540,6 +540,9 @@ namespace OpenSim.Region.Framework.Scenes /// /// /// True if the duplicate will immediately be in the scene, false otherwise + /// + /// Triggered in + /// public event SceneObjectPartCopyDelegate OnSceneObjectPartCopy; public delegate void SceneObjectPartCopyDelegate(SceneObjectPart copy, SceneObjectPart original, bool userExposed); -- cgit v1.1 From d53a53d4c599e77f039149128526ac67570b30fb Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Wed, 12 Sep 2012 00:10:48 +0100 Subject: Make "show http-handlers" command available for ROBUST instances as well as the simulator executable. --- OpenSim/Region/Application/OpenSim.cs | 31 ------------------------------- 1 file changed, 31 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Application/OpenSim.cs b/OpenSim/Region/Application/OpenSim.cs index 769eea8..ed339fd 100644 --- a/OpenSim/Region/Application/OpenSim.cs +++ b/OpenSim/Region/Application/OpenSim.cs @@ -332,10 +332,6 @@ namespace OpenSim "show circuits", "Show agent circuit data", HandleShow); - m_console.Commands.AddCommand("Comms", false, "show http-handlers", - "show http-handlers", - "Show all registered http handlers", HandleShow); - m_console.Commands.AddCommand("Comms", false, "show pending-objects", "show pending-objects", "Show # of objects on the pending queues of all scene viewers", HandleShow); @@ -1013,33 +1009,6 @@ namespace OpenSim HandleShowCircuits(); break; - case "http-handlers": - System.Text.StringBuilder handlers = new System.Text.StringBuilder("Registered HTTP Handlers:\n"); - - handlers.AppendFormat("* XMLRPC:\n"); - foreach (String s in HttpServer.GetXmlRpcHandlerKeys()) - handlers.AppendFormat("\t{0}\n", s); - - handlers.AppendFormat("* HTTP:\n"); - List poll = HttpServer.GetPollServiceHandlerKeys(); - foreach (String s in HttpServer.GetHTTPHandlerKeys()) - handlers.AppendFormat("\t{0} {1}\n", s, (poll.Contains(s) ? "(poll service)" : string.Empty)); - - handlers.AppendFormat("* Agent:\n"); - foreach (String s in HttpServer.GetAgentHandlerKeys()) - handlers.AppendFormat("\t{0}\n", s); - - handlers.AppendFormat("* LLSD:\n"); - foreach (String s in HttpServer.GetLLSDHandlerKeys()) - handlers.AppendFormat("\t{0}\n", s); - - handlers.AppendFormat("* StreamHandlers ({0}):\n", HttpServer.GetStreamHandlerKeys().Count); - foreach (String s in HttpServer.GetStreamHandlerKeys()) - handlers.AppendFormat("\t{0}\n", s); - - MainConsole.Instance.Output(handlers.ToString()); - break; - case "modules": MainConsole.Instance.Output("The currently loaded shared modules are:"); foreach (IRegionModule module in m_moduleLoader.GetLoadedSharedModules) -- cgit v1.1 From f06394f19509516005aa7003a6e5e599ad8b7df0 Mon Sep 17 00:00:00 2001 From: Mic Bowman Date: Tue, 11 Sep 2012 16:42:07 -0700 Subject: Allow an incoming identifier to be specified for a JsonStore. --- OpenSim/Region/Framework/Interfaces/IJsonStoreModule.cs | 2 +- .../OptionalModules/Scripting/JsonStore/JsonStoreModule.cs | 14 +++++++------- .../Scripting/JsonStore/JsonStoreScriptModule.cs | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Framework/Interfaces/IJsonStoreModule.cs b/OpenSim/Region/Framework/Interfaces/IJsonStoreModule.cs index baac6e8..da39e95 100644 --- a/OpenSim/Region/Framework/Interfaces/IJsonStoreModule.cs +++ b/OpenSim/Region/Framework/Interfaces/IJsonStoreModule.cs @@ -35,7 +35,7 @@ namespace OpenSim.Region.Framework.Interfaces public interface IJsonStoreModule { - bool CreateStore(string value, out UUID result); + bool CreateStore(string value, ref UUID result); bool DestroyStore(UUID storeID); bool TestPath(UUID storeID, string path, bool useJson); bool SetValue(UUID storeID, string path, string value, bool useJson); diff --git a/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreModule.cs b/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreModule.cs index 311531c..732c28f 100644 --- a/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreModule.cs +++ b/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreModule.cs @@ -175,14 +175,15 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore /// /// // ----------------------------------------------------------------- - public bool CreateStore(string value, out UUID result) + public bool CreateStore(string value, ref UUID result) { - result = UUID.Zero; + if (result == UUID.Zero) + result = UUID.Random(); + + JsonStore map = null; if (! m_enabled) return false; - UUID uuid = UUID.Random(); - JsonStore map = null; try { @@ -195,9 +196,8 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore } lock (m_JsonValueStore) - m_JsonValueStore.Add(uuid,map); + m_JsonValueStore.Add(result,map); - result = uuid; return true; } @@ -231,7 +231,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore if (! m_JsonValueStore.TryGetValue(storeID,out map)) { m_log.InfoFormat("[JsonStore] Missing store {0}",storeID); - return true; + return false; } } diff --git a/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreScriptModule.cs b/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreScriptModule.cs index eaba816..6910d14 100644 --- a/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreScriptModule.cs +++ b/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreScriptModule.cs @@ -227,7 +227,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore protected UUID JsonCreateStore(UUID hostID, UUID scriptID, string value) { UUID uuid = UUID.Zero; - if (! m_store.CreateStore(value, out uuid)) + if (! m_store.CreateStore(value, ref uuid)) GenerateRuntimeError("Failed to create Json store"); return uuid; -- cgit v1.1 From 41f3f2400e40345b66fd7cad76675d25f9e7beb1 Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Tue, 11 Sep 2012 23:34:24 +0100 Subject: Documentation of economy-related EventManager events --- OpenSim/Region/Framework/Scenes/EventManager.cs | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Framework/Scenes/EventManager.cs b/OpenSim/Region/Framework/Scenes/EventManager.cs index 9bdaecf..02c032e 100644 --- a/OpenSim/Region/Framework/Scenes/EventManager.cs +++ b/OpenSim/Region/Framework/Scenes/EventManager.cs @@ -651,8 +651,29 @@ namespace OpenSim.Region.Framework.Scenes public delegate void LandBuy(Object sender, LandBuyArgs e); + /// + /// Triggered when an attempt to transfer grid currency occurs + /// + /// + /// Triggered in + /// via + /// via + /// via + /// public event MoneyTransferEvent OnMoneyTransfer; + + /// + /// Triggered after after + /// public event LandBuy OnLandBuy; + + /// + /// Triggered to allow or prevent a real estate transaction + /// + /// + /// Triggered in + /// + /// public event LandBuy OnValidateLandBuy; public void TriggerOnAttach(uint localID, UUID itemID, UUID avatarID) -- cgit v1.1 From ebb394bbdac0d7d26d4e51d5e7fbc05010ada870 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Wed, 12 Sep 2012 01:45:34 +0100 Subject: Fix indentation and issues where tabs were used instead of spaces in commit 783ee949 --- OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index e528288..ac26be7 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -2022,13 +2022,14 @@ namespace OpenSim.Region.Framework.Scenes m_scene.m_linksetCapacity) { m_log.DebugFormat( - "[SCENE OBJECT GROUP]: Cannot link group with root" + - " part {0}, {1} ({2} prims) to group with root part" + - " {3}, {4} ({5} prims) because the new linkset" + - " would exceed the configured maximum of {6}", - objectGroup.RootPart.Name, objectGroup.RootPart.UUID, - objectGroup.PrimCount, RootPart.Name, RootPart.UUID, - PrimCount, m_scene.m_linksetCapacity); + "[SCENE OBJECT GROUP]: Cannot link group with root" + + " part {0}, {1} ({2} prims) to group with root part" + + " {3}, {4} ({5} prims) because the new linkset" + + " would exceed the configured maximum of {6}", + objectGroup.RootPart.Name, objectGroup.RootPart.UUID, + objectGroup.PrimCount, RootPart.Name, RootPart.UUID, + PrimCount, m_scene.m_linksetCapacity); + return; } -- cgit v1.1 From 224efe7b763640fd62ed177968efe61f175e5b8f Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Wed, 12 Sep 2012 01:57:48 +0100 Subject: minor: Comment out friends notification log spam for now. --- OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs index 24ec435..11db18a 100644 --- a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs @@ -482,9 +482,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends Util.FireAndForget( delegate { - m_log.DebugFormat( - "[FRIENDS MODULE]: Notifying {0} friends of {1} of online status {2}", - friendList.Count, agentID, online); +// m_log.DebugFormat( +// "[FRIENDS MODULE]: Notifying {0} friends of {1} of online status {2}", +// friendList.Count, agentID, online); // Notify about this user status StatusNotify(friendList, agentID, online); -- cgit v1.1 From 9598c1af9e365cc212de42057c963fef5f3ad190 Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Thu, 13 Sep 2012 13:10:59 +0100 Subject: correcting a typo that causes c# express to complain about xml comment containing invalid xml Signed-off-by: BlueWall --- OpenSim/Region/CoreModules/World/Land/PrimCountModule.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/World/Land/PrimCountModule.cs b/OpenSim/Region/CoreModules/World/Land/PrimCountModule.cs index b2f71d1..665875f 100644 --- a/OpenSim/Region/CoreModules/World/Land/PrimCountModule.cs +++ b/OpenSim/Region/CoreModules/World/Land/PrimCountModule.cs @@ -69,7 +69,7 @@ namespace OpenSim.Region.CoreModules.World.Land /// without recounting the whole sim. /// /// We start out tainted so that the first get call resets the various prim counts. - /// + /// private bool m_Tainted = true; private Object m_TaintLock = new Object(); -- cgit v1.1 From 46d8405229becbad5025278226e416c37160dd96 Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Thu, 13 Sep 2012 13:36:10 +0100 Subject: Documentation of parcel-related events Signed-off-by: BlueWall --- OpenSim/Region/Framework/Scenes/EventManager.cs | 44 +++++++++++++++++++++++++ 1 file changed, 44 insertions(+) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Framework/Scenes/EventManager.cs b/OpenSim/Region/Framework/Scenes/EventManager.cs index 02c032e..2f34785 100644 --- a/OpenSim/Region/Framework/Scenes/EventManager.cs +++ b/OpenSim/Region/Framework/Scenes/EventManager.cs @@ -154,10 +154,32 @@ namespace OpenSim.Region.Framework.Scenes public delegate void OnParcelPrimCountUpdateDelegate(); + /// + /// Triggered whenever the prim count may have been altered, or prior + /// to an action that requires the current prim count to be accurate. + /// + /// + /// Triggered by in + /// , + /// , + /// , + /// , + /// , + /// , + /// + /// public event OnParcelPrimCountUpdateDelegate OnParcelPrimCountUpdate; public delegate void OnParcelPrimCountAddDelegate(SceneObjectGroup obj); + /// + /// Triggered in response to for + /// objects that actually contribute to parcel prim count. + /// + /// + /// Triggered by in + /// + /// public event OnParcelPrimCountAddDelegate OnParcelPrimCountAdd; public delegate void OnPluginConsoleDelegate(string[] args); @@ -178,6 +200,14 @@ namespace OpenSim.Region.Framework.Scenes public event OnSetRootAgentSceneDelegate OnSetRootAgentScene; + /// + /// Triggered after parcel properties have been updated. + /// + /// + /// Triggered by in + /// , + /// + /// public event ParcelPropertiesUpdateRequest OnParcelPropertiesUpdateRequest; /// @@ -428,6 +458,20 @@ namespace OpenSim.Region.Framework.Scenes public event RequestParcelPrimCountUpdate OnRequestParcelPrimCountUpdate; public delegate void ParcelPrimCountTainted(); + + /// + /// Triggered when the parcel prim count has been altered. + /// + /// + /// Triggered by in + /// , + /// , + /// , + /// , + /// , + /// , + /// + /// public event ParcelPrimCountTainted OnParcelPrimCountTainted; public event GetScriptRunning OnGetScriptRunning; -- cgit v1.1 From 190f9c258b6cd1efda214b2e188903f571e1c6e4 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Thu, 13 Sep 2012 10:00:29 -0700 Subject: Restarting to work on HGSuitcaseInventoryService: added the ability for the outside world to retrieve appearance items. Not ACLed yet. --- .../CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs | 2 ++ 1 file changed, 2 insertions(+) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs index cf72b58..a0cad40 100644 --- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs +++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs @@ -308,6 +308,8 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess protected override InventoryItemBase GetItem(UUID agentID, UUID itemID) { InventoryItemBase item = base.GetItem(agentID, itemID); + if (item == null) + return null; string userAssetServer = string.Empty; if (IsForeignUser(agentID, out userAssetServer)) -- cgit v1.1 From ce468215d576cc301a261d85bee9baa68a246ce6 Mon Sep 17 00:00:00 2001 From: Oren Hurvitz Date: Tue, 24 Jul 2012 19:48:08 +0300 Subject: Support multi-region OAR files Merged ArchiveWriteRequestPreparation.cs and ArchiveWriteRequestExecution.cs. This simplifies the code, and it's faster to write each scene to the archive as it's found rather than all at once at the end. --- OpenSim/Region/Application/OpenSim.cs | 3 +- .../World/Archiver/ArchiveReadRequest.cs | 365 +++++++++++---- .../World/Archiver/ArchiveScenesGroup.cs | 176 ++++++++ .../World/Archiver/ArchiveWriteRequestExecution.cs | 153 ------- .../Archiver/ArchiveWriteRequestPreparation.cs | 492 ++++++++++++++------- .../CoreModules/World/Archiver/ArchiverModule.cs | 5 +- .../CoreModules/World/Archiver/AssetsRequest.cs | 6 + .../World/Archiver/DearchiveScenesGroup.cs | 232 ++++++++++ .../World/Archiver/Tests/ArchiverTests.cs | 23 +- .../Region/Framework/Interfaces/IEstateModule.cs | 5 + OpenSim/Region/Framework/Scenes/EventManager.cs | 6 +- .../RegionReadyModule/RegionReadyModule.cs | 2 +- 12 files changed, 1068 insertions(+), 400 deletions(-) create mode 100644 OpenSim/Region/CoreModules/World/Archiver/ArchiveScenesGroup.cs delete mode 100644 OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestExecution.cs create mode 100644 OpenSim/Region/CoreModules/World/Archiver/DearchiveScenesGroup.cs (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Application/OpenSim.cs b/OpenSim/Region/Application/OpenSim.cs index ed339fd..c3c612f 100644 --- a/OpenSim/Region/Application/OpenSim.cs +++ b/OpenSim/Region/Application/OpenSim.cs @@ -292,7 +292,7 @@ namespace OpenSim m_console.Commands.AddCommand("Archiving", false, "save oar", //"save oar [-v|--version=] [-p|--profile=] []", - "save oar [-h|--home=] [--noassets] [--publish] [--perm=] []", + "save oar [-h|--home=] [--noassets] [--publish] [--perm=] [--all] []", "Save a region's data to an OAR archive.", // "-v|--version= generates scene objects as per older versions of the serialization (e.g. -v=0)" + Environment.NewLine "-h|--home= adds the url of the profile service to the saved user information.\n" @@ -302,6 +302,7 @@ namespace OpenSim + " this is useful if you're making oars generally available that might be reloaded to the same grid from which you published\n" + "--perm= stops objects with insufficient permissions from being saved to the OAR.\n" + " can contain one or more of these characters: \"C\" = Copy, \"T\" = Transfer\n" + + "--all saves all the regions in the simulator, instead of just the current region.\n" + "The OAR path must be a filesystem path." + " If this is not given then the oar is saved to region.oar in the current directory.", SaveOar); diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs index 433166d..a6923ef 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs @@ -43,6 +43,7 @@ using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Scenes; using OpenSim.Region.Framework.Scenes.Serialization; using OpenSim.Services.Interfaces; +using System.Threading; namespace OpenSim.Region.CoreModules.World.Archiver { @@ -52,7 +53,30 @@ namespace OpenSim.Region.CoreModules.World.Archiver public class ArchiveReadRequest { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + /// + /// Contains data used while dearchiving a single scene. + /// + private class DearchiveContext + { + public Scene Scene { get; set; } + + public List SerialisedSceneObjects { get; set; } + + public List SerialisedParcels { get; set; } + + public List SceneObjects { get; set; } + + public DearchiveContext(Scene scene) + { + Scene = scene; + SerialisedSceneObjects = new List(); + SerialisedParcels = new List(); + SceneObjects = new List(); + } + } + /// /// The maximum major version of OAR that we can read. Minor versions shouldn't need a max number since version /// bumps here should be compatible. @@ -62,9 +86,10 @@ namespace OpenSim.Region.CoreModules.World.Archiver /// /// Has the control file been loaded for this archive? /// - public bool ControlFileLoaded { get; private set; } + public bool ControlFileLoaded { get; private set; } - protected Scene m_scene; + protected string m_loadPath; + protected Scene m_rootScene; protected Stream m_loadStream; protected Guid m_requestId; protected string m_errorMessage; @@ -91,7 +116,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver { if (m_UserMan == null) { - m_UserMan = m_scene.RequestModuleInterface(); + m_UserMan = m_rootScene.RequestModuleInterface(); } return m_UserMan; } @@ -104,10 +129,14 @@ namespace OpenSim.Region.CoreModules.World.Archiver private IGroupsModule m_groupsModule; + private IAssetService m_assetService = null; + + public ArchiveReadRequest(Scene scene, string loadPath, bool merge, bool skipAssets, Guid requestId) { - m_scene = scene; + m_rootScene = scene; + m_loadPath = loadPath; try { m_loadStream = new GZipStream(ArchiveHelpers.GetStream(loadPath), CompressionMode.Decompress); @@ -128,12 +157,14 @@ namespace OpenSim.Region.CoreModules.World.Archiver // Zero can never be a valid user id m_validUserUuids[UUID.Zero] = false; - m_groupsModule = m_scene.RequestModuleInterface(); + m_groupsModule = m_rootScene.RequestModuleInterface(); + m_assetService = m_rootScene.AssetService; } public ArchiveReadRequest(Scene scene, Stream loadStream, bool merge, bool skipAssets, Guid requestId) { - m_scene = scene; + m_rootScene = scene; + m_loadPath = null; m_loadStream = loadStream; m_merge = merge; m_skipAssets = skipAssets; @@ -142,7 +173,8 @@ namespace OpenSim.Region.CoreModules.World.Archiver // Zero can never be a valid user id m_validUserUuids[UUID.Zero] = false; - m_groupsModule = m_scene.RequestModuleInterface(); + m_groupsModule = m_rootScene.RequestModuleInterface(); + m_assetService = m_rootScene.AssetService; } /// @@ -150,25 +182,25 @@ namespace OpenSim.Region.CoreModules.World.Archiver /// public void DearchiveRegion() { - // The same code can handle dearchiving 0.1 and 0.2 OpenSim Archive versions - DearchiveRegion0DotStar(); - } - - private void DearchiveRegion0DotStar() - { int successfulAssetRestores = 0; int failedAssetRestores = 0; - List serialisedSceneObjects = new List(); - List serialisedParcels = new List(); - string filePath = "NONE"; - TarArchiveReader archive = new TarArchiveReader(m_loadStream); + DearchiveScenesInfo dearchivedScenes; + + // We dearchive all the scenes at once, because the files in the TAR archive might be mixed. + // Therefore, we have to keep track of the dearchive context of all the scenes. + Dictionary sceneContexts = new Dictionary(); + + string fullPath = "NONE"; + TarArchiveReader archive = null; byte[] data; TarArchiveReader.TarEntryType entryType; - + try { - while ((data = archive.ReadEntry(out filePath, out entryType)) != null) + FindAndLoadControlFile(out archive, out dearchivedScenes); + + while ((data = archive.ReadEntry(out fullPath, out entryType)) != null) { //m_log.DebugFormat( // "[ARCHIVER]: Successfully read {0} ({1} bytes)", filePath, data.Length); @@ -176,9 +208,30 @@ namespace OpenSim.Region.CoreModules.World.Archiver if (TarArchiveReader.TarEntryType.TYPE_DIRECTORY == entryType) continue; + + // Find the scene that this file belongs to + + Scene scene; + string filePath; + if (!dearchivedScenes.GetRegionFromPath(fullPath, out scene, out filePath)) + continue; // this file belongs to a region that we're not loading + + DearchiveContext sceneContext = null; + if (scene != null) + { + if (!sceneContexts.TryGetValue(scene.RegionInfo.RegionID, out sceneContext)) + { + sceneContext = new DearchiveContext(scene); + sceneContexts.Add(scene.RegionInfo.RegionID, sceneContext); + } + } + + + // Process the file + if (filePath.StartsWith(ArchiveConstants.OBJECTS_PATH)) { - serialisedSceneObjects.Add(Encoding.UTF8.GetString(data)); + sceneContext.SerialisedSceneObjects.Add(Encoding.UTF8.GetString(data)); } else if (filePath.StartsWith(ArchiveConstants.ASSETS_PATH) && !m_skipAssets) { @@ -192,19 +245,19 @@ namespace OpenSim.Region.CoreModules.World.Archiver } else if (!m_merge && filePath.StartsWith(ArchiveConstants.TERRAINS_PATH)) { - LoadTerrain(filePath, data); + LoadTerrain(scene, filePath, data); } else if (!m_merge && filePath.StartsWith(ArchiveConstants.SETTINGS_PATH)) { - LoadRegionSettings(filePath, data); + LoadRegionSettings(scene, filePath, data, dearchivedScenes); } else if (!m_merge && filePath.StartsWith(ArchiveConstants.LANDDATA_PATH)) { - serialisedParcels.Add(Encoding.UTF8.GetString(data)); + sceneContext.SerialisedParcels.Add(Encoding.UTF8.GetString(data)); } else if (filePath == ArchiveConstants.CONTROL_FILE_PATH) { - LoadControlFile(filePath, data); + // Ignore, because we already read the control file } } @@ -212,15 +265,16 @@ namespace OpenSim.Region.CoreModules.World.Archiver } catch (Exception e) { - m_log.ErrorFormat( - "[ARCHIVER]: Aborting load with error in archive file {0}. {1}", filePath, e); + m_log.Error( + String.Format("[ARCHIVER]: Aborting load with error in archive file {0} ", fullPath), e); m_errorMessage += e.ToString(); - m_scene.EventManager.TriggerOarFileLoaded(m_requestId, m_errorMessage); + m_rootScene.EventManager.TriggerOarFileLoaded(m_requestId, new List(), m_errorMessage); return; } finally { - archive.Close(); + if (archive != null) + archive.Close(); } if (!m_skipAssets) @@ -234,32 +288,143 @@ namespace OpenSim.Region.CoreModules.World.Archiver } } - if (!m_merge) + foreach (DearchiveContext sceneContext in sceneContexts.Values) { - m_log.Info("[ARCHIVER]: Clearing all existing scene objects"); - m_scene.DeleteAllSceneObjects(); + m_log.InfoFormat("[ARCHIVER:] Loading region {0}", sceneContext.Scene.RegionInfo.RegionName); + + if (!m_merge) + { + m_log.Info("[ARCHIVER]: Clearing all existing scene objects"); + sceneContext.Scene.DeleteAllSceneObjects(); + } + + try + { + LoadParcels(sceneContext.Scene, sceneContext.SerialisedParcels); + LoadObjects(sceneContext.Scene, sceneContext.SerialisedSceneObjects, sceneContext.SceneObjects); + + // Inform any interested parties that the region has changed. We waited until now so that all + // of the region's objects will be loaded when we send this notification. + IEstateModule estateModule = sceneContext.Scene.RequestModuleInterface(); + if (estateModule != null) + estateModule.TriggerRegionInfoChange(); + } + catch (Exception e) + { + m_log.Error("[ARCHIVER]: Error loading parcels or objects ", e); + m_errorMessage += e.ToString(); + m_rootScene.EventManager.TriggerOarFileLoaded(m_requestId, new List(), m_errorMessage); + return; + } } - LoadParcels(serialisedParcels); - LoadObjects(serialisedSceneObjects); + // Start the scripts. We delayed this because we want the OAR to finish loading ASAP, so + // that users can enter the scene. If we allow the scripts to start in the loop above + // then they significantly increase the time until the OAR finishes loading. + Util.FireAndForget(delegate(object o) + { + Thread.Sleep(15000); + m_log.Info("Starting scripts in scene objects"); + + foreach (DearchiveContext sceneContext in sceneContexts.Values) + { + foreach (SceneObjectGroup sceneObject in sceneContext.SceneObjects) + { + sceneObject.CreateScriptInstances(0, false, sceneContext.Scene.DefaultScriptEngine, 0); // StateSource.RegionStart + sceneObject.ResumeScripts(); + } + + sceneContext.SceneObjects.Clear(); + } + }); m_log.InfoFormat("[ARCHIVER]: Successfully loaded archive"); - m_scene.EventManager.TriggerOarFileLoaded(m_requestId, m_errorMessage); + m_rootScene.EventManager.TriggerOarFileLoaded(m_requestId, dearchivedScenes.GetLoadedScenes(), m_errorMessage); + } + + /// + /// Searches through the files in the archive for the control file, and reads it. + /// We must read the control file first, in order to know which regions are available. + /// + /// + /// In most cases the control file *is* first, since that's how we create archives. However, + /// it's possible that someone rewrote the archive externally so we can't rely on this fact. + /// + /// + /// + private void FindAndLoadControlFile(out TarArchiveReader archive, out DearchiveScenesInfo dearchivedScenes) + { + archive = new TarArchiveReader(m_loadStream); + dearchivedScenes = new DearchiveScenesInfo(); + + string filePath; + byte[] data; + TarArchiveReader.TarEntryType entryType; + bool firstFile = true; + + while ((data = archive.ReadEntry(out filePath, out entryType)) != null) + { + if (TarArchiveReader.TarEntryType.TYPE_DIRECTORY == entryType) + continue; + + if (filePath == ArchiveConstants.CONTROL_FILE_PATH) + { + LoadControlFile(filePath, data, dearchivedScenes); + + // Find which scenes are available in the simulator + ArchiveScenesGroup simulatorScenes = new ArchiveScenesGroup(); + SceneManager.Instance.ForEachScene(delegate(Scene scene2) + { + simulatorScenes.AddScene(scene2); + }); + simulatorScenes.CalcSceneLocations(); + dearchivedScenes.SetSimulatorScenes(m_rootScene, simulatorScenes); + + // If the control file wasn't the first file then reset the read pointer + if (!firstFile) + { + m_log.Warn("Control file wasn't the first file in the archive"); + if (m_loadStream.CanSeek) + { + m_loadStream.Seek(0, SeekOrigin.Begin); + } + else if (m_loadPath != null) + { + archive.Close(); + archive = null; + m_loadStream.Close(); + m_loadStream = null; + m_loadStream = new GZipStream(ArchiveHelpers.GetStream(m_loadPath), CompressionMode.Decompress); + archive = new TarArchiveReader(m_loadStream); + } + else + { + // There isn't currently a scenario where this happens, but it's best to add a check just in case + throw new Exception("Error reading archive: control file wasn't the first file, and the input stream doesn't allow seeking"); + } + } + + return; + } + + firstFile = false; + } + + throw new Exception("Control file not found"); } /// /// Load serialized scene objects. /// - /// - protected void LoadObjects(List serialisedSceneObjects) + protected void LoadObjects(Scene scene, List serialisedSceneObjects, List sceneObjects) { // Reload serialized prims m_log.InfoFormat("[ARCHIVER]: Loading {0} scene objects. Please wait.", serialisedSceneObjects.Count); - UUID oldTelehubUUID = m_scene.RegionInfo.RegionSettings.TelehubObject; + UUID oldTelehubUUID = scene.RegionInfo.RegionSettings.TelehubObject; - IRegionSerialiserModule serialiser = m_scene.RequestModuleInterface(); + IRegionSerialiserModule serialiser = scene.RequestModuleInterface(); int sceneObjectsLoadedCount = 0; foreach (string serialisedSceneObject in serialisedSceneObjects) @@ -280,7 +445,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver SceneObjectGroup sceneObject = serialiser.DeserializeGroupFromXml2(serialisedSceneObject); - bool isTelehub = (sceneObject.UUID == oldTelehubUUID); + bool isTelehub = (sceneObject.UUID == oldTelehubUUID) && (oldTelehubUUID != UUID.Zero); // For now, give all incoming scene objects new uuids. This will allow scenes to be cloned // on the same region server and multiple examples a single object archive to be imported @@ -290,8 +455,8 @@ namespace OpenSim.Region.CoreModules.World.Archiver if (isTelehub) { // Change the Telehub Object to the new UUID - m_scene.RegionInfo.RegionSettings.TelehubObject = sceneObject.UUID; - m_scene.RegionInfo.RegionSettings.Save(); + scene.RegionInfo.RegionSettings.TelehubObject = sceneObject.UUID; + scene.RegionInfo.RegionSettings.Save(); oldTelehubUUID = UUID.Zero; } @@ -301,17 +466,17 @@ namespace OpenSim.Region.CoreModules.World.Archiver { if (part.CreatorData == null || part.CreatorData == string.Empty) { - if (!ResolveUserUuid(part.CreatorID)) - part.CreatorID = m_scene.RegionInfo.EstateSettings.EstateOwner; + if (!ResolveUserUuid(scene, part.CreatorID)) + part.CreatorID = scene.RegionInfo.EstateSettings.EstateOwner; } if (UserManager != null) UserManager.AddUser(part.CreatorID, part.CreatorData); - if (!ResolveUserUuid(part.OwnerID)) - part.OwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner; + if (!ResolveUserUuid(scene, part.OwnerID)) + part.OwnerID = scene.RegionInfo.EstateSettings.EstateOwner; - if (!ResolveUserUuid(part.LastOwnerID)) - part.LastOwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner; + if (!ResolveUserUuid(scene, part.LastOwnerID)) + part.LastOwnerID = scene.RegionInfo.EstateSettings.EstateOwner; if (!ResolveGroupUuid(part.GroupID)) part.GroupID = UUID.Zero; @@ -328,15 +493,15 @@ namespace OpenSim.Region.CoreModules.World.Archiver TaskInventoryDictionary inv = part.TaskInventory; foreach (KeyValuePair kvp in inv) { - if (!ResolveUserUuid(kvp.Value.OwnerID)) + if (!ResolveUserUuid(scene, kvp.Value.OwnerID)) { - kvp.Value.OwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner; + kvp.Value.OwnerID = scene.RegionInfo.EstateSettings.EstateOwner; } if (kvp.Value.CreatorData == null || kvp.Value.CreatorData == string.Empty) { - if (!ResolveUserUuid(kvp.Value.CreatorID)) - kvp.Value.CreatorID = m_scene.RegionInfo.EstateSettings.EstateOwner; + if (!ResolveUserUuid(scene, kvp.Value.CreatorID)) + kvp.Value.CreatorID = scene.RegionInfo.EstateSettings.EstateOwner; } if (UserManager != null) @@ -348,10 +513,10 @@ namespace OpenSim.Region.CoreModules.World.Archiver } } - if (m_scene.AddRestoredSceneObject(sceneObject, true, false)) + if (scene.AddRestoredSceneObject(sceneObject, true, false)) { sceneObjectsLoadedCount++; - sceneObject.CreateScriptInstances(0, false, m_scene.DefaultScriptEngine, 0); + sceneObject.CreateScriptInstances(0, false, scene.DefaultScriptEngine, 0); sceneObject.ResumeScripts(); } } @@ -366,16 +531,17 @@ namespace OpenSim.Region.CoreModules.World.Archiver if (oldTelehubUUID != UUID.Zero) { m_log.WarnFormat("Telehub object not found: {0}", oldTelehubUUID); - m_scene.RegionInfo.RegionSettings.TelehubObject = UUID.Zero; - m_scene.RegionInfo.RegionSettings.ClearSpawnPoints(); + scene.RegionInfo.RegionSettings.TelehubObject = UUID.Zero; + scene.RegionInfo.RegionSettings.ClearSpawnPoints(); } } /// /// Load serialized parcels. /// + /// /// - protected void LoadParcels(List serialisedParcels) + protected void LoadParcels(Scene scene, List serialisedParcels) { // Reload serialized parcels m_log.InfoFormat("[ARCHIVER]: Loading {0} parcels. Please wait.", serialisedParcels.Count); @@ -386,8 +552,8 @@ namespace OpenSim.Region.CoreModules.World.Archiver // Validate User and Group UUID's - if (!ResolveUserUuid(parcel.OwnerID)) - parcel.OwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner; + if (!ResolveUserUuid(scene, parcel.OwnerID)) + parcel.OwnerID = m_rootScene.RegionInfo.EstateSettings.EstateOwner; if (!ResolveGroupUuid(parcel.GroupID)) { @@ -398,7 +564,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver List accessList = new List(); foreach (LandAccessEntry entry in parcel.ParcelAccessList) { - if (ResolveUserUuid(entry.AgentID)) + if (ResolveUserUuid(scene, entry.AgentID)) accessList.Add(entry); // else, drop this access rule } @@ -414,23 +580,24 @@ namespace OpenSim.Region.CoreModules.World.Archiver if (!m_merge) { bool setupDefaultParcel = (landData.Count == 0); - m_scene.LandChannel.Clear(setupDefaultParcel); + scene.LandChannel.Clear(setupDefaultParcel); } - m_scene.EventManager.TriggerIncomingLandDataFromStorage(landData); + scene.EventManager.TriggerIncomingLandDataFromStorage(landData); m_log.InfoFormat("[ARCHIVER]: Restored {0} parcels.", landData.Count); } /// /// Look up the given user id to check whether it's one that is valid for this grid. /// + /// /// /// - private bool ResolveUserUuid(UUID uuid) + private bool ResolveUserUuid(Scene scene, UUID uuid) { if (!m_validUserUuids.ContainsKey(uuid)) { - UserAccount account = m_scene.UserAccountService.GetUserAccount(m_scene.RegionInfo.ScopeID, uuid); + UserAccount account = scene.UserAccountService.GetUserAccount(scene.RegionInfo.ScopeID, uuid); m_validUserUuids.Add(uuid, account != null); } @@ -485,7 +652,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver string extension = filename.Substring(i); string uuid = filename.Remove(filename.Length - extension.Length); - if (m_scene.AssetService.GetMetadata(uuid) != null) + if (m_assetService.GetMetadata(uuid) != null) { // m_log.DebugFormat("[ARCHIVER]: found existing asset {0}",uuid); return true; @@ -505,7 +672,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver // We're relying on the asset service to do the sensible thing and not store the asset if it already // exists. - m_scene.AssetService.Store(asset); + m_assetService.Store(asset); /** * Create layers on decode for image assets. This is likely to significantly increase the time to load archives so @@ -533,12 +700,14 @@ namespace OpenSim.Region.CoreModules.World.Archiver /// /// Load region settings data /// + /// /// /// + /// /// /// true if settings were loaded successfully, false otherwise /// - private bool LoadRegionSettings(string settingsPath, byte[] data) + private bool LoadRegionSettings(Scene scene, string settingsPath, byte[] data, DearchiveScenesInfo dearchivedScenes) { RegionSettings loadedRegionSettings; @@ -554,7 +723,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver return false; } - RegionSettings currentRegionSettings = m_scene.RegionInfo.RegionSettings; + RegionSettings currentRegionSettings = scene.RegionInfo.RegionSettings; currentRegionSettings.AgentLimit = loadedRegionSettings.AgentLimit; currentRegionSettings.AllowDamage = loadedRegionSettings.AllowDamage; @@ -591,12 +760,14 @@ namespace OpenSim.Region.CoreModules.World.Archiver foreach (SpawnPoint sp in loadedRegionSettings.SpawnPoints()) currentRegionSettings.AddSpawnPoint(sp); + currentRegionSettings.LoadedCreationDateTime = dearchivedScenes.LoadedCreationDateTime; + currentRegionSettings.LoadedCreationID = dearchivedScenes.GetOriginalRegionID(scene.RegionInfo.RegionID).ToString(); + currentRegionSettings.Save(); - m_scene.TriggerEstateSunUpdate(); + scene.TriggerEstateSunUpdate(); - IEstateModule estateModule = m_scene.RequestModuleInterface(); - + IEstateModule estateModule = scene.RequestModuleInterface(); if (estateModule != null) estateModule.sendRegionHandshakeToAll(); @@ -606,14 +777,15 @@ namespace OpenSim.Region.CoreModules.World.Archiver /// /// Load terrain data /// + /// /// /// /// /// true if terrain was resolved successfully, false otherwise. /// - private bool LoadTerrain(string terrainPath, byte[] data) + private bool LoadTerrain(Scene scene, string terrainPath, byte[] data) { - ITerrainModule terrainModule = m_scene.RequestModuleInterface(); + ITerrainModule terrainModule = scene.RequestModuleInterface(); MemoryStream ms = new MemoryStream(data); terrainModule.LoadFromStream(terrainPath, ms); @@ -629,17 +801,18 @@ namespace OpenSim.Region.CoreModules.World.Archiver /// /// /// - public void LoadControlFile(string path, byte[] data) + /// + public DearchiveScenesInfo LoadControlFile(string path, byte[] data, DearchiveScenesInfo dearchivedScenes) { XmlNamespaceManager nsmgr = new XmlNamespaceManager(new NameTable()); XmlParserContext context = new XmlParserContext(null, nsmgr, null, XmlSpace.None); XmlTextReader xtr = new XmlTextReader(Encoding.ASCII.GetString(data), XmlNodeType.Document, context); - RegionSettings currentRegionSettings = m_scene.RegionInfo.RegionSettings; + // Loaded metadata will be empty if no information exists in the archive + dearchivedScenes.LoadedCreationDateTime = 0; + dearchivedScenes.DefaultOriginalID = ""; - // Loaded metadata will empty if no information exists in the archive - currentRegionSettings.LoadedCreationDateTime = 0; - currentRegionSettings.LoadedCreationID = ""; + bool multiRegion = false; while (xtr.Read()) { @@ -665,18 +838,44 @@ namespace OpenSim.Region.CoreModules.World.Archiver { int value; if (Int32.TryParse(xtr.ReadElementContentAsString(), out value)) - currentRegionSettings.LoadedCreationDateTime = value; + dearchivedScenes.LoadedCreationDateTime = value; } - else if (xtr.Name.ToString() == "id") + else if (xtr.Name.ToString() == "row") + { + multiRegion = true; + dearchivedScenes.StartRow(); + } + else if (xtr.Name.ToString() == "region") { - currentRegionSettings.LoadedCreationID = xtr.ReadElementContentAsString(); + dearchivedScenes.StartRegion(); + } + else if (xtr.Name.ToString() == "id") + { + string id = xtr.ReadElementContentAsString(); + dearchivedScenes.DefaultOriginalID = id; + if (multiRegion) + dearchivedScenes.SetRegionOriginalID(id); + } + else if (xtr.Name.ToString() == "dir") + { + dearchivedScenes.SetRegionDirectory(xtr.ReadElementContentAsString()); } } } - - currentRegionSettings.Save(); - + + dearchivedScenes.MultiRegionFormat = multiRegion; + if (!multiRegion) + { + // Add the single scene + dearchivedScenes.StartRow(); + dearchivedScenes.StartRegion(); + dearchivedScenes.SetRegionOriginalID(dearchivedScenes.DefaultOriginalID); + dearchivedScenes.SetRegionDirectory(""); + } + ControlFileLoaded = true; + + return dearchivedScenes; } } } \ No newline at end of file diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveScenesGroup.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveScenesGroup.cs new file mode 100644 index 0000000..a66ed88 --- /dev/null +++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveScenesGroup.cs @@ -0,0 +1,176 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using OpenSim.Region.Framework.Scenes; +using OpenMetaverse; +using System.Drawing; + +namespace OpenSim.Region.CoreModules.World.Archiver +{ + /// + /// A group of regions arranged in a rectangle, possibly with holes. + /// + /// + /// The regions usually (but not necessarily) belong to an archive file, in which case we + /// store additional information used to create the archive (e.g., each region's + /// directory within the archive). + /// + public class ArchiveScenesGroup + { + /// + /// All the regions. The outer dictionary contains rows (key: Y coordinate). + /// The inner dictionaries contain each row's regions (key: X coordinate). + /// + public SortedDictionary> Regions { get; set; } + + /// + /// The subdirectory where each region is stored in the archive. + /// + protected Dictionary m_regionDirs; + + /// + /// The grid coordinates of the regions' bounding box. + /// + public Rectangle Rect { get; set; } + + + public ArchiveScenesGroup() + { + Regions = new SortedDictionary>(); + m_regionDirs = new Dictionary(); + Rect = new Rectangle(0, 0, 0, 0); + } + + public void AddScene(Scene scene) + { + uint x = scene.RegionInfo.RegionLocX; + uint y = scene.RegionInfo.RegionLocY; + + SortedDictionary row; + if (!Regions.TryGetValue(y, out row)) + { + row = new SortedDictionary(); + Regions[y] = row; + } + + row[x] = scene; + } + + /// + /// Called after all the scenes have been added. Performs calculations that require + /// knowledge of all the scenes. + /// + public void CalcSceneLocations() + { + if (Regions.Count == 0) + return; + + // Find the bounding rectangle + + uint firstY = Regions.First().Key; + uint lastY = Regions.Last().Key; + + uint? firstX = null; + uint? lastX = null; + + foreach (SortedDictionary row in Regions.Values) + { + uint curFirstX = row.First().Key; + uint curLastX = row.Last().Key; + + firstX = (firstX == null) ? curFirstX : (firstX < curFirstX) ? firstX : curFirstX; + lastX = (lastX == null) ? curLastX : (lastX > curLastX) ? lastX : curLastX; + } + + Rect = new Rectangle((int)firstX, (int)firstY, (int)(lastY - firstY + 1), (int)(lastX - firstX + 1)); + + + // Calculate the subdirectory in which each region will be stored in the archive + + m_regionDirs.Clear(); + ForEachScene(delegate(Scene scene) + { + // We add the region's coordinates to ensure uniqueness even if multiple regions have the same name + string path = string.Format("{0}_{1}_{2}", + scene.RegionInfo.RegionLocX - Rect.X + 1, + scene.RegionInfo.RegionLocY - Rect.Y + 1, + scene.RegionInfo.RegionName.Replace(' ', '_')); + m_regionDirs[scene.RegionInfo.RegionID] = path; + }); + } + + /// + /// Returns the subdirectory where the region is stored. + /// + /// + /// + public string GetRegionDir(UUID regionID) + { + return m_regionDirs[regionID]; + } + + /// + /// Performs an action on all the scenes in this order: rows from South to North, + /// and within each row West to East. + /// + /// + public void ForEachScene(Action action) + { + foreach (SortedDictionary row in Regions.Values) + { + foreach (Scene scene in row.Values) + { + action(scene); + } + } + } + + /// + /// Returns the scene at position 'location'. + /// + /// A location in the grid + /// The scene at this location + /// Whether the scene was found + public bool TryGetScene(Point location, out Scene scene) + { + SortedDictionary row; + if (Regions.TryGetValue((uint)location.Y, out row)) + { + if (row.TryGetValue((uint)location.X, out scene)) + return true; + } + + scene = null; + return false; + } + + } +} diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestExecution.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestExecution.cs deleted file mode 100644 index 0780d86..0000000 --- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestExecution.cs +++ /dev/null @@ -1,153 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.IO; -using System.Reflection; -using System.Xml; -using log4net; -using OpenMetaverse; -using OpenSim.Framework; -using OpenSim.Framework.Serialization; -using OpenSim.Framework.Serialization.External; -using OpenSim.Region.CoreModules.World.Terrain; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; - -namespace OpenSim.Region.CoreModules.World.Archiver -{ - /// - /// Method called when all the necessary assets for an archive request have been received. - /// - public delegate void AssetsRequestCallback( - ICollection assetsFoundUuids, ICollection assetsNotFoundUuids); - - /// - /// Execute the write of an archive once we have received all the necessary data - /// - public class ArchiveWriteRequestExecution - { - private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - protected ITerrainModule m_terrainModule; - protected IRegionSerialiserModule m_serialiser; - protected List m_sceneObjects; - protected Scene m_scene; - protected TarArchiveWriter m_archiveWriter; - protected Guid m_requestId; - protected Dictionary m_options; - - public ArchiveWriteRequestExecution( - List sceneObjects, - ITerrainModule terrainModule, - IRegionSerialiserModule serialiser, - Scene scene, - TarArchiveWriter archiveWriter, - Guid requestId, - Dictionary options) - { - m_sceneObjects = sceneObjects; - m_terrainModule = terrainModule; - m_serialiser = serialiser; - m_scene = scene; - m_archiveWriter = archiveWriter; - m_requestId = requestId; - m_options = options; - } - - protected internal void ReceivedAllAssets( - ICollection assetsFoundUuids, ICollection assetsNotFoundUuids) - { - try - { - Save(assetsFoundUuids, assetsNotFoundUuids); - } - finally - { - m_archiveWriter.Close(); - } - - m_log.InfoFormat("[ARCHIVER]: Finished writing out OAR for {0}", m_scene.RegionInfo.RegionName); - - m_scene.EventManager.TriggerOarFileSaved(m_requestId, String.Empty); - } - - protected internal void Save(ICollection assetsFoundUuids, ICollection assetsNotFoundUuids) - { - foreach (UUID uuid in assetsNotFoundUuids) - { - m_log.DebugFormat("[ARCHIVER]: Could not find asset {0}", uuid); - } - -// m_log.InfoFormat( -// "[ARCHIVER]: Received {0} of {1} assets requested", -// assetsFoundUuids.Count, assetsFoundUuids.Count + assetsNotFoundUuids.Count); - - m_log.InfoFormat("[ARCHIVER]: Adding region settings to archive."); - - // Write out region settings - string settingsPath - = String.Format("{0}{1}.xml", ArchiveConstants.SETTINGS_PATH, m_scene.RegionInfo.RegionName); - m_archiveWriter.WriteFile(settingsPath, RegionSettingsSerializer.Serialize(m_scene.RegionInfo.RegionSettings)); - - m_log.InfoFormat("[ARCHIVER]: Adding parcel settings to archive."); - - // Write out land data (aka parcel) settings - ListlandObjects = m_scene.LandChannel.AllParcels(); - foreach (ILandObject lo in landObjects) - { - LandData landData = lo.LandData; - string landDataPath = String.Format("{0}{1}.xml", ArchiveConstants.LANDDATA_PATH, - landData.GlobalID.ToString()); - m_archiveWriter.WriteFile(landDataPath, LandDataSerializer.Serialize(landData, m_options)); - } - - m_log.InfoFormat("[ARCHIVER]: Adding terrain information to archive."); - - // Write out terrain - string terrainPath - = String.Format("{0}{1}.r32", ArchiveConstants.TERRAINS_PATH, m_scene.RegionInfo.RegionName); - - MemoryStream ms = new MemoryStream(); - m_terrainModule.SaveToStream(terrainPath, ms); - m_archiveWriter.WriteFile(terrainPath, ms.ToArray()); - ms.Close(); - - m_log.InfoFormat("[ARCHIVER]: Adding scene objects to archive."); - - // Write out scene object metadata - foreach (SceneObjectGroup sceneObject in m_sceneObjects) - { - //m_log.DebugFormat("[ARCHIVER]: Saving {0} {1}, {2}", entity.Name, entity.UUID, entity.GetType()); - - string serializedObject = m_serialiser.SerializeGroupToXml2(sceneObject, m_options); - m_archiveWriter.WriteFile(ArchiveHelpers.CreateObjectPath(sceneObject), serializedObject); - } - } - } -} \ No newline at end of file diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestPreparation.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestPreparation.cs index 4edaaca..2c34f4b 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestPreparation.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestPreparation.cs @@ -43,6 +43,7 @@ using OpenSim.Region.Framework.Scenes; using Ionic.Zlib; using GZipStream = Ionic.Zlib.GZipStream; using CompressionMode = Ionic.Zlib.CompressionMode; +using OpenSim.Framework.Serialization.External; namespace OpenSim.Region.CoreModules.World.Archiver { @@ -61,17 +62,29 @@ namespace OpenSim.Region.CoreModules.World.Archiver /// /// The maximum major version of OAR that we can write. /// - public static int MAX_MAJOR_VERSION = 0; + public static int MAX_MAJOR_VERSION = 1; + + /// + /// Whether we're saving a multi-region archive. + /// + public bool MultiRegionFormat { get; set; } /// /// Determine whether this archive will save assets. Default is true. /// public bool SaveAssets { get; set; } - protected ArchiverModule m_module; - protected Scene m_scene; + /// + /// Determines which objects will be included in the archive, according to their permissions. + /// Default is null, meaning no permission checks. + /// + public string CheckPermissions { get; set; } + + protected Scene m_rootScene; protected Stream m_saveStream; + protected TarArchiveWriter m_archiveWriter; protected Guid m_requestId; + protected Dictionary m_options; /// /// Constructor @@ -82,7 +95,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver /// /// If there was a problem opening a stream for the file specified by the savePath /// - public ArchiveWriteRequestPreparation(ArchiverModule module, string savePath, Guid requestId) : this(module, requestId) + public ArchiveWriteRequestPreparation(Scene scene, string savePath, Guid requestId) : this(scene, requestId) { try { @@ -100,26 +113,23 @@ namespace OpenSim.Region.CoreModules.World.Archiver /// /// Constructor. /// - /// Calling module + /// The root scene to archive /// The stream to which to save data. /// The id associated with this request - public ArchiveWriteRequestPreparation(ArchiverModule module, Stream saveStream, Guid requestId) : this(module, requestId) + public ArchiveWriteRequestPreparation(Scene scene, Stream saveStream, Guid requestId) : this(scene, requestId) { m_saveStream = saveStream; } - protected ArchiveWriteRequestPreparation(ArchiverModule module, Guid requestId) + protected ArchiveWriteRequestPreparation(Scene scene, Guid requestId) { - m_module = module; - - // FIXME: This is only here for regression test purposes since they do not supply a module. Need to fix - // this. - if (m_module != null) - m_scene = m_module.Scene; - + m_rootScene = scene; m_requestId = requestId; + m_archiveWriter = null; + MultiRegionFormat = false; SaveAssets = true; + CheckPermissions = null; } /// @@ -128,126 +138,157 @@ namespace OpenSim.Region.CoreModules.World.Archiver /// if there was an io problem with creating the file public void ArchiveRegion(Dictionary options) { + m_options = options; + + if (options.ContainsKey("all") && (bool)options["all"]) + MultiRegionFormat = true; + if (options.ContainsKey("noassets") && (bool)options["noassets"]) SaveAssets = false; + Object temp; + if (options.TryGetValue("checkPermissions", out temp)) + CheckPermissions = (string)temp; + + + // Find the regions to archive + ArchiveScenesGroup scenesGroup = new ArchiveScenesGroup(); + if (MultiRegionFormat) + { + m_log.InfoFormat("[ARCHIVER]: Saving {0} regions", SceneManager.Instance.Scenes.Count); + SceneManager.Instance.ForEachScene(delegate(Scene scene) + { + scenesGroup.AddScene(scene); + }); + } + else + { + scenesGroup.AddScene(m_rootScene); + } + scenesGroup.CalcSceneLocations(); + + + m_archiveWriter = new TarArchiveWriter(m_saveStream); + try { + // Write out control file. It should be first so that it will be found ASAP when loading the file. + m_archiveWriter.WriteFile(ArchiveConstants.CONTROL_FILE_PATH, CreateControlFile(scenesGroup)); + m_log.InfoFormat("[ARCHIVER]: Added control file to archive."); + + // Archive the regions + Dictionary assetUuids = new Dictionary(); - - EntityBase[] entities = m_scene.GetEntities(); - List sceneObjects = new List(); - - string checkPermissions = null; - int numObjectsSkippedPermissions = 0; - Object temp; - if (options.TryGetValue("checkPermissions", out temp)) - checkPermissions = (string)temp; - - // Filter entities so that we only have scene objects. - // FIXME: Would be nicer to have this as a proper list in SceneGraph, since lots of methods - // end up having to do this - foreach (EntityBase entity in entities) + + scenesGroup.ForEachScene(delegate(Scene scene) { - if (entity is SceneObjectGroup) - { - SceneObjectGroup sceneObject = (SceneObjectGroup)entity; + string regionDir = MultiRegionFormat ? scenesGroup.GetRegionDir(scene.RegionInfo.RegionID) : ""; + ArchiveOneRegion(scene, regionDir, assetUuids); + }); - if (!sceneObject.IsDeleted && !sceneObject.IsAttachment) - { - if (!CanUserArchiveObject(m_scene.RegionInfo.EstateSettings.EstateOwner, sceneObject, checkPermissions)) - { - // The user isn't allowed to copy/transfer this object, so it will not be included in the OAR. - ++numObjectsSkippedPermissions; - } - else - { - sceneObjects.Add(sceneObject); - } - } - } - } + // Archive the assets if (SaveAssets) { - UuidGatherer assetGatherer = new UuidGatherer(m_scene.AssetService); + m_log.DebugFormat("[ARCHIVER]: Saving {0} assets", assetUuids.Count); - foreach (SceneObjectGroup sceneObject in sceneObjects) - { - assetGatherer.GatherAssetUuids(sceneObject, assetUuids); - } + // Asynchronously request all the assets required to perform this archive operation + AssetsRequest ar + = new AssetsRequest( + new AssetsArchiver(m_archiveWriter), assetUuids, + m_rootScene.AssetService, m_rootScene.UserAccountService, + m_rootScene.RegionInfo.ScopeID, options, ReceivedAllAssets); - m_log.DebugFormat( - "[ARCHIVER]: {0} scene objects to serialize requiring save of {1} assets", - sceneObjects.Count, assetUuids.Count); + Util.FireAndForget(o => ar.Execute()); + + // CloseArchive() will be called from ReceivedAllAssets() } else { m_log.DebugFormat("[ARCHIVER]: Not saving assets since --noassets was specified"); + CloseArchive(string.Empty); } + } + catch (Exception e) + { + CloseArchive(e.Message); + throw; + } + } - if (numObjectsSkippedPermissions > 0) - { - m_log.DebugFormat( - "[ARCHIVER]: {0} scene objects skipped due to lack of permissions", - numObjectsSkippedPermissions); - } - // Make sure that we also request terrain texture assets - RegionSettings regionSettings = m_scene.RegionInfo.RegionSettings; - - if (regionSettings.TerrainTexture1 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_1) - assetUuids[regionSettings.TerrainTexture1] = AssetType.Texture; - - if (regionSettings.TerrainTexture2 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_2) - assetUuids[regionSettings.TerrainTexture2] = AssetType.Texture; - - if (regionSettings.TerrainTexture3 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_3) - assetUuids[regionSettings.TerrainTexture3] = AssetType.Texture; - - if (regionSettings.TerrainTexture4 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_4) - assetUuids[regionSettings.TerrainTexture4] = AssetType.Texture; - - TarArchiveWriter archiveWriter = new TarArchiveWriter(m_saveStream); - - // Asynchronously request all the assets required to perform this archive operation - ArchiveWriteRequestExecution awre - = new ArchiveWriteRequestExecution( - sceneObjects, - m_scene.RequestModuleInterface(), - m_scene.RequestModuleInterface(), - m_scene, - archiveWriter, - m_requestId, - options); - - m_log.InfoFormat("[ARCHIVER]: Creating archive file. This may take some time."); - - // Write out control file. This has to be done first so that subsequent loaders will see this file first - // XXX: I know this is a weak way of doing it since external non-OAR aware tar executables will not do this - archiveWriter.WriteFile(ArchiveConstants.CONTROL_FILE_PATH, CreateControlFile(options)); - m_log.InfoFormat("[ARCHIVER]: Added control file to archive."); + private void ArchiveOneRegion(Scene scene, string regionDir, Dictionary assetUuids) + { + m_log.InfoFormat("[ARCHIVER]: Writing region {0}", scene.RegionInfo.RegionName); - if (SaveAssets) + EntityBase[] entities = scene.GetEntities(); + List sceneObjects = new List(); + + int numObjectsSkippedPermissions = 0; + + // Filter entities so that we only have scene objects. + // FIXME: Would be nicer to have this as a proper list in SceneGraph, since lots of methods + // end up having to do this + IPermissionsModule permissionsModule = scene.RequestModuleInterface(); + foreach (EntityBase entity in entities) + { + if (entity is SceneObjectGroup) { - AssetsRequest ar - = new AssetsRequest( - new AssetsArchiver(archiveWriter), assetUuids, - m_scene.AssetService, m_scene.UserAccountService, - m_scene.RegionInfo.ScopeID, options, awre.ReceivedAllAssets); + SceneObjectGroup sceneObject = (SceneObjectGroup)entity; - Util.FireAndForget(o => ar.Execute()); + if (!sceneObject.IsDeleted && !sceneObject.IsAttachment) + { + if (!CanUserArchiveObject(scene.RegionInfo.EstateSettings.EstateOwner, sceneObject, CheckPermissions, permissionsModule)) + { + // The user isn't allowed to copy/transfer this object, so it will not be included in the OAR. + ++numObjectsSkippedPermissions; + } + else + { + sceneObjects.Add(sceneObject); + } + } } - else + } + + if (SaveAssets) + { + UuidGatherer assetGatherer = new UuidGatherer(scene.AssetService); + int prevAssets = assetUuids.Count; + + foreach (SceneObjectGroup sceneObject in sceneObjects) { - awre.ReceivedAllAssets(new List(), new List()); + assetGatherer.GatherAssetUuids(sceneObject, assetUuids); } + + m_log.DebugFormat( + "[ARCHIVER]: {0} scene objects to serialize requiring save of {1} assets", + sceneObjects.Count, assetUuids.Count - prevAssets); } - catch (Exception) + + if (numObjectsSkippedPermissions > 0) { - m_saveStream.Close(); - throw; - } + m_log.DebugFormat( + "[ARCHIVER]: {0} scene objects skipped due to lack of permissions", + numObjectsSkippedPermissions); + } + + // Make sure that we also request terrain texture assets + RegionSettings regionSettings = scene.RegionInfo.RegionSettings; + + if (regionSettings.TerrainTexture1 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_1) + assetUuids[regionSettings.TerrainTexture1] = AssetType.Texture; + + if (regionSettings.TerrainTexture2 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_2) + assetUuids[regionSettings.TerrainTexture2] = AssetType.Texture; + + if (regionSettings.TerrainTexture3 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_3) + assetUuids[regionSettings.TerrainTexture3] = AssetType.Texture; + + if (regionSettings.TerrainTexture4 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_4) + assetUuids[regionSettings.TerrainTexture4] = AssetType.Texture; + + Save(scene, sceneObjects, regionDir); } /// @@ -256,14 +297,14 @@ namespace OpenSim.Region.CoreModules.World.Archiver /// The user /// The object group /// Which permissions to check: "C" = Copy, "T" = Transfer + /// The scene's permissions module /// Whether the user is allowed to export the object to an OAR - private bool CanUserArchiveObject(UUID user, SceneObjectGroup objGroup, string checkPermissions) + private bool CanUserArchiveObject(UUID user, SceneObjectGroup objGroup, string checkPermissions, IPermissionsModule permissionsModule) { if (checkPermissions == null) return true; - IPermissionsModule module = m_scene.RequestModuleInterface(); - if (module == null) + if (permissionsModule == null) return true; // this shouldn't happen // Check whether the user is permitted to export all of the parts in the SOG. If any @@ -275,7 +316,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver foreach (SceneObjectPart obj in objGroup.Parts) { uint perm; - PermissionClass permissionClass = module.GetPermissionClass(user, obj); + PermissionClass permissionClass = permissionsModule.GetPermissionClass(user, obj); switch (permissionClass) { case PermissionClass.Owner: @@ -330,16 +371,30 @@ namespace OpenSim.Region.CoreModules.World.Archiver } /// - /// Create the control file for the most up to date archive + /// Create the control file. /// /// - public string CreateControlFile(Dictionary options) + public string CreateControlFile(ArchiveScenesGroup scenesGroup) { - int majorVersion = MAX_MAJOR_VERSION, minorVersion = 8; + int majorVersion; + int minorVersion; + + if (MultiRegionFormat) + { + majorVersion = MAX_MAJOR_VERSION; + minorVersion = 0; + } + else + { + // To support older versions of OpenSim, we continue to create single-region OARs + // using the old file format. In the future this format will be discontinued. + majorVersion = 0; + minorVersion = 8; + } // -// if (options.ContainsKey("version")) +// if (m_options.ContainsKey("version")) // { -// string[] parts = options["version"].ToString().Split('.'); +// string[] parts = m_options["version"].ToString().Split('.'); // if (parts.Length >= 1) // { // majorVersion = Int32.Parse(parts[0]); @@ -368,10 +423,10 @@ namespace OpenSim.Region.CoreModules.World.Archiver // } m_log.InfoFormat("[ARCHIVER]: Creating version {0}.{1} OAR", majorVersion, minorVersion); - //if (majorVersion == 1) - //{ - // m_log.WarnFormat("[ARCHIVER]: Please be aware that version 1.0 OARs are not compatible with OpenSim 0.7.0.2 and earlier. Please use the --version=0 option if you want to produce a compatible OAR"); - //} + if (majorVersion == 1) + { + m_log.WarnFormat("[ARCHIVER]: Please be aware that version 1.0 OARs are not compatible with OpenSim versions prior to 0.7.4. Do not use the --all option if you want to produce a compatible OAR"); + } String s; @@ -389,50 +444,191 @@ namespace OpenSim.Region.CoreModules.World.Archiver DateTime now = DateTime.UtcNow; TimeSpan t = now - new DateTime(1970, 1, 1); xtw.WriteElementString("datetime", ((int)t.TotalSeconds).ToString()); - xtw.WriteElementString("id", UUID.Random().ToString()); + if (!MultiRegionFormat) + xtw.WriteElementString("id", m_rootScene.RegionInfo.RegionID.ToString()); xtw.WriteEndElement(); + + xtw.WriteElementString("assets_included", SaveAssets.ToString()); - xtw.WriteStartElement("region_info"); + if (MultiRegionFormat) + { + WriteRegionsManifest(scenesGroup, xtw); + } + else + { + xtw.WriteStartElement("region_info"); + WriteRegionInfo(m_rootScene, xtw); + xtw.WriteEndElement(); + } - bool isMegaregion; - Vector2 size; - IRegionCombinerModule rcMod = null; + xtw.WriteEndElement(); + + xtw.Flush(); + } - // FIXME: This is only here for regression test purposes since they do not supply a module. Need to fix - // this, possibly by doing control file creation somewhere else. - if (m_module != null) - rcMod = m_module.RegionCombinerModule; + s = sw.ToString(); + } - if (rcMod != null) - isMegaregion = rcMod.IsRootForMegaregion(m_scene.RegionInfo.RegionID); - else - isMegaregion = false; + return s; + } - if (isMegaregion) - size = rcMod.GetSizeOfMegaregion(m_scene.RegionInfo.RegionID); - else - size = new Vector2((float)Constants.RegionSize, (float)Constants.RegionSize); + /// + /// Writes the list of regions included in a multi-region OAR. + /// + private static void WriteRegionsManifest(ArchiveScenesGroup scenesGroup, XmlTextWriter xtw) + { + xtw.WriteStartElement("regions"); - xtw.WriteElementString("is_megaregion", isMegaregion.ToString()); - xtw.WriteElementString("size_in_meters", string.Format("{0},{1}", size.X, size.Y)); + // Write the regions in order: rows from South to North, then regions from West to East. + // The list of regions can have "holes"; we write empty elements in their position. - xtw.WriteEndElement(); - - xtw.WriteElementString("assets_included", SaveAssets.ToString()); + for (uint y = (uint)scenesGroup.Rect.Top; y < scenesGroup.Rect.Bottom; ++y) + { + SortedDictionary row; + if (scenesGroup.Regions.TryGetValue(y, out row)) + { + xtw.WriteStartElement("row"); + + for (uint x = (uint)scenesGroup.Rect.Left; x < scenesGroup.Rect.Right; ++x) + { + Scene scene; + if (row.TryGetValue(x, out scene)) + { + xtw.WriteStartElement("region"); + xtw.WriteElementString("id", scene.RegionInfo.RegionID.ToString()); + xtw.WriteElementString("dir", scenesGroup.GetRegionDir(scene.RegionInfo.RegionID)); + WriteRegionInfo(scene, xtw); + xtw.WriteEndElement(); + } + else + { + // Write a placeholder for a missing region + xtw.WriteElementString("region", ""); + } + } xtw.WriteEndElement(); - - xtw.Flush(); } + else + { + // Write a placeholder for a missing row + xtw.WriteElementString("row", ""); + } + } - s = sw.ToString(); + xtw.WriteEndElement(); // "regions" + } + + protected static void WriteRegionInfo(Scene scene, XmlTextWriter xtw) + { + bool isMegaregion; + Vector2 size; + + IRegionCombinerModule rcMod = scene.RequestModuleInterface(); + + if (rcMod != null) + isMegaregion = rcMod.IsRootForMegaregion(scene.RegionInfo.RegionID); + else + isMegaregion = false; + + if (isMegaregion) + size = rcMod.GetSizeOfMegaregion(scene.RegionInfo.RegionID); + else + size = new Vector2((float)Constants.RegionSize, (float)Constants.RegionSize); + + xtw.WriteElementString("is_megaregion", isMegaregion.ToString()); + xtw.WriteElementString("size_in_meters", string.Format("{0},{1}", size.X, size.Y)); + } + + + protected void Save(Scene scene, List sceneObjects, string regionDir) + { + if (regionDir != string.Empty) + regionDir = ArchiveConstants.REGIONS_PATH + regionDir + "/"; + + m_log.InfoFormat("[ARCHIVER]: Adding region settings to archive."); + + // Write out region settings + string settingsPath = String.Format("{0}{1}{2}.xml", + regionDir, ArchiveConstants.SETTINGS_PATH, scene.RegionInfo.RegionName); + m_archiveWriter.WriteFile(settingsPath, RegionSettingsSerializer.Serialize(scene.RegionInfo.RegionSettings)); + + m_log.InfoFormat("[ARCHIVER]: Adding parcel settings to archive."); + + // Write out land data (aka parcel) settings + List landObjects = scene.LandChannel.AllParcels(); + foreach (ILandObject lo in landObjects) + { + LandData landData = lo.LandData; + string landDataPath = String.Format("{0}{1}{2}.xml", + regionDir, ArchiveConstants.LANDDATA_PATH, landData.GlobalID.ToString()); + m_archiveWriter.WriteFile(landDataPath, LandDataSerializer.Serialize(landData, m_options)); } -// if (m_scene != null) -// Console.WriteLine( -// "[ARCHIVE WRITE REQUEST PREPARATION]: Control file for {0} is: {1}", m_scene.RegionInfo.RegionName, s); + m_log.InfoFormat("[ARCHIVER]: Adding terrain information to archive."); - return s; + // Write out terrain + string terrainPath = String.Format("{0}{1}{2}.r32", + regionDir, ArchiveConstants.TERRAINS_PATH, scene.RegionInfo.RegionName); + + MemoryStream ms = new MemoryStream(); + scene.RequestModuleInterface().SaveToStream(terrainPath, ms); + m_archiveWriter.WriteFile(terrainPath, ms.ToArray()); + ms.Close(); + + m_log.InfoFormat("[ARCHIVER]: Adding scene objects to archive."); + + // Write out scene object metadata + IRegionSerialiserModule serializer = scene.RequestModuleInterface(); + foreach (SceneObjectGroup sceneObject in sceneObjects) + { + //m_log.DebugFormat("[ARCHIVER]: Saving {0} {1}, {2}", entity.Name, entity.UUID, entity.GetType()); + + string serializedObject = serializer.SerializeGroupToXml2(sceneObject, m_options); + string objectPath = string.Format("{0}{1}", regionDir, ArchiveHelpers.CreateObjectPath(sceneObject)); + m_archiveWriter.WriteFile(objectPath, serializedObject); + } } + + protected void ReceivedAllAssets( + ICollection assetsFoundUuids, ICollection assetsNotFoundUuids) + { + foreach (UUID uuid in assetsNotFoundUuids) + { + m_log.DebugFormat("[ARCHIVER]: Could not find asset {0}", uuid); + } + + // m_log.InfoFormat( + // "[ARCHIVER]: Received {0} of {1} assets requested", + // assetsFoundUuids.Count, assetsFoundUuids.Count + assetsNotFoundUuids.Count); + + CloseArchive(String.Empty); + } + + + /// + /// Closes the archive and notifies that we're done. + /// + /// The error that occurred, or empty for success + protected void CloseArchive(string errorMessage) + { + try + { + if (m_archiveWriter != null) + m_archiveWriter.Close(); + m_saveStream.Close(); + } + catch (Exception e) + { + m_log.Error(string.Format("[ARCHIVER]: Error closing archive: {0} ", e.Message), e); + if (errorMessage == string.Empty) + errorMessage = e.Message; + } + + m_log.InfoFormat("[ARCHIVER]: Finished writing out OAR for {0}", m_rootScene.RegionInfo.RegionName); + + m_rootScene.EventManager.TriggerOarFileSaved(m_requestId, errorMessage); + } + } } diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiverModule.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiverModule.cs index bf3b124..26535a9 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/ArchiverModule.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiverModule.cs @@ -146,6 +146,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver ops.Add("noassets", delegate(string v) { options["noassets"] = v != null; }); ops.Add("publish", v => options["wipe-owners"] = v != null); ops.Add("perm=", delegate(string v) { options["checkPermissions"] = v; }); + ops.Add("all", delegate(string v) { options["all"] = v != null; }); List mainParams = ops.Parse(cmdparams); @@ -169,7 +170,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver m_log.InfoFormat( "[ARCHIVER]: Writing archive for region {0} to {1}", Scene.RegionInfo.RegionName, savePath); - new ArchiveWriteRequestPreparation(this, savePath, requestId).ArchiveRegion(options); + new ArchiveWriteRequestPreparation(Scene, savePath, requestId).ArchiveRegion(options); } public void ArchiveRegion(Stream saveStream) @@ -184,7 +185,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver public void ArchiveRegion(Stream saveStream, Guid requestId, Dictionary options) { - new ArchiveWriteRequestPreparation(this, saveStream, requestId).ArchiveRegion(options); + new ArchiveWriteRequestPreparation(Scene, saveStream, requestId).ArchiveRegion(options); } public void DearchiveRegion(string loadPath) diff --git a/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs index a073cb9..5787279 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs @@ -46,6 +46,12 @@ namespace OpenSim.Region.CoreModules.World.Archiver { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + /// + /// Method called when all the necessary assets for an archive request have been received. + /// + public delegate void AssetsRequestCallback( + ICollection assetsFoundUuids, ICollection assetsNotFoundUuids); + enum RequestState { Initial, diff --git a/OpenSim/Region/CoreModules/World/Archiver/DearchiveScenesGroup.cs b/OpenSim/Region/CoreModules/World/Archiver/DearchiveScenesGroup.cs new file mode 100644 index 0000000..3dcc020 --- /dev/null +++ b/OpenSim/Region/CoreModules/World/Archiver/DearchiveScenesGroup.cs @@ -0,0 +1,232 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using OpenSim.Region.Framework.Scenes; +using OpenMetaverse; +using System.Drawing; +using log4net; +using System.Reflection; +using OpenSim.Framework.Serialization; + +namespace OpenSim.Region.CoreModules.World.Archiver +{ + /// + /// The regions included in an OAR file. + /// + public class DearchiveScenesInfo + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + /// + /// One region in the archive. + /// + public class RegionInfo + { + /// + /// The subdirectory in which the region is stored. + /// + public string Directory { get; set; } + + /// + /// The region's coordinates (relative to the South-West corner of the block). + /// + public Point Location { get; set; } + + /// + /// The UUID of the original scene from which this archived region was saved. + /// + public string OriginalID { get; set; } + + /// + /// The scene in the current simulator into which this region is loaded. + /// If null then the region doesn't have a corresponding scene, and it won't be loaded. + /// + public Scene Scene { get; set; } + } + + /// + /// Whether this archive uses the multi-region format. + /// + public Boolean MultiRegionFormat { get; set; } + + /// + /// Maps (Region directory -> region) + /// + protected Dictionary m_directory2region = new Dictionary(); + + /// + /// Maps (UUID of the scene in the simulator where the region will be loaded -> region) + /// + protected Dictionary m_newId2region = new Dictionary(); + + public int LoadedCreationDateTime { get; set; } + public string DefaultOriginalID { get; set; } + + // These variables are used while reading the archive control file + protected int? m_curY = null; + protected int? m_curX = null; + protected RegionInfo m_curRegion; + + + public DearchiveScenesInfo() + { + MultiRegionFormat = false; + } + + + // The following methods are used while reading the archive control file + + public void StartRow() + { + m_curY = (m_curY == null) ? 0 : m_curY + 1; + m_curX = null; + } + + public void StartRegion() + { + m_curX = (m_curX == null) ? 0 : m_curX + 1; + // Note: this doesn't mean we have a real region in this location; this could just be a "hole" + } + + public void SetRegionOriginalID(string id) + { + m_curRegion = new RegionInfo(); + m_curRegion.Location = new Point((int)m_curX, (int)m_curY); + m_curRegion.OriginalID = id; + // 'curRegion' will be saved in 'm_directory2region' when SetRegionDir() is called + } + + public void SetRegionDirectory(string directory) + { + m_curRegion.Directory = directory; + m_directory2region[directory] = m_curRegion; + } + + + /// + /// Sets all the scenes present in the simulator. + /// + /// + /// This method matches regions in the archive to scenes in the simulator according to + /// their relative position. We only load regions if there's an existing Scene in the + /// grid location where the region should be loaded. + /// + /// The scene where the Load OAR operation was run + /// All the scenes in the simulator + public void SetSimulatorScenes(Scene rootScene, ArchiveScenesGroup simulatorScenes) + { + foreach (RegionInfo archivedRegion in m_directory2region.Values) + { + Point location = new Point((int)rootScene.RegionInfo.RegionLocX, (int)rootScene.RegionInfo.RegionLocY); + location.Offset(archivedRegion.Location); + + Scene scene; + if (simulatorScenes.TryGetScene(location, out scene)) + { + archivedRegion.Scene = scene; + m_newId2region[scene.RegionInfo.RegionID] = archivedRegion; + } + else + { + m_log.WarnFormat("[ARCHIVER]: Not loading archived region {0} because there's no existing region at location {1},{2}", + archivedRegion.Directory, location.X, location.Y); + } + } + } + + /// + /// Returns the archived region according to the path of a file in the archive. + /// Also, converts the full path into a path that is relative to the region's directory. + /// + /// The path of a file in the archive + /// The corresponding Scene, or null if none + /// The path relative to the region's directory. (Or the original + /// path, if this file doesn't belong to a region.) + /// True: use this file; False: skip it + public bool GetRegionFromPath(string fullPath, out Scene scene, out string relativePath) + { + scene = null; + relativePath = fullPath; + + if (!MultiRegionFormat) + { + if (m_newId2region.Count > 0) + scene = m_newId2region.First().Value.Scene; + return true; + } + + if (!fullPath.StartsWith(ArchiveConstants.REGIONS_PATH)) + return true; // this file doesn't belong to a region + + string[] parts = fullPath.Split(new Char[] { '/' }, 3); + if (parts.Length != 3) + return false; + string regionDirectory = parts[1]; + relativePath = parts[2]; + + RegionInfo region; + if (m_directory2region.TryGetValue(regionDirectory, out region)) + { + scene = region.Scene; + return (scene != null); + } + else + { + return false; + } + } + + /// + /// Returns the original UUID of a region (from the simulator where the OAR was saved), + /// given the UUID of the scene it was loaded into in the current simulator. + /// + /// + /// + public string GetOriginalRegionID(UUID newID) + { + RegionInfo region; + if (m_newId2region.TryGetValue(newID, out region)) + return region.OriginalID; + else + return DefaultOriginalID; + } + + /// + /// Returns the scenes that have been (or will be) loaded. + /// + /// + public List GetLoadedScenes() + { + return m_newId2region.Keys.ToList(); + } + + } +} diff --git a/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs b/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs index 904110e..cfdfd8c 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs @@ -47,6 +47,7 @@ using ArchiveConstants = OpenSim.Framework.Serialization.ArchiveConstants; using TarArchiveReader = OpenSim.Framework.Serialization.TarArchiveReader; using TarArchiveWriter = OpenSim.Framework.Serialization.TarArchiveWriter; using RegionSettings = OpenSim.Framework.RegionSettings; +using OpenSim.Region.Framework.Interfaces; namespace OpenSim.Region.CoreModules.World.Archiver.Tests { @@ -70,9 +71,12 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests m_scene = new SceneHelpers().SetupScene(); SceneHelpers.SetupSceneModules(m_scene, m_archiverModule, serialiserModule, terrainModule); + + new SceneManager(); + SceneManager.Instance.Add(m_scene); } - - private void LoadCompleted(Guid requestId, string errorMessage) + + private void LoadCompleted(Guid requestId, List loadedScenes, string errorMessage) { lock (this) { @@ -186,7 +190,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests Assert.That(filePath, Is.EqualTo(ArchiveConstants.CONTROL_FILE_PATH)); ArchiveReadRequest arr = new ArchiveReadRequest(m_scene, (Stream)null, false, false, Guid.Empty); - arr.LoadControlFile(filePath, data); + arr.LoadControlFile(filePath, data, new DearchiveScenesInfo()); Assert.That(arr.ControlFileLoaded, Is.True); @@ -270,7 +274,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests Assert.That(filePath, Is.EqualTo(ArchiveConstants.CONTROL_FILE_PATH)); ArchiveReadRequest arr = new ArchiveReadRequest(m_scene, (Stream)null, false, false, Guid.Empty); - arr.LoadControlFile(filePath, data); + arr.LoadControlFile(filePath, data, new DearchiveScenesInfo()); Assert.That(arr.ControlFileLoaded, Is.True); @@ -307,7 +311,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests tar.WriteFile( ArchiveConstants.CONTROL_FILE_PATH, - new ArchiveWriteRequestPreparation(null, (Stream)null, Guid.Empty).CreateControlFile(new Dictionary())); + new ArchiveWriteRequestPreparation(m_scene, (Stream)null, Guid.Empty).CreateControlFile(new ArchiveScenesGroup())); SceneObjectGroup sog1 = SceneHelpers.CreateSceneObject(1, ownerId, "obj1-", 0x11); SceneObjectPart sop2 @@ -362,11 +366,10 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests // Also check that direct entries which will also have a file entry containing that directory doesn't // upset load tar.WriteDir(ArchiveConstants.TERRAINS_PATH); - + tar.WriteFile( ArchiveConstants.CONTROL_FILE_PATH, - new ArchiveWriteRequestPreparation(null, (Stream)null, Guid.Empty).CreateControlFile(new Dictionary())); - + new ArchiveWriteRequestPreparation(m_scene, (Stream)null, Guid.Empty).CreateControlFile(new ArchiveScenesGroup())); SceneObjectPart part1 = CreateSceneObjectPart1(); part1.SitTargetOrientation = new Quaternion(0.2f, 0.3f, 0.4f, 0.5f); @@ -519,6 +522,8 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests TestScene scene2 = new SceneHelpers().SetupScene(); SceneHelpers.SetupSceneModules(scene2, archiverModule, serialiserModule, terrainModule); + SceneManager.Instance.Add(scene2); + // Make sure there's a valid owner for the owner we saved (this should have been wiped if the code is // behaving correctly UserAccountHelpers.CreateUserWithInventory(scene2, objectOwner); @@ -554,7 +559,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests tar.WriteDir(ArchiveConstants.TERRAINS_PATH); tar.WriteFile( ArchiveConstants.CONTROL_FILE_PATH, - new ArchiveWriteRequestPreparation(null, (Stream)null, Guid.Empty).CreateControlFile(new Dictionary())); + new ArchiveWriteRequestPreparation(m_scene, (Stream)null, Guid.Empty).CreateControlFile(new ArchiveScenesGroup())); RegionSettings rs = new RegionSettings(); rs.AgentLimit = 17; diff --git a/OpenSim/Region/Framework/Interfaces/IEstateModule.cs b/OpenSim/Region/Framework/Interfaces/IEstateModule.cs index 15cd238..1983984 100644 --- a/OpenSim/Region/Framework/Interfaces/IEstateModule.cs +++ b/OpenSim/Region/Framework/Interfaces/IEstateModule.cs @@ -46,6 +46,11 @@ namespace OpenSim.Region.Framework.Interfaces /// void sendRegionHandshakeToAll(); + /// + /// Fires the OnRegionInfoChange event. + /// + void TriggerRegionInfoChange(); + void setEstateTerrainBaseTexture(int level, UUID texture); void setEstateTerrainTextureHeights(int corner, float lowValue, float highValue); } diff --git a/OpenSim/Region/Framework/Scenes/EventManager.cs b/OpenSim/Region/Framework/Scenes/EventManager.cs index 2f34785..e1c9c8e 100644 --- a/OpenSim/Region/Framework/Scenes/EventManager.cs +++ b/OpenSim/Region/Framework/Scenes/EventManager.cs @@ -531,7 +531,7 @@ namespace OpenSim.Region.Framework.Scenes /// the scripts may not have started yet /// Message is non empty string if there were problems loading the oar file /// - public delegate void OarFileLoaded(Guid guid, string message); + public delegate void OarFileLoaded(Guid guid, List loadedScenes, string message); public event OarFileLoaded OnOarFileLoaded; /// @@ -2195,7 +2195,7 @@ namespace OpenSim.Region.Framework.Scenes return 6; } - public void TriggerOarFileLoaded(Guid requestId, string message) + public void TriggerOarFileLoaded(Guid requestId, List loadedScenes, string message) { OarFileLoaded handlerOarFileLoaded = OnOarFileLoaded; if (handlerOarFileLoaded != null) @@ -2204,7 +2204,7 @@ namespace OpenSim.Region.Framework.Scenes { try { - d(requestId, message); + d(requestId, loadedScenes, message); } catch (Exception e) { diff --git a/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs b/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs index fff3a32..bad75f7 100644 --- a/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs +++ b/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs @@ -181,7 +181,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.RegionReady } } - void OnOarFileLoaded(Guid requestId, string message) + void OnOarFileLoaded(Guid requestId, List loadedScenes, string message) { m_oarFileLoading = true; -- cgit v1.1 From d7e6fe488d5258ec92230b6c652969f2d0420376 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 7 Sep 2012 23:30:54 +0100 Subject: Rename ArchiveWriteRequestPreparatio nto ArchiveWriteRequest since after the multi-OAR patch there is now only one class that handles this operation. Adapation of 0004-Renamed-ArchiveWriteRequestPreparation-to-ArchiveWri.patch in http://opensimulator.org/mantis/view.php?id=6105 since that did not directly apply --- .../World/Archiver/ArchiveWriteRequest.cs | 634 +++++++++++++++++++++ .../Archiver/ArchiveWriteRequestPreparation.cs | 634 --------------------- .../CoreModules/World/Archiver/ArchiverModule.cs | 4 +- .../World/Archiver/Tests/ArchiverTests.cs | 6 +- 4 files changed, 639 insertions(+), 639 deletions(-) create mode 100644 OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequest.cs delete mode 100644 OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestPreparation.cs (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequest.cs new file mode 100644 index 0000000..d751b1c --- /dev/null +++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequest.cs @@ -0,0 +1,634 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections.Generic; +using System.IO; +using System.IO.Compression; +using System.Reflection; +using System.Text.RegularExpressions; +using System.Threading; +using System.Xml; +using log4net; +using OpenMetaverse; +using OpenSim.Framework; +using OpenSim.Framework.Serialization; +using OpenSim.Region.CoreModules.World.Terrain; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; +using Ionic.Zlib; +using GZipStream = Ionic.Zlib.GZipStream; +using CompressionMode = Ionic.Zlib.CompressionMode; +using OpenSim.Framework.Serialization.External; + +namespace OpenSim.Region.CoreModules.World.Archiver +{ + /// + /// Prepare to write out an archive. + /// + public class ArchiveWriteRequest + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + /// + /// The minimum major version of OAR that we can write. + /// + public static int MIN_MAJOR_VERSION = 0; + + /// + /// The maximum major version of OAR that we can write. + /// + public static int MAX_MAJOR_VERSION = 1; + + /// + /// Whether we're saving a multi-region archive. + /// + public bool MultiRegionFormat { get; set; } + + /// + /// Determine whether this archive will save assets. Default is true. + /// + public bool SaveAssets { get; set; } + + /// + /// Determines which objects will be included in the archive, according to their permissions. + /// Default is null, meaning no permission checks. + /// + public string CheckPermissions { get; set; } + + protected Scene m_rootScene; + protected Stream m_saveStream; + protected TarArchiveWriter m_archiveWriter; + protected Guid m_requestId; + protected Dictionary m_options; + + /// + /// Constructor + /// + /// Calling module + /// The path to which to save data. + /// The id associated with this request + /// + /// If there was a problem opening a stream for the file specified by the savePath + /// + public ArchiveWriteRequest(Scene scene, string savePath, Guid requestId) : this(scene, requestId) + { + try + { + m_saveStream = new GZipStream(new FileStream(savePath, FileMode.Create), CompressionMode.Compress, CompressionLevel.BestCompression); + } + catch (EntryPointNotFoundException e) + { + m_log.ErrorFormat( + "[ARCHIVER]: Mismatch between Mono and zlib1g library version when trying to create compression stream." + + "If you've manually installed Mono, have you appropriately updated zlib1g as well?"); + m_log.ErrorFormat("{0} {1}", e.Message, e.StackTrace); + } + } + + /// + /// Constructor. + /// + /// The root scene to archive + /// The stream to which to save data. + /// The id associated with this request + public ArchiveWriteRequest(Scene scene, Stream saveStream, Guid requestId) : this(scene, requestId) + { + m_saveStream = saveStream; + } + + protected ArchiveWriteRequest(Scene scene, Guid requestId) + { + m_rootScene = scene; + m_requestId = requestId; + m_archiveWriter = null; + + MultiRegionFormat = false; + SaveAssets = true; + CheckPermissions = null; + } + + /// + /// Archive the region requested. + /// + /// if there was an io problem with creating the file + public void ArchiveRegion(Dictionary options) + { + m_options = options; + + if (options.ContainsKey("all") && (bool)options["all"]) + MultiRegionFormat = true; + + if (options.ContainsKey("noassets") && (bool)options["noassets"]) + SaveAssets = false; + + Object temp; + if (options.TryGetValue("checkPermissions", out temp)) + CheckPermissions = (string)temp; + + + // Find the regions to archive + ArchiveScenesGroup scenesGroup = new ArchiveScenesGroup(); + if (MultiRegionFormat) + { + m_log.InfoFormat("[ARCHIVER]: Saving {0} regions", SceneManager.Instance.Scenes.Count); + SceneManager.Instance.ForEachScene(delegate(Scene scene) + { + scenesGroup.AddScene(scene); + }); + } + else + { + scenesGroup.AddScene(m_rootScene); + } + scenesGroup.CalcSceneLocations(); + + + m_archiveWriter = new TarArchiveWriter(m_saveStream); + + try + { + // Write out control file. It should be first so that it will be found ASAP when loading the file. + m_archiveWriter.WriteFile(ArchiveConstants.CONTROL_FILE_PATH, CreateControlFile(scenesGroup)); + m_log.InfoFormat("[ARCHIVER]: Added control file to archive."); + + // Archive the regions + + Dictionary assetUuids = new Dictionary(); + + scenesGroup.ForEachScene(delegate(Scene scene) + { + string regionDir = MultiRegionFormat ? scenesGroup.GetRegionDir(scene.RegionInfo.RegionID) : ""; + ArchiveOneRegion(scene, regionDir, assetUuids); + }); + + // Archive the assets + + if (SaveAssets) + { + m_log.DebugFormat("[ARCHIVER]: Saving {0} assets", assetUuids.Count); + + // Asynchronously request all the assets required to perform this archive operation + AssetsRequest ar + = new AssetsRequest( + new AssetsArchiver(m_archiveWriter), assetUuids, + m_rootScene.AssetService, m_rootScene.UserAccountService, + m_rootScene.RegionInfo.ScopeID, options, ReceivedAllAssets); + + Util.FireAndForget(o => ar.Execute()); + + // CloseArchive() will be called from ReceivedAllAssets() + } + else + { + m_log.DebugFormat("[ARCHIVER]: Not saving assets since --noassets was specified"); + CloseArchive(string.Empty); + } + } + catch (Exception e) + { + CloseArchive(e.Message); + throw; + } + } + + + private void ArchiveOneRegion(Scene scene, string regionDir, Dictionary assetUuids) + { + m_log.InfoFormat("[ARCHIVER]: Writing region {0}", scene.RegionInfo.RegionName); + + EntityBase[] entities = scene.GetEntities(); + List sceneObjects = new List(); + + int numObjectsSkippedPermissions = 0; + + // Filter entities so that we only have scene objects. + // FIXME: Would be nicer to have this as a proper list in SceneGraph, since lots of methods + // end up having to do this + IPermissionsModule permissionsModule = scene.RequestModuleInterface(); + foreach (EntityBase entity in entities) + { + if (entity is SceneObjectGroup) + { + SceneObjectGroup sceneObject = (SceneObjectGroup)entity; + + if (!sceneObject.IsDeleted && !sceneObject.IsAttachment) + { + if (!CanUserArchiveObject(scene.RegionInfo.EstateSettings.EstateOwner, sceneObject, CheckPermissions, permissionsModule)) + { + // The user isn't allowed to copy/transfer this object, so it will not be included in the OAR. + ++numObjectsSkippedPermissions; + } + else + { + sceneObjects.Add(sceneObject); + } + } + } + } + + if (SaveAssets) + { + UuidGatherer assetGatherer = new UuidGatherer(scene.AssetService); + int prevAssets = assetUuids.Count; + + foreach (SceneObjectGroup sceneObject in sceneObjects) + { + assetGatherer.GatherAssetUuids(sceneObject, assetUuids); + } + + m_log.DebugFormat( + "[ARCHIVER]: {0} scene objects to serialize requiring save of {1} assets", + sceneObjects.Count, assetUuids.Count - prevAssets); + } + + if (numObjectsSkippedPermissions > 0) + { + m_log.DebugFormat( + "[ARCHIVER]: {0} scene objects skipped due to lack of permissions", + numObjectsSkippedPermissions); + } + + // Make sure that we also request terrain texture assets + RegionSettings regionSettings = scene.RegionInfo.RegionSettings; + + if (regionSettings.TerrainTexture1 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_1) + assetUuids[regionSettings.TerrainTexture1] = AssetType.Texture; + + if (regionSettings.TerrainTexture2 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_2) + assetUuids[regionSettings.TerrainTexture2] = AssetType.Texture; + + if (regionSettings.TerrainTexture3 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_3) + assetUuids[regionSettings.TerrainTexture3] = AssetType.Texture; + + if (regionSettings.TerrainTexture4 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_4) + assetUuids[regionSettings.TerrainTexture4] = AssetType.Texture; + + Save(scene, sceneObjects, regionDir); + } + + /// + /// Checks whether the user has permission to export an object group to an OAR. + /// + /// The user + /// The object group + /// Which permissions to check: "C" = Copy, "T" = Transfer + /// The scene's permissions module + /// Whether the user is allowed to export the object to an OAR + private bool CanUserArchiveObject(UUID user, SceneObjectGroup objGroup, string checkPermissions, IPermissionsModule permissionsModule) + { + if (checkPermissions == null) + return true; + + if (permissionsModule == null) + return true; // this shouldn't happen + + // Check whether the user is permitted to export all of the parts in the SOG. If any + // part can't be exported then the entire SOG can't be exported. + + bool permitted = true; + //int primNumber = 1; + + foreach (SceneObjectPart obj in objGroup.Parts) + { + uint perm; + PermissionClass permissionClass = permissionsModule.GetPermissionClass(user, obj); + switch (permissionClass) + { + case PermissionClass.Owner: + perm = obj.BaseMask; + break; + case PermissionClass.Group: + perm = obj.GroupMask | obj.EveryoneMask; + break; + case PermissionClass.Everyone: + default: + perm = obj.EveryoneMask; + break; + } + + bool canCopy = (perm & (uint)PermissionMask.Copy) != 0; + bool canTransfer = (perm & (uint)PermissionMask.Transfer) != 0; + + // Special case: if Everyone can copy the object then this implies it can also be + // Transferred. + // However, if the user is the Owner then we don't check EveryoneMask, because it seems that the mask + // always (incorrectly) includes the Copy bit set in this case. But that's a mistake: the viewer + // does NOT show that the object has Everyone-Copy permissions, and doesn't allow it to be copied. + if (permissionClass != PermissionClass.Owner) + canTransfer |= (obj.EveryoneMask & (uint)PermissionMask.Copy) != 0; + + bool partPermitted = true; + if (checkPermissions.Contains("C") && !canCopy) + partPermitted = false; + if (checkPermissions.Contains("T") && !canTransfer) + partPermitted = false; + + // If the user is the Creator of the object then it can always be included in the OAR + bool creator = (obj.CreatorID.Guid == user.Guid); + if (creator) + partPermitted = true; + + //string name = (objGroup.PrimCount == 1) ? objGroup.Name : string.Format("{0} ({1}/{2})", obj.Name, primNumber, objGroup.PrimCount); + //m_log.DebugFormat("[ARCHIVER]: Object permissions: {0}: Base={1:X4}, Owner={2:X4}, Everyone={3:X4}, permissionClass={4}, checkPermissions={5}, canCopy={6}, canTransfer={7}, creator={8}, permitted={9}", + // name, obj.BaseMask, obj.OwnerMask, obj.EveryoneMask, + // permissionClass, checkPermissions, canCopy, canTransfer, creator, partPermitted); + + if (!partPermitted) + { + permitted = false; + break; + } + + //++primNumber; + } + + return permitted; + } + + /// + /// Create the control file. + /// + /// + public string CreateControlFile(ArchiveScenesGroup scenesGroup) + { + int majorVersion; + int minorVersion; + + if (MultiRegionFormat) + { + majorVersion = MAX_MAJOR_VERSION; + minorVersion = 0; + } + else + { + // To support older versions of OpenSim, we continue to create single-region OARs + // using the old file format. In the future this format will be discontinued. + majorVersion = 0; + minorVersion = 8; + } +// +// if (m_options.ContainsKey("version")) +// { +// string[] parts = m_options["version"].ToString().Split('.'); +// if (parts.Length >= 1) +// { +// majorVersion = Int32.Parse(parts[0]); +// +// if (parts.Length >= 2) +// minorVersion = Int32.Parse(parts[1]); +// } +// } +// +// if (majorVersion < MIN_MAJOR_VERSION || majorVersion > MAX_MAJOR_VERSION) +// { +// throw new Exception( +// string.Format( +// "OAR version number for save must be between {0} and {1}", +// MIN_MAJOR_VERSION, MAX_MAJOR_VERSION)); +// } +// else if (majorVersion == MAX_MAJOR_VERSION) +// { +// // Force 1.0 +// minorVersion = 0; +// } +// else if (majorVersion == MIN_MAJOR_VERSION) +// { +// // Force 0.4 +// minorVersion = 4; +// } + + m_log.InfoFormat("[ARCHIVER]: Creating version {0}.{1} OAR", majorVersion, minorVersion); + if (majorVersion == 1) + { + m_log.WarnFormat("[ARCHIVER]: Please be aware that version 1.0 OARs are not compatible with OpenSim versions prior to 0.7.4. Do not use the --all option if you want to produce a compatible OAR"); + } + + String s; + + using (StringWriter sw = new StringWriter()) + { + using (XmlTextWriter xtw = new XmlTextWriter(sw)) + { + xtw.Formatting = Formatting.Indented; + xtw.WriteStartDocument(); + xtw.WriteStartElement("archive"); + xtw.WriteAttributeString("major_version", majorVersion.ToString()); + xtw.WriteAttributeString("minor_version", minorVersion.ToString()); + + xtw.WriteStartElement("creation_info"); + DateTime now = DateTime.UtcNow; + TimeSpan t = now - new DateTime(1970, 1, 1); + xtw.WriteElementString("datetime", ((int)t.TotalSeconds).ToString()); + if (!MultiRegionFormat) + xtw.WriteElementString("id", m_rootScene.RegionInfo.RegionID.ToString()); + xtw.WriteEndElement(); + + xtw.WriteElementString("assets_included", SaveAssets.ToString()); + + if (MultiRegionFormat) + { + WriteRegionsManifest(scenesGroup, xtw); + } + else + { + xtw.WriteStartElement("region_info"); + WriteRegionInfo(m_rootScene, xtw); + xtw.WriteEndElement(); + } + + xtw.WriteEndElement(); + + xtw.Flush(); + } + + s = sw.ToString(); + } + + return s; + } + + /// + /// Writes the list of regions included in a multi-region OAR. + /// + private static void WriteRegionsManifest(ArchiveScenesGroup scenesGroup, XmlTextWriter xtw) + { + xtw.WriteStartElement("regions"); + + // Write the regions in order: rows from South to North, then regions from West to East. + // The list of regions can have "holes"; we write empty elements in their position. + + for (uint y = (uint)scenesGroup.Rect.Top; y < scenesGroup.Rect.Bottom; ++y) + { + SortedDictionary row; + if (scenesGroup.Regions.TryGetValue(y, out row)) + { + xtw.WriteStartElement("row"); + + for (uint x = (uint)scenesGroup.Rect.Left; x < scenesGroup.Rect.Right; ++x) + { + Scene scene; + if (row.TryGetValue(x, out scene)) + { + xtw.WriteStartElement("region"); + xtw.WriteElementString("id", scene.RegionInfo.RegionID.ToString()); + xtw.WriteElementString("dir", scenesGroup.GetRegionDir(scene.RegionInfo.RegionID)); + WriteRegionInfo(scene, xtw); + xtw.WriteEndElement(); + } + else + { + // Write a placeholder for a missing region + xtw.WriteElementString("region", ""); + } + } + + xtw.WriteEndElement(); + } + else + { + // Write a placeholder for a missing row + xtw.WriteElementString("row", ""); + } + } + + xtw.WriteEndElement(); // "regions" + } + + protected static void WriteRegionInfo(Scene scene, XmlTextWriter xtw) + { + bool isMegaregion; + Vector2 size; + + IRegionCombinerModule rcMod = scene.RequestModuleInterface(); + + if (rcMod != null) + isMegaregion = rcMod.IsRootForMegaregion(scene.RegionInfo.RegionID); + else + isMegaregion = false; + + if (isMegaregion) + size = rcMod.GetSizeOfMegaregion(scene.RegionInfo.RegionID); + else + size = new Vector2((float)Constants.RegionSize, (float)Constants.RegionSize); + + xtw.WriteElementString("is_megaregion", isMegaregion.ToString()); + xtw.WriteElementString("size_in_meters", string.Format("{0},{1}", size.X, size.Y)); + } + + + protected void Save(Scene scene, List sceneObjects, string regionDir) + { + if (regionDir != string.Empty) + regionDir = ArchiveConstants.REGIONS_PATH + regionDir + "/"; + + m_log.InfoFormat("[ARCHIVER]: Adding region settings to archive."); + + // Write out region settings + string settingsPath = String.Format("{0}{1}{2}.xml", + regionDir, ArchiveConstants.SETTINGS_PATH, scene.RegionInfo.RegionName); + m_archiveWriter.WriteFile(settingsPath, RegionSettingsSerializer.Serialize(scene.RegionInfo.RegionSettings)); + + m_log.InfoFormat("[ARCHIVER]: Adding parcel settings to archive."); + + // Write out land data (aka parcel) settings + List landObjects = scene.LandChannel.AllParcels(); + foreach (ILandObject lo in landObjects) + { + LandData landData = lo.LandData; + string landDataPath = String.Format("{0}{1}{2}.xml", + regionDir, ArchiveConstants.LANDDATA_PATH, landData.GlobalID.ToString()); + m_archiveWriter.WriteFile(landDataPath, LandDataSerializer.Serialize(landData, m_options)); + } + + m_log.InfoFormat("[ARCHIVER]: Adding terrain information to archive."); + + // Write out terrain + string terrainPath = String.Format("{0}{1}{2}.r32", + regionDir, ArchiveConstants.TERRAINS_PATH, scene.RegionInfo.RegionName); + + MemoryStream ms = new MemoryStream(); + scene.RequestModuleInterface().SaveToStream(terrainPath, ms); + m_archiveWriter.WriteFile(terrainPath, ms.ToArray()); + ms.Close(); + + m_log.InfoFormat("[ARCHIVER]: Adding scene objects to archive."); + + // Write out scene object metadata + IRegionSerialiserModule serializer = scene.RequestModuleInterface(); + foreach (SceneObjectGroup sceneObject in sceneObjects) + { + //m_log.DebugFormat("[ARCHIVER]: Saving {0} {1}, {2}", entity.Name, entity.UUID, entity.GetType()); + + string serializedObject = serializer.SerializeGroupToXml2(sceneObject, m_options); + string objectPath = string.Format("{0}{1}", regionDir, ArchiveHelpers.CreateObjectPath(sceneObject)); + m_archiveWriter.WriteFile(objectPath, serializedObject); + } + } + + protected void ReceivedAllAssets( + ICollection assetsFoundUuids, ICollection assetsNotFoundUuids) + { + foreach (UUID uuid in assetsNotFoundUuids) + { + m_log.DebugFormat("[ARCHIVER]: Could not find asset {0}", uuid); + } + + // m_log.InfoFormat( + // "[ARCHIVER]: Received {0} of {1} assets requested", + // assetsFoundUuids.Count, assetsFoundUuids.Count + assetsNotFoundUuids.Count); + + CloseArchive(String.Empty); + } + + + /// + /// Closes the archive and notifies that we're done. + /// + /// The error that occurred, or empty for success + protected void CloseArchive(string errorMessage) + { + try + { + if (m_archiveWriter != null) + m_archiveWriter.Close(); + m_saveStream.Close(); + } + catch (Exception e) + { + m_log.Error(string.Format("[ARCHIVER]: Error closing archive: {0} ", e.Message), e); + if (errorMessage == string.Empty) + errorMessage = e.Message; + } + + m_log.InfoFormat("[ARCHIVER]: Finished writing out OAR for {0}", m_rootScene.RegionInfo.RegionName); + + m_rootScene.EventManager.TriggerOarFileSaved(m_requestId, errorMessage); + } + + } +} diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestPreparation.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestPreparation.cs deleted file mode 100644 index 2c34f4b..0000000 --- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestPreparation.cs +++ /dev/null @@ -1,634 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.IO; -using System.IO.Compression; -using System.Reflection; -using System.Text.RegularExpressions; -using System.Threading; -using System.Xml; -using log4net; -using OpenMetaverse; -using OpenSim.Framework; -using OpenSim.Framework.Serialization; -using OpenSim.Region.CoreModules.World.Terrain; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; -using Ionic.Zlib; -using GZipStream = Ionic.Zlib.GZipStream; -using CompressionMode = Ionic.Zlib.CompressionMode; -using OpenSim.Framework.Serialization.External; - -namespace OpenSim.Region.CoreModules.World.Archiver -{ - /// - /// Prepare to write out an archive. - /// - public class ArchiveWriteRequestPreparation - { - private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - /// - /// The minimum major version of OAR that we can write. - /// - public static int MIN_MAJOR_VERSION = 0; - - /// - /// The maximum major version of OAR that we can write. - /// - public static int MAX_MAJOR_VERSION = 1; - - /// - /// Whether we're saving a multi-region archive. - /// - public bool MultiRegionFormat { get; set; } - - /// - /// Determine whether this archive will save assets. Default is true. - /// - public bool SaveAssets { get; set; } - - /// - /// Determines which objects will be included in the archive, according to their permissions. - /// Default is null, meaning no permission checks. - /// - public string CheckPermissions { get; set; } - - protected Scene m_rootScene; - protected Stream m_saveStream; - protected TarArchiveWriter m_archiveWriter; - protected Guid m_requestId; - protected Dictionary m_options; - - /// - /// Constructor - /// - /// Calling module - /// The path to which to save data. - /// The id associated with this request - /// - /// If there was a problem opening a stream for the file specified by the savePath - /// - public ArchiveWriteRequestPreparation(Scene scene, string savePath, Guid requestId) : this(scene, requestId) - { - try - { - m_saveStream = new GZipStream(new FileStream(savePath, FileMode.Create), CompressionMode.Compress, CompressionLevel.BestCompression); - } - catch (EntryPointNotFoundException e) - { - m_log.ErrorFormat( - "[ARCHIVER]: Mismatch between Mono and zlib1g library version when trying to create compression stream." - + "If you've manually installed Mono, have you appropriately updated zlib1g as well?"); - m_log.ErrorFormat("{0} {1}", e.Message, e.StackTrace); - } - } - - /// - /// Constructor. - /// - /// The root scene to archive - /// The stream to which to save data. - /// The id associated with this request - public ArchiveWriteRequestPreparation(Scene scene, Stream saveStream, Guid requestId) : this(scene, requestId) - { - m_saveStream = saveStream; - } - - protected ArchiveWriteRequestPreparation(Scene scene, Guid requestId) - { - m_rootScene = scene; - m_requestId = requestId; - m_archiveWriter = null; - - MultiRegionFormat = false; - SaveAssets = true; - CheckPermissions = null; - } - - /// - /// Archive the region requested. - /// - /// if there was an io problem with creating the file - public void ArchiveRegion(Dictionary options) - { - m_options = options; - - if (options.ContainsKey("all") && (bool)options["all"]) - MultiRegionFormat = true; - - if (options.ContainsKey("noassets") && (bool)options["noassets"]) - SaveAssets = false; - - Object temp; - if (options.TryGetValue("checkPermissions", out temp)) - CheckPermissions = (string)temp; - - - // Find the regions to archive - ArchiveScenesGroup scenesGroup = new ArchiveScenesGroup(); - if (MultiRegionFormat) - { - m_log.InfoFormat("[ARCHIVER]: Saving {0} regions", SceneManager.Instance.Scenes.Count); - SceneManager.Instance.ForEachScene(delegate(Scene scene) - { - scenesGroup.AddScene(scene); - }); - } - else - { - scenesGroup.AddScene(m_rootScene); - } - scenesGroup.CalcSceneLocations(); - - - m_archiveWriter = new TarArchiveWriter(m_saveStream); - - try - { - // Write out control file. It should be first so that it will be found ASAP when loading the file. - m_archiveWriter.WriteFile(ArchiveConstants.CONTROL_FILE_PATH, CreateControlFile(scenesGroup)); - m_log.InfoFormat("[ARCHIVER]: Added control file to archive."); - - // Archive the regions - - Dictionary assetUuids = new Dictionary(); - - scenesGroup.ForEachScene(delegate(Scene scene) - { - string regionDir = MultiRegionFormat ? scenesGroup.GetRegionDir(scene.RegionInfo.RegionID) : ""; - ArchiveOneRegion(scene, regionDir, assetUuids); - }); - - // Archive the assets - - if (SaveAssets) - { - m_log.DebugFormat("[ARCHIVER]: Saving {0} assets", assetUuids.Count); - - // Asynchronously request all the assets required to perform this archive operation - AssetsRequest ar - = new AssetsRequest( - new AssetsArchiver(m_archiveWriter), assetUuids, - m_rootScene.AssetService, m_rootScene.UserAccountService, - m_rootScene.RegionInfo.ScopeID, options, ReceivedAllAssets); - - Util.FireAndForget(o => ar.Execute()); - - // CloseArchive() will be called from ReceivedAllAssets() - } - else - { - m_log.DebugFormat("[ARCHIVER]: Not saving assets since --noassets was specified"); - CloseArchive(string.Empty); - } - } - catch (Exception e) - { - CloseArchive(e.Message); - throw; - } - } - - - private void ArchiveOneRegion(Scene scene, string regionDir, Dictionary assetUuids) - { - m_log.InfoFormat("[ARCHIVER]: Writing region {0}", scene.RegionInfo.RegionName); - - EntityBase[] entities = scene.GetEntities(); - List sceneObjects = new List(); - - int numObjectsSkippedPermissions = 0; - - // Filter entities so that we only have scene objects. - // FIXME: Would be nicer to have this as a proper list in SceneGraph, since lots of methods - // end up having to do this - IPermissionsModule permissionsModule = scene.RequestModuleInterface(); - foreach (EntityBase entity in entities) - { - if (entity is SceneObjectGroup) - { - SceneObjectGroup sceneObject = (SceneObjectGroup)entity; - - if (!sceneObject.IsDeleted && !sceneObject.IsAttachment) - { - if (!CanUserArchiveObject(scene.RegionInfo.EstateSettings.EstateOwner, sceneObject, CheckPermissions, permissionsModule)) - { - // The user isn't allowed to copy/transfer this object, so it will not be included in the OAR. - ++numObjectsSkippedPermissions; - } - else - { - sceneObjects.Add(sceneObject); - } - } - } - } - - if (SaveAssets) - { - UuidGatherer assetGatherer = new UuidGatherer(scene.AssetService); - int prevAssets = assetUuids.Count; - - foreach (SceneObjectGroup sceneObject in sceneObjects) - { - assetGatherer.GatherAssetUuids(sceneObject, assetUuids); - } - - m_log.DebugFormat( - "[ARCHIVER]: {0} scene objects to serialize requiring save of {1} assets", - sceneObjects.Count, assetUuids.Count - prevAssets); - } - - if (numObjectsSkippedPermissions > 0) - { - m_log.DebugFormat( - "[ARCHIVER]: {0} scene objects skipped due to lack of permissions", - numObjectsSkippedPermissions); - } - - // Make sure that we also request terrain texture assets - RegionSettings regionSettings = scene.RegionInfo.RegionSettings; - - if (regionSettings.TerrainTexture1 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_1) - assetUuids[regionSettings.TerrainTexture1] = AssetType.Texture; - - if (regionSettings.TerrainTexture2 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_2) - assetUuids[regionSettings.TerrainTexture2] = AssetType.Texture; - - if (regionSettings.TerrainTexture3 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_3) - assetUuids[regionSettings.TerrainTexture3] = AssetType.Texture; - - if (regionSettings.TerrainTexture4 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_4) - assetUuids[regionSettings.TerrainTexture4] = AssetType.Texture; - - Save(scene, sceneObjects, regionDir); - } - - /// - /// Checks whether the user has permission to export an object group to an OAR. - /// - /// The user - /// The object group - /// Which permissions to check: "C" = Copy, "T" = Transfer - /// The scene's permissions module - /// Whether the user is allowed to export the object to an OAR - private bool CanUserArchiveObject(UUID user, SceneObjectGroup objGroup, string checkPermissions, IPermissionsModule permissionsModule) - { - if (checkPermissions == null) - return true; - - if (permissionsModule == null) - return true; // this shouldn't happen - - // Check whether the user is permitted to export all of the parts in the SOG. If any - // part can't be exported then the entire SOG can't be exported. - - bool permitted = true; - //int primNumber = 1; - - foreach (SceneObjectPart obj in objGroup.Parts) - { - uint perm; - PermissionClass permissionClass = permissionsModule.GetPermissionClass(user, obj); - switch (permissionClass) - { - case PermissionClass.Owner: - perm = obj.BaseMask; - break; - case PermissionClass.Group: - perm = obj.GroupMask | obj.EveryoneMask; - break; - case PermissionClass.Everyone: - default: - perm = obj.EveryoneMask; - break; - } - - bool canCopy = (perm & (uint)PermissionMask.Copy) != 0; - bool canTransfer = (perm & (uint)PermissionMask.Transfer) != 0; - - // Special case: if Everyone can copy the object then this implies it can also be - // Transferred. - // However, if the user is the Owner then we don't check EveryoneMask, because it seems that the mask - // always (incorrectly) includes the Copy bit set in this case. But that's a mistake: the viewer - // does NOT show that the object has Everyone-Copy permissions, and doesn't allow it to be copied. - if (permissionClass != PermissionClass.Owner) - canTransfer |= (obj.EveryoneMask & (uint)PermissionMask.Copy) != 0; - - bool partPermitted = true; - if (checkPermissions.Contains("C") && !canCopy) - partPermitted = false; - if (checkPermissions.Contains("T") && !canTransfer) - partPermitted = false; - - // If the user is the Creator of the object then it can always be included in the OAR - bool creator = (obj.CreatorID.Guid == user.Guid); - if (creator) - partPermitted = true; - - //string name = (objGroup.PrimCount == 1) ? objGroup.Name : string.Format("{0} ({1}/{2})", obj.Name, primNumber, objGroup.PrimCount); - //m_log.DebugFormat("[ARCHIVER]: Object permissions: {0}: Base={1:X4}, Owner={2:X4}, Everyone={3:X4}, permissionClass={4}, checkPermissions={5}, canCopy={6}, canTransfer={7}, creator={8}, permitted={9}", - // name, obj.BaseMask, obj.OwnerMask, obj.EveryoneMask, - // permissionClass, checkPermissions, canCopy, canTransfer, creator, partPermitted); - - if (!partPermitted) - { - permitted = false; - break; - } - - //++primNumber; - } - - return permitted; - } - - /// - /// Create the control file. - /// - /// - public string CreateControlFile(ArchiveScenesGroup scenesGroup) - { - int majorVersion; - int minorVersion; - - if (MultiRegionFormat) - { - majorVersion = MAX_MAJOR_VERSION; - minorVersion = 0; - } - else - { - // To support older versions of OpenSim, we continue to create single-region OARs - // using the old file format. In the future this format will be discontinued. - majorVersion = 0; - minorVersion = 8; - } -// -// if (m_options.ContainsKey("version")) -// { -// string[] parts = m_options["version"].ToString().Split('.'); -// if (parts.Length >= 1) -// { -// majorVersion = Int32.Parse(parts[0]); -// -// if (parts.Length >= 2) -// minorVersion = Int32.Parse(parts[1]); -// } -// } -// -// if (majorVersion < MIN_MAJOR_VERSION || majorVersion > MAX_MAJOR_VERSION) -// { -// throw new Exception( -// string.Format( -// "OAR version number for save must be between {0} and {1}", -// MIN_MAJOR_VERSION, MAX_MAJOR_VERSION)); -// } -// else if (majorVersion == MAX_MAJOR_VERSION) -// { -// // Force 1.0 -// minorVersion = 0; -// } -// else if (majorVersion == MIN_MAJOR_VERSION) -// { -// // Force 0.4 -// minorVersion = 4; -// } - - m_log.InfoFormat("[ARCHIVER]: Creating version {0}.{1} OAR", majorVersion, minorVersion); - if (majorVersion == 1) - { - m_log.WarnFormat("[ARCHIVER]: Please be aware that version 1.0 OARs are not compatible with OpenSim versions prior to 0.7.4. Do not use the --all option if you want to produce a compatible OAR"); - } - - String s; - - using (StringWriter sw = new StringWriter()) - { - using (XmlTextWriter xtw = new XmlTextWriter(sw)) - { - xtw.Formatting = Formatting.Indented; - xtw.WriteStartDocument(); - xtw.WriteStartElement("archive"); - xtw.WriteAttributeString("major_version", majorVersion.ToString()); - xtw.WriteAttributeString("minor_version", minorVersion.ToString()); - - xtw.WriteStartElement("creation_info"); - DateTime now = DateTime.UtcNow; - TimeSpan t = now - new DateTime(1970, 1, 1); - xtw.WriteElementString("datetime", ((int)t.TotalSeconds).ToString()); - if (!MultiRegionFormat) - xtw.WriteElementString("id", m_rootScene.RegionInfo.RegionID.ToString()); - xtw.WriteEndElement(); - - xtw.WriteElementString("assets_included", SaveAssets.ToString()); - - if (MultiRegionFormat) - { - WriteRegionsManifest(scenesGroup, xtw); - } - else - { - xtw.WriteStartElement("region_info"); - WriteRegionInfo(m_rootScene, xtw); - xtw.WriteEndElement(); - } - - xtw.WriteEndElement(); - - xtw.Flush(); - } - - s = sw.ToString(); - } - - return s; - } - - /// - /// Writes the list of regions included in a multi-region OAR. - /// - private static void WriteRegionsManifest(ArchiveScenesGroup scenesGroup, XmlTextWriter xtw) - { - xtw.WriteStartElement("regions"); - - // Write the regions in order: rows from South to North, then regions from West to East. - // The list of regions can have "holes"; we write empty elements in their position. - - for (uint y = (uint)scenesGroup.Rect.Top; y < scenesGroup.Rect.Bottom; ++y) - { - SortedDictionary row; - if (scenesGroup.Regions.TryGetValue(y, out row)) - { - xtw.WriteStartElement("row"); - - for (uint x = (uint)scenesGroup.Rect.Left; x < scenesGroup.Rect.Right; ++x) - { - Scene scene; - if (row.TryGetValue(x, out scene)) - { - xtw.WriteStartElement("region"); - xtw.WriteElementString("id", scene.RegionInfo.RegionID.ToString()); - xtw.WriteElementString("dir", scenesGroup.GetRegionDir(scene.RegionInfo.RegionID)); - WriteRegionInfo(scene, xtw); - xtw.WriteEndElement(); - } - else - { - // Write a placeholder for a missing region - xtw.WriteElementString("region", ""); - } - } - - xtw.WriteEndElement(); - } - else - { - // Write a placeholder for a missing row - xtw.WriteElementString("row", ""); - } - } - - xtw.WriteEndElement(); // "regions" - } - - protected static void WriteRegionInfo(Scene scene, XmlTextWriter xtw) - { - bool isMegaregion; - Vector2 size; - - IRegionCombinerModule rcMod = scene.RequestModuleInterface(); - - if (rcMod != null) - isMegaregion = rcMod.IsRootForMegaregion(scene.RegionInfo.RegionID); - else - isMegaregion = false; - - if (isMegaregion) - size = rcMod.GetSizeOfMegaregion(scene.RegionInfo.RegionID); - else - size = new Vector2((float)Constants.RegionSize, (float)Constants.RegionSize); - - xtw.WriteElementString("is_megaregion", isMegaregion.ToString()); - xtw.WriteElementString("size_in_meters", string.Format("{0},{1}", size.X, size.Y)); - } - - - protected void Save(Scene scene, List sceneObjects, string regionDir) - { - if (regionDir != string.Empty) - regionDir = ArchiveConstants.REGIONS_PATH + regionDir + "/"; - - m_log.InfoFormat("[ARCHIVER]: Adding region settings to archive."); - - // Write out region settings - string settingsPath = String.Format("{0}{1}{2}.xml", - regionDir, ArchiveConstants.SETTINGS_PATH, scene.RegionInfo.RegionName); - m_archiveWriter.WriteFile(settingsPath, RegionSettingsSerializer.Serialize(scene.RegionInfo.RegionSettings)); - - m_log.InfoFormat("[ARCHIVER]: Adding parcel settings to archive."); - - // Write out land data (aka parcel) settings - List landObjects = scene.LandChannel.AllParcels(); - foreach (ILandObject lo in landObjects) - { - LandData landData = lo.LandData; - string landDataPath = String.Format("{0}{1}{2}.xml", - regionDir, ArchiveConstants.LANDDATA_PATH, landData.GlobalID.ToString()); - m_archiveWriter.WriteFile(landDataPath, LandDataSerializer.Serialize(landData, m_options)); - } - - m_log.InfoFormat("[ARCHIVER]: Adding terrain information to archive."); - - // Write out terrain - string terrainPath = String.Format("{0}{1}{2}.r32", - regionDir, ArchiveConstants.TERRAINS_PATH, scene.RegionInfo.RegionName); - - MemoryStream ms = new MemoryStream(); - scene.RequestModuleInterface().SaveToStream(terrainPath, ms); - m_archiveWriter.WriteFile(terrainPath, ms.ToArray()); - ms.Close(); - - m_log.InfoFormat("[ARCHIVER]: Adding scene objects to archive."); - - // Write out scene object metadata - IRegionSerialiserModule serializer = scene.RequestModuleInterface(); - foreach (SceneObjectGroup sceneObject in sceneObjects) - { - //m_log.DebugFormat("[ARCHIVER]: Saving {0} {1}, {2}", entity.Name, entity.UUID, entity.GetType()); - - string serializedObject = serializer.SerializeGroupToXml2(sceneObject, m_options); - string objectPath = string.Format("{0}{1}", regionDir, ArchiveHelpers.CreateObjectPath(sceneObject)); - m_archiveWriter.WriteFile(objectPath, serializedObject); - } - } - - protected void ReceivedAllAssets( - ICollection assetsFoundUuids, ICollection assetsNotFoundUuids) - { - foreach (UUID uuid in assetsNotFoundUuids) - { - m_log.DebugFormat("[ARCHIVER]: Could not find asset {0}", uuid); - } - - // m_log.InfoFormat( - // "[ARCHIVER]: Received {0} of {1} assets requested", - // assetsFoundUuids.Count, assetsFoundUuids.Count + assetsNotFoundUuids.Count); - - CloseArchive(String.Empty); - } - - - /// - /// Closes the archive and notifies that we're done. - /// - /// The error that occurred, or empty for success - protected void CloseArchive(string errorMessage) - { - try - { - if (m_archiveWriter != null) - m_archiveWriter.Close(); - m_saveStream.Close(); - } - catch (Exception e) - { - m_log.Error(string.Format("[ARCHIVER]: Error closing archive: {0} ", e.Message), e); - if (errorMessage == string.Empty) - errorMessage = e.Message; - } - - m_log.InfoFormat("[ARCHIVER]: Finished writing out OAR for {0}", m_rootScene.RegionInfo.RegionName); - - m_rootScene.EventManager.TriggerOarFileSaved(m_requestId, errorMessage); - } - - } -} diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiverModule.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiverModule.cs index 26535a9..2a87dc2 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/ArchiverModule.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiverModule.cs @@ -170,7 +170,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver m_log.InfoFormat( "[ARCHIVER]: Writing archive for region {0} to {1}", Scene.RegionInfo.RegionName, savePath); - new ArchiveWriteRequestPreparation(Scene, savePath, requestId).ArchiveRegion(options); + new ArchiveWriteRequest(Scene, savePath, requestId).ArchiveRegion(options); } public void ArchiveRegion(Stream saveStream) @@ -185,7 +185,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver public void ArchiveRegion(Stream saveStream, Guid requestId, Dictionary options) { - new ArchiveWriteRequestPreparation(Scene, saveStream, requestId).ArchiveRegion(options); + new ArchiveWriteRequest(Scene, saveStream, requestId).ArchiveRegion(options); } public void DearchiveRegion(string loadPath) diff --git a/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs b/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs index cfdfd8c..abbaf41 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs @@ -311,7 +311,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests tar.WriteFile( ArchiveConstants.CONTROL_FILE_PATH, - new ArchiveWriteRequestPreparation(m_scene, (Stream)null, Guid.Empty).CreateControlFile(new ArchiveScenesGroup())); + new ArchiveWriteRequest(m_scene, (Stream)null, Guid.Empty).CreateControlFile(new ArchiveScenesGroup())); SceneObjectGroup sog1 = SceneHelpers.CreateSceneObject(1, ownerId, "obj1-", 0x11); SceneObjectPart sop2 @@ -369,7 +369,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests tar.WriteFile( ArchiveConstants.CONTROL_FILE_PATH, - new ArchiveWriteRequestPreparation(m_scene, (Stream)null, Guid.Empty).CreateControlFile(new ArchiveScenesGroup())); + new ArchiveWriteRequest(m_scene, (Stream)null, Guid.Empty).CreateControlFile(new ArchiveScenesGroup())); SceneObjectPart part1 = CreateSceneObjectPart1(); part1.SitTargetOrientation = new Quaternion(0.2f, 0.3f, 0.4f, 0.5f); @@ -559,7 +559,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests tar.WriteDir(ArchiveConstants.TERRAINS_PATH); tar.WriteFile( ArchiveConstants.CONTROL_FILE_PATH, - new ArchiveWriteRequestPreparation(m_scene, (Stream)null, Guid.Empty).CreateControlFile(new ArchiveScenesGroup())); + new ArchiveWriteRequest(m_scene, (Stream)null, Guid.Empty).CreateControlFile(new ArchiveScenesGroup())); RegionSettings rs = new RegionSettings(); rs.AgentLimit = 17; -- cgit v1.1 From 5dd2569bf7d50217d1786c3268a537745b2e9fd3 Mon Sep 17 00:00:00 2001 From: Oren Hurvitz Date: Mon, 27 Aug 2012 12:47:04 +0300 Subject: Added unit tests for multi-region OARs --- .../Region/ClientStack/RegionApplicationBase.cs | 2 +- .../World/Archiver/Tests/ArchiverTests.cs | 384 +++++++++++++++++---- OpenSim/Region/Framework/Scenes/SceneManager.cs | 6 +- 3 files changed, 332 insertions(+), 60 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/ClientStack/RegionApplicationBase.cs b/OpenSim/Region/ClientStack/RegionApplicationBase.cs index 4672f8a..853b72d 100644 --- a/OpenSim/Region/ClientStack/RegionApplicationBase.cs +++ b/OpenSim/Region/ClientStack/RegionApplicationBase.cs @@ -76,7 +76,7 @@ namespace OpenSim.Region.ClientStack protected override void StartupSpecific() { - SceneManager = new SceneManager(); + SceneManager = SceneManager.Instance; m_clientStackManager = CreateClientStackManager(); Initialize(); diff --git a/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs b/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs index abbaf41..0a30905 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs @@ -57,23 +57,25 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests private Guid m_lastRequestId; private string m_lastErrorMessage; + protected SceneHelpers m_sceneHelpers; protected TestScene m_scene; protected ArchiverModule m_archiverModule; + protected SerialiserModule m_serialiserModule; protected TaskInventoryItem m_soundItem; [SetUp] public void SetUp() { + new SceneManager(); + m_archiverModule = new ArchiverModule(); - SerialiserModule serialiserModule = new SerialiserModule(); + m_serialiserModule = new SerialiserModule(); TerrainModule terrainModule = new TerrainModule(); - m_scene = new SceneHelpers().SetupScene(); - SceneHelpers.SetupSceneModules(m_scene, m_archiverModule, serialiserModule, terrainModule); - - new SceneManager(); - SceneManager.Instance.Add(m_scene); + m_sceneHelpers = new SceneHelpers(); + m_scene = m_sceneHelpers.SetupScene(); + SceneHelpers.SetupSceneModules(m_scene, m_archiverModule, m_serialiserModule, terrainModule); } private void LoadCompleted(Guid requestId, List loadedScenes, string errorMessage) @@ -132,26 +134,10 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests TestHelpers.InMethod(); // log4net.Config.XmlConfigurator.Configure(); - SceneObjectPart part1 = CreateSceneObjectPart1(); - SceneObjectGroup sog1 = new SceneObjectGroup(part1); - m_scene.AddNewSceneObject(sog1, false); - - SceneObjectPart part2 = CreateSceneObjectPart2(); - - AssetNotecard nc = new AssetNotecard(); - nc.BodyText = "Hello World!"; - nc.Encode(); - UUID ncAssetUuid = new UUID("00000000-0000-0000-1000-000000000000"); - UUID ncItemUuid = new UUID("00000000-0000-0000-1100-000000000000"); - AssetBase ncAsset - = AssetHelpers.CreateAsset(ncAssetUuid, AssetType.Notecard, nc.AssetData, UUID.Zero); - m_scene.AssetService.Store(ncAsset); - SceneObjectGroup sog2 = new SceneObjectGroup(part2); - TaskInventoryItem ncItem - = new TaskInventoryItem { Name = "ncItem", AssetID = ncAssetUuid, ItemID = ncItemUuid }; - part2.Inventory.AddInventoryItem(ncItem, true); - - m_scene.AddNewSceneObject(sog2, false); + SceneObjectGroup sog1; + SceneObjectGroup sog2; + UUID ncAssetUuid; + CreateTestObjects(m_scene, out sog1, out sog2, out ncAssetUuid); MemoryStream archiveWriteStream = new MemoryStream(); m_scene.EventManager.OnOarFileSaved += SaveCompleted; @@ -215,6 +201,30 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests // TODO: Test presence of more files and contents of files. } + private void CreateTestObjects(Scene scene, out SceneObjectGroup sog1, out SceneObjectGroup sog2, out UUID ncAssetUuid) + { + SceneObjectPart part1 = CreateSceneObjectPart1(); + sog1 = new SceneObjectGroup(part1); + scene.AddNewSceneObject(sog1, false); + + AssetNotecard nc = new AssetNotecard(); + nc.BodyText = "Hello World!"; + nc.Encode(); + ncAssetUuid = UUID.Random(); + UUID ncItemUuid = UUID.Random(); + AssetBase ncAsset + = AssetHelpers.CreateAsset(ncAssetUuid, AssetType.Notecard, nc.AssetData, UUID.Zero); + m_scene.AssetService.Store(ncAsset); + + TaskInventoryItem ncItem + = new TaskInventoryItem { Name = "ncItem", AssetID = ncAssetUuid, ItemID = ncItemUuid }; + SceneObjectPart part2 = CreateSceneObjectPart2(); + sog2 = new SceneObjectGroup(part2); + part2.Inventory.AddInventoryItem(ncItem, true); + + scene.AddNewSceneObject(sog2, false); + } + /// /// Test saving an OpenSim Region Archive with the no assets option /// @@ -392,31 +402,12 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests Assert.That(soundDataResourceName, Is.Not.Null); byte[] soundData; - Console.WriteLine("Loading " + soundDataResourceName); - using (Stream resource = assembly.GetManifestResourceStream(soundDataResourceName)) - { - using (BinaryReader br = new BinaryReader(resource)) - { - // FIXME: Use the inspector instead - soundData = br.ReadBytes(99999999); - UUID soundUuid = UUID.Parse("00000000-0000-0000-0000-000000000001"); - string soundAssetFileName - = ArchiveConstants.ASSETS_PATH + soundUuid - + ArchiveConstants.ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.SoundWAV]; - tar.WriteFile(soundAssetFileName, soundData); - - /* - AssetBase soundAsset = AssetHelpers.CreateAsset(soundUuid, soundData); - scene.AssetService.Store(soundAsset); - asset1FileName = ArchiveConstants.ASSETS_PATH + soundUuid + ".wav"; - */ - - TaskInventoryItem item1 - = new TaskInventoryItem { AssetID = soundUuid, ItemID = soundItemUuid, Name = soundItemName }; - part1.Inventory.AddInventoryItem(item1, true); - } - } - + UUID soundUuid; + CreateSoundAsset(tar, assembly, soundDataResourceName, out soundData, out soundUuid); + + TaskInventoryItem item1 + = new TaskInventoryItem { AssetID = soundUuid, ItemID = soundItemUuid, Name = soundItemName }; + part1.Inventory.AddInventoryItem(item1, true); m_scene.AddNewSceneObject(object1, false); string object1FileName = string.Format( @@ -438,6 +429,34 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests Assert.That(m_lastErrorMessage, Is.Null); + TestLoadedRegion(part1, soundItemName, soundData); + } + + private static void CreateSoundAsset(TarArchiveWriter tar, Assembly assembly, string soundDataResourceName, out byte[] soundData, out UUID soundUuid) + { + using (Stream resource = assembly.GetManifestResourceStream(soundDataResourceName)) + { + using (BinaryReader br = new BinaryReader(resource)) + { + // FIXME: Use the inspector instead + soundData = br.ReadBytes(99999999); + soundUuid = UUID.Parse("00000000-0000-0000-0000-000000000001"); + string soundAssetFileName + = ArchiveConstants.ASSETS_PATH + soundUuid + + ArchiveConstants.ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.SoundWAV]; + tar.WriteFile(soundAssetFileName, soundData); + + /* + AssetBase soundAsset = AssetHelpers.CreateAsset(soundUuid, soundData); + scene.AssetService.Store(soundAsset); + asset1FileName = ArchiveConstants.ASSETS_PATH + soundUuid + ".wav"; + */ + } + } + } + + private void TestLoadedRegion(SceneObjectPart part1, string soundItemName, byte[] soundData) + { SceneObjectPart object1PartLoaded = m_scene.GetSceneObjectPart(part1.Name); Assert.That(object1PartLoaded, Is.Not.Null, "object1 was not loaded"); @@ -457,9 +476,6 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests Assert.That(loadedSoundAsset.Data, Is.EqualTo(soundData), "saved and loaded sound data do not match"); Assert.Greater(m_scene.LandChannel.AllParcels().Count, 0, "incorrect number of parcels"); - - // Temporary - Console.WriteLine("Successfully completed {0}", MethodBase.GetCurrentMethod()); } /// @@ -519,11 +535,10 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests SerialiserModule serialiserModule = new SerialiserModule(); TerrainModule terrainModule = new TerrainModule(); - TestScene scene2 = new SceneHelpers().SetupScene(); + m_sceneHelpers = new SceneHelpers(); + TestScene scene2 = m_sceneHelpers.SetupScene(); SceneHelpers.SetupSceneModules(scene2, archiverModule, serialiserModule, terrainModule); - SceneManager.Instance.Add(scene2); - // Make sure there's a valid owner for the owner we saved (this should have been wiped if the code is // behaving correctly UserAccountHelpers.CreateUserWithInventory(scene2, objectOwner); @@ -669,7 +684,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests SerialiserModule serialiserModule = new SerialiserModule(); TerrainModule terrainModule = new TerrainModule(); - Scene scene = new SceneHelpers().SetupScene(); + Scene scene = m_sceneHelpers.SetupScene(); SceneHelpers.SetupSceneModules(scene, archiverModule, serialiserModule, terrainModule); m_scene.AddNewSceneObject(new SceneObjectGroup(part2), false); @@ -705,5 +720,258 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests Assert.That(object2PartMerged.GroupPosition, Is.EqualTo(part2.GroupPosition), "object2 group position not equal after merge"); } } + + /// + /// Test saving a multi-region OAR. + /// + [Test] + public void TestSaveMultiRegionOar() + { + TestHelpers.InMethod(); + + // Create test regions + + int WIDTH = 2; + int HEIGHT = 2; + + List scenes = new List(); + + // Maps (Directory in OAR file -> scene) + Dictionary regionPaths = new Dictionary(); + + // Maps (Scene -> expected object paths) + Dictionary> expectedPaths = new Dictionary>(); + + // List of expected assets + List expectedAssets = new List(); + + for (uint y = 0; y < HEIGHT; y++) + { + for (uint x = 0; x < WIDTH; x++) + { + Scene scene; + if (x == 0 && y == 0) + { + scene = m_scene; // this scene was already created in SetUp() + } + else + { + scene = m_sceneHelpers.SetupScene(string.Format("Unit test region {0}", (y * WIDTH) + x + 1), UUID.Random(), 1000 + x, 1000 + y); + SceneHelpers.SetupSceneModules(scene, new ArchiverModule(), m_serialiserModule, new TerrainModule()); + } + scenes.Add(scene); + + string dir = String.Format("{0}_{1}_{2}", x + 1, y + 1, scene.RegionInfo.RegionName.Replace(" ", "_")); + regionPaths[dir] = scene; + + SceneObjectGroup sog1; + SceneObjectGroup sog2; + UUID ncAssetUuid; + + CreateTestObjects(scene, out sog1, out sog2, out ncAssetUuid); + + expectedPaths[scene.RegionInfo.RegionID] = new List(); + expectedPaths[scene.RegionInfo.RegionID].Add(ArchiveHelpers.CreateObjectPath(sog1)); + expectedPaths[scene.RegionInfo.RegionID].Add(ArchiveHelpers.CreateObjectPath(sog2)); + + expectedAssets.Add(ncAssetUuid); + } + } + + + // Save OAR + + MemoryStream archiveWriteStream = new MemoryStream(); + m_scene.EventManager.OnOarFileSaved += SaveCompleted; + + Guid requestId = new Guid("00000000-0000-0000-0000-808080808080"); + + Dictionary options = new Dictionary(); + options.Add("all", true); + + lock (this) + { + m_archiverModule.ArchiveRegion(archiveWriteStream, requestId, options); + Monitor.Wait(this, 60000); + } + + + // Check that the OAR contains the expected data + + Assert.That(m_lastRequestId, Is.EqualTo(requestId)); + + byte[] archive = archiveWriteStream.ToArray(); + MemoryStream archiveReadStream = new MemoryStream(archive); + TarArchiveReader tar = new TarArchiveReader(archiveReadStream); + + Dictionary> foundPaths = new Dictionary>(); + List foundAssets = new List(); + + foreach (Scene scene in scenes) + { + foundPaths[scene.RegionInfo.RegionID] = new List(); + } + + string filePath; + TarArchiveReader.TarEntryType tarEntryType; + + byte[] data = tar.ReadEntry(out filePath, out tarEntryType); + Assert.That(filePath, Is.EqualTo(ArchiveConstants.CONTROL_FILE_PATH)); + + ArchiveReadRequest arr = new ArchiveReadRequest(m_scene, (Stream)null, false, false, Guid.Empty); + arr.LoadControlFile(filePath, data, new DearchiveScenesInfo()); + + Assert.That(arr.ControlFileLoaded, Is.True); + + while (tar.ReadEntry(out filePath, out tarEntryType) != null) + { + if (filePath.StartsWith(ArchiveConstants.ASSETS_PATH)) + { + // Assets are shared, so this file doesn't belong to any specific region. + string fileName = filePath.Remove(0, ArchiveConstants.ASSETS_PATH.Length); + if (fileName.EndsWith("_notecard.txt")) + foundAssets.Add(UUID.Parse(fileName.Substring(0, fileName.Length - "_notecard.txt".Length))); + } + else + { + // This file belongs to one of the regions. Find out which one. + Assert.IsTrue(filePath.StartsWith(ArchiveConstants.REGIONS_PATH)); + string[] parts = filePath.Split(new Char[] { '/' }, 3); + Assert.AreEqual(3, parts.Length); + string regionDirectory = parts[1]; + string relativePath = parts[2]; + Scene scene = regionPaths[regionDirectory]; + + if (relativePath.StartsWith(ArchiveConstants.OBJECTS_PATH)) + { + foundPaths[scene.RegionInfo.RegionID].Add(relativePath); + } + } + } + + Assert.AreEqual(scenes.Count, foundPaths.Count); + foreach (Scene scene in scenes) + { + Assert.That(foundPaths[scene.RegionInfo.RegionID], Is.EquivalentTo(expectedPaths[scene.RegionInfo.RegionID])); + } + + Assert.That(foundAssets, Is.EquivalentTo(expectedAssets)); + } + + /// + /// Test loading a multi-region OAR. + /// + [Test] + public void TestLoadMultiRegionOar() + { + TestHelpers.InMethod(); + + // Create an ArchiveScenesGroup with the regions in the OAR. This is needed to generate the control file. + + int WIDTH = 2; + int HEIGHT = 2; + + for (uint y = 0; y < HEIGHT; y++) + { + for (uint x = 0; x < WIDTH; x++) + { + Scene scene; + if (x == 0 && y == 0) + { + scene = m_scene; // this scene was already created in SetUp() + } + else + { + scene = m_sceneHelpers.SetupScene(string.Format("Unit test region {0}", (y * WIDTH) + x + 1), UUID.Random(), 1000 + x, 1000 + y); + SceneHelpers.SetupSceneModules(scene, new ArchiverModule(), m_serialiserModule, new TerrainModule()); + } + } + } + + ArchiveScenesGroup scenesGroup = new ArchiveScenesGroup(); + SceneManager.Instance.ForEachScene(delegate(Scene scene) + { + scenesGroup.AddScene(scene); + }); + scenesGroup.CalcSceneLocations(); + + // Generate the OAR file + + MemoryStream archiveWriteStream = new MemoryStream(); + TarArchiveWriter tar = new TarArchiveWriter(archiveWriteStream); + + ArchiveWriteRequest writeRequest = new ArchiveWriteRequest(m_scene, (Stream)null, Guid.Empty); + writeRequest.MultiRegionFormat = true; + tar.WriteFile( + ArchiveConstants.CONTROL_FILE_PATH, writeRequest.CreateControlFile(scenesGroup)); + + SceneObjectPart part1 = CreateSceneObjectPart1(); + part1.SitTargetOrientation = new Quaternion(0.2f, 0.3f, 0.4f, 0.5f); + part1.SitTargetPosition = new Vector3(1, 2, 3); + + SceneObjectGroup object1 = new SceneObjectGroup(part1); + + // Let's put some inventory items into our object + string soundItemName = "sound-item1"; + UUID soundItemUuid = UUID.Parse("00000000-0000-0000-0000-000000000002"); + Type type = GetType(); + Assembly assembly = type.Assembly; + string soundDataResourceName = null; + string[] names = assembly.GetManifestResourceNames(); + foreach (string name in names) + { + if (name.EndsWith(".Resources.test-sound.wav")) + soundDataResourceName = name; + } + Assert.That(soundDataResourceName, Is.Not.Null); + + byte[] soundData; + UUID soundUuid; + CreateSoundAsset(tar, assembly, soundDataResourceName, out soundData, out soundUuid); + + TaskInventoryItem item1 + = new TaskInventoryItem { AssetID = soundUuid, ItemID = soundItemUuid, Name = soundItemName }; + part1.Inventory.AddInventoryItem(item1, true); + m_scene.AddNewSceneObject(object1, false); + + string object1FileName = string.Format( + "{0}_{1:000}-{2:000}-{3:000}__{4}.xml", + part1.Name, + Math.Round(part1.GroupPosition.X), Math.Round(part1.GroupPosition.Y), Math.Round(part1.GroupPosition.Z), + part1.UUID); + string path = "regions/1_1_Unit_test_region/" + ArchiveConstants.OBJECTS_PATH + object1FileName; + tar.WriteFile(path, SceneObjectSerializer.ToXml2Format(object1)); + + tar.Close(); + + + // Delete the current objects, to test that they're loaded from the OAR and didn't + // just remain in the scene. + SceneManager.Instance.ForEachScene(delegate(Scene scene) + { + scene.DeleteAllSceneObjects(); + }); + + // Create a "hole", to test that that the corresponding region isn't loaded from the OAR + SceneManager.Instance.CloseScene(SceneManager.Instance.Scenes[1]); + + + // Check thay the OAR file contains the expected data + + MemoryStream archiveReadStream = new MemoryStream(archiveWriteStream.ToArray()); + + lock (this) + { + m_scene.EventManager.OnOarFileLoaded += LoadCompleted; + m_archiverModule.DearchiveRegion(archiveReadStream); + } + + Assert.That(m_lastErrorMessage, Is.Null); + + Assert.AreEqual(3, SceneManager.Instance.Scenes.Count); + + TestLoadedRegion(part1, soundItemName, soundData); + } + } } diff --git a/OpenSim/Region/Framework/Scenes/SceneManager.cs b/OpenSim/Region/Framework/Scenes/SceneManager.cs index c81b55d..cb5b2ba 100644 --- a/OpenSim/Region/Framework/Scenes/SceneManager.cs +++ b/OpenSim/Region/Framework/Scenes/SceneManager.cs @@ -92,7 +92,11 @@ namespace OpenSim.Region.Framework.Scenes private static SceneManager m_instance = null; public static SceneManager Instance { - get { return m_instance; } + get { + if (m_instance == null) + m_instance = new SceneManager(); + return m_instance; + } } private readonly List m_localScenes = new List(); -- cgit v1.1 From d5c8c6bc12d434bb6a4bbc6f326a4ae784c12861 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Sat, 15 Sep 2012 01:08:15 +0100 Subject: For FlotsamAssetCache, always update access times of cached scene assets before looking for files to expire. This is to resolve a problem where an asset marked as local but not temporary but still used in the scene would be removed. The timed expiry scan no longer tries to refetch assets from the scene that are not currently in the cache - this is not helpful since it just drags a lot of data into the cache that may never be referenced. This removes the DeepScanBeforePurge option since setting this to false will introduce the above problem. This previously had a default of true. --- .../Region/CoreModules/Asset/FlotsamAssetCache.cs | 37 ++++++++++------------ 1 file changed, 17 insertions(+), 20 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs index 5d8a278..8aa173a 100644 --- a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs +++ b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs @@ -107,8 +107,6 @@ namespace OpenSim.Region.CoreModules.Asset private IAssetService m_AssetService; private List m_Scenes = new List(); - private bool m_DeepScanBeforePurge; - public FlotsamAssetCache() { m_InvalidChars.AddRange(Path.GetInvalidPathChars()); @@ -170,8 +168,6 @@ namespace OpenSim.Region.CoreModules.Asset m_CacheDirectoryTierLen = assetConfig.GetInt("CacheDirectoryTierLength", m_CacheDirectoryTierLen); m_CacheWarnAt = assetConfig.GetInt("CacheWarnAt", m_CacheWarnAt); - - m_DeepScanBeforePurge = assetConfig.GetBoolean("DeepScanBeforePurge", m_DeepScanBeforePurge); } m_log.InfoFormat("[FLOTSAM ASSET CACHE]: Cache Directory {0}", m_CacheDirectory); @@ -506,13 +502,10 @@ namespace OpenSim.Region.CoreModules.Asset // Purge all files last accessed prior to this point DateTime purgeLine = DateTime.Now - m_FileExpiration; - // An optional deep scan at this point will ensure assets present in scenes, - // or referenced by objects in the scene, but not recently accessed - // are not purged. - if (m_DeepScanBeforePurge) - { - CacheScenes(); - } + // An asset cache may contain local non-temporary assets that are not in the asset service. Therefore, + // before cleaning up expired files we must scan the objects in the scene to make sure that we retain + // such local assets if they have not been recently accessed. + TouchAllSceneAssets(false); foreach (string dir in Directory.GetDirectories(m_CacheDirectory)) { @@ -705,11 +698,14 @@ namespace OpenSim.Region.CoreModules.Asset /// /// Iterates through all Scenes, doing a deep scan through assets - /// to cache all assets present in the scene or referenced by assets - /// in the scene + /// to update the access time of all assets present in the scene or referenced by assets + /// in the scene. /// - /// - private int CacheScenes() + /// + /// If true, then assets scanned which are not found in cache are added to the cache. + /// + /// Number of distinct asset references found in the scene. + private int TouchAllSceneAssets(bool storeUncached) { UuidGatherer gatherer = new UuidGatherer(m_AssetService); @@ -732,7 +728,7 @@ namespace OpenSim.Region.CoreModules.Asset { File.SetLastAccessTime(filename, DateTime.Now); } - else + else if (storeUncached) { m_AssetService.Get(assetID.ToString()); } @@ -860,13 +856,14 @@ namespace OpenSim.Region.CoreModules.Asset break; - case "assets": - m_log.Info("[FLOTSAM ASSET CACHE]: Caching all assets, in all scenes."); + m_log.Info("[FLOTSAM ASSET CACHE]: Ensuring assets are cached for all scenes."); Util.FireAndForget(delegate { - int assetsCached = CacheScenes(); - m_log.InfoFormat("[FLOTSAM ASSET CACHE]: Completed Scene Caching, {0} assets found.", assetsCached); + int assetReferenceTotal = TouchAllSceneAssets(true); + m_log.InfoFormat( + "[FLOTSAM ASSET CACHE]: Completed check with {0} assets.", + assetReferenceTotal); }); break; -- cgit v1.1 From 1ec84ac8b160c1a6ee903b832c75635d1219fe5a Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Sat, 15 Sep 2012 02:12:26 +0100 Subject: Add basic asset connector tests to check behaviour for normal, local and temporary assets. Make AssetServiceConnector return more useful data on failure, such as what DLL it was trying to load Allow LocalAssetServiceConnector.GetData() to work without a cache present, as works for the other lasc Get* methods. --- .../Asset/LocalAssetServiceConnector.cs | 7 +- .../Asset/Tests/AssetConnectorTests.cs | 136 +++++++++++++++++++++ 2 files changed, 141 insertions(+), 2 deletions(-) create mode 100644 OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/Tests/AssetConnectorTests.cs (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/LocalAssetServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/LocalAssetServiceConnector.cs index c78915f..449c1f1 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/LocalAssetServiceConnector.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/LocalAssetServiceConnector.cs @@ -204,8 +204,11 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset public byte[] GetData(string id) { // m_log.DebugFormat("[LOCAL ASSET SERVICES CONNECTOR]: Requesting data for asset {0}", id); - - AssetBase asset = m_Cache.Get(id); + + AssetBase asset = null; + + if (m_Cache != null) + asset = m_Cache.Get(id); if (asset != null) return asset.Data; diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/Tests/AssetConnectorTests.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/Tests/AssetConnectorTests.cs new file mode 100644 index 0000000..1982473 --- /dev/null +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/Tests/AssetConnectorTests.cs @@ -0,0 +1,136 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections.Generic; +using System.IO; +using System.Reflection; +using System.Threading; +using log4net.Config; +using Nini.Config; +using NUnit.Framework; +using OpenMetaverse; +using OpenSim.Framework; +using OpenSim.Region.Framework.Scenes; +using OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset; +using OpenSim.Tests.Common; + +namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset.Tests +{ + [TestFixture] + public class AssetConnectorsTests : OpenSimTestCase + { + [Test] + public void TestAddAsset() + { + TestHelpers.InMethod(); +// TestHelpers.EnableLogging(); + + IConfigSource config = new IniConfigSource(); + config.AddConfig("Modules"); + config.Configs["Modules"].Set("AssetServices", "LocalAssetServicesConnector"); + config.AddConfig("AssetService"); + config.Configs["AssetService"].Set("LocalServiceModule", "OpenSim.Services.AssetService.dll:AssetService"); + config.Configs["AssetService"].Set("StorageProvider", "OpenSim.Tests.Common.dll"); + + LocalAssetServicesConnector lasc = new LocalAssetServicesConnector(); + lasc.Initialise(config); + + AssetBase a1 = AssetHelpers.CreateNotecardAsset(); + lasc.Store(a1); + + AssetBase retreivedA1 = lasc.Get(a1.ID); + Assert.That(retreivedA1.ID, Is.EqualTo(a1.ID)); + Assert.That(retreivedA1.Metadata.ID, Is.EqualTo(a1.Metadata.ID)); + Assert.That(retreivedA1.Data.Length, Is.EqualTo(a1.Data.Length)); + + AssetMetadata retrievedA1Metadata = lasc.GetMetadata(a1.ID); + Assert.That(retrievedA1Metadata.ID, Is.EqualTo(a1.ID)); + + byte[] retrievedA1Data = lasc.GetData(a1.ID); + Assert.That(retrievedA1Data.Length, Is.EqualTo(a1.Data.Length)); + + // TODO: Add cache and check that this does receive a copy of the asset + } + + [Test] + public void TestAddTemporaryAsset() + { + TestHelpers.InMethod(); +// TestHelpers.EnableLogging(); + + IConfigSource config = new IniConfigSource(); + config.AddConfig("Modules"); + config.Configs["Modules"].Set("AssetServices", "LocalAssetServicesConnector"); + config.AddConfig("AssetService"); + config.Configs["AssetService"].Set("LocalServiceModule", "OpenSim.Services.AssetService.dll:AssetService"); + config.Configs["AssetService"].Set("StorageProvider", "OpenSim.Tests.Common.dll"); + + LocalAssetServicesConnector lasc = new LocalAssetServicesConnector(); + lasc.Initialise(config); + + AssetBase a1 = AssetHelpers.CreateNotecardAsset(); + a1.Temporary = true; + + lasc.Store(a1); + + Assert.That(lasc.Get(a1.ID), Is.Null); + Assert.That(lasc.GetData(a1.ID), Is.Null); + Assert.That(lasc.GetMetadata(a1.ID), Is.Null); + + // TODO: Add cache and check that this does receive a copy of the asset + } + + [Test] + public void TestAddLocalAsset() + { + TestHelpers.InMethod(); +// TestHelpers.EnableLogging(); + + IConfigSource config = new IniConfigSource(); + config.AddConfig("Modules"); + config.Configs["Modules"].Set("AssetServices", "LocalAssetServicesConnector"); + config.AddConfig("AssetService"); + config.Configs["AssetService"].Set("LocalServiceModule", "OpenSim.Services.AssetService.dll:AssetService"); + config.Configs["AssetService"].Set("StorageProvider", "OpenSim.Tests.Common.dll"); + + LocalAssetServicesConnector lasc = new LocalAssetServicesConnector(); + lasc.Initialise(config); + + AssetBase a1 = AssetHelpers.CreateNotecardAsset(); + a1.Local = true; + + lasc.Store(a1); + + Assert.That(lasc.Get(a1.ID), Is.Null); + Assert.That(lasc.GetData(a1.ID), Is.Null); + Assert.That(lasc.GetMetadata(a1.ID), Is.Null); + + // TODO: Add cache and check that this does receive a copy of the asset + } + } +} \ No newline at end of file -- cgit v1.1 From 2c5ff9399063080276a23bcd06fb696d653bef2e Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Thu, 13 Sep 2012 08:11:54 -0700 Subject: BulletSim: Way too many changes in one commit. Many changes to BSDynamic for readability and commentary. Linkset hacking for vehicles: don't over mass the root prim. Add parameter for link constraint solver iterations. Correct uses of timestep in timescale calculations for vehicles. Reorganize code/logic for making objects static and dynamic for readability and use of API2. Changed most calls in BSPrim to use API2 calls (the new way). Avatars do not generate default Bullet collision events but do call up to the simulator for every avatar. Reduces overhead. Objects added to collision list only if they are processing collisions. Reduces overhead especially for large numbers of avatars. Generalize call for water height to GetWaterHeightAtXYZ(). Catch and correct exception getting terrain height when out of bounds. Correct race condition in Terrain Manager where creation wasn't at taint-time. Add API calls for constructing compound shapes. Move NeedsMeshing() logic into object class. Reorganize logic for object meshing to reduce rebuilding of meshs/hulls. --- .../Region/Physics/BulletSPlugin/BSCharacter.cs | 17 +- .../Region/Physics/BulletSPlugin/BSConstraint.cs | 16 +- OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs | 218 +++++++++------------ OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs | 32 ++- .../Region/Physics/BulletSPlugin/BSPhysObject.cs | 2 +- OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | 196 ++++++++++-------- OpenSim/Region/Physics/BulletSPlugin/BSScene.cs | 67 ++++--- .../Physics/BulletSPlugin/BSTerrainManager.cs | 60 +++--- .../Region/Physics/BulletSPlugin/BulletSimAPI.cs | 29 ++- 9 files changed, 351 insertions(+), 286 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs index fa22c78..a9b1365 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs @@ -131,8 +131,6 @@ public class BSCharacter : BSPhysObject BulletSimAPI.SetObjectBuoyancy(Scene.WorldID, LocalID, _buoyancy); BSBody = new BulletBody(LocalID, BulletSimAPI.GetBodyHandle2(Scene.World.Ptr, LocalID)); - // avatars get all collisions no matter what (makes walking on ground and such work) - BulletSimAPI.AddToCollisionFlags2(BSBody.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); }); return; @@ -480,11 +478,10 @@ public class BSCharacter : BSPhysObject // Stop collision events public override void UnSubscribeEvents() { _subscribedEventsMs = 0; - // Avatars get all their collision events - // Scene.TaintedObject("BSCharacter.UnSubscribeEvents", delegate() - // { - // BulletSimAPI.RemoveFromCollisionFlags2(Body.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); - // }); + Scene.TaintedObject("BSCharacter.UnSubscribeEvents", delegate() + { + BulletSimAPI.RemoveFromCollisionFlags2(BSBody.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); + }); } // Return 'true' if someone has subscribed to events public override bool SubscribedEvents() { @@ -532,10 +529,12 @@ public class BSCharacter : BSPhysObject // The collision, if it should be reported to the character, is placed in a collection // that will later be sent to the simulator when SendCollisions() is called. CollisionEventUpdate collisionCollection = null; - public override void Collide(uint collidingWith, BSPhysObject collidee, ActorTypes type, Vector3 contactPoint, Vector3 contactNormal, float pentrationDepth) + public override bool Collide(uint collidingWith, BSPhysObject collidee, ActorTypes type, Vector3 contactPoint, Vector3 contactNormal, float pentrationDepth) { // m_log.DebugFormat("{0}: Collide: ms={1}, id={2}, with={3}", LogHeader, _subscribedEventsMs, LocalID, collidingWith); + bool ret = false; + // The following makes IsColliding() and IsCollidingGround() work _collidingStep = Scene.SimulationStep; if (collidingWith == BSScene.TERRAIN_ID || collidingWith == BSScene.GROUNDPLANE_ID) @@ -553,8 +552,10 @@ public class BSCharacter : BSPhysObject if (collisionCollection == null) collisionCollection = new CollisionEventUpdate(); collisionCollection.AddCollider(collidingWith, new ContactPoint(contactPoint, contactNormal, pentrationDepth)); + ret = true; } } + return ret; } public override void SendCollisions() diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs b/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs index 2e15ced..1376a29 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs @@ -74,6 +74,17 @@ public abstract class BSConstraint : IDisposable return ret; } + public virtual bool SetSolverIterations(float cnt) + { + bool ret = false; + if (m_enabled) + { + BulletSimAPI.SetConstraintNumSolverIterations2(m_constraint.Ptr, cnt); + ret = true; + } + return ret; + } + public virtual bool CalculateTransforms() { bool ret = false; @@ -96,12 +107,9 @@ public abstract class BSConstraint : IDisposable ret = CalculateTransforms(); if (ret) { - // m_world.scene.PhysicsLogging.Write("{0},BSConstraint.RecomputeConstraintVariables,taint,enabling,A={1},B={2}", - // BSScene.DetailLogZero, Body1.ID, Body2.ID); - // Setting an object's mass to zero (making it static like when it's selected) // automatically disables the constraints. - // If enabled, be sure to set the constraint itself to enabled. + // If the link is enabled, be sure to set the constraint itself to enabled. BulletSimAPI.SetConstraintEnable2(m_constraint.Ptr, m_world.scene.NumericBool(true)); } else diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs index 8169e99..098fea7 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs @@ -80,7 +80,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin // Linear properties private Vector3 m_linearMotorDirection = Vector3.Zero; // velocity requested by LSL, decayed by time private Vector3 m_linearMotorDirectionLASTSET = Vector3.Zero; // velocity requested by LSL - private Vector3 m_dir = Vector3.Zero; // velocity applied to body + private Vector3 m_newVelocity = Vector3.Zero; // velocity computed to be applied to body private Vector3 m_linearFrictionTimescale = Vector3.Zero; private float m_linearMotorDecayTimescale = 0; private float m_linearMotorTimescale = 0; @@ -475,32 +475,33 @@ namespace OpenSim.Region.Physics.BulletSPlugin frcount = 0; MoveLinear(pTimestep); - MoveAngular(pTimestep); + // MoveAngular(pTimestep); LimitRotation(pTimestep); + // remember the position so next step we can limit absolute movement effects + m_lastPositionVector = m_prim.Position; + VDetailLog("{0},BSDynamics.Step,done,pos={1},force={2},velocity={3},angvel={4}", m_prim.LocalID, m_prim.Position, m_prim.Force, m_prim.Velocity, m_prim.RotationalVelocity); }// end Step private void MoveLinear(float pTimestep) { - // requested m_linearMotorDirection is significant - // if (!m_linearMotorDirection.ApproxEquals(Vector3.Zero, 0.01f)) - if (m_linearMotorDirection.LengthSquared() > 0.0001f) + // m_linearMotorDirection is the direction we are moving relative to the vehicle coordinates + // m_lastLinearVelocityVector is the speed we are moving in that direction + if (m_linearMotorDirection.LengthSquared() > 0.001f) { Vector3 origDir = m_linearMotorDirection; Vector3 origVel = m_lastLinearVelocityVector; // add drive to body - // Vector3 addAmount = m_linearMotorDirection/(m_linearMotorTimescale/pTimestep); - Vector3 addAmount = m_linearMotorDirection/(m_linearMotorTimescale); - // lastLinearVelocityVector is the current body velocity vector? + // Vector3 addAmount = m_linearMotorDirection/(m_linearMotorTimescale / pTimestep); + Vector3 addAmount = (m_linearMotorDirection - m_lastLinearVelocityVector)/(m_linearMotorTimescale / pTimestep); + // lastLinearVelocityVector is the current body velocity vector // RA: Not sure what the *10 is for. A correction for pTimestep? // m_lastLinearVelocityVector += (addAmount*10); m_lastLinearVelocityVector += addAmount; - // This will work temporarily, but we really need to compare speed on an axis - // KF: Limit body velocity to applied velocity? // Limit the velocity vector to less than the last set linear motor direction if (Math.Abs(m_lastLinearVelocityVector.X) > Math.Abs(m_linearMotorDirectionLASTSET.X)) m_lastLinearVelocityVector.X = m_linearMotorDirectionLASTSET.X; @@ -509,34 +510,29 @@ namespace OpenSim.Region.Physics.BulletSPlugin if (Math.Abs(m_lastLinearVelocityVector.Z) > Math.Abs(m_linearMotorDirectionLASTSET.Z)) m_lastLinearVelocityVector.Z = m_linearMotorDirectionLASTSET.Z; + /* // decay applied velocity - Vector3 decayfraction = ((Vector3.One/(m_linearMotorDecayTimescale/pTimestep))); + Vector3 decayfraction = Vector3.One/(m_linearMotorDecayTimescale / pTimestep); + // (RA: do not know where the 0.5f comes from) m_linearMotorDirection -= m_linearMotorDirection * decayfraction * 0.5f; - - /* - Vector3 addAmount = (m_linearMotorDirection - m_lastLinearVelocityVector)/m_linearMotorTimescale; - m_lastLinearVelocityVector += addAmount; - - float decayfraction = (1.0f - 1.0f / m_linearMotorDecayTimescale); - m_linearMotorDirection *= decayfraction; - */ + float keepfraction = 1.0f - (1.0f / (m_linearMotorDecayTimescale / pTimestep)); + m_linearMotorDirection *= keepfraction; - VDetailLog("{0},MoveLinear,nonZero,origdir={1},origvel={2},add={3},decay={4},dir={5},vel={6}", - m_prim.LocalID, origDir, origVel, addAmount, decayfraction, m_linearMotorDirection, m_lastLinearVelocityVector); + VDetailLog("{0},MoveLinear,nonZero,origdir={1},origvel={2},add={3},notDecay={4},dir={5},vel={6}", + m_prim.LocalID, origDir, origVel, addAmount, keepfraction, m_linearMotorDirection, m_lastLinearVelocityVector); } else { - // if what remains of applied is small, zero it. - // if (m_lastLinearVelocityVector.ApproxEquals(Vector3.Zero, 0.01f)) - // m_lastLinearVelocityVector = Vector3.Zero; + // if what remains of direction is very small, zero it. m_linearMotorDirection = Vector3.Zero; m_lastLinearVelocityVector = Vector3.Zero; + VDetailLog("{0},MoveLinear,zeroed", m_prim.LocalID); } // convert requested object velocity to object relative vector Quaternion rotq = m_prim.Orientation; - m_dir = m_lastLinearVelocityVector * rotq; + m_newVelocity = m_lastLinearVelocityVector * rotq; // Add the various forces into m_dir which will be our new direction vector (velocity) @@ -544,60 +540,31 @@ namespace OpenSim.Region.Physics.BulletSPlugin // KF: So far I have found no good method to combine a script-requested // .Z velocity and gravity. Therefore only 0g will used script-requested // .Z velocity. >0g (m_VehicleBuoyancy < 1) will used modified gravity only. - Vector3 grav = Vector3.Zero; // There is some gravity, make a gravity force vector that is applied after object velocity. // m_VehicleBuoyancy: -1=2g; 0=1g; 1=0g; - grav.Z = m_prim.Scene.DefaultGravity.Z * m_prim.Mass * (1f - m_VehicleBuoyancy); + Vector3 grav = m_prim.Scene.DefaultGravity * (m_prim.Mass * (1f - m_VehicleBuoyancy)); + + /* + * RA: Not sure why one would do this // Preserve the current Z velocity Vector3 vel_now = m_prim.Velocity; m_dir.Z = vel_now.Z; // Preserve the accumulated falling velocity + */ Vector3 pos = m_prim.Position; - Vector3 posChange = pos; // Vector3 accel = new Vector3(-(m_dir.X - m_lastLinearVelocityVector.X / 0.1f), -(m_dir.Y - m_lastLinearVelocityVector.Y / 0.1f), m_dir.Z - m_lastLinearVelocityVector.Z / 0.1f); - double Zchange = Math.Abs(posChange.Z); - if (m_BlockingEndPoint != Vector3.Zero) - { - bool changed = false; - if (pos.X >= (m_BlockingEndPoint.X - (float)1)) - { - pos.X -= posChange.X + 1; - changed = true; - } - if (pos.Y >= (m_BlockingEndPoint.Y - (float)1)) - { - pos.Y -= posChange.Y + 1; - changed = true; - } - if (pos.Z >= (m_BlockingEndPoint.Z - (float)1)) - { - pos.Z -= posChange.Z + 1; - changed = true; - } - if (pos.X <= 0) - { - pos.X += posChange.X + 1; - changed = true; - } - if (pos.Y <= 0) - { - pos.Y += posChange.Y + 1; - changed = true; - } - if (changed) - { - m_prim.Position = pos; - VDetailLog("{0},MoveLinear,blockingEndPoint,block={1},origPos={2},pos={3}", - m_prim.LocalID, m_BlockingEndPoint, posChange, pos); - } - } // If below the terrain, move us above the ground a little. - if (pos.Z < m_prim.Scene.TerrainManager.GetTerrainHeightAtXYZ(pos)) + float terrainHeight = m_prim.Scene.TerrainManager.GetTerrainHeightAtXYZ(pos); + // Taking the rotated size doesn't work here because m_prim.Size is the size of the root prim and not the linkset. + // Need to add a m_prim.LinkSet.Size similar to m_prim.LinkSet.Mass. + // Vector3 rotatedSize = m_prim.Size * m_prim.Orientation; + // if (rotatedSize.Z < terrainHeight) + if (pos.Z < terrainHeight) { - pos.Z = m_prim.Scene.TerrainManager.GetTerrainHeightAtXYZ(pos) + 2; + pos.Z = terrainHeight + 2; m_prim.Position = pos; - VDetailLog("{0},MoveLinear,terrainHeight,pos={1}", m_prim.LocalID, pos); + VDetailLog("{0},MoveLinear,terrainHeight,terrainHeight={1},pos={2}", m_prim.LocalID, terrainHeight, pos); } // Check if hovering @@ -606,11 +573,11 @@ namespace OpenSim.Region.Physics.BulletSPlugin // We should hover, get the target height if ((m_flags & VehicleFlag.HOVER_WATER_ONLY) != 0) { - m_VhoverTargetHeight = m_prim.Scene.GetWaterLevel() + m_VhoverHeight; + m_VhoverTargetHeight = m_prim.Scene.GetWaterLevelAtXYZ(pos) + m_VhoverHeight; } if ((m_flags & VehicleFlag.HOVER_TERRAIN_ONLY) != 0) { - m_VhoverTargetHeight = m_prim.Scene.TerrainManager.GetTerrainHeightAtXY(pos.X, pos.Y) + m_VhoverHeight; + m_VhoverTargetHeight = terrainHeight + m_VhoverHeight; } if ((m_flags & VehicleFlag.HOVER_GLOBAL_HEIGHT) != 0) { @@ -635,82 +602,92 @@ namespace OpenSim.Region.Physics.BulletSPlugin // Replace Vertical speed with correction figure if significant if (Math.Abs(herr0) > 0.01f) { - m_dir.Z = -((herr0 * pTimestep * 50.0f) / m_VhoverTimescale); + m_newVelocity.Z = -((herr0 * pTimestep * 50.0f) / m_VhoverTimescale); //KF: m_VhoverEfficiency is not yet implemented } else { - m_dir.Z = 0f; + m_newVelocity.Z = 0f; } } - VDetailLog("{0},MoveLinear,hover,pos={1},dir={2},height={3},target={4}", m_prim.LocalID, pos, m_dir, m_VhoverHeight, m_VhoverTargetHeight); + VDetailLog("{0},MoveLinear,hover,pos={1},dir={2},height={3},target={4}", m_prim.LocalID, pos, m_newVelocity, m_VhoverHeight, m_VhoverTargetHeight); + } -// m_VhoverEfficiency = 0f; // 0=boucy, 1=Crit.damped -// m_VhoverTimescale = 0f; // time to acheive height -// pTimestep is time since last frame,in secs + Vector3 posChange = pos - m_lastPositionVector; + if (m_BlockingEndPoint != Vector3.Zero) + { + bool changed = false; + if (pos.X >= (m_BlockingEndPoint.X - (float)1)) + { + pos.X -= posChange.X + 1; + changed = true; + } + if (pos.Y >= (m_BlockingEndPoint.Y - (float)1)) + { + pos.Y -= posChange.Y + 1; + changed = true; + } + if (pos.Z >= (m_BlockingEndPoint.Z - (float)1)) + { + pos.Z -= posChange.Z + 1; + changed = true; + } + if (pos.X <= 0) + { + pos.X += posChange.X + 1; + changed = true; + } + if (pos.Y <= 0) + { + pos.Y += posChange.Y + 1; + changed = true; + } + if (changed) + { + m_prim.Position = pos; + VDetailLog("{0},MoveLinear,blockingEndPoint,block={1},origPos={2},pos={3}", + m_prim.LocalID, m_BlockingEndPoint, posChange, pos); + } } + float Zchange = Math.Abs(posChange.Z); if ((m_flags & (VehicleFlag.LIMIT_MOTOR_UP)) != 0) { - //Start Experimental Values if (Zchange > .3) - { grav.Z = (float)(grav.Z * 3); - } if (Zchange > .15) - { grav.Z = (float)(grav.Z * 2); - } if (Zchange > .75) - { grav.Z = (float)(grav.Z * 1.5); - } if (Zchange > .05) - { grav.Z = (float)(grav.Z * 1.25); - } if (Zchange > .025) - { grav.Z = (float)(grav.Z * 1.125); - } - float terraintemp = m_prim.Scene.TerrainManager.GetTerrainHeightAtXYZ(pos); - float postemp = (pos.Z - terraintemp); + float postemp = (pos.Z - terrainHeight); if (postemp > 2.5f) - { grav.Z = (float)(grav.Z * 1.037125); - } VDetailLog("{0},MoveLinear,limitMotorUp,grav={1}", m_prim.LocalID, grav); - //End Experimental Values } if ((m_flags & (VehicleFlag.NO_X)) != 0) - { - m_dir.X = 0; - } + m_newVelocity.X = 0; if ((m_flags & (VehicleFlag.NO_Y)) != 0) - { - m_dir.Y = 0; - } + m_newVelocity.Y = 0; if ((m_flags & (VehicleFlag.NO_Z)) != 0) - { - m_dir.Z = 0; - } - - m_lastPositionVector = m_prim.Position; + m_newVelocity.Z = 0; // Apply velocity - m_prim.Velocity = m_dir; + m_prim.Velocity = m_newVelocity; // apply gravity force // Why is this set here? The physics engine already does gravity. // m_prim.AddForce(grav, false); - // m_prim.Force = grav; // Apply friction - Vector3 decayamount = Vector3.One / (m_linearFrictionTimescale / pTimestep); - m_lastLinearVelocityVector -= m_lastLinearVelocityVector * decayamount; + Vector3 keepFraction = Vector3.One - (Vector3.One / (m_linearFrictionTimescale / pTimestep)); + m_lastLinearVelocityVector *= keepFraction; - VDetailLog("{0},MoveLinear,done,pos={1},vel={2},force={3},decay={4}", - m_prim.LocalID, m_lastPositionVector, m_dir, grav, decayamount); + VDetailLog("{0},MoveLinear,done,lmDir={1},lmVel={2},newVel={3},grav={4},1Mdecay={5}", + m_prim.LocalID, m_linearMotorDirection, m_lastLinearVelocityVector, m_newVelocity, grav, keepFraction); } // end MoveLinear() @@ -735,17 +712,18 @@ namespace OpenSim.Region.Physics.BulletSPlugin // There are m_angularMotorApply steps. Vector3 origAngularVelocity = m_angularMotorVelocity; // ramp up to new value - // current velocity += error / (time to get there / step interval) - // requested speed - last motor speed + // current velocity += error / ( time to get there / step interval) + // requested speed - last motor speed m_angularMotorVelocity.X += (m_angularMotorDirection.X - m_angularMotorVelocity.X) / (m_angularMotorTimescale / pTimestep); m_angularMotorVelocity.Y += (m_angularMotorDirection.Y - m_angularMotorVelocity.Y) / (m_angularMotorTimescale / pTimestep); m_angularMotorVelocity.Z += (m_angularMotorDirection.Z - m_angularMotorVelocity.Z) / (m_angularMotorTimescale / pTimestep); - VDetailLog("{0},MoveAngular,angularMotorApply,apply={1},origvel={2},dir={3},vel={4}", - m_prim.LocalID,m_angularMotorApply,origAngularVelocity, m_angularMotorDirection, m_angularMotorVelocity); + VDetailLog("{0},MoveAngular,angularMotorApply,apply={1},angTScale={2},timeStep={3},origvel={4},dir={5},vel={6}", + m_prim.LocalID, m_angularMotorApply, m_angularMotorTimescale, pTimestep, origAngularVelocity, m_angularMotorDirection, m_angularMotorVelocity); - m_angularMotorApply--; // This is done so that if script request rate is less than phys frame rate the expected - // velocity may still be acheived. + // This is done so that if script request rate is less than phys frame rate the expected + // velocity may still be acheived. + m_angularMotorApply--; } else { @@ -760,7 +738,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin Vector3 vertattr = Vector3.Zero; if (m_verticalAttractionTimescale < 300) { - float VAservo = 0.2f / (m_verticalAttractionTimescale * pTimestep); + float VAservo = 0.2f / (m_verticalAttractionTimescale / pTimestep); // get present body rotation Quaternion rotq = m_prim.Orientation; // make a vector pointing up @@ -863,16 +841,12 @@ namespace OpenSim.Region.Physics.BulletSPlugin m_rot.Y = 0; changed = true; } - if ((m_flags & VehicleFlag.LOCK_ROTATION) != 0) - { - m_rot.X = 0; - m_rot.Y = 0; - changed = true; - } if (changed) + { m_prim.Orientation = m_rot; + VDetailLog("{0},LimitRotation,done,orig={1},new={2}", m_prim.LocalID, rotq, m_rot); + } - VDetailLog("{0},LimitRotation,done,changed={1},orig={2},new={3}", m_prim.LocalID, changed, rotq, m_rot); } // Invoke the detailed logger and output something if it's enabled. diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs index 5f6601d..dc1de6c 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs @@ -206,7 +206,7 @@ public class BSLinkset // its internal properties. public void Refresh(BSPhysObject requestor) { - // If there are no children, there aren't any constraints to recompute + // If there are no children, there can't be any constraints to recompute if (!HasAnyChildren) return; @@ -225,11 +225,12 @@ public class BSLinkset // from a linkset to make sure the constraints know about the new mass and // geometry. // Must only be called at taint time!! - private bool RecomputeLinksetConstraintVariables() + private void RecomputeLinksetConstraintVariables() { float linksetMass = LinksetMass; lock (m_linksetActivityLock) { + bool somethingMissing = false; foreach (BSPhysObject child in m_children) { BSConstraint constrain; @@ -241,16 +242,29 @@ public class BSLinkset } else { - // Non-fatal error that can happen when children are being added to the linkset but + // Non-fatal error that happens when children are being added to the linkset but // their constraints have not been created yet. // Caused by the fact that m_children is built at run time but building constraints // happens at taint time. - // m_physicsScene.Logger.ErrorFormat("{0} RecomputeLinksetConstraintVariables: constraint not found for root={1}, child={2}", - // LogHeader, m_linksetRoot.Body.ID, child.Body.ID); + somethingMissing = true; + break; } } + + // If the whole linkset is not here, doesn't make sense to recompute the root prim now. + if (!somethingMissing) + { + // The root prim takes on the weight of the whole linkset + /* + OMV.Vector3 inertia = BulletSimAPI.CalculateLocalInertia2(LinksetRoot.BSShape.Ptr, linksetMass); + BulletSimAPI.SetMassProps2(LinksetRoot.BSBody.Ptr, linksetMass, inertia); + OMV.Vector3 centerOfMass = ComputeLinksetCenterOfMass(); + BulletSimAPI.SetCenterOfMassByPosRot2(LinksetRoot.BSBody.Ptr, centerOfMass, OMV.Quaternion.Identity); + BulletSimAPI.UpdateInertiaTensor2(LinksetRoot.BSBody.Ptr); + */ + } } - return false; + return; } // I am the root of a linkset and a new child is being added @@ -296,9 +310,9 @@ public class BSLinkset DetailLog("{0},RemoveChildFromLinkset,taint,child={1}", m_linksetRoot.LocalID, child.LocalID); PhysicallyUnlinkAChildFromRoot(rootx, childx); + RecomputeLinksetConstraintVariables(); }); - RecomputeLinksetConstraintVariables(); } else { @@ -377,6 +391,10 @@ public class BSLinkset PhysicsScene.Params.linkConstraintTransMotorMaxVel, PhysicsScene.Params.linkConstraintTransMotorMaxForce); constrain.SetCFMAndERP(PhysicsScene.Params.linkConstraintCFM, PhysicsScene.Params.linkConstraintERP); + if (PhysicsScene.Params.linkConstraintSolverIterations != 0f) + { + constrain.SetSolverIterations(PhysicsScene.Params.linkConstraintSolverIterations); + } RecomputeLinksetConstraintVariables(); } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs index e411fcb..969c53e 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs @@ -41,7 +41,7 @@ public abstract class BSPhysObject : PhysicsActor { public abstract BSLinkset Linkset { get; set; } - public abstract void Collide(uint collidingWith, BSPhysObject collidee, ActorTypes type, + public abstract bool Collide(uint collidingWith, BSPhysObject collidee, ActorTypes type, OMV.Vector3 contactPoint, OMV.Vector3 contactNormal, float pentrationDepth); public abstract void SendCollisions(); diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index 6d0af63..481a8db 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs @@ -136,11 +136,11 @@ public sealed class BSPrim : BSPhysObject Linkset = new BSLinkset(Scene, this); // a linkset of one _vehicle = new BSDynamics(Scene, this); // add vehicleness _mass = CalculateMass(); - // do the actual object creation at taint time DetailLog("{0},BSPrim.constructor,call", LocalID); + // do the actual object creation at taint time _scene.TaintedObject("BSPrim.create", delegate() { - RecreateGeomAndObject(); + CreateGeomAndObject(true); // Get the pointer to the physical body for this object. // At the moment, we're still letting BulletSim manage the creation and destruction @@ -186,9 +186,10 @@ public sealed class BSPrim : BSPhysObject _scene.TaintedObject("BSPrim.setSize", delegate() { _mass = CalculateMass(); // changing size changes the mass - BulletSimAPI.SetObjectScaleMass(_scene.WorldID, _localID, _scale, (IsPhysical ? _mass : 0f), IsPhysical); - DetailLog("{0}: BSPrim.setSize: size={1}, mass={2}, physical={3}", LocalID, _size, _mass, IsPhysical); - RecreateGeomAndObject(); + // Since _size changed, the mesh needs to be rebuilt. If rebuilt, all the correct + // scale and margins are set. + CreateGeomAndObject(true); + DetailLog("{0}: BSPrim.setSize: size={1}, scale={2}, mass={3}, physical={4}", LocalID, _size, _scale, _mass, IsPhysical); }); } } @@ -198,7 +199,7 @@ public sealed class BSPrim : BSPhysObject _scene.TaintedObject("BSPrim.setShape", delegate() { _mass = CalculateMass(); // changing the shape changes the mass - RecreateGeomAndObject(); + CreateGeomAndObject(false); }); } } @@ -279,7 +280,7 @@ public sealed class BSPrim : BSPhysObject get { if (!Linkset.IsRoot(this)) // child prims move around based on their parent. Need to get the latest location - _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID); + _position = BulletSimAPI.GetPosition2(BSBody.Ptr); // don't do the GetObjectPosition for root elements because this function is called a zillion times // _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID); @@ -291,7 +292,7 @@ public sealed class BSPrim : BSPhysObject _scene.TaintedObject("BSPrim.setPosition", delegate() { DetailLog("{0},BSPrim.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation); - BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation); + BulletSimAPI.SetTranslation2(BSBody.Ptr, _position, _orientation); }); } } @@ -302,7 +303,8 @@ public sealed class BSPrim : BSPhysObject { get { - return Linkset.LinksetMass; + // return Linkset.LinksetMass; + return _mass; } } @@ -328,7 +330,6 @@ public sealed class BSPrim : BSPhysObject _scene.TaintedObject("BSPrim.setForce", delegate() { DetailLog("{0},BSPrim.setForce,taint,force={1}", LocalID, _force); - // BulletSimAPI.SetObjectForce(_scene.WorldID, _localID, _force); BulletSimAPI.SetObjectForce2(BSBody.Ptr, _force); }); } @@ -406,7 +407,7 @@ public sealed class BSPrim : BSPhysObject _scene.TaintedObject("BSPrim.setVelocity", delegate() { DetailLog("{0},BSPrim.SetVelocity,taint,vel={1}", LocalID, _velocity); - BulletSimAPI.SetObjectVelocity(_scene.WorldID, LocalID, _velocity); + BulletSimAPI.SetLinearVelocity2(BSBody.Ptr, _velocity); }); } } @@ -430,7 +431,7 @@ public sealed class BSPrim : BSPhysObject if (!Linkset.IsRoot(this)) { // Children move around because tied to parent. Get a fresh value. - _orientation = BulletSimAPI.GetObjectOrientation(_scene.WorldID, LocalID); + _orientation = BulletSimAPI.GetOrientation2(BSBody.Ptr); } return _orientation; } @@ -441,7 +442,7 @@ public sealed class BSPrim : BSPhysObject { // _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID); DetailLog("{0},BSPrim.setOrientation,taint,pos={1},orient={2}", LocalID, _position, _orientation); - BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation); + BulletSimAPI.SetTranslation2(BSBody.Ptr, _position, _orientation); }); } } @@ -483,31 +484,37 @@ public sealed class BSPrim : BSPhysObject { // If it's becoming dynamic, it will need hullness VerifyCorrectPhysicalShape(); + UpdatePhysicalParameters(); + } + private void UpdatePhysicalParameters() + { + /* // Bullet wants static objects to have a mass of zero float mass = IsStatic ? 0f : _mass; BulletSimAPI.SetObjectProperties(_scene.WorldID, LocalID, IsStatic, IsSolid, SubscribedEvents(), mass); - /* + */ BulletSimAPI.RemoveObjectFromWorld2(Scene.World.Ptr, BSBody.Ptr); - // Set up the object physicalness (static or dynamic) - MakeDynamic(); + // Set up the object physicalness (does gravity and collisions move this object) + MakeDynamic(IsStatic); - // Make solid or not and arrange for collisions, etc - MakeSolid(); + // Make solid or not (do things bounce off or pass through this object) + MakeSolid(IsSolid); - m_currentCollisionFlags = BulletSimAPI.GetCollisionFlags2(BSBody.Ptr); + // Arrange for collisions events if the simulator wants them + EnableCollisions(SubscribedEvents()); BulletSimAPI.AddObjectToWorld2(Scene.World.Ptr, BSBody.Ptr); - */ // Recompute any linkset parameters. // When going from non-physical to physical, this re-enables the constraints that // had been automatically disabled when the mass was set to zero. Linkset.Refresh(this); - DetailLog("{0},BSPrim.SetObjectDynamic,taint,static={1},solid={2},mass={3}, cf={4}", LocalID, IsStatic, IsSolid, mass, m_currentCollisionFlags); + DetailLog("{0},BSPrim.UpdatePhysicalParameters,taint,static={1},solid={2},mass={3}, cf={4}", + LocalID, IsStatic, IsSolid, _mass, m_currentCollisionFlags); } // "Making dynamic" means changing to and from static. @@ -515,12 +522,12 @@ public sealed class BSPrim : BSPhysObject // When dynamic, the object can fall and be pushed by others. // This is independent of its 'solidness' which controls what passes through // this object and what interacts with it. - private void MakeDynamic() + private void MakeDynamic(bool makeStatic) { - if (IsStatic) + if (makeStatic) { // Become a Bullet 'static' object type - BulletSimAPI.AddToCollisionFlags2(BSBody.Ptr, CollisionFlags.CF_STATIC_OBJECT); + m_currentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(BSBody.Ptr, CollisionFlags.CF_STATIC_OBJECT); // Stop all movement BulletSimAPI.ClearAllForces2(BSBody.Ptr); // Mass is zero which disables a bunch of physics stuff in Bullet @@ -533,12 +540,11 @@ public sealed class BSPrim : BSPhysObject else { // Not a Bullet static object - BulletSimAPI.RemoveFromCollisionFlags2(BSBody.Ptr, CollisionFlags.CF_STATIC_OBJECT); + m_currentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(BSBody.Ptr, CollisionFlags.CF_STATIC_OBJECT); // A dynamic object has mass - BulletSimAPI.SetMassProps2(BSBody.Ptr, _mass, OMV.Vector3.Zero); - // The shape is interesting and has mass and a center of gravity IntPtr collisionShapePtr = BulletSimAPI.GetCollisionShape2(BSBody.Ptr); - BulletSimAPI.CalculateLocalInertia2(collisionShapePtr, _mass, OMV.Vector3.Zero); + OMV.Vector3 inertia = BulletSimAPI.CalculateLocalInertia2(collisionShapePtr, _mass); + BulletSimAPI.SetMassProps2(BSBody.Ptr, _mass, inertia); // Inertia is based on our new mass BulletSimAPI.UpdateInertiaTensor2(BSBody.Ptr); // Force activation of the object so Bullet will act on it. @@ -546,8 +552,31 @@ public sealed class BSPrim : BSPhysObject } } - private void MakeSolid() + // "Making solid" means that other object will not pass through this object. + private void MakeSolid(bool makeSolid) { + if (makeSolid) + { + // Easy in Bullet -- just remove the object flag that controls collision response + m_currentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(BSBody.Ptr, CollisionFlags.CF_NO_CONTACT_RESPONSE); + } + else + { + m_currentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(BSBody.Ptr, CollisionFlags.CF_NO_CONTACT_RESPONSE); + } + } + + // Turn on or off the flag controlling whether collision events are returned to the simulator. + private void EnableCollisions(bool wantsCollisionEvents) + { + if (wantsCollisionEvents) + { + m_currentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(BSBody.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); + } + else + { + m_currentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(BSBody.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); + } } // prims don't fly @@ -607,7 +636,7 @@ public sealed class BSPrim : BSPhysObject _scene.TaintedObject("BSPrim.setRotationalVelocity", delegate() { DetailLog("{0},BSPrim.SetRotationalVel,taint,rotvel={1}", LocalID, _rotationalVelocity); - BulletSimAPI.SetObjectAngularVelocity(_scene.WorldID, LocalID, _rotationalVelocity); + BulletSimAPI.SetAngularVelocity2(BSBody.Ptr, _rotationalVelocity); }); } } @@ -624,7 +653,10 @@ public sealed class BSPrim : BSPhysObject _scene.TaintedObject("BSPrim.setBuoyancy", delegate() { DetailLog("{0},BSPrim.SetBuoyancy,taint,buoy={1}", LocalID, _buoyancy); - BulletSimAPI.SetObjectBuoyancy(_scene.WorldID, _localID, _buoyancy); + // Buoyancy is faked by changing the gravity applied to the object + float grav = Scene.Params.gravity * (1f - _buoyancy); + BulletSimAPI.SetGravity2(BSBody.Ptr, new OMV.Vector3(0f, 0f, grav)); + // BulletSimAPI.SetObjectBuoyancy(_scene.WorldID, _localID, _buoyancy); }); } } @@ -686,8 +718,8 @@ public sealed class BSPrim : BSPhysObject } m_accumulatedForces.Clear(); } - DetailLog("{0},BSPrim.AddObjectForce,taint,force={1}", LocalID, _force); - // For unknown reason, "ApplyCentralForce" is really additive. + DetailLog("{0},BSPrim.AddObjectForce,taint,force={1}", LocalID, fSum); + // For unknown reasons, "ApplyCentralForce" adds this force to the total force on the object. BulletSimAPI.ApplyCentralForce2(BSBody.Ptr, fSum); }); } @@ -1030,29 +1062,36 @@ public sealed class BSPrim : BSPhysObject // Returns 'true' if the geometry was rebuilt private bool CreateGeom(bool forceRebuild) { - // the mesher thought this was too simple to mesh. Use a native Bullet collision shape. bool ret = false; - if (!_scene.NeedsMeshing(_pbs)) + bool haveShape = false; + + // If the prim attributes are simple, this could be a simple Bullet native shape + if ((_pbs.SculptEntry && !Scene.ShouldMeshSculptedPrim) + || (_pbs.ProfileBegin == 0 && _pbs.ProfileEnd == 0 + && _pbs.ProfileHollow == 0 + && _pbs.PathTwist == 0 && _pbs.PathTwistBegin == 0 + && _pbs.PathBegin == 0 && _pbs.PathEnd == 0 + && _pbs.PathTaperX == 0 && _pbs.PathTaperY == 0 + && _pbs.PathScaleX == 100 && _pbs.PathScaleY == 100 + && _pbs.PathShearX == 0 && _pbs.PathShearY == 0) ) { if (_pbs.ProfileShape == ProfileShape.HalfCircle && _pbs.PathCurve == (byte)Extrusion.Curve1) { - // if (_size.X == _size.Y && _size.Y == _size.Z && _size.X == _size.Z) - // { - // m_log.DebugFormat("{0}: CreateGeom: Defaulting to sphere of size {1}", LogHeader, _size); - if (forceRebuild || (_shapeType != ShapeData.PhysicsShapeType.SHAPE_SPHERE)) - { - DetailLog("{0},BSPrim.CreateGeom,sphere (force={1}", LocalID, forceRebuild); - _shapeType = ShapeData.PhysicsShapeType.SHAPE_SPHERE; - // Bullet native objects are scaled by the Bullet engine so pass the size in - _scale = _size; - // TODO: do we need to check for and destroy a mesh or hull that might have been left from before? - ret = true; - } - // } + haveShape = true; + if (forceRebuild || (_shapeType != ShapeData.PhysicsShapeType.SHAPE_SPHERE)) + { + DetailLog("{0},BSPrim.CreateGeom,sphere (force={1}", LocalID, forceRebuild); + _shapeType = ShapeData.PhysicsShapeType.SHAPE_SPHERE; + // Bullet native objects are scaled by the Bullet engine so pass the size in + _scale = _size; + // TODO: do we need to check for and destroy a mesh or hull that might have been left from before? + ret = true; + } } else { // m_log.DebugFormat("{0}: CreateGeom: Defaulting to box. lid={1}, type={2}, size={3}", LogHeader, LocalID, _shapeType, _size); + haveShape = true; if (forceRebuild || (_shapeType != ShapeData.PhysicsShapeType.SHAPE_BOX)) { DetailLog("{0},BSPrim.CreateGeom,box (force={1})", LocalID, forceRebuild); @@ -1063,16 +1102,16 @@ public sealed class BSPrim : BSPhysObject } } } - else + // If a simple shape isn't happening, create a mesh and possibly a hull + if (!haveShape) { if (IsPhysical) { if (forceRebuild || _hullKey == 0) { // physical objects require a hull for interaction. - // This will create the mesh if it doesn't already exist - CreateGeomHull(); - ret = true; + // This also creates the mesh if it doesn't already exist + ret = CreateGeomHull(); } } else @@ -1080,8 +1119,7 @@ public sealed class BSPrim : BSPhysObject if (forceRebuild || _meshKey == 0) { // Static (non-physical) objects only need a mesh for bumping into - CreateGeomMesh(); - ret = true; + ret = CreateGeomMesh(); } } } @@ -1089,7 +1127,8 @@ public sealed class BSPrim : BSPhysObject } // No locking here because this is done when we know physics is not simulating - private void CreateGeomMesh() + // Returns 'true' of a mesh was actually rebuild (we could also have one of these specs). + private bool CreateGeomMesh() { // level of detail based on size and type of the object float lod = _scene.MeshLOD; @@ -1103,7 +1142,7 @@ public sealed class BSPrim : BSPhysObject // m_log.DebugFormat("{0}: CreateGeomMesh: lID={1}, oldKey={2}, newKey={3}", LogHeader, _localID, _meshKey, newMeshKey); // if this new shape is the same as last time, don't recreate the mesh - if (_meshKey == newMeshKey) return; + if (_meshKey == newMeshKey) return false; DetailLog("{0},BSPrim.CreateGeomMesh,create,key={1}", LocalID, newMeshKey); // Since we're recreating new, get rid of any previously generated shape @@ -1140,19 +1179,19 @@ public sealed class BSPrim : BSPhysObject _shapeType = ShapeData.PhysicsShapeType.SHAPE_MESH; // meshes are already scaled by the meshmerizer _scale = new OMV.Vector3(1f, 1f, 1f); - DetailLog("{0},BSPrim.CreateGeomMesh,done", LocalID); - return; + return true; } // No locking here because this is done when we know physics is not simulating - private void CreateGeomHull() + // Returns 'true' of a mesh was actually rebuild (we could also have one of these specs). + private bool CreateGeomHull() { float lod = _pbs.SculptEntry ? _scene.SculptLOD : _scene.MeshLOD; ulong newHullKey = (ulong)_pbs.GetMeshKey(_size, lod); // m_log.DebugFormat("{0}: CreateGeomHull: lID={1}, oldKey={2}, newKey={3}", LogHeader, _localID, _hullKey, newHullKey); // if the hull hasn't changed, don't rebuild it - if (newHullKey == _hullKey) return; + if (newHullKey == _hullKey) return false; DetailLog("{0},BSPrim.CreateGeomHull,create,oldKey={1},newKey={2}", LocalID, _hullKey, newHullKey); @@ -1255,7 +1294,7 @@ public sealed class BSPrim : BSPhysObject // meshes are already scaled by the meshmerizer _scale = new OMV.Vector3(1f, 1f, 1f); DetailLog("{0},BSPrim.CreateGeomHull,done", LocalID); - return; + return true; } // Callback from convex hull creater with a newly created hull. @@ -1268,20 +1307,12 @@ public sealed class BSPrim : BSPhysObject private void VerifyCorrectPhysicalShape() { - if (IsStatic) - { - // if static, we don't need a hull so, if there is one, rebuild without it - if (_hullKey != 0) - { - RecreateGeomAndObject(); - } - } - else + if (!IsStatic) { // if not static, it will need a hull to efficiently collide with things if (_hullKey == 0) { - RecreateGeomAndObject(); + CreateGeomAndObject(false); } } @@ -1300,8 +1331,9 @@ public sealed class BSPrim : BSPhysObject // m_log.DebugFormat("{0}: CreateObject: lID={1}, shape={2}", LogHeader, _localID, shape.Type); bool ret = BulletSimAPI.CreateObject(_scene.WorldID, shape); - // the CreateObject() may have recreated the rigid body. Make sure we have the latest. + // the CreateObject() may have recreated the rigid body. Make sure we have the latest address. BSBody = new BulletBody(LocalID, BulletSimAPI.GetBodyHandle2(_scene.World.Ptr, LocalID)); + BSShape = new BulletShape(BulletSimAPI.GetCollisionShape2(BSBody.Ptr)); return ret; } @@ -1325,15 +1357,20 @@ public sealed class BSPrim : BSPhysObject shape.Static = _isPhysical ? ShapeData.numericFalse : ShapeData.numericTrue; } - // Rebuild the geometry and object. // This is called when the shape changes so we need to recreate the mesh/hull. // No locking here because this is done when the physics engine is not simulating - private void RecreateGeomAndObject() + private void CreateGeomAndObject(bool forceRebuild) { - // m_log.DebugFormat("{0}: RecreateGeomAndObject. lID={1}", LogHeader, _localID); - if (CreateGeom(true)) + // m_log.DebugFormat("{0}: CreateGeomAndObject. lID={1}, force={2}", LogHeader, _localID, forceRebuild); + // Create the geometry that will make up the object + if (CreateGeom(forceRebuild)) + { + // Create the object and place it into the world CreateObject(); + // Make sure the properties are set on the new object + UpdatePhysicalParameters(); + } return; } @@ -1430,9 +1467,10 @@ public sealed class BSPrim : BSPhysObject // I've collided with something // Called at taint time from within the Step() function CollisionEventUpdate collisionCollection; - public override void Collide(uint collidingWith, BSPhysObject collidee, ActorTypes type, OMV.Vector3 contactPoint, OMV.Vector3 contactNormal, float pentrationDepth) + public override bool Collide(uint collidingWith, BSPhysObject collidee, ActorTypes type, OMV.Vector3 contactPoint, OMV.Vector3 contactNormal, float pentrationDepth) { // m_log.DebugFormat("{0}: Collide: ms={1}, id={2}, with={3}", LogHeader, _subscribedEventsMs, LocalID, collidingWith); + bool ret = false; // The following lines make IsColliding() and IsCollidingGround() work _collidingStep = _scene.SimulationStep; @@ -1446,7 +1484,7 @@ public sealed class BSPrim : BSPhysObject // prims in the same linkset cannot collide with each other if (collidee != null && (this.Linkset.LinksetID == collidee.Linkset.LinksetID)) { - return; + return ret; } // if someone has subscribed for collision events.... @@ -1459,8 +1497,10 @@ public sealed class BSPrim : BSPhysObject if (collisionCollection == null) collisionCollection = new CollisionEventUpdate(); collisionCollection.AddCollider(collidingWith, new ContactPoint(contactPoint, contactNormal, pentrationDepth)); + ret = true; } } + return ret; } // The scene is telling us it's time to pass our collected collisions into the simulator diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs index 4a468af..eea899f 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs @@ -79,7 +79,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters private HashSet m_objectsWithCollisions = new HashSet(); // Following is a kludge and can be removed when avatar animation updating is // moved to a better place. - private HashSet m_avatarsWithCollisions = new HashSet(); + private HashSet m_avatarsWithCollisions = new HashSet(); // List of all the objects that have vehicle properties and should be called // to update each physics step. @@ -132,8 +132,8 @@ public class BSScene : PhysicsScene, IPhysicsParameters private EntityProperties[] m_updateArray; private GCHandle m_updateArrayPinnedHandle; - private bool _meshSculptedPrim = true; // cause scuplted prims to get meshed - private bool _forceSimplePrimMeshing = false; // if a cube or sphere, let Bullet do internal shapes + public bool ShouldMeshSculptedPrim { get; private set; } // cause scuplted prims to get meshed + public bool ShouldForceSimplePrimMeshing { get; private set; } // if a cube or sphere, let Bullet do internal shapes public float PID_D { get; private set; } // derivative public float PID_P { get; private set; } // proportional @@ -153,6 +153,11 @@ public class BSScene : PhysicsScene, IPhysicsParameters { get { return new Vector3(0f, 0f, Params.gravity); } } + // Just the Z value of the gravity + public float DefaultGravityZ + { + get { return Params.gravity; } + } public float MaximumObjectMass { get; private set; } @@ -171,8 +176,8 @@ public class BSScene : PhysicsScene, IPhysicsParameters callback = c; } } + private Object _taintLock = new Object(); // lock for using the next object private List _taintedObjects; - private Object _taintLock = new Object(); // A pointer to an instance if this structure is passed to the C++ code // Used to pass basic configuration values to the unmanaged code. @@ -478,6 +483,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters // Some of the prims operate with special vehicle properties ProcessVehicles(timeStep); + numTaints += _taintedObjects.Count; ProcessTaints(); // the vehicles might have added taints // step the physical world one interval @@ -506,6 +512,12 @@ public class BSScene : PhysicsScene, IPhysicsParameters // Get a value for 'now' so all the collision and update routines don't have to get their own SimulationNowTime = Util.EnvironmentTickCount(); + // This is a kludge to get avatar movement updates. + // ODE sends collisions for avatars even if there are have been no collisions. This updates + // avatar animations and stuff. + // If you fix avatar animation updates, remove this overhead and let collisions happen. + m_objectsWithCollisions = new HashSet(m_avatarsWithCollisions); + // If there were collisions, process them by sending the event to the prim. // Collisions must be processed before updates. if (collidersCount > 0) @@ -527,13 +539,6 @@ public class BSScene : PhysicsScene, IPhysicsParameters bsp.SendCollisions(); m_objectsWithCollisions.Clear(); - // This is a kludge to get avatar movement updated. - // ODE sends collisions even if there are none and this is used to update - // avatar animations and stuff. - foreach (BSPhysObject bpo in m_avatarsWithCollisions) - bpo.SendCollisions(); - // m_avatarsWithCollisions.Clear(); - // If any of the objects had updated properties, tell the object it has been changed by the physics engine if (updatedEntityCount > 0) { @@ -544,7 +549,6 @@ public class BSScene : PhysicsScene, IPhysicsParameters if (PhysObjects.TryGetValue(entprop.ID, out pobj)) { pobj.UpdateProperties(entprop); - continue; } } } @@ -600,8 +604,11 @@ public class BSScene : PhysicsScene, IPhysicsParameters // DetailLog("{0},BSScene.SendCollision,collide,id={1},with={2}", DetailLogZero, localID, collidingWith); - collider.Collide(collidingWith, collidee, type, collidePoint, collideNormal, penetration); - m_objectsWithCollisions.Add(collider); + if (collider.Collide(collidingWith, collidee, type, collidePoint, collideNormal, penetration)) + { + // If a collision was posted, remember to send it to the simulator + m_objectsWithCollisions.Add(collider); + } return; } @@ -619,9 +626,9 @@ public class BSScene : PhysicsScene, IPhysicsParameters public override void SetWaterLevel(float baseheight) { m_waterLevel = baseheight; - // TODO: pass to physics engine so things will float? } - public float GetWaterLevel() + // Someday.... + public float GetWaterLevelAtXYZ(Vector3 loc) { return m_waterLevel; } @@ -672,7 +679,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters // int iPropertiesNotSupportedDefault = 0; - if (pbs.SculptEntry && !_meshSculptedPrim) + if (pbs.SculptEntry && !ShouldMeshSculptedPrim) { // Render sculpties as boxes return false; @@ -680,7 +687,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters // if it's a standard box or sphere with no cuts, hollows, twist or top shear, return false since Bullet // can use an internal representation for the prim - if (!_forceSimplePrimMeshing) + if (!ShouldForceSimplePrimMeshing) { if ((pbs.ProfileShape == ProfileShape.Square && pbs.PathCurve == (byte)Extrusion.Straight) || (pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1 @@ -782,7 +789,10 @@ public class BSScene : PhysicsScene, IPhysicsParameters if (!m_initialized) return; lock (_taintLock) + { _taintedObjects.Add(new TaintCallbackEntry(ident, callback)); + } + return; } @@ -919,14 +929,14 @@ public class BSScene : PhysicsScene, IPhysicsParameters { new ParameterDefn("MeshSculptedPrim", "Whether to create meshes for sculpties", ConfigurationParameters.numericTrue, - (s,cf,p,v) => { s._meshSculptedPrim = cf.GetBoolean(p, s.BoolNumeric(v)); }, - (s) => { return s.NumericBool(s._meshSculptedPrim); }, - (s,p,l,v) => { s._meshSculptedPrim = s.BoolNumeric(v); } ), + (s,cf,p,v) => { s.ShouldMeshSculptedPrim = cf.GetBoolean(p, s.BoolNumeric(v)); }, + (s) => { return s.NumericBool(s.ShouldMeshSculptedPrim); }, + (s,p,l,v) => { s.ShouldMeshSculptedPrim = s.BoolNumeric(v); } ), new ParameterDefn("ForceSimplePrimMeshing", "If true, only use primitive meshes for objects", ConfigurationParameters.numericFalse, - (s,cf,p,v) => { s._forceSimplePrimMeshing = cf.GetBoolean(p, s.BoolNumeric(v)); }, - (s) => { return s.NumericBool(s._forceSimplePrimMeshing); }, - (s,p,l,v) => { s._forceSimplePrimMeshing = s.BoolNumeric(v); } ), + (s,cf,p,v) => { s.ShouldForceSimplePrimMeshing = cf.GetBoolean(p, s.BoolNumeric(v)); }, + (s) => { return s.NumericBool(s.ShouldForceSimplePrimMeshing); }, + (s,p,l,v) => { s.ShouldForceSimplePrimMeshing = s.BoolNumeric(v); } ), new ParameterDefn("MeshLevelOfDetail", "Level of detail to render meshes (32, 16, 8 or 4. 32=most detailed)", 8f, @@ -1162,8 +1172,8 @@ public class BSScene : PhysicsScene, IPhysicsParameters (s,cf,p,v) => { s.m_params[0].linkConstraintTransMotorMaxForce = cf.GetFloat(p, v); }, (s) => { return s.m_params[0].linkConstraintTransMotorMaxForce; }, (s,p,l,v) => { s.m_params[0].linkConstraintTransMotorMaxForce = v; } ), - new ParameterDefn("LinkConstraintCFM", "Amount constraint can be violated. 0=none, 1=all. Default=0", - 0.0f, + new ParameterDefn("LinkConstraintCFM", "Amount constraint can be violated. 0=no violation, 1=infinite. Default=0.1", + 0.1f, (s,cf,p,v) => { s.m_params[0].linkConstraintCFM = cf.GetFloat(p, v); }, (s) => { return s.m_params[0].linkConstraintCFM; }, (s,p,l,v) => { s.m_params[0].linkConstraintCFM = v; } ), @@ -1172,6 +1182,11 @@ public class BSScene : PhysicsScene, IPhysicsParameters (s,cf,p,v) => { s.m_params[0].linkConstraintERP = cf.GetFloat(p, v); }, (s) => { return s.m_params[0].linkConstraintERP; }, (s,p,l,v) => { s.m_params[0].linkConstraintERP = v; } ), + new ParameterDefn("LinkConstraintSolverIterations", "Number of solver iterations when computing constraint. (0 = Bullet default)", + 40, + (s,cf,p,v) => { s.m_params[0].linkConstraintSolverIterations = cf.GetFloat(p, v); }, + (s) => { return s.m_params[0].linkConstraintSolverIterations; }, + (s,p,l,v) => { s.m_params[0].linkConstraintSolverIterations = v; } ), new ParameterDefn("DetailedStats", "Frames between outputting detailed phys stats. (0 is off)", 0f, diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs index 47d7199..d48462e 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs @@ -154,27 +154,31 @@ public class BSTerrainManager // The simulator wants to set a new heightmap for the terrain. public void SetTerrain(float[] heightMap) { - if (m_worldOffset != Vector3.Zero && m_parentScene != null) + float[] localHeightMap = heightMap; + m_physicsScene.TaintedObject("TerrainManager.SetTerrain", delegate() { - // If a child of a mega-region, we shouldn't have any terrain allocated for us - ReleaseGroundPlaneAndTerrain(); - // If doing the mega-prim stuff and we are the child of the zero region, - // the terrain is added to our parent - if (m_parentScene is BSScene) + if (m_worldOffset != Vector3.Zero && m_parentScene != null) { - DetailLog("{0},SetTerrain.ToParent,offset={1},worldMax={2}", - BSScene.DetailLogZero, m_worldOffset, m_worldMax); - ((BSScene)m_parentScene).TerrainManager.UpdateOrCreateTerrain(BSScene.CHILDTERRAIN_ID, - heightMap, m_worldOffset, m_worldOffset+DefaultRegionSize, false); + // If a child of a mega-region, we shouldn't have any terrain allocated for us + ReleaseGroundPlaneAndTerrain(); + // If doing the mega-prim stuff and we are the child of the zero region, + // the terrain is added to our parent + if (m_parentScene is BSScene) + { + DetailLog("{0},SetTerrain.ToParent,offset={1},worldMax={2}", + BSScene.DetailLogZero, m_worldOffset, m_worldMax); + ((BSScene)m_parentScene).TerrainManager.UpdateOrCreateTerrain(BSScene.CHILDTERRAIN_ID, + localHeightMap, m_worldOffset, m_worldOffset + DefaultRegionSize, true); + } } - } - else - { - // If not doing the mega-prim thing, just change the terrain - DetailLog("{0},SetTerrain.Existing", BSScene.DetailLogZero); + else + { + // If not doing the mega-prim thing, just change the terrain + DetailLog("{0},SetTerrain.Existing", BSScene.DetailLogZero); - UpdateOrCreateTerrain(BSScene.TERRAIN_ID, heightMap, m_worldOffset, m_worldOffset+DefaultRegionSize, false); - } + UpdateOrCreateTerrain(BSScene.TERRAIN_ID, localHeightMap, m_worldOffset, m_worldOffset + DefaultRegionSize, true); + } + }); } // If called with no mapInfo for the terrain, this will create a new mapInfo and terrain @@ -319,6 +323,8 @@ public class BSTerrainManager // Make sure the new shape is processed. BulletSimAPI.Activate2(mapInfo.terrainBody.Ptr, true); + + m_terrainModified = true; }; // There is the option to do the changes now (we're already in 'taint time'), or @@ -357,6 +363,8 @@ public class BSTerrainManager m_heightMaps.Add(terrainRegionBase, mapInfo); // Build the terrain UpdateOrCreateTerrain(newTerrainID, heightMap, minCoords, maxCoords, true); + + m_terrainModified = true; }; // If already in taint-time, just call Bullet. Otherwise queue the operations for the safe time. @@ -383,7 +391,7 @@ public class BSTerrainManager private float lastHeightTX = 999999f; private float lastHeightTY = 999999f; private float lastHeight = HEIGHT_INITIAL_LASTHEIGHT; - public float GetTerrainHeightAtXY(float tX, float tY) + private float GetTerrainHeightAtXY(float tX, float tY) { // You'd be surprized at the number of times this routine is called // with the same parameters as last time. @@ -403,11 +411,18 @@ public class BSTerrainManager { float regionX = tX - offsetX; float regionY = tY - offsetY; - if (regionX >= mapInfo.sizeX || regionX < 0f) regionX = 0; - if (regionY >= mapInfo.sizeY || regionY < 0f) regionY = 0; int mapIndex = (int)regionY * (int)mapInfo.sizeY + (int)regionX; - ret = mapInfo.heightMap[mapIndex]; - m_terrainModified = false; + try + { + ret = mapInfo.heightMap[mapIndex]; + } + catch + { + // Sometimes they give us wonky values of X and Y. Give a warning and return something. + m_physicsScene.Logger.WarnFormat("{0} Bad request for terrain height. terrainBase={1}, x={2}, y={3}", + LogHeader, terrainBaseXY, regionX, regionY); + ret = HEIGHT_GETHEIGHT_RET; + } // DetailLog("{0},BSTerrainManager.GetTerrainHeightAtXY,bX={1},baseY={2},szX={3},szY={4},regX={5},regY={6},index={7},ht={8}", // BSScene.DetailLogZero, offsetX, offsetY, mapInfo.sizeX, mapInfo.sizeY, regionX, regionY, mapIndex, ret); } @@ -416,6 +431,7 @@ public class BSTerrainManager m_physicsScene.Logger.ErrorFormat("{0} GetTerrainHeightAtXY: terrain not found: region={1}, x={2}, y={3}", LogHeader, m_physicsScene.RegionName, tX, tY); } + m_terrainModified = false; lastHeight = ret; return ret; } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs index e579cf2..043423e 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs @@ -213,6 +213,7 @@ public struct ConfigurationParameters public float linkConstraintTransMotorMaxForce; public float linkConstraintERP; public float linkConstraintCFM; + public float linkConstraintSolverIterations; public const float numericTrue = 1f; public const float numericFalse = 0f; @@ -395,23 +396,6 @@ public static extern bool DestroyMesh(uint worldID, System.UInt64 meshKey); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern bool CreateObject(uint worldID, ShapeData shapeData); -/* Remove old functionality -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void CreateLinkset(uint worldID, int objectCount, ShapeData[] shapeDatas); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void AddConstraint(uint worldID, uint id1, uint id2, - Vector3 frame1, Quaternion frame1rot, - Vector3 frame2, Quaternion frame2rot, - Vector3 lowLinear, Vector3 hiLinear, Vector3 lowAngular, Vector3 hiAngular); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern bool RemoveConstraintByID(uint worldID, uint id1); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern bool RemoveConstraint(uint worldID, uint id1, uint id2); - */ - [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern Vector3 GetObjectPosition(uint WorldID, uint id); @@ -545,6 +529,15 @@ public static extern bool DeleteCollisionShape2(IntPtr world, IntPtr shape); public static extern IntPtr CreateBodyFromShape2(IntPtr sim, IntPtr shape, Vector3 pos, Quaternion rot); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern IntPtr CreateCompoundShape2(IntPtr sim); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern void AddChildToCompoundShape2(IntPtr cShape, IntPtr addShape, Vector3 pos, Quaternion rot); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern void RemoveChildFromCompoundShape2(IntPtr cShape, IntPtr removeShape); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern IntPtr CreateBodyFromShapeAndInfo2(IntPtr sim, IntPtr shape, IntPtr constructionInfo); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] @@ -1010,7 +1003,7 @@ public static extern void SetLocalScaling2(IntPtr shape, Vector3 scale); public static extern Vector3 GetLocalScaling2(IntPtr shape); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void CalculateLocalInertia2(IntPtr shape, float mass, Vector3 inertia); +public static extern Vector3 CalculateLocalInertia2(IntPtr shape, float mass); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern int GetShapeType2(IntPtr shape); -- cgit v1.1 From c0fec70b1ad3047b8e543558a6aaee2916bd7b3f Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Thu, 13 Sep 2012 10:10:29 -0700 Subject: BulletSim: Add 'IsNativeShape2' call --- OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs index 043423e..087c61b 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs @@ -523,10 +523,7 @@ public static extern IntPtr BuildNativeShape2(IntPtr world, float shapeType, float collisionMargin, Vector3 scale); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern bool DeleteCollisionShape2(IntPtr world, IntPtr shape); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern IntPtr CreateBodyFromShape2(IntPtr sim, IntPtr shape, Vector3 pos, Quaternion rot); +public static extern bool IsNativeShape2(IntPtr shape); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern IntPtr CreateCompoundShape2(IntPtr sim); @@ -541,6 +538,12 @@ public static extern void RemoveChildFromCompoundShape2(IntPtr cShape, IntPtr re public static extern IntPtr CreateBodyFromShapeAndInfo2(IntPtr sim, IntPtr shape, IntPtr constructionInfo); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern bool DeleteCollisionShape2(IntPtr world, IntPtr shape); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern IntPtr CreateBodyFromShape2(IntPtr sim, IntPtr shape, Vector3 pos, Quaternion rot); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern IntPtr CreateBodyWithDefaultMotionState2(IntPtr shape, Vector3 pos, Quaternion rot); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -- cgit v1.1 From d86cbe637943acde05528d0bce6dc61a77257cc0 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Thu, 13 Sep 2012 10:11:25 -0700 Subject: BulletSim: remove unused NeedsMeshing() code from BSScene. --- OpenSim/Region/Physics/BulletSPlugin/BSScene.cs | 116 ------------------------ 1 file changed, 116 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs index eea899f..9c958d5 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs @@ -56,7 +56,6 @@ using OpenMetaverse; // Do attachments need to be handled separately? Need collision events. Do not collide with VolumeDetect // Implement LockAngularMotion // Decide if clearing forces is the right thing to do when setting position (BulletSim::SetObjectTranslation) -// Does NeedsMeshing() really need to exclude all the different shapes? // Remove mesh and Hull stuff. Use mesh passed to bullet and use convexdecom from bullet. // Add PID movement operations. What does ScenePresence.MoveToTarget do? // Check terrain size. 128 or 127? @@ -666,121 +665,6 @@ public class BSScene : PhysicsScene, IPhysicsParameters public override bool IsThreaded { get { return false; } } - /// - /// Routine to figure out if we need to mesh this prim with our mesher - /// - /// - /// true if the prim needs meshing - public bool NeedsMeshing(PrimitiveBaseShape pbs) - { - // most of this is redundant now as the mesher will return null if it cant mesh a prim - // but we still need to check for sculptie meshing being enabled so this is the most - // convenient place to do it for now... - - // int iPropertiesNotSupportedDefault = 0; - - if (pbs.SculptEntry && !ShouldMeshSculptedPrim) - { - // Render sculpties as boxes - return false; - } - - // if it's a standard box or sphere with no cuts, hollows, twist or top shear, return false since Bullet - // can use an internal representation for the prim - if (!ShouldForceSimplePrimMeshing) - { - if ((pbs.ProfileShape == ProfileShape.Square && pbs.PathCurve == (byte)Extrusion.Straight) - || (pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1 - && pbs.Scale.X == pbs.Scale.Y && pbs.Scale.Y == pbs.Scale.Z)) - { - - if (pbs.ProfileBegin == 0 && pbs.ProfileEnd == 0 - && pbs.ProfileHollow == 0 - && pbs.PathTwist == 0 && pbs.PathTwistBegin == 0 - && pbs.PathBegin == 0 && pbs.PathEnd == 0 - && pbs.PathTaperX == 0 && pbs.PathTaperY == 0 - && pbs.PathScaleX == 100 && pbs.PathScaleY == 100 - && pbs.PathShearX == 0 && pbs.PathShearY == 0) - { - return false; - } - } - } - - /* TODO: verify that the mesher will now do all these shapes - if (pbs.ProfileHollow != 0) - iPropertiesNotSupportedDefault++; - - if ((pbs.PathBegin != 0) || pbs.PathEnd != 0) - iPropertiesNotSupportedDefault++; - - if ((pbs.PathTwistBegin != 0) || (pbs.PathTwist != 0)) - iPropertiesNotSupportedDefault++; - - if ((pbs.ProfileBegin != 0) || pbs.ProfileEnd != 0) - iPropertiesNotSupportedDefault++; - - if ((pbs.PathScaleX != 100) || (pbs.PathScaleY != 100)) - iPropertiesNotSupportedDefault++; - - if ((pbs.PathShearX != 0) || (pbs.PathShearY != 0)) - iPropertiesNotSupportedDefault++; - - if (pbs.ProfileShape == ProfileShape.Circle && pbs.PathCurve == (byte)Extrusion.Straight) - iPropertiesNotSupportedDefault++; - - if (pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1 && (pbs.Scale.X != pbs.Scale.Y || pbs.Scale.Y != pbs.Scale.Z || pbs.Scale.Z != pbs.Scale.X)) - iPropertiesNotSupportedDefault++; - - if (pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte) Extrusion.Curve1) - iPropertiesNotSupportedDefault++; - - // test for torus - if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.Square) - { - if (pbs.PathCurve == (byte)Extrusion.Curve1) - { - iPropertiesNotSupportedDefault++; - } - } - else if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.Circle) - { - if (pbs.PathCurve == (byte)Extrusion.Straight) - { - iPropertiesNotSupportedDefault++; - } - // ProfileCurve seems to combine hole shape and profile curve so we need to only compare against the lower 3 bits - else if (pbs.PathCurve == (byte)Extrusion.Curve1) - { - iPropertiesNotSupportedDefault++; - } - } - else if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.HalfCircle) - { - if (pbs.PathCurve == (byte)Extrusion.Curve1 || pbs.PathCurve == (byte)Extrusion.Curve2) - { - iPropertiesNotSupportedDefault++; - } - } - else if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.EquilateralTriangle) - { - if (pbs.PathCurve == (byte)Extrusion.Straight) - { - iPropertiesNotSupportedDefault++; - } - else if (pbs.PathCurve == (byte)Extrusion.Curve1) - { - iPropertiesNotSupportedDefault++; - } - } - if (iPropertiesNotSupportedDefault == 0) - { - return false; - } - */ - return true; - } - // Calls to the PhysicsActors can't directly call into the physics engine // because it might be busy. We delay changes to a known time. // We rely on C#'s closure to save and restore the context for the delegate. -- cgit v1.1 From 7c347f4c5c966848669b979b367e1bc3912621d5 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Thu, 13 Sep 2012 10:11:39 -0700 Subject: BulletSim: Add calls to linkset class when object going static or dynamic. Reset center of mass on an object when going dynamic. --- OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs | 20 ++++++++++++++++++-- OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | 20 ++++++++++++++------ 2 files changed, 32 insertions(+), 8 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs index dc1de6c..3d73887 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs @@ -202,6 +202,24 @@ public class BSLinkset return com; } + // The object is going dynamic (physical). Do any setup necessary + // for a dynamic linkset. + // Return 'true' if any properties updated on the passed object. + // Called at taint-time! + public bool MakeDynamic(BSPhysObject child) + { + return false; + } + + // The object is going static (non-physical). Do any setup necessary + // for a static linkset. + // Return 'true' if any properties updated on the passed object. + // Called at taint-time! + public bool MakeStatic(BSPhysObject child) + { + return false; + } + // When physical properties are changed the linkset needs to recalculate // its internal properties. public void Refresh(BSPhysObject requestor) @@ -255,13 +273,11 @@ public class BSLinkset if (!somethingMissing) { // The root prim takes on the weight of the whole linkset - /* OMV.Vector3 inertia = BulletSimAPI.CalculateLocalInertia2(LinksetRoot.BSShape.Ptr, linksetMass); BulletSimAPI.SetMassProps2(LinksetRoot.BSBody.Ptr, linksetMass, inertia); OMV.Vector3 centerOfMass = ComputeLinksetCenterOfMass(); BulletSimAPI.SetCenterOfMassByPosRot2(LinksetRoot.BSBody.Ptr, centerOfMass, OMV.Quaternion.Identity); BulletSimAPI.UpdateInertiaTensor2(LinksetRoot.BSBody.Ptr); - */ } } return; diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index 481a8db..04b7be5 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs @@ -530,10 +530,14 @@ public sealed class BSPrim : BSPhysObject m_currentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(BSBody.Ptr, CollisionFlags.CF_STATIC_OBJECT); // Stop all movement BulletSimAPI.ClearAllForces2(BSBody.Ptr); + // Center of mass is at the center of the object + BulletSimAPI.SetCenterOfMassByPosRot2(Linkset.LinksetRoot.BSBody.Ptr, _position, _orientation); // Mass is zero which disables a bunch of physics stuff in Bullet BulletSimAPI.SetMassProps2(BSBody.Ptr, 0f, OMV.Vector3.Zero); // There is no inertia in a static object BulletSimAPI.UpdateInertiaTensor2(BSBody.Ptr); + // There can be special things needed for implementing linksets + Linkset.MakeStatic(this); // The activation state is 'sleeping' so Bullet will not try to act on it BulletSimAPI.ForceActivationState2(BSBody.Ptr, ActivationState.ISLAND_SLEEPING); } @@ -543,10 +547,12 @@ public sealed class BSPrim : BSPhysObject m_currentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(BSBody.Ptr, CollisionFlags.CF_STATIC_OBJECT); // A dynamic object has mass IntPtr collisionShapePtr = BulletSimAPI.GetCollisionShape2(BSBody.Ptr); - OMV.Vector3 inertia = BulletSimAPI.CalculateLocalInertia2(collisionShapePtr, _mass); + OMV.Vector3 inertia = BulletSimAPI.CalculateLocalInertia2(collisionShapePtr, Linkset.LinksetMass); BulletSimAPI.SetMassProps2(BSBody.Ptr, _mass, inertia); // Inertia is based on our new mass BulletSimAPI.UpdateInertiaTensor2(BSBody.Ptr); + // There can be special things needed for implementing linksets + Linkset.MakeDynamic(this); // Force activation of the object so Bullet will act on it. BulletSimAPI.Activate2(BSBody.Ptr, true); } @@ -1055,11 +1061,12 @@ public sealed class BSPrim : BSPhysObject }// end CalculateMass #endregion Mass Calculation - // Create the geometry information in Bullet for later use - // The objects needs a hull if it's physical otherwise a mesh is enough - // No locking here because this is done when we know physics is not simulating - // if 'forceRebuild' is true, the geometry is rebuilt. Otherwise a previously built version is used - // Returns 'true' if the geometry was rebuilt + // Create the geometry information in Bullet for later use. + // The objects needs a hull if it's physical otherwise a mesh is enough. + // No locking here because this is done when we know physics is not simulating. + // if 'forceRebuild' is true, the geometry is rebuilt. Otherwise a previously built version is used. + // Returns 'true' if the geometry was rebuilt. + // Called at taint-time! private bool CreateGeom(bool forceRebuild) { bool ret = false; @@ -1128,6 +1135,7 @@ public sealed class BSPrim : BSPhysObject // No locking here because this is done when we know physics is not simulating // Returns 'true' of a mesh was actually rebuild (we could also have one of these specs). + // Called at taint-time! private bool CreateGeomMesh() { // level of detail based on size and type of the object -- cgit v1.1 From f0a098924e8a3f64692de5d3326bfbdfb2b208a2 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Thu, 13 Sep 2012 13:51:28 -0700 Subject: BulletSim: set all linkset objects center of mass to the whole linkset's center of mass --- OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs index 3d73887..7e784eb 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs @@ -204,11 +204,14 @@ public class BSLinkset // The object is going dynamic (physical). Do any setup necessary // for a dynamic linkset. + // Only the state of the passed object can be modified. The rest of the linkset + // has not yet been fully constructed. // Return 'true' if any properties updated on the passed object. // Called at taint-time! public bool MakeDynamic(BSPhysObject child) { - return false; + bool ret = false; + return ret; } // The object is going static (non-physical). Do any setup necessary @@ -217,6 +220,7 @@ public class BSLinkset // Called at taint-time! public bool MakeStatic(BSPhysObject child) { + // What is done for each object in BSPrim is what we want. return false; } @@ -269,15 +273,24 @@ public class BSLinkset } } - // If the whole linkset is not here, doesn't make sense to recompute the root prim now. + // If the whole linkset is not here, doesn't make sense to recompute linkset wide values if (!somethingMissing) { + // If this is a multiple object linkset, set everybody's center of mass to the set's center of mass + OMV.Vector3 centerOfMass = ComputeLinksetCenterOfMass(); + BulletSimAPI.SetCenterOfMassByPosRot2(LinksetRoot.BSBody.Ptr, centerOfMass, OMV.Quaternion.Identity); + foreach (BSPhysObject child in m_children) + { + BulletSimAPI.SetCenterOfMassByPosRot2(child.BSBody.Ptr, centerOfMass, OMV.Quaternion.Identity); + } + /* // The root prim takes on the weight of the whole linkset OMV.Vector3 inertia = BulletSimAPI.CalculateLocalInertia2(LinksetRoot.BSShape.Ptr, linksetMass); BulletSimAPI.SetMassProps2(LinksetRoot.BSBody.Ptr, linksetMass, inertia); OMV.Vector3 centerOfMass = ComputeLinksetCenterOfMass(); BulletSimAPI.SetCenterOfMassByPosRot2(LinksetRoot.BSBody.Ptr, centerOfMass, OMV.Quaternion.Identity); BulletSimAPI.UpdateInertiaTensor2(LinksetRoot.BSBody.Ptr); + */ } } return; -- cgit v1.1 From 6632eb7c051e2638ea1c58c2876e7d6825398556 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Thu, 13 Sep 2012 13:51:42 -0700 Subject: BulletSim: Remove calculation and passing of unused collied object type. Fix collision code to properly sense mega-region children regions as terrain. When setting an object physical, reset all the physical properties (friction, ...). --- .../Region/Physics/BulletSPlugin/BSCharacter.cs | 8 +++---- .../Region/Physics/BulletSPlugin/BSPhysObject.cs | 2 +- OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | 28 +++++++++++++++++----- OpenSim/Region/Physics/BulletSPlugin/BSScene.cs | 26 ++++++++------------ 4 files changed, 36 insertions(+), 28 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs index a9b1365..526dbad 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs @@ -529,22 +529,20 @@ public class BSCharacter : BSPhysObject // The collision, if it should be reported to the character, is placed in a collection // that will later be sent to the simulator when SendCollisions() is called. CollisionEventUpdate collisionCollection = null; - public override bool Collide(uint collidingWith, BSPhysObject collidee, ActorTypes type, Vector3 contactPoint, Vector3 contactNormal, float pentrationDepth) + public override bool Collide(uint collidingWith, BSPhysObject collidee, Vector3 contactPoint, Vector3 contactNormal, float pentrationDepth) { - // m_log.DebugFormat("{0}: Collide: ms={1}, id={2}, with={3}", LogHeader, _subscribedEventsMs, LocalID, collidingWith); - bool ret = false; // The following makes IsColliding() and IsCollidingGround() work _collidingStep = Scene.SimulationStep; - if (collidingWith == BSScene.TERRAIN_ID || collidingWith == BSScene.GROUNDPLANE_ID) + if (collidingWith <= Scene.TerrainManager.HighestTerrainID) { _collidingGroundStep = Scene.SimulationStep; } // DetailLog("{0},BSCharacter.Collison,call,with={1}", LocalID, collidingWith); // throttle collisions to the rate specified in the subscription - if (_subscribedEventsMs != 0) { + if (SubscribedEvents()) { int nowTime = Scene.SimulationNowTime; if (nowTime >= _nextCollisionOkTime) { _nextCollisionOkTime = nowTime + _subscribedEventsMs; diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs index 969c53e..3fe71e1 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs @@ -41,7 +41,7 @@ public abstract class BSPhysObject : PhysicsActor { public abstract BSLinkset Linkset { get; set; } - public abstract bool Collide(uint collidingWith, BSPhysObject collidee, ActorTypes type, + public abstract bool Collide(uint collidingWith, BSPhysObject collidee, OMV.Vector3 contactPoint, OMV.Vector3 contactNormal, float pentrationDepth); public abstract void SendCollisions(); diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index 04b7be5..6827be0 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs @@ -545,14 +545,31 @@ public sealed class BSPrim : BSPhysObject { // Not a Bullet static object m_currentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(BSBody.Ptr, CollisionFlags.CF_STATIC_OBJECT); + + // Set various physical properties so internal things will get computed correctly as they are set + BulletSimAPI.SetFriction2(BSBody.Ptr, Scene.Params.defaultFriction); + BulletSimAPI.SetRestitution2(BSBody.Ptr, Scene.Params.defaultRestitution); + // per http://www.bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=3382 + BulletSimAPI.SetInterpolationLinearVelocity2(BSBody.Ptr, OMV.Vector3.Zero); + BulletSimAPI.SetInterpolationAngularVelocity2(BSBody.Ptr, OMV.Vector3.Zero); + BulletSimAPI.SetInterpolationVelocity2(BSBody.Ptr, OMV.Vector3.Zero, OMV.Vector3.Zero); + // A dynamic object has mass IntPtr collisionShapePtr = BulletSimAPI.GetCollisionShape2(BSBody.Ptr); OMV.Vector3 inertia = BulletSimAPI.CalculateLocalInertia2(collisionShapePtr, Linkset.LinksetMass); BulletSimAPI.SetMassProps2(BSBody.Ptr, _mass, inertia); // Inertia is based on our new mass BulletSimAPI.UpdateInertiaTensor2(BSBody.Ptr); + + // Various values for simulation limits + BulletSimAPI.SetDamping2(BSBody.Ptr, Scene.Params.linearDamping, Scene.Params.angularDamping); + BulletSimAPI.SetDeactivationTime2(BSBody.Ptr, Scene.Params.deactivationTime); + BulletSimAPI.SetSleepingThresholds2(BSBody.Ptr, Scene.Params.linearSleepingThreshold, Scene.Params.angularSleepingThreshold); + BulletSimAPI.SetContactProcessingThreshold2(BSBody.Ptr, Scene.Params.contactProcessingThreshold); + // There can be special things needed for implementing linksets Linkset.MakeDynamic(this); + // Force activation of the object so Bullet will act on it. BulletSimAPI.Activate2(BSBody.Ptr, true); } @@ -1475,16 +1492,15 @@ public sealed class BSPrim : BSPhysObject // I've collided with something // Called at taint time from within the Step() function CollisionEventUpdate collisionCollection; - public override bool Collide(uint collidingWith, BSPhysObject collidee, ActorTypes type, OMV.Vector3 contactPoint, OMV.Vector3 contactNormal, float pentrationDepth) + public override bool Collide(uint collidingWith, BSPhysObject collidee, OMV.Vector3 contactPoint, OMV.Vector3 contactNormal, float pentrationDepth) { - // m_log.DebugFormat("{0}: Collide: ms={1}, id={2}, with={3}", LogHeader, _subscribedEventsMs, LocalID, collidingWith); bool ret = false; // The following lines make IsColliding() and IsCollidingGround() work - _collidingStep = _scene.SimulationStep; - if (collidingWith == BSScene.TERRAIN_ID || collidingWith == BSScene.GROUNDPLANE_ID) + _collidingStep = Scene.SimulationStep; + if (collidingWith <= Scene.TerrainManager.HighestTerrainID) { - _collidingGroundStep = _scene.SimulationStep; + _collidingGroundStep = Scene.SimulationStep; } // DetailLog("{0},BSPrim.Collison,call,with={1}", LocalID, collidingWith); @@ -1498,7 +1514,7 @@ public sealed class BSPrim : BSPhysObject // if someone has subscribed for collision events.... if (SubscribedEvents()) { // throttle the collisions to the number of milliseconds specified in the subscription - int nowTime = _scene.SimulationNowTime; + int nowTime = Scene.SimulationNowTime; if (nowTime >= _nextCollisionOkTime) { _nextCollisionOkTime = nowTime + _subscribedEventsMs; diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs index 9c958d5..c38867f 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs @@ -583,27 +583,21 @@ public class BSScene : PhysicsScene, IPhysicsParameters return; // don't send collisions to the terrain } - BSPhysObject collider = PhysObjects[localID]; - // TODO: as of this code, terrain was not in the physical object list. - // When BSTerrain is created and it will be in the list, we can remove - // the possibility that it's not there and just fetch the collidee. - BSPhysObject collidee = null; - - ActorTypes type = ActorTypes.Prim; - if (collidingWith <= TerrainManager.HighestTerrainID) + BSPhysObject collider; + if (!PhysObjects.TryGetValue(localID, out collider)) { - type = ActorTypes.Ground; - } - else - { - collidee = PhysObjects[collidingWith]; - if (collidee is BSCharacter) - type = ActorTypes.Agent; + // If the object that is colliding cannot be found, just ignore the collision. + return; } + // The terrain is not in the physical object list so 'collidee' + // can be null when Collide() is called. + BSPhysObject collidee = null; + PhysObjects.TryGetValue(collidingWith, out collidee); + // DetailLog("{0},BSScene.SendCollision,collide,id={1},with={2}", DetailLogZero, localID, collidingWith); - if (collider.Collide(collidingWith, collidee, type, collidePoint, collideNormal, penetration)) + if (collider.Collide(collidingWith, collidee, collidePoint, collideNormal, penetration)) { // If a collision was posted, remember to send it to the simulator m_objectsWithCollisions.Add(collider); -- cgit v1.1 From dcb94b8a242dff0f3a33f084565af49d6582f663 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Fri, 14 Sep 2012 11:11:43 -0700 Subject: BulletSim: remove timeStep parameter from calls for vehicle parameter setting. There is no reason these should be using the simulation time interval for parameter calculation. --- OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs | 9 +++------ OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | 6 +++--- 2 files changed, 6 insertions(+), 9 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs index 098fea7..5f62b12 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs @@ -131,7 +131,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin m_type = Vehicle.TYPE_NONE; } - internal void ProcessFloatVehicleParam(Vehicle pParam, float pValue, float timestep) + internal void ProcessFloatVehicleParam(Vehicle pParam, float pValue) { VDetailLog("{0},ProcessFloatVehicleParam,param={1},val={2}", m_prim.LocalID, pParam, pValue); switch (pParam) @@ -230,7 +230,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin } }//end ProcessFloatVehicleParam - internal void ProcessVectorVehicleParam(Vehicle pParam, Vector3 pValue, float timestep) + internal void ProcessVectorVehicleParam(Vehicle pParam, Vector3 pValue) { VDetailLog("{0},ProcessVectorVehicleParam,param={1},val={2}", m_prim.LocalID, pParam, pValue); switch (pParam) @@ -299,7 +299,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin } }//end ProcessVehicleFlags - internal void ProcessTypeChange(Vehicle pType, float stepSize) + internal void ProcessTypeChange(Vehicle pType) { VDetailLog("{0},ProcessTypeChange,type={1}", m_prim.LocalID, pType); // Set Defaults For Type @@ -537,9 +537,6 @@ namespace OpenSim.Region.Physics.BulletSPlugin // Add the various forces into m_dir which will be our new direction vector (velocity) // add Gravity and Buoyancy - // KF: So far I have found no good method to combine a script-requested - // .Z velocity and gravity. Therefore only 0g will used script-requested - // .Z velocity. >0g (m_VehicleBuoyancy < 1) will used modified gravity only. // There is some gravity, make a gravity force vector that is applied after object velocity. // m_VehicleBuoyancy: -1=2g; 0=1g; 1=0g; Vector3 grav = m_prim.Scene.DefaultGravity * (m_prim.Mass * (1f - m_VehicleBuoyancy)); diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index 6827be0..d97231c 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs @@ -346,7 +346,7 @@ public sealed class BSPrim : BSPhysObject { // Done at taint time so we're sure the physics engine is not using the variables // Vehicle code changes the parameters for this vehicle type. - _vehicle.ProcessTypeChange(type, Scene.LastSimulatedTimestep); + _vehicle.ProcessTypeChange(type); // Tell the scene about the vehicle so it will get processing each frame. _scene.VehicleInSceneTypeChanged(this, type); }); @@ -356,14 +356,14 @@ public sealed class BSPrim : BSPhysObject { _scene.TaintedObject("BSPrim.VehicleFloatParam", delegate() { - _vehicle.ProcessFloatVehicleParam((Vehicle)param, value, _scene.LastSimulatedTimestep); + _vehicle.ProcessFloatVehicleParam((Vehicle)param, value); }); } public override void VehicleVectorParam(int param, OMV.Vector3 value) { _scene.TaintedObject("BSPrim.VehicleVectorParam", delegate() { - _vehicle.ProcessVectorVehicleParam((Vehicle)param, value, _scene.LastSimulatedTimestep); + _vehicle.ProcessVectorVehicleParam((Vehicle)param, value); }); } public override void VehicleRotationParam(int param, OMV.Quaternion rotation) -- cgit v1.1 From f35bd6eb7d5b0eb1a6d385f5f1d0147acfc3c8ef Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Fri, 14 Sep 2012 11:12:23 -0700 Subject: BulletSim: another attempt at computing physics FPS correctly. --- OpenSim/Region/Physics/BulletSPlugin/BSScene.cs | 29 +++++-------------------- 1 file changed, 6 insertions(+), 23 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs index c38867f..52997dd 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs @@ -110,11 +110,6 @@ public class BSScene : PhysicsScene, IPhysicsParameters private long m_simulationStep = 0; public long SimulationStep { get { return m_simulationStep; } } - // The length of the last timestep we were asked to simulate. - // This is used by the vehicle code. Since the vehicle code is called - // once per simulation step, its constants need to be scaled by this. - public float LastSimulatedTimestep { get; private set; } - // A value of the time now so all the collision and update routines do not have to get their own // Set to 'now' just before all the prims and actors are called for collisions and updates public int SimulationNowTime { get; private set; } @@ -469,12 +464,8 @@ public class BSScene : PhysicsScene, IPhysicsParameters int collidersCount = 0; IntPtr collidersPtr; - LastSimulatedTimestep = timeStep; - // prevent simulation until we've been initialized - if (!m_initialized) return 10.0f; - - int simulateStartTime = Util.EnvironmentTickCount(); + if (!m_initialized) return 5.0f; // update the prim states while we know the physics engine is not busy int numTaints = _taintedObjects.Count; @@ -514,7 +505,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters // This is a kludge to get avatar movement updates. // ODE sends collisions for avatars even if there are have been no collisions. This updates // avatar animations and stuff. - // If you fix avatar animation updates, remove this overhead and let collisions happen. + // If you fix avatar animation updates, remove this overhead and let normal collision processing happen. m_objectsWithCollisions = new HashSet(m_avatarsWithCollisions); // If there were collisions, process them by sending the event to the prim. @@ -561,18 +552,10 @@ public class BSScene : PhysicsScene, IPhysicsParameters } } - // this is a waste since the outside routine also calcuates the physics simulation - // period. TODO: There should be a way of computing physics frames from simulator computation. - // long simulateTotalTime = Util.EnvironmentTickCountSubtract(simulateStartTime); - // return (timeStep * (float)simulateTotalTime); - - // TODO: FIX THIS: fps calculation possibly wrong. - // This calculation says 1/timeStep is the ideal frame rate. Any time added to - // that by the physics simulation gives a slower frame rate. - long totalSimulationTime = Util.EnvironmentTickCountSubtract(simulateStartTime); - if (totalSimulationTime >= timeStep) - return 0; - return 1f / (timeStep + totalSimulationTime); + // The physics engine returns the number of milliseconds it simulated this call. + // These are summed and normalized to one second and divided by 1000 to give the reported physics FPS. + // Since Bullet normally does 5 or 6 substeps, this will normally sum to about 60 FPS. + return numSubSteps * m_fixedTimeStep; } // Something has collided -- cgit v1.1 From 1826b2b18e8d82a91ca34787e17cf4ef0d1f46a6 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Fri, 14 Sep 2012 11:13:05 -0700 Subject: BulletSim: add the debugging routine DumpRigidBody2() to API2. --- OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs index 087c61b..9221cdb 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs @@ -558,9 +558,6 @@ public static extern void DestroyObject2(IntPtr sim, IntPtr obj); // ===================================================================================== // Terrain creation and helper routines [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void DumpMapInfo(IntPtr sim, IntPtr manInfo); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern IntPtr CreateHeightMapInfo2(IntPtr sim, uint id, Vector3 minCoords, Vector3 maxCoords, [MarshalAs(UnmanagedType.LPArray)] float[] heightMap, float collisionMargin); @@ -1023,6 +1020,12 @@ public static extern void SetCollisionFilterMask(IntPtr shape, uint filter, uint // ===================================================================================== // Debugging [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern void DumpRigidBody2(IntPtr sim, IntPtr collisionObject); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern void DumpMapInfo2(IntPtr sim, IntPtr manInfo); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern void DumpPhysicsStatistics2(IntPtr sim); } -- cgit v1.1 From c77be802d2879c0504438905359c1b865a92d3a1 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Sat, 15 Sep 2012 15:23:54 -0700 Subject: BulletSim: some debugging prints in BSPrim for tracking changes in linkset children. --- OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index d97231c..26a581f 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs @@ -1476,12 +1476,14 @@ public sealed class BSPrim : BSPhysObject DetailLog("{0},BSPrim.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5}", LocalID, _position, _orientation, _velocity, _acceleration, _rotationalVelocity); + // BulletSimAPI.DumpRigidBody2(Scene.World.Ptr, BSBody.Ptr); + base.RequestPhysicsterseUpdate(); } /* else { - // For debugging, we also report the movement of children + // For debugging, we can also report the movement of children DetailLog("{0},BSPrim.UpdateProperties,child,pos={1},orient={2},vel={3},accel={4},rotVel={5}", LocalID, entprop.Position, entprop.Rotation, entprop.Velocity, entprop.Acceleration, entprop.RotationalVelocity); -- cgit v1.1 From b602b476adafe8e6eab9ec257db029a3d05db224 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Sat, 15 Sep 2012 15:36:13 -0700 Subject: BulletSim: update DLLs and SOs and remove some debugging code. --- OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs index 5f62b12..61006f0 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs @@ -475,7 +475,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin frcount = 0; MoveLinear(pTimestep); - // MoveAngular(pTimestep); + MoveAngular(pTimestep); LimitRotation(pTimestep); // remember the position so next step we can limit absolute movement effects -- cgit v1.1 From de69a24574786f7517e8dc3be62e413f9e0fae22 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Sat, 15 Sep 2012 19:33:51 -0700 Subject: More on HG2.0: added the possibility of controlling the appearance that avies use to visit other grids. Not as good as I wanted, but good enough. Unfortunately we can't switch the appearance from under the avie without getting into a lot of weirdnesses because appearance is viewer-controlled. So instead, when this control is on, I'm disallowing HG-TP unless the user is wearing an allowed HG appearance -- the user gets a warning and needs to switch appearance. WARNING: I'm still not committing the config vars because this is still not ready for ppl to test. --- .../EntityTransfer/EntityTransferModule.cs | 19 ++- .../EntityTransfer/HGEntityTransferModule.cs | 154 +++++++++++++++++++++ 2 files changed, 171 insertions(+), 2 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs index c63b0a4..b51570f 100644 --- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs +++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs @@ -323,6 +323,14 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer return; } + // Validate assorted conditions + string reason = string.Empty; + if (!ValidateGenericConditions(sp, reg, finalDestination, teleportFlags, out reason)) + { + sp.ControllingClient.SendTeleportFailed(reason); + return; + } + // // This is it // @@ -354,6 +362,13 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer } } + // Nothing to validate here + protected virtual bool ValidateGenericConditions(ScenePresence sp, GridRegion reg, GridRegion finalDestination, uint teleportFlags, out string reason) + { + reason = String.Empty; + return true; + } + /// /// Determines whether this instance is within the max transfer distance. /// @@ -568,7 +583,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer //sp.ControllingClient.SendTeleportProgress(teleportFlags, "Updating agent..."); - if (!UpdateAgent(reg, finalDestination, agent)) + if (!UpdateAgent(reg, finalDestination, agent, sp)) { // Region doesn't take it m_log.WarnFormat( @@ -695,7 +710,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer return success; } - protected virtual bool UpdateAgent(GridRegion reg, GridRegion finalDestination, AgentData agent) + protected virtual bool UpdateAgent(GridRegion reg, GridRegion finalDestination, AgentData agent, ScenePresence sp) { return Scene.SimulationService.UpdateAgent(finalDestination, agent); } diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs index 08863c2..f3c5873 100644 --- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs +++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs @@ -54,6 +54,47 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer private GatekeeperServiceConnector m_GatekeeperConnector; + protected bool m_RestrictAppearanceAbroad; + protected string m_AccountName; + protected AvatarAppearance m_ExportedAppearance; + + protected AvatarAppearance ExportedAppearance + { + get + { + if (m_ExportedAppearance != null) + return m_ExportedAppearance; + + string[] parts = m_AccountName.Split(); + if (parts.Length != 2) + { + m_log.WarnFormat("[HG ENTITY TRANSFER MODULE]: Wrong user account name format {0}. Specify 'First Last'", m_AccountName); + return null; + } + UserAccount account = Scene.UserAccountService.GetUserAccount(UUID.Zero, parts[0], parts[1]); + if (account == null) + { + m_log.WarnFormat("[HG ENTITY TRANSFER MODULE]: Unknown account {0}", m_AccountName); + return null; + } + m_ExportedAppearance = Scene.AvatarService.GetAppearance(account.PrincipalID); + if (m_ExportedAppearance != null) + m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Successfully retrieved appearance for {0}", m_AccountName); + + foreach (AvatarAttachment att in m_ExportedAppearance.GetAttachments()) + { + InventoryItemBase item = new InventoryItemBase(att.ItemID, account.PrincipalID); + item = Scene.InventoryService.GetItem(item); + if (item != null) + m_ExportedAppearance.SetAttachment(att.AttachPoint, att.ItemID, item.AssetID); + else + m_log.WarnFormat("[HG ENTITY TRANSFER MODULE]: Unable to retrieve item {0} from inventory", att.ItemID); + } + return m_ExportedAppearance; + } + } + + #region ISharedRegionModule public override string Name @@ -72,8 +113,18 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer { IConfig transferConfig = source.Configs["EntityTransfer"]; if (transferConfig != null) + { m_levelHGTeleport = transferConfig.GetInt("LevelHGTeleport", 0); + m_RestrictAppearanceAbroad = transferConfig.GetBoolean("RestrictAppearanceAbroad", false); + if (m_RestrictAppearanceAbroad) + { + m_AccountName = transferConfig.GetString("AccountForAppearance", string.Empty); + if (m_AccountName == string.Empty) + m_log.WarnFormat("[HG ENTITY TRANSFER MODULE]: RestrictAppearanceAbroad is on, but no account has been given for avatar appearance!"); + } + } + InitialiseCommon(source); m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: {0} enabled.", Name); } @@ -195,6 +246,109 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer return base.CreateAgent(sp, reg, finalDestination, agentCircuit, teleportFlags, out reason, out logout); } + protected override bool ValidateGenericConditions(ScenePresence sp, GridRegion reg, GridRegion finalDestination, uint teleportFlags, out string reason) + { + reason = "Please wear your grid's allowed appearance before teleporting to another grid"; + if (!m_RestrictAppearanceAbroad) + return true; + + // The rest is only needed for controlling appearance + + int flags = Scene.GridService.GetRegionFlags(Scene.RegionInfo.ScopeID, reg.RegionID); + if (flags == -1 /* no region in DB */ || (flags & (int)OpenSim.Data.RegionFlags.Hyperlink) != 0) + { + // this user is going to another grid + if (Scene.UserManagementModule.IsLocalGridUser(sp.UUID)) + { + m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: RestrictAppearanceAbroad is ON. Checking generic appearance"); + + // Check wearables + for (int i = 0; i < AvatarWearable.MAX_WEARABLES; i++) + { + for (int j = 0; j < sp.Appearance.Wearables[i].Count; j++) + { + if (sp.Appearance.Wearables[i] == null) + continue; + + if (ExportedAppearance.Wearables[i] == null) + { + m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Wearable not allowed to go outside {0}", i); + return false; + } + + if (sp.Appearance.Wearables[i][j].AssetID != ExportedAppearance.Wearables[i][j].AssetID) + { + m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Wearable not allowed to go outside {0}", i); + return false; + } + } + } + + // Check attachments + + foreach (AvatarAttachment att in sp.Appearance.GetAttachments()) + { + bool found = false; + foreach (AvatarAttachment att2 in ExportedAppearance.GetAttachments()) + { + if (att2.AssetID == att.AssetID) + { + found = true; + break; + } + } + if (!found) + { + m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Attachment not allowed to go outside {0}", att.AttachPoint); + return false; + } + } + } + } + + reason = string.Empty; + return true; + } + + + //protected override bool UpdateAgent(GridRegion reg, GridRegion finalDestination, AgentData agentData, ScenePresence sp) + //{ + // int flags = Scene.GridService.GetRegionFlags(Scene.RegionInfo.ScopeID, reg.RegionID); + // if (flags == -1 /* no region in DB */ || (flags & (int)OpenSim.Data.RegionFlags.Hyperlink) != 0) + // { + // // this user is going to another grid + // if (m_RestrictAppearanceAbroad && Scene.UserManagementModule.IsLocalGridUser(agentData.AgentID)) + // { + // // We need to strip the agent off its appearance + // m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: RestrictAppearanceAbroad is ON. Sending generic appearance"); + + // // Delete existing npc attachments + // Scene.AttachmentsModule.DeleteAttachmentsFromScene(sp, false); + + // // XXX: We can't just use IAvatarFactoryModule.SetAppearance() yet since it doesn't transfer attachments + // AvatarAppearance newAppearance = new AvatarAppearance(ExportedAppearance, true); + // sp.Appearance = newAppearance; + + // // Rez needed npc attachments + // Scene.AttachmentsModule.RezAttachments(sp); + + + // IAvatarFactoryModule module = Scene.RequestModuleInterface(); + // //module.SendAppearance(sp.UUID); + // module.RequestRebake(sp, false); + + // Scene.AttachmentsModule.CopyAttachments(sp, agentData); + // agentData.Appearance = sp.Appearance; + // } + // } + + // foreach (AvatarAttachment a in agentData.Appearance.GetAttachments()) + // m_log.DebugFormat("[XXX]: {0}-{1}", a.ItemID, a.AssetID); + + + // return base.UpdateAgent(reg, finalDestination, agentData, sp); + //} + public override void TeleportHome(UUID id, IClientAPI client) { m_log.DebugFormat( -- cgit v1.1 From 380962d3594b9a45625889975609ebf5dc4b3683 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Sun, 16 Sep 2012 16:45:57 -0700 Subject: HG2.0: Generalized the allowed HG appearances to be more than 1. --- .../EntityTransfer/HGEntityTransferModule.cs | 90 ++++++++++++++-------- 1 file changed, 59 insertions(+), 31 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs index f3c5873..0b386d3 100644 --- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs +++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs @@ -56,41 +56,54 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer protected bool m_RestrictAppearanceAbroad; protected string m_AccountName; - protected AvatarAppearance m_ExportedAppearance; + protected List m_ExportedAppearances; + protected List m_Attachs; - protected AvatarAppearance ExportedAppearance + protected List ExportedAppearance { get { - if (m_ExportedAppearance != null) - return m_ExportedAppearance; + if (m_ExportedAppearances != null) + return m_ExportedAppearances; - string[] parts = m_AccountName.Split(); - if (parts.Length != 2) - { - m_log.WarnFormat("[HG ENTITY TRANSFER MODULE]: Wrong user account name format {0}. Specify 'First Last'", m_AccountName); - return null; - } - UserAccount account = Scene.UserAccountService.GetUserAccount(UUID.Zero, parts[0], parts[1]); - if (account == null) - { - m_log.WarnFormat("[HG ENTITY TRANSFER MODULE]: Unknown account {0}", m_AccountName); - return null; - } - m_ExportedAppearance = Scene.AvatarService.GetAppearance(account.PrincipalID); - if (m_ExportedAppearance != null) - m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Successfully retrieved appearance for {0}", m_AccountName); + m_ExportedAppearances = new List(); + m_Attachs = new List(); + + string[] names = m_AccountName.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries); - foreach (AvatarAttachment att in m_ExportedAppearance.GetAttachments()) + foreach (string name in names) { - InventoryItemBase item = new InventoryItemBase(att.ItemID, account.PrincipalID); - item = Scene.InventoryService.GetItem(item); - if (item != null) - m_ExportedAppearance.SetAttachment(att.AttachPoint, att.ItemID, item.AssetID); - else - m_log.WarnFormat("[HG ENTITY TRANSFER MODULE]: Unable to retrieve item {0} from inventory", att.ItemID); + string[] parts = name.Trim().Split(); + if (parts.Length != 2) + { + m_log.WarnFormat("[HG ENTITY TRANSFER MODULE]: Wrong user account name format {0}. Specify 'First Last'", name); + return null; + } + UserAccount account = Scene.UserAccountService.GetUserAccount(UUID.Zero, parts[0], parts[1]); + if (account == null) + { + m_log.WarnFormat("[HG ENTITY TRANSFER MODULE]: Unknown account {0}", m_AccountName); + return null; + } + AvatarAppearance a = Scene.AvatarService.GetAppearance(account.PrincipalID); + if (a != null) + m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Successfully retrieved appearance for {0}", name); + + foreach (AvatarAttachment att in a.GetAttachments()) + { + InventoryItemBase item = new InventoryItemBase(att.ItemID, account.PrincipalID); + item = Scene.InventoryService.GetItem(item); + if (item != null) + a.SetAttachment(att.AttachPoint, att.ItemID, item.AssetID); + else + m_log.WarnFormat("[HG ENTITY TRANSFER MODULE]: Unable to retrieve item {0} from inventory {1}", att.ItemID, name); + } + + m_ExportedAppearances.Add(a); + m_Attachs.AddRange(a.GetAttachments()); } - return m_ExportedAppearance; + + return m_ExportedAppearances; } } @@ -270,13 +283,29 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer if (sp.Appearance.Wearables[i] == null) continue; - if (ExportedAppearance.Wearables[i] == null) + bool found = false; + foreach (AvatarAppearance a in ExportedAppearance) + if (a.Wearables[i] != null) + { + found = true; + break; + } + + if (!found) { m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Wearable not allowed to go outside {0}", i); return false; } - if (sp.Appearance.Wearables[i][j].AssetID != ExportedAppearance.Wearables[i][j].AssetID) + found = false; + foreach (AvatarAppearance a in ExportedAppearance) + if (sp.Appearance.Wearables[i][j].AssetID == a.Wearables[i][j].AssetID) + { + found = true; + break; + } + + if (!found) { m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Wearable not allowed to go outside {0}", i); return false; @@ -285,11 +314,10 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer } // Check attachments - foreach (AvatarAttachment att in sp.Appearance.GetAttachments()) { bool found = false; - foreach (AvatarAttachment att2 in ExportedAppearance.GetAttachments()) + foreach (AvatarAttachment att2 in m_Attachs) { if (att2.AssetID == att.AssetID) { -- cgit v1.1 From 5e626ce55de0b12797f2da7819e15747721779e6 Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Mon, 17 Sep 2012 13:02:56 +0100 Subject: script invocations cannot have void return type --- .../Avatar/Attachments/TempAttachmentsModule.cs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/OptionalModules/Avatar/Attachments/TempAttachmentsModule.cs b/OpenSim/Region/OptionalModules/Avatar/Attachments/TempAttachmentsModule.cs index cb89cd1..d7fb272 100644 --- a/OpenSim/Region/OptionalModules/Avatar/Attachments/TempAttachmentsModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/Attachments/TempAttachmentsModule.cs @@ -130,37 +130,37 @@ namespace OpenSim.Region.OptionalModules.Avatar.Attachments SendConsoleOutput(agentID, String.Format("auto_grant_attach_perms set to {0}", val)); } - private void llAttachToAvatarTemp(UUID host, UUID script, int attachmentPoint) + private int llAttachToAvatarTemp(UUID host, UUID script, int attachmentPoint) { SceneObjectPart hostPart = m_scene.GetSceneObjectPart(host); if (hostPart == null) - return; + return 0; if (hostPart.ParentGroup.IsAttachment) - return; + return 0; IAttachmentsModule attachmentsModule = m_scene.RequestModuleInterface(); if (attachmentsModule == null) - return; + return 0; TaskInventoryItem item = hostPart.Inventory.GetInventoryItem(script); if (item == null) - return; + return 0; if ((item.PermsMask & 32) == 0) // PERMISSION_ATTACH - return; + return 0; ScenePresence target; if (!m_scene.TryGetScenePresence(item.PermsGranter, out target)) - return; + return 0; if (target.UUID != hostPart.ParentGroup.OwnerID) { uint effectivePerms = hostPart.ParentGroup.GetEffectivePermissions(); if ((effectivePerms & (uint)PermissionMask.Transfer) == 0) - return; + return 0; hostPart.ParentGroup.SetOwnerId(target.UUID); hostPart.ParentGroup.SetRootPartOwner(hostPart.ParentGroup.RootPart, target.UUID, target.ControllingClient.ActiveGroupId); @@ -183,7 +183,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Attachments hostPart.ParentGroup.RootPart.ScheduleFullUpdate(); } - attachmentsModule.AttachObject(target, hostPart.ParentGroup, (uint)attachmentPoint, false, true); + return attachmentsModule.AttachObject(target, hostPart.ParentGroup, (uint)attachmentPoint, false, true) ? 1 : 0; } } } -- cgit v1.1 From c7948a669a200af1f18b125c22467f02ecb4784d Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Mon, 17 Sep 2012 13:03:34 +0100 Subject: preventing a null reference exception from being thrown Signed-off-by: Melanie --- OpenSim/Region/Framework/Scenes/Scene.cs | 3 +++ 1 file changed, 3 insertions(+) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index c2c0b96..9c3c53d 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -5527,6 +5527,9 @@ namespace OpenSim.Region.Framework.Scenes public string GetExtraSetting(string name) { + if (m_extraSettings == null) + return String.Empty; + string val; if (!m_extraSettings.TryGetValue(name, out val)) -- cgit v1.1 From f9721573d956092c2d993ee41654f3f5e160401c Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Fri, 14 Sep 2012 13:17:07 +0100 Subject: Implementing ability to register script constants and invocations on a region module automatically --- .../Framework/Interfaces/IScriptModuleComms.cs | 23 ++++++++++++++++ .../ScriptModuleComms/ScriptModuleCommsModule.cs | 31 ++++++++++++++++++++++ 2 files changed, 54 insertions(+) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Framework/Interfaces/IScriptModuleComms.cs b/OpenSim/Region/Framework/Interfaces/IScriptModuleComms.cs index dae7c00..277c9ed 100644 --- a/OpenSim/Region/Framework/Interfaces/IScriptModuleComms.cs +++ b/OpenSim/Region/Framework/Interfaces/IScriptModuleComms.cs @@ -75,6 +75,14 @@ namespace OpenSim.Region.Framework.Interfaces void RegisterScriptInvocation(Type target, string[] methods); /// + /// Automatically register script invocations by checking for methods + /// with . Should only check + /// public methods. + /// + /// + void RegisterScriptInvocations(IRegionModuleBase target); + + /// /// Returns an array of all registered script calls /// /// @@ -98,9 +106,24 @@ namespace OpenSim.Region.Framework.Interfaces /// For constants void RegisterConstant(string cname, object value); + + /// + /// Automatically register all constants on a region module by + /// checking for fields with . + /// + /// + void RegisterConstants(IRegionModuleBase target); object LookupModConstant(string cname); // For use ONLY by the script API void RaiseEvent(UUID script, string id, string module, string command, string key); } + + [AttributeUsage(AttributeTargets.Method)] + public class ScriptInvocationAttribute : Attribute + { } + + [AttributeUsage(AttributeTargets.Field)] + public class ScriptConstantAttribute : Attribute + { } } diff --git a/OpenSim/Region/OptionalModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs b/OpenSim/Region/OptionalModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs index 23cc633..98396ff 100644 --- a/OpenSim/Region/OptionalModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs +++ b/OpenSim/Region/OptionalModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs @@ -211,6 +211,23 @@ namespace OpenSim.Region.OptionalModules.Scripting.ScriptModuleComms RegisterScriptInvocation(target, mi); } } + + public void RegisterScriptInvocations(IRegionModuleBase target) + { + foreach(MethodInfo method in target.GetType().GetMethods( + BindingFlags.Public | BindingFlags.Instance | + BindingFlags.Static)) + { + if(method.GetCustomAttributes( + typeof(ScriptInvocationAttribute), true).Any()) + { + if(method.IsStatic) + RegisterScriptInvocation(target.GetType(), method); + else + RegisterScriptInvocation(target, method); + } + } + } public Delegate[] GetScriptInvocationList() { @@ -313,6 +330,20 @@ namespace OpenSim.Region.OptionalModules.Scripting.ScriptModuleComms } } + public void RegisterConstants(IRegionModuleBase target) + { + foreach (FieldInfo field in target.GetType().GetFields( + BindingFlags.Public | BindingFlags.Static | + BindingFlags.Instance)) + { + if (field.GetCustomAttributes( + typeof(ScriptConstantAttribute), true).Any()) + { + RegisterConstant(field.Name, field.GetValue(target)); + } + } + } + /// /// Operation to check for a registered constant /// -- cgit v1.1 From 0e5f5538bcaa031ae252468e5c0b70e5dce1a9b1 Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Fri, 14 Sep 2012 13:20:14 +0100 Subject: Documentation of IScriptModuleComms.RegisterConstant and IScriptModuleComms.LookupModConstant Signed-off-by: Melanie --- .../Region/Framework/Interfaces/IScriptModuleComms.cs | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Framework/Interfaces/IScriptModuleComms.cs b/OpenSim/Region/Framework/Interfaces/IScriptModuleComms.cs index 277c9ed..93930ce 100644 --- a/OpenSim/Region/Framework/Interfaces/IScriptModuleComms.cs +++ b/OpenSim/Region/Framework/Interfaces/IScriptModuleComms.cs @@ -104,7 +104,18 @@ namespace OpenSim.Region.Framework.Interfaces /// void DispatchReply(UUID scriptId, int code, string text, string key); - /// For constants + /// + /// Operation to for a region module to register a constant to be used + /// by the script engine + /// + /// + /// The name of the constant. LSL convention is for constant names to + /// be uppercase. + /// + /// + /// The value of the constant. Should be of a type that can be + /// converted to one of + /// void RegisterConstant(string cname, object value); /// @@ -113,6 +124,12 @@ namespace OpenSim.Region.Framework.Interfaces /// /// void RegisterConstants(IRegionModuleBase target); + + /// + /// Operation to check for a registered constant + /// + /// Name of constant + /// Value of constant or null if none found. object LookupModConstant(string cname); // For use ONLY by the script API -- cgit v1.1 From 91312daeb2974c75ede3e53c9d7a1d9ca0300201 Mon Sep 17 00:00:00 2001 From: Mic Bowman Date: Mon, 17 Sep 2012 09:04:54 -0700 Subject: Moving ScriptModuleComms into the CoreModules tree. --- .../ScriptModuleComms/ScriptModuleCommsModule.cs | 367 +++++++++++++++++++++ .../ScriptModuleComms/ScriptModuleCommsModule.cs | 367 --------------------- 2 files changed, 367 insertions(+), 367 deletions(-) create mode 100644 OpenSim/Region/CoreModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs delete mode 100644 OpenSim/Region/OptionalModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs b/OpenSim/Region/CoreModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs new file mode 100644 index 0000000..98396ff --- /dev/null +++ b/OpenSim/Region/CoreModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs @@ -0,0 +1,367 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Reflection; +using System.Collections.Generic; +using Nini.Config; +using log4net; +using OpenSim.Framework; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; +using Mono.Addins; +using OpenMetaverse; +using System.Linq; +using System.Linq.Expressions; + +namespace OpenSim.Region.OptionalModules.Scripting.ScriptModuleComms +{ + [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "ScriptModuleCommsModule")] + class ScriptModuleCommsModule : INonSharedRegionModule, IScriptModuleComms + { + private static readonly ILog m_log = + LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + private Dictionary m_constants = new Dictionary(); + +#region ScriptInvocation + protected class ScriptInvocationData + { + public Delegate ScriptInvocationDelegate { get; private set; } + public string FunctionName { get; private set; } + public Type[] TypeSignature { get; private set; } + public Type ReturnType { get; private set; } + + public ScriptInvocationData(string fname, Delegate fn, Type[] callsig, Type returnsig) + { + FunctionName = fname; + ScriptInvocationDelegate = fn; + TypeSignature = callsig; + ReturnType = returnsig; + } + } + + private Dictionary m_scriptInvocation = new Dictionary(); +#endregion + + private IScriptModule m_scriptModule = null; + public event ScriptCommand OnScriptCommand; + +#region RegionModuleInterface + public void Initialise(IConfigSource config) + { + } + + public void AddRegion(Scene scene) + { + scene.RegisterModuleInterface(this); + } + + public void RemoveRegion(Scene scene) + { + } + + public void RegionLoaded(Scene scene) + { + m_scriptModule = scene.RequestModuleInterface(); + + if (m_scriptModule != null) + m_log.Info("[MODULE COMMANDS]: Script engine found, module active"); + } + + public string Name + { + get { return "ScriptModuleCommsModule"; } + } + + public Type ReplaceableInterface + { + get { return null; } + } + + public void Close() + { + } +#endregion + +#region ScriptModuleComms + + public void RaiseEvent(UUID script, string id, string module, string command, string k) + { + ScriptCommand c = OnScriptCommand; + + if (c == null) + return; + + c(script, id, module, command, k); + } + + public void DispatchReply(UUID script, int code, string text, string k) + { + if (m_scriptModule == null) + return; + + Object[] args = new Object[] {-1, code, text, k}; + + m_scriptModule.PostScriptEvent(script, "link_message", args); + } + + private static MethodInfo GetMethodInfoFromType(Type target, string meth, bool searchInstanceMethods) + { + BindingFlags getMethodFlags = + BindingFlags.NonPublic | BindingFlags.Public; + + if (searchInstanceMethods) + getMethodFlags |= BindingFlags.Instance; + else + getMethodFlags |= BindingFlags.Static; + + return target.GetMethod(meth, getMethodFlags); + } + + public void RegisterScriptInvocation(object target, string meth) + { + MethodInfo mi = GetMethodInfoFromType(target.GetType(), meth, true); + if (mi == null) + { + m_log.WarnFormat("[MODULE COMMANDS] Failed to register method {0}", meth); + return; + } + + RegisterScriptInvocation(target, mi); + } + + public void RegisterScriptInvocation(object target, string[] meth) + { + foreach (string m in meth) + RegisterScriptInvocation(target, m); + } + + public void RegisterScriptInvocation(object target, MethodInfo mi) + { + m_log.DebugFormat("[MODULE COMMANDS] Register method {0} from type {1}", mi.Name, (target is Type) ? ((Type)target).Name : target.GetType().Name); + + Type delegateType; + List typeArgs = mi.GetParameters() + .Select(p => p.ParameterType) + .ToList(); + + if (mi.ReturnType == typeof(void)) + { + delegateType = Expression.GetActionType(typeArgs.ToArray()); + } + else + { + typeArgs.Add(mi.ReturnType); + delegateType = Expression.GetFuncType(typeArgs.ToArray()); + } + + Delegate fcall; + if (!(target is Type)) + fcall = Delegate.CreateDelegate(delegateType, target, mi); + else + fcall = Delegate.CreateDelegate(delegateType, (Type)target, mi.Name); + + lock (m_scriptInvocation) + { + ParameterInfo[] parameters = fcall.Method.GetParameters(); + if (parameters.Length < 2) // Must have two UUID params + return; + + // Hide the first two parameters + Type[] parmTypes = new Type[parameters.Length - 2]; + for (int i = 2; i < parameters.Length; i++) + parmTypes[i - 2] = parameters[i].ParameterType; + m_scriptInvocation[fcall.Method.Name] = new ScriptInvocationData(fcall.Method.Name, fcall, parmTypes, fcall.Method.ReturnType); + } + } + + public void RegisterScriptInvocation(Type target, string[] methods) + { + foreach (string method in methods) + { + MethodInfo mi = GetMethodInfoFromType(target, method, false); + if (mi == null) + m_log.WarnFormat("[MODULE COMMANDS] Failed to register method {0}", method); + else + RegisterScriptInvocation(target, mi); + } + } + + public void RegisterScriptInvocations(IRegionModuleBase target) + { + foreach(MethodInfo method in target.GetType().GetMethods( + BindingFlags.Public | BindingFlags.Instance | + BindingFlags.Static)) + { + if(method.GetCustomAttributes( + typeof(ScriptInvocationAttribute), true).Any()) + { + if(method.IsStatic) + RegisterScriptInvocation(target.GetType(), method); + else + RegisterScriptInvocation(target, method); + } + } + } + + public Delegate[] GetScriptInvocationList() + { + List ret = new List(); + + lock (m_scriptInvocation) + { + foreach (ScriptInvocationData d in m_scriptInvocation.Values) + ret.Add(d.ScriptInvocationDelegate); + } + return ret.ToArray(); + } + + public string LookupModInvocation(string fname) + { + lock (m_scriptInvocation) + { + ScriptInvocationData sid; + if (m_scriptInvocation.TryGetValue(fname,out sid)) + { + if (sid.ReturnType == typeof(string)) + return "modInvokeS"; + else if (sid.ReturnType == typeof(int)) + return "modInvokeI"; + else if (sid.ReturnType == typeof(float)) + return "modInvokeF"; + else if (sid.ReturnType == typeof(UUID)) + return "modInvokeK"; + else if (sid.ReturnType == typeof(OpenMetaverse.Vector3)) + return "modInvokeV"; + else if (sid.ReturnType == typeof(OpenMetaverse.Quaternion)) + return "modInvokeR"; + else if (sid.ReturnType == typeof(object[])) + return "modInvokeL"; + + m_log.WarnFormat("[MODULE COMMANDS] failed to find match for {0} with return type {1}",fname,sid.ReturnType.Name); + } + } + + return null; + } + + public Delegate LookupScriptInvocation(string fname) + { + lock (m_scriptInvocation) + { + ScriptInvocationData sid; + if (m_scriptInvocation.TryGetValue(fname,out sid)) + return sid.ScriptInvocationDelegate; + } + + return null; + } + + public Type[] LookupTypeSignature(string fname) + { + lock (m_scriptInvocation) + { + ScriptInvocationData sid; + if (m_scriptInvocation.TryGetValue(fname,out sid)) + return sid.TypeSignature; + } + + return null; + } + + public Type LookupReturnType(string fname) + { + lock (m_scriptInvocation) + { + ScriptInvocationData sid; + if (m_scriptInvocation.TryGetValue(fname,out sid)) + return sid.ReturnType; + } + + return null; + } + + public object InvokeOperation(UUID hostid, UUID scriptid, string fname, params object[] parms) + { + List olist = new List(); + olist.Add(hostid); + olist.Add(scriptid); + foreach (object o in parms) + olist.Add(o); + Delegate fn = LookupScriptInvocation(fname); + return fn.DynamicInvoke(olist.ToArray()); + } + + /// + /// Operation to for a region module to register a constant to be used + /// by the script engine + /// + public void RegisterConstant(string cname, object value) + { + m_log.DebugFormat("[MODULE COMMANDS] register constant <{0}> with value {1}",cname,value.ToString()); + lock (m_constants) + { + m_constants.Add(cname,value); + } + } + + public void RegisterConstants(IRegionModuleBase target) + { + foreach (FieldInfo field in target.GetType().GetFields( + BindingFlags.Public | BindingFlags.Static | + BindingFlags.Instance)) + { + if (field.GetCustomAttributes( + typeof(ScriptConstantAttribute), true).Any()) + { + RegisterConstant(field.Name, field.GetValue(target)); + } + } + } + + /// + /// Operation to check for a registered constant + /// + public object LookupModConstant(string cname) + { + // m_log.DebugFormat("[MODULE COMMANDS] lookup constant <{0}>",cname); + + lock (m_constants) + { + object value = null; + if (m_constants.TryGetValue(cname,out value)) + return value; + } + + return null; + } + +#endregion + + } +} diff --git a/OpenSim/Region/OptionalModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs b/OpenSim/Region/OptionalModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs deleted file mode 100644 index 98396ff..0000000 --- a/OpenSim/Region/OptionalModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs +++ /dev/null @@ -1,367 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Reflection; -using System.Collections.Generic; -using Nini.Config; -using log4net; -using OpenSim.Framework; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; -using Mono.Addins; -using OpenMetaverse; -using System.Linq; -using System.Linq.Expressions; - -namespace OpenSim.Region.OptionalModules.Scripting.ScriptModuleComms -{ - [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "ScriptModuleCommsModule")] - class ScriptModuleCommsModule : INonSharedRegionModule, IScriptModuleComms - { - private static readonly ILog m_log = - LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - private Dictionary m_constants = new Dictionary(); - -#region ScriptInvocation - protected class ScriptInvocationData - { - public Delegate ScriptInvocationDelegate { get; private set; } - public string FunctionName { get; private set; } - public Type[] TypeSignature { get; private set; } - public Type ReturnType { get; private set; } - - public ScriptInvocationData(string fname, Delegate fn, Type[] callsig, Type returnsig) - { - FunctionName = fname; - ScriptInvocationDelegate = fn; - TypeSignature = callsig; - ReturnType = returnsig; - } - } - - private Dictionary m_scriptInvocation = new Dictionary(); -#endregion - - private IScriptModule m_scriptModule = null; - public event ScriptCommand OnScriptCommand; - -#region RegionModuleInterface - public void Initialise(IConfigSource config) - { - } - - public void AddRegion(Scene scene) - { - scene.RegisterModuleInterface(this); - } - - public void RemoveRegion(Scene scene) - { - } - - public void RegionLoaded(Scene scene) - { - m_scriptModule = scene.RequestModuleInterface(); - - if (m_scriptModule != null) - m_log.Info("[MODULE COMMANDS]: Script engine found, module active"); - } - - public string Name - { - get { return "ScriptModuleCommsModule"; } - } - - public Type ReplaceableInterface - { - get { return null; } - } - - public void Close() - { - } -#endregion - -#region ScriptModuleComms - - public void RaiseEvent(UUID script, string id, string module, string command, string k) - { - ScriptCommand c = OnScriptCommand; - - if (c == null) - return; - - c(script, id, module, command, k); - } - - public void DispatchReply(UUID script, int code, string text, string k) - { - if (m_scriptModule == null) - return; - - Object[] args = new Object[] {-1, code, text, k}; - - m_scriptModule.PostScriptEvent(script, "link_message", args); - } - - private static MethodInfo GetMethodInfoFromType(Type target, string meth, bool searchInstanceMethods) - { - BindingFlags getMethodFlags = - BindingFlags.NonPublic | BindingFlags.Public; - - if (searchInstanceMethods) - getMethodFlags |= BindingFlags.Instance; - else - getMethodFlags |= BindingFlags.Static; - - return target.GetMethod(meth, getMethodFlags); - } - - public void RegisterScriptInvocation(object target, string meth) - { - MethodInfo mi = GetMethodInfoFromType(target.GetType(), meth, true); - if (mi == null) - { - m_log.WarnFormat("[MODULE COMMANDS] Failed to register method {0}", meth); - return; - } - - RegisterScriptInvocation(target, mi); - } - - public void RegisterScriptInvocation(object target, string[] meth) - { - foreach (string m in meth) - RegisterScriptInvocation(target, m); - } - - public void RegisterScriptInvocation(object target, MethodInfo mi) - { - m_log.DebugFormat("[MODULE COMMANDS] Register method {0} from type {1}", mi.Name, (target is Type) ? ((Type)target).Name : target.GetType().Name); - - Type delegateType; - List typeArgs = mi.GetParameters() - .Select(p => p.ParameterType) - .ToList(); - - if (mi.ReturnType == typeof(void)) - { - delegateType = Expression.GetActionType(typeArgs.ToArray()); - } - else - { - typeArgs.Add(mi.ReturnType); - delegateType = Expression.GetFuncType(typeArgs.ToArray()); - } - - Delegate fcall; - if (!(target is Type)) - fcall = Delegate.CreateDelegate(delegateType, target, mi); - else - fcall = Delegate.CreateDelegate(delegateType, (Type)target, mi.Name); - - lock (m_scriptInvocation) - { - ParameterInfo[] parameters = fcall.Method.GetParameters(); - if (parameters.Length < 2) // Must have two UUID params - return; - - // Hide the first two parameters - Type[] parmTypes = new Type[parameters.Length - 2]; - for (int i = 2; i < parameters.Length; i++) - parmTypes[i - 2] = parameters[i].ParameterType; - m_scriptInvocation[fcall.Method.Name] = new ScriptInvocationData(fcall.Method.Name, fcall, parmTypes, fcall.Method.ReturnType); - } - } - - public void RegisterScriptInvocation(Type target, string[] methods) - { - foreach (string method in methods) - { - MethodInfo mi = GetMethodInfoFromType(target, method, false); - if (mi == null) - m_log.WarnFormat("[MODULE COMMANDS] Failed to register method {0}", method); - else - RegisterScriptInvocation(target, mi); - } - } - - public void RegisterScriptInvocations(IRegionModuleBase target) - { - foreach(MethodInfo method in target.GetType().GetMethods( - BindingFlags.Public | BindingFlags.Instance | - BindingFlags.Static)) - { - if(method.GetCustomAttributes( - typeof(ScriptInvocationAttribute), true).Any()) - { - if(method.IsStatic) - RegisterScriptInvocation(target.GetType(), method); - else - RegisterScriptInvocation(target, method); - } - } - } - - public Delegate[] GetScriptInvocationList() - { - List ret = new List(); - - lock (m_scriptInvocation) - { - foreach (ScriptInvocationData d in m_scriptInvocation.Values) - ret.Add(d.ScriptInvocationDelegate); - } - return ret.ToArray(); - } - - public string LookupModInvocation(string fname) - { - lock (m_scriptInvocation) - { - ScriptInvocationData sid; - if (m_scriptInvocation.TryGetValue(fname,out sid)) - { - if (sid.ReturnType == typeof(string)) - return "modInvokeS"; - else if (sid.ReturnType == typeof(int)) - return "modInvokeI"; - else if (sid.ReturnType == typeof(float)) - return "modInvokeF"; - else if (sid.ReturnType == typeof(UUID)) - return "modInvokeK"; - else if (sid.ReturnType == typeof(OpenMetaverse.Vector3)) - return "modInvokeV"; - else if (sid.ReturnType == typeof(OpenMetaverse.Quaternion)) - return "modInvokeR"; - else if (sid.ReturnType == typeof(object[])) - return "modInvokeL"; - - m_log.WarnFormat("[MODULE COMMANDS] failed to find match for {0} with return type {1}",fname,sid.ReturnType.Name); - } - } - - return null; - } - - public Delegate LookupScriptInvocation(string fname) - { - lock (m_scriptInvocation) - { - ScriptInvocationData sid; - if (m_scriptInvocation.TryGetValue(fname,out sid)) - return sid.ScriptInvocationDelegate; - } - - return null; - } - - public Type[] LookupTypeSignature(string fname) - { - lock (m_scriptInvocation) - { - ScriptInvocationData sid; - if (m_scriptInvocation.TryGetValue(fname,out sid)) - return sid.TypeSignature; - } - - return null; - } - - public Type LookupReturnType(string fname) - { - lock (m_scriptInvocation) - { - ScriptInvocationData sid; - if (m_scriptInvocation.TryGetValue(fname,out sid)) - return sid.ReturnType; - } - - return null; - } - - public object InvokeOperation(UUID hostid, UUID scriptid, string fname, params object[] parms) - { - List olist = new List(); - olist.Add(hostid); - olist.Add(scriptid); - foreach (object o in parms) - olist.Add(o); - Delegate fn = LookupScriptInvocation(fname); - return fn.DynamicInvoke(olist.ToArray()); - } - - /// - /// Operation to for a region module to register a constant to be used - /// by the script engine - /// - public void RegisterConstant(string cname, object value) - { - m_log.DebugFormat("[MODULE COMMANDS] register constant <{0}> with value {1}",cname,value.ToString()); - lock (m_constants) - { - m_constants.Add(cname,value); - } - } - - public void RegisterConstants(IRegionModuleBase target) - { - foreach (FieldInfo field in target.GetType().GetFields( - BindingFlags.Public | BindingFlags.Static | - BindingFlags.Instance)) - { - if (field.GetCustomAttributes( - typeof(ScriptConstantAttribute), true).Any()) - { - RegisterConstant(field.Name, field.GetValue(target)); - } - } - } - - /// - /// Operation to check for a registered constant - /// - public object LookupModConstant(string cname) - { - // m_log.DebugFormat("[MODULE COMMANDS] lookup constant <{0}>",cname); - - lock (m_constants) - { - object value = null; - if (m_constants.TryGetValue(cname,out value)) - return value; - } - - return null; - } - -#endregion - - } -} -- cgit v1.1 From d29fc5305222abcc081daa7aa4b0b017d04bbae1 Mon Sep 17 00:00:00 2001 From: BlueWall Date: Tue, 18 Sep 2012 09:47:15 -0400 Subject: Fix some inconsistencies in configurartion: NonPhys prims Fix inconsistencies between configuration parameter names and their description names. Changing the configuration parameters for non physical prim size min-max from Nonphys* to NonPhys*. Please update your OpenSim.ini and Regions.ini to reflect these changes. --- OpenSim/Region/Framework/Scenes/Scene.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 9c3c53d..a27e126 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -116,7 +116,7 @@ namespace OpenSim.Region.Framework.Scenes /// /// Minimum value of the size of a physical prim in each axis /// - public float m_minPhys = 0.01f; + public float m_minPhys = 0.001f; /// /// Maximum value of the size of a physical prim in each axis @@ -744,13 +744,13 @@ namespace OpenSim.Region.Framework.Scenes PhysicalPrims = startupConfig.GetBoolean("physical_prim", PhysicalPrims); CollidablePrims = startupConfig.GetBoolean("collidable_prim", CollidablePrims); - m_minNonphys = startupConfig.GetFloat("NonphysicalPrimMin", m_minNonphys); + m_minNonphys = startupConfig.GetFloat("NonPhysicalPrimMin", m_minNonphys); if (RegionInfo.NonphysPrimMin > 0) { m_minNonphys = RegionInfo.NonphysPrimMin; } - m_maxNonphys = startupConfig.GetFloat("NonphysicalPrimMax", m_maxNonphys); + m_maxNonphys = startupConfig.GetFloat("NonPhysicalPrimMax", m_maxNonphys); if (RegionInfo.NonphysPrimMax > 0) { m_maxNonphys = RegionInfo.NonphysPrimMax; -- cgit v1.1 From 9d973ec3b377f51eab4cbd8ef7528d91477fc1d7 Mon Sep 17 00:00:00 2001 From: BlueWall Date: Tue, 18 Sep 2012 10:09:32 -0400 Subject: Cleanup from prev. commit Make correct defaults to Phys/nonPhys prims to fix errors in prev. commit --- OpenSim/Region/Framework/Scenes/Scene.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index a27e126..c873cdf 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -106,7 +106,7 @@ namespace OpenSim.Region.Framework.Scenes /// /// Minimum value of the size of a non-physical prim in each axis /// - public float m_minNonphys = 0.01f; + public float m_minNonphys = 0.001f; /// /// Maximum value of the size of a non-physical prim in each axis @@ -116,7 +116,7 @@ namespace OpenSim.Region.Framework.Scenes /// /// Minimum value of the size of a physical prim in each axis /// - public float m_minPhys = 0.001f; + public float m_minPhys = 0.01f; /// /// Maximum value of the size of a physical prim in each axis -- cgit v1.1 From 967d42d393a48841dd0f6e4e1173f77cfaa3c5e6 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Wed, 19 Sep 2012 01:06:42 +0100 Subject: Correctly override and call base OpenSimTestCase.SetUp() method in GridConnectorsTests and ArchiverTests. Remove unrelated compile warning from AttachmentsModuleTests. --- .../Avatar/Attachments/Tests/AttachmentsModuleTests.cs | 4 ++-- .../ServiceConnectorsOut/Grid/Tests/GridConnectorsTests.cs | 8 +++++--- OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs | 5 ++++- 3 files changed, 11 insertions(+), 6 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs index 82c6390..51e10f5 100644 --- a/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs +++ b/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs @@ -62,7 +62,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests public class AttachmentsModuleTests : OpenSimTestCase { private AutoResetEvent m_chatEvent = new AutoResetEvent(false); - private OSChatMessage m_osChatMessageReceived; +// private OSChatMessage m_osChatMessageReceived; [TestFixtureSetUp] public void FixtureInit() @@ -83,7 +83,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests { // Console.WriteLine("Got chat [{0}]", oscm.Message); - m_osChatMessageReceived = oscm; +// m_osChatMessageReceived = oscm; m_chatEvent.Set(); } diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/Tests/GridConnectorsTests.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/Tests/GridConnectorsTests.cs index 57ae549..4338133 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/Tests/GridConnectorsTests.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/Tests/GridConnectorsTests.cs @@ -46,8 +46,12 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid.Tests public class GridConnectorsTests : OpenSimTestCase { LocalGridServicesConnector m_LocalConnector; - private void SetUp() + + [SetUp] + public override void SetUp() { + base.SetUp(); + IConfigSource config = new IniConfigSource(); config.AddConfig("Modules"); config.AddConfig("GridService"); @@ -71,8 +75,6 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid.Tests TestHelpers.InMethod(); // log4net.Config.XmlConfigurator.Configure(); - SetUp(); - // Create 4 regions GridRegion r1 = new GridRegion(); r1.RegionName = "Test Region 1"; diff --git a/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs b/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs index 0a30905..82f49b0 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs @@ -65,8 +65,11 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests protected TaskInventoryItem m_soundItem; [SetUp] - public void SetUp() + public override void SetUp() { + base.SetUp(); + + // FIXME: Do something about this - relying on statics in unit tests causes trouble sooner or later new SceneManager(); m_archiverModule = new ArchiverModule(); -- cgit v1.1 From f2a9d26118f87903564990ff220d642801767c25 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Thu, 20 Sep 2012 01:40:05 +0100 Subject: Make ResendAppearanceUpdates = true by default in [Appearance] in OpenSimDefaults.ini. This resends appearance uuids to avatars in the scene once a minute. I have seen this help in the past resolve grey appearance problems where viewers have for unknown reasons sometimes ignored the packet. The overhead is very small since only the UUIDs are sent - the viewer then requests the texture only if it does not have it cached. This setting will not help with cloudy avatars which are usually due to the viewer not uploading baked texture data or uploading something that isn't valid JPEG2000 --- OpenSim/Region/Framework/Scenes/Scene.cs | 2 ++ 1 file changed, 2 insertions(+) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index c873cdf..e9d1d42 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -861,6 +861,8 @@ namespace OpenSim.Region.Framework.Scenes } // FIXME: Ultimately this should be in a module. + SendPeriodicAppearanceUpdates = true; + IConfig appearanceConfig = m_config.Configs["Appearance"]; if (appearanceConfig != null) { -- cgit v1.1 From a74167bb0684eb6977aef08247144dc0e4aa6b3f Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Wed, 19 Sep 2012 12:47:23 +0100 Subject: Documentation of OnPluginConsole --- OpenSim/Region/Framework/Scenes/EventManager.cs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Framework/Scenes/EventManager.cs b/OpenSim/Region/Framework/Scenes/EventManager.cs index e1c9c8e..1025943 100644 --- a/OpenSim/Region/Framework/Scenes/EventManager.cs +++ b/OpenSim/Region/Framework/Scenes/EventManager.cs @@ -184,6 +184,22 @@ namespace OpenSim.Region.Framework.Scenes public delegate void OnPluginConsoleDelegate(string[] args); + /// + /// Triggered after + /// has been called for all + /// loaded via . + /// Handlers for this event are typically used to parse the arguments + /// from in order to process or + /// filter the arguments and pass them onto + /// + /// + /// Triggered by in + /// via + /// via + /// via + /// via + /// + /// public event OnPluginConsoleDelegate OnPluginConsole; /// -- cgit v1.1 From 61f4523e01b11ac116ab0c1a86075126039f481b Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Wed, 19 Sep 2012 15:00:02 +0100 Subject: Documentation of object-related events --- OpenSim/Region/Framework/Scenes/EventManager.cs | 39 ++++++++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Framework/Scenes/EventManager.cs b/OpenSim/Region/Framework/Scenes/EventManager.cs index 1025943..7024bd6 100644 --- a/OpenSim/Region/Framework/Scenes/EventManager.cs +++ b/OpenSim/Region/Framework/Scenes/EventManager.cs @@ -238,12 +238,34 @@ namespace OpenSim.Region.Framework.Scenes /// /// Fired when an object is touched/grabbed. /// + /// /// The originalID is the local ID of the part that was actually touched. The localID itself is always that of /// the root part. + /// Triggerd in response to + /// via + /// in + /// public event ObjectGrabDelegate OnObjectGrab; public delegate void ObjectGrabDelegate(uint localID, uint originalID, Vector3 offsetPos, IClientAPI remoteClient, SurfaceTouchEventArgs surfaceArgs); + /// + /// Triggered when an object is being touched/grabbed continuously. + /// + /// + /// Triggered in response to + /// via + /// in + /// public event ObjectGrabDelegate OnObjectGrabbing; + + /// + /// Triggered when an object stops being touched/grabbed. + /// + /// + /// Triggered in response to + /// via + /// in + /// public event ObjectDeGrabDelegate OnObjectDeGrab; public event ScriptResetDelegate OnScriptReset; @@ -453,12 +475,27 @@ namespace OpenSim.Region.Framework.Scenes /// /// Triggered when an object is added to the scene. /// + /// + /// Triggered by + /// in , + /// , + /// + /// public event Action OnObjectAddedToScene; /// - /// Triggered when an object is removed from the scene. + /// Delegate for /// + /// The object being removed from the scene public delegate void ObjectBeingRemovedFromScene(SceneObjectGroup obj); + + /// + /// Triggered when an object is removed from the scene. + /// + /// + /// Triggered by + /// in + /// public event ObjectBeingRemovedFromScene OnObjectBeingRemovedFromScene; public delegate void NoticeNoLandDataFromStorage(); -- cgit v1.1 From 49e2872f9ee3c5c11145a43ec91bac2dab324f42 Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Wed, 19 Sep 2012 20:26:57 +0100 Subject: Documentation of agent-related events --- OpenSim/Region/Framework/Scenes/EventManager.cs | 35 ++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Framework/Scenes/EventManager.cs b/OpenSim/Region/Framework/Scenes/EventManager.cs index 7024bd6..48a85a2 100644 --- a/OpenSim/Region/Framework/Scenes/EventManager.cs +++ b/OpenSim/Region/Framework/Scenes/EventManager.cs @@ -214,6 +214,18 @@ namespace OpenSim.Region.Framework.Scenes public delegate void OnSetRootAgentSceneDelegate(UUID agentID, Scene scene); + /// + /// Triggered before the grunt work for adding a root agent to a + /// scene has been performed (resuming attachment scripts, physics, + /// animations etc.) + /// + /// + /// Triggered before + /// by + /// in + /// via + /// and + /// public event OnSetRootAgentSceneDelegate OnSetRootAgentScene; /// @@ -429,15 +441,36 @@ namespace OpenSim.Region.Framework.Scenes public event ScriptColliding OnScriptLandColliderEnd; public delegate void OnMakeChildAgentDelegate(ScenePresence presence); + + /// + /// Triggered when an agent has been made a child agent of a scene. + /// + /// + /// Triggered by + /// in + /// via , + /// , + /// + /// public event OnMakeChildAgentDelegate OnMakeChildAgent; public delegate void OnSaveNewWindlightProfileDelegate(); public delegate void OnSendNewWindlightProfileTargetedDelegate(RegionLightShareData wl, UUID user); /// + /// Triggered after the grunt work for adding a root agent to a + /// scene has been performed (resuming attachment scripts, physics, + /// animations etc.) + /// + /// /// This event is on the critical path for transferring an avatar from one region to another. Try and do /// as little work on this event as possible, or do work asynchronously. - /// + /// Triggered after + /// by + /// in + /// via + /// and + /// public event Action OnMakeRootAgent; public event OnSendNewWindlightProfileTargetedDelegate OnSendNewWindlightProfileTargeted; -- cgit v1.1 From 696b3f66c482aa6ee56b0a0d7cd3686a43e59503 Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Wed, 19 Sep 2012 20:27:52 +0100 Subject: minor tweaks to existing comments for IDE goodness --- OpenSim/Region/Framework/Scenes/EventManager.cs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Framework/Scenes/EventManager.cs b/OpenSim/Region/Framework/Scenes/EventManager.cs index 48a85a2..e415e09 100644 --- a/OpenSim/Region/Framework/Scenes/EventManager.cs +++ b/OpenSim/Region/Framework/Scenes/EventManager.cs @@ -496,9 +496,10 @@ namespace OpenSim.Region.Framework.Scenes public event AvatarKillData OnAvatarKilled; public delegate void AvatarKillData(uint KillerLocalID, ScenePresence avatar); -// public delegate void ScriptTimerEvent(uint localID, double timerinterval); - -// public event ScriptTimerEvent OnScriptTimerEvent; + /* + public delegate void ScriptTimerEvent(uint localID, double timerinterval); + public event ScriptTimerEvent OnScriptTimerEvent; + */ public delegate void EstateToolsSunUpdate(ulong regionHandle, bool FixedTime, bool EstateSun, float LindenHour); public delegate void GetScriptRunning(IClientAPI controllingClient, UUID objectID, UUID itemID); @@ -724,7 +725,9 @@ namespace OpenSim.Region.Framework.Scenes public UUID sender; public UUID receiver; - // Always false. The SL protocol sucks. + /// + /// Always false. The SL protocol sucks. + /// public bool authenticated = false; public int amount; -- cgit v1.1 From d667f9d260808a27e91acf11244dded87517ec58 Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Sat, 15 Sep 2012 17:32:10 +0100 Subject: Documentation of teleport-related events --- OpenSim/Region/Framework/Scenes/EventManager.cs | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Framework/Scenes/EventManager.cs b/OpenSim/Region/Framework/Scenes/EventManager.cs index e415e09..f079e00 100644 --- a/OpenSim/Region/Framework/Scenes/EventManager.cs +++ b/OpenSim/Region/Framework/Scenes/EventManager.cs @@ -715,9 +715,28 @@ namespace OpenSim.Region.Framework.Scenes public event PrimsLoaded OnPrimsLoaded; public delegate void TeleportStart(IClientAPI client, GridRegion destination, GridRegion finalDestination, uint teleportFlags, bool gridLogout); + + /// + /// Triggered when a teleport starts + /// + /// + /// Triggered by + /// in + /// and + /// via + /// public event TeleportStart OnTeleportStart; public delegate void TeleportFail(IClientAPI client, bool gridLogout); + + /// + /// Trigered when a teleport fails. + /// + /// + /// Triggered by + /// in + /// via + /// public event TeleportFail OnTeleportFail; public class MoneyTransferArgs : EventArgs -- cgit v1.1 From b481a782341b721b14f30108b411a580e5f8651e Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Thu, 20 Sep 2012 02:01:01 +0100 Subject: Don't fail to create an IRC nick if nick randomization is disabled in the IRC module. Patch from http://opensimulator.org/mantis/view.php?id=6293 Thanks Starflower. --- OpenSim/Region/OptionalModules/Avatar/Chat/IRCConnector.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/OptionalModules/Avatar/Chat/IRCConnector.cs b/OpenSim/Region/OptionalModules/Avatar/Chat/IRCConnector.cs index ca956fb..a014798 100644 --- a/OpenSim/Region/OptionalModules/Avatar/Chat/IRCConnector.cs +++ b/OpenSim/Region/OptionalModules/Avatar/Chat/IRCConnector.cs @@ -231,12 +231,12 @@ namespace OpenSim.Region.OptionalModules.Avatar.Chat if (m_server == null || m_baseNick == null || m_ircChannel == null || m_user == null) throw new Exception("Invalid connector configuration"); - // Generate an initial nickname if randomizing is enabled + // Generate an initial nickname if (m_randomizeNick) - { m_nick = m_baseNick + Util.RandomClass.Next(1, 99); - } + else + m_nick = m_baseNick; m_log.InfoFormat("[IRC-Connector-{0}]: Initialization complete", idn); -- cgit v1.1 From 3089b6d824f1d4eb25ba12c5fd037153fdc92e1e Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Thu, 20 Sep 2012 15:49:22 -0700 Subject: More HG2.0: Added permission policies in HGAsset Service based on asset types. The policies are given in the config. This is only half of the story. The other half, pertaining to exports/imports made by the sim, will be done next. --- .../Framework/InventoryAccess/HGAssetMapper.cs | 34 ++++++++++++---------- 1 file changed, 19 insertions(+), 15 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs index eaadc1b..fcecbbc 100644 --- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs +++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs @@ -93,6 +93,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess if (!url.EndsWith("/") && !url.EndsWith("=")) url = url + "/"; + bool success = true; // See long comment in AssetCache.AddAsset if (!asset.Temporary || asset.Local) { @@ -103,14 +104,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess // not having a global naming infrastructure AssetBase asset1 = new AssetBase(asset.FullID, asset.Name, asset.Type, asset.Metadata.CreatorID); Copy(asset, asset1); - try - { - asset1.ID = url + asset.ID; - } - catch - { - m_log.Warn("[HG ASSET MAPPER]: Oops."); - } + asset1.ID = url + asset.ID; AdjustIdentifiers(asset1.Metadata); if (asset1.Metadata.Type == (sbyte)AssetType.Object) @@ -118,11 +112,17 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess else asset1.Data = asset.Data; - m_scene.AssetService.Store(asset1); - m_log.DebugFormat("[HG ASSET MAPPER]: Posted copy of asset {0} from local asset server to {1}", asset1.ID, url); + string id = m_scene.AssetService.Store(asset1); + if (id == UUID.Zero.ToString()) + { + m_log.DebugFormat("[HG ASSET MAPPER]: Asset server {0} did not accept {1}", url, asset.ID); + success = false; + } + else + m_log.DebugFormat("[HG ASSET MAPPER]: Posted copy of asset {0} from local asset server to {1}", asset1.ID, url); } - return true; - } + return success; + } else m_log.Warn("[HG ASSET MAPPER]: Tried to post asset to remote server, but asset not in local cache."); @@ -259,17 +259,21 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess Dictionary ids = new Dictionary(); HGUuidGatherer uuidGatherer = new HGUuidGatherer(this, m_scene.AssetService, string.Empty); uuidGatherer.GatherAssetUuids(asset.FullID, (AssetType)asset.Type, ids); + bool success = false; foreach (UUID uuid in ids.Keys) { asset = m_scene.AssetService.Get(uuid.ToString()); if (asset == null) m_log.DebugFormat("[HG ASSET MAPPER]: Could not find asset {0}", uuid); else - PostAsset(userAssetURL, asset); + success = PostAsset(userAssetURL, asset); } - // maybe all pieces got there... - m_log.DebugFormat("[HG ASSET MAPPER]: Successfully posted item {0} to asset server {1}", assetID, userAssetURL); + // maybe all pieces got there... + if (!success) + m_log.DebugFormat("[HG ASSET MAPPER]: Problems posting item {0} to asset server {1}", assetID, userAssetURL); + else + m_log.DebugFormat("[HG ASSET MAPPER]: Successfully posted item {0} to asset server {1}", assetID, userAssetURL); } else -- cgit v1.1 From bceef401fa9f7b9d56c5d1173ca5204aead0a57c Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 21 Sep 2012 01:36:23 +0100 Subject: Simplify UuidGatherer by performing asset fetch synchronously rather than using the async call but waiting for completion anyway! --- OpenSim/Region/Framework/Scenes/UuidGatherer.cs | 84 +++++++++++++------------ 1 file changed, 44 insertions(+), 40 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Framework/Scenes/UuidGatherer.cs b/OpenSim/Region/Framework/Scenes/UuidGatherer.cs index efb68a2..af99090 100644 --- a/OpenSim/Region/Framework/Scenes/UuidGatherer.cs +++ b/OpenSim/Region/Framework/Scenes/UuidGatherer.cs @@ -57,17 +57,17 @@ namespace OpenSim.Region.Framework.Scenes /// Asset cache used for gathering assets /// protected IAssetService m_assetCache; - - /// - /// Used as a temporary store of an asset which represents an object. This can be a null if no appropriate - /// asset was found by the asset service. - /// - private AssetBase m_requestedObjectAsset; - /// - /// Signal whether we are currently waiting for the asset service to deliver an asset. - /// - private bool m_waitingForObjectAsset; +// /// +// /// Used as a temporary store of an asset which represents an object. This can be a null if no appropriate +// /// asset was found by the asset service. +// /// +// private AssetBase m_requestedObjectAsset; +// +// /// +// /// Signal whether we are currently waiting for the asset service to deliver an asset. +// /// +// private bool m_waitingForObjectAsset; public UuidGatherer(IAssetService assetCache) { @@ -195,18 +195,18 @@ namespace OpenSim.Region.Framework.Scenes } } - /// - /// The callback made when we request the asset for an object from the asset service. - /// - private void AssetReceived(string id, Object sender, AssetBase asset) - { - lock (this) - { - m_requestedObjectAsset = asset; - m_waitingForObjectAsset = false; - Monitor.Pulse(this); - } - } +// /// +// /// The callback made when we request the asset for an object from the asset service. +// /// +// private void AssetReceived(string id, Object sender, AssetBase asset) +// { +// lock (this) +// { +// m_requestedObjectAsset = asset; +// m_waitingForObjectAsset = false; +// Monitor.Pulse(this); +// } +// } /// /// Get an asset synchronously, potentially using an asynchronous callback. If the @@ -216,25 +216,29 @@ namespace OpenSim.Region.Framework.Scenes /// protected virtual AssetBase GetAsset(UUID uuid) { - m_waitingForObjectAsset = true; - m_assetCache.Get(uuid.ToString(), this, AssetReceived); - - // The asset cache callback can either - // - // 1. Complete on the same thread (if the asset is already in the cache) or - // 2. Come in via a different thread (if we need to go fetch it). - // - // The code below handles both these alternatives. - lock (this) - { - if (m_waitingForObjectAsset) - { - Monitor.Wait(this); - m_waitingForObjectAsset = false; - } - } + return m_assetCache.Get(uuid.ToString()); - return m_requestedObjectAsset; + // XXX: Switching to do this synchronously where the call was async before but we always waited for it + // to complete anyway! +// m_waitingForObjectAsset = true; +// m_assetCache.Get(uuid.ToString(), this, AssetReceived); +// +// // The asset cache callback can either +// // +// // 1. Complete on the same thread (if the asset is already in the cache) or +// // 2. Come in via a different thread (if we need to go fetch it). +// // +// // The code below handles both these alternatives. +// lock (this) +// { +// if (m_waitingForObjectAsset) +// { +// Monitor.Wait(this); +// m_waitingForObjectAsset = false; +// } +// } +// +// return m_requestedObjectAsset; } /// -- cgit v1.1 From 632a42e2b1e9a649be812ed57de1189778a370c9 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 21 Sep 2012 01:57:13 +0100 Subject: Rename UuidGather.m_assetCache to m_assetService. If HGUuidGatherer hasn't been instantiated with an assetServerURL then call down to overriden UuidGatherer.GetAsset() instead of calling m_assetService.GetAsset() itself - these two codepaths are now identical. --- .../CoreModules/Framework/InventoryAccess/HGUuidGatherer.cs | 4 ++-- OpenSim/Region/Framework/Scenes/UuidGatherer.cs | 11 ++++------- 2 files changed, 6 insertions(+), 9 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGUuidGatherer.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGUuidGatherer.cs index fcb544f..c7e1ef4 100644 --- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGUuidGatherer.cs +++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGUuidGatherer.cs @@ -40,7 +40,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess protected string m_assetServerURL; protected HGAssetMapper m_assetMapper; - public HGUuidGatherer(HGAssetMapper assMap, IAssetService assetCache, string assetServerURL) : base(assetCache) + public HGUuidGatherer(HGAssetMapper assMap, IAssetService assetService, string assetServerURL) : base(assetService) { m_assetMapper = assMap; m_assetServerURL = assetServerURL; @@ -49,7 +49,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess protected override AssetBase GetAsset(UUID uuid) { if (string.Empty == m_assetServerURL) - return m_assetCache.Get(uuid.ToString()); + return base.GetAsset(uuid); else return m_assetMapper.FetchAsset(m_assetServerURL, uuid); } diff --git a/OpenSim/Region/Framework/Scenes/UuidGatherer.cs b/OpenSim/Region/Framework/Scenes/UuidGatherer.cs index af99090..dc4a082 100644 --- a/OpenSim/Region/Framework/Scenes/UuidGatherer.cs +++ b/OpenSim/Region/Framework/Scenes/UuidGatherer.cs @@ -52,11 +52,8 @@ namespace OpenSim.Region.Framework.Scenes public class UuidGatherer { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - /// - /// Asset cache used for gathering assets - /// - protected IAssetService m_assetCache; + + protected IAssetService m_assetService; // /// // /// Used as a temporary store of an asset which represents an object. This can be a null if no appropriate @@ -71,7 +68,7 @@ namespace OpenSim.Region.Framework.Scenes public UuidGatherer(IAssetService assetCache) { - m_assetCache = assetCache; + m_assetService = assetCache; } /// @@ -216,7 +213,7 @@ namespace OpenSim.Region.Framework.Scenes /// protected virtual AssetBase GetAsset(UUID uuid) { - return m_assetCache.Get(uuid.ToString()); + return m_assetService.Get(uuid.ToString()); // XXX: Switching to do this synchronously where the call was async before but we always waited for it // to complete anyway! -- cgit v1.1 From 5f97b3e1d9775a88c1d952f1d599254969a262d2 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Fri, 21 Sep 2012 06:41:32 -0700 Subject: Minor: change the return value of unsuccessful posts to string.Empty. --- OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs index fcecbbc..144cc87 100644 --- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs +++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs @@ -113,7 +113,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess asset1.Data = asset.Data; string id = m_scene.AssetService.Store(asset1); - if (id == UUID.Zero.ToString()) + if (id == string.Empty) { m_log.DebugFormat("[HG ASSET MAPPER]: Asset server {0} did not accept {1}", url, asset.ID); success = false; -- cgit v1.1 From b542622b3a841e73f071aab563ba1e211c5a87e3 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Fri, 21 Sep 2012 07:44:18 -0700 Subject: HG 2.0: added asset import/export policies at the sim too. --- .../ServiceConnectorsOut/Asset/HGAssetBroker.cs | 23 ++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/HGAssetBroker.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/HGAssetBroker.cs index 008465f..0456852 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/HGAssetBroker.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/HGAssetBroker.cs @@ -56,6 +56,8 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset private bool m_Enabled = false; + private AssetPermissions m_AssetPerms; + public Type ReplaceableInterface { get { return null; } @@ -128,6 +130,9 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset if (m_LocalAssetServiceURI != string.Empty) m_LocalAssetServiceURI = m_LocalAssetServiceURI.Trim('/'); + IConfig hgConfig = source.Configs["HGAssetService"]; + m_AssetPerms = new AssetPermissions(hgConfig); + m_Enabled = true; m_log.Info("[HG ASSET CONNECTOR]: HG asset broker enabled"); } @@ -206,14 +211,11 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset asset = m_HGService.Get(id); if (asset != null) { - // Now store it locally - // For now, let me just do it for textures and scripts - if (((AssetType)asset.Type == AssetType.Texture) || - ((AssetType)asset.Type == AssetType.LSLBytecode) || - ((AssetType)asset.Type == AssetType.LSLText)) - { + // Now store it locally, if allowed + if (m_AssetPerms.AllowedImport(asset.Type)) m_GridService.Store(asset); - } + else + return null; } } else @@ -328,7 +330,12 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset string id = string.Empty; if (IsHG(asset.ID)) - id = m_HGService.Store(asset); + { + if (m_AssetPerms.AllowedExport(asset.Type)) + id = m_HGService.Store(asset); + else + return String.Empty; + } else id = m_GridService.Store(asset); -- cgit v1.1 From f931c0a86893799548d1d0f72c327c37823e4612 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Fri, 21 Sep 2012 15:04:41 -0700 Subject: Minor: may avoid crashes of sims that still don't have this configuration section. --- OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/HGAssetBroker.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/HGAssetBroker.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/HGAssetBroker.cs index 0456852..1e1c7d0 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/HGAssetBroker.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/HGAssetBroker.cs @@ -131,7 +131,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset m_LocalAssetServiceURI = m_LocalAssetServiceURI.Trim('/'); IConfig hgConfig = source.Configs["HGAssetService"]; - m_AssetPerms = new AssetPermissions(hgConfig); + m_AssetPerms = new AssetPermissions(hgConfig); // it's ok if arg is null m_Enabled = true; m_log.Info("[HG ASSET CONNECTOR]: HG asset broker enabled"); -- cgit v1.1 From fb2ace6fff788b18df070933f8f80ee2d2fc1679 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Fri, 21 Sep 2012 15:55:58 -0700 Subject: Removed redundant asset fetches on HGAssetMapper. The UuidGatherer already downloads the assets, so we don't need to do it again... --- .../Framework/InventoryAccess/HGAssetMapper.cs | 42 ++++++++++++---------- 1 file changed, 24 insertions(+), 18 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs index 144cc87..dd0ea1c 100644 --- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs +++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs @@ -71,6 +71,21 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess #region Internal functions + public AssetMetadata FetchMetadata(string url, UUID assetID) + { + if (!url.EndsWith("/") && !url.EndsWith("=")) + url = url + "/"; + + AssetMetadata meta = m_scene.AssetService.GetMetadata(url + assetID.ToString()); + + if (meta != null) + m_log.DebugFormat("[HG ASSET MAPPER]: Fetched metadata for asset {0} of type {1} from {2} ", assetID, meta.Type, url); + else + m_log.DebugFormat("[HG ASSET MAPPER]: Unable to fetched metadata for asset {0} from {1} ", assetID, url); + + return meta; + } + public AssetBase FetchAsset(string url, UUID assetID) { if (!url.EndsWith("/") && !url.EndsWith("=")) @@ -222,28 +237,19 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess public void Get(UUID assetID, UUID ownerID, string userAssetURL) { - // Get the item from the remote asset server onto the local AssetCache - // and place an entry in m_assetMap + // Get the item from the remote asset server onto the local AssetService - m_log.Debug("[HG ASSET MAPPER]: Fetching object " + assetID + " from asset server " + userAssetURL); - AssetBase asset = FetchAsset(userAssetURL, assetID); + AssetMetadata meta = FetchMetadata(userAssetURL, assetID); + if (meta == null) + return; - if (asset != null) - { - // OK, now fetch the inside. - Dictionary ids = new Dictionary(); - HGUuidGatherer uuidGatherer = new HGUuidGatherer(this, m_scene.AssetService, userAssetURL); - uuidGatherer.GatherAssetUuids(asset.FullID, (AssetType)asset.Type, ids); - if (ids.ContainsKey(assetID)) - ids.Remove(assetID); - foreach (UUID uuid in ids.Keys) - FetchAsset(userAssetURL, uuid); + // The act of gathering UUIDs downloads the assets from the remote server + Dictionary ids = new Dictionary(); + HGUuidGatherer uuidGatherer = new HGUuidGatherer(this, m_scene.AssetService, userAssetURL); + uuidGatherer.GatherAssetUuids(assetID, (AssetType)meta.Type, ids); - m_log.DebugFormat("[HG ASSET MAPPER]: Successfully fetched asset {0} from asset server {1}", asset.ID, userAssetURL); + m_log.DebugFormat("[HG ASSET MAPPER]: Successfully fetched asset {0} from asset server {1}", assetID, userAssetURL); - } - else - m_log.Warn("[HG ASSET MAPPER]: Could not fetch asset from remote asset server " + userAssetURL); } -- cgit v1.1 From 5df39446078327106df5e9331f0156b149727d61 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Sat, 22 Sep 2012 00:23:25 +0100 Subject: Fix llListFindList() returning no match when there is a match with a script constant component in the source list. Adds regression test for this case. Based on http://opensimulator.org/mantis/view.php?id=6156 Thanks SignpostMarv. --- .../Shared/Api/Implementation/LSL_Api.cs | 24 ++-- .../ScriptEngine/Shared/Tests/LSL_ApiListTests.cs | 134 +++++++++++++++++++++ 2 files changed, 150 insertions(+), 8 deletions(-) create mode 100644 OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiListTests.cs (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 11826bd..52d96bc 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -5465,27 +5465,36 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api /// Returns the index of the first occurrence of test /// in src. /// - + /// Source list + /// List to search for + /// + /// The index number of the point in src where test was found if it was found. + /// Otherwise returns -1 + /// public LSL_Integer llListFindList(LSL_List src, LSL_List test) { - int index = -1; int length = src.Length - test.Length + 1; m_host.AddScriptLPS(1); // If either list is empty, do not match - if (src.Length != 0 && test.Length != 0) { for (int i = 0; i < length; i++) { - if (src.Data[i].Equals(test.Data[0])) + // Why this piece of insanity? This is because most script constants are C# value types (e.g. int) + // rather than wrapped LSL types. Such a script constant does not have int.Equal(LSL_Integer) code + // and so the comparison fails even if the LSL_Integer conceptually has the same value. + // Therefore, here we test Equals on both the source and destination objects. + // However, a future better approach may be use LSL struct script constants (e.g. LSL_Integer(1)). + if (src.Data[i].Equals(test.Data[0]) || test.Data[0].Equals(src.Data[i])) { int j; for (j = 1; j < test.Length; j++) - if (!src.Data[i+j].Equals(test.Data[j])) + if (!(src.Data[i+j].Equals(test.Data[j]) || test.Data[j].Equals(src.Data[i+j]))) break; + if (j == test.Length) { index = i; @@ -5496,19 +5505,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } return index; - } public LSL_String llGetObjectName() { m_host.AddScriptLPS(1); - return m_host.Name!=null?m_host.Name:String.Empty; + return m_host.Name !=null ? m_host.Name : String.Empty; } public void llSetObjectName(string name) { m_host.AddScriptLPS(1); - m_host.Name = name!=null?name:String.Empty; + m_host.Name = name != null ? name : String.Empty; } public LSL_String llGetDate() diff --git a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiListTests.cs b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiListTests.cs new file mode 100644 index 0000000..dd23be8 --- /dev/null +++ b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiListTests.cs @@ -0,0 +1,134 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections.Generic; +using NUnit.Framework; +using OpenSim.Framework; +using OpenSim.Tests.Common; +using OpenSim.Region.ScriptEngine.Shared; +using OpenSim.Region.Framework.Scenes; +using Nini.Config; +using OpenSim.Region.ScriptEngine.Shared.Api; +using OpenSim.Region.ScriptEngine.Shared.ScriptBase; +using OpenMetaverse; +using OpenSim.Tests.Common.Mock; + +using LSL_Float = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLFloat; +using LSL_Integer = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLInteger; +using LSL_List = OpenSim.Region.ScriptEngine.Shared.LSL_Types.list; +using LSL_String = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString; + +namespace OpenSim.Region.ScriptEngine.Shared.Tests +{ + [TestFixture] + public class LSL_ApiListTests + { + private LSL_Api m_lslApi; + + [SetUp] + public void SetUp() + { + IConfigSource initConfigSource = new IniConfigSource(); + IConfig config = initConfigSource.AddConfig("XEngine"); + config.Set("Enabled", "true"); + + Scene scene = new SceneHelpers().SetupScene(); + SceneObjectPart part = SceneHelpers.AddSceneObject(scene).RootPart; + + XEngine.XEngine engine = new XEngine.XEngine(); + engine.Initialise(initConfigSource); + engine.AddRegion(scene); + + m_lslApi = new LSL_Api(); + m_lslApi.Initialize(engine, part, null); + } + + [Test] + public void TestllListFindList() + { + TestHelpers.InMethod(); + + LSL_List src = new LSL_List(new LSL_Integer(1), new LSL_Integer(2), new LSL_Integer(3)); + + { + // Test for a single item that should be found + int result = m_lslApi.llListFindList(src, new LSL_List(new LSL_Integer(4))); + Assert.That(result, Is.EqualTo(-1)); + } + + { + // Test for a single item that should be found + int result = m_lslApi.llListFindList(src, new LSL_List(new LSL_Integer(2))); + Assert.That(result, Is.EqualTo(1)); + } + + { + // Test for a constant that should be found + int result = m_lslApi.llListFindList(src, new LSL_List(ScriptBaseClass.AGENT)); + Assert.That(result, Is.EqualTo(0)); + } + + { + // Test for a list that should be found + int result = m_lslApi.llListFindList(src, new LSL_List(new LSL_Integer(2), new LSL_Integer(3))); + Assert.That(result, Is.EqualTo(1)); + } + + { + // Test for a single item not in the list + int result = m_lslApi.llListFindList(src, new LSL_List(new LSL_Integer(4))); + Assert.That(result, Is.EqualTo(-1)); + } + + { + // Test for something that should not be cast + int result = m_lslApi.llListFindList(src, new LSL_List(new LSL_String("4"))); + Assert.That(result, Is.EqualTo(-1)); + } + + { + // Test for a list not in the list + int result + = m_lslApi.llListFindList( + src, new LSL_List(new LSL_Integer(2), new LSL_Integer(3), new LSL_Integer(4))); + Assert.That(result, Is.EqualTo(-1)); + } + + { + LSL_List srcWithConstants + = new LSL_List(new LSL_Integer(3), ScriptBaseClass.AGENT, ScriptBaseClass.OS_NPC_LAND_AT_TARGET); + + // Test for constants that appears in the source list that should be found + int result + = m_lslApi.llListFindList(srcWithConstants, new LSL_List(new LSL_Integer(1), new LSL_Integer(2))); + + Assert.That(result, Is.EqualTo(1)); + } + } + } + } \ No newline at end of file -- cgit v1.1 From cfa022700d3d099eee7cd25d18da875639506ea8 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Fri, 21 Sep 2012 16:45:16 -0700 Subject: Moved the small HGUuidGatherer class to the file where its parent class is. No need to keep 2 separate files. --- .../Framework/InventoryAccess/HGAssetMapper.cs | 19 +------- .../Framework/InventoryAccess/HGUuidGatherer.cs | 57 ---------------------- OpenSim/Region/Framework/Scenes/UuidGatherer.cs | 36 ++++++++++++++ 3 files changed, 38 insertions(+), 74 deletions(-) delete mode 100644 OpenSim/Region/CoreModules/Framework/InventoryAccess/HGUuidGatherer.cs (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs index dd0ea1c..6f62856 100644 --- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs +++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs @@ -86,21 +86,6 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess return meta; } - public AssetBase FetchAsset(string url, UUID assetID) - { - if (!url.EndsWith("/") && !url.EndsWith("=")) - url = url + "/"; - - AssetBase asset = m_scene.AssetService.Get(url + assetID.ToString()); - - if (asset != null) - { - m_log.DebugFormat("[HG ASSET MAPPER]: Copied asset {0} from {1} to local asset server. ", asset.ID, url); - return asset; - } - return null; - } - public bool PostAsset(string url, AssetBase asset) { if (asset != null) @@ -245,7 +230,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess // The act of gathering UUIDs downloads the assets from the remote server Dictionary ids = new Dictionary(); - HGUuidGatherer uuidGatherer = new HGUuidGatherer(this, m_scene.AssetService, userAssetURL); + HGUuidGatherer uuidGatherer = new HGUuidGatherer(m_scene.AssetService, userAssetURL); uuidGatherer.GatherAssetUuids(assetID, (AssetType)meta.Type, ids); m_log.DebugFormat("[HG ASSET MAPPER]: Successfully fetched asset {0} from asset server {1}", assetID, userAssetURL); @@ -263,7 +248,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess if (asset != null) { Dictionary ids = new Dictionary(); - HGUuidGatherer uuidGatherer = new HGUuidGatherer(this, m_scene.AssetService, string.Empty); + HGUuidGatherer uuidGatherer = new HGUuidGatherer(m_scene.AssetService, string.Empty); uuidGatherer.GatherAssetUuids(asset.FullID, (AssetType)asset.Type, ids); bool success = false; foreach (UUID uuid in ids.Keys) diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGUuidGatherer.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGUuidGatherer.cs deleted file mode 100644 index c7e1ef4..0000000 --- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGUuidGatherer.cs +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; - -using OpenSim.Framework; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Services.Interfaces; -using OpenMetaverse; - -namespace OpenSim.Region.CoreModules.Framework.InventoryAccess -{ - public class HGUuidGatherer : UuidGatherer - { - protected string m_assetServerURL; - protected HGAssetMapper m_assetMapper; - - public HGUuidGatherer(HGAssetMapper assMap, IAssetService assetService, string assetServerURL) : base(assetService) - { - m_assetMapper = assMap; - m_assetServerURL = assetServerURL; - } - - protected override AssetBase GetAsset(UUID uuid) - { - if (string.Empty == m_assetServerURL) - return base.GetAsset(uuid); - else - return m_assetMapper.FetchAsset(m_assetServerURL, uuid); - } - } -} diff --git a/OpenSim/Region/Framework/Scenes/UuidGatherer.cs b/OpenSim/Region/Framework/Scenes/UuidGatherer.cs index dc4a082..383604d 100644 --- a/OpenSim/Region/Framework/Scenes/UuidGatherer.cs +++ b/OpenSim/Region/Framework/Scenes/UuidGatherer.cs @@ -366,4 +366,40 @@ namespace OpenSim.Region.Framework.Scenes } } } + + public class HGUuidGatherer : UuidGatherer + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + protected string m_assetServerURL; + + public HGUuidGatherer(IAssetService assetService, string assetServerURL) + : base(assetService) + { + m_assetServerURL = assetServerURL; + } + + protected override AssetBase GetAsset(UUID uuid) + { + if (string.Empty == m_assetServerURL) + return base.GetAsset(uuid); + else + return FetchAsset(m_assetServerURL, uuid); + } + + public AssetBase FetchAsset(string url, UUID assetID) + { + if (!url.EndsWith("/") && !url.EndsWith("=")) + url = url + "/"; + + AssetBase asset = m_assetService.Get(url + assetID.ToString()); + + if (asset != null) + { + m_log.DebugFormat("[HGUUIDGatherer]: Copied asset {0} from {1} to local asset server. ", asset.ID, url); + return asset; + } + return null; + } + } } -- cgit v1.1 From 8d7b1f8aa08efbb2d0087abee22178c36cbc2f98 Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Fri, 21 Sep 2012 23:32:41 +0100 Subject: Documenting non-LSL script-related events --- OpenSim/Region/Framework/Scenes/EventManager.cs | 52 +++++++++++++++++++++++++ 1 file changed, 52 insertions(+) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Framework/Scenes/EventManager.cs b/OpenSim/Region/Framework/Scenes/EventManager.cs index f079e00..96e9797 100644 --- a/OpenSim/Region/Framework/Scenes/EventManager.cs +++ b/OpenSim/Region/Framework/Scenes/EventManager.cs @@ -279,6 +279,16 @@ namespace OpenSim.Region.Framework.Scenes /// in /// public event ObjectDeGrabDelegate OnObjectDeGrab; + + /// + /// Triggered when a script resets. + /// + /// + /// Triggered by + /// in + /// via + /// via + /// public event ScriptResetDelegate OnScriptReset; public event OnPermissionErrorDelegate OnPermissionError; @@ -288,17 +298,50 @@ namespace OpenSim.Region.Framework.Scenes /// /// /// Occurs after OnNewScript. + /// Triggered by + /// in /// public event NewRezScript OnRezScript; public delegate void NewRezScript(uint localID, UUID itemID, string script, int startParam, bool postOnRez, string engine, int stateSource); public delegate void RemoveScript(uint localID, UUID itemID); + + /// + /// Triggered when a script is removed from an object. + /// + /// + /// Triggered by + /// in , + /// , + /// , + /// + /// public event RemoveScript OnRemoveScript; public delegate void StartScript(uint localID, UUID itemID); + + /// + /// Triggered when a script starts. + /// + /// + /// Triggered by + /// in + /// via , + /// via + /// public event StartScript OnStartScript; public delegate void StopScript(uint localID, UUID itemID); + + /// + /// Triggered when a script stops. + /// + /// + /// Triggered by , + /// in , + /// , + /// + /// public event StopScript OnStopScript; public delegate bool SceneGroupMoved(UUID groupID, Vector3 delta); @@ -349,6 +392,9 @@ namespace OpenSim.Region.Framework.Scenes /// /// /// Occurs before OnRezScript + /// Triggered by + /// in , + /// /// public event NewScript OnNewScript; @@ -383,6 +429,12 @@ namespace OpenSim.Region.Framework.Scenes /// /// /// Triggered after the scene receives a client's upload of an updated script and has stored it in an asset. + /// Triggered by + /// in + /// via + /// via + /// via + /// via /// public event UpdateScript OnUpdateScript; -- cgit v1.1 From 21a6ef5bb63e56612b8e03002dbee9ff1fcdc4c0 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Fri, 21 Sep 2012 17:58:44 -0700 Subject: This fixes HG attachments' missing assets (textures, etc). Also, further improvements on HGUuidGatherer: if the assets are already in this grid don't fetch them again. --- .../EntityTransfer/HGEntityTransferModule.cs | 28 ++++++++++++++++++++++ OpenSim/Region/Framework/Scenes/UuidGatherer.cs | 27 +++++++++++++-------- 2 files changed, 45 insertions(+), 10 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs index 0b386d3..a6698e6 100644 --- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs +++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs @@ -150,6 +150,34 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer if (m_Enabled) scene.RegisterModuleInterface(this); + + scene.EventManager.OnIncomingSceneObject += OnIncomingSceneObject; + } + + void OnIncomingSceneObject(SceneObjectGroup so) + { + if (!so.IsAttachment) + return; + + if (so.Scene.UserManagementModule.IsLocalGridUser(so.AttachedAvatar)) + return; + + // foreign user + AgentCircuitData aCircuit = so.Scene.AuthenticateHandler.GetAgentCircuitData(so.AttachedAvatar); + if (aCircuit != null && (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaHGLogin) != 0) + { + if (aCircuit.ServiceURLs != null && aCircuit.ServiceURLs.ContainsKey("AssetServerURI")) + { + string url = aCircuit.ServiceURLs["AssetServerURI"].ToString(); + m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Incoming attachement {0} for HG user {1} with asset server {2}", so.Name, so.AttachedAvatar, url); + Dictionary ids = new Dictionary(); + HGUuidGatherer uuidGatherer = new HGUuidGatherer(so.Scene.AssetService, url); + uuidGatherer.GatherAssetUuids(so, ids); + + foreach (KeyValuePair kvp in ids) + uuidGatherer.FetchAsset(kvp.Key); + } + } } protected override void OnNewClient(IClientAPI client) diff --git a/OpenSim/Region/Framework/Scenes/UuidGatherer.cs b/OpenSim/Region/Framework/Scenes/UuidGatherer.cs index 383604d..28cd09f 100644 --- a/OpenSim/Region/Framework/Scenes/UuidGatherer.cs +++ b/OpenSim/Region/Framework/Scenes/UuidGatherer.cs @@ -377,6 +377,8 @@ namespace OpenSim.Region.Framework.Scenes : base(assetService) { m_assetServerURL = assetServerURL; + if (!m_assetServerURL.EndsWith("/") && !m_assetServerURL.EndsWith("=")) + m_assetServerURL = m_assetServerURL + "/"; } protected override AssetBase GetAsset(UUID uuid) @@ -384,22 +386,27 @@ namespace OpenSim.Region.Framework.Scenes if (string.Empty == m_assetServerURL) return base.GetAsset(uuid); else - return FetchAsset(m_assetServerURL, uuid); + return FetchAsset(uuid); } - public AssetBase FetchAsset(string url, UUID assetID) + public AssetBase FetchAsset(UUID assetID) { - if (!url.EndsWith("/") && !url.EndsWith("=")) - url = url + "/"; - AssetBase asset = m_assetService.Get(url + assetID.ToString()); - - if (asset != null) + // Test if it's already here + AssetBase asset = m_assetService.Get(assetID.ToString()); + if (asset == null) { - m_log.DebugFormat("[HGUUIDGatherer]: Copied asset {0} from {1} to local asset server. ", asset.ID, url); - return asset; + // It's not, so fetch it from abroad + asset = m_assetService.Get(m_assetServerURL + assetID.ToString()); + if (asset != null) + m_log.DebugFormat("[HGUUIDGatherer]: Copied asset {0} from {1} to local asset server", assetID, m_assetServerURL); + else + m_log.DebugFormat("[HGUUIDGatherer]: Failed to fetch asset {0} from {1}", assetID, m_assetServerURL); } - return null; + //else + // m_log.DebugFormat("[HGUUIDGatherer]: Asset {0} from {1} was already here", assetID, m_assetServerURL); + + return asset; } } } -- cgit v1.1 From 87d810217e2675880bec68891431bd5d422cb1b8 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Sat, 22 Sep 2012 14:01:51 -0700 Subject: Guard against inventory get failures. --- OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs | 3 +++ 1 file changed, 3 insertions(+) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs index d6ad07e..c74584c 100644 --- a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs @@ -859,6 +859,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments InventoryItemBase item = new InventoryItemBase(itemID, sp.UUID); item = m_scene.InventoryService.GetItem(item); + if (item == null) + return; + bool changed = sp.Appearance.SetAttachment((int)AttachmentPt, itemID, item.AssetID); if (changed && m_scene.AvatarFactory != null) { -- cgit v1.1 From 1c4233738123f1bcf3f9b45a527422cb09a43bcc Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Sat, 22 Sep 2012 14:41:19 -0700 Subject: HG Rez object: warn the user if the item or asset cannot be found. --- .../Framework/InventoryAccess/HGInventoryAccessModule.cs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs index a0cad40..80257bd 100644 --- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs +++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs @@ -263,8 +263,13 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess //} // OK, we're done fetching. Pass it up to the default RezObject - return base.RezObject(remoteClient, itemID, RayEnd, RayStart, RayTargetID, BypassRayCast, RayEndIsIntersection, - RezSelected, RemoveItem, fromTaskID, attachment); + SceneObjectGroup sog = base.RezObject(remoteClient, itemID, RayEnd, RayStart, RayTargetID, BypassRayCast, RayEndIsIntersection, + RezSelected, RemoveItem, fromTaskID, attachment); + + if (sog == null) + remoteClient.SendAgentAlertMessage("Unable to rez: problem accessing inventory or locating assets", false); + + return sog; } -- cgit v1.1 From 1cfd63d0b4bfdd1318d55b8d1c70ab25d101328d Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Sat, 22 Sep 2012 17:44:48 +0100 Subject: Documenting LSL script-related events --- OpenSim/Region/Framework/Scenes/EventManager.cs | 149 +++++++++++++++++++++++- 1 file changed, 147 insertions(+), 2 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Framework/Scenes/EventManager.cs b/OpenSim/Region/Framework/Scenes/EventManager.cs index 96e9797..22d395c 100644 --- a/OpenSim/Region/Framework/Scenes/EventManager.cs +++ b/OpenSim/Region/Framework/Scenes/EventManager.cs @@ -460,36 +460,170 @@ namespace OpenSim.Region.Framework.Scenes } /// + /// Triggered when some scene object properties change. + /// + /// /// ScriptChangedEvent is fired when a scene object property that a script might be interested /// in (such as color, scale or inventory) changes. Only enough information sent is for the LSL changed event. /// This is not an indication that the script has changed (see OnUpdateScript for that). /// This event is sent to a script to tell it that some property changed on /// the object the script is in. See http://lslwiki.net/lslwiki/wakka.php?wakka=changed . - /// + /// Triggered by + /// in , + /// + /// public event ScriptChangedEvent OnScriptChangedEvent; public delegate void ScriptChangedEvent(uint localID, uint change); public delegate void ScriptControlEvent(UUID item, UUID avatarID, uint held, uint changed); + + /// + /// Triggered when a script receives control input from an agent. + /// + /// + /// Triggered by + /// in + /// via + /// via + /// via + /// public event ScriptControlEvent OnScriptControlEvent; public delegate void ScriptAtTargetEvent(uint localID, uint handle, Vector3 targetpos, Vector3 atpos); + + /// + /// Triggered when an object has arrived within a tolerance distance + /// of a motion target. + /// + /// + /// Triggered by + /// in + /// via , + /// via + /// public event ScriptAtTargetEvent OnScriptAtTargetEvent; public delegate void ScriptNotAtTargetEvent(uint localID); + + /// + /// Triggered when an object has a motion target but has not arrived + /// within a tolerance distance. + /// + /// + /// Triggered by + /// in + /// via , + /// via + /// public event ScriptNotAtTargetEvent OnScriptNotAtTargetEvent; public delegate void ScriptAtRotTargetEvent(uint localID, uint handle, Quaternion targetrot, Quaternion atrot); + + /// + /// Triggered when an object has arrived within a tolerance rotation + /// of a rotation target. + /// + /// + /// Triggered by + /// in + /// via , + /// via + /// public event ScriptAtRotTargetEvent OnScriptAtRotTargetEvent; public delegate void ScriptNotAtRotTargetEvent(uint localID); + + /// + /// Triggered when an object has a rotation target but has not arrived + /// within a tolerance rotation. + /// + /// + /// Triggered by + /// in + /// via , + /// via + /// public event ScriptNotAtRotTargetEvent OnScriptNotAtRotTargetEvent; public delegate void ScriptColliding(uint localID, ColliderArgs colliders); + + /// + /// Triggered when a physical collision has started between a prim + /// and something other than the region terrain. + /// + /// + /// Triggered by + /// in + /// via + /// via + /// via + /// public event ScriptColliding OnScriptColliderStart; + + /// + /// Triggered when something that previously collided with a prim has + /// not stopped colliding with it. + /// + /// + /// + /// Triggered by + /// in + /// via + /// via + /// via + /// public event ScriptColliding OnScriptColliding; + + /// + /// Triggered when something that previously collided with a prim has + /// stopped colliding with it. + /// + /// + /// Triggered by + /// in + /// via + /// via + /// via + /// public event ScriptColliding OnScriptCollidingEnd; + + /// + /// Triggered when a physical collision has started between an object + /// and the region terrain. + /// + /// + /// Triggered by + /// in + /// via + /// via + /// via + /// public event ScriptColliding OnScriptLandColliderStart; + + /// + /// Triggered when an object that previously collided with the region + /// terrain has not yet stopped colliding with it. + /// + /// + /// Triggered by + /// in + /// via + /// via + /// via + /// public event ScriptColliding OnScriptLandColliding; + + /// + /// Triggered when an object that previously collided with the region + /// terrain has stopped colliding with it. + /// + /// + /// Triggered by + /// in + /// via + /// via + /// via + /// public event ScriptColliding OnScriptLandColliderEnd; public delegate void OnMakeChildAgentDelegate(ScenePresence presence); @@ -550,6 +684,13 @@ namespace OpenSim.Region.Framework.Scenes /* public delegate void ScriptTimerEvent(uint localID, double timerinterval); + /// + /// Used to be triggered when the LSL timer event fires. + /// + /// + /// Triggered by + /// via + /// public event ScriptTimerEvent OnScriptTimerEvent; */ @@ -2293,7 +2434,11 @@ namespace OpenSim.Region.Framework.Scenes } } - // this lets us keep track of nasty script events like timer, etc. + /// + /// this lets us keep track of nasty script events like timer, etc. + /// + /// + /// public void TriggerTimerEvent(uint objLocalID, double Interval) { throw new NotImplementedException("TriggerTimerEvent was thought to be not used anymore and the registration for the event from scene object part has been commented out due to a memory leak"); -- cgit v1.1 From 020103c51e4b8e340c44b2cfbe7826a95b041068 Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Sun, 23 Sep 2012 15:33:01 +0100 Subject: Documenting object-related events --- OpenSim/Region/Framework/Scenes/EventManager.cs | 43 +++++++++++++++++++++++++ 1 file changed, 43 insertions(+) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Framework/Scenes/EventManager.cs b/OpenSim/Region/Framework/Scenes/EventManager.cs index 22d395c..e25fa94 100644 --- a/OpenSim/Region/Framework/Scenes/EventManager.cs +++ b/OpenSim/Region/Framework/Scenes/EventManager.cs @@ -345,15 +345,58 @@ namespace OpenSim.Region.Framework.Scenes public event StopScript OnStopScript; public delegate bool SceneGroupMoved(UUID groupID, Vector3 delta); + + /// + /// Triggered when an object is moved. + /// + /// + /// Triggered by + /// in , + /// + /// public event SceneGroupMoved OnSceneGroupMove; public delegate void SceneGroupGrabed(UUID groupID, Vector3 offset, UUID userID); + + /// + /// Triggered when an object is grabbed. + /// + /// + /// Triggered by + /// in + /// via + /// via + /// via + /// via + /// public event SceneGroupGrabed OnSceneGroupGrab; public delegate bool SceneGroupSpinStarted(UUID groupID); + + /// + /// Triggered when an object starts to spin. + /// + /// + /// Triggered by + /// in + /// via + /// via + /// via + /// public event SceneGroupSpinStarted OnSceneGroupSpinStart; public delegate bool SceneGroupSpun(UUID groupID, Quaternion rotation); + + /// + /// Triggered when an object is being spun. + /// + /// + /// Triggered by + /// in + /// via + /// via + /// via + /// public event SceneGroupSpun OnSceneGroupSpin; public delegate void LandObjectAdded(ILandObject newParcel); -- cgit v1.1 From 4ec2fc4cc2a04ed673bc965d0ebc3f004c1734fc Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Tue, 25 Sep 2012 10:46:21 -0700 Subject: Deleted extraneous debug message --- OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs | 2 -- 1 file changed, 2 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs index 6f62856..f8ec6de 100644 --- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs +++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs @@ -233,8 +233,6 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess HGUuidGatherer uuidGatherer = new HGUuidGatherer(m_scene.AssetService, userAssetURL); uuidGatherer.GatherAssetUuids(assetID, (AssetType)meta.Type, ids); - m_log.DebugFormat("[HG ASSET MAPPER]: Successfully fetched asset {0} from asset server {1}", assetID, userAssetURL); - } -- cgit v1.1 From 4fc0cfba3ce1e6545e334f8e34a0e5b45274081e Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Tue, 25 Sep 2012 21:35:39 +0100 Subject: Fix occasional race condition failure when creating new clothing/body parts in the viewer or updating existing assets. On creating these items, the viewer sends a UDP AssetUploadRequest followed by a CreateInventoryItem. It was possible for the CreateInventoryItem/UpdateInventoryItem to occasionally outrace the AssetUploadRequest and fail to find an initialized Xfer object, at which point the item create would fail. So instead we always set up a Xfer object on either the asset or inventory item update request. This does not introduce a new race because code already exists to delay the item operation until the asset is uploaded if necessary (but this only worked if the xfer object already existed) --- .../AssetTransaction/AgentAssetsTransactions.cs | 123 +++++++-------------- .../AssetTransaction/AssetTransactionModule.cs | 9 +- .../Agent/AssetTransaction/AssetXferUploader.cs | 72 +++++++++--- 3 files changed, 94 insertions(+), 110 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs index b557ffe..bba7b9c 100644 --- a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs +++ b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs @@ -57,39 +57,36 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction } /// - /// Return a xfer uploader if one does not already exist. + /// Return the xfer uploader for the given transaction. /// + /// + /// If an uploader does not already exist for this transaction then it is created, otherwise the existing + /// uploader is returned. + /// /// - /// - /// We must transfer the new asset ID into the uploader on creation, otherwise - /// we can see race conditions with other threads which can retrieve an item before it is updated with the new - /// asset id. - /// - /// - /// The xfer uploader requested. Null if one is already in existence. - /// FIXME: This is a bizarre thing to do, and is probably meant to signal an error condition if multiple - /// transfers are made. Needs to be corrected. - /// - public AssetXferUploader RequestXferUploader(UUID transactionID, UUID assetID) + /// The asset xfer uploader + public AssetXferUploader RequestXferUploader(UUID transactionID) { + AssetXferUploader uploader; + lock (XferUploaders) { if (!XferUploaders.ContainsKey(transactionID)) { - AssetXferUploader uploader = new AssetXferUploader(this, m_Scene, assetID, m_dumpAssetsToFile); + uploader = new AssetXferUploader(this, m_Scene, m_dumpAssetsToFile); // m_log.DebugFormat( // "[AGENT ASSETS TRANSACTIONS]: Adding asset xfer uploader {0} since it didn't previously exist", transactionID); XferUploaders.Add(transactionID, uploader); - - return uploader; + } + else + { + uploader = XferUploaders[transactionID]; } } - m_log.WarnFormat("[AGENT ASSETS TRANSACTIONS]: Ignoring request for asset xfer uploader {0} since it already exists", transactionID); - - return null; + return uploader; } public void HandleXfer(ulong xferID, uint packetID, byte[] data) @@ -151,23 +148,11 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction string description, string name, sbyte invType, sbyte type, byte wearableType, uint nextOwnerMask) { - AssetXferUploader uploader = null; + AssetXferUploader uploader = RequestXferUploader(transactionID); - lock (XferUploaders) - { - if (XferUploaders.ContainsKey(transactionID)) - uploader = XferUploaders[transactionID]; - } - - if (uploader != null) - uploader.RequestCreateInventoryItem( - remoteClient, transactionID, folderID, - callbackID, description, name, invType, type, - wearableType, nextOwnerMask); - else - m_log.ErrorFormat( - "[AGENT ASSET TRANSACTIONS]: Could not find uploader with transaction ID {0} when handling request to create inventory item {1} from {2}", - transactionID, name, remoteClient.Name); + uploader.RequestCreateInventoryItem( + remoteClient, transactionID, folderID, callbackID, + description, name, invType, type, wearableType, nextOwnerMask); } /// @@ -197,69 +182,37 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction SceneObjectPart part, UUID transactionID, TaskInventoryItem item) { - AssetXferUploader uploader = null; + AssetBase asset = GetTransactionAsset(transactionID); - lock (XferUploaders) - { - if (XferUploaders.ContainsKey(transactionID)) - uploader = XferUploaders[transactionID]; - } + // Only legacy viewers use this, and they prefer CAPS, which + // we have, so this really never runs. + // Allow it, but only for "safe" types. + if ((InventoryType)item.InvType != InventoryType.Notecard && + (InventoryType)item.InvType != InventoryType.LSL) + return; - if (uploader != null) + if (asset != null) { - AssetBase asset = GetTransactionAsset(transactionID); - - // Only legacy viewers use this, and they prefer CAPS, which - // we have, so this really never runs. - // Allow it, but only for "safe" types. - if ((InventoryType)item.InvType != InventoryType.Notecard && - (InventoryType)item.InvType != InventoryType.LSL) - return; - - if (asset != null) - { // m_log.DebugFormat( // "[AGENT ASSETS TRANSACTIONS]: Updating item {0} in {1} for transaction {2}", // item.Name, part.Name, transactionID); - - asset.FullID = UUID.Random(); - asset.Name = item.Name; - asset.Description = item.Description; - asset.Type = (sbyte)item.Type; - item.AssetID = asset.FullID; - - m_Scene.AssetService.Store(asset); - } - } - else - { - m_log.ErrorFormat( - "[AGENT ASSET TRANSACTIONS]: Could not find uploader with transaction ID {0} when handling request to update task inventory item {1} in {2}", - transactionID, item.Name, part.Name); + + asset.FullID = UUID.Random(); + asset.Name = item.Name; + asset.Description = item.Description; + asset.Type = (sbyte)item.Type; + item.AssetID = asset.FullID; + + m_Scene.AssetService.Store(asset); } } public void RequestUpdateInventoryItem(IClientAPI remoteClient, UUID transactionID, InventoryItemBase item) { - AssetXferUploader uploader = null; - - lock (XferUploaders) - { - if (XferUploaders.ContainsKey(transactionID)) - uploader = XferUploaders[transactionID]; - } + AssetXferUploader uploader = RequestXferUploader(transactionID); - if (uploader != null) - { - uploader.RequestUpdateInventoryItem(remoteClient, transactionID, item); - } - else - { - m_log.ErrorFormat( - "[AGENT ASSET TRANSACTIONS]: Could not find uploader with transaction ID {0} when handling request to update inventory item {1} for {2}", - transactionID, item.Name, remoteClient.Name); - } + uploader.RequestUpdateInventoryItem(remoteClient, transactionID, item); } } -} +} \ No newline at end of file diff --git a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetTransactionModule.cs b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetTransactionModule.cs index 7081989..10a0794 100644 --- a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetTransactionModule.cs +++ b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetTransactionModule.cs @@ -274,13 +274,8 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction } AgentAssetTransactions transactions = GetUserTransactions(remoteClient.AgentId); - AssetXferUploader uploader = transactions.RequestXferUploader(transaction, assetID); - - if (uploader != null) - { - uploader.Initialise(remoteClient, assetID, transaction, type, - data, storeLocal, tempFile); - } + AssetXferUploader uploader = transactions.RequestXferUploader(transaction); + uploader.StartUpload(remoteClient, assetID, transaction, type, data, storeLocal, tempFile); } /// diff --git a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs index ec4dfd0..9f05120 100644 --- a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs +++ b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs @@ -41,11 +41,26 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); /// + /// Upload state. + /// + /// + /// New -> Uploading -> Complete + /// + private enum UploadState + { + New, + Uploading, + Complete + } + + /// /// Reference to the object that holds this uploader. Used to remove ourselves from it's list if we /// are performing a delayed update. /// AgentAssetTransactions m_transactions; + private UploadState m_uploadState = UploadState.New; + private AssetBase m_asset; private UUID InventFolder = UUID.Zero; private sbyte invType = 0; @@ -57,7 +72,6 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction private string m_description = String.Empty; private bool m_dumpAssetToFile; - private bool m_finished = false; private string m_name = String.Empty; private bool m_storeLocal; private uint nextPerm = 0; @@ -68,11 +82,10 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction public ulong XferID; private Scene m_Scene; - public AssetXferUploader(AgentAssetTransactions transactions, Scene scene, UUID assetID, bool dumpAssetToFile) + public AssetXferUploader(AgentAssetTransactions transactions, Scene scene, bool dumpAssetToFile) { m_transactions = transactions; m_Scene = scene; - m_asset = new AssetBase() { FullID = assetID }; m_dumpAssetToFile = dumpAssetToFile; } @@ -118,20 +131,43 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction } /// - /// Initialise asset transfer from the client + /// Start asset transfer from the client /// - /// - /// - /// - public void Initialise(IClientAPI remoteClient, UUID assetID, - UUID transaction, sbyte type, byte[] data, bool storeLocal, - bool tempFile) + /// + /// + /// + /// + /// + /// Optional data. If present then the asset is created immediately with this data + /// rather than requesting an upload from the client. The data must be longer than 2 bytes. + /// + /// + /// + public void StartUpload( + IClientAPI remoteClient, UUID assetID, UUID transaction, sbyte type, byte[] data, bool storeLocal, + bool tempFile) { // m_log.DebugFormat( // "[ASSET XFER UPLOADER]: Initialised xfer from {0}, asset {1}, transaction {2}, type {3}, storeLocal {4}, tempFile {5}, already received data length {6}", // remoteClient.Name, assetID, transaction, type, storeLocal, tempFile, data.Length); + lock (this) + { + if (m_uploadState != UploadState.New) + { + m_log.WarnFormat( + "[ASSET XFER UPLOADER]: Tried to start upload of asset {0}, transaction {1} for {2} but this is already in state {3}. Aborting.", + assetID, transaction, remoteClient.Name, m_uploadState); + + return; + } + + m_uploadState = UploadState.Uploading; + } + ourClient = remoteClient; + + m_asset = new AssetBase() { FullID = assetID }; m_asset.Name = "blank"; m_asset.Description = "empty"; m_asset.Type = type; @@ -166,14 +202,14 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction protected void SendCompleteMessage() { - ourClient.SendAssetUploadCompleteMessage(m_asset.Type, true, - m_asset.FullID); - // We must lock in order to avoid a race with a separate thread dealing with an inventory item or create // message from other client UDP. lock (this) { - m_finished = true; + m_uploadState = UploadState.Complete; + + ourClient.SendAssetUploadCompleteMessage(m_asset.Type, true, m_asset.FullID); + if (m_createItem) { DoCreateItem(m_createItemCallback); @@ -243,7 +279,7 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction // We must lock to avoid a race with a separate thread uploading the asset. lock (this) { - if (m_finished) + if (m_uploadState == UploadState.Complete) { DoCreateItem(callbackID); } @@ -271,7 +307,7 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction item.AssetID = m_asset.FullID; m_Scene.InventoryService.UpdateItem(item); - if (m_finished) + if (m_uploadState == UploadState.Complete) { StoreAssetForItemUpdate(item); } @@ -334,7 +370,7 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction /// null if the asset has not finished uploading public AssetBase GetAssetData() { - if (m_finished) + if (m_uploadState == UploadState.Complete) { return m_asset; } @@ -342,4 +378,4 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction return null; } } -} +} \ No newline at end of file -- cgit v1.1 From 2f795e4fa6433269748f4e062d4bba7197e46ab1 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Tue, 25 Sep 2012 22:08:11 +0100 Subject: Move UDP update task item code to AssetXferUploader to match existing create user item and update user item mechanisms This is done for consistency and to allow removal or some access methods that increase code complexity. However, this path has not been used for a long time, not even by LL 1.23 - viewers use caps http upload for this instead --- .../AssetTransaction/AgentAssetsTransactions.cs | 47 +-------------- .../AssetTransaction/AssetTransactionModule.cs | 2 +- .../Agent/AssetTransaction/AssetXferUploader.cs | 67 ++++++++++++++++------ 3 files changed, 52 insertions(+), 64 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs index bba7b9c..59d0075 100644 --- a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs +++ b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs @@ -155,56 +155,13 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction description, name, invType, type, wearableType, nextOwnerMask); } - /// - /// Get an uploaded asset. If the data is successfully retrieved, - /// the transaction will be removed. - /// - /// - /// The asset if the upload has completed, null if it has not. - private AssetBase GetTransactionAsset(UUID transactionID) - { - lock (XferUploaders) - { - if (XferUploaders.ContainsKey(transactionID)) - { - AssetXferUploader uploader = XferUploaders[transactionID]; - AssetBase asset = uploader.GetAssetData(); - RemoveXferUploader(transactionID); - - return asset; - } - } - - return null; - } - public void RequestUpdateTaskInventoryItem(IClientAPI remoteClient, SceneObjectPart part, UUID transactionID, TaskInventoryItem item) { - AssetBase asset = GetTransactionAsset(transactionID); - - // Only legacy viewers use this, and they prefer CAPS, which - // we have, so this really never runs. - // Allow it, but only for "safe" types. - if ((InventoryType)item.InvType != InventoryType.Notecard && - (InventoryType)item.InvType != InventoryType.LSL) - return; + AssetXferUploader uploader = RequestXferUploader(transactionID); - if (asset != null) - { -// m_log.DebugFormat( -// "[AGENT ASSETS TRANSACTIONS]: Updating item {0} in {1} for transaction {2}", -// item.Name, part.Name, transactionID); - - asset.FullID = UUID.Random(); - asset.Name = item.Name; - asset.Description = item.Description; - asset.Type = (sbyte)item.Type; - item.AssetID = asset.FullID; - - m_Scene.AssetService.Store(asset); - } + uploader.RequestUpdateTaskInventoryItem(remoteClient, transactionID, item); } public void RequestUpdateInventoryItem(IClientAPI remoteClient, diff --git a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetTransactionModule.cs b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetTransactionModule.cs index 10a0794..73d1f72 100644 --- a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetTransactionModule.cs +++ b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetTransactionModule.cs @@ -215,7 +215,7 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction IClientAPI remoteClient, SceneObjectPart part, UUID transactionID, TaskInventoryItem item) { m_log.DebugFormat( - "[TRANSACTIONS MANAGER] Called HandleTaskItemUpdateFromTransaction with item {0} in {1} for {2} in {3}", + "[ASSET TRANSACTION MODULE] Called HandleTaskItemUpdateFromTransaction with item {0} in {1} for {2} in {3}", item.Name, part.Name, remoteClient.Name, m_Scene.RegionInfo.RegionName); AgentAssetTransactions transactions = diff --git a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs index 9f05120..08c3134 100644 --- a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs +++ b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs @@ -65,11 +65,15 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction private UUID InventFolder = UUID.Zero; private sbyte invType = 0; - private bool m_createItem = false; - private uint m_createItemCallback = 0; - private bool m_updateItem = false; + private bool m_createItem; + private uint m_createItemCallback; + + private bool m_updateItem; private InventoryItemBase m_updateItemData; + private bool m_updateTaskItem; + private TaskInventoryItem m_updateTaskItemData; + private string m_description = String.Empty; private bool m_dumpAssetToFile; private string m_name = String.Empty; @@ -223,6 +227,12 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction // TODO: Should probably do the same for create item. m_transactions.RemoveXferUploader(TransactionID); } + else if (m_updateTaskItem) + { + StoreAssetForTaskItemUpdate(m_updateTaskItemData); + + m_transactions.RemoveXferUploader(TransactionID); + } else if (m_storeLocal) { m_Scene.AssetService.Store(m_asset); @@ -323,8 +333,30 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction } } + public void RequestUpdateTaskInventoryItem(IClientAPI remoteClient, UUID transactionID, TaskInventoryItem taskItem) + { + // We must lock to avoid a race with a separate thread uploading the asset. + lock (this) + { + m_asset.Name = taskItem.Name; + m_asset.Description = taskItem.Description; + m_asset.Type = (sbyte)taskItem.Type; + taskItem.AssetID = m_asset.FullID; + + if (m_uploadState == UploadState.Complete) + { + StoreAssetForTaskItemUpdate(taskItem); + } + else + { + m_updateTaskItem = true; + m_updateTaskItemData = taskItem; + } + } + } + /// - /// Store the asset for the given item. + /// Store the asset for the given item when it has been uploaded. /// /// private void StoreAssetForItemUpdate(InventoryItemBase item) @@ -336,6 +368,19 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction m_Scene.AssetService.Store(m_asset); } + /// + /// Store the asset for the given task item when it has been uploaded. + /// + /// + private void StoreAssetForTaskItemUpdate(TaskInventoryItem taskItem) + { +// m_log.DebugFormat( +// "[ASSET XFER UPLOADER]: Storing asset {0} for earlier task item update for {1} for {2}", +// m_asset.FullID, taskItem.Name, ourClient.Name); + + m_Scene.AssetService.Store(m_asset); + } + private void DoCreateItem(uint callbackID) { m_Scene.AssetService.Store(m_asset); @@ -363,19 +408,5 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction else ourClient.SendAlertMessage("Unable to create inventory item"); } - - /// - /// Get the asset data uploaded in this transfer. - /// - /// null if the asset has not finished uploading - public AssetBase GetAssetData() - { - if (m_uploadState == UploadState.Complete) - { - return m_asset; - } - - return null; - } } } \ No newline at end of file -- cgit v1.1 From eb5bec96e49466ede4ece376cb15cd68477ce983 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Tue, 25 Sep 2012 22:54:20 +0100 Subject: Insert transaction ID into AssetXferUploader constructor rather than at UploadAsset() to prevent item creation failure when NewInventoryItem thread reachs the object first. This was preventing the previous race condition fix in 4fc0cfb from actually working. This commit also removes some of the pointless transaction id checks - these conditions are already being enforced in AgentAssetsTransactions. --- .../AssetTransaction/AgentAssetsTransactions.cs | 8 +-- .../Agent/AssetTransaction/AssetXferUploader.cs | 77 +++++++++++++--------- 2 files changed, 49 insertions(+), 36 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs index 59d0075..0271738 100644 --- a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs +++ b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs @@ -73,7 +73,7 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction { if (!XferUploaders.ContainsKey(transactionID)) { - uploader = new AssetXferUploader(this, m_Scene, m_dumpAssetsToFile); + uploader = new AssetXferUploader(this, m_Scene, transactionID, m_dumpAssetsToFile); // m_log.DebugFormat( // "[AGENT ASSETS TRANSACTIONS]: Adding asset xfer uploader {0} since it didn't previously exist", transactionID); @@ -151,7 +151,7 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction AssetXferUploader uploader = RequestXferUploader(transactionID); uploader.RequestCreateInventoryItem( - remoteClient, transactionID, folderID, callbackID, + remoteClient, folderID, callbackID, description, name, invType, type, wearableType, nextOwnerMask); } @@ -161,7 +161,7 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction { AssetXferUploader uploader = RequestXferUploader(transactionID); - uploader.RequestUpdateTaskInventoryItem(remoteClient, transactionID, item); + uploader.RequestUpdateTaskInventoryItem(remoteClient, item); } public void RequestUpdateInventoryItem(IClientAPI remoteClient, @@ -169,7 +169,7 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction { AssetXferUploader uploader = RequestXferUploader(transactionID); - uploader.RequestUpdateInventoryItem(remoteClient, transactionID, item); + uploader.RequestUpdateInventoryItem(remoteClient, item); } } } \ No newline at end of file diff --git a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs index 08c3134..52d7d57 100644 --- a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs +++ b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs @@ -80,15 +80,32 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction private bool m_storeLocal; private uint nextPerm = 0; private IClientAPI ourClient; - private UUID TransactionID = UUID.Zero; + + private UUID m_transactionID; + private sbyte type = 0; private byte wearableType = 0; public ulong XferID; private Scene m_Scene; - public AssetXferUploader(AgentAssetTransactions transactions, Scene scene, bool dumpAssetToFile) + /// + /// AssetXferUploader constructor + /// + /// /param> + /// + /// + /// + /// If true then when the asset is uploaded it is dumped to a file with the format + /// String.Format("{6}_{7}_{0:d2}{1:d2}{2:d2}_{3:d2}{4:d2}{5:d2}.dat", + /// now.Year, now.Month, now.Day, now.Hour, now.Minute, + /// now.Second, m_asset.Name, m_asset.Type); + /// for debugging purposes. + /// + public AssetXferUploader( + AgentAssetTransactions transactions, Scene scene, UUID transactionID, bool dumpAssetToFile) { m_transactions = transactions; + m_transactionID = transactionID; m_Scene = scene; m_dumpAssetToFile = dumpAssetToFile; } @@ -180,7 +197,6 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction m_asset.Local = storeLocal; m_asset.Temporary = tempFile; - TransactionID = transaction; m_storeLocal = storeLocal; if (m_asset.Data.Length > 2) @@ -225,13 +241,13 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction // Remove ourselves from the list of transactions if completion was delayed until the transaction // was complete. // TODO: Should probably do the same for create item. - m_transactions.RemoveXferUploader(TransactionID); + m_transactions.RemoveXferUploader(m_transactionID); } else if (m_updateTaskItem) { StoreAssetForTaskItemUpdate(m_updateTaskItemData); - m_transactions.RemoveXferUploader(TransactionID); + m_transactions.RemoveXferUploader(m_transactionID); } else if (m_storeLocal) { @@ -241,7 +257,7 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction m_log.DebugFormat( "[ASSET XFER UPLOADER]: Uploaded asset {0} for transaction {1}", - m_asset.FullID, TransactionID); + m_asset.FullID, m_transactionID); if (m_dumpAssetToFile) { @@ -269,40 +285,37 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction } public void RequestCreateInventoryItem(IClientAPI remoteClient, - UUID transactionID, UUID folderID, uint callbackID, + UUID folderID, uint callbackID, string description, string name, sbyte invType, sbyte type, byte wearableType, uint nextOwnerMask) { - if (TransactionID == transactionID) + InventFolder = folderID; + m_name = name; + m_description = description; + this.type = type; + this.invType = invType; + this.wearableType = wearableType; + nextPerm = nextOwnerMask; + m_asset.Name = name; + m_asset.Description = description; + m_asset.Type = type; + + // We must lock to avoid a race with a separate thread uploading the asset. + lock (this) { - InventFolder = folderID; - m_name = name; - m_description = description; - this.type = type; - this.invType = invType; - this.wearableType = wearableType; - nextPerm = nextOwnerMask; - m_asset.Name = name; - m_asset.Description = description; - m_asset.Type = type; - - // We must lock to avoid a race with a separate thread uploading the asset. - lock (this) + if (m_uploadState == UploadState.Complete) + { + DoCreateItem(callbackID); + } + else { - if (m_uploadState == UploadState.Complete) - { - DoCreateItem(callbackID); - } - else - { - m_createItem = true; //set flag so the inventory item is created when upload is complete - m_createItemCallback = callbackID; - } + m_createItem = true; //set flag so the inventory item is created when upload is complete + m_createItemCallback = callbackID; } } } - public void RequestUpdateInventoryItem(IClientAPI remoteClient, UUID transactionID, InventoryItemBase item) + public void RequestUpdateInventoryItem(IClientAPI remoteClient, InventoryItemBase item) { // We must lock to avoid a race with a separate thread uploading the asset. lock (this) @@ -333,7 +346,7 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction } } - public void RequestUpdateTaskInventoryItem(IClientAPI remoteClient, UUID transactionID, TaskInventoryItem taskItem) + public void RequestUpdateTaskInventoryItem(IClientAPI remoteClient, TaskInventoryItem taskItem) { // We must lock to avoid a race with a separate thread uploading the asset. lock (this) -- cgit v1.1 From b96a53962b86083476b78498278868ce8152ddd8 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Tue, 25 Sep 2012 23:12:28 +0100 Subject: Comment out old m_storeLocal from AssetXferUploader. This was only used if none of new item, update item or update task item had been set. But since all transactions go through these paths this old code is redundant. --- .../CoreModules/Agent/AssetTransaction/AssetXferUploader.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs index 52d7d57..8d21202 100644 --- a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs +++ b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs @@ -77,7 +77,7 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction private string m_description = String.Empty; private bool m_dumpAssetToFile; private string m_name = String.Empty; - private bool m_storeLocal; +// private bool m_storeLocal; private uint nextPerm = 0; private IClientAPI ourClient; @@ -197,7 +197,7 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction m_asset.Local = storeLocal; m_asset.Temporary = tempFile; - m_storeLocal = storeLocal; +// m_storeLocal = storeLocal; if (m_asset.Data.Length > 2) { @@ -249,10 +249,10 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction m_transactions.RemoveXferUploader(m_transactionID); } - else if (m_storeLocal) - { - m_Scene.AssetService.Store(m_asset); - } +// else if (m_storeLocal) +// { +// m_Scene.AssetService.Store(m_asset); +// } } m_log.DebugFormat( -- cgit v1.1 From ddd9384b3901f532243c1e8018334385b84290d1 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Tue, 25 Sep 2012 23:30:25 +0100 Subject: Fix very recently introduced race condition where a CreateNewItem outracing an UploadAsset request could throw an exception because m_asset did not yet exist. This was accidentally introduced in 4fc0cfb This commit also consistently removes the AssetXferUploader when the transaction completes, no matter if it completed on asset upload or item operation. The amount of data being retained was small, since this was clothing/bodypart metadata in the asset rather than textures themselves. --- .../Agent/AssetTransaction/AssetXferUploader.cs | 37 +++++++++++----------- 1 file changed, 18 insertions(+), 19 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs index 8d21202..8add4bb 100644 --- a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs +++ b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs @@ -104,6 +104,8 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction public AssetXferUploader( AgentAssetTransactions transactions, Scene scene, UUID transactionID, bool dumpAssetToFile) { + m_asset = new AssetBase(); + m_transactions = transactions; m_transactionID = transactionID; m_Scene = scene; @@ -188,9 +190,7 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction ourClient = remoteClient; - m_asset = new AssetBase() { FullID = assetID }; - m_asset.Name = "blank"; - m_asset.Description = "empty"; + m_asset.FullID = assetID; m_asset.Type = type; m_asset.CreatorID = remoteClient.AgentId.ToString(); m_asset.Data = data; @@ -232,22 +232,15 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction if (m_createItem) { - DoCreateItem(m_createItemCallback); + CompleteCreateItem(m_createItemCallback); } else if (m_updateItem) { - StoreAssetForItemUpdate(m_updateItemData); - - // Remove ourselves from the list of transactions if completion was delayed until the transaction - // was complete. - // TODO: Should probably do the same for create item. - m_transactions.RemoveXferUploader(m_transactionID); + CompleteItemUpdate(m_updateItemData); } else if (m_updateTaskItem) { - StoreAssetForTaskItemUpdate(m_updateTaskItemData); - - m_transactions.RemoveXferUploader(m_transactionID); + CompleteTaskItemUpdate(m_updateTaskItemData); } // else if (m_storeLocal) // { @@ -305,7 +298,7 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction { if (m_uploadState == UploadState.Complete) { - DoCreateItem(callbackID); + CompleteCreateItem(callbackID); } else { @@ -332,7 +325,7 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction if (m_uploadState == UploadState.Complete) { - StoreAssetForItemUpdate(item); + CompleteItemUpdate(item); } else { @@ -358,7 +351,7 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction if (m_uploadState == UploadState.Complete) { - StoreAssetForTaskItemUpdate(taskItem); + CompleteTaskItemUpdate(taskItem); } else { @@ -372,29 +365,33 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction /// Store the asset for the given item when it has been uploaded. /// /// - private void StoreAssetForItemUpdate(InventoryItemBase item) + private void CompleteItemUpdate(InventoryItemBase item) { // m_log.DebugFormat( // "[ASSET XFER UPLOADER]: Storing asset {0} for earlier item update for {1} for {2}", // m_asset.FullID, item.Name, ourClient.Name); m_Scene.AssetService.Store(m_asset); + + m_transactions.RemoveXferUploader(m_transactionID); } /// /// Store the asset for the given task item when it has been uploaded. /// /// - private void StoreAssetForTaskItemUpdate(TaskInventoryItem taskItem) + private void CompleteTaskItemUpdate(TaskInventoryItem taskItem) { // m_log.DebugFormat( // "[ASSET XFER UPLOADER]: Storing asset {0} for earlier task item update for {1} for {2}", // m_asset.FullID, taskItem.Name, ourClient.Name); m_Scene.AssetService.Store(m_asset); + + m_transactions.RemoveXferUploader(m_transactionID); } - private void DoCreateItem(uint callbackID) + private void CompleteCreateItem(uint callbackID) { m_Scene.AssetService.Store(m_asset); @@ -420,6 +417,8 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction ourClient.SendInventoryItemCreateUpdate(item, callbackID); else ourClient.SendAlertMessage("Unable to create inventory item"); + + m_transactions.RemoveXferUploader(m_transactionID); } } } \ No newline at end of file -- cgit v1.1 From 495a3e7daf95c65a1a0e39aaf85c6c66a62424c7 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Tue, 25 Sep 2012 19:54:42 -0700 Subject: Oops, that should be inside the curly bracket. --- .../CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs index a6698e6..e46dfeb 100644 --- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs +++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs @@ -106,7 +106,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer return m_ExportedAppearances; } } - #region ISharedRegionModule @@ -149,9 +148,10 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer base.AddRegion(scene); if (m_Enabled) + { scene.RegisterModuleInterface(this); - - scene.EventManager.OnIncomingSceneObject += OnIncomingSceneObject; + scene.EventManager.OnIncomingSceneObject += OnIncomingSceneObject; + } } void OnIncomingSceneObject(SceneObjectGroup so) -- cgit v1.1 From ae58cf42242433c786162b53a2724962f4a8380b Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Tue, 25 Sep 2012 20:03:49 -0700 Subject: TOS module. WARNING: migration in GridUser table. --- .../GridUser/ActivityDetector.cs | 13 +++++- .../GridUser/RemoteGridUserServiceConnector.cs | 46 ++++++++++++++++++++-- 2 files changed, 54 insertions(+), 5 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/ActivityDetector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/ActivityDetector.cs index b0edce7..dd8a8ef 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/ActivityDetector.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/ActivityDetector.cs @@ -68,8 +68,11 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.GridUser // m_log.DebugFormat("[ACTIVITY DETECTOR]: Detected root presence {0} in {1}", sp.UUID, sp.Scene.RegionInfo.RegionName); if (sp.PresenceType != PresenceType.Npc) + { + string userid = sp.Scene.UserManagementModule.GetUserUUI(sp.UUID); m_GridUserService.SetLastPosition( - sp.UUID.ToString(), UUID.Zero, sp.Scene.RegionInfo.RegionID, sp.AbsolutePosition, sp.Lookat); + userid, UUID.Zero, sp.Scene.RegionInfo.RegionID, sp.AbsolutePosition, sp.Lookat); + } } public void OnNewClient(IClientAPI client) @@ -83,8 +86,14 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.GridUser return; // m_log.DebugFormat("[ACTIVITY DETECTOR]: Detected client logout {0} in {1}", client.AgentId, client.Scene.RegionInfo.RegionName); + string userId = client.AgentId.ToString(); + if (client.Scene is Scene) + { + Scene s = (Scene)client.Scene; + userId = s.UserManagementModule.GetUserUUI(client.AgentId); + } m_GridUserService.LoggedOut( - client.AgentId.ToString(), client.SessionId, client.Scene.RegionInfo.RegionID, + userId, client.SessionId, client.Scene.RegionInfo.RegionID, client.SceneAgent.AbsolutePosition, client.SceneAgent.Lookat); } } diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/RemoteGridUserServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/RemoteGridUserServiceConnector.cs index badb552..04acf67 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/RemoteGridUserServiceConnector.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/RemoteGridUserServiceConnector.cs @@ -44,6 +44,9 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.GridUser { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + private const int KEEPTIME = 30; // 30 secs + private ExpiringCache m_Infos = new ExpiringCache(); + #region ISharedRegionModule private bool m_Enabled = false; @@ -128,23 +131,60 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.GridUser public bool LoggedOut(string userID, UUID sessionID, UUID region, Vector3 position, Vector3 lookat) { + if (m_Infos.Contains(userID)) + m_Infos.Remove(userID); + return m_RemoteConnector.LoggedOut(userID, sessionID, region, position, lookat); } public bool SetHome(string userID, UUID regionID, Vector3 position, Vector3 lookAt) { - return m_RemoteConnector.SetHome(userID, regionID, position, lookAt); + if (m_RemoteConnector.SetHome(userID, regionID, position, lookAt)) + { + // Update the cache too + GridUserInfo info = null; + if (m_Infos.TryGetValue(userID, out info)) + { + info.HomeRegionID = regionID; + info.HomePosition = position; + info.HomeLookAt = lookAt; + } + return true; + } + + return false; } public bool SetLastPosition(string userID, UUID sessionID, UUID regionID, Vector3 position, Vector3 lookAt) { - return m_RemoteConnector.SetLastPosition(userID, sessionID, regionID, position, lookAt); + if (m_RemoteConnector.SetLastPosition(userID, sessionID, regionID, position, lookAt)) + { + // Update the cache too + GridUserInfo info = null; + if (m_Infos.TryGetValue(userID, out info)) + { + info.LastRegionID = regionID; + info.LastPosition = position; + info.LastLookAt = lookAt; + } + return true; + } + + return false; } public GridUserInfo GetGridUserInfo(string userID) { - return m_RemoteConnector.GetGridUserInfo(userID); + GridUserInfo info = null; + if (m_Infos.TryGetValue(userID, out info)) + return info; + + info = m_RemoteConnector.GetGridUserInfo(userID); + + m_Infos.AddOrUpdate(userID, info, KEEPTIME); + + return info; } public GridUserInfo[] GetGridUserInfo(string[] userID) -- cgit v1.1 From 2f61763923b41c48cea96e76ef691ec63b529a7d Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Wed, 26 Sep 2012 11:26:51 -0700 Subject: Not really a change, just added a reminder to fix something here. --- .../CoreModules/Framework/UserManagement/HGUserManagementModule.cs | 3 +++ 1 file changed, 3 insertions(+) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/Framework/UserManagement/HGUserManagementModule.cs b/OpenSim/Region/CoreModules/Framework/UserManagement/HGUserManagementModule.cs index 4eecaa2..acefc97 100644 --- a/OpenSim/Region/CoreModules/Framework/UserManagement/HGUserManagementModule.cs +++ b/OpenSim/Region/CoreModules/Framework/UserManagement/HGUserManagementModule.cs @@ -137,6 +137,9 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement ud.FirstName = words[0]; ud.LastName = "@" + words[1]; users.Add(ud); + // WARNING! that uriStr is not quite right... it may be missing the / at the end, + // which will cause trouble (duplicate entries on some tables). We should + // get the UUI instead from the UAS. TO BE FIXED. AddUser(userID, names[0], names[1], uriStr); m_log.DebugFormat("[USER MANAGEMENT MODULE]: User {0}@{1} found", words[0], words[1]); } -- cgit v1.1 From 80133f9ebe353fe7c9542533c84a957aa96cf70a Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Wed, 26 Sep 2012 11:27:31 -0700 Subject: Show the user's home url too on the console command. --- .../CoreModules/Framework/UserManagement/UserManagementModule.cs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs b/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs index f4ed67b..36c84c7 100644 --- a/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs +++ b/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs @@ -429,8 +429,7 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement public void AddUser(UUID uuid, string first, string last, string homeURL) { - // m_log.DebugFormat("[USER MANAGEMENT MODULE]: Adding user with id {0}, first {1}, last {2}, url {3}", uuid, first, last, homeURL); - + //m_log.DebugFormat("[USER MANAGEMENT MODULE]: Adding user with id {0}, first {1}, last {2}, url {3}", uuid, first, last, homeURL); AddUser(uuid, homeURL + ";" + first + " " + last); } @@ -553,8 +552,8 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement MainConsole.Instance.Output("-----------------------------------------------------------------------------"); foreach (KeyValuePair kvp in m_UserCache) { - MainConsole.Instance.Output(String.Format("{0} {1} {2}", - kvp.Key, kvp.Value.FirstName, kvp.Value.LastName)); + MainConsole.Instance.Output(String.Format("{0} {1} {2} ({3})", + kvp.Key, kvp.Value.FirstName, kvp.Value.LastName, kvp.Value.HomeURL)); } return; -- cgit v1.1 From 3c77b8f463a852aecf3cb29fe4e5f4614f474dbf Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Wed, 26 Sep 2012 12:40:41 -0700 Subject: Use GridUser properly for foreign users. --- .../CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs | 2 ++ .../CoreModules/ServiceConnectorsOut/GridUser/ActivityDetector.cs | 6 +++--- 2 files changed, 5 insertions(+), 3 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs index e46dfeb..aa1e127 100644 --- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs +++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs @@ -245,6 +245,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer { // Log them out of this grid Scene.PresenceService.LogoutAgent(sp.ControllingClient.SessionId); + string userId = Scene.UserManagementModule.GetUserUUI(sp.UUID); + Scene.GridUserService.LoggedOut(userId, UUID.Zero, Scene.RegionInfo.RegionID, sp.AbsolutePosition, sp.Lookat); } } diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/ActivityDetector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/ActivityDetector.cs index dd8a8ef..221f815 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/ActivityDetector.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/ActivityDetector.cs @@ -65,11 +65,10 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.GridUser public void OnMakeRootAgent(ScenePresence sp) { -// m_log.DebugFormat("[ACTIVITY DETECTOR]: Detected root presence {0} in {1}", sp.UUID, sp.Scene.RegionInfo.RegionName); - if (sp.PresenceType != PresenceType.Npc) { string userid = sp.Scene.UserManagementModule.GetUserUUI(sp.UUID); + //m_log.DebugFormat("[ACTIVITY DETECTOR]: Detected root presence {0} in {1}", userid, sp.Scene.RegionInfo.RegionName); m_GridUserService.SetLastPosition( userid, UUID.Zero, sp.Scene.RegionInfo.RegionID, sp.AbsolutePosition, sp.Lookat); } @@ -85,13 +84,14 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.GridUser if (client.SceneAgent.IsChildAgent) return; -// m_log.DebugFormat("[ACTIVITY DETECTOR]: Detected client logout {0} in {1}", client.AgentId, client.Scene.RegionInfo.RegionName); string userId = client.AgentId.ToString(); if (client.Scene is Scene) { Scene s = (Scene)client.Scene; userId = s.UserManagementModule.GetUserUUI(client.AgentId); } + //m_log.DebugFormat("[ACTIVITY DETECTOR]: Detected client logout {0} in {1}", userId, client.Scene.RegionInfo.RegionName); + m_GridUserService.LoggedOut( userId, client.SessionId, client.Scene.RegionInfo.RegionID, client.SceneAgent.AbsolutePosition, client.SceneAgent.Lookat); -- cgit v1.1 From 90dd5844d64643246fb8bccf356614eb7e07d61c Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Wed, 26 Sep 2012 21:28:43 +0100 Subject: Add basic undo/redo regression tests. --- OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | 12 +- .../Scenes/Tests/SceneObjectUndoRedoTests.cs | 130 +++++++++++++++++++++ .../Scenes/Tests/SceneObjectUserGroupTests.cs | 3 +- 3 files changed, 137 insertions(+), 8 deletions(-) create mode 100644 OpenSim/Region/Framework/Scenes/Tests/SceneObjectUndoRedoTests.cs (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index 411dcc7..63eb387 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -3191,9 +3191,9 @@ namespace OpenSim.Region.Framework.Scenes } } - // m_log.DebugFormat( - // "[SCENE OBJECT PART]: Storing undo state for {0} {1}, forGroup {2}, initial stack size {3}", - // Name, LocalId, forGroup, m_undo.Count); +// m_log.DebugFormat( +// "[SCENE OBJECT PART]: Storing undo state for {0} {1}, forGroup {2}, initial stack size {3}", +// Name, LocalId, forGroup, m_undo.Count); if (ParentGroup.GetSceneMaxUndo() > 0) { @@ -3204,9 +3204,9 @@ namespace OpenSim.Region.Framework.Scenes if (m_redo.Count > 0) m_redo.Clear(); - // m_log.DebugFormat( - // "[SCENE OBJECT PART]: Stored undo state for {0} {1}, forGroup {2}, stack size now {3}", - // Name, LocalId, forGroup, m_undo.Count); +// m_log.DebugFormat( +// "[SCENE OBJECT PART]: Stored undo state for {0} {1}, forGroup {2}, stack size now {3}", +// Name, LocalId, forGroup, m_undo.Count); } } } diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectUndoRedoTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectUndoRedoTests.cs new file mode 100644 index 0000000..1e317c6 --- /dev/null +++ b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectUndoRedoTests.cs @@ -0,0 +1,130 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Reflection; +using NUnit.Framework; +using OpenMetaverse; +using OpenSim.Framework; +using OpenSim.Framework.Communications; +using OpenSim.Region.Framework.Scenes; +using OpenSim.Tests.Common; +using OpenSim.Tests.Common.Mock; + +namespace OpenSim.Region.Framework.Scenes.Tests +{ + /// + /// Tests for undo/redo + /// + public class SceneObjectUndoRedoTests : OpenSimTestCase + { + [Test] + public void TestUndoRedoResizeSceneObject() + { + TestHelpers.InMethod(); +// TestHelpers.EnableLogging(); + + Vector3 firstSize = new Vector3(2, 3, 4); + Vector3 secondSize = new Vector3(5, 6, 7); + + Scene scene = new SceneHelpers().SetupScene(); + SceneObjectGroup g1 = SceneHelpers.AddSceneObject(scene); + + // TODO: It happens to be the case that we are not storing undo states for SOPs which are not yet in a SOG, + // which is the way that AddSceneObject() sets up the object (i.e. it creates the SOP first). However, + // this is somewhat by chance. Really, we shouldn't be storing undo states at all if the object is not + // in a scene. + Assert.That(g1.RootPart.UndoCount, Is.EqualTo(0)); + + g1.GroupResize(firstSize); + Assert.That(g1.RootPart.UndoCount, Is.EqualTo(1)); + + g1.GroupResize(secondSize); + Assert.That(g1.RootPart.UndoCount, Is.EqualTo(2)); + + g1.RootPart.Undo(); + Assert.That(g1.RootPart.UndoCount, Is.EqualTo(1)); + Assert.That(g1.GroupScale, Is.EqualTo(firstSize)); + + g1.RootPart.Redo(); + Assert.That(g1.RootPart.UndoCount, Is.EqualTo(2)); + Assert.That(g1.GroupScale, Is.EqualTo(secondSize)); + } + + [Test] + public void TestUndoBeyondAvailable() + { + TestHelpers.InMethod(); + + Vector3 newSize = new Vector3(2, 3, 4); + + Scene scene = new SceneHelpers().SetupScene(); + SceneObjectGroup g1 = SceneHelpers.AddSceneObject(scene); + Vector3 originalSize = g1.GroupScale; + + g1.RootPart.Undo(); + + Assert.That(g1.RootPart.UndoCount, Is.EqualTo(0)); + Assert.That(g1.GroupScale, Is.EqualTo(originalSize)); + + g1.GroupResize(newSize); + Assert.That(g1.RootPart.UndoCount, Is.EqualTo(1)); + Assert.That(g1.GroupScale, Is.EqualTo(newSize)); + + g1.RootPart.Undo(); + g1.RootPart.Undo(); + + Assert.That(g1.RootPart.UndoCount, Is.EqualTo(0)); + Assert.That(g1.GroupScale, Is.EqualTo(originalSize)); + } + + [Test] + public void TestRedoBeyondAvailable() + { + TestHelpers.InMethod(); + + Vector3 newSize = new Vector3(2, 3, 4); + + Scene scene = new SceneHelpers().SetupScene(); + SceneObjectGroup g1 = SceneHelpers.AddSceneObject(scene); + Vector3 originalSize = g1.GroupScale; + + g1.RootPart.Redo(); + + Assert.That(g1.RootPart.UndoCount, Is.EqualTo(0)); + Assert.That(g1.GroupScale, Is.EqualTo(originalSize)); + + g1.GroupResize(newSize); + g1.RootPart.Undo(); + g1.RootPart.Redo(); + g1.RootPart.Redo(); + + Assert.That(g1.RootPart.UndoCount, Is.EqualTo(1)); + Assert.That(g1.GroupScale, Is.EqualTo(newSize)); + } + } +} \ No newline at end of file diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectUserGroupTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectUserGroupTests.cs index c7eaff9..2b79271 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectUserGroupTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectUserGroupTests.cs @@ -44,7 +44,7 @@ using OpenSim.Tests.Common.Mock; namespace OpenSim.Region.Framework.Scenes.Tests { [TestFixture] - public class SceneObjectUserGroupTests + public class SceneObjectUserGroupTests : OpenSimTestCase { /// /// Test share with group object functionality @@ -54,7 +54,6 @@ namespace OpenSim.Region.Framework.Scenes.Tests public void TestShareWithGroup() { TestHelpers.InMethod(); -// log4net.Config.XmlConfigurator.Configure(); UUID userId = UUID.Parse("10000000-0000-0000-0000-000000000001"); -- cgit v1.1 From 327320d1a7acbba969d26c281f92f64ce8ff365f Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Wed, 26 Sep 2012 22:49:44 +0100 Subject: Enforce existing 5 action hardcoded undo limit. This was present in the code but not enforced, which led to a memory leak over time as part properties were changed, whether by viewer, script or another source. This commit enforces that limit, which will soon become configurable. Regression test for undo limit added Should help with http://opensimulator.org/mantis/view.php?id=6279 --- OpenSim/Region/Framework/Scenes/Scene.cs | 6 ++- OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | 59 ++++++++++++---------- .../Scenes/Tests/SceneObjectUndoRedoTests.cs | 27 ++++++++++ 3 files changed, 65 insertions(+), 27 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index e9d1d42..872c061 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -151,7 +151,8 @@ namespace OpenSim.Region.Framework.Scenes // TODO: need to figure out how allow client agents but deny // root agents when ACL denies access to root agent public bool m_strictAccessControl = true; - public int MaxUndoCount = 5; + + public int MaxUndoCount { get; set; } // Using this for RegionReady module to prevent LoginsDisabled from changing under our feet; public bool LoginLock = false; @@ -931,6 +932,9 @@ namespace OpenSim.Region.Framework.Scenes WestBorders.Add(westBorder); BordersLocked = false; + // TODO: At some point this should be made configurable. + MaxUndoCount = 5; + m_eventManager = new EventManager(); m_permissions = new ScenePermissions(this); diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index 63eb387..9e78242 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -266,8 +266,8 @@ namespace OpenSim.Region.Framework.Scenes private string m_sitAnimation = "SIT"; private string m_text = String.Empty; private string m_touchName = String.Empty; - private readonly Stack m_undo = new Stack(5); - private readonly Stack m_redo = new Stack(5); + private readonly List m_undo = new List(5); + private readonly List m_redo = new List(5); private bool m_passTouches = false; private bool m_passCollisions = false; @@ -3176,7 +3176,7 @@ namespace OpenSim.Region.Framework.Scenes { if (m_undo.Count > 0) { - UndoState last = m_undo.Peek(); + UndoState last = m_undo[m_undo.Count - 1]; if (last != null) { // TODO: May need to fix for group comparison @@ -3199,7 +3199,10 @@ namespace OpenSim.Region.Framework.Scenes { UndoState nUndo = new UndoState(this, forGroup); - m_undo.Push(nUndo); + m_undo.Add(nUndo); + + if (m_undo.Count > ParentGroup.GetSceneMaxUndo()) + m_undo.RemoveAt(0); if (m_redo.Count > 0) m_redo.Clear(); @@ -3245,21 +3248,24 @@ namespace OpenSim.Region.Framework.Scenes if (m_undo.Count > 0) { - UndoState goback = m_undo.Pop(); + UndoState goback = m_undo[m_undo.Count - 1]; + m_undo.RemoveAt(m_undo.Count - 1); - if (goback != null) + UndoState nUndo = null; + + if (ParentGroup.GetSceneMaxUndo() > 0) { - UndoState nUndo = null; - - if (ParentGroup.GetSceneMaxUndo() > 0) - { - nUndo = new UndoState(this, goback.ForGroup); - } + nUndo = new UndoState(this, goback.ForGroup); + } + + goback.PlaybackState(this); - goback.PlaybackState(this); + if (nUndo != null) + { + m_redo.Add(nUndo); - if (nUndo != null) - m_redo.Push(nUndo); + if (m_redo.Count > ParentGroup.GetSceneMaxUndo()) + m_redo.RemoveAt(0); } } @@ -3279,20 +3285,21 @@ namespace OpenSim.Region.Framework.Scenes if (m_redo.Count > 0) { - UndoState gofwd = m_redo.Pop(); - - if (gofwd != null) + UndoState gofwd = m_redo[m_redo.Count - 1]; + m_redo.RemoveAt(m_redo.Count - 1); + + if (ParentGroup.GetSceneMaxUndo() > 0) { - if (ParentGroup.GetSceneMaxUndo() > 0) - { - UndoState nUndo = new UndoState(this, gofwd.ForGroup); - - m_undo.Push(nUndo); - } - - gofwd.PlayfwdState(this); + UndoState nUndo = new UndoState(this, gofwd.ForGroup); + + m_undo.Add(nUndo); + + if (m_undo.Count > ParentGroup.GetSceneMaxUndo()) + m_undo.RemoveAt(0); } + gofwd.PlayfwdState(this); + // m_log.DebugFormat( // "[SCENE OBJECT PART]: Handled redo request for {0} {1}, stack size now {2}", // Name, LocalId, m_redo.Count); diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectUndoRedoTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectUndoRedoTests.cs index 1e317c6..c93562d 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectUndoRedoTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectUndoRedoTests.cs @@ -76,6 +76,33 @@ namespace OpenSim.Region.Framework.Scenes.Tests } [Test] + public void TestUndoLimit() + { + TestHelpers.InMethod(); + + Vector3 firstSize = new Vector3(2, 3, 4); + Vector3 secondSize = new Vector3(5, 6, 7); + Vector3 thirdSize = new Vector3(8, 9, 10); + Vector3 fourthSize = new Vector3(11, 12, 13); + + Scene scene = new SceneHelpers().SetupScene(); + scene.MaxUndoCount = 2; + SceneObjectGroup g1 = SceneHelpers.AddSceneObject(scene); + + g1.GroupResize(firstSize); + g1.GroupResize(secondSize); + g1.GroupResize(thirdSize); + g1.GroupResize(fourthSize); + + g1.RootPart.Undo(); + g1.RootPart.Undo(); + g1.RootPart.Undo(); + + Assert.That(g1.RootPart.UndoCount, Is.EqualTo(0)); + Assert.That(g1.GroupScale, Is.EqualTo(secondSize)); + } + + [Test] public void TestUndoBeyondAvailable() { TestHelpers.InMethod(); -- cgit v1.1 From 36e3123069fb7524d3872d095c0f54c155c55a28 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Wed, 26 Sep 2012 23:17:21 +0100 Subject: Make it possible to rescale SOGs when they are not in a scene. --- .../Region/Framework/Scenes/SceneObjectGroup.cs | 54 +++++++++++----------- OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | 20 ++++---- 2 files changed, 40 insertions(+), 34 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index ac26be7..85a37e9 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -2703,29 +2703,32 @@ namespace OpenSim.Region.Framework.Scenes // m_log.DebugFormat( // "[SCENE OBJECT GROUP]: Group resizing {0} {1} from {2} to {3}", Name, LocalId, RootPart.Scale, scale); - RootPart.StoreUndoState(true); - - scale.X = Math.Max(Scene.m_minNonphys, Math.Min(Scene.m_maxNonphys, scale.X)); - scale.Y = Math.Max(Scene.m_minNonphys, Math.Min(Scene.m_maxNonphys, scale.Y)); - scale.Z = Math.Max(Scene.m_minNonphys, Math.Min(Scene.m_maxNonphys, scale.Z)); - PhysicsActor pa = m_rootPart.PhysActor; - if (pa != null && pa.IsPhysical) + RootPart.StoreUndoState(true); + + if (Scene != null) { - scale.X = Math.Max(Scene.m_minPhys, Math.Min(Scene.m_maxPhys, scale.X)); - scale.Y = Math.Max(Scene.m_minPhys, Math.Min(Scene.m_maxPhys, scale.Y)); - scale.Z = Math.Max(Scene.m_minPhys, Math.Min(Scene.m_maxPhys, scale.Z)); + scale.X = Math.Max(Scene.m_minNonphys, Math.Min(Scene.m_maxNonphys, scale.X)); + scale.Y = Math.Max(Scene.m_minNonphys, Math.Min(Scene.m_maxNonphys, scale.Y)); + scale.Z = Math.Max(Scene.m_minNonphys, Math.Min(Scene.m_maxNonphys, scale.Z)); + + if (pa != null && pa.IsPhysical) + { + scale.X = Math.Max(Scene.m_minPhys, Math.Min(Scene.m_maxPhys, scale.X)); + scale.Y = Math.Max(Scene.m_minPhys, Math.Min(Scene.m_maxPhys, scale.Y)); + scale.Z = Math.Max(Scene.m_minPhys, Math.Min(Scene.m_maxPhys, scale.Z)); + } } float x = (scale.X / RootPart.Scale.X); float y = (scale.Y / RootPart.Scale.Y); float z = (scale.Z / RootPart.Scale.Z); - SceneObjectPart[] parts; - if (x > 1.0f || y > 1.0f || z > 1.0f) + SceneObjectPart[] parts = m_parts.GetArray(); + + if (Scene != null & (x > 1.0f || y > 1.0f || z > 1.0f)) { - parts = m_parts.GetArray(); for (int i = 0; i < parts.Length; i++) { SceneObjectPart obPart = parts[i]; @@ -2739,7 +2742,7 @@ namespace OpenSim.Region.Framework.Scenes if (pa != null && pa.IsPhysical) { - if (oldSize.X * x > m_scene.m_maxPhys) + if (oldSize.X * x > Scene.m_maxPhys) { f = m_scene.m_maxPhys / oldSize.X; a = f / x; @@ -2747,7 +2750,7 @@ namespace OpenSim.Region.Framework.Scenes y *= a; z *= a; } - else if (oldSize.X * x < m_scene.m_minPhys) + else if (oldSize.X * x < Scene.m_minPhys) { f = m_scene.m_minPhys / oldSize.X; a = f / x; @@ -2756,7 +2759,7 @@ namespace OpenSim.Region.Framework.Scenes z *= a; } - if (oldSize.Y * y > m_scene.m_maxPhys) + if (oldSize.Y * y > Scene.m_maxPhys) { f = m_scene.m_maxPhys / oldSize.Y; a = f / y; @@ -2764,7 +2767,7 @@ namespace OpenSim.Region.Framework.Scenes y *= a; z *= a; } - else if (oldSize.Y * y < m_scene.m_minPhys) + else if (oldSize.Y * y < Scene.m_minPhys) { f = m_scene.m_minPhys / oldSize.Y; a = f / y; @@ -2773,7 +2776,7 @@ namespace OpenSim.Region.Framework.Scenes z *= a; } - if (oldSize.Z * z > m_scene.m_maxPhys) + if (oldSize.Z * z > Scene.m_maxPhys) { f = m_scene.m_maxPhys / oldSize.Z; a = f / z; @@ -2781,7 +2784,7 @@ namespace OpenSim.Region.Framework.Scenes y *= a; z *= a; } - else if (oldSize.Z * z < m_scene.m_minPhys) + else if (oldSize.Z * z < Scene.m_minPhys) { f = m_scene.m_minPhys / oldSize.Z; a = f / z; @@ -2792,7 +2795,7 @@ namespace OpenSim.Region.Framework.Scenes } else { - if (oldSize.X * x > m_scene.m_maxNonphys) + if (oldSize.X * x > Scene.m_maxNonphys) { f = m_scene.m_maxNonphys / oldSize.X; a = f / x; @@ -2800,7 +2803,7 @@ namespace OpenSim.Region.Framework.Scenes y *= a; z *= a; } - else if (oldSize.X * x < m_scene.m_minNonphys) + else if (oldSize.X * x < Scene.m_minNonphys) { f = m_scene.m_minNonphys / oldSize.X; a = f / x; @@ -2809,7 +2812,7 @@ namespace OpenSim.Region.Framework.Scenes z *= a; } - if (oldSize.Y * y > m_scene.m_maxNonphys) + if (oldSize.Y * y > Scene.m_maxNonphys) { f = m_scene.m_maxNonphys / oldSize.Y; a = f / y; @@ -2817,7 +2820,7 @@ namespace OpenSim.Region.Framework.Scenes y *= a; z *= a; } - else if (oldSize.Y * y < m_scene.m_minNonphys) + else if (oldSize.Y * y < Scene.m_minNonphys) { f = m_scene.m_minNonphys / oldSize.Y; a = f / y; @@ -2826,7 +2829,7 @@ namespace OpenSim.Region.Framework.Scenes z *= a; } - if (oldSize.Z * z > m_scene.m_maxNonphys) + if (oldSize.Z * z > Scene.m_maxNonphys) { f = m_scene.m_maxNonphys / oldSize.Z; a = f / z; @@ -2834,7 +2837,7 @@ namespace OpenSim.Region.Framework.Scenes y *= a; z *= a; } - else if (oldSize.Z * z < m_scene.m_minNonphys) + else if (oldSize.Z * z < Scene.m_minNonphys) { f = m_scene.m_minNonphys / oldSize.Z; a = f / z; @@ -2858,7 +2861,6 @@ namespace OpenSim.Region.Framework.Scenes RootPart.Resize(prevScale); // RootPart.IgnoreUndoUpdate = false; - parts = m_parts.GetArray(); for (int i = 0; i < parts.Length; i++) { SceneObjectPart obPart = parts[i]; diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index 9e78242..018e4fc 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -2368,16 +2368,20 @@ namespace OpenSim.Region.Framework.Scenes /// public void Resize(Vector3 scale) { - scale.X = Math.Max(ParentGroup.Scene.m_minNonphys, Math.Min(ParentGroup.Scene.m_maxNonphys, scale.X)); - scale.Y = Math.Max(ParentGroup.Scene.m_minNonphys, Math.Min(ParentGroup.Scene.m_maxNonphys, scale.Y)); - scale.Z = Math.Max(ParentGroup.Scene.m_minNonphys, Math.Min(ParentGroup.Scene.m_maxNonphys, scale.Z)); - PhysicsActor pa = PhysActor; - if (pa != null && pa.IsPhysical) + + if (ParentGroup.Scene != null) { - scale.X = Math.Max(ParentGroup.Scene.m_minPhys, Math.Min(ParentGroup.Scene.m_maxPhys, scale.X)); - scale.Y = Math.Max(ParentGroup.Scene.m_minPhys, Math.Min(ParentGroup.Scene.m_maxPhys, scale.Y)); - scale.Z = Math.Max(ParentGroup.Scene.m_minPhys, Math.Min(ParentGroup.Scene.m_maxPhys, scale.Z)); + scale.X = Math.Max(ParentGroup.Scene.m_minNonphys, Math.Min(ParentGroup.Scene.m_maxNonphys, scale.X)); + scale.Y = Math.Max(ParentGroup.Scene.m_minNonphys, Math.Min(ParentGroup.Scene.m_maxNonphys, scale.Y)); + scale.Z = Math.Max(ParentGroup.Scene.m_minNonphys, Math.Min(ParentGroup.Scene.m_maxNonphys, scale.Z)); + + if (pa != null && pa.IsPhysical) + { + scale.X = Math.Max(ParentGroup.Scene.m_minPhys, Math.Min(ParentGroup.Scene.m_maxPhys, scale.X)); + scale.Y = Math.Max(ParentGroup.Scene.m_minPhys, Math.Min(ParentGroup.Scene.m_maxPhys, scale.Y)); + scale.Z = Math.Max(ParentGroup.Scene.m_minPhys, Math.Min(ParentGroup.Scene.m_maxPhys, scale.Z)); + } } // m_log.DebugFormat("[SCENE OBJECT PART]: Resizing {0} {1} to {2}", Name, LocalId, scale); -- cgit v1.1 From 31c636f1e48db2a42950e2ec0e8c7eba2c16616c Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Wed, 26 Sep 2012 23:25:50 +0100 Subject: refactor: Change control structures in SOP.StoreUndoState() to reduce nesting. --- OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | 88 +++++++++++----------- 1 file changed, 43 insertions(+), 45 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index 018e4fc..8710c3e 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -3170,64 +3170,62 @@ namespace OpenSim.Region.Framework.Scenes public void StoreUndoState(bool forGroup) { - if (!Undoing) + if (Undoing) { - if (!IgnoreUndoUpdate) +// m_log.DebugFormat( +// "[SCENE OBJECT PART]: Ignoring undo store for {0} {1} since already undoing", Name, LocalId); + return; + } + + if (IgnoreUndoUpdate) + { +// m_log.DebugFormat("[SCENE OBJECT PART]: Ignoring undo store for {0} {1}", Name, LocalId); + return; + } + + if (ParentGroup == null) + return; + + lock (m_undo) + { + if (m_undo.Count > 0) { - if (ParentGroup != null) + UndoState last = m_undo[m_undo.Count - 1]; + if (last != null) { - lock (m_undo) + // TODO: May need to fix for group comparison + if (last.Compare(this)) { - if (m_undo.Count > 0) - { - UndoState last = m_undo[m_undo.Count - 1]; - if (last != null) - { - // TODO: May need to fix for group comparison - if (last.Compare(this)) - { - // m_log.DebugFormat( - // "[SCENE OBJECT PART]: Not storing undo for {0} {1} since current state is same as last undo state, initial stack size {2}", - // Name, LocalId, m_undo.Count); - - return; - } - } - } - +// m_log.DebugFormat( +// "[SCENE OBJECT PART]: Not storing undo for {0} {1} since current state is same as last undo state, initial stack size {2}", +// Name, LocalId, m_undo.Count); + + return; + } + } + } + // m_log.DebugFormat( // "[SCENE OBJECT PART]: Storing undo state for {0} {1}, forGroup {2}, initial stack size {3}", // Name, LocalId, forGroup, m_undo.Count); - - if (ParentGroup.GetSceneMaxUndo() > 0) - { - UndoState nUndo = new UndoState(this, forGroup); - - m_undo.Add(nUndo); - if (m_undo.Count > ParentGroup.GetSceneMaxUndo()) - m_undo.RemoveAt(0); - - if (m_redo.Count > 0) - m_redo.Clear(); - + if (ParentGroup.GetSceneMaxUndo() > 0) + { + UndoState nUndo = new UndoState(this, forGroup); + + m_undo.Add(nUndo); + + if (m_undo.Count > ParentGroup.GetSceneMaxUndo()) + m_undo.RemoveAt(0); + + if (m_redo.Count > 0) + m_redo.Clear(); + // m_log.DebugFormat( // "[SCENE OBJECT PART]: Stored undo state for {0} {1}, forGroup {2}, stack size now {3}", // Name, LocalId, forGroup, m_undo.Count); - } - } - } } -// else -// { -// m_log.DebugFormat("[SCENE OBJECT PART]: Ignoring undo store for {0} {1}", Name, LocalId); -// } } -// else -// { -// m_log.DebugFormat( -// "[SCENE OBJECT PART]: Ignoring undo store for {0} {1} since already undoing", Name, LocalId); -// } } /// -- cgit v1.1 From b9934fc4dbb1267409fa7264f3dd83a98959ea87 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Wed, 26 Sep 2012 23:31:10 +0100 Subject: Don't store undo states if a scene object is manipulated when it is not in a scene. Adds regression test for this. --- OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | 6 +++--- .../Scenes/Tests/SceneObjectUndoRedoTests.cs | 23 ++++++++++++++++++++++ 2 files changed, 26 insertions(+), 3 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index 8710c3e..3d4bc3c 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -3170,6 +3170,9 @@ namespace OpenSim.Region.Framework.Scenes public void StoreUndoState(bool forGroup) { + if (ParentGroup == null || ParentGroup.Scene == null) + return; + if (Undoing) { // m_log.DebugFormat( @@ -3183,9 +3186,6 @@ namespace OpenSim.Region.Framework.Scenes return; } - if (ParentGroup == null) - return; - lock (m_undo) { if (m_undo.Count > 0) diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectUndoRedoTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectUndoRedoTests.cs index c93562d..133fac5 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectUndoRedoTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectUndoRedoTests.cs @@ -103,6 +103,29 @@ namespace OpenSim.Region.Framework.Scenes.Tests } [Test] + public void TestNoUndoOnObjectsNotInScene() + { + TestHelpers.InMethod(); + + Vector3 firstSize = new Vector3(2, 3, 4); + Vector3 secondSize = new Vector3(5, 6, 7); + Vector3 thirdSize = new Vector3(8, 9, 10); + Vector3 fourthSize = new Vector3(11, 12, 13); + + Scene scene = new SceneHelpers().SetupScene(); + SceneObjectGroup g1 = SceneHelpers.CreateSceneObject(1, TestHelpers.ParseTail(0x1)); + + g1.GroupResize(firstSize); + g1.GroupResize(secondSize); + + Assert.That(g1.RootPart.UndoCount, Is.EqualTo(0)); + + g1.RootPart.Undo(); + + Assert.That(g1.GroupScale, Is.EqualTo(secondSize)); + } + + [Test] public void TestUndoBeyondAvailable() { TestHelpers.InMethod(); -- cgit v1.1 From 2bf42f30af5030890b8e3ff5bb29074a1f0e9085 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Thu, 27 Sep 2012 00:12:34 +0100 Subject: Add MaxPrimsUndo config setting to [Startup] section of OpenSim.ini. This controls how many undo steps the simulator will store for each prim. Default is now 20 rather than 5 as it briefly was. The default number could be increased through this is a memory tradeoff which will scale with the number of prims in the sim and level of activity. --- OpenSim/Region/Framework/Scenes/Scene.cs | 5 ++--- OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs | 8 -------- OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | 12 ++++++------ .../Region/Framework/Scenes/Tests/SceneObjectResizeTests.cs | 2 -- .../Framework/Scenes/Tests/SceneObjectUndoRedoTests.cs | 4 ++++ 5 files changed, 12 insertions(+), 19 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 872c061..2e03874 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -742,6 +742,8 @@ namespace OpenSim.Region.Framework.Scenes //Animation states m_useFlySlow = startupConfig.GetBoolean("enableflyslow", false); + MaxUndoCount = startupConfig.GetInt("MaxPrimUndos", 20); + PhysicalPrims = startupConfig.GetBoolean("physical_prim", PhysicalPrims); CollidablePrims = startupConfig.GetBoolean("collidable_prim", CollidablePrims); @@ -932,9 +934,6 @@ namespace OpenSim.Region.Framework.Scenes WestBorders.Add(westBorder); BordersLocked = false; - // TODO: At some point this should be made configurable. - MaxUndoCount = 5; - m_eventManager = new EventManager(); m_permissions = new ScenePermissions(this); diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index 85a37e9..45bbbda 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -1119,14 +1119,6 @@ namespace OpenSim.Region.Framework.Scenes parts[i].UUID = UUID.Random(); } - // helper provided for parts. - public int GetSceneMaxUndo() - { - if (m_scene != null) - return m_scene.MaxUndoCount; - return 5; - } - // justincc: I don't believe this hack is needed any longer, especially since the physics // parts of set AbsolutePosition were already commented out. By changing HasGroupChanged to false // this method was preventing proper reload of scene objects. diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index 3d4bc3c..3f10b34 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -3209,13 +3209,13 @@ namespace OpenSim.Region.Framework.Scenes // "[SCENE OBJECT PART]: Storing undo state for {0} {1}, forGroup {2}, initial stack size {3}", // Name, LocalId, forGroup, m_undo.Count); - if (ParentGroup.GetSceneMaxUndo() > 0) + if (ParentGroup.Scene.MaxUndoCount > 0) { UndoState nUndo = new UndoState(this, forGroup); m_undo.Add(nUndo); - if (m_undo.Count > ParentGroup.GetSceneMaxUndo()) + if (m_undo.Count > ParentGroup.Scene.MaxUndoCount) m_undo.RemoveAt(0); if (m_redo.Count > 0) @@ -3255,7 +3255,7 @@ namespace OpenSim.Region.Framework.Scenes UndoState nUndo = null; - if (ParentGroup.GetSceneMaxUndo() > 0) + if (ParentGroup.Scene.MaxUndoCount > 0) { nUndo = new UndoState(this, goback.ForGroup); } @@ -3266,7 +3266,7 @@ namespace OpenSim.Region.Framework.Scenes { m_redo.Add(nUndo); - if (m_redo.Count > ParentGroup.GetSceneMaxUndo()) + if (m_redo.Count > ParentGroup.Scene.MaxUndoCount) m_redo.RemoveAt(0); } } @@ -3290,13 +3290,13 @@ namespace OpenSim.Region.Framework.Scenes UndoState gofwd = m_redo[m_redo.Count - 1]; m_redo.RemoveAt(m_redo.Count - 1); - if (ParentGroup.GetSceneMaxUndo() > 0) + if (ParentGroup.Scene.MaxUndoCount > 0) { UndoState nUndo = new UndoState(this, gofwd.ForGroup); m_undo.Add(nUndo); - if (m_undo.Count > ParentGroup.GetSceneMaxUndo()) + if (m_undo.Count > ParentGroup.Scene.MaxUndoCount) m_undo.RemoveAt(0); } diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectResizeTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectResizeTests.cs index e931859..89647d6 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectResizeTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectResizeTests.cs @@ -62,8 +62,6 @@ namespace OpenSim.Region.Framework.Scenes.Tests Assert.That(g1Post.RootPart.Scale.X, Is.EqualTo(2)); Assert.That(g1Post.RootPart.Scale.Y, Is.EqualTo(3)); Assert.That(g1Post.RootPart.Scale.Z, Is.EqualTo(4)); - - Assert.That(g1Post.RootPart.UndoCount, Is.EqualTo(1)); } /// diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectUndoRedoTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectUndoRedoTests.cs index 133fac5..96973de 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectUndoRedoTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectUndoRedoTests.cs @@ -52,6 +52,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests Vector3 secondSize = new Vector3(5, 6, 7); Scene scene = new SceneHelpers().SetupScene(); + scene.MaxUndoCount = 20; SceneObjectGroup g1 = SceneHelpers.AddSceneObject(scene); // TODO: It happens to be the case that we are not storing undo states for SOPs which are not yet in a SOG, @@ -113,6 +114,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests Vector3 fourthSize = new Vector3(11, 12, 13); Scene scene = new SceneHelpers().SetupScene(); + scene.MaxUndoCount = 20; SceneObjectGroup g1 = SceneHelpers.CreateSceneObject(1, TestHelpers.ParseTail(0x1)); g1.GroupResize(firstSize); @@ -133,6 +135,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests Vector3 newSize = new Vector3(2, 3, 4); Scene scene = new SceneHelpers().SetupScene(); + scene.MaxUndoCount = 20; SceneObjectGroup g1 = SceneHelpers.AddSceneObject(scene); Vector3 originalSize = g1.GroupScale; @@ -160,6 +163,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests Vector3 newSize = new Vector3(2, 3, 4); Scene scene = new SceneHelpers().SetupScene(); + scene.MaxUndoCount = 20; SceneObjectGroup g1 = SceneHelpers.AddSceneObject(scene); Vector3 originalSize = g1.GroupScale; -- cgit v1.1 From 1a902fceb54d9501f489b2ce872a0b03b5b17ad5 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Tue, 25 Sep 2012 21:35:39 +0100 Subject: Fix occasional race condition failure when creating new clothing/body parts in the viewer or updating existing assets. On creating these items, the viewer sends a UDP AssetUploadRequest followed by a CreateInventoryItem. It was possible for the CreateInventoryItem/UpdateInventoryItem to occasionally outrace the AssetUploadRequest and fail to find an initialized Xfer object, at which point the item create would fail. So instead we always set up a Xfer object on either the asset or inventory item update request. This does not introduce a new race because code already exists to delay the item operation until the asset is uploaded if necessary (but this only worked if the xfer object already existed) --- .../AssetTransaction/AgentAssetsTransactions.cs | 123 +++++++-------------- .../AssetTransaction/AssetTransactionModule.cs | 9 +- .../Agent/AssetTransaction/AssetXferUploader.cs | 71 +++++++++--- 3 files changed, 93 insertions(+), 110 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs index b557ffe..bba7b9c 100644 --- a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs +++ b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs @@ -57,39 +57,36 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction } /// - /// Return a xfer uploader if one does not already exist. + /// Return the xfer uploader for the given transaction. /// + /// + /// If an uploader does not already exist for this transaction then it is created, otherwise the existing + /// uploader is returned. + /// /// - /// - /// We must transfer the new asset ID into the uploader on creation, otherwise - /// we can see race conditions with other threads which can retrieve an item before it is updated with the new - /// asset id. - /// - /// - /// The xfer uploader requested. Null if one is already in existence. - /// FIXME: This is a bizarre thing to do, and is probably meant to signal an error condition if multiple - /// transfers are made. Needs to be corrected. - /// - public AssetXferUploader RequestXferUploader(UUID transactionID, UUID assetID) + /// The asset xfer uploader + public AssetXferUploader RequestXferUploader(UUID transactionID) { + AssetXferUploader uploader; + lock (XferUploaders) { if (!XferUploaders.ContainsKey(transactionID)) { - AssetXferUploader uploader = new AssetXferUploader(this, m_Scene, assetID, m_dumpAssetsToFile); + uploader = new AssetXferUploader(this, m_Scene, m_dumpAssetsToFile); // m_log.DebugFormat( // "[AGENT ASSETS TRANSACTIONS]: Adding asset xfer uploader {0} since it didn't previously exist", transactionID); XferUploaders.Add(transactionID, uploader); - - return uploader; + } + else + { + uploader = XferUploaders[transactionID]; } } - m_log.WarnFormat("[AGENT ASSETS TRANSACTIONS]: Ignoring request for asset xfer uploader {0} since it already exists", transactionID); - - return null; + return uploader; } public void HandleXfer(ulong xferID, uint packetID, byte[] data) @@ -151,23 +148,11 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction string description, string name, sbyte invType, sbyte type, byte wearableType, uint nextOwnerMask) { - AssetXferUploader uploader = null; + AssetXferUploader uploader = RequestXferUploader(transactionID); - lock (XferUploaders) - { - if (XferUploaders.ContainsKey(transactionID)) - uploader = XferUploaders[transactionID]; - } - - if (uploader != null) - uploader.RequestCreateInventoryItem( - remoteClient, transactionID, folderID, - callbackID, description, name, invType, type, - wearableType, nextOwnerMask); - else - m_log.ErrorFormat( - "[AGENT ASSET TRANSACTIONS]: Could not find uploader with transaction ID {0} when handling request to create inventory item {1} from {2}", - transactionID, name, remoteClient.Name); + uploader.RequestCreateInventoryItem( + remoteClient, transactionID, folderID, callbackID, + description, name, invType, type, wearableType, nextOwnerMask); } /// @@ -197,69 +182,37 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction SceneObjectPart part, UUID transactionID, TaskInventoryItem item) { - AssetXferUploader uploader = null; + AssetBase asset = GetTransactionAsset(transactionID); - lock (XferUploaders) - { - if (XferUploaders.ContainsKey(transactionID)) - uploader = XferUploaders[transactionID]; - } + // Only legacy viewers use this, and they prefer CAPS, which + // we have, so this really never runs. + // Allow it, but only for "safe" types. + if ((InventoryType)item.InvType != InventoryType.Notecard && + (InventoryType)item.InvType != InventoryType.LSL) + return; - if (uploader != null) + if (asset != null) { - AssetBase asset = GetTransactionAsset(transactionID); - - // Only legacy viewers use this, and they prefer CAPS, which - // we have, so this really never runs. - // Allow it, but only for "safe" types. - if ((InventoryType)item.InvType != InventoryType.Notecard && - (InventoryType)item.InvType != InventoryType.LSL) - return; - - if (asset != null) - { // m_log.DebugFormat( // "[AGENT ASSETS TRANSACTIONS]: Updating item {0} in {1} for transaction {2}", // item.Name, part.Name, transactionID); - - asset.FullID = UUID.Random(); - asset.Name = item.Name; - asset.Description = item.Description; - asset.Type = (sbyte)item.Type; - item.AssetID = asset.FullID; - - m_Scene.AssetService.Store(asset); - } - } - else - { - m_log.ErrorFormat( - "[AGENT ASSET TRANSACTIONS]: Could not find uploader with transaction ID {0} when handling request to update task inventory item {1} in {2}", - transactionID, item.Name, part.Name); + + asset.FullID = UUID.Random(); + asset.Name = item.Name; + asset.Description = item.Description; + asset.Type = (sbyte)item.Type; + item.AssetID = asset.FullID; + + m_Scene.AssetService.Store(asset); } } public void RequestUpdateInventoryItem(IClientAPI remoteClient, UUID transactionID, InventoryItemBase item) { - AssetXferUploader uploader = null; - - lock (XferUploaders) - { - if (XferUploaders.ContainsKey(transactionID)) - uploader = XferUploaders[transactionID]; - } + AssetXferUploader uploader = RequestXferUploader(transactionID); - if (uploader != null) - { - uploader.RequestUpdateInventoryItem(remoteClient, transactionID, item); - } - else - { - m_log.ErrorFormat( - "[AGENT ASSET TRANSACTIONS]: Could not find uploader with transaction ID {0} when handling request to update inventory item {1} for {2}", - transactionID, item.Name, remoteClient.Name); - } + uploader.RequestUpdateInventoryItem(remoteClient, transactionID, item); } } -} +} \ No newline at end of file diff --git a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetTransactionModule.cs b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetTransactionModule.cs index 7081989..10a0794 100644 --- a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetTransactionModule.cs +++ b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetTransactionModule.cs @@ -274,13 +274,8 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction } AgentAssetTransactions transactions = GetUserTransactions(remoteClient.AgentId); - AssetXferUploader uploader = transactions.RequestXferUploader(transaction, assetID); - - if (uploader != null) - { - uploader.Initialise(remoteClient, assetID, transaction, type, - data, storeLocal, tempFile); - } + AssetXferUploader uploader = transactions.RequestXferUploader(transaction); + uploader.StartUpload(remoteClient, assetID, transaction, type, data, storeLocal, tempFile); } /// diff --git a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs index 4cedfe6..d134c43 100644 --- a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs +++ b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs @@ -49,11 +49,26 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); /// + /// Upload state. + /// + /// + /// New -> Uploading -> Complete + /// + private enum UploadState + { + New, + Uploading, + Complete + } + + /// /// Reference to the object that holds this uploader. Used to remove ourselves from it's list if we /// are performing a delayed update. /// AgentAssetTransactions m_transactions; + private UploadState m_uploadState = UploadState.New; + private AssetBase m_asset; private UUID InventFolder = UUID.Zero; private sbyte invType = 0; @@ -65,7 +80,6 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction private string m_description = String.Empty; private bool m_dumpAssetToFile; - private bool m_finished = false; private string m_name = String.Empty; private bool m_storeLocal; private uint nextPerm = 0; @@ -77,11 +91,10 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction public ulong XferID; private Scene m_Scene; - public AssetXferUploader(AgentAssetTransactions transactions, Scene scene, UUID assetID, bool dumpAssetToFile) + public AssetXferUploader(AgentAssetTransactions transactions, Scene scene, bool dumpAssetToFile) { m_transactions = transactions; m_Scene = scene; - m_asset = new AssetBase() { FullID = assetID }; m_dumpAssetToFile = dumpAssetToFile; } @@ -127,20 +140,43 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction } /// - /// Initialise asset transfer from the client + /// Start asset transfer from the client /// - /// - /// - /// - public void Initialise(IClientAPI remoteClient, UUID assetID, - UUID transaction, sbyte type, byte[] data, bool storeLocal, - bool tempFile) + /// + /// + /// + /// + /// + /// Optional data. If present then the asset is created immediately with this data + /// rather than requesting an upload from the client. The data must be longer than 2 bytes. + /// + /// + /// + public void StartUpload( + IClientAPI remoteClient, UUID assetID, UUID transaction, sbyte type, byte[] data, bool storeLocal, + bool tempFile) { // m_log.DebugFormat( // "[ASSET XFER UPLOADER]: Initialised xfer from {0}, asset {1}, transaction {2}, type {3}, storeLocal {4}, tempFile {5}, already received data length {6}", // remoteClient.Name, assetID, transaction, type, storeLocal, tempFile, data.Length); + lock (this) + { + if (m_uploadState != UploadState.New) + { + m_log.WarnFormat( + "[ASSET XFER UPLOADER]: Tried to start upload of asset {0}, transaction {1} for {2} but this is already in state {3}. Aborting.", + assetID, transaction, remoteClient.Name, m_uploadState); + + return; + } + + m_uploadState = UploadState.Uploading; + } + ourClient = remoteClient; + + m_asset = new AssetBase() { FullID = assetID }; m_asset.Name = "blank"; m_asset.Description = "empty"; m_asset.Type = type; @@ -175,14 +211,14 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction protected void SendCompleteMessage() { - ourClient.SendAssetUploadCompleteMessage(m_asset.Type, true, - m_asset.FullID); - // We must lock in order to avoid a race with a separate thread dealing with an inventory item or create // message from other client UDP. lock (this) { - m_finished = true; + m_uploadState = UploadState.Complete; + + ourClient.SendAssetUploadCompleteMessage(m_asset.Type, true, m_asset.FullID); + if (m_createItem) { DoCreateItem(m_createItemCallback); @@ -252,7 +288,7 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction // We must lock to avoid a race with a separate thread uploading the asset. lock (this) { - if (m_finished) + if (m_uploadState == UploadState.Complete) { DoCreateItem(callbackID); } @@ -280,7 +316,7 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction item.AssetID = m_asset.FullID; m_Scene.InventoryService.UpdateItem(item); - if (m_finished) + if (m_uploadState == UploadState.Complete) { StoreAssetForItemUpdate(item); } @@ -416,7 +452,7 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction /// null if the asset has not finished uploading public AssetBase GetAssetData() { - if (m_finished) + if (m_uploadState == UploadState.Complete) { ValidateAssets(); return m_asset; @@ -469,4 +505,3 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction } } } - -- cgit v1.1 From 65e294267df7fb3892d3d926182794f51ce42a71 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Tue, 25 Sep 2012 22:08:11 +0100 Subject: Move UDP update task item code to AssetXferUploader to match existing create user item and update user item mechanisms This is done for consistency and to allow removal or some access methods that increase code complexity. However, this path has not been used for a long time, not even by LL 1.23 - viewers use caps http upload for this instead --- .../AssetTransaction/AgentAssetsTransactions.cs | 47 +------------------ .../AssetTransaction/AssetTransactionModule.cs | 2 +- .../Agent/AssetTransaction/AssetXferUploader.cs | 53 ++++++++++++++++++++-- 3 files changed, 52 insertions(+), 50 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs index bba7b9c..59d0075 100644 --- a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs +++ b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs @@ -155,56 +155,13 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction description, name, invType, type, wearableType, nextOwnerMask); } - /// - /// Get an uploaded asset. If the data is successfully retrieved, - /// the transaction will be removed. - /// - /// - /// The asset if the upload has completed, null if it has not. - private AssetBase GetTransactionAsset(UUID transactionID) - { - lock (XferUploaders) - { - if (XferUploaders.ContainsKey(transactionID)) - { - AssetXferUploader uploader = XferUploaders[transactionID]; - AssetBase asset = uploader.GetAssetData(); - RemoveXferUploader(transactionID); - - return asset; - } - } - - return null; - } - public void RequestUpdateTaskInventoryItem(IClientAPI remoteClient, SceneObjectPart part, UUID transactionID, TaskInventoryItem item) { - AssetBase asset = GetTransactionAsset(transactionID); - - // Only legacy viewers use this, and they prefer CAPS, which - // we have, so this really never runs. - // Allow it, but only for "safe" types. - if ((InventoryType)item.InvType != InventoryType.Notecard && - (InventoryType)item.InvType != InventoryType.LSL) - return; + AssetXferUploader uploader = RequestXferUploader(transactionID); - if (asset != null) - { -// m_log.DebugFormat( -// "[AGENT ASSETS TRANSACTIONS]: Updating item {0} in {1} for transaction {2}", -// item.Name, part.Name, transactionID); - - asset.FullID = UUID.Random(); - asset.Name = item.Name; - asset.Description = item.Description; - asset.Type = (sbyte)item.Type; - item.AssetID = asset.FullID; - - m_Scene.AssetService.Store(asset); - } + uploader.RequestUpdateTaskInventoryItem(remoteClient, transactionID, item); } public void RequestUpdateInventoryItem(IClientAPI remoteClient, diff --git a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetTransactionModule.cs b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetTransactionModule.cs index 10a0794..73d1f72 100644 --- a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetTransactionModule.cs +++ b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetTransactionModule.cs @@ -215,7 +215,7 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction IClientAPI remoteClient, SceneObjectPart part, UUID transactionID, TaskInventoryItem item) { m_log.DebugFormat( - "[TRANSACTIONS MANAGER] Called HandleTaskItemUpdateFromTransaction with item {0} in {1} for {2} in {3}", + "[ASSET TRANSACTION MODULE] Called HandleTaskItemUpdateFromTransaction with item {0} in {1} for {2} in {3}", item.Name, part.Name, remoteClient.Name, m_Scene.RegionInfo.RegionName); AgentAssetTransactions transactions = diff --git a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs index d134c43..96f0d0f 100644 --- a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs +++ b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs @@ -73,11 +73,15 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction private UUID InventFolder = UUID.Zero; private sbyte invType = 0; - private bool m_createItem = false; - private uint m_createItemCallback = 0; - private bool m_updateItem = false; + private bool m_createItem; + private uint m_createItemCallback; + + private bool m_updateItem; private InventoryItemBase m_updateItemData; + private bool m_updateTaskItem; + private TaskInventoryItem m_updateTaskItemData; + private string m_description = String.Empty; private bool m_dumpAssetToFile; private string m_name = String.Empty; @@ -232,6 +236,12 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction // TODO: Should probably do the same for create item. m_transactions.RemoveXferUploader(TransactionID); } + else if (m_updateTaskItem) + { + StoreAssetForTaskItemUpdate(m_updateTaskItemData); + + m_transactions.RemoveXferUploader(TransactionID); + } else if (m_storeLocal) { m_Scene.AssetService.Store(m_asset); @@ -332,8 +342,30 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction } } + public void RequestUpdateTaskInventoryItem(IClientAPI remoteClient, UUID transactionID, TaskInventoryItem taskItem) + { + // We must lock to avoid a race with a separate thread uploading the asset. + lock (this) + { + m_asset.Name = taskItem.Name; + m_asset.Description = taskItem.Description; + m_asset.Type = (sbyte)taskItem.Type; + taskItem.AssetID = m_asset.FullID; + + if (m_uploadState == UploadState.Complete) + { + StoreAssetForTaskItemUpdate(taskItem); + } + else + { + m_updateTaskItem = true; + m_updateTaskItemData = taskItem; + } + } + } + /// - /// Store the asset for the given item. + /// Store the asset for the given item when it has been uploaded. /// /// private void StoreAssetForItemUpdate(InventoryItemBase item) @@ -345,6 +377,19 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction m_Scene.AssetService.Store(m_asset); } + /// + /// Store the asset for the given task item when it has been uploaded. + /// + /// + private void StoreAssetForTaskItemUpdate(TaskInventoryItem taskItem) + { +// m_log.DebugFormat( +// "[ASSET XFER UPLOADER]: Storing asset {0} for earlier task item update for {1} for {2}", +// m_asset.FullID, taskItem.Name, ourClient.Name); + + m_Scene.AssetService.Store(m_asset); + } + private void DoCreateItem(uint callbackID) { ValidateAssets(); -- cgit v1.1 From 5c8b9ff9ed479b9baf7d57c1b15f058d88778bc5 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Tue, 25 Sep 2012 22:54:20 +0100 Subject: Insert transaction ID into AssetXferUploader constructor rather than at UploadAsset() to prevent item creation failure when NewInventoryItem thread reachs the object first. This was preventing the previous race condition fix in 4fc0cfb from actually working. This commit also removes some of the pointless transaction id checks - these conditions are already being enforced in AgentAssetsTransactions. --- .../AssetTransaction/AgentAssetsTransactions.cs | 8 +-- .../Agent/AssetTransaction/AssetXferUploader.cs | 77 +++++++++++++--------- 2 files changed, 49 insertions(+), 36 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs index 59d0075..0271738 100644 --- a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs +++ b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs @@ -73,7 +73,7 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction { if (!XferUploaders.ContainsKey(transactionID)) { - uploader = new AssetXferUploader(this, m_Scene, m_dumpAssetsToFile); + uploader = new AssetXferUploader(this, m_Scene, transactionID, m_dumpAssetsToFile); // m_log.DebugFormat( // "[AGENT ASSETS TRANSACTIONS]: Adding asset xfer uploader {0} since it didn't previously exist", transactionID); @@ -151,7 +151,7 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction AssetXferUploader uploader = RequestXferUploader(transactionID); uploader.RequestCreateInventoryItem( - remoteClient, transactionID, folderID, callbackID, + remoteClient, folderID, callbackID, description, name, invType, type, wearableType, nextOwnerMask); } @@ -161,7 +161,7 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction { AssetXferUploader uploader = RequestXferUploader(transactionID); - uploader.RequestUpdateTaskInventoryItem(remoteClient, transactionID, item); + uploader.RequestUpdateTaskInventoryItem(remoteClient, item); } public void RequestUpdateInventoryItem(IClientAPI remoteClient, @@ -169,7 +169,7 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction { AssetXferUploader uploader = RequestXferUploader(transactionID); - uploader.RequestUpdateInventoryItem(remoteClient, transactionID, item); + uploader.RequestUpdateInventoryItem(remoteClient, item); } } } \ No newline at end of file diff --git a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs index 96f0d0f..a852767 100644 --- a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs +++ b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs @@ -88,16 +88,33 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction private bool m_storeLocal; private uint nextPerm = 0; private IClientAPI ourClient; - private UUID TransactionID = UUID.Zero; + + private UUID m_transactionID; + private sbyte type = 0; private byte wearableType = 0; private byte[] m_oldData = null; public ulong XferID; private Scene m_Scene; - public AssetXferUploader(AgentAssetTransactions transactions, Scene scene, bool dumpAssetToFile) + /// + /// AssetXferUploader constructor + /// + /// /param> + /// + /// + /// + /// If true then when the asset is uploaded it is dumped to a file with the format + /// String.Format("{6}_{7}_{0:d2}{1:d2}{2:d2}_{3:d2}{4:d2}{5:d2}.dat", + /// now.Year, now.Month, now.Day, now.Hour, now.Minute, + /// now.Second, m_asset.Name, m_asset.Type); + /// for debugging purposes. + /// + public AssetXferUploader( + AgentAssetTransactions transactions, Scene scene, UUID transactionID, bool dumpAssetToFile) { m_transactions = transactions; + m_transactionID = transactionID; m_Scene = scene; m_dumpAssetToFile = dumpAssetToFile; } @@ -189,7 +206,6 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction m_asset.Local = storeLocal; m_asset.Temporary = tempFile; - TransactionID = transaction; m_storeLocal = storeLocal; if (m_asset.Data.Length > 2) @@ -234,13 +250,13 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction // Remove ourselves from the list of transactions if completion was delayed until the transaction // was complete. // TODO: Should probably do the same for create item. - m_transactions.RemoveXferUploader(TransactionID); + m_transactions.RemoveXferUploader(m_transactionID); } else if (m_updateTaskItem) { StoreAssetForTaskItemUpdate(m_updateTaskItemData); - m_transactions.RemoveXferUploader(TransactionID); + m_transactions.RemoveXferUploader(m_transactionID); } else if (m_storeLocal) { @@ -250,7 +266,7 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction m_log.DebugFormat( "[ASSET XFER UPLOADER]: Uploaded asset {0} for transaction {1}", - m_asset.FullID, TransactionID); + m_asset.FullID, m_transactionID); if (m_dumpAssetToFile) { @@ -278,40 +294,37 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction } public void RequestCreateInventoryItem(IClientAPI remoteClient, - UUID transactionID, UUID folderID, uint callbackID, + UUID folderID, uint callbackID, string description, string name, sbyte invType, sbyte type, byte wearableType, uint nextOwnerMask) { - if (TransactionID == transactionID) + InventFolder = folderID; + m_name = name; + m_description = description; + this.type = type; + this.invType = invType; + this.wearableType = wearableType; + nextPerm = nextOwnerMask; + m_asset.Name = name; + m_asset.Description = description; + m_asset.Type = type; + + // We must lock to avoid a race with a separate thread uploading the asset. + lock (this) { - InventFolder = folderID; - m_name = name; - m_description = description; - this.type = type; - this.invType = invType; - this.wearableType = wearableType; - nextPerm = nextOwnerMask; - m_asset.Name = name; - m_asset.Description = description; - m_asset.Type = type; - - // We must lock to avoid a race with a separate thread uploading the asset. - lock (this) + if (m_uploadState == UploadState.Complete) { - if (m_uploadState == UploadState.Complete) - { - DoCreateItem(callbackID); - } - else - { - m_createItem = true; //set flag so the inventory item is created when upload is complete - m_createItemCallback = callbackID; - } + DoCreateItem(callbackID); + } + else + { + m_createItem = true; //set flag so the inventory item is created when upload is complete + m_createItemCallback = callbackID; } } } - public void RequestUpdateInventoryItem(IClientAPI remoteClient, UUID transactionID, InventoryItemBase item) + public void RequestUpdateInventoryItem(IClientAPI remoteClient, InventoryItemBase item) { // We must lock to avoid a race with a separate thread uploading the asset. lock (this) @@ -342,7 +355,7 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction } } - public void RequestUpdateTaskInventoryItem(IClientAPI remoteClient, UUID transactionID, TaskInventoryItem taskItem) + public void RequestUpdateTaskInventoryItem(IClientAPI remoteClient, TaskInventoryItem taskItem) { // We must lock to avoid a race with a separate thread uploading the asset. lock (this) -- cgit v1.1 From 7d6ac75f872998ef175b3887391db0610fab1464 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Tue, 25 Sep 2012 23:12:28 +0100 Subject: Comment out old m_storeLocal from AssetXferUploader. This was only used if none of new item, update item or update task item had been set. But since all transactions go through these paths this old code is redundant. --- .../CoreModules/Agent/AssetTransaction/AssetXferUploader.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs index a852767..9a1dd4d 100644 --- a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs +++ b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs @@ -85,7 +85,7 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction private string m_description = String.Empty; private bool m_dumpAssetToFile; private string m_name = String.Empty; - private bool m_storeLocal; +// private bool m_storeLocal; private uint nextPerm = 0; private IClientAPI ourClient; @@ -206,7 +206,7 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction m_asset.Local = storeLocal; m_asset.Temporary = tempFile; - m_storeLocal = storeLocal; +// m_storeLocal = storeLocal; if (m_asset.Data.Length > 2) { @@ -258,10 +258,10 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction m_transactions.RemoveXferUploader(m_transactionID); } - else if (m_storeLocal) - { - m_Scene.AssetService.Store(m_asset); - } +// else if (m_storeLocal) +// { +// m_Scene.AssetService.Store(m_asset); +// } } m_log.DebugFormat( -- cgit v1.1 From fdd4361928e5e3defa2afba5588738f57cdc426d Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Tue, 25 Sep 2012 23:30:25 +0100 Subject: Fix very recently introduced race condition where a CreateNewItem outracing an UploadAsset request could throw an exception because m_asset did not yet exist. This was accidentally introduced in 4fc0cfb This commit also consistently removes the AssetXferUploader when the transaction completes, no matter if it completed on asset upload or item operation. The amount of data being retained was small, since this was clothing/bodypart metadata in the asset rather than textures themselves. --- .../Agent/AssetTransaction/AssetXferUploader.cs | 37 +++++++++++----------- 1 file changed, 18 insertions(+), 19 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs index 9a1dd4d..f6dd5af 100644 --- a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs +++ b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs @@ -113,6 +113,8 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction public AssetXferUploader( AgentAssetTransactions transactions, Scene scene, UUID transactionID, bool dumpAssetToFile) { + m_asset = new AssetBase(); + m_transactions = transactions; m_transactionID = transactionID; m_Scene = scene; @@ -197,9 +199,7 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction ourClient = remoteClient; - m_asset = new AssetBase() { FullID = assetID }; - m_asset.Name = "blank"; - m_asset.Description = "empty"; + m_asset.FullID = assetID; m_asset.Type = type; m_asset.CreatorID = remoteClient.AgentId.ToString(); m_asset.Data = data; @@ -241,22 +241,15 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction if (m_createItem) { - DoCreateItem(m_createItemCallback); + CompleteCreateItem(m_createItemCallback); } else if (m_updateItem) { - StoreAssetForItemUpdate(m_updateItemData); - - // Remove ourselves from the list of transactions if completion was delayed until the transaction - // was complete. - // TODO: Should probably do the same for create item. - m_transactions.RemoveXferUploader(m_transactionID); + CompleteItemUpdate(m_updateItemData); } else if (m_updateTaskItem) { - StoreAssetForTaskItemUpdate(m_updateTaskItemData); - - m_transactions.RemoveXferUploader(m_transactionID); + CompleteTaskItemUpdate(m_updateTaskItemData); } // else if (m_storeLocal) // { @@ -314,7 +307,7 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction { if (m_uploadState == UploadState.Complete) { - DoCreateItem(callbackID); + CompleteCreateItem(callbackID); } else { @@ -341,7 +334,7 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction if (m_uploadState == UploadState.Complete) { - StoreAssetForItemUpdate(item); + CompleteItemUpdate(item); } else { @@ -367,7 +360,7 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction if (m_uploadState == UploadState.Complete) { - StoreAssetForTaskItemUpdate(taskItem); + CompleteTaskItemUpdate(taskItem); } else { @@ -381,29 +374,33 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction /// Store the asset for the given item when it has been uploaded. /// /// - private void StoreAssetForItemUpdate(InventoryItemBase item) + private void CompleteItemUpdate(InventoryItemBase item) { // m_log.DebugFormat( // "[ASSET XFER UPLOADER]: Storing asset {0} for earlier item update for {1} for {2}", // m_asset.FullID, item.Name, ourClient.Name); m_Scene.AssetService.Store(m_asset); + + m_transactions.RemoveXferUploader(m_transactionID); } /// /// Store the asset for the given task item when it has been uploaded. /// /// - private void StoreAssetForTaskItemUpdate(TaskInventoryItem taskItem) + private void CompleteTaskItemUpdate(TaskInventoryItem taskItem) { // m_log.DebugFormat( // "[ASSET XFER UPLOADER]: Storing asset {0} for earlier task item update for {1} for {2}", // m_asset.FullID, taskItem.Name, ourClient.Name); m_Scene.AssetService.Store(m_asset); + + m_transactions.RemoveXferUploader(m_transactionID); } - private void DoCreateItem(uint callbackID) + private void CompleteCreateItem(uint callbackID) { ValidateAssets(); m_Scene.AssetService.Store(m_asset); @@ -433,6 +430,8 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction ourClient.SendInventoryItemCreateUpdate(item, callbackID); else ourClient.SendAlertMessage("Unable to create inventory item"); + + m_transactions.RemoveXferUploader(m_transactionID); } private void ValidateAssets() -- cgit v1.1 From 9eca154bced7423867e8f9597b8baf214de79087 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Wed, 26 Sep 2012 23:17:21 +0100 Subject: Make it possible to rescale SOGs when they are not in a scene. --- .../Region/Framework/Scenes/SceneObjectGroup.cs | 53 ++++++++++++---------- OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | 20 ++++---- 2 files changed, 42 insertions(+), 31 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index f1df6d6..ddcc956 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -3483,27 +3483,35 @@ namespace OpenSim.Region.Framework.Scenes /// public void GroupResize(Vector3 scale) { - scale.X = Math.Max(Scene.m_minNonphys, Math.Min(Scene.m_maxNonphys, scale.X)); - scale.Y = Math.Max(Scene.m_minNonphys, Math.Min(Scene.m_maxNonphys, scale.Y)); - scale.Z = Math.Max(Scene.m_minNonphys, Math.Min(Scene.m_maxNonphys, scale.Z)); +// m_log.DebugFormat( +// "[SCENE OBJECT GROUP]: Group resizing {0} {1} from {2} to {3}", Name, LocalId, RootPart.Scale, scale); PhysicsActor pa = m_rootPart.PhysActor; - if (pa != null && pa.IsPhysical) + RootPart.StoreUndoState(true); + + if (Scene != null) { - scale.X = Math.Max(Scene.m_minPhys, Math.Min(Scene.m_maxPhys, scale.X)); - scale.Y = Math.Max(Scene.m_minPhys, Math.Min(Scene.m_maxPhys, scale.Y)); - scale.Z = Math.Max(Scene.m_minPhys, Math.Min(Scene.m_maxPhys, scale.Z)); + scale.X = Math.Max(Scene.m_minNonphys, Math.Min(Scene.m_maxNonphys, scale.X)); + scale.Y = Math.Max(Scene.m_minNonphys, Math.Min(Scene.m_maxNonphys, scale.Y)); + scale.Z = Math.Max(Scene.m_minNonphys, Math.Min(Scene.m_maxNonphys, scale.Z)); + + if (pa != null && pa.IsPhysical) + { + scale.X = Math.Max(Scene.m_minPhys, Math.Min(Scene.m_maxPhys, scale.X)); + scale.Y = Math.Max(Scene.m_minPhys, Math.Min(Scene.m_maxPhys, scale.Y)); + scale.Z = Math.Max(Scene.m_minPhys, Math.Min(Scene.m_maxPhys, scale.Z)); + } } float x = (scale.X / RootPart.Scale.X); float y = (scale.Y / RootPart.Scale.Y); float z = (scale.Z / RootPart.Scale.Z); - SceneObjectPart[] parts; - if (x > 1.0f || y > 1.0f || z > 1.0f) + SceneObjectPart[] parts = m_parts.GetArray(); + + if (Scene != null & (x > 1.0f || y > 1.0f || z > 1.0f)) { - parts = m_parts.GetArray(); for (int i = 0; i < parts.Length; i++) { SceneObjectPart obPart = parts[i]; @@ -3516,7 +3524,7 @@ namespace OpenSim.Region.Framework.Scenes if (pa != null && pa.IsPhysical) { - if (oldSize.X * x > m_scene.m_maxPhys) + if (oldSize.X * x > Scene.m_maxPhys) { f = m_scene.m_maxPhys / oldSize.X; a = f / x; @@ -3524,7 +3532,7 @@ namespace OpenSim.Region.Framework.Scenes y *= a; z *= a; } - else if (oldSize.X * x < m_scene.m_minPhys) + else if (oldSize.X * x < Scene.m_minPhys) { f = m_scene.m_minPhys / oldSize.X; a = f / x; @@ -3533,7 +3541,7 @@ namespace OpenSim.Region.Framework.Scenes z *= a; } - if (oldSize.Y * y > m_scene.m_maxPhys) + if (oldSize.Y * y > Scene.m_maxPhys) { f = m_scene.m_maxPhys / oldSize.Y; a = f / y; @@ -3541,7 +3549,7 @@ namespace OpenSim.Region.Framework.Scenes y *= a; z *= a; } - else if (oldSize.Y * y < m_scene.m_minPhys) + else if (oldSize.Y * y < Scene.m_minPhys) { f = m_scene.m_minPhys / oldSize.Y; a = f / y; @@ -3550,7 +3558,7 @@ namespace OpenSim.Region.Framework.Scenes z *= a; } - if (oldSize.Z * z > m_scene.m_maxPhys) + if (oldSize.Z * z > Scene.m_maxPhys) { f = m_scene.m_maxPhys / oldSize.Z; a = f / z; @@ -3558,7 +3566,7 @@ namespace OpenSim.Region.Framework.Scenes y *= a; z *= a; } - else if (oldSize.Z * z < m_scene.m_minPhys) + else if (oldSize.Z * z < Scene.m_minPhys) { f = m_scene.m_minPhys / oldSize.Z; a = f / z; @@ -3569,7 +3577,7 @@ namespace OpenSim.Region.Framework.Scenes } else { - if (oldSize.X * x > m_scene.m_maxNonphys) + if (oldSize.X * x > Scene.m_maxNonphys) { f = m_scene.m_maxNonphys / oldSize.X; a = f / x; @@ -3577,7 +3585,7 @@ namespace OpenSim.Region.Framework.Scenes y *= a; z *= a; } - else if (oldSize.X * x < m_scene.m_minNonphys) + else if (oldSize.X * x < Scene.m_minNonphys) { f = m_scene.m_minNonphys / oldSize.X; a = f / x; @@ -3586,7 +3594,7 @@ namespace OpenSim.Region.Framework.Scenes z *= a; } - if (oldSize.Y * y > m_scene.m_maxNonphys) + if (oldSize.Y * y > Scene.m_maxNonphys) { f = m_scene.m_maxNonphys / oldSize.Y; a = f / y; @@ -3594,7 +3602,7 @@ namespace OpenSim.Region.Framework.Scenes y *= a; z *= a; } - else if (oldSize.Y * y < m_scene.m_minNonphys) + else if (oldSize.Y * y < Scene.m_minNonphys) { f = m_scene.m_minNonphys / oldSize.Y; a = f / y; @@ -3603,7 +3611,7 @@ namespace OpenSim.Region.Framework.Scenes z *= a; } - if (oldSize.Z * z > m_scene.m_maxNonphys) + if (oldSize.Z * z > Scene.m_maxNonphys) { f = m_scene.m_maxNonphys / oldSize.Z; a = f / z; @@ -3611,7 +3619,7 @@ namespace OpenSim.Region.Framework.Scenes y *= a; z *= a; } - else if (oldSize.Z * z < m_scene.m_minNonphys) + else if (oldSize.Z * z < Scene.m_minNonphys) { f = m_scene.m_minNonphys / oldSize.Z; a = f / z; @@ -3631,7 +3639,6 @@ namespace OpenSim.Region.Framework.Scenes RootPart.Resize(prevScale); - parts = m_parts.GetArray(); for (int i = 0; i < parts.Length; i++) { SceneObjectPart obPart = parts[i]; diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index 4af508e..44573eb 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -2972,16 +2972,20 @@ namespace OpenSim.Region.Framework.Scenes /// public void Resize(Vector3 scale) { - scale.X = Math.Max(ParentGroup.Scene.m_minNonphys, Math.Min(ParentGroup.Scene.m_maxNonphys, scale.X)); - scale.Y = Math.Max(ParentGroup.Scene.m_minNonphys, Math.Min(ParentGroup.Scene.m_maxNonphys, scale.Y)); - scale.Z = Math.Max(ParentGroup.Scene.m_minNonphys, Math.Min(ParentGroup.Scene.m_maxNonphys, scale.Z)); - PhysicsActor pa = PhysActor; - if (pa != null && pa.IsPhysical) + + if (ParentGroup.Scene != null) { - scale.X = Math.Max(ParentGroup.Scene.m_minPhys, Math.Min(ParentGroup.Scene.m_maxPhys, scale.X)); - scale.Y = Math.Max(ParentGroup.Scene.m_minPhys, Math.Min(ParentGroup.Scene.m_maxPhys, scale.Y)); - scale.Z = Math.Max(ParentGroup.Scene.m_minPhys, Math.Min(ParentGroup.Scene.m_maxPhys, scale.Z)); + scale.X = Math.Max(ParentGroup.Scene.m_minNonphys, Math.Min(ParentGroup.Scene.m_maxNonphys, scale.X)); + scale.Y = Math.Max(ParentGroup.Scene.m_minNonphys, Math.Min(ParentGroup.Scene.m_maxNonphys, scale.Y)); + scale.Z = Math.Max(ParentGroup.Scene.m_minNonphys, Math.Min(ParentGroup.Scene.m_maxNonphys, scale.Z)); + + if (pa != null && pa.IsPhysical) + { + scale.X = Math.Max(ParentGroup.Scene.m_minPhys, Math.Min(ParentGroup.Scene.m_maxPhys, scale.X)); + scale.Y = Math.Max(ParentGroup.Scene.m_minPhys, Math.Min(ParentGroup.Scene.m_maxPhys, scale.Y)); + scale.Z = Math.Max(ParentGroup.Scene.m_minPhys, Math.Min(ParentGroup.Scene.m_maxPhys, scale.Z)); + } } // m_log.DebugFormat("[SCENE OBJECT PART]: Resizing {0} {1} to {2}", Name, LocalId, scale); -- cgit v1.1 From b52311b8f80db28183069901d5540d61db0bd8ea Mon Sep 17 00:00:00 2001 From: Melanie Date: Thu, 27 Sep 2012 17:16:39 +0100 Subject: Remove a core undo call that we don't need. --- OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs | 2 -- 1 file changed, 2 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index ddcc956..bf898bb 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -3488,8 +3488,6 @@ namespace OpenSim.Region.Framework.Scenes PhysicsActor pa = m_rootPart.PhysActor; - RootPart.StoreUndoState(true); - if (Scene != null) { scale.X = Math.Max(Scene.m_minNonphys, Math.Min(Scene.m_maxNonphys, scale.X)); -- cgit v1.1 From 3db10fdbefa94509d318b9574e5a96c9567d5377 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 28 Sep 2012 01:50:21 +0100 Subject: Lock GDI+ portion og VectorRenderModule.GetDrawStringSize() to prevent concurrent thread use provoking mono crashes. Same rationale as commit 13690582. --- .../Scripting/VectorRender/VectorRenderModule.cs | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs b/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs index d82551e..b4e3d77 100644 --- a/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs +++ b/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs @@ -112,14 +112,19 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender public void GetDrawStringSize(string text, string fontName, int fontSize, out double xSize, out double ySize) { - using (Font myFont = new Font(fontName, fontSize)) + lock (this) { - SizeF stringSize = new SizeF(); - lock (m_graph) + using (Font myFont = new Font(fontName, fontSize)) { - stringSize = m_graph.MeasureString(text, myFont); - xSize = stringSize.Width; - ySize = stringSize.Height; + SizeF stringSize = new SizeF(); + + // XXX: This lock may be unnecessary. + lock (m_graph) + { + stringSize = m_graph.MeasureString(text, myFont); + xSize = stringSize.Width; + ySize = stringSize.Height; + } } } } -- cgit v1.1 From ee7cda261cbbc9dcd558c35eabc070cc0bf45644 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Tue, 18 Sep 2012 08:39:52 -0700 Subject: BulletSim: move a bunch of common logic out of BSPrim and BSCharacter and into the parent class BSPhysObject. Rework collision logic to enable extra collision after done colliding. Rename 'Scene' to 'PhysicsScene' to differentiate it from the simulator 'Scene'. --- .../Region/Physics/BulletSPlugin/BSCharacter.cs | 238 +++++++-------------- OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs | 10 +- OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs | 42 ++-- .../Region/Physics/BulletSPlugin/BSPhysObject.cs | 138 +++++++++++- OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | 232 +++++++------------- OpenSim/Region/Physics/BulletSPlugin/BSScene.cs | 60 ++++-- .../Region/Physics/BulletSPlugin/BulletSimAPI.cs | 57 +---- 7 files changed, 361 insertions(+), 416 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs index 526dbad..57d5726 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs @@ -28,7 +28,7 @@ using System; using System.Collections.Generic; using System.Reflection; using log4net; -using OpenMetaverse; +using OMV = OpenMetaverse; using OpenSim.Framework; using OpenSim.Region.Physics.Manager; @@ -39,25 +39,24 @@ public class BSCharacter : BSPhysObject private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private static readonly string LogHeader = "[BULLETS CHAR]"; - public BSScene Scene { get; private set; } private String _avName; // private bool _stopped; - private Vector3 _size; - private Vector3 _scale; + private OMV.Vector3 _size; + private OMV.Vector3 _scale; private PrimitiveBaseShape _pbs; private uint _localID = 0; private bool _grabbed; private bool _selected; - private Vector3 _position; + private OMV.Vector3 _position; private float _mass; public float _density; public float _avatarVolume; - private Vector3 _force; - private Vector3 _velocity; - private Vector3 _torque; + private OMV.Vector3 _force; + private OMV.Vector3 _velocity; + private OMV.Vector3 _torque; private float _collisionScore; - private Vector3 _acceleration; - private Quaternion _orientation; + private OMV.Vector3 _acceleration; + private OMV.Quaternion _orientation; private int _physicsActorType; private bool _isPhysical; private bool _flying; @@ -69,18 +68,14 @@ public class BSCharacter : BSPhysObject private long _collidingGroundStep; private bool _collidingObj; private bool _floatOnWater; - private Vector3 _rotationalVelocity; + private OMV.Vector3 _rotationalVelocity; private bool _kinematic; private float _buoyancy; - public override BulletBody BSBody { get; set; } - public override BulletShape BSShape { get; set; } - public override BSLinkset Linkset { get; set; } - private int _subscribedEventsMs = 0; private int _nextCollisionOkTime = 0; - private Vector3 _PIDTarget; + private OMV.Vector3 _PIDTarget; private bool _usePID; private float _PIDTau; private bool _useHoverPID; @@ -88,26 +83,24 @@ public class BSCharacter : BSPhysObject private PIDHoverType _PIDHoverType; private float _PIDHoverTao; - public BSCharacter(uint localID, String avName, BSScene parent_scene, Vector3 pos, Vector3 size, bool isFlying) + public BSCharacter(uint localID, String avName, BSScene parent_scene, OMV.Vector3 pos, OMV.Vector3 size, bool isFlying) { + base.BaseInitialize(parent_scene); _localID = localID; _avName = avName; - Scene = parent_scene; _physicsActorType = (int)ActorTypes.Agent; _position = pos; _size = size; _flying = isFlying; - _orientation = Quaternion.Identity; - _velocity = Vector3.Zero; + _orientation = OMV.Quaternion.Identity; + _velocity = OMV.Vector3.Zero; _buoyancy = ComputeBuoyancyFromFlying(isFlying); // The dimensions of the avatar capsule are kept in the scale. // Physics creates a unit capsule which is scaled by the physics engine. - _scale = new Vector3(Scene.Params.avatarCapsuleRadius, Scene.Params.avatarCapsuleRadius, size.Z); - _density = Scene.Params.avatarDensity; + _scale = new OMV.Vector3(PhysicsScene.Params.avatarCapsuleRadius, PhysicsScene.Params.avatarCapsuleRadius, size.Z); + _density = PhysicsScene.Params.avatarDensity; ComputeAvatarVolumeAndMass(); // set _avatarVolume and _mass based on capsule size, _density and _scale - Linkset = new BSLinkset(Scene, this); - ShapeData shapeData = new ShapeData(); shapeData.ID = _localID; shapeData.Type = ShapeData.PhysicsShapeType.SHAPE_AVATAR; @@ -118,19 +111,19 @@ public class BSCharacter : BSPhysObject shapeData.Mass = _mass; shapeData.Buoyancy = _buoyancy; shapeData.Static = ShapeData.numericFalse; - shapeData.Friction = Scene.Params.avatarFriction; - shapeData.Restitution = Scene.Params.avatarRestitution; + shapeData.Friction = PhysicsScene.Params.avatarFriction; + shapeData.Restitution = PhysicsScene.Params.avatarRestitution; // do actual create at taint time - Scene.TaintedObject("BSCharacter.create", delegate() + PhysicsScene.TaintedObject("BSCharacter.create", delegate() { DetailLog("{0},BSCharacter.create", _localID); - BulletSimAPI.CreateObject(Scene.WorldID, shapeData); + BulletSimAPI.CreateObject(PhysicsScene.WorldID, shapeData); // Set the buoyancy for flying. This will be refactored when all the settings happen in C# - BulletSimAPI.SetObjectBuoyancy(Scene.WorldID, LocalID, _buoyancy); + BulletSimAPI.SetObjectBuoyancy(PhysicsScene.WorldID, LocalID, _buoyancy); - BSBody = new BulletBody(LocalID, BulletSimAPI.GetBodyHandle2(Scene.World.Ptr, LocalID)); + BSBody = new BulletBody(LocalID, BulletSimAPI.GetBodyHandle2(PhysicsScene.World.Ptr, LocalID)); }); return; @@ -140,9 +133,9 @@ public class BSCharacter : BSPhysObject public override void Destroy() { DetailLog("{0},BSCharacter.Destroy", LocalID); - Scene.TaintedObject("BSCharacter.destroy", delegate() + PhysicsScene.TaintedObject("BSCharacter.destroy", delegate() { - BulletSimAPI.DestroyObject(Scene.WorldID, _localID); + BulletSimAPI.DestroyObject(PhysicsScene.WorldID, _localID); }); } @@ -154,11 +147,11 @@ public class BSCharacter : BSPhysObject public override bool Stopped { get { return false; } } - public override Vector3 Size { + public override OMV.Vector3 Size { get { // Avatar capsule size is kept in the scale parameter. - return new Vector3(_scale.X * 2, _scale.Y * 2, _scale.Z); + return new OMV.Vector3(_scale.X * 2, _scale.Y * 2, _scale.Z); } set { @@ -171,9 +164,9 @@ public class BSCharacter : BSPhysObject ComputeAvatarVolumeAndMass(); - Scene.TaintedObject("BSCharacter.setSize", delegate() + PhysicsScene.TaintedObject("BSCharacter.setSize", delegate() { - BulletSimAPI.SetObjectScaleMass(Scene.WorldID, LocalID, _scale, _mass, true); + BulletSimAPI.SetObjectScaleMass(PhysicsScene.WorldID, LocalID, _scale, _mass, true); }); } @@ -198,9 +191,27 @@ public class BSCharacter : BSPhysObject public override void CrossingFailure() { return; } public override void link(PhysicsActor obj) { return; } public override void delink() { return; } - public override void LockAngularMotion(Vector3 axis) { return; } - public override Vector3 Position { + // Set motion values to zero. + // Do it to the properties so the values get set in the physics engine. + // Push the setting of the values to the viewer. + // Called at taint time! + public override void ZeroMotion() + { + _velocity = OMV.Vector3.Zero; + _acceleration = OMV.Vector3.Zero; + _rotationalVelocity = OMV.Vector3.Zero; + + // Zero some other properties directly into the physics engine + BulletSimAPI.SetLinearVelocity2(BSBody.Ptr, OMV.Vector3.Zero); + BulletSimAPI.SetAngularVelocity2(BSBody.Ptr, OMV.Vector3.Zero); + BulletSimAPI.SetInterpolationVelocity2(BSBody.Ptr, OMV.Vector3.Zero, OMV.Vector3.Zero); + BulletSimAPI.ClearForces2(BSBody.Ptr); + } + + public override void LockAngularMotion(OMV.Vector3 axis) { return; } + + public override OMV.Vector3 Position { get { // _position = BulletSimAPI.GetObjectPosition(Scene.WorldID, _localID); return _position; @@ -209,10 +220,10 @@ public class BSCharacter : BSPhysObject _position = value; PositionSanityCheck(); - Scene.TaintedObject("BSCharacter.setPosition", delegate() + PhysicsScene.TaintedObject("BSCharacter.setPosition", delegate() { DetailLog("{0},BSCharacter.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation); - BulletSimAPI.SetObjectTranslation(Scene.WorldID, _localID, _position, _orientation); + BulletSimAPI.SetObjectTranslation(PhysicsScene.WorldID, _localID, _position, _orientation); }); } } @@ -225,7 +236,7 @@ public class BSCharacter : BSPhysObject bool ret = false; // If below the ground, move the avatar up - float terrainHeight = Scene.TerrainManager.GetTerrainHeightAtXYZ(_position); + float terrainHeight = PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(_position); if (Position.Z < terrainHeight) { DetailLog("{0},BSCharacter.PositionAdjustUnderGround,call,pos={1},terrain={2}", LocalID, _position, terrainHeight); @@ -247,10 +258,10 @@ public class BSCharacter : BSPhysObject { // The new position value must be pushed into the physics engine but we can't // just assign to "Position" because of potential call loops. - Scene.TaintedObject("BSCharacter.PositionSanityCheck", delegate() + PhysicsScene.TaintedObject("BSCharacter.PositionSanityCheck", delegate() { DetailLog("{0},BSCharacter.PositionSanityCheck,taint,pos={1},orient={2}", LocalID, _position, _orientation); - BulletSimAPI.SetObjectTranslation(Scene.WorldID, _localID, _position, _orientation); + BulletSimAPI.SetObjectTranslation(PhysicsScene.WorldID, _localID, _position, _orientation); }); ret = true; } @@ -266,15 +277,15 @@ public class BSCharacter : BSPhysObject // used when we only want this prim's mass and not the linkset thing public override float MassRaw { get {return _mass; } } - public override Vector3 Force { + public override OMV.Vector3 Force { get { return _force; } set { _force = value; // m_log.DebugFormat("{0}: Force = {1}", LogHeader, _force); - Scene.TaintedObject("BSCharacter.SetForce", delegate() + PhysicsScene.TaintedObject("BSCharacter.SetForce", delegate() { DetailLog("{0},BSCharacter.setForce,taint,force={1}", LocalID, _force); - BulletSimAPI.SetObjectForce(Scene.WorldID, LocalID, _force); + BulletSimAPI.SetObjectForce(PhysicsScene.WorldID, LocalID, _force); }); } } @@ -284,28 +295,28 @@ public class BSCharacter : BSPhysObject set { return; } } public override void VehicleFloatParam(int param, float value) { } - public override void VehicleVectorParam(int param, Vector3 value) {} - public override void VehicleRotationParam(int param, Quaternion rotation) { } + public override void VehicleVectorParam(int param, OMV.Vector3 value) {} + public override void VehicleRotationParam(int param, OMV.Quaternion rotation) { } public override void VehicleFlags(int param, bool remove) { } // Allows the detection of collisions with inherently non-physical prims. see llVolumeDetect for more public override void SetVolumeDetect(int param) { return; } - public override Vector3 GeometricCenter { get { return Vector3.Zero; } } - public override Vector3 CenterOfMass { get { return Vector3.Zero; } } - public override Vector3 Velocity { + public override OMV.Vector3 GeometricCenter { get { return OMV.Vector3.Zero; } } + public override OMV.Vector3 CenterOfMass { get { return OMV.Vector3.Zero; } } + public override OMV.Vector3 Velocity { get { return _velocity; } set { _velocity = value; // m_log.DebugFormat("{0}: set velocity = {1}", LogHeader, _velocity); - Scene.TaintedObject("BSCharacter.setVelocity", delegate() + PhysicsScene.TaintedObject("BSCharacter.setVelocity", delegate() { DetailLog("{0},BSCharacter.setVelocity,taint,vel={1}", LocalID, _velocity); - BulletSimAPI.SetObjectVelocity(Scene.WorldID, _localID, _velocity); + BulletSimAPI.SetObjectVelocity(PhysicsScene.WorldID, _localID, _velocity); }); } } - public override Vector3 Torque { + public override OMV.Vector3 Torque { get { return _torque; } set { _torque = value; } @@ -315,19 +326,19 @@ public class BSCharacter : BSPhysObject set { _collisionScore = value; } } - public override Vector3 Acceleration { + public override OMV.Vector3 Acceleration { get { return _acceleration; } set { _acceleration = value; } } - public override Quaternion Orientation { + public override OMV.Quaternion Orientation { get { return _orientation; } set { _orientation = value; // m_log.DebugFormat("{0}: set orientation to {1}", LogHeader, _orientation); - Scene.TaintedObject("BSCharacter.setOrientation", delegate() + PhysicsScene.TaintedObject("BSCharacter.setOrientation", delegate() { // _position = BulletSimAPI.GetObjectPosition(Scene.WorldID, _localID); - BulletSimAPI.SetObjectTranslation(Scene.WorldID, _localID, _position, _orientation); + BulletSimAPI.SetObjectTranslation(PhysicsScene.WorldID, _localID, _position, _orientation); }); } } @@ -364,11 +375,11 @@ public class BSCharacter : BSPhysObject set { _throttleUpdates = value; } } public override bool IsColliding { - get { return (_collidingStep == Scene.SimulationStep); } + get { return (_collidingStep == PhysicsScene.SimulationStep); } set { _isColliding = value; } } public override bool CollidingGround { - get { return (_collidingGroundStep == Scene.SimulationStep); } + get { return (_collidingGroundStep == PhysicsScene.SimulationStep); } set { _collidingGround = value; } } public override bool CollidingObj { @@ -378,7 +389,7 @@ public class BSCharacter : BSPhysObject public override bool FloatOnWater { set { _floatOnWater = value; } } - public override Vector3 RotationalVelocity { + public override OMV.Vector3 RotationalVelocity { get { return _rotationalVelocity; } set { _rotationalVelocity = value; } } @@ -390,16 +401,16 @@ public class BSCharacter : BSPhysObject public override float Buoyancy { get { return _buoyancy; } set { _buoyancy = value; - Scene.TaintedObject("BSCharacter.setBuoyancy", delegate() + PhysicsScene.TaintedObject("BSCharacter.setBuoyancy", delegate() { DetailLog("{0},BSCharacter.setBuoyancy,taint,buoy={1}", LocalID, _buoyancy); - BulletSimAPI.SetObjectBuoyancy(Scene.WorldID, LocalID, _buoyancy); + BulletSimAPI.SetObjectBuoyancy(PhysicsScene.WorldID, LocalID, _buoyancy); }); } } // Used for MoveTo - public override Vector3 PIDTarget { + public override OMV.Vector3 PIDTarget { set { _PIDTarget = value; } } public override bool PIDActive { @@ -425,19 +436,19 @@ public class BSCharacter : BSPhysObject } // For RotLookAt - public override Quaternion APIDTarget { set { return; } } + public override OMV.Quaternion APIDTarget { set { return; } } public override bool APIDActive { set { return; } } public override float APIDStrength { set { return; } } public override float APIDDamping { set { return; } } - public override void AddForce(Vector3 force, bool pushforce) { + public override void AddForce(OMV.Vector3 force, bool pushforce) { if (force.IsFinite()) { _force.X += force.X; _force.Y += force.Y; _force.Z += force.Z; // m_log.DebugFormat("{0}: AddForce. adding={1}, newForce={2}", LogHeader, force, _force); - Scene.TaintedObject("BSCharacter.AddForce", delegate() + PhysicsScene.TaintedObject("BSCharacter.AddForce", delegate() { DetailLog("{0},BSCharacter.setAddForce,taint,addedForce={1}", LocalID, _force); BulletSimAPI.SetObjectForce2(BSBody.Ptr, _force); @@ -450,42 +461,9 @@ public class BSCharacter : BSPhysObject //m_lastUpdateSent = false; } - public override void AddAngularForce(Vector3 force, bool pushforce) { - } - public override void SetMomentum(Vector3 momentum) { - } - - // Turn on collision events at a rate no faster than one every the given milliseconds - public override void SubscribeEvents(int ms) { - _subscribedEventsMs = ms; - if (ms > 0) - { - // make sure first collision happens - _nextCollisionOkTime = Util.EnvironmentTickCount() - _subscribedEventsMs; - - Scene.TaintedObject("BSCharacter.SubscribeEvents", delegate() - { - BulletSimAPI.AddToCollisionFlags2(BSBody.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); - }); - } + public override void AddAngularForce(OMV.Vector3 force, bool pushforce) { } - - public override void ZeroMotion() - { - return; - } - - // Stop collision events - public override void UnSubscribeEvents() { - _subscribedEventsMs = 0; - Scene.TaintedObject("BSCharacter.UnSubscribeEvents", delegate() - { - BulletSimAPI.RemoveFromCollisionFlags2(BSBody.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); - }); - } - // Return 'true' if someone has subscribed to events - public override bool SubscribedEvents() { - return (_subscribedEventsMs > 0); + public override void SetMomentum(OMV.Vector3 momentum) { } // set _avatarVolume and _mass based on capsule size, _density and _scale @@ -520,67 +498,15 @@ public class BSCharacter : BSPhysObject // Do some sanity checking for the avatar. Make sure it's above ground and inbounds. PositionSanityCheck2(); - float heightHere = Scene.TerrainManager.GetTerrainHeightAtXYZ(_position); // only for debug + float heightHere = PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(_position); // only for debug DetailLog("{0},BSCharacter.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5},terrain={6}", LocalID, _position, _orientation, _velocity, _acceleration, _rotationalVelocity, heightHere); } - // Called by the scene when a collision with this object is reported - // The collision, if it should be reported to the character, is placed in a collection - // that will later be sent to the simulator when SendCollisions() is called. - CollisionEventUpdate collisionCollection = null; - public override bool Collide(uint collidingWith, BSPhysObject collidee, Vector3 contactPoint, Vector3 contactNormal, float pentrationDepth) - { - bool ret = false; - - // The following makes IsColliding() and IsCollidingGround() work - _collidingStep = Scene.SimulationStep; - if (collidingWith <= Scene.TerrainManager.HighestTerrainID) - { - _collidingGroundStep = Scene.SimulationStep; - } - // DetailLog("{0},BSCharacter.Collison,call,with={1}", LocalID, collidingWith); - - // throttle collisions to the rate specified in the subscription - if (SubscribedEvents()) { - int nowTime = Scene.SimulationNowTime; - if (nowTime >= _nextCollisionOkTime) { - _nextCollisionOkTime = nowTime + _subscribedEventsMs; - - if (collisionCollection == null) - collisionCollection = new CollisionEventUpdate(); - collisionCollection.AddCollider(collidingWith, new ContactPoint(contactPoint, contactNormal, pentrationDepth)); - ret = true; - } - } - return ret; - } - - public override void SendCollisions() - { - /* - if (collisionCollection != null && collisionCollection.Count > 0) - { - base.SendCollisionUpdate(collisionCollection); - collisionCollection = null; - } - */ - // Kludge to make a collision call even if there are no collisions. - // This causes the avatar animation to get updated. - if (collisionCollection == null) - collisionCollection = new CollisionEventUpdate(); - base.SendCollisionUpdate(collisionCollection); - // If there were any collisions in the collection, make sure we don't use the - // same instance next time. - if (collisionCollection.Count > 0) - collisionCollection = null; - // End kludge - } - // Invoke the detailed logger and output something if it's enabled. private void DetailLog(string msg, params Object[] args) { - Scene.PhysicsLogging.Write(msg, args); + PhysicsScene.PhysicsLogging.Write(msg, args); } } } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs index 61006f0..2da2331 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs @@ -539,7 +539,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin // add Gravity and Buoyancy // There is some gravity, make a gravity force vector that is applied after object velocity. // m_VehicleBuoyancy: -1=2g; 0=1g; 1=0g; - Vector3 grav = m_prim.Scene.DefaultGravity * (m_prim.Mass * (1f - m_VehicleBuoyancy)); + Vector3 grav = m_prim.PhysicsScene.DefaultGravity * (m_prim.Mass * (1f - m_VehicleBuoyancy)); /* * RA: Not sure why one would do this @@ -552,7 +552,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin // Vector3 accel = new Vector3(-(m_dir.X - m_lastLinearVelocityVector.X / 0.1f), -(m_dir.Y - m_lastLinearVelocityVector.Y / 0.1f), m_dir.Z - m_lastLinearVelocityVector.Z / 0.1f); // If below the terrain, move us above the ground a little. - float terrainHeight = m_prim.Scene.TerrainManager.GetTerrainHeightAtXYZ(pos); + float terrainHeight = m_prim.PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(pos); // Taking the rotated size doesn't work here because m_prim.Size is the size of the root prim and not the linkset. // Need to add a m_prim.LinkSet.Size similar to m_prim.LinkSet.Mass. // Vector3 rotatedSize = m_prim.Size * m_prim.Orientation; @@ -570,7 +570,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin // We should hover, get the target height if ((m_flags & VehicleFlag.HOVER_WATER_ONLY) != 0) { - m_VhoverTargetHeight = m_prim.Scene.GetWaterLevelAtXYZ(pos) + m_VhoverHeight; + m_VhoverTargetHeight = m_prim.PhysicsScene.GetWaterLevelAtXYZ(pos) + m_VhoverHeight; } if ((m_flags & VehicleFlag.HOVER_TERRAIN_ONLY) != 0) { @@ -849,8 +849,8 @@ namespace OpenSim.Region.Physics.BulletSPlugin // Invoke the detailed logger and output something if it's enabled. private void VDetailLog(string msg, params Object[] args) { - if (m_prim.Scene.VehicleLoggingEnabled) - m_prim.Scene.PhysicsLogging.Write(msg, args); + if (m_prim.PhysicsScene.VehicleLoggingEnabled) + m_prim.PhysicsScene.PhysicsLogging.Write(msg, args); } } } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs index 7e784eb..005a758 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs @@ -36,11 +36,9 @@ public class BSLinkset { private static string LogHeader = "[BULLETSIM LINKSET]"; - private BSPhysObject m_linksetRoot; - public BSPhysObject LinksetRoot { get { return m_linksetRoot; } } + public BSPhysObject LinksetRoot { get; protected set; } - private BSScene m_physicsScene; - public BSScene PhysicsScene { get { return m_physicsScene; } } + public BSScene PhysicsScene { get; private set; } static int m_nextLinksetID = 1; public int LinksetID { get; private set; } @@ -81,8 +79,8 @@ public class BSLinkset // We create LOTS of linksets. if (m_nextLinksetID < 0) m_nextLinksetID = 1; - m_physicsScene = scene; - m_linksetRoot = parent; + PhysicsScene = scene; + LinksetRoot = parent; m_children = new List(); m_mass = parent.MassRaw; } @@ -131,7 +129,7 @@ public class BSLinkset // Return 'true' if the passed object is the root object of this linkset public bool IsRoot(BSPhysObject requestor) { - return (requestor.LocalID == m_linksetRoot.LocalID); + return (requestor.LocalID == LinksetRoot.LocalID); } public int NumberOfChildren { get { return m_children.Count; } } @@ -159,7 +157,7 @@ public class BSLinkset private float ComputeLinksetMass() { - float mass = m_linksetRoot.MassRaw; + float mass = LinksetRoot.MassRaw; foreach (BSPhysObject bp in m_children) { mass += bp.MassRaw; @@ -169,8 +167,8 @@ public class BSLinkset private OMV.Vector3 ComputeLinksetCenterOfMass() { - OMV.Vector3 com = m_linksetRoot.Position * m_linksetRoot.MassRaw; - float totalMass = m_linksetRoot.MassRaw; + OMV.Vector3 com = LinksetRoot.Position * LinksetRoot.MassRaw; + float totalMass = LinksetRoot.MassRaw; lock (m_linksetActivityLock) { @@ -188,7 +186,7 @@ public class BSLinkset private OMV.Vector3 ComputeLinksetGeometricCenter() { - OMV.Vector3 com = m_linksetRoot.Position; + OMV.Vector3 com = LinksetRoot.Position; lock (m_linksetActivityLock) { @@ -256,7 +254,7 @@ public class BSLinkset foreach (BSPhysObject child in m_children) { BSConstraint constrain; - if (m_physicsScene.Constraints.TryGetConstraint(LinksetRoot.BSBody, child.BSBody, out constrain)) + if (PhysicsScene.Constraints.TryGetConstraint(LinksetRoot.BSBody, child.BSBody, out constrain)) { // DetailLog("{0},BSLinkset.RecomputeLinksetConstraintVariables,taint,child={1},mass={2},A={3},B={4}", // LinksetRoot.LocalID, child.LocalID, linksetMass, constrain.Body1.ID, constrain.Body2.ID); @@ -306,9 +304,9 @@ public class BSLinkset BSPhysObject rootx = LinksetRoot; // capture the root as of now BSPhysObject childx = child; - m_physicsScene.TaintedObject("AddChildToLinkset", delegate() + PhysicsScene.TaintedObject("AddChildToLinkset", delegate() { - DetailLog("{0},AddChildToLinkset,taint,child={1}", m_linksetRoot.LocalID, child.LocalID); + DetailLog("{0},AddChildToLinkset,taint,child={1}", LinksetRoot.LocalID, child.LocalID); PhysicallyLinkAChildToRoot(rootx, childx); // build the physical binding between me and the child }); } @@ -322,7 +320,7 @@ public class BSLinkset // has to be updated also (like pointer to prim's parent). private void RemoveChildFromOtherLinkset(BSPhysObject pchild) { - pchild.Linkset = new BSLinkset(m_physicsScene, pchild); + pchild.Linkset = new BSLinkset(PhysicsScene, pchild); RemoveChildFromLinkset(pchild); } @@ -334,9 +332,9 @@ public class BSLinkset { BSPhysObject rootx = LinksetRoot; // capture the root as of now BSPhysObject childx = child; - m_physicsScene.TaintedObject("RemoveChildFromLinkset", delegate() + PhysicsScene.TaintedObject("RemoveChildFromLinkset", delegate() { - DetailLog("{0},RemoveChildFromLinkset,taint,child={1}", m_linksetRoot.LocalID, child.LocalID); + DetailLog("{0},RemoveChildFromLinkset,taint,child={1}", LinksetRoot.LocalID, child.LocalID); PhysicallyUnlinkAChildFromRoot(rootx, childx); RecomputeLinksetConstraintVariables(); @@ -370,7 +368,7 @@ public class BSLinkset DetailLog("{0},PhysicallyLinkAChildToRoot,taint,root={1},child={2},rLoc={3},cLoc={4},midLoc={5}", rootPrim.LocalID, rootPrim.LocalID, childPrim.LocalID, rootPrim.Position, childPrim.Position, midPoint); BS6DofConstraint constrain = new BS6DofConstraint( - m_physicsScene.World, rootPrim.BSBody, childPrim.BSBody, + PhysicsScene.World, rootPrim.BSBody, childPrim.BSBody, midPoint, true, true @@ -408,7 +406,7 @@ public class BSLinkset // ================================================================================== */ - m_physicsScene.Constraints.AddConstraint(constrain); + PhysicsScene.Constraints.AddConstraint(constrain); // zero linear and angular limits makes the objects unable to move in relation to each other constrain.SetLinearLimits(OMV.Vector3.Zero, OMV.Vector3.Zero); @@ -435,7 +433,7 @@ public class BSLinkset DetailLog("{0},PhysicallyUnlinkAChildFromRoot,taint,root={1},child={2}", rootPrim.LocalID, rootPrim.LocalID, childPrim.LocalID); // Find the constraint for this link and get rid of it from the overall collection and from my list - m_physicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.BSBody, childPrim.BSBody); + PhysicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.BSBody, childPrim.BSBody); // Make the child refresh its location BulletSimAPI.PushUpdate2(childPrim.BSBody.Ptr); @@ -447,13 +445,13 @@ public class BSLinkset { DetailLog("{0},PhysicallyUnlinkAllChildren,taint", rootPrim.LocalID); - m_physicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.BSBody); + PhysicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.BSBody); } // Invoke the detailed logger and output something if it's enabled. private void DetailLog(string msg, params Object[] args) { - m_physicsScene.PhysicsLogging.Write(msg, args); + PhysicsScene.PhysicsLogging.Write(msg, args); } } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs index 3fe71e1..242aa80 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs @@ -39,26 +39,150 @@ namespace OpenSim.Region.Physics.BulletSPlugin // unless the difference is significant. public abstract class BSPhysObject : PhysicsActor { - public abstract BSLinkset Linkset { get; set; } + protected void BaseInitialize(BSScene parentScene) + { + PhysicsScene = parentScene; + Linkset = new BSLinkset(PhysicsScene, this); - public abstract bool Collide(uint collidingWith, BSPhysObject collidee, - OMV.Vector3 contactPoint, OMV.Vector3 contactNormal, float pentrationDepth); - public abstract void SendCollisions(); + CollisionCollection = new CollisionEventUpdate(); + SubscribedEventsMs = 0; + CollidingStep = 0; + CollidingGroundStep = 0; + } - // Return the object mass without calculating it or side effects + public BSScene PhysicsScene { get; protected set; } + + public BSLinkset Linkset { get; set; } + + // Return the object mass without calculating it or having side effects public abstract float MassRaw { get; } // Reference to the physical body (btCollisionObject) of this object - public abstract BulletBody BSBody { get; set; } + public BulletBody BSBody { get; protected set; } // Reference to the physical shape (btCollisionShape) of this object - public abstract BulletShape BSShape { get; set; } + public BulletShape BSShape { get; protected set; } + // Stop all physical motion. public abstract void ZeroMotion(); + // Step the vehicle simulation for this object. A NOOP if the vehicle was not configured. public virtual void StepVehicle(float timeStep) { } + // Update the physical location and motion of the object. Called with data from Bullet. public abstract void UpdateProperties(EntityProperties entprop); + // Tell the object to clean up. public abstract void Destroy(); + + #region Collisions + + // Requested number of milliseconds between collision events. Zero means disabled. + protected int SubscribedEventsMs { get; set; } + // Given subscription, the time that a collision may be passed up + protected int NextCollisionOkTime { get; set; } + // The simulation step that last had a collision + protected long CollidingStep { get; set; } + // The simulation step that last had a collision with the ground + protected long CollidingGroundStep { get; set; } + // The collision flags we think are set in Bullet + protected CollisionFlags CurrentCollisionFlags { get; set; } + + // The collisions that have been collected this tick + protected CollisionEventUpdate CollisionCollection; + + // The simulation step is telling this object about a collision. + // Return 'true' if a collision was processed and should be sent up. + // Called at taint time from within the Step() function + public virtual bool Collide(uint collidingWith, BSPhysObject collidee, + OMV.Vector3 contactPoint, OMV.Vector3 contactNormal, float pentrationDepth) + { + bool ret = false; + + // The following lines make IsColliding() and IsCollidingGround() work + CollidingStep = PhysicsScene.SimulationStep; + if (collidingWith <= PhysicsScene.TerrainManager.HighestTerrainID) + { + CollidingGroundStep = PhysicsScene.SimulationStep; + } + + // prims in the same linkset cannot collide with each other + if (collidee != null && (this.Linkset.LinksetID == collidee.Linkset.LinksetID)) + { + return ret; + } + + PhysicsScene.PhysicsLogging.Write("{0},BSPhysObject.Collison,call,with={1}", LocalID, collidingWith); + + // if someone has subscribed for collision events.... + if (SubscribedEvents()) { + CollisionCollection.AddCollider(collidingWith, new ContactPoint(contactPoint, contactNormal, pentrationDepth)); + PhysicsScene.PhysicsLogging.Write("{0},BSPhysObject.Collison.AddCollider,call,with={1},point={2},normal={3},depth={4},next={5}", + LocalID, collidingWith, contactPoint, contactNormal, pentrationDepth, NextCollisionOkTime.ToString("yyyyMMddHHmmssfff")); + ret = true; + } + return ret; + } + + // Routine to send the collected collisions into the simulator. + // Also handles removal of this from the collection of objects with collisions if + // there are no collisions from this object. Mechanism is create one last + // collision event to make collision_end work. + public virtual void SendCollisions() + { + // throttle the collisions to the number of milliseconds specified in the subscription + int nowTime = PhysicsScene.SimulationNowTime; + if (nowTime >= NextCollisionOkTime) + { + NextCollisionOkTime = nowTime + SubscribedEventsMs; + + // We are called if we previously had collisions. If there are no collisions + // this time, send up one last empty event so OpenSim can sense collision end. + if (CollisionCollection.Count == 0) + PhysicsScene.ObjectsWithNoMoreCollisions.Add(this); + + base.SendCollisionUpdate(CollisionCollection); + + // The collisionCollection structure is passed around in the simulator. + // Make sure we don't have a handle to that one and that a new one is used next time. + CollisionCollection = new CollisionEventUpdate(); + } + } + + // Subscribe for collision events. + // Parameter is the millisecond rate the caller wishes collision events to occur. + public override void SubscribeEvents(int ms) { + SubscribedEventsMs = ms; + if (ms > 0) + { + // make sure first collision happens + NextCollisionOkTime = Util.EnvironmentTickCountSubtract(SubscribedEventsMs); + PhysicsScene.PhysicsLogging.Write("{0},SubscribeEvents,call,ms={1},nextOKTime={2}", + LocalID, SubscribedEventsMs, NextCollisionOkTime.ToString("yyyyMMddHHmmssfff")); + + PhysicsScene.TaintedObject("BSPhysObject.SubscribeEvents", delegate() + { + CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(BSBody.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); + }); + } + else + { + // Subscribing for zero or less is the same as unsubscribing + UnSubscribeEvents(); + } + } + public override void UnSubscribeEvents() { + SubscribedEventsMs = 0; + PhysicsScene.PhysicsLogging.Write("{0},UnSubscribeEvents,call", LocalID); + PhysicsScene.TaintedObject("BSPhysObject.UnSubscribeEvents", delegate() + { + CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(BSBody.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); + }); + } + // Return 'true' if the simulator wants collision events + public override bool SubscribedEvents() { + return (SubscribedEventsMs > 0); + } + + #endregion // Collisions } } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index 26a581f..29f27e8 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs @@ -49,8 +49,6 @@ public sealed class BSPrim : BSPhysObject private ulong _hullKey; private List _hulls; - private BSScene _scene; - public BSScene Scene { get { return _scene; } } private String _avName; private uint _localID = 0; @@ -87,18 +85,6 @@ public sealed class BSPrim : BSPhysObject private bool _kinematic; private float _buoyancy; - // Membership in a linkset is controlled by this class. - public override BSLinkset Linkset { get; set; } - - private int _subscribedEventsMs = 0; - private int _nextCollisionOkTime = 0; - long _collidingStep; - long _collidingGroundStep; - CollisionFlags m_currentCollisionFlags = 0; - - public override BulletBody BSBody { get; set; } - public override BulletShape BSShape { get; set; } - private BSDynamics _vehicle; private OMV.Vector3 _PIDTarget; @@ -113,10 +99,10 @@ public sealed class BSPrim : BSPhysObject OMV.Quaternion rotation, PrimitiveBaseShape pbs, bool pisPhysical) { // m_log.DebugFormat("{0}: BSPrim creation of {1}, id={2}", LogHeader, primName, localID); + base.BaseInitialize(parent_scene); _localID = localID; _avName = primName; _physicsActorType = (int)ActorTypes.Prim; - _scene = parent_scene; _position = pos; _size = size; _scale = new OMV.Vector3(1f, 1f, 1f); // the scale will be set by CreateGeom depending on object type @@ -129,25 +115,23 @@ public sealed class BSPrim : BSPhysObject _pbs = pbs; _isPhysical = pisPhysical; _isVolumeDetect = false; - _subscribedEventsMs = 0; - _friction = _scene.Params.defaultFriction; // TODO: compute based on object material - _density = _scene.Params.defaultDensity; // TODO: compute based on object material - _restitution = _scene.Params.defaultRestitution; - Linkset = new BSLinkset(Scene, this); // a linkset of one - _vehicle = new BSDynamics(Scene, this); // add vehicleness + _friction = PhysicsScene.Params.defaultFriction; // TODO: compute based on object material + _density = PhysicsScene.Params.defaultDensity; // TODO: compute based on object material + _restitution = PhysicsScene.Params.defaultRestitution; + _vehicle = new BSDynamics(PhysicsScene, this); // add vehicleness _mass = CalculateMass(); DetailLog("{0},BSPrim.constructor,call", LocalID); // do the actual object creation at taint time - _scene.TaintedObject("BSPrim.create", delegate() + PhysicsScene.TaintedObject("BSPrim.create", delegate() { CreateGeomAndObject(true); // Get the pointer to the physical body for this object. // At the moment, we're still letting BulletSim manage the creation and destruction // of the object. Someday we'll move that into the C# code. - BSBody = new BulletBody(LocalID, BulletSimAPI.GetBodyHandle2(_scene.World.Ptr, LocalID)); + BSBody = new BulletBody(LocalID, BulletSimAPI.GetBodyHandle2(PhysicsScene.World.Ptr, LocalID)); BSShape = new BulletShape(BulletSimAPI.GetCollisionShape2(BSBody.Ptr)); - m_currentCollisionFlags = BulletSimAPI.GetCollisionFlags2(BSBody.Ptr); + CurrentCollisionFlags = BulletSimAPI.GetCollisionFlags2(BSBody.Ptr); }); } @@ -168,11 +152,11 @@ public sealed class BSPrim : BSPhysObject // Undo any vehicle properties this.VehicleType = (int)Vehicle.TYPE_NONE; - _scene.TaintedObject("BSPrim.destroy", delegate() + PhysicsScene.TaintedObject("BSPrim.destroy", delegate() { DetailLog("{0},BSPrim.Destroy,taint,", LocalID); // everything in the C# world will get garbage collected. Tell the C++ world to free stuff. - BulletSimAPI.DestroyObject(_scene.WorldID, LocalID); + BulletSimAPI.DestroyObject(PhysicsScene.WorldID, LocalID); }); } @@ -183,7 +167,7 @@ public sealed class BSPrim : BSPhysObject get { return _size; } set { _size = value; - _scene.TaintedObject("BSPrim.setSize", delegate() + PhysicsScene.TaintedObject("BSPrim.setSize", delegate() { _mass = CalculateMass(); // changing size changes the mass // Since _size changed, the mesh needs to be rebuilt. If rebuilt, all the correct @@ -196,7 +180,7 @@ public sealed class BSPrim : BSPhysObject public override PrimitiveBaseShape Shape { set { _pbs = value; - _scene.TaintedObject("BSPrim.setShape", delegate() + PhysicsScene.TaintedObject("BSPrim.setShape", delegate() { _mass = CalculateMass(); // changing the shape changes the mass CreateGeomAndObject(false); @@ -214,7 +198,7 @@ public sealed class BSPrim : BSPhysObject public override bool Selected { set { _isSelected = value; - _scene.TaintedObject("BSPrim.setSelected", delegate() + PhysicsScene.TaintedObject("BSPrim.setSelected", delegate() { SetObjectDynamic(); }); @@ -283,13 +267,13 @@ public sealed class BSPrim : BSPhysObject _position = BulletSimAPI.GetPosition2(BSBody.Ptr); // don't do the GetObjectPosition for root elements because this function is called a zillion times - // _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID); + // _position = BulletSimAPI.GetObjectPosition(Scene.WorldID, _localID); return _position; } set { _position = value; // TODO: what does it mean to set the position of a child prim?? Rebuild the constraint? - _scene.TaintedObject("BSPrim.setPosition", delegate() + PhysicsScene.TaintedObject("BSPrim.setPosition", delegate() { DetailLog("{0},BSPrim.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation); BulletSimAPI.SetTranslation2(BSBody.Ptr, _position, _orientation); @@ -327,7 +311,7 @@ public sealed class BSPrim : BSPhysObject get { return _force; } set { _force = value; - _scene.TaintedObject("BSPrim.setForce", delegate() + PhysicsScene.TaintedObject("BSPrim.setForce", delegate() { DetailLog("{0},BSPrim.setForce,taint,force={1}", LocalID, _force); BulletSimAPI.SetObjectForce2(BSBody.Ptr, _force); @@ -342,40 +326,40 @@ public sealed class BSPrim : BSPhysObject set { Vehicle type = (Vehicle)value; BSPrim vehiclePrim = this; - _scene.TaintedObject("setVehicleType", delegate() + PhysicsScene.TaintedObject("setVehicleType", delegate() { // Done at taint time so we're sure the physics engine is not using the variables // Vehicle code changes the parameters for this vehicle type. _vehicle.ProcessTypeChange(type); // Tell the scene about the vehicle so it will get processing each frame. - _scene.VehicleInSceneTypeChanged(this, type); + PhysicsScene.VehicleInSceneTypeChanged(this, type); }); } } public override void VehicleFloatParam(int param, float value) { - _scene.TaintedObject("BSPrim.VehicleFloatParam", delegate() + PhysicsScene.TaintedObject("BSPrim.VehicleFloatParam", delegate() { _vehicle.ProcessFloatVehicleParam((Vehicle)param, value); }); } public override void VehicleVectorParam(int param, OMV.Vector3 value) { - _scene.TaintedObject("BSPrim.VehicleVectorParam", delegate() + PhysicsScene.TaintedObject("BSPrim.VehicleVectorParam", delegate() { _vehicle.ProcessVectorVehicleParam((Vehicle)param, value); }); } public override void VehicleRotationParam(int param, OMV.Quaternion rotation) { - _scene.TaintedObject("BSPrim.VehicleRotationParam", delegate() + PhysicsScene.TaintedObject("BSPrim.VehicleRotationParam", delegate() { _vehicle.ProcessRotationVehicleParam((Vehicle)param, rotation); }); } public override void VehicleFlags(int param, bool remove) { - _scene.TaintedObject("BSPrim.VehicleFlags", delegate() + PhysicsScene.TaintedObject("BSPrim.VehicleFlags", delegate() { _vehicle.ProcessVehicleFlags(param, remove); }); @@ -393,8 +377,9 @@ public sealed class BSPrim : BSPhysObject public override void SetVolumeDetect(int param) { bool newValue = (param != 0); _isVolumeDetect = newValue; - _scene.TaintedObject("BSPrim.SetVolumeDetect", delegate() + PhysicsScene.TaintedObject("BSPrim.SetVolumeDetect", delegate() { + DetailLog("{0},setVolumeDetect,taint,volDetect={1}", LocalID, _isVolumeDetect); SetObjectDynamic(); }); return; @@ -404,7 +389,7 @@ public sealed class BSPrim : BSPhysObject get { return _velocity; } set { _velocity = value; - _scene.TaintedObject("BSPrim.setVelocity", delegate() + PhysicsScene.TaintedObject("BSPrim.setVelocity", delegate() { DetailLog("{0},BSPrim.SetVelocity,taint,vel={1}", LocalID, _velocity); BulletSimAPI.SetLinearVelocity2(BSBody.Ptr, _velocity); @@ -438,9 +423,9 @@ public sealed class BSPrim : BSPhysObject set { _orientation = value; // TODO: what does it mean if a child in a linkset changes its orientation? Rebuild the constraint? - _scene.TaintedObject("BSPrim.setOrientation", delegate() + PhysicsScene.TaintedObject("BSPrim.setOrientation", delegate() { - // _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID); + // _position = BulletSimAPI.GetObjectPosition(Scene.WorldID, _localID); DetailLog("{0},BSPrim.setOrientation,taint,pos={1},orient={2}", LocalID, _position, _orientation); BulletSimAPI.SetTranslation2(BSBody.Ptr, _position, _orientation); }); @@ -454,8 +439,9 @@ public sealed class BSPrim : BSPhysObject get { return _isPhysical; } set { _isPhysical = value; - _scene.TaintedObject("BSPrim.setIsPhysical", delegate() + PhysicsScene.TaintedObject("BSPrim.setIsPhysical", delegate() { + DetailLog("{0},setIsPhysical,taint,isPhys={1}", LocalID, _isPhysical); SetObjectDynamic(); }); } @@ -493,9 +479,9 @@ public sealed class BSPrim : BSPhysObject // Bullet wants static objects to have a mass of zero float mass = IsStatic ? 0f : _mass; - BulletSimAPI.SetObjectProperties(_scene.WorldID, LocalID, IsStatic, IsSolid, SubscribedEvents(), mass); + BulletSimAPI.SetObjectProperties(Scene.WorldID, LocalID, IsStatic, IsSolid, SubscribedEvents(), mass); */ - BulletSimAPI.RemoveObjectFromWorld2(Scene.World.Ptr, BSBody.Ptr); + BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.Ptr, BSBody.Ptr); // Set up the object physicalness (does gravity and collisions move this object) MakeDynamic(IsStatic); @@ -506,15 +492,15 @@ public sealed class BSPrim : BSPhysObject // Arrange for collisions events if the simulator wants them EnableCollisions(SubscribedEvents()); - BulletSimAPI.AddObjectToWorld2(Scene.World.Ptr, BSBody.Ptr); + BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.Ptr, BSBody.Ptr); // Recompute any linkset parameters. // When going from non-physical to physical, this re-enables the constraints that // had been automatically disabled when the mass was set to zero. Linkset.Refresh(this); - DetailLog("{0},BSPrim.UpdatePhysicalParameters,taint,static={1},solid={2},mass={3}, cf={4}", - LocalID, IsStatic, IsSolid, _mass, m_currentCollisionFlags); + DetailLog("{0},BSPrim.UpdatePhysicalParameters,taint,static={1},solid={2},mass={3},collide={4},cf={5}", + LocalID, IsStatic, IsSolid, _mass, SubscribedEvents(), CurrentCollisionFlags); } // "Making dynamic" means changing to and from static. @@ -527,7 +513,7 @@ public sealed class BSPrim : BSPhysObject if (makeStatic) { // Become a Bullet 'static' object type - m_currentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(BSBody.Ptr, CollisionFlags.CF_STATIC_OBJECT); + CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(BSBody.Ptr, CollisionFlags.CF_STATIC_OBJECT); // Stop all movement BulletSimAPI.ClearAllForces2(BSBody.Ptr); // Center of mass is at the center of the object @@ -539,16 +525,17 @@ public sealed class BSPrim : BSPhysObject // There can be special things needed for implementing linksets Linkset.MakeStatic(this); // The activation state is 'sleeping' so Bullet will not try to act on it - BulletSimAPI.ForceActivationState2(BSBody.Ptr, ActivationState.ISLAND_SLEEPING); + // BulletSimAPI.ForceActivationState2(BSBody.Ptr, ActivationState.ISLAND_SLEEPING); + BulletSimAPI.ForceActivationState2(BSBody.Ptr, ActivationState.DISABLE_SIMULATION); } else { // Not a Bullet static object - m_currentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(BSBody.Ptr, CollisionFlags.CF_STATIC_OBJECT); + CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(BSBody.Ptr, CollisionFlags.CF_STATIC_OBJECT); - // Set various physical properties so internal things will get computed correctly as they are set - BulletSimAPI.SetFriction2(BSBody.Ptr, Scene.Params.defaultFriction); - BulletSimAPI.SetRestitution2(BSBody.Ptr, Scene.Params.defaultRestitution); + // Set various physical properties so internal dynamic properties will get computed correctly as they are set + BulletSimAPI.SetFriction2(BSBody.Ptr, PhysicsScene.Params.defaultFriction); + BulletSimAPI.SetRestitution2(BSBody.Ptr, PhysicsScene.Params.defaultRestitution); // per http://www.bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=3382 BulletSimAPI.SetInterpolationLinearVelocity2(BSBody.Ptr, OMV.Vector3.Zero); BulletSimAPI.SetInterpolationAngularVelocity2(BSBody.Ptr, OMV.Vector3.Zero); @@ -562,10 +549,10 @@ public sealed class BSPrim : BSPhysObject BulletSimAPI.UpdateInertiaTensor2(BSBody.Ptr); // Various values for simulation limits - BulletSimAPI.SetDamping2(BSBody.Ptr, Scene.Params.linearDamping, Scene.Params.angularDamping); - BulletSimAPI.SetDeactivationTime2(BSBody.Ptr, Scene.Params.deactivationTime); - BulletSimAPI.SetSleepingThresholds2(BSBody.Ptr, Scene.Params.linearSleepingThreshold, Scene.Params.angularSleepingThreshold); - BulletSimAPI.SetContactProcessingThreshold2(BSBody.Ptr, Scene.Params.contactProcessingThreshold); + BulletSimAPI.SetDamping2(BSBody.Ptr, PhysicsScene.Params.linearDamping, PhysicsScene.Params.angularDamping); + BulletSimAPI.SetDeactivationTime2(BSBody.Ptr, PhysicsScene.Params.deactivationTime); + BulletSimAPI.SetSleepingThresholds2(BSBody.Ptr, PhysicsScene.Params.linearSleepingThreshold, PhysicsScene.Params.angularSleepingThreshold); + BulletSimAPI.SetContactProcessingThreshold2(BSBody.Ptr, PhysicsScene.Params.contactProcessingThreshold); // There can be special things needed for implementing linksets Linkset.MakeDynamic(this); @@ -581,11 +568,11 @@ public sealed class BSPrim : BSPhysObject if (makeSolid) { // Easy in Bullet -- just remove the object flag that controls collision response - m_currentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(BSBody.Ptr, CollisionFlags.CF_NO_CONTACT_RESPONSE); + CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(BSBody.Ptr, CollisionFlags.CF_NO_CONTACT_RESPONSE); } else { - m_currentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(BSBody.Ptr, CollisionFlags.CF_NO_CONTACT_RESPONSE); + CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(BSBody.Ptr, CollisionFlags.CF_NO_CONTACT_RESPONSE); } } @@ -594,11 +581,11 @@ public sealed class BSPrim : BSPhysObject { if (wantsCollisionEvents) { - m_currentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(BSBody.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); + CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(BSBody.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); } else { - m_currentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(BSBody.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); + CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(BSBody.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); } } @@ -618,11 +605,11 @@ public sealed class BSPrim : BSPhysObject set { _throttleUpdates = value; } } public override bool IsColliding { - get { return (_collidingStep == _scene.SimulationStep); } + get { return (CollidingStep == PhysicsScene.SimulationStep); } set { _isColliding = value; } } public override bool CollidingGround { - get { return (_collidingGroundStep == _scene.SimulationStep); } + get { return (CollidingGroundStep == PhysicsScene.SimulationStep); } set { _collidingGround = value; } } public override bool CollidingObj { @@ -656,7 +643,7 @@ public sealed class BSPrim : BSPhysObject set { _rotationalVelocity = value; // m_log.DebugFormat("{0}: RotationalVelocity={1}", LogHeader, _rotationalVelocity); - _scene.TaintedObject("BSPrim.setRotationalVelocity", delegate() + PhysicsScene.TaintedObject("BSPrim.setRotationalVelocity", delegate() { DetailLog("{0},BSPrim.SetRotationalVel,taint,rotvel={1}", LocalID, _rotationalVelocity); BulletSimAPI.SetAngularVelocity2(BSBody.Ptr, _rotationalVelocity); @@ -673,13 +660,13 @@ public sealed class BSPrim : BSPhysObject get { return _buoyancy; } set { _buoyancy = value; - _scene.TaintedObject("BSPrim.setBuoyancy", delegate() + PhysicsScene.TaintedObject("BSPrim.setBuoyancy", delegate() { DetailLog("{0},BSPrim.SetBuoyancy,taint,buoy={1}", LocalID, _buoyancy); // Buoyancy is faked by changing the gravity applied to the object - float grav = Scene.Params.gravity * (1f - _buoyancy); + float grav = PhysicsScene.Params.gravity * (1f - _buoyancy); BulletSimAPI.SetGravity2(BSBody.Ptr, new OMV.Vector3(0f, 0f, grav)); - // BulletSimAPI.SetObjectBuoyancy(_scene.WorldID, _localID, _buoyancy); + // BulletSimAPI.SetObjectBuoyancy(Scene.WorldID, _localID, _buoyancy); }); } } @@ -730,7 +717,7 @@ public sealed class BSPrim : BSPhysObject m_log.WarnFormat("{0}: Got a NaN force applied to a prim. LocalID={1}", LogHeader, LocalID); return; } - _scene.TaintedObject("BSPrim.AddForce", delegate() + PhysicsScene.TaintedObject("BSPrim.AddForce", delegate() { OMV.Vector3 fSum = OMV.Vector3.Zero; lock (m_accumulatedForces) @@ -754,30 +741,6 @@ public sealed class BSPrim : BSPhysObject public override void SetMomentum(OMV.Vector3 momentum) { DetailLog("{0},BSPrim.SetMomentum,call,mom={1}", LocalID, momentum); } - public override void SubscribeEvents(int ms) { - _subscribedEventsMs = ms; - if (ms > 0) - { - // make sure first collision happens - _nextCollisionOkTime = Util.EnvironmentTickCount() - _subscribedEventsMs; - - Scene.TaintedObject("BSPrim.SubscribeEvents", delegate() - { - m_currentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(BSBody.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); - }); - } - } - public override void UnSubscribeEvents() { - _subscribedEventsMs = 0; - Scene.TaintedObject("BSPrim.UnSubscribeEvents", delegate() - { - m_currentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(BSBody.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); - }); - } - public override bool SubscribedEvents() { - return (_subscribedEventsMs > 0); - } - #region Mass Calculation private float CalculateMass() @@ -1071,8 +1034,8 @@ public sealed class BSPrim : BSPhysObject if (returnMass <= 0) returnMass = 0.0001f; - if (returnMass > _scene.MaximumObjectMass) - returnMass = _scene.MaximumObjectMass; + if (returnMass > PhysicsScene.MaximumObjectMass) + returnMass = PhysicsScene.MaximumObjectMass; return returnMass; }// end CalculateMass @@ -1090,7 +1053,7 @@ public sealed class BSPrim : BSPhysObject bool haveShape = false; // If the prim attributes are simple, this could be a simple Bullet native shape - if ((_pbs.SculptEntry && !Scene.ShouldMeshSculptedPrim) + if ((_pbs.SculptEntry && !PhysicsScene.ShouldMeshSculptedPrim) || (_pbs.ProfileBegin == 0 && _pbs.ProfileEnd == 0 && _pbs.ProfileHollow == 0 && _pbs.PathTwist == 0 && _pbs.PathTwistBegin == 0 @@ -1156,12 +1119,12 @@ public sealed class BSPrim : BSPhysObject private bool CreateGeomMesh() { // level of detail based on size and type of the object - float lod = _scene.MeshLOD; + float lod = PhysicsScene.MeshLOD; if (_pbs.SculptEntry) - lod = _scene.SculptLOD; + lod = PhysicsScene.SculptLOD; float maxAxis = Math.Max(_size.X, Math.Max(_size.Y, _size.Z)); - if (maxAxis > _scene.MeshMegaPrimThreshold) - lod = _scene.MeshMegaPrimLOD; + if (maxAxis > PhysicsScene.MeshMegaPrimThreshold) + lod = PhysicsScene.MeshMegaPrimLOD; ulong newMeshKey = (ulong)_pbs.GetMeshKey(_size, lod); // m_log.DebugFormat("{0}: CreateGeomMesh: lID={1}, oldKey={2}, newKey={3}", LogHeader, _localID, _meshKey, newMeshKey); @@ -1175,14 +1138,14 @@ public sealed class BSPrim : BSPhysObject { // m_log.DebugFormat("{0}: CreateGeom: deleting old mesh. lID={1}, Key={2}", LogHeader, _localID, _meshKey); DetailLog("{0},BSPrim.CreateGeomMesh,deleteOld,key={1}", LocalID, _meshKey); - BulletSimAPI.DestroyMesh(_scene.WorldID, _meshKey); + BulletSimAPI.DestroyMesh(PhysicsScene.WorldID, _meshKey); _mesh = null; _meshKey = 0; } _meshKey = newMeshKey; // always pass false for physicalness as this creates some sort of bounding box which we don't need - _mesh = _scene.mesher.CreateMesh(_avName, _pbs, _size, lod, false); + _mesh = PhysicsScene.mesher.CreateMesh(_avName, _pbs, _size, lod, false); int[] indices = _mesh.getIndexListAsInt(); List vertices = _mesh.getVertexList(); @@ -1198,7 +1161,7 @@ public sealed class BSPrim : BSPhysObject // m_log.DebugFormat("{0}: CreateGeomMesh: calling CreateMesh. lid={1}, key={2}, indices={3}, vertices={4}", // LogHeader, _localID, _meshKey, indices.Length, vertices.Count); - BulletSimAPI.CreateMesh(_scene.WorldID, _meshKey, indices.GetLength(0), indices, + BulletSimAPI.CreateMesh(PhysicsScene.WorldID, _meshKey, indices.GetLength(0), indices, vertices.Count, verticesAsFloats); _shapeType = ShapeData.PhysicsShapeType.SHAPE_MESH; @@ -1211,7 +1174,7 @@ public sealed class BSPrim : BSPhysObject // Returns 'true' of a mesh was actually rebuild (we could also have one of these specs). private bool CreateGeomHull() { - float lod = _pbs.SculptEntry ? _scene.SculptLOD : _scene.MeshLOD; + float lod = _pbs.SculptEntry ? PhysicsScene.SculptLOD : PhysicsScene.MeshLOD; ulong newHullKey = (ulong)_pbs.GetMeshKey(_size, lod); // m_log.DebugFormat("{0}: CreateGeomHull: lID={1}, oldKey={2}, newKey={3}", LogHeader, _localID, _hullKey, newHullKey); @@ -1225,7 +1188,7 @@ public sealed class BSPrim : BSPhysObject { // m_log.DebugFormat("{0}: CreateGeom: deleting old hull. Key={1}", LogHeader, _hullKey); DetailLog("{0},BSPrim.CreateGeomHull,deleteOldHull,key={1}", LocalID, _hullKey); - BulletSimAPI.DestroyHull(_scene.WorldID, _hullKey); + BulletSimAPI.DestroyHull(PhysicsScene.WorldID, _hullKey); _hullKey = 0; } @@ -1314,7 +1277,7 @@ public sealed class BSPrim : BSPhysObject // create the hull definition in Bullet // m_log.DebugFormat("{0}: CreateGeom: calling CreateHull. lid={1}, key={2}, hulls={3}", LogHeader, _localID, _hullKey, hullCount); - BulletSimAPI.CreateHull(_scene.WorldID, _hullKey, hullCount, convHulls); + BulletSimAPI.CreateHull(PhysicsScene.WorldID, _hullKey, hullCount, convHulls); _shapeType = ShapeData.PhysicsShapeType.SHAPE_HULL; // meshes are already scaled by the meshmerizer _scale = new OMV.Vector3(1f, 1f, 1f); @@ -1354,10 +1317,10 @@ public sealed class BSPrim : BSPhysObject ShapeData shape; FillShapeInfo(out shape); // m_log.DebugFormat("{0}: CreateObject: lID={1}, shape={2}", LogHeader, _localID, shape.Type); - bool ret = BulletSimAPI.CreateObject(_scene.WorldID, shape); + bool ret = BulletSimAPI.CreateObject(PhysicsScene.WorldID, shape); // the CreateObject() may have recreated the rigid body. Make sure we have the latest address. - BSBody = new BulletBody(LocalID, BulletSimAPI.GetBodyHandle2(_scene.World.Ptr, LocalID)); + BSBody = new BulletBody(LocalID, BulletSimAPI.GetBodyHandle2(PhysicsScene.World.Ptr, LocalID)); BSShape = new BulletShape(BulletSimAPI.GetCollisionShape2(BSBody.Ptr)); return ret; @@ -1490,61 +1453,10 @@ public sealed class BSPrim : BSPhysObject } */ } - - // I've collided with something - // Called at taint time from within the Step() function - CollisionEventUpdate collisionCollection; - public override bool Collide(uint collidingWith, BSPhysObject collidee, OMV.Vector3 contactPoint, OMV.Vector3 contactNormal, float pentrationDepth) - { - bool ret = false; - - // The following lines make IsColliding() and IsCollidingGround() work - _collidingStep = Scene.SimulationStep; - if (collidingWith <= Scene.TerrainManager.HighestTerrainID) - { - _collidingGroundStep = Scene.SimulationStep; - } - - // DetailLog("{0},BSPrim.Collison,call,with={1}", LocalID, collidingWith); - - // prims in the same linkset cannot collide with each other - if (collidee != null && (this.Linkset.LinksetID == collidee.Linkset.LinksetID)) - { - return ret; - } - - // if someone has subscribed for collision events.... - if (SubscribedEvents()) { - // throttle the collisions to the number of milliseconds specified in the subscription - int nowTime = Scene.SimulationNowTime; - if (nowTime >= _nextCollisionOkTime) { - _nextCollisionOkTime = nowTime + _subscribedEventsMs; - - if (collisionCollection == null) - collisionCollection = new CollisionEventUpdate(); - collisionCollection.AddCollider(collidingWith, new ContactPoint(contactPoint, contactNormal, pentrationDepth)); - ret = true; - } - } - return ret; - } - - // The scene is telling us it's time to pass our collected collisions into the simulator - public override void SendCollisions() - { - if (collisionCollection != null && collisionCollection.Count > 0) - { - base.SendCollisionUpdate(collisionCollection); - // The collisionCollection structure is passed around in the simulator. - // Make sure we don't have a handle to that one and that a new one is used next time. - collisionCollection = null; - } - } - // Invoke the detailed logger and output something if it's enabled. private void DetailLog(string msg, params Object[] args) { - Scene.PhysicsLogging.Write(msg, args); + PhysicsScene.PhysicsLogging.Write(msg, args); } } } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs index 52997dd..dabced5 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs @@ -75,10 +75,11 @@ public class BSScene : PhysicsScene, IPhysicsParameters public Dictionary PhysObjects = new Dictionary(); - private HashSet m_objectsWithCollisions = new HashSet(); - // Following is a kludge and can be removed when avatar animation updating is - // moved to a better place. - private HashSet m_avatarsWithCollisions = new HashSet(); + public HashSet ObjectsWithCollisions = new HashSet(); + public HashSet ObjectsWithNoMoreCollisions = new HashSet(); + // Keep track of all the avatars so we can send them a collision event + // every tick so OpenSim will update its animation. + private HashSet m_avatars = new HashSet(); // List of all the objects that have vehicle properties and should be called // to update each physics step. @@ -379,7 +380,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters // TODO: Remove kludge someday. // We must generate a collision for avatars whether they collide or not. // This is required by OpenSim to update avatar animations, etc. - lock (m_avatarsWithCollisions) m_avatarsWithCollisions.Add(actor); + lock (m_avatars) m_avatars.Add(actor); return actor; } @@ -397,7 +398,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters { lock (PhysObjects) PhysObjects.Remove(actor.LocalID); // Remove kludge someday - lock (m_avatarsWithCollisions) m_avatarsWithCollisions.Remove(bsactor); + lock (m_avatars) m_avatars.Remove(bsactor); } catch (Exception e) { @@ -464,6 +465,9 @@ public class BSScene : PhysicsScene, IPhysicsParameters int collidersCount = 0; IntPtr collidersPtr; + int beforeTime = 0; + int simTime = 0; + // prevent simulation until we've been initialized if (!m_initialized) return 5.0f; @@ -481,10 +485,14 @@ public class BSScene : PhysicsScene, IPhysicsParameters int numSubSteps = 0; try { + if (PhysicsLogging.Enabled) beforeTime = Util.EnvironmentTickCount(); + numSubSteps = BulletSimAPI.PhysicsStep(WorldID, timeStep, m_maxSubSteps, m_fixedTimeStep, out updatedEntityCount, out updatedEntitiesPtr, out collidersCount, out collidersPtr); - DetailLog("{0},Simulate,call, nTaints= {1}, substeps={2}, updates={3}, colliders={4}", - DetailLogZero, numTaints, numSubSteps, updatedEntityCount, collidersCount); + + if (PhysicsLogging.Enabled) simTime = Util.EnvironmentTickCountSubtract(beforeTime); + DetailLog("{0},Simulate,call, nTaints={1}, simTime={2}, substeps={3}, updates={4}, colliders={5}", + DetailLogZero, numTaints, simTime, numSubSteps, updatedEntityCount, collidersCount); } catch (Exception e) { @@ -502,12 +510,6 @@ public class BSScene : PhysicsScene, IPhysicsParameters // Get a value for 'now' so all the collision and update routines don't have to get their own SimulationNowTime = Util.EnvironmentTickCount(); - // This is a kludge to get avatar movement updates. - // ODE sends collisions for avatars even if there are have been no collisions. This updates - // avatar animations and stuff. - // If you fix avatar animation updates, remove this overhead and let normal collision processing happen. - m_objectsWithCollisions = new HashSet(m_avatarsWithCollisions); - // If there were collisions, process them by sending the event to the prim. // Collisions must be processed before updates. if (collidersCount > 0) @@ -523,11 +525,31 @@ public class BSScene : PhysicsScene, IPhysicsParameters } } + // This is a kludge to get avatar movement updates. + // ODE sends collisions for avatars even if there are have been no collisions. This updates + // avatar animations and stuff. + // If you fix avatar animation updates, remove this overhead and let normal collision processing happen. + foreach (BSPhysObject bsp in m_avatars) + bsp.SendCollisions(); + // The above SendCollision's batch up the collisions on the objects. // Now push the collisions into the simulator. - foreach (BSPhysObject bsp in m_objectsWithCollisions) - bsp.SendCollisions(); - m_objectsWithCollisions.Clear(); + // If the object is done colliding, it will add itself to the ObjectsWithNoMoreCollisions list. + if (ObjectsWithCollisions.Count > 0) + { + foreach (BSPhysObject bsp in ObjectsWithCollisions) + if (!m_avatars.Contains(bsp)) // don't call avatars twice + bsp.SendCollisions(); + } + + // Objects that are done colliding are removed from the ObjectsWithCollisions list. + // This can't be done by SendCollisions because it is inside an iteration of ObjectWithCollisions. + if (ObjectsWithNoMoreCollisions.Count > 0) + { + foreach (BSPhysObject po in ObjectsWithNoMoreCollisions) + ObjectsWithCollisions.Remove(po); + ObjectsWithNoMoreCollisions.Clear(); + } // If any of the objects had updated properties, tell the object it has been changed by the physics engine if (updatedEntityCount > 0) @@ -555,7 +577,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters // The physics engine returns the number of milliseconds it simulated this call. // These are summed and normalized to one second and divided by 1000 to give the reported physics FPS. // Since Bullet normally does 5 or 6 substeps, this will normally sum to about 60 FPS. - return numSubSteps * m_fixedTimeStep; + return numSubSteps * m_fixedTimeStep * 1000; } // Something has collided @@ -583,7 +605,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters if (collider.Collide(collidingWith, collidee, collidePoint, collideNormal, penetration)) { // If a collision was posted, remember to send it to the simulator - m_objectsWithCollisions.Add(collider); + ObjectsWithCollisions.Add(collider); } return; diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs index 9221cdb..4d2d962 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs @@ -249,7 +249,16 @@ public enum CollisionFlags : uint BS_PHYSICAL_OBJECT = 1 << 13, BS_TERRAIN_OBJECT = 1 << 14, BS_NONE = 0, - BS_ALL = 0xFFFFFFFF + BS_ALL = 0xFFFFFFFF, + + // These are the collision flags switched depending on physical state. + // The other flags are used for other things and should not be fooled with. + BS_ACTIVE = CF_STATIC_OBJECT + | CF_KINEMATIC_OBJECT + | CF_NO_CONTACT_RESPONSE + | BS_VOLUME_DETECT_OBJECT + | BS_PHANTOM_OBJECT + | BS_PHYSICAL_OBJECT, }; // Values for collisions groups and masks @@ -270,52 +279,6 @@ public enum CollisionFilterGroups : uint SolidFilter = 1 << 13, }; - // For each type, we first clear and then set the collision flags -public enum ClearCollisionFlag : uint -{ - Terrain = CollisionFlags.BS_ALL, - Phantom = CollisionFlags.BS_ALL, - VolumeDetect = CollisionFlags.BS_ALL, - PhysicalObject = CollisionFlags.BS_ALL, - StaticObject = CollisionFlags.BS_ALL -} - -public enum SetCollisionFlag : uint -{ - Terrain = CollisionFlags.CF_STATIC_OBJECT - | CollisionFlags.BS_TERRAIN_OBJECT, - Phantom = CollisionFlags.CF_STATIC_OBJECT - | CollisionFlags.BS_PHANTOM_OBJECT - | CollisionFlags.CF_NO_CONTACT_RESPONSE, - VolumeDetect = CollisionFlags.CF_STATIC_OBJECT - | CollisionFlags.BS_VOLUME_DETECT_OBJECT - | CollisionFlags.CF_NO_CONTACT_RESPONSE, - PhysicalObject = CollisionFlags.BS_PHYSICAL_OBJECT, - StaticObject = CollisionFlags.CF_STATIC_OBJECT, -} - -// Collision filters used for different types of objects -public enum SetCollisionFilter : uint -{ - Terrain = CollisionFilterGroups.AllFilter, - Phantom = CollisionFilterGroups.GroundPlaneFilter - | CollisionFilterGroups.TerrainFilter, - VolumeDetect = CollisionFilterGroups.AllFilter, - PhysicalObject = CollisionFilterGroups.AllFilter, - StaticObject = CollisionFilterGroups.AllFilter, -} - -// Collision masks used for different types of objects -public enum SetCollisionMask : uint -{ - Terrain = CollisionFilterGroups.AllFilter, - Phantom = CollisionFilterGroups.GroundPlaneFilter - | CollisionFilterGroups.TerrainFilter, - VolumeDetect = CollisionFilterGroups.AllFilter, - PhysicalObject = CollisionFilterGroups.AllFilter, - StaticObject = CollisionFilterGroups.AllFilter -} - // CFM controls the 'hardness' of the constraint. 0=fixed, 0..1=violatable. Default=0 // ERP controls amount of correction per tick. Usable range=0.1..0.8. Default=0.2. public enum ConstraintParams : int -- cgit v1.1 From 91efccabdcb45ed95ae35ab24ed5d3ed5508b463 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Tue, 18 Sep 2012 11:26:19 -0700 Subject: BulletSim: Convert BSCharacter to use common BSPhysObject code and variables. Fix avatar height calculation to properly account for the capsule ends. Rearrange some locking in TerrainManager to eliminate possible race conditions. Move DetailLog() definition into common BSPhysObject class. Some variable renaming to make usage clearer (refactor.rename makes this so easy). --- .../Region/Physics/BulletSPlugin/BSCharacter.cs | 66 +++++++++------------ OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs | 28 +++++---- .../Region/Physics/BulletSPlugin/BSPhysObject.cs | 29 +++++++--- OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | 40 +++++-------- .../Physics/BulletSPlugin/BSTerrainManager.cs | 67 +++++++++++----------- 5 files changed, 113 insertions(+), 117 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs index 57d5726..19eb1e6 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs @@ -39,18 +39,16 @@ public class BSCharacter : BSPhysObject private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private static readonly string LogHeader = "[BULLETS CHAR]"; - private String _avName; // private bool _stopped; private OMV.Vector3 _size; private OMV.Vector3 _scale; private PrimitiveBaseShape _pbs; - private uint _localID = 0; private bool _grabbed; private bool _selected; private OMV.Vector3 _position; private float _mass; - public float _density; - public float _avatarVolume; + private float _avatarDensity; + private float _avatarVolume; private OMV.Vector3 _force; private OMV.Vector3 _velocity; private OMV.Vector3 _torque; @@ -63,18 +61,12 @@ public class BSCharacter : BSPhysObject private bool _setAlwaysRun; private bool _throttleUpdates; private bool _isColliding; - private long _collidingStep; - private bool _collidingGround; - private long _collidingGroundStep; private bool _collidingObj; private bool _floatOnWater; private OMV.Vector3 _rotationalVelocity; private bool _kinematic; private float _buoyancy; - private int _subscribedEventsMs = 0; - private int _nextCollisionOkTime = 0; - private OMV.Vector3 _PIDTarget; private bool _usePID; private float _PIDTau; @@ -85,9 +77,7 @@ public class BSCharacter : BSPhysObject public BSCharacter(uint localID, String avName, BSScene parent_scene, OMV.Vector3 pos, OMV.Vector3 size, bool isFlying) { - base.BaseInitialize(parent_scene); - _localID = localID; - _avName = avName; + base.BaseInitialize(parent_scene, localID, avName); _physicsActorType = (int)ActorTypes.Agent; _position = pos; _size = size; @@ -95,14 +85,15 @@ public class BSCharacter : BSPhysObject _orientation = OMV.Quaternion.Identity; _velocity = OMV.Vector3.Zero; _buoyancy = ComputeBuoyancyFromFlying(isFlying); + // The dimensions of the avatar capsule are kept in the scale. // Physics creates a unit capsule which is scaled by the physics engine. - _scale = new OMV.Vector3(PhysicsScene.Params.avatarCapsuleRadius, PhysicsScene.Params.avatarCapsuleRadius, size.Z); - _density = PhysicsScene.Params.avatarDensity; + ComputeAvatarScale(_size); + _avatarDensity = PhysicsScene.Params.avatarDensity; ComputeAvatarVolumeAndMass(); // set _avatarVolume and _mass based on capsule size, _density and _scale ShapeData shapeData = new ShapeData(); - shapeData.ID = _localID; + shapeData.ID = LocalID; shapeData.Type = ShapeData.PhysicsShapeType.SHAPE_AVATAR; shapeData.Position = _position; shapeData.Rotation = _orientation; @@ -117,7 +108,7 @@ public class BSCharacter : BSPhysObject // do actual create at taint time PhysicsScene.TaintedObject("BSCharacter.create", delegate() { - DetailLog("{0},BSCharacter.create", _localID); + DetailLog("{0},BSCharacter.create,taint", LocalID); BulletSimAPI.CreateObject(PhysicsScene.WorldID, shapeData); // Set the buoyancy for flying. This will be refactored when all the settings happen in C# @@ -135,7 +126,7 @@ public class BSCharacter : BSPhysObject DetailLog("{0},BSCharacter.Destroy", LocalID); PhysicsScene.TaintedObject("BSCharacter.destroy", delegate() { - BulletSimAPI.DestroyObject(PhysicsScene.WorldID, _localID); + BulletSimAPI.DestroyObject(PhysicsScene.WorldID, LocalID); }); } @@ -158,7 +149,7 @@ public class BSCharacter : BSPhysObject // When an avatar's size is set, only the height is changed // and that really only depends on the radius. _size = value; - _scale.Z = (_size.Z * 1.15f) - (_scale.X + _scale.Y); + ComputeAvatarScale(_size); // TODO: something has to be done with the avatar's vertical position @@ -175,11 +166,6 @@ public class BSCharacter : BSPhysObject set { _pbs = value; } } - public override uint LocalID { - set { _localID = value; - } - get { return _localID; } - } public override bool Grabbed { set { _grabbed = value; } @@ -223,7 +209,7 @@ public class BSCharacter : BSPhysObject PhysicsScene.TaintedObject("BSCharacter.setPosition", delegate() { DetailLog("{0},BSCharacter.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation); - BulletSimAPI.SetObjectTranslation(PhysicsScene.WorldID, _localID, _position, _orientation); + BulletSimAPI.SetObjectTranslation(PhysicsScene.WorldID, LocalID, _position, _orientation); }); } } @@ -261,7 +247,7 @@ public class BSCharacter : BSPhysObject PhysicsScene.TaintedObject("BSCharacter.PositionSanityCheck", delegate() { DetailLog("{0},BSCharacter.PositionSanityCheck,taint,pos={1},orient={2}", LocalID, _position, _orientation); - BulletSimAPI.SetObjectTranslation(PhysicsScene.WorldID, _localID, _position, _orientation); + BulletSimAPI.SetObjectTranslation(PhysicsScene.WorldID, LocalID, _position, _orientation); }); ret = true; } @@ -312,7 +298,7 @@ public class BSCharacter : BSPhysObject PhysicsScene.TaintedObject("BSCharacter.setVelocity", delegate() { DetailLog("{0},BSCharacter.setVelocity,taint,vel={1}", LocalID, _velocity); - BulletSimAPI.SetObjectVelocity(PhysicsScene.WorldID, _localID, _velocity); + BulletSimAPI.SetObjectVelocity(PhysicsScene.WorldID, LocalID, _velocity); }); } } @@ -338,7 +324,7 @@ public class BSCharacter : BSPhysObject PhysicsScene.TaintedObject("BSCharacter.setOrientation", delegate() { // _position = BulletSimAPI.GetObjectPosition(Scene.WorldID, _localID); - BulletSimAPI.SetObjectTranslation(PhysicsScene.WorldID, _localID, _position, _orientation); + BulletSimAPI.SetObjectTranslation(PhysicsScene.WorldID, LocalID, _position, _orientation); }); } } @@ -375,12 +361,12 @@ public class BSCharacter : BSPhysObject set { _throttleUpdates = value; } } public override bool IsColliding { - get { return (_collidingStep == PhysicsScene.SimulationStep); } + get { return (CollidingStep == PhysicsScene.SimulationStep); } set { _isColliding = value; } } public override bool CollidingGround { - get { return (_collidingGroundStep == PhysicsScene.SimulationStep); } - set { _collidingGround = value; } + get { return (CollidingGroundStep == PhysicsScene.SimulationStep); } + set { CollidingGround = value; } } public override bool CollidingObj { get { return _collidingObj; } @@ -466,6 +452,16 @@ public class BSCharacter : BSPhysObject public override void SetMomentum(OMV.Vector3 momentum) { } + private void ComputeAvatarScale(OMV.Vector3 size) + { + _scale.X = PhysicsScene.Params.avatarCapsuleRadius; + _scale.Y = PhysicsScene.Params.avatarCapsuleRadius; + + // The 1.15 came from ODE but it seems to cause the avatar to float off the ground + // _scale.Z = (_size.Z * 1.15f) - (_scale.X + _scale.Y); + _scale.Z = (_size.Z) - (_scale.X + _scale.Y); + } + // set _avatarVolume and _mass based on capsule size, _density and _scale private void ComputeAvatarVolumeAndMass() { @@ -480,7 +476,7 @@ public class BSCharacter : BSPhysObject * Math.Min(_scale.X, _scale.Y) * _scale.Y // plus the volume of the capsule end caps ); - _mass = _density * _avatarVolume; + _mass = _avatarDensity * _avatarVolume; } // The physics engine says that properties have updated. Update same and inform @@ -502,11 +498,5 @@ public class BSCharacter : BSPhysObject DetailLog("{0},BSCharacter.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5},terrain={6}", LocalID, _position, _orientation, _velocity, _acceleration, _rotationalVelocity, heightHere); } - - // Invoke the detailed logger and output something if it's enabled. - private void DetailLog(string msg, params Object[] args) - { - PhysicsScene.PhysicsLogging.Write(msg, args); - } } } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs index 005a758..1e8fe52 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs @@ -77,7 +77,7 @@ public class BSLinkset // A simple linkset of one (no children) LinksetID = m_nextLinksetID++; // We create LOTS of linksets. - if (m_nextLinksetID < 0) + if (m_nextLinksetID <= 0) m_nextLinksetID = 1; PhysicsScene = scene; LinksetRoot = parent; @@ -157,21 +157,26 @@ public class BSLinkset private float ComputeLinksetMass() { - float mass = LinksetRoot.MassRaw; - foreach (BSPhysObject bp in m_children) + float mass; + lock (m_linksetActivityLock) { - mass += bp.MassRaw; + mass = LinksetRoot.MassRaw; + foreach (BSPhysObject bp in m_children) + { + mass += bp.MassRaw; + } } return mass; } private OMV.Vector3 ComputeLinksetCenterOfMass() { - OMV.Vector3 com = LinksetRoot.Position * LinksetRoot.MassRaw; - float totalMass = LinksetRoot.MassRaw; - + OMV.Vector3 com; lock (m_linksetActivityLock) { + com = LinksetRoot.Position * LinksetRoot.MassRaw; + float totalMass = LinksetRoot.MassRaw; + foreach (BSPhysObject bp in m_children) { com += bp.Position * bp.MassRaw; @@ -186,10 +191,11 @@ public class BSLinkset private OMV.Vector3 ComputeLinksetGeometricCenter() { - OMV.Vector3 com = LinksetRoot.Position; - + OMV.Vector3 com; lock (m_linksetActivityLock) { + com = LinksetRoot.Position; + foreach (BSPhysObject bp in m_children) { com += bp.Position * bp.MassRaw; @@ -208,8 +214,8 @@ public class BSLinkset // Called at taint-time! public bool MakeDynamic(BSPhysObject child) { - bool ret = false; - return ret; + // What is done for each object in BSPrim is what we want. + return false; } // The object is going static (non-physical). Do any setup necessary diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs index 242aa80..b575e37 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs @@ -39,9 +39,12 @@ namespace OpenSim.Region.Physics.BulletSPlugin // unless the difference is significant. public abstract class BSPhysObject : PhysicsActor { - protected void BaseInitialize(BSScene parentScene) + protected void BaseInitialize(BSScene parentScene, uint localID, string name) { PhysicsScene = parentScene; + LocalID = localID; + PhysObjectName = name; + Linkset = new BSLinkset(PhysicsScene, this); CollisionCollection = new CollisionEventUpdate(); @@ -51,6 +54,8 @@ public abstract class BSPhysObject : PhysicsActor } public BSScene PhysicsScene { get; protected set; } + // public override uint LocalID { get; set; } // Use the LocalID definition in PhysicsActor + public string PhysObjectName { get; protected set; } public BSLinkset Linkset { get; set; } @@ -111,13 +116,13 @@ public abstract class BSPhysObject : PhysicsActor return ret; } - PhysicsScene.PhysicsLogging.Write("{0},BSPhysObject.Collison,call,with={1}", LocalID, collidingWith); + DetailLog("{0},BSPhysObject.Collison,call,with={1}", LocalID, collidingWith); // if someone has subscribed for collision events.... if (SubscribedEvents()) { CollisionCollection.AddCollider(collidingWith, new ContactPoint(contactPoint, contactNormal, pentrationDepth)); - PhysicsScene.PhysicsLogging.Write("{0},BSPhysObject.Collison.AddCollider,call,with={1},point={2},normal={3},depth={4},next={5}", - LocalID, collidingWith, contactPoint, contactNormal, pentrationDepth, NextCollisionOkTime.ToString("yyyyMMddHHmmssfff")); + DetailLog("{0},BSPhysObject.Collison.AddCollider,call,with={1},point={2},normal={3},depth={4}", + LocalID, collidingWith, contactPoint, contactNormal, pentrationDepth); ret = true; } return ret; @@ -127,6 +132,8 @@ public abstract class BSPhysObject : PhysicsActor // Also handles removal of this from the collection of objects with collisions if // there are no collisions from this object. Mechanism is create one last // collision event to make collision_end work. + // Called at taint time from within the Step() function thus no locking problems + // with CollisionCollection and ObjectsWithNoMoreCollisions. public virtual void SendCollisions() { // throttle the collisions to the number of milliseconds specified in the subscription @@ -140,10 +147,11 @@ public abstract class BSPhysObject : PhysicsActor if (CollisionCollection.Count == 0) PhysicsScene.ObjectsWithNoMoreCollisions.Add(this); + DetailLog("{0},SendCollisions.SendCollisionUpdate,call,numCollisions={1}", LocalID, CollisionCollection.Count); base.SendCollisionUpdate(CollisionCollection); // The collisionCollection structure is passed around in the simulator. - // Make sure we don't have a handle to that one and that a new one is used next time. + // Make sure we don't have a handle to that one and that a new one is used for next time. CollisionCollection = new CollisionEventUpdate(); } } @@ -156,8 +164,7 @@ public abstract class BSPhysObject : PhysicsActor { // make sure first collision happens NextCollisionOkTime = Util.EnvironmentTickCountSubtract(SubscribedEventsMs); - PhysicsScene.PhysicsLogging.Write("{0},SubscribeEvents,call,ms={1},nextOKTime={2}", - LocalID, SubscribedEventsMs, NextCollisionOkTime.ToString("yyyyMMddHHmmssfff")); + DetailLog("{0},SubscribeEvents,call,ms={1}", LocalID, SubscribedEventsMs); PhysicsScene.TaintedObject("BSPhysObject.SubscribeEvents", delegate() { @@ -172,7 +179,7 @@ public abstract class BSPhysObject : PhysicsActor } public override void UnSubscribeEvents() { SubscribedEventsMs = 0; - PhysicsScene.PhysicsLogging.Write("{0},UnSubscribeEvents,call", LocalID); + DetailLog("{0},UnSubscribeEvents,call", LocalID); PhysicsScene.TaintedObject("BSPhysObject.UnSubscribeEvents", delegate() { CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(BSBody.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); @@ -184,5 +191,11 @@ public abstract class BSPhysObject : PhysicsActor } #endregion // Collisions + + // High performance detailed logging routine used by the physical objects. + protected void DetailLog(string msg, params Object[] args) + { + PhysicsScene.PhysicsLogging.Write(msg, args); + } } } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index 29f27e8..4f10d46 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs @@ -49,9 +49,6 @@ public sealed class BSPrim : BSPhysObject private ulong _hullKey; private List _hulls; - private String _avName; - private uint _localID = 0; - // _size is what the user passed. _scale is what we pass to the physics engine with the mesh. // Often _scale is unity because the meshmerizer will apply _size when creating the mesh. private OMV.Vector3 _size; // the multiplier for each mesh dimension as passed by the user @@ -99,9 +96,7 @@ public sealed class BSPrim : BSPhysObject OMV.Quaternion rotation, PrimitiveBaseShape pbs, bool pisPhysical) { // m_log.DebugFormat("{0}: BSPrim creation of {1}, id={2}", LogHeader, primName, localID); - base.BaseInitialize(parent_scene); - _localID = localID; - _avName = primName; + base.BaseInitialize(parent_scene, localID, primName); _physicsActorType = (int)ActorTypes.Prim; _position = pos; _size = size; @@ -187,10 +182,6 @@ public sealed class BSPrim : BSPhysObject }); } } - public override uint LocalID { - set { _localID = value; } - get { return _localID; } - } public override bool Grabbed { set { _grabbed = value; } @@ -267,7 +258,7 @@ public sealed class BSPrim : BSPhysObject _position = BulletSimAPI.GetPosition2(BSBody.Ptr); // don't do the GetObjectPosition for root elements because this function is called a zillion times - // _position = BulletSimAPI.GetObjectPosition(Scene.WorldID, _localID); + // _position = BulletSimAPI.GetObjectPosition(Scene.WorldID, LocalID); return _position; } set { @@ -425,7 +416,7 @@ public sealed class BSPrim : BSPhysObject // TODO: what does it mean if a child in a linkset changes its orientation? Rebuild the constraint? PhysicsScene.TaintedObject("BSPrim.setOrientation", delegate() { - // _position = BulletSimAPI.GetObjectPosition(Scene.WorldID, _localID); + // _position = BulletSimAPI.GetObjectPosition(Scene.WorldID, LocalID); DetailLog("{0},BSPrim.setOrientation,taint,pos={1},orient={2}", LocalID, _position, _orientation); BulletSimAPI.SetTranslation2(BSBody.Ptr, _position, _orientation); }); @@ -666,7 +657,7 @@ public sealed class BSPrim : BSPhysObject // Buoyancy is faked by changing the gravity applied to the object float grav = PhysicsScene.Params.gravity * (1f - _buoyancy); BulletSimAPI.SetGravity2(BSBody.Ptr, new OMV.Vector3(0f, 0f, grav)); - // BulletSimAPI.SetObjectBuoyancy(Scene.WorldID, _localID, _buoyancy); + // BulletSimAPI.SetObjectBuoyancy(Scene.WorldID, LocalID, _buoyancy); }); } } @@ -1127,7 +1118,7 @@ public sealed class BSPrim : BSPhysObject lod = PhysicsScene.MeshMegaPrimLOD; ulong newMeshKey = (ulong)_pbs.GetMeshKey(_size, lod); - // m_log.DebugFormat("{0}: CreateGeomMesh: lID={1}, oldKey={2}, newKey={3}", LogHeader, _localID, _meshKey, newMeshKey); + // m_log.DebugFormat("{0}: CreateGeomMesh: lID={1}, oldKey={2}, newKey={3}", LogHeader, LocalID, _meshKey, newMeshKey); // if this new shape is the same as last time, don't recreate the mesh if (_meshKey == newMeshKey) return false; @@ -1136,7 +1127,7 @@ public sealed class BSPrim : BSPhysObject // Since we're recreating new, get rid of any previously generated shape if (_meshKey != 0) { - // m_log.DebugFormat("{0}: CreateGeom: deleting old mesh. lID={1}, Key={2}", LogHeader, _localID, _meshKey); + // m_log.DebugFormat("{0}: CreateGeom: deleting old mesh. lID={1}, Key={2}", LogHeader, LocalID, _meshKey); DetailLog("{0},BSPrim.CreateGeomMesh,deleteOld,key={1}", LocalID, _meshKey); BulletSimAPI.DestroyMesh(PhysicsScene.WorldID, _meshKey); _mesh = null; @@ -1145,7 +1136,7 @@ public sealed class BSPrim : BSPhysObject _meshKey = newMeshKey; // always pass false for physicalness as this creates some sort of bounding box which we don't need - _mesh = PhysicsScene.mesher.CreateMesh(_avName, _pbs, _size, lod, false); + _mesh = PhysicsScene.mesher.CreateMesh(PhysObjectName, _pbs, _size, lod, false); int[] indices = _mesh.getIndexListAsInt(); List vertices = _mesh.getVertexList(); @@ -1160,7 +1151,7 @@ public sealed class BSPrim : BSPhysObject } // m_log.DebugFormat("{0}: CreateGeomMesh: calling CreateMesh. lid={1}, key={2}, indices={3}, vertices={4}", - // LogHeader, _localID, _meshKey, indices.Length, vertices.Count); + // LogHeader, LocalID, _meshKey, indices.Length, vertices.Count); BulletSimAPI.CreateMesh(PhysicsScene.WorldID, _meshKey, indices.GetLength(0), indices, vertices.Count, verticesAsFloats); @@ -1176,7 +1167,7 @@ public sealed class BSPrim : BSPhysObject { float lod = _pbs.SculptEntry ? PhysicsScene.SculptLOD : PhysicsScene.MeshLOD; ulong newHullKey = (ulong)_pbs.GetMeshKey(_size, lod); - // m_log.DebugFormat("{0}: CreateGeomHull: lID={1}, oldKey={2}, newKey={3}", LogHeader, _localID, _hullKey, newHullKey); + // m_log.DebugFormat("{0}: CreateGeomHull: lID={1}, oldKey={2}, newKey={3}", LogHeader, LocalID, _hullKey, newHullKey); // if the hull hasn't changed, don't rebuild it if (newHullKey == _hullKey) return false; @@ -1276,7 +1267,7 @@ public sealed class BSPrim : BSPhysObject } // create the hull definition in Bullet - // m_log.DebugFormat("{0}: CreateGeom: calling CreateHull. lid={1}, key={2}, hulls={3}", LogHeader, _localID, _hullKey, hullCount); + // m_log.DebugFormat("{0}: CreateGeom: calling CreateHull. lid={1}, key={2}, hulls={3}", LogHeader, LocalID, _hullKey, hullCount); BulletSimAPI.CreateHull(PhysicsScene.WorldID, _hullKey, hullCount, convHulls); _shapeType = ShapeData.PhysicsShapeType.SHAPE_HULL; // meshes are already scaled by the meshmerizer @@ -1316,7 +1307,7 @@ public sealed class BSPrim : BSPhysObject // the mesh or hull must have already been created in Bullet ShapeData shape; FillShapeInfo(out shape); - // m_log.DebugFormat("{0}: CreateObject: lID={1}, shape={2}", LogHeader, _localID, shape.Type); + // m_log.DebugFormat("{0}: CreateObject: lID={1}, shape={2}", LogHeader, LocalID, shape.Type); bool ret = BulletSimAPI.CreateObject(PhysicsScene.WorldID, shape); // the CreateObject() may have recreated the rigid body. Make sure we have the latest address. @@ -1329,7 +1320,7 @@ public sealed class BSPrim : BSPhysObject // Copy prim's info into the BulletSim shape description structure public void FillShapeInfo(out ShapeData shape) { - shape.ID = _localID; + shape.ID = LocalID; shape.Type = _shapeType; shape.Position = _position; shape.Rotation = _orientation; @@ -1350,7 +1341,7 @@ public sealed class BSPrim : BSPhysObject // No locking here because this is done when the physics engine is not simulating private void CreateGeomAndObject(bool forceRebuild) { - // m_log.DebugFormat("{0}: CreateGeomAndObject. lID={1}, force={2}", LogHeader, _localID, forceRebuild); + // m_log.DebugFormat("{0}: CreateGeomAndObject. lID={1}, force={2}", LogHeader, LocalID, forceRebuild); // Create the geometry that will make up the object if (CreateGeom(forceRebuild)) { @@ -1453,10 +1444,5 @@ public sealed class BSPrim : BSPhysObject } */ } - // Invoke the detailed logger and output something if it's enabled. - private void DetailLog(string msg, params Object[] args) - { - PhysicsScene.PhysicsLogging.Write(msg, args); - } } } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs index d48462e..c113db1 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs @@ -57,10 +57,10 @@ public class BSTerrainManager public const float TERRAIN_COLLISION_MARGIN = 0.0f; // Until the whole simulator is changed to pass us the region size, we rely on constants. - public Vector3 DefaultRegionSize = new Vector3(Constants.RegionSize, Constants.RegionSize, 0f); + public Vector3 DefaultRegionSize = new Vector3(Constants.RegionSize, Constants.RegionSize, Constants.RegionHeight); // The scene that I am part of - private BSScene m_physicsScene; + private BSScene PhysicsScene { get; set; } // The ground plane created to keep thing from falling to infinity. private BulletBody m_groundPlane; @@ -84,18 +84,18 @@ public class BSTerrainManager // If the parent region (region 0), this is the extent of the combined regions // relative to the origin of region zero private Vector3 m_worldMax; - private PhysicsScene m_parentScene; + private PhysicsScene MegaRegionParentPhysicsScene { get; set; } public BSTerrainManager(BSScene physicsScene) { - m_physicsScene = physicsScene; + PhysicsScene = physicsScene; m_heightMaps = new Dictionary(); m_terrainModified = false; // Assume one region of default size m_worldOffset = Vector3.Zero; - m_worldMax = new Vector3(DefaultRegionSize.X, DefaultRegionSize.Y, 4096f); - m_parentScene = null; + m_worldMax = new Vector3(DefaultRegionSize); + MegaRegionParentPhysicsScene = null; } // Create the initial instance of terrain and the underlying ground plane. @@ -110,7 +110,7 @@ public class BSTerrainManager BulletShape groundPlaneShape = new BulletShape(BulletSimAPI.CreateGroundPlaneShape2(BSScene.GROUNDPLANE_ID, 1f, TERRAIN_COLLISION_MARGIN)); m_groundPlane = new BulletBody(BSScene.GROUNDPLANE_ID, BulletSimAPI.CreateBodyWithDefaultMotionState2(groundPlaneShape.Ptr, Vector3.Zero, Quaternion.Identity)); - BulletSimAPI.AddObjectToWorld2(m_physicsScene.World.Ptr, m_groundPlane.Ptr); + BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.Ptr, m_groundPlane.Ptr); Vector3 minTerrainCoords = new Vector3(0f, 0f, HEIGHT_INITIALIZATION - HEIGHT_EQUAL_FUDGE); Vector3 maxTerrainCoords = new Vector3(DefaultRegionSize.X, DefaultRegionSize.Y, HEIGHT_INITIALIZATION); @@ -128,9 +128,9 @@ public class BSTerrainManager { if (m_groundPlane.Ptr != IntPtr.Zero) { - if (BulletSimAPI.RemoveObjectFromWorld2(m_physicsScene.World.Ptr, m_groundPlane.Ptr)) + if (BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.Ptr, m_groundPlane.Ptr)) { - BulletSimAPI.DestroyObject2(m_physicsScene.World.Ptr, m_groundPlane.Ptr); + BulletSimAPI.DestroyObject2(PhysicsScene.World.Ptr, m_groundPlane.Ptr); } m_groundPlane.Ptr = IntPtr.Zero; } @@ -143,9 +143,9 @@ public class BSTerrainManager { foreach (KeyValuePair kvp in m_heightMaps) { - if (BulletSimAPI.RemoveObjectFromWorld2(m_physicsScene.World.Ptr, kvp.Value.terrainBody.Ptr)) + if (BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.Ptr, kvp.Value.terrainBody.Ptr)) { - BulletSimAPI.DestroyObject2(m_physicsScene.World.Ptr, kvp.Value.terrainBody.Ptr); + BulletSimAPI.DestroyObject2(PhysicsScene.World.Ptr, kvp.Value.terrainBody.Ptr); BulletSimAPI.ReleaseHeightMapInfo2(kvp.Value.Ptr); } } @@ -155,19 +155,19 @@ public class BSTerrainManager // The simulator wants to set a new heightmap for the terrain. public void SetTerrain(float[] heightMap) { float[] localHeightMap = heightMap; - m_physicsScene.TaintedObject("TerrainManager.SetTerrain", delegate() + PhysicsScene.TaintedObject("TerrainManager.SetTerrain", delegate() { - if (m_worldOffset != Vector3.Zero && m_parentScene != null) + if (m_worldOffset != Vector3.Zero && MegaRegionParentPhysicsScene != null) { // If a child of a mega-region, we shouldn't have any terrain allocated for us ReleaseGroundPlaneAndTerrain(); // If doing the mega-prim stuff and we are the child of the zero region, // the terrain is added to our parent - if (m_parentScene is BSScene) + if (MegaRegionParentPhysicsScene is BSScene) { DetailLog("{0},SetTerrain.ToParent,offset={1},worldMax={2}", BSScene.DetailLogZero, m_worldOffset, m_worldMax); - ((BSScene)m_parentScene).TerrainManager.UpdateOrCreateTerrain(BSScene.CHILDTERRAIN_ID, + ((BSScene)MegaRegionParentPhysicsScene).TerrainManager.UpdateOrCreateTerrain(BSScene.CHILDTERRAIN_ID, localHeightMap, m_worldOffset, m_worldOffset + DefaultRegionSize, true); } } @@ -176,7 +176,8 @@ public class BSTerrainManager // If not doing the mega-prim thing, just change the terrain DetailLog("{0},SetTerrain.Existing", BSScene.DetailLogZero); - UpdateOrCreateTerrain(BSScene.TERRAIN_ID, localHeightMap, m_worldOffset, m_worldOffset + DefaultRegionSize, true); + UpdateOrCreateTerrain(BSScene.TERRAIN_ID, localHeightMap, + m_worldOffset, m_worldOffset + DefaultRegionSize, true); } }); } @@ -232,7 +233,7 @@ public class BSTerrainManager BSScene.TaintCallback rebuildOperation = delegate() { - if (m_parentScene != null) + if (MegaRegionParentPhysicsScene != null) { // It's possible that Combine() was called after this code was queued. // If we are a child of combined regions, we don't create any terrain for us. @@ -252,10 +253,10 @@ public class BSTerrainManager BSScene.DetailLogZero, terrainRegionBase, mapInfo.minCoords, mapInfo.maxCoords, mapInfo.sizeX, mapInfo.sizeY); // Remove from the dynamics world because we're going to mangle this object - BulletSimAPI.RemoveObjectFromWorld2(m_physicsScene.World.Ptr, mapInfo.terrainBody.Ptr); + BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.Ptr, mapInfo.terrainBody.Ptr); // Get rid of the old terrain - BulletSimAPI.DestroyObject2(m_physicsScene.World.Ptr, mapInfo.terrainBody.Ptr); + BulletSimAPI.DestroyObject2(PhysicsScene.World.Ptr, mapInfo.terrainBody.Ptr); BulletSimAPI.ReleaseHeightMapInfo2(mapInfo.Ptr); mapInfo.Ptr = IntPtr.Zero; @@ -286,7 +287,7 @@ public class BSTerrainManager BSScene.DetailLogZero, mapInfo.minCoords.X, mapInfo.minCoords.Y, minZ, maxZ); mapInfo.ID = id; - mapInfo.Ptr = BulletSimAPI.CreateHeightMapInfo2(m_physicsScene.World.Ptr, mapInfo.ID, + mapInfo.Ptr = BulletSimAPI.CreateHeightMapInfo2(PhysicsScene.World.Ptr, mapInfo.ID, mapInfo.minCoords, mapInfo.maxCoords, mapInfo.heightMap, TERRAIN_COLLISION_MARGIN); // The terrain object initial position is at the center of the object @@ -307,19 +308,19 @@ public class BSTerrainManager m_heightMaps[terrainRegionBase] = mapInfo; // Set current terrain attributes - BulletSimAPI.SetFriction2(mapInfo.terrainBody.Ptr, m_physicsScene.Params.terrainFriction); - BulletSimAPI.SetHitFraction2(mapInfo.terrainBody.Ptr, m_physicsScene.Params.terrainHitFraction); - BulletSimAPI.SetRestitution2(mapInfo.terrainBody.Ptr, m_physicsScene.Params.terrainRestitution); + BulletSimAPI.SetFriction2(mapInfo.terrainBody.Ptr, PhysicsScene.Params.terrainFriction); + BulletSimAPI.SetHitFraction2(mapInfo.terrainBody.Ptr, PhysicsScene.Params.terrainHitFraction); + BulletSimAPI.SetRestitution2(mapInfo.terrainBody.Ptr, PhysicsScene.Params.terrainRestitution); BulletSimAPI.SetCollisionFlags2(mapInfo.terrainBody.Ptr, CollisionFlags.CF_STATIC_OBJECT); BulletSimAPI.SetMassProps2(mapInfo.terrainBody.Ptr, 0f, Vector3.Zero); BulletSimAPI.UpdateInertiaTensor2(mapInfo.terrainBody.Ptr); // Return the new terrain to the world of physical objects - BulletSimAPI.AddObjectToWorld2(m_physicsScene.World.Ptr, mapInfo.terrainBody.Ptr); + BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.Ptr, mapInfo.terrainBody.Ptr); // redo its bounding box now that it is in the world - BulletSimAPI.UpdateSingleAabb2(m_physicsScene.World.Ptr, mapInfo.terrainBody.Ptr); + BulletSimAPI.UpdateSingleAabb2(PhysicsScene.World.Ptr, mapInfo.terrainBody.Ptr); // Make sure the new shape is processed. BulletSimAPI.Activate2(mapInfo.terrainBody.Ptr, true); @@ -332,7 +333,7 @@ public class BSTerrainManager if (doNow) rebuildOperation(); else - m_physicsScene.TaintedObject("BSScene.UpdateOrCreateTerrain:UpdateExisting", rebuildOperation); + PhysicsScene.TaintedObject("BSScene.UpdateOrCreateTerrain:UpdateExisting", rebuildOperation); } else { @@ -357,7 +358,7 @@ public class BSTerrainManager DetailLog("{0},UpdateOrCreateTerrain:NewTerrain,taint,baseX={1},baseY={2}", BSScene.DetailLogZero, minCoords.X, minCoords.Y); // Create a new mapInfo that will be filled with the new info mapInfo = new BulletHeightMapInfo(id, heightMapX, - BulletSimAPI.CreateHeightMapInfo2(m_physicsScene.World.Ptr, newTerrainID, + BulletSimAPI.CreateHeightMapInfo2(PhysicsScene.World.Ptr, newTerrainID, minCoordsX, maxCoordsX, heightMapX, TERRAIN_COLLISION_MARGIN)); // Put the unfilled heightmap info into the collection of same m_heightMaps.Add(terrainRegionBase, mapInfo); @@ -371,7 +372,7 @@ public class BSTerrainManager if (doNow) createOperation(); else - m_physicsScene.TaintedObject("BSScene.UpdateOrCreateTerrain:NewTerrain", createOperation); + PhysicsScene.TaintedObject("BSScene.UpdateOrCreateTerrain:NewTerrain", createOperation); } } @@ -419,7 +420,7 @@ public class BSTerrainManager catch { // Sometimes they give us wonky values of X and Y. Give a warning and return something. - m_physicsScene.Logger.WarnFormat("{0} Bad request for terrain height. terrainBase={1}, x={2}, y={3}", + PhysicsScene.Logger.WarnFormat("{0} Bad request for terrain height. terrainBase={1}, x={2}, y={3}", LogHeader, terrainBaseXY, regionX, regionY); ret = HEIGHT_GETHEIGHT_RET; } @@ -428,8 +429,8 @@ public class BSTerrainManager } else { - m_physicsScene.Logger.ErrorFormat("{0} GetTerrainHeightAtXY: terrain not found: region={1}, x={2}, y={3}", - LogHeader, m_physicsScene.RegionName, tX, tY); + PhysicsScene.Logger.ErrorFormat("{0} GetTerrainHeightAtXY: terrain not found: region={1}, x={2}, y={3}", + LogHeader, PhysicsScene.RegionName, tX, tY); } m_terrainModified = false; lastHeight = ret; @@ -453,7 +454,7 @@ public class BSTerrainManager { m_worldOffset = offset; m_worldMax = extents; - m_parentScene = pScene; + MegaRegionParentPhysicsScene = pScene; if (pScene != null) { // We are a child. @@ -474,7 +475,7 @@ public class BSTerrainManager private void DetailLog(string msg, params Object[] args) { - m_physicsScene.PhysicsLogging.Write(msg, args); + PhysicsScene.PhysicsLogging.Write(msg, args); } } } -- cgit v1.1 From a27e4ce6cbfb0a2e852624fd4d81121ca829f85c Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Wed, 19 Sep 2012 08:21:29 -0700 Subject: BulletSim: add class and infrastructure for shape and object tracking in the C# code. Needed for the changing body type (to and from GhostObjects) for volumeDetect. --- OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | 47 +++++++++-- OpenSim/Region/Physics/BulletSPlugin/BSScene.cs | 16 ++-- .../Physics/BulletSPlugin/BSShapeCollection.cs | 70 +++++++++++++++++ .../Physics/BulletSPlugin/BSTerrainManager.cs | 7 +- .../Region/Physics/BulletSPlugin/BulletSimAPI.cs | 91 ++++++++++++++++------ 5 files changed, 192 insertions(+), 39 deletions(-) create mode 100755 OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index 4f10d46..4d17e6c 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs @@ -474,12 +474,13 @@ public sealed class BSPrim : BSPhysObject */ BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.Ptr, BSBody.Ptr); - // Set up the object physicalness (does gravity and collisions move this object) - MakeDynamic(IsStatic); - // Make solid or not (do things bounce off or pass through this object) + // This is done first because it can change the collisionObject type. MakeSolid(IsSolid); + // Set up the object physicalness (does gravity and collisions move this object) + MakeDynamic(IsStatic); + // Arrange for collisions events if the simulator wants them EnableCollisions(SubscribedEvents()); @@ -554,17 +555,51 @@ public sealed class BSPrim : BSPhysObject } // "Making solid" means that other object will not pass through this object. + // To make transparent, we create a Bullet ghost object. + // Note: This expects to be called from the UpdatePhysicalParameters() routine as + // the functions after this one set up the state of a possibly newly created collision body. private void MakeSolid(bool makeSolid) { + CollisionObjectTypes bodyType = (CollisionObjectTypes)BulletSimAPI.GetBodyType2(BSBody.Ptr); + /* if (makeSolid) { - // Easy in Bullet -- just remove the object flag that controls collision response - CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(BSBody.Ptr, CollisionFlags.CF_NO_CONTACT_RESPONSE); + if ((bodyType & CollisionObjectTypes.CO_RIGID_BODY) == 0) + { + // Solid things are made out of rigid bodies. Remove this old body from the world + // and use this shape in a new rigid body. + BulletBody oldBody = BSBody; + BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.Ptr, BSBody.Ptr); + BSShape = new BulletShape(BulletSimAPI.GetCollisionShape2(BSBody.Ptr)); + BSBody = new BulletBody(LocalID, BulletSimAPI.CreateBodyFromShape2(PhysicsScene.World.Ptr, BSShape.Ptr, _position, _orientation)); + BulletSimAPI.DestroyObject2(PhysicsScene.World.Ptr, oldBody.Ptr); + BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.Ptr, BSBody.Ptr); + } } else { - CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(BSBody.Ptr, CollisionFlags.CF_NO_CONTACT_RESPONSE); + if ((bodyType & CollisionObjectTypes.CO_GHOST_OBJECT) == 0) + { + // Non-solid things are made out of ghost objects. Remove this old body from the world + // and use this shape in a new rigid body. + BulletBody oldBody = BSBody; + BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.Ptr, BSBody.Ptr); + BSShape = new BulletShape(BulletSimAPI.GetCollisionShape2(BSBody.Ptr)); + BSBody = new BulletBody(LocalID, + BulletSimAPI.CreateGhostFromShape2(PhysicsScene.World.Ptr, BSShape.Ptr, _position, _orientation)); + if (BSBody.Ptr == IntPtr.Zero) + { + m_log.ErrorFormat("{0} BSPrim.MakeSolid: failed creation of ghost object. LocalID=[1}", LogHeader, LocalID); + BSBody = oldBody; + } + else + { + BulletSimAPI.DestroyObject2(PhysicsScene.World.Ptr, oldBody.Ptr); + BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.Ptr, BSBody.Ptr); + } + } } + */ } // Turn on or off the flag controlling whether collision events are returned to the simulator. diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs index dabced5..76da42d 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs @@ -73,8 +73,10 @@ public class BSScene : PhysicsScene, IPhysicsParameters public string BulletSimVersion = "?"; - public Dictionary PhysObjects = new Dictionary(); + public Dictionary PhysObjects; + public BSShapeCollection Shapes; + // Keeping track of the objects with collisions so we can report begin and end of a collision public HashSet ObjectsWithCollisions = new HashSet(); public HashSet ObjectsWithNoMoreCollisions = new HashSet(); // Keep track of all the avatars so we can send them a collision event @@ -203,6 +205,11 @@ public class BSScene : PhysicsScene, IPhysicsParameters public override void Initialise(IMesher meshmerizer, IConfigSource config) { + mesher = meshmerizer; + _taintedObjects = new List(); + PhysObjects = new Dictionary(); + Shapes = new BSShapeCollection(this); + // Allocate pinned memory to pass parameters. m_params = new ConfigurationParameters[1]; m_paramsHandle = GCHandle.Alloc(m_params, GCHandleType.Pinned); @@ -216,12 +223,9 @@ public class BSScene : PhysicsScene, IPhysicsParameters m_updateArray = new EntityProperties[m_maxUpdatesPerFrame]; m_updateArrayPinnedHandle = GCHandle.Alloc(m_updateArray, GCHandleType.Pinned); - mesher = meshmerizer; - _taintedObjects = new List(); - // Enable very detailed logging. // By creating an empty logger when not logging, the log message invocation code - // can be left in and every call doesn't have to check for null. + // can be left in and every call doesn't have to check for null. if (m_physicsLoggingEnabled) { PhysicsLogging = new Logging.LogWriter(m_physicsLoggingDir, m_physicsLoggingPrefix, m_physicsLoggingFileMinutes); @@ -252,7 +256,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters // a child in a mega-region. // Turns out that Bullet really doesn't care about the extents of the simulated // area. It tracks active objects no matter where they are. - Vector3 worldExtent = new Vector3(Constants.RegionSize, Constants.RegionSize, 8192f); + Vector3 worldExtent = new Vector3(Constants.RegionSize, Constants.RegionSize, Constants.RegionHeight); // m_log.DebugFormat("{0}: Initialize: Calling BulletSimAPI.Initialize.", LogHeader); WorldID = BulletSimAPI.Initialize(worldExtent, m_paramsHandle.AddrOfPinnedObject(), diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs new file mode 100755 index 0000000..eb4b2ad --- /dev/null +++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs @@ -0,0 +1,70 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyrightD + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +using System; +using System.Collections.Generic; +using System.Text; +using OMV = OpenMetaverse; + +namespace OpenSim.Region.Physics.BulletSPlugin +{ +public class BSShapeCollection : IDisposable +{ + protected BSScene PhysicsScene { get; set; } + + public BSShapeCollection(BSScene physScene) + { + PhysicsScene = physScene; + } + + public void Dispose() + { + } + + // Track another user of a body + public void ReferenceBody(BulletBody shape) + { + } + + // Release the usage of a body + public void DereferenceBody(BulletBody shape) + { + } + + // Track another user of the shape + public void ReferenceShape(BulletShape shape) + { + } + + // Release the usage of a shape + public void DereferenceShape(BulletShape shape) + { + } + + + +} +} diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs index c113db1..fb802e4 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs @@ -107,7 +107,9 @@ public class BSTerrainManager public void CreateInitialGroundPlaneAndTerrain() { // The ground plane is here to catch things that are trying to drop to negative infinity - BulletShape groundPlaneShape = new BulletShape(BulletSimAPI.CreateGroundPlaneShape2(BSScene.GROUNDPLANE_ID, 1f, TERRAIN_COLLISION_MARGIN)); + BulletShape groundPlaneShape = new BulletShape( + BulletSimAPI.CreateGroundPlaneShape2(BSScene.GROUNDPLANE_ID, 1f, TERRAIN_COLLISION_MARGIN), + ShapeData.PhysicsShapeType.SHAPE_GROUNDPLANE); m_groundPlane = new BulletBody(BSScene.GROUNDPLANE_ID, BulletSimAPI.CreateBodyWithDefaultMotionState2(groundPlaneShape.Ptr, Vector3.Zero, Quaternion.Identity)); BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.Ptr, m_groundPlane.Ptr); @@ -297,7 +299,8 @@ public class BSTerrainManager centerPos.Z = minZ + ((maxZ - minZ) / 2f); // Create the terrain shape from the mapInfo - mapInfo.terrainShape = new BulletShape(BulletSimAPI.CreateTerrainShape2(mapInfo.Ptr)); + mapInfo.terrainShape = new BulletShape(BulletSimAPI.CreateTerrainShape2(mapInfo.Ptr), + ShapeData.PhysicsShapeType.SHAPE_TERRAIN); mapInfo.terrainBody = new BulletBody(mapInfo.ID, BulletSimAPI.CreateBodyWithDefaultMotionState2(mapInfo.terrainShape.Ptr, diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs index 4d2d962..52c8a24 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs @@ -38,31 +38,54 @@ namespace OpenSim.Region.Physics.BulletSPlugin { // The physics engine controller class created at initialization public struct BulletSim { - public BulletSim(uint worldId, BSScene bss, IntPtr xx) { worldID = worldId; scene = bss; Ptr = xx; } + public BulletSim(uint worldId, BSScene bss, IntPtr xx) + { + worldID = worldId; scene = bss; Ptr = xx; + } public uint worldID; // The scene is only in here so very low level routines have a handle to print debug/error messages public BSScene scene; public IntPtr Ptr; } -public struct BulletShape +// An allocated Bullet btRigidBody +public struct BulletBody { - public BulletShape(IntPtr xx) { Ptr = xx; } + public BulletBody(uint id, IntPtr xx) + { + ID = id; + Ptr = xx; + } public IntPtr Ptr; + public uint ID; } -// An allocated Bullet btRigidBody -public struct BulletBody +public struct BulletShape { - public BulletBody(uint id, IntPtr xx) { ID = id; Ptr = xx; } + public BulletShape(IntPtr xx) + { + Ptr = xx; + type=ShapeData.PhysicsShapeType.SHAPE_UNKNOWN; + hashKey = 0; + } + public BulletShape(IntPtr xx, ShapeData.PhysicsShapeType typ) + { + Ptr = xx; + type = typ; + hashKey = 0; + } public IntPtr Ptr; - public uint ID; + public ShapeData.PhysicsShapeType type; + public ulong hashKey; } // An allocated Bullet btConstraint public struct BulletConstraint { - public BulletConstraint(IntPtr xx) { Ptr = xx; } + public BulletConstraint(IntPtr xx) + { + Ptr = xx; + } public IntPtr Ptr; } @@ -96,14 +119,14 @@ public class BulletHeightMapInfo // =============================================================================== [StructLayout(LayoutKind.Sequential)] -public struct ConvexHull +public struct ConvexHull { Vector3 Offset; int VertexCount; Vector3[] Vertices; } [StructLayout(LayoutKind.Sequential)] -public struct ShapeData +public struct ShapeData { public enum PhysicsShapeType { @@ -114,7 +137,9 @@ public struct ShapeData SHAPE_CYLINDER = 4, SHAPE_SPHERE = 5, SHAPE_MESH = 6, - SHAPE_HULL = 7 + SHAPE_HULL = 7, + SHAPE_GROUNDPLANE = 8, + SHAPE_TERRAIN = 9, }; public uint ID; public PhysicsShapeType Type; @@ -136,7 +161,7 @@ public struct ShapeData public const float numericFalse = 0f; } [StructLayout(LayoutKind.Sequential)] -public struct SweepHit +public struct SweepHit { public uint ID; public float Fraction; @@ -227,7 +252,17 @@ public enum ActivationState : uint ISLAND_SLEEPING, WANTS_DEACTIVATION, DISABLE_DEACTIVATION, - DISABLE_SIMULATION + DISABLE_SIMULATION, +} + +public enum CollisionObjectTypes : int +{ + CO_COLLISION_OBJECT = 1 << 0, + CO_RIGID_BODY = 1 << 1, + CO_GHOST_OBJECT = 1 << 2, + CO_SOFT_BODY = 1 << 3, + CO_HF_FLUID = 1 << 4, + CO_USER_TYPE = 1 << 5, } // Values used by Bullet and BulletSim to control object properties. @@ -313,8 +348,8 @@ public delegate void DebugLogCallback([MarshalAs(UnmanagedType.LPStr)]string msg public static extern string GetVersion(); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern uint Initialize(Vector3 maxPosition, IntPtr parms, - int maxCollisions, IntPtr collisionArray, +public static extern uint Initialize(Vector3 maxPosition, IntPtr parms, + int maxCollisions, IntPtr collisionArray, int maxUpdates, IntPtr updateArray, DebugLogCallback logRoutine); @@ -333,19 +368,19 @@ public static extern bool UpdateParameter(uint worldID, uint localID, // =============================================================================== [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern int PhysicsStep(uint worldID, float timeStep, int maxSubSteps, float fixedTimeStep, - out int updatedEntityCount, +public static extern int PhysicsStep(uint worldID, float timeStep, int maxSubSteps, float fixedTimeStep, + out int updatedEntityCount, out IntPtr updatedEntitiesPtr, out int collidersCount, out IntPtr collidersPtr); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern bool CreateHull(uint worldID, System.UInt64 meshKey, +public static extern bool CreateHull(uint worldID, System.UInt64 meshKey, int hullCount, [MarshalAs(UnmanagedType.LPArray)] float[] hulls ); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern bool CreateMesh(uint worldID, System.UInt64 meshKey, +public static extern bool CreateMesh(uint worldID, System.UInt64 meshKey, int indexCount, [MarshalAs(UnmanagedType.LPArray)] int[] indices, int verticesCount, [MarshalAs(UnmanagedType.LPArray)] float[] vertices ); @@ -459,7 +494,7 @@ public static extern void Shutdown2(IntPtr sim); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern int PhysicsStep2(IntPtr world, float timeStep, int maxSubSteps, float fixedTimeStep, - out int updatedEntityCount, + out int updatedEntityCount, out IntPtr updatedEntitiesPtr, out int collidersCount, out IntPtr collidersPtr); @@ -470,8 +505,8 @@ public static extern bool PushUpdate2(IntPtr obj); // ===================================================================================== // Mesh, hull, shape and body creation helper routines [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern IntPtr CreateMeshShape2(IntPtr world, - int indicesCount, [MarshalAs(UnmanagedType.LPArray)] int[] indices, +public static extern IntPtr CreateMeshShape2(IntPtr world, + int indicesCount, [MarshalAs(UnmanagedType.LPArray)] int[] indices, int verticesCount, [MarshalAs(UnmanagedType.LPArray)] float[] vertices ); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] @@ -504,12 +539,18 @@ public static extern IntPtr CreateBodyFromShapeAndInfo2(IntPtr sim, IntPtr shape public static extern bool DeleteCollisionShape2(IntPtr world, IntPtr shape); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern int GetBodyType2(IntPtr obj); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern IntPtr CreateBodyFromShape2(IntPtr sim, IntPtr shape, Vector3 pos, Quaternion rot); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern IntPtr CreateBodyWithDefaultMotionState2(IntPtr shape, Vector3 pos, Quaternion rot); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern IntPtr CreateGhostFromShape2(IntPtr sim, IntPtr shape, Vector3 pos, Quaternion rot); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern IntPtr AllocateBodyInfo2(IntPtr obj); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] @@ -521,11 +562,11 @@ public static extern void DestroyObject2(IntPtr sim, IntPtr obj); // ===================================================================================== // Terrain creation and helper routines [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern IntPtr CreateHeightMapInfo2(IntPtr sim, uint id, Vector3 minCoords, Vector3 maxCoords, +public static extern IntPtr CreateHeightMapInfo2(IntPtr sim, uint id, Vector3 minCoords, Vector3 maxCoords, [MarshalAs(UnmanagedType.LPArray)] float[] heightMap, float collisionMargin); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern IntPtr FillHeightMapInfo2(IntPtr sim, IntPtr mapInfo, uint id, Vector3 minCoords, Vector3 maxCoords, +public static extern IntPtr FillHeightMapInfo2(IntPtr sim, IntPtr mapInfo, uint id, Vector3 minCoords, Vector3 maxCoords, [MarshalAs(UnmanagedType.LPArray)] float[] heightMap, float collisionMargin); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] @@ -563,7 +604,7 @@ public static extern void SetConstraintEnable2(IntPtr constrain, float numericTr public static extern void SetConstraintNumSolverIterations2(IntPtr constrain, float iterations); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern bool SetFrames2(IntPtr constrain, +public static extern bool SetFrames2(IntPtr constrain, Vector3 frameA, Quaternion frameArot, Vector3 frameB, Quaternion frameBrot); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -- cgit v1.1 From 22290ef35aa13edb1501c69b3cce63a885302563 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Thu, 20 Sep 2012 10:12:51 -0700 Subject: BulletSim: complete code for managed code shape and body tracking. Not debugged. Eliminate some null exceptions created adding the above code. Add and remove some detailed logging statements. --- .../Region/Physics/BulletSPlugin/BSCharacter.cs | 2 +- .../Region/Physics/BulletSPlugin/BSPhysObject.cs | 22 +- OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | 121 ++-- .../Physics/BulletSPlugin/BSShapeCollection.cs | 617 ++++++++++++++++++--- .../Region/Physics/BulletSPlugin/BulletSimAPI.cs | 43 +- 5 files changed, 675 insertions(+), 130 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs index 19eb1e6..014cd99 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs @@ -77,7 +77,7 @@ public class BSCharacter : BSPhysObject public BSCharacter(uint localID, String avName, BSScene parent_scene, OMV.Vector3 pos, OMV.Vector3 size, bool isFlying) { - base.BaseInitialize(parent_scene, localID, avName); + base.BaseInitialize(parent_scene, localID, avName, "BSCharacter"); _physicsActorType = (int)ActorTypes.Agent; _position = pos; _size = size; diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs index b575e37..70a10b1 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs @@ -39,11 +39,12 @@ namespace OpenSim.Region.Physics.BulletSPlugin // unless the difference is significant. public abstract class BSPhysObject : PhysicsActor { - protected void BaseInitialize(BSScene parentScene, uint localID, string name) + protected void BaseInitialize(BSScene parentScene, uint localID, string name, string typeName) { PhysicsScene = parentScene; LocalID = localID; PhysObjectName = name; + TypeName = typeName; Linkset = new BSLinkset(PhysicsScene, this); @@ -56,6 +57,7 @@ public abstract class BSPhysObject : PhysicsActor public BSScene PhysicsScene { get; protected set; } // public override uint LocalID { get; set; } // Use the LocalID definition in PhysicsActor public string PhysObjectName { get; protected set; } + public string TypeName { get; protected set; } public BSLinkset Linkset { get; set; } @@ -63,9 +65,9 @@ public abstract class BSPhysObject : PhysicsActor public abstract float MassRaw { get; } // Reference to the physical body (btCollisionObject) of this object - public BulletBody BSBody { get; protected set; } + public BulletBody BSBody; // Reference to the physical shape (btCollisionShape) of this object - public BulletShape BSShape { get; protected set; } + public BulletShape BSShape; // Stop all physical motion. public abstract void ZeroMotion(); @@ -116,13 +118,11 @@ public abstract class BSPhysObject : PhysicsActor return ret; } - DetailLog("{0},BSPhysObject.Collison,call,with={1}", LocalID, collidingWith); - // if someone has subscribed for collision events.... if (SubscribedEvents()) { CollisionCollection.AddCollider(collidingWith, new ContactPoint(contactPoint, contactNormal, pentrationDepth)); - DetailLog("{0},BSPhysObject.Collison.AddCollider,call,with={1},point={2},normal={3},depth={4}", - LocalID, collidingWith, contactPoint, contactNormal, pentrationDepth); + // DetailLog("{0},{1}.Collison.AddCollider,call,with={2},point={3},normal={4},depth={5}", + // LocalID, TypeName, collidingWith, contactPoint, contactNormal, pentrationDepth); ret = true; } return ret; @@ -147,7 +147,7 @@ public abstract class BSPhysObject : PhysicsActor if (CollisionCollection.Count == 0) PhysicsScene.ObjectsWithNoMoreCollisions.Add(this); - DetailLog("{0},SendCollisions.SendCollisionUpdate,call,numCollisions={1}", LocalID, CollisionCollection.Count); + // DetailLog("{0},{1}.SendCollisionUpdate,call,numCollisions={2}", LocalID, TypeName, CollisionCollection.Count); base.SendCollisionUpdate(CollisionCollection); // The collisionCollection structure is passed around in the simulator. @@ -164,9 +164,8 @@ public abstract class BSPhysObject : PhysicsActor { // make sure first collision happens NextCollisionOkTime = Util.EnvironmentTickCountSubtract(SubscribedEventsMs); - DetailLog("{0},SubscribeEvents,call,ms={1}", LocalID, SubscribedEventsMs); - PhysicsScene.TaintedObject("BSPhysObject.SubscribeEvents", delegate() + PhysicsScene.TaintedObject(TypeName+".SubscribeEvents", delegate() { CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(BSBody.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); }); @@ -179,8 +178,7 @@ public abstract class BSPhysObject : PhysicsActor } public override void UnSubscribeEvents() { SubscribedEventsMs = 0; - DetailLog("{0},UnSubscribeEvents,call", LocalID); - PhysicsScene.TaintedObject("BSPhysObject.UnSubscribeEvents", delegate() + PhysicsScene.TaintedObject(TypeName+".UnSubscribeEvents", delegate() { CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(BSBody.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); }); diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index 4d17e6c..4d2c70c 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs @@ -96,7 +96,7 @@ public sealed class BSPrim : BSPhysObject OMV.Quaternion rotation, PrimitiveBaseShape pbs, bool pisPhysical) { // m_log.DebugFormat("{0}: BSPrim creation of {1}, id={2}", LogHeader, primName, localID); - base.BaseInitialize(parent_scene, localID, primName); + base.BaseInitialize(parent_scene, localID, primName, "BSPrim"); _physicsActorType = (int)ActorTypes.Prim; _position = pos; _size = size; @@ -115,17 +115,17 @@ public sealed class BSPrim : BSPhysObject _restitution = PhysicsScene.Params.defaultRestitution; _vehicle = new BSDynamics(PhysicsScene, this); // add vehicleness _mass = CalculateMass(); + + // No body or shape yet + BSBody = new BulletBody(LocalID, IntPtr.Zero); + BSShape = new BulletShape(IntPtr.Zero); + DetailLog("{0},BSPrim.constructor,call", LocalID); // do the actual object creation at taint time PhysicsScene.TaintedObject("BSPrim.create", delegate() { CreateGeomAndObject(true); - // Get the pointer to the physical body for this object. - // At the moment, we're still letting BulletSim manage the creation and destruction - // of the object. Someday we'll move that into the C# code. - BSBody = new BulletBody(LocalID, BulletSimAPI.GetBodyHandle2(PhysicsScene.World.Ptr, LocalID)); - BSShape = new BulletShape(BulletSimAPI.GetCollisionShape2(BSBody.Ptr)); CurrentCollisionFlags = BulletSimAPI.GetCollisionFlags2(BSBody.Ptr); }); } @@ -168,17 +168,24 @@ public sealed class BSPrim : BSPhysObject // Since _size changed, the mesh needs to be rebuilt. If rebuilt, all the correct // scale and margins are set. CreateGeomAndObject(true); - DetailLog("{0}: BSPrim.setSize: size={1}, scale={2}, mass={3}, physical={4}", LocalID, _size, _scale, _mass, IsPhysical); + DetailLog("{0},BSPrim.setSize,size={1},scale={2},mass={3},physical={4}", LocalID, _size, _scale, _mass, IsPhysical); }); } } + // Scale is what we set in the physics engine. It is different than 'size' in that + // 'size' can be encorporated into the mesh. In that case, the scale is <1,1,1>. + public OMV.Vector3 Scale + { + get { return _scale; } + set { _scale = value; } + } public override PrimitiveBaseShape Shape { set { _pbs = value; PhysicsScene.TaintedObject("BSPrim.setShape", delegate() { _mass = CalculateMass(); // changing the shape changes the mass - CreateGeomAndObject(false); + CreateGeomAndObject(true); }); } } @@ -191,7 +198,7 @@ public sealed class BSPrim : BSPhysObject _isSelected = value; PhysicsScene.TaintedObject("BSPrim.setSelected", delegate() { - SetObjectDynamic(); + SetObjectDynamic(false); }); } } @@ -371,7 +378,7 @@ public sealed class BSPrim : BSPhysObject PhysicsScene.TaintedObject("BSPrim.SetVolumeDetect", delegate() { DetailLog("{0},setVolumeDetect,taint,volDetect={1}", LocalID, _isVolumeDetect); - SetObjectDynamic(); + SetObjectDynamic(true); }); return; } @@ -433,7 +440,7 @@ public sealed class BSPrim : BSPhysObject PhysicsScene.TaintedObject("BSPrim.setIsPhysical", delegate() { DetailLog("{0},setIsPhysical,taint,isPhys={1}", LocalID, _isPhysical); - SetObjectDynamic(); + SetObjectDynamic(true); }); } } @@ -445,7 +452,7 @@ public sealed class BSPrim : BSPhysObject } // An object is solid if it's not phantom and if it's not doing VolumeDetect - private bool IsSolid + public bool IsSolid { get { return !IsPhantom && !_isVolumeDetect; } } @@ -457,21 +464,23 @@ public sealed class BSPrim : BSPhysObject // isSolid: other objects bounce off of this object // isVolumeDetect: other objects pass through but can generate collisions // collisionEvents: whether this object returns collision events - private void SetObjectDynamic() + private void SetObjectDynamic(bool forceRebuild) { +#if CSHARP_BODY_MANAGEMENT + // Recreate the physical object if necessary + CreateGeomAndObject(forceRebuild); +#else // If it's becoming dynamic, it will need hullness VerifyCorrectPhysicalShape(); UpdatePhysicalParameters(); +#endif // CSHARP_BODY_MANAGEMENT } private void UpdatePhysicalParameters() { - /* - // Bullet wants static objects to have a mass of zero - float mass = IsStatic ? 0f : _mass; + DetailLog("{0},BSPrim.UpdatePhysicalParameters,entry,body={1},shape={2}", LocalID, BSBody, BSShape); - BulletSimAPI.SetObjectProperties(Scene.WorldID, LocalID, IsStatic, IsSolid, SubscribedEvents(), mass); - */ + // Mangling all the physical properties requires the object to be out of the physical world BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.Ptr, BSBody.Ptr); // Make solid or not (do things bounce off or pass through this object) @@ -517,8 +526,8 @@ public sealed class BSPrim : BSPhysObject // There can be special things needed for implementing linksets Linkset.MakeStatic(this); // The activation state is 'sleeping' so Bullet will not try to act on it - // BulletSimAPI.ForceActivationState2(BSBody.Ptr, ActivationState.ISLAND_SLEEPING); - BulletSimAPI.ForceActivationState2(BSBody.Ptr, ActivationState.DISABLE_SIMULATION); + BulletSimAPI.ForceActivationState2(BSBody.Ptr, ActivationState.ISLAND_SLEEPING); + // BulletSimAPI.ForceActivationState2(BSBody.Ptr, ActivationState.DISABLE_SIMULATION); } else { @@ -560,8 +569,8 @@ public sealed class BSPrim : BSPhysObject // the functions after this one set up the state of a possibly newly created collision body. private void MakeSolid(bool makeSolid) { +#if !CSHARP_BODY_MANAGEMENT CollisionObjectTypes bodyType = (CollisionObjectTypes)BulletSimAPI.GetBodyType2(BSBody.Ptr); - /* if (makeSolid) { if ((bodyType & CollisionObjectTypes.CO_RIGID_BODY) == 0) @@ -569,11 +578,16 @@ public sealed class BSPrim : BSPhysObject // Solid things are made out of rigid bodies. Remove this old body from the world // and use this shape in a new rigid body. BulletBody oldBody = BSBody; - BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.Ptr, BSBody.Ptr); - BSShape = new BulletShape(BulletSimAPI.GetCollisionShape2(BSBody.Ptr)); + // Zero out the pointer to the shape in the old body so the shape will not get freed + BSShape.Ptr = BulletSimAPI.GetCollisionShape2(oldBody.Ptr); + BulletSimAPI.SetCollisionShape2(PhysicsScene.World.Ptr, oldBody.Ptr, IntPtr.Zero); + // Get rid of the old body and remove it from BulletSim's object list + BulletSimAPI.DestroyObject(PhysicsScene.WorldID, LocalID); + + // Create the new body with the shape BSBody = new BulletBody(LocalID, BulletSimAPI.CreateBodyFromShape2(PhysicsScene.World.Ptr, BSShape.Ptr, _position, _orientation)); - BulletSimAPI.DestroyObject2(PhysicsScene.World.Ptr, oldBody.Ptr); - BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.Ptr, BSBody.Ptr); + BulletSimAPI.RemoveFromCollisionFlags2(BSBody.Ptr, CollisionFlags.CF_NO_CONTACT_RESPONSE); + DetailLog("{0},BSPrim.MakeSolid:rigidBody,body={1},shape={2}", LocalID, BSBody, BSShape); } } else @@ -583,23 +597,20 @@ public sealed class BSPrim : BSPhysObject // Non-solid things are made out of ghost objects. Remove this old body from the world // and use this shape in a new rigid body. BulletBody oldBody = BSBody; - BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.Ptr, BSBody.Ptr); - BSShape = new BulletShape(BulletSimAPI.GetCollisionShape2(BSBody.Ptr)); + + // Zero out the pointer to the shape in the old body so the shape will not get freed + BSShape.Ptr = BulletSimAPI.GetCollisionShape2(oldBody.Ptr); + BulletSimAPI.SetCollisionShape2(PhysicsScene.World.Ptr, oldBody.Ptr, IntPtr.Zero); + // Get rid of the old body and remove it from BulletSim's object list + BulletSimAPI.DestroyObject(PhysicsScene.WorldID, LocalID); + BSBody = new BulletBody(LocalID, BulletSimAPI.CreateGhostFromShape2(PhysicsScene.World.Ptr, BSShape.Ptr, _position, _orientation)); - if (BSBody.Ptr == IntPtr.Zero) - { - m_log.ErrorFormat("{0} BSPrim.MakeSolid: failed creation of ghost object. LocalID=[1}", LogHeader, LocalID); - BSBody = oldBody; - } - else - { - BulletSimAPI.DestroyObject2(PhysicsScene.World.Ptr, oldBody.Ptr); - BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.Ptr, BSBody.Ptr); - } + CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(BSBody.Ptr, CollisionFlags.CF_NO_CONTACT_RESPONSE); + DetailLog("{0},BSPrim.MakeGhostBody,body={1},shape={2}", LocalID, BSBody, BSShape); } } - */ +#endif } // Turn on or off the flag controlling whether collision events are returned to the simulator. @@ -1067,6 +1078,7 @@ public sealed class BSPrim : BSPhysObject }// end CalculateMass #endregion Mass Calculation +#if !CSHARP_BODY_MANAGEMENT // Create the geometry information in Bullet for later use. // The objects needs a hull if it's physical otherwise a mesh is enough. // No locking here because this is done when we know physics is not simulating. @@ -1095,6 +1107,7 @@ public sealed class BSPrim : BSPhysObject { DetailLog("{0},BSPrim.CreateGeom,sphere (force={1}", LocalID, forceRebuild); _shapeType = ShapeData.PhysicsShapeType.SHAPE_SPHERE; + _meshKey = (ulong)ShapeData.FixedShapeKey.KEY_SPHERE; // Bullet native objects are scaled by the Bullet engine so pass the size in _scale = _size; // TODO: do we need to check for and destroy a mesh or hull that might have been left from before? @@ -1109,6 +1122,7 @@ public sealed class BSPrim : BSPhysObject { DetailLog("{0},BSPrim.CreateGeom,box (force={1})", LocalID, forceRebuild); _shapeType = ShapeData.PhysicsShapeType.SHAPE_BOX; + _meshKey = (ulong)ShapeData.FixedShapeKey.KEY_BOX; _scale = _size; // TODO: do we need to check for and destroy a mesh or hull that might have been left from before? ret = true; @@ -1136,6 +1150,7 @@ public sealed class BSPrim : BSPhysObject } } } + return ret; } @@ -1345,12 +1360,9 @@ public sealed class BSPrim : BSPhysObject // m_log.DebugFormat("{0}: CreateObject: lID={1}, shape={2}", LogHeader, LocalID, shape.Type); bool ret = BulletSimAPI.CreateObject(PhysicsScene.WorldID, shape); - // the CreateObject() may have recreated the rigid body. Make sure we have the latest address. - BSBody = new BulletBody(LocalID, BulletSimAPI.GetBodyHandle2(PhysicsScene.World.Ptr, LocalID)); - BSShape = new BulletShape(BulletSimAPI.GetCollisionShape2(BSBody.Ptr)); - return ret; } +#endif // !CSHARP_BODY_MANAGEMENT // Copy prim's info into the BulletSim shape description structure public void FillShapeInfo(out ShapeData shape) @@ -1369,22 +1381,45 @@ public sealed class BSPrim : BSPhysObject shape.Restitution = _restitution; shape.Collidable = (!IsPhantom) ? ShapeData.numericTrue : ShapeData.numericFalse; shape.Static = _isPhysical ? ShapeData.numericFalse : ShapeData.numericTrue; + shape.Solid = IsSolid ? ShapeData.numericFalse : ShapeData.numericTrue; + shape.Size = _size; } - // Rebuild the geometry and object. // This is called when the shape changes so we need to recreate the mesh/hull. // No locking here because this is done when the physics engine is not simulating private void CreateGeomAndObject(bool forceRebuild) { +#if CSHARP_BODY_MANAGEMENT + ShapeData shapeData; + FillShapeInfo(out shapeData); + + // Create the correct physical representation for this type of object. + // Updates BSBody and BSShape with the new information. + if (PhysicsScene.Shapes.GetBodyAndShape(forceRebuild, PhysicsScene.World, this, shapeData, _pbs)) + { + // Make sure the properties are set on the new object + UpdatePhysicalParameters(); + } +#else // m_log.DebugFormat("{0}: CreateGeomAndObject. lID={1}, force={2}", LogHeader, LocalID, forceRebuild); // Create the geometry that will make up the object if (CreateGeom(forceRebuild)) { // Create the object and place it into the world CreateObject(); + + // the CreateObject() may have recreated the rigid body. Make sure we have the latest address. + BSBody = new BulletBody(LocalID, BulletSimAPI.GetBodyHandle2(PhysicsScene.World.Ptr, LocalID)); + BSShape = new BulletShape(BulletSimAPI.GetCollisionShape2(BSBody.Ptr), _shapeType); + BSShape.shapeKey = _meshKey; + DetailLog("{0},BSPrim.CreateGeomAndObject,body={1},shape={2}", LocalID, BSBody, BSShape); + // Make sure the properties are set on the new object UpdatePhysicalParameters(); } + + +#endif // CSHARP_BODY_MANAGEMENT return; } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs index eb4b2ad..7470d23 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs @@ -1,70 +1,547 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyrightD - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -using System; -using System.Collections.Generic; -using System.Text; -using OMV = OpenMetaverse; - -namespace OpenSim.Region.Physics.BulletSPlugin -{ -public class BSShapeCollection : IDisposable -{ - protected BSScene PhysicsScene { get; set; } - - public BSShapeCollection(BSScene physScene) - { - PhysicsScene = physScene; - } - - public void Dispose() - { - } - - // Track another user of a body - public void ReferenceBody(BulletBody shape) - { - } - - // Release the usage of a body - public void DereferenceBody(BulletBody shape) - { - } - - // Track another user of the shape - public void ReferenceShape(BulletShape shape) - { - } - - // Release the usage of a shape - public void DereferenceShape(BulletShape shape) - { - } - - - -} -} +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyrightD + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +using System; +using System.Collections.Generic; +using System.Text; +using OMV = OpenMetaverse; +using OpenSim.Framework; +using OpenSim.Region.Physics.Manager; +using OpenSim.Region.Physics.ConvexDecompositionDotNet; + +namespace OpenSim.Region.Physics.BulletSPlugin +{ +public class BSShapeCollection : IDisposable +{ + protected BSScene PhysicsScene { get; set; } + + private Object m_shapeActivityLock = new Object(); + + private struct MeshDesc + { + public IntPtr Ptr; + public int referenceCount; + public DateTime lastReferenced; + public IMesh meshData; + } + + private struct HullDesc + { + public IntPtr Ptr; + public int referenceCount; + public DateTime lastReferenced; + } + + private Dictionary Meshes = new Dictionary(); + private Dictionary Hulls = new Dictionary(); + + public BSShapeCollection(BSScene physScene) + { + PhysicsScene = physScene; + } + + public void Dispose() + { + } + + // Called to update/change the body and shape for an object. + // First checks the shape and updates that if necessary then makes + // sure the body is of the right type. + // Return 'true' if either the body or the shape changed. + // Called at taint-time!! + public bool GetBodyAndShape(bool forceRebuild, BulletSim sim, BSPrim prim, ShapeData shapeData, PrimitiveBaseShape pbs) + { + bool ret = false; + + // Do we have the correct geometry for this type of object? + if (CreateGeom(forceRebuild, prim, shapeData, pbs)) + { + // If we had to select a new shape geometry for the object, + // rebuild the body around it. + CreateObject(true, prim, PhysicsScene.World, prim.BSShape, shapeData); + ret = true; + } + + return ret; + } + + // Track another user of a body + public void ReferenceBody(BulletBody shape) + { + } + + // Release the usage of a body + public void DereferenceBody(BulletBody shape) + { + } + + // Track another user of the shape + public void ReferenceShape(BulletShape shape) + { + ReferenceShape(shape, null); + } + + // Track the datastructures and use count for a shape. + // When creating a hull, this is called first to reference the mesh + // and then again to reference the hull. + // Meshes and hulls for the same shape have the same hash key. + private void ReferenceShape(BulletShape shape, IMesh meshData) + { + switch (shape.type) + { + case ShapeData.PhysicsShapeType.SHAPE_MESH: + MeshDesc meshDesc; + if (Meshes.TryGetValue(shape.shapeKey, out meshDesc)) + { + // There is an existing instance of this mesh. + meshDesc.referenceCount++; + } + else + { + // This is a new reference to a mesh + meshDesc.Ptr = shape.Ptr; + meshDesc.meshData = meshData; + meshDesc.referenceCount = 1; + + } + meshDesc.lastReferenced = System.DateTime.Now; + Meshes[shape.shapeKey] = meshDesc; + break; + case ShapeData.PhysicsShapeType.SHAPE_HULL: + HullDesc hullDesc; + if (Hulls.TryGetValue(shape.shapeKey, out hullDesc)) + { + // There is an existing instance of this mesh. + hullDesc.referenceCount++; + } + else + { + // This is a new reference to a mesh + hullDesc.Ptr = shape.Ptr; + hullDesc.referenceCount = 1; + + } + hullDesc.lastReferenced = System.DateTime.Now; + Hulls[shape.shapeKey] = hullDesc; + break; + default: + break; + } + } + + // Release the usage of a shape + public void DereferenceShape(BulletShape shape) + { + switch (shape.type) + { + case ShapeData.PhysicsShapeType.SHAPE_HULL: + DereferenceHull(shape); + // Hulls also include a mesh + DereferenceMesh(shape); + break; + case ShapeData.PhysicsShapeType.SHAPE_MESH: + DereferenceMesh(shape); + break; + default: + break; + } + } + + // Count down the reference count for a mesh shape + private void DereferenceMesh(BulletShape shape) + { + MeshDesc meshDesc; + if (Meshes.TryGetValue(shape.shapeKey, out meshDesc)) + { + meshDesc.referenceCount--; + // TODO: release the Bullet storage + meshDesc.lastReferenced = System.DateTime.Now; + Meshes[shape.shapeKey] = meshDesc; + } + } + + // Count down the reference count for a hull shape + private void DereferenceHull(BulletShape shape) + { + HullDesc hullDesc; + if (Hulls.TryGetValue(shape.shapeKey, out hullDesc)) + { + hullDesc.referenceCount--; + // TODO: release the Bullet storage (aging old entries?) + hullDesc.lastReferenced = System.DateTime.Now; + Hulls[shape.shapeKey] = hullDesc; + } + } + + // Create the geometry information in Bullet for later use. + // The objects needs a hull if it's physical otherwise a mesh is enough. + // No locking here because this is done when we know physics is not simulating. + // if 'forceRebuild' is true, the geometry is rebuilt. Otherwise a previously built version is used. + // Returns 'true' if the geometry was rebuilt. + // Called at taint-time! + private bool CreateGeom(bool forceRebuild, BSPrim prim, ShapeData shapeData, PrimitiveBaseShape pbs) + { + bool ret = false; + bool haveShape = false; + bool nativeShapePossible = true; + + BulletShape newShape = new BulletShape(IntPtr.Zero); + + // If the object is dynamic, it must have a hull shape + if (prim.IsPhysical) + nativeShapePossible = false; + + // If the prim attributes are simple, this could be a simple Bullet native shape + if (nativeShapePossible + && ((pbs.SculptEntry && !PhysicsScene.ShouldMeshSculptedPrim) + || (pbs.ProfileBegin == 0 && pbs.ProfileEnd == 0 + && pbs.ProfileHollow == 0 + && pbs.PathTwist == 0 && pbs.PathTwistBegin == 0 + && pbs.PathBegin == 0 && pbs.PathEnd == 0 + && pbs.PathTaperX == 0 && pbs.PathTaperY == 0 + && pbs.PathScaleX == 100 && pbs.PathScaleY == 100 + && pbs.PathShearX == 0 && pbs.PathShearY == 0) ) ) + { + if (pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1) + { + haveShape = true; + if (forceRebuild || (prim.BSShape.type != ShapeData.PhysicsShapeType.SHAPE_SPHERE)) + { + DetailLog("{0},BSShapeCollection.CreateGeom,sphere (force={1}", prim.LocalID, forceRebuild); + newShape = AddNativeShapeToPrim(prim, shapeData, ShapeData.PhysicsShapeType.SHAPE_SPHERE); + + ret = true; + } + } + else + { + // m_log.DebugFormat("{0}: CreateGeom: Defaulting to box. lid={1}, type={2}, size={3}", LogHeader, LocalID, _shapeType, _size); + haveShape = true; + if (forceRebuild || (prim.BSShape.type != ShapeData.PhysicsShapeType.SHAPE_BOX)) + { + DetailLog("{0},BSShapeCollection.CreateGeom,box (force={1})", prim.LocalID, forceRebuild); + newShape = AddNativeShapeToPrim(prim, shapeData, ShapeData.PhysicsShapeType.SHAPE_BOX); + + ret = true; + } + } + } + // If a simple shape isn't happening, create a mesh and possibly a hull + if (!haveShape) + { + if (prim.IsPhysical) + { + if (forceRebuild || !Hulls.ContainsKey(prim.BSShape.shapeKey)) + { + // physical objects require a hull for interaction. + // This also creates the mesh if it doesn't already exist + ret = CreateGeomHull(prim, shapeData, pbs); + } + } + else + { + if (forceRebuild || !Meshes.ContainsKey(prim.BSShape.shapeKey)) + { + // Static (non-physical) objects only need a mesh for bumping into + ret = CreateGeomMesh(prim, shapeData, pbs); + } + } + } + return ret; + } + + private BulletShape AddNativeShapeToPrim(BSPrim prim, ShapeData shapeData, ShapeData.PhysicsShapeType shapeType) + { + BulletShape newShape; + + // Bullet native objects are scaled by the Bullet engine so pass the size in + prim.Scale = shapeData.Size; + + // release any previous shape + DereferenceShape(prim.BSShape); + + MeshDesc existingShapeDesc; + if (Meshes.TryGetValue(shapeData.MeshKey, out existingShapeDesc)) + { + // If there is an existing allocated shape, use it + newShape = new BulletShape(existingShapeDesc.Ptr, shapeType); + } + else + { + // Shape of this discriptioin is not allocated. Create new. + newShape = new BulletShape( + BulletSimAPI.BuildNativeShape2(PhysicsScene.World.Ptr, + (float)shapeType, + PhysicsScene.Params.collisionMargin, + prim.Scale), + shapeType); + } + newShape.shapeKey = shapeData.MeshKey; + ReferenceShape(newShape); + prim.BSShape = newShape; + return newShape; + } + + // No locking here because this is done when we know physics is not simulating + // Returns 'true' of a mesh was actually rebuild (we could also have one of these specs). + // Called at taint-time! + private bool CreateGeomMesh(BSPrim prim, ShapeData shapeData, PrimitiveBaseShape pbs) + { + BulletShape newShape = new BulletShape(IntPtr.Zero); + + // level of detail based on size and type of the object + float lod = PhysicsScene.MeshLOD; + if (pbs.SculptEntry) + lod = PhysicsScene.SculptLOD; + + float maxAxis = Math.Max(shapeData.Size.X, Math.Max(shapeData.Size.Y, shapeData.Size.Z)); + if (maxAxis > PhysicsScene.MeshMegaPrimThreshold) + lod = PhysicsScene.MeshMegaPrimLOD; + + ulong newMeshKey = (ulong)pbs.GetMeshKey(shapeData.Size, lod); + // m_log.DebugFormat("{0}: CreateGeomMesh: lID={1}, oldKey={2}, newKey={3}", LogHeader, LocalID, _meshKey, newMeshKey); + + // if this new shape is the same as last time, don't recreate the mesh + if (prim.BSShape.shapeKey == newMeshKey) return false; + + DetailLog("{0},BSShapeCollection.CreateGeomMesh,create,key={1}", prim.LocalID, newMeshKey); + + // Since we're recreating new, get rid of the reference to the previous shape + DereferenceShape(prim.BSShape); + + IMesh meshData = null; + IntPtr meshPtr; + MeshDesc meshDesc; + if (Meshes.TryGetValue(newMeshKey, out meshDesc)) + { + // If the mesh has already been built just use it. + meshPtr = meshDesc.Ptr; + } + else + { + // always pass false for physicalness as this creates some sort of bounding box which we don't need + meshData = PhysicsScene.mesher.CreateMesh(prim.PhysObjectName, pbs, shapeData.Size, lod, false); + + int[] indices = meshData.getIndexListAsInt(); + List vertices = meshData.getVertexList(); + + float[] verticesAsFloats = new float[vertices.Count * 3]; + int vi = 0; + foreach (OMV.Vector3 vv in vertices) + { + verticesAsFloats[vi++] = vv.X; + verticesAsFloats[vi++] = vv.Y; + verticesAsFloats[vi++] = vv.Z; + } + + // m_log.DebugFormat("{0}: CreateGeomMesh: calling CreateMesh. lid={1}, key={2}, indices={3}, vertices={4}", + // LogHeader, prim.LocalID, newMeshKey, indices.Length, vertices.Count); + + meshPtr = BulletSimAPI.CreateMeshShape2(PhysicsScene.World.Ptr, + indices.GetLength(0), indices, vertices.Count, verticesAsFloats); + } + newShape = new BulletShape(meshPtr, ShapeData.PhysicsShapeType.SHAPE_MESH); + newShape.shapeKey = newMeshKey; + + ReferenceShape(newShape, meshData); + + // meshes are already scaled by the meshmerizer + prim.Scale = new OMV.Vector3(1f, 1f, 1f); + prim.BSShape = newShape; + return true; // 'true' means a new shape has been added to this prim + } + + // No locking here because this is done when we know physics is not simulating + // Returns 'true' of a mesh was actually rebuild (we could also have one of these specs). + List m_hulls; + private bool CreateGeomHull(BSPrim prim, ShapeData shapeData, PrimitiveBaseShape pbs) + { + BulletShape newShape; + + float lod = pbs.SculptEntry ? PhysicsScene.SculptLOD : PhysicsScene.MeshLOD; + ulong newHullKey = (ulong)pbs.GetMeshKey(shapeData.Size, lod); + // m_log.DebugFormat("{0}: CreateGeomHull: lID={1}, oldKey={2}, newKey={3}", LogHeader, LocalID, _hullKey, newHullKey); + + // if the hull hasn't changed, don't rebuild it + if (newHullKey == prim.BSShape.shapeKey) return false; + + DetailLog("{0},BSShapeCollection.CreateGeomHull,create,oldKey={1},newKey={2}", prim.LocalID, newHullKey, newHullKey); + + // remove references to any previous shape + DereferenceShape(prim.BSShape); + + // Make sure the underlying mesh exists and is correct + // Since we're in the hull code, we know CreateGeomMesh() will not create a native shape. + CreateGeomMesh(prim, shapeData, pbs); + MeshDesc meshDesc = Meshes[newHullKey]; + + IntPtr hullPtr; + HullDesc hullDesc; + if (Hulls.TryGetValue(newHullKey, out hullDesc)) + { + hullPtr = hullDesc.Ptr; + } + else + { + int[] indices = meshDesc.meshData.getIndexListAsInt(); + List vertices = meshDesc.meshData.getVertexList(); + + //format conversion from IMesh format to DecompDesc format + List convIndices = new List(); + List convVertices = new List(); + for (int ii = 0; ii < indices.GetLength(0); ii++) + { + convIndices.Add(indices[ii]); + } + foreach (OMV.Vector3 vv in vertices) + { + convVertices.Add(new float3(vv.X, vv.Y, vv.Z)); + } + + // setup and do convex hull conversion + m_hulls = new List(); + DecompDesc dcomp = new DecompDesc(); + dcomp.mIndices = convIndices; + dcomp.mVertices = convVertices; + ConvexBuilder convexBuilder = new ConvexBuilder(HullReturn); + // create the hull into the _hulls variable + convexBuilder.process(dcomp); + + // Convert the vertices and indices for passing to unmanaged. + // The hull information is passed as a large floating point array. + // The format is: + // convHulls[0] = number of hulls + // convHulls[1] = number of vertices in first hull + // convHulls[2] = hull centroid X coordinate + // convHulls[3] = hull centroid Y coordinate + // convHulls[4] = hull centroid Z coordinate + // convHulls[5] = first hull vertex X + // convHulls[6] = first hull vertex Y + // convHulls[7] = first hull vertex Z + // convHulls[8] = second hull vertex X + // ... + // convHulls[n] = number of vertices in second hull + // convHulls[n+1] = second hull centroid X coordinate + // ... + // + // TODO: is is very inefficient. Someday change the convex hull generator to return + // data structures that do not need to be converted in order to pass to Bullet. + // And maybe put the values directly into pinned memory rather than marshaling. + int hullCount = m_hulls.Count; + int totalVertices = 1; // include one for the count of the hulls + foreach (ConvexResult cr in m_hulls) + { + totalVertices += 4; // add four for the vertex count and centroid + totalVertices += cr.HullIndices.Count * 3; // we pass just triangles + } + float[] convHulls = new float[totalVertices]; + + convHulls[0] = (float)hullCount; + int jj = 1; + foreach (ConvexResult cr in m_hulls) + { + // copy vertices for index access + float3[] verts = new float3[cr.HullVertices.Count]; + int kk = 0; + foreach (float3 ff in cr.HullVertices) + { + verts[kk++] = ff; + } + + // add to the array one hull's worth of data + convHulls[jj++] = cr.HullIndices.Count; + convHulls[jj++] = 0f; // centroid x,y,z + convHulls[jj++] = 0f; + convHulls[jj++] = 0f; + foreach (int ind in cr.HullIndices) + { + convHulls[jj++] = verts[ind].x; + convHulls[jj++] = verts[ind].y; + convHulls[jj++] = verts[ind].z; + } + } + // create the hull data structure in Bullet + // m_log.DebugFormat("{0}: CreateGeom: calling CreateHull. lid={1}, key={2}, hulls={3}", LogHeader, LocalID, _hullKey, hullCount); + hullPtr = BulletSimAPI.CreateHullShape2(PhysicsScene.World.Ptr, hullCount, convHulls); + } + newShape = new BulletShape(hullPtr, ShapeData.PhysicsShapeType.SHAPE_HULL); + newShape.shapeKey = newHullKey; + + ReferenceShape(newShape); + + // meshes are already scaled by the meshmerizer + prim.Scale = new OMV.Vector3(1f, 1f, 1f); + prim.BSShape = newShape; + return true; // 'true' means a new shape has been added to this prim + } + + // Callback from convex hull creater with a newly created hull. + // Just add it to the collection of hulls for this shape. + private void HullReturn(ConvexResult result) + { + m_hulls.Add(result); + return; + } + + // Create an object in Bullet if it has not already been created + // No locking here because this is done when the physics engine is not simulating + // Returns 'true' if an object was actually created. + private bool CreateObject(bool forceRebuild, BSPrim prim, BulletSim sim, BulletShape shape, ShapeData shapeData) + { + // the mesh or hull must have already been created in Bullet + // m_log.DebugFormat("{0}: CreateObject: lID={1}, shape={2}", LogHeader, LocalID, shape.Type); + + DereferenceBody(prim.BSBody); + + BulletBody aBody; + IntPtr bodyPtr = IntPtr.Zero; + if (prim.IsSolid) + { + bodyPtr = BulletSimAPI.CreateBodyFromShape2(sim.Ptr, shape.Ptr, shapeData.Position, shapeData.Rotation); + } + else + { + bodyPtr = BulletSimAPI.CreateGhostFromShape2(sim.Ptr, shape.Ptr, shapeData.Position, shapeData.Rotation); + } + aBody = new BulletBody(shapeData.ID, bodyPtr); + + ReferenceBody(aBody); + + prim.BSBody = aBody; + return true; + } + + private void DetailLog(string msg, params Object[] args) + { + PhysicsScene.PhysicsLogging.Write(msg, args); + } + + + + + +} +} diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs index 52c8a24..47875b0 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs @@ -40,7 +40,9 @@ public struct BulletSim { public BulletSim(uint worldId, BSScene bss, IntPtr xx) { - worldID = worldId; scene = bss; Ptr = xx; + worldID = worldId; + scene = bss; + Ptr = xx; } public uint worldID; // The scene is only in here so very low level routines have a handle to print debug/error messages @@ -58,6 +60,16 @@ public struct BulletBody } public IntPtr Ptr; public uint ID; + public override string ToString() + { + StringBuilder buff = new StringBuilder(); + buff.Append(""); + return buff.ToString(); + } } public struct BulletShape @@ -66,17 +78,29 @@ public struct BulletShape { Ptr = xx; type=ShapeData.PhysicsShapeType.SHAPE_UNKNOWN; - hashKey = 0; + shapeKey = 0; } public BulletShape(IntPtr xx, ShapeData.PhysicsShapeType typ) { Ptr = xx; type = typ; - hashKey = 0; + shapeKey = 0; } public IntPtr Ptr; public ShapeData.PhysicsShapeType type; - public ulong hashKey; + public ulong shapeKey; + public override string ToString() + { + StringBuilder buff = new StringBuilder(); + buff.Append(""); + return buff.ToString(); + } } // An allocated Bullet btConstraint @@ -155,10 +179,21 @@ public struct ShapeData public float Restitution; public float Collidable; // true of things bump into this public float Static; // true if a static object. Otherwise gravity, etc. + public float Solid; // true if object cannot be passed through + public Vector3 Size; // note that bools are passed as floats since bool size changes by language and architecture public const float numericTrue = 1f; public const float numericFalse = 0f; + + // The native shapes have predefined shape hash keys + public enum FixedShapeKey : ulong + { + KEY_BOX = 1, + KEY_SPHERE = 2, + KEY_CONE = 3, + KEY_CYLINDER = 4, + } } [StructLayout(LayoutKind.Sequential)] public struct SweepHit -- cgit v1.1 From 42802669dd8e2d574f9bbd25fbaa86b255fbe25b Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Fri, 21 Sep 2012 10:40:14 -0700 Subject: BulletSim: fix regression that caused cylindar shapes to have a box collision shape --- OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index 4d2c70c..b764379 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs @@ -1091,7 +1091,14 @@ public sealed class BSPrim : BSPhysObject bool haveShape = false; // If the prim attributes are simple, this could be a simple Bullet native shape - if ((_pbs.SculptEntry && !PhysicsScene.ShouldMeshSculptedPrim) + if ( + // if the basic shape is a cube or a sphere... + ((_pbs.ProfileShape == ProfileShape.Square && _pbs.PathCurve == (byte)Extrusion.Straight) + || (_pbs.ProfileShape == ProfileShape.HalfCircle && _pbs.PathCurve == (byte)Extrusion.Curve1 + /* && _pbs.Scale.X == _pbs.Scale.Y && _pbs.Scale.Y == _pbs.Scale.Z */ )) + // ... and we are not doing sculpty meshes... + && (_pbs.SculptEntry && !PhysicsScene.ShouldMeshSculptedPrim) + // ... or this is a 'simple' shape... || (_pbs.ProfileBegin == 0 && _pbs.ProfileEnd == 0 && _pbs.ProfileHollow == 0 && _pbs.PathTwist == 0 && _pbs.PathTwistBegin == 0 @@ -1099,6 +1106,7 @@ public sealed class BSPrim : BSPhysObject && _pbs.PathTaperX == 0 && _pbs.PathTaperY == 0 && _pbs.PathScaleX == 100 && _pbs.PathScaleY == 100 && _pbs.PathShearX == 0 && _pbs.PathShearY == 0) ) + // ... then this might be representable as a native Bullet collision shape { if (_pbs.ProfileShape == ProfileShape.HalfCircle && _pbs.PathCurve == (byte)Extrusion.Curve1) { -- cgit v1.1 From d016051fa028a485b09fac47b3fa3d8fd08e207a Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Sun, 23 Sep 2012 18:39:46 -0700 Subject: BulletSim: renamed members of BulletShape, BulletSim and BulletBody so the members case is consistant. Caused modifications everywhere. New logic in BSShapeCollection to track use and sharing of shapes. I just reslized, though, that shapes cannot be shared because the shape's UserPointer is the localID of the prim and is required for tracking collisions. More changes coming. Added DuplicateCollisionShape2() to API and changed BuildNativeShape2 to take a ShapeData structure so don't have to pass so many parameters. This matches the latest version of BulletSim.dll. Additions and removal of DetailLog() statements for debugging. --- .../Physics/BulletSPlugin/BS6DofConstraint.cs | 4 +- .../Region/Physics/BulletSPlugin/BSCharacter.cs | 12 +- .../Region/Physics/BulletSPlugin/BSConstraint.cs | 2 +- .../Physics/BulletSPlugin/BSHingeConstraint.cs | 110 +++---- OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs | 6 +- .../Region/Physics/BulletSPlugin/BSPhysObject.cs | 16 +- OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | 159 ++++++---- OpenSim/Region/Physics/BulletSPlugin/BSScene.cs | 4 +- .../Physics/BulletSPlugin/BSShapeCollection.cs | 344 +++++++++++++++------ .../Physics/BulletSPlugin/BSTerrainManager.cs | 46 +-- .../Region/Physics/BulletSPlugin/BulletSimAPI.cs | 49 +-- 11 files changed, 482 insertions(+), 270 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BS6DofConstraint.cs b/OpenSim/Region/Physics/BulletSPlugin/BS6DofConstraint.cs index 683bc51..ff271fe 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BS6DofConstraint.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BS6DofConstraint.cs @@ -44,7 +44,7 @@ public class BS6DofConstraint : BSConstraint m_body1 = obj1; m_body2 = obj2; m_constraint = new BulletConstraint( - BulletSimAPI.Create6DofConstraint2(m_world.Ptr, m_body1.Ptr, m_body2.Ptr, + BulletSimAPI.Create6DofConstraint2(m_world.ptr, m_body1.ptr, m_body2.ptr, frame1, frame1rot, frame2, frame2rot, useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies)); @@ -59,7 +59,7 @@ public class BS6DofConstraint : BSConstraint m_body1 = obj1; m_body2 = obj2; m_constraint = new BulletConstraint( - BulletSimAPI.Create6DofConstraintToPoint2(m_world.Ptr, m_body1.Ptr, m_body2.Ptr, + BulletSimAPI.Create6DofConstraintToPoint2(m_world.ptr, m_body1.ptr, m_body2.ptr, joinPoint, useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies)); m_enabled = true; diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs index 014cd99..e4b1dd4 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs @@ -114,7 +114,7 @@ public class BSCharacter : BSPhysObject // Set the buoyancy for flying. This will be refactored when all the settings happen in C# BulletSimAPI.SetObjectBuoyancy(PhysicsScene.WorldID, LocalID, _buoyancy); - BSBody = new BulletBody(LocalID, BulletSimAPI.GetBodyHandle2(PhysicsScene.World.Ptr, LocalID)); + BSBody = new BulletBody(LocalID, BulletSimAPI.GetBodyHandle2(PhysicsScene.World.ptr, LocalID)); }); return; @@ -189,10 +189,10 @@ public class BSCharacter : BSPhysObject _rotationalVelocity = OMV.Vector3.Zero; // Zero some other properties directly into the physics engine - BulletSimAPI.SetLinearVelocity2(BSBody.Ptr, OMV.Vector3.Zero); - BulletSimAPI.SetAngularVelocity2(BSBody.Ptr, OMV.Vector3.Zero); - BulletSimAPI.SetInterpolationVelocity2(BSBody.Ptr, OMV.Vector3.Zero, OMV.Vector3.Zero); - BulletSimAPI.ClearForces2(BSBody.Ptr); + BulletSimAPI.SetLinearVelocity2(BSBody.ptr, OMV.Vector3.Zero); + BulletSimAPI.SetAngularVelocity2(BSBody.ptr, OMV.Vector3.Zero); + BulletSimAPI.SetInterpolationVelocity2(BSBody.ptr, OMV.Vector3.Zero, OMV.Vector3.Zero); + BulletSimAPI.ClearForces2(BSBody.ptr); } public override void LockAngularMotion(OMV.Vector3 axis) { return; } @@ -437,7 +437,7 @@ public class BSCharacter : BSPhysObject PhysicsScene.TaintedObject("BSCharacter.AddForce", delegate() { DetailLog("{0},BSCharacter.setAddForce,taint,addedForce={1}", LocalID, _force); - BulletSimAPI.SetObjectForce2(BSBody.Ptr, _force); + BulletSimAPI.SetObjectForce2(BSBody.ptr, _force); }); } else diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs b/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs index 1376a29..c21252b 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs @@ -49,7 +49,7 @@ public abstract class BSConstraint : IDisposable if (m_enabled) { m_enabled = false; - bool success = BulletSimAPI.DestroyConstraint2(m_world.Ptr, m_constraint.Ptr); + bool success = BulletSimAPI.DestroyConstraint2(m_world.ptr, m_constraint.Ptr); m_world.scene.DetailLog("{0},BSConstraint.Dispose,taint,body1={1},body2={2},success={3}", BSScene.DetailLogZero, m_body1.ID, m_body2.ID, success); m_constraint.Ptr = System.IntPtr.Zero; } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSHingeConstraint.cs b/OpenSim/Region/Physics/BulletSPlugin/BSHingeConstraint.cs index d68048b..a6e4235 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSHingeConstraint.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSHingeConstraint.cs @@ -1,55 +1,55 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyrightD - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -using System; -using System.Collections.Generic; -using System.Text; -using OpenMetaverse; - -namespace OpenSim.Region.Physics.BulletSPlugin -{ - -class BSHingeConstraint : BSConstraint -{ - public BSHingeConstraint(BulletSim world, BulletBody obj1, BulletBody obj2, - Vector3 pivotInA, Vector3 pivotInB, - Vector3 axisInA, Vector3 axisInB, - bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies) - { - m_world = world; - m_body1 = obj1; - m_body2 = obj2; - m_constraint = new BulletConstraint( - BulletSimAPI.CreateHingeConstraint2(m_world.Ptr, m_body1.Ptr, m_body2.Ptr, - pivotInA, pivotInB, - axisInA, axisInB, - useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies)); - m_enabled = true; - } - -} - -} +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyrightD + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +using System; +using System.Collections.Generic; +using System.Text; +using OpenMetaverse; + +namespace OpenSim.Region.Physics.BulletSPlugin +{ + +class BSHingeConstraint : BSConstraint +{ + public BSHingeConstraint(BulletSim world, BulletBody obj1, BulletBody obj2, + Vector3 pivotInA, Vector3 pivotInB, + Vector3 axisInA, Vector3 axisInB, + bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies) + { + m_world = world; + m_body1 = obj1; + m_body2 = obj2; + m_constraint = new BulletConstraint( + BulletSimAPI.CreateHingeConstraint2(m_world.ptr, m_body1.ptr, m_body2.ptr, + pivotInA, pivotInB, + axisInA, axisInB, + useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies)); + m_enabled = true; + } + +} + +} diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs index 1e8fe52..84a7fac 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs @@ -282,10 +282,10 @@ public class BSLinkset { // If this is a multiple object linkset, set everybody's center of mass to the set's center of mass OMV.Vector3 centerOfMass = ComputeLinksetCenterOfMass(); - BulletSimAPI.SetCenterOfMassByPosRot2(LinksetRoot.BSBody.Ptr, centerOfMass, OMV.Quaternion.Identity); + BulletSimAPI.SetCenterOfMassByPosRot2(LinksetRoot.BSBody.ptr, centerOfMass, OMV.Quaternion.Identity); foreach (BSPhysObject child in m_children) { - BulletSimAPI.SetCenterOfMassByPosRot2(child.BSBody.Ptr, centerOfMass, OMV.Quaternion.Identity); + BulletSimAPI.SetCenterOfMassByPosRot2(child.BSBody.ptr, centerOfMass, OMV.Quaternion.Identity); } /* // The root prim takes on the weight of the whole linkset @@ -442,7 +442,7 @@ public class BSLinkset PhysicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.BSBody, childPrim.BSBody); // Make the child refresh its location - BulletSimAPI.PushUpdate2(childPrim.BSBody.Ptr); + BulletSimAPI.PushUpdate2(childPrim.BSBody.ptr); } // Remove linkage between myself and any possible children I might have diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs index 70a10b1..6a9fe50 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs @@ -1,4 +1,4 @@ -/* +/* * Copyright (c) Contributors, http://opensimulator.org/ * See CONTRIBUTORS.TXT for a full list of copyright holders. * @@ -121,8 +121,8 @@ public abstract class BSPhysObject : PhysicsActor // if someone has subscribed for collision events.... if (SubscribedEvents()) { CollisionCollection.AddCollider(collidingWith, new ContactPoint(contactPoint, contactNormal, pentrationDepth)); - // DetailLog("{0},{1}.Collison.AddCollider,call,with={2},point={3},normal={4},depth={5}", - // LocalID, TypeName, collidingWith, contactPoint, contactNormal, pentrationDepth); + DetailLog("{0},{1}.Collison.AddCollider,call,with={2},point={3},normal={4},depth={5}", + LocalID, TypeName, collidingWith, contactPoint, contactNormal, pentrationDepth); ret = true; } return ret; @@ -147,7 +147,7 @@ public abstract class BSPhysObject : PhysicsActor if (CollisionCollection.Count == 0) PhysicsScene.ObjectsWithNoMoreCollisions.Add(this); - // DetailLog("{0},{1}.SendCollisionUpdate,call,numCollisions={2}", LocalID, TypeName, CollisionCollection.Count); + DetailLog("{0},{1}.SendCollisionUpdate,call,numCollisions={2}", LocalID, TypeName, CollisionCollection.Count); base.SendCollisionUpdate(CollisionCollection); // The collisionCollection structure is passed around in the simulator. @@ -158,7 +158,8 @@ public abstract class BSPhysObject : PhysicsActor // Subscribe for collision events. // Parameter is the millisecond rate the caller wishes collision events to occur. - public override void SubscribeEvents(int ms) { + public override void SubscribeEvents(int ms) { + DetailLog("{0},BSScene.SubscribeEvents,subscribing,ms={1}", BSScene.DetailLogZero, ms); SubscribedEventsMs = ms; if (ms > 0) { @@ -167,7 +168,7 @@ public abstract class BSPhysObject : PhysicsActor PhysicsScene.TaintedObject(TypeName+".SubscribeEvents", delegate() { - CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(BSBody.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); + CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(BSBody.ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); }); } else @@ -177,10 +178,11 @@ public abstract class BSPhysObject : PhysicsActor } } public override void UnSubscribeEvents() { + DetailLog("{0},BSScene.UnSubscribeEvents,unsubscribing", BSScene.DetailLogZero); SubscribedEventsMs = 0; PhysicsScene.TaintedObject(TypeName+".UnSubscribeEvents", delegate() { - CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(BSBody.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); + CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(BSBody.ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); }); } // Return 'true' if the simulator wants collision events diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index b764379..5be2b1b 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs @@ -24,6 +24,11 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + +// Uncomment this it enable code to do all shape an body memory management +// in the C# code. +#define CSHARP_BODY_MANAGEMENT + using System; using System.Reflection; using System.Collections.Generic; @@ -36,6 +41,7 @@ using OpenSim.Region.Physics.ConvexDecompositionDotNet; namespace OpenSim.Region.Physics.BulletSPlugin { + [Serializable] public sealed class BSPrim : BSPhysObject { @@ -126,7 +132,7 @@ public sealed class BSPrim : BSPhysObject { CreateGeomAndObject(true); - CurrentCollisionFlags = BulletSimAPI.GetCollisionFlags2(BSBody.Ptr); + CurrentCollisionFlags = BulletSimAPI.GetCollisionFlags2(BSBody.ptr); }); } @@ -246,10 +252,10 @@ public sealed class BSPrim : BSPhysObject _rotationalVelocity = OMV.Vector3.Zero; // Zero some other properties directly into the physics engine - BulletSimAPI.SetLinearVelocity2(BSBody.Ptr, OMV.Vector3.Zero); - BulletSimAPI.SetAngularVelocity2(BSBody.Ptr, OMV.Vector3.Zero); - BulletSimAPI.SetInterpolationVelocity2(BSBody.Ptr, OMV.Vector3.Zero, OMV.Vector3.Zero); - BulletSimAPI.ClearForces2(BSBody.Ptr); + BulletSimAPI.SetLinearVelocity2(BSBody.ptr, OMV.Vector3.Zero); + BulletSimAPI.SetAngularVelocity2(BSBody.ptr, OMV.Vector3.Zero); + BulletSimAPI.SetInterpolationVelocity2(BSBody.ptr, OMV.Vector3.Zero, OMV.Vector3.Zero); + BulletSimAPI.ClearForces2(BSBody.ptr); } public override void LockAngularMotion(OMV.Vector3 axis) @@ -262,7 +268,7 @@ public sealed class BSPrim : BSPhysObject get { if (!Linkset.IsRoot(this)) // child prims move around based on their parent. Need to get the latest location - _position = BulletSimAPI.GetPosition2(BSBody.Ptr); + _position = BulletSimAPI.GetPosition2(BSBody.ptr); // don't do the GetObjectPosition for root elements because this function is called a zillion times // _position = BulletSimAPI.GetObjectPosition(Scene.WorldID, LocalID); @@ -274,7 +280,7 @@ public sealed class BSPrim : BSPhysObject PhysicsScene.TaintedObject("BSPrim.setPosition", delegate() { DetailLog("{0},BSPrim.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation); - BulletSimAPI.SetTranslation2(BSBody.Ptr, _position, _orientation); + BulletSimAPI.SetTranslation2(BSBody.ptr, _position, _orientation); }); } } @@ -312,7 +318,7 @@ public sealed class BSPrim : BSPhysObject PhysicsScene.TaintedObject("BSPrim.setForce", delegate() { DetailLog("{0},BSPrim.setForce,taint,force={1}", LocalID, _force); - BulletSimAPI.SetObjectForce2(BSBody.Ptr, _force); + BulletSimAPI.SetObjectForce2(BSBody.ptr, _force); }); } } @@ -374,12 +380,15 @@ public sealed class BSPrim : BSPhysObject // Allows the detection of collisions with inherently non-physical prims. see llVolumeDetect for more public override void SetVolumeDetect(int param) { bool newValue = (param != 0); - _isVolumeDetect = newValue; - PhysicsScene.TaintedObject("BSPrim.SetVolumeDetect", delegate() + if (_isVolumeDetect != newValue) { - DetailLog("{0},setVolumeDetect,taint,volDetect={1}", LocalID, _isVolumeDetect); - SetObjectDynamic(true); - }); + _isVolumeDetect = newValue; + PhysicsScene.TaintedObject("BSPrim.SetVolumeDetect", delegate() + { + DetailLog("{0},setVolumeDetect,taint,volDetect={1}", LocalID, _isVolumeDetect); + SetObjectDynamic(true); + }); + } return; } @@ -390,7 +399,7 @@ public sealed class BSPrim : BSPhysObject PhysicsScene.TaintedObject("BSPrim.setVelocity", delegate() { DetailLog("{0},BSPrim.SetVelocity,taint,vel={1}", LocalID, _velocity); - BulletSimAPI.SetLinearVelocity2(BSBody.Ptr, _velocity); + BulletSimAPI.SetLinearVelocity2(BSBody.ptr, _velocity); }); } } @@ -414,7 +423,7 @@ public sealed class BSPrim : BSPhysObject if (!Linkset.IsRoot(this)) { // Children move around because tied to parent. Get a fresh value. - _orientation = BulletSimAPI.GetOrientation2(BSBody.Ptr); + _orientation = BulletSimAPI.GetOrientation2(BSBody.ptr); } return _orientation; } @@ -425,7 +434,7 @@ public sealed class BSPrim : BSPhysObject { // _position = BulletSimAPI.GetObjectPosition(Scene.WorldID, LocalID); DetailLog("{0},BSPrim.setOrientation,taint,pos={1},orient={2}", LocalID, _position, _orientation); - BulletSimAPI.SetTranslation2(BSBody.Ptr, _position, _orientation); + BulletSimAPI.SetTranslation2(BSBody.ptr, _position, _orientation); }); } } @@ -436,12 +445,15 @@ public sealed class BSPrim : BSPhysObject public override bool IsPhysical { get { return _isPhysical; } set { - _isPhysical = value; - PhysicsScene.TaintedObject("BSPrim.setIsPhysical", delegate() + if (_isPhysical != value) { - DetailLog("{0},setIsPhysical,taint,isPhys={1}", LocalID, _isPhysical); - SetObjectDynamic(true); - }); + _isPhysical = value; + PhysicsScene.TaintedObject("BSPrim.setIsPhysical", delegate() + { + DetailLog("{0},setIsPhysical,taint,isPhys={1}", LocalID, _isPhysical); + SetObjectDynamic(true); + }); + } } } @@ -458,7 +470,7 @@ public sealed class BSPrim : BSPhysObject } // Make gravity work if the object is physical and not selected - // No locking here because only called when it is safe + // No locking here because only called when it is safe (called at taint-time). // There are four flags we're interested in: // IsStatic: Object does not move, otherwise the object has mass and moves // isSolid: other objects bounce off of this object @@ -481,11 +493,13 @@ public sealed class BSPrim : BSPhysObject DetailLog("{0},BSPrim.UpdatePhysicalParameters,entry,body={1},shape={2}", LocalID, BSBody, BSShape); // Mangling all the physical properties requires the object to be out of the physical world - BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.Ptr, BSBody.Ptr); + BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, BSBody.ptr); +#if !CSHARP_BODY_MANAGEMENT // Make solid or not (do things bounce off or pass through this object) // This is done first because it can change the collisionObject type. MakeSolid(IsSolid); +#endif // !CSHARP_BODY_MANAGEMENT // Set up the object physicalness (does gravity and collisions move this object) MakeDynamic(IsStatic); @@ -493,15 +507,23 @@ public sealed class BSPrim : BSPhysObject // Arrange for collisions events if the simulator wants them EnableCollisions(SubscribedEvents()); - BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.Ptr, BSBody.Ptr); +#if CSHARP_BODY_MANAGEMENT + // Make solid or not (do things bounce off or pass through this object). + MakeSolid(IsSolid); +#endif // CSHARP_BODY_MANAGEMENT + + BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, BSBody.ptr); + + // Rebuild its shape + BulletSimAPI.UpdateSingleAabb2(PhysicsScene.World.ptr, BSBody.ptr); // Recompute any linkset parameters. // When going from non-physical to physical, this re-enables the constraints that // had been automatically disabled when the mass was set to zero. Linkset.Refresh(this); - DetailLog("{0},BSPrim.UpdatePhysicalParameters,taint,static={1},solid={2},mass={3},collide={4},cf={5}", - LocalID, IsStatic, IsSolid, _mass, SubscribedEvents(), CurrentCollisionFlags); + DetailLog("{0},BSPrim.UpdatePhysicalParameters,exit,static={1},solid={2},mass={3},collide={4},cf={5:X},body={6},shape={7}", + LocalID, IsStatic, IsSolid, _mass, SubscribedEvents(), CurrentCollisionFlags, BSBody, BSShape); } // "Making dynamic" means changing to and from static. @@ -514,52 +536,52 @@ public sealed class BSPrim : BSPhysObject if (makeStatic) { // Become a Bullet 'static' object type - CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(BSBody.Ptr, CollisionFlags.CF_STATIC_OBJECT); + CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(BSBody.ptr, CollisionFlags.CF_STATIC_OBJECT); // Stop all movement - BulletSimAPI.ClearAllForces2(BSBody.Ptr); + BulletSimAPI.ClearAllForces2(BSBody.ptr); // Center of mass is at the center of the object - BulletSimAPI.SetCenterOfMassByPosRot2(Linkset.LinksetRoot.BSBody.Ptr, _position, _orientation); + BulletSimAPI.SetCenterOfMassByPosRot2(Linkset.LinksetRoot.BSBody.ptr, _position, _orientation); // Mass is zero which disables a bunch of physics stuff in Bullet - BulletSimAPI.SetMassProps2(BSBody.Ptr, 0f, OMV.Vector3.Zero); + BulletSimAPI.SetMassProps2(BSBody.ptr, 0f, OMV.Vector3.Zero); // There is no inertia in a static object - BulletSimAPI.UpdateInertiaTensor2(BSBody.Ptr); + BulletSimAPI.UpdateInertiaTensor2(BSBody.ptr); // There can be special things needed for implementing linksets Linkset.MakeStatic(this); // The activation state is 'sleeping' so Bullet will not try to act on it - BulletSimAPI.ForceActivationState2(BSBody.Ptr, ActivationState.ISLAND_SLEEPING); + BulletSimAPI.ForceActivationState2(BSBody.ptr, ActivationState.ISLAND_SLEEPING); // BulletSimAPI.ForceActivationState2(BSBody.Ptr, ActivationState.DISABLE_SIMULATION); } else { // Not a Bullet static object - CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(BSBody.Ptr, CollisionFlags.CF_STATIC_OBJECT); + CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(BSBody.ptr, CollisionFlags.CF_STATIC_OBJECT); // Set various physical properties so internal dynamic properties will get computed correctly as they are set - BulletSimAPI.SetFriction2(BSBody.Ptr, PhysicsScene.Params.defaultFriction); - BulletSimAPI.SetRestitution2(BSBody.Ptr, PhysicsScene.Params.defaultRestitution); + BulletSimAPI.SetFriction2(BSBody.ptr, PhysicsScene.Params.defaultFriction); + BulletSimAPI.SetRestitution2(BSBody.ptr, PhysicsScene.Params.defaultRestitution); // per http://www.bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=3382 - BulletSimAPI.SetInterpolationLinearVelocity2(BSBody.Ptr, OMV.Vector3.Zero); - BulletSimAPI.SetInterpolationAngularVelocity2(BSBody.Ptr, OMV.Vector3.Zero); - BulletSimAPI.SetInterpolationVelocity2(BSBody.Ptr, OMV.Vector3.Zero, OMV.Vector3.Zero); + BulletSimAPI.SetInterpolationLinearVelocity2(BSBody.ptr, OMV.Vector3.Zero); + BulletSimAPI.SetInterpolationAngularVelocity2(BSBody.ptr, OMV.Vector3.Zero); + BulletSimAPI.SetInterpolationVelocity2(BSBody.ptr, OMV.Vector3.Zero, OMV.Vector3.Zero); // A dynamic object has mass - IntPtr collisionShapePtr = BulletSimAPI.GetCollisionShape2(BSBody.Ptr); + IntPtr collisionShapePtr = BulletSimAPI.GetCollisionShape2(BSBody.ptr); OMV.Vector3 inertia = BulletSimAPI.CalculateLocalInertia2(collisionShapePtr, Linkset.LinksetMass); - BulletSimAPI.SetMassProps2(BSBody.Ptr, _mass, inertia); + BulletSimAPI.SetMassProps2(BSBody.ptr, _mass, inertia); // Inertia is based on our new mass - BulletSimAPI.UpdateInertiaTensor2(BSBody.Ptr); + BulletSimAPI.UpdateInertiaTensor2(BSBody.ptr); // Various values for simulation limits - BulletSimAPI.SetDamping2(BSBody.Ptr, PhysicsScene.Params.linearDamping, PhysicsScene.Params.angularDamping); - BulletSimAPI.SetDeactivationTime2(BSBody.Ptr, PhysicsScene.Params.deactivationTime); - BulletSimAPI.SetSleepingThresholds2(BSBody.Ptr, PhysicsScene.Params.linearSleepingThreshold, PhysicsScene.Params.angularSleepingThreshold); - BulletSimAPI.SetContactProcessingThreshold2(BSBody.Ptr, PhysicsScene.Params.contactProcessingThreshold); + BulletSimAPI.SetDamping2(BSBody.ptr, PhysicsScene.Params.linearDamping, PhysicsScene.Params.angularDamping); + BulletSimAPI.SetDeactivationTime2(BSBody.ptr, PhysicsScene.Params.deactivationTime); + BulletSimAPI.SetSleepingThresholds2(BSBody.ptr, PhysicsScene.Params.linearSleepingThreshold, PhysicsScene.Params.angularSleepingThreshold); + BulletSimAPI.SetContactProcessingThreshold2(BSBody.ptr, PhysicsScene.Params.contactProcessingThreshold); // There can be special things needed for implementing linksets Linkset.MakeDynamic(this); // Force activation of the object so Bullet will act on it. - BulletSimAPI.Activate2(BSBody.Ptr, true); + BulletSimAPI.Activate2(BSBody.ptr, true); } } @@ -569,8 +591,28 @@ public sealed class BSPrim : BSPhysObject // the functions after this one set up the state of a possibly newly created collision body. private void MakeSolid(bool makeSolid) { -#if !CSHARP_BODY_MANAGEMENT - CollisionObjectTypes bodyType = (CollisionObjectTypes)BulletSimAPI.GetBodyType2(BSBody.Ptr); +#if CSHARP_BODY_MANAGEMENT + CollisionObjectTypes bodyType = (CollisionObjectTypes)BulletSimAPI.GetBodyType2(BSBody.ptr); + if (makeSolid) + { + // Verify the previous code created the correct shape for this type of thing. + if ((bodyType & CollisionObjectTypes.CO_RIGID_BODY) == 0) + { + m_log.ErrorFormat("{0} MakeSolid: physical body of wrong type for solidity. id={1}, type={2}", LogHeader, LocalID, bodyType); + } + CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(BSBody.ptr, CollisionFlags.CF_NO_CONTACT_RESPONSE); + } + else + { + if ((bodyType & CollisionObjectTypes.CO_GHOST_OBJECT) == 0) + { + m_log.ErrorFormat("{0} MakeSolid: physical body of wrong type for non-solidness. id={1}, type={2}", LogHeader, LocalID, bodyType); + } + CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(BSBody.ptr, CollisionFlags.CF_NO_CONTACT_RESPONSE); + } +#else + // If doing the body management in C#, all this logic is in CSShapeCollection.CreateObject(). + CollisionObjectTypes bodyType = (CollisionObjectTypes)BulletSimAPI.GetBodyType2(BSBody.ptr); if (makeSolid) { if ((bodyType & CollisionObjectTypes.CO_RIGID_BODY) == 0) @@ -618,11 +660,11 @@ public sealed class BSPrim : BSPhysObject { if (wantsCollisionEvents) { - CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(BSBody.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); + CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(BSBody.ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); } else { - CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(BSBody.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); + CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(BSBody.ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); } } @@ -683,7 +725,7 @@ public sealed class BSPrim : BSPhysObject PhysicsScene.TaintedObject("BSPrim.setRotationalVelocity", delegate() { DetailLog("{0},BSPrim.SetRotationalVel,taint,rotvel={1}", LocalID, _rotationalVelocity); - BulletSimAPI.SetAngularVelocity2(BSBody.Ptr, _rotationalVelocity); + BulletSimAPI.SetAngularVelocity2(BSBody.ptr, _rotationalVelocity); }); } } @@ -702,7 +744,7 @@ public sealed class BSPrim : BSPhysObject DetailLog("{0},BSPrim.SetBuoyancy,taint,buoy={1}", LocalID, _buoyancy); // Buoyancy is faked by changing the gravity applied to the object float grav = PhysicsScene.Params.gravity * (1f - _buoyancy); - BulletSimAPI.SetGravity2(BSBody.Ptr, new OMV.Vector3(0f, 0f, grav)); + BulletSimAPI.SetGravity2(BSBody.ptr, new OMV.Vector3(0f, 0f, grav)); // BulletSimAPI.SetObjectBuoyancy(Scene.WorldID, LocalID, _buoyancy); }); } @@ -767,7 +809,7 @@ public sealed class BSPrim : BSPhysObject } DetailLog("{0},BSPrim.AddObjectForce,taint,force={1}", LocalID, fSum); // For unknown reasons, "ApplyCentralForce" adds this force to the total force on the object. - BulletSimAPI.ApplyCentralForce2(BSBody.Ptr, fSum); + BulletSimAPI.ApplyCentralForce2(BSBody.ptr, fSum); }); } @@ -1394,7 +1436,7 @@ public sealed class BSPrim : BSPhysObject } // Rebuild the geometry and object. // This is called when the shape changes so we need to recreate the mesh/hull. - // No locking here because this is done when the physics engine is not simulating + // No locking here because this is done when the physics engine is not simulating (taint-time). private void CreateGeomAndObject(bool forceRebuild) { #if CSHARP_BODY_MANAGEMENT @@ -1403,11 +1445,10 @@ public sealed class BSPrim : BSPhysObject // Create the correct physical representation for this type of object. // Updates BSBody and BSShape with the new information. - if (PhysicsScene.Shapes.GetBodyAndShape(forceRebuild, PhysicsScene.World, this, shapeData, _pbs)) - { - // Make sure the properties are set on the new object - UpdatePhysicalParameters(); - } + PhysicsScene.Shapes.GetBodyAndShape(forceRebuild, PhysicsScene.World, this, shapeData, _pbs); + + // Make sure the properties are set on the new object + UpdatePhysicalParameters(); #else // m_log.DebugFormat("{0}: CreateGeomAndObject. lID={1}, force={2}", LogHeader, LocalID, forceRebuild); // Create the geometry that will make up the object diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs index 76da42d..87c7b1b 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs @@ -589,6 +589,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters { if (localID <= TerrainManager.HighestTerrainID) { + DetailLog("{0},BSScene.SendCollision,collideWithTerrain,id={1},with={2}", DetailLogZero, localID, collidingWith); return; // don't send collisions to the terrain } @@ -596,6 +597,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters if (!PhysObjects.TryGetValue(localID, out collider)) { // If the object that is colliding cannot be found, just ignore the collision. + DetailLog("{0},BSScene.SendCollision,colliderNotInObjectList,id={1},with={2}", DetailLogZero, localID, collidingWith); return; } @@ -604,7 +606,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters BSPhysObject collidee = null; PhysObjects.TryGetValue(collidingWith, out collidee); - // DetailLog("{0},BSScene.SendCollision,collide,id={1},with={2}", DetailLogZero, localID, collidingWith); + DetailLog("{0},BSScene.SendCollision,collide,id={1},with={2}", DetailLogZero, localID, collidingWith); if (collider.Collide(collidingWith, collidee, collidePoint, collideNormal, penetration)) { diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs index 7470d23..6b90661 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs @@ -38,8 +38,9 @@ public class BSShapeCollection : IDisposable { protected BSScene PhysicsScene { get; set; } - private Object m_shapeActivityLock = new Object(); + private Object m_collectionActivityLock = new Object(); + // Description of a Mesh private struct MeshDesc { public IntPtr Ptr; @@ -48,6 +49,8 @@ public class BSShapeCollection : IDisposable public IMesh meshData; } + // Description of a hull. + // Meshes and hulls have the same shape hash key but we only need hulls for efficient physical objects private struct HullDesc { public IntPtr Ptr; @@ -55,8 +58,17 @@ public class BSShapeCollection : IDisposable public DateTime lastReferenced; } + private struct BodyDesc + { + public IntPtr Ptr; + // Bodies are only used once so reference count is always either one or zero + public int referenceCount; + public DateTime lastReferenced; + } + private Dictionary Meshes = new Dictionary(); private Dictionary Hulls = new Dictionary(); + private Dictionary Bodies = new Dictionary(); public BSShapeCollection(BSScene physScene) { @@ -65,6 +77,7 @@ public class BSShapeCollection : IDisposable public void Dispose() { + // TODO!!!!!!!!! } // Called to update/change the body and shape for an object. @@ -76,40 +89,104 @@ public class BSShapeCollection : IDisposable { bool ret = false; - // Do we have the correct geometry for this type of object? - if (CreateGeom(forceRebuild, prim, shapeData, pbs)) + // This lock could probably be pushed down lower but building shouldn't take long + lock (m_collectionActivityLock) { + // Do we have the correct geometry for this type of object? + bool newGeom = CreateGeom(forceRebuild, prim, shapeData, pbs); // If we had to select a new shape geometry for the object, // rebuild the body around it. - CreateObject(true, prim, PhysicsScene.World, prim.BSShape, shapeData); - ret = true; + bool newBody = CreateBody((newGeom || forceRebuild), prim, PhysicsScene.World, prim.BSShape, shapeData); + ret = newGeom || newBody; } + DetailLog("{0},BSShapeCollection.GetBodyAndShape,force-{1},ret={2},body={3},shape={4}", + prim.LocalID, forceRebuild, ret, prim.BSBody, prim.BSShape); return ret; } // Track another user of a body - public void ReferenceBody(BulletBody shape) + // We presume the caller has allocated the body. + // Bodies only have one user so the reference count is either 1 or 0. + public void ReferenceBody(BulletBody shape, bool atTaintTime) { - } + lock (m_collectionActivityLock) + { + BodyDesc bodyDesc; + if (Bodies.TryGetValue(shape.ID, out bodyDesc)) + { + bodyDesc.referenceCount++; + DetailLog("{0},BSShapeCollection.ReferenceBody,existingBody,ref={1}", shape.ID, bodyDesc.referenceCount); + } + else + { + bodyDesc.Ptr = shape.ptr; + bodyDesc.referenceCount = 1; + DetailLog("{0},BSShapeCollection.ReferenceBody,newBody,ref={1}", shape.ID, bodyDesc.referenceCount); + } + bodyDesc.lastReferenced = System.DateTime.Now; + Bodies[shape.ID] = bodyDesc; + } +} - // Release the usage of a body - public void DereferenceBody(BulletBody shape) + // Release the usage of a body. + // Not that this will also delete the body in BUllet if the body is now unused (reference count = 0). + public void DereferenceBody(BulletBody shape, bool inTaintTime) { + if (shape.ptr == IntPtr.Zero) + return; + + lock (m_collectionActivityLock) + { + BodyDesc bodyDesc; + if (Bodies.TryGetValue(shape.ID, out bodyDesc)) + { + bodyDesc.referenceCount--; + bodyDesc.lastReferenced = System.DateTime.Now; + Bodies[shape.ID] = bodyDesc; + DetailLog("{0},BSShapeCollection.DereferenceBody,ref={1}", shape.ID, bodyDesc.referenceCount); + + if (bodyDesc.referenceCount == 0) + { + Bodies.Remove(shape.ID); + BSScene.TaintCallback removeOperation = delegate() + { + DetailLog("{0},BSShapeCollection.DereferenceBody,DestroyingBody. Ptr={1:X}", shape.ID, shape.ptr); + // zero any reference to the shape so it is not freed when the body is deleted + BulletSimAPI.SetCollisionShape2(PhysicsScene.World.ptr, shape.ptr, IntPtr.Zero); + // It may have already been removed from the world in which case the next is a NOOP + BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, shape.ptr); + BulletSimAPI.DestroyObject2(PhysicsScene.World.ptr, shape.ptr); + }; + // If already in taint-time, do the operations now. Otherwise queue for later. + if (inTaintTime) + removeOperation(); + else + PhysicsScene.TaintedObject("BSShapeCollection.DereferenceBody", removeOperation); + } + } + else + { + DetailLog("{0},BSShapeCollection.DereferenceBody,DID NOT FIND BODY", shape.ID, bodyDesc.referenceCount); + } + } } // Track another user of the shape - public void ReferenceShape(BulletShape shape) + private bool ReferenceShape(BulletShape shape) { - ReferenceShape(shape, null); + return ReferenceShape(shape, null); } // Track the datastructures and use count for a shape. // When creating a hull, this is called first to reference the mesh // and then again to reference the hull. // Meshes and hulls for the same shape have the same hash key. - private void ReferenceShape(BulletShape shape, IMesh meshData) + // NOTE that native shapes are not added to the mesh list or removed. + // Returns 'true' if this is the initial reference to the shape. Otherwise reused. + private bool ReferenceShape(BulletShape shape, IMesh meshData) { + bool ret = false; switch (shape.type) { case ShapeData.PhysicsShapeType.SHAPE_MESH: @@ -118,14 +195,18 @@ public class BSShapeCollection : IDisposable { // There is an existing instance of this mesh. meshDesc.referenceCount++; + DetailLog("{0},BSShapeColliction.ReferenceShape,existingMesh,key={1},cnt={2}", + BSScene.DetailLogZero, shape.shapeKey, meshDesc.referenceCount); } else { // This is a new reference to a mesh - meshDesc.Ptr = shape.Ptr; + meshDesc.Ptr = shape.ptr; meshDesc.meshData = meshData; meshDesc.referenceCount = 1; - + DetailLog("{0},BSShapeColliction.ReferenceShape,newMesh,key={1},cnt={2}", + BSScene.DetailLogZero, shape.shapeKey, meshDesc.referenceCount); + ret = true; } meshDesc.lastReferenced = System.DateTime.Now; Meshes[shape.shapeKey] = meshDesc; @@ -136,41 +217,68 @@ public class BSShapeCollection : IDisposable { // There is an existing instance of this mesh. hullDesc.referenceCount++; + DetailLog("{0},BSShapeColliction.ReferenceShape,existingHull,key={1},cnt={2}", + BSScene.DetailLogZero, shape.shapeKey, hullDesc.referenceCount); } else { - // This is a new reference to a mesh - hullDesc.Ptr = shape.Ptr; + // This is a new reference to a hull + hullDesc.Ptr = shape.ptr; hullDesc.referenceCount = 1; + DetailLog("{0},BSShapeColliction.ReferenceShape,newHull,key={1},cnt={2}", + BSScene.DetailLogZero, shape.shapeKey, hullDesc.referenceCount); + ret = true; } hullDesc.lastReferenced = System.DateTime.Now; Hulls[shape.shapeKey] = hullDesc; break; + case ShapeData.PhysicsShapeType.SHAPE_UNKNOWN: + break; default: + // Native shapes are not tracked and they don't go into any list break; } + return ret; } // Release the usage of a shape - public void DereferenceShape(BulletShape shape) + private void DereferenceShape(BulletShape shape, bool atTaintTime) { - switch (shape.type) + if (shape.ptr == IntPtr.Zero) + return; + + BSScene.TaintCallback dereferenceOperation = delegate() { - case ShapeData.PhysicsShapeType.SHAPE_HULL: - DereferenceHull(shape); - // Hulls also include a mesh - DereferenceMesh(shape); - break; - case ShapeData.PhysicsShapeType.SHAPE_MESH: - DereferenceMesh(shape); - break; - default: - break; - } + switch (shape.type) + { + case ShapeData.PhysicsShapeType.SHAPE_HULL: + DereferenceHull(shape); + // Hulls also include a mesh + DereferenceMesh(shape); + break; + case ShapeData.PhysicsShapeType.SHAPE_MESH: + DereferenceMesh(shape); + break; + case ShapeData.PhysicsShapeType.SHAPE_UNKNOWN: + break; + default: + // Native shapes are not tracked and are released immediately + if (shape.ptr != IntPtr.Zero & shape.isNativeShape) + { + BulletSimAPI.DeleteCollisionShape2(PhysicsScene.World.ptr, shape.ptr); + } + break; + } + }; + if (atTaintTime) + dereferenceOperation(); + else + PhysicsScene.TaintedObject("BSShapeCollection.DereferenceShape", dereferenceOperation); } // Count down the reference count for a mesh shape + // Called at taint-time. private void DereferenceMesh(BulletShape shape) { MeshDesc meshDesc; @@ -180,10 +288,14 @@ public class BSShapeCollection : IDisposable // TODO: release the Bullet storage meshDesc.lastReferenced = System.DateTime.Now; Meshes[shape.shapeKey] = meshDesc; + DetailLog("{0},BSShapeColliction.DereferenceMesh,key={1},cnt={2}", + BSScene.DetailLogZero, shape.shapeKey, meshDesc.referenceCount); + } } // Count down the reference count for a hull shape + // Called at taint-time. private void DereferenceHull(BulletShape shape) { HullDesc hullDesc; @@ -193,6 +305,8 @@ public class BSShapeCollection : IDisposable // TODO: release the Bullet storage (aging old entries?) hullDesc.lastReferenced = System.DateTime.Now; Hulls[shape.shapeKey] = hullDesc; + DetailLog("{0},BSShapeColliction.DereferenceHull,key={1},cnt={2}", + BSScene.DetailLogZero, shape.shapeKey, hullDesc.referenceCount); } } @@ -210,10 +324,6 @@ public class BSShapeCollection : IDisposable BulletShape newShape = new BulletShape(IntPtr.Zero); - // If the object is dynamic, it must have a hull shape - if (prim.IsPhysical) - nativeShapePossible = false; - // If the prim attributes are simple, this could be a simple Bullet native shape if (nativeShapePossible && ((pbs.SculptEntry && !PhysicsScene.ShouldMeshSculptedPrim) @@ -230,8 +340,10 @@ public class BSShapeCollection : IDisposable haveShape = true; if (forceRebuild || (prim.BSShape.type != ShapeData.PhysicsShapeType.SHAPE_SPHERE)) { - DetailLog("{0},BSShapeCollection.CreateGeom,sphere (force={1}", prim.LocalID, forceRebuild); - newShape = AddNativeShapeToPrim(prim, shapeData, ShapeData.PhysicsShapeType.SHAPE_SPHERE); + newShape = AddNativeShapeToPrim( + prim, shapeData, ShapeData.PhysicsShapeType.SHAPE_SPHERE, ShapeData.FixedShapeKey.KEY_SPHERE); + DetailLog("{0},BSShapeCollection.CreateGeom,sphere,force={1},shape={2}", + prim.LocalID, forceRebuild,prim.BSShape); ret = true; } @@ -242,71 +354,87 @@ public class BSShapeCollection : IDisposable haveShape = true; if (forceRebuild || (prim.BSShape.type != ShapeData.PhysicsShapeType.SHAPE_BOX)) { - DetailLog("{0},BSShapeCollection.CreateGeom,box (force={1})", prim.LocalID, forceRebuild); - newShape = AddNativeShapeToPrim(prim, shapeData, ShapeData.PhysicsShapeType.SHAPE_BOX); + newShape = AddNativeShapeToPrim( + prim, shapeData, ShapeData.PhysicsShapeType.SHAPE_BOX, ShapeData.FixedShapeKey.KEY_BOX); + DetailLog("{0},BSShapeCollection.CreateGeom,box,force={1},shape={2}", + prim.LocalID, forceRebuild,prim.BSShape); ret = true; } } } - // If a simple shape isn't happening, create a mesh and possibly a hull + // If a simple shape is not happening, create a mesh and possibly a hull + // Note that if it's a native shape, the check for physical/non-physical is not + // made. Native shapes are best used in either case. if (!haveShape) { if (prim.IsPhysical) { - if (forceRebuild || !Hulls.ContainsKey(prim.BSShape.shapeKey)) + if (forceRebuild || !Hulls.ContainsKey(shapeData.HullKey)) { // physical objects require a hull for interaction. - // This also creates the mesh if it doesn't already exist + // This also creates the mesh if it doesn't already exist. ret = CreateGeomHull(prim, shapeData, pbs); } + else + { + prim.BSShape = new BulletShape(Hulls[shapeData.HullKey].Ptr, + ShapeData.PhysicsShapeType.SHAPE_HULL); + prim.BSShape.shapeKey = shapeData.HullKey; + // Another user of this shape. + ReferenceShape(prim.BSShape); + ret = true; + } } else { if (forceRebuild || !Meshes.ContainsKey(prim.BSShape.shapeKey)) { // Static (non-physical) objects only need a mesh for bumping into + // Returning 'true' means prim.BShape was changed. ret = CreateGeomMesh(prim, shapeData, pbs); } + else + { + prim.BSShape = new BulletShape(Hulls[shapeData.MeshKey].Ptr, + ShapeData.PhysicsShapeType.SHAPE_MESH); + prim.BSShape.shapeKey = shapeData.MeshKey; + ReferenceShape(prim.BSShape); + ret = true; + } } } return ret; } - private BulletShape AddNativeShapeToPrim(BSPrim prim, ShapeData shapeData, ShapeData.PhysicsShapeType shapeType) + // Creates a native shape and assignes it to prim.BSShape + private BulletShape AddNativeShapeToPrim( + BSPrim prim, ShapeData shapeData, ShapeData.PhysicsShapeType shapeType, + ShapeData.FixedShapeKey shapeKey) { BulletShape newShape; // Bullet native objects are scaled by the Bullet engine so pass the size in prim.Scale = shapeData.Size; + shapeData.Type = shapeType; + shapeData.Scale = prim.Scale; // release any previous shape - DereferenceShape(prim.BSShape); + DereferenceShape(prim.BSShape, true); + + // Shape of this discriptioin is not allocated. Create new. + newShape = new BulletShape( + BulletSimAPI.BuildNativeShape2(PhysicsScene.World.ptr, shapeData), shapeType); + newShape.shapeKey = (ulong)shapeKey; + newShape.isNativeShape = true; + + // Don't to a 'ReferenceShape()' here because native shapes are not tracked. - MeshDesc existingShapeDesc; - if (Meshes.TryGetValue(shapeData.MeshKey, out existingShapeDesc)) - { - // If there is an existing allocated shape, use it - newShape = new BulletShape(existingShapeDesc.Ptr, shapeType); - } - else - { - // Shape of this discriptioin is not allocated. Create new. - newShape = new BulletShape( - BulletSimAPI.BuildNativeShape2(PhysicsScene.World.Ptr, - (float)shapeType, - PhysicsScene.Params.collisionMargin, - prim.Scale), - shapeType); - } - newShape.shapeKey = shapeData.MeshKey; - ReferenceShape(newShape); prim.BSShape = newShape; return newShape; } - // No locking here because this is done when we know physics is not simulating - // Returns 'true' of a mesh was actually rebuild (we could also have one of these specs). + // Returns 'true' of a mesh was actually rebuild. // Called at taint-time! private bool CreateGeomMesh(BSPrim prim, ShapeData shapeData, PrimitiveBaseShape pbs) { @@ -322,7 +450,6 @@ public class BSShapeCollection : IDisposable lod = PhysicsScene.MeshMegaPrimLOD; ulong newMeshKey = (ulong)pbs.GetMeshKey(shapeData.Size, lod); - // m_log.DebugFormat("{0}: CreateGeomMesh: lID={1}, oldKey={2}, newKey={3}", LogHeader, LocalID, _meshKey, newMeshKey); // if this new shape is the same as last time, don't recreate the mesh if (prim.BSShape.shapeKey == newMeshKey) return false; @@ -330,7 +457,7 @@ public class BSShapeCollection : IDisposable DetailLog("{0},BSShapeCollection.CreateGeomMesh,create,key={1}", prim.LocalID, newMeshKey); // Since we're recreating new, get rid of the reference to the previous shape - DereferenceShape(prim.BSShape); + DereferenceShape(prim.BSShape, true); IMesh meshData = null; IntPtr meshPtr; @@ -360,7 +487,7 @@ public class BSShapeCollection : IDisposable // m_log.DebugFormat("{0}: CreateGeomMesh: calling CreateMesh. lid={1}, key={2}, indices={3}, vertices={4}", // LogHeader, prim.LocalID, newMeshKey, indices.Length, vertices.Count); - meshPtr = BulletSimAPI.CreateMeshShape2(PhysicsScene.World.Ptr, + meshPtr = BulletSimAPI.CreateMeshShape2(PhysicsScene.World.ptr, indices.GetLength(0), indices, vertices.Count, verticesAsFloats); } newShape = new BulletShape(meshPtr, ShapeData.PhysicsShapeType.SHAPE_MESH); @@ -374,26 +501,29 @@ public class BSShapeCollection : IDisposable return true; // 'true' means a new shape has been added to this prim } - // No locking here because this is done when we know physics is not simulating // Returns 'true' of a mesh was actually rebuild (we could also have one of these specs). List m_hulls; private bool CreateGeomHull(BSPrim prim, ShapeData shapeData, PrimitiveBaseShape pbs) { BulletShape newShape; + // Level of detail for the mesh can be different for sculpties and regular meshes. float lod = pbs.SculptEntry ? PhysicsScene.SculptLOD : PhysicsScene.MeshLOD; + ulong newHullKey = (ulong)pbs.GetMeshKey(shapeData.Size, lod); - // m_log.DebugFormat("{0}: CreateGeomHull: lID={1}, oldKey={2}, newKey={3}", LogHeader, LocalID, _hullKey, newHullKey); // if the hull hasn't changed, don't rebuild it if (newHullKey == prim.BSShape.shapeKey) return false; DetailLog("{0},BSShapeCollection.CreateGeomHull,create,oldKey={1},newKey={2}", prim.LocalID, newHullKey, newHullKey); - // remove references to any previous shape - DereferenceShape(prim.BSShape); + // Remove references to the previous shape. Also removes reference to underlying mesh. + DereferenceShape(prim.BSShape, true); - // Make sure the underlying mesh exists and is correct + // Do not let the mesh dereference itself again. Was done in the above DerefereceShape(). + prim.BSShape.type = ShapeData.PhysicsShapeType.SHAPE_UNKNOWN; + + // Make sure the underlying mesh exists and is correct. // Since we're in the hull code, we know CreateGeomMesh() will not create a native shape. CreateGeomMesh(prim, shapeData, pbs); MeshDesc meshDesc = Meshes[newHullKey]; @@ -402,10 +532,12 @@ public class BSShapeCollection : IDisposable HullDesc hullDesc; if (Hulls.TryGetValue(newHullKey, out hullDesc)) { + // If the hull shape already is created, just use it. hullPtr = hullDesc.Ptr; } else { + // Build a new hull in the physical world int[] indices = meshDesc.meshData.getIndexListAsInt(); List vertices = meshDesc.meshData.getVertexList(); @@ -485,63 +617,85 @@ public class BSShapeCollection : IDisposable } // create the hull data structure in Bullet // m_log.DebugFormat("{0}: CreateGeom: calling CreateHull. lid={1}, key={2}, hulls={3}", LogHeader, LocalID, _hullKey, hullCount); - hullPtr = BulletSimAPI.CreateHullShape2(PhysicsScene.World.Ptr, hullCount, convHulls); + hullPtr = BulletSimAPI.CreateHullShape2(PhysicsScene.World.ptr, hullCount, convHulls); } + newShape = new BulletShape(hullPtr, ShapeData.PhysicsShapeType.SHAPE_HULL); newShape.shapeKey = newHullKey; + newShape.meshPtr = meshDesc.Ptr; ReferenceShape(newShape); - // meshes are already scaled by the meshmerizer + // meshes and hulls are already scaled by the meshmerizer prim.Scale = new OMV.Vector3(1f, 1f, 1f); prim.BSShape = newShape; return true; // 'true' means a new shape has been added to this prim } // Callback from convex hull creater with a newly created hull. - // Just add it to the collection of hulls for this shape. + // Just add it to our collection of hulls for this shape. private void HullReturn(ConvexResult result) { m_hulls.Add(result); return; } - // Create an object in Bullet if it has not already been created - // No locking here because this is done when the physics engine is not simulating + // Create an object in Bullet if it has not already been created. + // Updates prim.BSBody with the information about the new body if one is created. // Returns 'true' if an object was actually created. - private bool CreateObject(bool forceRebuild, BSPrim prim, BulletSim sim, BulletShape shape, ShapeData shapeData) + // Called at taint-time. + private bool CreateBody(bool forceRebuild, BSPrim prim, BulletSim sim, BulletShape shape, ShapeData shapeData) { - // the mesh or hull must have already been created in Bullet - // m_log.DebugFormat("{0}: CreateObject: lID={1}, shape={2}", LogHeader, LocalID, shape.Type); + bool ret = false; - DereferenceBody(prim.BSBody); + // the mesh, hull or native shape must have already been created in Bullet + bool mustRebuild = (prim.BSBody.ptr == IntPtr.Zero); - BulletBody aBody; - IntPtr bodyPtr = IntPtr.Zero; - if (prim.IsSolid) + // If there is an existing body, verify it's of an acceptable type. + // If not a solid object, body is a GhostObject. Otherwise a RigidBody. + if (!mustRebuild) { - bodyPtr = BulletSimAPI.CreateBodyFromShape2(sim.Ptr, shape.Ptr, shapeData.Position, shapeData.Rotation); + CollisionObjectTypes bodyType = (CollisionObjectTypes)BulletSimAPI.GetBodyType2(prim.BSBody.ptr); + if (prim.IsSolid && bodyType != CollisionObjectTypes.CO_RIGID_BODY + || !prim.IsSolid && bodyType != CollisionObjectTypes.CO_GHOST_OBJECT) + { + // If the collisionObject is not the correct type for solidness, rebuild what's there + mustRebuild = true; + } + } - else + + if (mustRebuild) { - bodyPtr = BulletSimAPI.CreateGhostFromShape2(sim.Ptr, shape.Ptr, shapeData.Position, shapeData.Rotation); - } - aBody = new BulletBody(shapeData.ID, bodyPtr); + DereferenceBody(prim.BSBody, true); + + BulletBody aBody; + IntPtr bodyPtr = IntPtr.Zero; + if (prim.IsSolid) + { + bodyPtr = BulletSimAPI.CreateBodyFromShape2(sim.ptr, shape.ptr, shapeData.Position, shapeData.Rotation); + DetailLog("{0},BSShapeCollection.CreateObject,mesh,ptr={1:X}", prim.LocalID, bodyPtr); + } + else + { + bodyPtr = BulletSimAPI.CreateGhostFromShape2(sim.ptr, shape.ptr, shapeData.Position, shapeData.Rotation); + DetailLog("{0},BSShapeCollection.CreateObject,ghost,ptr={1:X}", prim.LocalID, bodyPtr); + } + aBody = new BulletBody(shapeData.ID, bodyPtr); + + ReferenceBody(aBody, true); + + prim.BSBody = aBody; - ReferenceBody(aBody); + ret = true; + } - prim.BSBody = aBody; - return true; + return ret; } private void DetailLog(string msg, params Object[] args) { PhysicsScene.PhysicsLogging.Write(msg, args); } - - - - - } } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs index fb802e4..093d2a4 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs @@ -111,8 +111,8 @@ public class BSTerrainManager BulletSimAPI.CreateGroundPlaneShape2(BSScene.GROUNDPLANE_ID, 1f, TERRAIN_COLLISION_MARGIN), ShapeData.PhysicsShapeType.SHAPE_GROUNDPLANE); m_groundPlane = new BulletBody(BSScene.GROUNDPLANE_ID, - BulletSimAPI.CreateBodyWithDefaultMotionState2(groundPlaneShape.Ptr, Vector3.Zero, Quaternion.Identity)); - BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.Ptr, m_groundPlane.Ptr); + BulletSimAPI.CreateBodyWithDefaultMotionState2(groundPlaneShape.ptr, Vector3.Zero, Quaternion.Identity)); + BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, m_groundPlane.ptr); Vector3 minTerrainCoords = new Vector3(0f, 0f, HEIGHT_INITIALIZATION - HEIGHT_EQUAL_FUDGE); Vector3 maxTerrainCoords = new Vector3(DefaultRegionSize.X, DefaultRegionSize.Y, HEIGHT_INITIALIZATION); @@ -128,13 +128,13 @@ public class BSTerrainManager // Release all the terrain structures we might have allocated public void ReleaseGroundPlaneAndTerrain() { - if (m_groundPlane.Ptr != IntPtr.Zero) + if (m_groundPlane.ptr != IntPtr.Zero) { - if (BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.Ptr, m_groundPlane.Ptr)) + if (BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, m_groundPlane.ptr)) { - BulletSimAPI.DestroyObject2(PhysicsScene.World.Ptr, m_groundPlane.Ptr); + BulletSimAPI.DestroyObject2(PhysicsScene.World.ptr, m_groundPlane.ptr); } - m_groundPlane.Ptr = IntPtr.Zero; + m_groundPlane.ptr = IntPtr.Zero; } ReleaseTerrain(); @@ -145,9 +145,9 @@ public class BSTerrainManager { foreach (KeyValuePair kvp in m_heightMaps) { - if (BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.Ptr, kvp.Value.terrainBody.Ptr)) + if (BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, kvp.Value.terrainBody.ptr)) { - BulletSimAPI.DestroyObject2(PhysicsScene.World.Ptr, kvp.Value.terrainBody.Ptr); + BulletSimAPI.DestroyObject2(PhysicsScene.World.ptr, kvp.Value.terrainBody.ptr); BulletSimAPI.ReleaseHeightMapInfo2(kvp.Value.Ptr); } } @@ -248,17 +248,17 @@ public class BSTerrainManager return; } - if (mapInfo.terrainBody.Ptr != IntPtr.Zero) + if (mapInfo.terrainBody.ptr != IntPtr.Zero) { // Updating an existing terrain. DetailLog("{0},UpdateOrCreateTerrain:UpdateExisting,taint,terrainBase={1},minC={2}, maxC={3}, szX={4}, szY={5}", BSScene.DetailLogZero, terrainRegionBase, mapInfo.minCoords, mapInfo.maxCoords, mapInfo.sizeX, mapInfo.sizeY); // Remove from the dynamics world because we're going to mangle this object - BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.Ptr, mapInfo.terrainBody.Ptr); + BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, mapInfo.terrainBody.ptr); // Get rid of the old terrain - BulletSimAPI.DestroyObject2(PhysicsScene.World.Ptr, mapInfo.terrainBody.Ptr); + BulletSimAPI.DestroyObject2(PhysicsScene.World.ptr, mapInfo.terrainBody.ptr); BulletSimAPI.ReleaseHeightMapInfo2(mapInfo.Ptr); mapInfo.Ptr = IntPtr.Zero; @@ -289,7 +289,7 @@ public class BSTerrainManager BSScene.DetailLogZero, mapInfo.minCoords.X, mapInfo.minCoords.Y, minZ, maxZ); mapInfo.ID = id; - mapInfo.Ptr = BulletSimAPI.CreateHeightMapInfo2(PhysicsScene.World.Ptr, mapInfo.ID, + mapInfo.Ptr = BulletSimAPI.CreateHeightMapInfo2(PhysicsScene.World.ptr, mapInfo.ID, mapInfo.minCoords, mapInfo.maxCoords, mapInfo.heightMap, TERRAIN_COLLISION_MARGIN); // The terrain object initial position is at the center of the object @@ -303,7 +303,7 @@ public class BSTerrainManager ShapeData.PhysicsShapeType.SHAPE_TERRAIN); mapInfo.terrainBody = new BulletBody(mapInfo.ID, - BulletSimAPI.CreateBodyWithDefaultMotionState2(mapInfo.terrainShape.Ptr, + BulletSimAPI.CreateBodyWithDefaultMotionState2(mapInfo.terrainShape.ptr, centerPos, Quaternion.Identity)); } @@ -311,22 +311,22 @@ public class BSTerrainManager m_heightMaps[terrainRegionBase] = mapInfo; // Set current terrain attributes - BulletSimAPI.SetFriction2(mapInfo.terrainBody.Ptr, PhysicsScene.Params.terrainFriction); - BulletSimAPI.SetHitFraction2(mapInfo.terrainBody.Ptr, PhysicsScene.Params.terrainHitFraction); - BulletSimAPI.SetRestitution2(mapInfo.terrainBody.Ptr, PhysicsScene.Params.terrainRestitution); - BulletSimAPI.SetCollisionFlags2(mapInfo.terrainBody.Ptr, CollisionFlags.CF_STATIC_OBJECT); + BulletSimAPI.SetFriction2(mapInfo.terrainBody.ptr, PhysicsScene.Params.terrainFriction); + BulletSimAPI.SetHitFraction2(mapInfo.terrainBody.ptr, PhysicsScene.Params.terrainHitFraction); + BulletSimAPI.SetRestitution2(mapInfo.terrainBody.ptr, PhysicsScene.Params.terrainRestitution); + BulletSimAPI.SetCollisionFlags2(mapInfo.terrainBody.ptr, CollisionFlags.CF_STATIC_OBJECT); - BulletSimAPI.SetMassProps2(mapInfo.terrainBody.Ptr, 0f, Vector3.Zero); - BulletSimAPI.UpdateInertiaTensor2(mapInfo.terrainBody.Ptr); + BulletSimAPI.SetMassProps2(mapInfo.terrainBody.ptr, 0f, Vector3.Zero); + BulletSimAPI.UpdateInertiaTensor2(mapInfo.terrainBody.ptr); // Return the new terrain to the world of physical objects - BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.Ptr, mapInfo.terrainBody.Ptr); + BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, mapInfo.terrainBody.ptr); // redo its bounding box now that it is in the world - BulletSimAPI.UpdateSingleAabb2(PhysicsScene.World.Ptr, mapInfo.terrainBody.Ptr); + BulletSimAPI.UpdateSingleAabb2(PhysicsScene.World.ptr, mapInfo.terrainBody.ptr); // Make sure the new shape is processed. - BulletSimAPI.Activate2(mapInfo.terrainBody.Ptr, true); + BulletSimAPI.Activate2(mapInfo.terrainBody.ptr, true); m_terrainModified = true; }; @@ -361,7 +361,7 @@ public class BSTerrainManager DetailLog("{0},UpdateOrCreateTerrain:NewTerrain,taint,baseX={1},baseY={2}", BSScene.DetailLogZero, minCoords.X, minCoords.Y); // Create a new mapInfo that will be filled with the new info mapInfo = new BulletHeightMapInfo(id, heightMapX, - BulletSimAPI.CreateHeightMapInfo2(PhysicsScene.World.Ptr, newTerrainID, + BulletSimAPI.CreateHeightMapInfo2(PhysicsScene.World.ptr, newTerrainID, minCoordsX, maxCoordsX, heightMapX, TERRAIN_COLLISION_MARGIN)); // Put the unfilled heightmap info into the collection of same m_heightMaps.Add(terrainRegionBase, mapInfo); diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs index 47875b0..8480dd1 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs @@ -40,14 +40,14 @@ public struct BulletSim { public BulletSim(uint worldId, BSScene bss, IntPtr xx) { + ptr = xx; worldID = worldId; scene = bss; - Ptr = xx; } + public IntPtr ptr; public uint worldID; // The scene is only in here so very low level routines have a handle to print debug/error messages public BSScene scene; - public IntPtr Ptr; } // An allocated Bullet btRigidBody @@ -56,9 +56,9 @@ public struct BulletBody public BulletBody(uint id, IntPtr xx) { ID = id; - Ptr = xx; + ptr = xx; } - public IntPtr Ptr; + public IntPtr ptr; public uint ID; public override string ToString() { @@ -66,7 +66,7 @@ public struct BulletBody buff.Append(""); return buff.ToString(); } @@ -76,28 +76,39 @@ public struct BulletShape { public BulletShape(IntPtr xx) { - Ptr = xx; + ptr = xx; type=ShapeData.PhysicsShapeType.SHAPE_UNKNOWN; shapeKey = 0; + isNativeShape = false; + meshPtr = IntPtr.Zero; } public BulletShape(IntPtr xx, ShapeData.PhysicsShapeType typ) { - Ptr = xx; + ptr = xx; type = typ; shapeKey = 0; + isNativeShape = false; + meshPtr = IntPtr.Zero; } - public IntPtr Ptr; + public IntPtr ptr; public ShapeData.PhysicsShapeType type; public ulong shapeKey; + public bool isNativeShape; + // Hulls have an underlying mesh. A pointer to it is hidden here. + public IntPtr meshPtr; public override string ToString() { StringBuilder buff = new StringBuilder(); buff.Append(""); return buff.ToString(); } @@ -314,10 +325,10 @@ public enum CollisionFlags : uint CF_DISABLE_SPU_COLLISION_PROCESS = 1 << 6, // Following used by BulletSim to control collisions BS_SUBSCRIBE_COLLISION_EVENTS = 1 << 10, - BS_VOLUME_DETECT_OBJECT = 1 << 11, - BS_PHANTOM_OBJECT = 1 << 12, - BS_PHYSICAL_OBJECT = 1 << 13, - BS_TERRAIN_OBJECT = 1 << 14, + // BS_VOLUME_DETECT_OBJECT = 1 << 11, + // BS_PHANTOM_OBJECT = 1 << 12, + // BS_PHYSICAL_OBJECT = 1 << 13, + // BS_TERRAIN_OBJECT = 1 << 14, BS_NONE = 0, BS_ALL = 0xFFFFFFFF, @@ -326,9 +337,9 @@ public enum CollisionFlags : uint BS_ACTIVE = CF_STATIC_OBJECT | CF_KINEMATIC_OBJECT | CF_NO_CONTACT_RESPONSE - | BS_VOLUME_DETECT_OBJECT - | BS_PHANTOM_OBJECT - | BS_PHYSICAL_OBJECT, + // | BS_VOLUME_DETECT_OBJECT + // | BS_PHANTOM_OBJECT + // | BS_PHYSICAL_OBJECT, }; // Values for collisions groups and masks @@ -552,8 +563,7 @@ public static extern IntPtr CreateHullShape2(IntPtr world, public static extern IntPtr BuildHullShape2(IntPtr world, IntPtr meshShape); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern IntPtr BuildNativeShape2(IntPtr world, - float shapeType, float collisionMargin, Vector3 scale); +public static extern IntPtr BuildNativeShape2(IntPtr world, ShapeData shapeData); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern bool IsNativeShape2(IntPtr shape); @@ -568,6 +578,9 @@ public static extern void AddChildToCompoundShape2(IntPtr cShape, IntPtr addShap public static extern void RemoveChildFromCompoundShape2(IntPtr cShape, IntPtr removeShape); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern IntPtr DuplicateCollisionShape2(IntPtr sim, IntPtr srcShape, uint id); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern IntPtr CreateBodyFromShapeAndInfo2(IntPtr sim, IntPtr shape, IntPtr constructionInfo); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -- cgit v1.1 From 735d89e3692bb7c620b9e3c248a1dbd5924b8b3f Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Tue, 25 Sep 2012 15:01:18 -0700 Subject: BulletSim: btGhostObjects working to make 'volume detect' work. Rearrangement and cleanup of shape collection code. Much more readable. Enabling and use of collision filters and masks. Addition of ID to body creation BulletSimAPI calls so always set in shape for collision reporting. Change default of ShouldSplitSimulationIslands and ShouldRandomizeSolverOrder from 'false' to 'true'. When 'false', this suppresses NO_CONTACT_RESPONSE which makes volume detect fail. --- .../Region/Physics/BulletSPlugin/BSCharacter.cs | 10 +- .../Region/Physics/BulletSPlugin/BSPhysObject.cs | 8 +- OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | 28 +- OpenSim/Region/Physics/BulletSPlugin/BSScene.cs | 24 +- .../Physics/BulletSPlugin/BSShapeCollection.cs | 296 +++++++++++---------- .../Physics/BulletSPlugin/BSTerrainManager.cs | 12 +- .../Region/Physics/BulletSPlugin/BulletSimAPI.cs | 78 ++++-- 7 files changed, 265 insertions(+), 191 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs index e4b1dd4..961bcde 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs @@ -90,7 +90,8 @@ public class BSCharacter : BSPhysObject // Physics creates a unit capsule which is scaled by the physics engine. ComputeAvatarScale(_size); _avatarDensity = PhysicsScene.Params.avatarDensity; - ComputeAvatarVolumeAndMass(); // set _avatarVolume and _mass based on capsule size, _density and _scale + // set _avatarVolume and _mass based on capsule size, _density and _scale + ComputeAvatarVolumeAndMass(); ShapeData shapeData = new ShapeData(); shapeData.ID = LocalID; @@ -111,10 +112,15 @@ public class BSCharacter : BSPhysObject DetailLog("{0},BSCharacter.create,taint", LocalID); BulletSimAPI.CreateObject(PhysicsScene.WorldID, shapeData); - // Set the buoyancy for flying. This will be refactored when all the settings happen in C# + // Set the buoyancy for flying. This will be refactored when all the settings happen in C#. + // If not set at creation, the avatar will stop flying when created after crossing a region boundry. BulletSimAPI.SetObjectBuoyancy(PhysicsScene.WorldID, LocalID, _buoyancy); BSBody = new BulletBody(LocalID, BulletSimAPI.GetBodyHandle2(PhysicsScene.World.ptr, LocalID)); + + // This works here because CreateObject has already put the character into the physical world. + BulletSimAPI.SetCollisionFilterMask2(BSBody.ptr, + (uint)CollisionFilterGroups.AvatarFilter, (uint)CollisionFilterGroups.AvatarMask); }); return; diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs index 6a9fe50..3458477 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs @@ -123,6 +123,7 @@ public abstract class BSPhysObject : PhysicsActor CollisionCollection.AddCollider(collidingWith, new ContactPoint(contactPoint, contactNormal, pentrationDepth)); DetailLog("{0},{1}.Collison.AddCollider,call,with={2},point={3},normal={4},depth={5}", LocalID, TypeName, collidingWith, contactPoint, contactNormal, pentrationDepth); + ret = true; } return ret; @@ -145,7 +146,10 @@ public abstract class BSPhysObject : PhysicsActor // We are called if we previously had collisions. If there are no collisions // this time, send up one last empty event so OpenSim can sense collision end. if (CollisionCollection.Count == 0) + { + // If I have no collisions this time, remove me from the list of objects with collisions. PhysicsScene.ObjectsWithNoMoreCollisions.Add(this); + } DetailLog("{0},{1}.SendCollisionUpdate,call,numCollisions={2}", LocalID, TypeName, CollisionCollection.Count); base.SendCollisionUpdate(CollisionCollection); @@ -159,7 +163,7 @@ public abstract class BSPhysObject : PhysicsActor // Subscribe for collision events. // Parameter is the millisecond rate the caller wishes collision events to occur. public override void SubscribeEvents(int ms) { - DetailLog("{0},BSScene.SubscribeEvents,subscribing,ms={1}", BSScene.DetailLogZero, ms); + DetailLog("{0},{1}.SubscribeEvents,subscribing,ms={2}", LocalID, TypeName, ms); SubscribedEventsMs = ms; if (ms > 0) { @@ -178,7 +182,7 @@ public abstract class BSPhysObject : PhysicsActor } } public override void UnSubscribeEvents() { - DetailLog("{0},BSScene.UnSubscribeEvents,unsubscribing", BSScene.DetailLogZero); + DetailLog("{0},{1}.UnSubscribeEvents,unsubscribing", LocalID, TypeName); SubscribedEventsMs = 0; PhysicsScene.TaintedObject(TypeName+".UnSubscribeEvents", delegate() { diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index 5be2b1b..1c6d476 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs @@ -271,7 +271,7 @@ public sealed class BSPrim : BSPhysObject _position = BulletSimAPI.GetPosition2(BSBody.ptr); // don't do the GetObjectPosition for root elements because this function is called a zillion times - // _position = BulletSimAPI.GetObjectPosition(Scene.WorldID, LocalID); + // _position = BulletSimAPI.GetObjectPosition2(PhysicsScene.World.ptr, BSBody.ptr); return _position; } set { @@ -432,7 +432,7 @@ public sealed class BSPrim : BSPhysObject // TODO: what does it mean if a child in a linkset changes its orientation? Rebuild the constraint? PhysicsScene.TaintedObject("BSPrim.setOrientation", delegate() { - // _position = BulletSimAPI.GetObjectPosition(Scene.WorldID, LocalID); + // _position = BulletSimAPI.GetObjectPosition2(PhysicsScene.World.ptr, BSBody.ptr); DetailLog("{0},BSPrim.setOrientation,taint,pos={1},orient={2}", LocalID, _position, _orientation); BulletSimAPI.SetTranslation2(BSBody.ptr, _position, _orientation); }); @@ -492,7 +492,8 @@ public sealed class BSPrim : BSPhysObject { DetailLog("{0},BSPrim.UpdatePhysicalParameters,entry,body={1},shape={2}", LocalID, BSBody, BSShape); - // Mangling all the physical properties requires the object to be out of the physical world + // Mangling all the physical properties requires the object to be out of the physical world. + // This is a NOOP if the object is not in the world (BulletSim and Bullet ignore objects not found). BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, BSBody.ptr); #if !CSHARP_BODY_MANAGEMENT @@ -517,6 +518,14 @@ public sealed class BSPrim : BSPhysObject // Rebuild its shape BulletSimAPI.UpdateSingleAabb2(PhysicsScene.World.ptr, BSBody.ptr); + // Collision filter can be set only when the object is in the world + if (BSBody.collisionFilter != 0 || BSBody.collisionMask != 0) + { + BulletSimAPI.SetCollisionFilterMask2(BSBody.ptr, (uint)BSBody.collisionFilter, (uint)BSBody.collisionMask); + DetailLog("{0},BSPrim.UpdatePhysicalParameters,setCollisionFilterMask,filter={1},mask={2}", + LocalID, BSBody.collisionFilter.ToString("X"), BSBody.collisionMask.ToString("X")); + } + // Recompute any linkset parameters. // When going from non-physical to physical, this re-enables the constraints that // had been automatically disabled when the mass was set to zero. @@ -548,8 +557,11 @@ public sealed class BSPrim : BSPhysObject // There can be special things needed for implementing linksets Linkset.MakeStatic(this); // The activation state is 'sleeping' so Bullet will not try to act on it - BulletSimAPI.ForceActivationState2(BSBody.ptr, ActivationState.ISLAND_SLEEPING); - // BulletSimAPI.ForceActivationState2(BSBody.Ptr, ActivationState.DISABLE_SIMULATION); + // BulletSimAPI.ForceActivationState2(BSBody.ptr, ActivationState.ISLAND_SLEEPING); + BulletSimAPI.ForceActivationState2(BSBody.ptr, ActivationState.DISABLE_SIMULATION); + + BSBody.collisionFilter = CollisionFilterGroups.StaticObjectFilter; + BSBody.collisionMask = CollisionFilterGroups.StaticObjectMask; } else { @@ -582,6 +594,9 @@ public sealed class BSPrim : BSPhysObject // Force activation of the object so Bullet will act on it. BulletSimAPI.Activate2(BSBody.ptr, true); + + BSBody.collisionFilter = CollisionFilterGroups.ObjectFilter; + BSBody.collisionMask = CollisionFilterGroups.ObjectMask; } } @@ -609,6 +624,8 @@ public sealed class BSPrim : BSPhysObject m_log.ErrorFormat("{0} MakeSolid: physical body of wrong type for non-solidness. id={1}, type={2}", LogHeader, LocalID, bodyType); } CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(BSBody.ptr, CollisionFlags.CF_NO_CONTACT_RESPONSE); + BSBody.collisionFilter = CollisionFilterGroups.VolumeDetectFilter; + BSBody.collisionMask = CollisionFilterGroups.VolumeDetectMask; } #else // If doing the body management in C#, all this logic is in CSShapeCollection.CreateObject(). @@ -745,7 +762,6 @@ public sealed class BSPrim : BSPhysObject // Buoyancy is faked by changing the gravity applied to the object float grav = PhysicsScene.Params.gravity * (1f - _buoyancy); BulletSimAPI.SetGravity2(BSBody.ptr, new OMV.Vector3(0f, 0f, grav)); - // BulletSimAPI.SetObjectBuoyancy(Scene.WorldID, LocalID, _buoyancy); }); } } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs index 87c7b1b..e8c628c 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs @@ -39,20 +39,20 @@ using log4net; using OpenMetaverse; // TODOs for BulletSim (for BSScene, BSPrim, BSCharacter and BulletSim) -// Adjust character capsule size when height is adjusted (ScenePresence.SetHeight) -// Test sculpties +// Move all logic out of the C++ code and into the C# code for easier future modifications. +// Test sculpties (verified that they don't work) // Compute physics FPS reasonably // Based on material, set density and friction -// More efficient memory usage when passing hull information from BSPrim to BulletSim -// Move all logic out of the C++ code and into the C# code for easier future modifications. +// Don't use constraints in linksets of non-physical objects. Means having to move children manually. // Four states of prim: Physical, regular, phantom and selected. Are we modeling these correctly? // In SL one can set both physical and phantom (gravity, does not effect others, makes collisions with ground) // At the moment, physical and phantom causes object to drop through the terrain // Physical phantom objects and related typing (collision options ) -// Use collision masks for collision with terrain and phantom objects // Check out llVolumeDetect. Must do something for that. +// Use collision masks for collision with terrain and phantom objects +// More efficient memory usage when passing hull information from BSPrim to BulletSim // Should prim.link() and prim.delink() membership checking happen at taint time? -// Mesh sharing. Use meshHash to tell if we already have a hull of that shape and only create once +// Mesh sharing. Use meshHash to tell if we already have a hull of that shape and only create once. // Do attachments need to be handled separately? Need collision events. Do not collide with VolumeDetect // Implement LockAngularMotion // Decide if clearing forces is the right thing to do when setting position (BulletSim::SetObjectTranslation) @@ -356,6 +356,12 @@ public class BSScene : PhysicsScene, IPhysicsParameters Constraints = null; } + if (Shapes != null) + { + Shapes.Dispose(); + Shapes = null; + } + // Anything left in the unmanaged code should be cleaned out BulletSimAPI.Shutdown(WorldID); @@ -589,7 +595,6 @@ public class BSScene : PhysicsScene, IPhysicsParameters { if (localID <= TerrainManager.HighestTerrainID) { - DetailLog("{0},BSScene.SendCollision,collideWithTerrain,id={1},with={2}", DetailLogZero, localID, collidingWith); return; // don't send collisions to the terrain } @@ -601,8 +606,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters return; } - // The terrain is not in the physical object list so 'collidee' - // can be null when Collide() is called. + // The terrain is not in the physical object list so 'collidee' can be null when Collide() is called. BSPhysObject collidee = null; PhysObjects.TryGetValue(collidingWith, out collidee); @@ -1026,7 +1030,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters (s) => { return s.m_params[0].shouldRandomizeSolverOrder; }, (s,p,l,v) => { s.m_params[0].shouldRandomizeSolverOrder = v; } ), new ParameterDefn("ShouldSplitSimulationIslands", "Enable splitting active object scanning islands", - ConfigurationParameters.numericFalse, + ConfigurationParameters.numericTrue, (s,cf,p,v) => { s.m_params[0].shouldSplitSimulationIslands = s.NumericBool(cf.GetBoolean(p, s.BoolNumeric(v))); }, (s) => { return s.m_params[0].shouldSplitSimulationIslands; }, (s,p,l,v) => { s.m_params[0].shouldSplitSimulationIslands = v; } ), diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs index 6b90661..7fce8c9 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs @@ -36,6 +36,8 @@ namespace OpenSim.Region.Physics.BulletSPlugin { public class BSShapeCollection : IDisposable { + private static string LogHeader = "[BULLETSIM SHAPE COLLECTION]"; + protected BSScene PhysicsScene { get; set; } private Object m_collectionActivityLock = new Object(); @@ -43,24 +45,23 @@ public class BSShapeCollection : IDisposable // Description of a Mesh private struct MeshDesc { - public IntPtr Ptr; + public IntPtr ptr; public int referenceCount; public DateTime lastReferenced; - public IMesh meshData; } // Description of a hull. // Meshes and hulls have the same shape hash key but we only need hulls for efficient physical objects private struct HullDesc { - public IntPtr Ptr; + public IntPtr ptr; public int referenceCount; public DateTime lastReferenced; } private struct BodyDesc { - public IntPtr Ptr; + public IntPtr ptr; // Bodies are only used once so reference count is always either one or zero public int referenceCount; public DateTime lastReferenced; @@ -93,14 +94,16 @@ public class BSShapeCollection : IDisposable lock (m_collectionActivityLock) { // Do we have the correct geometry for this type of object? + // Updates prim.BSShape with information/pointers to requested shape bool newGeom = CreateGeom(forceRebuild, prim, shapeData, pbs); // If we had to select a new shape geometry for the object, // rebuild the body around it. + // Updates prim.BSBody with information/pointers to requested body bool newBody = CreateBody((newGeom || forceRebuild), prim, PhysicsScene.World, prim.BSShape, shapeData); ret = newGeom || newBody; } - DetailLog("{0},BSShapeCollection.GetBodyAndShape,force-{1},ret={2},body={3},shape={4}", - prim.LocalID, forceRebuild, ret, prim.BSBody, prim.BSShape); + DetailLog("{0},BSShapeCollection.GetBodyAndShape,force={1},ret={2},body={3},shape={4}", + prim.LocalID, forceRebuild, ret, prim.BSBody, prim.BSShape); return ret; } @@ -120,7 +123,8 @@ public class BSShapeCollection : IDisposable } else { - bodyDesc.Ptr = shape.ptr; + // New entry + bodyDesc.ptr = shape.ptr; bodyDesc.referenceCount = 1; DetailLog("{0},BSShapeCollection.ReferenceBody,newBody,ref={1}", shape.ID, bodyDesc.referenceCount); } @@ -130,7 +134,7 @@ public class BSShapeCollection : IDisposable } // Release the usage of a body. - // Not that this will also delete the body in BUllet if the body is now unused (reference count = 0). + // Called when releasing use of a BSBody. BSShape is handled separately. public void DereferenceBody(BulletBody shape, bool inTaintTime) { if (shape.ptr == IntPtr.Zero) @@ -146,15 +150,17 @@ public class BSShapeCollection : IDisposable Bodies[shape.ID] = bodyDesc; DetailLog("{0},BSShapeCollection.DereferenceBody,ref={1}", shape.ID, bodyDesc.referenceCount); + // If body is no longer being used, free it -- bodies are never shared. if (bodyDesc.referenceCount == 0) { Bodies.Remove(shape.ID); BSScene.TaintCallback removeOperation = delegate() { - DetailLog("{0},BSShapeCollection.DereferenceBody,DestroyingBody. Ptr={1:X}", shape.ID, shape.ptr); - // zero any reference to the shape so it is not freed when the body is deleted + DetailLog("{0},BSShapeCollection.DereferenceBody,DestroyingBody. ptr={1}", + shape.ID, shape.ptr.ToString("X")); + // Zero any reference to the shape so it is not freed when the body is deleted. BulletSimAPI.SetCollisionShape2(PhysicsScene.World.ptr, shape.ptr, IntPtr.Zero); - // It may have already been removed from the world in which case the next is a NOOP + // It may have already been removed from the world in which case the next is a NOOP. BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, shape.ptr); BulletSimAPI.DestroyObject2(PhysicsScene.World.ptr, shape.ptr); }; @@ -172,19 +178,13 @@ public class BSShapeCollection : IDisposable } } - // Track another user of the shape - private bool ReferenceShape(BulletShape shape) - { - return ReferenceShape(shape, null); - } - // Track the datastructures and use count for a shape. // When creating a hull, this is called first to reference the mesh // and then again to reference the hull. // Meshes and hulls for the same shape have the same hash key. // NOTE that native shapes are not added to the mesh list or removed. // Returns 'true' if this is the initial reference to the shape. Otherwise reused. - private bool ReferenceShape(BulletShape shape, IMesh meshData) + private bool ReferenceShape(BulletShape shape) { bool ret = false; switch (shape.type) @@ -196,16 +196,16 @@ public class BSShapeCollection : IDisposable // There is an existing instance of this mesh. meshDesc.referenceCount++; DetailLog("{0},BSShapeColliction.ReferenceShape,existingMesh,key={1},cnt={2}", - BSScene.DetailLogZero, shape.shapeKey, meshDesc.referenceCount); + BSScene.DetailLogZero, shape.shapeKey.ToString("X"), meshDesc.referenceCount); } else { // This is a new reference to a mesh - meshDesc.Ptr = shape.ptr; - meshDesc.meshData = meshData; + meshDesc.ptr = shape.ptr; + // We keep a reference to the underlying IMesh data so a hull can be built meshDesc.referenceCount = 1; DetailLog("{0},BSShapeColliction.ReferenceShape,newMesh,key={1},cnt={2}", - BSScene.DetailLogZero, shape.shapeKey, meshDesc.referenceCount); + BSScene.DetailLogZero, shape.shapeKey.ToString("X"), meshDesc.referenceCount); ret = true; } meshDesc.lastReferenced = System.DateTime.Now; @@ -215,18 +215,18 @@ public class BSShapeCollection : IDisposable HullDesc hullDesc; if (Hulls.TryGetValue(shape.shapeKey, out hullDesc)) { - // There is an existing instance of this mesh. + // There is an existing instance of this hull. hullDesc.referenceCount++; DetailLog("{0},BSShapeColliction.ReferenceShape,existingHull,key={1},cnt={2}", - BSScene.DetailLogZero, shape.shapeKey, hullDesc.referenceCount); + BSScene.DetailLogZero, shape.shapeKey.ToString("X"), hullDesc.referenceCount); } else { // This is a new reference to a hull - hullDesc.Ptr = shape.ptr; + hullDesc.ptr = shape.ptr; hullDesc.referenceCount = 1; DetailLog("{0},BSShapeColliction.ReferenceShape,newHull,key={1},cnt={2}", - BSScene.DetailLogZero, shape.shapeKey, hullDesc.referenceCount); + BSScene.DetailLogZero, shape.shapeKey.ToString("X"), hullDesc.referenceCount); ret = true; } @@ -242,7 +242,8 @@ public class BSShapeCollection : IDisposable return ret; } - // Release the usage of a shape + // Release the usage of a shape. + // The collisionObject is released since it is a copy of the real collision shape. private void DereferenceShape(BulletShape shape, bool atTaintTime) { if (shape.ptr == IntPtr.Zero) @@ -254,8 +255,6 @@ public class BSShapeCollection : IDisposable { case ShapeData.PhysicsShapeType.SHAPE_HULL: DereferenceHull(shape); - // Hulls also include a mesh - DereferenceMesh(shape); break; case ShapeData.PhysicsShapeType.SHAPE_MESH: DereferenceMesh(shape); @@ -266,15 +265,24 @@ public class BSShapeCollection : IDisposable // Native shapes are not tracked and are released immediately if (shape.ptr != IntPtr.Zero & shape.isNativeShape) { + DetailLog("{0},BSShapeCollection.DereferenceShape,deleteNativeShape,ptr={1},taintTime={2}", + BSScene.DetailLogZero, shape.ptr.ToString("X"), atTaintTime); BulletSimAPI.DeleteCollisionShape2(PhysicsScene.World.ptr, shape.ptr); } break; } }; if (atTaintTime) - dereferenceOperation(); + { + lock (m_collectionActivityLock) + { + dereferenceOperation(); + } + } else + { PhysicsScene.TaintedObject("BSShapeCollection.DereferenceShape", dereferenceOperation); + } } // Count down the reference count for a mesh shape @@ -288,8 +296,8 @@ public class BSShapeCollection : IDisposable // TODO: release the Bullet storage meshDesc.lastReferenced = System.DateTime.Now; Meshes[shape.shapeKey] = meshDesc; - DetailLog("{0},BSShapeColliction.DereferenceMesh,key={1},cnt={2}", - BSScene.DetailLogZero, shape.shapeKey, meshDesc.referenceCount); + DetailLog("{0},BSShapeCollection.DereferenceMesh,key={1},refCnt={2}", + BSScene.DetailLogZero, shape.shapeKey.ToString("X"), meshDesc.referenceCount); } } @@ -305,8 +313,8 @@ public class BSShapeCollection : IDisposable // TODO: release the Bullet storage (aging old entries?) hullDesc.lastReferenced = System.DateTime.Now; Hulls[shape.shapeKey] = hullDesc; - DetailLog("{0},BSShapeColliction.DereferenceHull,key={1},cnt={2}", - BSScene.DetailLogZero, shape.shapeKey, hullDesc.referenceCount); + DetailLog("{0},BSShapeCollection.DereferenceHull,key={1},refCnt={2}", + BSScene.DetailLogZero, shape.shapeKey.ToString("X"), hullDesc.referenceCount); } } @@ -322,8 +330,6 @@ public class BSShapeCollection : IDisposable bool haveShape = false; bool nativeShapePossible = true; - BulletShape newShape = new BulletShape(IntPtr.Zero); - // If the prim attributes are simple, this could be a simple Bullet native shape if (nativeShapePossible && ((pbs.SculptEntry && !PhysicsScene.ShouldMeshSculptedPrim) @@ -340,137 +346,117 @@ public class BSShapeCollection : IDisposable haveShape = true; if (forceRebuild || (prim.BSShape.type != ShapeData.PhysicsShapeType.SHAPE_SPHERE)) { - newShape = AddNativeShapeToPrim( - prim, shapeData, ShapeData.PhysicsShapeType.SHAPE_SPHERE, ShapeData.FixedShapeKey.KEY_SPHERE); + ret = GetReferenceToNativeShape(prim, shapeData, + ShapeData.PhysicsShapeType.SHAPE_SPHERE, ShapeData.FixedShapeKey.KEY_SPHERE); DetailLog("{0},BSShapeCollection.CreateGeom,sphere,force={1},shape={2}", - prim.LocalID, forceRebuild,prim.BSShape); - - ret = true; + prim.LocalID, forceRebuild, prim.BSShape); } } else { - // m_log.DebugFormat("{0}: CreateGeom: Defaulting to box. lid={1}, type={2}, size={3}", LogHeader, LocalID, _shapeType, _size); haveShape = true; if (forceRebuild || (prim.BSShape.type != ShapeData.PhysicsShapeType.SHAPE_BOX)) { - newShape = AddNativeShapeToPrim( + ret = GetReferenceToNativeShape( prim, shapeData, ShapeData.PhysicsShapeType.SHAPE_BOX, ShapeData.FixedShapeKey.KEY_BOX); DetailLog("{0},BSShapeCollection.CreateGeom,box,force={1},shape={2}", - prim.LocalID, forceRebuild,prim.BSShape); - - ret = true; + prim.LocalID, forceRebuild, prim.BSShape); } } } - // If a simple shape is not happening, create a mesh and possibly a hull + // If a simple shape is not happening, create a mesh and possibly a hull. // Note that if it's a native shape, the check for physical/non-physical is not // made. Native shapes are best used in either case. if (!haveShape) { if (prim.IsPhysical) { - if (forceRebuild || !Hulls.ContainsKey(shapeData.HullKey)) - { - // physical objects require a hull for interaction. - // This also creates the mesh if it doesn't already exist. - ret = CreateGeomHull(prim, shapeData, pbs); - } - else - { - prim.BSShape = new BulletShape(Hulls[shapeData.HullKey].Ptr, - ShapeData.PhysicsShapeType.SHAPE_HULL); - prim.BSShape.shapeKey = shapeData.HullKey; - // Another user of this shape. - ReferenceShape(prim.BSShape); - ret = true; - } + // Update prim.BSShape to reference a hull of this shape. + ret = GetReferenceToHull(prim, shapeData, pbs); + DetailLog("{0},BSShapeCollection.CreateGeom,hull,shape={1},key={2}", + shapeData.ID, prim.BSShape, prim.BSShape.shapeKey.ToString("X")); } else { - if (forceRebuild || !Meshes.ContainsKey(prim.BSShape.shapeKey)) - { - // Static (non-physical) objects only need a mesh for bumping into - // Returning 'true' means prim.BShape was changed. - ret = CreateGeomMesh(prim, shapeData, pbs); - } - else - { - prim.BSShape = new BulletShape(Hulls[shapeData.MeshKey].Ptr, - ShapeData.PhysicsShapeType.SHAPE_MESH); - prim.BSShape.shapeKey = shapeData.MeshKey; - ReferenceShape(prim.BSShape); - ret = true; - } + ret = GetReferenceToMesh(prim, shapeData, pbs); + DetailLog("{0},BSShapeCollection.CreateGeom,mesh,shape={1},key={2}", + shapeData.ID, prim.BSShape, prim.BSShape.shapeKey.ToString("X")); } } return ret; } // Creates a native shape and assignes it to prim.BSShape - private BulletShape AddNativeShapeToPrim( - BSPrim prim, ShapeData shapeData, ShapeData.PhysicsShapeType shapeType, - ShapeData.FixedShapeKey shapeKey) + private bool GetReferenceToNativeShape( BSPrim prim, ShapeData shapeData, + ShapeData.PhysicsShapeType shapeType, ShapeData.FixedShapeKey shapeKey) { BulletShape newShape; + shapeData.Type = shapeType; // Bullet native objects are scaled by the Bullet engine so pass the size in prim.Scale = shapeData.Size; - shapeData.Type = shapeType; - shapeData.Scale = prim.Scale; + shapeData.Scale = shapeData.Size; // release any previous shape DereferenceShape(prim.BSShape, true); - // Shape of this discriptioin is not allocated. Create new. - newShape = new BulletShape( - BulletSimAPI.BuildNativeShape2(PhysicsScene.World.ptr, shapeData), shapeType); + // Native shapes are always built independently. + newShape = new BulletShape(BulletSimAPI.BuildNativeShape2(PhysicsScene.World.ptr, shapeData), shapeType); newShape.shapeKey = (ulong)shapeKey; newShape.isNativeShape = true; - // Don't to a 'ReferenceShape()' here because native shapes are not tracked. + // Don't need to do a 'ReferenceShape()' here because native shapes are not tracked. + DetailLog("{0},BSShapeCollection.AddNativeShapeToPrim,create,newshape={1}", shapeData.ID, newShape); prim.BSShape = newShape; - return newShape; + return true; } - // Returns 'true' of a mesh was actually rebuild. + // Builds a mesh shape in the physical world and updates prim.BSShape. + // Dereferences previous shape in BSShape and adds a reference for this new shape. + // Returns 'true' of a mesh was actually built. Otherwise . // Called at taint-time! - private bool CreateGeomMesh(BSPrim prim, ShapeData shapeData, PrimitiveBaseShape pbs) + private bool GetReferenceToMesh(BSPrim prim, ShapeData shapeData, PrimitiveBaseShape pbs) { BulletShape newShape = new BulletShape(IntPtr.Zero); - // level of detail based on size and type of the object - float lod = PhysicsScene.MeshLOD; - if (pbs.SculptEntry) - lod = PhysicsScene.SculptLOD; - - float maxAxis = Math.Max(shapeData.Size.X, Math.Max(shapeData.Size.Y, shapeData.Size.Z)); - if (maxAxis > PhysicsScene.MeshMegaPrimThreshold) - lod = PhysicsScene.MeshMegaPrimLOD; - - ulong newMeshKey = (ulong)pbs.GetMeshKey(shapeData.Size, lod); + float lod; + ulong newMeshKey = ComputeShapeKey(shapeData, pbs, out lod); // if this new shape is the same as last time, don't recreate the mesh if (prim.BSShape.shapeKey == newMeshKey) return false; - DetailLog("{0},BSShapeCollection.CreateGeomMesh,create,key={1}", prim.LocalID, newMeshKey); + DetailLog("{0},BSShapeCollection.CreateGeomMesh,create,oldKey={1},newKey={2}", + prim.LocalID, prim.BSShape.shapeKey.ToString("X"), newMeshKey.ToString("X")); // Since we're recreating new, get rid of the reference to the previous shape DereferenceShape(prim.BSShape, true); + newShape = CreatePhysicalMesh(prim.PhysObjectName, newMeshKey, pbs, shapeData.Size, lod); + + ReferenceShape(newShape); + + // meshes are already scaled by the meshmerizer + prim.Scale = new OMV.Vector3(1f, 1f, 1f); + prim.BSShape = newShape; + + return true; // 'true' means a new shape has been added to this prim + } + + private BulletShape CreatePhysicalMesh(string objName, ulong newMeshKey, PrimitiveBaseShape pbs, OMV.Vector3 size, float lod) + { IMesh meshData = null; IntPtr meshPtr; MeshDesc meshDesc; if (Meshes.TryGetValue(newMeshKey, out meshDesc)) { // If the mesh has already been built just use it. - meshPtr = meshDesc.Ptr; + meshPtr = meshDesc.ptr; } else { - // always pass false for physicalness as this creates some sort of bounding box which we don't need - meshData = PhysicsScene.mesher.CreateMesh(prim.PhysObjectName, pbs, shapeData.Size, lod, false); + // Pass false for physicalness as this creates some sort of bounding box which we don't need + meshData = PhysicsScene.mesher.CreateMesh(objName, pbs, size, lod, false); int[] indices = meshData.getIndexListAsInt(); List vertices = meshData.getVertexList(); @@ -490,56 +476,62 @@ public class BSShapeCollection : IDisposable meshPtr = BulletSimAPI.CreateMeshShape2(PhysicsScene.World.ptr, indices.GetLength(0), indices, vertices.Count, verticesAsFloats); } - newShape = new BulletShape(meshPtr, ShapeData.PhysicsShapeType.SHAPE_MESH); + BulletShape newShape = new BulletShape(meshPtr, ShapeData.PhysicsShapeType.SHAPE_MESH); newShape.shapeKey = newMeshKey; - ReferenceShape(newShape, meshData); - - // meshes are already scaled by the meshmerizer - prim.Scale = new OMV.Vector3(1f, 1f, 1f); - prim.BSShape = newShape; - return true; // 'true' means a new shape has been added to this prim + return newShape; } - // Returns 'true' of a mesh was actually rebuild (we could also have one of these specs). - List m_hulls; - private bool CreateGeomHull(BSPrim prim, ShapeData shapeData, PrimitiveBaseShape pbs) + // See that hull shape exists in the physical world and update prim.BSShape. + // We could be creating the hull because scale changed or whatever. + private bool GetReferenceToHull(BSPrim prim, ShapeData shapeData, PrimitiveBaseShape pbs) { BulletShape newShape; - // Level of detail for the mesh can be different for sculpties and regular meshes. - float lod = pbs.SculptEntry ? PhysicsScene.SculptLOD : PhysicsScene.MeshLOD; - - ulong newHullKey = (ulong)pbs.GetMeshKey(shapeData.Size, lod); + float lod; + ulong newHullKey = ComputeShapeKey(shapeData, pbs, out lod); // if the hull hasn't changed, don't rebuild it if (newHullKey == prim.BSShape.shapeKey) return false; - DetailLog("{0},BSShapeCollection.CreateGeomHull,create,oldKey={1},newKey={2}", prim.LocalID, newHullKey, newHullKey); + DetailLog("{0},BSShapeCollection.CreateGeomHull,create,oldKey={1},newKey={2}", + prim.LocalID, prim.BSShape.shapeKey.ToString("X"), newHullKey.ToString("X")); - // Remove references to the previous shape. Also removes reference to underlying mesh. + // Remove usage of the previous shape. Also removes reference to underlying mesh if it is a hull. DereferenceShape(prim.BSShape, true); - // Do not let the mesh dereference itself again. Was done in the above DerefereceShape(). - prim.BSShape.type = ShapeData.PhysicsShapeType.SHAPE_UNKNOWN; - - // Make sure the underlying mesh exists and is correct. - // Since we're in the hull code, we know CreateGeomMesh() will not create a native shape. - CreateGeomMesh(prim, shapeData, pbs); - MeshDesc meshDesc = Meshes[newHullKey]; + newShape = CreatePhysicalHull(prim.PhysObjectName, newHullKey, pbs, shapeData.Size, lod); + + if (!ReferenceShape(newShape)) + { + PhysicsScene.Logger.ErrorFormat("{0} Created new hull shape but one already exists: id={1}, key={2}, refCnt={3}", + LogHeader, shapeData.ID, newHullKey.ToString("X"), Hulls[newHullKey].referenceCount); + } + // hulls are already scaled by the meshmerizer + prim.Scale = new OMV.Vector3(1f, 1f, 1f); + prim.BSShape = newShape; + return true; // 'true' means a new shape has been added to this prim + } + + List m_hulls; + private BulletShape CreatePhysicalHull(string objName, ulong newHullKey, PrimitiveBaseShape pbs, OMV.Vector3 size, float lod) + { IntPtr hullPtr; HullDesc hullDesc; if (Hulls.TryGetValue(newHullKey, out hullDesc)) { // If the hull shape already is created, just use it. - hullPtr = hullDesc.Ptr; + hullPtr = hullDesc.ptr; } else { // Build a new hull in the physical world - int[] indices = meshDesc.meshData.getIndexListAsInt(); - List vertices = meshDesc.meshData.getVertexList(); + // Pass false for physicalness as this creates some sort of bounding box which we don't need + IMesh meshData = PhysicsScene.mesher.CreateMesh(objName, pbs, size, lod, false); + + int[] indices = meshData.getIndexListAsInt(); + List vertices = meshData.getVertexList(); //format conversion from IMesh format to DecompDesc format List convIndices = new List(); @@ -616,20 +608,13 @@ public class BSShapeCollection : IDisposable } } // create the hull data structure in Bullet - // m_log.DebugFormat("{0}: CreateGeom: calling CreateHull. lid={1}, key={2}, hulls={3}", LogHeader, LocalID, _hullKey, hullCount); hullPtr = BulletSimAPI.CreateHullShape2(PhysicsScene.World.ptr, hullCount, convHulls); } - newShape = new BulletShape(hullPtr, ShapeData.PhysicsShapeType.SHAPE_HULL); + BulletShape newShape = new BulletShape(hullPtr, ShapeData.PhysicsShapeType.SHAPE_HULL); newShape.shapeKey = newHullKey; - newShape.meshPtr = meshDesc.Ptr; - - ReferenceShape(newShape); - // meshes and hulls are already scaled by the meshmerizer - prim.Scale = new OMV.Vector3(1f, 1f, 1f); - prim.BSShape = newShape; - return true; // 'true' means a new shape has been added to this prim + return newShape; // 'true' means a new shape has been added to this prim } // Callback from convex hull creater with a newly created hull. @@ -640,7 +625,30 @@ public class BSShapeCollection : IDisposable return; } - // Create an object in Bullet if it has not already been created. + // Create a hash of all the shape parameters to be used as a key + // for this particular shape. + private ulong ComputeShapeKey(ShapeData shapeData, PrimitiveBaseShape pbs, out float retLod) + { + // level of detail based on size and type of the object + float lod = PhysicsScene.MeshLOD; + if (pbs.SculptEntry) + lod = PhysicsScene.SculptLOD; + + float maxAxis = Math.Max(shapeData.Size.X, Math.Max(shapeData.Size.Y, shapeData.Size.Z)); + if (maxAxis > PhysicsScene.MeshMegaPrimThreshold) + lod = PhysicsScene.MeshMegaPrimLOD; + + retLod = lod; + return (ulong)pbs.GetMeshKey(shapeData.Size, lod); + } + // For those who don't want the LOD + private ulong ComputeShapeKey(ShapeData shapeData, PrimitiveBaseShape pbs) + { + float lod; + return ComputeShapeKey(shapeData, pbs, out lod); + } + + // Create a body object in Bullet. // Updates prim.BSBody with the information about the new body if one is created. // Returns 'true' if an object was actually created. // Called at taint-time. @@ -665,7 +673,7 @@ public class BSShapeCollection : IDisposable } - if (mustRebuild) + if (mustRebuild || forceRebuild) { DereferenceBody(prim.BSBody, true); @@ -673,13 +681,15 @@ public class BSShapeCollection : IDisposable IntPtr bodyPtr = IntPtr.Zero; if (prim.IsSolid) { - bodyPtr = BulletSimAPI.CreateBodyFromShape2(sim.ptr, shape.ptr, shapeData.Position, shapeData.Rotation); - DetailLog("{0},BSShapeCollection.CreateObject,mesh,ptr={1:X}", prim.LocalID, bodyPtr); + bodyPtr = BulletSimAPI.CreateBodyFromShape2(sim.ptr, shape.ptr, + shapeData.ID, shapeData.Position, shapeData.Rotation); + DetailLog("{0},BSShapeCollection.CreateBody,mesh,ptr={1}", prim.LocalID, bodyPtr.ToString("X")); } else { - bodyPtr = BulletSimAPI.CreateGhostFromShape2(sim.ptr, shape.ptr, shapeData.Position, shapeData.Rotation); - DetailLog("{0},BSShapeCollection.CreateObject,ghost,ptr={1:X}", prim.LocalID, bodyPtr); + bodyPtr = BulletSimAPI.CreateGhostFromShape2(sim.ptr, shape.ptr, + shapeData.ID, shapeData.Position, shapeData.Rotation); + DetailLog("{0},BSShapeCollection.CreateBody,ghost,ptr={1}", prim.LocalID, bodyPtr.ToString("X")); } aBody = new BulletBody(shapeData.ID, bodyPtr); diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs index 093d2a4..5d5d9cb 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs @@ -111,8 +111,12 @@ public class BSTerrainManager BulletSimAPI.CreateGroundPlaneShape2(BSScene.GROUNDPLANE_ID, 1f, TERRAIN_COLLISION_MARGIN), ShapeData.PhysicsShapeType.SHAPE_GROUNDPLANE); m_groundPlane = new BulletBody(BSScene.GROUNDPLANE_ID, - BulletSimAPI.CreateBodyWithDefaultMotionState2(groundPlaneShape.ptr, Vector3.Zero, Quaternion.Identity)); + BulletSimAPI.CreateBodyWithDefaultMotionState2(groundPlaneShape.ptr, BSScene.GROUNDPLANE_ID, + Vector3.Zero, Quaternion.Identity)); BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, m_groundPlane.ptr); + // Everything collides with the ground plane. + BulletSimAPI.SetCollisionFilterMask2(m_groundPlane.ptr, + (uint)CollisionFilterGroups.GroundPlaneFilter, (uint)CollisionFilterGroups.GroundPlaneMask); Vector3 minTerrainCoords = new Vector3(0f, 0f, HEIGHT_INITIALIZATION - HEIGHT_EQUAL_FUDGE); Vector3 maxTerrainCoords = new Vector3(DefaultRegionSize.X, DefaultRegionSize.Y, HEIGHT_INITIALIZATION); @@ -304,7 +308,11 @@ public class BSTerrainManager mapInfo.terrainBody = new BulletBody(mapInfo.ID, BulletSimAPI.CreateBodyWithDefaultMotionState2(mapInfo.terrainShape.ptr, - centerPos, Quaternion.Identity)); + id, centerPos, Quaternion.Identity)); + + BulletSimAPI.SetCollisionFilterMask2(mapInfo.terrainBody.ptr, + (uint)CollisionFilterGroups.TerrainFilter, + (uint)CollisionFilterGroups.TerrainMask); } // Make sure the entry is in the heightmap table diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs index 8480dd1..6910050 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs @@ -57,9 +57,13 @@ public struct BulletBody { ID = id; ptr = xx; + collisionFilter = 0; + collisionMask = 0; } public IntPtr ptr; public uint ID; + public CollisionFilterGroups collisionFilter; + public CollisionFilterGroups collisionMask; public override string ToString() { StringBuilder buff = new StringBuilder(); @@ -67,6 +71,13 @@ public struct BulletBody buff.Append(ID.ToString()); buff.Append(",p="); buff.Append(ptr.ToString("X")); + if (collisionFilter != 0 && collisionMask != 0) + { + buff.Append(",f="); + buff.Append(collisionFilter.ToString("X")); + buff.Append(",m="); + buff.Append(collisionMask.ToString("X")); + } buff.Append(">"); return buff.ToString(); } @@ -80,7 +91,6 @@ public struct BulletShape type=ShapeData.PhysicsShapeType.SHAPE_UNKNOWN; shapeKey = 0; isNativeShape = false; - meshPtr = IntPtr.Zero; } public BulletShape(IntPtr xx, ShapeData.PhysicsShapeType typ) { @@ -88,14 +98,12 @@ public struct BulletShape type = typ; shapeKey = 0; isNativeShape = false; - meshPtr = IntPtr.Zero; } public IntPtr ptr; public ShapeData.PhysicsShapeType type; public ulong shapeKey; public bool isNativeShape; // Hulls have an underlying mesh. A pointer to it is hidden here. - public IntPtr meshPtr; public override string ToString() { StringBuilder buff = new StringBuilder(); @@ -107,8 +115,6 @@ public struct BulletShape buff.Append(shapeKey.ToString("X")); buff.Append(",n="); buff.Append(isNativeShape.ToString()); - buff.Append(",m="); - buff.Append(meshPtr.ToString("X")); buff.Append(">"); return buff.ToString(); } @@ -124,7 +130,7 @@ public struct BulletConstraint public IntPtr Ptr; } -// An allocated HeightMapThing which hold various heightmap info +// An allocated HeightMapThing which holds various heightmap info. // Made a class rather than a struct so there would be only one // instance of this and C# will pass around pointers rather // than making copies. @@ -345,21 +351,41 @@ public enum CollisionFlags : uint // Values for collisions groups and masks public enum CollisionFilterGroups : uint { - NoneFilter = 0, - DefaultFilter = 1 << 0, - StaticFilter = 1 << 1, - KinematicFilter = 1 << 2, - DebrisFilter = 1 << 3, - SensorTrigger = 1 << 4, - CharacterFilter = 1 << 5, - AllFilter = 0xFFFFFFFF, + // Don't use the bit definitions!! Define the use in a + // filter/mask definition below. This way collision interactions + // are more easily debugged. + BNoneFilter = 0, + BDefaultFilter = 1 << 0, + BStaticFilter = 1 << 1, + BKinematicFilter = 1 << 2, + BDebrisFilter = 1 << 3, + BSensorTrigger = 1 << 4, + BCharacterFilter = 1 << 5, + BAllFilter = 0xFFFFFFFF, // Filter groups defined by BulletSim - GroundPlaneFilter = 1 << 10, - TerrainFilter = 1 << 11, - RaycastFilter = 1 << 12, - SolidFilter = 1 << 13, + BGroundPlaneFilter = 1 << 10, + BTerrainFilter = 1 << 11, + BRaycastFilter = 1 << 12, + BSolidFilter = 1 << 13, + + // The collsion filters and masked are defined in one place -- don't want them scattered + AvatarFilter = BDefaultFilter | BCharacterFilter | BSolidFilter, + AvatarMask = BAllFilter, + ObjectFilter = BDefaultFilter | BSolidFilter, + ObjectMask = BAllFilter, + StaticObjectFilter = BDefaultFilter | BStaticFilter | BSolidFilter, + StaticObjectMask = BAllFilter, + VolumeDetectFilter = BSensorTrigger, + VolumeDetectMask = ~BSensorTrigger, + TerrainFilter = BTerrainFilter, + TerrainMask = BAllFilter, + GroundPlaneFilter = BAllFilter, + GroundPlaneMask = BAllFilter + }; + + // CFM controls the 'hardness' of the constraint. 0=fixed, 0..1=violatable. Default=0 // ERP controls amount of correction per tick. Usable range=0.1..0.8. Default=0.2. public enum ConstraintParams : int @@ -560,7 +586,7 @@ public static extern IntPtr CreateHullShape2(IntPtr world, int hullCount, [MarshalAs(UnmanagedType.LPArray)] float[] hulls); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern IntPtr BuildHullShape2(IntPtr world, IntPtr meshShape); +public static extern IntPtr BuildHullShapeFromMesh2(IntPtr world, IntPtr meshShape); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern IntPtr BuildNativeShape2(IntPtr world, ShapeData shapeData); @@ -581,7 +607,7 @@ public static extern void RemoveChildFromCompoundShape2(IntPtr cShape, IntPtr re public static extern IntPtr DuplicateCollisionShape2(IntPtr sim, IntPtr srcShape, uint id); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern IntPtr CreateBodyFromShapeAndInfo2(IntPtr sim, IntPtr shape, IntPtr constructionInfo); +public static extern IntPtr CreateBodyFromShapeAndInfo2(IntPtr sim, IntPtr shape, uint id, IntPtr constructionInfo); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern bool DeleteCollisionShape2(IntPtr world, IntPtr shape); @@ -590,13 +616,13 @@ public static extern bool DeleteCollisionShape2(IntPtr world, IntPtr shape); public static extern int GetBodyType2(IntPtr obj); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern IntPtr CreateBodyFromShape2(IntPtr sim, IntPtr shape, Vector3 pos, Quaternion rot); +public static extern IntPtr CreateBodyFromShape2(IntPtr sim, IntPtr shape, uint id, Vector3 pos, Quaternion rot); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern IntPtr CreateBodyWithDefaultMotionState2(IntPtr shape, Vector3 pos, Quaternion rot); +public static extern IntPtr CreateBodyWithDefaultMotionState2(IntPtr shape, uint id, Vector3 pos, Quaternion rot); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern IntPtr CreateGhostFromShape2(IntPtr sim, IntPtr shape, Vector3 pos, Quaternion rot); +public static extern IntPtr CreateGhostFromShape2(IntPtr sim, IntPtr shape, uint id, Vector3 pos, Quaternion rot); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern IntPtr AllocateBodyInfo2(IntPtr obj); @@ -1015,6 +1041,9 @@ public static extern Vector3 GetPushVelocity2(IntPtr obj); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern Vector3 GetTurnVelocity2(IntPtr obj); +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern void SetCollisionFilterMask2(IntPtr body, uint filter, uint mask); + // ===================================================================================== // btCollisionShape entries @@ -1066,9 +1095,6 @@ public static extern void SetMargin2(IntPtr shape, float val); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern float GetMargin2(IntPtr shape); -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void SetCollisionFilterMask(IntPtr shape, uint filter, uint mask); - // ===================================================================================== // Debugging [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -- cgit v1.1 From 4589bc84a32366c6aae68b67f1fc7a2ee08be86d Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Wed, 26 Sep 2012 09:25:56 -0700 Subject: BulletSim: Terrain sets proper collision flags on creation. Static objects are set to ISLAND_SLEEPING rather than DISABLE_SIMULATION. Might reconsider this and, alternatively, have dynamic objects force activation. Clean up use of DetailLog(). --- .../Region/Physics/BulletSPlugin/BSPhysObject.cs | 10 ++-- OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | 62 +++++++++++----------- .../Physics/BulletSPlugin/BSShapeCollection.cs | 16 ++++-- .../Physics/BulletSPlugin/BSTerrainManager.cs | 20 +++---- 4 files changed, 56 insertions(+), 52 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs index 3458477..4f83adc 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs @@ -121,8 +121,8 @@ public abstract class BSPhysObject : PhysicsActor // if someone has subscribed for collision events.... if (SubscribedEvents()) { CollisionCollection.AddCollider(collidingWith, new ContactPoint(contactPoint, contactNormal, pentrationDepth)); - DetailLog("{0},{1}.Collison.AddCollider,call,with={2},point={3},normal={4},depth={5}", - LocalID, TypeName, collidingWith, contactPoint, contactNormal, pentrationDepth); + // DetailLog("{0},{1}.Collison.AddCollider,call,with={2},point={3},normal={4},depth={5}", + // LocalID, TypeName, collidingWith, contactPoint, contactNormal, pentrationDepth); ret = true; } @@ -151,7 +151,7 @@ public abstract class BSPhysObject : PhysicsActor PhysicsScene.ObjectsWithNoMoreCollisions.Add(this); } - DetailLog("{0},{1}.SendCollisionUpdate,call,numCollisions={2}", LocalID, TypeName, CollisionCollection.Count); + // DetailLog("{0},{1}.SendCollisionUpdate,call,numCollisions={2}", LocalID, TypeName, CollisionCollection.Count); base.SendCollisionUpdate(CollisionCollection); // The collisionCollection structure is passed around in the simulator. @@ -163,7 +163,7 @@ public abstract class BSPhysObject : PhysicsActor // Subscribe for collision events. // Parameter is the millisecond rate the caller wishes collision events to occur. public override void SubscribeEvents(int ms) { - DetailLog("{0},{1}.SubscribeEvents,subscribing,ms={2}", LocalID, TypeName, ms); + // DetailLog("{0},{1}.SubscribeEvents,subscribing,ms={2}", LocalID, TypeName, ms); SubscribedEventsMs = ms; if (ms > 0) { @@ -182,7 +182,7 @@ public abstract class BSPhysObject : PhysicsActor } } public override void UnSubscribeEvents() { - DetailLog("{0},{1}.UnSubscribeEvents,unsubscribing", LocalID, TypeName); + // DetailLog("{0},{1}.UnSubscribeEvents,unsubscribing", LocalID, TypeName); SubscribedEventsMs = 0; PhysicsScene.TaintedObject(TypeName+".UnSubscribeEvents", delegate() { diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index 1c6d476..68a153e 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs @@ -174,7 +174,7 @@ public sealed class BSPrim : BSPhysObject // Since _size changed, the mesh needs to be rebuilt. If rebuilt, all the correct // scale and margins are set. CreateGeomAndObject(true); - DetailLog("{0},BSPrim.setSize,size={1},scale={2},mass={3},physical={4}", LocalID, _size, _scale, _mass, IsPhysical); + // DetailLog("{0},BSPrim.setSize,size={1},scale={2},mass={3},physical={4}", LocalID, _size, _scale, _mass, IsPhysical); }); } } @@ -204,6 +204,7 @@ public sealed class BSPrim : BSPhysObject _isSelected = value; PhysicsScene.TaintedObject("BSPrim.setSelected", delegate() { + // DetailLog("{0},BSPrim.selected,taint,selected={1}", LocalID, _isSelected); SetObjectDynamic(false); }); } @@ -279,7 +280,7 @@ public sealed class BSPrim : BSPhysObject // TODO: what does it mean to set the position of a child prim?? Rebuild the constraint? PhysicsScene.TaintedObject("BSPrim.setPosition", delegate() { - DetailLog("{0},BSPrim.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation); + // DetailLog("{0},BSPrim.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation); BulletSimAPI.SetTranslation2(BSBody.ptr, _position, _orientation); }); } @@ -317,7 +318,7 @@ public sealed class BSPrim : BSPhysObject _force = value; PhysicsScene.TaintedObject("BSPrim.setForce", delegate() { - DetailLog("{0},BSPrim.setForce,taint,force={1}", LocalID, _force); + // DetailLog("{0},BSPrim.setForce,taint,force={1}", LocalID, _force); BulletSimAPI.SetObjectForce2(BSBody.ptr, _force); }); } @@ -385,7 +386,7 @@ public sealed class BSPrim : BSPhysObject _isVolumeDetect = newValue; PhysicsScene.TaintedObject("BSPrim.SetVolumeDetect", delegate() { - DetailLog("{0},setVolumeDetect,taint,volDetect={1}", LocalID, _isVolumeDetect); + // DetailLog("{0},setVolumeDetect,taint,volDetect={1}", LocalID, _isVolumeDetect); SetObjectDynamic(true); }); } @@ -398,7 +399,7 @@ public sealed class BSPrim : BSPhysObject _velocity = value; PhysicsScene.TaintedObject("BSPrim.setVelocity", delegate() { - DetailLog("{0},BSPrim.SetVelocity,taint,vel={1}", LocalID, _velocity); + // DetailLog("{0},BSPrim.SetVelocity,taint,vel={1}", LocalID, _velocity); BulletSimAPI.SetLinearVelocity2(BSBody.ptr, _velocity); }); } @@ -406,7 +407,7 @@ public sealed class BSPrim : BSPhysObject public override OMV.Vector3 Torque { get { return _torque; } set { _torque = value; - DetailLog("{0},BSPrim.SetTorque,call,torque={1}", LocalID, _torque); + // DetailLog("{0},BSPrim.SetTorque,call,torque={1}", LocalID, _torque); } } public override float CollisionScore { @@ -433,7 +434,7 @@ public sealed class BSPrim : BSPhysObject PhysicsScene.TaintedObject("BSPrim.setOrientation", delegate() { // _position = BulletSimAPI.GetObjectPosition2(PhysicsScene.World.ptr, BSBody.ptr); - DetailLog("{0},BSPrim.setOrientation,taint,pos={1},orient={2}", LocalID, _position, _orientation); + // DetailLog("{0},BSPrim.setOrientation,taint,pos={1},orient={2}", LocalID, _position, _orientation); BulletSimAPI.SetTranslation2(BSBody.ptr, _position, _orientation); }); } @@ -450,7 +451,7 @@ public sealed class BSPrim : BSPhysObject _isPhysical = value; PhysicsScene.TaintedObject("BSPrim.setIsPhysical", delegate() { - DetailLog("{0},setIsPhysical,taint,isPhys={1}", LocalID, _isPhysical); + // DetailLog("{0},setIsPhysical,taint,isPhys={1}", LocalID, _isPhysical); SetObjectDynamic(true); }); } @@ -470,12 +471,7 @@ public sealed class BSPrim : BSPhysObject } // Make gravity work if the object is physical and not selected - // No locking here because only called when it is safe (called at taint-time). - // There are four flags we're interested in: - // IsStatic: Object does not move, otherwise the object has mass and moves - // isSolid: other objects bounce off of this object - // isVolumeDetect: other objects pass through but can generate collisions - // collisionEvents: whether this object returns collision events + // Called at taint-time!! private void SetObjectDynamic(bool forceRebuild) { #if CSHARP_BODY_MANAGEMENT @@ -488,11 +484,17 @@ public sealed class BSPrim : BSPhysObject #endif // CSHARP_BODY_MANAGEMENT } + // Convert the simulator's physical properties into settings on BulletSim objects. + // There are four flags we're interested in: + // IsStatic: Object does not move, otherwise the object has mass and moves + // isSolid: other objects bounce off of this object + // isVolumeDetect: other objects pass through but can generate collisions + // collisionEvents: whether this object returns collision events private void UpdatePhysicalParameters() { - DetailLog("{0},BSPrim.UpdatePhysicalParameters,entry,body={1},shape={2}", LocalID, BSBody, BSShape); + // DetailLog("{0},BSPrim.UpdatePhysicalParameters,entry,body={1},shape={2}", LocalID, BSBody, BSShape); - // Mangling all the physical properties requires the object to be out of the physical world. + // Mangling all the physical properties requires the object not be in the physical world. // This is a NOOP if the object is not in the world (BulletSim and Bullet ignore objects not found). BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, BSBody.ptr); @@ -505,7 +507,7 @@ public sealed class BSPrim : BSPhysObject // Set up the object physicalness (does gravity and collisions move this object) MakeDynamic(IsStatic); - // Arrange for collisions events if the simulator wants them + // Arrange for collision events if the simulator wants them EnableCollisions(SubscribedEvents()); #if CSHARP_BODY_MANAGEMENT @@ -522,8 +524,6 @@ public sealed class BSPrim : BSPhysObject if (BSBody.collisionFilter != 0 || BSBody.collisionMask != 0) { BulletSimAPI.SetCollisionFilterMask2(BSBody.ptr, (uint)BSBody.collisionFilter, (uint)BSBody.collisionMask); - DetailLog("{0},BSPrim.UpdatePhysicalParameters,setCollisionFilterMask,filter={1},mask={2}", - LocalID, BSBody.collisionFilter.ToString("X"), BSBody.collisionMask.ToString("X")); } // Recompute any linkset parameters. @@ -557,8 +557,8 @@ public sealed class BSPrim : BSPhysObject // There can be special things needed for implementing linksets Linkset.MakeStatic(this); // The activation state is 'sleeping' so Bullet will not try to act on it - // BulletSimAPI.ForceActivationState2(BSBody.ptr, ActivationState.ISLAND_SLEEPING); - BulletSimAPI.ForceActivationState2(BSBody.ptr, ActivationState.DISABLE_SIMULATION); + BulletSimAPI.ForceActivationState2(BSBody.ptr, ActivationState.ISLAND_SLEEPING); + // BulletSimAPI.ForceActivationState2(BSBody.ptr, ActivationState.DISABLE_SIMULATION); BSBody.collisionFilter = CollisionFilterGroups.StaticObjectFilter; BSBody.collisionMask = CollisionFilterGroups.StaticObjectMask; @@ -571,16 +571,14 @@ public sealed class BSPrim : BSPhysObject // Set various physical properties so internal dynamic properties will get computed correctly as they are set BulletSimAPI.SetFriction2(BSBody.ptr, PhysicsScene.Params.defaultFriction); BulletSimAPI.SetRestitution2(BSBody.ptr, PhysicsScene.Params.defaultRestitution); + // per http://www.bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=3382 - BulletSimAPI.SetInterpolationLinearVelocity2(BSBody.ptr, OMV.Vector3.Zero); - BulletSimAPI.SetInterpolationAngularVelocity2(BSBody.ptr, OMV.Vector3.Zero); - BulletSimAPI.SetInterpolationVelocity2(BSBody.ptr, OMV.Vector3.Zero, OMV.Vector3.Zero); + BulletSimAPI.ClearAllForces2(BSBody.ptr); // A dynamic object has mass IntPtr collisionShapePtr = BulletSimAPI.GetCollisionShape2(BSBody.ptr); OMV.Vector3 inertia = BulletSimAPI.CalculateLocalInertia2(collisionShapePtr, Linkset.LinksetMass); BulletSimAPI.SetMassProps2(BSBody.ptr, _mass, inertia); - // Inertia is based on our new mass BulletSimAPI.UpdateInertiaTensor2(BSBody.ptr); // Various values for simulation limits @@ -645,7 +643,7 @@ public sealed class BSPrim : BSPhysObject // Create the new body with the shape BSBody = new BulletBody(LocalID, BulletSimAPI.CreateBodyFromShape2(PhysicsScene.World.Ptr, BSShape.Ptr, _position, _orientation)); - BulletSimAPI.RemoveFromCollisionFlags2(BSBody.Ptr, CollisionFlags.CF_NO_CONTACT_RESPONSE); + CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(BSBody.Ptr, CollisionFlags.CF_NO_CONTACT_RESPONSE); DetailLog("{0},BSPrim.MakeSolid:rigidBody,body={1},shape={2}", LocalID, BSBody, BSShape); } } @@ -741,7 +739,7 @@ public sealed class BSPrim : BSPhysObject // m_log.DebugFormat("{0}: RotationalVelocity={1}", LogHeader, _rotationalVelocity); PhysicsScene.TaintedObject("BSPrim.setRotationalVelocity", delegate() { - DetailLog("{0},BSPrim.SetRotationalVel,taint,rotvel={1}", LocalID, _rotationalVelocity); + // DetailLog("{0},BSPrim.SetRotationalVel,taint,rotvel={1}", LocalID, _rotationalVelocity); BulletSimAPI.SetAngularVelocity2(BSBody.ptr, _rotationalVelocity); }); } @@ -758,7 +756,7 @@ public sealed class BSPrim : BSPhysObject _buoyancy = value; PhysicsScene.TaintedObject("BSPrim.setBuoyancy", delegate() { - DetailLog("{0},BSPrim.SetBuoyancy,taint,buoy={1}", LocalID, _buoyancy); + // DetailLog("{0},BSPrim.SetBuoyancy,taint,buoy={1}", LocalID, _buoyancy); // Buoyancy is faked by changing the gravity applied to the object float grav = PhysicsScene.Params.gravity * (1f - _buoyancy); BulletSimAPI.SetGravity2(BSBody.ptr, new OMV.Vector3(0f, 0f, grav)); @@ -823,18 +821,18 @@ public sealed class BSPrim : BSPhysObject } m_accumulatedForces.Clear(); } - DetailLog("{0},BSPrim.AddObjectForce,taint,force={1}", LocalID, fSum); + // DetailLog("{0},BSPrim.AddObjectForce,taint,force={1}", LocalID, fSum); // For unknown reasons, "ApplyCentralForce" adds this force to the total force on the object. BulletSimAPI.ApplyCentralForce2(BSBody.ptr, fSum); }); } public override void AddAngularForce(OMV.Vector3 force, bool pushforce) { - DetailLog("{0},BSPrim.AddAngularForce,call,angForce={1},push={2}", LocalID, force, pushforce); + // DetailLog("{0},BSPrim.AddAngularForce,call,angForce={1},push={2}", LocalID, force, pushforce); // m_log.DebugFormat("{0}: AddAngularForce. f={1}, push={2}", LogHeader, force, pushforce); } public override void SetMomentum(OMV.Vector3 momentum) { - DetailLog("{0},BSPrim.SetMomentum,call,mom={1}", LocalID, momentum); + // DetailLog("{0},BSPrim.SetMomentum,call,mom={1}", LocalID, momentum); } #region Mass Calculation @@ -1452,7 +1450,7 @@ public sealed class BSPrim : BSPhysObject } // Rebuild the geometry and object. // This is called when the shape changes so we need to recreate the mesh/hull. - // No locking here because this is done when the physics engine is not simulating (taint-time). + // Called at taint-time!!! private void CreateGeomAndObject(bool forceRebuild) { #if CSHARP_BODY_MANAGEMENT diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs index 7fce8c9..aadb8d6 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs @@ -344,7 +344,10 @@ public class BSShapeCollection : IDisposable if (pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1) { haveShape = true; - if (forceRebuild || (prim.BSShape.type != ShapeData.PhysicsShapeType.SHAPE_SPHERE)) + if (forceRebuild + || prim.Scale != shapeData.Size + || prim.BSShape.type != ShapeData.PhysicsShapeType.SHAPE_SPHERE + ) { ret = GetReferenceToNativeShape(prim, shapeData, ShapeData.PhysicsShapeType.SHAPE_SPHERE, ShapeData.FixedShapeKey.KEY_SPHERE); @@ -355,7 +358,10 @@ public class BSShapeCollection : IDisposable else { haveShape = true; - if (forceRebuild || (prim.BSShape.type != ShapeData.PhysicsShapeType.SHAPE_BOX)) + if (forceRebuild + || prim.Scale != shapeData.Size + || prim.BSShape.type != ShapeData.PhysicsShapeType.SHAPE_BOX + ) { ret = GetReferenceToNativeShape( prim, shapeData, ShapeData.PhysicsShapeType.SHAPE_BOX, ShapeData.FixedShapeKey.KEY_BOX); @@ -406,7 +412,7 @@ public class BSShapeCollection : IDisposable newShape.isNativeShape = true; // Don't need to do a 'ReferenceShape()' here because native shapes are not tracked. - DetailLog("{0},BSShapeCollection.AddNativeShapeToPrim,create,newshape={1}", shapeData.ID, newShape); + // DetailLog("{0},BSShapeCollection.AddNativeShapeToPrim,create,newshape={1}", shapeData.ID, newShape); prim.BSShape = newShape; return true; @@ -683,13 +689,13 @@ public class BSShapeCollection : IDisposable { bodyPtr = BulletSimAPI.CreateBodyFromShape2(sim.ptr, shape.ptr, shapeData.ID, shapeData.Position, shapeData.Rotation); - DetailLog("{0},BSShapeCollection.CreateBody,mesh,ptr={1}", prim.LocalID, bodyPtr.ToString("X")); + // DetailLog("{0},BSShapeCollection.CreateBody,mesh,ptr={1}", prim.LocalID, bodyPtr.ToString("X")); } else { bodyPtr = BulletSimAPI.CreateGhostFromShape2(sim.ptr, shape.ptr, shapeData.ID, shapeData.Position, shapeData.Rotation); - DetailLog("{0},BSShapeCollection.CreateBody,ghost,ptr={1}", prim.LocalID, bodyPtr.ToString("X")); + // DetailLog("{0},BSShapeCollection.CreateBody,ghost,ptr={1}", prim.LocalID, bodyPtr.ToString("X")); } aBody = new BulletBody(shapeData.ID, bodyPtr); diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs index 5d5d9cb..50638d6 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs @@ -201,10 +201,10 @@ public class BSTerrainManager // The 'doNow' boolean says whether to do all the unmanaged activities right now (like when // calling this routine from initialization or taint-time routines) or whether to delay // all the unmanaged activities to taint-time. - private void UpdateOrCreateTerrain(uint id, float[] heightMap, Vector3 minCoords, Vector3 maxCoords, bool doNow) + private void UpdateOrCreateTerrain(uint id, float[] heightMap, Vector3 minCoords, Vector3 maxCoords, bool atTaintTime) { - DetailLog("{0},BSTerrainManager.UpdateOrCreateTerrain,call,minC={1},maxC={2},doNow={3}", - BSScene.DetailLogZero, minCoords, maxCoords, doNow); + DetailLog("{0},BSTerrainManager.UpdateOrCreateTerrain,call,minC={1},maxC={2},atTaintTime={3}", + BSScene.DetailLogZero, minCoords, maxCoords, atTaintTime); float minZ = float.MaxValue; float maxZ = float.MinValue; @@ -308,11 +308,7 @@ public class BSTerrainManager mapInfo.terrainBody = new BulletBody(mapInfo.ID, BulletSimAPI.CreateBodyWithDefaultMotionState2(mapInfo.terrainShape.ptr, - id, centerPos, Quaternion.Identity)); - - BulletSimAPI.SetCollisionFilterMask2(mapInfo.terrainBody.ptr, - (uint)CollisionFilterGroups.TerrainFilter, - (uint)CollisionFilterGroups.TerrainMask); + id, centerPos, Quaternion.Identity)); } // Make sure the entry is in the heightmap table @@ -333,6 +329,10 @@ public class BSTerrainManager // redo its bounding box now that it is in the world BulletSimAPI.UpdateSingleAabb2(PhysicsScene.World.ptr, mapInfo.terrainBody.ptr); + BulletSimAPI.SetCollisionFilterMask2(mapInfo.terrainBody.ptr, + (uint)CollisionFilterGroups.TerrainFilter, + (uint)CollisionFilterGroups.TerrainMask); + // Make sure the new shape is processed. BulletSimAPI.Activate2(mapInfo.terrainBody.ptr, true); @@ -341,7 +341,7 @@ public class BSTerrainManager // There is the option to do the changes now (we're already in 'taint time'), or // to do the Bullet operations later. - if (doNow) + if (atTaintTime) rebuildOperation(); else PhysicsScene.TaintedObject("BSScene.UpdateOrCreateTerrain:UpdateExisting", rebuildOperation); @@ -380,7 +380,7 @@ public class BSTerrainManager }; // If already in taint-time, just call Bullet. Otherwise queue the operations for the safe time. - if (doNow) + if (atTaintTime) createOperation(); else PhysicsScene.TaintedObject("BSScene.UpdateOrCreateTerrain:NewTerrain", createOperation); -- cgit v1.1 From f82b903deeaaf8eaa7ae5c4d4b7e917dd0a6ce7b Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Thu, 27 Sep 2012 08:23:29 -0700 Subject: BulletSim: Fix linkset crash. Caused by the different body and shape pointers at runtime and at taint-time. Now passes the body into the taint. Vehicles zero inertia when active to eliminate Bullet's contribution to vehicle motion. --- .../Physics/BulletSPlugin/BS6DofConstraint.cs | 20 +++- OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs | 123 ++++++++++++--------- OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs | 75 ++++++++++--- .../Region/Physics/BulletSPlugin/BSPhysObject.cs | 8 +- OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | 22 +++- OpenSim/Region/Physics/BulletSPlugin/BSScene.cs | 7 +- .../Physics/BulletSPlugin/BSShapeCollection.cs | 10 +- .../Physics/BulletSPlugin/BSTerrainManager.cs | 3 +- .../Region/Physics/BulletSPlugin/BulletSimAPI.cs | 8 +- 9 files changed, 182 insertions(+), 94 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BS6DofConstraint.cs b/OpenSim/Region/Physics/BulletSPlugin/BS6DofConstraint.cs index ff271fe..39a3421 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BS6DofConstraint.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BS6DofConstraint.cs @@ -58,10 +58,22 @@ public class BS6DofConstraint : BSConstraint m_world = world; m_body1 = obj1; m_body2 = obj2; - m_constraint = new BulletConstraint( - BulletSimAPI.Create6DofConstraintToPoint2(m_world.ptr, m_body1.ptr, m_body2.ptr, - joinPoint, - useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies)); + if (obj1.ptr == IntPtr.Zero || obj2.ptr == IntPtr.Zero) + { + world.scene.DetailLog("{0},BS6DOFConstraint,badBodyPtr,wID={1}, rID={2}, rBody={3}, cID={4}, cBody={5}", + "[BULLETSIM 6DOF CONSTRAINT]", world.worldID, + obj1.ID, obj1.ptr.ToString("X"), obj2.ID, obj2.ptr.ToString("X")); + world.scene.Logger.ErrorFormat("{0} Attempt to build 6DOF constraint with missing bodies: wID={1}, rID={2}, rBody={3}, cID={4}, cBody={5}", + "[BULLETSIM 6DOF CONSTRAINT]", world.worldID, + obj1.ID, obj1.ptr.ToString("X"), obj2.ID, obj2.ptr.ToString("X")); + } + else + { + m_constraint = new BulletConstraint( + BulletSimAPI.Create6DofConstraintToPoint2(m_world.ptr, m_body1.ptr, m_body2.ptr, + joinPoint, + useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies)); + } m_enabled = true; } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs index 2da2331..cf33d0e 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs @@ -54,18 +54,13 @@ namespace OpenSim.Region.Physics.BulletSPlugin { public class BSDynamics { - private int frcount = 0; // Used to limit dynamics debug output to - // every 100th frame - - private BSScene m_physicsScene; - private BSPrim m_prim; // the prim this dynamic controller belongs to + private BSScene PhysicsScene { get; set; } + // the prim this dynamic controller belongs to + private BSPrim Prim { get; set; } // Vehicle properties - private Vehicle m_type = Vehicle.TYPE_NONE; // If a 'VEHICLE', and what kind - public Vehicle Type - { - get { return m_type; } - } + public Vehicle Type { get; set; } + // private Quaternion m_referenceFrame = Quaternion.Identity; // Axis modifier private VehicleFlag m_flags = (VehicleFlag) 0; // Boolean settings: // HOVER_TERRAIN_ONLY @@ -126,14 +121,20 @@ namespace OpenSim.Region.Physics.BulletSPlugin public BSDynamics(BSScene myScene, BSPrim myPrim) { - m_physicsScene = myScene; - m_prim = myPrim; - m_type = Vehicle.TYPE_NONE; + PhysicsScene = myScene; + Prim = myPrim; + Type = Vehicle.TYPE_NONE; + } + + // Return 'true' if this vehicle is doing vehicle things + public bool IsActive + { + get { return Type != Vehicle.TYPE_NONE; } } internal void ProcessFloatVehicleParam(Vehicle pParam, float pValue) { - VDetailLog("{0},ProcessFloatVehicleParam,param={1},val={2}", m_prim.LocalID, pParam, pValue); + VDetailLog("{0},ProcessFloatVehicleParam,param={1},val={2}", Prim.LocalID, pParam, pValue); switch (pParam) { case Vehicle.ANGULAR_DEFLECTION_EFFICIENCY: @@ -232,7 +233,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin internal void ProcessVectorVehicleParam(Vehicle pParam, Vector3 pValue) { - VDetailLog("{0},ProcessVectorVehicleParam,param={1},val={2}", m_prim.LocalID, pParam, pValue); + VDetailLog("{0},ProcessVectorVehicleParam,param={1},val={2}", Prim.LocalID, pParam, pValue); switch (pParam) { case Vehicle.ANGULAR_FRICTION_TIMESCALE: @@ -267,7 +268,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin internal void ProcessRotationVehicleParam(Vehicle pParam, Quaternion pValue) { - VDetailLog("{0},ProcessRotationalVehicleParam,param={1},val={2}", m_prim.LocalID, pParam, pValue); + VDetailLog("{0},ProcessRotationalVehicleParam,param={1},val={2}", Prim.LocalID, pParam, pValue); switch (pParam) { case Vehicle.REFERENCE_FRAME: @@ -281,7 +282,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin internal void ProcessVehicleFlags(int pParam, bool remove) { - VDetailLog("{0},ProcessVehicleFlags,param={1},remove={2}", m_prim.LocalID, pParam, remove); + VDetailLog("{0},ProcessVehicleFlags,param={1},remove={2}", Prim.LocalID, pParam, remove); VehicleFlag parm = (VehicleFlag)pParam; if (remove) { @@ -301,9 +302,9 @@ namespace OpenSim.Region.Physics.BulletSPlugin internal void ProcessTypeChange(Vehicle pType) { - VDetailLog("{0},ProcessTypeChange,type={1}", m_prim.LocalID, pType); + VDetailLog("{0},ProcessTypeChange,type={1}", Prim.LocalID, pType); // Set Defaults For Type - m_type = pType; + Type = pType; switch (pType) { case Vehicle.TYPE_NONE: @@ -465,26 +466,37 @@ namespace OpenSim.Region.Physics.BulletSPlugin } }//end SetDefaultsForType + // Some of the properties of this prim may have changed. + // Do any updating needed for a vehicle + public void Refresh() + { + if (Type == Vehicle.TYPE_NONE) return; + + // Set the prim's inertia to zero. The vehicle code handles that and this + // removes the torque action introduced by Bullet. + Vector3 inertia = Vector3.Zero; + BulletSimAPI.SetMassProps2(Prim.BSBody.ptr, Prim.MassRaw, inertia); + BulletSimAPI.UpdateInertiaTensor2(Prim.BSBody.ptr); + } + // One step of the vehicle properties for the next 'pTimestep' seconds. internal void Step(float pTimestep) { - if (m_type == Vehicle.TYPE_NONE) return; - - frcount++; // used to limit debug comment output - if (frcount > 100) - frcount = 0; + if (!IsActive) return; MoveLinear(pTimestep); MoveAngular(pTimestep); LimitRotation(pTimestep); // remember the position so next step we can limit absolute movement effects - m_lastPositionVector = m_prim.Position; + m_lastPositionVector = Prim.Position; VDetailLog("{0},BSDynamics.Step,done,pos={1},force={2},velocity={3},angvel={4}", - m_prim.LocalID, m_prim.Position, m_prim.Force, m_prim.Velocity, m_prim.RotationalVelocity); + Prim.LocalID, Prim.Position, Prim.Force, Prim.Velocity, Prim.RotationalVelocity); }// end Step + // Apply the effect of the linear motor. + // Also does hover and float. private void MoveLinear(float pTimestep) { // m_linearMotorDirection is the direction we are moving relative to the vehicle coordinates @@ -520,18 +532,18 @@ namespace OpenSim.Region.Physics.BulletSPlugin m_linearMotorDirection *= keepfraction; VDetailLog("{0},MoveLinear,nonZero,origdir={1},origvel={2},add={3},notDecay={4},dir={5},vel={6}", - m_prim.LocalID, origDir, origVel, addAmount, keepfraction, m_linearMotorDirection, m_lastLinearVelocityVector); + Prim.LocalID, origDir, origVel, addAmount, keepfraction, m_linearMotorDirection, m_lastLinearVelocityVector); } else { // if what remains of direction is very small, zero it. m_linearMotorDirection = Vector3.Zero; m_lastLinearVelocityVector = Vector3.Zero; - VDetailLog("{0},MoveLinear,zeroed", m_prim.LocalID); + VDetailLog("{0},MoveLinear,zeroed", Prim.LocalID); } // convert requested object velocity to object relative vector - Quaternion rotq = m_prim.Orientation; + Quaternion rotq = Prim.Orientation; m_newVelocity = m_lastLinearVelocityVector * rotq; // Add the various forces into m_dir which will be our new direction vector (velocity) @@ -539,7 +551,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin // add Gravity and Buoyancy // There is some gravity, make a gravity force vector that is applied after object velocity. // m_VehicleBuoyancy: -1=2g; 0=1g; 1=0g; - Vector3 grav = m_prim.PhysicsScene.DefaultGravity * (m_prim.Mass * (1f - m_VehicleBuoyancy)); + Vector3 grav = Prim.PhysicsScene.DefaultGravity * (Prim.Mass * (1f - m_VehicleBuoyancy)); /* * RA: Not sure why one would do this @@ -548,11 +560,11 @@ namespace OpenSim.Region.Physics.BulletSPlugin m_dir.Z = vel_now.Z; // Preserve the accumulated falling velocity */ - Vector3 pos = m_prim.Position; + Vector3 pos = Prim.Position; // Vector3 accel = new Vector3(-(m_dir.X - m_lastLinearVelocityVector.X / 0.1f), -(m_dir.Y - m_lastLinearVelocityVector.Y / 0.1f), m_dir.Z - m_lastLinearVelocityVector.Z / 0.1f); // If below the terrain, move us above the ground a little. - float terrainHeight = m_prim.PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(pos); + float terrainHeight = Prim.PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(pos); // Taking the rotated size doesn't work here because m_prim.Size is the size of the root prim and not the linkset. // Need to add a m_prim.LinkSet.Size similar to m_prim.LinkSet.Mass. // Vector3 rotatedSize = m_prim.Size * m_prim.Orientation; @@ -560,8 +572,8 @@ namespace OpenSim.Region.Physics.BulletSPlugin if (pos.Z < terrainHeight) { pos.Z = terrainHeight + 2; - m_prim.Position = pos; - VDetailLog("{0},MoveLinear,terrainHeight,terrainHeight={1},pos={2}", m_prim.LocalID, terrainHeight, pos); + Prim.Position = pos; + VDetailLog("{0},MoveLinear,terrainHeight,terrainHeight={1},pos={2}", Prim.LocalID, terrainHeight, pos); } // Check if hovering @@ -570,7 +582,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin // We should hover, get the target height if ((m_flags & VehicleFlag.HOVER_WATER_ONLY) != 0) { - m_VhoverTargetHeight = m_prim.PhysicsScene.GetWaterLevelAtXYZ(pos) + m_VhoverHeight; + m_VhoverTargetHeight = Prim.PhysicsScene.GetWaterLevelAtXYZ(pos) + m_VhoverHeight; } if ((m_flags & VehicleFlag.HOVER_TERRAIN_ONLY) != 0) { @@ -590,7 +602,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin { if ((pos.Z - m_VhoverTargetHeight) > .2 || (pos.Z - m_VhoverTargetHeight) < -.2) { - m_prim.Position = pos; + Prim.Position = pos; } } else @@ -608,7 +620,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin } } - VDetailLog("{0},MoveLinear,hover,pos={1},dir={2},height={3},target={4}", m_prim.LocalID, pos, m_newVelocity, m_VhoverHeight, m_VhoverTargetHeight); + VDetailLog("{0},MoveLinear,hover,pos={1},dir={2},height={3},target={4}", Prim.LocalID, pos, m_newVelocity, m_VhoverHeight, m_VhoverTargetHeight); } Vector3 posChange = pos - m_lastPositionVector; @@ -642,9 +654,9 @@ namespace OpenSim.Region.Physics.BulletSPlugin } if (changed) { - m_prim.Position = pos; + Prim.Position = pos; VDetailLog("{0},MoveLinear,blockingEndPoint,block={1},origPos={2},pos={3}", - m_prim.LocalID, m_BlockingEndPoint, posChange, pos); + Prim.LocalID, m_BlockingEndPoint, posChange, pos); } } @@ -664,7 +676,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin float postemp = (pos.Z - terrainHeight); if (postemp > 2.5f) grav.Z = (float)(grav.Z * 1.037125); - VDetailLog("{0},MoveLinear,limitMotorUp,grav={1}", m_prim.LocalID, grav); + VDetailLog("{0},MoveLinear,limitMotorUp,grav={1}", Prim.LocalID, grav); } if ((m_flags & (VehicleFlag.NO_X)) != 0) m_newVelocity.X = 0; @@ -674,7 +686,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin m_newVelocity.Z = 0; // Apply velocity - m_prim.Velocity = m_newVelocity; + Prim.Velocity = m_newVelocity; // apply gravity force // Why is this set here? The physics engine already does gravity. // m_prim.AddForce(grav, false); @@ -684,10 +696,11 @@ namespace OpenSim.Region.Physics.BulletSPlugin m_lastLinearVelocityVector *= keepFraction; VDetailLog("{0},MoveLinear,done,lmDir={1},lmVel={2},newVel={3},grav={4},1Mdecay={5}", - m_prim.LocalID, m_linearMotorDirection, m_lastLinearVelocityVector, m_newVelocity, grav, keepFraction); + Prim.LocalID, m_linearMotorDirection, m_lastLinearVelocityVector, m_newVelocity, grav, keepFraction); } // end MoveLinear() + // Apply the effect of the angular motor. private void MoveAngular(float pTimestep) { // m_angularMotorDirection // angular velocity requested by LSL motor @@ -699,7 +712,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin // m_lastAngularVelocity // what was last applied to body // Get what the body is doing, this includes 'external' influences - Vector3 angularVelocity = m_prim.RotationalVelocity; + Vector3 angularVelocity = Prim.RotationalVelocity; if (m_angularMotorApply > 0) { @@ -716,7 +729,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin m_angularMotorVelocity.Z += (m_angularMotorDirection.Z - m_angularMotorVelocity.Z) / (m_angularMotorTimescale / pTimestep); VDetailLog("{0},MoveAngular,angularMotorApply,apply={1},angTScale={2},timeStep={3},origvel={4},dir={5},vel={6}", - m_prim.LocalID, m_angularMotorApply, m_angularMotorTimescale, pTimestep, origAngularVelocity, m_angularMotorDirection, m_angularMotorVelocity); + Prim.LocalID, m_angularMotorApply, m_angularMotorTimescale, pTimestep, origAngularVelocity, m_angularMotorDirection, m_angularMotorVelocity); // This is done so that if script request rate is less than phys frame rate the expected // velocity may still be acheived. @@ -737,7 +750,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin { float VAservo = 0.2f / (m_verticalAttractionTimescale / pTimestep); // get present body rotation - Quaternion rotq = m_prim.Orientation; + Quaternion rotq = Prim.Orientation; // make a vector pointing up Vector3 verterr = Vector3.Zero; verterr.Z = 1.0f; @@ -767,7 +780,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin vertattr.Y += bounce * angularVelocity.Y; VDetailLog("{0},MoveAngular,verticalAttraction,verterr={1},bounce={2},vertattr={3}", - m_prim.LocalID, verterr, bounce, vertattr); + Prim.LocalID, verterr, bounce, vertattr); } // else vertical attractor is off @@ -784,13 +797,13 @@ namespace OpenSim.Region.Physics.BulletSPlugin { m_lastAngularVelocity.X = 0; m_lastAngularVelocity.Y = 0; - VDetailLog("{0},MoveAngular,noDeflectionUp,lastAngular={1}", m_prim.LocalID, m_lastAngularVelocity); + VDetailLog("{0},MoveAngular,noDeflectionUp,lastAngular={1}", Prim.LocalID, m_lastAngularVelocity); } if (m_lastAngularVelocity.ApproxEquals(Vector3.Zero, 0.01f)) { m_lastAngularVelocity = Vector3.Zero; // Reduce small value to zero. - VDetailLog("{0},MoveAngular,zeroSmallValues,lastAngular={1}", m_prim.LocalID, m_lastAngularVelocity); + VDetailLog("{0},MoveAngular,zeroSmallValues,lastAngular={1}", Prim.LocalID, m_lastAngularVelocity); } // apply friction @@ -798,14 +811,14 @@ namespace OpenSim.Region.Physics.BulletSPlugin m_lastAngularVelocity -= m_lastAngularVelocity * decayamount; // Apply to the body - m_prim.RotationalVelocity = m_lastAngularVelocity; + Prim.RotationalVelocity = m_lastAngularVelocity; - VDetailLog("{0},MoveAngular,done,decay={1},lastAngular={2}", m_prim.LocalID, decayamount, m_lastAngularVelocity); + VDetailLog("{0},MoveAngular,done,decay={1},lastAngular={2}", Prim.LocalID, decayamount, m_lastAngularVelocity); } //end MoveAngular internal void LimitRotation(float timestep) { - Quaternion rotq = m_prim.Orientation; + Quaternion rotq = Prim.Orientation; Quaternion m_rot = rotq; bool changed = false; if (m_RollreferenceFrame != Quaternion.Identity) @@ -840,8 +853,8 @@ namespace OpenSim.Region.Physics.BulletSPlugin } if (changed) { - m_prim.Orientation = m_rot; - VDetailLog("{0},LimitRotation,done,orig={1},new={2}", m_prim.LocalID, rotq, m_rot); + Prim.Orientation = m_rot; + VDetailLog("{0},LimitRotation,done,orig={1},new={2}", Prim.LocalID, rotq, m_rot); } } @@ -849,8 +862,8 @@ namespace OpenSim.Region.Physics.BulletSPlugin // Invoke the detailed logger and output something if it's enabled. private void VDetailLog(string msg, params Object[] args) { - if (m_prim.PhysicsScene.VehicleLoggingEnabled) - m_prim.PhysicsScene.PhysicsLogging.Write(msg, args); + if (Prim.PhysicsScene.VehicleLoggingEnabled) + Prim.PhysicsScene.PhysicsLogging.Write(msg, args); } } } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs index 84a7fac..6967108 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs @@ -92,7 +92,9 @@ public class BSLinkset { lock (m_linksetActivityLock) { - AddChildToLinkset(child); + // Don't add the root to its own linkset + if (!IsRoot(child)) + AddChildToLinkset(child); } return this; } @@ -106,6 +108,17 @@ public class BSLinkset { if (IsRoot(child)) { + // Cannot remove the root from a linkset. + return this; + } + + RemoveChildFromLinkset(child); + + /* Alternate implementation that destroys the linkset of the root is removed. + * This fails because items are added and removed from linksets to build shapes. + * Code left for reference. + if (IsRoot(child)) + { // if root of linkset, take the linkset apart while (m_children.Count > 0) { @@ -120,6 +133,7 @@ public class BSLinkset // Just removing a child from an existing linkset RemoveChildFromLinkset(child); } + */ } // The child is down to a linkset of just itself @@ -308,12 +322,16 @@ public class BSLinkset { m_children.Add(child); - BSPhysObject rootx = LinksetRoot; // capture the root as of now + BSPhysObject rootx = LinksetRoot; // capture the root and body as of now + BulletBody rootBodyx = LinksetRoot.BSBody; BSPhysObject childx = child; + BulletBody childBodyx = child.BSBody; + PhysicsScene.TaintedObject("AddChildToLinkset", delegate() { DetailLog("{0},AddChildToLinkset,taint,child={1}", LinksetRoot.LocalID, child.LocalID); - PhysicallyLinkAChildToRoot(rootx, childx); // build the physical binding between me and the child + // build the physical binding between me and the child + PhysicallyLinkAChildToRoot(rootx, rootBodyx, childx, childBodyx); }); } return; @@ -323,7 +341,7 @@ public class BSLinkset // This is not being called by the child so we have to make sure the child doesn't think // it's still connected to the linkset. // Normal OpenSimulator operation will never do this because other SceneObjectPart information - // has to be updated also (like pointer to prim's parent). + // also has to be updated (like pointer to prim's parent). private void RemoveChildFromOtherLinkset(BSPhysObject pchild) { pchild.Linkset = new BSLinkset(PhysicsScene, pchild); @@ -336,13 +354,15 @@ public class BSLinkset { if (m_children.Remove(child)) { - BSPhysObject rootx = LinksetRoot; // capture the root as of now + BSPhysObject rootx = LinksetRoot; // capture the root and body as of now + BulletBody rootBodyx = LinksetRoot.BSBody; BSPhysObject childx = child; + BulletBody childBodyx = child.BSBody; PhysicsScene.TaintedObject("RemoveChildFromLinkset", delegate() { DetailLog("{0},RemoveChildFromLinkset,taint,child={1}", LinksetRoot.LocalID, child.LocalID); - PhysicallyUnlinkAChildFromRoot(rootx, childx); + PhysicallyUnlinkAChildFromRoot(rootx, rootBodyx, childx, childBodyx); RecomputeLinksetConstraintVariables(); }); @@ -357,7 +377,8 @@ public class BSLinkset // Create a constraint between me (root of linkset) and the passed prim (the child). // Called at taint time! - private void PhysicallyLinkAChildToRoot(BSPhysObject rootPrim, BSPhysObject childPrim) + private void PhysicallyLinkAChildToRoot(BSPhysObject rootPrim, BulletBody rootBody, + BSPhysObject childPrim, BulletBody childBody) { // Zero motion for children so they don't interpolate childPrim.ZeroMotion(); @@ -371,16 +392,32 @@ public class BSLinkset // create a constraint that allows no freedom of movement between the two objects // http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818 - DetailLog("{0},PhysicallyLinkAChildToRoot,taint,root={1},child={2},rLoc={3},cLoc={4},midLoc={5}", - rootPrim.LocalID, rootPrim.LocalID, childPrim.LocalID, rootPrim.Position, childPrim.Position, midPoint); + DetailLog("{0},PhysicallyLinkAChildToRoot,taint,root={1},rBody={2},child={3},cBody={4},rLoc={5},cLoc={6},midLoc={7}", + rootPrim.LocalID, + rootPrim.LocalID, rootBody.ptr.ToString("X"), + childPrim.LocalID, childBody.ptr.ToString("X"), + rootPrim.Position, childPrim.Position, midPoint); + + // There is great subtlty in these paramters. Notice the check for a ptr of zero. + // We pass the BulletBody structure into the taint in order to capture the pointer + // of the body at the time of constraint creation. This doesn't work for the very first + // construction because there is no body yet. The body + // is constructed later at taint time. Thus we use the body address at time of the + // taint creation but, if it is zero, use what's in the prim at the moment. + // There is a possible race condition since shape can change without a taint call + // (like changing to a mesh that is already constructed). The fix for that would be + // to only change BSShape at taint time thus syncronizing these operations at + // the cost of efficiency and lag. BS6DofConstraint constrain = new BS6DofConstraint( - PhysicsScene.World, rootPrim.BSBody, childPrim.BSBody, + PhysicsScene.World, + rootBody.ptr == IntPtr.Zero ? rootPrim.BSBody : rootBody, + childBody.ptr == IntPtr.Zero ? childPrim.BSBody : childBody, midPoint, true, true ); /* NOTE: below is an attempt to build constraint with full frame computation, etc. - * Using the midpoint is easier since it lets the Bullet code use the transforms + * Using the midpoint is easier since it lets the Bullet code manipulate the transforms * of the objects. * Code left as a warning to future programmers. // ================================================================================== @@ -433,19 +470,26 @@ public class BSLinkset } // Remove linkage between myself and a particular child + // The root and child bodies are passed in because we need to remove the constraint between + // the bodies that were at unlink time. // Called at taint time! - private void PhysicallyUnlinkAChildFromRoot(BSPhysObject rootPrim, BSPhysObject childPrim) + private void PhysicallyUnlinkAChildFromRoot(BSPhysObject rootPrim, BulletBody rootBody, + BSPhysObject childPrim, BulletBody childBody) { - DetailLog("{0},PhysicallyUnlinkAChildFromRoot,taint,root={1},child={2}", rootPrim.LocalID, rootPrim.LocalID, childPrim.LocalID); + DetailLog("{0},PhysicallyUnlinkAChildFromRoot,taint,root={1},rBody={2},child={3},cBody={4}", + rootPrim.LocalID, + rootPrim.LocalID, rootBody.ptr.ToString("X"), + childPrim.LocalID, childBody.ptr.ToString("X")); // Find the constraint for this link and get rid of it from the overall collection and from my list - PhysicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.BSBody, childPrim.BSBody); + PhysicsScene.Constraints.RemoveAndDestroyConstraint(rootBody, childBody); // Make the child refresh its location BulletSimAPI.PushUpdate2(childPrim.BSBody.ptr); } - // Remove linkage between myself and any possible children I might have + /* + // Remove linkage between myself and any possible children I might have. // Called at taint time! private void PhysicallyUnlinkAllChildrenFromRoot(BSPhysObject rootPrim) { @@ -453,6 +497,7 @@ public class BSLinkset PhysicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.BSBody); } + */ // Invoke the detailed logger and output something if it's enabled. private void DetailLog(string msg, params Object[] args) diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs index 4f83adc..df95625 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs @@ -135,8 +135,11 @@ public abstract class BSPhysObject : PhysicsActor // collision event to make collision_end work. // Called at taint time from within the Step() function thus no locking problems // with CollisionCollection and ObjectsWithNoMoreCollisions. - public virtual void SendCollisions() + // Return 'true' if there were some actual collisions passed up + public virtual bool SendCollisions() { + bool ret = true; + // throttle the collisions to the number of milliseconds specified in the subscription int nowTime = PhysicsScene.SimulationNowTime; if (nowTime >= NextCollisionOkTime) @@ -148,7 +151,7 @@ public abstract class BSPhysObject : PhysicsActor if (CollisionCollection.Count == 0) { // If I have no collisions this time, remove me from the list of objects with collisions. - PhysicsScene.ObjectsWithNoMoreCollisions.Add(this); + ret = false; } // DetailLog("{0},{1}.SendCollisionUpdate,call,numCollisions={2}", LocalID, TypeName, CollisionCollection.Count); @@ -158,6 +161,7 @@ public abstract class BSPhysObject : PhysicsActor // Make sure we don't have a handle to that one and that a new one is used for next time. CollisionCollection = new CollisionEventUpdate(); } + return ret; } // Subscribe for collision events. diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index 68a153e..17ba85a 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs @@ -507,6 +507,9 @@ public sealed class BSPrim : BSPhysObject // Set up the object physicalness (does gravity and collisions move this object) MakeDynamic(IsStatic); + // Do any vehicle stuff + _vehicle.Refresh(); + // Arrange for collision events if the simulator wants them EnableCollisions(SubscribedEvents()); @@ -556,9 +559,8 @@ public sealed class BSPrim : BSPhysObject BulletSimAPI.UpdateInertiaTensor2(BSBody.ptr); // There can be special things needed for implementing linksets Linkset.MakeStatic(this); - // The activation state is 'sleeping' so Bullet will not try to act on it - BulletSimAPI.ForceActivationState2(BSBody.ptr, ActivationState.ISLAND_SLEEPING); - // BulletSimAPI.ForceActivationState2(BSBody.ptr, ActivationState.DISABLE_SIMULATION); + // The activation state is 'disabled' so Bullet will not try to act on it + BulletSimAPI.ForceActivationState2(BSBody.ptr, ActivationState.DISABLE_SIMULATION); BSBody.collisionFilter = CollisionFilterGroups.StaticObjectFilter; BSBody.collisionMask = CollisionFilterGroups.StaticObjectMask; @@ -577,7 +579,8 @@ public sealed class BSPrim : BSPhysObject // A dynamic object has mass IntPtr collisionShapePtr = BulletSimAPI.GetCollisionShape2(BSBody.ptr); - OMV.Vector3 inertia = BulletSimAPI.CalculateLocalInertia2(collisionShapePtr, Linkset.LinksetMass); + OMV.Vector3 inertia = BulletSimAPI.CalculateLocalInertia2(collisionShapePtr, Mass); + // OMV.Vector3 inertia = OMV.Vector3.Zero; BulletSimAPI.SetMassProps2(BSBody.ptr, _mass, inertia); BulletSimAPI.UpdateInertiaTensor2(BSBody.ptr); @@ -587,10 +590,12 @@ public sealed class BSPrim : BSPhysObject BulletSimAPI.SetSleepingThresholds2(BSBody.ptr, PhysicsScene.Params.linearSleepingThreshold, PhysicsScene.Params.angularSleepingThreshold); BulletSimAPI.SetContactProcessingThreshold2(BSBody.ptr, PhysicsScene.Params.contactProcessingThreshold); - // There can be special things needed for implementing linksets + // There can be special things needed for implementing linksets. Linkset.MakeDynamic(this); // Force activation of the object so Bullet will act on it. + // Must do the ForceActivationState2() to overcome the DISABLE_SIMULATION from static objects. + BulletSimAPI.ForceActivationState2(BSBody.ptr, ActivationState.ISLAND_SLEEPING); BulletSimAPI.Activate2(BSBody.ptr, true); BSBody.collisionFilter = CollisionFilterGroups.ObjectFilter; @@ -1457,9 +1462,16 @@ public sealed class BSPrim : BSPhysObject ShapeData shapeData; FillShapeInfo(out shapeData); + // Undo me from any possible linkset so, if body is rebuilt, the link will get restored. + // NOTE that the new linkset is not set. This saves the handle to the linkset + // so we can add ourselves back when shape mangling is complete. + Linkset.RemoveMeFromLinkset(this); + // Create the correct physical representation for this type of object. // Updates BSBody and BSShape with the new information. PhysicsScene.Shapes.GetBodyAndShape(forceRebuild, PhysicsScene.World, this, shapeData, _pbs); + + Linkset = Linkset.AddMeToLinkset(this); // Make sure the properties are set on the new object UpdatePhysicalParameters(); diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs index e8c628c..44a249c 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs @@ -544,12 +544,15 @@ public class BSScene : PhysicsScene, IPhysicsParameters // The above SendCollision's batch up the collisions on the objects. // Now push the collisions into the simulator. - // If the object is done colliding, it will add itself to the ObjectsWithNoMoreCollisions list. if (ObjectsWithCollisions.Count > 0) { foreach (BSPhysObject bsp in ObjectsWithCollisions) if (!m_avatars.Contains(bsp)) // don't call avatars twice - bsp.SendCollisions(); + if (!bsp.SendCollisions()) + { + // If the object is done colliding, see that it's removed from the colliding list + ObjectsWithNoMoreCollisions.Add(bsp); + } } // Objects that are done colliding are removed from the ObjectsWithCollisions list. diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs index aadb8d6..72c6df5 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs @@ -498,7 +498,8 @@ public class BSShapeCollection : IDisposable ulong newHullKey = ComputeShapeKey(shapeData, pbs, out lod); // if the hull hasn't changed, don't rebuild it - if (newHullKey == prim.BSShape.shapeKey) return false; + if (newHullKey == prim.BSShape.shapeKey && prim.BSShape.type == ShapeData.PhysicsShapeType.SHAPE_HULL) + return false; DetailLog("{0},BSShapeCollection.CreateGeomHull,create,oldKey={1},newKey={2}", prim.LocalID, prim.BSShape.shapeKey.ToString("X"), newHullKey.ToString("X")); @@ -508,11 +509,8 @@ public class BSShapeCollection : IDisposable newShape = CreatePhysicalHull(prim.PhysObjectName, newHullKey, pbs, shapeData.Size, lod); - if (!ReferenceShape(newShape)) - { - PhysicsScene.Logger.ErrorFormat("{0} Created new hull shape but one already exists: id={1}, key={2}, refCnt={3}", - LogHeader, shapeData.ID, newHullKey.ToString("X"), Hulls[newHullKey].referenceCount); - } + ReferenceShape(newShape); + // hulls are already scaled by the meshmerizer prim.Scale = new OMV.Vector3(1f, 1f, 1f); prim.BSShape = newShape; diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs index 50638d6..269c3d5 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs @@ -334,7 +334,8 @@ public class BSTerrainManager (uint)CollisionFilterGroups.TerrainMask); // Make sure the new shape is processed. - BulletSimAPI.Activate2(mapInfo.terrainBody.ptr, true); + // BulletSimAPI.Activate2(mapInfo.terrainBody.ptr, true); + BulletSimAPI.ForceActivationState2(mapInfo.terrainBody.ptr, ActivationState.DISABLE_SIMULATION); m_terrainModified = true; }; diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs index 6910050..2d65a35 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs @@ -369,16 +369,16 @@ public enum CollisionFilterGroups : uint BSolidFilter = 1 << 13, // The collsion filters and masked are defined in one place -- don't want them scattered - AvatarFilter = BDefaultFilter | BCharacterFilter | BSolidFilter, + AvatarFilter = BCharacterFilter, AvatarMask = BAllFilter, - ObjectFilter = BDefaultFilter | BSolidFilter, + ObjectFilter = BSolidFilter, ObjectMask = BAllFilter, - StaticObjectFilter = BDefaultFilter | BStaticFilter | BSolidFilter, + StaticObjectFilter = BStaticFilter, StaticObjectMask = BAllFilter, VolumeDetectFilter = BSensorTrigger, VolumeDetectMask = ~BSensorTrigger, TerrainFilter = BTerrainFilter, - TerrainMask = BAllFilter, + TerrainMask = BAllFilter & ~BStaticFilter, GroundPlaneFilter = BAllFilter, GroundPlaneMask = BAllFilter -- cgit v1.1 From 5781d4d52d0e4c761737fd9b1382365589a4717e Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Thu, 27 Sep 2012 09:19:42 -0700 Subject: BulletSim: remove the unused body management code from BSPrim. There is no going back now. --- OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | 374 ------------------------- 1 file changed, 374 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index 17ba85a..e65e42b 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs @@ -27,8 +27,6 @@ // Uncomment this it enable code to do all shape an body memory management // in the C# code. -#define CSHARP_BODY_MANAGEMENT - using System; using System.Reflection; using System.Collections.Generic; @@ -474,14 +472,8 @@ public sealed class BSPrim : BSPhysObject // Called at taint-time!! private void SetObjectDynamic(bool forceRebuild) { -#if CSHARP_BODY_MANAGEMENT // Recreate the physical object if necessary CreateGeomAndObject(forceRebuild); -#else - // If it's becoming dynamic, it will need hullness - VerifyCorrectPhysicalShape(); - UpdatePhysicalParameters(); -#endif // CSHARP_BODY_MANAGEMENT } // Convert the simulator's physical properties into settings on BulletSim objects. @@ -498,11 +490,6 @@ public sealed class BSPrim : BSPhysObject // This is a NOOP if the object is not in the world (BulletSim and Bullet ignore objects not found). BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, BSBody.ptr); -#if !CSHARP_BODY_MANAGEMENT - // Make solid or not (do things bounce off or pass through this object) - // This is done first because it can change the collisionObject type. - MakeSolid(IsSolid); -#endif // !CSHARP_BODY_MANAGEMENT // Set up the object physicalness (does gravity and collisions move this object) MakeDynamic(IsStatic); @@ -513,10 +500,8 @@ public sealed class BSPrim : BSPhysObject // Arrange for collision events if the simulator wants them EnableCollisions(SubscribedEvents()); -#if CSHARP_BODY_MANAGEMENT // Make solid or not (do things bounce off or pass through this object). MakeSolid(IsSolid); -#endif // CSHARP_BODY_MANAGEMENT BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, BSBody.ptr); @@ -609,7 +594,6 @@ public sealed class BSPrim : BSPhysObject // the functions after this one set up the state of a possibly newly created collision body. private void MakeSolid(bool makeSolid) { -#if CSHARP_BODY_MANAGEMENT CollisionObjectTypes bodyType = (CollisionObjectTypes)BulletSimAPI.GetBodyType2(BSBody.ptr); if (makeSolid) { @@ -630,49 +614,6 @@ public sealed class BSPrim : BSPhysObject BSBody.collisionFilter = CollisionFilterGroups.VolumeDetectFilter; BSBody.collisionMask = CollisionFilterGroups.VolumeDetectMask; } -#else - // If doing the body management in C#, all this logic is in CSShapeCollection.CreateObject(). - CollisionObjectTypes bodyType = (CollisionObjectTypes)BulletSimAPI.GetBodyType2(BSBody.ptr); - if (makeSolid) - { - if ((bodyType & CollisionObjectTypes.CO_RIGID_BODY) == 0) - { - // Solid things are made out of rigid bodies. Remove this old body from the world - // and use this shape in a new rigid body. - BulletBody oldBody = BSBody; - // Zero out the pointer to the shape in the old body so the shape will not get freed - BSShape.Ptr = BulletSimAPI.GetCollisionShape2(oldBody.Ptr); - BulletSimAPI.SetCollisionShape2(PhysicsScene.World.Ptr, oldBody.Ptr, IntPtr.Zero); - // Get rid of the old body and remove it from BulletSim's object list - BulletSimAPI.DestroyObject(PhysicsScene.WorldID, LocalID); - - // Create the new body with the shape - BSBody = new BulletBody(LocalID, BulletSimAPI.CreateBodyFromShape2(PhysicsScene.World.Ptr, BSShape.Ptr, _position, _orientation)); - CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(BSBody.Ptr, CollisionFlags.CF_NO_CONTACT_RESPONSE); - DetailLog("{0},BSPrim.MakeSolid:rigidBody,body={1},shape={2}", LocalID, BSBody, BSShape); - } - } - else - { - if ((bodyType & CollisionObjectTypes.CO_GHOST_OBJECT) == 0) - { - // Non-solid things are made out of ghost objects. Remove this old body from the world - // and use this shape in a new rigid body. - BulletBody oldBody = BSBody; - - // Zero out the pointer to the shape in the old body so the shape will not get freed - BSShape.Ptr = BulletSimAPI.GetCollisionShape2(oldBody.Ptr); - BulletSimAPI.SetCollisionShape2(PhysicsScene.World.Ptr, oldBody.Ptr, IntPtr.Zero); - // Get rid of the old body and remove it from BulletSim's object list - BulletSimAPI.DestroyObject(PhysicsScene.WorldID, LocalID); - - BSBody = new BulletBody(LocalID, - BulletSimAPI.CreateGhostFromShape2(PhysicsScene.World.Ptr, BSShape.Ptr, _position, _orientation)); - CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(BSBody.Ptr, CollisionFlags.CF_NO_CONTACT_RESPONSE); - DetailLog("{0},BSPrim.MakeGhostBody,body={1},shape={2}", LocalID, BSBody, BSShape); - } - } -#endif } // Turn on or off the flag controlling whether collision events are returned to the simulator. @@ -1139,300 +1080,6 @@ public sealed class BSPrim : BSPhysObject }// end CalculateMass #endregion Mass Calculation -#if !CSHARP_BODY_MANAGEMENT - // Create the geometry information in Bullet for later use. - // The objects needs a hull if it's physical otherwise a mesh is enough. - // No locking here because this is done when we know physics is not simulating. - // if 'forceRebuild' is true, the geometry is rebuilt. Otherwise a previously built version is used. - // Returns 'true' if the geometry was rebuilt. - // Called at taint-time! - private bool CreateGeom(bool forceRebuild) - { - bool ret = false; - bool haveShape = false; - - // If the prim attributes are simple, this could be a simple Bullet native shape - if ( - // if the basic shape is a cube or a sphere... - ((_pbs.ProfileShape == ProfileShape.Square && _pbs.PathCurve == (byte)Extrusion.Straight) - || (_pbs.ProfileShape == ProfileShape.HalfCircle && _pbs.PathCurve == (byte)Extrusion.Curve1 - /* && _pbs.Scale.X == _pbs.Scale.Y && _pbs.Scale.Y == _pbs.Scale.Z */ )) - // ... and we are not doing sculpty meshes... - && (_pbs.SculptEntry && !PhysicsScene.ShouldMeshSculptedPrim) - // ... or this is a 'simple' shape... - || (_pbs.ProfileBegin == 0 && _pbs.ProfileEnd == 0 - && _pbs.ProfileHollow == 0 - && _pbs.PathTwist == 0 && _pbs.PathTwistBegin == 0 - && _pbs.PathBegin == 0 && _pbs.PathEnd == 0 - && _pbs.PathTaperX == 0 && _pbs.PathTaperY == 0 - && _pbs.PathScaleX == 100 && _pbs.PathScaleY == 100 - && _pbs.PathShearX == 0 && _pbs.PathShearY == 0) ) - // ... then this might be representable as a native Bullet collision shape - { - if (_pbs.ProfileShape == ProfileShape.HalfCircle && _pbs.PathCurve == (byte)Extrusion.Curve1) - { - haveShape = true; - if (forceRebuild || (_shapeType != ShapeData.PhysicsShapeType.SHAPE_SPHERE)) - { - DetailLog("{0},BSPrim.CreateGeom,sphere (force={1}", LocalID, forceRebuild); - _shapeType = ShapeData.PhysicsShapeType.SHAPE_SPHERE; - _meshKey = (ulong)ShapeData.FixedShapeKey.KEY_SPHERE; - // Bullet native objects are scaled by the Bullet engine so pass the size in - _scale = _size; - // TODO: do we need to check for and destroy a mesh or hull that might have been left from before? - ret = true; - } - } - else - { - // m_log.DebugFormat("{0}: CreateGeom: Defaulting to box. lid={1}, type={2}, size={3}", LogHeader, LocalID, _shapeType, _size); - haveShape = true; - if (forceRebuild || (_shapeType != ShapeData.PhysicsShapeType.SHAPE_BOX)) - { - DetailLog("{0},BSPrim.CreateGeom,box (force={1})", LocalID, forceRebuild); - _shapeType = ShapeData.PhysicsShapeType.SHAPE_BOX; - _meshKey = (ulong)ShapeData.FixedShapeKey.KEY_BOX; - _scale = _size; - // TODO: do we need to check for and destroy a mesh or hull that might have been left from before? - ret = true; - } - } - } - // If a simple shape isn't happening, create a mesh and possibly a hull - if (!haveShape) - { - if (IsPhysical) - { - if (forceRebuild || _hullKey == 0) - { - // physical objects require a hull for interaction. - // This also creates the mesh if it doesn't already exist - ret = CreateGeomHull(); - } - } - else - { - if (forceRebuild || _meshKey == 0) - { - // Static (non-physical) objects only need a mesh for bumping into - ret = CreateGeomMesh(); - } - } - } - - return ret; - } - - // No locking here because this is done when we know physics is not simulating - // Returns 'true' of a mesh was actually rebuild (we could also have one of these specs). - // Called at taint-time! - private bool CreateGeomMesh() - { - // level of detail based on size and type of the object - float lod = PhysicsScene.MeshLOD; - if (_pbs.SculptEntry) - lod = PhysicsScene.SculptLOD; - float maxAxis = Math.Max(_size.X, Math.Max(_size.Y, _size.Z)); - if (maxAxis > PhysicsScene.MeshMegaPrimThreshold) - lod = PhysicsScene.MeshMegaPrimLOD; - - ulong newMeshKey = (ulong)_pbs.GetMeshKey(_size, lod); - // m_log.DebugFormat("{0}: CreateGeomMesh: lID={1}, oldKey={2}, newKey={3}", LogHeader, LocalID, _meshKey, newMeshKey); - - // if this new shape is the same as last time, don't recreate the mesh - if (_meshKey == newMeshKey) return false; - - DetailLog("{0},BSPrim.CreateGeomMesh,create,key={1}", LocalID, newMeshKey); - // Since we're recreating new, get rid of any previously generated shape - if (_meshKey != 0) - { - // m_log.DebugFormat("{0}: CreateGeom: deleting old mesh. lID={1}, Key={2}", LogHeader, LocalID, _meshKey); - DetailLog("{0},BSPrim.CreateGeomMesh,deleteOld,key={1}", LocalID, _meshKey); - BulletSimAPI.DestroyMesh(PhysicsScene.WorldID, _meshKey); - _mesh = null; - _meshKey = 0; - } - - _meshKey = newMeshKey; - // always pass false for physicalness as this creates some sort of bounding box which we don't need - _mesh = PhysicsScene.mesher.CreateMesh(PhysObjectName, _pbs, _size, lod, false); - - int[] indices = _mesh.getIndexListAsInt(); - List vertices = _mesh.getVertexList(); - - float[] verticesAsFloats = new float[vertices.Count * 3]; - int vi = 0; - foreach (OMV.Vector3 vv in vertices) - { - verticesAsFloats[vi++] = vv.X; - verticesAsFloats[vi++] = vv.Y; - verticesAsFloats[vi++] = vv.Z; - } - - // m_log.DebugFormat("{0}: CreateGeomMesh: calling CreateMesh. lid={1}, key={2}, indices={3}, vertices={4}", - // LogHeader, LocalID, _meshKey, indices.Length, vertices.Count); - BulletSimAPI.CreateMesh(PhysicsScene.WorldID, _meshKey, indices.GetLength(0), indices, - vertices.Count, verticesAsFloats); - - _shapeType = ShapeData.PhysicsShapeType.SHAPE_MESH; - // meshes are already scaled by the meshmerizer - _scale = new OMV.Vector3(1f, 1f, 1f); - return true; - } - - // No locking here because this is done when we know physics is not simulating - // Returns 'true' of a mesh was actually rebuild (we could also have one of these specs). - private bool CreateGeomHull() - { - float lod = _pbs.SculptEntry ? PhysicsScene.SculptLOD : PhysicsScene.MeshLOD; - ulong newHullKey = (ulong)_pbs.GetMeshKey(_size, lod); - // m_log.DebugFormat("{0}: CreateGeomHull: lID={1}, oldKey={2}, newKey={3}", LogHeader, LocalID, _hullKey, newHullKey); - - // if the hull hasn't changed, don't rebuild it - if (newHullKey == _hullKey) return false; - - DetailLog("{0},BSPrim.CreateGeomHull,create,oldKey={1},newKey={2}", LocalID, _hullKey, newHullKey); - - // Since we're recreating new, get rid of any previously generated shape - if (_hullKey != 0) - { - // m_log.DebugFormat("{0}: CreateGeom: deleting old hull. Key={1}", LogHeader, _hullKey); - DetailLog("{0},BSPrim.CreateGeomHull,deleteOldHull,key={1}", LocalID, _hullKey); - BulletSimAPI.DestroyHull(PhysicsScene.WorldID, _hullKey); - _hullKey = 0; - } - - _hullKey = newHullKey; - - // Make sure the underlying mesh exists and is correct - CreateGeomMesh(); - - int[] indices = _mesh.getIndexListAsInt(); - List vertices = _mesh.getVertexList(); - - //format conversion from IMesh format to DecompDesc format - List convIndices = new List(); - List convVertices = new List(); - for (int ii = 0; ii < indices.GetLength(0); ii++) - { - convIndices.Add(indices[ii]); - } - foreach (OMV.Vector3 vv in vertices) - { - convVertices.Add(new float3(vv.X, vv.Y, vv.Z)); - } - - // setup and do convex hull conversion - _hulls = new List(); - DecompDesc dcomp = new DecompDesc(); - dcomp.mIndices = convIndices; - dcomp.mVertices = convVertices; - ConvexBuilder convexBuilder = new ConvexBuilder(HullReturn); - // create the hull into the _hulls variable - convexBuilder.process(dcomp); - - // Convert the vertices and indices for passing to unmanaged. - // The hull information is passed as a large floating point array. - // The format is: - // convHulls[0] = number of hulls - // convHulls[1] = number of vertices in first hull - // convHulls[2] = hull centroid X coordinate - // convHulls[3] = hull centroid Y coordinate - // convHulls[4] = hull centroid Z coordinate - // convHulls[5] = first hull vertex X - // convHulls[6] = first hull vertex Y - // convHulls[7] = first hull vertex Z - // convHulls[8] = second hull vertex X - // ... - // convHulls[n] = number of vertices in second hull - // convHulls[n+1] = second hull centroid X coordinate - // ... - // - // TODO: is is very inefficient. Someday change the convex hull generator to return - // data structures that do not need to be converted in order to pass to Bullet. - // And maybe put the values directly into pinned memory rather than marshaling. - int hullCount = _hulls.Count; - int totalVertices = 1; // include one for the count of the hulls - foreach (ConvexResult cr in _hulls) - { - totalVertices += 4; // add four for the vertex count and centroid - totalVertices += cr.HullIndices.Count * 3; // we pass just triangles - } - float[] convHulls = new float[totalVertices]; - - convHulls[0] = (float)hullCount; - int jj = 1; - foreach (ConvexResult cr in _hulls) - { - // copy vertices for index access - float3[] verts = new float3[cr.HullVertices.Count]; - int kk = 0; - foreach (float3 ff in cr.HullVertices) - { - verts[kk++] = ff; - } - - // add to the array one hull's worth of data - convHulls[jj++] = cr.HullIndices.Count; - convHulls[jj++] = 0f; // centroid x,y,z - convHulls[jj++] = 0f; - convHulls[jj++] = 0f; - foreach (int ind in cr.HullIndices) - { - convHulls[jj++] = verts[ind].x; - convHulls[jj++] = verts[ind].y; - convHulls[jj++] = verts[ind].z; - } - } - - // create the hull definition in Bullet - // m_log.DebugFormat("{0}: CreateGeom: calling CreateHull. lid={1}, key={2}, hulls={3}", LogHeader, LocalID, _hullKey, hullCount); - BulletSimAPI.CreateHull(PhysicsScene.WorldID, _hullKey, hullCount, convHulls); - _shapeType = ShapeData.PhysicsShapeType.SHAPE_HULL; - // meshes are already scaled by the meshmerizer - _scale = new OMV.Vector3(1f, 1f, 1f); - DetailLog("{0},BSPrim.CreateGeomHull,done", LocalID); - return true; - } - - // Callback from convex hull creater with a newly created hull. - // Just add it to the collection of hulls for this shape. - private void HullReturn(ConvexResult result) - { - _hulls.Add(result); - return; - } - - private void VerifyCorrectPhysicalShape() - { - if (!IsStatic) - { - // if not static, it will need a hull to efficiently collide with things - if (_hullKey == 0) - { - CreateGeomAndObject(false); - } - - } - } - - // Create an object in Bullet if it has not already been created - // No locking here because this is done when the physics engine is not simulating - // Returns 'true' if an object was actually created. - private bool CreateObject() - { - // this routine is called when objects are rebuilt. - - // the mesh or hull must have already been created in Bullet - ShapeData shape; - FillShapeInfo(out shape); - // m_log.DebugFormat("{0}: CreateObject: lID={1}, shape={2}", LogHeader, LocalID, shape.Type); - bool ret = BulletSimAPI.CreateObject(PhysicsScene.WorldID, shape); - - return ret; - } -#endif // !CSHARP_BODY_MANAGEMENT - // Copy prim's info into the BulletSim shape description structure public void FillShapeInfo(out ShapeData shape) { @@ -1458,7 +1105,6 @@ public sealed class BSPrim : BSPhysObject // Called at taint-time!!! private void CreateGeomAndObject(bool forceRebuild) { -#if CSHARP_BODY_MANAGEMENT ShapeData shapeData; FillShapeInfo(out shapeData); @@ -1475,26 +1121,6 @@ public sealed class BSPrim : BSPhysObject // Make sure the properties are set on the new object UpdatePhysicalParameters(); -#else - // m_log.DebugFormat("{0}: CreateGeomAndObject. lID={1}, force={2}", LogHeader, LocalID, forceRebuild); - // Create the geometry that will make up the object - if (CreateGeom(forceRebuild)) - { - // Create the object and place it into the world - CreateObject(); - - // the CreateObject() may have recreated the rigid body. Make sure we have the latest address. - BSBody = new BulletBody(LocalID, BulletSimAPI.GetBodyHandle2(PhysicsScene.World.Ptr, LocalID)); - BSShape = new BulletShape(BulletSimAPI.GetCollisionShape2(BSBody.Ptr), _shapeType); - BSShape.shapeKey = _meshKey; - DetailLog("{0},BSPrim.CreateGeomAndObject,body={1},shape={2}", LocalID, BSBody, BSShape); - - // Make sure the properties are set on the new object - UpdatePhysicalParameters(); - } - - -#endif // CSHARP_BODY_MANAGEMENT return; } -- cgit v1.1 From 7b65985047bdf0789fe3eccf8f515279f362abf1 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Thu, 27 Sep 2012 09:31:33 -0700 Subject: BulletSim: remove the trailing spaces from lines to make git happier --- .../Region/Physics/BulletSPlugin/BSCharacter.cs | 185 +++++++++--------- OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs | 14 +- OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs | 30 +-- .../Region/Physics/BulletSPlugin/BSPhysObject.cs | 2 +- OpenSim/Region/Physics/BulletSPlugin/BSPlugin.cs | 4 +- OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | 212 ++++++++++----------- OpenSim/Region/Physics/BulletSPlugin/BSScene.cs | 26 +-- .../Physics/BulletSPlugin/BSShapeCollection.cs | 42 ++-- .../Physics/BulletSPlugin/BSTerrainManager.cs | 32 ++-- .../Region/Physics/BulletSPlugin/BulletSimAPI.cs | 4 +- 10 files changed, 275 insertions(+), 276 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs index 961bcde..b88ec3c 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs @@ -122,7 +122,6 @@ public class BSCharacter : BSPhysObject BulletSimAPI.SetCollisionFilterMask2(BSBody.ptr, (uint)CollisionFilterGroups.AvatarFilter, (uint)CollisionFilterGroups.AvatarMask); }); - return; } @@ -141,8 +140,8 @@ public class BSCharacter : BSPhysObject base.RequestPhysicsterseUpdate(); } // No one calls this method so I don't know what it could possibly mean - public override bool Stopped { - get { return false; } + public override bool Stopped { + get { return false; } } public override OMV.Vector3 Size { get @@ -151,7 +150,7 @@ public class BSCharacter : BSPhysObject return new OMV.Vector3(_scale.X * 2, _scale.Y * 2, _scale.Z); } - set { + set { // When an avatar's size is set, only the height is changed // and that really only depends on the radius. _size = value; @@ -166,19 +165,19 @@ public class BSCharacter : BSPhysObject BulletSimAPI.SetObjectScaleMass(PhysicsScene.WorldID, LocalID, _scale, _mass, true); }); - } + } } - public override PrimitiveBaseShape Shape { - set { _pbs = value; - } + public override PrimitiveBaseShape Shape { + set { _pbs = value; + } } - public override bool Grabbed { - set { _grabbed = value; - } + public override bool Grabbed { + set { _grabbed = value; + } } - public override bool Selected { - set { _selected = value; - } + public override bool Selected { + set { _selected = value; + } } public override void CrossingFailure() { return; } public override void link(PhysicsActor obj) { return; } @@ -203,11 +202,11 @@ public class BSCharacter : BSPhysObject public override void LockAngularMotion(OMV.Vector3 axis) { return; } - public override OMV.Vector3 Position { + public override OMV.Vector3 Position { get { // _position = BulletSimAPI.GetObjectPosition(Scene.WorldID, _localID); - return _position; - } + return _position; + } set { _position = value; PositionSanityCheck(); @@ -217,7 +216,7 @@ public class BSCharacter : BSPhysObject DetailLog("{0},BSCharacter.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation); BulletSimAPI.SetObjectTranslation(PhysicsScene.WorldID, LocalID, _position, _orientation); }); - } + } } // Check that the current position is sane and, if not, modify the position to make it so. @@ -226,7 +225,7 @@ public class BSCharacter : BSPhysObject private bool PositionSanityCheck() { bool ret = false; - + // If below the ground, move the avatar up float terrainHeight = PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(_position); if (Position.Z < terrainHeight) @@ -260,17 +259,17 @@ public class BSCharacter : BSPhysObject return ret; } - public override float Mass { - get { - return _mass; - } + public override float Mass { + get { + return _mass; + } } // used when we only want this prim's mass and not the linkset thing public override float MassRaw { get {return _mass; } } - public override OMV.Vector3 Force { - get { return _force; } + public override OMV.Vector3 Force { + get { return _force; } set { _force = value; // m_log.DebugFormat("{0}: Force = {1}", LogHeader, _force); @@ -279,12 +278,12 @@ public class BSCharacter : BSPhysObject DetailLog("{0},BSCharacter.setForce,taint,force={1}", LocalID, _force); BulletSimAPI.SetObjectForce(PhysicsScene.WorldID, LocalID, _force); }); - } + } } - public override int VehicleType { - get { return 0; } - set { return; } + public override int VehicleType { + get { return 0; } + set { return; } } public override void VehicleFloatParam(int param, float value) { } public override void VehicleVectorParam(int param, OMV.Vector3 value) {} @@ -296,8 +295,8 @@ public class BSCharacter : BSPhysObject public override OMV.Vector3 GeometricCenter { get { return OMV.Vector3.Zero; } } public override OMV.Vector3 CenterOfMass { get { return OMV.Vector3.Zero; } } - public override OMV.Vector3 Velocity { - get { return _velocity; } + public override OMV.Vector3 Velocity { + get { return _velocity; } set { _velocity = value; // m_log.DebugFormat("{0}: set velocity = {1}", LogHeader, _velocity); @@ -306,24 +305,24 @@ public class BSCharacter : BSPhysObject DetailLog("{0},BSCharacter.setVelocity,taint,vel={1}", LocalID, _velocity); BulletSimAPI.SetObjectVelocity(PhysicsScene.WorldID, LocalID, _velocity); }); - } + } } - public override OMV.Vector3 Torque { - get { return _torque; } - set { _torque = value; - } + public override OMV.Vector3 Torque { + get { return _torque; } + set { _torque = value; + } } - public override float CollisionScore { - get { return _collisionScore; } - set { _collisionScore = value; - } + public override float CollisionScore { + get { return _collisionScore; } + set { _collisionScore = value; + } } - public override OMV.Vector3 Acceleration { + public override OMV.Vector3 Acceleration { get { return _acceleration; } set { _acceleration = value; } } - public override OMV.Quaternion Orientation { - get { return _orientation; } + public override OMV.Quaternion Orientation { + get { return _orientation; } set { _orientation = value; // m_log.DebugFormat("{0}: set orientation to {1}", LogHeader, _orientation); @@ -332,98 +331,98 @@ public class BSCharacter : BSPhysObject // _position = BulletSimAPI.GetObjectPosition(Scene.WorldID, _localID); BulletSimAPI.SetObjectTranslation(PhysicsScene.WorldID, LocalID, _position, _orientation); }); - } + } } - public override int PhysicsActorType { - get { return _physicsActorType; } - set { _physicsActorType = value; - } + public override int PhysicsActorType { + get { return _physicsActorType; } + set { _physicsActorType = value; + } } - public override bool IsPhysical { - get { return _isPhysical; } + public override bool IsPhysical { + get { return _isPhysical; } set { _isPhysical = value; - } + } } - public override bool Flying { - get { return _flying; } + public override bool Flying { + get { return _flying; } set { _flying = value; // simulate flying by changing the effect of gravity this.Buoyancy = ComputeBuoyancyFromFlying(_flying); - } + } } // Flying is implimented by changing the avatar's buoyancy. // Would this be done better with a vehicle type? private float ComputeBuoyancyFromFlying(bool ifFlying) { return ifFlying ? 1f : 0f; } - public override bool - SetAlwaysRun { - get { return _setAlwaysRun; } - set { _setAlwaysRun = value; } + public override bool + SetAlwaysRun { + get { return _setAlwaysRun; } + set { _setAlwaysRun = value; } } - public override bool ThrottleUpdates { - get { return _throttleUpdates; } - set { _throttleUpdates = value; } + public override bool ThrottleUpdates { + get { return _throttleUpdates; } + set { _throttleUpdates = value; } } public override bool IsColliding { - get { return (CollidingStep == PhysicsScene.SimulationStep); } - set { _isColliding = value; } + get { return (CollidingStep == PhysicsScene.SimulationStep); } + set { _isColliding = value; } } public override bool CollidingGround { - get { return (CollidingGroundStep == PhysicsScene.SimulationStep); } - set { CollidingGround = value; } + get { return (CollidingGroundStep == PhysicsScene.SimulationStep); } + set { CollidingGround = value; } } - public override bool CollidingObj { - get { return _collidingObj; } - set { _collidingObj = value; } + public override bool CollidingObj { + get { return _collidingObj; } + set { _collidingObj = value; } } - public override bool FloatOnWater { - set { _floatOnWater = value; } + public override bool FloatOnWater { + set { _floatOnWater = value; } } - public override OMV.Vector3 RotationalVelocity { - get { return _rotationalVelocity; } - set { _rotationalVelocity = value; } + public override OMV.Vector3 RotationalVelocity { + get { return _rotationalVelocity; } + set { _rotationalVelocity = value; } } - public override bool Kinematic { - get { return _kinematic; } - set { _kinematic = value; } + public override bool Kinematic { + get { return _kinematic; } + set { _kinematic = value; } } // neg=fall quickly, 0=1g, 1=0g, pos=float up - public override float Buoyancy { - get { return _buoyancy; } - set { _buoyancy = value; + public override float Buoyancy { + get { return _buoyancy; } + set { _buoyancy = value; PhysicsScene.TaintedObject("BSCharacter.setBuoyancy", delegate() { DetailLog("{0},BSCharacter.setBuoyancy,taint,buoy={1}", LocalID, _buoyancy); BulletSimAPI.SetObjectBuoyancy(PhysicsScene.WorldID, LocalID, _buoyancy); }); - } + } } // Used for MoveTo - public override OMV.Vector3 PIDTarget { - set { _PIDTarget = value; } + public override OMV.Vector3 PIDTarget { + set { _PIDTarget = value; } } - public override bool PIDActive { - set { _usePID = value; } + public override bool PIDActive { + set { _usePID = value; } } - public override float PIDTau { - set { _PIDTau = value; } + public override float PIDTau { + set { _PIDTau = value; } } // Used for llSetHoverHeight and maybe vehicle height // Hover Height will override MoveTo target's Z - public override bool PIDHoverActive { + public override bool PIDHoverActive { set { _useHoverPID = value; } } - public override float PIDHoverHeight { + public override float PIDHoverHeight { set { _PIDHoverHeight = value; } } - public override PIDHoverType PIDHoverType { + public override PIDHoverType PIDHoverType { set { _PIDHoverType = value; } } - public override float PIDHoverTau { + public override float PIDHoverTau { set { _PIDHoverTao = value; } } @@ -433,7 +432,7 @@ public class BSCharacter : BSPhysObject public override float APIDStrength { set { return; } } public override float APIDDamping { set { return; } } - public override void AddForce(OMV.Vector3 force, bool pushforce) { + public override void AddForce(OMV.Vector3 force, bool pushforce) { if (force.IsFinite()) { _force.X += force.X; @@ -453,9 +452,9 @@ public class BSCharacter : BSPhysObject //m_lastUpdateSent = false; } - public override void AddAngularForce(OMV.Vector3 force, bool pushforce) { + public override void AddAngularForce(OMV.Vector3 force, bool pushforce) { } - public override void SetMomentum(OMV.Vector3 momentum) { + public override void SetMomentum(OMV.Vector3 momentum) { } private void ComputeAvatarScale(OMV.Vector3 size) diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs index cf33d0e..65b38d6 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs @@ -491,7 +491,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin // remember the position so next step we can limit absolute movement effects m_lastPositionVector = Prim.Position; - VDetailLog("{0},BSDynamics.Step,done,pos={1},force={2},velocity={3},angvel={4}", + VDetailLog("{0},BSDynamics.Step,done,pos={1},force={2},velocity={3},angvel={4}", Prim.LocalID, Prim.Position, Prim.Force, Prim.Velocity, Prim.RotationalVelocity); }// end Step @@ -511,8 +511,8 @@ namespace OpenSim.Region.Physics.BulletSPlugin Vector3 addAmount = (m_linearMotorDirection - m_lastLinearVelocityVector)/(m_linearMotorTimescale / pTimestep); // lastLinearVelocityVector is the current body velocity vector // RA: Not sure what the *10 is for. A correction for pTimestep? - // m_lastLinearVelocityVector += (addAmount*10); - m_lastLinearVelocityVector += addAmount; + // m_lastLinearVelocityVector += (addAmount*10); + m_lastLinearVelocityVector += addAmount; // Limit the velocity vector to less than the last set linear motor direction if (Math.Abs(m_lastLinearVelocityVector.X) > Math.Abs(m_linearMotorDirectionLASTSET.X)) @@ -695,7 +695,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin Vector3 keepFraction = Vector3.One - (Vector3.One / (m_linearFrictionTimescale / pTimestep)); m_lastLinearVelocityVector *= keepFraction; - VDetailLog("{0},MoveLinear,done,lmDir={1},lmVel={2},newVel={3},grav={4},1Mdecay={5}", + VDetailLog("{0},MoveLinear,done,lmDir={1},lmVel={2},newVel={3},grav={4},1Mdecay={5}", Prim.LocalID, m_linearMotorDirection, m_lastLinearVelocityVector, m_newVelocity, grav, keepFraction); } // end MoveLinear() @@ -728,7 +728,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin m_angularMotorVelocity.Y += (m_angularMotorDirection.Y - m_angularMotorVelocity.Y) / (m_angularMotorTimescale / pTimestep); m_angularMotorVelocity.Z += (m_angularMotorDirection.Z - m_angularMotorVelocity.Z) / (m_angularMotorTimescale / pTimestep); - VDetailLog("{0},MoveAngular,angularMotorApply,apply={1},angTScale={2},timeStep={3},origvel={4},dir={5},vel={6}", + VDetailLog("{0},MoveAngular,angularMotorApply,apply={1},angTScale={2},timeStep={3},origvel={4},dir={5},vel={6}", Prim.LocalID, m_angularMotorApply, m_angularMotorTimescale, pTimestep, origAngularVelocity, m_angularMotorDirection, m_angularMotorVelocity); // This is done so that if script request rate is less than phys frame rate the expected @@ -779,7 +779,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin vertattr.X += bounce * angularVelocity.X; vertattr.Y += bounce * angularVelocity.Y; - VDetailLog("{0},MoveAngular,verticalAttraction,verterr={1},bounce={2},vertattr={3}", + VDetailLog("{0},MoveAngular,verticalAttraction,verterr={1},bounce={2},vertattr={3}", Prim.LocalID, verterr, bounce, vertattr); } // else vertical attractor is off @@ -792,7 +792,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin // Sum velocities m_lastAngularVelocity = m_angularMotorVelocity + vertattr; // + bank + deflection - + if ((m_flags & (VehicleFlag.NO_DEFLECTION_UP)) != 0) { m_lastAngularVelocity.X = 0; diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs index 6967108..b0cc63c 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs @@ -53,9 +53,9 @@ public class BSLinkset // We keep the prim's mass in the linkset structure since it could be dependent on other prims private float m_mass; - public float LinksetMass - { - get + public float LinksetMass + { + get { m_mass = ComputeLinksetMass(); return m_mass; @@ -77,7 +77,7 @@ public class BSLinkset // A simple linkset of one (no children) LinksetID = m_nextLinksetID++; // We create LOTS of linksets. - if (m_nextLinksetID <= 0) + if (m_nextLinksetID <= 0) m_nextLinksetID = 1; PhysicsScene = scene; LinksetRoot = parent; @@ -276,7 +276,7 @@ public class BSLinkset BSConstraint constrain; if (PhysicsScene.Constraints.TryGetConstraint(LinksetRoot.BSBody, child.BSBody, out constrain)) { - // DetailLog("{0},BSLinkset.RecomputeLinksetConstraintVariables,taint,child={1},mass={2},A={3},B={4}", + // DetailLog("{0},BSLinkset.RecomputeLinksetConstraintVariables,taint,child={1},mass={2},A={3},B={4}", // LinksetRoot.LocalID, child.LocalID, linksetMass, constrain.Body1.ID, constrain.Body2.ID); constrain.RecomputeConstraintVariables(linksetMass); } @@ -392,14 +392,14 @@ public class BSLinkset // create a constraint that allows no freedom of movement between the two objects // http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818 - DetailLog("{0},PhysicallyLinkAChildToRoot,taint,root={1},rBody={2},child={3},cBody={4},rLoc={5},cLoc={6},midLoc={7}", - rootPrim.LocalID, - rootPrim.LocalID, rootBody.ptr.ToString("X"), - childPrim.LocalID, childBody.ptr.ToString("X"), + DetailLog("{0},PhysicallyLinkAChildToRoot,taint,root={1},rBody={2},child={3},cBody={4},rLoc={5},cLoc={6},midLoc={7}", + rootPrim.LocalID, + rootPrim.LocalID, rootBody.ptr.ToString("X"), + childPrim.LocalID, childBody.ptr.ToString("X"), rootPrim.Position, childPrim.Position, midPoint); // There is great subtlty in these paramters. Notice the check for a ptr of zero. - // We pass the BulletBody structure into the taint in order to capture the pointer + // We pass the BulletBody structure into the taint in order to capture the pointer // of the body at the time of constraint creation. This doesn't work for the very first // construction because there is no body yet. The body // is constructed later at taint time. Thus we use the body address at time of the @@ -409,8 +409,8 @@ public class BSLinkset // to only change BSShape at taint time thus syncronizing these operations at // the cost of efficiency and lag. BS6DofConstraint constrain = new BS6DofConstraint( - PhysicsScene.World, - rootBody.ptr == IntPtr.Zero ? rootPrim.BSBody : rootBody, + PhysicsScene.World, + rootBody.ptr == IntPtr.Zero ? rootPrim.BSBody : rootBody, childBody.ptr == IntPtr.Zero ? childPrim.BSBody : childBody, midPoint, true, @@ -473,11 +473,11 @@ public class BSLinkset // The root and child bodies are passed in because we need to remove the constraint between // the bodies that were at unlink time. // Called at taint time! - private void PhysicallyUnlinkAChildFromRoot(BSPhysObject rootPrim, BulletBody rootBody, + private void PhysicallyUnlinkAChildFromRoot(BSPhysObject rootPrim, BulletBody rootBody, BSPhysObject childPrim, BulletBody childBody) { - DetailLog("{0},PhysicallyUnlinkAChildFromRoot,taint,root={1},rBody={2},child={3},cBody={4}", - rootPrim.LocalID, + DetailLog("{0},PhysicallyUnlinkAChildFromRoot,taint,root={1},rBody={2},child={3},cBody={4}", + rootPrim.LocalID, rootPrim.LocalID, rootBody.ptr.ToString("X"), childPrim.LocalID, childBody.ptr.ToString("X")); diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs index df95625..d9b738b 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs @@ -100,7 +100,7 @@ public abstract class BSPhysObject : PhysicsActor // The simulation step is telling this object about a collision. // Return 'true' if a collision was processed and should be sent up. // Called at taint time from within the Step() function - public virtual bool Collide(uint collidingWith, BSPhysObject collidee, + public virtual bool Collide(uint collidingWith, BSPhysObject collidee, OMV.Vector3 contactPoint, OMV.Vector3 contactNormal, float pentrationDepth) { bool ret = false; diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPlugin.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPlugin.cs index 0f027b8..20f5180 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPlugin.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPlugin.cs @@ -33,7 +33,7 @@ using OpenMetaverse; namespace OpenSim.Region.Physics.BulletSPlugin { /// - /// Entry for a port of Bullet (http://bulletphysics.org/) to OpenSim. + /// Entry for a port of Bullet (http://bulletphysics.org/) to OpenSim. /// This module interfaces to an unmanaged C++ library which makes the /// actual calls into the Bullet physics engine. /// The unmanaged library is found in opensim-libs::trunk/unmanaged/BulletSim/. @@ -62,7 +62,7 @@ public class BSPlugin : IPhysicsPlugin if (Util.IsWindows()) Util.LoadArchSpecificWindowsDll("BulletSim.dll"); // If not Windows, loading is performed by the - // Mono loader as specified in + // Mono loader as specified in // "bin/Physics/OpenSim.Region.Physics.BulletSPlugin.dll.config". _mScene = new BSScene(sceneIdentifier); diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index e65e42b..8688485 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs @@ -158,12 +158,12 @@ public sealed class BSPrim : BSPhysObject BulletSimAPI.DestroyObject(PhysicsScene.WorldID, LocalID); }); } - - public override bool Stopped { - get { return _stopped; } + + public override bool Stopped { + get { return _stopped; } } - public override OMV.Vector3 Size { - get { return _size; } + public override OMV.Vector3 Size { + get { return _size; } set { _size = value; PhysicsScene.TaintedObject("BSPrim.setSize", delegate() @@ -174,7 +174,7 @@ public sealed class BSPrim : BSPhysObject CreateGeomAndObject(true); // DetailLog("{0},BSPrim.setSize,size={1},scale={2},mass={3},physical={4}", LocalID, _size, _scale, _mass, IsPhysical); }); - } + } } // Scale is what we set in the physics engine. It is different than 'size' in that // 'size' can be encorporated into the mesh. In that case, the scale is <1,1,1>. @@ -183,7 +183,7 @@ public sealed class BSPrim : BSPhysObject get { return _scale; } set { _scale = value; } } - public override PrimitiveBaseShape Shape { + public override PrimitiveBaseShape Shape { set { _pbs = value; PhysicsScene.TaintedObject("BSPrim.setShape", delegate() @@ -191,13 +191,13 @@ public sealed class BSPrim : BSPhysObject _mass = CalculateMass(); // changing the shape changes the mass CreateGeomAndObject(true); }); - } + } } - public override bool Grabbed { - set { _grabbed = value; - } + public override bool Grabbed { + set { _grabbed = value; + } } - public override bool Selected { + public override bool Selected { set { _isSelected = value; PhysicsScene.TaintedObject("BSPrim.setSelected", delegate() @@ -205,7 +205,7 @@ public sealed class BSPrim : BSPhysObject // DetailLog("{0},BSPrim.selected,taint,selected={1}", LocalID, _isSelected); SetObjectDynamic(false); }); - } + } } public override void CrossingFailure() { return; } @@ -219,10 +219,10 @@ public sealed class BSPrim : BSPhysObject Linkset = parent.Linkset.AddMeToLinkset(this); - DetailLog("{0},BSPrim.link,call,parentBefore={1}, childrenBefore=={2}, parentAfter={3}, childrenAfter={4}", + DetailLog("{0},BSPrim.link,call,parentBefore={1}, childrenBefore=={2}, parentAfter={3}, childrenAfter={4}", LocalID, parentBefore.LocalID, childrenBefore, Linkset.LinksetRoot.LocalID, Linkset.NumberOfChildren); } - return; + return; } // delink me from my linkset @@ -232,12 +232,12 @@ public sealed class BSPrim : BSPhysObject BSPhysObject parentBefore = Linkset.LinksetRoot; int childrenBefore = Linkset.NumberOfChildren; - + Linkset = Linkset.RemoveMeFromLinkset(this); - DetailLog("{0},BSPrim.delink,parentBefore={1},childrenBefore={2},parentAfter={3},childrenAfter={4}, ", + DetailLog("{0},BSPrim.delink,parentBefore={1},childrenBefore={2},parentAfter={3},childrenAfter={4}, ", LocalID, parentBefore.LocalID, childrenBefore, Linkset.LinksetRoot.LocalID, Linkset.NumberOfChildren); - return; + return; } // Set motion values to zero. @@ -258,21 +258,21 @@ public sealed class BSPrim : BSPhysObject } public override void LockAngularMotion(OMV.Vector3 axis) - { + { DetailLog("{0},BSPrim.LockAngularMotion,call,axis={1}", LocalID, axis); return; } - public override OMV.Vector3 Position { - get { + public override OMV.Vector3 Position { + get { if (!Linkset.IsRoot(this)) // child prims move around based on their parent. Need to get the latest location _position = BulletSimAPI.GetPosition2(BSBody.ptr); // don't do the GetObjectPosition for root elements because this function is called a zillion times // _position = BulletSimAPI.GetObjectPosition2(PhysicsScene.World.ptr, BSBody.ptr); - return _position; - } + return _position; + } set { _position = value; // TODO: what does it mean to set the position of a child prim?? Rebuild the constraint? @@ -281,13 +281,13 @@ public sealed class BSPrim : BSPhysObject // DetailLog("{0},BSPrim.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation); BulletSimAPI.SetTranslation2(BSBody.ptr, _position, _orientation); }); - } + } } // Return the effective mass of the object. // If there are multiple items in the linkset, add them together for the root public override float Mass - { + { get { // return Linkset.LinksetMass; @@ -310,8 +310,8 @@ public sealed class BSPrim : BSPhysObject get { return Linkset.GeometricCenter; } } - public override OMV.Vector3 Force { - get { return _force; } + public override OMV.Vector3 Force { + get { return _force; } set { _force = value; PhysicsScene.TaintedObject("BSPrim.setForce", delegate() @@ -319,13 +319,13 @@ public sealed class BSPrim : BSPhysObject // DetailLog("{0},BSPrim.setForce,taint,force={1}", LocalID, _force); BulletSimAPI.SetObjectForce2(BSBody.ptr, _force); }); - } + } } - public override int VehicleType { + public override int VehicleType { get { return (int)_vehicle.Type; // if we are a vehicle, return that type - } + } set { Vehicle type = (Vehicle)value; BSPrim vehiclePrim = this; @@ -337,30 +337,30 @@ public sealed class BSPrim : BSPhysObject // Tell the scene about the vehicle so it will get processing each frame. PhysicsScene.VehicleInSceneTypeChanged(this, type); }); - } + } } - public override void VehicleFloatParam(int param, float value) + public override void VehicleFloatParam(int param, float value) { PhysicsScene.TaintedObject("BSPrim.VehicleFloatParam", delegate() { _vehicle.ProcessFloatVehicleParam((Vehicle)param, value); }); } - public override void VehicleVectorParam(int param, OMV.Vector3 value) + public override void VehicleVectorParam(int param, OMV.Vector3 value) { PhysicsScene.TaintedObject("BSPrim.VehicleVectorParam", delegate() { _vehicle.ProcessVectorVehicleParam((Vehicle)param, value); }); } - public override void VehicleRotationParam(int param, OMV.Quaternion rotation) + public override void VehicleRotationParam(int param, OMV.Quaternion rotation) { PhysicsScene.TaintedObject("BSPrim.VehicleRotationParam", delegate() { _vehicle.ProcessRotationVehicleParam((Vehicle)param, rotation); }); } - public override void VehicleFlags(int param, bool remove) + public override void VehicleFlags(int param, bool remove) { PhysicsScene.TaintedObject("BSPrim.VehicleFlags", delegate() { @@ -388,11 +388,11 @@ public sealed class BSPrim : BSPhysObject SetObjectDynamic(true); }); } - return; + return; } - public override OMV.Vector3 Velocity { - get { return _velocity; } + public override OMV.Vector3 Velocity { + get { return _velocity; } set { _velocity = value; PhysicsScene.TaintedObject("BSPrim.setVelocity", delegate() @@ -400,24 +400,24 @@ public sealed class BSPrim : BSPhysObject // DetailLog("{0},BSPrim.SetVelocity,taint,vel={1}", LocalID, _velocity); BulletSimAPI.SetLinearVelocity2(BSBody.ptr, _velocity); }); - } + } } - public override OMV.Vector3 Torque { - get { return _torque; } - set { _torque = value; + public override OMV.Vector3 Torque { + get { return _torque; } + set { _torque = value; // DetailLog("{0},BSPrim.SetTorque,call,torque={1}", LocalID, _torque); - } + } } - public override float CollisionScore { - get { return _collisionScore; } - set { _collisionScore = value; - } + public override float CollisionScore { + get { return _collisionScore; } + set { _collisionScore = value; + } } - public override OMV.Vector3 Acceleration { + public override OMV.Vector3 Acceleration { get { return _acceleration; } set { _acceleration = value; } } - public override OMV.Quaternion Orientation { + public override OMV.Quaternion Orientation { get { if (!Linkset.IsRoot(this)) { @@ -425,7 +425,7 @@ public sealed class BSPrim : BSPhysObject _orientation = BulletSimAPI.GetOrientation2(BSBody.ptr); } return _orientation; - } + } set { _orientation = value; // TODO: what does it mean if a child in a linkset changes its orientation? Rebuild the constraint? @@ -435,14 +435,14 @@ public sealed class BSPrim : BSPhysObject // DetailLog("{0},BSPrim.setOrientation,taint,pos={1},orient={2}", LocalID, _position, _orientation); BulletSimAPI.SetTranslation2(BSBody.ptr, _position, _orientation); }); - } + } } - public override int PhysicsActorType { - get { return _physicsActorType; } - set { _physicsActorType = value; } + public override int PhysicsActorType { + get { return _physicsActorType; } + set { _physicsActorType = value; } } - public override bool IsPhysical { - get { return _isPhysical; } + public override bool IsPhysical { + get { return _isPhysical; } set { if (_isPhysical != value) { @@ -453,7 +453,7 @@ public sealed class BSPrim : BSPhysObject SetObjectDynamic(true); }); } - } + } } // An object is static (does not move) if selected or not physical @@ -519,7 +519,7 @@ public sealed class BSPrim : BSPhysObject // had been automatically disabled when the mass was set to zero. Linkset.Refresh(this); - DetailLog("{0},BSPrim.UpdatePhysicalParameters,exit,static={1},solid={2},mass={3},collide={4},cf={5:X},body={6},shape={7}", + DetailLog("{0},BSPrim.UpdatePhysicalParameters,exit,static={1},solid={2},mass={3},collide={4},cf={5:X},body={6},shape={7}", LocalID, IsStatic, IsSolid, _mass, SubscribedEvents(), CurrentCollisionFlags, BSBody, BSShape); } @@ -630,31 +630,31 @@ public sealed class BSPrim : BSPhysObject } // prims don't fly - public override bool Flying { - get { return _flying; } + public override bool Flying { + get { return _flying; } set { _flying = value; - } + } } - public override bool SetAlwaysRun { - get { return _setAlwaysRun; } - set { _setAlwaysRun = value; } + public override bool SetAlwaysRun { + get { return _setAlwaysRun; } + set { _setAlwaysRun = value; } } - public override bool ThrottleUpdates { - get { return _throttleUpdates; } - set { _throttleUpdates = value; } + public override bool ThrottleUpdates { + get { return _throttleUpdates; } + set { _throttleUpdates = value; } } public override bool IsColliding { - get { return (CollidingStep == PhysicsScene.SimulationStep); } - set { _isColliding = value; } + get { return (CollidingStep == PhysicsScene.SimulationStep); } + set { _isColliding = value; } } public override bool CollidingGround { - get { return (CollidingGroundStep == PhysicsScene.SimulationStep); } - set { _collidingGround = value; } + get { return (CollidingGroundStep == PhysicsScene.SimulationStep); } + set { _collidingGround = value; } } - public override bool CollidingObj { - get { return _collidingObj; } - set { _collidingObj = value; } + public override bool CollidingObj { + get { return _collidingObj; } + set { _collidingObj = value; } } public bool IsPhantom { get { @@ -664,10 +664,10 @@ public sealed class BSPrim : BSPhysObject return false; } } - public override bool FloatOnWater { - set { _floatOnWater = value; } + public override bool FloatOnWater { + set { _floatOnWater = value; } } - public override OMV.Vector3 RotationalVelocity { + public override OMV.Vector3 RotationalVelocity { get { /* OMV.Vector3 pv = OMV.Vector3.Zero; @@ -679,7 +679,7 @@ public sealed class BSPrim : BSPhysObject */ return _rotationalVelocity; - } + } set { _rotationalVelocity = value; // m_log.DebugFormat("{0}: RotationalVelocity={1}", LogHeader, _rotationalVelocity); @@ -688,16 +688,16 @@ public sealed class BSPrim : BSPhysObject // DetailLog("{0},BSPrim.SetRotationalVel,taint,rotvel={1}", LocalID, _rotationalVelocity); BulletSimAPI.SetAngularVelocity2(BSBody.ptr, _rotationalVelocity); }); - } + } } - public override bool Kinematic { - get { return _kinematic; } - set { _kinematic = value; + public override bool Kinematic { + get { return _kinematic; } + set { _kinematic = value; // m_log.DebugFormat("{0}: Kinematic={1}", LogHeader, _kinematic); - } + } } - public override float Buoyancy { - get { return _buoyancy; } + public override float Buoyancy { + get { return _buoyancy; } set { _buoyancy = value; PhysicsScene.TaintedObject("BSPrim.setBuoyancy", delegate() @@ -707,32 +707,32 @@ public sealed class BSPrim : BSPhysObject float grav = PhysicsScene.Params.gravity * (1f - _buoyancy); BulletSimAPI.SetGravity2(BSBody.ptr, new OMV.Vector3(0f, 0f, grav)); }); - } + } } // Used for MoveTo - public override OMV.Vector3 PIDTarget { - set { _PIDTarget = value; } + public override OMV.Vector3 PIDTarget { + set { _PIDTarget = value; } } - public override bool PIDActive { - set { _usePID = value; } + public override bool PIDActive { + set { _usePID = value; } } - public override float PIDTau { - set { _PIDTau = value; } + public override float PIDTau { + set { _PIDTau = value; } } // Used for llSetHoverHeight and maybe vehicle height // Hover Height will override MoveTo target's Z - public override bool PIDHoverActive { + public override bool PIDHoverActive { set { _useHoverPID = value; } } - public override float PIDHoverHeight { + public override float PIDHoverHeight { set { _PIDHoverHeight = value; } } - public override PIDHoverType PIDHoverType { + public override PIDHoverType PIDHoverType { set { _PIDHoverType = value; } } - public override float PIDHoverTau { + public override float PIDHoverTau { set { _PIDHoverTao = value; } } @@ -773,11 +773,11 @@ public sealed class BSPrim : BSPhysObject }); } - public override void AddAngularForce(OMV.Vector3 force, bool pushforce) { + public override void AddAngularForce(OMV.Vector3 force, bool pushforce) { // DetailLog("{0},BSPrim.AddAngularForce,call,angForce={1},push={2}", LocalID, force, pushforce); // m_log.DebugFormat("{0}: AddAngularForce. f={1}, push={2}", LogHeader, force, pushforce); } - public override void SetMomentum(OMV.Vector3 momentum) { + public override void SetMomentum(OMV.Vector3 momentum) { // DetailLog("{0},BSPrim.SetMomentum,call,mom={1}", LocalID, momentum); } #region Mass Calculation @@ -789,8 +789,8 @@ public sealed class BSPrim : BSPhysObject float returnMass = 0; float hollowAmount = (float)_pbs.ProfileHollow * 2.0e-5f; - float hollowVolume = hollowAmount * hollowAmount; - + float hollowVolume = hollowAmount * hollowAmount; + switch (_pbs.ProfileShape) { case ProfileShape.Square: @@ -826,16 +826,16 @@ public sealed class BSPrim : BSPhysObject else if (_pbs.PathCurve == (byte)Extrusion.Curve1) { - //a tube + //a tube volume *= 0.78539816339e-2f * (float)(200 - _pbs.PathScaleX); tmp= 1.0f -2.0e-2f * (float)(200 - _pbs.PathScaleY); volume -= volume*tmp*tmp; - + if (hollowAmount > 0.0) { hollowVolume *= hollowAmount; - + switch (_pbs.HollowShape) { case HollowShape.Square: @@ -894,7 +894,7 @@ public sealed class BSPrim : BSPhysObject volume *= 0.61685027506808491367715568749226e-2f * (float)(200 - _pbs.PathScaleX); tmp = 1.0f - .02f * (float)(200 - _pbs.PathScaleY); volume *= (1.0f - tmp * tmp); - + if (hollowAmount > 0.0) { @@ -1118,7 +1118,7 @@ public sealed class BSPrim : BSPhysObject PhysicsScene.Shapes.GetBodyAndShape(forceRebuild, PhysicsScene.World, this, shapeData, _pbs); Linkset = Linkset.AddMeToLinkset(this); - + // Make sure the properties are set on the new object UpdatePhysicalParameters(); return; @@ -1210,7 +1210,7 @@ public sealed class BSPrim : BSPhysObject { // For debugging, we can also report the movement of children DetailLog("{0},BSPrim.UpdateProperties,child,pos={1},orient={2},vel={3},accel={4},rotVel={5}", - LocalID, entprop.Position, entprop.Rotation, entprop.Velocity, + LocalID, entprop.Position, entprop.Rotation, entprop.Velocity, entprop.Acceleration, entprop.RotationalVelocity); } */ diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs index 44a249c..0cf8c91 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs @@ -49,7 +49,7 @@ using OpenMetaverse; // At the moment, physical and phantom causes object to drop through the terrain // Physical phantom objects and related typing (collision options ) // Check out llVolumeDetect. Must do something for that. -// Use collision masks for collision with terrain and phantom objects +// Use collision masks for collision with terrain and phantom objects // More efficient memory usage when passing hull information from BSPrim to BulletSim // Should prim.link() and prim.delink() membership checking happen at taint time? // Mesh sharing. Use meshHash to tell if we already have a hull of that shape and only create once. @@ -60,7 +60,7 @@ using OpenMetaverse; // Add PID movement operations. What does ScenePresence.MoveToTarget do? // Check terrain size. 128 or 127? // Raycast -// +// namespace OpenSim.Region.Physics.BulletSPlugin { public class BSScene : PhysicsScene, IPhysicsParameters @@ -327,7 +327,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters { m_log.Debug("[BULLETS UNMANAGED]:" + msg); } - + // Called directly from unmanaged code so don't do much private void BulletLoggerPhysLog(string msg) { @@ -460,7 +460,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters } // This is a call from the simulator saying that some physical property has been updated. - // The BulletSim driver senses the changing of relevant properties so this taint + // The BulletSim driver senses the changing of relevant properties so this taint // information call is not needed. public override void AddPhysicsActorTaint(PhysicsActor prim) { } @@ -501,14 +501,14 @@ public class BSScene : PhysicsScene, IPhysicsParameters out updatedEntityCount, out updatedEntitiesPtr, out collidersCount, out collidersPtr); if (PhysicsLogging.Enabled) simTime = Util.EnvironmentTickCountSubtract(beforeTime); - DetailLog("{0},Simulate,call, nTaints={1}, simTime={2}, substeps={3}, updates={4}, colliders={5}", - DetailLogZero, numTaints, simTime, numSubSteps, updatedEntityCount, collidersCount); + DetailLog("{0},Simulate,call, nTaints={1}, simTime={2}, substeps={3}, updates={4}, colliders={5}", + DetailLogZero, numTaints, simTime, numSubSteps, updatedEntityCount, collidersCount); } catch (Exception e) { - m_log.WarnFormat("{0},PhysicsStep Exception: nTaints={1}, substeps={2}, updates={3}, colliders={4}, e={5}", + m_log.WarnFormat("{0},PhysicsStep Exception: nTaints={1}, substeps={2}, updates={3}, colliders={4}, e={5}", LogHeader, numTaints, numSubSteps, updatedEntityCount, collidersCount, e); - DetailLog("{0},PhysicsStepException,call, nTaints={1}, substeps={2}, updates={3}, colliders={4}", + DetailLog("{0},PhysicsStepException,call, nTaints={1}, substeps={2}, updates={3}, colliders={4}", DetailLogZero, numTaints, numSubSteps, updatedEntityCount, collidersCount); updatedEntityCount = 0; collidersCount = 0; @@ -535,7 +535,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters } } - // This is a kludge to get avatar movement updates. + // This is a kludge to get avatar movement updates. // ODE sends collisions for avatars even if there are have been no collisions. This updates // avatar animations and stuff. // If you fix avatar animation updates, remove this overhead and let normal collision processing happen. @@ -634,7 +634,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters TerrainManager.SetTerrain(heightMap); } - public override void SetWaterLevel(float baseheight) + public override void SetWaterLevel(float baseheight) { m_waterLevel = baseheight; } @@ -644,7 +644,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters return m_waterLevel; } - public override void DeleteTerrain() + public override void DeleteTerrain() { // m_log.DebugFormat("{0}: DeleteTerrain()", LogHeader); } @@ -806,7 +806,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters // getters and setters. // It is easiest to find an existing definition and copy it. // Parameter values are floats. Booleans are converted to a floating value. - // + // // A ParameterDefn() takes the following parameters: // -- the text name of the parameter. This is used for console input and ini file. // -- a short text description of the parameter. This shows up in the console listing. @@ -1228,7 +1228,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters } }); break; - default: + default: // setting only one localID TaintedUpdateParameter(parm, localID, val); break; diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs index 72c6df5..b428ba3 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs @@ -102,7 +102,7 @@ public class BSShapeCollection : IDisposable bool newBody = CreateBody((newGeom || forceRebuild), prim, PhysicsScene.World, prim.BSShape, shapeData); ret = newGeom || newBody; } - DetailLog("{0},BSShapeCollection.GetBodyAndShape,force={1},ret={2},body={3},shape={4}", + DetailLog("{0},BSShapeCollection.GetBodyAndShape,force={1},ret={2},body={3},shape={4}", prim.LocalID, forceRebuild, ret, prim.BSBody, prim.BSShape); return ret; @@ -149,14 +149,14 @@ public class BSShapeCollection : IDisposable bodyDesc.lastReferenced = System.DateTime.Now; Bodies[shape.ID] = bodyDesc; DetailLog("{0},BSShapeCollection.DereferenceBody,ref={1}", shape.ID, bodyDesc.referenceCount); - + // If body is no longer being used, free it -- bodies are never shared. if (bodyDesc.referenceCount == 0) { Bodies.Remove(shape.ID); BSScene.TaintCallback removeOperation = delegate() { - DetailLog("{0},BSShapeCollection.DereferenceBody,DestroyingBody. ptr={1}", + DetailLog("{0},BSShapeCollection.DereferenceBody,DestroyingBody. ptr={1}", shape.ID, shape.ptr.ToString("X")); // Zero any reference to the shape so it is not freed when the body is deleted. BulletSimAPI.SetCollisionShape2(PhysicsScene.World.ptr, shape.ptr, IntPtr.Zero); @@ -344,28 +344,28 @@ public class BSShapeCollection : IDisposable if (pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1) { haveShape = true; - if (forceRebuild + if (forceRebuild || prim.Scale != shapeData.Size || prim.BSShape.type != ShapeData.PhysicsShapeType.SHAPE_SPHERE ) { - ret = GetReferenceToNativeShape(prim, shapeData, + ret = GetReferenceToNativeShape(prim, shapeData, ShapeData.PhysicsShapeType.SHAPE_SPHERE, ShapeData.FixedShapeKey.KEY_SPHERE); - DetailLog("{0},BSShapeCollection.CreateGeom,sphere,force={1},shape={2}", + DetailLog("{0},BSShapeCollection.CreateGeom,sphere,force={1},shape={2}", prim.LocalID, forceRebuild, prim.BSShape); } } else { haveShape = true; - if (forceRebuild + if (forceRebuild || prim.Scale != shapeData.Size || prim.BSShape.type != ShapeData.PhysicsShapeType.SHAPE_BOX ) { ret = GetReferenceToNativeShape( prim, shapeData, ShapeData.PhysicsShapeType.SHAPE_BOX, ShapeData.FixedShapeKey.KEY_BOX); - DetailLog("{0},BSShapeCollection.CreateGeom,box,force={1},shape={2}", + DetailLog("{0},BSShapeCollection.CreateGeom,box,force={1},shape={2}", prim.LocalID, forceRebuild, prim.BSShape); } } @@ -379,13 +379,13 @@ public class BSShapeCollection : IDisposable { // Update prim.BSShape to reference a hull of this shape. ret = GetReferenceToHull(prim, shapeData, pbs); - DetailLog("{0},BSShapeCollection.CreateGeom,hull,shape={1},key={2}", + DetailLog("{0},BSShapeCollection.CreateGeom,hull,shape={1},key={2}", shapeData.ID, prim.BSShape, prim.BSShape.shapeKey.ToString("X")); } else { ret = GetReferenceToMesh(prim, shapeData, pbs); - DetailLog("{0},BSShapeCollection.CreateGeom,mesh,shape={1},key={2}", + DetailLog("{0},BSShapeCollection.CreateGeom,mesh,shape={1},key={2}", shapeData.ID, prim.BSShape, prim.BSShape.shapeKey.ToString("X")); } } @@ -393,7 +393,7 @@ public class BSShapeCollection : IDisposable } // Creates a native shape and assignes it to prim.BSShape - private bool GetReferenceToNativeShape( BSPrim prim, ShapeData shapeData, + private bool GetReferenceToNativeShape( BSPrim prim, ShapeData shapeData, ShapeData.PhysicsShapeType shapeType, ShapeData.FixedShapeKey shapeKey) { BulletShape newShape; @@ -432,7 +432,7 @@ public class BSShapeCollection : IDisposable // if this new shape is the same as last time, don't recreate the mesh if (prim.BSShape.shapeKey == newMeshKey) return false; - DetailLog("{0},BSShapeCollection.CreateGeomMesh,create,oldKey={1},newKey={2}", + DetailLog("{0},BSShapeCollection.CreateGeomMesh,create,oldKey={1},newKey={2}", prim.LocalID, prim.BSShape.shapeKey.ToString("X"), newMeshKey.ToString("X")); // Since we're recreating new, get rid of the reference to the previous shape @@ -476,10 +476,10 @@ public class BSShapeCollection : IDisposable verticesAsFloats[vi++] = vv.Z; } - // m_log.DebugFormat("{0}: CreateGeomMesh: calling CreateMesh. lid={1}, key={2}, indices={3}, vertices={4}", + // m_log.DebugFormat("{0}: CreateGeomMesh: calling CreateMesh. lid={1}, key={2}, indices={3}, vertices={4}", // LogHeader, prim.LocalID, newMeshKey, indices.Length, vertices.Count); - meshPtr = BulletSimAPI.CreateMeshShape2(PhysicsScene.World.ptr, + meshPtr = BulletSimAPI.CreateMeshShape2(PhysicsScene.World.ptr, indices.GetLength(0), indices, vertices.Count, verticesAsFloats); } BulletShape newShape = new BulletShape(meshPtr, ShapeData.PhysicsShapeType.SHAPE_MESH); @@ -501,14 +501,14 @@ public class BSShapeCollection : IDisposable if (newHullKey == prim.BSShape.shapeKey && prim.BSShape.type == ShapeData.PhysicsShapeType.SHAPE_HULL) return false; - DetailLog("{0},BSShapeCollection.CreateGeomHull,create,oldKey={1},newKey={2}", + DetailLog("{0},BSShapeCollection.CreateGeomHull,create,oldKey={1},newKey={2}", prim.LocalID, prim.BSShape.shapeKey.ToString("X"), newHullKey.ToString("X")); // Remove usage of the previous shape. Also removes reference to underlying mesh if it is a hull. DereferenceShape(prim.BSShape, true); newShape = CreatePhysicalHull(prim.PhysObjectName, newHullKey, pbs, shapeData.Size, lod); - + ReferenceShape(newShape); // hulls are already scaled by the meshmerizer @@ -559,7 +559,7 @@ public class BSShapeCollection : IDisposable convexBuilder.process(dcomp); // Convert the vertices and indices for passing to unmanaged. - // The hull information is passed as a large floating point array. + // The hull information is passed as a large floating point array. // The format is: // convHulls[0] = number of hulls // convHulls[1] = number of vertices in first hull @@ -635,11 +635,11 @@ public class BSShapeCollection : IDisposable { // level of detail based on size and type of the object float lod = PhysicsScene.MeshLOD; - if (pbs.SculptEntry) + if (pbs.SculptEntry) lod = PhysicsScene.SculptLOD; float maxAxis = Math.Max(shapeData.Size.X, Math.Max(shapeData.Size.Y, shapeData.Size.Z)); - if (maxAxis > PhysicsScene.MeshMegaPrimThreshold) + if (maxAxis > PhysicsScene.MeshMegaPrimThreshold) lod = PhysicsScene.MeshMegaPrimLOD; retLod = lod; @@ -685,13 +685,13 @@ public class BSShapeCollection : IDisposable IntPtr bodyPtr = IntPtr.Zero; if (prim.IsSolid) { - bodyPtr = BulletSimAPI.CreateBodyFromShape2(sim.ptr, shape.ptr, + bodyPtr = BulletSimAPI.CreateBodyFromShape2(sim.ptr, shape.ptr, shapeData.ID, shapeData.Position, shapeData.Rotation); // DetailLog("{0},BSShapeCollection.CreateBody,mesh,ptr={1}", prim.LocalID, bodyPtr.ToString("X")); } else { - bodyPtr = BulletSimAPI.CreateGhostFromShape2(sim.ptr, shape.ptr, + bodyPtr = BulletSimAPI.CreateGhostFromShape2(sim.ptr, shape.ptr, shapeData.ID, shapeData.Position, shapeData.Rotation); // DetailLog("{0},BSShapeCollection.CreateBody,ghost,ptr={1}", prim.LocalID, bodyPtr.ToString("X")); } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs index 269c3d5..70aa429 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs @@ -64,7 +64,7 @@ public class BSTerrainManager // The ground plane created to keep thing from falling to infinity. private BulletBody m_groundPlane; - + // If doing mega-regions, if we're region zero we will be managing multiple // region terrains since region zero does the physics for the whole mega-region. private Dictionary m_heightMaps; @@ -110,8 +110,8 @@ public class BSTerrainManager BulletShape groundPlaneShape = new BulletShape( BulletSimAPI.CreateGroundPlaneShape2(BSScene.GROUNDPLANE_ID, 1f, TERRAIN_COLLISION_MARGIN), ShapeData.PhysicsShapeType.SHAPE_GROUNDPLANE); - m_groundPlane = new BulletBody(BSScene.GROUNDPLANE_ID, - BulletSimAPI.CreateBodyWithDefaultMotionState2(groundPlaneShape.ptr, BSScene.GROUNDPLANE_ID, + m_groundPlane = new BulletBody(BSScene.GROUNDPLANE_ID, + BulletSimAPI.CreateBodyWithDefaultMotionState2(groundPlaneShape.ptr, BSScene.GROUNDPLANE_ID, Vector3.Zero, Quaternion.Identity)); BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, m_groundPlane.ptr); // Everything collides with the ground plane. @@ -182,7 +182,7 @@ public class BSTerrainManager // If not doing the mega-prim thing, just change the terrain DetailLog("{0},SetTerrain.Existing", BSScene.DetailLogZero); - UpdateOrCreateTerrain(BSScene.TERRAIN_ID, localHeightMap, + UpdateOrCreateTerrain(BSScene.TERRAIN_ID, localHeightMap, m_worldOffset, m_worldOffset + DefaultRegionSize, true); } }); @@ -234,7 +234,7 @@ public class BSTerrainManager mapInfo.maxZ = maxZ; mapInfo.sizeX = maxCoords.X - minCoords.X; mapInfo.sizeY = maxCoords.Y - minCoords.Y; - DetailLog("{0},UpdateOrCreateTerrain:UpdateExisting,call,terrainBase={1},minC={2}, maxC={3}, szX={4}, szY={5}", + DetailLog("{0},UpdateOrCreateTerrain:UpdateExisting,call,terrainBase={1},minC={2}, maxC={3}, szX={4}, szY={5}", BSScene.DetailLogZero, terrainRegionBase, mapInfo.minCoords, mapInfo.maxCoords, mapInfo.sizeX, mapInfo.sizeY); BSScene.TaintCallback rebuildOperation = delegate() @@ -255,7 +255,7 @@ public class BSTerrainManager if (mapInfo.terrainBody.ptr != IntPtr.Zero) { // Updating an existing terrain. - DetailLog("{0},UpdateOrCreateTerrain:UpdateExisting,taint,terrainBase={1},minC={2}, maxC={3}, szX={4}, szY={5}", + DetailLog("{0},UpdateOrCreateTerrain:UpdateExisting,taint,terrainBase={1},minC={2}, maxC={3}, szX={4}, szY={5}", BSScene.DetailLogZero, terrainRegionBase, mapInfo.minCoords, mapInfo.maxCoords, mapInfo.sizeX, mapInfo.sizeY); // Remove from the dynamics world because we're going to mangle this object @@ -289,7 +289,7 @@ public class BSTerrainManager // else { // Creating a new terrain. - DetailLog("{0},UpdateOrCreateTerrain:CreateNewTerrain,taint,baseX={1},baseY={2},minZ={3},maxZ={4}", + DetailLog("{0},UpdateOrCreateTerrain:CreateNewTerrain,taint,baseX={1},baseY={2},minZ={3},maxZ={4}", BSScene.DetailLogZero, mapInfo.minCoords.X, mapInfo.minCoords.Y, minZ, maxZ); mapInfo.ID = id; @@ -306,9 +306,9 @@ public class BSTerrainManager mapInfo.terrainShape = new BulletShape(BulletSimAPI.CreateTerrainShape2(mapInfo.Ptr), ShapeData.PhysicsShapeType.SHAPE_TERRAIN); - mapInfo.terrainBody = new BulletBody(mapInfo.ID, - BulletSimAPI.CreateBodyWithDefaultMotionState2(mapInfo.terrainShape.ptr, - id, centerPos, Quaternion.Identity)); + mapInfo.terrainBody = new BulletBody(mapInfo.ID, + BulletSimAPI.CreateBodyWithDefaultMotionState2(mapInfo.terrainShape.ptr, + id, centerPos, Quaternion.Identity)); } // Make sure the entry is in the heightmap table @@ -329,7 +329,7 @@ public class BSTerrainManager // redo its bounding box now that it is in the world BulletSimAPI.UpdateSingleAabb2(PhysicsScene.World.ptr, mapInfo.terrainBody.ptr); - BulletSimAPI.SetCollisionFilterMask2(mapInfo.terrainBody.ptr, + BulletSimAPI.SetCollisionFilterMask2(mapInfo.terrainBody.ptr, (uint)CollisionFilterGroups.TerrainFilter, (uint)CollisionFilterGroups.TerrainMask); @@ -361,7 +361,7 @@ public class BSTerrainManager Vector3 minCoordsX = minCoords; Vector3 maxCoordsX = maxCoords; - DetailLog("{0},UpdateOrCreateTerrain:NewTerrain,call,id={1}, minC={2}, maxC={3}", + DetailLog("{0},UpdateOrCreateTerrain:NewTerrain,call,id={1}, minC={2}, maxC={3}", BSScene.DetailLogZero, newTerrainID, minCoords, minCoords); // Code that must happen at taint-time @@ -370,7 +370,7 @@ public class BSTerrainManager DetailLog("{0},UpdateOrCreateTerrain:NewTerrain,taint,baseX={1},baseY={2}", BSScene.DetailLogZero, minCoords.X, minCoords.Y); // Create a new mapInfo that will be filled with the new info mapInfo = new BulletHeightMapInfo(id, heightMapX, - BulletSimAPI.CreateHeightMapInfo2(PhysicsScene.World.ptr, newTerrainID, + BulletSimAPI.CreateHeightMapInfo2(PhysicsScene.World.ptr, newTerrainID, minCoordsX, maxCoordsX, heightMapX, TERRAIN_COLLISION_MARGIN)); // Put the unfilled heightmap info into the collection of same m_heightMaps.Add(terrainRegionBase, mapInfo); @@ -454,7 +454,7 @@ public class BSTerrainManager { return true; } - + // This routine is called two ways: // One with 'offset' and 'pScene' zero and null but 'extents' giving the maximum // extent of the combined regions. This is to inform the parent of the size @@ -469,11 +469,11 @@ public class BSTerrainManager MegaRegionParentPhysicsScene = pScene; if (pScene != null) { - // We are a child. + // We are a child. // We want m_worldMax to be the highest coordinate of our piece of terrain. m_worldMax = offset + DefaultRegionSize; } - DetailLog("{0},BSTerrainManager.Combine,offset={1},extents={2},wOffset={3},wMax={4}", + DetailLog("{0},BSTerrainManager.Combine,offset={1},extents={2},wOffset={3},wMax={4}", BSScene.DetailLogZero, offset, extents, m_worldOffset, m_worldMax); } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs index 2d65a35..544c53d 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs @@ -41,8 +41,8 @@ public struct BulletSim public BulletSim(uint worldId, BSScene bss, IntPtr xx) { ptr = xx; - worldID = worldId; - scene = bss; + worldID = worldId; + scene = bss; } public IntPtr ptr; public uint worldID; -- cgit v1.1 From 74dea4cfd52be75b4dd6277260c3ada80b939fbb Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Thu, 27 Sep 2012 19:57:35 -0700 Subject: BulletSim: rename some constraint variables to be consistant with other name use. Added callbacks for shape and body changes in GetBodyAndShape() so the linkset constraints can be picked up and restored. A better design might be to have a "prim shape changed" event. Think about that. Added constraint types to general constraint class. --- .../Physics/BulletSPlugin/BS6DofConstraint.cs | 42 +++-- .../Region/Physics/BulletSPlugin/BSConstraint.cs | 21 ++- .../Physics/BulletSPlugin/BSHingeConstraint.cs | 2 + OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs | 182 +++++++++++++-------- OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | 14 +- .../Physics/BulletSPlugin/BSShapeCollection.cs | 65 +++++--- .../Region/Physics/BulletSPlugin/BulletSimAPI.cs | 21 ++- 7 files changed, 231 insertions(+), 116 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BS6DofConstraint.cs b/OpenSim/Region/Physics/BulletSPlugin/BS6DofConstraint.cs index 39a3421..3306a97 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BS6DofConstraint.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BS6DofConstraint.cs @@ -34,6 +34,10 @@ namespace OpenSim.Region.Physics.BulletSPlugin public class BS6DofConstraint : BSConstraint { + private static string LogHeader = "[BULLETSIM 6DOF CONSTRAINT]"; + + public override ConstraintType Type { get { return ConstraintType.D6_CONSTRAINT_TYPE; } } + // Create a btGeneric6DofConstraint public BS6DofConstraint(BulletSim world, BulletBody obj1, BulletBody obj2, Vector3 frame1, Quaternion frame1rot, @@ -49,6 +53,9 @@ public class BS6DofConstraint : BSConstraint frame2, frame2rot, useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies)); m_enabled = true; + world.physicsScene.DetailLog("{0},BS6DofConstraint,createFrame,wID={1}, rID={2}, rBody={3}, cID={4}, cBody={5}", + BSScene.DetailLogZero, world.worldID, + obj1.ID, obj1.ptr.ToString("X"), obj2.ID, obj2.ptr.ToString("X")); } public BS6DofConstraint(BulletSim world, BulletBody obj1, BulletBody obj2, @@ -60,12 +67,13 @@ public class BS6DofConstraint : BSConstraint m_body2 = obj2; if (obj1.ptr == IntPtr.Zero || obj2.ptr == IntPtr.Zero) { - world.scene.DetailLog("{0},BS6DOFConstraint,badBodyPtr,wID={1}, rID={2}, rBody={3}, cID={4}, cBody={5}", - "[BULLETSIM 6DOF CONSTRAINT]", world.worldID, + world.physicsScene.DetailLog("{0},BS6DOFConstraint,badBodyPtr,wID={1}, rID={2}, rBody={3}, cID={4}, cBody={5}", + BSScene.DetailLogZero, world.worldID, obj1.ID, obj1.ptr.ToString("X"), obj2.ID, obj2.ptr.ToString("X")); - world.scene.Logger.ErrorFormat("{0} Attempt to build 6DOF constraint with missing bodies: wID={1}, rID={2}, rBody={3}, cID={4}, cBody={5}", + world.physicsScene.Logger.ErrorFormat("{0} Attempt to build 6DOF constraint with missing bodies: wID={1}, rID={2}, rBody={3}, cID={4}, cBody={5}", "[BULLETSIM 6DOF CONSTRAINT]", world.worldID, obj1.ID, obj1.ptr.ToString("X"), obj2.ID, obj2.ptr.ToString("X")); + m_enabled = false; } else { @@ -73,8 +81,20 @@ public class BS6DofConstraint : BSConstraint BulletSimAPI.Create6DofConstraintToPoint2(m_world.ptr, m_body1.ptr, m_body2.ptr, joinPoint, useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies)); + world.physicsScene.DetailLog("{0},BS6DofConstraint,createMidPoint,wID={1}, csrt={2}, rID={3}, rBody={4}, cID={5}, cBody={6}", + BSScene.DetailLogZero, world.worldID, m_constraint.ptr.ToString("X"), + obj1.ID, obj1.ptr.ToString("X"), obj2.ID, obj2.ptr.ToString("X")); + if (m_constraint.ptr == IntPtr.Zero) + { + world.physicsScene.Logger.ErrorFormat("{0} Failed creation of 6Dof constraint. rootID={1}, childID={2}", + LogHeader, obj1.ID, obj2.ID); + m_enabled = false; + } + else + { + m_enabled = true; + } } - m_enabled = true; } public bool SetFrames(Vector3 frameA, Quaternion frameArot, Vector3 frameB, Quaternion frameBrot) @@ -82,7 +102,7 @@ public class BS6DofConstraint : BSConstraint bool ret = false; if (m_enabled) { - BulletSimAPI.SetFrames2(m_constraint.Ptr, frameA, frameArot, frameB, frameBrot); + BulletSimAPI.SetFrames2(m_constraint.ptr, frameA, frameArot, frameB, frameBrot); ret = true; } return ret; @@ -93,9 +113,9 @@ public class BS6DofConstraint : BSConstraint bool ret = false; if (m_enabled) { - BulletSimAPI.SetConstraintParam2(m_constraint.Ptr, ConstraintParams.BT_CONSTRAINT_STOP_CFM, cfm, ConstraintParamAxis.AXIS_ALL); - BulletSimAPI.SetConstraintParam2(m_constraint.Ptr, ConstraintParams.BT_CONSTRAINT_STOP_ERP, erp, ConstraintParamAxis.AXIS_ALL); - BulletSimAPI.SetConstraintParam2(m_constraint.Ptr, ConstraintParams.BT_CONSTRAINT_CFM, cfm, ConstraintParamAxis.AXIS_ALL); + BulletSimAPI.SetConstraintParam2(m_constraint.ptr, ConstraintParams.BT_CONSTRAINT_STOP_CFM, cfm, ConstraintParamAxis.AXIS_ALL); + BulletSimAPI.SetConstraintParam2(m_constraint.ptr, ConstraintParams.BT_CONSTRAINT_STOP_ERP, erp, ConstraintParamAxis.AXIS_ALL); + BulletSimAPI.SetConstraintParam2(m_constraint.ptr, ConstraintParams.BT_CONSTRAINT_CFM, cfm, ConstraintParamAxis.AXIS_ALL); ret = true; } return ret; @@ -106,7 +126,7 @@ public class BS6DofConstraint : BSConstraint bool ret = false; float onOff = useOffset ? ConfigurationParameters.numericTrue : ConfigurationParameters.numericFalse; if (m_enabled) - ret = BulletSimAPI.UseFrameOffset2(m_constraint.Ptr, onOff); + ret = BulletSimAPI.UseFrameOffset2(m_constraint.ptr, onOff); return ret; } @@ -115,7 +135,7 @@ public class BS6DofConstraint : BSConstraint bool ret = false; float onOff = enable ? ConfigurationParameters.numericTrue : ConfigurationParameters.numericFalse; if (m_enabled) - ret = BulletSimAPI.TranslationalLimitMotor2(m_constraint.Ptr, onOff, targetVelocity, maxMotorForce); + ret = BulletSimAPI.TranslationalLimitMotor2(m_constraint.ptr, onOff, targetVelocity, maxMotorForce); return ret; } @@ -123,7 +143,7 @@ public class BS6DofConstraint : BSConstraint { bool ret = false; if (m_enabled) - ret = BulletSimAPI.SetBreakingImpulseThreshold2(m_constraint.Ptr, threshold); + ret = BulletSimAPI.SetBreakingImpulseThreshold2(m_constraint.ptr, threshold); return ret; } } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs b/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs index c21252b..63a4127 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs @@ -49,20 +49,23 @@ public abstract class BSConstraint : IDisposable if (m_enabled) { m_enabled = false; - bool success = BulletSimAPI.DestroyConstraint2(m_world.ptr, m_constraint.Ptr); - m_world.scene.DetailLog("{0},BSConstraint.Dispose,taint,body1={1},body2={2},success={3}", BSScene.DetailLogZero, m_body1.ID, m_body2.ID, success); - m_constraint.Ptr = System.IntPtr.Zero; + bool success = BulletSimAPI.DestroyConstraint2(m_world.ptr, m_constraint.ptr); + m_world.physicsScene.DetailLog("{0},BSConstraint.Dispose,taint,body1={1},body2={2},success={3}", BSScene.DetailLogZero, m_body1.ID, m_body2.ID, success); + m_constraint.ptr = System.IntPtr.Zero; } } public BulletBody Body1 { get { return m_body1; } } public BulletBody Body2 { get { return m_body2; } } + public BulletConstraint Constraint { get { return m_constraint; } } + public abstract ConstraintType Type { get; } + public virtual bool SetLinearLimits(Vector3 low, Vector3 high) { bool ret = false; if (m_enabled) - ret = BulletSimAPI.SetLinearLimits2(m_constraint.Ptr, low, high); + ret = BulletSimAPI.SetLinearLimits2(m_constraint.ptr, low, high); return ret; } @@ -70,7 +73,7 @@ public abstract class BSConstraint : IDisposable { bool ret = false; if (m_enabled) - ret = BulletSimAPI.SetAngularLimits2(m_constraint.Ptr, low, high); + ret = BulletSimAPI.SetAngularLimits2(m_constraint.ptr, low, high); return ret; } @@ -79,7 +82,7 @@ public abstract class BSConstraint : IDisposable bool ret = false; if (m_enabled) { - BulletSimAPI.SetConstraintNumSolverIterations2(m_constraint.Ptr, cnt); + BulletSimAPI.SetConstraintNumSolverIterations2(m_constraint.ptr, cnt); ret = true; } return ret; @@ -91,7 +94,7 @@ public abstract class BSConstraint : IDisposable if (m_enabled) { // Recompute the internal transforms - BulletSimAPI.CalculateTransforms2(m_constraint.Ptr); + BulletSimAPI.CalculateTransforms2(m_constraint.ptr); ret = true; } return ret; @@ -110,11 +113,11 @@ public abstract class BSConstraint : IDisposable // Setting an object's mass to zero (making it static like when it's selected) // automatically disables the constraints. // If the link is enabled, be sure to set the constraint itself to enabled. - BulletSimAPI.SetConstraintEnable2(m_constraint.Ptr, m_world.scene.NumericBool(true)); + BulletSimAPI.SetConstraintEnable2(m_constraint.ptr, m_world.physicsScene.NumericBool(true)); } else { - m_world.scene.Logger.ErrorFormat("[BULLETSIM CONSTRAINT] CalculateTransforms failed. A={0}, B={1}", Body1.ID, Body2.ID); + m_world.physicsScene.Logger.ErrorFormat("[BULLETSIM CONSTRAINT] CalculateTransforms failed. A={0}, B={1}", Body1.ID, Body2.ID); } } return ret; diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSHingeConstraint.cs b/OpenSim/Region/Physics/BulletSPlugin/BSHingeConstraint.cs index a6e4235..7c8a215 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSHingeConstraint.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSHingeConstraint.cs @@ -34,6 +34,8 @@ namespace OpenSim.Region.Physics.BulletSPlugin class BSHingeConstraint : BSConstraint { + public override ConstraintType Type { get { return ConstraintType.HINGE_CONSTRAINT_TYPE; } } + public BSHingeConstraint(BulletSim world, BulletBody obj1, BulletBody obj2, Vector3 pivotInA, Vector3 pivotInB, Vector3 axisInA, Vector3 axisInB, diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs index b0cc63c..dff71af 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs @@ -88,6 +88,7 @@ public class BSLinkset // Link to a linkset where the child knows the parent. // Parent changing should not happen so do some sanity checking. // We return the parent's linkset so the child can track its membership. + // Called at runtime. public BSLinkset AddMeToLinkset(BSPhysObject child) { lock (m_linksetActivityLock) @@ -102,6 +103,7 @@ public class BSLinkset // Remove a child from a linkset. // Returns a new linkset for the child which is a linkset of one (just the // orphened child). + // Called at runtime. public BSLinkset RemoveMeFromLinkset(BSPhysObject child) { lock (m_linksetActivityLock) @@ -113,27 +115,6 @@ public class BSLinkset } RemoveChildFromLinkset(child); - - /* Alternate implementation that destroys the linkset of the root is removed. - * This fails because items are added and removed from linksets to build shapes. - * Code left for reference. - if (IsRoot(child)) - { - // if root of linkset, take the linkset apart - while (m_children.Count > 0) - { - // Note that we don't do a foreach because the remove routine - // takes it out of the list. - RemoveChildFromOtherLinkset(m_children[0]); - } - m_children.Clear(); // just to make sure - } - else - { - // Just removing a child from an existing linkset - RemoveChildFromLinkset(child); - } - */ } // The child is down to a linkset of just itself @@ -169,6 +150,106 @@ public class BSLinkset return ret; } + // The object is going dynamic (physical). Do any setup necessary + // for a dynamic linkset. + // Only the state of the passed object can be modified. The rest of the linkset + // has not yet been fully constructed. + // Return 'true' if any properties updated on the passed object. + // Called at taint-time! + public bool MakeDynamic(BSPhysObject child) + { + // What is done for each object in BSPrim is what we want. + return false; + } + + // The object is going static (non-physical). Do any setup necessary + // for a static linkset. + // Return 'true' if any properties updated on the passed object. + // Called at taint-time! + public bool MakeStatic(BSPhysObject child) + { + // What is done for each object in BSPrim is what we want. + return false; + } + + // When physical properties are changed the linkset needs to recalculate + // its internal properties. + // Called at runtime. + public void Refresh(BSPhysObject requestor) + { + // If there are no children, there can't be any constraints to recompute + if (!HasAnyChildren) + return; + + // Only the root does the recomputation + if (IsRoot(requestor)) + { + PhysicsScene.TaintedObject("BSLinkSet.Refresh", delegate() + { + RecomputeLinksetConstraintVariables(); + }); + } + } + + // Routine used when rebuilding the body of the root of the linkset + // Destroy all the constraints have have been made to root. + // This is called when the root body is changing. + // Called at taint-time!! + public void RemoveBodyDependencies(BSPrim child) + { + lock (m_linksetActivityLock) + { + if (IsRoot(child)) + { + // If the one with the dependency is root, must undo all children + DetailLog("{0},BSLinkset.RemoveBodyDependencies,removeChildrenForRoot,rID={1},numChild={2}", + LinksetRoot.LocalID, m_children.Count); + foreach (BSPhysObject bpo in m_children) + { + PhysicallyUnlinkAChildFromRoot(LinksetRoot, LinksetRoot.BSBody, bpo, bpo.BSBody); + } + } + else + { + DetailLog("{0},BSLinkset.RemoveBodyDependencies,removeSingleChild,rID={1},rBody={2},cID={3},cBody={4}", + LinksetRoot.LocalID, LinksetRoot.BSBody.ptr.ToString("X"), + child.LocalID, child.BSBody.ptr.ToString("X")); + // Remove the dependency on the body of this one + PhysicallyUnlinkAChildFromRoot(LinksetRoot, LinksetRoot.BSBody, child, child.BSBody); + } + } + } + + // Routine used when rebuilding the body of the root of the linkset + // This is called after RemoveAllLinksToRoot() to restore all the constraints. + // This is called when the root body has been changed. + // Called at taint-time!! + public void RestoreBodyDependencies(BSPrim child) + { + lock (m_linksetActivityLock) + { + if (IsRoot(child)) + { + DetailLog("{0},BSLinkset.RestoreBodyDependencies,restoreChildrenForRoot,rID={1},numChild={2}", + LinksetRoot.LocalID, m_children.Count); + foreach (BSPhysObject bpo in m_children) + { + PhysicallyLinkAChildToRoot(LinksetRoot, LinksetRoot.BSBody, bpo, bpo.BSBody); + } + } + else + { + DetailLog("{0},BSLinkset.RestoreBodyDependencies,restoreSingleChild,rID={1},rBody={2},cID={3},cBody={4}", + LinksetRoot.LocalID, LinksetRoot.BSBody.ptr.ToString("X"), + child.LocalID, child.BSBody.ptr.ToString("X")); + PhysicallyLinkAChildToRoot(LinksetRoot, LinksetRoot.BSBody, child, child.BSBody); + } + } + } + + // ================================================================ + // Below this point is internal magic + private float ComputeLinksetMass() { float mass; @@ -220,46 +301,6 @@ public class BSLinkset return com; } - // The object is going dynamic (physical). Do any setup necessary - // for a dynamic linkset. - // Only the state of the passed object can be modified. The rest of the linkset - // has not yet been fully constructed. - // Return 'true' if any properties updated on the passed object. - // Called at taint-time! - public bool MakeDynamic(BSPhysObject child) - { - // What is done for each object in BSPrim is what we want. - return false; - } - - // The object is going static (non-physical). Do any setup necessary - // for a static linkset. - // Return 'true' if any properties updated on the passed object. - // Called at taint-time! - public bool MakeStatic(BSPhysObject child) - { - // What is done for each object in BSPrim is what we want. - return false; - } - - // When physical properties are changed the linkset needs to recalculate - // its internal properties. - public void Refresh(BSPhysObject requestor) - { - // If there are no children, there can't be any constraints to recompute - if (!HasAnyChildren) - return; - - // Only the root does the recomputation - if (IsRoot(requestor)) - { - PhysicsScene.TaintedObject("BSLinkSet.Refresh", delegate() - { - RecomputeLinksetConstraintVariables(); - }); - } - } - // Call each of the constraints that make up this linkset and recompute the // various transforms and variables. Used when objects are added or removed // from a linkset to make sure the constraints know about the new mass and @@ -327,6 +368,11 @@ public class BSLinkset BSPhysObject childx = child; BulletBody childBodyx = child.BSBody; + DetailLog("{0},AddChildToLinkset,call,rID={1},rBody={2},cID={3},cBody={4}", + rootx.LocalID, + rootx.LocalID, rootBodyx.ptr.ToString("X"), + childx.LocalID, childBodyx.ptr.ToString("X")); + PhysicsScene.TaintedObject("AddChildToLinkset", delegate() { DetailLog("{0},AddChildToLinkset,taint,child={1}", LinksetRoot.LocalID, child.LocalID); @@ -358,10 +404,14 @@ public class BSLinkset BulletBody rootBodyx = LinksetRoot.BSBody; BSPhysObject childx = child; BulletBody childBodyx = child.BSBody; + + DetailLog("{0},RemoveChildFromLinkset,call,child={1}", + rootx.LocalID, + rootx.LocalID, rootBodyx.ptr.ToString("X"), + childx.LocalID, childBodyx.ptr.ToString("X")); + PhysicsScene.TaintedObject("RemoveChildFromLinkset", delegate() { - DetailLog("{0},RemoveChildFromLinkset,taint,child={1}", LinksetRoot.LocalID, child.LocalID); - PhysicallyUnlinkAChildFromRoot(rootx, rootBodyx, childx, childBodyx); RecomputeLinksetConstraintVariables(); }); @@ -390,14 +440,15 @@ public class BSLinkset // real world coordinate of midpoint between the two objects OMV.Vector3 midPoint = rootPrim.Position + (childRelativePosition / 2); - // create a constraint that allows no freedom of movement between the two objects - // http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818 DetailLog("{0},PhysicallyLinkAChildToRoot,taint,root={1},rBody={2},child={3},cBody={4},rLoc={5},cLoc={6},midLoc={7}", rootPrim.LocalID, rootPrim.LocalID, rootBody.ptr.ToString("X"), childPrim.LocalID, childBody.ptr.ToString("X"), rootPrim.Position, childPrim.Position, midPoint); + // create a constraint that allows no freedom of movement between the two objects + // http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818 + // There is great subtlty in these paramters. Notice the check for a ptr of zero. // We pass the BulletBody structure into the taint in order to capture the pointer // of the body at the time of constraint creation. This doesn't work for the very first @@ -416,6 +467,7 @@ public class BSLinkset true, true ); + /* NOTE: below is an attempt to build constraint with full frame computation, etc. * Using the midpoint is easier since it lets the Bullet code manipulate the transforms * of the objects. diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index 8688485..c879143 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs @@ -1111,13 +1111,21 @@ public sealed class BSPrim : BSPhysObject // Undo me from any possible linkset so, if body is rebuilt, the link will get restored. // NOTE that the new linkset is not set. This saves the handle to the linkset // so we can add ourselves back when shape mangling is complete. - Linkset.RemoveMeFromLinkset(this); + bool needToRestoreLinkset = false; // Create the correct physical representation for this type of object. // Updates BSBody and BSShape with the new information. - PhysicsScene.Shapes.GetBodyAndShape(forceRebuild, PhysicsScene.World, this, shapeData, _pbs); + PhysicsScene.Shapes.GetBodyAndShape(forceRebuild, PhysicsScene.World, this, shapeData, _pbs, + null, delegate(BulletBody dBody) + { + // Called if the current prim body is about to be destroyed. + // The problem is the constraints for Linksets which need to be updated for the new body. + Linkset.RemoveBodyDependencies(this); + needToRestoreLinkset = true; + }); - Linkset = Linkset.AddMeToLinkset(this); + if (needToRestoreLinkset) + Linkset.RestoreBodyDependencies(this); // Make sure the properties are set on the new object UpdatePhysicalParameters(); diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs index b428ba3..2618971 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs @@ -81,12 +81,21 @@ public class BSShapeCollection : IDisposable // TODO!!!!!!!!! } + // Callbacks called just before either the body or shape is destroyed. + // Mostly used for changing bodies out from under Linksets. + // Useful for other cases where parameters need saving. + // Passing 'null' says no callback. + public delegate void ShapeDestructionCallback(BulletShape shape); + public delegate void BodyDestructionCallback(BulletBody body); + // Called to update/change the body and shape for an object. // First checks the shape and updates that if necessary then makes // sure the body is of the right type. // Return 'true' if either the body or the shape changed. // Called at taint-time!! - public bool GetBodyAndShape(bool forceRebuild, BulletSim sim, BSPrim prim, ShapeData shapeData, PrimitiveBaseShape pbs) + public bool GetBodyAndShape(bool forceRebuild, BulletSim sim, BSPrim prim, + ShapeData shapeData, PrimitiveBaseShape pbs, + ShapeDestructionCallback shapeCallback, BodyDestructionCallback bodyCallback) { bool ret = false; @@ -95,11 +104,11 @@ public class BSShapeCollection : IDisposable { // Do we have the correct geometry for this type of object? // Updates prim.BSShape with information/pointers to requested shape - bool newGeom = CreateGeom(forceRebuild, prim, shapeData, pbs); + bool newGeom = CreateGeom(forceRebuild, prim, shapeData, pbs, shapeCallback); // If we had to select a new shape geometry for the object, // rebuild the body around it. // Updates prim.BSBody with information/pointers to requested body - bool newBody = CreateBody((newGeom || forceRebuild), prim, PhysicsScene.World, prim.BSShape, shapeData); + bool newBody = CreateBody((newGeom || forceRebuild), prim, PhysicsScene.World, prim.BSShape, shapeData, bodyCallback); ret = newGeom || newBody; } DetailLog("{0},BSShapeCollection.GetBodyAndShape,force={1},ret={2},body={3},shape={4}", @@ -135,7 +144,7 @@ public class BSShapeCollection : IDisposable // Release the usage of a body. // Called when releasing use of a BSBody. BSShape is handled separately. - public void DereferenceBody(BulletBody shape, bool inTaintTime) + public void DereferenceBody(BulletBody shape, bool inTaintTime, BodyDestructionCallback bodyCallback ) { if (shape.ptr == IntPtr.Zero) return; @@ -244,7 +253,7 @@ public class BSShapeCollection : IDisposable // Release the usage of a shape. // The collisionObject is released since it is a copy of the real collision shape. - private void DereferenceShape(BulletShape shape, bool atTaintTime) + private void DereferenceShape(BulletShape shape, bool atTaintTime, ShapeDestructionCallback shapeCallback) { if (shape.ptr == IntPtr.Zero) return; @@ -254,10 +263,10 @@ public class BSShapeCollection : IDisposable switch (shape.type) { case ShapeData.PhysicsShapeType.SHAPE_HULL: - DereferenceHull(shape); + DereferenceHull(shape, shapeCallback); break; case ShapeData.PhysicsShapeType.SHAPE_MESH: - DereferenceMesh(shape); + DereferenceMesh(shape, shapeCallback); break; case ShapeData.PhysicsShapeType.SHAPE_UNKNOWN: break; @@ -267,6 +276,7 @@ public class BSShapeCollection : IDisposable { DetailLog("{0},BSShapeCollection.DereferenceShape,deleteNativeShape,ptr={1},taintTime={2}", BSScene.DetailLogZero, shape.ptr.ToString("X"), atTaintTime); + if (shapeCallback != null) shapeCallback(shape); BulletSimAPI.DeleteCollisionShape2(PhysicsScene.World.ptr, shape.ptr); } break; @@ -287,13 +297,14 @@ public class BSShapeCollection : IDisposable // Count down the reference count for a mesh shape // Called at taint-time. - private void DereferenceMesh(BulletShape shape) + private void DereferenceMesh(BulletShape shape, ShapeDestructionCallback shapeCallback) { MeshDesc meshDesc; if (Meshes.TryGetValue(shape.shapeKey, out meshDesc)) { meshDesc.referenceCount--; // TODO: release the Bullet storage + if (shapeCallback != null) shapeCallback(shape); meshDesc.lastReferenced = System.DateTime.Now; Meshes[shape.shapeKey] = meshDesc; DetailLog("{0},BSShapeCollection.DereferenceMesh,key={1},refCnt={2}", @@ -304,13 +315,14 @@ public class BSShapeCollection : IDisposable // Count down the reference count for a hull shape // Called at taint-time. - private void DereferenceHull(BulletShape shape) + private void DereferenceHull(BulletShape shape, ShapeDestructionCallback shapeCallback) { HullDesc hullDesc; if (Hulls.TryGetValue(shape.shapeKey, out hullDesc)) { hullDesc.referenceCount--; // TODO: release the Bullet storage (aging old entries?) + if (shapeCallback != null) shapeCallback(shape); hullDesc.lastReferenced = System.DateTime.Now; Hulls[shape.shapeKey] = hullDesc; DetailLog("{0},BSShapeCollection.DereferenceHull,key={1},refCnt={2}", @@ -324,7 +336,8 @@ public class BSShapeCollection : IDisposable // if 'forceRebuild' is true, the geometry is rebuilt. Otherwise a previously built version is used. // Returns 'true' if the geometry was rebuilt. // Called at taint-time! - private bool CreateGeom(bool forceRebuild, BSPrim prim, ShapeData shapeData, PrimitiveBaseShape pbs) + private bool CreateGeom(bool forceRebuild, BSPrim prim, ShapeData shapeData, + PrimitiveBaseShape pbs, ShapeDestructionCallback shapeCallback) { bool ret = false; bool haveShape = false; @@ -349,8 +362,8 @@ public class BSShapeCollection : IDisposable || prim.BSShape.type != ShapeData.PhysicsShapeType.SHAPE_SPHERE ) { - ret = GetReferenceToNativeShape(prim, shapeData, - ShapeData.PhysicsShapeType.SHAPE_SPHERE, ShapeData.FixedShapeKey.KEY_SPHERE); + ret = GetReferenceToNativeShape(prim, shapeData, ShapeData.PhysicsShapeType.SHAPE_SPHERE, + ShapeData.FixedShapeKey.KEY_SPHERE, shapeCallback); DetailLog("{0},BSShapeCollection.CreateGeom,sphere,force={1},shape={2}", prim.LocalID, forceRebuild, prim.BSShape); } @@ -363,8 +376,8 @@ public class BSShapeCollection : IDisposable || prim.BSShape.type != ShapeData.PhysicsShapeType.SHAPE_BOX ) { - ret = GetReferenceToNativeShape( - prim, shapeData, ShapeData.PhysicsShapeType.SHAPE_BOX, ShapeData.FixedShapeKey.KEY_BOX); + ret = GetReferenceToNativeShape( prim, shapeData, ShapeData.PhysicsShapeType.SHAPE_BOX, + ShapeData.FixedShapeKey.KEY_BOX, shapeCallback); DetailLog("{0},BSShapeCollection.CreateGeom,box,force={1},shape={2}", prim.LocalID, forceRebuild, prim.BSShape); } @@ -378,13 +391,13 @@ public class BSShapeCollection : IDisposable if (prim.IsPhysical) { // Update prim.BSShape to reference a hull of this shape. - ret = GetReferenceToHull(prim, shapeData, pbs); + ret = GetReferenceToHull(prim, shapeData, pbs, shapeCallback); DetailLog("{0},BSShapeCollection.CreateGeom,hull,shape={1},key={2}", shapeData.ID, prim.BSShape, prim.BSShape.shapeKey.ToString("X")); } else { - ret = GetReferenceToMesh(prim, shapeData, pbs); + ret = GetReferenceToMesh(prim, shapeData, pbs, shapeCallback); DetailLog("{0},BSShapeCollection.CreateGeom,mesh,shape={1},key={2}", shapeData.ID, prim.BSShape, prim.BSShape.shapeKey.ToString("X")); } @@ -394,7 +407,8 @@ public class BSShapeCollection : IDisposable // Creates a native shape and assignes it to prim.BSShape private bool GetReferenceToNativeShape( BSPrim prim, ShapeData shapeData, - ShapeData.PhysicsShapeType shapeType, ShapeData.FixedShapeKey shapeKey) + ShapeData.PhysicsShapeType shapeType, ShapeData.FixedShapeKey shapeKey, + ShapeDestructionCallback shapeCallback) { BulletShape newShape; @@ -404,7 +418,7 @@ public class BSShapeCollection : IDisposable shapeData.Scale = shapeData.Size; // release any previous shape - DereferenceShape(prim.BSShape, true); + DereferenceShape(prim.BSShape, true, shapeCallback); // Native shapes are always built independently. newShape = new BulletShape(BulletSimAPI.BuildNativeShape2(PhysicsScene.World.ptr, shapeData), shapeType); @@ -422,7 +436,8 @@ public class BSShapeCollection : IDisposable // Dereferences previous shape in BSShape and adds a reference for this new shape. // Returns 'true' of a mesh was actually built. Otherwise . // Called at taint-time! - private bool GetReferenceToMesh(BSPrim prim, ShapeData shapeData, PrimitiveBaseShape pbs) + private bool GetReferenceToMesh(BSPrim prim, ShapeData shapeData, PrimitiveBaseShape pbs, + ShapeDestructionCallback shapeCallback) { BulletShape newShape = new BulletShape(IntPtr.Zero); @@ -436,7 +451,7 @@ public class BSShapeCollection : IDisposable prim.LocalID, prim.BSShape.shapeKey.ToString("X"), newMeshKey.ToString("X")); // Since we're recreating new, get rid of the reference to the previous shape - DereferenceShape(prim.BSShape, true); + DereferenceShape(prim.BSShape, true, shapeCallback); newShape = CreatePhysicalMesh(prim.PhysObjectName, newMeshKey, pbs, shapeData.Size, lod); @@ -490,7 +505,8 @@ public class BSShapeCollection : IDisposable // See that hull shape exists in the physical world and update prim.BSShape. // We could be creating the hull because scale changed or whatever. - private bool GetReferenceToHull(BSPrim prim, ShapeData shapeData, PrimitiveBaseShape pbs) + private bool GetReferenceToHull(BSPrim prim, ShapeData shapeData, PrimitiveBaseShape pbs, + ShapeDestructionCallback shapeCallback) { BulletShape newShape; @@ -505,7 +521,7 @@ public class BSShapeCollection : IDisposable prim.LocalID, prim.BSShape.shapeKey.ToString("X"), newHullKey.ToString("X")); // Remove usage of the previous shape. Also removes reference to underlying mesh if it is a hull. - DereferenceShape(prim.BSShape, true); + DereferenceShape(prim.BSShape, true, shapeCallback); newShape = CreatePhysicalHull(prim.PhysObjectName, newHullKey, pbs, shapeData.Size, lod); @@ -656,7 +672,8 @@ public class BSShapeCollection : IDisposable // Updates prim.BSBody with the information about the new body if one is created. // Returns 'true' if an object was actually created. // Called at taint-time. - private bool CreateBody(bool forceRebuild, BSPrim prim, BulletSim sim, BulletShape shape, ShapeData shapeData) + private bool CreateBody(bool forceRebuild, BSPrim prim, BulletSim sim, BulletShape shape, + ShapeData shapeData, BodyDestructionCallback bodyCallback) { bool ret = false; @@ -679,7 +696,7 @@ public class BSShapeCollection : IDisposable if (mustRebuild || forceRebuild) { - DereferenceBody(prim.BSBody, true); + DereferenceBody(prim.BSBody, true, bodyCallback); BulletBody aBody; IntPtr bodyPtr = IntPtr.Zero; diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs index 544c53d..1125d7e 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs @@ -42,12 +42,12 @@ public struct BulletSim { ptr = xx; worldID = worldId; - scene = bss; + physicsScene = bss; } public IntPtr ptr; public uint worldID; // The scene is only in here so very low level routines have a handle to print debug/error messages - public BSScene scene; + public BSScene physicsScene; } // An allocated Bullet btRigidBody @@ -120,14 +120,27 @@ public struct BulletShape } } + // Constraint type values as defined by Bullet +public enum ConstraintType : int +{ + POINT2POINT_CONSTRAINT_TYPE = 3, + HINGE_CONSTRAINT_TYPE, + CONETWIST_CONSTRAINT_TYPE, + D6_CONSTRAINT_TYPE, + SLIDER_CONSTRAINT_TYPE, + CONTACT_CONSTRAINT_TYPE, + D6_SPRING_CONSTRAINT_TYPE, + MAX_CONSTRAINT_TYPE +} + // An allocated Bullet btConstraint public struct BulletConstraint { public BulletConstraint(IntPtr xx) { - Ptr = xx; + ptr = xx; } - public IntPtr Ptr; + public IntPtr ptr; } // An allocated HeightMapThing which holds various heightmap info. -- cgit v1.1 From 6f89975526359b81c43c23d9a549660d12212c59 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Thu, 27 Sep 2012 22:00:02 -0700 Subject: BulletSim: add separate runtime and taint-time linkset children lists to keep the creation of constraints separate from runtime. --- OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs | 145 +++++++++++---------- OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | 3 +- .../Physics/BulletSPlugin/BSShapeCollection.cs | 25 ++-- 3 files changed, 93 insertions(+), 80 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs index dff71af..4f225ae 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs @@ -43,8 +43,17 @@ public class BSLinkset static int m_nextLinksetID = 1; public int LinksetID { get; private set; } - // The children under the root in this linkset + // The children under the root in this linkset. + // There are two lists of children: the current children at runtime + // and the children at taint-time. For instance, if you delink a + // child from the linkset, the child is removed from m_children + // but the constraint won't be removed until taint time. + // Two lists lets this track the 'current' children and + // the physical 'taint' children separately. + // After taint processing and before the simulation step, these + // two lists must be the same. private List m_children; + private List m_taintChildren; // We lock the diddling of linkset classes to prevent any badness. // This locks the modification of the instances of this class. Changes @@ -82,6 +91,7 @@ public class BSLinkset PhysicsScene = scene; LinksetRoot = parent; m_children = new List(); + m_taintChildren = new List(); m_mass = parent.MassRaw; } @@ -194,30 +204,40 @@ public class BSLinkset // Routine used when rebuilding the body of the root of the linkset // Destroy all the constraints have have been made to root. // This is called when the root body is changing. + // Returns 'true' of something eas actually removed and would need restoring // Called at taint-time!! - public void RemoveBodyDependencies(BSPrim child) + public bool RemoveBodyDependencies(BSPrim child) { + bool ret = false; + lock (m_linksetActivityLock) { if (IsRoot(child)) { // If the one with the dependency is root, must undo all children DetailLog("{0},BSLinkset.RemoveBodyDependencies,removeChildrenForRoot,rID={1},numChild={2}", - LinksetRoot.LocalID, m_children.Count); - foreach (BSPhysObject bpo in m_children) + child.LocalID, LinksetRoot.LocalID, m_taintChildren.Count); + foreach (BSPhysObject bpo in m_taintChildren) { PhysicallyUnlinkAChildFromRoot(LinksetRoot, LinksetRoot.BSBody, bpo, bpo.BSBody); + ret = true; } } else { DetailLog("{0},BSLinkset.RemoveBodyDependencies,removeSingleChild,rID={1},rBody={2},cID={3},cBody={4}", + child.LocalID, LinksetRoot.LocalID, LinksetRoot.BSBody.ptr.ToString("X"), child.LocalID, child.BSBody.ptr.ToString("X")); // Remove the dependency on the body of this one - PhysicallyUnlinkAChildFromRoot(LinksetRoot, LinksetRoot.BSBody, child, child.BSBody); + if (m_taintChildren.Contains(child)) + { + PhysicallyUnlinkAChildFromRoot(LinksetRoot, LinksetRoot.BSBody, child, child.BSBody); + ret = true; + } } } + return ret; } // Routine used when rebuilding the body of the root of the linkset @@ -231,8 +251,8 @@ public class BSLinkset if (IsRoot(child)) { DetailLog("{0},BSLinkset.RestoreBodyDependencies,restoreChildrenForRoot,rID={1},numChild={2}", - LinksetRoot.LocalID, m_children.Count); - foreach (BSPhysObject bpo in m_children) + child.LocalID, LinksetRoot.LocalID, m_taintChildren.Count); + foreach (BSPhysObject bpo in m_taintChildren) { PhysicallyLinkAChildToRoot(LinksetRoot, LinksetRoot.BSBody, bpo, bpo.BSBody); } @@ -240,6 +260,7 @@ public class BSLinkset else { DetailLog("{0},BSLinkset.RestoreBodyDependencies,restoreSingleChild,rID={1},rBody={2},cID={3},cBody={4}", + LinksetRoot.LocalID, LinksetRoot.LocalID, LinksetRoot.BSBody.ptr.ToString("X"), child.LocalID, child.BSBody.ptr.ToString("X")); PhysicallyLinkAChildToRoot(LinksetRoot, LinksetRoot.BSBody, child, child.BSBody); @@ -256,7 +277,7 @@ public class BSLinkset lock (m_linksetActivityLock) { mass = LinksetRoot.MassRaw; - foreach (BSPhysObject bp in m_children) + foreach (BSPhysObject bp in m_taintChildren) { mass += bp.MassRaw; } @@ -272,7 +293,7 @@ public class BSLinkset com = LinksetRoot.Position * LinksetRoot.MassRaw; float totalMass = LinksetRoot.MassRaw; - foreach (BSPhysObject bp in m_children) + foreach (BSPhysObject bp in m_taintChildren) { com += bp.Position * bp.MassRaw; totalMass += bp.MassRaw; @@ -291,70 +312,16 @@ public class BSLinkset { com = LinksetRoot.Position; - foreach (BSPhysObject bp in m_children) + foreach (BSPhysObject bp in m_taintChildren) { com += bp.Position * bp.MassRaw; } - com /= (m_children.Count + 1); + com /= (m_taintChildren.Count + 1); } return com; } - // Call each of the constraints that make up this linkset and recompute the - // various transforms and variables. Used when objects are added or removed - // from a linkset to make sure the constraints know about the new mass and - // geometry. - // Must only be called at taint time!! - private void RecomputeLinksetConstraintVariables() - { - float linksetMass = LinksetMass; - lock (m_linksetActivityLock) - { - bool somethingMissing = false; - foreach (BSPhysObject child in m_children) - { - BSConstraint constrain; - if (PhysicsScene.Constraints.TryGetConstraint(LinksetRoot.BSBody, child.BSBody, out constrain)) - { - // DetailLog("{0},BSLinkset.RecomputeLinksetConstraintVariables,taint,child={1},mass={2},A={3},B={4}", - // LinksetRoot.LocalID, child.LocalID, linksetMass, constrain.Body1.ID, constrain.Body2.ID); - constrain.RecomputeConstraintVariables(linksetMass); - } - else - { - // Non-fatal error that happens when children are being added to the linkset but - // their constraints have not been created yet. - // Caused by the fact that m_children is built at run time but building constraints - // happens at taint time. - somethingMissing = true; - break; - } - } - - // If the whole linkset is not here, doesn't make sense to recompute linkset wide values - if (!somethingMissing) - { - // If this is a multiple object linkset, set everybody's center of mass to the set's center of mass - OMV.Vector3 centerOfMass = ComputeLinksetCenterOfMass(); - BulletSimAPI.SetCenterOfMassByPosRot2(LinksetRoot.BSBody.ptr, centerOfMass, OMV.Quaternion.Identity); - foreach (BSPhysObject child in m_children) - { - BulletSimAPI.SetCenterOfMassByPosRot2(child.BSBody.ptr, centerOfMass, OMV.Quaternion.Identity); - } - /* - // The root prim takes on the weight of the whole linkset - OMV.Vector3 inertia = BulletSimAPI.CalculateLocalInertia2(LinksetRoot.BSShape.Ptr, linksetMass); - BulletSimAPI.SetMassProps2(LinksetRoot.BSBody.Ptr, linksetMass, inertia); - OMV.Vector3 centerOfMass = ComputeLinksetCenterOfMass(); - BulletSimAPI.SetCenterOfMassByPosRot2(LinksetRoot.BSBody.Ptr, centerOfMass, OMV.Quaternion.Identity); - BulletSimAPI.UpdateInertiaTensor2(LinksetRoot.BSBody.Ptr); - */ - } - } - return; - } - // I am the root of a linkset and a new child is being added // Called while LinkActivity is locked. private void AddChildToLinkset(BSPhysObject child) @@ -377,6 +344,7 @@ public class BSLinkset { DetailLog("{0},AddChildToLinkset,taint,child={1}", LinksetRoot.LocalID, child.LocalID); // build the physical binding between me and the child + m_taintChildren.Add(childx); PhysicallyLinkAChildToRoot(rootx, rootBodyx, childx, childBodyx); }); } @@ -405,13 +373,16 @@ public class BSLinkset BSPhysObject childx = child; BulletBody childBodyx = child.BSBody; - DetailLog("{0},RemoveChildFromLinkset,call,child={1}", - rootx.LocalID, + DetailLog("{0},RemoveChildFromLinkset,call,rID={1},rBody={2},cID={3},cBody={4}", + childx.LocalID, rootx.LocalID, rootBodyx.ptr.ToString("X"), childx.LocalID, childBodyx.ptr.ToString("X")); PhysicsScene.TaintedObject("RemoveChildFromLinkset", delegate() { + if (m_taintChildren.Contains(childx)) + m_taintChildren.Remove(childx); + PhysicallyUnlinkAChildFromRoot(rootx, rootBodyx, childx, childBodyx); RecomputeLinksetConstraintVariables(); }); @@ -551,6 +522,46 @@ public class BSLinkset } */ + // Call each of the constraints that make up this linkset and recompute the + // various transforms and variables. Used when objects are added or removed + // from a linkset to make sure the constraints know about the new mass and + // geometry. + // Must only be called at taint time!! + private void RecomputeLinksetConstraintVariables() + { + float linksetMass = LinksetMass; + foreach (BSPhysObject child in m_taintChildren) + { + BSConstraint constrain; + if (PhysicsScene.Constraints.TryGetConstraint(LinksetRoot.BSBody, child.BSBody, out constrain)) + { + // DetailLog("{0},BSLinkset.RecomputeLinksetConstraintVariables,taint,child={1},mass={2},A={3},B={4}", + // LinksetRoot.LocalID, child.LocalID, linksetMass, constrain.Body1.ID, constrain.Body2.ID); + constrain.RecomputeConstraintVariables(linksetMass); + } + else + { + // Non-fatal error that happens when children are being added to the linkset but + // their constraints have not been created yet. + break; + } + } + + // If the whole linkset is not here, doesn't make sense to recompute linkset wide values + if (m_children.Count == m_taintChildren.Count) + { + // If this is a multiple object linkset, set everybody's center of mass to the set's center of mass + OMV.Vector3 centerOfMass = ComputeLinksetCenterOfMass(); + BulletSimAPI.SetCenterOfMassByPosRot2(LinksetRoot.BSBody.ptr, centerOfMass, OMV.Quaternion.Identity); + foreach (BSPhysObject child in m_taintChildren) + { + BulletSimAPI.SetCenterOfMassByPosRot2(child.BSBody.ptr, centerOfMass, OMV.Quaternion.Identity); + } + } + return; + } + + // Invoke the detailed logger and output something if it's enabled. private void DetailLog(string msg, params Object[] args) { diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index c879143..87ffe3e 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs @@ -1120,8 +1120,7 @@ public sealed class BSPrim : BSPhysObject { // Called if the current prim body is about to be destroyed. // The problem is the constraints for Linksets which need to be updated for the new body. - Linkset.RemoveBodyDependencies(this); - needToRestoreLinkset = true; + needToRestoreLinkset = Linkset.RemoveBodyDependencies(this); }); if (needToRestoreLinkset) diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs index 2618971..648910a 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs @@ -144,34 +144,37 @@ public class BSShapeCollection : IDisposable // Release the usage of a body. // Called when releasing use of a BSBody. BSShape is handled separately. - public void DereferenceBody(BulletBody shape, bool inTaintTime, BodyDestructionCallback bodyCallback ) + public void DereferenceBody(BulletBody body, bool inTaintTime, BodyDestructionCallback bodyCallback ) { - if (shape.ptr == IntPtr.Zero) + if (body.ptr == IntPtr.Zero) return; lock (m_collectionActivityLock) { BodyDesc bodyDesc; - if (Bodies.TryGetValue(shape.ID, out bodyDesc)) + if (Bodies.TryGetValue(body.ID, out bodyDesc)) { bodyDesc.referenceCount--; bodyDesc.lastReferenced = System.DateTime.Now; - Bodies[shape.ID] = bodyDesc; - DetailLog("{0},BSShapeCollection.DereferenceBody,ref={1}", shape.ID, bodyDesc.referenceCount); + Bodies[body.ID] = bodyDesc; + DetailLog("{0},BSShapeCollection.DereferenceBody,ref={1}", body.ID, bodyDesc.referenceCount); // If body is no longer being used, free it -- bodies are never shared. if (bodyDesc.referenceCount == 0) { - Bodies.Remove(shape.ID); + Bodies.Remove(body.ID); BSScene.TaintCallback removeOperation = delegate() { DetailLog("{0},BSShapeCollection.DereferenceBody,DestroyingBody. ptr={1}", - shape.ID, shape.ptr.ToString("X")); + body.ID, body.ptr.ToString("X")); + // If the caller needs to know, pass the event up. + if (bodyCallback != null) bodyCallback(body); + // Zero any reference to the shape so it is not freed when the body is deleted. - BulletSimAPI.SetCollisionShape2(PhysicsScene.World.ptr, shape.ptr, IntPtr.Zero); + BulletSimAPI.SetCollisionShape2(PhysicsScene.World.ptr, body.ptr, IntPtr.Zero); // It may have already been removed from the world in which case the next is a NOOP. - BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, shape.ptr); - BulletSimAPI.DestroyObject2(PhysicsScene.World.ptr, shape.ptr); + BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, body.ptr); + BulletSimAPI.DestroyObject2(PhysicsScene.World.ptr, body.ptr); }; // If already in taint-time, do the operations now. Otherwise queue for later. if (inTaintTime) @@ -182,7 +185,7 @@ public class BSShapeCollection : IDisposable } else { - DetailLog("{0},BSShapeCollection.DereferenceBody,DID NOT FIND BODY", shape.ID, bodyDesc.referenceCount); + DetailLog("{0},BSShapeCollection.DereferenceBody,DID NOT FIND BODY", body.ID, bodyDesc.referenceCount); } } } -- cgit v1.1 From 76e9cc41bd612035850e105a6fe34f483aab25e7 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Fri, 28 Sep 2012 12:34:50 -0700 Subject: BulletSim: remember to release the physical body and shape when a prim is destroyed. This fixes many problems with physical linksets. --- OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | 18 +++++++++--------- .../Region/Physics/BulletSPlugin/BSShapeCollection.cs | 14 +++++++------- 2 files changed, 16 insertions(+), 16 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index 87ffe3e..a0e627e 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs @@ -154,8 +154,9 @@ public sealed class BSPrim : BSPhysObject PhysicsScene.TaintedObject("BSPrim.destroy", delegate() { DetailLog("{0},BSPrim.Destroy,taint,", LocalID); - // everything in the C# world will get garbage collected. Tell the C++ world to free stuff. - BulletSimAPI.DestroyObject(PhysicsScene.WorldID, LocalID); + // If there are physical body and shape, release my use of same. + PhysicsScene.Shapes.DereferenceBody(BSBody, true, null); + PhysicsScene.Shapes.DereferenceShape(BSShape, true, null); }); } @@ -251,9 +252,6 @@ public sealed class BSPrim : BSPhysObject _rotationalVelocity = OMV.Vector3.Zero; // Zero some other properties directly into the physics engine - BulletSimAPI.SetLinearVelocity2(BSBody.ptr, OMV.Vector3.Zero); - BulletSimAPI.SetAngularVelocity2(BSBody.ptr, OMV.Vector3.Zero); - BulletSimAPI.SetInterpolationVelocity2(BSBody.ptr, OMV.Vector3.Zero, OMV.Vector3.Zero); BulletSimAPI.ClearForces2(BSBody.ptr); } @@ -1108,9 +1106,8 @@ public sealed class BSPrim : BSPhysObject ShapeData shapeData; FillShapeInfo(out shapeData); - // Undo me from any possible linkset so, if body is rebuilt, the link will get restored. - // NOTE that the new linkset is not set. This saves the handle to the linkset - // so we can add ourselves back when shape mangling is complete. + // If this prim is part of a linkset, we must remove and restore the physical + // links of the body is rebuilt. bool needToRestoreLinkset = false; // Create the correct physical representation for this type of object. @@ -1119,12 +1116,15 @@ public sealed class BSPrim : BSPhysObject null, delegate(BulletBody dBody) { // Called if the current prim body is about to be destroyed. - // The problem is the constraints for Linksets which need to be updated for the new body. + // Remove all the physical dependencies on the old body. needToRestoreLinkset = Linkset.RemoveBodyDependencies(this); }); if (needToRestoreLinkset) + { + // If physical body dependencies were removed, restore them Linkset.RestoreBodyDependencies(this); + } // Make sure the properties are set on the new object UpdatePhysicalParameters(); diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs index 648910a..dee6243 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs @@ -120,25 +120,25 @@ public class BSShapeCollection : IDisposable // Track another user of a body // We presume the caller has allocated the body. // Bodies only have one user so the reference count is either 1 or 0. - public void ReferenceBody(BulletBody shape, bool atTaintTime) + public void ReferenceBody(BulletBody body, bool atTaintTime) { lock (m_collectionActivityLock) { BodyDesc bodyDesc; - if (Bodies.TryGetValue(shape.ID, out bodyDesc)) + if (Bodies.TryGetValue(body.ID, out bodyDesc)) { bodyDesc.referenceCount++; - DetailLog("{0},BSShapeCollection.ReferenceBody,existingBody,ref={1}", shape.ID, bodyDesc.referenceCount); + DetailLog("{0},BSShapeCollection.ReferenceBody,existingBody,body={1},ref={2}", body.ID, body, bodyDesc.referenceCount); } else { // New entry - bodyDesc.ptr = shape.ptr; + bodyDesc.ptr = body.ptr; bodyDesc.referenceCount = 1; - DetailLog("{0},BSShapeCollection.ReferenceBody,newBody,ref={1}", shape.ID, bodyDesc.referenceCount); + DetailLog("{0},BSShapeCollection.ReferenceBody,newBody,ref={1}", body.ID, body, bodyDesc.referenceCount); } bodyDesc.lastReferenced = System.DateTime.Now; - Bodies[shape.ID] = bodyDesc; + Bodies[body.ID] = bodyDesc; } } @@ -256,7 +256,7 @@ public class BSShapeCollection : IDisposable // Release the usage of a shape. // The collisionObject is released since it is a copy of the real collision shape. - private void DereferenceShape(BulletShape shape, bool atTaintTime, ShapeDestructionCallback shapeCallback) + public void DereferenceShape(BulletShape shape, bool atTaintTime, ShapeDestructionCallback shapeCallback) { if (shape.ptr == IntPtr.Zero) return; -- cgit v1.1 From d588467d5b77c5c71bb8efd415af6a2a5faf1b10 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Sat, 29 Sep 2012 00:07:11 +0100 Subject: Extend attachment regression test to check for appropriate attach event firing. This reveals that the event is not being fired when an object is attached from ground, which is incorrect. This check is temporairly disabled. --- .../Attachments/Tests/AttachmentsModuleTests.cs | 74 ++++++++++++++-------- 1 file changed, 49 insertions(+), 25 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs index 51e10f5..8d4e2e0 100644 --- a/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs +++ b/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs @@ -64,6 +64,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests private AutoResetEvent m_chatEvent = new AutoResetEvent(false); // private OSChatMessage m_osChatMessageReceived; + // Used to test whether the operations have fired the attach event. Must be reset after each test. + private int m_numberOfAttachEventsFired; + [TestFixtureSetUp] public void FixtureInit() { @@ -99,6 +102,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests "attachments-test-scene", TestHelpers.ParseTail(999), 1000, 1000, config); SceneHelpers.SetupSceneModules(scene, config, modules.ToArray()); + scene.EventManager.OnAttach += (localID, itemID, avatarID) => m_numberOfAttachEventsFired++; + return scene; } @@ -181,6 +186,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests TestHelpers.InMethod(); // TestHelpers.EnableLogging(); + m_numberOfAttachEventsFired = 0; + Scene scene = CreateTestScene(); UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene, 0x1); ScenePresence sp = SceneHelpers.AddScenePresence(scene, ua1); @@ -189,6 +196,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests SceneObjectGroup so = SceneHelpers.AddSceneObject(scene, attName, sp.UUID); + m_numberOfAttachEventsFired = 0; scene.AttachmentsModule.AttachObject(sp, so, (uint)AttachmentPoint.Chest, false, false); // Check status on scene presence @@ -216,7 +224,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1)); -// TestHelpers.DisableLogging(); + // Check events + + // FIXME: This is currently not occuring! +// Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(1)); } /// @@ -228,6 +239,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests TestHelpers.InMethod(); // TestHelpers.EnableLogging(); + m_numberOfAttachEventsFired = 0; + Scene scene = CreateTestScene(); UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene, 0x1); ScenePresence sp = SceneHelpers.AddScenePresence(scene, ua1); @@ -247,6 +260,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests Assert.That(sp.HasAttachments(), Is.False); Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1)); + + // Check events + Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(0)); } [Test] @@ -261,6 +277,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests InventoryItemBase attItem = CreateAttachmentItem(scene, ua1.PrincipalID, "att", 0x10, 0x20); + m_numberOfAttachEventsFired = 0; scene.AttachmentsModule.RezSingleAttachmentFromInventory( sp, attItem.ID, (uint)AttachmentPoint.Chest); @@ -280,6 +297,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests Assert.That(sp.Appearance.GetAttachpoint(attItem.ID), Is.EqualTo((int)AttachmentPoint.Chest)); Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1)); + + // Check events + Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(1)); } /// @@ -338,6 +358,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests ISceneEntity so = scene.AttachmentsModule.RezSingleAttachmentFromInventory( sp, attItem.ID, (uint)AttachmentPoint.Chest); + + m_numberOfAttachEventsFired = 0; scene.AttachmentsModule.DetachSingleAttachmentToGround(sp, so.LocalId); // Check scene presence status @@ -353,6 +375,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests // Check object in scene Assert.That(scene.GetSceneObjectGroup("att"), Is.Not.Null); + + // Check events + Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(1)); } [Test] @@ -369,6 +394,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests SceneObjectGroup so = (SceneObjectGroup)scene.AttachmentsModule.RezSingleAttachmentFromInventory( sp, attItem.ID, (uint)AttachmentPoint.Chest); + + m_numberOfAttachEventsFired = 0; scene.AttachmentsModule.DetachSingleAttachmentToInv(sp, so); // Check status on scene presence @@ -380,6 +407,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests Assert.That(sp.Appearance.GetAttachpoint(attItem.ID), Is.EqualTo(0)); Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(0)); + + // Check events + Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(1)); } /// @@ -461,10 +491,14 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests SceneObjectGroup rezzedAtt = presence.GetAttachments()[0]; + m_numberOfAttachEventsFired = 0; scene.IncomingCloseAgent(presence.UUID, false); // Check that we can't retrieve this attachment from the scene. Assert.That(scene.GetSceneObjectGroup(rezzedAtt.UUID), Is.Null); + + // Check events + Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(0)); } [Test] @@ -480,6 +514,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests AgentCircuitData acd = SceneHelpers.GenerateAgentData(ua1.PrincipalID); acd.Appearance = new AvatarAppearance(); acd.Appearance.SetAttachment((int)AttachmentPoint.Chest, attItem.ID, attItem.AssetID); + + m_numberOfAttachEventsFired = 0; ScenePresence presence = SceneHelpers.AddScenePresence(scene, acd); Assert.That(presence.HasAttachments(), Is.True); @@ -502,6 +538,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests Assert.That(presence.Appearance.GetAttachpoint(attItem.ID), Is.EqualTo((int)AttachmentPoint.Chest)); Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1)); + + // Check events. We expect OnAttach to fire on login. + Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(1)); } [Test] @@ -522,10 +561,14 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests Vector3 newPosition = new Vector3(1, 2, 4); + m_numberOfAttachEventsFired = 0; scene.SceneGraph.UpdatePrimGroupPosition(attSo.LocalId, newPosition, sp.ControllingClient); Assert.That(attSo.AbsolutePosition, Is.EqualTo(sp.AbsolutePosition)); Assert.That(attSo.RootPart.AttachedPos, Is.EqualTo(newPosition)); + + // Check events + Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(0)); } [Test] @@ -574,6 +617,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests Vector3 teleportPosition = new Vector3(10, 11, 12); Vector3 teleportLookAt = new Vector3(20, 21, 22); + m_numberOfAttachEventsFired = 0; sceneA.RequestTeleportLocation( beforeTeleportSp.ControllingClient, sceneB.RegionInfo.RegionHandle, @@ -616,29 +660,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests Assert.That(actualSceneAAttachments.Count, Is.EqualTo(0)); Assert.That(sceneA.GetSceneObjectGroups().Count, Is.EqualTo(0)); - } - // I'm commenting this test because scene setup NEEDS InventoryService to - // be non-null - //[Test] -// public void T032_CrossAttachments() -// { -// TestHelpers.InMethod(); -// -// ScenePresence presence = scene.GetScenePresence(agent1); -// ScenePresence presence2 = scene2.GetScenePresence(agent1); -// presence2.AddAttachment(sog1); -// presence2.AddAttachment(sog2); -// -// ISharedRegionModule serialiser = new SerialiserModule(); -// SceneHelpers.SetupSceneModules(scene, new IniConfigSource(), serialiser); -// SceneHelpers.SetupSceneModules(scene2, new IniConfigSource(), serialiser); -// -// Assert.That(presence.HasAttachments(), Is.False, "Presence has attachments before cross"); -// -// //Assert.That(presence2.CrossAttachmentsIntoNewRegion(region1, true), Is.True, "Cross was not successful"); -// Assert.That(presence2.HasAttachments(), Is.False, "Presence2 objects were not deleted"); -// Assert.That(presence.HasAttachments(), Is.True, "Presence has not received new objects"); -// } + // Check events + Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(0)); + } } -} +} \ No newline at end of file -- cgit v1.1 From 818379ba14e487568571113d24a9de7c3a29b458 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Sat, 29 Sep 2012 01:14:23 +0100 Subject: Fire EventManager.TriggerOnAttach (and hence LSL attach event) when an object is attached from the scene. Enables previously disabled regression test. Based on SingpostMarv's patch in http://opensimulator.org/mantis/view.php?id=6302 but I prefer a simpler approach that does not expose a resume scripts option right now. --- .../Avatar/Attachments/AttachmentsModule.cs | 28 +++++++++++++--------- .../Attachments/Tests/AttachmentsModuleTests.cs | 4 +--- 2 files changed, 18 insertions(+), 14 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs index c74584c..130c869 100644 --- a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs @@ -238,9 +238,23 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments sp.ClearAttachments(); } - + public bool AttachObject(IScenePresence sp, SceneObjectGroup group, uint attachmentPt, bool silent, bool temp) { + if (!Enabled) + return false; + + if (AttachObjectInternal(sp, group, attachmentPt, silent, temp)) + { + m_scene.EventManager.TriggerOnAttach(group.LocalId, group.FromItemID, sp.UUID); + return true; + } + + return false; + } + + private bool AttachObjectInternal(IScenePresence sp, SceneObjectGroup group, uint attachmentPt, bool silent, bool temp) + { lock (sp.AttachmentsSyncLock) { // m_log.DebugFormat( @@ -794,7 +808,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments // This will throw if the attachment fails try { - AttachObject(sp, objatt, attachmentPt, false, false); + AttachObjectInternal(sp, objatt, attachmentPt, false, false); } catch (Exception e) { @@ -951,15 +965,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments AttachmentPt &= 0x7f; // Calls attach with a Zero position - if (AttachObject(sp, part.ParentGroup, AttachmentPt, false, false)) - { -// m_log.Debug( -// "[ATTACHMENTS MODULE]: Saving avatar attachment. AgentID: " + remoteClient.AgentId -// + ", AttachmentPoint: " + AttachmentPt); - - // Save avatar attachment information - m_scene.EventManager.TriggerOnAttach(objectLocalID, part.ParentGroup.FromItemID, remoteClient.AgentId); - } + AttachObject(sp, part.ParentGroup, AttachmentPt, false, false); } catch (Exception e) { diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs index 8d4e2e0..0ee01c7 100644 --- a/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs +++ b/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs @@ -225,9 +225,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1)); // Check events - - // FIXME: This is currently not occuring! -// Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(1)); + Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(1)); } /// -- cgit v1.1 From 531edd51d82ecd6a842a2611c99e9919634491ef Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Sun, 30 Sep 2012 07:22:55 -0700 Subject: Added request.Proxy=null everywhere, as discussed in http://stackoverflow.com/questions/2519655/httpwebrequest-is-extremely-slow. Thanks R.Gunther (rigun@rigutech.nl) https://lists.berlios.de/pipermail/opensim-users/2012-September/010986.html --- .../CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs | 1 + .../CoreModules/Scripting/LoadImageURL/LoadImageURLModule.cs | 12 +++++++----- .../CoreModules/Scripting/VectorRender/VectorRenderModule.cs | 1 + OpenSim/Region/CoreModules/World/Archiver/ArchiveHelpers.cs | 1 + OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs | 1 + OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs | 1 + .../OptionalModules/Avatar/Concierge/ConciergeModule.cs | 2 +- .../Avatar/Voice/FreeSwitchVoice/FreeSwitchVoiceModule.cs | 1 + .../Avatar/Voice/VivoxVoice/VivoxVoiceModule.cs | 1 + .../XmlRpcGroups/XmlRpcGroupsServicesConnectorModule.cs | 1 + .../Scripting/RegionReadyModule/RegionReadyModule.cs | 1 + 11 files changed, 17 insertions(+), 6 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs b/OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs index d328eb3..2be91c0 100644 --- a/OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs +++ b/OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs @@ -384,6 +384,7 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest Request = (HttpWebRequest) WebRequest.Create(Url); Request.Method = HttpMethod; Request.ContentType = HttpMIMEType; + Request.Proxy = null; if(!HttpVerifyCert) { diff --git a/OpenSim/Region/CoreModules/Scripting/LoadImageURL/LoadImageURLModule.cs b/OpenSim/Region/CoreModules/Scripting/LoadImageURL/LoadImageURLModule.cs index 45e6527..5af3326 100644 --- a/OpenSim/Region/CoreModules/Scripting/LoadImageURL/LoadImageURLModule.cs +++ b/OpenSim/Region/CoreModules/Scripting/LoadImageURL/LoadImageURLModule.cs @@ -148,19 +148,21 @@ namespace OpenSim.Region.CoreModules.Scripting.LoadImageURL private void MakeHttpRequest(string url, UUID requestID) { WebRequest request = HttpWebRequest.Create(url); - - if (m_proxyurl != null && m_proxyurl.Length > 0) + + if (m_proxyurl != null && m_proxyurl.Length > 0) { - if (m_proxyexcepts != null && m_proxyexcepts.Length > 0) + if (m_proxyexcepts != null && m_proxyexcepts.Length > 0) { string[] elist = m_proxyexcepts.Split(';'); request.Proxy = new WebProxy(m_proxyurl, true, elist); - } - else + } + else { request.Proxy = new WebProxy(m_proxyurl, true); } } + else + request.Proxy = null; RequestState state = new RequestState((HttpWebRequest) request, requestID); // IAsyncResult result = request.BeginGetResponse(new AsyncCallback(HttpRequestReturn), state); diff --git a/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs b/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs index b4e3d77..9def6ee 100644 --- a/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs +++ b/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs @@ -826,6 +826,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender try { WebRequest request = HttpWebRequest.Create(url); + request.Proxy = null; //Ckrinke: Comment out for now as 'str' is unused. Bring it back into play later when it is used. //Ckrinke Stream str = null; HttpWebResponse response = (HttpWebResponse)(request).GetResponse(); diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveHelpers.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveHelpers.cs index c72acc3..ff8f119 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveHelpers.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveHelpers.cs @@ -110,6 +110,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver request.ContentLength = 0; request.KeepAlive = false; + request.Proxy = null; WebResponse response = request.GetResponse(); Stream file = response.GetResponseStream(); diff --git a/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs b/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs index 4694b14..c70031f 100644 --- a/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs +++ b/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs @@ -352,6 +352,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain request.ContentLength = 0; request.KeepAlive = false; + request.Proxy = null; WebResponse response = request.GetResponse(); Stream file = response.GetResponseStream(); diff --git a/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs b/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs index dfba3ff..0fdc5a8 100644 --- a/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs +++ b/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs @@ -819,6 +819,7 @@ namespace OpenSim.Region.CoreModules.World.WorldMap mapitemsrequest.Method = "POST"; mapitemsrequest.ContentType = "application/xml+llsd"; + mapitemsrequest.Proxy = null; OSDMap RAMap = new OSDMap(); // string RAMapString = RAMap.ToString(); diff --git a/OpenSim/Region/OptionalModules/Avatar/Concierge/ConciergeModule.cs b/OpenSim/Region/OptionalModules/Avatar/Concierge/ConciergeModule.cs index e22618d..fbbb60f 100644 --- a/OpenSim/Region/OptionalModules/Avatar/Concierge/ConciergeModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/Concierge/ConciergeModule.cs @@ -386,7 +386,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Concierge updatePost.ContentType = "text/xml"; updatePost.ContentLength = payload.Length; updatePost.UserAgent = "OpenSim.Concierge"; - + updatePost.Proxy = null; BrokerState bs = new BrokerState(uri, payload, updatePost); bs.Timer = new Timer(delegate(object state) diff --git a/OpenSim/Region/OptionalModules/Avatar/Voice/FreeSwitchVoice/FreeSwitchVoiceModule.cs b/OpenSim/Region/OptionalModules/Avatar/Voice/FreeSwitchVoice/FreeSwitchVoiceModule.cs index 37ab35a..8a5ce62 100644 --- a/OpenSim/Region/OptionalModules/Avatar/Voice/FreeSwitchVoice/FreeSwitchVoiceModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/Voice/FreeSwitchVoice/FreeSwitchVoiceModule.cs @@ -541,6 +541,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.FreeSwitchVoice forwardreq.Method = method; forwardreq.ContentType = contenttype; forwardreq.KeepAlive = false; + forwardreq.Proxy = null; if (method == "POST") { diff --git a/OpenSim/Region/OptionalModules/Avatar/Voice/VivoxVoice/VivoxVoiceModule.cs b/OpenSim/Region/OptionalModules/Avatar/Voice/VivoxVoice/VivoxVoiceModule.cs index c5fcef4..f5d8e19 100644 --- a/OpenSim/Region/OptionalModules/Avatar/Voice/VivoxVoice/VivoxVoiceModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/Voice/VivoxVoice/VivoxVoiceModule.cs @@ -1119,6 +1119,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice // We are sending just parameters, no content req.ContentLength = 0; + req.Proxy = null; // Send request and retrieve the response rsp = (HttpWebResponse)req.GetResponse(); diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/XmlRpcGroupsServicesConnectorModule.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/XmlRpcGroupsServicesConnectorModule.cs index d412cd1..5102115 100644 --- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/XmlRpcGroupsServicesConnectorModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/XmlRpcGroupsServicesConnectorModule.cs @@ -1150,6 +1150,7 @@ namespace Nwc.XmlRpc request.ContentType = "text/xml"; request.AllowWriteStreamBuffering = true; request.KeepAlive = !_disableKeepAlive; + request.Proxy = null; Stream stream = request.GetRequestStream(); XmlTextWriter xml = new XmlTextWriter(stream, Encoding.ASCII); diff --git a/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs b/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs index bad75f7..3e476ce 100644 --- a/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs +++ b/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs @@ -280,6 +280,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.RegionReady WebRequest request = WebRequest.Create(m_uri); request.Method = request_method; request.ContentType = content_type; + request.Proxy = null; Stream os = null; try -- cgit v1.1 From 91a5c602e313b96ffaf1d50b7f0d2923a2e141ba Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Sun, 30 Sep 2012 07:48:03 -0700 Subject: Revert "Added request.Proxy=null everywhere, as discussed in http://stackoverflow.com/questions/2519655/httpwebrequest-is-extremely-slow." But the patch is here, in case anyone wants to try it. This reverts commit 531edd51d82ecd6a842a2611c99e9919634491ef. --- .../CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs | 1 - .../CoreModules/Scripting/LoadImageURL/LoadImageURLModule.cs | 12 +++++------- .../CoreModules/Scripting/VectorRender/VectorRenderModule.cs | 1 - OpenSim/Region/CoreModules/World/Archiver/ArchiveHelpers.cs | 1 - OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs | 1 - OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs | 1 - .../OptionalModules/Avatar/Concierge/ConciergeModule.cs | 2 +- .../Avatar/Voice/FreeSwitchVoice/FreeSwitchVoiceModule.cs | 1 - .../Avatar/Voice/VivoxVoice/VivoxVoiceModule.cs | 1 - .../XmlRpcGroups/XmlRpcGroupsServicesConnectorModule.cs | 1 - .../Scripting/RegionReadyModule/RegionReadyModule.cs | 1 - 11 files changed, 6 insertions(+), 17 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs b/OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs index 2be91c0..d328eb3 100644 --- a/OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs +++ b/OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs @@ -384,7 +384,6 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest Request = (HttpWebRequest) WebRequest.Create(Url); Request.Method = HttpMethod; Request.ContentType = HttpMIMEType; - Request.Proxy = null; if(!HttpVerifyCert) { diff --git a/OpenSim/Region/CoreModules/Scripting/LoadImageURL/LoadImageURLModule.cs b/OpenSim/Region/CoreModules/Scripting/LoadImageURL/LoadImageURLModule.cs index 5af3326..45e6527 100644 --- a/OpenSim/Region/CoreModules/Scripting/LoadImageURL/LoadImageURLModule.cs +++ b/OpenSim/Region/CoreModules/Scripting/LoadImageURL/LoadImageURLModule.cs @@ -148,21 +148,19 @@ namespace OpenSim.Region.CoreModules.Scripting.LoadImageURL private void MakeHttpRequest(string url, UUID requestID) { WebRequest request = HttpWebRequest.Create(url); - - if (m_proxyurl != null && m_proxyurl.Length > 0) + + if (m_proxyurl != null && m_proxyurl.Length > 0) { - if (m_proxyexcepts != null && m_proxyexcepts.Length > 0) + if (m_proxyexcepts != null && m_proxyexcepts.Length > 0) { string[] elist = m_proxyexcepts.Split(';'); request.Proxy = new WebProxy(m_proxyurl, true, elist); - } - else + } + else { request.Proxy = new WebProxy(m_proxyurl, true); } } - else - request.Proxy = null; RequestState state = new RequestState((HttpWebRequest) request, requestID); // IAsyncResult result = request.BeginGetResponse(new AsyncCallback(HttpRequestReturn), state); diff --git a/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs b/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs index 9def6ee..b4e3d77 100644 --- a/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs +++ b/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs @@ -826,7 +826,6 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender try { WebRequest request = HttpWebRequest.Create(url); - request.Proxy = null; //Ckrinke: Comment out for now as 'str' is unused. Bring it back into play later when it is used. //Ckrinke Stream str = null; HttpWebResponse response = (HttpWebResponse)(request).GetResponse(); diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveHelpers.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveHelpers.cs index ff8f119..c72acc3 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveHelpers.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveHelpers.cs @@ -110,7 +110,6 @@ namespace OpenSim.Region.CoreModules.World.Archiver request.ContentLength = 0; request.KeepAlive = false; - request.Proxy = null; WebResponse response = request.GetResponse(); Stream file = response.GetResponseStream(); diff --git a/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs b/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs index c70031f..4694b14 100644 --- a/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs +++ b/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs @@ -352,7 +352,6 @@ namespace OpenSim.Region.CoreModules.World.Terrain request.ContentLength = 0; request.KeepAlive = false; - request.Proxy = null; WebResponse response = request.GetResponse(); Stream file = response.GetResponseStream(); diff --git a/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs b/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs index 0fdc5a8..dfba3ff 100644 --- a/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs +++ b/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs @@ -819,7 +819,6 @@ namespace OpenSim.Region.CoreModules.World.WorldMap mapitemsrequest.Method = "POST"; mapitemsrequest.ContentType = "application/xml+llsd"; - mapitemsrequest.Proxy = null; OSDMap RAMap = new OSDMap(); // string RAMapString = RAMap.ToString(); diff --git a/OpenSim/Region/OptionalModules/Avatar/Concierge/ConciergeModule.cs b/OpenSim/Region/OptionalModules/Avatar/Concierge/ConciergeModule.cs index fbbb60f..e22618d 100644 --- a/OpenSim/Region/OptionalModules/Avatar/Concierge/ConciergeModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/Concierge/ConciergeModule.cs @@ -386,7 +386,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Concierge updatePost.ContentType = "text/xml"; updatePost.ContentLength = payload.Length; updatePost.UserAgent = "OpenSim.Concierge"; - updatePost.Proxy = null; + BrokerState bs = new BrokerState(uri, payload, updatePost); bs.Timer = new Timer(delegate(object state) diff --git a/OpenSim/Region/OptionalModules/Avatar/Voice/FreeSwitchVoice/FreeSwitchVoiceModule.cs b/OpenSim/Region/OptionalModules/Avatar/Voice/FreeSwitchVoice/FreeSwitchVoiceModule.cs index 8a5ce62..37ab35a 100644 --- a/OpenSim/Region/OptionalModules/Avatar/Voice/FreeSwitchVoice/FreeSwitchVoiceModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/Voice/FreeSwitchVoice/FreeSwitchVoiceModule.cs @@ -541,7 +541,6 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.FreeSwitchVoice forwardreq.Method = method; forwardreq.ContentType = contenttype; forwardreq.KeepAlive = false; - forwardreq.Proxy = null; if (method == "POST") { diff --git a/OpenSim/Region/OptionalModules/Avatar/Voice/VivoxVoice/VivoxVoiceModule.cs b/OpenSim/Region/OptionalModules/Avatar/Voice/VivoxVoice/VivoxVoiceModule.cs index f5d8e19..c5fcef4 100644 --- a/OpenSim/Region/OptionalModules/Avatar/Voice/VivoxVoice/VivoxVoiceModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/Voice/VivoxVoice/VivoxVoiceModule.cs @@ -1119,7 +1119,6 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice // We are sending just parameters, no content req.ContentLength = 0; - req.Proxy = null; // Send request and retrieve the response rsp = (HttpWebResponse)req.GetResponse(); diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/XmlRpcGroupsServicesConnectorModule.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/XmlRpcGroupsServicesConnectorModule.cs index 5102115..d412cd1 100644 --- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/XmlRpcGroupsServicesConnectorModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/XmlRpcGroupsServicesConnectorModule.cs @@ -1150,7 +1150,6 @@ namespace Nwc.XmlRpc request.ContentType = "text/xml"; request.AllowWriteStreamBuffering = true; request.KeepAlive = !_disableKeepAlive; - request.Proxy = null; Stream stream = request.GetRequestStream(); XmlTextWriter xml = new XmlTextWriter(stream, Encoding.ASCII); diff --git a/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs b/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs index 3e476ce..bad75f7 100644 --- a/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs +++ b/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs @@ -280,7 +280,6 @@ namespace OpenSim.Region.OptionalModules.Scripting.RegionReady WebRequest request = WebRequest.Create(m_uri); request.Method = request_method; request.ContentType = content_type; - request.Proxy = null; Stream os = null; try -- cgit v1.1 From f8a4b61954707a0adb7a20f7a1b530631c15aa79 Mon Sep 17 00:00:00 2001 From: Melanie Date: Sun, 30 Sep 2012 15:49:51 +0100 Subject: Allow up to 12 simultaneous connections to a given endpoint rather than 2 --- OpenSim/Region/Application/Application.cs | 1 + 1 file changed, 1 insertion(+) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Application/Application.cs b/OpenSim/Region/Application/Application.cs index ebfebc4..a5a5201 100644 --- a/OpenSim/Region/Application/Application.cs +++ b/OpenSim/Region/Application/Application.cs @@ -73,6 +73,7 @@ namespace OpenSim AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException); + ServicePointManager.DefaultConnectionLimit = 12; // Add the arguments supplied when running the application to the configuration ArgvConfigSource configSource = new ArgvConfigSource(args); -- cgit v1.1 From 7cc89cdadccd743a4c1ad8a7f16e896842d849e6 Mon Sep 17 00:00:00 2001 From: Melanie Date: Sun, 30 Sep 2012 15:57:49 +0100 Subject: Add using clause I missed --- OpenSim/Region/Application/Application.cs | 1 + 1 file changed, 1 insertion(+) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Application/Application.cs b/OpenSim/Region/Application/Application.cs index a5a5201..0f90d37 100644 --- a/OpenSim/Region/Application/Application.cs +++ b/OpenSim/Region/Application/Application.cs @@ -27,6 +27,7 @@ using System; using System.IO; +using System.Net; using System.Reflection; using log4net; using log4net.Config; -- cgit v1.1 From 402128bb536ba19bd9c9962146ca04ad493de4e3 Mon Sep 17 00:00:00 2001 From: Melanie Date: Tue, 2 Oct 2012 00:51:38 +0100 Subject: Prevent the ExtraSettings code from crashing SQLite driven sims. --- OpenSim/Region/Framework/Scenes/Scene.cs | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 2e03874..0a4aa4a 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -5545,6 +5545,9 @@ namespace OpenSim.Region.Framework.Scenes public void StoreExtraSetting(string name, string val) { + if (m_extraSettings == null) + return; + string oldVal; if (m_extraSettings.TryGetValue(name, out oldVal)) @@ -5562,6 +5565,9 @@ namespace OpenSim.Region.Framework.Scenes public void RemoveExtraSetting(string name) { + if (m_extraSettings == null) + return; + if (!m_extraSettings.ContainsKey(name)) return; -- cgit v1.1 From 14b659e550b4e24ecffa87fc28ee0196c36c73e3 Mon Sep 17 00:00:00 2001 From: Melanie Date: Tue, 2 Oct 2012 01:17:46 +0100 Subject: Send money() events to the clicked prim. Reverting a change I made over a year ago. --- OpenSim/Region/ScriptEngine/XEngine/EventManager.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/ScriptEngine/XEngine/EventManager.cs b/OpenSim/Region/ScriptEngine/XEngine/EventManager.cs index cee10df..74baaf9 100644 --- a/OpenSim/Region/ScriptEngine/XEngine/EventManager.cs +++ b/OpenSim/Region/ScriptEngine/XEngine/EventManager.cs @@ -98,7 +98,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine m_log.Debug("Paid: " + objectID + " from " + agentID + ", amount " + amount); - part = part.ParentGroup.RootPart; +// part = part.ParentGroup.RootPart; money(part.LocalId, agentID, amount); } -- cgit v1.1 From 54ec8b197b9119d0443bed0797563a88bdf49f6f Mon Sep 17 00:00:00 2001 From: Melanie Date: Tue, 2 Oct 2012 01:25:55 +0100 Subject: Add money event routing to the script engine. --- OpenSim/Region/ScriptEngine/XEngine/EventManager.cs | 3 +++ 1 file changed, 3 insertions(+) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/ScriptEngine/XEngine/EventManager.cs b/OpenSim/Region/ScriptEngine/XEngine/EventManager.cs index 74baaf9..9405075 100644 --- a/OpenSim/Region/ScriptEngine/XEngine/EventManager.cs +++ b/OpenSim/Region/ScriptEngine/XEngine/EventManager.cs @@ -96,6 +96,9 @@ namespace OpenSim.Region.ScriptEngine.XEngine if (part == null) return; + if ((part.ScriptEvents & scriptEvents.money) == 0) + part = part.ParentGroup.RootPart; + m_log.Debug("Paid: " + objectID + " from " + agentID + ", amount " + amount); // part = part.ParentGroup.RootPart; -- cgit v1.1 From 5221f2421e2a9b7dcc1a1e0e8cccaf1c9c94d2e2 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Mon, 1 Oct 2012 08:27:26 -0700 Subject: BulletSim: remove warnings for unused variables. --- OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs | 2 +- OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | 17 +++++------------ .../Region/Physics/BulletSPlugin/BSShapeCollection.cs | 2 +- 3 files changed, 7 insertions(+), 14 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs index 4f225ae..a7aaf9b 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs @@ -34,7 +34,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin { public class BSLinkset { - private static string LogHeader = "[BULLETSIM LINKSET]"; + // private static string LogHeader = "[BULLETSIM LINKSET]"; public BSPhysObject LinksetRoot { get; protected set; } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index a0e627e..e54bf75 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs @@ -46,19 +46,13 @@ public sealed class BSPrim : BSPhysObject private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private static readonly string LogHeader = "[BULLETS PRIM]"; - private IMesh _mesh; private PrimitiveBaseShape _pbs; - private ShapeData.PhysicsShapeType _shapeType; - private ulong _meshKey; - private ulong _hullKey; - private List _hulls; // _size is what the user passed. _scale is what we pass to the physics engine with the mesh. // Often _scale is unity because the meshmerizer will apply _size when creating the mesh. private OMV.Vector3 _size; // the multiplier for each mesh dimension as passed by the user private OMV.Vector3 _scale; // the multiplier for each mesh dimension for the mesh as created by the meshmerizer - private bool _stopped; private bool _grabbed; private bool _isSelected; private bool _isVolumeDetect; @@ -109,8 +103,6 @@ public sealed class BSPrim : BSPhysObject _buoyancy = 1f; _velocity = OMV.Vector3.Zero; _rotationalVelocity = OMV.Vector3.Zero; - _hullKey = 0; - _meshKey = 0; _pbs = pbs; _isPhysical = pisPhysical; _isVolumeDetect = false; @@ -160,8 +152,9 @@ public sealed class BSPrim : BSPhysObject }); } + // No one uses this property. public override bool Stopped { - get { return _stopped; } + get { return false; } } public override OMV.Vector3 Size { get { return _size; } @@ -1082,15 +1075,15 @@ public sealed class BSPrim : BSPhysObject public void FillShapeInfo(out ShapeData shape) { shape.ID = LocalID; - shape.Type = _shapeType; + shape.Type = ShapeData.PhysicsShapeType.SHAPE_UNKNOWN; shape.Position = _position; shape.Rotation = _orientation; shape.Velocity = _velocity; shape.Scale = _scale; shape.Mass = _isPhysical ? _mass : 0f; shape.Buoyancy = _buoyancy; - shape.HullKey = _hullKey; - shape.MeshKey = _meshKey; + shape.HullKey = 0; + shape.MeshKey = 0; shape.Friction = _friction; shape.Restitution = _restitution; shape.Collidable = (!IsPhantom) ? ShapeData.numericTrue : ShapeData.numericFalse; diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs index dee6243..a86bf8a 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs @@ -36,7 +36,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin { public class BSShapeCollection : IDisposable { - private static string LogHeader = "[BULLETSIM SHAPE COLLECTION]"; + // private static string LogHeader = "[BULLETSIM SHAPE COLLECTION]"; protected BSScene PhysicsScene { get; set; } -- cgit v1.1 From c1740a29036eed153138493f865435d22bd12406 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Mon, 1 Oct 2012 09:58:49 -0700 Subject: Correct my name in CONTRIBUTORS.txt --- OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs | 51 +++++++--------------- 1 file changed, 16 insertions(+), 35 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs index 65b38d6..cbfd7e3 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs @@ -138,74 +138,55 @@ namespace OpenSim.Region.Physics.BulletSPlugin switch (pParam) { case Vehicle.ANGULAR_DEFLECTION_EFFICIENCY: - if (pValue < 0.01f) pValue = 0.01f; - // m_angularDeflectionEfficiency = pValue; + // m_angularDeflectionEfficiency = Math.Max(pValue, 0.01f); break; case Vehicle.ANGULAR_DEFLECTION_TIMESCALE: - if (pValue < 0.01f) pValue = 0.01f; - // m_angularDeflectionTimescale = pValue; + // m_angularDeflectionTimescale = Math.Max(pValue, 0.01f); break; case Vehicle.ANGULAR_MOTOR_DECAY_TIMESCALE: - if (pValue < 0.01f) pValue = 0.01f; - m_angularMotorDecayTimescale = pValue; + m_angularMotorDecayTimescale = Math.Max(pValue, 0.01f); break; case Vehicle.ANGULAR_MOTOR_TIMESCALE: - if (pValue < 0.01f) pValue = 0.01f; - m_angularMotorTimescale = pValue; + m_angularMotorTimescale = Math.Max(pValue, 0.01f); break; case Vehicle.BANKING_EFFICIENCY: - if (pValue < 0.01f) pValue = 0.01f; - // m_bankingEfficiency = pValue; + // m_bankingEfficiency = Math.Max(pValue, 0.01f); break; case Vehicle.BANKING_MIX: - if (pValue < 0.01f) pValue = 0.01f; - // m_bankingMix = pValue; + // m_bankingMix = Math.Max(pValue, 0.01f); break; case Vehicle.BANKING_TIMESCALE: - if (pValue < 0.01f) pValue = 0.01f; - // m_bankingTimescale = pValue; + // m_bankingTimescale = Math.Max(pValue, 0.01f); break; case Vehicle.BUOYANCY: - if (pValue < -1f) pValue = -1f; - if (pValue > 1f) pValue = 1f; - m_VehicleBuoyancy = pValue; + m_VehicleBuoyancy = Math.Max(-1f, Math.Min(pValue, 1f)); break; // case Vehicle.HOVER_EFFICIENCY: -// if (pValue < 0f) pValue = 0f; -// if (pValue > 1f) pValue = 1f; -// m_VhoverEfficiency = pValue; +// m_VhoverEfficiency = Math.Max(0f, Math.Min(pValue, 1f)); // break; case Vehicle.HOVER_HEIGHT: m_VhoverHeight = pValue; break; case Vehicle.HOVER_TIMESCALE: - if (pValue < 0.01f) pValue = 0.01f; - m_VhoverTimescale = pValue; + m_VhoverTimescale = Math.Max(pValue, 0.01f); break; case Vehicle.LINEAR_DEFLECTION_EFFICIENCY: - if (pValue < 0.01f) pValue = 0.01f; - // m_linearDeflectionEfficiency = pValue; + // m_linearDeflectionEfficiency = Math.Max(pValue, 0.01f); break; case Vehicle.LINEAR_DEFLECTION_TIMESCALE: - if (pValue < 0.01f) pValue = 0.01f; - // m_linearDeflectionTimescale = pValue; + // m_linearDeflectionTimescale = Math.Max(pValue, 0.01f); break; case Vehicle.LINEAR_MOTOR_DECAY_TIMESCALE: - if (pValue < 0.01f) pValue = 0.01f; - m_linearMotorDecayTimescale = pValue; + m_linearMotorDecayTimescale = Math.Max(pValue, 0.01f); break; case Vehicle.LINEAR_MOTOR_TIMESCALE: - if (pValue < 0.01f) pValue = 0.01f; - m_linearMotorTimescale = pValue; + m_linearMotorTimescale = Math.Max(pValue, 0.01f); break; case Vehicle.VERTICAL_ATTRACTION_EFFICIENCY: - if (pValue < 0.1f) pValue = 0.1f; // Less goes unstable - if (pValue > 1.0f) pValue = 1.0f; - m_verticalAttractionEfficiency = pValue; + m_verticalAttractionEfficiency = Math.Max(0.1f, Math.Min(pValue, 1f)); break; case Vehicle.VERTICAL_ATTRACTION_TIMESCALE: - if (pValue < 0.01f) pValue = 0.01f; - m_verticalAttractionTimescale = pValue; + m_verticalAttractionTimescale = Math.Max(pValue, 0.01f); break; // These are vector properties but the engine lets you use a single float value to -- cgit v1.1 From 33617e09a185be68ceeaaba0fe9b7b2e6068124d Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Mon, 1 Oct 2012 11:54:35 -0700 Subject: BulletSim: impliment FloatOnWater OS function. --- .../Region/Physics/BulletSPlugin/BSCharacter.cs | 41 +++++++++--- OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | 77 ++++++++++++++++++++-- .../Region/Physics/BulletSPlugin/BulletSimAPI.cs | 8 +-- 3 files changed, 104 insertions(+), 22 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs index b88ec3c..5cf8953 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs @@ -234,6 +234,15 @@ public class BSCharacter : BSPhysObject _position.Z = terrainHeight + 2.0f; ret = true; } + if ((CurrentCollisionFlags & CollisionFlags.BS_FLOATS_ON_WATER) == 0) + { + float waterHeight = PhysicsScene.GetWaterLevelAtXYZ(_position); + if (Position.Z < waterHeight) + { + _position.Z = waterHeight; + ret = true; + } + } // TODO: check for out of bounds return ret; @@ -242,18 +251,22 @@ public class BSCharacter : BSPhysObject // A version of the sanity check that also makes sure a new position value is // pushed back to the physics engine. This routine would be used by anyone // who is not already pushing the value. - private bool PositionSanityCheck2() + private bool PositionSanityCheck2(bool atTaintTime) { bool ret = false; if (PositionSanityCheck()) { // The new position value must be pushed into the physics engine but we can't // just assign to "Position" because of potential call loops. - PhysicsScene.TaintedObject("BSCharacter.PositionSanityCheck", delegate() + BSScene.TaintCallback sanityOperation = delegate() { DetailLog("{0},BSCharacter.PositionSanityCheck,taint,pos={1},orient={2}", LocalID, _position, _orientation); BulletSimAPI.SetObjectTranslation(PhysicsScene.WorldID, LocalID, _position, _orientation); - }); + }; + if (atTaintTime) + sanityOperation(); + else + PhysicsScene.TaintedObject("BSCharacter.PositionSanityCheck", sanityOperation); ret = true; } return ret; @@ -378,7 +391,16 @@ public class BSCharacter : BSPhysObject set { _collidingObj = value; } } public override bool FloatOnWater { - set { _floatOnWater = value; } + set { + _floatOnWater = value; + PhysicsScene.TaintedObject("BSCharacter.setFloatOnWater", delegate() + { + if (_floatOnWater) + CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(BSBody.ptr, CollisionFlags.BS_FLOATS_ON_WATER); + else + CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(BSBody.ptr, CollisionFlags.BS_FLOATS_ON_WATER); + }); + } } public override OMV.Vector3 RotationalVelocity { get { return _rotationalVelocity; } @@ -493,15 +515,14 @@ public class BSCharacter : BSPhysObject _velocity = entprop.Velocity; _acceleration = entprop.Acceleration; _rotationalVelocity = entprop.RotationalVelocity; + // Do some sanity checking for the avatar. Make sure it's above ground and inbounds. + PositionSanityCheck2(true); + // Avatars don't report their changes the usual way. Changes are checked for in the heartbeat loop. // base.RequestPhysicsterseUpdate(); - // Do some sanity checking for the avatar. Make sure it's above ground and inbounds. - PositionSanityCheck2(); - - float heightHere = PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(_position); // only for debug - DetailLog("{0},BSCharacter.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5},terrain={6}", - LocalID, _position, _orientation, _velocity, _acceleration, _rotationalVelocity, heightHere); + DetailLog("{0},BSCharacter.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5}", + LocalID, _position, _orientation, _velocity, _acceleration, _rotationalVelocity); } } } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index e54bf75..e37a4a0 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs @@ -267,6 +267,7 @@ public sealed class BSPrim : BSPhysObject set { _position = value; // TODO: what does it mean to set the position of a child prim?? Rebuild the constraint? + PositionSanityCheck(); PhysicsScene.TaintedObject("BSPrim.setPosition", delegate() { // DetailLog("{0},BSPrim.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation); @@ -275,6 +276,63 @@ public sealed class BSPrim : BSPhysObject } } + // Check that the current position is sane and, if not, modify the position to make it so. + // Check for being below terrain and being out of bounds. + // Returns 'true' of the position was made sane by some action. + private bool PositionSanityCheck() + { + bool ret = false; + + // If totally below the ground, move the prim up + // TODO: figure out the right solution for this... only for dynamic objects? + /* + float terrainHeight = PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(_position); + if (Position.Z < terrainHeight) + { + DetailLog("{0},BSPrim.PositionAdjustUnderGround,call,pos={1},terrain={2}", LocalID, _position, terrainHeight); + _position.Z = terrainHeight + 2.0f; + ret = true; + } + */ + if ((CurrentCollisionFlags & CollisionFlags.BS_FLOATS_ON_WATER) != 0) + { + float waterHeight = PhysicsScene.GetWaterLevelAtXYZ(_position); + if (Position.Z < waterHeight) + { + _position.Z = waterHeight; + ret = true; + } + } + + // TODO: check for out of bounds + return ret; + } + + // A version of the sanity check that also makes sure a new position value is + // pushed back to the physics engine. This routine would be used by anyone + // who is not already pushing the value. + private bool PositionSanityCheck2(bool atTaintTime) + { + bool ret = false; + if (PositionSanityCheck()) + { + // The new position value must be pushed into the physics engine but we can't + // just assign to "Position" because of potential call loops. + BSScene.TaintCallback sanityOperation = delegate() + { + DetailLog("{0},BSPrim.PositionSanityCheck,taint,pos={1},orient={2}", LocalID, _position, _orientation); + BulletSimAPI.SetObjectTranslation(PhysicsScene.WorldID, LocalID, _position, _orientation); + }; + if (atTaintTime) + sanityOperation(); + else + PhysicsScene.TaintedObject("BSPrim.PositionSanityCheck", sanityOperation); + + ret = true; + } + return ret; + } + // Return the effective mass of the object. // If there are multiple items in the linkset, add them together for the root public override float Mass @@ -481,11 +539,10 @@ public sealed class BSPrim : BSPhysObject // This is a NOOP if the object is not in the world (BulletSim and Bullet ignore objects not found). BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, BSBody.ptr); - // Set up the object physicalness (does gravity and collisions move this object) MakeDynamic(IsStatic); - // Do any vehicle stuff + // Update vehicle specific parameters _vehicle.Refresh(); // Arrange for collision events if the simulator wants them @@ -556,7 +613,6 @@ public sealed class BSPrim : BSPhysObject // A dynamic object has mass IntPtr collisionShapePtr = BulletSimAPI.GetCollisionShape2(BSBody.ptr); OMV.Vector3 inertia = BulletSimAPI.CalculateLocalInertia2(collisionShapePtr, Mass); - // OMV.Vector3 inertia = OMV.Vector3.Zero; BulletSimAPI.SetMassProps2(BSBody.ptr, _mass, inertia); BulletSimAPI.UpdateInertiaTensor2(BSBody.ptr); @@ -566,7 +622,7 @@ public sealed class BSPrim : BSPhysObject BulletSimAPI.SetSleepingThresholds2(BSBody.ptr, PhysicsScene.Params.linearSleepingThreshold, PhysicsScene.Params.angularSleepingThreshold); BulletSimAPI.SetContactProcessingThreshold2(BSBody.ptr, PhysicsScene.Params.contactProcessingThreshold); - // There can be special things needed for implementing linksets. + // There might be special things needed for implementing linksets. Linkset.MakeDynamic(this); // Force activation of the object so Bullet will act on it. @@ -656,7 +712,16 @@ public sealed class BSPrim : BSPhysObject } } public override bool FloatOnWater { - set { _floatOnWater = value; } + set { + _floatOnWater = value; + PhysicsScene.TaintedObject("BSPrim.setFloatOnWater", delegate() + { + if (_floatOnWater) + CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(BSBody.ptr, CollisionFlags.BS_FLOATS_ON_WATER); + else + CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(BSBody.ptr, CollisionFlags.BS_FLOATS_ON_WATER); + }); + } } public override OMV.Vector3 RotationalVelocity { get { @@ -1198,6 +1263,8 @@ public sealed class BSPrim : BSPhysObject _acceleration = entprop.Acceleration; _rotationalVelocity = entprop.RotationalVelocity; + PositionSanityCheck2(true); + DetailLog("{0},BSPrim.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5}", LocalID, _position, _orientation, _velocity, _acceleration, _rotationalVelocity); diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs index 1125d7e..d49e5f3 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs @@ -344,10 +344,7 @@ public enum CollisionFlags : uint CF_DISABLE_SPU_COLLISION_PROCESS = 1 << 6, // Following used by BulletSim to control collisions BS_SUBSCRIBE_COLLISION_EVENTS = 1 << 10, - // BS_VOLUME_DETECT_OBJECT = 1 << 11, - // BS_PHANTOM_OBJECT = 1 << 12, - // BS_PHYSICAL_OBJECT = 1 << 13, - // BS_TERRAIN_OBJECT = 1 << 14, + BS_FLOATS_ON_WATER = 1 << 11, BS_NONE = 0, BS_ALL = 0xFFFFFFFF, @@ -356,9 +353,6 @@ public enum CollisionFlags : uint BS_ACTIVE = CF_STATIC_OBJECT | CF_KINEMATIC_OBJECT | CF_NO_CONTACT_RESPONSE - // | BS_VOLUME_DETECT_OBJECT - // | BS_PHANTOM_OBJECT - // | BS_PHYSICAL_OBJECT, }; // Values for collisions groups and masks -- cgit v1.1 From f2c78281ce46ff1be96f0bf86f2b7ddefd94a900 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Mon, 1 Oct 2012 12:10:06 -0700 Subject: BulletSim: fix the FloatOnWater code so avatars can normally go underwater. --- OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs index 5cf8953..2fe4d68 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs @@ -234,7 +234,7 @@ public class BSCharacter : BSPhysObject _position.Z = terrainHeight + 2.0f; ret = true; } - if ((CurrentCollisionFlags & CollisionFlags.BS_FLOATS_ON_WATER) == 0) + if ((CurrentCollisionFlags & CollisionFlags.BS_FLOATS_ON_WATER) != 0) { float waterHeight = PhysicsScene.GetWaterLevelAtXYZ(_position); if (Position.Z < waterHeight) -- cgit v1.1 From 1e5869dcf63c50897e94784a5a4aec3a12c843cc Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Tue, 2 Oct 2012 10:48:16 -0700 Subject: Add Flush() method to LogWriter. Also correct line endings to Linux form. --- .../Framework/Statistics/Logging/LogWriter.cs | 331 +++++++++++---------- 1 file changed, 170 insertions(+), 161 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/Framework/Statistics/Logging/LogWriter.cs b/OpenSim/Region/CoreModules/Framework/Statistics/Logging/LogWriter.cs index 65e4c90..fd8d5e3 100755 --- a/OpenSim/Region/CoreModules/Framework/Statistics/Logging/LogWriter.cs +++ b/OpenSim/Region/CoreModules/Framework/Statistics/Logging/LogWriter.cs @@ -1,161 +1,170 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.IO; -using System.Text; -using log4net; - -namespace OpenSim.Region.CoreModules.Framework.Statistics.Logging -{ - /// - /// Class for writing a high performance, high volume log file. - /// Sometimes, to debug, one has a high volume logging to do and the regular - /// log file output is not appropriate. - /// Create a new instance with the parameters needed and - /// call Write() to output a line. Call Close() when finished. - /// If created with no parameters, it will not log anything. - /// - public class LogWriter : IDisposable - { - public bool Enabled { get; private set; } - - private string m_logDirectory = "."; - private int m_logMaxFileTimeMin = 5; // 5 minutes - public String LogFileHeader { get; set; } - - private StreamWriter m_logFile = null; - private TimeSpan m_logFileLife; - private DateTime m_logFileEndTime; - private Object m_logFileWriteLock = new Object(); - - // set externally when debugging. If let 'null', this does not write any error messages. - public ILog ErrorLogger = null; - private string LogHeader = "[LOG WRITER]"; - - /// - /// Create a log writer that will not write anything. Good for when not enabled - /// but the write statements are still in the code. - /// - public LogWriter() - { - Enabled = false; - m_logFile = null; - } - - /// - /// Create a log writer instance. - /// - /// The directory to create the log file in. May be 'null' for default. - /// The characters that begin the log file name. May be 'null' for default. - /// Maximum age of a log file in minutes. If zero, will set default. - public LogWriter(string dir, string headr, int maxFileTime) - { - m_logDirectory = dir == null ? "." : dir; - - LogFileHeader = headr == null ? "log-" : headr; - - m_logMaxFileTimeMin = maxFileTime; - if (m_logMaxFileTimeMin < 1) - m_logMaxFileTimeMin = 5; - - m_logFileLife = new TimeSpan(0, m_logMaxFileTimeMin, 0); - m_logFileEndTime = DateTime.Now + m_logFileLife; - - Enabled = true; - } - - public void Dispose() - { - this.Close(); - } - - public void Close() - { - Enabled = false; - if (m_logFile != null) - { - m_logFile.Close(); - m_logFile.Dispose(); - m_logFile = null; - } - } - - public void Write(string line, params object[] args) - { - if (!Enabled) return; - Write(String.Format(line, args)); - } - - public void Write(string line) - { - if (!Enabled) return; - try - { - lock (m_logFileWriteLock) - { - DateTime now = DateTime.Now; - if (m_logFile == null || now > m_logFileEndTime) - { - if (m_logFile != null) - { - m_logFile.Close(); - m_logFile.Dispose(); - m_logFile = null; - } - - // First log file or time has expired, start writing to a new log file - m_logFileEndTime = now + m_logFileLife; - string path = (m_logDirectory.Length > 0 ? m_logDirectory - + System.IO.Path.DirectorySeparatorChar.ToString() : "") - + String.Format("{0}{1}.log", LogFileHeader, now.ToString("yyyyMMddHHmmss")); - m_logFile = new StreamWriter(File.Open(path, FileMode.Append, FileAccess.Write)); - } - if (m_logFile != null) - { - StringBuilder buff = new StringBuilder(line.Length + 25); - buff.Append(now.ToString("yyyyMMddHHmmssfff")); - // buff.Append(now.ToString("yyyyMMddHHmmss")); - buff.Append(","); - buff.Append(line); - buff.Append("\r\n"); - m_logFile.Write(buff.ToString()); - } - } - } - catch (Exception e) - { - if (ErrorLogger != null) - { - ErrorLogger.ErrorFormat("{0}: FAILURE WRITING TO LOGFILE: {1}", LogHeader, e); - } - Enabled = false; - } - return; - } - } -} \ No newline at end of file +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.IO; +using System.Text; +using log4net; + +namespace OpenSim.Region.CoreModules.Framework.Statistics.Logging +{ + /// + /// Class for writing a high performance, high volume log file. + /// Sometimes, to debug, one has a high volume logging to do and the regular + /// log file output is not appropriate. + /// Create a new instance with the parameters needed and + /// call Write() to output a line. Call Close() when finished. + /// If created with no parameters, it will not log anything. + /// + public class LogWriter : IDisposable + { + public bool Enabled { get; private set; } + + private string m_logDirectory = "."; + private int m_logMaxFileTimeMin = 5; // 5 minutes + public String LogFileHeader { get; set; } + + private StreamWriter m_logFile = null; + private TimeSpan m_logFileLife; + private DateTime m_logFileEndTime; + private Object m_logFileWriteLock = new Object(); + + // set externally when debugging. If let 'null', this does not write any error messages. + public ILog ErrorLogger = null; + private string LogHeader = "[LOG WRITER]"; + + /// + /// Create a log writer that will not write anything. Good for when not enabled + /// but the write statements are still in the code. + /// + public LogWriter() + { + Enabled = false; + m_logFile = null; + } + + /// + /// Create a log writer instance. + /// + /// The directory to create the log file in. May be 'null' for default. + /// The characters that begin the log file name. May be 'null' for default. + /// Maximum age of a log file in minutes. If zero, will set default. + public LogWriter(string dir, string headr, int maxFileTime) + { + m_logDirectory = dir == null ? "." : dir; + + LogFileHeader = headr == null ? "log-" : headr; + + m_logMaxFileTimeMin = maxFileTime; + if (m_logMaxFileTimeMin < 1) + m_logMaxFileTimeMin = 5; + + m_logFileLife = new TimeSpan(0, m_logMaxFileTimeMin, 0); + m_logFileEndTime = DateTime.Now + m_logFileLife; + + Enabled = true; + } + + public void Dispose() + { + this.Close(); + } + + public void Close() + { + Enabled = false; + if (m_logFile != null) + { + m_logFile.Close(); + m_logFile.Dispose(); + m_logFile = null; + } + } + + public void Write(string line, params object[] args) + { + if (!Enabled) return; + Write(String.Format(line, args)); + } + + public void Flush() + { + if (!Enabled) return; + if (m_logFile != null) + { + m_logFile.Flush(); + } + } + + public void Write(string line) + { + if (!Enabled) return; + try + { + lock (m_logFileWriteLock) + { + DateTime now = DateTime.Now; + if (m_logFile == null || now > m_logFileEndTime) + { + if (m_logFile != null) + { + m_logFile.Close(); + m_logFile.Dispose(); + m_logFile = null; + } + + // First log file or time has expired, start writing to a new log file + m_logFileEndTime = now + m_logFileLife; + string path = (m_logDirectory.Length > 0 ? m_logDirectory + + System.IO.Path.DirectorySeparatorChar.ToString() : "") + + String.Format("{0}{1}.log", LogFileHeader, now.ToString("yyyyMMddHHmmss")); + m_logFile = new StreamWriter(File.Open(path, FileMode.Append, FileAccess.Write)); + } + if (m_logFile != null) + { + StringBuilder buff = new StringBuilder(line.Length + 25); + buff.Append(now.ToString("yyyyMMddHHmmssfff")); + // buff.Append(now.ToString("yyyyMMddHHmmss")); + buff.Append(","); + buff.Append(line); + buff.Append("\r\n"); + m_logFile.Write(buff.ToString()); + } + } + } + catch (Exception e) + { + if (ErrorLogger != null) + { + ErrorLogger.ErrorFormat("{0}: FAILURE WRITING TO LOGFILE: {1}", LogHeader, e); + } + Enabled = false; + } + return; + } + } +} -- cgit v1.1 From b6b505163c98683adaf7f298026c5bd2f954c05c Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Tue, 2 Oct 2012 10:50:29 -0700 Subject: BulletSim: call ForcePosition and ForceOrientation in BSDynamics so there is no lag between what the vehicle code sees and what the physics engine is using. --- OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs | 96 +++++++++++++--------- 1 file changed, 57 insertions(+), 39 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs index cbfd7e3..4ba2f62 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs @@ -92,7 +92,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin private float m_angularMotorDecayTimescale = 0; // motor angular velocity decay rate private Vector3 m_angularFrictionTimescale = Vector3.Zero; // body angular velocity decay rate private Vector3 m_lastAngularVelocity = Vector3.Zero; // what was last applied to body - // private Vector3 m_lastVertAttractor = Vector3.Zero; // what VA was last applied to body + private Vector3 m_lastVertAttractor = Vector3.Zero; // what VA was last applied to body //Deflection properties // private float m_angularDeflectionEfficiency = 0; @@ -352,8 +352,9 @@ namespace OpenSim.Region.Physics.BulletSPlugin // m_bankingMix = 1; // m_bankingTimescale = 1; // m_referenceFrame = Quaternion.Identity; - m_flags |= (VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.LIMIT_ROLL_ONLY | - VehicleFlag.LIMIT_MOTOR_UP); + m_flags |= (VehicleFlag.NO_DEFLECTION_UP + | VehicleFlag.LIMIT_ROLL_ONLY + | VehicleFlag.LIMIT_MOTOR_UP); m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT); m_flags |= (VehicleFlag.HOVER_UP_ONLY); break; @@ -380,12 +381,13 @@ namespace OpenSim.Region.Physics.BulletSPlugin // m_bankingMix = 0.8f; // m_bankingTimescale = 1; // m_referenceFrame = Quaternion.Identity; - m_flags &= ~(VehicleFlag.HOVER_TERRAIN_ONLY | - VehicleFlag.HOVER_GLOBAL_HEIGHT | VehicleFlag.HOVER_UP_ONLY); - m_flags &= ~(VehicleFlag.LIMIT_ROLL_ONLY); - m_flags |= (VehicleFlag.NO_DEFLECTION_UP | - VehicleFlag.LIMIT_MOTOR_UP); - m_flags |= (VehicleFlag.HOVER_WATER_ONLY); + m_flags &= ~(VehicleFlag.HOVER_TERRAIN_ONLY + | VehicleFlag.HOVER_GLOBAL_HEIGHT + | VehicleFlag.LIMIT_ROLL_ONLY + | VehicleFlag.HOVER_UP_ONLY); + m_flags |= (VehicleFlag.NO_DEFLECTION_UP + | VehicleFlag.LIMIT_MOTOR_UP + | VehicleFlag.HOVER_WATER_ONLY); break; case Vehicle.TYPE_AIRPLANE: m_linearFrictionTimescale = new Vector3(200, 10, 5); @@ -410,9 +412,12 @@ namespace OpenSim.Region.Physics.BulletSPlugin // m_bankingMix = 0.7f; // m_bankingTimescale = 2; // m_referenceFrame = Quaternion.Identity; - m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | - VehicleFlag.HOVER_GLOBAL_HEIGHT | VehicleFlag.HOVER_UP_ONLY); - m_flags &= ~(VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.LIMIT_MOTOR_UP); + m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY + | VehicleFlag.HOVER_TERRAIN_ONLY + | VehicleFlag.HOVER_GLOBAL_HEIGHT + | VehicleFlag.HOVER_UP_ONLY + | VehicleFlag.NO_DEFLECTION_UP + | VehicleFlag.LIMIT_MOTOR_UP); m_flags |= (VehicleFlag.LIMIT_ROLL_ONLY); break; case Vehicle.TYPE_BALLOON: @@ -438,11 +443,13 @@ namespace OpenSim.Region.Physics.BulletSPlugin // m_bankingMix = 0.7f; // m_bankingTimescale = 5; // m_referenceFrame = Quaternion.Identity; - m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | - VehicleFlag.HOVER_UP_ONLY); - m_flags &= ~(VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.LIMIT_MOTOR_UP); - m_flags |= (VehicleFlag.LIMIT_ROLL_ONLY); - m_flags |= (VehicleFlag.HOVER_GLOBAL_HEIGHT); + m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY + | VehicleFlag.HOVER_TERRAIN_ONLY + | VehicleFlag.HOVER_UP_ONLY + | VehicleFlag.NO_DEFLECTION_UP + | VehicleFlag.LIMIT_MOTOR_UP); + m_flags |= (VehicleFlag.LIMIT_ROLL_ONLY + | VehicleFlag.HOVER_GLOBAL_HEIGHT); break; } }//end SetDefaultsForType @@ -451,7 +458,8 @@ namespace OpenSim.Region.Physics.BulletSPlugin // Do any updating needed for a vehicle public void Refresh() { - if (Type == Vehicle.TYPE_NONE) return; + if (!IsActive) + return; // Set the prim's inertia to zero. The vehicle code handles that and this // removes the torque action introduced by Bullet. @@ -470,7 +478,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin LimitRotation(pTimestep); // remember the position so next step we can limit absolute movement effects - m_lastPositionVector = Prim.Position; + m_lastPositionVector = Prim.ForcePosition; VDetailLog("{0},BSDynamics.Step,done,pos={1},force={2},velocity={3},angvel={4}", Prim.LocalID, Prim.Position, Prim.Force, Prim.Velocity, Prim.RotationalVelocity); @@ -524,7 +532,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin } // convert requested object velocity to object relative vector - Quaternion rotq = Prim.Orientation; + Quaternion rotq = Prim.ForceOrientation; m_newVelocity = m_lastLinearVelocityVector * rotq; // Add the various forces into m_dir which will be our new direction vector (velocity) @@ -541,19 +549,19 @@ namespace OpenSim.Region.Physics.BulletSPlugin m_dir.Z = vel_now.Z; // Preserve the accumulated falling velocity */ - Vector3 pos = Prim.Position; + Vector3 pos = Prim.ForcePosition; // Vector3 accel = new Vector3(-(m_dir.X - m_lastLinearVelocityVector.X / 0.1f), -(m_dir.Y - m_lastLinearVelocityVector.Y / 0.1f), m_dir.Z - m_lastLinearVelocityVector.Z / 0.1f); // If below the terrain, move us above the ground a little. float terrainHeight = Prim.PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(pos); // Taking the rotated size doesn't work here because m_prim.Size is the size of the root prim and not the linkset. // Need to add a m_prim.LinkSet.Size similar to m_prim.LinkSet.Mass. - // Vector3 rotatedSize = m_prim.Size * m_prim.Orientation; + // Vector3 rotatedSize = m_prim.Size * m_prim.ForceOrientation; // if (rotatedSize.Z < terrainHeight) if (pos.Z < terrainHeight) { pos.Z = terrainHeight + 2; - Prim.Position = pos; + Prim.ForcePosition = pos; VDetailLog("{0},MoveLinear,terrainHeight,terrainHeight={1},pos={2}", Prim.LocalID, terrainHeight, pos); } @@ -583,7 +591,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin { if ((pos.Z - m_VhoverTargetHeight) > .2 || (pos.Z - m_VhoverTargetHeight) < -.2) { - Prim.Position = pos; + Prim.ForcePosition = pos; } } else @@ -635,12 +643,13 @@ namespace OpenSim.Region.Physics.BulletSPlugin } if (changed) { - Prim.Position = pos; + Prim.ForcePosition = pos; VDetailLog("{0},MoveLinear,blockingEndPoint,block={1},origPos={2},pos={3}", Prim.LocalID, m_BlockingEndPoint, posChange, pos); } } + // Limit absolute vertical change float Zchange = Math.Abs(posChange.Z); if ((m_flags & (VehicleFlag.LIMIT_MOTOR_UP)) != 0) { @@ -659,6 +668,8 @@ namespace OpenSim.Region.Physics.BulletSPlugin grav.Z = (float)(grav.Z * 1.037125); VDetailLog("{0},MoveLinear,limitMotorUp,grav={1}", Prim.LocalID, grav); } + + // If not changing some axis, reduce out velocity if ((m_flags & (VehicleFlag.NO_X)) != 0) m_newVelocity.X = 0; if ((m_flags & (VehicleFlag.NO_Y)) != 0) @@ -701,19 +712,19 @@ namespace OpenSim.Region.Physics.BulletSPlugin // a newly set velocity, this routine steps the value from the previous // value (m_angularMotorVelocity) to the requested value (m_angularMotorDirection). // There are m_angularMotorApply steps. - Vector3 origAngularVelocity = m_angularMotorVelocity; + Vector3 origVel = m_angularMotorVelocity; + Vector3 origDir = m_angularMotorDirection; + // ramp up to new value - // current velocity += error / ( time to get there / step interval) + // new velocity += error / ( time to get there / step interval) // requested speed - last motor speed m_angularMotorVelocity.X += (m_angularMotorDirection.X - m_angularMotorVelocity.X) / (m_angularMotorTimescale / pTimestep); m_angularMotorVelocity.Y += (m_angularMotorDirection.Y - m_angularMotorVelocity.Y) / (m_angularMotorTimescale / pTimestep); m_angularMotorVelocity.Z += (m_angularMotorDirection.Z - m_angularMotorVelocity.Z) / (m_angularMotorTimescale / pTimestep); - VDetailLog("{0},MoveAngular,angularMotorApply,apply={1},angTScale={2},timeStep={3},origvel={4},dir={5},vel={6}", - Prim.LocalID, m_angularMotorApply, m_angularMotorTimescale, pTimestep, origAngularVelocity, m_angularMotorDirection, m_angularMotorVelocity); + VDetailLog("{0},MoveAngular,angularMotorApply,apply={1},angTScale={2},timeStep={3},origvel={4},origDir={5},vel={6}", + Prim.LocalID, m_angularMotorApply, m_angularMotorTimescale, pTimestep, origVel, origDir, m_angularMotorVelocity); - // This is done so that if script request rate is less than phys frame rate the expected - // velocity may still be acheived. m_angularMotorApply--; } else @@ -727,25 +738,32 @@ namespace OpenSim.Region.Physics.BulletSPlugin // Vertical attractor section Vector3 vertattr = Vector3.Zero; - if (m_verticalAttractionTimescale < 300) + Vector3 deflection = Vector3.Zero; + Vector3 banking = Vector3.Zero; + + if (m_verticalAttractionTimescale < 300 && m_lastAngularVelocity != Vector3.Zero) { float VAservo = 0.2f / (m_verticalAttractionTimescale / pTimestep); + VAservo *= (m_verticalAttractionEfficiency * m_verticalAttractionEfficiency); + // get present body rotation - Quaternion rotq = Prim.Orientation; - // make a vector pointing up + Quaternion rotq = Prim.ForceOrientation; + // vector pointing up Vector3 verterr = Vector3.Zero; verterr.Z = 1.0f; + // rotate it to Body Angle verterr = verterr * rotq; - // verterr.X and .Y are the World error ammounts. They are 0 when there is no error (Vehicle Body is 'vertical'), and .Z will be 1. + // verterr.X and .Y are the World error amounts. They are 0 when there is no error (Vehicle Body is 'vertical'), and .Z will be 1. // As the body leans to its side |.X| will increase to 1 and .Z fall to 0. As body inverts |.X| will fall and .Z will go // negative. Similar for tilt and |.Y|. .X and .Y must be modulated to prevent a stable inverted body. + + // Error is 0 (no error) to +/- 2 (max error) if (verterr.Z < 0.0f) { verterr.X = 2.0f - verterr.X; verterr.Y = 2.0f - verterr.Y; } - // Error is 0 (no error) to +/- 2 (max error) // scale it by VAservo verterr = verterr * VAservo; @@ -765,7 +783,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin } // else vertical attractor is off - // m_lastVertAttractor = vertattr; + m_lastVertAttractor = vertattr; // Bank section tba @@ -799,7 +817,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin internal void LimitRotation(float timestep) { - Quaternion rotq = Prim.Orientation; + Quaternion rotq = Prim.ForceOrientation; Quaternion m_rot = rotq; bool changed = false; if (m_RollreferenceFrame != Quaternion.Identity) @@ -834,7 +852,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin } if (changed) { - Prim.Orientation = m_rot; + Prim.ForceOrientation = m_rot; VDetailLog("{0},LimitRotation,done,orig={1},new={2}", Prim.LocalID, rotq, m_rot); } -- cgit v1.1 From ce97ebdc88ea525fe6e0c823b6f0072b6acddbc9 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Tue, 2 Oct 2012 10:52:51 -0700 Subject: BulletSim: Fix linkset problem where delayed manipulations of child objects was using the child shape address at call time rather than the one created at taint time. --- OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs index a7aaf9b..3e82642 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs @@ -331,21 +331,21 @@ public class BSLinkset m_children.Add(child); BSPhysObject rootx = LinksetRoot; // capture the root and body as of now - BulletBody rootBodyx = LinksetRoot.BSBody; BSPhysObject childx = child; - BulletBody childBodyx = child.BSBody; DetailLog("{0},AddChildToLinkset,call,rID={1},rBody={2},cID={3},cBody={4}", rootx.LocalID, - rootx.LocalID, rootBodyx.ptr.ToString("X"), - childx.LocalID, childBodyx.ptr.ToString("X")); + rootx.LocalID, rootx.BSBody.ptr.ToString("X"), + childx.LocalID, childx.BSBody.ptr.ToString("X")); PhysicsScene.TaintedObject("AddChildToLinkset", delegate() { DetailLog("{0},AddChildToLinkset,taint,child={1}", LinksetRoot.LocalID, child.LocalID); // build the physical binding between me and the child m_taintChildren.Add(childx); - PhysicallyLinkAChildToRoot(rootx, rootBodyx, childx, childBodyx); + + // Since this is taint-time, the body and shape could have changed for the child + PhysicallyLinkAChildToRoot(rootx, rootx.BSBody, childx, childx.BSBody); }); } return; @@ -369,21 +369,19 @@ public class BSLinkset if (m_children.Remove(child)) { BSPhysObject rootx = LinksetRoot; // capture the root and body as of now - BulletBody rootBodyx = LinksetRoot.BSBody; BSPhysObject childx = child; - BulletBody childBodyx = child.BSBody; DetailLog("{0},RemoveChildFromLinkset,call,rID={1},rBody={2},cID={3},cBody={4}", childx.LocalID, - rootx.LocalID, rootBodyx.ptr.ToString("X"), - childx.LocalID, childBodyx.ptr.ToString("X")); + rootx.LocalID, rootx.BSBody.ptr.ToString("X"), + childx.LocalID, childx.BSBody.ptr.ToString("X")); PhysicsScene.TaintedObject("RemoveChildFromLinkset", delegate() { if (m_taintChildren.Contains(childx)) m_taintChildren.Remove(childx); - PhysicallyUnlinkAChildFromRoot(rootx, rootBodyx, childx, childBodyx); + PhysicallyUnlinkAChildFromRoot(rootx, rootx.BSBody, childx, childx.BSBody); RecomputeLinksetConstraintVariables(); }); -- cgit v1.1 From d8a786870b5ff03241e9f6b0393a2e1f91de2b01 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Tue, 2 Oct 2012 10:56:39 -0700 Subject: BulletSim: Fix problem where box shapes were not being rebuilt if the shape type changed. --- OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs index a86bf8a..399a133 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs @@ -108,7 +108,8 @@ public class BSShapeCollection : IDisposable // If we had to select a new shape geometry for the object, // rebuild the body around it. // Updates prim.BSBody with information/pointers to requested body - bool newBody = CreateBody((newGeom || forceRebuild), prim, PhysicsScene.World, prim.BSShape, shapeData, bodyCallback); + bool newBody = CreateBody((newGeom || forceRebuild), prim, PhysicsScene.World, + prim.BSShape, shapeData, bodyCallback); ret = newGeom || newBody; } DetailLog("{0},BSShapeCollection.GetBodyAndShape,force={1},ret={2},body={3},shape={4}", @@ -140,7 +141,7 @@ public class BSShapeCollection : IDisposable bodyDesc.lastReferenced = System.DateTime.Now; Bodies[body.ID] = bodyDesc; } -} + } // Release the usage of a body. // Called when releasing use of a BSBody. BSShape is handled separately. @@ -167,7 +168,7 @@ public class BSShapeCollection : IDisposable { DetailLog("{0},BSShapeCollection.DereferenceBody,DestroyingBody. ptr={1}", body.ID, body.ptr.ToString("X")); - // If the caller needs to know, pass the event up. + // If the caller needs to know the old body is going away, pass the event up. if (bodyCallback != null) bodyCallback(body); // Zero any reference to the shape so it is not freed when the body is deleted. @@ -448,7 +449,8 @@ public class BSShapeCollection : IDisposable ulong newMeshKey = ComputeShapeKey(shapeData, pbs, out lod); // if this new shape is the same as last time, don't recreate the mesh - if (prim.BSShape.shapeKey == newMeshKey) return false; + if (newMeshKey == prim.BSShape.shapeKey && prim.BSShape.type == ShapeData.PhysicsShapeType.SHAPE_MESH) + return false; DetailLog("{0},BSShapeCollection.CreateGeomMesh,create,oldKey={1},newKey={2}", prim.LocalID, prim.BSShape.shapeKey.ToString("X"), newMeshKey.ToString("X")); -- cgit v1.1 From ce47d0c4541159a730b2d83a7b2ccffc908d06f1 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Tue, 2 Oct 2012 11:06:07 -0700 Subject: BulletSim: Add ForcePosition and ForceOrientation to BSPhysObject and to its children of BSPrim and BSCharacter. --- .../Region/Physics/BulletSPlugin/BSCharacter.cs | 26 +++++++++++++++ .../Region/Physics/BulletSPlugin/BSPhysObject.cs | 4 +++ OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | 39 +++++++++++++++++++--- 3 files changed, 64 insertions(+), 5 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs index 2fe4d68..2a52e01 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs @@ -218,6 +218,18 @@ public class BSCharacter : BSPhysObject }); } } + public override OMV.Vector3 ForcePosition { + get { + _position = BulletSimAPI.GetPosition2(BSBody.ptr); + return _position; + } + set { + _position = value; + PositionSanityCheck(); + BulletSimAPI.SetTranslation2(BSBody.ptr, _position, _orientation); + } + } + // Check that the current position is sane and, if not, modify the position to make it so. // Check for being below terrain and being out of bounds. @@ -346,6 +358,20 @@ public class BSCharacter : BSPhysObject }); } } + // Go directly to Bullet to get/set the value. + public override OMV.Quaternion ForceOrientation + { + get + { + _orientation = BulletSimAPI.GetOrientation2(BSBody.ptr); + return _orientation; + } + set + { + _orientation = value; + BulletSimAPI.SetTranslation2(BSBody.ptr, _position, _orientation); + } + } public override int PhysicsActorType { get { return _physicsActorType; } set { _physicsActorType = value; diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs index d9b738b..1ac8c59 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs @@ -81,6 +81,10 @@ public abstract class BSPhysObject : PhysicsActor // Tell the object to clean up. public abstract void Destroy(); + public abstract OMV.Vector3 ForcePosition { get; set; } + + public abstract OMV.Quaternion ForceOrientation { get; set; } + #region Collisions // Requested number of milliseconds between collision events. Zero means disabled. diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index e37a4a0..f7b68ba 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs @@ -275,6 +275,17 @@ public sealed class BSPrim : BSPhysObject }); } } + public override OMV.Vector3 ForcePosition { + get { + _position = BulletSimAPI.GetPosition2(BSBody.ptr); + return _position; + } + set { + _position = value; + PositionSanityCheck(); + BulletSimAPI.SetTranslation2(BSBody.ptr, _position, _orientation); + } + } // Check that the current position is sane and, if not, modify the position to make it so. // Check for being below terrain and being out of bounds. @@ -377,14 +388,15 @@ public sealed class BSPrim : BSPhysObject } set { Vehicle type = (Vehicle)value; - BSPrim vehiclePrim = this; + + // Tell the scene about the vehicle so it will get processing each frame. + PhysicsScene.VehicleInSceneTypeChanged(this, type); + PhysicsScene.TaintedObject("setVehicleType", delegate() { // Done at taint time so we're sure the physics engine is not using the variables // Vehicle code changes the parameters for this vehicle type. - _vehicle.ProcessTypeChange(type); - // Tell the scene about the vehicle so it will get processing each frame. - PhysicsScene.VehicleInSceneTypeChanged(this, type); + this._vehicle.ProcessTypeChange(type); }); } } @@ -422,7 +434,9 @@ public sealed class BSPrim : BSPhysObject public override void StepVehicle(float timeStep) { if (IsPhysical) + { _vehicle.Step(timeStep); + } } // Allows the detection of collisions with inherently non-physical prims. see llVolumeDetect for more @@ -486,6 +500,20 @@ public sealed class BSPrim : BSPhysObject }); } } + // Go directly to Bullet to get/set the value. + public override OMV.Quaternion ForceOrientation + { + get + { + _orientation = BulletSimAPI.GetOrientation2(BSBody.ptr); + return _orientation; + } + set + { + _orientation = value; + BulletSimAPI.SetTranslation2(BSBody.ptr, _position, _orientation); + } + } public override int PhysicsActorType { get { return _physicsActorType; } set { _physicsActorType = value; } @@ -1170,7 +1198,8 @@ public sealed class BSPrim : BSPhysObject // Create the correct physical representation for this type of object. // Updates BSBody and BSShape with the new information. - PhysicsScene.Shapes.GetBodyAndShape(forceRebuild, PhysicsScene.World, this, shapeData, _pbs, + // Ignore 'forceRebuild'. This routine makes the right choices and changes of necessary. + PhysicsScene.Shapes.GetBodyAndShape(false, PhysicsScene.World, this, shapeData, _pbs, null, delegate(BulletBody dBody) { // Called if the current prim body is about to be destroyed. -- cgit v1.1 From 210f227fe69138f736e3d37e5bfbacd10e967922 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Tue, 2 Oct 2012 11:11:22 -0700 Subject: BulletSim: Make parameter value defaults match what should be the default and what is in OpenSimDefaults.ini. Comment and debug printout changes. --- OpenSim/Region/Physics/BulletSPlugin/BSScene.cs | 26 +++++++++++----------- .../Region/Physics/BulletSPlugin/BulletSimAPI.cs | 2 +- 2 files changed, 14 insertions(+), 14 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs index 0cf8c91..aaed7de 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs @@ -493,6 +493,10 @@ public class BSScene : PhysicsScene, IPhysicsParameters // step the physical world one interval m_simulationStep++; int numSubSteps = 0; + + // Sometimes needed for debugging to find out what happened before the step + // PhysicsLogging.Flush(); + try { if (PhysicsLogging.Enabled) beforeTime = Util.EnvironmentTickCount(); @@ -536,7 +540,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters } // This is a kludge to get avatar movement updates. - // ODE sends collisions for avatars even if there are have been no collisions. This updates + // the simulator expects collisions for avatars even if there are have been no collisions. This updates // avatar animations and stuff. // If you fix avatar animation updates, remove this overhead and let normal collision processing happen. foreach (BSPhysObject bsp in m_avatars) @@ -556,7 +560,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters } // Objects that are done colliding are removed from the ObjectsWithCollisions list. - // This can't be done by SendCollisions because it is inside an iteration of ObjectWithCollisions. + // Not done above because it is inside an iteration of ObjectWithCollisions. if (ObjectsWithNoMoreCollisions.Count > 0) { foreach (BSPhysObject po in ObjectsWithNoMoreCollisions) @@ -726,13 +730,10 @@ public class BSScene : PhysicsScene, IPhysicsParameters public void VehicleInSceneTypeChanged(BSPrim vehic, Vehicle newType) { - if (newType == Vehicle.TYPE_NONE) - { - RemoveVehiclePrim(vehic); - } - else + RemoveVehiclePrim(vehic); + if (newType != Vehicle.TYPE_NONE) { - // make it so the scene will call us each tick to do vehicle things + // make it so the scene will call us each tick to do vehicle things AddVehiclePrim(vehic); } } @@ -764,7 +765,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters } // Some prims have extra vehicle actions - // no locking because only called when physics engine is not busy + // Called at taint time! private void ProcessVehicles(float timeStep) { foreach (BSPhysObject pobj in m_vehicles) @@ -1008,12 +1009,12 @@ public class BSScene : PhysicsScene, IPhysicsParameters new ParameterDefn("MaxPersistantManifoldPoolSize", "Number of manifolds pooled (0 means default of 4096)", - 0f, // zero to disable + 0f, (s,cf,p,v) => { s.m_params[0].maxPersistantManifoldPoolSize = cf.GetFloat(p, v); }, (s) => { return s.m_params[0].maxPersistantManifoldPoolSize; }, (s,p,l,v) => { s.m_params[0].maxPersistantManifoldPoolSize = v; } ), new ParameterDefn("MaxCollisionAlgorithmPoolSize", "Number of collisions pooled (0 means default of 4096)", - 0f, // zero to disable + 0f, (s,cf,p,v) => { s.m_params[0].maxCollisionAlgorithmPoolSize = cf.GetFloat(p, v); }, (s) => { return s.m_params[0].maxCollisionAlgorithmPoolSize; }, (s,p,l,v) => { s.m_params[0].maxCollisionAlgorithmPoolSize = v; } ), @@ -1028,7 +1029,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters (s) => { return s.m_params[0].shouldForceUpdateAllAabbs; }, (s,p,l,v) => { s.m_params[0].shouldForceUpdateAllAabbs = v; } ), new ParameterDefn("ShouldRandomizeSolverOrder", "Enable for slightly better stacking interaction", - ConfigurationParameters.numericFalse, + ConfigurationParameters.numericTrue, (s,cf,p,v) => { s.m_params[0].shouldRandomizeSolverOrder = s.NumericBool(cf.GetBoolean(p, s.BoolNumeric(v))); }, (s) => { return s.m_params[0].shouldRandomizeSolverOrder; }, (s,p,l,v) => { s.m_params[0].shouldRandomizeSolverOrder = v; } ), @@ -1152,7 +1153,6 @@ public class BSScene : PhysicsScene, IPhysicsParameters { if (SettableParameters.Length < ParameterDefinitions.Length) { - List entries = new List(); for (int ii = 0; ii < ParameterDefinitions.Length; ii++) { diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs index d49e5f3..a43880d 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs @@ -71,7 +71,7 @@ public struct BulletBody buff.Append(ID.ToString()); buff.Append(",p="); buff.Append(ptr.ToString("X")); - if (collisionFilter != 0 && collisionMask != 0) + if (collisionFilter != 0 || collisionMask != 0) { buff.Append(",f="); buff.Append(collisionFilter.ToString("X")); -- cgit v1.1 From 35b7c80e0ba876649c606d5d047fcb59754372ea Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Tue, 31 Jul 2012 14:45:23 +0100 Subject: implementing osDropAttachment & osDropAttachmentAt --- .../Avatar/Attachments/AttachmentsModule.cs | 11 +++++++- .../Framework/Interfaces/IAttachmentsModule.cs | 9 ++++++ .../Shared/Api/Implementation/OSSL_Api.cs | 33 ++++++++++++++++++++-- .../ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs | 12 ++++++++ .../ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs | 10 +++++++ 5 files changed, 72 insertions(+), 3 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs index 130c869..2a513e9 100644 --- a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs @@ -407,6 +407,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments public void DetachSingleAttachmentToGround(IScenePresence sp, uint soLocalId) { + DetachSingleAttachmentToGround(sp, soLocalId, sp.AbsolutePosition, Quaternion.Identity); + } + + public void DetachSingleAttachmentToGround(IScenePresence sp, uint soLocalId, Vector3 absolutePos, Quaternion absoluteRot) + { if (!Enabled) return; @@ -448,7 +453,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments so.FromItemID = UUID.Zero; SceneObjectPart rootPart = so.RootPart; - so.AbsolutePosition = sp.AbsolutePosition; + so.AbsolutePosition = absolutePos; + if (absoluteRot != Quaternion.Identity) + { + so.UpdateGroupRotationR(absoluteRot); + } so.AttachedAvatar = UUID.Zero; rootPart.SetParentLocalId(0); so.ClearPartAttachmentData(); diff --git a/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs b/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs index 8155eab..620ec22 100644 --- a/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs +++ b/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs @@ -109,6 +109,15 @@ namespace OpenSim.Region.Framework.Interfaces void DetachSingleAttachmentToGround(IScenePresence sp, uint objectLocalID); /// + /// Detach the given item to the ground at the specified coordinates & rotation + /// + /// + /// + /// + /// + void DetachSingleAttachmentToGround(IScenePresence sp, uint objectLocalID, Vector3 absolutePos, Quaternion absoluteRot); + + /// /// Detach the given attachment so that it remains in the user's inventory. /// /// /param> diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs index 8b73cd9..fec8a67 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs @@ -3549,6 +3549,35 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (m_UrlModule != null) m_UrlModule.HttpContentType(new UUID(id),type); } - - } + + public void osDropAttachment() + { + CheckThreatLevel(ThreatLevel.Moderate, "osDropAttachment"); + m_host.AddScriptLPS(1); + + IAttachmentsModule attachmentsModule = m_ScriptEngine.World.AttachmentsModule; + ScenePresence sp = attachmentsModule == null ? null : m_host.ParentGroup.Scene.GetScenePresence(m_host.ParentGroup.OwnerID); + + if (attachmentsModule != null && sp != null) + { + attachmentsModule.DetachSingleAttachmentToGround(sp, m_host.ParentGroup.LocalId); + } + } + + public void osDropAttachmentAt(LSL_Vector pos, LSL_Rotation rot) + { + CheckThreatLevel(ThreatLevel.Moderate, "osDropAttachment"); + m_host.AddScriptLPS(1); + + IAttachmentsModule attachmentsModule = m_ScriptEngine.World.AttachmentsModule; + ScenePresence sp = attachmentsModule == null ? null : m_host.ParentGroup.Scene.GetScenePresence(m_host.ParentGroup.OwnerID); + + if (attachmentsModule != null && sp != null) + { + Vector3 omvPos = new Vector3((float)pos.x, (float)pos.y, (float)pos.z); + Quaternion omvRot = LSL_Api.Rot2Quaternion(rot); + attachmentsModule.DetachSingleAttachmentToGround(sp, m_host.ParentGroup.LocalId, omvPos, omvRot); + } + } + } } \ No newline at end of file diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs index 3985e66..e28473d 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs @@ -394,5 +394,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces /// /// void osSetContentType(LSL_Key id, string type); + + /// + /// Attempts to drop an attachment to the ground + /// + void osDropAttachment(); + + /// + /// Attempts to drop an attachment at the specified coordinates. + /// + /// + /// + void osDropAttachmentAt(vector pos, rotation rot); } } diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs index 52ca3da..bae5594 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs @@ -972,5 +972,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase { m_OSSL_Functions.osSetContentType(id,type); } + + public void osDropAttachment() + { + m_OSSL_Functions.osDropAttachment(); + } + + public void osDropAttachmentAt(vector pos, rotation rot) + { + m_OSSL_Functions.osDropAttachmentAt(pos, rot); + } } } -- cgit v1.1 From c677c04f10bf0ec9ed66799effe2b3d4c881f5dd Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Tue, 31 Jul 2012 15:24:15 +0100 Subject: fixing copypasta --- OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs index fec8a67..02b97e8 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs @@ -3566,7 +3566,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public void osDropAttachmentAt(LSL_Vector pos, LSL_Rotation rot) { - CheckThreatLevel(ThreatLevel.Moderate, "osDropAttachment"); + CheckThreatLevel(ThreatLevel.Moderate, "osDropAttachmentAt"); m_host.AddScriptLPS(1); IAttachmentsModule attachmentsModule = m_ScriptEngine.World.AttachmentsModule; -- cgit v1.1 From ce7694c108e8abf2e52a0b0167eab3d550f364ab Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Wed, 1 Aug 2012 10:28:58 +0100 Subject: added perms checking, duplicated functionality to methods that do not require perms and have higher threat level --- .../Shared/Api/Implementation/OSSL_Api.cs | 70 ++++++++++++++++++++-- .../ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs | 12 ++++ .../ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs | 10 ++++ 3 files changed, 86 insertions(+), 6 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs index 02b97e8..d0db15f 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs @@ -3538,7 +3538,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api return new LSL_Key(m_host.ParentGroup.FromPartID.ToString()); } - + /// /// Sets the response type for an HTTP request/response /// @@ -3549,11 +3549,35 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (m_UrlModule != null) m_UrlModule.HttpContentType(new UUID(id),type); } - - public void osDropAttachment() + /// Shout an error if the object owner did not grant the script the specified permissions. + /// + /// + /// boolean indicating whether an error was shouted. + protected bool ShoutErrorOnLackingOwnerPerms(int perms, string errorPrefix) { CheckThreatLevel(ThreatLevel.Moderate, "osDropAttachment"); m_host.AddScriptLPS(1); + bool fail = false; + if (m_item.PermsGranter != m_host.OwnerID) + { + fail = true; + OSSLShoutError(string.Format("{0}. Permissions not granted to owner.", errorPrefix)); + } + else if ((m_item.PermsMask & perms) == 0) + { + fail = true; + OSSLShoutError(string.Format("{0}. Permissions not granted.", errorPrefix)); + } + + return fail; + } + + protected void DropAttachment(bool checkPerms) + { + if (checkPerms && ShoutErrorOnLackingOwnerPerms(ScriptBaseClass.PERMISSION_ATTACH, "Cannot drop attachment")) + { + return; + } IAttachmentsModule attachmentsModule = m_ScriptEngine.World.AttachmentsModule; ScenePresence sp = attachmentsModule == null ? null : m_host.ParentGroup.Scene.GetScenePresence(m_host.ParentGroup.OwnerID); @@ -3564,10 +3588,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } } - public void osDropAttachmentAt(LSL_Vector pos, LSL_Rotation rot) + protected void DropAttachemntAt(bool checkPerms, LSL_Vector pos, LSL_Rotation rot) { - CheckThreatLevel(ThreatLevel.Moderate, "osDropAttachmentAt"); - m_host.AddScriptLPS(1); + if (checkPerms && ShoutErrorOnLackingOwnerPerms(ScriptBaseClass.PERMISSION_ATTACH, "Cannot drop attachment")) + { + return; + } IAttachmentsModule attachmentsModule = m_ScriptEngine.World.AttachmentsModule; ScenePresence sp = attachmentsModule == null ? null : m_host.ParentGroup.Scene.GetScenePresence(m_host.ParentGroup.OwnerID); @@ -3579,5 +3605,37 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api attachmentsModule.DetachSingleAttachmentToGround(sp, m_host.ParentGroup.LocalId, omvPos, omvRot); } } + + public void osDropAttachment() + { + CheckThreatLevel(ThreatLevel.Moderate, "osDropAttachment"); + m_host.AddScriptLPS(1); + + DropAttachment(true); + } + + public void osForceDropAttachment() + { + CheckThreatLevel(ThreatLevel.High, "osForceDropAttachment"); + m_host.AddScriptLPS(1); + + DropAttachment(false); + } + + public void osDropAttachmentAt(LSL_Vector pos, LSL_Rotation rot) + { + CheckThreatLevel(ThreatLevel.Moderate, "osDropAttachmentAt"); + m_host.AddScriptLPS(1); + + DropAttachemntAt(true, pos, rot); + } + + public void osForceDropAttachmentAt(LSL_Vector pos, LSL_Rotation rot) + { + CheckThreatLevel(ThreatLevel.High, "osForceDropAttachmentAt"); + m_host.AddScriptLPS(1); + + DropAttachemntAt(false, pos, rot); + } } } \ No newline at end of file diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs index e28473d..93188c9 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs @@ -401,10 +401,22 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces void osDropAttachment(); /// + /// Attempts to drop an attachment to the ground while bypassing the script permissions + /// + void osForceDropAttachment(); + + /// /// Attempts to drop an attachment at the specified coordinates. /// /// /// void osDropAttachmentAt(vector pos, rotation rot); + + /// + /// Attempts to drop an attachment at the specified coordinates while bypassing the script permissions + /// + /// + /// + void osForceDropAttachmentAt(vector pos, rotation rot); } } diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs index bae5594..dee1b28 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs @@ -978,9 +978,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase m_OSSL_Functions.osDropAttachment(); } + public void osForceDropAttachment() + { + m_OSSL_Functions.osForceDropAttachment(); + } + public void osDropAttachmentAt(vector pos, rotation rot) { m_OSSL_Functions.osDropAttachmentAt(pos, rot); } + + public void osForceDropAttachmentAt(vector pos, rotation rot) + { + m_OSSL_Functions.osForceDropAttachmentAt(pos, rot); + } } } -- cgit v1.1 From f555febdb7c6bbd9ef8b98f897e6c296a62b23fe Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Mon, 20 Aug 2012 10:19:39 +0100 Subject: taking into account the recent introduction of implicit operators --- OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs index d0db15f..e56a36f 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs @@ -3600,9 +3600,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (attachmentsModule != null && sp != null) { - Vector3 omvPos = new Vector3((float)pos.x, (float)pos.y, (float)pos.z); - Quaternion omvRot = LSL_Api.Rot2Quaternion(rot); - attachmentsModule.DetachSingleAttachmentToGround(sp, m_host.ParentGroup.LocalId, omvPos, omvRot); + attachmentsModule.DetachSingleAttachmentToGround(sp, m_host.ParentGroup.LocalId, pos, rot); } } -- cgit v1.1 From a1679517d39f11591c89203eba914f52c09838ea Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Sun, 30 Sep 2012 12:27:53 +0100 Subject: correcting typo --- OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs index e56a36f..31be450 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs @@ -3588,7 +3588,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } } - protected void DropAttachemntAt(bool checkPerms, LSL_Vector pos, LSL_Rotation rot) + protected void DropAttachmentAt(bool checkPerms, LSL_Vector pos, LSL_Rotation rot) { if (checkPerms && ShoutErrorOnLackingOwnerPerms(ScriptBaseClass.PERMISSION_ATTACH, "Cannot drop attachment")) { @@ -3625,7 +3625,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api CheckThreatLevel(ThreatLevel.Moderate, "osDropAttachmentAt"); m_host.AddScriptLPS(1); - DropAttachemntAt(true, pos, rot); + DropAttachmentAt(true, pos, rot); } public void osForceDropAttachmentAt(LSL_Vector pos, LSL_Rotation rot) @@ -3633,7 +3633,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api CheckThreatLevel(ThreatLevel.High, "osForceDropAttachmentAt"); m_host.AddScriptLPS(1); - DropAttachemntAt(false, pos, rot); + DropAttachmentAt(false, pos, rot); } } } \ No newline at end of file -- cgit v1.1 From f1886c449cd3395de66bacbce0f3704c77c6a935 Mon Sep 17 00:00:00 2001 From: Melanie Date: Tue, 2 Oct 2012 23:02:01 +0100 Subject: Attempt to fix Mantis #6311. Honor a destination folder if one is given --- .../Inventory/Transfer/InventoryTransferModule.cs | 39 ++++++++++++++++++++++ 1 file changed, 39 insertions(+) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs index f3af59a..91eda19 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs @@ -297,6 +297,45 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer }); } } + else if (im.dialog == (byte) InstantMessageDialog.TaskInventoryAccepted) + { + UUID destinationFolderID = UUID.Zero; + + if (im.binaryBucket != null && im.binaryBucket.Length >= 16) + { + destinationFolderID = new UUID(im.binaryBucket, 0); + } + + if (destinationFolderID != UUID.Zero) + { + IInventoryService invService = scene.InventoryService; + + UUID inventoryID = new UUID(im.imSessionID); // The inventory item/folder, back from it's trip + + InventoryItemBase item = new InventoryItemBase(inventoryID, client.AgentId); + item = invService.GetItem(item); + InventoryFolderBase folder = null; + + if (item != null) // It's an item + { + item.Folder = destinationFolderID; + + invService.DeleteItems(item.Owner, new List() { item.ID }); + scene.AddInventoryItem(client, item); + } + else + { + folder = new InventoryFolderBase(inventoryID, client.AgentId); + folder = invService.GetFolder(folder); + + if (folder != null) // It's a folder + { + folder.ParentID = destinationFolderID; + invService.MoveFolder(folder); + } + } + } + } else if ( im.dialog == (byte)InstantMessageDialog.InventoryDeclined || im.dialog == (byte)InstantMessageDialog.TaskInventoryDeclined) -- cgit v1.1 From df3d1d13014cf937240ddc2131231624b47eaccd Mon Sep 17 00:00:00 2001 From: teravus Date: Tue, 2 Oct 2012 23:14:35 -0400 Subject: Minor Modification, switch /2 to 0.5f in ODEPrim.Velocity --- OpenSim/Region/Physics/OdePlugin/ODEPrim.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs b/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs index 0716214..3056f67 100644 --- a/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs +++ b/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs @@ -2395,15 +2395,15 @@ Console.WriteLine(" JointCreateFixed"); { get { - // Averate previous velocity with the new one so + // Average previous velocity with the new one so // client object interpolation works a 'little' better if (_zeroFlag) return Vector3.Zero; Vector3 returnVelocity = Vector3.Zero; - returnVelocity.X = (m_lastVelocity.X + _velocity.X)/2; - returnVelocity.Y = (m_lastVelocity.Y + _velocity.Y)/2; - returnVelocity.Z = (m_lastVelocity.Z + _velocity.Z)/2; + returnVelocity.X = (m_lastVelocity.X + _velocity.X) * 0.5f; // 0.5f is mathematically equiv to '/ 2' + returnVelocity.Y = (m_lastVelocity.Y + _velocity.Y) * 0.5f; + returnVelocity.Z = (m_lastVelocity.Z + _velocity.Z) * 0.5f; return returnVelocity; } set -- cgit v1.1 From e56ef2720ecd603c9b3c81cbb7c3a0d49d24bf85 Mon Sep 17 00:00:00 2001 From: teravus Date: Wed, 3 Oct 2012 02:30:23 -0400 Subject: I propose that 0.5m/step change for linear velocity is too big of a change to control the reporting of a new angular velocity. I think that this could be here for one of two reasons, 1. vehicles and llMoveToTarget with axis lock, or 2. To attempt to make things look more stable in the physics scene then they really are, however, this also really affects the angular velocity reporting negatively causing things to spin wildly and jump back into place repeatedly. To compromise, if the prim is a vehicle or is being used as a motor target, the original functionality is still applied. If that's not the case, angular velocity is reported with a linear velocity of 0.02m/step. To be clear on the effect of the physical world... When you push things, there's still a lag time where you walk into the object but once the object is in motion, it begins to move as you would expect so results in slightly more realistic motion. --- OpenSim/Region/Physics/OdePlugin/ODEPrim.cs | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs b/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs index 3056f67..1b47754 100644 --- a/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs +++ b/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs @@ -2600,6 +2600,7 @@ Console.WriteLine(" JointCreateFixed"); { Vector3 pv = Vector3.Zero; bool lastZeroFlag = _zeroFlag; + float m_minvelocity = 0; if (Body != (IntPtr)0) // FIXME -> or if it is a joint { d.Vector3 vec = d.BodyGetPosition(Body); @@ -2752,8 +2753,21 @@ Console.WriteLine(" JointCreateFixed"); _acceleration = ((_velocity - m_lastVelocity) / 0.1f); _acceleration = new Vector3(_velocity.X - m_lastVelocity.X / 0.1f, _velocity.Y - m_lastVelocity.Y / 0.1f, _velocity.Z - m_lastVelocity.Z / 0.1f); //m_log.Info("[PHYSICS]: V1: " + _velocity + " V2: " + m_lastVelocity + " Acceleration: " + _acceleration.ToString()); + + // Note here that linearvelocity is affecting angular velocity... so I'm guessing this is a vehicle specific thing... + // it does make sense to do this for tiny little instabilities with physical prim, however 0.5m/frame is fairly large. + // reducing this to 0.02m/frame seems to help the angular rubberbanding quite a bit, however, to make sure it doesn't affect elevators and vehicles + // adding these logical exclusion situations to maintain this where I think it was intended to be. + if (m_throttleUpdates || m_usePID || (m_vehicle != null && m_vehicle.Type != Vehicle.TYPE_NONE) || (Amotor != IntPtr.Zero)) + { + m_minvelocity = 0.5f; + } + else + { + m_minvelocity = 0.02f; + } - if (_velocity.ApproxEquals(pv, 0.5f)) + if (_velocity.ApproxEquals(pv, m_minvelocity)) { m_rotationalVelocity = pv; } -- cgit v1.1 From 653a98e891dcd97b55010900bacc4d033958756a Mon Sep 17 00:00:00 2001 From: Melanie Date: Wed, 3 Oct 2012 17:39:13 +0100 Subject: Fix a viewer crash issue Conflicts: OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs --- .../ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) (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 52d96bc..7fa6f05 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -4006,7 +4006,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { m_host.AddScriptLPS(1); Vector3 av3 = Util.Clip(color, 0.0f, 1.0f); - m_host.SetText(text.Length > 254 ? text.Remove(254) : text, av3, Util.Clip((float)alpha, 0.0f, 1.0f)); + if (text.Length > 254) + text = text.Remove(254); + + byte[] data; + do + { + data = Util.UTF8.GetBytes(text); + if (data.Length > 254) + text = text.Substring(0, text.Length - 1); + } while (data.Length > 254); + + m_host.SetText(text, av3, Util.Clip((float)alpha, 0.0f, 1.0f)); //m_host.ParentGroup.HasGroupChanged = true; //m_host.ParentGroup.ScheduleGroupForFullUpdate(); } -- cgit v1.1 From b9baab55216a112df039480f9b6914c0078ab3fa Mon Sep 17 00:00:00 2001 From: Mic Bowman Date: Wed, 3 Oct 2012 10:45:57 -0700 Subject: Fix the use of the wrong index when locating the assets associated with wearables. The fact that this hasn't caused problems earlier suggests either that no one is using multiple layers of wearables or that this code is useless because the assets are coming in with the wearables request. --- OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs index 1d6e522..b5b0082 100644 --- a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs @@ -525,7 +525,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory { for (int i = 0; i < AvatarWearable.MAX_WEARABLES; i++) { - for (int j = 0; j < appearance.Wearables[j].Count; j++) + for (int j = 0; j < appearance.Wearables[i].Count; j++) { if (appearance.Wearables[i][j].ItemID == UUID.Zero) continue; @@ -533,6 +533,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory // Ignore ruth's assets if (appearance.Wearables[i][j].ItemID == AvatarWearable.DefaultWearables[i][0].ItemID) continue; + InventoryItemBase baseItem = new InventoryItemBase(appearance.Wearables[i][j].ItemID, userID); baseItem = invService.GetItem(baseItem); -- cgit v1.1 From a2ab3b88de764112996b1e37d74c1e7b7355b1d8 Mon Sep 17 00:00:00 2001 From: teravus Date: Wed, 3 Oct 2012 18:30:44 -0400 Subject: Soliciting for comments on smoothness of physics objects for this build. This introduces expected contact point hints to the ODE Collider to better determine when to throttle updates as excessive. This /should/ smooth physics objects out again, however, I cannot know every configuration of OpenSimulator, so I'm requesting that testers please examine this change on their build. Thanks! --- OpenSim/Region/Physics/OdePlugin/ODEPrim.cs | 13 +++++++-- OpenSim/Region/Physics/OdePlugin/OdeScene.cs | 41 ++++++++++++++++++++++++---- 2 files changed, 46 insertions(+), 8 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs b/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs index 1b47754..e7b3b2b 100644 --- a/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs +++ b/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs @@ -63,6 +63,9 @@ namespace OpenSim.Region.Physics.OdePlugin private bool m_isphysical; + public int ExpectedCollisionContacts { get { return m_expectedCollisionContacts; } } + private int m_expectedCollisionContacts = 0; + /// /// Is this prim subject to physics? Even if not, it's still solid for collision purposes. /// @@ -150,7 +153,7 @@ namespace OpenSim.Region.Physics.OdePlugin private PrimitiveBaseShape _pbs; private OdeScene _parent_scene; - + /// /// The physics space which contains prim geometries /// @@ -840,7 +843,7 @@ namespace OpenSim.Region.Physics.OdePlugin int vertexStride, triStride; mesh.getVertexListAsPtrToFloatArray(out vertices, out vertexStride, out vertexCount); // Note, that vertices are fixed in unmanaged heap mesh.getIndexListAsPtrToIntArray(out indices, out triStride, out indexCount); // Also fixed, needs release after usage - + m_expectedCollisionContacts = indexCount; mesh.releaseSourceMeshData(); // free up the original mesh data to save memory // We must lock here since m_MeshToTriMeshMap is static and multiple scene threads may call this method at @@ -1377,6 +1380,7 @@ Console.WriteLine("CreateGeom:"); { //Console.WriteLine(" CreateGeom 1"); SetGeom(d.CreateSphere(m_targetSpace, _size.X / 2)); + m_expectedCollisionContacts = 3; } catch (AccessViolationException) { @@ -1391,6 +1395,7 @@ Console.WriteLine("CreateGeom:"); { //Console.WriteLine(" CreateGeom 2"); SetGeom(d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z)); + m_expectedCollisionContacts = 4; } catch (AccessViolationException) { @@ -1406,6 +1411,7 @@ Console.WriteLine("CreateGeom:"); { //Console.WriteLine(" CreateGeom 3"); SetGeom(d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z)); + m_expectedCollisionContacts = 4; } catch (AccessViolationException) { @@ -1421,6 +1427,7 @@ Console.WriteLine("CreateGeom:"); { //Console.WriteLine(" CreateGeom 4"); SetGeom(d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z)); + m_expectedCollisionContacts = 4; } catch (AccessViolationException) { @@ -1446,11 +1453,13 @@ Console.WriteLine("CreateGeom:"); _parent_scene.geom_name_map.Remove(prim_geom); _parent_scene.actor_name_map.Remove(prim_geom); d.GeomDestroy(prim_geom); + m_expectedCollisionContacts = 0; prim_geom = IntPtr.Zero; } catch (System.AccessViolationException) { prim_geom = IntPtr.Zero; + m_expectedCollisionContacts = 0; m_log.ErrorFormat("[PHYSICS]: PrimGeom dead for {0}", Name); return false; diff --git a/OpenSim/Region/Physics/OdePlugin/OdeScene.cs b/OpenSim/Region/Physics/OdePlugin/OdeScene.cs index 929b019..7a50c4c 100644 --- a/OpenSim/Region/Physics/OdePlugin/OdeScene.cs +++ b/OpenSim/Region/Physics/OdePlugin/OdeScene.cs @@ -336,6 +336,7 @@ namespace OpenSim.Region.Physics.OdePlugin public int geomContactPointsStartthrottle = 3; public int geomUpdatesPerThrottledUpdate = 15; + private const int avatarExpectedContacts = 3; public float bodyPIDD = 35f; public float bodyPIDG = 25; @@ -474,6 +475,8 @@ namespace OpenSim.Region.Physics.OdePlugin private OdePrim cp1; private OdeCharacter cc2; private OdePrim cp2; + private int p1ExpectedPoints = 0; + private int p2ExpectedPoints = 0; //private int cStartStop = 0; //private string cDictKey = ""; @@ -498,6 +501,7 @@ namespace OpenSim.Region.Physics.OdePlugin public int physics_logging_interval = 0; public bool physics_logging_append_existing_logfile = false; + public d.Vector3 xyz = new d.Vector3(128.1640f, 128.3079f, 25.7600f); public d.Vector3 hpr = new d.Vector3(125.5000f, -17.0000f, 0.0000f); @@ -644,7 +648,7 @@ namespace OpenSim.Region.Physics.OdePlugin contactsPerCollision = physicsconfig.GetInt("contacts_per_collision", 80); - geomContactPointsStartthrottle = physicsconfig.GetInt("geom_contactpoints_start_throttling", 3); + geomContactPointsStartthrottle = physicsconfig.GetInt("geom_contactpoints_start_throttling", 5); geomUpdatesPerThrottledUpdate = physicsconfig.GetInt("geom_updates_before_throttled_update", 15); geomCrossingFailuresBeforeOutofbounds = physicsconfig.GetInt("geom_crossing_failures_before_outofbounds", 5); @@ -1064,7 +1068,10 @@ namespace OpenSim.Region.Physics.OdePlugin PhysicsActor p1; PhysicsActor p2; - + + p1ExpectedPoints = 0; + p2ExpectedPoints = 0; + if (!actor_name_map.TryGetValue(g1, out p1)) { p1 = PANull; @@ -1121,9 +1128,13 @@ namespace OpenSim.Region.Physics.OdePlugin switch (p1.PhysicsActorType) { case (int)ActorTypes.Agent: + p1ExpectedPoints = avatarExpectedContacts; p2.CollidingObj = true; break; case (int)ActorTypes.Prim: + if (p1 != null && p1 is OdePrim) + p1ExpectedPoints = ((OdePrim) p1).ExpectedCollisionContacts; + if (p2.Velocity.LengthSquared() > 0.0f) p2.CollidingObj = true; break; @@ -1319,6 +1330,7 @@ namespace OpenSim.Region.Physics.OdePlugin if ((p2.PhysicsActorType == (int) ActorTypes.Agent) && (Math.Abs(p2.Velocity.X) > 0.01f || Math.Abs(p2.Velocity.Y) > 0.01f)) { + p2ExpectedPoints = avatarExpectedContacts; // Avatar is moving on terrain, use the movement terrain contact AvatarMovementTerrainContact.geom = curContact; @@ -1332,6 +1344,7 @@ namespace OpenSim.Region.Physics.OdePlugin { if (p2.PhysicsActorType == (int)ActorTypes.Agent) { + p2ExpectedPoints = avatarExpectedContacts; // Avatar is standing on terrain, use the non moving terrain contact TerrainContact.geom = curContact; @@ -1356,9 +1369,18 @@ namespace OpenSim.Region.Physics.OdePlugin } if (p2 is OdePrim) - material = ((OdePrim)p2).m_material; - + { + material = ((OdePrim) p2).m_material; + p2ExpectedPoints = ((OdePrim)p2).ExpectedCollisionContacts; + } + + // Unnessesary because p1 is defined above + //if (p1 is OdePrim) + // { + // p1ExpectedPoints = ((OdePrim)p1).ExpectedCollisionContacts; + // } //m_log.DebugFormat("Material: {0}", material); + m_materialContacts[material, movintYN].geom = curContact; if (m_global_contactcount < maxContactsbeforedeath) @@ -1379,7 +1401,10 @@ namespace OpenSim.Region.Physics.OdePlugin int material = (int)Material.Wood; if (p2 is OdePrim) + { material = ((OdePrim)p2).m_material; + p2ExpectedPoints = ((OdePrim)p2).ExpectedCollisionContacts; + } //m_log.DebugFormat("Material: {0}", material); m_materialContacts[material, movintYN].geom = curContact; @@ -1429,6 +1454,7 @@ namespace OpenSim.Region.Physics.OdePlugin { if ((p2.PhysicsActorType == (int)ActorTypes.Agent)) { + p2ExpectedPoints = avatarExpectedContacts; if ((Math.Abs(p2.Velocity.X) > 0.01f || Math.Abs(p2.Velocity.Y) > 0.01f)) { // Avatar is moving on a prim, use the Movement prim contact @@ -1458,7 +1484,10 @@ namespace OpenSim.Region.Physics.OdePlugin int material = (int)Material.Wood; if (p2 is OdePrim) + { material = ((OdePrim)p2).m_material; + p2ExpectedPoints = ((OdePrim)p2).ExpectedCollisionContacts; + } //m_log.DebugFormat("Material: {0}", material); m_materialContacts[material, 0].geom = curContact; @@ -1479,8 +1508,8 @@ namespace OpenSim.Region.Physics.OdePlugin } collision_accounting_events(p1, p2, maxDepthContact); - - if (count > geomContactPointsStartthrottle) + + if (count > ((p1ExpectedPoints + p2ExpectedPoints) * 0.25) + (geomContactPointsStartthrottle)) { // If there are more then 3 contact points, it's likely // that we've got a pile of objects, so ... -- cgit v1.1 From e717398f6c72bdb30e59468462f3a5f589c1bb35 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Thu, 4 Oct 2012 00:32:42 +0100 Subject: Add experimental "slow frames" stat, available in "show stats" and via the monitoring module. This increments a SlowFrames counter if a frame takes over 120% of maximum time. This commit also introduces a generic OpenSim.Framework.Monitoring.Stat which is available to any code that wants to register a statistic. This is more granualar than asking objects to create their own reports. At some point this will supersede earlier IMonitor and IAlert facilities in MonitoringModule which are only available to scene code. --- .../Region/Framework/Scenes/SimStatsReporter.cs | 33 ++++++++++++++++++++++ 1 file changed, 33 insertions(+) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs b/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs index 96317c3..b7b5ea2 100644 --- a/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs +++ b/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs @@ -47,6 +47,7 @@ namespace OpenSim.Region.Framework.Scenes = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); public const string LastReportedObjectUpdateStatName = "LastReportedObjectUpdates"; + public const string SlowFramesStatName = "SlowFrames"; public delegate void SendStatResult(SimStats stats); @@ -129,6 +130,16 @@ namespace OpenSim.Region.Framework.Scenes } /// + /// Number of frames that have taken longer to process than Scene.MIN_FRAME_TIME + /// + public Stat SlowFramesStat { get; private set; } + + /// + /// The threshold at which we log a slow frame. + /// + public int SlowFramesStatReportThreshold { get; private set; } + + /// /// Extra sim statistics that are used by monitors but not sent to the client. /// /// @@ -225,6 +236,22 @@ namespace OpenSim.Region.Framework.Scenes if (StatsManager.SimExtraStats != null) OnSendStatsResult += StatsManager.SimExtraStats.ReceiveClassicSimStatsPacket; + + /// At the moment, we'll only report if a frame is over 120% of target, since commonly frames are a bit + /// longer than ideal (which in itself is a concern). + SlowFramesStatReportThreshold = (int)Math.Ceiling(m_scene.MinFrameTime * 1000 * 1.2); + + SlowFramesStat + = new Stat( + "SlowFrames", + "Slow Frames", + "frames", + "scene", + m_scene.Name, + StatVerbosity.Info, + "Number of frames where frame time has been significantly longer than the desired frame time."); + + StatsManager.RegisterStat(SlowFramesStat); } public void Close() @@ -418,6 +445,7 @@ namespace OpenSim.Region.Framework.Scenes lock (m_lastReportedExtraSimStats) { m_lastReportedExtraSimStats[LastReportedObjectUpdateStatName] = m_objectUpdates / m_statsUpdateFactor; + m_lastReportedExtraSimStats[SlowFramesStat.ShortName] = (float)SlowFramesStat.Value; Dictionary physicsStats = m_scene.PhysicsScene.GetStats(); @@ -535,6 +563,11 @@ namespace OpenSim.Region.Framework.Scenes public void addFrameMS(int ms) { m_frameMS += ms; + + // At the moment, we'll only report if a frame is over 120% of target, since commonly frames are a bit + // longer than ideal due to the inaccuracy of the Sleep in Scene.Update() (which in itself is a concern). + if (ms > SlowFramesStatReportThreshold) + SlowFramesStat.Value++; } public void AddSpareMS(int ms) -- cgit v1.1 From 3d36a6d55cb0bba408f5447d4596c12564366030 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Thu, 4 Oct 2012 01:27:40 +0100 Subject: Add generic PercentageStat. Not yet used. --- OpenSim/Region/Framework/Scenes/SimStatsReporter.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs b/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs index b7b5ea2..2addb5b 100644 --- a/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs +++ b/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs @@ -245,7 +245,7 @@ namespace OpenSim.Region.Framework.Scenes = new Stat( "SlowFrames", "Slow Frames", - "frames", + " frames", "scene", m_scene.Name, StatVerbosity.Info, -- cgit v1.1 From aa52c8b20fc041ee505301301a14192ecb8776de Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Thu, 4 Oct 2012 02:17:57 +0100 Subject: Output monitor data in response to console command on MainConsole.Instance rather than m_log This should really be happening for all console commands (though many don't). However, things might get difficult if both a console command and other code invoke the same paths. --- OpenSim/Region/CoreModules/Framework/Monitoring/MonitorModule.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/Framework/Monitoring/MonitorModule.cs b/OpenSim/Region/CoreModules/Framework/Monitoring/MonitorModule.cs index e135c21..e411585 100644 --- a/OpenSim/Region/CoreModules/Framework/Monitoring/MonitorModule.cs +++ b/OpenSim/Region/CoreModules/Framework/Monitoring/MonitorModule.cs @@ -95,14 +95,14 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring { foreach (IMonitor monitor in m_staticMonitors) { - m_log.InfoFormat( + MainConsole.Instance.OutputFormat( "[MONITOR MODULE]: {0} reports {1} = {2}", m_scene.RegionInfo.RegionName, monitor.GetFriendlyName(), monitor.GetFriendlyValue()); } foreach (KeyValuePair tuple in m_scene.StatsReporter.GetExtraSimStats()) { - m_log.InfoFormat( + MainConsole.Instance.OutputFormat( "[MONITOR MODULE]: {0} reports {1} = {2}", m_scene.RegionInfo.RegionName, tuple.Key, tuple.Value); } -- cgit v1.1 From b977f962fab9be0c823b0b3ae9b4777241c9f22c Mon Sep 17 00:00:00 2001 From: Melanie Date: Thu, 4 Oct 2012 15:20:04 +0200 Subject: Allow default animation to be stopped to be replaced with another one. Fixes Mantis #6327 --- .../Framework/Scenes/Animation/AnimationSet.cs | 27 ++++++++++++++-------- .../Scenes/Animation/ScenePresenceAnimator.cs | 18 ++++++++++----- 2 files changed, 29 insertions(+), 16 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Framework/Scenes/Animation/AnimationSet.cs b/OpenSim/Region/Framework/Scenes/Animation/AnimationSet.cs index 33041e9..ad421ee 100644 --- a/OpenSim/Region/Framework/Scenes/Animation/AnimationSet.cs +++ b/OpenSim/Region/Framework/Scenes/Animation/AnimationSet.cs @@ -87,7 +87,7 @@ namespace OpenSim.Region.Framework.Scenes.Animation { if (m_defaultAnimation.AnimID == animID) { - ResetDefaultAnimation(); + m_defaultAnimation = new OpenSim.Framework.Animation(UUID.Zero, 1, UUID.Zero); } else if (HasAnimation(animID)) { @@ -149,19 +149,26 @@ namespace OpenSim.Region.Framework.Scenes.Animation { lock (m_animations) { - animIDs = new UUID[m_animations.Count + 1]; - sequenceNums = new int[m_animations.Count + 1]; - objectIDs = new UUID[m_animations.Count + 1]; + int defaultSize = 0; + if (m_defaultAnimation.AnimID != UUID.Zero) + defaultSize++; - animIDs[0] = m_defaultAnimation.AnimID; - sequenceNums[0] = m_defaultAnimation.SequenceNum; - objectIDs[0] = m_defaultAnimation.ObjectID; + animIDs = new UUID[m_animations.Count + defaultSize]; + sequenceNums = new int[m_animations.Count + defaultSize]; + objectIDs = new UUID[m_animations.Count + defaultSize]; + + if (m_defaultAnimation.AnimID != UUID.Zero) + { + animIDs[0] = m_defaultAnimation.AnimID; + sequenceNums[0] = m_defaultAnimation.SequenceNum; + objectIDs[0] = m_defaultAnimation.ObjectID; + } for (int i = 0; i < m_animations.Count; ++i) { - animIDs[i + 1] = m_animations[i].AnimID; - sequenceNums[i + 1] = m_animations[i].SequenceNum; - objectIDs[i + 1] = m_animations[i].ObjectID; + animIDs[i + defaultSize] = m_animations[i].AnimID; + sequenceNums[i + defaultSize] = m_animations[i].SequenceNum; + objectIDs[i + defaultSize] = m_animations[i].ObjectID; } } } diff --git a/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs b/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs index ff53f45..bb33f07 100644 --- a/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs +++ b/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs @@ -408,13 +408,19 @@ namespace OpenSim.Region.Framework.Scenes.Animation { lock (m_animations) { - CurrentMovementAnimation = DetermineMovementAnimation(); + string newMovementAnimation = DetermineMovementAnimation(); + if (CurrentMovementAnimation != newMovementAnimation) + { + CurrentMovementAnimation = DetermineMovementAnimation(); -// m_log.DebugFormat( -// "[SCENE PRESENCE ANIMATOR]: Determined animation {0} for {1} in UpdateMovementAnimations()", -// CurrentMovementAnimation, m_scenePresence.Name); +// m_log.DebugFormat( +// "[SCENE PRESENCE ANIMATOR]: Determined animation {0} for {1} in UpdateMovementAnimations()", +// CurrentMovementAnimation, m_scenePresence.Name); - TrySetMovementAnimation(CurrentMovementAnimation); + // Only set it if it's actually changed, give a script + // a chance to stop a default animation + TrySetMovementAnimation(CurrentMovementAnimation); + } } } @@ -536,4 +542,4 @@ namespace OpenSim.Region.Framework.Scenes.Animation SendAnimPack(animIDs, sequenceNums, objectIDs); } } -} \ No newline at end of file +} -- cgit v1.1 From f0178a6a413e35a45efcb0f7f0eeffc0daed15fe Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 5 Oct 2012 01:12:56 +0100 Subject: refactor: Move OpenSim.Framework.PacketPool to OpenSim.Region.Clientstack.Linden.UDP This is to allow it to use OpenSim.Framework.Monitoring in the future. This is also a better location since the packet pool is linden udp specific --- .../Region/ClientStack/Linden/UDP/PacketPool.cs | 249 +++++++++++++++++++++ 1 file changed, 249 insertions(+) create mode 100644 OpenSim/Region/ClientStack/Linden/UDP/PacketPool.cs (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/PacketPool.cs b/OpenSim/Region/ClientStack/Linden/UDP/PacketPool.cs new file mode 100644 index 0000000..fc9406b --- /dev/null +++ b/OpenSim/Region/ClientStack/Linden/UDP/PacketPool.cs @@ -0,0 +1,249 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections.Generic; +using System.Reflection; +using OpenMetaverse; +using OpenMetaverse.Packets; +using log4net; + +namespace OpenSim.Region.ClientStack.LindenUDP +{ + public sealed class PacketPool + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + private static readonly PacketPool instance = new PacketPool(); + + private bool packetPoolEnabled = true; + private bool dataBlockPoolEnabled = true; + + /// + /// Pool of packets available for reuse. + /// + private readonly Dictionary> pool = new Dictionary>(); + + private static Dictionary> DataBlocks = + new Dictionary>(); + + static PacketPool() + { + } + + public static PacketPool Instance + { + get { return instance; } + } + + public bool RecyclePackets + { + set { packetPoolEnabled = value; } + get { return packetPoolEnabled; } + } + + public bool RecycleDataBlocks + { + set { dataBlockPoolEnabled = value; } + get { return dataBlockPoolEnabled; } + } + + public Packet GetPacket(PacketType type) + { + Packet packet; + + if (!packetPoolEnabled) + return Packet.BuildPacket(type); + + lock (pool) + { + if (!pool.ContainsKey(type) || pool[type] == null || (pool[type]).Count == 0) + { + // Creating a new packet if we cannot reuse an old package + packet = Packet.BuildPacket(type); + } + else + { + // Recycle old packages + packet = (pool[type]).Pop(); + } + } + + return packet; + } + + // private byte[] decoded_header = new byte[10]; + private static PacketType GetType(byte[] bytes) + { + byte[] decoded_header = new byte[10 + 8]; + ushort id; + PacketFrequency freq; + + if ((bytes[0] & Helpers.MSG_ZEROCODED) != 0) + { + Helpers.ZeroDecode(bytes, 16, decoded_header); + } + else + { + Buffer.BlockCopy(bytes, 0, decoded_header, 0, 10); + } + + if (decoded_header[6] == 0xFF) + { + if (decoded_header[7] == 0xFF) + { + id = (ushort) ((decoded_header[8] << 8) + decoded_header[9]); + freq = PacketFrequency.Low; + } + else + { + id = decoded_header[7]; + freq = PacketFrequency.Medium; + } + } + else + { + id = decoded_header[6]; + freq = PacketFrequency.High; + } + + return Packet.GetType(id, freq); + } + + public Packet GetPacket(byte[] bytes, ref int packetEnd, byte[] zeroBuffer) + { + PacketType type = GetType(bytes); + + Array.Clear(zeroBuffer, 0, zeroBuffer.Length); + + int i = 0; + Packet packet = GetPacket(type); + if (packet == null) + m_log.WarnFormat("[PACKETPOOL]: Failed to get packet of type {0}", type); + else + packet.FromBytes(bytes, ref i, ref packetEnd, zeroBuffer); + + return packet; + } + + /// + /// Return a packet to the packet pool + /// + /// + public void ReturnPacket(Packet packet) + { + if (dataBlockPoolEnabled) + { + switch (packet.Type) + { + case PacketType.ObjectUpdate: + ObjectUpdatePacket oup = (ObjectUpdatePacket)packet; + + foreach (ObjectUpdatePacket.ObjectDataBlock oupod in oup.ObjectData) + ReturnDataBlock(oupod); + + oup.ObjectData = null; + break; + + case PacketType.ImprovedTerseObjectUpdate: + ImprovedTerseObjectUpdatePacket itoup = (ImprovedTerseObjectUpdatePacket)packet; + + foreach (ImprovedTerseObjectUpdatePacket.ObjectDataBlock itoupod in itoup.ObjectData) + ReturnDataBlock(itoupod); + + itoup.ObjectData = null; + break; + } + } + + if (packetPoolEnabled) + { + switch (packet.Type) + { + // List pooling packets here + case PacketType.PacketAck: + case PacketType.ObjectUpdate: + case PacketType.ImprovedTerseObjectUpdate: + lock (pool) + { + PacketType type = packet.Type; + + if (!pool.ContainsKey(type)) + { + pool[type] = new Stack(); + } + + if ((pool[type]).Count < 50) + { + (pool[type]).Push(packet); + } + } + break; + + // Other packets wont pool + default: + return; + } + } + } + + public static T GetDataBlock() where T: new() + { + lock (DataBlocks) + { + Stack s; + + if (DataBlocks.TryGetValue(typeof(T), out s)) + { + if (s.Count > 0) + return (T)s.Pop(); + } + else + { + DataBlocks[typeof(T)] = new Stack(); + } + + return new T(); + } + } + + public static void ReturnDataBlock(T block) where T: new() + { + if (block == null) + return; + + lock (DataBlocks) + { + if (!DataBlocks.ContainsKey(typeof(T))) + DataBlocks[typeof(T)] = new Stack(); + + if (DataBlocks[typeof(T)].Count < 50) + DataBlocks[typeof(T)].Push(block); + } + } + } +} \ No newline at end of file -- cgit v1.1 From 7c7cdf3431c1c8ee1575779f96980ac1d0de6be8 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 5 Oct 2012 01:43:29 +0100 Subject: Read PacketPool config in LLUDPServer with other config params rather than in Scene. This is to resolve previous build break. This unnecessarily but harmlessly reads and sets the parameter multiple times - scene was doing the same thing. --- OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs index 55780d6..d11fcbf 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs @@ -222,6 +222,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP m_pausedAckTimeout = 1000 * 300; // 5 minutes } + // FIXME: This actually only needs to be done once since the PacketPool is shared across all servers. + // However, there is no harm in temporarily doing it multiple times. + IConfig packetConfig = configSource.Configs["PacketPool"]; + if (packetConfig != null) + { + PacketPool.Instance.RecyclePackets = packetConfig.GetBoolean("RecyclePackets", true); + PacketPool.Instance.RecycleDataBlocks = packetConfig.GetBoolean("RecycleDataBlocks", true); + } + #region BinaryStats config = configSource.Configs["Statistics.Binary"]; m_shouldCollectStats = false; -- cgit v1.1 From 03136df1a7f858482ef755d342a33e5b6cfa6ae7 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 5 Oct 2012 01:45:49 +0100 Subject: Forgot to actually remove the packetpool set code from scene. --- OpenSim/Region/Framework/Scenes/Scene.cs | 7 ------- 1 file changed, 7 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 0a4aa4a..e6b8c16 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -801,13 +801,6 @@ namespace OpenSim.Region.Framework.Scenes SpawnPointRouting = startupConfig.GetString("SpawnPointRouting", "closest"); TelehubAllowLandmarks = startupConfig.GetBoolean("TelehubAllowLandmark", false); - IConfig packetConfig = m_config.Configs["PacketPool"]; - if (packetConfig != null) - { - PacketPool.Instance.RecyclePackets = packetConfig.GetBoolean("RecyclePackets", true); - PacketPool.Instance.RecycleDataBlocks = packetConfig.GetBoolean("RecycleDataBlocks", true); - } - m_strictAccessControl = startupConfig.GetBoolean("StrictAccessControl", m_strictAccessControl); m_generateMaptiles = startupConfig.GetBoolean("GenerateMaptiles", true); -- cgit v1.1 From 046113c137db67f1ded44e0093762c4805283b12 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 5 Oct 2012 01:46:28 +0100 Subject: Print number of objects found with "show object name" and "show part name" simulator console commands --- .../World/Objects/Commands/ObjectCommandsModule.cs | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs b/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs index 09f6758..e96dc3e 100644 --- a/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs +++ b/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs @@ -215,12 +215,6 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands m_scene.ForEachSOG(searchAction); - if (sceneObjects.Count == 0) - { - m_console.OutputFormat("No objects with name {0} found in {1}", name, m_scene.RegionInfo.RegionName); - return; - } - StringBuilder sb = new StringBuilder(); foreach (SceneObjectGroup so in sceneObjects) @@ -229,6 +223,8 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands sb.Append("\n"); } + sb.AppendFormat("{0} objects found in {1}\n", sceneObjects.Count, m_scene.Name); + m_console.OutputFormat(sb.ToString()); } @@ -298,12 +294,6 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands m_scene.ForEachSOG(searchAction); - if (parts.Count == 0) - { - m_console.OutputFormat("No parts with name {0} found in {1}", name, m_scene.RegionInfo.RegionName); - return; - } - StringBuilder sb = new StringBuilder(); foreach (SceneObjectPart part in parts) @@ -312,6 +302,8 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands sb.Append("\n"); } + sb.AppendFormat("{0} parts found in {1}\n", parts.Count, m_scene.Name); + m_console.OutputFormat(sb.ToString()); } -- cgit v1.1 From d87813a194359b648dc62965d29ae3a10b91c2bb Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 5 Oct 2012 02:02:19 +0100 Subject: Finally fix build break by allowing UserManagementModule (which constructs a packet directly) to reference OpenSim.Region.ClientStack.LindenUDP. This time I actually properly did a clean build --- .../Region/CoreModules/Framework/UserManagement/UserManagementModule.cs | 1 + 1 file changed, 1 insertion(+) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs b/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs index 36c84c7..b4811da 100644 --- a/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs +++ b/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs @@ -31,6 +31,7 @@ using System.Reflection; using OpenSim.Framework; using OpenSim.Framework.Console; +using OpenSim.Region.ClientStack.LindenUDP; using OpenSim.Region.Framework; using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Scenes; -- cgit v1.1 From 8cd1dc8d6097d4a5fd1965f9dc2f9f98489f8220 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 5 Oct 2012 02:07:28 +0100 Subject: minor: Add missing license information from the top of IUserManagement --- .../Region/Framework/Interfaces/IUserManagement.cs | 29 +++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Framework/Interfaces/IUserManagement.cs b/OpenSim/Region/Framework/Interfaces/IUserManagement.cs index 24cd069..f8088c3 100644 --- a/OpenSim/Region/Framework/Interfaces/IUserManagement.cs +++ b/OpenSim/Region/Framework/Interfaces/IUserManagement.cs @@ -1,4 +1,31 @@ -using System; +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; using System.Collections.Generic; using OpenMetaverse; -- cgit v1.1 From 130768b16a35e307389e88d902f6e3a785dfb8ee Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 5 Oct 2012 03:52:42 +0100 Subject: Add "show object pos to " command to simulator console. This allows you to display details of all objects in a given bounding box. Values parts of the co-ord can be left out as appropriate (e.g. to get all objects between the ground and z=30. See "help show object pos" for more details. --- .../World/Objects/Commands/ObjectCommandsModule.cs | 67 ++++++++++++++++++++++ 1 file changed, 67 insertions(+) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs b/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs index e96dc3e..5ecf5a1 100644 --- a/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs +++ b/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs @@ -126,6 +126,25 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands m_console.Commands.AddCommand( "Objects", false, + "show object pos", + "show object pos to ", + "Show details of scene objects within the given area.", + "Each component of the coord is comma separated. There must be no spaces between the commas.\n" + + "If you don't care about the z component you can simply omit it.\n" + + "If you don't care about the x or y components then you can leave them blank (though a comma is still required)\n" + + "If you want to specify the maxmimum value of a component then you can use ~ instead of a number\n" + + "If you want to specify the minimum value of a component then you can use -~ instead of a number\n" + + "e.g.\n" + + "show object pos 20,20,20 to 40,40,40\n" + + "show object pos 20,20 to 40,40\n" + + "show object pos ,20,20 to ,40,40\n" + + "show object pos ,,30 to ,,~\n" + + "show object pos ,,-~ to ,,30\n", + HandleShowObjectByPos); + + m_console.Commands.AddCommand( + "Objects", + false, "show part uuid", "show part uuid ", "Show details of a scene object parts with the given UUID", HandleShowPartByUuid); @@ -228,6 +247,54 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands m_console.OutputFormat(sb.ToString()); } + private void HandleShowObjectByPos(string module, string[] cmdparams) + { + if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene)) + return; + + if (cmdparams.Length < 5) + { + m_console.OutputFormat("Usage: show object pos to "); + return; + } + + string rawConsoleStartVector = cmdparams[3]; + Vector3 startVector; + + if (!ConsoleUtil.TryParseConsoleMinVector(rawConsoleStartVector, out startVector)) + { + m_console.OutputFormat("Error: Start vector {0} does not have a valid format", rawConsoleStartVector); + return; + } + + string rawConsoleEndVector = cmdparams[5]; + Vector3 endVector; + + if (!ConsoleUtil.TryParseConsoleMaxVector(rawConsoleEndVector, out endVector)) + { + m_console.OutputFormat("Error: End vector {0} does not have a valid format", rawConsoleEndVector); + return; + } + + List sceneObjects = new List(); + Action searchAction + = so => { if (Util.IsInsideBox(so.AbsolutePosition, startVector, endVector)) { sceneObjects.Add(so); }}; + + m_scene.ForEachSOG(searchAction); + + StringBuilder sb = new StringBuilder(); + + foreach (SceneObjectGroup so in sceneObjects) + { + AddSceneObjectReport(sb, so); + sb.Append("\n"); + } + + sb.AppendFormat("{0} objects found in {1}\n", sceneObjects.Count, m_scene.Name); + + m_console.OutputFormat(sb.ToString()); + } + private void HandleShowPartByUuid(string module, string[] cmd) { if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene)) -- cgit v1.1 From 16feed456adbcf43a9ec797d1a499599aadda6b9 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 5 Oct 2012 04:16:38 +0100 Subject: refactor: eliminate some now duplicate code in ObjectCommandsModule --- .../World/Objects/Commands/ObjectCommandsModule.cs | 59 +++++++++------------- 1 file changed, 25 insertions(+), 34 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs b/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs index 5ecf5a1..fbc64e3 100644 --- a/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs +++ b/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs @@ -139,7 +139,7 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands + "show object pos 20,20 to 40,40\n" + "show object pos ,20,20 to ,40,40\n" + "show object pos ,,30 to ,,~\n" - + "show object pos ,,-~ to ,,30\n", + + "show object pos ,,-~ to ,,30", HandleShowObjectByPos); m_console.Commands.AddCommand( @@ -169,6 +169,23 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands // m_log.DebugFormat("[OBJECTS COMMANDS MODULE]: REGION {0} LOADED", scene.RegionInfo.RegionName); } + private void OutputSogsToConsole(Predicate searchPredicate) + { + List sceneObjects = m_scene.GetSceneObjectGroups().FindAll(searchPredicate); + + StringBuilder sb = new StringBuilder(); + + foreach (SceneObjectGroup so in sceneObjects) + { + AddSceneObjectReport(sb, so); + sb.Append("\n"); + } + + sb.AppendFormat("{0} object(s) found in {1}\n", sceneObjects.Count, m_scene.Name); + + m_console.OutputFormat(sb.ToString()); + } + private void HandleShowObjectByUuid(string module, string[] cmd) { if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene)) @@ -219,32 +236,19 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands string name = mainParams[3]; - List sceneObjects = new List(); - Action searchAction; + Predicate searchPredicate; if (useRegex) { Regex nameRegex = new Regex(name); - searchAction = so => { if (nameRegex.IsMatch(so.Name)) { sceneObjects.Add(so); }}; + searchPredicate = so => nameRegex.IsMatch(so.Name); } else { - searchAction = so => { if (so.Name == name) { sceneObjects.Add(so); }}; + searchPredicate = so => so.Name == name; } - m_scene.ForEachSOG(searchAction); - - StringBuilder sb = new StringBuilder(); - - foreach (SceneObjectGroup so in sceneObjects) - { - AddSceneObjectReport(sb, so); - sb.Append("\n"); - } - - sb.AppendFormat("{0} objects found in {1}\n", sceneObjects.Count, m_scene.Name); - - m_console.OutputFormat(sb.ToString()); + OutputSogsToConsole(searchPredicate); } private void HandleShowObjectByPos(string module, string[] cmdparams) @@ -276,23 +280,10 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands return; } - List sceneObjects = new List(); - Action searchAction - = so => { if (Util.IsInsideBox(so.AbsolutePosition, startVector, endVector)) { sceneObjects.Add(so); }}; - - m_scene.ForEachSOG(searchAction); + Predicate searchPredicate + = so => Util.IsInsideBox(so.AbsolutePosition, startVector, endVector); - StringBuilder sb = new StringBuilder(); - - foreach (SceneObjectGroup so in sceneObjects) - { - AddSceneObjectReport(sb, so); - sb.Append("\n"); - } - - sb.AppendFormat("{0} objects found in {1}\n", sceneObjects.Count, m_scene.Name); - - m_console.OutputFormat(sb.ToString()); + OutputSogsToConsole(searchPredicate); } private void HandleShowPartByUuid(string module, string[] cmd) -- cgit v1.1 From 22f6fa49e3751ce0bf80167e7d4467681faacf89 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 5 Oct 2012 04:22:08 +0100 Subject: Add "show part pos" console command to match "show object pos" --- .../World/Objects/Commands/ObjectCommandsModule.cs | 72 ++++++++++++++++++++++ 1 file changed, 72 insertions(+) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs b/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs index fbc64e3..0c9295b 100644 --- a/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs +++ b/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs @@ -157,6 +157,25 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands "Show details of scene object parts with the given name.", "If --regex is specified then the name is treatead as a regular expression", HandleShowPartByName); + + m_console.Commands.AddCommand( + "Objects", + false, + "show part pos", + "show part pos to ", + "Show details of scene object parts within the given area.", + "Each component of the coord is comma separated. There must be no spaces between the commas.\n" + + "If you don't care about the z component you can simply omit it.\n" + + "If you don't care about the x or y components then you can leave them blank (though a comma is still required)\n" + + "If you want to specify the maxmimum value of a component then you can use ~ instead of a number\n" + + "If you want to specify the minimum value of a component then you can use -~ instead of a number\n" + + "e.g.\n" + + "show object pos 20,20,20 to 40,40,40\n" + + "show object pos 20,20 to 40,40\n" + + "show object pos ,20,20 to ,40,40\n" + + "show object pos ,,30 to ,,~\n" + + "show object pos ,,-~ to ,,30", + HandleShowPartByPos); } public void RemoveRegion(Scene scene) @@ -318,6 +337,59 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands m_console.OutputFormat(sb.ToString()); } + private void HandleShowPartByPos(string module, string[] cmdparams) + { + if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene)) + return; + + if (cmdparams.Length < 5) + { + m_console.OutputFormat("Usage: show part pos to "); + return; + } + + string rawConsoleStartVector = cmdparams[3]; + Vector3 startVector; + + if (!ConsoleUtil.TryParseConsoleMinVector(rawConsoleStartVector, out startVector)) + { + m_console.OutputFormat("Error: Start vector {0} does not have a valid format", rawConsoleStartVector); + return; + } + + string rawConsoleEndVector = cmdparams[5]; + Vector3 endVector; + + if (!ConsoleUtil.TryParseConsoleMaxVector(rawConsoleEndVector, out endVector)) + { + m_console.OutputFormat("Error: End vector {0} does not have a valid format", rawConsoleEndVector); + return; + } + + Predicate searchPredicate + = so => Util.IsInsideBox(so.AbsolutePosition, startVector, endVector); + + List parts = new List(); + + Action searchAction + = so + => so.ForEachPart(sop => { if (Util.IsInsideBox(so.AbsolutePosition, startVector, endVector)) { parts.Add(sop); }}); + + m_scene.ForEachSOG(searchAction); + + StringBuilder sb = new StringBuilder(); + + foreach (SceneObjectPart part in parts) + { + AddScenePartReport(sb, part); + sb.Append("\n"); + } + + sb.AppendFormat("{0} parts found in {1}\n", parts.Count, m_scene.Name); + + m_console.OutputFormat(sb.ToString()); + } + private void HandleShowPartByName(string module, string[] cmdparams) { if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene)) -- cgit v1.1 From 1fb53e7103fccba7a2ee440e7e7055c379d93803 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 5 Oct 2012 04:31:43 +0100 Subject: Fix bug in implementation of "show part pos" that would not filter probably. Also refactors more of ObjectCommandsModule to remove duplicate code --- .../World/Objects/Commands/ObjectCommandsModule.cs | 65 +++++++++------------- 1 file changed, 25 insertions(+), 40 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs b/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs index 0c9295b..6e39e9a 100644 --- a/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs +++ b/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs @@ -205,6 +205,26 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands m_console.OutputFormat(sb.ToString()); } + private void OutputSopsToConsole(Predicate searchPredicate) + { + List sceneObjects = m_scene.GetSceneObjectGroups(); + List parts = new List(); + + sceneObjects.ForEach(so => parts.AddRange(Array.FindAll(so.Parts, searchPredicate))); + + StringBuilder sb = new StringBuilder(); + + foreach (SceneObjectPart part in parts) + { + AddScenePartReport(sb, part); + sb.Append("\n"); + } + + sb.AppendFormat("{0} parts found in {1}\n", parts.Count, m_scene.Name); + + m_console.OutputFormat(sb.ToString()); + } + private void HandleShowObjectByUuid(string module, string[] cmd) { if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene)) @@ -366,28 +386,7 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands return; } - Predicate searchPredicate - = so => Util.IsInsideBox(so.AbsolutePosition, startVector, endVector); - - List parts = new List(); - - Action searchAction - = so - => so.ForEachPart(sop => { if (Util.IsInsideBox(so.AbsolutePosition, startVector, endVector)) { parts.Add(sop); }}); - - m_scene.ForEachSOG(searchAction); - - StringBuilder sb = new StringBuilder(); - - foreach (SceneObjectPart part in parts) - { - AddScenePartReport(sb, part); - sb.Append("\n"); - } - - sb.AppendFormat("{0} parts found in {1}\n", parts.Count, m_scene.Name); - - m_console.OutputFormat(sb.ToString()); + OutputSopsToConsole(sop => Util.IsInsideBox(sop.AbsolutePosition, startVector, endVector)); } private void HandleShowPartByName(string module, string[] cmdparams) @@ -408,33 +407,19 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands string name = mainParams[3]; - List parts = new List(); - - Action searchAction; + Predicate searchPredicate; if (useRegex) { Regex nameRegex = new Regex(name); - searchAction = so => so.ForEachPart(sop => { if (nameRegex.IsMatch(sop.Name)) { parts.Add(sop); } }); + searchPredicate = sop => nameRegex.IsMatch(sop.Name); } else { - searchAction = so => so.ForEachPart(sop => { if (sop.Name == name) { parts.Add(sop); } }); + searchPredicate = sop => sop.Name == name; } - m_scene.ForEachSOG(searchAction); - - StringBuilder sb = new StringBuilder(); - - foreach (SceneObjectPart part in parts) - { - AddScenePartReport(sb, part); - sb.Append("\n"); - } - - sb.AppendFormat("{0} parts found in {1}\n", parts.Count, m_scene.Name); - - m_console.OutputFormat(sb.ToString()); + OutputSopsToConsole(searchPredicate); } private StringBuilder AddSceneObjectReport(StringBuilder sb, SceneObjectGroup so) -- cgit v1.1 From 6f220a867981db8e3357484feff1fe1977170561 Mon Sep 17 00:00:00 2001 From: Dan Lake Date: Fri, 5 Oct 2012 17:30:27 -0700 Subject: Trigger ObjectAddedToScene when loading objects from oarfile. Already triggers when creating, duplicating or loading from database, incoming attachments, etc --- OpenSim/Region/Framework/Scenes/Scene.cs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index e6b8c16..671feda 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -2139,7 +2139,14 @@ namespace OpenSim.Region.Framework.Scenes public bool AddRestoredSceneObject( SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates) { - return m_sceneGraph.AddRestoredSceneObject(sceneObject, attachToBackup, alreadyPersisted, sendClientUpdates); + if (m_sceneGraph.AddRestoredSceneObject(sceneObject, attachToBackup, alreadyPersisted, sendClientUpdates)) + { + EventManager.TriggerObjectAddedToScene(sceneObject); + return true; + } + + return false; + } /// -- cgit v1.1 From 91ca3117cb35444e6b0e4300468959ed43c048c3 Mon Sep 17 00:00:00 2001 From: Dan Lake Date: Fri, 5 Oct 2012 17:32:07 -0700 Subject: Add bool to TriggerSceneObjectPartUpdated where full = true indicates a full update. There should be a better way to indicate which properties have changed that is non LLUDP-centric --- OpenSim/Region/Framework/Scenes/EventManager.cs | 6 +++--- OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Framework/Scenes/EventManager.cs b/OpenSim/Region/Framework/Scenes/EventManager.cs index e25fa94..a8ff218 100644 --- a/OpenSim/Region/Framework/Scenes/EventManager.cs +++ b/OpenSim/Region/Framework/Scenes/EventManager.cs @@ -913,7 +913,7 @@ namespace OpenSim.Region.Framework.Scenes public event SceneObjectPartCopyDelegate OnSceneObjectPartCopy; public delegate void SceneObjectPartCopyDelegate(SceneObjectPart copy, SceneObjectPart original, bool userExposed); - public delegate void SceneObjectPartUpdated(SceneObjectPart sop); + public delegate void SceneObjectPartUpdated(SceneObjectPart sop, bool full); public event SceneObjectPartUpdated OnSceneObjectPartUpdated; public delegate void ScenePresenceUpdated(ScenePresence sp); @@ -2837,7 +2837,7 @@ namespace OpenSim.Region.Framework.Scenes } } - public void TriggerSceneObjectPartUpdated(SceneObjectPart sop) + public void TriggerSceneObjectPartUpdated(SceneObjectPart sop, bool full) { SceneObjectPartUpdated handler = OnSceneObjectPartUpdated; if (handler != null) @@ -2846,7 +2846,7 @@ namespace OpenSim.Region.Framework.Scenes { try { - d(sop); + d(sop, full); } catch (Exception e) { diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index 3f10b34..199526e 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -2465,7 +2465,7 @@ namespace OpenSim.Region.Framework.Scenes // UUID, Name, TimeStampFull); if (ParentGroup.Scene != null) - ParentGroup.Scene.EventManager.TriggerSceneObjectPartUpdated(this); + ParentGroup.Scene.EventManager.TriggerSceneObjectPartUpdated(this, true); } /// @@ -2499,7 +2499,7 @@ namespace OpenSim.Region.Framework.Scenes } if (ParentGroup.Scene != null) - ParentGroup.Scene.EventManager.TriggerSceneObjectPartUpdated(this); + ParentGroup.Scene.EventManager.TriggerSceneObjectPartUpdated(this, false); } public void ScriptSetPhysicsStatus(bool UsePhysics) -- cgit v1.1 From 16c9c1dff7bbf299efddd44e4f9aeeb7db38fff6 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Sat, 6 Oct 2012 02:34:49 +0100 Subject: On receiving TaskInventoryAccepted with a destination folder in the binary bucket slot for RLV, notify the viewer about inventory folder updates. The viewer would not see the folder move without this, either on accept or decline. This commit also updates the TaskInventoryOffered message to better conform with the data LL uses Changes are, agentID is prim owner rather than prim id, agent name is now simply object name rather than name with owner detail, message is just folder name in single quotes, message is not timestamped. However, folder is not renamed "still #RLV/~". Long term solution is probably not to do these operations server-side. Notes will be added to http://opensimulator.org/mantis/view.php?id=6311 --- .../Region/ClientStack/Linden/UDP/LLClientView.cs | 3 +- .../Avatar/Friends/CallingCardModule.cs | 2 +- .../Inventory/Transfer/InventoryTransferModule.cs | 42 ++++++++++++++++++++++ .../Region/CoreModules/Avatar/Lure/HGLureModule.cs | 2 +- .../Region/CoreModules/Avatar/Lure/LureModule.cs | 2 +- .../EntityTransfer/EntityTransferModule.cs | 22 +++++++++--- OpenSim/Region/Framework/Scenes/Scene.Inventory.cs | 2 +- .../Region/OptionalModules/World/NPC/NPCAvatar.cs | 2 +- .../Shared/Api/Implementation/LSL_Api.cs | 19 +++++----- 9 files changed, 76 insertions(+), 20 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index d05ffea..0869bd5 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -5862,7 +5862,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP msgpack.MessageBlock.ID, msgpack.MessageBlock.Offline != 0 ? true : false, msgpack.MessageBlock.Position, - msgpack.MessageBlock.BinaryBucket); + msgpack.MessageBlock.BinaryBucket, + true); handlerInstantMessage(this, im); } diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/CallingCardModule.cs b/OpenSim/Region/CoreModules/Avatar/Friends/CallingCardModule.cs index d942e87..5ec0ea9 100644 --- a/OpenSim/Region/CoreModules/Avatar/Friends/CallingCardModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Friends/CallingCardModule.cs @@ -141,7 +141,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends client.FirstName+" "+client.LastName, destID, (byte)211, false, String.Empty, - transactionID, false, new Vector3(), new byte[0]), + transactionID, false, new Vector3(), new byte[0], true), delegate(bool success) {} ); } } diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs index 91eda19..33b4839 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs @@ -297,6 +297,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer }); } } + + // XXX: This code was placed here to try and accomdate RLV which moves given folders named #RLV/~ + // to a folder called name in #RLV. However, this approach may not be ultimately correct - from analysis + // of Firestorm 4.2.2 on sending an InventoryOffered instead of TaskInventoryOffered (as was previously + // done), the viewer itself would appear to move and rename the folder, rather than the simulator doing it here. else if (im.dialog == (byte) InstantMessageDialog.TaskInventoryAccepted) { UUID destinationFolderID = UUID.Zero; @@ -308,6 +313,16 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer if (destinationFolderID != UUID.Zero) { + InventoryFolderBase destinationFolder = new InventoryFolderBase(destinationFolderID, client.AgentId); + if (destinationFolder == null) + { + m_log.WarnFormat( + "[INVENTORY TRANSFER]: TaskInventoryAccepted message from {0} in {1} specified folder {2} which does not exist", + client.Name, scene.Name, destinationFolderID); + + return; + } + IInventoryService invService = scene.InventoryService; UUID inventoryID = new UUID(im.imSessionID); // The inventory item/folder, back from it's trip @@ -315,9 +330,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer InventoryItemBase item = new InventoryItemBase(inventoryID, client.AgentId); item = invService.GetItem(item); InventoryFolderBase folder = null; + UUID? previousParentFolderID = null; if (item != null) // It's an item { + previousParentFolderID = item.Folder; item.Folder = destinationFolderID; invService.DeleteItems(item.Owner, new List() { item.ID }); @@ -330,10 +347,22 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer if (folder != null) // It's a folder { + previousParentFolderID = folder.ParentID; folder.ParentID = destinationFolderID; invService.MoveFolder(folder); } } + + // Tell client about updates to original parent and new parent (this should probably be factored with existing move item/folder code). + if (previousParentFolderID != null) + { + InventoryFolderBase previousParentFolder + = new InventoryFolderBase((UUID)previousParentFolderID, client.AgentId); + previousParentFolder = invService.GetFolder(previousParentFolder); + scene.SendInventoryUpdate(client, previousParentFolder, true, true); + + scene.SendInventoryUpdate(client, destinationFolder, true, true); + } } } else if ( @@ -354,9 +383,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer InventoryItemBase item = new InventoryItemBase(inventoryID, client.AgentId); item = invService.GetItem(item); InventoryFolderBase folder = null; + UUID? previousParentFolderID = null; if (item != null && trashFolder != null) { + previousParentFolderID = item.Folder; item.Folder = trashFolder.ID; // Diva comment: can't we just update this item??? @@ -372,6 +403,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer if (folder != null & trashFolder != null) { + previousParentFolderID = folder.ParentID; folder.ParentID = trashFolder.ID; invService.MoveFolder(folder); } @@ -391,6 +423,16 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer client.SendAgentAlertMessage("Unable to delete "+ "received inventory" + reason, false); } + // Tell client about updates to original parent and new parent (this should probably be factored with existing move item/folder code). + else if (previousParentFolderID != null) + { + InventoryFolderBase previousParentFolder + = new InventoryFolderBase((UUID)previousParentFolderID, client.AgentId); + previousParentFolder = invService.GetFolder(previousParentFolder); + scene.SendInventoryUpdate(client, previousParentFolder, true, true); + + scene.SendInventoryUpdate(client, trashFolder, true, true); + } ScenePresence user = scene.GetScenePresence(new UUID(im.toAgentID)); diff --git a/OpenSim/Region/CoreModules/Avatar/Lure/HGLureModule.cs b/OpenSim/Region/CoreModules/Avatar/Lure/HGLureModule.cs index 92cf9d1..9c369f6 100644 --- a/OpenSim/Region/CoreModules/Avatar/Lure/HGLureModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Lure/HGLureModule.cs @@ -186,7 +186,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Lure client.FirstName+" "+client.LastName, targetid, (byte)InstantMessageDialog.RequestTeleport, false, message, sessionID, false, presence.AbsolutePosition, - new Byte[0]); + new Byte[0], true); m.RegionID = client.Scene.RegionInfo.RegionID.Guid; m_log.DebugFormat("[HG LURE MODULE]: RequestTeleport sessionID={0}, regionID={1}, message={2}", m.imSessionID, m.RegionID, m.message); diff --git a/OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs b/OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs index 2d4cffd..6ce9556 100644 --- a/OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs @@ -169,7 +169,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Lure client.FirstName+" "+client.LastName, targetid, (byte)InstantMessageDialog.RequestTeleport, false, message, dest, false, presence.AbsolutePosition, - new Byte[0]); + new Byte[0], true); if (m_TransferModule != null) { diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs index b51570f..617a350 100644 --- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs +++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs @@ -1068,6 +1068,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer Scene initiatingScene) { Thread.Sleep(10000); + IMessageTransferModule im = initiatingScene.RequestModuleInterface(); if (im != null) { @@ -1080,11 +1081,22 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer (uint)(int)position.X, (uint)(int)position.Y, (uint)(int)position.Z); - GridInstantMessage m = new GridInstantMessage(initiatingScene, UUID.Zero, - "Region", agent.UUID, - (byte)InstantMessageDialog.GodLikeRequestTeleport, false, - "", gotoLocation, false, new Vector3(127, 0, 0), - new Byte[0]); + + GridInstantMessage m + = new GridInstantMessage( + initiatingScene, + UUID.Zero, + "Region", + agent.UUID, + (byte)InstantMessageDialog.GodLikeRequestTeleport, + false, + "", + gotoLocation, + false, + new Vector3(127, 0, 0), + new Byte[0], + false); + im.SendInstantMessage(m, delegate(bool success) { m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Client Initiating Teleport sending IM success = {0}", success); diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs index 3b59dc4..b23ddb4 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs @@ -1424,7 +1424,7 @@ namespace OpenSim.Region.Framework.Scenes return newFolderID; } - private void SendInventoryUpdate(IClientAPI client, InventoryFolderBase folder, bool fetchFolders, bool fetchItems) + public void SendInventoryUpdate(IClientAPI client, InventoryFolderBase folder, bool fetchFolders, bool fetchItems) { if (folder == null) return; diff --git a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs index a8e4d90..ffd4222 100644 --- a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs +++ b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs @@ -148,7 +148,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC OnInstantMessage(this, new GridInstantMessage(m_scene, m_uuid, m_firstname + " " + m_lastname, target, 0, false, message, - UUID.Zero, false, Position, new byte[0])); + UUID.Zero, false, Position, new byte[0], true)); } public void SendAgentOffline(UUID[] agentIDs) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 7fa6f05..7620df3 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -3978,7 +3978,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api World.RegionInfo.RegionName+" "+ m_host.AbsolutePosition.ToString(), agentItem.ID, true, m_host.AbsolutePosition, - bucket); + bucket, true); // TODO: May actually send no timestamp m_TransferModule.SendInstantMessage(msg, delegate(bool success) {}); } @@ -6452,16 +6452,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (m_TransferModule != null) { byte[] bucket = new byte[] { (byte)AssetType.Folder }; - + + Vector3 pos = m_host.AbsolutePosition; + GridInstantMessage msg = new GridInstantMessage(World, - m_host.UUID, m_host.Name + ", an object owned by " + - resolveName(m_host.OwnerID) + ",", destID, + m_host.OwnerID, m_host.Name, destID, (byte)InstantMessageDialog.TaskInventoryOffered, - false, category + "\n" + m_host.Name + " is located at " + - World.RegionInfo.RegionName + " " + - m_host.AbsolutePosition.ToString(), - folderID, true, m_host.AbsolutePosition, - bucket); + false, string.Format("'{0}'"), +// We won't go so far as to add a SLURL, but this is the format used by LL as of 2012-10-06 +// false, string.Format("'{0}' ( http://slurl.com/secondlife/{1}/{2}/{3}/{4} )", category, World.Name, (int)pos.X, (int)pos.Y, (int)pos.Z), + folderID, false, pos, + bucket, false); m_TransferModule.SendInstantMessage(msg, delegate(bool success) {}); } -- cgit v1.1 From 9de991301cfcb66721a5593dd9098fe84e090dec Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Sat, 6 Oct 2012 04:03:53 +0100 Subject: Make UserSessionID a class rather than a struct, so that later updates to value suceed (rather than having to pull the data out and reinsert back into the Dictionary). Fixes http://opensimulator.org/mantis/view.php?id=6338 --- OpenSim/Region/UserStatistics/WebStatsModule.cs | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/UserStatistics/WebStatsModule.cs b/OpenSim/Region/UserStatistics/WebStatsModule.cs index c11ea02..b1795db 100644 --- a/OpenSim/Region/UserStatistics/WebStatsModule.cs +++ b/OpenSim/Region/UserStatistics/WebStatsModule.cs @@ -319,6 +319,10 @@ namespace OpenSim.Region.UserStatistics private void OnMakeRootAgent(ScenePresence agent) { +// m_log.DebugFormat( +// "[WEB STATS MODULE]: Looking for session {0} for {1} in {2}", +// agent.ControllingClient.SessionId, agent.Name, agent.Scene.Name); + lock (m_sessions) { UserSessionID uid; @@ -427,7 +431,10 @@ namespace OpenSim.Region.UserStatistics m_log.WarnFormat("[WEB STATS MODULE]: no session for stat disclosure for agent {0}", agentID); return new UserSessionID(); } + uid = m_sessions[agentID]; + +// m_log.DebugFormat("[WEB STATS MODULE]: Got session {0} for {1}", uid.session_id, agentID); } else { @@ -499,6 +506,7 @@ namespace OpenSim.Region.UserStatistics usd.d_texture_kb = (float)downloads_map["texture_kbytes"].AsReal(); usd.d_world_kb = (float)downloads_map["workd_kbytes"].AsReal(); +// m_log.DebugFormat("[WEB STATS MODULE]: mmap[\"session_id\"] = [{0}]", mmap["session_id"].AsUUID()); usd.session_id = mmap["session_id"].AsUUID(); @@ -549,11 +557,18 @@ namespace OpenSim.Region.UserStatistics uid.session_data = usd; m_sessions[agentID] = uid; + +// m_log.DebugFormat( +// "[WEB STATS MODULE]: Parse data for {0} {1}, session {2}", uid.name_f, uid.name_l, uid.session_id); + return uid; } private void UpdateUserStats(UserSessionID uid, SqliteConnection db) { +// m_log.DebugFormat( +// "[WEB STATS MODULE]: Updating user stats for {0} {1}, session {2}", uid.name_f, uid.name_l, uid.session_id); + if (uid.session_id == UUID.Zero) return; @@ -740,7 +755,6 @@ VALUES s.min_ping = ArrayMin_f(__ping); s.max_ping = ArrayMax_f(__ping); s.mode_ping = ArrayMode_f(__ping); - } #region Statistics @@ -985,7 +999,7 @@ VALUES } #region structs - public struct UserSessionID + public class UserSessionID { public UUID session_id; public UUID region_id; -- cgit v1.1 From 13c4fd7271783d3e2c51da7b9509d08aeedf3131 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Sat, 6 Oct 2012 04:06:27 +0100 Subject: refactor: Rename UserSessioNID -> UserSession in WebStatsModule since this is what it actually represents --- OpenSim/Region/UserStatistics/WebStatsModule.cs | 40 ++++++++++++------------- 1 file changed, 20 insertions(+), 20 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/UserStatistics/WebStatsModule.cs b/OpenSim/Region/UserStatistics/WebStatsModule.cs index b1795db..625eba4 100644 --- a/OpenSim/Region/UserStatistics/WebStatsModule.cs +++ b/OpenSim/Region/UserStatistics/WebStatsModule.cs @@ -61,7 +61,7 @@ namespace OpenSim.Region.UserStatistics /// /// User statistics sessions keyed by agent ID /// - private Dictionary m_sessions = new Dictionary(); + private Dictionary m_sessions = new Dictionary(); private List m_scenes = new List(); private Dictionary reports = new Dictionary(); @@ -325,12 +325,12 @@ namespace OpenSim.Region.UserStatistics lock (m_sessions) { - UserSessionID uid; + UserSession uid; if (!m_sessions.ContainsKey(agent.UUID)) { UserSessionData usd = UserSessionUtil.newUserSessionData(); - uid = new UserSessionID(); + uid = new UserSession(); uid.name_f = agent.Firstname; uid.name_l = agent.Lastname; uid.session_data = usd; @@ -415,9 +415,9 @@ namespace OpenSim.Region.UserStatistics return String.Empty; } - private UserSessionID ParseViewerStats(string request, UUID agentID) + private UserSession ParseViewerStats(string request, UUID agentID) { - UserSessionID uid = new UserSessionID(); + UserSession uid = new UserSession(); UserSessionData usd; OSD message = OSDParser.DeserializeLLSDXml(request); OSDMap mmap; @@ -429,7 +429,7 @@ namespace OpenSim.Region.UserStatistics if (!m_sessions.ContainsKey(agentID)) { m_log.WarnFormat("[WEB STATS MODULE]: no session for stat disclosure for agent {0}", agentID); - return new UserSessionID(); + return new UserSession(); } uid = m_sessions[agentID]; @@ -440,14 +440,14 @@ namespace OpenSim.Region.UserStatistics { // parse through the beginning to locate the session if (message.Type != OSDType.Map) - return new UserSessionID(); + return new UserSession(); mmap = (OSDMap)message; { UUID sessionID = mmap["session_id"].AsUUID(); if (sessionID == UUID.Zero) - return new UserSessionID(); + return new UserSession(); // search through each session looking for the owner @@ -466,7 +466,7 @@ namespace OpenSim.Region.UserStatistics // can't find a session if (agentID == UUID.Zero) { - return new UserSessionID(); + return new UserSession(); } } } @@ -475,12 +475,12 @@ namespace OpenSim.Region.UserStatistics usd = uid.session_data; if (message.Type != OSDType.Map) - return new UserSessionID(); + return new UserSession(); mmap = (OSDMap)message; { if (mmap["agent"].Type != OSDType.Map) - return new UserSessionID(); + return new UserSession(); OSDMap agent_map = (OSDMap)mmap["agent"]; usd.agent_id = agentID; usd.name_f = uid.name_f; @@ -500,7 +500,7 @@ namespace OpenSim.Region.UserStatistics (float)agent_map["fps"].AsReal()); if (mmap["downloads"].Type != OSDType.Map) - return new UserSessionID(); + return new UserSession(); OSDMap downloads_map = (OSDMap)mmap["downloads"]; usd.d_object_kb = (float)downloads_map["object_kbytes"].AsReal(); usd.d_texture_kb = (float)downloads_map["texture_kbytes"].AsReal(); @@ -511,7 +511,7 @@ namespace OpenSim.Region.UserStatistics usd.session_id = mmap["session_id"].AsUUID(); if (mmap["system"].Type != OSDType.Map) - return new UserSessionID(); + return new UserSession(); OSDMap system_map = (OSDMap)mmap["system"]; usd.s_cpu = system_map["cpu"].AsString(); @@ -520,13 +520,13 @@ namespace OpenSim.Region.UserStatistics usd.s_ram = system_map["ram"].AsInteger(); if (mmap["stats"].Type != OSDType.Map) - return new UserSessionID(); + return new UserSession(); OSDMap stats_map = (OSDMap)mmap["stats"]; { if (stats_map["failures"].Type != OSDType.Map) - return new UserSessionID(); + return new UserSession(); OSDMap stats_failures = (OSDMap)stats_map["failures"]; usd.f_dropped = stats_failures["dropped"].AsInteger(); usd.f_failed_resends = stats_failures["failed_resends"].AsInteger(); @@ -535,18 +535,18 @@ namespace OpenSim.Region.UserStatistics usd.f_send_packet = stats_failures["send_packet"].AsInteger(); if (stats_map["net"].Type != OSDType.Map) - return new UserSessionID(); + return new UserSession(); OSDMap stats_net = (OSDMap)stats_map["net"]; { if (stats_net["in"].Type != OSDType.Map) - return new UserSessionID(); + return new UserSession(); OSDMap net_in = (OSDMap)stats_net["in"]; usd.n_in_kb = (float)net_in["kbytes"].AsReal(); usd.n_in_pk = net_in["packets"].AsInteger(); if (stats_net["out"].Type != OSDType.Map) - return new UserSessionID(); + return new UserSession(); OSDMap net_out = (OSDMap)stats_net["out"]; usd.n_out_kb = (float)net_out["kbytes"].AsReal(); @@ -564,7 +564,7 @@ namespace OpenSim.Region.UserStatistics return uid; } - private void UpdateUserStats(UserSessionID uid, SqliteConnection db) + private void UpdateUserStats(UserSession uid, SqliteConnection db) { // m_log.DebugFormat( // "[WEB STATS MODULE]: Updating user stats for {0} {1}, session {2}", uid.name_f, uid.name_l, uid.session_id); @@ -999,7 +999,7 @@ VALUES } #region structs - public class UserSessionID + public class UserSession { public UUID session_id; public UUID region_id; -- cgit v1.1 From 9be2d5c77da8c2fc6c953e26a8b1412642588eb2 Mon Sep 17 00:00:00 2001 From: Melanie Date: Sun, 7 Oct 2012 03:03:24 +0100 Subject: Fix merge issues --- OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs | 2 +- OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs | 4 ++-- OpenSim/Region/Framework/Scenes/Scene.cs | 7 ------- 3 files changed, 3 insertions(+), 10 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs b/OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs index 716cc69..82816d9 100644 --- a/OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs @@ -206,7 +206,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Gods transferModule.SendInstantMessage(new GridInstantMessage( m_scene, godID, "God", agentID, (byte)250, false, Utils.BytesToString(reason), UUID.Zero, true, - new Vector3(), new byte[] {(byte)kickflags}), + new Vector3(), new byte[] {(byte)kickflags}, true), delegate(bool success) {} ); } return; diff --git a/OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs b/OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs index a889984..1949459 100644 --- a/OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs @@ -173,7 +173,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Lure client.FirstName+" "+client.LastName, targetid, (byte)InstantMessageDialog.GodLikeRequestTeleport, false, message, dest, false, presence.AbsolutePosition, - new Byte[0]); + new Byte[0], true); } else { @@ -181,7 +181,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Lure client.FirstName+" "+client.LastName, targetid, (byte)InstantMessageDialog.RequestTeleport, false, message, dest, false, presence.AbsolutePosition, - new Byte[0]); + new Byte[0], true); } if (m_TransferModule != null) diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 6e3e436..8d112db 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -825,13 +825,6 @@ namespace OpenSim.Region.Framework.Scenes m_defaultScriptEngine = startupConfig.GetString("DefaultScriptEngine", "XEngine"); m_log.InfoFormat("[SCENE]: Default script engine {0}", m_defaultScriptEngine); - IConfig packetConfig = m_config.Configs["PacketPool"]; - if (packetConfig != null) - { - PacketPool.Instance.RecyclePackets = packetConfig.GetBoolean("RecyclePackets", true); - PacketPool.Instance.RecycleDataBlocks = packetConfig.GetBoolean("RecycleDataBlocks", true); - } - m_strictAccessControl = startupConfig.GetBoolean("StrictAccessControl", m_strictAccessControl); m_seeIntoBannedRegion = startupConfig.GetBoolean("SeeIntoBannedRegion", m_seeIntoBannedRegion); CombineRegions = startupConfig.GetBoolean("CombineContiguousRegions", false); -- cgit v1.1 From 73c9abf5f2e2017bf924d6183502e337d28a7232 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Tue, 9 Oct 2012 01:35:27 +0100 Subject: Move OpenSim.Data.RegionFlags -> OpenSim.Framework.RegionFlags to make it easier for other code to use (e.g. LSL_Api) without having to reference OpenSim.Data just for this. --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 1 + .../Framework/EntityTransfer/HGEntityTransferModule.cs | 8 ++++---- OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs | 1 + OpenSim/Region/CoreModules/World/Land/LandObject.cs | 1 + 4 files changed, 7 insertions(+), 4 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 0869bd5..62f51d9 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -47,6 +47,7 @@ using OpenSim.Region.Framework.Scenes; using OpenSim.Services.Interfaces; using Timer = System.Timers.Timer; using AssetLandmark = OpenSim.Framework.AssetLandmark; +using RegionFlags = OpenMetaverse.RegionFlags; using Nini.Config; using System.IO; diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs index aa1e127..679be18 100644 --- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs +++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs @@ -212,7 +212,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer int flags = Scene.GridService.GetRegionFlags(Scene.RegionInfo.ScopeID, region.RegionID); m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: region {0} flags: {1}", region.RegionID, flags); - if ((flags & (int)OpenSim.Data.RegionFlags.Hyperlink) != 0) + if ((flags & (int)OpenSim.Framework.RegionFlags.Hyperlink) != 0) { m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Destination region {0} is hyperlink", region.RegionID); GridRegion real_destination = m_GatekeeperConnector.GetHyperlinkRegion(region, region.RegionID); @@ -232,7 +232,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer return true; int flags = Scene.GridService.GetRegionFlags(Scene.RegionInfo.ScopeID, reg.RegionID); - if (flags == -1 /* no region in DB */ || (flags & (int)OpenSim.Data.RegionFlags.Hyperlink) != 0) + if (flags == -1 /* no region in DB */ || (flags & (int)OpenSim.Framework.RegionFlags.Hyperlink) != 0) return true; return false; @@ -256,7 +256,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer reason = string.Empty; logout = false; int flags = Scene.GridService.GetRegionFlags(Scene.RegionInfo.ScopeID, reg.RegionID); - if (flags == -1 /* no region in DB */ || (flags & (int)OpenSim.Data.RegionFlags.Hyperlink) != 0) + if (flags == -1 /* no region in DB */ || (flags & (int)OpenSim.Framework.RegionFlags.Hyperlink) != 0) { // this user is going to another grid // check if HyperGrid teleport is allowed, based on user level @@ -298,7 +298,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer // The rest is only needed for controlling appearance int flags = Scene.GridService.GetRegionFlags(Scene.RegionInfo.ScopeID, reg.RegionID); - if (flags == -1 /* no region in DB */ || (flags & (int)OpenSim.Data.RegionFlags.Hyperlink) != 0) + if (flags == -1 /* no region in DB */ || (flags & (int)OpenSim.Framework.RegionFlags.Hyperlink) != 0) { // this user is going to another grid if (Scene.UserManagementModule.IsLocalGridUser(sp.UUID)) diff --git a/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs b/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs index 58bbd24..0e6d663 100644 --- a/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs +++ b/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs @@ -39,6 +39,7 @@ using OpenMetaverse; using OpenSim.Framework; using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Scenes; +using RegionFlags = OpenMetaverse.RegionFlags; namespace OpenSim.Region.CoreModules.World.Estate { diff --git a/OpenSim/Region/CoreModules/World/Land/LandObject.cs b/OpenSim/Region/CoreModules/World/Land/LandObject.cs index 0536f6e..8829f27 100644 --- a/OpenSim/Region/CoreModules/World/Land/LandObject.cs +++ b/OpenSim/Region/CoreModules/World/Land/LandObject.cs @@ -33,6 +33,7 @@ using OpenMetaverse; using OpenSim.Framework; using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Scenes; +using RegionFlags = OpenMetaverse.RegionFlags; namespace OpenSim.Region.CoreModules.World.Land { -- cgit v1.1 From 764270a0d81ef3aeba9ceb2eb50eab74a4707a95 Mon Sep 17 00:00:00 2001 From: teravus Date: Tue, 9 Oct 2012 09:26:11 -0400 Subject: Add config option to plant avatar where they are reducing avatar avatar 'pushability' av_planted see OpenSimDefaults.ini. Use when you have unruly visitors that rudely push each other around. Still allows a small amount of movement based on the avatar movement PID controller settings. You can increase the spring tension in the PID controller and really prevent any movement if you would like. --- OpenSim/Region/Physics/OdePlugin/ODECharacter.cs | 4 ++-- OpenSim/Region/Physics/OdePlugin/OdeScene.cs | 8 +++++++- 2 files changed, 9 insertions(+), 3 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs b/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs index f3b0630..c736557 100644 --- a/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs +++ b/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs @@ -100,7 +100,7 @@ namespace OpenSim.Region.Physics.OdePlugin private bool m_hackSentFly = false; private int m_requestedUpdateFrequency = 0; private Vector3 m_taintPosition; - + internal bool m_avatarplanted = false; /// /// Hold set forces so we can process them outside physics calculations. This prevents race conditions if we set force /// while calculatios are going on @@ -413,7 +413,7 @@ namespace OpenSim.Region.Physics.OdePlugin set { m_iscollidingObj = value; - if (value) + if (value && !m_avatarplanted) m_pidControllerActive = false; else m_pidControllerActive = true; diff --git a/OpenSim/Region/Physics/OdePlugin/OdeScene.cs b/OpenSim/Region/Physics/OdePlugin/OdeScene.cs index 7a50c4c..8421cdf 100644 --- a/OpenSim/Region/Physics/OdePlugin/OdeScene.cs +++ b/OpenSim/Region/Physics/OdePlugin/OdeScene.cs @@ -501,6 +501,8 @@ namespace OpenSim.Region.Physics.OdePlugin public int physics_logging_interval = 0; public bool physics_logging_append_existing_logfile = false; + private bool avplanted = false; + public d.Vector3 xyz = new d.Vector3(128.1640f, 128.3079f, 25.7600f); public d.Vector3 hpr = new d.Vector3(125.5000f, -17.0000f, 0.0000f); @@ -644,6 +646,8 @@ namespace OpenSim.Region.Physics.OdePlugin avMovementDivisorWalk = physicsconfig.GetFloat("av_movement_divisor_walk", 1.3f); avMovementDivisorRun = physicsconfig.GetFloat("av_movement_divisor_run", 0.8f); avCapRadius = physicsconfig.GetFloat("av_capsule_radius", 0.37f); + avplanted = physicsconfig.GetBoolean("av_planted", false); + IsAvCapsuleTilted = physicsconfig.GetBoolean("av_capsule_tilted", false); contactsPerCollision = physicsconfig.GetInt("contacts_per_collision", 80); @@ -1972,7 +1976,8 @@ namespace OpenSim.Region.Physics.OdePlugin newAv.Flying = isFlying; newAv.MinimumGroundFlightOffset = minimumGroundFlightOffset; - + newAv.m_avatarplanted = avplanted; + return newAv; } @@ -1987,6 +1992,7 @@ namespace OpenSim.Region.Physics.OdePlugin internal void AddCharacter(OdeCharacter chr) { + chr.m_avatarplanted = avplanted; if (!_characters.Contains(chr)) { _characters.Add(chr); -- cgit v1.1 From 7e90ea355120c717d1639d817b2b38326a4d5528 Mon Sep 17 00:00:00 2001 From: teravus Date: Tue, 9 Oct 2012 10:41:16 -0400 Subject: av_av_collisions_off = false OdePhysics Settings in OpenSimDefaults.ini - No Avatar Avatar Collisions. This causes avatar to be able to walk through each other as if they're ghosts but still interact with the environment. --- OpenSim/Region/Physics/OdePlugin/OdeScene.cs | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Physics/OdePlugin/OdeScene.cs b/OpenSim/Region/Physics/OdePlugin/OdeScene.cs index 8421cdf..cbe21e2 100644 --- a/OpenSim/Region/Physics/OdePlugin/OdeScene.cs +++ b/OpenSim/Region/Physics/OdePlugin/OdeScene.cs @@ -502,7 +502,7 @@ namespace OpenSim.Region.Physics.OdePlugin public bool physics_logging_append_existing_logfile = false; private bool avplanted = false; - + private bool av_av_collisions_off = false; public d.Vector3 xyz = new d.Vector3(128.1640f, 128.3079f, 25.7600f); public d.Vector3 hpr = new d.Vector3(125.5000f, -17.0000f, 0.0000f); @@ -647,7 +647,8 @@ namespace OpenSim.Region.Physics.OdePlugin avMovementDivisorRun = physicsconfig.GetFloat("av_movement_divisor_run", 0.8f); avCapRadius = physicsconfig.GetFloat("av_capsule_radius", 0.37f); avplanted = physicsconfig.GetBoolean("av_planted", false); - + av_av_collisions_off = physicsconfig.GetBoolean("av_av_collisions_off", false); + IsAvCapsuleTilted = physicsconfig.GetBoolean("av_capsule_tilted", false); contactsPerCollision = physicsconfig.GetInt("contacts_per_collision", 80); @@ -667,6 +668,8 @@ namespace OpenSim.Region.Physics.OdePlugin meshSculptLOD = physicsconfig.GetFloat("mesh_lod", 32f); MeshSculptphysicalLOD = physicsconfig.GetFloat("mesh_physical_lod", 16f); m_filterCollisions = physicsconfig.GetBoolean("filter_collisions", false); + + if (Environment.OSVersion.Platform == PlatformID.Unix) { @@ -1313,6 +1316,10 @@ namespace OpenSim.Region.Physics.OdePlugin if ((p1 is OdePrim) && (((OdePrim)p1).m_isVolumeDetect)) skipThisContact = true; // No collision on volume detect prims + if (av_av_collisions_off) + if ((p1 is OdeCharacter) && (p2 is OdeCharacter)) + skipThisContact = true; + if (!skipThisContact && (p2 is OdePrim) && (((OdePrim)p2).m_isVolumeDetect)) skipThisContact = true; // No collision on volume detect prims -- cgit v1.1 From a3c0e3ed260a8a76e3009e99162cdcb8142ea1b1 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Tue, 9 Oct 2012 22:19:47 +0100 Subject: minor: elaborate method doc on Scene.NewUserConnection() --- OpenSim/Region/Framework/Scenes/Scene.cs | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 671feda..ed88571 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -3461,11 +3461,9 @@ namespace OpenSim.Region.Framework.Scenes /// /// Do the work necessary to initiate a new user connection for a particular scene. - /// At the moment, this consists of setting up the caps infrastructure - /// The return bool should allow for connections to be refused, but as not all calling paths - /// take proper notice of it let, we allowed banned users in still. /// /// CircuitData of the agent who is connecting + /// /// Outputs the reason for the false response on this string /// True if the region accepts this agent. False if it does not. False will /// also return a reason. @@ -3476,10 +3474,20 @@ namespace OpenSim.Region.Framework.Scenes /// /// Do the work necessary to initiate a new user connection for a particular scene. - /// At the moment, this consists of setting up the caps infrastructure + /// + /// + /// The return bool should allow for connections to be refused, but as not all calling paths + /// take proper notice of it yet, we still allowed banned users in. + /// + /// At the moment this method consists of setting up the caps infrastructure /// The return bool should allow for connections to be refused, but as not all calling paths /// take proper notice of it let, we allowed banned users in still. - /// + /// + /// This method is called by the login service (in the case of login) or another simulator (in the case of region + /// cross or teleport) to initiate the connection. It is not triggered by the viewer itself - the connection + /// is activated later when the viewer sends the initial UseCircuitCodePacket UDP packet (in the case of + /// the LLUDP stack). + /// /// CircuitData of the agent who is connecting /// Outputs the reason for the false response on this string /// True for normal presence. False for NPC @@ -3566,7 +3574,6 @@ namespace OpenSim.Region.Framework.Scenes return false; } - ScenePresence sp = GetScenePresence(agent.AgentID); if (sp != null && !sp.IsChildAgent) -- cgit v1.1 From e76b01a201a9b2d45b56cd5dc2a207b08b4529e5 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Wed, 10 Oct 2012 00:26:43 +0100 Subject: Lock on AgentCircuitData during Scene.AddClient() and RemoveClient() to prevent an inactive connection being left behind if the user closes the viewer whilst the connection is being established. This should remove the need to run the console command "kick user --force" when these connections are left around. --- .../Linden/Caps/EventQueue/EventQueueGetModule.cs | 13 +- .../Region/ClientStack/Linden/UDP/LLUDPServer.cs | 14 +- OpenSim/Region/Framework/Scenes/Scene.cs | 457 ++++++++++++--------- 3 files changed, 265 insertions(+), 219 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs index 594b229..0dd0904 100644 --- a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs +++ b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs @@ -94,7 +94,7 @@ namespace OpenSim.Region.ClientStack.Linden //scene.CommsManager.HttpServer.AddLLSDHandler("/CAPS/EQG/", EventQueueFallBack); - scene.EventManager.OnNewClient += OnNewClient; +// scene.EventManager.OnNewClient += OnNewClient; // TODO: Leaving these open, or closing them when we // become a child is incorrect. It messes up TP in a big @@ -102,6 +102,7 @@ namespace OpenSim.Region.ClientStack.Linden // circuit is there. scene.EventManager.OnClientClosed += ClientClosed; + scene.EventManager.OnMakeChildAgent += MakeChildAgent; scene.EventManager.OnRegisterCaps += OnRegisterCaps; @@ -226,16 +227,6 @@ namespace OpenSim.Region.ClientStack.Linden #endregion - private void OnNewClient(IClientAPI client) - { - //client.OnLogout += ClientClosed; - } - -// private void ClientClosed(IClientAPI client) -// { -// ClientClosed(client.AgentId); -// } - private void ClientClosed(UUID agentID, Scene scene) { // m_log.DebugFormat("[EVENTQUEUE]: Closed client {0} in region {1}", agentID, m_scene.RegionInfo.RegionName); diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs index d11fcbf..ab670a7 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs @@ -1103,20 +1103,20 @@ namespace OpenSim.Region.ClientStack.LindenUDP { IClientAPI client = null; - // In priciple there shouldn't be more than one thread here, ever. - // But in case that happens, we need to synchronize this piece of code - // because it's too important - lock (this) + // We currently synchronize this code across the whole scene to avoid issues such as + // http://opensimulator.org/mantis/view.php?id=5365 However, once locking per agent circuit can be done + // consistently, this lock could probably be removed. + lock (this) { if (!m_scene.TryGetClient(agentID, out client)) { LLUDPClient udpClient = new LLUDPClient(this, ThrottleRates, m_throttle, circuitCode, agentID, remoteEndPoint, m_defaultRTO, m_maxRTO); - + client = new LLClientView(m_scene, this, udpClient, sessionInfo, agentID, sessionID, circuitCode); client.OnLogout += LogoutHandler; - + ((LLClientView)client).DisableFacelights = m_disableFacelights; - + client.Start(); } } diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index ed88571..fb2decc 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -80,6 +80,11 @@ namespace OpenSim.Region.Framework.Scenes public SynchronizeSceneHandler SynchronizeScene; /// + /// Used to prevent simultaneous calls to RemoveClient() for the same agent from interfering with each other. + /// + private object m_removeClientLock = new object(); + + /// /// Statistical information for this scene. /// public SimStatsReporter StatsReporter { get; private set; } @@ -2709,69 +2714,89 @@ namespace OpenSim.Region.Framework.Scenes public override ISceneAgent AddNewClient(IClientAPI client, PresenceType type) { + ScenePresence sp; + bool vialogin; + // Validation occurs in LLUDPServer + // + // XXX: A race condition exists here where two simultaneous calls to AddNewClient can interfere with + // each other. In practice, this does not currently occur in the code. AgentCircuitData aCircuit = m_authenticateHandler.GetAgentCircuitData(client.CircuitCode); - bool vialogin - = (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaHGLogin) != 0 - || (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaLogin) != 0; - -// CheckHeartbeat(); - - ScenePresence sp = GetScenePresence(client.AgentId); - - // XXX: Not sure how good it is to add a new client if a scene presence already exists. Possibly this - // could occur if a viewer crashes and relogs before the old client is kicked out. But this could cause - // other problems, and possible the code calling AddNewClient() should ensure that no client is already - // connected. - if (sp == null) - { - m_log.DebugFormat( - "[SCENE]: Adding new child scene presence {0} {1} to scene {2} at pos {3}", - client.Name, client.AgentId, RegionInfo.RegionName, client.StartPos); - - m_clientManager.Add(client); - SubscribeToClientEvents(client); - - sp = m_sceneGraph.CreateAndAddChildScenePresence(client, aCircuit.Appearance, type); - m_eventManager.TriggerOnNewPresence(sp); - - sp.TeleportFlags = (TPFlags)aCircuit.teleportFlags; + // We lock here on AgentCircuitData to prevent a race condition between the thread adding a new connection + // and a simultaneous one that removes it (as can happen if the client is closed at a particular point + // whilst connecting). + // + // It would be easier to lock across all NewUserConnection(), AddNewClient() and + // RemoveClient() calls for all agents, but this would allow a slow call (e.g. because of slow service + // response in some module listening to AddNewClient()) from holding up unrelated agent calls. + // + // In practice, the lock (this) in LLUDPServer.AddNewClient() currently lock across all + // AddNewClient() operations (though not other ops). + // In the future this can be relieved once locking per agent (not necessarily on AgentCircuitData) is improved. + lock (aCircuit) + { + vialogin + = (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaHGLogin) != 0 + || (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaLogin) != 0; + + // CheckHeartbeat(); + + sp = GetScenePresence(client.AgentId); - // The first agent upon login is a root agent by design. - // For this agent we will have to rez the attachments. - // All other AddNewClient calls find aCircuit.child to be true. - if (aCircuit.child == false) + // XXX: Not sure how good it is to add a new client if a scene presence already exists. Possibly this + // could occur if a viewer crashes and relogs before the old client is kicked out. But this could cause + // other problems, and possible the code calling AddNewClient() should ensure that no client is already + // connected. + if (sp == null) { - // We have to set SP to be a root agent here so that SP.MakeRootAgent() will later not try to - // start the scripts again (since this is done in RezAttachments()). - // XXX: This is convoluted. - sp.IsChildAgent = false; - - if (AttachmentsModule != null) - Util.FireAndForget(delegate(object o) { AttachmentsModule.RezAttachments(sp); }); + m_log.DebugFormat( + "[SCENE]: Adding new child scene presence {0} {1} to scene {2} at pos {3}", + client.Name, client.AgentId, RegionInfo.RegionName, client.StartPos); + + m_clientManager.Add(client); + SubscribeToClientEvents(client); + + sp = m_sceneGraph.CreateAndAddChildScenePresence(client, aCircuit.Appearance, type); + m_eventManager.TriggerOnNewPresence(sp); + + sp.TeleportFlags = (TPFlags)aCircuit.teleportFlags; + + // The first agent upon login is a root agent by design. + // For this agent we will have to rez the attachments. + // All other AddNewClient calls find aCircuit.child to be true. + if (aCircuit.child == false) + { + // We have to set SP to be a root agent here so that SP.MakeRootAgent() will later not try to + // start the scripts again (since this is done in RezAttachments()). + // XXX: This is convoluted. + sp.IsChildAgent = false; + + if (AttachmentsModule != null) + Util.FireAndForget(delegate(object o) { AttachmentsModule.RezAttachments(sp); }); + } } - } - else - { - m_log.WarnFormat( - "[SCENE]: Already found {0} scene presence for {1} in {2} when asked to add new scene presence", - sp.IsChildAgent ? "child" : "root", sp.Name, RegionInfo.RegionName); - } + else + { + m_log.WarnFormat( + "[SCENE]: Already found {0} scene presence for {1} in {2} when asked to add new scene presence", + sp.IsChildAgent ? "child" : "root", sp.Name, RegionInfo.RegionName); + } + + // We must set this here so that TriggerOnNewClient and TriggerOnClientLogin can determine whether the + // client is for a root or child agent. + client.SceneAgent = sp; - // We must set this here so that TriggerOnNewClient and TriggerOnClientLogin can determine whether the - // client is for a root or child agent. - client.SceneAgent = sp; + // Cache the user's name + CacheUserName(sp, aCircuit); + + EventManager.TriggerOnNewClient(client); + if (vialogin) + EventManager.TriggerOnClientLogin(client); + } m_LastLogin = Util.EnvironmentTickCount(); - // Cache the user's name - CacheUserName(sp, aCircuit); - - EventManager.TriggerOnNewClient(client); - if (vialogin) - EventManager.TriggerOnClientLogin(client); - return sp; } @@ -3300,109 +3325,129 @@ namespace OpenSim.Region.Framework.Scenes { // CheckHeartbeat(); bool isChildAgent = false; - ScenePresence avatar = GetScenePresence(agentID); - - if (avatar == null) - { - m_log.WarnFormat( - "[SCENE]: Called RemoveClient() with agent ID {0} but no such presence is in the scene.", agentID); - - return; - } + AgentCircuitData acd; - try + lock (m_removeClientLock) { - isChildAgent = avatar.IsChildAgent; - - m_log.DebugFormat( - "[SCENE]: Removing {0} agent {1} {2} from {3}", - (isChildAgent ? "child" : "root"), avatar.Name, agentID, RegionInfo.RegionName); + acd = m_authenticateHandler.GetAgentCircuitData(agentID); - // Don't do this to root agents, it's not nice for the viewer - if (closeChildAgents && isChildAgent) + if (acd == null) { - // Tell a single agent to disconnect from the region. - IEventQueue eq = RequestModuleInterface(); - if (eq != null) - { - eq.DisableSimulator(RegionInfo.RegionHandle, avatar.UUID); - } - else - { - avatar.ControllingClient.SendShutdownConnectionNotice(); - } + m_log.ErrorFormat("[SCENE]: No agent circuit found for {0}, aborting Scene.RemoveClient", agentID); + return; } - - // Only applies to root agents. - if (avatar.ParentID != 0) + else { - avatar.StandUp(); + // We remove the acd up here to avoid later raec conditions if two RemoveClient() calls occurred + // simultaneously. + m_authenticateHandler.RemoveCircuit(acd.circuitcode); } + } - m_sceneGraph.removeUserCount(!isChildAgent); - - // TODO: We shouldn't use closeChildAgents here - it's being used by the NPC module to stop - // unnecessary operations. This should go away once NPCs have no accompanying IClientAPI - if (closeChildAgents && CapsModule != null) - CapsModule.RemoveCaps(agentID); - - // REFACTORING PROBLEM -- well not really a problem, but just to point out that whatever - // this method is doing is HORRIBLE!!! - avatar.Scene.NeedSceneCacheClear(avatar.UUID); - - if (closeChildAgents && !isChildAgent) + lock (acd) + { + ScenePresence avatar = GetScenePresence(agentID); + + if (avatar == null) { - List regions = avatar.KnownRegionHandles; - regions.Remove(RegionInfo.RegionHandle); - m_sceneGridService.SendCloseChildAgentConnections(agentID, regions); + m_log.WarnFormat( + "[SCENE]: Called RemoveClient() with agent ID {0} but no such presence is in the scene.", agentID); + + return; } - - m_eventManager.TriggerClientClosed(agentID, this); - m_eventManager.TriggerOnRemovePresence(agentID); - - if (!isChildAgent) + + try { - if (AttachmentsModule != null) + isChildAgent = avatar.IsChildAgent; + + m_log.DebugFormat( + "[SCENE]: Removing {0} agent {1} {2} from {3}", + (isChildAgent ? "child" : "root"), avatar.Name, agentID, RegionInfo.RegionName); + + // Don't do this to root agents, it's not nice for the viewer + if (closeChildAgents && isChildAgent) { - AttachmentsModule.DeRezAttachments(avatar); + // Tell a single agent to disconnect from the region. + IEventQueue eq = RequestModuleInterface(); + if (eq != null) + { + eq.DisableSimulator(RegionInfo.RegionHandle, avatar.UUID); + } + else + { + avatar.ControllingClient.SendShutdownConnectionNotice(); + } } - - ForEachClient( - delegate(IClientAPI client) + + // Only applies to root agents. + if (avatar.ParentID != 0) + { + avatar.StandUp(); + } + + m_sceneGraph.removeUserCount(!isChildAgent); + + // TODO: We shouldn't use closeChildAgents here - it's being used by the NPC module to stop + // unnecessary operations. This should go away once NPCs have no accompanying IClientAPI + if (closeChildAgents && CapsModule != null) + CapsModule.RemoveCaps(agentID); + + // REFACTORING PROBLEM -- well not really a problem, but just to point out that whatever + // this method is doing is HORRIBLE!!! + avatar.Scene.NeedSceneCacheClear(avatar.UUID); + + if (closeChildAgents && !isChildAgent) + { + List regions = avatar.KnownRegionHandles; + regions.Remove(RegionInfo.RegionHandle); + m_sceneGridService.SendCloseChildAgentConnections(agentID, regions); + } + + m_eventManager.TriggerClientClosed(agentID, this); + m_eventManager.TriggerOnRemovePresence(agentID); + + if (!isChildAgent) + { + if (AttachmentsModule != null) { - //We can safely ignore null reference exceptions. It means the avatar is dead and cleaned up anyway - try { client.SendKillObject(avatar.RegionHandle, new List { avatar.LocalId }); } - catch (NullReferenceException) { } - }); - } - - // It's possible for child agents to have transactions if changes are being made cross-border. - if (AgentTransactionsModule != null) - AgentTransactionsModule.RemoveAgentAssetTransactions(agentID); + AttachmentsModule.DeRezAttachments(avatar); + } - m_authenticateHandler.RemoveCircuit(avatar.ControllingClient.CircuitCode); - } - catch (Exception e) - { - m_log.Error( - string.Format("[SCENE]: Exception removing {0} from {1}. Cleaning up. Exception ", avatar.Name, Name), e); - } - finally - { - try - { - // Always clean these structures up so that any failure above doesn't cause them to remain in the - // scene with possibly bad effects (e.g. continually timing out on unacked packets and triggering - // the same cleanup exception continually. - m_sceneGraph.RemoveScenePresence(agentID); - m_clientManager.Remove(agentID); + ForEachClient( + delegate(IClientAPI client) + { + //We can safely ignore null reference exceptions. It means the avatar is dead and cleaned up anyway + try { client.SendKillObject(avatar.RegionHandle, new List { avatar.LocalId }); } + catch (NullReferenceException) { } + }); + } - avatar.Close(); + // It's possible for child agents to have transactions if changes are being made cross-border. + if (AgentTransactionsModule != null) + AgentTransactionsModule.RemoveAgentAssetTransactions(agentID); } catch (Exception e) { m_log.Error( - string.Format("[SCENE]: Exception in final clean up of {0} in {1}. Exception ", avatar.Name, Name), e); + string.Format("[SCENE]: Exception removing {0} from {1}. Cleaning up. Exception ", avatar.Name, Name), e); + } + finally + { + try + { + // Always clean these structures up so that any failure above doesn't cause them to remain in the + // scene with possibly bad effects (e.g. continually timing out on unacked packets and triggering + // the same cleanup exception continually. + m_sceneGraph.RemoveScenePresence(agentID); + m_clientManager.Remove(agentID); + + avatar.Close(); + } + catch (Exception e) + { + m_log.Error( + string.Format("[SCENE]: Exception in final clean up of {0} in {1}. Exception ", avatar.Name, Name), e); + } } } @@ -3572,87 +3617,97 @@ namespace OpenSim.Region.Framework.Scenes agent.firstname, agent.lastname, agent.Viewer); reason = "Access denied, your viewer is banned by the region owner"; return false; - } - - ScenePresence sp = GetScenePresence(agent.AgentID); - - if (sp != null && !sp.IsChildAgent) - { - // We have a zombie from a crashed session. - // Or the same user is trying to be root twice here, won't work. - // Kill it. - m_log.WarnFormat( - "[SCENE]: Existing root scene presence detected for {0} {1} in {2} when connecting. Removing existing presence.", - sp.Name, sp.UUID, RegionInfo.RegionName); - - sp.ControllingClient.Close(true); - sp = null; } - ILandObject land = LandChannel.GetLandObject(agent.startpos.X, agent.startpos.Y); + ILandObject land; - //On login test land permisions - if (vialogin) + lock (agent) { - if (land != null && !TestLandRestrictions(agent, land, out reason)) + ScenePresence sp = GetScenePresence(agent.AgentID); + + if (sp != null && !sp.IsChildAgent) { - return false; + // We have a zombie from a crashed session. + // Or the same user is trying to be root twice here, won't work. + // Kill it. + m_log.WarnFormat( + "[SCENE]: Existing root scene presence detected for {0} {1} in {2} when connecting. Removing existing presence.", + sp.Name, sp.UUID, RegionInfo.RegionName); + + sp.ControllingClient.Close(true); + sp = null; } - } - - if (sp == null) // We don't have an [child] agent here already - { - if (requirePresenceLookup) + + land = LandChannel.GetLandObject(agent.startpos.X, agent.startpos.Y); + + //On login test land permisions + if (vialogin) { - try - { - if (!VerifyUserPresence(agent, out reason)) - return false; - } catch (Exception e) + if (land != null && !TestLandRestrictions(agent, land, out reason)) { - m_log.ErrorFormat( - "[SCENE]: Exception verifying presence {0}{1}", e.Message, e.StackTrace); return false; } } - - try - { - if (!AuthorizeUser(agent, out reason)) - return false; - } catch (Exception e) - { - m_log.ErrorFormat( - "[SCENE]: Exception authorizing user {0}{1}", e.Message, e.StackTrace); - return false; - } - - m_log.InfoFormat( - "[SCENE]: Region {0} authenticated and authorized incoming {1} agent {2} {3} {4} (circuit code {5})", - RegionInfo.RegionName, (agent.child ? "child" : "root"), agent.firstname, agent.lastname, - agent.AgentID, agent.circuitcode); - - if (CapsModule != null) + + if (sp == null) // We don't have an [child] agent here already { - CapsModule.SetAgentCapsSeeds(agent); - CapsModule.CreateCaps(agent.AgentID); - } - } else - { - // Let the SP know how we got here. This has a lot of interesting - // uses down the line. - sp.TeleportFlags = (TPFlags)teleportFlags; + if (requirePresenceLookup) + { + try + { + if (!VerifyUserPresence(agent, out reason)) + return false; + } + catch (Exception e) + { + m_log.ErrorFormat( + "[SCENE]: Exception verifying presence {0}{1}", e.Message, e.StackTrace); - if (sp.IsChildAgent) - { - m_log.DebugFormat( - "[SCENE]: Adjusting known seeds for existing agent {0} in {1}", - agent.AgentID, RegionInfo.RegionName); + return false; + } + } + + try + { + if (!AuthorizeUser(agent, out reason)) + return false; + } + catch (Exception e) + { + m_log.ErrorFormat( + "[SCENE]: Exception authorizing user {0}{1}", e.Message, e.StackTrace); - sp.AdjustKnownSeeds(); - + return false; + } + + m_log.InfoFormat( + "[SCENE]: Region {0} authenticated and authorized incoming {1} agent {2} {3} {4} (circuit code {5})", + RegionInfo.RegionName, (agent.child ? "child" : "root"), agent.firstname, agent.lastname, + agent.AgentID, agent.circuitcode); + if (CapsModule != null) + { CapsModule.SetAgentCapsSeeds(agent); + CapsModule.CreateCaps(agent.AgentID); + } + } + else + { + // Let the SP know how we got here. This has a lot of interesting + // uses down the line. + sp.TeleportFlags = (TPFlags)teleportFlags; + + if (sp.IsChildAgent) + { + m_log.DebugFormat( + "[SCENE]: Adjusting known seeds for existing agent {0} in {1}", + agent.AgentID, RegionInfo.RegionName); + + sp.AdjustKnownSeeds(); + + if (CapsModule != null) + CapsModule.SetAgentCapsSeeds(agent); + } } } -- cgit v1.1 From 528085adefdd105aca2621c747fefe728ea8c218 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Wed, 10 Oct 2012 00:48:20 +0100 Subject: minor: Add method doc to EventManager.OnNewClient, OnClientLogin, ClientClosed, OnRemovePresence that any long-running operations should be launched on a thread separate to the event thread. --- OpenSim/Region/Framework/Scenes/EventManager.cs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Framework/Scenes/EventManager.cs b/OpenSim/Region/Framework/Scenes/EventManager.cs index a8ff218..4c49b71 100644 --- a/OpenSim/Region/Framework/Scenes/EventManager.cs +++ b/OpenSim/Region/Framework/Scenes/EventManager.cs @@ -121,13 +121,21 @@ namespace OpenSim.Region.Framework.Scenes /// /// /// This is triggered for both child and root agent client connections. + /// /// Triggered before OnClientLogin. + /// + /// This is triggered under per-agent lock. So if you want to perform any long-running operations, please + /// do this on a separate thread. /// public event OnNewClientDelegate OnNewClient; /// /// Fired if the client entering this sim is doing so as a new login /// + /// + /// This is triggered under per-agent lock. So if you want to perform any long-running operations, please + /// do this on a separate thread. + /// public event Action OnClientLogin; public delegate void OnNewPresenceDelegate(ScenePresence presence); @@ -149,6 +157,9 @@ namespace OpenSim.Region.Framework.Scenes /// /// Triggered in which is used by both /// users and NPCs + /// + /// Triggered under per-agent lock. So if you want to perform any long-running operations, please + /// do this on a separate thread. /// public event OnRemovePresenceDelegate OnRemovePresence; @@ -425,6 +436,9 @@ namespace OpenSim.Region.Framework.Scenes /// /// /// At the point of firing, the scene still contains the client's scene presence. + /// + /// This is triggered under per-agent lock. So if you want to perform any long-running operations, please + /// do this on a separate thread. /// public event ClientClosed OnClientClosed; -- cgit v1.1 From 11d8119a21c645d6a0d71edc7444f058ba89414b Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Wed, 10 Oct 2012 01:37:57 +0100 Subject: Remove osDropAttachment threat level check wrongly placed in OSSL_Api.ShoutErrorOnLackingOwnerPerms. --- OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs | 1 - 1 file changed, 1 deletion(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs index 31be450..279ad59 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs @@ -3555,7 +3555,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api /// boolean indicating whether an error was shouted. protected bool ShoutErrorOnLackingOwnerPerms(int perms, string errorPrefix) { - CheckThreatLevel(ThreatLevel.Moderate, "osDropAttachment"); m_host.AddScriptLPS(1); bool fail = false; if (m_item.PermsGranter != m_host.OwnerID) -- cgit v1.1 From 756ac4f32104db9dcdfb1c1da81075299e2cbfb4 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Wed, 10 Oct 2012 01:39:47 +0100 Subject: Correct osSetContentType() threat check to query osSetContentType rather than osSetResponseType --- OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs index 279ad59..29bc163 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs @@ -3545,10 +3545,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api /// public void osSetContentType(LSL_Key id, string type) { - CheckThreatLevel(ThreatLevel.High,"osSetResponseType"); + CheckThreatLevel(ThreatLevel.High, "osSetContentType"); + if (m_UrlModule != null) m_UrlModule.HttpContentType(new UUID(id),type); } + /// Shout an error if the object owner did not grant the script the specified permissions. /// /// -- cgit v1.1 From efd9791506b00e424bb5f1846b37d79e7638bda2 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Wed, 10 Oct 2012 23:30:48 +0100 Subject: Add "delete object pos to " console command. This allows one to delete objects within a certain volume. See help on console for more details. --- .../World/Objects/Commands/ObjectCommandsModule.cs | 109 ++++++++++++++++----- 1 file changed, 85 insertions(+), 24 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs b/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs index 6e39e9a..85779ec 100644 --- a/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs +++ b/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs @@ -27,6 +27,7 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Reflection; using System.Text; using System.Text.RegularExpressions; @@ -83,29 +84,56 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands m_console.Commands.AddCommand( "Objects", false, "delete object owner", "delete object owner ", - "Delete a scene object by owner", HandleDeleteObject); + "Delete scene objects by owner", + "Command will ask for confirmation before proceeding.", + HandleDeleteObject); m_console.Commands.AddCommand( "Objects", false, "delete object creator", "delete object creator ", - "Delete a scene object by creator", HandleDeleteObject); + "Delete scene objects by creator", + "Command will ask for confirmation before proceeding.", + HandleDeleteObject); m_console.Commands.AddCommand( "Objects", false, "delete object uuid", "delete object uuid ", - "Delete a scene object by uuid", HandleDeleteObject); + "Delete a scene object by uuid", + HandleDeleteObject); m_console.Commands.AddCommand( "Objects", false, "delete object name", "delete object name [--regex] ", "Delete a scene object by name.", - "If --regex is specified then the name is treatead as a regular expression", + "Command will ask for confirmation before proceeding.\n" + + "If --regex is specified then the name is treatead as a regular expression", HandleDeleteObject); m_console.Commands.AddCommand( "Objects", false, "delete object outside", "delete object outside", - "Delete all scene objects outside region boundaries", HandleDeleteObject); + "Delete all scene objects outside region boundaries", + "Command will ask for confirmation before proceeding.", + HandleDeleteObject); + + m_console.Commands.AddCommand( + "Objects", + false, + "delete object pos", + "delete object pos to ", + "Delete scene objects within the given area.", + "Each component of the coord is comma separated. There must be no spaces between the commas.\n" + + "If you don't care about the z component you can simply omit it.\n" + + "If you don't care about the x or y components then you can leave them blank (though a comma is still required)\n" + + "If you want to specify the maxmimum value of a component then you can use ~ instead of a number\n" + + "If you want to specify the minimum value of a component then you can use -~ instead of a number\n" + + "e.g.\n" + + "delete object pos 20,20,20 to 40,40,40\n" + + "delete object pos 20,20 to 40,40\n" + + "delete object pos ,20,20 to ,40,40\n" + + "delete object pos ,,30 to ,,~\n" + + "delete object pos ,,-~ to ,,30", + HandleDeleteObject); m_console.Commands.AddCommand( "Objects", @@ -301,23 +329,10 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands return; } - string rawConsoleStartVector = cmdparams[3]; - Vector3 startVector; + Vector3 startVector, endVector; - if (!ConsoleUtil.TryParseConsoleMinVector(rawConsoleStartVector, out startVector)) - { - m_console.OutputFormat("Error: Start vector {0} does not have a valid format", rawConsoleStartVector); + if (!TryParseVectorRange(cmdparams.Skip(3).Take(3), out startVector, out endVector)) return; - } - - string rawConsoleEndVector = cmdparams[5]; - Vector3 endVector; - - if (!ConsoleUtil.TryParseConsoleMaxVector(rawConsoleEndVector, out endVector)) - { - m_console.OutputFormat("Error: End vector {0} does not have a valid format", rawConsoleEndVector); - return; - } Predicate searchPredicate = so => Util.IsInsideBox(so.AbsolutePosition, startVector, endVector); @@ -557,6 +572,10 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands break; + case "pos": + deletes = GetDeleteCandidatesByPos(module, cmd); + break; + default: m_console.OutputFormat("Unrecognized mode {0}", mode); return; @@ -571,7 +590,7 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands string.Format( "Are you sure that you want to delete {0} objects from {1}", deletes.Count, m_scene.RegionInfo.RegionName), - "n"); + "y/N"); if (response.ToLower() != "y") { @@ -593,9 +612,6 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands private List GetDeleteCandidatesByName(string module, string[] cmdparams) { - if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene)) - return null; - bool useRegex = false; OptionSet options = new OptionSet().Add("regex", v=> useRegex = v != null ); @@ -629,5 +645,50 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands return sceneObjects; } + + /// + /// Get scene object delete candidates by position + /// + /// + /// + /// null if parsing failed on one of the arguments, otherwise a list of objects to delete. If there + /// are no objects to delete then the list will be empty./returns> + private List GetDeleteCandidatesByPos(string module, string[] cmdparams) + { + if (cmdparams.Length < 5) + { + m_console.OutputFormat("Usage: delete object pos to "); + return null; + } + + Vector3 startVector, endVector; + + if (!TryParseVectorRange(cmdparams.Skip(3).Take(3), out startVector, out endVector)) + return null; + + return m_scene.GetSceneObjectGroups().FindAll( + so => !so.IsAttachment && Util.IsInsideBox(so.AbsolutePosition, startVector, endVector)); + } + + private bool TryParseVectorRange(IEnumerable rawComponents, out Vector3 startVector, out Vector3 endVector) + { + string rawConsoleStartVector = rawComponents.Take(1).Single(); + + if (!ConsoleUtil.TryParseConsoleMinVector(rawConsoleStartVector, out startVector)) + { + m_console.OutputFormat("Error: Start vector {0} does not have a valid format", rawConsoleStartVector); + return false; + } + + string rawConsoleEndVector = rawComponents.Skip(1).Take(1).Single(); + + if (!ConsoleUtil.TryParseConsoleMaxVector(rawConsoleEndVector, out endVector)) + { + m_console.OutputFormat("Error: End vector {0} does not have a valid format", rawConsoleEndVector); + return false; + } + + return true; + } } } \ No newline at end of file -- cgit v1.1 From b768c35f6f69606d17fdd76d94b95428ac9d0029 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Thu, 11 Oct 2012 00:05:34 +0100 Subject: Assign endVector before control leaves ObjectCommandsModule.TryParseVectorRange() in order to fix mono 2.4.3 compile failure. This doesn't fail the compile on mono 2.10.8. --- .../Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs | 2 ++ 1 file changed, 2 insertions(+) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs b/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs index 85779ec..7a35182 100644 --- a/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs +++ b/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs @@ -677,6 +677,8 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands if (!ConsoleUtil.TryParseConsoleMinVector(rawConsoleStartVector, out startVector)) { m_console.OutputFormat("Error: Start vector {0} does not have a valid format", rawConsoleStartVector); + endVector = Vector3.Zero; + return false; } -- cgit v1.1 From 87825b0abee76c28dcffdaa2c532779b813b6d14 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Fri, 5 Oct 2012 15:33:17 -0700 Subject: BulletSim: Fix crash when linking large physical linksets. Properly remove and restore linkage constraints when upgrading a prim's mesh to a hull. Lots more debug logging. Definitions and use of Bullet structure dumping. Centralize detail logging so a Flush() can be added for debugging. --- .../Region/Physics/BulletSPlugin/BSConstraint.cs | 13 +- OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs | 2 +- OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs | 137 ++++++++++----------- .../Region/Physics/BulletSPlugin/BSPhysObject.cs | 3 +- OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | 9 +- OpenSim/Region/Physics/BulletSPlugin/BSScene.cs | 11 +- .../Physics/BulletSPlugin/BSShapeCollection.cs | 45 ++++--- .../Region/Physics/BulletSPlugin/BulletSimAPI.cs | 14 ++- 8 files changed, 132 insertions(+), 102 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs b/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs index 63a4127..a20be3a 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs @@ -49,9 +49,16 @@ public abstract class BSConstraint : IDisposable if (m_enabled) { m_enabled = false; - bool success = BulletSimAPI.DestroyConstraint2(m_world.ptr, m_constraint.ptr); - m_world.physicsScene.DetailLog("{0},BSConstraint.Dispose,taint,body1={1},body2={2},success={3}", BSScene.DetailLogZero, m_body1.ID, m_body2.ID, success); - m_constraint.ptr = System.IntPtr.Zero; + if (m_constraint.ptr != IntPtr.Zero) + { + bool success = BulletSimAPI.DestroyConstraint2(m_world.ptr, m_constraint.ptr); + m_world.physicsScene.DetailLog("{0},BSConstraint.Dispose,taint,id1={1},body1={2},id2={3},body2={4},success={5}", + BSScene.DetailLogZero, + m_body1.ID, m_body1.ptr.ToString("X"), + m_body2.ID, m_body2.ptr.ToString("X"), + success); + m_constraint.ptr = System.IntPtr.Zero; + } } } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs index 4ba2f62..3fb2253 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs @@ -862,7 +862,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin private void VDetailLog(string msg, params Object[] args) { if (Prim.PhysicsScene.VehicleLoggingEnabled) - Prim.PhysicsScene.PhysicsLogging.Write(msg, args); + Prim.PhysicsScene.DetailLog(msg, args); } } } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs index 3e82642..20db4de 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs @@ -52,8 +52,8 @@ public class BSLinkset // the physical 'taint' children separately. // After taint processing and before the simulation step, these // two lists must be the same. - private List m_children; - private List m_taintChildren; + private HashSet m_children; + private HashSet m_taintChildren; // We lock the diddling of linkset classes to prevent any badness. // This locks the modification of the instances of this class. Changes @@ -90,8 +90,8 @@ public class BSLinkset m_nextLinksetID = 1; PhysicsScene = scene; LinksetRoot = parent; - m_children = new List(); - m_taintChildren = new List(); + m_children = new HashSet(); + m_taintChildren = new HashSet(); m_mass = parent.MassRaw; } @@ -197,6 +197,8 @@ public class BSLinkset PhysicsScene.TaintedObject("BSLinkSet.Refresh", delegate() { RecomputeLinksetConstraintVariables(); + DetailLog("{0},BSLinkset.Refresh,complete,rBody={1}", + LinksetRoot.LocalID, LinksetRoot.BSBody.ptr.ToString("X")); }); } } @@ -215,13 +217,10 @@ public class BSLinkset if (IsRoot(child)) { // If the one with the dependency is root, must undo all children - DetailLog("{0},BSLinkset.RemoveBodyDependencies,removeChildrenForRoot,rID={1},numChild={2}", - child.LocalID, LinksetRoot.LocalID, m_taintChildren.Count); - foreach (BSPhysObject bpo in m_taintChildren) - { - PhysicallyUnlinkAChildFromRoot(LinksetRoot, LinksetRoot.BSBody, bpo, bpo.BSBody); - ret = true; - } + DetailLog("{0},BSLinkset.RemoveBodyDependencies,removeChildrenForRoot,rID={1},rBody={2}", + child.LocalID, LinksetRoot.LocalID, LinksetRoot.BSBody.ptr.ToString("X")); + + ret = PhysicallyUnlinkAllChildrenFromRoot(LinksetRoot); } else { @@ -229,12 +228,9 @@ public class BSLinkset child.LocalID, LinksetRoot.LocalID, LinksetRoot.BSBody.ptr.ToString("X"), child.LocalID, child.BSBody.ptr.ToString("X")); - // Remove the dependency on the body of this one - if (m_taintChildren.Contains(child)) - { - PhysicallyUnlinkAChildFromRoot(LinksetRoot, LinksetRoot.BSBody, child, child.BSBody); - ret = true; - } + // ret = PhysicallyUnlinkAChildFromRoot(LinksetRoot, child); + // Despite the function name, this removes any link to the specified object. + ret = PhysicallyUnlinkAllChildrenFromRoot(child); } } return ret; @@ -254,7 +250,7 @@ public class BSLinkset child.LocalID, LinksetRoot.LocalID, m_taintChildren.Count); foreach (BSPhysObject bpo in m_taintChildren) { - PhysicallyLinkAChildToRoot(LinksetRoot, LinksetRoot.BSBody, bpo, bpo.BSBody); + PhysicallyLinkAChildToRoot(LinksetRoot, bpo); } } else @@ -263,7 +259,7 @@ public class BSLinkset LinksetRoot.LocalID, LinksetRoot.LocalID, LinksetRoot.BSBody.ptr.ToString("X"), child.LocalID, child.BSBody.ptr.ToString("X")); - PhysicallyLinkAChildToRoot(LinksetRoot, LinksetRoot.BSBody, child, child.BSBody); + PhysicallyLinkAChildToRoot(LinksetRoot, child); } } } @@ -330,22 +326,22 @@ public class BSLinkset { m_children.Add(child); - BSPhysObject rootx = LinksetRoot; // capture the root and body as of now + BSPhysObject rootx = LinksetRoot; // capture the root as of now BSPhysObject childx = child; - DetailLog("{0},AddChildToLinkset,call,rID={1},rBody={2},cID={3},cBody={4}", - rootx.LocalID, - rootx.LocalID, rootx.BSBody.ptr.ToString("X"), - childx.LocalID, childx.BSBody.ptr.ToString("X")); + DetailLog("{0},AddChildToLinkset,call,child={1}", LinksetRoot.LocalID, child.LocalID); PhysicsScene.TaintedObject("AddChildToLinkset", delegate() { - DetailLog("{0},AddChildToLinkset,taint,child={1}", LinksetRoot.LocalID, child.LocalID); - // build the physical binding between me and the child - m_taintChildren.Add(childx); - + DetailLog("{0},AddChildToLinkset,taint,rID={1},rBody={2},cID={3},cBody={4}", + rootx.LocalID, + rootx.LocalID, rootx.BSBody.ptr.ToString("X"), + childx.LocalID, childx.BSBody.ptr.ToString("X")); // Since this is taint-time, the body and shape could have changed for the child - PhysicallyLinkAChildToRoot(rootx, rootx.BSBody, childx, childx.BSBody); + rootx.ForcePosition = rootx.Position; // DEBUG + childx.ForcePosition = childx.Position; // DEBUG + PhysicallyLinkAChildToRoot(rootx, childx); + m_taintChildren.Add(child); }); } return; @@ -378,10 +374,8 @@ public class BSLinkset PhysicsScene.TaintedObject("RemoveChildFromLinkset", delegate() { - if (m_taintChildren.Contains(childx)) - m_taintChildren.Remove(childx); - - PhysicallyUnlinkAChildFromRoot(rootx, rootx.BSBody, childx, childx.BSBody); + m_taintChildren.Remove(child); + PhysicallyUnlinkAChildFromRoot(rootx, childx); RecomputeLinksetConstraintVariables(); }); @@ -396,8 +390,7 @@ public class BSLinkset // Create a constraint between me (root of linkset) and the passed prim (the child). // Called at taint time! - private void PhysicallyLinkAChildToRoot(BSPhysObject rootPrim, BulletBody rootBody, - BSPhysObject childPrim, BulletBody childBody) + private void PhysicallyLinkAChildToRoot(BSPhysObject rootPrim, BSPhysObject childPrim) { // Zero motion for children so they don't interpolate childPrim.ZeroMotion(); @@ -409,33 +402,17 @@ public class BSLinkset // real world coordinate of midpoint between the two objects OMV.Vector3 midPoint = rootPrim.Position + (childRelativePosition / 2); - DetailLog("{0},PhysicallyLinkAChildToRoot,taint,root={1},rBody={2},child={3},cBody={4},rLoc={5},cLoc={6},midLoc={7}", + DetailLog("{0},BSLinkset.PhysicallyLinkAChildToRoot,taint,root={1},rBody={2},child={3},cBody={4},rLoc={5},cLoc={6},midLoc={7}", rootPrim.LocalID, - rootPrim.LocalID, rootBody.ptr.ToString("X"), - childPrim.LocalID, childBody.ptr.ToString("X"), + rootPrim.LocalID, rootPrim.BSBody.ptr.ToString("X"), + childPrim.LocalID, childPrim.BSBody.ptr.ToString("X"), rootPrim.Position, childPrim.Position, midPoint); // create a constraint that allows no freedom of movement between the two objects // http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818 - // There is great subtlty in these paramters. Notice the check for a ptr of zero. - // We pass the BulletBody structure into the taint in order to capture the pointer - // of the body at the time of constraint creation. This doesn't work for the very first - // construction because there is no body yet. The body - // is constructed later at taint time. Thus we use the body address at time of the - // taint creation but, if it is zero, use what's in the prim at the moment. - // There is a possible race condition since shape can change without a taint call - // (like changing to a mesh that is already constructed). The fix for that would be - // to only change BSShape at taint time thus syncronizing these operations at - // the cost of efficiency and lag. BS6DofConstraint constrain = new BS6DofConstraint( - PhysicsScene.World, - rootBody.ptr == IntPtr.Zero ? rootPrim.BSBody : rootBody, - childBody.ptr == IntPtr.Zero ? childPrim.BSBody : childBody, - midPoint, - true, - true - ); + PhysicsScene.World, rootPrim.BSBody, childPrim.BSBody, midPoint, true, true ); /* NOTE: below is an attempt to build constraint with full frame computation, etc. * Using the midpoint is easier since it lets the Bullet code manipulate the transforms @@ -452,7 +429,7 @@ public class BSLinkset // create a constraint that allows no freedom of movement between the two objects // http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818 - DetailLog("{0},PhysicallyLinkAChildToRoot,taint,root={1},child={2}", rootPrim.LocalID, rootPrim.LocalID, childPrim.LocalID); + DetailLog("{0},BSLinkset.PhysicallyLinkAChildToRoot,taint,root={1},child={2}", rootPrim.LocalID, rootPrim.LocalID, childPrim.LocalID); BS6DofConstraint constrain = new BS6DofConstraint( PhysicsScene.World, rootPrim.Body, childPrim.Body, OMV.Vector3.Zero, @@ -486,39 +463,44 @@ public class BSLinkset { constrain.SetSolverIterations(PhysicsScene.Params.linkConstraintSolverIterations); } - - RecomputeLinksetConstraintVariables(); } // Remove linkage between myself and a particular child // The root and child bodies are passed in because we need to remove the constraint between // the bodies that were at unlink time. // Called at taint time! - private void PhysicallyUnlinkAChildFromRoot(BSPhysObject rootPrim, BulletBody rootBody, - BSPhysObject childPrim, BulletBody childBody) + private bool PhysicallyUnlinkAChildFromRoot(BSPhysObject rootPrim, BSPhysObject childPrim) { - DetailLog("{0},PhysicallyUnlinkAChildFromRoot,taint,root={1},rBody={2},child={3},cBody={4}", + bool ret = false; + DetailLog("{0},BSLinkset.PhysicallyUnlinkAChildFromRoot,taint,root={1},rBody={2},child={3},cBody={4}", rootPrim.LocalID, - rootPrim.LocalID, rootBody.ptr.ToString("X"), - childPrim.LocalID, childBody.ptr.ToString("X")); + rootPrim.LocalID, rootPrim.BSBody.ptr.ToString("X"), + childPrim.LocalID, childPrim.BSBody.ptr.ToString("X")); // Find the constraint for this link and get rid of it from the overall collection and from my list - PhysicsScene.Constraints.RemoveAndDestroyConstraint(rootBody, childBody); + if (PhysicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.BSBody, childPrim.BSBody)) + { + // Make the child refresh its location + BulletSimAPI.PushUpdate2(childPrim.BSBody.ptr); + ret = true; + } - // Make the child refresh its location - BulletSimAPI.PushUpdate2(childPrim.BSBody.ptr); + return ret; } - /* // Remove linkage between myself and any possible children I might have. // Called at taint time! - private void PhysicallyUnlinkAllChildrenFromRoot(BSPhysObject rootPrim) + private bool PhysicallyUnlinkAllChildrenFromRoot(BSPhysObject rootPrim) { - DetailLog("{0},PhysicallyUnlinkAllChildren,taint", rootPrim.LocalID); + DetailLog("{0},BSLinkset.PhysicallyUnlinkAllChildren,taint", rootPrim.LocalID); + bool ret = false; - PhysicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.BSBody); + if (PhysicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.BSBody)) + { + ret = true; + } + return ret; } - */ // Call each of the constraints that make up this linkset and recompute the // various transforms and variables. Used when objects are added or removed @@ -550,11 +532,17 @@ public class BSLinkset { // If this is a multiple object linkset, set everybody's center of mass to the set's center of mass OMV.Vector3 centerOfMass = ComputeLinksetCenterOfMass(); - BulletSimAPI.SetCenterOfMassByPosRot2(LinksetRoot.BSBody.ptr, centerOfMass, OMV.Quaternion.Identity); + BulletSimAPI.SetCenterOfMassByPosRot2(LinksetRoot.BSBody.ptr, + centerOfMass, OMV.Quaternion.Identity); + DetailLog("{0},BSLinkset.RecomputeLinksetConstraintVariables,setCenterOfMass,COM={1},rBody={2}", + LinksetRoot.LocalID, centerOfMass, LinksetRoot.BSBody.ptr.ToString("X")); foreach (BSPhysObject child in m_taintChildren) { - BulletSimAPI.SetCenterOfMassByPosRot2(child.BSBody.ptr, centerOfMass, OMV.Quaternion.Identity); + BulletSimAPI.SetCenterOfMassByPosRot2(child.BSBody.ptr, + centerOfMass, OMV.Quaternion.Identity); } + + // BulletSimAPI.DumpAllInfo2(PhysicsScene.World.ptr); // DEBUG DEBUG DEBUG } return; } @@ -563,7 +551,8 @@ public class BSLinkset // Invoke the detailed logger and output something if it's enabled. private void DetailLog(string msg, params Object[] args) { - PhysicsScene.PhysicsLogging.Write(msg, args); + if (PhysicsScene.PhysicsLogging.Enabled) + PhysicsScene.DetailLog(msg, args); } } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs index 1ac8c59..0665292 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs @@ -207,7 +207,8 @@ public abstract class BSPhysObject : PhysicsActor // High performance detailed logging routine used by the physical objects. protected void DetailLog(string msg, params Object[] args) { - PhysicsScene.PhysicsLogging.Write(msg, args); + if (PhysicsScene.PhysicsLogging.Enabled) + PhysicsScene.DetailLog(msg, args); } } } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index f7b68ba..98a18a1 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs @@ -196,7 +196,7 @@ public sealed class BSPrim : BSPhysObject _isSelected = value; PhysicsScene.TaintedObject("BSPrim.setSelected", delegate() { - // DetailLog("{0},BSPrim.selected,taint,selected={1}", LocalID, _isSelected); + DetailLog("{0},BSPrim.selected,taint,selected={1}", LocalID, _isSelected); SetObjectDynamic(false); }); } @@ -620,8 +620,10 @@ public sealed class BSPrim : BSPhysObject BulletSimAPI.UpdateInertiaTensor2(BSBody.ptr); // There can be special things needed for implementing linksets Linkset.MakeStatic(this); - // The activation state is 'disabled' so Bullet will not try to act on it - BulletSimAPI.ForceActivationState2(BSBody.ptr, ActivationState.DISABLE_SIMULATION); + // The activation state is 'disabled' so Bullet will not try to act on it. + // BulletSimAPI.ForceActivationState2(BSBody.ptr, ActivationState.DISABLE_SIMULATION); + // Start it out sleeping and physical actions could wake it up. + BulletSimAPI.ForceActivationState2(BSBody.ptr, ActivationState.ISLAND_SLEEPING); BSBody.collisionFilter = CollisionFilterGroups.StaticObjectFilter; BSBody.collisionMask = CollisionFilterGroups.StaticObjectMask; @@ -1204,6 +1206,7 @@ public sealed class BSPrim : BSPhysObject { // Called if the current prim body is about to be destroyed. // Remove all the physical dependencies on the old body. + // (Maybe someday make the changing of BSShape an event handled by BSLinkset.) needToRestoreLinkset = Linkset.RemoveBodyDependencies(this); }); diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs index aaed7de..eed915d 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs @@ -254,7 +254,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters // The bounding box for the simulated world. The origin is 0,0,0 unless we're // a child in a mega-region. - // Turns out that Bullet really doesn't care about the extents of the simulated + // Bullet actually doesn't care about the extents of the simulated // area. It tracks active objects no matter where they are. Vector3 worldExtent = new Vector3(Constants.RegionSize, Constants.RegionSize, Constants.RegionHeight); @@ -331,7 +331,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters // Called directly from unmanaged code so don't do much private void BulletLoggerPhysLog(string msg) { - PhysicsLogging.Write("[BULLETS UNMANAGED]:" + msg); + DetailLog("[BULLETS UNMANAGED]:" + msg); } public override void Dispose() @@ -494,8 +494,8 @@ public class BSScene : PhysicsScene, IPhysicsParameters m_simulationStep++; int numSubSteps = 0; - // Sometimes needed for debugging to find out what happened before the step - // PhysicsLogging.Flush(); + // DEBUG + DetailLog("{0},BSScene.Simulate,beforeStep,ntaimts={1},step={2}", DetailLogZero, numTaints, m_simulationStep); try { @@ -715,6 +715,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters { try { + DetailLog("{0},BSScene.ProcessTaints,doTaint,id={1}", DetailLogZero, tcbe.ident); // DEBUG DEBUG DEBUG tcbe.callback(); } catch (Exception e) @@ -1270,6 +1271,8 @@ public class BSScene : PhysicsScene, IPhysicsParameters public void DetailLog(string msg, params Object[] args) { PhysicsLogging.Write(msg, args); + // Add the Flush() if debugging crashes to get all the messages written out. + PhysicsLogging.Flush(); // DEBUG DEBUG DEBUG } // used to fill in the LocalID when there isn't one public const string DetailLogZero = "0000000000"; diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs index 399a133..283b601 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs @@ -136,7 +136,21 @@ public class BSShapeCollection : IDisposable // New entry bodyDesc.ptr = body.ptr; bodyDesc.referenceCount = 1; - DetailLog("{0},BSShapeCollection.ReferenceBody,newBody,ref={1}", body.ID, body, bodyDesc.referenceCount); + DetailLog("{0},BSShapeCollection.ReferenceBody,newBody,ref={2}", + body.ID, body, bodyDesc.referenceCount); + BSScene.TaintCallback createOperation = delegate() + { + if (!BulletSimAPI.IsInWorld2(body.ptr)) + { + BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, body.ptr); + DetailLog("{0},BSShapeCollection.ReferenceBody,addedToWorld,ref={1}", + body.ID, body); + } + }; + if (atTaintTime) + createOperation(); + else + PhysicsScene.TaintedObject("BSShapeCollection.ReferenceBody", createOperation); } bodyDesc.lastReferenced = System.DateTime.Now; Bodies[body.ID] = bodyDesc; @@ -160,21 +174,22 @@ public class BSShapeCollection : IDisposable Bodies[body.ID] = bodyDesc; DetailLog("{0},BSShapeCollection.DereferenceBody,ref={1}", body.ID, bodyDesc.referenceCount); - // If body is no longer being used, free it -- bodies are never shared. + // If body is no longer being used, free it -- bodies can never be shared. if (bodyDesc.referenceCount == 0) { Bodies.Remove(body.ID); BSScene.TaintCallback removeOperation = delegate() { - DetailLog("{0},BSShapeCollection.DereferenceBody,DestroyingBody. ptr={1}", - body.ID, body.ptr.ToString("X")); + DetailLog("{0},BSShapeCollection.DereferenceBody,DestroyingBody. ptr={1}, inTaintTime={2}", + body.ID, body.ptr.ToString("X"), inTaintTime); // If the caller needs to know the old body is going away, pass the event up. if (bodyCallback != null) bodyCallback(body); - // Zero any reference to the shape so it is not freed when the body is deleted. - BulletSimAPI.SetCollisionShape2(PhysicsScene.World.ptr, body.ptr, IntPtr.Zero); // It may have already been removed from the world in which case the next is a NOOP. BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, body.ptr); + + // Zero any reference to the shape so it is not freed when the body is deleted. + BulletSimAPI.SetCollisionShape2(PhysicsScene.World.ptr, body.ptr, IntPtr.Zero); BulletSimAPI.DestroyObject2(PhysicsScene.World.ptr, body.ptr); }; // If already in taint-time, do the operations now. Otherwise queue for later. @@ -208,7 +223,7 @@ public class BSShapeCollection : IDisposable { // There is an existing instance of this mesh. meshDesc.referenceCount++; - DetailLog("{0},BSShapeColliction.ReferenceShape,existingMesh,key={1},cnt={2}", + DetailLog("{0},BSShapeCollection.ReferenceShape,existingMesh,key={1},cnt={2}", BSScene.DetailLogZero, shape.shapeKey.ToString("X"), meshDesc.referenceCount); } else @@ -217,7 +232,7 @@ public class BSShapeCollection : IDisposable meshDesc.ptr = shape.ptr; // We keep a reference to the underlying IMesh data so a hull can be built meshDesc.referenceCount = 1; - DetailLog("{0},BSShapeColliction.ReferenceShape,newMesh,key={1},cnt={2}", + DetailLog("{0},BSShapeCollection.ReferenceShape,newMesh,key={1},cnt={2}", BSScene.DetailLogZero, shape.shapeKey.ToString("X"), meshDesc.referenceCount); ret = true; } @@ -230,7 +245,7 @@ public class BSShapeCollection : IDisposable { // There is an existing instance of this hull. hullDesc.referenceCount++; - DetailLog("{0},BSShapeColliction.ReferenceShape,existingHull,key={1},cnt={2}", + DetailLog("{0},BSShapeCollection.ReferenceShape,existingHull,key={1},cnt={2}", BSScene.DetailLogZero, shape.shapeKey.ToString("X"), hullDesc.referenceCount); } else @@ -238,7 +253,7 @@ public class BSShapeCollection : IDisposable // This is a new reference to a hull hullDesc.ptr = shape.ptr; hullDesc.referenceCount = 1; - DetailLog("{0},BSShapeColliction.ReferenceShape,newHull,key={1},cnt={2}", + DetailLog("{0},BSShapeCollection.ReferenceShape,newHull,key={1},cnt={2}", BSScene.DetailLogZero, shape.shapeKey.ToString("X"), hullDesc.referenceCount); ret = true; @@ -525,7 +540,7 @@ public class BSShapeCollection : IDisposable DetailLog("{0},BSShapeCollection.CreateGeomHull,create,oldKey={1},newKey={2}", prim.LocalID, prim.BSShape.shapeKey.ToString("X"), newHullKey.ToString("X")); - // Remove usage of the previous shape. Also removes reference to underlying mesh if it is a hull. + // Remove usage of the previous shape. DereferenceShape(prim.BSShape, true, shapeCallback); newShape = CreatePhysicalHull(prim.PhysObjectName, newHullKey, pbs, shapeData.Size, lod); @@ -659,6 +674,7 @@ public class BSShapeCollection : IDisposable if (pbs.SculptEntry) lod = PhysicsScene.SculptLOD; + // Mega prims usually get more detail because one can interact with shape approximations at this size. float maxAxis = Math.Max(shapeData.Size.X, Math.Max(shapeData.Size.Y, shapeData.Size.Z)); if (maxAxis > PhysicsScene.MeshMegaPrimThreshold) lod = PhysicsScene.MeshMegaPrimLOD; @@ -709,13 +725,13 @@ public class BSShapeCollection : IDisposable { bodyPtr = BulletSimAPI.CreateBodyFromShape2(sim.ptr, shape.ptr, shapeData.ID, shapeData.Position, shapeData.Rotation); - // DetailLog("{0},BSShapeCollection.CreateBody,mesh,ptr={1}", prim.LocalID, bodyPtr.ToString("X")); + DetailLog("{0},BSShapeCollection.CreateBody,mesh,ptr={1}", prim.LocalID, bodyPtr.ToString("X")); } else { bodyPtr = BulletSimAPI.CreateGhostFromShape2(sim.ptr, shape.ptr, shapeData.ID, shapeData.Position, shapeData.Rotation); - // DetailLog("{0},BSShapeCollection.CreateBody,ghost,ptr={1}", prim.LocalID, bodyPtr.ToString("X")); + DetailLog("{0},BSShapeCollection.CreateBody,ghost,ptr={1}", prim.LocalID, bodyPtr.ToString("X")); } aBody = new BulletBody(shapeData.ID, bodyPtr); @@ -731,7 +747,8 @@ public class BSShapeCollection : IDisposable private void DetailLog(string msg, params Object[] args) { - PhysicsScene.PhysicsLogging.Write(msg, args); + if (PhysicsScene.PhysicsLogging.Enabled) + PhysicsScene.DetailLog(msg, args); } } } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs index a43880d..bb4d399 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs @@ -192,8 +192,9 @@ public struct ShapeData SHAPE_SPHERE = 5, SHAPE_MESH = 6, SHAPE_HULL = 7, - SHAPE_GROUNDPLANE = 8, - SHAPE_TERRAIN = 9, + // following defined by BulletSim + SHAPE_GROUNDPLANE = 20, + SHAPE_TERRAIN = 21, }; public uint ID; public PhysicsShapeType Type; @@ -1108,6 +1109,15 @@ public static extern float GetMargin2(IntPtr shape); public static extern void DumpRigidBody2(IntPtr sim, IntPtr collisionObject); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern void DumpCollisionShape2(IntPtr sim, IntPtr collisionShape); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern void DumpConstraint2(IntPtr sim, IntPtr constrain); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern void DumpAllInfo2(IntPtr sim); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern void DumpMapInfo2(IntPtr sim, IntPtr manInfo); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -- cgit v1.1 From 68698975f1537725a1f53bc4b2db2cfc798ac7f3 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Tue, 9 Oct 2012 12:58:06 -0700 Subject: BulletSim: Add Force* operations to objects to allow direct push to engine. Update BSDynamics to use same (don't want to delay updates til next taint-time. Suppress queuing a taint update for position and orientation calls if value does not change. Move Bullet timing statistics call from C# back to C++ code. Throttle taints per simulation step and add parameter to set. By default, don't create hulls for physical objects. Add a parameter to turn on and off. --- .../Region/Physics/BulletSPlugin/BSCharacter.cs | 11 ++++ OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs | 12 ++-- .../Region/Physics/BulletSPlugin/BSPhysObject.cs | 4 ++ OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | 33 +++++++++-- OpenSim/Region/Physics/BulletSPlugin/BSScene.cs | 65 ++++++++++++++++------ .../Physics/BulletSPlugin/BSShapeCollection.cs | 2 +- .../Region/Physics/BulletSPlugin/BulletSimAPI.cs | 2 + 7 files changed, 100 insertions(+), 29 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs index 2a52e01..c23ccd5 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs @@ -332,6 +332,13 @@ public class BSCharacter : BSPhysObject }); } } + public override OMV.Vector3 ForceVelocity { + get { return _velocity; } + set { + _velocity = value; + BulletSimAPI.SetObjectVelocity(PhysicsScene.WorldID, LocalID, _velocity); + } + } public override OMV.Vector3 Torque { get { return _torque; } set { _torque = value; @@ -432,6 +439,10 @@ public class BSCharacter : BSPhysObject get { return _rotationalVelocity; } set { _rotationalVelocity = value; } } + public override OMV.Vector3 ForceRotationalVelocity { + get { return _rotationalVelocity; } + set { _rotationalVelocity = value; } + } public override bool Kinematic { get { return _kinematic; } set { _kinematic = value; } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs index 3fb2253..76230a1 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs @@ -481,7 +481,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin m_lastPositionVector = Prim.ForcePosition; VDetailLog("{0},BSDynamics.Step,done,pos={1},force={2},velocity={3},angvel={4}", - Prim.LocalID, Prim.Position, Prim.Force, Prim.Velocity, Prim.RotationalVelocity); + Prim.LocalID, Prim.ForcePosition, Prim.Force, Prim.ForceVelocity, Prim.RotationalVelocity); }// end Step // Apply the effect of the linear motor. @@ -540,7 +540,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin // add Gravity and Buoyancy // There is some gravity, make a gravity force vector that is applied after object velocity. // m_VehicleBuoyancy: -1=2g; 0=1g; 1=0g; - Vector3 grav = Prim.PhysicsScene.DefaultGravity * (Prim.Mass * (1f - m_VehicleBuoyancy)); + Vector3 grav = Prim.PhysicsScene.DefaultGravity * (Prim.MassRaw * (1f - m_VehicleBuoyancy)); /* * RA: Not sure why one would do this @@ -678,10 +678,10 @@ namespace OpenSim.Region.Physics.BulletSPlugin m_newVelocity.Z = 0; // Apply velocity - Prim.Velocity = m_newVelocity; + Prim.ForceVelocity = m_newVelocity; // apply gravity force // Why is this set here? The physics engine already does gravity. - // m_prim.AddForce(grav, false); + Prim.AddForce(grav, false); // Apply friction Vector3 keepFraction = Vector3.One - (Vector3.One / (m_linearFrictionTimescale / pTimestep)); @@ -704,7 +704,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin // m_lastAngularVelocity // what was last applied to body // Get what the body is doing, this includes 'external' influences - Vector3 angularVelocity = Prim.RotationalVelocity; + Vector3 angularVelocity = Prim.ForceRotationalVelocity; if (m_angularMotorApply > 0) { @@ -810,7 +810,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin m_lastAngularVelocity -= m_lastAngularVelocity * decayamount; // Apply to the body - Prim.RotationalVelocity = m_lastAngularVelocity; + Prim.ForceRotationalVelocity = m_lastAngularVelocity; VDetailLog("{0},MoveAngular,done,decay={1},lastAngular={2}", Prim.LocalID, decayamount, m_lastAngularVelocity); } //end MoveAngular diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs index 0665292..cae599c 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs @@ -85,6 +85,10 @@ public abstract class BSPhysObject : PhysicsActor public abstract OMV.Quaternion ForceOrientation { get; set; } + public abstract OMV.Vector3 ForceVelocity { get; set; } + + public abstract OMV.Vector3 ForceRotationalVelocity { get; set; } + #region Collisions // Requested number of milliseconds between collision events. Zero means disabled. diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index 98a18a1..d408be0 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs @@ -265,6 +265,11 @@ public sealed class BSPrim : BSPhysObject return _position; } set { + // If you must push the position into the physics engine, use ForcePosition. + if (_position == value) + { + return; + } _position = value; // TODO: what does it mean to set the position of a child prim?? Rebuild the constraint? PositionSanityCheck(); @@ -453,7 +458,6 @@ public sealed class BSPrim : BSPhysObject } return; } - public override OMV.Vector3 Velocity { get { return _velocity; } set { @@ -465,6 +469,13 @@ public sealed class BSPrim : BSPhysObject }); } } + public override OMV.Vector3 ForceVelocity { + get { return _velocity; } + set { + _velocity = value; + BulletSimAPI.SetLinearVelocity2(BSBody.ptr, _velocity); + } + } public override OMV.Vector3 Torque { get { return _torque; } set { _torque = value; @@ -490,6 +501,8 @@ public sealed class BSPrim : BSPhysObject return _orientation; } set { + if (_orientation == value) + return; _orientation = value; // TODO: what does it mean if a child in a linkset changes its orientation? Rebuild the constraint? PhysicsScene.TaintedObject("BSPrim.setOrientation", delegate() @@ -621,9 +634,9 @@ public sealed class BSPrim : BSPhysObject // There can be special things needed for implementing linksets Linkset.MakeStatic(this); // The activation state is 'disabled' so Bullet will not try to act on it. - // BulletSimAPI.ForceActivationState2(BSBody.ptr, ActivationState.DISABLE_SIMULATION); + BulletSimAPI.ForceActivationState2(BSBody.ptr, ActivationState.DISABLE_SIMULATION); // Start it out sleeping and physical actions could wake it up. - BulletSimAPI.ForceActivationState2(BSBody.ptr, ActivationState.ISLAND_SLEEPING); + // BulletSimAPI.ForceActivationState2(BSBody.ptr, ActivationState.ISLAND_SLEEPING); BSBody.collisionFilter = CollisionFilterGroups.StaticObjectFilter; BSBody.collisionMask = CollisionFilterGroups.StaticObjectMask; @@ -640,6 +653,9 @@ public sealed class BSPrim : BSPhysObject // per http://www.bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=3382 BulletSimAPI.ClearAllForces2(BSBody.ptr); + // For good measure, make sure the transform is set through to the motion state + BulletSimAPI.SetTranslation2(BSBody.ptr, _position, _orientation); + // A dynamic object has mass IntPtr collisionShapePtr = BulletSimAPI.GetCollisionShape2(BSBody.ptr); OMV.Vector3 inertia = BulletSimAPI.CalculateLocalInertia2(collisionShapePtr, Mass); @@ -776,6 +792,15 @@ public sealed class BSPrim : BSPhysObject }); } } + public override OMV.Vector3 ForceRotationalVelocity { + get { + return _rotationalVelocity; + } + set { + _rotationalVelocity = value; + BulletSimAPI.SetAngularVelocity2(BSBody.ptr, _rotationalVelocity); + } + } public override bool Kinematic { get { return _kinematic; } set { _kinematic = value; @@ -1307,7 +1332,7 @@ public sealed class BSPrim : BSPhysObject /* else { - // For debugging, we can also report the movement of children + // For debugging, report the movement of children DetailLog("{0},BSPrim.UpdateProperties,child,pos={1},orient={2},vel={3},accel={4},rotVel={5}", LocalID, entprop.Position, entprop.Rotation, entprop.Velocity, entprop.Acceleration, entprop.RotationalVelocity); diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs index eed915d..33ac116 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs @@ -90,10 +90,6 @@ public class BSScene : PhysicsScene, IPhysicsParameters // let my minuions use my logger public ILog Logger { get { return m_log; } } - // If non-zero, the number of simulation steps between calls to the physics - // engine to output detailed physics stats. Debug logging level must be on also. - private int m_detailedStatsStep = 0; - public IMesher mesher; // Level of Detail values kept as float because that's what the Meshmerizer wants public float MeshLOD { get; private set; } @@ -112,6 +108,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters private float m_fixedTimeStep; private long m_simulationStep = 0; public long SimulationStep { get { return m_simulationStep; } } + private int m_taintsToProcessPerStep; // A value of the time now so all the collision and update routines do not have to get their own // Set to 'now' just before all the prims and actors are called for collisions and updates @@ -131,6 +128,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters public bool ShouldMeshSculptedPrim { get; private set; } // cause scuplted prims to get meshed public bool ShouldForceSimplePrimMeshing { get; private set; } // if a cube or sphere, let Bullet do internal shapes + public bool ShouldUseHullsForPhysicalObjects { get; private set; } // 'true' if should create hulls for physical objects public float PID_D { get; private set; } // derivative public float PID_P { get; private set; } // proportional @@ -582,15 +580,6 @@ public class BSScene : PhysicsScene, IPhysicsParameters } } - // If enabled, call into the physics engine to dump statistics - if (m_detailedStatsStep > 0) - { - if ((m_simulationStep % m_detailedStatsStep) == 0) - { - BulletSimAPI.DumpBulletStatistics(); - } - } - // The physics engine returns the number of milliseconds it simulated this call. // These are summed and normalized to one second and divided by 1000 to give the reported physics FPS. // Since Bullet normally does 5 or 6 substeps, this will normally sum to about 60 FPS. @@ -617,7 +606,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters BSPhysObject collidee = null; PhysObjects.TryGetValue(collidingWith, out collidee); - DetailLog("{0},BSScene.SendCollision,collide,id={1},with={2}", DetailLogZero, localID, collidingWith); + // DetailLog("{0},BSScene.SendCollision,collide,id={1},with={2}", DetailLogZero, localID, collidingWith); if (collider.Collide(collidingWith, collidee, collidePoint, collideNormal, penetration)) { @@ -704,6 +693,35 @@ public class BSScene : PhysicsScene, IPhysicsParameters if (_taintedObjects.Count > 0) // save allocating new list if there is nothing to process { // swizzle a new list into the list location so we can process what's there + int taintCount = m_taintsToProcessPerStep; + TaintCallbackEntry oneCallback = new TaintCallbackEntry(); + while (_taintedObjects.Count > 0 && taintCount-- > 0) + { + bool gotOne = false; + lock (_taintLock) + { + if (_taintedObjects.Count > 0) + { + oneCallback = _taintedObjects[0]; + _taintedObjects.RemoveAt(0); + gotOne = true; + } + } + if (gotOne) + { + try + { + DetailLog("{0},BSScene.ProcessTaints,doTaint,id={1}", DetailLogZero, oneCallback.ident); // DEBUG DEBUG DEBUG + oneCallback.callback(); + } + catch (Exception e) + { + m_log.ErrorFormat("{0}: ProcessTaints: {1}: Exception: {2}", LogHeader, oneCallback.ident, e); + } + } + } + /* + // swizzle a new list into the list location so we can process what's there List oldList; lock (_taintLock) { @@ -724,6 +742,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters } } oldList.Clear(); + */ } } @@ -835,6 +854,11 @@ public class BSScene : PhysicsScene, IPhysicsParameters (s,cf,p,v) => { s.ShouldForceSimplePrimMeshing = cf.GetBoolean(p, s.BoolNumeric(v)); }, (s) => { return s.NumericBool(s.ShouldForceSimplePrimMeshing); }, (s,p,l,v) => { s.ShouldForceSimplePrimMeshing = s.BoolNumeric(v); } ), + new ParameterDefn("UseHullsForPhysicalObjects", "If true, create hulls for physical objects", + ConfigurationParameters.numericFalse, + (s,cf,p,v) => { s.ShouldUseHullsForPhysicalObjects = cf.GetBoolean(p, s.BoolNumeric(v)); }, + (s) => { return s.NumericBool(s.ShouldUseHullsForPhysicalObjects); }, + (s,p,l,v) => { s.ShouldUseHullsForPhysicalObjects = s.BoolNumeric(v); } ), new ParameterDefn("MeshLevelOfDetail", "Level of detail to render meshes (32, 16, 8 or 4. 32=most detailed)", 8f, @@ -877,6 +901,11 @@ public class BSScene : PhysicsScene, IPhysicsParameters (s,cf,p,v) => { s.m_maxUpdatesPerFrame = cf.GetInt(p, (int)v); }, (s) => { return (float)s.m_maxUpdatesPerFrame; }, (s,p,l,v) => { s.m_maxUpdatesPerFrame = (int)v; } ), + new ParameterDefn("MaxTaintsToProcessPerStep", "Number of update taints to process before each simulation step", + 100f, + (s,cf,p,v) => { s.m_taintsToProcessPerStep = cf.GetInt(p, (int)v); }, + (s) => { return (float)s.m_taintsToProcessPerStep; }, + (s,p,l,v) => { s.m_taintsToProcessPerStep = (int)v; } ), new ParameterDefn("MaxObjectMass", "Maximum object mass (10000.01)", 10000.01f, (s,cf,p,v) => { s.MaximumObjectMass = cf.GetFloat(p, v); }, @@ -1086,11 +1115,11 @@ public class BSScene : PhysicsScene, IPhysicsParameters (s) => { return s.m_params[0].linkConstraintSolverIterations; }, (s,p,l,v) => { s.m_params[0].linkConstraintSolverIterations = v; } ), - new ParameterDefn("DetailedStats", "Frames between outputting detailed phys stats. (0 is off)", + new ParameterDefn("LogPhysicsStatisticsFrames", "Frames between outputting detailed phys stats. (0 is off)", 0f, - (s,cf,p,v) => { s.m_detailedStatsStep = cf.GetInt(p, (int)v); }, - (s) => { return (float)s.m_detailedStatsStep; }, - (s,p,l,v) => { s.m_detailedStatsStep = (int)v; } ), + (s,cf,p,v) => { s.m_params[0].physicsLoggingFrames = cf.GetInt(p, (int)v); }, + (s) => { return (float)s.m_params[0].physicsLoggingFrames; }, + (s,p,l,v) => { s.m_params[0].physicsLoggingFrames = (int)v; } ), }; // Convert a boolean to our numeric true and false values diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs index 283b601..e619b48 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs @@ -407,7 +407,7 @@ public class BSShapeCollection : IDisposable // made. Native shapes are best used in either case. if (!haveShape) { - if (prim.IsPhysical) + if (prim.IsPhysical && PhysicsScene.ShouldUseHullsForPhysicalObjects) { // Update prim.BSShape to reference a hull of this shape. ret = GetReferenceToHull(prim, shapeData, pbs, shapeCallback); diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs index bb4d399..7a60afb 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs @@ -306,6 +306,8 @@ public struct ConfigurationParameters public float linkConstraintCFM; public float linkConstraintSolverIterations; + public float physicsLoggingFrames; + public const float numericTrue = 1f; public const float numericFalse = 0f; } -- cgit v1.1 From a791620622dc0a67a6af2c4a9c011d9057360411 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Wed, 10 Oct 2012 08:02:37 -0700 Subject: BulletSim: cosmetic changes (comments and renaming). Give mass to terrain to improve interactions. --- .../Region/Physics/BulletSPlugin/BSCharacter.cs | 4 +- OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs | 55 +++++++++++++++------- OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | 10 ++-- OpenSim/Region/Physics/BulletSPlugin/BSScene.cs | 9 ++-- .../Physics/BulletSPlugin/BSShapeCollection.cs | 31 ++++++------ .../Physics/BulletSPlugin/BSTerrainManager.cs | 14 +++--- .../Region/Physics/BulletSPlugin/BulletSimAPI.cs | 3 +- 7 files changed, 74 insertions(+), 52 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs index c23ccd5..2e6b2da 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs @@ -263,7 +263,7 @@ public class BSCharacter : BSPhysObject // A version of the sanity check that also makes sure a new position value is // pushed back to the physics engine. This routine would be used by anyone // who is not already pushing the value. - private bool PositionSanityCheck2(bool atTaintTime) + private bool PositionSanityCheck2(bool inTaintTime) { bool ret = false; if (PositionSanityCheck()) @@ -275,7 +275,7 @@ public class BSCharacter : BSPhysObject DetailLog("{0},BSCharacter.PositionSanityCheck,taint,pos={1},orient={2}", LocalID, _position, _orientation); BulletSimAPI.SetObjectTranslation(PhysicsScene.WorldID, LocalID, _position, _orientation); }; - if (atTaintTime) + if (inTaintTime) sanityOperation(); else PhysicsScene.TaintedObject("BSCharacter.PositionSanityCheck", sanityOperation); diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs index 20db4de..b84ccdc 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs @@ -160,6 +160,31 @@ public class BSLinkset return ret; } + // When physical properties are changed the linkset needs to recalculate + // its internal properties. + // May be called at runtime or taint-time (just pass the appropriate flag). + public void Refresh(BSPhysObject requestor, bool inTaintTime) + { + // If there are no children, there can't be any constraints to recompute + if (!HasAnyChildren) + return; + + // Only the root does the recomputation + if (IsRoot(requestor)) + { + BSScene.TaintCallback refreshOperation = delegate() + { + RecomputeLinksetConstraintVariables(); + DetailLog("{0},BSLinkset.Refresh,complete,rBody={1}", + LinksetRoot.LocalID, LinksetRoot.BSBody.ptr.ToString("X")); + }; + if (inTaintTime) + refreshOperation(); + else + PhysicsScene.TaintedObject("BSLinkSet.Refresh", refreshOperation); + } + } + // The object is going dynamic (physical). Do any setup necessary // for a dynamic linkset. // Only the state of the passed object can be modified. The rest of the linkset @@ -182,24 +207,19 @@ public class BSLinkset return false; } - // When physical properties are changed the linkset needs to recalculate - // its internal properties. - // Called at runtime. - public void Refresh(BSPhysObject requestor) + // If the software is handling the movement of all the objects in a linkset + // (like if one doesn't use constraints for static linksets), this is called + // when an update for the root of the linkset is received. + // Called at taint-time!! + public void UpdateProperties(BSPhysObject physObject) { - // If there are no children, there can't be any constraints to recompute - if (!HasAnyChildren) - return; - - // Only the root does the recomputation - if (IsRoot(requestor)) + // The root local properties have been updated. Apply to the children if appropriate. + if (IsRoot(physObject) && HasAnyChildren) { - PhysicsScene.TaintedObject("BSLinkSet.Refresh", delegate() + if (!physObject.IsPhysical) { - RecomputeLinksetConstraintVariables(); - DetailLog("{0},BSLinkset.Refresh,complete,rBody={1}", - LinksetRoot.LocalID, LinksetRoot.BSBody.ptr.ToString("X")); - }); + // TODO: implement software linkset update for static object linksets + } } } @@ -236,9 +256,8 @@ public class BSLinkset return ret; } - // Routine used when rebuilding the body of the root of the linkset - // This is called after RemoveAllLinksToRoot() to restore all the constraints. - // This is called when the root body has been changed. + // Companion to RemoveBodyDependencies(). If RemoveBodyDependencies() returns 'true', + // this routine will restore the removed constraints. // Called at taint-time!! public void RestoreBodyDependencies(BSPrim child) { diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index d408be0..b26f049 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs @@ -327,7 +327,7 @@ public sealed class BSPrim : BSPhysObject // A version of the sanity check that also makes sure a new position value is // pushed back to the physics engine. This routine would be used by anyone // who is not already pushing the value. - private bool PositionSanityCheck2(bool atTaintTime) + private bool PositionSanityCheck2(bool inTaintTime) { bool ret = false; if (PositionSanityCheck()) @@ -339,7 +339,7 @@ public sealed class BSPrim : BSPhysObject DetailLog("{0},BSPrim.PositionSanityCheck,taint,pos={1},orient={2}", LocalID, _position, _orientation); BulletSimAPI.SetObjectTranslation(PhysicsScene.WorldID, LocalID, _position, _orientation); }; - if (atTaintTime) + if (inTaintTime) sanityOperation(); else PhysicsScene.TaintedObject("BSPrim.PositionSanityCheck", sanityOperation); @@ -583,7 +583,7 @@ public sealed class BSPrim : BSPhysObject // Set up the object physicalness (does gravity and collisions move this object) MakeDynamic(IsStatic); - // Update vehicle specific parameters + // Update vehicle specific parameters (after MakeDynamic() so can change physical parameters) _vehicle.Refresh(); // Arrange for collision events if the simulator wants them @@ -606,7 +606,7 @@ public sealed class BSPrim : BSPhysObject // Recompute any linkset parameters. // When going from non-physical to physical, this re-enables the constraints that // had been automatically disabled when the mass was set to zero. - Linkset.Refresh(this); + Linkset.Refresh(this, true); DetailLog("{0},BSPrim.UpdatePhysicalParameters,exit,static={1},solid={2},mass={3},collide={4},cf={5:X},body={6},shape={7}", LocalID, IsStatic, IsSolid, _mass, SubscribedEvents(), CurrentCollisionFlags, BSBody, BSShape); @@ -1322,6 +1322,8 @@ public sealed class BSPrim : BSPhysObject PositionSanityCheck2(true); + Linkset.UpdateProperties(this); + DetailLog("{0},BSPrim.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5}", LocalID, _position, _orientation, _velocity, _acceleration, _rotationalVelocity); diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs index 33ac116..50091cc 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs @@ -39,7 +39,6 @@ using log4net; using OpenMetaverse; // TODOs for BulletSim (for BSScene, BSPrim, BSCharacter and BulletSim) -// Move all logic out of the C++ code and into the C# code for easier future modifications. // Test sculpties (verified that they don't work) // Compute physics FPS reasonably // Based on material, set density and friction @@ -493,7 +492,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters int numSubSteps = 0; // DEBUG - DetailLog("{0},BSScene.Simulate,beforeStep,ntaimts={1},step={2}", DetailLogZero, numTaints, m_simulationStep); + // DetailLog("{0},BSScene.Simulate,beforeStep,ntaimts={1},step={2}", DetailLogZero, numTaints, m_simulationStep); try { @@ -503,8 +502,8 @@ public class BSScene : PhysicsScene, IPhysicsParameters out updatedEntityCount, out updatedEntitiesPtr, out collidersCount, out collidersPtr); if (PhysicsLogging.Enabled) simTime = Util.EnvironmentTickCountSubtract(beforeTime); - DetailLog("{0},Simulate,call, nTaints={1}, simTime={2}, substeps={3}, updates={4}, colliders={5}", - DetailLogZero, numTaints, simTime, numSubSteps, updatedEntityCount, collidersCount); + DetailLog("{0},Simulate,call, frame={1}, nTaints={2}, simTime={3}, substeps={4}, updates={5}, colliders={6}", + DetailLogZero, m_simulationStep, numTaints, simTime, numSubSteps, updatedEntityCount, collidersCount); } catch (Exception e) { @@ -855,7 +854,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters (s) => { return s.NumericBool(s.ShouldForceSimplePrimMeshing); }, (s,p,l,v) => { s.ShouldForceSimplePrimMeshing = s.BoolNumeric(v); } ), new ParameterDefn("UseHullsForPhysicalObjects", "If true, create hulls for physical objects", - ConfigurationParameters.numericFalse, + ConfigurationParameters.numericTrue, (s,cf,p,v) => { s.ShouldUseHullsForPhysicalObjects = cf.GetBoolean(p, s.BoolNumeric(v)); }, (s) => { return s.NumericBool(s.ShouldUseHullsForPhysicalObjects); }, (s,p,l,v) => { s.ShouldUseHullsForPhysicalObjects = s.BoolNumeric(v); } ), diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs index e619b48..d5e2172 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs @@ -67,8 +67,8 @@ public class BSShapeCollection : IDisposable public DateTime lastReferenced; } - private Dictionary Meshes = new Dictionary(); - private Dictionary Hulls = new Dictionary(); + private Dictionary Meshes = new Dictionary(); + private Dictionary Hulls = new Dictionary(); private Dictionary Bodies = new Dictionary(); public BSShapeCollection(BSScene physScene) @@ -121,7 +121,7 @@ public class BSShapeCollection : IDisposable // Track another user of a body // We presume the caller has allocated the body. // Bodies only have one user so the reference count is either 1 or 0. - public void ReferenceBody(BulletBody body, bool atTaintTime) + public void ReferenceBody(BulletBody body, bool inTaintTime) { lock (m_collectionActivityLock) { @@ -147,7 +147,7 @@ public class BSShapeCollection : IDisposable body.ID, body); } }; - if (atTaintTime) + if (inTaintTime) createOperation(); else PhysicsScene.TaintedObject("BSShapeCollection.ReferenceBody", createOperation); @@ -272,7 +272,7 @@ public class BSShapeCollection : IDisposable // Release the usage of a shape. // The collisionObject is released since it is a copy of the real collision shape. - public void DereferenceShape(BulletShape shape, bool atTaintTime, ShapeDestructionCallback shapeCallback) + public void DereferenceShape(BulletShape shape, bool inTaintTime, ShapeDestructionCallback shapeCallback) { if (shape.ptr == IntPtr.Zero) return; @@ -294,14 +294,14 @@ public class BSShapeCollection : IDisposable if (shape.ptr != IntPtr.Zero & shape.isNativeShape) { DetailLog("{0},BSShapeCollection.DereferenceShape,deleteNativeShape,ptr={1},taintTime={2}", - BSScene.DetailLogZero, shape.ptr.ToString("X"), atTaintTime); + BSScene.DetailLogZero, shape.ptr.ToString("X"), inTaintTime); if (shapeCallback != null) shapeCallback(shape); BulletSimAPI.DeleteCollisionShape2(PhysicsScene.World.ptr, shape.ptr); } break; } }; - if (atTaintTime) + if (inTaintTime) { lock (m_collectionActivityLock) { @@ -441,7 +441,7 @@ public class BSShapeCollection : IDisposable // Native shapes are always built independently. newShape = new BulletShape(BulletSimAPI.BuildNativeShape2(PhysicsScene.World.ptr, shapeData), shapeType); - newShape.shapeKey = (ulong)shapeKey; + newShape.shapeKey = (System.UInt64)shapeKey; newShape.isNativeShape = true; // Don't need to do a 'ReferenceShape()' here because native shapes are not tracked. @@ -461,7 +461,7 @@ public class BSShapeCollection : IDisposable BulletShape newShape = new BulletShape(IntPtr.Zero); float lod; - ulong newMeshKey = ComputeShapeKey(shapeData, pbs, out lod); + System.UInt64 newMeshKey = ComputeShapeKey(shapeData, pbs, out lod); // if this new shape is the same as last time, don't recreate the mesh if (newMeshKey == prim.BSShape.shapeKey && prim.BSShape.type == ShapeData.PhysicsShapeType.SHAPE_MESH) @@ -484,7 +484,7 @@ public class BSShapeCollection : IDisposable return true; // 'true' means a new shape has been added to this prim } - private BulletShape CreatePhysicalMesh(string objName, ulong newMeshKey, PrimitiveBaseShape pbs, OMV.Vector3 size, float lod) + private BulletShape CreatePhysicalMesh(string objName, System.UInt64 newMeshKey, PrimitiveBaseShape pbs, OMV.Vector3 size, float lod) { IMesh meshData = null; IntPtr meshPtr; @@ -531,7 +531,7 @@ public class BSShapeCollection : IDisposable BulletShape newShape; float lod; - ulong newHullKey = ComputeShapeKey(shapeData, pbs, out lod); + System.UInt64 newHullKey = ComputeShapeKey(shapeData, pbs, out lod); // if the hull hasn't changed, don't rebuild it if (newHullKey == prim.BSShape.shapeKey && prim.BSShape.type == ShapeData.PhysicsShapeType.SHAPE_HULL) @@ -554,7 +554,7 @@ public class BSShapeCollection : IDisposable } List m_hulls; - private BulletShape CreatePhysicalHull(string objName, ulong newHullKey, PrimitiveBaseShape pbs, OMV.Vector3 size, float lod) + private BulletShape CreatePhysicalHull(string objName, System.UInt64 newHullKey, PrimitiveBaseShape pbs, OMV.Vector3 size, float lod) { IntPtr hullPtr; @@ -667,7 +667,7 @@ public class BSShapeCollection : IDisposable // Create a hash of all the shape parameters to be used as a key // for this particular shape. - private ulong ComputeShapeKey(ShapeData shapeData, PrimitiveBaseShape pbs, out float retLod) + private System.UInt64 ComputeShapeKey(ShapeData shapeData, PrimitiveBaseShape pbs, out float retLod) { // level of detail based on size and type of the object float lod = PhysicsScene.MeshLOD; @@ -680,10 +680,10 @@ public class BSShapeCollection : IDisposable lod = PhysicsScene.MeshMegaPrimLOD; retLod = lod; - return (ulong)pbs.GetMeshKey(shapeData.Size, lod); + return pbs.GetMeshKey(shapeData.Size, lod); } // For those who don't want the LOD - private ulong ComputeShapeKey(ShapeData shapeData, PrimitiveBaseShape pbs) + private System.UInt64 ComputeShapeKey(ShapeData shapeData, PrimitiveBaseShape pbs) { float lod; return ComputeShapeKey(shapeData, pbs, out lod); @@ -717,6 +717,7 @@ public class BSShapeCollection : IDisposable if (mustRebuild || forceRebuild) { + // Free any old body DereferenceBody(prim.BSBody, true, bodyCallback); BulletBody aBody; diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs index 70aa429..2808603 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs @@ -201,10 +201,10 @@ public class BSTerrainManager // The 'doNow' boolean says whether to do all the unmanaged activities right now (like when // calling this routine from initialization or taint-time routines) or whether to delay // all the unmanaged activities to taint-time. - private void UpdateOrCreateTerrain(uint id, float[] heightMap, Vector3 minCoords, Vector3 maxCoords, bool atTaintTime) + private void UpdateOrCreateTerrain(uint id, float[] heightMap, Vector3 minCoords, Vector3 maxCoords, bool inTaintTime) { - DetailLog("{0},BSTerrainManager.UpdateOrCreateTerrain,call,minC={1},maxC={2},atTaintTime={3}", - BSScene.DetailLogZero, minCoords, maxCoords, atTaintTime); + DetailLog("{0},BSTerrainManager.UpdateOrCreateTerrain,call,minC={1},maxC={2},inTaintTime={3}", + BSScene.DetailLogZero, minCoords, maxCoords, inTaintTime); float minZ = float.MaxValue; float maxZ = float.MinValue; @@ -320,7 +320,9 @@ public class BSTerrainManager BulletSimAPI.SetRestitution2(mapInfo.terrainBody.ptr, PhysicsScene.Params.terrainRestitution); BulletSimAPI.SetCollisionFlags2(mapInfo.terrainBody.ptr, CollisionFlags.CF_STATIC_OBJECT); - BulletSimAPI.SetMassProps2(mapInfo.terrainBody.ptr, 0f, Vector3.Zero); + float terrainMass = 1000; + Vector3 localInertia = BulletSimAPI.CalculateLocalInertia2(mapInfo.terrainBody.ptr, terrainMass); + BulletSimAPI.SetMassProps2(mapInfo.terrainBody.ptr, terrainMass, localInertia); BulletSimAPI.UpdateInertiaTensor2(mapInfo.terrainBody.ptr); // Return the new terrain to the world of physical objects @@ -342,7 +344,7 @@ public class BSTerrainManager // There is the option to do the changes now (we're already in 'taint time'), or // to do the Bullet operations later. - if (atTaintTime) + if (inTaintTime) rebuildOperation(); else PhysicsScene.TaintedObject("BSScene.UpdateOrCreateTerrain:UpdateExisting", rebuildOperation); @@ -381,7 +383,7 @@ public class BSTerrainManager }; // If already in taint-time, just call Bullet. Otherwise queue the operations for the safe time. - if (atTaintTime) + if (inTaintTime) createOperation(); else PhysicsScene.TaintedObject("BSScene.UpdateOrCreateTerrain:NewTerrain", createOperation); diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs index 7a60afb..e23fe5a 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs @@ -101,9 +101,8 @@ public struct BulletShape } public IntPtr ptr; public ShapeData.PhysicsShapeType type; - public ulong shapeKey; + public System.UInt64 shapeKey; public bool isNativeShape; - // Hulls have an underlying mesh. A pointer to it is hidden here. public override string ToString() { StringBuilder buff = new StringBuilder(); -- cgit v1.1 From 919569f6ecd5fe84d0f5b0981a48b4808a44f7ad Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Wed, 10 Oct 2012 09:43:46 -0700 Subject: BulletSim: Change defaults for constraint CFM and ERP to make large linksets more rigid. Remove mass calculation for terrain (it should stay a static object). --- OpenSim/Region/Physics/BulletSPlugin/BSScene.cs | 4 ++-- OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs | 15 ++++++--------- 2 files changed, 8 insertions(+), 11 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs index 50091cc..617bdb4 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs @@ -1099,12 +1099,12 @@ public class BSScene : PhysicsScene, IPhysicsParameters (s) => { return s.m_params[0].linkConstraintTransMotorMaxForce; }, (s,p,l,v) => { s.m_params[0].linkConstraintTransMotorMaxForce = v; } ), new ParameterDefn("LinkConstraintCFM", "Amount constraint can be violated. 0=no violation, 1=infinite. Default=0.1", - 0.1f, + 0.001f, (s,cf,p,v) => { s.m_params[0].linkConstraintCFM = cf.GetFloat(p, v); }, (s) => { return s.m_params[0].linkConstraintCFM; }, (s,p,l,v) => { s.m_params[0].linkConstraintCFM = v; } ), new ParameterDefn("LinkConstraintERP", "Amount constraint is corrected each tick. 0=none, 1=all. Default = 0.2", - 0.2f, + 0.8f, (s,cf,p,v) => { s.m_params[0].linkConstraintERP = cf.GetFloat(p, v); }, (s) => { return s.m_params[0].linkConstraintERP; }, (s,p,l,v) => { s.m_params[0].linkConstraintERP = v; } ), diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs index 2808603..caf411e 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs @@ -114,6 +114,8 @@ public class BSTerrainManager BulletSimAPI.CreateBodyWithDefaultMotionState2(groundPlaneShape.ptr, BSScene.GROUNDPLANE_ID, Vector3.Zero, Quaternion.Identity)); BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, m_groundPlane.ptr); + // Ground plane does not move + BulletSimAPI.ForceActivationState2(m_groundPlane.ptr, ActivationState.DISABLE_SIMULATION); // Everything collides with the ground plane. BulletSimAPI.SetCollisionFilterMask2(m_groundPlane.ptr, (uint)CollisionFilterGroups.GroundPlaneFilter, (uint)CollisionFilterGroups.GroundPlaneMask); @@ -296,16 +298,16 @@ public class BSTerrainManager mapInfo.Ptr = BulletSimAPI.CreateHeightMapInfo2(PhysicsScene.World.ptr, mapInfo.ID, mapInfo.minCoords, mapInfo.maxCoords, mapInfo.heightMap, TERRAIN_COLLISION_MARGIN); + // Create the terrain shape from the mapInfo + mapInfo.terrainShape = new BulletShape(BulletSimAPI.CreateTerrainShape2(mapInfo.Ptr), + ShapeData.PhysicsShapeType.SHAPE_TERRAIN); + // The terrain object initial position is at the center of the object Vector3 centerPos; centerPos.X = minCoords.X + (mapInfo.sizeX / 2f); centerPos.Y = minCoords.Y + (mapInfo.sizeY / 2f); centerPos.Z = minZ + ((maxZ - minZ) / 2f); - // Create the terrain shape from the mapInfo - mapInfo.terrainShape = new BulletShape(BulletSimAPI.CreateTerrainShape2(mapInfo.Ptr), - ShapeData.PhysicsShapeType.SHAPE_TERRAIN); - mapInfo.terrainBody = new BulletBody(mapInfo.ID, BulletSimAPI.CreateBodyWithDefaultMotionState2(mapInfo.terrainShape.ptr, id, centerPos, Quaternion.Identity)); @@ -320,11 +322,6 @@ public class BSTerrainManager BulletSimAPI.SetRestitution2(mapInfo.terrainBody.ptr, PhysicsScene.Params.terrainRestitution); BulletSimAPI.SetCollisionFlags2(mapInfo.terrainBody.ptr, CollisionFlags.CF_STATIC_OBJECT); - float terrainMass = 1000; - Vector3 localInertia = BulletSimAPI.CalculateLocalInertia2(mapInfo.terrainBody.ptr, terrainMass); - BulletSimAPI.SetMassProps2(mapInfo.terrainBody.ptr, terrainMass, localInertia); - BulletSimAPI.UpdateInertiaTensor2(mapInfo.terrainBody.ptr); - // Return the new terrain to the world of physical objects BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, mapInfo.terrainBody.ptr); -- cgit v1.1 From 3a458e2a36253f6514720213deaa19372b06cc52 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Wed, 10 Oct 2012 13:56:16 -0700 Subject: BulletSim: Use full linkset mass when computing vehicle gravity force. Add taint-time specification to new AddForce(). --- OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs | 6 +++--- OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs | 9 +++------ OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | 12 ++++++++++-- 3 files changed, 16 insertions(+), 11 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs index 76230a1..56342b8 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs @@ -462,7 +462,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin return; // Set the prim's inertia to zero. The vehicle code handles that and this - // removes the torque action introduced by Bullet. + // removes the motion and torque actions introduced by Bullet. Vector3 inertia = Vector3.Zero; BulletSimAPI.SetMassProps2(Prim.BSBody.ptr, Prim.MassRaw, inertia); BulletSimAPI.UpdateInertiaTensor2(Prim.BSBody.ptr); @@ -540,7 +540,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin // add Gravity and Buoyancy // There is some gravity, make a gravity force vector that is applied after object velocity. // m_VehicleBuoyancy: -1=2g; 0=1g; 1=0g; - Vector3 grav = Prim.PhysicsScene.DefaultGravity * (Prim.MassRaw * (1f - m_VehicleBuoyancy)); + Vector3 grav = Prim.PhysicsScene.DefaultGravity * (Prim.Linkset.LinksetMass * (1f - m_VehicleBuoyancy)); /* * RA: Not sure why one would do this @@ -681,7 +681,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin Prim.ForceVelocity = m_newVelocity; // apply gravity force // Why is this set here? The physics engine already does gravity. - Prim.AddForce(grav, false); + Prim.AddForce(grav, false, true); // Apply friction Vector3 keepFraction = Vector3.One - (Vector3.One / (m_linearFrictionTimescale / pTimestep)); diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs index b84ccdc..43b1262 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs @@ -165,13 +165,11 @@ public class BSLinkset // May be called at runtime or taint-time (just pass the appropriate flag). public void Refresh(BSPhysObject requestor, bool inTaintTime) { - // If there are no children, there can't be any constraints to recompute - if (!HasAnyChildren) + // If there are no children, not physical or not root, I am not the one that recomputes the constraints + // (For the moment, static linksets do create constraints so remove the test for physical.) + if (!HasAnyChildren || /*!requestor.IsPhysical ||*/ !IsRoot(requestor)) return; - // Only the root does the recomputation - if (IsRoot(requestor)) - { BSScene.TaintCallback refreshOperation = delegate() { RecomputeLinksetConstraintVariables(); @@ -182,7 +180,6 @@ public class BSLinkset refreshOperation(); else PhysicsScene.TaintedObject("BSLinkSet.Refresh", refreshOperation); - } } // The object is going dynamic (physical). Do any setup necessary diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index b26f049..692713d 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs @@ -855,6 +855,9 @@ public sealed class BSPrim : BSPhysObject private List m_accumulatedForces = new List(); public override void AddForce(OMV.Vector3 force, bool pushforce) { + AddForce(force, pushforce, false); + } + public void AddForce(OMV.Vector3 force, bool pushforce, bool inTaintTime) { // for an object, doesn't matter if force is a pushforce or not if (force.IsFinite()) { @@ -867,11 +870,12 @@ public sealed class BSPrim : BSPhysObject m_log.WarnFormat("{0}: Got a NaN force applied to a prim. LocalID={1}", LogHeader, LocalID); return; } - PhysicsScene.TaintedObject("BSPrim.AddForce", delegate() + BSScene.TaintCallback addForceOperation = delegate() { OMV.Vector3 fSum = OMV.Vector3.Zero; lock (m_accumulatedForces) { + // Sum the accumulated additional forces for one big force to apply once. foreach (OMV.Vector3 v in m_accumulatedForces) { fSum += v; @@ -881,7 +885,11 @@ public sealed class BSPrim : BSPhysObject // DetailLog("{0},BSPrim.AddObjectForce,taint,force={1}", LocalID, fSum); // For unknown reasons, "ApplyCentralForce" adds this force to the total force on the object. BulletSimAPI.ApplyCentralForce2(BSBody.ptr, fSum); - }); + }; + if (inTaintTime) + addForceOperation(); + else + PhysicsScene.TaintedObject("BSPrim.AddForce", addForceOperation); } public override void AddAngularForce(OMV.Vector3 force, bool pushforce) { -- cgit v1.1 From a86fedd25ffb02c328b0591d16eda1dab797d8f9 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Wed, 10 Oct 2012 16:51:50 -0700 Subject: BulletSim: normalize physics FPS to 45. --- OpenSim/Region/Physics/BulletSPlugin/BSScene.cs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs index 617bdb4..25f8f5f 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs @@ -581,8 +581,9 @@ public class BSScene : PhysicsScene, IPhysicsParameters // The physics engine returns the number of milliseconds it simulated this call. // These are summed and normalized to one second and divided by 1000 to give the reported physics FPS. - // Since Bullet normally does 5 or 6 substeps, this will normally sum to about 60 FPS. - return numSubSteps * m_fixedTimeStep * 1000; + // We multiply by 45 to give a recognizable running rate (45 or less). + return numSubSteps * m_fixedTimeStep * 1000 * 45; + // return timeStep * 1000 * 45; } // Something has collided @@ -1300,7 +1301,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters { PhysicsLogging.Write(msg, args); // Add the Flush() if debugging crashes to get all the messages written out. - PhysicsLogging.Flush(); // DEBUG DEBUG DEBUG + // PhysicsLogging.Flush(); } // used to fill in the LocalID when there isn't one public const string DetailLogZero = "0000000000"; -- cgit v1.1 From 5b82f18d6422d89da53d382eb1ae89e47b4465b7 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Wed, 10 Oct 2012 16:53:58 -0700 Subject: BulletSim: normalize physics FPS to 45 (for real this time). --- OpenSim/Region/Physics/BulletSPlugin/BSScene.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs index 25f8f5f..2c3c481 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs @@ -582,8 +582,8 @@ public class BSScene : PhysicsScene, IPhysicsParameters // The physics engine returns the number of milliseconds it simulated this call. // These are summed and normalized to one second and divided by 1000 to give the reported physics FPS. // We multiply by 45 to give a recognizable running rate (45 or less). - return numSubSteps * m_fixedTimeStep * 1000 * 45; - // return timeStep * 1000 * 45; + return numSubSteps * m_fixedTimeStep * 1000 * 45; + // return timeStep * 1000 * 45; } // Something has collided -- cgit v1.1 From b24190ec98f31f1e4672d1174163426b9b44e25d Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Thu, 11 Oct 2012 12:54:27 -0700 Subject: BulletSim: remove some unused API2 calls because they were removed from Bullet 2.81 --- OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | 4 ++-- OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs | 12 ------------ 2 files changed, 2 insertions(+), 14 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index 692713d..6a4365c 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs @@ -673,8 +673,8 @@ public sealed class BSPrim : BSPhysObject // Force activation of the object so Bullet will act on it. // Must do the ForceActivationState2() to overcome the DISABLE_SIMULATION from static objects. - BulletSimAPI.ForceActivationState2(BSBody.ptr, ActivationState.ISLAND_SLEEPING); - BulletSimAPI.Activate2(BSBody.ptr, true); + BulletSimAPI.ForceActivationState2(BSBody.ptr, ActivationState.ACTIVE_TAG); + // BulletSimAPI.Activate2(BSBody.ptr, true); BSBody.collisionFilter = CollisionFilterGroups.ObjectFilter; BSBody.collisionMask = CollisionFilterGroups.ObjectMask; diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs index e23fe5a..276111c 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs @@ -1039,18 +1039,6 @@ public static extern IntPtr GetConstraintRef2(IntPtr obj, int index); public static extern int GetNumConstraintRefs2(IntPtr obj); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern Vector3 GetDeltaLinearVelocity2(IntPtr obj); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern Vector3 GetDeltaAngularVelocity2(IntPtr obj); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern Vector3 GetPushVelocity2(IntPtr obj); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern Vector3 GetTurnVelocity2(IntPtr obj); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern void SetCollisionFilterMask2(IntPtr body, uint filter, uint mask); // ===================================================================================== -- cgit v1.1 From 1f2472d0fcd86a7ae09c01ecb3508eab001ce033 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Thu, 11 Oct 2012 23:28:53 +0100 Subject: Extend "show stats" command to "show stats [list|all|]" This allows different categories of stats to be shown, with options to list categories or show all stats. Currently categories are scene and simulator and only a very few stats are currently registered via this mechanism. This commit also adds percentage stats for packets and blocks reused from the packet pool. --- OpenSim/Region/Application/OpenSimBase.cs | 72 +++++++++++----------- .../Region/ClientStack/Linden/UDP/PacketPool.cs | 43 ++++++++++--- 2 files changed, 70 insertions(+), 45 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Application/OpenSimBase.cs b/OpenSim/Region/Application/OpenSimBase.cs index f784398..4f1b439 100644 --- a/OpenSim/Region/Application/OpenSimBase.cs +++ b/OpenSim/Region/Application/OpenSimBase.cs @@ -223,8 +223,6 @@ namespace OpenSim base.StartupSpecific(); - m_stats = StatsManager.SimExtraStats; - // Create a ModuleLoader instance m_moduleLoader = new ModuleLoader(m_config.Source); @@ -234,51 +232,51 @@ namespace OpenSim plugin.PostInitialise(); } - AddPluginCommands(); + if (m_console != null) + { + StatsManager.RegisterConsoleCommands(m_console); + AddPluginCommands(m_console); + } } - protected virtual void AddPluginCommands() + protected virtual void AddPluginCommands(CommandConsole console) { - // If console exists add plugin commands. - if (m_console != null) - { - List topics = GetHelpTopics(); + List topics = GetHelpTopics(); - foreach (string topic in topics) - { - string capitalizedTopic = char.ToUpper(topic[0]) + topic.Substring(1); + foreach (string topic in topics) + { + string capitalizedTopic = char.ToUpper(topic[0]) + topic.Substring(1); - // This is a hack to allow the user to enter the help command in upper or lowercase. This will go - // away at some point. - m_console.Commands.AddCommand(capitalizedTopic, false, "help " + topic, - "help " + capitalizedTopic, - "Get help on plugin command '" + topic + "'", - HandleCommanderHelp); - m_console.Commands.AddCommand(capitalizedTopic, false, "help " + capitalizedTopic, - "help " + capitalizedTopic, - "Get help on plugin command '" + topic + "'", - HandleCommanderHelp); + // This is a hack to allow the user to enter the help command in upper or lowercase. This will go + // away at some point. + console.Commands.AddCommand(capitalizedTopic, false, "help " + topic, + "help " + capitalizedTopic, + "Get help on plugin command '" + topic + "'", + HandleCommanderHelp); + console.Commands.AddCommand(capitalizedTopic, false, "help " + capitalizedTopic, + "help " + capitalizedTopic, + "Get help on plugin command '" + topic + "'", + HandleCommanderHelp); - ICommander commander = null; + ICommander commander = null; - Scene s = SceneManager.CurrentOrFirstScene; + Scene s = SceneManager.CurrentOrFirstScene; - if (s != null && s.GetCommanders() != null) - { - if (s.GetCommanders().ContainsKey(topic)) - commander = s.GetCommanders()[topic]; - } + if (s != null && s.GetCommanders() != null) + { + if (s.GetCommanders().ContainsKey(topic)) + commander = s.GetCommanders()[topic]; + } - if (commander == null) - continue; + if (commander == null) + continue; - foreach (string command in commander.Commands.Keys) - { - m_console.Commands.AddCommand(capitalizedTopic, false, - topic + " " + command, - topic + " " + commander.Commands[command].ShortHelp(), - String.Empty, HandleCommanderCommand); - } + foreach (string command in commander.Commands.Keys) + { + console.Commands.AddCommand(capitalizedTopic, false, + topic + " " + command, + topic + " " + commander.Commands[command].ShortHelp(), + String.Empty, HandleCommanderCommand); } } } diff --git a/OpenSim/Region/ClientStack/Linden/UDP/PacketPool.cs b/OpenSim/Region/ClientStack/Linden/UDP/PacketPool.cs index fc9406b..3d9f94f 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/PacketPool.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/PacketPool.cs @@ -31,6 +31,7 @@ using System.Reflection; using OpenMetaverse; using OpenMetaverse.Packets; using log4net; +using OpenSim.Framework.Monitoring; namespace OpenSim.Region.ClientStack.LindenUDP { @@ -43,17 +44,28 @@ namespace OpenSim.Region.ClientStack.LindenUDP private bool packetPoolEnabled = true; private bool dataBlockPoolEnabled = true; + private PercentageStat m_packetsReusedStat = new PercentageStat( + "PacketsReused", + "Packets reused", + "simulator", + "simulator", + StatVerbosity.Debug, + "Number of packets reused out of all requests to the packet pool"); + + private PercentageStat m_blocksReusedStat = new PercentageStat( + "BlocksReused", + "Blocks reused", + "simulator", + "simulator", + StatVerbosity.Debug, + "Number of data blocks reused out of all requests to the packet pool"); + /// /// Pool of packets available for reuse. /// private readonly Dictionary> pool = new Dictionary>(); - private static Dictionary> DataBlocks = - new Dictionary>(); - - static PacketPool() - { - } + private static Dictionary> DataBlocks = new Dictionary>(); public static PacketPool Instance { @@ -72,8 +84,16 @@ namespace OpenSim.Region.ClientStack.LindenUDP get { return dataBlockPoolEnabled; } } + private PacketPool() + { + StatsManager.RegisterStat(m_packetsReusedStat); + StatsManager.RegisterStat(m_blocksReusedStat); + } + public Packet GetPacket(PacketType type) { + m_packetsReusedStat.Consequent++; + Packet packet; if (!packetPoolEnabled) @@ -89,6 +109,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP else { // Recycle old packages + m_packetsReusedStat.Antecedent++; + packet = (pool[type]).Pop(); } } @@ -211,16 +233,21 @@ namespace OpenSim.Region.ClientStack.LindenUDP } } - public static T GetDataBlock() where T: new() + public T GetDataBlock() where T: new() { lock (DataBlocks) { + m_blocksReusedStat.Consequent++; + Stack s; if (DataBlocks.TryGetValue(typeof(T), out s)) { if (s.Count > 0) + { + m_blocksReusedStat.Antecedent++; return (T)s.Pop(); + } } else { @@ -231,7 +258,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP } } - public static void ReturnDataBlock(T block) where T: new() + public void ReturnDataBlock(T block) where T: new() { if (block == null) return; -- cgit v1.1 From 2e9ef015f7b73a3942011a36a9f94ce59d848dc0 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Thu, 11 Oct 2012 23:58:37 +0100 Subject: Fix packetpool for ImprovedTerseObjectUpdate packets. These were neither being returned or in many places reused. Getting packets from a pool rather than deallocating and reallocating reduces memory churn which in turn reduces garbage collection time and frequency. --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 14 +++++++++++--- OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs | 2 ++ OpenSim/Region/ClientStack/Linden/UDP/PacketPool.cs | 4 ++-- 3 files changed, 15 insertions(+), 5 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 62f51d9..dc88686 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -3922,7 +3922,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP { List blocks = terseAgentUpdateBlocks.Value; - ImprovedTerseObjectUpdatePacket packet = new ImprovedTerseObjectUpdatePacket(); + ImprovedTerseObjectUpdatePacket packet + = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ImprovedTerseObjectUpdate); + packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle; packet.RegionData.TimeDilation = timeDilation; packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count]; @@ -3967,7 +3969,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP { List blocks = terseUpdateBlocks.Value; - ImprovedTerseObjectUpdatePacket packet = new ImprovedTerseObjectUpdatePacket(); + ImprovedTerseObjectUpdatePacket packet + = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket( + PacketType.ImprovedTerseObjectUpdate); + packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle; packet.RegionData.TimeDilation = timeDilation; packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count]; @@ -12286,7 +12291,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP ushort timeDilation = Utils.FloatToUInt16(TIME_DILATION, 0.0f, 1.0f); - ImprovedTerseObjectUpdatePacket packet = new ImprovedTerseObjectUpdatePacket(); + ImprovedTerseObjectUpdatePacket packet + = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket( + PacketType.ImprovedTerseObjectUpdate); + packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle; packet.RegionData.TimeDilation = timeDilation; packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[1]; diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs index ab670a7..6d2cda5 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs @@ -420,6 +420,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP byte[] data = packet.ToBytes(); SendPacketData(udpClient, data, packet.Type, category, method); } + + PacketPool.Instance.ReturnPacket(packet); } /// diff --git a/OpenSim/Region/ClientStack/Linden/UDP/PacketPool.cs b/OpenSim/Region/ClientStack/Linden/UDP/PacketPool.cs index 3d9f94f..fd6b0ed 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/PacketPool.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/PacketPool.cs @@ -47,7 +47,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP private PercentageStat m_packetsReusedStat = new PercentageStat( "PacketsReused", "Packets reused", - "simulator", + "clientstack", "simulator", StatVerbosity.Debug, "Number of packets reused out of all requests to the packet pool"); @@ -55,7 +55,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP private PercentageStat m_blocksReusedStat = new PercentageStat( "BlocksReused", "Blocks reused", - "simulator", + "clientstack", "simulator", StatVerbosity.Debug, "Number of data blocks reused out of all requests to the packet pool"); -- cgit v1.1 From 8a402850ddbdd9497998774b646c8e0ae6ef1eb8 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 12 Oct 2012 00:21:45 +0100 Subject: Enable reuse of data blocks for ImprovedTerseObjectUpdate using existing Packetpool code. --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index dc88686..5f9face 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -4964,7 +4964,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP Utils.UInt16ToBytes(Utils.FloatToUInt16(angularVelocity.Y, -64.0f, 64.0f), data, pos); pos += 2; Utils.UInt16ToBytes(Utils.FloatToUInt16(angularVelocity.Z, -64.0f, 64.0f), data, pos); pos += 2; - ImprovedTerseObjectUpdatePacket.ObjectDataBlock block = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock(); + ImprovedTerseObjectUpdatePacket.ObjectDataBlock block + = PacketPool.Instance.GetDataBlock(); + block.Data = data; if (textureEntry != null && textureEntry.Length > 0) -- cgit v1.1 From 59a17ad676326d5affc2e221ef9c02166a85c6fd Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 12 Oct 2012 00:26:15 +0100 Subject: Fix percentage stats to multiply by 100. Adjust container name for packetpool stats. --- OpenSim/Region/ClientStack/Linden/UDP/PacketPool.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/PacketPool.cs b/OpenSim/Region/ClientStack/Linden/UDP/PacketPool.cs index fd6b0ed..a8a1bfe 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/PacketPool.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/PacketPool.cs @@ -48,14 +48,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP "PacketsReused", "Packets reused", "clientstack", - "simulator", + "packetpool", StatVerbosity.Debug, "Number of packets reused out of all requests to the packet pool"); private PercentageStat m_blocksReusedStat = new PercentageStat( "BlocksReused", "Blocks reused", - "clientstack", + "packetpool", "simulator", StatVerbosity.Debug, "Number of data blocks reused out of all requests to the packet pool"); -- cgit v1.1 From 87a87ebb9a68f9bb4cd44f3b00954ed7fca7da3a Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Thu, 11 Oct 2012 17:06:58 -0700 Subject: BulletSim: fix problem with some shapes (like cylinders) being implemented as cubes. --- OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs index d5e2172..a0d111a 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs @@ -387,7 +387,7 @@ public class BSShapeCollection : IDisposable prim.LocalID, forceRebuild, prim.BSShape); } } - else + if (pbs.ProfileShape == ProfileShape.Square && pbs.PathCurve == (byte)Extrusion.Straight) { haveShape = true; if (forceRebuild -- cgit v1.1 From 21d0cbf7038cfb1b1010310a0f4b455cf9ab700d Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 12 Oct 2012 01:39:37 +0100 Subject: Add AgentUpdate to PacketPool. This is the most common inbound packet from viewers. --- .../Region/ClientStack/Linden/UDP/LLUDPServer.cs | 21 +++++++++++++++++++-- OpenSim/Region/ClientStack/Linden/UDP/PacketPool.cs | 8 +++++++- .../Linden/UDP/Tests/BasicCircuitTests.cs | 4 ++-- 3 files changed, 28 insertions(+), 5 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs index 6d2cda5..e3f4679 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs @@ -100,9 +100,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// The measured resolution of Environment.TickCount public readonly float TickCountResolution; + /// Number of prim updates to put on the queue each time the /// OnQueueEmpty event is triggered for updates public readonly int PrimUpdatesPerCallback; + /// Number of texture packets to put on the queue each time the /// OnQueueEmpty event is triggered for textures public readonly int TextureSendLimit; @@ -111,6 +113,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP //PacketEventDictionary packetEvents = new PacketEventDictionary(); /// Incoming packets that are awaiting handling private OpenMetaverse.BlockingQueue packetInbox = new OpenMetaverse.BlockingQueue(); + /// //private UDPClientCollection m_clients = new UDPClientCollection(); /// Bandwidth throttle for this UDP server @@ -121,28 +124,37 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// Manages authentication for agent circuits private AgentCircuitManager m_circuitManager; + /// Reference to the scene this UDP server is attached to protected Scene m_scene; + /// The X/Y coordinates of the scene this UDP server is attached to private Location m_location; + /// The size of the receive buffer for the UDP socket. This value /// is passed up to the operating system and used in the system networking /// stack. Use zero to leave this value as the default private int m_recvBufferSize; + /// Flag to process packets asynchronously or synchronously private bool m_asyncPacketHandling; + /// Tracks whether or not a packet was sent each round so we know /// whether or not to sleep private bool m_packetSent; /// Environment.TickCount of the last time that packet stats were reported to the scene private int m_elapsedMSSinceLastStatReport = 0; + /// Environment.TickCount of the last time the outgoing packet handler executed private int m_tickLastOutgoingPacketHandler; + /// Keeps track of the number of elapsed milliseconds since the last time the outgoing packet handler looped private int m_elapsedMSOutgoingPacketHandler; + /// Keeps track of the number of 100 millisecond periods elapsed in the outgoing packet handler executed private int m_elapsed100MSOutgoingPacketHandler; + /// Keeps track of the number of 500 millisecond periods elapsed in the outgoing packet handler executed private int m_elapsed500MSOutgoingPacketHandler; @@ -739,7 +751,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP try { - packet = Packet.BuildPacket(buffer.Data, ref packetEnd, +// packet = Packet.BuildPacket(buffer.Data, ref packetEnd, +// // Only allocate a buffer for zerodecoding if the packet is zerocoded +// ((buffer.Data[0] & Helpers.MSG_ZEROCODED) != 0) ? new byte[4096] : null); + packet = PacketPool.Instance.GetPacket(buffer.Data, ref packetEnd, // Only allocate a buffer for zerodecoding if the packet is zerocoded ((buffer.Data[0] & Helpers.MSG_ZEROCODED) != 0) ? new byte[4096] : null); } @@ -754,11 +769,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP return; // Drop short packet } - catch(Exception e) + catch (Exception e) { if (m_malformedCount < 100) m_log.DebugFormat("[LLUDPSERVER]: Dropped malformed packet: " + e.ToString()); + m_malformedCount++; + if ((m_malformedCount % 100000) == 0) m_log.DebugFormat("[LLUDPSERVER]: Received {0} malformed packets so far, probable network attack.", m_malformedCount); } diff --git a/OpenSim/Region/ClientStack/Linden/UDP/PacketPool.cs b/OpenSim/Region/ClientStack/Linden/UDP/PacketPool.cs index a8a1bfe..052d334 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/PacketPool.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/PacketPool.cs @@ -90,6 +90,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP StatsManager.RegisterStat(m_blocksReusedStat); } + /// + /// Gets a packet of the given type. + /// + /// + /// Guaranteed to always return a packet, whether from the pool or newly constructed. public Packet GetPacket(PacketType type) { m_packetsReusedStat.Consequent++; @@ -160,7 +165,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP { PacketType type = GetType(bytes); - Array.Clear(zeroBuffer, 0, zeroBuffer.Length); +// Array.Clear(zeroBuffer, 0, zeroBuffer.Length); int i = 0; Packet packet = GetPacket(type); @@ -207,6 +212,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP switch (packet.Type) { // List pooling packets here + case PacketType.AgentUpdate: case PacketType.PacketAck: case PacketType.ObjectUpdate: case PacketType.ImprovedTerseObjectUpdate: diff --git a/OpenSim/Region/ClientStack/Linden/UDP/Tests/BasicCircuitTests.cs b/OpenSim/Region/ClientStack/Linden/UDP/Tests/BasicCircuitTests.cs index 109a8e1..fa9378c 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/Tests/BasicCircuitTests.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/Tests/BasicCircuitTests.cs @@ -43,7 +43,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests /// This will contain basic tests for the LindenUDP client stack /// [TestFixture] - public class BasicCircuitTests + public class BasicCircuitTests : OpenSimTestCase { private Scene m_scene; private TestLLUDPServer m_udpServer; @@ -143,7 +143,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests public void TestAddClient() { TestHelpers.InMethod(); -// XmlConfigurator.Configure(); +// TestHelpers.EnableLogging(); AddUdpServer(); -- cgit v1.1 From 8873a4a8fcaa3372713463094f2cfebeaaf45834 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 12 Oct 2012 01:59:47 +0100 Subject: minor: Fix bug in categorization of blocks reused stat from packetpool --- OpenSim/Region/ClientStack/Linden/UDP/PacketPool.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/PacketPool.cs b/OpenSim/Region/ClientStack/Linden/UDP/PacketPool.cs index 052d334..71f6fe1 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/PacketPool.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/PacketPool.cs @@ -55,8 +55,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP private PercentageStat m_blocksReusedStat = new PercentageStat( "BlocksReused", "Blocks reused", + "clientstack", "packetpool", - "simulator", StatVerbosity.Debug, "Number of data blocks reused out of all requests to the packet pool"); -- cgit v1.1 From b7e75d467c2edf052b0cf5216043937ebf583ef4 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 12 Oct 2012 02:10:30 +0100 Subject: minor: Use && instead of & when deciding whether to print Improve/ObjectUpdate packet out messages when debug is turned on. Practical effect is probably none. --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 5f9face..2db8df2 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -11765,7 +11765,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP logPacket = false; if (DebugPacketLevel <= 50 - & (packet.Type == PacketType.ImprovedTerseObjectUpdate || packet.Type == PacketType.ObjectUpdate)) + && (packet.Type == PacketType.ImprovedTerseObjectUpdate || packet.Type == PacketType.ObjectUpdate)) logPacket = false; if (DebugPacketLevel <= 25 && packet.Type == PacketType.ObjectPropertiesFamily) -- cgit v1.1 From b5a3c74a5cbd1634d021923124a997fc4945e5ef Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 12 Oct 2012 02:52:08 +0100 Subject: Add "active true|false" to "debug scene" console command. This allows the scene update and maintenance loops to be started and stopped for debug purposes. --- OpenSim/Region/Application/OpenSim.cs | 13 ++++++++--- OpenSim/Region/Framework/Scenes/Scene.cs | 40 +++++++++++++++++++++++++++++--- 2 files changed, 47 insertions(+), 6 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Application/OpenSim.cs b/OpenSim/Region/Application/OpenSim.cs index c3c612f..b24641a 100644 --- a/OpenSim/Region/Application/OpenSim.cs +++ b/OpenSim/Region/Application/OpenSim.cs @@ -254,8 +254,14 @@ namespace OpenSim m_console.Commands.AddCommand("Debug", false, "debug teleport", "debug teleport", "Toggle teleport route debugging", Debug); m_console.Commands.AddCommand("Debug", false, "debug scene", - "debug scene ", - "Turn on scene debugging", Debug); + "debug scene active|collisions|physics|scripting|teleport true|false", + "Turn on scene debugging.", + "If active is false then main scene update and maintenance loops are suspended.\n" + + "If collisions is false then collisions with other objects are turned off.\n" + + "If physics is false then all physics objects are non-physical.\n" + + "If scripting is false then no scripting operations happen.\n" + + "If teleport is true then some extra teleport debug information is logged.", + Debug); m_console.Commands.AddCommand("General", false, "change region", "change region ", @@ -930,7 +936,8 @@ namespace OpenSim } else { - MainConsole.Instance.Output("Usage: debug scene scripting|collisions|physics|teleport true|false"); + MainConsole.Instance.Output( + "Usage: debug scene active|scripting|collisions|physics|teleport true|false"); } break; diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index fb2decc..7f4f7e5 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -306,6 +306,30 @@ namespace OpenSim.Region.Framework.Scenes } private volatile bool m_shuttingDown; + /// + /// Is the scene active? + /// + /// + /// If false, maintenance and update loops are not run. + /// + public bool Active + { + get { return m_active; } + set + { + if (value) + { + if (!m_active) + Start(); + } + else + { + m_active = false; + } + } + } + private volatile bool m_active; + // private int m_lastUpdate; // private bool m_firstHeartbeat = true; @@ -1159,6 +1183,14 @@ namespace OpenSim.Region.Framework.Scenes public void SetSceneCoreDebug(Dictionary options) { + if (options.ContainsKey("active")) + { + bool active; + + if (bool.TryParse(options["active"], out active)) + Active = active; + } + if (options.ContainsKey("scripting")) { bool enableScripts = true; @@ -1298,6 +1330,8 @@ namespace OpenSim.Region.Framework.Scenes /// public void Start() { + m_active = true; + // m_log.DebugFormat("[SCENE]: Starting Heartbeat timer for {0}", RegionInfo.RegionName); //m_heartbeatTimer.Enabled = true; @@ -1339,7 +1373,7 @@ namespace OpenSim.Region.Framework.Scenes #region Update Methods /// - /// Performs per-frame updates regularly + /// Activate the various loops necessary to continually update the scene. /// private void Heartbeat() { @@ -1396,7 +1430,7 @@ namespace OpenSim.Region.Framework.Scenes List coarseLocations; List avatarUUIDs; - while (!m_shuttingDown && (endRun == null || MaintenanceRun < endRun)) + while (Active && !m_shuttingDown && (endRun == null || MaintenanceRun < endRun)) { runtc = Util.EnvironmentTickCount(); ++MaintenanceRun; @@ -1455,7 +1489,7 @@ namespace OpenSim.Region.Framework.Scenes int previousFrameTick, tmpMS; int maintc = Util.EnvironmentTickCount(); - while (!m_shuttingDown && (endFrame == null || Frame < endFrame)) + while (Active && !m_shuttingDown && (endFrame == null || Frame < endFrame)) { ++Frame; -- cgit v1.1 From b9c2a1508e68b5580328097a5d5e0b5bfbc16a7d Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 12 Oct 2012 03:19:12 +0100 Subject: Fix problems with regression tests by allowing invoke of Update() with a finite number of frames even if the scene isn't active. --- OpenSim/Region/Framework/Scenes/Scene.cs | 7 ++++--- .../Region/Framework/Scenes/Tests/ScenePresenceAutopilotTests.cs | 1 + 2 files changed, 5 insertions(+), 3 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 7f4f7e5..fe549bc 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -310,7 +310,8 @@ namespace OpenSim.Region.Framework.Scenes /// Is the scene active? /// /// - /// If false, maintenance and update loops are not run. + /// If false, maintenance and update loops are not being run. Updates can still be triggered manually if + /// the scene is not active. /// public bool Active { @@ -1430,7 +1431,7 @@ namespace OpenSim.Region.Framework.Scenes List coarseLocations; List avatarUUIDs; - while (Active && !m_shuttingDown && (endRun == null || MaintenanceRun < endRun)) + while (!m_shuttingDown && ((endRun == null && Active) || MaintenanceRun < endRun)) { runtc = Util.EnvironmentTickCount(); ++MaintenanceRun; @@ -1489,7 +1490,7 @@ namespace OpenSim.Region.Framework.Scenes int previousFrameTick, tmpMS; int maintc = Util.EnvironmentTickCount(); - while (Active && !m_shuttingDown && (endFrame == null || Frame < endFrame)) + while (!m_shuttingDown && ((endFrame == null && Active) || Frame < endFrame)) { ++Frame; diff --git a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAutopilotTests.cs b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAutopilotTests.cs index 1d1ff88..9a871f0 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAutopilotTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAutopilotTests.cs @@ -65,6 +65,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests public void Init() { m_scene = new SceneHelpers().SetupScene(); + m_scene.Start(); } [Test] -- cgit v1.1 From fba59d905c9f165e0fd8365e045f69df7b1383e3 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 12 Oct 2012 03:20:27 +0100 Subject: Get rid of accidental scene start left in ScenePresenceAutopilotTests --- OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAutopilotTests.cs | 1 - 1 file changed, 1 deletion(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAutopilotTests.cs b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAutopilotTests.cs index 9a871f0..1d1ff88 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAutopilotTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAutopilotTests.cs @@ -65,7 +65,6 @@ namespace OpenSim.Region.Framework.Scenes.Tests public void Init() { m_scene = new SceneHelpers().SetupScene(); - m_scene.Start(); } [Test] -- cgit v1.1 From 8c40215834bc1286a6bd2902e1c8b0f2ef793fd7 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Fri, 12 Oct 2012 07:37:52 -0700 Subject: BulletSim: only use native sphere shape if it is a sphere. --- OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs index a0d111a..d189f1d 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs @@ -373,7 +373,8 @@ public class BSShapeCollection : IDisposable && pbs.PathScaleX == 100 && pbs.PathScaleY == 100 && pbs.PathShearX == 0 && pbs.PathShearY == 0) ) ) { - if (pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1) + if ((pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1) + && pbs.Scale.X == pbs.Scale.Y && pbs.Scale.Y == pbs.Scale.Z) { haveShape = true; if (forceRebuild -- cgit v1.1 From f6e166cd0bfc868fe17fb003390872ae70190177 Mon Sep 17 00:00:00 2001 From: TBG Renfold Date: Tue, 9 Oct 2012 14:56:25 +0100 Subject: Now using region flags for llRequestSimulatorData DATA_SIM_POS. If the region is not classed a hypergrid region, then the region secret is checked to make sure that it is a valid UUID. Just a temporary fix at this time. --- .../Shared/Api/Implementation/LSL_Api.cs | 25 +++++++++++++++------- 1 file changed, 17 insertions(+), 8 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 7620df3..6b08b00 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -56,6 +56,7 @@ using GridRegion = OpenSim.Services.Interfaces.GridRegion; using PresenceInfo = OpenSim.Services.Interfaces.PresenceInfo; using PrimType = OpenSim.Region.Framework.Scenes.PrimType; using AssetLandmark = OpenSim.Framework.AssetLandmark; +using RegionFlags = OpenSim.Framework.RegionFlags; using LSL_Float = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLFloat; using LSL_Integer = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLInteger; @@ -9327,12 +9328,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api ScriptSleep(1000); return UUID.Zero.ToString(); } - if (m_ScriptEngine.World.RegionInfo.RegionName != simulator) + + RegionFlags regionFlags = (RegionFlags)m_ScriptEngine.World.GridService.GetRegionFlags(info.ScopeID, info.RegionID); + if ((regionFlags & RegionFlags.Hyperlink) != 0) { - //Hypergrid Region co-ordinates uint rx = 0, ry = 0; + //Hypergrid Region co-ordinates Utils.LongToUInts(Convert.ToUInt64(info.RegionSecret), out rx, out ry); - reply = new LSL_Vector( rx, ry, @@ -9340,11 +9342,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } else { - //Local-cooridnates - reply = new LSL_Vector( - info.RegionLocX, - info.RegionLocY, - 0).ToString(); + UUID regionSecret = UUID.Zero; + if (UUID.TryParse(info.RegionSecret, out regionSecret)) + { + if (regionSecret != UUID.Zero) + { + //Local co-oridnates + reply = new LSL_Vector( + info.RegionLocX, + info.RegionLocY, + 0).ToString(); + } + } } break; case ScriptBaseClass.DATA_SIM_STATUS: -- cgit v1.1 From 330b976a62b3153dadfb1acdaa99b60a9084453d Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Sat, 13 Oct 2012 01:03:09 +0100 Subject: Improve on TBG Renfold's fix to llRequestSimulatorData DATA_SIM_POS by only performing HG regionflags service check if the region secret is not empty. An empty RegionSecret is never HG, whilst a non-empty one may be HG or being genuinely used as a RegionSecret. --- .../Shared/Api/Implementation/LSL_Api.cs | 44 ++++++++++++---------- 1 file changed, 25 insertions(+), 19 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 6b08b00..1e8dec8 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -9314,11 +9314,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api GridRegion info; - if (m_ScriptEngine.World.RegionInfo.RegionName == simulator) //Det data for this simulator? - - info = new GridRegion(m_ScriptEngine.World.RegionInfo); + if (World.RegionInfo.RegionName == simulator) + info = new GridRegion(World.RegionInfo); else - info = m_ScriptEngine.World.GridService.GetRegionByName(m_ScriptEngine.World.RegionInfo.ScopeID, simulator); + info = World.GridService.GetRegionByName(m_ScriptEngine.World.RegionInfo.ScopeID, simulator); switch (data) { @@ -9329,12 +9328,26 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api return UUID.Zero.ToString(); } - RegionFlags regionFlags = (RegionFlags)m_ScriptEngine.World.GridService.GetRegionFlags(info.ScopeID, info.RegionID); - if ((regionFlags & RegionFlags.Hyperlink) != 0) + bool isHypergridRegion = false; + + if (World.RegionInfo.RegionName != simulator && info.RegionSecret != "") + { + // Hypergrid is currently placing real destination region co-ords into RegionSecret. + // But other code can also use this field for a genuine RegionSecret! Therefore, if + // anything is present we need to disambiguate. + // + // FIXME: Hypergrid should be storing this data in a different field. + RegionFlags regionFlags + = (RegionFlags)m_ScriptEngine.World.GridService.GetRegionFlags( + info.ScopeID, info.RegionID); + isHypergridRegion = (regionFlags & RegionFlags.Hyperlink) != 0; + } + + if (isHypergridRegion) { uint rx = 0, ry = 0; - //Hypergrid Region co-ordinates Utils.LongToUInts(Convert.ToUInt64(info.RegionSecret), out rx, out ry); + reply = new LSL_Vector( rx, ry, @@ -9342,18 +9355,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } else { - UUID regionSecret = UUID.Zero; - if (UUID.TryParse(info.RegionSecret, out regionSecret)) - { - if (regionSecret != UUID.Zero) - { - //Local co-oridnates - reply = new LSL_Vector( - info.RegionLocX, - info.RegionLocY, - 0).ToString(); - } - } + // Local grid co-oridnates + reply = new LSL_Vector( + info.RegionLocX, + info.RegionLocY, + 0).ToString(); } break; case ScriptBaseClass.DATA_SIM_STATUS: -- cgit v1.1 From dc460579fd94b2017e334e71ffd20d94a3dec425 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Sat, 13 Oct 2012 01:47:10 +0100 Subject: minor: Fix and elaborate on log information printed when an unrecognized estate method is received from the client. --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 2db8df2..0d4f09d 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -9063,7 +9063,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP } #endregion - switch (Utils.BytesToString(messagePacket.MethodData.Method)) + string method = Utils.BytesToString(messagePacket.MethodData.Method); + + switch (method) { case "getinfo": if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false)) @@ -9379,7 +9381,17 @@ namespace OpenSim.Region.ClientStack.LindenUDP return true; default: - m_log.Error("EstateOwnerMessage: Unknown method requested\n" + messagePacket); + m_log.WarnFormat( + "[LLCLIENTVIEW]: EstateOwnerMessage: Unknown method {0} requested for {1} in {2}", + method, Name, Scene.Name); + + for (int i = 0; i < messagePacket.ParamList.Length; i++) + { + EstateOwnerMessagePacket.ParamListBlock block = messagePacket.ParamList[i]; + string data = (string)Utils.BytesToString(block.Parameter); + m_log.DebugFormat("[LLCLIENTVIEW]: Param {0}={1}", i, data); + } + return true; } -- cgit v1.1 From 8c2564c05cbf277bef85bba62313f5d5493a4a81 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Tue, 16 Oct 2012 00:40:28 +0100 Subject: minor: Comment out the region console caps message for now. --- OpenSim/Region/ClientStack/Linden/Caps/RegionConsoleModule.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/ClientStack/Linden/Caps/RegionConsoleModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/RegionConsoleModule.cs index 36af55f..17c7270 100644 --- a/OpenSim/Region/ClientStack/Linden/Caps/RegionConsoleModule.cs +++ b/OpenSim/Region/ClientStack/Linden/Caps/RegionConsoleModule.cs @@ -107,7 +107,7 @@ namespace OpenSim.Region.ClientStack.Linden UUID capID = UUID.Random(); - m_log.DebugFormat("[REGION CONSOLE]: /CAPS/{0} in region {1}", capID, m_scene.RegionInfo.RegionName); +// m_log.DebugFormat("[REGION CONSOLE]: /CAPS/{0} in region {1}", capID, m_scene.RegionInfo.RegionName); caps.RegisterHandler( "SimConsoleAsync", new ConsoleHandler("/CAPS/" + capID + "/", "SimConsoleAsync", agentID, this, m_scene)); -- cgit v1.1 From 3ac6a423f7748bf9d5da0d1bd8fc62652ed8e151 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Tue, 16 Oct 2012 00:54:25 +0100 Subject: minor: comment out "Registered seed capability" message for "Received SEED caps request" message for now. I think this is more useful right now since it tells us if the viewer requested a seed caps at all in various scenarios (such as when teleporting to a new region). --- .../Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs b/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs index 185f9ce..cc69645 100644 --- a/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs +++ b/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs @@ -163,8 +163,8 @@ namespace OpenSim.Region.ClientStack.Linden m_HostCapsObj.RegisterHandler( "SEED", new RestStreamHandler("POST", capsBase + m_requestPath, SeedCapRequest, "SEED", null)); - m_log.DebugFormat( - "[CAPS]: Registered seed capability {0} for {1}", capsBase + m_requestPath, m_HostCapsObj.AgentID); +// m_log.DebugFormat( +// "[CAPS]: Registered seed capability {0} for {1}", capsBase + m_requestPath, m_HostCapsObj.AgentID); //m_capsHandlers["MapLayer"] = // new LLSDStreamhandler("POST", @@ -254,11 +254,12 @@ namespace OpenSim.Region.ClientStack.Linden public string SeedCapRequest(string request, string path, string param, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) { -// m_log.Debug("[CAPS]: Seed Caps Request in region: " + m_regionName); + m_log.DebugFormat( + "[CAPS]: Received SEED caps request in {0} for agent {1}", m_regionName, m_HostCapsObj.AgentID); if (!m_Scene.CheckClient(m_HostCapsObj.AgentID, httpRequest.RemoteIPEndPoint)) { - m_log.DebugFormat( + m_log.WarnFormat( "[CAPS]: Unauthorized CAPS client {0} from {1}", m_HostCapsObj.AgentID, httpRequest.RemoteIPEndPoint); -- cgit v1.1 From d469bde849f53a4c80b301051599390e916ce08a Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Tue, 16 Oct 2012 01:20:41 +0100 Subject: minor: Add/correct some doc messages associated with entity teleport. I believe UseCircuitCode is sent on EnableSimulator EQ message, rather than EstablishAgentCommunication At least with LL 3.3.4, EstablishAgentCommunication appears unnecessary in the teleport context - viewer still requests it though possibly only after TeleportFinish(). However, we will continue to send it. --- .../CoreModules/Framework/EntityTransfer/EntityTransferModule.cs | 7 ++++++- OpenSim/Region/Framework/Scenes/Scene.cs | 5 +++-- 2 files changed, 9 insertions(+), 3 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs index 617a350..90fe430 100644 --- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs +++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs @@ -486,6 +486,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer if (sp.ParentID != (uint)0) sp.StandUp(); + // At least on LL 3.3.4, this is not strictly necessary - a teleport will succeed without sending this to + // the viewer. However, it might mean that the viewer does not see the black teleport screen (untested). sp.ControllingClient.SendTeleportStart(teleportFlags); // the avatar.Close below will clear the child region list. We need this below for (possibly) @@ -561,8 +563,11 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer // So let's wait Thread.Sleep(200); + // At least on LL 3.3.4 for teleports between different regions on the same simulator this appears + // unnecessary - teleport will succeed and SEED caps will be requested without it (though possibly + // only on TeleportFinish). This is untested for region teleport between different simulators + // though this probably also works. m_eqModule.EstablishAgentCommunication(sp.UUID, endPoint, capsPath); - } else { diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index fe549bc..5f45529 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -4144,8 +4144,9 @@ namespace OpenSim.Region.Framework.Scenes return false; } - // We have to wait until the viewer contacts this region after receiving EAC. - // That calls AddNewClient, which finally creates the ScenePresence + // We have to wait until the viewer contacts this region + // after receiving the EnableSimulator HTTP Event Queue message. This triggers the viewer to send + // a UseCircuitCode packet which in turn calls AddNewClient which finally creates the ScenePresence. ScenePresence childAgentUpdate = WaitGetScenePresence(cAgentData.AgentID); if (childAgentUpdate != null) -- cgit v1.1 From 0eb457442d87315810fd8280458ca8c0c3e97d23 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Tue, 16 Oct 2012 01:31:38 +0100 Subject: minor: Add missing newlines and spacing to help for "debug eq" console command --- .../ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs index 0dd0904..47cb049 100644 --- a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs +++ b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs @@ -111,10 +111,10 @@ namespace OpenSim.Region.ClientStack.Linden false, "debug eq", "debug eq [0|1|2]", - "Turn on event queue debugging" - + "<= 0 - turns off all event queue logging" - + ">= 1 - turns on outgoing event logging" - + ">= 2 - turns on poll notification", + "Turn on event queue debugging\n" + + " <= 0 - turns off all event queue logging\n" + + " >= 1 - turns on outgoing event logging\n" + + " >= 2 - turns on poll notification", HandleDebugEq); } else -- cgit v1.1 From ab0294f0109416da0546e25797e7747b23071d33 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Tue, 16 Oct 2012 01:33:35 +0100 Subject: Add missing category paremeter to llGiveInventoryList grid IM construction. This was a regression from 16c9c1df Sat Oct 6 02:34:49 2012 +0100. Should resolve http://opensimulator.org/mantis/view.php?id=6360 --- OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (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 1e8dec8..ac74bf8 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -6459,7 +6459,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api GridInstantMessage msg = new GridInstantMessage(World, m_host.OwnerID, m_host.Name, destID, (byte)InstantMessageDialog.TaskInventoryOffered, - false, string.Format("'{0}'"), + false, string.Format("'{0}'", category), // We won't go so far as to add a SLURL, but this is the format used by LL as of 2012-10-06 // false, string.Format("'{0}' ( http://slurl.com/secondlife/{1}/{2}/{3}/{4} )", category, World.Name, (int)pos.X, (int)pos.Y, (int)pos.Z), folderID, false, pos, -- cgit v1.1 From db4ca57590db44aba7d19530285091c7ea4c082c Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Tue, 16 Oct 2012 21:55:00 +0100 Subject: Make it possible to separate start and stop lludp packet processing from the console for debug processes. This is controlled via the "debug lludp start " and "debug lludp stop " region console commands. The command "debug lludp status" will show current status. --- .../Region/ClientStack/Linden/UDP/LLUDPServer.cs | 116 ++++++++++++++++++--- .../ClientStack/Linden/UDP/OpenSimUDPBase.cs | 44 +++++--- 2 files changed, 129 insertions(+), 31 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs index e3f4679..fc6dd4d 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs @@ -37,6 +37,7 @@ using log4net; using Nini.Config; using OpenMetaverse.Packets; using OpenSim.Framework; +using OpenSim.Framework.Console; using OpenSim.Framework.Monitoring; using OpenSim.Region.Framework.Scenes; using OpenMetaverse; @@ -274,16 +275,21 @@ namespace OpenSim.Region.ClientStack.LindenUDP public void Start() { - if (m_scene == null) - throw new InvalidOperationException("[LLUDPSERVER]: Cannot LLUDPServer.Start() without an IScene reference"); + StartInbound(); + StartOutbound(); + m_elapsedMSSinceLastStatReport = Environment.TickCount; + } + + private void StartInbound() + { m_log.InfoFormat( - "[LLUDPSERVER]: Starting the LLUDP server in {0} mode", + "[LLUDPSERVER]: Starting inbound packet processing for the LLUDP server in {0} mode", m_asyncPacketHandling ? "asynchronous" : "synchronous"); - base.Start(m_recvBufferSize, m_asyncPacketHandling); + base.StartInbound(m_recvBufferSize, m_asyncPacketHandling); - // Start the packet processing threads + // This thread will process the packets received that are placed on the packetInbox Watchdog.StartThread( IncomingPacketHandler, string.Format("Incoming Packets ({0})", m_scene.RegionInfo.RegionName), @@ -292,7 +298,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP true, GetWatchdogIncomingAlarmData, Watchdog.DEFAULT_WATCHDOG_TIMEOUT_MS); + } + private void StartOutbound() + { + m_log.Info("[LLUDPSERVER]: Starting outbound packet processing for the LLUDP server"); + + base.StartOutbound(); + + // This thread will process the packets received that are placed on the packetInbox Watchdog.StartThread( OutgoingPacketHandler, string.Format("Outgoing Packets ({0})", m_scene.RegionInfo.RegionName), @@ -301,8 +315,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP true, GetWatchdogOutgoingAlarmData, Watchdog.DEFAULT_WATCHDOG_TIMEOUT_MS); + } - m_elapsedMSSinceLastStatReport = Environment.TickCount; + public new void Stop() + { + m_log.Info("[LLUDPSERVER]: Shutting down the LLUDP server for " + m_scene.RegionInfo.RegionName); + base.StopOutbound(); + base.StopInbound(); } /// @@ -327,12 +346,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP m_currentOutgoingClient != null ? m_currentOutgoingClient.Name : "none"); } - public new void Stop() - { - m_log.Info("[LLUDPSERVER]: Shutting down the LLUDP server for " + m_scene.RegionInfo.RegionName); - base.Stop(); - } - public void AddScene(IScene scene) { if (m_scene != null) @@ -349,6 +362,81 @@ namespace OpenSim.Region.ClientStack.LindenUDP m_scene = (Scene)scene; m_location = new Location(m_scene.RegionInfo.RegionHandle); + + MainConsole.Instance.Commands.AddCommand( + "Debug", + false, + "debug lludp start", + "debug lludp start ", + "Control LLUDP packet processing.", + "No effect if packet processing has already started.\n" + + "in - start inbound processing.\n" + + "out - start outbound processing.\n" + + "all - start in and outbound processing.\n", + HandleStartCommand); + + MainConsole.Instance.Commands.AddCommand( + "Debug", + false, + "debug lludp stop", + "debug lludp stop ", + "Stop LLUDP packet processing.", + "No effect if packet processing has already stopped.\n" + + "in - stop inbound processing.\n" + + "out - stop outbound processing.\n" + + "all - stop in and outbound processing.\n", + HandleStopCommand); + + MainConsole.Instance.Commands.AddCommand( + "Debug", + false, + "debug lludp status", + "debug lludp status", + "Return status of LLUDP packet processing.", + HandleStatusCommand); + } + + private void HandleStartCommand(string module, string[] args) + { + if (args.Length != 4) + { + MainConsole.Instance.Output("Usage: debug lludp start "); + return; + } + + string subCommand = args[3]; + + if (subCommand == "in" || subCommand == "all") + StartInbound(); + + if (subCommand == "out" || subCommand == "all") + StartOutbound(); + } + + private void HandleStopCommand(string module, string[] args) + { + if (args.Length != 4) + { + MainConsole.Instance.Output("Usage: debug lludp stop "); + return; + } + + string subCommand = args[3]; + + if (subCommand == "in" || subCommand == "all") + StopInbound(); + + if (subCommand == "out" || subCommand == "all") + StopOutbound(); + } + + private void HandleStatusCommand(string module, string[] args) + { + MainConsole.Instance.OutputFormat( + "IN LLUDP packet processing for {0} is {1}", m_scene.Name, IsRunningInbound ? "enabled" : "disabled"); + + MainConsole.Instance.OutputFormat( + "OUT LLUDP packet processing for {0} is {1}", m_scene.Name, IsRunningOutbound ? "enabled" : "disabled"); } public bool HandlesRegion(Location x) @@ -1174,7 +1262,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP // on to en-US to avoid number parsing issues Culture.SetCurrentCulture(); - while (base.IsRunning) + while (base.IsRunningInbound) { try { @@ -1216,7 +1304,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP // Action generic every round Action clientPacketHandler = ClientOutgoingPacketHandler; - while (base.IsRunning) + while (base.IsRunningOutbound) { try { diff --git a/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs b/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs index 039379d..828c23c 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs @@ -58,11 +58,12 @@ namespace OpenMetaverse /// Flag to process packets asynchronously or synchronously private bool m_asyncPacketHandling; - /// The all important shutdown flag - private volatile bool m_shutdownFlag = true; + /// Returns true if the server is currently listening for inbound packets, otherwise false + public bool IsRunningInbound { get; private set; } - /// Returns true if the server is currently listening, otherwise false - public bool IsRunning { get { return !m_shutdownFlag; } } + /// Returns true if the server is currently sending outbound packets, otherwise false + /// If IsRunningOut = false, then any request to send a packet is simply dropped. + public bool IsRunningOutbound { get; private set; } /// /// Default constructor @@ -76,7 +77,7 @@ namespace OpenMetaverse } /// - /// Start the UDP server + /// Start inbound UDP packet handling. /// /// The size of the receive buffer for /// the UDP socket. This value is passed up to the operating system @@ -91,11 +92,11 @@ namespace OpenMetaverse /// manner (not throwing an exception when the remote side resets the /// connection). This call is ignored on Mono where the flag is not /// necessary - public void Start(int recvBufferSize, bool asyncPacketHandling) + public void StartInbound(int recvBufferSize, bool asyncPacketHandling) { m_asyncPacketHandling = asyncPacketHandling; - if (m_shutdownFlag) + if (!IsRunningInbound) { const int SIO_UDP_CONNRESET = -1744830452; @@ -127,8 +128,7 @@ namespace OpenMetaverse m_udpSocket.Bind(ipep); - // we're not shutting down, we're starting up - m_shutdownFlag = false; + IsRunningInbound = true; // kick off an async receive. The Start() method will return, the // actual receives will occur asynchronously and will be caught in @@ -138,28 +138,38 @@ namespace OpenMetaverse } /// - /// Stops the UDP server + /// Start outbound UDP packet handling. /// - public void Stop() + public void StartOutbound() { - if (!m_shutdownFlag) + IsRunningOutbound = true; + } + + public void StopInbound() + { + if (IsRunningInbound) { // wait indefinitely for a writer lock. Once this is called, the .NET runtime // will deny any more reader locks, in effect blocking all other send/receive - // threads. Once we have the lock, we set shutdownFlag to inform the other + // threads. Once we have the lock, we set IsRunningInbound = false to inform the other // threads that the socket is closed. - m_shutdownFlag = true; + IsRunningInbound = false; m_udpSocket.Close(); } } + public void StopOutbound() + { + IsRunningOutbound = false; + } + private void AsyncBeginReceive() { // allocate a packet buffer //WrappedObject wrappedBuffer = Pool.CheckOut(); UDPPacketBuffer buf = new UDPPacketBuffer(); - if (!m_shutdownFlag) + if (IsRunningInbound) { try { @@ -212,7 +222,7 @@ namespace OpenMetaverse { // Asynchronous receive operations will complete here through the call // to AsyncBeginReceive - if (!m_shutdownFlag) + if (IsRunningInbound) { // Asynchronous mode will start another receive before the // callback for this packet is even fired. Very parallel :-) @@ -252,7 +262,7 @@ namespace OpenMetaverse public void AsyncBeginSend(UDPPacketBuffer buf) { - if (!m_shutdownFlag) + if (IsRunningOutbound) { try { -- cgit v1.1 From fc861c7904840b2b0b9de0621e9b5d976c8071b1 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Tue, 16 Oct 2012 23:35:05 +0100 Subject: Add optional pool for the UDPPacketBuffer objects that handle all incoming UDP data. Even when an avatar is standing still, it's sending in a constant stream of AgentUpdate packets that the client creates new UDPPacketBuffer objects to handle. This option pools those objects. This reduces memory churn. Currently off by default. Works but the scope can be expanded. --- .../Region/ClientStack/Linden/UDP/LLUDPServer.cs | 42 ++++++++++++---------- .../ClientStack/Linden/UDP/OpenSimUDPBase.cs | 31 ++++++++++++---- 2 files changed, 49 insertions(+), 24 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs index fc6dd4d..42247ca 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs @@ -188,7 +188,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// private IClientAPI m_currentIncomingClient; - public LLUDPServer(IPAddress listenIP, ref uint port, int proxyPortOffsetParm, bool allow_alternate_port, IConfigSource configSource, AgentCircuitManager circuitManager) + public LLUDPServer( + IPAddress listenIP, ref uint port, int proxyPortOffsetParm, bool allow_alternate_port, + IConfigSource configSource, AgentCircuitManager circuitManager) : base(listenIP, (int)port) { #region Environment.TickCount Measurement @@ -242,6 +244,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP { PacketPool.Instance.RecyclePackets = packetConfig.GetBoolean("RecyclePackets", true); PacketPool.Instance.RecycleDataBlocks = packetConfig.GetBoolean("RecycleDataBlocks", true); + UsePools = packetConfig.GetBoolean("RecycleBaseUDPPackets", false); } #region BinaryStats @@ -284,8 +287,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP private void StartInbound() { m_log.InfoFormat( - "[LLUDPSERVER]: Starting inbound packet processing for the LLUDP server in {0} mode", - m_asyncPacketHandling ? "asynchronous" : "synchronous"); + "[LLUDPSERVER]: Starting inbound packet processing for the LLUDP server in {0} mode with UsePools = {1}", + m_asyncPacketHandling ? "asynchronous" : "synchronous", UsePools); base.StartInbound(m_recvBufferSize, m_asyncPacketHandling); @@ -300,7 +303,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP Watchdog.DEFAULT_WATCHDOG_TIMEOUT_MS); } - private void StartOutbound() + private new void StartOutbound() { m_log.Info("[LLUDPSERVER]: Starting outbound packet processing for the LLUDP server"); @@ -317,7 +320,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP Watchdog.DEFAULT_WATCHDOG_TIMEOUT_MS); } - public new void Stop() + public void Stop() { m_log.Info("[LLUDPSERVER]: Shutting down the LLUDP server for " + m_scene.RegionInfo.RegionName); base.StopOutbound(); @@ -806,7 +809,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP LLUDPClient udpClient = null; Packet packet = null; int packetEnd = buffer.DataLength - 1; - IPEndPoint address = (IPEndPoint)buffer.RemoteEndPoint; + IPEndPoint endPoint = (IPEndPoint)buffer.RemoteEndPoint; #region Decoding @@ -816,7 +819,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP // "[LLUDPSERVER]: Dropping undersized packet with {0} bytes received from {1} in {2}", // buffer.DataLength, buffer.RemoteEndPoint, m_scene.RegionInfo.RegionName); - return; // Drop undersizd packet + return; // Drop undersized packet } int headerLen = 7; @@ -842,6 +845,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP // packet = Packet.BuildPacket(buffer.Data, ref packetEnd, // // Only allocate a buffer for zerodecoding if the packet is zerocoded // ((buffer.Data[0] & Helpers.MSG_ZEROCODED) != 0) ? new byte[4096] : null); + // If OpenSimUDPBase.UsePool == true (which is currently separate from the PacketPool) then we + // assume that packet construction does not retain a reference to byte[] buffer.Data (instead, all + // bytes are copied out). packet = PacketPool.Instance.GetPacket(buffer.Data, ref packetEnd, // Only allocate a buffer for zerodecoding if the packet is zerocoded ((buffer.Data[0] & Helpers.MSG_ZEROCODED) != 0) ? new byte[4096] : null); @@ -884,7 +890,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP // UseCircuitCode handling if (packet.Type == PacketType.UseCircuitCode) { - object[] array = new object[] { buffer, packet }; + // We need to copy the endpoint so that it doesn't get changed when another thread reuses the + // buffer. + object[] array = new object[] { new IPEndPoint(endPoint.Address, endPoint.Port), packet }; Util.FireAndForget(HandleUseCircuitCode, array); @@ -893,7 +901,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP // Determine which agent this packet came from IClientAPI client; - if (!m_scene.TryGetClient(address, out client) || !(client is LLClientView)) + if (!m_scene.TryGetClient(endPoint, out client) || !(client is LLClientView)) { //m_log.Debug("[LLUDPSERVER]: Received a " + packet.Type + " packet from an unrecognized source: " + address + " in " + m_scene.RegionInfo.RegionName); return; @@ -1091,21 +1099,19 @@ namespace OpenSim.Region.ClientStack.LindenUDP private void HandleUseCircuitCode(object o) { - IPEndPoint remoteEndPoint = null; + IPEndPoint endPoint = null; IClientAPI client = null; try { // DateTime startTime = DateTime.Now; object[] array = (object[])o; - UDPPacketBuffer buffer = (UDPPacketBuffer)array[0]; + endPoint = (IPEndPoint)array[0]; UseCircuitCodePacket uccp = (UseCircuitCodePacket)array[1]; m_log.DebugFormat( "[LLUDPSERVER]: Handling UseCircuitCode request for circuit {0} to {1} from IP {2}", - uccp.CircuitCode.Code, m_scene.RegionInfo.RegionName, buffer.RemoteEndPoint); - - remoteEndPoint = (IPEndPoint)buffer.RemoteEndPoint; + uccp.CircuitCode.Code, m_scene.RegionInfo.RegionName, endPoint); AuthenticateResponse sessionInfo; if (IsClientAuthorized(uccp, out sessionInfo)) @@ -1116,13 +1122,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP uccp.CircuitCode.Code, uccp.CircuitCode.ID, uccp.CircuitCode.SessionID, - remoteEndPoint, + endPoint, sessionInfo); // Send ack straight away to let the viewer know that the connection is active. // The client will be null if it already exists (e.g. if on a region crossing the client sends a use // circuit code to the existing child agent. This is not particularly obvious. - SendAckImmediate(remoteEndPoint, uccp.Header.Sequence); + SendAckImmediate(endPoint, uccp.Header.Sequence); // We only want to send initial data to new clients, not ones which are being converted from child to root. if (client != null) @@ -1133,7 +1139,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP // Don't create clients for unauthorized requesters. m_log.WarnFormat( "[LLUDPSERVER]: Ignoring connection request for {0} to {1} with unknown circuit code {2} from IP {3}", - uccp.CircuitCode.ID, m_scene.RegionInfo.RegionName, uccp.CircuitCode.Code, remoteEndPoint); + uccp.CircuitCode.ID, m_scene.RegionInfo.RegionName, uccp.CircuitCode.Code, endPoint); } // m_log.DebugFormat( @@ -1145,7 +1151,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP { m_log.ErrorFormat( "[LLUDPSERVER]: UseCircuitCode handling from endpoint {0}, client {1} {2} failed. Exception {3}{4}", - remoteEndPoint != null ? remoteEndPoint.ToString() : "n/a", + endPoint != null ? endPoint.ToString() : "n/a", client != null ? client.Name : "unknown", client != null ? client.AgentId.ToString() : "unknown", e.Message, diff --git a/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs b/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs index 828c23c..6e6b3ef 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs @@ -30,6 +30,7 @@ using System.Net; using System.Net.Sockets; using System.Threading; using log4net; +using OpenSim.Framework; namespace OpenMetaverse { @@ -58,6 +59,16 @@ namespace OpenMetaverse /// Flag to process packets asynchronously or synchronously private bool m_asyncPacketHandling; + /// + /// Pool to use for handling data. May be null if UsePools = false; + /// + protected OpenSim.Framework.Pool m_pool; + + /// + /// Are we to use object pool(s) to reduce memory churn when receiving data? + /// + public bool UsePools { get; protected set; } + /// Returns true if the server is currently listening for inbound packets, otherwise false public bool IsRunningInbound { get; private set; } @@ -70,6 +81,7 @@ namespace OpenMetaverse /// /// Local IP address to bind the server to /// Port to listening for incoming UDP packets on + /// /// Are we to use an object pool to get objects for handing inbound data? public OpenSimUDPBase(IPAddress bindAddress, int port) { m_localBindAddress = bindAddress; @@ -94,6 +106,11 @@ namespace OpenMetaverse /// necessary public void StartInbound(int recvBufferSize, bool asyncPacketHandling) { + if (UsePools) + m_pool = new Pool(() => new UDPPacketBuffer(), 500); + else + m_pool = null; + m_asyncPacketHandling = asyncPacketHandling; if (!IsRunningInbound) @@ -165,9 +182,12 @@ namespace OpenMetaverse private void AsyncBeginReceive() { - // allocate a packet buffer - //WrappedObject wrappedBuffer = Pool.CheckOut(); - UDPPacketBuffer buf = new UDPPacketBuffer(); + UDPPacketBuffer buf; + + if (UsePools) + buf = m_pool.GetObject(); + else + buf = new UDPPacketBuffer(); if (IsRunningInbound) { @@ -231,8 +251,6 @@ namespace OpenMetaverse // get the buffer that was created in AsyncBeginReceive // this is the received data - //WrappedObject wrappedBuffer = (WrappedObject)iar.AsyncState; - //UDPPacketBuffer buffer = wrappedBuffer.Instance; UDPPacketBuffer buffer = (UDPPacketBuffer)iar.AsyncState; try @@ -249,7 +267,8 @@ namespace OpenMetaverse catch (ObjectDisposedException) { } finally { - //wrappedBuffer.Dispose(); + if (UsePools) + m_pool.ReturnObject(buffer); // Synchronous mode waits until the packet callback completes // before starting the receive to fetch another packet -- cgit v1.1 From f35826eb31e2f286e3ae5bdbcf8c3beb4723d5d9 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Tue, 16 Oct 2012 23:50:45 +0100 Subject: minor: Make BasicCircuitTests.SetUp() call overriden base method instead of ignoring it. --- OpenSim/Region/ClientStack/Linden/UDP/Tests/BasicCircuitTests.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/Tests/BasicCircuitTests.cs b/OpenSim/Region/ClientStack/Linden/UDP/Tests/BasicCircuitTests.cs index fa9378c..556df30 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/Tests/BasicCircuitTests.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/Tests/BasicCircuitTests.cs @@ -65,8 +65,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests } [SetUp] - public void SetUp() + public override void SetUp() { + base.SetUp(); m_scene = new SceneHelpers().SetupScene(); } -- cgit v1.1 From 2ed59ad8ac3ec836517b60580f13ab37102a0c67 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Wed, 17 Oct 2012 21:08:15 +0100 Subject: If RecycleBaseUDPPackets = true, also pool IncomingPackets to reduce memory churn --- .../ClientStack/Linden/UDP/IncomingPacket.cs | 7 +++++- .../Region/ClientStack/Linden/UDP/LLUDPServer.cs | 25 +++++++++++++++++++++- 2 files changed, 30 insertions(+), 2 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/IncomingPacket.cs b/OpenSim/Region/ClientStack/Linden/UDP/IncomingPacket.cs index 1b8535c..e22670b 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/IncomingPacket.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/IncomingPacket.cs @@ -45,7 +45,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP public Packet Packet; /// - /// Default constructor + /// No arg constructor. + /// + public IncomingPacket() {} + + /// + /// Constructor /// /// Reference to the client this packet came from /// Packet data diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs index 42247ca..286d931 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs @@ -168,6 +168,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// Flag to signal when clients should send pings protected bool m_sendPing; + private Pool m_incomingPacketPool; + private int m_defaultRTO = 0; private int m_maxRTO = 0; private int m_ackTimeout = 0; @@ -274,6 +276,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP m_throttle = new TokenBucket(null, sceneThrottleBps); ThrottleRates = new ThrottleRates(configSource); + + if (UsePools) + m_incomingPacketPool = new Pool(() => new IncomingPacket(), 500); } public void Start() @@ -1012,8 +1017,21 @@ namespace OpenSim.Region.ClientStack.LindenUDP #endregion Ping Check Handling + IncomingPacket incomingPacket; + // Inbox insertion - packetInbox.Enqueue(new IncomingPacket((LLClientView)client, packet)); + if (UsePools) + { + incomingPacket = m_incomingPacketPool.GetObject(); + incomingPacket.Client = (LLClientView)client; + incomingPacket.Packet = packet; + } + else + { + incomingPacket = new IncomingPacket((LLClientView)client, packet); + } + + packetInbox.Enqueue(incomingPacket); } #region BinaryStats @@ -1283,7 +1301,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP } if (packetInbox.Dequeue(100, ref incomingPacket)) + { ProcessInPacket(incomingPacket);//, incomingPacket); Util.FireAndForget(ProcessInPacket, incomingPacket); + + if (UsePools) + m_incomingPacketPool.ReturnObject(incomingPacket); + } } catch (Exception ex) { -- cgit v1.1 From faf6b568393d8edfed103e0a656c98322c195e95 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Wed, 17 Oct 2012 23:08:14 +0100 Subject: Explicitly return only the incoming AgentUpdate packet as this is the only one we pool atm, rather than attempting to return all incoming packets. --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 11 +++++++---- OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs | 17 +++++++++++++++-- OpenSim/Region/ClientStack/Linden/UDP/PacketPool.cs | 10 ++++++++-- 3 files changed, 30 insertions(+), 8 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 0d4f09d..1e93b84 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -5425,16 +5425,19 @@ namespace OpenSim.Region.ClientStack.LindenUDP #region Scene/Avatar - private bool HandleAgentUpdate(IClientAPI sener, Packet Pack) + private bool HandleAgentUpdate(IClientAPI sener, Packet packet) { if (OnAgentUpdate != null) { bool update = false; - AgentUpdatePacket agenUpdate = (AgentUpdatePacket)Pack; + AgentUpdatePacket agenUpdate = (AgentUpdatePacket)packet; #region Packet Session and User Check if (agenUpdate.AgentData.SessionID != SessionId || agenUpdate.AgentData.AgentID != AgentId) + { + PacketPool.Instance.ReturnPacket(packet); return false; + } #endregion AgentUpdatePacket.AgentDataBlock x = agenUpdate.AgentData; @@ -5499,6 +5502,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP } } + PacketPool.Instance.ReturnPacket(packet); + return true; } @@ -11851,8 +11856,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP if (!ProcessPacketMethod(packet)) m_log.Warn("[CLIENT]: unhandled packet " + packet.Type); - - PacketPool.Instance.ReturnPacket(packet); } private static PrimitiveBaseShape GetShapeFromAddPacket(ObjectAddPacket addPacket) diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs index 286d931..419de66 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs @@ -314,7 +314,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP base.StartOutbound(); - // This thread will process the packets received that are placed on the packetInbox Watchdog.StartThread( OutgoingPacketHandler, string.Format("Outgoing Packets ({0})", m_scene.RegionInfo.RegionName), @@ -930,6 +929,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP // Handle appended ACKs if (packet.Header.AppendedAcks && packet.Header.AckList != null) { +// m_log.DebugFormat( +// "[LLUDPSERVER]: Handling {0} appended acks from {1} in {2}", +// packet.Header.AckList.Length, client.Name, m_scene.Name); + for (int i = 0; i < packet.Header.AckList.Length; i++) udpClient.NeedAcks.Acknowledge(packet.Header.AckList[i], now, packet.Header.Resent); } @@ -939,6 +942,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP { PacketAckPacket ackPacket = (PacketAckPacket)packet; +// m_log.DebugFormat( +// "[LLUDPSERVER]: Handling {0} packet acks for {1} in {2}", +// ackPacket.Packets.Length, client.Name, m_scene.Name); + for (int i = 0; i < ackPacket.Packets.Length; i++) udpClient.NeedAcks.Acknowledge(ackPacket.Packets[i].ID, now, packet.Header.Resent); @@ -952,6 +959,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP if (packet.Header.Reliable) { +// m_log.DebugFormat( +// "[LLUDPSERVER]: Adding ack request for {0} {1} from {2} in {3}", +// packet.Type, packet.Header.Sequence, client.Name, m_scene.Name); + udpClient.PendingAcks.Enqueue(packet.Header.Sequence); // This is a somewhat odd sequence of steps to pull the client.BytesSinceLastACK value out, @@ -998,6 +1009,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP if (packet.Type == PacketType.StartPingCheck) { +// m_log.DebugFormat("[LLUDPSERVER]: Handling ping from {0} in {1}", client.Name, m_scene.Name); + // We don't need to do anything else with ping checks StartPingCheckPacket startPing = (StartPingCheckPacket)packet; CompletePing(udpClient, startPing.PingID.PingID); @@ -1286,7 +1299,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP // on to en-US to avoid number parsing issues Culture.SetCurrentCulture(); - while (base.IsRunningInbound) + while (IsRunningInbound) { try { diff --git a/OpenSim/Region/ClientStack/Linden/UDP/PacketPool.cs b/OpenSim/Region/ClientStack/Linden/UDP/PacketPool.cs index 71f6fe1..2a3d14f 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/PacketPool.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/PacketPool.cs @@ -108,15 +108,19 @@ namespace OpenSim.Region.ClientStack.LindenUDP { if (!pool.ContainsKey(type) || pool[type] == null || (pool[type]).Count == 0) { +// m_log.DebugFormat("[PACKETPOOL]: Building {0} packet", type); + // Creating a new packet if we cannot reuse an old package packet = Packet.BuildPacket(type); } else { +// m_log.DebugFormat("[PACKETPOOL]: Pulling {0} packet", type); + // Recycle old packages m_packetsReusedStat.Antecedent++; - packet = (pool[type]).Pop(); + packet = pool[type].Pop(); } } @@ -227,7 +231,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP if ((pool[type]).Count < 50) { - (pool[type]).Push(packet); +// m_log.DebugFormat("[PACKETPOOL]: Pushing {0} packet", type); + + pool[type].Push(packet); } } break; -- cgit v1.1 From 3ec2923022dbc3e0b5411b17c6495dab6d641f0b Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Wed, 17 Oct 2012 23:54:05 +0100 Subject: Reuse the same AgentUpdateArgs object for each AgentUpdate UDP packet (of which there are 10 a second) rather than constructing a new one every time. We can do this because AgentUpdate packets are handled synchronously. --- .../Region/ClientStack/Linden/UDP/LLClientView.cs | 109 +++++++++++++-------- 1 file changed, 68 insertions(+), 41 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 1e93b84..65daca0 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -92,8 +92,23 @@ namespace OpenSim.Region.ClientStack.LindenUDP public event ObjectDeselect OnObjectDetach; public event ObjectDrop OnObjectDrop; public event Action OnCompleteMovementToRegion; + + /// + /// Called when an AgentUpdate message is received and before OnAgentUpdate. + /// + /// + /// Listeners must not retain a reference to AgentUpdateArgs since this object is reused for subsequent AgentUpdates. + /// public event UpdateAgent OnPreAgentUpdate; + + /// + /// Called when an AgentUpdate message is received and after OnPreAgentUpdate. + /// + /// + /// Listeners must not retain a reference to AgentUpdateArgs since this object is reused for subsequent AgentUpdates. + /// public event UpdateAgent OnAgentUpdate; + public event AgentRequestSit OnAgentRequestSit; public event AgentSit OnAgentSit; public event AvatarPickerRequest OnAvatarPickerRequest; @@ -347,7 +362,17 @@ namespace OpenSim.Region.ClientStack.LindenUDP private int m_moneyBalance; private int m_animationSequenceNumber = 1; private bool m_SendLogoutPacketWhenClosing = true; - private AgentUpdateArgs lastarg; + + /// + /// We retain a single AgentUpdateArgs so that we can constantly reuse it rather than construct a new one for + /// every single incoming AgentUpdate. Every client sends 10 AgentUpdate UDP messages per second, even if it + /// is doing absolutely nothing. + /// + /// + /// This does mean that agent updates must be processed synchronously, at least for each client, and called methods + /// cannot retain a reference to it outside of that method. + /// + private AgentUpdateArgs m_lastAgentUpdateArgs; protected Dictionary m_packetHandlers = new Dictionary(); protected Dictionary m_genericPacketHandlers = new Dictionary(); //PauPaw:Local Generic Message handlers @@ -5198,7 +5223,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP protected virtual void RegisterLocalPacketHandlers() { AddLocalPacketHandler(PacketType.LogoutRequest, HandleLogout); + + // If AgentUpdate is ever handled asynchronously, then we will also need to construct a new AgentUpdateArgs + // for each AgentUpdate packet. AddLocalPacketHandler(PacketType.AgentUpdate, HandleAgentUpdate, false); + AddLocalPacketHandler(PacketType.ViewerEffect, HandleViewerEffect, false); AddLocalPacketHandler(PacketType.AgentCachedTexture, HandleAgentTextureCached, false); AddLocalPacketHandler(PacketType.MultipleObjectUpdate, HandleMultipleObjUpdate, false); @@ -5429,73 +5458,71 @@ namespace OpenSim.Region.ClientStack.LindenUDP { if (OnAgentUpdate != null) { - bool update = false; - AgentUpdatePacket agenUpdate = (AgentUpdatePacket)packet; + AgentUpdatePacket agentUpdate = (AgentUpdatePacket)packet; #region Packet Session and User Check - if (agenUpdate.AgentData.SessionID != SessionId || agenUpdate.AgentData.AgentID != AgentId) + if (agentUpdate.AgentData.SessionID != SessionId || agentUpdate.AgentData.AgentID != AgentId) { PacketPool.Instance.ReturnPacket(packet); return false; } #endregion - AgentUpdatePacket.AgentDataBlock x = agenUpdate.AgentData; - - // We can only check when we have something to check - // against. + bool update = false; + AgentUpdatePacket.AgentDataBlock x = agentUpdate.AgentData; - if (lastarg != null) + if (m_lastAgentUpdateArgs != null) { + // These should be ordered from most-likely to + // least likely to change. I've made an initial + // guess at that. update = ( - (x.BodyRotation != lastarg.BodyRotation) || - (x.CameraAtAxis != lastarg.CameraAtAxis) || - (x.CameraCenter != lastarg.CameraCenter) || - (x.CameraLeftAxis != lastarg.CameraLeftAxis) || - (x.CameraUpAxis != lastarg.CameraUpAxis) || - (x.ControlFlags != lastarg.ControlFlags) || - (x.Far != lastarg.Far) || - (x.Flags != lastarg.Flags) || - (x.State != lastarg.State) || - (x.HeadRotation != lastarg.HeadRotation) || - (x.SessionID != lastarg.SessionID) || - (x.AgentID != lastarg.AgentID) + (x.BodyRotation != m_lastAgentUpdateArgs.BodyRotation) || + (x.CameraAtAxis != m_lastAgentUpdateArgs.CameraAtAxis) || + (x.CameraCenter != m_lastAgentUpdateArgs.CameraCenter) || + (x.CameraLeftAxis != m_lastAgentUpdateArgs.CameraLeftAxis) || + (x.CameraUpAxis != m_lastAgentUpdateArgs.CameraUpAxis) || + (x.ControlFlags != m_lastAgentUpdateArgs.ControlFlags) || + (x.Far != m_lastAgentUpdateArgs.Far) || + (x.Flags != m_lastAgentUpdateArgs.Flags) || + (x.State != m_lastAgentUpdateArgs.State) || + (x.HeadRotation != m_lastAgentUpdateArgs.HeadRotation) || + (x.SessionID != m_lastAgentUpdateArgs.SessionID) || + (x.AgentID != m_lastAgentUpdateArgs.AgentID) ); } else { + m_lastAgentUpdateArgs = new AgentUpdateArgs(); update = true; } - // These should be ordered from most-likely to - // least likely to change. I've made an initial - // guess at that. - if (update) { // m_log.DebugFormat("[LLCLIENTVIEW]: Triggered AgentUpdate for {0}", sener.Name); - AgentUpdateArgs arg = new AgentUpdateArgs(); - arg.AgentID = x.AgentID; - arg.BodyRotation = x.BodyRotation; - arg.CameraAtAxis = x.CameraAtAxis; - arg.CameraCenter = x.CameraCenter; - arg.CameraLeftAxis = x.CameraLeftAxis; - arg.CameraUpAxis = x.CameraUpAxis; - arg.ControlFlags = x.ControlFlags; - arg.Far = x.Far; - arg.Flags = x.Flags; - arg.HeadRotation = x.HeadRotation; - arg.SessionID = x.SessionID; - arg.State = x.State; + m_lastAgentUpdateArgs.AgentID = x.AgentID; + m_lastAgentUpdateArgs.BodyRotation = x.BodyRotation; + m_lastAgentUpdateArgs.CameraAtAxis = x.CameraAtAxis; + m_lastAgentUpdateArgs.CameraCenter = x.CameraCenter; + m_lastAgentUpdateArgs.CameraLeftAxis = x.CameraLeftAxis; + m_lastAgentUpdateArgs.CameraUpAxis = x.CameraUpAxis; + m_lastAgentUpdateArgs.ControlFlags = x.ControlFlags; + m_lastAgentUpdateArgs.Far = x.Far; + m_lastAgentUpdateArgs.Flags = x.Flags; + m_lastAgentUpdateArgs.HeadRotation = x.HeadRotation; + m_lastAgentUpdateArgs.SessionID = x.SessionID; + m_lastAgentUpdateArgs.State = x.State; + UpdateAgent handlerAgentUpdate = OnAgentUpdate; UpdateAgent handlerPreAgentUpdate = OnPreAgentUpdate; - lastarg = arg; // save this set of arguments for nexttime + if (handlerPreAgentUpdate != null) - OnPreAgentUpdate(this, arg); + OnPreAgentUpdate(this, m_lastAgentUpdateArgs); + if (handlerAgentUpdate != null) - OnAgentUpdate(this, arg); + OnAgentUpdate(this, m_lastAgentUpdateArgs); handlerAgentUpdate = null; handlerPreAgentUpdate = null; -- cgit v1.1 From 0811f3d28d70432e4657df735b5337726eb2f53f Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Thu, 18 Oct 2012 00:34:10 +0100 Subject: minor: Remove event method doc from LLClientView that I forgot in the last commit (1de80c) --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 15 --------------- 1 file changed, 15 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 65daca0..7427c59 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -92,23 +92,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP public event ObjectDeselect OnObjectDetach; public event ObjectDrop OnObjectDrop; public event Action OnCompleteMovementToRegion; - - /// - /// Called when an AgentUpdate message is received and before OnAgentUpdate. - /// - /// - /// Listeners must not retain a reference to AgentUpdateArgs since this object is reused for subsequent AgentUpdates. - /// public event UpdateAgent OnPreAgentUpdate; - - /// - /// Called when an AgentUpdate message is received and after OnPreAgentUpdate. - /// - /// - /// Listeners must not retain a reference to AgentUpdateArgs since this object is reused for subsequent AgentUpdates. - /// public event UpdateAgent OnAgentUpdate; - public event AgentRequestSit OnAgentRequestSit; public event AgentSit OnAgentSit; public event AvatarPickerRequest OnAvatarPickerRequest; -- cgit v1.1 From 1e7fb2dc364bd8fcbe92fc3cca45c3eea85e5558 Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Sun, 7 Oct 2012 05:53:52 +0100 Subject: i update core ode plugin and make it load is meshs (i hope) Signed-off-by: Melanie --- OpenSim/Region/Physics/OdePlugin/ODEPrim.cs | 51 +++++++++++++++++++++++++++- OpenSim/Region/Physics/OdePlugin/OdeScene.cs | 2 +- 2 files changed, 51 insertions(+), 2 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs b/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs index e7b3b2b..c86084c 100644 --- a/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs +++ b/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs @@ -100,6 +100,9 @@ namespace OpenSim.Region.Physics.OdePlugin private Vector3 m_taintAngularLock = Vector3.One; private IntPtr Amotor = IntPtr.Zero; + private object m_assetsLock = new object(); + private bool m_assetFailed = false; + private Vector3 m_PIDTarget; private float m_PIDTau; private float PID_D = 35f; @@ -282,6 +285,7 @@ namespace OpenSim.Region.Physics.OdePlugin } m_taintadd = true; + m_assetFailed = false; _parent_scene.AddPhysicsActorTaint(this); } @@ -1498,6 +1502,8 @@ Console.WriteLine("CreateGeom:"); mesh = _parent_scene.mesher.CreateMesh(Name, _pbs, _size, _parent_scene.meshSculptLOD, IsPhysical); // createmesh returns null when it's a shape that isn't a cube. // m_log.Debug(m_localID); + if (mesh == null) + CheckMeshAsset(); } #if SPAM @@ -1997,7 +2003,12 @@ Console.WriteLine(" JointCreateFixed"); // Don't need to re-enable body.. it's done in SetMesh if (_parent_scene.needsMeshing(_pbs)) + { mesh = _parent_scene.mesher.CreateMesh(Name, _pbs, _size, meshlod, IsPhysical); + if (mesh == null) + CheckMeshAsset(); + } + } CreateGeom(m_targetSpace, mesh); @@ -2057,6 +2068,8 @@ Console.WriteLine(" JointCreateFixed"); /// private void changeshape() { + m_taintshape = false; + // Cleanup of old prim geometry and Bodies if (IsPhysical && Body != IntPtr.Zero) { @@ -2084,6 +2097,7 @@ Console.WriteLine(" JointCreateFixed"); IMesh mesh = null; + if (_parent_scene.needsMeshing(_pbs)) { // Don't need to re-enable body.. it's done in CreateMesh @@ -2094,6 +2108,8 @@ Console.WriteLine(" JointCreateFixed"); // createmesh returns null when it doesn't mesh. mesh = _parent_scene.mesher.CreateMesh(Name, _pbs, _size, meshlod, IsPhysical); + if (mesh == null) + CheckMeshAsset(); } CreateGeom(m_targetSpace, mesh); @@ -2130,7 +2146,7 @@ Console.WriteLine(" JointCreateFixed"); } resetCollisionAccounting(); - m_taintshape = false; +// m_taintshape = false; } /// @@ -2396,6 +2412,7 @@ Console.WriteLine(" JointCreateFixed"); set { _pbs = value; + m_assetFailed = false; m_taintshape = true; } } @@ -3234,5 +3251,37 @@ Console.WriteLine(" JointCreateFixed"); { m_material = pMaterial; } + + + private void CheckMeshAsset() + { + if (_pbs.SculptEntry && !m_assetFailed && _pbs.SculptTexture != UUID.Zero) + { + m_assetFailed = true; + Util.FireAndForget(delegate + { + RequestAssetDelegate assetProvider = _parent_scene.RequestAssetMethod; + if (assetProvider != null) + assetProvider(_pbs.SculptTexture, MeshAssetReveived); + }); + } + } + + void MeshAssetReveived(AssetBase asset) + { + if (asset.Data != null && asset.Data.Length > 0) + { + if (!_pbs.SculptEntry) + return; + if (_pbs.SculptTexture.ToString() != asset.ID) + return; + + _pbs.SculptData = new byte[asset.Data.Length]; + asset.Data.CopyTo(_pbs.SculptData, 0); + m_assetFailed = false; + m_taintshape = true; + _parent_scene.AddPhysicsActorTaint(this); + } + } } } \ No newline at end of file diff --git a/OpenSim/Region/Physics/OdePlugin/OdeScene.cs b/OpenSim/Region/Physics/OdePlugin/OdeScene.cs index cbe21e2..d53bd90 100644 --- a/OpenSim/Region/Physics/OdePlugin/OdeScene.cs +++ b/OpenSim/Region/Physics/OdePlugin/OdeScene.cs @@ -4320,4 +4320,4 @@ namespace OpenSim.Region.Physics.OdePlugin m_stats[ODEPrimUpdateFrameMsStatName] = 0; } } -} \ No newline at end of file +} -- cgit v1.1 From de44e93aa27f55d939fd27493d195ee498270381 Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Wed, 3 Oct 2012 23:18:35 +0100 Subject: missing changed file Signed-off-by: Melanie --- OpenSim/Region/Physics/Manager/PhysicsScene.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Physics/Manager/PhysicsScene.cs b/OpenSim/Region/Physics/Manager/PhysicsScene.cs index 6a0558a..488900e 100644 --- a/OpenSim/Region/Physics/Manager/PhysicsScene.cs +++ b/OpenSim/Region/Physics/Manager/PhysicsScene.cs @@ -76,7 +76,7 @@ namespace OpenSim.Region.Physics.Manager get { return new NullPhysicsScene(); } } - public RequestAssetDelegate RequestAssetMethod { private get; set; } + public RequestAssetDelegate RequestAssetMethod { get; set; } public virtual void TriggerPhysicsBasedRestart() { -- cgit v1.1 From 7ab83f9eb22c5aaef3118ef45e4681503d6b93fc Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Sun, 7 Oct 2012 01:20:52 +0100 Subject: [DANGER UNTESTED] ODE mesh assets. Other plugins will not do meshs/sculpts now Signed-off-by: Melanie --- .../Region/Framework/Scenes/SceneObjectGroup.cs | 4 ++-- OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | 28 ++++++++++++---------- 2 files changed, 18 insertions(+), 14 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index 45bbbda..0729dc9 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -3444,8 +3444,8 @@ namespace OpenSim.Region.Framework.Scenes SceneObjectPart[] parts = m_parts.GetArray(); - for (int i = 0; i < parts.Length; i++) - parts[i].CheckSculptAndLoad(); +// for (int i = 0; i < parts.Length; i++) +// parts[i].CheckSculptAndLoad(); } /// diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index 199526e..58ef9f7 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -1014,9 +1014,9 @@ namespace OpenSim.Region.Framework.Scenes { actor.Size = m_shape.Scale; - if (Shape.SculptEntry) - CheckSculptAndLoad(); - else +// if (Shape.SculptEntry) +// CheckSculptAndLoad(); +// else ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor); } } @@ -1620,12 +1620,13 @@ namespace OpenSim.Region.Framework.Scenes if (userExposed) { +/* if (dupe.m_shape.SculptEntry && dupe.m_shape.SculptTexture != UUID.Zero) { ParentGroup.Scene.AssetService.Get( dupe.m_shape.SculptTexture.ToString(), dupe, dupe.AssetReceived); } - +*/ bool UsePhysics = ((dupe.Flags & PrimFlags.Physics) != 0); dupe.DoPhysicsPropertyUpdate(UsePhysics, true); } @@ -1643,6 +1644,7 @@ namespace OpenSim.Region.Framework.Scenes /// ID of asset received /// Register /// +/* protected void AssetReceived(string id, Object sender, AssetBase asset) { if (asset != null) @@ -1652,7 +1654,7 @@ namespace OpenSim.Region.Framework.Scenes "[SCENE OBJECT PART]: Part {0} {1} requested mesh/sculpt data for asset id {2} from asset service but received no data", Name, UUID, id); } - +*/ /// /// Do a physics property update for a NINJA joint. /// @@ -1833,9 +1835,9 @@ namespace OpenSim.Region.Framework.Scenes // If this part is a sculpt then delay the physics update until we've asynchronously loaded the // mesh data. - if (Shape.SculptEntry) - CheckSculptAndLoad(); - else +// if (Shape.SculptEntry) +// CheckSculptAndLoad(); +// else ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(pa); } } @@ -2511,6 +2513,7 @@ namespace OpenSim.Region.Framework.Scenes /// Set sculpt and mesh data, and tell the physics engine to process the change. /// /// The mesh itself. +/* public void SculptTextureCallback(AssetBase texture) { if (m_shape.SculptEntry) @@ -2538,7 +2541,7 @@ namespace OpenSim.Region.Framework.Scenes } } } - +*/ /// /// Send a full update to the client for the given part /// @@ -3783,7 +3786,7 @@ namespace OpenSim.Region.Framework.Scenes public void UpdateExtraParam(ushort type, bool inUse, byte[] data) { m_shape.ReadInUpdateExtraParam(type, inUse, data); - +/* if (type == 0x30) { if (m_shape.SculptEntry && m_shape.SculptTexture != UUID.Zero) @@ -3791,7 +3794,7 @@ namespace OpenSim.Region.Framework.Scenes ParentGroup.Scene.AssetService.Get(m_shape.SculptTexture.ToString(), this, AssetReceived); } } - +*/ if (ParentGroup != null) { ParentGroup.HasGroupChanged = true; @@ -4341,6 +4344,7 @@ namespace OpenSim.Region.Framework.Scenes /// /// When the physics engine has finished with it, the sculpt data is discarded to save memory. /// +/* public void CheckSculptAndLoad() { // m_log.DebugFormat("Processing CheckSculptAndLoad for {0} {1}", Name, LocalId); @@ -4366,7 +4370,7 @@ namespace OpenSim.Region.Framework.Scenes } } } - +*/ /// /// Update the texture entry for this part. /// -- cgit v1.1 From afab5f5cd1f0d39b62a664753897e5d871e6307d Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Thu, 18 Oct 2012 15:30:42 +0100 Subject: extend coment to include all unused SOG CheckSculptAndLoad() --- OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index 0729dc9..1fa6a75 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -3432,6 +3432,7 @@ namespace OpenSim.Region.Framework.Scenes /// /// When the physics engine has finished with it, the sculpt data is discarded to save memory. /// +/* public void CheckSculptAndLoad() { if (IsDeleted) @@ -3444,10 +3445,10 @@ namespace OpenSim.Region.Framework.Scenes SceneObjectPart[] parts = m_parts.GetArray(); -// for (int i = 0; i < parts.Length; i++) -// parts[i].CheckSculptAndLoad(); + for (int i = 0; i < parts.Length; i++) + parts[i].CheckSculptAndLoad(); } - +*/ /// /// Set the user group to which this scene object belongs. /// -- cgit v1.1 From a2c93133be90822076e4e8d0b4096a83a30d80bd Mon Sep 17 00:00:00 2001 From: Melanie Date: Thu, 18 Oct 2012 21:23:57 +0100 Subject: Remove extraneous calls to the now commented CheckSculptAndLoad --- OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | 24 ---------------------- 1 file changed, 24 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index 58ef9f7..da2c069 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -4028,14 +4028,6 @@ namespace OpenSim.Region.Framework.Scenes if (!wasUsingPhysics) { DoPhysicsPropertyUpdate(UsePhysics, false); - - if (!ParentGroup.IsDeleted) - { - if (LocalId == ParentGroup.RootPart.LocalId) - { - ParentGroup.CheckSculptAndLoad(); - } - } } } else @@ -4075,14 +4067,6 @@ namespace OpenSim.Region.Framework.Scenes pa.SetMaterial(Material); DoPhysicsPropertyUpdate(UsePhysics, true); - if (!ParentGroup.IsDeleted) - { - if (LocalId == ParentGroup.RootPart.LocalId) - { - ParentGroup.CheckSculptAndLoad(); - } - } - if ( ((AggregateScriptEvents & scriptEvents.collision) != 0) || ((AggregateScriptEvents & scriptEvents.collision_end) != 0) || @@ -4107,14 +4091,6 @@ namespace OpenSim.Region.Framework.Scenes else // it already has a physical representation { DoPhysicsPropertyUpdate(UsePhysics, false); // Update physical status. If it's phantom this will remove the prim - - if (!ParentGroup.IsDeleted) - { - if (LocalId == ParentGroup.RootPart.LocalId) - { - ParentGroup.CheckSculptAndLoad(); - } - } } } -- cgit v1.1 From a960273e91e43eedbab923539d817b81c0e50dbd Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Thu, 18 Oct 2012 23:02:57 +0100 Subject: Add number of inventory items to information displayed via "show part" console command --- .../World/Objects/Commands/ObjectCommandsModule.cs | 1 + OpenSim/Region/Framework/Interfaces/IEntityInventory.cs | 14 +++++++++++--- .../Region/Framework/Scenes/SceneObjectPartInventory.cs | 9 +++++++++ 3 files changed, 21 insertions(+), 3 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs b/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs index 7a35182..5d0163a 100644 --- a/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs +++ b/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs @@ -456,6 +456,7 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands sb.AppendFormat("Parent: {0}", sop.IsRoot ? "Is Root\n" : string.Format("{0} {1}\n", sop.ParentGroup.Name, sop.ParentGroup.UUID)); sb.AppendFormat("Link number: {0}\n", sop.LinkNum); + sb.AppendFormat("Items: {0}\n", sop.Inventory.Count); sb.AppendFormat("Flags: {0}\n", sop.Flags); return sb; diff --git a/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs b/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs index 8d62847..c457b2f 100644 --- a/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs +++ b/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs @@ -268,17 +268,25 @@ namespace OpenSim.Region.Framework.Interfaces void ApplyGodPermissions(uint perms); /// + /// Number of items in this inventory. + /// + int Count { get; } + + /// /// Returns true if this inventory contains any scripts /// bool ContainsScripts(); /// - /// Returns the count of scripts contained - /// + /// Number of scripts in this inventory. + /// + /// + /// Includes both running and non running scripts. + /// int ScriptCount(); /// - /// Returns the count of running scripts contained + /// Number of running scripts in this inventory. /// int RunningScriptCount(); diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs index 821fd81..bdb0446 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs @@ -92,6 +92,15 @@ namespace OpenSim.Region.Framework.Scenes QueryScriptStates(); } } + + public int Count + { + get + { + lock (m_items) + return m_items.Count; + } + } /// /// Constructor -- cgit v1.1 From 1f3c9db2b9ba71a84438b53b2a8a6f398137deb0 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Thu, 18 Oct 2012 23:41:18 +0100 Subject: Add --full option to "show object name/uuid/pos" to show info on all parts of an object, not just whole object summary information. --- .../World/Objects/Commands/ObjectCommandsModule.cs | 80 ++++++++++++++++------ 1 file changed, 60 insertions(+), 20 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs b/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs index 5d0163a..7ceac7e 100644 --- a/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs +++ b/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs @@ -139,25 +139,29 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands "Objects", false, "show object uuid", - "show object uuid ", - "Show details of a scene object with the given UUID", HandleShowObjectByUuid); + "show object uuid [--full] ", + "Show details of a scene object with the given UUID", + "The --full option will print out information on all the parts of the object.", + HandleShowObjectByUuid); m_console.Commands.AddCommand( "Objects", false, "show object name", - "show object name [--regex] ", + "show object name [--full] [--regex] ", "Show details of scene objects with the given name.", - "If --regex is specified then the name is treatead as a regular expression", + "The --full option will print out information on all the parts of the object.\n" + + "If --regex is specified then the name is treatead as a regular expression.", HandleShowObjectByName); m_console.Commands.AddCommand( "Objects", false, "show object pos", - "show object pos to ", + "show object pos [--full] to ", "Show details of scene objects within the given area.", - "Each component of the coord is comma separated. There must be no spaces between the commas.\n" + "The --full option will print out information on all the parts of the object.\n" + + "Each component of the coord is comma separated. There must be no spaces between the commas.\n" + "If you don't care about the z component you can simply omit it.\n" + "If you don't care about the x or y components then you can leave them blank (though a comma is still required)\n" + "If you want to specify the maxmimum value of a component then you can use ~ instead of a number\n" @@ -216,7 +220,12 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands // m_log.DebugFormat("[OBJECTS COMMANDS MODULE]: REGION {0} LOADED", scene.RegionInfo.RegionName); } - private void OutputSogsToConsole(Predicate searchPredicate) + /// + /// Outputs the sogs to console. + /// + /// + /// If true then output all part details. If false then output summary. + private void OutputSogsToConsole(Predicate searchPredicate, bool showFull) { List sceneObjects = m_scene.GetSceneObjectGroups().FindAll(searchPredicate); @@ -224,7 +233,7 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands foreach (SceneObjectGroup so in sceneObjects) { - AddSceneObjectReport(sb, so); + AddSceneObjectReport(sb, so, showFull); sb.Append("\n"); } @@ -253,21 +262,26 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands m_console.OutputFormat(sb.ToString()); } - private void HandleShowObjectByUuid(string module, string[] cmd) + private void HandleShowObjectByUuid(string module, string[] cmdparams) { if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene)) return; - if (cmd.Length < 4) + bool showFull = false; + OptionSet options = new OptionSet().Add("full", v => showFull = v != null ); + + List mainParams = options.Parse(cmdparams); + + if (mainParams.Count < 4) { m_console.OutputFormat("Usage: show object uuid "); return; } UUID objectUuid; - if (!UUID.TryParse(cmd[3], out objectUuid)) + if (!UUID.TryParse(mainParams[3], out objectUuid)) { - m_console.OutputFormat("{0} is not a valid uuid", cmd[3]); + m_console.OutputFormat("{0} is not a valid uuid", mainParams[3]); return; } @@ -280,7 +294,7 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands } StringBuilder sb = new StringBuilder(); - AddSceneObjectReport(sb, so); + AddSceneObjectReport(sb, so, showFull); m_console.OutputFormat(sb.ToString()); } @@ -290,14 +304,17 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene)) return; + bool showFull = false; bool useRegex = false; - OptionSet options = new OptionSet().Add("regex", v=> useRegex = v != null ); + OptionSet options = new OptionSet(); + options.Add("full", v => showFull = v != null ); + options.Add("regex", v => useRegex = v != null ); List mainParams = options.Parse(cmdparams); if (mainParams.Count < 4) { - m_console.OutputFormat("Usage: show object name [--regex] "); + m_console.OutputFormat("Usage: show object name [--full] [--regex] "); return; } @@ -315,7 +332,7 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands searchPredicate = so => so.Name == name; } - OutputSogsToConsole(searchPredicate); + OutputSogsToConsole(searchPredicate, showFull); } private void HandleShowObjectByPos(string module, string[] cmdparams) @@ -323,9 +340,14 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene)) return; - if (cmdparams.Length < 5) + bool showFull = false; + OptionSet options = new OptionSet().Add("full", v => showFull = v != null ); + + List mainParams = options.Parse(cmdparams); + + if (mainParams.Count < 5) { - m_console.OutputFormat("Usage: show object pos to "); + m_console.OutputFormat("Usage: show object pos [--full] to "); return; } @@ -337,7 +359,7 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands Predicate searchPredicate = so => Util.IsInsideBox(so.AbsolutePosition, startVector, endVector); - OutputSogsToConsole(searchPredicate); + OutputSogsToConsole(searchPredicate, showFull); } private void HandleShowPartByUuid(string module, string[] cmd) @@ -437,7 +459,25 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands OutputSopsToConsole(searchPredicate); } - private StringBuilder AddSceneObjectReport(StringBuilder sb, SceneObjectGroup so) + private StringBuilder AddSceneObjectReport(StringBuilder sb, SceneObjectGroup so, bool showFull) + { + if (showFull) + { + foreach (SceneObjectPart sop in so.Parts) + { + AddScenePartReport(sb, sop); + sb.Append("\n"); + } + } + else + { + AddSummarySceneObjectReport(sb, so); + } + + return sb; + } + + private StringBuilder AddSummarySceneObjectReport(StringBuilder sb, SceneObjectGroup so) { sb.AppendFormat("Name: {0}\n", so.Name); sb.AppendFormat("Description: {0}\n", so.Description); -- cgit v1.1 From 75f5e66d1c17ad6507a13c89345f3e4d351c44d2 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Thu, 18 Oct 2012 23:45:07 +0100 Subject: Add local and UUID to information output of "show object" and "show part" region console commands --- .../Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs b/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs index 7ceac7e..b90b71e 100644 --- a/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs +++ b/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs @@ -481,6 +481,8 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands { sb.AppendFormat("Name: {0}\n", so.Name); sb.AppendFormat("Description: {0}\n", so.Description); + sb.AppendFormat("Local ID {0}\n", so.LocalId); + sb.AppendFormat("UUID {0}\n", so.UUID); sb.AppendFormat("Location: {0} @ {1}\n", so.AbsolutePosition, so.Scene.RegionInfo.RegionName); sb.AppendFormat("Parts: {0}\n", so.PrimCount); sb.AppendFormat("Flags: {0}\n", so.RootPart.Flags); @@ -492,6 +494,8 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands { sb.AppendFormat("Name: {0}\n", sop.Name); sb.AppendFormat("Description: {0}\n", sop.Description); + sb.AppendFormat("Local ID {0}\n", sop.LocalId); + sb.AppendFormat("UUID {0}\n", sop.UUID); sb.AppendFormat("Location: {0} @ {1}\n", sop.AbsolutePosition, sop.ParentGroup.Scene.RegionInfo.RegionName); sb.AppendFormat("Parent: {0}", sop.IsRoot ? "Is Root\n" : string.Format("{0} {1}\n", sop.ParentGroup.Name, sop.ParentGroup.UUID)); -- cgit v1.1 From 845228b35e75dea4ec597ca394dd43196ff8bb48 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Thu, 18 Oct 2012 23:58:29 +0100 Subject: minor: Convert ad-hoc list building in ObjectCommandsModule to use ConsoleDisplayList --- .../World/Objects/Commands/ObjectCommandsModule.cs | 45 ++++++++++++---------- 1 file changed, 24 insertions(+), 21 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs b/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs index b90b71e..6feba21 100644 --- a/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs +++ b/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs @@ -479,31 +479,34 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands private StringBuilder AddSummarySceneObjectReport(StringBuilder sb, SceneObjectGroup so) { - sb.AppendFormat("Name: {0}\n", so.Name); - sb.AppendFormat("Description: {0}\n", so.Description); - sb.AppendFormat("Local ID {0}\n", so.LocalId); - sb.AppendFormat("UUID {0}\n", so.UUID); - sb.AppendFormat("Location: {0} @ {1}\n", so.AbsolutePosition, so.Scene.RegionInfo.RegionName); - sb.AppendFormat("Parts: {0}\n", so.PrimCount); - sb.AppendFormat("Flags: {0}\n", so.RootPart.Flags); - - return sb; + ConsoleDisplayList cdl = new ConsoleDisplayList(); + cdl.AddRow("Name", so.Name); + cdl.AddRow("Descrition", so.Description); + cdl.AddRow("Local ID", so.LocalId); + cdl.AddRow("UUID", so.UUID); + cdl.AddRow("Location", string.Format("{0} @ {1}", so.AbsolutePosition, so.Scene.Name)); + cdl.AddRow("Parts", so.PrimCount); + cdl.AddRow("Flags", so.RootPart.Flags); + + return sb.Append(cdl.ToString()); } private StringBuilder AddScenePartReport(StringBuilder sb, SceneObjectPart sop) { - sb.AppendFormat("Name: {0}\n", sop.Name); - sb.AppendFormat("Description: {0}\n", sop.Description); - sb.AppendFormat("Local ID {0}\n", sop.LocalId); - sb.AppendFormat("UUID {0}\n", sop.UUID); - sb.AppendFormat("Location: {0} @ {1}\n", sop.AbsolutePosition, sop.ParentGroup.Scene.RegionInfo.RegionName); - sb.AppendFormat("Parent: {0}", - sop.IsRoot ? "Is Root\n" : string.Format("{0} {1}\n", sop.ParentGroup.Name, sop.ParentGroup.UUID)); - sb.AppendFormat("Link number: {0}\n", sop.LinkNum); - sb.AppendFormat("Items: {0}\n", sop.Inventory.Count); - sb.AppendFormat("Flags: {0}\n", sop.Flags); - - return sb; + ConsoleDisplayList cdl = new ConsoleDisplayList(); + cdl.AddRow("Name", sop.Name); + cdl.AddRow("Description", sop.Description); + cdl.AddRow("Local ID", sop.LocalId); + cdl.AddRow("UUID", sop.UUID); + cdl.AddRow("Location", string.Format("{0} @ {1}", sop.AbsolutePosition, sop.ParentGroup.Scene.Name)); + cdl.AddRow( + "Parent", + sop.IsRoot ? "Is Root" : string.Format("{0} {1}", sop.ParentGroup.Name, sop.ParentGroup.UUID)); + cdl.AddRow("Link number", sop.LinkNum); + cdl.AddRow("Flags", sop.Flags); + cdl.AddRow("Items", sop.Inventory.Count); + + return sb.Append(cdl.ToString()); } private void HandleDeleteObject(string module, string[] cmd) -- cgit v1.1 From b058ba5859b1012a23e58c9b9e0d91f77ac19ba3 Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Fri, 19 Oct 2012 00:36:32 +0100 Subject: [UNTESTED] core Ode: stop trying to load a broken asset. Make broken assets behave like phantom by Nebadon request --- OpenSim/Region/Physics/OdePlugin/ODEPrim.cs | 118 +++++++++++++++++++++++----- 1 file changed, 97 insertions(+), 21 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs b/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs index c86084c..a6c657f 100644 --- a/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs +++ b/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs @@ -341,8 +341,17 @@ namespace OpenSim.Region.Physics.OdePlugin prim_geom = geom; //Console.WriteLine("SetGeom to " + prim_geom + " for " + Name); - d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories); - d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags); + if (m_assetFailed) + { + d.GeomSetCategoryBits(prim_geom, 0); + d.GeomSetCollideBits(prim_geom, 0); + } + else + { + + d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories); + d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags); + } _parent_scene.geom_name_map[prim_geom] = Name; _parent_scene.actor_name_map[prim_geom] = this; @@ -405,8 +414,17 @@ namespace OpenSim.Region.Physics.OdePlugin myrot.W = _orientation.W; d.BodySetQuaternion(Body, ref myrot); d.GeomSetBody(prim_geom, Body); - m_collisionCategories |= CollisionCategories.Body; - m_collisionFlags |= (CollisionCategories.Land | CollisionCategories.Wind); + + if (m_assetFailed) + { + d.GeomSetCategoryBits(prim_geom, 0); + d.GeomSetCollideBits(prim_geom, 0); + } + else + { + m_collisionCategories |= CollisionCategories.Body; + m_collisionFlags |= (CollisionCategories.Land | CollisionCategories.Wind); + } d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories); d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags); @@ -778,8 +796,16 @@ namespace OpenSim.Region.Physics.OdePlugin m_collisionCategories &= ~CollisionCategories.Body; m_collisionFlags &= ~(CollisionCategories.Wind | CollisionCategories.Land); - d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories); - d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags); + if (m_assetFailed) + { + d.GeomSetCategoryBits(prim_geom, 0); + d.GeomSetCollideBits(prim_geom, 0); + } + else + { + d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories); + d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags); + } d.BodyDestroy(Body); lock (childrenPrim) @@ -803,8 +829,17 @@ namespace OpenSim.Region.Physics.OdePlugin m_collisionCategories &= ~CollisionCategories.Body; m_collisionFlags &= ~(CollisionCategories.Wind | CollisionCategories.Land); - d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories); - d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags); + if (m_assetFailed) + { + d.GeomSetCategoryBits(prim_geom, 0); + d.GeomSetCollideBits(prim_geom, 0); + } + else + { + + d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories); + d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags); + } Body = IntPtr.Zero; } @@ -1094,8 +1129,16 @@ Console.WriteLine("ZProcessTaints for " + Name); prm.m_collisionFlags |= (CollisionCategories.Land | CollisionCategories.Wind); //Console.WriteLine(" GeomSetCategoryBits 1: " + prm.prim_geom + " - " + (int)prm.m_collisionCategories + " for " + Name); - d.GeomSetCategoryBits(prm.prim_geom, (int)prm.m_collisionCategories); - d.GeomSetCollideBits(prm.prim_geom, (int)prm.m_collisionFlags); + if (prm.m_assetFailed) + { + d.GeomSetCategoryBits(prm.prim_geom, 0); + d.GeomSetCollideBits(prm.prim_geom, 0); + } + else + { + d.GeomSetCategoryBits(prm.prim_geom, (int)prm.m_collisionCategories); + d.GeomSetCollideBits(prm.prim_geom, (int)prm.m_collisionFlags); + } d.Quaternion quat = new d.Quaternion(); quat.W = prm._orientation.W; @@ -1140,10 +1183,18 @@ Console.WriteLine("ZProcessTaints for " + Name); m_collisionCategories |= CollisionCategories.Body; m_collisionFlags |= (CollisionCategories.Land | CollisionCategories.Wind); -//Console.WriteLine("GeomSetCategoryBits 2: " + prim_geom + " - " + (int)m_collisionCategories + " for " + Name); - d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories); -//Console.WriteLine(" Post GeomSetCategoryBits 2"); - d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags); + if (m_assetFailed) + { + d.GeomSetCategoryBits(prim_geom, 0); + d.GeomSetCollideBits(prim_geom, 0); + } + else + { + //Console.WriteLine("GeomSetCategoryBits 2: " + prim_geom + " - " + (int)m_collisionCategories + " for " + Name); + d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories); + //Console.WriteLine(" Post GeomSetCategoryBits 2"); + d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags); + } d.Quaternion quat2 = new d.Quaternion(); quat2.W = _orientation.W; @@ -1304,8 +1355,16 @@ Console.WriteLine("ZProcessTaints for " + Name); disableBodySoft(); } - d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories); - d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags); + if (m_assetFailed) + { + d.GeomSetCategoryBits(prim_geom, 0); + d.GeomSetCollideBits(prim_geom, 0); + } + else + { + d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories); + d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags); + } if (IsPhysical) { @@ -1326,8 +1385,16 @@ Console.WriteLine("ZProcessTaints for " + Name); if (m_collidesWater) m_collisionFlags |= CollisionCategories.Water; - d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories); - d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags); + if (m_assetFailed) + { + d.GeomSetCategoryBits(prim_geom, 0); + d.GeomSetCollideBits(prim_geom, 0); + } + else + { + d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories); + d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags); + } if (IsPhysical) { @@ -1504,6 +1571,8 @@ Console.WriteLine("CreateGeom:"); // m_log.Debug(m_localID); if (mesh == null) CheckMeshAsset(); + else + m_assetFailed = false; } #if SPAM @@ -2007,6 +2076,8 @@ Console.WriteLine(" JointCreateFixed"); mesh = _parent_scene.mesher.CreateMesh(Name, _pbs, _size, meshlod, IsPhysical); if (mesh == null) CheckMeshAsset(); + else + m_assetFailed = false; } } @@ -2060,9 +2131,12 @@ Console.WriteLine(" JointCreateFixed"); m_collisionFlags &= ~CollisionCategories.Water; } - d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags); - } + if (m_assetFailed) + d.GeomSetCollideBits(prim_geom, 0); + else + d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags); + } /// /// Change prim in response to a shape taint. /// @@ -2110,6 +2184,8 @@ Console.WriteLine(" JointCreateFixed"); mesh = _parent_scene.mesher.CreateMesh(Name, _pbs, _size, meshlod, IsPhysical); if (mesh == null) CheckMeshAsset(); + else + m_assetFailed = false; } CreateGeom(m_targetSpace, mesh); @@ -3278,7 +3354,7 @@ Console.WriteLine(" JointCreateFixed"); _pbs.SculptData = new byte[asset.Data.Length]; asset.Data.CopyTo(_pbs.SculptData, 0); - m_assetFailed = false; +// m_assetFailed = false; m_taintshape = true; _parent_scene.AddPhysicsActorTaint(this); } -- cgit v1.1 From 941717638991f093ae600cd0f1b1d646f0cd3c21 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 19 Oct 2012 00:37:25 +0100 Subject: Make "show part" console commands print out information about each item the part contains --- .../World/Objects/Commands/ObjectCommandsModule.cs | 113 +++++++++++++++++---- 1 file changed, 93 insertions(+), 20 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs b/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs index 6feba21..87241e1 100644 --- a/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs +++ b/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs @@ -141,7 +141,8 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands "show object uuid", "show object uuid [--full] ", "Show details of a scene object with the given UUID", - "The --full option will print out information on all the parts of the object.", + "The --full option will print out information on all the parts of the object.\n" + + "For yet more detailed part information, use the \"show part\" commands.", HandleShowObjectByUuid); m_console.Commands.AddCommand( @@ -151,6 +152,7 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands "show object name [--full] [--regex] ", "Show details of scene objects with the given name.", "The --full option will print out information on all the parts of the object.\n" + + "For yet more detailed part information, use the \"show part\" commands.\n" + "If --regex is specified then the name is treatead as a regular expression.", HandleShowObjectByName); @@ -161,6 +163,7 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands "show object pos [--full] to ", "Show details of scene objects within the given area.", "The --full option will print out information on all the parts of the object.\n" + + "For yet more detailed part information, use the \"show part\" commands.\n" + "Each component of the coord is comma separated. There must be no spaces between the commas.\n" + "If you don't care about the z component you can simply omit it.\n" + "If you don't care about the x or y components then you can leave them blank (though a comma is still required)\n" @@ -242,7 +245,7 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands m_console.OutputFormat(sb.ToString()); } - private void OutputSopsToConsole(Predicate searchPredicate) + private void OutputSopsToConsole(Predicate searchPredicate, bool showFull) { List sceneObjects = m_scene.GetSceneObjectGroups(); List parts = new List(); @@ -253,7 +256,7 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands foreach (SceneObjectPart part in parts) { - AddScenePartReport(sb, part); + AddScenePartReport(sb, part, showFull); sb.Append("\n"); } @@ -362,21 +365,27 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands OutputSogsToConsole(searchPredicate, showFull); } - private void HandleShowPartByUuid(string module, string[] cmd) + private void HandleShowPartByUuid(string module, string[] cmdparams) { if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene)) return; - if (cmd.Length < 4) +// bool showFull = false; + OptionSet options = new OptionSet(); +// options.Add("full", v => showFull = v != null ); + + List mainParams = options.Parse(cmdparams); + + if (mainParams.Count < 4) { - m_console.OutputFormat("Usage: show part uuid "); + m_console.OutputFormat("Usage: show part uuid [--full] "); return; } UUID objectUuid; - if (!UUID.TryParse(cmd[3], out objectUuid)) + if (!UUID.TryParse(mainParams[3], out objectUuid)) { - m_console.OutputFormat("{0} is not a valid uuid", cmd[3]); + m_console.OutputFormat("{0} is not a valid uuid", mainParams[3]); return; } @@ -389,7 +398,7 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands } StringBuilder sb = new StringBuilder(); - AddScenePartReport(sb, sop); + AddScenePartReport(sb, sop, true); m_console.OutputFormat(sb.ToString()); } @@ -399,13 +408,19 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene)) return; - if (cmdparams.Length < 5) +// bool showFull = false; + OptionSet options = new OptionSet(); +// options.Add("full", v => showFull = v != null ); + + List mainParams = options.Parse(cmdparams); + + if (mainParams.Count < 5) { - m_console.OutputFormat("Usage: show part pos to "); + m_console.OutputFormat("Usage: show part pos [--full] to "); return; } - string rawConsoleStartVector = cmdparams[3]; + string rawConsoleStartVector = mainParams[3]; Vector3 startVector; if (!ConsoleUtil.TryParseConsoleMinVector(rawConsoleStartVector, out startVector)) @@ -414,7 +429,7 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands return; } - string rawConsoleEndVector = cmdparams[5]; + string rawConsoleEndVector = mainParams[5]; Vector3 endVector; if (!ConsoleUtil.TryParseConsoleMaxVector(rawConsoleEndVector, out endVector)) @@ -423,7 +438,7 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands return; } - OutputSopsToConsole(sop => Util.IsInsideBox(sop.AbsolutePosition, startVector, endVector)); + OutputSopsToConsole(sop => Util.IsInsideBox(sop.AbsolutePosition, startVector, endVector), true); } private void HandleShowPartByName(string module, string[] cmdparams) @@ -431,14 +446,17 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene)) return; +// bool showFull = false; bool useRegex = false; - OptionSet options = new OptionSet().Add("regex", v=> useRegex = v != null ); + OptionSet options = new OptionSet(); +// options.Add("full", v => showFull = v != null ); + options.Add("regex", v => useRegex = v != null ); List mainParams = options.Parse(cmdparams); if (mainParams.Count < 4) { - m_console.OutputFormat("Usage: show part name [--regex] "); + m_console.OutputFormat("Usage: show part name [--full] [--regex] "); return; } @@ -456,16 +474,26 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands searchPredicate = sop => sop.Name == name; } - OutputSopsToConsole(searchPredicate); + OutputSopsToConsole(searchPredicate, true); } + /// + /// Append a scene object report to an input StringBuilder + /// + /// + /// + /// + /// + /// If true then information on all parts of an object is appended. + /// If false then only summary information about an object is appended. + /// private StringBuilder AddSceneObjectReport(StringBuilder sb, SceneObjectGroup so, bool showFull) { if (showFull) { foreach (SceneObjectPart sop in so.Parts) { - AddScenePartReport(sb, sop); + AddScenePartReport(sb, sop, false); sb.Append("\n"); } } @@ -491,7 +519,17 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands return sb.Append(cdl.ToString()); } - private StringBuilder AddScenePartReport(StringBuilder sb, SceneObjectPart sop) + /// + /// Append a scene object part report to an input StringBuilder + /// + /// + /// + /// + /// + /// If true then information on each inventory item will be shown. + /// If false then only summary inventory information is shown. + /// + private StringBuilder AddScenePartReport(StringBuilder sb, SceneObjectPart sop, bool showFull) { ConsoleDisplayList cdl = new ConsoleDisplayList(); cdl.AddRow("Name", sop.Name); @@ -504,11 +542,46 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands sop.IsRoot ? "Is Root" : string.Format("{0} {1}", sop.ParentGroup.Name, sop.ParentGroup.UUID)); cdl.AddRow("Link number", sop.LinkNum); cdl.AddRow("Flags", sop.Flags); - cdl.AddRow("Items", sop.Inventory.Count); + + object itemsOutput; + if (showFull) + { + StringBuilder itemsSb = new StringBuilder("\n"); + itemsOutput = AddScenePartItemsReport(itemsSb, sop.Inventory).ToString(); + } + else + { + itemsOutput = sop.Inventory.Count; + } + + + cdl.AddRow("Items", itemsOutput); return sb.Append(cdl.ToString()); } + private StringBuilder AddScenePartItemsReport(StringBuilder sb, IEntityInventory inv) + { + ConsoleDisplayTable cdt = new ConsoleDisplayTable(); + cdt.Indent = 2; + + cdt.AddColumn("Name", 50); + cdt.AddColumn("Type", 12); + cdt.AddColumn("Running", 7); + cdt.AddColumn("Item UUID", 36); + cdt.AddColumn("Asset UUID", 36); + + foreach (TaskInventoryItem item in inv.GetInventoryItems()) + cdt.AddRow( + item.Name, + ((InventoryType)item.InvType).ToString(), + (InventoryType)item.InvType == InventoryType.LSL ? item.ScriptRunning.ToString() : "n/a", + item.ItemID.ToString(), + item.AssetID.ToString()); + + return sb.Append(cdt.ToString()); + } + private void HandleDeleteObject(string module, string[] cmd) { if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene)) -- cgit v1.1 From 0f70460a320da5606f3bdf316d5d25611fb0b3fb Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 19 Oct 2012 00:39:18 +0100 Subject: minor: comment out currently unused logger in DynamicTextureModule --- .../Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs b/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs index 1f340df..93a045e 100644 --- a/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs +++ b/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs @@ -42,7 +42,7 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture { public class DynamicTextureModule : IRegionModule, IDynamicTextureManager { - private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); +// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private const int ALL_SIDES = -1; -- cgit v1.1 From 28483150e2dcc123b632c89d0a08595b567af669 Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Fri, 19 Oct 2012 01:25:30 +0100 Subject: [UNTESTED] core Ode: let broken mesh physical prims collide with land as the defaul basic box so they don't go off world. --- OpenSim/Region/Physics/OdePlugin/ODEPrim.cs | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs b/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs index a6c657f..5a1fdf9 100644 --- a/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs +++ b/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs @@ -344,7 +344,7 @@ namespace OpenSim.Region.Physics.OdePlugin if (m_assetFailed) { d.GeomSetCategoryBits(prim_geom, 0); - d.GeomSetCollideBits(prim_geom, 0); + d.GeomSetCollideBits(prim_geom, BadAssetColideBits()); } else { @@ -418,7 +418,7 @@ namespace OpenSim.Region.Physics.OdePlugin if (m_assetFailed) { d.GeomSetCategoryBits(prim_geom, 0); - d.GeomSetCollideBits(prim_geom, 0); + d.GeomSetCollideBits(prim_geom, BadAssetColideBits()); } else { @@ -851,6 +851,11 @@ namespace OpenSim.Region.Physics.OdePlugin private static Dictionary m_MeshToTriMeshMap = new Dictionary(); + public int BadAssetColideBits() + { + return (m_isphysical ? (int)CollisionCategories.Land : 0); + } + private void setMesh(OdeScene parent_scene, IMesh mesh) { // m_log.DebugFormat("[ODE PRIM]: Setting mesh on {0} to {1}", Name, mesh); @@ -1132,7 +1137,7 @@ Console.WriteLine("ZProcessTaints for " + Name); if (prm.m_assetFailed) { d.GeomSetCategoryBits(prm.prim_geom, 0); - d.GeomSetCollideBits(prm.prim_geom, 0); + d.GeomSetCollideBits(prm.prim_geom, prm.BadAssetColideBits()); } else { @@ -1186,7 +1191,7 @@ Console.WriteLine("ZProcessTaints for " + Name); if (m_assetFailed) { d.GeomSetCategoryBits(prim_geom, 0); - d.GeomSetCollideBits(prim_geom, 0); + d.GeomSetCollideBits(prim_geom, BadAssetColideBits()); } else { @@ -1388,7 +1393,7 @@ Console.WriteLine("ZProcessTaints for " + Name); if (m_assetFailed) { d.GeomSetCategoryBits(prim_geom, 0); - d.GeomSetCollideBits(prim_geom, 0); + d.GeomSetCollideBits(prim_geom, BadAssetColideBits()); } else { @@ -2132,7 +2137,7 @@ Console.WriteLine(" JointCreateFixed"); } if (m_assetFailed) - d.GeomSetCollideBits(prim_geom, 0); + d.GeomSetCollideBits(prim_geom, BadAssetColideBits()); else d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags); -- cgit v1.1 From 32171708c3a29d2bb989b5638dc7536c6e4ecf3c Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Wed, 10 Oct 2012 01:37:59 +0100 Subject: normalize quaternion.Slerp outputs Signed-off-by: Melanie --- OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | 1 + 1 file changed, 1 insertion(+) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index da2c069..27ef4c9 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -4584,6 +4584,7 @@ namespace OpenSim.Region.Framework.Scenes } Quaternion rot = Quaternion.Slerp(RotationOffset,APIDTarget,1.0f/(float)m_APIDIterations); + rot.Normalize(); UpdateRotation(rot); m_APIDIterations--; -- cgit v1.1 From ec044537d50b425178c4e081abcf325d28028480 Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Thu, 18 Oct 2012 10:15:34 +0100 Subject: ensuring that operand order in llGetLinkName is internally consistent --- OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (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 ac74bf8..42ab39a 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -3828,7 +3828,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } // simplest case, this prims link number - if (m_host.LinkNum == linknum) + if (linknum == m_host.LinkNum) return m_host.Name; // Single prim -- cgit v1.1 From 597df51f918327f2ac46bc452a3288ec624e029f Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Thu, 18 Oct 2012 10:16:42 +0100 Subject: the simplest case for llGetLinkName also applies to the LINK_THIS constant --- OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (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 42ab39a..e8d0bea 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -3828,7 +3828,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } // simplest case, this prims link number - if (linknum == m_host.LinkNum) + if (linknum == m_host.LinkNum || linknum == ScriptBaseClass.LINK_THIS) return m_host.Name; // Single prim -- cgit v1.1 From 645e3171b41be4c5611bb43a9c14ec1d501ff8b9 Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Thu, 18 Oct 2012 10:18:46 +0100 Subject: since llGetLinkName has a "simplest case", it should be the first check made. --- OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 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 e8d0bea..e8bf5cf 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -3804,6 +3804,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public LSL_String llGetLinkName(int linknum) { m_host.AddScriptLPS(1); + // simplest case, this prims link number + if (linknum == m_host.LinkNum || linknum == ScriptBaseClass.LINK_THIS) + return m_host.Name; + // parse for sitting avatare-names List nametable = new List(); World.ForEachRootScenePresence(delegate(ScenePresence presence) @@ -3827,10 +3831,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api return nametable[totalprims - linknum]; } - // simplest case, this prims link number - if (linknum == m_host.LinkNum || linknum == ScriptBaseClass.LINK_THIS) - return m_host.Name; - // Single prim if (m_host.LinkNum == 0) { -- cgit v1.1 From af5383e479e264f2c257ff802f258bd03550e4b4 Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Thu, 18 Oct 2012 10:22:41 +0100 Subject: altering documentation for llGetLinkName, as the current documentation is rather lengthy for a "summary". --- .../Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (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 e8bf5cf..cf801ba 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -3773,6 +3773,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } /// + /// Returns the name of the child prim or seated avatar matching the + /// specified link number. + /// + /// + /// The number of a link in the linkset or a link-related constant. + /// + /// + /// The name determined to match the specified link number. + /// + /// /// The rules governing the returned name are not simple. The only /// time a blank name is returned is if the target prim has a blank /// name. If no prim with the given link number can be found then @@ -3800,7 +3810,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api /// Mentions NULL_KEY being returned /// http://wiki.secondlife.com/wiki/LlGetLinkName /// Mentions using the LINK_* constants, some of which are negative - /// + /// public LSL_String llGetLinkName(int linknum) { m_host.AddScriptLPS(1); -- cgit v1.1 From 6ba42e9e751477d5da3abf79eb1aaffc787dee30 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 19 Oct 2012 02:54:13 +0100 Subject: Fix a few minor issues in ArchiveReadRequest logging. --- OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs index a6923ef..ea806ec 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs @@ -290,7 +290,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver foreach (DearchiveContext sceneContext in sceneContexts.Values) { - m_log.InfoFormat("[ARCHIVER:] Loading region {0}", sceneContext.Scene.RegionInfo.RegionName); + m_log.InfoFormat("[ARCHIVER]: Loading region {0}", sceneContext.Scene.RegionInfo.RegionName); if (!m_merge) { @@ -324,7 +324,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver Util.FireAndForget(delegate(object o) { Thread.Sleep(15000); - m_log.Info("Starting scripts in scene objects"); + m_log.Info("[ARCHIVER]: Starting scripts in scene objects"); foreach (DearchiveContext sceneContext in sceneContexts.Values) { -- cgit v1.1 From f7dcd3300837f3be42031448198f70cbbb29e467 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 19 Oct 2012 03:12:58 +0100 Subject: minor: Increase attachment name field from 36 to 50 chars in "attachments show" report --- .../OptionalModules/Avatar/Attachments/AttachmentsCommandModule.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/OptionalModules/Avatar/Attachments/AttachmentsCommandModule.cs b/OpenSim/Region/OptionalModules/Avatar/Attachments/AttachmentsCommandModule.cs index d68aabc..68bcb4a 100644 --- a/OpenSim/Region/OptionalModules/Avatar/Attachments/AttachmentsCommandModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/Attachments/AttachmentsCommandModule.cs @@ -146,7 +146,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Attachments sb.AppendFormat("Attachments for {0}\n", sp.Name); ConsoleDisplayTable ct = new ConsoleDisplayTable() { Indent = 2 }; - ct.Columns.Add(new ConsoleDisplayTableColumn("Attachment Name", 36)); + ct.Columns.Add(new ConsoleDisplayTableColumn("Attachment Name", 50)); ct.Columns.Add(new ConsoleDisplayTableColumn("Local ID", 10)); ct.Columns.Add(new ConsoleDisplayTableColumn("Item ID", 36)); ct.Columns.Add(new ConsoleDisplayTableColumn("Attach Point", 14)); -- cgit v1.1 From fd7a097849b8a405bdd62cfe6d4ee2bbf0a3961c Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Fri, 12 Oct 2012 16:03:03 -0700 Subject: BulletSim: Update BSCharacter to use API2 interface. Add capsule shape to BSShapeCollection(). Remember last updated values so inter frame diffs can be computed. Parameterize avatarStandingFriction and reduce to 10 from 999. The latter high value made avatars very hard to push. Set CCD parameters for prims and characters of specified. --- .../Region/Physics/BulletSPlugin/BSCharacter.cs | 182 +++++++++++++++------ .../Region/Physics/BulletSPlugin/BSPhysObject.cs | 12 ++ OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | 66 +++++--- OpenSim/Region/Physics/BulletSPlugin/BSScene.cs | 21 ++- .../Physics/BulletSPlugin/BSShapeCollection.cs | 51 ++++-- .../Region/Physics/BulletSPlugin/BulletSimAPI.cs | 11 +- 6 files changed, 250 insertions(+), 93 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs index 2e6b2da..7c2f856 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs @@ -41,8 +41,6 @@ public class BSCharacter : BSPhysObject // private bool _stopped; private OMV.Vector3 _size; - private OMV.Vector3 _scale; - private PrimitiveBaseShape _pbs; private bool _grabbed; private bool _selected; private OMV.Vector3 _position; @@ -67,6 +65,10 @@ public class BSCharacter : BSPhysObject private bool _kinematic; private float _buoyancy; + // The friction and velocity of the avatar is modified depending on whether walking or not. + private OMV.Vector3 _appliedVelocity; // the last velocity applied to the avatar + private float _currentFriction; // the friction currently being used (changed by setVelocity). + private OMV.Vector3 _PIDTarget; private bool _usePID; private float _PIDTau; @@ -84,13 +86,15 @@ public class BSCharacter : BSPhysObject _flying = isFlying; _orientation = OMV.Quaternion.Identity; _velocity = OMV.Vector3.Zero; + _appliedVelocity = OMV.Vector3.Zero; _buoyancy = ComputeBuoyancyFromFlying(isFlying); + _currentFriction = PhysicsScene.Params.avatarStandingFriction; // The dimensions of the avatar capsule are kept in the scale. // Physics creates a unit capsule which is scaled by the physics engine. ComputeAvatarScale(_size); _avatarDensity = PhysicsScene.Params.avatarDensity; - // set _avatarVolume and _mass based on capsule size, _density and _scale + // set _avatarVolume and _mass based on capsule size, _density and Scale ComputeAvatarVolumeAndMass(); ShapeData shapeData = new ShapeData(); @@ -99,24 +103,24 @@ public class BSCharacter : BSPhysObject shapeData.Position = _position; shapeData.Rotation = _orientation; shapeData.Velocity = _velocity; - shapeData.Scale = _scale; + shapeData.Scale = Scale; shapeData.Mass = _mass; shapeData.Buoyancy = _buoyancy; shapeData.Static = ShapeData.numericFalse; - shapeData.Friction = PhysicsScene.Params.avatarFriction; + shapeData.Friction = PhysicsScene.Params.avatarStandingFriction; shapeData.Restitution = PhysicsScene.Params.avatarRestitution; // do actual create at taint time PhysicsScene.TaintedObject("BSCharacter.create", delegate() { DetailLog("{0},BSCharacter.create,taint", LocalID); - BulletSimAPI.CreateObject(PhysicsScene.WorldID, shapeData); + PhysicsScene.Shapes.GetBodyAndShape(true, PhysicsScene.World, this, shapeData, null, null, null); + + SetPhysicalProperties(); // Set the buoyancy for flying. This will be refactored when all the settings happen in C#. // If not set at creation, the avatar will stop flying when created after crossing a region boundry. - BulletSimAPI.SetObjectBuoyancy(PhysicsScene.WorldID, LocalID, _buoyancy); - - BSBody = new BulletBody(LocalID, BulletSimAPI.GetBodyHandle2(PhysicsScene.World.ptr, LocalID)); + ForceBuoyancy = _buoyancy; // This works here because CreateObject has already put the character into the physical world. BulletSimAPI.SetCollisionFilterMask2(BSBody.ptr, @@ -131,10 +135,40 @@ public class BSCharacter : BSPhysObject DetailLog("{0},BSCharacter.Destroy", LocalID); PhysicsScene.TaintedObject("BSCharacter.destroy", delegate() { - BulletSimAPI.DestroyObject(PhysicsScene.WorldID, LocalID); + PhysicsScene.Shapes.DereferenceBody(BSBody, true, null); + PhysicsScene.Shapes.DereferenceShape(BSShape, true, null); }); } + private void SetPhysicalProperties() + { + BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, BSBody.ptr); + + ZeroMotion(); + + OMV.Vector3 localInertia = BulletSimAPI.CalculateLocalInertia2(BSBody.ptr, MassRaw); + BulletSimAPI.SetMassProps2(BSBody.ptr, MassRaw, localInertia); + + // Set the velocity and compute the proper friction + ForceVelocity = _velocity; + + BulletSimAPI.SetFriction2(BSBody.ptr, _currentFriction); + BulletSimAPI.SetRestitution2(BSBody.ptr, PhysicsScene.Params.avatarRestitution); + + BulletSimAPI.SetLocalScaling2(BSShape.ptr, Scale); + BulletSimAPI.SetContactProcessingThreshold2(BSBody.ptr, PhysicsScene.Params.contactProcessingThreshold); + + if (PhysicsScene.Params.ccdMotionThreshold > 0f) + { + BulletSimAPI.SetCcdMotionThreshold2(BSBody.ptr, PhysicsScene.Params.ccdMotionThreshold); + BulletSimAPI.SetCcdSweepSphereRadius2(BSBody.ptr, PhysicsScene.Params.ccdSweptSphereRadius); + } + + BulletSimAPI.SetActivationState2(BSBody.ptr, (int)ActivationState.DISABLE_DEACTIVATION); + + BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, BSBody.ptr); + } + public override void RequestPhysicsterseUpdate() { base.RequestPhysicsterseUpdate(); @@ -147,7 +181,7 @@ public class BSCharacter : BSPhysObject get { // Avatar capsule size is kept in the scale parameter. - return new OMV.Vector3(_scale.X * 2, _scale.Y * 2, _scale.Z); + return new OMV.Vector3(Scale.X * 2, Scale.Y * 2, Scale.Z); } set { @@ -162,22 +196,25 @@ public class BSCharacter : BSPhysObject PhysicsScene.TaintedObject("BSCharacter.setSize", delegate() { - BulletSimAPI.SetObjectScaleMass(PhysicsScene.WorldID, LocalID, _scale, _mass, true); + BulletSimAPI.SetLocalScaling2(BSBody.ptr, Scale); + OMV.Vector3 localInertia = BulletSimAPI.CalculateLocalInertia2(BSBody.ptr, MassRaw); + BulletSimAPI.SetMassProps2(BSBody.ptr, MassRaw, localInertia); }); } } - public override PrimitiveBaseShape Shape { - set { _pbs = value; - } + public override OMV.Vector3 Scale { get; set; } + private PrimitiveBaseShape _pbs; + public override PrimitiveBaseShape Shape + { + set { _pbs = value;} } + public override bool Grabbed { - set { _grabbed = value; - } + set { _grabbed = value; } } public override bool Selected { - set { _selected = value; - } + set { _selected = value; } } public override void CrossingFailure() { return; } public override void link(PhysicsActor obj) { return; } @@ -204,7 +241,7 @@ public class BSCharacter : BSPhysObject public override OMV.Vector3 Position { get { - // _position = BulletSimAPI.GetObjectPosition(Scene.WorldID, _localID); + // _position = BulletSimAPI.GetObjectPosition2(Scene.World.ptr, LocalID); return _position; } set { @@ -214,7 +251,7 @@ public class BSCharacter : BSPhysObject PhysicsScene.TaintedObject("BSCharacter.setPosition", delegate() { DetailLog("{0},BSCharacter.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation); - BulletSimAPI.SetObjectTranslation(PhysicsScene.WorldID, LocalID, _position, _orientation); + BulletSimAPI.SetTranslation2(BSBody.ptr, _position, _orientation); }); } } @@ -273,7 +310,7 @@ public class BSCharacter : BSPhysObject BSScene.TaintCallback sanityOperation = delegate() { DetailLog("{0},BSCharacter.PositionSanityCheck,taint,pos={1},orient={2}", LocalID, _position, _orientation); - BulletSimAPI.SetObjectTranslation(PhysicsScene.WorldID, LocalID, _position, _orientation); + BulletSimAPI.SetTranslation2(BSBody.ptr, _position, _orientation); }; if (inTaintTime) sanityOperation(); @@ -284,11 +321,7 @@ public class BSCharacter : BSPhysObject return ret; } - public override float Mass { - get { - return _mass; - } - } + public override float Mass { get { return _mass; } } // used when we only want this prim's mass and not the linkset thing public override float MassRaw { get {return _mass; } } @@ -301,15 +334,13 @@ public class BSCharacter : BSPhysObject PhysicsScene.TaintedObject("BSCharacter.SetForce", delegate() { DetailLog("{0},BSCharacter.setForce,taint,force={1}", LocalID, _force); - BulletSimAPI.SetObjectForce(PhysicsScene.WorldID, LocalID, _force); + BulletSimAPI.SetObjectForce2(BSBody.ptr, _force); }); } } - public override int VehicleType { - get { return 0; } - set { return; } - } + // Avatars don't do vehicles + public override int VehicleType { get { return 0; } set { return; } } public override void VehicleFloatParam(int param, float value) { } public override void VehicleVectorParam(int param, OMV.Vector3 value) {} public override void VehicleRotationParam(int param, OMV.Quaternion rotation) { } @@ -328,15 +359,35 @@ public class BSCharacter : BSPhysObject PhysicsScene.TaintedObject("BSCharacter.setVelocity", delegate() { DetailLog("{0},BSCharacter.setVelocity,taint,vel={1}", LocalID, _velocity); - BulletSimAPI.SetObjectVelocity(PhysicsScene.WorldID, LocalID, _velocity); + ForceVelocity = _velocity; }); } } public override OMV.Vector3 ForceVelocity { get { return _velocity; } set { + // Depending on whether the avatar is moving or not, change the friction + // to keep the avatar from slipping around + if (_velocity.Length() == 0) + { + if (_currentFriction != PhysicsScene.Params.avatarStandingFriction) + { + _currentFriction = PhysicsScene.Params.avatarStandingFriction; + BulletSimAPI.SetFriction2(BSBody.ptr, _currentFriction); + } + } + else + { + if (_currentFriction == 999f) + { + _currentFriction = PhysicsScene.Params.avatarFriction; + BulletSimAPI.SetFriction2(BSBody.ptr, _currentFriction); + } + } _velocity = value; - BulletSimAPI.SetObjectVelocity(PhysicsScene.WorldID, LocalID, _velocity); + _appliedVelocity = value; + BulletSimAPI.SetLinearVelocity2(BSBody.ptr, _velocity); + BulletSimAPI.Activate2(BSBody.ptr, true); } } public override OMV.Vector3 Torque { @@ -360,8 +411,8 @@ public class BSCharacter : BSPhysObject // m_log.DebugFormat("{0}: set orientation to {1}", LogHeader, _orientation); PhysicsScene.TaintedObject("BSCharacter.setOrientation", delegate() { - // _position = BulletSimAPI.GetObjectPosition(Scene.WorldID, _localID); - BulletSimAPI.SetObjectTranslation(PhysicsScene.WorldID, LocalID, _position, _orientation); + // _position = BulletSimAPI.GetPosition2(BSBody.ptr); + BulletSimAPI.SetTranslation2(BSBody.ptr, _position, _orientation); }); } } @@ -389,12 +440,18 @@ public class BSCharacter : BSPhysObject set { _isPhysical = value; } } + public override bool IsSolid { + get { return true; } + } + public override bool IsStatic { + get { return false; } + } public override bool Flying { get { return _flying; } set { _flying = value; // simulate flying by changing the effect of gravity - this.Buoyancy = ComputeBuoyancyFromFlying(_flying); + Buoyancy = ComputeBuoyancyFromFlying(_flying); } } // Flying is implimented by changing the avatar's buoyancy. @@ -454,10 +511,19 @@ public class BSCharacter : BSPhysObject PhysicsScene.TaintedObject("BSCharacter.setBuoyancy", delegate() { DetailLog("{0},BSCharacter.setBuoyancy,taint,buoy={1}", LocalID, _buoyancy); - BulletSimAPI.SetObjectBuoyancy(PhysicsScene.WorldID, LocalID, _buoyancy); + ForceBuoyancy = _buoyancy; }); } } + public override float ForceBuoyancy { + get { return _buoyancy; } + set { _buoyancy = value; + DetailLog("{0},BSCharacter.setForceBuoyancy,taint,buoy={1}", LocalID, _buoyancy); + // Buoyancy is faked by changing the gravity applied to the object + float grav = PhysicsScene.Params.gravity * (1f - _buoyancy); + BulletSimAPI.SetGravity2(BSBody.ptr, new OMV.Vector3(0f, 0f, grav)); + } + } // Used for MoveTo public override OMV.Vector3 PIDTarget { @@ -518,27 +584,29 @@ public class BSCharacter : BSPhysObject private void ComputeAvatarScale(OMV.Vector3 size) { - _scale.X = PhysicsScene.Params.avatarCapsuleRadius; - _scale.Y = PhysicsScene.Params.avatarCapsuleRadius; + OMV.Vector3 newScale = OMV.Vector3.Zero; + newScale.X = PhysicsScene.Params.avatarCapsuleRadius; + newScale.Y = PhysicsScene.Params.avatarCapsuleRadius; // The 1.15 came from ODE but it seems to cause the avatar to float off the ground - // _scale.Z = (_size.Z * 1.15f) - (_scale.X + _scale.Y); - _scale.Z = (_size.Z) - (_scale.X + _scale.Y); + // Scale.Z = (_size.Z * 1.15f) - (Scale.X + Scale.Y); + newScale.Z = (_size.Z) - (Scale.X + Scale.Y); + Scale = newScale; } - // set _avatarVolume and _mass based on capsule size, _density and _scale + // set _avatarVolume and _mass based on capsule size, _density and Scale private void ComputeAvatarVolumeAndMass() { _avatarVolume = (float)( Math.PI - * _scale.X - * _scale.Y // the area of capsule cylinder - * _scale.Z // times height of capsule cylinder + * Scale.X + * Scale.Y // the area of capsule cylinder + * Scale.Z // times height of capsule cylinder + 1.33333333f * Math.PI - * _scale.X - * Math.Min(_scale.X, _scale.Y) - * _scale.Y // plus the volume of the capsule end caps + * Scale.X + * Math.Min(Scale.X, Scale.Y) + * Scale.Y // plus the volume of the capsule end caps ); _mass = _avatarDensity * _avatarVolume; } @@ -555,6 +623,22 @@ public class BSCharacter : BSPhysObject // Do some sanity checking for the avatar. Make sure it's above ground and inbounds. PositionSanityCheck2(true); + // remember the current and last set values + LastEntityProperties = CurrentEntityProperties; + CurrentEntityProperties = entprop; + + if (entprop.Velocity != LastEntityProperties.Velocity) + { + // Changes in the velocity are suppressed in avatars. + // That's just the way they are defined. + OMV.Vector3 avVel = new OMV.Vector3(_appliedVelocity.X, _appliedVelocity.Y, entprop.Velocity.Z); + _velocity = avVel; + BulletSimAPI.SetLinearVelocity2(BSBody.ptr, avVel); + } + + // Tell the linkset about this + Linkset.UpdateProperties(this); + // Avatars don't report their changes the usual way. Changes are checked for in the heartbeat loop. // base.RequestPhysicsterseUpdate(); diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs index cae599c..34dec26 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs @@ -69,6 +69,16 @@ public abstract class BSPhysObject : PhysicsActor // Reference to the physical shape (btCollisionShape) of this object public BulletShape BSShape; + // When the physical properties are updated, an EntityProperty holds the update values. + // Keep the current and last EntityProperties to enable computation of differences + // between the current update and the previous values. + public EntityProperties CurrentEntityProperties { get; set; } + public EntityProperties LastEntityProperties { get; set; } + + public abstract OMV.Vector3 Scale { get; set; } + public abstract bool IsSolid { get; } + public abstract bool IsStatic { get; } + // Stop all physical motion. public abstract void ZeroMotion(); @@ -89,6 +99,8 @@ public abstract class BSPhysObject : PhysicsActor public abstract OMV.Vector3 ForceRotationalVelocity { get; set; } + public abstract float ForceBuoyancy { get; set; } + #region Collisions // Requested number of milliseconds between collision events. Zero means disabled. diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index 6a4365c..3421e30 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs @@ -172,11 +172,8 @@ public sealed class BSPrim : BSPhysObject } // Scale is what we set in the physics engine. It is different than 'size' in that // 'size' can be encorporated into the mesh. In that case, the scale is <1,1,1>. - public OMV.Vector3 Scale - { - get { return _scale; } - set { _scale = value; } - } + public override OMV.Vector3 Scale { get; set; } + public override PrimitiveBaseShape Shape { set { _pbs = value; @@ -325,9 +322,9 @@ public sealed class BSPrim : BSPhysObject } // A version of the sanity check that also makes sure a new position value is - // pushed back to the physics engine. This routine would be used by anyone + // pushed to the physics engine. This routine would be used by anyone // who is not already pushing the value. - private bool PositionSanityCheck2(bool inTaintTime) + private bool PositionSanityCheck(bool inTaintTime) { bool ret = false; if (PositionSanityCheck()) @@ -336,8 +333,8 @@ public sealed class BSPrim : BSPhysObject // just assign to "Position" because of potential call loops. BSScene.TaintCallback sanityOperation = delegate() { - DetailLog("{0},BSPrim.PositionSanityCheck,taint,pos={1},orient={2}", LocalID, _position, _orientation); - BulletSimAPI.SetObjectTranslation(PhysicsScene.WorldID, LocalID, _position, _orientation); + DetailLog("{0},BSPrim.PositionSanityCheck,taint,pos={1},orient={2}", LocalID, _position, _orientation); + ForcePosition = _position; }; if (inTaintTime) sanityOperation(); @@ -547,13 +544,13 @@ public sealed class BSPrim : BSPhysObject } // An object is static (does not move) if selected or not physical - private bool IsStatic + public override bool IsStatic { get { return _isSelected || !IsPhysical; } } // An object is solid if it's not phantom and if it's not doing VolumeDetect - public bool IsSolid + public override bool IsSolid { get { return !IsPhantom && !_isVolumeDetect; } } @@ -631,6 +628,12 @@ public sealed class BSPrim : BSPhysObject BulletSimAPI.SetMassProps2(BSBody.ptr, 0f, OMV.Vector3.Zero); // There is no inertia in a static object BulletSimAPI.UpdateInertiaTensor2(BSBody.ptr); + // Set collision detection parameters + if (PhysicsScene.Params.ccdMotionThreshold > 0f) + { + BulletSimAPI.SetCcdMotionThreshold2(BSBody.ptr, PhysicsScene.Params.ccdMotionThreshold); + BulletSimAPI.SetCcdSweepSphereRadius2(BSBody.ptr, PhysicsScene.Params.ccdSweptSphereRadius); + } // There can be special things needed for implementing linksets Linkset.MakeStatic(this); // The activation state is 'disabled' so Bullet will not try to act on it. @@ -662,6 +665,13 @@ public sealed class BSPrim : BSPhysObject BulletSimAPI.SetMassProps2(BSBody.ptr, _mass, inertia); BulletSimAPI.UpdateInertiaTensor2(BSBody.ptr); + // Set collision detection parameters + if (PhysicsScene.Params.ccdMotionThreshold > 0f) + { + BulletSimAPI.SetCcdMotionThreshold2(BSBody.ptr, PhysicsScene.Params.ccdMotionThreshold); + BulletSimAPI.SetCcdSweepSphereRadius2(BSBody.ptr, PhysicsScene.Params.ccdSweptSphereRadius); + } + // Various values for simulation limits BulletSimAPI.SetDamping2(BSBody.ptr, PhysicsScene.Params.linearDamping, PhysicsScene.Params.angularDamping); BulletSimAPI.SetDeactivationTime2(BSBody.ptr, PhysicsScene.Params.deactivationTime); @@ -812,14 +822,21 @@ public sealed class BSPrim : BSPhysObject set { _buoyancy = value; PhysicsScene.TaintedObject("BSPrim.setBuoyancy", delegate() - { - // DetailLog("{0},BSPrim.SetBuoyancy,taint,buoy={1}", LocalID, _buoyancy); - // Buoyancy is faked by changing the gravity applied to the object - float grav = PhysicsScene.Params.gravity * (1f - _buoyancy); - BulletSimAPI.SetGravity2(BSBody.ptr, new OMV.Vector3(0f, 0f, grav)); + { + ForceBuoyancy = _buoyancy; }); } } + public override float ForceBuoyancy { + get { return _buoyancy; } + set { + _buoyancy = value; + // DetailLog("{0},BSPrim.setForceBuoyancy,taint,buoy={1}", LocalID, _buoyancy); + // Buoyancy is faked by changing the gravity applied to the object + float grav = PhysicsScene.Params.gravity * (1f - _buoyancy); + BulletSimAPI.SetGravity2(BSBody.ptr, new OMV.Vector3(0f, 0f, grav)); + } + } // Used for MoveTo public override OMV.Vector3 PIDTarget { @@ -1269,8 +1286,8 @@ public sealed class BSPrim : BSPhysObject const float VELOCITY_TOLERANCE = 0.001f; const float POSITION_TOLERANCE = 0.05f; const float ACCELERATION_TOLERANCE = 0.01f; - const float ROTATIONAL_VELOCITY_TOLERANCE = 0.01f; - + const float ROTATIONAL_VELOCITY_TOLERANCE = 0.01f; + public override void UpdateProperties(EntityProperties entprop) { /* @@ -1326,11 +1343,13 @@ public sealed class BSPrim : BSPhysObject _orientation = entprop.Rotation; _velocity = entprop.Velocity; _acceleration = entprop.Acceleration; - _rotationalVelocity = entprop.RotationalVelocity; + _rotationalVelocity = entprop.RotationalVelocity; + + // remember the current and last set values + LastEntityProperties = CurrentEntityProperties; + CurrentEntityProperties = entprop; - PositionSanityCheck2(true); - - Linkset.UpdateProperties(this); + PositionSanityCheck(true); DetailLog("{0},BSPrim.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5}", LocalID, _position, _orientation, _velocity, _acceleration, _rotationalVelocity); @@ -1348,6 +1367,9 @@ public sealed class BSPrim : BSPhysObject entprop.Acceleration, entprop.RotationalVelocity); } */ + // The linkset implimentation might want to know about this. + + Linkset.UpdateProperties(this); } } } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs index 2c3c481..5158011 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs @@ -256,10 +256,10 @@ public class BSScene : PhysicsScene, IPhysicsParameters Vector3 worldExtent = new Vector3(Constants.RegionSize, Constants.RegionSize, Constants.RegionHeight); // m_log.DebugFormat("{0}: Initialize: Calling BulletSimAPI.Initialize.", LogHeader); - WorldID = BulletSimAPI.Initialize(worldExtent, m_paramsHandle.AddrOfPinnedObject(), + World = new BulletSim(0, this, BulletSimAPI.Initialize2(worldExtent, m_paramsHandle.AddrOfPinnedObject(), m_maxCollisionsPerFrame, m_collisionArrayPinnedHandle.AddrOfPinnedObject(), m_maxUpdatesPerFrame, m_updateArrayPinnedHandle.AddrOfPinnedObject(), - m_DebugLogCallbackHandle); + m_DebugLogCallbackHandle)); // Initialization to support the transition to a new API which puts most of the logic // into the C# code so it is easier to modify and add to. @@ -360,7 +360,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters } // Anything left in the unmanaged code should be cleaned out - BulletSimAPI.Shutdown(WorldID); + BulletSimAPI.Shutdown2(World.ptr); // Not logging any more PhysicsLogging.Close(); @@ -498,7 +498,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters { if (PhysicsLogging.Enabled) beforeTime = Util.EnvironmentTickCount(); - numSubSteps = BulletSimAPI.PhysicsStep(WorldID, timeStep, m_maxSubSteps, m_fixedTimeStep, + numSubSteps = BulletSimAPI.PhysicsStep2(World.ptr, timeStep, m_maxSubSteps, m_fixedTimeStep, out updatedEntityCount, out updatedEntitiesPtr, out collidersCount, out collidersPtr); if (PhysicsLogging.Enabled) simTime = Util.EnvironmentTickCountSubtract(beforeTime); @@ -1011,6 +1011,11 @@ public class BSScene : PhysicsScene, IPhysicsParameters (s,cf,p,v) => { s.m_params[0].avatarFriction = cf.GetFloat(p, v); }, (s) => { return s.m_params[0].avatarFriction; }, (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarFriction, p, l, v); } ), + new ParameterDefn("AvatarStandingFriction", "Avatar friction when standing. Changed on avatar recreation.", + 10f, + (s,cf,p,v) => { s.m_params[0].avatarStandingFriction = cf.GetFloat(p, v); }, + (s) => { return s.m_params[0].avatarStandingFriction; }, + (s,p,l,v) => { s.m_params[0].avatarStandingFriction = v; } ), new ParameterDefn("AvatarDensity", "Density of an avatar. Changed on avatar recreation.", 60f, (s,cf,p,v) => { s.m_params[0].avatarDensity = cf.GetFloat(p, v); }, @@ -1246,7 +1251,9 @@ public class BSScene : PhysicsScene, IPhysicsParameters case PhysParameterEntry.APPLY_TO_NONE: defaultLoc = val; // setting only the default value break; - case PhysParameterEntry.APPLY_TO_ALL: + case PhysParameterEntry.APPLY_TO_ALL: + m_log.ErrorFormat("{0} Cannot change parameters of multiple objects. Someday it will be added.", LogHeader); + /* defaultLoc = val; // setting ALL also sets the default value List objectIDs = lIDs; string xparm = parm.ToLower(); @@ -1257,6 +1264,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters BulletSimAPI.UpdateParameter(WorldID, lID, xparm, xval); } }); + */ break; default: // setting only one localID @@ -1268,12 +1276,15 @@ public class BSScene : PhysicsScene, IPhysicsParameters // schedule the actual updating of the paramter to when the phys engine is not busy protected void TaintedUpdateParameter(string parm, uint localID, float val) { + m_log.ErrorFormat("{0} Cannot change parameters of base objects. Someday it will be added.", LogHeader); + /* uint xlocalID = localID; string xparm = parm.ToLower(); float xval = val; TaintedObject("BSScene.TaintedUpdateParameter", delegate() { BulletSimAPI.UpdateParameter(WorldID, xlocalID, xparm, xval); }); + */ } // Get parameter. diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs index d189f1d..7d0f84a 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs @@ -93,7 +93,7 @@ public class BSShapeCollection : IDisposable // sure the body is of the right type. // Return 'true' if either the body or the shape changed. // Called at taint-time!! - public bool GetBodyAndShape(bool forceRebuild, BulletSim sim, BSPrim prim, + public bool GetBodyAndShape(bool forceRebuild, BulletSim sim, BSPhysObject prim, ShapeData shapeData, PrimitiveBaseShape pbs, ShapeDestructionCallback shapeCallback, BodyDestructionCallback bodyCallback) { @@ -351,19 +351,30 @@ public class BSShapeCollection : IDisposable // Create the geometry information in Bullet for later use. // The objects needs a hull if it's physical otherwise a mesh is enough. - // No locking here because this is done when we know physics is not simulating. - // if 'forceRebuild' is true, the geometry is rebuilt. Otherwise a previously built version is used. + // if 'forceRebuild' is true, the geometry is unconditionally rebuilt. For meshes and hulls, + // shared geometries will be used. If the parameters of the existing shape are the same + // as this request, the shape is not rebuilt. + // Info in prim.BSShape is updated to the new shape. // Returns 'true' if the geometry was rebuilt. // Called at taint-time! - private bool CreateGeom(bool forceRebuild, BSPrim prim, ShapeData shapeData, + private bool CreateGeom(bool forceRebuild, BSPhysObject prim, ShapeData shapeData, PrimitiveBaseShape pbs, ShapeDestructionCallback shapeCallback) { bool ret = false; bool haveShape = false; bool nativeShapePossible = true; + if (shapeData.Type == ShapeData.PhysicsShapeType.SHAPE_AVATAR) + { + // an avatar capsule is close to a native shape (it is not shared) + ret = GetReferenceToNativeShape(prim, shapeData, ShapeData.PhysicsShapeType.SHAPE_AVATAR, + ShapeData.FixedShapeKey.KEY_CAPSULE, shapeCallback); + haveShape = true; + } // If the prim attributes are simple, this could be a simple Bullet native shape - if (nativeShapePossible + if (!haveShape + && pbs != null + && nativeShapePossible && ((pbs.SculptEntry && !PhysicsScene.ShouldMeshSculptedPrim) || (pbs.ProfileBegin == 0 && pbs.ProfileEnd == 0 && pbs.ProfileHollow == 0 @@ -406,7 +417,7 @@ public class BSShapeCollection : IDisposable // If a simple shape is not happening, create a mesh and possibly a hull. // Note that if it's a native shape, the check for physical/non-physical is not // made. Native shapes are best used in either case. - if (!haveShape) + if (!haveShape && pbs != null) { if (prim.IsPhysical && PhysicsScene.ShouldUseHullsForPhysicalObjects) { @@ -425,8 +436,9 @@ public class BSShapeCollection : IDisposable return ret; } - // Creates a native shape and assignes it to prim.BSShape - private bool GetReferenceToNativeShape( BSPrim prim, ShapeData shapeData, + // Creates a native shape and assignes it to prim.BSShape. + // "Native" shapes are never shared. they are created here and destroyed in DereferenceShape(). + private bool GetReferenceToNativeShape(BSPhysObject prim, ShapeData shapeData, ShapeData.PhysicsShapeType shapeType, ShapeData.FixedShapeKey shapeKey, ShapeDestructionCallback shapeCallback) { @@ -440,10 +452,19 @@ public class BSShapeCollection : IDisposable // release any previous shape DereferenceShape(prim.BSShape, true, shapeCallback); - // Native shapes are always built independently. - newShape = new BulletShape(BulletSimAPI.BuildNativeShape2(PhysicsScene.World.ptr, shapeData), shapeType); - newShape.shapeKey = (System.UInt64)shapeKey; - newShape.isNativeShape = true; + if (shapeType == ShapeData.PhysicsShapeType.SHAPE_AVATAR) + { + newShape = new BulletShape(BulletSimAPI.BuildCapsuleShape2(PhysicsScene.World.ptr, shapeData), shapeType); + newShape.shapeKey = (System.UInt64)shapeKey; + newShape.isNativeShape = true; + } + else + { + // Native shapes are always built independently. + newShape = new BulletShape(BulletSimAPI.BuildNativeShape2(PhysicsScene.World.ptr, shapeData), shapeType); + newShape.shapeKey = (System.UInt64)shapeKey; + newShape.isNativeShape = true; + } // Don't need to do a 'ReferenceShape()' here because native shapes are not tracked. // DetailLog("{0},BSShapeCollection.AddNativeShapeToPrim,create,newshape={1}", shapeData.ID, newShape); @@ -456,7 +477,7 @@ public class BSShapeCollection : IDisposable // Dereferences previous shape in BSShape and adds a reference for this new shape. // Returns 'true' of a mesh was actually built. Otherwise . // Called at taint-time! - private bool GetReferenceToMesh(BSPrim prim, ShapeData shapeData, PrimitiveBaseShape pbs, + private bool GetReferenceToMesh(BSPhysObject prim, ShapeData shapeData, PrimitiveBaseShape pbs, ShapeDestructionCallback shapeCallback) { BulletShape newShape = new BulletShape(IntPtr.Zero); @@ -526,7 +547,7 @@ public class BSShapeCollection : IDisposable // See that hull shape exists in the physical world and update prim.BSShape. // We could be creating the hull because scale changed or whatever. - private bool GetReferenceToHull(BSPrim prim, ShapeData shapeData, PrimitiveBaseShape pbs, + private bool GetReferenceToHull(BSPhysObject prim, ShapeData shapeData, PrimitiveBaseShape pbs, ShapeDestructionCallback shapeCallback) { BulletShape newShape; @@ -694,7 +715,7 @@ public class BSShapeCollection : IDisposable // Updates prim.BSBody with the information about the new body if one is created. // Returns 'true' if an object was actually created. // Called at taint-time. - private bool CreateBody(bool forceRebuild, BSPrim prim, BulletSim sim, BulletShape shape, + private bool CreateBody(bool forceRebuild, BSPhysObject prim, BulletSim sim, BulletShape shape, ShapeData shapeData, BodyDestructionCallback bodyCallback) { bool ret = false; diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs index 276111c..30754a7 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs @@ -223,6 +223,7 @@ public struct ShapeData KEY_SPHERE = 2, KEY_CONE = 3, KEY_CYLINDER = 4, + KEY_CAPSULE = 5, } } [StructLayout(LayoutKind.Sequential)] @@ -282,6 +283,7 @@ public struct ConfigurationParameters public float terrainHitFraction; public float terrainRestitution; public float avatarFriction; + public float avatarStandingFriction; public float avatarDensity; public float avatarRestitution; public float avatarCapsuleRadius; @@ -428,6 +430,7 @@ public delegate void DebugLogCallback([MarshalAs(UnmanagedType.LPStr)]string msg [return: MarshalAs(UnmanagedType.LPStr)] public static extern string GetVersion(); +/* Remove the linkage to the old api methods [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern uint Initialize(Vector3 maxPosition, IntPtr parms, int maxCollisions, IntPtr collisionArray, @@ -531,7 +534,7 @@ public static extern Vector3 RecoverFromPenetration(uint worldID, uint id); // =============================================================================== [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern void DumpBulletStatistics(); - +*/ // Log a debug message [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern void SetDebugLogCallback(DebugLogCallback callback); @@ -562,7 +565,8 @@ public static extern IntPtr GetBodyHandle2(IntPtr world, uint id); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern IntPtr Initialize2(Vector3 maxPosition, IntPtr parms, int maxCollisions, IntPtr collisionArray, - int maxUpdates, IntPtr updateArray); + int maxUpdates, IntPtr updateArray, + DebugLogCallback logRoutine); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern bool UpdateParameter2(IntPtr world, uint localID, String parm, float value); @@ -604,6 +608,9 @@ public static extern IntPtr BuildNativeShape2(IntPtr world, ShapeData shapeData) public static extern bool IsNativeShape2(IntPtr shape); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern IntPtr BuildCapsuleShape2(IntPtr world, ShapeData shapeData); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern IntPtr CreateCompoundShape2(IntPtr sim); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -- cgit v1.1 From eaccfa6d99ac51b4963ae0fa457ff0d2b9ce65e7 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Sun, 14 Oct 2012 19:23:35 -0700 Subject: BulletSim: Fix small problems with last patch: BSScene.World properly initialized and setting of C++ parameters commented out. Comments and logging added. --- OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs | 2 +- OpenSim/Region/Physics/BulletSPlugin/BSScene.cs | 13 ++++--------- OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs | 2 +- 3 files changed, 6 insertions(+), 11 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs index 7c2f856..7bc6b69 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs @@ -146,7 +146,7 @@ public class BSCharacter : BSPhysObject ZeroMotion(); - OMV.Vector3 localInertia = BulletSimAPI.CalculateLocalInertia2(BSBody.ptr, MassRaw); + OMV.Vector3 localInertia = BulletSimAPI.CalculateLocalInertia2(BSShape.ptr, MassRaw); BulletSimAPI.SetMassProps2(BSBody.ptr, MassRaw, localInertia); // Set the velocity and compute the proper friction diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs index 5158011..7998b08 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs @@ -261,10 +261,6 @@ public class BSScene : PhysicsScene, IPhysicsParameters m_maxUpdatesPerFrame, m_updateArrayPinnedHandle.AddrOfPinnedObject(), m_DebugLogCallbackHandle)); - // Initialization to support the transition to a new API which puts most of the logic - // into the C# code so it is easier to modify and add to. - World = new BulletSim(WorldID, this, BulletSimAPI.GetSimHandle2(WorldID)); - Constraints = new BSConstraintCollection(World); TerrainManager = new BSTerrainManager(this); @@ -1251,10 +1247,9 @@ public class BSScene : PhysicsScene, IPhysicsParameters case PhysParameterEntry.APPLY_TO_NONE: defaultLoc = val; // setting only the default value break; - case PhysParameterEntry.APPLY_TO_ALL: - m_log.ErrorFormat("{0} Cannot change parameters of multiple objects. Someday it will be added.", LogHeader); - /* + case PhysParameterEntry.APPLY_TO_ALL: defaultLoc = val; // setting ALL also sets the default value + /* List objectIDs = lIDs; string xparm = parm.ToLower(); float xval = val; @@ -1276,15 +1271,15 @@ public class BSScene : PhysicsScene, IPhysicsParameters // schedule the actual updating of the paramter to when the phys engine is not busy protected void TaintedUpdateParameter(string parm, uint localID, float val) { + /* Settings in the C++ code are not working at the moment. TODO: fix the settings. m_log.ErrorFormat("{0} Cannot change parameters of base objects. Someday it will be added.", LogHeader); - /* uint xlocalID = localID; string xparm = parm.ToLower(); float xval = val; TaintedObject("BSScene.TaintedUpdateParameter", delegate() { BulletSimAPI.UpdateParameter(WorldID, xlocalID, xparm, xval); }); - */ + */ } // Get parameter. diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs index 7d0f84a..5a77e52 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs @@ -369,6 +369,7 @@ public class BSShapeCollection : IDisposable // an avatar capsule is close to a native shape (it is not shared) ret = GetReferenceToNativeShape(prim, shapeData, ShapeData.PhysicsShapeType.SHAPE_AVATAR, ShapeData.FixedShapeKey.KEY_CAPSULE, shapeCallback); + DetailLog("{0},BSShapeCollection.CreateGeom,avatarCapsule,shape={1}", prim.LocalID, prim.BSShape); haveShape = true; } // If the prim attributes are simple, this could be a simple Bullet native shape @@ -460,7 +461,6 @@ public class BSShapeCollection : IDisposable } else { - // Native shapes are always built independently. newShape = new BulletShape(BulletSimAPI.BuildNativeShape2(PhysicsScene.World.ptr, shapeData), shapeType); newShape.shapeKey = (System.UInt64)shapeKey; newShape.isNativeShape = true; -- cgit v1.1 From fc33afddd360843d05f030750b7075315a526ae1 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Mon, 15 Oct 2012 12:11:00 -0700 Subject: BulletSim: remove code in ShapeCollection that hinted at shape sharing. Add new function to ParameterDefn for calling BulletSimAPI to set values. Tweaking to BSCharacter parameter setting to try and have avatars stand. --- .../Region/Physics/BulletSPlugin/BSCharacter.cs | 56 +++++----- OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | 16 +-- OpenSim/Region/Physics/BulletSPlugin/BSScene.cs | 114 ++++++++++++--------- .../Physics/BulletSPlugin/BSShapeCollection.cs | 110 +++++++------------- .../Physics/BulletSPlugin/BSTerrainManager.cs | 3 +- 5 files changed, 138 insertions(+), 161 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs index 7bc6b69..8e1171a 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs @@ -114,17 +114,9 @@ public class BSCharacter : BSPhysObject PhysicsScene.TaintedObject("BSCharacter.create", delegate() { DetailLog("{0},BSCharacter.create,taint", LocalID); - PhysicsScene.Shapes.GetBodyAndShape(true, PhysicsScene.World, this, shapeData, null, null, null); - + PhysicsScene.Shapes.GetBodyAndShape(true, PhysicsScene.World, this, shapeData, null, null, null); + SetPhysicalProperties(); - - // Set the buoyancy for flying. This will be refactored when all the settings happen in C#. - // If not set at creation, the avatar will stop flying when created after crossing a region boundry. - ForceBuoyancy = _buoyancy; - - // This works here because CreateObject has already put the character into the physical world. - BulletSimAPI.SetCollisionFilterMask2(BSBody.ptr, - (uint)CollisionFilterGroups.AvatarFilter, (uint)CollisionFilterGroups.AvatarMask); }); return; } @@ -146,27 +138,32 @@ public class BSCharacter : BSPhysObject ZeroMotion(); - OMV.Vector3 localInertia = BulletSimAPI.CalculateLocalInertia2(BSShape.ptr, MassRaw); + OMV.Vector3 localInertia = BulletSimAPI.CalculateLocalInertia2(BSShape.ptr, MassRaw); BulletSimAPI.SetMassProps2(BSBody.ptr, MassRaw, localInertia); + ForcePosition = _position; // Set the velocity and compute the proper friction ForceVelocity = _velocity; - - BulletSimAPI.SetFriction2(BSBody.ptr, _currentFriction); BulletSimAPI.SetRestitution2(BSBody.ptr, PhysicsScene.Params.avatarRestitution); - BulletSimAPI.SetLocalScaling2(BSShape.ptr, Scale); BulletSimAPI.SetContactProcessingThreshold2(BSBody.ptr, PhysicsScene.Params.contactProcessingThreshold); - if (PhysicsScene.Params.ccdMotionThreshold > 0f) { BulletSimAPI.SetCcdMotionThreshold2(BSBody.ptr, PhysicsScene.Params.ccdMotionThreshold); BulletSimAPI.SetCcdSweepSphereRadius2(BSBody.ptr, PhysicsScene.Params.ccdSweptSphereRadius); - } - - BulletSimAPI.SetActivationState2(BSBody.ptr, (int)ActivationState.DISABLE_DEACTIVATION); + } + + BulletSimAPI.AddToCollisionFlags2(BSBody.ptr, CollisionFlags.CF_CHARACTER_OBJECT); BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, BSBody.ptr); + + BulletSimAPI.ForceActivationState2(BSBody.ptr, ActivationState.DISABLE_DEACTIVATION); + BulletSimAPI.UpdateSingleAabb2(PhysicsScene.World.ptr, BSBody.ptr); + + // Do this after the object has been added to the world + BulletSimAPI.SetCollisionFilterMask2(BSBody.ptr, + (uint)CollisionFilterGroups.AvatarFilter, + (uint)CollisionFilterGroups.AvatarMask); } public override void RequestPhysicsterseUpdate() @@ -174,9 +171,7 @@ public class BSCharacter : BSPhysObject base.RequestPhysicsterseUpdate(); } // No one calls this method so I don't know what it could possibly mean - public override bool Stopped { - get { return false; } - } + public override bool Stopped { get { return false; } } public override OMV.Vector3 Size { get { @@ -185,18 +180,14 @@ public class BSCharacter : BSPhysObject } set { - // When an avatar's size is set, only the height is changed - // and that really only depends on the radius. + // When an avatar's size is set, only the height is changed. _size = value; ComputeAvatarScale(_size); - - // TODO: something has to be done with the avatar's vertical position - ComputeAvatarVolumeAndMass(); PhysicsScene.TaintedObject("BSCharacter.setSize", delegate() { - BulletSimAPI.SetLocalScaling2(BSBody.ptr, Scale); + BulletSimAPI.SetLocalScaling2(BSShape.ptr, Scale); OMV.Vector3 localInertia = BulletSimAPI.CalculateLocalInertia2(BSBody.ptr, MassRaw); BulletSimAPI.SetMassProps2(BSBody.ptr, MassRaw, localInertia); }); @@ -300,7 +291,7 @@ public class BSCharacter : BSPhysObject // A version of the sanity check that also makes sure a new position value is // pushed back to the physics engine. This routine would be used by anyone // who is not already pushing the value. - private bool PositionSanityCheck2(bool inTaintTime) + private bool PositionSanityCheck(bool inTaintTime) { bool ret = false; if (PositionSanityCheck()) @@ -378,14 +369,16 @@ public class BSCharacter : BSPhysObject } else { - if (_currentFriction == 999f) + if (_currentFriction != PhysicsScene.Params.avatarFriction) { _currentFriction = PhysicsScene.Params.avatarFriction; BulletSimAPI.SetFriction2(BSBody.ptr, _currentFriction); } } _velocity = value; + // Remember the set velocity so we can suppress the reduction by friction, ... _appliedVelocity = value; + BulletSimAPI.SetLinearVelocity2(BSBody.ptr, _velocity); BulletSimAPI.Activate2(BSBody.ptr, true); } @@ -590,7 +583,8 @@ public class BSCharacter : BSPhysObject // The 1.15 came from ODE but it seems to cause the avatar to float off the ground // Scale.Z = (_size.Z * 1.15f) - (Scale.X + Scale.Y); - newScale.Z = (_size.Z) - (Scale.X + Scale.Y); + // From the total height, remove the capsule half spheres that are at each end + newScale.Z = (size.Z) - (Math.Min(newScale.X, newScale.Y) * 2f); Scale = newScale; } @@ -621,7 +615,7 @@ public class BSCharacter : BSPhysObject _acceleration = entprop.Acceleration; _rotationalVelocity = entprop.RotationalVelocity; // Do some sanity checking for the avatar. Make sure it's above ground and inbounds. - PositionSanityCheck2(true); + PositionSanityCheck(true); // remember the current and last set values LastEntityProperties = CurrentEntityProperties; diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index 3421e30..b9e1908 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs @@ -333,7 +333,7 @@ public sealed class BSPrim : BSPhysObject // just assign to "Position" because of potential call loops. BSScene.TaintCallback sanityOperation = delegate() { - DetailLog("{0},BSPrim.PositionSanityCheck,taint,pos={1},orient={2}", LocalID, _position, _orientation); + DetailLog("{0},BSPrim.PositionSanityCheck,taint,pos={1},orient={2}", LocalID, _position, _orientation); ForcePosition = _position; }; if (inTaintTime) @@ -822,7 +822,7 @@ public sealed class BSPrim : BSPhysObject set { _buoyancy = value; PhysicsScene.TaintedObject("BSPrim.setBuoyancy", delegate() - { + { ForceBuoyancy = _buoyancy; }); } @@ -1286,8 +1286,8 @@ public sealed class BSPrim : BSPhysObject const float VELOCITY_TOLERANCE = 0.001f; const float POSITION_TOLERANCE = 0.05f; const float ACCELERATION_TOLERANCE = 0.01f; - const float ROTATIONAL_VELOCITY_TOLERANCE = 0.01f; - + const float ROTATIONAL_VELOCITY_TOLERANCE = 0.01f; + public override void UpdateProperties(EntityProperties entprop) { /* @@ -1343,10 +1343,10 @@ public sealed class BSPrim : BSPhysObject _orientation = entprop.Rotation; _velocity = entprop.Velocity; _acceleration = entprop.Acceleration; - _rotationalVelocity = entprop.RotationalVelocity; - - // remember the current and last set values - LastEntityProperties = CurrentEntityProperties; + _rotationalVelocity = entprop.RotationalVelocity; + + // remember the current and last set values + LastEntityProperties = CurrentEntityProperties; CurrentEntityProperties = entprop; PositionSanityCheck(true); diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs index 7998b08..c6e8bc4 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs @@ -795,7 +795,8 @@ public class BSScene : PhysicsScene, IPhysicsParameters delegate void ParamUser(BSScene scene, IConfig conf, string paramName, float val); delegate float ParamGet(BSScene scene); - delegate void ParamSet(BSScene scene, string paramName, uint localID, float val); + delegate void ParamSet(BSScene scene, string paramName, uint localID, float val); + delegate void SetOnObject(BSScene scene, BSPhysObject obj, float val); private struct ParameterDefn { @@ -804,7 +805,8 @@ public class BSScene : PhysicsScene, IPhysicsParameters public float defaultValue; // default value if not specified anywhere else public ParamUser userParam; // get the value from the configuration file public ParamGet getter; // return the current value stored for this parameter - public ParamSet setter; // set the current value for this parameter + public ParamSet setter; // set the current value for this parameter + public SetOnObject onObject; // set the value on an object in the physical domain public ParameterDefn(string n, string d, float v, ParamUser u, ParamGet g, ParamSet s) { name = n; @@ -812,7 +814,18 @@ public class BSScene : PhysicsScene, IPhysicsParameters defaultValue = v; userParam = u; getter = g; - setter = s; + setter = s; + onObject = null; + } + public ParameterDefn(string n, string d, float v, ParamUser u, ParamGet g, ParamSet s, SetOnObject o) + { + name = n; + desc = d; + defaultValue = v; + userParam = u; + getter = g; + setter = s; + onObject = o; } } @@ -834,6 +847,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters // // The single letter parameters for the delegates are: // s = BSScene + // o = BSPhysObject // p = string parameter name // l = localID of referenced object // v = float value @@ -943,65 +957,74 @@ public class BSScene : PhysicsScene, IPhysicsParameters -9.80665f, (s,cf,p,v) => { s.m_params[0].gravity = cf.GetFloat(p, v); }, (s) => { return s.m_params[0].gravity; }, - (s,p,l,v) => { s.m_params[0].gravity = v; s.TaintedUpdateParameter(p,l,v); } ), + (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].gravity, p, PhysParameterEntry.APPLY_TO_NONE, v); }, + (s,o,v) => { BulletSimAPI.SetGravity2(s.World.ptr, new Vector3(0f,0f,v)); } ), new ParameterDefn("LinearDamping", "Factor to damp linear movement per second (0.0 - 1.0)", 0f, (s,cf,p,v) => { s.m_params[0].linearDamping = cf.GetFloat(p, v); }, (s) => { return s.m_params[0].linearDamping; }, - (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].linearDamping, p, l, v); } ), + (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].linearDamping, p, l, v); }, + (s,o,v) => { BulletSimAPI.SetDamping2(o.BSBody.ptr, v, v); } ), new ParameterDefn("AngularDamping", "Factor to damp angular movement per second (0.0 - 1.0)", 0f, (s,cf,p,v) => { s.m_params[0].angularDamping = cf.GetFloat(p, v); }, (s) => { return s.m_params[0].angularDamping; }, - (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].angularDamping, p, l, v); } ), + (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].angularDamping, p, l, v); }, + (s,o,v) => { BulletSimAPI.SetDamping2(o.BSBody.ptr, v, v); } ), new ParameterDefn("DeactivationTime", "Seconds before considering an object potentially static", 0.2f, (s,cf,p,v) => { s.m_params[0].deactivationTime = cf.GetFloat(p, v); }, (s) => { return s.m_params[0].deactivationTime; }, - (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].deactivationTime, p, l, v); } ), + (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].deactivationTime, p, l, v); }, + (s,o,v) => { BulletSimAPI.SetDeactivationTime2(o.BSBody.ptr, v); } ), new ParameterDefn("LinearSleepingThreshold", "Seconds to measure linear movement before considering static", 0.8f, (s,cf,p,v) => { s.m_params[0].linearSleepingThreshold = cf.GetFloat(p, v); }, (s) => { return s.m_params[0].linearSleepingThreshold; }, - (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].linearSleepingThreshold, p, l, v); } ), + (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].linearSleepingThreshold, p, l, v); }, + (s,o,v) => { BulletSimAPI.SetSleepingThresholds2(o.BSBody.ptr, v, v); } ), new ParameterDefn("AngularSleepingThreshold", "Seconds to measure angular movement before considering static", 1.0f, (s,cf,p,v) => { s.m_params[0].angularSleepingThreshold = cf.GetFloat(p, v); }, (s) => { return s.m_params[0].angularSleepingThreshold; }, - (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].angularSleepingThreshold, p, l, v); } ), + (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].angularSleepingThreshold, p, l, v); }, + (s,o,v) => { BulletSimAPI.SetSleepingThresholds2(o.BSBody.ptr, v, v); } ), new ParameterDefn("CcdMotionThreshold", "Continuious collision detection threshold (0 means no CCD)" , 0f, // set to zero to disable (s,cf,p,v) => { s.m_params[0].ccdMotionThreshold = cf.GetFloat(p, v); }, (s) => { return s.m_params[0].ccdMotionThreshold; }, - (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].ccdMotionThreshold, p, l, v); } ), + (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].ccdMotionThreshold, p, l, v); }, + (s,o,v) => { BulletSimAPI.SetCcdMotionThreshold2(o.BSBody.ptr, v); } ), new ParameterDefn("CcdSweptSphereRadius", "Continuious collision detection test radius" , 0f, (s,cf,p,v) => { s.m_params[0].ccdSweptSphereRadius = cf.GetFloat(p, v); }, (s) => { return s.m_params[0].ccdSweptSphereRadius; }, - (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].ccdSweptSphereRadius, p, l, v); } ), + (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].ccdSweptSphereRadius, p, l, v); }, + (s,o,v) => { BulletSimAPI.SetCcdSweepSphereRadius2(o.BSBody.ptr, v); } ), new ParameterDefn("ContactProcessingThreshold", "Distance between contacts before doing collision check" , 0.1f, (s,cf,p,v) => { s.m_params[0].contactProcessingThreshold = cf.GetFloat(p, v); }, (s) => { return s.m_params[0].contactProcessingThreshold; }, - (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].contactProcessingThreshold, p, l, v); } ), + (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].contactProcessingThreshold, p, l, v); }, + (s,o,v) => { BulletSimAPI.SetContactProcessingThreshold2(o.BSBody.ptr, v); } ), new ParameterDefn("TerrainFriction", "Factor to reduce movement against terrain surface" , 0.5f, (s,cf,p,v) => { s.m_params[0].terrainFriction = cf.GetFloat(p, v); }, (s) => { return s.m_params[0].terrainFriction; }, - (s,p,l,v) => { s.m_params[0].terrainFriction = v; s.TaintedUpdateParameter(p,l,v); } ), + (s,p,l,v) => { s.m_params[0].terrainFriction = v; /* TODO: set on real terrain */} ), new ParameterDefn("TerrainHitFraction", "Distance to measure hit collisions" , 0.8f, (s,cf,p,v) => { s.m_params[0].terrainHitFraction = cf.GetFloat(p, v); }, (s) => { return s.m_params[0].terrainHitFraction; }, - (s,p,l,v) => { s.m_params[0].terrainHitFraction = v; s.TaintedUpdateParameter(p,l,v); } ), + (s,p,l,v) => { s.m_params[0].terrainHitFraction = v; /* TODO: set on real terrain */ } ), new ParameterDefn("TerrainRestitution", "Bouncyness" , 0f, (s,cf,p,v) => { s.m_params[0].terrainRestitution = cf.GetFloat(p, v); }, (s) => { return s.m_params[0].terrainRestitution; }, - (s,p,l,v) => { s.m_params[0].terrainRestitution = v; s.TaintedUpdateParameter(p,l,v); } ), + (s,p,l,v) => { s.m_params[0].terrainRestitution = v; /* TODO: set on real terrain */ } ), new ParameterDefn("AvatarFriction", "Factor to reduce movement against an avatar. Changed on avatar recreation.", 0.2f, (s,cf,p,v) => { s.m_params[0].avatarFriction = cf.GetFloat(p, v); }, @@ -1228,58 +1251,55 @@ public class BSScene : PhysicsScene, IPhysicsParameters return ret; } - // check to see if we are updating a parameter for a particular or all of the prims - protected void UpdateParameterObject(ref float loc, string parm, uint localID, float val) - { - List operateOn; - lock (PhysObjects) operateOn = new List(PhysObjects.Keys); - UpdateParameterSet(operateOn, ref loc, parm, localID, val); - } - // update all the localIDs specified // If the local ID is APPLY_TO_NONE, just change the default value // If the localID is APPLY_TO_ALL change the default value and apply the new value to all the lIDs // If the localID is a specific object, apply the parameter change to only that object - protected void UpdateParameterSet(List lIDs, ref float defaultLoc, string parm, uint localID, float val) + protected void UpdateParameterObject(ref float defaultLoc, string parm, uint localID, float val) { + List objectIDs = new List(); switch (localID) { case PhysParameterEntry.APPLY_TO_NONE: defaultLoc = val; // setting only the default value + // This will cause a call into the physical world if some operation is specified (SetOnObject). + objectIDs.Add(TERRAIN_ID); + TaintedUpdateParameter(parm, objectIDs, val); break; - case PhysParameterEntry.APPLY_TO_ALL: + case PhysParameterEntry.APPLY_TO_ALL: defaultLoc = val; // setting ALL also sets the default value - /* - List objectIDs = lIDs; - string xparm = parm.ToLower(); - float xval = val; - TaintedObject("BSScene.UpdateParameterSet", delegate() { - foreach (uint lID in objectIDs) - { - BulletSimAPI.UpdateParameter(WorldID, lID, xparm, xval); - } - }); - */ + lock (PhysObjects) objectIDs = new List(PhysObjects.Keys); + TaintedUpdateParameter(parm, objectIDs, val); break; default: - // setting only one localID - TaintedUpdateParameter(parm, localID, val); + // setting only one localID + objectIDs.Add(localID); + TaintedUpdateParameter(parm, objectIDs, val); break; } } // schedule the actual updating of the paramter to when the phys engine is not busy - protected void TaintedUpdateParameter(string parm, uint localID, float val) + protected void TaintedUpdateParameter(string parm, List lIDs, float val) { - /* Settings in the C++ code are not working at the moment. TODO: fix the settings. - m_log.ErrorFormat("{0} Cannot change parameters of base objects. Someday it will be added.", LogHeader); - uint xlocalID = localID; - string xparm = parm.ToLower(); - float xval = val; - TaintedObject("BSScene.TaintedUpdateParameter", delegate() { - BulletSimAPI.UpdateParameter(WorldID, xlocalID, xparm, xval); + float xval = val; + List xlIDs = lIDs; + string xparm = parm; + TaintedObject("BSScene.UpdateParameterSet", delegate() { + ParameterDefn thisParam; + if (TryGetParameter(xparm, out thisParam)) + { + if (thisParam.onObject != null) + { + foreach (uint lID in xlIDs) + { + BSPhysObject theObject = null; + PhysObjects.TryGetValue(lID, out theObject); + thisParam.onObject(this, theObject, xval); + } + } + } }); - */ } // Get parameter. diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs index 5a77e52..bbfdac6 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs @@ -51,7 +51,7 @@ public class BSShapeCollection : IDisposable } // Description of a hull. - // Meshes and hulls have the same shape hash key but we only need hulls for efficient physical objects + // Meshes and hulls have the same shape hash key but we only need hulls for efficient collision calculations. private struct HullDesc { public IntPtr ptr; @@ -59,17 +59,9 @@ public class BSShapeCollection : IDisposable public DateTime lastReferenced; } - private struct BodyDesc - { - public IntPtr ptr; - // Bodies are only used once so reference count is always either one or zero - public int referenceCount; - public DateTime lastReferenced; - } - + // The sharable set of meshes and hulls. Indexed by their shape hash. private Dictionary Meshes = new Dictionary(); private Dictionary Hulls = new Dictionary(); - private Dictionary Bodies = new Dictionary(); public BSShapeCollection(BSScene physScene) { @@ -92,6 +84,10 @@ public class BSShapeCollection : IDisposable // First checks the shape and updates that if necessary then makes // sure the body is of the right type. // Return 'true' if either the body or the shape changed. + // 'shapeCallback' and 'bodyCallback' are, if non-null, functions called just before + // the current shape or body is destroyed. This allows the caller to remove any + // higher level dependencies on the shape or body. Mostly used for LinkSets to + // remove the physical constraints before the body is destroyed. // Called at taint-time!! public bool GetBodyAndShape(bool forceRebuild, BulletSim sim, BSPhysObject prim, ShapeData shapeData, PrimitiveBaseShape pbs, @@ -103,7 +99,8 @@ public class BSShapeCollection : IDisposable lock (m_collectionActivityLock) { // Do we have the correct geometry for this type of object? - // Updates prim.BSShape with information/pointers to requested shape + // Updates prim.BSShape with information/pointers to shape. + // CreateGeom returns 'true' of BSShape as changed to a new shape. bool newGeom = CreateGeom(forceRebuild, prim, shapeData, pbs, shapeCallback); // If we had to select a new shape geometry for the object, // rebuild the body around it. @@ -125,35 +122,19 @@ public class BSShapeCollection : IDisposable { lock (m_collectionActivityLock) { - BodyDesc bodyDesc; - if (Bodies.TryGetValue(body.ID, out bodyDesc)) + DetailLog("{0},BSShapeCollection.ReferenceBody,newBody", body.ID, body); + BSScene.TaintCallback createOperation = delegate() { - bodyDesc.referenceCount++; - DetailLog("{0},BSShapeCollection.ReferenceBody,existingBody,body={1},ref={2}", body.ID, body, bodyDesc.referenceCount); - } - else - { - // New entry - bodyDesc.ptr = body.ptr; - bodyDesc.referenceCount = 1; - DetailLog("{0},BSShapeCollection.ReferenceBody,newBody,ref={2}", - body.ID, body, bodyDesc.referenceCount); - BSScene.TaintCallback createOperation = delegate() + if (!BulletSimAPI.IsInWorld2(body.ptr)) { - if (!BulletSimAPI.IsInWorld2(body.ptr)) - { - BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, body.ptr); - DetailLog("{0},BSShapeCollection.ReferenceBody,addedToWorld,ref={1}", - body.ID, body); - } - }; - if (inTaintTime) - createOperation(); - else - PhysicsScene.TaintedObject("BSShapeCollection.ReferenceBody", createOperation); - } - bodyDesc.lastReferenced = System.DateTime.Now; - Bodies[body.ID] = bodyDesc; + BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, body.ptr); + DetailLog("{0},BSShapeCollection.ReferenceBody,addedToWorld,ref={1}", body.ID, body); + } + }; + if (inTaintTime) + createOperation(); + else + PhysicsScene.TaintedObject("BSShapeCollection.ReferenceBody", createOperation); } } @@ -166,43 +147,25 @@ public class BSShapeCollection : IDisposable lock (m_collectionActivityLock) { - BodyDesc bodyDesc; - if (Bodies.TryGetValue(body.ID, out bodyDesc)) + BSScene.TaintCallback removeOperation = delegate() { - bodyDesc.referenceCount--; - bodyDesc.lastReferenced = System.DateTime.Now; - Bodies[body.ID] = bodyDesc; - DetailLog("{0},BSShapeCollection.DereferenceBody,ref={1}", body.ID, bodyDesc.referenceCount); - - // If body is no longer being used, free it -- bodies can never be shared. - if (bodyDesc.referenceCount == 0) - { - Bodies.Remove(body.ID); - BSScene.TaintCallback removeOperation = delegate() - { - DetailLog("{0},BSShapeCollection.DereferenceBody,DestroyingBody. ptr={1}, inTaintTime={2}", - body.ID, body.ptr.ToString("X"), inTaintTime); - // If the caller needs to know the old body is going away, pass the event up. - if (bodyCallback != null) bodyCallback(body); - - // It may have already been removed from the world in which case the next is a NOOP. - BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, body.ptr); - - // Zero any reference to the shape so it is not freed when the body is deleted. - BulletSimAPI.SetCollisionShape2(PhysicsScene.World.ptr, body.ptr, IntPtr.Zero); - BulletSimAPI.DestroyObject2(PhysicsScene.World.ptr, body.ptr); - }; - // If already in taint-time, do the operations now. Otherwise queue for later. - if (inTaintTime) - removeOperation(); - else - PhysicsScene.TaintedObject("BSShapeCollection.DereferenceBody", removeOperation); - } - } + DetailLog("{0},BSShapeCollection.DereferenceBody,DestroyingBody. ptr={1}, inTaintTime={2}", + body.ID, body.ptr.ToString("X"), inTaintTime); + // If the caller needs to know the old body is going away, pass the event up. + if (bodyCallback != null) bodyCallback(body); + + // It may have already been removed from the world in which case the next is a NOOP. + BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, body.ptr); + + // Zero any reference to the shape so it is not freed when the body is deleted. + BulletSimAPI.SetCollisionShape2(PhysicsScene.World.ptr, body.ptr, IntPtr.Zero); + BulletSimAPI.DestroyObject2(PhysicsScene.World.ptr, body.ptr); + }; + // If already in taint-time, do the operations now. Otherwise queue for later. + if (inTaintTime) + removeOperation(); else - { - DetailLog("{0},BSShapeCollection.DereferenceBody,DID NOT FIND BODY", body.ID, bodyDesc.referenceCount); - } + PhysicsScene.TaintedObject("BSShapeCollection.DereferenceBody", removeOperation); } } @@ -271,7 +234,6 @@ public class BSShapeCollection : IDisposable } // Release the usage of a shape. - // The collisionObject is released since it is a copy of the real collision shape. public void DereferenceShape(BulletShape shape, bool inTaintTime, ShapeDestructionCallback shapeCallback) { if (shape.ptr == IntPtr.Zero) diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs index caf411e..9743d94 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs @@ -334,7 +334,8 @@ public class BSTerrainManager // Make sure the new shape is processed. // BulletSimAPI.Activate2(mapInfo.terrainBody.ptr, true); - BulletSimAPI.ForceActivationState2(mapInfo.terrainBody.ptr, ActivationState.DISABLE_SIMULATION); + BulletSimAPI.ForceActivationState2(mapInfo.terrainBody.ptr, ActivationState.ISLAND_SLEEPING); + // BulletSimAPI.ForceActivationState2(mapInfo.terrainBody.ptr, ActivationState.DISABLE_SIMULATION); m_terrainModified = true; }; -- cgit v1.1 From e87a179c893ef246dae8338e0f56c3fe20458fbc Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Wed, 17 Oct 2012 08:30:10 -0700 Subject: BulletSim: change nonimal physics frame rate to 55 to give same numbers as ODE. Change character scaling to represent size of capsule (diameter rather than radius) Modify create capsule call to pass radius and height. Eliminate errors when calculating shape inertia (should have some type checking). --- .../Region/Physics/BulletSPlugin/BSCharacter.cs | 46 ++++++++++++---------- .../Region/Physics/BulletSPlugin/BSPhysObject.cs | 14 +++---- OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | 14 +++---- OpenSim/Region/Physics/BulletSPlugin/BSScene.cs | 26 ++++++------ .../Physics/BulletSPlugin/BSShapeCollection.cs | 7 +++- .../Region/Physics/BulletSPlugin/BulletSimAPI.cs | 2 +- 6 files changed, 57 insertions(+), 52 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs index 8e1171a..e7bff6e 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs @@ -89,13 +89,15 @@ public class BSCharacter : BSPhysObject _appliedVelocity = OMV.Vector3.Zero; _buoyancy = ComputeBuoyancyFromFlying(isFlying); _currentFriction = PhysicsScene.Params.avatarStandingFriction; + _avatarDensity = PhysicsScene.Params.avatarDensity; // The dimensions of the avatar capsule are kept in the scale. // Physics creates a unit capsule which is scaled by the physics engine. ComputeAvatarScale(_size); - _avatarDensity = PhysicsScene.Params.avatarDensity; // set _avatarVolume and _mass based on capsule size, _density and Scale ComputeAvatarVolumeAndMass(); + DetailLog("{0},BSCharacter.create,call,size={1},scale={2},density={3},volume={4},mass={5}", + LocalID, _size, Scale, _avatarDensity, _avatarVolume, MassRaw); ShapeData shapeData = new ShapeData(); shapeData.ID = LocalID; @@ -103,6 +105,7 @@ public class BSCharacter : BSPhysObject shapeData.Position = _position; shapeData.Rotation = _orientation; shapeData.Velocity = _velocity; + shapeData.Size = Scale; shapeData.Scale = Scale; shapeData.Mass = _mass; shapeData.Buoyancy = _buoyancy; @@ -114,8 +117,9 @@ public class BSCharacter : BSPhysObject PhysicsScene.TaintedObject("BSCharacter.create", delegate() { DetailLog("{0},BSCharacter.create,taint", LocalID); - PhysicsScene.Shapes.GetBodyAndShape(true, PhysicsScene.World, this, shapeData, null, null, null); - + // New body and shape into BSBody and BSShape + PhysicsScene.Shapes.GetBodyAndShape(true, PhysicsScene.World, this, shapeData, null, null, null); + SetPhysicalProperties(); }); return; @@ -138,7 +142,7 @@ public class BSCharacter : BSPhysObject ZeroMotion(); - OMV.Vector3 localInertia = BulletSimAPI.CalculateLocalInertia2(BSShape.ptr, MassRaw); + OMV.Vector3 localInertia = BulletSimAPI.CalculateLocalInertia2(BSShape.ptr, MassRaw); BulletSimAPI.SetMassProps2(BSBody.ptr, MassRaw, localInertia); ForcePosition = _position; @@ -151,13 +155,13 @@ public class BSCharacter : BSPhysObject { BulletSimAPI.SetCcdMotionThreshold2(BSBody.ptr, PhysicsScene.Params.ccdMotionThreshold); BulletSimAPI.SetCcdSweepSphereRadius2(BSBody.ptr, PhysicsScene.Params.ccdSweptSphereRadius); - } - + } + BulletSimAPI.AddToCollisionFlags2(BSBody.ptr, CollisionFlags.CF_CHARACTER_OBJECT); BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, BSBody.ptr); - BulletSimAPI.ForceActivationState2(BSBody.ptr, ActivationState.DISABLE_DEACTIVATION); + BulletSimAPI.ForceActivationState2(BSBody.ptr, ActivationState.ACTIVE_TAG); BulletSimAPI.UpdateSingleAabb2(PhysicsScene.World.ptr, BSBody.ptr); // Do this after the object has been added to the world @@ -176,7 +180,7 @@ public class BSCharacter : BSPhysObject get { // Avatar capsule size is kept in the scale parameter. - return new OMV.Vector3(Scale.X * 2, Scale.Y * 2, Scale.Z); + return _size; } set { @@ -184,11 +188,13 @@ public class BSCharacter : BSPhysObject _size = value; ComputeAvatarScale(_size); ComputeAvatarVolumeAndMass(); + DetailLog("{0},BSCharacter.setSize,call,scale={1},density={2},volume={3},mass={4}", + LocalID, Scale, _avatarDensity, _avatarVolume, MassRaw); PhysicsScene.TaintedObject("BSCharacter.setSize", delegate() { BulletSimAPI.SetLocalScaling2(BSShape.ptr, Scale); - OMV.Vector3 localInertia = BulletSimAPI.CalculateLocalInertia2(BSBody.ptr, MassRaw); + OMV.Vector3 localInertia = BulletSimAPI.CalculateLocalInertia2(BSShape.ptr, MassRaw); BulletSimAPI.SetMassProps2(BSBody.ptr, MassRaw, localInertia); }); @@ -578,13 +584,13 @@ public class BSCharacter : BSPhysObject private void ComputeAvatarScale(OMV.Vector3 size) { OMV.Vector3 newScale = OMV.Vector3.Zero; - newScale.X = PhysicsScene.Params.avatarCapsuleRadius; - newScale.Y = PhysicsScene.Params.avatarCapsuleRadius; + // Scale wants the diameter so mult radius by two + newScale.X = PhysicsScene.Params.avatarCapsuleRadius * 2f; + newScale.Y = PhysicsScene.Params.avatarCapsuleRadius * 2f; - // The 1.15 came from ODE but it seems to cause the avatar to float off the ground - // Scale.Z = (_size.Z * 1.15f) - (Scale.X + Scale.Y); - // From the total height, remove the capsule half spheres that are at each end - newScale.Z = (size.Z) - (Math.Min(newScale.X, newScale.Y) * 2f); + // From the total height, add the capsule half spheres that are at each end + // newScale.Z = (size.Z) - Math.Min(newScale.X, newScale.Y); + newScale.Z = (size.Z * 2f); Scale = newScale; } @@ -593,14 +599,14 @@ public class BSCharacter : BSPhysObject { _avatarVolume = (float)( Math.PI - * Scale.X - * Scale.Y // the area of capsule cylinder + * (Scale.X / 2f) + * (Scale.Y / 2f) // the area of capsule cylinder * Scale.Z // times height of capsule cylinder + 1.33333333f * Math.PI - * Scale.X - * Math.Min(Scale.X, Scale.Y) - * Scale.Y // plus the volume of the capsule end caps + * (Scale.X / 2f) + * (Math.Min(Scale.X, Scale.Y) / 2f) + * (Scale.Y / 2f) // plus the volume of the capsule end caps ); _mass = _avatarDensity * _avatarVolume; } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs index 34dec26..b8ef338 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs @@ -141,18 +141,15 @@ public abstract class BSPhysObject : PhysicsActor // if someone has subscribed for collision events.... if (SubscribedEvents()) { CollisionCollection.AddCollider(collidingWith, new ContactPoint(contactPoint, contactNormal, pentrationDepth)); - // DetailLog("{0},{1}.Collison.AddCollider,call,with={2},point={3},normal={4},depth={5}", - // LocalID, TypeName, collidingWith, contactPoint, contactNormal, pentrationDepth); + DetailLog("{0},{1}.Collison.AddCollider,call,with={2},point={3},normal={4},depth={5}", + LocalID, TypeName, collidingWith, contactPoint, contactNormal, pentrationDepth); ret = true; } return ret; } - // Routine to send the collected collisions into the simulator. - // Also handles removal of this from the collection of objects with collisions if - // there are no collisions from this object. Mechanism is create one last - // collision event to make collision_end work. + // Send the collected collisions into the simulator. // Called at taint time from within the Step() function thus no locking problems // with CollisionCollection and ObjectsWithNoMoreCollisions. // Return 'true' if there were some actual collisions passed up @@ -161,10 +158,9 @@ public abstract class BSPhysObject : PhysicsActor bool ret = true; // throttle the collisions to the number of milliseconds specified in the subscription - int nowTime = PhysicsScene.SimulationNowTime; - if (nowTime >= NextCollisionOkTime) + if (PhysicsScene.SimulationNowTime >= NextCollisionOkTime) { - NextCollisionOkTime = nowTime + SubscribedEventsMs; + NextCollisionOkTime = PhysicsScene.SimulationNowTime + SubscribedEventsMs; // We are called if we previously had collisions. If there are no collisions // this time, send up one last empty event so OpenSim can sense collision end. diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index b9e1908..8013e68 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs @@ -48,10 +48,10 @@ public sealed class BSPrim : BSPhysObject private PrimitiveBaseShape _pbs; - // _size is what the user passed. _scale is what we pass to the physics engine with the mesh. - // Often _scale is unity because the meshmerizer will apply _size when creating the mesh. + // _size is what the user passed. Scale is what we pass to the physics engine with the mesh. + // Often Scale is unity because the meshmerizer will apply _size when creating the mesh. private OMV.Vector3 _size; // the multiplier for each mesh dimension as passed by the user - private OMV.Vector3 _scale; // the multiplier for each mesh dimension for the mesh as created by the meshmerizer + // private OMV.Vector3 _scale; // the multiplier for each mesh dimension for the mesh as created by the meshmerizer private bool _grabbed; private bool _isSelected; @@ -98,7 +98,7 @@ public sealed class BSPrim : BSPhysObject _physicsActorType = (int)ActorTypes.Prim; _position = pos; _size = size; - _scale = new OMV.Vector3(1f, 1f, 1f); // the scale will be set by CreateGeom depending on object type + Scale = new OMV.Vector3(1f, 1f, 1f); // the scale will be set by CreateGeom depending on object type _orientation = rotation; _buoyancy = 1f; _velocity = OMV.Vector3.Zero; @@ -166,7 +166,7 @@ public sealed class BSPrim : BSPhysObject // Since _size changed, the mesh needs to be rebuilt. If rebuilt, all the correct // scale and margins are set. CreateGeomAndObject(true); - // DetailLog("{0},BSPrim.setSize,size={1},scale={2},mass={3},physical={4}", LocalID, _size, _scale, _mass, IsPhysical); + // DetailLog("{0},BSPrim.setSize,size={1},scale={2},mass={3},physical={4}", LocalID, _size, Scale, _mass, IsPhysical); }); } } @@ -1224,7 +1224,8 @@ public sealed class BSPrim : BSPhysObject shape.Position = _position; shape.Rotation = _orientation; shape.Velocity = _velocity; - shape.Scale = _scale; + shape.Size = _size; + shape.Scale = Scale; shape.Mass = _isPhysical ? _mass : 0f; shape.Buoyancy = _buoyancy; shape.HullKey = 0; @@ -1234,7 +1235,6 @@ public sealed class BSPrim : BSPhysObject shape.Collidable = (!IsPhantom) ? ShapeData.numericTrue : ShapeData.numericFalse; shape.Static = _isPhysical ? ShapeData.numericFalse : ShapeData.numericTrue; shape.Solid = IsSolid ? ShapeData.numericFalse : ShapeData.numericTrue; - shape.Size = _size; } // Rebuild the geometry and object. // This is called when the shape changes so we need to recreate the mesh/hull. diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs index c6e8bc4..ab2835c 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs @@ -533,7 +533,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters } // This is a kludge to get avatar movement updates. - // the simulator expects collisions for avatars even if there are have been no collisions. This updates + // The simulator expects collisions for avatars even if there are have been no collisions. This updates // avatar animations and stuff. // If you fix avatar animation updates, remove this overhead and let normal collision processing happen. foreach (BSPhysObject bsp in m_avatars) @@ -577,9 +577,9 @@ public class BSScene : PhysicsScene, IPhysicsParameters // The physics engine returns the number of milliseconds it simulated this call. // These are summed and normalized to one second and divided by 1000 to give the reported physics FPS. - // We multiply by 45 to give a recognizable running rate (45 or less). - return numSubSteps * m_fixedTimeStep * 1000 * 45; - // return timeStep * 1000 * 45; + // We multiply by 55 to give a recognizable running rate (55 or less). + return numSubSteps * m_fixedTimeStep * 1000 * 55; + // return timeStep * 1000 * 55; } // Something has collided @@ -795,7 +795,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters delegate void ParamUser(BSScene scene, IConfig conf, string paramName, float val); delegate float ParamGet(BSScene scene); - delegate void ParamSet(BSScene scene, string paramName, uint localID, float val); + delegate void ParamSet(BSScene scene, string paramName, uint localID, float val); delegate void SetOnObject(BSScene scene, BSPhysObject obj, float val); private struct ParameterDefn @@ -805,7 +805,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters public float defaultValue; // default value if not specified anywhere else public ParamUser userParam; // get the value from the configuration file public ParamGet getter; // return the current value stored for this parameter - public ParamSet setter; // set the current value for this parameter + public ParamSet setter; // set the current value for this parameter public SetOnObject onObject; // set the value on an object in the physical domain public ParameterDefn(string n, string d, float v, ParamUser u, ParamGet g, ParamSet s) { @@ -814,7 +814,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters defaultValue = v; userParam = u; getter = g; - setter = s; + setter = s; onObject = null; } public ParameterDefn(string n, string d, float v, ParamUser u, ParamGet g, ParamSet s, SetOnObject o) @@ -824,7 +824,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters defaultValue = v; userParam = u; getter = g; - setter = s; + setter = s; onObject = o; } } @@ -1266,13 +1266,13 @@ public class BSScene : PhysicsScene, IPhysicsParameters objectIDs.Add(TERRAIN_ID); TaintedUpdateParameter(parm, objectIDs, val); break; - case PhysParameterEntry.APPLY_TO_ALL: + case PhysParameterEntry.APPLY_TO_ALL: defaultLoc = val; // setting ALL also sets the default value - lock (PhysObjects) objectIDs = new List(PhysObjects.Keys); + lock (PhysObjects) objectIDs = new List(PhysObjects.Keys); TaintedUpdateParameter(parm, objectIDs, val); break; default: - // setting only one localID + // setting only one localID objectIDs.Add(localID); TaintedUpdateParameter(parm, objectIDs, val); break; @@ -1282,8 +1282,8 @@ public class BSScene : PhysicsScene, IPhysicsParameters // schedule the actual updating of the paramter to when the phys engine is not busy protected void TaintedUpdateParameter(string parm, List lIDs, float val) { - float xval = val; - List xlIDs = lIDs; + float xval = val; + List xlIDs = lIDs; string xparm = parm; TaintedObject("BSScene.UpdateParameterSet", delegate() { ParameterDefn thisParam; diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs index bbfdac6..3d15eaa 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs @@ -417,7 +417,10 @@ public class BSShapeCollection : IDisposable if (shapeType == ShapeData.PhysicsShapeType.SHAPE_AVATAR) { - newShape = new BulletShape(BulletSimAPI.BuildCapsuleShape2(PhysicsScene.World.ptr, shapeData), shapeType); + // The radius is scaled by 1/2 because we scale by the diameter. + newShape = new BulletShape( + BulletSimAPI.BuildCapsuleShape2(PhysicsScene.World.ptr, 0.5f, 1.0f, shapeData.Scale), + shapeType); newShape.shapeKey = (System.UInt64)shapeKey; newShape.isNativeShape = true; } @@ -428,7 +431,7 @@ public class BSShapeCollection : IDisposable newShape.isNativeShape = true; } - // Don't need to do a 'ReferenceShape()' here because native shapes are not tracked. + // Don't need to do a 'ReferenceShape()' here because native shapes are not shared. // DetailLog("{0},BSShapeCollection.AddNativeShapeToPrim,create,newshape={1}", shapeData.ID, newShape); prim.BSShape = newShape; diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs index 30754a7..24d8db6 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs @@ -608,7 +608,7 @@ public static extern IntPtr BuildNativeShape2(IntPtr world, ShapeData shapeData) public static extern bool IsNativeShape2(IntPtr shape); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern IntPtr BuildCapsuleShape2(IntPtr world, ShapeData shapeData); +public static extern IntPtr BuildCapsuleShape2(IntPtr world, float radius, float height, Vector3 scale); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern IntPtr CreateCompoundShape2(IntPtr sim); -- cgit v1.1 From f422b9b388fe67c61e610c79efabd5e07512884b Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Fri, 19 Oct 2012 10:48:45 -0700 Subject: BulletSim: reorder avatar collision checking to eliminate double collision_end. Various tweekings to avatar shape/mass/inertia/etc. Remove change from avatar radius to diameter. But still the avatar sinks. Collision_end now happens immediately rather than at the next subscription time. --- .../Region/Physics/BulletSPlugin/BSCharacter.cs | 33 +++++++++++----------- .../Region/Physics/BulletSPlugin/BSPhysObject.cs | 4 ++- OpenSim/Region/Physics/BulletSPlugin/BSScene.cs | 30 +++++++++++--------- .../Physics/BulletSPlugin/BSShapeCollection.cs | 8 +++--- .../Physics/BulletSPlugin/BSTerrainManager.cs | 1 + .../Region/Physics/BulletSPlugin/BulletSimAPI.cs | 2 +- 6 files changed, 43 insertions(+), 35 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs index e7bff6e..fc4526b 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs @@ -141,10 +141,6 @@ public class BSCharacter : BSPhysObject BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, BSBody.ptr); ZeroMotion(); - - OMV.Vector3 localInertia = BulletSimAPI.CalculateLocalInertia2(BSShape.ptr, MassRaw); - BulletSimAPI.SetMassProps2(BSBody.ptr, MassRaw, localInertia); - ForcePosition = _position; // Set the velocity and compute the proper friction ForceVelocity = _velocity; @@ -157,6 +153,9 @@ public class BSCharacter : BSPhysObject BulletSimAPI.SetCcdSweepSphereRadius2(BSBody.ptr, PhysicsScene.Params.ccdSweptSphereRadius); } + OMV.Vector3 localInertia = BulletSimAPI.CalculateLocalInertia2(BSShape.ptr, MassRaw); + BulletSimAPI.SetMassProps2(BSBody.ptr, MassRaw, localInertia); + BulletSimAPI.AddToCollisionFlags2(BSBody.ptr, CollisionFlags.CF_CHARACTER_OBJECT); BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, BSBody.ptr); @@ -583,14 +582,16 @@ public class BSCharacter : BSPhysObject private void ComputeAvatarScale(OMV.Vector3 size) { + // The 'size' given by the simulator is the mid-point of the avatar + // and X and Y are unspecified. + OMV.Vector3 newScale = OMV.Vector3.Zero; - // Scale wants the diameter so mult radius by two - newScale.X = PhysicsScene.Params.avatarCapsuleRadius * 2f; - newScale.Y = PhysicsScene.Params.avatarCapsuleRadius * 2f; + newScale.X = PhysicsScene.Params.avatarCapsuleRadius; + newScale.Y = PhysicsScene.Params.avatarCapsuleRadius; - // From the total height, add the capsule half spheres that are at each end - // newScale.Z = (size.Z) - Math.Min(newScale.X, newScale.Y); - newScale.Z = (size.Z * 2f); + // From the total height, remote the capsule half spheres that are at each end + newScale.Z = (size.Z * 2f) - Math.Min(newScale.X, newScale.Y); + // newScale.Z = (size.Z * 2f); Scale = newScale; } @@ -599,14 +600,14 @@ public class BSCharacter : BSPhysObject { _avatarVolume = (float)( Math.PI - * (Scale.X / 2f) - * (Scale.Y / 2f) // the area of capsule cylinder - * Scale.Z // times height of capsule cylinder + * Scale.X + * Scale.Y // the area of capsule cylinder + * Scale.Z // times height of capsule cylinder + 1.33333333f * Math.PI - * (Scale.X / 2f) - * (Math.Min(Scale.X, Scale.Y) / 2f) - * (Scale.Y / 2f) // plus the volume of the capsule end caps + * Scale.X + * Math.Min(Scale.X, Scale.Y) + * Scale.Y // plus the volume of the capsule end caps ); _mass = _avatarDensity * _avatarVolume; } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs index b8ef338..202052d 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs @@ -156,9 +156,11 @@ public abstract class BSPhysObject : PhysicsActor public virtual bool SendCollisions() { bool ret = true; + // If the 'no collision' call, force it to happen right now so quick collision_end + bool force = CollisionCollection.Count == 0; // throttle the collisions to the number of milliseconds specified in the subscription - if (PhysicsScene.SimulationNowTime >= NextCollisionOkTime) + if (force || (PhysicsScene.SimulationNowTime >= NextCollisionOkTime)) { NextCollisionOkTime = PhysicsScene.SimulationNowTime + SubscribedEventsMs; diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs index ab2835c..6621d39 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs @@ -532,26 +532,26 @@ public class BSScene : PhysicsScene, IPhysicsParameters } } - // This is a kludge to get avatar movement updates. - // The simulator expects collisions for avatars even if there are have been no collisions. This updates - // avatar animations and stuff. - // If you fix avatar animation updates, remove this overhead and let normal collision processing happen. - foreach (BSPhysObject bsp in m_avatars) - bsp.SendCollisions(); - // The above SendCollision's batch up the collisions on the objects. // Now push the collisions into the simulator. if (ObjectsWithCollisions.Count > 0) { foreach (BSPhysObject bsp in ObjectsWithCollisions) - if (!m_avatars.Contains(bsp)) // don't call avatars twice - if (!bsp.SendCollisions()) - { - // If the object is done colliding, see that it's removed from the colliding list - ObjectsWithNoMoreCollisions.Add(bsp); - } + if (!bsp.SendCollisions()) + { + // If the object is done colliding, see that it's removed from the colliding list + ObjectsWithNoMoreCollisions.Add(bsp); + } } + // This is a kludge to get avatar movement updates. + // The simulator expects collisions for avatars even if there are have been no collisions. + // The event updates avatar animations and stuff. + // If you fix avatar animation updates, remove this overhead and let normal collision processing happen. + foreach (BSPhysObject bsp in m_avatars) + if (!ObjectsWithCollisions.Contains(bsp)) // don't call avatars twice + bsp.SendCollisions(); + // Objects that are done colliding are removed from the ObjectsWithCollisions list. // Not done above because it is inside an iteration of ObjectWithCollisions. if (ObjectsWithNoMoreCollisions.Count > 0) @@ -575,6 +575,10 @@ public class BSScene : PhysicsScene, IPhysicsParameters } } + // This causes the unmanaged code to output ALL the values found in ALL the objects in the world. + // Only enable this in a limited test world with few objects. + // BulletSimAPI.DumpAllInfo2(World.ptr); // DEBUG DEBUG DEBUG + // The physics engine returns the number of milliseconds it simulated this call. // These are summed and normalized to one second and divided by 1000 to give the reported physics FPS. // We multiply by 55 to give a recognizable running rate (55 or less). diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs index 3d15eaa..861ffe7 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs @@ -417,10 +417,9 @@ public class BSShapeCollection : IDisposable if (shapeType == ShapeData.PhysicsShapeType.SHAPE_AVATAR) { - // The radius is scaled by 1/2 because we scale by the diameter. newShape = new BulletShape( - BulletSimAPI.BuildCapsuleShape2(PhysicsScene.World.ptr, 0.5f, 1.0f, shapeData.Scale), - shapeType); + BulletSimAPI.BuildCapsuleShape2(PhysicsScene.World.ptr, 1.0f, 1.0f, shapeData.Scale), + shapeType); newShape.shapeKey = (System.UInt64)shapeKey; newShape.isNativeShape = true; } @@ -432,7 +431,8 @@ public class BSShapeCollection : IDisposable } // Don't need to do a 'ReferenceShape()' here because native shapes are not shared. - // DetailLog("{0},BSShapeCollection.AddNativeShapeToPrim,create,newshape={1}", shapeData.ID, newShape); + DetailLog("{0},BSShapeCollection.AddNativeShapeToPrim,create,newshape={1},scale={2}", + shapeData.ID, newShape, shapeData.Scale); prim.BSShape = newShape; return true; diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs index 9743d94..4106534 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs @@ -114,6 +114,7 @@ public class BSTerrainManager BulletSimAPI.CreateBodyWithDefaultMotionState2(groundPlaneShape.ptr, BSScene.GROUNDPLANE_ID, Vector3.Zero, Quaternion.Identity)); BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, m_groundPlane.ptr); + BulletSimAPI.UpdateSingleAabb2(PhysicsScene.World.ptr, m_groundPlane.ptr); // Ground plane does not move BulletSimAPI.ForceActivationState2(m_groundPlane.ptr, ActivationState.DISABLE_SIMULATION); // Everything collides with the ground plane. diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs index 24d8db6..5ffd591 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs @@ -390,7 +390,7 @@ public enum CollisionFilterGroups : uint VolumeDetectMask = ~BSensorTrigger, TerrainFilter = BTerrainFilter, TerrainMask = BAllFilter & ~BStaticFilter, - GroundPlaneFilter = BAllFilter, + GroundPlaneFilter = BGroundPlaneFilter, GroundPlaneMask = BAllFilter }; -- cgit v1.1 From d94c4646ccf0703019dd5a7915afb43706a4de35 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Fri, 19 Oct 2012 15:43:31 -0700 Subject: BulletSim: add asset fetching so BulletSim works with new physics asset handling. Refactor some names to make them available for the asset tracking and fetching. --- .../Region/Physics/BulletSPlugin/BSCharacter.cs | 3 +- .../Region/Physics/BulletSPlugin/BSPhysObject.cs | 10 + OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | 96 +++---- .../Physics/BulletSPlugin/BSShapeCollection.cs | 296 +++++++++++++-------- 4 files changed, 240 insertions(+), 165 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs index fc4526b..623ac8f 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs @@ -200,10 +200,9 @@ public class BSCharacter : BSPhysObject } } public override OMV.Vector3 Scale { get; set; } - private PrimitiveBaseShape _pbs; public override PrimitiveBaseShape Shape { - set { _pbs = value;} + set { BaseShape = value; } } public override bool Grabbed { diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs index 202052d..ead6a08 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs @@ -47,6 +47,7 @@ public abstract class BSPhysObject : PhysicsActor TypeName = typeName; Linkset = new BSLinkset(PhysicsScene, this); + LastAssetBuildFailed = false; CollisionCollection = new CollisionEventUpdate(); SubscribedEventsMs = 0; @@ -69,6 +70,13 @@ public abstract class BSPhysObject : PhysicsActor // Reference to the physical shape (btCollisionShape) of this object public BulletShape BSShape; + // 'true' if the mesh's underlying asset failed to build. + // This will keep us from looping after the first time the build failed. + public bool LastAssetBuildFailed { get; set; } + + // The objects base shape information. Null if not a prim type shape. + public PrimitiveBaseShape BaseShape { get; protected set; } + // When the physical properties are updated, an EntityProperty holds the update values. // Keep the current and last EntityProperties to enable computation of differences // between the current update and the previous values. @@ -101,6 +109,8 @@ public abstract class BSPhysObject : PhysicsActor public abstract float ForceBuoyancy { get; set; } + public virtual bool ForceBodyShapeRebuild(bool inTaintTime) { return false; } + #region Collisions // Requested number of milliseconds between collision events. Zero means disabled. diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index 8013e68..aeeb4dd 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs @@ -46,8 +46,6 @@ public sealed class BSPrim : BSPhysObject private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private static readonly string LogHeader = "[BULLETS PRIM]"; - private PrimitiveBaseShape _pbs; - // _size is what the user passed. Scale is what we pass to the physics engine with the mesh. // Often Scale is unity because the meshmerizer will apply _size when creating the mesh. private OMV.Vector3 _size; // the multiplier for each mesh dimension as passed by the user @@ -103,7 +101,7 @@ public sealed class BSPrim : BSPhysObject _buoyancy = 1f; _velocity = OMV.Vector3.Zero; _rotationalVelocity = OMV.Vector3.Zero; - _pbs = pbs; + BaseShape = pbs; _isPhysical = pisPhysical; _isVolumeDetect = false; _friction = PhysicsScene.Params.defaultFriction; // TODO: compute based on object material @@ -160,14 +158,7 @@ public sealed class BSPrim : BSPhysObject get { return _size; } set { _size = value; - PhysicsScene.TaintedObject("BSPrim.setSize", delegate() - { - _mass = CalculateMass(); // changing size changes the mass - // Since _size changed, the mesh needs to be rebuilt. If rebuilt, all the correct - // scale and margins are set. - CreateGeomAndObject(true); - // DetailLog("{0},BSPrim.setSize,size={1},scale={2},mass={3},physical={4}", LocalID, _size, Scale, _mass, IsPhysical); - }); + ForceBodyShapeRebuild(false); } } // Scale is what we set in the physics engine. It is different than 'size' in that @@ -176,14 +167,23 @@ public sealed class BSPrim : BSPhysObject public override PrimitiveBaseShape Shape { set { - _pbs = value; - PhysicsScene.TaintedObject("BSPrim.setShape", delegate() - { - _mass = CalculateMass(); // changing the shape changes the mass - CreateGeomAndObject(true); - }); + BaseShape = value; + ForceBodyShapeRebuild(false); } } + public override bool ForceBodyShapeRebuild(bool inTaintTime) + { + BSScene.TaintCallback rebuildOperation = delegate() + { + _mass = CalculateMass(); // changing the shape changes the mass + CreateGeomAndObject(true); + }; + if (inTaintTime) + rebuildOperation(); + else + PhysicsScene.TaintedObject("BSPrim.ForceBodyShapeRebuild", rebuildOperation); + return true; + } public override bool Grabbed { set { _grabbed = value; } @@ -924,19 +924,19 @@ public sealed class BSPrim : BSPhysObject float tmp; float returnMass = 0; - float hollowAmount = (float)_pbs.ProfileHollow * 2.0e-5f; + float hollowAmount = (float)BaseShape.ProfileHollow * 2.0e-5f; float hollowVolume = hollowAmount * hollowAmount; - switch (_pbs.ProfileShape) + switch (BaseShape.ProfileShape) { case ProfileShape.Square: // default box - if (_pbs.PathCurve == (byte)Extrusion.Straight) + if (BaseShape.PathCurve == (byte)Extrusion.Straight) { if (hollowAmount > 0.0) { - switch (_pbs.HollowShape) + switch (BaseShape.HollowShape) { case HollowShape.Square: case HollowShape.Same: @@ -960,19 +960,19 @@ public sealed class BSPrim : BSPhysObject } } - else if (_pbs.PathCurve == (byte)Extrusion.Curve1) + else if (BaseShape.PathCurve == (byte)Extrusion.Curve1) { //a tube - volume *= 0.78539816339e-2f * (float)(200 - _pbs.PathScaleX); - tmp= 1.0f -2.0e-2f * (float)(200 - _pbs.PathScaleY); + volume *= 0.78539816339e-2f * (float)(200 - BaseShape.PathScaleX); + tmp= 1.0f -2.0e-2f * (float)(200 - BaseShape.PathScaleY); volume -= volume*tmp*tmp; if (hollowAmount > 0.0) { hollowVolume *= hollowAmount; - switch (_pbs.HollowShape) + switch (BaseShape.HollowShape) { case HollowShape.Square: case HollowShape.Same: @@ -997,13 +997,13 @@ public sealed class BSPrim : BSPhysObject case ProfileShape.Circle: - if (_pbs.PathCurve == (byte)Extrusion.Straight) + if (BaseShape.PathCurve == (byte)Extrusion.Straight) { volume *= 0.78539816339f; // elipse base if (hollowAmount > 0.0) { - switch (_pbs.HollowShape) + switch (BaseShape.HollowShape) { case HollowShape.Same: case HollowShape.Circle: @@ -1025,10 +1025,10 @@ public sealed class BSPrim : BSPhysObject } } - else if (_pbs.PathCurve == (byte)Extrusion.Curve1) + else if (BaseShape.PathCurve == (byte)Extrusion.Curve1) { - volume *= 0.61685027506808491367715568749226e-2f * (float)(200 - _pbs.PathScaleX); - tmp = 1.0f - .02f * (float)(200 - _pbs.PathScaleY); + volume *= 0.61685027506808491367715568749226e-2f * (float)(200 - BaseShape.PathScaleX); + tmp = 1.0f - .02f * (float)(200 - BaseShape.PathScaleY); volume *= (1.0f - tmp * tmp); if (hollowAmount > 0.0) @@ -1037,7 +1037,7 @@ public sealed class BSPrim : BSPhysObject // calculate the hollow volume by it's shape compared to the prim shape hollowVolume *= hollowAmount; - switch (_pbs.HollowShape) + switch (BaseShape.HollowShape) { case HollowShape.Same: case HollowShape.Circle: @@ -1061,7 +1061,7 @@ public sealed class BSPrim : BSPhysObject break; case ProfileShape.HalfCircle: - if (_pbs.PathCurve == (byte)Extrusion.Curve1) + if (BaseShape.PathCurve == (byte)Extrusion.Curve1) { volume *= 0.52359877559829887307710723054658f; } @@ -1069,7 +1069,7 @@ public sealed class BSPrim : BSPhysObject case ProfileShape.EquilateralTriangle: - if (_pbs.PathCurve == (byte)Extrusion.Straight) + if (BaseShape.PathCurve == (byte)Extrusion.Straight) { volume *= 0.32475953f; @@ -1077,7 +1077,7 @@ public sealed class BSPrim : BSPhysObject { // calculate the hollow volume by it's shape compared to the prim shape - switch (_pbs.HollowShape) + switch (BaseShape.HollowShape) { case HollowShape.Same: case HollowShape.Triangle: @@ -1102,11 +1102,11 @@ public sealed class BSPrim : BSPhysObject volume *= (1.0f - hollowVolume); } } - else if (_pbs.PathCurve == (byte)Extrusion.Curve1) + else if (BaseShape.PathCurve == (byte)Extrusion.Curve1) { volume *= 0.32475953f; - volume *= 0.01f * (float)(200 - _pbs.PathScaleX); - tmp = 1.0f - .02f * (float)(200 - _pbs.PathScaleY); + volume *= 0.01f * (float)(200 - BaseShape.PathScaleX); + tmp = 1.0f - .02f * (float)(200 - BaseShape.PathScaleY); volume *= (1.0f - tmp * tmp); if (hollowAmount > 0.0) @@ -1114,7 +1114,7 @@ public sealed class BSPrim : BSPhysObject hollowVolume *= hollowAmount; - switch (_pbs.HollowShape) + switch (BaseShape.HollowShape) { case HollowShape.Same: case HollowShape.Triangle: @@ -1154,26 +1154,26 @@ public sealed class BSPrim : BSPhysObject float profileBegin; float profileEnd; - if (_pbs.PathCurve == (byte)Extrusion.Straight || _pbs.PathCurve == (byte)Extrusion.Flexible) + if (BaseShape.PathCurve == (byte)Extrusion.Straight || BaseShape.PathCurve == (byte)Extrusion.Flexible) { - taperX1 = _pbs.PathScaleX * 0.01f; + taperX1 = BaseShape.PathScaleX * 0.01f; if (taperX1 > 1.0f) taperX1 = 2.0f - taperX1; taperX = 1.0f - taperX1; - taperY1 = _pbs.PathScaleY * 0.01f; + taperY1 = BaseShape.PathScaleY * 0.01f; if (taperY1 > 1.0f) taperY1 = 2.0f - taperY1; taperY = 1.0f - taperY1; } else { - taperX = _pbs.PathTaperX * 0.01f; + taperX = BaseShape.PathTaperX * 0.01f; if (taperX < 0.0f) taperX = -taperX; taperX1 = 1.0f - taperX; - taperY = _pbs.PathTaperY * 0.01f; + taperY = BaseShape.PathTaperY * 0.01f; if (taperY < 0.0f) taperY = -taperY; taperY1 = 1.0f - taperY; @@ -1183,13 +1183,13 @@ public sealed class BSPrim : BSPhysObject volume *= (taperX1 * taperY1 + 0.5f * (taperX1 * taperY + taperX * taperY1) + 0.3333333333f * taperX * taperY); - pathBegin = (float)_pbs.PathBegin * 2.0e-5f; - pathEnd = 1.0f - (float)_pbs.PathEnd * 2.0e-5f; + pathBegin = (float)BaseShape.PathBegin * 2.0e-5f; + pathEnd = 1.0f - (float)BaseShape.PathEnd * 2.0e-5f; volume *= (pathEnd - pathBegin); // this is crude aproximation - profileBegin = (float)_pbs.ProfileBegin * 2.0e-5f; - profileEnd = 1.0f - (float)_pbs.ProfileEnd * 2.0e-5f; + profileBegin = (float)BaseShape.ProfileBegin * 2.0e-5f; + profileEnd = 1.0f - (float)BaseShape.ProfileEnd * 2.0e-5f; volume *= (profileEnd - profileBegin); returnMass = _density * volume; @@ -1251,7 +1251,7 @@ public sealed class BSPrim : BSPhysObject // Create the correct physical representation for this type of object. // Updates BSBody and BSShape with the new information. // Ignore 'forceRebuild'. This routine makes the right choices and changes of necessary. - PhysicsScene.Shapes.GetBodyAndShape(false, PhysicsScene.World, this, shapeData, _pbs, + PhysicsScene.Shapes.GetBodyAndShape(false, PhysicsScene.World, this, shapeData, BaseShape, null, delegate(BulletBody dBody) { // Called if the current prim body is about to be destroyed. diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs index 861ffe7..d3ba273 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs @@ -117,7 +117,7 @@ public class BSShapeCollection : IDisposable // Track another user of a body // We presume the caller has allocated the body. - // Bodies only have one user so the reference count is either 1 or 0. + // Bodies only have one user so the body is just put into the world if not already there. public void ReferenceBody(BulletBody body, bool inTaintTime) { lock (m_collectionActivityLock) @@ -241,26 +241,32 @@ public class BSShapeCollection : IDisposable BSScene.TaintCallback dereferenceOperation = delegate() { - switch (shape.type) + if (shape.ptr != IntPtr.Zero) { - case ShapeData.PhysicsShapeType.SHAPE_HULL: - DereferenceHull(shape, shapeCallback); - break; - case ShapeData.PhysicsShapeType.SHAPE_MESH: - DereferenceMesh(shape, shapeCallback); - break; - case ShapeData.PhysicsShapeType.SHAPE_UNKNOWN: - break; - default: + if (shape.isNativeShape) + { // Native shapes are not tracked and are released immediately - if (shape.ptr != IntPtr.Zero & shape.isNativeShape) + DetailLog("{0},BSShapeCollection.DereferenceShape,deleteNativeShape,ptr={1},taintTime={2}", + BSScene.DetailLogZero, shape.ptr.ToString("X"), inTaintTime); + if (shapeCallback != null) shapeCallback(shape); + BulletSimAPI.DeleteCollisionShape2(PhysicsScene.World.ptr, shape.ptr); + } + else + { + switch (shape.type) { - DetailLog("{0},BSShapeCollection.DereferenceShape,deleteNativeShape,ptr={1},taintTime={2}", - BSScene.DetailLogZero, shape.ptr.ToString("X"), inTaintTime); - if (shapeCallback != null) shapeCallback(shape); - BulletSimAPI.DeleteCollisionShape2(PhysicsScene.World.ptr, shape.ptr); + case ShapeData.PhysicsShapeType.SHAPE_HULL: + DereferenceHull(shape, shapeCallback); + break; + case ShapeData.PhysicsShapeType.SHAPE_MESH: + DereferenceMesh(shape, shapeCallback); + break; + case ShapeData.PhysicsShapeType.SHAPE_UNKNOWN: + break; + default: + break; } - break; + } } }; if (inTaintTime) @@ -405,7 +411,6 @@ public class BSShapeCollection : IDisposable ShapeData.PhysicsShapeType shapeType, ShapeData.FixedShapeKey shapeKey, ShapeDestructionCallback shapeCallback) { - BulletShape newShape; shapeData.Type = shapeType; // Bullet native objects are scaled by the Bullet engine so pass the size in @@ -415,27 +420,35 @@ public class BSShapeCollection : IDisposable // release any previous shape DereferenceShape(prim.BSShape, true, shapeCallback); + BulletShape newShape = BuildPhysicalNativeShape(shapeType, shapeData, shapeKey); + + // Don't need to do a 'ReferenceShape()' here because native shapes are not shared. + DetailLog("{0},BSShapeCollection.AddNativeShapeToPrim,create,newshape={1},scale={2}", + shapeData.ID, newShape, shapeData.Scale); + + prim.BSShape = newShape; + return true; + } + + private BulletShape BuildPhysicalNativeShape(ShapeData.PhysicsShapeType shapeType, + ShapeData shapeData, ShapeData.FixedShapeKey shapeKey) + { + BulletShape newShape; + if (shapeType == ShapeData.PhysicsShapeType.SHAPE_AVATAR) { newShape = new BulletShape( BulletSimAPI.BuildCapsuleShape2(PhysicsScene.World.ptr, 1.0f, 1.0f, shapeData.Scale), shapeType); - newShape.shapeKey = (System.UInt64)shapeKey; - newShape.isNativeShape = true; } else { newShape = new BulletShape(BulletSimAPI.BuildNativeShape2(PhysicsScene.World.ptr, shapeData), shapeType); - newShape.shapeKey = (System.UInt64)shapeKey; - newShape.isNativeShape = true; } + newShape.shapeKey = (System.UInt64)shapeKey; + newShape.isNativeShape = true; - // Don't need to do a 'ReferenceShape()' here because native shapes are not shared. - DetailLog("{0},BSShapeCollection.AddNativeShapeToPrim,create,newshape={1},scale={2}", - shapeData.ID, newShape, shapeData.Scale); - - prim.BSShape = newShape; - return true; + return newShape; } // Builds a mesh shape in the physical world and updates prim.BSShape. @@ -461,6 +474,8 @@ public class BSShapeCollection : IDisposable DereferenceShape(prim.BSShape, true, shapeCallback); newShape = CreatePhysicalMesh(prim.PhysObjectName, newMeshKey, pbs, shapeData.Size, lod); + // Take evasive action if the mesh was not constructed. + newShape = VerifyMeshCreated(newShape, prim, shapeData, pbs); ReferenceShape(newShape); @@ -474,7 +489,7 @@ public class BSShapeCollection : IDisposable private BulletShape CreatePhysicalMesh(string objName, System.UInt64 newMeshKey, PrimitiveBaseShape pbs, OMV.Vector3 size, float lod) { IMesh meshData = null; - IntPtr meshPtr; + IntPtr meshPtr = IntPtr.Zero; MeshDesc meshDesc; if (Meshes.TryGetValue(newMeshKey, out meshDesc)) { @@ -486,23 +501,26 @@ public class BSShapeCollection : IDisposable // Pass false for physicalness as this creates some sort of bounding box which we don't need meshData = PhysicsScene.mesher.CreateMesh(objName, pbs, size, lod, false); - int[] indices = meshData.getIndexListAsInt(); - List vertices = meshData.getVertexList(); - - float[] verticesAsFloats = new float[vertices.Count * 3]; - int vi = 0; - foreach (OMV.Vector3 vv in vertices) + if (meshData != null) { - verticesAsFloats[vi++] = vv.X; - verticesAsFloats[vi++] = vv.Y; - verticesAsFloats[vi++] = vv.Z; - } + int[] indices = meshData.getIndexListAsInt(); + List vertices = meshData.getVertexList(); - // m_log.DebugFormat("{0}: CreateGeomMesh: calling CreateMesh. lid={1}, key={2}, indices={3}, vertices={4}", - // LogHeader, prim.LocalID, newMeshKey, indices.Length, vertices.Count); + float[] verticesAsFloats = new float[vertices.Count * 3]; + int vi = 0; + foreach (OMV.Vector3 vv in vertices) + { + verticesAsFloats[vi++] = vv.X; + verticesAsFloats[vi++] = vv.Y; + verticesAsFloats[vi++] = vv.Z; + } + + // m_log.DebugFormat("{0}: CreateGeomMesh: calling CreateMesh. lid={1}, key={2}, indices={3}, vertices={4}", + // LogHeader, prim.LocalID, newMeshKey, indices.Length, vertices.Count); - meshPtr = BulletSimAPI.CreateMeshShape2(PhysicsScene.World.ptr, - indices.GetLength(0), indices, vertices.Count, verticesAsFloats); + meshPtr = BulletSimAPI.CreateMeshShape2(PhysicsScene.World.ptr, + indices.GetLength(0), indices, vertices.Count, verticesAsFloats); + } } BulletShape newShape = new BulletShape(meshPtr, ShapeData.PhysicsShapeType.SHAPE_MESH); newShape.shapeKey = newMeshKey; @@ -531,6 +549,7 @@ public class BSShapeCollection : IDisposable DereferenceShape(prim.BSShape, true, shapeCallback); newShape = CreatePhysicalHull(prim.PhysObjectName, newHullKey, pbs, shapeData.Size, lod); + newShape = VerifyMeshCreated(newShape, prim, shapeData, pbs); ReferenceShape(newShape); @@ -544,7 +563,7 @@ public class BSShapeCollection : IDisposable private BulletShape CreatePhysicalHull(string objName, System.UInt64 newHullKey, PrimitiveBaseShape pbs, OMV.Vector3 size, float lod) { - IntPtr hullPtr; + IntPtr hullPtr = IntPtr.Zero; HullDesc hullDesc; if (Hulls.TryGetValue(newHullKey, out hullDesc)) { @@ -556,86 +575,89 @@ public class BSShapeCollection : IDisposable // Build a new hull in the physical world // Pass false for physicalness as this creates some sort of bounding box which we don't need IMesh meshData = PhysicsScene.mesher.CreateMesh(objName, pbs, size, lod, false); - - int[] indices = meshData.getIndexListAsInt(); - List vertices = meshData.getVertexList(); - - //format conversion from IMesh format to DecompDesc format - List convIndices = new List(); - List convVertices = new List(); - for (int ii = 0; ii < indices.GetLength(0); ii++) - { - convIndices.Add(indices[ii]); - } - foreach (OMV.Vector3 vv in vertices) + if (meshData != null) { - convVertices.Add(new float3(vv.X, vv.Y, vv.Z)); - } - // setup and do convex hull conversion - m_hulls = new List(); - DecompDesc dcomp = new DecompDesc(); - dcomp.mIndices = convIndices; - dcomp.mVertices = convVertices; - ConvexBuilder convexBuilder = new ConvexBuilder(HullReturn); - // create the hull into the _hulls variable - convexBuilder.process(dcomp); - - // Convert the vertices and indices for passing to unmanaged. - // The hull information is passed as a large floating point array. - // The format is: - // convHulls[0] = number of hulls - // convHulls[1] = number of vertices in first hull - // convHulls[2] = hull centroid X coordinate - // convHulls[3] = hull centroid Y coordinate - // convHulls[4] = hull centroid Z coordinate - // convHulls[5] = first hull vertex X - // convHulls[6] = first hull vertex Y - // convHulls[7] = first hull vertex Z - // convHulls[8] = second hull vertex X - // ... - // convHulls[n] = number of vertices in second hull - // convHulls[n+1] = second hull centroid X coordinate - // ... - // - // TODO: is is very inefficient. Someday change the convex hull generator to return - // data structures that do not need to be converted in order to pass to Bullet. - // And maybe put the values directly into pinned memory rather than marshaling. - int hullCount = m_hulls.Count; - int totalVertices = 1; // include one for the count of the hulls - foreach (ConvexResult cr in m_hulls) - { - totalVertices += 4; // add four for the vertex count and centroid - totalVertices += cr.HullIndices.Count * 3; // we pass just triangles - } - float[] convHulls = new float[totalVertices]; + int[] indices = meshData.getIndexListAsInt(); + List vertices = meshData.getVertexList(); - convHulls[0] = (float)hullCount; - int jj = 1; - foreach (ConvexResult cr in m_hulls) - { - // copy vertices for index access - float3[] verts = new float3[cr.HullVertices.Count]; - int kk = 0; - foreach (float3 ff in cr.HullVertices) + //format conversion from IMesh format to DecompDesc format + List convIndices = new List(); + List convVertices = new List(); + for (int ii = 0; ii < indices.GetLength(0); ii++) { - verts[kk++] = ff; + convIndices.Add(indices[ii]); + } + foreach (OMV.Vector3 vv in vertices) + { + convVertices.Add(new float3(vv.X, vv.Y, vv.Z)); } - // add to the array one hull's worth of data - convHulls[jj++] = cr.HullIndices.Count; - convHulls[jj++] = 0f; // centroid x,y,z - convHulls[jj++] = 0f; - convHulls[jj++] = 0f; - foreach (int ind in cr.HullIndices) + // setup and do convex hull conversion + m_hulls = new List(); + DecompDesc dcomp = new DecompDesc(); + dcomp.mIndices = convIndices; + dcomp.mVertices = convVertices; + ConvexBuilder convexBuilder = new ConvexBuilder(HullReturn); + // create the hull into the _hulls variable + convexBuilder.process(dcomp); + + // Convert the vertices and indices for passing to unmanaged. + // The hull information is passed as a large floating point array. + // The format is: + // convHulls[0] = number of hulls + // convHulls[1] = number of vertices in first hull + // convHulls[2] = hull centroid X coordinate + // convHulls[3] = hull centroid Y coordinate + // convHulls[4] = hull centroid Z coordinate + // convHulls[5] = first hull vertex X + // convHulls[6] = first hull vertex Y + // convHulls[7] = first hull vertex Z + // convHulls[8] = second hull vertex X + // ... + // convHulls[n] = number of vertices in second hull + // convHulls[n+1] = second hull centroid X coordinate + // ... + // + // TODO: is is very inefficient. Someday change the convex hull generator to return + // data structures that do not need to be converted in order to pass to Bullet. + // And maybe put the values directly into pinned memory rather than marshaling. + int hullCount = m_hulls.Count; + int totalVertices = 1; // include one for the count of the hulls + foreach (ConvexResult cr in m_hulls) { - convHulls[jj++] = verts[ind].x; - convHulls[jj++] = verts[ind].y; - convHulls[jj++] = verts[ind].z; + totalVertices += 4; // add four for the vertex count and centroid + totalVertices += cr.HullIndices.Count * 3; // we pass just triangles + } + float[] convHulls = new float[totalVertices]; + + convHulls[0] = (float)hullCount; + int jj = 1; + foreach (ConvexResult cr in m_hulls) + { + // copy vertices for index access + float3[] verts = new float3[cr.HullVertices.Count]; + int kk = 0; + foreach (float3 ff in cr.HullVertices) + { + verts[kk++] = ff; + } + + // add to the array one hull's worth of data + convHulls[jj++] = cr.HullIndices.Count; + convHulls[jj++] = 0f; // centroid x,y,z + convHulls[jj++] = 0f; + convHulls[jj++] = 0f; + foreach (int ind in cr.HullIndices) + { + convHulls[jj++] = verts[ind].x; + convHulls[jj++] = verts[ind].y; + convHulls[jj++] = verts[ind].z; + } } + // create the hull data structure in Bullet + hullPtr = BulletSimAPI.CreateHullShape2(PhysicsScene.World.ptr, hullCount, convHulls); } - // create the hull data structure in Bullet - hullPtr = BulletSimAPI.CreateHullShape2(PhysicsScene.World.ptr, hullCount, convHulls); } BulletShape newShape = new BulletShape(hullPtr, ShapeData.PhysicsShapeType.SHAPE_HULL); @@ -676,6 +698,50 @@ public class BSShapeCollection : IDisposable return ComputeShapeKey(shapeData, pbs, out lod); } + private BulletShape VerifyMeshCreated(BulletShape newShape, BSPhysObject prim, ShapeData shapeData, PrimitiveBaseShape pbs) + { + // If the shape was successfully created, nothing more to do + if (newShape.ptr != IntPtr.Zero) + return newShape; + + // The most common reason for failure is that an underlying asset is not available + + // If this mesh has an underlying asset and we have not failed getting it before, fetch the asset + if (pbs.SculptEntry && !prim.LastAssetBuildFailed && pbs.SculptTexture != OMV.UUID.Zero) + { + prim.LastAssetBuildFailed = true; + BSPhysObject xprim = prim; + Util.FireAndForget(delegate + { + RequestAssetDelegate assetProvider = PhysicsScene.RequestAssetMethod; + if (assetProvider != null) + { + BSPhysObject yprim = xprim; // probably not necessary, but, just in case. + assetProvider(yprim.BaseShape.SculptTexture, delegate(AssetBase asset) + { + if (!yprim.BaseShape.SculptEntry) + return; + if (yprim.BaseShape.SculptTexture.ToString() != asset.ID) + return; + + yprim.BaseShape.SculptData = new byte[asset.Data.Length]; + asset.Data.CopyTo(yprim.BaseShape.SculptData, 0); + // This will cause the prim to see that the filler shape is not the right + // one and try again to build the object. + yprim.ForceBodyShapeRebuild(false); + + }); + } + }); + } + + // While we figure out the real problem, stick a simple native shape on the object. + BulletShape fillinShape = + BuildPhysicalNativeShape(ShapeData.PhysicsShapeType.SHAPE_SPHERE, shapeData, ShapeData.FixedShapeKey.KEY_SPHERE); + + return fillinShape; + } + // Create a body object in Bullet. // Updates prim.BSBody with the information about the new body if one is created. // Returns 'true' if an object was actually created. -- cgit v1.1 From e46987972525f7727eb4bd9d6eafa522937558cb Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 19 Oct 2012 23:45:55 +0100 Subject: Add "debug groups verbose " region console command This allows one to turn on super-verbose groups debug logging on and off whilst the region is in operation. --- .../Avatar/XmlRpcGroups/GroupsModule.cs | 29 ++++++++++++++++++++++ 1 file changed, 29 insertions(+) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs index e669f4c..6b69de2 100644 --- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs @@ -123,7 +123,36 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups public void AddRegion(Scene scene) { if (m_groupsEnabled) + { scene.RegisterModuleInterface(this); + scene.AddCommand( + "debug", + this, + "debug groups verbose", + "debug groups verbose ", + "This setting turns on very verbose groups debugging", + HandleDebugGroupsVerbose); + } + } + + private void HandleDebugGroupsVerbose(object modules, string[] args) + { + if (args.Length < 4) + { + MainConsole.Instance.Output("Usage: debug groups verbose "); + return; + } + + bool verbose = false; + if (!bool.TryParse(args[3], out verbose)) + { + MainConsole.Instance.Output("Usage: debug groups verbose "); + return; + } + + m_debugEnabled = verbose; + + MainConsole.Instance.Output("{0} verbose logging set to {1}", Name, m_debugEnabled); } public void RegionLoaded(Scene scene) -- cgit v1.1 From 6cca7136799c2f89c0511eb1831102e4b7a87fed Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Sat, 20 Oct 2012 01:08:52 +0100 Subject: Fix build break from commit e469879 --- OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs index 6b69de2..b9b4413 100644 --- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs @@ -152,7 +152,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups m_debugEnabled = verbose; - MainConsole.Instance.Output("{0} verbose logging set to {1}", Name, m_debugEnabled); + MainConsole.Instance.OutputFormat("{0} verbose logging set to {1}", Name, m_debugEnabled); } public void RegionLoaded(Scene scene) -- cgit v1.1 From cd3762ca9f97052a6fe91a3eca491407cc6f039e Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Sat, 20 Oct 2012 01:26:04 +0100 Subject: Add experimental [Groups] MessageOnlineUsersOnly option for Flotsam XmlRpc groups. This retrieves and caches information from the PresenceService to only send messages to online users. This is reported to much improve performance for large groups where most users are offline. Cache is 20 seconds to balance requests against users not receiving messages until cache updates. This is an alternative to an approach where login/logout notification is sent directly from simulator to groups service. However, I'm not convinced that this PresenceService approach is actually better. Needs more thought. --- .../Avatar/XmlRpcGroups/GroupsMessagingModule.cs | 76 ++++++++++++++++++++-- 1 file changed, 69 insertions(+), 7 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsMessagingModule.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsMessagingModule.cs index 10b83e6..55bb7dc 100644 --- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsMessagingModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsMessagingModule.cs @@ -27,6 +27,7 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Reflection; using log4net; using Mono.Addins; @@ -36,6 +37,8 @@ using OpenMetaverse.StructuredData; using OpenSim.Framework; using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Scenes; +using OpenSim.Services.Interfaces; +using PresenceInfo = OpenSim.Services.Interfaces.PresenceInfo; namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups { @@ -45,6 +48,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private List m_sceneList = new List(); + private IPresenceService m_presenceService; private IMessageTransferModule m_msgTransferModule = null; @@ -54,6 +58,27 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups private bool m_groupMessagingEnabled = false; private bool m_debugEnabled = true; + /// + /// If enabled, module only tries to send group IMs to online users by querying cached presence information. + /// + private bool m_messageOnlineAgentsOnly; + + /// + /// Cache for online users. + /// + /// + /// Group ID is key, presence information for online members is value. + /// Will only be non-null if m_messageOnlineAgentsOnly = true + /// We cache here so that group messages don't constantly have to re-request the online user list to avoid + /// attempted expensive sending of messages to offline users. + /// The tradeoff is that a user that comes online will not receive messages consistently from all other users + /// until caches have updated. + /// Therefore, we set the cache expiry to just 20 seconds. + /// + private ExpiringCache m_usersOnlineCache; + + private int m_usersOnlineCacheExpirySeconds = 20; + #region IRegionModuleBase Members public void Initialise(IConfigSource config) @@ -83,10 +108,17 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups return; } + m_messageOnlineAgentsOnly = groupsConfig.GetBoolean("MessageOnlineUsersOnly", false); + + if (m_messageOnlineAgentsOnly) + m_usersOnlineCache = new ExpiringCache(); + m_debugEnabled = groupsConfig.GetBoolean("DebugEnabled", true); } - m_log.Info("[GROUPS-MESSAGING]: GroupsMessagingModule starting up"); + m_log.InfoFormat( + "[GROUPS-MESSAGING]: GroupsMessagingModule enabled with MessageOnlineOnly = {0}, DebugEnabled = {1}", + m_messageOnlineAgentsOnly, m_debugEnabled); } public void AddRegion(Scene scene) @@ -126,6 +158,8 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups return; } + if (m_presenceService == null) + m_presenceService = scene.PresenceService; m_sceneList.Add(scene); @@ -207,12 +241,40 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups public void SendMessageToGroup(GridInstantMessage im, UUID groupID) { List groupMembers = m_groupData.GetGroupMembers(new UUID(im.fromAgentID), groupID); - - if (m_debugEnabled) - m_log.DebugFormat( - "[GROUPS-MESSAGING]: SendMessageToGroup called for group {0} with {1} visible members", - groupID, groupMembers.Count); - + + if (m_messageOnlineAgentsOnly) + { + string[] t1 = groupMembers.ConvertAll(gmd => gmd.AgentID.ToString()).ToArray(); + + // We cache in order not to overwhlem the presence service on large grids with many groups. This does + // mean that members coming online will not see all group members until after m_usersOnlineCacheExpirySeconds has elapsed. + // (assuming this is the same across all grid simulators). + PresenceInfo[] onlineAgents; + if (!m_usersOnlineCache.TryGetValue(groupID, out onlineAgents)) + { + onlineAgents = m_presenceService.GetAgents(t1); + m_usersOnlineCache.Add(groupID, onlineAgents, m_usersOnlineCacheExpirySeconds); + } + + HashSet onlineAgentsUuidSet = new HashSet(); + Array.ForEach(onlineAgents, pi => onlineAgentsUuidSet.Add(pi.UserID)); + + int allMembersCount = groupMembers.Count; + groupMembers = groupMembers.Where(gmd => onlineAgentsUuidSet.Contains(gmd.AgentID.ToString())).ToList(); + + // if (m_debugEnabled) + m_log.DebugFormat( + "[GROUPS-MESSAGING]: SendMessageToGroup called for group {0} with {1} visible members, {2} online", + groupID, allMembersCount, groupMembers.Count()); + } + else + { + if (m_debugEnabled) + m_log.DebugFormat( + "[GROUPS-MESSAGING]: SendMessageToGroup called for group {0} with {1} visible members", + groupID, groupMembers.Count); + } + foreach (GroupMembersData member in groupMembers) { if (m_groupData.hasAgentDroppedGroupChatSession(member.AgentID, groupID)) -- cgit v1.1 From da2b23f18d232230ac4d967f8d3b256aebd4741e Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Sat, 20 Oct 2012 02:02:13 +0100 Subject: Improve efficiency of friends notification by only make one PresenceService call for all friends rather than one for each friend. However, large groups could still take a very long time since we still need to message each avatar on different simulators. --- .../CoreModules/Avatar/Friends/FriendsModule.cs | 53 ++++++++++------------ 1 file changed, 24 insertions(+), 29 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs index 11db18a..f1903c3 100644 --- a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs @@ -28,6 +28,7 @@ using System; using System.Collections; using System.Collections.Generic; +using System.Linq; using System.Reflection; using System.Threading; using log4net; @@ -495,42 +496,36 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends protected virtual void StatusNotify(List friendList, UUID userID, bool online) { - foreach (FriendInfo friend in friendList) + List friendStringIds = friendList.ConvertAll(friend => friend.Friend); + List remoteFriendStringIds = new List(); + foreach (string friendStringId in friendStringIds) { - UUID friendID; - if (UUID.TryParse(friend.Friend, out friendID)) + UUID friendUuid; + if (UUID.TryParse(friendStringId, out friendUuid)) { - // Try local - if (LocalStatusNotification(userID, friendID, online)) + if (LocalStatusNotification(userID, friendUuid, online)) continue; - // The friend is not here [as root]. Let's forward. - PresenceInfo[] friendSessions = PresenceService.GetAgents(new string[] { friendID.ToString() }); - if (friendSessions != null && friendSessions.Length > 0) - { - PresenceInfo friendSession = null; - foreach (PresenceInfo pinfo in friendSessions) - { - if (pinfo.RegionID != UUID.Zero) // let's guard against sessions-gone-bad - { - friendSession = pinfo; - break; - } - } - - if (friendSession != null) - { - GridRegion region = GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, friendSession.RegionID); - //m_log.DebugFormat("[FRIENDS]: Remote Notify to region {0}", region.RegionName); - m_FriendsSimConnector.StatusNotify(region, userID, friendID, online); - } - } - - // Friend is not online. Ignore. + remoteFriendStringIds.Add(friendStringId); } else { - m_log.WarnFormat("[FRIENDS]: Error parsing friend ID {0}", friend.Friend); + m_log.WarnFormat("[FRIENDS]: Error parsing friend ID {0}", friendStringId); + } + } + + // We do this regrouping so that we can efficiently send a single request rather than one for each + // friend in what may be a very large friends list. + PresenceInfo[] friendSessions = PresenceService.GetAgents(remoteFriendStringIds.ToArray()); + + foreach (PresenceInfo friendSession in friendSessions) + { + // let's guard against sessions-gone-bad + if (friendSession.RegionID != UUID.Zero) + { + GridRegion region = GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, friendSession.RegionID); + //m_log.DebugFormat("[FRIENDS]: Remote Notify to region {0}", region.RegionName); + m_FriendsSimConnector.StatusNotify(region, userID, friendSession.UserID, online); } } } -- cgit v1.1 From 1937e5f1ec73dcfb9663ad4fe4b59f33a2210d64 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Sat, 20 Oct 2012 02:13:00 +0100 Subject: Relocate temporary debug message for sending group IMs to online members only so that we can add ms it takes to send. This is chiefly to assess how long it may still take to send messages to such filtered groups. --- .../Avatar/XmlRpcGroups/GroupsMessagingModule.cs | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsMessagingModule.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsMessagingModule.cs index 55bb7dc..1528330 100644 --- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsMessagingModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsMessagingModule.cs @@ -241,6 +241,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups public void SendMessageToGroup(GridInstantMessage im, UUID groupID) { List groupMembers = m_groupData.GetGroupMembers(new UUID(im.fromAgentID), groupID); + int groupMembersCount = groupMembers.Count; if (m_messageOnlineAgentsOnly) { @@ -259,13 +260,12 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups HashSet onlineAgentsUuidSet = new HashSet(); Array.ForEach(onlineAgents, pi => onlineAgentsUuidSet.Add(pi.UserID)); - int allMembersCount = groupMembers.Count; groupMembers = groupMembers.Where(gmd => onlineAgentsUuidSet.Contains(gmd.AgentID.ToString())).ToList(); // if (m_debugEnabled) - m_log.DebugFormat( - "[GROUPS-MESSAGING]: SendMessageToGroup called for group {0} with {1} visible members, {2} online", - groupID, allMembersCount, groupMembers.Count()); +// m_log.DebugFormat( +// "[GROUPS-MESSAGING]: SendMessageToGroup called for group {0} with {1} visible members, {2} online", +// groupID, groupMembersCount, groupMembers.Count()); } else { @@ -275,6 +275,8 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups groupID, groupMembers.Count); } + int requestStartTick = Environment.TickCount; + foreach (GroupMembersData member in groupMembers) { if (m_groupData.hasAgentDroppedGroupChatSession(member.AgentID, groupID)) @@ -316,6 +318,12 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups ProcessMessageFromGroupSession(msg); } } + + // Temporary for assessing how long it still takes to send messages to large online groups. + if (m_messageOnlineAgentsOnly) + m_log.DebugFormat( + "[GROUPS-MESSAGING]: SendMessageToGroup for group {0} with {1} visible members, {2} online took {3}ms", + groupID, groupMembersCount, groupMembers.Count(), Environment.TickCount - requestStartTick); } #region SimGridEventHandlers -- cgit v1.1 From d55f72f3df9dad8cd9c96ec7abc2e71de486fe56 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Sat, 20 Oct 2012 02:35:39 +0100 Subject: minor: Rename assetCache constructor param in UUIDGatherer to assetService which is what it is. --- OpenSim/Region/Framework/Scenes/UuidGatherer.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Framework/Scenes/UuidGatherer.cs b/OpenSim/Region/Framework/Scenes/UuidGatherer.cs index 28cd09f..e238d01 100644 --- a/OpenSim/Region/Framework/Scenes/UuidGatherer.cs +++ b/OpenSim/Region/Framework/Scenes/UuidGatherer.cs @@ -66,9 +66,9 @@ namespace OpenSim.Region.Framework.Scenes // /// // private bool m_waitingForObjectAsset; - public UuidGatherer(IAssetService assetCache) + public UuidGatherer(IAssetService assetService) { - m_assetService = assetCache; + m_assetService = assetService; } /// -- cgit v1.1 From d2b19f00dafe2c7c89c07b6a713fdd359cf9dcab Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Sat, 20 Oct 2012 02:49:16 +0100 Subject: Fix minor issues from commit 28483150 Fix spelling of collide, change to more self-documenting property BadMeshAssetCollideBits, add method doc, change to private to reduce code analysis complexity --- OpenSim/Region/Physics/OdePlugin/ODEPrim.cs | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs b/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs index 5a1fdf9..d11dff1 100644 --- a/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs +++ b/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs @@ -67,6 +67,17 @@ namespace OpenSim.Region.Physics.OdePlugin private int m_expectedCollisionContacts = 0; /// + /// Gets collide bits so that we can still perform land collisions if a mesh fails to load. + /// + /// + /// The bad asset collide bits. + /// + private int BadMeshAssetCollideBits + { + get { return m_isphysical ? (int)CollisionCategories.Land : 0; } + } + + /// /// Is this prim subject to physics? Even if not, it's still solid for collision purposes. /// public override bool IsPhysical @@ -344,11 +355,10 @@ namespace OpenSim.Region.Physics.OdePlugin if (m_assetFailed) { d.GeomSetCategoryBits(prim_geom, 0); - d.GeomSetCollideBits(prim_geom, BadAssetColideBits()); + d.GeomSetCollideBits(prim_geom, BadMeshAssetCollideBits); } else { - d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories); d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags); } @@ -418,7 +428,7 @@ namespace OpenSim.Region.Physics.OdePlugin if (m_assetFailed) { d.GeomSetCategoryBits(prim_geom, 0); - d.GeomSetCollideBits(prim_geom, BadAssetColideBits()); + d.GeomSetCollideBits(prim_geom, BadMeshAssetCollideBits); } else { @@ -851,11 +861,6 @@ namespace OpenSim.Region.Physics.OdePlugin private static Dictionary m_MeshToTriMeshMap = new Dictionary(); - public int BadAssetColideBits() - { - return (m_isphysical ? (int)CollisionCategories.Land : 0); - } - private void setMesh(OdeScene parent_scene, IMesh mesh) { // m_log.DebugFormat("[ODE PRIM]: Setting mesh on {0} to {1}", Name, mesh); @@ -1137,7 +1142,7 @@ Console.WriteLine("ZProcessTaints for " + Name); if (prm.m_assetFailed) { d.GeomSetCategoryBits(prm.prim_geom, 0); - d.GeomSetCollideBits(prm.prim_geom, prm.BadAssetColideBits()); + d.GeomSetCollideBits(prm.prim_geom, prm.BadMeshAssetCollideBits); } else { @@ -1191,7 +1196,7 @@ Console.WriteLine("ZProcessTaints for " + Name); if (m_assetFailed) { d.GeomSetCategoryBits(prim_geom, 0); - d.GeomSetCollideBits(prim_geom, BadAssetColideBits()); + d.GeomSetCollideBits(prim_geom, BadMeshAssetCollideBits); } else { @@ -1393,7 +1398,7 @@ Console.WriteLine("ZProcessTaints for " + Name); if (m_assetFailed) { d.GeomSetCategoryBits(prim_geom, 0); - d.GeomSetCollideBits(prim_geom, BadAssetColideBits()); + d.GeomSetCollideBits(prim_geom, BadMeshAssetCollideBits); } else { @@ -2137,7 +2142,7 @@ Console.WriteLine(" JointCreateFixed"); } if (m_assetFailed) - d.GeomSetCollideBits(prim_geom, BadAssetColideBits()); + d.GeomSetCollideBits(prim_geom, BadMeshAssetCollideBits); else d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags); -- cgit v1.1 From 5bc07a15f508f4860de4defd328f23c4300b33c0 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Sat, 20 Oct 2012 02:52:38 +0100 Subject: minor: remove unnecessary bit of method doc from OdePrim.BadMeshAssetCollideBits that monodevelop inserted automatically --- OpenSim/Region/Physics/OdePlugin/ODEPrim.cs | 3 --- 1 file changed, 3 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs b/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs index d11dff1..2548648 100644 --- a/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs +++ b/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs @@ -69,9 +69,6 @@ namespace OpenSim.Region.Physics.OdePlugin /// /// Gets collide bits so that we can still perform land collisions if a mesh fails to load. /// - /// - /// The bad asset collide bits. - /// private int BadMeshAssetCollideBits { get { return m_isphysical ? (int)CollisionCategories.Land : 0; } -- cgit v1.1 From 2aac113ac14f22509343ae82eb2eb4c3d7ad85b1 Mon Sep 17 00:00:00 2001 From: BlueWall Date: Sat, 20 Oct 2012 04:28:58 -0400 Subject: Add CLICK_ACTION_ZOOM Add support for V2/3 CLICK_ACTION_ZOOM to llSetClickAction --- OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs | 1 + 1 file changed, 1 insertion(+) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs index 60a7e14..62bd6b8 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs @@ -612,6 +612,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase public const int CLICK_ACTION_OPEN = 4; public const int CLICK_ACTION_PLAY = 5; public const int CLICK_ACTION_OPEN_MEDIA = 6; + public const int CLICK_ACTION_ZOOM = 7; // constants for the llDetectedTouch* functions public const int TOUCH_INVALID_FACE = -1; -- cgit v1.1 From d7fa4cacb3227cb432a13d4f27076e408e8c114f Mon Sep 17 00:00:00 2001 From: PixelTomsen Date: Fri, 19 Oct 2012 21:02:54 +0200 Subject: Fix: invinite loading for Viewer3 : parcelinfo request of traffic-value (implementation of dwell-value in LandData + eventhandler, return always 0); source-formatting of LandData Signed-off-by: BlueWall --- .../Region/CoreModules/World/Land/LandManagementModule.cs | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs index 8b7406d..95edf62 100644 --- a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs +++ b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs @@ -207,6 +207,7 @@ namespace OpenSim.Region.CoreModules.World.Land client.OnParcelInfoRequest += ClientOnParcelInfoRequest; client.OnParcelDeedToGroup += ClientOnParcelDeedToGroup; client.OnPreAgentUpdate += ClientOnPreAgentUpdate; + client.OnParcelDwellRequest += ClientOnParcelDwellRequest; EntityBase presenceEntity; if (m_scene.Entities.TryGetValue(client.AgentId, out presenceEntity) && presenceEntity is ScenePresence) @@ -798,6 +799,17 @@ namespace OpenSim.Region.CoreModules.World.Land } } + private void ClientOnParcelDwellRequest(int localID, IClientAPI client) + { + ILandObject parcel = null; + lock (m_landList) + { + if (!m_landList.TryGetValue(localID, out parcel)) + return; + } + client.SendParcelDwellReply(localID, parcel.LandData.GlobalID, parcel.LandData.Dwell); + } + #endregion #region Parcel Modification -- cgit v1.1 From 20eac8d6d07257031f529718dfb9a5863e977653 Mon Sep 17 00:00:00 2001 From: PixelTomsen Date: Sun, 21 Oct 2012 14:59:22 +0200 Subject: SQLite DB: some values of land data will be not saved / loaded http://opensimulator.org/mantis/view.php?id=6370 Signed-off-by: BlueWall --- OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs | 1 + 1 file changed, 1 insertion(+) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs index 95edf62..1f8e823 100644 --- a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs +++ b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs @@ -962,6 +962,7 @@ namespace OpenSim.Region.CoreModules.World.Land ILandObject newLand = startLandObject.Copy(); newLand.LandData.Name = newLand.LandData.Name; newLand.LandData.GlobalID = UUID.Random(); + newLand.LandData.Dwell = 0; newLand.SetLandBitmap(newLand.GetSquareLandBitmap(start_x, start_y, end_x, end_y)); -- cgit v1.1 From efae7c6fc27cc43134c531df9cb9b42e210fad5e Mon Sep 17 00:00:00 2001 From: Melanie Date: Sun, 21 Oct 2012 21:12:34 +0100 Subject: Refactor: Move Dwell reply to a module that can be disabled. The prior, hardcoded approach disabled the use of non-core dwell tracking modules. --- .../Resources/CoreModulePlugin.addin.xml | 1 + .../Region/CoreModules/World/Land/DwellModule.cs | 110 +++++++++++++++++++++ .../CoreModules/World/Land/LandManagementModule.cs | 12 --- 3 files changed, 111 insertions(+), 12 deletions(-) create mode 100644 OpenSim/Region/CoreModules/World/Land/DwellModule.cs (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/Resources/CoreModulePlugin.addin.xml b/OpenSim/Region/CoreModules/Resources/CoreModulePlugin.addin.xml index 424e0ab..6c73d91 100644 --- a/OpenSim/Region/CoreModules/Resources/CoreModulePlugin.addin.xml +++ b/OpenSim/Region/CoreModules/Resources/CoreModulePlugin.addin.xml @@ -15,6 +15,7 @@ + diff --git a/OpenSim/Region/CoreModules/World/Land/DwellModule.cs b/OpenSim/Region/CoreModules/World/Land/DwellModule.cs new file mode 100644 index 0000000..d1f05a7 --- /dev/null +++ b/OpenSim/Region/CoreModules/World/Land/DwellModule.cs @@ -0,0 +1,110 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Diagnostics; +using System.Reflection; +using System.Text; +using log4net; +using Nini.Config; +using OpenMetaverse; +using OpenMetaverse.StructuredData; +using OpenMetaverse.Messages.Linden; +using OpenSim.Framework; +using OpenSim.Framework.Capabilities; +using OpenSim.Framework.Console; +using OpenSim.Framework.Servers; +using OpenSim.Framework.Servers.HttpServer; +using OpenSim.Region.CoreModules.Framework.InterfaceCommander; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; +using OpenSim.Region.Physics.Manager; +using OpenSim.Services.Interfaces; +using Caps = OpenSim.Framework.Capabilities.Caps; +using GridRegion = OpenSim.Services.Interfaces.GridRegion; + +namespace OpenSim.Region.CoreModules.World.Land +{ + public class DwellModule : IDwellModule, INonSharedRegionModule + { + private Scene m_scene; + + public Type ReplaceableInterface + { + get { return typeof(IDwellModule); } + } + + public string Name + { + get { return "DwellModule"; } + } + + public void Initialise(IConfigSource source) + { + } + + public void AddRegion(Scene scene) + { + m_scene = scene; + + m_scene.EventManager.OnNewClient += OnNewClient; + } + + public void RegionLoaded(Scene scene) + { + } + + public void RemoveRegion(Scene scene) + { + } + + public void Close() + { + } + + public void OnNewClient(IClientAPI client) + { + client.OnParcelDwellRequest += ClientOnParcelDwellRequest; + } + + private void ClientOnParcelDwellRequest(int localID, IClientAPI client) + { + ILandObject parcel = m_scene.LandChannel.GetLandObject(localID); + if (parcel == null) + return; + + client.SendParcelDwellReply(localID, parcel.LandData.GlobalID, parcel.LandData.Dwell); + } + + public int GetDwell(UUID parcelID) + { + return 0; + } + } +} diff --git a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs index 1f8e823..e935462 100644 --- a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs +++ b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs @@ -207,7 +207,6 @@ namespace OpenSim.Region.CoreModules.World.Land client.OnParcelInfoRequest += ClientOnParcelInfoRequest; client.OnParcelDeedToGroup += ClientOnParcelDeedToGroup; client.OnPreAgentUpdate += ClientOnPreAgentUpdate; - client.OnParcelDwellRequest += ClientOnParcelDwellRequest; EntityBase presenceEntity; if (m_scene.Entities.TryGetValue(client.AgentId, out presenceEntity) && presenceEntity is ScenePresence) @@ -799,17 +798,6 @@ namespace OpenSim.Region.CoreModules.World.Land } } - private void ClientOnParcelDwellRequest(int localID, IClientAPI client) - { - ILandObject parcel = null; - lock (m_landList) - { - if (!m_landList.TryGetValue(localID, out parcel)) - return; - } - client.SendParcelDwellReply(localID, parcel.LandData.GlobalID, parcel.LandData.Dwell); - } - #endregion #region Parcel Modification -- cgit v1.1 From 4578ff74fec7500902f58fbdee6ce5a6b39601fb Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Tue, 23 Oct 2012 01:50:05 +0100 Subject: Add object count stats for new IncomingPacket and UDPPacketBuffer pools if they are enabled. Add count stats for existing LLUDP pool. This introduces a pull stat type in addition to the push stat type. A pull stat takes a method on construction which knows how to update the stat on request. In this way, special interfaces for pull stat collection are not necessary. --- .../Region/ClientStack/Linden/UDP/LLUDPServer.cs | 14 ++++++++ .../ClientStack/Linden/UDP/OpenSimUDPBase.cs | 17 +++++++++ .../Region/ClientStack/Linden/UDP/PacketPool.cs | 40 ++++++++++++++++++---- .../Region/Framework/Scenes/SimStatsReporter.cs | 6 ++-- 4 files changed, 69 insertions(+), 8 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs index 419de66..bcfd392 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs @@ -278,7 +278,21 @@ namespace OpenSim.Region.ClientStack.LindenUDP ThrottleRates = new ThrottleRates(configSource); if (UsePools) + { m_incomingPacketPool = new Pool(() => new IncomingPacket(), 500); + + StatsManager.RegisterStat( + new Stat( + "IncomingPacketPoolCount", + "Objects within incoming packet pool", + "The number of objects currently stored within the incoming packet pool", + "", + "clientstack", + "packetpool", + StatType.Pull, + stat => stat.Value = m_incomingPacketPool.Count, + StatVerbosity.Debug)); + } } public void Start() diff --git a/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs b/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs index 6e6b3ef..18abfd6 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs @@ -31,6 +31,7 @@ using System.Net.Sockets; using System.Threading; using log4net; using OpenSim.Framework; +using OpenSim.Framework.Monitoring; namespace OpenMetaverse { @@ -107,9 +108,25 @@ namespace OpenMetaverse public void StartInbound(int recvBufferSize, bool asyncPacketHandling) { if (UsePools) + { m_pool = new Pool(() => new UDPPacketBuffer(), 500); + + StatsManager.RegisterStat( + new Stat( + "UDPPacketBufferPoolCount", + "Objects within the UDPPacketBuffer pool", + "The number of objects currently stored within the UDPPacketBuffer pool", + "", + "clientstack", + "packetpool", + StatType.Pull, + stat => stat.Value = m_pool.Count, + StatVerbosity.Debug)); + } else + { m_pool = null; + } m_asyncPacketHandling = asyncPacketHandling; diff --git a/OpenSim/Region/ClientStack/Linden/UDP/PacketPool.cs b/OpenSim/Region/ClientStack/Linden/UDP/PacketPool.cs index 2a3d14f..9f22fb4 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/PacketPool.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/PacketPool.cs @@ -47,18 +47,22 @@ namespace OpenSim.Region.ClientStack.LindenUDP private PercentageStat m_packetsReusedStat = new PercentageStat( "PacketsReused", "Packets reused", + "Number of packets reused out of all requests to the packet pool", "clientstack", "packetpool", - StatVerbosity.Debug, - "Number of packets reused out of all requests to the packet pool"); + StatType.Push, + null, + StatVerbosity.Debug); private PercentageStat m_blocksReusedStat = new PercentageStat( - "BlocksReused", - "Blocks reused", + "PacketDataBlocksReused", + "Packet data blocks reused", + "Number of data blocks reused out of all requests to the packet pool", "clientstack", "packetpool", - StatVerbosity.Debug, - "Number of data blocks reused out of all requests to the packet pool"); + StatType.Push, + null, + StatVerbosity.Debug); /// /// Pool of packets available for reuse. @@ -88,6 +92,30 @@ namespace OpenSim.Region.ClientStack.LindenUDP { StatsManager.RegisterStat(m_packetsReusedStat); StatsManager.RegisterStat(m_blocksReusedStat); + + StatsManager.RegisterStat( + new Stat( + "PacketsPoolCount", + "Objects within the packet pool", + "The number of objects currently stored within the packet pool", + "", + "clientstack", + "packetpool", + StatType.Pull, + stat => { lock (pool) { stat.Value = pool.Count; } }, + StatVerbosity.Debug)); + + StatsManager.RegisterStat( + new Stat( + "PacketDataBlocksPoolCount", + "Objects within the packet data block pool", + "The number of objects currently stored within the packet data block pool", + "", + "clientstack", + "packetpool", + StatType.Pull, + stat => { lock (DataBlocks) { stat.Value = DataBlocks.Count; } }, + StatVerbosity.Debug)); } /// diff --git a/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs b/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs index 2addb5b..b9d615e 100644 --- a/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs +++ b/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs @@ -245,11 +245,13 @@ namespace OpenSim.Region.Framework.Scenes = new Stat( "SlowFrames", "Slow Frames", + "Number of frames where frame time has been significantly longer than the desired frame time.", " frames", "scene", m_scene.Name, - StatVerbosity.Info, - "Number of frames where frame time has been significantly longer than the desired frame time."); + StatType.Push, + null, + StatVerbosity.Info); StatsManager.RegisterStat(SlowFramesStat); } -- cgit v1.1 From 319ebaca06db3d4a38beff74725d321b7c836157 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Tue, 23 Oct 2012 02:44:15 +0100 Subject: Make it possible to turn the base UDP object packet pools on and off whilst running via the "debug lludp pool " console command. For debug purposes. This does not currently apply to the higher LLUDP packetpool. --- .../Region/ClientStack/Linden/UDP/LLUDPServer.cs | 103 +++++++++++++++++---- .../ClientStack/Linden/UDP/OpenSimUDPBase.cs | 66 ++++++++----- 2 files changed, 131 insertions(+), 38 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs index bcfd392..14cc863 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs @@ -170,6 +170,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP private Pool m_incomingPacketPool; + private Stat m_incomingPacketPoolStat; + private int m_defaultRTO = 0; private int m_maxRTO = 0; private int m_ackTimeout = 0; @@ -214,6 +216,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP m_circuitManager = circuitManager; int sceneThrottleBps = 0; + bool usePools = false; IConfig config = configSource.Configs["ClientStack.LindenUDP"]; if (config != null) @@ -246,7 +249,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP { PacketPool.Instance.RecyclePackets = packetConfig.GetBoolean("RecyclePackets", true); PacketPool.Instance.RecycleDataBlocks = packetConfig.GetBoolean("RecycleDataBlocks", true); - UsePools = packetConfig.GetBoolean("RecycleBaseUDPPackets", false); + usePools = packetConfig.GetBoolean("RecycleBaseUDPPackets", usePools); } #region BinaryStats @@ -277,22 +280,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP m_throttle = new TokenBucket(null, sceneThrottleBps); ThrottleRates = new ThrottleRates(configSource); - if (UsePools) - { - m_incomingPacketPool = new Pool(() => new IncomingPacket(), 500); - - StatsManager.RegisterStat( - new Stat( - "IncomingPacketPoolCount", - "Objects within incoming packet pool", - "The number of objects currently stored within the incoming packet pool", - "", - "clientstack", - "packetpool", - StatType.Pull, - stat => stat.Value = m_incomingPacketPool.Count, - StatVerbosity.Debug)); - } + if (usePools) + EnablePools(); } public void Start() @@ -345,6 +334,50 @@ namespace OpenSim.Region.ClientStack.LindenUDP base.StopInbound(); } + protected override bool EnablePools() + { + if (!UsePools) + { + base.EnablePools(); + + m_incomingPacketPool = new Pool(() => new IncomingPacket(), 500); + + m_incomingPacketPoolStat + = new Stat( + "IncomingPacketPoolCount", + "Objects within incoming packet pool", + "The number of objects currently stored within the incoming packet pool", + "", + "clientstack", + "packetpool", + StatType.Pull, + stat => stat.Value = m_incomingPacketPool.Count, + StatVerbosity.Debug); + + StatsManager.RegisterStat(m_incomingPacketPoolStat); + + return true; + } + + return false; + } + + protected override bool DisablePools() + { + if (UsePools) + { + base.DisablePools(); + + StatsManager.DeregisterStat(m_incomingPacketPoolStat); + + // We won't null out the pool to avoid a race condition with code that may be in the middle of using it. + + return true; + } + + return false; + } + /// /// If the outgoing UDP thread times out, then return client that was being processed to help with debugging. /// @@ -411,6 +444,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP MainConsole.Instance.Commands.AddCommand( "Debug", false, + "debug lludp pool", + "debug lludp pool ", + "Turn object pooling within the lludp component on or off.", + HandlePoolCommand); + + MainConsole.Instance.Commands.AddCommand( + "Debug", + false, "debug lludp status", "debug lludp status", "Return status of LLUDP packet processing.", @@ -451,6 +492,32 @@ namespace OpenSim.Region.ClientStack.LindenUDP StopOutbound(); } + private void HandlePoolCommand(string module, string[] args) + { + if (args.Length != 4) + { + MainConsole.Instance.Output("Usage: debug lludp pool "); + return; + } + + string enabled = args[3]; + + if (enabled == "on") + { + if (EnablePools()) + MainConsole.Instance.OutputFormat("Packet pools enabled on {0}", m_scene.Name); + } + else if (enabled == "off") + { + if (DisablePools()) + MainConsole.Instance.OutputFormat("Packet pools disabled on {0}", m_scene.Name); + } + else + { + MainConsole.Instance.Output("Usage: debug lludp pool "); + } + } + private void HandleStatusCommand(string module, string[] args) { MainConsole.Instance.OutputFormat( @@ -458,6 +525,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP MainConsole.Instance.OutputFormat( "OUT LLUDP packet processing for {0} is {1}", m_scene.Name, IsRunningOutbound ? "enabled" : "disabled"); + + MainConsole.Instance.OutputFormat("LLUDP pools in {0} are {1}", m_scene.Name, UsePools ? "on" : "off"); } public bool HandlesRegion(Location x) diff --git a/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs b/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs index 18abfd6..85cbb06 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs @@ -77,6 +77,8 @@ namespace OpenMetaverse /// If IsRunningOut = false, then any request to send a packet is simply dropped. public bool IsRunningOutbound { get; private set; } + private Stat m_poolCountStat; + /// /// Default constructor /// @@ -107,27 +109,6 @@ namespace OpenMetaverse /// necessary public void StartInbound(int recvBufferSize, bool asyncPacketHandling) { - if (UsePools) - { - m_pool = new Pool(() => new UDPPacketBuffer(), 500); - - StatsManager.RegisterStat( - new Stat( - "UDPPacketBufferPoolCount", - "Objects within the UDPPacketBuffer pool", - "The number of objects currently stored within the UDPPacketBuffer pool", - "", - "clientstack", - "packetpool", - StatType.Pull, - stat => stat.Value = m_pool.Count, - StatVerbosity.Debug)); - } - else - { - m_pool = null; - } - m_asyncPacketHandling = asyncPacketHandling; if (!IsRunningInbound) @@ -197,6 +178,49 @@ namespace OpenMetaverse IsRunningOutbound = false; } + protected virtual bool EnablePools() + { + if (!UsePools) + { + m_pool = new Pool(() => new UDPPacketBuffer(), 500); + + m_poolCountStat + = new Stat( + "UDPPacketBufferPoolCount", + "Objects within the UDPPacketBuffer pool", + "The number of objects currently stored within the UDPPacketBuffer pool", + "", + "clientstack", + "packetpool", + StatType.Pull, + stat => stat.Value = m_pool.Count, + StatVerbosity.Debug); + + StatsManager.RegisterStat(m_poolCountStat); + + UsePools = true; + + return true; + } + + return false; + } + + protected virtual bool DisablePools() + { + if (UsePools) + { + UsePools = false; + StatsManager.DeregisterStat(m_poolCountStat); + + // We won't null out the pool to avoid a race condition with code that may be in the middle of using it. + + return true; + } + + return false; + } + private void AsyncBeginReceive() { UDPPacketBuffer buf; -- cgit v1.1 From a61f20ac74836049cbd24397670c2dcd75fb22da Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Sun, 21 Oct 2012 16:12:06 -0700 Subject: BulletSim: Create LinkSet abstract class and sparate constraint based linksets into own subclass. Will eventually add manual movement linkset subclass. --- OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs | 355 ++---------------- .../Physics/BulletSPlugin/BSLinksetConstraints.cs | 396 +++++++++++++++++++++ .../Region/Physics/BulletSPlugin/BSPhysObject.cs | 2 +- 3 files changed, 434 insertions(+), 319 deletions(-) create mode 100755 OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs index 43b1262..2e6b104 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs @@ -32,10 +32,27 @@ using OMV = OpenMetaverse; namespace OpenSim.Region.Physics.BulletSPlugin { -public class BSLinkset +public abstract class BSLinkset { // private static string LogHeader = "[BULLETSIM LINKSET]"; + // Create the correct type of linkset for this child + public static BSLinkset Factory(BSScene physScene, BSPhysObject parent) + { + BSLinkset ret = null; + /* + if (parent.IsPhysical) + ret = new BSLinksetConstraints(physScene, parent); + else + ret = new BSLinksetManual(physScene, parent); + */ + + // at the moment, there is only one + ret = new BSLinksetConstraints(physScene, parent); + + return ret; + } + public BSPhysObject LinksetRoot { get; protected set; } public BSScene PhysicsScene { get; private set; } @@ -52,16 +69,16 @@ public class BSLinkset // the physical 'taint' children separately. // After taint processing and before the simulation step, these // two lists must be the same. - private HashSet m_children; - private HashSet m_taintChildren; + protected HashSet m_children; + protected HashSet m_taintChildren; // We lock the diddling of linkset classes to prevent any badness. // This locks the modification of the instances of this class. Changes // to the physical representation is done via the tainting mechenism. - private object m_linksetActivityLock = new Object(); + protected object m_linksetActivityLock = new Object(); // We keep the prim's mass in the linkset structure since it could be dependent on other prims - private float m_mass; + protected float m_mass; public float LinksetMass { get @@ -81,7 +98,7 @@ public class BSLinkset get { return ComputeLinksetGeometricCenter(); } } - public BSLinkset(BSScene scene, BSPhysObject parent) + protected void Initialize(BSScene scene, BSPhysObject parent) { // A simple linkset of one (no children) LinksetID = m_nextLinksetID++; @@ -128,7 +145,7 @@ public class BSLinkset } // The child is down to a linkset of just itself - return new BSLinkset(PhysicsScene, child); + return BSLinkset.Factory(PhysicsScene, child); } // Return 'true' if the passed object is the root object of this linkset @@ -163,24 +180,7 @@ public class BSLinkset // When physical properties are changed the linkset needs to recalculate // its internal properties. // May be called at runtime or taint-time (just pass the appropriate flag). - public void Refresh(BSPhysObject requestor, bool inTaintTime) - { - // If there are no children, not physical or not root, I am not the one that recomputes the constraints - // (For the moment, static linksets do create constraints so remove the test for physical.) - if (!HasAnyChildren || /*!requestor.IsPhysical ||*/ !IsRoot(requestor)) - return; - - BSScene.TaintCallback refreshOperation = delegate() - { - RecomputeLinksetConstraintVariables(); - DetailLog("{0},BSLinkset.Refresh,complete,rBody={1}", - LinksetRoot.LocalID, LinksetRoot.BSBody.ptr.ToString("X")); - }; - if (inTaintTime) - refreshOperation(); - else - PhysicsScene.TaintedObject("BSLinkSet.Refresh", refreshOperation); - } + public abstract void Refresh(BSPhysObject requestor, bool inTaintTime); // The object is going dynamic (physical). Do any setup necessary // for a dynamic linkset. @@ -188,102 +188,36 @@ public class BSLinkset // has not yet been fully constructed. // Return 'true' if any properties updated on the passed object. // Called at taint-time! - public bool MakeDynamic(BSPhysObject child) - { - // What is done for each object in BSPrim is what we want. - return false; - } + public abstract bool MakeDynamic(BSPhysObject child); // The object is going static (non-physical). Do any setup necessary // for a static linkset. // Return 'true' if any properties updated on the passed object. // Called at taint-time! - public bool MakeStatic(BSPhysObject child) - { - // What is done for each object in BSPrim is what we want. - return false; - } + public abstract bool MakeStatic(BSPhysObject child); // If the software is handling the movement of all the objects in a linkset // (like if one doesn't use constraints for static linksets), this is called // when an update for the root of the linkset is received. // Called at taint-time!! - public void UpdateProperties(BSPhysObject physObject) - { - // The root local properties have been updated. Apply to the children if appropriate. - if (IsRoot(physObject) && HasAnyChildren) - { - if (!physObject.IsPhysical) - { - // TODO: implement software linkset update for static object linksets - } - } - } + public abstract void UpdateProperties(BSPhysObject physObject); // Routine used when rebuilding the body of the root of the linkset // Destroy all the constraints have have been made to root. // This is called when the root body is changing. // Returns 'true' of something eas actually removed and would need restoring // Called at taint-time!! - public bool RemoveBodyDependencies(BSPrim child) - { - bool ret = false; - - lock (m_linksetActivityLock) - { - if (IsRoot(child)) - { - // If the one with the dependency is root, must undo all children - DetailLog("{0},BSLinkset.RemoveBodyDependencies,removeChildrenForRoot,rID={1},rBody={2}", - child.LocalID, LinksetRoot.LocalID, LinksetRoot.BSBody.ptr.ToString("X")); - - ret = PhysicallyUnlinkAllChildrenFromRoot(LinksetRoot); - } - else - { - DetailLog("{0},BSLinkset.RemoveBodyDependencies,removeSingleChild,rID={1},rBody={2},cID={3},cBody={4}", - child.LocalID, - LinksetRoot.LocalID, LinksetRoot.BSBody.ptr.ToString("X"), - child.LocalID, child.BSBody.ptr.ToString("X")); - // ret = PhysicallyUnlinkAChildFromRoot(LinksetRoot, child); - // Despite the function name, this removes any link to the specified object. - ret = PhysicallyUnlinkAllChildrenFromRoot(child); - } - } - return ret; - } + public abstract bool RemoveBodyDependencies(BSPrim child); // Companion to RemoveBodyDependencies(). If RemoveBodyDependencies() returns 'true', // this routine will restore the removed constraints. // Called at taint-time!! - public void RestoreBodyDependencies(BSPrim child) - { - lock (m_linksetActivityLock) - { - if (IsRoot(child)) - { - DetailLog("{0},BSLinkset.RestoreBodyDependencies,restoreChildrenForRoot,rID={1},numChild={2}", - child.LocalID, LinksetRoot.LocalID, m_taintChildren.Count); - foreach (BSPhysObject bpo in m_taintChildren) - { - PhysicallyLinkAChildToRoot(LinksetRoot, bpo); - } - } - else - { - DetailLog("{0},BSLinkset.RestoreBodyDependencies,restoreSingleChild,rID={1},rBody={2},cID={3},cBody={4}", - LinksetRoot.LocalID, - LinksetRoot.LocalID, LinksetRoot.BSBody.ptr.ToString("X"), - child.LocalID, child.BSBody.ptr.ToString("X")); - PhysicallyLinkAChildToRoot(LinksetRoot, child); - } - } - } + public abstract void RestoreBodyDependencies(BSPrim child); // ================================================================ // Below this point is internal magic - private float ComputeLinksetMass() + protected virtual float ComputeLinksetMass() { float mass; lock (m_linksetActivityLock) @@ -297,7 +231,7 @@ public class BSLinkset return mass; } - private OMV.Vector3 ComputeLinksetCenterOfMass() + protected virtual OMV.Vector3 ComputeLinksetCenterOfMass() { OMV.Vector3 com; lock (m_linksetActivityLock) @@ -317,7 +251,7 @@ public class BSLinkset return com; } - private OMV.Vector3 ComputeLinksetGeometricCenter() + protected virtual OMV.Vector3 ComputeLinksetGeometricCenter() { OMV.Vector3 com; lock (m_linksetActivityLock) @@ -336,236 +270,21 @@ public class BSLinkset // I am the root of a linkset and a new child is being added // Called while LinkActivity is locked. - private void AddChildToLinkset(BSPhysObject child) - { - if (!HasChild(child)) - { - m_children.Add(child); - - BSPhysObject rootx = LinksetRoot; // capture the root as of now - BSPhysObject childx = child; - - DetailLog("{0},AddChildToLinkset,call,child={1}", LinksetRoot.LocalID, child.LocalID); - - PhysicsScene.TaintedObject("AddChildToLinkset", delegate() - { - DetailLog("{0},AddChildToLinkset,taint,rID={1},rBody={2},cID={3},cBody={4}", - rootx.LocalID, - rootx.LocalID, rootx.BSBody.ptr.ToString("X"), - childx.LocalID, childx.BSBody.ptr.ToString("X")); - // Since this is taint-time, the body and shape could have changed for the child - rootx.ForcePosition = rootx.Position; // DEBUG - childx.ForcePosition = childx.Position; // DEBUG - PhysicallyLinkAChildToRoot(rootx, childx); - m_taintChildren.Add(child); - }); - } - return; - } + protected abstract void AddChildToLinkset(BSPhysObject child); // Forcefully removing a child from a linkset. // This is not being called by the child so we have to make sure the child doesn't think // it's still connected to the linkset. // Normal OpenSimulator operation will never do this because other SceneObjectPart information // also has to be updated (like pointer to prim's parent). - private void RemoveChildFromOtherLinkset(BSPhysObject pchild) - { - pchild.Linkset = new BSLinkset(PhysicsScene, pchild); - RemoveChildFromLinkset(pchild); - } + protected abstract void RemoveChildFromOtherLinkset(BSPhysObject pchild); // I am the root of a linkset and one of my children is being removed. // Safe to call even if the child is not really in my linkset. - private void RemoveChildFromLinkset(BSPhysObject child) - { - if (m_children.Remove(child)) - { - BSPhysObject rootx = LinksetRoot; // capture the root and body as of now - BSPhysObject childx = child; - - DetailLog("{0},RemoveChildFromLinkset,call,rID={1},rBody={2},cID={3},cBody={4}", - childx.LocalID, - rootx.LocalID, rootx.BSBody.ptr.ToString("X"), - childx.LocalID, childx.BSBody.ptr.ToString("X")); - - PhysicsScene.TaintedObject("RemoveChildFromLinkset", delegate() - { - m_taintChildren.Remove(child); - PhysicallyUnlinkAChildFromRoot(rootx, childx); - RecomputeLinksetConstraintVariables(); - }); - - } - else - { - // This will happen if we remove the root of the linkset first. Non-fatal occurance. - // PhysicsScene.Logger.ErrorFormat("{0}: Asked to remove child from linkset that was not in linkset", LogHeader); - } - return; - } - - // Create a constraint between me (root of linkset) and the passed prim (the child). - // Called at taint time! - private void PhysicallyLinkAChildToRoot(BSPhysObject rootPrim, BSPhysObject childPrim) - { - // Zero motion for children so they don't interpolate - childPrim.ZeroMotion(); - - // Relative position normalized to the root prim - // Essentually a vector pointing from center of rootPrim to center of childPrim - OMV.Vector3 childRelativePosition = childPrim.Position - rootPrim.Position; - - // real world coordinate of midpoint between the two objects - OMV.Vector3 midPoint = rootPrim.Position + (childRelativePosition / 2); - - DetailLog("{0},BSLinkset.PhysicallyLinkAChildToRoot,taint,root={1},rBody={2},child={3},cBody={4},rLoc={5},cLoc={6},midLoc={7}", - rootPrim.LocalID, - rootPrim.LocalID, rootPrim.BSBody.ptr.ToString("X"), - childPrim.LocalID, childPrim.BSBody.ptr.ToString("X"), - rootPrim.Position, childPrim.Position, midPoint); - - // create a constraint that allows no freedom of movement between the two objects - // http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818 - - BS6DofConstraint constrain = new BS6DofConstraint( - PhysicsScene.World, rootPrim.BSBody, childPrim.BSBody, midPoint, true, true ); - - /* NOTE: below is an attempt to build constraint with full frame computation, etc. - * Using the midpoint is easier since it lets the Bullet code manipulate the transforms - * of the objects. - * Code left as a warning to future programmers. - // ================================================================================== - // relative position normalized to the root prim - OMV.Quaternion invThisOrientation = OMV.Quaternion.Inverse(rootPrim.Orientation); - OMV.Vector3 childRelativePosition = (childPrim.Position - rootPrim.Position) * invThisOrientation; - - // relative rotation of the child to the parent - OMV.Quaternion childRelativeRotation = invThisOrientation * childPrim.Orientation; - OMV.Quaternion inverseChildRelativeRotation = OMV.Quaternion.Inverse(childRelativeRotation); - - // create a constraint that allows no freedom of movement between the two objects - // http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818 - DetailLog("{0},BSLinkset.PhysicallyLinkAChildToRoot,taint,root={1},child={2}", rootPrim.LocalID, rootPrim.LocalID, childPrim.LocalID); - BS6DofConstraint constrain = new BS6DofConstraint( - PhysicsScene.World, rootPrim.Body, childPrim.Body, - OMV.Vector3.Zero, - OMV.Quaternion.Inverse(rootPrim.Orientation), - OMV.Vector3.Zero, - OMV.Quaternion.Inverse(childPrim.Orientation), - // A point half way between the parent and child - // childRelativePosition/2, - // childRelativeRotation, - // childRelativePosition/2, - // inverseChildRelativeRotation, - true, - true - ); - // ================================================================================== - */ - - PhysicsScene.Constraints.AddConstraint(constrain); - - // zero linear and angular limits makes the objects unable to move in relation to each other - constrain.SetLinearLimits(OMV.Vector3.Zero, OMV.Vector3.Zero); - constrain.SetAngularLimits(OMV.Vector3.Zero, OMV.Vector3.Zero); - - // tweek the constraint to increase stability - constrain.UseFrameOffset(PhysicsScene.BoolNumeric(PhysicsScene.Params.linkConstraintUseFrameOffset)); - constrain.TranslationalLimitMotor(PhysicsScene.BoolNumeric(PhysicsScene.Params.linkConstraintEnableTransMotor), - PhysicsScene.Params.linkConstraintTransMotorMaxVel, - PhysicsScene.Params.linkConstraintTransMotorMaxForce); - constrain.SetCFMAndERP(PhysicsScene.Params.linkConstraintCFM, PhysicsScene.Params.linkConstraintERP); - if (PhysicsScene.Params.linkConstraintSolverIterations != 0f) - { - constrain.SetSolverIterations(PhysicsScene.Params.linkConstraintSolverIterations); - } - } - - // Remove linkage between myself and a particular child - // The root and child bodies are passed in because we need to remove the constraint between - // the bodies that were at unlink time. - // Called at taint time! - private bool PhysicallyUnlinkAChildFromRoot(BSPhysObject rootPrim, BSPhysObject childPrim) - { - bool ret = false; - DetailLog("{0},BSLinkset.PhysicallyUnlinkAChildFromRoot,taint,root={1},rBody={2},child={3},cBody={4}", - rootPrim.LocalID, - rootPrim.LocalID, rootPrim.BSBody.ptr.ToString("X"), - childPrim.LocalID, childPrim.BSBody.ptr.ToString("X")); - - // Find the constraint for this link and get rid of it from the overall collection and from my list - if (PhysicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.BSBody, childPrim.BSBody)) - { - // Make the child refresh its location - BulletSimAPI.PushUpdate2(childPrim.BSBody.ptr); - ret = true; - } - - return ret; - } - - // Remove linkage between myself and any possible children I might have. - // Called at taint time! - private bool PhysicallyUnlinkAllChildrenFromRoot(BSPhysObject rootPrim) - { - DetailLog("{0},BSLinkset.PhysicallyUnlinkAllChildren,taint", rootPrim.LocalID); - bool ret = false; - - if (PhysicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.BSBody)) - { - ret = true; - } - return ret; - } - - // Call each of the constraints that make up this linkset and recompute the - // various transforms and variables. Used when objects are added or removed - // from a linkset to make sure the constraints know about the new mass and - // geometry. - // Must only be called at taint time!! - private void RecomputeLinksetConstraintVariables() - { - float linksetMass = LinksetMass; - foreach (BSPhysObject child in m_taintChildren) - { - BSConstraint constrain; - if (PhysicsScene.Constraints.TryGetConstraint(LinksetRoot.BSBody, child.BSBody, out constrain)) - { - // DetailLog("{0},BSLinkset.RecomputeLinksetConstraintVariables,taint,child={1},mass={2},A={3},B={4}", - // LinksetRoot.LocalID, child.LocalID, linksetMass, constrain.Body1.ID, constrain.Body2.ID); - constrain.RecomputeConstraintVariables(linksetMass); - } - else - { - // Non-fatal error that happens when children are being added to the linkset but - // their constraints have not been created yet. - break; - } - } - - // If the whole linkset is not here, doesn't make sense to recompute linkset wide values - if (m_children.Count == m_taintChildren.Count) - { - // If this is a multiple object linkset, set everybody's center of mass to the set's center of mass - OMV.Vector3 centerOfMass = ComputeLinksetCenterOfMass(); - BulletSimAPI.SetCenterOfMassByPosRot2(LinksetRoot.BSBody.ptr, - centerOfMass, OMV.Quaternion.Identity); - DetailLog("{0},BSLinkset.RecomputeLinksetConstraintVariables,setCenterOfMass,COM={1},rBody={2}", - LinksetRoot.LocalID, centerOfMass, LinksetRoot.BSBody.ptr.ToString("X")); - foreach (BSPhysObject child in m_taintChildren) - { - BulletSimAPI.SetCenterOfMassByPosRot2(child.BSBody.ptr, - centerOfMass, OMV.Quaternion.Identity); - } - - // BulletSimAPI.DumpAllInfo2(PhysicsScene.World.ptr); // DEBUG DEBUG DEBUG - } - return; - } - + protected abstract void RemoveChildFromLinkset(BSPhysObject child); // Invoke the detailed logger and output something if it's enabled. - private void DetailLog(string msg, params Object[] args) + protected void DetailLog(string msg, params Object[] args) { if (PhysicsScene.PhysicsLogging.Enabled) PhysicsScene.DetailLog(msg, args); diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs new file mode 100755 index 0000000..ee53d92 --- /dev/null +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs @@ -0,0 +1,396 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyrightD + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +using System; +using System.Collections.Generic; +using System.Text; + +using OMV = OpenMetaverse; + +namespace OpenSim.Region.Physics.BulletSPlugin +{ +public class BSLinksetConstraints : BSLinkset +{ + // private static string LogHeader = "[BULLETSIM LINKSET CONSTRAINTS]"; + + public BSLinksetConstraints(BSScene scene, BSPhysObject parent) + { + base.Initialize(scene, parent); + } + + // When physical properties are changed the linkset needs to recalculate + // its internal properties. + // May be called at runtime or taint-time (just pass the appropriate flag). + public override void Refresh(BSPhysObject requestor, bool inTaintTime) + { + // If there are no children, not physical or not root, I am not the one that recomputes the constraints + // (For the moment, static linksets do create constraints so remove the test for physical.) + if (!HasAnyChildren || /*!requestor.IsPhysical ||*/ !IsRoot(requestor)) + return; + + BSScene.TaintCallback refreshOperation = delegate() + { + RecomputeLinksetConstraintVariables(); + DetailLog("{0},BSLinkset.Refresh,complete,rBody={1}", + LinksetRoot.LocalID, LinksetRoot.BSBody.ptr.ToString("X")); + }; + if (inTaintTime) + refreshOperation(); + else + PhysicsScene.TaintedObject("BSLinkSet.Refresh", refreshOperation); + } + + // The object is going dynamic (physical). Do any setup necessary + // for a dynamic linkset. + // Only the state of the passed object can be modified. The rest of the linkset + // has not yet been fully constructed. + // Return 'true' if any properties updated on the passed object. + // Called at taint-time! + public override bool MakeDynamic(BSPhysObject child) + { + // What is done for each object in BSPrim is what we want. + return false; + } + + // The object is going static (non-physical). Do any setup necessary + // for a static linkset. + // Return 'true' if any properties updated on the passed object. + // Called at taint-time! + public override bool MakeStatic(BSPhysObject child) + { + // What is done for each object in BSPrim is what we want. + return false; + } + + // If the software is handling the movement of all the objects in a linkset + // (like if one doesn't use constraints for static linksets), this is called + // when an update for the root of the linkset is received. + // Called at taint-time!! + public override void UpdateProperties(BSPhysObject physObject) + { + // The root local properties have been updated. Apply to the children if appropriate. + if (IsRoot(physObject) && HasAnyChildren) + { + if (!physObject.IsPhysical) + { + // TODO: implement software linkset update for static object linksets + } + } + } + + // Routine used when rebuilding the body of the root of the linkset + // Destroy all the constraints have have been made to root. + // This is called when the root body is changing. + // Returns 'true' of something eas actually removed and would need restoring + // Called at taint-time!! + public override bool RemoveBodyDependencies(BSPrim child) + { + bool ret = false; + + lock (m_linksetActivityLock) + { + if (IsRoot(child)) + { + // If the one with the dependency is root, must undo all children + DetailLog("{0},BSLinkset.RemoveBodyDependencies,removeChildrenForRoot,rID={1},rBody={2}", + child.LocalID, LinksetRoot.LocalID, LinksetRoot.BSBody.ptr.ToString("X")); + + ret = PhysicallyUnlinkAllChildrenFromRoot(LinksetRoot); + } + else + { + DetailLog("{0},BSLinkset.RemoveBodyDependencies,removeSingleChild,rID={1},rBody={2},cID={3},cBody={4}", + child.LocalID, + LinksetRoot.LocalID, LinksetRoot.BSBody.ptr.ToString("X"), + child.LocalID, child.BSBody.ptr.ToString("X")); + // ret = PhysicallyUnlinkAChildFromRoot(LinksetRoot, child); + // Despite the function name, this removes any link to the specified object. + ret = PhysicallyUnlinkAllChildrenFromRoot(child); + } + } + return ret; + } + + // Companion to RemoveBodyDependencies(). If RemoveBodyDependencies() returns 'true', + // this routine will restore the removed constraints. + // Called at taint-time!! + public override void RestoreBodyDependencies(BSPrim child) + { + lock (m_linksetActivityLock) + { + if (IsRoot(child)) + { + DetailLog("{0},BSLinkset.RestoreBodyDependencies,restoreChildrenForRoot,rID={1},numChild={2}", + child.LocalID, LinksetRoot.LocalID, m_taintChildren.Count); + foreach (BSPhysObject bpo in m_taintChildren) + { + PhysicallyLinkAChildToRoot(LinksetRoot, bpo); + } + } + else + { + DetailLog("{0},BSLinkset.RestoreBodyDependencies,restoreSingleChild,rID={1},rBody={2},cID={3},cBody={4}", + LinksetRoot.LocalID, + LinksetRoot.LocalID, LinksetRoot.BSBody.ptr.ToString("X"), + child.LocalID, child.BSBody.ptr.ToString("X")); + PhysicallyLinkAChildToRoot(LinksetRoot, child); + } + } + } + + // ================================================================ + // Below this point is internal magic + + // I am the root of a linkset and a new child is being added + // Called while LinkActivity is locked. + protected override void AddChildToLinkset(BSPhysObject child) + { + if (!HasChild(child)) + { + m_children.Add(child); + + BSPhysObject rootx = LinksetRoot; // capture the root as of now + BSPhysObject childx = child; + + DetailLog("{0},AddChildToLinkset,call,child={1}", LinksetRoot.LocalID, child.LocalID); + + PhysicsScene.TaintedObject("AddChildToLinkset", delegate() + { + DetailLog("{0},AddChildToLinkset,taint,rID={1},rBody={2},cID={3},cBody={4}", + rootx.LocalID, + rootx.LocalID, rootx.BSBody.ptr.ToString("X"), + childx.LocalID, childx.BSBody.ptr.ToString("X")); + // Since this is taint-time, the body and shape could have changed for the child + rootx.ForcePosition = rootx.Position; // DEBUG + childx.ForcePosition = childx.Position; // DEBUG + PhysicallyLinkAChildToRoot(rootx, childx); + m_taintChildren.Add(child); + }); + } + return; + } + + // Forcefully removing a child from a linkset. + // This is not being called by the child so we have to make sure the child doesn't think + // it's still connected to the linkset. + // Normal OpenSimulator operation will never do this because other SceneObjectPart information + // also has to be updated (like pointer to prim's parent). + protected override void RemoveChildFromOtherLinkset(BSPhysObject pchild) + { + pchild.Linkset = BSLinkset.Factory(PhysicsScene, pchild); + RemoveChildFromLinkset(pchild); + } + + // I am the root of a linkset and one of my children is being removed. + // Safe to call even if the child is not really in my linkset. + protected override void RemoveChildFromLinkset(BSPhysObject child) + { + if (m_children.Remove(child)) + { + BSPhysObject rootx = LinksetRoot; // capture the root and body as of now + BSPhysObject childx = child; + + DetailLog("{0},RemoveChildFromLinkset,call,rID={1},rBody={2},cID={3},cBody={4}", + childx.LocalID, + rootx.LocalID, rootx.BSBody.ptr.ToString("X"), + childx.LocalID, childx.BSBody.ptr.ToString("X")); + + PhysicsScene.TaintedObject("RemoveChildFromLinkset", delegate() + { + m_taintChildren.Remove(child); + PhysicallyUnlinkAChildFromRoot(rootx, childx); + RecomputeLinksetConstraintVariables(); + }); + + } + else + { + // This will happen if we remove the root of the linkset first. Non-fatal occurance. + // PhysicsScene.Logger.ErrorFormat("{0}: Asked to remove child from linkset that was not in linkset", LogHeader); + } + return; + } + + // Create a constraint between me (root of linkset) and the passed prim (the child). + // Called at taint time! + private void PhysicallyLinkAChildToRoot(BSPhysObject rootPrim, BSPhysObject childPrim) + { + // Zero motion for children so they don't interpolate + childPrim.ZeroMotion(); + + // Relative position normalized to the root prim + // Essentually a vector pointing from center of rootPrim to center of childPrim + OMV.Vector3 childRelativePosition = childPrim.Position - rootPrim.Position; + + // real world coordinate of midpoint between the two objects + OMV.Vector3 midPoint = rootPrim.Position + (childRelativePosition / 2); + + DetailLog("{0},BSLinkset.PhysicallyLinkAChildToRoot,taint,root={1},rBody={2},child={3},cBody={4},rLoc={5},cLoc={6},midLoc={7}", + rootPrim.LocalID, + rootPrim.LocalID, rootPrim.BSBody.ptr.ToString("X"), + childPrim.LocalID, childPrim.BSBody.ptr.ToString("X"), + rootPrim.Position, childPrim.Position, midPoint); + + // create a constraint that allows no freedom of movement between the two objects + // http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818 + + BS6DofConstraint constrain = new BS6DofConstraint( + PhysicsScene.World, rootPrim.BSBody, childPrim.BSBody, midPoint, true, true ); + + /* NOTE: below is an attempt to build constraint with full frame computation, etc. + * Using the midpoint is easier since it lets the Bullet code manipulate the transforms + * of the objects. + * Code left as a warning to future programmers. + // ================================================================================== + // relative position normalized to the root prim + OMV.Quaternion invThisOrientation = OMV.Quaternion.Inverse(rootPrim.Orientation); + OMV.Vector3 childRelativePosition = (childPrim.Position - rootPrim.Position) * invThisOrientation; + + // relative rotation of the child to the parent + OMV.Quaternion childRelativeRotation = invThisOrientation * childPrim.Orientation; + OMV.Quaternion inverseChildRelativeRotation = OMV.Quaternion.Inverse(childRelativeRotation); + + // create a constraint that allows no freedom of movement between the two objects + // http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818 + DetailLog("{0},BSLinkset.PhysicallyLinkAChildToRoot,taint,root={1},child={2}", rootPrim.LocalID, rootPrim.LocalID, childPrim.LocalID); + BS6DofConstraint constrain = new BS6DofConstraint( + PhysicsScene.World, rootPrim.Body, childPrim.Body, + OMV.Vector3.Zero, + OMV.Quaternion.Inverse(rootPrim.Orientation), + OMV.Vector3.Zero, + OMV.Quaternion.Inverse(childPrim.Orientation), + // A point half way between the parent and child + // childRelativePosition/2, + // childRelativeRotation, + // childRelativePosition/2, + // inverseChildRelativeRotation, + true, + true + ); + // ================================================================================== + */ + + PhysicsScene.Constraints.AddConstraint(constrain); + + // zero linear and angular limits makes the objects unable to move in relation to each other + constrain.SetLinearLimits(OMV.Vector3.Zero, OMV.Vector3.Zero); + constrain.SetAngularLimits(OMV.Vector3.Zero, OMV.Vector3.Zero); + + // tweek the constraint to increase stability + constrain.UseFrameOffset(PhysicsScene.BoolNumeric(PhysicsScene.Params.linkConstraintUseFrameOffset)); + constrain.TranslationalLimitMotor(PhysicsScene.BoolNumeric(PhysicsScene.Params.linkConstraintEnableTransMotor), + PhysicsScene.Params.linkConstraintTransMotorMaxVel, + PhysicsScene.Params.linkConstraintTransMotorMaxForce); + constrain.SetCFMAndERP(PhysicsScene.Params.linkConstraintCFM, PhysicsScene.Params.linkConstraintERP); + if (PhysicsScene.Params.linkConstraintSolverIterations != 0f) + { + constrain.SetSolverIterations(PhysicsScene.Params.linkConstraintSolverIterations); + } + } + + // Remove linkage between myself and a particular child + // The root and child bodies are passed in because we need to remove the constraint between + // the bodies that were at unlink time. + // Called at taint time! + private bool PhysicallyUnlinkAChildFromRoot(BSPhysObject rootPrim, BSPhysObject childPrim) + { + bool ret = false; + DetailLog("{0},BSLinkset.PhysicallyUnlinkAChildFromRoot,taint,root={1},rBody={2},child={3},cBody={4}", + rootPrim.LocalID, + rootPrim.LocalID, rootPrim.BSBody.ptr.ToString("X"), + childPrim.LocalID, childPrim.BSBody.ptr.ToString("X")); + + // Find the constraint for this link and get rid of it from the overall collection and from my list + if (PhysicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.BSBody, childPrim.BSBody)) + { + // Make the child refresh its location + BulletSimAPI.PushUpdate2(childPrim.BSBody.ptr); + ret = true; + } + + return ret; + } + + // Remove linkage between myself and any possible children I might have. + // Called at taint time! + private bool PhysicallyUnlinkAllChildrenFromRoot(BSPhysObject rootPrim) + { + DetailLog("{0},BSLinkset.PhysicallyUnlinkAllChildren,taint", rootPrim.LocalID); + bool ret = false; + + if (PhysicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.BSBody)) + { + ret = true; + } + return ret; + } + + // Call each of the constraints that make up this linkset and recompute the + // various transforms and variables. Used when objects are added or removed + // from a linkset to make sure the constraints know about the new mass and + // geometry. + // Must only be called at taint time!! + private void RecomputeLinksetConstraintVariables() + { + float linksetMass = LinksetMass; + foreach (BSPhysObject child in m_taintChildren) + { + BSConstraint constrain; + if (PhysicsScene.Constraints.TryGetConstraint(LinksetRoot.BSBody, child.BSBody, out constrain)) + { + // DetailLog("{0},BSLinkset.RecomputeLinksetConstraintVariables,taint,child={1},mass={2},A={3},B={4}", + // LinksetRoot.LocalID, child.LocalID, linksetMass, constrain.Body1.ID, constrain.Body2.ID); + constrain.RecomputeConstraintVariables(linksetMass); + } + else + { + // Non-fatal error that happens when children are being added to the linkset but + // their constraints have not been created yet. + break; + } + } + + // If the whole linkset is not here, doesn't make sense to recompute linkset wide values + if (m_children.Count == m_taintChildren.Count) + { + // If this is a multiple object linkset, set everybody's center of mass to the set's center of mass + OMV.Vector3 centerOfMass = ComputeLinksetCenterOfMass(); + BulletSimAPI.SetCenterOfMassByPosRot2(LinksetRoot.BSBody.ptr, + centerOfMass, OMV.Quaternion.Identity); + DetailLog("{0},BSLinkset.RecomputeLinksetConstraintVariables,setCenterOfMass,COM={1},rBody={2}", + LinksetRoot.LocalID, centerOfMass, LinksetRoot.BSBody.ptr.ToString("X")); + foreach (BSPhysObject child in m_taintChildren) + { + BulletSimAPI.SetCenterOfMassByPosRot2(child.BSBody.ptr, + centerOfMass, OMV.Quaternion.Identity); + } + + // BulletSimAPI.DumpAllInfo2(PhysicsScene.World.ptr); // DEBUG DEBUG DEBUG + } + return; + } +} +} diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs index ead6a08..51b9196 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs @@ -46,7 +46,7 @@ public abstract class BSPhysObject : PhysicsActor PhysObjectName = name; TypeName = typeName; - Linkset = new BSLinkset(PhysicsScene, this); + Linkset = BSLinkset.Factory(PhysicsScene, this); LastAssetBuildFailed = false; CollisionCollection = new CollisionEventUpdate(); -- cgit v1.1 From c245178eeee530e2be90ef9395ee885e0a79b7df Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Sun, 21 Oct 2012 16:13:22 -0700 Subject: BulletSim: encorporate UBit's suggestion to save a copy of mesh raw data. --- OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs index d3ba273..7b808eb 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs @@ -724,8 +724,7 @@ public class BSShapeCollection : IDisposable if (yprim.BaseShape.SculptTexture.ToString() != asset.ID) return; - yprim.BaseShape.SculptData = new byte[asset.Data.Length]; - asset.Data.CopyTo(yprim.BaseShape.SculptData, 0); + yprim.BaseShape.SculptData = asset.Data; // This will cause the prim to see that the filler shape is not the right // one and try again to build the object. yprim.ForceBodyShapeRebuild(false); -- cgit v1.1 From 65c131c4a362bed347a6240184ce40b9ddeaaae1 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Mon, 22 Oct 2012 08:23:21 -0700 Subject: BulletSim: remove trailing spaces to make git happy. --- OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs | 10 +++++----- OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs | 2 +- OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs | 10 +++++----- .../Physics/BulletSPlugin/BSLinksetConstraints.cs | 10 +++++----- OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs | 6 +++--- OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | 10 +++++----- OpenSim/Region/Physics/BulletSPlugin/BSScene.cs | 4 ++-- .../Physics/BulletSPlugin/BSShapeCollection.cs | 20 ++++++++++---------- 8 files changed, 36 insertions(+), 36 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs index 623ac8f..07dd613 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs @@ -165,7 +165,7 @@ public class BSCharacter : BSPhysObject // Do this after the object has been added to the world BulletSimAPI.SetCollisionFilterMask2(BSBody.ptr, - (uint)CollisionFilterGroups.AvatarFilter, + (uint)CollisionFilterGroups.AvatarFilter, (uint)CollisionFilterGroups.AvatarMask); } @@ -269,7 +269,7 @@ public class BSCharacter : BSPhysObject private bool PositionSanityCheck() { bool ret = false; - + // If below the ground, move the avatar up float terrainHeight = PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(_position); if (Position.Z < terrainHeight) @@ -413,7 +413,7 @@ public class BSCharacter : BSPhysObject }); } } - // Go directly to Bullet to get/set the value. + // Go directly to Bullet to get/set the value. public override OMV.Quaternion ForceOrientation { get @@ -478,7 +478,7 @@ public class BSCharacter : BSPhysObject set { _collidingObj = value; } } public override bool FloatOnWater { - set { + set { _floatOnWater = value; PhysicsScene.TaintedObject("BSCharacter.setFloatOnWater", delegate() { @@ -588,7 +588,7 @@ public class BSCharacter : BSPhysObject newScale.X = PhysicsScene.Params.avatarCapsuleRadius; newScale.Y = PhysicsScene.Params.avatarCapsuleRadius; - // From the total height, remote the capsule half spheres that are at each end + // From the total height, remote the capsule half spheres that are at each end newScale.Z = (size.Z * 2f) - Math.Min(newScale.X, newScale.Y); // newScale.Z = (size.Z * 2f); Scale = newScale; diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs b/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs index a20be3a..b58745a 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs @@ -53,7 +53,7 @@ public abstract class BSConstraint : IDisposable { bool success = BulletSimAPI.DestroyConstraint2(m_world.ptr, m_constraint.ptr); m_world.physicsScene.DetailLog("{0},BSConstraint.Dispose,taint,id1={1},body1={2},id2={3},body2={4},success={5}", - BSScene.DetailLogZero, + BSScene.DetailLogZero, m_body1.ID, m_body1.ptr.ToString("X"), m_body2.ID, m_body2.ptr.ToString("X"), success); diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs index 56342b8..f71f3b0 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs @@ -23,7 +23,7 @@ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ + * /* RA: June 14, 2011. Copied from ODEDynamics.cs and converted to * call the BulletSim system. @@ -352,7 +352,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin // m_bankingMix = 1; // m_bankingTimescale = 1; // m_referenceFrame = Quaternion.Identity; - m_flags |= (VehicleFlag.NO_DEFLECTION_UP + m_flags |= (VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.LIMIT_ROLL_ONLY | VehicleFlag.LIMIT_MOTOR_UP); m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT); @@ -382,7 +382,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin // m_bankingTimescale = 1; // m_referenceFrame = Quaternion.Identity; m_flags &= ~(VehicleFlag.HOVER_TERRAIN_ONLY - | VehicleFlag.HOVER_GLOBAL_HEIGHT + | VehicleFlag.HOVER_GLOBAL_HEIGHT | VehicleFlag.LIMIT_ROLL_ONLY | VehicleFlag.HOVER_UP_ONLY); m_flags |= (VehicleFlag.NO_DEFLECTION_UP @@ -458,7 +458,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin // Do any updating needed for a vehicle public void Refresh() { - if (!IsActive) + if (!IsActive) return; // Set the prim's inertia to zero. The vehicle code handles that and this @@ -791,7 +791,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin // Sum velocities m_lastAngularVelocity = m_angularMotorVelocity + vertattr; // + bank + deflection - + if ((m_flags & (VehicleFlag.NO_DEFLECTION_UP)) != 0) { m_lastAngularVelocity.X = 0; diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs index ee53d92..8eeeb73 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs @@ -54,7 +54,7 @@ public class BSLinksetConstraints : BSLinkset BSScene.TaintCallback refreshOperation = delegate() { RecomputeLinksetConstraintVariables(); - DetailLog("{0},BSLinkset.Refresh,complete,rBody={1}", + DetailLog("{0},BSLinkset.Refresh,complete,rBody={1}", LinksetRoot.LocalID, LinksetRoot.BSBody.ptr.ToString("X")); }; if (inTaintTime) @@ -179,7 +179,7 @@ public class BSLinksetConstraints : BSLinkset PhysicsScene.TaintedObject("AddChildToLinkset", delegate() { - DetailLog("{0},AddChildToLinkset,taint,rID={1},rBody={2},cID={3},cBody={4}", + DetailLog("{0},AddChildToLinkset,taint,rID={1},rBody={2},cID={3},cBody={4}", rootx.LocalID, rootx.LocalID, rootx.BSBody.ptr.ToString("X"), childx.LocalID, childx.BSBody.ptr.ToString("X")); @@ -213,7 +213,7 @@ public class BSLinksetConstraints : BSLinkset BSPhysObject rootx = LinksetRoot; // capture the root and body as of now BSPhysObject childx = child; - DetailLog("{0},RemoveChildFromLinkset,call,rID={1},rBody={2},cID={3},cBody={4}", + DetailLog("{0},RemoveChildFromLinkset,call,rID={1},rBody={2},cID={3},cBody={4}", childx.LocalID, rootx.LocalID, rootx.BSBody.ptr.ToString("X"), childx.LocalID, childx.BSBody.ptr.ToString("X")); @@ -378,13 +378,13 @@ public class BSLinksetConstraints : BSLinkset { // If this is a multiple object linkset, set everybody's center of mass to the set's center of mass OMV.Vector3 centerOfMass = ComputeLinksetCenterOfMass(); - BulletSimAPI.SetCenterOfMassByPosRot2(LinksetRoot.BSBody.ptr, + BulletSimAPI.SetCenterOfMassByPosRot2(LinksetRoot.BSBody.ptr, centerOfMass, OMV.Quaternion.Identity); DetailLog("{0},BSLinkset.RecomputeLinksetConstraintVariables,setCenterOfMass,COM={1},rBody={2}", LinksetRoot.LocalID, centerOfMass, LinksetRoot.BSBody.ptr.ToString("X")); foreach (BSPhysObject child in m_taintChildren) { - BulletSimAPI.SetCenterOfMassByPosRot2(child.BSBody.ptr, + BulletSimAPI.SetCenterOfMassByPosRot2(child.BSBody.ptr, centerOfMass, OMV.Quaternion.Identity); } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs index 51b9196..538f905 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs @@ -78,7 +78,7 @@ public abstract class BSPhysObject : PhysicsActor public PrimitiveBaseShape BaseShape { get; protected set; } // When the physical properties are updated, an EntityProperty holds the update values. - // Keep the current and last EntityProperties to enable computation of differences + // Keep the current and last EntityProperties to enable computation of differences // between the current update and the previous values. public EntityProperties CurrentEntityProperties { get; set; } public EntityProperties LastEntityProperties { get; set; } @@ -213,7 +213,7 @@ public abstract class BSPhysObject : PhysicsActor UnSubscribeEvents(); } } - public override void UnSubscribeEvents() { + public override void UnSubscribeEvents() { // DetailLog("{0},{1}.UnSubscribeEvents,unsubscribing", LocalID, TypeName); SubscribedEventsMs = 0; PhysicsScene.TaintedObject(TypeName+".UnSubscribeEvents", delegate() @@ -222,7 +222,7 @@ public abstract class BSPhysObject : PhysicsActor }); } // Return 'true' if the simulator wants collision events - public override bool SubscribedEvents() { + public override bool SubscribedEvents() { return (SubscribedEventsMs > 0); } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index aeeb4dd..7b211fa 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs @@ -295,7 +295,7 @@ public sealed class BSPrim : BSPhysObject private bool PositionSanityCheck() { bool ret = false; - + // If totally below the ground, move the prim up // TODO: figure out the right solution for this... only for dynamic objects? /* @@ -510,7 +510,7 @@ public sealed class BSPrim : BSPhysObject }); } } - // Go directly to Bullet to get/set the value. + // Go directly to Bullet to get/set the value. public override OMV.Quaternion ForceOrientation { get @@ -768,7 +768,7 @@ public sealed class BSPrim : BSPhysObject } } public override bool FloatOnWater { - set { + set { _floatOnWater = value; PhysicsScene.TaintedObject("BSPrim.setFloatOnWater", delegate() { @@ -971,7 +971,7 @@ public sealed class BSPrim : BSPhysObject if (hollowAmount > 0.0) { hollowVolume *= hollowAmount; - + switch (BaseShape.HollowShape) { case HollowShape.Square: @@ -1251,7 +1251,7 @@ public sealed class BSPrim : BSPhysObject // Create the correct physical representation for this type of object. // Updates BSBody and BSShape with the new information. // Ignore 'forceRebuild'. This routine makes the right choices and changes of necessary. - PhysicsScene.Shapes.GetBodyAndShape(false, PhysicsScene.World, this, shapeData, BaseShape, + PhysicsScene.Shapes.GetBodyAndShape(false, PhysicsScene.World, this, shapeData, BaseShape, null, delegate(BulletBody dBody) { // Called if the current prim body is about to be destroyed. diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs index 6621d39..233f1ca 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs @@ -320,7 +320,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters { m_log.Debug("[BULLETS UNMANAGED]:" + msg); } - + // Called directly from unmanaged code so don't do much private void BulletLoggerPhysLog(string msg) { @@ -545,7 +545,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters } // This is a kludge to get avatar movement updates. - // The simulator expects collisions for avatars even if there are have been no collisions. + // The simulator expects collisions for avatars even if there are have been no collisions. // The event updates avatar animations and stuff. // If you fix avatar animation updates, remove this overhead and let normal collision processing happen. foreach (BSPhysObject bsp in m_avatars) diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs index 7b808eb..86bbf46 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs @@ -89,7 +89,7 @@ public class BSShapeCollection : IDisposable // higher level dependencies on the shape or body. Mostly used for LinkSets to // remove the physical constraints before the body is destroyed. // Called at taint-time!! - public bool GetBodyAndShape(bool forceRebuild, BulletSim sim, BSPhysObject prim, + public bool GetBodyAndShape(bool forceRebuild, BulletSim sim, BSPhysObject prim, ShapeData shapeData, PrimitiveBaseShape pbs, ShapeDestructionCallback shapeCallback, BodyDestructionCallback bodyCallback) { @@ -105,7 +105,7 @@ public class BSShapeCollection : IDisposable // If we had to select a new shape geometry for the object, // rebuild the body around it. // Updates prim.BSBody with information/pointers to requested body - bool newBody = CreateBody((newGeom || forceRebuild), prim, PhysicsScene.World, + bool newBody = CreateBody((newGeom || forceRebuild), prim, PhysicsScene.World, prim.BSShape, shapeData, bodyCallback); ret = newGeom || newBody; } @@ -325,7 +325,7 @@ public class BSShapeCollection : IDisposable // Info in prim.BSShape is updated to the new shape. // Returns 'true' if the geometry was rebuilt. // Called at taint-time! - private bool CreateGeom(bool forceRebuild, BSPhysObject prim, ShapeData shapeData, + private bool CreateGeom(bool forceRebuild, BSPhysObject prim, ShapeData shapeData, PrimitiveBaseShape pbs, ShapeDestructionCallback shapeCallback) { bool ret = false; @@ -335,7 +335,7 @@ public class BSShapeCollection : IDisposable if (shapeData.Type == ShapeData.PhysicsShapeType.SHAPE_AVATAR) { // an avatar capsule is close to a native shape (it is not shared) - ret = GetReferenceToNativeShape(prim, shapeData, ShapeData.PhysicsShapeType.SHAPE_AVATAR, + ret = GetReferenceToNativeShape(prim, shapeData, ShapeData.PhysicsShapeType.SHAPE_AVATAR, ShapeData.FixedShapeKey.KEY_CAPSULE, shapeCallback); DetailLog("{0},BSShapeCollection.CreateGeom,avatarCapsule,shape={1}", prim.LocalID, prim.BSShape); haveShape = true; @@ -362,7 +362,7 @@ public class BSShapeCollection : IDisposable || prim.BSShape.type != ShapeData.PhysicsShapeType.SHAPE_SPHERE ) { - ret = GetReferenceToNativeShape(prim, shapeData, ShapeData.PhysicsShapeType.SHAPE_SPHERE, + ret = GetReferenceToNativeShape(prim, shapeData, ShapeData.PhysicsShapeType.SHAPE_SPHERE, ShapeData.FixedShapeKey.KEY_SPHERE, shapeCallback); DetailLog("{0},BSShapeCollection.CreateGeom,sphere,force={1},shape={2}", prim.LocalID, forceRebuild, prim.BSShape); @@ -376,7 +376,7 @@ public class BSShapeCollection : IDisposable || prim.BSShape.type != ShapeData.PhysicsShapeType.SHAPE_BOX ) { - ret = GetReferenceToNativeShape( prim, shapeData, ShapeData.PhysicsShapeType.SHAPE_BOX, + ret = GetReferenceToNativeShape( prim, shapeData, ShapeData.PhysicsShapeType.SHAPE_BOX, ShapeData.FixedShapeKey.KEY_BOX, shapeCallback); DetailLog("{0},BSShapeCollection.CreateGeom,box,force={1},shape={2}", prim.LocalID, forceRebuild, prim.BSShape); @@ -423,14 +423,14 @@ public class BSShapeCollection : IDisposable BulletShape newShape = BuildPhysicalNativeShape(shapeType, shapeData, shapeKey); // Don't need to do a 'ReferenceShape()' here because native shapes are not shared. - DetailLog("{0},BSShapeCollection.AddNativeShapeToPrim,create,newshape={1},scale={2}", + DetailLog("{0},BSShapeCollection.AddNativeShapeToPrim,create,newshape={1},scale={2}", shapeData.ID, newShape, shapeData.Scale); prim.BSShape = newShape; return true; } - private BulletShape BuildPhysicalNativeShape(ShapeData.PhysicsShapeType shapeType, + private BulletShape BuildPhysicalNativeShape(ShapeData.PhysicsShapeType shapeType, ShapeData shapeData, ShapeData.FixedShapeKey shapeKey) { BulletShape newShape; @@ -438,7 +438,7 @@ public class BSShapeCollection : IDisposable if (shapeType == ShapeData.PhysicsShapeType.SHAPE_AVATAR) { newShape = new BulletShape( - BulletSimAPI.BuildCapsuleShape2(PhysicsScene.World.ptr, 1.0f, 1.0f, shapeData.Scale), + BulletSimAPI.BuildCapsuleShape2(PhysicsScene.World.ptr, 1.0f, 1.0f, shapeData.Scale), shapeType); } else @@ -745,7 +745,7 @@ public class BSShapeCollection : IDisposable // Updates prim.BSBody with the information about the new body if one is created. // Returns 'true' if an object was actually created. // Called at taint-time. - private bool CreateBody(bool forceRebuild, BSPhysObject prim, BulletSim sim, BulletShape shape, + private bool CreateBody(bool forceRebuild, BSPhysObject prim, BulletSim sim, BulletShape shape, ShapeData shapeData, BodyDestructionCallback bodyCallback) { bool ret = false; -- cgit v1.1 From 7272a4cae835f2d3d2a696241c6e6eb5f4b5af54 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Mon, 22 Oct 2012 09:12:06 -0700 Subject: BulletSim: fix problem of not rebuilding shape by clearing last rebuild failed flag in BSPrim.ForceBodyShapeRebuild() --- OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | 1 + OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs | 9 +++++++-- 2 files changed, 8 insertions(+), 2 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index 7b211fa..3c5e6e5 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs @@ -173,6 +173,7 @@ public sealed class BSPrim : BSPhysObject } public override bool ForceBodyShapeRebuild(bool inTaintTime) { + LastAssetBuildFailed = false; BSScene.TaintCallback rebuildOperation = delegate() { _mass = CalculateMass(); // changing the shape changes the mass diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs index 86bbf46..89d0d3e 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs @@ -698,14 +698,19 @@ public class BSShapeCollection : IDisposable return ComputeShapeKey(shapeData, pbs, out lod); } + // The creation of a mesh or hull can fail if an underlying asset is not available. + // There are two cases: 1) the asset is not in the cache and it needs to be fetched; + // and 2) the asset cannot be converted (like decompressing JPEG2000s). + // The first case causes the asset to be fetched. The second case just requires + // us to not loop forever. + // Called after creating a physical mesh or hull. If the physical shape was created, + // just return. private BulletShape VerifyMeshCreated(BulletShape newShape, BSPhysObject prim, ShapeData shapeData, PrimitiveBaseShape pbs) { // If the shape was successfully created, nothing more to do if (newShape.ptr != IntPtr.Zero) return newShape; - // The most common reason for failure is that an underlying asset is not available - // If this mesh has an underlying asset and we have not failed getting it before, fetch the asset if (pbs.SculptEntry && !prim.LastAssetBuildFailed && pbs.SculptTexture != OMV.UUID.Zero) { -- cgit v1.1 From 14eeb8b31b865f7b1927703028b03b6f61693cb6 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Mon, 22 Oct 2012 16:33:21 -0700 Subject: BulletSim: fix bug that caused error (and a crash on 32 bit Linux) when mesh assets weren't already in the cache. Comment cleanups. --- .../Region/Physics/BulletSPlugin/BSConstraint.cs | 4 ++- OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs | 5 ++-- OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs | 13 +++++---- .../Physics/BulletSPlugin/BSLinksetConstraints.cs | 19 +++---------- OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | 9 ++++--- OpenSim/Region/Physics/BulletSPlugin/BSScene.cs | 1 + .../Physics/BulletSPlugin/BSShapeCollection.cs | 31 ++++++++++++++++++---- .../Physics/BulletSPlugin/BSTerrainManager.cs | 4 +-- 8 files changed, 51 insertions(+), 35 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs b/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs index b58745a..f017cdd 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs @@ -34,6 +34,8 @@ namespace OpenSim.Region.Physics.BulletSPlugin public abstract class BSConstraint : IDisposable { + private static string LogHeader = "[BULLETSIM CONSTRAINT]"; + protected BulletSim m_world; protected BulletBody m_body1; protected BulletBody m_body2; @@ -124,7 +126,7 @@ public abstract class BSConstraint : IDisposable } else { - m_world.physicsScene.Logger.ErrorFormat("[BULLETSIM CONSTRAINT] CalculateTransforms failed. A={0}, B={1}", Body1.ID, Body2.ID); + m_world.physicsScene.Logger.ErrorFormat("{0} CalculateTransforms failed. A={1}, B={2}", LogHeader, Body1.ID, Body2.ID); } } return ret; diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs index f71f3b0..117c878 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs @@ -464,8 +464,9 @@ namespace OpenSim.Region.Physics.BulletSPlugin // Set the prim's inertia to zero. The vehicle code handles that and this // removes the motion and torque actions introduced by Bullet. Vector3 inertia = Vector3.Zero; - BulletSimAPI.SetMassProps2(Prim.BSBody.ptr, Prim.MassRaw, inertia); - BulletSimAPI.UpdateInertiaTensor2(Prim.BSBody.ptr); + // comment out for DEBUG test + // BulletSimAPI.SetMassProps2(Prim.BSBody.ptr, Prim.MassRaw, inertia); + // BulletSimAPI.UpdateInertiaTensor2(Prim.BSBody.ptr); } // One step of the vehicle properties for the next 'pTimestep' seconds. diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs index 2e6b104..c984824 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs @@ -165,6 +165,9 @@ public abstract class BSLinkset bool ret = false; lock (m_linksetActivityLock) { + if (m_children.Contains(child)) + ret = true; + /* foreach (BSPhysObject bp in m_children) { if (child.LocalID == bp.LocalID) @@ -173,6 +176,7 @@ public abstract class BSLinkset break; } } + */ } return ret; } @@ -196,21 +200,20 @@ public abstract class BSLinkset // Called at taint-time! public abstract bool MakeStatic(BSPhysObject child); - // If the software is handling the movement of all the objects in a linkset - // (like if one doesn't use constraints for static linksets), this is called - // when an update for the root of the linkset is received. + // Called when a parameter update comes from the physics engine for any object + // of the linkset is received. // Called at taint-time!! public abstract void UpdateProperties(BSPhysObject physObject); // Routine used when rebuilding the body of the root of the linkset // Destroy all the constraints have have been made to root. // This is called when the root body is changing. - // Returns 'true' of something eas actually removed and would need restoring + // Returns 'true' of something was actually removed and would need restoring // Called at taint-time!! public abstract bool RemoveBodyDependencies(BSPrim child); // Companion to RemoveBodyDependencies(). If RemoveBodyDependencies() returns 'true', - // this routine will restore the removed constraints. + // this routine will restore the removed constraints. // Called at taint-time!! public abstract void RestoreBodyDependencies(BSPrim child); diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs index 8eeeb73..8a750b5 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs @@ -46,9 +46,8 @@ public class BSLinksetConstraints : BSLinkset // May be called at runtime or taint-time (just pass the appropriate flag). public override void Refresh(BSPhysObject requestor, bool inTaintTime) { - // If there are no children, not physical or not root, I am not the one that recomputes the constraints - // (For the moment, static linksets do create constraints so remove the test for physical.) - if (!HasAnyChildren || /*!requestor.IsPhysical ||*/ !IsRoot(requestor)) + // If there are no children or not root, I am not the one that recomputes the constraints + if (!HasAnyChildren || !IsRoot(requestor)) return; BSScene.TaintCallback refreshOperation = delegate() @@ -85,20 +84,10 @@ public class BSLinksetConstraints : BSLinkset return false; } - // If the software is handling the movement of all the objects in a linkset - // (like if one doesn't use constraints for static linksets), this is called - // when an update for the root of the linkset is received. // Called at taint-time!! - public override void UpdateProperties(BSPhysObject physObject) + public override void UpdateProperties(BSPhysObject updated) { - // The root local properties have been updated. Apply to the children if appropriate. - if (IsRoot(physObject) && HasAnyChildren) - { - if (!physObject.IsPhysical) - { - // TODO: implement software linkset update for static object linksets - } - } + // Nothing to do for constraints on property updates } // Routine used when rebuilding the body of the root of the linkset diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index 3c5e6e5..8401c69 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs @@ -399,7 +399,7 @@ public sealed class BSPrim : BSPhysObject { // Done at taint time so we're sure the physics engine is not using the variables // Vehicle code changes the parameters for this vehicle type. - this._vehicle.ProcessTypeChange(type); + _vehicle.ProcessTypeChange(type); }); } } @@ -1246,12 +1246,13 @@ public sealed class BSPrim : BSPhysObject FillShapeInfo(out shapeData); // If this prim is part of a linkset, we must remove and restore the physical - // links of the body is rebuilt. + // links if the body is rebuilt. bool needToRestoreLinkset = false; // Create the correct physical representation for this type of object. // Updates BSBody and BSShape with the new information. // Ignore 'forceRebuild'. This routine makes the right choices and changes of necessary. + // Returns 'true' if either the body or the shape was changed. PhysicsScene.Shapes.GetBodyAndShape(false, PhysicsScene.World, this, shapeData, BaseShape, null, delegate(BulletBody dBody) { @@ -1355,7 +1356,7 @@ public sealed class BSPrim : BSPhysObject DetailLog("{0},BSPrim.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5}", LocalID, _position, _orientation, _velocity, _acceleration, _rotationalVelocity); - // BulletSimAPI.DumpRigidBody2(Scene.World.Ptr, BSBody.Ptr); + BulletSimAPI.DumpRigidBody2(PhysicsScene.World.ptr, BSBody.ptr); // DEBUG DEBUG DEBUG base.RequestPhysicsterseUpdate(); } @@ -1368,8 +1369,8 @@ public sealed class BSPrim : BSPhysObject entprop.Acceleration, entprop.RotationalVelocity); } */ - // The linkset implimentation might want to know about this. + // The linkset implimentation might want to know about this. Linkset.UpdateProperties(this); } } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs index 233f1ca..48ee6f6 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs @@ -716,6 +716,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters } catch (Exception e) { + DetailLog("{0},BSScene.ProcessTaints,doTaintException,id={1}", DetailLogZero, oneCallback.ident); // DEBUG DEBUG DEBUG m_log.ErrorFormat("{0}: ProcessTaints: {1}: Exception: {2}", LogHeader, oneCallback.ident, e); } } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs index 89d0d3e..b1833c5 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs @@ -36,7 +36,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin { public class BSShapeCollection : IDisposable { - // private static string LogHeader = "[BULLETSIM SHAPE COLLECTION]"; + private static string LogHeader = "[BULLETSIM SHAPE COLLECTION]"; protected BSScene PhysicsScene { get; set; } @@ -434,16 +434,26 @@ public class BSShapeCollection : IDisposable ShapeData shapeData, ShapeData.FixedShapeKey shapeKey) { BulletShape newShape; + // Need to make sure the passed shape information is for the native type. + ShapeData nativeShapeData = shapeData; + nativeShapeData.Type = shapeType; + nativeShapeData.MeshKey = (ulong)shapeKey; + nativeShapeData.HullKey = (ulong)shapeKey; if (shapeType == ShapeData.PhysicsShapeType.SHAPE_AVATAR) { newShape = new BulletShape( - BulletSimAPI.BuildCapsuleShape2(PhysicsScene.World.ptr, 1.0f, 1.0f, shapeData.Scale), - shapeType); + BulletSimAPI.BuildCapsuleShape2(PhysicsScene.World.ptr, 1.0f, 1.0f, nativeShapeData.Scale), shapeType); + DetailLog("{0},BSShapeCollection.BuiletPhysicalNativeShape,capsule,scale={1}", nativeShapeData.ID, nativeShapeData.Scale); } else { - newShape = new BulletShape(BulletSimAPI.BuildNativeShape2(PhysicsScene.World.ptr, shapeData), shapeType); + newShape = new BulletShape(BulletSimAPI.BuildNativeShape2(PhysicsScene.World.ptr, nativeShapeData), shapeType); + } + if (newShape.ptr == IntPtr.Zero) + { + PhysicsScene.Logger.ErrorFormat("{0} BuildPhysicalNativeShape failed. ID={1}, shape={2}", + LogHeader, nativeShapeData.ID, nativeShapeData.Type); } newShape.shapeKey = (System.UInt64)shapeKey; newShape.isNativeShape = true; @@ -716,6 +726,8 @@ public class BSShapeCollection : IDisposable { prim.LastAssetBuildFailed = true; BSPhysObject xprim = prim; + DetailLog("{0},BSShapeCollection.VerifyMeshCreated,fetchAsset,lID={1},lastFailed={2}", + LogHeader, shapeData.ID.ToString("X"), prim.LastAssetBuildFailed); Util.FireAndForget(delegate { RequestAssetDelegate assetProvider = PhysicsScene.RequestAssetMethod; @@ -732,16 +744,25 @@ public class BSShapeCollection : IDisposable yprim.BaseShape.SculptData = asset.Data; // This will cause the prim to see that the filler shape is not the right // one and try again to build the object. + // No race condition with the native sphere setting since the rebuild is at taint time. yprim.ForceBodyShapeRebuild(false); }); } }); } + else + { + if (prim.LastAssetBuildFailed) + { + PhysicsScene.Logger.ErrorFormat("{0} Mesh failed to fetch asset. lID={1}, texture={2}", + LogHeader, shapeData.ID, pbs.SculptTexture); + } + } // While we figure out the real problem, stick a simple native shape on the object. BulletShape fillinShape = - BuildPhysicalNativeShape(ShapeData.PhysicsShapeType.SHAPE_SPHERE, shapeData, ShapeData.FixedShapeKey.KEY_SPHERE); + BuildPhysicalNativeShape(ShapeData.PhysicsShapeType.SHAPE_BOX, shapeData, ShapeData.FixedShapeKey.KEY_BOX); return fillinShape; } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs index 4106534..ae267e3 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs @@ -201,9 +201,7 @@ public class BSTerrainManager // If called with a mapInfo in m_heightMaps and there is an existing terrain body, a new // terrain shape is created and added to the body. // This call is most often used to update the heightMap and parameters of the terrain. - // The 'doNow' boolean says whether to do all the unmanaged activities right now (like when - // calling this routine from initialization or taint-time routines) or whether to delay - // all the unmanaged activities to taint-time. + // (The above does suggest that some simplification/refactoring is in order.) private void UpdateOrCreateTerrain(uint id, float[] heightMap, Vector3 minCoords, Vector3 maxCoords, bool inTaintTime) { DetailLog("{0},BSTerrainManager.UpdateOrCreateTerrain,call,minC={1},maxC={2},inTaintTime={3}", -- cgit v1.1 From 36bfd3667c44f7cd4e66e880c45c34903ed34842 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Mon, 22 Oct 2012 22:22:48 -0700 Subject: BulletSim: remove chatty debug message. --- OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | 2 +- OpenSim/Region/Physics/BulletSPlugin/BSScene.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index 8401c69..38ab3de 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs @@ -1356,7 +1356,7 @@ public sealed class BSPrim : BSPhysObject DetailLog("{0},BSPrim.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5}", LocalID, _position, _orientation, _velocity, _acceleration, _rotationalVelocity); - BulletSimAPI.DumpRigidBody2(PhysicsScene.World.ptr, BSBody.ptr); // DEBUG DEBUG DEBUG + // BulletSimAPI.DumpRigidBody2(PhysicsScene.World.ptr, BSBody.ptr); // DEBUG DEBUG DEBUG base.RequestPhysicsterseUpdate(); } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs index 48ee6f6..e686f2f 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs @@ -1334,7 +1334,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters // Add the Flush() if debugging crashes to get all the messages written out. // PhysicsLogging.Flush(); } - // used to fill in the LocalID when there isn't one + // Used to fill in the LocalID when there isn't one. It's the correct number of characters. public const string DetailLogZero = "0000000000"; } -- cgit v1.1 From b49f8a377b9ac542096a0bc8ad30b11942c27413 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Tue, 23 Oct 2012 08:02:26 -0700 Subject: BulletSim: minor change to insure avatar body recreation when shape changes. --- OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs index b1833c5..d9427e1 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs @@ -338,6 +338,7 @@ public class BSShapeCollection : IDisposable ret = GetReferenceToNativeShape(prim, shapeData, ShapeData.PhysicsShapeType.SHAPE_AVATAR, ShapeData.FixedShapeKey.KEY_CAPSULE, shapeCallback); DetailLog("{0},BSShapeCollection.CreateGeom,avatarCapsule,shape={1}", prim.LocalID, prim.BSShape); + ret = true; haveShape = true; } // If the prim attributes are simple, this could be a simple Bullet native shape @@ -411,15 +412,14 @@ public class BSShapeCollection : IDisposable ShapeData.PhysicsShapeType shapeType, ShapeData.FixedShapeKey shapeKey, ShapeDestructionCallback shapeCallback) { + // release any previous shape + DereferenceShape(prim.BSShape, true, shapeCallback); shapeData.Type = shapeType; // Bullet native objects are scaled by the Bullet engine so pass the size in prim.Scale = shapeData.Size; shapeData.Scale = shapeData.Size; - // release any previous shape - DereferenceShape(prim.BSShape, true, shapeCallback); - BulletShape newShape = BuildPhysicalNativeShape(shapeType, shapeData, shapeKey); // Don't need to do a 'ReferenceShape()' here because native shapes are not shared. -- cgit v1.1 From b6fc5bad000e7e7af992e7f29eeb2de9f716fcc4 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Tue, 23 Oct 2012 17:30:43 -0700 Subject: BulletSim: fix problem with avatars sinking into the ground. Change terrain activation state to DISABLE_SIMULATION for better performance. --- .../Region/Physics/BulletSPlugin/BSCharacter.cs | 27 ++++++++++++++-------- OpenSim/Region/Physics/BulletSPlugin/BSScene.cs | 3 +-- .../Physics/BulletSPlugin/BSShapeCollection.cs | 4 ++-- .../Physics/BulletSPlugin/BSTerrainManager.cs | 4 ++-- 4 files changed, 23 insertions(+), 15 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs index 07dd613..a041ba8 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs @@ -105,7 +105,7 @@ public class BSCharacter : BSPhysObject shapeData.Position = _position; shapeData.Rotation = _orientation; shapeData.Velocity = _velocity; - shapeData.Size = Scale; + shapeData.Size = Scale; // capsule is a native shape but scale is not just <1,1,1> shapeData.Scale = Scale; shapeData.Mass = _mass; shapeData.Buoyancy = _buoyancy; @@ -144,7 +144,9 @@ public class BSCharacter : BSPhysObject ForcePosition = _position; // Set the velocity and compute the proper friction ForceVelocity = _velocity; + BulletSimAPI.SetRestitution2(BSBody.ptr, PhysicsScene.Params.avatarRestitution); + BulletSimAPI.SetMargin2(BSShape.ptr, PhysicsScene.Params.collisionMargin); BulletSimAPI.SetLocalScaling2(BSShape.ptr, Scale); BulletSimAPI.SetContactProcessingThreshold2(BSBody.ptr, PhysicsScene.Params.contactProcessingThreshold); if (PhysicsScene.Params.ccdMotionThreshold > 0f) @@ -156,11 +158,15 @@ public class BSCharacter : BSPhysObject OMV.Vector3 localInertia = BulletSimAPI.CalculateLocalInertia2(BSShape.ptr, MassRaw); BulletSimAPI.SetMassProps2(BSBody.ptr, MassRaw, localInertia); + // Make so capsule does not fall over + BulletSimAPI.SetAngularFactorV2(BSBody.ptr, OMV.Vector3.Zero); + BulletSimAPI.AddToCollisionFlags2(BSBody.ptr, CollisionFlags.CF_CHARACTER_OBJECT); BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, BSBody.ptr); - BulletSimAPI.ForceActivationState2(BSBody.ptr, ActivationState.ACTIVE_TAG); + // BulletSimAPI.ForceActivationState2(BSBody.ptr, ActivationState.ACTIVE_TAG); + BulletSimAPI.ForceActivationState2(BSBody.ptr, ActivationState.DISABLE_DEACTIVATION); BulletSimAPI.UpdateSingleAabb2(PhysicsScene.World.ptr, BSBody.ptr); // Do this after the object has been added to the world @@ -175,11 +181,13 @@ public class BSCharacter : BSPhysObject } // No one calls this method so I don't know what it could possibly mean public override bool Stopped { get { return false; } } + public override OMV.Vector3 Size { get { // Avatar capsule size is kept in the scale parameter. - return _size; + // return _size; + return new OMV.Vector3(Scale.X * 2f, Scale.Y * 2f, Scale.Z); } set { @@ -199,7 +207,9 @@ public class BSCharacter : BSPhysObject } } + public override OMV.Vector3 Scale { get; set; } + public override PrimitiveBaseShape Shape { set { BaseShape = value; } @@ -264,7 +274,7 @@ public class BSCharacter : BSPhysObject // Check that the current position is sane and, if not, modify the position to make it so. - // Check for being below terrain and being out of bounds. + // Check for being below terrain or on water. // Returns 'true' of the position was made sane by some action. private bool PositionSanityCheck() { @@ -335,7 +345,7 @@ public class BSCharacter : BSPhysObject } // Avatars don't do vehicles - public override int VehicleType { get { return 0; } set { return; } } + public override int VehicleType { get { return (int)Vehicle.TYPE_NONE; } set { return; } } public override void VehicleFloatParam(int param, float value) { } public override void VehicleVectorParam(int param, OMV.Vector3 value) {} public override void VehicleRotationParam(int param, OMV.Quaternion rotation) { } @@ -588,9 +598,8 @@ public class BSCharacter : BSPhysObject newScale.X = PhysicsScene.Params.avatarCapsuleRadius; newScale.Y = PhysicsScene.Params.avatarCapsuleRadius; - // From the total height, remote the capsule half spheres that are at each end - newScale.Z = (size.Z * 2f) - Math.Min(newScale.X, newScale.Y); - // newScale.Z = (size.Z * 2f); + // From the total height, remove the capsule half spheres that are at each end + newScale.Z = size.Z- (newScale.X + newScale.Y); Scale = newScale; } @@ -636,7 +645,7 @@ public class BSCharacter : BSPhysObject BulletSimAPI.SetLinearVelocity2(BSBody.ptr, avVel); } - // Tell the linkset about this + // Tell the linkset about value changes Linkset.UpdateProperties(this); // Avatars don't report their changes the usual way. Changes are checked for in the heartbeat loop. diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs index e686f2f..db0c99e 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs @@ -692,7 +692,6 @@ public class BSScene : PhysicsScene, IPhysicsParameters { if (_taintedObjects.Count > 0) // save allocating new list if there is nothing to process { - // swizzle a new list into the list location so we can process what's there int taintCount = m_taintsToProcessPerStep; TaintCallbackEntry oneCallback = new TaintCallbackEntry(); while (_taintedObjects.Count > 0 && taintCount-- > 0) @@ -711,7 +710,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters { try { - DetailLog("{0},BSScene.ProcessTaints,doTaint,id={1}", DetailLogZero, oneCallback.ident); // DEBUG DEBUG DEBUG + DetailLog("{0},BSScene.ProcessTaints,doTaint,id={1}", DetailLogZero, oneCallback.ident); oneCallback.callback(); } catch (Exception e) diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs index d9427e1..30fa50a 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs @@ -443,7 +443,8 @@ public class BSShapeCollection : IDisposable if (shapeType == ShapeData.PhysicsShapeType.SHAPE_AVATAR) { newShape = new BulletShape( - BulletSimAPI.BuildCapsuleShape2(PhysicsScene.World.ptr, 1.0f, 1.0f, nativeShapeData.Scale), shapeType); + BulletSimAPI.BuildCapsuleShape2(PhysicsScene.World.ptr, 1f, 1f, nativeShapeData.Scale) + , shapeType); DetailLog("{0},BSShapeCollection.BuiletPhysicalNativeShape,capsule,scale={1}", nativeShapeData.ID, nativeShapeData.Scale); } else @@ -790,7 +791,6 @@ public class BSShapeCollection : IDisposable // If the collisionObject is not the correct type for solidness, rebuild what's there mustRebuild = true; } - } if (mustRebuild || forceRebuild) diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs index ae267e3..880859a 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs @@ -333,8 +333,8 @@ public class BSTerrainManager // Make sure the new shape is processed. // BulletSimAPI.Activate2(mapInfo.terrainBody.ptr, true); - BulletSimAPI.ForceActivationState2(mapInfo.terrainBody.ptr, ActivationState.ISLAND_SLEEPING); - // BulletSimAPI.ForceActivationState2(mapInfo.terrainBody.ptr, ActivationState.DISABLE_SIMULATION); + // BulletSimAPI.ForceActivationState2(mapInfo.terrainBody.ptr, ActivationState.ISLAND_SLEEPING); + BulletSimAPI.ForceActivationState2(mapInfo.terrainBody.ptr, ActivationState.DISABLE_SIMULATION); m_terrainModified = true; }; -- cgit v1.1 From 938fa96b9f5377ef330171232262b4d8aaca0918 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Wed, 24 Oct 2012 01:33:21 +0100 Subject: minor: Move co-ordinate related help to object commands to common ConsoleUtil.CoordHelp --- .../World/Objects/Commands/ObjectCommandsModule.cs | 36 ++-------------------- 1 file changed, 3 insertions(+), 33 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs b/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs index 87241e1..6435ae6 100644 --- a/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs +++ b/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs @@ -122,17 +122,7 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands "delete object pos", "delete object pos to ", "Delete scene objects within the given area.", - "Each component of the coord is comma separated. There must be no spaces between the commas.\n" - + "If you don't care about the z component you can simply omit it.\n" - + "If you don't care about the x or y components then you can leave them blank (though a comma is still required)\n" - + "If you want to specify the maxmimum value of a component then you can use ~ instead of a number\n" - + "If you want to specify the minimum value of a component then you can use -~ instead of a number\n" - + "e.g.\n" - + "delete object pos 20,20,20 to 40,40,40\n" - + "delete object pos 20,20 to 40,40\n" - + "delete object pos ,20,20 to ,40,40\n" - + "delete object pos ,,30 to ,,~\n" - + "delete object pos ,,-~ to ,,30", + ConsoleUtil.CoordHelp, HandleDeleteObject); m_console.Commands.AddCommand( @@ -164,17 +154,7 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands "Show details of scene objects within the given area.", "The --full option will print out information on all the parts of the object.\n" + "For yet more detailed part information, use the \"show part\" commands.\n" - + "Each component of the coord is comma separated. There must be no spaces between the commas.\n" - + "If you don't care about the z component you can simply omit it.\n" - + "If you don't care about the x or y components then you can leave them blank (though a comma is still required)\n" - + "If you want to specify the maxmimum value of a component then you can use ~ instead of a number\n" - + "If you want to specify the minimum value of a component then you can use -~ instead of a number\n" - + "e.g.\n" - + "show object pos 20,20,20 to 40,40,40\n" - + "show object pos 20,20 to 40,40\n" - + "show object pos ,20,20 to ,40,40\n" - + "show object pos ,,30 to ,,~\n" - + "show object pos ,,-~ to ,,30", + + ConsoleUtil.CoordHelp, HandleShowObjectByPos); m_console.Commands.AddCommand( @@ -199,17 +179,7 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands "show part pos", "show part pos to ", "Show details of scene object parts within the given area.", - "Each component of the coord is comma separated. There must be no spaces between the commas.\n" - + "If you don't care about the z component you can simply omit it.\n" - + "If you don't care about the x or y components then you can leave them blank (though a comma is still required)\n" - + "If you want to specify the maxmimum value of a component then you can use ~ instead of a number\n" - + "If you want to specify the minimum value of a component then you can use -~ instead of a number\n" - + "e.g.\n" - + "show object pos 20,20,20 to 40,40,40\n" - + "show object pos 20,20 to 40,40\n" - + "show object pos ,20,20 to ,40,40\n" - + "show object pos ,,30 to ,,~\n" - + "show object pos ,,-~ to ,,30", + ConsoleUtil.CoordHelp, HandleShowPartByPos); } -- cgit v1.1 From 73db057fa1dbda7d6dff7de770cef8670b234f84 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Wed, 24 Oct 2012 02:05:28 +0100 Subject: Add "dump object uuid" console command. This allows any object in the scene to be serialized and dumped to XML for debug purposes. --- .../World/Objects/Commands/ObjectCommandsModule.cs | 53 ++++++++++++++++++++++ 1 file changed, 53 insertions(+) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs b/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs index 6435ae6..41a1afd 100644 --- a/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs +++ b/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs @@ -27,10 +27,12 @@ using System; using System.Collections.Generic; +using System.IO; using System.Linq; using System.Reflection; using System.Text; using System.Text.RegularExpressions; +using System.Xml; using log4net; using Mono.Addins; using NDesk.Options; @@ -41,6 +43,7 @@ using OpenSim.Framework.Console; using OpenSim.Framework.Monitoring; using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Scenes; +using OpenSim.Region.Framework.Scenes.Serialization; namespace OpenSim.Region.CoreModules.World.Objects.Commands { @@ -181,6 +184,16 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands "Show details of scene object parts within the given area.", ConsoleUtil.CoordHelp, HandleShowPartByPos); + + m_console.Commands.AddCommand( + "Objects", + false, + "dump object uuid", + "dump object uuid ", + "Dump the formatted serialization of the given object to the file .xml", + "e.g. dump object uuid c1ed6809-cc24-4061-a4c2-93082a2d1f1d will dump serialization to c1ed6809-cc24-4061-a4c2-93082a2d1f1d.xml\n" + + "To locate the UUID in the first place, you need to use the other show object commands", + HandleDumpObjectByUuid); } public void RemoveRegion(Scene scene) @@ -447,6 +460,46 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands OutputSopsToConsole(searchPredicate, true); } + private void HandleDumpObjectByUuid(string module, string[] cmdparams) + { + if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene)) + return; + + if (cmdparams.Length < 4) + { + m_console.OutputFormat("Usage: dump object uuid "); + return; + } + + UUID objectUuid; + if (!ConsoleUtil.TryParseConsoleUuid(m_console, cmdparams[3], out objectUuid)) + return; + + SceneObjectGroup so = m_scene.GetSceneObjectGroup(objectUuid); + + if (so == null) + { +// m_console.OutputFormat("No part found with uuid {0}", objectUuid); + return; + } + + string fileName = string.Format("{0}.xml", objectUuid); + + if (File.Exists(fileName)) + { + m_console.OutputFormat("File {0} already exists. Please move or remove it.", fileName); + return; + } + + using (XmlTextWriter xtw = new XmlTextWriter(fileName, Encoding.UTF8)) + { + xtw.Formatting = Formatting.Indented; + SceneObjectSerializer.ToOriginalXmlFormat(so, xtw, true); + } + + m_console.OutputFormat("Object dumped to file {0}", fileName); + } + /// /// Append a scene object report to an input StringBuilder /// -- cgit v1.1 From f76dceb90b5a76a7b6a5243c9032996c007c0cf5 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Wed, 24 Oct 2012 03:08:58 +0100 Subject: Get "save oar" and "save iar" to tell you in a more friendly manner if the filename to save already exists, rather than exception throwing. Also changes ConsoleUtil.CheckFileExists to CheckFileDoesNotExist() since this is more meaningful in the context, even though it does result in double negatives. --- .../Inventory/Archiver/InventoryArchiverModule.cs | 4 ++++ .../CoreModules/World/Archiver/ArchiverModule.cs | 18 +++++++++++------- .../World/Objects/Commands/ObjectCommandsModule.cs | 5 +---- .../Region/OptionalModules/Asset/AssetInfoModule.cs | 3 +++ 4 files changed, 19 insertions(+), 11 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs index cf87010..afe1200 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs @@ -35,6 +35,7 @@ using Nini.Config; using OpenMetaverse; using OpenSim.Framework; using OpenSim.Framework.Communications; +using OpenSim.Framework.Console; using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Scenes; using OpenSim.Services.Interfaces; @@ -209,6 +210,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver Guid id, string firstName, string lastName, string invPath, string pass, string savePath, Dictionary options) { + if (!ConsoleUtil.CheckFileDoesNotExist(MainConsole.Instance, savePath)) + return false; + if (m_scenes.Count > 0) { UserAccount userInfo = GetUserInfo(firstName, lastName, pass); diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiverModule.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiverModule.cs index 2a87dc2..970487a 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/ArchiverModule.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiverModule.cs @@ -32,6 +32,8 @@ using System.Reflection; using log4net; using NDesk.Options; using Nini.Config; +using OpenSim.Framework; +using OpenSim.Framework.Console; using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Scenes; @@ -117,7 +119,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver // // foreach (string param in mainParams) // m_log.DebugFormat("GOT PARAM [{0}]", param); - + if (mainParams.Count > 2) { DearchiveRegion(mainParams[2], mergeOar, skipAssets, Guid.Empty); @@ -150,14 +152,16 @@ namespace OpenSim.Region.CoreModules.World.Archiver List mainParams = ops.Parse(cmdparams); + string path; if (mainParams.Count > 2) - { - ArchiveRegion(mainParams[2], options); - } + path = mainParams[2]; else - { - ArchiveRegion(DEFAULT_OAR_BACKUP_FILENAME, options); - } + path = DEFAULT_OAR_BACKUP_FILENAME; + + if (!ConsoleUtil.CheckFileDoesNotExist(MainConsole.Instance, path)) + return; + + ArchiveRegion(path, options); } public void ArchiveRegion(string savePath, Dictionary options) diff --git a/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs b/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs index 41a1afd..f0a35ad 100644 --- a/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs +++ b/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs @@ -485,11 +485,8 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands string fileName = string.Format("{0}.xml", objectUuid); - if (File.Exists(fileName)) - { - m_console.OutputFormat("File {0} already exists. Please move or remove it.", fileName); + if (!ConsoleUtil.CheckFileDoesNotExist(m_console, fileName)) return; - } using (XmlTextWriter xtw = new XmlTextWriter(fileName, Encoding.UTF8)) { diff --git a/OpenSim/Region/OptionalModules/Asset/AssetInfoModule.cs b/OpenSim/Region/OptionalModules/Asset/AssetInfoModule.cs index 41ec14f..7639c6c 100644 --- a/OpenSim/Region/OptionalModules/Asset/AssetInfoModule.cs +++ b/OpenSim/Region/OptionalModules/Asset/AssetInfoModule.cs @@ -127,6 +127,9 @@ namespace OpenSim.Region.OptionalModules.Asset } string fileName = rawAssetId; + + if (!ConsoleUtil.CheckFileDoesNotExist(MainConsole.Instance, fileName)) + return; using (FileStream fs = new FileStream(fileName, FileMode.CreateNew)) { -- cgit v1.1 From 81aeecc90723658187668baa49bd168b7b333afb Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Wed, 24 Oct 2012 04:10:22 +0100 Subject: Allow "show object", "show part", "dump object" and "delete object" to accept a local ID as well as a UUID. This means that the sub-commands are now id rather than uuid, e.g. show object id --- .../World/Objects/Commands/ObjectCommandsModule.cs | 103 ++++++++++++--------- OpenSim/Region/Framework/Scenes/Scene.cs | 13 ++- OpenSim/Region/Framework/Scenes/SceneGraph.cs | 24 +++++ 3 files changed, 97 insertions(+), 43 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs b/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs index f0a35ad..b2c9bce 100644 --- a/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs +++ b/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs @@ -99,9 +99,9 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands HandleDeleteObject); m_console.Commands.AddCommand( - "Objects", false, "delete object uuid", - "delete object uuid ", - "Delete a scene object by uuid", + "Objects", false, "delete object id", + "delete object id ", + "Delete a scene object by uuid or localID", HandleDeleteObject); m_console.Commands.AddCommand( @@ -131,12 +131,12 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands m_console.Commands.AddCommand( "Objects", false, - "show object uuid", - "show object uuid [--full] ", - "Show details of a scene object with the given UUID", + "show object id", + "show object id [--full] ", + "Show details of a scene object with the given UUID or localID", "The --full option will print out information on all the parts of the object.\n" + "For yet more detailed part information, use the \"show part\" commands.", - HandleShowObjectByUuid); + HandleShowObjectById); m_console.Commands.AddCommand( "Objects", @@ -163,9 +163,9 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands m_console.Commands.AddCommand( "Objects", false, - "show part uuid", - "show part uuid ", - "Show details of a scene object parts with the given UUID", HandleShowPartByUuid); + "show part id", + "show part id ", + "Show details of a scene object part with the given UUID or localID", HandleShowPartById); m_console.Commands.AddCommand( "Objects", @@ -173,7 +173,7 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands "show part name", "show part name [--regex] ", "Show details of scene object parts with the given name.", - "If --regex is specified then the name is treatead as a regular expression", + "If --regex is specified then the name is treated as a regular expression", HandleShowPartByName); m_console.Commands.AddCommand( @@ -188,12 +188,13 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands m_console.Commands.AddCommand( "Objects", false, - "dump object uuid", - "dump object uuid ", + "dump object id", + "dump object id ", "Dump the formatted serialization of the given object to the file .xml", "e.g. dump object uuid c1ed6809-cc24-4061-a4c2-93082a2d1f1d will dump serialization to c1ed6809-cc24-4061-a4c2-93082a2d1f1d.xml\n" - + "To locate the UUID in the first place, you need to use the other show object commands", - HandleDumpObjectByUuid); + + "To locate the UUID or localID in the first place, you need to use the other show object commands.\n" + + "If a local ID is given then the filename used is still that for the UUID", + HandleDumpObjectById); } public void RemoveRegion(Scene scene) @@ -248,7 +249,7 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands m_console.OutputFormat(sb.ToString()); } - private void HandleShowObjectByUuid(string module, string[] cmdparams) + private void HandleShowObjectById(string module, string[] cmdparams) { if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene)) return; @@ -264,14 +265,17 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands return; } - UUID objectUuid; - if (!UUID.TryParse(mainParams[3], out objectUuid)) - { - m_console.OutputFormat("{0} is not a valid uuid", mainParams[3]); + UUID uuid; + uint localId; + if (!ConsoleUtil.TryParseConsoleId(m_console, mainParams[3], out uuid, out localId)) return; - } - SceneObjectGroup so = m_scene.GetSceneObjectGroup(objectUuid); + SceneObjectGroup so; + + if (localId != ConsoleUtil.LocalIdNotFound) + so = m_scene.GetSceneObjectGroup(localId); + else + so = m_scene.GetSceneObjectGroup(uuid); if (so == null) { @@ -348,7 +352,7 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands OutputSogsToConsole(searchPredicate, showFull); } - private void HandleShowPartByUuid(string module, string[] cmdparams) + private void HandleShowPartById(string module, string[] cmdparams) { if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene)) return; @@ -361,18 +365,20 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands if (mainParams.Count < 4) { - m_console.OutputFormat("Usage: show part uuid [--full] "); + m_console.OutputFormat("Usage: show part id [--full] "); return; } UUID objectUuid; - if (!UUID.TryParse(mainParams[3], out objectUuid)) - { - m_console.OutputFormat("{0} is not a valid uuid", mainParams[3]); + uint localId; + if (!ConsoleUtil.TryParseConsoleId(m_console, mainParams[3], out objectUuid, out localId)) return; - } - SceneObjectPart sop = m_scene.GetSceneObjectPart(objectUuid); + SceneObjectPart sop; + if (localId == ConsoleUtil.LocalIdNotFound) + sop = m_scene.GetSceneObjectPart(objectUuid); + else + sop = m_scene.GetSceneObjectPart(localId); if (sop == null) { @@ -460,22 +466,27 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands OutputSopsToConsole(searchPredicate, true); } - private void HandleDumpObjectByUuid(string module, string[] cmdparams) + private void HandleDumpObjectById(string module, string[] cmdparams) { if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene)) return; if (cmdparams.Length < 4) { - m_console.OutputFormat("Usage: dump object uuid "); + m_console.OutputFormat("Usage: dump object id "); return; } UUID objectUuid; - if (!ConsoleUtil.TryParseConsoleUuid(m_console, cmdparams[3], out objectUuid)) + uint localId; + if (!ConsoleUtil.TryParseConsoleId(m_console, cmdparams[3], out objectUuid, out localId)) return; - SceneObjectGroup so = m_scene.GetSceneObjectGroup(objectUuid); + SceneObjectGroup so; + if (localId == ConsoleUtil.LocalIdNotFound) + so = m_scene.GetSceneObjectGroup(objectUuid); + else + so = m_scene.GetSceneObjectGroup(localId); if (so == null) { @@ -483,6 +494,9 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands return; } + // In case we found it via local ID. + objectUuid = so.UUID; + string fileName = string.Format("{0}.xml", objectUuid); if (!ConsoleUtil.CheckFileDoesNotExist(m_console, fileName)) @@ -661,19 +675,24 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands break; - case "uuid": - if (!UUID.TryParse(o, out match)) + case "id": + UUID uuid; + uint localId; + if (!ConsoleUtil.TryParseConsoleId(m_console, o, out uuid, out localId)) return; requireConfirmation = false; deletes = new List(); - - m_scene.ForEachSOG(delegate (SceneObjectGroup g) - { - if (g.UUID == match && !g.IsAttachment) - deletes.Add(g); - }); - + + SceneObjectGroup so; + if (localId == ConsoleUtil.LocalIdNotFound) + so = m_scene.GetSceneObjectGroup(uuid); + else + so = m_scene.GetSceneObjectGroup(localId); + + if (!so.IsAttachment) + deletes.Add(so); + // if (deletes.Count == 0) // m_console.OutputFormat("No objects were found with uuid {0}", match); diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 5f45529..532598a 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -4688,13 +4688,24 @@ namespace OpenSim.Region.Framework.Scenes /// Get a group via its UUID /// /// - /// null if no group with that name exists + /// null if no group with that id exists public SceneObjectGroup GetSceneObjectGroup(UUID fullID) { return m_sceneGraph.GetSceneObjectGroup(fullID); } /// + /// Get a group via its local ID + /// + /// This will only return a group if the local ID matches a root part + /// + /// null if no group with that id exists + public SceneObjectGroup GetSceneObjectGroup(uint localID) + { + return m_sceneGraph.GetSceneObjectGroup(localID); + } + + /// /// Get a group by name from the scene (will return the first /// found, if there are more than one prim with the same name) /// diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs index 209a770..a4383fd 100644 --- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs +++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs @@ -983,6 +983,30 @@ namespace OpenSim.Region.Framework.Scenes } /// + /// Get a group in the scene + /// + /// + /// This will only return a group if the local ID matches the root part, not other parts. + /// + /// Local id of the root part of the group + /// null if no such group was found + protected internal SceneObjectGroup GetSceneObjectGroup(uint localID) + { + lock (SceneObjectGroupsByLocalPartID) + { + if (SceneObjectGroupsByLocalPartID.ContainsKey(localID)) + { + SceneObjectGroup so = SceneObjectGroupsByLocalPartID[localID]; + + if (so.LocalId == localID) + return so; + } + } + + return null; + } + + /// /// Get a group by name from the scene (will return the first /// found, if there are more than one prim with the same name) /// -- cgit v1.1 From 1743fe5d62422f959f1f865d1def2ad929375460 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Thu, 25 Oct 2012 00:29:50 +0100 Subject: Move npc creation tests involving appearance from OSSL_ApiAppearanceTest to OSSL_ApiNpcTests This is a more intuitive location. --- .../Shared/Tests/OSSL_ApiAppearanceTest.cs | 70 ---------------------- .../ScriptEngine/Shared/Tests/OSSL_ApiNpcTests.cs | 69 +++++++++++++++++++++ 2 files changed, 69 insertions(+), 70 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiAppearanceTest.cs b/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiAppearanceTest.cs index c8718d9..c401794 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiAppearanceTest.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiAppearanceTest.cs @@ -75,76 +75,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests m_engine.AddRegion(m_scene); } - /// - /// Test creation of an NPC where the appearance data comes from a notecard - /// - [Test] - public void TestOsNpcCreateUsingAppearanceFromNotecard() - { - TestHelpers.InMethod(); -// log4net.Config.XmlConfigurator.Configure(); - - // Store an avatar with a different height from default in a notecard. - UUID userId = TestHelpers.ParseTail(0x1); - float newHeight = 1.9f; - - ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, userId); - sp.Appearance.AvatarHeight = newHeight; - SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, userId, 0x10); - SceneObjectPart part = so.RootPart; - m_scene.AddSceneObject(so); - - OSSL_Api osslApi = new OSSL_Api(); - osslApi.Initialize(m_engine, part, null); - - string notecardName = "appearanceNc"; - osslApi.osOwnerSaveAppearance(notecardName); - - // Try creating a bot using the appearance in the notecard. - string npcRaw = osslApi.osNpcCreate("Jane", "Doe", new LSL_Types.Vector3(128, 128, 128), notecardName); - Assert.That(npcRaw, Is.Not.Null); - - UUID npcId = new UUID(npcRaw); - ScenePresence npc = m_scene.GetScenePresence(npcId); - Assert.That(npc, Is.Not.Null); - Assert.That(npc.Appearance.AvatarHeight, Is.EqualTo(newHeight)); - } - - /// - /// Test creation of an NPC where the appearance data comes from an avatar already in the region. - /// - [Test] - public void TestOsNpcCreateUsingAppearanceFromAvatar() - { - TestHelpers.InMethod(); -// TestHelpers.EnableLogging(); - - // Store an avatar with a different height from default in a notecard. - UUID userId = TestHelpers.ParseTail(0x1); - float newHeight = 1.9f; - - ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, userId); - sp.Appearance.AvatarHeight = newHeight; - SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, userId, 0x10); - SceneObjectPart part = so.RootPart; - m_scene.AddSceneObject(so); - - OSSL_Api osslApi = new OSSL_Api(); - osslApi.Initialize(m_engine, part, null); - - string notecardName = "appearanceNc"; - osslApi.osOwnerSaveAppearance(notecardName); - - // Try creating a bot using the existing avatar's appearance - string npcRaw = osslApi.osNpcCreate("Jane", "Doe", new LSL_Types.Vector3(128, 128, 128), sp.UUID.ToString()); - Assert.That(npcRaw, Is.Not.Null); - - UUID npcId = new UUID(npcRaw); - ScenePresence npc = m_scene.GetScenePresence(npcId); - Assert.That(npc, Is.Not.Null); - Assert.That(npc.Appearance.AvatarHeight, Is.EqualTo(newHeight)); - } - [Test] public void TestOsOwnerSaveAppearance() { diff --git a/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiNpcTests.cs b/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiNpcTests.cs index 25679a6..b5a4d93 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiNpcTests.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiNpcTests.cs @@ -79,6 +79,75 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests } /// + /// Test creation of an NPC where the appearance data comes from a notecard + /// + [Test] + public void TestOsNpcCreateUsingAppearanceFromNotecard() + { + TestHelpers.InMethod(); + + // Store an avatar with a different height from default in a notecard. + UUID userId = TestHelpers.ParseTail(0x1); + float newHeight = 1.9f; + + ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, userId); + sp.Appearance.AvatarHeight = newHeight; + SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, userId, 0x10); + SceneObjectPart part = so.RootPart; + m_scene.AddSceneObject(so); + + OSSL_Api osslApi = new OSSL_Api(); + osslApi.Initialize(m_engine, part, null); + + string notecardName = "appearanceNc"; + osslApi.osOwnerSaveAppearance(notecardName); + + // Try creating a bot using the appearance in the notecard. + string npcRaw = osslApi.osNpcCreate("Jane", "Doe", new LSL_Types.Vector3(128, 128, 128), notecardName); + Assert.That(npcRaw, Is.Not.Null); + + UUID npcId = new UUID(npcRaw); + ScenePresence npc = m_scene.GetScenePresence(npcId); + Assert.That(npc, Is.Not.Null); + Assert.That(npc.Appearance.AvatarHeight, Is.EqualTo(newHeight)); + } + + /// + /// Test creation of an NPC where the appearance data comes from an avatar already in the region. + /// + [Test] + public void TestOsNpcCreateUsingAppearanceFromAvatar() + { + TestHelpers.InMethod(); +// TestHelpers.EnableLogging(); + + // Store an avatar with a different height from default in a notecard. + UUID userId = TestHelpers.ParseTail(0x1); + float newHeight = 1.9f; + + ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, userId); + sp.Appearance.AvatarHeight = newHeight; + SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, userId, 0x10); + SceneObjectPart part = so.RootPart; + m_scene.AddSceneObject(so); + + OSSL_Api osslApi = new OSSL_Api(); + osslApi.Initialize(m_engine, part, null); + + string notecardName = "appearanceNc"; + osslApi.osOwnerSaveAppearance(notecardName); + + // Try creating a bot using the existing avatar's appearance + string npcRaw = osslApi.osNpcCreate("Jane", "Doe", new LSL_Types.Vector3(128, 128, 128), sp.UUID.ToString()); + Assert.That(npcRaw, Is.Not.Null); + + UUID npcId = new UUID(npcRaw); + ScenePresence npc = m_scene.GetScenePresence(npcId); + Assert.That(npc, Is.Not.Null); + Assert.That(npc.Appearance.AvatarHeight, Is.EqualTo(newHeight)); + } + + /// /// Test removal of an owned NPC. /// [Test] -- cgit v1.1 From 5d4ac5a90fea758e18c8a9e97b06e799186b5a14 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Thu, 25 Oct 2012 00:59:27 +0100 Subject: Add TestOsNpcLoadAppearance() --- .../Shared/Tests/OSSL_ApiAppearanceTest.cs | 6 ++- .../ScriptEngine/Shared/Tests/OSSL_ApiNpcTests.cs | 43 +++++++++++++++++++++- 2 files changed, 45 insertions(+), 4 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiAppearanceTest.cs b/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiAppearanceTest.cs index c401794..eb51c4e 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiAppearanceTest.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiAppearanceTest.cs @@ -36,11 +36,12 @@ using OpenMetaverse; using OpenMetaverse.Assets; using OpenMetaverse.StructuredData; using OpenSim.Framework; +using OpenSim.Region.CoreModules.Avatar.Attachments; using OpenSim.Region.CoreModules.Avatar.AvatarFactory; -using OpenSim.Region.OptionalModules.World.NPC; using OpenSim.Region.Framework.Scenes; using OpenSim.Region.ScriptEngine.Shared; using OpenSim.Region.ScriptEngine.Shared.Api; +using OpenSim.Region.OptionalModules.World.NPC; using OpenSim.Services.Interfaces; using OpenSim.Tests.Common; using OpenSim.Tests.Common.Mock; @@ -68,7 +69,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests config.Set("Enabled", "true"); m_scene = new SceneHelpers().SetupScene(); - SceneHelpers.SetupSceneModules(m_scene, initConfigSource, new AvatarFactoryModule(), new NPCModule()); + SceneHelpers.SetupSceneModules( + m_scene, initConfigSource, new AvatarFactoryModule(), new AttachmentsModule(), new NPCModule()); m_engine = new XEngine.XEngine(); m_engine.Initialise(initConfigSource); diff --git a/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiNpcTests.cs b/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiNpcTests.cs index b5a4d93..0a3a75d 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiNpcTests.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiNpcTests.cs @@ -36,6 +36,7 @@ using OpenMetaverse; using OpenMetaverse.Assets; using OpenMetaverse.StructuredData; using OpenSim.Framework; +using OpenSim.Region.CoreModules.Avatar.Attachments; using OpenSim.Region.CoreModules.Avatar.AvatarFactory; using OpenSim.Region.OptionalModules.World.NPC; using OpenSim.Region.Framework.Scenes; @@ -71,7 +72,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests config.Set("Enabled", "true"); m_scene = new SceneHelpers().SetupScene(); - SceneHelpers.SetupSceneModules(m_scene, initConfigSource, new AvatarFactoryModule(), new NPCModule()); + SceneHelpers.SetupSceneModules( + m_scene, initConfigSource, new AvatarFactoryModule(), new AttachmentsModule(), new NPCModule()); m_engine = new XEngine.XEngine(); m_engine.Initialise(initConfigSource); @@ -147,6 +149,44 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests Assert.That(npc.Appearance.AvatarHeight, Is.EqualTo(newHeight)); } + [Test] + public void TestOsNpcLoadAppearance() + { + TestHelpers.InMethod(); + + // Store an avatar with a different height from default in a notecard. + UUID userId = TestHelpers.ParseTail(0x1); + float firstHeight = 1.9f; + float secondHeight = 2.1f; + string firstAppearanceNcName = "appearanceNc1"; + string secondAppearanceNcName = "appearanceNc2"; + + ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, userId); + sp.Appearance.AvatarHeight = firstHeight; + SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, userId, 0x10); + SceneObjectPart part = so.RootPart; + m_scene.AddSceneObject(so); + + OSSL_Api osslApi = new OSSL_Api(); + osslApi.Initialize(m_engine, part, null); + + osslApi.osOwnerSaveAppearance(firstAppearanceNcName); + + string npcRaw + = osslApi.osNpcCreate("Jane", "Doe", new LSL_Types.Vector3(128, 128, 128), firstAppearanceNcName); + + // Create a second appearance notecard with a different height + sp.Appearance.AvatarHeight = secondHeight; + osslApi.osOwnerSaveAppearance(secondAppearanceNcName); + + osslApi.osNpcLoadAppearance(npcRaw, secondAppearanceNcName); + + UUID npcId = new UUID(npcRaw); + ScenePresence npc = m_scene.GetScenePresence(npcId); + Assert.That(npc, Is.Not.Null); + Assert.That(npc.Appearance.AvatarHeight, Is.EqualTo(secondHeight)); + } + /// /// Test removal of an owned NPC. /// @@ -154,7 +194,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests public void TestOsNpcRemoveOwned() { TestHelpers.InMethod(); -// log4net.Config.XmlConfigurator.Configure(); // Store an avatar with a different height from default in a notecard. UUID userId = TestHelpers.ParseTail(0x1); -- cgit v1.1 From ae662b54ea972e4da4f805fe38b5714d595e032a Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Thu, 25 Oct 2012 01:07:06 +0100 Subject: Make osNpcCreate() return UUID.Zero instead of throwing an exception if notecard name is invalid. Make osNpcLoadAppearance() fail silently in same circumstance rather than throwing exception. --- .../Shared/Api/Implementation/OSSL_Api.cs | 26 +++++++---- .../Shared/Tests/OSSL_ApiAppearanceTest.cs | 6 +-- .../ScriptEngine/Shared/Tests/OSSL_ApiNpcTests.cs | 54 ++++++++++++++++++++++ 3 files changed, 74 insertions(+), 12 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs index 29bc163..804b0af 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs @@ -1780,18 +1780,24 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api protected string LoadNotecard(string notecardNameOrUuid) { UUID assetID = CacheNotecard(notecardNameOrUuid); - StringBuilder notecardData = new StringBuilder(); - for (int count = 0; count < NotecardCache.GetLines(assetID); count++) + if (assetID != UUID.Zero) { - string line = NotecardCache.GetLine(assetID, count) + "\n"; - -// m_log.DebugFormat("[OSSL]: From notecard {0} loading line {1}", notecardNameOrUuid, line); - - notecardData.Append(line); + StringBuilder notecardData = new StringBuilder(); + + for (int count = 0; count < NotecardCache.GetLines(assetID); count++) + { + string line = NotecardCache.GetLine(assetID, count) + "\n"; + + // m_log.DebugFormat("[OSSL]: From notecard {0} loading line {1}", notecardNameOrUuid, line); + + notecardData.Append(line); + } + + return notecardData.ToString(); } - return notecardData.ToString(); + return null; } /// @@ -2407,6 +2413,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api return; string appearanceSerialized = LoadNotecard(notecard); + + if (appearanceSerialized == null) + return; + OSDMap appearanceOsd = (OSDMap)OSDParser.DeserializeLLSDXml(appearanceSerialized); // OSD a = OSDParser.DeserializeLLSDXml(appearanceSerialized); // Console.WriteLine("appearanceSerialized {0}", appearanceSerialized); diff --git a/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiAppearanceTest.cs b/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiAppearanceTest.cs index eb51c4e..c401794 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiAppearanceTest.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiAppearanceTest.cs @@ -36,12 +36,11 @@ using OpenMetaverse; using OpenMetaverse.Assets; using OpenMetaverse.StructuredData; using OpenSim.Framework; -using OpenSim.Region.CoreModules.Avatar.Attachments; using OpenSim.Region.CoreModules.Avatar.AvatarFactory; +using OpenSim.Region.OptionalModules.World.NPC; using OpenSim.Region.Framework.Scenes; using OpenSim.Region.ScriptEngine.Shared; using OpenSim.Region.ScriptEngine.Shared.Api; -using OpenSim.Region.OptionalModules.World.NPC; using OpenSim.Services.Interfaces; using OpenSim.Tests.Common; using OpenSim.Tests.Common.Mock; @@ -69,8 +68,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests config.Set("Enabled", "true"); m_scene = new SceneHelpers().SetupScene(); - SceneHelpers.SetupSceneModules( - m_scene, initConfigSource, new AvatarFactoryModule(), new AttachmentsModule(), new NPCModule()); + SceneHelpers.SetupSceneModules(m_scene, initConfigSource, new AvatarFactoryModule(), new NPCModule()); m_engine = new XEngine.XEngine(); m_engine.Initialise(initConfigSource); diff --git a/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiNpcTests.cs b/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiNpcTests.cs index 0a3a75d..4e58315 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiNpcTests.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiNpcTests.cs @@ -114,6 +114,26 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests Assert.That(npc.Appearance.AvatarHeight, Is.EqualTo(newHeight)); } + [Test] + public void TestOsNpcCreateNotExistingNotecard() + { + TestHelpers.InMethod(); + + UUID userId = TestHelpers.ParseTail(0x1); + + SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, userId, 0x10); + m_scene.AddSceneObject(so); + + OSSL_Api osslApi = new OSSL_Api(); + osslApi.Initialize(m_engine, so.RootPart, null); + + string npcRaw + = osslApi.osNpcCreate("Jane", "Doe", new LSL_Types.Vector3(128, 128, 128), "not existing notecard name"); + + UUID npcId = new UUID(npcRaw); + Assert.That(npcId, Is.EqualTo(UUID.Zero)); + } + /// /// Test creation of an NPC where the appearance data comes from an avatar already in the region. /// @@ -187,6 +207,40 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests Assert.That(npc.Appearance.AvatarHeight, Is.EqualTo(secondHeight)); } + [Test] + public void TestOsNpcLoadAppearanceNotExistingNotecard() + { + TestHelpers.InMethod(); + + // Store an avatar with a different height from default in a notecard. + UUID userId = TestHelpers.ParseTail(0x1); + float firstHeight = 1.9f; + float secondHeight = 2.1f; + string firstAppearanceNcName = "appearanceNc1"; + string secondAppearanceNcName = "appearanceNc2"; + + ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, userId); + sp.Appearance.AvatarHeight = firstHeight; + SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, userId, 0x10); + SceneObjectPart part = so.RootPart; + m_scene.AddSceneObject(so); + + OSSL_Api osslApi = new OSSL_Api(); + osslApi.Initialize(m_engine, part, null); + + osslApi.osOwnerSaveAppearance(firstAppearanceNcName); + + string npcRaw + = osslApi.osNpcCreate("Jane", "Doe", new LSL_Types.Vector3(128, 128, 128), firstAppearanceNcName); + + osslApi.osNpcLoadAppearance(npcRaw, secondAppearanceNcName); + + UUID npcId = new UUID(npcRaw); + ScenePresence npc = m_scene.GetScenePresence(npcId); + Assert.That(npc, Is.Not.Null); + Assert.That(npc.Appearance.AvatarHeight, Is.EqualTo(firstHeight)); + } + /// /// Test removal of an owned NPC. /// -- cgit v1.1 From d9aaf51561ea7bb2ee030c648611a5281f21ec49 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Thu, 25 Oct 2012 02:52:20 +0100 Subject: When scripts generate expected exceptions (e.g. due to checked bad parameter) throw ScriptException instead of just a plain old exception. This is to make it easier to distinguish these exceptions from unexpected OpenSimulator problems internally and in regression tests. No functional changes. --- .../Framework/Scenes/Scene.PacketHandlers.cs | 5 ++- .../Shared/Api/Implementation/LSL_Api.cs | 4 +-- .../Shared/Api/Implementation/MOD_Api.cs | 10 +++--- .../Shared/Api/Implementation/OSSL_Api.cs | 2 +- .../Region/ScriptEngine/Shared/ScriptException.cs | 40 ++++++++++++++++++++++ 5 files changed, 52 insertions(+), 9 deletions(-) create mode 100644 OpenSim/Region/ScriptEngine/Shared/ScriptException.cs (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs b/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs index 6e53951..99bf72a 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs @@ -38,7 +38,6 @@ namespace OpenSim.Region.Framework.Scenes { public partial class Scene { - protected void SimChat(byte[] message, ChatTypeEnum type, int channel, Vector3 fromPos, string fromName, UUID fromID, UUID targetID, bool fromAgent, bool broadcast) { @@ -66,6 +65,10 @@ namespace OpenSim.Region.Framework.Scenes args.From = fromName; args.TargetUUID = targetID; +// m_log.DebugFormat( +// "[SCENE]: Sending message {0} on channel {1}, type {2} from {3}, broadcast {4}", +// args.Message.Replace("\n", "\\n"), args.Channel, args.Type, fromName, broadcast); + if (broadcast) EventManager.TriggerOnChatBroadcast(this, args); else diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index cf801ba..dc791d3 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -10685,12 +10685,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api internal void Deprecated(string command) { - throw new Exception("Command deprecated: " + command); + throw new ScriptException("Command deprecated: " + command); } internal void LSLError(string msg) { - throw new Exception("LSL Runtime Error: " + msg); + throw new ScriptException("LSL Runtime Error: " + msg); } public delegate void AssetRequestCallback(UUID assetID, AssetBase asset); diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs index 6809c09..a830a15 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs @@ -95,13 +95,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api internal void MODError(string msg) { - throw new Exception("MOD Runtime Error: " + msg); + throw new ScriptException("MOD Runtime Error: " + msg); } - // - //Dumps an error message on the debug console. - // - + /// + /// Dumps an error message on the debug console. + /// + /// internal void MODShoutError(string message) { if (message.Length > 1023) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs index 804b0af..5301ccd 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs @@ -210,7 +210,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api internal void OSSLError(string msg) { - throw new Exception("OSSL Runtime Error: " + msg); + throw new ScriptException("OSSL Runtime Error: " + msg); } /// diff --git a/OpenSim/Region/ScriptEngine/Shared/ScriptException.cs b/OpenSim/Region/ScriptEngine/Shared/ScriptException.cs new file mode 100644 index 0000000..ae67fc5 --- /dev/null +++ b/OpenSim/Region/ScriptEngine/Shared/ScriptException.cs @@ -0,0 +1,40 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; + +namespace OpenSim.Region.ScriptEngine.Shared +{ + public class ScriptException : Exception + { + public ScriptException() : base() {} + + public ScriptException(string message) : base(message) {} + + public ScriptException(string message, Exception innerException) : base(message, innerException) {} + } +} \ No newline at end of file -- cgit v1.1 From 8af8319b95c14819d0305527f8f6876a334fa3c0 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Thu, 25 Oct 2012 03:02:00 +0100 Subject: Get osNpcCreate() and osNpcLoadAppearance() to generate a script error if appearance notecard does not exist, rather than returning UUID.Zero or silently failing. --- .../Shared/Api/Implementation/OSSL_Api.cs | 11 ++++---- .../ScriptEngine/Shared/Tests/OSSL_ApiNpcTests.cs | 30 +++++++++++++++++----- 2 files changed, 30 insertions(+), 11 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs index 5301ccd..0811519 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs @@ -2346,11 +2346,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api appearance = new AvatarAppearance(); appearance.Unpack(appearanceOsd); } + else + { + OSSLError(string.Format("osNpcCreate: Notecard reference '{0}' not found.", notecard)); + } } - if (appearance == null) - return new LSL_Key(UUID.Zero.ToString()); - UUID ownerID = UUID.Zero; if (owned) ownerID = m_host.OwnerID; @@ -2415,8 +2416,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api string appearanceSerialized = LoadNotecard(notecard); if (appearanceSerialized == null) - return; - + OSSLError(string.Format("osNpcCreate: Notecard reference '{0}' not found.", notecard)); + OSDMap appearanceOsd = (OSDMap)OSDParser.DeserializeLLSDXml(appearanceSerialized); // OSD a = OSDParser.DeserializeLLSDXml(appearanceSerialized); // Console.WriteLine("appearanceSerialized {0}", appearanceSerialized); diff --git a/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiNpcTests.cs b/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiNpcTests.cs index 4e58315..b49bcc2 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiNpcTests.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiNpcTests.cs @@ -127,11 +127,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests OSSL_Api osslApi = new OSSL_Api(); osslApi.Initialize(m_engine, so.RootPart, null); - string npcRaw - = osslApi.osNpcCreate("Jane", "Doe", new LSL_Types.Vector3(128, 128, 128), "not existing notecard name"); - - UUID npcId = new UUID(npcRaw); - Assert.That(npcId, Is.EqualTo(UUID.Zero)); + string npcRaw; + bool gotExpectedException = false; + try + { + npcRaw + = osslApi.osNpcCreate("Jane", "Doe", new LSL_Types.Vector3(128, 128, 128), "not existing notecard name"); + } + catch (ScriptException) + { + gotExpectedException = true; + } + + Assert.That(gotExpectedException, Is.True); } /// @@ -233,7 +241,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests string npcRaw = osslApi.osNpcCreate("Jane", "Doe", new LSL_Types.Vector3(128, 128, 128), firstAppearanceNcName); - osslApi.osNpcLoadAppearance(npcRaw, secondAppearanceNcName); + bool gotExpectedException = false; + try + { + osslApi.osNpcLoadAppearance(npcRaw, secondAppearanceNcName); + } + catch (ScriptException) + { + gotExpectedException = true; + } + + Assert.That(gotExpectedException, Is.True); UUID npcId = new UUID(npcRaw); ScenePresence npc = m_scene.GetScenePresence(npcId); -- cgit v1.1 From c13a99dc5cc82efac5497dab27dcb6b0d9865cea Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Thu, 25 Oct 2012 03:26:12 +0100 Subject: Fix script error messages not showing up in viewer 3 and associated viewers. Viewer 3 will discard such a message if the chat message owner does not match the avatar. We were filling the ownerID with the primID, so this never matched, hence viewer 3 did not see any script error messages. This commit fills the ownerID in with the prim ownerID so the script owner will receive script error messages. This does not affect viewer 1 and associated viewers which continue to process script errors as normal. --- .../Region/ClientStack/Linden/UDP/LLClientView.cs | 7 ++-- .../Region/CoreModules/Avatar/Chat/ChatModule.cs | 39 +++++++++++++++------- .../Framework/Scenes/Scene.PacketHandlers.cs | 12 +++++++ .../Server/IRCClientView.cs | 3 +- .../Avatar/Concierge/ConciergeModule.cs | 5 +-- .../Region/OptionalModules/World/NPC/NPCAvatar.cs | 10 +++--- 6 files changed, 54 insertions(+), 22 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 7427c59..8e5a6d2 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -817,8 +817,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP OutPacket(mov, ThrottleOutPacketType.Unknown); } - public void SendChatMessage(string message, byte type, Vector3 fromPos, string fromName, - UUID fromAgentID, byte source, byte audible) + public void SendChatMessage( + string message, byte type, Vector3 fromPos, string fromName, + UUID fromAgentID, UUID ownerID, byte source, byte audible) { ChatFromSimulatorPacket reply = (ChatFromSimulatorPacket)PacketPool.Instance.GetPacket(PacketType.ChatFromSimulator); reply.ChatData.Audible = audible; @@ -827,7 +828,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP reply.ChatData.SourceType = source; reply.ChatData.Position = fromPos; reply.ChatData.FromName = Util.StringToBytes256(fromName); - reply.ChatData.OwnerID = fromAgentID; + reply.ChatData.OwnerID = ownerID; reply.ChatData.SourceID = fromAgentID; OutPacket(reply, ThrottleOutPacketType.Task); diff --git a/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs b/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs index e4452fb..ddf92c3 100644 --- a/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs @@ -186,6 +186,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat { string fromName = c.From; UUID fromID = UUID.Zero; + UUID ownerID = UUID.Zero; UUID targetID = c.TargetUUID; string message = c.Message; IScene scene = c.Scene; @@ -208,12 +209,16 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat fromPos = avatar.AbsolutePosition; fromName = avatar.Name; fromID = c.Sender.AgentId; + ownerID = c.Sender.AgentId; break; case ChatSourceType.Object: fromID = c.SenderUUID; + if (c.SenderObject != null && c.SenderObject is SceneObjectPart) + ownerID = ((SceneObjectPart)c.SenderObject).OwnerID; + break; } @@ -236,7 +241,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat s.ForEachRootScenePresence( delegate(ScenePresence presence) { - if (TrySendChatMessage(presence, fromPos, regionPos, fromID, fromName, c.Type, message, sourceType, false)) + if (TrySendChatMessage( + presence, fromPos, regionPos, fromID, ownerID, fromName, c.Type, message, sourceType, false)) receiverIDs.Add(presence.UUID); } ); @@ -248,8 +254,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat ScenePresence presence = s.GetScenePresence(targetID); if (presence != null && !presence.IsChildAgent) { - if (TrySendChatMessage(presence, fromPos, regionPos, fromID, fromName, ChatTypeEnum.Say, message, sourceType, true)) - receiverIDs.Add(presence.UUID); + if (TrySendChatMessage( + presence, fromPos, regionPos, fromID, ownerID, fromName, ChatTypeEnum.Say, message, sourceType, true)) + receiverIDs.Add(presence.UUID); } } } @@ -305,9 +312,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat (null != c.SenderObject) && (((SceneObjectPart)c.SenderObject).OwnerID != client.AgentId)) return; - - client.SendChatMessage(c.Message, (byte)cType, CenterOfRegion, fromName, fromID, - (byte)sourceType, (byte)ChatAudibleLevel.Fully); + + client.SendChatMessage( + c.Message, (byte)cType, CenterOfRegion, fromName, fromID, fromID, + (byte)sourceType, (byte)ChatAudibleLevel.Fully); + receiverIDs.Add(client.AgentId); }); @@ -322,15 +331,20 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat /// /// /param> /// + /// + /// Owner of the message. For at least some messages from objects, this has to be correctly filled with the owner's UUID. + /// This is the case for script error messages in viewer 3 since LLViewer change EXT-7762 + /// /// /// /// /// /// true if the message was sent to the receiver, false if it was not sent due to failing a /// precondition - protected virtual bool TrySendChatMessage(ScenePresence presence, Vector3 fromPos, Vector3 regionPos, - UUID fromAgentID, string fromName, ChatTypeEnum type, - string message, ChatSourceType src, bool ignoreDistance) + protected virtual bool TrySendChatMessage( + ScenePresence presence, Vector3 fromPos, Vector3 regionPos, + UUID fromAgentID, UUID ownerID, string fromName, ChatTypeEnum type, + string message, ChatSourceType src, bool ignoreDistance) { // don't send stuff to child agents if (presence.IsChildAgent) return false; @@ -353,10 +367,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat } // TODO: should change so the message is sent through the avatar rather than direct to the ClientView - presence.ControllingClient.SendChatMessage(message, (byte) type, fromPos, fromName, - fromAgentID, (byte)src, (byte)ChatAudibleLevel.Fully); + presence.ControllingClient.SendChatMessage( + message, (byte) type, fromPos, fromName, + fromAgentID, ownerID, (byte)src, (byte)ChatAudibleLevel.Fully); return true; } } -} +} \ No newline at end of file diff --git a/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs b/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs index 99bf72a..df43271 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs @@ -38,6 +38,18 @@ namespace OpenSim.Region.Framework.Scenes { public partial class Scene { + /// + /// Send chat to listeners. + /// + /// + /// /param> + /// + /// + /// + /// + /// + /// + /// protected void SimChat(byte[] message, ChatTypeEnum type, int channel, Vector3 fromPos, string fromName, UUID fromID, UUID targetID, bool fromAgent, bool broadcast) { diff --git a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs index e93bd7c..781539a 100644 --- a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs +++ b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs @@ -954,7 +954,8 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server } - public void SendChatMessage(string message, byte type, Vector3 fromPos, string fromName, UUID fromAgentID, byte source, byte audible) + public void SendChatMessage( + string message, byte type, Vector3 fromPos, string fromName, UUID fromAgentID, UUID ownerID, byte source, byte audible) { if (audible > 0 && message.Length > 0) IRC_SendChannelPrivmsg(fromName, message); diff --git a/OpenSim/Region/OptionalModules/Avatar/Concierge/ConciergeModule.cs b/OpenSim/Region/OptionalModules/Avatar/Concierge/ConciergeModule.cs index e22618d..5c3be29 100644 --- a/OpenSim/Region/OptionalModules/Avatar/Concierge/ConciergeModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/Concierge/ConciergeModule.cs @@ -546,8 +546,9 @@ namespace OpenSim.Region.OptionalModules.Avatar.Concierge c.SenderUUID = UUID.Zero; c.Scene = agent.Scene; - agent.ControllingClient.SendChatMessage(msg, (byte) ChatTypeEnum.Say, PosOfGod, m_whoami, UUID.Zero, - (byte)ChatSourceType.Object, (byte)ChatAudibleLevel.Fully); + agent.ControllingClient.SendChatMessage( + msg, (byte) ChatTypeEnum.Say, PosOfGod, m_whoami, UUID.Zero, UUID.Zero, + (byte)ChatSourceType.Object, (byte)ChatAudibleLevel.Fully); } private static void checkStringParameters(XmlRpcRequest request, string[] param) diff --git a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs index ffd4222..5ea2bcd 100644 --- a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs +++ b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs @@ -603,13 +603,15 @@ namespace OpenSim.Region.OptionalModules.World.NPC { } - public virtual void SendChatMessage(string message, byte type, Vector3 fromPos, string fromName, - UUID fromAgentID, byte source, byte audible) + public virtual void SendChatMessage( + string message, byte type, Vector3 fromPos, string fromName, + UUID fromAgentID, UUID ownerID, byte source, byte audible) { } - public virtual void SendChatMessage(byte[] message, byte type, Vector3 fromPos, string fromName, - UUID fromAgentID, byte source, byte audible) + public virtual void SendChatMessage( + byte[] message, byte type, Vector3 fromPos, string fromName, + UUID fromAgentID, UUID ownerID, byte source, byte audible) { } -- cgit v1.1 From fa484c3494a7190b4d7526094347be74d091e125 Mon Sep 17 00:00:00 2001 From: nebadon Date: Thu, 25 Oct 2012 11:31:25 -0700 Subject: Fix for Mantis 0006376: Avatar no longer show Walking animation when any AO hud is loaded. Thank you tglion --- OpenSim/Region/Framework/Scenes/Animation/AnimationSet.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Framework/Scenes/Animation/AnimationSet.cs b/OpenSim/Region/Framework/Scenes/Animation/AnimationSet.cs index ad421ee..9ed4f47 100644 --- a/OpenSim/Region/Framework/Scenes/Animation/AnimationSet.cs +++ b/OpenSim/Region/Framework/Scenes/Animation/AnimationSet.cs @@ -87,7 +87,7 @@ namespace OpenSim.Region.Framework.Scenes.Animation { if (m_defaultAnimation.AnimID == animID) { - m_defaultAnimation = new OpenSim.Framework.Animation(UUID.Zero, 1, UUID.Zero); + m_defaultAnimation = new OpenSim.Framework.Animation(animID, 1, UUID.Zero); } else if (HasAnimation(animID)) { -- cgit v1.1 From 22e216fd123744f6c87024fc18f3c9b306777fe2 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Thu, 25 Oct 2012 22:55:29 +0100 Subject: In Scene.Close(), dispose of the physics scene after base.Close() since script events can still access Physics scene until the script engine shuts down (triggered off base.Close()) XEngine listeners to EventManager.OnShutdown which is triggered from base.Close(). Possibly it could listen for the earlier OnSceneShuttingDown instead, but the easier solution right now is to relocate disposal of the physics scene. This bug has existed since c150320 (Thu Jul 26 15:27:18 2012) and was in 0.7.4 --- OpenSim/Region/Framework/Scenes/Scene.cs | 14 ++++++++------ OpenSim/Region/Framework/Scenes/Tests/SceneTests.cs | 17 +++++++++++++++++ 2 files changed, 25 insertions(+), 6 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 532598a..d48dc11 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -1310,6 +1310,14 @@ namespace OpenSim.Region.Framework.Scenes m_sceneGraph.Close(); + if (!GridService.DeregisterRegion(RegionInfo.RegionID)) + m_log.WarnFormat("[SCENE]: Deregister from grid failed for region {0}", Name); + + base.Close(); + + // XEngine currently listens to the EventManager.OnShutdown event to trigger script stop and persistence. + // Therefore. we must dispose of the PhysicsScene after this to prevent a window where script code can + // attempt to reference a null or disposed physics scene. if (PhysicsScene != null) { PhysicsScene phys = PhysicsScene; @@ -1318,12 +1326,6 @@ namespace OpenSim.Region.Framework.Scenes phys.Dispose(); phys = null; } - - if (!GridService.DeregisterRegion(RegionInfo.RegionID)) - m_log.WarnFormat("[SCENE]: Deregister from grid failed for region {0}", Name); - - // call the base class Close method. - base.Close(); } /// diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneTests.cs index d722a09..ac3da1e 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/SceneTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/SceneTests.cs @@ -65,5 +65,22 @@ namespace OpenSim.Region.Framework.Scenes.Tests Assert.That(scene.Frame, Is.EqualTo(1)); } + + [Test] + public void TestShutdownScene() + { + TestHelpers.InMethod(); + + Scene scene = new SceneHelpers().SetupScene(); + scene.Close(); + + Assert.That(scene.ShuttingDown, Is.True); + Assert.That(scene.Active, Is.False); + + // Trying to update a shutdown scene should result in no update + scene.Update(1); + + Assert.That(scene.Frame, Is.EqualTo(0)); + } } } \ No newline at end of file -- cgit v1.1 From b4923da3348b05e4b85f842210bea4e6f08b4cef Mon Sep 17 00:00:00 2001 From: Oren Hurvitz Date: Mon, 13 Aug 2012 16:02:50 +0300 Subject: Changed "course" to "coarse" in several places --- OpenSim/Region/Framework/Scenes/ScenePresence.cs | 14 +++++++------- .../RegionCombinerModule/RegionCombinerModule.cs | 20 ++++++++++---------- .../RegionCombinerModule/RegionCourseLocation.cs | 2 +- 3 files changed, 18 insertions(+), 18 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index 1222ac6..b6d0a3b 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -68,7 +68,7 @@ namespace OpenSim.Region.Framework.Scenes public ScriptControlled eventControls; } - public delegate void SendCourseLocationsMethod(UUID scene, ScenePresence presence, List coarseLocations, List avatarUUIDs); + public delegate void SendCoarseLocationsMethod(UUID scene, ScenePresence presence, List coarseLocations, List avatarUUIDs); public class ScenePresence : EntityBase, IScenePresence { @@ -186,7 +186,7 @@ namespace OpenSim.Region.Framework.Scenes /// public bool SitGround { get; private set; } - private SendCourseLocationsMethod m_sendCourseLocationsMethod; + private SendCoarseLocationsMethod m_sendCoarseLocationsMethod; //private Vector3 m_requestedSitOffset = new Vector3(); @@ -695,7 +695,7 @@ namespace OpenSim.Region.Framework.Scenes AttachmentsSyncLock = new Object(); AllowMovement = true; IsChildAgent = true; - m_sendCourseLocationsMethod = SendCoarseLocationsDefault; + m_sendCoarseLocationsMethod = SendCoarseLocationsDefault; Animator = new ScenePresenceAnimator(this); PresenceType = type; DrawDistance = world.DefaultDrawDistance; @@ -2432,17 +2432,17 @@ namespace OpenSim.Region.Framework.Scenes public void SendCoarseLocations(List coarseLocations, List avatarUUIDs) { - SendCourseLocationsMethod d = m_sendCourseLocationsMethod; + SendCoarseLocationsMethod d = m_sendCoarseLocationsMethod; if (d != null) { d.Invoke(m_scene.RegionInfo.originRegionID, this, coarseLocations, avatarUUIDs); } } - public void SetSendCourseLocationMethod(SendCourseLocationsMethod d) + public void SetSendCoarseLocationMethod(SendCoarseLocationsMethod d) { if (d != null) - m_sendCourseLocationsMethod = d; + m_sendCoarseLocationsMethod = d; } public void SendCoarseLocationsDefault(UUID sceneId, ScenePresence p, List coarseLocations, List avatarUUIDs) @@ -2646,7 +2646,7 @@ namespace OpenSim.Region.Framework.Scenes #region Significant Movement Method /// - /// This checks for a significant movement and sends a courselocationchange update + /// This checks for a significant movement and sends a coarselocationchange update /// protected void CheckForSignificantMovement() { diff --git a/OpenSim/Region/RegionCombinerModule/RegionCombinerModule.cs b/OpenSim/Region/RegionCombinerModule/RegionCombinerModule.cs index 190fca0..905540d 100644 --- a/OpenSim/Region/RegionCombinerModule/RegionCombinerModule.cs +++ b/OpenSim/Region/RegionCombinerModule/RegionCombinerModule.cs @@ -719,21 +719,21 @@ namespace OpenSim.Region.RegionCombinerModule rootConn.ClientEventForwarder = new RegionCombinerClientEventForwarder(rootConn); // Sets up the CoarseLocationUpdate forwarder for this root region - scene.EventManager.OnNewPresence += SetCourseLocationDelegate; + scene.EventManager.OnNewPresence += SetCoarseLocationDelegate; // Adds this root region to a dictionary of regions that are connectable m_regions.Add(scene.RegionInfo.originRegionID, rootConn); } } - private void SetCourseLocationDelegate(ScenePresence presence) + private void SetCoarseLocationDelegate(ScenePresence presence) { - presence.SetSendCourseLocationMethod(SendCourseLocationUpdates); + presence.SetSendCoarseLocationMethod(SendCoarseLocationUpdates); } // This delegate was refactored for non-combined regions. // This combined region version will not use the pre-compiled lists of locations and ids - private void SendCourseLocationUpdates(UUID sceneId, ScenePresence presence, List coarseLocations, List avatarUUIDs) + private void SendCoarseLocationUpdates(UUID sceneId, ScenePresence presence, List coarseLocations, List avatarUUIDs) { RegionConnections connectiondata = null; lock (m_regions) @@ -756,18 +756,18 @@ namespace OpenSim.Region.RegionCombinerModule } }); - DistributeCourseLocationUpdates(CoarseLocations, AvatarUUIDs, connectiondata, presence); + DistributeCoarseLocationUpdates(CoarseLocations, AvatarUUIDs, connectiondata, presence); } - private void DistributeCourseLocationUpdates(List locations, List uuids, + private void DistributeCoarseLocationUpdates(List locations, List uuids, RegionConnections connectiondata, ScenePresence rootPresence) { RegionData[] rdata = connectiondata.ConnectedRegions.ToArray(); //List clients = new List(); - Dictionary updates = new Dictionary(); + Dictionary updates = new Dictionary(); // Root Region entry - RegionCourseLocationStruct rootupdatedata = new RegionCourseLocationStruct(); + RegionCoarseLocationStruct rootupdatedata = new RegionCoarseLocationStruct(); rootupdatedata.Locations = new List(); rootupdatedata.Uuids = new List(); rootupdatedata.Offset = Vector2.Zero; @@ -781,7 +781,7 @@ namespace OpenSim.Region.RegionCombinerModule foreach (RegionData regiondata in rdata) { Vector2 offset = new Vector2(regiondata.Offset.X, regiondata.Offset.Y); - RegionCourseLocationStruct updatedata = new RegionCourseLocationStruct(); + RegionCoarseLocationStruct updatedata = new RegionCoarseLocationStruct(); updatedata.Locations = new List(); updatedata.Uuids = new List(); updatedata.Offset = offset; @@ -807,7 +807,7 @@ namespace OpenSim.Region.RegionCombinerModule if (!updates.ContainsKey(offset)) { // This shouldn't happen - RegionCourseLocationStruct updatedata = new RegionCourseLocationStruct(); + RegionCoarseLocationStruct updatedata = new RegionCoarseLocationStruct(); updatedata.Locations = new List(); updatedata.Uuids = new List(); updatedata.Offset = offset; diff --git a/OpenSim/Region/RegionCombinerModule/RegionCourseLocation.cs b/OpenSim/Region/RegionCombinerModule/RegionCourseLocation.cs index 53a678f..224ac99 100644 --- a/OpenSim/Region/RegionCombinerModule/RegionCourseLocation.cs +++ b/OpenSim/Region/RegionCombinerModule/RegionCourseLocation.cs @@ -33,7 +33,7 @@ using OpenSim.Framework; namespace OpenSim.Region.RegionCombinerModule { - struct RegionCourseLocationStruct + struct RegionCoarseLocationStruct { public List Locations; public List Uuids; -- cgit v1.1 From dc17cee044e0d2d17e8152eb31829c3ad5a99359 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Thu, 25 Oct 2012 23:47:13 +0100 Subject: minor: if a scene is already shutting down on Scene.Close(), warn and exit instead of attempting to run another shutdown concurrently. Thanks to Oren Hurvitz for this change. --- OpenSim/Region/Framework/Scenes/Scene.cs | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index d48dc11..0f39671 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -1267,6 +1267,12 @@ namespace OpenSim.Region.Framework.Scenes // This is the method that shuts down the scene. public override void Close() { + if (m_shuttingDown) + { + m_log.WarnFormat("[SCENE]: Ignoring close request because already closing {0}", Name); + return; + } + m_log.InfoFormat("[SCENE]: Closing down the single simulator: {0}", RegionInfo.RegionName); StatsReporter.Close(); -- cgit v1.1 From 85c909c0b551630d17c3f3bf4aff20e7bf8008e5 Mon Sep 17 00:00:00 2001 From: Oren Hurvitz Date: Tue, 23 Oct 2012 10:46:45 +0200 Subject: Fixed saving non-square multi-region OARs --- OpenSim/Region/CoreModules/World/Archiver/ArchiveScenesGroup.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveScenesGroup.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveScenesGroup.cs index a66ed88..d8dace2 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveScenesGroup.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveScenesGroup.cs @@ -110,7 +110,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver lastX = (lastX == null) ? curLastX : (lastX > curLastX) ? lastX : curLastX; } - Rect = new Rectangle((int)firstX, (int)firstY, (int)(lastY - firstY + 1), (int)(lastX - firstX + 1)); + Rect = new Rectangle((int)firstX, (int)firstY, (int)(lastX - firstX + 1), (int)(lastY - firstY + 1)); // Calculate the subdirectory in which each region will be stored in the archive -- cgit v1.1 From 2fb89b5aac0369e126234a8189d676d904d0ae33 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 26 Oct 2012 01:15:16 +0100 Subject: Comment out InventoryTransferModule.NeedSceneCacheClear() and invocations since the call itself does nothing and the return value is ignored by all callers. This is a very old method (+4 years) so is probably confusing code cruft. --- .../Inventory/Transfer/InventoryTransferModule.cs | 154 ++++++++++----------- .../EntityTransfer/EntityTransferModule.cs | 31 +++-- OpenSim/Region/Framework/Scenes/Scene.cs | 24 ++-- 3 files changed, 106 insertions(+), 103 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs index 33b4839..8ff20dd 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs @@ -38,15 +38,15 @@ using OpenSim.Services.Interfaces; namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer { - public class InventoryTransferModule : IInventoryTransferModule, ISharedRegionModule + public class InventoryTransferModule : ISharedRegionModule { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); /// private List m_Scenelist = new List(); - private Dictionary m_AgentRegions = - new Dictionary(); +// private Dictionary m_AgentRegions = +// new Dictionary(); private IMessageTransferModule m_TransferModule = null; private bool m_Enabled = true; @@ -76,12 +76,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer m_Scenelist.Add(scene); - scene.RegisterModuleInterface(this); +// scene.RegisterModuleInterface(this); scene.EventManager.OnNewClient += OnNewClient; - scene.EventManager.OnClientClosed += ClientLoggedOut; +// scene.EventManager.OnClientClosed += ClientLoggedOut; scene.EventManager.OnIncomingInstantMessage += OnGridInstantMessage; - scene.EventManager.OnSetRootAgentScene += OnSetRootAgentScene; +// scene.EventManager.OnSetRootAgentScene += OnSetRootAgentScene; } public void RegionLoaded(Scene scene) @@ -96,9 +96,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer m_Scenelist.Clear(); scene.EventManager.OnNewClient -= OnNewClient; - scene.EventManager.OnClientClosed -= ClientLoggedOut; +// scene.EventManager.OnClientClosed -= ClientLoggedOut; scene.EventManager.OnIncomingInstantMessage -= OnGridInstantMessage; - scene.EventManager.OnSetRootAgentScene -= OnSetRootAgentScene; +// scene.EventManager.OnSetRootAgentScene -= OnSetRootAgentScene; } } } @@ -106,9 +106,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer public void RemoveRegion(Scene scene) { scene.EventManager.OnNewClient -= OnNewClient; - scene.EventManager.OnClientClosed -= ClientLoggedOut; +// scene.EventManager.OnClientClosed -= ClientLoggedOut; scene.EventManager.OnIncomingInstantMessage -= OnGridInstantMessage; - scene.EventManager.OnSetRootAgentScene -= OnSetRootAgentScene; +// scene.EventManager.OnSetRootAgentScene -= OnSetRootAgentScene; m_Scenelist.Remove(scene); } @@ -138,10 +138,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer client.OnInstantMessage += OnInstantMessage; } - protected void OnSetRootAgentScene(UUID id, Scene scene) - { - m_AgentRegions[id] = scene; - } +// protected void OnSetRootAgentScene(UUID id, Scene scene) +// { +// m_AgentRegions[id] = scene; +// } private Scene FindClientScene(UUID agentId) { @@ -448,69 +448,69 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer } } - public bool NeedSceneCacheClear(UUID agentID, Scene scene) - { - if (!m_AgentRegions.ContainsKey(agentID)) - { - // Since we can get here two ways, we need to scan - // the scenes here. This is somewhat more expensive - // but helps avoid a nasty bug - // - - foreach (Scene s in m_Scenelist) - { - ScenePresence presence; - - if (s.TryGetScenePresence(agentID, out presence)) - { - // If the agent is in this scene, then we - // are being called twice in a single - // teleport. This is wasteful of cycles - // but harmless due to this 2nd level check - // - // If the agent is found in another scene - // then the list wasn't current - // - // If the agent is totally unknown, then what - // are we even doing here?? - // - if (s == scene) - { - //m_log.Debug("[INVTRANSFERMOD]: s == scene. Returning true in " + scene.RegionInfo.RegionName); - return true; - } - else - { - //m_log.Debug("[INVTRANSFERMOD]: s != scene. Returning false in " + scene.RegionInfo.RegionName); - return false; - } - } - } - //m_log.Debug("[INVTRANSFERMOD]: agent not in scene. Returning true in " + scene.RegionInfo.RegionName); - return true; - } - - // The agent is left in current Scene, so we must be - // going to another instance - // - if (m_AgentRegions[agentID] == scene) - { - //m_log.Debug("[INVTRANSFERMOD]: m_AgentRegions[agentID] == scene. Returning true in " + scene.RegionInfo.RegionName); - m_AgentRegions.Remove(agentID); - return true; - } - - // Another region has claimed the agent - // - //m_log.Debug("[INVTRANSFERMOD]: last resort. Returning false in " + scene.RegionInfo.RegionName); - return false; - } - - public void ClientLoggedOut(UUID agentID, Scene scene) - { - if (m_AgentRegions.ContainsKey(agentID)) - m_AgentRegions.Remove(agentID); - } +// public bool NeedSceneCacheClear(UUID agentID, Scene scene) +// { +// if (!m_AgentRegions.ContainsKey(agentID)) +// { +// // Since we can get here two ways, we need to scan +// // the scenes here. This is somewhat more expensive +// // but helps avoid a nasty bug +// // +// +// foreach (Scene s in m_Scenelist) +// { +// ScenePresence presence; +// +// if (s.TryGetScenePresence(agentID, out presence)) +// { +// // If the agent is in this scene, then we +// // are being called twice in a single +// // teleport. This is wasteful of cycles +// // but harmless due to this 2nd level check +// // +// // If the agent is found in another scene +// // then the list wasn't current +// // +// // If the agent is totally unknown, then what +// // are we even doing here?? +// // +// if (s == scene) +// { +// //m_log.Debug("[INVTRANSFERMOD]: s == scene. Returning true in " + scene.RegionInfo.RegionName); +// return true; +// } +// else +// { +// //m_log.Debug("[INVTRANSFERMOD]: s != scene. Returning false in " + scene.RegionInfo.RegionName); +// return false; +// } +// } +// } +// //m_log.Debug("[INVTRANSFERMOD]: agent not in scene. Returning true in " + scene.RegionInfo.RegionName); +// return true; +// } +// +// // The agent is left in current Scene, so we must be +// // going to another instance +// // +// if (m_AgentRegions[agentID] == scene) +// { +// //m_log.Debug("[INVTRANSFERMOD]: m_AgentRegions[agentID] == scene. Returning true in " + scene.RegionInfo.RegionName); +// m_AgentRegions.Remove(agentID); +// return true; +// } +// +// // Another region has claimed the agent +// // +// //m_log.Debug("[INVTRANSFERMOD]: last resort. Returning false in " + scene.RegionInfo.RegionName); +// return false; +// } +// +// public void ClientLoggedOut(UUID agentID, Scene scene) +// { +// if (m_AgentRegions.ContainsKey(agentID)) +// m_AgentRegions.Remove(agentID); +// } /// /// diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs index 90fe430..7498cfe 100644 --- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs +++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs @@ -672,13 +672,14 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer sp.Reset(); } - // REFACTORING PROBLEM. Well, not a problem, but this method is HORRIBLE! - if (sp.Scene.NeedSceneCacheClear(sp.UUID)) - { - m_log.DebugFormat( - "[ENTITY TRANSFER MODULE]: User {0} is going to another region, profile cache removed", - sp.UUID); - } + // Commented pending deletion since this method no longer appears to do anything at all +// // REFACTORING PROBLEM. Well, not a problem, but this method is HORRIBLE! +// if (sp.Scene.NeedSceneCacheClear(sp.UUID)) +// { +// m_log.DebugFormat( +// "[ENTITY TRANSFER MODULE]: User {0} is going to another region, profile cache removed", +// sp.UUID); +// } m_entityTransferStateMachine.ResetFromTransit(sp.UUID); } @@ -1237,14 +1238,14 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer AgentHasMovedAway(agent, false); - // the user may change their profile information in other region, - // so the userinfo in UserProfileCache is not reliable any more, delete it - // REFACTORING PROBLEM. Well, not a problem, but this method is HORRIBLE! - if (agent.Scene.NeedSceneCacheClear(agent.UUID)) - { - m_log.DebugFormat( - "[ENTITY TRANSFER MODULE]: User {0} is going to another region", agent.UUID); - } +// // the user may change their profile information in other region, +// // so the userinfo in UserProfileCache is not reliable any more, delete it +// // REFACTORING PROBLEM. Well, not a problem, but this method is HORRIBLE! +// if (agent.Scene.NeedSceneCacheClear(agent.UUID)) +// { +// m_log.DebugFormat( +// "[ENTITY TRANSFER MODULE]: User {0} is going to another region", agent.UUID); +// } //m_log.Debug("AFTER CROSS"); //Scene.DumpChildrenSeeds(UUID); diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 0f39671..9c61fe7 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -3435,9 +3435,10 @@ namespace OpenSim.Region.Framework.Scenes if (closeChildAgents && CapsModule != null) CapsModule.RemoveCaps(agentID); - // REFACTORING PROBLEM -- well not really a problem, but just to point out that whatever - // this method is doing is HORRIBLE!!! - avatar.Scene.NeedSceneCacheClear(avatar.UUID); +// // REFACTORING PROBLEM -- well not really a problem, but just to point out that whatever +// // this method is doing is HORRIBLE!!! + // Commented pending deletion since this method no longer appears to do anything at all +// avatar.Scene.NeedSceneCacheClear(avatar.UUID); if (closeChildAgents && !isChildAgent) { @@ -4873,14 +4874,15 @@ namespace OpenSim.Region.Framework.Scenes client.SendRegionHandle(regionID, handle); } - public bool NeedSceneCacheClear(UUID agentID) - { - IInventoryTransferModule inv = RequestModuleInterface(); - if (inv == null) - return true; - - return inv.NeedSceneCacheClear(agentID, this); - } +// Commented pending deletion since this method no longer appears to do anything at all +// public bool NeedSceneCacheClear(UUID agentID) +// { +// IInventoryTransferModule inv = RequestModuleInterface(); +// if (inv == null) +// return true; +// +// return inv.NeedSceneCacheClear(agentID, this); +// } public void CleanTempObjects() { -- cgit v1.1 From 01972cc9e8f3288330cdc7ba343b99be7f1491ec Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Tue, 23 Oct 2012 11:34:43 +0100 Subject: system ints can end up in LSL lists, which can cause counter-intuitive unknown list element type errors in ConvertFromLSL (via modInvoke) --- OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs | 2 ++ 1 file changed, 2 insertions(+) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs index a830a15..60bb107 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs @@ -359,6 +359,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api result[i] = (string)(LSL_String)plist[i]; else if (plist[i] is LSL_Integer) result[i] = (int)(LSL_Integer)plist[i]; + else if (plist[i] is int) + result[i] = plist[i]; else if (plist[i] is LSL_Float) result[i] = (float)(LSL_Float)plist[i]; else if (plist[i] is LSL_Key) -- cgit v1.1 From ecdb88679e6bb59da13da0f3994cc42d8e84a30d Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Tue, 23 Oct 2012 11:39:55 +0100 Subject: Removing the apparently superfluous explicit namespace reference so that the if-else-if-else block in ConvertFromLSL can have a consistent appearance --- .../Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs index 60bb107..a181dbe 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs @@ -366,15 +366,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api else if (plist[i] is LSL_Key) result[i] = new UUID((LSL_Key)plist[i]); else if (plist[i] is LSL_Rotation) - { - result[i] = (OpenMetaverse.Quaternion)( - (LSL_Rotation)plist[i]); - } + result[i] = (Quaternion)((LSL_Rotation)plist[i]); else if (plist[i] is LSL_Vector) - { - result[i] = (OpenMetaverse.Vector3)( - (LSL_Vector)plist[i]); - } + result[i] = (Vector3)((LSL_Vector)plist[i]); else MODError(String.Format("{0}: unknown LSL list element type", fname)); } -- cgit v1.1 From 1b3b7a61acf8784af3167a35c0f06eaeb413af9c Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 26 Oct 2012 01:50:46 +0100 Subject: minor: Add comment as to why we are pulcking plain old ints out of the LSL_List when converting values from LSL for modInvoke() --- OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs | 2 ++ 1 file changed, 2 insertions(+) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs index a181dbe..8f34833 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs @@ -359,6 +359,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api result[i] = (string)(LSL_String)plist[i]; else if (plist[i] is LSL_Integer) result[i] = (int)(LSL_Integer)plist[i]; + // The int check exists because of the many plain old int script constants in ScriptBase which + // are not LSL_Integers. else if (plist[i] is int) result[i] = plist[i]; else if (plist[i] is LSL_Float) -- cgit v1.1 From 18b1ee6f379f4d34f72a9056bf6cdf185311fd05 Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Tue, 23 Oct 2012 15:29:40 +0100 Subject: Formatting and casing correction in WorldCommModule, trailing new line in OSSL to get git diff to not complain --- OpenSim/Region/CoreModules/Scripting/WorldComm/WorldCommModule.cs | 6 +++--- OpenSim/Region/Framework/Interfaces/IWorldComm.cs | 2 +- OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/Scripting/WorldComm/WorldCommModule.cs b/OpenSim/Region/CoreModules/Scripting/WorldComm/WorldCommModule.cs index 8358bc0..c68ed6b 100644 --- a/OpenSim/Region/CoreModules/Scripting/WorldComm/WorldCommModule.cs +++ b/OpenSim/Region/CoreModules/Scripting/WorldComm/WorldCommModule.cs @@ -472,8 +472,8 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm if (coll.Count > 0) { - // special case, called with same filter settings, return same handle - // (2008-05-02, tested on 1.21.1 server, still holds) + // special case, called with same filter settings, return same + // handle (2008-05-02, tested on 1.21.1 server, still holds) return coll[0].GetHandle(); } @@ -712,7 +712,7 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm } } - public class ListenerInfo: IWorldCommListenerInfo + public class ListenerInfo : IWorldCommListenerInfo { private bool m_active; // Listener is active or not private int m_handle; // Assigned handle of this listener diff --git a/OpenSim/Region/Framework/Interfaces/IWorldComm.cs b/OpenSim/Region/Framework/Interfaces/IWorldComm.cs index 4e74781..8d88065 100644 --- a/OpenSim/Region/Framework/Interfaces/IWorldComm.cs +++ b/OpenSim/Region/Framework/Interfaces/IWorldComm.cs @@ -60,7 +60,7 @@ namespace OpenSim.Region.Framework.Interfaces /// the script during 'peek' time. Parameter hostID is needed to /// determine the position of the script. /// - /// localID of the script engine + /// localID of the script engine /// UUID of the script engine /// UUID of the SceneObjectPart /// channel to listen on diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs index 0811519..0650b90 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs @@ -3648,4 +3648,4 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api DropAttachmentAt(false, pos, rot); } } -} \ No newline at end of file +} -- cgit v1.1 From e977761071a2d614a9a621437fbf86479b414759 Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Tue, 23 Oct 2012 15:42:16 +0100 Subject: adding ability for listeners to be filtered by regular expressions and a general-purpose function to see if a given string matches a given regex --- .../Scripting/WorldComm/WorldCommModule.cs | 129 ++++++++++++++++++--- OpenSim/Region/Framework/Interfaces/IWorldComm.cs | 25 ++++ .../Shared/Api/Implementation/OSSL_Api.cs | 63 ++++++++++ .../ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs | 24 ++++ .../Shared/Api/Runtime/LSL_Constants.cs | 10 ++ .../ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs | 10 ++ 6 files changed, 242 insertions(+), 19 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/Scripting/WorldComm/WorldCommModule.cs b/OpenSim/Region/CoreModules/Scripting/WorldComm/WorldCommModule.cs index c68ed6b..cf0eb2a 100644 --- a/OpenSim/Region/CoreModules/Scripting/WorldComm/WorldCommModule.cs +++ b/OpenSim/Region/CoreModules/Scripting/WorldComm/WorldCommModule.cs @@ -28,6 +28,7 @@ using System; using System.Collections; using System.Collections.Generic; +using System.Text.RegularExpressions; using Nini.Config; using OpenMetaverse; using OpenSim.Framework; @@ -170,12 +171,42 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm /// UUID of the SceneObjectPart /// channel to listen on /// name to filter on - /// key to filter on (user given, could be totally faked) + /// + /// key to filter on (user given, could be totally faked) + /// /// msg to filter on /// number of the scripts handle - public int Listen(uint localID, UUID itemID, UUID hostID, int channel, string name, UUID id, string msg) + public int Listen(uint localID, UUID itemID, UUID hostID, int channel, + string name, UUID id, string msg) { - return m_listenerManager.AddListener(localID, itemID, hostID, channel, name, id, msg); + return m_listenerManager.AddListener(localID, itemID, hostID, + channel, name, id, msg); + } + + /// + /// Create a listen event callback with the specified filters. + /// The parameters localID,itemID are needed to uniquely identify + /// the script during 'peek' time. Parameter hostID is needed to + /// determine the position of the script. + /// + /// localID of the script engine + /// UUID of the script engine + /// UUID of the SceneObjectPart + /// channel to listen on + /// name to filter on + /// + /// key to filter on (user given, could be totally faked) + /// + /// msg to filter on + /// + /// Bitfield indicating which strings should be processed as regex. + /// + /// number of the scripts handle + public int Listen(uint localID, UUID itemID, UUID hostID, int channel, + string name, UUID id, string msg, int regexBitfield) + { + return m_listenerManager.AddListener(localID, itemID, hostID, + channel, name, id, msg, regexBitfield); } /// @@ -465,10 +496,20 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm m_curlisteners = 0; } - public int AddListener(uint localID, UUID itemID, UUID hostID, int channel, string name, UUID id, string msg) + public int AddListener(uint localID, UUID itemID, UUID hostID, + int channel, string name, UUID id, string msg) + { + return AddListener(localID, itemID, hostID, channel, name, id, + msg, 0); + } + + public int AddListener(uint localID, UUID itemID, UUID hostID, + int channel, string name, UUID id, string msg, + int regexBitfield) { // do we already have a match on this particular filter event? - List coll = GetListeners(itemID, channel, name, id, msg); + List coll = GetListeners(itemID, channel, name, id, + msg); if (coll.Count > 0) { @@ -485,7 +526,9 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm if (newHandle > 0) { - ListenerInfo li = new ListenerInfo(newHandle, localID, itemID, hostID, channel, name, id, msg); + ListenerInfo li = new ListenerInfo(newHandle, localID, + itemID, hostID, channel, name, id, msg, + regexBitfield); List listeners; if (!m_listeners.TryGetValue(channel,out listeners)) @@ -626,6 +669,22 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm return -1; } + /// These are duplicated from ScriptBaseClass + /// http://opensimulator.org/mantis/view.php?id=6106#c21945 + #region Constants for the bitfield parameter of osListenRegex + + /// + /// process name parameter as regex + /// + public const int OS_LISTEN_REGEX_NAME = 0x1; + + /// + /// process message parameter as regex + /// + public const int OS_LISTEN_REGEX_MESSAGE = 0x2; + + #endregion + // Theres probably a more clever and efficient way to // do this, maybe with regex. // PM2008: Ha, one could even be smart and define a specialized Enumerator. @@ -651,7 +710,10 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm { continue; } - if (li.GetName().Length > 0 && !li.GetName().Equals(name)) + if (li.GetName().Length > 0 && ( + ((li.GetRegexBitfield() & OS_LISTEN_REGEX_NAME) != OS_LISTEN_REGEX_NAME && !li.GetName().Equals(name)) || + ((li.GetRegexBitfield() & OS_LISTEN_REGEX_NAME) == OS_LISTEN_REGEX_NAME && !Regex.IsMatch(name, li.GetName())) + )) { continue; } @@ -659,7 +721,10 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm { continue; } - if (li.GetMessage().Length > 0 && !li.GetMessage().Equals(msg)) + if (li.GetMessage().Length > 0 && ( + ((li.GetRegexBitfield() & OS_LISTEN_REGEX_MESSAGE) != OS_LISTEN_REGEX_MESSAGE && !li.GetMessage().Equals(msg)) || + ((li.GetRegexBitfield() & OS_LISTEN_REGEX_MESSAGE) == OS_LISTEN_REGEX_MESSAGE && !Regex.IsMatch(msg, li.GetMessage())) + )) { continue; } @@ -692,10 +757,13 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm { int idx = 0; Object[] item = new Object[6]; + int dataItemLength = 6; while (idx < data.Length) { - Array.Copy(data, idx, item, 0, 6); + dataItemLength = (idx + 7 == data.Length || (idx + 7 < data.Length && data[idx + 7] is bool)) ? 7 : 6; + item = new Object[dataItemLength]; + Array.Copy(data, idx, item, 0, dataItemLength); ListenerInfo info = ListenerInfo.FromData(localID, itemID, hostID, item); @@ -707,7 +775,7 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm m_listeners[(int)item[2]].Add(info); } - idx+=6; + idx+=dataItemLength; } } } @@ -723,19 +791,33 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm private UUID m_id; // ID to filter messages from private string m_name; // Object name to filter messages from private string m_message; // The message + private int m_regexBitfield; // The regex bitfield public ListenerInfo(int handle, uint localID, UUID ItemID, UUID hostID, int channel, string name, UUID id, string message) { - Initialise(handle, localID, ItemID, hostID, channel, name, id, message); + Initialise(handle, localID, ItemID, hostID, channel, name, id, + message, 0); + } + + public ListenerInfo(int handle, uint localID, UUID ItemID, + UUID hostID, int channel, string name, UUID id, + string message, int regexBitfield) + { + Initialise(handle, localID, ItemID, hostID, channel, name, id, + message, regexBitfield); } public ListenerInfo(ListenerInfo li, string name, UUID id, string message) { - Initialise(li.m_handle, li.m_localID, li.m_itemID, li.m_hostID, li.m_channel, name, id, message); + Initialise(li.m_handle, li.m_localID, li.m_itemID, li.m_hostID, li.m_channel, name, id, message, 0); + } + + public ListenerInfo(ListenerInfo li, string name, UUID id, string message, int regexBitfield) + { + Initialise(li.m_handle, li.m_localID, li.m_itemID, li.m_hostID, li.m_channel, name, id, message, regexBitfield); } - private void Initialise(int handle, uint localID, UUID ItemID, UUID hostID, int channel, string name, - UUID id, string message) + private void Initialise(int handle, uint localID, UUID ItemID, UUID hostID, int channel, string name, UUID id, string message, int regexBitfield) { m_active = true; m_handle = handle; @@ -746,11 +828,12 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm m_name = name; m_id = id; m_message = message; + m_regexBitfield = regexBitfield; } public Object[] GetSerializationData() { - Object[] data = new Object[6]; + Object[] data = new Object[7]; data[0] = m_active; data[1] = m_handle; @@ -758,16 +841,19 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm data[3] = m_name; data[4] = m_id; data[5] = m_message; + data[6] = m_regexBitfield; return data; } public static ListenerInfo FromData(uint localID, UUID ItemID, UUID hostID, Object[] data) { - ListenerInfo linfo = new ListenerInfo((int)data[1], localID, - ItemID, hostID, (int)data[2], (string)data[3], - (UUID)data[4], (string)data[5]); - linfo.m_active=(bool)data[0]; + ListenerInfo linfo = new ListenerInfo((int)data[1], localID, ItemID, hostID, (int)data[2], (string)data[3], (UUID)data[4], (string)data[5]); + linfo.m_active = (bool)data[0]; + if (data.Length >= 7) + { + linfo.m_regexBitfield = (int)data[6]; + } return linfo; } @@ -826,5 +912,10 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm { return m_id; } + + public int GetRegexBitfield() + { + return m_regexBitfield; + } } } diff --git a/OpenSim/Region/Framework/Interfaces/IWorldComm.cs b/OpenSim/Region/Framework/Interfaces/IWorldComm.cs index 8d88065..66b3f3a 100644 --- a/OpenSim/Region/Framework/Interfaces/IWorldComm.cs +++ b/OpenSim/Region/Framework/Interfaces/IWorldComm.cs @@ -45,6 +45,14 @@ namespace OpenSim.Region.Framework.Interfaces void Deactivate(); void Activate(); UUID GetID(); + + /// + /// Bitfield indicating which strings should be processed as regex. + /// 1 corresponds to IWorldCommListenerInfo::GetName() + /// 2 corresponds to IWorldCommListenerInfo::GetMessage() + /// + /// + int GetRegexBitfield(); } public interface IWorldComm @@ -70,6 +78,23 @@ namespace OpenSim.Region.Framework.Interfaces /// number of the scripts handle int Listen(uint LocalID, UUID itemID, UUID hostID, int channel, string name, UUID id, string msg); + /// + /// Create a listen event callback with the specified filters. + /// The parameters localID,itemID are needed to uniquely identify + /// the script during 'peek' time. Parameter hostID is needed to + /// determine the position of the script. + /// + /// localID of the script engine + /// UUID of the script engine + /// UUID of the SceneObjectPart + /// channel to listen on + /// name to filter on + /// key to filter on (user given, could be totally faked) + /// msg to filter on + /// Bitfield indicating which strings should be processed as regex. + /// number of the scripts handle + int Listen(uint LocalID, UUID itemID, UUID hostID, int channel, string name, UUID id, string msg, int regexBitfield); + /// /// This method scans over the objects which registered an interest in listen callbacks. /// For everyone it finds, it checks if it fits the given filter. If it does, then diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs index 0650b90..828288d 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs @@ -3647,5 +3647,68 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api DropAttachmentAt(false, pos, rot); } + + public LSL_Integer osListenRegex(int channelID, string name, string ID, string msg, int regexBitfield) + { + CheckThreatLevel(ThreatLevel.Low, "osListenRegex"); + m_host.AddScriptLPS(1); + UUID keyID; + UUID.TryParse(ID, out keyID); + + // if we want the name to be used as a regular expression, ensure it is valid first. + if ((regexBitfield & ScriptBaseClass.OS_LISTEN_REGEX_NAME) == ScriptBaseClass.OS_LISTEN_REGEX_NAME) + { + try + { + Regex.IsMatch("", name); + } + catch (Exception) + { + OSSLShoutError("Name regex is invalid."); + return -1; + } + } + + // if we want the msg to be used as a regular expression, ensure it is valid first. + if ((regexBitfield & ScriptBaseClass.OS_LISTEN_REGEX_MESSAGE) == ScriptBaseClass.OS_LISTEN_REGEX_MESSAGE) + { + try + { + Regex.IsMatch("", msg); + } + catch (Exception) + { + OSSLShoutError("Message regex is invalid."); + return -1; + } + } + + IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface(); + return (wComm == null) ? -1 : wComm.Listen( + m_host.LocalId, + m_item.ItemID, + m_host.UUID, + channelID, + name, + keyID, + msg, + regexBitfield + ); + } + + public LSL_Integer osRegexIsMatch(string input, string pattern) + { + CheckThreatLevel(ThreatLevel.Low, "osRegexIsMatch"); + m_host.AddScriptLPS(1); + try + { + return Regex.IsMatch(input, pattern) ? 1 : 0; + } + catch (Exception) + { + OSSLShoutError("Possible invalid regular expression detected."); + return 0; + } + } } } diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs index 93188c9..cdd9ea8 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs @@ -418,5 +418,29 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces /// /// void osForceDropAttachmentAt(vector pos, rotation rot); + + /// + /// Identical to llListen except for a bitfield which indicates which + /// string parameters should be parsed as regex patterns. + /// + /// + /// + /// + /// + /// + /// OS_LISTEN_REGEX_NAME + /// OS_LISTEN_REGEX_MESSAGE + /// + /// + LSL_Integer osListenRegex(int channelID, string name, string ID, + string msg, int regexBitfield); + + /// + /// Wraps to bool Regex.IsMatch(string input, string pattern) + /// + /// string to test for match + /// string to use as pattern + /// boolean + LSL_Integer osRegexIsMatch(string input, string pattern); } } diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs index 62bd6b8..880841b 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs @@ -716,5 +716,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase public static readonly LSLInteger RCERR_UNKNOWN = -1; public static readonly LSLInteger RCERR_SIM_PERF_LOW = -2; public static readonly LSLInteger RCERR_CAST_TIME_EXCEEDED = 3; + + /// + /// process name parameter as regex + /// + public const int OS_LISTEN_REGEX_NAME = 0x1; + + /// + /// process message parameter as regex + /// + public const int OS_LISTEN_REGEX_MESSAGE = 0x2; } } diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs index dee1b28..afa9ae0 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs @@ -992,5 +992,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase { m_OSSL_Functions.osForceDropAttachmentAt(pos, rot); } + + public LSL_Integer osListenRegex(int channelID, string name, string ID, string msg, int regexBitfield) + { + return m_OSSL_Functions.osListenRegex(channelID, name, ID, msg, regexBitfield); + } + + public LSL_Integer osRegexIsMatch(string input, string pattern) + { + return m_OSSL_Functions.osRegexIsMatch(input, pattern); + } } } -- cgit v1.1 From 80dcc13af2b33a5621bac49f15cbf6a97d2d8e16 Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Tue, 23 Oct 2012 16:02:31 +0100 Subject: refactoring IWorldCommListenerInfo.GetRegexBitfield() method to be a field with a private setter --- .../Scripting/WorldComm/WorldCommModule.cs | 20 ++++++++------------ OpenSim/Region/Framework/Interfaces/IWorldComm.cs | 3 +-- 2 files changed, 9 insertions(+), 14 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/Scripting/WorldComm/WorldCommModule.cs b/OpenSim/Region/CoreModules/Scripting/WorldComm/WorldCommModule.cs index cf0eb2a..401ff6c 100644 --- a/OpenSim/Region/CoreModules/Scripting/WorldComm/WorldCommModule.cs +++ b/OpenSim/Region/CoreModules/Scripting/WorldComm/WorldCommModule.cs @@ -711,8 +711,8 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm continue; } if (li.GetName().Length > 0 && ( - ((li.GetRegexBitfield() & OS_LISTEN_REGEX_NAME) != OS_LISTEN_REGEX_NAME && !li.GetName().Equals(name)) || - ((li.GetRegexBitfield() & OS_LISTEN_REGEX_NAME) == OS_LISTEN_REGEX_NAME && !Regex.IsMatch(name, li.GetName())) + ((li.RegexBitfield & OS_LISTEN_REGEX_NAME) != OS_LISTEN_REGEX_NAME && !li.GetName().Equals(name)) || + ((li.RegexBitfield & OS_LISTEN_REGEX_NAME) == OS_LISTEN_REGEX_NAME && !Regex.IsMatch(name, li.GetName())) )) { continue; @@ -722,8 +722,8 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm continue; } if (li.GetMessage().Length > 0 && ( - ((li.GetRegexBitfield() & OS_LISTEN_REGEX_MESSAGE) != OS_LISTEN_REGEX_MESSAGE && !li.GetMessage().Equals(msg)) || - ((li.GetRegexBitfield() & OS_LISTEN_REGEX_MESSAGE) == OS_LISTEN_REGEX_MESSAGE && !Regex.IsMatch(msg, li.GetMessage())) + ((li.RegexBitfield & OS_LISTEN_REGEX_MESSAGE) != OS_LISTEN_REGEX_MESSAGE && !li.GetMessage().Equals(msg)) || + ((li.RegexBitfield & OS_LISTEN_REGEX_MESSAGE) == OS_LISTEN_REGEX_MESSAGE && !Regex.IsMatch(msg, li.GetMessage())) )) { continue; @@ -791,7 +791,6 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm private UUID m_id; // ID to filter messages from private string m_name; // Object name to filter messages from private string m_message; // The message - private int m_regexBitfield; // The regex bitfield public ListenerInfo(int handle, uint localID, UUID ItemID, UUID hostID, int channel, string name, UUID id, string message) { @@ -828,7 +827,7 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm m_name = name; m_id = id; m_message = message; - m_regexBitfield = regexBitfield; + RegexBitfield = regexBitfield; } public Object[] GetSerializationData() @@ -841,7 +840,7 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm data[3] = m_name; data[4] = m_id; data[5] = m_message; - data[6] = m_regexBitfield; + data[6] = RegexBitfield; return data; } @@ -852,7 +851,7 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm linfo.m_active = (bool)data[0]; if (data.Length >= 7) { - linfo.m_regexBitfield = (int)data[6]; + linfo.RegexBitfield = (int)data[6]; } return linfo; @@ -913,9 +912,6 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm return m_id; } - public int GetRegexBitfield() - { - return m_regexBitfield; - } + public int RegexBitfield { get; private set; } } } diff --git a/OpenSim/Region/Framework/Interfaces/IWorldComm.cs b/OpenSim/Region/Framework/Interfaces/IWorldComm.cs index 66b3f3a..d76a0d7 100644 --- a/OpenSim/Region/Framework/Interfaces/IWorldComm.cs +++ b/OpenSim/Region/Framework/Interfaces/IWorldComm.cs @@ -51,8 +51,7 @@ namespace OpenSim.Region.Framework.Interfaces /// 1 corresponds to IWorldCommListenerInfo::GetName() /// 2 corresponds to IWorldCommListenerInfo::GetMessage() /// - /// - int GetRegexBitfield(); + int RegexBitfield { get; } } public interface IWorldComm -- cgit v1.1 From 16809bd0eada0e5bd0f4dbf823cbd27ae212e037 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 26 Oct 2012 02:36:58 +0100 Subject: minor: Make the error thrown logged when a simulator in grid mode is trying to set estate owner to a user that doesn't exist a little more obvious. --- OpenSim/Region/Application/OpenSimBase.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Application/OpenSimBase.cs b/OpenSim/Region/Application/OpenSimBase.cs index 4f1b439..7b591a8 100644 --- a/OpenSim/Region/Application/OpenSimBase.cs +++ b/OpenSim/Region/Application/OpenSimBase.cs @@ -543,7 +543,7 @@ namespace OpenSim if (account == null) { m_log.ErrorFormat( - "[OPENSIM]: Unable to store account. If this simulator is connected to a grid, you must create the estate owner account first."); + "[OPENSIM]: Unable to store account. If this simulator is connected to a grid, you must create the estate owner account first at the grid level."); } else { -- cgit v1.1 From de6f147d3c2f178b47c4fffddb85925f75e6d88f Mon Sep 17 00:00:00 2001 From: Melanie Date: Fri, 26 Oct 2012 21:16:27 +0100 Subject: Revert "Fix for Mantis 0006376: Avatar no longer show Walking animation when any AO hud is" This reverts commit fa484c3494a7190b4d7526094347be74d091e125. --- OpenSim/Region/Framework/Scenes/Animation/AnimationSet.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Framework/Scenes/Animation/AnimationSet.cs b/OpenSim/Region/Framework/Scenes/Animation/AnimationSet.cs index 9ed4f47..ad421ee 100644 --- a/OpenSim/Region/Framework/Scenes/Animation/AnimationSet.cs +++ b/OpenSim/Region/Framework/Scenes/Animation/AnimationSet.cs @@ -87,7 +87,7 @@ namespace OpenSim.Region.Framework.Scenes.Animation { if (m_defaultAnimation.AnimID == animID) { - m_defaultAnimation = new OpenSim.Framework.Animation(animID, 1, UUID.Zero); + m_defaultAnimation = new OpenSim.Framework.Animation(UUID.Zero, 1, UUID.Zero); } else if (HasAnimation(animID)) { -- cgit v1.1 From 1c5f6e48b80e15f97c8203f3db0df6745c7a2283 Mon Sep 17 00:00:00 2001 From: Melanie Date: Fri, 26 Oct 2012 21:23:20 +0100 Subject: Separate LSL's notion of the default anim from the actually playing anims. --- OpenSim/Region/Framework/Scenes/Animation/AnimationSet.cs | 6 ++++-- OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 6 +++--- 2 files changed, 7 insertions(+), 5 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Framework/Scenes/Animation/AnimationSet.cs b/OpenSim/Region/Framework/Scenes/Animation/AnimationSet.cs index ad421ee..3d8e8be 100644 --- a/OpenSim/Region/Framework/Scenes/Animation/AnimationSet.cs +++ b/OpenSim/Region/Framework/Scenes/Animation/AnimationSet.cs @@ -41,12 +41,13 @@ namespace OpenSim.Region.Framework.Scenes.Animation { // private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + private OpenSim.Framework.Animation m_implicitDefaultAnimation = new OpenSim.Framework.Animation(); private OpenSim.Framework.Animation m_defaultAnimation = new OpenSim.Framework.Animation(); private List m_animations = new List(); - public OpenSim.Framework.Animation DefaultAnimation + public OpenSim.Framework.Animation ImplicitDefaultAnimation { - get { return m_defaultAnimation; } + get { return m_implicitDefaultAnimation; } } public AnimationSet() @@ -119,6 +120,7 @@ namespace OpenSim.Region.Framework.Scenes.Animation if (m_defaultAnimation.AnimID != animID) { m_defaultAnimation = new OpenSim.Framework.Animation(animID, sequenceNum, objectID); + m_implicitDefaultAnimation = m_defaultAnimation; return true; } return false; diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index dc791d3..fa57845 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -4388,7 +4388,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { AnimationSet currentAnims = presence.Animator.Animations; string currentAnimationState = String.Empty; - if (animationstateNames.TryGetValue(currentAnims.DefaultAnimation.AnimID, out currentAnimationState)) + if (animationstateNames.TryGetValue(currentAnims.ImplicitDefaultAnimation.AnimID, out currentAnimationState)) return currentAnimationState; } } @@ -5705,7 +5705,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api flags |= ScriptBaseClass.AGENT_SITTING; } - if (agent.Animator.Animations.DefaultAnimation.AnimID + if (agent.Animator.Animations.ImplicitDefaultAnimation.AnimID == DefaultAvatarAnimations.AnimsUUID["SIT_GROUND_CONSTRAINED"]) { flags |= ScriptBaseClass.AGENT_SITTING; @@ -7892,7 +7892,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { LSL_Vector lower; LSL_Vector upper; - if (presence.Animator.Animations.DefaultAnimation.AnimID + if (presence.Animator.Animations.ImplicitDefaultAnimation.AnimID == DefaultAvatarAnimations.AnimsUUID["SIT_GROUND_CONSTRAINED"]) { // This is for ground sitting avatars -- cgit v1.1 From 67432fcbf2b9ad58e83eb55f789c28ffd9ab572b Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 26 Oct 2012 23:08:59 +0100 Subject: Fix "save iar" hanging permanently if the asset request phase times out. Unlike "save oar", this was happening on the same thread as the original request. The timeout happens on another so the original thread is never aborted. On "save oar" this leaves the thread hanging (still bad) but on "save iar" it left the console thread hanging. Temporary fix is to make "save iar" do asset request on a separate thread, like "save oar". Longer term fix will be to restructure asset save to use a ManualResetEvent rather than a separate timeout timer. --- .../Archiver/InventoryArchiveWriteRequest.cs | 13 ++++++----- .../Archiver/Tests/InventoryArchiveTestCase.cs | 26 ++++++++++++++++------ .../Archiver/Tests/InventoryArchiverTests.cs | 4 ++-- .../CoreModules/World/Archiver/AssetsRequest.cs | 4 ++++ 4 files changed, 33 insertions(+), 14 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs index 6587ead..d13b4a0 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs @@ -337,11 +337,14 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver { m_log.DebugFormat("[INVENTORY ARCHIVER]: Saving {0} assets for items", m_assetUuids.Count); - new AssetsRequest( - new AssetsArchiver(m_archiveWriter), - m_assetUuids, m_scene.AssetService, - m_scene.UserAccountService, m_scene.RegionInfo.ScopeID, - options, ReceivedAllAssets).Execute(); + AssetsRequest ar + = new AssetsRequest( + new AssetsArchiver(m_archiveWriter), + m_assetUuids, m_scene.AssetService, + m_scene.UserAccountService, m_scene.RegionInfo.ScopeID, + options, ReceivedAllAssets); + + Util.FireAndForget(o => ar.Execute()); } else { diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveTestCase.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveTestCase.cs index 1056865..00727a4 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveTestCase.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveTestCase.cs @@ -82,7 +82,25 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests protected string m_item1Name = "Ray Gun Item"; protected string m_coaItemName = "Coalesced Item"; - + + [TestFixtureSetUp] + public void FixtureSetup() + { + // Don't allow tests to be bamboozled by asynchronous events. Execute everything on the same thread. + Util.FireAndForgetMethod = FireAndForgetMethod.RegressionTest; + + ConstructDefaultIarBytesForTestLoad(); + } + + [TestFixtureTearDown] + public void TearDown() + { + // We must set this back afterwards, otherwise later tests will fail since they're expecting multiple + // threads. Possibly, later tests should be rewritten so none of them require async stuff (which regression + // tests really shouldn't). + Util.FireAndForgetMethod = Util.DefaultFireAndForgetMethod; + } + [SetUp] public override void SetUp() { @@ -90,12 +108,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests m_iarStream = new MemoryStream(m_iarStreamBytes); } - [TestFixtureSetUp] - public void FixtureSetup() - { - ConstructDefaultIarBytesForTestLoad(); - } - protected void ConstructDefaultIarBytesForTestLoad() { // log4net.Config.XmlConfigurator.Configure(); diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs index 12a05b3..06f6e49 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs @@ -49,7 +49,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests { [TestFixture] public class InventoryArchiverTests : InventoryArchiveTestCase - { + { protected TestScene m_scene; protected InventoryArchiverModule m_archiverModule; @@ -69,7 +69,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests public void TestLoadCoalesecedItem() { TestHelpers.InMethod(); -// log4net.Config.XmlConfigurator.Configure(); +// TestHelpers.EnableLogging(); UserAccountHelpers.CreateUserWithInventory(m_scene, m_uaLL1, "password"); m_archiverModule.DearchiveInventory(m_uaLL1.FirstName, m_uaLL1.LastName, "/", "password", m_iarStream); diff --git a/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs index 5787279..103eb47 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs @@ -129,6 +129,10 @@ namespace OpenSim.Region.CoreModules.World.Archiver m_options = options; m_repliesRequired = uuids.Count; + // FIXME: This is a really poor way of handling the timeout since it will always leave the original requesting thread + // hanging. Need to restructure so an original request thread waits for a ManualResetEvent on asset received + // so we can properly abort that thread. Or request all assets synchronously, though that would be a more + // radical change m_requestCallbackTimer = new System.Timers.Timer(TIMEOUT); m_requestCallbackTimer.AutoReset = false; m_requestCallbackTimer.Elapsed += new ElapsedEventHandler(OnRequestCallbackTimeout); -- cgit v1.1 From 3531f29a6a81cd9106080a38d68a4b8b0e347db5 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Sat, 27 Oct 2012 00:24:25 +0100 Subject: minor: Fix verbose IAR save message to make it a bit clearer that item data is being saved at that point, not asset data. --- .../Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs index d13b4a0..d0e88f6 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs @@ -166,7 +166,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver if (options.ContainsKey("verbose")) m_log.InfoFormat( - "[INVENTORY ARCHIVER]: Saving item {0} {1} with asset {2}", + "[INVENTORY ARCHIVER]: Saving item {0} {1} (asset UUID {2})", inventoryItem.ID, inventoryItem.Name, inventoryItem.AssetID); string filename = path + CreateArchiveItemName(inventoryItem); -- cgit v1.1 From 5a96ef52cb552c835cc109cb005db989eade5803 Mon Sep 17 00:00:00 2001 From: Melanie Date: Sun, 28 Oct 2012 18:41:47 +0000 Subject: Deep copy the collection of at_target objects so it can't be modified while it's being iterated --- OpenSim/Region/Framework/Scenes/Scene.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 9c61fe7..2cdc4b3 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -1692,9 +1692,12 @@ namespace OpenSim.Region.Framework.Scenes private void CheckAtTargets() { - Dictionary.ValueCollection objs; + List objs = new List(); lock (m_groupsWithTargets) - objs = m_groupsWithTargets.Values; + { + foreach (SceneObjectGroup grp in m_groupsWithTargets.Values) + objs.Add(grp); + } foreach (SceneObjectGroup entry in objs) entry.checkAtTargets(); -- cgit v1.1 From c97890ca69df91e6590ac7dd234a3e86cf7fbaf1 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Mon, 29 Oct 2012 22:53:06 +0000 Subject: Add "force gc" region console command which manually invokes garbage collection. For debugging purposes. --- OpenSim/Region/Framework/Scenes/ScenePresence.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index b6d0a3b..aa82af4 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -74,8 +74,9 @@ namespace OpenSim.Region.Framework.Scenes { // ~ScenePresence() // { -// m_log.Debug("[SCENE PRESENCE] Destructor called"); +// m_log.DebugFormat("[SCENE PRESENCE]: Destructor called on {0}", Name); // } + private void TriggerScenePresenceUpdated() { if (m_scene != null) -- cgit v1.1 From 09f4e72d6af4b86238af516b1719ff4f63aa7174 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Mon, 29 Oct 2012 23:22:40 +0000 Subject: Fix memory leak where removing an NPC did not remove its circuits. This was because we were removing by circuitcode where NPCs have no code. Now removing by agent ID instead. This commit also fixes the "show circuits" console command to work properly where the circuit has no associated IP address. --- OpenSim/Region/Application/OpenSim.cs | 2 +- OpenSim/Region/Framework/Scenes/Scene.cs | 5 +++-- .../Region/OptionalModules/World/NPC/Tests/NPCModuleTests.cs | 11 +++++++++++ 3 files changed, 15 insertions(+), 3 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Application/OpenSim.cs b/OpenSim/Region/Application/OpenSim.cs index b24641a..2236e43 100644 --- a/OpenSim/Region/Application/OpenSim.cs +++ b/OpenSim/Region/Application/OpenSim.cs @@ -1111,7 +1111,7 @@ namespace OpenSim aCircuit.Name, aCircuit.child ? "child" : "root", aCircuit.circuitcode.ToString(), - aCircuit.IPAddress.ToString(), + aCircuit.IPAddress != null ? aCircuit.IPAddress.ToString() : "not set", aCircuit.Viewer); }); diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 2cdc4b3..7d8cbf5 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -3384,9 +3384,10 @@ namespace OpenSim.Region.Framework.Scenes } else { - // We remove the acd up here to avoid later raec conditions if two RemoveClient() calls occurred + // We remove the acd up here to avoid later race conditions if two RemoveClient() calls occurred // simultaneously. - m_authenticateHandler.RemoveCircuit(acd.circuitcode); + // We also need to remove by agent ID since NPCs will have no circuit code. + m_authenticateHandler.RemoveCircuit(agentID); } } diff --git a/OpenSim/Region/OptionalModules/World/NPC/Tests/NPCModuleTests.cs b/OpenSim/Region/OptionalModules/World/NPC/Tests/NPCModuleTests.cs index 9179966..52ed846 100644 --- a/OpenSim/Region/OptionalModules/World/NPC/Tests/NPCModuleTests.cs +++ b/OpenSim/Region/OptionalModules/World/NPC/Tests/NPCModuleTests.cs @@ -117,6 +117,12 @@ namespace OpenSim.Region.OptionalModules.World.NPC.Tests Assert.That(npc, Is.Not.Null); Assert.That(npc.Appearance.Texture.FaceTextures[8].TextureID, Is.EqualTo(originalFace8TextureId)); Assert.That(m_umMod.GetUserName(npc.UUID), Is.EqualTo(string.Format("{0} {1}", npc.Firstname, npc.Lastname))); + + IClientAPI client; + Assert.That(m_scene.TryGetClient(npcId, out client), Is.True); + + // Have to account for both SP and NPC. + Assert.That(m_scene.AuthenticateHandler.GetAgentCircuits().Count, Is.EqualTo(2)); } [Test] @@ -136,6 +142,11 @@ namespace OpenSim.Region.OptionalModules.World.NPC.Tests ScenePresence deletedNpc = m_scene.GetScenePresence(npcId); Assert.That(deletedNpc, Is.Null); + IClientAPI client; + Assert.That(m_scene.TryGetClient(npcId, out client), Is.False); + + // Have to account for SP still present. + Assert.That(m_scene.AuthenticateHandler.GetAgentCircuits().Count, Is.EqualTo(1)); } [Test] -- cgit v1.1 From 7560010f340e9e67e0fb87d0e3863ed69bdbedf1 Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Thu, 4 Oct 2012 11:33:21 +0100 Subject: Immediately setting gain to zero as a workaround for code not stopping sound started by llPlaySound --- OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 1 + 1 file changed, 1 insertion(+) (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 fa57845..bedcd85 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -2452,6 +2452,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public void llStopSound() { m_host.AddScriptLPS(1); + m_host.AdjustSoundGain(0); if (m_host.ParentGroup.LoopSoundSlavePrims.Contains(m_host)) { if (m_host.ParentGroup.LoopSoundMasterPrim == m_host) -- cgit v1.1 From ed162a10beaa8bcab1c51f03a51acf5a9537eaae Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Fri, 5 Oct 2012 13:50:12 +0100 Subject: Converting the ISoundModule implementation from an IRegionModule to an INonSharedRegionModule --- .../Region/CoreModules/World/Sound/SoundModule.cs | 141 ---------------- .../World/Sound/SoundModuleNonShared.cs | 179 +++++++++++++++++++++ 2 files changed, 179 insertions(+), 141 deletions(-) delete mode 100644 OpenSim/Region/CoreModules/World/Sound/SoundModule.cs create mode 100644 OpenSim/Region/CoreModules/World/Sound/SoundModuleNonShared.cs (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/World/Sound/SoundModule.cs b/OpenSim/Region/CoreModules/World/Sound/SoundModule.cs deleted file mode 100644 index a2f0950..0000000 --- a/OpenSim/Region/CoreModules/World/Sound/SoundModule.cs +++ /dev/null @@ -1,141 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using Nini.Config; -using OpenMetaverse; -using OpenSim.Framework; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; -using System.Reflection; -using log4net; - -namespace OpenSim.Region.CoreModules.World.Sound -{ - public class SoundModule : IRegionModule, ISoundModule - { -// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - protected Scene m_scene; - - public void Initialise(Scene scene, IConfigSource source) - { - m_scene = scene; - - m_scene.EventManager.OnNewClient += OnNewClient; - - m_scene.RegisterModuleInterface(this); - } - - public void PostInitialise() {} - public void Close() {} - public string Name { get { return "Sound Module"; } } - public bool IsSharedModule { get { return false; } } - - private void OnNewClient(IClientAPI client) - { - client.OnSoundTrigger += TriggerSound; - } - - public virtual void PlayAttachedSound( - UUID soundID, UUID ownerID, UUID objectID, double gain, Vector3 position, byte flags, float radius) - { - SceneObjectPart part = m_scene.GetSceneObjectPart(objectID); - if (part == null) - return; - - SceneObjectGroup grp = part.ParentGroup; - - m_scene.ForEachRootScenePresence(delegate(ScenePresence sp) - { - double dis = Util.GetDistanceTo(sp.AbsolutePosition, position); - if (dis > 100.0) // Max audio distance - return; - - if (grp.IsAttachment) - { - if (grp.HasPrivateAttachmentPoint && sp.ControllingClient.AgentId != grp.OwnerID) - return; - - if (sp.ControllingClient.AgentId == grp.OwnerID) - dis = 0; - } - - float thisSpGain; - - // Scale by distance - if (radius == 0) - thisSpGain = (float)((double)gain * ((100.0 - dis) / 100.0)); - else - thisSpGain = (float)((double)gain * ((radius - dis) / radius)); - - sp.ControllingClient.SendPlayAttachedSound(soundID, objectID, ownerID, thisSpGain, flags); - }); - } - - public virtual void TriggerSound( - UUID soundId, UUID ownerID, UUID objectID, UUID parentID, double gain, Vector3 position, UInt64 handle, float radius) - { - SceneObjectPart part = m_scene.GetSceneObjectPart(objectID); - if (part == null) - { - ScenePresence sp; - if (!m_scene.TryGetScenePresence(objectID, out sp)) - return; - } - else - { - SceneObjectGroup grp = part.ParentGroup; - - if (grp.IsAttachment && grp.AttachmentPoint > 30) - { - objectID = ownerID; - parentID = ownerID; - } - } - - m_scene.ForEachRootScenePresence(delegate(ScenePresence sp) - { - double dis = Util.GetDistanceTo(sp.AbsolutePosition, position); - - if (dis > 100.0) // Max audio distance - return; - - float thisSpGain; - - // Scale by distance - if (radius == 0) - thisSpGain = (float)((double)gain * ((100.0 - dis) / 100.0)); - else - thisSpGain = (float)((double)gain * ((radius - dis) / radius)); - - sp.ControllingClient.SendTriggeredSound( - soundId, ownerID, objectID, parentID, handle, position, thisSpGain); - }); - } - } -} diff --git a/OpenSim/Region/CoreModules/World/Sound/SoundModuleNonShared.cs b/OpenSim/Region/CoreModules/World/Sound/SoundModuleNonShared.cs new file mode 100644 index 0000000..9fd0a36 --- /dev/null +++ b/OpenSim/Region/CoreModules/World/Sound/SoundModuleNonShared.cs @@ -0,0 +1,179 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +using System; +using System.Reflection; + +using Nini.Config; +using OpenMetaverse; +using log4net; +using Mono.Addins; + +using OpenSim.Framework; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; + +namespace OpenSim.Region.CoreModules.World.Sound +{ + [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "SoundModuleNonShared")] + public class SoundModuleNonShared : INonSharedRegionModule, ISoundModule + { + private static readonly ILog m_log = LogManager.GetLogger( + MethodBase.GetCurrentMethod().DeclaringType); + + private Scene m_scene; + + public bool Enabled { get; private set; } + + #region INonSharedRegionModule + + public void Initialise(IConfigSource configSource) + { + IConfig config = configSource.Configs["Sounds"]; + + Enabled = (config != null && config.GetString("Module", "SoundModuleNonShared") == "SoundModuleNonShared"); + } + + public void AddRegion(Scene scene) { } + + public void RemoveRegion(Scene scene) + { + m_scene.EventManager.OnClientLogin -= OnNewClient; + } + + public void RegionLoaded(Scene scene) + { + if (!Enabled) + return; + + m_scene = scene; + m_scene.EventManager.OnClientLogin += OnNewClient; + + m_scene.RegisterModuleInterface(this); + } + + public void Close() { } + + public Type ReplaceableInterface + { + get { return typeof(ISoundModule); } + } + + public string Name { get { return "Sound Module"; } } + + #endregion + + #region Event Handlers + + private void OnNewClient(IClientAPI client) + { + client.OnSoundTrigger += TriggerSound; + } + + #endregion + + #region ISoundModule + + public virtual void PlayAttachedSound( + UUID soundID, UUID ownerID, UUID objectID, double gain, Vector3 position, byte flags, float radius) + { + SceneObjectPart part = m_scene.GetSceneObjectPart(objectID); + if (part == null) + return; + + SceneObjectGroup grp = part.ParentGroup; + + m_scene.ForEachRootScenePresence(delegate(ScenePresence sp) + { + double dis = Util.GetDistanceTo(sp.AbsolutePosition, position); + if (dis > 100.0) // Max audio distance + return; + + if (grp.IsAttachment) + { + if (grp.HasPrivateAttachmentPoint && sp.ControllingClient.AgentId != grp.OwnerID) + return; + + if (sp.ControllingClient.AgentId == grp.OwnerID) + dis = 0; + } + + float thisSpGain; + + // Scale by distance + if (radius == 0) + thisSpGain = (float)((double)gain * ((100.0 - dis) / 100.0)); + else + thisSpGain = (float)((double)gain * ((radius - dis) / radius)); + + sp.ControllingClient.SendPlayAttachedSound(soundID, objectID, ownerID, thisSpGain, flags); + }); + } + + public virtual void TriggerSound( + UUID soundId, UUID ownerID, UUID objectID, UUID parentID, double gain, Vector3 position, UInt64 handle, float radius) + { + SceneObjectPart part = m_scene.GetSceneObjectPart(objectID); + if (part == null) + { + ScenePresence sp; + if (!m_scene.TryGetScenePresence(objectID, out sp)) + return; + } + else + { + SceneObjectGroup grp = part.ParentGroup; + + if (grp.IsAttachment && grp.AttachmentPoint > 30) + { + objectID = ownerID; + parentID = ownerID; + } + } + + m_scene.ForEachRootScenePresence(delegate(ScenePresence sp) + { + double dis = Util.GetDistanceTo(sp.AbsolutePosition, position); + + if (dis > 100.0) // Max audio distance + return; + + float thisSpGain; + + // Scale by distance + if (radius == 0) + thisSpGain = (float)((double)gain * ((100.0 - dis) / 100.0)); + else + thisSpGain = (float)((double)gain * ((radius - dis) / radius)); + + sp.ControllingClient.SendTriggeredSound( + soundId, ownerID, objectID, parentID, handle, position, thisSpGain); + }); + } + + #endregion + } +} -- cgit v1.1 From 375fb6658909f619f3210590743c228834d0d2c0 Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Fri, 5 Oct 2012 14:01:29 +0100 Subject: making the max distance for sounds to be heard from their origin a configurable option exposed via a public field on ISoundModule (with private setter in the implementation) --- .../Region/CoreModules/World/Sound/SoundModuleNonShared.cs | 12 +++++++++--- OpenSim/Region/Framework/Interfaces/ISoundModule.cs | 2 ++ 2 files changed, 11 insertions(+), 3 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/World/Sound/SoundModuleNonShared.cs b/OpenSim/Region/CoreModules/World/Sound/SoundModuleNonShared.cs index 9fd0a36..ff052ba 100644 --- a/OpenSim/Region/CoreModules/World/Sound/SoundModuleNonShared.cs +++ b/OpenSim/Region/CoreModules/World/Sound/SoundModuleNonShared.cs @@ -48,13 +48,19 @@ namespace OpenSim.Region.CoreModules.World.Sound public bool Enabled { get; private set; } + public float MaxDistance { get; private set; } + #region INonSharedRegionModule public void Initialise(IConfigSource configSource) { IConfig config = configSource.Configs["Sounds"]; - Enabled = (config != null && config.GetString("Module", "SoundModuleNonShared") == "SoundModuleNonShared"); + if (config == null) + return; + + Enabled = config.GetString("Module", "SoundModuleNonShared") == "SoundModuleNonShared"; + MaxDistance = config.GetFloat("MaxDistance", 100.0f); } public void AddRegion(Scene scene) { } @@ -109,7 +115,7 @@ namespace OpenSim.Region.CoreModules.World.Sound m_scene.ForEachRootScenePresence(delegate(ScenePresence sp) { double dis = Util.GetDistanceTo(sp.AbsolutePosition, position); - if (dis > 100.0) // Max audio distance + if (dis > MaxDistance) // Max audio distance return; if (grp.IsAttachment) @@ -158,7 +164,7 @@ namespace OpenSim.Region.CoreModules.World.Sound { double dis = Util.GetDistanceTo(sp.AbsolutePosition, position); - if (dis > 100.0) // Max audio distance + if (dis > MaxDistance) // Max audio distance return; float thisSpGain; diff --git a/OpenSim/Region/Framework/Interfaces/ISoundModule.cs b/OpenSim/Region/Framework/Interfaces/ISoundModule.cs index 6117a80..4c558cc 100644 --- a/OpenSim/Region/Framework/Interfaces/ISoundModule.cs +++ b/OpenSim/Region/Framework/Interfaces/ISoundModule.cs @@ -32,6 +32,8 @@ namespace OpenSim.Region.Framework.Interfaces { public interface ISoundModule { + float MaxDistance { get; } + void PlayAttachedSound(UUID soundID, UUID ownerID, UUID objectID, double gain, Vector3 position, byte flags, float radius); void TriggerSound( -- cgit v1.1 From 6bd1f0f209bce2f158c881f525235078957e9a62 Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Fri, 5 Oct 2012 14:04:28 +0100 Subject: Factoring out an if-else block in PlayAttachedSound as it was using the previously hard-coded max distance value. --- .../Region/CoreModules/World/Sound/SoundModuleNonShared.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/World/Sound/SoundModuleNonShared.cs b/OpenSim/Region/CoreModules/World/Sound/SoundModuleNonShared.cs index ff052ba..f3ec572 100644 --- a/OpenSim/Region/CoreModules/World/Sound/SoundModuleNonShared.cs +++ b/OpenSim/Region/CoreModules/World/Sound/SoundModuleNonShared.cs @@ -112,6 +112,9 @@ namespace OpenSim.Region.CoreModules.World.Sound SceneObjectGroup grp = part.ParentGroup; + if (radius == 0) + radius = MaxDistance; + m_scene.ForEachRootScenePresence(delegate(ScenePresence sp) { double dis = Util.GetDistanceTo(sp.AbsolutePosition, position); @@ -130,9 +133,6 @@ namespace OpenSim.Region.CoreModules.World.Sound float thisSpGain; // Scale by distance - if (radius == 0) - thisSpGain = (float)((double)gain * ((100.0 - dis) / 100.0)); - else thisSpGain = (float)((double)gain * ((radius - dis) / radius)); sp.ControllingClient.SendPlayAttachedSound(soundID, objectID, ownerID, thisSpGain, flags); @@ -160,6 +160,9 @@ namespace OpenSim.Region.CoreModules.World.Sound } } + if (radius == 0) + radius = MaxDistance; + m_scene.ForEachRootScenePresence(delegate(ScenePresence sp) { double dis = Util.GetDistanceTo(sp.AbsolutePosition, position); @@ -170,9 +173,6 @@ namespace OpenSim.Region.CoreModules.World.Sound float thisSpGain; // Scale by distance - if (radius == 0) - thisSpGain = (float)((double)gain * ((100.0 - dis) / 100.0)); - else thisSpGain = (float)((double)gain * ((radius - dis) / radius)); sp.ControllingClient.SendTriggeredSound( -- cgit v1.1 From 20be6a4b48d73734e0041780868ff60078163004 Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Fri, 5 Oct 2012 14:13:38 +0100 Subject: refactoring thisSpGain in PlayAttachedSound as it was previously using two typecasts in the assignment and had the assignment on a separate line to the declaration --- .../Region/CoreModules/World/Sound/SoundModuleNonShared.cs | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/World/Sound/SoundModuleNonShared.cs b/OpenSim/Region/CoreModules/World/Sound/SoundModuleNonShared.cs index f3ec572..14914b6 100644 --- a/OpenSim/Region/CoreModules/World/Sound/SoundModuleNonShared.cs +++ b/OpenSim/Region/CoreModules/World/Sound/SoundModuleNonShared.cs @@ -130,12 +130,10 @@ namespace OpenSim.Region.CoreModules.World.Sound dis = 0; } - float thisSpGain; - // Scale by distance - thisSpGain = (float)((double)gain * ((radius - dis) / radius)); + double thisSpGain = gain * ((radius - dis) / radius); - sp.ControllingClient.SendPlayAttachedSound(soundID, objectID, ownerID, thisSpGain, flags); + sp.ControllingClient.SendPlayAttachedSound(soundID, objectID, ownerID, (float)thisSpGain, flags); }); } @@ -170,13 +168,11 @@ namespace OpenSim.Region.CoreModules.World.Sound if (dis > MaxDistance) // Max audio distance return; - float thisSpGain; - // Scale by distance - thisSpGain = (float)((double)gain * ((radius - dis) / radius)); + double thisSpGain = gain * ((radius - dis) / radius); sp.ControllingClient.SendTriggeredSound( - soundId, ownerID, objectID, parentID, handle, position, thisSpGain); + soundId, ownerID, objectID, parentID, handle, position, (float)thisSpGain); }); } -- cgit v1.1 From 1d47bcb6b6838500fa9b80d441a8b87ceaf0e01c Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Fri, 5 Oct 2012 14:14:01 +0100 Subject: stripping whitespace from ISoundModule, formatting SoundModuleNonShared.cs --- OpenSim/Region/CoreModules/World/Sound/SoundModuleNonShared.cs | 8 +++++--- OpenSim/Region/Framework/Interfaces/ISoundModule.cs | 2 +- 2 files changed, 6 insertions(+), 4 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/World/Sound/SoundModuleNonShared.cs b/OpenSim/Region/CoreModules/World/Sound/SoundModuleNonShared.cs index 14914b6..74f2874 100644 --- a/OpenSim/Region/CoreModules/World/Sound/SoundModuleNonShared.cs +++ b/OpenSim/Region/CoreModules/World/Sound/SoundModuleNonShared.cs @@ -133,7 +133,8 @@ namespace OpenSim.Region.CoreModules.World.Sound // Scale by distance double thisSpGain = gain * ((radius - dis) / radius); - sp.ControllingClient.SendPlayAttachedSound(soundID, objectID, ownerID, (float)thisSpGain, flags); + sp.ControllingClient.SendPlayAttachedSound(soundID, objectID, + ownerID, (float)thisSpGain, flags); }); } @@ -171,8 +172,9 @@ namespace OpenSim.Region.CoreModules.World.Sound // Scale by distance double thisSpGain = gain * ((radius - dis) / radius); - sp.ControllingClient.SendTriggeredSound( - soundId, ownerID, objectID, parentID, handle, position, (float)thisSpGain); + sp.ControllingClient.SendTriggeredSound(soundId, ownerID, + objectID, parentID, handle, position, + (float)thisSpGain); }); } diff --git a/OpenSim/Region/Framework/Interfaces/ISoundModule.cs b/OpenSim/Region/Framework/Interfaces/ISoundModule.cs index 4c558cc..945029f 100644 --- a/OpenSim/Region/Framework/Interfaces/ISoundModule.cs +++ b/OpenSim/Region/Framework/Interfaces/ISoundModule.cs @@ -35,7 +35,7 @@ namespace OpenSim.Region.Framework.Interfaces float MaxDistance { get; } void PlayAttachedSound(UUID soundID, UUID ownerID, UUID objectID, double gain, Vector3 position, byte flags, float radius); - + void TriggerSound( UUID soundId, UUID ownerID, UUID objectID, UUID parentID, double gain, Vector3 position, UInt64 handle, float radius); } -- cgit v1.1 From 516ee244b4f8f493b9b76a62b62f4e8304826e4f Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Fri, 5 Oct 2012 14:30:51 +0100 Subject: swapping GetSceneObjectPart for TryGetSceneObjectPart in PlayAttachedSound to imply why we're doing an early return. --- OpenSim/Region/CoreModules/World/Sound/SoundModuleNonShared.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/World/Sound/SoundModuleNonShared.cs b/OpenSim/Region/CoreModules/World/Sound/SoundModuleNonShared.cs index 74f2874..917b3dc 100644 --- a/OpenSim/Region/CoreModules/World/Sound/SoundModuleNonShared.cs +++ b/OpenSim/Region/CoreModules/World/Sound/SoundModuleNonShared.cs @@ -106,8 +106,8 @@ namespace OpenSim.Region.CoreModules.World.Sound public virtual void PlayAttachedSound( UUID soundID, UUID ownerID, UUID objectID, double gain, Vector3 position, byte flags, float radius) { - SceneObjectPart part = m_scene.GetSceneObjectPart(objectID); - if (part == null) + SceneObjectPart part; + if (!m_scene.TryGetSceneObjectPart(objectID, out part)) return; SceneObjectGroup grp = part.ParentGroup; @@ -141,8 +141,8 @@ namespace OpenSim.Region.CoreModules.World.Sound public virtual void TriggerSound( UUID soundId, UUID ownerID, UUID objectID, UUID parentID, double gain, Vector3 position, UInt64 handle, float radius) { - SceneObjectPart part = m_scene.GetSceneObjectPart(objectID); - if (part == null) + SceneObjectPart part; + if (!m_scene.TryGetSceneObjectPart(objectID, out part)) { ScenePresence sp; if (!m_scene.TryGetScenePresence(objectID, out sp)) -- cgit v1.1 From 644089278814a269d30fe8198e6a000e6e3153e7 Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Fri, 5 Oct 2012 14:31:50 +0100 Subject: TryGetScenePresence in TriggerSound is probably meant to be using the ownerID, not the objectID --- OpenSim/Region/CoreModules/World/Sound/SoundModuleNonShared.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/World/Sound/SoundModuleNonShared.cs b/OpenSim/Region/CoreModules/World/Sound/SoundModuleNonShared.cs index 917b3dc..f0e446f 100644 --- a/OpenSim/Region/CoreModules/World/Sound/SoundModuleNonShared.cs +++ b/OpenSim/Region/CoreModules/World/Sound/SoundModuleNonShared.cs @@ -145,7 +145,7 @@ namespace OpenSim.Region.CoreModules.World.Sound if (!m_scene.TryGetSceneObjectPart(objectID, out part)) { ScenePresence sp; - if (!m_scene.TryGetScenePresence(objectID, out sp)) + if (!m_scene.TryGetScenePresence(ownerID, out sp)) return; } else -- cgit v1.1 From b42cfe49a2f4e95687eb76381ed911515ef2e3b2 Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Fri, 5 Oct 2012 14:37:01 +0100 Subject: Replacing double-if block in SceneObjectPart.SendSound with Util.Clip --- OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index 27ef4c9..a539eff 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -2684,10 +2684,7 @@ namespace OpenSim.Region.Framework.Scenes /// public void SendSound(string sound, double volume, bool triggered, byte flags, float radius, bool useMaster, bool isMaster) { - if (volume > 1) - volume = 1; - if (volume < 0) - volume = 0; + volume = Util.Clip((float)volume, 0, 1); UUID ownerID = OwnerID; UUID objectID = ParentGroup.RootPart.UUID; -- cgit v1.1 From f4fe8763ad4f4cb85ff38eb65f1138baee74ece1 Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Fri, 5 Oct 2012 14:37:55 +0100 Subject: Changing the logic order in the TaskInventory iterator of ScenObjectPart.SendSound, since we can currently have non-unique object inventory names so we should check the asset type first. --- OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index a539eff..681feea 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -2701,7 +2701,7 @@ namespace OpenSim.Region.Framework.Scenes { foreach (KeyValuePair item in TaskInventory) { - if (item.Value.Name == sound && item.Value.Type == (int)AssetType.Sound) + if (item.Value.Type == (int)AssetType.Sound && item.Value.Name == sound) { soundID = item.Value.ItemID; break; -- cgit v1.1 From 32db725dd770a52d02f86cf8a1274f68178d6844 Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Fri, 5 Oct 2012 14:39:06 +0100 Subject: SceneObjectPart.SendSound can exit early if a sound module was not found. --- OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index 681feea..3a39da0 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -2684,6 +2684,10 @@ namespace OpenSim.Region.Framework.Scenes /// public void SendSound(string sound, double volume, bool triggered, byte flags, float radius, bool useMaster, bool isMaster) { + ISoundModule soundModule = ParentGroup.Scene.RequestModuleInterface(); + if(soundModule == null) + return; + volume = Util.Clip((float)volume, 0, 1); UUID ownerID = OwnerID; @@ -2713,9 +2717,6 @@ namespace OpenSim.Region.Framework.Scenes if (soundID == UUID.Zero) return; - ISoundModule soundModule = ParentGroup.Scene.RequestModuleInterface(); - if (soundModule != null) - { if (useMaster) { if (isMaster) @@ -2761,7 +2762,6 @@ namespace OpenSim.Region.Framework.Scenes else soundModule.PlayAttachedSound(soundID, ownerID, objectID, volume, position, flags, radius); } - } } /// -- cgit v1.1 From 1c618843b836c4e9ad8ae685d2f49836e32d8b08 Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Fri, 5 Oct 2012 14:39:23 +0100 Subject: formatting changes to SceneObjectPart.SendSound; consistent indentation --- OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | 68 +++++++++++----------- 1 file changed, 34 insertions(+), 34 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index 3a39da0..b333a1a 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -2717,51 +2717,51 @@ namespace OpenSim.Region.Framework.Scenes if (soundID == UUID.Zero) return; - if (useMaster) + if (useMaster) + { + if (isMaster) { - if (isMaster) + if (triggered) + soundModule.TriggerSound(soundID, ownerID, objectID, parentID, volume, position, regionHandle, radius); + else + soundModule.PlayAttachedSound(soundID, ownerID, objectID, volume, position, flags, radius); + ParentGroup.PlaySoundMasterPrim = this; + ownerID = OwnerID; + objectID = ParentGroup.RootPart.UUID; + parentID = ParentGroup.UUID; + position = AbsolutePosition; // region local + regionHandle = ParentGroup.Scene.RegionInfo.RegionHandle; + if (triggered) + soundModule.TriggerSound(soundID, ownerID, objectID, parentID, volume, position, regionHandle, radius); + else + soundModule.PlayAttachedSound(soundID, ownerID, objectID, volume, position, flags, radius); + foreach (SceneObjectPart prim in ParentGroup.PlaySoundSlavePrims) { + ownerID = prim.OwnerID; + objectID = prim.ParentGroup.RootPart.UUID; + parentID = prim.ParentGroup.UUID; + position = prim.AbsolutePosition; // region local + regionHandle = prim.ParentGroup.Scene.RegionInfo.RegionHandle; if (triggered) soundModule.TriggerSound(soundID, ownerID, objectID, parentID, volume, position, regionHandle, radius); else soundModule.PlayAttachedSound(soundID, ownerID, objectID, volume, position, flags, radius); - ParentGroup.PlaySoundMasterPrim = this; - ownerID = OwnerID; - objectID = ParentGroup.RootPart.UUID; - parentID = ParentGroup.UUID; - position = AbsolutePosition; // region local - regionHandle = ParentGroup.Scene.RegionInfo.RegionHandle; - if (triggered) - soundModule.TriggerSound(soundID, ownerID, objectID, parentID, volume, position, regionHandle, radius); - else - soundModule.PlayAttachedSound(soundID, ownerID, objectID, volume, position, flags, radius); - foreach (SceneObjectPart prim in ParentGroup.PlaySoundSlavePrims) - { - ownerID = prim.OwnerID; - objectID = prim.ParentGroup.RootPart.UUID; - parentID = prim.ParentGroup.UUID; - position = prim.AbsolutePosition; // region local - regionHandle = prim.ParentGroup.Scene.RegionInfo.RegionHandle; - if (triggered) - soundModule.TriggerSound(soundID, ownerID, objectID, parentID, volume, position, regionHandle, radius); - else - soundModule.PlayAttachedSound(soundID, ownerID, objectID, volume, position, flags, radius); - } - ParentGroup.PlaySoundSlavePrims.Clear(); - ParentGroup.PlaySoundMasterPrim = null; - } - else - { - ParentGroup.PlaySoundSlavePrims.Add(this); } + ParentGroup.PlaySoundSlavePrims.Clear(); + ParentGroup.PlaySoundMasterPrim = null; } else { - if (triggered) - soundModule.TriggerSound(soundID, ownerID, objectID, parentID, volume, position, regionHandle, radius); - else - soundModule.PlayAttachedSound(soundID, ownerID, objectID, volume, position, flags, radius); + ParentGroup.PlaySoundSlavePrims.Add(this); } + } + else + { + if (triggered) + soundModule.TriggerSound(soundID, ownerID, objectID, parentID, volume, position, regionHandle, radius); + else + soundModule.PlayAttachedSound(soundID, ownerID, objectID, volume, position, flags, radius); + } } /// -- cgit v1.1 From d4034271eb37ff31cbdcad416a00f4e4c426731e Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Fri, 5 Oct 2012 14:42:59 +0100 Subject: formatting ISoundModule prior to documentation --- OpenSim/Region/Framework/Interfaces/ISoundModule.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Framework/Interfaces/ISoundModule.cs b/OpenSim/Region/Framework/Interfaces/ISoundModule.cs index 945029f..90fe0bc 100644 --- a/OpenSim/Region/Framework/Interfaces/ISoundModule.cs +++ b/OpenSim/Region/Framework/Interfaces/ISoundModule.cs @@ -34,9 +34,11 @@ namespace OpenSim.Region.Framework.Interfaces { float MaxDistance { get; } - void PlayAttachedSound(UUID soundID, UUID ownerID, UUID objectID, double gain, Vector3 position, byte flags, float radius); + void PlayAttachedSound(UUID soundID, UUID ownerID, UUID objectID, + double gain, Vector3 position, byte flags, float radius); void TriggerSound( - UUID soundId, UUID ownerID, UUID objectID, UUID parentID, double gain, Vector3 position, UInt64 handle, float radius); + UUID soundId, UUID ownerID, UUID objectID, UUID parentID, + double gain, Vector3 position, UInt64 handle, float radius); } } \ No newline at end of file -- cgit v1.1 From b9e0f1cd2be3fe8b20d639d66f5f4fc8f1995d73 Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Fri, 5 Oct 2012 14:46:31 +0100 Subject: documenting ISoundModule methods & fields --- .../Region/Framework/Interfaces/ISoundModule.cs | 28 ++++++++++++++++++++++ 1 file changed, 28 insertions(+) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Framework/Interfaces/ISoundModule.cs b/OpenSim/Region/Framework/Interfaces/ISoundModule.cs index 90fe0bc..6930d78 100644 --- a/OpenSim/Region/Framework/Interfaces/ISoundModule.cs +++ b/OpenSim/Region/Framework/Interfaces/ISoundModule.cs @@ -32,11 +32,39 @@ namespace OpenSim.Region.Framework.Interfaces { public interface ISoundModule { + /// + /// Maximum distance between a sound source and a recipient. + /// float MaxDistance { get; } + /// + /// Play a sound from an object. + /// + /// Sound asset ID + /// Sound source owner + /// Sound source ID + /// Sound volume + /// Sound source position + /// Sound flags + /// + /// Radius used to affect gain over distance. + /// void PlayAttachedSound(UUID soundID, UUID ownerID, UUID objectID, double gain, Vector3 position, byte flags, float radius); + /// + /// Trigger a sound in the scene. + /// + /// Sound asset ID + /// Sound source owner + /// Sound source ID + /// Sound source parent. + /// Sound volume + /// Sound source position + /// + /// + /// Radius used to affect gain over distance. + /// void TriggerSound( UUID soundId, UUID ownerID, UUID objectID, UUID parentID, double gain, Vector3 position, UInt64 handle, float radius); -- cgit v1.1 From 206a694c6baf9603855cc8eab50909e5e63b0f10 Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Fri, 5 Oct 2012 14:50:31 +0100 Subject: moving comment for llStopSound inside the method block prior to transposition to sound module --- OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (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 bedcd85..7fa01c1 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -2448,11 +2448,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api m_host.SendSound(KeyOrName(sound).ToString(), volume, true, 0, 0, false, false); } - // Xantor 20080528: Clear prim data of sound instead public void llStopSound() { m_host.AddScriptLPS(1); m_host.AdjustSoundGain(0); + // Xantor 20080528: Clear prim data of sound instead if (m_host.ParentGroup.LoopSoundSlavePrims.Contains(m_host)) { if (m_host.ParentGroup.LoopSoundMasterPrim == m_host) -- cgit v1.1 From 8763a637b5c2e48a97111b4f569e71b7e1c2f1d2 Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Fri, 5 Oct 2012 14:55:00 +0100 Subject: transposing stop sound into sound module --- .../World/Sound/SoundModuleNonShared.cs | 45 ++++++++++++++++++++++ .../Region/Framework/Interfaces/ISoundModule.cs | 6 +++ .../Shared/Api/Implementation/LSL_Api.cs | 42 +++----------------- 3 files changed, 56 insertions(+), 37 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/World/Sound/SoundModuleNonShared.cs b/OpenSim/Region/CoreModules/World/Sound/SoundModuleNonShared.cs index f0e446f..670794d 100644 --- a/OpenSim/Region/CoreModules/World/Sound/SoundModuleNonShared.cs +++ b/OpenSim/Region/CoreModules/World/Sound/SoundModuleNonShared.cs @@ -178,6 +178,51 @@ namespace OpenSim.Region.CoreModules.World.Sound }); } + public virtual void StopSound(UUID objectID) + { + SceneObjectPart m_host; + if (!m_scene.TryGetSceneObjectPart(objectID, out m_host)) + return; + + m_host.AdjustSoundGain(0); + // Xantor 20080528: Clear prim data of sound instead + if (m_host.ParentGroup.LoopSoundSlavePrims.Contains(m_host)) + { + if (m_host.ParentGroup.LoopSoundMasterPrim == m_host) + { + foreach (SceneObjectPart part in m_host.ParentGroup.LoopSoundSlavePrims) + { + part.Sound = UUID.Zero; + part.SoundGain = 0; + part.SoundFlags = 0; + part.SoundRadius = 0; + part.ScheduleFullUpdate(); + part.SendFullUpdateToAllClients(); + } + m_host.ParentGroup.LoopSoundMasterPrim = null; + m_host.ParentGroup.LoopSoundSlavePrims.Clear(); + } + else + { + m_host.Sound = UUID.Zero; + m_host.SoundGain = 0; + m_host.SoundFlags = 0; + m_host.SoundRadius = 0; + m_host.ScheduleFullUpdate(); + m_host.SendFullUpdateToAllClients(); + } + } + else + { + m_host.Sound = UUID.Zero; + m_host.SoundGain = 0; + m_host.SoundFlags = 0; + m_host.SoundRadius = 0; + m_host.ScheduleFullUpdate(); + m_host.SendFullUpdateToAllClients(); + } + } + #endregion } } diff --git a/OpenSim/Region/Framework/Interfaces/ISoundModule.cs b/OpenSim/Region/Framework/Interfaces/ISoundModule.cs index 6930d78..45219ed 100644 --- a/OpenSim/Region/Framework/Interfaces/ISoundModule.cs +++ b/OpenSim/Region/Framework/Interfaces/ISoundModule.cs @@ -68,5 +68,11 @@ namespace OpenSim.Region.Framework.Interfaces void TriggerSound( UUID soundId, UUID ownerID, UUID objectID, UUID parentID, double gain, Vector3 position, UInt64 handle, float radius); + + /// + /// Stop sounds eminating from an object. + /// + /// Sound source ID + void StopSound(UUID objectID); } } \ No newline at end of file diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 7fa01c1..25be3ff 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -107,6 +107,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api protected IUrlModule m_UrlModule = null; protected Dictionary m_userInfoCache = new Dictionary(); protected int EMAIL_PAUSE_TIME = 20; // documented delay value for smtp. + protected ISoundModule m_SoundModule = null; public void Initialize(IScriptEngine ScriptEngine, SceneObjectPart host, TaskInventoryItem item) { @@ -119,6 +120,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api m_TransferModule = m_ScriptEngine.World.RequestModuleInterface(); m_UrlModule = m_ScriptEngine.World.RequestModuleInterface(); + m_SoundModule = m_ScriptEngine.World.RequestModuleInterface(); AsyncCommands = new AsyncCommandManager(ScriptEngine); } @@ -2451,43 +2453,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public void llStopSound() { m_host.AddScriptLPS(1); - m_host.AdjustSoundGain(0); - // Xantor 20080528: Clear prim data of sound instead - if (m_host.ParentGroup.LoopSoundSlavePrims.Contains(m_host)) - { - if (m_host.ParentGroup.LoopSoundMasterPrim == m_host) - { - foreach (SceneObjectPart part in m_host.ParentGroup.LoopSoundSlavePrims) - { - part.Sound = UUID.Zero; - part.SoundGain = 0; - part.SoundFlags = 0; - part.SoundRadius = 0; - part.ScheduleFullUpdate(); - part.SendFullUpdateToAllClients(); - } - m_host.ParentGroup.LoopSoundMasterPrim = null; - m_host.ParentGroup.LoopSoundSlavePrims.Clear(); - } - else - { - m_host.Sound = UUID.Zero; - m_host.SoundGain = 0; - m_host.SoundFlags = 0; - m_host.SoundRadius = 0; - m_host.ScheduleFullUpdate(); - m_host.SendFullUpdateToAllClients(); - } - } - else - { - m_host.Sound = UUID.Zero; - m_host.SoundGain = 0; - m_host.SoundFlags = 0; - m_host.SoundRadius = 0; - m_host.ScheduleFullUpdate(); - m_host.SendFullUpdateToAllClients(); - } + + if (m_SoundModule != null) + m_SoundModule.StopSound(m_host.UUID); } public void llPreloadSound(string sound) -- cgit v1.1 From a68e2fe1692a7611c58f774ac5b94c4298343433 Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Fri, 5 Oct 2012 15:16:30 +0100 Subject: transposing preload sound onto sound module --- .../World/Sound/SoundModuleNonShared.cs | 20 ++++++++++++++ .../Region/Framework/Interfaces/ISoundModule.cs | 10 +++++++ OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | 31 ---------------------- .../Shared/Api/Implementation/LSL_Api.cs | 3 ++- 4 files changed, 32 insertions(+), 32 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/World/Sound/SoundModuleNonShared.cs b/OpenSim/Region/CoreModules/World/Sound/SoundModuleNonShared.cs index 670794d..0225d6f 100644 --- a/OpenSim/Region/CoreModules/World/Sound/SoundModuleNonShared.cs +++ b/OpenSim/Region/CoreModules/World/Sound/SoundModuleNonShared.cs @@ -25,6 +25,7 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ using System; +using System.Collections.Generic; using System.Reflection; using Nini.Config; @@ -223,6 +224,25 @@ namespace OpenSim.Region.CoreModules.World.Sound } } + public virtual void PreloadSound(UUID soundID, UUID objectID, float radius) + { + SceneObjectPart part; + if (soundID == UUID.Zero + || !m_scene.TryGetSceneObjectPart(objectID, out part)) + { + return; + } + + if (radius == 0) + radius = MaxDistance; + + m_scene.ForEachRootScenePresence(delegate(ScenePresence sp) + { + if (!(Util.GetDistanceTo(sp.AbsolutePosition, part.AbsolutePosition) >= MaxDistance)) + sp.ControllingClient.SendPreLoadSound(objectID, objectID, soundID); + }); + } + #endregion } } diff --git a/OpenSim/Region/Framework/Interfaces/ISoundModule.cs b/OpenSim/Region/Framework/Interfaces/ISoundModule.cs index 45219ed..0f65763 100644 --- a/OpenSim/Region/Framework/Interfaces/ISoundModule.cs +++ b/OpenSim/Region/Framework/Interfaces/ISoundModule.cs @@ -74,5 +74,15 @@ namespace OpenSim.Region.Framework.Interfaces /// /// Sound source ID void StopSound(UUID objectID); + + /// + /// Preload sound to viewers within range. + /// + /// Sound asset ID + /// Sound source ID + /// + /// Radius used to determine which viewers should preload the sound. + /// + void PreloadSound(UUID soundID, UUID objectID, float radius); } } \ No newline at end of file diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index b333a1a..48615de 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -2287,37 +2287,6 @@ namespace OpenSim.Region.Framework.Scenes ScheduleTerseUpdate(); } - public void PreloadSound(string sound) - { - // UUID ownerID = OwnerID; - UUID objectID = ParentGroup.RootPart.UUID; - UUID soundID = UUID.Zero; - - if (!UUID.TryParse(sound, out soundID)) - { - //Trys to fetch sound id from prim's inventory. - //Prim's inventory doesn't support non script items yet - - lock (TaskInventory) - { - foreach (KeyValuePair item in TaskInventory) - { - if (item.Value.Name == sound) - { - soundID = item.Value.ItemID; - break; - } - } - } - } - - ParentGroup.Scene.ForEachRootScenePresence(delegate(ScenePresence sp) - { - if (!(Util.GetDistanceTo(sp.AbsolutePosition, AbsolutePosition) >= 100)) - sp.ControllingClient.SendPreLoadSound(objectID, objectID, soundID); - }); - } - public void RemFlag(PrimFlags flag) { // PrimFlags prevflag = Flags; diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 25be3ff..61fd1aa 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -2461,7 +2461,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public void llPreloadSound(string sound) { m_host.AddScriptLPS(1); - m_host.PreloadSound(sound); + if (m_SoundModule != null) + m_SoundModule.PreloadSound(KeyOrName(sound), m_host.UUID, 0); ScriptSleep(1000); } -- cgit v1.1 From 29a8ae48b51de55a02f839b6e4566054ad3f7f58 Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Sat, 6 Oct 2012 22:23:14 +0100 Subject: transposing LoopSoundMaster to Sound Module --- .../World/Sound/SoundModuleNonShared.cs | 36 ++++++++++++++++++++++ .../Region/Framework/Interfaces/ISoundModule.cs | 11 +++++++ .../Shared/Api/Implementation/LSL_Api.cs | 28 ++--------------- 3 files changed, 50 insertions(+), 25 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/World/Sound/SoundModuleNonShared.cs b/OpenSim/Region/CoreModules/World/Sound/SoundModuleNonShared.cs index 0225d6f..4912ed8 100644 --- a/OpenSim/Region/CoreModules/World/Sound/SoundModuleNonShared.cs +++ b/OpenSim/Region/CoreModules/World/Sound/SoundModuleNonShared.cs @@ -243,6 +243,42 @@ namespace OpenSim.Region.CoreModules.World.Sound }); } + public virtual void LoopSoundMaster(UUID objectID, UUID soundID, + double volume, double radius) + { + SceneObjectPart m_host; + if (!m_scene.TryGetSceneObjectPart(objectID, out m_host)) + return; + + m_host.ParentGroup.LoopSoundMasterPrim = m_host; + lock (m_host.ParentGroup.LoopSoundSlavePrims) + { + foreach (SceneObjectPart prim in m_host.ParentGroup.LoopSoundSlavePrims) + { + if (prim.Sound != UUID.Zero) + StopSound(objectID); + + prim.Sound = soundID; + prim.SoundGain = volume; + prim.SoundFlags = 1; // looping + prim.SoundRadius = radius; + + prim.ScheduleFullUpdate(); + prim.SendFullUpdateToAllClients(); + } + } + if (m_host.Sound != UUID.Zero) + StopSound(objectID); + + m_host.Sound = soundID; + m_host.SoundGain = volume; + m_host.SoundFlags = 1; // looping + m_host.SoundRadius = radius; + + m_host.ScheduleFullUpdate(); + m_host.SendFullUpdateToAllClients(); + } + #endregion } } diff --git a/OpenSim/Region/Framework/Interfaces/ISoundModule.cs b/OpenSim/Region/Framework/Interfaces/ISoundModule.cs index 0f65763..d2557b5 100644 --- a/OpenSim/Region/Framework/Interfaces/ISoundModule.cs +++ b/OpenSim/Region/Framework/Interfaces/ISoundModule.cs @@ -84,5 +84,16 @@ namespace OpenSim.Region.Framework.Interfaces /// Radius used to determine which viewers should preload the sound. /// void PreloadSound(UUID soundID, UUID objectID, float radius); + + /// + /// Declare object as new sync master, play specified sound at + /// specified volume with specified radius. + /// + /// Sound source ID + /// Sound asset ID + /// Sound volume + /// Sound radius + void LoopSoundMaster(UUID objectID, UUID soundID, double gain, + double radius); } } \ No newline at end of file diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 61fd1aa..2669add 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -2397,33 +2397,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public void llLoopSoundMaster(string sound, double volume) { m_host.AddScriptLPS(1); - m_host.ParentGroup.LoopSoundMasterPrim = m_host; - lock (m_host.ParentGroup.LoopSoundSlavePrims) + if (m_SoundModule != null) { - foreach (SceneObjectPart prim in m_host.ParentGroup.LoopSoundSlavePrims) - { - if (prim.Sound != UUID.Zero) - llStopSound(); - - prim.Sound = KeyOrName(sound); - prim.SoundGain = volume; - prim.SoundFlags = 1; // looping - prim.SoundRadius = 20; // Magic number, 20 seems reasonable. Make configurable? - - prim.ScheduleFullUpdate(); - prim.SendFullUpdateToAllClients(); - } + m_SoundModule.LoopSoundMaster(m_host.UUID, KeyOrName(sound), + volume, 20); } - if (m_host.Sound != UUID.Zero) - llStopSound(); - - m_host.Sound = KeyOrName(sound); - m_host.SoundGain = volume; - m_host.SoundFlags = 1; // looping - m_host.SoundRadius = 20; // Magic number, 20 seems reasonable. Make configurable? - - m_host.ScheduleFullUpdate(); - m_host.SendFullUpdateToAllClients(); } public void llLoopSoundSlave(string sound, double volume) -- cgit v1.1 From d7ffcace8f596d9b0cf84f1e8cbe4e2d6a71baef Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Sat, 6 Oct 2012 22:27:20 +0100 Subject: adjusting parameter order of PreloadSound to be more logical --- OpenSim/Region/CoreModules/World/Sound/SoundModuleNonShared.cs | 2 +- OpenSim/Region/Framework/Interfaces/ISoundModule.cs | 4 ++-- OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/World/Sound/SoundModuleNonShared.cs b/OpenSim/Region/CoreModules/World/Sound/SoundModuleNonShared.cs index 4912ed8..5a560d8 100644 --- a/OpenSim/Region/CoreModules/World/Sound/SoundModuleNonShared.cs +++ b/OpenSim/Region/CoreModules/World/Sound/SoundModuleNonShared.cs @@ -224,7 +224,7 @@ namespace OpenSim.Region.CoreModules.World.Sound } } - public virtual void PreloadSound(UUID soundID, UUID objectID, float radius) + public virtual void PreloadSound(UUID objectID, UUID soundID, float radius) { SceneObjectPart part; if (soundID == UUID.Zero diff --git a/OpenSim/Region/Framework/Interfaces/ISoundModule.cs b/OpenSim/Region/Framework/Interfaces/ISoundModule.cs index d2557b5..d34a520 100644 --- a/OpenSim/Region/Framework/Interfaces/ISoundModule.cs +++ b/OpenSim/Region/Framework/Interfaces/ISoundModule.cs @@ -78,12 +78,12 @@ namespace OpenSim.Region.Framework.Interfaces /// /// Preload sound to viewers within range. /// - /// Sound asset ID /// Sound source ID + /// Sound asset ID /// /// Radius used to determine which viewers should preload the sound. /// - void PreloadSound(UUID soundID, UUID objectID, float radius); + void PreloadSound(UUID objectID, UUID soundID, float radius); /// /// Declare object as new sync master, play specified sound at diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 2669add..0252145 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -2440,7 +2440,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { m_host.AddScriptLPS(1); if (m_SoundModule != null) - m_SoundModule.PreloadSound(KeyOrName(sound), m_host.UUID, 0); + m_SoundModule.PreloadSound(m_host.UUID, KeyOrName(sound), 0); ScriptSleep(1000); } -- cgit v1.1 From e5df8cafb8d2cc813824299fe4714ee0ceee30c3 Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Sat, 6 Oct 2012 22:37:27 +0100 Subject: Removing a locked iteration over SceneObjectGroup.LoopSoundSlavePrims as the SL Wiki spec does not state that slaves are set to match master values --- .../CoreModules/World/Sound/SoundModuleNonShared.cs | 15 --------------- 1 file changed, 15 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/World/Sound/SoundModuleNonShared.cs b/OpenSim/Region/CoreModules/World/Sound/SoundModuleNonShared.cs index 5a560d8..7ce13d1 100644 --- a/OpenSim/Region/CoreModules/World/Sound/SoundModuleNonShared.cs +++ b/OpenSim/Region/CoreModules/World/Sound/SoundModuleNonShared.cs @@ -251,22 +251,7 @@ namespace OpenSim.Region.CoreModules.World.Sound return; m_host.ParentGroup.LoopSoundMasterPrim = m_host; - lock (m_host.ParentGroup.LoopSoundSlavePrims) - { - foreach (SceneObjectPart prim in m_host.ParentGroup.LoopSoundSlavePrims) - { - if (prim.Sound != UUID.Zero) - StopSound(objectID); - - prim.Sound = soundID; - prim.SoundGain = volume; - prim.SoundFlags = 1; // looping - prim.SoundRadius = radius; - prim.ScheduleFullUpdate(); - prim.SendFullUpdateToAllClients(); - } - } if (m_host.Sound != UUID.Zero) StopSound(objectID); -- cgit v1.1 From 3d8f59aac38e57cf573809b0456053aa0cc8500d Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Sat, 6 Oct 2012 22:40:26 +0100 Subject: refactoring StopSound into a private static method to skip repeating m_scene.TryGetSceneObjectPart --- OpenSim/Region/CoreModules/World/Sound/SoundModuleNonShared.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/World/Sound/SoundModuleNonShared.cs b/OpenSim/Region/CoreModules/World/Sound/SoundModuleNonShared.cs index 7ce13d1..b4b8e79 100644 --- a/OpenSim/Region/CoreModules/World/Sound/SoundModuleNonShared.cs +++ b/OpenSim/Region/CoreModules/World/Sound/SoundModuleNonShared.cs @@ -185,6 +185,11 @@ namespace OpenSim.Region.CoreModules.World.Sound if (!m_scene.TryGetSceneObjectPart(objectID, out m_host)) return; + StopSound(m_host); + } + + private static void StopSound(SceneObjectPart m_host) + { m_host.AdjustSoundGain(0); // Xantor 20080528: Clear prim data of sound instead if (m_host.ParentGroup.LoopSoundSlavePrims.Contains(m_host)) @@ -253,7 +258,7 @@ namespace OpenSim.Region.CoreModules.World.Sound m_host.ParentGroup.LoopSoundMasterPrim = m_host; if (m_host.Sound != UUID.Zero) - StopSound(objectID); + StopSound(m_host); m_host.Sound = soundID; m_host.SoundGain = volume; -- cgit v1.1 From 22693304fb3cfbb8d073c48affd2e56453dd2b2f Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Mon, 15 Oct 2012 14:05:17 +0100 Subject: removing superfluous lines from SceneObjectPart.SendSound --- OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | 8 -------- 1 file changed, 8 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index 48615de..681c725 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -2695,11 +2695,6 @@ namespace OpenSim.Region.Framework.Scenes else soundModule.PlayAttachedSound(soundID, ownerID, objectID, volume, position, flags, radius); ParentGroup.PlaySoundMasterPrim = this; - ownerID = OwnerID; - objectID = ParentGroup.RootPart.UUID; - parentID = ParentGroup.UUID; - position = AbsolutePosition; // region local - regionHandle = ParentGroup.Scene.RegionInfo.RegionHandle; if (triggered) soundModule.TriggerSound(soundID, ownerID, objectID, parentID, volume, position, regionHandle, radius); else @@ -2707,10 +2702,7 @@ namespace OpenSim.Region.Framework.Scenes foreach (SceneObjectPart prim in ParentGroup.PlaySoundSlavePrims) { ownerID = prim.OwnerID; - objectID = prim.ParentGroup.RootPart.UUID; - parentID = prim.ParentGroup.UUID; position = prim.AbsolutePosition; // region local - regionHandle = prim.ParentGroup.Scene.RegionInfo.RegionHandle; if (triggered) soundModule.TriggerSound(soundID, ownerID, objectID, parentID, volume, position, regionHandle, radius); else -- cgit v1.1 From 9df510157e26ffcaf04fd4b85512778fddc08f68 Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Mon, 15 Oct 2012 14:28:34 +0100 Subject: deduplicating code into a single LoopSound method --- .../World/Sound/SoundModuleNonShared.cs | 13 ++++++++-- .../Region/Framework/Interfaces/ISoundModule.cs | 9 +++---- .../Shared/Api/Implementation/LSL_Api.cs | 28 ++++++---------------- 3 files changed, 23 insertions(+), 27 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/World/Sound/SoundModuleNonShared.cs b/OpenSim/Region/CoreModules/World/Sound/SoundModuleNonShared.cs index b4b8e79..6f35a23 100644 --- a/OpenSim/Region/CoreModules/World/Sound/SoundModuleNonShared.cs +++ b/OpenSim/Region/CoreModules/World/Sound/SoundModuleNonShared.cs @@ -248,13 +248,22 @@ namespace OpenSim.Region.CoreModules.World.Sound }); } - public virtual void LoopSoundMaster(UUID objectID, UUID soundID, - double volume, double radius) + // Xantor 20080528 we should do this differently. + // 1) apply the sound to the object + // 2) schedule full update + // just sending the sound out once doesn't work so well when other avatars come in view later on + // or when the prim gets moved, changed, sat on, whatever + // see large number of mantises (mantes?) + // 20080530 Updated to remove code duplication + // 20080530 Stop sound if there is one, otherwise volume only changes don't work + public void LoopSound(UUID objectID, UUID soundID, + double volume, double radius, bool isMaster) { SceneObjectPart m_host; if (!m_scene.TryGetSceneObjectPart(objectID, out m_host)) return; + if (isMaster) m_host.ParentGroup.LoopSoundMasterPrim = m_host; if (m_host.Sound != UUID.Zero) diff --git a/OpenSim/Region/Framework/Interfaces/ISoundModule.cs b/OpenSim/Region/Framework/Interfaces/ISoundModule.cs index d34a520..e514a59 100644 --- a/OpenSim/Region/Framework/Interfaces/ISoundModule.cs +++ b/OpenSim/Region/Framework/Interfaces/ISoundModule.cs @@ -86,14 +86,15 @@ namespace OpenSim.Region.Framework.Interfaces void PreloadSound(UUID objectID, UUID soundID, float radius); /// - /// Declare object as new sync master, play specified sound at - /// specified volume with specified radius. + /// Loop specified sound at specified volume with specified radius, + /// optionally declaring object as new sync master. /// /// Sound source ID /// Sound asset ID /// Sound volume /// Sound radius - void LoopSoundMaster(UUID objectID, UUID soundID, double gain, - double radius); + /// Set object to sync master if true + void LoopSound(UUID objectID, UUID soundID, double gain, + double radius, bool isMaster); } } \ No newline at end of file diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 0252145..c479944 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -2370,28 +2370,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api m_host.SendSound(KeyOrName(sound).ToString(), volume, false, 0, 0, false, false); } - // Xantor 20080528 we should do this differently. - // 1) apply the sound to the object - // 2) schedule full update - // just sending the sound out once doesn't work so well when other avatars come in view later on - // or when the prim gets moved, changed, sat on, whatever - // see large number of mantises (mantes?) - // 20080530 Updated to remove code duplication - // 20080530 Stop sound if there is one, otherwise volume only changes don't work public void llLoopSound(string sound, double volume) { m_host.AddScriptLPS(1); - - if (m_host.Sound != UUID.Zero) - llStopSound(); - - m_host.Sound = KeyOrName(sound); - m_host.SoundGain = volume; - m_host.SoundFlags = 1; // looping - m_host.SoundRadius = 20; // Magic number, 20 seems reasonable. Make configurable? - - m_host.ScheduleFullUpdate(); - m_host.SendFullUpdateToAllClients(); + if (m_SoundModule != null) + { + m_SoundModule.LoopSound(m_host.UUID, KeyOrName(sound), + volume, 20, false); + } } public void llLoopSoundMaster(string sound, double volume) @@ -2399,8 +2385,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api m_host.AddScriptLPS(1); if (m_SoundModule != null) { - m_SoundModule.LoopSoundMaster(m_host.UUID, KeyOrName(sound), - volume, 20); + m_SoundModule.LoopSound(m_host.UUID, KeyOrName(sound), + volume, 20, true); } } -- cgit v1.1 From e75596524a1d8f1a785d78eccdaf0fa585b703f8 Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Mon, 15 Oct 2012 14:31:10 +0100 Subject: Formatting SoundModuleNonShared.LoopSound, consistent indentation --- OpenSim/Region/CoreModules/World/Sound/SoundModuleNonShared.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/World/Sound/SoundModuleNonShared.cs b/OpenSim/Region/CoreModules/World/Sound/SoundModuleNonShared.cs index 6f35a23..6f61c32 100644 --- a/OpenSim/Region/CoreModules/World/Sound/SoundModuleNonShared.cs +++ b/OpenSim/Region/CoreModules/World/Sound/SoundModuleNonShared.cs @@ -264,7 +264,7 @@ namespace OpenSim.Region.CoreModules.World.Sound return; if (isMaster) - m_host.ParentGroup.LoopSoundMasterPrim = m_host; + m_host.ParentGroup.LoopSoundMasterPrim = m_host; if (m_host.Sound != UUID.Zero) StopSound(m_host); -- cgit v1.1 From 57940087d125cf817d1d2492145dc224439434ad Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Mon, 15 Oct 2012 15:09:45 +0100 Subject: Factoring out a superfluous local variable & repeated assignment in SceneObjectPart.SendSound as linksets are only meant to have a single owner --- OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index 681c725..240cfa5 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -2659,7 +2659,6 @@ namespace OpenSim.Region.Framework.Scenes volume = Util.Clip((float)volume, 0, 1); - UUID ownerID = OwnerID; UUID objectID = ParentGroup.RootPart.UUID; UUID parentID = ParentGroup.UUID; @@ -2691,22 +2690,21 @@ namespace OpenSim.Region.Framework.Scenes if (isMaster) { if (triggered) - soundModule.TriggerSound(soundID, ownerID, objectID, parentID, volume, position, regionHandle, radius); + soundModule.TriggerSound(soundID, OwnerID, objectID, parentID, volume, position, regionHandle, radius); else - soundModule.PlayAttachedSound(soundID, ownerID, objectID, volume, position, flags, radius); + soundModule.PlayAttachedSound(soundID, OwnerID, objectID, volume, position, flags, radius); ParentGroup.PlaySoundMasterPrim = this; if (triggered) - soundModule.TriggerSound(soundID, ownerID, objectID, parentID, volume, position, regionHandle, radius); + soundModule.TriggerSound(soundID, OwnerID, objectID, parentID, volume, position, regionHandle, radius); else - soundModule.PlayAttachedSound(soundID, ownerID, objectID, volume, position, flags, radius); + soundModule.PlayAttachedSound(soundID, OwnerID, objectID, volume, position, flags, radius); foreach (SceneObjectPart prim in ParentGroup.PlaySoundSlavePrims) { - ownerID = prim.OwnerID; position = prim.AbsolutePosition; // region local if (triggered) - soundModule.TriggerSound(soundID, ownerID, objectID, parentID, volume, position, regionHandle, radius); + soundModule.TriggerSound(soundID, OwnerID, objectID, parentID, volume, position, regionHandle, radius); else - soundModule.PlayAttachedSound(soundID, ownerID, objectID, volume, position, flags, radius); + soundModule.PlayAttachedSound(soundID, OwnerID, objectID, volume, position, flags, radius); } ParentGroup.PlaySoundSlavePrims.Clear(); ParentGroup.PlaySoundMasterPrim = null; @@ -2719,9 +2717,9 @@ namespace OpenSim.Region.Framework.Scenes else { if (triggered) - soundModule.TriggerSound(soundID, ownerID, objectID, parentID, volume, position, regionHandle, radius); + soundModule.TriggerSound(soundID, OwnerID, objectID, parentID, volume, position, regionHandle, radius); else - soundModule.PlayAttachedSound(soundID, ownerID, objectID, volume, position, flags, radius); + soundModule.PlayAttachedSound(soundID, OwnerID, objectID, volume, position, flags, radius); } } -- cgit v1.1 From af39af1cc407b88d6d2838acff09de77d4a4335d Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Mon, 15 Oct 2012 16:11:26 +0100 Subject: fixing a bug in SceneObjectPart.SendSound where sounds would always come from the root prim rather than the source prim --- OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index 240cfa5..5da4207 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -2659,7 +2659,6 @@ namespace OpenSim.Region.Framework.Scenes volume = Util.Clip((float)volume, 0, 1); - UUID objectID = ParentGroup.RootPart.UUID; UUID parentID = ParentGroup.UUID; UUID soundID = UUID.Zero; @@ -2690,21 +2689,21 @@ namespace OpenSim.Region.Framework.Scenes if (isMaster) { if (triggered) - soundModule.TriggerSound(soundID, OwnerID, objectID, parentID, volume, position, regionHandle, radius); + soundModule.TriggerSound(soundID, OwnerID, UUID, parentID, volume, position, regionHandle, radius); else - soundModule.PlayAttachedSound(soundID, OwnerID, objectID, volume, position, flags, radius); + soundModule.PlayAttachedSound(soundID, OwnerID, UUID, volume, position, flags, radius); ParentGroup.PlaySoundMasterPrim = this; if (triggered) - soundModule.TriggerSound(soundID, OwnerID, objectID, parentID, volume, position, regionHandle, radius); + soundModule.TriggerSound(soundID, OwnerID, UUID, parentID, volume, position, regionHandle, radius); else - soundModule.PlayAttachedSound(soundID, OwnerID, objectID, volume, position, flags, radius); + soundModule.PlayAttachedSound(soundID, OwnerID, UUID, volume, position, flags, radius); foreach (SceneObjectPart prim in ParentGroup.PlaySoundSlavePrims) { position = prim.AbsolutePosition; // region local if (triggered) - soundModule.TriggerSound(soundID, OwnerID, objectID, parentID, volume, position, regionHandle, radius); + soundModule.TriggerSound(soundID, OwnerID, prim.UUID, parentID, volume, position, regionHandle, radius); else - soundModule.PlayAttachedSound(soundID, OwnerID, objectID, volume, position, flags, radius); + soundModule.PlayAttachedSound(soundID, OwnerID, prim.UUID, volume, position, flags, radius); } ParentGroup.PlaySoundSlavePrims.Clear(); ParentGroup.PlaySoundMasterPrim = null; @@ -2717,9 +2716,9 @@ namespace OpenSim.Region.Framework.Scenes else { if (triggered) - soundModule.TriggerSound(soundID, OwnerID, objectID, parentID, volume, position, regionHandle, radius); + soundModule.TriggerSound(soundID, OwnerID, UUID, parentID, volume, position, regionHandle, radius); else - soundModule.PlayAttachedSound(soundID, OwnerID, objectID, volume, position, flags, radius); + soundModule.PlayAttachedSound(soundID, OwnerID, UUID, volume, position, flags, radius); } } -- cgit v1.1 From 5abcecc7356bf58c479a7cff86581131a6ab3c9e Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Tue, 16 Oct 2012 12:24:33 +0100 Subject: moving SendSound from SceneObjectPart to ISoundModule --- .../World/Sound/SoundModuleNonShared.cs | 73 ++++++++++++++++++ .../Region/Framework/Interfaces/ISoundModule.cs | 15 ++++ OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | 88 +++------------------- .../Scripting/Minimodule/SOPObject.cs | 7 +- .../Shared/Api/Implementation/LSL_Api.cs | 22 ++++-- 5 files changed, 119 insertions(+), 86 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/World/Sound/SoundModuleNonShared.cs b/OpenSim/Region/CoreModules/World/Sound/SoundModuleNonShared.cs index 6f61c32..37863ee 100644 --- a/OpenSim/Region/CoreModules/World/Sound/SoundModuleNonShared.cs +++ b/OpenSim/Region/CoreModules/World/Sound/SoundModuleNonShared.cs @@ -278,6 +278,79 @@ namespace OpenSim.Region.CoreModules.World.Sound m_host.SendFullUpdateToAllClients(); } + public void SendSound(UUID objectID, string sound, double volume, + bool triggered, byte flags, float radius, bool useMaster, + bool isMaster) + { + SceneObjectPart part; + if (!m_scene.TryGetSceneObjectPart(objectID, out part)) + return; + + volume = Util.Clip((float)volume, 0, 1); + + UUID parentID = part.ParentGroup.UUID; + + UUID soundID = UUID.Zero; + Vector3 position = part.AbsolutePosition; // region local + ulong regionHandle = m_scene.RegionInfo.RegionHandle; + + if (!UUID.TryParse(sound, out soundID)) + { + // search sound file from inventory + lock (part.TaskInventory) + { + foreach (KeyValuePair item in part.TaskInventory) + { + if (item.Value.Type == (int)AssetType.Sound && item.Value.Name == sound) + { + soundID = item.Value.ItemID; + break; + } + } + } + } + + if (soundID == UUID.Zero) + return; + + if (useMaster) + { + if (isMaster) + { + if (triggered) + TriggerSound(soundID, part.OwnerID, part.UUID, parentID, volume, position, regionHandle, radius); + else + PlayAttachedSound(soundID, part.OwnerID, part.UUID, volume, position, flags, radius); + part.ParentGroup.PlaySoundMasterPrim = part; + if (triggered) + TriggerSound(soundID, part.OwnerID, part.UUID, parentID, volume, position, regionHandle, radius); + else + PlayAttachedSound(soundID, part.OwnerID, part.UUID, volume, position, flags, radius); + foreach (SceneObjectPart prim in part.ParentGroup.PlaySoundSlavePrims) + { + position = prim.AbsolutePosition; // region local + if (triggered) + TriggerSound(soundID, part.OwnerID, prim.UUID, parentID, volume, position, regionHandle, radius); + else + PlayAttachedSound(soundID, part.OwnerID, prim.UUID, volume, position, flags, radius); + } + part.ParentGroup.PlaySoundSlavePrims.Clear(); + part.ParentGroup.PlaySoundMasterPrim = null; + } + else + { + part.ParentGroup.PlaySoundSlavePrims.Add(part); + } + } + else + { + if (triggered) + TriggerSound(soundID, part.OwnerID, part.UUID, parentID, volume, position, regionHandle, radius); + else + PlayAttachedSound(soundID, part.OwnerID, part.UUID, volume, position, flags, radius); + } + } + #endregion } } diff --git a/OpenSim/Region/Framework/Interfaces/ISoundModule.cs b/OpenSim/Region/Framework/Interfaces/ISoundModule.cs index e514a59..c5edcb0 100644 --- a/OpenSim/Region/Framework/Interfaces/ISoundModule.cs +++ b/OpenSim/Region/Framework/Interfaces/ISoundModule.cs @@ -96,5 +96,20 @@ namespace OpenSim.Region.Framework.Interfaces /// Set object to sync master if true void LoopSound(UUID objectID, UUID soundID, double gain, double radius, bool isMaster); + + /// + /// Trigger or play an attached sound in this part's inventory. + /// + /// + /// + /// + /// + /// + /// + /// + /// + void SendSound(UUID objectID, string sound, double volume, + bool triggered, byte flags, float radius, bool useMaster, + bool isMaster); } } \ No newline at end of file diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index 5da4207..cbb92b2 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -2239,7 +2239,15 @@ namespace OpenSim.Region.Framework.Scenes // play the sound. if (startedColliders.Count > 0 && CollisionSound != UUID.Zero && CollisionSoundVolume > 0.0f) - SendSound(CollisionSound.ToString(), CollisionSoundVolume, true, (byte)0, 0, false, false); + { + ISoundModule soundModule = ParentGroup.Scene.RequestModuleInterface(); + if (soundModule != null) + { + soundModule.SendSound(UUID, CollisionSound.ToString(), + CollisionSoundVolume, true, (byte)0, 0, false, + false); + } + } SendCollisionEvent(scriptEvents.collision_start, startedColliders, ParentGroup.Scene.EventManager.TriggerScriptCollidingStart); SendCollisionEvent(scriptEvents.collision , m_lastColliders , ParentGroup.Scene.EventManager.TriggerScriptColliding); @@ -2645,84 +2653,6 @@ namespace OpenSim.Region.Framework.Scenes } /// - /// Trigger or play an attached sound in this part's inventory. - /// - /// - /// - /// - /// - public void SendSound(string sound, double volume, bool triggered, byte flags, float radius, bool useMaster, bool isMaster) - { - ISoundModule soundModule = ParentGroup.Scene.RequestModuleInterface(); - if(soundModule == null) - return; - - volume = Util.Clip((float)volume, 0, 1); - - UUID parentID = ParentGroup.UUID; - - UUID soundID = UUID.Zero; - Vector3 position = AbsolutePosition; // region local - ulong regionHandle = ParentGroup.Scene.RegionInfo.RegionHandle; - - if (!UUID.TryParse(sound, out soundID)) - { - // search sound file from inventory - lock (TaskInventory) - { - foreach (KeyValuePair item in TaskInventory) - { - if (item.Value.Type == (int)AssetType.Sound && item.Value.Name == sound) - { - soundID = item.Value.ItemID; - break; - } - } - } - } - - if (soundID == UUID.Zero) - return; - - if (useMaster) - { - if (isMaster) - { - if (triggered) - soundModule.TriggerSound(soundID, OwnerID, UUID, parentID, volume, position, regionHandle, radius); - else - soundModule.PlayAttachedSound(soundID, OwnerID, UUID, volume, position, flags, radius); - ParentGroup.PlaySoundMasterPrim = this; - if (triggered) - soundModule.TriggerSound(soundID, OwnerID, UUID, parentID, volume, position, regionHandle, radius); - else - soundModule.PlayAttachedSound(soundID, OwnerID, UUID, volume, position, flags, radius); - foreach (SceneObjectPart prim in ParentGroup.PlaySoundSlavePrims) - { - position = prim.AbsolutePosition; // region local - if (triggered) - soundModule.TriggerSound(soundID, OwnerID, prim.UUID, parentID, volume, position, regionHandle, radius); - else - soundModule.PlayAttachedSound(soundID, OwnerID, prim.UUID, volume, position, flags, radius); - } - ParentGroup.PlaySoundSlavePrims.Clear(); - ParentGroup.PlaySoundMasterPrim = null; - } - else - { - ParentGroup.PlaySoundSlavePrims.Add(this); - } - } - else - { - if (triggered) - soundModule.TriggerSound(soundID, OwnerID, UUID, parentID, volume, position, regionHandle, radius); - else - soundModule.PlayAttachedSound(soundID, OwnerID, UUID, volume, position, flags, radius); - } - } - - /// /// Send a terse update to all clients /// public void SendTerseUpdateToAllClients() diff --git a/OpenSim/Region/OptionalModules/Scripting/Minimodule/SOPObject.cs b/OpenSim/Region/OptionalModules/Scripting/Minimodule/SOPObject.cs index aa23fee..9e438e2 100644 --- a/OpenSim/Region/OptionalModules/Scripting/Minimodule/SOPObject.cs +++ b/OpenSim/Region/OptionalModules/Scripting/Minimodule/SOPObject.cs @@ -821,8 +821,11 @@ namespace OpenSim.Region.OptionalModules.Scripting.Minimodule { if (!CanEdit()) return; - - GetSOP().SendSound(asset.ToString(), volume, true, 0, 0, false, false); + ISoundModule module = m_rootScene.RequestModuleInterface(); + if (module != null) + { + module.SendSound(GetSOP().UUID, asset.ToString(), volume, true, 0, 0, false, false); + } } #endregion diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index c479944..f29be92 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -2367,7 +2367,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api m_host.AddScriptLPS(1); // send the sound, once, to all clients in range - m_host.SendSound(KeyOrName(sound).ToString(), volume, false, 0, 0, false, false); + if (m_SoundModule != null) + { + m_SoundModule.SendSound(m_host.UUID, KeyOrName(sound).ToString(), volume, false, 0, 0, false, false); + } } public void llLoopSound(string sound, double volume) @@ -2404,14 +2407,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api m_host.AddScriptLPS(1); // send the sound, once, to all clients in range - m_host.SendSound(KeyOrName(sound).ToString(), volume, false, 0, 0, true, false); + if (m_SoundModule != null) + { + m_SoundModule.SendSound(m_host.UUID, KeyOrName(sound).ToString(), volume, false, 0, 0, true, false); + } } public void llTriggerSound(string sound, double volume) { m_host.AddScriptLPS(1); - // send the sound, once, to all clients in range - m_host.SendSound(KeyOrName(sound).ToString(), volume, true, 0, 0, false, false); + // send the sound, once, to all clients in rangeTrigger or play an attached sound in this part's inventory. + if (m_SoundModule != null) + { + m_SoundModule.SendSound(m_host.UUID, KeyOrName(sound).ToString(), volume, true, 0, 0, false, false); + } } public void llStopSound() @@ -5824,10 +5833,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api LSL_Vector bottom_south_west) { m_host.AddScriptLPS(1); + if (m_SoundModule != null) + { float radius1 = (float)llVecDist(llGetPos(), top_north_east); float radius2 = (float)llVecDist(llGetPos(), bottom_south_west); float radius = Math.Abs(radius1 - radius2); - m_host.SendSound(KeyOrName(sound).ToString(), volume, true, 0, radius, false, false); + m_SoundModule.SendSound(m_host.UUID, KeyOrName(sound).ToString(), volume, true, 0, radius, false, false); + } } public void llEjectFromLand(string pest) -- cgit v1.1 From c5af16aef82e2bdf2f4d877a231180e00a8893a6 Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Tue, 16 Oct 2012 12:40:21 +0100 Subject: shuffling code around so that the interface for ISoundModule.SendSound() specifies a UUID rather than a string --- .../World/Sound/SoundModuleNonShared.cs | 25 ++---------- .../Region/Framework/Interfaces/ISoundModule.cs | 2 +- OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | 2 +- .../Scripting/Minimodule/SOPObject.cs | 2 +- .../Shared/Api/Implementation/LSL_Api.cs | 44 ++++++++++++++++++++-- 5 files changed, 47 insertions(+), 28 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/World/Sound/SoundModuleNonShared.cs b/OpenSim/Region/CoreModules/World/Sound/SoundModuleNonShared.cs index 37863ee..417c071 100644 --- a/OpenSim/Region/CoreModules/World/Sound/SoundModuleNonShared.cs +++ b/OpenSim/Region/CoreModules/World/Sound/SoundModuleNonShared.cs @@ -278,10 +278,13 @@ namespace OpenSim.Region.CoreModules.World.Sound m_host.SendFullUpdateToAllClients(); } - public void SendSound(UUID objectID, string sound, double volume, + public void SendSound(UUID objectID, UUID soundID, double volume, bool triggered, byte flags, float radius, bool useMaster, bool isMaster) { + if (soundID == UUID.Zero) + return; + SceneObjectPart part; if (!m_scene.TryGetSceneObjectPart(objectID, out part)) return; @@ -290,29 +293,9 @@ namespace OpenSim.Region.CoreModules.World.Sound UUID parentID = part.ParentGroup.UUID; - UUID soundID = UUID.Zero; Vector3 position = part.AbsolutePosition; // region local ulong regionHandle = m_scene.RegionInfo.RegionHandle; - if (!UUID.TryParse(sound, out soundID)) - { - // search sound file from inventory - lock (part.TaskInventory) - { - foreach (KeyValuePair item in part.TaskInventory) - { - if (item.Value.Type == (int)AssetType.Sound && item.Value.Name == sound) - { - soundID = item.Value.ItemID; - break; - } - } - } - } - - if (soundID == UUID.Zero) - return; - if (useMaster) { if (isMaster) diff --git a/OpenSim/Region/Framework/Interfaces/ISoundModule.cs b/OpenSim/Region/Framework/Interfaces/ISoundModule.cs index c5edcb0..5d1bb63 100644 --- a/OpenSim/Region/Framework/Interfaces/ISoundModule.cs +++ b/OpenSim/Region/Framework/Interfaces/ISoundModule.cs @@ -108,7 +108,7 @@ namespace OpenSim.Region.Framework.Interfaces /// /// /// - void SendSound(UUID objectID, string sound, double volume, + void SendSound(UUID objectID, UUID sound, double volume, bool triggered, byte flags, float radius, bool useMaster, bool isMaster); } diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index cbb92b2..f79ac96 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -2243,7 +2243,7 @@ namespace OpenSim.Region.Framework.Scenes ISoundModule soundModule = ParentGroup.Scene.RequestModuleInterface(); if (soundModule != null) { - soundModule.SendSound(UUID, CollisionSound.ToString(), + soundModule.SendSound(UUID, CollisionSound, CollisionSoundVolume, true, (byte)0, 0, false, false); } diff --git a/OpenSim/Region/OptionalModules/Scripting/Minimodule/SOPObject.cs b/OpenSim/Region/OptionalModules/Scripting/Minimodule/SOPObject.cs index 9e438e2..5ed1514 100644 --- a/OpenSim/Region/OptionalModules/Scripting/Minimodule/SOPObject.cs +++ b/OpenSim/Region/OptionalModules/Scripting/Minimodule/SOPObject.cs @@ -824,7 +824,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.Minimodule ISoundModule module = m_rootScene.RequestModuleInterface(); if (module != null) { - module.SendSound(GetSOP().UUID, asset.ToString(), volume, true, 0, 0, false, false); + module.SendSound(GetSOP().UUID, asset, volume, true, 0, 0, false, false); } } diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index f29be92..869d94e 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -333,6 +333,42 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api return key; } + /// + /// Return the UUID of the asset matching the specified key or name + /// and asset type. + /// + /// + /// + /// + protected UUID KeyOrName(string k, AssetType type) + { + UUID key; + + if (!UUID.TryParse(k, out key)) + { + TaskInventoryItem item = m_host.Inventory.GetInventoryItem(k); + if (item != null && item.Type == (int)type) + key = item.AssetID; + } + else + { + lock (m_host.TaskInventory) + { + foreach (KeyValuePair item in m_host.TaskInventory) + { + if (item.Value.Type == (int)type && item.Value.Name == k) + { + key = item.Value.ItemID; + break; + } + } + } + } + + + return key; + } + //These are the implementations of the various ll-functions used by the LSL scripts. public LSL_Float llSin(double f) { @@ -2369,7 +2405,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api // send the sound, once, to all clients in range if (m_SoundModule != null) { - m_SoundModule.SendSound(m_host.UUID, KeyOrName(sound).ToString(), volume, false, 0, 0, false, false); + m_SoundModule.SendSound(m_host.UUID, KeyOrName(sound, AssetType.Sound), volume, false, 0, 0, false, false); } } @@ -2409,7 +2445,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api // send the sound, once, to all clients in range if (m_SoundModule != null) { - m_SoundModule.SendSound(m_host.UUID, KeyOrName(sound).ToString(), volume, false, 0, 0, true, false); + m_SoundModule.SendSound(m_host.UUID, KeyOrName(sound, AssetType.Sound), volume, false, 0, 0, true, false); } } @@ -2419,7 +2455,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api // send the sound, once, to all clients in rangeTrigger or play an attached sound in this part's inventory. if (m_SoundModule != null) { - m_SoundModule.SendSound(m_host.UUID, KeyOrName(sound).ToString(), volume, true, 0, 0, false, false); + m_SoundModule.SendSound(m_host.UUID, KeyOrName(sound, AssetType.Sound), volume, true, 0, 0, false, false); } } @@ -5838,7 +5874,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api float radius1 = (float)llVecDist(llGetPos(), top_north_east); float radius2 = (float)llVecDist(llGetPos(), bottom_south_west); float radius = Math.Abs(radius1 - radius2); - m_SoundModule.SendSound(m_host.UUID, KeyOrName(sound).ToString(), volume, true, 0, radius, false, false); + m_SoundModule.SendSound(m_host.UUID, KeyOrName(sound, AssetType.Sound), volume, true, 0, radius, false, false); } } -- cgit v1.1 From c796f7861e318cc12248f3a86ee5b29e3fa99d79 Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Tue, 16 Oct 2012 12:44:09 +0100 Subject: 80-character width terminal formatting of recent commits to llPlaySound, llPlaySoundSlave, llTriggerSound and llTriggerSoundLimited --- .../Shared/Api/Implementation/LSL_Api.cs | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 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 869d94e..610cb14 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -2405,7 +2405,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api // send the sound, once, to all clients in range if (m_SoundModule != null) { - m_SoundModule.SendSound(m_host.UUID, KeyOrName(sound, AssetType.Sound), volume, false, 0, 0, false, false); + m_SoundModule.SendSound(m_host.UUID, + KeyOrName(sound, AssetType.Sound), volume, false, 0, + 0, false, false); } } @@ -2445,7 +2447,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api // send the sound, once, to all clients in range if (m_SoundModule != null) { - m_SoundModule.SendSound(m_host.UUID, KeyOrName(sound, AssetType.Sound), volume, false, 0, 0, true, false); + m_SoundModule.SendSound(m_host.UUID, + KeyOrName(sound, AssetType.Sound), volume, false, 0, + 0, true, false); } } @@ -2455,7 +2459,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api // send the sound, once, to all clients in rangeTrigger or play an attached sound in this part's inventory. if (m_SoundModule != null) { - m_SoundModule.SendSound(m_host.UUID, KeyOrName(sound, AssetType.Sound), volume, true, 0, 0, false, false); + m_SoundModule.SendSound(m_host.UUID, + KeyOrName(sound, AssetType.Sound), volume, true, 0, 0, + false, false); } } @@ -5871,10 +5877,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api m_host.AddScriptLPS(1); if (m_SoundModule != null) { - float radius1 = (float)llVecDist(llGetPos(), top_north_east); - float radius2 = (float)llVecDist(llGetPos(), bottom_south_west); - float radius = Math.Abs(radius1 - radius2); - m_SoundModule.SendSound(m_host.UUID, KeyOrName(sound, AssetType.Sound), volume, true, 0, radius, false, false); + float radius1 = (float)llVecDist(llGetPos(), top_north_east); + float radius2 = (float)llVecDist(llGetPos(), bottom_south_west); + float radius = Math.Abs(radius1 - radius2); + m_SoundModule.SendSound(m_host.UUID, + KeyOrName(sound, AssetType.Sound), volume, true, 0, + radius, false, false); } } -- cgit v1.1 From f9923d4423f8f9dcf09a12e702737d2030a26d4a Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Tue, 16 Oct 2012 12:45:30 +0100 Subject: shifting from two instances of typecasting to one instance of typecasting in llTriggerSoundLimited --- OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 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 610cb14..2b6a3fd 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -5877,12 +5877,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api m_host.AddScriptLPS(1); if (m_SoundModule != null) { - float radius1 = (float)llVecDist(llGetPos(), top_north_east); - float radius2 = (float)llVecDist(llGetPos(), bottom_south_west); - float radius = Math.Abs(radius1 - radius2); + double radius1 = llVecDist(llGetPos(), top_north_east); + double radius2 = llVecDist(llGetPos(), bottom_south_west); + double radius = Math.Abs(radius1 - radius2); m_SoundModule.SendSound(m_host.UUID, KeyOrName(sound, AssetType.Sound), volume, true, 0, - radius, false, false); + (float)radius, false, false); } } -- cgit v1.1 From af9dc483e9db950ca4187a7afe186da80d2c7acf Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Tue, 16 Oct 2012 12:48:41 +0100 Subject: refactoring llGetPos() to take advantage of implicit converter --- OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 3 +-- 1 file changed, 1 insertion(+), 2 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 2b6a3fd..2654b5a 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -2082,8 +2082,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public LSL_Vector llGetPos() { m_host.AddScriptLPS(1); - Vector3 pos = m_host.GetWorldPosition(); - return new LSL_Vector(pos.X, pos.Y, pos.Z); + return m_host.GetWorldPosition(); } public LSL_Vector llGetLocalPos() -- cgit v1.1 From ef157110897ef162c7f076d6d5f423b8cd9a8f47 Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Tue, 16 Oct 2012 12:49:25 +0100 Subject: refactoring llTriggerSoundLimited to not use the LSL methods, since that will cause unnecessary calls to m_host.AddScriptLPS(1) --- OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 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 2654b5a..99b6189 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -5876,8 +5876,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api m_host.AddScriptLPS(1); if (m_SoundModule != null) { - double radius1 = llVecDist(llGetPos(), top_north_east); - double radius2 = llVecDist(llGetPos(), bottom_south_west); + double radius1 = VecDist(m_host.GetWorldPosition(), top_north_east); + double radius2 = VecDist(m_host.GetWorldPosition(), bottom_south_west); double radius = Math.Abs(radius1 - radius2); m_SoundModule.SendSound(m_host.UUID, KeyOrName(sound, AssetType.Sound), volume, true, 0, -- cgit v1.1 From a9999a9676d46669150343e4cdbf65428326a91d Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Tue, 16 Oct 2012 13:11:17 +0100 Subject: Refactoring llTriggerSoundLimited with a new method on ISoundModule, as the LL Wiki spec for llTriggerSoundLimited states an axis-aligned bounding box, not radial constraint --- .../World/Sound/SoundModuleNonShared.cs | 30 ++++++++++++++++++++++ .../Region/Framework/Interfaces/ISoundModule.cs | 3 +++ .../Shared/Api/Implementation/LSL_Api.cs | 9 +++---- 3 files changed, 36 insertions(+), 6 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/World/Sound/SoundModuleNonShared.cs b/OpenSim/Region/CoreModules/World/Sound/SoundModuleNonShared.cs index 417c071..ac7f7b4 100644 --- a/OpenSim/Region/CoreModules/World/Sound/SoundModuleNonShared.cs +++ b/OpenSim/Region/CoreModules/World/Sound/SoundModuleNonShared.cs @@ -334,6 +334,36 @@ namespace OpenSim.Region.CoreModules.World.Sound } } + public void TriggerSoundLimited(UUID objectID, UUID sound, + double volume, Vector3 min, Vector3 max) + { + if (sound == UUID.Zero) + return; + + SceneObjectPart part; + if (!m_scene.TryGetSceneObjectPart(objectID, out part)) + return; + + m_scene.ForEachRootScenePresence(delegate(ScenePresence sp) + { + double dis = Util.GetDistanceTo(sp.AbsolutePosition, + part.AbsolutePosition); + + if (dis > MaxDistance) // Max audio distance + return; + else if (!Util.IsInsideBox(sp.AbsolutePosition, min, max)) + return; + + // Scale by distance + double thisSpGain = volume * ((MaxDistance - dis) / MaxDistance); + + sp.ControllingClient.SendTriggeredSound(sound, part.OwnerID, + part.UUID, part.ParentGroup.UUID, + m_scene.RegionInfo.RegionHandle, + part.AbsolutePosition, (float)thisSpGain); + }); + } + #endregion } } diff --git a/OpenSim/Region/Framework/Interfaces/ISoundModule.cs b/OpenSim/Region/Framework/Interfaces/ISoundModule.cs index 5d1bb63..2e53b16 100644 --- a/OpenSim/Region/Framework/Interfaces/ISoundModule.cs +++ b/OpenSim/Region/Framework/Interfaces/ISoundModule.cs @@ -111,5 +111,8 @@ namespace OpenSim.Region.Framework.Interfaces void SendSound(UUID objectID, UUID sound, double volume, bool triggered, byte flags, float radius, bool useMaster, bool isMaster); + + void TriggerSoundLimited(UUID objectID, UUID sound, double volume, + Vector3 min, Vector3 max); } } \ No newline at end of file diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 99b6189..aeb74a5 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -5876,12 +5876,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api m_host.AddScriptLPS(1); if (m_SoundModule != null) { - double radius1 = VecDist(m_host.GetWorldPosition(), top_north_east); - double radius2 = VecDist(m_host.GetWorldPosition(), bottom_south_west); - double radius = Math.Abs(radius1 - radius2); - m_SoundModule.SendSound(m_host.UUID, - KeyOrName(sound, AssetType.Sound), volume, true, 0, - (float)radius, false, false); + m_SoundModule.TriggerSoundLimited(m_host.UUID, + KeyOrName(sound, AssetType.Sound), volume, + bottom_south_west, top_north_east); } } -- cgit v1.1 From dcac2a7f716e512b604cce02768770e1660600eb Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Tue, 16 Oct 2012 13:27:03 +0100 Subject: refactoring llCollisionSound to use new KeyOrName method --- .../Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 11 +---------- 1 file changed, 1 insertion(+), 10 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 aeb74a5..0fa247d 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -4342,16 +4342,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api m_host.AddScriptLPS(1); // TODO: Parameter check logic required. - UUID soundId = UUID.Zero; - if (!UUID.TryParse(impact_sound, out soundId)) - { - TaskInventoryItem item = m_host.Inventory.GetInventoryItem(impact_sound); - - if (item != null && item.Type == (int)AssetType.Sound) - soundId = item.AssetID; - } - - m_host.CollisionSound = soundId; + m_host.CollisionSound = KeyOrName(impact_sound, AssetType.Sound); m_host.CollisionSoundVolume = (float)impact_volume; } -- cgit v1.1 From 2bb041925160922be669d7e185fb5da6df0efd29 Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Tue, 16 Oct 2012 14:30:33 +0100 Subject: documenting some params on ISoundModule methods --- .../Region/Framework/Interfaces/ISoundModule.cs | 23 +++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Framework/Interfaces/ISoundModule.cs b/OpenSim/Region/Framework/Interfaces/ISoundModule.cs index 2e53b16..68af492 100644 --- a/OpenSim/Region/Framework/Interfaces/ISoundModule.cs +++ b/OpenSim/Region/Framework/Interfaces/ISoundModule.cs @@ -100,18 +100,27 @@ namespace OpenSim.Region.Framework.Interfaces /// /// Trigger or play an attached sound in this part's inventory. /// - /// - /// - /// - /// + /// Sound source ID + /// Sound asset ID + /// Sound volume + /// Triggered or not. /// - /// - /// - /// + /// Sound radius + /// Play using sound master + /// Play as sound master void SendSound(UUID objectID, UUID sound, double volume, bool triggered, byte flags, float radius, bool useMaster, bool isMaster); + /// + /// Trigger a sound to be played to all agents within an axis-aligned + /// bounding box. + /// + /// Sound source ID + /// Sound asset ID + /// Sound volume + /// AABB bottom south-west corner + /// AABB top north-east corner void TriggerSoundLimited(UUID objectID, UUID sound, double volume, Vector3 min, Vector3 max); } -- cgit v1.1 From e0b5a3cd900d8ad29cdb7d43415b069d5484a424 Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Tue, 16 Oct 2012 15:15:03 +0100 Subject: tweaking configuration logic so that the INonSharedRegionModule will load by default --- .../Region/CoreModules/World/Sound/SoundModuleNonShared.cs | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/World/Sound/SoundModuleNonShared.cs b/OpenSim/Region/CoreModules/World/Sound/SoundModuleNonShared.cs index ac7f7b4..68bd413 100644 --- a/OpenSim/Region/CoreModules/World/Sound/SoundModuleNonShared.cs +++ b/OpenSim/Region/CoreModules/World/Sound/SoundModuleNonShared.cs @@ -58,10 +58,15 @@ namespace OpenSim.Region.CoreModules.World.Sound IConfig config = configSource.Configs["Sounds"]; if (config == null) - return; - - Enabled = config.GetString("Module", "SoundModuleNonShared") == "SoundModuleNonShared"; - MaxDistance = config.GetFloat("MaxDistance", 100.0f); + { + Enabled = true; + MaxDistance = 100.0f; + } + else + { + Enabled = config.GetString("Module", "SoundModuleNonShared") == "SoundModuleNonShared"; + MaxDistance = config.GetFloat("MaxDistance", 100.0f); + } } public void AddRegion(Scene scene) { } -- cgit v1.1 From e308841de98ed3798b1c960c84831588b6598123 Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Tue, 16 Oct 2012 15:28:22 +0100 Subject: SianaGearz notes stop sound flag is 1 << 5, so using that for ISoundModule.StopSound rather than setting gain to zero --- OpenSim/Region/CoreModules/World/Sound/SoundModuleNonShared.cs | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/World/Sound/SoundModuleNonShared.cs b/OpenSim/Region/CoreModules/World/Sound/SoundModuleNonShared.cs index 68bd413..c163e86 100644 --- a/OpenSim/Region/CoreModules/World/Sound/SoundModuleNonShared.cs +++ b/OpenSim/Region/CoreModules/World/Sound/SoundModuleNonShared.cs @@ -204,8 +204,7 @@ namespace OpenSim.Region.CoreModules.World.Sound foreach (SceneObjectPart part in m_host.ParentGroup.LoopSoundSlavePrims) { part.Sound = UUID.Zero; - part.SoundGain = 0; - part.SoundFlags = 0; + part.SoundFlags = 1 << 5; part.SoundRadius = 0; part.ScheduleFullUpdate(); part.SendFullUpdateToAllClients(); @@ -216,8 +215,7 @@ namespace OpenSim.Region.CoreModules.World.Sound else { m_host.Sound = UUID.Zero; - m_host.SoundGain = 0; - m_host.SoundFlags = 0; + m_host.SoundFlags = 1 << 5; m_host.SoundRadius = 0; m_host.ScheduleFullUpdate(); m_host.SendFullUpdateToAllClients(); @@ -226,8 +224,7 @@ namespace OpenSim.Region.CoreModules.World.Sound else { m_host.Sound = UUID.Zero; - m_host.SoundGain = 0; - m_host.SoundFlags = 0; + m_host.SoundFlags = 1 << 5; m_host.SoundRadius = 0; m_host.ScheduleFullUpdate(); m_host.SendFullUpdateToAllClients(); -- cgit v1.1 From a16ddbee4116fd1234bb2d53598616d5345c09c9 Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Mon, 29 Oct 2012 16:05:02 +0000 Subject: Renaming module back to SoundModule as the hypothetical plan was to make another module using the shared region module interface, but this was pointed out by Melanie_T to be mostly pointless. --- .../Region/CoreModules/World/Sound/SoundModule.cs | 371 +++++++++++++++++++++ .../World/Sound/SoundModuleNonShared.cs | 371 --------------------- 2 files changed, 371 insertions(+), 371 deletions(-) create mode 100644 OpenSim/Region/CoreModules/World/Sound/SoundModule.cs delete mode 100644 OpenSim/Region/CoreModules/World/Sound/SoundModuleNonShared.cs (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/World/Sound/SoundModule.cs b/OpenSim/Region/CoreModules/World/Sound/SoundModule.cs new file mode 100644 index 0000000..1db6519 --- /dev/null +++ b/OpenSim/Region/CoreModules/World/Sound/SoundModule.cs @@ -0,0 +1,371 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +using System; +using System.Collections.Generic; +using System.Reflection; + +using Nini.Config; +using OpenMetaverse; +using log4net; +using Mono.Addins; + +using OpenSim.Framework; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; + +namespace OpenSim.Region.CoreModules.World.Sound +{ + [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "SoundModule")] + public class SoundModule : INonSharedRegionModule, ISoundModule + { + private static readonly ILog m_log = LogManager.GetLogger( + MethodBase.GetCurrentMethod().DeclaringType); + + private Scene m_scene; + + public bool Enabled { get; private set; } + + public float MaxDistance { get; private set; } + + #region INonSharedRegionModule + + public void Initialise(IConfigSource configSource) + { + IConfig config = configSource.Configs["Sounds"]; + + if (config == null) + { + Enabled = true; + MaxDistance = 100.0f; + } + else + { + Enabled = config.GetString("Module", "SoundModule") == "SoundModule"; + MaxDistance = config.GetFloat("MaxDistance", 100.0f); + } + } + + public void AddRegion(Scene scene) { } + + public void RemoveRegion(Scene scene) + { + m_scene.EventManager.OnClientLogin -= OnNewClient; + } + + public void RegionLoaded(Scene scene) + { + if (!Enabled) + return; + + m_scene = scene; + m_scene.EventManager.OnClientLogin += OnNewClient; + + m_scene.RegisterModuleInterface(this); + } + + public void Close() { } + + public Type ReplaceableInterface + { + get { return typeof(ISoundModule); } + } + + public string Name { get { return "Sound Module"; } } + + #endregion + + #region Event Handlers + + private void OnNewClient(IClientAPI client) + { + client.OnSoundTrigger += TriggerSound; + } + + #endregion + + #region ISoundModule + + public virtual void PlayAttachedSound( + UUID soundID, UUID ownerID, UUID objectID, double gain, Vector3 position, byte flags, float radius) + { + SceneObjectPart part; + if (!m_scene.TryGetSceneObjectPart(objectID, out part)) + return; + + SceneObjectGroup grp = part.ParentGroup; + + if (radius == 0) + radius = MaxDistance; + + m_scene.ForEachRootScenePresence(delegate(ScenePresence sp) + { + double dis = Util.GetDistanceTo(sp.AbsolutePosition, position); + if (dis > MaxDistance) // Max audio distance + return; + + if (grp.IsAttachment) + { + if (grp.HasPrivateAttachmentPoint && sp.ControllingClient.AgentId != grp.OwnerID) + return; + + if (sp.ControllingClient.AgentId == grp.OwnerID) + dis = 0; + } + + // Scale by distance + double thisSpGain = gain * ((radius - dis) / radius); + + sp.ControllingClient.SendPlayAttachedSound(soundID, objectID, + ownerID, (float)thisSpGain, flags); + }); + } + + public virtual void TriggerSound( + UUID soundId, UUID ownerID, UUID objectID, UUID parentID, double gain, Vector3 position, UInt64 handle, float radius) + { + SceneObjectPart part; + if (!m_scene.TryGetSceneObjectPart(objectID, out part)) + { + ScenePresence sp; + if (!m_scene.TryGetScenePresence(ownerID, out sp)) + return; + } + else + { + SceneObjectGroup grp = part.ParentGroup; + + if (grp.IsAttachment && grp.AttachmentPoint > 30) + { + objectID = ownerID; + parentID = ownerID; + } + } + + if (radius == 0) + radius = MaxDistance; + + m_scene.ForEachRootScenePresence(delegate(ScenePresence sp) + { + double dis = Util.GetDistanceTo(sp.AbsolutePosition, position); + + if (dis > MaxDistance) // Max audio distance + return; + + // Scale by distance + double thisSpGain = gain * ((radius - dis) / radius); + + sp.ControllingClient.SendTriggeredSound(soundId, ownerID, + objectID, parentID, handle, position, + (float)thisSpGain); + }); + } + + public virtual void StopSound(UUID objectID) + { + SceneObjectPart m_host; + if (!m_scene.TryGetSceneObjectPart(objectID, out m_host)) + return; + + StopSound(m_host); + } + + private static void StopSound(SceneObjectPart m_host) + { + m_host.AdjustSoundGain(0); + // Xantor 20080528: Clear prim data of sound instead + if (m_host.ParentGroup.LoopSoundSlavePrims.Contains(m_host)) + { + if (m_host.ParentGroup.LoopSoundMasterPrim == m_host) + { + foreach (SceneObjectPart part in m_host.ParentGroup.LoopSoundSlavePrims) + { + part.Sound = UUID.Zero; + part.SoundFlags = 1 << 5; + part.SoundRadius = 0; + part.ScheduleFullUpdate(); + part.SendFullUpdateToAllClients(); + } + m_host.ParentGroup.LoopSoundMasterPrim = null; + m_host.ParentGroup.LoopSoundSlavePrims.Clear(); + } + else + { + m_host.Sound = UUID.Zero; + m_host.SoundFlags = 1 << 5; + m_host.SoundRadius = 0; + m_host.ScheduleFullUpdate(); + m_host.SendFullUpdateToAllClients(); + } + } + else + { + m_host.Sound = UUID.Zero; + m_host.SoundFlags = 1 << 5; + m_host.SoundRadius = 0; + m_host.ScheduleFullUpdate(); + m_host.SendFullUpdateToAllClients(); + } + } + + public virtual void PreloadSound(UUID objectID, UUID soundID, float radius) + { + SceneObjectPart part; + if (soundID == UUID.Zero + || !m_scene.TryGetSceneObjectPart(objectID, out part)) + { + return; + } + + if (radius == 0) + radius = MaxDistance; + + m_scene.ForEachRootScenePresence(delegate(ScenePresence sp) + { + if (!(Util.GetDistanceTo(sp.AbsolutePosition, part.AbsolutePosition) >= MaxDistance)) + sp.ControllingClient.SendPreLoadSound(objectID, objectID, soundID); + }); + } + + // Xantor 20080528 we should do this differently. + // 1) apply the sound to the object + // 2) schedule full update + // just sending the sound out once doesn't work so well when other avatars come in view later on + // or when the prim gets moved, changed, sat on, whatever + // see large number of mantises (mantes?) + // 20080530 Updated to remove code duplication + // 20080530 Stop sound if there is one, otherwise volume only changes don't work + public void LoopSound(UUID objectID, UUID soundID, + double volume, double radius, bool isMaster) + { + SceneObjectPart m_host; + if (!m_scene.TryGetSceneObjectPart(objectID, out m_host)) + return; + + if (isMaster) + m_host.ParentGroup.LoopSoundMasterPrim = m_host; + + if (m_host.Sound != UUID.Zero) + StopSound(m_host); + + m_host.Sound = soundID; + m_host.SoundGain = volume; + m_host.SoundFlags = 1; // looping + m_host.SoundRadius = radius; + + m_host.ScheduleFullUpdate(); + m_host.SendFullUpdateToAllClients(); + } + + public void SendSound(UUID objectID, UUID soundID, double volume, + bool triggered, byte flags, float radius, bool useMaster, + bool isMaster) + { + if (soundID == UUID.Zero) + return; + + SceneObjectPart part; + if (!m_scene.TryGetSceneObjectPart(objectID, out part)) + return; + + volume = Util.Clip((float)volume, 0, 1); + + UUID parentID = part.ParentGroup.UUID; + + Vector3 position = part.AbsolutePosition; // region local + ulong regionHandle = m_scene.RegionInfo.RegionHandle; + + if (useMaster) + { + if (isMaster) + { + if (triggered) + TriggerSound(soundID, part.OwnerID, part.UUID, parentID, volume, position, regionHandle, radius); + else + PlayAttachedSound(soundID, part.OwnerID, part.UUID, volume, position, flags, radius); + part.ParentGroup.PlaySoundMasterPrim = part; + if (triggered) + TriggerSound(soundID, part.OwnerID, part.UUID, parentID, volume, position, regionHandle, radius); + else + PlayAttachedSound(soundID, part.OwnerID, part.UUID, volume, position, flags, radius); + foreach (SceneObjectPart prim in part.ParentGroup.PlaySoundSlavePrims) + { + position = prim.AbsolutePosition; // region local + if (triggered) + TriggerSound(soundID, part.OwnerID, prim.UUID, parentID, volume, position, regionHandle, radius); + else + PlayAttachedSound(soundID, part.OwnerID, prim.UUID, volume, position, flags, radius); + } + part.ParentGroup.PlaySoundSlavePrims.Clear(); + part.ParentGroup.PlaySoundMasterPrim = null; + } + else + { + part.ParentGroup.PlaySoundSlavePrims.Add(part); + } + } + else + { + if (triggered) + TriggerSound(soundID, part.OwnerID, part.UUID, parentID, volume, position, regionHandle, radius); + else + PlayAttachedSound(soundID, part.OwnerID, part.UUID, volume, position, flags, radius); + } + } + + public void TriggerSoundLimited(UUID objectID, UUID sound, + double volume, Vector3 min, Vector3 max) + { + if (sound == UUID.Zero) + return; + + SceneObjectPart part; + if (!m_scene.TryGetSceneObjectPart(objectID, out part)) + return; + + m_scene.ForEachRootScenePresence(delegate(ScenePresence sp) + { + double dis = Util.GetDistanceTo(sp.AbsolutePosition, + part.AbsolutePosition); + + if (dis > MaxDistance) // Max audio distance + return; + else if (!Util.IsInsideBox(sp.AbsolutePosition, min, max)) + return; + + // Scale by distance + double thisSpGain = volume * ((MaxDistance - dis) / MaxDistance); + + sp.ControllingClient.SendTriggeredSound(sound, part.OwnerID, + part.UUID, part.ParentGroup.UUID, + m_scene.RegionInfo.RegionHandle, + part.AbsolutePosition, (float)thisSpGain); + }); + } + + #endregion + } +} diff --git a/OpenSim/Region/CoreModules/World/Sound/SoundModuleNonShared.cs b/OpenSim/Region/CoreModules/World/Sound/SoundModuleNonShared.cs deleted file mode 100644 index c163e86..0000000 --- a/OpenSim/Region/CoreModules/World/Sound/SoundModuleNonShared.cs +++ /dev/null @@ -1,371 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -using System; -using System.Collections.Generic; -using System.Reflection; - -using Nini.Config; -using OpenMetaverse; -using log4net; -using Mono.Addins; - -using OpenSim.Framework; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; - -namespace OpenSim.Region.CoreModules.World.Sound -{ - [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "SoundModuleNonShared")] - public class SoundModuleNonShared : INonSharedRegionModule, ISoundModule - { - private static readonly ILog m_log = LogManager.GetLogger( - MethodBase.GetCurrentMethod().DeclaringType); - - private Scene m_scene; - - public bool Enabled { get; private set; } - - public float MaxDistance { get; private set; } - - #region INonSharedRegionModule - - public void Initialise(IConfigSource configSource) - { - IConfig config = configSource.Configs["Sounds"]; - - if (config == null) - { - Enabled = true; - MaxDistance = 100.0f; - } - else - { - Enabled = config.GetString("Module", "SoundModuleNonShared") == "SoundModuleNonShared"; - MaxDistance = config.GetFloat("MaxDistance", 100.0f); - } - } - - public void AddRegion(Scene scene) { } - - public void RemoveRegion(Scene scene) - { - m_scene.EventManager.OnClientLogin -= OnNewClient; - } - - public void RegionLoaded(Scene scene) - { - if (!Enabled) - return; - - m_scene = scene; - m_scene.EventManager.OnClientLogin += OnNewClient; - - m_scene.RegisterModuleInterface(this); - } - - public void Close() { } - - public Type ReplaceableInterface - { - get { return typeof(ISoundModule); } - } - - public string Name { get { return "Sound Module"; } } - - #endregion - - #region Event Handlers - - private void OnNewClient(IClientAPI client) - { - client.OnSoundTrigger += TriggerSound; - } - - #endregion - - #region ISoundModule - - public virtual void PlayAttachedSound( - UUID soundID, UUID ownerID, UUID objectID, double gain, Vector3 position, byte flags, float radius) - { - SceneObjectPart part; - if (!m_scene.TryGetSceneObjectPart(objectID, out part)) - return; - - SceneObjectGroup grp = part.ParentGroup; - - if (radius == 0) - radius = MaxDistance; - - m_scene.ForEachRootScenePresence(delegate(ScenePresence sp) - { - double dis = Util.GetDistanceTo(sp.AbsolutePosition, position); - if (dis > MaxDistance) // Max audio distance - return; - - if (grp.IsAttachment) - { - if (grp.HasPrivateAttachmentPoint && sp.ControllingClient.AgentId != grp.OwnerID) - return; - - if (sp.ControllingClient.AgentId == grp.OwnerID) - dis = 0; - } - - // Scale by distance - double thisSpGain = gain * ((radius - dis) / radius); - - sp.ControllingClient.SendPlayAttachedSound(soundID, objectID, - ownerID, (float)thisSpGain, flags); - }); - } - - public virtual void TriggerSound( - UUID soundId, UUID ownerID, UUID objectID, UUID parentID, double gain, Vector3 position, UInt64 handle, float radius) - { - SceneObjectPart part; - if (!m_scene.TryGetSceneObjectPart(objectID, out part)) - { - ScenePresence sp; - if (!m_scene.TryGetScenePresence(ownerID, out sp)) - return; - } - else - { - SceneObjectGroup grp = part.ParentGroup; - - if (grp.IsAttachment && grp.AttachmentPoint > 30) - { - objectID = ownerID; - parentID = ownerID; - } - } - - if (radius == 0) - radius = MaxDistance; - - m_scene.ForEachRootScenePresence(delegate(ScenePresence sp) - { - double dis = Util.GetDistanceTo(sp.AbsolutePosition, position); - - if (dis > MaxDistance) // Max audio distance - return; - - // Scale by distance - double thisSpGain = gain * ((radius - dis) / radius); - - sp.ControllingClient.SendTriggeredSound(soundId, ownerID, - objectID, parentID, handle, position, - (float)thisSpGain); - }); - } - - public virtual void StopSound(UUID objectID) - { - SceneObjectPart m_host; - if (!m_scene.TryGetSceneObjectPart(objectID, out m_host)) - return; - - StopSound(m_host); - } - - private static void StopSound(SceneObjectPart m_host) - { - m_host.AdjustSoundGain(0); - // Xantor 20080528: Clear prim data of sound instead - if (m_host.ParentGroup.LoopSoundSlavePrims.Contains(m_host)) - { - if (m_host.ParentGroup.LoopSoundMasterPrim == m_host) - { - foreach (SceneObjectPart part in m_host.ParentGroup.LoopSoundSlavePrims) - { - part.Sound = UUID.Zero; - part.SoundFlags = 1 << 5; - part.SoundRadius = 0; - part.ScheduleFullUpdate(); - part.SendFullUpdateToAllClients(); - } - m_host.ParentGroup.LoopSoundMasterPrim = null; - m_host.ParentGroup.LoopSoundSlavePrims.Clear(); - } - else - { - m_host.Sound = UUID.Zero; - m_host.SoundFlags = 1 << 5; - m_host.SoundRadius = 0; - m_host.ScheduleFullUpdate(); - m_host.SendFullUpdateToAllClients(); - } - } - else - { - m_host.Sound = UUID.Zero; - m_host.SoundFlags = 1 << 5; - m_host.SoundRadius = 0; - m_host.ScheduleFullUpdate(); - m_host.SendFullUpdateToAllClients(); - } - } - - public virtual void PreloadSound(UUID objectID, UUID soundID, float radius) - { - SceneObjectPart part; - if (soundID == UUID.Zero - || !m_scene.TryGetSceneObjectPart(objectID, out part)) - { - return; - } - - if (radius == 0) - radius = MaxDistance; - - m_scene.ForEachRootScenePresence(delegate(ScenePresence sp) - { - if (!(Util.GetDistanceTo(sp.AbsolutePosition, part.AbsolutePosition) >= MaxDistance)) - sp.ControllingClient.SendPreLoadSound(objectID, objectID, soundID); - }); - } - - // Xantor 20080528 we should do this differently. - // 1) apply the sound to the object - // 2) schedule full update - // just sending the sound out once doesn't work so well when other avatars come in view later on - // or when the prim gets moved, changed, sat on, whatever - // see large number of mantises (mantes?) - // 20080530 Updated to remove code duplication - // 20080530 Stop sound if there is one, otherwise volume only changes don't work - public void LoopSound(UUID objectID, UUID soundID, - double volume, double radius, bool isMaster) - { - SceneObjectPart m_host; - if (!m_scene.TryGetSceneObjectPart(objectID, out m_host)) - return; - - if (isMaster) - m_host.ParentGroup.LoopSoundMasterPrim = m_host; - - if (m_host.Sound != UUID.Zero) - StopSound(m_host); - - m_host.Sound = soundID; - m_host.SoundGain = volume; - m_host.SoundFlags = 1; // looping - m_host.SoundRadius = radius; - - m_host.ScheduleFullUpdate(); - m_host.SendFullUpdateToAllClients(); - } - - public void SendSound(UUID objectID, UUID soundID, double volume, - bool triggered, byte flags, float radius, bool useMaster, - bool isMaster) - { - if (soundID == UUID.Zero) - return; - - SceneObjectPart part; - if (!m_scene.TryGetSceneObjectPart(objectID, out part)) - return; - - volume = Util.Clip((float)volume, 0, 1); - - UUID parentID = part.ParentGroup.UUID; - - Vector3 position = part.AbsolutePosition; // region local - ulong regionHandle = m_scene.RegionInfo.RegionHandle; - - if (useMaster) - { - if (isMaster) - { - if (triggered) - TriggerSound(soundID, part.OwnerID, part.UUID, parentID, volume, position, regionHandle, radius); - else - PlayAttachedSound(soundID, part.OwnerID, part.UUID, volume, position, flags, radius); - part.ParentGroup.PlaySoundMasterPrim = part; - if (triggered) - TriggerSound(soundID, part.OwnerID, part.UUID, parentID, volume, position, regionHandle, radius); - else - PlayAttachedSound(soundID, part.OwnerID, part.UUID, volume, position, flags, radius); - foreach (SceneObjectPart prim in part.ParentGroup.PlaySoundSlavePrims) - { - position = prim.AbsolutePosition; // region local - if (triggered) - TriggerSound(soundID, part.OwnerID, prim.UUID, parentID, volume, position, regionHandle, radius); - else - PlayAttachedSound(soundID, part.OwnerID, prim.UUID, volume, position, flags, radius); - } - part.ParentGroup.PlaySoundSlavePrims.Clear(); - part.ParentGroup.PlaySoundMasterPrim = null; - } - else - { - part.ParentGroup.PlaySoundSlavePrims.Add(part); - } - } - else - { - if (triggered) - TriggerSound(soundID, part.OwnerID, part.UUID, parentID, volume, position, regionHandle, radius); - else - PlayAttachedSound(soundID, part.OwnerID, part.UUID, volume, position, flags, radius); - } - } - - public void TriggerSoundLimited(UUID objectID, UUID sound, - double volume, Vector3 min, Vector3 max) - { - if (sound == UUID.Zero) - return; - - SceneObjectPart part; - if (!m_scene.TryGetSceneObjectPart(objectID, out part)) - return; - - m_scene.ForEachRootScenePresence(delegate(ScenePresence sp) - { - double dis = Util.GetDistanceTo(sp.AbsolutePosition, - part.AbsolutePosition); - - if (dis > MaxDistance) // Max audio distance - return; - else if (!Util.IsInsideBox(sp.AbsolutePosition, min, max)) - return; - - // Scale by distance - double thisSpGain = volume * ((MaxDistance - dis) / MaxDistance); - - sp.ControllingClient.SendTriggeredSound(sound, part.OwnerID, - part.UUID, part.ParentGroup.UUID, - m_scene.RegionInfo.RegionHandle, - part.AbsolutePosition, (float)thisSpGain); - }); - } - - #endregion - } -} -- cgit v1.1 From a09cba6da363606f0e2d63118b63f5b05232c452 Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Mon, 29 Oct 2012 16:17:18 +0000 Subject: refactoring to use assembly:classname style of configuration --- OpenSim/Region/CoreModules/World/Sound/SoundModule.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/World/Sound/SoundModule.cs b/OpenSim/Region/CoreModules/World/Sound/SoundModule.cs index 1db6519..513a8f5 100644 --- a/OpenSim/Region/CoreModules/World/Sound/SoundModule.cs +++ b/OpenSim/Region/CoreModules/World/Sound/SoundModule.cs @@ -25,6 +25,7 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ using System; +using System.IO; using System.Collections.Generic; using System.Reflection; @@ -64,7 +65,9 @@ namespace OpenSim.Region.CoreModules.World.Sound } else { - Enabled = config.GetString("Module", "SoundModule") == "SoundModule"; + Enabled = config.GetString("Module", "OpenSim.Region.CoreModules.dll:SoundModule") == + Path.GetFileName(Assembly.GetExecutingAssembly().Location) + + ":" + MethodBase.GetCurrentMethod().DeclaringType.Name; MaxDistance = config.GetFloat("MaxDistance", 100.0f); } } -- cgit v1.1 From aeeed29d627f7d40bbcc160bf446a019b54e8b32 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Tue, 30 Oct 2012 01:07:14 +0000 Subject: correct ODEPrim.MeshAssetReveived -> MeshAssetReceived --- OpenSim/Region/Physics/OdePlugin/ODEPrim.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs b/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs index 2548648..7c46ff8 100644 --- a/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs +++ b/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs @@ -3335,7 +3335,6 @@ Console.WriteLine(" JointCreateFixed"); m_material = pMaterial; } - private void CheckMeshAsset() { if (_pbs.SculptEntry && !m_assetFailed && _pbs.SculptTexture != UUID.Zero) @@ -3345,12 +3344,12 @@ Console.WriteLine(" JointCreateFixed"); { RequestAssetDelegate assetProvider = _parent_scene.RequestAssetMethod; if (assetProvider != null) - assetProvider(_pbs.SculptTexture, MeshAssetReveived); + assetProvider(_pbs.SculptTexture, MeshAssetReceived); }); } } - void MeshAssetReveived(AssetBase asset) + void MeshAssetReceived(AssetBase asset) { if (asset.Data != null && asset.Data.Length > 0) { -- cgit v1.1 From 37de965233ad6c25c2ce7a29d89762aa478a6147 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Tue, 30 Oct 2012 01:08:00 +0000 Subject: Make MeshAssetReceived private. Keep methods private unless they need to be opened up to external callers. Reduces analysis complexity. --- OpenSim/Region/Physics/OdePlugin/ODEPrim.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs b/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs index 7c46ff8..5b49e3b 100644 --- a/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs +++ b/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs @@ -3349,7 +3349,7 @@ Console.WriteLine(" JointCreateFixed"); } } - void MeshAssetReceived(AssetBase asset) + private void MeshAssetReceived(AssetBase asset) { if (asset.Data != null && asset.Data.Length > 0) { -- cgit v1.1 From cccf6953276eda0af34fb7b8e95c2c4351db5546 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Tue, 30 Oct 2012 01:14:48 +0000 Subject: Add asset != null check to ODEPrim.MeshAssetReceived instead of throwing exception. In some cases (such as failure to receive response from asset service), it is possible for a null to be returned from IAssetService.Get(string, object, AssetRetrieved). --- OpenSim/Region/Physics/OdePlugin/ODEPrim.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs b/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs index 5b49e3b..2637295 100644 --- a/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs +++ b/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs @@ -3351,7 +3351,7 @@ Console.WriteLine(" JointCreateFixed"); private void MeshAssetReceived(AssetBase asset) { - if (asset.Data != null && asset.Data.Length > 0) + if (asset != null && asset.Data != null && asset.Data.Length > 0) { if (!_pbs.SculptEntry) return; -- cgit v1.1 From d15d71a7efd2e1d3510111cbc9e617fc113fc29c Mon Sep 17 00:00:00 2001 From: Melanie Date: Tue, 30 Oct 2012 01:28:03 +0000 Subject: Put back the collision sound shim into SOP --- OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | 29 ++++++++++++++++++++++ 1 file changed, 29 insertions(+) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index b7f4291..5714fdd 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -2864,6 +2864,35 @@ namespace OpenSim.Region.Framework.Scenes SendLandCollisionEvent(scriptEvents.land_collision_end, ParentGroup.Scene.EventManager.TriggerScriptLandCollidingEnd); } + // The Collision sounds code calls this + public void SendCollisionSound(UUID soundID, double volume, Vector3 position) + { + if (soundID == UUID.Zero) + return; + + ISoundModule soundModule = ParentGroup.Scene.RequestModuleInterface(); + if (soundModule == null) + return; + + if (volume > 1) + volume = 1; + if (volume < 0) + volume = 0; + + int now = Util.EnvironmentTickCount(); + if(Util.EnvironmentTickCountSubtract(now,LastColSoundSentTime) <200) + return; + + LastColSoundSentTime = now; + + UUID ownerID = OwnerID; + UUID objectID = ParentGroup.RootPart.UUID; + UUID parentID = ParentGroup.UUID; + ulong regionHandle = ParentGroup.Scene.RegionInfo.RegionHandle; + + soundModule.TriggerSound(soundID, ownerID, objectID, parentID, volume, position, regionHandle, 0 ); + } + public void PhysicsOutOfBounds(Vector3 pos) { m_log.Error("[PHYSICS]: Physical Object went out of bounds."); -- cgit v1.1 From ff6c69000e3f192f81e7408a522b78d91521a5ff Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Tue, 30 Oct 2012 01:40:59 +0000 Subject: Log warning if mesh/sculpt asset couldn't be found by ODEPrim.MeshAssetReceived() callback. Presumably this is now more useful if the false positive from the old method of loading mesh assets have been eliminated. --- OpenSim/Region/Physics/OdePlugin/ODEPrim.cs | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs b/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs index 2637295..5a0b8d1 100644 --- a/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs +++ b/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs @@ -3364,6 +3364,12 @@ Console.WriteLine(" JointCreateFixed"); m_taintshape = true; _parent_scene.AddPhysicsActorTaint(this); } + else + { + m_log.WarnFormat( + "[ODE PRIM]: Could not get mesh/sculpt asset {0} for {1} at {2} in {3}", + _pbs.SculptTexture, Name, _position, _parent_scene.Name); + } } } } \ No newline at end of file -- cgit v1.1 From 984faf24dfaea26cdd436c8097abf334b74ebed8 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Tue, 30 Oct 2012 01:48:05 +0000 Subject: Only create a new list to check if objects have reached targets if there actually are any targets. --- OpenSim/Region/Framework/Scenes/Scene.cs | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 7d8cbf5..69c1027 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -1692,15 +1692,19 @@ namespace OpenSim.Region.Framework.Scenes private void CheckAtTargets() { - List objs = new List(); + List objs = null; + lock (m_groupsWithTargets) { - foreach (SceneObjectGroup grp in m_groupsWithTargets.Values) - objs.Add(grp); + if (m_groupsWithTargets.Count != 0) + objs = new List(m_groupsWithTargets.Values); } - foreach (SceneObjectGroup entry in objs) - entry.checkAtTargets(); + if (objs != null) + { + foreach (SceneObjectGroup entry in objs) + entry.checkAtTargets(); + } } /// -- cgit v1.1 From fd9cb3cb68959c2dd42dd0645fef50161ac085a7 Mon Sep 17 00:00:00 2001 From: Melanie Date: Tue, 30 Oct 2012 23:08:22 +0000 Subject: Store and send the current movement animation state to a new sim on crossing --- OpenSim/Region/Framework/Scenes/Animation/AnimationSet.cs | 11 +++++++++++ OpenSim/Region/Framework/Scenes/ScenePresence.cs | 6 ++++++ 2 files changed, 17 insertions(+) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Framework/Scenes/Animation/AnimationSet.cs b/OpenSim/Region/Framework/Scenes/Animation/AnimationSet.cs index 3d8e8be..65ae445 100644 --- a/OpenSim/Region/Framework/Scenes/Animation/AnimationSet.cs +++ b/OpenSim/Region/Framework/Scenes/Animation/AnimationSet.cs @@ -45,6 +45,11 @@ namespace OpenSim.Region.Framework.Scenes.Animation private OpenSim.Framework.Animation m_defaultAnimation = new OpenSim.Framework.Animation(); private List m_animations = new List(); + public OpenSim.Framework.Animation DefaultAnimation + { + get { return m_defaultAnimation; } + } + public OpenSim.Framework.Animation ImplicitDefaultAnimation { get { return m_implicitDefaultAnimation; } @@ -126,6 +131,12 @@ namespace OpenSim.Region.Framework.Scenes.Animation return false; } + // Called from serialization only + public void SetImplicitDefaultAnimation(UUID animID, int sequenceNum, UUID objectID) + { + m_implicitDefaultAnimation = new OpenSim.Framework.Animation(animID, sequenceNum, objectID); + } + protected bool ResetDefaultAnimation() { return TrySetDefaultAnimation("STAND", 1, UUID.Zero); diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index aa82af4..71e322d 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -3075,6 +3075,8 @@ namespace OpenSim.Region.Framework.Scenes cAgent.Anims = Animator.Animations.ToArray(); } catch { } + cAgent.DefaultAnim = Animator.Animations.DefaultAnimation; + cAgent.AnimState = Animator.Animations.ImplicitDefaultAnimation; if (Scene.AttachmentsModule != null) Scene.AttachmentsModule.CopyAttachments(this, cAgent); @@ -3146,6 +3148,10 @@ namespace OpenSim.Region.Framework.Scenes // FIXME: Why is this null check necessary? Where are the cases where we get a null Anims object? if (cAgent.Anims != null) Animator.Animations.FromArray(cAgent.Anims); + if (cAgent.DefaultAnim != null) + Animator.Animations.SetDefaultAnimation(cAgent.DefaultAnim.AnimID, cAgent.DefaultAnim.SequenceNum, UUID.Zero); + if (cAgent.AnimState != null) + Animator.Animations.SetImplicitDefaultAnimation(cAgent.AnimState.AnimID, cAgent.AnimState.SequenceNum, UUID.Zero); if (Scene.AttachmentsModule != null) Scene.AttachmentsModule.CopyAttachments(cAgent, this); -- cgit v1.1 From 6235d16c3148bb6f9f881b0dc286deccfdf9148a Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Wed, 31 Oct 2012 00:31:18 +0000 Subject: Make "show object part" command correctly display script status. Uses new IEntityInventory.TryGetScriptInstanceRunning() Makes it clearer that TaskInventoryItem.ScriptRunning cannot be used as it is temporary and not updated. --- .../Avatar/Attachments/AttachmentsModule.cs | 6 +-- .../World/Objects/Commands/ObjectCommandsModule.cs | 8 +++- .../Framework/Interfaces/IEntityInventory.cs | 13 ++++++ .../Framework/Scenes/SceneObjectPartInventory.cs | 52 +++++++++++++++------- .../ScriptEngine/XEngine/Tests/XEngineTest.cs | 10 ++++- 5 files changed, 66 insertions(+), 23 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs index 2a513e9..24170fc 100644 --- a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs @@ -571,9 +571,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments if (grp.HasGroupChanged) { -// m_log.DebugFormat( -// "[ATTACHMENTS MODULE]: Updating asset for attachment {0}, attachpoint {1}", -// grp.UUID, grp.AttachmentPoint); + m_log.DebugFormat( + "[ATTACHMENTS MODULE]: Updating asset for attachment {0}, attachpoint {1}", + grp.UUID, grp.AttachmentPoint); string sceneObjectXml = SceneObjectSerializer.ToOriginalXmlFormat(grp, scriptedState); diff --git a/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs b/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs index b2c9bce..ab8f143 100644 --- a/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs +++ b/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs @@ -606,12 +606,18 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands cdt.AddColumn("Asset UUID", 36); foreach (TaskInventoryItem item in inv.GetInventoryItems()) + { + bool foundScriptInstance, scriptRunning; + foundScriptInstance + = SceneObjectPartInventory.TryGetScriptInstanceRunning(m_scene, item, out scriptRunning); + cdt.AddRow( item.Name, ((InventoryType)item.InvType).ToString(), - (InventoryType)item.InvType == InventoryType.LSL ? item.ScriptRunning.ToString() : "n/a", + foundScriptInstance ? scriptRunning.ToString() : "n/a", item.ItemID.ToString(), item.AssetID.ToString()); + } return sb.Append(cdt.ToString()); } diff --git a/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs b/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs index c457b2f..150193d 100644 --- a/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs +++ b/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs @@ -150,6 +150,19 @@ namespace OpenSim.Region.Framework.Interfaces void StopScriptInstance(UUID itemId); /// + /// Try to get the script running status. + /// + /// + /// Returns true if a script for the item was found in one of the simulator's script engines. In this case, + /// the running parameter will reflect the running status. + /// Returns false if the item could not be found, if the item is not a script or if a script instance for the + /// item was not found in any of the script engines. In this case, running status is irrelevant. + /// + /// + /// + bool TryGetScriptInstanceRunning(UUID itemId, out bool running); + + /// /// Add an item to this entity's inventory. If an item with the same name already exists, then an alternative /// name is chosen. /// diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs index bdb0446..db723fa 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs @@ -232,31 +232,49 @@ namespace OpenSim.Region.Framework.Scenes if (m_part == null || m_part.ParentGroup == null || m_part.ParentGroup.Scene == null) return; - IScriptModule[] engines = m_part.ParentGroup.Scene.RequestModuleInterfaces(); - if (engines == null) // No engine at all - return; - lock (Items) { foreach (TaskInventoryItem item in Items.Values) { - if (item.InvType == (int)InventoryType.LSL) - { - foreach (IScriptModule e in engines) - { - bool running; - - if (e.HasScript(item.ItemID, out running)) - { - item.ScriptRunning = running; - break; - } - } - } + bool running; + if (TryGetScriptInstanceRunning(m_part.ParentGroup.Scene, item, out running)) + item.ScriptRunning = running; } } } + public bool TryGetScriptInstanceRunning(UUID itemId, out bool running) + { + running = false; + + TaskInventoryItem item = GetInventoryItem(itemId); + + if (item == null) + return false; + + return TryGetScriptInstanceRunning(m_part.ParentGroup.Scene, item, out running); + } + + public static bool TryGetScriptInstanceRunning(Scene scene, TaskInventoryItem item, out bool running) + { + running = false; + + if (item.InvType != (int)InventoryType.LSL) + return false; + + IScriptModule[] engines = scene.RequestModuleInterfaces(); + if (engines == null) // No engine at all + return false; + + foreach (IScriptModule e in engines) + { + if (e.HasScript(item.ItemID, out running)) + return true; + } + + return false; + } + public int CreateScriptInstances(int startParam, bool postOnRez, string engine, int stateSource) { int scriptsValidForStarting = 0; diff --git a/OpenSim/Region/ScriptEngine/XEngine/Tests/XEngineTest.cs b/OpenSim/Region/ScriptEngine/XEngine/Tests/XEngineTest.cs index f247a0b..f331658 100644 --- a/OpenSim/Region/ScriptEngine/XEngine/Tests/XEngineTest.cs +++ b/OpenSim/Region/ScriptEngine/XEngine/Tests/XEngineTest.cs @@ -90,7 +90,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine.Tests // log4net.Config.XmlConfigurator.Configure(); UUID userId = TestHelpers.ParseTail(0x1); -// UUID objectId = TestHelpers.ParseTail(0x2); +// UUID objectId = TestHelpers.ParseTail(0x100); // UUID itemId = TestHelpers.ParseTail(0x3); string itemName = "TestStartScript() Item"; @@ -105,12 +105,18 @@ namespace OpenSim.Region.ScriptEngine.XEngine.Tests m_scene.EventManager.OnChatFromWorld += OnChatFromWorld; - m_scene.RezNewScript(userId, itemTemplate); + SceneObjectPart partWhereRezzed = m_scene.RezNewScript(userId, itemTemplate); m_chatEvent.WaitOne(60000); Assert.That(m_osChatMessageReceived, Is.Not.Null, "No chat message received in TestStartScript()"); Assert.That(m_osChatMessageReceived.Message, Is.EqualTo("Script running")); + + bool running; + TaskInventoryItem scriptItem = partWhereRezzed.Inventory.GetInventoryItem(itemName); + Assert.That( + SceneObjectPartInventory.TryGetScriptInstanceRunning(m_scene, scriptItem, out running), Is.True); + Assert.That(running, Is.True); } private void OnChatFromWorld(object sender, OSChatMessage oscm) -- cgit v1.1 From 4ba48151b232716ebb473bc320793a9610a96e5b Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Wed, 31 Oct 2012 00:39:45 +0000 Subject: Handle UUIDGroupName and ObjectGroup viewer UDP requests asynchronously rather than synchronously. This is to avoid the entire scene loop being held up when the group service is slow to respond. There's no obvious reason for these queries to be sync rather than async. --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 8e5a6d2..7382e09 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -5219,8 +5219,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP AddLocalPacketHandler(PacketType.MultipleObjectUpdate, HandleMultipleObjUpdate, false); AddLocalPacketHandler(PacketType.MoneyTransferRequest, HandleMoneyTransferRequest, false); AddLocalPacketHandler(PacketType.ParcelBuy, HandleParcelBuyRequest, false); - AddLocalPacketHandler(PacketType.UUIDGroupNameRequest, HandleUUIDGroupNameRequest, false); - AddLocalPacketHandler(PacketType.ObjectGroup, HandleObjectGroupRequest, false); + AddLocalPacketHandler(PacketType.UUIDGroupNameRequest, HandleUUIDGroupNameRequest); + AddLocalPacketHandler(PacketType.ObjectGroup, HandleObjectGroupRequest); AddLocalPacketHandler(PacketType.GenericMessage, HandleGenericMessage); AddLocalPacketHandler(PacketType.AvatarPropertiesRequest, HandleAvatarPropertiesRequest); AddLocalPacketHandler(PacketType.ChatFromViewer, HandleChatFromViewer); -- cgit v1.1 From b3072cf343e15ec58a70295cc66996a44e30ff1d Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Wed, 31 Oct 2012 00:46:07 +0000 Subject: Mark ScriptException as [Serializable] for when it has to cross AppDomains --- OpenSim/Region/ScriptEngine/Shared/ScriptException.cs | 1 + 1 file changed, 1 insertion(+) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/ScriptEngine/Shared/ScriptException.cs b/OpenSim/Region/ScriptEngine/Shared/ScriptException.cs index ae67fc5..ebe6fbd 100644 --- a/OpenSim/Region/ScriptEngine/Shared/ScriptException.cs +++ b/OpenSim/Region/ScriptEngine/Shared/ScriptException.cs @@ -29,6 +29,7 @@ using System; namespace OpenSim.Region.ScriptEngine.Shared { + [Serializable] public class ScriptException : Exception { public ScriptException() : base() {} -- cgit v1.1 From 566aaef1f4c7eade864d9e3d7b7b6ded8e0156a1 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Wed, 31 Oct 2012 00:56:41 +0000 Subject: Also add the additional ScriptException constructor necessary to get [Serializable] to work. --- OpenSim/Region/ScriptEngine/Shared/ScriptException.cs | 3 +++ 1 file changed, 3 insertions(+) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/ScriptEngine/Shared/ScriptException.cs b/OpenSim/Region/ScriptEngine/Shared/ScriptException.cs index ebe6fbd..f55ba7e 100644 --- a/OpenSim/Region/ScriptEngine/Shared/ScriptException.cs +++ b/OpenSim/Region/ScriptEngine/Shared/ScriptException.cs @@ -26,6 +26,7 @@ */ using System; +using System.Runtime.Serialization; namespace OpenSim.Region.ScriptEngine.Shared { @@ -37,5 +38,7 @@ namespace OpenSim.Region.ScriptEngine.Shared public ScriptException(string message) : base(message) {} public ScriptException(string message, Exception innerException) : base(message, innerException) {} + + public ScriptException(SerializationInfo info, StreamingContext context) :base(info, context) {} } } \ No newline at end of file -- cgit v1.1 From ffe4d738fbcd27e3c037693ab6812df1d9fbb977 Mon Sep 17 00:00:00 2001 From: Dan Lake Date: Wed, 31 Oct 2012 17:13:18 -0700 Subject: Add TargetVelocity to PhysicsActor interface to support distributed physics. No change to existing functions. --- OpenSim/Region/Framework/Scenes/ScenePresence.cs | 2 +- OpenSim/Region/Physics/Manager/PhysicsActor.cs | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index 71e322d..5f2a6b1 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -523,7 +523,7 @@ namespace OpenSim.Region.Framework.Scenes { if (PhysicsActor != null) { - m_velocity = PhysicsActor.Velocity; + m_velocity = PhysicsActor.TargetVelocity; // m_log.DebugFormat( // "[SCENE PRESENCE]: Set velocity {0} for {1} in {2} via getting Velocity!", diff --git a/OpenSim/Region/Physics/Manager/PhysicsActor.cs b/OpenSim/Region/Physics/Manager/PhysicsActor.cs index 0587054..34413e5 100644 --- a/OpenSim/Region/Physics/Manager/PhysicsActor.cs +++ b/OpenSim/Region/Physics/Manager/PhysicsActor.cs @@ -257,6 +257,12 @@ namespace OpenSim.Region.Physics.Manager /// Getting this returns the velocity calculated by physics scene updates, using factors such as target velocity, /// time to accelerate and collisions. /// + public virtual Vector3 TargetVelocity + { + get { return Velocity; } + set { Velocity = value; } + } + public abstract Vector3 Velocity { get; set; } public abstract Vector3 Torque { get; set; } -- cgit v1.1 From 8dfe59d7b88309fdc2436abe7dda9a2fc699a427 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Thu, 1 Nov 2012 03:42:15 +0000 Subject: Comment out checks not to overwrite existing IAR/OAR files for now on "save iar/oar" since this causes problems for some backup systems. Needs more thought, maybe an explicit --force/--overwrite switch Comments on http://opensimulator.org/mantis/view.php?id=6389 --- .../Avatar/Inventory/Archiver/InventoryArchiverModule.cs | 4 ++-- OpenSim/Region/CoreModules/World/Archiver/ArchiverModule.cs | 6 ++++-- 2 files changed, 6 insertions(+), 4 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs index afe1200..fdba682 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs @@ -210,8 +210,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver Guid id, string firstName, string lastName, string invPath, string pass, string savePath, Dictionary options) { - if (!ConsoleUtil.CheckFileDoesNotExist(MainConsole.Instance, savePath)) - return false; +// if (!ConsoleUtil.CheckFileDoesNotExist(MainConsole.Instance, savePath)) +// return false; if (m_scenes.Count > 0) { diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiverModule.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiverModule.cs index 970487a..abf3713 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/ArchiverModule.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiverModule.cs @@ -158,8 +158,10 @@ namespace OpenSim.Region.CoreModules.World.Archiver else path = DEFAULT_OAR_BACKUP_FILENAME; - if (!ConsoleUtil.CheckFileDoesNotExist(MainConsole.Instance, path)) - return; + // Not doing this right now as this causes some problems with auto-backup systems. Maybe a force flag is + // needed +// if (!ConsoleUtil.CheckFileDoesNotExist(MainConsole.Instance, path)) +// return; ArchiveRegion(path, options); } -- cgit v1.1 From 2e106cd5de63caf3d4eaeda8ac9a6ab0007a6b14 Mon Sep 17 00:00:00 2001 From: Dan Lake Date: Fri, 2 Nov 2012 03:07:53 -0700 Subject: Change to earlier commit for TargetVelocity to support distributed physics. --- OpenSim/Region/Framework/Scenes/ScenePresence.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index 5f2a6b1..96bca3e 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -1,4 +1,4 @@ -/* +/* * Copyright (c) Contributors, http://opensimulator.org/ * See CONTRIBUTORS.TXT for a full list of copyright holders. * @@ -523,7 +523,7 @@ namespace OpenSim.Region.Framework.Scenes { if (PhysicsActor != null) { - m_velocity = PhysicsActor.TargetVelocity; + m_velocity = PhysicsActor.Velocity; // m_log.DebugFormat( // "[SCENE PRESENCE]: Set velocity {0} for {1} in {2} via getting Velocity!", @@ -538,7 +538,7 @@ namespace OpenSim.Region.Framework.Scenes { try { - PhysicsActor.Velocity = value; + PhysicsActor.TargetVelocity = value; } catch (Exception e) { -- cgit v1.1 From 7412795a0bedae060e9f2bce2fa12e0497916f6e Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Fri, 2 Nov 2012 08:05:56 -0700 Subject: HG: flip all configs to HG2.0. PLEASE CHECK YOUR EXISTING HG CONFIGS AGAINST THESE. --- .../CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs | 4 ++-- .../CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs | 4 +++- 2 files changed, 5 insertions(+), 3 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs index 679be18..e37d429 100644 --- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs +++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs @@ -259,8 +259,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer if (flags == -1 /* no region in DB */ || (flags & (int)OpenSim.Framework.RegionFlags.Hyperlink) != 0) { // this user is going to another grid - // check if HyperGrid teleport is allowed, based on user level - if (sp.UserLevel < m_levelHGTeleport) + // for local users, check if HyperGrid teleport is allowed, based on user level + if (Scene.UserManagementModule.IsLocalGridUser(sp.UUID) && sp.UserLevel < m_levelHGTeleport) { m_log.WarnFormat("[HG ENTITY TRANSFER MODULE]: Unable to HG teleport agent due to insufficient UserLevel."); reason = "Hypergrid teleport not allowed"; diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs index 80257bd..6bb758e 100644 --- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs +++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs @@ -92,7 +92,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess m_HomeURI = thisModuleConfig.GetString("HomeURI", m_HomeURI); m_OutboundPermission = thisModuleConfig.GetBoolean("OutboundPermission", true); m_ThisGatekeeper = thisModuleConfig.GetString("Gatekeeper", string.Empty); - m_RestrictInventoryAccessAbroad = thisModuleConfig.GetBoolean("RestrictInventoryAccessAbroad", false); + m_RestrictInventoryAccessAbroad = thisModuleConfig.GetBoolean("RestrictInventoryAccessAbroad", true); } else m_log.Warn("[HG INVENTORY ACCESS MODULE]: HGInventoryAccessModule configs not found. ProfileServerURI not set!"); @@ -351,6 +351,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess private void ProcessInventoryForArriving(IClientAPI client) { + // No-op for now, but we may need to do something for freign users inventory } // @@ -397,6 +398,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess private void ProcessInventoryForLeaving(IClientAPI client) { + // No-op for now } #endregion -- cgit v1.1 From 804b332d45c3989958f5ec08e1509ba373fb84b1 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Thu, 25 Oct 2012 08:04:20 -0700 Subject: BulletSim: Add banking and other new code to vechile dynamics. Add third party license and contributor in for for Aurora-Sim project for physics code. --- .../Physics/BulletSPlugin/BS6DofConstraint.cs | 2 +- .../Region/Physics/BulletSPlugin/BSCharacter.cs | 2 +- .../BulletSPlugin/BSConstraintCollection.cs | 2 +- OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs | 489 +++++++++++++-------- .../Physics/BulletSPlugin/BSHingeConstraint.cs | 2 +- OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs | 2 + .../Physics/BulletSPlugin/BSLinksetConstraints.cs | 2 +- OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | 4 +- OpenSim/Region/Physics/BulletSPlugin/BSScene.cs | 2 +- .../Physics/BulletSPlugin/BSShapeCollection.cs | 2 +- .../Physics/BulletSPlugin/BSTerrainManager.cs | 2 +- 11 files changed, 323 insertions(+), 188 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BS6DofConstraint.cs b/OpenSim/Region/Physics/BulletSPlugin/BS6DofConstraint.cs index 3306a97..310df3d 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BS6DofConstraint.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BS6DofConstraint.cs @@ -32,7 +32,7 @@ using OpenMetaverse; namespace OpenSim.Region.Physics.BulletSPlugin { -public class BS6DofConstraint : BSConstraint +public sealed class BS6DofConstraint : BSConstraint { private static string LogHeader = "[BULLETSIM 6DOF CONSTRAINT]"; diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs index a041ba8..9fea9b8 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs @@ -34,7 +34,7 @@ using OpenSim.Region.Physics.Manager; namespace OpenSim.Region.Physics.BulletSPlugin { -public class BSCharacter : BSPhysObject +public sealed class BSCharacter : BSPhysObject { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private static readonly string LogHeader = "[BULLETS CHAR]"; diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSConstraintCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSConstraintCollection.cs index 22ea367..b9add06 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSConstraintCollection.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSConstraintCollection.cs @@ -33,7 +33,7 @@ using OpenMetaverse; namespace OpenSim.Region.Physics.BulletSPlugin { -public class BSConstraintCollection : IDisposable +public sealed class BSConstraintCollection : IDisposable { // private static readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); // private static readonly string LogHeader = "[CONSTRAINT COLLECTION]"; diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs index 117c878..9b59bef 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs @@ -52,7 +52,7 @@ using OpenSim.Region.Physics.Manager; namespace OpenSim.Region.Physics.BulletSPlugin { - public class BSDynamics + public sealed class BSDynamics { private BSScene PhysicsScene { get; set; } // the prim this dynamic controller belongs to @@ -72,8 +72,11 @@ namespace OpenSim.Region.Physics.BulletSPlugin // LIMIT_ROLL_ONLY private Vector3 m_BlockingEndPoint = Vector3.Zero; private Quaternion m_RollreferenceFrame = Quaternion.Identity; + private Quaternion m_referenceFrame = Quaternion.Identity; + // Linear properties private Vector3 m_linearMotorDirection = Vector3.Zero; // velocity requested by LSL, decayed by time + private Vector3 m_linearMotorOffset = Vector3.Zero; // the point of force can be offset from the center private Vector3 m_linearMotorDirectionLASTSET = Vector3.Zero; // velocity requested by LSL private Vector3 m_newVelocity = Vector3.Zero; // velocity computed to be applied to body private Vector3 m_linearFrictionTimescale = Vector3.Zero; @@ -95,19 +98,19 @@ namespace OpenSim.Region.Physics.BulletSPlugin private Vector3 m_lastVertAttractor = Vector3.Zero; // what VA was last applied to body //Deflection properties - // private float m_angularDeflectionEfficiency = 0; - // private float m_angularDeflectionTimescale = 0; - // private float m_linearDeflectionEfficiency = 0; - // private float m_linearDeflectionTimescale = 0; + private float m_angularDeflectionEfficiency = 0; + private float m_angularDeflectionTimescale = 0; + private float m_linearDeflectionEfficiency = 0; + private float m_linearDeflectionTimescale = 0; //Banking properties - // private float m_bankingEfficiency = 0; - // private float m_bankingMix = 0; - // private float m_bankingTimescale = 0; + private float m_bankingEfficiency = 0; + private float m_bankingMix = 0; + private float m_bankingTimescale = 0; //Hover and Buoyancy properties private float m_VhoverHeight = 0f; -// private float m_VhoverEfficiency = 0f; + private float m_VhoverEfficiency = 0f; private float m_VhoverTimescale = 0f; private float m_VhoverTargetHeight = -1.0f; // if <0 then no hover, else its the current target height private float m_VehicleBuoyancy = 0f; //KF: m_VehicleBuoyancy is set by VEHICLE_BUOYANCY for a vehicle. @@ -138,10 +141,10 @@ namespace OpenSim.Region.Physics.BulletSPlugin switch (pParam) { case Vehicle.ANGULAR_DEFLECTION_EFFICIENCY: - // m_angularDeflectionEfficiency = Math.Max(pValue, 0.01f); + m_angularDeflectionEfficiency = Math.Max(pValue, 0.01f); break; case Vehicle.ANGULAR_DEFLECTION_TIMESCALE: - // m_angularDeflectionTimescale = Math.Max(pValue, 0.01f); + m_angularDeflectionTimescale = Math.Max(pValue, 0.01f); break; case Vehicle.ANGULAR_MOTOR_DECAY_TIMESCALE: m_angularMotorDecayTimescale = Math.Max(pValue, 0.01f); @@ -150,20 +153,20 @@ namespace OpenSim.Region.Physics.BulletSPlugin m_angularMotorTimescale = Math.Max(pValue, 0.01f); break; case Vehicle.BANKING_EFFICIENCY: - // m_bankingEfficiency = Math.Max(pValue, 0.01f); + m_bankingEfficiency = Math.Max(-1f, Math.Min(pValue, 1f)); break; case Vehicle.BANKING_MIX: - // m_bankingMix = Math.Max(pValue, 0.01f); + m_bankingMix = Math.Max(pValue, 0.01f); break; case Vehicle.BANKING_TIMESCALE: - // m_bankingTimescale = Math.Max(pValue, 0.01f); + m_bankingTimescale = Math.Max(pValue, 0.01f); break; case Vehicle.BUOYANCY: m_VehicleBuoyancy = Math.Max(-1f, Math.Min(pValue, 1f)); break; -// case Vehicle.HOVER_EFFICIENCY: -// m_VhoverEfficiency = Math.Max(0f, Math.Min(pValue, 1f)); -// break; + case Vehicle.HOVER_EFFICIENCY: + m_VhoverEfficiency = Math.Max(0f, Math.Min(pValue, 1f)); + break; case Vehicle.HOVER_HEIGHT: m_VhoverHeight = pValue; break; @@ -171,10 +174,10 @@ namespace OpenSim.Region.Physics.BulletSPlugin m_VhoverTimescale = Math.Max(pValue, 0.01f); break; case Vehicle.LINEAR_DEFLECTION_EFFICIENCY: - // m_linearDeflectionEfficiency = Math.Max(pValue, 0.01f); + m_linearDeflectionEfficiency = Math.Max(pValue, 0.01f); break; case Vehicle.LINEAR_DEFLECTION_TIMESCALE: - // m_linearDeflectionTimescale = Math.Max(pValue, 0.01f); + m_linearDeflectionTimescale = Math.Max(pValue, 0.01f); break; case Vehicle.LINEAR_MOTOR_DECAY_TIMESCALE: m_linearMotorDecayTimescale = Math.Max(pValue, 0.01f); @@ -196,7 +199,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin break; case Vehicle.ANGULAR_MOTOR_DIRECTION: m_angularMotorDirection = new Vector3(pValue, pValue, pValue); - m_angularMotorApply = 10; + m_angularMotorApply = 100; break; case Vehicle.LINEAR_FRICTION_TIMESCALE: m_linearFrictionTimescale = new Vector3(pValue, pValue, pValue); @@ -206,7 +209,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin m_linearMotorDirectionLASTSET = new Vector3(pValue, pValue, pValue); break; case Vehicle.LINEAR_MOTOR_OFFSET: - // m_linearMotorOffset = new Vector3(pValue, pValue, pValue); + m_linearMotorOffset = new Vector3(pValue, pValue, pValue); break; } @@ -221,15 +224,12 @@ namespace OpenSim.Region.Physics.BulletSPlugin m_angularFrictionTimescale = new Vector3(pValue.X, pValue.Y, pValue.Z); break; case Vehicle.ANGULAR_MOTOR_DIRECTION: - m_angularMotorDirection = new Vector3(pValue.X, pValue.Y, pValue.Z); // Limit requested angular speed to 2 rps= 4 pi rads/sec - if (m_angularMotorDirection.X > 12.56f) m_angularMotorDirection.X = 12.56f; - if (m_angularMotorDirection.X < - 12.56f) m_angularMotorDirection.X = - 12.56f; - if (m_angularMotorDirection.Y > 12.56f) m_angularMotorDirection.Y = 12.56f; - if (m_angularMotorDirection.Y < - 12.56f) m_angularMotorDirection.Y = - 12.56f; - if (m_angularMotorDirection.Z > 12.56f) m_angularMotorDirection.Z = 12.56f; - if (m_angularMotorDirection.Z < - 12.56f) m_angularMotorDirection.Z = - 12.56f; - m_angularMotorApply = 10; + pValue.X = Math.Max(-12.56f, Math.Min(pValue.X, 12.56f)); + pValue.Y = Math.Max(-12.56f, Math.Min(pValue.Y, 12.56f)); + pValue.Z = Math.Max(-12.56f, Math.Min(pValue.Z, 12.56f)); + m_angularMotorDirection = new Vector3(pValue.X, pValue.Y, pValue.Z); + m_angularMotorApply = 100; break; case Vehicle.LINEAR_FRICTION_TIMESCALE: m_linearFrictionTimescale = new Vector3(pValue.X, pValue.Y, pValue.Z); @@ -239,7 +239,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin m_linearMotorDirectionLASTSET = new Vector3(pValue.X, pValue.Y, pValue.Z); break; case Vehicle.LINEAR_MOTOR_OFFSET: - // m_linearMotorOffset = new Vector3(pValue.X, pValue.Y, pValue.Z); + m_linearMotorOffset = new Vector3(pValue.X, pValue.Y, pValue.Z); break; case Vehicle.BLOCK_EXIT: m_BlockingEndPoint = new Vector3(pValue.X, pValue.Y, pValue.Z); @@ -253,7 +253,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin switch (pParam) { case Vehicle.REFERENCE_FRAME: - // m_referenceFrame = pValue; + m_referenceFrame = pValue; break; case Vehicle.ROLL_FRAME: m_RollreferenceFrame = pValue; @@ -265,21 +265,16 @@ namespace OpenSim.Region.Physics.BulletSPlugin { VDetailLog("{0},ProcessVehicleFlags,param={1},remove={2}", Prim.LocalID, pParam, remove); VehicleFlag parm = (VehicleFlag)pParam; - if (remove) + if (pParam == -1) + m_flags = (VehicleFlag)0; + else { - if (pParam == -1) - { - m_flags = (VehicleFlag)0; - } - else - { + if (remove) m_flags &= ~parm; - } - } - else { - m_flags |= parm; + else + m_flags |= parm; } - }//end ProcessVehicleFlags + } internal void ProcessTypeChange(Vehicle pType) { @@ -288,99 +283,142 @@ namespace OpenSim.Region.Physics.BulletSPlugin Type = pType; switch (pType) { - case Vehicle.TYPE_NONE: - m_linearFrictionTimescale = new Vector3(0, 0, 0); - m_angularFrictionTimescale = new Vector3(0, 0, 0); + case Vehicle.TYPE_NONE: m_linearMotorDirection = Vector3.Zero; m_linearMotorTimescale = 0; m_linearMotorDecayTimescale = 0; + m_linearFrictionTimescale = new Vector3(0, 0, 0); + m_angularMotorDirection = Vector3.Zero; - m_angularMotorTimescale = 0; m_angularMotorDecayTimescale = 0; + m_angularMotorTimescale = 0; + m_angularFrictionTimescale = new Vector3(0, 0, 0); + m_VhoverHeight = 0; + m_VhoverEfficiency = 0; m_VhoverTimescale = 0; m_VehicleBuoyancy = 0; + + m_linearDeflectionEfficiency = 1; + m_linearDeflectionTimescale = 1; + + m_angularDeflectionEfficiency = 0; + m_angularDeflectionTimescale = 1000; + + m_verticalAttractionEfficiency = 0; + m_verticalAttractionTimescale = 0; + + m_bankingEfficiency = 0; + m_bankingTimescale = 1000; + m_bankingMix = 1; + + m_referenceFrame = Quaternion.Identity; m_flags = (VehicleFlag)0; break; case Vehicle.TYPE_SLED: - m_linearFrictionTimescale = new Vector3(30, 1, 1000); - m_angularFrictionTimescale = new Vector3(1000, 1000, 1000); m_linearMotorDirection = Vector3.Zero; m_linearMotorTimescale = 1000; m_linearMotorDecayTimescale = 120; + m_linearFrictionTimescale = new Vector3(30, 1, 1000); + m_angularMotorDirection = Vector3.Zero; m_angularMotorTimescale = 1000; m_angularMotorDecayTimescale = 120; + m_angularFrictionTimescale = new Vector3(1000, 1000, 1000); + m_VhoverHeight = 0; -// m_VhoverEfficiency = 1; + m_VhoverEfficiency = 10; // TODO: this looks wrong!! m_VhoverTimescale = 10; m_VehicleBuoyancy = 0; - // m_linearDeflectionEfficiency = 1; - // m_linearDeflectionTimescale = 1; - // m_angularDeflectionEfficiency = 1; - // m_angularDeflectionTimescale = 1000; - // m_bankingEfficiency = 0; - // m_bankingMix = 1; - // m_bankingTimescale = 10; - // m_referenceFrame = Quaternion.Identity; + + m_linearDeflectionEfficiency = 1; + m_linearDeflectionTimescale = 1; + + m_angularDeflectionEfficiency = 1; + m_angularDeflectionTimescale = 1000; + + m_verticalAttractionEfficiency = 0; + m_verticalAttractionTimescale = 0; + + m_bankingEfficiency = 0; + m_bankingTimescale = 10; + m_bankingMix = 1; + + m_referenceFrame = Quaternion.Identity; m_flags |= (VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.LIMIT_ROLL_ONLY | VehicleFlag.LIMIT_MOTOR_UP); m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT | VehicleFlag.HOVER_UP_ONLY); break; case Vehicle.TYPE_CAR: - m_linearFrictionTimescale = new Vector3(100, 2, 1000); - m_angularFrictionTimescale = new Vector3(1000, 1000, 1000); m_linearMotorDirection = Vector3.Zero; m_linearMotorTimescale = 1; m_linearMotorDecayTimescale = 60; + m_linearFrictionTimescale = new Vector3(100, 2, 1000); + m_angularMotorDirection = Vector3.Zero; m_angularMotorTimescale = 1; m_angularMotorDecayTimescale = 0.8f; + m_angularFrictionTimescale = new Vector3(1000, 1000, 1000); + m_VhoverHeight = 0; -// m_VhoverEfficiency = 0; + m_VhoverEfficiency = 0; m_VhoverTimescale = 1000; m_VehicleBuoyancy = 0; - // // m_linearDeflectionEfficiency = 1; - // // m_linearDeflectionTimescale = 2; - // // m_angularDeflectionEfficiency = 0; - // m_angularDeflectionTimescale = 10; + + m_linearDeflectionEfficiency = 1; + m_linearDeflectionTimescale = 2; + + m_angularDeflectionEfficiency = 0; + m_angularDeflectionTimescale = 10; + m_verticalAttractionEfficiency = 1f; m_verticalAttractionTimescale = 10f; - // m_bankingEfficiency = -0.2f; - // m_bankingMix = 1; - // m_bankingTimescale = 1; - // m_referenceFrame = Quaternion.Identity; + + m_bankingEfficiency = -0.2f; + m_bankingMix = 1; + m_bankingTimescale = 1; + + m_referenceFrame = Quaternion.Identity; + m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY + | VehicleFlag.HOVER_TERRAIN_ONLY + | VehicleFlag.HOVER_GLOBAL_HEIGHT); m_flags |= (VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.LIMIT_ROLL_ONLY - | VehicleFlag.LIMIT_MOTOR_UP); - m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT); - m_flags |= (VehicleFlag.HOVER_UP_ONLY); + | VehicleFlag.LIMIT_MOTOR_UP + | VehicleFlag.HOVER_UP_ONLY); break; case Vehicle.TYPE_BOAT: - m_linearFrictionTimescale = new Vector3(10, 3, 2); - m_angularFrictionTimescale = new Vector3(10,10,10); m_linearMotorDirection = Vector3.Zero; m_linearMotorTimescale = 5; m_linearMotorDecayTimescale = 60; + m_linearFrictionTimescale = new Vector3(10, 3, 2); + m_angularMotorDirection = Vector3.Zero; m_angularMotorTimescale = 4; m_angularMotorDecayTimescale = 4; + m_angularFrictionTimescale = new Vector3(10,10,10); + m_VhoverHeight = 0; -// m_VhoverEfficiency = 0.5f; + m_VhoverEfficiency = 0.5f; m_VhoverTimescale = 2; m_VehicleBuoyancy = 1; - // m_linearDeflectionEfficiency = 0.5f; - // m_linearDeflectionTimescale = 3; - // m_angularDeflectionEfficiency = 0.5f; - // m_angularDeflectionTimescale = 5; + + m_linearDeflectionEfficiency = 0.5f; + m_linearDeflectionTimescale = 3; + + m_angularDeflectionEfficiency = 0.5f; + m_angularDeflectionTimescale = 5; + m_verticalAttractionEfficiency = 0.5f; m_verticalAttractionTimescale = 5f; - // m_bankingEfficiency = -0.3f; - // m_bankingMix = 0.8f; - // m_bankingTimescale = 1; - // m_referenceFrame = Quaternion.Identity; + + m_bankingEfficiency = -0.3f; + m_bankingMix = 0.8f; + m_bankingTimescale = 1; + + m_referenceFrame = Quaternion.Identity; m_flags &= ~(VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT | VehicleFlag.LIMIT_ROLL_ONLY @@ -390,28 +428,35 @@ namespace OpenSim.Region.Physics.BulletSPlugin | VehicleFlag.HOVER_WATER_ONLY); break; case Vehicle.TYPE_AIRPLANE: - m_linearFrictionTimescale = new Vector3(200, 10, 5); - m_angularFrictionTimescale = new Vector3(20, 20, 20); m_linearMotorDirection = Vector3.Zero; m_linearMotorTimescale = 2; m_linearMotorDecayTimescale = 60; + m_linearFrictionTimescale = new Vector3(200, 10, 5); + m_angularMotorDirection = Vector3.Zero; m_angularMotorTimescale = 4; m_angularMotorDecayTimescale = 4; + m_angularFrictionTimescale = new Vector3(20, 20, 20); + m_VhoverHeight = 0; -// m_VhoverEfficiency = 0.5f; + m_VhoverEfficiency = 0.5f; m_VhoverTimescale = 1000; m_VehicleBuoyancy = 0; - // m_linearDeflectionEfficiency = 0.5f; - // m_linearDeflectionTimescale = 3; - // m_angularDeflectionEfficiency = 1; - // m_angularDeflectionTimescale = 2; + + m_linearDeflectionEfficiency = 0.5f; + m_linearDeflectionTimescale = 3; + + m_angularDeflectionEfficiency = 1; + m_angularDeflectionTimescale = 2; + m_verticalAttractionEfficiency = 0.9f; m_verticalAttractionTimescale = 2f; - // m_bankingEfficiency = 1; - // m_bankingMix = 0.7f; - // m_bankingTimescale = 2; - // m_referenceFrame = Quaternion.Identity; + + m_bankingEfficiency = 1; + m_bankingMix = 0.7f; + m_bankingTimescale = 2; + + m_referenceFrame = Quaternion.Identity; m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT @@ -421,28 +466,36 @@ namespace OpenSim.Region.Physics.BulletSPlugin m_flags |= (VehicleFlag.LIMIT_ROLL_ONLY); break; case Vehicle.TYPE_BALLOON: - m_linearFrictionTimescale = new Vector3(5, 5, 5); - m_angularFrictionTimescale = new Vector3(10, 10, 10); m_linearMotorDirection = Vector3.Zero; m_linearMotorTimescale = 5; + m_linearFrictionTimescale = new Vector3(5, 5, 5); m_linearMotorDecayTimescale = 60; + m_angularMotorDirection = Vector3.Zero; m_angularMotorTimescale = 6; + m_angularFrictionTimescale = new Vector3(10, 10, 10); m_angularMotorDecayTimescale = 10; + m_VhoverHeight = 5; -// m_VhoverEfficiency = 0.8f; + m_VhoverEfficiency = 0.8f; m_VhoverTimescale = 10; m_VehicleBuoyancy = 1; - // m_linearDeflectionEfficiency = 0; - // m_linearDeflectionTimescale = 5; - // m_angularDeflectionEfficiency = 0; - // m_angularDeflectionTimescale = 5; + + m_linearDeflectionEfficiency = 0; + m_linearDeflectionTimescale = 5; + + m_angularDeflectionEfficiency = 0; + m_angularDeflectionTimescale = 5; + m_verticalAttractionEfficiency = 1f; m_verticalAttractionTimescale = 100f; - // m_bankingEfficiency = 0; - // m_bankingMix = 0.7f; - // m_bankingTimescale = 5; - // m_referenceFrame = Quaternion.Identity; + + m_bankingEfficiency = 0; + m_bankingMix = 0.7f; + m_bankingTimescale = 5; + m_referenceFrame = Quaternion.Identity; + + m_referenceFrame = Quaternion.Identity; m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.HOVER_UP_ONLY @@ -452,21 +505,27 @@ namespace OpenSim.Region.Physics.BulletSPlugin | VehicleFlag.HOVER_GLOBAL_HEIGHT); break; } - }//end SetDefaultsForType + } // Some of the properties of this prim may have changed. // Do any updating needed for a vehicle public void Refresh() { - if (!IsActive) - return; - - // Set the prim's inertia to zero. The vehicle code handles that and this - // removes the motion and torque actions introduced by Bullet. - Vector3 inertia = Vector3.Zero; - // comment out for DEBUG test - // BulletSimAPI.SetMassProps2(Prim.BSBody.ptr, Prim.MassRaw, inertia); - // BulletSimAPI.UpdateInertiaTensor2(Prim.BSBody.ptr); + /* + * Doesnt work unless BSDynamics senses and corrects for all collisions + if (IsActive) + BulletSimAPI.AddToCollisionFlags2(Prim.BSBody.ptr, CollisionFlags.CF_KINEMATIC_OBJECT); + else + BulletSimAPI.RemoveFromCollisionFlags2(Prim.BSBody.ptr, CollisionFlags.CF_KINEMATIC_OBJECT); + */ + /* + * Doesn't work because with zero inertia, Bullet will not apply any forces to the object. + if (IsActive) + { + BulletSimAPI.SetMassProps2(Prim.BSBody.ptr, Prim.MassRaw, Vector3.Zero); + BulletSimAPI.UpdateInertiaTensor2(Prim.BSBody.ptr); + } + */ } // One step of the vehicle properties for the next 'pTimestep' seconds. @@ -478,6 +537,22 @@ namespace OpenSim.Region.Physics.BulletSPlugin MoveAngular(pTimestep); LimitRotation(pTimestep); + /* Experimental + // Wonder if Bullet could handle collision penetration while this applies the forces. + // Apply the computed forces on the vehicle + Prim.ForcePosition += Prim.ForceVelocity * Prim.MassRaw * pTimestep; + + if (Prim.ForceRotationalVelocity != Vector3.Zero) + { + Quaternion newOrientation = Prim.ForceOrientation; + newOrientation.Normalize(); + Quaternion appliedRotation = new Quaternion((Prim.ForceRotationalVelocity * pTimestep), 0f); + newOrientation += (appliedRotation * newOrientation) * 0.5f; + newOrientation.Normalize(); + Prim.ForceOrientation = newOrientation; + } + */ + // remember the position so next step we can limit absolute movement effects m_lastPositionVector = Prim.ForcePosition; @@ -489,59 +564,46 @@ namespace OpenSim.Region.Physics.BulletSPlugin // Also does hover and float. private void MoveLinear(float pTimestep) { - // m_linearMotorDirection is the direction we are moving relative to the vehicle coordinates - // m_lastLinearVelocityVector is the speed we are moving in that direction + // m_linearMotorDirection is the target direction we are moving relative to the vehicle coordinates + // m_lastLinearVelocityVector is the current speed we are moving in that direction if (m_linearMotorDirection.LengthSquared() > 0.001f) { Vector3 origDir = m_linearMotorDirection; Vector3 origVel = m_lastLinearVelocityVector; // add drive to body - // Vector3 addAmount = m_linearMotorDirection/(m_linearMotorTimescale / pTimestep); Vector3 addAmount = (m_linearMotorDirection - m_lastLinearVelocityVector)/(m_linearMotorTimescale / pTimestep); // lastLinearVelocityVector is the current body velocity vector - // RA: Not sure what the *10 is for. A correction for pTimestep? - // m_lastLinearVelocityVector += (addAmount*10); m_lastLinearVelocityVector += addAmount; - // Limit the velocity vector to less than the last set linear motor direction - if (Math.Abs(m_lastLinearVelocityVector.X) > Math.Abs(m_linearMotorDirectionLASTSET.X)) - m_lastLinearVelocityVector.X = m_linearMotorDirectionLASTSET.X; - if (Math.Abs(m_lastLinearVelocityVector.Y) > Math.Abs(m_linearMotorDirectionLASTSET.Y)) - m_lastLinearVelocityVector.Y = m_linearMotorDirectionLASTSET.Y; - if (Math.Abs(m_lastLinearVelocityVector.Z) > Math.Abs(m_linearMotorDirectionLASTSET.Z)) - m_lastLinearVelocityVector.Z = m_linearMotorDirectionLASTSET.Z; - - /* - // decay applied velocity - Vector3 decayfraction = Vector3.One/(m_linearMotorDecayTimescale / pTimestep); - // (RA: do not know where the 0.5f comes from) - m_linearMotorDirection -= m_linearMotorDirection * decayfraction * 0.5f; - */ float keepfraction = 1.0f - (1.0f / (m_linearMotorDecayTimescale / pTimestep)); m_linearMotorDirection *= keepfraction; VDetailLog("{0},MoveLinear,nonZero,origdir={1},origvel={2},add={3},notDecay={4},dir={5},vel={6}", Prim.LocalID, origDir, origVel, addAmount, keepfraction, m_linearMotorDirection, m_lastLinearVelocityVector); + + // convert requested object velocity to object relative vector + m_newVelocity = m_lastLinearVelocityVector * Prim.ForceOrientation; } else { // if what remains of direction is very small, zero it. m_linearMotorDirection = Vector3.Zero; m_lastLinearVelocityVector = Vector3.Zero; + m_newVelocity = Vector3.Zero; + VDetailLog("{0},MoveLinear,zeroed", Prim.LocalID); } - // convert requested object velocity to object relative vector - Quaternion rotq = Prim.ForceOrientation; - m_newVelocity = m_lastLinearVelocityVector * rotq; + // m_newVelocity is velocity computed from linear motor // Add the various forces into m_dir which will be our new direction vector (velocity) // add Gravity and Buoyancy // There is some gravity, make a gravity force vector that is applied after object velocity. // m_VehicleBuoyancy: -1=2g; 0=1g; 1=0g; - Vector3 grav = Prim.PhysicsScene.DefaultGravity * (Prim.Linkset.LinksetMass * (1f - m_VehicleBuoyancy)); + // Vector3 grav = Prim.PhysicsScene.DefaultGravity * (Prim.Linkset.LinksetMass * (1f - m_VehicleBuoyancy)); + Vector3 grav = Prim.PhysicsScene.DefaultGravity * (1f - m_VehicleBuoyancy); /* * RA: Not sure why one would do this @@ -567,6 +629,8 @@ namespace OpenSim.Region.Physics.BulletSPlugin } // Check if hovering + // m_VhoverEfficiency: 0=bouncy, 1=totally damped + // m_VhoverTimescale: time to achieve height if ((m_flags & (VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT)) != 0) { // We should hover, get the target height @@ -597,13 +661,19 @@ namespace OpenSim.Region.Physics.BulletSPlugin } else { - float herr0 = pos.Z - m_VhoverTargetHeight; + float horizontalError = pos.Z - m_VhoverTargetHeight; + // RA: where does the 50 come from> + float horizontalCorrectionVelocity = ((horizontalError * 50.0f) / (m_VhoverTimescale / pTimestep)); // Replace Vertical speed with correction figure if significant - if (Math.Abs(herr0) > 0.01f) + if (Math.Abs(horizontalError) > 0.01f) { - m_newVelocity.Z = -((herr0 * pTimestep * 50.0f) / m_VhoverTimescale); + m_newVelocity.Z += horizontalCorrectionVelocity; //KF: m_VhoverEfficiency is not yet implemented } + else if (horizontalError < -0.01) + { + m_newVelocity.Z -= horizontalCorrectionVelocity; + } else { m_newVelocity.Z = 0f; @@ -678,16 +748,14 @@ namespace OpenSim.Region.Physics.BulletSPlugin if ((m_flags & (VehicleFlag.NO_Z)) != 0) m_newVelocity.Z = 0; - // Apply velocity - Prim.ForceVelocity = m_newVelocity; - // apply gravity force - // Why is this set here? The physics engine already does gravity. - Prim.AddForce(grav, false, true); - // Apply friction Vector3 keepFraction = Vector3.One - (Vector3.One / (m_linearFrictionTimescale / pTimestep)); m_lastLinearVelocityVector *= keepFraction; + // Apply velocity + // Prim.ForceVelocity = m_newVelocity; + Prim.AddForce(m_newVelocity, false); + VDetailLog("{0},MoveLinear,done,lmDir={1},lmVel={2},newVel={3},grav={4},1Mdecay={5}", Prim.LocalID, m_linearMotorDirection, m_lastLinearVelocityVector, m_newVelocity, grav, keepFraction); @@ -717,11 +785,9 @@ namespace OpenSim.Region.Physics.BulletSPlugin Vector3 origDir = m_angularMotorDirection; // ramp up to new value - // new velocity += error / ( time to get there / step interval) - // requested speed - last motor speed - m_angularMotorVelocity.X += (m_angularMotorDirection.X - m_angularMotorVelocity.X) / (m_angularMotorTimescale / pTimestep); - m_angularMotorVelocity.Y += (m_angularMotorDirection.Y - m_angularMotorVelocity.Y) / (m_angularMotorTimescale / pTimestep); - m_angularMotorVelocity.Z += (m_angularMotorDirection.Z - m_angularMotorVelocity.Z) / (m_angularMotorTimescale / pTimestep); + // new velocity += error / ( time to get there / step interval) + // requested speed - last motor speed + m_angularMotorVelocity += (m_angularMotorDirection - m_angularMotorVelocity) / (m_angularMotorTimescale / pTimestep); VDetailLog("{0},MoveAngular,angularMotorApply,apply={1},angTScale={2},timeStep={3},origvel={4},origDir={5},vel={6}", Prim.LocalID, m_angularMotorApply, m_angularMotorTimescale, pTimestep, origVel, origDir, m_angularMotorVelocity); @@ -732,46 +798,50 @@ namespace OpenSim.Region.Physics.BulletSPlugin { // No motor recently applied, keep the body velocity // and decay the velocity - m_angularMotorVelocity -= m_angularMotorVelocity / (m_angularMotorDecayTimescale / pTimestep); - if (m_angularMotorVelocity.LengthSquared() < 0.00001) + if (m_angularMotorVelocity.LengthSquared() < 0.0001) m_angularMotorVelocity = Vector3.Zero; + else + m_angularMotorVelocity -= m_angularMotorVelocity / (m_angularMotorDecayTimescale / pTimestep); } // end motor section - // Vertical attractor section + #region Vertical attactor + Vector3 vertattr = Vector3.Zero; Vector3 deflection = Vector3.Zero; Vector3 banking = Vector3.Zero; if (m_verticalAttractionTimescale < 300 && m_lastAngularVelocity != Vector3.Zero) { - float VAservo = 0.2f / (m_verticalAttractionTimescale / pTimestep); + float VAservo = 0.2f; + if (Prim.Linkset.LinksetIsColliding) + VAservo = 0.05f / (m_verticalAttractionTimescale / pTimestep); + VAservo *= (m_verticalAttractionEfficiency * m_verticalAttractionEfficiency); // get present body rotation Quaternion rotq = Prim.ForceOrientation; // vector pointing up - Vector3 verterr = Vector3.Zero; - verterr.Z = 1.0f; + Vector3 verticalError = Vector3.UnitZ; // rotate it to Body Angle - verterr = verterr * rotq; - // verterr.X and .Y are the World error amounts. They are 0 when there is no error (Vehicle Body is 'vertical'), and .Z will be 1. + verticalError = verticalError * rotq; + // verticalError.X and .Y are the World error amounts. They are 0 when there is no error (Vehicle Body is 'vertical'), and .Z will be 1. // As the body leans to its side |.X| will increase to 1 and .Z fall to 0. As body inverts |.X| will fall and .Z will go // negative. Similar for tilt and |.Y|. .X and .Y must be modulated to prevent a stable inverted body. // Error is 0 (no error) to +/- 2 (max error) - if (verterr.Z < 0.0f) + if (verticalError.Z < 0.0f) { - verterr.X = 2.0f - verterr.X; - verterr.Y = 2.0f - verterr.Y; + verticalError.X = 2.0f - verticalError.X; + verticalError.Y = 2.0f - verticalError.Y; } // scale it by VAservo - verterr = verterr * VAservo; + verticalError = verticalError * VAservo; - // As the body rotates around the X axis, then verterr.Y increases; Rotated around Y then .X increases, so + // As the body rotates around the X axis, then verticalError.Y increases; Rotated around Y then .X increases, so // Change Body angular velocity X based on Y, and Y based on X. Z is not changed. - vertattr.X = verterr.Y; - vertattr.Y = - verterr.X; + vertattr.X = verticalError.Y; + vertattr.Y = - verticalError.X; vertattr.Z = 0f; // scaling appears better usingsquare-law @@ -779,10 +849,77 @@ namespace OpenSim.Region.Physics.BulletSPlugin vertattr.X += bounce * angularVelocity.X; vertattr.Y += bounce * angularVelocity.Y; - VDetailLog("{0},MoveAngular,verticalAttraction,verterr={1},bounce={2},vertattr={3}", - Prim.LocalID, verterr, bounce, vertattr); + VDetailLog("{0},MoveAngular,verticalAttraction,verticalError={1},bounce={2},vertattr={3}", + Prim.LocalID, verticalError, bounce, vertattr); + + } + #endregion // Vertical attactor + + #region Deflection + + //Forward is the prefered direction, but if the reference frame has changed, we need to take this into account as well + Vector3 PreferredAxisOfMotion = + new Vector3((10*(m_angularDeflectionEfficiency/m_angularDeflectionTimescale)), 0, 0); + PreferredAxisOfMotion *= Quaternion.Add(Prim.ForceOrientation, m_referenceFrame); + + //Multiply it so that it scales linearly + //deflection = PreferredAxisOfMotion; + + //deflection = ((PreferredAxisOfMotion * m_angularDeflectionEfficiency) / (m_angularDeflectionTimescale / pTimestep)); + + #endregion - } // else vertical attractor is off + #region Banking + + if (m_bankingEfficiency != 0) + { + Vector3 dir = Vector3.One * Prim.ForceOrientation; + float mult = (m_bankingMix*m_bankingMix)*-1*(m_bankingMix < 0 ? -1 : 1); + //Changes which way it banks in and out of turns + + //Use the square of the efficiency, as it looks much more how SL banking works + float effSquared = (m_bankingEfficiency*m_bankingEfficiency); + if (m_bankingEfficiency < 0) + effSquared *= -1; //Keep the negative! + + float mix = Math.Abs(m_bankingMix); + if (m_angularMotorVelocity.X == 0) + { + /*if (!parent.Orientation.ApproxEquals(this.m_referenceFrame, 0.25f)) + { + Vector3 axisAngle; + float angle; + parent.Orientation.GetAxisAngle(out axisAngle, out angle); + Vector3 rotatedVel = parent.Velocity * parent.Orientation; + if ((rotatedVel.X < 0 && axisAngle.Y > 0) || (rotatedVel.X > 0 && axisAngle.Y < 0)) + m_angularMotorVelocity.X += (effSquared * (mult * mix)) * (1f) * 10; + else + m_angularMotorVelocity.X += (effSquared * (mult * mix)) * (-1f) * 10; + }*/ + } + else + banking.Z += (effSquared*(mult*mix))*(m_angularMotorVelocity.X) * 4; + if (!Prim.Linkset.LinksetIsColliding && Math.Abs(m_angularMotorVelocity.X) > mix) + //If they are colliding, we probably shouldn't shove the prim around... probably + { + float angVelZ = m_angularMotorVelocity.X*-1; + /*if(angVelZ > mix) + angVelZ = mix; + else if(angVelZ < -mix) + angVelZ = -mix;*/ + //This controls how fast and how far the banking occurs + Vector3 bankingRot = new Vector3(angVelZ*(effSquared*mult), 0, 0); + if (bankingRot.X > 3) + bankingRot.X = 3; + else if (bankingRot.X < -3) + bankingRot.X = -3; + bankingRot *= Prim.ForceOrientation; + banking += bankingRot; + } + m_angularMotorVelocity.X *= m_bankingEfficiency == 1 ? 0.0f : 1 - m_bankingEfficiency; + } + + #endregion m_lastVertAttractor = vertattr; @@ -811,7 +948,8 @@ namespace OpenSim.Region.Physics.BulletSPlugin m_lastAngularVelocity -= m_lastAngularVelocity * decayamount; // Apply to the body - Prim.ForceRotationalVelocity = m_lastAngularVelocity; + // Prim.ForceRotationalVelocity = m_lastAngularVelocity; + Prim.AddAngularForce(m_lastAngularVelocity, false); VDetailLog("{0},MoveAngular,done,decay={1},lastAngular={2}", Prim.LocalID, decayamount, m_lastAngularVelocity); } //end MoveAngular @@ -820,38 +958,31 @@ namespace OpenSim.Region.Physics.BulletSPlugin { Quaternion rotq = Prim.ForceOrientation; Quaternion m_rot = rotq; - bool changed = false; if (m_RollreferenceFrame != Quaternion.Identity) { if (rotq.X >= m_RollreferenceFrame.X) { m_rot.X = rotq.X - (m_RollreferenceFrame.X / 2); - changed = true; } if (rotq.Y >= m_RollreferenceFrame.Y) { m_rot.Y = rotq.Y - (m_RollreferenceFrame.Y / 2); - changed = true; } if (rotq.X <= -m_RollreferenceFrame.X) { m_rot.X = rotq.X + (m_RollreferenceFrame.X / 2); - changed = true; } if (rotq.Y <= -m_RollreferenceFrame.Y) { m_rot.Y = rotq.Y + (m_RollreferenceFrame.Y / 2); - changed = true; } - changed = true; } if ((m_flags & VehicleFlag.LOCK_ROTATION) != 0) { m_rot.X = 0; m_rot.Y = 0; - changed = true; } - if (changed) + if (rotq != m_rot) { Prim.ForceOrientation = m_rot; VDetailLog("{0},LimitRotation,done,orig={1},new={2}", Prim.LocalID, rotq, m_rot); diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSHingeConstraint.cs b/OpenSim/Region/Physics/BulletSPlugin/BSHingeConstraint.cs index 7c8a215..76bd930 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSHingeConstraint.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSHingeConstraint.cs @@ -32,7 +32,7 @@ using OpenMetaverse; namespace OpenSim.Region.Physics.BulletSPlugin { -class BSHingeConstraint : BSConstraint +public sealed class BSHingeConstraint : BSConstraint { public override ConstraintType Type { get { return ConstraintType.HINGE_CONSTRAINT_TYPE; } } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs index c984824..24fe6b9 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs @@ -88,6 +88,8 @@ public abstract class BSLinkset } } + public virtual bool LinksetIsColliding { get { return false; } } + public OMV.Vector3 CenterOfMass { get { return ComputeLinksetCenterOfMass(); } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs index 8a750b5..003c294 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs @@ -32,7 +32,7 @@ using OMV = OpenMetaverse; namespace OpenSim.Region.Physics.BulletSPlugin { -public class BSLinksetConstraints : BSLinkset +public sealed class BSLinksetConstraints : BSLinkset { // private static string LogHeader = "[BULLETSIM LINKSET CONSTRAINTS]"; diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index 38ab3de..39d20dc 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs @@ -311,6 +311,7 @@ public sealed class BSPrim : BSPhysObject if ((CurrentCollisionFlags & CollisionFlags.BS_FLOATS_ON_WATER) != 0) { float waterHeight = PhysicsScene.GetWaterLevelAtXYZ(_position); + // TODO: a floating motor so object will bob in the water if (Position.Z < waterHeight) { _position.Z = waterHeight; @@ -902,7 +903,8 @@ public sealed class BSPrim : BSPhysObject } // DetailLog("{0},BSPrim.AddObjectForce,taint,force={1}", LocalID, fSum); // For unknown reasons, "ApplyCentralForce" adds this force to the total force on the object. - BulletSimAPI.ApplyCentralForce2(BSBody.ptr, fSum); + if (fSum != OMV.Vector3.Zero) + BulletSimAPI.ApplyCentralForce2(BSBody.ptr, fSum); }; if (inTaintTime) addForceOperation(); diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs index db0c99e..9e95ce5 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs @@ -62,7 +62,7 @@ using OpenMetaverse; // namespace OpenSim.Region.Physics.BulletSPlugin { -public class BSScene : PhysicsScene, IPhysicsParameters +public sealed class BSScene : PhysicsScene, IPhysicsParameters { private static readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); private static readonly string LogHeader = "[BULLETS SCENE]"; diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs index 30fa50a..1c0e6f5 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs @@ -34,7 +34,7 @@ using OpenSim.Region.Physics.ConvexDecompositionDotNet; namespace OpenSim.Region.Physics.BulletSPlugin { -public class BSShapeCollection : IDisposable +public sealed class BSShapeCollection : IDisposable { private static string LogHeader = "[BULLETSIM SHAPE COLLECTION]"; diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs index 880859a..11298fe 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs @@ -40,7 +40,7 @@ using OpenMetaverse; namespace OpenSim.Region.Physics.BulletSPlugin { -public class BSTerrainManager +public sealed class BSTerrainManager { static string LogHeader = "[BULLETSIM TERRAIN MANAGER]"; -- cgit v1.1 From b83449ae9ad3073abaa06167a99c47943c3199c2 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Fri, 26 Oct 2012 13:47:28 -0700 Subject: BulletSim: correct spelling of Bullet call. It's 'swept' not 'sweep'. --- OpenSim/Region/Physics/BulletSPlugin/BS6DofConstraint.cs | 4 ++++ OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs | 2 +- OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs | 4 ++-- 3 files changed, 7 insertions(+), 3 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BS6DofConstraint.cs b/OpenSim/Region/Physics/BulletSPlugin/BS6DofConstraint.cs index 310df3d..ecb3ec8 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BS6DofConstraint.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BS6DofConstraint.cs @@ -135,7 +135,11 @@ public sealed class BS6DofConstraint : BSConstraint bool ret = false; float onOff = enable ? ConfigurationParameters.numericTrue : ConfigurationParameters.numericFalse; if (m_enabled) + { ret = BulletSimAPI.TranslationalLimitMotor2(m_constraint.ptr, onOff, targetVelocity, maxMotorForce); + m_world.physicsScene.DetailLog("{0},BS6DOFConstraint,TransLimitMotor,enable={1},vel={2},maxForce={3}", + BSScene.DetailLogZero, enable, targetVelocity, maxMotorForce); + } return ret; } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs index 9fea9b8..8bb4b21 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs @@ -152,7 +152,7 @@ public sealed class BSCharacter : BSPhysObject if (PhysicsScene.Params.ccdMotionThreshold > 0f) { BulletSimAPI.SetCcdMotionThreshold2(BSBody.ptr, PhysicsScene.Params.ccdMotionThreshold); - BulletSimAPI.SetCcdSweepSphereRadius2(BSBody.ptr, PhysicsScene.Params.ccdSweptSphereRadius); + BulletSimAPI.SetCcdSweptSphereRadius2(BSBody.ptr, PhysicsScene.Params.ccdSweptSphereRadius); } OMV.Vector3 localInertia = BulletSimAPI.CalculateLocalInertia2(BSShape.ptr, MassRaw); diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs index 5ffd591..be3a5ad 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs @@ -881,10 +881,10 @@ public static extern float GetCcdMotionThreshold2(IntPtr obj); public static extern void SetCcdMotionThreshold2(IntPtr obj, float val); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern float GetCcdSweepSphereRadius2(IntPtr obj); +public static extern float GetCcdSweptSphereRadius2(IntPtr obj); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void SetCcdSweepSphereRadius2(IntPtr obj, float val); +public static extern void SetCcdSweptSphereRadius2(IntPtr obj, float val); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern IntPtr GetUserPointer2(IntPtr obj); -- cgit v1.1 From 8fa83cf43045401ee02321e0fb1191402db5bb05 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Fri, 26 Oct 2012 13:49:57 -0700 Subject: BulletSim: Add activations after vehicle properties change. Problem was the vehicle was going to sleep while waiting for commands. Make AddAngularForce work the same way as AddForce -- accumulates values and pushes them once into Bullet. --- OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | 74 +++++++++++++++++++++----- 1 file changed, 62 insertions(+), 12 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index 39d20dc..44937df 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs @@ -242,8 +242,8 @@ public sealed class BSPrim : BSPhysObject _acceleration = OMV.Vector3.Zero; _rotationalVelocity = OMV.Vector3.Zero; - // Zero some other properties directly into the physics engine - BulletSimAPI.ClearForces2(BSBody.ptr); + // Zero some other properties in the physics engine + BulletSimAPI.ClearAllForces2(BSBody.ptr); } public override void LockAngularMotion(OMV.Vector3 axis) @@ -275,6 +275,7 @@ public sealed class BSPrim : BSPhysObject { // DetailLog("{0},BSPrim.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation); BulletSimAPI.SetTranslation2(BSBody.ptr, _position, _orientation); + ActivateIfPhysical(false); }); } } @@ -287,6 +288,7 @@ public sealed class BSPrim : BSPhysObject _position = value; PositionSanityCheck(); BulletSimAPI.SetTranslation2(BSBody.ptr, _position, _orientation); + ActivateIfPhysical(false); } } @@ -401,6 +403,7 @@ public sealed class BSPrim : BSPhysObject // Done at taint time so we're sure the physics engine is not using the variables // Vehicle code changes the parameters for this vehicle type. _vehicle.ProcessTypeChange(type); + ActivateIfPhysical(false); }); } } @@ -409,6 +412,7 @@ public sealed class BSPrim : BSPhysObject PhysicsScene.TaintedObject("BSPrim.VehicleFloatParam", delegate() { _vehicle.ProcessFloatVehicleParam((Vehicle)param, value); + ActivateIfPhysical(false); }); } public override void VehicleVectorParam(int param, OMV.Vector3 value) @@ -416,6 +420,7 @@ public sealed class BSPrim : BSPhysObject PhysicsScene.TaintedObject("BSPrim.VehicleVectorParam", delegate() { _vehicle.ProcessVectorVehicleParam((Vehicle)param, value); + ActivateIfPhysical(false); }); } public override void VehicleRotationParam(int param, OMV.Quaternion rotation) @@ -423,6 +428,7 @@ public sealed class BSPrim : BSPhysObject PhysicsScene.TaintedObject("BSPrim.VehicleRotationParam", delegate() { _vehicle.ProcessRotationVehicleParam((Vehicle)param, rotation); + ActivateIfPhysical(false); }); } public override void VehicleFlags(int param, bool remove) @@ -540,6 +546,8 @@ public sealed class BSPrim : BSPhysObject { // DetailLog("{0},setIsPhysical,taint,isPhys={1}", LocalID, _isPhysical); SetObjectDynamic(true); + // whether phys-to-static or static-to-phys, the object is not moving. + ZeroMotion(); }); } } @@ -623,7 +631,7 @@ public sealed class BSPrim : BSPhysObject // Become a Bullet 'static' object type CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(BSBody.ptr, CollisionFlags.CF_STATIC_OBJECT); // Stop all movement - BulletSimAPI.ClearAllForces2(BSBody.ptr); + ZeroMotion(); // Center of mass is at the center of the object BulletSimAPI.SetCenterOfMassByPosRot2(Linkset.LinksetRoot.BSBody.ptr, _position, _orientation); // Mass is zero which disables a bunch of physics stuff in Bullet @@ -634,7 +642,7 @@ public sealed class BSPrim : BSPhysObject if (PhysicsScene.Params.ccdMotionThreshold > 0f) { BulletSimAPI.SetCcdMotionThreshold2(BSBody.ptr, PhysicsScene.Params.ccdMotionThreshold); - BulletSimAPI.SetCcdSweepSphereRadius2(BSBody.ptr, PhysicsScene.Params.ccdSweptSphereRadius); + BulletSimAPI.SetCcdSweptSphereRadius2(BSBody.ptr, PhysicsScene.Params.ccdSweptSphereRadius); } // There can be special things needed for implementing linksets Linkset.MakeStatic(this); @@ -656,14 +664,14 @@ public sealed class BSPrim : BSPhysObject BulletSimAPI.SetRestitution2(BSBody.ptr, PhysicsScene.Params.defaultRestitution); // per http://www.bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=3382 - BulletSimAPI.ClearAllForces2(BSBody.ptr); + // Since this can be called multiple times, only zero forces when becoming physical + // BulletSimAPI.ClearAllForces2(BSBody.ptr); // For good measure, make sure the transform is set through to the motion state BulletSimAPI.SetTranslation2(BSBody.ptr, _position, _orientation); // A dynamic object has mass - IntPtr collisionShapePtr = BulletSimAPI.GetCollisionShape2(BSBody.ptr); - OMV.Vector3 inertia = BulletSimAPI.CalculateLocalInertia2(collisionShapePtr, Mass); + OMV.Vector3 inertia = BulletSimAPI.CalculateLocalInertia2(BSShape.ptr, Mass); BulletSimAPI.SetMassProps2(BSBody.ptr, _mass, inertia); BulletSimAPI.UpdateInertiaTensor2(BSBody.ptr); @@ -671,7 +679,7 @@ public sealed class BSPrim : BSPhysObject if (PhysicsScene.Params.ccdMotionThreshold > 0f) { BulletSimAPI.SetCcdMotionThreshold2(BSBody.ptr, PhysicsScene.Params.ccdMotionThreshold); - BulletSimAPI.SetCcdSweepSphereRadius2(BSBody.ptr, PhysicsScene.Params.ccdSweptSphereRadius); + BulletSimAPI.SetCcdSweptSphereRadius2(BSBody.ptr, PhysicsScene.Params.ccdSweptSphereRadius); } // Various values for simulation limits @@ -721,6 +729,15 @@ public sealed class BSPrim : BSPhysObject } } + // Enable physical actions. Bullet will keep sleeping non-moving physical objects so + // they need waking up when parameters are changed. + // Called in taint-time!! + private void ActivateIfPhysical(bool forceIt) + { + if (IsPhysical) + BulletSimAPI.Activate2(BSBody.ptr, forceIt); + } + // Turn on or off the flag controlling whether collision events are returned to the simulator. private void EnableCollisions(bool wantsCollisionEvents) { @@ -901,8 +918,7 @@ public sealed class BSPrim : BSPhysObject } m_accumulatedForces.Clear(); } - // DetailLog("{0},BSPrim.AddObjectForce,taint,force={1}", LocalID, fSum); - // For unknown reasons, "ApplyCentralForce" adds this force to the total force on the object. + DetailLog("{0},BSPrim.AddForce,taint,force={1}", LocalID, fSum); if (fSum != OMV.Vector3.Zero) BulletSimAPI.ApplyCentralForce2(BSBody.ptr, fSum); }; @@ -912,9 +928,43 @@ public sealed class BSPrim : BSPhysObject PhysicsScene.TaintedObject("BSPrim.AddForce", addForceOperation); } + private List m_accumulatedAngularForces = new List(); public override void AddAngularForce(OMV.Vector3 force, bool pushforce) { - // DetailLog("{0},BSPrim.AddAngularForce,call,angForce={1},push={2}", LocalID, force, pushforce); - // m_log.DebugFormat("{0}: AddAngularForce. f={1}, push={2}", LogHeader, force, pushforce); + AddAngularForce(force, pushforce, false); + } + public void AddAngularForce(OMV.Vector3 force, bool pushforce, bool inTaintTime) + { + if (force.IsFinite()) + { + // _force += force; + lock (m_accumulatedAngularForces) + m_accumulatedAngularForces.Add(new OMV.Vector3(force)); + } + else + { + m_log.WarnFormat("{0}: Got a NaN force applied to a prim. LocalID={1}", LogHeader, LocalID); + return; + } + BSScene.TaintCallback addAngularForceOperation = delegate() + { + OMV.Vector3 fSum = OMV.Vector3.Zero; + lock (m_accumulatedAngularForces) + { + // Sum the accumulated additional forces for one big force to apply once. + foreach (OMV.Vector3 v in m_accumulatedAngularForces) + { + fSum += v; + } + m_accumulatedAngularForces.Clear(); + } + // DetailLog("{0},BSPrim.AddAngularForce,taint,aForce={1}", LocalID, fSum); + if (fSum != OMV.Vector3.Zero) + BulletSimAPI.ApplyTorque2(BSBody.ptr, fSum); + }; + if (inTaintTime) + addAngularForceOperation(); + else + PhysicsScene.TaintedObject("BSPrim.AddForce", addAngularForceOperation); } public override void SetMomentum(OMV.Vector3 momentum) { // DetailLog("{0},BSPrim.SetMomentum,call,mom={1}", LocalID, momentum); -- cgit v1.1 From 2b75035aefceeae44e35364036a0748dfd5fb786 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Fri, 26 Oct 2012 13:54:54 -0700 Subject: BulletSim: add ForEachMember(action) call for linkset. --- OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs | 36 ++++++++++++++++++----- 1 file changed, 28 insertions(+), 8 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs index 24fe6b9..d0e514b 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs @@ -167,9 +167,8 @@ public abstract class BSLinkset bool ret = false; lock (m_linksetActivityLock) { - if (m_children.Contains(child)) - ret = true; - /* + ret = m_children.Contains(child); + /* Safer version but the above should work foreach (BSPhysObject bp in m_children) { if (child.LocalID == bp.LocalID) @@ -183,6 +182,25 @@ public abstract class BSLinkset return ret; } + // Perform an action on each member of the linkset including root prim. + // The action is performed only on the objects that are physically in the linkset. + // Depends on the action on whether this should be done at taint time. + public delegate bool ForEachMemberAction(BSPhysObject obj); + public virtual bool ForEachMember(ForEachMemberAction action) + { + bool ret = false; + lock (m_linksetActivityLock) + { + action(LinksetRoot); + foreach (BSPhysObject po in m_taintChildren) + { + if (action(po)) + break; + } + } + return ret; + } + // When physical properties are changed the linkset needs to recalculate // its internal properties. // May be called at runtime or taint-time (just pass the appropriate flag). @@ -224,13 +242,15 @@ public abstract class BSLinkset protected virtual float ComputeLinksetMass() { - float mass; - lock (m_linksetActivityLock) + float mass = LinksetRoot.MassRaw; + if (HasAnyChildren) { - mass = LinksetRoot.MassRaw; - foreach (BSPhysObject bp in m_taintChildren) + lock (m_linksetActivityLock) { - mass += bp.MassRaw; + foreach (BSPhysObject bp in m_children) + { + mass += bp.MassRaw; + } } } return mass; -- cgit v1.1 From 92d3c611e57fc320bf20b6b500c275eaebf912aa Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Fri, 26 Oct 2012 13:55:20 -0700 Subject: BulletSim: many small changes for vehicles simulation. --- OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs | 71 ++++++++++++---------- 1 file changed, 40 insertions(+), 31 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs index 9b59bef..8bd8117 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs @@ -526,6 +526,12 @@ namespace OpenSim.Region.Physics.BulletSPlugin BulletSimAPI.UpdateInertiaTensor2(Prim.BSBody.ptr); } */ + if (IsActive) + { + // Friction effects are handled by this vehicle code + BulletSimAPI.SetFriction2(Prim.BSBody.ptr, 0f); + BulletSimAPI.SetHitFraction2(Prim.BSBody.ptr, 0f); + } } // One step of the vehicle properties for the next 'pTimestep' seconds. @@ -552,6 +558,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin Prim.ForceOrientation = newOrientation; } */ + BulletSimAPI.SetInterpolationVelocity2(Prim.BSBody.ptr, m_newVelocity, m_lastAngularVelocity); // remember the position so next step we can limit absolute movement effects m_lastPositionVector = Prim.ForcePosition; @@ -570,17 +577,21 @@ namespace OpenSim.Region.Physics.BulletSPlugin { Vector3 origDir = m_linearMotorDirection; Vector3 origVel = m_lastLinearVelocityVector; + Vector3 vehicleVelocity = Prim.ForceVelocity * Quaternion.Inverse(Prim.ForceOrientation); // DEBUG // add drive to body Vector3 addAmount = (m_linearMotorDirection - m_lastLinearVelocityVector)/(m_linearMotorTimescale / pTimestep); // lastLinearVelocityVector is the current body velocity vector m_lastLinearVelocityVector += addAmount; - float keepfraction = 1.0f - (1.0f / (m_linearMotorDecayTimescale / pTimestep)); - m_linearMotorDirection *= keepfraction; + float decayFactor = (1.0f / m_linearMotorDecayTimescale) * pTimestep; + m_linearMotorDirection *= (1f - decayFactor); - VDetailLog("{0},MoveLinear,nonZero,origdir={1},origvel={2},add={3},notDecay={4},dir={5},vel={6}", - Prim.LocalID, origDir, origVel, addAmount, keepfraction, m_linearMotorDirection, m_lastLinearVelocityVector); + Vector3 frictionFactor = (Vector3.One / m_linearFrictionTimescale) * pTimestep; + m_lastLinearVelocityVector *= (Vector3.One - frictionFactor); + + VDetailLog("{0},MoveLinear,nonZero,origdir={1},origvel={2},vehVel={3},add={4},decay={5},lmDir={6},lmVel={7}", + Prim.LocalID, origDir, origVel, vehicleVelocity, addAmount, decayFactor, m_linearMotorDirection, m_lastLinearVelocityVector); // convert requested object velocity to object relative vector m_newVelocity = m_lastLinearVelocityVector * Prim.ForceOrientation; @@ -661,18 +672,18 @@ namespace OpenSim.Region.Physics.BulletSPlugin } else { - float horizontalError = pos.Z - m_VhoverTargetHeight; + float verticalError = pos.Z - m_VhoverTargetHeight; // RA: where does the 50 come from> - float horizontalCorrectionVelocity = ((horizontalError * 50.0f) / (m_VhoverTimescale / pTimestep)); + float verticalCorrectionVelocity = pTimestep * ((verticalError * 50.0f) / m_VhoverTimescale); // Replace Vertical speed with correction figure if significant - if (Math.Abs(horizontalError) > 0.01f) + if (Math.Abs(verticalError) > 0.01f) { - m_newVelocity.Z += horizontalCorrectionVelocity; + m_newVelocity.Z += verticalCorrectionVelocity; //KF: m_VhoverEfficiency is not yet implemented } - else if (horizontalError < -0.01) + else if (verticalError < -0.01) { - m_newVelocity.Z -= horizontalCorrectionVelocity; + m_newVelocity.Z -= verticalCorrectionVelocity; } else { @@ -748,16 +759,13 @@ namespace OpenSim.Region.Physics.BulletSPlugin if ((m_flags & (VehicleFlag.NO_Z)) != 0) m_newVelocity.Z = 0; - // Apply friction - Vector3 keepFraction = Vector3.One - (Vector3.One / (m_linearFrictionTimescale / pTimestep)); - m_lastLinearVelocityVector *= keepFraction; - // Apply velocity - // Prim.ForceVelocity = m_newVelocity; - Prim.AddForce(m_newVelocity, false); + Prim.ForceVelocity = m_newVelocity; + // Prim.AddForce(m_newVelocity * Prim.Linkset.LinksetMass, false); + // Prim.AddForce(grav * Prim.Linkset.LinksetMass, false); - VDetailLog("{0},MoveLinear,done,lmDir={1},lmVel={2},newVel={3},grav={4},1Mdecay={5}", - Prim.LocalID, m_linearMotorDirection, m_lastLinearVelocityVector, m_newVelocity, grav, keepFraction); + VDetailLog("{0},MoveLinear,done,lmDir={1},lmVel={2},newVel={3},grav={4}", + Prim.LocalID, m_linearMotorDirection, m_lastLinearVelocityVector, m_newVelocity, grav); } // end MoveLinear() @@ -858,14 +866,17 @@ namespace OpenSim.Region.Physics.BulletSPlugin #region Deflection //Forward is the prefered direction, but if the reference frame has changed, we need to take this into account as well - Vector3 PreferredAxisOfMotion = - new Vector3((10*(m_angularDeflectionEfficiency/m_angularDeflectionTimescale)), 0, 0); - PreferredAxisOfMotion *= Quaternion.Add(Prim.ForceOrientation, m_referenceFrame); + if (m_angularDeflectionEfficiency != 0) + { + Vector3 preferredAxisOfMotion = + new Vector3((pTimestep * 10 * (m_angularDeflectionEfficiency / m_angularDeflectionTimescale)), 0, 0); + preferredAxisOfMotion *= Quaternion.Add(Prim.ForceOrientation, m_referenceFrame); - //Multiply it so that it scales linearly - //deflection = PreferredAxisOfMotion; + deflection = (preferredAxisOfMotion * (m_angularDeflectionEfficiency) / m_angularDeflectionTimescale) * pTimestep; - //deflection = ((PreferredAxisOfMotion * m_angularDeflectionEfficiency) / (m_angularDeflectionTimescale / pTimestep)); + VDetailLog("{0},MoveAngular,Deflection,perfAxis={1},deflection={2}", + Prim.LocalID, preferredAxisOfMotion, deflection); + } #endregion @@ -917,18 +928,16 @@ namespace OpenSim.Region.Physics.BulletSPlugin banking += bankingRot; } m_angularMotorVelocity.X *= m_bankingEfficiency == 1 ? 0.0f : 1 - m_bankingEfficiency; + VDetailLog("{0},MoveAngular,Banking,bEff={1},angMotVel={2},banking={3}", + Prim.LocalID, m_bankingEfficiency, m_angularMotorVelocity, banking); } #endregion m_lastVertAttractor = vertattr; - // Bank section tba - - // Deflection section tba - // Sum velocities - m_lastAngularVelocity = m_angularMotorVelocity + vertattr; // + bank + deflection + m_lastAngularVelocity = m_angularMotorVelocity + vertattr + banking + deflection; if ((m_flags & (VehicleFlag.NO_DEFLECTION_UP)) != 0) { @@ -948,8 +957,8 @@ namespace OpenSim.Region.Physics.BulletSPlugin m_lastAngularVelocity -= m_lastAngularVelocity * decayamount; // Apply to the body - // Prim.ForceRotationalVelocity = m_lastAngularVelocity; - Prim.AddAngularForce(m_lastAngularVelocity, false); + // The above calculates the absolute angular velocity needed + Prim.ForceRotationalVelocity = m_lastAngularVelocity; VDetailLog("{0},MoveAngular,done,decay={1},lastAngular={2}", Prim.LocalID, decayamount, m_lastAngularVelocity); } //end MoveAngular -- cgit v1.1 From 7af28724acf12245977fc44576c36ec0de320a8a Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Fri, 26 Oct 2012 16:09:08 -0700 Subject: BulletSim: rename constraint classes so they show up together alphabetically. --- .../Physics/BulletSPlugin/BS6DofConstraint.cs | 154 --------------------- .../Physics/BulletSPlugin/BSConstraint6Dof.cs | 154 +++++++++++++++++++++ .../Physics/BulletSPlugin/BSConstraintHinge.cs | 57 ++++++++ .../Physics/BulletSPlugin/BSHingeConstraint.cs | 57 -------- .../Physics/BulletSPlugin/BSLinksetConstraints.cs | 2 +- 5 files changed, 212 insertions(+), 212 deletions(-) delete mode 100755 OpenSim/Region/Physics/BulletSPlugin/BS6DofConstraint.cs create mode 100755 OpenSim/Region/Physics/BulletSPlugin/BSConstraint6Dof.cs create mode 100755 OpenSim/Region/Physics/BulletSPlugin/BSConstraintHinge.cs delete mode 100755 OpenSim/Region/Physics/BulletSPlugin/BSHingeConstraint.cs (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BS6DofConstraint.cs b/OpenSim/Region/Physics/BulletSPlugin/BS6DofConstraint.cs deleted file mode 100755 index ecb3ec8..0000000 --- a/OpenSim/Region/Physics/BulletSPlugin/BS6DofConstraint.cs +++ /dev/null @@ -1,154 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyrightD - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -using System; -using System.Collections.Generic; -using System.Text; -using OpenMetaverse; - -namespace OpenSim.Region.Physics.BulletSPlugin -{ - -public sealed class BS6DofConstraint : BSConstraint -{ - private static string LogHeader = "[BULLETSIM 6DOF CONSTRAINT]"; - - public override ConstraintType Type { get { return ConstraintType.D6_CONSTRAINT_TYPE; } } - - // Create a btGeneric6DofConstraint - public BS6DofConstraint(BulletSim world, BulletBody obj1, BulletBody obj2, - Vector3 frame1, Quaternion frame1rot, - Vector3 frame2, Quaternion frame2rot, - bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies) - { - m_world = world; - m_body1 = obj1; - m_body2 = obj2; - m_constraint = new BulletConstraint( - BulletSimAPI.Create6DofConstraint2(m_world.ptr, m_body1.ptr, m_body2.ptr, - frame1, frame1rot, - frame2, frame2rot, - useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies)); - m_enabled = true; - world.physicsScene.DetailLog("{0},BS6DofConstraint,createFrame,wID={1}, rID={2}, rBody={3}, cID={4}, cBody={5}", - BSScene.DetailLogZero, world.worldID, - obj1.ID, obj1.ptr.ToString("X"), obj2.ID, obj2.ptr.ToString("X")); - } - - public BS6DofConstraint(BulletSim world, BulletBody obj1, BulletBody obj2, - Vector3 joinPoint, - bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies) - { - m_world = world; - m_body1 = obj1; - m_body2 = obj2; - if (obj1.ptr == IntPtr.Zero || obj2.ptr == IntPtr.Zero) - { - world.physicsScene.DetailLog("{0},BS6DOFConstraint,badBodyPtr,wID={1}, rID={2}, rBody={3}, cID={4}, cBody={5}", - BSScene.DetailLogZero, world.worldID, - obj1.ID, obj1.ptr.ToString("X"), obj2.ID, obj2.ptr.ToString("X")); - world.physicsScene.Logger.ErrorFormat("{0} Attempt to build 6DOF constraint with missing bodies: wID={1}, rID={2}, rBody={3}, cID={4}, cBody={5}", - "[BULLETSIM 6DOF CONSTRAINT]", world.worldID, - obj1.ID, obj1.ptr.ToString("X"), obj2.ID, obj2.ptr.ToString("X")); - m_enabled = false; - } - else - { - m_constraint = new BulletConstraint( - BulletSimAPI.Create6DofConstraintToPoint2(m_world.ptr, m_body1.ptr, m_body2.ptr, - joinPoint, - useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies)); - world.physicsScene.DetailLog("{0},BS6DofConstraint,createMidPoint,wID={1}, csrt={2}, rID={3}, rBody={4}, cID={5}, cBody={6}", - BSScene.DetailLogZero, world.worldID, m_constraint.ptr.ToString("X"), - obj1.ID, obj1.ptr.ToString("X"), obj2.ID, obj2.ptr.ToString("X")); - if (m_constraint.ptr == IntPtr.Zero) - { - world.physicsScene.Logger.ErrorFormat("{0} Failed creation of 6Dof constraint. rootID={1}, childID={2}", - LogHeader, obj1.ID, obj2.ID); - m_enabled = false; - } - else - { - m_enabled = true; - } - } - } - - public bool SetFrames(Vector3 frameA, Quaternion frameArot, Vector3 frameB, Quaternion frameBrot) - { - bool ret = false; - if (m_enabled) - { - BulletSimAPI.SetFrames2(m_constraint.ptr, frameA, frameArot, frameB, frameBrot); - ret = true; - } - return ret; - } - - public bool SetCFMAndERP(float cfm, float erp) - { - bool ret = false; - if (m_enabled) - { - BulletSimAPI.SetConstraintParam2(m_constraint.ptr, ConstraintParams.BT_CONSTRAINT_STOP_CFM, cfm, ConstraintParamAxis.AXIS_ALL); - BulletSimAPI.SetConstraintParam2(m_constraint.ptr, ConstraintParams.BT_CONSTRAINT_STOP_ERP, erp, ConstraintParamAxis.AXIS_ALL); - BulletSimAPI.SetConstraintParam2(m_constraint.ptr, ConstraintParams.BT_CONSTRAINT_CFM, cfm, ConstraintParamAxis.AXIS_ALL); - ret = true; - } - return ret; - } - - public bool UseFrameOffset(bool useOffset) - { - bool ret = false; - float onOff = useOffset ? ConfigurationParameters.numericTrue : ConfigurationParameters.numericFalse; - if (m_enabled) - ret = BulletSimAPI.UseFrameOffset2(m_constraint.ptr, onOff); - return ret; - } - - public bool TranslationalLimitMotor(bool enable, float targetVelocity, float maxMotorForce) - { - bool ret = false; - float onOff = enable ? ConfigurationParameters.numericTrue : ConfigurationParameters.numericFalse; - if (m_enabled) - { - ret = BulletSimAPI.TranslationalLimitMotor2(m_constraint.ptr, onOff, targetVelocity, maxMotorForce); - m_world.physicsScene.DetailLog("{0},BS6DOFConstraint,TransLimitMotor,enable={1},vel={2},maxForce={3}", - BSScene.DetailLogZero, enable, targetVelocity, maxMotorForce); - } - return ret; - } - - public bool SetBreakingImpulseThreshold(float threshold) - { - bool ret = false; - if (m_enabled) - ret = BulletSimAPI.SetBreakingImpulseThreshold2(m_constraint.ptr, threshold); - return ret; - } -} -} diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSConstraint6Dof.cs b/OpenSim/Region/Physics/BulletSPlugin/BSConstraint6Dof.cs new file mode 100755 index 0000000..3c37d76 --- /dev/null +++ b/OpenSim/Region/Physics/BulletSPlugin/BSConstraint6Dof.cs @@ -0,0 +1,154 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyrightD + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +using System; +using System.Collections.Generic; +using System.Text; +using OpenMetaverse; + +namespace OpenSim.Region.Physics.BulletSPlugin +{ + +public sealed class BSConstraint6Dof : BSConstraint +{ + private static string LogHeader = "[BULLETSIM 6DOF CONSTRAINT]"; + + public override ConstraintType Type { get { return ConstraintType.D6_CONSTRAINT_TYPE; } } + + // Create a btGeneric6DofConstraint + public BSConstraint6Dof(BulletSim world, BulletBody obj1, BulletBody obj2, + Vector3 frame1, Quaternion frame1rot, + Vector3 frame2, Quaternion frame2rot, + bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies) + { + m_world = world; + m_body1 = obj1; + m_body2 = obj2; + m_constraint = new BulletConstraint( + BulletSimAPI.Create6DofConstraint2(m_world.ptr, m_body1.ptr, m_body2.ptr, + frame1, frame1rot, + frame2, frame2rot, + useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies)); + m_enabled = true; + world.physicsScene.DetailLog("{0},BS6DofConstraint,createFrame,wID={1}, rID={2}, rBody={3}, cID={4}, cBody={5}", + BSScene.DetailLogZero, world.worldID, + obj1.ID, obj1.ptr.ToString("X"), obj2.ID, obj2.ptr.ToString("X")); + } + + public BSConstraint6Dof(BulletSim world, BulletBody obj1, BulletBody obj2, + Vector3 joinPoint, + bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies) + { + m_world = world; + m_body1 = obj1; + m_body2 = obj2; + if (obj1.ptr == IntPtr.Zero || obj2.ptr == IntPtr.Zero) + { + world.physicsScene.DetailLog("{0},BS6DOFConstraint,badBodyPtr,wID={1}, rID={2}, rBody={3}, cID={4}, cBody={5}", + BSScene.DetailLogZero, world.worldID, + obj1.ID, obj1.ptr.ToString("X"), obj2.ID, obj2.ptr.ToString("X")); + world.physicsScene.Logger.ErrorFormat("{0} Attempt to build 6DOF constraint with missing bodies: wID={1}, rID={2}, rBody={3}, cID={4}, cBody={5}", + "[BULLETSIM 6DOF CONSTRAINT]", world.worldID, + obj1.ID, obj1.ptr.ToString("X"), obj2.ID, obj2.ptr.ToString("X")); + m_enabled = false; + } + else + { + m_constraint = new BulletConstraint( + BulletSimAPI.Create6DofConstraintToPoint2(m_world.ptr, m_body1.ptr, m_body2.ptr, + joinPoint, + useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies)); + world.physicsScene.DetailLog("{0},BS6DofConstraint,createMidPoint,wID={1}, csrt={2}, rID={3}, rBody={4}, cID={5}, cBody={6}", + BSScene.DetailLogZero, world.worldID, m_constraint.ptr.ToString("X"), + obj1.ID, obj1.ptr.ToString("X"), obj2.ID, obj2.ptr.ToString("X")); + if (m_constraint.ptr == IntPtr.Zero) + { + world.physicsScene.Logger.ErrorFormat("{0} Failed creation of 6Dof constraint. rootID={1}, childID={2}", + LogHeader, obj1.ID, obj2.ID); + m_enabled = false; + } + else + { + m_enabled = true; + } + } + } + + public bool SetFrames(Vector3 frameA, Quaternion frameArot, Vector3 frameB, Quaternion frameBrot) + { + bool ret = false; + if (m_enabled) + { + BulletSimAPI.SetFrames2(m_constraint.ptr, frameA, frameArot, frameB, frameBrot); + ret = true; + } + return ret; + } + + public bool SetCFMAndERP(float cfm, float erp) + { + bool ret = false; + if (m_enabled) + { + BulletSimAPI.SetConstraintParam2(m_constraint.ptr, ConstraintParams.BT_CONSTRAINT_STOP_CFM, cfm, ConstraintParamAxis.AXIS_ALL); + BulletSimAPI.SetConstraintParam2(m_constraint.ptr, ConstraintParams.BT_CONSTRAINT_STOP_ERP, erp, ConstraintParamAxis.AXIS_ALL); + BulletSimAPI.SetConstraintParam2(m_constraint.ptr, ConstraintParams.BT_CONSTRAINT_CFM, cfm, ConstraintParamAxis.AXIS_ALL); + ret = true; + } + return ret; + } + + public bool UseFrameOffset(bool useOffset) + { + bool ret = false; + float onOff = useOffset ? ConfigurationParameters.numericTrue : ConfigurationParameters.numericFalse; + if (m_enabled) + ret = BulletSimAPI.UseFrameOffset2(m_constraint.ptr, onOff); + return ret; + } + + public bool TranslationalLimitMotor(bool enable, float targetVelocity, float maxMotorForce) + { + bool ret = false; + float onOff = enable ? ConfigurationParameters.numericTrue : ConfigurationParameters.numericFalse; + if (m_enabled) + { + ret = BulletSimAPI.TranslationalLimitMotor2(m_constraint.ptr, onOff, targetVelocity, maxMotorForce); + m_world.physicsScene.DetailLog("{0},BS6DOFConstraint,TransLimitMotor,enable={1},vel={2},maxForce={3}", + BSScene.DetailLogZero, enable, targetVelocity, maxMotorForce); + } + return ret; + } + + public bool SetBreakingImpulseThreshold(float threshold) + { + bool ret = false; + if (m_enabled) + ret = BulletSimAPI.SetBreakingImpulseThreshold2(m_constraint.ptr, threshold); + return ret; + } +} +} diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSConstraintHinge.cs b/OpenSim/Region/Physics/BulletSPlugin/BSConstraintHinge.cs new file mode 100755 index 0000000..ed3ffa7 --- /dev/null +++ b/OpenSim/Region/Physics/BulletSPlugin/BSConstraintHinge.cs @@ -0,0 +1,57 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyrightD + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +using System; +using System.Collections.Generic; +using System.Text; +using OpenMetaverse; + +namespace OpenSim.Region.Physics.BulletSPlugin +{ + +public sealed class BSConstraintHinge : BSConstraint +{ + public override ConstraintType Type { get { return ConstraintType.HINGE_CONSTRAINT_TYPE; } } + + public BSConstraintHinge(BulletSim world, BulletBody obj1, BulletBody obj2, + Vector3 pivotInA, Vector3 pivotInB, + Vector3 axisInA, Vector3 axisInB, + bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies) + { + m_world = world; + m_body1 = obj1; + m_body2 = obj2; + m_constraint = new BulletConstraint( + BulletSimAPI.CreateHingeConstraint2(m_world.ptr, m_body1.ptr, m_body2.ptr, + pivotInA, pivotInB, + axisInA, axisInB, + useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies)); + m_enabled = true; + } + +} + +} diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSHingeConstraint.cs b/OpenSim/Region/Physics/BulletSPlugin/BSHingeConstraint.cs deleted file mode 100755 index 76bd930..0000000 --- a/OpenSim/Region/Physics/BulletSPlugin/BSHingeConstraint.cs +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyrightD - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -using System; -using System.Collections.Generic; -using System.Text; -using OpenMetaverse; - -namespace OpenSim.Region.Physics.BulletSPlugin -{ - -public sealed class BSHingeConstraint : BSConstraint -{ - public override ConstraintType Type { get { return ConstraintType.HINGE_CONSTRAINT_TYPE; } } - - public BSHingeConstraint(BulletSim world, BulletBody obj1, BulletBody obj2, - Vector3 pivotInA, Vector3 pivotInB, - Vector3 axisInA, Vector3 axisInB, - bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies) - { - m_world = world; - m_body1 = obj1; - m_body2 = obj2; - m_constraint = new BulletConstraint( - BulletSimAPI.CreateHingeConstraint2(m_world.ptr, m_body1.ptr, m_body2.ptr, - pivotInA, pivotInB, - axisInA, axisInB, - useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies)); - m_enabled = true; - } - -} - -} diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs index 003c294..67979b3 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs @@ -246,7 +246,7 @@ public sealed class BSLinksetConstraints : BSLinkset // create a constraint that allows no freedom of movement between the two objects // http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818 - BS6DofConstraint constrain = new BS6DofConstraint( + BSConstraint6Dof constrain = new BSConstraint6Dof( PhysicsScene.World, rootPrim.BSBody, childPrim.BSBody, midPoint, true, true ); /* NOTE: below is an attempt to build constraint with full frame computation, etc. -- cgit v1.1 From e20bad12cc0584c6368e46e0f326e6b616133e8f Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Mon, 29 Oct 2012 11:30:47 -0700 Subject: BulletSim: centralize mass/inertia computation with UpdatePhysicalMassProperties() function. Didn't add setMassRaw because assignment with side effect is dirty. --- .../Region/Physics/BulletSPlugin/BSCharacter.cs | 15 ++++++--- .../Region/Physics/BulletSPlugin/BSPhysObject.cs | 2 ++ OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | 39 ++++++++++++++-------- 3 files changed, 38 insertions(+), 18 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs index 8bb4b21..b9013ab 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs @@ -155,8 +155,7 @@ public sealed class BSCharacter : BSPhysObject BulletSimAPI.SetCcdSweptSphereRadius2(BSBody.ptr, PhysicsScene.Params.ccdSweptSphereRadius); } - OMV.Vector3 localInertia = BulletSimAPI.CalculateLocalInertia2(BSShape.ptr, MassRaw); - BulletSimAPI.SetMassProps2(BSBody.ptr, MassRaw, localInertia); + UpdatePhysicalMassProperties(MassRaw); // Make so capsule does not fall over BulletSimAPI.SetAngularFactorV2(BSBody.ptr, OMV.Vector3.Zero); @@ -201,8 +200,7 @@ public sealed class BSCharacter : BSPhysObject PhysicsScene.TaintedObject("BSCharacter.setSize", delegate() { BulletSimAPI.SetLocalScaling2(BSShape.ptr, Scale); - OMV.Vector3 localInertia = BulletSimAPI.CalculateLocalInertia2(BSShape.ptr, MassRaw); - BulletSimAPI.SetMassProps2(BSBody.ptr, MassRaw, localInertia); + UpdatePhysicalMassProperties(MassRaw); }); } @@ -329,7 +327,14 @@ public sealed class BSCharacter : BSPhysObject public override float Mass { get { return _mass; } } // used when we only want this prim's mass and not the linkset thing - public override float MassRaw { get {return _mass; } } + public override float MassRaw { + get {return _mass; } + } + public override void UpdatePhysicalMassProperties(float physMass) + { + OMV.Vector3 localInertia = BulletSimAPI.CalculateLocalInertia2(BSShape.ptr, physMass); + BulletSimAPI.SetMassProps2(BSBody.ptr, physMass, localInertia); + } public override OMV.Vector3 Force { get { return _force; } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs index 538f905..be8d64b 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs @@ -64,6 +64,8 @@ public abstract class BSPhysObject : PhysicsActor // Return the object mass without calculating it or having side effects public abstract float MassRaw { get; } + // Set the raw mass but also update physical mass properties (inertia, ...) + public abstract void UpdatePhysicalMassProperties(float mass); // Reference to the physical body (btCollisionObject) of this object public BulletBody BSBody; diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index 44937df..ad09a61 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs @@ -356,13 +356,32 @@ public sealed class BSPrim : BSPhysObject { get { - // return Linkset.LinksetMass; - return _mass; + return Linkset.LinksetMass; + // return _mass; } } // used when we only want this prim's mass and not the linkset thing - public override float MassRaw { get { return _mass; } } + public override float MassRaw { + get { return _mass; } + } + // Set the physical mass to the passed mass. + // Note that this does not change _mass! + public override void UpdatePhysicalMassProperties(float physMass) + { + if (IsStatic) + { + BulletSimAPI.SetMassProps2(BSBody.ptr, 0f, OMV.Vector3.Zero); + BulletSimAPI.UpdateInertiaTensor2(BSBody.ptr); + } + else + { + OMV.Vector3 localInertia = BulletSimAPI.CalculateLocalInertia2(BSShape.ptr, physMass); + BulletSimAPI.SetMassProps2(BSBody.ptr, physMass, localInertia); + BulletSimAPI.UpdateInertiaTensor2(BSBody.ptr); + DetailLog("{0},BSPrim.UpdateMassProperties,mass={1},localInertia={2}", LocalID, physMass, localInertia); + } + } // Is this used? public override OMV.Vector3 CenterOfMass @@ -613,7 +632,7 @@ public sealed class BSPrim : BSPhysObject // Recompute any linkset parameters. // When going from non-physical to physical, this re-enables the constraints that // had been automatically disabled when the mass was set to zero. - Linkset.Refresh(this, true); + Linkset.Refresh(this); DetailLog("{0},BSPrim.UpdatePhysicalParameters,exit,static={1},solid={2},mass={3},collide={4},cf={5:X},body={6},shape={7}", LocalID, IsStatic, IsSolid, _mass, SubscribedEvents(), CurrentCollisionFlags, BSBody, BSShape); @@ -635,9 +654,7 @@ public sealed class BSPrim : BSPhysObject // Center of mass is at the center of the object BulletSimAPI.SetCenterOfMassByPosRot2(Linkset.LinksetRoot.BSBody.ptr, _position, _orientation); // Mass is zero which disables a bunch of physics stuff in Bullet - BulletSimAPI.SetMassProps2(BSBody.ptr, 0f, OMV.Vector3.Zero); - // There is no inertia in a static object - BulletSimAPI.UpdateInertiaTensor2(BSBody.ptr); + UpdatePhysicalMassProperties(0f); // Set collision detection parameters if (PhysicsScene.Params.ccdMotionThreshold > 0f) { @@ -671,9 +688,7 @@ public sealed class BSPrim : BSPhysObject BulletSimAPI.SetTranslation2(BSBody.ptr, _position, _orientation); // A dynamic object has mass - OMV.Vector3 inertia = BulletSimAPI.CalculateLocalInertia2(BSShape.ptr, Mass); - BulletSimAPI.SetMassProps2(BSBody.ptr, _mass, inertia); - BulletSimAPI.UpdateInertiaTensor2(BSBody.ptr); + UpdatePhysicalMassProperties(MassRaw); // Set collision detection parameters if (PhysicsScene.Params.ccdMotionThreshold > 0f) @@ -1247,9 +1262,7 @@ public sealed class BSPrim : BSPhysObject returnMass = _density * volume; - /* - * This change means each object keeps its own mass and the Mass property - * will return the sum if we're part of a linkset. + /* Comment out code that computes the mass of the linkset. That is done in the Linkset class. if (IsRootOfLinkset) { foreach (BSPrim prim in _childrenPrims) -- cgit v1.1 From 2f25f70316ff712d338bbff3f6d02650480a340b Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Mon, 29 Oct 2012 11:31:50 -0700 Subject: BulletSim: remove unneeded parameter from Refresh(). --- OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs index d0e514b..569d2e7 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs @@ -204,7 +204,7 @@ public abstract class BSLinkset // When physical properties are changed the linkset needs to recalculate // its internal properties. // May be called at runtime or taint-time (just pass the appropriate flag). - public abstract void Refresh(BSPhysObject requestor, bool inTaintTime); + public abstract void Refresh(BSPhysObject requestor); // The object is going dynamic (physical). Do any setup necessary // for a dynamic linkset. -- cgit v1.1 From 9568f24c2628312f366c99ce6beb5c193aace33c Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Mon, 29 Oct 2012 11:38:01 -0700 Subject: BulletSim: add post taint taints and post step taints. The post taints operation is most useful and is used by linksets to build and rebuild only once before the simulation step. --- OpenSim/Region/Physics/BulletSPlugin/BSScene.cs | 138 +++++++++++++++++++++--- 1 file changed, 122 insertions(+), 16 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs index 9e95ce5..cb52937 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs @@ -171,7 +171,9 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters } } private Object _taintLock = new Object(); // lock for using the next object - private List _taintedObjects; + private List _taintOperations; + private Dictionary _postTaintOperations; + private List _postStepOperations; // A pointer to an instance if this structure is passed to the C++ code // Used to pass basic configuration values to the unmanaged code. @@ -203,7 +205,9 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters public override void Initialise(IMesher meshmerizer, IConfigSource config) { mesher = meshmerizer; - _taintedObjects = new List(); + _taintOperations = new List(); + _postTaintOperations = new Dictionary(); + _postStepOperations = new List(); PhysObjects = new Dictionary(); Shapes = new BSShapeCollection(this); @@ -475,23 +479,21 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters if (!m_initialized) return 5.0f; // update the prim states while we know the physics engine is not busy - int numTaints = _taintedObjects.Count; + int numTaints = _taintOperations.Count; ProcessTaints(); // Some of the prims operate with special vehicle properties ProcessVehicles(timeStep); - numTaints += _taintedObjects.Count; + numTaints += _taintOperations.Count; ProcessTaints(); // the vehicles might have added taints // step the physical world one interval m_simulationStep++; int numSubSteps = 0; - // DEBUG - // DetailLog("{0},BSScene.Simulate,beforeStep,ntaimts={1},step={2}", DetailLogZero, numTaints, m_simulationStep); - try { + // DumpVehicles(); // DEBUG if (PhysicsLogging.Enabled) beforeTime = Util.EnvironmentTickCount(); numSubSteps = BulletSimAPI.PhysicsStep2(World.ptr, timeStep, m_maxSubSteps, m_fixedTimeStep, @@ -500,6 +502,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters if (PhysicsLogging.Enabled) simTime = Util.EnvironmentTickCountSubtract(beforeTime); DetailLog("{0},Simulate,call, frame={1}, nTaints={2}, simTime={3}, substeps={4}, updates={5}, colliders={6}", DetailLogZero, m_simulationStep, numTaints, simTime, numSubSteps, updatedEntityCount, collidersCount); + // DumpVehicles(); // DEBUG } catch (Exception e) { @@ -579,6 +582,8 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters // Only enable this in a limited test world with few objects. // BulletSimAPI.DumpAllInfo2(World.ptr); // DEBUG DEBUG DEBUG + ProcessPostStepTaints(); + // The physics engine returns the number of milliseconds it simulated this call. // These are summed and normalized to one second and divided by 1000 to give the reported physics FPS. // We multiply by 55 to give a recognizable running rate (55 or less). @@ -670,6 +675,8 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters public override bool IsThreaded { get { return false; } } + #region Taints + // Calls to the PhysicsActors can't directly call into the physics engine // because it might be busy. We delay changes to a known time. // We rely on C#'s closure to save and restore the context for the delegate. @@ -679,7 +686,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters lock (_taintLock) { - _taintedObjects.Add(new TaintCallbackEntry(ident, callback)); + _taintOperations.Add(new TaintCallbackEntry(ident, callback)); } return; @@ -690,19 +697,25 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters // here just before the physics engine is called to step the simulation. public void ProcessTaints() { - if (_taintedObjects.Count > 0) // save allocating new list if there is nothing to process + ProcessRegularTaints(); + ProcessPostTaintTaints(); + } + + private void ProcessRegularTaints() + { + if (_taintOperations.Count > 0) // save allocating new list if there is nothing to process { int taintCount = m_taintsToProcessPerStep; TaintCallbackEntry oneCallback = new TaintCallbackEntry(); - while (_taintedObjects.Count > 0 && taintCount-- > 0) + while (_taintOperations.Count > 0 && taintCount-- > 0) { bool gotOne = false; lock (_taintLock) { - if (_taintedObjects.Count > 0) + if (_taintOperations.Count > 0) { - oneCallback = _taintedObjects[0]; - _taintedObjects.RemoveAt(0); + oneCallback = _taintOperations[0]; + _taintOperations.RemoveAt(0); gotOne = true; } } @@ -746,6 +759,89 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters } } + // Schedule an update to happen after all the regular taints are processed. + // Note that new requests for the same operation ("ident") for the same object ("ID") + // will replace any previous operation by the same object. + public void PostTaintObject(String ident, uint ID, TaintCallback callback) + { + if (!m_initialized) return; + + lock (_taintLock) + { + _postTaintOperations[ident] = new TaintCallbackEntry(ident + "-" + ID.ToString(), callback); + } + + return; + } + + private void ProcessPostTaintTaints() + { + if (_postTaintOperations.Count > 0) + { + Dictionary oldList; + lock (_taintLock) + { + oldList = _postTaintOperations; + _postTaintOperations = new Dictionary(); + } + + foreach (KeyValuePair kvp in oldList) + { + try + { + DetailLog("{0},BSScene.ProcessPostTaintTaints,doTaint,id={1}", DetailLogZero, kvp.Key); // DEBUG DEBUG DEBUG + kvp.Value.callback(); + } + catch (Exception e) + { + m_log.ErrorFormat("{0}: ProcessPostTaintTaints: {1}: Exception: {2}", LogHeader, kvp.Key, e); + } + } + oldList.Clear(); + } + } + + public void PostStepTaintObject(String ident, TaintCallback callback) + { + if (!m_initialized) return; + + lock (_taintLock) + { + _postStepOperations.Add(new TaintCallbackEntry(ident, callback)); + } + + return; + } + + private void ProcessPostStepTaints() + { + if (_postStepOperations.Count > 0) + { + List oldList; + lock (_taintLock) + { + oldList = _postStepOperations; + _postStepOperations = new List(); + } + + foreach (TaintCallbackEntry tcbe in oldList) + { + try + { + DetailLog("{0},BSScene.ProcessPostStepTaints,doTaint,id={1}", DetailLogZero, tcbe.ident); // DEBUG DEBUG DEBUG + tcbe.callback(); + } + catch (Exception e) + { + m_log.ErrorFormat("{0}: ProcessPostStepTaints: {1}: Exception: {2}", LogHeader, tcbe.ident, e); + } + } + oldList.Clear(); + } + } + + #endregion // Taints + #region Vehicles public void VehicleInSceneTypeChanged(BSPrim vehic, Vehicle newType) @@ -1006,7 +1102,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters (s,cf,p,v) => { s.m_params[0].ccdSweptSphereRadius = cf.GetFloat(p, v); }, (s) => { return s.m_params[0].ccdSweptSphereRadius; }, (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].ccdSweptSphereRadius, p, l, v); }, - (s,o,v) => { BulletSimAPI.SetCcdSweepSphereRadius2(o.BSBody.ptr, v); } ), + (s,o,v) => { BulletSimAPI.SetCcdSweptSphereRadius2(o.BSBody.ptr, v); } ), new ParameterDefn("ContactProcessingThreshold", "Distance between contacts before doing collision check" , 0.1f, (s,cf,p,v) => { s.m_params[0].contactProcessingThreshold = cf.GetFloat(p, v); }, @@ -1128,12 +1224,12 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters (s) => { return s.m_params[0].linkConstraintTransMotorMaxForce; }, (s,p,l,v) => { s.m_params[0].linkConstraintTransMotorMaxForce = v; } ), new ParameterDefn("LinkConstraintCFM", "Amount constraint can be violated. 0=no violation, 1=infinite. Default=0.1", - 0.001f, + 0.1f, (s,cf,p,v) => { s.m_params[0].linkConstraintCFM = cf.GetFloat(p, v); }, (s) => { return s.m_params[0].linkConstraintCFM; }, (s,p,l,v) => { s.m_params[0].linkConstraintCFM = v; } ), new ParameterDefn("LinkConstraintERP", "Amount constraint is corrected each tick. 0=none, 1=all. Default = 0.2", - 0.8f, + 0.1f, (s,cf,p,v) => { s.m_params[0].linkConstraintERP = cf.GetFloat(p, v); }, (s) => { return s.m_params[0].linkConstraintERP; }, (s,p,l,v) => { s.m_params[0].linkConstraintERP = v; } ), @@ -1326,6 +1422,16 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters #endregion Runtime settable parameters + // Debugging routine for dumping detailed physical information for vehicle prims + private void DumpVehicles() + { + foreach (BSPrim prim in m_vehicles) + { + BulletSimAPI.DumpRigidBody2(World.ptr, prim.BSBody.ptr); + BulletSimAPI.DumpCollisionShape2(World.ptr, prim.BSShape.ptr); + } + } + // Invoke the detailed logger and output something if it's enabled. public void DetailLog(string msg, params Object[] args) { -- cgit v1.1 From 8c9e4c1f7bdde47c9f29a9dfcf917421b943bb32 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Mon, 29 Oct 2012 11:41:25 -0700 Subject: BulletSim: Use Refresh/PostTaints to cause recomputing of constraint variables before the simulation step. Update logging and messages to properly name LinksetConstraints. Use UpdatePhysicalMassProperties to put the whole linkset mass into all the physical linkset members so they have the inertia to move the whole linkset. --- .../Physics/BulletSPlugin/BSLinksetConstraints.cs | 65 ++++++++++++---------- 1 file changed, 36 insertions(+), 29 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs index 67979b3..086aa12 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs @@ -43,23 +43,20 @@ public sealed class BSLinksetConstraints : BSLinkset // When physical properties are changed the linkset needs to recalculate // its internal properties. - // May be called at runtime or taint-time (just pass the appropriate flag). - public override void Refresh(BSPhysObject requestor, bool inTaintTime) + // This is queued in such a way that the + // refresh will only happen once after all the other taints are applied. + public override void Refresh(BSPhysObject requestor) { - // If there are no children or not root, I am not the one that recomputes the constraints - if (!HasAnyChildren || !IsRoot(requestor)) + // If there are no children, there are no constraints to recompute. + if (!HasAnyChildren) return; - BSScene.TaintCallback refreshOperation = delegate() + // Queue to happen after all the other taint processing + PhysicsScene.PostTaintObject("BSLinksetContraints.Refresh", requestor.LocalID, delegate() { RecomputeLinksetConstraintVariables(); - DetailLog("{0},BSLinkset.Refresh,complete,rBody={1}", - LinksetRoot.LocalID, LinksetRoot.BSBody.ptr.ToString("X")); - }; - if (inTaintTime) - refreshOperation(); - else - PhysicsScene.TaintedObject("BSLinkSet.Refresh", refreshOperation); + }); + } // The object is going dynamic (physical). Do any setup necessary @@ -104,14 +101,14 @@ public sealed class BSLinksetConstraints : BSLinkset if (IsRoot(child)) { // If the one with the dependency is root, must undo all children - DetailLog("{0},BSLinkset.RemoveBodyDependencies,removeChildrenForRoot,rID={1},rBody={2}", + DetailLog("{0},BSLinksetConstraint.RemoveBodyDependencies,removeChildrenForRoot,rID={1},rBody={2}", child.LocalID, LinksetRoot.LocalID, LinksetRoot.BSBody.ptr.ToString("X")); ret = PhysicallyUnlinkAllChildrenFromRoot(LinksetRoot); } else { - DetailLog("{0},BSLinkset.RemoveBodyDependencies,removeSingleChild,rID={1},rBody={2},cID={3},cBody={4}", + DetailLog("{0},BSLinksetConstraint.RemoveBodyDependencies,removeSingleChild,rID={1},rBody={2},cID={3},cBody={4}", child.LocalID, LinksetRoot.LocalID, LinksetRoot.BSBody.ptr.ToString("X"), child.LocalID, child.BSBody.ptr.ToString("X")); @@ -132,7 +129,7 @@ public sealed class BSLinksetConstraints : BSLinkset { if (IsRoot(child)) { - DetailLog("{0},BSLinkset.RestoreBodyDependencies,restoreChildrenForRoot,rID={1},numChild={2}", + DetailLog("{0},BSLinksetConstraint.RestoreBodyDependencies,restoreChildrenForRoot,rID={1},numChild={2}", child.LocalID, LinksetRoot.LocalID, m_taintChildren.Count); foreach (BSPhysObject bpo in m_taintChildren) { @@ -141,7 +138,7 @@ public sealed class BSLinksetConstraints : BSLinkset } else { - DetailLog("{0},BSLinkset.RestoreBodyDependencies,restoreSingleChild,rID={1},rBody={2},cID={3},cBody={4}", + DetailLog("{0},BSLinksetConstraint.RestoreBodyDependencies,restoreSingleChild,rID={1},rBody={2},cID={3},cBody={4}", LinksetRoot.LocalID, LinksetRoot.LocalID, LinksetRoot.BSBody.ptr.ToString("X"), child.LocalID, child.BSBody.ptr.ToString("X")); @@ -178,6 +175,7 @@ public sealed class BSLinksetConstraints : BSLinkset PhysicallyLinkAChildToRoot(rootx, childx); m_taintChildren.Add(child); }); + Refresh(LinksetRoot); } return; } @@ -211,9 +209,9 @@ public sealed class BSLinksetConstraints : BSLinkset { m_taintChildren.Remove(child); PhysicallyUnlinkAChildFromRoot(rootx, childx); - RecomputeLinksetConstraintVariables(); }); - + // See that the linkset parameters are recomputed at the end of the taint time. + Refresh(LinksetRoot); } else { @@ -237,7 +235,7 @@ public sealed class BSLinksetConstraints : BSLinkset // real world coordinate of midpoint between the two objects OMV.Vector3 midPoint = rootPrim.Position + (childRelativePosition / 2); - DetailLog("{0},BSLinkset.PhysicallyLinkAChildToRoot,taint,root={1},rBody={2},child={3},cBody={4},rLoc={5},cLoc={6},midLoc={7}", + DetailLog("{0},BSLinksetConstraint.PhysicallyLinkAChildToRoot,taint,root={1},rBody={2},child={3},cBody={4},rLoc={5},cLoc={6},midLoc={7}", rootPrim.LocalID, rootPrim.LocalID, rootPrim.BSBody.ptr.ToString("X"), childPrim.LocalID, childPrim.BSBody.ptr.ToString("X"), @@ -248,6 +246,7 @@ public sealed class BSLinksetConstraints : BSLinkset BSConstraint6Dof constrain = new BSConstraint6Dof( PhysicsScene.World, rootPrim.BSBody, childPrim.BSBody, midPoint, true, true ); + // PhysicsScene.World, childPrim.BSBody, rootPrim.BSBody, midPoint, true, true ); /* NOTE: below is an attempt to build constraint with full frame computation, etc. * Using the midpoint is easier since it lets the Bullet code manipulate the transforms @@ -264,7 +263,7 @@ public sealed class BSLinksetConstraints : BSLinkset // create a constraint that allows no freedom of movement between the two objects // http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818 - DetailLog("{0},BSLinkset.PhysicallyLinkAChildToRoot,taint,root={1},child={2}", rootPrim.LocalID, rootPrim.LocalID, childPrim.LocalID); + DetailLog("{0},BSLinksetConstraint.PhysicallyLinkAChildToRoot,taint,root={1},child={2}", rootPrim.LocalID, rootPrim.LocalID, childPrim.LocalID); BS6DofConstraint constrain = new BS6DofConstraint( PhysicsScene.World, rootPrim.Body, childPrim.Body, OMV.Vector3.Zero, @@ -307,7 +306,7 @@ public sealed class BSLinksetConstraints : BSLinkset private bool PhysicallyUnlinkAChildFromRoot(BSPhysObject rootPrim, BSPhysObject childPrim) { bool ret = false; - DetailLog("{0},BSLinkset.PhysicallyUnlinkAChildFromRoot,taint,root={1},rBody={2},child={3},cBody={4}", + DetailLog("{0},BSLinksetConstraint.PhysicallyUnlinkAChildFromRoot,taint,root={1},rBody={2},child={3},cBody={4}", rootPrim.LocalID, rootPrim.LocalID, rootPrim.BSBody.ptr.ToString("X"), childPrim.LocalID, childPrim.BSBody.ptr.ToString("X")); @@ -327,7 +326,7 @@ public sealed class BSLinksetConstraints : BSLinkset // Called at taint time! private bool PhysicallyUnlinkAllChildrenFromRoot(BSPhysObject rootPrim) { - DetailLog("{0},BSLinkset.PhysicallyUnlinkAllChildren,taint", rootPrim.LocalID); + DetailLog("{0},BSLinksetConstraint.PhysicallyUnlinkAllChildren,taint", rootPrim.LocalID); bool ret = false; if (PhysicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.BSBody)) @@ -350,7 +349,7 @@ public sealed class BSLinksetConstraints : BSLinkset BSConstraint constrain; if (PhysicsScene.Constraints.TryGetConstraint(LinksetRoot.BSBody, child.BSBody, out constrain)) { - // DetailLog("{0},BSLinkset.RecomputeLinksetConstraintVariables,taint,child={1},mass={2},A={3},B={4}", + // DetailLog("{0},BSLinksetConstraint.RecomputeLinksetConstraintVariables,taint,child={1},mass={2},A={3},B={4}", // LinksetRoot.LocalID, child.LocalID, linksetMass, constrain.Body1.ID, constrain.Body2.ID); constrain.RecomputeConstraintVariables(linksetMass); } @@ -367,15 +366,23 @@ public sealed class BSLinksetConstraints : BSLinkset { // If this is a multiple object linkset, set everybody's center of mass to the set's center of mass OMV.Vector3 centerOfMass = ComputeLinksetCenterOfMass(); - BulletSimAPI.SetCenterOfMassByPosRot2(LinksetRoot.BSBody.ptr, - centerOfMass, OMV.Quaternion.Identity); - DetailLog("{0},BSLinkset.RecomputeLinksetConstraintVariables,setCenterOfMass,COM={1},rBody={2}", - LinksetRoot.LocalID, centerOfMass, LinksetRoot.BSBody.ptr.ToString("X")); + BulletSimAPI.SetCenterOfMassByPosRot2(LinksetRoot.BSBody.ptr, centerOfMass, OMV.Quaternion.Identity); + // BulletSimAPI.SetCollisionFilterMask2(LinksetRoot.BSBody.ptr, + // (uint)CollisionFilterGroups.LinksetFilter, (uint)CollisionFilterGroups.LinksetMask); + DetailLog("{0},BSLinksetConstraint.RecomputeLinksetConstraintVariables,setCenterOfMass,COM={1},rBody={2},linksetMass={3}", + LinksetRoot.LocalID, centerOfMass, LinksetRoot.BSBody.ptr.ToString("X"), linksetMass); foreach (BSPhysObject child in m_taintChildren) { - BulletSimAPI.SetCenterOfMassByPosRot2(child.BSBody.ptr, - centerOfMass, OMV.Quaternion.Identity); + BulletSimAPI.SetCenterOfMassByPosRot2(child.BSBody.ptr, centerOfMass, OMV.Quaternion.Identity); + // A child in the linkset physically shows the mass of the whole linkset. + // This allows Bullet to apply enough force on the child to move the whole linkset. + child.UpdatePhysicalMassProperties(linksetMass); + // DEBUG: see of inter-linkset collisions are causing problems + // BulletSimAPI.SetCollisionFilterMask2(child.BSBody.ptr, + // (uint)CollisionFilterGroups.LinksetFilter, (uint)CollisionFilterGroups.LinksetMask); } + // Also update the root's physical mass to the whole linkset + LinksetRoot.UpdatePhysicalMassProperties(linksetMass); // BulletSimAPI.DumpAllInfo2(PhysicsScene.World.ptr); // DEBUG DEBUG DEBUG } -- cgit v1.1 From bc43c7007d3d8ffc2f497a6d37004eb3d3544e00 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Mon, 29 Oct 2012 14:27:48 -0700 Subject: BulletSim: code rearrangement --- OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs | 12 ++++++------ .../Region/Physics/BulletSPlugin/BSConstraintCollection.cs | 2 -- 2 files changed, 6 insertions(+), 8 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs b/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs index f017cdd..65fac00 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs @@ -42,6 +42,12 @@ public abstract class BSConstraint : IDisposable protected BulletConstraint m_constraint; protected bool m_enabled = false; + public BulletBody Body1 { get { return m_body1; } } + public BulletBody Body2 { get { return m_body2; } } + public BulletConstraint Constraint { get { return m_constraint; } } + public abstract ConstraintType Type { get; } + public bool IsEnabled { get { return m_enabled; } } + public BSConstraint() { } @@ -64,12 +70,6 @@ public abstract class BSConstraint : IDisposable } } - public BulletBody Body1 { get { return m_body1; } } - public BulletBody Body2 { get { return m_body2; } } - public BulletConstraint Constraint { get { return m_constraint; } } - public abstract ConstraintType Type { get; } - - public virtual bool SetLinearLimits(Vector3 low, Vector3 high) { bool ret = false; diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSConstraintCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSConstraintCollection.cs index b9add06..a9fd826 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSConstraintCollection.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSConstraintCollection.cs @@ -143,8 +143,6 @@ public sealed class BSConstraintCollection : IDisposable // Return 'true' if any constraints were destroyed. public bool RemoveAndDestroyConstraint(BulletBody body1) { - // return BulletSimAPI.RemoveConstraintByID(m_world.ID, obj.ID); - List toRemove = new List(); uint lookingID = body1.ID; lock (m_constraints) -- cgit v1.1 From 4cfa3be4efbca49e4670b92ec2c110f65f658b8e Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Mon, 29 Oct 2012 14:28:24 -0700 Subject: BulletSim: add definitions for linkset collision mask --- OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs | 3 +++ 1 file changed, 3 insertions(+) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs index be3a5ad..9b7ba03 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs @@ -378,6 +378,7 @@ public enum CollisionFilterGroups : uint BTerrainFilter = 1 << 11, BRaycastFilter = 1 << 12, BSolidFilter = 1 << 13, + BLinksetFilter = 1 << 14, // The collsion filters and masked are defined in one place -- don't want them scattered AvatarFilter = BCharacterFilter, @@ -386,6 +387,8 @@ public enum CollisionFilterGroups : uint ObjectMask = BAllFilter, StaticObjectFilter = BStaticFilter, StaticObjectMask = BAllFilter, + LinksetFilter = BLinksetFilter, + LinksetMask = BAllFilter & ~BLinksetFilter, VolumeDetectFilter = BSensorTrigger, VolumeDetectMask = ~BSensorTrigger, TerrainFilter = BTerrainFilter, -- cgit v1.1 From dae038a117c3110970d6fe0b743e20f342df2269 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Mon, 29 Oct 2012 14:30:16 -0700 Subject: BulletSim: fix problem with multiple linksets stepping on each other if they are built at the same time. --- OpenSim/Region/Physics/BulletSPlugin/BSScene.cs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs index cb52937..c27b5f0 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs @@ -578,12 +578,12 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters } } + ProcessPostStepTaints(); + // This causes the unmanaged code to output ALL the values found in ALL the objects in the world. // Only enable this in a limited test world with few objects. // BulletSimAPI.DumpAllInfo2(World.ptr); // DEBUG DEBUG DEBUG - ProcessPostStepTaints(); - // The physics engine returns the number of milliseconds it simulated this call. // These are summed and normalized to one second and divided by 1000 to give the reported physics FPS. // We multiply by 55 to give a recognizable running rate (55 or less). @@ -766,9 +766,10 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters { if (!m_initialized) return; + string uniqueIdent = ident + "-" + ID.ToString(); lock (_taintLock) { - _postTaintOperations[ident] = new TaintCallbackEntry(ident + "-" + ID.ToString(), callback); + _postTaintOperations[uniqueIdent] = new TaintCallbackEntry(uniqueIdent, callback); } return; -- cgit v1.1 From 42d65840c843f2cac6f02fc1b6012140c9cb240e Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Mon, 29 Oct 2012 14:32:07 -0700 Subject: BulletSim: Add gravity force to vehicle. Some debugging additions. --- OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs index 8bd8117..4981007 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs @@ -539,6 +539,8 @@ namespace OpenSim.Region.Physics.BulletSPlugin { if (!IsActive) return; + m_lastAngularVelocity = Prim.ForceRotationalVelocity; // DEBUG: account for what Bullet did last time + MoveLinear(pTimestep); MoveAngular(pTimestep); LimitRotation(pTimestep); @@ -558,7 +560,8 @@ namespace OpenSim.Region.Physics.BulletSPlugin Prim.ForceOrientation = newOrientation; } */ - BulletSimAPI.SetInterpolationVelocity2(Prim.BSBody.ptr, m_newVelocity, m_lastAngularVelocity); + // DEBUG: Trying to figure out why Bullet goes crazy when the root prim is moved. + BulletSimAPI.SetInterpolationVelocity2(Prim.BSBody.ptr, m_newVelocity, m_lastAngularVelocity); // DEBUG DEBUG DEBUG // remember the position so next step we can limit absolute movement effects m_lastPositionVector = Prim.ForcePosition; @@ -762,13 +765,14 @@ namespace OpenSim.Region.Physics.BulletSPlugin // Apply velocity Prim.ForceVelocity = m_newVelocity; // Prim.AddForce(m_newVelocity * Prim.Linkset.LinksetMass, false); - // Prim.AddForce(grav * Prim.Linkset.LinksetMass, false); + Prim.AddForce(grav * Prim.Linkset.LinksetMass, false); VDetailLog("{0},MoveLinear,done,lmDir={1},lmVel={2},newVel={3},grav={4}", Prim.LocalID, m_linearMotorDirection, m_lastLinearVelocityVector, m_newVelocity, grav); } // end MoveLinear() + // ======================================================================= // Apply the effect of the angular motor. private void MoveAngular(float pTimestep) { -- cgit v1.1 From 93fe384cce42e91337f446fd658ef29ca3d9f733 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Mon, 29 Oct 2012 14:33:31 -0700 Subject: BulletSim: Use the PostTaints operation to build the linkset once before the next simulation step. This eliminates the management of children vs taintChildren and simplifies the constratin creation code. --- OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs | 52 +++----- .../Physics/BulletSPlugin/BSLinksetConstraints.cs | 140 +++++++-------------- 2 files changed, 68 insertions(+), 124 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs index 569d2e7..187951e 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs @@ -61,16 +61,7 @@ public abstract class BSLinkset public int LinksetID { get; private set; } // The children under the root in this linkset. - // There are two lists of children: the current children at runtime - // and the children at taint-time. For instance, if you delink a - // child from the linkset, the child is removed from m_children - // but the constraint won't be removed until taint time. - // Two lists lets this track the 'current' children and - // the physical 'taint' children separately. - // After taint processing and before the simulation step, these - // two lists must be the same. protected HashSet m_children; - protected HashSet m_taintChildren; // We lock the diddling of linkset classes to prevent any badness. // This locks the modification of the instances of this class. Changes @@ -110,7 +101,6 @@ public abstract class BSLinkset PhysicsScene = scene; LinksetRoot = parent; m_children = new HashSet(); - m_taintChildren = new HashSet(); m_mass = parent.MassRaw; } @@ -192,7 +182,7 @@ public abstract class BSLinkset lock (m_linksetActivityLock) { action(LinksetRoot); - foreach (BSPhysObject po in m_taintChildren) + foreach (BSPhysObject po in m_children) { if (action(po)) break; @@ -201,9 +191,24 @@ public abstract class BSLinkset return ret; } + // I am the root of a linkset and a new child is being added + // Called while LinkActivity is locked. + protected abstract void AddChildToLinkset(BSPhysObject child); + + // Forcefully removing a child from a linkset. + // This is not being called by the child so we have to make sure the child doesn't think + // it's still connected to the linkset. + // Normal OpenSimulator operation will never do this because other SceneObjectPart information + // also has to be updated (like pointer to prim's parent). + protected abstract void RemoveChildFromOtherLinkset(BSPhysObject pchild); + + // I am the root of a linkset and one of my children is being removed. + // Safe to call even if the child is not really in my linkset. + protected abstract void RemoveChildFromLinkset(BSPhysObject child); + // When physical properties are changed the linkset needs to recalculate // its internal properties. - // May be called at runtime or taint-time (just pass the appropriate flag). + // May be called at runtime or taint-time. public abstract void Refresh(BSPhysObject requestor); // The object is going dynamic (physical). Do any setup necessary @@ -238,8 +243,6 @@ public abstract class BSLinkset public abstract void RestoreBodyDependencies(BSPrim child); // ================================================================ - // Below this point is internal magic - protected virtual float ComputeLinksetMass() { float mass = LinksetRoot.MassRaw; @@ -264,7 +267,7 @@ public abstract class BSLinkset com = LinksetRoot.Position * LinksetRoot.MassRaw; float totalMass = LinksetRoot.MassRaw; - foreach (BSPhysObject bp in m_taintChildren) + foreach (BSPhysObject bp in m_children) { com += bp.Position * bp.MassRaw; totalMass += bp.MassRaw; @@ -283,31 +286,16 @@ public abstract class BSLinkset { com = LinksetRoot.Position; - foreach (BSPhysObject bp in m_taintChildren) + foreach (BSPhysObject bp in m_children) { com += bp.Position * bp.MassRaw; } - com /= (m_taintChildren.Count + 1); + com /= (m_children.Count + 1); } return com; } - // I am the root of a linkset and a new child is being added - // Called while LinkActivity is locked. - protected abstract void AddChildToLinkset(BSPhysObject child); - - // Forcefully removing a child from a linkset. - // This is not being called by the child so we have to make sure the child doesn't think - // it's still connected to the linkset. - // Normal OpenSimulator operation will never do this because other SceneObjectPart information - // also has to be updated (like pointer to prim's parent). - protected abstract void RemoveChildFromOtherLinkset(BSPhysObject pchild); - - // I am the root of a linkset and one of my children is being removed. - // Safe to call even if the child is not really in my linkset. - protected abstract void RemoveChildFromLinkset(BSPhysObject child); - // Invoke the detailed logger and output something if it's enabled. protected void DetailLog(string msg, params Object[] args) { diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs index 086aa12..6c1fa2a 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs @@ -54,7 +54,7 @@ public sealed class BSLinksetConstraints : BSLinkset // Queue to happen after all the other taint processing PhysicsScene.PostTaintObject("BSLinksetContraints.Refresh", requestor.LocalID, delegate() { - RecomputeLinksetConstraintVariables(); + RecomputeLinksetConstraints(); }); } @@ -98,24 +98,13 @@ public sealed class BSLinksetConstraints : BSLinkset lock (m_linksetActivityLock) { - if (IsRoot(child)) - { - // If the one with the dependency is root, must undo all children - DetailLog("{0},BSLinksetConstraint.RemoveBodyDependencies,removeChildrenForRoot,rID={1},rBody={2}", - child.LocalID, LinksetRoot.LocalID, LinksetRoot.BSBody.ptr.ToString("X")); + // Just undo all the constraints for this linkset. Rebuild at the end of the step. + DetailLog("{0},BSLinksetConstraint.RemoveBodyDependencies,removeChildrenForRoot,rID={1},rBody={2}", + child.LocalID, LinksetRoot.LocalID, LinksetRoot.BSBody.ptr.ToString("X")); - ret = PhysicallyUnlinkAllChildrenFromRoot(LinksetRoot); - } - else - { - DetailLog("{0},BSLinksetConstraint.RemoveBodyDependencies,removeSingleChild,rID={1},rBody={2},cID={3},cBody={4}", - child.LocalID, - LinksetRoot.LocalID, LinksetRoot.BSBody.ptr.ToString("X"), - child.LocalID, child.BSBody.ptr.ToString("X")); - // ret = PhysicallyUnlinkAChildFromRoot(LinksetRoot, child); - // Despite the function name, this removes any link to the specified object. - ret = PhysicallyUnlinkAllChildrenFromRoot(child); - } + ret = PhysicallyUnlinkAllChildrenFromRoot(LinksetRoot); + // Cause the constraints, et al to be rebuilt before the next simulation step. + Refresh(LinksetRoot); } return ret; } @@ -125,26 +114,7 @@ public sealed class BSLinksetConstraints : BSLinkset // Called at taint-time!! public override void RestoreBodyDependencies(BSPrim child) { - lock (m_linksetActivityLock) - { - if (IsRoot(child)) - { - DetailLog("{0},BSLinksetConstraint.RestoreBodyDependencies,restoreChildrenForRoot,rID={1},numChild={2}", - child.LocalID, LinksetRoot.LocalID, m_taintChildren.Count); - foreach (BSPhysObject bpo in m_taintChildren) - { - PhysicallyLinkAChildToRoot(LinksetRoot, bpo); - } - } - else - { - DetailLog("{0},BSLinksetConstraint.RestoreBodyDependencies,restoreSingleChild,rID={1},rBody={2},cID={3},cBody={4}", - LinksetRoot.LocalID, - LinksetRoot.LocalID, LinksetRoot.BSBody.ptr.ToString("X"), - child.LocalID, child.BSBody.ptr.ToString("X")); - PhysicallyLinkAChildToRoot(LinksetRoot, child); - } - } + // The Refresh operation will build any missing constraints. } // ================================================================ @@ -163,18 +133,7 @@ public sealed class BSLinksetConstraints : BSLinkset DetailLog("{0},AddChildToLinkset,call,child={1}", LinksetRoot.LocalID, child.LocalID); - PhysicsScene.TaintedObject("AddChildToLinkset", delegate() - { - DetailLog("{0},AddChildToLinkset,taint,rID={1},rBody={2},cID={3},cBody={4}", - rootx.LocalID, - rootx.LocalID, rootx.BSBody.ptr.ToString("X"), - childx.LocalID, childx.BSBody.ptr.ToString("X")); - // Since this is taint-time, the body and shape could have changed for the child - rootx.ForcePosition = rootx.Position; // DEBUG - childx.ForcePosition = childx.Position; // DEBUG - PhysicallyLinkAChildToRoot(rootx, childx); - m_taintChildren.Add(child); - }); + // Cause constraints and assorted properties to be recomputed before the next simulation step. Refresh(LinksetRoot); } return; @@ -207,7 +166,6 @@ public sealed class BSLinksetConstraints : BSLinkset PhysicsScene.TaintedObject("RemoveChildFromLinkset", delegate() { - m_taintChildren.Remove(child); PhysicallyUnlinkAChildFromRoot(rootx, childx); }); // See that the linkset parameters are recomputed at the end of the taint time. @@ -225,6 +183,12 @@ public sealed class BSLinksetConstraints : BSLinkset // Called at taint time! private void PhysicallyLinkAChildToRoot(BSPhysObject rootPrim, BSPhysObject childPrim) { + // Don't build the constraint when asked. Put it off until just before the simulation step. + Refresh(rootPrim); + } + + private BSConstraint BuildConstraint(BSPhysObject rootPrim, BSPhysObject childPrim) + { // Zero motion for children so they don't interpolate childPrim.ZeroMotion(); @@ -235,7 +199,7 @@ public sealed class BSLinksetConstraints : BSLinkset // real world coordinate of midpoint between the two objects OMV.Vector3 midPoint = rootPrim.Position + (childRelativePosition / 2); - DetailLog("{0},BSLinksetConstraint.PhysicallyLinkAChildToRoot,taint,root={1},rBody={2},child={3},cBody={4},rLoc={5},cLoc={6},midLoc={7}", + DetailLog("{0},BSLinksetConstraint.BuildConstraint,taint,root={1},rBody={2},child={3},cBody={4},rLoc={5},cLoc={6},midLoc={7}", rootPrim.LocalID, rootPrim.LocalID, rootPrim.BSBody.ptr.ToString("X"), childPrim.LocalID, childPrim.BSBody.ptr.ToString("X"), @@ -297,6 +261,7 @@ public sealed class BSLinksetConstraints : BSLinkset { constrain.SetSolverIterations(PhysicsScene.Params.linkConstraintSolverIterations); } + return constrain; } // Remove linkage between myself and a particular child @@ -337,56 +302,47 @@ public sealed class BSLinksetConstraints : BSLinkset } // Call each of the constraints that make up this linkset and recompute the - // various transforms and variables. Used when objects are added or removed - // from a linkset to make sure the constraints know about the new mass and - // geometry. + // various transforms and variables. Create constraints of not created yet. + // Called before the simulation step to make sure the constraint based linkset + // is all initialized. // Must only be called at taint time!! - private void RecomputeLinksetConstraintVariables() + private void RecomputeLinksetConstraints() { float linksetMass = LinksetMass; - foreach (BSPhysObject child in m_taintChildren) + LinksetRoot.UpdatePhysicalMassProperties(linksetMass); + + // For a multiple object linkset, set everybody's center of mass to the set's center of mass + OMV.Vector3 centerOfMass = ComputeLinksetCenterOfMass(); + BulletSimAPI.SetCenterOfMassByPosRot2(LinksetRoot.BSBody.ptr, centerOfMass, OMV.Quaternion.Identity); + + // BulletSimAPI.SetCollisionFilterMask2(LinksetRoot.BSBody.ptr, + // (uint)CollisionFilterGroups.LinksetFilter, (uint)CollisionFilterGroups.LinksetMask); + DetailLog("{0},BSLinksetConstraint.RecomputeLinksetConstraints,setCenterOfMass,COM={1},rBody={2},linksetMass={3}", + LinksetRoot.LocalID, centerOfMass, LinksetRoot.BSBody.ptr.ToString("X"), linksetMass); + + foreach (BSPhysObject child in m_children) { + // A child in the linkset physically shows the mass of the whole linkset. + // This allows Bullet to apply enough force on the child to move the whole linkset. + // (Also do the mass stuff before recomputing the constraint so mass is not zero.) + BulletSimAPI.SetCenterOfMassByPosRot2(child.BSBody.ptr, centerOfMass, OMV.Quaternion.Identity); + child.UpdatePhysicalMassProperties(linksetMass); + BSConstraint constrain; - if (PhysicsScene.Constraints.TryGetConstraint(LinksetRoot.BSBody, child.BSBody, out constrain)) - { - // DetailLog("{0},BSLinksetConstraint.RecomputeLinksetConstraintVariables,taint,child={1},mass={2},A={3},B={4}", - // LinksetRoot.LocalID, child.LocalID, linksetMass, constrain.Body1.ID, constrain.Body2.ID); - constrain.RecomputeConstraintVariables(linksetMass); - } - else + if (!PhysicsScene.Constraints.TryGetConstraint(LinksetRoot.BSBody, child.BSBody, out constrain)) { - // Non-fatal error that happens when children are being added to the linkset but - // their constraints have not been created yet. - break; + // If constraint doesn't exist yet, create it. + constrain = BuildConstraint(LinksetRoot, child); } - } + constrain.RecomputeConstraintVariables(linksetMass); - // If the whole linkset is not here, doesn't make sense to recompute linkset wide values - if (m_children.Count == m_taintChildren.Count) - { - // If this is a multiple object linkset, set everybody's center of mass to the set's center of mass - OMV.Vector3 centerOfMass = ComputeLinksetCenterOfMass(); - BulletSimAPI.SetCenterOfMassByPosRot2(LinksetRoot.BSBody.ptr, centerOfMass, OMV.Quaternion.Identity); - // BulletSimAPI.SetCollisionFilterMask2(LinksetRoot.BSBody.ptr, - // (uint)CollisionFilterGroups.LinksetFilter, (uint)CollisionFilterGroups.LinksetMask); - DetailLog("{0},BSLinksetConstraint.RecomputeLinksetConstraintVariables,setCenterOfMass,COM={1},rBody={2},linksetMass={3}", - LinksetRoot.LocalID, centerOfMass, LinksetRoot.BSBody.ptr.ToString("X"), linksetMass); - foreach (BSPhysObject child in m_taintChildren) - { - BulletSimAPI.SetCenterOfMassByPosRot2(child.BSBody.ptr, centerOfMass, OMV.Quaternion.Identity); - // A child in the linkset physically shows the mass of the whole linkset. - // This allows Bullet to apply enough force on the child to move the whole linkset. - child.UpdatePhysicalMassProperties(linksetMass); - // DEBUG: see of inter-linkset collisions are causing problems - // BulletSimAPI.SetCollisionFilterMask2(child.BSBody.ptr, - // (uint)CollisionFilterGroups.LinksetFilter, (uint)CollisionFilterGroups.LinksetMask); - } - // Also update the root's physical mass to the whole linkset - LinksetRoot.UpdatePhysicalMassProperties(linksetMass); + // DEBUG: see of inter-linkset collisions are causing problems + // BulletSimAPI.SetCollisionFilterMask2(child.BSBody.ptr, + // (uint)CollisionFilterGroups.LinksetFilter, (uint)CollisionFilterGroups.LinksetMask); - // BulletSimAPI.DumpAllInfo2(PhysicsScene.World.ptr); // DEBUG DEBUG DEBUG + // BulletSimAPI.DumpConstraint2(PhysicsScene.World.ptr, constrain.Constraint.ptr); // DEBUG DEBUG } - return; + } } } -- cgit v1.1 From 52be581f71b3c8da6113e4f4b193694683e6f8cc Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Tue, 30 Oct 2012 09:12:07 -0700 Subject: BulletSim: remove center-of-mass setting for linksets because it causes the constraint calculation to pull the objects together. --- .../Physics/BulletSPlugin/BSConstraint6Dof.cs | 3 +- OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs | 1 - .../Physics/BulletSPlugin/BSLinksetConstraints.cs | 79 ++++++++-------------- OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | 2 +- .../Physics/BulletSPlugin/BSShapeCollection.cs | 2 +- 5 files changed, 33 insertions(+), 54 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSConstraint6Dof.cs b/OpenSim/Region/Physics/BulletSPlugin/BSConstraint6Dof.cs index 3c37d76..23ef052 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSConstraint6Dof.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSConstraint6Dof.cs @@ -71,8 +71,7 @@ public sealed class BSConstraint6Dof : BSConstraint BSScene.DetailLogZero, world.worldID, obj1.ID, obj1.ptr.ToString("X"), obj2.ID, obj2.ptr.ToString("X")); world.physicsScene.Logger.ErrorFormat("{0} Attempt to build 6DOF constraint with missing bodies: wID={1}, rID={2}, rBody={3}, cID={4}, cBody={5}", - "[BULLETSIM 6DOF CONSTRAINT]", world.worldID, - obj1.ID, obj1.ptr.ToString("X"), obj2.ID, obj2.ptr.ToString("X")); + LogHeader, world.worldID, obj1.ID, obj1.ptr.ToString("X"), obj2.ID, obj2.ptr.ToString("X")); m_enabled = false; } else diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs index 187951e..6d84fcc 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs @@ -132,7 +132,6 @@ public abstract class BSLinkset // Cannot remove the root from a linkset. return this; } - RemoveChildFromLinkset(child); } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs index 6c1fa2a..ecb6ad4 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs @@ -43,20 +43,16 @@ public sealed class BSLinksetConstraints : BSLinkset // When physical properties are changed the linkset needs to recalculate // its internal properties. - // This is queued in such a way that the - // refresh will only happen once after all the other taints are applied. + // This is queued in the 'post taint' queue so the + // refresh will happen once after all the other taints are applied. public override void Refresh(BSPhysObject requestor) { - // If there are no children, there are no constraints to recompute. - if (!HasAnyChildren) - return; - // Queue to happen after all the other taint processing PhysicsScene.PostTaintObject("BSLinksetContraints.Refresh", requestor.LocalID, delegate() { - RecomputeLinksetConstraints(); + if (HasAnyChildren && IsRoot(requestor)) + RecomputeLinksetConstraints(); }); - } // The object is going dynamic (physical). Do any setup necessary @@ -71,9 +67,10 @@ public sealed class BSLinksetConstraints : BSLinkset return false; } - // The object is going static (non-physical). Do any setup necessary - // for a static linkset. + // The object is going static (non-physical). Do any setup necessary for a static linkset. // Return 'true' if any properties updated on the passed object. + // This doesn't normally happen -- OpenSim removes the objects from the physical + // world if it is a static linkset. // Called at taint-time! public override bool MakeStatic(BSPhysObject child) { @@ -87,21 +84,21 @@ public sealed class BSLinksetConstraints : BSLinkset // Nothing to do for constraints on property updates } - // Routine used when rebuilding the body of the root of the linkset - // Destroy all the constraints have have been made to root. - // This is called when the root body is changing. - // Returns 'true' of something eas actually removed and would need restoring + // Routine called when rebuilding the body of some member of the linkset. + // Destroy all the constraints have have been made to root and set + // up to rebuild the constraints before the next simulation step. + // Returns 'true' of something was actually removed and would need restoring // Called at taint-time!! public override bool RemoveBodyDependencies(BSPrim child) { bool ret = false; + DetailLog("{0},BSLinksetConstraint.RemoveBodyDependencies,removeChildrenForRoot,rID={1},rBody={2}", + child.LocalID, LinksetRoot.LocalID, LinksetRoot.BSBody.ptr.ToString("X")); + lock (m_linksetActivityLock) { // Just undo all the constraints for this linkset. Rebuild at the end of the step. - DetailLog("{0},BSLinksetConstraint.RemoveBodyDependencies,removeChildrenForRoot,rID={1},rBody={2}", - child.LocalID, LinksetRoot.LocalID, LinksetRoot.BSBody.ptr.ToString("X")); - ret = PhysicallyUnlinkAllChildrenFromRoot(LinksetRoot); // Cause the constraints, et al to be rebuilt before the next simulation step. Refresh(LinksetRoot); @@ -114,13 +111,12 @@ public sealed class BSLinksetConstraints : BSLinkset // Called at taint-time!! public override void RestoreBodyDependencies(BSPrim child) { - // The Refresh operation will build any missing constraints. + // The Refresh operation queued by RemoveBodyDependencies() will build any missing constraints. } // ================================================================ - // Below this point is internal magic - // I am the root of a linkset and a new child is being added + // Add a new child to the linkset. // Called while LinkActivity is locked. protected override void AddChildToLinkset(BSPhysObject child) { @@ -131,7 +127,7 @@ public sealed class BSLinksetConstraints : BSLinkset BSPhysObject rootx = LinksetRoot; // capture the root as of now BSPhysObject childx = child; - DetailLog("{0},AddChildToLinkset,call,child={1}", LinksetRoot.LocalID, child.LocalID); + DetailLog("{0},BSLinksetConstraints.AddChildToLinkset,call,child={1}", LinksetRoot.LocalID, child.LocalID); // Cause constraints and assorted properties to be recomputed before the next simulation step. Refresh(LinksetRoot); @@ -150,7 +146,7 @@ public sealed class BSLinksetConstraints : BSLinkset RemoveChildFromLinkset(pchild); } - // I am the root of a linkset and one of my children is being removed. + // Remove the specified child from the linkset. // Safe to call even if the child is not really in my linkset. protected override void RemoveChildFromLinkset(BSPhysObject child) { @@ -159,12 +155,12 @@ public sealed class BSLinksetConstraints : BSLinkset BSPhysObject rootx = LinksetRoot; // capture the root and body as of now BSPhysObject childx = child; - DetailLog("{0},RemoveChildFromLinkset,call,rID={1},rBody={2},cID={3},cBody={4}", + DetailLog("{0},BSLinksetConstraints.RemoveChildFromLinkset,call,rID={1},rBody={2},cID={3},cBody={4}", childx.LocalID, rootx.LocalID, rootx.BSBody.ptr.ToString("X"), childx.LocalID, childx.BSBody.ptr.ToString("X")); - PhysicsScene.TaintedObject("RemoveChildFromLinkset", delegate() + PhysicsScene.TaintedObject("BSLinksetConstraints.RemoveChildFromLinkset", delegate() { PhysicallyUnlinkAChildFromRoot(rootx, childx); }); @@ -173,7 +169,7 @@ public sealed class BSLinksetConstraints : BSLinkset } else { - // This will happen if we remove the root of the linkset first. Non-fatal occurance. + // Non-fatal occurance. // PhysicsScene.Logger.ErrorFormat("{0}: Asked to remove child from linkset that was not in linkset", LogHeader); } return; @@ -215,7 +211,7 @@ public sealed class BSLinksetConstraints : BSLinkset /* NOTE: below is an attempt to build constraint with full frame computation, etc. * Using the midpoint is easier since it lets the Bullet code manipulate the transforms * of the objects. - * Code left as a warning to future programmers. + * Code left for future programmers. // ================================================================================== // relative position normalized to the root prim OMV.Quaternion invThisOrientation = OMV.Quaternion.Inverse(rootPrim.Orientation); @@ -225,8 +221,6 @@ public sealed class BSLinksetConstraints : BSLinkset OMV.Quaternion childRelativeRotation = invThisOrientation * childPrim.Orientation; OMV.Quaternion inverseChildRelativeRotation = OMV.Quaternion.Inverse(childRelativeRotation); - // create a constraint that allows no freedom of movement between the two objects - // http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818 DetailLog("{0},BSLinksetConstraint.PhysicallyLinkAChildToRoot,taint,root={1},child={2}", rootPrim.LocalID, rootPrim.LocalID, childPrim.LocalID); BS6DofConstraint constrain = new BS6DofConstraint( PhysicsScene.World, rootPrim.Body, childPrim.Body, @@ -234,11 +228,6 @@ public sealed class BSLinksetConstraints : BSLinkset OMV.Quaternion.Inverse(rootPrim.Orientation), OMV.Vector3.Zero, OMV.Quaternion.Inverse(childPrim.Orientation), - // A point half way between the parent and child - // childRelativePosition/2, - // childRelativeRotation, - // childRelativePosition/2, - // inverseChildRelativeRotation, true, true ); @@ -264,9 +253,9 @@ public sealed class BSLinksetConstraints : BSLinkset return constrain; } - // Remove linkage between myself and a particular child + // Remove linkage between the linkset root and a particular child // The root and child bodies are passed in because we need to remove the constraint between - // the bodies that were at unlink time. + // the bodies that were present at unlink time. // Called at taint time! private bool PhysicallyUnlinkAChildFromRoot(BSPhysObject rootPrim, BSPhysObject childPrim) { @@ -288,44 +277,36 @@ public sealed class BSLinksetConstraints : BSLinkset } // Remove linkage between myself and any possible children I might have. + // Returns 'true' of any constraints were destroyed. // Called at taint time! private bool PhysicallyUnlinkAllChildrenFromRoot(BSPhysObject rootPrim) { DetailLog("{0},BSLinksetConstraint.PhysicallyUnlinkAllChildren,taint", rootPrim.LocalID); - bool ret = false; - if (PhysicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.BSBody)) - { - ret = true; - } - return ret; + return PhysicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.BSBody); } // Call each of the constraints that make up this linkset and recompute the // various transforms and variables. Create constraints of not created yet. // Called before the simulation step to make sure the constraint based linkset // is all initialized. - // Must only be called at taint time!! + // Called at taint time!! private void RecomputeLinksetConstraints() { float linksetMass = LinksetMass; LinksetRoot.UpdatePhysicalMassProperties(linksetMass); - // For a multiple object linkset, set everybody's center of mass to the set's center of mass - OMV.Vector3 centerOfMass = ComputeLinksetCenterOfMass(); - BulletSimAPI.SetCenterOfMassByPosRot2(LinksetRoot.BSBody.ptr, centerOfMass, OMV.Quaternion.Identity); - + // DEBUG: see of inter-linkset collisions are causing problems // BulletSimAPI.SetCollisionFilterMask2(LinksetRoot.BSBody.ptr, // (uint)CollisionFilterGroups.LinksetFilter, (uint)CollisionFilterGroups.LinksetMask); - DetailLog("{0},BSLinksetConstraint.RecomputeLinksetConstraints,setCenterOfMass,COM={1},rBody={2},linksetMass={3}", - LinksetRoot.LocalID, centerOfMass, LinksetRoot.BSBody.ptr.ToString("X"), linksetMass); + DetailLog("{0},BSLinksetConstraint.RecomputeLinksetConstraints,setCenterOfMass,rBody={1},linksetMass={2}", + LinksetRoot.LocalID, LinksetRoot.BSBody.ptr.ToString("X"), linksetMass); foreach (BSPhysObject child in m_children) { // A child in the linkset physically shows the mass of the whole linkset. // This allows Bullet to apply enough force on the child to move the whole linkset. // (Also do the mass stuff before recomputing the constraint so mass is not zero.) - BulletSimAPI.SetCenterOfMassByPosRot2(child.BSBody.ptr, centerOfMass, OMV.Quaternion.Identity); child.UpdatePhysicalMassProperties(linksetMass); BSConstraint constrain; diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index ad09a61..7851a40 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs @@ -634,7 +634,7 @@ public sealed class BSPrim : BSPhysObject // had been automatically disabled when the mass was set to zero. Linkset.Refresh(this); - DetailLog("{0},BSPrim.UpdatePhysicalParameters,exit,static={1},solid={2},mass={3},collide={4},cf={5:X},body={6},shape={7}", + DetailLog("{0},BSPrim.UpdatePhysicalParameters,taintExit,static={1},solid={2},mass={3},collide={4},cf={5:X},body={6},shape={7}", LocalID, IsStatic, IsSolid, _mass, SubscribedEvents(), CurrentCollisionFlags, BSBody, BSShape); } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs index 1c0e6f5..1219fc0 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs @@ -109,7 +109,7 @@ public sealed class BSShapeCollection : IDisposable prim.BSShape, shapeData, bodyCallback); ret = newGeom || newBody; } - DetailLog("{0},BSShapeCollection.GetBodyAndShape,force={1},ret={2},body={3},shape={4}", + DetailLog("{0},BSShapeCollection.GetBodyAndShape,taintExit,force={1},ret={2},body={3},shape={4}", prim.LocalID, forceRebuild, ret, prim.BSBody, prim.BSShape); return ret; -- cgit v1.1 From 28e2cd3fa21835b124552dec024745f5784f6b3a Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Wed, 31 Oct 2012 09:26:58 -0700 Subject: BulletSim: vehicle tweeking. Add AddTorque() method to BSPrim. Remove some manual motor actions in computing angular force (will eventually be replaced with motor class). Remove some experimental changes. --- OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs | 136 ++++++++------------- .../Physics/BulletSPlugin/BSLinksetConstraints.cs | 2 +- OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | 45 +++++-- 3 files changed, 90 insertions(+), 93 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs index 4981007..5c61774 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs @@ -511,21 +511,6 @@ namespace OpenSim.Region.Physics.BulletSPlugin // Do any updating needed for a vehicle public void Refresh() { - /* - * Doesnt work unless BSDynamics senses and corrects for all collisions - if (IsActive) - BulletSimAPI.AddToCollisionFlags2(Prim.BSBody.ptr, CollisionFlags.CF_KINEMATIC_OBJECT); - else - BulletSimAPI.RemoveFromCollisionFlags2(Prim.BSBody.ptr, CollisionFlags.CF_KINEMATIC_OBJECT); - */ - /* - * Doesn't work because with zero inertia, Bullet will not apply any forces to the object. - if (IsActive) - { - BulletSimAPI.SetMassProps2(Prim.BSBody.ptr, Prim.MassRaw, Vector3.Zero); - BulletSimAPI.UpdateInertiaTensor2(Prim.BSBody.ptr); - } - */ if (IsActive) { // Friction effects are handled by this vehicle code @@ -539,29 +524,21 @@ namespace OpenSim.Region.Physics.BulletSPlugin { if (!IsActive) return; - m_lastAngularVelocity = Prim.ForceRotationalVelocity; // DEBUG: account for what Bullet did last time + // DEBUG + // Because Bullet does apply forces to the vehicle, our last computed + // linear and angular velocities are not what is happening now. + // Vector3 externalAngularVelocity = Prim.ForceRotationalVelocity - m_lastAngularVelocity; + // m_lastAngularVelocity += (externalAngularVelocity * 0.5f) * pTimestep; + // m_lastAngularVelocity = Prim.ForceRotationalVelocity; // DEBUG: account for what Bullet did last time + // m_lastLinearVelocityVector = Prim.ForceVelocity * Quaternion.Inverse(Prim.ForceOrientation); // DEBUG: + // END DEBUG MoveLinear(pTimestep); MoveAngular(pTimestep); LimitRotation(pTimestep); - /* Experimental - // Wonder if Bullet could handle collision penetration while this applies the forces. - // Apply the computed forces on the vehicle - Prim.ForcePosition += Prim.ForceVelocity * Prim.MassRaw * pTimestep; - - if (Prim.ForceRotationalVelocity != Vector3.Zero) - { - Quaternion newOrientation = Prim.ForceOrientation; - newOrientation.Normalize(); - Quaternion appliedRotation = new Quaternion((Prim.ForceRotationalVelocity * pTimestep), 0f); - newOrientation += (appliedRotation * newOrientation) * 0.5f; - newOrientation.Normalize(); - Prim.ForceOrientation = newOrientation; - } - */ // DEBUG: Trying to figure out why Bullet goes crazy when the root prim is moved. - BulletSimAPI.SetInterpolationVelocity2(Prim.BSBody.ptr, m_newVelocity, m_lastAngularVelocity); // DEBUG DEBUG DEBUG + // BulletSimAPI.SetInterpolationVelocity2(Prim.BSBody.ptr, m_newVelocity, m_lastAngularVelocity); // DEBUG DEBUG DEBUG // remember the position so next step we can limit absolute movement effects m_lastPositionVector = Prim.ForcePosition; @@ -583,7 +560,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin Vector3 vehicleVelocity = Prim.ForceVelocity * Quaternion.Inverse(Prim.ForceOrientation); // DEBUG // add drive to body - Vector3 addAmount = (m_linearMotorDirection - m_lastLinearVelocityVector)/(m_linearMotorTimescale / pTimestep); + Vector3 addAmount = (m_linearMotorDirection - m_lastLinearVelocityVector)/(m_linearMotorTimescale) * pTimestep; // lastLinearVelocityVector is the current body velocity vector m_lastLinearVelocityVector += addAmount; @@ -593,11 +570,12 @@ namespace OpenSim.Region.Physics.BulletSPlugin Vector3 frictionFactor = (Vector3.One / m_linearFrictionTimescale) * pTimestep; m_lastLinearVelocityVector *= (Vector3.One - frictionFactor); - VDetailLog("{0},MoveLinear,nonZero,origdir={1},origvel={2},vehVel={3},add={4},decay={5},lmDir={6},lmVel={7}", - Prim.LocalID, origDir, origVel, vehicleVelocity, addAmount, decayFactor, m_linearMotorDirection, m_lastLinearVelocityVector); - - // convert requested object velocity to object relative vector + // Rotate new object velocity from vehicle relative to world coordinates m_newVelocity = m_lastLinearVelocityVector * Prim.ForceOrientation; + + VDetailLog("{0},MoveLinear,nonZero,origdir={1},origvel={2},vehVel={3},add={4},decay={5},frict={6},lmDir={7},lmVel={8},newVel={9}", + Prim.LocalID, origDir, origVel, vehicleVelocity, addAmount, decayFactor, frictionFactor, + m_linearMotorDirection, m_lastLinearVelocityVector, m_newVelocity); } else { @@ -609,18 +587,15 @@ namespace OpenSim.Region.Physics.BulletSPlugin VDetailLog("{0},MoveLinear,zeroed", Prim.LocalID); } - // m_newVelocity is velocity computed from linear motor + // m_newVelocity is velocity computed from linear motor in world coordinates - // Add the various forces into m_dir which will be our new direction vector (velocity) - - // add Gravity and Buoyancy + // Gravity and Buoyancy // There is some gravity, make a gravity force vector that is applied after object velocity. // m_VehicleBuoyancy: -1=2g; 0=1g; 1=0g; - // Vector3 grav = Prim.PhysicsScene.DefaultGravity * (Prim.Linkset.LinksetMass * (1f - m_VehicleBuoyancy)); Vector3 grav = Prim.PhysicsScene.DefaultGravity * (1f - m_VehicleBuoyancy); /* - * RA: Not sure why one would do this + * RA: Not sure why one would do this unless we are hoping external forces are doing gravity, ... // Preserve the current Z velocity Vector3 vel_now = m_prim.Velocity; m_dir.Z = vel_now.Z; // Preserve the accumulated falling velocity @@ -676,7 +651,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin else { float verticalError = pos.Z - m_VhoverTargetHeight; - // RA: where does the 50 come from> + // RA: where does the 50 come from? float verticalCorrectionVelocity = pTimestep * ((verticalError * 50.0f) / m_VhoverTimescale); // Replace Vertical speed with correction figure if significant if (Math.Abs(verticalError) > 0.01f) @@ -784,37 +759,24 @@ namespace OpenSim.Region.Physics.BulletSPlugin // m_angularFrictionTimescale // body angular velocity decay rate // m_lastAngularVelocity // what was last applied to body - // Get what the body is doing, this includes 'external' influences - Vector3 angularVelocity = Prim.ForceRotationalVelocity; - - if (m_angularMotorApply > 0) + if (m_angularMotorDirection.LengthSquared() > 0.0001) { - // Rather than snapping the angular motor velocity from the old value to - // a newly set velocity, this routine steps the value from the previous - // value (m_angularMotorVelocity) to the requested value (m_angularMotorDirection). - // There are m_angularMotorApply steps. Vector3 origVel = m_angularMotorVelocity; Vector3 origDir = m_angularMotorDirection; - // ramp up to new value // new velocity += error / ( time to get there / step interval) // requested speed - last motor speed m_angularMotorVelocity += (m_angularMotorDirection - m_angularMotorVelocity) / (m_angularMotorTimescale / pTimestep); + // decay requested direction + m_angularMotorDirection *= (1.0f - (pTimestep * 1.0f/m_angularMotorDecayTimescale)); - VDetailLog("{0},MoveAngular,angularMotorApply,apply={1},angTScale={2},timeStep={3},origvel={4},origDir={5},vel={6}", - Prim.LocalID, m_angularMotorApply, m_angularMotorTimescale, pTimestep, origVel, origDir, m_angularMotorVelocity); - - m_angularMotorApply--; + VDetailLog("{0},MoveAngular,angularMotorApply,angTScale={1},timeStep={2},origvel={3},origDir={4},vel={5}", + Prim.LocalID, m_angularMotorTimescale, pTimestep, origVel, origDir, m_angularMotorVelocity); } else { - // No motor recently applied, keep the body velocity - // and decay the velocity - if (m_angularMotorVelocity.LengthSquared() < 0.0001) - m_angularMotorVelocity = Vector3.Zero; - else - m_angularMotorVelocity -= m_angularMotorVelocity / (m_angularMotorDecayTimescale / pTimestep); - } // end motor section + m_angularMotorVelocity = Vector3.Zero; + } #region Vertical attactor @@ -824,22 +786,19 @@ namespace OpenSim.Region.Physics.BulletSPlugin if (m_verticalAttractionTimescale < 300 && m_lastAngularVelocity != Vector3.Zero) { - float VAservo = 0.2f; + float VAservo = pTimestep * 0.2f / m_verticalAttractionTimescale; if (Prim.Linkset.LinksetIsColliding) - VAservo = 0.05f / (m_verticalAttractionTimescale / pTimestep); + VAservo = pTimestep * 0.05f / (m_verticalAttractionTimescale); VAservo *= (m_verticalAttractionEfficiency * m_verticalAttractionEfficiency); - // get present body rotation - Quaternion rotq = Prim.ForceOrientation; - // vector pointing up - Vector3 verticalError = Vector3.UnitZ; - - // rotate it to Body Angle - verticalError = verticalError * rotq; - // verticalError.X and .Y are the World error amounts. They are 0 when there is no error (Vehicle Body is 'vertical'), and .Z will be 1. - // As the body leans to its side |.X| will increase to 1 and .Z fall to 0. As body inverts |.X| will fall and .Z will go - // negative. Similar for tilt and |.Y|. .X and .Y must be modulated to prevent a stable inverted body. + // Create a vector of the vehicle "up" in world coordinates + Vector3 verticalError = Vector3.UnitZ * Prim.ForceOrientation; + // verticalError.X and .Y are the World error amounts. They are 0 when there is no + // error (Vehicle Body is 'vertical'), and .Z will be 1. As the body leans to its + // side |.X| will increase to 1 and .Z fall to 0. As body inverts |.X| will fall + // and .Z will go // negative. Similar for tilt and |.Y|. .X and .Y must be + // modulated to prevent a stable inverted body. // Error is 0 (no error) to +/- 2 (max error) if (verticalError.Z < 0.0f) @@ -850,13 +809,15 @@ namespace OpenSim.Region.Physics.BulletSPlugin // scale it by VAservo verticalError = verticalError * VAservo; - // As the body rotates around the X axis, then verticalError.Y increases; Rotated around Y then .X increases, so - // Change Body angular velocity X based on Y, and Y based on X. Z is not changed. + // As the body rotates around the X axis, then verticalError.Y increases; Rotated around Y + // then .X increases, so change Body angular velocity X based on Y, and Y based on X. + // Z is not changed. vertattr.X = verticalError.Y; vertattr.Y = - verticalError.X; vertattr.Z = 0f; // scaling appears better usingsquare-law + Vector3 angularVelocity = Prim.ForceRotationalVelocity; float bounce = 1.0f - (m_verticalAttractionEfficiency * m_verticalAttractionEfficiency); vertattr.X += bounce * angularVelocity.X; vertattr.Y += bounce * angularVelocity.Y; @@ -956,15 +917,22 @@ namespace OpenSim.Region.Physics.BulletSPlugin VDetailLog("{0},MoveAngular,zeroSmallValues,lastAngular={1}", Prim.LocalID, m_lastAngularVelocity); } - // apply friction - Vector3 decayamount = Vector3.One / (m_angularFrictionTimescale / pTimestep); - m_lastAngularVelocity -= m_lastAngularVelocity * decayamount; - // Apply to the body // The above calculates the absolute angular velocity needed - Prim.ForceRotationalVelocity = m_lastAngularVelocity; + // Prim.ForceRotationalVelocity = m_lastAngularVelocity; + + // Apply a force to overcome current angular velocity + Vector3 applyAngularForce = (m_lastAngularVelocity - Prim.ForceRotationalVelocity) * Prim.Linkset.LinksetMass; + // Vector3 applyAngularForce = (m_lastAngularVelocity - Prim.ForceRotationalVelocity); + // Prim.AddAngularForce(applyAngularForce, false); + Prim.ApplyTorqueImpulse(applyAngularForce, false); + + // Apply friction for next time + Vector3 decayamount = (Vector3.One / m_angularFrictionTimescale) * pTimestep; + m_lastAngularVelocity *= Vector3.One - decayamount; - VDetailLog("{0},MoveAngular,done,decay={1},lastAngular={2}", Prim.LocalID, decayamount, m_lastAngularVelocity); + VDetailLog("{0},MoveAngular,done,applyAForce={1},decay={2},lastAngular={3}", + Prim.LocalID, applyAngularForce, decayamount, m_lastAngularVelocity); } //end MoveAngular internal void LimitRotation(float timestep) diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs index ecb6ad4..8cdbd9b 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs @@ -299,7 +299,7 @@ public sealed class BSLinksetConstraints : BSLinkset // DEBUG: see of inter-linkset collisions are causing problems // BulletSimAPI.SetCollisionFilterMask2(LinksetRoot.BSBody.ptr, // (uint)CollisionFilterGroups.LinksetFilter, (uint)CollisionFilterGroups.LinksetMask); - DetailLog("{0},BSLinksetConstraint.RecomputeLinksetConstraints,setCenterOfMass,rBody={1},linksetMass={2}", + DetailLog("{0},BSLinksetConstraint.RecomputeLinksetConstraints,set,rBody={1},linksetMass={2}", LinksetRoot.LocalID, LinksetRoot.BSBody.ptr.ToString("X"), linksetMass); foreach (BSPhysObject child in m_children) diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index 7851a40..9ced61fa 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs @@ -378,7 +378,9 @@ public sealed class BSPrim : BSPhysObject { OMV.Vector3 localInertia = BulletSimAPI.CalculateLocalInertia2(BSShape.ptr, physMass); BulletSimAPI.SetMassProps2(BSBody.ptr, physMass, localInertia); - BulletSimAPI.UpdateInertiaTensor2(BSBody.ptr); + // center of mass is at the zero of the object + BulletSimAPI.SetCenterOfMassByPosRot2(BSBody.ptr, ForcePosition, ForceOrientation); + // BulletSimAPI.UpdateInertiaTensor2(BSBody.ptr); DetailLog("{0},BSPrim.UpdateMassProperties,mass={1},localInertia={2}", LocalID, physMass, localInertia); } } @@ -462,9 +464,16 @@ public sealed class BSPrim : BSPhysObject // Called from Scene when doing simulation step so we're in taint processing time. public override void StepVehicle(float timeStep) { - if (IsPhysical) + if (IsPhysical && _vehicle.IsActive) { _vehicle.Step(timeStep); + /* // TEST TEST DEBUG DEBUG -- trying to reduce the extra action of Bullet simulation step + PhysicsScene.PostTaintObject("BSPrim.StepVehicles", LocalID, delegate() + { + // This resets the interpolation values and recomputes the tensor variables + BulletSimAPI.SetCenterOfMassByPosRot2(BSBody.ptr, ForcePosition, ForceOrientation); + }); + */ } } @@ -502,7 +511,9 @@ public sealed class BSPrim : BSPhysObject } public override OMV.Vector3 Torque { get { return _torque; } - set { _torque = value; + set { + _torque = value; + AddAngularForce(_torque, false, false); // DetailLog("{0},BSPrim.SetTorque,call,torque={1}", LocalID, _torque); } } @@ -831,7 +842,7 @@ public sealed class BSPrim : BSPhysObject // m_log.DebugFormat("{0}: RotationalVelocity={1}", LogHeader, _rotationalVelocity); PhysicsScene.TaintedObject("BSPrim.setRotationalVelocity", delegate() { - // DetailLog("{0},BSPrim.SetRotationalVel,taint,rotvel={1}", LocalID, _rotationalVelocity); + DetailLog("{0},BSPrim.SetRotationalVel,taint,rotvel={1}", LocalID, _rotationalVelocity); BulletSimAPI.SetAngularVelocity2(BSBody.ptr, _rotationalVelocity); }); } @@ -972,14 +983,31 @@ public sealed class BSPrim : BSPhysObject } m_accumulatedAngularForces.Clear(); } - // DetailLog("{0},BSPrim.AddAngularForce,taint,aForce={1}", LocalID, fSum); + DetailLog("{0},BSPrim.AddAngularForce,taint,aForce={1}", LocalID, fSum); if (fSum != OMV.Vector3.Zero) + { BulletSimAPI.ApplyTorque2(BSBody.ptr, fSum); + _torque = fSum; + } }; if (inTaintTime) addAngularForceOperation(); else - PhysicsScene.TaintedObject("BSPrim.AddForce", addAngularForceOperation); + PhysicsScene.TaintedObject("BSPrim.AddAngularForce", addAngularForceOperation); + } + // A torque impulse. + public void ApplyTorqueImpulse(OMV.Vector3 impulse, bool inTaintTime) + { + OMV.Vector3 applyImpulse = impulse; + BSScene.TaintCallback applyTorqueImpulseOperation = delegate() + { + DetailLog("{0},BSPrim.ApplyTorqueImpulse,taint,tImpulse={1}", LocalID, applyImpulse); + BulletSimAPI.ApplyTorqueImpulse2(BSBody.ptr, applyImpulse); + }; + if (inTaintTime) + applyTorqueImpulseOperation(); + else + PhysicsScene.TaintedObject("BSPrim.ApplyTorqueImpulse", applyTorqueImpulseOperation); } public override void SetMomentum(OMV.Vector3 momentum) { // DetailLog("{0},BSPrim.SetMomentum,call,mom={1}", LocalID, momentum); @@ -1418,8 +1446,9 @@ public sealed class BSPrim : BSPhysObject PositionSanityCheck(true); - DetailLog("{0},BSPrim.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5}", - LocalID, _position, _orientation, _velocity, _acceleration, _rotationalVelocity); + OMV.Vector3 direction = OMV.Vector3.UnitX * _orientation; + DetailLog("{0},BSPrim.UpdateProperties,call,pos={1},orient={2},dir={3},vel={4},rotVel={5}", + LocalID, _position, _orientation, direction, _velocity, _rotationalVelocity); // BulletSimAPI.DumpRigidBody2(PhysicsScene.World.ptr, BSBody.ptr); // DEBUG DEBUG DEBUG -- cgit v1.1 From 364a7c308804a3e331199ca60c6dfafa406b5d0d Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Wed, 31 Oct 2012 14:49:28 -0700 Subject: BulletSim: rename BSBody and BSShape to PhysBody and PhysShape. Add skeleton of BSLinksetCompound. --- .../Region/Physics/BulletSPlugin/BSCharacter.cs | 78 +++++----- OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs | 4 +- OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs | 7 - .../Physics/BulletSPlugin/BSLinksetCompound.cs | 173 +++++++++++++++++++++ .../Physics/BulletSPlugin/BSLinksetConstraints.cs | 40 ++--- .../Region/Physics/BulletSPlugin/BSPhysObject.cs | 8 +- OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | 128 +++++++-------- OpenSim/Region/Physics/BulletSPlugin/BSScene.cs | 20 +-- .../Physics/BulletSPlugin/BSShapeCollection.cs | 46 +++--- 9 files changed, 328 insertions(+), 176 deletions(-) create mode 100755 OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs index b9013ab..8c7061d 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs @@ -131,45 +131,45 @@ public sealed class BSCharacter : BSPhysObject DetailLog("{0},BSCharacter.Destroy", LocalID); PhysicsScene.TaintedObject("BSCharacter.destroy", delegate() { - PhysicsScene.Shapes.DereferenceBody(BSBody, true, null); - PhysicsScene.Shapes.DereferenceShape(BSShape, true, null); + PhysicsScene.Shapes.DereferenceBody(PhysBody, true, null); + PhysicsScene.Shapes.DereferenceShape(PhysShape, true, null); }); } private void SetPhysicalProperties() { - BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, BSBody.ptr); + BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, PhysBody.ptr); ZeroMotion(); ForcePosition = _position; // Set the velocity and compute the proper friction ForceVelocity = _velocity; - BulletSimAPI.SetRestitution2(BSBody.ptr, PhysicsScene.Params.avatarRestitution); - BulletSimAPI.SetMargin2(BSShape.ptr, PhysicsScene.Params.collisionMargin); - BulletSimAPI.SetLocalScaling2(BSShape.ptr, Scale); - BulletSimAPI.SetContactProcessingThreshold2(BSBody.ptr, PhysicsScene.Params.contactProcessingThreshold); + BulletSimAPI.SetRestitution2(PhysBody.ptr, PhysicsScene.Params.avatarRestitution); + BulletSimAPI.SetMargin2(PhysShape.ptr, PhysicsScene.Params.collisionMargin); + BulletSimAPI.SetLocalScaling2(PhysShape.ptr, Scale); + BulletSimAPI.SetContactProcessingThreshold2(PhysBody.ptr, PhysicsScene.Params.contactProcessingThreshold); if (PhysicsScene.Params.ccdMotionThreshold > 0f) { - BulletSimAPI.SetCcdMotionThreshold2(BSBody.ptr, PhysicsScene.Params.ccdMotionThreshold); - BulletSimAPI.SetCcdSweptSphereRadius2(BSBody.ptr, PhysicsScene.Params.ccdSweptSphereRadius); + BulletSimAPI.SetCcdMotionThreshold2(PhysBody.ptr, PhysicsScene.Params.ccdMotionThreshold); + BulletSimAPI.SetCcdSweptSphereRadius2(PhysBody.ptr, PhysicsScene.Params.ccdSweptSphereRadius); } UpdatePhysicalMassProperties(MassRaw); // Make so capsule does not fall over - BulletSimAPI.SetAngularFactorV2(BSBody.ptr, OMV.Vector3.Zero); + BulletSimAPI.SetAngularFactorV2(PhysBody.ptr, OMV.Vector3.Zero); - BulletSimAPI.AddToCollisionFlags2(BSBody.ptr, CollisionFlags.CF_CHARACTER_OBJECT); + BulletSimAPI.AddToCollisionFlags2(PhysBody.ptr, CollisionFlags.CF_CHARACTER_OBJECT); - BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, BSBody.ptr); + BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, PhysBody.ptr); // BulletSimAPI.ForceActivationState2(BSBody.ptr, ActivationState.ACTIVE_TAG); - BulletSimAPI.ForceActivationState2(BSBody.ptr, ActivationState.DISABLE_DEACTIVATION); - BulletSimAPI.UpdateSingleAabb2(PhysicsScene.World.ptr, BSBody.ptr); + BulletSimAPI.ForceActivationState2(PhysBody.ptr, ActivationState.DISABLE_DEACTIVATION); + BulletSimAPI.UpdateSingleAabb2(PhysicsScene.World.ptr, PhysBody.ptr); // Do this after the object has been added to the world - BulletSimAPI.SetCollisionFilterMask2(BSBody.ptr, + BulletSimAPI.SetCollisionFilterMask2(PhysBody.ptr, (uint)CollisionFilterGroups.AvatarFilter, (uint)CollisionFilterGroups.AvatarMask); } @@ -199,7 +199,7 @@ public sealed class BSCharacter : BSPhysObject PhysicsScene.TaintedObject("BSCharacter.setSize", delegate() { - BulletSimAPI.SetLocalScaling2(BSShape.ptr, Scale); + BulletSimAPI.SetLocalScaling2(PhysShape.ptr, Scale); UpdatePhysicalMassProperties(MassRaw); }); @@ -234,10 +234,10 @@ public sealed class BSCharacter : BSPhysObject _rotationalVelocity = OMV.Vector3.Zero; // Zero some other properties directly into the physics engine - BulletSimAPI.SetLinearVelocity2(BSBody.ptr, OMV.Vector3.Zero); - BulletSimAPI.SetAngularVelocity2(BSBody.ptr, OMV.Vector3.Zero); - BulletSimAPI.SetInterpolationVelocity2(BSBody.ptr, OMV.Vector3.Zero, OMV.Vector3.Zero); - BulletSimAPI.ClearForces2(BSBody.ptr); + BulletSimAPI.SetLinearVelocity2(PhysBody.ptr, OMV.Vector3.Zero); + BulletSimAPI.SetAngularVelocity2(PhysBody.ptr, OMV.Vector3.Zero); + BulletSimAPI.SetInterpolationVelocity2(PhysBody.ptr, OMV.Vector3.Zero, OMV.Vector3.Zero); + BulletSimAPI.ClearForces2(PhysBody.ptr); } public override void LockAngularMotion(OMV.Vector3 axis) { return; } @@ -254,19 +254,19 @@ public sealed class BSCharacter : BSPhysObject PhysicsScene.TaintedObject("BSCharacter.setPosition", delegate() { DetailLog("{0},BSCharacter.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation); - BulletSimAPI.SetTranslation2(BSBody.ptr, _position, _orientation); + BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation); }); } } public override OMV.Vector3 ForcePosition { get { - _position = BulletSimAPI.GetPosition2(BSBody.ptr); + _position = BulletSimAPI.GetPosition2(PhysBody.ptr); return _position; } set { _position = value; PositionSanityCheck(); - BulletSimAPI.SetTranslation2(BSBody.ptr, _position, _orientation); + BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation); } } @@ -313,7 +313,7 @@ public sealed class BSCharacter : BSPhysObject BSScene.TaintCallback sanityOperation = delegate() { DetailLog("{0},BSCharacter.PositionSanityCheck,taint,pos={1},orient={2}", LocalID, _position, _orientation); - BulletSimAPI.SetTranslation2(BSBody.ptr, _position, _orientation); + BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation); }; if (inTaintTime) sanityOperation(); @@ -332,8 +332,8 @@ public sealed class BSCharacter : BSPhysObject } public override void UpdatePhysicalMassProperties(float physMass) { - OMV.Vector3 localInertia = BulletSimAPI.CalculateLocalInertia2(BSShape.ptr, physMass); - BulletSimAPI.SetMassProps2(BSBody.ptr, physMass, localInertia); + OMV.Vector3 localInertia = BulletSimAPI.CalculateLocalInertia2(PhysShape.ptr, physMass); + BulletSimAPI.SetMassProps2(PhysBody.ptr, physMass, localInertia); } public override OMV.Vector3 Force { @@ -344,7 +344,7 @@ public sealed class BSCharacter : BSPhysObject PhysicsScene.TaintedObject("BSCharacter.SetForce", delegate() { DetailLog("{0},BSCharacter.setForce,taint,force={1}", LocalID, _force); - BulletSimAPI.SetObjectForce2(BSBody.ptr, _force); + BulletSimAPI.SetObjectForce2(PhysBody.ptr, _force); }); } } @@ -383,7 +383,7 @@ public sealed class BSCharacter : BSPhysObject if (_currentFriction != PhysicsScene.Params.avatarStandingFriction) { _currentFriction = PhysicsScene.Params.avatarStandingFriction; - BulletSimAPI.SetFriction2(BSBody.ptr, _currentFriction); + BulletSimAPI.SetFriction2(PhysBody.ptr, _currentFriction); } } else @@ -391,15 +391,15 @@ public sealed class BSCharacter : BSPhysObject if (_currentFriction != PhysicsScene.Params.avatarFriction) { _currentFriction = PhysicsScene.Params.avatarFriction; - BulletSimAPI.SetFriction2(BSBody.ptr, _currentFriction); + BulletSimAPI.SetFriction2(PhysBody.ptr, _currentFriction); } } _velocity = value; // Remember the set velocity so we can suppress the reduction by friction, ... _appliedVelocity = value; - BulletSimAPI.SetLinearVelocity2(BSBody.ptr, _velocity); - BulletSimAPI.Activate2(BSBody.ptr, true); + BulletSimAPI.SetLinearVelocity2(PhysBody.ptr, _velocity); + BulletSimAPI.Activate2(PhysBody.ptr, true); } } public override OMV.Vector3 Torque { @@ -424,7 +424,7 @@ public sealed class BSCharacter : BSPhysObject PhysicsScene.TaintedObject("BSCharacter.setOrientation", delegate() { // _position = BulletSimAPI.GetPosition2(BSBody.ptr); - BulletSimAPI.SetTranslation2(BSBody.ptr, _position, _orientation); + BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation); }); } } @@ -433,13 +433,13 @@ public sealed class BSCharacter : BSPhysObject { get { - _orientation = BulletSimAPI.GetOrientation2(BSBody.ptr); + _orientation = BulletSimAPI.GetOrientation2(PhysBody.ptr); return _orientation; } set { _orientation = value; - BulletSimAPI.SetTranslation2(BSBody.ptr, _position, _orientation); + BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation); } } public override int PhysicsActorType { @@ -498,9 +498,9 @@ public sealed class BSCharacter : BSPhysObject PhysicsScene.TaintedObject("BSCharacter.setFloatOnWater", delegate() { if (_floatOnWater) - CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(BSBody.ptr, CollisionFlags.BS_FLOATS_ON_WATER); + CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(PhysBody.ptr, CollisionFlags.BS_FLOATS_ON_WATER); else - CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(BSBody.ptr, CollisionFlags.BS_FLOATS_ON_WATER); + CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(PhysBody.ptr, CollisionFlags.BS_FLOATS_ON_WATER); }); } } @@ -533,7 +533,7 @@ public sealed class BSCharacter : BSPhysObject DetailLog("{0},BSCharacter.setForceBuoyancy,taint,buoy={1}", LocalID, _buoyancy); // Buoyancy is faked by changing the gravity applied to the object float grav = PhysicsScene.Params.gravity * (1f - _buoyancy); - BulletSimAPI.SetGravity2(BSBody.ptr, new OMV.Vector3(0f, 0f, grav)); + BulletSimAPI.SetGravity2(PhysBody.ptr, new OMV.Vector3(0f, 0f, grav)); } } @@ -579,7 +579,7 @@ public sealed class BSCharacter : BSPhysObject PhysicsScene.TaintedObject("BSCharacter.AddForce", delegate() { DetailLog("{0},BSCharacter.setAddForce,taint,addedForce={1}", LocalID, _force); - BulletSimAPI.SetObjectForce2(BSBody.ptr, _force); + BulletSimAPI.SetObjectForce2(PhysBody.ptr, _force); }); } else @@ -647,7 +647,7 @@ public sealed class BSCharacter : BSPhysObject // That's just the way they are defined. OMV.Vector3 avVel = new OMV.Vector3(_appliedVelocity.X, _appliedVelocity.Y, entprop.Velocity.Z); _velocity = avVel; - BulletSimAPI.SetLinearVelocity2(BSBody.ptr, avVel); + BulletSimAPI.SetLinearVelocity2(PhysBody.ptr, avVel); } // Tell the linkset about value changes diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs index 5c61774..38609e3 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs @@ -514,8 +514,8 @@ namespace OpenSim.Region.Physics.BulletSPlugin if (IsActive) { // Friction effects are handled by this vehicle code - BulletSimAPI.SetFriction2(Prim.BSBody.ptr, 0f); - BulletSimAPI.SetHitFraction2(Prim.BSBody.ptr, 0f); + BulletSimAPI.SetFriction2(Prim.PhysBody.ptr, 0f); + BulletSimAPI.SetHitFraction2(Prim.PhysBody.ptr, 0f); } } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs index 6d84fcc..525ec28 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs @@ -194,13 +194,6 @@ public abstract class BSLinkset // Called while LinkActivity is locked. protected abstract void AddChildToLinkset(BSPhysObject child); - // Forcefully removing a child from a linkset. - // This is not being called by the child so we have to make sure the child doesn't think - // it's still connected to the linkset. - // Normal OpenSimulator operation will never do this because other SceneObjectPart information - // also has to be updated (like pointer to prim's parent). - protected abstract void RemoveChildFromOtherLinkset(BSPhysObject pchild); - // I am the root of a linkset and one of my children is being removed. // Safe to call even if the child is not really in my linkset. protected abstract void RemoveChildFromLinkset(BSPhysObject child); diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs new file mode 100755 index 0000000..1c569b5 --- /dev/null +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs @@ -0,0 +1,173 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyrightD + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +using System; +using System.Collections.Generic; +using System.Text; + +using OMV = OpenMetaverse; + +namespace OpenSim.Region.Physics.BulletSPlugin +{ +public sealed class BSLinksetCompound : BSLinkset +{ + // private static string LogHeader = "[BULLETSIM LINKSET CONSTRAINTS]"; + + public BSLinksetCompound(BSScene scene, BSPhysObject parent) + { + base.Initialize(scene, parent); + } + + // When physical properties are changed the linkset needs to recalculate + // its internal properties. + // This is queued in the 'post taint' queue so the + // refresh will happen once after all the other taints are applied. + public override void Refresh(BSPhysObject requestor) + { + // Queue to happen after all the other taint processing + PhysicsScene.PostTaintObject("BSLinksetcompound.Refresh", requestor.LocalID, delegate() + { + if (HasAnyChildren && IsRoot(requestor)) + RecomputeLinksetCompound(); + }); + } + + // The object is going dynamic (physical). Do any setup necessary + // for a dynamic linkset. + // Only the state of the passed object can be modified. The rest of the linkset + // has not yet been fully constructed. + // Return 'true' if any properties updated on the passed object. + // Called at taint-time! + public override bool MakeDynamic(BSPhysObject child) + { + // What is done for each object in BSPrim is what we want. + return false; + } + + // The object is going static (non-physical). Do any setup necessary for a static linkset. + // Return 'true' if any properties updated on the passed object. + // This doesn't normally happen -- OpenSim removes the objects from the physical + // world if it is a static linkset. + // Called at taint-time! + public override bool MakeStatic(BSPhysObject child) + { + // What is done for each object in BSPrim is what we want. + return false; + } + + // Called at taint-time!! + public override void UpdateProperties(BSPhysObject updated) + { + // Nothing to do for constraints on property updates + } + + // Routine called when rebuilding the body of some member of the linkset. + // Destroy all the constraints have have been made to root and set + // up to rebuild the constraints before the next simulation step. + // Returns 'true' of something was actually removed and would need restoring + // Called at taint-time!! + public override bool RemoveBodyDependencies(BSPrim child) + { + bool ret = false; + + DetailLog("{0},BSLinksetcompound.RemoveBodyDependencies,removeChildrenForRoot,rID={1},rBody={2}", + child.LocalID, LinksetRoot.LocalID, LinksetRoot.PhysBody.ptr.ToString("X")); + + // Cause the current shape to be freed and the new one to be built. + Refresh(LinksetRoot); + + return ret; + } + + // Companion to RemoveBodyDependencies(). If RemoveBodyDependencies() returns 'true', + // this routine will restore the removed constraints. + // Called at taint-time!! + public override void RestoreBodyDependencies(BSPrim child) + { + // The Refresh operation queued by RemoveBodyDependencies() will build any missing constraints. + } + + // ================================================================ + + // Add a new child to the linkset. + // Called while LinkActivity is locked. + protected override void AddChildToLinkset(BSPhysObject child) + { + if (!HasChild(child)) + { + m_children.Add(child); + + DetailLog("{0},BSLinksetCompound.AddChildToLinkset,call,child={1}", LinksetRoot.LocalID, child.LocalID); + + // Cause constraints and assorted properties to be recomputed before the next simulation step. + Refresh(LinksetRoot); + } + return; + } + + // Remove the specified child from the linkset. + // Safe to call even if the child is not really in my linkset. + protected override void RemoveChildFromLinkset(BSPhysObject child) + { + if (m_children.Remove(child)) + { + DetailLog("{0},BSLinksetCompound.RemoveChildFromLinkset,call,rID={1},rBody={2},cID={3},cBody={4}", + child.LocalID, + LinksetRoot.LocalID, LinksetRoot.PhysBody.ptr.ToString("X"), + child.LocalID, child.PhysBody.ptr.ToString("X")); + + // See that the linkset parameters are recomputed at the end of the taint time. + Refresh(LinksetRoot); + } + else + { + // Non-fatal occurance. + // PhysicsScene.Logger.ErrorFormat("{0}: Asked to remove child from linkset that was not in linkset", LogHeader); + } + return; + } + + + // Call each of the constraints that make up this linkset and recompute the + // various transforms and variables. Create constraints of not created yet. + // Called before the simulation step to make sure the constraint based linkset + // is all initialized. + // Called at taint time!! + private void RecomputeLinksetCompound() + { + float linksetMass = LinksetMass; + LinksetRoot.UpdatePhysicalMassProperties(linksetMass); + + // DEBUG: see of inter-linkset collisions are causing problems + // BulletSimAPI.SetCollisionFilterMask2(LinksetRoot.BSBody.ptr, + // (uint)CollisionFilterGroups.LinksetFilter, (uint)CollisionFilterGroups.LinksetMask); + DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,set,rBody={1},linksetMass={2}", + LinksetRoot.LocalID, LinksetRoot.PhysBody.ptr.ToString("X"), linksetMass); + + + } +} +} \ No newline at end of file diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs index 8cdbd9b..65aed77 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs @@ -94,7 +94,7 @@ public sealed class BSLinksetConstraints : BSLinkset bool ret = false; DetailLog("{0},BSLinksetConstraint.RemoveBodyDependencies,removeChildrenForRoot,rID={1},rBody={2}", - child.LocalID, LinksetRoot.LocalID, LinksetRoot.BSBody.ptr.ToString("X")); + child.LocalID, LinksetRoot.LocalID, LinksetRoot.PhysBody.ptr.ToString("X")); lock (m_linksetActivityLock) { @@ -124,9 +124,6 @@ public sealed class BSLinksetConstraints : BSLinkset { m_children.Add(child); - BSPhysObject rootx = LinksetRoot; // capture the root as of now - BSPhysObject childx = child; - DetailLog("{0},BSLinksetConstraints.AddChildToLinkset,call,child={1}", LinksetRoot.LocalID, child.LocalID); // Cause constraints and assorted properties to be recomputed before the next simulation step. @@ -135,17 +132,6 @@ public sealed class BSLinksetConstraints : BSLinkset return; } - // Forcefully removing a child from a linkset. - // This is not being called by the child so we have to make sure the child doesn't think - // it's still connected to the linkset. - // Normal OpenSimulator operation will never do this because other SceneObjectPart information - // also has to be updated (like pointer to prim's parent). - protected override void RemoveChildFromOtherLinkset(BSPhysObject pchild) - { - pchild.Linkset = BSLinkset.Factory(PhysicsScene, pchild); - RemoveChildFromLinkset(pchild); - } - // Remove the specified child from the linkset. // Safe to call even if the child is not really in my linkset. protected override void RemoveChildFromLinkset(BSPhysObject child) @@ -157,8 +143,8 @@ public sealed class BSLinksetConstraints : BSLinkset DetailLog("{0},BSLinksetConstraints.RemoveChildFromLinkset,call,rID={1},rBody={2},cID={3},cBody={4}", childx.LocalID, - rootx.LocalID, rootx.BSBody.ptr.ToString("X"), - childx.LocalID, childx.BSBody.ptr.ToString("X")); + rootx.LocalID, rootx.PhysBody.ptr.ToString("X"), + childx.LocalID, childx.PhysBody.ptr.ToString("X")); PhysicsScene.TaintedObject("BSLinksetConstraints.RemoveChildFromLinkset", delegate() { @@ -197,15 +183,15 @@ public sealed class BSLinksetConstraints : BSLinkset DetailLog("{0},BSLinksetConstraint.BuildConstraint,taint,root={1},rBody={2},child={3},cBody={4},rLoc={5},cLoc={6},midLoc={7}", rootPrim.LocalID, - rootPrim.LocalID, rootPrim.BSBody.ptr.ToString("X"), - childPrim.LocalID, childPrim.BSBody.ptr.ToString("X"), + rootPrim.LocalID, rootPrim.PhysBody.ptr.ToString("X"), + childPrim.LocalID, childPrim.PhysBody.ptr.ToString("X"), rootPrim.Position, childPrim.Position, midPoint); // create a constraint that allows no freedom of movement between the two objects // http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818 BSConstraint6Dof constrain = new BSConstraint6Dof( - PhysicsScene.World, rootPrim.BSBody, childPrim.BSBody, midPoint, true, true ); + PhysicsScene.World, rootPrim.PhysBody, childPrim.PhysBody, midPoint, true, true ); // PhysicsScene.World, childPrim.BSBody, rootPrim.BSBody, midPoint, true, true ); /* NOTE: below is an attempt to build constraint with full frame computation, etc. @@ -262,14 +248,14 @@ public sealed class BSLinksetConstraints : BSLinkset bool ret = false; DetailLog("{0},BSLinksetConstraint.PhysicallyUnlinkAChildFromRoot,taint,root={1},rBody={2},child={3},cBody={4}", rootPrim.LocalID, - rootPrim.LocalID, rootPrim.BSBody.ptr.ToString("X"), - childPrim.LocalID, childPrim.BSBody.ptr.ToString("X")); + rootPrim.LocalID, rootPrim.PhysBody.ptr.ToString("X"), + childPrim.LocalID, childPrim.PhysBody.ptr.ToString("X")); // Find the constraint for this link and get rid of it from the overall collection and from my list - if (PhysicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.BSBody, childPrim.BSBody)) + if (PhysicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.PhysBody, childPrim.PhysBody)) { // Make the child refresh its location - BulletSimAPI.PushUpdate2(childPrim.BSBody.ptr); + BulletSimAPI.PushUpdate2(childPrim.PhysBody.ptr); ret = true; } @@ -283,7 +269,7 @@ public sealed class BSLinksetConstraints : BSLinkset { DetailLog("{0},BSLinksetConstraint.PhysicallyUnlinkAllChildren,taint", rootPrim.LocalID); - return PhysicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.BSBody); + return PhysicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.PhysBody); } // Call each of the constraints that make up this linkset and recompute the @@ -300,7 +286,7 @@ public sealed class BSLinksetConstraints : BSLinkset // BulletSimAPI.SetCollisionFilterMask2(LinksetRoot.BSBody.ptr, // (uint)CollisionFilterGroups.LinksetFilter, (uint)CollisionFilterGroups.LinksetMask); DetailLog("{0},BSLinksetConstraint.RecomputeLinksetConstraints,set,rBody={1},linksetMass={2}", - LinksetRoot.LocalID, LinksetRoot.BSBody.ptr.ToString("X"), linksetMass); + LinksetRoot.LocalID, LinksetRoot.PhysBody.ptr.ToString("X"), linksetMass); foreach (BSPhysObject child in m_children) { @@ -310,7 +296,7 @@ public sealed class BSLinksetConstraints : BSLinkset child.UpdatePhysicalMassProperties(linksetMass); BSConstraint constrain; - if (!PhysicsScene.Constraints.TryGetConstraint(LinksetRoot.BSBody, child.BSBody, out constrain)) + if (!PhysicsScene.Constraints.TryGetConstraint(LinksetRoot.PhysBody, child.PhysBody, out constrain)) { // If constraint doesn't exist yet, create it. constrain = BuildConstraint(LinksetRoot, child); diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs index be8d64b..6220b21 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs @@ -68,9 +68,9 @@ public abstract class BSPhysObject : PhysicsActor public abstract void UpdatePhysicalMassProperties(float mass); // Reference to the physical body (btCollisionObject) of this object - public BulletBody BSBody; + public BulletBody PhysBody; // Reference to the physical shape (btCollisionShape) of this object - public BulletShape BSShape; + public BulletShape PhysShape; // 'true' if the mesh's underlying asset failed to build. // This will keep us from looping after the first time the build failed. @@ -206,7 +206,7 @@ public abstract class BSPhysObject : PhysicsActor PhysicsScene.TaintedObject(TypeName+".SubscribeEvents", delegate() { - CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(BSBody.ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); + CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(PhysBody.ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); }); } else @@ -220,7 +220,7 @@ public abstract class BSPhysObject : PhysicsActor SubscribedEventsMs = 0; PhysicsScene.TaintedObject(TypeName+".UnSubscribeEvents", delegate() { - CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(BSBody.ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); + CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(PhysBody.ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); }); } // Return 'true' if the simulator wants collision events diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index 9ced61fa..8dd48ca 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs @@ -111,8 +111,8 @@ public sealed class BSPrim : BSPhysObject _mass = CalculateMass(); // No body or shape yet - BSBody = new BulletBody(LocalID, IntPtr.Zero); - BSShape = new BulletShape(IntPtr.Zero); + PhysBody = new BulletBody(LocalID, IntPtr.Zero); + PhysShape = new BulletShape(IntPtr.Zero); DetailLog("{0},BSPrim.constructor,call", LocalID); // do the actual object creation at taint time @@ -120,7 +120,7 @@ public sealed class BSPrim : BSPhysObject { CreateGeomAndObject(true); - CurrentCollisionFlags = BulletSimAPI.GetCollisionFlags2(BSBody.ptr); + CurrentCollisionFlags = BulletSimAPI.GetCollisionFlags2(PhysBody.ptr); }); } @@ -145,8 +145,8 @@ public sealed class BSPrim : BSPhysObject { DetailLog("{0},BSPrim.Destroy,taint,", LocalID); // If there are physical body and shape, release my use of same. - PhysicsScene.Shapes.DereferenceBody(BSBody, true, null); - PhysicsScene.Shapes.DereferenceShape(BSShape, true, null); + PhysicsScene.Shapes.DereferenceBody(PhysBody, true, null); + PhysicsScene.Shapes.DereferenceShape(PhysShape, true, null); }); } @@ -243,7 +243,7 @@ public sealed class BSPrim : BSPhysObject _rotationalVelocity = OMV.Vector3.Zero; // Zero some other properties in the physics engine - BulletSimAPI.ClearAllForces2(BSBody.ptr); + BulletSimAPI.ClearAllForces2(PhysBody.ptr); } public override void LockAngularMotion(OMV.Vector3 axis) @@ -256,7 +256,7 @@ public sealed class BSPrim : BSPhysObject get { if (!Linkset.IsRoot(this)) // child prims move around based on their parent. Need to get the latest location - _position = BulletSimAPI.GetPosition2(BSBody.ptr); + _position = BulletSimAPI.GetPosition2(PhysBody.ptr); // don't do the GetObjectPosition for root elements because this function is called a zillion times // _position = BulletSimAPI.GetObjectPosition2(PhysicsScene.World.ptr, BSBody.ptr); @@ -274,20 +274,20 @@ public sealed class BSPrim : BSPhysObject PhysicsScene.TaintedObject("BSPrim.setPosition", delegate() { // DetailLog("{0},BSPrim.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation); - BulletSimAPI.SetTranslation2(BSBody.ptr, _position, _orientation); + BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation); ActivateIfPhysical(false); }); } } public override OMV.Vector3 ForcePosition { get { - _position = BulletSimAPI.GetPosition2(BSBody.ptr); + _position = BulletSimAPI.GetPosition2(PhysBody.ptr); return _position; } set { _position = value; PositionSanityCheck(); - BulletSimAPI.SetTranslation2(BSBody.ptr, _position, _orientation); + BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation); ActivateIfPhysical(false); } } @@ -371,15 +371,15 @@ public sealed class BSPrim : BSPhysObject { if (IsStatic) { - BulletSimAPI.SetMassProps2(BSBody.ptr, 0f, OMV.Vector3.Zero); - BulletSimAPI.UpdateInertiaTensor2(BSBody.ptr); + BulletSimAPI.SetMassProps2(PhysBody.ptr, 0f, OMV.Vector3.Zero); + BulletSimAPI.UpdateInertiaTensor2(PhysBody.ptr); } else { - OMV.Vector3 localInertia = BulletSimAPI.CalculateLocalInertia2(BSShape.ptr, physMass); - BulletSimAPI.SetMassProps2(BSBody.ptr, physMass, localInertia); + OMV.Vector3 localInertia = BulletSimAPI.CalculateLocalInertia2(PhysShape.ptr, physMass); + BulletSimAPI.SetMassProps2(PhysBody.ptr, physMass, localInertia); // center of mass is at the zero of the object - BulletSimAPI.SetCenterOfMassByPosRot2(BSBody.ptr, ForcePosition, ForceOrientation); + BulletSimAPI.SetCenterOfMassByPosRot2(PhysBody.ptr, ForcePosition, ForceOrientation); // BulletSimAPI.UpdateInertiaTensor2(BSBody.ptr); DetailLog("{0},BSPrim.UpdateMassProperties,mass={1},localInertia={2}", LocalID, physMass, localInertia); } @@ -404,7 +404,7 @@ public sealed class BSPrim : BSPhysObject PhysicsScene.TaintedObject("BSPrim.setForce", delegate() { // DetailLog("{0},BSPrim.setForce,taint,force={1}", LocalID, _force); - BulletSimAPI.SetObjectForce2(BSBody.ptr, _force); + BulletSimAPI.SetObjectForce2(PhysBody.ptr, _force); }); } } @@ -498,7 +498,7 @@ public sealed class BSPrim : BSPhysObject PhysicsScene.TaintedObject("BSPrim.setVelocity", delegate() { // DetailLog("{0},BSPrim.SetVelocity,taint,vel={1}", LocalID, _velocity); - BulletSimAPI.SetLinearVelocity2(BSBody.ptr, _velocity); + BulletSimAPI.SetLinearVelocity2(PhysBody.ptr, _velocity); }); } } @@ -506,7 +506,7 @@ public sealed class BSPrim : BSPhysObject get { return _velocity; } set { _velocity = value; - BulletSimAPI.SetLinearVelocity2(BSBody.ptr, _velocity); + BulletSimAPI.SetLinearVelocity2(PhysBody.ptr, _velocity); } } public override OMV.Vector3 Torque { @@ -531,7 +531,7 @@ public sealed class BSPrim : BSPhysObject if (!Linkset.IsRoot(this)) { // Children move around because tied to parent. Get a fresh value. - _orientation = BulletSimAPI.GetOrientation2(BSBody.ptr); + _orientation = BulletSimAPI.GetOrientation2(PhysBody.ptr); } return _orientation; } @@ -544,7 +544,7 @@ public sealed class BSPrim : BSPhysObject { // _position = BulletSimAPI.GetObjectPosition2(PhysicsScene.World.ptr, BSBody.ptr); // DetailLog("{0},BSPrim.setOrientation,taint,pos={1},orient={2}", LocalID, _position, _orientation); - BulletSimAPI.SetTranslation2(BSBody.ptr, _position, _orientation); + BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation); }); } } @@ -553,13 +553,13 @@ public sealed class BSPrim : BSPhysObject { get { - _orientation = BulletSimAPI.GetOrientation2(BSBody.ptr); + _orientation = BulletSimAPI.GetOrientation2(PhysBody.ptr); return _orientation; } set { _orientation = value; - BulletSimAPI.SetTranslation2(BSBody.ptr, _position, _orientation); + BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation); } } public override int PhysicsActorType { @@ -615,7 +615,7 @@ public sealed class BSPrim : BSPhysObject // Mangling all the physical properties requires the object not be in the physical world. // This is a NOOP if the object is not in the world (BulletSim and Bullet ignore objects not found). - BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, BSBody.ptr); + BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, PhysBody.ptr); // Set up the object physicalness (does gravity and collisions move this object) MakeDynamic(IsStatic); @@ -629,15 +629,15 @@ public sealed class BSPrim : BSPhysObject // Make solid or not (do things bounce off or pass through this object). MakeSolid(IsSolid); - BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, BSBody.ptr); + BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, PhysBody.ptr); // Rebuild its shape - BulletSimAPI.UpdateSingleAabb2(PhysicsScene.World.ptr, BSBody.ptr); + BulletSimAPI.UpdateSingleAabb2(PhysicsScene.World.ptr, PhysBody.ptr); // Collision filter can be set only when the object is in the world - if (BSBody.collisionFilter != 0 || BSBody.collisionMask != 0) + if (PhysBody.collisionFilter != 0 || PhysBody.collisionMask != 0) { - BulletSimAPI.SetCollisionFilterMask2(BSBody.ptr, (uint)BSBody.collisionFilter, (uint)BSBody.collisionMask); + BulletSimAPI.SetCollisionFilterMask2(PhysBody.ptr, (uint)PhysBody.collisionFilter, (uint)PhysBody.collisionMask); } // Recompute any linkset parameters. @@ -646,7 +646,7 @@ public sealed class BSPrim : BSPhysObject Linkset.Refresh(this); DetailLog("{0},BSPrim.UpdatePhysicalParameters,taintExit,static={1},solid={2},mass={3},collide={4},cf={5:X},body={6},shape={7}", - LocalID, IsStatic, IsSolid, _mass, SubscribedEvents(), CurrentCollisionFlags, BSBody, BSShape); + LocalID, IsStatic, IsSolid, _mass, SubscribedEvents(), CurrentCollisionFlags, PhysBody, PhysShape); } // "Making dynamic" means changing to and from static. @@ -659,44 +659,44 @@ public sealed class BSPrim : BSPhysObject if (makeStatic) { // Become a Bullet 'static' object type - CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(BSBody.ptr, CollisionFlags.CF_STATIC_OBJECT); + CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(PhysBody.ptr, CollisionFlags.CF_STATIC_OBJECT); // Stop all movement ZeroMotion(); // Center of mass is at the center of the object - BulletSimAPI.SetCenterOfMassByPosRot2(Linkset.LinksetRoot.BSBody.ptr, _position, _orientation); + BulletSimAPI.SetCenterOfMassByPosRot2(Linkset.LinksetRoot.PhysBody.ptr, _position, _orientation); // Mass is zero which disables a bunch of physics stuff in Bullet UpdatePhysicalMassProperties(0f); // Set collision detection parameters if (PhysicsScene.Params.ccdMotionThreshold > 0f) { - BulletSimAPI.SetCcdMotionThreshold2(BSBody.ptr, PhysicsScene.Params.ccdMotionThreshold); - BulletSimAPI.SetCcdSweptSphereRadius2(BSBody.ptr, PhysicsScene.Params.ccdSweptSphereRadius); + BulletSimAPI.SetCcdMotionThreshold2(PhysBody.ptr, PhysicsScene.Params.ccdMotionThreshold); + BulletSimAPI.SetCcdSweptSphereRadius2(PhysBody.ptr, PhysicsScene.Params.ccdSweptSphereRadius); } // There can be special things needed for implementing linksets Linkset.MakeStatic(this); // The activation state is 'disabled' so Bullet will not try to act on it. - BulletSimAPI.ForceActivationState2(BSBody.ptr, ActivationState.DISABLE_SIMULATION); + BulletSimAPI.ForceActivationState2(PhysBody.ptr, ActivationState.DISABLE_SIMULATION); // Start it out sleeping and physical actions could wake it up. // BulletSimAPI.ForceActivationState2(BSBody.ptr, ActivationState.ISLAND_SLEEPING); - BSBody.collisionFilter = CollisionFilterGroups.StaticObjectFilter; - BSBody.collisionMask = CollisionFilterGroups.StaticObjectMask; + PhysBody.collisionFilter = CollisionFilterGroups.StaticObjectFilter; + PhysBody.collisionMask = CollisionFilterGroups.StaticObjectMask; } else { // Not a Bullet static object - CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(BSBody.ptr, CollisionFlags.CF_STATIC_OBJECT); + CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(PhysBody.ptr, CollisionFlags.CF_STATIC_OBJECT); // Set various physical properties so internal dynamic properties will get computed correctly as they are set - BulletSimAPI.SetFriction2(BSBody.ptr, PhysicsScene.Params.defaultFriction); - BulletSimAPI.SetRestitution2(BSBody.ptr, PhysicsScene.Params.defaultRestitution); + BulletSimAPI.SetFriction2(PhysBody.ptr, PhysicsScene.Params.defaultFriction); + BulletSimAPI.SetRestitution2(PhysBody.ptr, PhysicsScene.Params.defaultRestitution); // per http://www.bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=3382 // Since this can be called multiple times, only zero forces when becoming physical // BulletSimAPI.ClearAllForces2(BSBody.ptr); // For good measure, make sure the transform is set through to the motion state - BulletSimAPI.SetTranslation2(BSBody.ptr, _position, _orientation); + BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation); // A dynamic object has mass UpdatePhysicalMassProperties(MassRaw); @@ -704,26 +704,26 @@ public sealed class BSPrim : BSPhysObject // Set collision detection parameters if (PhysicsScene.Params.ccdMotionThreshold > 0f) { - BulletSimAPI.SetCcdMotionThreshold2(BSBody.ptr, PhysicsScene.Params.ccdMotionThreshold); - BulletSimAPI.SetCcdSweptSphereRadius2(BSBody.ptr, PhysicsScene.Params.ccdSweptSphereRadius); + BulletSimAPI.SetCcdMotionThreshold2(PhysBody.ptr, PhysicsScene.Params.ccdMotionThreshold); + BulletSimAPI.SetCcdSweptSphereRadius2(PhysBody.ptr, PhysicsScene.Params.ccdSweptSphereRadius); } // Various values for simulation limits - BulletSimAPI.SetDamping2(BSBody.ptr, PhysicsScene.Params.linearDamping, PhysicsScene.Params.angularDamping); - BulletSimAPI.SetDeactivationTime2(BSBody.ptr, PhysicsScene.Params.deactivationTime); - BulletSimAPI.SetSleepingThresholds2(BSBody.ptr, PhysicsScene.Params.linearSleepingThreshold, PhysicsScene.Params.angularSleepingThreshold); - BulletSimAPI.SetContactProcessingThreshold2(BSBody.ptr, PhysicsScene.Params.contactProcessingThreshold); + BulletSimAPI.SetDamping2(PhysBody.ptr, PhysicsScene.Params.linearDamping, PhysicsScene.Params.angularDamping); + BulletSimAPI.SetDeactivationTime2(PhysBody.ptr, PhysicsScene.Params.deactivationTime); + BulletSimAPI.SetSleepingThresholds2(PhysBody.ptr, PhysicsScene.Params.linearSleepingThreshold, PhysicsScene.Params.angularSleepingThreshold); + BulletSimAPI.SetContactProcessingThreshold2(PhysBody.ptr, PhysicsScene.Params.contactProcessingThreshold); // There might be special things needed for implementing linksets. Linkset.MakeDynamic(this); // Force activation of the object so Bullet will act on it. // Must do the ForceActivationState2() to overcome the DISABLE_SIMULATION from static objects. - BulletSimAPI.ForceActivationState2(BSBody.ptr, ActivationState.ACTIVE_TAG); + BulletSimAPI.ForceActivationState2(PhysBody.ptr, ActivationState.ACTIVE_TAG); // BulletSimAPI.Activate2(BSBody.ptr, true); - BSBody.collisionFilter = CollisionFilterGroups.ObjectFilter; - BSBody.collisionMask = CollisionFilterGroups.ObjectMask; + PhysBody.collisionFilter = CollisionFilterGroups.ObjectFilter; + PhysBody.collisionMask = CollisionFilterGroups.ObjectMask; } } @@ -733,7 +733,7 @@ public sealed class BSPrim : BSPhysObject // the functions after this one set up the state of a possibly newly created collision body. private void MakeSolid(bool makeSolid) { - CollisionObjectTypes bodyType = (CollisionObjectTypes)BulletSimAPI.GetBodyType2(BSBody.ptr); + CollisionObjectTypes bodyType = (CollisionObjectTypes)BulletSimAPI.GetBodyType2(PhysBody.ptr); if (makeSolid) { // Verify the previous code created the correct shape for this type of thing. @@ -741,7 +741,7 @@ public sealed class BSPrim : BSPhysObject { m_log.ErrorFormat("{0} MakeSolid: physical body of wrong type for solidity. id={1}, type={2}", LogHeader, LocalID, bodyType); } - CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(BSBody.ptr, CollisionFlags.CF_NO_CONTACT_RESPONSE); + CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(PhysBody.ptr, CollisionFlags.CF_NO_CONTACT_RESPONSE); } else { @@ -749,9 +749,9 @@ public sealed class BSPrim : BSPhysObject { m_log.ErrorFormat("{0} MakeSolid: physical body of wrong type for non-solidness. id={1}, type={2}", LogHeader, LocalID, bodyType); } - CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(BSBody.ptr, CollisionFlags.CF_NO_CONTACT_RESPONSE); - BSBody.collisionFilter = CollisionFilterGroups.VolumeDetectFilter; - BSBody.collisionMask = CollisionFilterGroups.VolumeDetectMask; + CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(PhysBody.ptr, CollisionFlags.CF_NO_CONTACT_RESPONSE); + PhysBody.collisionFilter = CollisionFilterGroups.VolumeDetectFilter; + PhysBody.collisionMask = CollisionFilterGroups.VolumeDetectMask; } } @@ -761,7 +761,7 @@ public sealed class BSPrim : BSPhysObject private void ActivateIfPhysical(bool forceIt) { if (IsPhysical) - BulletSimAPI.Activate2(BSBody.ptr, forceIt); + BulletSimAPI.Activate2(PhysBody.ptr, forceIt); } // Turn on or off the flag controlling whether collision events are returned to the simulator. @@ -769,11 +769,11 @@ public sealed class BSPrim : BSPhysObject { if (wantsCollisionEvents) { - CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(BSBody.ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); + CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(PhysBody.ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); } else { - CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(BSBody.ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); + CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(PhysBody.ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); } } @@ -818,9 +818,9 @@ public sealed class BSPrim : BSPhysObject PhysicsScene.TaintedObject("BSPrim.setFloatOnWater", delegate() { if (_floatOnWater) - CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(BSBody.ptr, CollisionFlags.BS_FLOATS_ON_WATER); + CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(PhysBody.ptr, CollisionFlags.BS_FLOATS_ON_WATER); else - CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(BSBody.ptr, CollisionFlags.BS_FLOATS_ON_WATER); + CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(PhysBody.ptr, CollisionFlags.BS_FLOATS_ON_WATER); }); } } @@ -843,7 +843,7 @@ public sealed class BSPrim : BSPhysObject PhysicsScene.TaintedObject("BSPrim.setRotationalVelocity", delegate() { DetailLog("{0},BSPrim.SetRotationalVel,taint,rotvel={1}", LocalID, _rotationalVelocity); - BulletSimAPI.SetAngularVelocity2(BSBody.ptr, _rotationalVelocity); + BulletSimAPI.SetAngularVelocity2(PhysBody.ptr, _rotationalVelocity); }); } } @@ -853,7 +853,7 @@ public sealed class BSPrim : BSPhysObject } set { _rotationalVelocity = value; - BulletSimAPI.SetAngularVelocity2(BSBody.ptr, _rotationalVelocity); + BulletSimAPI.SetAngularVelocity2(PhysBody.ptr, _rotationalVelocity); } } public override bool Kinematic { @@ -879,7 +879,7 @@ public sealed class BSPrim : BSPhysObject // DetailLog("{0},BSPrim.setForceBuoyancy,taint,buoy={1}", LocalID, _buoyancy); // Buoyancy is faked by changing the gravity applied to the object float grav = PhysicsScene.Params.gravity * (1f - _buoyancy); - BulletSimAPI.SetGravity2(BSBody.ptr, new OMV.Vector3(0f, 0f, grav)); + BulletSimAPI.SetGravity2(PhysBody.ptr, new OMV.Vector3(0f, 0f, grav)); } } @@ -946,7 +946,7 @@ public sealed class BSPrim : BSPhysObject } DetailLog("{0},BSPrim.AddForce,taint,force={1}", LocalID, fSum); if (fSum != OMV.Vector3.Zero) - BulletSimAPI.ApplyCentralForce2(BSBody.ptr, fSum); + BulletSimAPI.ApplyCentralForce2(PhysBody.ptr, fSum); }; if (inTaintTime) addForceOperation(); @@ -986,7 +986,7 @@ public sealed class BSPrim : BSPhysObject DetailLog("{0},BSPrim.AddAngularForce,taint,aForce={1}", LocalID, fSum); if (fSum != OMV.Vector3.Zero) { - BulletSimAPI.ApplyTorque2(BSBody.ptr, fSum); + BulletSimAPI.ApplyTorque2(PhysBody.ptr, fSum); _torque = fSum; } }; @@ -1002,7 +1002,7 @@ public sealed class BSPrim : BSPhysObject BSScene.TaintCallback applyTorqueImpulseOperation = delegate() { DetailLog("{0},BSPrim.ApplyTorqueImpulse,taint,tImpulse={1}", LocalID, applyImpulse); - BulletSimAPI.ApplyTorqueImpulse2(BSBody.ptr, applyImpulse); + BulletSimAPI.ApplyTorqueImpulse2(PhysBody.ptr, applyImpulse); }; if (inTaintTime) applyTorqueImpulseOperation(); diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs index c27b5f0..cc5dbb2 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs @@ -1067,49 +1067,49 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters (s,cf,p,v) => { s.m_params[0].linearDamping = cf.GetFloat(p, v); }, (s) => { return s.m_params[0].linearDamping; }, (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].linearDamping, p, l, v); }, - (s,o,v) => { BulletSimAPI.SetDamping2(o.BSBody.ptr, v, v); } ), + (s,o,v) => { BulletSimAPI.SetDamping2(o.PhysBody.ptr, v, v); } ), new ParameterDefn("AngularDamping", "Factor to damp angular movement per second (0.0 - 1.0)", 0f, (s,cf,p,v) => { s.m_params[0].angularDamping = cf.GetFloat(p, v); }, (s) => { return s.m_params[0].angularDamping; }, (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].angularDamping, p, l, v); }, - (s,o,v) => { BulletSimAPI.SetDamping2(o.BSBody.ptr, v, v); } ), + (s,o,v) => { BulletSimAPI.SetDamping2(o.PhysBody.ptr, v, v); } ), new ParameterDefn("DeactivationTime", "Seconds before considering an object potentially static", 0.2f, (s,cf,p,v) => { s.m_params[0].deactivationTime = cf.GetFloat(p, v); }, (s) => { return s.m_params[0].deactivationTime; }, (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].deactivationTime, p, l, v); }, - (s,o,v) => { BulletSimAPI.SetDeactivationTime2(o.BSBody.ptr, v); } ), + (s,o,v) => { BulletSimAPI.SetDeactivationTime2(o.PhysBody.ptr, v); } ), new ParameterDefn("LinearSleepingThreshold", "Seconds to measure linear movement before considering static", 0.8f, (s,cf,p,v) => { s.m_params[0].linearSleepingThreshold = cf.GetFloat(p, v); }, (s) => { return s.m_params[0].linearSleepingThreshold; }, (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].linearSleepingThreshold, p, l, v); }, - (s,o,v) => { BulletSimAPI.SetSleepingThresholds2(o.BSBody.ptr, v, v); } ), + (s,o,v) => { BulletSimAPI.SetSleepingThresholds2(o.PhysBody.ptr, v, v); } ), new ParameterDefn("AngularSleepingThreshold", "Seconds to measure angular movement before considering static", 1.0f, (s,cf,p,v) => { s.m_params[0].angularSleepingThreshold = cf.GetFloat(p, v); }, (s) => { return s.m_params[0].angularSleepingThreshold; }, (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].angularSleepingThreshold, p, l, v); }, - (s,o,v) => { BulletSimAPI.SetSleepingThresholds2(o.BSBody.ptr, v, v); } ), + (s,o,v) => { BulletSimAPI.SetSleepingThresholds2(o.PhysBody.ptr, v, v); } ), new ParameterDefn("CcdMotionThreshold", "Continuious collision detection threshold (0 means no CCD)" , 0f, // set to zero to disable (s,cf,p,v) => { s.m_params[0].ccdMotionThreshold = cf.GetFloat(p, v); }, (s) => { return s.m_params[0].ccdMotionThreshold; }, (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].ccdMotionThreshold, p, l, v); }, - (s,o,v) => { BulletSimAPI.SetCcdMotionThreshold2(o.BSBody.ptr, v); } ), + (s,o,v) => { BulletSimAPI.SetCcdMotionThreshold2(o.PhysBody.ptr, v); } ), new ParameterDefn("CcdSweptSphereRadius", "Continuious collision detection test radius" , 0f, (s,cf,p,v) => { s.m_params[0].ccdSweptSphereRadius = cf.GetFloat(p, v); }, (s) => { return s.m_params[0].ccdSweptSphereRadius; }, (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].ccdSweptSphereRadius, p, l, v); }, - (s,o,v) => { BulletSimAPI.SetCcdSweptSphereRadius2(o.BSBody.ptr, v); } ), + (s,o,v) => { BulletSimAPI.SetCcdSweptSphereRadius2(o.PhysBody.ptr, v); } ), new ParameterDefn("ContactProcessingThreshold", "Distance between contacts before doing collision check" , 0.1f, (s,cf,p,v) => { s.m_params[0].contactProcessingThreshold = cf.GetFloat(p, v); }, (s) => { return s.m_params[0].contactProcessingThreshold; }, (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].contactProcessingThreshold, p, l, v); }, - (s,o,v) => { BulletSimAPI.SetContactProcessingThreshold2(o.BSBody.ptr, v); } ), + (s,o,v) => { BulletSimAPI.SetContactProcessingThreshold2(o.PhysBody.ptr, v); } ), new ParameterDefn("TerrainFriction", "Factor to reduce movement against terrain surface" , 0.5f, @@ -1428,8 +1428,8 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters { foreach (BSPrim prim in m_vehicles) { - BulletSimAPI.DumpRigidBody2(World.ptr, prim.BSBody.ptr); - BulletSimAPI.DumpCollisionShape2(World.ptr, prim.BSShape.ptr); + BulletSimAPI.DumpRigidBody2(World.ptr, prim.PhysBody.ptr); + BulletSimAPI.DumpCollisionShape2(World.ptr, prim.PhysShape.ptr); } } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs index 1219fc0..a38e650 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs @@ -106,11 +106,11 @@ public sealed class BSShapeCollection : IDisposable // rebuild the body around it. // Updates prim.BSBody with information/pointers to requested body bool newBody = CreateBody((newGeom || forceRebuild), prim, PhysicsScene.World, - prim.BSShape, shapeData, bodyCallback); + prim.PhysShape, shapeData, bodyCallback); ret = newGeom || newBody; } DetailLog("{0},BSShapeCollection.GetBodyAndShape,taintExit,force={1},ret={2},body={3},shape={4}", - prim.LocalID, forceRebuild, ret, prim.BSBody, prim.BSShape); + prim.LocalID, forceRebuild, ret, prim.PhysBody, prim.PhysShape); return ret; } @@ -337,7 +337,7 @@ public sealed class BSShapeCollection : IDisposable // an avatar capsule is close to a native shape (it is not shared) ret = GetReferenceToNativeShape(prim, shapeData, ShapeData.PhysicsShapeType.SHAPE_AVATAR, ShapeData.FixedShapeKey.KEY_CAPSULE, shapeCallback); - DetailLog("{0},BSShapeCollection.CreateGeom,avatarCapsule,shape={1}", prim.LocalID, prim.BSShape); + DetailLog("{0},BSShapeCollection.CreateGeom,avatarCapsule,shape={1}", prim.LocalID, prim.PhysShape); ret = true; haveShape = true; } @@ -360,13 +360,13 @@ public sealed class BSShapeCollection : IDisposable haveShape = true; if (forceRebuild || prim.Scale != shapeData.Size - || prim.BSShape.type != ShapeData.PhysicsShapeType.SHAPE_SPHERE + || prim.PhysShape.type != ShapeData.PhysicsShapeType.SHAPE_SPHERE ) { ret = GetReferenceToNativeShape(prim, shapeData, ShapeData.PhysicsShapeType.SHAPE_SPHERE, ShapeData.FixedShapeKey.KEY_SPHERE, shapeCallback); DetailLog("{0},BSShapeCollection.CreateGeom,sphere,force={1},shape={2}", - prim.LocalID, forceRebuild, prim.BSShape); + prim.LocalID, forceRebuild, prim.PhysShape); } } if (pbs.ProfileShape == ProfileShape.Square && pbs.PathCurve == (byte)Extrusion.Straight) @@ -374,13 +374,13 @@ public sealed class BSShapeCollection : IDisposable haveShape = true; if (forceRebuild || prim.Scale != shapeData.Size - || prim.BSShape.type != ShapeData.PhysicsShapeType.SHAPE_BOX + || prim.PhysShape.type != ShapeData.PhysicsShapeType.SHAPE_BOX ) { ret = GetReferenceToNativeShape( prim, shapeData, ShapeData.PhysicsShapeType.SHAPE_BOX, ShapeData.FixedShapeKey.KEY_BOX, shapeCallback); DetailLog("{0},BSShapeCollection.CreateGeom,box,force={1},shape={2}", - prim.LocalID, forceRebuild, prim.BSShape); + prim.LocalID, forceRebuild, prim.PhysShape); } } } @@ -394,13 +394,13 @@ public sealed class BSShapeCollection : IDisposable // Update prim.BSShape to reference a hull of this shape. ret = GetReferenceToHull(prim, shapeData, pbs, shapeCallback); DetailLog("{0},BSShapeCollection.CreateGeom,hull,shape={1},key={2}", - shapeData.ID, prim.BSShape, prim.BSShape.shapeKey.ToString("X")); + shapeData.ID, prim.PhysShape, prim.PhysShape.shapeKey.ToString("X")); } else { ret = GetReferenceToMesh(prim, shapeData, pbs, shapeCallback); DetailLog("{0},BSShapeCollection.CreateGeom,mesh,shape={1},key={2}", - shapeData.ID, prim.BSShape, prim.BSShape.shapeKey.ToString("X")); + shapeData.ID, prim.PhysShape, prim.PhysShape.shapeKey.ToString("X")); } } return ret; @@ -413,7 +413,7 @@ public sealed class BSShapeCollection : IDisposable ShapeDestructionCallback shapeCallback) { // release any previous shape - DereferenceShape(prim.BSShape, true, shapeCallback); + DereferenceShape(prim.PhysShape, true, shapeCallback); shapeData.Type = shapeType; // Bullet native objects are scaled by the Bullet engine so pass the size in @@ -426,7 +426,7 @@ public sealed class BSShapeCollection : IDisposable DetailLog("{0},BSShapeCollection.AddNativeShapeToPrim,create,newshape={1},scale={2}", shapeData.ID, newShape, shapeData.Scale); - prim.BSShape = newShape; + prim.PhysShape = newShape; return true; } @@ -475,14 +475,14 @@ public sealed class BSShapeCollection : IDisposable System.UInt64 newMeshKey = ComputeShapeKey(shapeData, pbs, out lod); // if this new shape is the same as last time, don't recreate the mesh - if (newMeshKey == prim.BSShape.shapeKey && prim.BSShape.type == ShapeData.PhysicsShapeType.SHAPE_MESH) + if (newMeshKey == prim.PhysShape.shapeKey && prim.PhysShape.type == ShapeData.PhysicsShapeType.SHAPE_MESH) return false; DetailLog("{0},BSShapeCollection.CreateGeomMesh,create,oldKey={1},newKey={2}", - prim.LocalID, prim.BSShape.shapeKey.ToString("X"), newMeshKey.ToString("X")); + prim.LocalID, prim.PhysShape.shapeKey.ToString("X"), newMeshKey.ToString("X")); // Since we're recreating new, get rid of the reference to the previous shape - DereferenceShape(prim.BSShape, true, shapeCallback); + DereferenceShape(prim.PhysShape, true, shapeCallback); newShape = CreatePhysicalMesh(prim.PhysObjectName, newMeshKey, pbs, shapeData.Size, lod); // Take evasive action if the mesh was not constructed. @@ -492,7 +492,7 @@ public sealed class BSShapeCollection : IDisposable // meshes are already scaled by the meshmerizer prim.Scale = new OMV.Vector3(1f, 1f, 1f); - prim.BSShape = newShape; + prim.PhysShape = newShape; return true; // 'true' means a new shape has been added to this prim } @@ -550,14 +550,14 @@ public sealed class BSShapeCollection : IDisposable System.UInt64 newHullKey = ComputeShapeKey(shapeData, pbs, out lod); // if the hull hasn't changed, don't rebuild it - if (newHullKey == prim.BSShape.shapeKey && prim.BSShape.type == ShapeData.PhysicsShapeType.SHAPE_HULL) + if (newHullKey == prim.PhysShape.shapeKey && prim.PhysShape.type == ShapeData.PhysicsShapeType.SHAPE_HULL) return false; DetailLog("{0},BSShapeCollection.CreateGeomHull,create,oldKey={1},newKey={2}", - prim.LocalID, prim.BSShape.shapeKey.ToString("X"), newHullKey.ToString("X")); + prim.LocalID, prim.PhysShape.shapeKey.ToString("X"), newHullKey.ToString("X")); // Remove usage of the previous shape. - DereferenceShape(prim.BSShape, true, shapeCallback); + DereferenceShape(prim.PhysShape, true, shapeCallback); newShape = CreatePhysicalHull(prim.PhysObjectName, newHullKey, pbs, shapeData.Size, lod); newShape = VerifyMeshCreated(newShape, prim, shapeData, pbs); @@ -566,7 +566,7 @@ public sealed class BSShapeCollection : IDisposable // hulls are already scaled by the meshmerizer prim.Scale = new OMV.Vector3(1f, 1f, 1f); - prim.BSShape = newShape; + prim.PhysShape = newShape; return true; // 'true' means a new shape has been added to this prim } @@ -778,13 +778,13 @@ public sealed class BSShapeCollection : IDisposable bool ret = false; // the mesh, hull or native shape must have already been created in Bullet - bool mustRebuild = (prim.BSBody.ptr == IntPtr.Zero); + bool mustRebuild = (prim.PhysBody.ptr == IntPtr.Zero); // If there is an existing body, verify it's of an acceptable type. // If not a solid object, body is a GhostObject. Otherwise a RigidBody. if (!mustRebuild) { - CollisionObjectTypes bodyType = (CollisionObjectTypes)BulletSimAPI.GetBodyType2(prim.BSBody.ptr); + CollisionObjectTypes bodyType = (CollisionObjectTypes)BulletSimAPI.GetBodyType2(prim.PhysBody.ptr); if (prim.IsSolid && bodyType != CollisionObjectTypes.CO_RIGID_BODY || !prim.IsSolid && bodyType != CollisionObjectTypes.CO_GHOST_OBJECT) { @@ -796,7 +796,7 @@ public sealed class BSShapeCollection : IDisposable if (mustRebuild || forceRebuild) { // Free any old body - DereferenceBody(prim.BSBody, true, bodyCallback); + DereferenceBody(prim.PhysBody, true, bodyCallback); BulletBody aBody; IntPtr bodyPtr = IntPtr.Zero; @@ -816,7 +816,7 @@ public sealed class BSShapeCollection : IDisposable ReferenceBody(aBody, true); - prim.BSBody = aBody; + prim.PhysBody = aBody; ret = true; } -- cgit v1.1 From 39c02dcc8c537d5989238ec97c876e033895a8a9 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Thu, 1 Nov 2012 10:23:37 -0700 Subject: BulletSim: Remove use of shapeData in ShapeCollection and rely on the available BSPhysObject varaiables. Fix line endings in BSLinksetCompound. --- .../Region/Physics/BulletSPlugin/BSCharacter.cs | 19 +- OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs | 5 + .../Physics/BulletSPlugin/BSLinksetCompound.cs | 347 +++++++++++---------- .../Region/Physics/BulletSPlugin/BSPhysObject.cs | 4 + OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | 30 +- .../Physics/BulletSPlugin/BSShapeCollection.cs | 116 +++---- .../Region/Physics/BulletSPlugin/BulletSimAPI.cs | 1 + 7 files changed, 256 insertions(+), 266 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs index 8c7061d..2a634b9 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs @@ -99,26 +99,12 @@ public sealed class BSCharacter : BSPhysObject DetailLog("{0},BSCharacter.create,call,size={1},scale={2},density={3},volume={4},mass={5}", LocalID, _size, Scale, _avatarDensity, _avatarVolume, MassRaw); - ShapeData shapeData = new ShapeData(); - shapeData.ID = LocalID; - shapeData.Type = ShapeData.PhysicsShapeType.SHAPE_AVATAR; - shapeData.Position = _position; - shapeData.Rotation = _orientation; - shapeData.Velocity = _velocity; - shapeData.Size = Scale; // capsule is a native shape but scale is not just <1,1,1> - shapeData.Scale = Scale; - shapeData.Mass = _mass; - shapeData.Buoyancy = _buoyancy; - shapeData.Static = ShapeData.numericFalse; - shapeData.Friction = PhysicsScene.Params.avatarStandingFriction; - shapeData.Restitution = PhysicsScene.Params.avatarRestitution; - // do actual create at taint time PhysicsScene.TaintedObject("BSCharacter.create", delegate() { DetailLog("{0},BSCharacter.create,taint", LocalID); // New body and shape into BSBody and BSShape - PhysicsScene.Shapes.GetBodyAndShape(true, PhysicsScene.World, this, shapeData, null, null, null); + PhysicsScene.Shapes.GetBodyAndShape(true, PhysicsScene.World, this, null, null); SetPhysicalProperties(); }); @@ -212,6 +198,9 @@ public sealed class BSCharacter : BSPhysObject { set { BaseShape = value; } } + // I want the physics engine to make an avatar capsule + public override ShapeData.PhysicsShapeType PreferredPhysicalShape + { get { return ShapeData.PhysicsShapeType.SHAPE_AVATAR; } } public override bool Grabbed { set { _grabbed = value; } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs index 525ec28..f56851f 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs @@ -68,6 +68,11 @@ public abstract class BSLinkset // to the physical representation is done via the tainting mechenism. protected object m_linksetActivityLock = new Object(); + // Some linksets have a preferred physical shape. + // Returns SHAPE_UNKNOWN if there is no preference. + public virtual ShapeData.PhysicsShapeType PreferredPhysicalShape + { get { return ShapeData.PhysicsShapeType.SHAPE_UNKNOWN; } } + // We keep the prim's mass in the linkset structure since it could be dependent on other prims protected float m_mass; public float LinksetMass diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs index 1c569b5..638fae1 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs @@ -1,173 +1,176 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyrightD - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -using System; -using System.Collections.Generic; -using System.Text; - -using OMV = OpenMetaverse; - -namespace OpenSim.Region.Physics.BulletSPlugin -{ -public sealed class BSLinksetCompound : BSLinkset -{ - // private static string LogHeader = "[BULLETSIM LINKSET CONSTRAINTS]"; - - public BSLinksetCompound(BSScene scene, BSPhysObject parent) - { - base.Initialize(scene, parent); - } - - // When physical properties are changed the linkset needs to recalculate - // its internal properties. - // This is queued in the 'post taint' queue so the - // refresh will happen once after all the other taints are applied. - public override void Refresh(BSPhysObject requestor) - { - // Queue to happen after all the other taint processing - PhysicsScene.PostTaintObject("BSLinksetcompound.Refresh", requestor.LocalID, delegate() - { - if (HasAnyChildren && IsRoot(requestor)) - RecomputeLinksetCompound(); - }); - } - - // The object is going dynamic (physical). Do any setup necessary - // for a dynamic linkset. - // Only the state of the passed object can be modified. The rest of the linkset - // has not yet been fully constructed. - // Return 'true' if any properties updated on the passed object. - // Called at taint-time! - public override bool MakeDynamic(BSPhysObject child) - { - // What is done for each object in BSPrim is what we want. - return false; - } - - // The object is going static (non-physical). Do any setup necessary for a static linkset. - // Return 'true' if any properties updated on the passed object. - // This doesn't normally happen -- OpenSim removes the objects from the physical - // world if it is a static linkset. - // Called at taint-time! - public override bool MakeStatic(BSPhysObject child) - { - // What is done for each object in BSPrim is what we want. - return false; - } - - // Called at taint-time!! - public override void UpdateProperties(BSPhysObject updated) - { - // Nothing to do for constraints on property updates - } - - // Routine called when rebuilding the body of some member of the linkset. - // Destroy all the constraints have have been made to root and set - // up to rebuild the constraints before the next simulation step. - // Returns 'true' of something was actually removed and would need restoring - // Called at taint-time!! - public override bool RemoveBodyDependencies(BSPrim child) - { - bool ret = false; - - DetailLog("{0},BSLinksetcompound.RemoveBodyDependencies,removeChildrenForRoot,rID={1},rBody={2}", - child.LocalID, LinksetRoot.LocalID, LinksetRoot.PhysBody.ptr.ToString("X")); - - // Cause the current shape to be freed and the new one to be built. - Refresh(LinksetRoot); - - return ret; - } - - // Companion to RemoveBodyDependencies(). If RemoveBodyDependencies() returns 'true', - // this routine will restore the removed constraints. - // Called at taint-time!! - public override void RestoreBodyDependencies(BSPrim child) - { - // The Refresh operation queued by RemoveBodyDependencies() will build any missing constraints. - } - - // ================================================================ - - // Add a new child to the linkset. - // Called while LinkActivity is locked. - protected override void AddChildToLinkset(BSPhysObject child) - { - if (!HasChild(child)) - { - m_children.Add(child); - - DetailLog("{0},BSLinksetCompound.AddChildToLinkset,call,child={1}", LinksetRoot.LocalID, child.LocalID); - - // Cause constraints and assorted properties to be recomputed before the next simulation step. - Refresh(LinksetRoot); - } - return; - } - - // Remove the specified child from the linkset. - // Safe to call even if the child is not really in my linkset. - protected override void RemoveChildFromLinkset(BSPhysObject child) - { - if (m_children.Remove(child)) - { - DetailLog("{0},BSLinksetCompound.RemoveChildFromLinkset,call,rID={1},rBody={2},cID={3},cBody={4}", - child.LocalID, - LinksetRoot.LocalID, LinksetRoot.PhysBody.ptr.ToString("X"), - child.LocalID, child.PhysBody.ptr.ToString("X")); - - // See that the linkset parameters are recomputed at the end of the taint time. - Refresh(LinksetRoot); - } - else - { - // Non-fatal occurance. - // PhysicsScene.Logger.ErrorFormat("{0}: Asked to remove child from linkset that was not in linkset", LogHeader); - } - return; - } - - - // Call each of the constraints that make up this linkset and recompute the - // various transforms and variables. Create constraints of not created yet. - // Called before the simulation step to make sure the constraint based linkset - // is all initialized. - // Called at taint time!! - private void RecomputeLinksetCompound() - { - float linksetMass = LinksetMass; - LinksetRoot.UpdatePhysicalMassProperties(linksetMass); - - // DEBUG: see of inter-linkset collisions are causing problems - // BulletSimAPI.SetCollisionFilterMask2(LinksetRoot.BSBody.ptr, - // (uint)CollisionFilterGroups.LinksetFilter, (uint)CollisionFilterGroups.LinksetMask); - DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,set,rBody={1},linksetMass={2}", - LinksetRoot.LocalID, LinksetRoot.PhysBody.ptr.ToString("X"), linksetMass); - - - } -} +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyrightD + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +using System; +using System.Collections.Generic; +using System.Text; + +using OMV = OpenMetaverse; + +namespace OpenSim.Region.Physics.BulletSPlugin +{ +public sealed class BSLinksetCompound : BSLinkset +{ + // private static string LogHeader = "[BULLETSIM LINKSET CONSTRAINTS]"; + + public BSLinksetCompound(BSScene scene, BSPhysObject parent) + { + base.Initialize(scene, parent); + } + + // When physical properties are changed the linkset needs to recalculate + // its internal properties. + // This is queued in the 'post taint' queue so the + // refresh will happen once after all the other taints are applied. + public override void Refresh(BSPhysObject requestor) + { + // Queue to happen after all the other taint processing + PhysicsScene.PostTaintObject("BSLinksetcompound.Refresh", requestor.LocalID, delegate() + { + if (HasAnyChildren && IsRoot(requestor)) + RecomputeLinksetCompound(); + }); + } + + // The object is going dynamic (physical). Do any setup necessary + // for a dynamic linkset. + // Only the state of the passed object can be modified. The rest of the linkset + // has not yet been fully constructed. + // Return 'true' if any properties updated on the passed object. + // Called at taint-time! + public override bool MakeDynamic(BSPhysObject child) + { + // What is done for each object in BSPrim is what we want. + return false; + } + + // The object is going static (non-physical). Do any setup necessary for a static linkset. + // Return 'true' if any properties updated on the passed object. + // This doesn't normally happen -- OpenSim removes the objects from the physical + // world if it is a static linkset. + // Called at taint-time! + public override bool MakeStatic(BSPhysObject child) + { + // What is done for each object in BSPrim is what we want. + return false; + } + + // Called at taint-time!! + public override void UpdateProperties(BSPhysObject updated) + { + // Nothing to do for constraints on property updates + } + + // Routine called when rebuilding the body of some member of the linkset. + // Destroy all the constraints have have been made to root and set + // up to rebuild the constraints before the next simulation step. + // Returns 'true' of something was actually removed and would need restoring + // Called at taint-time!! + public override bool RemoveBodyDependencies(BSPrim child) + { + bool ret = false; + + DetailLog("{0},BSLinksetcompound.RemoveBodyDependencies,removeChildrenForRoot,rID={1},rBody={2}", + child.LocalID, LinksetRoot.LocalID, LinksetRoot.PhysBody.ptr.ToString("X")); + + // Cause the current shape to be freed and the new one to be built. + Refresh(LinksetRoot); + + return ret; + } + + // Companion to RemoveBodyDependencies(). If RemoveBodyDependencies() returns 'true', + // this routine will restore the removed constraints. + // Called at taint-time!! + public override void RestoreBodyDependencies(BSPrim child) + { + // The Refresh operation queued by RemoveBodyDependencies() will build any missing constraints. + } + + // ================================================================ + + // Add a new child to the linkset. + // Called while LinkActivity is locked. + protected override void AddChildToLinkset(BSPhysObject child) + { + if (!HasChild(child)) + { + m_children.Add(child); + + DetailLog("{0},BSLinksetCompound.AddChildToLinkset,call,child={1}", LinksetRoot.LocalID, child.LocalID); + + // Cause constraints and assorted properties to be recomputed before the next simulation step. + Refresh(LinksetRoot); + } + return; + } + + // Remove the specified child from the linkset. + // Safe to call even if the child is not really in my linkset. + protected override void RemoveChildFromLinkset(BSPhysObject child) + { + if (m_children.Remove(child)) + { + DetailLog("{0},BSLinksetCompound.RemoveChildFromLinkset,call,rID={1},rBody={2},cID={3},cBody={4}", + child.LocalID, + LinksetRoot.LocalID, LinksetRoot.PhysBody.ptr.ToString("X"), + child.LocalID, child.PhysBody.ptr.ToString("X")); + + // See that the linkset parameters are recomputed at the end of the taint time. + Refresh(LinksetRoot); + } + else + { + // Non-fatal occurance. + // PhysicsScene.Logger.ErrorFormat("{0}: Asked to remove child from linkset that was not in linkset", LogHeader); + } + return; + } + + + // Call each of the constraints that make up this linkset and recompute the + // various transforms and variables. Create constraints of not created yet. + // Called before the simulation step to make sure the constraint based linkset + // is all initialized. + // Called at taint time!! + private void RecomputeLinksetCompound() + { + // Release the existing shape + PhysicsScene.Shapes.DereferenceShape(LinksetRoot.PhysShape, true, null); + + float linksetMass = LinksetMass; + LinksetRoot.UpdatePhysicalMassProperties(linksetMass); + + // DEBUG: see of inter-linkset collisions are causing problems + // BulletSimAPI.SetCollisionFilterMask2(LinksetRoot.BSBody.ptr, + // (uint)CollisionFilterGroups.LinksetFilter, (uint)CollisionFilterGroups.LinksetMask); + DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,set,rBody={1},linksetMass={2}", + LinksetRoot.LocalID, LinksetRoot.PhysBody.ptr.ToString("X"), linksetMass); + + + } +} } \ No newline at end of file diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs index 6220b21..7d91468 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs @@ -78,6 +78,10 @@ public abstract class BSPhysObject : PhysicsActor // The objects base shape information. Null if not a prim type shape. public PrimitiveBaseShape BaseShape { get; protected set; } + // Some types of objects have preferred physical representations. + // Returns SHAPE_UNKNOWN if there is no preference. + public virtual ShapeData.PhysicsShapeType PreferredPhysicalShape + { get { return ShapeData.PhysicsShapeType.SHAPE_UNKNOWN; } } // When the physical properties are updated, an EntityProperty holds the update values. // Keep the current and last EntityProperties to enable computation of differences diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index 8dd48ca..8ce960d 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs @@ -171,6 +171,10 @@ public sealed class BSPrim : BSPhysObject ForceBodyShapeRebuild(false); } } + // Whatever the linkset wants is what I want. + public override ShapeData.PhysicsShapeType PreferredPhysicalShape + { get { return Linkset.PreferredPhysicalShape; } } + public override bool ForceBodyShapeRebuild(bool inTaintTime) { LastAssetBuildFailed = false; @@ -1310,34 +1314,11 @@ public sealed class BSPrim : BSPhysObject }// end CalculateMass #endregion Mass Calculation - // Copy prim's info into the BulletSim shape description structure - public void FillShapeInfo(out ShapeData shape) - { - shape.ID = LocalID; - shape.Type = ShapeData.PhysicsShapeType.SHAPE_UNKNOWN; - shape.Position = _position; - shape.Rotation = _orientation; - shape.Velocity = _velocity; - shape.Size = _size; - shape.Scale = Scale; - shape.Mass = _isPhysical ? _mass : 0f; - shape.Buoyancy = _buoyancy; - shape.HullKey = 0; - shape.MeshKey = 0; - shape.Friction = _friction; - shape.Restitution = _restitution; - shape.Collidable = (!IsPhantom) ? ShapeData.numericTrue : ShapeData.numericFalse; - shape.Static = _isPhysical ? ShapeData.numericFalse : ShapeData.numericTrue; - shape.Solid = IsSolid ? ShapeData.numericFalse : ShapeData.numericTrue; - } // Rebuild the geometry and object. // This is called when the shape changes so we need to recreate the mesh/hull. // Called at taint-time!!! private void CreateGeomAndObject(bool forceRebuild) { - ShapeData shapeData; - FillShapeInfo(out shapeData); - // If this prim is part of a linkset, we must remove and restore the physical // links if the body is rebuilt. bool needToRestoreLinkset = false; @@ -1346,8 +1327,7 @@ public sealed class BSPrim : BSPhysObject // Updates BSBody and BSShape with the new information. // Ignore 'forceRebuild'. This routine makes the right choices and changes of necessary. // Returns 'true' if either the body or the shape was changed. - PhysicsScene.Shapes.GetBodyAndShape(false, PhysicsScene.World, this, shapeData, BaseShape, - null, delegate(BulletBody dBody) + PhysicsScene.Shapes.GetBodyAndShape(false, PhysicsScene.World, this, null, delegate(BulletBody dBody) { // Called if the current prim body is about to be destroyed. // Remove all the physical dependencies on the old body. diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs index a38e650..478924a 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs @@ -90,7 +90,6 @@ public sealed class BSShapeCollection : IDisposable // remove the physical constraints before the body is destroyed. // Called at taint-time!! public bool GetBodyAndShape(bool forceRebuild, BulletSim sim, BSPhysObject prim, - ShapeData shapeData, PrimitiveBaseShape pbs, ShapeDestructionCallback shapeCallback, BodyDestructionCallback bodyCallback) { bool ret = false; @@ -101,12 +100,12 @@ public sealed class BSShapeCollection : IDisposable // Do we have the correct geometry for this type of object? // Updates prim.BSShape with information/pointers to shape. // CreateGeom returns 'true' of BSShape as changed to a new shape. - bool newGeom = CreateGeom(forceRebuild, prim, shapeData, pbs, shapeCallback); + bool newGeom = CreateGeom(forceRebuild, prim, shapeCallback); // If we had to select a new shape geometry for the object, // rebuild the body around it. // Updates prim.BSBody with information/pointers to requested body bool newBody = CreateBody((newGeom || forceRebuild), prim, PhysicsScene.World, - prim.PhysShape, shapeData, bodyCallback); + prim.PhysShape, bodyCallback); ret = newGeom || newBody; } DetailLog("{0},BSShapeCollection.GetBodyAndShape,taintExit,force={1},ret={2},body={3},shape={4}", @@ -261,6 +260,9 @@ public sealed class BSShapeCollection : IDisposable case ShapeData.PhysicsShapeType.SHAPE_MESH: DereferenceMesh(shape, shapeCallback); break; + case ShapeData.PhysicsShapeType.SHAPE_COMPOUND: + DereferenceCompound(shape, shapeCallback); + break; case ShapeData.PhysicsShapeType.SHAPE_UNKNOWN: break; default: @@ -317,6 +319,13 @@ public sealed class BSShapeCollection : IDisposable } } + // Remove a reference to a compound shape. + // Called at taint-time. + private void DereferenceCompound(BulletShape shape, ShapeDestructionCallback shapeCallback) + { + // Compound shape is made of a bunch of meshes and natives. + } + // Create the geometry information in Bullet for later use. // The objects needs a hull if it's physical otherwise a mesh is enough. // if 'forceRebuild' is true, the geometry is unconditionally rebuilt. For meshes and hulls, @@ -325,17 +334,17 @@ public sealed class BSShapeCollection : IDisposable // Info in prim.BSShape is updated to the new shape. // Returns 'true' if the geometry was rebuilt. // Called at taint-time! - private bool CreateGeom(bool forceRebuild, BSPhysObject prim, ShapeData shapeData, - PrimitiveBaseShape pbs, ShapeDestructionCallback shapeCallback) + private bool CreateGeom(bool forceRebuild, BSPhysObject prim, ShapeDestructionCallback shapeCallback) { bool ret = false; bool haveShape = false; bool nativeShapePossible = true; + PrimitiveBaseShape pbs = prim.BaseShape; - if (shapeData.Type == ShapeData.PhysicsShapeType.SHAPE_AVATAR) + if (prim.PreferredPhysicalShape == ShapeData.PhysicsShapeType.SHAPE_AVATAR) { // an avatar capsule is close to a native shape (it is not shared) - ret = GetReferenceToNativeShape(prim, shapeData, ShapeData.PhysicsShapeType.SHAPE_AVATAR, + ret = GetReferenceToNativeShape(prim, ShapeData.PhysicsShapeType.SHAPE_AVATAR, ShapeData.FixedShapeKey.KEY_CAPSULE, shapeCallback); DetailLog("{0},BSShapeCollection.CreateGeom,avatarCapsule,shape={1}", prim.LocalID, prim.PhysShape); ret = true; @@ -359,11 +368,11 @@ public sealed class BSShapeCollection : IDisposable { haveShape = true; if (forceRebuild - || prim.Scale != shapeData.Size + || prim.Scale != prim.Size || prim.PhysShape.type != ShapeData.PhysicsShapeType.SHAPE_SPHERE ) { - ret = GetReferenceToNativeShape(prim, shapeData, ShapeData.PhysicsShapeType.SHAPE_SPHERE, + ret = GetReferenceToNativeShape(prim, ShapeData.PhysicsShapeType.SHAPE_SPHERE, ShapeData.FixedShapeKey.KEY_SPHERE, shapeCallback); DetailLog("{0},BSShapeCollection.CreateGeom,sphere,force={1},shape={2}", prim.LocalID, forceRebuild, prim.PhysShape); @@ -373,11 +382,11 @@ public sealed class BSShapeCollection : IDisposable { haveShape = true; if (forceRebuild - || prim.Scale != shapeData.Size + || prim.Scale != prim.Size || prim.PhysShape.type != ShapeData.PhysicsShapeType.SHAPE_BOX ) { - ret = GetReferenceToNativeShape( prim, shapeData, ShapeData.PhysicsShapeType.SHAPE_BOX, + ret = GetReferenceToNativeShape( prim, ShapeData.PhysicsShapeType.SHAPE_BOX, ShapeData.FixedShapeKey.KEY_BOX, shapeCallback); DetailLog("{0},BSShapeCollection.CreateGeom,box,force={1},shape={2}", prim.LocalID, forceRebuild, prim.PhysShape); @@ -392,15 +401,15 @@ public sealed class BSShapeCollection : IDisposable if (prim.IsPhysical && PhysicsScene.ShouldUseHullsForPhysicalObjects) { // Update prim.BSShape to reference a hull of this shape. - ret = GetReferenceToHull(prim, shapeData, pbs, shapeCallback); + ret = GetReferenceToHull(prim,shapeCallback); DetailLog("{0},BSShapeCollection.CreateGeom,hull,shape={1},key={2}", - shapeData.ID, prim.PhysShape, prim.PhysShape.shapeKey.ToString("X")); + prim.LocalID, prim.PhysShape, prim.PhysShape.shapeKey.ToString("X")); } else { - ret = GetReferenceToMesh(prim, shapeData, pbs, shapeCallback); + ret = GetReferenceToMesh(prim, shapeCallback); DetailLog("{0},BSShapeCollection.CreateGeom,mesh,shape={1},key={2}", - shapeData.ID, prim.PhysShape, prim.PhysShape.shapeKey.ToString("X")); + prim.LocalID, prim.PhysShape, prim.PhysShape.shapeKey.ToString("X")); } } return ret; @@ -408,44 +417,45 @@ public sealed class BSShapeCollection : IDisposable // Creates a native shape and assignes it to prim.BSShape. // "Native" shapes are never shared. they are created here and destroyed in DereferenceShape(). - private bool GetReferenceToNativeShape(BSPhysObject prim, ShapeData shapeData, + private bool GetReferenceToNativeShape(BSPhysObject prim, ShapeData.PhysicsShapeType shapeType, ShapeData.FixedShapeKey shapeKey, ShapeDestructionCallback shapeCallback) { // release any previous shape DereferenceShape(prim.PhysShape, true, shapeCallback); - shapeData.Type = shapeType; // Bullet native objects are scaled by the Bullet engine so pass the size in - prim.Scale = shapeData.Size; - shapeData.Scale = shapeData.Size; + prim.Scale = prim.Size; - BulletShape newShape = BuildPhysicalNativeShape(shapeType, shapeData, shapeKey); + BulletShape newShape = BuildPhysicalNativeShape(prim, shapeType, shapeKey); // Don't need to do a 'ReferenceShape()' here because native shapes are not shared. DetailLog("{0},BSShapeCollection.AddNativeShapeToPrim,create,newshape={1},scale={2}", - shapeData.ID, newShape, shapeData.Scale); + prim.LocalID, newShape, prim.Scale); prim.PhysShape = newShape; return true; } - private BulletShape BuildPhysicalNativeShape(ShapeData.PhysicsShapeType shapeType, - ShapeData shapeData, ShapeData.FixedShapeKey shapeKey) + private BulletShape BuildPhysicalNativeShape(BSPhysObject prim, ShapeData.PhysicsShapeType shapeType, + ShapeData.FixedShapeKey shapeKey) { BulletShape newShape; // Need to make sure the passed shape information is for the native type. - ShapeData nativeShapeData = shapeData; + ShapeData nativeShapeData = new ShapeData(); nativeShapeData.Type = shapeType; + nativeShapeData.ID = prim.LocalID; + nativeShapeData.Scale = prim.Scale; + nativeShapeData.Size = prim.Scale; nativeShapeData.MeshKey = (ulong)shapeKey; nativeShapeData.HullKey = (ulong)shapeKey; if (shapeType == ShapeData.PhysicsShapeType.SHAPE_AVATAR) { newShape = new BulletShape( - BulletSimAPI.BuildCapsuleShape2(PhysicsScene.World.ptr, 1f, 1f, nativeShapeData.Scale) + BulletSimAPI.BuildCapsuleShape2(PhysicsScene.World.ptr, 1f, 1f, prim.Scale) , shapeType); - DetailLog("{0},BSShapeCollection.BuiletPhysicalNativeShape,capsule,scale={1}", nativeShapeData.ID, nativeShapeData.Scale); + DetailLog("{0},BSShapeCollection.BuiletPhysicalNativeShape,capsule,scale={1}", prim.LocalID, prim.Scale); } else { @@ -454,7 +464,7 @@ public sealed class BSShapeCollection : IDisposable if (newShape.ptr == IntPtr.Zero) { PhysicsScene.Logger.ErrorFormat("{0} BuildPhysicalNativeShape failed. ID={1}, shape={2}", - LogHeader, nativeShapeData.ID, nativeShapeData.Type); + LogHeader, prim.LocalID, shapeType); } newShape.shapeKey = (System.UInt64)shapeKey; newShape.isNativeShape = true; @@ -466,13 +476,12 @@ public sealed class BSShapeCollection : IDisposable // Dereferences previous shape in BSShape and adds a reference for this new shape. // Returns 'true' of a mesh was actually built. Otherwise . // Called at taint-time! - private bool GetReferenceToMesh(BSPhysObject prim, ShapeData shapeData, PrimitiveBaseShape pbs, - ShapeDestructionCallback shapeCallback) + private bool GetReferenceToMesh(BSPhysObject prim, ShapeDestructionCallback shapeCallback) { BulletShape newShape = new BulletShape(IntPtr.Zero); float lod; - System.UInt64 newMeshKey = ComputeShapeKey(shapeData, pbs, out lod); + System.UInt64 newMeshKey = ComputeShapeKey(prim.Size, prim.BaseShape, out lod); // if this new shape is the same as last time, don't recreate the mesh if (newMeshKey == prim.PhysShape.shapeKey && prim.PhysShape.type == ShapeData.PhysicsShapeType.SHAPE_MESH) @@ -484,9 +493,9 @@ public sealed class BSShapeCollection : IDisposable // Since we're recreating new, get rid of the reference to the previous shape DereferenceShape(prim.PhysShape, true, shapeCallback); - newShape = CreatePhysicalMesh(prim.PhysObjectName, newMeshKey, pbs, shapeData.Size, lod); + newShape = CreatePhysicalMesh(prim.PhysObjectName, newMeshKey, prim.BaseShape, prim.Size, lod); // Take evasive action if the mesh was not constructed. - newShape = VerifyMeshCreated(newShape, prim, shapeData, pbs); + newShape = VerifyMeshCreated(newShape, prim); ReferenceShape(newShape); @@ -541,13 +550,12 @@ public sealed class BSShapeCollection : IDisposable // See that hull shape exists in the physical world and update prim.BSShape. // We could be creating the hull because scale changed or whatever. - private bool GetReferenceToHull(BSPhysObject prim, ShapeData shapeData, PrimitiveBaseShape pbs, - ShapeDestructionCallback shapeCallback) + private bool GetReferenceToHull(BSPhysObject prim, ShapeDestructionCallback shapeCallback) { BulletShape newShape; float lod; - System.UInt64 newHullKey = ComputeShapeKey(shapeData, pbs, out lod); + System.UInt64 newHullKey = ComputeShapeKey(prim.Size, prim.BaseShape, out lod); // if the hull hasn't changed, don't rebuild it if (newHullKey == prim.PhysShape.shapeKey && prim.PhysShape.type == ShapeData.PhysicsShapeType.SHAPE_HULL) @@ -559,8 +567,8 @@ public sealed class BSShapeCollection : IDisposable // Remove usage of the previous shape. DereferenceShape(prim.PhysShape, true, shapeCallback); - newShape = CreatePhysicalHull(prim.PhysObjectName, newHullKey, pbs, shapeData.Size, lod); - newShape = VerifyMeshCreated(newShape, prim, shapeData, pbs); + newShape = CreatePhysicalHull(prim.PhysObjectName, newHullKey, prim.BaseShape, prim.Size, lod); + newShape = VerifyMeshCreated(newShape, prim); ReferenceShape(newShape); @@ -687,7 +695,7 @@ public sealed class BSShapeCollection : IDisposable // Create a hash of all the shape parameters to be used as a key // for this particular shape. - private System.UInt64 ComputeShapeKey(ShapeData shapeData, PrimitiveBaseShape pbs, out float retLod) + private System.UInt64 ComputeShapeKey(OMV.Vector3 size, PrimitiveBaseShape pbs, out float retLod) { // level of detail based on size and type of the object float lod = PhysicsScene.MeshLOD; @@ -695,40 +703,40 @@ public sealed class BSShapeCollection : IDisposable lod = PhysicsScene.SculptLOD; // Mega prims usually get more detail because one can interact with shape approximations at this size. - float maxAxis = Math.Max(shapeData.Size.X, Math.Max(shapeData.Size.Y, shapeData.Size.Z)); + float maxAxis = Math.Max(size.X, Math.Max(size.Y, size.Z)); if (maxAxis > PhysicsScene.MeshMegaPrimThreshold) lod = PhysicsScene.MeshMegaPrimLOD; retLod = lod; - return pbs.GetMeshKey(shapeData.Size, lod); + return pbs.GetMeshKey(size, lod); } // For those who don't want the LOD - private System.UInt64 ComputeShapeKey(ShapeData shapeData, PrimitiveBaseShape pbs) + private System.UInt64 ComputeShapeKey(OMV.Vector3 size, PrimitiveBaseShape pbs) { float lod; - return ComputeShapeKey(shapeData, pbs, out lod); + return ComputeShapeKey(size, pbs, out lod); } // The creation of a mesh or hull can fail if an underlying asset is not available. // There are two cases: 1) the asset is not in the cache and it needs to be fetched; - // and 2) the asset cannot be converted (like decompressing JPEG2000s). - // The first case causes the asset to be fetched. The second case just requires + // and 2) the asset cannot be converted (like failed decompression of JPEG2000s). + // The first case causes the asset to be fetched. The second case requires // us to not loop forever. // Called after creating a physical mesh or hull. If the physical shape was created, // just return. - private BulletShape VerifyMeshCreated(BulletShape newShape, BSPhysObject prim, ShapeData shapeData, PrimitiveBaseShape pbs) + private BulletShape VerifyMeshCreated(BulletShape newShape, BSPhysObject prim) { // If the shape was successfully created, nothing more to do if (newShape.ptr != IntPtr.Zero) return newShape; // If this mesh has an underlying asset and we have not failed getting it before, fetch the asset - if (pbs.SculptEntry && !prim.LastAssetBuildFailed && pbs.SculptTexture != OMV.UUID.Zero) + if (prim.BaseShape.SculptEntry && !prim.LastAssetBuildFailed && prim.BaseShape.SculptTexture != OMV.UUID.Zero) { prim.LastAssetBuildFailed = true; BSPhysObject xprim = prim; DetailLog("{0},BSShapeCollection.VerifyMeshCreated,fetchAsset,lID={1},lastFailed={2}", - LogHeader, shapeData.ID.ToString("X"), prim.LastAssetBuildFailed); + LogHeader, prim.LocalID, prim.LastAssetBuildFailed); Util.FireAndForget(delegate { RequestAssetDelegate assetProvider = PhysicsScene.RequestAssetMethod; @@ -745,7 +753,7 @@ public sealed class BSShapeCollection : IDisposable yprim.BaseShape.SculptData = asset.Data; // This will cause the prim to see that the filler shape is not the right // one and try again to build the object. - // No race condition with the native sphere setting since the rebuild is at taint time. + // No race condition with the normal shape setting since the rebuild is at taint time. yprim.ForceBodyShapeRebuild(false); }); @@ -757,13 +765,13 @@ public sealed class BSShapeCollection : IDisposable if (prim.LastAssetBuildFailed) { PhysicsScene.Logger.ErrorFormat("{0} Mesh failed to fetch asset. lID={1}, texture={2}", - LogHeader, shapeData.ID, pbs.SculptTexture); + LogHeader, prim.LocalID, prim.BaseShape.SculptTexture); } } // While we figure out the real problem, stick a simple native shape on the object. BulletShape fillinShape = - BuildPhysicalNativeShape(ShapeData.PhysicsShapeType.SHAPE_BOX, shapeData, ShapeData.FixedShapeKey.KEY_BOX); + BuildPhysicalNativeShape(prim, ShapeData.PhysicsShapeType.SHAPE_BOX, ShapeData.FixedShapeKey.KEY_BOX); return fillinShape; } @@ -773,7 +781,7 @@ public sealed class BSShapeCollection : IDisposable // Returns 'true' if an object was actually created. // Called at taint-time. private bool CreateBody(bool forceRebuild, BSPhysObject prim, BulletSim sim, BulletShape shape, - ShapeData shapeData, BodyDestructionCallback bodyCallback) + BodyDestructionCallback bodyCallback) { bool ret = false; @@ -803,16 +811,16 @@ public sealed class BSShapeCollection : IDisposable if (prim.IsSolid) { bodyPtr = BulletSimAPI.CreateBodyFromShape2(sim.ptr, shape.ptr, - shapeData.ID, shapeData.Position, shapeData.Rotation); + prim.LocalID, prim.ForcePosition, prim.ForceOrientation); DetailLog("{0},BSShapeCollection.CreateBody,mesh,ptr={1}", prim.LocalID, bodyPtr.ToString("X")); } else { bodyPtr = BulletSimAPI.CreateGhostFromShape2(sim.ptr, shape.ptr, - shapeData.ID, shapeData.Position, shapeData.Rotation); + prim.LocalID, prim.ForcePosition, prim.ForceOrientation); DetailLog("{0},BSShapeCollection.CreateBody,ghost,ptr={1}", prim.LocalID, bodyPtr.ToString("X")); } - aBody = new BulletBody(shapeData.ID, bodyPtr); + aBody = new BulletBody(prim.LocalID, bodyPtr); ReferenceBody(aBody, true); diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs index 9b7ba03..3b6355c 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs @@ -194,6 +194,7 @@ public struct ShapeData // following defined by BulletSim SHAPE_GROUNDPLANE = 20, SHAPE_TERRAIN = 21, + SHAPE_COMPOUND = 22, }; public uint ID; public PhysicsShapeType Type; -- cgit v1.1 From f53b4e7a21f62a84e237c4ce8d2806124c3a76d2 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Thu, 1 Nov 2012 10:53:55 -0700 Subject: BulletSim: Add RawPosition and RawOrientation to BSPhysObject and rename MassRaw to RawMass. Fix BSShapeCollection to use Raw* for creating the body to eliminate exception from referencing the physical body before it has been created. --- OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs | 20 +++++++++++++++----- OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs | 16 ++++++++-------- OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs | 4 +++- OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | 14 ++++++++++++-- .../Physics/BulletSPlugin/BSShapeCollection.cs | 2 +- 5 files changed, 39 insertions(+), 17 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs index 2a634b9..9e1206a 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs @@ -97,7 +97,7 @@ public sealed class BSCharacter : BSPhysObject // set _avatarVolume and _mass based on capsule size, _density and Scale ComputeAvatarVolumeAndMass(); DetailLog("{0},BSCharacter.create,call,size={1},scale={2},density={3},volume={4},mass={5}", - LocalID, _size, Scale, _avatarDensity, _avatarVolume, MassRaw); + LocalID, _size, Scale, _avatarDensity, _avatarVolume, RawMass); // do actual create at taint time PhysicsScene.TaintedObject("BSCharacter.create", delegate() @@ -141,7 +141,7 @@ public sealed class BSCharacter : BSPhysObject BulletSimAPI.SetCcdSweptSphereRadius2(PhysBody.ptr, PhysicsScene.Params.ccdSweptSphereRadius); } - UpdatePhysicalMassProperties(MassRaw); + UpdatePhysicalMassProperties(RawMass); // Make so capsule does not fall over BulletSimAPI.SetAngularFactorV2(PhysBody.ptr, OMV.Vector3.Zero); @@ -181,12 +181,12 @@ public sealed class BSCharacter : BSPhysObject ComputeAvatarScale(_size); ComputeAvatarVolumeAndMass(); DetailLog("{0},BSCharacter.setSize,call,scale={1},density={2},volume={3},mass={4}", - LocalID, Scale, _avatarDensity, _avatarVolume, MassRaw); + LocalID, Scale, _avatarDensity, _avatarVolume, RawMass); PhysicsScene.TaintedObject("BSCharacter.setSize", delegate() { BulletSimAPI.SetLocalScaling2(PhysShape.ptr, Scale); - UpdatePhysicalMassProperties(MassRaw); + UpdatePhysicalMassProperties(RawMass); }); } @@ -231,6 +231,11 @@ public sealed class BSCharacter : BSPhysObject public override void LockAngularMotion(OMV.Vector3 axis) { return; } + public override OMV.Vector3 RawPosition + { + get { return _position; } + set { _position = value; } + } public override OMV.Vector3 Position { get { // _position = BulletSimAPI.GetObjectPosition2(Scene.World.ptr, LocalID); @@ -316,7 +321,7 @@ public sealed class BSCharacter : BSPhysObject public override float Mass { get { return _mass; } } // used when we only want this prim's mass and not the linkset thing - public override float MassRaw { + public override float RawMass { get {return _mass; } } public override void UpdatePhysicalMassProperties(float physMass) @@ -405,6 +410,11 @@ public sealed class BSCharacter : BSPhysObject get { return _acceleration; } set { _acceleration = value; } } + public override OMV.Quaternion RawOrientation + { + get { return _orientation; } + set { _orientation = value; } + } public override OMV.Quaternion Orientation { get { return _orientation; } set { diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs index f56851f..9e0f499 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs @@ -106,7 +106,7 @@ public abstract class BSLinkset PhysicsScene = scene; LinksetRoot = parent; m_children = new HashSet(); - m_mass = parent.MassRaw; + m_mass = parent.RawMass; } // Link to a linkset where the child knows the parent. @@ -242,14 +242,14 @@ public abstract class BSLinkset // ================================================================ protected virtual float ComputeLinksetMass() { - float mass = LinksetRoot.MassRaw; + float mass = LinksetRoot.RawMass; if (HasAnyChildren) { lock (m_linksetActivityLock) { foreach (BSPhysObject bp in m_children) { - mass += bp.MassRaw; + mass += bp.RawMass; } } } @@ -261,13 +261,13 @@ public abstract class BSLinkset OMV.Vector3 com; lock (m_linksetActivityLock) { - com = LinksetRoot.Position * LinksetRoot.MassRaw; - float totalMass = LinksetRoot.MassRaw; + com = LinksetRoot.Position * LinksetRoot.RawMass; + float totalMass = LinksetRoot.RawMass; foreach (BSPhysObject bp in m_children) { - com += bp.Position * bp.MassRaw; - totalMass += bp.MassRaw; + com += bp.Position * bp.RawMass; + totalMass += bp.RawMass; } if (totalMass != 0f) com /= totalMass; @@ -285,7 +285,7 @@ public abstract class BSLinkset foreach (BSPhysObject bp in m_children) { - com += bp.Position * bp.MassRaw; + com += bp.Position * bp.RawMass; } com /= (m_children.Count + 1); } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs index 7d91468..65d7f34 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs @@ -63,7 +63,7 @@ public abstract class BSPhysObject : PhysicsActor public BSLinkset Linkset { get; set; } // Return the object mass without calculating it or having side effects - public abstract float MassRaw { get; } + public abstract float RawMass { get; } // Set the raw mass but also update physical mass properties (inertia, ...) public abstract void UpdatePhysicalMassProperties(float mass); @@ -105,8 +105,10 @@ public abstract class BSPhysObject : PhysicsActor // Tell the object to clean up. public abstract void Destroy(); + public abstract OMV.Vector3 RawPosition { get; set; } public abstract OMV.Vector3 ForcePosition { get; set; } + public abstract OMV.Quaternion RawOrientation { get; set; } public abstract OMV.Quaternion ForceOrientation { get; set; } public abstract OMV.Vector3 ForceVelocity { get; set; } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index 8ce960d..1754be6 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs @@ -256,6 +256,11 @@ public sealed class BSPrim : BSPhysObject return; } + public override OMV.Vector3 RawPosition + { + get { return _position; } + set { _position = value; } + } public override OMV.Vector3 Position { get { if (!Linkset.IsRoot(this)) @@ -366,7 +371,7 @@ public sealed class BSPrim : BSPhysObject } // used when we only want this prim's mass and not the linkset thing - public override float MassRaw { + public override float RawMass { get { return _mass; } } // Set the physical mass to the passed mass. @@ -530,6 +535,11 @@ public sealed class BSPrim : BSPhysObject get { return _acceleration; } set { _acceleration = value; } } + public override OMV.Quaternion RawOrientation + { + get { return _orientation; } + set { _orientation = value; } + } public override OMV.Quaternion Orientation { get { if (!Linkset.IsRoot(this)) @@ -703,7 +713,7 @@ public sealed class BSPrim : BSPhysObject BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation); // A dynamic object has mass - UpdatePhysicalMassProperties(MassRaw); + UpdatePhysicalMassProperties(RawMass); // Set collision detection parameters if (PhysicsScene.Params.ccdMotionThreshold > 0f) diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs index 478924a..e131919 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs @@ -811,7 +811,7 @@ public sealed class BSShapeCollection : IDisposable if (prim.IsSolid) { bodyPtr = BulletSimAPI.CreateBodyFromShape2(sim.ptr, shape.ptr, - prim.LocalID, prim.ForcePosition, prim.ForceOrientation); + prim.LocalID, prim.RawPosition, prim.RawOrientation); DetailLog("{0},BSShapeCollection.CreateBody,mesh,ptr={1}", prim.LocalID, bodyPtr.ToString("X")); } else -- cgit v1.1 From b0eccd5044b1a20b995a62d6fb76fdd73b712f9a Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Fri, 2 Nov 2012 09:53:41 -0700 Subject: BulletSim: debugging of compound shape implementation of linksets. Add compound shape creation and freeing in shape manager. Add optional taint-time execution method and update code to use it. Add API2 linkage for more compound shape methods (get num, get/remove by index, ...) Modify perferred shape return so linkset children can have differet shapes than root. Add Position and Orientation calls to linksets so children can be moved around by the linkset by its own calculation. Allows for very general linkset implementations. --- .../Region/Physics/BulletSPlugin/BSCharacter.cs | 13 +- OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs | 19 ++- .../Physics/BulletSPlugin/BSLinksetCompound.cs | 106 ++++++++++---- .../Physics/BulletSPlugin/BSLinksetConstraints.cs | 12 ++ .../Region/Physics/BulletSPlugin/BSPhysObject.cs | 4 +- OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | 52 +++---- OpenSim/Region/Physics/BulletSPlugin/BSScene.cs | 12 +- .../Physics/BulletSPlugin/BSShapeCollection.cs | 152 ++++++++++++++++----- .../Physics/BulletSPlugin/BSTerrainManager.cs | 21 +-- .../Region/Physics/BulletSPlugin/BulletSimAPI.cs | 15 +- 10 files changed, 274 insertions(+), 132 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs index 9e1206a..2a5397e 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs @@ -200,7 +200,9 @@ public sealed class BSCharacter : BSPhysObject } // I want the physics engine to make an avatar capsule public override ShapeData.PhysicsShapeType PreferredPhysicalShape - { get { return ShapeData.PhysicsShapeType.SHAPE_AVATAR; } } + { + get {return ShapeData.PhysicsShapeType.SHAPE_AVATAR; } + } public override bool Grabbed { set { _grabbed = value; } @@ -238,6 +240,7 @@ public sealed class BSCharacter : BSPhysObject } public override OMV.Vector3 Position { get { + // Don't refetch the position because this function is called a zillion times // _position = BulletSimAPI.GetObjectPosition2(Scene.World.ptr, LocalID); return _position; } @@ -304,15 +307,11 @@ public sealed class BSCharacter : BSPhysObject { // The new position value must be pushed into the physics engine but we can't // just assign to "Position" because of potential call loops. - BSScene.TaintCallback sanityOperation = delegate() + PhysicsScene.TaintedObject(inTaintTime, "BSCharacter.PositionSanityCheck", delegate() { DetailLog("{0},BSCharacter.PositionSanityCheck,taint,pos={1},orient={2}", LocalID, _position, _orientation); BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation); - }; - if (inTaintTime) - sanityOperation(); - else - PhysicsScene.TaintedObject("BSCharacter.PositionSanityCheck", sanityOperation); + }); ret = true; } return ret; diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs index 9e0f499..8f973f4 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs @@ -48,7 +48,8 @@ public abstract class BSLinkset */ // at the moment, there is only one - ret = new BSLinksetConstraints(physScene, parent); + // ret = new BSLinksetConstraints(physScene, parent); + ret = new BSLinksetCompound(physScene, parent); return ret; } @@ -69,10 +70,19 @@ public abstract class BSLinkset protected object m_linksetActivityLock = new Object(); // Some linksets have a preferred physical shape. - // Returns SHAPE_UNKNOWN if there is no preference. - public virtual ShapeData.PhysicsShapeType PreferredPhysicalShape - { get { return ShapeData.PhysicsShapeType.SHAPE_UNKNOWN; } } + // Returns SHAPE_UNKNOWN if there is no preference. Causes the correct shape to be selected. + public virtual ShapeData.PhysicsShapeType PreferredPhysicalShape(BSPhysObject requestor) + { + return ShapeData.PhysicsShapeType.SHAPE_UNKNOWN; + } + // Linksets move around the children so the linkset might need to compute the child position + public virtual OMV.Vector3 Position(BSPhysObject member) + { return member.RawPosition; } + public virtual OMV.Quaternion Orientation(BSPhysObject member) + { return member.RawOrientation; } + // TODO: does this need to be done for Velocity and RotationalVelocityy? + // We keep the prim's mass in the linkset structure since it could be dependent on other prims protected float m_mass; public float LinksetMass @@ -177,7 +187,6 @@ public abstract class BSLinkset } // Perform an action on each member of the linkset including root prim. - // The action is performed only on the objects that are physically in the linkset. // Depends on the action on whether this should be done at taint time. public delegate bool ForEachMemberAction(BSPhysObject obj); public virtual bool ForEachMember(ForEachMemberAction action) diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs index 638fae1..8b97ebb 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs @@ -41,18 +41,31 @@ public sealed class BSLinksetCompound : BSLinkset base.Initialize(scene, parent); } + // For compound implimented linksets, if there are children, use compound shape for the root. + public override ShapeData.PhysicsShapeType PreferredPhysicalShape(BSPhysObject requestor) + { + ShapeData.PhysicsShapeType ret = ShapeData.PhysicsShapeType.SHAPE_UNKNOWN; + if (IsRoot(requestor) && HasAnyChildren) + { + ret = ShapeData.PhysicsShapeType.SHAPE_COMPOUND; + } + // DetailLog("{0},BSLinksetCompound.PreferredPhysicalShape,call,shape={1}", LinksetRoot.LocalID, ret); + return ret; + } + // When physical properties are changed the linkset needs to recalculate // its internal properties. // This is queued in the 'post taint' queue so the // refresh will happen once after all the other taints are applied. public override void Refresh(BSPhysObject requestor) { + DetailLog("{0},BSLinksetCompound.Refresh,schedulingRefresh,requestor={1}", LinksetRoot.LocalID, requestor.LocalID); // Queue to happen after all the other taint processing - PhysicsScene.PostTaintObject("BSLinksetcompound.Refresh", requestor.LocalID, delegate() - { - if (HasAnyChildren && IsRoot(requestor)) - RecomputeLinksetCompound(); - }); + PhysicsScene.PostTaintObject("BSLinksetCompound.Refresh", requestor.LocalID, delegate() + { + if (IsRoot(requestor) && HasAnyChildren) + RecomputeLinksetCompound(); + }); } // The object is going dynamic (physical). Do any setup necessary @@ -63,8 +76,17 @@ public sealed class BSLinksetCompound : BSLinkset // Called at taint-time! public override bool MakeDynamic(BSPhysObject child) { - // What is done for each object in BSPrim is what we want. - return false; + bool ret = false; + DetailLog("{0},BSLinksetCompound.MakeDynamic,call,isChild={1}", child.LocalID, HasChild(child)); + if (HasChild(child)) + { + // Physical children are removed from the world as the shape ofthe root compound + // shape takes over. + BulletSimAPI.AddToCollisionFlags2(child.PhysBody.ptr, CollisionFlags.CF_NO_CONTACT_RESPONSE); + BulletSimAPI.ForceActivationState2(child.PhysBody.ptr, ActivationState.DISABLE_SIMULATION); + ret = true; + } + return ret; } // The object is going static (non-physical). Do any setup necessary for a static linkset. @@ -74,8 +96,17 @@ public sealed class BSLinksetCompound : BSLinkset // Called at taint-time! public override bool MakeStatic(BSPhysObject child) { - // What is done for each object in BSPrim is what we want. - return false; + bool ret = false; + DetailLog("{0},BSLinksetCompound.MakeStatic,call,hasChild={1}", child.LocalID, HasChild(child)); + if (HasChild(child)) + { + // The non-physical children can come back to life. + BulletSimAPI.RemoveFromCollisionFlags2(child.PhysBody.ptr, CollisionFlags.CF_NO_CONTACT_RESPONSE); + // Don't force activation so setting of DISABLE_SIMULATION can stay. + BulletSimAPI.Activate2(child.PhysBody.ptr, false); + ret = true; + } + return ret; } // Called at taint-time!! @@ -84,20 +115,35 @@ public sealed class BSLinksetCompound : BSLinkset // Nothing to do for constraints on property updates } + // The children move around in relationship to the root. + // Just grab the current values of wherever it is right now. + public override OMV.Vector3 Position(BSPhysObject member) + { + return BulletSimAPI.GetPosition2(member.PhysBody.ptr); + } + + public override OMV.Quaternion Orientation(BSPhysObject member) + { + return BulletSimAPI.GetOrientation2(member.PhysBody.ptr); + } + // Routine called when rebuilding the body of some member of the linkset. - // Destroy all the constraints have have been made to root and set - // up to rebuild the constraints before the next simulation step. + // Since we don't keep in-physical world relationships, do nothing unless it's a child changing. // Returns 'true' of something was actually removed and would need restoring // Called at taint-time!! public override bool RemoveBodyDependencies(BSPrim child) { bool ret = false; - DetailLog("{0},BSLinksetcompound.RemoveBodyDependencies,removeChildrenForRoot,rID={1},rBody={2}", - child.LocalID, LinksetRoot.LocalID, LinksetRoot.PhysBody.ptr.ToString("X")); + DetailLog("{0},BSLinksetCompound.RemoveBodyDependencies,removeChildrenForRoot,rID={1},rBody={2},isRoot={3}", + child.LocalID, LinksetRoot.LocalID, LinksetRoot.PhysBody.ptr.ToString("X"), IsRoot(child)); - // Cause the current shape to be freed and the new one to be built. - Refresh(LinksetRoot); + if (!IsRoot(child)) + { + // Cause the current shape to be freed and the new one to be built. + Refresh(LinksetRoot); + ret = true; + } return ret; } @@ -139,13 +185,19 @@ public sealed class BSLinksetCompound : BSLinkset LinksetRoot.LocalID, LinksetRoot.PhysBody.ptr.ToString("X"), child.LocalID, child.PhysBody.ptr.ToString("X")); - // See that the linkset parameters are recomputed at the end of the taint time. - Refresh(LinksetRoot); - } - else - { - // Non-fatal occurance. - // PhysicsScene.Logger.ErrorFormat("{0}: Asked to remove child from linkset that was not in linkset", LogHeader); + // Cause the child's body to be rebuilt and thus restored to normal operation + child.ForceBodyShapeRebuild(false); + + if (!HasAnyChildren) + { + // The linkset is now empty. The root needs rebuilding. + LinksetRoot.ForceBodyShapeRebuild(false); + } + else + { + // Schedule a rebuild of the linkset before the next simulation tick. + Refresh(LinksetRoot); + } } return; } @@ -158,16 +210,18 @@ public sealed class BSLinksetCompound : BSLinkset // Called at taint time!! private void RecomputeLinksetCompound() { - // Release the existing shape - PhysicsScene.Shapes.DereferenceShape(LinksetRoot.PhysShape, true, null); - + DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,start,rBody={1},numChildren={2}", + LinksetRoot.LocalID, LinksetRoot.PhysBody.ptr.ToString("X"), NumberOfChildren); + + LinksetRoot.ForceBodyShapeRebuild(true); + float linksetMass = LinksetMass; LinksetRoot.UpdatePhysicalMassProperties(linksetMass); // DEBUG: see of inter-linkset collisions are causing problems // BulletSimAPI.SetCollisionFilterMask2(LinksetRoot.BSBody.ptr, // (uint)CollisionFilterGroups.LinksetFilter, (uint)CollisionFilterGroups.LinksetMask); - DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,set,rBody={1},linksetMass={2}", + DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,end,rBody={1},linksetMass={2}", LinksetRoot.LocalID, LinksetRoot.PhysBody.ptr.ToString("X"), linksetMass); diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs index 65aed77..67a59ef 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs @@ -84,6 +84,18 @@ public sealed class BSLinksetConstraints : BSLinkset // Nothing to do for constraints on property updates } + // The children of the linkset are moved around by the constraints. + // Just grab the current values of wherever it is right now. + public override OMV.Vector3 Position(BSPhysObject member) + { + return BulletSimAPI.GetPosition2(member.PhysBody.ptr); + } + + public override OMV.Quaternion Orientation(BSPhysObject member) + { + return BulletSimAPI.GetOrientation2(member.PhysBody.ptr); + } + // Routine called when rebuilding the body of some member of the linkset. // Destroy all the constraints have have been made to root and set // up to rebuild the constraints before the next simulation step. diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs index 65d7f34..7127aaf 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs @@ -81,7 +81,9 @@ public abstract class BSPhysObject : PhysicsActor // Some types of objects have preferred physical representations. // Returns SHAPE_UNKNOWN if there is no preference. public virtual ShapeData.PhysicsShapeType PreferredPhysicalShape - { get { return ShapeData.PhysicsShapeType.SHAPE_UNKNOWN; } } + { + get { return ShapeData.PhysicsShapeType.SHAPE_UNKNOWN; } + } // When the physical properties are updated, an EntityProperty holds the update values. // Keep the current and last EntityProperties to enable computation of differences diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index 1754be6..af403aa 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs @@ -173,20 +173,16 @@ public sealed class BSPrim : BSPhysObject } // Whatever the linkset wants is what I want. public override ShapeData.PhysicsShapeType PreferredPhysicalShape - { get { return Linkset.PreferredPhysicalShape; } } + { get { return Linkset.PreferredPhysicalShape(this); } } public override bool ForceBodyShapeRebuild(bool inTaintTime) { LastAssetBuildFailed = false; - BSScene.TaintCallback rebuildOperation = delegate() + PhysicsScene.TaintedObject(inTaintTime, "BSPrim.ForceBodyShapeRebuild", delegate() { _mass = CalculateMass(); // changing the shape changes the mass CreateGeomAndObject(true); - }; - if (inTaintTime) - rebuildOperation(); - else - PhysicsScene.TaintedObject("BSPrim.ForceBodyShapeRebuild", rebuildOperation); + }); return true; } public override bool Grabbed { @@ -263,9 +259,9 @@ public sealed class BSPrim : BSPhysObject } public override OMV.Vector3 Position { get { + // child prims move around based on their parent. Need to get the latest location if (!Linkset.IsRoot(this)) - // child prims move around based on their parent. Need to get the latest location - _position = BulletSimAPI.GetPosition2(PhysBody.ptr); + _position = Linkset.Position(this); // don't do the GetObjectPosition for root elements because this function is called a zillion times // _position = BulletSimAPI.GetObjectPosition2(PhysicsScene.World.ptr, BSBody.ptr); @@ -344,16 +340,11 @@ public sealed class BSPrim : BSPhysObject { // The new position value must be pushed into the physics engine but we can't // just assign to "Position" because of potential call loops. - BSScene.TaintCallback sanityOperation = delegate() + PhysicsScene.TaintedObject(inTaintTime, "BSPrim.PositionSanityCheck", delegate() { DetailLog("{0},BSPrim.PositionSanityCheck,taint,pos={1},orient={2}", LocalID, _position, _orientation); ForcePosition = _position; - }; - if (inTaintTime) - sanityOperation(); - else - PhysicsScene.TaintedObject("BSPrim.PositionSanityCheck", sanityOperation); - + }); ret = true; } return ret; @@ -542,10 +533,10 @@ public sealed class BSPrim : BSPhysObject } public override OMV.Quaternion Orientation { get { + // Children move around because tied to parent. Get a fresh value. if (!Linkset.IsRoot(this)) { - // Children move around because tied to parent. Get a fresh value. - _orientation = BulletSimAPI.GetOrientation2(PhysBody.ptr); + _orientation = Linkset.Orientation(this); } return _orientation; } @@ -946,7 +937,7 @@ public sealed class BSPrim : BSPhysObject m_log.WarnFormat("{0}: Got a NaN force applied to a prim. LocalID={1}", LogHeader, LocalID); return; } - BSScene.TaintCallback addForceOperation = delegate() + PhysicsScene.TaintedObject(inTaintTime, "BSPrim.AddForce", delegate() { OMV.Vector3 fSum = OMV.Vector3.Zero; lock (m_accumulatedForces) @@ -961,11 +952,7 @@ public sealed class BSPrim : BSPhysObject DetailLog("{0},BSPrim.AddForce,taint,force={1}", LocalID, fSum); if (fSum != OMV.Vector3.Zero) BulletSimAPI.ApplyCentralForce2(PhysBody.ptr, fSum); - }; - if (inTaintTime) - addForceOperation(); - else - PhysicsScene.TaintedObject("BSPrim.AddForce", addForceOperation); + }); } private List m_accumulatedAngularForces = new List(); @@ -985,7 +972,7 @@ public sealed class BSPrim : BSPhysObject m_log.WarnFormat("{0}: Got a NaN force applied to a prim. LocalID={1}", LogHeader, LocalID); return; } - BSScene.TaintCallback addAngularForceOperation = delegate() + PhysicsScene.TaintedObject(inTaintTime, "BSPrim.AddAngularForce", delegate() { OMV.Vector3 fSum = OMV.Vector3.Zero; lock (m_accumulatedAngularForces) @@ -1003,26 +990,19 @@ public sealed class BSPrim : BSPhysObject BulletSimAPI.ApplyTorque2(PhysBody.ptr, fSum); _torque = fSum; } - }; - if (inTaintTime) - addAngularForceOperation(); - else - PhysicsScene.TaintedObject("BSPrim.AddAngularForce", addAngularForceOperation); + }); } // A torque impulse. public void ApplyTorqueImpulse(OMV.Vector3 impulse, bool inTaintTime) { OMV.Vector3 applyImpulse = impulse; - BSScene.TaintCallback applyTorqueImpulseOperation = delegate() + PhysicsScene.TaintedObject(inTaintTime, "BSPrim.ApplyTorqueImpulse", delegate() { DetailLog("{0},BSPrim.ApplyTorqueImpulse,taint,tImpulse={1}", LocalID, applyImpulse); BulletSimAPI.ApplyTorqueImpulse2(PhysBody.ptr, applyImpulse); - }; - if (inTaintTime) - applyTorqueImpulseOperation(); - else - PhysicsScene.TaintedObject("BSPrim.ApplyTorqueImpulse", applyTorqueImpulseOperation); + }); } + public override void SetMomentum(OMV.Vector3 momentum) { // DetailLog("{0},BSPrim.SetMomentum,call,mom={1}", LocalID, momentum); } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs index cc5dbb2..dcfcb83 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs @@ -692,6 +692,16 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters return; } + // Sometimes a potentially tainted operation can be used in and out of taint time. + // This routine executes the command immediately if in taint-time otherwise it is queued. + public void TaintedObject(bool inTaintTime, string ident, TaintCallback callback) + { + if (inTaintTime) + callback(); + else + TaintedObject(ident, callback); + } + // When someone tries to change a property on a BSPrim or BSCharacter, the object queues // a callback into itself to do the actual property change. That callback is called // here just before the physics engine is called to step the simulation. @@ -1438,7 +1448,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters { PhysicsLogging.Write(msg, args); // Add the Flush() if debugging crashes to get all the messages written out. - // PhysicsLogging.Flush(); + PhysicsLogging.Flush(); } // Used to fill in the LocalID when there isn't one. It's the correct number of characters. public const string DetailLogZero = "0000000000"; diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs index e131919..107befe 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs @@ -122,18 +122,14 @@ public sealed class BSShapeCollection : IDisposable lock (m_collectionActivityLock) { DetailLog("{0},BSShapeCollection.ReferenceBody,newBody", body.ID, body); - BSScene.TaintCallback createOperation = delegate() + PhysicsScene.TaintedObject(inTaintTime, "BSShapeCollection.ReferenceBody", delegate() { if (!BulletSimAPI.IsInWorld2(body.ptr)) { BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, body.ptr); DetailLog("{0},BSShapeCollection.ReferenceBody,addedToWorld,ref={1}", body.ID, body); } - }; - if (inTaintTime) - createOperation(); - else - PhysicsScene.TaintedObject("BSShapeCollection.ReferenceBody", createOperation); + }); } } @@ -146,7 +142,7 @@ public sealed class BSShapeCollection : IDisposable lock (m_collectionActivityLock) { - BSScene.TaintCallback removeOperation = delegate() + PhysicsScene.TaintedObject(inTaintTime, "BSShapeCollection.DereferenceBody", delegate() { DetailLog("{0},BSShapeCollection.DereferenceBody,DestroyingBody. ptr={1}, inTaintTime={2}", body.ID, body.ptr.ToString("X"), inTaintTime); @@ -159,12 +155,7 @@ public sealed class BSShapeCollection : IDisposable // Zero any reference to the shape so it is not freed when the body is deleted. BulletSimAPI.SetCollisionShape2(PhysicsScene.World.ptr, body.ptr, IntPtr.Zero); BulletSimAPI.DestroyObject2(PhysicsScene.World.ptr, body.ptr); - }; - // If already in taint-time, do the operations now. Otherwise queue for later. - if (inTaintTime) - removeOperation(); - else - PhysicsScene.TaintedObject("BSShapeCollection.DereferenceBody", removeOperation); + }); } } @@ -238,7 +229,7 @@ public sealed class BSShapeCollection : IDisposable if (shape.ptr == IntPtr.Zero) return; - BSScene.TaintCallback dereferenceOperation = delegate() + PhysicsScene.TaintedObject(inTaintTime, "BSShapeCollection.DereferenceShape", delegate() { if (shape.ptr != IntPtr.Zero) { @@ -270,18 +261,7 @@ public sealed class BSShapeCollection : IDisposable } } } - }; - if (inTaintTime) - { - lock (m_collectionActivityLock) - { - dereferenceOperation(); - } - } - else - { - PhysicsScene.TaintedObject("BSShapeCollection.DereferenceShape", dereferenceOperation); - } + }); } // Count down the reference count for a mesh shape @@ -311,7 +291,10 @@ public sealed class BSShapeCollection : IDisposable { hullDesc.referenceCount--; // TODO: release the Bullet storage (aging old entries?) + + // Tell upper layers that, if they have dependencies on this shape, this link is going away if (shapeCallback != null) shapeCallback(shape); + hullDesc.lastReferenced = System.DateTime.Now; Hulls[shape.shapeKey] = hullDesc; DetailLog("{0},BSShapeCollection.DereferenceHull,key={1},refCnt={2}", @@ -320,10 +303,48 @@ public sealed class BSShapeCollection : IDisposable } // Remove a reference to a compound shape. + // Taking a compound shape apart is a little tricky because if you just delete the + // physical object, it will free all the underlying children. We can't do that because + // they could be shared. So, this removes each of the children from the compound and + // dereferences them separately before destroying the compound collision object itself. // Called at taint-time. private void DereferenceCompound(BulletShape shape, ShapeDestructionCallback shapeCallback) { - // Compound shape is made of a bunch of meshes and natives. + if (!BulletSimAPI.IsCompound2(shape.ptr)) + { + // Failed the sanity check!! + PhysicsScene.Logger.ErrorFormat("{0} Attempt to free a compound shape that is not compound!! type={1}, ptr={2}", + LogHeader, shape.type, shape.ptr.ToString("X")); + DetailLog("{0},BSShapeCollection.DereferenceCompound,notACompoundShape,type={1},ptr={2}", + BSScene.DetailLogZero, shape.type, shape.ptr.ToString("X")); + return; + } + int numChildren = BulletSimAPI.GetNumberOfCompoundChildren2(shape.ptr); + for (int ii = 0; ii < numChildren; ii++) + { + IntPtr childShape = BulletSimAPI.RemoveChildShapeFromCompoundShapeIndex2(shape.ptr, ii); + DereferenceAnonCollisionShape(childShape); + } + BulletSimAPI.DeleteCollisionShape2(PhysicsScene.World.ptr, shape.ptr); + } + + // Sometimes we have a pointer to a collision shape but don't know what type it is. + // Figure out type and call the correct dereference routine. + // This is coming from a compound shape that we created so we know it is either native or mesh. + // Called at taint-time. + private void DereferenceAnonCollisionShape(IntPtr cShape) + { + BulletShape shapeInfo = new BulletShape(cShape, ShapeData.PhysicsShapeType.SHAPE_MESH); + if (BulletSimAPI.IsCompound2(cShape)) + shapeInfo.type = ShapeData.PhysicsShapeType.SHAPE_COMPOUND; + + if (BulletSimAPI.IsNativeShape2(cShape)) + { + shapeInfo.isNativeShape = true; + shapeInfo.type = ShapeData.PhysicsShapeType.SHAPE_BOX; // (technically, type doesn't matter) + } + + DereferenceShape(shapeInfo, true, null); } // Create the geometry information in Bullet for later use. @@ -338,10 +359,8 @@ public sealed class BSShapeCollection : IDisposable { bool ret = false; bool haveShape = false; - bool nativeShapePossible = true; - PrimitiveBaseShape pbs = prim.BaseShape; - if (prim.PreferredPhysicalShape == ShapeData.PhysicsShapeType.SHAPE_AVATAR) + if (!haveShape && prim.PreferredPhysicalShape == ShapeData.PhysicsShapeType.SHAPE_AVATAR) { // an avatar capsule is close to a native shape (it is not shared) ret = GetReferenceToNativeShape(prim, ShapeData.PhysicsShapeType.SHAPE_AVATAR, @@ -350,6 +369,31 @@ public sealed class BSShapeCollection : IDisposable ret = true; haveShape = true; } + + // Compound shapes are handled special as they are rebuilt from scratch. + // This isn't too great a hardship since most of the child shapes will already been created. + if (!haveShape && prim.PreferredPhysicalShape == ShapeData.PhysicsShapeType.SHAPE_COMPOUND) + { + ret = GetReferenceToCompoundShape(prim, shapeCallback); + DetailLog("{0},BSShapeCollection.CreateGeom,compoundShape,shape={1}", prim.LocalID, prim.PhysShape); + haveShape = true; + } + + if (!haveShape) + { + ret = CreateGeomNonSpecial(forceRebuild, prim, shapeCallback); + } + + return ret; + } + + private bool CreateGeomNonSpecial(bool forceRebuild, BSPhysObject prim, ShapeDestructionCallback shapeCallback) + { + bool ret = false; + bool haveShape = false; + bool nativeShapePossible = true; + PrimitiveBaseShape pbs = prim.BaseShape; + // If the prim attributes are simple, this could be a simple Bullet native shape if (!haveShape && pbs != null @@ -363,6 +407,7 @@ public sealed class BSShapeCollection : IDisposable && pbs.PathScaleX == 100 && pbs.PathScaleY == 100 && pbs.PathShearX == 0 && pbs.PathShearY == 0) ) ) { + // It doesn't look like Bullet scales spheres so make sure the scales are all equal if ((pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1) && pbs.Scale.X == pbs.Scale.Y && pbs.Scale.Y == pbs.Scale.Z) { @@ -378,7 +423,7 @@ public sealed class BSShapeCollection : IDisposable prim.LocalID, forceRebuild, prim.PhysShape); } } - if (pbs.ProfileShape == ProfileShape.Square && pbs.PathCurve == (byte)Extrusion.Straight) + if (!haveShape && pbs.ProfileShape == ProfileShape.Square && pbs.PathCurve == (byte)Extrusion.Straight) { haveShape = true; if (forceRebuild @@ -393,9 +438,10 @@ public sealed class BSShapeCollection : IDisposable } } } + // If a simple shape is not happening, create a mesh and possibly a hull. // Note that if it's a native shape, the check for physical/non-physical is not - // made. Native shapes are best used in either case. + // made. Native shapes work in either case. if (!haveShape && pbs != null) { if (prim.IsPhysical && PhysicsScene.ShouldUseHullsForPhysicalObjects) @@ -487,7 +533,7 @@ public sealed class BSShapeCollection : IDisposable if (newMeshKey == prim.PhysShape.shapeKey && prim.PhysShape.type == ShapeData.PhysicsShapeType.SHAPE_MESH) return false; - DetailLog("{0},BSShapeCollection.CreateGeomMesh,create,oldKey={1},newKey={2}", + DetailLog("{0},BSShapeCollection.GetReferenceToMesh,create,oldKey={1},newKey={2}", prim.LocalID, prim.PhysShape.shapeKey.ToString("X"), newMeshKey.ToString("X")); // Since we're recreating new, get rid of the reference to the previous shape @@ -535,7 +581,7 @@ public sealed class BSShapeCollection : IDisposable verticesAsFloats[vi++] = vv.Z; } - // m_log.DebugFormat("{0}: CreateGeomMesh: calling CreateMesh. lid={1}, key={2}, indices={3}, vertices={4}", + // m_log.DebugFormat("{0}: BSShapeCollection.CreatePhysicalMesh: calling CreateMesh. lid={1}, key={2}, indices={3}, vertices={4}", // LogHeader, prim.LocalID, newMeshKey, indices.Length, vertices.Count); meshPtr = BulletSimAPI.CreateMeshShape2(PhysicsScene.World.ptr, @@ -561,7 +607,7 @@ public sealed class BSShapeCollection : IDisposable if (newHullKey == prim.PhysShape.shapeKey && prim.PhysShape.type == ShapeData.PhysicsShapeType.SHAPE_HULL) return false; - DetailLog("{0},BSShapeCollection.CreateGeomHull,create,oldKey={1},newKey={2}", + DetailLog("{0},BSShapeCollection.GetReferenceToHull,create,oldKey={1},newKey={2}", prim.LocalID, prim.PhysShape.shapeKey.ToString("X"), newHullKey.ToString("X")); // Remove usage of the previous shape. @@ -693,6 +739,42 @@ public sealed class BSShapeCollection : IDisposable return; } + // Compound shapes are always built from scratch. + // This shouldn't be to bad since most of the parts will be meshes that had been built previously. + private bool GetReferenceToCompoundShape(BSPhysObject prim, ShapeDestructionCallback shapeCallback) + { + BulletShape cShape = new BulletShape( + BulletSimAPI.CreateCompoundShape2(PhysicsScene.World.ptr), ShapeData.PhysicsShapeType.SHAPE_COMPOUND); + + // The prim's linkset is the source of the children. + // TODO: there is too much knowledge here about the internals of linksets and too much + // dependency on the relationship of compound shapes and linksets (what if we want to use + // compound shapes for something else?). Think through this and clean up so the + // appropriate knowledge is used at the correct software levels. + + // Recreate the geometry of the root prim (might have been a linkset root in the past) + CreateGeomNonSpecial(true, prim, null); + + BSPhysObject rootPrim = prim.Linkset.LinksetRoot; + + prim.Linkset.ForEachMember(delegate(BSPhysObject cPrim) + { + OMV.Quaternion invRootOrientation = OMV.Quaternion.Inverse(rootPrim.RawOrientation); + OMV.Vector3 displacementPos = (cPrim.RawPosition - rootPrim.RawPosition) * invRootOrientation; + OMV.Quaternion displacementRot = cPrim.RawOrientation * invRootOrientation; + + DetailLog("{0},BSShapeCollection.GetReferenceToCompoundShape,addMemberToShape,mID={1},mShape={2},dispPos={3},dispRot={4}", + prim.LocalID, cPrim.LocalID, cPrim.PhysShape.ptr.ToString("X"), displacementPos, displacementRot); + + BulletSimAPI.AddChildShapeToCompoundShape2(cShape.ptr, cPrim.PhysShape.ptr, displacementPos, displacementRot); + return false; + }); + + prim.PhysShape = cShape; + + return true; + } + // Create a hash of all the shape parameters to be used as a key // for this particular shape. private System.UInt64 ComputeShapeKey(OMV.Vector3 size, PrimitiveBaseShape pbs, out float retLod) diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs index 11298fe..7c34af2 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs @@ -238,7 +238,7 @@ public sealed class BSTerrainManager DetailLog("{0},UpdateOrCreateTerrain:UpdateExisting,call,terrainBase={1},minC={2}, maxC={3}, szX={4}, szY={5}", BSScene.DetailLogZero, terrainRegionBase, mapInfo.minCoords, mapInfo.maxCoords, mapInfo.sizeX, mapInfo.sizeY); - BSScene.TaintCallback rebuildOperation = delegate() + PhysicsScene.TaintedObject(inTaintTime, "BSScene.UpdateOrCreateTerrain:UpdateExisting", delegate() { if (MegaRegionParentPhysicsScene != null) { @@ -337,14 +337,7 @@ public sealed class BSTerrainManager BulletSimAPI.ForceActivationState2(mapInfo.terrainBody.ptr, ActivationState.DISABLE_SIMULATION); m_terrainModified = true; - }; - - // There is the option to do the changes now (we're already in 'taint time'), or - // to do the Bullet operations later. - if (inTaintTime) - rebuildOperation(); - else - PhysicsScene.TaintedObject("BSScene.UpdateOrCreateTerrain:UpdateExisting", rebuildOperation); + }); } else { @@ -364,7 +357,7 @@ public sealed class BSTerrainManager BSScene.DetailLogZero, newTerrainID, minCoords, minCoords); // Code that must happen at taint-time - BSScene.TaintCallback createOperation = delegate() + PhysicsScene.TaintedObject(inTaintTime, "BSScene.UpdateOrCreateTerrain:NewTerrain", delegate() { DetailLog("{0},UpdateOrCreateTerrain:NewTerrain,taint,baseX={1},baseY={2}", BSScene.DetailLogZero, minCoords.X, minCoords.Y); // Create a new mapInfo that will be filled with the new info @@ -377,13 +370,7 @@ public sealed class BSTerrainManager UpdateOrCreateTerrain(newTerrainID, heightMap, minCoords, maxCoords, true); m_terrainModified = true; - }; - - // If already in taint-time, just call Bullet. Otherwise queue the operations for the safe time. - if (inTaintTime) - createOperation(); - else - PhysicsScene.TaintedObject("BSScene.UpdateOrCreateTerrain:NewTerrain", createOperation); + }); } } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs index 3b6355c..143b8be 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs @@ -399,8 +399,6 @@ public enum CollisionFilterGroups : uint }; - - // CFM controls the 'hardness' of the constraint. 0=fixed, 0..1=violatable. Default=0 // ERP controls amount of correction per tick. Usable range=0.1..0.8. Default=0.2. public enum ConstraintParams : int @@ -618,10 +616,19 @@ public static extern IntPtr BuildCapsuleShape2(IntPtr world, float radius, float public static extern IntPtr CreateCompoundShape2(IntPtr sim); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void AddChildToCompoundShape2(IntPtr cShape, IntPtr addShape, Vector3 pos, Quaternion rot); +public static extern int GetNumberOfCompoundChildren2(IntPtr cShape); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern void AddChildShapeToCompoundShape2(IntPtr cShape, IntPtr addShape, Vector3 pos, Quaternion rot); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern IntPtr GetChildShapeFromCompoundShapeIndex2(IntPtr cShape, int indx); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern IntPtr RemoveChildShapeFromCompoundShapeIndex2(IntPtr cShape, int indx); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void RemoveChildFromCompoundShape2(IntPtr cShape, IntPtr removeShape); +public static extern void RemoveChildShapeFromCompoundShape2(IntPtr cShape, IntPtr removeShape); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern IntPtr DuplicateCollisionShape2(IntPtr sim, IntPtr srcShape, uint id); -- cgit v1.1 From 1dc23b2b9713f4099534ae0d08c2caf5c8b036b4 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Fri, 2 Nov 2012 10:35:12 -0700 Subject: BulletSim: parameterize selection of linkset implementation --- OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs | 28 ++++++++++++++-------- OpenSim/Region/Physics/BulletSPlugin/BSScene.cs | 5 ++++ .../Region/Physics/BulletSPlugin/BulletSimAPI.cs | 1 + 3 files changed, 24 insertions(+), 10 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs index 8f973f4..3a92f93 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs @@ -36,21 +36,29 @@ public abstract class BSLinkset { // private static string LogHeader = "[BULLETSIM LINKSET]"; + public enum LinksetImplementation + { + Constraint = 0, // linkset tied together with constraints + Compound = 1, // linkset tied together as a compound object + Manual = 2 // linkset tied together manually (code moves all the pieces) + } // Create the correct type of linkset for this child public static BSLinkset Factory(BSScene physScene, BSPhysObject parent) { BSLinkset ret = null; - /* - if (parent.IsPhysical) - ret = new BSLinksetConstraints(physScene, parent); - else - ret = new BSLinksetManual(physScene, parent); - */ - - // at the moment, there is only one - // ret = new BSLinksetConstraints(physScene, parent); - ret = new BSLinksetCompound(physScene, parent); + switch ((int)physScene.Params.linksetImplementation) + { + case (int)LinksetImplementation.Compound: + ret = new BSLinksetCompound(physScene, parent); + break; + case (int)LinksetImplementation.Manual: + // ret = new BSLinksetManual(physScene, parent); + break; + default: + ret = new BSLinksetConstraints(physScene, parent); + break; + } return ret; } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs index dcfcb83..13aa860 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs @@ -1214,6 +1214,11 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters (s) => { return s.m_params[0].numberOfSolverIterations; }, (s,p,l,v) => { s.m_params[0].numberOfSolverIterations = v; } ), + new ParameterDefn("LinksetImplementation", "Type of linkset implementation (0=Constraint, 1=Compound)", + (float)BSLinkset.LinksetImplementation.Constraint, + (s,cf,p,v) => { s.m_params[0].linksetImplementation = cf.GetFloat(p,v); }, + (s) => { return s.m_params[0].linksetImplementation; }, + (s,p,l,v) => { s.m_params[0].linksetImplementation = v; } ), new ParameterDefn("LinkConstraintUseFrameOffset", "For linksets built with constraints, enable frame offsetFor linksets built with constraints, enable frame offset.", ConfigurationParameters.numericFalse, (s,cf,p,v) => { s.m_params[0].linkConstraintUseFrameOffset = s.NumericBool(cf.GetBoolean(p, s.BoolNumeric(v))); }, diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs index 143b8be..ac6d2b2 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs @@ -300,6 +300,7 @@ public struct ConfigurationParameters public float shouldEnableFrictionCaching; public float numberOfSolverIterations; + public float linksetImplementation; public float linkConstraintUseFrameOffset; public float linkConstraintEnableTransMotor; public float linkConstraintTransMotorMaxVel; -- cgit v1.1 From 498ea76e637961d8b4e3d39b758f7f2dea2fe998 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Fri, 2 Nov 2012 17:22:34 -0700 Subject: BulletSim: Move construction of compound linkset from ShapeCollection into LinksetCompound where it should be. Create meshes for native shapes when part of a compound linkset because scale is currently per object and not per collision shape. Don't schedule a LinksetCompound refresh if just changing properties. --- .../Physics/BulletSPlugin/BSLinksetCompound.cs | 72 ++++++++++++++---- OpenSim/Region/Physics/BulletSPlugin/BSScene.cs | 24 +++++- .../Physics/BulletSPlugin/BSShapeCollection.cs | 85 +++++++++++----------- 3 files changed, 120 insertions(+), 61 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs index 8b97ebb..adf4aff 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs @@ -34,7 +34,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin { public sealed class BSLinksetCompound : BSLinkset { - // private static string LogHeader = "[BULLETSIM LINKSET CONSTRAINTS]"; + private static string LogHeader = "[BULLETSIM LINKSET COMPOUND]"; public BSLinksetCompound(BSScene scene, BSPhysObject parent) { @@ -59,6 +59,12 @@ public sealed class BSLinksetCompound : BSLinkset // refresh will happen once after all the other taints are applied. public override void Refresh(BSPhysObject requestor) { + // External request for Refresh (from BSPrim) is not necessary + // InternalRefresh(requestor); + } + + private void InternalRefresh(BSPhysObject requestor) + { DetailLog("{0},BSLinksetCompound.Refresh,schedulingRefresh,requestor={1}", LinksetRoot.LocalID, requestor.LocalID); // Queue to happen after all the other taint processing PhysicsScene.PostTaintObject("BSLinksetCompound.Refresh", requestor.LocalID, delegate() @@ -135,13 +141,13 @@ public sealed class BSLinksetCompound : BSLinkset { bool ret = false; - DetailLog("{0},BSLinksetCompound.RemoveBodyDependencies,removeChildrenForRoot,rID={1},rBody={2},isRoot={3}", - child.LocalID, LinksetRoot.LocalID, LinksetRoot.PhysBody.ptr.ToString("X"), IsRoot(child)); + DetailLog("{0},BSLinksetCompound.RemoveBodyDependencies,refreshIfChild,rID={1},rBody={2},isRoot={3}", + child.LocalID, LinksetRoot.LocalID, LinksetRoot.PhysBody.ptr.ToString("X"), IsRoot(child)); if (!IsRoot(child)) { // Cause the current shape to be freed and the new one to be built. - Refresh(LinksetRoot); + InternalRefresh(LinksetRoot); ret = true; } @@ -169,7 +175,7 @@ public sealed class BSLinksetCompound : BSLinkset DetailLog("{0},BSLinksetCompound.AddChildToLinkset,call,child={1}", LinksetRoot.LocalID, child.LocalID); // Cause constraints and assorted properties to be recomputed before the next simulation step. - Refresh(LinksetRoot); + InternalRefresh(LinksetRoot); } return; } @@ -196,34 +202,68 @@ public sealed class BSLinksetCompound : BSLinkset else { // Schedule a rebuild of the linkset before the next simulation tick. - Refresh(LinksetRoot); + InternalRefresh(LinksetRoot); } } return; } - - // Call each of the constraints that make up this linkset and recompute the - // various transforms and variables. Create constraints of not created yet. - // Called before the simulation step to make sure the constraint based linkset + // Called before the simulation step to make sure the compound based linkset // is all initialized. + // Constraint linksets are rebuilt every time. + // Note that this works for rebuilding just the root after a linkset is taken apart. // Called at taint time!! private void RecomputeLinksetCompound() { - DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,start,rBody={1},numChildren={2}", - LinksetRoot.LocalID, LinksetRoot.PhysBody.ptr.ToString("X"), NumberOfChildren); - + // Cause the root shape to be rebuilt as a compound object with just the root in it LinksetRoot.ForceBodyShapeRebuild(true); + DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,start,rBody={1},rShape={2},numChildren={3}", + LinksetRoot.LocalID, LinksetRoot.PhysBody, LinksetRoot.PhysShape, NumberOfChildren); + + ForEachMember(delegate(BSPhysObject cPrim) + { + if (!IsRoot(cPrim)) + { + OMV.Quaternion invRootOrientation = OMV.Quaternion.Inverse(LinksetRoot.RawOrientation); + OMV.Vector3 displacementPos = (cPrim.RawPosition - LinksetRoot.RawPosition) * invRootOrientation; + OMV.Quaternion displacementRot = cPrim.RawOrientation * invRootOrientation; + + DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,addMemberToShape,mID={1},mShape={2},dispPos={3},dispRot={4}", + LinksetRoot.LocalID, cPrim.LocalID, cPrim.PhysShape, displacementPos, displacementRot); + + if (cPrim.PhysShape.isNativeShape) + { + // Native shapes are not shared so we need to create a new one. + // A mesh or hull is created because scale is not available on a native shape. + // (TODO: Bullet does have a btScaledCollisionShape. Can that be used?) + BulletShape saveShape = cPrim.PhysShape; + PhysicsScene.Shapes.CreateGeomMeshOrHull(cPrim, null); + BulletShape newShape = cPrim.PhysShape; + cPrim.PhysShape = saveShape; + BulletSimAPI.AddChildShapeToCompoundShape2(LinksetRoot.PhysShape.ptr, newShape.ptr, displacementPos, displacementRot); + } + else + { + // For the shared shapes (meshes and hulls) just use the shape in the child + if (PhysicsScene.Shapes.ReferenceShape(cPrim.PhysShape)) + { + PhysicsScene.Logger.ErrorFormat("{0} Rebuilt sharable shape when building linkset! Region={1}, primID={2}, shape={3}", + LogHeader, PhysicsScene.RegionName, cPrim.LocalID, cPrim.PhysShape); + } + BulletSimAPI.AddChildShapeToCompoundShape2(LinksetRoot.PhysShape.ptr, cPrim.PhysShape.ptr, displacementPos, displacementRot); + } + } + return false; + }); + + float linksetMass = LinksetMass; LinksetRoot.UpdatePhysicalMassProperties(linksetMass); // DEBUG: see of inter-linkset collisions are causing problems // BulletSimAPI.SetCollisionFilterMask2(LinksetRoot.BSBody.ptr, // (uint)CollisionFilterGroups.LinksetFilter, (uint)CollisionFilterGroups.LinksetMask); - DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,end,rBody={1},linksetMass={2}", - LinksetRoot.LocalID, LinksetRoot.PhysBody.ptr.ToString("X"), linksetMass); - } } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs index 13aa860..de35359 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs @@ -116,6 +116,10 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters // True if initialized and ready to do simulation steps private bool m_initialized = false; + // Flag which is true when processing taints. + // Not guaranteed to be correct all the time (don't depend on this) but good for debugging. + public bool InTaintTime { get; private set; } + // Pinned memory used to pass step information between managed and unmanaged private int m_maxCollisionsPerFrame; private CollisionDesc[] m_collisionArray; @@ -270,6 +274,9 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters TerrainManager = new BSTerrainManager(this); TerrainManager.CreateInitialGroundPlaneAndTerrain(); + m_log.WarnFormat("{0} Linksets implemented with {1}", LogHeader, (BSLinkset.LinksetImplementation)Params.linksetImplementation); + + InTaintTime = false; m_initialized = true; } @@ -707,8 +714,10 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters // here just before the physics engine is called to step the simulation. public void ProcessTaints() { + InTaintTime = true; ProcessRegularTaints(); ProcessPostTaintTaints(); + InTaintTime = false; } private void ProcessRegularTaints() @@ -851,6 +860,17 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters } } + public bool AssertInTaintTime(string whereFrom) + { + if (!InTaintTime) + { + DetailLog("{0},BSScene.AssertInTaintTime,NOT IN TAINT TIME,Region={1},Where={2}", DetailLogZero, RegionName, whereFrom); + m_log.ErrorFormat("{0} NOT IN TAINT TIME!! Region={1}, Where={2}", LogHeader, RegionName, whereFrom); + Util.PrintCallStack(); + } + return InTaintTime; + } + #endregion // Taints #region Vehicles @@ -1214,8 +1234,8 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters (s) => { return s.m_params[0].numberOfSolverIterations; }, (s,p,l,v) => { s.m_params[0].numberOfSolverIterations = v; } ), - new ParameterDefn("LinksetImplementation", "Type of linkset implementation (0=Constraint, 1=Compound)", - (float)BSLinkset.LinksetImplementation.Constraint, + new ParameterDefn("LinksetImplementation", "Type of linkset implementation (0=Constraint, 1=Compound, 2=Manual)", + (float)BSLinkset.LinksetImplementation.Compound, (s,cf,p,v) => { s.m_params[0].linksetImplementation = cf.GetFloat(p,v); }, (s) => { return s.m_params[0].linksetImplementation; }, (s,p,l,v) => { s.m_params[0].linksetImplementation = v; } ), diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs index 107befe..662b19d 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs @@ -92,6 +92,8 @@ public sealed class BSShapeCollection : IDisposable public bool GetBodyAndShape(bool forceRebuild, BulletSim sim, BSPhysObject prim, ShapeDestructionCallback shapeCallback, BodyDestructionCallback bodyCallback) { + PhysicsScene.AssertInTaintTime("BSShapeCollection.GetBodyAndShape"); + bool ret = false; // This lock could probably be pushed down lower but building shouldn't take long @@ -121,7 +123,7 @@ public sealed class BSShapeCollection : IDisposable { lock (m_collectionActivityLock) { - DetailLog("{0},BSShapeCollection.ReferenceBody,newBody", body.ID, body); + DetailLog("{0},BSShapeCollection.ReferenceBody,newBody,body={1}", body.ID, body); PhysicsScene.TaintedObject(inTaintTime, "BSShapeCollection.ReferenceBody", delegate() { if (!BulletSimAPI.IsInWorld2(body.ptr)) @@ -165,7 +167,7 @@ public sealed class BSShapeCollection : IDisposable // Meshes and hulls for the same shape have the same hash key. // NOTE that native shapes are not added to the mesh list or removed. // Returns 'true' if this is the initial reference to the shape. Otherwise reused. - private bool ReferenceShape(BulletShape shape) + public bool ReferenceShape(BulletShape shape) { bool ret = false; switch (shape.type) @@ -276,8 +278,8 @@ public sealed class BSShapeCollection : IDisposable if (shapeCallback != null) shapeCallback(shape); meshDesc.lastReferenced = System.DateTime.Now; Meshes[shape.shapeKey] = meshDesc; - DetailLog("{0},BSShapeCollection.DereferenceMesh,key={1},refCnt={2}", - BSScene.DetailLogZero, shape.shapeKey.ToString("X"), meshDesc.referenceCount); + DetailLog("{0},BSShapeCollection.DereferenceMesh,shape={1},refCnt={2}", + BSScene.DetailLogZero, shape, meshDesc.referenceCount); } } @@ -297,8 +299,8 @@ public sealed class BSShapeCollection : IDisposable hullDesc.lastReferenced = System.DateTime.Now; Hulls[shape.shapeKey] = hullDesc; - DetailLog("{0},BSShapeCollection.DereferenceHull,key={1},refCnt={2}", - BSScene.DetailLogZero, shape.shapeKey.ToString("X"), hullDesc.referenceCount); + DetailLog("{0},BSShapeCollection.DereferenceHull,shape={1},refCnt={2}", + BSScene.DetailLogZero, shape, hullDesc.referenceCount); } } @@ -319,8 +321,11 @@ public sealed class BSShapeCollection : IDisposable BSScene.DetailLogZero, shape.type, shape.ptr.ToString("X")); return; } + int numChildren = BulletSimAPI.GetNumberOfCompoundChildren2(shape.ptr); - for (int ii = 0; ii < numChildren; ii++) + DetailLog("{0},BSShapeCollection.DereferenceCompound,shape={1},children={2}", BSScene.DetailLogZero, shape, numChildren); + + for (int ii = numChildren - 1; ii >= 0; ii--) { IntPtr childShape = BulletSimAPI.RemoveChildShapeFromCompoundShapeIndex2(shape.ptr, ii); DereferenceAnonCollisionShape(childShape); @@ -343,6 +348,7 @@ public sealed class BSShapeCollection : IDisposable shapeInfo.isNativeShape = true; shapeInfo.type = ShapeData.PhysicsShapeType.SHAPE_BOX; // (technically, type doesn't matter) } + DetailLog("{0},BSShapeCollection.DereferenceAnonCollisionShape,shape={1}", BSScene.DetailLogZero, shapeInfo); DereferenceShape(shapeInfo, true, null); } @@ -440,23 +446,32 @@ public sealed class BSShapeCollection : IDisposable } // If a simple shape is not happening, create a mesh and possibly a hull. + if (!haveShape && pbs != null) + { + ret = CreateGeomMeshOrHull(prim, shapeCallback); + } + + return ret; + } + + public bool CreateGeomMeshOrHull(BSPhysObject prim, ShapeDestructionCallback shapeCallback) + { + + bool ret = false; // Note that if it's a native shape, the check for physical/non-physical is not // made. Native shapes work in either case. - if (!haveShape && pbs != null) + if (prim.IsPhysical && PhysicsScene.ShouldUseHullsForPhysicalObjects) { - if (prim.IsPhysical && PhysicsScene.ShouldUseHullsForPhysicalObjects) - { - // Update prim.BSShape to reference a hull of this shape. - ret = GetReferenceToHull(prim,shapeCallback); - DetailLog("{0},BSShapeCollection.CreateGeom,hull,shape={1},key={2}", - prim.LocalID, prim.PhysShape, prim.PhysShape.shapeKey.ToString("X")); - } - else - { - ret = GetReferenceToMesh(prim, shapeCallback); - DetailLog("{0},BSShapeCollection.CreateGeom,mesh,shape={1},key={2}", - prim.LocalID, prim.PhysShape, prim.PhysShape.shapeKey.ToString("X")); - } + // Update prim.BSShape to reference a hull of this shape. + ret = GetReferenceToHull(prim,shapeCallback); + DetailLog("{0},BSShapeCollection.CreateGeom,hull,shape={1},key={2}", + prim.LocalID, prim.PhysShape, prim.PhysShape.shapeKey.ToString("X")); + } + else + { + ret = GetReferenceToMesh(prim, shapeCallback); + DetailLog("{0},BSShapeCollection.CreateGeom,mesh,shape={1},key={2}", + prim.LocalID, prim.PhysShape, prim.PhysShape.shapeKey.ToString("X")); } return ret; } @@ -743,32 +758,16 @@ public sealed class BSShapeCollection : IDisposable // This shouldn't be to bad since most of the parts will be meshes that had been built previously. private bool GetReferenceToCompoundShape(BSPhysObject prim, ShapeDestructionCallback shapeCallback) { + // Remove reference to the old shape + // Don't need to do this as the shape is freed when we create the new root shape below. + // DereferenceShape(prim.PhysShape, true, shapeCallback); + BulletShape cShape = new BulletShape( BulletSimAPI.CreateCompoundShape2(PhysicsScene.World.ptr), ShapeData.PhysicsShapeType.SHAPE_COMPOUND); - // The prim's linkset is the source of the children. - // TODO: there is too much knowledge here about the internals of linksets and too much - // dependency on the relationship of compound shapes and linksets (what if we want to use - // compound shapes for something else?). Think through this and clean up so the - // appropriate knowledge is used at the correct software levels. - - // Recreate the geometry of the root prim (might have been a linkset root in the past) + // Create the shape for the root prim and add it to the compound shape CreateGeomNonSpecial(true, prim, null); - - BSPhysObject rootPrim = prim.Linkset.LinksetRoot; - - prim.Linkset.ForEachMember(delegate(BSPhysObject cPrim) - { - OMV.Quaternion invRootOrientation = OMV.Quaternion.Inverse(rootPrim.RawOrientation); - OMV.Vector3 displacementPos = (cPrim.RawPosition - rootPrim.RawPosition) * invRootOrientation; - OMV.Quaternion displacementRot = cPrim.RawOrientation * invRootOrientation; - - DetailLog("{0},BSShapeCollection.GetReferenceToCompoundShape,addMemberToShape,mID={1},mShape={2},dispPos={3},dispRot={4}", - prim.LocalID, cPrim.LocalID, cPrim.PhysShape.ptr.ToString("X"), displacementPos, displacementRot); - - BulletSimAPI.AddChildShapeToCompoundShape2(cShape.ptr, cPrim.PhysShape.ptr, displacementPos, displacementRot); - return false; - }); + BulletSimAPI.AddChildShapeToCompoundShape2(cShape.ptr, prim.PhysShape.ptr, OMV.Vector3.Zero, OMV.Quaternion.Identity); prim.PhysShape = cShape; -- cgit v1.1 From 894bb4893b8bb269f8561737e4603a9b31183f2c Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Sat, 3 Nov 2012 18:26:00 -0700 Subject: BulletSim: search the mesh and hull lists to find shapes if type is not known. This makes sure the correct accounting is done for the particular shape. --- .../Physics/BulletSPlugin/BSLinksetCompound.cs | 10 +- .../Physics/BulletSPlugin/BSLinksetConstraints.cs | 2 +- OpenSim/Region/Physics/BulletSPlugin/BSScene.cs | 2 +- .../Physics/BulletSPlugin/BSShapeCollection.cs | 102 ++++++++++++++++++--- 4 files changed, 96 insertions(+), 20 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs index adf4aff..6e68695 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs @@ -134,7 +134,7 @@ public sealed class BSLinksetCompound : BSLinkset } // Routine called when rebuilding the body of some member of the linkset. - // Since we don't keep in-physical world relationships, do nothing unless it's a child changing. + // Since we don't keep in world relationships, do nothing unless it's a child changing. // Returns 'true' of something was actually removed and would need restoring // Called at taint-time!! public override bool RemoveBodyDependencies(BSPrim child) @@ -221,10 +221,12 @@ public sealed class BSLinksetCompound : BSLinkset DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,start,rBody={1},rShape={2},numChildren={3}", LinksetRoot.LocalID, LinksetRoot.PhysBody, LinksetRoot.PhysShape, NumberOfChildren); + // Add a shape for each of the other children in the linkset ForEachMember(delegate(BSPhysObject cPrim) { if (!IsRoot(cPrim)) { + // Each child position and rotation is given relative to the root. OMV.Quaternion invRootOrientation = OMV.Quaternion.Inverse(LinksetRoot.RawOrientation); OMV.Vector3 displacementPos = (cPrim.RawPosition - LinksetRoot.RawPosition) * invRootOrientation; OMV.Quaternion displacementRot = cPrim.RawOrientation * invRootOrientation; @@ -245,7 +247,7 @@ public sealed class BSLinksetCompound : BSLinkset } else { - // For the shared shapes (meshes and hulls) just use the shape in the child + // For the shared shapes (meshes and hulls), just use the shape in the child. if (PhysicsScene.Shapes.ReferenceShape(cPrim.PhysShape)) { PhysicsScene.Logger.ErrorFormat("{0} Rebuilt sharable shape when building linkset! Region={1}, primID={2}, shape={3}", @@ -254,10 +256,10 @@ public sealed class BSLinksetCompound : BSLinkset BulletSimAPI.AddChildShapeToCompoundShape2(LinksetRoot.PhysShape.ptr, cPrim.PhysShape.ptr, displacementPos, displacementRot); } } - return false; + return false; // 'false' says to move onto the next child in the list }); - + // With all of the linkset packed into the root prim, it has the mass of everyone. float linksetMass = LinksetMass; LinksetRoot.UpdatePhysicalMassProperties(linksetMass); diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs index 67a59ef..d2387fb 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs @@ -294,7 +294,7 @@ public sealed class BSLinksetConstraints : BSLinkset float linksetMass = LinksetMass; LinksetRoot.UpdatePhysicalMassProperties(linksetMass); - // DEBUG: see of inter-linkset collisions are causing problems + // DEBUG: see of inter-linkset collisions are causing problems // BulletSimAPI.SetCollisionFilterMask2(LinksetRoot.BSBody.ptr, // (uint)CollisionFilterGroups.LinksetFilter, (uint)CollisionFilterGroups.LinksetMask); DetailLog("{0},BSLinksetConstraint.RecomputeLinksetConstraints,set,rBody={1},linksetMass={2}", diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs index de35359..c2e0ef1 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs @@ -1472,7 +1472,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters public void DetailLog(string msg, params Object[] args) { PhysicsLogging.Write(msg, args); - // Add the Flush() if debugging crashes to get all the messages written out. + // Add the Flush() if debugging crashes. Gets all the messages written out. PhysicsLogging.Flush(); } // Used to fill in the LocalID when there isn't one. It's the correct number of characters. diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs index 662b19d..4a31c7d 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs @@ -48,6 +48,7 @@ public sealed class BSShapeCollection : IDisposable public IntPtr ptr; public int referenceCount; public DateTime lastReferenced; + public UInt64 shapeKey; } // Description of a hull. @@ -57,6 +58,7 @@ public sealed class BSShapeCollection : IDisposable public IntPtr ptr; public int referenceCount; public DateTime lastReferenced; + public UInt64 shapeKey; } // The sharable set of meshes and hulls. Indexed by their shape hash. @@ -116,7 +118,7 @@ public sealed class BSShapeCollection : IDisposable return ret; } - // Track another user of a body + // Track another user of a body. // We presume the caller has allocated the body. // Bodies only have one user so the body is just put into the world if not already there. public void ReferenceBody(BulletBody body, bool inTaintTime) @@ -146,13 +148,16 @@ public sealed class BSShapeCollection : IDisposable { PhysicsScene.TaintedObject(inTaintTime, "BSShapeCollection.DereferenceBody", delegate() { - DetailLog("{0},BSShapeCollection.DereferenceBody,DestroyingBody. ptr={1}, inTaintTime={2}", - body.ID, body.ptr.ToString("X"), inTaintTime); + DetailLog("{0},BSShapeCollection.DereferenceBody,DestroyingBody,body={1},inTaintTime={2}", + body.ID, body, inTaintTime); // If the caller needs to know the old body is going away, pass the event up. if (bodyCallback != null) bodyCallback(body); - // It may have already been removed from the world in which case the next is a NOOP. - BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, body.ptr); + if (BulletSimAPI.IsInWorld2(body.ptr)) + { + BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, body.ptr); + DetailLog("{0},BSShapeCollection.DereferenceBody,removingFromWorld. Body={1}", body.ID, body); + } // Zero any reference to the shape so it is not freed when the body is deleted. BulletSimAPI.SetCollisionShape2(PhysicsScene.World.ptr, body.ptr, IntPtr.Zero); @@ -185,6 +190,7 @@ public sealed class BSShapeCollection : IDisposable { // This is a new reference to a mesh meshDesc.ptr = shape.ptr; + meshDesc.shapeKey = shape.shapeKey; // We keep a reference to the underlying IMesh data so a hull can be built meshDesc.referenceCount = 1; DetailLog("{0},BSShapeCollection.ReferenceShape,newMesh,key={1},cnt={2}", @@ -207,6 +213,7 @@ public sealed class BSShapeCollection : IDisposable { // This is a new reference to a hull hullDesc.ptr = shape.ptr; + hullDesc.shapeKey = shape.shapeKey; hullDesc.referenceCount = 1; DetailLog("{0},BSShapeCollection.ReferenceShape,newHull,key={1},cnt={2}", BSScene.DetailLogZero, shape.shapeKey.ToString("X"), hullDesc.referenceCount); @@ -306,7 +313,7 @@ public sealed class BSShapeCollection : IDisposable // Remove a reference to a compound shape. // Taking a compound shape apart is a little tricky because if you just delete the - // physical object, it will free all the underlying children. We can't do that because + // physical shape, it will free all the underlying children. We can't do that because // they could be shared. So, this removes each of the children from the compound and // dereferences them separately before destroying the compound collision object itself. // Called at taint-time. @@ -335,22 +342,53 @@ public sealed class BSShapeCollection : IDisposable // Sometimes we have a pointer to a collision shape but don't know what type it is. // Figure out type and call the correct dereference routine. - // This is coming from a compound shape that we created so we know it is either native or mesh. // Called at taint-time. private void DereferenceAnonCollisionShape(IntPtr cShape) { - BulletShape shapeInfo = new BulletShape(cShape, ShapeData.PhysicsShapeType.SHAPE_MESH); - if (BulletSimAPI.IsCompound2(cShape)) - shapeInfo.type = ShapeData.PhysicsShapeType.SHAPE_COMPOUND; + MeshDesc meshDesc; + HullDesc hullDesc; - if (BulletSimAPI.IsNativeShape2(cShape)) + BulletShape shapeInfo = new BulletShape(cShape); + if (TryGetMeshByPtr(cShape, out meshDesc)) + { + shapeInfo.type = ShapeData.PhysicsShapeType.SHAPE_MESH; + shapeInfo.shapeKey = meshDesc.shapeKey; + } + else { - shapeInfo.isNativeShape = true; - shapeInfo.type = ShapeData.PhysicsShapeType.SHAPE_BOX; // (technically, type doesn't matter) + if (TryGetHullByPtr(cShape, out hullDesc)) + { + shapeInfo.type = ShapeData.PhysicsShapeType.SHAPE_HULL; + shapeInfo.shapeKey = hullDesc.shapeKey; + } + else + { + if (BulletSimAPI.IsCompound2(cShape)) + { + shapeInfo.type = ShapeData.PhysicsShapeType.SHAPE_COMPOUND; + } + else + { + if (BulletSimAPI.IsNativeShape2(cShape)) + { + shapeInfo.isNativeShape = true; + shapeInfo.type = ShapeData.PhysicsShapeType.SHAPE_BOX; // (technically, type doesn't matter) + } + } + } } + DetailLog("{0},BSShapeCollection.DereferenceAnonCollisionShape,shape={1}", BSScene.DetailLogZero, shapeInfo); - DereferenceShape(shapeInfo, true, null); + if (shapeInfo.type != ShapeData.PhysicsShapeType.SHAPE_UNKNOWN) + { + DereferenceShape(shapeInfo, true, null); + } + else + { + PhysicsScene.Logger.ErrorFormat("{0} Could not decypher shape type. Region={1}, addr={2}", + LogHeader, PhysicsScene.RegionName, cShape.ToString("X")); + } } // Create the geometry information in Bullet for later use. @@ -913,6 +951,42 @@ public sealed class BSShapeCollection : IDisposable return ret; } + private bool TryGetMeshByPtr(IntPtr addr, out MeshDesc outDesc) + { + bool ret = false; + MeshDesc foundDesc = new MeshDesc(); + foreach (MeshDesc md in Meshes.Values) + { + if (md.ptr == addr) + { + foundDesc = md; + ret = true; + break; + } + + } + outDesc = foundDesc; + return ret; + } + + private bool TryGetHullByPtr(IntPtr addr, out HullDesc outDesc) + { + bool ret = false; + HullDesc foundDesc = new HullDesc(); + foreach (HullDesc hd in Hulls.Values) + { + if (hd.ptr == addr) + { + foundDesc = hd; + ret = true; + break; + } + + } + outDesc = foundDesc; + return ret; + } + private void DetailLog(string msg, params Object[] args) { if (PhysicsScene.PhysicsLogging.Enabled) -- cgit v1.1 From 79f7c466a116bf368423d4e18163f34fd8d66ce1 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Sat, 3 Nov 2012 21:08:39 -0700 Subject: BulletSim: fix compound linkset crash by not freeing shape of child prims. Remove all compilation warnings (mostly 'protected' in sealed classes.) Add the dynamicAabbEnable parameter to creation of compound shapes. --- OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs | 6 +++--- .../Region/Physics/BulletSPlugin/BSLinksetCompound.cs | 11 ++++++----- OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | 3 +++ OpenSim/Region/Physics/BulletSPlugin/BSScene.cs | 4 ++-- .../Region/Physics/BulletSPlugin/BSShapeCollection.cs | 16 ++++++++++------ OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs | 2 +- 6 files changed, 25 insertions(+), 17 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs index 38609e3..819635a 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs @@ -89,7 +89,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin //Angular properties private Vector3 m_angularMotorDirection = Vector3.Zero; // angular velocity requested by LSL motor - private int m_angularMotorApply = 0; // application frame counter + // private int m_angularMotorApply = 0; // application frame counter private Vector3 m_angularMotorVelocity = Vector3.Zero; // current angular motor velocity private float m_angularMotorTimescale = 0; // motor angular velocity ramp up rate private float m_angularMotorDecayTimescale = 0; // motor angular velocity decay rate @@ -199,7 +199,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin break; case Vehicle.ANGULAR_MOTOR_DIRECTION: m_angularMotorDirection = new Vector3(pValue, pValue, pValue); - m_angularMotorApply = 100; + // m_angularMotorApply = 100; break; case Vehicle.LINEAR_FRICTION_TIMESCALE: m_linearFrictionTimescale = new Vector3(pValue, pValue, pValue); @@ -229,7 +229,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin pValue.Y = Math.Max(-12.56f, Math.Min(pValue.Y, 12.56f)); pValue.Z = Math.Max(-12.56f, Math.Min(pValue.Z, 12.56f)); m_angularMotorDirection = new Vector3(pValue.X, pValue.Y, pValue.Z); - m_angularMotorApply = 100; + // m_angularMotorApply = 100; break; case Vehicle.LINEAR_FRICTION_TIMESCALE: m_linearFrictionTimescale = new Vector3(pValue.X, pValue.Y, pValue.Z); diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs index 6e68695..12c6d7a 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs @@ -83,8 +83,8 @@ public sealed class BSLinksetCompound : BSLinkset public override bool MakeDynamic(BSPhysObject child) { bool ret = false; - DetailLog("{0},BSLinksetCompound.MakeDynamic,call,isChild={1}", child.LocalID, HasChild(child)); - if (HasChild(child)) + DetailLog("{0},BSLinksetCompound.MakeDynamic,call,IsRoot={1}", child.LocalID, IsRoot(child)); + if (!IsRoot(child)) { // Physical children are removed from the world as the shape ofthe root compound // shape takes over. @@ -103,8 +103,8 @@ public sealed class BSLinksetCompound : BSLinkset public override bool MakeStatic(BSPhysObject child) { bool ret = false; - DetailLog("{0},BSLinksetCompound.MakeStatic,call,hasChild={1}", child.LocalID, HasChild(child)); - if (HasChild(child)) + DetailLog("{0},BSLinksetCompound.MakeStatic,call,IsRoot={1}", child.LocalID, IsRoot(child)); + if (!IsRoot(child)) { // The non-physical children can come back to life. BulletSimAPI.RemoveFromCollisionFlags2(child.PhysBody.ptr, CollisionFlags.CF_NO_CONTACT_RESPONSE); @@ -240,6 +240,7 @@ public sealed class BSLinksetCompound : BSLinkset // A mesh or hull is created because scale is not available on a native shape. // (TODO: Bullet does have a btScaledCollisionShape. Can that be used?) BulletShape saveShape = cPrim.PhysShape; + cPrim.PhysShape.ptr = IntPtr.Zero; // Don't let the create free the child's shape PhysicsScene.Shapes.CreateGeomMeshOrHull(cPrim, null); BulletShape newShape = cPrim.PhysShape; cPrim.PhysShape = saveShape; @@ -263,7 +264,7 @@ public sealed class BSLinksetCompound : BSLinkset float linksetMass = LinksetMass; LinksetRoot.UpdatePhysicalMassProperties(linksetMass); - // DEBUG: see of inter-linkset collisions are causing problems + // DEBUG: see of inter-linkset collisions are causing problems for constraint linksets. // BulletSimAPI.SetCollisionFilterMask2(LinksetRoot.BSBody.ptr, // (uint)CollisionFilterGroups.LinksetFilter, (uint)CollisionFilterGroups.LinksetMask); diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index af403aa..aaa0d93 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs @@ -703,6 +703,9 @@ public sealed class BSPrim : BSPhysObject // For good measure, make sure the transform is set through to the motion state BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation); + // Center of mass is at the center of the object + BulletSimAPI.SetCenterOfMassByPosRot2(Linkset.LinksetRoot.PhysBody.ptr, _position, _orientation); + // A dynamic object has mass UpdatePhysicalMassProperties(RawMass); diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs index c2e0ef1..740f339 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs @@ -1391,7 +1391,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters // If the local ID is APPLY_TO_NONE, just change the default value // If the localID is APPLY_TO_ALL change the default value and apply the new value to all the lIDs // If the localID is a specific object, apply the parameter change to only that object - protected void UpdateParameterObject(ref float defaultLoc, string parm, uint localID, float val) + private void UpdateParameterObject(ref float defaultLoc, string parm, uint localID, float val) { List objectIDs = new List(); switch (localID) @@ -1416,7 +1416,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters } // schedule the actual updating of the paramter to when the phys engine is not busy - protected void TaintedUpdateParameter(string parm, List lIDs, float val) + private void TaintedUpdateParameter(string parm, List lIDs, float val) { float xval = val; List xlIDs = lIDs; diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs index 4a31c7d..29a23c0 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs @@ -38,7 +38,7 @@ public sealed class BSShapeCollection : IDisposable { private static string LogHeader = "[BULLETSIM SHAPE COLLECTION]"; - protected BSScene PhysicsScene { get; set; } + private BSScene PhysicsScene { get; set; } private Object m_collectionActivityLock = new Object(); @@ -103,11 +103,12 @@ public sealed class BSShapeCollection : IDisposable { // Do we have the correct geometry for this type of object? // Updates prim.BSShape with information/pointers to shape. - // CreateGeom returns 'true' of BSShape as changed to a new shape. + // Returns 'true' of BSShape is changed to a new shape. bool newGeom = CreateGeom(forceRebuild, prim, shapeCallback); // If we had to select a new shape geometry for the object, // rebuild the body around it. // Updates prim.BSBody with information/pointers to requested body + // Returns 'true' if BSBody was changed. bool newBody = CreateBody((newGeom || forceRebuild), prim, PhysicsScene.World, prim.PhysShape, bodyCallback); ret = newGeom || newBody; @@ -431,6 +432,7 @@ public sealed class BSShapeCollection : IDisposable return ret; } + // Create a mesh/hull shape or a native shape if 'nativeShapePossible' is 'true'. private bool CreateGeomNonSpecial(bool forceRebuild, BSPhysObject prim, ShapeDestructionCallback shapeCallback) { bool ret = false; @@ -797,15 +799,17 @@ public sealed class BSShapeCollection : IDisposable private bool GetReferenceToCompoundShape(BSPhysObject prim, ShapeDestructionCallback shapeCallback) { // Remove reference to the old shape - // Don't need to do this as the shape is freed when we create the new root shape below. + // Don't need to do this as the shape is freed when the new root shape is created below. // DereferenceShape(prim.PhysShape, true, shapeCallback); BulletShape cShape = new BulletShape( - BulletSimAPI.CreateCompoundShape2(PhysicsScene.World.ptr), ShapeData.PhysicsShapeType.SHAPE_COMPOUND); + BulletSimAPI.CreateCompoundShape2(PhysicsScene.World.ptr, false), ShapeData.PhysicsShapeType.SHAPE_COMPOUND); - // Create the shape for the root prim and add it to the compound shape - CreateGeomNonSpecial(true, prim, null); + // Create the shape for the root prim and add it to the compound shape. Cannot be a native shape. + CreateGeomMeshOrHull(prim, shapeCallback); BulletSimAPI.AddChildShapeToCompoundShape2(cShape.ptr, prim.PhysShape.ptr, OMV.Vector3.Zero, OMV.Quaternion.Identity); + DetailLog("{0},BSShapeCollection.GetReferenceToCompoundShape,addRootPrim,compShape={1},rootShape={2}", + prim.LocalID, cShape, prim.PhysShape); prim.PhysShape = cShape; diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs index ac6d2b2..702bd77 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs @@ -614,7 +614,7 @@ public static extern bool IsNativeShape2(IntPtr shape); public static extern IntPtr BuildCapsuleShape2(IntPtr world, float radius, float height, Vector3 scale); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern IntPtr CreateCompoundShape2(IntPtr sim); +public static extern IntPtr CreateCompoundShape2(IntPtr sim, bool enableDynamicAabbTree); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern int GetNumberOfCompoundChildren2(IntPtr cShape); -- cgit v1.1 From f391d028de3aff0cc49d024d855555253eb8c02c Mon Sep 17 00:00:00 2001 From: Melanie Date: Sun, 4 Nov 2012 22:01:34 +0100 Subject: Add a method to query all registered script constants to allow non-XEngine script engines to use them. --- .../ScriptModuleComms/ScriptModuleCommsModule.cs | 16 ++++++++++++++++ .../Region/Framework/Interfaces/IScriptModuleComms.cs | 2 ++ 2 files changed, 18 insertions(+) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs b/OpenSim/Region/CoreModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs index 98396ff..dc54c3f 100644 --- a/OpenSim/Region/CoreModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs +++ b/OpenSim/Region/CoreModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs @@ -361,6 +361,22 @@ namespace OpenSim.Region.OptionalModules.Scripting.ScriptModuleComms return null; } + /// + /// Get all registered constants + /// + public Dictionary GetConstants() + { + Dictionary ret = new Dictionary(); + + lock (m_constants) + { + foreach (KeyValuePair kvp in m_constants) + ret[kvp.Key] = kvp.Value; + } + + return ret; + } + #endregion } diff --git a/OpenSim/Region/Framework/Interfaces/IScriptModuleComms.cs b/OpenSim/Region/Framework/Interfaces/IScriptModuleComms.cs index 93930ce..70ff954 100644 --- a/OpenSim/Region/Framework/Interfaces/IScriptModuleComms.cs +++ b/OpenSim/Region/Framework/Interfaces/IScriptModuleComms.cs @@ -27,6 +27,7 @@ using System; using System.Reflection; +using System.Collections.Generic; using OpenMetaverse; namespace OpenSim.Region.Framework.Interfaces @@ -131,6 +132,7 @@ namespace OpenSim.Region.Framework.Interfaces /// Name of constant /// Value of constant or null if none found. object LookupModConstant(string cname); + Dictionary GetConstants(); // For use ONLY by the script API void RaiseEvent(UUID script, string id, string module, string command, string key); -- cgit v1.1 From 89322aaf9424ea9ef58d8a91f34f7856ce597e9b Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Sun, 4 Nov 2012 15:17:47 -0800 Subject: Prevent IMs being sent to prims when avies decline inventory offers from them. --- .../Inventory/Transfer/InventoryTransferModule.cs | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs index 8ff20dd..e200775 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs @@ -434,16 +434,19 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer scene.SendInventoryUpdate(client, trashFolder, true, true); } - ScenePresence user = scene.GetScenePresence(new UUID(im.toAgentID)); - - if (user != null) // Local - { - user.ControllingClient.SendInstantMessage(im); - } - else + if (im.dialog == (byte)InstantMessageDialog.InventoryDeclined) { - if (m_TransferModule != null) - m_TransferModule.SendInstantMessage(im, delegate(bool success) {}); + ScenePresence user = scene.GetScenePresence(new UUID(im.toAgentID)); + + if (user != null) // Local + { + user.ControllingClient.SendInstantMessage(im); + } + else + { + if (m_TransferModule != null) + m_TransferModule.SendInstantMessage(im, delegate(bool success) { }); + } } } } -- cgit v1.1 From cda127e30f0049cda21137363e4d759fd7fd4959 Mon Sep 17 00:00:00 2001 From: teravus Date: Fri, 9 Nov 2012 23:55:30 -0500 Subject: * Prep work switching the GetMeshModule over to a poll service. * This still has the image throttler in it.. as is... so it's not suitable for live yet.... The throttler keeps track of the task throttle but doesn't balance the UDP throttle yet. --- .../ClientStack/Linden/Caps/GetMeshModule.cs | 362 ++++++++++++++++++++- .../ClientStack/Linden/Caps/GetTextureModule.cs | 121 +++---- 2 files changed, 410 insertions(+), 73 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/ClientStack/Linden/Caps/GetMeshModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/GetMeshModule.cs index 0d7b1fc..8deff81 100644 --- a/OpenSim/Region/ClientStack/Linden/Caps/GetMeshModule.cs +++ b/OpenSim/Region/ClientStack/Linden/Caps/GetMeshModule.cs @@ -27,11 +27,14 @@ using System; using System.Collections; +using System.Collections.Generic; using System.Collections.Specialized; using System.Reflection; using System.IO; +using System.Threading; using System.Web; using Mono.Addins; +using OpenSim.Framework.Monitoring; using log4net; using Nini.Config; using OpenMetaverse; @@ -57,8 +60,42 @@ namespace OpenSim.Region.ClientStack.Linden private IAssetService m_AssetService; private bool m_Enabled = true; private string m_URL; + struct aPollRequest + { + public PollServiceMeshEventArgs thepoll; + public UUID reqID; + public Hashtable request; + } + + public class aPollResponse + { + public Hashtable response; + public int bytes; + } + + + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + private static GetMeshHandler m_getMeshHandler; + + private IAssetService m_assetService = null; + + private Dictionary m_capsDict = new Dictionary(); + private static Thread[] m_workerThreads = null; + + private static OpenMetaverse.BlockingQueue m_queue = + new OpenMetaverse.BlockingQueue(); + + private Dictionary m_pollservices = new Dictionary(); - #region IRegionModuleBase Members + #region ISharedRegionModule Members + + ~GetMeshModule() + { + foreach (Thread t in m_workerThreads) + Watchdog.AbortThread(t.ManagedThreadId); + + } public Type ReplaceableInterface { @@ -83,6 +120,8 @@ namespace OpenSim.Region.ClientStack.Linden return; m_scene = pScene; + + m_assetService = pScene.AssetService; } public void RemoveRegion(Scene scene) @@ -91,6 +130,9 @@ namespace OpenSim.Region.ClientStack.Linden return; m_scene.EventManager.OnRegisterCaps -= RegisterCaps; + m_scene.EventManager.OnDeregisterCaps -= DeregisterCaps; + m_scene.EventManager.OnThrottleUpdate -= ThrottleUpdate; + m_scene = null; } @@ -101,6 +143,27 @@ namespace OpenSim.Region.ClientStack.Linden m_AssetService = m_scene.RequestModuleInterface(); m_scene.EventManager.OnRegisterCaps += RegisterCaps; + // We'll reuse the same handler for all requests. + m_getMeshHandler = new GetMeshHandler(m_assetService); + m_scene.EventManager.OnDeregisterCaps += DeregisterCaps; + m_scene.EventManager.OnThrottleUpdate += ThrottleUpdate; + + if (m_workerThreads == null) + { + m_workerThreads = new Thread[2]; + + for (uint i = 0; i < 2; i++) + { + m_workerThreads[i] = Watchdog.StartThread(DoMeshRequests, + String.Format("MeshWorkerThread{0}", i), + ThreadPriority.Normal, + false, + false, + null, + int.MaxValue); + } + } + } @@ -110,25 +173,209 @@ namespace OpenSim.Region.ClientStack.Linden #endregion + private void DoMeshRequests() + { + while (true) + { + aPollRequest poolreq = m_queue.Dequeue(); + + poolreq.thepoll.Process(poolreq); + } + } + + // Now we know when the throttle is changed by the client in the case of a root agent or by a neighbor region in the case of a child agent. + public void ThrottleUpdate(ScenePresence p) + { + byte[] throttles = p.ControllingClient.GetThrottlesPacked(1); + UUID user = p.UUID; + int imagethrottle = ExtractTaskThrottle(throttles); + PollServiceMeshEventArgs args; + if (m_pollservices.TryGetValue(user, out args)) + { + args.UpdateThrottle(imagethrottle); + } + } + + private int ExtractTaskThrottle(byte[] pthrottles) + { + + byte[] adjData; + int pos = 0; + + if (!BitConverter.IsLittleEndian) + { + byte[] newData = new byte[7 * 4]; + Buffer.BlockCopy(pthrottles, 0, newData, 0, 7 * 4); + + for (int i = 0; i < 7; i++) + Array.Reverse(newData, i * 4, 4); + + adjData = newData; + } + else + { + adjData = pthrottles; + } + + // 0.125f converts from bits to bytes + //int resend = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); + //pos += 4; + // int land = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); + //pos += 4; + // int wind = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); + // pos += 4; + // int cloud = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); + // pos += 4; + pos += 16; + int task = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); + // pos += 4; + //int texture = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); //pos += 4; + //int asset = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); + return task; + } + + private class PollServiceMeshEventArgs : PollServiceEventArgs + { + private List requests = + new List(); + private Dictionary responses = + new Dictionary(); + + private Scene m_scene; + private CapsDataThrottler m_throttler = new CapsDataThrottler(100000, 1400000, 10000); + public PollServiceMeshEventArgs(UUID pId, Scene scene) : + base(null, null, null, null, pId, int.MaxValue) + { + m_scene = scene; + // x is request id, y is userid + HasEvents = (x, y) => + { + lock (responses) + { + bool ret = m_throttler.hasEvents(x, responses); + m_throttler.ProcessTime(); + return ret; + + } + }; + GetEvents = (x, y) => + { + lock (responses) + { + try + { + return responses[x].response; + } + finally + { + responses.Remove(x); + } + } + }; + // x is request id, y is request data hashtable + Request = (x, y) => + { + aPollRequest reqinfo = new aPollRequest(); + reqinfo.thepoll = this; + reqinfo.reqID = x; + reqinfo.request = y; + + m_queue.Enqueue(reqinfo); + }; + + // this should never happen except possible on shutdown + NoEvents = (x, y) => + { + /* + lock (requests) + { + Hashtable request = requests.Find(id => id["RequestID"].ToString() == x.ToString()); + requests.Remove(request); + } + */ + Hashtable response = new Hashtable(); + + response["int_response_code"] = 500; + response["str_response_string"] = "Script timeout"; + response["content_type"] = "text/plain"; + response["keepalive"] = false; + response["reusecontext"] = false; + + return response; + }; + } + + public void Process(aPollRequest requestinfo) + { + Hashtable response; + + UUID requestID = requestinfo.reqID; + + // If the avatar is gone, don't bother to get the texture + if (m_scene.GetScenePresence(Id) == null) + { + response = new Hashtable(); + + response["int_response_code"] = 500; + response["str_response_string"] = "Script timeout"; + response["content_type"] = "text/plain"; + response["keepalive"] = false; + response["reusecontext"] = false; + + lock (responses) + responses[requestID] = new aPollResponse() { bytes = 0, response = response }; + + return; + } + + response = m_getMeshHandler.Handle(requestinfo.request); + lock (responses) + { + responses[requestID] = new aPollResponse() + { + bytes = (int)response["int_bytes"], + response = response + }; + + } + m_throttler.ProcessTime(); + } + + internal void UpdateThrottle(int pimagethrottle) + { + m_throttler.ThrottleBytes = pimagethrottle; + } + } public void RegisterCaps(UUID agentID, Caps caps) { // UUID capID = UUID.Random(); - - //caps.RegisterHandler("GetTexture", new StreamHandler("GET", "/CAPS/" + capID, ProcessGetTexture)); if (m_URL == "localhost") { -// m_log.DebugFormat("[GETMESH]: /CAPS/{0} in region {1}", capID, m_scene.RegionInfo.RegionName); - GetMeshHandler gmeshHandler = new GetMeshHandler(m_AssetService); - IRequestHandler reqHandler - = new RestHTTPHandler( - "GET", - "/CAPS/" + UUID.Random(), - httpMethod => gmeshHandler.ProcessGetMesh(httpMethod, UUID.Zero, null), - "GetMesh", - agentID.ToString()); + string capUrl = "/CAPS/" + UUID.Random() + "/"; + + // Register this as a poll service + PollServiceMeshEventArgs args = new PollServiceMeshEventArgs(agentID, m_scene); + + args.Type = PollServiceEventArgs.EventType.Mesh; + MainServer.Instance.AddPollServiceHTTPHandler(capUrl, args); + + string hostName = m_scene.RegionInfo.ExternalHostName; + uint port = (MainServer.Instance == null) ? 0 : MainServer.Instance.Port; + string protocol = "http"; - caps.RegisterHandler("GetMesh", reqHandler); + if (MainServer.Instance.UseSSL) + { + hostName = MainServer.Instance.SSLCommonName; + port = MainServer.Instance.SSLPort; + protocol = "https"; + } + caps.RegisterHandler("GetMesh", String.Format("{0}://{1}:{2}{3}", protocol, hostName, port, capUrl)); + m_pollservices.Add(agentID, args); + m_capsDict[agentID] = capUrl; + + + } else { @@ -136,6 +383,95 @@ namespace OpenSim.Region.ClientStack.Linden caps.RegisterHandler("GetMesh", m_URL); } } + private void DeregisterCaps(UUID agentID, Caps caps) + { + string capUrl; + PollServiceMeshEventArgs args; + if (m_capsDict.TryGetValue(agentID, out capUrl)) + { + MainServer.Instance.RemoveHTTPHandler("", capUrl); + m_capsDict.Remove(agentID); + } + if (m_pollservices.TryGetValue(agentID, out args)) + { + m_pollservices.Remove(agentID); + } + } + + internal sealed class CapsDataThrottler + { + + private volatile int currenttime = 0; + private volatile int lastTimeElapsed = 0; + private volatile int BytesSent = 0; + private int oversizedImages = 0; + public CapsDataThrottler(int pBytes, int max, int min) + { + ThrottleBytes = pBytes; + lastTimeElapsed = Util.EnvironmentTickCount(); + } + public bool hasEvents(UUID key, Dictionary responses) + { + PassTime(); + // Note, this is called IN LOCK + bool haskey = responses.ContainsKey(key); + if (!haskey) + { + return false; + } + aPollResponse response; + if (responses.TryGetValue(key, out response)) + { + + // Normal + if (BytesSent + response.bytes <= ThrottleBytes) + { + BytesSent += response.bytes; + //TimeBasedAction timeBasedAction = new TimeBasedAction { byteRemoval = response.bytes, requestId = key, timeMS = currenttime + 1000, unlockyn = false }; + //m_actions.Add(timeBasedAction); + return true; + } + // Big textures + else if (response.bytes > ThrottleBytes && oversizedImages <= ((ThrottleBytes % 50000) + 1)) + { + Interlocked.Increment(ref oversizedImages); + BytesSent += response.bytes; + //TimeBasedAction timeBasedAction = new TimeBasedAction { byteRemoval = response.bytes, requestId = key, timeMS = currenttime + (((response.bytes % ThrottleBytes)+1)*1000) , unlockyn = false }; + //m_actions.Add(timeBasedAction); + return true; + } + else + { + return false; + } + } + + return haskey; + } + public void ProcessTime() + { + PassTime(); + } + + + private void PassTime() + { + currenttime = Util.EnvironmentTickCount(); + int timeElapsed = Util.EnvironmentTickCountSubtract(currenttime, lastTimeElapsed); + //processTimeBasedActions(responses); + if (Util.EnvironmentTickCountSubtract(currenttime, timeElapsed) >= 1000) + { + lastTimeElapsed = Util.EnvironmentTickCount(); + BytesSent -= ThrottleBytes; + if (BytesSent < 0) BytesSent = 0; + if (BytesSent < ThrottleBytes) + { + oversizedImages = 0; + } + } + } + public int ThrottleBytes; + } } } diff --git a/OpenSim/Region/ClientStack/Linden/Caps/GetTextureModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/GetTextureModule.cs index 8cba6c8..c8c709a 100644 --- a/OpenSim/Region/ClientStack/Linden/Caps/GetTextureModule.cs +++ b/OpenSim/Region/ClientStack/Linden/Caps/GetTextureModule.cs @@ -364,80 +364,81 @@ namespace OpenSim.Region.ClientStack.Linden poolreq.thepoll.Process(poolreq); } } - } - - internal sealed class CapsDataThrottler - { - - private volatile int currenttime = 0; - private volatile int lastTimeElapsed = 0; - private volatile int BytesSent = 0; - private int oversizedImages = 0; - public CapsDataThrottler(int pBytes, int max, int min) - { - ThrottleBytes = pBytes; - lastTimeElapsed = Util.EnvironmentTickCount(); - } - public bool hasEvents(UUID key, Dictionary responses) + internal sealed class CapsDataThrottler { - PassTime(); - // Note, this is called IN LOCK - bool haskey = responses.ContainsKey(key); - if (!haskey) + + private volatile int currenttime = 0; + private volatile int lastTimeElapsed = 0; + private volatile int BytesSent = 0; + private int oversizedImages = 0; + public CapsDataThrottler(int pBytes, int max, int min) { - return false; + ThrottleBytes = pBytes; + lastTimeElapsed = Util.EnvironmentTickCount(); } - GetTextureModule.aPollResponse response; - if (responses.TryGetValue(key,out response)) + public bool hasEvents(UUID key, Dictionary responses) { - - // Normal - if (BytesSent + response.bytes <= ThrottleBytes) + PassTime(); + // Note, this is called IN LOCK + bool haskey = responses.ContainsKey(key); + if (!haskey) { - BytesSent += response.bytes; - //TimeBasedAction timeBasedAction = new TimeBasedAction { byteRemoval = response.bytes, requestId = key, timeMS = currenttime + 1000, unlockyn = false }; - //m_actions.Add(timeBasedAction); - return true; - } - // Big textures - else if (response.bytes > ThrottleBytes && oversizedImages <= ((ThrottleBytes%50000) + 1)) - { - Interlocked.Increment(ref oversizedImages); - BytesSent += response.bytes; - //TimeBasedAction timeBasedAction = new TimeBasedAction { byteRemoval = response.bytes, requestId = key, timeMS = currenttime + (((response.bytes % ThrottleBytes)+1)*1000) , unlockyn = false }; - //m_actions.Add(timeBasedAction); - return true; + return false; } - else + GetTextureModule.aPollResponse response; + if (responses.TryGetValue(key, out response)) { - return false; + + // Normal + if (BytesSent + response.bytes <= ThrottleBytes) + { + BytesSent += response.bytes; + //TimeBasedAction timeBasedAction = new TimeBasedAction { byteRemoval = response.bytes, requestId = key, timeMS = currenttime + 1000, unlockyn = false }; + //m_actions.Add(timeBasedAction); + return true; + } + // Big textures + else if (response.bytes > ThrottleBytes && oversizedImages <= ((ThrottleBytes % 50000) + 1)) + { + Interlocked.Increment(ref oversizedImages); + BytesSent += response.bytes; + //TimeBasedAction timeBasedAction = new TimeBasedAction { byteRemoval = response.bytes, requestId = key, timeMS = currenttime + (((response.bytes % ThrottleBytes)+1)*1000) , unlockyn = false }; + //m_actions.Add(timeBasedAction); + return true; + } + else + { + return false; + } } + + return haskey; + } + public void ProcessTime() + { + PassTime(); } - return haskey; - } - public void ProcessTime() - { - PassTime(); - } - - - private void PassTime() - { - currenttime = Util.EnvironmentTickCount(); - int timeElapsed = Util.EnvironmentTickCountSubtract(currenttime, lastTimeElapsed); - //processTimeBasedActions(responses); - if (Util.EnvironmentTickCountSubtract(currenttime, timeElapsed) >= 1000) + + private void PassTime() { - lastTimeElapsed = Util.EnvironmentTickCount(); - BytesSent -= ThrottleBytes; - if (BytesSent < 0) BytesSent = 0; - if (BytesSent < ThrottleBytes) + currenttime = Util.EnvironmentTickCount(); + int timeElapsed = Util.EnvironmentTickCountSubtract(currenttime, lastTimeElapsed); + //processTimeBasedActions(responses); + if (Util.EnvironmentTickCountSubtract(currenttime, timeElapsed) >= 1000) { - oversizedImages = 0; + lastTimeElapsed = Util.EnvironmentTickCount(); + BytesSent -= ThrottleBytes; + if (BytesSent < 0) BytesSent = 0; + if (BytesSent < ThrottleBytes) + { + oversizedImages = 0; + } } } + public int ThrottleBytes; } - public int ThrottleBytes; } + + } -- cgit v1.1 From e9153e1d1aae50024d8cd05fe14a9bce34343a0e Mon Sep 17 00:00:00 2001 From: teravus Date: Thu, 15 Nov 2012 10:05:16 -0500 Subject: Revert "Merge master into teravuswork", it should have been avination, not master. This reverts commit dfac269032300872c4d0dc507f4f9062d102b0f4, reversing changes made to 619c39e5144f15aca129d6d999bcc5c34133ee64. --- OpenSim/Region/Application/OpenSim.cs | 74 +- OpenSim/Region/Application/OpenSimBase.cs | 74 +- .../Linden/Caps/BunchOfCaps/BunchOfCaps.cs | 9 +- .../Linden/Caps/EventQueue/EventQueueGetModule.cs | 21 +- .../Caps/EventQueue/Tests/EventQueueTests.cs | 2 +- .../ClientStack/Linden/Caps/RegionConsoleModule.cs | 2 +- .../ClientStack/Linden/UDP/IncomingPacket.cs | 7 +- .../Region/ClientStack/Linden/UDP/LLClientView.cs | 169 +- .../Region/ClientStack/Linden/UDP/LLUDPServer.cs | 338 +--- .../ClientStack/Linden/UDP/OpenSimUDPBase.cs | 116 +- .../Region/ClientStack/Linden/UDP/PacketPool.cs | 316 ---- .../Linden/UDP/Tests/BasicCircuitTests.cs | 7 +- .../Region/ClientStack/RegionApplicationBase.cs | 2 +- .../AssetTransaction/AgentAssetsTransactions.cs | 138 +- .../AssetTransaction/AssetTransactionModule.cs | 11 +- .../Agent/AssetTransaction/AssetXferUploader.cs | 222 +-- .../Region/CoreModules/Asset/FlotsamAssetCache.cs | 39 +- .../Asset/Tests/FlotsamAssetCacheTests.cs | 1 + .../Avatar/Attachments/AttachmentsModule.cs | 36 +- .../Attachments/Tests/AttachmentsModuleTests.cs | 76 +- .../Avatar/AvatarFactory/AvatarFactoryModule.cs | 1 - .../Region/CoreModules/Avatar/Chat/ChatModule.cs | 36 +- .../Avatar/Friends/CallingCardModule.cs | 2 +- .../CoreModules/Avatar/Friends/FriendsModule.cs | 59 +- .../Region/CoreModules/Avatar/Gods/GodsModule.cs | 2 +- .../Archiver/InventoryArchiveWriteRequest.cs | 15 +- .../Inventory/Archiver/InventoryArchiverModule.cs | 4 - .../Archiver/Tests/InventoryArchiveTestCase.cs | 26 +- .../Archiver/Tests/InventoryArchiverTests.cs | 68 +- .../Inventory/Transfer/InventoryTransferModule.cs | 196 +-- .../Region/CoreModules/Avatar/Lure/HGLureModule.cs | 2 +- .../Region/CoreModules/Avatar/Lure/LureModule.cs | 4 +- .../EntityTransfer/EntityTransferModule.cs | 76 +- .../EntityTransfer/HGEntityTransferModule.cs | 224 +-- .../Framework/InventoryAccess/HGAssetMapper.cs | 79 +- .../InventoryAccess/HGInventoryAccessModule.cs | 15 +- .../Framework/InventoryAccess/HGUuidGatherer.cs | 57 + .../Framework/Monitoring/MonitorModule.cs | 4 +- .../Framework/Statistics/Logging/LogWriter.cs | 331 ++-- .../UserManagement/HGUserManagementModule.cs | 3 - .../UserManagement/UserManagementModule.cs | 8 +- .../Resources/CoreModulePlugin.addin.xml | 1 - .../Scripting/DynamicTexture/DynamicTexture.cs | 61 - .../DynamicTexture/DynamicTextureModule.cs | 277 +-- .../CoreModules/Scripting/LSLHttp/UrlModule.cs | 17 - .../Scripting/LoadImageURL/LoadImageURLModule.cs | 49 +- .../ScriptModuleComms/ScriptModuleCommsModule.cs | 383 ----- .../VectorRender/Tests/VectorRenderModuleTests.cs | 281 +-- .../Scripting/VectorRender/VectorRenderModule.cs | 159 +- .../Scripting/WorldComm/WorldCommModule.cs | 133 +- .../ServiceConnectorsOut/Asset/HGAssetBroker.cs | 23 +- .../Asset/LocalAssetServiceConnector.cs | 7 +- .../Asset/Tests/AssetConnectorTests.cs | 136 -- .../Grid/Tests/GridConnectorsTests.cs | 10 +- .../GridUser/ActivityDetector.cs | 19 +- .../GridUser/RemoteGridUserServiceConnector.cs | 46 +- .../Simulation/LocalSimulationConnector.cs | 6 +- .../World/Archiver/ArchiveReadRequest.cs | 434 +---- .../World/Archiver/ArchiveScenesGroup.cs | 176 -- .../World/Archiver/ArchiveWriteRequest.cs | 634 ------- .../World/Archiver/ArchiveWriteRequestExecution.cs | 153 ++ .../Archiver/ArchiveWriteRequestPreparation.cs | 438 +++++ .../CoreModules/World/Archiver/ArchiverModule.cs | 25 +- .../CoreModules/World/Archiver/AssetsRequest.cs | 10 - .../World/Archiver/DearchiveScenesGroup.cs | 232 --- .../World/Archiver/Tests/ArchiverTests.cs | 404 +---- .../World/Estate/EstateManagementModule.cs | 1 - .../Region/CoreModules/World/Land/DwellModule.cs | 110 -- .../CoreModules/World/Land/LandManagementModule.cs | 1 - .../Region/CoreModules/World/Land/LandObject.cs | 1 - .../CoreModules/World/Land/PrimCountModule.cs | 2 +- .../World/Objects/Commands/ObjectCommandsModule.cs | 522 +----- .../Region/CoreModules/World/Sound/SoundModule.cs | 313 +--- .../CoreModules/World/Terrain/TerrainModule.cs | 61 +- .../World/Warp3DMap/Warp3DImageModule.cs | 7 - .../Framework/Interfaces/IAttachmentsModule.cs | 9 - .../Framework/Interfaces/IDynamicTextureManager.cs | 69 +- .../Framework/Interfaces/IEntityInventory.cs | 27 +- .../Region/Framework/Interfaces/IEstateModule.cs | 4 - .../Framework/Interfaces/IJsonStoreModule.cs | 2 +- .../Framework/Interfaces/IScriptModuleComms.cs | 71 +- .../Region/Framework/Interfaces/ISoundModule.cs | 93 +- OpenSim/Region/Framework/Interfaces/IUrlModule.cs | 2 - .../Region/Framework/Interfaces/IUserManagement.cs | 29 +- OpenSim/Region/Framework/Interfaces/IWorldComm.cs | 26 +- .../Framework/Scenes/Animation/AnimationSet.cs | 13 - OpenSim/Region/Framework/Scenes/EventManager.cs | 521 +----- OpenSim/Region/Framework/Scenes/Scene.Inventory.cs | 7 +- .../Framework/Scenes/Scene.PacketHandlers.cs | 24 +- OpenSim/Region/Framework/Scenes/Scene.cs | 685 +++----- OpenSim/Region/Framework/Scenes/SceneGraph.cs | 35 +- OpenSim/Region/Framework/Scenes/SceneManager.cs | 6 +- .../Region/Framework/Scenes/SceneObjectGroup.cs | 106 +- OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | 300 ++-- .../Framework/Scenes/SceneObjectPartInventory.cs | 58 +- OpenSim/Region/Framework/Scenes/ScenePresence.cs | 56 +- .../Region/Framework/Scenes/SimStatsReporter.cs | 35 - .../Scenes/Tests/ScenePresenceAgentTests.cs | 2 +- .../Region/Framework/Scenes/Tests/SceneTests.cs | 17 - .../Framework/Scenes/Tests/UserInventoryTests.cs | 36 +- OpenSim/Region/Framework/Scenes/UuidGatherer.cs | 138 +- .../Server/IRCClientView.cs | 7 +- .../OptionalModules/Asset/AssetInfoModule.cs | 3 - .../Avatar/Attachments/AttachmentsCommandModule.cs | 2 +- .../Avatar/Attachments/TempAttachmentsModule.cs | 18 +- .../OptionalModules/Avatar/Chat/IRCConnector.cs | 6 +- .../Avatar/Concierge/ConciergeModule.cs | 5 +- .../Voice/FreeSwitchVoice/FreeSwitchVoiceModule.cs | 2 +- .../Avatar/Voice/VivoxVoice/VivoxVoiceModule.cs | 2 +- .../Avatar/XmlRpcGroups/GroupsMessagingModule.cs | 84 +- .../Avatar/XmlRpcGroups/GroupsModule.cs | 29 - .../Scripting/JsonStore/JsonStoreModule.cs | 14 +- .../Scripting/JsonStore/JsonStoreScriptModule.cs | 2 +- .../Scripting/Minimodule/SOPObject.cs | 7 +- .../RegionReadyModule/RegionReadyModule.cs | 2 +- .../ScriptModuleComms/ScriptModuleCommsModule.cs | 324 ++++ .../Region/OptionalModules/World/NPC/NPCAvatar.cs | 18 +- .../World/NPC/Tests/NPCModuleTests.cs | 11 - .../Physics/BulletSPlugin/BS6DofConstraint.cs | 118 ++ .../Region/Physics/BulletSPlugin/BSCharacter.cs | 689 ++++---- .../Region/Physics/BulletSPlugin/BSConstraint.cs | 51 +- .../Physics/BulletSPlugin/BSConstraint6Dof.cs | 153 -- .../BulletSPlugin/BSConstraintCollection.cs | 4 +- .../Physics/BulletSPlugin/BSConstraintHinge.cs | 57 - OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs | 1051 ++++++------ .../Physics/BulletSPlugin/BSHingeConstraint.cs | 55 + OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs | 431 +++-- .../Physics/BulletSPlugin/BSLinksetCompound.cs | 273 --- .../Physics/BulletSPlugin/BSLinksetConstraints.cs | 327 ---- .../Region/Physics/BulletSPlugin/BSPhysObject.cs | 248 --- OpenSim/Region/Physics/BulletSPlugin/BSPlugin.cs | 4 +- OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | 1364 ++++++++------- OpenSim/Region/Physics/BulletSPlugin/BSScene.cs | 978 +++++------ .../Physics/BulletSPlugin/BSShapeCollection.cs | 1000 ----------- .../Physics/BulletSPlugin/BSTerrainManager.cs | 479 ------ .../Region/Physics/BulletSPlugin/BulletSimAPI.cs | 739 +------- OpenSim/Region/Physics/Manager/PhysicsActor.cs | 6 - OpenSim/Region/Physics/OdePlugin/ODECharacter.cs | 4 +- OpenSim/Region/Physics/OdePlugin/ODEPrim.cs | 25 +- OpenSim/Region/Physics/OdePlugin/OdeScene.cs | 17 +- .../RegionCombinerModule/RegionCombinerModule.cs | 23 +- .../RegionCombinerModule/RegionCourseLocation.cs | 2 +- .../Resources/RegionCombinerModule.addin.xml | 14 - .../Shared/Api/Implementation/LSL_Api.cs | 1790 ++++++++++---------- .../Shared/Api/Implementation/LS_Api.cs | 8 +- .../Shared/Api/Implementation/MOD_Api.cs | 40 +- .../Shared/Api/Implementation/OSSL_Api.cs | 439 +---- .../Api/Implementation/Plugins/SensorRepeat.cs | 13 +- .../ScriptEngine/Shared/Api/Interface/ILSL_Api.cs | 4 +- .../ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs | 139 +- .../Shared/Api/Runtime/LSL_Constants.cs | 64 - .../ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs | 56 +- .../ScriptEngine/Shared/CodeTools/Compiler.cs | 2 - OpenSim/Region/ScriptEngine/Shared/Helpers.cs | 28 +- OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs | 77 +- .../Region/ScriptEngine/Shared/ScriptException.cs | 44 - .../ScriptEngine/Shared/Tests/LSL_ApiListTests.cs | 134 -- .../Shared/Tests/OSSL_ApiAppearanceTest.cs | 70 + .../ScriptEngine/Shared/Tests/OSSL_ApiNpcTests.cs | 184 +- .../Region/ScriptEngine/XEngine/EventManager.cs | 29 +- .../ScriptEngine/XEngine/Tests/XEngineTest.cs | 10 +- OpenSim/Region/ScriptEngine/XEngine/XEngine.cs | 57 +- OpenSim/Region/UserStatistics/WebStatsModule.cs | 56 +- 163 files changed, 6566 insertions(+), 15701 deletions(-) delete mode 100644 OpenSim/Region/ClientStack/Linden/UDP/PacketPool.cs create mode 100644 OpenSim/Region/CoreModules/Framework/InventoryAccess/HGUuidGatherer.cs delete mode 100644 OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTexture.cs delete mode 100644 OpenSim/Region/CoreModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs delete mode 100644 OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/Tests/AssetConnectorTests.cs delete mode 100644 OpenSim/Region/CoreModules/World/Archiver/ArchiveScenesGroup.cs delete mode 100644 OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequest.cs create mode 100644 OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestExecution.cs create mode 100644 OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestPreparation.cs delete mode 100644 OpenSim/Region/CoreModules/World/Archiver/DearchiveScenesGroup.cs delete mode 100644 OpenSim/Region/CoreModules/World/Land/DwellModule.cs create mode 100644 OpenSim/Region/OptionalModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs create mode 100755 OpenSim/Region/Physics/BulletSPlugin/BS6DofConstraint.cs delete mode 100755 OpenSim/Region/Physics/BulletSPlugin/BSConstraint6Dof.cs delete mode 100755 OpenSim/Region/Physics/BulletSPlugin/BSConstraintHinge.cs create mode 100755 OpenSim/Region/Physics/BulletSPlugin/BSHingeConstraint.cs delete mode 100755 OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs delete mode 100755 OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs delete mode 100755 OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs delete mode 100755 OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs delete mode 100755 OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs delete mode 100644 OpenSim/Region/RegionCombinerModule/Resources/RegionCombinerModule.addin.xml delete mode 100644 OpenSim/Region/ScriptEngine/Shared/ScriptException.cs delete mode 100644 OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiListTests.cs (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Application/OpenSim.cs b/OpenSim/Region/Application/OpenSim.cs index 5f07272..6255515 100644 --- a/OpenSim/Region/Application/OpenSim.cs +++ b/OpenSim/Region/Application/OpenSim.cs @@ -35,7 +35,6 @@ using System.Text; using System.Text.RegularExpressions; using System.Timers; using log4net; -using NDesk.Options; using Nini.Config; using OpenMetaverse; using OpenSim.Framework; @@ -254,14 +253,8 @@ namespace OpenSim m_console.Commands.AddCommand("Debug", false, "debug teleport", "debug teleport", "Toggle teleport route debugging", Debug); m_console.Commands.AddCommand("Debug", false, "debug scene", - "debug scene active|collisions|physics|scripting|teleport true|false", - "Turn on scene debugging.", - "If active is false then main scene update and maintenance loops are suspended.\n" - + "If collisions is false then collisions with other objects are turned off.\n" - + "If physics is false then all physics objects are non-physical.\n" - + "If scripting is false then no scripting operations happen.\n" - + "If teleport is true then some extra teleport debug information is logged.", - Debug); + "debug scene ", + "Turn on scene debugging", Debug); m_console.Commands.AddCommand("General", false, "change region", "change region ", @@ -298,7 +291,7 @@ namespace OpenSim m_console.Commands.AddCommand("Archiving", false, "save oar", //"save oar [-v|--version=] [-p|--profile=] []", - "save oar [-h|--home=] [--noassets] [--publish] [--perm=] [--all] []", + "save oar [-h|--home=] [--noassets] [--publish] [--perm=] []", "Save a region's data to an OAR archive.", // "-v|--version= generates scene objects as per older versions of the serialization (e.g. -v=0)" + Environment.NewLine "-h|--home= adds the url of the profile service to the saved user information.\n" @@ -308,7 +301,6 @@ namespace OpenSim + " this is useful if you're making oars generally available that might be reloaded to the same grid from which you published\n" + "--perm= stops objects with insufficient permissions from being saved to the OAR.\n" + " can contain one or more of these characters: \"C\" = Copy, \"T\" = Transfer\n" - + "--all saves all the regions in the simulator, instead of just the current region.\n" + "The OAR path must be a filesystem path." + " If this is not given then the oar is saved to region.oar in the current directory.", SaveOar); @@ -318,11 +310,8 @@ namespace OpenSim "Change the scale of a named prim", HandleEditScale); m_console.Commands.AddCommand("Users", false, "kick user", - "kick user [--force] [message]", - "Kick a user off the simulator", - "The --force option will kick the user without any checks to see whether it's already in the process of closing\n" - + "Only use this option if you are sure the avatar is inactive and a normal kick user operation does not removed them", - KickUserCommand); + "kick user [message]", + "Kick a user off the simulator", KickUserCommand); m_console.Commands.AddCommand("Users", false, "show users", "show users [full]", @@ -339,6 +328,10 @@ namespace OpenSim "show circuits", "Show agent circuit data", HandleShow); + m_console.Commands.AddCommand("Comms", false, "show http-handlers", + "show http-handlers", + "Show all registered http handlers", HandleShow); + m_console.Commands.AddCommand("Comms", false, "show pending-objects", "show pending-objects", "Show # of objects on the pending queues of all scene viewers", HandleShow); @@ -423,7 +416,6 @@ namespace OpenSim { RunCommandScript(m_shutdownCommandsFile); } - base.ShutdownSpecific(); } @@ -461,17 +453,11 @@ namespace OpenSim /// name of avatar to kick private void KickUserCommand(string module, string[] cmdparams) { - bool force = false; - - OptionSet options = new OptionSet().Add("f|force", delegate (string v) { force = v != null; }); - - List mainParams = options.Parse(cmdparams); - - if (mainParams.Count < 4) + if (cmdparams.Length < 4) return; string alert = null; - if (mainParams.Count > 4) + if (cmdparams.Length > 4) alert = String.Format("\n{0}\n", String.Join(" ", cmdparams, 4, cmdparams.Length - 4)); IList agents = SceneManager.GetCurrentSceneAvatars(); @@ -480,8 +466,8 @@ namespace OpenSim { RegionInfo regionInfo = presence.Scene.RegionInfo; - if (presence.Firstname.ToLower().Contains(mainParams[2].ToLower()) && - presence.Lastname.ToLower().Contains(mainParams[3].ToLower())) + if (presence.Firstname.ToLower().Contains(cmdparams[2].ToLower()) && + presence.Lastname.ToLower().Contains(cmdparams[3].ToLower())) { MainConsole.Instance.Output( String.Format( @@ -494,7 +480,7 @@ namespace OpenSim else presence.ControllingClient.Kick("\nYou have been logged out by an administrator.\n"); - presence.Scene.IncomingCloseAgent(presence.UUID, force); + presence.Scene.IncomingCloseAgent(presence.UUID); } } @@ -936,8 +922,7 @@ namespace OpenSim } else { - MainConsole.Instance.Output( - "Usage: debug scene active|scripting|collisions|physics|teleport true|false"); + MainConsole.Instance.Output("Usage: debug scene scripting|collisions|physics|teleport true|false"); } break; @@ -1017,6 +1002,33 @@ namespace OpenSim HandleShowCircuits(); break; + case "http-handlers": + System.Text.StringBuilder handlers = new System.Text.StringBuilder("Registered HTTP Handlers:\n"); + + handlers.AppendFormat("* XMLRPC:\n"); + foreach (String s in HttpServer.GetXmlRpcHandlerKeys()) + handlers.AppendFormat("\t{0}\n", s); + + handlers.AppendFormat("* HTTP:\n"); + List poll = HttpServer.GetPollServiceHandlerKeys(); + foreach (String s in HttpServer.GetHTTPHandlerKeys()) + handlers.AppendFormat("\t{0} {1}\n", s, (poll.Contains(s) ? "(poll service)" : string.Empty)); + + handlers.AppendFormat("* Agent:\n"); + foreach (String s in HttpServer.GetAgentHandlerKeys()) + handlers.AppendFormat("\t{0}\n", s); + + handlers.AppendFormat("* LLSD:\n"); + foreach (String s in HttpServer.GetLLSDHandlerKeys()) + handlers.AppendFormat("\t{0}\n", s); + + handlers.AppendFormat("* StreamHandlers ({0}):\n", HttpServer.GetStreamHandlerKeys().Count); + foreach (String s in HttpServer.GetStreamHandlerKeys()) + handlers.AppendFormat("\t{0}\n", s); + + MainConsole.Instance.Output(handlers.ToString()); + break; + case "modules": MainConsole.Instance.Output("The currently loaded shared modules are:"); foreach (IRegionModule module in m_moduleLoader.GetLoadedSharedModules) @@ -1111,7 +1123,7 @@ namespace OpenSim aCircuit.Name, aCircuit.child ? "child" : "root", aCircuit.circuitcode.ToString(), - aCircuit.IPAddress != null ? aCircuit.IPAddress.ToString() : "not set", + aCircuit.IPAddress.ToString(), aCircuit.Viewer); }); diff --git a/OpenSim/Region/Application/OpenSimBase.cs b/OpenSim/Region/Application/OpenSimBase.cs index 7232383..d107b7a 100644 --- a/OpenSim/Region/Application/OpenSimBase.cs +++ b/OpenSim/Region/Application/OpenSimBase.cs @@ -232,6 +232,8 @@ namespace OpenSim base.StartupSpecific(); + m_stats = StatsManager.SimExtraStats; + // Create a ModuleLoader instance m_moduleLoader = new ModuleLoader(m_config.Source); @@ -247,51 +249,51 @@ namespace OpenSim plugin.PostInitialise(); } - if (m_console != null) - { - StatsManager.RegisterConsoleCommands(m_console); - AddPluginCommands(m_console); - } + AddPluginCommands(); } - protected virtual void AddPluginCommands(CommandConsole console) + protected virtual void AddPluginCommands() { - List topics = GetHelpTopics(); - - foreach (string topic in topics) + // If console exists add plugin commands. + if (m_console != null) { - string capitalizedTopic = char.ToUpper(topic[0]) + topic.Substring(1); + List topics = GetHelpTopics(); - // This is a hack to allow the user to enter the help command in upper or lowercase. This will go - // away at some point. - console.Commands.AddCommand(capitalizedTopic, false, "help " + topic, - "help " + capitalizedTopic, - "Get help on plugin command '" + topic + "'", - HandleCommanderHelp); - console.Commands.AddCommand(capitalizedTopic, false, "help " + capitalizedTopic, - "help " + capitalizedTopic, - "Get help on plugin command '" + topic + "'", - HandleCommanderHelp); + foreach (string topic in topics) + { + string capitalizedTopic = char.ToUpper(topic[0]) + topic.Substring(1); - ICommander commander = null; + // This is a hack to allow the user to enter the help command in upper or lowercase. This will go + // away at some point. + m_console.Commands.AddCommand(capitalizedTopic, false, "help " + topic, + "help " + capitalizedTopic, + "Get help on plugin command '" + topic + "'", + HandleCommanderHelp); + m_console.Commands.AddCommand(capitalizedTopic, false, "help " + capitalizedTopic, + "help " + capitalizedTopic, + "Get help on plugin command '" + topic + "'", + HandleCommanderHelp); - Scene s = SceneManager.CurrentOrFirstScene; + ICommander commander = null; - if (s != null && s.GetCommanders() != null) - { - if (s.GetCommanders().ContainsKey(topic)) - commander = s.GetCommanders()[topic]; - } + Scene s = SceneManager.CurrentOrFirstScene; - if (commander == null) - continue; + if (s != null && s.GetCommanders() != null) + { + if (s.GetCommanders().ContainsKey(topic)) + commander = s.GetCommanders()[topic]; + } - foreach (string command in commander.Commands.Keys) - { - console.Commands.AddCommand(capitalizedTopic, false, - topic + " " + command, - topic + " " + commander.Commands[command].ShortHelp(), - String.Empty, HandleCommanderCommand); + if (commander == null) + continue; + + foreach (string command in commander.Commands.Keys) + { + m_console.Commands.AddCommand(capitalizedTopic, false, + topic + " " + command, + topic + " " + commander.Commands[command].ShortHelp(), + String.Empty, HandleCommanderCommand); + } } } } @@ -621,7 +623,7 @@ namespace OpenSim if (account == null) { m_log.ErrorFormat( - "[OPENSIM]: Unable to store account. If this simulator is connected to a grid, you must create the estate owner account first at the grid level."); + "[OPENSIM]: Unable to store account. If this simulator is connected to a grid, you must create the estate owner account first."); } else { diff --git a/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs b/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs index f6146a9..650cd50 100644 --- a/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs +++ b/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs @@ -241,8 +241,8 @@ namespace OpenSim.Region.ClientStack.Linden m_HostCapsObj.RegisterHandler( "SEED", new RestStreamHandler("POST", capsBase + m_requestPath, SeedCapRequest, "SEED", null)); -// m_log.DebugFormat( -// "[CAPS]: Registered seed capability {0} for {1}", capsBase + m_requestPath, m_HostCapsObj.AgentID); + m_log.DebugFormat( + "[CAPS]: Registered seed capability {0} for {1}", capsBase + m_requestPath, m_HostCapsObj.AgentID); //m_capsHandlers["MapLayer"] = // new LLSDStreamhandler("POST", @@ -337,12 +337,11 @@ namespace OpenSim.Region.ClientStack.Linden public string SeedCapRequest(string request, string path, string param, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) { - m_log.DebugFormat( - "[CAPS]: Received SEED caps request in {0} for agent {1}", m_regionName, m_HostCapsObj.AgentID); +// m_log.Debug("[CAPS]: Seed Caps Request in region: " + m_regionName); if (!m_Scene.CheckClient(m_HostCapsObj.AgentID, httpRequest.RemoteIPEndPoint)) { - m_log.WarnFormat( + m_log.DebugFormat( "[CAPS]: Unauthorized CAPS client {0} from {1}", m_HostCapsObj.AgentID, httpRequest.RemoteIPEndPoint); diff --git a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs index 5bbdce8..e113c60 100644 --- a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs +++ b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs @@ -94,7 +94,7 @@ namespace OpenSim.Region.ClientStack.Linden //scene.CommsManager.HttpServer.AddLLSDHandler("/CAPS/EQG/", EventQueueFallBack); -// scene.EventManager.OnNewClient += OnNewClient; + scene.EventManager.OnNewClient += OnNewClient; // TODO: Leaving these open, or closing them when we // become a child is incorrect. It messes up TP in a big @@ -102,7 +102,6 @@ namespace OpenSim.Region.ClientStack.Linden // circuit is there. scene.EventManager.OnClientClosed += ClientClosed; - scene.EventManager.OnMakeChildAgent += MakeChildAgent; scene.EventManager.OnRegisterCaps += OnRegisterCaps; @@ -111,10 +110,10 @@ namespace OpenSim.Region.ClientStack.Linden false, "debug eq", "debug eq [0|1|2]", - "Turn on event queue debugging\n" - + " <= 0 - turns off all event queue logging\n" - + " >= 1 - turns on outgoing event logging\n" - + " >= 2 - turns on poll notification", + "Turn on event queue debugging" + + "<= 0 - turns off all event queue logging" + + ">= 1 - turns on outgoing event logging" + + ">= 2 - turns on poll notification", HandleDebugEq); } else @@ -227,6 +226,16 @@ namespace OpenSim.Region.ClientStack.Linden #endregion + private void OnNewClient(IClientAPI client) + { + //client.OnLogout += ClientClosed; + } + +// private void ClientClosed(IClientAPI client) +// { +// ClientClosed(client.AgentId); +// } + private void ClientClosed(UUID agentID, Scene scene) { // m_log.DebugFormat("[EVENTQUEUE]: Closed client {0} in region {1}", agentID, m_scene.RegionInfo.RegionName); diff --git a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/Tests/EventQueueTests.cs b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/Tests/EventQueueTests.cs index d604cf6..cd70410 100644 --- a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/Tests/EventQueueTests.cs +++ b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/Tests/EventQueueTests.cs @@ -94,7 +94,7 @@ namespace OpenSim.Region.ClientStack.Linden.Tests UUID spId = TestHelpers.ParseTail(0x1); SceneHelpers.AddScenePresence(m_scene, spId); - m_scene.IncomingCloseAgent(spId, false); + m_scene.IncomingCloseAgent(spId); // TODO: Add more assertions for the other aspects of event queues Assert.That(MainServer.Instance.GetPollServiceHandlerKeys().Count, Is.EqualTo(0)); diff --git a/OpenSim/Region/ClientStack/Linden/Caps/RegionConsoleModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/RegionConsoleModule.cs index fcac182..0a5ad0f 100644 --- a/OpenSim/Region/ClientStack/Linden/Caps/RegionConsoleModule.cs +++ b/OpenSim/Region/ClientStack/Linden/Caps/RegionConsoleModule.cs @@ -109,7 +109,7 @@ namespace OpenSim.Region.ClientStack.Linden UUID capID = UUID.Random(); -// m_log.DebugFormat("[REGION CONSOLE]: /CAPS/{0} in region {1}", capID, m_scene.RegionInfo.RegionName); + m_log.DebugFormat("[REGION CONSOLE]: /CAPS/{0} in region {1}", capID, m_scene.RegionInfo.RegionName); caps.RegisterHandler( "SimConsoleAsync", new ConsoleHandler("/CAPS/" + capID + "/", "SimConsoleAsync", agentID, this, m_scene)); diff --git a/OpenSim/Region/ClientStack/Linden/UDP/IncomingPacket.cs b/OpenSim/Region/ClientStack/Linden/UDP/IncomingPacket.cs index e22670b..1b8535c 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/IncomingPacket.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/IncomingPacket.cs @@ -45,12 +45,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP public Packet Packet; /// - /// No arg constructor. - /// - public IncomingPacket() {} - - /// - /// Constructor + /// Default constructor /// /// Reference to the client this packet came from /// Packet data diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index c9aa4ca..ae9ed7f 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -47,7 +47,6 @@ using OpenSim.Region.Framework.Scenes; using OpenSim.Services.Interfaces; using Timer = System.Timers.Timer; using AssetLandmark = OpenSim.Framework.AssetLandmark; -using RegionFlags = OpenMetaverse.RegionFlags; using Nini.Config; using System.IO; @@ -356,17 +355,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP private bool m_deliverPackets = true; private int m_animationSequenceNumber = 1; private bool m_SendLogoutPacketWhenClosing = true; - - /// - /// We retain a single AgentUpdateArgs so that we can constantly reuse it rather than construct a new one for - /// every single incoming AgentUpdate. Every client sends 10 AgentUpdate UDP messages per second, even if it - /// is doing absolutely nothing. - /// - /// - /// This does mean that agent updates must be processed synchronously, at least for each client, and called methods - /// cannot retain a reference to it outside of that method. - /// - private AgentUpdateArgs m_lastAgentUpdateArgs; + private AgentUpdateArgs lastarg; protected Dictionary m_packetHandlers = new Dictionary(); protected Dictionary m_genericPacketHandlers = new Dictionary(); //PauPaw:Local Generic Message handlers @@ -521,18 +510,19 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// public void Close() { - Close(true, false); + Close(true); } - public void Close(bool sendStop, bool force) + /// + /// Shut down the client view + /// + public void Close(bool sendStop) { // We lock here to prevent race conditions between two threads calling close simultaneously (e.g. // a simultaneous relog just as a client is being closed out due to no packet ack from the old connection. lock (CloseSyncLock) { - // We still perform a force close inside the sync lock since this is intended to attempt close where - // there is some unidentified connection problem, not where we have issues due to deadlock - if (!IsActive && !force) + if (!IsActive) return; IsActive = false; @@ -847,9 +837,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP OutPacket(mov, ThrottleOutPacketType.Unknown); } - public void SendChatMessage( - string message, byte type, Vector3 fromPos, string fromName, - UUID fromAgentID, UUID ownerID, byte source, byte audible) + public void SendChatMessage(string message, byte type, Vector3 fromPos, string fromName, + UUID fromAgentID, byte source, byte audible) { ChatFromSimulatorPacket reply = (ChatFromSimulatorPacket)PacketPool.Instance.GetPacket(PacketType.ChatFromSimulator); reply.ChatData.Audible = audible; @@ -858,7 +847,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP reply.ChatData.SourceType = source; reply.ChatData.Position = fromPos; reply.ChatData.FromName = Util.StringToBytes256(fromName); - reply.ChatData.OwnerID = ownerID; + reply.ChatData.OwnerID = fromAgentID; reply.ChatData.SourceID = fromAgentID; OutPacket(reply, ThrottleOutPacketType.Unknown); @@ -3996,8 +3985,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP { List blocks = terseAgentUpdateBlocks.Value; - ImprovedTerseObjectUpdatePacket packet - = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ImprovedTerseObjectUpdate); + ImprovedTerseObjectUpdatePacket packet = new ImprovedTerseObjectUpdatePacket(); packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle; packet.RegionData.TimeDilation = timeDilation; packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count]; @@ -4042,9 +4030,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP { List blocks = terseUpdateBlocks.Value; - ImprovedTerseObjectUpdatePacket packet - = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket( - PacketType.ImprovedTerseObjectUpdate); + ImprovedTerseObjectUpdatePacket packet = new ImprovedTerseObjectUpdatePacket(); packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle; packet.RegionData.TimeDilation = timeDilation; packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count]; @@ -4052,7 +4038,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP for (int i = 0; i < blocks.Count; i++) packet.ObjectData[i] = blocks[i]; - OutPacket(packet, ThrottleOutPacketType.Task, true, delegate(OutgoingPacket oPacket) { ResendPrimUpdates(terseUpdates.Value, oPacket); }); + OutPacket(packet, ThrottleOutPacketType.Task, true); } #endregion Packet Sending @@ -4549,7 +4535,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP { returnblock[j] = new EstateOwnerMessagePacket.ParamListBlock(); } - j = 0; + j = 0; returnblock[j].Parameter = Utils.StringToBytes(estateID.ToString()); j++; returnblock[j].Parameter = Utils.StringToBytes(((int)Constants.EstateAccessCodex.EstateBans).ToString()); j++; @@ -5053,9 +5039,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP Utils.UInt16ToBytes(Utils.FloatToUInt16(angularVelocity.Y, -64.0f, 64.0f), data, pos); pos += 2; Utils.UInt16ToBytes(Utils.FloatToUInt16(angularVelocity.Z, -64.0f, 64.0f), data, pos); pos += 2; - ImprovedTerseObjectUpdatePacket.ObjectDataBlock block - = PacketPool.Instance.GetDataBlock(); - + ImprovedTerseObjectUpdatePacket.ObjectDataBlock block = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock(); block.Data = data; if (textureEntry != null && textureEntry.Length > 0) @@ -5305,18 +5289,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP protected virtual void RegisterLocalPacketHandlers() { AddLocalPacketHandler(PacketType.LogoutRequest, HandleLogout); - - // If AgentUpdate is ever handled asynchronously, then we will also need to construct a new AgentUpdateArgs - // for each AgentUpdate packet. AddLocalPacketHandler(PacketType.AgentUpdate, HandleAgentUpdate, false); - AddLocalPacketHandler(PacketType.ViewerEffect, HandleViewerEffect, false); AddLocalPacketHandler(PacketType.AgentCachedTexture, HandleAgentTextureCached, false); AddLocalPacketHandler(PacketType.MultipleObjectUpdate, HandleMultipleObjUpdate, false); AddLocalPacketHandler(PacketType.MoneyTransferRequest, HandleMoneyTransferRequest, false); AddLocalPacketHandler(PacketType.ParcelBuy, HandleParcelBuyRequest, false); - AddLocalPacketHandler(PacketType.UUIDGroupNameRequest, HandleUUIDGroupNameRequest); - AddLocalPacketHandler(PacketType.ObjectGroup, HandleObjectGroupRequest); + AddLocalPacketHandler(PacketType.UUIDGroupNameRequest, HandleUUIDGroupNameRequest, false); + AddLocalPacketHandler(PacketType.ObjectGroup, HandleObjectGroupRequest, false); AddLocalPacketHandler(PacketType.GenericMessage, HandleGenericMessage); AddLocalPacketHandler(PacketType.AvatarPropertiesRequest, HandleAvatarPropertiesRequest); AddLocalPacketHandler(PacketType.ChatFromViewer, HandleChatFromViewer); @@ -5538,84 +5518,81 @@ namespace OpenSim.Region.ClientStack.LindenUDP #region Scene/Avatar - private bool HandleAgentUpdate(IClientAPI sener, Packet packet) + private bool HandleAgentUpdate(IClientAPI sener, Packet Pack) { if (OnAgentUpdate != null) { - AgentUpdatePacket agentUpdate = (AgentUpdatePacket)packet; + bool update = false; + AgentUpdatePacket agenUpdate = (AgentUpdatePacket)Pack; #region Packet Session and User Check - if (agentUpdate.AgentData.SessionID != SessionId || agentUpdate.AgentData.AgentID != AgentId) - { - PacketPool.Instance.ReturnPacket(packet); + if (agenUpdate.AgentData.SessionID != SessionId || agenUpdate.AgentData.AgentID != AgentId) return false; - } #endregion - bool update = false; - AgentUpdatePacket.AgentDataBlock x = agentUpdate.AgentData; + AgentUpdatePacket.AgentDataBlock x = agenUpdate.AgentData; + + // We can only check when we have something to check + // against. - if (m_lastAgentUpdateArgs != null) + if (lastarg != null) { - // These should be ordered from most-likely to - // least likely to change. I've made an initial - // guess at that. update = ( - (x.BodyRotation != m_lastAgentUpdateArgs.BodyRotation) || - (x.CameraAtAxis != m_lastAgentUpdateArgs.CameraAtAxis) || - (x.CameraCenter != m_lastAgentUpdateArgs.CameraCenter) || - (x.CameraLeftAxis != m_lastAgentUpdateArgs.CameraLeftAxis) || - (x.CameraUpAxis != m_lastAgentUpdateArgs.CameraUpAxis) || - (x.ControlFlags != m_lastAgentUpdateArgs.ControlFlags) || + (x.BodyRotation != lastarg.BodyRotation) || + (x.CameraAtAxis != lastarg.CameraAtAxis) || + (x.CameraCenter != lastarg.CameraCenter) || + (x.CameraLeftAxis != lastarg.CameraLeftAxis) || + (x.CameraUpAxis != lastarg.CameraUpAxis) || + (x.ControlFlags != lastarg.ControlFlags) || (x.ControlFlags != 0) || - (x.Far != m_lastAgentUpdateArgs.Far) || - (x.Flags != m_lastAgentUpdateArgs.Flags) || - (x.State != m_lastAgentUpdateArgs.State) || - (x.HeadRotation != m_lastAgentUpdateArgs.HeadRotation) || - (x.SessionID != m_lastAgentUpdateArgs.SessionID) || - (x.AgentID != m_lastAgentUpdateArgs.AgentID) + (x.Far != lastarg.Far) || + (x.Flags != lastarg.Flags) || + (x.State != lastarg.State) || + (x.HeadRotation != lastarg.HeadRotation) || + (x.SessionID != lastarg.SessionID) || + (x.AgentID != lastarg.AgentID) ); } else { - m_lastAgentUpdateArgs = new AgentUpdateArgs(); update = true; } + // These should be ordered from most-likely to + // least likely to change. I've made an initial + // guess at that. + if (update) { // m_log.DebugFormat("[LLCLIENTVIEW]: Triggered AgentUpdate for {0}", sener.Name); - m_lastAgentUpdateArgs.AgentID = x.AgentID; - m_lastAgentUpdateArgs.BodyRotation = x.BodyRotation; - m_lastAgentUpdateArgs.CameraAtAxis = x.CameraAtAxis; - m_lastAgentUpdateArgs.CameraCenter = x.CameraCenter; - m_lastAgentUpdateArgs.CameraLeftAxis = x.CameraLeftAxis; - m_lastAgentUpdateArgs.CameraUpAxis = x.CameraUpAxis; - m_lastAgentUpdateArgs.ControlFlags = x.ControlFlags; - m_lastAgentUpdateArgs.Far = x.Far; - m_lastAgentUpdateArgs.Flags = x.Flags; - m_lastAgentUpdateArgs.HeadRotation = x.HeadRotation; - m_lastAgentUpdateArgs.SessionID = x.SessionID; - m_lastAgentUpdateArgs.State = x.State; - + AgentUpdateArgs arg = new AgentUpdateArgs(); + arg.AgentID = x.AgentID; + arg.BodyRotation = x.BodyRotation; + arg.CameraAtAxis = x.CameraAtAxis; + arg.CameraCenter = x.CameraCenter; + arg.CameraLeftAxis = x.CameraLeftAxis; + arg.CameraUpAxis = x.CameraUpAxis; + arg.ControlFlags = x.ControlFlags; + arg.Far = x.Far; + arg.Flags = x.Flags; + arg.HeadRotation = x.HeadRotation; + arg.SessionID = x.SessionID; + arg.State = x.State; UpdateAgent handlerAgentUpdate = OnAgentUpdate; UpdateAgent handlerPreAgentUpdate = OnPreAgentUpdate; - + lastarg = arg; // save this set of arguments for nexttime if (handlerPreAgentUpdate != null) - OnPreAgentUpdate(this, m_lastAgentUpdateArgs); - + OnPreAgentUpdate(this, arg); if (handlerAgentUpdate != null) - OnAgentUpdate(this, m_lastAgentUpdateArgs); + OnAgentUpdate(this, arg); handlerAgentUpdate = null; handlerPreAgentUpdate = null; } } - PacketPool.Instance.ReturnPacket(packet); - return true; } @@ -5987,8 +5964,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP msgpack.MessageBlock.ID, msgpack.MessageBlock.Offline != 0 ? true : false, msgpack.MessageBlock.Position, - msgpack.MessageBlock.BinaryBucket, - true); + msgpack.MessageBlock.BinaryBucket); handlerInstantMessage(this, im); } @@ -9275,9 +9251,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP } #endregion - string method = Utils.BytesToString(messagePacket.MethodData.Method); - - switch (method) + switch (Utils.BytesToString(messagePacket.MethodData.Method)) { case "getinfo": if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false)) @@ -9593,17 +9567,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP return true; default: - m_log.WarnFormat( - "[LLCLIENTVIEW]: EstateOwnerMessage: Unknown method {0} requested for {1} in {2}", - method, Name, Scene.Name); - - for (int i = 0; i < messagePacket.ParamList.Length; i++) - { - EstateOwnerMessagePacket.ParamListBlock block = messagePacket.ParamList[i]; - string data = (string)Utils.BytesToString(block.Parameter); - m_log.DebugFormat("[LLCLIENTVIEW]: Param {0}={1}", i, data); - } - + m_log.Error("EstateOwnerMessage: Unknown method requested\n" + messagePacket); return true; } @@ -11996,7 +11960,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP logPacket = false; if (DebugPacketLevel <= 50 - && (packet.Type == PacketType.ImprovedTerseObjectUpdate || packet.Type == PacketType.ObjectUpdate)) + & (packet.Type == PacketType.ImprovedTerseObjectUpdate || packet.Type == PacketType.ObjectUpdate)) logPacket = false; if (DebugPacketLevel <= 25 && packet.Type == PacketType.ObjectPropertiesFamily) @@ -12070,6 +12034,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP if (!ProcessPacketMethod(packet)) m_log.Warn("[CLIENT]: unhandled packet " + packet.Type); + + PacketPool.Instance.ReturnPacket(packet); } private static PrimitiveBaseShape GetShapeFromAddPacket(ObjectAddPacket addPacket) @@ -12238,7 +12204,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP { Kick(reason); Thread.Sleep(1000); - Disconnect(); + Close(); } public void Disconnect() @@ -12526,10 +12492,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP ushort timeDilation = Utils.FloatToUInt16(TIME_DILATION, 0.0f, 1.0f); - ImprovedTerseObjectUpdatePacket packet - = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket( - PacketType.ImprovedTerseObjectUpdate); - + ImprovedTerseObjectUpdatePacket packet = new ImprovedTerseObjectUpdatePacket(); packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle; packet.RegionData.TimeDilation = timeDilation; packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[1]; diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs index b8951d9..d6513c5 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs @@ -37,7 +37,6 @@ using log4net; using Nini.Config; using OpenMetaverse.Packets; using OpenSim.Framework; -using OpenSim.Framework.Console; using OpenSim.Framework.Monitoring; using OpenSim.Region.Framework.Scenes; using OpenMetaverse; @@ -101,11 +100,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// The measured resolution of Environment.TickCount public readonly float TickCountResolution; - /// Number of prim updates to put on the queue each time the /// OnQueueEmpty event is triggered for updates public readonly int PrimUpdatesPerCallback; - /// Number of texture packets to put on the queue each time the /// OnQueueEmpty event is triggered for textures public readonly int TextureSendLimit; @@ -127,37 +124,28 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// Manages authentication for agent circuits private AgentCircuitManager m_circuitManager; - /// Reference to the scene this UDP server is attached to protected Scene m_scene; - /// The X/Y coordinates of the scene this UDP server is attached to private Location m_location; - /// The size of the receive buffer for the UDP socket. This value /// is passed up to the operating system and used in the system networking /// stack. Use zero to leave this value as the default private int m_recvBufferSize; - /// Flag to process packets asynchronously or synchronously private bool m_asyncPacketHandling; - /// Tracks whether or not a packet was sent each round so we know /// whether or not to sleep private bool m_packetSent; /// Environment.TickCount of the last time that packet stats were reported to the scene private int m_elapsedMSSinceLastStatReport = 0; - /// Environment.TickCount of the last time the outgoing packet handler executed private int m_tickLastOutgoingPacketHandler; - /// Keeps track of the number of elapsed milliseconds since the last time the outgoing packet handler looped private int m_elapsedMSOutgoingPacketHandler; - /// Keeps track of the number of 100 millisecond periods elapsed in the outgoing packet handler executed private int m_elapsed100MSOutgoingPacketHandler; - /// Keeps track of the number of 500 millisecond periods elapsed in the outgoing packet handler executed private int m_elapsed500MSOutgoingPacketHandler; @@ -171,9 +159,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP protected bool m_sendPing; private ExpiringCache> m_pendingCache = new ExpiringCache>(); - private Pool m_incomingPacketPool; - - private Stat m_incomingPacketPoolStat; private int m_defaultRTO = 0; private int m_maxRTO = 0; @@ -195,9 +180,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// private IClientAPI m_currentIncomingClient; - public LLUDPServer( - IPAddress listenIP, ref uint port, int proxyPortOffsetParm, bool allow_alternate_port, - IConfigSource configSource, AgentCircuitManager circuitManager) + public LLUDPServer(IPAddress listenIP, ref uint port, int proxyPortOffsetParm, bool allow_alternate_port, IConfigSource configSource, AgentCircuitManager circuitManager) : base(listenIP, (int)port) { #region Environment.TickCount Measurement @@ -219,7 +202,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP m_circuitManager = circuitManager; int sceneThrottleBps = 0; - bool usePools = false; IConfig config = configSource.Configs["ClientStack.LindenUDP"]; if (config != null) @@ -245,16 +227,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP m_pausedAckTimeout = 1000 * 300; // 5 minutes } - // FIXME: This actually only needs to be done once since the PacketPool is shared across all servers. - // However, there is no harm in temporarily doing it multiple times. - IConfig packetConfig = configSource.Configs["PacketPool"]; - if (packetConfig != null) - { - PacketPool.Instance.RecyclePackets = packetConfig.GetBoolean("RecyclePackets", true); - PacketPool.Instance.RecycleDataBlocks = packetConfig.GetBoolean("RecycleDataBlocks", true); - usePools = packetConfig.GetBoolean("RecycleBaseUDPPackets", usePools); - } - #region BinaryStats config = configSource.Configs["Statistics.Binary"]; m_shouldCollectStats = false; @@ -282,28 +254,20 @@ namespace OpenSim.Region.ClientStack.LindenUDP m_throttle = new TokenBucket(null, sceneThrottleBps); ThrottleRates = new ThrottleRates(configSource); - - if (usePools) - EnablePools(); } public void Start() { - StartInbound(); - StartOutbound(); + if (m_scene == null) + throw new InvalidOperationException("[LLUDPSERVER]: Cannot LLUDPServer.Start() without an IScene reference"); - m_elapsedMSSinceLastStatReport = Environment.TickCount; - } - - private void StartInbound() - { m_log.InfoFormat( - "[LLUDPSERVER]: Starting inbound packet processing for the LLUDP server in {0} mode with UsePools = {1}", - m_asyncPacketHandling ? "asynchronous" : "synchronous", UsePools); + "[LLUDPSERVER]: Starting the LLUDP server in {0} mode", + m_asyncPacketHandling ? "asynchronous" : "synchronous"); - base.StartInbound(m_recvBufferSize, m_asyncPacketHandling); + base.Start(m_recvBufferSize, m_asyncPacketHandling); - // This thread will process the packets received that are placed on the packetInbox + // Start the packet processing threads Watchdog.StartThread( IncomingPacketHandler, string.Format("Incoming Packets ({0})", m_scene.RegionInfo.RegionName), @@ -312,13 +276,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP true, GetWatchdogIncomingAlarmData, Watchdog.DEFAULT_WATCHDOG_TIMEOUT_MS); - } - - private new void StartOutbound() - { - m_log.Info("[LLUDPSERVER]: Starting outbound packet processing for the LLUDP server"); - - base.StartOutbound(); Watchdog.StartThread( OutgoingPacketHandler, @@ -328,57 +285,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP true, GetWatchdogOutgoingAlarmData, Watchdog.DEFAULT_WATCHDOG_TIMEOUT_MS); - } - - public void Stop() - { - m_log.Info("[LLUDPSERVER]: Shutting down the LLUDP server for " + m_scene.RegionInfo.RegionName); - base.StopOutbound(); - base.StopInbound(); - } - protected override bool EnablePools() - { - if (!UsePools) - { - base.EnablePools(); - - m_incomingPacketPool = new Pool(() => new IncomingPacket(), 500); - - m_incomingPacketPoolStat - = new Stat( - "IncomingPacketPoolCount", - "Objects within incoming packet pool", - "The number of objects currently stored within the incoming packet pool", - "", - "clientstack", - "packetpool", - StatType.Pull, - stat => stat.Value = m_incomingPacketPool.Count, - StatVerbosity.Debug); - - StatsManager.RegisterStat(m_incomingPacketPoolStat); - - return true; - } - - return false; - } - - protected override bool DisablePools() - { - if (UsePools) - { - base.DisablePools(); - - StatsManager.DeregisterStat(m_incomingPacketPoolStat); - - // We won't null out the pool to avoid a race condition with code that may be in the middle of using it. - - return true; - } - - return false; + m_elapsedMSSinceLastStatReport = Environment.TickCount; } /// @@ -403,6 +311,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP m_currentOutgoingClient != null ? m_currentOutgoingClient.Name : "none"); } + public new void Stop() + { + m_log.Info("[LLUDPSERVER]: Shutting down the LLUDP server for " + m_scene.RegionInfo.RegionName); + base.Stop(); + } + public void AddScene(IScene scene) { if (m_scene != null) @@ -419,117 +333,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP m_scene = (Scene)scene; m_location = new Location(m_scene.RegionInfo.RegionHandle); - - MainConsole.Instance.Commands.AddCommand( - "Debug", - false, - "debug lludp start", - "debug lludp start ", - "Control LLUDP packet processing.", - "No effect if packet processing has already started.\n" - + "in - start inbound processing.\n" - + "out - start outbound processing.\n" - + "all - start in and outbound processing.\n", - HandleStartCommand); - - MainConsole.Instance.Commands.AddCommand( - "Debug", - false, - "debug lludp stop", - "debug lludp stop ", - "Stop LLUDP packet processing.", - "No effect if packet processing has already stopped.\n" - + "in - stop inbound processing.\n" - + "out - stop outbound processing.\n" - + "all - stop in and outbound processing.\n", - HandleStopCommand); - - MainConsole.Instance.Commands.AddCommand( - "Debug", - false, - "debug lludp pool", - "debug lludp pool ", - "Turn object pooling within the lludp component on or off.", - HandlePoolCommand); - - MainConsole.Instance.Commands.AddCommand( - "Debug", - false, - "debug lludp status", - "debug lludp status", - "Return status of LLUDP packet processing.", - HandleStatusCommand); - } - - private void HandleStartCommand(string module, string[] args) - { - if (args.Length != 4) - { - MainConsole.Instance.Output("Usage: debug lludp start "); - return; - } - - string subCommand = args[3]; - - if (subCommand == "in" || subCommand == "all") - StartInbound(); - - if (subCommand == "out" || subCommand == "all") - StartOutbound(); - } - - private void HandleStopCommand(string module, string[] args) - { - if (args.Length != 4) - { - MainConsole.Instance.Output("Usage: debug lludp stop "); - return; - } - - string subCommand = args[3]; - - if (subCommand == "in" || subCommand == "all") - StopInbound(); - - if (subCommand == "out" || subCommand == "all") - StopOutbound(); - } - - private void HandlePoolCommand(string module, string[] args) - { - if (args.Length != 4) - { - MainConsole.Instance.Output("Usage: debug lludp pool "); - return; - } - - string enabled = args[3]; - - if (enabled == "on") - { - if (EnablePools()) - MainConsole.Instance.OutputFormat("Packet pools enabled on {0}", m_scene.Name); - } - else if (enabled == "off") - { - if (DisablePools()) - MainConsole.Instance.OutputFormat("Packet pools disabled on {0}", m_scene.Name); - } - else - { - MainConsole.Instance.Output("Usage: debug lludp pool "); - } - } - - private void HandleStatusCommand(string module, string[] args) - { - MainConsole.Instance.OutputFormat( - "IN LLUDP packet processing for {0} is {1}", m_scene.Name, IsRunningInbound ? "enabled" : "disabled"); - - MainConsole.Instance.OutputFormat( - "OUT LLUDP packet processing for {0} is {1}", m_scene.Name, IsRunningOutbound ? "enabled" : "disabled"); - - MainConsole.Instance.OutputFormat("LLUDP pools in {0} are {1}", m_scene.Name, UsePools ? "on" : "off"); } public bool HandlesRegion(Location x) @@ -613,8 +416,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP byte[] data = packet.ToBytes(); SendPacketData(udpClient, data, packet.Type, category, method); } - - PacketPool.Instance.ReturnPacket(packet); } /// @@ -899,7 +700,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP LLUDPClient udpClient = null; Packet packet = null; int packetEnd = buffer.DataLength - 1; - IPEndPoint endPoint = (IPEndPoint)buffer.RemoteEndPoint; + IPEndPoint address = (IPEndPoint)buffer.RemoteEndPoint; #region Decoding @@ -909,7 +710,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP // "[LLUDPSERVER]: Dropping undersized packet with {0} bytes received from {1} in {2}", // buffer.DataLength, buffer.RemoteEndPoint, m_scene.RegionInfo.RegionName); - return; // Drop undersized packet + return; // Drop undersizd packet } int headerLen = 7; @@ -932,13 +733,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP try { -// packet = Packet.BuildPacket(buffer.Data, ref packetEnd, -// // Only allocate a buffer for zerodecoding if the packet is zerocoded -// ((buffer.Data[0] & Helpers.MSG_ZEROCODED) != 0) ? new byte[4096] : null); - // If OpenSimUDPBase.UsePool == true (which is currently separate from the PacketPool) then we - // assume that packet construction does not retain a reference to byte[] buffer.Data (instead, all - // bytes are copied out). - packet = PacketPool.Instance.GetPacket(buffer.Data, ref packetEnd, + packet = Packet.BuildPacket(buffer.Data, ref packetEnd, // Only allocate a buffer for zerodecoding if the packet is zerocoded ((buffer.Data[0] & Helpers.MSG_ZEROCODED) != 0) ? new byte[4096] : null); } @@ -953,13 +748,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP return; // Drop short packet } - catch (Exception e) + catch(Exception e) { if (m_malformedCount < 100) m_log.DebugFormat("[LLUDPSERVER]: Dropped malformed packet: " + e.ToString()); - m_malformedCount++; - if ((m_malformedCount % 100000) == 0) m_log.DebugFormat("[LLUDPSERVER]: Received {0} malformed packets so far, probable network attack.", m_malformedCount); } @@ -979,7 +772,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP // If there is already a client for this endpoint, don't process UseCircuitCode IClientAPI client = null; - if (!m_scene.TryGetClient(endPoint, out client) || !(client is LLClientView)) + if (!m_scene.TryGetClient(address, out client)) { // UseCircuitCode handling if (packet.Type == PacketType.UseCircuitCode) @@ -987,15 +780,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP // And if there is a UseCircuitCode pending, also drop it lock (m_pendingCache) { - if (m_pendingCache.Contains(endPoint)) + if (m_pendingCache.Contains(address)) return; - m_pendingCache.AddOrUpdate(endPoint, new Queue(), 60); + m_pendingCache.AddOrUpdate(address, new Queue(), 60); } - // We need to copy the endpoint so that it doesn't get changed when another thread reuses the - // buffer. - object[] array = new object[] { new IPEndPoint(endPoint.Address, endPoint.Port), packet }; + object[] array = new object[] { buffer, packet }; Util.FireAndForget(HandleUseCircuitCode, array); @@ -1007,7 +798,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP lock (m_pendingCache) { Queue queue; - if (m_pendingCache.TryGetValue(endPoint, out queue)) + if (m_pendingCache.TryGetValue(address, out queue)) { //m_log.DebugFormat("[LLUDPSERVER]: Enqueued a {0} packet into the pending queue", packet.Type); queue.Enqueue(buffer); @@ -1043,10 +834,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP // Handle appended ACKs if (packet.Header.AppendedAcks && packet.Header.AckList != null) { -// m_log.DebugFormat( -// "[LLUDPSERVER]: Handling {0} appended acks from {1} in {2}", -// packet.Header.AckList.Length, client.Name, m_scene.Name); - for (int i = 0; i < packet.Header.AckList.Length; i++) udpClient.NeedAcks.Acknowledge(packet.Header.AckList[i], now, packet.Header.Resent); } @@ -1056,10 +843,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP { PacketAckPacket ackPacket = (PacketAckPacket)packet; -// m_log.DebugFormat( -// "[LLUDPSERVER]: Handling {0} packet acks for {1} in {2}", -// ackPacket.Packets.Length, client.Name, m_scene.Name); - for (int i = 0; i < ackPacket.Packets.Length; i++) udpClient.NeedAcks.Acknowledge(ackPacket.Packets[i].ID, now, packet.Header.Resent); @@ -1073,10 +856,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP if (packet.Header.Reliable) { -// m_log.DebugFormat( -// "[LLUDPSERVER]: Adding ack request for {0} {1} from {2} in {3}", -// packet.Type, packet.Header.Sequence, client.Name, m_scene.Name); - udpClient.PendingAcks.Enqueue(packet.Header.Sequence); // This is a somewhat odd sequence of steps to pull the client.BytesSinceLastACK value out, @@ -1123,8 +902,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP if (packet.Type == PacketType.StartPingCheck) { -// m_log.DebugFormat("[LLUDPSERVER]: Handling ping from {0} in {1}", client.Name, m_scene.Name); - // We don't need to do anything else with ping checks StartPingCheckPacket startPing = (StartPingCheckPacket)packet; CompletePing(udpClient, startPing.PingID.PingID); @@ -1144,25 +921,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP #endregion Ping Check Handling - IncomingPacket incomingPacket; - // Inbox insertion - if (UsePools) - { - incomingPacket = m_incomingPacketPool.GetObject(); - incomingPacket.Client = (LLClientView)client; - incomingPacket.Packet = packet; - } - else - { - incomingPacket = new IncomingPacket((LLClientView)client, packet); - } - - if (incomingPacket.Packet.Type == PacketType.AgentUpdate || - incomingPacket.Packet.Type == PacketType.ChatFromViewer) - packetInbox.EnqueueHigh(incomingPacket); + if (packet.Type == PacketType.AgentUpdate || + packet.Type == PacketType.ChatFromViewer) + packetInbox.EnqueueHigh(new IncomingPacket((LLClientView)client, packet)); else - packetInbox.EnqueueLow(incomingPacket); + packetInbox.EnqueueLow(new IncomingPacket((LLClientView)client, packet)); +// packetInbox.Enqueue(new IncomingPacket((LLClientView)client, packet)); } #region BinaryStats @@ -1248,19 +1013,21 @@ namespace OpenSim.Region.ClientStack.LindenUDP private void HandleUseCircuitCode(object o) { - IPEndPoint endPoint = null; + IPEndPoint remoteEndPoint = null; IClientAPI client = null; try { // DateTime startTime = DateTime.Now; object[] array = (object[])o; - endPoint = (IPEndPoint)array[0]; + UDPPacketBuffer buffer = (UDPPacketBuffer)array[0]; UseCircuitCodePacket uccp = (UseCircuitCodePacket)array[1]; m_log.DebugFormat( "[LLUDPSERVER]: Handling UseCircuitCode request for circuit {0} to {1} from IP {2}", - uccp.CircuitCode.Code, m_scene.RegionInfo.RegionName, endPoint); + uccp.CircuitCode.Code, m_scene.RegionInfo.RegionName, buffer.RemoteEndPoint); + + remoteEndPoint = (IPEndPoint)buffer.RemoteEndPoint; AuthenticateResponse sessionInfo; if (IsClientAuthorized(uccp, out sessionInfo)) @@ -1271,13 +1038,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP uccp.CircuitCode.Code, uccp.CircuitCode.ID, uccp.CircuitCode.SessionID, - endPoint, + remoteEndPoint, sessionInfo); // Send ack straight away to let the viewer know that the connection is active. // The client will be null if it already exists (e.g. if on a region crossing the client sends a use // circuit code to the existing child agent. This is not particularly obvious. - SendAckImmediate(endPoint, uccp.Header.Sequence); + SendAckImmediate(remoteEndPoint, uccp.Header.Sequence); // We only want to send initial data to new clients, not ones which are being converted from child to root. if (client != null) @@ -1291,12 +1058,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP lock (m_pendingCache) { - if (!m_pendingCache.TryGetValue(endPoint, out queue)) + if (!m_pendingCache.TryGetValue(remoteEndPoint, out queue)) { m_log.DebugFormat("[LLUDPSERVER]: Client created but no pending queue present"); return; } - m_pendingCache.Remove(endPoint); + m_pendingCache.Remove(remoteEndPoint); } m_log.DebugFormat("[LLUDPSERVER]: Client created, processing pending queue, {0} entries", queue.Count); @@ -1314,9 +1081,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP // Don't create clients for unauthorized requesters. m_log.WarnFormat( "[LLUDPSERVER]: Ignoring connection request for {0} to {1} with unknown circuit code {2} from IP {3}", - uccp.CircuitCode.ID, m_scene.RegionInfo.RegionName, uccp.CircuitCode.Code, endPoint); + uccp.CircuitCode.ID, m_scene.RegionInfo.RegionName, uccp.CircuitCode.Code, remoteEndPoint); lock (m_pendingCache) - m_pendingCache.Remove(endPoint); + m_pendingCache.Remove(remoteEndPoint); } // m_log.DebugFormat( @@ -1328,7 +1095,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP { m_log.ErrorFormat( "[LLUDPSERVER]: UseCircuitCode handling from endpoint {0}, client {1} {2} failed. Exception {3}{4}", - endPoint != null ? endPoint.ToString() : "n/a", + remoteEndPoint != null ? remoteEndPoint.ToString() : "n/a", client != null ? client.Name : "unknown", client != null ? client.AgentId.ToString() : "unknown", e.Message, @@ -1393,20 +1160,20 @@ namespace OpenSim.Region.ClientStack.LindenUDP { IClientAPI client = null; - // We currently synchronize this code across the whole scene to avoid issues such as - // http://opensimulator.org/mantis/view.php?id=5365 However, once locking per agent circuit can be done - // consistently, this lock could probably be removed. - lock (this) + // In priciple there shouldn't be more than one thread here, ever. + // But in case that happens, we need to synchronize this piece of code + // because it's too important + lock (this) { if (!m_scene.TryGetClient(agentID, out client)) { LLUDPClient udpClient = new LLUDPClient(this, ThrottleRates, m_throttle, circuitCode, agentID, remoteEndPoint, m_defaultRTO, m_maxRTO); - + client = new LLClientView(m_scene, this, udpClient, sessionInfo, agentID, sessionID, circuitCode); client.OnLogout += LogoutHandler; - + ((LLClientView)client).DisableFacelights = m_disableFacelights; - + client.Start(); } } @@ -1445,7 +1212,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP // on to en-US to avoid number parsing issues Culture.SetCurrentCulture(); - while (IsRunningInbound) + while (base.IsRunning) { m_scene.ThreadAlive(1); try @@ -1461,12 +1228,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP } if (packetInbox.Dequeue(100, ref incomingPacket)) - { ProcessInPacket(incomingPacket);//, incomingPacket); Util.FireAndForget(ProcessInPacket, incomingPacket); - - if (UsePools) - m_incomingPacketPool.ReturnObject(incomingPacket); - } } catch (Exception ex) { @@ -1493,7 +1255,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP // Action generic every round Action clientPacketHandler = ClientOutgoingPacketHandler; - while (base.IsRunningOutbound) + while (base.IsRunning) { m_scene.ThreadAlive(2); try @@ -1761,7 +1523,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP if (!client.IsLoggingOut) { client.IsLoggingOut = true; - client.Close(false, false); + client.Close(false); } } } diff --git a/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs b/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs index 8bd3461..cfe7c9d 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs @@ -30,8 +30,6 @@ using System.Net; using System.Net.Sockets; using System.Threading; using log4net; -using OpenSim.Framework; -using OpenSim.Framework.Monitoring; namespace OpenMetaverse { @@ -60,31 +58,17 @@ namespace OpenMetaverse /// Flag to process packets asynchronously or synchronously private bool m_asyncPacketHandling; - /// - /// Pool to use for handling data. May be null if UsePools = false; - /// - protected OpenSim.Framework.Pool m_pool; - - /// - /// Are we to use object pool(s) to reduce memory churn when receiving data? - /// - public bool UsePools { get; protected set; } - - /// Returns true if the server is currently listening for inbound packets, otherwise false - public bool IsRunningInbound { get; private set; } + /// The all important shutdown flag + private volatile bool m_shutdownFlag = true; - /// Returns true if the server is currently sending outbound packets, otherwise false - /// If IsRunningOut = false, then any request to send a packet is simply dropped. - public bool IsRunningOutbound { get; private set; } - - private Stat m_poolCountStat; + /// Returns true if the server is currently listening, otherwise false + public bool IsRunning { get { return !m_shutdownFlag; } } /// /// Default constructor /// /// Local IP address to bind the server to /// Port to listening for incoming UDP packets on - /// /// Are we to use an object pool to get objects for handing inbound data? public OpenSimUDPBase(IPAddress bindAddress, int port) { m_localBindAddress = bindAddress; @@ -92,7 +76,7 @@ namespace OpenMetaverse } /// - /// Start inbound UDP packet handling. + /// Start the UDP server /// /// The size of the receive buffer for /// the UDP socket. This value is passed up to the operating system @@ -107,11 +91,11 @@ namespace OpenMetaverse /// manner (not throwing an exception when the remote side resets the /// connection). This call is ignored on Mono where the flag is not /// necessary - public void StartInbound(int recvBufferSize, bool asyncPacketHandling) + public void Start(int recvBufferSize, bool asyncPacketHandling) { m_asyncPacketHandling = asyncPacketHandling; - if (!IsRunningInbound) + if (m_shutdownFlag) { const int SIO_UDP_CONNRESET = -1744830452; @@ -139,7 +123,8 @@ namespace OpenMetaverse m_udpSocket.Bind(ipep); - IsRunningInbound = true; + // we're not shutting down, we're starting up + m_shutdownFlag = false; // kick off an async receive. The Start() method will return, the // actual receives will occur asynchronously and will be caught in @@ -149,84 +134,28 @@ namespace OpenMetaverse } /// - /// Start outbound UDP packet handling. + /// Stops the UDP server /// - public void StartOutbound() - { - IsRunningOutbound = true; - } - - public void StopInbound() + public void Stop() { - if (IsRunningInbound) + if (!m_shutdownFlag) { // wait indefinitely for a writer lock. Once this is called, the .NET runtime // will deny any more reader locks, in effect blocking all other send/receive - // threads. Once we have the lock, we set IsRunningInbound = false to inform the other + // threads. Once we have the lock, we set shutdownFlag to inform the other // threads that the socket is closed. - IsRunningInbound = false; + m_shutdownFlag = true; m_udpSocket.Close(); } } - public void StopOutbound() - { - IsRunningOutbound = false; - } - - protected virtual bool EnablePools() - { - if (!UsePools) - { - m_pool = new Pool(() => new UDPPacketBuffer(), 500); - - m_poolCountStat - = new Stat( - "UDPPacketBufferPoolCount", - "Objects within the UDPPacketBuffer pool", - "The number of objects currently stored within the UDPPacketBuffer pool", - "", - "clientstack", - "packetpool", - StatType.Pull, - stat => stat.Value = m_pool.Count, - StatVerbosity.Debug); - - StatsManager.RegisterStat(m_poolCountStat); - - UsePools = true; - - return true; - } - - return false; - } - - protected virtual bool DisablePools() - { - if (UsePools) - { - UsePools = false; - StatsManager.DeregisterStat(m_poolCountStat); - - // We won't null out the pool to avoid a race condition with code that may be in the middle of using it. - - return true; - } - - return false; - } - private void AsyncBeginReceive() { - UDPPacketBuffer buf; - - if (UsePools) - buf = m_pool.GetObject(); - else - buf = new UDPPacketBuffer(); + // allocate a packet buffer + //WrappedObject wrappedBuffer = Pool.CheckOut(); + UDPPacketBuffer buf = new UDPPacketBuffer(); - if (IsRunningInbound) + if (!m_shutdownFlag) { try { @@ -279,7 +208,7 @@ namespace OpenMetaverse { // Asynchronous receive operations will complete here through the call // to AsyncBeginReceive - if (IsRunningInbound) + if (!m_shutdownFlag) { // Asynchronous mode will start another receive before the // callback for this packet is even fired. Very parallel :-) @@ -288,6 +217,8 @@ namespace OpenMetaverse // get the buffer that was created in AsyncBeginReceive // this is the received data + //WrappedObject wrappedBuffer = (WrappedObject)iar.AsyncState; + //UDPPacketBuffer buffer = wrappedBuffer.Instance; UDPPacketBuffer buffer = (UDPPacketBuffer)iar.AsyncState; try @@ -304,8 +235,7 @@ namespace OpenMetaverse catch (ObjectDisposedException) { } finally { - if (UsePools) - m_pool.ReturnObject(buffer); + //wrappedBuffer.Dispose(); // Synchronous mode waits until the packet callback completes // before starting the receive to fetch another packet @@ -318,7 +248,7 @@ namespace OpenMetaverse public void AsyncBeginSend(UDPPacketBuffer buf) { - if (IsRunningOutbound) + if (!m_shutdownFlag) { try { diff --git a/OpenSim/Region/ClientStack/Linden/UDP/PacketPool.cs b/OpenSim/Region/ClientStack/Linden/UDP/PacketPool.cs deleted file mode 100644 index 9f22fb4..0000000 --- a/OpenSim/Region/ClientStack/Linden/UDP/PacketPool.cs +++ /dev/null @@ -1,316 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.Reflection; -using OpenMetaverse; -using OpenMetaverse.Packets; -using log4net; -using OpenSim.Framework.Monitoring; - -namespace OpenSim.Region.ClientStack.LindenUDP -{ - public sealed class PacketPool - { - private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - private static readonly PacketPool instance = new PacketPool(); - - private bool packetPoolEnabled = true; - private bool dataBlockPoolEnabled = true; - - private PercentageStat m_packetsReusedStat = new PercentageStat( - "PacketsReused", - "Packets reused", - "Number of packets reused out of all requests to the packet pool", - "clientstack", - "packetpool", - StatType.Push, - null, - StatVerbosity.Debug); - - private PercentageStat m_blocksReusedStat = new PercentageStat( - "PacketDataBlocksReused", - "Packet data blocks reused", - "Number of data blocks reused out of all requests to the packet pool", - "clientstack", - "packetpool", - StatType.Push, - null, - StatVerbosity.Debug); - - /// - /// Pool of packets available for reuse. - /// - private readonly Dictionary> pool = new Dictionary>(); - - private static Dictionary> DataBlocks = new Dictionary>(); - - public static PacketPool Instance - { - get { return instance; } - } - - public bool RecyclePackets - { - set { packetPoolEnabled = value; } - get { return packetPoolEnabled; } - } - - public bool RecycleDataBlocks - { - set { dataBlockPoolEnabled = value; } - get { return dataBlockPoolEnabled; } - } - - private PacketPool() - { - StatsManager.RegisterStat(m_packetsReusedStat); - StatsManager.RegisterStat(m_blocksReusedStat); - - StatsManager.RegisterStat( - new Stat( - "PacketsPoolCount", - "Objects within the packet pool", - "The number of objects currently stored within the packet pool", - "", - "clientstack", - "packetpool", - StatType.Pull, - stat => { lock (pool) { stat.Value = pool.Count; } }, - StatVerbosity.Debug)); - - StatsManager.RegisterStat( - new Stat( - "PacketDataBlocksPoolCount", - "Objects within the packet data block pool", - "The number of objects currently stored within the packet data block pool", - "", - "clientstack", - "packetpool", - StatType.Pull, - stat => { lock (DataBlocks) { stat.Value = DataBlocks.Count; } }, - StatVerbosity.Debug)); - } - - /// - /// Gets a packet of the given type. - /// - /// - /// Guaranteed to always return a packet, whether from the pool or newly constructed. - public Packet GetPacket(PacketType type) - { - m_packetsReusedStat.Consequent++; - - Packet packet; - - if (!packetPoolEnabled) - return Packet.BuildPacket(type); - - lock (pool) - { - if (!pool.ContainsKey(type) || pool[type] == null || (pool[type]).Count == 0) - { -// m_log.DebugFormat("[PACKETPOOL]: Building {0} packet", type); - - // Creating a new packet if we cannot reuse an old package - packet = Packet.BuildPacket(type); - } - else - { -// m_log.DebugFormat("[PACKETPOOL]: Pulling {0} packet", type); - - // Recycle old packages - m_packetsReusedStat.Antecedent++; - - packet = pool[type].Pop(); - } - } - - return packet; - } - - // private byte[] decoded_header = new byte[10]; - private static PacketType GetType(byte[] bytes) - { - byte[] decoded_header = new byte[10 + 8]; - ushort id; - PacketFrequency freq; - - if ((bytes[0] & Helpers.MSG_ZEROCODED) != 0) - { - Helpers.ZeroDecode(bytes, 16, decoded_header); - } - else - { - Buffer.BlockCopy(bytes, 0, decoded_header, 0, 10); - } - - if (decoded_header[6] == 0xFF) - { - if (decoded_header[7] == 0xFF) - { - id = (ushort) ((decoded_header[8] << 8) + decoded_header[9]); - freq = PacketFrequency.Low; - } - else - { - id = decoded_header[7]; - freq = PacketFrequency.Medium; - } - } - else - { - id = decoded_header[6]; - freq = PacketFrequency.High; - } - - return Packet.GetType(id, freq); - } - - public Packet GetPacket(byte[] bytes, ref int packetEnd, byte[] zeroBuffer) - { - PacketType type = GetType(bytes); - -// Array.Clear(zeroBuffer, 0, zeroBuffer.Length); - - int i = 0; - Packet packet = GetPacket(type); - if (packet == null) - m_log.WarnFormat("[PACKETPOOL]: Failed to get packet of type {0}", type); - else - packet.FromBytes(bytes, ref i, ref packetEnd, zeroBuffer); - - return packet; - } - - /// - /// Return a packet to the packet pool - /// - /// - public void ReturnPacket(Packet packet) - { - if (dataBlockPoolEnabled) - { - switch (packet.Type) - { - case PacketType.ObjectUpdate: - ObjectUpdatePacket oup = (ObjectUpdatePacket)packet; - - foreach (ObjectUpdatePacket.ObjectDataBlock oupod in oup.ObjectData) - ReturnDataBlock(oupod); - - oup.ObjectData = null; - break; - - case PacketType.ImprovedTerseObjectUpdate: - ImprovedTerseObjectUpdatePacket itoup = (ImprovedTerseObjectUpdatePacket)packet; - - foreach (ImprovedTerseObjectUpdatePacket.ObjectDataBlock itoupod in itoup.ObjectData) - ReturnDataBlock(itoupod); - - itoup.ObjectData = null; - break; - } - } - - if (packetPoolEnabled) - { - switch (packet.Type) - { - // List pooling packets here - case PacketType.AgentUpdate: - case PacketType.PacketAck: - case PacketType.ObjectUpdate: - case PacketType.ImprovedTerseObjectUpdate: - lock (pool) - { - PacketType type = packet.Type; - - if (!pool.ContainsKey(type)) - { - pool[type] = new Stack(); - } - - if ((pool[type]).Count < 50) - { -// m_log.DebugFormat("[PACKETPOOL]: Pushing {0} packet", type); - - pool[type].Push(packet); - } - } - break; - - // Other packets wont pool - default: - return; - } - } - } - - public T GetDataBlock() where T: new() - { - lock (DataBlocks) - { - m_blocksReusedStat.Consequent++; - - Stack s; - - if (DataBlocks.TryGetValue(typeof(T), out s)) - { - if (s.Count > 0) - { - m_blocksReusedStat.Antecedent++; - return (T)s.Pop(); - } - } - else - { - DataBlocks[typeof(T)] = new Stack(); - } - - return new T(); - } - } - - public void ReturnDataBlock(T block) where T: new() - { - if (block == null) - return; - - lock (DataBlocks) - { - if (!DataBlocks.ContainsKey(typeof(T))) - DataBlocks[typeof(T)] = new Stack(); - - if (DataBlocks[typeof(T)].Count < 50) - DataBlocks[typeof(T)].Push(block); - } - } - } -} \ No newline at end of file diff --git a/OpenSim/Region/ClientStack/Linden/UDP/Tests/BasicCircuitTests.cs b/OpenSim/Region/ClientStack/Linden/UDP/Tests/BasicCircuitTests.cs index 556df30..109a8e1 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/Tests/BasicCircuitTests.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/Tests/BasicCircuitTests.cs @@ -43,7 +43,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests /// This will contain basic tests for the LindenUDP client stack /// [TestFixture] - public class BasicCircuitTests : OpenSimTestCase + public class BasicCircuitTests { private Scene m_scene; private TestLLUDPServer m_udpServer; @@ -65,9 +65,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests } [SetUp] - public override void SetUp() + public void SetUp() { - base.SetUp(); m_scene = new SceneHelpers().SetupScene(); } @@ -144,7 +143,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests public void TestAddClient() { TestHelpers.InMethod(); -// TestHelpers.EnableLogging(); +// XmlConfigurator.Configure(); AddUdpServer(); diff --git a/OpenSim/Region/ClientStack/RegionApplicationBase.cs b/OpenSim/Region/ClientStack/RegionApplicationBase.cs index 853b72d..4672f8a 100644 --- a/OpenSim/Region/ClientStack/RegionApplicationBase.cs +++ b/OpenSim/Region/ClientStack/RegionApplicationBase.cs @@ -76,7 +76,7 @@ namespace OpenSim.Region.ClientStack protected override void StartupSpecific() { - SceneManager = SceneManager.Instance; + SceneManager = new SceneManager(); m_clientStackManager = CreateClientStackManager(); Initialize(); diff --git a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs index da1ff2e..8a4fd8f 100644 --- a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs +++ b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs @@ -57,36 +57,39 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction } /// - /// Return the xfer uploader for the given transaction. + /// Return a xfer uploader if one does not already exist. /// - /// - /// If an uploader does not already exist for this transaction then it is created, otherwise the existing - /// uploader is returned. - /// /// - /// The asset xfer uploader - public AssetXferUploader RequestXferUploader(UUID transactionID) + /// + /// We must transfer the new asset ID into the uploader on creation, otherwise + /// we can see race conditions with other threads which can retrieve an item before it is updated with the new + /// asset id. + /// + /// + /// The xfer uploader requested. Null if one is already in existence. + /// FIXME: This is a bizarre thing to do, and is probably meant to signal an error condition if multiple + /// transfers are made. Needs to be corrected. + /// + public AssetXferUploader RequestXferUploader(UUID transactionID, UUID assetID) { - AssetXferUploader uploader; - lock (XferUploaders) { if (!XferUploaders.ContainsKey(transactionID)) { - uploader = new AssetXferUploader(this, m_Scene, transactionID, m_dumpAssetsToFile); + AssetXferUploader uploader = new AssetXferUploader(this, m_Scene, assetID, m_dumpAssetsToFile); // m_log.DebugFormat( // "[AGENT ASSETS TRANSACTIONS]: Adding asset xfer uploader {0} since it didn't previously exist", transactionID); XferUploaders.Add(transactionID, uploader); - } - else - { - uploader = XferUploaders[transactionID]; + + return uploader; } } - return uploader; + m_log.WarnFormat("[AGENT ASSETS TRANSACTIONS]: Ignoring request for asset xfer uploader {0} since it already exists", transactionID); + + return null; } public void HandleXfer(ulong xferID, uint packetID, byte[] data) @@ -148,30 +151,117 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction string description, string name, sbyte invType, sbyte type, byte wearableType, uint nextOwnerMask) { - AssetXferUploader uploader = RequestXferUploader(transactionID); + AssetXferUploader uploader = null; + + lock (XferUploaders) + { + if (XferUploaders.ContainsKey(transactionID)) + uploader = XferUploaders[transactionID]; + } - uploader.RequestCreateInventoryItem( - remoteClient, folderID, callbackID, - description, name, invType, type, wearableType, nextOwnerMask); + if (uploader != null) + { + uploader.RequestCreateInventoryItem( + remoteClient, transactionID, folderID, + callbackID, description, name, invType, type, + wearableType, nextOwnerMask); - return true; + return true; + } + + return false; + } + + /// + /// Get an uploaded asset. If the data is successfully retrieved, + /// the transaction will be removed. + /// + /// + /// The asset if the upload has completed, null if it has not. + private AssetBase GetTransactionAsset(UUID transactionID) + { + lock (XferUploaders) + { + if (XferUploaders.ContainsKey(transactionID)) + { + AssetXferUploader uploader = XferUploaders[transactionID]; + AssetBase asset = uploader.GetAssetData(); + RemoveXferUploader(transactionID); + + return asset; + } + } + + return null; } public void RequestUpdateTaskInventoryItem(IClientAPI remoteClient, SceneObjectPart part, UUID transactionID, TaskInventoryItem item) { - AssetXferUploader uploader = RequestXferUploader(transactionID); + AssetXferUploader uploader = null; + + lock (XferUploaders) + { + if (XferUploaders.ContainsKey(transactionID)) + uploader = XferUploaders[transactionID]; + } + + if (uploader != null) + { + AssetBase asset = GetTransactionAsset(transactionID); + + // Only legacy viewers use this, and they prefer CAPS, which + // we have, so this really never runs. + // Allow it, but only for "safe" types. + if ((InventoryType)item.InvType != InventoryType.Notecard && + (InventoryType)item.InvType != InventoryType.LSL) + return; - uploader.RequestUpdateTaskInventoryItem(remoteClient, item); + if (asset != null) + { +// m_log.DebugFormat( +// "[AGENT ASSETS TRANSACTIONS]: Updating item {0} in {1} for transaction {2}", +// item.Name, part.Name, transactionID); + + asset.FullID = UUID.Random(); + asset.Name = item.Name; + asset.Description = item.Description; + asset.Type = (sbyte)item.Type; + item.AssetID = asset.FullID; + + m_Scene.AssetService.Store(asset); + } + } + else + { + m_log.ErrorFormat( + "[AGENT ASSET TRANSACTIONS]: Could not find uploader with transaction ID {0} when handling request to update task inventory item {1} in {2}", + transactionID, item.Name, part.Name); + } } public void RequestUpdateInventoryItem(IClientAPI remoteClient, UUID transactionID, InventoryItemBase item) { - AssetXferUploader uploader = RequestXferUploader(transactionID); + AssetXferUploader uploader = null; + + lock (XferUploaders) + { + if (XferUploaders.ContainsKey(transactionID)) + uploader = XferUploaders[transactionID]; + } - uploader.RequestUpdateInventoryItem(remoteClient, item); + if (uploader != null) + { + uploader.RequestUpdateInventoryItem(remoteClient, transactionID, item); + } + else + { + m_log.ErrorFormat( + "[AGENT ASSET TRANSACTIONS]: Could not find uploader with transaction ID {0} when handling request to update inventory item {1} for {2}", + transactionID, item.Name, remoteClient.Name); + } } } } diff --git a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetTransactionModule.cs b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetTransactionModule.cs index 4bb8986..441c4ff 100644 --- a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetTransactionModule.cs +++ b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetTransactionModule.cs @@ -215,7 +215,7 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction IClientAPI remoteClient, SceneObjectPart part, UUID transactionID, TaskInventoryItem item) { m_log.DebugFormat( - "[ASSET TRANSACTION MODULE] Called HandleTaskItemUpdateFromTransaction with item {0} in {1} for {2} in {3}", + "[TRANSACTIONS MANAGER] Called HandleTaskItemUpdateFromTransaction with item {0} in {1} for {2} in {3}", item.Name, part.Name, remoteClient.Name, m_Scene.RegionInfo.RegionName); AgentAssetTransactions transactions = @@ -274,8 +274,13 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction } AgentAssetTransactions transactions = GetUserTransactions(remoteClient.AgentId); - AssetXferUploader uploader = transactions.RequestXferUploader(transaction); - uploader.StartUpload(remoteClient, assetID, transaction, type, data, storeLocal, tempFile); + AssetXferUploader uploader = transactions.RequestXferUploader(transaction, assetID); + + if (uploader != null) + { + uploader.Initialise(remoteClient, assetID, transaction, type, + data, storeLocal, tempFile); + } } /// diff --git a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs index f6dd5af..4cedfe6 100644 --- a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs +++ b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs @@ -49,75 +49,39 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); /// - /// Upload state. - /// - /// - /// New -> Uploading -> Complete - /// - private enum UploadState - { - New, - Uploading, - Complete - } - - /// /// Reference to the object that holds this uploader. Used to remove ourselves from it's list if we /// are performing a delayed update. /// AgentAssetTransactions m_transactions; - private UploadState m_uploadState = UploadState.New; - private AssetBase m_asset; private UUID InventFolder = UUID.Zero; private sbyte invType = 0; - private bool m_createItem; - private uint m_createItemCallback; - - private bool m_updateItem; + private bool m_createItem = false; + private uint m_createItemCallback = 0; + private bool m_updateItem = false; private InventoryItemBase m_updateItemData; - private bool m_updateTaskItem; - private TaskInventoryItem m_updateTaskItemData; - private string m_description = String.Empty; private bool m_dumpAssetToFile; + private bool m_finished = false; private string m_name = String.Empty; -// private bool m_storeLocal; + private bool m_storeLocal; private uint nextPerm = 0; private IClientAPI ourClient; - - private UUID m_transactionID; - + private UUID TransactionID = UUID.Zero; private sbyte type = 0; private byte wearableType = 0; private byte[] m_oldData = null; public ulong XferID; private Scene m_Scene; - /// - /// AssetXferUploader constructor - /// - /// /param> - /// - /// - /// - /// If true then when the asset is uploaded it is dumped to a file with the format - /// String.Format("{6}_{7}_{0:d2}{1:d2}{2:d2}_{3:d2}{4:d2}{5:d2}.dat", - /// now.Year, now.Month, now.Day, now.Hour, now.Minute, - /// now.Second, m_asset.Name, m_asset.Type); - /// for debugging purposes. - /// - public AssetXferUploader( - AgentAssetTransactions transactions, Scene scene, UUID transactionID, bool dumpAssetToFile) + public AssetXferUploader(AgentAssetTransactions transactions, Scene scene, UUID assetID, bool dumpAssetToFile) { - m_asset = new AssetBase(); - m_transactions = transactions; - m_transactionID = transactionID; m_Scene = scene; + m_asset = new AssetBase() { FullID = assetID }; m_dumpAssetToFile = dumpAssetToFile; } @@ -163,50 +127,30 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction } /// - /// Start asset transfer from the client + /// Initialise asset transfer from the client /// - /// - /// - /// - /// - /// - /// Optional data. If present then the asset is created immediately with this data - /// rather than requesting an upload from the client. The data must be longer than 2 bytes. - /// - /// - /// - public void StartUpload( - IClientAPI remoteClient, UUID assetID, UUID transaction, sbyte type, byte[] data, bool storeLocal, - bool tempFile) + /// + /// + /// + public void Initialise(IClientAPI remoteClient, UUID assetID, + UUID transaction, sbyte type, byte[] data, bool storeLocal, + bool tempFile) { // m_log.DebugFormat( // "[ASSET XFER UPLOADER]: Initialised xfer from {0}, asset {1}, transaction {2}, type {3}, storeLocal {4}, tempFile {5}, already received data length {6}", // remoteClient.Name, assetID, transaction, type, storeLocal, tempFile, data.Length); - lock (this) - { - if (m_uploadState != UploadState.New) - { - m_log.WarnFormat( - "[ASSET XFER UPLOADER]: Tried to start upload of asset {0}, transaction {1} for {2} but this is already in state {3}. Aborting.", - assetID, transaction, remoteClient.Name, m_uploadState); - - return; - } - - m_uploadState = UploadState.Uploading; - } - ourClient = remoteClient; - - m_asset.FullID = assetID; + m_asset.Name = "blank"; + m_asset.Description = "empty"; m_asset.Type = type; m_asset.CreatorID = remoteClient.AgentId.ToString(); m_asset.Data = data; m_asset.Local = storeLocal; m_asset.Temporary = tempFile; -// m_storeLocal = storeLocal; + TransactionID = transaction; + m_storeLocal = storeLocal; if (m_asset.Data.Length > 2) { @@ -231,35 +175,36 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction protected void SendCompleteMessage() { + ourClient.SendAssetUploadCompleteMessage(m_asset.Type, true, + m_asset.FullID); + // We must lock in order to avoid a race with a separate thread dealing with an inventory item or create // message from other client UDP. lock (this) { - m_uploadState = UploadState.Complete; - - ourClient.SendAssetUploadCompleteMessage(m_asset.Type, true, m_asset.FullID); - + m_finished = true; if (m_createItem) { - CompleteCreateItem(m_createItemCallback); + DoCreateItem(m_createItemCallback); } else if (m_updateItem) { - CompleteItemUpdate(m_updateItemData); + StoreAssetForItemUpdate(m_updateItemData); + + // Remove ourselves from the list of transactions if completion was delayed until the transaction + // was complete. + // TODO: Should probably do the same for create item. + m_transactions.RemoveXferUploader(TransactionID); } - else if (m_updateTaskItem) + else if (m_storeLocal) { - CompleteTaskItemUpdate(m_updateTaskItemData); + m_Scene.AssetService.Store(m_asset); } -// else if (m_storeLocal) -// { -// m_Scene.AssetService.Store(m_asset); -// } } m_log.DebugFormat( "[ASSET XFER UPLOADER]: Uploaded asset {0} for transaction {1}", - m_asset.FullID, m_transactionID); + m_asset.FullID, TransactionID); if (m_dumpAssetToFile) { @@ -287,37 +232,40 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction } public void RequestCreateInventoryItem(IClientAPI remoteClient, - UUID folderID, uint callbackID, + UUID transactionID, UUID folderID, uint callbackID, string description, string name, sbyte invType, sbyte type, byte wearableType, uint nextOwnerMask) { - InventFolder = folderID; - m_name = name; - m_description = description; - this.type = type; - this.invType = invType; - this.wearableType = wearableType; - nextPerm = nextOwnerMask; - m_asset.Name = name; - m_asset.Description = description; - m_asset.Type = type; - - // We must lock to avoid a race with a separate thread uploading the asset. - lock (this) + if (TransactionID == transactionID) { - if (m_uploadState == UploadState.Complete) + InventFolder = folderID; + m_name = name; + m_description = description; + this.type = type; + this.invType = invType; + this.wearableType = wearableType; + nextPerm = nextOwnerMask; + m_asset.Name = name; + m_asset.Description = description; + m_asset.Type = type; + + // We must lock to avoid a race with a separate thread uploading the asset. + lock (this) { - CompleteCreateItem(callbackID); - } - else - { - m_createItem = true; //set flag so the inventory item is created when upload is complete - m_createItemCallback = callbackID; + if (m_finished) + { + DoCreateItem(callbackID); + } + else + { + m_createItem = true; //set flag so the inventory item is created when upload is complete + m_createItemCallback = callbackID; + } } } } - public void RequestUpdateInventoryItem(IClientAPI remoteClient, InventoryItemBase item) + public void RequestUpdateInventoryItem(IClientAPI remoteClient, UUID transactionID, InventoryItemBase item) { // We must lock to avoid a race with a separate thread uploading the asset. lock (this) @@ -332,9 +280,9 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction item.AssetID = m_asset.FullID; m_Scene.InventoryService.UpdateItem(item); - if (m_uploadState == UploadState.Complete) + if (m_finished) { - CompleteItemUpdate(item); + StoreAssetForItemUpdate(item); } else { @@ -348,59 +296,20 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction } } - public void RequestUpdateTaskInventoryItem(IClientAPI remoteClient, TaskInventoryItem taskItem) - { - // We must lock to avoid a race with a separate thread uploading the asset. - lock (this) - { - m_asset.Name = taskItem.Name; - m_asset.Description = taskItem.Description; - m_asset.Type = (sbyte)taskItem.Type; - taskItem.AssetID = m_asset.FullID; - - if (m_uploadState == UploadState.Complete) - { - CompleteTaskItemUpdate(taskItem); - } - else - { - m_updateTaskItem = true; - m_updateTaskItemData = taskItem; - } - } - } - /// - /// Store the asset for the given item when it has been uploaded. + /// Store the asset for the given item. /// /// - private void CompleteItemUpdate(InventoryItemBase item) + private void StoreAssetForItemUpdate(InventoryItemBase item) { // m_log.DebugFormat( // "[ASSET XFER UPLOADER]: Storing asset {0} for earlier item update for {1} for {2}", // m_asset.FullID, item.Name, ourClient.Name); m_Scene.AssetService.Store(m_asset); - - m_transactions.RemoveXferUploader(m_transactionID); - } - - /// - /// Store the asset for the given task item when it has been uploaded. - /// - /// - private void CompleteTaskItemUpdate(TaskInventoryItem taskItem) - { -// m_log.DebugFormat( -// "[ASSET XFER UPLOADER]: Storing asset {0} for earlier task item update for {1} for {2}", -// m_asset.FullID, taskItem.Name, ourClient.Name); - - m_Scene.AssetService.Store(m_asset); - - m_transactions.RemoveXferUploader(m_transactionID); } - private void CompleteCreateItem(uint callbackID) + private void DoCreateItem(uint callbackID) { ValidateAssets(); m_Scene.AssetService.Store(m_asset); @@ -430,8 +339,6 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction ourClient.SendInventoryItemCreateUpdate(item, callbackID); else ourClient.SendAlertMessage("Unable to create inventory item"); - - m_transactions.RemoveXferUploader(m_transactionID); } private void ValidateAssets() @@ -509,7 +416,7 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction /// null if the asset has not finished uploading public AssetBase GetAssetData() { - if (m_uploadState == UploadState.Complete) + if (m_finished) { ValidateAssets(); return m_asset; @@ -562,3 +469,4 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction } } } + diff --git a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs index d1a563c..7d7176f 100644 --- a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs +++ b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs @@ -52,7 +52,7 @@ using OpenSim.Services.Interfaces; [assembly: Addin("FlotsamAssetCache", "1.1")] [assembly: AddinDependency("OpenSim", "0.5")] -namespace OpenSim.Region.CoreModules.Asset +namespace Flotsam.RegionModules.AssetCache { [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] public class FlotsamAssetCache : ISharedRegionModule, IImprovedAssetCache, IAssetService @@ -107,6 +107,8 @@ namespace OpenSim.Region.CoreModules.Asset private IAssetService m_AssetService; private List m_Scenes = new List(); + private bool m_DeepScanBeforePurge; + public FlotsamAssetCache() { m_InvalidChars.AddRange(Path.GetInvalidPathChars()); @@ -168,6 +170,8 @@ namespace OpenSim.Region.CoreModules.Asset m_CacheDirectoryTierLen = assetConfig.GetInt("CacheDirectoryTierLength", m_CacheDirectoryTierLen); m_CacheWarnAt = assetConfig.GetInt("CacheWarnAt", m_CacheWarnAt); + + m_DeepScanBeforePurge = assetConfig.GetBoolean("DeepScanBeforePurge", m_DeepScanBeforePurge); } m_log.InfoFormat("[FLOTSAM ASSET CACHE]: Cache Directory {0}", m_CacheDirectory); @@ -515,10 +519,13 @@ namespace OpenSim.Region.CoreModules.Asset // Purge all files last accessed prior to this point DateTime purgeLine = DateTime.Now - m_FileExpiration; - // An asset cache may contain local non-temporary assets that are not in the asset service. Therefore, - // before cleaning up expired files we must scan the objects in the scene to make sure that we retain - // such local assets if they have not been recently accessed. - TouchAllSceneAssets(false); + // An optional deep scan at this point will ensure assets present in scenes, + // or referenced by objects in the scene, but not recently accessed + // are not purged. + if (m_DeepScanBeforePurge) + { + CacheScenes(); + } foreach (string dir in Directory.GetDirectories(m_CacheDirectory)) { @@ -711,14 +718,11 @@ namespace OpenSim.Region.CoreModules.Asset /// /// Iterates through all Scenes, doing a deep scan through assets - /// to update the access time of all assets present in the scene or referenced by assets - /// in the scene. + /// to cache all assets present in the scene or referenced by assets + /// in the scene /// - /// - /// If true, then assets scanned which are not found in cache are added to the cache. - /// - /// Number of distinct asset references found in the scene. - private int TouchAllSceneAssets(bool storeUncached) + /// + private int CacheScenes() { UuidGatherer gatherer = new UuidGatherer(m_AssetService); @@ -741,7 +745,7 @@ namespace OpenSim.Region.CoreModules.Asset { File.SetLastAccessTime(filename, DateTime.Now); } - else if (storeUncached) + else { m_AssetService.Get(assetID.ToString()); } @@ -869,14 +873,13 @@ namespace OpenSim.Region.CoreModules.Asset break; + case "assets": - m_log.Info("[FLOTSAM ASSET CACHE]: Ensuring assets are cached for all scenes."); + m_log.Info("[FLOTSAM ASSET CACHE]: Caching all assets, in all scenes."); Util.FireAndForget(delegate { - int assetReferenceTotal = TouchAllSceneAssets(true); - m_log.InfoFormat( - "[FLOTSAM ASSET CACHE]: Completed check with {0} assets.", - assetReferenceTotal); + int assetsCached = CacheScenes(); + m_log.InfoFormat("[FLOTSAM ASSET CACHE]: Completed Scene Caching, {0} assets found.", assetsCached); }); break; diff --git a/OpenSim/Region/CoreModules/Asset/Tests/FlotsamAssetCacheTests.cs b/OpenSim/Region/CoreModules/Asset/Tests/FlotsamAssetCacheTests.cs index 1c2bfd0..c91b25f 100644 --- a/OpenSim/Region/CoreModules/Asset/Tests/FlotsamAssetCacheTests.cs +++ b/OpenSim/Region/CoreModules/Asset/Tests/FlotsamAssetCacheTests.cs @@ -35,6 +35,7 @@ using Nini.Config; using NUnit.Framework; using OpenMetaverse; using OpenMetaverse.Assets; +using Flotsam.RegionModules.AssetCache; using OpenSim.Framework; using OpenSim.Region.Framework.Scenes; using OpenSim.Region.Framework.Scenes.Serialization; diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs index acd156e..951afd7 100644 --- a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs @@ -286,20 +286,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments public bool AttachObject(IScenePresence sp, SceneObjectGroup group, uint attachmentPt, bool silent, bool useAttachData, bool temp) { - if (!Enabled) - return false; - - if (AttachObjectInternal(sp, group, attachmentPt, silent, useAttachData, temp)) - { - m_scene.EventManager.TriggerOnAttach(group.LocalId, group.FromItemID, sp.UUID); - return true; - } - - return false; - } - - private bool AttachObjectInternal(IScenePresence sp, SceneObjectGroup group, uint attachmentPt, bool silent, bool useAttachData, bool temp) - { lock (sp.AttachmentsSyncLock) { // m_log.DebugFormat( @@ -475,11 +461,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments public void DetachSingleAttachmentToGround(IScenePresence sp, uint soLocalId) { - DetachSingleAttachmentToGround(sp, soLocalId, sp.AbsolutePosition, Quaternion.Identity); - } - - public void DetachSingleAttachmentToGround(IScenePresence sp, uint soLocalId, Vector3 absolutePos, Quaternion absoluteRot) - { if (!Enabled) return; @@ -521,11 +502,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments so.FromItemID = UUID.Zero; SceneObjectPart rootPart = so.RootPart; - so.AbsolutePosition = absolutePos; - if (absoluteRot != Quaternion.Identity) - { - so.UpdateGroupRotationR(absoluteRot); - } + so.AbsolutePosition = sp.AbsolutePosition; so.AttachedAvatar = UUID.Zero; rootPart.SetParentLocalId(0); so.ClearPartAttachmentData(); @@ -639,9 +616,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments if (grp.HasGroupChanged) { - m_log.DebugFormat( - "[ATTACHMENTS MODULE]: Updating asset for attachment {0}, attachpoint {1}", - grp.UUID, grp.AttachmentPoint); +// m_log.DebugFormat( +// "[ATTACHMENTS MODULE]: Updating asset for attachment {0}, attachpoint {1}", +// grp.UUID, grp.AttachmentPoint); string sceneObjectXml = SceneObjectSerializer.ToOriginalXmlFormat(grp, scriptedState); @@ -885,7 +862,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments // This will throw if the attachment fails try { - AttachObjectInternal(sp, objatt, attachmentPt, false, false, false); + AttachObject(sp, objatt, attachmentPt, false, false, false); } catch (Exception e) { @@ -956,9 +933,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments InventoryItemBase item = new InventoryItemBase(itemID, sp.UUID); item = m_scene.InventoryService.GetItem(item); - if (item == null) - return; - bool changed = sp.Appearance.SetAttachment((int)AttachmentPt, itemID, item.AssetID); if (changed && m_scene.AvatarFactory != null) { diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs index 4e9d3f9..d9a619d 100644 --- a/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs +++ b/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs @@ -62,10 +62,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests public class AttachmentsModuleTests : OpenSimTestCase { private AutoResetEvent m_chatEvent = new AutoResetEvent(false); -// private OSChatMessage m_osChatMessageReceived; - - // Used to test whether the operations have fired the attach event. Must be reset after each test. - private int m_numberOfAttachEventsFired; + private OSChatMessage m_osChatMessageReceived; [TestFixtureSetUp] public void FixtureInit() @@ -86,7 +83,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests { // Console.WriteLine("Got chat [{0}]", oscm.Message); -// m_osChatMessageReceived = oscm; + m_osChatMessageReceived = oscm; m_chatEvent.Set(); } @@ -102,8 +99,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests "attachments-test-scene", TestHelpers.ParseTail(999), 1000, 1000, config); SceneHelpers.SetupSceneModules(scene, config, modules.ToArray()); - scene.EventManager.OnAttach += (localID, itemID, avatarID) => m_numberOfAttachEventsFired++; - return scene; } @@ -186,8 +181,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests TestHelpers.InMethod(); // TestHelpers.EnableLogging(); - m_numberOfAttachEventsFired = 0; - Scene scene = CreateTestScene(); UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene, 0x1); ScenePresence sp = SceneHelpers.AddScenePresence(scene, ua1); @@ -196,7 +189,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests SceneObjectGroup so = SceneHelpers.AddSceneObject(scene, attName, sp.UUID); - m_numberOfAttachEventsFired = 0; scene.AttachmentsModule.AttachObject(sp, so, (uint)AttachmentPoint.Chest, false, false, false); // Check status on scene presence @@ -224,8 +216,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1)); - // Check events - Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(1)); +// TestHelpers.DisableLogging(); } /// @@ -237,8 +228,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests TestHelpers.InMethod(); // TestHelpers.EnableLogging(); - m_numberOfAttachEventsFired = 0; - Scene scene = CreateTestScene(); UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene, 0x1); ScenePresence sp = SceneHelpers.AddScenePresence(scene, ua1); @@ -258,9 +247,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests Assert.That(sp.HasAttachments(), Is.False); Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1)); - - // Check events - Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(0)); } [Test] @@ -275,7 +261,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests InventoryItemBase attItem = CreateAttachmentItem(scene, ua1.PrincipalID, "att", 0x10, 0x20); - m_numberOfAttachEventsFired = 0; scene.AttachmentsModule.RezSingleAttachmentFromInventory( sp, attItem.ID, (uint)AttachmentPoint.Chest); @@ -295,9 +280,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests Assert.That(sp.Appearance.GetAttachpoint(attItem.ID), Is.EqualTo((int)AttachmentPoint.Chest)); Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1)); - - // Check events - Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(1)); } /// @@ -356,8 +338,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests ISceneEntity so = scene.AttachmentsModule.RezSingleAttachmentFromInventory( sp, attItem.ID, (uint)AttachmentPoint.Chest); - - m_numberOfAttachEventsFired = 0; scene.AttachmentsModule.DetachSingleAttachmentToGround(sp, so.LocalId); // Check scene presence status @@ -373,9 +353,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests // Check object in scene Assert.That(scene.GetSceneObjectGroup("att"), Is.Not.Null); - - // Check events - Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(1)); } [Test] @@ -392,8 +369,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests SceneObjectGroup so = (SceneObjectGroup)scene.AttachmentsModule.RezSingleAttachmentFromInventory( sp, attItem.ID, (uint)AttachmentPoint.Chest); - - m_numberOfAttachEventsFired = 0; scene.AttachmentsModule.DetachSingleAttachmentToInv(sp, so); // Check status on scene presence @@ -405,9 +380,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests Assert.That(sp.Appearance.GetAttachpoint(attItem.ID), Is.EqualTo(0)); Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(0)); - - // Check events - Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(1)); } /// @@ -489,14 +461,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests SceneObjectGroup rezzedAtt = presence.GetAttachments()[0]; - m_numberOfAttachEventsFired = 0; - scene.IncomingCloseAgent(presence.UUID, false); + scene.IncomingCloseAgent(presence.UUID); // Check that we can't retrieve this attachment from the scene. Assert.That(scene.GetSceneObjectGroup(rezzedAtt.UUID), Is.Null); - - // Check events - Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(0)); } [Test] @@ -512,8 +480,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests AgentCircuitData acd = SceneHelpers.GenerateAgentData(ua1.PrincipalID); acd.Appearance = new AvatarAppearance(); acd.Appearance.SetAttachment((int)AttachmentPoint.Chest, attItem.ID, attItem.AssetID); - - m_numberOfAttachEventsFired = 0; ScenePresence presence = SceneHelpers.AddScenePresence(scene, acd); Assert.That(presence.HasAttachments(), Is.True); @@ -536,9 +502,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests Assert.That(presence.Appearance.GetAttachpoint(attItem.ID), Is.EqualTo((int)AttachmentPoint.Chest)); Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1)); - - // Check events. We expect OnAttach to fire on login. - Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(1)); } [Test] @@ -559,14 +522,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests Vector3 newPosition = new Vector3(1, 2, 4); - m_numberOfAttachEventsFired = 0; scene.SceneGraph.UpdatePrimGroupPosition(attSo.LocalId, newPosition, sp.ControllingClient); Assert.That(attSo.AbsolutePosition, Is.EqualTo(sp.AbsolutePosition)); Assert.That(attSo.RootPart.AttachedPos, Is.EqualTo(newPosition)); - - // Check events - Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(0)); } [Test] @@ -615,7 +574,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests Vector3 teleportPosition = new Vector3(10, 11, 12); Vector3 teleportLookAt = new Vector3(20, 21, 22); - m_numberOfAttachEventsFired = 0; sceneA.RequestTeleportLocation( beforeTeleportSp.ControllingClient, sceneB.RegionInfo.RegionHandle, @@ -658,9 +616,29 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests Assert.That(actualSceneAAttachments.Count, Is.EqualTo(0)); Assert.That(sceneA.GetSceneObjectGroups().Count, Is.EqualTo(0)); - - // Check events - Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(0)); } + + // I'm commenting this test because scene setup NEEDS InventoryService to + // be non-null + //[Test] +// public void T032_CrossAttachments() +// { +// TestHelpers.InMethod(); +// +// ScenePresence presence = scene.GetScenePresence(agent1); +// ScenePresence presence2 = scene2.GetScenePresence(agent1); +// presence2.AddAttachment(sog1); +// presence2.AddAttachment(sog2); +// +// ISharedRegionModule serialiser = new SerialiserModule(); +// SceneHelpers.SetupSceneModules(scene, new IniConfigSource(), serialiser); +// SceneHelpers.SetupSceneModules(scene2, new IniConfigSource(), serialiser); +// +// Assert.That(presence.HasAttachments(), Is.False, "Presence has attachments before cross"); +// +// //Assert.That(presence2.CrossAttachmentsIntoNewRegion(region1, true), Is.True, "Cross was not successful"); +// Assert.That(presence2.HasAttachments(), Is.False, "Presence2 objects were not deleted"); +// Assert.That(presence.HasAttachments(), Is.True, "Presence has not received new objects"); +// } } } diff --git a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs index e3bf997..4cb4370 100644 --- a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs @@ -533,7 +533,6 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory // Ignore ruth's assets if (appearance.Wearables[i][j].ItemID == AvatarWearable.DefaultWearables[i][0].ItemID) continue; - InventoryItemBase baseItem = new InventoryItemBase(appearance.Wearables[i][j].ItemID, userID); baseItem = invService.GetItem(baseItem); diff --git a/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs b/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs index 4407e40..dbbb0ae 100644 --- a/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs @@ -197,7 +197,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat string fromName = c.From; string fromNamePrefix = ""; UUID fromID = UUID.Zero; - UUID ownerID = UUID.Zero; string message = c.Message; IScene scene = c.Scene; UUID destination = c.Destination; @@ -225,16 +224,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat fromNamePrefix = m_adminPrefix; } destination = UUID.Zero; // Avatars cant "SayTo" - ownerID = c.Sender.AgentId; - break; case ChatSourceType.Object: fromID = c.SenderUUID; - if (c.SenderObject != null && c.SenderObject is SceneObjectPart) - ownerID = ((SceneObjectPart)c.SenderObject).OwnerID; - break; } @@ -268,16 +262,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat // objects on a parcel with access restrictions if (c.Sender == null || Presencecheck.IsEitherBannedOrRestricted(c.Sender.AgentId) != true) { - if (destination != UUID.Zero) - { - if (TrySendChatMessage(presence, fromPos, regionPos, fromID, ownerID, fromNamePrefix + fromName, c.Type, message, sourceType, true)) - receiverIDs.Add(presence.UUID); - } - else - { - if (TrySendChatMessage(presence, fromPos, regionPos, fromID, ownerID, fromNamePrefix + fromName, c.Type, message, sourceType, false)) - receiverIDs.Add(presence.UUID); - } + if (TrySendChatMessage(presence, fromPos, regionPos, fromID, fromNamePrefix + fromName, c.Type, message, sourceType)) + receiverIDs.Add(presence.UUID); } } } @@ -338,7 +324,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat (((SceneObjectPart)c.SenderObject).OwnerID != client.AgentId)) return; - client.SendChatMessage(c.Message, (byte)cType, CenterOfRegion, fromName, fromID, fromID, + client.SendChatMessage(c.Message, (byte)cType, CenterOfRegion, fromName, fromID, (byte)sourceType, (byte)ChatAudibleLevel.Fully); receiverIDs.Add(client.AgentId); } @@ -355,20 +341,15 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat /// /// /param> /// - /// - /// Owner of the message. For at least some messages from objects, this has to be correctly filled with the owner's UUID. - /// This is the case for script error messages in viewer 3 since LLViewer change EXT-7762 - /// /// /// /// /// /// true if the message was sent to the receiver, false if it was not sent due to failing a /// precondition - protected virtual bool TrySendChatMessage( - ScenePresence presence, Vector3 fromPos, Vector3 regionPos, - UUID fromAgentID, UUID ownerID, string fromName, ChatTypeEnum type, - string message, ChatSourceType src, bool ignoreDistance) + protected virtual bool TrySendChatMessage(ScenePresence presence, Vector3 fromPos, Vector3 regionPos, + UUID fromAgentID, string fromName, ChatTypeEnum type, + string message, ChatSourceType src) { // don't send chat to child agents if (presence.IsChildAgent) return false; @@ -388,9 +369,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat } // TODO: should change so the message is sent through the avatar rather than direct to the ClientView - presence.ControllingClient.SendChatMessage( - message, (byte) type, fromPos, fromName, - fromAgentID, ownerID, (byte)src, (byte)ChatAudibleLevel.Fully); + presence.ControllingClient.SendChatMessage(message, (byte) type, fromPos, fromName, + fromAgentID, (byte)src, (byte)ChatAudibleLevel.Fully); return true; } diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/CallingCardModule.cs b/OpenSim/Region/CoreModules/Avatar/Friends/CallingCardModule.cs index 5ec0ea9..d942e87 100644 --- a/OpenSim/Region/CoreModules/Avatar/Friends/CallingCardModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Friends/CallingCardModule.cs @@ -141,7 +141,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends client.FirstName+" "+client.LastName, destID, (byte)211, false, String.Empty, - transactionID, false, new Vector3(), new byte[0], true), + transactionID, false, new Vector3(), new byte[0]), delegate(bool success) {} ); } } diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs index f1903c3..24ec435 100644 --- a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs @@ -28,7 +28,6 @@ using System; using System.Collections; using System.Collections.Generic; -using System.Linq; using System.Reflection; using System.Threading; using log4net; @@ -483,9 +482,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends Util.FireAndForget( delegate { -// m_log.DebugFormat( -// "[FRIENDS MODULE]: Notifying {0} friends of {1} of online status {2}", -// friendList.Count, agentID, online); + m_log.DebugFormat( + "[FRIENDS MODULE]: Notifying {0} friends of {1} of online status {2}", + friendList.Count, agentID, online); // Notify about this user status StatusNotify(friendList, agentID, online); @@ -496,36 +495,42 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends protected virtual void StatusNotify(List friendList, UUID userID, bool online) { - List friendStringIds = friendList.ConvertAll(friend => friend.Friend); - List remoteFriendStringIds = new List(); - foreach (string friendStringId in friendStringIds) + foreach (FriendInfo friend in friendList) { - UUID friendUuid; - if (UUID.TryParse(friendStringId, out friendUuid)) + UUID friendID; + if (UUID.TryParse(friend.Friend, out friendID)) { - if (LocalStatusNotification(userID, friendUuid, online)) + // Try local + if (LocalStatusNotification(userID, friendID, online)) continue; - remoteFriendStringIds.Add(friendStringId); + // The friend is not here [as root]. Let's forward. + PresenceInfo[] friendSessions = PresenceService.GetAgents(new string[] { friendID.ToString() }); + if (friendSessions != null && friendSessions.Length > 0) + { + PresenceInfo friendSession = null; + foreach (PresenceInfo pinfo in friendSessions) + { + if (pinfo.RegionID != UUID.Zero) // let's guard against sessions-gone-bad + { + friendSession = pinfo; + break; + } + } + + if (friendSession != null) + { + GridRegion region = GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, friendSession.RegionID); + //m_log.DebugFormat("[FRIENDS]: Remote Notify to region {0}", region.RegionName); + m_FriendsSimConnector.StatusNotify(region, userID, friendID, online); + } + } + + // Friend is not online. Ignore. } else { - m_log.WarnFormat("[FRIENDS]: Error parsing friend ID {0}", friendStringId); - } - } - - // We do this regrouping so that we can efficiently send a single request rather than one for each - // friend in what may be a very large friends list. - PresenceInfo[] friendSessions = PresenceService.GetAgents(remoteFriendStringIds.ToArray()); - - foreach (PresenceInfo friendSession in friendSessions) - { - // let's guard against sessions-gone-bad - if (friendSession.RegionID != UUID.Zero) - { - GridRegion region = GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, friendSession.RegionID); - //m_log.DebugFormat("[FRIENDS]: Remote Notify to region {0}", region.RegionName); - m_FriendsSimConnector.StatusNotify(region, userID, friendSession.UserID, online); + m_log.WarnFormat("[FRIENDS]: Error parsing friend ID {0}", friend.Friend); } } } diff --git a/OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs b/OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs index 82816d9..716cc69 100644 --- a/OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs @@ -206,7 +206,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Gods transferModule.SendInstantMessage(new GridInstantMessage( m_scene, godID, "God", agentID, (byte)250, false, Utils.BytesToString(reason), UUID.Zero, true, - new Vector3(), new byte[] {(byte)kickflags}, true), + new Vector3(), new byte[] {(byte)kickflags}), delegate(bool success) {} ); } return; diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs index d0e88f6..6587ead 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs @@ -166,7 +166,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver if (options.ContainsKey("verbose")) m_log.InfoFormat( - "[INVENTORY ARCHIVER]: Saving item {0} {1} (asset UUID {2})", + "[INVENTORY ARCHIVER]: Saving item {0} {1} with asset {2}", inventoryItem.ID, inventoryItem.Name, inventoryItem.AssetID); string filename = path + CreateArchiveItemName(inventoryItem); @@ -337,14 +337,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver { m_log.DebugFormat("[INVENTORY ARCHIVER]: Saving {0} assets for items", m_assetUuids.Count); - AssetsRequest ar - = new AssetsRequest( - new AssetsArchiver(m_archiveWriter), - m_assetUuids, m_scene.AssetService, - m_scene.UserAccountService, m_scene.RegionInfo.ScopeID, - options, ReceivedAllAssets); - - Util.FireAndForget(o => ar.Execute()); + new AssetsRequest( + new AssetsArchiver(m_archiveWriter), + m_assetUuids, m_scene.AssetService, + m_scene.UserAccountService, m_scene.RegionInfo.ScopeID, + options, ReceivedAllAssets).Execute(); } else { diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs index 765b960..7d1fe68 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs @@ -35,7 +35,6 @@ using Nini.Config; using OpenMetaverse; using OpenSim.Framework; using OpenSim.Framework.Communications; -using OpenSim.Framework.Console; using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Scenes; using OpenSim.Services.Interfaces; @@ -210,9 +209,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver Guid id, string firstName, string lastName, string invPath, string pass, string savePath, Dictionary options) { -// if (!ConsoleUtil.CheckFileDoesNotExist(MainConsole.Instance, savePath)) -// return false; - if (m_scenes.Count > 0) { UserAccount userInfo = GetUserInfo(firstName, lastName, pass); diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveTestCase.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveTestCase.cs index 00727a4..1056865 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveTestCase.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveTestCase.cs @@ -82,25 +82,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests protected string m_item1Name = "Ray Gun Item"; protected string m_coaItemName = "Coalesced Item"; - - [TestFixtureSetUp] - public void FixtureSetup() - { - // Don't allow tests to be bamboozled by asynchronous events. Execute everything on the same thread. - Util.FireAndForgetMethod = FireAndForgetMethod.RegressionTest; - - ConstructDefaultIarBytesForTestLoad(); - } - - [TestFixtureTearDown] - public void TearDown() - { - // We must set this back afterwards, otherwise later tests will fail since they're expecting multiple - // threads. Possibly, later tests should be rewritten so none of them require async stuff (which regression - // tests really shouldn't). - Util.FireAndForgetMethod = Util.DefaultFireAndForgetMethod; - } - + [SetUp] public override void SetUp() { @@ -108,6 +90,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests m_iarStream = new MemoryStream(m_iarStreamBytes); } + [TestFixtureSetUp] + public void FixtureSetup() + { + ConstructDefaultIarBytesForTestLoad(); + } + protected void ConstructDefaultIarBytesForTestLoad() { // log4net.Config.XmlConfigurator.Configure(); diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs index 06f6e49..b112b6d 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs @@ -49,7 +49,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests { [TestFixture] public class InventoryArchiverTests : InventoryArchiveTestCase - { + { protected TestScene m_scene; protected InventoryArchiverModule m_archiverModule; @@ -69,7 +69,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests public void TestLoadCoalesecedItem() { TestHelpers.InMethod(); -// TestHelpers.EnableLogging(); +// log4net.Config.XmlConfigurator.Configure(); UserAccountHelpers.CreateUserWithInventory(m_scene, m_uaLL1, "password"); m_archiverModule.DearchiveInventory(m_uaLL1.FirstName, m_uaLL1.LastName, "/", "password", m_iarStream); @@ -350,38 +350,38 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests Assert.That(sog1.RootPart.CreatorID, Is.EqualTo(m_uaLL1.PrincipalID)); } -// /// -// /// Test loading a V0.1 OpenSim Inventory Archive (subject to change since there is no fixed format yet) where -// /// an account exists with the same name as the creator, though not the same id. -// /// -// [Test] -// public void TestLoadIarV0_1SameNameCreator() -// { -// TestHelpers.InMethod(); -// TestHelpers.EnableLogging(); -// -// UserAccountHelpers.CreateUserWithInventory(m_scene, m_uaMT, "meowfood"); -// UserAccountHelpers.CreateUserWithInventory(m_scene, m_uaLL2, "hampshire"); -// -// m_archiverModule.DearchiveInventory(m_uaMT.FirstName, m_uaMT.LastName, "/", "meowfood", m_iarStream); -// InventoryItemBase foundItem1 -// = InventoryArchiveUtils.FindItemByPath(m_scene.InventoryService, m_uaMT.PrincipalID, m_item1Name); -// -// Assert.That( -// foundItem1.CreatorId, Is.EqualTo(m_uaLL2.PrincipalID.ToString()), -// "Loaded item non-uuid creator doesn't match original"); -// Assert.That( -// foundItem1.CreatorIdAsUuid, Is.EqualTo(m_uaLL2.PrincipalID), -// "Loaded item uuid creator doesn't match original"); -// Assert.That(foundItem1.Owner, Is.EqualTo(m_uaMT.PrincipalID), -// "Loaded item owner doesn't match inventory reciever"); -// -// AssetBase asset1 = m_scene.AssetService.Get(foundItem1.AssetID.ToString()); -// string xmlData = Utils.BytesToString(asset1.Data); -// SceneObjectGroup sog1 = SceneObjectSerializer.FromOriginalXmlFormat(xmlData); -// -// Assert.That(sog1.RootPart.CreatorID, Is.EqualTo(m_uaLL2.PrincipalID)); -// } + /// + /// Test loading a V0.1 OpenSim Inventory Archive (subject to change since there is no fixed format yet) where + /// an account exists with the same name as the creator, though not the same id. + /// + [Test] + public void TestLoadIarV0_1SameNameCreator() + { + TestHelpers.InMethod(); +// log4net.Config.XmlConfigurator.Configure(); + + UserAccountHelpers.CreateUserWithInventory(m_scene, m_uaMT, "meowfood"); + UserAccountHelpers.CreateUserWithInventory(m_scene, m_uaLL2, "hampshire"); + + m_archiverModule.DearchiveInventory(m_uaMT.FirstName, m_uaMT.LastName, "/", "meowfood", m_iarStream); + InventoryItemBase foundItem1 + = InventoryArchiveUtils.FindItemByPath(m_scene.InventoryService, m_uaMT.PrincipalID, m_item1Name); + + Assert.That( + foundItem1.CreatorId, Is.EqualTo(m_uaLL2.PrincipalID.ToString()), + "Loaded item non-uuid creator doesn't match original"); + Assert.That( + foundItem1.CreatorIdAsUuid, Is.EqualTo(m_uaLL2.PrincipalID), + "Loaded item uuid creator doesn't match original"); + Assert.That(foundItem1.Owner, Is.EqualTo(m_uaMT.PrincipalID), + "Loaded item owner doesn't match inventory reciever"); + + AssetBase asset1 = m_scene.AssetService.Get(foundItem1.AssetID.ToString()); + string xmlData = Utils.BytesToString(asset1.Data); + SceneObjectGroup sog1 = SceneObjectSerializer.FromOriginalXmlFormat(xmlData); + + Assert.That(sog1.RootPart.CreatorID, Is.EqualTo(m_uaLL2.PrincipalID)); + } /// /// Test loading a V0.1 OpenSim Inventory Archive (subject to change since there is no fixed format yet) where diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs index e26beec..8176989 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs @@ -38,15 +38,15 @@ using OpenSim.Services.Interfaces; namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer { - public class InventoryTransferModule : ISharedRegionModule + public class InventoryTransferModule : IInventoryTransferModule, ISharedRegionModule { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); /// private List m_Scenelist = new List(); -// private Dictionary m_AgentRegions = -// new Dictionary(); + private Dictionary m_AgentRegions = + new Dictionary(); private IMessageTransferModule m_TransferModule = null; private bool m_Enabled = true; @@ -76,12 +76,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer m_Scenelist.Add(scene); -// scene.RegisterModuleInterface(this); + scene.RegisterModuleInterface(this); scene.EventManager.OnNewClient += OnNewClient; -// scene.EventManager.OnClientClosed += ClientLoggedOut; + scene.EventManager.OnClientClosed += ClientLoggedOut; scene.EventManager.OnIncomingInstantMessage += OnGridInstantMessage; -// scene.EventManager.OnSetRootAgentScene += OnSetRootAgentScene; + scene.EventManager.OnSetRootAgentScene += OnSetRootAgentScene; } public void RegionLoaded(Scene scene) @@ -96,9 +96,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer m_Scenelist.Clear(); scene.EventManager.OnNewClient -= OnNewClient; -// scene.EventManager.OnClientClosed -= ClientLoggedOut; + scene.EventManager.OnClientClosed -= ClientLoggedOut; scene.EventManager.OnIncomingInstantMessage -= OnGridInstantMessage; -// scene.EventManager.OnSetRootAgentScene -= OnSetRootAgentScene; + scene.EventManager.OnSetRootAgentScene -= OnSetRootAgentScene; } } } @@ -106,9 +106,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer public void RemoveRegion(Scene scene) { scene.EventManager.OnNewClient -= OnNewClient; -// scene.EventManager.OnClientClosed -= ClientLoggedOut; + scene.EventManager.OnClientClosed -= ClientLoggedOut; scene.EventManager.OnIncomingInstantMessage -= OnGridInstantMessage; -// scene.EventManager.OnSetRootAgentScene -= OnSetRootAgentScene; + scene.EventManager.OnSetRootAgentScene -= OnSetRootAgentScene; m_Scenelist.Remove(scene); } @@ -138,10 +138,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer client.OnInstantMessage += OnInstantMessage; } -// protected void OnSetRootAgentScene(UUID id, Scene scene) -// { -// m_AgentRegions[id] = scene; -// } + protected void OnSetRootAgentScene(UUID id, Scene scene) + { + m_AgentRegions[id] = scene; + } private Scene FindClientScene(UUID agentId) { @@ -313,11 +313,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer m_TransferModule.SendInstantMessage(im, delegate(bool success) {}); } } - - // XXX: This code was placed here to try and accomdate RLV which moves given folders named #RLV/~ - // to a folder called name in #RLV. However, this approach may not be ultimately correct - from analysis - // of Firestorm 4.2.2 on sending an InventoryOffered instead of TaskInventoryOffered (as was previously - // done), the viewer itself would appear to move and rename the folder, rather than the simulator doing it here. else if (im.dialog == (byte) InstantMessageDialog.TaskInventoryAccepted) { UUID destinationFolderID = UUID.Zero; @@ -329,16 +324,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer if (destinationFolderID != UUID.Zero) { - InventoryFolderBase destinationFolder = new InventoryFolderBase(destinationFolderID, client.AgentId); - if (destinationFolder == null) - { - m_log.WarnFormat( - "[INVENTORY TRANSFER]: TaskInventoryAccepted message from {0} in {1} specified folder {2} which does not exist", - client.Name, scene.Name, destinationFolderID); - - return; - } - IInventoryService invService = scene.InventoryService; UUID inventoryID = new UUID(im.imSessionID); // The inventory item/folder, back from it's trip @@ -346,11 +331,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer InventoryItemBase item = new InventoryItemBase(inventoryID, client.AgentId); item = invService.GetItem(item); InventoryFolderBase folder = null; - UUID? previousParentFolderID = null; if (item != null) // It's an item { - previousParentFolderID = item.Folder; item.Folder = destinationFolderID; invService.DeleteItems(item.Owner, new List() { item.ID }); @@ -363,22 +346,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer if (folder != null) // It's a folder { - previousParentFolderID = folder.ParentID; folder.ParentID = destinationFolderID; invService.MoveFolder(folder); } } - - // Tell client about updates to original parent and new parent (this should probably be factored with existing move item/folder code). - if (previousParentFolderID != null) - { - InventoryFolderBase previousParentFolder - = new InventoryFolderBase((UUID)previousParentFolderID, client.AgentId); - previousParentFolder = invService.GetFolder(previousParentFolder); - scene.SendInventoryUpdate(client, previousParentFolder, true, true); - - scene.SendInventoryUpdate(client, destinationFolder, true, true); - } } } else if ( @@ -399,11 +370,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer InventoryItemBase item = new InventoryItemBase(inventoryID, client.AgentId); item = invService.GetItem(item); InventoryFolderBase folder = null; - UUID? previousParentFolderID = null; if (item != null && trashFolder != null) { - previousParentFolderID = item.Folder; item.Folder = trashFolder.ID; // Diva comment: can't we just update this item??? @@ -419,7 +388,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer if (folder != null & trashFolder != null) { - previousParentFolderID = folder.ParentID; folder.ParentID = trashFolder.ID; invService.MoveFolder(folder); client.SendBulkUpdateInventory(folder); @@ -440,16 +408,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer client.SendAgentAlertMessage("Unable to delete "+ "received inventory" + reason, false); } - // Tell client about updates to original parent and new parent (this should probably be factored with existing move item/folder code). - else if (previousParentFolderID != null) - { - InventoryFolderBase previousParentFolder - = new InventoryFolderBase((UUID)previousParentFolderID, client.AgentId); - previousParentFolder = invService.GetFolder(previousParentFolder); - scene.SendInventoryUpdate(client, previousParentFolder, true, true); - - scene.SendInventoryUpdate(client, trashFolder, true, true); - } if (im.dialog == (byte)InstantMessageDialog.InventoryDeclined) { @@ -468,69 +426,69 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer } } -// public bool NeedSceneCacheClear(UUID agentID, Scene scene) -// { -// if (!m_AgentRegions.ContainsKey(agentID)) -// { -// // Since we can get here two ways, we need to scan -// // the scenes here. This is somewhat more expensive -// // but helps avoid a nasty bug -// // -// -// foreach (Scene s in m_Scenelist) -// { -// ScenePresence presence; -// -// if (s.TryGetScenePresence(agentID, out presence)) -// { -// // If the agent is in this scene, then we -// // are being called twice in a single -// // teleport. This is wasteful of cycles -// // but harmless due to this 2nd level check -// // -// // If the agent is found in another scene -// // then the list wasn't current -// // -// // If the agent is totally unknown, then what -// // are we even doing here?? -// // -// if (s == scene) -// { -// //m_log.Debug("[INVTRANSFERMOD]: s == scene. Returning true in " + scene.RegionInfo.RegionName); -// return true; -// } -// else -// { -// //m_log.Debug("[INVTRANSFERMOD]: s != scene. Returning false in " + scene.RegionInfo.RegionName); -// return false; -// } -// } -// } -// //m_log.Debug("[INVTRANSFERMOD]: agent not in scene. Returning true in " + scene.RegionInfo.RegionName); -// return true; -// } -// -// // The agent is left in current Scene, so we must be -// // going to another instance -// // -// if (m_AgentRegions[agentID] == scene) -// { -// //m_log.Debug("[INVTRANSFERMOD]: m_AgentRegions[agentID] == scene. Returning true in " + scene.RegionInfo.RegionName); -// m_AgentRegions.Remove(agentID); -// return true; -// } -// -// // Another region has claimed the agent -// // -// //m_log.Debug("[INVTRANSFERMOD]: last resort. Returning false in " + scene.RegionInfo.RegionName); -// return false; -// } -// -// public void ClientLoggedOut(UUID agentID, Scene scene) -// { -// if (m_AgentRegions.ContainsKey(agentID)) -// m_AgentRegions.Remove(agentID); -// } + public bool NeedSceneCacheClear(UUID agentID, Scene scene) + { + if (!m_AgentRegions.ContainsKey(agentID)) + { + // Since we can get here two ways, we need to scan + // the scenes here. This is somewhat more expensive + // but helps avoid a nasty bug + // + + foreach (Scene s in m_Scenelist) + { + ScenePresence presence; + + if (s.TryGetScenePresence(agentID, out presence)) + { + // If the agent is in this scene, then we + // are being called twice in a single + // teleport. This is wasteful of cycles + // but harmless due to this 2nd level check + // + // If the agent is found in another scene + // then the list wasn't current + // + // If the agent is totally unknown, then what + // are we even doing here?? + // + if (s == scene) + { + //m_log.Debug("[INVTRANSFERMOD]: s == scene. Returning true in " + scene.RegionInfo.RegionName); + return true; + } + else + { + //m_log.Debug("[INVTRANSFERMOD]: s != scene. Returning false in " + scene.RegionInfo.RegionName); + return false; + } + } + } + //m_log.Debug("[INVTRANSFERMOD]: agent not in scene. Returning true in " + scene.RegionInfo.RegionName); + return true; + } + + // The agent is left in current Scene, so we must be + // going to another instance + // + if (m_AgentRegions[agentID] == scene) + { + //m_log.Debug("[INVTRANSFERMOD]: m_AgentRegions[agentID] == scene. Returning true in " + scene.RegionInfo.RegionName); + m_AgentRegions.Remove(agentID); + return true; + } + + // Another region has claimed the agent + // + //m_log.Debug("[INVTRANSFERMOD]: last resort. Returning false in " + scene.RegionInfo.RegionName); + return false; + } + + public void ClientLoggedOut(UUID agentID, Scene scene) + { + if (m_AgentRegions.ContainsKey(agentID)) + m_AgentRegions.Remove(agentID); + } /// /// diff --git a/OpenSim/Region/CoreModules/Avatar/Lure/HGLureModule.cs b/OpenSim/Region/CoreModules/Avatar/Lure/HGLureModule.cs index 9c369f6..92cf9d1 100644 --- a/OpenSim/Region/CoreModules/Avatar/Lure/HGLureModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Lure/HGLureModule.cs @@ -186,7 +186,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Lure client.FirstName+" "+client.LastName, targetid, (byte)InstantMessageDialog.RequestTeleport, false, message, sessionID, false, presence.AbsolutePosition, - new Byte[0], true); + new Byte[0]); m.RegionID = client.Scene.RegionInfo.RegionID.Guid; m_log.DebugFormat("[HG LURE MODULE]: RequestTeleport sessionID={0}, regionID={1}, message={2}", m.imSessionID, m.RegionID, m.message); diff --git a/OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs b/OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs index 1949459..a889984 100644 --- a/OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs @@ -173,7 +173,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Lure client.FirstName+" "+client.LastName, targetid, (byte)InstantMessageDialog.GodLikeRequestTeleport, false, message, dest, false, presence.AbsolutePosition, - new Byte[0], true); + new Byte[0]); } else { @@ -181,7 +181,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Lure client.FirstName+" "+client.LastName, targetid, (byte)InstantMessageDialog.RequestTeleport, false, message, dest, false, presence.AbsolutePosition, - new Byte[0], true); + new Byte[0]); } if (m_TransferModule != null) diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs index 31e6ce9..880b2cc 100644 --- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs +++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs @@ -327,14 +327,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer return; } - // Validate assorted conditions - string reason = string.Empty; - if (!ValidateGenericConditions(sp, reg, finalDestination, teleportFlags, out reason)) - { - sp.ControllingClient.SendTeleportFailed(reason); - return; - } - // // This is it // @@ -366,13 +358,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer } } - // Nothing to validate here - protected virtual bool ValidateGenericConditions(ScenePresence sp, GridRegion reg, GridRegion finalDestination, uint teleportFlags, out string reason) - { - reason = String.Empty; - return true; - } - /// /// Determines whether this instance is within the max transfer distance. /// @@ -488,11 +473,10 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer // both regions if (sp.ParentID != (uint)0) sp.StandUp(); + else if (sp.Flying) teleportFlags |= (uint)TeleportFlags.IsFlying; - // At least on LL 3.3.4, this is not strictly necessary - a teleport will succeed without sending this to - // the viewer. However, it might mean that the viewer does not see the black teleport screen (untested). sp.ControllingClient.SendTeleportStart(teleportFlags); // the avatar.Close below will clear the child region list. We need this below for (possibly) @@ -568,11 +552,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer // So let's wait Thread.Sleep(200); - // At least on LL 3.3.4 for teleports between different regions on the same simulator this appears - // unnecessary - teleport will succeed and SEED caps will be requested without it (though possibly - // only on TeleportFinish). This is untested for region teleport between different simulators - // though this probably also works. m_eqModule.EstablishAgentCommunication(sp.UUID, endPoint, capsPath); + } else { @@ -593,7 +574,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer //sp.ControllingClient.SendTeleportProgress(teleportFlags, "Updating agent..."); - if (!UpdateAgent(reg, finalDestination, agent, sp)) + if (!UpdateAgent(reg, finalDestination, agent)) { // Region doesn't take it m_log.WarnFormat( @@ -669,7 +650,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer // an agent cannot teleport back to this region if it has teleported away. Thread.Sleep(3000); - sp.Scene.IncomingCloseAgent(sp.UUID, false); + sp.Scene.IncomingCloseAgent(sp.UUID); } else { @@ -677,14 +658,13 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer sp.Reset(); } - // Commented pending deletion since this method no longer appears to do anything at all -// // REFACTORING PROBLEM. Well, not a problem, but this method is HORRIBLE! -// if (sp.Scene.NeedSceneCacheClear(sp.UUID)) -// { -// m_log.DebugFormat( -// "[ENTITY TRANSFER MODULE]: User {0} is going to another region, profile cache removed", -// sp.UUID); -// } + // REFACTORING PROBLEM. Well, not a problem, but this method is HORRIBLE! + if (sp.Scene.NeedSceneCacheClear(sp.UUID)) + { + m_log.DebugFormat( + "[ENTITY TRANSFER MODULE]: User {0} is going to another region, profile cache removed", + sp.UUID); + } m_entityTransferStateMachine.ResetFromTransit(sp.UUID); } @@ -721,7 +701,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer return success; } - protected virtual bool UpdateAgent(GridRegion reg, GridRegion finalDestination, AgentData agent, ScenePresence sp) + protected virtual bool UpdateAgent(GridRegion reg, GridRegion finalDestination, AgentData agent) { return Scene.SimulationService.UpdateAgent(finalDestination, agent); } @@ -1033,7 +1013,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer Scene initiatingScene) { Thread.Sleep(10000); - IMessageTransferModule im = initiatingScene.RequestModuleInterface(); if (im != null) { @@ -1046,22 +1025,11 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer (uint)(int)position.X, (uint)(int)position.Y, (uint)(int)position.Z); - - GridInstantMessage m - = new GridInstantMessage( - initiatingScene, - UUID.Zero, - "Region", - agent.UUID, - (byte)InstantMessageDialog.GodLikeRequestTeleport, - false, - "", - gotoLocation, - false, - new Vector3(127, 0, 0), - new Byte[0], - false); - + GridInstantMessage m = new GridInstantMessage(initiatingScene, UUID.Zero, + "Region", agent.UUID, + (byte)InstantMessageDialog.GodLikeRequestTeleport, false, + "", gotoLocation, false, new Vector3(127, 0, 0), + new Byte[0]); im.SendInstantMessage(m, delegate(bool success) { m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Client Initiating Teleport sending IM success = {0}", success); @@ -1223,11 +1191,11 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer // the user may change their profile information in other region, // so the userinfo in UserProfileCache is not reliable any more, delete it // REFACTORING PROBLEM. Well, not a problem, but this method is HORRIBLE! -// if (agent.Scene.NeedSceneCacheClear(agent.UUID)) -// { -// m_log.DebugFormat( -// "[ENTITY TRANSFER MODULE]: User {0} is going to another region", agent.UUID); -// } + if (agent.Scene.NeedSceneCacheClear(agent.UUID)) + { + m_log.DebugFormat( + "[ENTITY TRANSFER MODULE]: User {0} is going to another region", agent.UUID); + } //m_log.Debug("AFTER CROSS"); //Scene.DumpChildrenSeeds(UUID); diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs index b16c37a..3010b59 100644 --- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs +++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs @@ -54,59 +54,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer private GatekeeperServiceConnector m_GatekeeperConnector; - protected bool m_RestrictAppearanceAbroad; - protected string m_AccountName; - protected List m_ExportedAppearances; - protected List m_Attachs; - - protected List ExportedAppearance - { - get - { - if (m_ExportedAppearances != null) - return m_ExportedAppearances; - - m_ExportedAppearances = new List(); - m_Attachs = new List(); - - string[] names = m_AccountName.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries); - - foreach (string name in names) - { - string[] parts = name.Trim().Split(); - if (parts.Length != 2) - { - m_log.WarnFormat("[HG ENTITY TRANSFER MODULE]: Wrong user account name format {0}. Specify 'First Last'", name); - return null; - } - UserAccount account = Scene.UserAccountService.GetUserAccount(UUID.Zero, parts[0], parts[1]); - if (account == null) - { - m_log.WarnFormat("[HG ENTITY TRANSFER MODULE]: Unknown account {0}", m_AccountName); - return null; - } - AvatarAppearance a = Scene.AvatarService.GetAppearance(account.PrincipalID); - if (a != null) - m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Successfully retrieved appearance for {0}", name); - - foreach (AvatarAttachment att in a.GetAttachments()) - { - InventoryItemBase item = new InventoryItemBase(att.ItemID, account.PrincipalID); - item = Scene.InventoryService.GetItem(item); - if (item != null) - a.SetAttachment(att.AttachPoint, att.ItemID, item.AssetID); - else - m_log.WarnFormat("[HG ENTITY TRANSFER MODULE]: Unable to retrieve item {0} from inventory {1}", att.ItemID, name); - } - - m_ExportedAppearances.Add(a); - m_Attachs.AddRange(a.GetAttachments()); - } - - return m_ExportedAppearances; - } - } - #region ISharedRegionModule public override string Name @@ -125,18 +72,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer { IConfig transferConfig = source.Configs["EntityTransfer"]; if (transferConfig != null) - { m_levelHGTeleport = transferConfig.GetInt("LevelHGTeleport", 0); - m_RestrictAppearanceAbroad = transferConfig.GetBoolean("RestrictAppearanceAbroad", false); - if (m_RestrictAppearanceAbroad) - { - m_AccountName = transferConfig.GetString("AccountForAppearance", string.Empty); - if (m_AccountName == string.Empty) - m_log.WarnFormat("[HG ENTITY TRANSFER MODULE]: RestrictAppearanceAbroad is on, but no account has been given for avatar appearance!"); - } - } - InitialiseCommon(source); m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: {0} enabled.", Name); } @@ -148,36 +85,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer base.AddRegion(scene); if (m_Enabled) - { scene.RegisterModuleInterface(this); - scene.EventManager.OnIncomingSceneObject += OnIncomingSceneObject; - } - } - - void OnIncomingSceneObject(SceneObjectGroup so) - { - if (!so.IsAttachment) - return; - - if (so.Scene.UserManagementModule.IsLocalGridUser(so.AttachedAvatar)) - return; - - // foreign user - AgentCircuitData aCircuit = so.Scene.AuthenticateHandler.GetAgentCircuitData(so.AttachedAvatar); - if (aCircuit != null && (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaHGLogin) != 0) - { - if (aCircuit.ServiceURLs != null && aCircuit.ServiceURLs.ContainsKey("AssetServerURI")) - { - string url = aCircuit.ServiceURLs["AssetServerURI"].ToString(); - m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Incoming attachement {0} for HG user {1} with asset server {2}", so.Name, so.AttachedAvatar, url); - Dictionary ids = new Dictionary(); - HGUuidGatherer uuidGatherer = new HGUuidGatherer(so.Scene.AssetService, url); - uuidGatherer.GatherAssetUuids(so, ids); - - foreach (KeyValuePair kvp in ids) - uuidGatherer.FetchAsset(kvp.Key); - } - } } protected override void OnNewClient(IClientAPI client) @@ -212,7 +120,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer int flags = Scene.GridService.GetRegionFlags(Scene.RegionInfo.ScopeID, region.RegionID); m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: region {0} flags: {1}", region.RegionID, flags); - if ((flags & (int)OpenSim.Framework.RegionFlags.Hyperlink) != 0) + if ((flags & (int)OpenSim.Data.RegionFlags.Hyperlink) != 0) { m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Destination region {0} is hyperlink", region.RegionID); GridRegion real_destination = m_GatekeeperConnector.GetHyperlinkRegion(region, region.RegionID); @@ -232,7 +140,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer return true; int flags = Scene.GridService.GetRegionFlags(Scene.RegionInfo.ScopeID, reg.RegionID); - if (flags == -1 /* no region in DB */ || (flags & (int)OpenSim.Framework.RegionFlags.Hyperlink) != 0) + if (flags == -1 /* no region in DB */ || (flags & (int)OpenSim.Data.RegionFlags.Hyperlink) != 0) return true; return false; @@ -245,8 +153,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer { // Log them out of this grid Scene.PresenceService.LogoutAgent(sp.ControllingClient.SessionId); - string userId = Scene.UserManagementModule.GetUserUUI(sp.UUID); - Scene.GridUserService.LoggedOut(userId, UUID.Zero, Scene.RegionInfo.RegionID, sp.AbsolutePosition, sp.Lookat); } } @@ -256,11 +162,11 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer reason = string.Empty; logout = false; int flags = Scene.GridService.GetRegionFlags(Scene.RegionInfo.ScopeID, reg.RegionID); - if (flags == -1 /* no region in DB */ || (flags & (int)OpenSim.Framework.RegionFlags.Hyperlink) != 0) + if (flags == -1 /* no region in DB */ || (flags & (int)OpenSim.Data.RegionFlags.Hyperlink) != 0) { // this user is going to another grid - // for local users, check if HyperGrid teleport is allowed, based on user level - if (Scene.UserManagementModule.IsLocalGridUser(sp.UUID) && sp.UserLevel < m_levelHGTeleport) + // check if HyperGrid teleport is allowed, based on user level + if (sp.UserLevel < m_levelHGTeleport) { m_log.WarnFormat("[HG ENTITY TRANSFER MODULE]: Unable to HG teleport agent due to insufficient UserLevel."); reason = "Hypergrid teleport not allowed"; @@ -294,124 +200,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer TeleportHome(id, client); } - protected override bool ValidateGenericConditions(ScenePresence sp, GridRegion reg, GridRegion finalDestination, uint teleportFlags, out string reason) - { - reason = "Please wear your grid's allowed appearance before teleporting to another grid"; - if (!m_RestrictAppearanceAbroad) - return true; - - // The rest is only needed for controlling appearance - - int flags = Scene.GridService.GetRegionFlags(Scene.RegionInfo.ScopeID, reg.RegionID); - if (flags == -1 /* no region in DB */ || (flags & (int)OpenSim.Framework.RegionFlags.Hyperlink) != 0) - { - // this user is going to another grid - if (Scene.UserManagementModule.IsLocalGridUser(sp.UUID)) - { - m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: RestrictAppearanceAbroad is ON. Checking generic appearance"); - - // Check wearables - for (int i = 0; i < AvatarWearable.MAX_WEARABLES; i++) - { - for (int j = 0; j < sp.Appearance.Wearables[i].Count; j++) - { - if (sp.Appearance.Wearables[i] == null) - continue; - - bool found = false; - foreach (AvatarAppearance a in ExportedAppearance) - if (a.Wearables[i] != null) - { - found = true; - break; - } - - if (!found) - { - m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Wearable not allowed to go outside {0}", i); - return false; - } - - found = false; - foreach (AvatarAppearance a in ExportedAppearance) - if (sp.Appearance.Wearables[i][j].AssetID == a.Wearables[i][j].AssetID) - { - found = true; - break; - } - - if (!found) - { - m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Wearable not allowed to go outside {0}", i); - return false; - } - } - } - - // Check attachments - foreach (AvatarAttachment att in sp.Appearance.GetAttachments()) - { - bool found = false; - foreach (AvatarAttachment att2 in m_Attachs) - { - if (att2.AssetID == att.AssetID) - { - found = true; - break; - } - } - if (!found) - { - m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Attachment not allowed to go outside {0}", att.AttachPoint); - return false; - } - } - } - } - - reason = string.Empty; - return true; - } - - - //protected override bool UpdateAgent(GridRegion reg, GridRegion finalDestination, AgentData agentData, ScenePresence sp) - //{ - // int flags = Scene.GridService.GetRegionFlags(Scene.RegionInfo.ScopeID, reg.RegionID); - // if (flags == -1 /* no region in DB */ || (flags & (int)OpenSim.Data.RegionFlags.Hyperlink) != 0) - // { - // // this user is going to another grid - // if (m_RestrictAppearanceAbroad && Scene.UserManagementModule.IsLocalGridUser(agentData.AgentID)) - // { - // // We need to strip the agent off its appearance - // m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: RestrictAppearanceAbroad is ON. Sending generic appearance"); - - // // Delete existing npc attachments - // Scene.AttachmentsModule.DeleteAttachmentsFromScene(sp, false); - - // // XXX: We can't just use IAvatarFactoryModule.SetAppearance() yet since it doesn't transfer attachments - // AvatarAppearance newAppearance = new AvatarAppearance(ExportedAppearance, true); - // sp.Appearance = newAppearance; - - // // Rez needed npc attachments - // Scene.AttachmentsModule.RezAttachments(sp); - - - // IAvatarFactoryModule module = Scene.RequestModuleInterface(); - // //module.SendAppearance(sp.UUID); - // module.RequestRebake(sp, false); - - // Scene.AttachmentsModule.CopyAttachments(sp, agentData); - // agentData.Appearance = sp.Appearance; - // } - // } - - // foreach (AvatarAttachment a in agentData.Appearance.GetAttachments()) - // m_log.DebugFormat("[XXX]: {0}-{1}", a.ItemID, a.AssetID); - - - // return base.UpdateAgent(reg, finalDestination, agentData, sp); - //} - public override bool TeleportHome(UUID id, IClientAPI client) { m_log.DebugFormat( @@ -587,4 +375,4 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer return region; } } -} +} \ No newline at end of file diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs index f8ec6de..eaadc1b 100644 --- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs +++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs @@ -71,19 +71,19 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess #region Internal functions - public AssetMetadata FetchMetadata(string url, UUID assetID) + public AssetBase FetchAsset(string url, UUID assetID) { if (!url.EndsWith("/") && !url.EndsWith("=")) url = url + "/"; - AssetMetadata meta = m_scene.AssetService.GetMetadata(url + assetID.ToString()); + AssetBase asset = m_scene.AssetService.Get(url + assetID.ToString()); - if (meta != null) - m_log.DebugFormat("[HG ASSET MAPPER]: Fetched metadata for asset {0} of type {1} from {2} ", assetID, meta.Type, url); - else - m_log.DebugFormat("[HG ASSET MAPPER]: Unable to fetched metadata for asset {0} from {1} ", assetID, url); - - return meta; + if (asset != null) + { + m_log.DebugFormat("[HG ASSET MAPPER]: Copied asset {0} from {1} to local asset server. ", asset.ID, url); + return asset; + } + return null; } public bool PostAsset(string url, AssetBase asset) @@ -93,7 +93,6 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess if (!url.EndsWith("/") && !url.EndsWith("=")) url = url + "/"; - bool success = true; // See long comment in AssetCache.AddAsset if (!asset.Temporary || asset.Local) { @@ -104,7 +103,14 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess // not having a global naming infrastructure AssetBase asset1 = new AssetBase(asset.FullID, asset.Name, asset.Type, asset.Metadata.CreatorID); Copy(asset, asset1); - asset1.ID = url + asset.ID; + try + { + asset1.ID = url + asset.ID; + } + catch + { + m_log.Warn("[HG ASSET MAPPER]: Oops."); + } AdjustIdentifiers(asset1.Metadata); if (asset1.Metadata.Type == (sbyte)AssetType.Object) @@ -112,17 +118,11 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess else asset1.Data = asset.Data; - string id = m_scene.AssetService.Store(asset1); - if (id == string.Empty) - { - m_log.DebugFormat("[HG ASSET MAPPER]: Asset server {0} did not accept {1}", url, asset.ID); - success = false; - } - else - m_log.DebugFormat("[HG ASSET MAPPER]: Posted copy of asset {0} from local asset server to {1}", asset1.ID, url); + m_scene.AssetService.Store(asset1); + m_log.DebugFormat("[HG ASSET MAPPER]: Posted copy of asset {0} from local asset server to {1}", asset1.ID, url); } - return success; - } + return true; + } else m_log.Warn("[HG ASSET MAPPER]: Tried to post asset to remote server, but asset not in local cache."); @@ -222,17 +222,28 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess public void Get(UUID assetID, UUID ownerID, string userAssetURL) { - // Get the item from the remote asset server onto the local AssetService + // Get the item from the remote asset server onto the local AssetCache + // and place an entry in m_assetMap + + m_log.Debug("[HG ASSET MAPPER]: Fetching object " + assetID + " from asset server " + userAssetURL); + AssetBase asset = FetchAsset(userAssetURL, assetID); - AssetMetadata meta = FetchMetadata(userAssetURL, assetID); - if (meta == null) - return; + if (asset != null) + { + // OK, now fetch the inside. + Dictionary ids = new Dictionary(); + HGUuidGatherer uuidGatherer = new HGUuidGatherer(this, m_scene.AssetService, userAssetURL); + uuidGatherer.GatherAssetUuids(asset.FullID, (AssetType)asset.Type, ids); + if (ids.ContainsKey(assetID)) + ids.Remove(assetID); + foreach (UUID uuid in ids.Keys) + FetchAsset(userAssetURL, uuid); - // The act of gathering UUIDs downloads the assets from the remote server - Dictionary ids = new Dictionary(); - HGUuidGatherer uuidGatherer = new HGUuidGatherer(m_scene.AssetService, userAssetURL); - uuidGatherer.GatherAssetUuids(assetID, (AssetType)meta.Type, ids); + m_log.DebugFormat("[HG ASSET MAPPER]: Successfully fetched asset {0} from asset server {1}", asset.ID, userAssetURL); + } + else + m_log.Warn("[HG ASSET MAPPER]: Could not fetch asset from remote asset server " + userAssetURL); } @@ -246,23 +257,19 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess if (asset != null) { Dictionary ids = new Dictionary(); - HGUuidGatherer uuidGatherer = new HGUuidGatherer(m_scene.AssetService, string.Empty); + HGUuidGatherer uuidGatherer = new HGUuidGatherer(this, m_scene.AssetService, string.Empty); uuidGatherer.GatherAssetUuids(asset.FullID, (AssetType)asset.Type, ids); - bool success = false; foreach (UUID uuid in ids.Keys) { asset = m_scene.AssetService.Get(uuid.ToString()); if (asset == null) m_log.DebugFormat("[HG ASSET MAPPER]: Could not find asset {0}", uuid); else - success = PostAsset(userAssetURL, asset); + PostAsset(userAssetURL, asset); } - // maybe all pieces got there... - if (!success) - m_log.DebugFormat("[HG ASSET MAPPER]: Problems posting item {0} to asset server {1}", assetID, userAssetURL); - else - m_log.DebugFormat("[HG ASSET MAPPER]: Successfully posted item {0} to asset server {1}", assetID, userAssetURL); + // maybe all pieces got there... + m_log.DebugFormat("[HG ASSET MAPPER]: Successfully posted item {0} to asset server {1}", assetID, userAssetURL); } else diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs index 6bb758e..cf72b58 100644 --- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs +++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs @@ -92,7 +92,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess m_HomeURI = thisModuleConfig.GetString("HomeURI", m_HomeURI); m_OutboundPermission = thisModuleConfig.GetBoolean("OutboundPermission", true); m_ThisGatekeeper = thisModuleConfig.GetString("Gatekeeper", string.Empty); - m_RestrictInventoryAccessAbroad = thisModuleConfig.GetBoolean("RestrictInventoryAccessAbroad", true); + m_RestrictInventoryAccessAbroad = thisModuleConfig.GetBoolean("RestrictInventoryAccessAbroad", false); } else m_log.Warn("[HG INVENTORY ACCESS MODULE]: HGInventoryAccessModule configs not found. ProfileServerURI not set!"); @@ -263,13 +263,8 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess //} // OK, we're done fetching. Pass it up to the default RezObject - SceneObjectGroup sog = base.RezObject(remoteClient, itemID, RayEnd, RayStart, RayTargetID, BypassRayCast, RayEndIsIntersection, - RezSelected, RemoveItem, fromTaskID, attachment); - - if (sog == null) - remoteClient.SendAgentAlertMessage("Unable to rez: problem accessing inventory or locating assets", false); - - return sog; + return base.RezObject(remoteClient, itemID, RayEnd, RayStart, RayTargetID, BypassRayCast, RayEndIsIntersection, + RezSelected, RemoveItem, fromTaskID, attachment); } @@ -313,8 +308,6 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess protected override InventoryItemBase GetItem(UUID agentID, UUID itemID) { InventoryItemBase item = base.GetItem(agentID, itemID); - if (item == null) - return null; string userAssetServer = string.Empty; if (IsForeignUser(agentID, out userAssetServer)) @@ -351,7 +344,6 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess private void ProcessInventoryForArriving(IClientAPI client) { - // No-op for now, but we may need to do something for freign users inventory } // @@ -398,7 +390,6 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess private void ProcessInventoryForLeaving(IClientAPI client) { - // No-op for now } #endregion diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGUuidGatherer.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGUuidGatherer.cs new file mode 100644 index 0000000..fcb544f --- /dev/null +++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGUuidGatherer.cs @@ -0,0 +1,57 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections.Generic; + +using OpenSim.Framework; +using OpenSim.Region.Framework.Scenes; +using OpenSim.Services.Interfaces; +using OpenMetaverse; + +namespace OpenSim.Region.CoreModules.Framework.InventoryAccess +{ + public class HGUuidGatherer : UuidGatherer + { + protected string m_assetServerURL; + protected HGAssetMapper m_assetMapper; + + public HGUuidGatherer(HGAssetMapper assMap, IAssetService assetCache, string assetServerURL) : base(assetCache) + { + m_assetMapper = assMap; + m_assetServerURL = assetServerURL; + } + + protected override AssetBase GetAsset(UUID uuid) + { + if (string.Empty == m_assetServerURL) + return m_assetCache.Get(uuid.ToString()); + else + return m_assetMapper.FetchAsset(m_assetServerURL, uuid); + } + } +} diff --git a/OpenSim/Region/CoreModules/Framework/Monitoring/MonitorModule.cs b/OpenSim/Region/CoreModules/Framework/Monitoring/MonitorModule.cs index e411585..e135c21 100644 --- a/OpenSim/Region/CoreModules/Framework/Monitoring/MonitorModule.cs +++ b/OpenSim/Region/CoreModules/Framework/Monitoring/MonitorModule.cs @@ -95,14 +95,14 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring { foreach (IMonitor monitor in m_staticMonitors) { - MainConsole.Instance.OutputFormat( + m_log.InfoFormat( "[MONITOR MODULE]: {0} reports {1} = {2}", m_scene.RegionInfo.RegionName, monitor.GetFriendlyName(), monitor.GetFriendlyValue()); } foreach (KeyValuePair tuple in m_scene.StatsReporter.GetExtraSimStats()) { - MainConsole.Instance.OutputFormat( + m_log.InfoFormat( "[MONITOR MODULE]: {0} reports {1} = {2}", m_scene.RegionInfo.RegionName, tuple.Key, tuple.Value); } diff --git a/OpenSim/Region/CoreModules/Framework/Statistics/Logging/LogWriter.cs b/OpenSim/Region/CoreModules/Framework/Statistics/Logging/LogWriter.cs index fd8d5e3..65e4c90 100755 --- a/OpenSim/Region/CoreModules/Framework/Statistics/Logging/LogWriter.cs +++ b/OpenSim/Region/CoreModules/Framework/Statistics/Logging/LogWriter.cs @@ -1,170 +1,161 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.IO; -using System.Text; -using log4net; - -namespace OpenSim.Region.CoreModules.Framework.Statistics.Logging -{ - /// - /// Class for writing a high performance, high volume log file. - /// Sometimes, to debug, one has a high volume logging to do and the regular - /// log file output is not appropriate. - /// Create a new instance with the parameters needed and - /// call Write() to output a line. Call Close() when finished. - /// If created with no parameters, it will not log anything. - /// - public class LogWriter : IDisposable - { - public bool Enabled { get; private set; } - - private string m_logDirectory = "."; - private int m_logMaxFileTimeMin = 5; // 5 minutes - public String LogFileHeader { get; set; } - - private StreamWriter m_logFile = null; - private TimeSpan m_logFileLife; - private DateTime m_logFileEndTime; - private Object m_logFileWriteLock = new Object(); - - // set externally when debugging. If let 'null', this does not write any error messages. - public ILog ErrorLogger = null; - private string LogHeader = "[LOG WRITER]"; - - /// - /// Create a log writer that will not write anything. Good for when not enabled - /// but the write statements are still in the code. - /// - public LogWriter() - { - Enabled = false; - m_logFile = null; - } - - /// - /// Create a log writer instance. - /// - /// The directory to create the log file in. May be 'null' for default. - /// The characters that begin the log file name. May be 'null' for default. - /// Maximum age of a log file in minutes. If zero, will set default. - public LogWriter(string dir, string headr, int maxFileTime) - { - m_logDirectory = dir == null ? "." : dir; - - LogFileHeader = headr == null ? "log-" : headr; - - m_logMaxFileTimeMin = maxFileTime; - if (m_logMaxFileTimeMin < 1) - m_logMaxFileTimeMin = 5; - - m_logFileLife = new TimeSpan(0, m_logMaxFileTimeMin, 0); - m_logFileEndTime = DateTime.Now + m_logFileLife; - - Enabled = true; - } - - public void Dispose() - { - this.Close(); - } - - public void Close() - { - Enabled = false; - if (m_logFile != null) - { - m_logFile.Close(); - m_logFile.Dispose(); - m_logFile = null; - } - } - - public void Write(string line, params object[] args) - { - if (!Enabled) return; - Write(String.Format(line, args)); - } - - public void Flush() - { - if (!Enabled) return; - if (m_logFile != null) - { - m_logFile.Flush(); - } - } - - public void Write(string line) - { - if (!Enabled) return; - try - { - lock (m_logFileWriteLock) - { - DateTime now = DateTime.Now; - if (m_logFile == null || now > m_logFileEndTime) - { - if (m_logFile != null) - { - m_logFile.Close(); - m_logFile.Dispose(); - m_logFile = null; - } - - // First log file or time has expired, start writing to a new log file - m_logFileEndTime = now + m_logFileLife; - string path = (m_logDirectory.Length > 0 ? m_logDirectory - + System.IO.Path.DirectorySeparatorChar.ToString() : "") - + String.Format("{0}{1}.log", LogFileHeader, now.ToString("yyyyMMddHHmmss")); - m_logFile = new StreamWriter(File.Open(path, FileMode.Append, FileAccess.Write)); - } - if (m_logFile != null) - { - StringBuilder buff = new StringBuilder(line.Length + 25); - buff.Append(now.ToString("yyyyMMddHHmmssfff")); - // buff.Append(now.ToString("yyyyMMddHHmmss")); - buff.Append(","); - buff.Append(line); - buff.Append("\r\n"); - m_logFile.Write(buff.ToString()); - } - } - } - catch (Exception e) - { - if (ErrorLogger != null) - { - ErrorLogger.ErrorFormat("{0}: FAILURE WRITING TO LOGFILE: {1}", LogHeader, e); - } - Enabled = false; - } - return; - } - } -} +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.IO; +using System.Text; +using log4net; + +namespace OpenSim.Region.CoreModules.Framework.Statistics.Logging +{ + /// + /// Class for writing a high performance, high volume log file. + /// Sometimes, to debug, one has a high volume logging to do and the regular + /// log file output is not appropriate. + /// Create a new instance with the parameters needed and + /// call Write() to output a line. Call Close() when finished. + /// If created with no parameters, it will not log anything. + /// + public class LogWriter : IDisposable + { + public bool Enabled { get; private set; } + + private string m_logDirectory = "."; + private int m_logMaxFileTimeMin = 5; // 5 minutes + public String LogFileHeader { get; set; } + + private StreamWriter m_logFile = null; + private TimeSpan m_logFileLife; + private DateTime m_logFileEndTime; + private Object m_logFileWriteLock = new Object(); + + // set externally when debugging. If let 'null', this does not write any error messages. + public ILog ErrorLogger = null; + private string LogHeader = "[LOG WRITER]"; + + /// + /// Create a log writer that will not write anything. Good for when not enabled + /// but the write statements are still in the code. + /// + public LogWriter() + { + Enabled = false; + m_logFile = null; + } + + /// + /// Create a log writer instance. + /// + /// The directory to create the log file in. May be 'null' for default. + /// The characters that begin the log file name. May be 'null' for default. + /// Maximum age of a log file in minutes. If zero, will set default. + public LogWriter(string dir, string headr, int maxFileTime) + { + m_logDirectory = dir == null ? "." : dir; + + LogFileHeader = headr == null ? "log-" : headr; + + m_logMaxFileTimeMin = maxFileTime; + if (m_logMaxFileTimeMin < 1) + m_logMaxFileTimeMin = 5; + + m_logFileLife = new TimeSpan(0, m_logMaxFileTimeMin, 0); + m_logFileEndTime = DateTime.Now + m_logFileLife; + + Enabled = true; + } + + public void Dispose() + { + this.Close(); + } + + public void Close() + { + Enabled = false; + if (m_logFile != null) + { + m_logFile.Close(); + m_logFile.Dispose(); + m_logFile = null; + } + } + + public void Write(string line, params object[] args) + { + if (!Enabled) return; + Write(String.Format(line, args)); + } + + public void Write(string line) + { + if (!Enabled) return; + try + { + lock (m_logFileWriteLock) + { + DateTime now = DateTime.Now; + if (m_logFile == null || now > m_logFileEndTime) + { + if (m_logFile != null) + { + m_logFile.Close(); + m_logFile.Dispose(); + m_logFile = null; + } + + // First log file or time has expired, start writing to a new log file + m_logFileEndTime = now + m_logFileLife; + string path = (m_logDirectory.Length > 0 ? m_logDirectory + + System.IO.Path.DirectorySeparatorChar.ToString() : "") + + String.Format("{0}{1}.log", LogFileHeader, now.ToString("yyyyMMddHHmmss")); + m_logFile = new StreamWriter(File.Open(path, FileMode.Append, FileAccess.Write)); + } + if (m_logFile != null) + { + StringBuilder buff = new StringBuilder(line.Length + 25); + buff.Append(now.ToString("yyyyMMddHHmmssfff")); + // buff.Append(now.ToString("yyyyMMddHHmmss")); + buff.Append(","); + buff.Append(line); + buff.Append("\r\n"); + m_logFile.Write(buff.ToString()); + } + } + } + catch (Exception e) + { + if (ErrorLogger != null) + { + ErrorLogger.ErrorFormat("{0}: FAILURE WRITING TO LOGFILE: {1}", LogHeader, e); + } + Enabled = false; + } + return; + } + } +} \ No newline at end of file diff --git a/OpenSim/Region/CoreModules/Framework/UserManagement/HGUserManagementModule.cs b/OpenSim/Region/CoreModules/Framework/UserManagement/HGUserManagementModule.cs index acefc97..4eecaa2 100644 --- a/OpenSim/Region/CoreModules/Framework/UserManagement/HGUserManagementModule.cs +++ b/OpenSim/Region/CoreModules/Framework/UserManagement/HGUserManagementModule.cs @@ -137,9 +137,6 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement ud.FirstName = words[0]; ud.LastName = "@" + words[1]; users.Add(ud); - // WARNING! that uriStr is not quite right... it may be missing the / at the end, - // which will cause trouble (duplicate entries on some tables). We should - // get the UUI instead from the UAS. TO BE FIXED. AddUser(userID, names[0], names[1], uriStr); m_log.DebugFormat("[USER MANAGEMENT MODULE]: User {0}@{1} found", words[0], words[1]); } diff --git a/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs b/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs index b4811da..f4ed67b 100644 --- a/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs +++ b/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs @@ -31,7 +31,6 @@ using System.Reflection; using OpenSim.Framework; using OpenSim.Framework.Console; -using OpenSim.Region.ClientStack.LindenUDP; using OpenSim.Region.Framework; using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Scenes; @@ -430,7 +429,8 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement public void AddUser(UUID uuid, string first, string last, string homeURL) { - //m_log.DebugFormat("[USER MANAGEMENT MODULE]: Adding user with id {0}, first {1}, last {2}, url {3}", uuid, first, last, homeURL); + // m_log.DebugFormat("[USER MANAGEMENT MODULE]: Adding user with id {0}, first {1}, last {2}, url {3}", uuid, first, last, homeURL); + AddUser(uuid, homeURL + ";" + first + " " + last); } @@ -553,8 +553,8 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement MainConsole.Instance.Output("-----------------------------------------------------------------------------"); foreach (KeyValuePair kvp in m_UserCache) { - MainConsole.Instance.Output(String.Format("{0} {1} {2} ({3})", - kvp.Key, kvp.Value.FirstName, kvp.Value.LastName, kvp.Value.HomeURL)); + MainConsole.Instance.Output(String.Format("{0} {1} {2}", + kvp.Key, kvp.Value.FirstName, kvp.Value.LastName)); } return; diff --git a/OpenSim/Region/CoreModules/Resources/CoreModulePlugin.addin.xml b/OpenSim/Region/CoreModules/Resources/CoreModulePlugin.addin.xml index 6c73d91..424e0ab 100644 --- a/OpenSim/Region/CoreModules/Resources/CoreModulePlugin.addin.xml +++ b/OpenSim/Region/CoreModules/Resources/CoreModulePlugin.addin.xml @@ -15,7 +15,6 @@ - diff --git a/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTexture.cs b/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTexture.cs deleted file mode 100644 index fce9490..0000000 --- a/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTexture.cs +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Drawing; -using OpenSim.Region.Framework.Interfaces; - -namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture -{ - public class DynamicTexture : IDynamicTexture - { - public string InputCommands { get; private set; } - public Uri InputUri { get; private set; } - public string InputParams { get; private set; } - public byte[] Data { get; private set; } - public Size Size { get; private set; } - public bool IsReuseable { get; private set; } - - public DynamicTexture(string inputCommands, string inputParams, byte[] data, Size size, bool isReuseable) - { - InputCommands = inputCommands; - InputParams = inputParams; - Data = data; - Size = size; - IsReuseable = isReuseable; - } - - public DynamicTexture(Uri inputUri, string inputParams, byte[] data, Size size, bool isReuseable) - { - InputUri = inputUri; - InputParams = inputParams; - Data = data; - Size = size; - IsReuseable = isReuseable; - } - } -} \ No newline at end of file diff --git a/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs b/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs index 93a045e..18bd018 100644 --- a/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs +++ b/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs @@ -42,29 +42,13 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture { public class DynamicTextureModule : IRegionModule, IDynamicTextureManager { -// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + //private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private const int ALL_SIDES = -1; public const int DISP_EXPIRE = 1; public const int DISP_TEMP = 2; - /// - /// If true then where possible dynamic textures are reused. - /// - public bool ReuseTextures { get; set; } - - /// - /// If false, then textures which have a low data size are not reused when ReuseTextures = true. - /// - /// - /// LL viewers 3.3.4 and before appear to not fully render textures pulled from the viewer cache if those - /// textures have a relatively high pixel surface but a small data size. Typically, this appears to happen - /// if the data size is smaller than the viewer's discard level 2 size estimate. So if this is setting is - /// false, textures smaller than the calculation in IsSizeReuseable are always regenerated rather than reused - /// to work around this problem. - public bool ReuseLowDataTextures { get; set; } - private Dictionary RegisteredScenes = new Dictionary(); private Dictionary RenderPlugins = @@ -72,15 +56,6 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture private Dictionary Updaters = new Dictionary(); - /// - /// Record dynamic textures that we can reuse for a given data and parameter combination rather than - /// regenerate. - /// - /// - /// Key is string.Format("{0}{1}", data - /// - private Cache m_reuseableDynamicTextures; - #region IDynamicTextureManager Members public void RegisterRender(string handleType, IDynamicTextureRender render) @@ -94,17 +69,17 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture /// /// Called by code which actually renders the dynamic texture to supply texture data. /// - /// - /// - public void ReturnData(UUID updaterId, IDynamicTexture texture) + /// + /// + public void ReturnData(UUID id, byte[] data) { DynamicTextureUpdater updater = null; lock (Updaters) { - if (Updaters.ContainsKey(updaterId)) + if (Updaters.ContainsKey(id)) { - updater = Updaters[updaterId]; + updater = Updaters[id]; } } @@ -113,16 +88,7 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture if (RegisteredScenes.ContainsKey(updater.SimUUID)) { Scene scene = RegisteredScenes[updater.SimUUID]; - UUID newTextureID = updater.DataReceived(texture.Data, scene); - - if (ReuseTextures - && !updater.BlendWithOldTexture - && texture.IsReuseable - && (ReuseLowDataTextures || IsDataSizeReuseable(texture))) - { - m_reuseableDynamicTextures.Store( - GenerateReusableTextureKey(texture.InputCommands, texture.InputParams), newTextureID); - } + updater.DataReceived(data, scene); } } @@ -138,27 +104,6 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture } } - /// - /// Determines whether the texture is reuseable based on its data size. - /// - /// - /// This is a workaround for a viewer bug where very small data size textures relative to their pixel size - /// are not redisplayed properly when pulled from cache. The calculation here is based on the typical discard - /// level of 2, a 'rate' of 0.125 and 4 components (which makes for a factor of 0.5). - /// - /// - private bool IsDataSizeReuseable(IDynamicTexture texture) - { -// Console.WriteLine("{0} {1}", texture.Size.Width, texture.Size.Height); - int discardLevel2DataThreshold = (int)Math.Ceiling((texture.Size.Width >> 2) * (texture.Size.Height >> 2) * 0.5); - -// m_log.DebugFormat( -// "[DYNAMIC TEXTURE MODULE]: Discard level 2 threshold {0}, texture data length {1}", -// discardLevel2DataThreshold, texture.Data.Length); - - return discardLevel2DataThreshold < texture.Data.Length; - } - public UUID AddDynamicTextureURL(UUID simID, UUID primID, string contentType, string url, string extraParams, int updateTimer) { @@ -222,61 +167,22 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture public UUID AddDynamicTextureData(UUID simID, UUID primID, string contentType, string data, string extraParams, int updateTimer, bool SetBlending, int disp, byte AlphaValue, int face) { - if (!RenderPlugins.ContainsKey(contentType)) - return UUID.Zero; - - Scene scene; - RegisteredScenes.TryGetValue(simID, out scene); - - if (scene == null) - return UUID.Zero; - - SceneObjectPart part = scene.GetSceneObjectPart(primID); - - if (part == null) - return UUID.Zero; - - // If we want to reuse dynamic textures then we have to ignore any request from the caller to expire - // them. - if (ReuseTextures) - disp = disp & ~DISP_EXPIRE; - - DynamicTextureUpdater updater = new DynamicTextureUpdater(); - updater.SimUUID = simID; - updater.PrimID = primID; - updater.ContentType = contentType; - updater.BodyData = data; - updater.UpdateTimer = updateTimer; - updater.UpdaterID = UUID.Random(); - updater.Params = extraParams; - updater.BlendWithOldTexture = SetBlending; - updater.FrontAlpha = AlphaValue; - updater.Face = face; - updater.Url = "Local image"; - updater.Disp = disp; - - object objReusableTextureUUID = null; - - if (ReuseTextures && !updater.BlendWithOldTexture) + if (RenderPlugins.ContainsKey(contentType)) { - string reuseableTextureKey = GenerateReusableTextureKey(data, extraParams); - objReusableTextureUUID = m_reuseableDynamicTextures.Get(reuseableTextureKey); - - if (objReusableTextureUUID != null) - { - // If something else has removed this temporary asset from the cache, detect and invalidate - // our cached uuid. - if (scene.AssetService.GetMetadata(objReusableTextureUUID.ToString()) == null) - { - m_reuseableDynamicTextures.Invalidate(reuseableTextureKey); - objReusableTextureUUID = null; - } - } - } + DynamicTextureUpdater updater = new DynamicTextureUpdater(); + updater.SimUUID = simID; + updater.PrimID = primID; + updater.ContentType = contentType; + updater.BodyData = data; + updater.UpdateTimer = updateTimer; + updater.UpdaterID = UUID.Random(); + updater.Params = extraParams; + updater.BlendWithOldTexture = SetBlending; + updater.FrontAlpha = AlphaValue; + updater.Face = face; + updater.Url = "Local image"; + updater.Disp = disp; - // We cannot reuse a dynamic texture if the data is going to be blended with something already there. - if (objReusableTextureUUID == null) - { lock (Updaters) { if (!Updaters.ContainsKey(updater.UpdaterID)) @@ -285,29 +191,11 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture } } -// m_log.DebugFormat( -// "[DYNAMIC TEXTURE MODULE]: Requesting generation of new dynamic texture for {0} in {1}", -// part.Name, part.ParentGroup.Scene.Name); - RenderPlugins[contentType].AsyncConvertData(updater.UpdaterID, data, extraParams); + return updater.UpdaterID; } - else - { -// m_log.DebugFormat( -// "[DYNAMIC TEXTURE MODULE]: Reusing cached texture {0} for {1} in {2}", -// objReusableTextureUUID, part.Name, part.ParentGroup.Scene.Name); - - // No need to add to updaters as the texture is always the same. Not that this functionality - // apppears to be implemented anyway. - updater.UpdatePart(part, (UUID)objReusableTextureUUID); - } - - return updater.UpdaterID; - } - - private string GenerateReusableTextureKey(string data, string extraParams) - { - return string.Format("{0}{1}", data, extraParams); + + return UUID.Zero; } public void GetDrawStringSize(string contentType, string text, string fontName, int fontSize, @@ -327,13 +215,6 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture public void Initialise(Scene scene, IConfigSource config) { - IConfig texturesConfig = config.Configs["Textures"]; - if (texturesConfig != null) - { - ReuseTextures = texturesConfig.GetBoolean("ReuseDynamicTextures", false); - ReuseLowDataTextures = texturesConfig.GetBoolean("ReuseDynamicLowDataTextures", false); - } - if (!RegisteredScenes.ContainsKey(scene.RegionInfo.RegionID)) { RegisteredScenes.Add(scene.RegionInfo.RegionID, scene); @@ -343,11 +224,6 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture public void PostInitialise() { - if (ReuseTextures) - { - m_reuseableDynamicTextures = new Cache(CacheMedium.Memory, CacheStrategy.Conservative); - m_reuseableDynamicTextures.DefaultTTL = new TimeSpan(24, 0, 0); - } } public void Close() @@ -393,60 +269,9 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture } /// - /// Update the given part with the new texture. - /// - /// - /// The old texture UUID. - /// - public UUID UpdatePart(SceneObjectPart part, UUID textureID) - { - UUID oldID; - - lock (part) - { - // mostly keep the values from before - Primitive.TextureEntry tmptex = part.Shape.Textures; - - // FIXME: Need to return the appropriate ID if only a single face is replaced. - oldID = tmptex.DefaultTexture.TextureID; - - if (Face == ALL_SIDES) - { - oldID = tmptex.DefaultTexture.TextureID; - tmptex.DefaultTexture.TextureID = textureID; - } - else - { - try - { - Primitive.TextureEntryFace texface = tmptex.CreateFace((uint)Face); - texface.TextureID = textureID; - tmptex.FaceTextures[Face] = texface; - } - catch (Exception) - { - tmptex.DefaultTexture.TextureID = textureID; - } - } - - // I'm pretty sure we always want to force this to true - // I'm pretty sure noone whats to set fullbright true if it wasn't true before. - // tmptex.DefaultTexture.Fullbright = true; - - part.UpdateTextureEntry(tmptex.GetBytes()); - } - - return oldID; - } - - /// /// Called once new texture data has been received for this updater. /// - /// - /// - /// True if the data given is reuseable. - /// The asset UUID given to the incoming data. - public UUID DataReceived(byte[] data, Scene scene) + public void DataReceived(byte[] data, Scene scene) { SceneObjectPart part = scene.GetSceneObjectPart(PrimID); @@ -456,8 +281,7 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture String.Format("DynamicTextureModule: Error preparing image using URL {0}", Url); scene.SimChat(Utils.StringToBytes(msg), ChatTypeEnum.Say, 0, part.ParentGroup.RootPart.AbsolutePosition, part.Name, part.UUID, false); - - return UUID.Zero; + return; } byte[] assetData = null; @@ -495,29 +319,56 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture IJ2KDecoder cacheLayerDecode = scene.RequestModuleInterface(); if (cacheLayerDecode != null) { - if (!cacheLayerDecode.Decode(asset.FullID, asset.Data)) - m_log.WarnFormat( - "[DYNAMIC TEXTURE MODULE]: Decoding of dynamically generated asset {0} for {1} in {2} failed", - asset.ID, part.Name, part.ParentGroup.Scene.Name); + cacheLayerDecode.Decode(asset.FullID, asset.Data); + cacheLayerDecode = null; } - UUID oldID = UpdatePart(part, asset.FullID); + UUID oldID = UUID.Zero; - if (oldID != UUID.Zero && ((Disp & DISP_EXPIRE) != 0)) + lock (part) { - if (oldAsset == null) - oldAsset = scene.AssetService.Get(oldID.ToString()); + // mostly keep the values from before + Primitive.TextureEntry tmptex = part.Shape.Textures; + + // remove the old asset from the cache + oldID = tmptex.DefaultTexture.TextureID; + + if (Face == ALL_SIDES) + { + tmptex.DefaultTexture.TextureID = asset.FullID; + } + else + { + try + { + Primitive.TextureEntryFace texface = tmptex.CreateFace((uint)Face); + texface.TextureID = asset.FullID; + tmptex.FaceTextures[Face] = texface; + } + catch (Exception) + { + tmptex.DefaultTexture.TextureID = asset.FullID; + } + } + // I'm pretty sure we always want to force this to true + // I'm pretty sure noone whats to set fullbright true if it wasn't true before. + // tmptex.DefaultTexture.Fullbright = true; + + part.UpdateTextureEntry(tmptex.GetBytes()); + } + + if (oldID != UUID.Zero && ((Disp & DISP_EXPIRE) != 0)) + { + if (oldAsset == null) oldAsset = scene.AssetService.Get(oldID.ToString()); if (oldAsset != null) { - if (oldAsset.Temporary) + if (oldAsset.Temporary == true) { scene.AssetService.Delete(oldID.ToString()); } } } - - return asset.FullID; } private byte[] BlendTextures(byte[] frontImage, byte[] backImage, bool setNewAlpha, byte newAlpha) diff --git a/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs b/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs index 0b9174f..56221aa 100644 --- a/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs +++ b/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs @@ -58,7 +58,6 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp public string body; public int responseCode; public string responseBody; - public string responseType = "text/plain"; //public ManualResetEvent ev; public bool requestDone; public int startTime; @@ -271,22 +270,6 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp } } - public void HttpContentType(UUID request, string type) - { - lock (m_UrlMap) - { - if (m_RequestMap.ContainsKey(request)) - { - UrlData urlData = m_RequestMap[request]; - urlData.requests[request].responseType = type; - } - else - { - m_log.Info("[HttpRequestHandler] There is no http-in request with id " + request.ToString()); - } - } - } - public void HttpResponse(UUID request, int status, string body) { lock (m_RequestMap) diff --git a/OpenSim/Region/CoreModules/Scripting/LoadImageURL/LoadImageURLModule.cs b/OpenSim/Region/CoreModules/Scripting/LoadImageURL/LoadImageURLModule.cs index 45e6527..6f83948 100644 --- a/OpenSim/Region/CoreModules/Scripting/LoadImageURL/LoadImageURLModule.cs +++ b/OpenSim/Region/CoreModules/Scripting/LoadImageURL/LoadImageURLModule.cs @@ -32,7 +32,6 @@ using System.Net; using Nini.Config; using OpenMetaverse; using OpenMetaverse.Imaging; -using OpenSim.Region.CoreModules.Scripting.DynamicTexture; using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Scenes; using log4net; @@ -68,18 +67,12 @@ namespace OpenSim.Region.CoreModules.Scripting.LoadImageURL return true; } -// public bool AlwaysIdenticalConversion(string bodyData, string extraParams) -// { -// // We don't support conversion of body data. -// return false; -// } - - public IDynamicTexture ConvertUrl(string url, string extraParams) + public byte[] ConvertUrl(string url, string extraParams) { return null; } - public IDynamicTexture ConvertData(string bodyData, string extraParams) + public byte[] ConvertStream(Stream data, string extraParams) { return null; } @@ -172,11 +165,11 @@ namespace OpenSim.Region.CoreModules.Scripting.LoadImageURL private void HttpRequestReturn(IAsyncResult result) { + RequestState state = (RequestState) result.AsyncState; WebRequest request = (WebRequest) state.Request; Stream stream = null; byte[] imageJ2000 = new byte[0]; - Size newSize = new Size(0, 0); try { @@ -189,43 +182,37 @@ namespace OpenSim.Region.CoreModules.Scripting.LoadImageURL try { Bitmap image = new Bitmap(stream); + Size newsize; // TODO: make this a bit less hard coded if ((image.Height < 64) && (image.Width < 64)) { - newSize.Width = 32; - newSize.Height = 32; + newsize = new Size(32, 32); } else if ((image.Height < 128) && (image.Width < 128)) { - newSize.Width = 64; - newSize.Height = 64; + newsize = new Size(64, 64); } else if ((image.Height < 256) && (image.Width < 256)) { - newSize.Width = 128; - newSize.Height = 128; + newsize = new Size(128, 128); } else if ((image.Height < 512 && image.Width < 512)) { - newSize.Width = 256; - newSize.Height = 256; + newsize = new Size(256, 256); } else if ((image.Height < 1024 && image.Width < 1024)) { - newSize.Width = 512; - newSize.Height = 512; + newsize = new Size(512, 512); } else { - newSize.Width = 1024; - newSize.Height = 1024; + newsize = new Size(1024, 1024); } - using (Bitmap resize = new Bitmap(image, newSize)) - { - imageJ2000 = OpenJPEG.EncodeFromImage(resize, true); - } + Bitmap resize = new Bitmap(image, newsize); + + imageJ2000 = OpenJPEG.EncodeFromImage(resize, true); } catch (Exception) { @@ -240,6 +227,7 @@ namespace OpenSim.Region.CoreModules.Scripting.LoadImageURL } catch (WebException) { + } finally { @@ -248,14 +236,9 @@ namespace OpenSim.Region.CoreModules.Scripting.LoadImageURL stream.Close(); } } - - m_log.DebugFormat("[LOADIMAGEURLMODULE]: Returning {0} bytes of image data for request {1}", + m_log.DebugFormat("[LOADIMAGEURLMODULE] Returning {0} bytes of image data for request {1}", imageJ2000.Length, state.RequestID); - - m_textureManager.ReturnData( - state.RequestID, - new OpenSim.Region.CoreModules.Scripting.DynamicTexture.DynamicTexture( - request.RequestUri, null, imageJ2000, newSize, false)); + m_textureManager.ReturnData(state.RequestID, imageJ2000); } #region Nested type: RequestState diff --git a/OpenSim/Region/CoreModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs b/OpenSim/Region/CoreModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs deleted file mode 100644 index dc54c3f..0000000 --- a/OpenSim/Region/CoreModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs +++ /dev/null @@ -1,383 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Reflection; -using System.Collections.Generic; -using Nini.Config; -using log4net; -using OpenSim.Framework; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; -using Mono.Addins; -using OpenMetaverse; -using System.Linq; -using System.Linq.Expressions; - -namespace OpenSim.Region.OptionalModules.Scripting.ScriptModuleComms -{ - [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "ScriptModuleCommsModule")] - class ScriptModuleCommsModule : INonSharedRegionModule, IScriptModuleComms - { - private static readonly ILog m_log = - LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - private Dictionary m_constants = new Dictionary(); - -#region ScriptInvocation - protected class ScriptInvocationData - { - public Delegate ScriptInvocationDelegate { get; private set; } - public string FunctionName { get; private set; } - public Type[] TypeSignature { get; private set; } - public Type ReturnType { get; private set; } - - public ScriptInvocationData(string fname, Delegate fn, Type[] callsig, Type returnsig) - { - FunctionName = fname; - ScriptInvocationDelegate = fn; - TypeSignature = callsig; - ReturnType = returnsig; - } - } - - private Dictionary m_scriptInvocation = new Dictionary(); -#endregion - - private IScriptModule m_scriptModule = null; - public event ScriptCommand OnScriptCommand; - -#region RegionModuleInterface - public void Initialise(IConfigSource config) - { - } - - public void AddRegion(Scene scene) - { - scene.RegisterModuleInterface(this); - } - - public void RemoveRegion(Scene scene) - { - } - - public void RegionLoaded(Scene scene) - { - m_scriptModule = scene.RequestModuleInterface(); - - if (m_scriptModule != null) - m_log.Info("[MODULE COMMANDS]: Script engine found, module active"); - } - - public string Name - { - get { return "ScriptModuleCommsModule"; } - } - - public Type ReplaceableInterface - { - get { return null; } - } - - public void Close() - { - } -#endregion - -#region ScriptModuleComms - - public void RaiseEvent(UUID script, string id, string module, string command, string k) - { - ScriptCommand c = OnScriptCommand; - - if (c == null) - return; - - c(script, id, module, command, k); - } - - public void DispatchReply(UUID script, int code, string text, string k) - { - if (m_scriptModule == null) - return; - - Object[] args = new Object[] {-1, code, text, k}; - - m_scriptModule.PostScriptEvent(script, "link_message", args); - } - - private static MethodInfo GetMethodInfoFromType(Type target, string meth, bool searchInstanceMethods) - { - BindingFlags getMethodFlags = - BindingFlags.NonPublic | BindingFlags.Public; - - if (searchInstanceMethods) - getMethodFlags |= BindingFlags.Instance; - else - getMethodFlags |= BindingFlags.Static; - - return target.GetMethod(meth, getMethodFlags); - } - - public void RegisterScriptInvocation(object target, string meth) - { - MethodInfo mi = GetMethodInfoFromType(target.GetType(), meth, true); - if (mi == null) - { - m_log.WarnFormat("[MODULE COMMANDS] Failed to register method {0}", meth); - return; - } - - RegisterScriptInvocation(target, mi); - } - - public void RegisterScriptInvocation(object target, string[] meth) - { - foreach (string m in meth) - RegisterScriptInvocation(target, m); - } - - public void RegisterScriptInvocation(object target, MethodInfo mi) - { - m_log.DebugFormat("[MODULE COMMANDS] Register method {0} from type {1}", mi.Name, (target is Type) ? ((Type)target).Name : target.GetType().Name); - - Type delegateType; - List typeArgs = mi.GetParameters() - .Select(p => p.ParameterType) - .ToList(); - - if (mi.ReturnType == typeof(void)) - { - delegateType = Expression.GetActionType(typeArgs.ToArray()); - } - else - { - typeArgs.Add(mi.ReturnType); - delegateType = Expression.GetFuncType(typeArgs.ToArray()); - } - - Delegate fcall; - if (!(target is Type)) - fcall = Delegate.CreateDelegate(delegateType, target, mi); - else - fcall = Delegate.CreateDelegate(delegateType, (Type)target, mi.Name); - - lock (m_scriptInvocation) - { - ParameterInfo[] parameters = fcall.Method.GetParameters(); - if (parameters.Length < 2) // Must have two UUID params - return; - - // Hide the first two parameters - Type[] parmTypes = new Type[parameters.Length - 2]; - for (int i = 2; i < parameters.Length; i++) - parmTypes[i - 2] = parameters[i].ParameterType; - m_scriptInvocation[fcall.Method.Name] = new ScriptInvocationData(fcall.Method.Name, fcall, parmTypes, fcall.Method.ReturnType); - } - } - - public void RegisterScriptInvocation(Type target, string[] methods) - { - foreach (string method in methods) - { - MethodInfo mi = GetMethodInfoFromType(target, method, false); - if (mi == null) - m_log.WarnFormat("[MODULE COMMANDS] Failed to register method {0}", method); - else - RegisterScriptInvocation(target, mi); - } - } - - public void RegisterScriptInvocations(IRegionModuleBase target) - { - foreach(MethodInfo method in target.GetType().GetMethods( - BindingFlags.Public | BindingFlags.Instance | - BindingFlags.Static)) - { - if(method.GetCustomAttributes( - typeof(ScriptInvocationAttribute), true).Any()) - { - if(method.IsStatic) - RegisterScriptInvocation(target.GetType(), method); - else - RegisterScriptInvocation(target, method); - } - } - } - - public Delegate[] GetScriptInvocationList() - { - List ret = new List(); - - lock (m_scriptInvocation) - { - foreach (ScriptInvocationData d in m_scriptInvocation.Values) - ret.Add(d.ScriptInvocationDelegate); - } - return ret.ToArray(); - } - - public string LookupModInvocation(string fname) - { - lock (m_scriptInvocation) - { - ScriptInvocationData sid; - if (m_scriptInvocation.TryGetValue(fname,out sid)) - { - if (sid.ReturnType == typeof(string)) - return "modInvokeS"; - else if (sid.ReturnType == typeof(int)) - return "modInvokeI"; - else if (sid.ReturnType == typeof(float)) - return "modInvokeF"; - else if (sid.ReturnType == typeof(UUID)) - return "modInvokeK"; - else if (sid.ReturnType == typeof(OpenMetaverse.Vector3)) - return "modInvokeV"; - else if (sid.ReturnType == typeof(OpenMetaverse.Quaternion)) - return "modInvokeR"; - else if (sid.ReturnType == typeof(object[])) - return "modInvokeL"; - - m_log.WarnFormat("[MODULE COMMANDS] failed to find match for {0} with return type {1}",fname,sid.ReturnType.Name); - } - } - - return null; - } - - public Delegate LookupScriptInvocation(string fname) - { - lock (m_scriptInvocation) - { - ScriptInvocationData sid; - if (m_scriptInvocation.TryGetValue(fname,out sid)) - return sid.ScriptInvocationDelegate; - } - - return null; - } - - public Type[] LookupTypeSignature(string fname) - { - lock (m_scriptInvocation) - { - ScriptInvocationData sid; - if (m_scriptInvocation.TryGetValue(fname,out sid)) - return sid.TypeSignature; - } - - return null; - } - - public Type LookupReturnType(string fname) - { - lock (m_scriptInvocation) - { - ScriptInvocationData sid; - if (m_scriptInvocation.TryGetValue(fname,out sid)) - return sid.ReturnType; - } - - return null; - } - - public object InvokeOperation(UUID hostid, UUID scriptid, string fname, params object[] parms) - { - List olist = new List(); - olist.Add(hostid); - olist.Add(scriptid); - foreach (object o in parms) - olist.Add(o); - Delegate fn = LookupScriptInvocation(fname); - return fn.DynamicInvoke(olist.ToArray()); - } - - /// - /// Operation to for a region module to register a constant to be used - /// by the script engine - /// - public void RegisterConstant(string cname, object value) - { - m_log.DebugFormat("[MODULE COMMANDS] register constant <{0}> with value {1}",cname,value.ToString()); - lock (m_constants) - { - m_constants.Add(cname,value); - } - } - - public void RegisterConstants(IRegionModuleBase target) - { - foreach (FieldInfo field in target.GetType().GetFields( - BindingFlags.Public | BindingFlags.Static | - BindingFlags.Instance)) - { - if (field.GetCustomAttributes( - typeof(ScriptConstantAttribute), true).Any()) - { - RegisterConstant(field.Name, field.GetValue(target)); - } - } - } - - /// - /// Operation to check for a registered constant - /// - public object LookupModConstant(string cname) - { - // m_log.DebugFormat("[MODULE COMMANDS] lookup constant <{0}>",cname); - - lock (m_constants) - { - object value = null; - if (m_constants.TryGetValue(cname,out value)) - return value; - } - - return null; - } - - /// - /// Get all registered constants - /// - public Dictionary GetConstants() - { - Dictionary ret = new Dictionary(); - - lock (m_constants) - { - foreach (KeyValuePair kvp in m_constants) - ret[kvp.Key] = kvp.Value; - } - - return ret; - } - -#endregion - - } -} diff --git a/OpenSim/Region/CoreModules/Scripting/VectorRender/Tests/VectorRenderModuleTests.cs b/OpenSim/Region/CoreModules/Scripting/VectorRender/Tests/VectorRenderModuleTests.cs index 41baccc..9787c8c 100644 --- a/OpenSim/Region/CoreModules/Scripting/VectorRender/Tests/VectorRenderModuleTests.cs +++ b/OpenSim/Region/CoreModules/Scripting/VectorRender/Tests/VectorRenderModuleTests.cs @@ -45,292 +45,31 @@ using OpenSim.Tests.Common.Mock; namespace OpenSim.Region.CoreModules.Scripting.VectorRender.Tests { [TestFixture] - public class VectorRenderModuleTests : OpenSimTestCase + public class VectorRenderModuleTests { - Scene m_scene; - DynamicTextureModule m_dtm; - VectorRenderModule m_vrm; - - private void SetupScene(bool reuseTextures) - { - m_scene = new SceneHelpers().SetupScene(); - - m_dtm = new DynamicTextureModule(); - m_dtm.ReuseTextures = reuseTextures; -// m_dtm.ReuseLowDataTextures = reuseTextures; - - m_vrm = new VectorRenderModule(); - - SceneHelpers.SetupSceneModules(m_scene, m_dtm, m_vrm); - } - [Test] public void TestDraw() { TestHelpers.InMethod(); - SetupScene(false); - SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene); - UUID originalTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID; - - m_dtm.AddDynamicTextureData( - m_scene.RegionInfo.RegionID, - so.UUID, - m_vrm.GetContentType(), - "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;", - "", - 0); - - Assert.That(originalTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID)); - } - - [Test] - public void TestRepeatSameDraw() - { - TestHelpers.InMethod(); - - string dtText = "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;"; - - SetupScene(false); - SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene); - - m_dtm.AddDynamicTextureData( - m_scene.RegionInfo.RegionID, - so.UUID, - m_vrm.GetContentType(), - dtText, - "", - 0); - - UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID; - - m_dtm.AddDynamicTextureData( - m_scene.RegionInfo.RegionID, - so.UUID, - m_vrm.GetContentType(), - dtText, - "", - 0); - - Assert.That(firstDynamicTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID)); - } - - [Test] - public void TestRepeatSameDrawDifferentExtraParams() - { - TestHelpers.InMethod(); - - string dtText = "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;"; - - SetupScene(false); - SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene); - - m_dtm.AddDynamicTextureData( - m_scene.RegionInfo.RegionID, - so.UUID, - m_vrm.GetContentType(), - dtText, - "", - 0); - - UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID; - - m_dtm.AddDynamicTextureData( - m_scene.RegionInfo.RegionID, - so.UUID, - m_vrm.GetContentType(), - dtText, - "alpha:250", - 0); - - Assert.That(firstDynamicTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID)); - } - - [Test] - public void TestRepeatSameDrawContainingImage() - { - TestHelpers.InMethod(); - - string dtText - = "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World; Image http://localhost/shouldnotexist.png"; - - SetupScene(false); - SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene); - - m_dtm.AddDynamicTextureData( - m_scene.RegionInfo.RegionID, - so.UUID, - m_vrm.GetContentType(), - dtText, - "", - 0); - - UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID; - - m_dtm.AddDynamicTextureData( - m_scene.RegionInfo.RegionID, - so.UUID, - m_vrm.GetContentType(), - dtText, - "", - 0); - - Assert.That(firstDynamicTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID)); - } - - [Test] - public void TestDrawReusingTexture() - { - TestHelpers.InMethod(); + Scene scene = new SceneHelpers().SetupScene(); + DynamicTextureModule dtm = new DynamicTextureModule(); + VectorRenderModule vrm = new VectorRenderModule(); + SceneHelpers.SetupSceneModules(scene, dtm, vrm); - SetupScene(true); - SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene); + SceneObjectGroup so = SceneHelpers.AddSceneObject(scene); UUID originalTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID; - m_dtm.AddDynamicTextureData( - m_scene.RegionInfo.RegionID, + dtm.AddDynamicTextureData( + scene.RegionInfo.RegionID, so.UUID, - m_vrm.GetContentType(), + vrm.GetContentType(), "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;", "", 0); - Assert.That(originalTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID)); - } - - [Test] - public void TestRepeatSameDrawReusingTexture() - { - TestHelpers.InMethod(); -// TestHelpers.EnableLogging(); - - string dtText = "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;"; - - SetupScene(true); - SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene); - - m_dtm.AddDynamicTextureData( - m_scene.RegionInfo.RegionID, - so.UUID, - m_vrm.GetContentType(), - dtText, - "", - 0); - - UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID; - - m_dtm.AddDynamicTextureData( - m_scene.RegionInfo.RegionID, - so.UUID, - m_vrm.GetContentType(), - dtText, - "", - 0); - - Assert.That(firstDynamicTextureID, Is.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID)); - } - - /// - /// Test a low data dynamically generated texture such that it is treated as a low data texture that causes - /// problems for current viewers. - /// - /// - /// As we do not set DynamicTextureModule.ReuseLowDataTextures = true in this test, it should not reuse the - /// texture - /// - [Test] - public void TestRepeatSameDrawLowDataTexture() - { - TestHelpers.InMethod(); -// TestHelpers.EnableLogging(); - - string dtText = "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;"; - - SetupScene(true); - SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene); - - m_dtm.AddDynamicTextureData( - m_scene.RegionInfo.RegionID, - so.UUID, - m_vrm.GetContentType(), - dtText, - "1024", - 0); - - UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID; - - m_dtm.AddDynamicTextureData( - m_scene.RegionInfo.RegionID, - so.UUID, - m_vrm.GetContentType(), - dtText, - "1024", - 0); - - Assert.That(firstDynamicTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID)); - } - - [Test] - public void TestRepeatSameDrawDifferentExtraParamsReusingTexture() - { - TestHelpers.InMethod(); - - string dtText = "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;"; - - SetupScene(true); - SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene); - - m_dtm.AddDynamicTextureData( - m_scene.RegionInfo.RegionID, - so.UUID, - m_vrm.GetContentType(), - dtText, - "", - 0); - - UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID; - - m_dtm.AddDynamicTextureData( - m_scene.RegionInfo.RegionID, - so.UUID, - m_vrm.GetContentType(), - dtText, - "alpha:250", - 0); - - Assert.That(firstDynamicTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID)); - } - - [Test] - public void TestRepeatSameDrawContainingImageReusingTexture() - { - TestHelpers.InMethod(); - - string dtText - = "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World; Image http://localhost/shouldnotexist.png"; - - SetupScene(true); - SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene); - - m_dtm.AddDynamicTextureData( - m_scene.RegionInfo.RegionID, - so.UUID, - m_vrm.GetContentType(), - dtText, - "", - 0); - - UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID; - - m_dtm.AddDynamicTextureData( - m_scene.RegionInfo.RegionID, - so.UUID, - m_vrm.GetContentType(), - dtText, - "", - 0); - Assert.That(firstDynamicTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID)); + Assert.That(originalTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID)); } } } \ No newline at end of file diff --git a/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs b/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs index 673c2d1..8b2f2f8 100644 --- a/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs +++ b/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs @@ -30,12 +30,10 @@ using System.Drawing; using System.Drawing.Imaging; using System.Globalization; using System.IO; -using System.Linq; using System.Net; using Nini.Config; using OpenMetaverse; using OpenMetaverse.Imaging; -using OpenSim.Region.CoreModules.Scripting.DynamicTexture; using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Scenes; using log4net; @@ -47,13 +45,9 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender { public class VectorRenderModule : IRegionModule, IDynamicTextureRender { - // These fields exist for testing purposes, please do not remove. -// private static bool s_flipper; -// private static byte[] s_asset1Data; -// private static byte[] s_asset2Data; - private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + private string m_name = "VectorRenderModule"; private Scene m_scene; private IDynamicTextureManager m_textureManager; private Graphics m_graph; @@ -67,12 +61,12 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender public string GetContentType() { - return "vector"; + return ("vector"); } public string GetName() { - return Name; + return m_name; } public bool SupportsAsynchronous() @@ -80,20 +74,14 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender return true; } -// public bool AlwaysIdenticalConversion(string bodyData, string extraParams) -// { -// string[] lines = GetLines(bodyData); -// return lines.Any((str, r) => str.StartsWith("Image")); -// } - - public IDynamicTexture ConvertUrl(string url, string extraParams) + public byte[] ConvertUrl(string url, string extraParams) { return null; } - public IDynamicTexture ConvertData(string bodyData, string extraParams) + public byte[] ConvertStream(Stream data, string extraParams) { - return Draw(bodyData, extraParams); + return null; } public bool AsyncConvertUrl(UUID id, string url, string extraParams) @@ -103,28 +91,21 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender public bool AsyncConvertData(UUID id, string bodyData, string extraParams) { - // XXX: This isn't actually being done asynchronously! - m_textureManager.ReturnData(id, ConvertData(bodyData, extraParams)); - + Draw(bodyData, id, extraParams); return true; } public void GetDrawStringSize(string text, string fontName, int fontSize, out double xSize, out double ySize) { - lock (this) + using (Font myFont = new Font(fontName, fontSize)) { - using (Font myFont = new Font(fontName, fontSize)) + SizeF stringSize = new SizeF(); + lock (m_graph) { - SizeF stringSize = new SizeF(); - - // XXX: This lock may be unnecessary. - lock (m_graph) - { - stringSize = m_graph.MeasureString(text, myFont); - xSize = stringSize.Width; - ySize = stringSize.Height; - } + stringSize = m_graph.MeasureString(text, myFont); + xSize = stringSize.Width; + ySize = stringSize.Height; } } } @@ -163,13 +144,6 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender { m_textureManager.RegisterRender(GetContentType(), this); } - - // This code exists for testing purposes, please do not remove. -// s_asset1Data = m_scene.AssetService.Get("00000000-0000-1111-9999-000000000001").Data; -// s_asset1Data = m_scene.AssetService.Get("9f4acf0d-1841-4e15-bdb8-3a12efc9dd8f").Data; - - // Terrain dirt - smallest bin/assets file (6004 bytes) -// s_asset2Data = m_scene.AssetService.Get("b8d3965a-ad78-bf43-699b-bff8eca6c975").Data; } public void Close() @@ -178,7 +152,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender public string Name { - get { return "VectorRenderModule"; } + get { return m_name; } } public bool IsSharedModule @@ -188,7 +162,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender #endregion - private IDynamicTexture Draw(string data, string extraParams) + private void Draw(string data, UUID id, string extraParams) { // We need to cater for old scripts that didnt use extraParams neatly, they use either an integer size which represents both width and height, or setalpha // we will now support multiple comma seperated params in the form width:256,height:512,alpha:255 @@ -331,57 +305,40 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender Bitmap bitmap = null; Graphics graph = null; - bool reuseable = false; try { - // XXX: In testing, it appears that if multiple threads dispose of separate GDI+ objects simultaneously, - // the native malloc heap can become corrupted, possibly due to a double free(). This may be due to - // bugs in the underlying libcairo used by mono's libgdiplus.dll on Linux/OSX. These problems were - // seen with both libcario 1.10.2-6.1ubuntu3 and 1.8.10-2ubuntu1. They go away if disposal is perfomed - // under lock. - lock (this) - { - if (alpha == 256) - bitmap = new Bitmap(width, height, PixelFormat.Format32bppRgb); - else - bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); + if (alpha == 256) + bitmap = new Bitmap(width, height, PixelFormat.Format32bppRgb); + else + bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); + + graph = Graphics.FromImage(bitmap); - graph = Graphics.FromImage(bitmap); - - // this is really just to save people filling the - // background color in their scripts, only do when fully opaque - if (alpha >= 255) + // this is really just to save people filling the + // background color in their scripts, only do when fully opaque + if (alpha >= 255) + { + using (SolidBrush bgFillBrush = new SolidBrush(bgColor)) { - using (SolidBrush bgFillBrush = new SolidBrush(bgColor)) - { - graph.FillRectangle(bgFillBrush, 0, 0, width, height); - } + graph.FillRectangle(bgFillBrush, 0, 0, width, height); } - - for (int w = 0; w < bitmap.Width; w++) + } + + for (int w = 0; w < bitmap.Width; w++) + { + if (alpha <= 255) { - if (alpha <= 255) + for (int h = 0; h < bitmap.Height; h++) { - for (int h = 0; h < bitmap.Height; h++) - { - bitmap.SetPixel(w, h, Color.FromArgb(alpha, bitmap.GetPixel(w, h))); - } + bitmap.SetPixel(w, h, Color.FromArgb(alpha, bitmap.GetPixel(w, h))); } } - - GDIDraw(data, graph, altDataDelim, out reuseable); } + GDIDraw(data, graph, altDataDelim); + byte[] imageJ2000 = new byte[0]; - - // This code exists for testing purposes, please do not remove. -// if (s_flipper) -// imageJ2000 = s_asset1Data; -// else -// imageJ2000 = s_asset2Data; -// -// s_flipper = !s_flipper; try { @@ -394,24 +351,15 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender e.Message, e.StackTrace); } - return new OpenSim.Region.CoreModules.Scripting.DynamicTexture.DynamicTexture( - data, extraParams, imageJ2000, new Size(width, height), reuseable); + m_textureManager.ReturnData(id, imageJ2000); } finally { - // XXX: In testing, it appears that if multiple threads dispose of separate GDI+ objects simultaneously, - // the native malloc heap can become corrupted, possibly due to a double free(). This may be due to - // bugs in the underlying libcairo used by mono's libgdiplus.dll on Linux/OSX. These problems were - // seen with both libcario 1.10.2-6.1ubuntu3 and 1.8.10-2ubuntu1. They go away if disposal is perfomed - // under lock. - lock (this) - { - if (graph != null) - graph.Dispose(); - - if (bitmap != null) - bitmap.Dispose(); - } + if (graph != null) + graph.Dispose(); + + if (bitmap != null) + bitmap.Dispose(); } } @@ -470,21 +418,8 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender } */ - /// - /// Split input data into discrete command lines. - /// - /// - /// - /// - private string[] GetLines(string data, char dataDelim) - { - char[] lineDelimiter = { dataDelim }; - return data.Split(lineDelimiter); - } - - private void GDIDraw(string data, Graphics graph, char dataDelim, out bool reuseable) + private void GDIDraw(string data, Graphics graph, char dataDelim) { - reuseable = true; Point startPoint = new Point(0, 0); Point endPoint = new Point(0, 0); Pen drawPen = null; @@ -499,9 +434,11 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender myFont = new Font(fontName, fontSize); myBrush = new SolidBrush(Color.Black); + char[] lineDelimiter = {dataDelim}; char[] partsDelimiter = {','}; + string[] lines = data.Split(lineDelimiter); - foreach (string line in GetLines(data, dataDelim)) + foreach (string line in lines) { string nextLine = line.Trim(); //replace with switch, or even better, do some proper parsing @@ -532,10 +469,6 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender } else if (nextLine.StartsWith("Image")) { - // We cannot reuse any generated texture involving fetching an image via HTTP since that image - // can change. - reuseable = false; - float x = 0; float y = 0; GetParams(partsDelimiter, ref nextLine, 5, ref x, ref y); diff --git a/OpenSim/Region/CoreModules/Scripting/WorldComm/WorldCommModule.cs b/OpenSim/Region/CoreModules/Scripting/WorldComm/WorldCommModule.cs index e167e31..07bb291 100644 --- a/OpenSim/Region/CoreModules/Scripting/WorldComm/WorldCommModule.cs +++ b/OpenSim/Region/CoreModules/Scripting/WorldComm/WorldCommModule.cs @@ -28,7 +28,6 @@ using System; using System.Collections; using System.Collections.Generic; -using System.Text.RegularExpressions; using Nini.Config; using OpenMetaverse; using OpenSim.Framework; @@ -173,42 +172,12 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm /// UUID of the SceneObjectPart /// channel to listen on /// name to filter on - /// - /// key to filter on (user given, could be totally faked) - /// - /// msg to filter on - /// number of the scripts handle - public int Listen(uint localID, UUID itemID, UUID hostID, int channel, - string name, UUID id, string msg) - { - return m_listenerManager.AddListener(localID, itemID, hostID, - channel, name, id, msg); - } - - /// - /// Create a listen event callback with the specified filters. - /// The parameters localID,itemID are needed to uniquely identify - /// the script during 'peek' time. Parameter hostID is needed to - /// determine the position of the script. - /// - /// localID of the script engine - /// UUID of the script engine - /// UUID of the SceneObjectPart - /// channel to listen on - /// name to filter on - /// - /// key to filter on (user given, could be totally faked) - /// + /// key to filter on (user given, could be totally faked) /// msg to filter on - /// - /// Bitfield indicating which strings should be processed as regex. - /// /// number of the scripts handle - public int Listen(uint localID, UUID itemID, UUID hostID, int channel, - string name, UUID id, string msg, int regexBitfield) + public int Listen(uint localID, UUID itemID, UUID hostID, int channel, string name, UUID id, string msg) { - return m_listenerManager.AddListener(localID, itemID, hostID, - channel, name, id, msg, regexBitfield); + return m_listenerManager.AddListener(localID, itemID, hostID, channel, name, id, msg); } /// @@ -357,7 +326,7 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm if (channel == 0) { // Channel 0 goes to viewer ONLY - m_scene.SimChat(Utils.StringToBytes(msg), ChatTypeEnum.Broadcast, 0, pos, name, id, target, false, false); + m_scene.SimChat(Utils.StringToBytes(msg), ChatTypeEnum.Broadcast, 0, pos, name, id, false, false, target); return true; } @@ -501,25 +470,15 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm m_curlisteners = 0; } - public int AddListener(uint localID, UUID itemID, UUID hostID, - int channel, string name, UUID id, string msg) - { - return AddListener(localID, itemID, hostID, channel, name, id, - msg, 0); - } - - public int AddListener(uint localID, UUID itemID, UUID hostID, - int channel, string name, UUID id, string msg, - int regexBitfield) + public int AddListener(uint localID, UUID itemID, UUID hostID, int channel, string name, UUID id, string msg) { // do we already have a match on this particular filter event? - List coll = GetListeners(itemID, channel, name, id, - msg); + List coll = GetListeners(itemID, channel, name, id, msg); if (coll.Count > 0) { - // special case, called with same filter settings, return same - // handle (2008-05-02, tested on 1.21.1 server, still holds) + // special case, called with same filter settings, return same handle + // (2008-05-02, tested on 1.21.1 server, still holds) return coll[0].GetHandle(); } @@ -531,9 +490,7 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm if (newHandle > 0) { - ListenerInfo li = new ListenerInfo(newHandle, localID, - itemID, hostID, channel, name, id, msg, - regexBitfield); + ListenerInfo li = new ListenerInfo(newHandle, localID, itemID, hostID, channel, name, id, msg); List listeners; if (!m_listeners.TryGetValue(channel,out listeners)) @@ -674,22 +631,6 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm return -1; } - /// These are duplicated from ScriptBaseClass - /// http://opensimulator.org/mantis/view.php?id=6106#c21945 - #region Constants for the bitfield parameter of osListenRegex - - /// - /// process name parameter as regex - /// - public const int OS_LISTEN_REGEX_NAME = 0x1; - - /// - /// process message parameter as regex - /// - public const int OS_LISTEN_REGEX_MESSAGE = 0x2; - - #endregion - // Theres probably a more clever and efficient way to // do this, maybe with regex. // PM2008: Ha, one could even be smart and define a specialized Enumerator. @@ -715,10 +656,7 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm { continue; } - if (li.GetName().Length > 0 && ( - ((li.RegexBitfield & OS_LISTEN_REGEX_NAME) != OS_LISTEN_REGEX_NAME && !li.GetName().Equals(name)) || - ((li.RegexBitfield & OS_LISTEN_REGEX_NAME) == OS_LISTEN_REGEX_NAME && !Regex.IsMatch(name, li.GetName())) - )) + if (li.GetName().Length > 0 && !li.GetName().Equals(name)) { continue; } @@ -726,10 +664,7 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm { continue; } - if (li.GetMessage().Length > 0 && ( - ((li.RegexBitfield & OS_LISTEN_REGEX_MESSAGE) != OS_LISTEN_REGEX_MESSAGE && !li.GetMessage().Equals(msg)) || - ((li.RegexBitfield & OS_LISTEN_REGEX_MESSAGE) == OS_LISTEN_REGEX_MESSAGE && !Regex.IsMatch(msg, li.GetMessage())) - )) + if (li.GetMessage().Length > 0 && !li.GetMessage().Equals(msg)) { continue; } @@ -762,13 +697,10 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm { int idx = 0; Object[] item = new Object[6]; - int dataItemLength = 6; while (idx < data.Length) { - dataItemLength = (idx + 7 == data.Length || (idx + 7 < data.Length && data[idx + 7] is bool)) ? 7 : 6; - item = new Object[dataItemLength]; - Array.Copy(data, idx, item, 0, dataItemLength); + Array.Copy(data, idx, item, 0, 6); ListenerInfo info = ListenerInfo.FromData(localID, itemID, hostID, item); @@ -780,12 +712,12 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm m_listeners[(int)item[2]].Add(info); } - idx+=dataItemLength; + idx+=6; } } } - public class ListenerInfo : IWorldCommListenerInfo + public class ListenerInfo: IWorldCommListenerInfo { private bool m_active; // Listener is active or not private int m_handle; // Assigned handle of this listener @@ -799,29 +731,16 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm public ListenerInfo(int handle, uint localID, UUID ItemID, UUID hostID, int channel, string name, UUID id, string message) { - Initialise(handle, localID, ItemID, hostID, channel, name, id, - message, 0); - } - - public ListenerInfo(int handle, uint localID, UUID ItemID, - UUID hostID, int channel, string name, UUID id, - string message, int regexBitfield) - { - Initialise(handle, localID, ItemID, hostID, channel, name, id, - message, regexBitfield); + Initialise(handle, localID, ItemID, hostID, channel, name, id, message); } public ListenerInfo(ListenerInfo li, string name, UUID id, string message) { - Initialise(li.m_handle, li.m_localID, li.m_itemID, li.m_hostID, li.m_channel, name, id, message, 0); - } - - public ListenerInfo(ListenerInfo li, string name, UUID id, string message, int regexBitfield) - { - Initialise(li.m_handle, li.m_localID, li.m_itemID, li.m_hostID, li.m_channel, name, id, message, regexBitfield); + Initialise(li.m_handle, li.m_localID, li.m_itemID, li.m_hostID, li.m_channel, name, id, message); } - private void Initialise(int handle, uint localID, UUID ItemID, UUID hostID, int channel, string name, UUID id, string message, int regexBitfield) + private void Initialise(int handle, uint localID, UUID ItemID, UUID hostID, int channel, string name, + UUID id, string message) { m_active = true; m_handle = handle; @@ -832,12 +751,11 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm m_name = name; m_id = id; m_message = message; - RegexBitfield = regexBitfield; } public Object[] GetSerializationData() { - Object[] data = new Object[7]; + Object[] data = new Object[6]; data[0] = m_active; data[1] = m_handle; @@ -845,19 +763,16 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm data[3] = m_name; data[4] = m_id; data[5] = m_message; - data[6] = RegexBitfield; return data; } public static ListenerInfo FromData(uint localID, UUID ItemID, UUID hostID, Object[] data) { - ListenerInfo linfo = new ListenerInfo((int)data[1], localID, ItemID, hostID, (int)data[2], (string)data[3], (UUID)data[4], (string)data[5]); - linfo.m_active = (bool)data[0]; - if (data.Length >= 7) - { - linfo.RegexBitfield = (int)data[6]; - } + ListenerInfo linfo = new ListenerInfo((int)data[1], localID, + ItemID, hostID, (int)data[2], (string)data[3], + (UUID)data[4], (string)data[5]); + linfo.m_active=(bool)data[0]; return linfo; } @@ -916,7 +831,5 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm { return m_id; } - - public int RegexBitfield { get; private set; } } } diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/HGAssetBroker.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/HGAssetBroker.cs index 1e1c7d0..008465f 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/HGAssetBroker.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/HGAssetBroker.cs @@ -56,8 +56,6 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset private bool m_Enabled = false; - private AssetPermissions m_AssetPerms; - public Type ReplaceableInterface { get { return null; } @@ -130,9 +128,6 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset if (m_LocalAssetServiceURI != string.Empty) m_LocalAssetServiceURI = m_LocalAssetServiceURI.Trim('/'); - IConfig hgConfig = source.Configs["HGAssetService"]; - m_AssetPerms = new AssetPermissions(hgConfig); // it's ok if arg is null - m_Enabled = true; m_log.Info("[HG ASSET CONNECTOR]: HG asset broker enabled"); } @@ -211,11 +206,14 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset asset = m_HGService.Get(id); if (asset != null) { - // Now store it locally, if allowed - if (m_AssetPerms.AllowedImport(asset.Type)) + // Now store it locally + // For now, let me just do it for textures and scripts + if (((AssetType)asset.Type == AssetType.Texture) || + ((AssetType)asset.Type == AssetType.LSLBytecode) || + ((AssetType)asset.Type == AssetType.LSLText)) + { m_GridService.Store(asset); - else - return null; + } } } else @@ -330,12 +328,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset string id = string.Empty; if (IsHG(asset.ID)) - { - if (m_AssetPerms.AllowedExport(asset.Type)) - id = m_HGService.Store(asset); - else - return String.Empty; - } + id = m_HGService.Store(asset); else id = m_GridService.Store(asset); diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/LocalAssetServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/LocalAssetServiceConnector.cs index 449c1f1..c78915f 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/LocalAssetServiceConnector.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/LocalAssetServiceConnector.cs @@ -204,11 +204,8 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset public byte[] GetData(string id) { // m_log.DebugFormat("[LOCAL ASSET SERVICES CONNECTOR]: Requesting data for asset {0}", id); - - AssetBase asset = null; - - if (m_Cache != null) - asset = m_Cache.Get(id); + + AssetBase asset = m_Cache.Get(id); if (asset != null) return asset.Data; diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/Tests/AssetConnectorTests.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/Tests/AssetConnectorTests.cs deleted file mode 100644 index 1982473..0000000 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/Tests/AssetConnectorTests.cs +++ /dev/null @@ -1,136 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.IO; -using System.Reflection; -using System.Threading; -using log4net.Config; -using Nini.Config; -using NUnit.Framework; -using OpenMetaverse; -using OpenSim.Framework; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset; -using OpenSim.Tests.Common; - -namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset.Tests -{ - [TestFixture] - public class AssetConnectorsTests : OpenSimTestCase - { - [Test] - public void TestAddAsset() - { - TestHelpers.InMethod(); -// TestHelpers.EnableLogging(); - - IConfigSource config = new IniConfigSource(); - config.AddConfig("Modules"); - config.Configs["Modules"].Set("AssetServices", "LocalAssetServicesConnector"); - config.AddConfig("AssetService"); - config.Configs["AssetService"].Set("LocalServiceModule", "OpenSim.Services.AssetService.dll:AssetService"); - config.Configs["AssetService"].Set("StorageProvider", "OpenSim.Tests.Common.dll"); - - LocalAssetServicesConnector lasc = new LocalAssetServicesConnector(); - lasc.Initialise(config); - - AssetBase a1 = AssetHelpers.CreateNotecardAsset(); - lasc.Store(a1); - - AssetBase retreivedA1 = lasc.Get(a1.ID); - Assert.That(retreivedA1.ID, Is.EqualTo(a1.ID)); - Assert.That(retreivedA1.Metadata.ID, Is.EqualTo(a1.Metadata.ID)); - Assert.That(retreivedA1.Data.Length, Is.EqualTo(a1.Data.Length)); - - AssetMetadata retrievedA1Metadata = lasc.GetMetadata(a1.ID); - Assert.That(retrievedA1Metadata.ID, Is.EqualTo(a1.ID)); - - byte[] retrievedA1Data = lasc.GetData(a1.ID); - Assert.That(retrievedA1Data.Length, Is.EqualTo(a1.Data.Length)); - - // TODO: Add cache and check that this does receive a copy of the asset - } - - [Test] - public void TestAddTemporaryAsset() - { - TestHelpers.InMethod(); -// TestHelpers.EnableLogging(); - - IConfigSource config = new IniConfigSource(); - config.AddConfig("Modules"); - config.Configs["Modules"].Set("AssetServices", "LocalAssetServicesConnector"); - config.AddConfig("AssetService"); - config.Configs["AssetService"].Set("LocalServiceModule", "OpenSim.Services.AssetService.dll:AssetService"); - config.Configs["AssetService"].Set("StorageProvider", "OpenSim.Tests.Common.dll"); - - LocalAssetServicesConnector lasc = new LocalAssetServicesConnector(); - lasc.Initialise(config); - - AssetBase a1 = AssetHelpers.CreateNotecardAsset(); - a1.Temporary = true; - - lasc.Store(a1); - - Assert.That(lasc.Get(a1.ID), Is.Null); - Assert.That(lasc.GetData(a1.ID), Is.Null); - Assert.That(lasc.GetMetadata(a1.ID), Is.Null); - - // TODO: Add cache and check that this does receive a copy of the asset - } - - [Test] - public void TestAddLocalAsset() - { - TestHelpers.InMethod(); -// TestHelpers.EnableLogging(); - - IConfigSource config = new IniConfigSource(); - config.AddConfig("Modules"); - config.Configs["Modules"].Set("AssetServices", "LocalAssetServicesConnector"); - config.AddConfig("AssetService"); - config.Configs["AssetService"].Set("LocalServiceModule", "OpenSim.Services.AssetService.dll:AssetService"); - config.Configs["AssetService"].Set("StorageProvider", "OpenSim.Tests.Common.dll"); - - LocalAssetServicesConnector lasc = new LocalAssetServicesConnector(); - lasc.Initialise(config); - - AssetBase a1 = AssetHelpers.CreateNotecardAsset(); - a1.Local = true; - - lasc.Store(a1); - - Assert.That(lasc.Get(a1.ID), Is.Null); - Assert.That(lasc.GetData(a1.ID), Is.Null); - Assert.That(lasc.GetMetadata(a1.ID), Is.Null); - - // TODO: Add cache and check that this does receive a copy of the asset - } - } -} \ No newline at end of file diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/Tests/GridConnectorsTests.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/Tests/GridConnectorsTests.cs index 4338133..b286d17 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/Tests/GridConnectorsTests.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/Tests/GridConnectorsTests.cs @@ -43,15 +43,11 @@ using OpenSim.Tests.Common; namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid.Tests { [TestFixture] - public class GridConnectorsTests : OpenSimTestCase + public class GridConnectorsTests { LocalGridServicesConnector m_LocalConnector; - - [SetUp] - public override void SetUp() + private void SetUp() { - base.SetUp(); - IConfigSource config = new IniConfigSource(); config.AddConfig("Modules"); config.AddConfig("GridService"); @@ -75,6 +71,8 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid.Tests TestHelpers.InMethod(); // log4net.Config.XmlConfigurator.Configure(); + SetUp(); + // Create 4 regions GridRegion r1 = new GridRegion(); r1.RegionName = "Test Region 1"; diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/ActivityDetector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/ActivityDetector.cs index 221f815..b0edce7 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/ActivityDetector.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/ActivityDetector.cs @@ -65,13 +65,11 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.GridUser public void OnMakeRootAgent(ScenePresence sp) { +// m_log.DebugFormat("[ACTIVITY DETECTOR]: Detected root presence {0} in {1}", sp.UUID, sp.Scene.RegionInfo.RegionName); + if (sp.PresenceType != PresenceType.Npc) - { - string userid = sp.Scene.UserManagementModule.GetUserUUI(sp.UUID); - //m_log.DebugFormat("[ACTIVITY DETECTOR]: Detected root presence {0} in {1}", userid, sp.Scene.RegionInfo.RegionName); m_GridUserService.SetLastPosition( - userid, UUID.Zero, sp.Scene.RegionInfo.RegionID, sp.AbsolutePosition, sp.Lookat); - } + sp.UUID.ToString(), UUID.Zero, sp.Scene.RegionInfo.RegionID, sp.AbsolutePosition, sp.Lookat); } public void OnNewClient(IClientAPI client) @@ -84,16 +82,9 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.GridUser if (client.SceneAgent.IsChildAgent) return; - string userId = client.AgentId.ToString(); - if (client.Scene is Scene) - { - Scene s = (Scene)client.Scene; - userId = s.UserManagementModule.GetUserUUI(client.AgentId); - } - //m_log.DebugFormat("[ACTIVITY DETECTOR]: Detected client logout {0} in {1}", userId, client.Scene.RegionInfo.RegionName); - +// m_log.DebugFormat("[ACTIVITY DETECTOR]: Detected client logout {0} in {1}", client.AgentId, client.Scene.RegionInfo.RegionName); m_GridUserService.LoggedOut( - userId, client.SessionId, client.Scene.RegionInfo.RegionID, + client.AgentId.ToString(), client.SessionId, client.Scene.RegionInfo.RegionID, client.SceneAgent.AbsolutePosition, client.SceneAgent.Lookat); } } diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/RemoteGridUserServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/RemoteGridUserServiceConnector.cs index 04acf67..badb552 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/RemoteGridUserServiceConnector.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/RemoteGridUserServiceConnector.cs @@ -44,9 +44,6 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.GridUser { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - private const int KEEPTIME = 30; // 30 secs - private ExpiringCache m_Infos = new ExpiringCache(); - #region ISharedRegionModule private bool m_Enabled = false; @@ -131,60 +128,23 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.GridUser public bool LoggedOut(string userID, UUID sessionID, UUID region, Vector3 position, Vector3 lookat) { - if (m_Infos.Contains(userID)) - m_Infos.Remove(userID); - return m_RemoteConnector.LoggedOut(userID, sessionID, region, position, lookat); } public bool SetHome(string userID, UUID regionID, Vector3 position, Vector3 lookAt) { - if (m_RemoteConnector.SetHome(userID, regionID, position, lookAt)) - { - // Update the cache too - GridUserInfo info = null; - if (m_Infos.TryGetValue(userID, out info)) - { - info.HomeRegionID = regionID; - info.HomePosition = position; - info.HomeLookAt = lookAt; - } - return true; - } - - return false; + return m_RemoteConnector.SetHome(userID, regionID, position, lookAt); } public bool SetLastPosition(string userID, UUID sessionID, UUID regionID, Vector3 position, Vector3 lookAt) { - if (m_RemoteConnector.SetLastPosition(userID, sessionID, regionID, position, lookAt)) - { - // Update the cache too - GridUserInfo info = null; - if (m_Infos.TryGetValue(userID, out info)) - { - info.LastRegionID = regionID; - info.LastPosition = position; - info.LastLookAt = lookAt; - } - return true; - } - - return false; + return m_RemoteConnector.SetLastPosition(userID, sessionID, regionID, position, lookAt); } public GridUserInfo GetGridUserInfo(string userID) { - GridUserInfo info = null; - if (m_Infos.TryGetValue(userID, out info)) - return info; - - info = m_RemoteConnector.GetGridUserInfo(userID); - - m_Infos.AddOrUpdate(userID, info, KEEPTIME); - - return info; + return m_RemoteConnector.GetGridUserInfo(userID); } public GridUserInfo[] GetGridUserInfo(string[] userID) diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs index 8ed1833..6eb99ea 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs @@ -313,11 +313,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation if (m_scenes.ContainsKey(destination.RegionID)) { -// m_log.DebugFormat( -// "[LOCAL SIMULATION CONNECTOR]: Found region {0} {1} to send AgentUpdate", -// s.RegionInfo.RegionName, destination.RegionHandle); - - Util.FireAndForget(delegate { m_scenes[destination.RegionID].IncomingCloseAgent(id, false); }); + Util.FireAndForget(delegate { m_scenes[destination.RegionID].IncomingCloseAgent(id); }); return true; } //m_log.Debug("[LOCAL COMMS]: region not found in SendCloseAgent"); diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs index ade5e76..619550c 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs @@ -43,7 +43,6 @@ using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Scenes; using OpenSim.Region.Framework.Scenes.Serialization; using OpenSim.Services.Interfaces; -using System.Threading; namespace OpenSim.Region.CoreModules.World.Archiver { @@ -53,30 +52,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver public class ArchiveReadRequest { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - /// - /// Contains data used while dearchiving a single scene. - /// - private class DearchiveContext - { - public Scene Scene { get; set; } - - public List SerialisedSceneObjects { get; set; } - - public List SerialisedParcels { get; set; } - - public List SceneObjects { get; set; } - - public DearchiveContext(Scene scene) - { - Scene = scene; - SerialisedSceneObjects = new List(); - SerialisedParcels = new List(); - SceneObjects = new List(); - } - } - /// /// The maximum major version of OAR that we can read. Minor versions shouldn't need a max number since version /// bumps here should be compatible. @@ -86,10 +62,9 @@ namespace OpenSim.Region.CoreModules.World.Archiver /// /// Has the control file been loaded for this archive? /// - public bool ControlFileLoaded { get; private set; } + public bool ControlFileLoaded { get; private set; } - protected string m_loadPath; - protected Scene m_rootScene; + protected Scene m_scene; protected Stream m_loadStream; protected Guid m_requestId; protected string m_errorMessage; @@ -116,27 +91,16 @@ namespace OpenSim.Region.CoreModules.World.Archiver { if (m_UserMan == null) { - m_UserMan = m_rootScene.RequestModuleInterface(); + m_UserMan = m_scene.RequestModuleInterface(); } return m_UserMan; } } - /// - /// Used to cache lookups for valid groups. - /// - private IDictionary m_validGroupUuids = new Dictionary(); - - private IGroupsModule m_groupsModule; - - private IAssetService m_assetService = null; - - public ArchiveReadRequest(Scene scene, string loadPath, bool merge, bool skipAssets, Guid requestId) { - m_rootScene = scene; + m_scene = scene; - m_loadPath = loadPath; try { m_loadStream = new GZipStream(ArchiveHelpers.GetStream(loadPath), CompressionMode.Decompress); @@ -156,15 +120,11 @@ namespace OpenSim.Region.CoreModules.World.Archiver // Zero can never be a valid user id m_validUserUuids[UUID.Zero] = false; - - m_groupsModule = m_rootScene.RequestModuleInterface(); - m_assetService = m_rootScene.AssetService; } public ArchiveReadRequest(Scene scene, Stream loadStream, bool merge, bool skipAssets, Guid requestId) { - m_rootScene = scene; - m_loadPath = null; + m_scene = scene; m_loadStream = loadStream; m_merge = merge; m_skipAssets = skipAssets; @@ -172,9 +132,6 @@ namespace OpenSim.Region.CoreModules.World.Archiver // Zero can never be a valid user id m_validUserUuids[UUID.Zero] = false; - - m_groupsModule = m_rootScene.RequestModuleInterface(); - m_assetService = m_rootScene.AssetService; } /// @@ -182,25 +139,25 @@ namespace OpenSim.Region.CoreModules.World.Archiver /// public void DearchiveRegion() { + // The same code can handle dearchiving 0.1 and 0.2 OpenSim Archive versions + DearchiveRegion0DotStar(); + } + + private void DearchiveRegion0DotStar() + { int successfulAssetRestores = 0; int failedAssetRestores = 0; + List serialisedSceneObjects = new List(); + List serialisedParcels = new List(); + string filePath = "NONE"; - DearchiveScenesInfo dearchivedScenes; - - // We dearchive all the scenes at once, because the files in the TAR archive might be mixed. - // Therefore, we have to keep track of the dearchive context of all the scenes. - Dictionary sceneContexts = new Dictionary(); - - string fullPath = "NONE"; - TarArchiveReader archive = null; + TarArchiveReader archive = new TarArchiveReader(m_loadStream); byte[] data; TarArchiveReader.TarEntryType entryType; - + try { - FindAndLoadControlFile(out archive, out dearchivedScenes); - - while ((data = archive.ReadEntry(out fullPath, out entryType)) != null) + while ((data = archive.ReadEntry(out filePath, out entryType)) != null) { //m_log.DebugFormat( // "[ARCHIVER]: Successfully read {0} ({1} bytes)", filePath, data.Length); @@ -208,30 +165,9 @@ namespace OpenSim.Region.CoreModules.World.Archiver if (TarArchiveReader.TarEntryType.TYPE_DIRECTORY == entryType) continue; - - // Find the scene that this file belongs to - - Scene scene; - string filePath; - if (!dearchivedScenes.GetRegionFromPath(fullPath, out scene, out filePath)) - continue; // this file belongs to a region that we're not loading - - DearchiveContext sceneContext = null; - if (scene != null) - { - if (!sceneContexts.TryGetValue(scene.RegionInfo.RegionID, out sceneContext)) - { - sceneContext = new DearchiveContext(scene); - sceneContexts.Add(scene.RegionInfo.RegionID, sceneContext); - } - } - - - // Process the file - if (filePath.StartsWith(ArchiveConstants.OBJECTS_PATH)) { - sceneContext.SerialisedSceneObjects.Add(Encoding.UTF8.GetString(data)); + serialisedSceneObjects.Add(Encoding.UTF8.GetString(data)); } else if (filePath.StartsWith(ArchiveConstants.ASSETS_PATH) && !m_skipAssets) { @@ -245,19 +181,19 @@ namespace OpenSim.Region.CoreModules.World.Archiver } else if (!m_merge && filePath.StartsWith(ArchiveConstants.TERRAINS_PATH)) { - LoadTerrain(scene, filePath, data); + LoadTerrain(filePath, data); } else if (!m_merge && filePath.StartsWith(ArchiveConstants.SETTINGS_PATH)) { - LoadRegionSettings(scene, filePath, data, dearchivedScenes); + LoadRegionSettings(filePath, data); } else if (!m_merge && filePath.StartsWith(ArchiveConstants.LANDDATA_PATH)) { - sceneContext.SerialisedParcels.Add(Encoding.UTF8.GetString(data)); + serialisedParcels.Add(Encoding.UTF8.GetString(data)); } else if (filePath == ArchiveConstants.CONTROL_FILE_PATH) { - // Ignore, because we already read the control file + LoadControlFile(filePath, data); } } @@ -265,16 +201,15 @@ namespace OpenSim.Region.CoreModules.World.Archiver } catch (Exception e) { - m_log.Error( - String.Format("[ARCHIVER]: Aborting load with error in archive file {0} ", fullPath), e); + m_log.ErrorFormat( + "[ARCHIVER]: Aborting load with error in archive file {0}. {1}", filePath, e); m_errorMessage += e.ToString(); - m_rootScene.EventManager.TriggerOarFileLoaded(m_requestId, new List(), m_errorMessage); + m_scene.EventManager.TriggerOarFileLoaded(m_requestId, m_errorMessage); return; } finally { - if (archive != null) - archive.Close(); + archive.Close(); } if (!m_skipAssets) @@ -288,143 +223,32 @@ namespace OpenSim.Region.CoreModules.World.Archiver } } - foreach (DearchiveContext sceneContext in sceneContexts.Values) + if (!m_merge) { - m_log.InfoFormat("[ARCHIVER]: Loading region {0}", sceneContext.Scene.RegionInfo.RegionName); - - if (!m_merge) - { - m_log.Info("[ARCHIVER]: Clearing all existing scene objects"); - sceneContext.Scene.DeleteAllSceneObjects(); - } - - try - { - LoadParcels(sceneContext.Scene, sceneContext.SerialisedParcels); - LoadObjects(sceneContext.Scene, sceneContext.SerialisedSceneObjects, sceneContext.SceneObjects); - - // Inform any interested parties that the region has changed. We waited until now so that all - // of the region's objects will be loaded when we send this notification. - IEstateModule estateModule = sceneContext.Scene.RequestModuleInterface(); - if (estateModule != null) - estateModule.TriggerRegionInfoChange(); - } - catch (Exception e) - { - m_log.Error("[ARCHIVER]: Error loading parcels or objects ", e); - m_errorMessage += e.ToString(); - m_rootScene.EventManager.TriggerOarFileLoaded(m_requestId, new List(), m_errorMessage); - return; - } + m_log.Info("[ARCHIVER]: Clearing all existing scene objects"); + m_scene.DeleteAllSceneObjects(); } - // Start the scripts. We delayed this because we want the OAR to finish loading ASAP, so - // that users can enter the scene. If we allow the scripts to start in the loop above - // then they significantly increase the time until the OAR finishes loading. - Util.FireAndForget(delegate(object o) - { - Thread.Sleep(15000); - m_log.Info("[ARCHIVER]: Starting scripts in scene objects"); - - foreach (DearchiveContext sceneContext in sceneContexts.Values) - { - foreach (SceneObjectGroup sceneObject in sceneContext.SceneObjects) - { - sceneObject.CreateScriptInstances(0, false, sceneContext.Scene.DefaultScriptEngine, 0); // StateSource.RegionStart - sceneObject.ResumeScripts(); - } - - sceneContext.SceneObjects.Clear(); - } - }); + LoadParcels(serialisedParcels); + LoadObjects(serialisedSceneObjects); m_log.InfoFormat("[ARCHIVER]: Successfully loaded archive"); - m_rootScene.EventManager.TriggerOarFileLoaded(m_requestId, dearchivedScenes.GetLoadedScenes(), m_errorMessage); - } - - /// - /// Searches through the files in the archive for the control file, and reads it. - /// We must read the control file first, in order to know which regions are available. - /// - /// - /// In most cases the control file *is* first, since that's how we create archives. However, - /// it's possible that someone rewrote the archive externally so we can't rely on this fact. - /// - /// - /// - private void FindAndLoadControlFile(out TarArchiveReader archive, out DearchiveScenesInfo dearchivedScenes) - { - archive = new TarArchiveReader(m_loadStream); - dearchivedScenes = new DearchiveScenesInfo(); - - string filePath; - byte[] data; - TarArchiveReader.TarEntryType entryType; - bool firstFile = true; - - while ((data = archive.ReadEntry(out filePath, out entryType)) != null) - { - if (TarArchiveReader.TarEntryType.TYPE_DIRECTORY == entryType) - continue; - - if (filePath == ArchiveConstants.CONTROL_FILE_PATH) - { - LoadControlFile(filePath, data, dearchivedScenes); - - // Find which scenes are available in the simulator - ArchiveScenesGroup simulatorScenes = new ArchiveScenesGroup(); - SceneManager.Instance.ForEachScene(delegate(Scene scene2) - { - simulatorScenes.AddScene(scene2); - }); - simulatorScenes.CalcSceneLocations(); - dearchivedScenes.SetSimulatorScenes(m_rootScene, simulatorScenes); - - // If the control file wasn't the first file then reset the read pointer - if (!firstFile) - { - m_log.Warn("Control file wasn't the first file in the archive"); - if (m_loadStream.CanSeek) - { - m_loadStream.Seek(0, SeekOrigin.Begin); - } - else if (m_loadPath != null) - { - archive.Close(); - archive = null; - m_loadStream.Close(); - m_loadStream = null; - m_loadStream = new GZipStream(ArchiveHelpers.GetStream(m_loadPath), CompressionMode.Decompress); - archive = new TarArchiveReader(m_loadStream); - } - else - { - // There isn't currently a scenario where this happens, but it's best to add a check just in case - throw new Exception("Error reading archive: control file wasn't the first file, and the input stream doesn't allow seeking"); - } - } - - return; - } - - firstFile = false; - } - - throw new Exception("Control file not found"); + m_scene.EventManager.TriggerOarFileLoaded(m_requestId, m_errorMessage); } /// /// Load serialized scene objects. /// - protected void LoadObjects(Scene scene, List serialisedSceneObjects, List sceneObjects) + /// + protected void LoadObjects(List serialisedSceneObjects) { // Reload serialized prims m_log.InfoFormat("[ARCHIVER]: Loading {0} scene objects. Please wait.", serialisedSceneObjects.Count); - UUID oldTelehubUUID = scene.RegionInfo.RegionSettings.TelehubObject; + UUID oldTelehubUUID = m_scene.RegionInfo.RegionSettings.TelehubObject; - IRegionSerialiserModule serialiser = scene.RequestModuleInterface(); + IRegionSerialiserModule serialiser = m_scene.RequestModuleInterface(); int sceneObjectsLoadedCount = 0; foreach (string serialisedSceneObject in serialisedSceneObjects) @@ -445,7 +269,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver SceneObjectGroup sceneObject = serialiser.DeserializeGroupFromXml2(serialisedSceneObject); - bool isTelehub = (sceneObject.UUID == oldTelehubUUID) && (oldTelehubUUID != UUID.Zero); + bool isTelehub = (sceneObject.UUID == oldTelehubUUID); // For now, give all incoming scene objects new uuids. This will allow scenes to be cloned // on the same region server and multiple examples a single object archive to be imported @@ -455,8 +279,8 @@ namespace OpenSim.Region.CoreModules.World.Archiver if (isTelehub) { // Change the Telehub Object to the new UUID - scene.RegionInfo.RegionSettings.TelehubObject = sceneObject.UUID; - scene.RegionInfo.RegionSettings.Save(); + m_scene.RegionInfo.RegionSettings.TelehubObject = sceneObject.UUID; + m_scene.RegionInfo.RegionSettings.Save(); oldTelehubUUID = UUID.Zero; } @@ -466,20 +290,17 @@ namespace OpenSim.Region.CoreModules.World.Archiver { if (part.CreatorData == null || part.CreatorData == string.Empty) { - if (!ResolveUserUuid(scene, part.CreatorID)) - part.CreatorID = scene.RegionInfo.EstateSettings.EstateOwner; + if (!ResolveUserUuid(part.CreatorID)) + part.CreatorID = m_scene.RegionInfo.EstateSettings.EstateOwner; } if (UserManager != null) UserManager.AddUser(part.CreatorID, part.CreatorData); - if (!ResolveUserUuid(scene, part.OwnerID)) - part.OwnerID = scene.RegionInfo.EstateSettings.EstateOwner; - - if (!ResolveUserUuid(scene, part.LastOwnerID)) - part.LastOwnerID = scene.RegionInfo.EstateSettings.EstateOwner; + if (!ResolveUserUuid(part.OwnerID)) + part.OwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner; - if (!ResolveGroupUuid(part.GroupID)) - part.GroupID = UUID.Zero; + if (!ResolveUserUuid(part.LastOwnerID)) + part.LastOwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner; // And zap any troublesome sit target information // part.SitTargetOrientation = new Quaternion(0, 0, 0, 1); @@ -490,14 +311,14 @@ namespace OpenSim.Region.CoreModules.World.Archiver // being no copy/no mod for everyone lock (part.TaskInventory) { - if (!ResolveUserUuid(scene, part.CreatorID)) - part.CreatorID = scene.RegionInfo.EstateSettings.EstateOwner; + if (!ResolveUserUuid(part.CreatorID)) + part.CreatorID = m_scene.RegionInfo.EstateSettings.EstateOwner; - if (!ResolveUserUuid(scene, part.OwnerID)) - part.OwnerID = scene.RegionInfo.EstateSettings.EstateOwner; + if (!ResolveUserUuid(part.OwnerID)) + part.OwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner; - if (!ResolveUserUuid(scene, part.LastOwnerID)) - part.LastOwnerID = scene.RegionInfo.EstateSettings.EstateOwner; + if (!ResolveUserUuid(part.LastOwnerID)) + part.LastOwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner; // And zap any troublesome sit target information part.SitTargetOrientation = new Quaternion(0, 0, 0, 1); @@ -510,31 +331,26 @@ namespace OpenSim.Region.CoreModules.World.Archiver TaskInventoryDictionary inv = part.TaskInventory; foreach (KeyValuePair kvp in inv) { - if (!ResolveUserUuid(scene, kvp.Value.OwnerID)) + if (!ResolveUserUuid(kvp.Value.OwnerID)) { - kvp.Value.OwnerID = scene.RegionInfo.EstateSettings.EstateOwner; + kvp.Value.OwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner; } - if (kvp.Value.CreatorData == null || kvp.Value.CreatorData == string.Empty) { - if (!ResolveUserUuid(scene, kvp.Value.CreatorID)) - kvp.Value.CreatorID = scene.RegionInfo.EstateSettings.EstateOwner; + if (!ResolveUserUuid(kvp.Value.CreatorID)) + kvp.Value.CreatorID = m_scene.RegionInfo.EstateSettings.EstateOwner; } - if (UserManager != null) UserManager.AddUser(kvp.Value.CreatorID, kvp.Value.CreatorData); - - if (!ResolveGroupUuid(kvp.Value.GroupID)) - kvp.Value.GroupID = UUID.Zero; } part.TaskInventory.LockItemsForRead(false); } } - if (scene.AddRestoredSceneObject(sceneObject, true, false)) + if (m_scene.AddRestoredSceneObject(sceneObject, true, false)) { sceneObjectsLoadedCount++; - sceneObject.CreateScriptInstances(0, false, scene.DefaultScriptEngine, 0); + sceneObject.CreateScriptInstances(0, false, m_scene.DefaultScriptEngine, 0); sceneObject.ResumeScripts(); } } @@ -549,17 +365,16 @@ namespace OpenSim.Region.CoreModules.World.Archiver if (oldTelehubUUID != UUID.Zero) { m_log.WarnFormat("Telehub object not found: {0}", oldTelehubUUID); - scene.RegionInfo.RegionSettings.TelehubObject = UUID.Zero; - scene.RegionInfo.RegionSettings.ClearSpawnPoints(); + m_scene.RegionInfo.RegionSettings.TelehubObject = UUID.Zero; + m_scene.RegionInfo.RegionSettings.ClearSpawnPoints(); } } /// /// Load serialized parcels. /// - /// /// - protected void LoadParcels(Scene scene, List serialisedParcels) + protected void LoadParcels(List serialisedParcels) { // Reload serialized parcels m_log.InfoFormat("[ARCHIVER]: Loading {0} parcels. Please wait.", serialisedParcels.Count); @@ -567,27 +382,9 @@ namespace OpenSim.Region.CoreModules.World.Archiver foreach (string serialisedParcel in serialisedParcels) { LandData parcel = LandDataSerializer.Deserialize(serialisedParcel); + if (!ResolveUserUuid(parcel.OwnerID)) + parcel.OwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner; - // Validate User and Group UUID's - - if (!ResolveUserUuid(scene, parcel.OwnerID)) - parcel.OwnerID = m_rootScene.RegionInfo.EstateSettings.EstateOwner; - - if (!ResolveGroupUuid(parcel.GroupID)) - { - parcel.GroupID = UUID.Zero; - parcel.IsGroupOwned = false; - } - - List accessList = new List(); - foreach (LandAccessEntry entry in parcel.ParcelAccessList) - { - if (ResolveUserUuid(scene, entry.AgentID)) - accessList.Add(entry); - // else, drop this access rule - } - parcel.ParcelAccessList = accessList; - // m_log.DebugFormat( // "[ARCHIVER]: Adding parcel {0}, local id {1}, area {2}", // parcel.Name, parcel.LocalID, parcel.Area); @@ -598,24 +395,23 @@ namespace OpenSim.Region.CoreModules.World.Archiver if (!m_merge) { bool setupDefaultParcel = (landData.Count == 0); - scene.LandChannel.Clear(setupDefaultParcel); + m_scene.LandChannel.Clear(setupDefaultParcel); } - scene.EventManager.TriggerIncomingLandDataFromStorage(landData); + m_scene.EventManager.TriggerIncomingLandDataFromStorage(landData); m_log.InfoFormat("[ARCHIVER]: Restored {0} parcels.", landData.Count); } /// /// Look up the given user id to check whether it's one that is valid for this grid. /// - /// /// /// - private bool ResolveUserUuid(Scene scene, UUID uuid) + private bool ResolveUserUuid(UUID uuid) { if (!m_validUserUuids.ContainsKey(uuid)) { - UserAccount account = scene.UserAccountService.GetUserAccount(scene.RegionInfo.ScopeID, uuid); + UserAccount account = m_scene.UserAccountService.GetUserAccount(m_scene.RegionInfo.ScopeID, uuid); m_validUserUuids.Add(uuid, account != null); } @@ -623,30 +419,6 @@ namespace OpenSim.Region.CoreModules.World.Archiver } /// - /// Look up the given group id to check whether it's one that is valid for this grid. - /// - /// - /// - private bool ResolveGroupUuid(UUID uuid) - { - if (uuid == UUID.Zero) - return true; // this means the object has no group - - if (!m_validGroupUuids.ContainsKey(uuid)) - { - bool exists; - - if (m_groupsModule == null) - exists = false; - else - exists = (m_groupsModule.GetGroupRecord(uuid) != null); - - m_validGroupUuids.Add(uuid, exists); - } - - return m_validGroupUuids[uuid]; - } - /// Load an asset /// /// @@ -670,7 +442,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver string extension = filename.Substring(i); string uuid = filename.Remove(filename.Length - extension.Length); - if (m_assetService.GetMetadata(uuid) != null) + if (m_scene.AssetService.GetMetadata(uuid) != null) { // m_log.DebugFormat("[ARCHIVER]: found existing asset {0}",uuid); return true; @@ -690,7 +462,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver // We're relying on the asset service to do the sensible thing and not store the asset if it already // exists. - m_assetService.Store(asset); + m_scene.AssetService.Store(asset); /** * Create layers on decode for image assets. This is likely to significantly increase the time to load archives so @@ -718,14 +490,12 @@ namespace OpenSim.Region.CoreModules.World.Archiver /// /// Load region settings data /// - /// /// /// - /// /// /// true if settings were loaded successfully, false otherwise /// - private bool LoadRegionSettings(Scene scene, string settingsPath, byte[] data, DearchiveScenesInfo dearchivedScenes) + private bool LoadRegionSettings(string settingsPath, byte[] data) { RegionSettings loadedRegionSettings; @@ -741,7 +511,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver return false; } - RegionSettings currentRegionSettings = scene.RegionInfo.RegionSettings; + RegionSettings currentRegionSettings = m_scene.RegionInfo.RegionSettings; currentRegionSettings.AgentLimit = loadedRegionSettings.AgentLimit; currentRegionSettings.AllowDamage = loadedRegionSettings.AllowDamage; @@ -778,14 +548,12 @@ namespace OpenSim.Region.CoreModules.World.Archiver foreach (SpawnPoint sp in loadedRegionSettings.SpawnPoints()) currentRegionSettings.AddSpawnPoint(sp); - currentRegionSettings.LoadedCreationDateTime = dearchivedScenes.LoadedCreationDateTime; - currentRegionSettings.LoadedCreationID = dearchivedScenes.GetOriginalRegionID(scene.RegionInfo.RegionID).ToString(); - currentRegionSettings.Save(); - scene.TriggerEstateSunUpdate(); + m_scene.TriggerEstateSunUpdate(); - IEstateModule estateModule = scene.RequestModuleInterface(); + IEstateModule estateModule = m_scene.RequestModuleInterface(); + if (estateModule != null) estateModule.sendRegionHandshakeToAll(); @@ -795,15 +563,14 @@ namespace OpenSim.Region.CoreModules.World.Archiver /// /// Load terrain data /// - /// /// /// /// /// true if terrain was resolved successfully, false otherwise. /// - private bool LoadTerrain(Scene scene, string terrainPath, byte[] data) + private bool LoadTerrain(string terrainPath, byte[] data) { - ITerrainModule terrainModule = scene.RequestModuleInterface(); + ITerrainModule terrainModule = m_scene.RequestModuleInterface(); MemoryStream ms = new MemoryStream(data); terrainModule.LoadFromStream(terrainPath, ms); @@ -819,18 +586,17 @@ namespace OpenSim.Region.CoreModules.World.Archiver /// /// /// - /// - public DearchiveScenesInfo LoadControlFile(string path, byte[] data, DearchiveScenesInfo dearchivedScenes) + public void LoadControlFile(string path, byte[] data) { XmlNamespaceManager nsmgr = new XmlNamespaceManager(new NameTable()); XmlParserContext context = new XmlParserContext(null, nsmgr, null, XmlSpace.None); XmlTextReader xtr = new XmlTextReader(Encoding.ASCII.GetString(data), XmlNodeType.Document, context); - // Loaded metadata will be empty if no information exists in the archive - dearchivedScenes.LoadedCreationDateTime = 0; - dearchivedScenes.DefaultOriginalID = ""; + RegionSettings currentRegionSettings = m_scene.RegionInfo.RegionSettings; - bool multiRegion = false; + // Loaded metadata will empty if no information exists in the archive + currentRegionSettings.LoadedCreationDateTime = 0; + currentRegionSettings.LoadedCreationID = ""; while (xtr.Read()) { @@ -856,44 +622,18 @@ namespace OpenSim.Region.CoreModules.World.Archiver { int value; if (Int32.TryParse(xtr.ReadElementContentAsString(), out value)) - dearchivedScenes.LoadedCreationDateTime = value; + currentRegionSettings.LoadedCreationDateTime = value; } - else if (xtr.Name.ToString() == "row") - { - multiRegion = true; - dearchivedScenes.StartRow(); - } - else if (xtr.Name.ToString() == "region") - { - dearchivedScenes.StartRegion(); - } - else if (xtr.Name.ToString() == "id") - { - string id = xtr.ReadElementContentAsString(); - dearchivedScenes.DefaultOriginalID = id; - if (multiRegion) - dearchivedScenes.SetRegionOriginalID(id); - } - else if (xtr.Name.ToString() == "dir") + else if (xtr.Name.ToString() == "id") { - dearchivedScenes.SetRegionDirectory(xtr.ReadElementContentAsString()); + currentRegionSettings.LoadedCreationID = xtr.ReadElementContentAsString(); } } } - - dearchivedScenes.MultiRegionFormat = multiRegion; - if (!multiRegion) - { - // Add the single scene - dearchivedScenes.StartRow(); - dearchivedScenes.StartRegion(); - dearchivedScenes.SetRegionOriginalID(dearchivedScenes.DefaultOriginalID); - dearchivedScenes.SetRegionDirectory(""); - } - + + currentRegionSettings.Save(); + ControlFileLoaded = true; - - return dearchivedScenes; } } -} +} \ No newline at end of file diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveScenesGroup.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveScenesGroup.cs deleted file mode 100644 index d8dace2..0000000 --- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveScenesGroup.cs +++ /dev/null @@ -1,176 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using OpenSim.Region.Framework.Scenes; -using OpenMetaverse; -using System.Drawing; - -namespace OpenSim.Region.CoreModules.World.Archiver -{ - /// - /// A group of regions arranged in a rectangle, possibly with holes. - /// - /// - /// The regions usually (but not necessarily) belong to an archive file, in which case we - /// store additional information used to create the archive (e.g., each region's - /// directory within the archive). - /// - public class ArchiveScenesGroup - { - /// - /// All the regions. The outer dictionary contains rows (key: Y coordinate). - /// The inner dictionaries contain each row's regions (key: X coordinate). - /// - public SortedDictionary> Regions { get; set; } - - /// - /// The subdirectory where each region is stored in the archive. - /// - protected Dictionary m_regionDirs; - - /// - /// The grid coordinates of the regions' bounding box. - /// - public Rectangle Rect { get; set; } - - - public ArchiveScenesGroup() - { - Regions = new SortedDictionary>(); - m_regionDirs = new Dictionary(); - Rect = new Rectangle(0, 0, 0, 0); - } - - public void AddScene(Scene scene) - { - uint x = scene.RegionInfo.RegionLocX; - uint y = scene.RegionInfo.RegionLocY; - - SortedDictionary row; - if (!Regions.TryGetValue(y, out row)) - { - row = new SortedDictionary(); - Regions[y] = row; - } - - row[x] = scene; - } - - /// - /// Called after all the scenes have been added. Performs calculations that require - /// knowledge of all the scenes. - /// - public void CalcSceneLocations() - { - if (Regions.Count == 0) - return; - - // Find the bounding rectangle - - uint firstY = Regions.First().Key; - uint lastY = Regions.Last().Key; - - uint? firstX = null; - uint? lastX = null; - - foreach (SortedDictionary row in Regions.Values) - { - uint curFirstX = row.First().Key; - uint curLastX = row.Last().Key; - - firstX = (firstX == null) ? curFirstX : (firstX < curFirstX) ? firstX : curFirstX; - lastX = (lastX == null) ? curLastX : (lastX > curLastX) ? lastX : curLastX; - } - - Rect = new Rectangle((int)firstX, (int)firstY, (int)(lastX - firstX + 1), (int)(lastY - firstY + 1)); - - - // Calculate the subdirectory in which each region will be stored in the archive - - m_regionDirs.Clear(); - ForEachScene(delegate(Scene scene) - { - // We add the region's coordinates to ensure uniqueness even if multiple regions have the same name - string path = string.Format("{0}_{1}_{2}", - scene.RegionInfo.RegionLocX - Rect.X + 1, - scene.RegionInfo.RegionLocY - Rect.Y + 1, - scene.RegionInfo.RegionName.Replace(' ', '_')); - m_regionDirs[scene.RegionInfo.RegionID] = path; - }); - } - - /// - /// Returns the subdirectory where the region is stored. - /// - /// - /// - public string GetRegionDir(UUID regionID) - { - return m_regionDirs[regionID]; - } - - /// - /// Performs an action on all the scenes in this order: rows from South to North, - /// and within each row West to East. - /// - /// - public void ForEachScene(Action action) - { - foreach (SortedDictionary row in Regions.Values) - { - foreach (Scene scene in row.Values) - { - action(scene); - } - } - } - - /// - /// Returns the scene at position 'location'. - /// - /// A location in the grid - /// The scene at this location - /// Whether the scene was found - public bool TryGetScene(Point location, out Scene scene) - { - SortedDictionary row; - if (Regions.TryGetValue((uint)location.Y, out row)) - { - if (row.TryGetValue((uint)location.X, out scene)) - return true; - } - - scene = null; - return false; - } - - } -} diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequest.cs deleted file mode 100644 index d751b1c..0000000 --- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequest.cs +++ /dev/null @@ -1,634 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.IO; -using System.IO.Compression; -using System.Reflection; -using System.Text.RegularExpressions; -using System.Threading; -using System.Xml; -using log4net; -using OpenMetaverse; -using OpenSim.Framework; -using OpenSim.Framework.Serialization; -using OpenSim.Region.CoreModules.World.Terrain; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; -using Ionic.Zlib; -using GZipStream = Ionic.Zlib.GZipStream; -using CompressionMode = Ionic.Zlib.CompressionMode; -using OpenSim.Framework.Serialization.External; - -namespace OpenSim.Region.CoreModules.World.Archiver -{ - /// - /// Prepare to write out an archive. - /// - public class ArchiveWriteRequest - { - private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - /// - /// The minimum major version of OAR that we can write. - /// - public static int MIN_MAJOR_VERSION = 0; - - /// - /// The maximum major version of OAR that we can write. - /// - public static int MAX_MAJOR_VERSION = 1; - - /// - /// Whether we're saving a multi-region archive. - /// - public bool MultiRegionFormat { get; set; } - - /// - /// Determine whether this archive will save assets. Default is true. - /// - public bool SaveAssets { get; set; } - - /// - /// Determines which objects will be included in the archive, according to their permissions. - /// Default is null, meaning no permission checks. - /// - public string CheckPermissions { get; set; } - - protected Scene m_rootScene; - protected Stream m_saveStream; - protected TarArchiveWriter m_archiveWriter; - protected Guid m_requestId; - protected Dictionary m_options; - - /// - /// Constructor - /// - /// Calling module - /// The path to which to save data. - /// The id associated with this request - /// - /// If there was a problem opening a stream for the file specified by the savePath - /// - public ArchiveWriteRequest(Scene scene, string savePath, Guid requestId) : this(scene, requestId) - { - try - { - m_saveStream = new GZipStream(new FileStream(savePath, FileMode.Create), CompressionMode.Compress, CompressionLevel.BestCompression); - } - catch (EntryPointNotFoundException e) - { - m_log.ErrorFormat( - "[ARCHIVER]: Mismatch between Mono and zlib1g library version when trying to create compression stream." - + "If you've manually installed Mono, have you appropriately updated zlib1g as well?"); - m_log.ErrorFormat("{0} {1}", e.Message, e.StackTrace); - } - } - - /// - /// Constructor. - /// - /// The root scene to archive - /// The stream to which to save data. - /// The id associated with this request - public ArchiveWriteRequest(Scene scene, Stream saveStream, Guid requestId) : this(scene, requestId) - { - m_saveStream = saveStream; - } - - protected ArchiveWriteRequest(Scene scene, Guid requestId) - { - m_rootScene = scene; - m_requestId = requestId; - m_archiveWriter = null; - - MultiRegionFormat = false; - SaveAssets = true; - CheckPermissions = null; - } - - /// - /// Archive the region requested. - /// - /// if there was an io problem with creating the file - public void ArchiveRegion(Dictionary options) - { - m_options = options; - - if (options.ContainsKey("all") && (bool)options["all"]) - MultiRegionFormat = true; - - if (options.ContainsKey("noassets") && (bool)options["noassets"]) - SaveAssets = false; - - Object temp; - if (options.TryGetValue("checkPermissions", out temp)) - CheckPermissions = (string)temp; - - - // Find the regions to archive - ArchiveScenesGroup scenesGroup = new ArchiveScenesGroup(); - if (MultiRegionFormat) - { - m_log.InfoFormat("[ARCHIVER]: Saving {0} regions", SceneManager.Instance.Scenes.Count); - SceneManager.Instance.ForEachScene(delegate(Scene scene) - { - scenesGroup.AddScene(scene); - }); - } - else - { - scenesGroup.AddScene(m_rootScene); - } - scenesGroup.CalcSceneLocations(); - - - m_archiveWriter = new TarArchiveWriter(m_saveStream); - - try - { - // Write out control file. It should be first so that it will be found ASAP when loading the file. - m_archiveWriter.WriteFile(ArchiveConstants.CONTROL_FILE_PATH, CreateControlFile(scenesGroup)); - m_log.InfoFormat("[ARCHIVER]: Added control file to archive."); - - // Archive the regions - - Dictionary assetUuids = new Dictionary(); - - scenesGroup.ForEachScene(delegate(Scene scene) - { - string regionDir = MultiRegionFormat ? scenesGroup.GetRegionDir(scene.RegionInfo.RegionID) : ""; - ArchiveOneRegion(scene, regionDir, assetUuids); - }); - - // Archive the assets - - if (SaveAssets) - { - m_log.DebugFormat("[ARCHIVER]: Saving {0} assets", assetUuids.Count); - - // Asynchronously request all the assets required to perform this archive operation - AssetsRequest ar - = new AssetsRequest( - new AssetsArchiver(m_archiveWriter), assetUuids, - m_rootScene.AssetService, m_rootScene.UserAccountService, - m_rootScene.RegionInfo.ScopeID, options, ReceivedAllAssets); - - Util.FireAndForget(o => ar.Execute()); - - // CloseArchive() will be called from ReceivedAllAssets() - } - else - { - m_log.DebugFormat("[ARCHIVER]: Not saving assets since --noassets was specified"); - CloseArchive(string.Empty); - } - } - catch (Exception e) - { - CloseArchive(e.Message); - throw; - } - } - - - private void ArchiveOneRegion(Scene scene, string regionDir, Dictionary assetUuids) - { - m_log.InfoFormat("[ARCHIVER]: Writing region {0}", scene.RegionInfo.RegionName); - - EntityBase[] entities = scene.GetEntities(); - List sceneObjects = new List(); - - int numObjectsSkippedPermissions = 0; - - // Filter entities so that we only have scene objects. - // FIXME: Would be nicer to have this as a proper list in SceneGraph, since lots of methods - // end up having to do this - IPermissionsModule permissionsModule = scene.RequestModuleInterface(); - foreach (EntityBase entity in entities) - { - if (entity is SceneObjectGroup) - { - SceneObjectGroup sceneObject = (SceneObjectGroup)entity; - - if (!sceneObject.IsDeleted && !sceneObject.IsAttachment) - { - if (!CanUserArchiveObject(scene.RegionInfo.EstateSettings.EstateOwner, sceneObject, CheckPermissions, permissionsModule)) - { - // The user isn't allowed to copy/transfer this object, so it will not be included in the OAR. - ++numObjectsSkippedPermissions; - } - else - { - sceneObjects.Add(sceneObject); - } - } - } - } - - if (SaveAssets) - { - UuidGatherer assetGatherer = new UuidGatherer(scene.AssetService); - int prevAssets = assetUuids.Count; - - foreach (SceneObjectGroup sceneObject in sceneObjects) - { - assetGatherer.GatherAssetUuids(sceneObject, assetUuids); - } - - m_log.DebugFormat( - "[ARCHIVER]: {0} scene objects to serialize requiring save of {1} assets", - sceneObjects.Count, assetUuids.Count - prevAssets); - } - - if (numObjectsSkippedPermissions > 0) - { - m_log.DebugFormat( - "[ARCHIVER]: {0} scene objects skipped due to lack of permissions", - numObjectsSkippedPermissions); - } - - // Make sure that we also request terrain texture assets - RegionSettings regionSettings = scene.RegionInfo.RegionSettings; - - if (regionSettings.TerrainTexture1 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_1) - assetUuids[regionSettings.TerrainTexture1] = AssetType.Texture; - - if (regionSettings.TerrainTexture2 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_2) - assetUuids[regionSettings.TerrainTexture2] = AssetType.Texture; - - if (regionSettings.TerrainTexture3 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_3) - assetUuids[regionSettings.TerrainTexture3] = AssetType.Texture; - - if (regionSettings.TerrainTexture4 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_4) - assetUuids[regionSettings.TerrainTexture4] = AssetType.Texture; - - Save(scene, sceneObjects, regionDir); - } - - /// - /// Checks whether the user has permission to export an object group to an OAR. - /// - /// The user - /// The object group - /// Which permissions to check: "C" = Copy, "T" = Transfer - /// The scene's permissions module - /// Whether the user is allowed to export the object to an OAR - private bool CanUserArchiveObject(UUID user, SceneObjectGroup objGroup, string checkPermissions, IPermissionsModule permissionsModule) - { - if (checkPermissions == null) - return true; - - if (permissionsModule == null) - return true; // this shouldn't happen - - // Check whether the user is permitted to export all of the parts in the SOG. If any - // part can't be exported then the entire SOG can't be exported. - - bool permitted = true; - //int primNumber = 1; - - foreach (SceneObjectPart obj in objGroup.Parts) - { - uint perm; - PermissionClass permissionClass = permissionsModule.GetPermissionClass(user, obj); - switch (permissionClass) - { - case PermissionClass.Owner: - perm = obj.BaseMask; - break; - case PermissionClass.Group: - perm = obj.GroupMask | obj.EveryoneMask; - break; - case PermissionClass.Everyone: - default: - perm = obj.EveryoneMask; - break; - } - - bool canCopy = (perm & (uint)PermissionMask.Copy) != 0; - bool canTransfer = (perm & (uint)PermissionMask.Transfer) != 0; - - // Special case: if Everyone can copy the object then this implies it can also be - // Transferred. - // However, if the user is the Owner then we don't check EveryoneMask, because it seems that the mask - // always (incorrectly) includes the Copy bit set in this case. But that's a mistake: the viewer - // does NOT show that the object has Everyone-Copy permissions, and doesn't allow it to be copied. - if (permissionClass != PermissionClass.Owner) - canTransfer |= (obj.EveryoneMask & (uint)PermissionMask.Copy) != 0; - - bool partPermitted = true; - if (checkPermissions.Contains("C") && !canCopy) - partPermitted = false; - if (checkPermissions.Contains("T") && !canTransfer) - partPermitted = false; - - // If the user is the Creator of the object then it can always be included in the OAR - bool creator = (obj.CreatorID.Guid == user.Guid); - if (creator) - partPermitted = true; - - //string name = (objGroup.PrimCount == 1) ? objGroup.Name : string.Format("{0} ({1}/{2})", obj.Name, primNumber, objGroup.PrimCount); - //m_log.DebugFormat("[ARCHIVER]: Object permissions: {0}: Base={1:X4}, Owner={2:X4}, Everyone={3:X4}, permissionClass={4}, checkPermissions={5}, canCopy={6}, canTransfer={7}, creator={8}, permitted={9}", - // name, obj.BaseMask, obj.OwnerMask, obj.EveryoneMask, - // permissionClass, checkPermissions, canCopy, canTransfer, creator, partPermitted); - - if (!partPermitted) - { - permitted = false; - break; - } - - //++primNumber; - } - - return permitted; - } - - /// - /// Create the control file. - /// - /// - public string CreateControlFile(ArchiveScenesGroup scenesGroup) - { - int majorVersion; - int minorVersion; - - if (MultiRegionFormat) - { - majorVersion = MAX_MAJOR_VERSION; - minorVersion = 0; - } - else - { - // To support older versions of OpenSim, we continue to create single-region OARs - // using the old file format. In the future this format will be discontinued. - majorVersion = 0; - minorVersion = 8; - } -// -// if (m_options.ContainsKey("version")) -// { -// string[] parts = m_options["version"].ToString().Split('.'); -// if (parts.Length >= 1) -// { -// majorVersion = Int32.Parse(parts[0]); -// -// if (parts.Length >= 2) -// minorVersion = Int32.Parse(parts[1]); -// } -// } -// -// if (majorVersion < MIN_MAJOR_VERSION || majorVersion > MAX_MAJOR_VERSION) -// { -// throw new Exception( -// string.Format( -// "OAR version number for save must be between {0} and {1}", -// MIN_MAJOR_VERSION, MAX_MAJOR_VERSION)); -// } -// else if (majorVersion == MAX_MAJOR_VERSION) -// { -// // Force 1.0 -// minorVersion = 0; -// } -// else if (majorVersion == MIN_MAJOR_VERSION) -// { -// // Force 0.4 -// minorVersion = 4; -// } - - m_log.InfoFormat("[ARCHIVER]: Creating version {0}.{1} OAR", majorVersion, minorVersion); - if (majorVersion == 1) - { - m_log.WarnFormat("[ARCHIVER]: Please be aware that version 1.0 OARs are not compatible with OpenSim versions prior to 0.7.4. Do not use the --all option if you want to produce a compatible OAR"); - } - - String s; - - using (StringWriter sw = new StringWriter()) - { - using (XmlTextWriter xtw = new XmlTextWriter(sw)) - { - xtw.Formatting = Formatting.Indented; - xtw.WriteStartDocument(); - xtw.WriteStartElement("archive"); - xtw.WriteAttributeString("major_version", majorVersion.ToString()); - xtw.WriteAttributeString("minor_version", minorVersion.ToString()); - - xtw.WriteStartElement("creation_info"); - DateTime now = DateTime.UtcNow; - TimeSpan t = now - new DateTime(1970, 1, 1); - xtw.WriteElementString("datetime", ((int)t.TotalSeconds).ToString()); - if (!MultiRegionFormat) - xtw.WriteElementString("id", m_rootScene.RegionInfo.RegionID.ToString()); - xtw.WriteEndElement(); - - xtw.WriteElementString("assets_included", SaveAssets.ToString()); - - if (MultiRegionFormat) - { - WriteRegionsManifest(scenesGroup, xtw); - } - else - { - xtw.WriteStartElement("region_info"); - WriteRegionInfo(m_rootScene, xtw); - xtw.WriteEndElement(); - } - - xtw.WriteEndElement(); - - xtw.Flush(); - } - - s = sw.ToString(); - } - - return s; - } - - /// - /// Writes the list of regions included in a multi-region OAR. - /// - private static void WriteRegionsManifest(ArchiveScenesGroup scenesGroup, XmlTextWriter xtw) - { - xtw.WriteStartElement("regions"); - - // Write the regions in order: rows from South to North, then regions from West to East. - // The list of regions can have "holes"; we write empty elements in their position. - - for (uint y = (uint)scenesGroup.Rect.Top; y < scenesGroup.Rect.Bottom; ++y) - { - SortedDictionary row; - if (scenesGroup.Regions.TryGetValue(y, out row)) - { - xtw.WriteStartElement("row"); - - for (uint x = (uint)scenesGroup.Rect.Left; x < scenesGroup.Rect.Right; ++x) - { - Scene scene; - if (row.TryGetValue(x, out scene)) - { - xtw.WriteStartElement("region"); - xtw.WriteElementString("id", scene.RegionInfo.RegionID.ToString()); - xtw.WriteElementString("dir", scenesGroup.GetRegionDir(scene.RegionInfo.RegionID)); - WriteRegionInfo(scene, xtw); - xtw.WriteEndElement(); - } - else - { - // Write a placeholder for a missing region - xtw.WriteElementString("region", ""); - } - } - - xtw.WriteEndElement(); - } - else - { - // Write a placeholder for a missing row - xtw.WriteElementString("row", ""); - } - } - - xtw.WriteEndElement(); // "regions" - } - - protected static void WriteRegionInfo(Scene scene, XmlTextWriter xtw) - { - bool isMegaregion; - Vector2 size; - - IRegionCombinerModule rcMod = scene.RequestModuleInterface(); - - if (rcMod != null) - isMegaregion = rcMod.IsRootForMegaregion(scene.RegionInfo.RegionID); - else - isMegaregion = false; - - if (isMegaregion) - size = rcMod.GetSizeOfMegaregion(scene.RegionInfo.RegionID); - else - size = new Vector2((float)Constants.RegionSize, (float)Constants.RegionSize); - - xtw.WriteElementString("is_megaregion", isMegaregion.ToString()); - xtw.WriteElementString("size_in_meters", string.Format("{0},{1}", size.X, size.Y)); - } - - - protected void Save(Scene scene, List sceneObjects, string regionDir) - { - if (regionDir != string.Empty) - regionDir = ArchiveConstants.REGIONS_PATH + regionDir + "/"; - - m_log.InfoFormat("[ARCHIVER]: Adding region settings to archive."); - - // Write out region settings - string settingsPath = String.Format("{0}{1}{2}.xml", - regionDir, ArchiveConstants.SETTINGS_PATH, scene.RegionInfo.RegionName); - m_archiveWriter.WriteFile(settingsPath, RegionSettingsSerializer.Serialize(scene.RegionInfo.RegionSettings)); - - m_log.InfoFormat("[ARCHIVER]: Adding parcel settings to archive."); - - // Write out land data (aka parcel) settings - List landObjects = scene.LandChannel.AllParcels(); - foreach (ILandObject lo in landObjects) - { - LandData landData = lo.LandData; - string landDataPath = String.Format("{0}{1}{2}.xml", - regionDir, ArchiveConstants.LANDDATA_PATH, landData.GlobalID.ToString()); - m_archiveWriter.WriteFile(landDataPath, LandDataSerializer.Serialize(landData, m_options)); - } - - m_log.InfoFormat("[ARCHIVER]: Adding terrain information to archive."); - - // Write out terrain - string terrainPath = String.Format("{0}{1}{2}.r32", - regionDir, ArchiveConstants.TERRAINS_PATH, scene.RegionInfo.RegionName); - - MemoryStream ms = new MemoryStream(); - scene.RequestModuleInterface().SaveToStream(terrainPath, ms); - m_archiveWriter.WriteFile(terrainPath, ms.ToArray()); - ms.Close(); - - m_log.InfoFormat("[ARCHIVER]: Adding scene objects to archive."); - - // Write out scene object metadata - IRegionSerialiserModule serializer = scene.RequestModuleInterface(); - foreach (SceneObjectGroup sceneObject in sceneObjects) - { - //m_log.DebugFormat("[ARCHIVER]: Saving {0} {1}, {2}", entity.Name, entity.UUID, entity.GetType()); - - string serializedObject = serializer.SerializeGroupToXml2(sceneObject, m_options); - string objectPath = string.Format("{0}{1}", regionDir, ArchiveHelpers.CreateObjectPath(sceneObject)); - m_archiveWriter.WriteFile(objectPath, serializedObject); - } - } - - protected void ReceivedAllAssets( - ICollection assetsFoundUuids, ICollection assetsNotFoundUuids) - { - foreach (UUID uuid in assetsNotFoundUuids) - { - m_log.DebugFormat("[ARCHIVER]: Could not find asset {0}", uuid); - } - - // m_log.InfoFormat( - // "[ARCHIVER]: Received {0} of {1} assets requested", - // assetsFoundUuids.Count, assetsFoundUuids.Count + assetsNotFoundUuids.Count); - - CloseArchive(String.Empty); - } - - - /// - /// Closes the archive and notifies that we're done. - /// - /// The error that occurred, or empty for success - protected void CloseArchive(string errorMessage) - { - try - { - if (m_archiveWriter != null) - m_archiveWriter.Close(); - m_saveStream.Close(); - } - catch (Exception e) - { - m_log.Error(string.Format("[ARCHIVER]: Error closing archive: {0} ", e.Message), e); - if (errorMessage == string.Empty) - errorMessage = e.Message; - } - - m_log.InfoFormat("[ARCHIVER]: Finished writing out OAR for {0}", m_rootScene.RegionInfo.RegionName); - - m_rootScene.EventManager.TriggerOarFileSaved(m_requestId, errorMessage); - } - - } -} diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestExecution.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestExecution.cs new file mode 100644 index 0000000..0780d86 --- /dev/null +++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestExecution.cs @@ -0,0 +1,153 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections.Generic; +using System.IO; +using System.Reflection; +using System.Xml; +using log4net; +using OpenMetaverse; +using OpenSim.Framework; +using OpenSim.Framework.Serialization; +using OpenSim.Framework.Serialization.External; +using OpenSim.Region.CoreModules.World.Terrain; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; + +namespace OpenSim.Region.CoreModules.World.Archiver +{ + /// + /// Method called when all the necessary assets for an archive request have been received. + /// + public delegate void AssetsRequestCallback( + ICollection assetsFoundUuids, ICollection assetsNotFoundUuids); + + /// + /// Execute the write of an archive once we have received all the necessary data + /// + public class ArchiveWriteRequestExecution + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + protected ITerrainModule m_terrainModule; + protected IRegionSerialiserModule m_serialiser; + protected List m_sceneObjects; + protected Scene m_scene; + protected TarArchiveWriter m_archiveWriter; + protected Guid m_requestId; + protected Dictionary m_options; + + public ArchiveWriteRequestExecution( + List sceneObjects, + ITerrainModule terrainModule, + IRegionSerialiserModule serialiser, + Scene scene, + TarArchiveWriter archiveWriter, + Guid requestId, + Dictionary options) + { + m_sceneObjects = sceneObjects; + m_terrainModule = terrainModule; + m_serialiser = serialiser; + m_scene = scene; + m_archiveWriter = archiveWriter; + m_requestId = requestId; + m_options = options; + } + + protected internal void ReceivedAllAssets( + ICollection assetsFoundUuids, ICollection assetsNotFoundUuids) + { + try + { + Save(assetsFoundUuids, assetsNotFoundUuids); + } + finally + { + m_archiveWriter.Close(); + } + + m_log.InfoFormat("[ARCHIVER]: Finished writing out OAR for {0}", m_scene.RegionInfo.RegionName); + + m_scene.EventManager.TriggerOarFileSaved(m_requestId, String.Empty); + } + + protected internal void Save(ICollection assetsFoundUuids, ICollection assetsNotFoundUuids) + { + foreach (UUID uuid in assetsNotFoundUuids) + { + m_log.DebugFormat("[ARCHIVER]: Could not find asset {0}", uuid); + } + +// m_log.InfoFormat( +// "[ARCHIVER]: Received {0} of {1} assets requested", +// assetsFoundUuids.Count, assetsFoundUuids.Count + assetsNotFoundUuids.Count); + + m_log.InfoFormat("[ARCHIVER]: Adding region settings to archive."); + + // Write out region settings + string settingsPath + = String.Format("{0}{1}.xml", ArchiveConstants.SETTINGS_PATH, m_scene.RegionInfo.RegionName); + m_archiveWriter.WriteFile(settingsPath, RegionSettingsSerializer.Serialize(m_scene.RegionInfo.RegionSettings)); + + m_log.InfoFormat("[ARCHIVER]: Adding parcel settings to archive."); + + // Write out land data (aka parcel) settings + ListlandObjects = m_scene.LandChannel.AllParcels(); + foreach (ILandObject lo in landObjects) + { + LandData landData = lo.LandData; + string landDataPath = String.Format("{0}{1}.xml", ArchiveConstants.LANDDATA_PATH, + landData.GlobalID.ToString()); + m_archiveWriter.WriteFile(landDataPath, LandDataSerializer.Serialize(landData, m_options)); + } + + m_log.InfoFormat("[ARCHIVER]: Adding terrain information to archive."); + + // Write out terrain + string terrainPath + = String.Format("{0}{1}.r32", ArchiveConstants.TERRAINS_PATH, m_scene.RegionInfo.RegionName); + + MemoryStream ms = new MemoryStream(); + m_terrainModule.SaveToStream(terrainPath, ms); + m_archiveWriter.WriteFile(terrainPath, ms.ToArray()); + ms.Close(); + + m_log.InfoFormat("[ARCHIVER]: Adding scene objects to archive."); + + // Write out scene object metadata + foreach (SceneObjectGroup sceneObject in m_sceneObjects) + { + //m_log.DebugFormat("[ARCHIVER]: Saving {0} {1}, {2}", entity.Name, entity.UUID, entity.GetType()); + + string serializedObject = m_serialiser.SerializeGroupToXml2(sceneObject, m_options); + m_archiveWriter.WriteFile(ArchiveHelpers.CreateObjectPath(sceneObject), serializedObject); + } + } + } +} \ No newline at end of file diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestPreparation.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestPreparation.cs new file mode 100644 index 0000000..4edaaca --- /dev/null +++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestPreparation.cs @@ -0,0 +1,438 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections.Generic; +using System.IO; +using System.IO.Compression; +using System.Reflection; +using System.Text.RegularExpressions; +using System.Threading; +using System.Xml; +using log4net; +using OpenMetaverse; +using OpenSim.Framework; +using OpenSim.Framework.Serialization; +using OpenSim.Region.CoreModules.World.Terrain; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; +using Ionic.Zlib; +using GZipStream = Ionic.Zlib.GZipStream; +using CompressionMode = Ionic.Zlib.CompressionMode; + +namespace OpenSim.Region.CoreModules.World.Archiver +{ + /// + /// Prepare to write out an archive. + /// + public class ArchiveWriteRequestPreparation + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + /// + /// The minimum major version of OAR that we can write. + /// + public static int MIN_MAJOR_VERSION = 0; + + /// + /// The maximum major version of OAR that we can write. + /// + public static int MAX_MAJOR_VERSION = 0; + + /// + /// Determine whether this archive will save assets. Default is true. + /// + public bool SaveAssets { get; set; } + + protected ArchiverModule m_module; + protected Scene m_scene; + protected Stream m_saveStream; + protected Guid m_requestId; + + /// + /// Constructor + /// + /// Calling module + /// The path to which to save data. + /// The id associated with this request + /// + /// If there was a problem opening a stream for the file specified by the savePath + /// + public ArchiveWriteRequestPreparation(ArchiverModule module, string savePath, Guid requestId) : this(module, requestId) + { + try + { + m_saveStream = new GZipStream(new FileStream(savePath, FileMode.Create), CompressionMode.Compress, CompressionLevel.BestCompression); + } + catch (EntryPointNotFoundException e) + { + m_log.ErrorFormat( + "[ARCHIVER]: Mismatch between Mono and zlib1g library version when trying to create compression stream." + + "If you've manually installed Mono, have you appropriately updated zlib1g as well?"); + m_log.ErrorFormat("{0} {1}", e.Message, e.StackTrace); + } + } + + /// + /// Constructor. + /// + /// Calling module + /// The stream to which to save data. + /// The id associated with this request + public ArchiveWriteRequestPreparation(ArchiverModule module, Stream saveStream, Guid requestId) : this(module, requestId) + { + m_saveStream = saveStream; + } + + protected ArchiveWriteRequestPreparation(ArchiverModule module, Guid requestId) + { + m_module = module; + + // FIXME: This is only here for regression test purposes since they do not supply a module. Need to fix + // this. + if (m_module != null) + m_scene = m_module.Scene; + + m_requestId = requestId; + + SaveAssets = true; + } + + /// + /// Archive the region requested. + /// + /// if there was an io problem with creating the file + public void ArchiveRegion(Dictionary options) + { + if (options.ContainsKey("noassets") && (bool)options["noassets"]) + SaveAssets = false; + + try + { + Dictionary assetUuids = new Dictionary(); + + EntityBase[] entities = m_scene.GetEntities(); + List sceneObjects = new List(); + + string checkPermissions = null; + int numObjectsSkippedPermissions = 0; + Object temp; + if (options.TryGetValue("checkPermissions", out temp)) + checkPermissions = (string)temp; + + // Filter entities so that we only have scene objects. + // FIXME: Would be nicer to have this as a proper list in SceneGraph, since lots of methods + // end up having to do this + foreach (EntityBase entity in entities) + { + if (entity is SceneObjectGroup) + { + SceneObjectGroup sceneObject = (SceneObjectGroup)entity; + + if (!sceneObject.IsDeleted && !sceneObject.IsAttachment) + { + if (!CanUserArchiveObject(m_scene.RegionInfo.EstateSettings.EstateOwner, sceneObject, checkPermissions)) + { + // The user isn't allowed to copy/transfer this object, so it will not be included in the OAR. + ++numObjectsSkippedPermissions; + } + else + { + sceneObjects.Add(sceneObject); + } + } + } + } + + if (SaveAssets) + { + UuidGatherer assetGatherer = new UuidGatherer(m_scene.AssetService); + + foreach (SceneObjectGroup sceneObject in sceneObjects) + { + assetGatherer.GatherAssetUuids(sceneObject, assetUuids); + } + + m_log.DebugFormat( + "[ARCHIVER]: {0} scene objects to serialize requiring save of {1} assets", + sceneObjects.Count, assetUuids.Count); + } + else + { + m_log.DebugFormat("[ARCHIVER]: Not saving assets since --noassets was specified"); + } + + if (numObjectsSkippedPermissions > 0) + { + m_log.DebugFormat( + "[ARCHIVER]: {0} scene objects skipped due to lack of permissions", + numObjectsSkippedPermissions); + } + + // Make sure that we also request terrain texture assets + RegionSettings regionSettings = m_scene.RegionInfo.RegionSettings; + + if (regionSettings.TerrainTexture1 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_1) + assetUuids[regionSettings.TerrainTexture1] = AssetType.Texture; + + if (regionSettings.TerrainTexture2 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_2) + assetUuids[regionSettings.TerrainTexture2] = AssetType.Texture; + + if (regionSettings.TerrainTexture3 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_3) + assetUuids[regionSettings.TerrainTexture3] = AssetType.Texture; + + if (regionSettings.TerrainTexture4 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_4) + assetUuids[regionSettings.TerrainTexture4] = AssetType.Texture; + + TarArchiveWriter archiveWriter = new TarArchiveWriter(m_saveStream); + + // Asynchronously request all the assets required to perform this archive operation + ArchiveWriteRequestExecution awre + = new ArchiveWriteRequestExecution( + sceneObjects, + m_scene.RequestModuleInterface(), + m_scene.RequestModuleInterface(), + m_scene, + archiveWriter, + m_requestId, + options); + + m_log.InfoFormat("[ARCHIVER]: Creating archive file. This may take some time."); + + // Write out control file. This has to be done first so that subsequent loaders will see this file first + // XXX: I know this is a weak way of doing it since external non-OAR aware tar executables will not do this + archiveWriter.WriteFile(ArchiveConstants.CONTROL_FILE_PATH, CreateControlFile(options)); + m_log.InfoFormat("[ARCHIVER]: Added control file to archive."); + + if (SaveAssets) + { + AssetsRequest ar + = new AssetsRequest( + new AssetsArchiver(archiveWriter), assetUuids, + m_scene.AssetService, m_scene.UserAccountService, + m_scene.RegionInfo.ScopeID, options, awre.ReceivedAllAssets); + + Util.FireAndForget(o => ar.Execute()); + } + else + { + awre.ReceivedAllAssets(new List(), new List()); + } + } + catch (Exception) + { + m_saveStream.Close(); + throw; + } + } + + /// + /// Checks whether the user has permission to export an object group to an OAR. + /// + /// The user + /// The object group + /// Which permissions to check: "C" = Copy, "T" = Transfer + /// Whether the user is allowed to export the object to an OAR + private bool CanUserArchiveObject(UUID user, SceneObjectGroup objGroup, string checkPermissions) + { + if (checkPermissions == null) + return true; + + IPermissionsModule module = m_scene.RequestModuleInterface(); + if (module == null) + return true; // this shouldn't happen + + // Check whether the user is permitted to export all of the parts in the SOG. If any + // part can't be exported then the entire SOG can't be exported. + + bool permitted = true; + //int primNumber = 1; + + foreach (SceneObjectPart obj in objGroup.Parts) + { + uint perm; + PermissionClass permissionClass = module.GetPermissionClass(user, obj); + switch (permissionClass) + { + case PermissionClass.Owner: + perm = obj.BaseMask; + break; + case PermissionClass.Group: + perm = obj.GroupMask | obj.EveryoneMask; + break; + case PermissionClass.Everyone: + default: + perm = obj.EveryoneMask; + break; + } + + bool canCopy = (perm & (uint)PermissionMask.Copy) != 0; + bool canTransfer = (perm & (uint)PermissionMask.Transfer) != 0; + + // Special case: if Everyone can copy the object then this implies it can also be + // Transferred. + // However, if the user is the Owner then we don't check EveryoneMask, because it seems that the mask + // always (incorrectly) includes the Copy bit set in this case. But that's a mistake: the viewer + // does NOT show that the object has Everyone-Copy permissions, and doesn't allow it to be copied. + if (permissionClass != PermissionClass.Owner) + canTransfer |= (obj.EveryoneMask & (uint)PermissionMask.Copy) != 0; + + bool partPermitted = true; + if (checkPermissions.Contains("C") && !canCopy) + partPermitted = false; + if (checkPermissions.Contains("T") && !canTransfer) + partPermitted = false; + + // If the user is the Creator of the object then it can always be included in the OAR + bool creator = (obj.CreatorID.Guid == user.Guid); + if (creator) + partPermitted = true; + + //string name = (objGroup.PrimCount == 1) ? objGroup.Name : string.Format("{0} ({1}/{2})", obj.Name, primNumber, objGroup.PrimCount); + //m_log.DebugFormat("[ARCHIVER]: Object permissions: {0}: Base={1:X4}, Owner={2:X4}, Everyone={3:X4}, permissionClass={4}, checkPermissions={5}, canCopy={6}, canTransfer={7}, creator={8}, permitted={9}", + // name, obj.BaseMask, obj.OwnerMask, obj.EveryoneMask, + // permissionClass, checkPermissions, canCopy, canTransfer, creator, partPermitted); + + if (!partPermitted) + { + permitted = false; + break; + } + + //++primNumber; + } + + return permitted; + } + + /// + /// Create the control file for the most up to date archive + /// + /// + public string CreateControlFile(Dictionary options) + { + int majorVersion = MAX_MAJOR_VERSION, minorVersion = 8; +// +// if (options.ContainsKey("version")) +// { +// string[] parts = options["version"].ToString().Split('.'); +// if (parts.Length >= 1) +// { +// majorVersion = Int32.Parse(parts[0]); +// +// if (parts.Length >= 2) +// minorVersion = Int32.Parse(parts[1]); +// } +// } +// +// if (majorVersion < MIN_MAJOR_VERSION || majorVersion > MAX_MAJOR_VERSION) +// { +// throw new Exception( +// string.Format( +// "OAR version number for save must be between {0} and {1}", +// MIN_MAJOR_VERSION, MAX_MAJOR_VERSION)); +// } +// else if (majorVersion == MAX_MAJOR_VERSION) +// { +// // Force 1.0 +// minorVersion = 0; +// } +// else if (majorVersion == MIN_MAJOR_VERSION) +// { +// // Force 0.4 +// minorVersion = 4; +// } + + m_log.InfoFormat("[ARCHIVER]: Creating version {0}.{1} OAR", majorVersion, minorVersion); + //if (majorVersion == 1) + //{ + // m_log.WarnFormat("[ARCHIVER]: Please be aware that version 1.0 OARs are not compatible with OpenSim 0.7.0.2 and earlier. Please use the --version=0 option if you want to produce a compatible OAR"); + //} + + String s; + + using (StringWriter sw = new StringWriter()) + { + using (XmlTextWriter xtw = new XmlTextWriter(sw)) + { + xtw.Formatting = Formatting.Indented; + xtw.WriteStartDocument(); + xtw.WriteStartElement("archive"); + xtw.WriteAttributeString("major_version", majorVersion.ToString()); + xtw.WriteAttributeString("minor_version", minorVersion.ToString()); + + xtw.WriteStartElement("creation_info"); + DateTime now = DateTime.UtcNow; + TimeSpan t = now - new DateTime(1970, 1, 1); + xtw.WriteElementString("datetime", ((int)t.TotalSeconds).ToString()); + xtw.WriteElementString("id", UUID.Random().ToString()); + xtw.WriteEndElement(); + + xtw.WriteStartElement("region_info"); + + bool isMegaregion; + Vector2 size; + IRegionCombinerModule rcMod = null; + + // FIXME: This is only here for regression test purposes since they do not supply a module. Need to fix + // this, possibly by doing control file creation somewhere else. + if (m_module != null) + rcMod = m_module.RegionCombinerModule; + + if (rcMod != null) + isMegaregion = rcMod.IsRootForMegaregion(m_scene.RegionInfo.RegionID); + else + isMegaregion = false; + + if (isMegaregion) + size = rcMod.GetSizeOfMegaregion(m_scene.RegionInfo.RegionID); + else + size = new Vector2((float)Constants.RegionSize, (float)Constants.RegionSize); + + xtw.WriteElementString("is_megaregion", isMegaregion.ToString()); + xtw.WriteElementString("size_in_meters", string.Format("{0},{1}", size.X, size.Y)); + + xtw.WriteEndElement(); + + xtw.WriteElementString("assets_included", SaveAssets.ToString()); + + xtw.WriteEndElement(); + + xtw.Flush(); + } + + s = sw.ToString(); + } + +// if (m_scene != null) +// Console.WriteLine( +// "[ARCHIVE WRITE REQUEST PREPARATION]: Control file for {0} is: {1}", m_scene.RegionInfo.RegionName, s); + + return s; + } + } +} diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiverModule.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiverModule.cs index abf3713..bf3b124 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/ArchiverModule.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiverModule.cs @@ -32,8 +32,6 @@ using System.Reflection; using log4net; using NDesk.Options; using Nini.Config; -using OpenSim.Framework; -using OpenSim.Framework.Console; using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Scenes; @@ -119,7 +117,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver // // foreach (string param in mainParams) // m_log.DebugFormat("GOT PARAM [{0}]", param); - + if (mainParams.Count > 2) { DearchiveRegion(mainParams[2], mergeOar, skipAssets, Guid.Empty); @@ -148,22 +146,17 @@ namespace OpenSim.Region.CoreModules.World.Archiver ops.Add("noassets", delegate(string v) { options["noassets"] = v != null; }); ops.Add("publish", v => options["wipe-owners"] = v != null); ops.Add("perm=", delegate(string v) { options["checkPermissions"] = v; }); - ops.Add("all", delegate(string v) { options["all"] = v != null; }); List mainParams = ops.Parse(cmdparams); - string path; if (mainParams.Count > 2) - path = mainParams[2]; + { + ArchiveRegion(mainParams[2], options); + } else - path = DEFAULT_OAR_BACKUP_FILENAME; - - // Not doing this right now as this causes some problems with auto-backup systems. Maybe a force flag is - // needed -// if (!ConsoleUtil.CheckFileDoesNotExist(MainConsole.Instance, path)) -// return; - - ArchiveRegion(path, options); + { + ArchiveRegion(DEFAULT_OAR_BACKUP_FILENAME, options); + } } public void ArchiveRegion(string savePath, Dictionary options) @@ -176,7 +169,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver m_log.InfoFormat( "[ARCHIVER]: Writing archive for region {0} to {1}", Scene.RegionInfo.RegionName, savePath); - new ArchiveWriteRequest(Scene, savePath, requestId).ArchiveRegion(options); + new ArchiveWriteRequestPreparation(this, savePath, requestId).ArchiveRegion(options); } public void ArchiveRegion(Stream saveStream) @@ -191,7 +184,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver public void ArchiveRegion(Stream saveStream, Guid requestId, Dictionary options) { - new ArchiveWriteRequest(Scene, saveStream, requestId).ArchiveRegion(options); + new ArchiveWriteRequestPreparation(this, saveStream, requestId).ArchiveRegion(options); } public void DearchiveRegion(string loadPath) diff --git a/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs index e2f8833..89e9593 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs @@ -46,12 +46,6 @@ namespace OpenSim.Region.CoreModules.World.Archiver { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - /// - /// Method called when all the necessary assets for an archive request have been received. - /// - public delegate void AssetsRequestCallback( - ICollection assetsFoundUuids, ICollection assetsNotFoundUuids); - enum RequestState { Initial, @@ -129,10 +123,6 @@ namespace OpenSim.Region.CoreModules.World.Archiver m_options = options; m_repliesRequired = uuids.Count; - // FIXME: This is a really poor way of handling the timeout since it will always leave the original requesting thread - // hanging. Need to restructure so an original request thread waits for a ManualResetEvent on asset received - // so we can properly abort that thread. Or request all assets synchronously, though that would be a more - // radical change m_requestCallbackTimer = new System.Timers.Timer(TIMEOUT); m_requestCallbackTimer.AutoReset = false; m_requestCallbackTimer.Elapsed += new ElapsedEventHandler(OnRequestCallbackTimeout); diff --git a/OpenSim/Region/CoreModules/World/Archiver/DearchiveScenesGroup.cs b/OpenSim/Region/CoreModules/World/Archiver/DearchiveScenesGroup.cs deleted file mode 100644 index 3dcc020..0000000 --- a/OpenSim/Region/CoreModules/World/Archiver/DearchiveScenesGroup.cs +++ /dev/null @@ -1,232 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using OpenSim.Region.Framework.Scenes; -using OpenMetaverse; -using System.Drawing; -using log4net; -using System.Reflection; -using OpenSim.Framework.Serialization; - -namespace OpenSim.Region.CoreModules.World.Archiver -{ - /// - /// The regions included in an OAR file. - /// - public class DearchiveScenesInfo - { - private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - /// - /// One region in the archive. - /// - public class RegionInfo - { - /// - /// The subdirectory in which the region is stored. - /// - public string Directory { get; set; } - - /// - /// The region's coordinates (relative to the South-West corner of the block). - /// - public Point Location { get; set; } - - /// - /// The UUID of the original scene from which this archived region was saved. - /// - public string OriginalID { get; set; } - - /// - /// The scene in the current simulator into which this region is loaded. - /// If null then the region doesn't have a corresponding scene, and it won't be loaded. - /// - public Scene Scene { get; set; } - } - - /// - /// Whether this archive uses the multi-region format. - /// - public Boolean MultiRegionFormat { get; set; } - - /// - /// Maps (Region directory -> region) - /// - protected Dictionary m_directory2region = new Dictionary(); - - /// - /// Maps (UUID of the scene in the simulator where the region will be loaded -> region) - /// - protected Dictionary m_newId2region = new Dictionary(); - - public int LoadedCreationDateTime { get; set; } - public string DefaultOriginalID { get; set; } - - // These variables are used while reading the archive control file - protected int? m_curY = null; - protected int? m_curX = null; - protected RegionInfo m_curRegion; - - - public DearchiveScenesInfo() - { - MultiRegionFormat = false; - } - - - // The following methods are used while reading the archive control file - - public void StartRow() - { - m_curY = (m_curY == null) ? 0 : m_curY + 1; - m_curX = null; - } - - public void StartRegion() - { - m_curX = (m_curX == null) ? 0 : m_curX + 1; - // Note: this doesn't mean we have a real region in this location; this could just be a "hole" - } - - public void SetRegionOriginalID(string id) - { - m_curRegion = new RegionInfo(); - m_curRegion.Location = new Point((int)m_curX, (int)m_curY); - m_curRegion.OriginalID = id; - // 'curRegion' will be saved in 'm_directory2region' when SetRegionDir() is called - } - - public void SetRegionDirectory(string directory) - { - m_curRegion.Directory = directory; - m_directory2region[directory] = m_curRegion; - } - - - /// - /// Sets all the scenes present in the simulator. - /// - /// - /// This method matches regions in the archive to scenes in the simulator according to - /// their relative position. We only load regions if there's an existing Scene in the - /// grid location where the region should be loaded. - /// - /// The scene where the Load OAR operation was run - /// All the scenes in the simulator - public void SetSimulatorScenes(Scene rootScene, ArchiveScenesGroup simulatorScenes) - { - foreach (RegionInfo archivedRegion in m_directory2region.Values) - { - Point location = new Point((int)rootScene.RegionInfo.RegionLocX, (int)rootScene.RegionInfo.RegionLocY); - location.Offset(archivedRegion.Location); - - Scene scene; - if (simulatorScenes.TryGetScene(location, out scene)) - { - archivedRegion.Scene = scene; - m_newId2region[scene.RegionInfo.RegionID] = archivedRegion; - } - else - { - m_log.WarnFormat("[ARCHIVER]: Not loading archived region {0} because there's no existing region at location {1},{2}", - archivedRegion.Directory, location.X, location.Y); - } - } - } - - /// - /// Returns the archived region according to the path of a file in the archive. - /// Also, converts the full path into a path that is relative to the region's directory. - /// - /// The path of a file in the archive - /// The corresponding Scene, or null if none - /// The path relative to the region's directory. (Or the original - /// path, if this file doesn't belong to a region.) - /// True: use this file; False: skip it - public bool GetRegionFromPath(string fullPath, out Scene scene, out string relativePath) - { - scene = null; - relativePath = fullPath; - - if (!MultiRegionFormat) - { - if (m_newId2region.Count > 0) - scene = m_newId2region.First().Value.Scene; - return true; - } - - if (!fullPath.StartsWith(ArchiveConstants.REGIONS_PATH)) - return true; // this file doesn't belong to a region - - string[] parts = fullPath.Split(new Char[] { '/' }, 3); - if (parts.Length != 3) - return false; - string regionDirectory = parts[1]; - relativePath = parts[2]; - - RegionInfo region; - if (m_directory2region.TryGetValue(regionDirectory, out region)) - { - scene = region.Scene; - return (scene != null); - } - else - { - return false; - } - } - - /// - /// Returns the original UUID of a region (from the simulator where the OAR was saved), - /// given the UUID of the scene it was loaded into in the current simulator. - /// - /// - /// - public string GetOriginalRegionID(UUID newID) - { - RegionInfo region; - if (m_newId2region.TryGetValue(newID, out region)) - return region.OriginalID; - else - return DefaultOriginalID; - } - - /// - /// Returns the scenes that have been (or will be) loaded. - /// - /// - public List GetLoadedScenes() - { - return m_newId2region.Keys.ToList(); - } - - } -} diff --git a/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs b/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs index 82f49b0..5deaf52 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs @@ -47,41 +47,32 @@ using ArchiveConstants = OpenSim.Framework.Serialization.ArchiveConstants; using TarArchiveReader = OpenSim.Framework.Serialization.TarArchiveReader; using TarArchiveWriter = OpenSim.Framework.Serialization.TarArchiveWriter; using RegionSettings = OpenSim.Framework.RegionSettings; -using OpenSim.Region.Framework.Interfaces; namespace OpenSim.Region.CoreModules.World.Archiver.Tests { [TestFixture] - public class ArchiverTests : OpenSimTestCase + public class ArchiverTests { private Guid m_lastRequestId; private string m_lastErrorMessage; - protected SceneHelpers m_sceneHelpers; protected TestScene m_scene; protected ArchiverModule m_archiverModule; - protected SerialiserModule m_serialiserModule; protected TaskInventoryItem m_soundItem; [SetUp] - public override void SetUp() + public void SetUp() { - base.SetUp(); - - // FIXME: Do something about this - relying on statics in unit tests causes trouble sooner or later - new SceneManager(); - m_archiverModule = new ArchiverModule(); - m_serialiserModule = new SerialiserModule(); + SerialiserModule serialiserModule = new SerialiserModule(); TerrainModule terrainModule = new TerrainModule(); - m_sceneHelpers = new SceneHelpers(); - m_scene = m_sceneHelpers.SetupScene(); - SceneHelpers.SetupSceneModules(m_scene, m_archiverModule, m_serialiserModule, terrainModule); + m_scene = new SceneHelpers().SetupScene(); + SceneHelpers.SetupSceneModules(m_scene, m_archiverModule, serialiserModule, terrainModule); } - - private void LoadCompleted(Guid requestId, List loadedScenes, string errorMessage) + + private void LoadCompleted(Guid requestId, string errorMessage) { lock (this) { @@ -137,10 +128,26 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests TestHelpers.InMethod(); // log4net.Config.XmlConfigurator.Configure(); - SceneObjectGroup sog1; - SceneObjectGroup sog2; - UUID ncAssetUuid; - CreateTestObjects(m_scene, out sog1, out sog2, out ncAssetUuid); + SceneObjectPart part1 = CreateSceneObjectPart1(); + SceneObjectGroup sog1 = new SceneObjectGroup(part1); + m_scene.AddNewSceneObject(sog1, false); + + SceneObjectPart part2 = CreateSceneObjectPart2(); + + AssetNotecard nc = new AssetNotecard(); + nc.BodyText = "Hello World!"; + nc.Encode(); + UUID ncAssetUuid = new UUID("00000000-0000-0000-1000-000000000000"); + UUID ncItemUuid = new UUID("00000000-0000-0000-1100-000000000000"); + AssetBase ncAsset + = AssetHelpers.CreateAsset(ncAssetUuid, AssetType.Notecard, nc.AssetData, UUID.Zero); + m_scene.AssetService.Store(ncAsset); + SceneObjectGroup sog2 = new SceneObjectGroup(part2); + TaskInventoryItem ncItem + = new TaskInventoryItem { Name = "ncItem", AssetID = ncAssetUuid, ItemID = ncItemUuid }; + part2.Inventory.AddInventoryItem(ncItem, true); + + m_scene.AddNewSceneObject(sog2, false); MemoryStream archiveWriteStream = new MemoryStream(); m_scene.EventManager.OnOarFileSaved += SaveCompleted; @@ -179,7 +186,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests Assert.That(filePath, Is.EqualTo(ArchiveConstants.CONTROL_FILE_PATH)); ArchiveReadRequest arr = new ArchiveReadRequest(m_scene, (Stream)null, false, false, Guid.Empty); - arr.LoadControlFile(filePath, data, new DearchiveScenesInfo()); + arr.LoadControlFile(filePath, data); Assert.That(arr.ControlFileLoaded, Is.True); @@ -204,30 +211,6 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests // TODO: Test presence of more files and contents of files. } - private void CreateTestObjects(Scene scene, out SceneObjectGroup sog1, out SceneObjectGroup sog2, out UUID ncAssetUuid) - { - SceneObjectPart part1 = CreateSceneObjectPart1(); - sog1 = new SceneObjectGroup(part1); - scene.AddNewSceneObject(sog1, false); - - AssetNotecard nc = new AssetNotecard(); - nc.BodyText = "Hello World!"; - nc.Encode(); - ncAssetUuid = UUID.Random(); - UUID ncItemUuid = UUID.Random(); - AssetBase ncAsset - = AssetHelpers.CreateAsset(ncAssetUuid, AssetType.Notecard, nc.AssetData, UUID.Zero); - m_scene.AssetService.Store(ncAsset); - - TaskInventoryItem ncItem - = new TaskInventoryItem { Name = "ncItem", AssetID = ncAssetUuid, ItemID = ncItemUuid }; - SceneObjectPart part2 = CreateSceneObjectPart2(); - sog2 = new SceneObjectGroup(part2); - part2.Inventory.AddInventoryItem(ncItem, true); - - scene.AddNewSceneObject(sog2, false); - } - /// /// Test saving an OpenSim Region Archive with the no assets option /// @@ -287,7 +270,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests Assert.That(filePath, Is.EqualTo(ArchiveConstants.CONTROL_FILE_PATH)); ArchiveReadRequest arr = new ArchiveReadRequest(m_scene, (Stream)null, false, false, Guid.Empty); - arr.LoadControlFile(filePath, data, new DearchiveScenesInfo()); + arr.LoadControlFile(filePath, data); Assert.That(arr.ControlFileLoaded, Is.True); @@ -324,7 +307,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests tar.WriteFile( ArchiveConstants.CONTROL_FILE_PATH, - new ArchiveWriteRequest(m_scene, (Stream)null, Guid.Empty).CreateControlFile(new ArchiveScenesGroup())); + new ArchiveWriteRequestPreparation(null, (Stream)null, Guid.Empty).CreateControlFile(new Dictionary())); SceneObjectGroup sog1 = SceneHelpers.CreateSceneObject(1, ownerId, "obj1-", 0x11); SceneObjectPart sop2 @@ -379,10 +362,11 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests // Also check that direct entries which will also have a file entry containing that directory doesn't // upset load tar.WriteDir(ArchiveConstants.TERRAINS_PATH); - + tar.WriteFile( ArchiveConstants.CONTROL_FILE_PATH, - new ArchiveWriteRequest(m_scene, (Stream)null, Guid.Empty).CreateControlFile(new ArchiveScenesGroup())); + new ArchiveWriteRequestPreparation(null, (Stream)null, Guid.Empty).CreateControlFile(new Dictionary())); + SceneObjectPart part1 = CreateSceneObjectPart1(); part1.SitTargetOrientation = new Quaternion(0.2f, 0.3f, 0.4f, 0.5f); @@ -405,12 +389,31 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests Assert.That(soundDataResourceName, Is.Not.Null); byte[] soundData; - UUID soundUuid; - CreateSoundAsset(tar, assembly, soundDataResourceName, out soundData, out soundUuid); - - TaskInventoryItem item1 - = new TaskInventoryItem { AssetID = soundUuid, ItemID = soundItemUuid, Name = soundItemName }; - part1.Inventory.AddInventoryItem(item1, true); + Console.WriteLine("Loading " + soundDataResourceName); + using (Stream resource = assembly.GetManifestResourceStream(soundDataResourceName)) + { + using (BinaryReader br = new BinaryReader(resource)) + { + // FIXME: Use the inspector instead + soundData = br.ReadBytes(99999999); + UUID soundUuid = UUID.Parse("00000000-0000-0000-0000-000000000001"); + string soundAssetFileName + = ArchiveConstants.ASSETS_PATH + soundUuid + + ArchiveConstants.ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.SoundWAV]; + tar.WriteFile(soundAssetFileName, soundData); + + /* + AssetBase soundAsset = AssetHelpers.CreateAsset(soundUuid, soundData); + scene.AssetService.Store(soundAsset); + asset1FileName = ArchiveConstants.ASSETS_PATH + soundUuid + ".wav"; + */ + + TaskInventoryItem item1 + = new TaskInventoryItem { AssetID = soundUuid, ItemID = soundItemUuid, Name = soundItemName }; + part1.Inventory.AddInventoryItem(item1, true); + } + } + m_scene.AddNewSceneObject(object1, false); string object1FileName = string.Format( @@ -432,34 +435,6 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests Assert.That(m_lastErrorMessage, Is.Null); - TestLoadedRegion(part1, soundItemName, soundData); - } - - private static void CreateSoundAsset(TarArchiveWriter tar, Assembly assembly, string soundDataResourceName, out byte[] soundData, out UUID soundUuid) - { - using (Stream resource = assembly.GetManifestResourceStream(soundDataResourceName)) - { - using (BinaryReader br = new BinaryReader(resource)) - { - // FIXME: Use the inspector instead - soundData = br.ReadBytes(99999999); - soundUuid = UUID.Parse("00000000-0000-0000-0000-000000000001"); - string soundAssetFileName - = ArchiveConstants.ASSETS_PATH + soundUuid - + ArchiveConstants.ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.SoundWAV]; - tar.WriteFile(soundAssetFileName, soundData); - - /* - AssetBase soundAsset = AssetHelpers.CreateAsset(soundUuid, soundData); - scene.AssetService.Store(soundAsset); - asset1FileName = ArchiveConstants.ASSETS_PATH + soundUuid + ".wav"; - */ - } - } - } - - private void TestLoadedRegion(SceneObjectPart part1, string soundItemName, byte[] soundData) - { SceneObjectPart object1PartLoaded = m_scene.GetSceneObjectPart(part1.Name); Assert.That(object1PartLoaded, Is.Not.Null, "object1 was not loaded"); @@ -479,6 +454,9 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests Assert.That(loadedSoundAsset.Data, Is.EqualTo(soundData), "saved and loaded sound data do not match"); Assert.Greater(m_scene.LandChannel.AllParcels().Count, 0, "incorrect number of parcels"); + + // Temporary + Console.WriteLine("Successfully completed {0}", MethodBase.GetCurrentMethod()); } /// @@ -538,8 +516,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests SerialiserModule serialiserModule = new SerialiserModule(); TerrainModule terrainModule = new TerrainModule(); - m_sceneHelpers = new SceneHelpers(); - TestScene scene2 = m_sceneHelpers.SetupScene(); + TestScene scene2 = new SceneHelpers().SetupScene(); SceneHelpers.SetupSceneModules(scene2, archiverModule, serialiserModule, terrainModule); // Make sure there's a valid owner for the owner we saved (this should have been wiped if the code is @@ -577,7 +554,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests tar.WriteDir(ArchiveConstants.TERRAINS_PATH); tar.WriteFile( ArchiveConstants.CONTROL_FILE_PATH, - new ArchiveWriteRequest(m_scene, (Stream)null, Guid.Empty).CreateControlFile(new ArchiveScenesGroup())); + new ArchiveWriteRequestPreparation(null, (Stream)null, Guid.Empty).CreateControlFile(new Dictionary())); RegionSettings rs = new RegionSettings(); rs.AgentLimit = 17; @@ -687,7 +664,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests SerialiserModule serialiserModule = new SerialiserModule(); TerrainModule terrainModule = new TerrainModule(); - Scene scene = m_sceneHelpers.SetupScene(); + Scene scene = new SceneHelpers().SetupScene(); SceneHelpers.SetupSceneModules(scene, archiverModule, serialiserModule, terrainModule); m_scene.AddNewSceneObject(new SceneObjectGroup(part2), false); @@ -723,258 +700,5 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests Assert.That(object2PartMerged.GroupPosition, Is.EqualTo(part2.GroupPosition), "object2 group position not equal after merge"); } } - - /// - /// Test saving a multi-region OAR. - /// - [Test] - public void TestSaveMultiRegionOar() - { - TestHelpers.InMethod(); - - // Create test regions - - int WIDTH = 2; - int HEIGHT = 2; - - List scenes = new List(); - - // Maps (Directory in OAR file -> scene) - Dictionary regionPaths = new Dictionary(); - - // Maps (Scene -> expected object paths) - Dictionary> expectedPaths = new Dictionary>(); - - // List of expected assets - List expectedAssets = new List(); - - for (uint y = 0; y < HEIGHT; y++) - { - for (uint x = 0; x < WIDTH; x++) - { - Scene scene; - if (x == 0 && y == 0) - { - scene = m_scene; // this scene was already created in SetUp() - } - else - { - scene = m_sceneHelpers.SetupScene(string.Format("Unit test region {0}", (y * WIDTH) + x + 1), UUID.Random(), 1000 + x, 1000 + y); - SceneHelpers.SetupSceneModules(scene, new ArchiverModule(), m_serialiserModule, new TerrainModule()); - } - scenes.Add(scene); - - string dir = String.Format("{0}_{1}_{2}", x + 1, y + 1, scene.RegionInfo.RegionName.Replace(" ", "_")); - regionPaths[dir] = scene; - - SceneObjectGroup sog1; - SceneObjectGroup sog2; - UUID ncAssetUuid; - - CreateTestObjects(scene, out sog1, out sog2, out ncAssetUuid); - - expectedPaths[scene.RegionInfo.RegionID] = new List(); - expectedPaths[scene.RegionInfo.RegionID].Add(ArchiveHelpers.CreateObjectPath(sog1)); - expectedPaths[scene.RegionInfo.RegionID].Add(ArchiveHelpers.CreateObjectPath(sog2)); - - expectedAssets.Add(ncAssetUuid); - } - } - - - // Save OAR - - MemoryStream archiveWriteStream = new MemoryStream(); - m_scene.EventManager.OnOarFileSaved += SaveCompleted; - - Guid requestId = new Guid("00000000-0000-0000-0000-808080808080"); - - Dictionary options = new Dictionary(); - options.Add("all", true); - - lock (this) - { - m_archiverModule.ArchiveRegion(archiveWriteStream, requestId, options); - Monitor.Wait(this, 60000); - } - - - // Check that the OAR contains the expected data - - Assert.That(m_lastRequestId, Is.EqualTo(requestId)); - - byte[] archive = archiveWriteStream.ToArray(); - MemoryStream archiveReadStream = new MemoryStream(archive); - TarArchiveReader tar = new TarArchiveReader(archiveReadStream); - - Dictionary> foundPaths = new Dictionary>(); - List foundAssets = new List(); - - foreach (Scene scene in scenes) - { - foundPaths[scene.RegionInfo.RegionID] = new List(); - } - - string filePath; - TarArchiveReader.TarEntryType tarEntryType; - - byte[] data = tar.ReadEntry(out filePath, out tarEntryType); - Assert.That(filePath, Is.EqualTo(ArchiveConstants.CONTROL_FILE_PATH)); - - ArchiveReadRequest arr = new ArchiveReadRequest(m_scene, (Stream)null, false, false, Guid.Empty); - arr.LoadControlFile(filePath, data, new DearchiveScenesInfo()); - - Assert.That(arr.ControlFileLoaded, Is.True); - - while (tar.ReadEntry(out filePath, out tarEntryType) != null) - { - if (filePath.StartsWith(ArchiveConstants.ASSETS_PATH)) - { - // Assets are shared, so this file doesn't belong to any specific region. - string fileName = filePath.Remove(0, ArchiveConstants.ASSETS_PATH.Length); - if (fileName.EndsWith("_notecard.txt")) - foundAssets.Add(UUID.Parse(fileName.Substring(0, fileName.Length - "_notecard.txt".Length))); - } - else - { - // This file belongs to one of the regions. Find out which one. - Assert.IsTrue(filePath.StartsWith(ArchiveConstants.REGIONS_PATH)); - string[] parts = filePath.Split(new Char[] { '/' }, 3); - Assert.AreEqual(3, parts.Length); - string regionDirectory = parts[1]; - string relativePath = parts[2]; - Scene scene = regionPaths[regionDirectory]; - - if (relativePath.StartsWith(ArchiveConstants.OBJECTS_PATH)) - { - foundPaths[scene.RegionInfo.RegionID].Add(relativePath); - } - } - } - - Assert.AreEqual(scenes.Count, foundPaths.Count); - foreach (Scene scene in scenes) - { - Assert.That(foundPaths[scene.RegionInfo.RegionID], Is.EquivalentTo(expectedPaths[scene.RegionInfo.RegionID])); - } - - Assert.That(foundAssets, Is.EquivalentTo(expectedAssets)); - } - - /// - /// Test loading a multi-region OAR. - /// - [Test] - public void TestLoadMultiRegionOar() - { - TestHelpers.InMethod(); - - // Create an ArchiveScenesGroup with the regions in the OAR. This is needed to generate the control file. - - int WIDTH = 2; - int HEIGHT = 2; - - for (uint y = 0; y < HEIGHT; y++) - { - for (uint x = 0; x < WIDTH; x++) - { - Scene scene; - if (x == 0 && y == 0) - { - scene = m_scene; // this scene was already created in SetUp() - } - else - { - scene = m_sceneHelpers.SetupScene(string.Format("Unit test region {0}", (y * WIDTH) + x + 1), UUID.Random(), 1000 + x, 1000 + y); - SceneHelpers.SetupSceneModules(scene, new ArchiverModule(), m_serialiserModule, new TerrainModule()); - } - } - } - - ArchiveScenesGroup scenesGroup = new ArchiveScenesGroup(); - SceneManager.Instance.ForEachScene(delegate(Scene scene) - { - scenesGroup.AddScene(scene); - }); - scenesGroup.CalcSceneLocations(); - - // Generate the OAR file - - MemoryStream archiveWriteStream = new MemoryStream(); - TarArchiveWriter tar = new TarArchiveWriter(archiveWriteStream); - - ArchiveWriteRequest writeRequest = new ArchiveWriteRequest(m_scene, (Stream)null, Guid.Empty); - writeRequest.MultiRegionFormat = true; - tar.WriteFile( - ArchiveConstants.CONTROL_FILE_PATH, writeRequest.CreateControlFile(scenesGroup)); - - SceneObjectPart part1 = CreateSceneObjectPart1(); - part1.SitTargetOrientation = new Quaternion(0.2f, 0.3f, 0.4f, 0.5f); - part1.SitTargetPosition = new Vector3(1, 2, 3); - - SceneObjectGroup object1 = new SceneObjectGroup(part1); - - // Let's put some inventory items into our object - string soundItemName = "sound-item1"; - UUID soundItemUuid = UUID.Parse("00000000-0000-0000-0000-000000000002"); - Type type = GetType(); - Assembly assembly = type.Assembly; - string soundDataResourceName = null; - string[] names = assembly.GetManifestResourceNames(); - foreach (string name in names) - { - if (name.EndsWith(".Resources.test-sound.wav")) - soundDataResourceName = name; - } - Assert.That(soundDataResourceName, Is.Not.Null); - - byte[] soundData; - UUID soundUuid; - CreateSoundAsset(tar, assembly, soundDataResourceName, out soundData, out soundUuid); - - TaskInventoryItem item1 - = new TaskInventoryItem { AssetID = soundUuid, ItemID = soundItemUuid, Name = soundItemName }; - part1.Inventory.AddInventoryItem(item1, true); - m_scene.AddNewSceneObject(object1, false); - - string object1FileName = string.Format( - "{0}_{1:000}-{2:000}-{3:000}__{4}.xml", - part1.Name, - Math.Round(part1.GroupPosition.X), Math.Round(part1.GroupPosition.Y), Math.Round(part1.GroupPosition.Z), - part1.UUID); - string path = "regions/1_1_Unit_test_region/" + ArchiveConstants.OBJECTS_PATH + object1FileName; - tar.WriteFile(path, SceneObjectSerializer.ToXml2Format(object1)); - - tar.Close(); - - - // Delete the current objects, to test that they're loaded from the OAR and didn't - // just remain in the scene. - SceneManager.Instance.ForEachScene(delegate(Scene scene) - { - scene.DeleteAllSceneObjects(); - }); - - // Create a "hole", to test that that the corresponding region isn't loaded from the OAR - SceneManager.Instance.CloseScene(SceneManager.Instance.Scenes[1]); - - - // Check thay the OAR file contains the expected data - - MemoryStream archiveReadStream = new MemoryStream(archiveWriteStream.ToArray()); - - lock (this) - { - m_scene.EventManager.OnOarFileLoaded += LoadCompleted; - m_archiverModule.DearchiveRegion(archiveReadStream); - } - - Assert.That(m_lastErrorMessage, Is.Null); - - Assert.AreEqual(3, SceneManager.Instance.Scenes.Count); - - TestLoadedRegion(part1, soundItemName, soundData); - } - } } diff --git a/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs b/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs index 5fd1bce..fdef9d8 100644 --- a/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs +++ b/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs @@ -40,7 +40,6 @@ using OpenMetaverse; using OpenSim.Framework; using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Scenes; -using RegionFlags = OpenMetaverse.RegionFlags; namespace OpenSim.Region.CoreModules.World.Estate { diff --git a/OpenSim/Region/CoreModules/World/Land/DwellModule.cs b/OpenSim/Region/CoreModules/World/Land/DwellModule.cs deleted file mode 100644 index d1f05a7..0000000 --- a/OpenSim/Region/CoreModules/World/Land/DwellModule.cs +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections; -using System.Collections.Generic; -using System.Diagnostics; -using System.Reflection; -using System.Text; -using log4net; -using Nini.Config; -using OpenMetaverse; -using OpenMetaverse.StructuredData; -using OpenMetaverse.Messages.Linden; -using OpenSim.Framework; -using OpenSim.Framework.Capabilities; -using OpenSim.Framework.Console; -using OpenSim.Framework.Servers; -using OpenSim.Framework.Servers.HttpServer; -using OpenSim.Region.CoreModules.Framework.InterfaceCommander; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Region.Physics.Manager; -using OpenSim.Services.Interfaces; -using Caps = OpenSim.Framework.Capabilities.Caps; -using GridRegion = OpenSim.Services.Interfaces.GridRegion; - -namespace OpenSim.Region.CoreModules.World.Land -{ - public class DwellModule : IDwellModule, INonSharedRegionModule - { - private Scene m_scene; - - public Type ReplaceableInterface - { - get { return typeof(IDwellModule); } - } - - public string Name - { - get { return "DwellModule"; } - } - - public void Initialise(IConfigSource source) - { - } - - public void AddRegion(Scene scene) - { - m_scene = scene; - - m_scene.EventManager.OnNewClient += OnNewClient; - } - - public void RegionLoaded(Scene scene) - { - } - - public void RemoveRegion(Scene scene) - { - } - - public void Close() - { - } - - public void OnNewClient(IClientAPI client) - { - client.OnParcelDwellRequest += ClientOnParcelDwellRequest; - } - - private void ClientOnParcelDwellRequest(int localID, IClientAPI client) - { - ILandObject parcel = m_scene.LandChannel.GetLandObject(localID); - if (parcel == null) - return; - - client.SendParcelDwellReply(localID, parcel.LandData.GlobalID, parcel.LandData.Dwell); - } - - public int GetDwell(UUID parcelID) - { - return 0; - } - } -} diff --git a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs index b5e2bc3..aae6603 100644 --- a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs +++ b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs @@ -927,7 +927,6 @@ namespace OpenSim.Region.CoreModules.World.Land ILandObject newLand = startLandObject.Copy(); newLand.LandData.Name = newLand.LandData.Name; newLand.LandData.GlobalID = UUID.Random(); - newLand.LandData.Dwell = 0; newLand.SetLandBitmap(newLand.GetSquareLandBitmap(start_x, start_y, end_x, end_y)); diff --git a/OpenSim/Region/CoreModules/World/Land/LandObject.cs b/OpenSim/Region/CoreModules/World/Land/LandObject.cs index d5b2adb..4f06737 100644 --- a/OpenSim/Region/CoreModules/World/Land/LandObject.cs +++ b/OpenSim/Region/CoreModules/World/Land/LandObject.cs @@ -33,7 +33,6 @@ using OpenMetaverse; using OpenSim.Framework; using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Scenes; -using RegionFlags = OpenMetaverse.RegionFlags; namespace OpenSim.Region.CoreModules.World.Land { diff --git a/OpenSim/Region/CoreModules/World/Land/PrimCountModule.cs b/OpenSim/Region/CoreModules/World/Land/PrimCountModule.cs index cbb3abe..102b4d7 100644 --- a/OpenSim/Region/CoreModules/World/Land/PrimCountModule.cs +++ b/OpenSim/Region/CoreModules/World/Land/PrimCountModule.cs @@ -69,7 +69,7 @@ namespace OpenSim.Region.CoreModules.World.Land /// without recounting the whole sim. /// /// We start out tainted so that the first get call resets the various prim counts. - /// + /// private bool m_Tainted = true; private Object m_TaintLock = new Object(); diff --git a/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs b/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs index ab8f143..09f6758 100644 --- a/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs +++ b/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs @@ -27,12 +27,9 @@ using System; using System.Collections.Generic; -using System.IO; -using System.Linq; using System.Reflection; using System.Text; using System.Text.RegularExpressions; -using System.Xml; using log4net; using Mono.Addins; using NDesk.Options; @@ -43,7 +40,6 @@ using OpenSim.Framework.Console; using OpenSim.Framework.Monitoring; using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Scenes; -using OpenSim.Region.Framework.Scenes.Serialization; namespace OpenSim.Region.CoreModules.World.Objects.Commands { @@ -87,85 +83,52 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands m_console.Commands.AddCommand( "Objects", false, "delete object owner", "delete object owner ", - "Delete scene objects by owner", - "Command will ask for confirmation before proceeding.", - HandleDeleteObject); + "Delete a scene object by owner", HandleDeleteObject); m_console.Commands.AddCommand( "Objects", false, "delete object creator", "delete object creator ", - "Delete scene objects by creator", - "Command will ask for confirmation before proceeding.", - HandleDeleteObject); + "Delete a scene object by creator", HandleDeleteObject); m_console.Commands.AddCommand( - "Objects", false, "delete object id", - "delete object id ", - "Delete a scene object by uuid or localID", - HandleDeleteObject); + "Objects", false, "delete object uuid", + "delete object uuid ", + "Delete a scene object by uuid", HandleDeleteObject); m_console.Commands.AddCommand( "Objects", false, "delete object name", "delete object name [--regex] ", "Delete a scene object by name.", - "Command will ask for confirmation before proceeding.\n" - + "If --regex is specified then the name is treatead as a regular expression", + "If --regex is specified then the name is treatead as a regular expression", HandleDeleteObject); m_console.Commands.AddCommand( "Objects", false, "delete object outside", "delete object outside", - "Delete all scene objects outside region boundaries", - "Command will ask for confirmation before proceeding.", - HandleDeleteObject); + "Delete all scene objects outside region boundaries", HandleDeleteObject); m_console.Commands.AddCommand( "Objects", false, - "delete object pos", - "delete object pos to ", - "Delete scene objects within the given area.", - ConsoleUtil.CoordHelp, - HandleDeleteObject); - - m_console.Commands.AddCommand( - "Objects", - false, - "show object id", - "show object id [--full] ", - "Show details of a scene object with the given UUID or localID", - "The --full option will print out information on all the parts of the object.\n" - + "For yet more detailed part information, use the \"show part\" commands.", - HandleShowObjectById); + "show object uuid", + "show object uuid ", + "Show details of a scene object with the given UUID", HandleShowObjectByUuid); m_console.Commands.AddCommand( "Objects", false, "show object name", - "show object name [--full] [--regex] ", + "show object name [--regex] ", "Show details of scene objects with the given name.", - "The --full option will print out information on all the parts of the object.\n" - + "For yet more detailed part information, use the \"show part\" commands.\n" - + "If --regex is specified then the name is treatead as a regular expression.", + "If --regex is specified then the name is treatead as a regular expression", HandleShowObjectByName); m_console.Commands.AddCommand( "Objects", false, - "show object pos", - "show object pos [--full] to ", - "Show details of scene objects within the given area.", - "The --full option will print out information on all the parts of the object.\n" - + "For yet more detailed part information, use the \"show part\" commands.\n" - + ConsoleUtil.CoordHelp, - HandleShowObjectByPos); - - m_console.Commands.AddCommand( - "Objects", - false, - "show part id", - "show part id ", - "Show details of a scene object part with the given UUID or localID", HandleShowPartById); + "show part uuid", + "show part uuid ", + "Show details of a scene object parts with the given UUID", HandleShowPartByUuid); m_console.Commands.AddCommand( "Objects", @@ -173,28 +136,8 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands "show part name", "show part name [--regex] ", "Show details of scene object parts with the given name.", - "If --regex is specified then the name is treated as a regular expression", + "If --regex is specified then the name is treatead as a regular expression", HandleShowPartByName); - - m_console.Commands.AddCommand( - "Objects", - false, - "show part pos", - "show part pos to ", - "Show details of scene object parts within the given area.", - ConsoleUtil.CoordHelp, - HandleShowPartByPos); - - m_console.Commands.AddCommand( - "Objects", - false, - "dump object id", - "dump object id ", - "Dump the formatted serialization of the given object to the file .xml", - "e.g. dump object uuid c1ed6809-cc24-4061-a4c2-93082a2d1f1d will dump serialization to c1ed6809-cc24-4061-a4c2-93082a2d1f1d.xml\n" - + "To locate the UUID or localID in the first place, you need to use the other show object commands.\n" - + "If a local ID is given then the filename used is still that for the UUID", - HandleDumpObjectById); } public void RemoveRegion(Scene scene) @@ -207,75 +150,25 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands // m_log.DebugFormat("[OBJECTS COMMANDS MODULE]: REGION {0} LOADED", scene.RegionInfo.RegionName); } - /// - /// Outputs the sogs to console. - /// - /// - /// If true then output all part details. If false then output summary. - private void OutputSogsToConsole(Predicate searchPredicate, bool showFull) - { - List sceneObjects = m_scene.GetSceneObjectGroups().FindAll(searchPredicate); - - StringBuilder sb = new StringBuilder(); - - foreach (SceneObjectGroup so in sceneObjects) - { - AddSceneObjectReport(sb, so, showFull); - sb.Append("\n"); - } - - sb.AppendFormat("{0} object(s) found in {1}\n", sceneObjects.Count, m_scene.Name); - - m_console.OutputFormat(sb.ToString()); - } - - private void OutputSopsToConsole(Predicate searchPredicate, bool showFull) - { - List sceneObjects = m_scene.GetSceneObjectGroups(); - List parts = new List(); - - sceneObjects.ForEach(so => parts.AddRange(Array.FindAll(so.Parts, searchPredicate))); - - StringBuilder sb = new StringBuilder(); - - foreach (SceneObjectPart part in parts) - { - AddScenePartReport(sb, part, showFull); - sb.Append("\n"); - } - - sb.AppendFormat("{0} parts found in {1}\n", parts.Count, m_scene.Name); - - m_console.OutputFormat(sb.ToString()); - } - - private void HandleShowObjectById(string module, string[] cmdparams) + private void HandleShowObjectByUuid(string module, string[] cmd) { if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene)) return; - bool showFull = false; - OptionSet options = new OptionSet().Add("full", v => showFull = v != null ); - - List mainParams = options.Parse(cmdparams); - - if (mainParams.Count < 4) + if (cmd.Length < 4) { m_console.OutputFormat("Usage: show object uuid "); return; } - UUID uuid; - uint localId; - if (!ConsoleUtil.TryParseConsoleId(m_console, mainParams[3], out uuid, out localId)) + UUID objectUuid; + if (!UUID.TryParse(cmd[3], out objectUuid)) + { + m_console.OutputFormat("{0} is not a valid uuid", cmd[3]); return; + } - SceneObjectGroup so; - - if (localId != ConsoleUtil.LocalIdNotFound) - so = m_scene.GetSceneObjectGroup(localId); - else - so = m_scene.GetSceneObjectGroup(uuid); + SceneObjectGroup so = m_scene.GetSceneObjectGroup(objectUuid); if (so == null) { @@ -284,7 +177,7 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands } StringBuilder sb = new StringBuilder(); - AddSceneObjectReport(sb, so, showFull); + AddSceneObjectReport(sb, so); m_console.OutputFormat(sb.ToString()); } @@ -294,91 +187,70 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene)) return; - bool showFull = false; bool useRegex = false; - OptionSet options = new OptionSet(); - options.Add("full", v => showFull = v != null ); - options.Add("regex", v => useRegex = v != null ); + OptionSet options = new OptionSet().Add("regex", v=> useRegex = v != null ); List mainParams = options.Parse(cmdparams); if (mainParams.Count < 4) { - m_console.OutputFormat("Usage: show object name [--full] [--regex] "); + m_console.OutputFormat("Usage: show object name [--regex] "); return; } string name = mainParams[3]; - Predicate searchPredicate; + List sceneObjects = new List(); + Action searchAction; if (useRegex) { Regex nameRegex = new Regex(name); - searchPredicate = so => nameRegex.IsMatch(so.Name); + searchAction = so => { if (nameRegex.IsMatch(so.Name)) { sceneObjects.Add(so); }}; } else { - searchPredicate = so => so.Name == name; + searchAction = so => { if (so.Name == name) { sceneObjects.Add(so); }}; } - OutputSogsToConsole(searchPredicate, showFull); - } - - private void HandleShowObjectByPos(string module, string[] cmdparams) - { - if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene)) - return; - - bool showFull = false; - OptionSet options = new OptionSet().Add("full", v => showFull = v != null ); - - List mainParams = options.Parse(cmdparams); + m_scene.ForEachSOG(searchAction); - if (mainParams.Count < 5) + if (sceneObjects.Count == 0) { - m_console.OutputFormat("Usage: show object pos [--full] to "); + m_console.OutputFormat("No objects with name {0} found in {1}", name, m_scene.RegionInfo.RegionName); return; } - Vector3 startVector, endVector; - - if (!TryParseVectorRange(cmdparams.Skip(3).Take(3), out startVector, out endVector)) - return; + StringBuilder sb = new StringBuilder(); - Predicate searchPredicate - = so => Util.IsInsideBox(so.AbsolutePosition, startVector, endVector); + foreach (SceneObjectGroup so in sceneObjects) + { + AddSceneObjectReport(sb, so); + sb.Append("\n"); + } - OutputSogsToConsole(searchPredicate, showFull); + m_console.OutputFormat(sb.ToString()); } - private void HandleShowPartById(string module, string[] cmdparams) + private void HandleShowPartByUuid(string module, string[] cmd) { if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene)) return; -// bool showFull = false; - OptionSet options = new OptionSet(); -// options.Add("full", v => showFull = v != null ); - - List mainParams = options.Parse(cmdparams); - - if (mainParams.Count < 4) + if (cmd.Length < 4) { - m_console.OutputFormat("Usage: show part id [--full] "); + m_console.OutputFormat("Usage: show part uuid "); return; } UUID objectUuid; - uint localId; - if (!ConsoleUtil.TryParseConsoleId(m_console, mainParams[3], out objectUuid, out localId)) + if (!UUID.TryParse(cmd[3], out objectUuid)) + { + m_console.OutputFormat("{0} is not a valid uuid", cmd[3]); return; + } - SceneObjectPart sop; - if (localId == ConsoleUtil.LocalIdNotFound) - sop = m_scene.GetSceneObjectPart(objectUuid); - else - sop = m_scene.GetSceneObjectPart(localId); + SceneObjectPart sop = m_scene.GetSceneObjectPart(objectUuid); if (sop == null) { @@ -387,239 +259,84 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands } StringBuilder sb = new StringBuilder(); - AddScenePartReport(sb, sop, true); + AddScenePartReport(sb, sop); m_console.OutputFormat(sb.ToString()); } - private void HandleShowPartByPos(string module, string[] cmdparams) - { - if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene)) - return; - -// bool showFull = false; - OptionSet options = new OptionSet(); -// options.Add("full", v => showFull = v != null ); - - List mainParams = options.Parse(cmdparams); - - if (mainParams.Count < 5) - { - m_console.OutputFormat("Usage: show part pos [--full] to "); - return; - } - - string rawConsoleStartVector = mainParams[3]; - Vector3 startVector; - - if (!ConsoleUtil.TryParseConsoleMinVector(rawConsoleStartVector, out startVector)) - { - m_console.OutputFormat("Error: Start vector {0} does not have a valid format", rawConsoleStartVector); - return; - } - - string rawConsoleEndVector = mainParams[5]; - Vector3 endVector; - - if (!ConsoleUtil.TryParseConsoleMaxVector(rawConsoleEndVector, out endVector)) - { - m_console.OutputFormat("Error: End vector {0} does not have a valid format", rawConsoleEndVector); - return; - } - - OutputSopsToConsole(sop => Util.IsInsideBox(sop.AbsolutePosition, startVector, endVector), true); - } - private void HandleShowPartByName(string module, string[] cmdparams) { if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene)) return; -// bool showFull = false; bool useRegex = false; - OptionSet options = new OptionSet(); -// options.Add("full", v => showFull = v != null ); - options.Add("regex", v => useRegex = v != null ); + OptionSet options = new OptionSet().Add("regex", v=> useRegex = v != null ); List mainParams = options.Parse(cmdparams); if (mainParams.Count < 4) { - m_console.OutputFormat("Usage: show part name [--full] [--regex] "); + m_console.OutputFormat("Usage: show part name [--regex] "); return; } string name = mainParams[3]; - Predicate searchPredicate; + List parts = new List(); + + Action searchAction; if (useRegex) { Regex nameRegex = new Regex(name); - searchPredicate = sop => nameRegex.IsMatch(sop.Name); + searchAction = so => so.ForEachPart(sop => { if (nameRegex.IsMatch(sop.Name)) { parts.Add(sop); } }); } else { - searchPredicate = sop => sop.Name == name; + searchAction = so => so.ForEachPart(sop => { if (sop.Name == name) { parts.Add(sop); } }); } - OutputSopsToConsole(searchPredicate, true); - } - - private void HandleDumpObjectById(string module, string[] cmdparams) - { - if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene)) - return; + m_scene.ForEachSOG(searchAction); - if (cmdparams.Length < 4) + if (parts.Count == 0) { - m_console.OutputFormat("Usage: dump object id "); + m_console.OutputFormat("No parts with name {0} found in {1}", name, m_scene.RegionInfo.RegionName); return; } - UUID objectUuid; - uint localId; - if (!ConsoleUtil.TryParseConsoleId(m_console, cmdparams[3], out objectUuid, out localId)) - return; - - SceneObjectGroup so; - if (localId == ConsoleUtil.LocalIdNotFound) - so = m_scene.GetSceneObjectGroup(objectUuid); - else - so = m_scene.GetSceneObjectGroup(localId); + StringBuilder sb = new StringBuilder(); - if (so == null) + foreach (SceneObjectPart part in parts) { -// m_console.OutputFormat("No part found with uuid {0}", objectUuid); - return; + AddScenePartReport(sb, part); + sb.Append("\n"); } - // In case we found it via local ID. - objectUuid = so.UUID; - - string fileName = string.Format("{0}.xml", objectUuid); - - if (!ConsoleUtil.CheckFileDoesNotExist(m_console, fileName)) - return; - - using (XmlTextWriter xtw = new XmlTextWriter(fileName, Encoding.UTF8)) - { - xtw.Formatting = Formatting.Indented; - SceneObjectSerializer.ToOriginalXmlFormat(so, xtw, true); - } - - m_console.OutputFormat("Object dumped to file {0}", fileName); + m_console.OutputFormat(sb.ToString()); } - /// - /// Append a scene object report to an input StringBuilder - /// - /// - /// - /// - /// - /// If true then information on all parts of an object is appended. - /// If false then only summary information about an object is appended. - /// - private StringBuilder AddSceneObjectReport(StringBuilder sb, SceneObjectGroup so, bool showFull) + private StringBuilder AddSceneObjectReport(StringBuilder sb, SceneObjectGroup so) { - if (showFull) - { - foreach (SceneObjectPart sop in so.Parts) - { - AddScenePartReport(sb, sop, false); - sb.Append("\n"); - } - } - else - { - AddSummarySceneObjectReport(sb, so); - } + sb.AppendFormat("Name: {0}\n", so.Name); + sb.AppendFormat("Description: {0}\n", so.Description); + sb.AppendFormat("Location: {0} @ {1}\n", so.AbsolutePosition, so.Scene.RegionInfo.RegionName); + sb.AppendFormat("Parts: {0}\n", so.PrimCount); + sb.AppendFormat("Flags: {0}\n", so.RootPart.Flags); return sb; } - private StringBuilder AddSummarySceneObjectReport(StringBuilder sb, SceneObjectGroup so) - { - ConsoleDisplayList cdl = new ConsoleDisplayList(); - cdl.AddRow("Name", so.Name); - cdl.AddRow("Descrition", so.Description); - cdl.AddRow("Local ID", so.LocalId); - cdl.AddRow("UUID", so.UUID); - cdl.AddRow("Location", string.Format("{0} @ {1}", so.AbsolutePosition, so.Scene.Name)); - cdl.AddRow("Parts", so.PrimCount); - cdl.AddRow("Flags", so.RootPart.Flags); - - return sb.Append(cdl.ToString()); - } - - /// - /// Append a scene object part report to an input StringBuilder - /// - /// - /// - /// - /// - /// If true then information on each inventory item will be shown. - /// If false then only summary inventory information is shown. - /// - private StringBuilder AddScenePartReport(StringBuilder sb, SceneObjectPart sop, bool showFull) - { - ConsoleDisplayList cdl = new ConsoleDisplayList(); - cdl.AddRow("Name", sop.Name); - cdl.AddRow("Description", sop.Description); - cdl.AddRow("Local ID", sop.LocalId); - cdl.AddRow("UUID", sop.UUID); - cdl.AddRow("Location", string.Format("{0} @ {1}", sop.AbsolutePosition, sop.ParentGroup.Scene.Name)); - cdl.AddRow( - "Parent", - sop.IsRoot ? "Is Root" : string.Format("{0} {1}", sop.ParentGroup.Name, sop.ParentGroup.UUID)); - cdl.AddRow("Link number", sop.LinkNum); - cdl.AddRow("Flags", sop.Flags); - - object itemsOutput; - if (showFull) - { - StringBuilder itemsSb = new StringBuilder("\n"); - itemsOutput = AddScenePartItemsReport(itemsSb, sop.Inventory).ToString(); - } - else - { - itemsOutput = sop.Inventory.Count; - } - - - cdl.AddRow("Items", itemsOutput); - - return sb.Append(cdl.ToString()); - } - - private StringBuilder AddScenePartItemsReport(StringBuilder sb, IEntityInventory inv) + private StringBuilder AddScenePartReport(StringBuilder sb, SceneObjectPart sop) { - ConsoleDisplayTable cdt = new ConsoleDisplayTable(); - cdt.Indent = 2; - - cdt.AddColumn("Name", 50); - cdt.AddColumn("Type", 12); - cdt.AddColumn("Running", 7); - cdt.AddColumn("Item UUID", 36); - cdt.AddColumn("Asset UUID", 36); - - foreach (TaskInventoryItem item in inv.GetInventoryItems()) - { - bool foundScriptInstance, scriptRunning; - foundScriptInstance - = SceneObjectPartInventory.TryGetScriptInstanceRunning(m_scene, item, out scriptRunning); - - cdt.AddRow( - item.Name, - ((InventoryType)item.InvType).ToString(), - foundScriptInstance ? scriptRunning.ToString() : "n/a", - item.ItemID.ToString(), - item.AssetID.ToString()); - } + sb.AppendFormat("Name: {0}\n", sop.Name); + sb.AppendFormat("Description: {0}\n", sop.Description); + sb.AppendFormat("Location: {0} @ {1}\n", sop.AbsolutePosition, sop.ParentGroup.Scene.RegionInfo.RegionName); + sb.AppendFormat("Parent: {0}", + sop.IsRoot ? "Is Root\n" : string.Format("{0} {1}\n", sop.ParentGroup.Name, sop.ParentGroup.UUID)); + sb.AppendFormat("Link number: {0}\n", sop.LinkNum); + sb.AppendFormat("Flags: {0}\n", sop.Flags); - return sb.Append(cdt.ToString()); + return sb; } private void HandleDeleteObject(string module, string[] cmd) @@ -681,24 +398,19 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands break; - case "id": - UUID uuid; - uint localId; - if (!ConsoleUtil.TryParseConsoleId(m_console, o, out uuid, out localId)) + case "uuid": + if (!UUID.TryParse(o, out match)) return; requireConfirmation = false; deletes = new List(); - - SceneObjectGroup so; - if (localId == ConsoleUtil.LocalIdNotFound) - so = m_scene.GetSceneObjectGroup(uuid); - else - so = m_scene.GetSceneObjectGroup(localId); - - if (!so.IsAttachment) - deletes.Add(so); - + + m_scene.ForEachSOG(delegate (SceneObjectGroup g) + { + if (g.UUID == match && !g.IsAttachment) + deletes.Add(g); + }); + // if (deletes.Count == 0) // m_console.OutputFormat("No objects were found with uuid {0}", match); @@ -738,10 +450,6 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands break; - case "pos": - deletes = GetDeleteCandidatesByPos(module, cmd); - break; - default: m_console.OutputFormat("Unrecognized mode {0}", mode); return; @@ -756,7 +464,7 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands string.Format( "Are you sure that you want to delete {0} objects from {1}", deletes.Count, m_scene.RegionInfo.RegionName), - "y/N"); + "n"); if (response.ToLower() != "y") { @@ -778,6 +486,9 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands private List GetDeleteCandidatesByName(string module, string[] cmdparams) { + if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene)) + return null; + bool useRegex = false; OptionSet options = new OptionSet().Add("regex", v=> useRegex = v != null ); @@ -811,52 +522,5 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands return sceneObjects; } - - /// - /// Get scene object delete candidates by position - /// - /// - /// - /// null if parsing failed on one of the arguments, otherwise a list of objects to delete. If there - /// are no objects to delete then the list will be empty./returns> - private List GetDeleteCandidatesByPos(string module, string[] cmdparams) - { - if (cmdparams.Length < 5) - { - m_console.OutputFormat("Usage: delete object pos to "); - return null; - } - - Vector3 startVector, endVector; - - if (!TryParseVectorRange(cmdparams.Skip(3).Take(3), out startVector, out endVector)) - return null; - - return m_scene.GetSceneObjectGroups().FindAll( - so => !so.IsAttachment && Util.IsInsideBox(so.AbsolutePosition, startVector, endVector)); - } - - private bool TryParseVectorRange(IEnumerable rawComponents, out Vector3 startVector, out Vector3 endVector) - { - string rawConsoleStartVector = rawComponents.Take(1).Single(); - - if (!ConsoleUtil.TryParseConsoleMinVector(rawConsoleStartVector, out startVector)) - { - m_console.OutputFormat("Error: Start vector {0} does not have a valid format", rawConsoleStartVector); - endVector = Vector3.Zero; - - return false; - } - - string rawConsoleEndVector = rawComponents.Skip(1).Take(1).Single(); - - if (!ConsoleUtil.TryParseConsoleMaxVector(rawConsoleEndVector, out endVector)) - { - m_console.OutputFormat("Error: End vector {0} does not have a valid format", rawConsoleEndVector); - return false; - } - - return true; - } } } \ No newline at end of file diff --git a/OpenSim/Region/CoreModules/World/Sound/SoundModule.cs b/OpenSim/Region/CoreModules/World/Sound/SoundModule.cs index 513a8f5..14c1a39 100644 --- a/OpenSim/Region/CoreModules/World/Sound/SoundModule.cs +++ b/OpenSim/Region/CoreModules/World/Sound/SoundModule.cs @@ -1,4 +1,4 @@ -/* +/* * Copyright (c) Contributors, http://opensimulator.org/ * See CONTRIBUTORS.TXT for a full list of copyright holders. * @@ -24,110 +24,56 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -using System; -using System.IO; -using System.Collections.Generic; -using System.Reflection; +using System; using Nini.Config; using OpenMetaverse; -using log4net; -using Mono.Addins; - using OpenSim.Framework; using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Scenes; +using System.Reflection; +using log4net; namespace OpenSim.Region.CoreModules.World.Sound { - [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "SoundModule")] - public class SoundModule : INonSharedRegionModule, ISoundModule + public class SoundModule : IRegionModule, ISoundModule { - private static readonly ILog m_log = LogManager.GetLogger( - MethodBase.GetCurrentMethod().DeclaringType); - - private Scene m_scene; - - public bool Enabled { get; private set; } - - public float MaxDistance { get; private set; } - - #region INonSharedRegionModule - - public void Initialise(IConfigSource configSource) - { - IConfig config = configSource.Configs["Sounds"]; - - if (config == null) - { - Enabled = true; - MaxDistance = 100.0f; - } - else - { - Enabled = config.GetString("Module", "OpenSim.Region.CoreModules.dll:SoundModule") == - Path.GetFileName(Assembly.GetExecutingAssembly().Location) - + ":" + MethodBase.GetCurrentMethod().DeclaringType.Name; - MaxDistance = config.GetFloat("MaxDistance", 100.0f); - } - } - - public void AddRegion(Scene scene) { } - - public void RemoveRegion(Scene scene) +// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + protected Scene m_scene; + + public void Initialise(Scene scene, IConfigSource source) { - m_scene.EventManager.OnClientLogin -= OnNewClient; - } - - public void RegionLoaded(Scene scene) - { - if (!Enabled) - return; - m_scene = scene; - m_scene.EventManager.OnClientLogin += OnNewClient; - + + m_scene.EventManager.OnNewClient += OnNewClient; + m_scene.RegisterModuleInterface(this); } - - public void Close() { } - - public Type ReplaceableInterface - { - get { return typeof(ISoundModule); } - } - + + public void PostInitialise() {} + public void Close() {} public string Name { get { return "Sound Module"; } } - - #endregion - - #region Event Handlers - + public bool IsSharedModule { get { return false; } } + private void OnNewClient(IClientAPI client) { client.OnSoundTrigger += TriggerSound; } - - #endregion - - #region ISoundModule - + public virtual void PlayAttachedSound( UUID soundID, UUID ownerID, UUID objectID, double gain, Vector3 position, byte flags, float radius) { - SceneObjectPart part; - if (!m_scene.TryGetSceneObjectPart(objectID, out part)) + SceneObjectPart part = m_scene.GetSceneObjectPart(objectID); + if (part == null) return; SceneObjectGroup grp = part.ParentGroup; - if (radius == 0) - radius = MaxDistance; - m_scene.ForEachRootScenePresence(delegate(ScenePresence sp) { double dis = Util.GetDistanceTo(sp.AbsolutePosition, position); - if (dis > MaxDistance) // Max audio distance + if (dis > 100.0) // Max audio distance return; if (grp.IsAttachment) @@ -140,21 +86,23 @@ namespace OpenSim.Region.CoreModules.World.Sound } // Scale by distance - double thisSpGain = gain * ((radius - dis) / radius); + if (radius == 0) + gain = (float)((double)gain * ((100.0 - dis) / 100.0)); + else + gain = (float)((double)gain * ((radius - dis) / radius)); - sp.ControllingClient.SendPlayAttachedSound(soundID, objectID, - ownerID, (float)thisSpGain, flags); + sp.ControllingClient.SendPlayAttachedSound(soundID, objectID, ownerID, (float)gain, flags); }); } - + public virtual void TriggerSound( UUID soundId, UUID ownerID, UUID objectID, UUID parentID, double gain, Vector3 position, UInt64 handle, float radius) { - SceneObjectPart part; - if (!m_scene.TryGetSceneObjectPart(objectID, out part)) + SceneObjectPart part = m_scene.GetSceneObjectPart(objectID); + if (part == null) { ScenePresence sp; - if (!m_scene.TryGetScenePresence(ownerID, out sp)) + if (!m_scene.TryGetScenePresence(objectID, out sp)) return; } else @@ -168,207 +116,24 @@ namespace OpenSim.Region.CoreModules.World.Sound } } - if (radius == 0) - radius = MaxDistance; - m_scene.ForEachRootScenePresence(delegate(ScenePresence sp) { double dis = Util.GetDistanceTo(sp.AbsolutePosition, position); - if (dis > MaxDistance) // Max audio distance + if (dis > 100.0) // Max audio distance return; - // Scale by distance - double thisSpGain = gain * ((radius - dis) / radius); - - sp.ControllingClient.SendTriggeredSound(soundId, ownerID, - objectID, parentID, handle, position, - (float)thisSpGain); - }); - } - - public virtual void StopSound(UUID objectID) - { - SceneObjectPart m_host; - if (!m_scene.TryGetSceneObjectPart(objectID, out m_host)) - return; - - StopSound(m_host); - } - - private static void StopSound(SceneObjectPart m_host) - { - m_host.AdjustSoundGain(0); - // Xantor 20080528: Clear prim data of sound instead - if (m_host.ParentGroup.LoopSoundSlavePrims.Contains(m_host)) - { - if (m_host.ParentGroup.LoopSoundMasterPrim == m_host) - { - foreach (SceneObjectPart part in m_host.ParentGroup.LoopSoundSlavePrims) - { - part.Sound = UUID.Zero; - part.SoundFlags = 1 << 5; - part.SoundRadius = 0; - part.ScheduleFullUpdate(); - part.SendFullUpdateToAllClients(); - } - m_host.ParentGroup.LoopSoundMasterPrim = null; - m_host.ParentGroup.LoopSoundSlavePrims.Clear(); - } - else - { - m_host.Sound = UUID.Zero; - m_host.SoundFlags = 1 << 5; - m_host.SoundRadius = 0; - m_host.ScheduleFullUpdate(); - m_host.SendFullUpdateToAllClients(); - } - } - else - { - m_host.Sound = UUID.Zero; - m_host.SoundFlags = 1 << 5; - m_host.SoundRadius = 0; - m_host.ScheduleFullUpdate(); - m_host.SendFullUpdateToAllClients(); - } - } - - public virtual void PreloadSound(UUID objectID, UUID soundID, float radius) - { - SceneObjectPart part; - if (soundID == UUID.Zero - || !m_scene.TryGetSceneObjectPart(objectID, out part)) - { - return; - } - - if (radius == 0) - radius = MaxDistance; - - m_scene.ForEachRootScenePresence(delegate(ScenePresence sp) - { - if (!(Util.GetDistanceTo(sp.AbsolutePosition, part.AbsolutePosition) >= MaxDistance)) - sp.ControllingClient.SendPreLoadSound(objectID, objectID, soundID); - }); - } - - // Xantor 20080528 we should do this differently. - // 1) apply the sound to the object - // 2) schedule full update - // just sending the sound out once doesn't work so well when other avatars come in view later on - // or when the prim gets moved, changed, sat on, whatever - // see large number of mantises (mantes?) - // 20080530 Updated to remove code duplication - // 20080530 Stop sound if there is one, otherwise volume only changes don't work - public void LoopSound(UUID objectID, UUID soundID, - double volume, double radius, bool isMaster) - { - SceneObjectPart m_host; - if (!m_scene.TryGetSceneObjectPart(objectID, out m_host)) - return; - - if (isMaster) - m_host.ParentGroup.LoopSoundMasterPrim = m_host; - - if (m_host.Sound != UUID.Zero) - StopSound(m_host); - - m_host.Sound = soundID; - m_host.SoundGain = volume; - m_host.SoundFlags = 1; // looping - m_host.SoundRadius = radius; - - m_host.ScheduleFullUpdate(); - m_host.SendFullUpdateToAllClients(); - } - - public void SendSound(UUID objectID, UUID soundID, double volume, - bool triggered, byte flags, float radius, bool useMaster, - bool isMaster) - { - if (soundID == UUID.Zero) - return; - - SceneObjectPart part; - if (!m_scene.TryGetSceneObjectPart(objectID, out part)) - return; - - volume = Util.Clip((float)volume, 0, 1); - - UUID parentID = part.ParentGroup.UUID; - - Vector3 position = part.AbsolutePosition; // region local - ulong regionHandle = m_scene.RegionInfo.RegionHandle; - - if (useMaster) - { - if (isMaster) - { - if (triggered) - TriggerSound(soundID, part.OwnerID, part.UUID, parentID, volume, position, regionHandle, radius); - else - PlayAttachedSound(soundID, part.OwnerID, part.UUID, volume, position, flags, radius); - part.ParentGroup.PlaySoundMasterPrim = part; - if (triggered) - TriggerSound(soundID, part.OwnerID, part.UUID, parentID, volume, position, regionHandle, radius); - else - PlayAttachedSound(soundID, part.OwnerID, part.UUID, volume, position, flags, radius); - foreach (SceneObjectPart prim in part.ParentGroup.PlaySoundSlavePrims) - { - position = prim.AbsolutePosition; // region local - if (triggered) - TriggerSound(soundID, part.OwnerID, prim.UUID, parentID, volume, position, regionHandle, radius); - else - PlayAttachedSound(soundID, part.OwnerID, prim.UUID, volume, position, flags, radius); - } - part.ParentGroup.PlaySoundSlavePrims.Clear(); - part.ParentGroup.PlaySoundMasterPrim = null; - } - else - { - part.ParentGroup.PlaySoundSlavePrims.Add(part); - } - } - else - { - if (triggered) - TriggerSound(soundID, part.OwnerID, part.UUID, parentID, volume, position, regionHandle, radius); - else - PlayAttachedSound(soundID, part.OwnerID, part.UUID, volume, position, flags, radius); - } - } - - public void TriggerSoundLimited(UUID objectID, UUID sound, - double volume, Vector3 min, Vector3 max) - { - if (sound == UUID.Zero) - return; - - SceneObjectPart part; - if (!m_scene.TryGetSceneObjectPart(objectID, out part)) - return; - - m_scene.ForEachRootScenePresence(delegate(ScenePresence sp) - { - double dis = Util.GetDistanceTo(sp.AbsolutePosition, - part.AbsolutePosition); - - if (dis > MaxDistance) // Max audio distance - return; - else if (!Util.IsInsideBox(sp.AbsolutePosition, min, max)) - return; + float thisSpGain; // Scale by distance - double thisSpGain = volume * ((MaxDistance - dis) / MaxDistance); + if (radius == 0) + thisSpGain = (float)((double)gain * ((100.0 - dis) / 100.0)); + else + thisSpGain = (float)((double)gain * ((radius - dis) / radius)); - sp.ControllingClient.SendTriggeredSound(sound, part.OwnerID, - part.UUID, part.ParentGroup.UUID, - m_scene.RegionInfo.RegionHandle, - part.AbsolutePosition, (float)thisSpGain); + sp.ControllingClient.SendTriggeredSound( + soundId, ownerID, objectID, parentID, handle, position, thisSpGain); }); } - - #endregion } } diff --git a/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs b/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs index d99567c..402b9fb 100644 --- a/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs +++ b/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs @@ -414,7 +414,6 @@ namespace OpenSim.Region.CoreModules.World.Terrain private void LoadPlugins() { m_plugineffects = new Dictionary(); - LoadPlugins(Assembly.GetCallingAssembly()); string plugineffectsPath = "Terrain"; // Load the files in the Terrain/ dir @@ -428,39 +427,34 @@ namespace OpenSim.Region.CoreModules.World.Terrain try { Assembly library = Assembly.LoadFrom(file); - LoadPlugins(library); - } - catch (BadImageFormatException) - { - } - } - } - - private void LoadPlugins(Assembly library) - { - foreach (Type pluginType in library.GetTypes()) - { - try - { - if (pluginType.IsAbstract || pluginType.IsNotPublic) - continue; + foreach (Type pluginType in library.GetTypes()) + { + try + { + if (pluginType.IsAbstract || pluginType.IsNotPublic) + continue; - string typeName = pluginType.Name; + string typeName = pluginType.Name; - if (pluginType.GetInterface("ITerrainEffect", false) != null) - { - ITerrainEffect terEffect = (ITerrainEffect)Activator.CreateInstance(library.GetType(pluginType.ToString())); + if (pluginType.GetInterface("ITerrainEffect", false) != null) + { + ITerrainEffect terEffect = (ITerrainEffect) Activator.CreateInstance(library.GetType(pluginType.ToString())); - InstallPlugin(typeName, terEffect); - } - else if (pluginType.GetInterface("ITerrainLoader", false) != null) - { - ITerrainLoader terLoader = (ITerrainLoader)Activator.CreateInstance(library.GetType(pluginType.ToString())); - m_loaders[terLoader.FileExtension] = terLoader; - m_log.Info("L ... " + typeName); + InstallPlugin(typeName, terEffect); + } + else if (pluginType.GetInterface("ITerrainLoader", false) != null) + { + ITerrainLoader terLoader = (ITerrainLoader) Activator.CreateInstance(library.GetType(pluginType.ToString())); + m_loaders[terLoader.FileExtension] = terLoader; + m_log.Info("L ... " + typeName); + } + } + catch (AmbiguousMatchException) + { + } } } - catch (AmbiguousMatchException) + catch (BadImageFormatException) { } } @@ -1184,8 +1178,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain private void InterfaceRunPluginEffect(Object[] args) { - string firstArg = (string)args[0]; - if (firstArg == "list") + if ((string) args[0] == "list") { m_log.Info("List of loaded plugins"); foreach (KeyValuePair kvp in m_plugineffects) @@ -1194,14 +1187,14 @@ namespace OpenSim.Region.CoreModules.World.Terrain } return; } - if (firstArg == "reload") + if ((string) args[0] == "reload") { LoadPlugins(); return; } - if (m_plugineffects.ContainsKey(firstArg)) + if (m_plugineffects.ContainsKey((string) args[0])) { - m_plugineffects[firstArg].RunEffect(m_channel); + m_plugineffects[(string) args[0]].RunEffect(m_channel); CheckForTerrainUpdates(); } else diff --git a/OpenSim/Region/CoreModules/World/Warp3DMap/Warp3DImageModule.cs b/OpenSim/Region/CoreModules/World/Warp3DMap/Warp3DImageModule.cs index 33f6c3f..3c48d07 100644 --- a/OpenSim/Region/CoreModules/World/Warp3DMap/Warp3DImageModule.cs +++ b/OpenSim/Region/CoreModules/World/Warp3DMap/Warp3DImageModule.cs @@ -222,13 +222,6 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap bitmap = ImageUtils.ResizeImage(origBitmap, viewport.Width, viewport.Height); } - // XXX: It shouldn't really be necesary to force a GC here as one should occur anyway pretty shortly - // afterwards. It's generally regarded as a bad idea to manually GC. If Warp3D is using lots of memory - // then this may be some issue with the Warp3D code itself, though it's also quite possible that generating - // this map tile simply takes a lot of memory. - GC.Collect(); - m_log.Debug("[WARP 3D IMAGE MODULE]: GC.Collect()"); - return bitmap; } diff --git a/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs b/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs index d781eae..90a13a7 100644 --- a/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs +++ b/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs @@ -114,15 +114,6 @@ namespace OpenSim.Region.Framework.Interfaces void DetachSingleAttachmentToGround(IScenePresence sp, uint objectLocalID); /// - /// Detach the given item to the ground at the specified coordinates & rotation - /// - /// - /// - /// - /// - void DetachSingleAttachmentToGround(IScenePresence sp, uint objectLocalID, Vector3 absolutePos, Quaternion absoluteRot); - - /// /// Detach the given attachment so that it remains in the user's inventory. /// /// /param> diff --git a/OpenSim/Region/Framework/Interfaces/IDynamicTextureManager.cs b/OpenSim/Region/Framework/Interfaces/IDynamicTextureManager.cs index 6df5cc2..8954513 100644 --- a/OpenSim/Region/Framework/Interfaces/IDynamicTextureManager.cs +++ b/OpenSim/Region/Framework/Interfaces/IDynamicTextureManager.cs @@ -25,8 +25,6 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -using System; -using System.Drawing; using System.IO; using OpenMetaverse; @@ -35,14 +33,7 @@ namespace OpenSim.Region.Framework.Interfaces public interface IDynamicTextureManager { void RegisterRender(string handleType, IDynamicTextureRender render); - - /// - /// Used by IDynamicTextureRender implementations to return renders - /// - /// - /// - /// - void ReturnData(UUID id, IDynamicTexture texture); + void ReturnData(UUID id, byte[] data); UUID AddDynamicTextureURL(UUID simID, UUID primID, string contentType, string url, string extraParams, int updateTimer); @@ -122,65 +113,11 @@ namespace OpenSim.Region.Framework.Interfaces string GetName(); string GetContentType(); bool SupportsAsynchronous(); - -// /// -// /// Return true if converting the input body and extra params data will always result in the same byte[] array -// /// -// /// -// /// This method allows the caller to use a previously generated asset if it has one. -// /// -// /// -// /// -// /// -// bool AlwaysIdenticalConversion(string bodyData, string extraParams); - - IDynamicTexture ConvertUrl(string url, string extraParams); - IDynamicTexture ConvertData(string bodyData, string extraParams); - + byte[] ConvertUrl(string url, string extraParams); + byte[] ConvertStream(Stream data, string extraParams); bool AsyncConvertUrl(UUID id, string url, string extraParams); bool AsyncConvertData(UUID id, string bodyData, string extraParams); - void GetDrawStringSize(string text, string fontName, int fontSize, out double xSize, out double ySize); } - - public interface IDynamicTexture - { - /// - /// Input commands used to generate this data. - /// - /// - /// Null if input commands were not used. - /// - string InputCommands { get; } - - /// - /// Uri used to generate this data. - /// - /// - /// Null if a uri was not used. - /// - Uri InputUri { get; } - - /// - /// Extra input params used to generate this data. - /// - string InputParams { get; } - - /// - /// Texture data. - /// - byte[] Data { get; } - - /// - /// Size of texture. - /// - Size Size { get; } - - /// - /// Signal whether the texture is reuseable (i.e. whether the same input data will always generate the same - /// texture). - /// - bool IsReuseable { get; } - } } diff --git a/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs b/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs index 8028d87..4274cbe 100644 --- a/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs +++ b/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs @@ -152,19 +152,6 @@ namespace OpenSim.Region.Framework.Interfaces void StopScriptInstance(UUID itemId); /// - /// Try to get the script running status. - /// - /// - /// Returns true if a script for the item was found in one of the simulator's script engines. In this case, - /// the running parameter will reflect the running status. - /// Returns false if the item could not be found, if the item is not a script or if a script instance for the - /// item was not found in any of the script engines. In this case, running status is irrelevant. - /// - /// - /// - bool TryGetScriptInstanceRunning(UUID itemId, out bool running); - - /// /// Add an item to this entity's inventory. If an item with the same name already exists, then an alternative /// name is chosen. /// @@ -283,25 +270,17 @@ namespace OpenSim.Region.Framework.Interfaces void ApplyGodPermissions(uint perms); /// - /// Number of items in this inventory. - /// - int Count { get; } - - /// /// Returns true if this inventory contains any scripts /// bool ContainsScripts(); /// - /// Number of scripts in this inventory. - /// - /// - /// Includes both running and non running scripts. - /// + /// Returns the count of scripts contained + /// int ScriptCount(); /// - /// Number of running scripts in this inventory. + /// Returns the count of running scripts contained /// int RunningScriptCount(); diff --git a/OpenSim/Region/Framework/Interfaces/IEstateModule.cs b/OpenSim/Region/Framework/Interfaces/IEstateModule.cs index 292efa4..ca2ad94 100644 --- a/OpenSim/Region/Framework/Interfaces/IEstateModule.cs +++ b/OpenSim/Region/Framework/Interfaces/IEstateModule.cs @@ -46,10 +46,6 @@ namespace OpenSim.Region.Framework.Interfaces /// void sendRegionHandshakeToAll(); void TriggerEstateInfoChange(); - - /// - /// Fires the OnRegionInfoChange event. - /// void TriggerRegionInfoChange(); void setEstateTerrainBaseTexture(int level, UUID texture); diff --git a/OpenSim/Region/Framework/Interfaces/IJsonStoreModule.cs b/OpenSim/Region/Framework/Interfaces/IJsonStoreModule.cs index da39e95..baac6e8 100644 --- a/OpenSim/Region/Framework/Interfaces/IJsonStoreModule.cs +++ b/OpenSim/Region/Framework/Interfaces/IJsonStoreModule.cs @@ -35,7 +35,7 @@ namespace OpenSim.Region.Framework.Interfaces public interface IJsonStoreModule { - bool CreateStore(string value, ref UUID result); + bool CreateStore(string value, out UUID result); bool DestroyStore(UUID storeID); bool TestPath(UUID storeID, string path, bool useJson); bool SetValue(UUID storeID, string path, string value, bool useJson); diff --git a/OpenSim/Region/Framework/Interfaces/IScriptModuleComms.cs b/OpenSim/Region/Framework/Interfaces/IScriptModuleComms.cs index 70ff954..a76ffde 100644 --- a/OpenSim/Region/Framework/Interfaces/IScriptModuleComms.cs +++ b/OpenSim/Region/Framework/Interfaces/IScriptModuleComms.cs @@ -47,46 +47,9 @@ namespace OpenSim.Region.Framework.Interfaces /// event ScriptCommand OnScriptCommand; - /// - /// Register an instance method as a script call by method name - /// - /// - /// void RegisterScriptInvocation(object target, string method); - - /// - /// Register a static or instance method as a script call by method info - /// - /// If target is a Type object, will assume method is static. - /// void RegisterScriptInvocation(object target, MethodInfo method); - - /// - /// Register one or more instance methods as script calls by method name - /// - /// - /// void RegisterScriptInvocation(object target, string[] methods); - - /// - /// Register one or more static methods as script calls by method name - /// - /// - /// - void RegisterScriptInvocation(Type target, string[] methods); - - /// - /// Automatically register script invocations by checking for methods - /// with . Should only check - /// public methods. - /// - /// - void RegisterScriptInvocations(IRegionModuleBase target); - - /// - /// Returns an array of all registered script calls - /// - /// Delegate[] GetScriptInvocationList(); Delegate LookupScriptInvocation(string fname); @@ -105,44 +68,12 @@ namespace OpenSim.Region.Framework.Interfaces /// void DispatchReply(UUID scriptId, int code, string text, string key); - /// - /// Operation to for a region module to register a constant to be used - /// by the script engine - /// - /// - /// The name of the constant. LSL convention is for constant names to - /// be uppercase. - /// - /// - /// The value of the constant. Should be of a type that can be - /// converted to one of - /// + /// For constants void RegisterConstant(string cname, object value); - - /// - /// Automatically register all constants on a region module by - /// checking for fields with . - /// - /// - void RegisterConstants(IRegionModuleBase target); - - /// - /// Operation to check for a registered constant - /// - /// Name of constant - /// Value of constant or null if none found. object LookupModConstant(string cname); Dictionary GetConstants(); // For use ONLY by the script API void RaiseEvent(UUID script, string id, string module, string command, string key); } - - [AttributeUsage(AttributeTargets.Method)] - public class ScriptInvocationAttribute : Attribute - { } - - [AttributeUsage(AttributeTargets.Field)] - public class ScriptConstantAttribute : Attribute - { } } diff --git a/OpenSim/Region/Framework/Interfaces/ISoundModule.cs b/OpenSim/Region/Framework/Interfaces/ISoundModule.cs index 68af492..6117a80 100644 --- a/OpenSim/Region/Framework/Interfaces/ISoundModule.cs +++ b/OpenSim/Region/Framework/Interfaces/ISoundModule.cs @@ -32,96 +32,9 @@ namespace OpenSim.Region.Framework.Interfaces { public interface ISoundModule { - /// - /// Maximum distance between a sound source and a recipient. - /// - float MaxDistance { get; } - - /// - /// Play a sound from an object. - /// - /// Sound asset ID - /// Sound source owner - /// Sound source ID - /// Sound volume - /// Sound source position - /// Sound flags - /// - /// Radius used to affect gain over distance. - /// - void PlayAttachedSound(UUID soundID, UUID ownerID, UUID objectID, - double gain, Vector3 position, byte flags, float radius); - - /// - /// Trigger a sound in the scene. - /// - /// Sound asset ID - /// Sound source owner - /// Sound source ID - /// Sound source parent. - /// Sound volume - /// Sound source position - /// - /// - /// Radius used to affect gain over distance. - /// + void PlayAttachedSound(UUID soundID, UUID ownerID, UUID objectID, double gain, Vector3 position, byte flags, float radius); + void TriggerSound( - UUID soundId, UUID ownerID, UUID objectID, UUID parentID, - double gain, Vector3 position, UInt64 handle, float radius); - - /// - /// Stop sounds eminating from an object. - /// - /// Sound source ID - void StopSound(UUID objectID); - - /// - /// Preload sound to viewers within range. - /// - /// Sound source ID - /// Sound asset ID - /// - /// Radius used to determine which viewers should preload the sound. - /// - void PreloadSound(UUID objectID, UUID soundID, float radius); - - /// - /// Loop specified sound at specified volume with specified radius, - /// optionally declaring object as new sync master. - /// - /// Sound source ID - /// Sound asset ID - /// Sound volume - /// Sound radius - /// Set object to sync master if true - void LoopSound(UUID objectID, UUID soundID, double gain, - double radius, bool isMaster); - - /// - /// Trigger or play an attached sound in this part's inventory. - /// - /// Sound source ID - /// Sound asset ID - /// Sound volume - /// Triggered or not. - /// - /// Sound radius - /// Play using sound master - /// Play as sound master - void SendSound(UUID objectID, UUID sound, double volume, - bool triggered, byte flags, float radius, bool useMaster, - bool isMaster); - - /// - /// Trigger a sound to be played to all agents within an axis-aligned - /// bounding box. - /// - /// Sound source ID - /// Sound asset ID - /// Sound volume - /// AABB bottom south-west corner - /// AABB top north-east corner - void TriggerSoundLimited(UUID objectID, UUID sound, double volume, - Vector3 min, Vector3 max); + UUID soundId, UUID ownerID, UUID objectID, UUID parentID, double gain, Vector3 position, UInt64 handle, float radius); } } \ No newline at end of file diff --git a/OpenSim/Region/Framework/Interfaces/IUrlModule.cs b/OpenSim/Region/Framework/Interfaces/IUrlModule.cs index 79e9f9d..457444c 100644 --- a/OpenSim/Region/Framework/Interfaces/IUrlModule.cs +++ b/OpenSim/Region/Framework/Interfaces/IUrlModule.cs @@ -39,8 +39,6 @@ namespace OpenSim.Region.Framework.Interfaces UUID RequestSecureURL(IScriptModule engine, SceneObjectPart host, UUID itemID); void ReleaseURL(string url); void HttpResponse(UUID request, int status, string body); - void HttpContentType(UUID request, string type); - string GetHttpHeader(UUID request, string header); int GetFreeUrls(); diff --git a/OpenSim/Region/Framework/Interfaces/IUserManagement.cs b/OpenSim/Region/Framework/Interfaces/IUserManagement.cs index f8088c3..24cd069 100644 --- a/OpenSim/Region/Framework/Interfaces/IUserManagement.cs +++ b/OpenSim/Region/Framework/Interfaces/IUserManagement.cs @@ -1,31 +1,4 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; +using System; using System.Collections.Generic; using OpenMetaverse; diff --git a/OpenSim/Region/Framework/Interfaces/IWorldComm.cs b/OpenSim/Region/Framework/Interfaces/IWorldComm.cs index 20e0199..e8e375e 100644 --- a/OpenSim/Region/Framework/Interfaces/IWorldComm.cs +++ b/OpenSim/Region/Framework/Interfaces/IWorldComm.cs @@ -45,13 +45,6 @@ namespace OpenSim.Region.Framework.Interfaces void Deactivate(); void Activate(); UUID GetID(); - - /// - /// Bitfield indicating which strings should be processed as regex. - /// 1 corresponds to IWorldCommListenerInfo::GetName() - /// 2 corresponds to IWorldCommListenerInfo::GetMessage() - /// - int RegexBitfield { get; } } public interface IWorldComm @@ -67,7 +60,7 @@ namespace OpenSim.Region.Framework.Interfaces /// the script during 'peek' time. Parameter hostID is needed to /// determine the position of the script. /// - /// localID of the script engine + /// localID of the script engine /// UUID of the script engine /// UUID of the SceneObjectPart /// channel to listen on @@ -77,23 +70,6 @@ namespace OpenSim.Region.Framework.Interfaces /// number of the scripts handle int Listen(uint LocalID, UUID itemID, UUID hostID, int channel, string name, UUID id, string msg); - /// - /// Create a listen event callback with the specified filters. - /// The parameters localID,itemID are needed to uniquely identify - /// the script during 'peek' time. Parameter hostID is needed to - /// determine the position of the script. - /// - /// localID of the script engine - /// UUID of the script engine - /// UUID of the SceneObjectPart - /// channel to listen on - /// name to filter on - /// key to filter on (user given, could be totally faked) - /// msg to filter on - /// Bitfield indicating which strings should be processed as regex. - /// number of the scripts handle - int Listen(uint LocalID, UUID itemID, UUID hostID, int channel, string name, UUID id, string msg, int regexBitfield); - /// /// This method scans over the objects which registered an interest in listen callbacks. /// For everyone it finds, it checks if it fits the given filter. If it does, then diff --git a/OpenSim/Region/Framework/Scenes/Animation/AnimationSet.cs b/OpenSim/Region/Framework/Scenes/Animation/AnimationSet.cs index 65ae445..ad421ee 100644 --- a/OpenSim/Region/Framework/Scenes/Animation/AnimationSet.cs +++ b/OpenSim/Region/Framework/Scenes/Animation/AnimationSet.cs @@ -41,7 +41,6 @@ namespace OpenSim.Region.Framework.Scenes.Animation { // private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - private OpenSim.Framework.Animation m_implicitDefaultAnimation = new OpenSim.Framework.Animation(); private OpenSim.Framework.Animation m_defaultAnimation = new OpenSim.Framework.Animation(); private List m_animations = new List(); @@ -50,11 +49,6 @@ namespace OpenSim.Region.Framework.Scenes.Animation get { return m_defaultAnimation; } } - public OpenSim.Framework.Animation ImplicitDefaultAnimation - { - get { return m_implicitDefaultAnimation; } - } - public AnimationSet() { ResetDefaultAnimation(); @@ -125,18 +119,11 @@ namespace OpenSim.Region.Framework.Scenes.Animation if (m_defaultAnimation.AnimID != animID) { m_defaultAnimation = new OpenSim.Framework.Animation(animID, sequenceNum, objectID); - m_implicitDefaultAnimation = m_defaultAnimation; return true; } return false; } - // Called from serialization only - public void SetImplicitDefaultAnimation(UUID animID, int sequenceNum, UUID objectID) - { - m_implicitDefaultAnimation = new OpenSim.Framework.Animation(animID, sequenceNum, objectID); - } - protected bool ResetDefaultAnimation() { return TrySetDefaultAnimation("STAND", 1, UUID.Zero); diff --git a/OpenSim/Region/Framework/Scenes/EventManager.cs b/OpenSim/Region/Framework/Scenes/EventManager.cs index 5b1c9f4..4a19c3b 100644 --- a/OpenSim/Region/Framework/Scenes/EventManager.cs +++ b/OpenSim/Region/Framework/Scenes/EventManager.cs @@ -47,75 +47,30 @@ namespace OpenSim.Region.Framework.Scenes public delegate void OnFrameDelegate(); - /// - /// Triggered on each sim frame. - /// - /// - /// This gets triggered in - /// Core uses it for things like Sun, Wind & Clouds - /// The MRM module also uses it. - /// public event OnFrameDelegate OnFrame; public delegate void ClientMovement(ScenePresence client); - /// - /// Trigerred when an agent moves. - /// - /// - /// This gets triggered in - /// prior to - /// public event ClientMovement OnClientMovement; public delegate void OnTerrainTaintedDelegate(); - /// - /// Triggered if the terrain has been edited - /// - /// - /// This gets triggered in - /// after it determines that an update has been made. - /// public event OnTerrainTaintedDelegate OnTerrainTainted; public delegate void OnTerrainTickDelegate(); - /// - /// Triggered if the terrain has been edited - /// - /// - /// This gets triggered in - /// but is used by core solely to update the physics engine. - /// - public event OnTerrainTickDelegate OnTerrainTick; - public delegate void OnTerrainUpdateDelegate(); + public event OnTerrainTickDelegate OnTerrainTick; + public event OnTerrainUpdateDelegate OnTerrainUpdate; public delegate void OnBackupDelegate(ISimulationDataService datastore, bool forceBackup); - /// - /// Triggered when a region is backed up/persisted to storage - /// - /// - /// This gets triggered in - /// and is fired before the persistence occurs. - /// public event OnBackupDelegate OnBackup; public delegate void OnClientConnectCoreDelegate(IClientCore client); - /// - /// Triggered when a new client connects to the scene. - /// - /// - /// This gets triggered in , - /// which checks if an instance of - /// also implements and as such, - /// is not triggered by NPCs. - /// public event OnClientConnectCoreDelegate OnClientConnect; public delegate void OnNewClientDelegate(IClientAPI client); @@ -125,96 +80,33 @@ namespace OpenSim.Region.Framework.Scenes /// /// /// This is triggered for both child and root agent client connections. - /// /// Triggered before OnClientLogin. - /// - /// This is triggered under per-agent lock. So if you want to perform any long-running operations, please - /// do this on a separate thread. /// public event OnNewClientDelegate OnNewClient; /// /// Fired if the client entering this sim is doing so as a new login /// - /// - /// This is triggered under per-agent lock. So if you want to perform any long-running operations, please - /// do this on a separate thread. - /// public event Action OnClientLogin; public delegate void OnNewPresenceDelegate(ScenePresence presence); - /// - /// Triggered when a new presence is added to the scene - /// - /// - /// Triggered in which is used by both - /// users and NPCs - /// public event OnNewPresenceDelegate OnNewPresence; public delegate void OnRemovePresenceDelegate(UUID agentId); - /// - /// Triggered when a presence is removed from the scene - /// - /// - /// Triggered in which is used by both - /// users and NPCs - /// - /// Triggered under per-agent lock. So if you want to perform any long-running operations, please - /// do this on a separate thread. - /// public event OnRemovePresenceDelegate OnRemovePresence; public delegate void OnParcelPrimCountUpdateDelegate(); - /// - /// Triggered whenever the prim count may have been altered, or prior - /// to an action that requires the current prim count to be accurate. - /// - /// - /// Triggered by in - /// , - /// , - /// , - /// , - /// , - /// , - /// - /// public event OnParcelPrimCountUpdateDelegate OnParcelPrimCountUpdate; public delegate void OnParcelPrimCountAddDelegate(SceneObjectGroup obj); - /// - /// Triggered in response to for - /// objects that actually contribute to parcel prim count. - /// - /// - /// Triggered by in - /// - /// public event OnParcelPrimCountAddDelegate OnParcelPrimCountAdd; public delegate void OnPluginConsoleDelegate(string[] args); - /// - /// Triggered after - /// has been called for all - /// loaded via . - /// Handlers for this event are typically used to parse the arguments - /// from in order to process or - /// filter the arguments and pass them onto - /// - /// - /// Triggered by in - /// via - /// via - /// via - /// via - /// - /// public event OnPluginConsoleDelegate OnPluginConsole; /// @@ -229,28 +121,8 @@ namespace OpenSim.Region.Framework.Scenes public delegate void OnSetRootAgentSceneDelegate(UUID agentID, Scene scene); - /// - /// Triggered before the grunt work for adding a root agent to a - /// scene has been performed (resuming attachment scripts, physics, - /// animations etc.) - /// - /// - /// Triggered before - /// by - /// in - /// via - /// and - /// public event OnSetRootAgentSceneDelegate OnSetRootAgentScene; - /// - /// Triggered after parcel properties have been updated. - /// - /// - /// Triggered by in - /// , - /// - /// public event ParcelPropertiesUpdateRequest OnParcelPropertiesUpdateRequest; /// @@ -265,45 +137,13 @@ namespace OpenSim.Region.Framework.Scenes /// /// Fired when an object is touched/grabbed. /// - /// /// The originalID is the local ID of the part that was actually touched. The localID itself is always that of /// the root part. - /// Triggerd in response to - /// via - /// in - /// public event ObjectGrabDelegate OnObjectGrab; public delegate void ObjectGrabDelegate(uint localID, uint originalID, Vector3 offsetPos, IClientAPI remoteClient, SurfaceTouchEventArgs surfaceArgs); - /// - /// Triggered when an object is being touched/grabbed continuously. - /// - /// - /// Triggered in response to - /// via - /// in - /// public event ObjectGrabDelegate OnObjectGrabbing; - - /// - /// Triggered when an object stops being touched/grabbed. - /// - /// - /// Triggered in response to - /// via - /// in - /// public event ObjectDeGrabDelegate OnObjectDeGrab; - - /// - /// Triggered when a script resets. - /// - /// - /// Triggered by - /// in - /// via - /// via - /// public event ScriptResetDelegate OnScriptReset; public event OnPermissionErrorDelegate OnPermissionError; @@ -313,105 +153,29 @@ namespace OpenSim.Region.Framework.Scenes /// /// /// Occurs after OnNewScript. - /// Triggered by - /// in /// public event NewRezScript OnRezScript; public delegate void NewRezScript(uint localID, UUID itemID, string script, int startParam, bool postOnRez, string engine, int stateSource); public delegate void RemoveScript(uint localID, UUID itemID); - - /// - /// Triggered when a script is removed from an object. - /// - /// - /// Triggered by - /// in , - /// , - /// , - /// - /// public event RemoveScript OnRemoveScript; public delegate void StartScript(uint localID, UUID itemID); - - /// - /// Triggered when a script starts. - /// - /// - /// Triggered by - /// in - /// via , - /// via - /// public event StartScript OnStartScript; public delegate void StopScript(uint localID, UUID itemID); - - /// - /// Triggered when a script stops. - /// - /// - /// Triggered by , - /// in , - /// , - /// - /// public event StopScript OnStopScript; public delegate bool SceneGroupMoved(UUID groupID, Vector3 delta); - - /// - /// Triggered when an object is moved. - /// - /// - /// Triggered by - /// in , - /// - /// public event SceneGroupMoved OnSceneGroupMove; public delegate void SceneGroupGrabed(UUID groupID, Vector3 offset, UUID userID); - - /// - /// Triggered when an object is grabbed. - /// - /// - /// Triggered by - /// in - /// via - /// via - /// via - /// via - /// public event SceneGroupGrabed OnSceneGroupGrab; public delegate bool SceneGroupSpinStarted(UUID groupID); - - /// - /// Triggered when an object starts to spin. - /// - /// - /// Triggered by - /// in - /// via - /// via - /// via - /// public event SceneGroupSpinStarted OnSceneGroupSpinStart; public delegate bool SceneGroupSpun(UUID groupID, Quaternion rotation); - - /// - /// Triggered when an object is being spun. - /// - /// - /// Triggered by - /// in - /// via - /// via - /// via - /// public event SceneGroupSpun OnSceneGroupSpin; public delegate void LandObjectAdded(ILandObject newParcel); @@ -440,9 +204,6 @@ namespace OpenSim.Region.Framework.Scenes /// /// /// At the point of firing, the scene still contains the client's scene presence. - /// - /// This is triggered under per-agent lock. So if you want to perform any long-running operations, please - /// do this on a separate thread. /// public event ClientClosed OnClientClosed; @@ -453,9 +214,6 @@ namespace OpenSim.Region.Framework.Scenes /// /// /// Occurs before OnRezScript - /// Triggered by - /// in , - /// /// public event NewScript OnNewScript; @@ -490,12 +248,6 @@ namespace OpenSim.Region.Framework.Scenes /// /// /// Triggered after the scene receives a client's upload of an updated script and has stored it in an asset. - /// Triggered by - /// in - /// via - /// via - /// via - /// via /// public event UpdateScript OnUpdateScript; @@ -521,203 +273,48 @@ namespace OpenSim.Region.Framework.Scenes } /// - /// Triggered when some scene object properties change. - /// - /// /// ScriptChangedEvent is fired when a scene object property that a script might be interested /// in (such as color, scale or inventory) changes. Only enough information sent is for the LSL changed event. /// This is not an indication that the script has changed (see OnUpdateScript for that). /// This event is sent to a script to tell it that some property changed on /// the object the script is in. See http://lslwiki.net/lslwiki/wakka.php?wakka=changed . - /// Triggered by - /// in , - /// - /// + /// public event ScriptChangedEvent OnScriptChangedEvent; public delegate void ScriptChangedEvent(uint localID, uint change); public delegate void ScriptControlEvent(UUID item, UUID avatarID, uint held, uint changed); - - /// - /// Triggered when a script receives control input from an agent. - /// - /// - /// Triggered by - /// in - /// via - /// via - /// via - /// public event ScriptControlEvent OnScriptControlEvent; public delegate void ScriptAtTargetEvent(uint localID, uint handle, Vector3 targetpos, Vector3 atpos); - - /// - /// Triggered when an object has arrived within a tolerance distance - /// of a motion target. - /// - /// - /// Triggered by - /// in - /// via , - /// via - /// public event ScriptAtTargetEvent OnScriptAtTargetEvent; public delegate void ScriptNotAtTargetEvent(uint localID); - - /// - /// Triggered when an object has a motion target but has not arrived - /// within a tolerance distance. - /// - /// - /// Triggered by - /// in - /// via , - /// via - /// public event ScriptNotAtTargetEvent OnScriptNotAtTargetEvent; public delegate void ScriptAtRotTargetEvent(uint localID, uint handle, Quaternion targetrot, Quaternion atrot); - - /// - /// Triggered when an object has arrived within a tolerance rotation - /// of a rotation target. - /// - /// - /// Triggered by - /// in - /// via , - /// via - /// public event ScriptAtRotTargetEvent OnScriptAtRotTargetEvent; public delegate void ScriptNotAtRotTargetEvent(uint localID); - - /// - /// Triggered when an object has a rotation target but has not arrived - /// within a tolerance rotation. - /// - /// - /// Triggered by - /// in - /// via , - /// via - /// public event ScriptNotAtRotTargetEvent OnScriptNotAtRotTargetEvent; public delegate void ScriptColliding(uint localID, ColliderArgs colliders); - - /// - /// Triggered when a physical collision has started between a prim - /// and something other than the region terrain. - /// - /// - /// Triggered by - /// in - /// via - /// via - /// via - /// public event ScriptColliding OnScriptColliderStart; - - /// - /// Triggered when something that previously collided with a prim has - /// not stopped colliding with it. - /// - /// - /// - /// Triggered by - /// in - /// via - /// via - /// via - /// public event ScriptColliding OnScriptColliding; - - /// - /// Triggered when something that previously collided with a prim has - /// stopped colliding with it. - /// - /// - /// Triggered by - /// in - /// via - /// via - /// via - /// public event ScriptColliding OnScriptCollidingEnd; - - /// - /// Triggered when a physical collision has started between an object - /// and the region terrain. - /// - /// - /// Triggered by - /// in - /// via - /// via - /// via - /// public event ScriptColliding OnScriptLandColliderStart; - - /// - /// Triggered when an object that previously collided with the region - /// terrain has not yet stopped colliding with it. - /// - /// - /// Triggered by - /// in - /// via - /// via - /// via - /// public event ScriptColliding OnScriptLandColliding; - - /// - /// Triggered when an object that previously collided with the region - /// terrain has stopped colliding with it. - /// - /// - /// Triggered by - /// in - /// via - /// via - /// via - /// public event ScriptColliding OnScriptLandColliderEnd; public delegate void OnMakeChildAgentDelegate(ScenePresence presence); - - /// - /// Triggered when an agent has been made a child agent of a scene. - /// - /// - /// Triggered by - /// in - /// via , - /// , - /// - /// public event OnMakeChildAgentDelegate OnMakeChildAgent; public delegate void OnSaveNewWindlightProfileDelegate(); public delegate void OnSendNewWindlightProfileTargetedDelegate(RegionLightShareData wl, UUID user); /// - /// Triggered after the grunt work for adding a root agent to a - /// scene has been performed (resuming attachment scripts, physics, - /// animations etc.) - /// - /// /// This event is on the critical path for transferring an avatar from one region to another. Try and do /// as little work on this event as possible, or do work asynchronously. - /// Triggered after - /// by - /// in - /// via - /// and - /// + /// public event Action OnMakeRootAgent; public event OnSendNewWindlightProfileTargetedDelegate OnSendNewWindlightProfileTargeted; @@ -743,17 +340,9 @@ namespace OpenSim.Region.Framework.Scenes public event AvatarKillData OnAvatarKilled; public delegate void AvatarKillData(uint KillerLocalID, ScenePresence avatar); - /* - public delegate void ScriptTimerEvent(uint localID, double timerinterval); - /// - /// Used to be triggered when the LSL timer event fires. - /// - /// - /// Triggered by - /// via - /// - public event ScriptTimerEvent OnScriptTimerEvent; - */ +// public delegate void ScriptTimerEvent(uint localID, double timerinterval); + +// public event ScriptTimerEvent OnScriptTimerEvent; public delegate void EstateToolsSunUpdate(ulong regionHandle, bool FixedTime, bool EstateSun, float LindenHour); public delegate void GetScriptRunning(IClientAPI controllingClient, UUID objectID, UUID itemID); @@ -763,27 +352,12 @@ namespace OpenSim.Region.Framework.Scenes /// /// Triggered when an object is added to the scene. /// - /// - /// Triggered by - /// in , - /// , - /// - /// public event Action OnObjectAddedToScene; /// - /// Delegate for - /// - /// The object being removed from the scene - public delegate void ObjectBeingRemovedFromScene(SceneObjectGroup obj); - - /// /// Triggered when an object is removed from the scene. /// - /// - /// Triggered by - /// in - /// + public delegate void ObjectBeingRemovedFromScene(SceneObjectGroup obj); public event ObjectBeingRemovedFromScene OnObjectBeingRemovedFromScene; public delegate void NoticeNoLandDataFromStorage(); @@ -799,20 +373,6 @@ namespace OpenSim.Region.Framework.Scenes public event RequestParcelPrimCountUpdate OnRequestParcelPrimCountUpdate; public delegate void ParcelPrimCountTainted(); - - /// - /// Triggered when the parcel prim count has been altered. - /// - /// - /// Triggered by in - /// , - /// , - /// , - /// , - /// , - /// , - /// - /// public event ParcelPrimCountTainted OnParcelPrimCountTainted; public event GetScriptRunning OnGetScriptRunning; @@ -876,7 +436,7 @@ namespace OpenSim.Region.Framework.Scenes /// the scripts may not have started yet /// Message is non empty string if there were problems loading the oar file /// - public delegate void OarFileLoaded(Guid guid, List loadedScenes, string message); + public delegate void OarFileLoaded(Guid guid, string message); public event OarFileLoaded OnOarFileLoaded; /// @@ -929,13 +489,10 @@ namespace OpenSim.Region.Framework.Scenes /// /// /// True if the duplicate will immediately be in the scene, false otherwise - /// - /// Triggered in - /// public event SceneObjectPartCopyDelegate OnSceneObjectPartCopy; public delegate void SceneObjectPartCopyDelegate(SceneObjectPart copy, SceneObjectPart original, bool userExposed); - public delegate void SceneObjectPartUpdated(SceneObjectPart sop, bool full); + public delegate void SceneObjectPartUpdated(SceneObjectPart sop); public event SceneObjectPartUpdated OnSceneObjectPartUpdated; public delegate void ScenePresenceUpdated(ScenePresence sp); @@ -973,28 +530,9 @@ namespace OpenSim.Region.Framework.Scenes public event PrimsLoaded OnPrimsLoaded; public delegate void TeleportStart(IClientAPI client, GridRegion destination, GridRegion finalDestination, uint teleportFlags, bool gridLogout); - - /// - /// Triggered when a teleport starts - /// - /// - /// Triggered by - /// in - /// and - /// via - /// public event TeleportStart OnTeleportStart; public delegate void TeleportFail(IClientAPI client, bool gridLogout); - - /// - /// Trigered when a teleport fails. - /// - /// - /// Triggered by - /// in - /// via - /// public event TeleportFail OnTeleportFail; public class MoneyTransferArgs : EventArgs @@ -1002,9 +540,7 @@ namespace OpenSim.Region.Framework.Scenes public UUID sender; public UUID receiver; - /// - /// Always false. The SL protocol sucks. - /// + // Always false. The SL protocol sucks. public bool authenticated = false; public int amount; @@ -1061,29 +597,8 @@ namespace OpenSim.Region.Framework.Scenes public delegate void LandBuy(Object sender, LandBuyArgs e); - /// - /// Triggered when an attempt to transfer grid currency occurs - /// - /// - /// Triggered in - /// via - /// via - /// via - /// public event MoneyTransferEvent OnMoneyTransfer; - - /// - /// Triggered after after - /// public event LandBuy OnLandBuy; - - /// - /// Triggered to allow or prevent a real estate transaction - /// - /// - /// Triggered in - /// - /// public event LandBuy OnValidateLandBuy; public void TriggerOnAttach(uint localID, UUID itemID, UUID avatarID) @@ -2520,11 +2035,7 @@ namespace OpenSim.Region.Framework.Scenes } } - /// - /// this lets us keep track of nasty script events like timer, etc. - /// - /// - /// + // this lets us keep track of nasty script events like timer, etc. public void TriggerTimerEvent(uint objLocalID, double Interval) { throw new NotImplementedException("TriggerTimerEvent was thought to be not used anymore and the registration for the event from scene object part has been commented out due to a memory leak"); @@ -2586,7 +2097,7 @@ namespace OpenSim.Region.Framework.Scenes return 6; } - public void TriggerOarFileLoaded(Guid requestId, List loadedScenes, string message) + public void TriggerOarFileLoaded(Guid requestId, string message) { OarFileLoaded handlerOarFileLoaded = OnOarFileLoaded; if (handlerOarFileLoaded != null) @@ -2595,7 +2106,7 @@ namespace OpenSim.Region.Framework.Scenes { try { - d(requestId, loadedScenes, message); + d(requestId, message); } catch (Exception e) { @@ -2880,7 +2391,7 @@ namespace OpenSim.Region.Framework.Scenes } } - public void TriggerSceneObjectPartUpdated(SceneObjectPart sop, bool full) + public void TriggerSceneObjectPartUpdated(SceneObjectPart sop) { SceneObjectPartUpdated handler = OnSceneObjectPartUpdated; if (handler != null) @@ -2889,7 +2400,7 @@ namespace OpenSim.Region.Framework.Scenes { try { - d(sop, full); + d(sop); } catch (Exception e) { diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs index 6208a57..906c1ee 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs @@ -93,7 +93,7 @@ namespace OpenSim.Region.Framework.Scenes /// public void StartScripts() { -// m_log.InfoFormat("[SCENE]: Starting scripts in {0}, please wait.", RegionInfo.RegionName); + m_log.InfoFormat("[SCENE]: Starting scripts in {0}, please wait.", RegionInfo.RegionName); IScriptModule[] engines = RequestModuleInterfaces(); @@ -1469,7 +1469,7 @@ namespace OpenSim.Region.Framework.Scenes return newFolderID; } - public void SendInventoryUpdate(IClientAPI client, InventoryFolderBase folder, bool fetchFolders, bool fetchItems) + private void SendInventoryUpdate(IClientAPI client, InventoryFolderBase folder, bool fetchFolders, bool fetchItems) { if (folder == null) return; @@ -1997,9 +1997,6 @@ namespace OpenSim.Region.Framework.Scenes // If child prims have invalid perms, fix them grp.AdjustChildPrimPermissions(); - // If child prims have invalid perms, fix them - grp.AdjustChildPrimPermissions(); - if (remoteClient == null) { // Autoreturn has a null client. Nothing else does. So diff --git a/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs b/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs index ce6415a..e970543 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs @@ -38,20 +38,8 @@ namespace OpenSim.Region.Framework.Scenes { public partial class Scene { - /// - /// Send chat to listeners. - /// - /// - /// /param> - /// - /// - /// - /// - /// - /// - /// public void SimChat(byte[] message, ChatTypeEnum type, int channel, Vector3 fromPos, string fromName, - UUID fromID, UUID targetID, bool fromAgent, bool broadcast) + UUID fromID, bool fromAgent, bool broadcast, UUID destination) { OSChatMessage args = new OSChatMessage(); @@ -61,7 +49,7 @@ namespace OpenSim.Region.Framework.Scenes args.Position = fromPos; args.SenderUUID = fromID; args.Scene = this; - args.Destination = targetID; + args.Destination = destination; if (fromAgent) { @@ -78,10 +66,6 @@ namespace OpenSim.Region.Framework.Scenes args.From = fromName; //args. -// m_log.DebugFormat( -// "[SCENE]: Sending message {0} on channel {1}, type {2} from {3}, broadcast {4}", -// args.Message.Replace("\n", "\\n"), args.Channel, args.Type, fromName, broadcast); - if (broadcast) EventManager.TriggerOnChatBroadcast(this, args); else @@ -91,7 +75,7 @@ namespace OpenSim.Region.Framework.Scenes protected void SimChat(byte[] message, ChatTypeEnum type, int channel, Vector3 fromPos, string fromName, UUID fromID, bool fromAgent, bool broadcast) { - SimChat(message, type, channel, fromPos, fromName, fromID, UUID.Zero, fromAgent, broadcast); + SimChat(message, type, channel, fromPos, fromName, fromID, fromAgent, broadcast, UUID.Zero); } /// @@ -559,7 +543,7 @@ namespace OpenSim.Region.Framework.Scenes if (!InventoryService.AddFolder(folder)) { m_log.WarnFormat( - "[AGENT INVENTORY]: Failed to create folder for user {0} {1}", + "[AGENT INVENTORY]: Failed to move create folder for user {0} {1}", remoteClient.Name, remoteClient.AgentId); } } diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 2543333..649d545 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -80,11 +80,6 @@ namespace OpenSim.Region.Framework.Scenes public SynchronizeSceneHandler SynchronizeScene; /// - /// Used to prevent simultaneous calls to RemoveClient() for the same agent from interfering with each other. - /// - private object m_removeClientLock = new object(); - - /// /// Statistical information for this scene. /// public SimStatsReporter StatsReporter { get; private set; } @@ -108,31 +103,8 @@ namespace OpenSim.Region.Framework.Scenes /// public bool CollidablePrims { get; private set; } - /// - /// Minimum value of the size of a non-physical prim in each axis - /// - public float m_minNonphys = 0.001f; - - /// - /// Maximum value of the size of a non-physical prim in each axis - /// public float m_maxNonphys = 256; - - /// - /// Minimum value of the size of a physical prim in each axis - /// - public float m_minPhys = 0.01f; - - /// - /// Maximum value of the size of a physical prim in each axis - /// public float m_maxPhys = 10; - - /// - /// Max prims an object will hold - /// - public int m_linksetCapacity = 0; - public bool m_clampPrimSize; public bool m_trustBinaries; public bool m_allowScriptCrossings; @@ -313,31 +285,6 @@ namespace OpenSim.Region.Framework.Scenes } private volatile bool m_shuttingDown; - /// - /// Is the scene active? - /// - /// - /// If false, maintenance and update loops are not being run. Updates can still be triggered manually if - /// the scene is not active. - /// - public bool Active - { - get { return m_active; } - set - { - if (value) - { - if (!m_active) - Start(); - } - else - { - m_active = false; - } - } - } - private volatile bool m_active; - // private int m_lastUpdate; private bool m_firstHeartbeat = true; @@ -799,24 +746,12 @@ namespace OpenSim.Region.Framework.Scenes PhysicalPrims = startupConfig.GetBoolean("physical_prim", true); CollidablePrims = startupConfig.GetBoolean("collidable_prim", true); - m_minNonphys = startupConfig.GetFloat("NonPhysicalPrimMin", m_minNonphys); - if (RegionInfo.NonphysPrimMin > 0) - { - m_minNonphys = RegionInfo.NonphysPrimMin; - } - - m_maxNonphys = startupConfig.GetFloat("NonPhysicalPrimMax", m_maxNonphys); + m_maxNonphys = startupConfig.GetFloat("NonphysicalPrimMax", m_maxNonphys); if (RegionInfo.NonphysPrimMax > 0) { m_maxNonphys = RegionInfo.NonphysPrimMax; } - m_minPhys = startupConfig.GetFloat("PhysicalPrimMin", m_minPhys); - if (RegionInfo.PhysPrimMin > 0) - { - m_minPhys = RegionInfo.PhysPrimMin; - } - m_maxPhys = startupConfig.GetFloat("PhysicalPrimMax", m_maxPhys); if (RegionInfo.PhysPrimMax > 0) @@ -824,12 +759,6 @@ namespace OpenSim.Region.Framework.Scenes m_maxPhys = RegionInfo.PhysPrimMax; } - m_linksetCapacity = startupConfig.GetInt("LinksetPrims", m_linksetCapacity); - if (RegionInfo.LinksetCapacity > 0) - { - m_linksetCapacity = RegionInfo.LinksetCapacity; - } - SpawnPointRouting = startupConfig.GetString("SpawnPointRouting", "closest"); TelehubAllowLandmarks = startupConfig.GetBoolean("TelehubAllowLandmark", false); @@ -855,6 +784,13 @@ namespace OpenSim.Region.Framework.Scenes m_defaultScriptEngine = startupConfig.GetString("DefaultScriptEngine", "XEngine"); m_log.InfoFormat("[SCENE]: Default script engine {0}", m_defaultScriptEngine); + IConfig packetConfig = m_config.Configs["PacketPool"]; + if (packetConfig != null) + { + PacketPool.Instance.RecyclePackets = packetConfig.GetBoolean("RecyclePackets", true); + PacketPool.Instance.RecycleDataBlocks = packetConfig.GetBoolean("RecycleDataBlocks", true); + } + m_strictAccessControl = startupConfig.GetBoolean("StrictAccessControl", m_strictAccessControl); m_seeIntoBannedRegion = startupConfig.GetBoolean("SeeIntoBannedRegion", m_seeIntoBannedRegion); CombineRegions = startupConfig.GetBoolean("CombineContiguousRegions", false); @@ -918,8 +854,6 @@ namespace OpenSim.Region.Framework.Scenes } // FIXME: Ultimately this should be in a module. - SendPeriodicAppearanceUpdates = true; - IConfig appearanceConfig = m_config.Configs["Appearance"]; if (appearanceConfig != null) { @@ -1217,14 +1151,6 @@ namespace OpenSim.Region.Framework.Scenes public void SetSceneCoreDebug(Dictionary options) { - if (options.ContainsKey("active")) - { - bool active; - - if (bool.TryParse(options["active"], out active)) - Active = active; - } - if (options.ContainsKey("scripting")) { bool enableScripts = true; @@ -1300,12 +1226,6 @@ namespace OpenSim.Region.Framework.Scenes // This is the method that shuts down the scene. public override void Close() { - if (m_shuttingDown) - { - m_log.WarnFormat("[SCENE]: Ignoring close request because already closing {0}", Name); - return; - } - m_log.InfoFormat("[SCENE]: Closing down the single simulator: {0}", RegionInfo.RegionName); StatsReporter.Close(); @@ -1352,14 +1272,6 @@ namespace OpenSim.Region.Framework.Scenes m_log.Debug("[SCENE]: Graph close"); m_sceneGraph.Close(); - if (!GridService.DeregisterRegion(RegionInfo.RegionID)) - m_log.WarnFormat("[SCENE]: Deregister from grid failed for region {0}", Name); - - base.Close(); - - // XEngine currently listens to the EventManager.OnShutdown event to trigger script stop and persistence. - // Therefore. we must dispose of the PhysicsScene after this to prevent a window where script code can - // attempt to reference a null or disposed physics scene. if (PhysicsScene != null) { m_log.Debug("[SCENE]: Dispose Physics"); @@ -1369,6 +1281,13 @@ namespace OpenSim.Region.Framework.Scenes phys.Dispose(); phys = null; } + + if (!GridService.DeregisterRegion(RegionInfo.RegionID)) + m_log.WarnFormat("[SCENE]: Deregister from grid failed for region {0}", Name); + + // call the base class Close method. + m_log.Debug("[SCENE]: Base close"); + base.Close(); } /// @@ -1376,8 +1295,6 @@ namespace OpenSim.Region.Framework.Scenes /// public void Start() { - m_active = true; - // m_log.DebugFormat("[SCENE]: Starting Heartbeat timer for {0}", RegionInfo.RegionName); //m_heartbeatTimer.Enabled = true; @@ -1437,7 +1354,7 @@ namespace OpenSim.Region.Framework.Scenes #region Update Methods /// - /// Activate the various loops necessary to continually update the scene. + /// Performs per-frame updates regularly /// private void Heartbeat() { @@ -1494,7 +1411,7 @@ namespace OpenSim.Region.Framework.Scenes List coarseLocations; List avatarUUIDs; - while (!m_shuttingDown && ((endRun == null && Active) || MaintenanceRun < endRun)) + while (!m_shuttingDown && (endRun == null || MaintenanceRun < endRun)) { runtc = Util.EnvironmentTickCount(); ++MaintenanceRun; @@ -1556,7 +1473,7 @@ namespace OpenSim.Region.Framework.Scenes int sleepMS; int framestart; - while (!m_shuttingDown && ((endFrame == null && Active) || Frame < endFrame)) + while (!m_shuttingDown && (endFrame == null || Frame < endFrame)) { framestart = Util.EnvironmentTickCount(); ++Frame; @@ -1755,19 +1672,15 @@ namespace OpenSim.Region.Framework.Scenes private void CheckAtTargets() { - List objs = null; - + List objs = new List(); lock (m_groupsWithTargets) { - if (m_groupsWithTargets.Count != 0) - objs = new List(m_groupsWithTargets.Values); + foreach (SceneObjectGroup grp in m_groupsWithTargets.Values) + objs.Add(grp); } - if (objs != null) - { - foreach (SceneObjectGroup entry in objs) - entry.checkAtTargets(); - } + foreach (SceneObjectGroup entry in objs) + entry.checkAtTargets(); } /// @@ -2280,14 +2193,10 @@ namespace OpenSim.Region.Framework.Scenes public bool AddRestoredSceneObject( SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates) { - if (m_sceneGraph.AddRestoredSceneObject(sceneObject, attachToBackup, alreadyPersisted, sendClientUpdates)) - { + bool result = m_sceneGraph.AddRestoredSceneObject(sceneObject, attachToBackup, alreadyPersisted, sendClientUpdates); + if (result) sceneObject.IsDeleted = false; - EventManager.TriggerObjectAddedToScene(sceneObject); - return true; - } - - return false; + return result; } /// @@ -2928,89 +2837,77 @@ namespace OpenSim.Region.Framework.Scenes public override ISceneAgent AddNewClient(IClientAPI client, PresenceType type) { - ScenePresence sp; - bool vialogin; - // Validation occurs in LLUDPServer - // - // XXX: A race condition exists here where two simultaneous calls to AddNewClient can interfere with - // each other. In practice, this does not currently occur in the code. AgentCircuitData aCircuit = m_authenticateHandler.GetAgentCircuitData(client.CircuitCode); - // We lock here on AgentCircuitData to prevent a race condition between the thread adding a new connection - // and a simultaneous one that removes it (as can happen if the client is closed at a particular point - // whilst connecting). - // - // It would be easier to lock across all NewUserConnection(), AddNewClient() and - // RemoveClient() calls for all agents, but this would allow a slow call (e.g. because of slow service - // response in some module listening to AddNewClient()) from holding up unrelated agent calls. - // - // In practice, the lock (this) in LLUDPServer.AddNewClient() currently lock across all - // AddNewClient() operations (though not other ops). - // In the future this can be relieved once locking per agent (not necessarily on AgentCircuitData) is improved. - lock (aCircuit) - { - vialogin - = (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaHGLogin) != 0 - || (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaLogin) != 0; - - CheckHeartbeat(); - - sp = GetScenePresence(client.AgentId); + bool vialogin + = (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaHGLogin) != 0 + || (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaLogin) != 0; - // XXX: Not sure how good it is to add a new client if a scene presence already exists. Possibly this - // could occur if a viewer crashes and relogs before the old client is kicked out. But this could cause - // other problems, and possible the code calling AddNewClient() should ensure that no client is already - // connected. - if (sp == null) - { - m_log.DebugFormat( - "[SCENE]: Adding new child scene presence {0} {1} to scene {2} at pos {3}", - client.Name, client.AgentId, RegionInfo.RegionName, client.StartPos); - - m_clientManager.Add(client); - SubscribeToClientEvents(client); - - sp = m_sceneGraph.CreateAndAddChildScenePresence(client, aCircuit.Appearance, type); - m_eventManager.TriggerOnNewPresence(sp); - - sp.TeleportFlags = (TPFlags)aCircuit.teleportFlags; - - // The first agent upon login is a root agent by design. - // For this agent we will have to rez the attachments. - // All other AddNewClient calls find aCircuit.child to be true. - if (aCircuit.child == false) - { - // We have to set SP to be a root agent here so that SP.MakeRootAgent() will later not try to - // start the scripts again (since this is done in RezAttachments()). - // XXX: This is convoluted. - sp.IsChildAgent = false; - - if (AttachmentsModule != null) - Util.FireAndForget(delegate(object o) { AttachmentsModule.RezAttachments(sp); }); - } - } - else + CheckHeartbeat(); + + ScenePresence sp = GetScenePresence(client.AgentId); + + // XXX: Not sure how good it is to add a new client if a scene presence already exists. Possibly this + // could occur if a viewer crashes and relogs before the old client is kicked out. But this could cause + // other problems, and possible the code calling AddNewClient() should ensure that no client is already + // connected. + if (sp == null) + { + m_log.DebugFormat( + "[SCENE]: Adding new child scene presence {0} {1} to scene {2} at pos {3}", + client.Name, client.AgentId, RegionInfo.RegionName, client.StartPos); + + m_clientManager.Add(client); + SubscribeToClientEvents(client); + + sp = m_sceneGraph.CreateAndAddChildScenePresence(client, aCircuit.Appearance, type); + m_eventManager.TriggerOnNewPresence(sp); + + sp.TeleportFlags = (TPFlags)aCircuit.teleportFlags; + + // The first agent upon login is a root agent by design. + // For this agent we will have to rez the attachments. + // All other AddNewClient calls find aCircuit.child to be true. + if (aCircuit.child == false) { - m_log.WarnFormat( - "[SCENE]: Already found {0} scene presence for {1} in {2} when asked to add new scene presence", - sp.IsChildAgent ? "child" : "root", sp.Name, RegionInfo.RegionName); - } - - // We must set this here so that TriggerOnNewClient and TriggerOnClientLogin can determine whether the - // client is for a root or child agent. - client.SceneAgent = sp; + // We have to set SP to be a root agent here so that SP.MakeRootAgent() will later not try to + // start the scripts again (since this is done in RezAttachments()). + // XXX: This is convoluted. + sp.IsChildAgent = false; - // Cache the user's name - CacheUserName(sp, aCircuit); - - EventManager.TriggerOnNewClient(client); - if (vialogin) - EventManager.TriggerOnClientLogin(client); + if (AttachmentsModule != null) + Util.FireAndForget(delegate(object o) { AttachmentsModule.RezAttachments(sp); }); + } + } + else + { + m_log.WarnFormat( + "[SCENE]: Already found {0} scene presence for {1} in {2} when asked to add new scene presence", + sp.IsChildAgent ? "child" : "root", sp.Name, RegionInfo.RegionName); } + // We must set this here so that TriggerOnNewClient and TriggerOnClientLogin can determine whether the + // client is for a root or child agent. + client.SceneAgent = sp; + m_LastLogin = Util.EnvironmentTickCount(); + // Cache the user's name + CacheUserName(sp, aCircuit); + + EventManager.TriggerOnNewClient(client); + if (vialogin) + { + EventManager.TriggerOnClientLogin(client); + // Send initial parcel data +/* this is done on TriggerOnNewClient by landmanegement respective event handler + Vector3 pos = sp.AbsolutePosition; + ILandObject land = LandChannel.GetLandObject(pos.X, pos.Y); + land.SendLandUpdateToClient(client); +*/ + } + return sp; } @@ -3550,132 +3447,110 @@ namespace OpenSim.Region.Framework.Scenes { // CheckHeartbeat(); bool isChildAgent = false; - AgentCircuitData acd; + ScenePresence avatar = GetScenePresence(agentID); - lock (m_removeClientLock) + if (avatar == null) { - acd = m_authenticateHandler.GetAgentCircuitData(agentID); + m_log.WarnFormat( + "[SCENE]: Called RemoveClient() with agent ID {0} but no such presence is in the scene.", agentID); - if (acd == null) - { - m_log.ErrorFormat("[SCENE]: No agent circuit found for {0}, aborting Scene.RemoveClient", agentID); - return; - } - else - { - // We remove the acd up here to avoid later race conditions if two RemoveClient() calls occurred - // simultaneously. - // We also need to remove by agent ID since NPCs will have no circuit code. - m_authenticateHandler.RemoveCircuit(agentID); - } + return; } - lock (acd) + try { - ScenePresence avatar = GetScenePresence(agentID); - - if (avatar == null) - { - m_log.WarnFormat( - "[SCENE]: Called RemoveClient() with agent ID {0} but no such presence is in the scene.", agentID); - - return; - } - - try - { - isChildAgent = avatar.IsChildAgent; + isChildAgent = avatar.IsChildAgent; - m_log.DebugFormat( - "[SCENE]: Removing {0} agent {1} {2} from {3}", - (isChildAgent ? "child" : "root"), avatar.Name, agentID, RegionInfo.RegionName); - - // Don't do this to root agents, it's not nice for the viewer - if (closeChildAgents && isChildAgent) + m_log.DebugFormat( + "[SCENE]: Removing {0} agent {1} {2} from {3}", + (isChildAgent ? "child" : "root"), avatar.Name, agentID, RegionInfo.RegionName); + + // Don't do this to root agents, it's not nice for the viewer + if (closeChildAgents && isChildAgent) + { + // Tell a single agent to disconnect from the region. + IEventQueue eq = RequestModuleInterface(); + if (eq != null) { - // Tell a single agent to disconnect from the region. - IEventQueue eq = RequestModuleInterface(); - if (eq != null) - { - eq.DisableSimulator(RegionInfo.RegionHandle, avatar.UUID); - } - else - { - avatar.ControllingClient.SendShutdownConnectionNotice(); - } + eq.DisableSimulator(RegionInfo.RegionHandle, avatar.UUID); } - - // Only applies to root agents. - if (avatar.ParentID != 0) + else { - avatar.StandUp(); + avatar.ControllingClient.SendShutdownConnectionNotice(); } - - m_sceneGraph.removeUserCount(!isChildAgent); - - // TODO: We shouldn't use closeChildAgents here - it's being used by the NPC module to stop - // unnecessary operations. This should go away once NPCs have no accompanying IClientAPI - if (closeChildAgents && CapsModule != null) - CapsModule.RemoveCaps(agentID); - -// // REFACTORING PROBLEM -- well not really a problem, but just to point out that whatever -// // this method is doing is HORRIBLE!!! - // Commented pending deletion since this method no longer appears to do anything at all -// avatar.Scene.NeedSceneCacheClear(avatar.UUID); - - if (closeChildAgents && !isChildAgent) + } + + // Only applies to root agents. + if (avatar.ParentID != 0) + { + avatar.StandUp(); + } + + m_sceneGraph.removeUserCount(!isChildAgent); + + // TODO: We shouldn't use closeChildAgents here - it's being used by the NPC module to stop + // unnecessary operations. This should go away once NPCs have no accompanying IClientAPI + if (closeChildAgents && CapsModule != null) + CapsModule.RemoveCaps(agentID); + + // REFACTORING PROBLEM -- well not really a problem, but just to point out that whatever + // this method is doing is HORRIBLE!!! + avatar.Scene.NeedSceneCacheClear(avatar.UUID); + + if (closeChildAgents && !isChildAgent) + { + List regions = avatar.KnownRegionHandles; + regions.Remove(RegionInfo.RegionHandle); + m_sceneGridService.SendCloseChildAgentConnections(agentID, regions); + } + + m_eventManager.TriggerClientClosed(agentID, this); + m_eventManager.TriggerOnRemovePresence(agentID); + + if (!isChildAgent) + { + if (AttachmentsModule != null) { - List regions = avatar.KnownRegionHandles; - regions.Remove(RegionInfo.RegionHandle); - m_sceneGridService.SendCloseChildAgentConnections(agentID, regions); + AttachmentsModule.DeRezAttachments(avatar); } - - m_eventManager.TriggerClientClosed(agentID, this); - m_eventManager.TriggerOnRemovePresence(agentID); - - if (!isChildAgent) - { - if (AttachmentsModule != null) + + ForEachClient( + delegate(IClientAPI client) { - AttachmentsModule.DeRezAttachments(avatar); - } + //We can safely ignore null reference exceptions. It means the avatar is dead and cleaned up anyway + try { client.SendKillObject(avatar.RegionHandle, new List { avatar.LocalId }); } + catch (NullReferenceException) { } + }); + } - ForEachClient( - delegate(IClientAPI client) - { - //We can safely ignore null reference exceptions. It means the avatar is dead and cleaned up anyway - try { client.SendKillObject(avatar.RegionHandle, new List { avatar.LocalId }); } - catch (NullReferenceException) { } - }); - } + // It's possible for child agents to have transactions if changes are being made cross-border. + if (AgentTransactionsModule != null) + AgentTransactionsModule.RemoveAgentAssetTransactions(agentID); + + m_authenticateHandler.RemoveCircuit(avatar.ControllingClient.CircuitCode); + m_log.Debug("[Scene] The avatar has left the building"); + } + catch (Exception e) + { + m_log.Error( + string.Format("[SCENE]: Exception removing {0} from {1}. Cleaning up. Exception ", avatar.Name, Name), e); + } + finally + { + try + { + // Always clean these structures up so that any failure above doesn't cause them to remain in the + // scene with possibly bad effects (e.g. continually timing out on unacked packets and triggering + // the same cleanup exception continually. + m_sceneGraph.RemoveScenePresence(agentID); + m_clientManager.Remove(agentID); - // It's possible for child agents to have transactions if changes are being made cross-border. - if (AgentTransactionsModule != null) - AgentTransactionsModule.RemoveAgentAssetTransactions(agentID); - m_log.Debug("[Scene] The avatar has left the building"); + avatar.Close(); } catch (Exception e) { m_log.Error( - string.Format("[SCENE]: Exception removing {0} from {1}. Cleaning up. Exception ", avatar.Name, Name), e); - } - finally - { - try - { - // Always clean these structures up so that any failure above doesn't cause them to remain in the - // scene with possibly bad effects (e.g. continually timing out on unacked packets and triggering - // the same cleanup exception continually. - m_sceneGraph.RemoveScenePresence(agentID); - m_clientManager.Remove(agentID); - - avatar.Close(); - } - catch (Exception e) - { - m_log.Error( - string.Format("[SCENE]: Exception in final clean up of {0} in {1}. Exception ", avatar.Name, Name), e); - } + string.Format("[SCENE]: Exception in final clean up of {0} in {1}. Exception ", avatar.Name, Name), e); } } @@ -3734,9 +3609,11 @@ namespace OpenSim.Region.Framework.Scenes /// /// Do the work necessary to initiate a new user connection for a particular scene. + /// At the moment, this consists of setting up the caps infrastructure + /// The return bool should allow for connections to be refused, but as not all calling paths + /// take proper notice of it let, we allowed banned users in still. /// /// CircuitData of the agent who is connecting - /// /// Outputs the reason for the false response on this string /// True if the region accepts this agent. False if it does not. False will /// also return a reason. @@ -3747,20 +3624,10 @@ namespace OpenSim.Region.Framework.Scenes /// /// Do the work necessary to initiate a new user connection for a particular scene. - /// - /// - /// The return bool should allow for connections to be refused, but as not all calling paths - /// take proper notice of it yet, we still allowed banned users in. - /// - /// At the moment this method consists of setting up the caps infrastructure + /// At the moment, this consists of setting up the caps infrastructure /// The return bool should allow for connections to be refused, but as not all calling paths /// take proper notice of it let, we allowed banned users in still. - /// - /// This method is called by the login service (in the case of login) or another simulator (in the case of region - /// cross or teleport) to initiate the connection. It is not triggered by the viewer itself - the connection - /// is activated later when the viewer sends the initial UseCircuitCodePacket UDP packet (in the case of - /// the LLUDP stack). - /// + /// /// CircuitData of the agent who is connecting /// Outputs the reason for the false response on this string /// True for normal presence. False for NPC @@ -3859,86 +3726,83 @@ namespace OpenSim.Region.Framework.Scenes "[SCENE]: Existing root scene presence detected for {0} {1} in {2} when connecting. Removing existing presence.", sp.Name, sp.UUID, RegionInfo.RegionName); - sp.ControllingClient.Close(true, true); + sp.ControllingClient.Close(); sp = null; } - lock (agent) + + //On login test land permisions + if (vialogin) { - //On login test land permisions - if (vialogin) + IUserAccountCacheModule cache = RequestModuleInterface(); + if (cache != null) + cache.Remove(agent.firstname + " " + agent.lastname); + if (!TestLandRestrictions(agent.AgentID, out reason, ref agent.startpos.X, ref agent.startpos.Y)) { - IUserAccountCacheModule cache = RequestModuleInterface(); - if (cache != null) - cache.Remove(agent.firstname + " " + agent.lastname); - if (!TestLandRestrictions(agent.AgentID, out reason, ref agent.startpos.X, ref agent.startpos.Y)) - { - m_log.DebugFormat("[CONNECTION BEGIN]: Denying access to {0} due to no land access", agent.AgentID.ToString()); - return false; - } + m_log.DebugFormat("[CONNECTION BEGIN]: Denying access to {0} due to no land access", agent.AgentID.ToString()); + return false; } + } - if (sp == null) // We don't have an [child] agent here already + if (sp == null) // We don't have an [child] agent here already + { + if (requirePresenceLookup) { - if (requirePresenceLookup) - { - try - { - if (!VerifyUserPresence(agent, out reason)) - return false; - } catch (Exception e) - { - m_log.ErrorFormat( - "[SCENE]: Exception verifying presence {0}{1}", e.Message, e.StackTrace); - return false; - } - } - try { - // Always check estate if this is a login. Always - // check if banned regions are to be blacked out. - if (vialogin || (!m_seeIntoBannedRegion)) - { - if (!AuthorizeUser(agent, out reason)) - return false; - } - } - catch (Exception e) + if (!VerifyUserPresence(agent, out reason)) + return false; + } catch (Exception e) { m_log.ErrorFormat( - "[SCENE]: Exception authorizing user {0}{1}", e.Message, e.StackTrace); + "[SCENE]: Exception verifying presence {0}{1}", e.Message, e.StackTrace); return false; } + } - m_log.InfoFormat( - "[SCENE]: Region {0} authenticated and authorized incoming {1} agent {2} {3} {4} (circuit code {5})", - RegionInfo.RegionName, (agent.child ? "child" : "root"), agent.firstname, agent.lastname, - agent.AgentID, agent.circuitcode); - - if (CapsModule != null) + try + { + // Always check estate if this is a login. Always + // check if banned regions are to be blacked out. + if (vialogin || (!m_seeIntoBannedRegion)) { - CapsModule.SetAgentCapsSeeds(agent); - CapsModule.CreateCaps(agent.AgentID); + if (!AuthorizeUser(agent, out reason)) + return false; } } - else + catch (Exception e) { - // Let the SP know how we got here. This has a lot of interesting - // uses down the line. - sp.TeleportFlags = (TPFlags)teleportFlags; + m_log.ErrorFormat( + "[SCENE]: Exception authorizing user {0}{1}", e.Message, e.StackTrace); + return false; + } - if (sp.IsChildAgent) - { - m_log.DebugFormat( - "[SCENE]: Adjusting known seeds for existing agent {0} in {1}", - agent.AgentID, RegionInfo.RegionName); + m_log.InfoFormat( + "[SCENE]: Region {0} authenticated and authorized incoming {1} agent {2} {3} {4} (circuit code {5})", + RegionInfo.RegionName, (agent.child ? "child" : "root"), agent.firstname, agent.lastname, + agent.AgentID, agent.circuitcode); - sp.AdjustKnownSeeds(); + if (CapsModule != null) + { + CapsModule.SetAgentCapsSeeds(agent); + CapsModule.CreateCaps(agent.AgentID); + } + } else + { + // Let the SP know how we got here. This has a lot of interesting + // uses down the line. + sp.TeleportFlags = (TPFlags)teleportFlags; - if (CapsModule != null) - CapsModule.SetAgentCapsSeeds(agent); - } + if (sp.IsChildAgent) + { + m_log.DebugFormat( + "[SCENE]: Adjusting known seeds for existing agent {0} in {1}", + agent.AgentID, RegionInfo.RegionName); + + sp.AdjustKnownSeeds(); + + if (CapsModule != null) + CapsModule.SetAgentCapsSeeds(agent); } } @@ -4369,9 +4233,8 @@ namespace OpenSim.Region.Framework.Scenes return false; } - // We have to wait until the viewer contacts this region - // after receiving the EnableSimulator HTTP Event Queue message. This triggers the viewer to send - // a UseCircuitCode packet which in turn calls AddNewClient which finally creates the ScenePresence. + // We have to wait until the viewer contacts this region after receiving EAC. + // That calls AddNewClient, which finally creates the ScenePresence ScenePresence childAgentUpdate = WaitGetScenePresence(cAgentData.AgentID); if (childAgentUpdate != null) @@ -4466,18 +4329,15 @@ namespace OpenSim.Region.Framework.Scenes /// Tell a single agent to disconnect from the region. /// /// - /// - /// Force the agent to close even if it might be in the middle of some other operation. You do not want to - /// force unless you are absolutely sure that the agent is dead and a normal close is not working. - /// - public bool IncomingCloseAgent(UUID agentID, bool force) + /// + public bool IncomingCloseAgent(UUID agentID, bool childOnly) { //m_log.DebugFormat("[SCENE]: Processing incoming close agent for {0}", agentID); ScenePresence presence = m_sceneGraph.GetScenePresence(agentID); if (presence != null) { - presence.ControllingClient.Close(force, force); + presence.ControllingClient.Close(false); return true; } @@ -4683,16 +4543,6 @@ namespace OpenSim.Region.Framework.Scenes return LandChannel.GetLandObject(x, y).LandData; } - /// - /// Get LandData by position. - /// - /// - /// - public LandData GetLandData(Vector3 pos) - { - return GetLandData(pos.X, pos.Y); - } - public LandData GetLandData(uint x, uint y) { m_log.DebugFormat("[SCENE]: returning land for {0},{1}", x, y); @@ -4923,24 +4773,13 @@ namespace OpenSim.Region.Framework.Scenes /// Get a group via its UUID /// /// - /// null if no group with that id exists + /// null if no group with that name exists public SceneObjectGroup GetSceneObjectGroup(UUID fullID) { return m_sceneGraph.GetSceneObjectGroup(fullID); } /// - /// Get a group via its local ID - /// - /// This will only return a group if the local ID matches a root part - /// - /// null if no group with that id exists - public SceneObjectGroup GetSceneObjectGroup(uint localID) - { - return m_sceneGraph.GetSceneObjectGroup(localID); - } - - /// /// Get a group by name from the scene (will return the first /// found, if there are more than one prim with the same name) /// @@ -4952,18 +4791,6 @@ namespace OpenSim.Region.Framework.Scenes } /// - /// Attempt to get the SOG via its UUID - /// - /// - /// - /// - public bool TryGetSceneObjectGroup(UUID fullID, out SceneObjectGroup sog) - { - sog = GetSceneObjectGroup(fullID); - return sog != null; - } - - /// /// Get a prim by name from the scene (will return the first /// found, if there are more than one prim with the same name) /// @@ -4995,18 +4822,6 @@ namespace OpenSim.Region.Framework.Scenes } /// - /// Attempt to get a prim via its UUID - /// - /// - /// - /// - public bool TryGetSceneObjectPart(UUID fullID, out SceneObjectPart sop) - { - sop = GetSceneObjectPart(fullID); - return sop != null; - } - - /// /// Get a scene object group that contains the prim with the given local id /// /// @@ -5100,15 +4915,14 @@ namespace OpenSim.Region.Framework.Scenes client.SendRegionHandle(regionID, handle); } -// Commented pending deletion since this method no longer appears to do anything at all -// public bool NeedSceneCacheClear(UUID agentID) -// { -// IInventoryTransferModule inv = RequestModuleInterface(); -// if (inv == null) -// return true; -// -// return inv.NeedSceneCacheClear(agentID, this); -// } + public bool NeedSceneCacheClear(UUID agentID) + { + IInventoryTransferModule inv = RequestModuleInterface(); + if (inv == null) + return true; + + return inv.NeedSceneCacheClear(agentID, this); + } public void CleanTempObjects() { @@ -6062,9 +5876,6 @@ Environment.Exit(1); public string GetExtraSetting(string name) { - if (m_extraSettings == null) - return String.Empty; - string val; if (!m_extraSettings.TryGetValue(name, out val)) @@ -6075,9 +5886,6 @@ Environment.Exit(1); public void StoreExtraSetting(string name, string val) { - if (m_extraSettings == null) - return; - string oldVal; if (m_extraSettings.TryGetValue(name, out oldVal)) @@ -6095,9 +5903,6 @@ Environment.Exit(1); public void RemoveExtraSetting(string name) { - if (m_extraSettings == null) - return; - if (!m_extraSettings.ContainsKey(name)) return; diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs index e599e90..af13b46 100644 --- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs +++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs @@ -342,7 +342,7 @@ namespace OpenSim.Region.Framework.Scenes public bool AddNewSceneObject( SceneObjectGroup sceneObject, bool attachToBackup, Vector3? pos, Quaternion? rot, Vector3 vel) { - AddNewSceneObject(sceneObject, attachToBackup, false); + AddNewSceneObject(sceneObject, true, false); if (pos != null) sceneObject.AbsolutePosition = (Vector3)pos; @@ -421,9 +421,12 @@ namespace OpenSim.Region.Framework.Scenes { Vector3 scale = part.Shape.Scale; - scale.X = Math.Max(m_parentScene.m_minNonphys, Math.Min(m_parentScene.m_maxNonphys, scale.X)); - scale.Y = Math.Max(m_parentScene.m_minNonphys, Math.Min(m_parentScene.m_maxNonphys, scale.Y)); - scale.Z = Math.Max(m_parentScene.m_minNonphys, Math.Min(m_parentScene.m_maxNonphys, scale.Z)); + if (scale.X > m_parentScene.m_maxNonphys) + scale.X = m_parentScene.m_maxNonphys; + if (scale.Y > m_parentScene.m_maxNonphys) + scale.Y = m_parentScene.m_maxNonphys; + if (scale.Z > m_parentScene.m_maxNonphys) + scale.Z = m_parentScene.m_maxNonphys; part.Shape.Scale = scale; } @@ -1063,30 +1066,6 @@ namespace OpenSim.Region.Framework.Scenes } /// - /// Get a group in the scene - /// - /// - /// This will only return a group if the local ID matches the root part, not other parts. - /// - /// Local id of the root part of the group - /// null if no such group was found - protected internal SceneObjectGroup GetSceneObjectGroup(uint localID) - { - lock (SceneObjectGroupsByLocalPartID) - { - if (SceneObjectGroupsByLocalPartID.ContainsKey(localID)) - { - SceneObjectGroup so = SceneObjectGroupsByLocalPartID[localID]; - - if (so.LocalId == localID) - return so; - } - } - - return null; - } - - /// /// Get a group by name from the scene (will return the first /// found, if there are more than one prim with the same name) /// diff --git a/OpenSim/Region/Framework/Scenes/SceneManager.cs b/OpenSim/Region/Framework/Scenes/SceneManager.cs index dba3a61..f1b09ca 100644 --- a/OpenSim/Region/Framework/Scenes/SceneManager.cs +++ b/OpenSim/Region/Framework/Scenes/SceneManager.cs @@ -92,11 +92,7 @@ namespace OpenSim.Region.Framework.Scenes private static SceneManager m_instance = null; public static SceneManager Instance { - get { - if (m_instance == null) - m_instance = new SceneManager(); - return m_instance; - } + get { return m_instance; } } private readonly DoubleDictionary m_localScenes = new DoubleDictionary(); diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index 74d2629..ee61de6 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -2747,25 +2747,6 @@ namespace OpenSim.Region.Framework.Scenes if (objectGroup == this) return; - // If the configured linkset capacity is greater than zero, - // and the new linkset would have a prim count higher than this - // value, do not link it. - if (m_scene.m_linksetCapacity > 0 && - (PrimCount + objectGroup.PrimCount) > - m_scene.m_linksetCapacity) - { - m_log.DebugFormat( - "[SCENE OBJECT GROUP]: Cannot link group with root" + - " part {0}, {1} ({2} prims) to group with root part" + - " {3}, {4} ({5} prims) because the new linkset" + - " would exceed the configured maximum of {6}", - objectGroup.RootPart.Name, objectGroup.RootPart.UUID, - objectGroup.PrimCount, RootPart.Name, RootPart.UUID, - PrimCount, m_scene.m_linksetCapacity); - - return; - } - // 'linkPart' == the root of the group being linked into this group SceneObjectPart linkPart = objectGroup.m_rootPart; @@ -3511,33 +3492,27 @@ namespace OpenSim.Region.Framework.Scenes /// public void GroupResize(Vector3 scale) { -// m_log.DebugFormat( -// "[SCENE OBJECT GROUP]: Group resizing {0} {1} from {2} to {3}", Name, LocalId, RootPart.Scale, scale); + scale.X = Math.Min(scale.X, Scene.m_maxNonphys); + scale.Y = Math.Min(scale.Y, Scene.m_maxNonphys); + scale.Z = Math.Min(scale.Z, Scene.m_maxNonphys); PhysicsActor pa = m_rootPart.PhysActor; - if (Scene != null) + if (pa != null && pa.IsPhysical) { - scale.X = Math.Max(Scene.m_minNonphys, Math.Min(Scene.m_maxNonphys, scale.X)); - scale.Y = Math.Max(Scene.m_minNonphys, Math.Min(Scene.m_maxNonphys, scale.Y)); - scale.Z = Math.Max(Scene.m_minNonphys, Math.Min(Scene.m_maxNonphys, scale.Z)); - - if (pa != null && pa.IsPhysical) - { - scale.X = Math.Max(Scene.m_minPhys, Math.Min(Scene.m_maxPhys, scale.X)); - scale.Y = Math.Max(Scene.m_minPhys, Math.Min(Scene.m_maxPhys, scale.Y)); - scale.Z = Math.Max(Scene.m_minPhys, Math.Min(Scene.m_maxPhys, scale.Z)); - } + scale.X = Math.Min(scale.X, Scene.m_maxPhys); + scale.Y = Math.Min(scale.Y, Scene.m_maxPhys); + scale.Z = Math.Min(scale.Z, Scene.m_maxPhys); } float x = (scale.X / RootPart.Scale.X); float y = (scale.Y / RootPart.Scale.Y); float z = (scale.Z / RootPart.Scale.Z); - SceneObjectPart[] parts = m_parts.GetArray(); - - if (Scene != null & (x > 1.0f || y > 1.0f || z > 1.0f)) + SceneObjectPart[] parts; + if (x > 1.0f || y > 1.0f || z > 1.0f) { + parts = m_parts.GetArray(); for (int i = 0; i < parts.Length; i++) { SceneObjectPart obPart = parts[i]; @@ -3550,7 +3525,7 @@ namespace OpenSim.Region.Framework.Scenes if (pa != null && pa.IsPhysical) { - if (oldSize.X * x > Scene.m_maxPhys) + if (oldSize.X * x > m_scene.m_maxPhys) { f = m_scene.m_maxPhys / oldSize.X; a = f / x; @@ -3558,16 +3533,8 @@ namespace OpenSim.Region.Framework.Scenes y *= a; z *= a; } - else if (oldSize.X * x < Scene.m_minPhys) - { - f = m_scene.m_minPhys / oldSize.X; - a = f / x; - x *= a; - y *= a; - z *= a; - } - if (oldSize.Y * y > Scene.m_maxPhys) + if (oldSize.Y * y > m_scene.m_maxPhys) { f = m_scene.m_maxPhys / oldSize.Y; a = f / y; @@ -3575,16 +3542,8 @@ namespace OpenSim.Region.Framework.Scenes y *= a; z *= a; } - else if (oldSize.Y * y < Scene.m_minPhys) - { - f = m_scene.m_minPhys / oldSize.Y; - a = f / y; - x *= a; - y *= a; - z *= a; - } - if (oldSize.Z * z > Scene.m_maxPhys) + if (oldSize.Z * z > m_scene.m_maxPhys) { f = m_scene.m_maxPhys / oldSize.Z; a = f / z; @@ -3592,18 +3551,10 @@ namespace OpenSim.Region.Framework.Scenes y *= a; z *= a; } - else if (oldSize.Z * z < Scene.m_minPhys) - { - f = m_scene.m_minPhys / oldSize.Z; - a = f / z; - x *= a; - y *= a; - z *= a; - } } else { - if (oldSize.X * x > Scene.m_maxNonphys) + if (oldSize.X * x > m_scene.m_maxNonphys) { f = m_scene.m_maxNonphys / oldSize.X; a = f / x; @@ -3611,16 +3562,8 @@ namespace OpenSim.Region.Framework.Scenes y *= a; z *= a; } - else if (oldSize.X * x < Scene.m_minNonphys) - { - f = m_scene.m_minNonphys / oldSize.X; - a = f / x; - x *= a; - y *= a; - z *= a; - } - if (oldSize.Y * y > Scene.m_maxNonphys) + if (oldSize.Y * y > m_scene.m_maxNonphys) { f = m_scene.m_maxNonphys / oldSize.Y; a = f / y; @@ -3628,16 +3571,8 @@ namespace OpenSim.Region.Framework.Scenes y *= a; z *= a; } - else if (oldSize.Y * y < Scene.m_minNonphys) - { - f = m_scene.m_minNonphys / oldSize.Y; - a = f / y; - x *= a; - y *= a; - z *= a; - } - if (oldSize.Z * z > Scene.m_maxNonphys) + if (oldSize.Z * z > m_scene.m_maxNonphys) { f = m_scene.m_maxNonphys / oldSize.Z; a = f / z; @@ -3645,14 +3580,6 @@ namespace OpenSim.Region.Framework.Scenes y *= a; z *= a; } - else if (oldSize.Z * z < Scene.m_minNonphys) - { - f = m_scene.m_minNonphys / oldSize.Z; - a = f / z; - x *= a; - y *= a; - z *= a; - } } } } @@ -3665,6 +3592,7 @@ namespace OpenSim.Region.Framework.Scenes RootPart.Resize(prevScale); + parts = m_parts.GetArray(); for (int i = 0; i < parts.Length; i++) { SceneObjectPart obPart = parts[i]; diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index 2191cfa..165dd85 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -790,7 +790,7 @@ namespace OpenSim.Region.Framework.Scenes } catch (Exception e) { - m_log.ErrorFormat("[SCENEOBJECTPART]: GROUP POSITION. {0}", e); + m_log.Error("[SCENEOBJECTPART]: GROUP POSITION. " + e.Message); } } } @@ -2864,35 +2864,6 @@ namespace OpenSim.Region.Framework.Scenes SendLandCollisionEvent(scriptEvents.land_collision_end, ParentGroup.Scene.EventManager.TriggerScriptLandCollidingEnd); } - // The Collision sounds code calls this - public void SendCollisionSound(UUID soundID, double volume, Vector3 position) - { - if (soundID == UUID.Zero) - return; - - ISoundModule soundModule = ParentGroup.Scene.RequestModuleInterface(); - if (soundModule == null) - return; - - if (volume > 1) - volume = 1; - if (volume < 0) - volume = 0; - - int now = Util.EnvironmentTickCount(); - if(Util.EnvironmentTickCountSubtract(now,LastColSoundSentTime) <200) - return; - - LastColSoundSentTime = now; - - UUID ownerID = OwnerID; - UUID objectID = ParentGroup.RootPart.UUID; - UUID parentID = ParentGroup.UUID; - ulong regionHandle = ParentGroup.Scene.RegionInfo.RegionHandle; - - soundModule.TriggerSound(soundID, ownerID, objectID, parentID, volume, position, regionHandle, 0 ); - } - public void PhysicsOutOfBounds(Vector3 pos) { m_log.Error("[PHYSICS]: Physical Object went out of bounds."); @@ -2924,6 +2895,38 @@ namespace OpenSim.Region.Framework.Scenes ScheduleTerseUpdate(); } + public void PreloadSound(string sound) + { + // UUID ownerID = OwnerID; + UUID objectID = ParentGroup.RootPart.UUID; + UUID soundID = UUID.Zero; + + if (!UUID.TryParse(sound, out soundID)) + { + //Trys to fetch sound id from prim's inventory. + //Prim's inventory doesn't support non script items yet + + TaskInventory.LockItemsForRead(true); + + foreach (KeyValuePair item in TaskInventory) + { + if (item.Value.Name == sound) + { + soundID = item.Value.ItemID; + break; + } + } + + TaskInventory.LockItemsForRead(false); + } + + ParentGroup.Scene.ForEachRootScenePresence(delegate(ScenePresence sp) + { + if (!(Util.GetDistanceTo(sp.AbsolutePosition, AbsolutePosition) >= 100)) + sp.ControllingClient.SendPreLoadSound(objectID, objectID, soundID); + }); + } + public void RemFlag(PrimFlags flag) { // PrimFlags prevflag = Flags; @@ -2976,20 +2979,17 @@ namespace OpenSim.Region.Framework.Scenes /// public void Resize(Vector3 scale) { + scale.X = Math.Min(scale.X, ParentGroup.Scene.m_maxNonphys); + scale.Y = Math.Min(scale.Y, ParentGroup.Scene.m_maxNonphys); + scale.Z = Math.Min(scale.Z, ParentGroup.Scene.m_maxNonphys); + PhysicsActor pa = PhysActor; - if (ParentGroup.Scene != null) + if (pa != null && pa.IsPhysical) { - scale.X = Math.Max(ParentGroup.Scene.m_minNonphys, Math.Min(ParentGroup.Scene.m_maxNonphys, scale.X)); - scale.Y = Math.Max(ParentGroup.Scene.m_minNonphys, Math.Min(ParentGroup.Scene.m_maxNonphys, scale.Y)); - scale.Z = Math.Max(ParentGroup.Scene.m_minNonphys, Math.Min(ParentGroup.Scene.m_maxNonphys, scale.Z)); - - if (pa != null && pa.IsPhysical) - { - scale.X = Math.Max(ParentGroup.Scene.m_minPhys, Math.Min(ParentGroup.Scene.m_maxPhys, scale.X)); - scale.Y = Math.Max(ParentGroup.Scene.m_minPhys, Math.Min(ParentGroup.Scene.m_maxPhys, scale.Y)); - scale.Z = Math.Max(ParentGroup.Scene.m_minPhys, Math.Min(ParentGroup.Scene.m_maxPhys, scale.Z)); - } + scale.X = Math.Min(scale.X, ParentGroup.Scene.m_maxPhys); + scale.Y = Math.Min(scale.Y, ParentGroup.Scene.m_maxPhys); + scale.Z = Math.Min(scale.Z, ParentGroup.Scene.m_maxPhys); } // m_log.DebugFormat("[SCENE OBJECT PART]: Resizing {0} {1} to {2}", Name, LocalId, scale); @@ -3086,7 +3086,7 @@ namespace OpenSim.Region.Framework.Scenes // UUID, Name, TimeStampFull); if (ParentGroup.Scene != null) - ParentGroup.Scene.EventManager.TriggerSceneObjectPartUpdated(this, true); + ParentGroup.Scene.EventManager.TriggerSceneObjectPartUpdated(this); } /// @@ -3120,7 +3120,7 @@ namespace OpenSim.Region.Framework.Scenes } if (ParentGroup.Scene != null) - ParentGroup.Scene.EventManager.TriggerSceneObjectPartUpdated(this, false); + ParentGroup.Scene.EventManager.TriggerSceneObjectPartUpdated(this); } public void ScriptSetPhysicsStatus(bool UsePhysics) @@ -3295,6 +3295,126 @@ namespace OpenSim.Region.Framework.Scenes } /// + /// Trigger or play an attached sound in this part's inventory. + /// + /// + /// + /// + /// + public void SendSound(string sound, double volume, bool triggered, byte flags, float radius, bool useMaster, bool isMaster) + { + if (volume > 1) + volume = 1; + if (volume < 0) + volume = 0; + + UUID ownerID = OwnerID; + UUID objectID = ParentGroup.RootPart.UUID; + UUID parentID = ParentGroup.UUID; + + UUID soundID = UUID.Zero; + Vector3 position = AbsolutePosition; // region local + ulong regionHandle = ParentGroup.Scene.RegionInfo.RegionHandle; + + if (!UUID.TryParse(sound, out soundID)) + { + // search sound file from inventory + TaskInventory.LockItemsForRead(true); + foreach (KeyValuePair item in TaskInventory) + { + if (item.Value.Name == sound && item.Value.Type == (int)AssetType.Sound) + { + soundID = item.Value.ItemID; + break; + } + } + TaskInventory.LockItemsForRead(false); + } + + if (soundID == UUID.Zero) + return; + + ISoundModule soundModule = ParentGroup.Scene.RequestModuleInterface(); + if (soundModule != null) + { + if (useMaster) + { + if (isMaster) + { + if (triggered) + soundModule.TriggerSound(soundID, ownerID, objectID, parentID, volume, position, regionHandle, radius); + else + soundModule.PlayAttachedSound(soundID, ownerID, objectID, volume, position, flags, radius); + ParentGroup.PlaySoundMasterPrim = this; + ownerID = OwnerID; + objectID = ParentGroup.RootPart.UUID; + parentID = ParentGroup.UUID; + position = AbsolutePosition; // region local + regionHandle = ParentGroup.Scene.RegionInfo.RegionHandle; + if (triggered) + soundModule.TriggerSound(soundID, ownerID, objectID, parentID, volume, position, regionHandle, radius); + else + soundModule.PlayAttachedSound(soundID, ownerID, objectID, volume, position, flags, radius); + foreach (SceneObjectPart prim in ParentGroup.PlaySoundSlavePrims) + { + ownerID = prim.OwnerID; + objectID = prim.ParentGroup.RootPart.UUID; + parentID = prim.ParentGroup.UUID; + position = prim.AbsolutePosition; // region local + regionHandle = prim.ParentGroup.Scene.RegionInfo.RegionHandle; + if (triggered) + soundModule.TriggerSound(soundID, ownerID, objectID, parentID, volume, position, regionHandle, radius); + else + soundModule.PlayAttachedSound(soundID, ownerID, objectID, volume, position, flags, radius); + } + ParentGroup.PlaySoundSlavePrims.Clear(); + ParentGroup.PlaySoundMasterPrim = null; + } + else + { + ParentGroup.PlaySoundSlavePrims.Add(this); + } + } + else + { + if (triggered) + soundModule.TriggerSound(soundID, ownerID, objectID, parentID, volume, position, regionHandle, radius); + else + soundModule.PlayAttachedSound(soundID, ownerID, objectID, volume, position, flags, radius); + } + } + } + + public void SendCollisionSound(UUID soundID, double volume, Vector3 position) + { + if (soundID == UUID.Zero) + return; + + ISoundModule soundModule = ParentGroup.Scene.RequestModuleInterface(); + if (soundModule == null) + return; + + if (volume > 1) + volume = 1; + if (volume < 0) + volume = 0; + + int now = Util.EnvironmentTickCount(); + if(Util.EnvironmentTickCountSubtract(now,LastColSoundSentTime) <200) + return; + + LastColSoundSentTime = now; + + UUID ownerID = OwnerID; + UUID objectID = ParentGroup.RootPart.UUID; + UUID parentID = ParentGroup.UUID; + ulong regionHandle = ParentGroup.Scene.RegionInfo.RegionHandle; + + soundModule.TriggerSound(soundID, ownerID, objectID, parentID, volume, position, regionHandle, 0 ); + } + + + /// /// Send a terse update to all clients /// public void SendTerseUpdateToAllClients() @@ -3455,32 +3575,23 @@ namespace OpenSim.Region.Framework.Scenes } /// - /// Set the color & alpha of prim faces + /// Set the color of prim faces /// - /// /// - /// - public void SetFaceColorAlpha(int face, Vector3 color, double ?alpha) + /// + public void SetFaceColor(Vector3 color, int face) { - Vector3 clippedColor = Util.Clip(color, 0.0f, 1.0f); - float clippedAlpha = alpha.HasValue ? - Util.Clip((float)alpha.Value, 0.0f, 1.0f) : 0; - // The only way to get a deep copy/ If we don't do this, we can - // never detect color changes further down. + // mever detect color changes further down. Byte[] buf = Shape.Textures.GetBytes(); Primitive.TextureEntry tex = new Primitive.TextureEntry(buf, 0, buf.Length); Color4 texcolor; if (face >= 0 && face < GetNumberOfSides()) { texcolor = tex.CreateFace((uint)face).RGBA; - texcolor.R = clippedColor.X; - texcolor.G = clippedColor.Y; - texcolor.B = clippedColor.Z; - if (alpha.HasValue) - { - texcolor.A = clippedAlpha; - } + texcolor.R = Util.Clip((float)color.X, 0.0f, 1.0f); + texcolor.G = Util.Clip((float)color.Y, 0.0f, 1.0f); + texcolor.B = Util.Clip((float)color.Z, 0.0f, 1.0f); tex.FaceTextures[face].RGBA = texcolor; UpdateTextureEntry(tex.GetBytes()); return; @@ -3492,23 +3603,15 @@ namespace OpenSim.Region.Framework.Scenes if (tex.FaceTextures[i] != null) { texcolor = tex.FaceTextures[i].RGBA; - texcolor.R = clippedColor.X; - texcolor.G = clippedColor.Y; - texcolor.B = clippedColor.Z; - if (alpha.HasValue) - { - texcolor.A = clippedAlpha; - } + texcolor.R = Util.Clip((float)color.X, 0.0f, 1.0f); + texcolor.G = Util.Clip((float)color.Y, 0.0f, 1.0f); + texcolor.B = Util.Clip((float)color.Z, 0.0f, 1.0f); tex.FaceTextures[i].RGBA = texcolor; } texcolor = tex.DefaultTexture.RGBA; - texcolor.R = clippedColor.X; - texcolor.G = clippedColor.Y; - texcolor.B = clippedColor.Z; - if (alpha.HasValue) - { - texcolor.A = clippedAlpha; - } + texcolor.R = Util.Clip((float)color.X, 0.0f, 1.0f); + texcolor.G = Util.Clip((float)color.Y, 0.0f, 1.0f); + texcolor.B = Util.Clip((float)color.Z, 0.0f, 1.0f); tex.DefaultTexture.RGBA = texcolor; } UpdateTextureEntry(tex.GetBytes()); @@ -4796,57 +4899,6 @@ namespace OpenSim.Region.Framework.Scenes ScheduleFullUpdate(); } - public void UpdateSlice(float begin, float end) - { - if (end < begin) - { - float temp = begin; - begin = end; - end = temp; - } - end = Math.Min(1f, Math.Max(0f, end)); - begin = Math.Min(Math.Min(1f, Math.Max(0f, begin)), end - 0.02f); - if (begin < 0.02f && end < 0.02f) - { - begin = 0f; - end = 0.02f; - } - - ushort uBegin = (ushort)(50000.0 * begin); - ushort uEnd = (ushort)(50000.0 * (1f - end)); - bool updatePossiblyNeeded = false; - PrimType primType = GetPrimType(); - if (primType == PrimType.SPHERE || primType == PrimType.TORUS || primType == PrimType.TUBE || primType == PrimType.RING) - { - if (m_shape.ProfileBegin != uBegin || m_shape.ProfileEnd != uEnd) - { - m_shape.ProfileBegin = uBegin; - m_shape.ProfileEnd = uEnd; - updatePossiblyNeeded = true; - } - } - else if (m_shape.PathBegin != uBegin || m_shape.PathEnd != uEnd) - { - m_shape.PathBegin = uBegin; - m_shape.PathEnd = uEnd; - updatePossiblyNeeded = true; - } - - if (updatePossiblyNeeded && ParentGroup != null) - { - ParentGroup.HasGroupChanged = true; - } - if (updatePossiblyNeeded && PhysActor != null) - { - PhysActor.Shape = m_shape; - ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(PhysActor); - } - if (updatePossiblyNeeded) - { - ScheduleFullUpdate(); - } - } - /// /// If the part is a sculpt/mesh, retrieve the mesh data and reinsert it into the shape so that the physics /// engine can use it. diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs index 3a9a146..e010864 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs @@ -97,15 +97,6 @@ namespace OpenSim.Region.Framework.Scenes QueryScriptStates(); } } - - public int Count - { - get - { - lock (m_items) - return m_items.Count; - } - } /// /// Constructor @@ -244,52 +235,31 @@ namespace OpenSim.Region.Framework.Scenes if (m_part == null || m_part.ParentGroup == null || m_part.ParentGroup.Scene == null) return; + IScriptModule[] engines = m_part.ParentGroup.Scene.RequestModuleInterfaces(); + if (engines == null) // No engine at all + return; + Items.LockItemsForRead(true); foreach (TaskInventoryItem item in Items.Values) { if (item.InvType == (int)InventoryType.LSL) { - bool running; - if (TryGetScriptInstanceRunning(m_part.ParentGroup.Scene, item, out running)) - item.ScriptRunning = running; + foreach (IScriptModule e in engines) + { + bool running; + + if (e.HasScript(item.ItemID, out running)) + { + item.ScriptRunning = running; + break; + } + } } } Items.LockItemsForRead(false); } - public bool TryGetScriptInstanceRunning(UUID itemId, out bool running) - { - running = false; - - TaskInventoryItem item = GetInventoryItem(itemId); - - if (item == null) - return false; - - return TryGetScriptInstanceRunning(m_part.ParentGroup.Scene, item, out running); - } - - public static bool TryGetScriptInstanceRunning(Scene scene, TaskInventoryItem item, out bool running) - { - running = false; - - if (item.InvType != (int)InventoryType.LSL) - return false; - - IScriptModule[] engines = scene.RequestModuleInterfaces(); - if (engines == null) // No engine at all - return false; - - foreach (IScriptModule e in engines) - { - if (e.HasScript(item.ItemID, out running)) - return true; - } - - return false; - } - public int CreateScriptInstances(int startParam, bool postOnRez, string engine, int stateSource) { int scriptsValidForStarting = 0; diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index 25a53b4..2b9665c 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -1,4 +1,4 @@ -/* +/* * Copyright (c) Contributors, http://opensimulator.org/ * See CONTRIBUTORS.TXT for a full list of copyright holders. * @@ -69,15 +69,14 @@ namespace OpenSim.Region.Framework.Scenes public ScriptControlled eventControls; } - public delegate void SendCoarseLocationsMethod(UUID scene, ScenePresence presence, List coarseLocations, List avatarUUIDs); + public delegate void SendCourseLocationsMethod(UUID scene, ScenePresence presence, List coarseLocations, List avatarUUIDs); public class ScenePresence : EntityBase, IScenePresence { // ~ScenePresence() // { -// m_log.DebugFormat("[SCENE PRESENCE]: Destructor called on {0}", Name); +// m_log.Debug("[SCENE PRESENCE] Destructor called"); // } - private void TriggerScenePresenceUpdated() { if (m_scene != null) @@ -189,7 +188,7 @@ namespace OpenSim.Region.Framework.Scenes /// public bool SitGround { get; private set; } - private SendCoarseLocationsMethod m_sendCoarseLocationsMethod; + private SendCourseLocationsMethod m_sendCourseLocationsMethod; //private Vector3 m_requestedSitOffset = new Vector3(); @@ -547,7 +546,7 @@ namespace OpenSim.Region.Framework.Scenes { try { - PhysicsActor.TargetVelocity = value; + PhysicsActor.Velocity = value; } catch (Exception e) { @@ -712,7 +711,7 @@ namespace OpenSim.Region.Framework.Scenes AttachmentsSyncLock = new Object(); AllowMovement = true; IsChildAgent = true; - m_sendCoarseLocationsMethod = SendCoarseLocationsDefault; + m_sendCourseLocationsMethod = SendCoarseLocationsDefault; Animator = new ScenePresenceAnimator(this); PresenceType = type; DrawDistance = world.DefaultDrawDistance; @@ -976,9 +975,7 @@ namespace OpenSim.Region.Framework.Scenes { if (wasChild && HasAttachments()) { - m_log.DebugFormat( - "[SCENE PRESENCE]: Restarting scripts in attachments for {0} in {1}", Name, Scene.Name); - + m_log.DebugFormat("[SCENE PRESENCE]: Restarting scripts in attachments..."); // Resume scripts Util.FireAndForget(delegate(object x) { foreach (SceneObjectGroup sog in m_attachments) @@ -1534,22 +1531,17 @@ namespace OpenSim.Region.Framework.Scenes bool DCFlagKeyPressed = false; Vector3 agent_control_v3 = Vector3.Zero; - bool newFlying = actor.Flying; + bool oldflying = Flying; if (ForceFly) - newFlying = true; + actor.Flying = true; else if (FlyDisabled) - newFlying = false; + actor.Flying = false; else - newFlying = ((flags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0); + actor.Flying = ((flags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0); - if (actor.Flying != newFlying) - { - // Note: ScenePresence.Flying is actually fetched from the physical actor - // so setting PhysActor.Flying here also sets the ScenePresence's value. - actor.Flying = newFlying; + if (actor.Flying != oldflying) update_movementflag = true; - } if (ParentID == 0) { @@ -2631,17 +2623,17 @@ namespace OpenSim.Region.Framework.Scenes public void SendCoarseLocations(List coarseLocations, List avatarUUIDs) { - SendCoarseLocationsMethod d = m_sendCoarseLocationsMethod; + SendCourseLocationsMethod d = m_sendCourseLocationsMethod; if (d != null) { d.Invoke(m_scene.RegionInfo.originRegionID, this, coarseLocations, avatarUUIDs); } } - public void SetSendCoarseLocationMethod(SendCoarseLocationsMethod d) + public void SetSendCourseLocationMethod(SendCourseLocationsMethod d) { if (d != null) - m_sendCoarseLocationsMethod = d; + m_sendCourseLocationsMethod = d; } public void SendCoarseLocationsDefault(UUID sceneId, ScenePresence p, List coarseLocations, List avatarUUIDs) @@ -2845,7 +2837,7 @@ namespace OpenSim.Region.Framework.Scenes #region Significant Movement Method /// - /// This checks for a significant movement and sends a coarselocationchange update + /// This checks for a significant movement and sends a courselocationchange update /// protected void CheckForSignificantMovement() { @@ -3282,7 +3274,6 @@ namespace OpenSim.Region.Framework.Scenes } catch { } cAgent.DefaultAnim = Animator.Animations.DefaultAnimation; - cAgent.AnimState = Animator.Animations.ImplicitDefaultAnimation; if (Scene.AttachmentsModule != null) Scene.AttachmentsModule.CopyAttachments(this, cAgent); @@ -3359,8 +3350,6 @@ namespace OpenSim.Region.Framework.Scenes Animator.Animations.FromArray(cAgent.Anims); if (cAgent.DefaultAnim != null) Animator.Animations.SetDefaultAnimation(cAgent.DefaultAnim.AnimID, cAgent.DefaultAnim.SequenceNum, UUID.Zero); - if (cAgent.AnimState != null) - Animator.Animations.SetImplicitDefaultAnimation(cAgent.AnimState.AnimID, cAgent.AnimState.SequenceNum, UUID.Zero); if (Scene.AttachmentsModule != null) Scene.AttachmentsModule.CopyAttachments(cAgent, this); @@ -3643,16 +3632,13 @@ namespace OpenSim.Region.Framework.Scenes public List GetAttachments(uint attachmentPoint) { List attachments = new List(); - - if (attachmentPoint >= 0) + + lock (m_attachments) { - lock (m_attachments) + foreach (SceneObjectGroup so in m_attachments) { - foreach (SceneObjectGroup so in m_attachments) - { - if (attachmentPoint == so.AttachmentPoint) - attachments.Add(so); - } + if (attachmentPoint == so.AttachmentPoint) + attachments.Add(so); } } diff --git a/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs b/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs index 5398ab9..756b1f4 100644 --- a/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs +++ b/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs @@ -47,7 +47,6 @@ namespace OpenSim.Region.Framework.Scenes = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); public const string LastReportedObjectUpdateStatName = "LastReportedObjectUpdates"; - public const string SlowFramesStatName = "SlowFrames"; public delegate void SendStatResult(SimStats stats); @@ -130,16 +129,6 @@ namespace OpenSim.Region.Framework.Scenes } /// - /// Number of frames that have taken longer to process than Scene.MIN_FRAME_TIME - /// - public Stat SlowFramesStat { get; private set; } - - /// - /// The threshold at which we log a slow frame. - /// - public int SlowFramesStatReportThreshold { get; private set; } - - /// /// Extra sim statistics that are used by monitors but not sent to the client. /// /// @@ -237,24 +226,6 @@ namespace OpenSim.Region.Framework.Scenes if (StatsManager.SimExtraStats != null) OnSendStatsResult += StatsManager.SimExtraStats.ReceiveClassicSimStatsPacket; - - /// At the moment, we'll only report if a frame is over 120% of target, since commonly frames are a bit - /// longer than ideal (which in itself is a concern). - SlowFramesStatReportThreshold = (int)Math.Ceiling(m_scene.MinFrameTime * 1000 * 1.2); - - SlowFramesStat - = new Stat( - "SlowFrames", - "Slow Frames", - "Number of frames where frame time has been significantly longer than the desired frame time.", - " frames", - "scene", - m_scene.Name, - StatType.Push, - null, - StatVerbosity.Info); - - StatsManager.RegisterStat(SlowFramesStat); } public void Close() @@ -472,7 +443,6 @@ namespace OpenSim.Region.Framework.Scenes lock (m_lastReportedExtraSimStats) { m_lastReportedExtraSimStats[LastReportedObjectUpdateStatName] = m_objectUpdates / m_statsUpdateFactor; - m_lastReportedExtraSimStats[SlowFramesStat.ShortName] = (float)SlowFramesStat.Value; Dictionary physicsStats = m_scene.PhysicsScene.GetStats(); @@ -593,11 +563,6 @@ namespace OpenSim.Region.Framework.Scenes public void addFrameMS(int ms) { m_frameMS += ms; - - // At the moment, we'll only report if a frame is over 120% of target, since commonly frames are a bit - // longer than ideal due to the inaccuracy of the Sleep in Scene.Update() (which in itself is a concern). - if (ms > SlowFramesStatReportThreshold) - SlowFramesStat.Value++; } public void addNetMS(int ms) diff --git a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs index 5faf131..5758869 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs @@ -141,7 +141,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests TestScene scene = new SceneHelpers().SetupScene(); ScenePresence sp = SceneHelpers.AddScenePresence(scene, TestHelpers.ParseTail(0x1)); - scene.IncomingCloseAgent(sp.UUID, false); + scene.IncomingCloseAgent(sp.UUID); Assert.That(scene.GetScenePresence(sp.UUID), Is.Null); Assert.That(scene.AuthenticateHandler.GetAgentCircuitData(sp.UUID), Is.Null); diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneTests.cs index ac3da1e..d722a09 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/SceneTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/SceneTests.cs @@ -65,22 +65,5 @@ namespace OpenSim.Region.Framework.Scenes.Tests Assert.That(scene.Frame, Is.EqualTo(1)); } - - [Test] - public void TestShutdownScene() - { - TestHelpers.InMethod(); - - Scene scene = new SceneHelpers().SetupScene(); - scene.Close(); - - Assert.That(scene.ShuttingDown, Is.True); - Assert.That(scene.Active, Is.False); - - // Trying to update a shutdown scene should result in no update - scene.Update(1); - - Assert.That(scene.Frame, Is.EqualTo(0)); - } } } \ No newline at end of file diff --git a/OpenSim/Region/Framework/Scenes/Tests/UserInventoryTests.cs b/OpenSim/Region/Framework/Scenes/Tests/UserInventoryTests.cs index 9457ebb..44d2d45 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/UserInventoryTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/UserInventoryTests.cs @@ -50,41 +50,9 @@ using OpenSim.Tests.Common.Mock; namespace OpenSim.Region.Framework.Tests { [TestFixture] - public class UserInventoryTests : OpenSimTestCase + public class UserInventoryTests { [Test] - public void TestCreateInventoryFolders() - { - TestHelpers.InMethod(); -// TestHelpers.EnableLogging(); - - // For this test both folders will have the same name which is legal in SL user inventories. - string foldersName = "f1"; - - Scene scene = new SceneHelpers().SetupScene(); - UserAccount user1 = UserAccountHelpers.CreateUserWithInventory(scene, TestHelpers.ParseTail(1001)); - - UserInventoryHelpers.CreateInventoryFolder(scene.InventoryService, user1.PrincipalID, foldersName); - - List oneFolder - = UserInventoryHelpers.GetInventoryFolders(scene.InventoryService, user1.PrincipalID, foldersName); - - Assert.That(oneFolder.Count, Is.EqualTo(1)); - InventoryFolderBase firstRetrievedFolder = oneFolder[0]; - Assert.That(firstRetrievedFolder.Name, Is.EqualTo(foldersName)); - - UserInventoryHelpers.CreateInventoryFolder(scene.InventoryService, user1.PrincipalID, foldersName); - - List twoFolders - = UserInventoryHelpers.GetInventoryFolders(scene.InventoryService, user1.PrincipalID, foldersName); - - Assert.That(twoFolders.Count, Is.EqualTo(2)); - Assert.That(twoFolders[0].Name, Is.EqualTo(foldersName)); - Assert.That(twoFolders[1].Name, Is.EqualTo(foldersName)); - Assert.That(twoFolders[0].ID, Is.Not.EqualTo(twoFolders[1].ID)); - } - - [Test] public void TestGiveInventoryItem() { TestHelpers.InMethod(); @@ -115,7 +83,7 @@ namespace OpenSim.Region.Framework.Tests public void TestGiveInventoryFolder() { TestHelpers.InMethod(); -// TestHelpers.EnableLogging(); +// log4net.Config.XmlConfigurator.Configure(); Scene scene = new SceneHelpers().SetupScene(); UserAccount user1 = UserAccountHelpers.CreateUserWithInventory(scene, TestHelpers.ParseTail(1001)); diff --git a/OpenSim/Region/Framework/Scenes/UuidGatherer.cs b/OpenSim/Region/Framework/Scenes/UuidGatherer.cs index 2279e62..411e421 100644 --- a/OpenSim/Region/Framework/Scenes/UuidGatherer.cs +++ b/OpenSim/Region/Framework/Scenes/UuidGatherer.cs @@ -52,23 +52,26 @@ namespace OpenSim.Region.Framework.Scenes public class UuidGatherer { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + /// + /// Asset cache used for gathering assets + /// + protected IAssetService m_assetCache; + + /// + /// Used as a temporary store of an asset which represents an object. This can be a null if no appropriate + /// asset was found by the asset service. + /// + private AssetBase m_requestedObjectAsset; - protected IAssetService m_assetService; - -// /// -// /// Used as a temporary store of an asset which represents an object. This can be a null if no appropriate -// /// asset was found by the asset service. -// /// -// private AssetBase m_requestedObjectAsset; -// -// /// -// /// Signal whether we are currently waiting for the asset service to deliver an asset. -// /// -// private bool m_waitingForObjectAsset; + /// + /// Signal whether we are currently waiting for the asset service to deliver an asset. + /// + private bool m_waitingForObjectAsset; - public UuidGatherer(IAssetService assetService) + public UuidGatherer(IAssetService assetCache) { - m_assetService = assetService; + m_assetCache = assetCache; } /// @@ -188,18 +191,18 @@ namespace OpenSim.Region.Framework.Scenes } } -// /// -// /// The callback made when we request the asset for an object from the asset service. -// /// -// private void AssetReceived(string id, Object sender, AssetBase asset) -// { -// lock (this) -// { -// m_requestedObjectAsset = asset; -// m_waitingForObjectAsset = false; -// Monitor.Pulse(this); -// } -// } + /// + /// The callback made when we request the asset for an object from the asset service. + /// + private void AssetReceived(string id, Object sender, AssetBase asset) + { + lock (this) + { + m_requestedObjectAsset = asset; + m_waitingForObjectAsset = false; + Monitor.Pulse(this); + } + } /// /// Get an asset synchronously, potentially using an asynchronous callback. If the @@ -209,29 +212,25 @@ namespace OpenSim.Region.Framework.Scenes /// protected virtual AssetBase GetAsset(UUID uuid) { - return m_assetService.Get(uuid.ToString()); + m_waitingForObjectAsset = true; + m_assetCache.Get(uuid.ToString(), this, AssetReceived); + + // The asset cache callback can either + // + // 1. Complete on the same thread (if the asset is already in the cache) or + // 2. Come in via a different thread (if we need to go fetch it). + // + // The code below handles both these alternatives. + lock (this) + { + if (m_waitingForObjectAsset) + { + Monitor.Wait(this); + m_waitingForObjectAsset = false; + } + } - // XXX: Switching to do this synchronously where the call was async before but we always waited for it - // to complete anyway! -// m_waitingForObjectAsset = true; -// m_assetCache.Get(uuid.ToString(), this, AssetReceived); -// -// // The asset cache callback can either -// // -// // 1. Complete on the same thread (if the asset is already in the cache) or -// // 2. Come in via a different thread (if we need to go fetch it). -// // -// // The code below handles both these alternatives. -// lock (this) -// { -// if (m_waitingForObjectAsset) -// { -// Monitor.Wait(this); -// m_waitingForObjectAsset = false; -// } -// } -// -// return m_requestedObjectAsset; + return m_requestedObjectAsset; } /// @@ -362,47 +361,4 @@ namespace OpenSim.Region.Framework.Scenes } } } - - public class HGUuidGatherer : UuidGatherer - { - private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - protected string m_assetServerURL; - - public HGUuidGatherer(IAssetService assetService, string assetServerURL) - : base(assetService) - { - m_assetServerURL = assetServerURL; - if (!m_assetServerURL.EndsWith("/") && !m_assetServerURL.EndsWith("=")) - m_assetServerURL = m_assetServerURL + "/"; - } - - protected override AssetBase GetAsset(UUID uuid) - { - if (string.Empty == m_assetServerURL) - return base.GetAsset(uuid); - else - return FetchAsset(uuid); - } - - public AssetBase FetchAsset(UUID assetID) - { - - // Test if it's already here - AssetBase asset = m_assetService.Get(assetID.ToString()); - if (asset == null) - { - // It's not, so fetch it from abroad - asset = m_assetService.Get(m_assetServerURL + assetID.ToString()); - if (asset != null) - m_log.DebugFormat("[HGUUIDGatherer]: Copied asset {0} from {1} to local asset server", assetID, m_assetServerURL); - else - m_log.DebugFormat("[HGUUIDGatherer]: Failed to fetch asset {0} from {1}", assetID, m_assetServerURL); - } - //else - // m_log.DebugFormat("[HGUUIDGatherer]: Asset {0} from {1} was already here", assetID, m_assetServerURL); - - return asset; - } - } } diff --git a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs index 254eeb4..28b8293 100644 --- a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs +++ b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs @@ -891,10 +891,10 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server public void Close() { - Close(true, false); + Close(true); } - public void Close(bool sendStop, bool force) + public void Close(bool sendStop) { Disconnect(); } @@ -959,8 +959,7 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server } - public void SendChatMessage( - string message, byte type, Vector3 fromPos, string fromName, UUID fromAgentID, UUID ownerID, byte source, byte audible) + public void SendChatMessage(string message, byte type, Vector3 fromPos, string fromName, UUID fromAgentID, byte source, byte audible) { if (audible > 0 && message.Length > 0) IRC_SendChannelPrivmsg(fromName, message); diff --git a/OpenSim/Region/OptionalModules/Asset/AssetInfoModule.cs b/OpenSim/Region/OptionalModules/Asset/AssetInfoModule.cs index 7639c6c..41ec14f 100644 --- a/OpenSim/Region/OptionalModules/Asset/AssetInfoModule.cs +++ b/OpenSim/Region/OptionalModules/Asset/AssetInfoModule.cs @@ -127,9 +127,6 @@ namespace OpenSim.Region.OptionalModules.Asset } string fileName = rawAssetId; - - if (!ConsoleUtil.CheckFileDoesNotExist(MainConsole.Instance, fileName)) - return; using (FileStream fs = new FileStream(fileName, FileMode.CreateNew)) { diff --git a/OpenSim/Region/OptionalModules/Avatar/Attachments/AttachmentsCommandModule.cs b/OpenSim/Region/OptionalModules/Avatar/Attachments/AttachmentsCommandModule.cs index 68bcb4a..d68aabc 100644 --- a/OpenSim/Region/OptionalModules/Avatar/Attachments/AttachmentsCommandModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/Attachments/AttachmentsCommandModule.cs @@ -146,7 +146,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Attachments sb.AppendFormat("Attachments for {0}\n", sp.Name); ConsoleDisplayTable ct = new ConsoleDisplayTable() { Indent = 2 }; - ct.Columns.Add(new ConsoleDisplayTableColumn("Attachment Name", 50)); + ct.Columns.Add(new ConsoleDisplayTableColumn("Attachment Name", 36)); ct.Columns.Add(new ConsoleDisplayTableColumn("Local ID", 10)); ct.Columns.Add(new ConsoleDisplayTableColumn("Item ID", 36)); ct.Columns.Add(new ConsoleDisplayTableColumn("Attach Point", 14)); diff --git a/OpenSim/Region/OptionalModules/Avatar/Attachments/TempAttachmentsModule.cs b/OpenSim/Region/OptionalModules/Avatar/Attachments/TempAttachmentsModule.cs index 17971e3..31d0034 100644 --- a/OpenSim/Region/OptionalModules/Avatar/Attachments/TempAttachmentsModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/Attachments/TempAttachmentsModule.cs @@ -130,37 +130,37 @@ namespace OpenSim.Region.OptionalModules.Avatar.Attachments SendConsoleOutput(agentID, String.Format("auto_grant_attach_perms set to {0}", val)); } - private int llAttachToAvatarTemp(UUID host, UUID script, int attachmentPoint) + private void llAttachToAvatarTemp(UUID host, UUID script, int attachmentPoint) { SceneObjectPart hostPart = m_scene.GetSceneObjectPart(host); if (hostPart == null) - return 0; + return; if (hostPart.ParentGroup.IsAttachment) - return 0; + return; IAttachmentsModule attachmentsModule = m_scene.RequestModuleInterface(); if (attachmentsModule == null) - return 0; + return; TaskInventoryItem item = hostPart.Inventory.GetInventoryItem(script); if (item == null) - return 0; + return; if ((item.PermsMask & 32) == 0) // PERMISSION_ATTACH - return 0; + return; ScenePresence target; if (!m_scene.TryGetScenePresence(item.PermsGranter, out target)) - return 0; + return; if (target.UUID != hostPart.ParentGroup.OwnerID) { uint effectivePerms = hostPart.ParentGroup.GetEffectivePermissions(); if ((effectivePerms & (uint)PermissionMask.Transfer) == 0) - return 0; + return; hostPart.ParentGroup.SetOwnerId(target.UUID); hostPart.ParentGroup.SetRootPartOwner(hostPart.ParentGroup.RootPart, target.UUID, target.ControllingClient.ActiveGroupId); @@ -183,7 +183,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Attachments hostPart.ParentGroup.RootPart.ScheduleFullUpdate(); } - return attachmentsModule.AttachObject(target, hostPart.ParentGroup, (uint)attachmentPoint, false, true, true) ? 1 : 0; + attachmentsModule.AttachObject(target, hostPart.ParentGroup, (uint)attachmentPoint, false, true, true); } } } diff --git a/OpenSim/Region/OptionalModules/Avatar/Chat/IRCConnector.cs b/OpenSim/Region/OptionalModules/Avatar/Chat/IRCConnector.cs index a014798..ca956fb 100644 --- a/OpenSim/Region/OptionalModules/Avatar/Chat/IRCConnector.cs +++ b/OpenSim/Region/OptionalModules/Avatar/Chat/IRCConnector.cs @@ -231,12 +231,12 @@ namespace OpenSim.Region.OptionalModules.Avatar.Chat if (m_server == null || m_baseNick == null || m_ircChannel == null || m_user == null) throw new Exception("Invalid connector configuration"); - // Generate an initial nickname + // Generate an initial nickname if randomizing is enabled if (m_randomizeNick) + { m_nick = m_baseNick + Util.RandomClass.Next(1, 99); - else - m_nick = m_baseNick; + } m_log.InfoFormat("[IRC-Connector-{0}]: Initialization complete", idn); diff --git a/OpenSim/Region/OptionalModules/Avatar/Concierge/ConciergeModule.cs b/OpenSim/Region/OptionalModules/Avatar/Concierge/ConciergeModule.cs index 5c3be29..e22618d 100644 --- a/OpenSim/Region/OptionalModules/Avatar/Concierge/ConciergeModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/Concierge/ConciergeModule.cs @@ -546,9 +546,8 @@ namespace OpenSim.Region.OptionalModules.Avatar.Concierge c.SenderUUID = UUID.Zero; c.Scene = agent.Scene; - agent.ControllingClient.SendChatMessage( - msg, (byte) ChatTypeEnum.Say, PosOfGod, m_whoami, UUID.Zero, UUID.Zero, - (byte)ChatSourceType.Object, (byte)ChatAudibleLevel.Fully); + agent.ControllingClient.SendChatMessage(msg, (byte) ChatTypeEnum.Say, PosOfGod, m_whoami, UUID.Zero, + (byte)ChatSourceType.Object, (byte)ChatAudibleLevel.Fully); } private static void checkStringParameters(XmlRpcRequest request, string[] param) diff --git a/OpenSim/Region/OptionalModules/Avatar/Voice/FreeSwitchVoice/FreeSwitchVoiceModule.cs b/OpenSim/Region/OptionalModules/Avatar/Voice/FreeSwitchVoice/FreeSwitchVoiceModule.cs index f292a75..7b20446 100644 --- a/OpenSim/Region/OptionalModules/Avatar/Voice/FreeSwitchVoice/FreeSwitchVoiceModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/Voice/FreeSwitchVoice/FreeSwitchVoiceModule.cs @@ -447,7 +447,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.FreeSwitchVoice // settings allow voice, then whether parcel allows // voice, if all do retrieve or obtain the parcel // voice channel - LandData land = scene.GetLandData(avatar.AbsolutePosition); + LandData land = scene.GetLandData(avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y); //m_log.DebugFormat("[FreeSwitchVoice][PARCELVOICE]: region \"{0}\": Parcel \"{1}\" ({2}): avatar \"{3}\": request: {4}, path: {5}, param: {6}", // scene.RegionInfo.RegionName, land.Name, land.LocalID, avatarName, request, path, param); diff --git a/OpenSim/Region/OptionalModules/Avatar/Voice/VivoxVoice/VivoxVoiceModule.cs b/OpenSim/Region/OptionalModules/Avatar/Voice/VivoxVoice/VivoxVoiceModule.cs index 8a8a31c..a30a38d 100644 --- a/OpenSim/Region/OptionalModules/Avatar/Voice/VivoxVoice/VivoxVoiceModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/Voice/VivoxVoice/VivoxVoiceModule.cs @@ -623,7 +623,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice // settings allow voice, then whether parcel allows // voice, if all do retrieve or obtain the parcel // voice channel - LandData land = scene.GetLandData(avatar.AbsolutePosition); + LandData land = scene.GetLandData(avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y); // m_log.DebugFormat("[VivoxVoice][PARCELVOICE]: region \"{0}\": Parcel \"{1}\" ({2}): avatar \"{3}\": request: {4}, path: {5}, param: {6}", // scene.RegionInfo.RegionName, land.Name, land.LocalID, avatarName, request, path, param); diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsMessagingModule.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsMessagingModule.cs index 1528330..10b83e6 100644 --- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsMessagingModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsMessagingModule.cs @@ -27,7 +27,6 @@ using System; using System.Collections.Generic; -using System.Linq; using System.Reflection; using log4net; using Mono.Addins; @@ -37,8 +36,6 @@ using OpenMetaverse.StructuredData; using OpenSim.Framework; using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Scenes; -using OpenSim.Services.Interfaces; -using PresenceInfo = OpenSim.Services.Interfaces.PresenceInfo; namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups { @@ -48,7 +45,6 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private List m_sceneList = new List(); - private IPresenceService m_presenceService; private IMessageTransferModule m_msgTransferModule = null; @@ -58,27 +54,6 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups private bool m_groupMessagingEnabled = false; private bool m_debugEnabled = true; - /// - /// If enabled, module only tries to send group IMs to online users by querying cached presence information. - /// - private bool m_messageOnlineAgentsOnly; - - /// - /// Cache for online users. - /// - /// - /// Group ID is key, presence information for online members is value. - /// Will only be non-null if m_messageOnlineAgentsOnly = true - /// We cache here so that group messages don't constantly have to re-request the online user list to avoid - /// attempted expensive sending of messages to offline users. - /// The tradeoff is that a user that comes online will not receive messages consistently from all other users - /// until caches have updated. - /// Therefore, we set the cache expiry to just 20 seconds. - /// - private ExpiringCache m_usersOnlineCache; - - private int m_usersOnlineCacheExpirySeconds = 20; - #region IRegionModuleBase Members public void Initialise(IConfigSource config) @@ -108,17 +83,10 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups return; } - m_messageOnlineAgentsOnly = groupsConfig.GetBoolean("MessageOnlineUsersOnly", false); - - if (m_messageOnlineAgentsOnly) - m_usersOnlineCache = new ExpiringCache(); - m_debugEnabled = groupsConfig.GetBoolean("DebugEnabled", true); } - m_log.InfoFormat( - "[GROUPS-MESSAGING]: GroupsMessagingModule enabled with MessageOnlineOnly = {0}, DebugEnabled = {1}", - m_messageOnlineAgentsOnly, m_debugEnabled); + m_log.Info("[GROUPS-MESSAGING]: GroupsMessagingModule starting up"); } public void AddRegion(Scene scene) @@ -158,8 +126,6 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups return; } - if (m_presenceService == null) - m_presenceService = scene.PresenceService; m_sceneList.Add(scene); @@ -241,42 +207,12 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups public void SendMessageToGroup(GridInstantMessage im, UUID groupID) { List groupMembers = m_groupData.GetGroupMembers(new UUID(im.fromAgentID), groupID); - int groupMembersCount = groupMembers.Count; - - if (m_messageOnlineAgentsOnly) - { - string[] t1 = groupMembers.ConvertAll(gmd => gmd.AgentID.ToString()).ToArray(); - - // We cache in order not to overwhlem the presence service on large grids with many groups. This does - // mean that members coming online will not see all group members until after m_usersOnlineCacheExpirySeconds has elapsed. - // (assuming this is the same across all grid simulators). - PresenceInfo[] onlineAgents; - if (!m_usersOnlineCache.TryGetValue(groupID, out onlineAgents)) - { - onlineAgents = m_presenceService.GetAgents(t1); - m_usersOnlineCache.Add(groupID, onlineAgents, m_usersOnlineCacheExpirySeconds); - } - - HashSet onlineAgentsUuidSet = new HashSet(); - Array.ForEach(onlineAgents, pi => onlineAgentsUuidSet.Add(pi.UserID)); - - groupMembers = groupMembers.Where(gmd => onlineAgentsUuidSet.Contains(gmd.AgentID.ToString())).ToList(); - - // if (m_debugEnabled) -// m_log.DebugFormat( -// "[GROUPS-MESSAGING]: SendMessageToGroup called for group {0} with {1} visible members, {2} online", -// groupID, groupMembersCount, groupMembers.Count()); - } - else - { - if (m_debugEnabled) - m_log.DebugFormat( - "[GROUPS-MESSAGING]: SendMessageToGroup called for group {0} with {1} visible members", - groupID, groupMembers.Count); - } - - int requestStartTick = Environment.TickCount; - + + if (m_debugEnabled) + m_log.DebugFormat( + "[GROUPS-MESSAGING]: SendMessageToGroup called for group {0} with {1} visible members", + groupID, groupMembers.Count); + foreach (GroupMembersData member in groupMembers) { if (m_groupData.hasAgentDroppedGroupChatSession(member.AgentID, groupID)) @@ -318,12 +254,6 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups ProcessMessageFromGroupSession(msg); } } - - // Temporary for assessing how long it still takes to send messages to large online groups. - if (m_messageOnlineAgentsOnly) - m_log.DebugFormat( - "[GROUPS-MESSAGING]: SendMessageToGroup for group {0} with {1} visible members, {2} online took {3}ms", - groupID, groupMembersCount, groupMembers.Count(), Environment.TickCount - requestStartTick); } #region SimGridEventHandlers diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs index 79e9994..65bd26c 100644 --- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs @@ -123,36 +123,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups public void AddRegion(Scene scene) { if (m_groupsEnabled) - { scene.RegisterModuleInterface(this); - scene.AddCommand( - "debug", - this, - "debug groups verbose", - "debug groups verbose ", - "This setting turns on very verbose groups debugging", - HandleDebugGroupsVerbose); - } - } - - private void HandleDebugGroupsVerbose(object modules, string[] args) - { - if (args.Length < 4) - { - MainConsole.Instance.Output("Usage: debug groups verbose "); - return; - } - - bool verbose = false; - if (!bool.TryParse(args[3], out verbose)) - { - MainConsole.Instance.Output("Usage: debug groups verbose "); - return; - } - - m_debugEnabled = verbose; - - MainConsole.Instance.OutputFormat("{0} verbose logging set to {1}", Name, m_debugEnabled); } public void RegionLoaded(Scene scene) diff --git a/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreModule.cs b/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreModule.cs index 732c28f..311531c 100644 --- a/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreModule.cs +++ b/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreModule.cs @@ -175,15 +175,14 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore /// /// // ----------------------------------------------------------------- - public bool CreateStore(string value, ref UUID result) + public bool CreateStore(string value, out UUID result) { - if (result == UUID.Zero) - result = UUID.Random(); - - JsonStore map = null; + result = UUID.Zero; if (! m_enabled) return false; + UUID uuid = UUID.Random(); + JsonStore map = null; try { @@ -196,8 +195,9 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore } lock (m_JsonValueStore) - m_JsonValueStore.Add(result,map); + m_JsonValueStore.Add(uuid,map); + result = uuid; return true; } @@ -231,7 +231,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore if (! m_JsonValueStore.TryGetValue(storeID,out map)) { m_log.InfoFormat("[JsonStore] Missing store {0}",storeID); - return false; + return true; } } diff --git a/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreScriptModule.cs b/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreScriptModule.cs index 6910d14..eaba816 100644 --- a/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreScriptModule.cs +++ b/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreScriptModule.cs @@ -227,7 +227,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore protected UUID JsonCreateStore(UUID hostID, UUID scriptID, string value) { UUID uuid = UUID.Zero; - if (! m_store.CreateStore(value, ref uuid)) + if (! m_store.CreateStore(value, out uuid)) GenerateRuntimeError("Failed to create Json store"); return uuid; diff --git a/OpenSim/Region/OptionalModules/Scripting/Minimodule/SOPObject.cs b/OpenSim/Region/OptionalModules/Scripting/Minimodule/SOPObject.cs index 5ed1514..aa23fee 100644 --- a/OpenSim/Region/OptionalModules/Scripting/Minimodule/SOPObject.cs +++ b/OpenSim/Region/OptionalModules/Scripting/Minimodule/SOPObject.cs @@ -821,11 +821,8 @@ namespace OpenSim.Region.OptionalModules.Scripting.Minimodule { if (!CanEdit()) return; - ISoundModule module = m_rootScene.RequestModuleInterface(); - if (module != null) - { - module.SendSound(GetSOP().UUID, asset, volume, true, 0, 0, false, false); - } + + GetSOP().SendSound(asset.ToString(), volume, true, 0, 0, false, false); } #endregion diff --git a/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs b/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs index bad75f7..fff3a32 100644 --- a/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs +++ b/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs @@ -181,7 +181,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.RegionReady } } - void OnOarFileLoaded(Guid requestId, List loadedScenes, string message) + void OnOarFileLoaded(Guid requestId, string message) { m_oarFileLoading = true; diff --git a/OpenSim/Region/OptionalModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs b/OpenSim/Region/OptionalModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs new file mode 100644 index 0000000..c5c96a9 --- /dev/null +++ b/OpenSim/Region/OptionalModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs @@ -0,0 +1,324 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Reflection; +using System.Collections.Generic; +using Nini.Config; +using log4net; +using OpenSim.Framework; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; +using Mono.Addins; +using OpenMetaverse; +using System.Linq; +using System.Linq.Expressions; + +namespace OpenSim.Region.OptionalModules.Scripting.ScriptModuleComms +{ + [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "ScriptModuleCommsModule")] + class ScriptModuleCommsModule : INonSharedRegionModule, IScriptModuleComms + { + private static readonly ILog m_log = + LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + private Dictionary m_constants = new Dictionary(); + +#region ScriptInvocation + protected class ScriptInvocationData + { + public Delegate ScriptInvocationDelegate { get; private set; } + public string FunctionName { get; private set; } + public Type[] TypeSignature { get; private set; } + public Type ReturnType { get; private set; } + + public ScriptInvocationData(string fname, Delegate fn, Type[] callsig, Type returnsig) + { + FunctionName = fname; + ScriptInvocationDelegate = fn; + TypeSignature = callsig; + ReturnType = returnsig; + } + } + + private Dictionary m_scriptInvocation = new Dictionary(); +#endregion + + private IScriptModule m_scriptModule = null; + public event ScriptCommand OnScriptCommand; + +#region RegionModuleInterface + public void Initialise(IConfigSource config) + { + } + + public void AddRegion(Scene scene) + { + scene.RegisterModuleInterface(this); + } + + public void RemoveRegion(Scene scene) + { + } + + public void RegionLoaded(Scene scene) + { + m_scriptModule = scene.RequestModuleInterface(); + + if (m_scriptModule != null) + m_log.Info("[MODULE COMMANDS]: Script engine found, module active"); + } + + public string Name + { + get { return "ScriptModuleCommsModule"; } + } + + public Type ReplaceableInterface + { + get { return null; } + } + + public void Close() + { + } +#endregion + +#region ScriptModuleComms + + public void RaiseEvent(UUID script, string id, string module, string command, string k) + { + ScriptCommand c = OnScriptCommand; + + if (c == null) + return; + + c(script, id, module, command, k); + } + + public void DispatchReply(UUID script, int code, string text, string k) + { + if (m_scriptModule == null) + return; + + Object[] args = new Object[] {-1, code, text, k}; + + m_scriptModule.PostScriptEvent(script, "link_message", args); + } + + public void RegisterScriptInvocation(object target, string meth) + { + MethodInfo mi = target.GetType().GetMethod(meth, + BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance); + if (mi == null) + { + m_log.WarnFormat("[MODULE COMMANDS] Failed to register method {0}",meth); + return; + } + + RegisterScriptInvocation(target, mi); + } + + public void RegisterScriptInvocation(object target, string[] meth) + { + foreach (string m in meth) + RegisterScriptInvocation(target, m); + } + + public void RegisterScriptInvocation(object target, MethodInfo mi) + { + m_log.DebugFormat("[MODULE COMMANDS] Register method {0} from type {1}", mi.Name, target.GetType().Name); + + Type delegateType; + var typeArgs = mi.GetParameters() + .Select(p => p.ParameterType) + .ToList(); + + if (mi.ReturnType == typeof(void)) + { + delegateType = Expression.GetActionType(typeArgs.ToArray()); + } + else + { + typeArgs.Add(mi.ReturnType); + delegateType = Expression.GetFuncType(typeArgs.ToArray()); + } + + Delegate fcall = Delegate.CreateDelegate(delegateType, target, mi); + + lock (m_scriptInvocation) + { + ParameterInfo[] parameters = fcall.Method.GetParameters (); + if (parameters.Length < 2) // Must have two UUID params + return; + + // Hide the first two parameters + Type[] parmTypes = new Type[parameters.Length - 2]; + for (int i = 2 ; i < parameters.Length ; i++) + parmTypes[i - 2] = parameters[i].ParameterType; + m_scriptInvocation[fcall.Method.Name] = new ScriptInvocationData(fcall.Method.Name, fcall, parmTypes, fcall.Method.ReturnType); + } + } + + public Delegate[] GetScriptInvocationList() + { + List ret = new List(); + + lock (m_scriptInvocation) + { + foreach (ScriptInvocationData d in m_scriptInvocation.Values) + ret.Add(d.ScriptInvocationDelegate); + } + return ret.ToArray(); + } + + public string LookupModInvocation(string fname) + { + lock (m_scriptInvocation) + { + ScriptInvocationData sid; + if (m_scriptInvocation.TryGetValue(fname,out sid)) + { + if (sid.ReturnType == typeof(string)) + return "modInvokeS"; + else if (sid.ReturnType == typeof(int)) + return "modInvokeI"; + else if (sid.ReturnType == typeof(float)) + return "modInvokeF"; + else if (sid.ReturnType == typeof(UUID)) + return "modInvokeK"; + else if (sid.ReturnType == typeof(OpenMetaverse.Vector3)) + return "modInvokeV"; + else if (sid.ReturnType == typeof(OpenMetaverse.Quaternion)) + return "modInvokeR"; + else if (sid.ReturnType == typeof(object[])) + return "modInvokeL"; + + m_log.WarnFormat("[MODULE COMMANDS] failed to find match for {0} with return type {1}",fname,sid.ReturnType.Name); + } + } + + return null; + } + + public Delegate LookupScriptInvocation(string fname) + { + lock (m_scriptInvocation) + { + ScriptInvocationData sid; + if (m_scriptInvocation.TryGetValue(fname,out sid)) + return sid.ScriptInvocationDelegate; + } + + return null; + } + + public Type[] LookupTypeSignature(string fname) + { + lock (m_scriptInvocation) + { + ScriptInvocationData sid; + if (m_scriptInvocation.TryGetValue(fname,out sid)) + return sid.TypeSignature; + } + + return null; + } + + public Type LookupReturnType(string fname) + { + lock (m_scriptInvocation) + { + ScriptInvocationData sid; + if (m_scriptInvocation.TryGetValue(fname,out sid)) + return sid.ReturnType; + } + + return null; + } + + public object InvokeOperation(UUID hostid, UUID scriptid, string fname, params object[] parms) + { + List olist = new List(); + olist.Add(hostid); + olist.Add(scriptid); + foreach (object o in parms) + olist.Add(o); + Delegate fn = LookupScriptInvocation(fname); + return fn.DynamicInvoke(olist.ToArray()); + } + + /// + /// Operation to for a region module to register a constant to be used + /// by the script engine + /// + public void RegisterConstant(string cname, object value) + { + m_log.DebugFormat("[MODULE COMMANDS] register constant <{0}> with value {1}",cname,value.ToString()); + lock (m_constants) + { + m_constants.Add(cname,value); + } + } + + /// + /// Operation to check for a registered constant + /// + public object LookupModConstant(string cname) + { + // m_log.DebugFormat("[MODULE COMMANDS] lookup constant <{0}>",cname); + + lock (m_constants) + { + object value = null; + if (m_constants.TryGetValue(cname,out value)) + return value; + } + + return null; + } + + /// + /// Get all registered constants + /// + public Dictionary GetConstants() + { + Dictionary ret = new Dictionary(); + + lock (m_constants) + { + foreach (KeyValuePair kvp in m_constants) + ret[kvp.Key] = kvp.Value; + } + + return ret; + } + +#endregion + + } +} diff --git a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs index 3a03101..6c8e2fc 100644 --- a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs +++ b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs @@ -148,7 +148,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC OnInstantMessage(this, new GridInstantMessage(m_scene, m_uuid, m_firstname + " " + m_lastname, target, 0, false, message, - UUID.Zero, false, Position, new byte[0], true)); + UUID.Zero, false, Position, new byte[0])); } public void SendAgentOffline(UUID[] agentIDs) @@ -607,15 +607,13 @@ namespace OpenSim.Region.OptionalModules.World.NPC { } - public virtual void SendChatMessage( - string message, byte type, Vector3 fromPos, string fromName, - UUID fromAgentID, UUID ownerID, byte source, byte audible) + public virtual void SendChatMessage(string message, byte type, Vector3 fromPos, string fromName, + UUID fromAgentID, byte source, byte audible) { } - public virtual void SendChatMessage( - byte[] message, byte type, Vector3 fromPos, string fromName, - UUID fromAgentID, UUID ownerID, byte source, byte audible) + public virtual void SendChatMessage(byte[] message, byte type, Vector3 fromPos, string fromName, + UUID fromAgentID, byte source, byte audible) { } @@ -911,13 +909,11 @@ namespace OpenSim.Region.OptionalModules.World.NPC public void Close() { - Close(true, false); + Close(true); } - public void Close(bool sendStop, bool force) + public void Close(bool sendStop) { - // Remove ourselves from the scene - m_scene.RemoveClient(AgentId, false); } public void Start() diff --git a/OpenSim/Region/OptionalModules/World/NPC/Tests/NPCModuleTests.cs b/OpenSim/Region/OptionalModules/World/NPC/Tests/NPCModuleTests.cs index 52ed846..9179966 100644 --- a/OpenSim/Region/OptionalModules/World/NPC/Tests/NPCModuleTests.cs +++ b/OpenSim/Region/OptionalModules/World/NPC/Tests/NPCModuleTests.cs @@ -117,12 +117,6 @@ namespace OpenSim.Region.OptionalModules.World.NPC.Tests Assert.That(npc, Is.Not.Null); Assert.That(npc.Appearance.Texture.FaceTextures[8].TextureID, Is.EqualTo(originalFace8TextureId)); Assert.That(m_umMod.GetUserName(npc.UUID), Is.EqualTo(string.Format("{0} {1}", npc.Firstname, npc.Lastname))); - - IClientAPI client; - Assert.That(m_scene.TryGetClient(npcId, out client), Is.True); - - // Have to account for both SP and NPC. - Assert.That(m_scene.AuthenticateHandler.GetAgentCircuits().Count, Is.EqualTo(2)); } [Test] @@ -142,11 +136,6 @@ namespace OpenSim.Region.OptionalModules.World.NPC.Tests ScenePresence deletedNpc = m_scene.GetScenePresence(npcId); Assert.That(deletedNpc, Is.Null); - IClientAPI client; - Assert.That(m_scene.TryGetClient(npcId, out client), Is.False); - - // Have to account for SP still present. - Assert.That(m_scene.AuthenticateHandler.GetAgentCircuits().Count, Is.EqualTo(1)); } [Test] diff --git a/OpenSim/Region/Physics/BulletSPlugin/BS6DofConstraint.cs b/OpenSim/Region/Physics/BulletSPlugin/BS6DofConstraint.cs new file mode 100755 index 0000000..683bc51 --- /dev/null +++ b/OpenSim/Region/Physics/BulletSPlugin/BS6DofConstraint.cs @@ -0,0 +1,118 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyrightD + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +using System; +using System.Collections.Generic; +using System.Text; +using OpenMetaverse; + +namespace OpenSim.Region.Physics.BulletSPlugin +{ + +public class BS6DofConstraint : BSConstraint +{ + // Create a btGeneric6DofConstraint + public BS6DofConstraint(BulletSim world, BulletBody obj1, BulletBody obj2, + Vector3 frame1, Quaternion frame1rot, + Vector3 frame2, Quaternion frame2rot, + bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies) + { + m_world = world; + m_body1 = obj1; + m_body2 = obj2; + m_constraint = new BulletConstraint( + BulletSimAPI.Create6DofConstraint2(m_world.Ptr, m_body1.Ptr, m_body2.Ptr, + frame1, frame1rot, + frame2, frame2rot, + useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies)); + m_enabled = true; + } + + public BS6DofConstraint(BulletSim world, BulletBody obj1, BulletBody obj2, + Vector3 joinPoint, + bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies) + { + m_world = world; + m_body1 = obj1; + m_body2 = obj2; + m_constraint = new BulletConstraint( + BulletSimAPI.Create6DofConstraintToPoint2(m_world.Ptr, m_body1.Ptr, m_body2.Ptr, + joinPoint, + useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies)); + m_enabled = true; + } + + public bool SetFrames(Vector3 frameA, Quaternion frameArot, Vector3 frameB, Quaternion frameBrot) + { + bool ret = false; + if (m_enabled) + { + BulletSimAPI.SetFrames2(m_constraint.Ptr, frameA, frameArot, frameB, frameBrot); + ret = true; + } + return ret; + } + + public bool SetCFMAndERP(float cfm, float erp) + { + bool ret = false; + if (m_enabled) + { + BulletSimAPI.SetConstraintParam2(m_constraint.Ptr, ConstraintParams.BT_CONSTRAINT_STOP_CFM, cfm, ConstraintParamAxis.AXIS_ALL); + BulletSimAPI.SetConstraintParam2(m_constraint.Ptr, ConstraintParams.BT_CONSTRAINT_STOP_ERP, erp, ConstraintParamAxis.AXIS_ALL); + BulletSimAPI.SetConstraintParam2(m_constraint.Ptr, ConstraintParams.BT_CONSTRAINT_CFM, cfm, ConstraintParamAxis.AXIS_ALL); + ret = true; + } + return ret; + } + + public bool UseFrameOffset(bool useOffset) + { + bool ret = false; + float onOff = useOffset ? ConfigurationParameters.numericTrue : ConfigurationParameters.numericFalse; + if (m_enabled) + ret = BulletSimAPI.UseFrameOffset2(m_constraint.Ptr, onOff); + return ret; + } + + public bool TranslationalLimitMotor(bool enable, float targetVelocity, float maxMotorForce) + { + bool ret = false; + float onOff = enable ? ConfigurationParameters.numericTrue : ConfigurationParameters.numericFalse; + if (m_enabled) + ret = BulletSimAPI.TranslationalLimitMotor2(m_constraint.Ptr, onOff, targetVelocity, maxMotorForce); + return ret; + } + + public bool SetBreakingImpulseThreshold(float threshold) + { + bool ret = false; + if (m_enabled) + ret = BulletSimAPI.SetBreakingImpulseThreshold2(m_constraint.Ptr, threshold); + return ret; + } +} +} diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs index 2a5397e..e2f7af9 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs @@ -28,48 +28,62 @@ using System; using System.Collections.Generic; using System.Reflection; using log4net; -using OMV = OpenMetaverse; +using OpenMetaverse; using OpenSim.Framework; using OpenSim.Region.Physics.Manager; namespace OpenSim.Region.Physics.BulletSPlugin { -public sealed class BSCharacter : BSPhysObject +public class BSCharacter : PhysicsActor { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private static readonly string LogHeader = "[BULLETS CHAR]"; + private BSScene _scene; + public BSScene Scene { get { return _scene; } } + private String _avName; // private bool _stopped; - private OMV.Vector3 _size; + private Vector3 _size; + private Vector3 _scale; + private PrimitiveBaseShape _pbs; + private uint _localID = 0; private bool _grabbed; private bool _selected; - private OMV.Vector3 _position; + private Vector3 _position; private float _mass; - private float _avatarDensity; - private float _avatarVolume; - private OMV.Vector3 _force; - private OMV.Vector3 _velocity; - private OMV.Vector3 _torque; + public float _density; + public float _avatarVolume; + private Vector3 _force; + private Vector3 _velocity; + private Vector3 _torque; private float _collisionScore; - private OMV.Vector3 _acceleration; - private OMV.Quaternion _orientation; + private Vector3 _acceleration; + private Quaternion _orientation; private int _physicsActorType; private bool _isPhysical; private bool _flying; private bool _setAlwaysRun; private bool _throttleUpdates; private bool _isColliding; + private long _collidingStep; + private bool _collidingGround; + private long _collidingGroundStep; private bool _collidingObj; private bool _floatOnWater; - private OMV.Vector3 _rotationalVelocity; + private Vector3 _rotationalVelocity; private bool _kinematic; private float _buoyancy; - // The friction and velocity of the avatar is modified depending on whether walking or not. - private OMV.Vector3 _appliedVelocity; // the last velocity applied to the avatar - private float _currentFriction; // the friction currently being used (changed by setVelocity). + private BulletBody m_body; + public BulletBody Body { + get { return m_body; } + set { m_body = value; } + } + + private int _subscribedEventsMs = 0; + private int _nextCollisionOkTime = 0; - private OMV.Vector3 _PIDTarget; + private Vector3 _PIDTarget; private bool _usePID; private float _PIDTau; private bool _useHoverPID; @@ -77,507 +91,332 @@ public sealed class BSCharacter : BSPhysObject private PIDHoverType _PIDHoverType; private float _PIDHoverTao; - public BSCharacter(uint localID, String avName, BSScene parent_scene, OMV.Vector3 pos, OMV.Vector3 size, bool isFlying) + public BSCharacter(uint localID, String avName, BSScene parent_scene, Vector3 pos, Vector3 size, bool isFlying) { - base.BaseInitialize(parent_scene, localID, avName, "BSCharacter"); - _physicsActorType = (int)ActorTypes.Agent; + _localID = localID; + _avName = avName; + _scene = parent_scene; _position = pos; _size = size; _flying = isFlying; - _orientation = OMV.Quaternion.Identity; - _velocity = OMV.Vector3.Zero; - _appliedVelocity = OMV.Vector3.Zero; + _orientation = Quaternion.Identity; + _velocity = Vector3.Zero; _buoyancy = ComputeBuoyancyFromFlying(isFlying); - _currentFriction = PhysicsScene.Params.avatarStandingFriction; - _avatarDensity = PhysicsScene.Params.avatarDensity; - // The dimensions of the avatar capsule are kept in the scale. // Physics creates a unit capsule which is scaled by the physics engine. - ComputeAvatarScale(_size); - // set _avatarVolume and _mass based on capsule size, _density and Scale - ComputeAvatarVolumeAndMass(); - DetailLog("{0},BSCharacter.create,call,size={1},scale={2},density={3},volume={4},mass={5}", - LocalID, _size, Scale, _avatarDensity, _avatarVolume, RawMass); + _scale = new Vector3(_scene.Params.avatarCapsuleRadius, _scene.Params.avatarCapsuleRadius, size.Z); + _density = _scene.Params.avatarDensity; + ComputeAvatarVolumeAndMass(); // set _avatarVolume and _mass based on capsule size, _density and _scale + + ShapeData shapeData = new ShapeData(); + shapeData.ID = _localID; + shapeData.Type = ShapeData.PhysicsShapeType.SHAPE_AVATAR; + shapeData.Position = _position; + shapeData.Rotation = _orientation; + shapeData.Velocity = _velocity; + shapeData.Scale = _scale; + shapeData.Mass = _mass; + shapeData.Buoyancy = _buoyancy; + shapeData.Static = ShapeData.numericFalse; + shapeData.Friction = _scene.Params.avatarFriction; + shapeData.Restitution = _scene.Params.avatarRestitution; // do actual create at taint time - PhysicsScene.TaintedObject("BSCharacter.create", delegate() + _scene.TaintedObject("BSCharacter.create", delegate() { - DetailLog("{0},BSCharacter.create,taint", LocalID); - // New body and shape into BSBody and BSShape - PhysicsScene.Shapes.GetBodyAndShape(true, PhysicsScene.World, this, null, null); + BulletSimAPI.CreateObject(parent_scene.WorldID, shapeData); - SetPhysicalProperties(); + m_body = new BulletBody(LocalID, BulletSimAPI.GetBodyHandle2(_scene.World.Ptr, LocalID)); + // avatars get all collisions no matter what + BulletSimAPI.AddToCollisionFlags2(Body.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); }); + return; } // called when this character is being destroyed and the resources should be released - public override void Destroy() + public void Destroy() { - DetailLog("{0},BSCharacter.Destroy", LocalID); - PhysicsScene.TaintedObject("BSCharacter.destroy", delegate() + // DetailLog("{0},BSCharacter.Destroy", LocalID); + _scene.TaintedObject("BSCharacter.destroy", delegate() { - PhysicsScene.Shapes.DereferenceBody(PhysBody, true, null); - PhysicsScene.Shapes.DereferenceShape(PhysShape, true, null); + BulletSimAPI.DestroyObject(_scene.WorldID, _localID); }); } - private void SetPhysicalProperties() - { - BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, PhysBody.ptr); - - ZeroMotion(); - ForcePosition = _position; - // Set the velocity and compute the proper friction - ForceVelocity = _velocity; - - BulletSimAPI.SetRestitution2(PhysBody.ptr, PhysicsScene.Params.avatarRestitution); - BulletSimAPI.SetMargin2(PhysShape.ptr, PhysicsScene.Params.collisionMargin); - BulletSimAPI.SetLocalScaling2(PhysShape.ptr, Scale); - BulletSimAPI.SetContactProcessingThreshold2(PhysBody.ptr, PhysicsScene.Params.contactProcessingThreshold); - if (PhysicsScene.Params.ccdMotionThreshold > 0f) - { - BulletSimAPI.SetCcdMotionThreshold2(PhysBody.ptr, PhysicsScene.Params.ccdMotionThreshold); - BulletSimAPI.SetCcdSweptSphereRadius2(PhysBody.ptr, PhysicsScene.Params.ccdSweptSphereRadius); - } - - UpdatePhysicalMassProperties(RawMass); - - // Make so capsule does not fall over - BulletSimAPI.SetAngularFactorV2(PhysBody.ptr, OMV.Vector3.Zero); - - BulletSimAPI.AddToCollisionFlags2(PhysBody.ptr, CollisionFlags.CF_CHARACTER_OBJECT); - - BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, PhysBody.ptr); - - // BulletSimAPI.ForceActivationState2(BSBody.ptr, ActivationState.ACTIVE_TAG); - BulletSimAPI.ForceActivationState2(PhysBody.ptr, ActivationState.DISABLE_DEACTIVATION); - BulletSimAPI.UpdateSingleAabb2(PhysicsScene.World.ptr, PhysBody.ptr); - - // Do this after the object has been added to the world - BulletSimAPI.SetCollisionFilterMask2(PhysBody.ptr, - (uint)CollisionFilterGroups.AvatarFilter, - (uint)CollisionFilterGroups.AvatarMask); - } - public override void RequestPhysicsterseUpdate() { base.RequestPhysicsterseUpdate(); } // No one calls this method so I don't know what it could possibly mean - public override bool Stopped { get { return false; } } - - public override OMV.Vector3 Size { + public override bool Stopped { + get { return false; } + } + public override Vector3 Size { get { // Avatar capsule size is kept in the scale parameter. - // return _size; - return new OMV.Vector3(Scale.X * 2f, Scale.Y * 2f, Scale.Z); + return new Vector3(_scale.X * 2, _scale.Y * 2, _scale.Z); } - set { - // When an avatar's size is set, only the height is changed. + set { + // When an avatar's size is set, only the height is changed + // and that really only depends on the radius. _size = value; - ComputeAvatarScale(_size); + _scale.Z = (_size.Z * 1.15f) - (_scale.X + _scale.Y); + + // TODO: something has to be done with the avatar's vertical position + ComputeAvatarVolumeAndMass(); - DetailLog("{0},BSCharacter.setSize,call,scale={1},density={2},volume={3},mass={4}", - LocalID, Scale, _avatarDensity, _avatarVolume, RawMass); - PhysicsScene.TaintedObject("BSCharacter.setSize", delegate() + _scene.TaintedObject("BSCharacter.setSize", delegate() { - BulletSimAPI.SetLocalScaling2(PhysShape.ptr, Scale); - UpdatePhysicalMassProperties(RawMass); + BulletSimAPI.SetObjectScaleMass(_scene.WorldID, LocalID, _scale, _mass, true); }); - } + } } - - public override OMV.Vector3 Scale { get; set; } - - public override PrimitiveBaseShape Shape - { - set { BaseShape = value; } + public override PrimitiveBaseShape Shape { + set { _pbs = value; + } } - // I want the physics engine to make an avatar capsule - public override ShapeData.PhysicsShapeType PreferredPhysicalShape - { - get {return ShapeData.PhysicsShapeType.SHAPE_AVATAR; } + public override uint LocalID { + set { _localID = value; + } + get { return _localID; } } - - public override bool Grabbed { - set { _grabbed = value; } + public override bool Grabbed { + set { _grabbed = value; + } } - public override bool Selected { - set { _selected = value; } + public override bool Selected { + set { _selected = value; + } } public override void CrossingFailure() { return; } public override void link(PhysicsActor obj) { return; } public override void delink() { return; } + public override void LockAngularMotion(Vector3 axis) { return; } - // Set motion values to zero. - // Do it to the properties so the values get set in the physics engine. - // Push the setting of the values to the viewer. - // Called at taint time! - public override void ZeroMotion() - { - _velocity = OMV.Vector3.Zero; - _acceleration = OMV.Vector3.Zero; - _rotationalVelocity = OMV.Vector3.Zero; - - // Zero some other properties directly into the physics engine - BulletSimAPI.SetLinearVelocity2(PhysBody.ptr, OMV.Vector3.Zero); - BulletSimAPI.SetAngularVelocity2(PhysBody.ptr, OMV.Vector3.Zero); - BulletSimAPI.SetInterpolationVelocity2(PhysBody.ptr, OMV.Vector3.Zero, OMV.Vector3.Zero); - BulletSimAPI.ClearForces2(PhysBody.ptr); - } - - public override void LockAngularMotion(OMV.Vector3 axis) { return; } - - public override OMV.Vector3 RawPosition - { - get { return _position; } - set { _position = value; } - } - public override OMV.Vector3 Position { + public override Vector3 Position { get { - // Don't refetch the position because this function is called a zillion times - // _position = BulletSimAPI.GetObjectPosition2(Scene.World.ptr, LocalID); - return _position; - } + // _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID); + return _position; + } set { _position = value; PositionSanityCheck(); - PhysicsScene.TaintedObject("BSCharacter.setPosition", delegate() + _scene.TaintedObject("BSCharacter.setPosition", delegate() { DetailLog("{0},BSCharacter.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation); - BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation); + BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation); }); - } - } - public override OMV.Vector3 ForcePosition { - get { - _position = BulletSimAPI.GetPosition2(PhysBody.ptr); - return _position; - } - set { - _position = value; - PositionSanityCheck(); - BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation); - } + } } - // Check that the current position is sane and, if not, modify the position to make it so. - // Check for being below terrain or on water. + // Check for being below terrain and being out of bounds. // Returns 'true' of the position was made sane by some action. private bool PositionSanityCheck() { bool ret = false; - + // If below the ground, move the avatar up - float terrainHeight = PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(_position); - if (Position.Z < terrainHeight) + float terrainHeight = Scene.GetTerrainHeightAtXYZ(_position); + if (_position.Z < terrainHeight) { - DetailLog("{0},BSCharacter.PositionAdjustUnderGround,call,pos={1},terrain={2}", LocalID, _position, terrainHeight); + DetailLog("{0},BSCharacter.PositionAdjustUnderGround,call,pos={1},orient={2}", LocalID, _position, _orientation); _position.Z = terrainHeight + 2.0f; ret = true; } - if ((CurrentCollisionFlags & CollisionFlags.BS_FLOATS_ON_WATER) != 0) - { - float waterHeight = PhysicsScene.GetWaterLevelAtXYZ(_position); - if (Position.Z < waterHeight) - { - _position.Z = waterHeight; - ret = true; - } - } // TODO: check for out of bounds - return ret; - } - // A version of the sanity check that also makes sure a new position value is - // pushed back to the physics engine. This routine would be used by anyone - // who is not already pushing the value. - private bool PositionSanityCheck(bool inTaintTime) - { - bool ret = false; - if (PositionSanityCheck()) - { - // The new position value must be pushed into the physics engine but we can't - // just assign to "Position" because of potential call loops. - PhysicsScene.TaintedObject(inTaintTime, "BSCharacter.PositionSanityCheck", delegate() - { - DetailLog("{0},BSCharacter.PositionSanityCheck,taint,pos={1},orient={2}", LocalID, _position, _orientation); - BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation); - }); - ret = true; - } return ret; } - public override float Mass { get { return _mass; } } - - // used when we only want this prim's mass and not the linkset thing - public override float RawMass { - get {return _mass; } - } - public override void UpdatePhysicalMassProperties(float physMass) - { - OMV.Vector3 localInertia = BulletSimAPI.CalculateLocalInertia2(PhysShape.ptr, physMass); - BulletSimAPI.SetMassProps2(PhysBody.ptr, physMass, localInertia); + public override float Mass { + get { + return _mass; + } } - - public override OMV.Vector3 Force { - get { return _force; } + public override Vector3 Force { + get { return _force; } set { _force = value; // m_log.DebugFormat("{0}: Force = {1}", LogHeader, _force); - PhysicsScene.TaintedObject("BSCharacter.SetForce", delegate() + Scene.TaintedObject("BSCharacter.SetForce", delegate() { DetailLog("{0},BSCharacter.setForce,taint,force={1}", LocalID, _force); - BulletSimAPI.SetObjectForce2(PhysBody.ptr, _force); + BulletSimAPI.SetObjectForce(Scene.WorldID, LocalID, _force); }); - } + } } - // Avatars don't do vehicles - public override int VehicleType { get { return (int)Vehicle.TYPE_NONE; } set { return; } } + public override int VehicleType { + get { return 0; } + set { return; } + } public override void VehicleFloatParam(int param, float value) { } - public override void VehicleVectorParam(int param, OMV.Vector3 value) {} - public override void VehicleRotationParam(int param, OMV.Quaternion rotation) { } + public override void VehicleVectorParam(int param, Vector3 value) {} + public override void VehicleRotationParam(int param, Quaternion rotation) { } public override void VehicleFlags(int param, bool remove) { } // Allows the detection of collisions with inherently non-physical prims. see llVolumeDetect for more public override void SetVolumeDetect(int param) { return; } - public override OMV.Vector3 GeometricCenter { get { return OMV.Vector3.Zero; } } - public override OMV.Vector3 CenterOfMass { get { return OMV.Vector3.Zero; } } - public override OMV.Vector3 Velocity { - get { return _velocity; } + public override Vector3 GeometricCenter { get { return Vector3.Zero; } } + public override Vector3 CenterOfMass { get { return Vector3.Zero; } } + public override Vector3 Velocity { + get { return _velocity; } set { _velocity = value; // m_log.DebugFormat("{0}: set velocity = {1}", LogHeader, _velocity); - PhysicsScene.TaintedObject("BSCharacter.setVelocity", delegate() + _scene.TaintedObject("BSCharacter.setVelocity", delegate() { DetailLog("{0},BSCharacter.setVelocity,taint,vel={1}", LocalID, _velocity); - ForceVelocity = _velocity; + BulletSimAPI.SetObjectVelocity(_scene.WorldID, _localID, _velocity); }); - } - } - public override OMV.Vector3 ForceVelocity { - get { return _velocity; } - set { - // Depending on whether the avatar is moving or not, change the friction - // to keep the avatar from slipping around - if (_velocity.Length() == 0) - { - if (_currentFriction != PhysicsScene.Params.avatarStandingFriction) - { - _currentFriction = PhysicsScene.Params.avatarStandingFriction; - BulletSimAPI.SetFriction2(PhysBody.ptr, _currentFriction); - } - } - else - { - if (_currentFriction != PhysicsScene.Params.avatarFriction) - { - _currentFriction = PhysicsScene.Params.avatarFriction; - BulletSimAPI.SetFriction2(PhysBody.ptr, _currentFriction); - } - } - _velocity = value; - // Remember the set velocity so we can suppress the reduction by friction, ... - _appliedVelocity = value; - - BulletSimAPI.SetLinearVelocity2(PhysBody.ptr, _velocity); - BulletSimAPI.Activate2(PhysBody.ptr, true); - } + } } - public override OMV.Vector3 Torque { - get { return _torque; } - set { _torque = value; - } + public override Vector3 Torque { + get { return _torque; } + set { _torque = value; + } } - public override float CollisionScore { - get { return _collisionScore; } - set { _collisionScore = value; - } + public override float CollisionScore { + get { return _collisionScore; } + set { _collisionScore = value; + } } - public override OMV.Vector3 Acceleration { + public override Vector3 Acceleration { get { return _acceleration; } set { _acceleration = value; } } - public override OMV.Quaternion RawOrientation - { - get { return _orientation; } - set { _orientation = value; } - } - public override OMV.Quaternion Orientation { - get { return _orientation; } + public override Quaternion Orientation { + get { return _orientation; } set { _orientation = value; // m_log.DebugFormat("{0}: set orientation to {1}", LogHeader, _orientation); - PhysicsScene.TaintedObject("BSCharacter.setOrientation", delegate() + _scene.TaintedObject("BSCharacter.setOrientation", delegate() { - // _position = BulletSimAPI.GetPosition2(BSBody.ptr); - BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation); + // _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID); + BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation); }); - } + } } - // Go directly to Bullet to get/set the value. - public override OMV.Quaternion ForceOrientation - { - get - { - _orientation = BulletSimAPI.GetOrientation2(PhysBody.ptr); - return _orientation; - } - set - { - _orientation = value; - BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation); - } - } - public override int PhysicsActorType { - get { return _physicsActorType; } - set { _physicsActorType = value; - } + public override int PhysicsActorType { + get { return _physicsActorType; } + set { _physicsActorType = value; + } } - public override bool IsPhysical { - get { return _isPhysical; } + public override bool IsPhysical { + get { return _isPhysical; } set { _isPhysical = value; - } - } - public override bool IsSolid { - get { return true; } + } } - public override bool IsStatic { - get { return false; } - } - public override bool Flying { - get { return _flying; } + public override bool Flying { + get { return _flying; } set { - _flying = value; - // simulate flying by changing the effect of gravity - Buoyancy = ComputeBuoyancyFromFlying(_flying); - } + if (_flying != value) + { + _flying = value; + // simulate flying by changing the effect of gravity + this.Buoyancy = ComputeBuoyancyFromFlying(_flying); + } + } } - // Flying is implimented by changing the avatar's buoyancy. - // Would this be done better with a vehicle type? private float ComputeBuoyancyFromFlying(bool ifFlying) { return ifFlying ? 1f : 0f; } - public override bool - SetAlwaysRun { - get { return _setAlwaysRun; } - set { _setAlwaysRun = value; } + public override bool + SetAlwaysRun { + get { return _setAlwaysRun; } + set { _setAlwaysRun = value; } } - public override bool ThrottleUpdates { - get { return _throttleUpdates; } - set { _throttleUpdates = value; } + public override bool ThrottleUpdates { + get { return _throttleUpdates; } + set { _throttleUpdates = value; } } public override bool IsColliding { - get { return (CollidingStep == PhysicsScene.SimulationStep); } - set { _isColliding = value; } + get { return (_collidingStep == _scene.SimulationStep); } + set { _isColliding = value; } } public override bool CollidingGround { - get { return (CollidingGroundStep == PhysicsScene.SimulationStep); } - set { CollidingGround = value; } - } - public override bool CollidingObj { - get { return _collidingObj; } - set { _collidingObj = value; } + get { return (_collidingGroundStep == _scene.SimulationStep); } + set { _collidingGround = value; } } - public override bool FloatOnWater { - set { - _floatOnWater = value; - PhysicsScene.TaintedObject("BSCharacter.setFloatOnWater", delegate() - { - if (_floatOnWater) - CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(PhysBody.ptr, CollisionFlags.BS_FLOATS_ON_WATER); - else - CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(PhysBody.ptr, CollisionFlags.BS_FLOATS_ON_WATER); - }); - } + public override bool CollidingObj { + get { return _collidingObj; } + set { _collidingObj = value; } } - public override OMV.Vector3 RotationalVelocity { - get { return _rotationalVelocity; } - set { _rotationalVelocity = value; } + public override bool FloatOnWater { + set { _floatOnWater = value; } } - public override OMV.Vector3 ForceRotationalVelocity { - get { return _rotationalVelocity; } - set { _rotationalVelocity = value; } + public override Vector3 RotationalVelocity { + get { return _rotationalVelocity; } + set { _rotationalVelocity = value; } } - public override bool Kinematic { - get { return _kinematic; } - set { _kinematic = value; } + public override bool Kinematic { + get { return _kinematic; } + set { _kinematic = value; } } // neg=fall quickly, 0=1g, 1=0g, pos=float up - public override float Buoyancy { - get { return _buoyancy; } - set { _buoyancy = value; - PhysicsScene.TaintedObject("BSCharacter.setBuoyancy", delegate() + public override float Buoyancy { + get { return _buoyancy; } + set { _buoyancy = value; + _scene.TaintedObject("BSCharacter.setBuoyancy", delegate() { DetailLog("{0},BSCharacter.setBuoyancy,taint,buoy={1}", LocalID, _buoyancy); - ForceBuoyancy = _buoyancy; + BulletSimAPI.SetObjectBuoyancy(_scene.WorldID, LocalID, _buoyancy); }); - } - } - public override float ForceBuoyancy { - get { return _buoyancy; } - set { _buoyancy = value; - DetailLog("{0},BSCharacter.setForceBuoyancy,taint,buoy={1}", LocalID, _buoyancy); - // Buoyancy is faked by changing the gravity applied to the object - float grav = PhysicsScene.Params.gravity * (1f - _buoyancy); - BulletSimAPI.SetGravity2(PhysBody.ptr, new OMV.Vector3(0f, 0f, grav)); - } + } } // Used for MoveTo - public override OMV.Vector3 PIDTarget { - set { _PIDTarget = value; } + public override Vector3 PIDTarget { + set { _PIDTarget = value; } } - public override bool PIDActive { - set { _usePID = value; } + public override bool PIDActive { + set { _usePID = value; } } - public override float PIDTau { - set { _PIDTau = value; } + public override float PIDTau { + set { _PIDTau = value; } } // Used for llSetHoverHeight and maybe vehicle height // Hover Height will override MoveTo target's Z - public override bool PIDHoverActive { + public override bool PIDHoverActive { set { _useHoverPID = value; } } - public override float PIDHoverHeight { + public override float PIDHoverHeight { set { _PIDHoverHeight = value; } } - public override PIDHoverType PIDHoverType { + public override PIDHoverType PIDHoverType { set { _PIDHoverType = value; } } - public override float PIDHoverTau { + public override float PIDHoverTau { set { _PIDHoverTao = value; } } // For RotLookAt - public override OMV.Quaternion APIDTarget { set { return; } } + public override Quaternion APIDTarget { set { return; } } public override bool APIDActive { set { return; } } public override float APIDStrength { set { return; } } public override float APIDDamping { set { return; } } - public override void AddForce(OMV.Vector3 force, bool pushforce) { + public override void AddForce(Vector3 force, bool pushforce) { if (force.IsFinite()) { _force.X += force.X; _force.Y += force.Y; _force.Z += force.Z; // m_log.DebugFormat("{0}: AddForce. adding={1}, newForce={2}", LogHeader, force, _force); - PhysicsScene.TaintedObject("BSCharacter.AddForce", delegate() + _scene.TaintedObject("BSCharacter.AddForce", delegate() { DetailLog("{0},BSCharacter.setAddForce,taint,addedForce={1}", LocalID, _force); - BulletSimAPI.SetObjectForce2(PhysBody.ptr, _force); + BulletSimAPI.AddObjectForce2(Body.Ptr, _force); }); } else @@ -587,75 +426,129 @@ public sealed class BSCharacter : BSPhysObject //m_lastUpdateSent = false; } - public override void AddAngularForce(OMV.Vector3 force, bool pushforce) { + public override void AddAngularForce(Vector3 force, bool pushforce) { } - public override void SetMomentum(OMV.Vector3 momentum) { + public override void SetMomentum(Vector3 momentum) { } - private void ComputeAvatarScale(OMV.Vector3 size) - { - // The 'size' given by the simulator is the mid-point of the avatar - // and X and Y are unspecified. - - OMV.Vector3 newScale = OMV.Vector3.Zero; - newScale.X = PhysicsScene.Params.avatarCapsuleRadius; - newScale.Y = PhysicsScene.Params.avatarCapsuleRadius; + // Turn on collision events at a rate no faster than one every the given milliseconds + public override void SubscribeEvents(int ms) { + _subscribedEventsMs = ms; + if (ms > 0) + { + // make sure first collision happens + _nextCollisionOkTime = Util.EnvironmentTickCount() - _subscribedEventsMs; - // From the total height, remove the capsule half spheres that are at each end - newScale.Z = size.Z- (newScale.X + newScale.Y); - Scale = newScale; + Scene.TaintedObject("BSCharacter.SubscribeEvents", delegate() + { + BulletSimAPI.AddToCollisionFlags2(Body.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); + }); + } + } + // Stop collision events + public override void UnSubscribeEvents() { + _subscribedEventsMs = 0; + // Avatars get all their collision events + // Scene.TaintedObject("BSCharacter.UnSubscribeEvents", delegate() + // { + // BulletSimAPI.RemoveFromCollisionFlags2(Body.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); + // }); + } + // Return 'true' if someone has subscribed to events + public override bool SubscribedEvents() { + return (_subscribedEventsMs > 0); } - // set _avatarVolume and _mass based on capsule size, _density and Scale + // set _avatarVolume and _mass based on capsule size, _density and _scale private void ComputeAvatarVolumeAndMass() { _avatarVolume = (float)( Math.PI - * Scale.X - * Scale.Y // the area of capsule cylinder - * Scale.Z // times height of capsule cylinder + * _scale.X + * _scale.Y // the area of capsule cylinder + * _scale.Z // times height of capsule cylinder + 1.33333333f * Math.PI - * Scale.X - * Math.Min(Scale.X, Scale.Y) - * Scale.Y // plus the volume of the capsule end caps + * _scale.X + * Math.Min(_scale.X, _scale.Y) + * _scale.Y // plus the volume of the capsule end caps ); - _mass = _avatarDensity * _avatarVolume; + _mass = _density * _avatarVolume; } // The physics engine says that properties have updated. Update same and inform // the world that things have changed. - public override void UpdateProperties(EntityProperties entprop) + public void UpdateProperties(EntityProperties entprop) { _position = entprop.Position; _orientation = entprop.Rotation; _velocity = entprop.Velocity; _acceleration = entprop.Acceleration; _rotationalVelocity = entprop.RotationalVelocity; - // Do some sanity checking for the avatar. Make sure it's above ground and inbounds. - PositionSanityCheck(true); + // Avatars don't report their changes the usual way. Changes are checked for in the heartbeat loop. + // base.RequestPhysicsterseUpdate(); + + /* + DetailLog("{0},BSCharacter.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5}", + LocalID, entprop.Position, entprop.Rotation, entprop.Velocity, + entprop.Acceleration, entprop.RotationalVelocity); + */ + } - // remember the current and last set values - LastEntityProperties = CurrentEntityProperties; - CurrentEntityProperties = entprop; + // Called by the scene when a collision with this object is reported + // The collision, if it should be reported to the character, is placed in a collection + // that will later be sent to the simulator when SendCollisions() is called. + CollisionEventUpdate collisionCollection = null; + public void Collide(uint collidingWith, ActorTypes type, Vector3 contactPoint, Vector3 contactNormal, float pentrationDepth) + { + // m_log.DebugFormat("{0}: Collide: ms={1}, id={2}, with={3}", LogHeader, _subscribedEventsMs, LocalID, collidingWith); - if (entprop.Velocity != LastEntityProperties.Velocity) + // The following makes IsColliding() and IsCollidingGround() work + _collidingStep = _scene.SimulationStep; + if (collidingWith == BSScene.TERRAIN_ID || collidingWith == BSScene.GROUNDPLANE_ID) { - // Changes in the velocity are suppressed in avatars. - // That's just the way they are defined. - OMV.Vector3 avVel = new OMV.Vector3(_appliedVelocity.X, _appliedVelocity.Y, entprop.Velocity.Z); - _velocity = avVel; - BulletSimAPI.SetLinearVelocity2(PhysBody.ptr, avVel); + _collidingGroundStep = _scene.SimulationStep; } + // DetailLog("{0},BSCharacter.Collison,call,with={1}", LocalID, collidingWith); - // Tell the linkset about value changes - Linkset.UpdateProperties(this); + // throttle collisions to the rate specified in the subscription + if (_subscribedEventsMs != 0) { + int nowTime = _scene.SimulationNowTime; + if (nowTime >= _nextCollisionOkTime) { + _nextCollisionOkTime = nowTime + _subscribedEventsMs; - // Avatars don't report their changes the usual way. Changes are checked for in the heartbeat loop. - // base.RequestPhysicsterseUpdate(); + if (collisionCollection == null) + collisionCollection = new CollisionEventUpdate(); + collisionCollection.AddCollider(collidingWith, new ContactPoint(contactPoint, contactNormal, pentrationDepth)); + } + } + } - DetailLog("{0},BSCharacter.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5}", - LocalID, _position, _orientation, _velocity, _acceleration, _rotationalVelocity); + public void SendCollisions() + { + /* + if (collisionCollection != null && collisionCollection.Count > 0) + { + base.SendCollisionUpdate(collisionCollection); + collisionCollection = null; + } + */ + // Kludge to make a collision call even if there are no collisions. + // This causes the avatar animation to get updated. + if (collisionCollection == null) + collisionCollection = new CollisionEventUpdate(); + base.SendCollisionUpdate(collisionCollection); + // If there were any collisions in the collection, make sure we don't use the + // same instance next time. + if (collisionCollection.Count > 0) + collisionCollection = null; + // End kludge + } + + // Invoke the detailed logger and output something if it's enabled. + private void DetailLog(string msg, params Object[] args) + { + Scene.PhysicsLogging.Write(msg, args); } } } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs b/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs index 65fac00..25084d8 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs @@ -34,20 +34,12 @@ namespace OpenSim.Region.Physics.BulletSPlugin public abstract class BSConstraint : IDisposable { - private static string LogHeader = "[BULLETSIM CONSTRAINT]"; - protected BulletSim m_world; protected BulletBody m_body1; protected BulletBody m_body2; protected BulletConstraint m_constraint; protected bool m_enabled = false; - public BulletBody Body1 { get { return m_body1; } } - public BulletBody Body2 { get { return m_body2; } } - public BulletConstraint Constraint { get { return m_constraint; } } - public abstract ConstraintType Type { get; } - public bool IsEnabled { get { return m_enabled; } } - public BSConstraint() { } @@ -56,25 +48,22 @@ public abstract class BSConstraint : IDisposable { if (m_enabled) { + // BulletSimAPI.RemoveConstraint(m_world.ID, m_body1.ID, m_body2.ID); + bool success = BulletSimAPI.DestroyConstraint2(m_world.Ptr, m_constraint.Ptr); + m_world.scene.DetailLog("{0},BSConstraint.Dispose,taint,body1={1},body2={2},success={3}", BSScene.DetailLogZero, m_body1.ID, m_body2.ID, success); + m_constraint.Ptr = System.IntPtr.Zero; m_enabled = false; - if (m_constraint.ptr != IntPtr.Zero) - { - bool success = BulletSimAPI.DestroyConstraint2(m_world.ptr, m_constraint.ptr); - m_world.physicsScene.DetailLog("{0},BSConstraint.Dispose,taint,id1={1},body1={2},id2={3},body2={4},success={5}", - BSScene.DetailLogZero, - m_body1.ID, m_body1.ptr.ToString("X"), - m_body2.ID, m_body2.ptr.ToString("X"), - success); - m_constraint.ptr = System.IntPtr.Zero; - } } } + public BulletBody Body1 { get { return m_body1; } } + public BulletBody Body2 { get { return m_body2; } } + public virtual bool SetLinearLimits(Vector3 low, Vector3 high) { bool ret = false; if (m_enabled) - ret = BulletSimAPI.SetLinearLimits2(m_constraint.ptr, low, high); + ret = BulletSimAPI.SetLinearLimits2(m_constraint.Ptr, low, high); return ret; } @@ -82,18 +71,7 @@ public abstract class BSConstraint : IDisposable { bool ret = false; if (m_enabled) - ret = BulletSimAPI.SetAngularLimits2(m_constraint.ptr, low, high); - return ret; - } - - public virtual bool SetSolverIterations(float cnt) - { - bool ret = false; - if (m_enabled) - { - BulletSimAPI.SetConstraintNumSolverIterations2(m_constraint.ptr, cnt); - ret = true; - } + ret = BulletSimAPI.SetAngularLimits2(m_constraint.Ptr, low, high); return ret; } @@ -103,7 +81,7 @@ public abstract class BSConstraint : IDisposable if (m_enabled) { // Recompute the internal transforms - BulletSimAPI.CalculateTransforms2(m_constraint.ptr); + BulletSimAPI.CalculateTransforms2(m_constraint.Ptr); ret = true; } return ret; @@ -119,14 +97,13 @@ public abstract class BSConstraint : IDisposable ret = CalculateTransforms(); if (ret) { - // Setting an object's mass to zero (making it static like when it's selected) - // automatically disables the constraints. - // If the link is enabled, be sure to set the constraint itself to enabled. - BulletSimAPI.SetConstraintEnable2(m_constraint.ptr, m_world.physicsScene.NumericBool(true)); + // m_world.scene.PhysicsLogging.Write("{0},BSConstraint.RecomputeConstraintVariables,taint,enabling,A={1},B={2}", + // BSScene.DetailLogZero, Body1.ID, Body2.ID); + BulletSimAPI.SetConstraintEnable2(m_constraint.Ptr, m_world.scene.NumericBool(true)); } else { - m_world.physicsScene.Logger.ErrorFormat("{0} CalculateTransforms failed. A={1}, B={2}", LogHeader, Body1.ID, Body2.ID); + m_world.scene.Logger.ErrorFormat("[BULLETSIM CONSTRAINT] CalculateTransforms failed. A={0}, B={1}", Body1.ID, Body2.ID); } } return ret; diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSConstraint6Dof.cs b/OpenSim/Region/Physics/BulletSPlugin/BSConstraint6Dof.cs deleted file mode 100755 index 23ef052..0000000 --- a/OpenSim/Region/Physics/BulletSPlugin/BSConstraint6Dof.cs +++ /dev/null @@ -1,153 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyrightD - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -using System; -using System.Collections.Generic; -using System.Text; -using OpenMetaverse; - -namespace OpenSim.Region.Physics.BulletSPlugin -{ - -public sealed class BSConstraint6Dof : BSConstraint -{ - private static string LogHeader = "[BULLETSIM 6DOF CONSTRAINT]"; - - public override ConstraintType Type { get { return ConstraintType.D6_CONSTRAINT_TYPE; } } - - // Create a btGeneric6DofConstraint - public BSConstraint6Dof(BulletSim world, BulletBody obj1, BulletBody obj2, - Vector3 frame1, Quaternion frame1rot, - Vector3 frame2, Quaternion frame2rot, - bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies) - { - m_world = world; - m_body1 = obj1; - m_body2 = obj2; - m_constraint = new BulletConstraint( - BulletSimAPI.Create6DofConstraint2(m_world.ptr, m_body1.ptr, m_body2.ptr, - frame1, frame1rot, - frame2, frame2rot, - useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies)); - m_enabled = true; - world.physicsScene.DetailLog("{0},BS6DofConstraint,createFrame,wID={1}, rID={2}, rBody={3}, cID={4}, cBody={5}", - BSScene.DetailLogZero, world.worldID, - obj1.ID, obj1.ptr.ToString("X"), obj2.ID, obj2.ptr.ToString("X")); - } - - public BSConstraint6Dof(BulletSim world, BulletBody obj1, BulletBody obj2, - Vector3 joinPoint, - bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies) - { - m_world = world; - m_body1 = obj1; - m_body2 = obj2; - if (obj1.ptr == IntPtr.Zero || obj2.ptr == IntPtr.Zero) - { - world.physicsScene.DetailLog("{0},BS6DOFConstraint,badBodyPtr,wID={1}, rID={2}, rBody={3}, cID={4}, cBody={5}", - BSScene.DetailLogZero, world.worldID, - obj1.ID, obj1.ptr.ToString("X"), obj2.ID, obj2.ptr.ToString("X")); - world.physicsScene.Logger.ErrorFormat("{0} Attempt to build 6DOF constraint with missing bodies: wID={1}, rID={2}, rBody={3}, cID={4}, cBody={5}", - LogHeader, world.worldID, obj1.ID, obj1.ptr.ToString("X"), obj2.ID, obj2.ptr.ToString("X")); - m_enabled = false; - } - else - { - m_constraint = new BulletConstraint( - BulletSimAPI.Create6DofConstraintToPoint2(m_world.ptr, m_body1.ptr, m_body2.ptr, - joinPoint, - useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies)); - world.physicsScene.DetailLog("{0},BS6DofConstraint,createMidPoint,wID={1}, csrt={2}, rID={3}, rBody={4}, cID={5}, cBody={6}", - BSScene.DetailLogZero, world.worldID, m_constraint.ptr.ToString("X"), - obj1.ID, obj1.ptr.ToString("X"), obj2.ID, obj2.ptr.ToString("X")); - if (m_constraint.ptr == IntPtr.Zero) - { - world.physicsScene.Logger.ErrorFormat("{0} Failed creation of 6Dof constraint. rootID={1}, childID={2}", - LogHeader, obj1.ID, obj2.ID); - m_enabled = false; - } - else - { - m_enabled = true; - } - } - } - - public bool SetFrames(Vector3 frameA, Quaternion frameArot, Vector3 frameB, Quaternion frameBrot) - { - bool ret = false; - if (m_enabled) - { - BulletSimAPI.SetFrames2(m_constraint.ptr, frameA, frameArot, frameB, frameBrot); - ret = true; - } - return ret; - } - - public bool SetCFMAndERP(float cfm, float erp) - { - bool ret = false; - if (m_enabled) - { - BulletSimAPI.SetConstraintParam2(m_constraint.ptr, ConstraintParams.BT_CONSTRAINT_STOP_CFM, cfm, ConstraintParamAxis.AXIS_ALL); - BulletSimAPI.SetConstraintParam2(m_constraint.ptr, ConstraintParams.BT_CONSTRAINT_STOP_ERP, erp, ConstraintParamAxis.AXIS_ALL); - BulletSimAPI.SetConstraintParam2(m_constraint.ptr, ConstraintParams.BT_CONSTRAINT_CFM, cfm, ConstraintParamAxis.AXIS_ALL); - ret = true; - } - return ret; - } - - public bool UseFrameOffset(bool useOffset) - { - bool ret = false; - float onOff = useOffset ? ConfigurationParameters.numericTrue : ConfigurationParameters.numericFalse; - if (m_enabled) - ret = BulletSimAPI.UseFrameOffset2(m_constraint.ptr, onOff); - return ret; - } - - public bool TranslationalLimitMotor(bool enable, float targetVelocity, float maxMotorForce) - { - bool ret = false; - float onOff = enable ? ConfigurationParameters.numericTrue : ConfigurationParameters.numericFalse; - if (m_enabled) - { - ret = BulletSimAPI.TranslationalLimitMotor2(m_constraint.ptr, onOff, targetVelocity, maxMotorForce); - m_world.physicsScene.DetailLog("{0},BS6DOFConstraint,TransLimitMotor,enable={1},vel={2},maxForce={3}", - BSScene.DetailLogZero, enable, targetVelocity, maxMotorForce); - } - return ret; - } - - public bool SetBreakingImpulseThreshold(float threshold) - { - bool ret = false; - if (m_enabled) - ret = BulletSimAPI.SetBreakingImpulseThreshold2(m_constraint.ptr, threshold); - return ret; - } -} -} diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSConstraintCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSConstraintCollection.cs index a9fd826..22ea367 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSConstraintCollection.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSConstraintCollection.cs @@ -33,7 +33,7 @@ using OpenMetaverse; namespace OpenSim.Region.Physics.BulletSPlugin { -public sealed class BSConstraintCollection : IDisposable +public class BSConstraintCollection : IDisposable { // private static readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); // private static readonly string LogHeader = "[CONSTRAINT COLLECTION]"; @@ -143,6 +143,8 @@ public sealed class BSConstraintCollection : IDisposable // Return 'true' if any constraints were destroyed. public bool RemoveAndDestroyConstraint(BulletBody body1) { + // return BulletSimAPI.RemoveConstraintByID(m_world.ID, obj.ID); + List toRemove = new List(); uint lookingID = body1.ID; lock (m_constraints) diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSConstraintHinge.cs b/OpenSim/Region/Physics/BulletSPlugin/BSConstraintHinge.cs deleted file mode 100755 index ed3ffa7..0000000 --- a/OpenSim/Region/Physics/BulletSPlugin/BSConstraintHinge.cs +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyrightD - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -using System; -using System.Collections.Generic; -using System.Text; -using OpenMetaverse; - -namespace OpenSim.Region.Physics.BulletSPlugin -{ - -public sealed class BSConstraintHinge : BSConstraint -{ - public override ConstraintType Type { get { return ConstraintType.HINGE_CONSTRAINT_TYPE; } } - - public BSConstraintHinge(BulletSim world, BulletBody obj1, BulletBody obj2, - Vector3 pivotInA, Vector3 pivotInB, - Vector3 axisInA, Vector3 axisInB, - bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies) - { - m_world = world; - m_body1 = obj1; - m_body2 = obj2; - m_constraint = new BulletConstraint( - BulletSimAPI.CreateHingeConstraint2(m_world.ptr, m_body1.ptr, m_body2.ptr, - pivotInA, pivotInB, - axisInA, axisInB, - useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies)); - m_enabled = true; - } - -} - -} diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs index 819635a..5a9f135 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs @@ -23,7 +23,7 @@ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * + */ /* RA: June 14, 2011. Copied from ODEDynamics.cs and converted to * call the BulletSim system. @@ -52,15 +52,19 @@ using OpenSim.Region.Physics.Manager; namespace OpenSim.Region.Physics.BulletSPlugin { - public sealed class BSDynamics + public class BSDynamics { - private BSScene PhysicsScene { get; set; } - // the prim this dynamic controller belongs to - private BSPrim Prim { get; set; } + private int frcount = 0; // Used to limit dynamics debug output to + // every 100th frame - // Vehicle properties - public Vehicle Type { get; set; } + private BSPrim m_prim; // the prim this dynamic controller belongs to + // Vehicle properties + private Vehicle m_type = Vehicle.TYPE_NONE; // If a 'VEHICLE', and what kind + public Vehicle Type + { + get { return m_type; } + } // private Quaternion m_referenceFrame = Quaternion.Identity; // Axis modifier private VehicleFlag m_flags = (VehicleFlag) 0; // Boolean settings: // HOVER_TERRAIN_ONLY @@ -70,15 +74,13 @@ namespace OpenSim.Region.Physics.BulletSPlugin // HOVER_UP_ONLY // LIMIT_MOTOR_UP // LIMIT_ROLL_ONLY + private VehicleFlag m_Hoverflags = (VehicleFlag)0; private Vector3 m_BlockingEndPoint = Vector3.Zero; private Quaternion m_RollreferenceFrame = Quaternion.Identity; - private Quaternion m_referenceFrame = Quaternion.Identity; - // Linear properties private Vector3 m_linearMotorDirection = Vector3.Zero; // velocity requested by LSL, decayed by time - private Vector3 m_linearMotorOffset = Vector3.Zero; // the point of force can be offset from the center private Vector3 m_linearMotorDirectionLASTSET = Vector3.Zero; // velocity requested by LSL - private Vector3 m_newVelocity = Vector3.Zero; // velocity computed to be applied to body + private Vector3 m_dir = Vector3.Zero; // velocity applied to body private Vector3 m_linearFrictionTimescale = Vector3.Zero; private float m_linearMotorDecayTimescale = 0; private float m_linearMotorTimescale = 0; @@ -89,28 +91,28 @@ namespace OpenSim.Region.Physics.BulletSPlugin //Angular properties private Vector3 m_angularMotorDirection = Vector3.Zero; // angular velocity requested by LSL motor - // private int m_angularMotorApply = 0; // application frame counter + private int m_angularMotorApply = 0; // application frame counter private Vector3 m_angularMotorVelocity = Vector3.Zero; // current angular motor velocity private float m_angularMotorTimescale = 0; // motor angular velocity ramp up rate private float m_angularMotorDecayTimescale = 0; // motor angular velocity decay rate private Vector3 m_angularFrictionTimescale = Vector3.Zero; // body angular velocity decay rate private Vector3 m_lastAngularVelocity = Vector3.Zero; // what was last applied to body - private Vector3 m_lastVertAttractor = Vector3.Zero; // what VA was last applied to body + // private Vector3 m_lastVertAttractor = Vector3.Zero; // what VA was last applied to body //Deflection properties - private float m_angularDeflectionEfficiency = 0; - private float m_angularDeflectionTimescale = 0; - private float m_linearDeflectionEfficiency = 0; - private float m_linearDeflectionTimescale = 0; + // private float m_angularDeflectionEfficiency = 0; + // private float m_angularDeflectionTimescale = 0; + // private float m_linearDeflectionEfficiency = 0; + // private float m_linearDeflectionTimescale = 0; //Banking properties - private float m_bankingEfficiency = 0; - private float m_bankingMix = 0; - private float m_bankingTimescale = 0; + // private float m_bankingEfficiency = 0; + // private float m_bankingMix = 0; + // private float m_bankingTimescale = 0; //Hover and Buoyancy properties private float m_VhoverHeight = 0f; - private float m_VhoverEfficiency = 0f; +// private float m_VhoverEfficiency = 0f; private float m_VhoverTimescale = 0f; private float m_VhoverTargetHeight = -1.0f; // if <0 then no hover, else its the current target height private float m_VehicleBuoyancy = 0f; //KF: m_VehicleBuoyancy is set by VEHICLE_BUOYANCY for a vehicle. @@ -122,74 +124,86 @@ namespace OpenSim.Region.Physics.BulletSPlugin private float m_verticalAttractionEfficiency = 1.0f; // damped private float m_verticalAttractionTimescale = 500f; // Timescale > 300 means no vert attractor. - public BSDynamics(BSScene myScene, BSPrim myPrim) - { - PhysicsScene = myScene; - Prim = myPrim; - Type = Vehicle.TYPE_NONE; - } - - // Return 'true' if this vehicle is doing vehicle things - public bool IsActive + public BSDynamics(BSPrim myPrim) { - get { return Type != Vehicle.TYPE_NONE; } + m_prim = myPrim; + m_type = Vehicle.TYPE_NONE; } - internal void ProcessFloatVehicleParam(Vehicle pParam, float pValue) + internal void ProcessFloatVehicleParam(Vehicle pParam, float pValue, float timestep) { - VDetailLog("{0},ProcessFloatVehicleParam,param={1},val={2}", Prim.LocalID, pParam, pValue); + DetailLog("{0},ProcessFloatVehicleParam,param={1},val={2}", m_prim.LocalID, pParam, pValue); switch (pParam) { case Vehicle.ANGULAR_DEFLECTION_EFFICIENCY: - m_angularDeflectionEfficiency = Math.Max(pValue, 0.01f); + if (pValue < 0.01f) pValue = 0.01f; + // m_angularDeflectionEfficiency = pValue; break; case Vehicle.ANGULAR_DEFLECTION_TIMESCALE: - m_angularDeflectionTimescale = Math.Max(pValue, 0.01f); + if (pValue < 0.01f) pValue = 0.01f; + // m_angularDeflectionTimescale = pValue; break; case Vehicle.ANGULAR_MOTOR_DECAY_TIMESCALE: - m_angularMotorDecayTimescale = Math.Max(pValue, 0.01f); + if (pValue < 0.01f) pValue = 0.01f; + m_angularMotorDecayTimescale = pValue; break; case Vehicle.ANGULAR_MOTOR_TIMESCALE: - m_angularMotorTimescale = Math.Max(pValue, 0.01f); + if (pValue < 0.01f) pValue = 0.01f; + m_angularMotorTimescale = pValue; break; case Vehicle.BANKING_EFFICIENCY: - m_bankingEfficiency = Math.Max(-1f, Math.Min(pValue, 1f)); + if (pValue < 0.01f) pValue = 0.01f; + // m_bankingEfficiency = pValue; break; case Vehicle.BANKING_MIX: - m_bankingMix = Math.Max(pValue, 0.01f); + if (pValue < 0.01f) pValue = 0.01f; + // m_bankingMix = pValue; break; case Vehicle.BANKING_TIMESCALE: - m_bankingTimescale = Math.Max(pValue, 0.01f); + if (pValue < 0.01f) pValue = 0.01f; + // m_bankingTimescale = pValue; break; case Vehicle.BUOYANCY: - m_VehicleBuoyancy = Math.Max(-1f, Math.Min(pValue, 1f)); - break; - case Vehicle.HOVER_EFFICIENCY: - m_VhoverEfficiency = Math.Max(0f, Math.Min(pValue, 1f)); - break; + if (pValue < -1f) pValue = -1f; + if (pValue > 1f) pValue = 1f; + m_VehicleBuoyancy = pValue; + break; +// case Vehicle.HOVER_EFFICIENCY: +// if (pValue < 0f) pValue = 0f; +// if (pValue > 1f) pValue = 1f; +// m_VhoverEfficiency = pValue; +// break; case Vehicle.HOVER_HEIGHT: m_VhoverHeight = pValue; break; case Vehicle.HOVER_TIMESCALE: - m_VhoverTimescale = Math.Max(pValue, 0.01f); + if (pValue < 0.01f) pValue = 0.01f; + m_VhoverTimescale = pValue; break; case Vehicle.LINEAR_DEFLECTION_EFFICIENCY: - m_linearDeflectionEfficiency = Math.Max(pValue, 0.01f); + if (pValue < 0.01f) pValue = 0.01f; + // m_linearDeflectionEfficiency = pValue; break; case Vehicle.LINEAR_DEFLECTION_TIMESCALE: - m_linearDeflectionTimescale = Math.Max(pValue, 0.01f); + if (pValue < 0.01f) pValue = 0.01f; + // m_linearDeflectionTimescale = pValue; break; case Vehicle.LINEAR_MOTOR_DECAY_TIMESCALE: - m_linearMotorDecayTimescale = Math.Max(pValue, 0.01f); + if (pValue < 0.01f) pValue = 0.01f; + m_linearMotorDecayTimescale = pValue; break; case Vehicle.LINEAR_MOTOR_TIMESCALE: - m_linearMotorTimescale = Math.Max(pValue, 0.01f); + if (pValue < 0.01f) pValue = 0.01f; + m_linearMotorTimescale = pValue; break; case Vehicle.VERTICAL_ATTRACTION_EFFICIENCY: - m_verticalAttractionEfficiency = Math.Max(0.1f, Math.Min(pValue, 1f)); + if (pValue < 0.1f) pValue = 0.1f; // Less goes unstable + if (pValue > 1.0f) pValue = 1.0f; + m_verticalAttractionEfficiency = pValue; break; case Vehicle.VERTICAL_ATTRACTION_TIMESCALE: - m_verticalAttractionTimescale = Math.Max(pValue, 0.01f); + if (pValue < 0.01f) pValue = 0.01f; + m_verticalAttractionTimescale = pValue; break; // These are vector properties but the engine lets you use a single float value to @@ -199,7 +213,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin break; case Vehicle.ANGULAR_MOTOR_DIRECTION: m_angularMotorDirection = new Vector3(pValue, pValue, pValue); - // m_angularMotorApply = 100; + m_angularMotorApply = 10; break; case Vehicle.LINEAR_FRICTION_TIMESCALE: m_linearFrictionTimescale = new Vector3(pValue, pValue, pValue); @@ -209,27 +223,30 @@ namespace OpenSim.Region.Physics.BulletSPlugin m_linearMotorDirectionLASTSET = new Vector3(pValue, pValue, pValue); break; case Vehicle.LINEAR_MOTOR_OFFSET: - m_linearMotorOffset = new Vector3(pValue, pValue, pValue); + // m_linearMotorOffset = new Vector3(pValue, pValue, pValue); break; } }//end ProcessFloatVehicleParam - internal void ProcessVectorVehicleParam(Vehicle pParam, Vector3 pValue) + internal void ProcessVectorVehicleParam(Vehicle pParam, Vector3 pValue, float timestep) { - VDetailLog("{0},ProcessVectorVehicleParam,param={1},val={2}", Prim.LocalID, pParam, pValue); + DetailLog("{0},ProcessVectorVehicleParam,param={1},val={2}", m_prim.LocalID, pParam, pValue); switch (pParam) { case Vehicle.ANGULAR_FRICTION_TIMESCALE: m_angularFrictionTimescale = new Vector3(pValue.X, pValue.Y, pValue.Z); break; case Vehicle.ANGULAR_MOTOR_DIRECTION: - // Limit requested angular speed to 2 rps= 4 pi rads/sec - pValue.X = Math.Max(-12.56f, Math.Min(pValue.X, 12.56f)); - pValue.Y = Math.Max(-12.56f, Math.Min(pValue.Y, 12.56f)); - pValue.Z = Math.Max(-12.56f, Math.Min(pValue.Z, 12.56f)); m_angularMotorDirection = new Vector3(pValue.X, pValue.Y, pValue.Z); - // m_angularMotorApply = 100; + // Limit requested angular speed to 2 rps= 4 pi rads/sec + if (m_angularMotorDirection.X > 12.56f) m_angularMotorDirection.X = 12.56f; + if (m_angularMotorDirection.X < - 12.56f) m_angularMotorDirection.X = - 12.56f; + if (m_angularMotorDirection.Y > 12.56f) m_angularMotorDirection.Y = 12.56f; + if (m_angularMotorDirection.Y < - 12.56f) m_angularMotorDirection.Y = - 12.56f; + if (m_angularMotorDirection.Z > 12.56f) m_angularMotorDirection.Z = 12.56f; + if (m_angularMotorDirection.Z < - 12.56f) m_angularMotorDirection.Z = - 12.56f; + m_angularMotorApply = 10; break; case Vehicle.LINEAR_FRICTION_TIMESCALE: m_linearFrictionTimescale = new Vector3(pValue.X, pValue.Y, pValue.Z); @@ -239,7 +256,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin m_linearMotorDirectionLASTSET = new Vector3(pValue.X, pValue.Y, pValue.Z); break; case Vehicle.LINEAR_MOTOR_OFFSET: - m_linearMotorOffset = new Vector3(pValue.X, pValue.Y, pValue.Z); + // m_linearMotorOffset = new Vector3(pValue.X, pValue.Y, pValue.Z); break; case Vehicle.BLOCK_EXIT: m_BlockingEndPoint = new Vector3(pValue.X, pValue.Y, pValue.Z); @@ -249,11 +266,11 @@ namespace OpenSim.Region.Physics.BulletSPlugin internal void ProcessRotationVehicleParam(Vehicle pParam, Quaternion pValue) { - VDetailLog("{0},ProcessRotationalVehicleParam,param={1},val={2}", Prim.LocalID, pParam, pValue); + DetailLog("{0},ProcessRotationalVehicleParam,param={1},val={2}", m_prim.LocalID, pParam, pValue); switch (pParam) { case Vehicle.REFERENCE_FRAME: - m_referenceFrame = pValue; + // m_referenceFrame = pValue; break; case Vehicle.ROLL_FRAME: m_RollreferenceFrame = pValue; @@ -263,492 +280,575 @@ namespace OpenSim.Region.Physics.BulletSPlugin internal void ProcessVehicleFlags(int pParam, bool remove) { - VDetailLog("{0},ProcessVehicleFlags,param={1},remove={2}", Prim.LocalID, pParam, remove); - VehicleFlag parm = (VehicleFlag)pParam; - if (pParam == -1) - m_flags = (VehicleFlag)0; + DetailLog("{0},ProcessVehicleFlags,param={1},remove={2}", m_prim.LocalID, pParam, remove); + if (remove) + { + if (pParam == -1) + { + m_flags = (VehicleFlag)0; + m_Hoverflags = (VehicleFlag)0; + return; + } + if ((pParam & (int)VehicleFlag.HOVER_GLOBAL_HEIGHT) == (int)VehicleFlag.HOVER_GLOBAL_HEIGHT) + { + if ((m_Hoverflags & VehicleFlag.HOVER_GLOBAL_HEIGHT) != (VehicleFlag)0) + m_Hoverflags &= ~(VehicleFlag.HOVER_GLOBAL_HEIGHT); + } + if ((pParam & (int)VehicleFlag.HOVER_TERRAIN_ONLY) == (int)VehicleFlag.HOVER_TERRAIN_ONLY) + { + if ((m_Hoverflags & VehicleFlag.HOVER_TERRAIN_ONLY) != (VehicleFlag)0) + m_Hoverflags &= ~(VehicleFlag.HOVER_TERRAIN_ONLY); + } + if ((pParam & (int)VehicleFlag.HOVER_UP_ONLY) == (int)VehicleFlag.HOVER_UP_ONLY) + { + if ((m_Hoverflags & VehicleFlag.HOVER_UP_ONLY) != (VehicleFlag)0) + m_Hoverflags &= ~(VehicleFlag.HOVER_UP_ONLY); + } + if ((pParam & (int)VehicleFlag.HOVER_WATER_ONLY) == (int)VehicleFlag.HOVER_WATER_ONLY) + { + if ((m_Hoverflags & VehicleFlag.HOVER_WATER_ONLY) != (VehicleFlag)0) + m_Hoverflags &= ~(VehicleFlag.HOVER_WATER_ONLY); + } + if ((pParam & (int)VehicleFlag.LIMIT_MOTOR_UP) == (int)VehicleFlag.LIMIT_MOTOR_UP) + { + if ((m_flags & VehicleFlag.LIMIT_MOTOR_UP) != (VehicleFlag)0) + m_flags &= ~(VehicleFlag.LIMIT_MOTOR_UP); + } + if ((pParam & (int)VehicleFlag.LIMIT_ROLL_ONLY) == (int)VehicleFlag.LIMIT_ROLL_ONLY) + { + if ((m_flags & VehicleFlag.LIMIT_ROLL_ONLY) != (VehicleFlag)0) + m_flags &= ~(VehicleFlag.LIMIT_ROLL_ONLY); + } + if ((pParam & (int)VehicleFlag.MOUSELOOK_BANK) == (int)VehicleFlag.MOUSELOOK_BANK) + { + if ((m_flags & VehicleFlag.MOUSELOOK_BANK) != (VehicleFlag)0) + m_flags &= ~(VehicleFlag.MOUSELOOK_BANK); + } + if ((pParam & (int)VehicleFlag.MOUSELOOK_STEER) == (int)VehicleFlag.MOUSELOOK_STEER) + { + if ((m_flags & VehicleFlag.MOUSELOOK_STEER) != (VehicleFlag)0) + m_flags &= ~(VehicleFlag.MOUSELOOK_STEER); + } + if ((pParam & (int)VehicleFlag.NO_DEFLECTION_UP) == (int)VehicleFlag.NO_DEFLECTION_UP) + { + if ((m_flags & VehicleFlag.NO_DEFLECTION_UP) != (VehicleFlag)0) + m_flags &= ~(VehicleFlag.NO_DEFLECTION_UP); + } + if ((pParam & (int)VehicleFlag.CAMERA_DECOUPLED) == (int)VehicleFlag.CAMERA_DECOUPLED) + { + if ((m_flags & VehicleFlag.CAMERA_DECOUPLED) != (VehicleFlag)0) + m_flags &= ~(VehicleFlag.CAMERA_DECOUPLED); + } + if ((pParam & (int)VehicleFlag.NO_X) == (int)VehicleFlag.NO_X) + { + if ((m_flags & VehicleFlag.NO_X) != (VehicleFlag)0) + m_flags &= ~(VehicleFlag.NO_X); + } + if ((pParam & (int)VehicleFlag.NO_Y) == (int)VehicleFlag.NO_Y) + { + if ((m_flags & VehicleFlag.NO_Y) != (VehicleFlag)0) + m_flags &= ~(VehicleFlag.NO_Y); + } + if ((pParam & (int)VehicleFlag.NO_Z) == (int)VehicleFlag.NO_Z) + { + if ((m_flags & VehicleFlag.NO_Z) != (VehicleFlag)0) + m_flags &= ~(VehicleFlag.NO_Z); + } + if ((pParam & (int)VehicleFlag.LOCK_HOVER_HEIGHT) == (int)VehicleFlag.LOCK_HOVER_HEIGHT) + { + if ((m_Hoverflags & VehicleFlag.LOCK_HOVER_HEIGHT) != (VehicleFlag)0) + m_Hoverflags &= ~(VehicleFlag.LOCK_HOVER_HEIGHT); + } + if ((pParam & (int)VehicleFlag.NO_DEFLECTION) == (int)VehicleFlag.NO_DEFLECTION) + { + if ((m_flags & VehicleFlag.NO_DEFLECTION) != (VehicleFlag)0) + m_flags &= ~(VehicleFlag.NO_DEFLECTION); + } + if ((pParam & (int)VehicleFlag.LOCK_ROTATION) == (int)VehicleFlag.LOCK_ROTATION) + { + if ((m_flags & VehicleFlag.LOCK_ROTATION) != (VehicleFlag)0) + m_flags &= ~(VehicleFlag.LOCK_ROTATION); + } + } else { - if (remove) - m_flags &= ~parm; - else - m_flags |= parm; + if ((pParam & (int)VehicleFlag.HOVER_GLOBAL_HEIGHT) == (int)VehicleFlag.HOVER_GLOBAL_HEIGHT) + { + m_Hoverflags |= (VehicleFlag.HOVER_GLOBAL_HEIGHT | m_flags); + } + if ((pParam & (int)VehicleFlag.HOVER_TERRAIN_ONLY) == (int)VehicleFlag.HOVER_TERRAIN_ONLY) + { + m_Hoverflags |= (VehicleFlag.HOVER_TERRAIN_ONLY | m_flags); + } + if ((pParam & (int)VehicleFlag.HOVER_UP_ONLY) == (int)VehicleFlag.HOVER_UP_ONLY) + { + m_Hoverflags |= (VehicleFlag.HOVER_UP_ONLY | m_flags); + } + if ((pParam & (int)VehicleFlag.HOVER_WATER_ONLY) == (int)VehicleFlag.HOVER_WATER_ONLY) + { + m_Hoverflags |= (VehicleFlag.HOVER_WATER_ONLY | m_flags); + } + if ((pParam & (int)VehicleFlag.LIMIT_MOTOR_UP) == (int)VehicleFlag.LIMIT_MOTOR_UP) + { + m_flags |= (VehicleFlag.LIMIT_MOTOR_UP | m_flags); + } + if ((pParam & (int)VehicleFlag.MOUSELOOK_BANK) == (int)VehicleFlag.MOUSELOOK_BANK) + { + m_flags |= (VehicleFlag.MOUSELOOK_BANK | m_flags); + } + if ((pParam & (int)VehicleFlag.MOUSELOOK_STEER) == (int)VehicleFlag.MOUSELOOK_STEER) + { + m_flags |= (VehicleFlag.MOUSELOOK_STEER | m_flags); + } + if ((pParam & (int)VehicleFlag.NO_DEFLECTION_UP) == (int)VehicleFlag.NO_DEFLECTION_UP) + { + m_flags |= (VehicleFlag.NO_DEFLECTION_UP | m_flags); + } + if ((pParam & (int)VehicleFlag.CAMERA_DECOUPLED) == (int)VehicleFlag.CAMERA_DECOUPLED) + { + m_flags |= (VehicleFlag.CAMERA_DECOUPLED | m_flags); + } + if ((pParam & (int)VehicleFlag.NO_X) == (int)VehicleFlag.NO_X) + { + m_flags |= (VehicleFlag.NO_X); + } + if ((pParam & (int)VehicleFlag.NO_Y) == (int)VehicleFlag.NO_Y) + { + m_flags |= (VehicleFlag.NO_Y); + } + if ((pParam & (int)VehicleFlag.NO_Z) == (int)VehicleFlag.NO_Z) + { + m_flags |= (VehicleFlag.NO_Z); + } + if ((pParam & (int)VehicleFlag.LOCK_HOVER_HEIGHT) == (int)VehicleFlag.LOCK_HOVER_HEIGHT) + { + m_Hoverflags |= (VehicleFlag.LOCK_HOVER_HEIGHT); + } + if ((pParam & (int)VehicleFlag.NO_DEFLECTION) == (int)VehicleFlag.NO_DEFLECTION) + { + m_flags |= (VehicleFlag.NO_DEFLECTION); + } + if ((pParam & (int)VehicleFlag.LOCK_ROTATION) == (int)VehicleFlag.LOCK_ROTATION) + { + m_flags |= (VehicleFlag.LOCK_ROTATION); + } } - } + }//end ProcessVehicleFlags internal void ProcessTypeChange(Vehicle pType) { - VDetailLog("{0},ProcessTypeChange,type={1}", Prim.LocalID, pType); + DetailLog("{0},ProcessTypeChange,type={1}", m_prim.LocalID, pType); // Set Defaults For Type - Type = pType; + m_type = pType; switch (pType) { - case Vehicle.TYPE_NONE: + case Vehicle.TYPE_NONE: + m_linearFrictionTimescale = new Vector3(0, 0, 0); + m_angularFrictionTimescale = new Vector3(0, 0, 0); m_linearMotorDirection = Vector3.Zero; m_linearMotorTimescale = 0; m_linearMotorDecayTimescale = 0; - m_linearFrictionTimescale = new Vector3(0, 0, 0); - m_angularMotorDirection = Vector3.Zero; - m_angularMotorDecayTimescale = 0; m_angularMotorTimescale = 0; - m_angularFrictionTimescale = new Vector3(0, 0, 0); - + m_angularMotorDecayTimescale = 0; m_VhoverHeight = 0; - m_VhoverEfficiency = 0; m_VhoverTimescale = 0; m_VehicleBuoyancy = 0; - - m_linearDeflectionEfficiency = 1; - m_linearDeflectionTimescale = 1; - - m_angularDeflectionEfficiency = 0; - m_angularDeflectionTimescale = 1000; - - m_verticalAttractionEfficiency = 0; - m_verticalAttractionTimescale = 0; - - m_bankingEfficiency = 0; - m_bankingTimescale = 1000; - m_bankingMix = 1; - - m_referenceFrame = Quaternion.Identity; m_flags = (VehicleFlag)0; break; case Vehicle.TYPE_SLED: + m_linearFrictionTimescale = new Vector3(30, 1, 1000); + m_angularFrictionTimescale = new Vector3(1000, 1000, 1000); m_linearMotorDirection = Vector3.Zero; m_linearMotorTimescale = 1000; m_linearMotorDecayTimescale = 120; - m_linearFrictionTimescale = new Vector3(30, 1, 1000); - m_angularMotorDirection = Vector3.Zero; m_angularMotorTimescale = 1000; m_angularMotorDecayTimescale = 120; - m_angularFrictionTimescale = new Vector3(1000, 1000, 1000); - m_VhoverHeight = 0; - m_VhoverEfficiency = 10; // TODO: this looks wrong!! +// m_VhoverEfficiency = 1; m_VhoverTimescale = 10; m_VehicleBuoyancy = 0; - - m_linearDeflectionEfficiency = 1; - m_linearDeflectionTimescale = 1; - - m_angularDeflectionEfficiency = 1; - m_angularDeflectionTimescale = 1000; - - m_verticalAttractionEfficiency = 0; - m_verticalAttractionTimescale = 0; - - m_bankingEfficiency = 0; - m_bankingTimescale = 10; - m_bankingMix = 1; - - m_referenceFrame = Quaternion.Identity; - m_flags |= (VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.LIMIT_ROLL_ONLY | VehicleFlag.LIMIT_MOTOR_UP); - m_flags &= + // m_linearDeflectionEfficiency = 1; + // m_linearDeflectionTimescale = 1; + // m_angularDeflectionEfficiency = 1; + // m_angularDeflectionTimescale = 1000; + // m_bankingEfficiency = 0; + // m_bankingMix = 1; + // m_bankingTimescale = 10; + // m_referenceFrame = Quaternion.Identity; + m_Hoverflags &= ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT | VehicleFlag.HOVER_UP_ONLY); + m_flags |= (VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.LIMIT_ROLL_ONLY | VehicleFlag.LIMIT_MOTOR_UP); break; case Vehicle.TYPE_CAR: + m_linearFrictionTimescale = new Vector3(100, 2, 1000); + m_angularFrictionTimescale = new Vector3(1000, 1000, 1000); m_linearMotorDirection = Vector3.Zero; m_linearMotorTimescale = 1; m_linearMotorDecayTimescale = 60; - m_linearFrictionTimescale = new Vector3(100, 2, 1000); - m_angularMotorDirection = Vector3.Zero; m_angularMotorTimescale = 1; m_angularMotorDecayTimescale = 0.8f; - m_angularFrictionTimescale = new Vector3(1000, 1000, 1000); - m_VhoverHeight = 0; - m_VhoverEfficiency = 0; +// m_VhoverEfficiency = 0; m_VhoverTimescale = 1000; m_VehicleBuoyancy = 0; - - m_linearDeflectionEfficiency = 1; - m_linearDeflectionTimescale = 2; - - m_angularDeflectionEfficiency = 0; - m_angularDeflectionTimescale = 10; - + // // m_linearDeflectionEfficiency = 1; + // // m_linearDeflectionTimescale = 2; + // // m_angularDeflectionEfficiency = 0; + // m_angularDeflectionTimescale = 10; m_verticalAttractionEfficiency = 1f; m_verticalAttractionTimescale = 10f; - - m_bankingEfficiency = -0.2f; - m_bankingMix = 1; - m_bankingTimescale = 1; - - m_referenceFrame = Quaternion.Identity; - m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY - | VehicleFlag.HOVER_TERRAIN_ONLY - | VehicleFlag.HOVER_GLOBAL_HEIGHT); - m_flags |= (VehicleFlag.NO_DEFLECTION_UP - | VehicleFlag.LIMIT_ROLL_ONLY - | VehicleFlag.LIMIT_MOTOR_UP - | VehicleFlag.HOVER_UP_ONLY); + // m_bankingEfficiency = -0.2f; + // m_bankingMix = 1; + // m_bankingTimescale = 1; + // m_referenceFrame = Quaternion.Identity; + m_Hoverflags &= ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT); + m_flags |= (VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.LIMIT_ROLL_ONLY | + VehicleFlag.LIMIT_MOTOR_UP); + m_Hoverflags |= (VehicleFlag.HOVER_UP_ONLY); break; case Vehicle.TYPE_BOAT: + m_linearFrictionTimescale = new Vector3(10, 3, 2); + m_angularFrictionTimescale = new Vector3(10,10,10); m_linearMotorDirection = Vector3.Zero; m_linearMotorTimescale = 5; m_linearMotorDecayTimescale = 60; - m_linearFrictionTimescale = new Vector3(10, 3, 2); - m_angularMotorDirection = Vector3.Zero; m_angularMotorTimescale = 4; m_angularMotorDecayTimescale = 4; - m_angularFrictionTimescale = new Vector3(10,10,10); - m_VhoverHeight = 0; - m_VhoverEfficiency = 0.5f; +// m_VhoverEfficiency = 0.5f; m_VhoverTimescale = 2; m_VehicleBuoyancy = 1; - - m_linearDeflectionEfficiency = 0.5f; - m_linearDeflectionTimescale = 3; - - m_angularDeflectionEfficiency = 0.5f; - m_angularDeflectionTimescale = 5; - + // m_linearDeflectionEfficiency = 0.5f; + // m_linearDeflectionTimescale = 3; + // m_angularDeflectionEfficiency = 0.5f; + // m_angularDeflectionTimescale = 5; m_verticalAttractionEfficiency = 0.5f; m_verticalAttractionTimescale = 5f; - - m_bankingEfficiency = -0.3f; - m_bankingMix = 0.8f; - m_bankingTimescale = 1; - - m_referenceFrame = Quaternion.Identity; - m_flags &= ~(VehicleFlag.HOVER_TERRAIN_ONLY - | VehicleFlag.HOVER_GLOBAL_HEIGHT - | VehicleFlag.LIMIT_ROLL_ONLY - | VehicleFlag.HOVER_UP_ONLY); - m_flags |= (VehicleFlag.NO_DEFLECTION_UP - | VehicleFlag.LIMIT_MOTOR_UP - | VehicleFlag.HOVER_WATER_ONLY); + // m_bankingEfficiency = -0.3f; + // m_bankingMix = 0.8f; + // m_bankingTimescale = 1; + // m_referenceFrame = Quaternion.Identity; + m_Hoverflags &= ~(VehicleFlag.HOVER_TERRAIN_ONLY | + VehicleFlag.HOVER_GLOBAL_HEIGHT | VehicleFlag.HOVER_UP_ONLY); + m_flags &= ~(VehicleFlag.LIMIT_ROLL_ONLY); + m_flags |= (VehicleFlag.NO_DEFLECTION_UP | + VehicleFlag.LIMIT_MOTOR_UP); + m_Hoverflags |= (VehicleFlag.HOVER_WATER_ONLY); break; case Vehicle.TYPE_AIRPLANE: + m_linearFrictionTimescale = new Vector3(200, 10, 5); + m_angularFrictionTimescale = new Vector3(20, 20, 20); m_linearMotorDirection = Vector3.Zero; m_linearMotorTimescale = 2; m_linearMotorDecayTimescale = 60; - m_linearFrictionTimescale = new Vector3(200, 10, 5); - m_angularMotorDirection = Vector3.Zero; m_angularMotorTimescale = 4; m_angularMotorDecayTimescale = 4; - m_angularFrictionTimescale = new Vector3(20, 20, 20); - m_VhoverHeight = 0; - m_VhoverEfficiency = 0.5f; +// m_VhoverEfficiency = 0.5f; m_VhoverTimescale = 1000; m_VehicleBuoyancy = 0; - - m_linearDeflectionEfficiency = 0.5f; - m_linearDeflectionTimescale = 3; - - m_angularDeflectionEfficiency = 1; - m_angularDeflectionTimescale = 2; - + // m_linearDeflectionEfficiency = 0.5f; + // m_linearDeflectionTimescale = 3; + // m_angularDeflectionEfficiency = 1; + // m_angularDeflectionTimescale = 2; m_verticalAttractionEfficiency = 0.9f; m_verticalAttractionTimescale = 2f; - - m_bankingEfficiency = 1; - m_bankingMix = 0.7f; - m_bankingTimescale = 2; - - m_referenceFrame = Quaternion.Identity; - m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY - | VehicleFlag.HOVER_TERRAIN_ONLY - | VehicleFlag.HOVER_GLOBAL_HEIGHT - | VehicleFlag.HOVER_UP_ONLY - | VehicleFlag.NO_DEFLECTION_UP - | VehicleFlag.LIMIT_MOTOR_UP); + // m_bankingEfficiency = 1; + // m_bankingMix = 0.7f; + // m_bankingTimescale = 2; + // m_referenceFrame = Quaternion.Identity; + m_Hoverflags &= ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | + VehicleFlag.HOVER_GLOBAL_HEIGHT | VehicleFlag.HOVER_UP_ONLY); + m_flags &= ~(VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.LIMIT_MOTOR_UP); m_flags |= (VehicleFlag.LIMIT_ROLL_ONLY); break; case Vehicle.TYPE_BALLOON: + m_linearFrictionTimescale = new Vector3(5, 5, 5); + m_angularFrictionTimescale = new Vector3(10, 10, 10); m_linearMotorDirection = Vector3.Zero; m_linearMotorTimescale = 5; - m_linearFrictionTimescale = new Vector3(5, 5, 5); m_linearMotorDecayTimescale = 60; - m_angularMotorDirection = Vector3.Zero; m_angularMotorTimescale = 6; - m_angularFrictionTimescale = new Vector3(10, 10, 10); m_angularMotorDecayTimescale = 10; - m_VhoverHeight = 5; - m_VhoverEfficiency = 0.8f; +// m_VhoverEfficiency = 0.8f; m_VhoverTimescale = 10; m_VehicleBuoyancy = 1; - - m_linearDeflectionEfficiency = 0; - m_linearDeflectionTimescale = 5; - - m_angularDeflectionEfficiency = 0; - m_angularDeflectionTimescale = 5; - + // m_linearDeflectionEfficiency = 0; + // m_linearDeflectionTimescale = 5; + // m_angularDeflectionEfficiency = 0; + // m_angularDeflectionTimescale = 5; m_verticalAttractionEfficiency = 1f; m_verticalAttractionTimescale = 100f; - - m_bankingEfficiency = 0; - m_bankingMix = 0.7f; - m_bankingTimescale = 5; - m_referenceFrame = Quaternion.Identity; - - m_referenceFrame = Quaternion.Identity; - m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY - | VehicleFlag.HOVER_TERRAIN_ONLY - | VehicleFlag.HOVER_UP_ONLY - | VehicleFlag.NO_DEFLECTION_UP - | VehicleFlag.LIMIT_MOTOR_UP); - m_flags |= (VehicleFlag.LIMIT_ROLL_ONLY - | VehicleFlag.HOVER_GLOBAL_HEIGHT); + // m_bankingEfficiency = 0; + // m_bankingMix = 0.7f; + // m_bankingTimescale = 5; + // m_referenceFrame = Quaternion.Identity; + m_Hoverflags &= ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | + VehicleFlag.HOVER_UP_ONLY); + m_flags &= ~(VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.LIMIT_MOTOR_UP); + m_flags |= (VehicleFlag.LIMIT_ROLL_ONLY); + m_Hoverflags |= (VehicleFlag.HOVER_GLOBAL_HEIGHT); break; } - } + }//end SetDefaultsForType - // Some of the properties of this prim may have changed. - // Do any updating needed for a vehicle - public void Refresh() - { - if (IsActive) - { - // Friction effects are handled by this vehicle code - BulletSimAPI.SetFriction2(Prim.PhysBody.ptr, 0f); - BulletSimAPI.SetHitFraction2(Prim.PhysBody.ptr, 0f); - } - } - - // One step of the vehicle properties for the next 'pTimestep' seconds. internal void Step(float pTimestep) { - if (!IsActive) return; + if (m_type == Vehicle.TYPE_NONE) return; - // DEBUG - // Because Bullet does apply forces to the vehicle, our last computed - // linear and angular velocities are not what is happening now. - // Vector3 externalAngularVelocity = Prim.ForceRotationalVelocity - m_lastAngularVelocity; - // m_lastAngularVelocity += (externalAngularVelocity * 0.5f) * pTimestep; - // m_lastAngularVelocity = Prim.ForceRotationalVelocity; // DEBUG: account for what Bullet did last time - // m_lastLinearVelocityVector = Prim.ForceVelocity * Quaternion.Inverse(Prim.ForceOrientation); // DEBUG: - // END DEBUG + frcount++; // used to limit debug comment output + if (frcount > 100) + frcount = 0; MoveLinear(pTimestep); MoveAngular(pTimestep); LimitRotation(pTimestep); - // DEBUG: Trying to figure out why Bullet goes crazy when the root prim is moved. - // BulletSimAPI.SetInterpolationVelocity2(Prim.BSBody.ptr, m_newVelocity, m_lastAngularVelocity); // DEBUG DEBUG DEBUG - - // remember the position so next step we can limit absolute movement effects - m_lastPositionVector = Prim.ForcePosition; - - VDetailLog("{0},BSDynamics.Step,done,pos={1},force={2},velocity={3},angvel={4}", - Prim.LocalID, Prim.ForcePosition, Prim.Force, Prim.ForceVelocity, Prim.RotationalVelocity); + DetailLog("{0},BSDynamics.Step,done,pos={1},force={2},velocity={3},angvel={4}", + m_prim.LocalID, m_prim.Position, m_prim.Force, m_prim.Velocity, m_prim.RotationalVelocity); }// end Step - // Apply the effect of the linear motor. - // Also does hover and float. private void MoveLinear(float pTimestep) { - // m_linearMotorDirection is the target direction we are moving relative to the vehicle coordinates - // m_lastLinearVelocityVector is the current speed we are moving in that direction - if (m_linearMotorDirection.LengthSquared() > 0.001f) + // requested m_linearMotorDirection is significant + // if (!m_linearMotorDirection.ApproxEquals(Vector3.Zero, 0.01f)) + if (m_linearMotorDirection.LengthSquared() > 0.0001f) { Vector3 origDir = m_linearMotorDirection; Vector3 origVel = m_lastLinearVelocityVector; - Vector3 vehicleVelocity = Prim.ForceVelocity * Quaternion.Inverse(Prim.ForceOrientation); // DEBUG // add drive to body - Vector3 addAmount = (m_linearMotorDirection - m_lastLinearVelocityVector)/(m_linearMotorTimescale) * pTimestep; - // lastLinearVelocityVector is the current body velocity vector + // Vector3 addAmount = m_linearMotorDirection/(m_linearMotorTimescale/pTimestep); + Vector3 addAmount = m_linearMotorDirection/(m_linearMotorTimescale); + // lastLinearVelocityVector is the current body velocity vector? + // RA: Not sure what the *10 is for. A correction for pTimestep? + // m_lastLinearVelocityVector += (addAmount*10); + m_lastLinearVelocityVector += addAmount; + + // This will work temporarily, but we really need to compare speed on an axis + // KF: Limit body velocity to applied velocity? + // Limit the velocity vector to less than the last set linear motor direction + if (Math.Abs(m_lastLinearVelocityVector.X) > Math.Abs(m_linearMotorDirectionLASTSET.X)) + m_lastLinearVelocityVector.X = m_linearMotorDirectionLASTSET.X; + if (Math.Abs(m_lastLinearVelocityVector.Y) > Math.Abs(m_linearMotorDirectionLASTSET.Y)) + m_lastLinearVelocityVector.Y = m_linearMotorDirectionLASTSET.Y; + if (Math.Abs(m_lastLinearVelocityVector.Z) > Math.Abs(m_linearMotorDirectionLASTSET.Z)) + m_lastLinearVelocityVector.Z = m_linearMotorDirectionLASTSET.Z; + + // decay applied velocity + Vector3 decayfraction = ((Vector3.One/(m_linearMotorDecayTimescale/pTimestep))); + m_linearMotorDirection -= m_linearMotorDirection * decayfraction * 0.5f; + + /* + Vector3 addAmount = (m_linearMotorDirection - m_lastLinearVelocityVector)/m_linearMotorTimescale; m_lastLinearVelocityVector += addAmount; - float decayFactor = (1.0f / m_linearMotorDecayTimescale) * pTimestep; - m_linearMotorDirection *= (1f - decayFactor); + float decayfraction = (1.0f - 1.0f / m_linearMotorDecayTimescale); + m_linearMotorDirection *= decayfraction; - Vector3 frictionFactor = (Vector3.One / m_linearFrictionTimescale) * pTimestep; - m_lastLinearVelocityVector *= (Vector3.One - frictionFactor); + */ - // Rotate new object velocity from vehicle relative to world coordinates - m_newVelocity = m_lastLinearVelocityVector * Prim.ForceOrientation; - - VDetailLog("{0},MoveLinear,nonZero,origdir={1},origvel={2},vehVel={3},add={4},decay={5},frict={6},lmDir={7},lmVel={8},newVel={9}", - Prim.LocalID, origDir, origVel, vehicleVelocity, addAmount, decayFactor, frictionFactor, - m_linearMotorDirection, m_lastLinearVelocityVector, m_newVelocity); + DetailLog("{0},MoveLinear,nonZero,origdir={1},origvel={2},add={3},decay={4},dir={5},vel={6}", + m_prim.LocalID, origDir, origVel, addAmount, decayfraction, m_linearMotorDirection, m_lastLinearVelocityVector); } else { - // if what remains of direction is very small, zero it. + // if what remains of applied is small, zero it. + // if (m_lastLinearVelocityVector.ApproxEquals(Vector3.Zero, 0.01f)) + // m_lastLinearVelocityVector = Vector3.Zero; m_linearMotorDirection = Vector3.Zero; m_lastLinearVelocityVector = Vector3.Zero; - m_newVelocity = Vector3.Zero; - - VDetailLog("{0},MoveLinear,zeroed", Prim.LocalID); } - // m_newVelocity is velocity computed from linear motor in world coordinates + // convert requested object velocity to world-referenced vector + Quaternion rotq = m_prim.Orientation; + m_dir = m_lastLinearVelocityVector * rotq; - // Gravity and Buoyancy + // Add the various forces into m_dir which will be our new direction vector (velocity) + + // add Gravity and Buoyancy + // KF: So far I have found no good method to combine a script-requested + // .Z velocity and gravity. Therefore only 0g will used script-requested + // .Z velocity. >0g (m_VehicleBuoyancy < 1) will used modified gravity only. + Vector3 grav = Vector3.Zero; // There is some gravity, make a gravity force vector that is applied after object velocity. // m_VehicleBuoyancy: -1=2g; 0=1g; 1=0g; - Vector3 grav = Prim.PhysicsScene.DefaultGravity * (1f - m_VehicleBuoyancy); - - /* - * RA: Not sure why one would do this unless we are hoping external forces are doing gravity, ... + grav.Z = m_prim.Scene.DefaultGravity.Z * m_prim.Mass * (1f - m_VehicleBuoyancy); // Preserve the current Z velocity Vector3 vel_now = m_prim.Velocity; m_dir.Z = vel_now.Z; // Preserve the accumulated falling velocity - */ - Vector3 pos = Prim.ForcePosition; + Vector3 pos = m_prim.Position; + Vector3 posChange = pos; // Vector3 accel = new Vector3(-(m_dir.X - m_lastLinearVelocityVector.X / 0.1f), -(m_dir.Y - m_lastLinearVelocityVector.Y / 0.1f), m_dir.Z - m_lastLinearVelocityVector.Z / 0.1f); + double Zchange = Math.Abs(posChange.Z); + if (m_BlockingEndPoint != Vector3.Zero) + { + bool changed = false; + if (pos.X >= (m_BlockingEndPoint.X - (float)1)) + { + pos.X -= posChange.X + 1; + changed = true; + } + if (pos.Y >= (m_BlockingEndPoint.Y - (float)1)) + { + pos.Y -= posChange.Y + 1; + changed = true; + } + if (pos.Z >= (m_BlockingEndPoint.Z - (float)1)) + { + pos.Z -= posChange.Z + 1; + changed = true; + } + if (pos.X <= 0) + { + pos.X += posChange.X + 1; + changed = true; + } + if (pos.Y <= 0) + { + pos.Y += posChange.Y + 1; + changed = true; + } + if (changed) + { + m_prim.Position = pos; + DetailLog("{0},MoveLinear,blockingEndPoint,block={1},origPos={2},pos={3}", + m_prim.LocalID, m_BlockingEndPoint, posChange, pos); + } + } // If below the terrain, move us above the ground a little. - float terrainHeight = Prim.PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(pos); - // Taking the rotated size doesn't work here because m_prim.Size is the size of the root prim and not the linkset. - // Need to add a m_prim.LinkSet.Size similar to m_prim.LinkSet.Mass. - // Vector3 rotatedSize = m_prim.Size * m_prim.ForceOrientation; - // if (rotatedSize.Z < terrainHeight) - if (pos.Z < terrainHeight) + if (pos.Z < m_prim.Scene.GetTerrainHeightAtXYZ(pos)) { - pos.Z = terrainHeight + 2; - Prim.ForcePosition = pos; - VDetailLog("{0},MoveLinear,terrainHeight,terrainHeight={1},pos={2}", Prim.LocalID, terrainHeight, pos); + pos.Z = m_prim.Scene.GetTerrainHeightAtXYZ(pos) + 2; + m_prim.Position = pos; + DetailLog("{0},MoveLinear,terrainHeight,pos={1}", m_prim.LocalID, pos); } // Check if hovering - // m_VhoverEfficiency: 0=bouncy, 1=totally damped - // m_VhoverTimescale: time to achieve height - if ((m_flags & (VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT)) != 0) + if ((m_Hoverflags & (VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT)) != 0) { // We should hover, get the target height - if ((m_flags & VehicleFlag.HOVER_WATER_ONLY) != 0) + if ((m_Hoverflags & VehicleFlag.HOVER_WATER_ONLY) != 0) { - m_VhoverTargetHeight = Prim.PhysicsScene.GetWaterLevelAtXYZ(pos) + m_VhoverHeight; + m_VhoverTargetHeight = m_prim.Scene.GetWaterLevel() + m_VhoverHeight; } - if ((m_flags & VehicleFlag.HOVER_TERRAIN_ONLY) != 0) + if ((m_Hoverflags & VehicleFlag.HOVER_TERRAIN_ONLY) != 0) { - m_VhoverTargetHeight = terrainHeight + m_VhoverHeight; + m_VhoverTargetHeight = m_prim.Scene.GetTerrainHeightAtXY(pos.X, pos.Y) + m_VhoverHeight; } - if ((m_flags & VehicleFlag.HOVER_GLOBAL_HEIGHT) != 0) + if ((m_Hoverflags & VehicleFlag.HOVER_GLOBAL_HEIGHT) != 0) { m_VhoverTargetHeight = m_VhoverHeight; } - if ((m_flags & VehicleFlag.HOVER_UP_ONLY) != 0) + if ((m_Hoverflags & VehicleFlag.HOVER_UP_ONLY) != 0) { // If body is aready heigher, use its height as target height if (pos.Z > m_VhoverTargetHeight) m_VhoverTargetHeight = pos.Z; } - if ((m_flags & VehicleFlag.LOCK_HOVER_HEIGHT) != 0) + if ((m_Hoverflags & VehicleFlag.LOCK_HOVER_HEIGHT) != 0) { if ((pos.Z - m_VhoverTargetHeight) > .2 || (pos.Z - m_VhoverTargetHeight) < -.2) { - Prim.ForcePosition = pos; + m_prim.Position = pos; } } else { - float verticalError = pos.Z - m_VhoverTargetHeight; - // RA: where does the 50 come from? - float verticalCorrectionVelocity = pTimestep * ((verticalError * 50.0f) / m_VhoverTimescale); + float herr0 = pos.Z - m_VhoverTargetHeight; // Replace Vertical speed with correction figure if significant - if (Math.Abs(verticalError) > 0.01f) + if (Math.Abs(herr0) > 0.01f) { - m_newVelocity.Z += verticalCorrectionVelocity; + m_dir.Z = -((herr0 * pTimestep * 50.0f) / m_VhoverTimescale); //KF: m_VhoverEfficiency is not yet implemented } - else if (verticalError < -0.01) - { - m_newVelocity.Z -= verticalCorrectionVelocity; - } else { - m_newVelocity.Z = 0f; + m_dir.Z = 0f; } } - VDetailLog("{0},MoveLinear,hover,pos={1},dir={2},height={3},target={4}", Prim.LocalID, pos, m_newVelocity, m_VhoverHeight, m_VhoverTargetHeight); - } + DetailLog("{0},MoveLinear,hover,pos={1},dir={2},height={3},target={4}", m_prim.LocalID, pos, m_dir, m_VhoverHeight, m_VhoverTargetHeight); - Vector3 posChange = pos - m_lastPositionVector; - if (m_BlockingEndPoint != Vector3.Zero) - { - bool changed = false; - if (pos.X >= (m_BlockingEndPoint.X - (float)1)) - { - pos.X -= posChange.X + 1; - changed = true; - } - if (pos.Y >= (m_BlockingEndPoint.Y - (float)1)) - { - pos.Y -= posChange.Y + 1; - changed = true; - } - if (pos.Z >= (m_BlockingEndPoint.Z - (float)1)) - { - pos.Z -= posChange.Z + 1; - changed = true; - } - if (pos.X <= 0) - { - pos.X += posChange.X + 1; - changed = true; - } - if (pos.Y <= 0) - { - pos.Y += posChange.Y + 1; - changed = true; - } - if (changed) - { - Prim.ForcePosition = pos; - VDetailLog("{0},MoveLinear,blockingEndPoint,block={1},origPos={2},pos={3}", - Prim.LocalID, m_BlockingEndPoint, posChange, pos); - } +// m_VhoverEfficiency = 0f; // 0=boucy, 1=Crit.damped +// m_VhoverTimescale = 0f; // time to acheive height +// pTimestep is time since last frame,in secs } - // Limit absolute vertical change - float Zchange = Math.Abs(posChange.Z); if ((m_flags & (VehicleFlag.LIMIT_MOTOR_UP)) != 0) { + //Start Experimental Values if (Zchange > .3) + { grav.Z = (float)(grav.Z * 3); + } if (Zchange > .15) + { grav.Z = (float)(grav.Z * 2); + } if (Zchange > .75) + { grav.Z = (float)(grav.Z * 1.5); + } if (Zchange > .05) + { grav.Z = (float)(grav.Z * 1.25); + } if (Zchange > .025) + { grav.Z = (float)(grav.Z * 1.125); - float postemp = (pos.Z - terrainHeight); + } + float terraintemp = m_prim.Scene.GetTerrainHeightAtXYZ(pos); + float postemp = (pos.Z - terraintemp); if (postemp > 2.5f) + { grav.Z = (float)(grav.Z * 1.037125); - VDetailLog("{0},MoveLinear,limitMotorUp,grav={1}", Prim.LocalID, grav); + } + DetailLog("{0},MoveLinear,limitMotorUp,grav={1}", m_prim.LocalID, grav); + //End Experimental Values } - - // If not changing some axis, reduce out velocity if ((m_flags & (VehicleFlag.NO_X)) != 0) - m_newVelocity.X = 0; + { + m_dir.X = 0; + } if ((m_flags & (VehicleFlag.NO_Y)) != 0) - m_newVelocity.Y = 0; + { + m_dir.Y = 0; + } if ((m_flags & (VehicleFlag.NO_Z)) != 0) - m_newVelocity.Z = 0; + { + m_dir.Z = 0; + } + + m_lastPositionVector = m_prim.Position; // Apply velocity - Prim.ForceVelocity = m_newVelocity; - // Prim.AddForce(m_newVelocity * Prim.Linkset.LinksetMass, false); - Prim.AddForce(grav * Prim.Linkset.LinksetMass, false); + m_prim.Velocity = m_dir; + // apply gravity force + // Why is this set here? The physics engine already does gravity. + // m_prim.AddForce(grav, false); + // m_prim.Force = grav; - VDetailLog("{0},MoveLinear,done,lmDir={1},lmVel={2},newVel={3},grav={4}", - Prim.LocalID, m_linearMotorDirection, m_lastLinearVelocityVector, m_newVelocity, grav); + // Apply friction + Vector3 decayamount = Vector3.One / (m_linearFrictionTimescale / pTimestep); + m_lastLinearVelocityVector -= m_lastLinearVelocityVector * decayamount; + + DetailLog("{0},MoveLinear,done,pos={1},vel={2},force={3},decay={4}", + m_prim.LocalID, m_lastPositionVector, m_dir, grav, decayamount); } // end MoveLinear() - // ======================================================================= - // Apply the effect of the angular motor. private void MoveAngular(float pTimestep) { // m_angularMotorDirection // angular velocity requested by LSL motor @@ -759,223 +859,160 @@ namespace OpenSim.Region.Physics.BulletSPlugin // m_angularFrictionTimescale // body angular velocity decay rate // m_lastAngularVelocity // what was last applied to body - if (m_angularMotorDirection.LengthSquared() > 0.0001) - { - Vector3 origVel = m_angularMotorVelocity; - Vector3 origDir = m_angularMotorDirection; - - // new velocity += error / ( time to get there / step interval) - // requested speed - last motor speed - m_angularMotorVelocity += (m_angularMotorDirection - m_angularMotorVelocity) / (m_angularMotorTimescale / pTimestep); - // decay requested direction - m_angularMotorDirection *= (1.0f - (pTimestep * 1.0f/m_angularMotorDecayTimescale)); + // Get what the body is doing, this includes 'external' influences + Vector3 angularVelocity = m_prim.RotationalVelocity; - VDetailLog("{0},MoveAngular,angularMotorApply,angTScale={1},timeStep={2},origvel={3},origDir={4},vel={5}", - Prim.LocalID, m_angularMotorTimescale, pTimestep, origVel, origDir, m_angularMotorVelocity); + if (m_angularMotorApply > 0) + { + // Rather than snapping the angular motor velocity from the old value to + // a newly set velocity, this routine steps the value from the previous + // value (m_angularMotorVelocity) to the requested value (m_angularMotorDirection). + // There are m_angularMotorApply steps. + Vector3 origAngularVelocity = m_angularMotorVelocity; + // ramp up to new value + // current velocity += error / (time to get there / step interval) + // requested speed - last motor speed + m_angularMotorVelocity.X += (m_angularMotorDirection.X - m_angularMotorVelocity.X) / (m_angularMotorTimescale / pTimestep); + m_angularMotorVelocity.Y += (m_angularMotorDirection.Y - m_angularMotorVelocity.Y) / (m_angularMotorTimescale / pTimestep); + m_angularMotorVelocity.Z += (m_angularMotorDirection.Z - m_angularMotorVelocity.Z) / (m_angularMotorTimescale / pTimestep); + + DetailLog("{0},MoveAngular,angularMotorApply,apply={1},origvel={2},dir={3},vel={4}", + m_prim.LocalID,m_angularMotorApply,origAngularVelocity, m_angularMotorDirection, m_angularMotorVelocity); + + m_angularMotorApply--; // This is done so that if script request rate is less than phys frame rate the expected + // velocity may still be acheived. } else { - m_angularMotorVelocity = Vector3.Zero; - } - - #region Vertical attactor + // No motor recently applied, keep the body velocity + // and decay the velocity + m_angularMotorVelocity -= m_angularMotorVelocity / (m_angularMotorDecayTimescale / pTimestep); + } // end motor section + // Vertical attractor section Vector3 vertattr = Vector3.Zero; - Vector3 deflection = Vector3.Zero; - Vector3 banking = Vector3.Zero; - - if (m_verticalAttractionTimescale < 300 && m_lastAngularVelocity != Vector3.Zero) + if (m_verticalAttractionTimescale < 300) { - float VAservo = pTimestep * 0.2f / m_verticalAttractionTimescale; - if (Prim.Linkset.LinksetIsColliding) - VAservo = pTimestep * 0.05f / (m_verticalAttractionTimescale); - - VAservo *= (m_verticalAttractionEfficiency * m_verticalAttractionEfficiency); - - // Create a vector of the vehicle "up" in world coordinates - Vector3 verticalError = Vector3.UnitZ * Prim.ForceOrientation; - // verticalError.X and .Y are the World error amounts. They are 0 when there is no - // error (Vehicle Body is 'vertical'), and .Z will be 1. As the body leans to its - // side |.X| will increase to 1 and .Z fall to 0. As body inverts |.X| will fall - // and .Z will go // negative. Similar for tilt and |.Y|. .X and .Y must be - // modulated to prevent a stable inverted body. - - // Error is 0 (no error) to +/- 2 (max error) - if (verticalError.Z < 0.0f) + float VAservo = 0.2f / (m_verticalAttractionTimescale * pTimestep); + // get present body rotation + Quaternion rotq = m_prim.Orientation; + // make a vector pointing up + Vector3 verterr = Vector3.Zero; + verterr.Z = 1.0f; + // rotate it to Body Angle + verterr = verterr * rotq; + // verterr.X and .Y are the World error ammounts. They are 0 when there is no error (Vehicle Body is 'vertical'), and .Z will be 1. + // As the body leans to its side |.X| will increase to 1 and .Z fall to 0. As body inverts |.X| will fall and .Z will go + // negative. Similar for tilt and |.Y|. .X and .Y must be modulated to prevent a stable inverted body. + if (verterr.Z < 0.0f) { - verticalError.X = 2.0f - verticalError.X; - verticalError.Y = 2.0f - verticalError.Y; + verterr.X = 2.0f - verterr.X; + verterr.Y = 2.0f - verterr.Y; } + // Error is 0 (no error) to +/- 2 (max error) // scale it by VAservo - verticalError = verticalError * VAservo; + verterr = verterr * VAservo; - // As the body rotates around the X axis, then verticalError.Y increases; Rotated around Y - // then .X increases, so change Body angular velocity X based on Y, and Y based on X. - // Z is not changed. - vertattr.X = verticalError.Y; - vertattr.Y = - verticalError.X; + // As the body rotates around the X axis, then verterr.Y increases; Rotated around Y then .X increases, so + // Change Body angular velocity X based on Y, and Y based on X. Z is not changed. + vertattr.X = verterr.Y; + vertattr.Y = - verterr.X; vertattr.Z = 0f; // scaling appears better usingsquare-law - Vector3 angularVelocity = Prim.ForceRotationalVelocity; float bounce = 1.0f - (m_verticalAttractionEfficiency * m_verticalAttractionEfficiency); vertattr.X += bounce * angularVelocity.X; vertattr.Y += bounce * angularVelocity.Y; - VDetailLog("{0},MoveAngular,verticalAttraction,verticalError={1},bounce={2},vertattr={3}", - Prim.LocalID, verticalError, bounce, vertattr); - - } - #endregion // Vertical attactor - - #region Deflection - - //Forward is the prefered direction, but if the reference frame has changed, we need to take this into account as well - if (m_angularDeflectionEfficiency != 0) - { - Vector3 preferredAxisOfMotion = - new Vector3((pTimestep * 10 * (m_angularDeflectionEfficiency / m_angularDeflectionTimescale)), 0, 0); - preferredAxisOfMotion *= Quaternion.Add(Prim.ForceOrientation, m_referenceFrame); - - deflection = (preferredAxisOfMotion * (m_angularDeflectionEfficiency) / m_angularDeflectionTimescale) * pTimestep; - - VDetailLog("{0},MoveAngular,Deflection,perfAxis={1},deflection={2}", - Prim.LocalID, preferredAxisOfMotion, deflection); - } - - #endregion - - #region Banking + DetailLog("{0},MoveAngular,verticalAttraction,verterr={1},bounce={2},vertattr={3}", + m_prim.LocalID, verterr, bounce, vertattr); - if (m_bankingEfficiency != 0) - { - Vector3 dir = Vector3.One * Prim.ForceOrientation; - float mult = (m_bankingMix*m_bankingMix)*-1*(m_bankingMix < 0 ? -1 : 1); - //Changes which way it banks in and out of turns + } // else vertical attractor is off - //Use the square of the efficiency, as it looks much more how SL banking works - float effSquared = (m_bankingEfficiency*m_bankingEfficiency); - if (m_bankingEfficiency < 0) - effSquared *= -1; //Keep the negative! + // m_lastVertAttractor = vertattr; - float mix = Math.Abs(m_bankingMix); - if (m_angularMotorVelocity.X == 0) - { - /*if (!parent.Orientation.ApproxEquals(this.m_referenceFrame, 0.25f)) - { - Vector3 axisAngle; - float angle; - parent.Orientation.GetAxisAngle(out axisAngle, out angle); - Vector3 rotatedVel = parent.Velocity * parent.Orientation; - if ((rotatedVel.X < 0 && axisAngle.Y > 0) || (rotatedVel.X > 0 && axisAngle.Y < 0)) - m_angularMotorVelocity.X += (effSquared * (mult * mix)) * (1f) * 10; - else - m_angularMotorVelocity.X += (effSquared * (mult * mix)) * (-1f) * 10; - }*/ - } - else - banking.Z += (effSquared*(mult*mix))*(m_angularMotorVelocity.X) * 4; - if (!Prim.Linkset.LinksetIsColliding && Math.Abs(m_angularMotorVelocity.X) > mix) - //If they are colliding, we probably shouldn't shove the prim around... probably - { - float angVelZ = m_angularMotorVelocity.X*-1; - /*if(angVelZ > mix) - angVelZ = mix; - else if(angVelZ < -mix) - angVelZ = -mix;*/ - //This controls how fast and how far the banking occurs - Vector3 bankingRot = new Vector3(angVelZ*(effSquared*mult), 0, 0); - if (bankingRot.X > 3) - bankingRot.X = 3; - else if (bankingRot.X < -3) - bankingRot.X = -3; - bankingRot *= Prim.ForceOrientation; - banking += bankingRot; - } - m_angularMotorVelocity.X *= m_bankingEfficiency == 1 ? 0.0f : 1 - m_bankingEfficiency; - VDetailLog("{0},MoveAngular,Banking,bEff={1},angMotVel={2},banking={3}", - Prim.LocalID, m_bankingEfficiency, m_angularMotorVelocity, banking); - } - - #endregion + // Bank section tba - m_lastVertAttractor = vertattr; + // Deflection section tba // Sum velocities - m_lastAngularVelocity = m_angularMotorVelocity + vertattr + banking + deflection; - + m_lastAngularVelocity = m_angularMotorVelocity + vertattr; // + bank + deflection + if ((m_flags & (VehicleFlag.NO_DEFLECTION_UP)) != 0) { m_lastAngularVelocity.X = 0; m_lastAngularVelocity.Y = 0; - VDetailLog("{0},MoveAngular,noDeflectionUp,lastAngular={1}", Prim.LocalID, m_lastAngularVelocity); + DetailLog("{0},MoveAngular,noDeflectionUp,lastAngular={1}", m_prim.LocalID, m_lastAngularVelocity); } if (m_lastAngularVelocity.ApproxEquals(Vector3.Zero, 0.01f)) { m_lastAngularVelocity = Vector3.Zero; // Reduce small value to zero. - VDetailLog("{0},MoveAngular,zeroSmallValues,lastAngular={1}", Prim.LocalID, m_lastAngularVelocity); + DetailLog("{0},MoveAngular,zeroSmallValues,lastAngular={1}", m_prim.LocalID, m_lastAngularVelocity); } - // Apply to the body - // The above calculates the absolute angular velocity needed - // Prim.ForceRotationalVelocity = m_lastAngularVelocity; - - // Apply a force to overcome current angular velocity - Vector3 applyAngularForce = (m_lastAngularVelocity - Prim.ForceRotationalVelocity) * Prim.Linkset.LinksetMass; - // Vector3 applyAngularForce = (m_lastAngularVelocity - Prim.ForceRotationalVelocity); - // Prim.AddAngularForce(applyAngularForce, false); - Prim.ApplyTorqueImpulse(applyAngularForce, false); + // apply friction + Vector3 decayamount = Vector3.One / (m_angularFrictionTimescale / pTimestep); + m_lastAngularVelocity -= m_lastAngularVelocity * decayamount; - // Apply friction for next time - Vector3 decayamount = (Vector3.One / m_angularFrictionTimescale) * pTimestep; - m_lastAngularVelocity *= Vector3.One - decayamount; + // Apply to the body + m_prim.RotationalVelocity = m_lastAngularVelocity; - VDetailLog("{0},MoveAngular,done,applyAForce={1},decay={2},lastAngular={3}", - Prim.LocalID, applyAngularForce, decayamount, m_lastAngularVelocity); + DetailLog("{0},MoveAngular,done,decay={1},lastAngular={2}", m_prim.LocalID, decayamount, m_lastAngularVelocity); } //end MoveAngular internal void LimitRotation(float timestep) { - Quaternion rotq = Prim.ForceOrientation; + Quaternion rotq = m_prim.Orientation; Quaternion m_rot = rotq; + bool changed = false; if (m_RollreferenceFrame != Quaternion.Identity) { if (rotq.X >= m_RollreferenceFrame.X) { m_rot.X = rotq.X - (m_RollreferenceFrame.X / 2); + changed = true; } if (rotq.Y >= m_RollreferenceFrame.Y) { m_rot.Y = rotq.Y - (m_RollreferenceFrame.Y / 2); + changed = true; } if (rotq.X <= -m_RollreferenceFrame.X) { m_rot.X = rotq.X + (m_RollreferenceFrame.X / 2); + changed = true; } if (rotq.Y <= -m_RollreferenceFrame.Y) { m_rot.Y = rotq.Y + (m_RollreferenceFrame.Y / 2); + changed = true; } + changed = true; } if ((m_flags & VehicleFlag.LOCK_ROTATION) != 0) { m_rot.X = 0; m_rot.Y = 0; + changed = true; } - if (rotq != m_rot) + if ((m_flags & VehicleFlag.LOCK_ROTATION) != 0) { - Prim.ForceOrientation = m_rot; - VDetailLog("{0},LimitRotation,done,orig={1},new={2}", Prim.LocalID, rotq, m_rot); + m_rot.X = 0; + m_rot.Y = 0; + changed = true; } + if (changed) + m_prim.Orientation = m_rot; + DetailLog("{0},LimitRotation,done,changed={1},orig={2},new={3}", m_prim.LocalID, changed, rotq, m_rot); } // Invoke the detailed logger and output something if it's enabled. - private void VDetailLog(string msg, params Object[] args) + private void DetailLog(string msg, params Object[] args) { - if (Prim.PhysicsScene.VehicleLoggingEnabled) - Prim.PhysicsScene.DetailLog(msg, args); + if (m_prim.Scene.VehicleLoggingEnabled) + m_prim.Scene.PhysicsLogging.Write(msg, args); } } } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSHingeConstraint.cs b/OpenSim/Region/Physics/BulletSPlugin/BSHingeConstraint.cs new file mode 100755 index 0000000..d68048b --- /dev/null +++ b/OpenSim/Region/Physics/BulletSPlugin/BSHingeConstraint.cs @@ -0,0 +1,55 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyrightD + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +using System; +using System.Collections.Generic; +using System.Text; +using OpenMetaverse; + +namespace OpenSim.Region.Physics.BulletSPlugin +{ + +class BSHingeConstraint : BSConstraint +{ + public BSHingeConstraint(BulletSim world, BulletBody obj1, BulletBody obj2, + Vector3 pivotInA, Vector3 pivotInB, + Vector3 axisInA, Vector3 axisInB, + bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies) + { + m_world = world; + m_body1 = obj1; + m_body2 = obj2; + m_constraint = new BulletConstraint( + BulletSimAPI.CreateHingeConstraint2(m_world.Ptr, m_body1.Ptr, m_body2.Ptr, + pivotInA, pivotInB, + axisInA, axisInB, + useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies)); + m_enabled = true; + } + +} + +} diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs index 3a92f93..087b9bb 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs @@ -32,78 +32,35 @@ using OMV = OpenMetaverse; namespace OpenSim.Region.Physics.BulletSPlugin { -public abstract class BSLinkset +public class BSLinkset { - // private static string LogHeader = "[BULLETSIM LINKSET]"; + private static string LogHeader = "[BULLETSIM LINKSET]"; - public enum LinksetImplementation - { - Constraint = 0, // linkset tied together with constraints - Compound = 1, // linkset tied together as a compound object - Manual = 2 // linkset tied together manually (code moves all the pieces) - } - // Create the correct type of linkset for this child - public static BSLinkset Factory(BSScene physScene, BSPhysObject parent) - { - BSLinkset ret = null; - - switch ((int)physScene.Params.linksetImplementation) - { - case (int)LinksetImplementation.Compound: - ret = new BSLinksetCompound(physScene, parent); - break; - case (int)LinksetImplementation.Manual: - // ret = new BSLinksetManual(physScene, parent); - break; - default: - ret = new BSLinksetConstraints(physScene, parent); - break; - } - return ret; - } - - public BSPhysObject LinksetRoot { get; protected set; } + private BSPrim m_linksetRoot; + public BSPrim LinksetRoot { get { return m_linksetRoot; } } - public BSScene PhysicsScene { get; private set; } + private BSScene m_physicsScene; + public BSScene PhysicsScene { get { return m_physicsScene; } } - static int m_nextLinksetID = 1; - public int LinksetID { get; private set; } - - // The children under the root in this linkset. - protected HashSet m_children; + // The children under the root in this linkset + private List m_children; // We lock the diddling of linkset classes to prevent any badness. // This locks the modification of the instances of this class. Changes // to the physical representation is done via the tainting mechenism. - protected object m_linksetActivityLock = new Object(); - - // Some linksets have a preferred physical shape. - // Returns SHAPE_UNKNOWN if there is no preference. Causes the correct shape to be selected. - public virtual ShapeData.PhysicsShapeType PreferredPhysicalShape(BSPhysObject requestor) - { - return ShapeData.PhysicsShapeType.SHAPE_UNKNOWN; - } + private object m_linksetActivityLock = new Object(); - // Linksets move around the children so the linkset might need to compute the child position - public virtual OMV.Vector3 Position(BSPhysObject member) - { return member.RawPosition; } - public virtual OMV.Quaternion Orientation(BSPhysObject member) - { return member.RawOrientation; } - // TODO: does this need to be done for Velocity and RotationalVelocityy? - // We keep the prim's mass in the linkset structure since it could be dependent on other prims - protected float m_mass; - public float LinksetMass - { - get + private float m_mass; + public float LinksetMass + { + get { m_mass = ComputeLinksetMass(); return m_mass; } } - public virtual bool LinksetIsColliding { get { return false; } } - public OMV.Vector3 CenterOfMass { get { return ComputeLinksetCenterOfMass(); } @@ -114,30 +71,23 @@ public abstract class BSLinkset get { return ComputeLinksetGeometricCenter(); } } - protected void Initialize(BSScene scene, BSPhysObject parent) + public BSLinkset(BSScene scene, BSPrim parent) { // A simple linkset of one (no children) - LinksetID = m_nextLinksetID++; - // We create LOTS of linksets. - if (m_nextLinksetID <= 0) - m_nextLinksetID = 1; - PhysicsScene = scene; - LinksetRoot = parent; - m_children = new HashSet(); - m_mass = parent.RawMass; + m_physicsScene = scene; + m_linksetRoot = parent; + m_children = new List(); + m_mass = parent.MassRaw; } // Link to a linkset where the child knows the parent. // Parent changing should not happen so do some sanity checking. // We return the parent's linkset so the child can track its membership. - // Called at runtime. - public BSLinkset AddMeToLinkset(BSPhysObject child) + public BSLinkset AddMeToLinkset(BSPrim child) { lock (m_linksetActivityLock) { - // Don't add the root to its own linkset - if (!IsRoot(child)) - AddChildToLinkset(child); + AddChildToLinkset(child); } return this; } @@ -145,27 +95,36 @@ public abstract class BSLinkset // Remove a child from a linkset. // Returns a new linkset for the child which is a linkset of one (just the // orphened child). - // Called at runtime. - public BSLinkset RemoveMeFromLinkset(BSPhysObject child) + public BSLinkset RemoveMeFromLinkset(BSPrim child) { lock (m_linksetActivityLock) { if (IsRoot(child)) { - // Cannot remove the root from a linkset. - return this; + // if root of linkset, take the linkset apart + while (m_children.Count > 0) + { + // Note that we don't do a foreach because the remove routine + // takes it out of the list. + RemoveChildFromOtherLinkset(m_children[0]); + } + m_children.Clear(); // just to make sure + } + else + { + // Just removing a child from an existing linkset + RemoveChildFromLinkset(child); } - RemoveChildFromLinkset(child); } // The child is down to a linkset of just itself - return BSLinkset.Factory(PhysicsScene, child); + return new BSLinkset(PhysicsScene, child); } // Return 'true' if the passed object is the root object of this linkset - public bool IsRoot(BSPhysObject requestor) + public bool IsRoot(BSPrim requestor) { - return (requestor.LocalID == LinksetRoot.LocalID); + return (requestor.LocalID == m_linksetRoot.LocalID); } public int NumberOfChildren { get { return m_children.Count; } } @@ -174,14 +133,12 @@ public abstract class BSLinkset public bool HasAnyChildren { get { return (m_children.Count > 0); } } // Return 'true' if this child is in this linkset - public bool HasChild(BSPhysObject child) + public bool HasChild(BSPrim child) { bool ret = false; lock (m_linksetActivityLock) { - ret = m_children.Contains(child); - /* Safer version but the above should work - foreach (BSPhysObject bp in m_children) + foreach (BSPrim bp in m_children) { if (child.LocalID == bp.LocalID) { @@ -189,132 +146,274 @@ public abstract class BSLinkset break; } } - */ } return ret; } - // Perform an action on each member of the linkset including root prim. - // Depends on the action on whether this should be done at taint time. - public delegate bool ForEachMemberAction(BSPhysObject obj); - public virtual bool ForEachMember(ForEachMemberAction action) + private float ComputeLinksetMass() { - bool ret = false; + float mass = m_linksetRoot.MassRaw; + foreach (BSPrim bp in m_children) + { + mass += bp.MassRaw; + } + return mass; + } + + private OMV.Vector3 ComputeLinksetCenterOfMass() + { + OMV.Vector3 com = m_linksetRoot.Position * m_linksetRoot.MassRaw; + float totalMass = m_linksetRoot.MassRaw; + lock (m_linksetActivityLock) { - action(LinksetRoot); - foreach (BSPhysObject po in m_children) + foreach (BSPrim bp in m_children) { - if (action(po)) - break; + com += bp.Position * bp.MassRaw; + totalMass += bp.MassRaw; } + if (totalMass != 0f) + com /= totalMass; } - return ret; + + return com; } - // I am the root of a linkset and a new child is being added - // Called while LinkActivity is locked. - protected abstract void AddChildToLinkset(BSPhysObject child); + private OMV.Vector3 ComputeLinksetGeometricCenter() + { + OMV.Vector3 com = m_linksetRoot.Position; - // I am the root of a linkset and one of my children is being removed. - // Safe to call even if the child is not really in my linkset. - protected abstract void RemoveChildFromLinkset(BSPhysObject child); + lock (m_linksetActivityLock) + { + foreach (BSPrim bp in m_children) + { + com += bp.Position * bp.MassRaw; + } + com /= (m_children.Count + 1); + } + + return com; + } // When physical properties are changed the linkset needs to recalculate // its internal properties. - // May be called at runtime or taint-time. - public abstract void Refresh(BSPhysObject requestor); - - // The object is going dynamic (physical). Do any setup necessary - // for a dynamic linkset. - // Only the state of the passed object can be modified. The rest of the linkset - // has not yet been fully constructed. - // Return 'true' if any properties updated on the passed object. - // Called at taint-time! - public abstract bool MakeDynamic(BSPhysObject child); - - // The object is going static (non-physical). Do any setup necessary - // for a static linkset. - // Return 'true' if any properties updated on the passed object. - // Called at taint-time! - public abstract bool MakeStatic(BSPhysObject child); - - // Called when a parameter update comes from the physics engine for any object - // of the linkset is received. - // Called at taint-time!! - public abstract void UpdateProperties(BSPhysObject physObject); - - // Routine used when rebuilding the body of the root of the linkset - // Destroy all the constraints have have been made to root. - // This is called when the root body is changing. - // Returns 'true' of something was actually removed and would need restoring - // Called at taint-time!! - public abstract bool RemoveBodyDependencies(BSPrim child); - - // Companion to RemoveBodyDependencies(). If RemoveBodyDependencies() returns 'true', - // this routine will restore the removed constraints. - // Called at taint-time!! - public abstract void RestoreBodyDependencies(BSPrim child); - - // ================================================================ - protected virtual float ComputeLinksetMass() + public void Refresh(BSPrim requestor) { - float mass = LinksetRoot.RawMass; - if (HasAnyChildren) + // If there are no children, there aren't any constraints to recompute + if (!HasAnyChildren) + return; + + // Only the root does the recomputation + if (IsRoot(requestor)) + { + PhysicsScene.TaintedObject("BSLinkSet.Refresh", delegate() + { + RecomputeLinksetConstraintVariables(); + }); + } + } + + // Call each of the constraints that make up this linkset and recompute the + // various transforms and variables. Used when objects are added or removed + // from a linkset to make sure the constraints know about the new mass and + // geometry. + // Must only be called at taint time!! + private bool RecomputeLinksetConstraintVariables() + { + float linksetMass = LinksetMass; + lock (m_linksetActivityLock) { - lock (m_linksetActivityLock) + foreach (BSPrim child in m_children) { - foreach (BSPhysObject bp in m_children) + BSConstraint constrain; + if (m_physicsScene.Constraints.TryGetConstraint(LinksetRoot.Body, child.Body, out constrain)) + { + // DetailLog("{0},BSLinkset.RecomputeLinksetConstraintVariables,taint,child={1},mass={2},A={3},B={4}", + // LinksetRoot.LocalID, child.LocalID, linksetMass, constrain.Body1.ID, constrain.Body2.ID); + constrain.RecomputeConstraintVariables(linksetMass); + } + else { - mass += bp.RawMass; + // Non-fatal error that can happen when children are being added to the linkset but + // their constraints have not been created yet. + // Caused by the fact that m_children is built at run time but building constraints + // happens at taint time. + // m_physicsScene.Logger.ErrorFormat("[BULLETSIM LINKSET] RecomputeLinksetConstraintVariables: constraint not found for root={0}, child={1}", + // m_linksetRoot.Body.ID, child.Body.ID); } } } - return mass; + return false; } - protected virtual OMV.Vector3 ComputeLinksetCenterOfMass() + // I am the root of a linkset and a new child is being added + // Called while LinkActivity is locked. + private void AddChildToLinkset(BSPrim child) { - OMV.Vector3 com; - lock (m_linksetActivityLock) + if (!HasChild(child)) { - com = LinksetRoot.Position * LinksetRoot.RawMass; - float totalMass = LinksetRoot.RawMass; + m_children.Add(child); - foreach (BSPhysObject bp in m_children) + BSPrim rootx = LinksetRoot; // capture the root as of now + BSPrim childx = child; + m_physicsScene.TaintedObject("AddChildToLinkset", delegate() { - com += bp.Position * bp.RawMass; - totalMass += bp.RawMass; - } - if (totalMass != 0f) - com /= totalMass; + // DebugLog("{0}: AddChildToLinkset: adding child {1} to {2}", LogHeader, child.LocalID, m_linksetRoot.LocalID); + // DetailLog("{0},AddChildToLinkset,taint,child={1}", m_linksetRoot.LocalID, child.LocalID); + PhysicallyLinkAChildToRoot(rootx, childx); // build the physical binding between me and the child + }); } + return; + } - return com; + // Forcefully removing a child from a linkset. + // This is not being called by the child so we have to make sure the child doesn't think + // it's still connected to the linkset. + // Normal OpenSimulator operation will never do this because other SceneObjectPart information + // has to be updated also (like pointer to prim's parent). + private void RemoveChildFromOtherLinkset(BSPrim pchild) + { + pchild.Linkset = new BSLinkset(m_physicsScene, pchild); + RemoveChildFromLinkset(pchild); } - protected virtual OMV.Vector3 ComputeLinksetGeometricCenter() + // I am the root of a linkset and one of my children is being removed. + // Safe to call even if the child is not really in my linkset. + private void RemoveChildFromLinkset(BSPrim child) { - OMV.Vector3 com; - lock (m_linksetActivityLock) + if (m_children.Remove(child)) { - com = LinksetRoot.Position; - - foreach (BSPhysObject bp in m_children) + BSPrim rootx = LinksetRoot; // capture the root as of now + BSPrim childx = child; + m_physicsScene.TaintedObject("RemoveChildFromLinkset", delegate() { - com += bp.Position * bp.RawMass; - } - com /= (m_children.Count + 1); + // DebugLog("{0}: RemoveChildFromLinkset: Removing constraint to {1}", LogHeader, child.LocalID); + // DetailLog("{0},RemoveChildFromLinkset,taint,child={1}", m_linksetRoot.LocalID, child.LocalID); + + PhysicallyUnlinkAChildFromRoot(rootx, childx); + }); + + RecomputeLinksetConstraintVariables(); + } + else + { + // This will happen if we remove the root of the linkset first. Non-fatal occurance. + // PhysicsScene.Logger.ErrorFormat("{0}: Asked to remove child from linkset that was not in linkset", LogHeader); } + return; + } - return com; + // Create a constraint between me (root of linkset) and the passed prim (the child). + // Called at taint time! + private void PhysicallyLinkAChildToRoot(BSPrim rootPrim, BSPrim childPrim) + { + // Zero motion for children so they don't interpolate + childPrim.ZeroMotion(); + + // Relative position normalized to the root prim + // Essentually a vector pointing from center of rootPrim to center of childPrim + OMV.Vector3 childRelativePosition = childPrim.Position - rootPrim.Position; + + // real world coordinate of midpoint between the two objects + OMV.Vector3 midPoint = rootPrim.Position + (childRelativePosition / 2); + + // create a constraint that allows no freedom of movement between the two objects + // http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818 + // DebugLog("{0}: CreateLinkset: Adding a constraint between root prim {1} and child prim {2}", LogHeader, LocalID, childPrim.LocalID); + DetailLog("{0},PhysicallyLinkAChildToRoot,taint,root={1},child={2},rLoc={3},cLoc={4},midLoc={5}", + rootPrim.LocalID, rootPrim.LocalID, childPrim.LocalID, rootPrim.Position, childPrim.Position, midPoint); + BS6DofConstraint constrain = new BS6DofConstraint( + m_physicsScene.World, rootPrim.Body, childPrim.Body, + midPoint, + true, + true + ); + /* NOTE: attempt to build constraint with full frame computation, etc. + * Using the midpoint is easier since it lets the Bullet code use the transforms + * of the objects. + * Code left here as an example. + // ================================================================================== + // relative position normalized to the root prim + OMV.Quaternion invThisOrientation = OMV.Quaternion.Inverse(rootPrim.Orientation); + OMV.Vector3 childRelativePosition = (childPrim.Position - rootPrim.Position) * invThisOrientation; + + // relative rotation of the child to the parent + OMV.Quaternion childRelativeRotation = invThisOrientation * childPrim.Orientation; + OMV.Quaternion inverseChildRelativeRotation = OMV.Quaternion.Inverse(childRelativeRotation); + + // create a constraint that allows no freedom of movement between the two objects + // http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818 + // DebugLog("{0}: CreateLinkset: Adding a constraint between root prim {1} and child prim {2}", LogHeader, LocalID, childPrim.LocalID); + DetailLog("{0},PhysicallyLinkAChildToRoot,taint,root={1},child={2}", rootPrim.LocalID, rootPrim.LocalID, childPrim.LocalID); + BS6DofConstraint constrain = new BS6DofConstraint( + PhysicsScene.World, rootPrim.Body, childPrim.Body, + OMV.Vector3.Zero, + OMV.Quaternion.Inverse(rootPrim.Orientation), + OMV.Vector3.Zero, + OMV.Quaternion.Inverse(childPrim.Orientation), + // A point half way between the parent and child + // childRelativePosition/2, + // childRelativeRotation, + // childRelativePosition/2, + // inverseChildRelativeRotation, + true, + true + ); + // ================================================================================== + */ + + m_physicsScene.Constraints.AddConstraint(constrain); + + // zero linear and angular limits makes the objects unable to move in relation to each other + constrain.SetLinearLimits(OMV.Vector3.Zero, OMV.Vector3.Zero); + constrain.SetAngularLimits(OMV.Vector3.Zero, OMV.Vector3.Zero); + + // tweek the constraint to increase stability + constrain.UseFrameOffset(PhysicsScene.BoolNumeric(PhysicsScene.Params.linkConstraintUseFrameOffset)); + constrain.TranslationalLimitMotor(PhysicsScene.BoolNumeric(PhysicsScene.Params.linkConstraintEnableTransMotor), + PhysicsScene.Params.linkConstraintTransMotorMaxVel, + PhysicsScene.Params.linkConstraintTransMotorMaxForce); + constrain.SetCFMAndERP(PhysicsScene.Params.linkConstraintCFM, PhysicsScene.Params.linkConstraintERP); + + RecomputeLinksetConstraintVariables(); + } + + // Remove linkage between myself and a particular child + // Called at taint time! + private void PhysicallyUnlinkAChildFromRoot(BSPrim rootPrim, BSPrim childPrim) + { + // DebugLog("{0}: PhysicallyUnlinkAChildFromRoot: RemoveConstraint between root prim {1} and child prim {2}", + // LogHeader, rootPrim.LocalID, childPrim.LocalID); + DetailLog("{0},PhysicallyUnlinkAChildFromRoot,taint,root={1},child={2}", rootPrim.LocalID, rootPrim.LocalID, childPrim.LocalID); + + // Find the constraint for this link and get rid of it from the overall collection and from my list + m_physicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.Body, childPrim.Body); + + // Make the child refresh its location + BulletSimAPI.PushUpdate2(childPrim.Body.Ptr); + } + + // Remove linkage between myself and any possible children I might have + // Called at taint time! + private void PhysicallyUnlinkAllChildrenFromRoot(BSPrim rootPrim) + { + // DebugLog("{0}: PhysicallyUnlinkAllChildren:", LogHeader); + DetailLog("{0},PhysicallyUnlinkAllChildren,taint", rootPrim.LocalID); + + m_physicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.Body); + } + + // Invoke the detailed logger and output something if it's enabled. + private void DebugLog(string msg, params Object[] args) + { + if (m_physicsScene.ShouldDebugLog) + m_physicsScene.Logger.DebugFormat(msg, args); } // Invoke the detailed logger and output something if it's enabled. - protected void DetailLog(string msg, params Object[] args) + private void DetailLog(string msg, params Object[] args) { - if (PhysicsScene.PhysicsLogging.Enabled) - PhysicsScene.DetailLog(msg, args); + m_physicsScene.PhysicsLogging.Write(msg, args); } } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs deleted file mode 100755 index 12c6d7a..0000000 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs +++ /dev/null @@ -1,273 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyrightD - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -using System; -using System.Collections.Generic; -using System.Text; - -using OMV = OpenMetaverse; - -namespace OpenSim.Region.Physics.BulletSPlugin -{ -public sealed class BSLinksetCompound : BSLinkset -{ - private static string LogHeader = "[BULLETSIM LINKSET COMPOUND]"; - - public BSLinksetCompound(BSScene scene, BSPhysObject parent) - { - base.Initialize(scene, parent); - } - - // For compound implimented linksets, if there are children, use compound shape for the root. - public override ShapeData.PhysicsShapeType PreferredPhysicalShape(BSPhysObject requestor) - { - ShapeData.PhysicsShapeType ret = ShapeData.PhysicsShapeType.SHAPE_UNKNOWN; - if (IsRoot(requestor) && HasAnyChildren) - { - ret = ShapeData.PhysicsShapeType.SHAPE_COMPOUND; - } - // DetailLog("{0},BSLinksetCompound.PreferredPhysicalShape,call,shape={1}", LinksetRoot.LocalID, ret); - return ret; - } - - // When physical properties are changed the linkset needs to recalculate - // its internal properties. - // This is queued in the 'post taint' queue so the - // refresh will happen once after all the other taints are applied. - public override void Refresh(BSPhysObject requestor) - { - // External request for Refresh (from BSPrim) is not necessary - // InternalRefresh(requestor); - } - - private void InternalRefresh(BSPhysObject requestor) - { - DetailLog("{0},BSLinksetCompound.Refresh,schedulingRefresh,requestor={1}", LinksetRoot.LocalID, requestor.LocalID); - // Queue to happen after all the other taint processing - PhysicsScene.PostTaintObject("BSLinksetCompound.Refresh", requestor.LocalID, delegate() - { - if (IsRoot(requestor) && HasAnyChildren) - RecomputeLinksetCompound(); - }); - } - - // The object is going dynamic (physical). Do any setup necessary - // for a dynamic linkset. - // Only the state of the passed object can be modified. The rest of the linkset - // has not yet been fully constructed. - // Return 'true' if any properties updated on the passed object. - // Called at taint-time! - public override bool MakeDynamic(BSPhysObject child) - { - bool ret = false; - DetailLog("{0},BSLinksetCompound.MakeDynamic,call,IsRoot={1}", child.LocalID, IsRoot(child)); - if (!IsRoot(child)) - { - // Physical children are removed from the world as the shape ofthe root compound - // shape takes over. - BulletSimAPI.AddToCollisionFlags2(child.PhysBody.ptr, CollisionFlags.CF_NO_CONTACT_RESPONSE); - BulletSimAPI.ForceActivationState2(child.PhysBody.ptr, ActivationState.DISABLE_SIMULATION); - ret = true; - } - return ret; - } - - // The object is going static (non-physical). Do any setup necessary for a static linkset. - // Return 'true' if any properties updated on the passed object. - // This doesn't normally happen -- OpenSim removes the objects from the physical - // world if it is a static linkset. - // Called at taint-time! - public override bool MakeStatic(BSPhysObject child) - { - bool ret = false; - DetailLog("{0},BSLinksetCompound.MakeStatic,call,IsRoot={1}", child.LocalID, IsRoot(child)); - if (!IsRoot(child)) - { - // The non-physical children can come back to life. - BulletSimAPI.RemoveFromCollisionFlags2(child.PhysBody.ptr, CollisionFlags.CF_NO_CONTACT_RESPONSE); - // Don't force activation so setting of DISABLE_SIMULATION can stay. - BulletSimAPI.Activate2(child.PhysBody.ptr, false); - ret = true; - } - return ret; - } - - // Called at taint-time!! - public override void UpdateProperties(BSPhysObject updated) - { - // Nothing to do for constraints on property updates - } - - // The children move around in relationship to the root. - // Just grab the current values of wherever it is right now. - public override OMV.Vector3 Position(BSPhysObject member) - { - return BulletSimAPI.GetPosition2(member.PhysBody.ptr); - } - - public override OMV.Quaternion Orientation(BSPhysObject member) - { - return BulletSimAPI.GetOrientation2(member.PhysBody.ptr); - } - - // Routine called when rebuilding the body of some member of the linkset. - // Since we don't keep in world relationships, do nothing unless it's a child changing. - // Returns 'true' of something was actually removed and would need restoring - // Called at taint-time!! - public override bool RemoveBodyDependencies(BSPrim child) - { - bool ret = false; - - DetailLog("{0},BSLinksetCompound.RemoveBodyDependencies,refreshIfChild,rID={1},rBody={2},isRoot={3}", - child.LocalID, LinksetRoot.LocalID, LinksetRoot.PhysBody.ptr.ToString("X"), IsRoot(child)); - - if (!IsRoot(child)) - { - // Cause the current shape to be freed and the new one to be built. - InternalRefresh(LinksetRoot); - ret = true; - } - - return ret; - } - - // Companion to RemoveBodyDependencies(). If RemoveBodyDependencies() returns 'true', - // this routine will restore the removed constraints. - // Called at taint-time!! - public override void RestoreBodyDependencies(BSPrim child) - { - // The Refresh operation queued by RemoveBodyDependencies() will build any missing constraints. - } - - // ================================================================ - - // Add a new child to the linkset. - // Called while LinkActivity is locked. - protected override void AddChildToLinkset(BSPhysObject child) - { - if (!HasChild(child)) - { - m_children.Add(child); - - DetailLog("{0},BSLinksetCompound.AddChildToLinkset,call,child={1}", LinksetRoot.LocalID, child.LocalID); - - // Cause constraints and assorted properties to be recomputed before the next simulation step. - InternalRefresh(LinksetRoot); - } - return; - } - - // Remove the specified child from the linkset. - // Safe to call even if the child is not really in my linkset. - protected override void RemoveChildFromLinkset(BSPhysObject child) - { - if (m_children.Remove(child)) - { - DetailLog("{0},BSLinksetCompound.RemoveChildFromLinkset,call,rID={1},rBody={2},cID={3},cBody={4}", - child.LocalID, - LinksetRoot.LocalID, LinksetRoot.PhysBody.ptr.ToString("X"), - child.LocalID, child.PhysBody.ptr.ToString("X")); - - // Cause the child's body to be rebuilt and thus restored to normal operation - child.ForceBodyShapeRebuild(false); - - if (!HasAnyChildren) - { - // The linkset is now empty. The root needs rebuilding. - LinksetRoot.ForceBodyShapeRebuild(false); - } - else - { - // Schedule a rebuild of the linkset before the next simulation tick. - InternalRefresh(LinksetRoot); - } - } - return; - } - - // Called before the simulation step to make sure the compound based linkset - // is all initialized. - // Constraint linksets are rebuilt every time. - // Note that this works for rebuilding just the root after a linkset is taken apart. - // Called at taint time!! - private void RecomputeLinksetCompound() - { - // Cause the root shape to be rebuilt as a compound object with just the root in it - LinksetRoot.ForceBodyShapeRebuild(true); - - DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,start,rBody={1},rShape={2},numChildren={3}", - LinksetRoot.LocalID, LinksetRoot.PhysBody, LinksetRoot.PhysShape, NumberOfChildren); - - // Add a shape for each of the other children in the linkset - ForEachMember(delegate(BSPhysObject cPrim) - { - if (!IsRoot(cPrim)) - { - // Each child position and rotation is given relative to the root. - OMV.Quaternion invRootOrientation = OMV.Quaternion.Inverse(LinksetRoot.RawOrientation); - OMV.Vector3 displacementPos = (cPrim.RawPosition - LinksetRoot.RawPosition) * invRootOrientation; - OMV.Quaternion displacementRot = cPrim.RawOrientation * invRootOrientation; - - DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,addMemberToShape,mID={1},mShape={2},dispPos={3},dispRot={4}", - LinksetRoot.LocalID, cPrim.LocalID, cPrim.PhysShape, displacementPos, displacementRot); - - if (cPrim.PhysShape.isNativeShape) - { - // Native shapes are not shared so we need to create a new one. - // A mesh or hull is created because scale is not available on a native shape. - // (TODO: Bullet does have a btScaledCollisionShape. Can that be used?) - BulletShape saveShape = cPrim.PhysShape; - cPrim.PhysShape.ptr = IntPtr.Zero; // Don't let the create free the child's shape - PhysicsScene.Shapes.CreateGeomMeshOrHull(cPrim, null); - BulletShape newShape = cPrim.PhysShape; - cPrim.PhysShape = saveShape; - BulletSimAPI.AddChildShapeToCompoundShape2(LinksetRoot.PhysShape.ptr, newShape.ptr, displacementPos, displacementRot); - } - else - { - // For the shared shapes (meshes and hulls), just use the shape in the child. - if (PhysicsScene.Shapes.ReferenceShape(cPrim.PhysShape)) - { - PhysicsScene.Logger.ErrorFormat("{0} Rebuilt sharable shape when building linkset! Region={1}, primID={2}, shape={3}", - LogHeader, PhysicsScene.RegionName, cPrim.LocalID, cPrim.PhysShape); - } - BulletSimAPI.AddChildShapeToCompoundShape2(LinksetRoot.PhysShape.ptr, cPrim.PhysShape.ptr, displacementPos, displacementRot); - } - } - return false; // 'false' says to move onto the next child in the list - }); - - // With all of the linkset packed into the root prim, it has the mass of everyone. - float linksetMass = LinksetMass; - LinksetRoot.UpdatePhysicalMassProperties(linksetMass); - - // DEBUG: see of inter-linkset collisions are causing problems for constraint linksets. - // BulletSimAPI.SetCollisionFilterMask2(LinksetRoot.BSBody.ptr, - // (uint)CollisionFilterGroups.LinksetFilter, (uint)CollisionFilterGroups.LinksetMask); - - } -} -} \ No newline at end of file diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs deleted file mode 100755 index d2387fb..0000000 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs +++ /dev/null @@ -1,327 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyrightD - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -using System; -using System.Collections.Generic; -using System.Text; - -using OMV = OpenMetaverse; - -namespace OpenSim.Region.Physics.BulletSPlugin -{ -public sealed class BSLinksetConstraints : BSLinkset -{ - // private static string LogHeader = "[BULLETSIM LINKSET CONSTRAINTS]"; - - public BSLinksetConstraints(BSScene scene, BSPhysObject parent) - { - base.Initialize(scene, parent); - } - - // When physical properties are changed the linkset needs to recalculate - // its internal properties. - // This is queued in the 'post taint' queue so the - // refresh will happen once after all the other taints are applied. - public override void Refresh(BSPhysObject requestor) - { - // Queue to happen after all the other taint processing - PhysicsScene.PostTaintObject("BSLinksetContraints.Refresh", requestor.LocalID, delegate() - { - if (HasAnyChildren && IsRoot(requestor)) - RecomputeLinksetConstraints(); - }); - } - - // The object is going dynamic (physical). Do any setup necessary - // for a dynamic linkset. - // Only the state of the passed object can be modified. The rest of the linkset - // has not yet been fully constructed. - // Return 'true' if any properties updated on the passed object. - // Called at taint-time! - public override bool MakeDynamic(BSPhysObject child) - { - // What is done for each object in BSPrim is what we want. - return false; - } - - // The object is going static (non-physical). Do any setup necessary for a static linkset. - // Return 'true' if any properties updated on the passed object. - // This doesn't normally happen -- OpenSim removes the objects from the physical - // world if it is a static linkset. - // Called at taint-time! - public override bool MakeStatic(BSPhysObject child) - { - // What is done for each object in BSPrim is what we want. - return false; - } - - // Called at taint-time!! - public override void UpdateProperties(BSPhysObject updated) - { - // Nothing to do for constraints on property updates - } - - // The children of the linkset are moved around by the constraints. - // Just grab the current values of wherever it is right now. - public override OMV.Vector3 Position(BSPhysObject member) - { - return BulletSimAPI.GetPosition2(member.PhysBody.ptr); - } - - public override OMV.Quaternion Orientation(BSPhysObject member) - { - return BulletSimAPI.GetOrientation2(member.PhysBody.ptr); - } - - // Routine called when rebuilding the body of some member of the linkset. - // Destroy all the constraints have have been made to root and set - // up to rebuild the constraints before the next simulation step. - // Returns 'true' of something was actually removed and would need restoring - // Called at taint-time!! - public override bool RemoveBodyDependencies(BSPrim child) - { - bool ret = false; - - DetailLog("{0},BSLinksetConstraint.RemoveBodyDependencies,removeChildrenForRoot,rID={1},rBody={2}", - child.LocalID, LinksetRoot.LocalID, LinksetRoot.PhysBody.ptr.ToString("X")); - - lock (m_linksetActivityLock) - { - // Just undo all the constraints for this linkset. Rebuild at the end of the step. - ret = PhysicallyUnlinkAllChildrenFromRoot(LinksetRoot); - // Cause the constraints, et al to be rebuilt before the next simulation step. - Refresh(LinksetRoot); - } - return ret; - } - - // Companion to RemoveBodyDependencies(). If RemoveBodyDependencies() returns 'true', - // this routine will restore the removed constraints. - // Called at taint-time!! - public override void RestoreBodyDependencies(BSPrim child) - { - // The Refresh operation queued by RemoveBodyDependencies() will build any missing constraints. - } - - // ================================================================ - - // Add a new child to the linkset. - // Called while LinkActivity is locked. - protected override void AddChildToLinkset(BSPhysObject child) - { - if (!HasChild(child)) - { - m_children.Add(child); - - DetailLog("{0},BSLinksetConstraints.AddChildToLinkset,call,child={1}", LinksetRoot.LocalID, child.LocalID); - - // Cause constraints and assorted properties to be recomputed before the next simulation step. - Refresh(LinksetRoot); - } - return; - } - - // Remove the specified child from the linkset. - // Safe to call even if the child is not really in my linkset. - protected override void RemoveChildFromLinkset(BSPhysObject child) - { - if (m_children.Remove(child)) - { - BSPhysObject rootx = LinksetRoot; // capture the root and body as of now - BSPhysObject childx = child; - - DetailLog("{0},BSLinksetConstraints.RemoveChildFromLinkset,call,rID={1},rBody={2},cID={3},cBody={4}", - childx.LocalID, - rootx.LocalID, rootx.PhysBody.ptr.ToString("X"), - childx.LocalID, childx.PhysBody.ptr.ToString("X")); - - PhysicsScene.TaintedObject("BSLinksetConstraints.RemoveChildFromLinkset", delegate() - { - PhysicallyUnlinkAChildFromRoot(rootx, childx); - }); - // See that the linkset parameters are recomputed at the end of the taint time. - Refresh(LinksetRoot); - } - else - { - // Non-fatal occurance. - // PhysicsScene.Logger.ErrorFormat("{0}: Asked to remove child from linkset that was not in linkset", LogHeader); - } - return; - } - - // Create a constraint between me (root of linkset) and the passed prim (the child). - // Called at taint time! - private void PhysicallyLinkAChildToRoot(BSPhysObject rootPrim, BSPhysObject childPrim) - { - // Don't build the constraint when asked. Put it off until just before the simulation step. - Refresh(rootPrim); - } - - private BSConstraint BuildConstraint(BSPhysObject rootPrim, BSPhysObject childPrim) - { - // Zero motion for children so they don't interpolate - childPrim.ZeroMotion(); - - // Relative position normalized to the root prim - // Essentually a vector pointing from center of rootPrim to center of childPrim - OMV.Vector3 childRelativePosition = childPrim.Position - rootPrim.Position; - - // real world coordinate of midpoint between the two objects - OMV.Vector3 midPoint = rootPrim.Position + (childRelativePosition / 2); - - DetailLog("{0},BSLinksetConstraint.BuildConstraint,taint,root={1},rBody={2},child={3},cBody={4},rLoc={5},cLoc={6},midLoc={7}", - rootPrim.LocalID, - rootPrim.LocalID, rootPrim.PhysBody.ptr.ToString("X"), - childPrim.LocalID, childPrim.PhysBody.ptr.ToString("X"), - rootPrim.Position, childPrim.Position, midPoint); - - // create a constraint that allows no freedom of movement between the two objects - // http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818 - - BSConstraint6Dof constrain = new BSConstraint6Dof( - PhysicsScene.World, rootPrim.PhysBody, childPrim.PhysBody, midPoint, true, true ); - // PhysicsScene.World, childPrim.BSBody, rootPrim.BSBody, midPoint, true, true ); - - /* NOTE: below is an attempt to build constraint with full frame computation, etc. - * Using the midpoint is easier since it lets the Bullet code manipulate the transforms - * of the objects. - * Code left for future programmers. - // ================================================================================== - // relative position normalized to the root prim - OMV.Quaternion invThisOrientation = OMV.Quaternion.Inverse(rootPrim.Orientation); - OMV.Vector3 childRelativePosition = (childPrim.Position - rootPrim.Position) * invThisOrientation; - - // relative rotation of the child to the parent - OMV.Quaternion childRelativeRotation = invThisOrientation * childPrim.Orientation; - OMV.Quaternion inverseChildRelativeRotation = OMV.Quaternion.Inverse(childRelativeRotation); - - DetailLog("{0},BSLinksetConstraint.PhysicallyLinkAChildToRoot,taint,root={1},child={2}", rootPrim.LocalID, rootPrim.LocalID, childPrim.LocalID); - BS6DofConstraint constrain = new BS6DofConstraint( - PhysicsScene.World, rootPrim.Body, childPrim.Body, - OMV.Vector3.Zero, - OMV.Quaternion.Inverse(rootPrim.Orientation), - OMV.Vector3.Zero, - OMV.Quaternion.Inverse(childPrim.Orientation), - true, - true - ); - // ================================================================================== - */ - - PhysicsScene.Constraints.AddConstraint(constrain); - - // zero linear and angular limits makes the objects unable to move in relation to each other - constrain.SetLinearLimits(OMV.Vector3.Zero, OMV.Vector3.Zero); - constrain.SetAngularLimits(OMV.Vector3.Zero, OMV.Vector3.Zero); - - // tweek the constraint to increase stability - constrain.UseFrameOffset(PhysicsScene.BoolNumeric(PhysicsScene.Params.linkConstraintUseFrameOffset)); - constrain.TranslationalLimitMotor(PhysicsScene.BoolNumeric(PhysicsScene.Params.linkConstraintEnableTransMotor), - PhysicsScene.Params.linkConstraintTransMotorMaxVel, - PhysicsScene.Params.linkConstraintTransMotorMaxForce); - constrain.SetCFMAndERP(PhysicsScene.Params.linkConstraintCFM, PhysicsScene.Params.linkConstraintERP); - if (PhysicsScene.Params.linkConstraintSolverIterations != 0f) - { - constrain.SetSolverIterations(PhysicsScene.Params.linkConstraintSolverIterations); - } - return constrain; - } - - // Remove linkage between the linkset root and a particular child - // The root and child bodies are passed in because we need to remove the constraint between - // the bodies that were present at unlink time. - // Called at taint time! - private bool PhysicallyUnlinkAChildFromRoot(BSPhysObject rootPrim, BSPhysObject childPrim) - { - bool ret = false; - DetailLog("{0},BSLinksetConstraint.PhysicallyUnlinkAChildFromRoot,taint,root={1},rBody={2},child={3},cBody={4}", - rootPrim.LocalID, - rootPrim.LocalID, rootPrim.PhysBody.ptr.ToString("X"), - childPrim.LocalID, childPrim.PhysBody.ptr.ToString("X")); - - // Find the constraint for this link and get rid of it from the overall collection and from my list - if (PhysicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.PhysBody, childPrim.PhysBody)) - { - // Make the child refresh its location - BulletSimAPI.PushUpdate2(childPrim.PhysBody.ptr); - ret = true; - } - - return ret; - } - - // Remove linkage between myself and any possible children I might have. - // Returns 'true' of any constraints were destroyed. - // Called at taint time! - private bool PhysicallyUnlinkAllChildrenFromRoot(BSPhysObject rootPrim) - { - DetailLog("{0},BSLinksetConstraint.PhysicallyUnlinkAllChildren,taint", rootPrim.LocalID); - - return PhysicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.PhysBody); - } - - // Call each of the constraints that make up this linkset and recompute the - // various transforms and variables. Create constraints of not created yet. - // Called before the simulation step to make sure the constraint based linkset - // is all initialized. - // Called at taint time!! - private void RecomputeLinksetConstraints() - { - float linksetMass = LinksetMass; - LinksetRoot.UpdatePhysicalMassProperties(linksetMass); - - // DEBUG: see of inter-linkset collisions are causing problems - // BulletSimAPI.SetCollisionFilterMask2(LinksetRoot.BSBody.ptr, - // (uint)CollisionFilterGroups.LinksetFilter, (uint)CollisionFilterGroups.LinksetMask); - DetailLog("{0},BSLinksetConstraint.RecomputeLinksetConstraints,set,rBody={1},linksetMass={2}", - LinksetRoot.LocalID, LinksetRoot.PhysBody.ptr.ToString("X"), linksetMass); - - foreach (BSPhysObject child in m_children) - { - // A child in the linkset physically shows the mass of the whole linkset. - // This allows Bullet to apply enough force on the child to move the whole linkset. - // (Also do the mass stuff before recomputing the constraint so mass is not zero.) - child.UpdatePhysicalMassProperties(linksetMass); - - BSConstraint constrain; - if (!PhysicsScene.Constraints.TryGetConstraint(LinksetRoot.PhysBody, child.PhysBody, out constrain)) - { - // If constraint doesn't exist yet, create it. - constrain = BuildConstraint(LinksetRoot, child); - } - constrain.RecomputeConstraintVariables(linksetMass); - - // DEBUG: see of inter-linkset collisions are causing problems - // BulletSimAPI.SetCollisionFilterMask2(child.BSBody.ptr, - // (uint)CollisionFilterGroups.LinksetFilter, (uint)CollisionFilterGroups.LinksetMask); - - // BulletSimAPI.DumpConstraint2(PhysicsScene.World.ptr, constrain.Constraint.ptr); // DEBUG DEBUG - } - - } -} -} diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs deleted file mode 100755 index 7127aaf..0000000 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs +++ /dev/null @@ -1,248 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyrightD - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -using System; -using System.Collections.Generic; -using System.Text; - -using OMV = OpenMetaverse; -using OpenSim.Framework; -using OpenSim.Region.Physics.Manager; - -namespace OpenSim.Region.Physics.BulletSPlugin -{ -// Class to wrap all objects. -// The rest of BulletSim doesn't need to keep checking for avatars or prims -// unless the difference is significant. -public abstract class BSPhysObject : PhysicsActor -{ - protected void BaseInitialize(BSScene parentScene, uint localID, string name, string typeName) - { - PhysicsScene = parentScene; - LocalID = localID; - PhysObjectName = name; - TypeName = typeName; - - Linkset = BSLinkset.Factory(PhysicsScene, this); - LastAssetBuildFailed = false; - - CollisionCollection = new CollisionEventUpdate(); - SubscribedEventsMs = 0; - CollidingStep = 0; - CollidingGroundStep = 0; - } - - public BSScene PhysicsScene { get; protected set; } - // public override uint LocalID { get; set; } // Use the LocalID definition in PhysicsActor - public string PhysObjectName { get; protected set; } - public string TypeName { get; protected set; } - - public BSLinkset Linkset { get; set; } - - // Return the object mass without calculating it or having side effects - public abstract float RawMass { get; } - // Set the raw mass but also update physical mass properties (inertia, ...) - public abstract void UpdatePhysicalMassProperties(float mass); - - // Reference to the physical body (btCollisionObject) of this object - public BulletBody PhysBody; - // Reference to the physical shape (btCollisionShape) of this object - public BulletShape PhysShape; - - // 'true' if the mesh's underlying asset failed to build. - // This will keep us from looping after the first time the build failed. - public bool LastAssetBuildFailed { get; set; } - - // The objects base shape information. Null if not a prim type shape. - public PrimitiveBaseShape BaseShape { get; protected set; } - // Some types of objects have preferred physical representations. - // Returns SHAPE_UNKNOWN if there is no preference. - public virtual ShapeData.PhysicsShapeType PreferredPhysicalShape - { - get { return ShapeData.PhysicsShapeType.SHAPE_UNKNOWN; } - } - - // When the physical properties are updated, an EntityProperty holds the update values. - // Keep the current and last EntityProperties to enable computation of differences - // between the current update and the previous values. - public EntityProperties CurrentEntityProperties { get; set; } - public EntityProperties LastEntityProperties { get; set; } - - public abstract OMV.Vector3 Scale { get; set; } - public abstract bool IsSolid { get; } - public abstract bool IsStatic { get; } - - // Stop all physical motion. - public abstract void ZeroMotion(); - - // Step the vehicle simulation for this object. A NOOP if the vehicle was not configured. - public virtual void StepVehicle(float timeStep) { } - - // Update the physical location and motion of the object. Called with data from Bullet. - public abstract void UpdateProperties(EntityProperties entprop); - - // Tell the object to clean up. - public abstract void Destroy(); - - public abstract OMV.Vector3 RawPosition { get; set; } - public abstract OMV.Vector3 ForcePosition { get; set; } - - public abstract OMV.Quaternion RawOrientation { get; set; } - public abstract OMV.Quaternion ForceOrientation { get; set; } - - public abstract OMV.Vector3 ForceVelocity { get; set; } - - public abstract OMV.Vector3 ForceRotationalVelocity { get; set; } - - public abstract float ForceBuoyancy { get; set; } - - public virtual bool ForceBodyShapeRebuild(bool inTaintTime) { return false; } - - #region Collisions - - // Requested number of milliseconds between collision events. Zero means disabled. - protected int SubscribedEventsMs { get; set; } - // Given subscription, the time that a collision may be passed up - protected int NextCollisionOkTime { get; set; } - // The simulation step that last had a collision - protected long CollidingStep { get; set; } - // The simulation step that last had a collision with the ground - protected long CollidingGroundStep { get; set; } - // The collision flags we think are set in Bullet - protected CollisionFlags CurrentCollisionFlags { get; set; } - - // The collisions that have been collected this tick - protected CollisionEventUpdate CollisionCollection; - - // The simulation step is telling this object about a collision. - // Return 'true' if a collision was processed and should be sent up. - // Called at taint time from within the Step() function - public virtual bool Collide(uint collidingWith, BSPhysObject collidee, - OMV.Vector3 contactPoint, OMV.Vector3 contactNormal, float pentrationDepth) - { - bool ret = false; - - // The following lines make IsColliding() and IsCollidingGround() work - CollidingStep = PhysicsScene.SimulationStep; - if (collidingWith <= PhysicsScene.TerrainManager.HighestTerrainID) - { - CollidingGroundStep = PhysicsScene.SimulationStep; - } - - // prims in the same linkset cannot collide with each other - if (collidee != null && (this.Linkset.LinksetID == collidee.Linkset.LinksetID)) - { - return ret; - } - - // if someone has subscribed for collision events.... - if (SubscribedEvents()) { - CollisionCollection.AddCollider(collidingWith, new ContactPoint(contactPoint, contactNormal, pentrationDepth)); - DetailLog("{0},{1}.Collison.AddCollider,call,with={2},point={3},normal={4},depth={5}", - LocalID, TypeName, collidingWith, contactPoint, contactNormal, pentrationDepth); - - ret = true; - } - return ret; - } - - // Send the collected collisions into the simulator. - // Called at taint time from within the Step() function thus no locking problems - // with CollisionCollection and ObjectsWithNoMoreCollisions. - // Return 'true' if there were some actual collisions passed up - public virtual bool SendCollisions() - { - bool ret = true; - // If the 'no collision' call, force it to happen right now so quick collision_end - bool force = CollisionCollection.Count == 0; - - // throttle the collisions to the number of milliseconds specified in the subscription - if (force || (PhysicsScene.SimulationNowTime >= NextCollisionOkTime)) - { - NextCollisionOkTime = PhysicsScene.SimulationNowTime + SubscribedEventsMs; - - // We are called if we previously had collisions. If there are no collisions - // this time, send up one last empty event so OpenSim can sense collision end. - if (CollisionCollection.Count == 0) - { - // If I have no collisions this time, remove me from the list of objects with collisions. - ret = false; - } - - // DetailLog("{0},{1}.SendCollisionUpdate,call,numCollisions={2}", LocalID, TypeName, CollisionCollection.Count); - base.SendCollisionUpdate(CollisionCollection); - - // The collisionCollection structure is passed around in the simulator. - // Make sure we don't have a handle to that one and that a new one is used for next time. - CollisionCollection = new CollisionEventUpdate(); - } - return ret; - } - - // Subscribe for collision events. - // Parameter is the millisecond rate the caller wishes collision events to occur. - public override void SubscribeEvents(int ms) { - // DetailLog("{0},{1}.SubscribeEvents,subscribing,ms={2}", LocalID, TypeName, ms); - SubscribedEventsMs = ms; - if (ms > 0) - { - // make sure first collision happens - NextCollisionOkTime = Util.EnvironmentTickCountSubtract(SubscribedEventsMs); - - PhysicsScene.TaintedObject(TypeName+".SubscribeEvents", delegate() - { - CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(PhysBody.ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); - }); - } - else - { - // Subscribing for zero or less is the same as unsubscribing - UnSubscribeEvents(); - } - } - public override void UnSubscribeEvents() { - // DetailLog("{0},{1}.UnSubscribeEvents,unsubscribing", LocalID, TypeName); - SubscribedEventsMs = 0; - PhysicsScene.TaintedObject(TypeName+".UnSubscribeEvents", delegate() - { - CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(PhysBody.ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); - }); - } - // Return 'true' if the simulator wants collision events - public override bool SubscribedEvents() { - return (SubscribedEventsMs > 0); - } - - #endregion // Collisions - - // High performance detailed logging routine used by the physical objects. - protected void DetailLog(string msg, params Object[] args) - { - if (PhysicsScene.PhysicsLogging.Enabled) - PhysicsScene.DetailLog(msg, args); - } -} -} diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPlugin.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPlugin.cs index 20f5180..0f027b8 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPlugin.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPlugin.cs @@ -33,7 +33,7 @@ using OpenMetaverse; namespace OpenSim.Region.Physics.BulletSPlugin { /// - /// Entry for a port of Bullet (http://bulletphysics.org/) to OpenSim. + /// Entry for a port of Bullet (http://bulletphysics.org/) to OpenSim. /// This module interfaces to an unmanaged C++ library which makes the /// actual calls into the Bullet physics engine. /// The unmanaged library is found in opensim-libs::trunk/unmanaged/BulletSim/. @@ -62,7 +62,7 @@ public class BSPlugin : IPhysicsPlugin if (Util.IsWindows()) Util.LoadArchSpecificWindowsDll("BulletSim.dll"); // If not Windows, loading is performed by the - // Mono loader as specified in + // Mono loader as specified in // "bin/Physics/OpenSim.Region.Physics.BulletSPlugin.dll.config". _mScene = new BSScene(sceneIdentifier); diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index aaa0d93..9c20004 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs @@ -24,9 +24,6 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ - -// Uncomment this it enable code to do all shape an body memory management -// in the C# code. using System; using System.Reflection; using System.Collections.Generic; @@ -39,18 +36,32 @@ using OpenSim.Region.Physics.ConvexDecompositionDotNet; namespace OpenSim.Region.Physics.BulletSPlugin { - [Serializable] -public sealed class BSPrim : BSPhysObject +public sealed class BSPrim : PhysicsActor { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private static readonly string LogHeader = "[BULLETS PRIM]"; - // _size is what the user passed. Scale is what we pass to the physics engine with the mesh. - // Often Scale is unity because the meshmerizer will apply _size when creating the mesh. + private void DebugLog(string mm, params Object[] xx) { if (_scene.ShouldDebugLog) m_log.DebugFormat(mm, xx); } + + private IMesh _mesh; + private PrimitiveBaseShape _pbs; + private ShapeData.PhysicsShapeType _shapeType; + private ulong _meshKey; + private ulong _hullKey; + private List _hulls; + + private BSScene _scene; + public BSScene Scene { get { return _scene; } } + private String _avName; + private uint _localID = 0; + + // _size is what the user passed. _scale is what we pass to the physics engine with the mesh. + // Often _scale is unity because the meshmerizer will apply _size when creating the mesh. private OMV.Vector3 _size; // the multiplier for each mesh dimension as passed by the user - // private OMV.Vector3 _scale; // the multiplier for each mesh dimension for the mesh as created by the meshmerizer + private OMV.Vector3 _scale; // the multiplier for each mesh dimension for the mesh as created by the meshmerizer + private bool _stopped; private bool _grabbed; private bool _isSelected; private bool _isVolumeDetect; @@ -78,6 +89,25 @@ public sealed class BSPrim : BSPhysObject private bool _kinematic; private float _buoyancy; + // Membership in a linkset is controlled by this class. + private BSLinkset _linkset; + public BSLinkset Linkset + { + get { return _linkset; } + set { _linkset = value; } + } + + private int _subscribedEventsMs = 0; + private int _nextCollisionOkTime = 0; + long _collidingStep; + long _collidingGroundStep; + + private BulletBody m_body; + public BulletBody Body { + get { return m_body; } + set { m_body = value; } + } + private BSDynamics _vehicle; private OMV.Vector3 _PIDTarget; @@ -92,112 +122,108 @@ public sealed class BSPrim : BSPhysObject OMV.Quaternion rotation, PrimitiveBaseShape pbs, bool pisPhysical) { // m_log.DebugFormat("{0}: BSPrim creation of {1}, id={2}", LogHeader, primName, localID); - base.BaseInitialize(parent_scene, localID, primName, "BSPrim"); - _physicsActorType = (int)ActorTypes.Prim; + _localID = localID; + _avName = primName; + _scene = parent_scene; _position = pos; _size = size; - Scale = new OMV.Vector3(1f, 1f, 1f); // the scale will be set by CreateGeom depending on object type + _scale = new OMV.Vector3(1f, 1f, 1f); // the scale will be set by CreateGeom depending on object type _orientation = rotation; _buoyancy = 1f; _velocity = OMV.Vector3.Zero; _rotationalVelocity = OMV.Vector3.Zero; - BaseShape = pbs; + _hullKey = 0; + _meshKey = 0; + _pbs = pbs; _isPhysical = pisPhysical; _isVolumeDetect = false; - _friction = PhysicsScene.Params.defaultFriction; // TODO: compute based on object material - _density = PhysicsScene.Params.defaultDensity; // TODO: compute based on object material - _restitution = PhysicsScene.Params.defaultRestitution; - _vehicle = new BSDynamics(PhysicsScene, this); // add vehicleness + _subscribedEventsMs = 0; + _friction = _scene.Params.defaultFriction; // TODO: compute based on object material + _density = _scene.Params.defaultDensity; // TODO: compute based on object material + _restitution = _scene.Params.defaultRestitution; + _linkset = new BSLinkset(_scene, this); // a linkset of one + _vehicle = new BSDynamics(this); // add vehicleness _mass = CalculateMass(); - - // No body or shape yet - PhysBody = new BulletBody(LocalID, IntPtr.Zero); - PhysShape = new BulletShape(IntPtr.Zero); - - DetailLog("{0},BSPrim.constructor,call", LocalID); // do the actual object creation at taint time - PhysicsScene.TaintedObject("BSPrim.create", delegate() + DetailLog("{0},BSPrim.constructor,call", LocalID); + _scene.TaintedObject("BSPrim.create", delegate() { - CreateGeomAndObject(true); + RecreateGeomAndObject(); - CurrentCollisionFlags = BulletSimAPI.GetCollisionFlags2(PhysBody.ptr); + // Get the pointer to the physical body for this object. + // At the moment, we're still letting BulletSim manage the creation and destruction + // of the object. Someday we'll move that into the C# code. + m_body = new BulletBody(LocalID, BulletSimAPI.GetBodyHandle2(_scene.World.Ptr, LocalID)); }); } // called when this prim is being destroyed and we should free all the resources - public override void Destroy() + public void Destroy() { // m_log.DebugFormat("{0}: Destroy, id={1}", LogHeader, LocalID); // Undo any links between me and any other object - BSPhysObject parentBefore = Linkset.LinksetRoot; - int childrenBefore = Linkset.NumberOfChildren; + BSPrim parentBefore = _linkset.LinksetRoot; + int childrenBefore = _linkset.NumberOfChildren; - Linkset = Linkset.RemoveMeFromLinkset(this); + _linkset = _linkset.RemoveMeFromLinkset(this); DetailLog("{0},BSPrim.Destroy,call,parentBefore={1},childrenBefore={2},parentAfter={3},childrenAfter={4}", - LocalID, parentBefore.LocalID, childrenBefore, Linkset.LinksetRoot.LocalID, Linkset.NumberOfChildren); + LocalID, parentBefore.LocalID, childrenBefore, _linkset.LinksetRoot.LocalID, _linkset.NumberOfChildren); // Undo any vehicle properties this.VehicleType = (int)Vehicle.TYPE_NONE; - PhysicsScene.TaintedObject("BSPrim.destroy", delegate() + _scene.TaintedObject("BSPrim.destroy", delegate() { DetailLog("{0},BSPrim.Destroy,taint,", LocalID); - // If there are physical body and shape, release my use of same. - PhysicsScene.Shapes.DereferenceBody(PhysBody, true, null); - PhysicsScene.Shapes.DereferenceShape(PhysShape, true, null); + // everything in the C# world will get garbage collected. Tell the C++ world to free stuff. + BulletSimAPI.DestroyObject(_scene.WorldID, LocalID); }); } - - // No one uses this property. - public override bool Stopped { - get { return false; } + + public override bool Stopped { + get { return _stopped; } } - public override OMV.Vector3 Size { - get { return _size; } + public override OMV.Vector3 Size { + get { return _size; } set { _size = value; - ForceBodyShapeRebuild(false); - } + _scene.TaintedObject("BSPrim.setSize", delegate() + { + _mass = CalculateMass(); // changing size changes the mass + BulletSimAPI.SetObjectScaleMass(_scene.WorldID, _localID, _scale, (IsPhysical ? _mass : 0f), IsPhysical); + // DetailLog("{0}: BSPrim.setSize: size={1}, mass={2}, physical={3}", LocalID, _size, _mass, IsPhysical); + RecreateGeomAndObject(); + }); + } } - // Scale is what we set in the physics engine. It is different than 'size' in that - // 'size' can be encorporated into the mesh. In that case, the scale is <1,1,1>. - public override OMV.Vector3 Scale { get; set; } - - public override PrimitiveBaseShape Shape { + public override PrimitiveBaseShape Shape { set { - BaseShape = value; - ForceBodyShapeRebuild(false); - } + _pbs = value; + _scene.TaintedObject("BSPrim.setShape", delegate() + { + _mass = CalculateMass(); // changing the shape changes the mass + RecreateGeomAndObject(); + }); + } } - // Whatever the linkset wants is what I want. - public override ShapeData.PhysicsShapeType PreferredPhysicalShape - { get { return Linkset.PreferredPhysicalShape(this); } } - - public override bool ForceBodyShapeRebuild(bool inTaintTime) - { - LastAssetBuildFailed = false; - PhysicsScene.TaintedObject(inTaintTime, "BSPrim.ForceBodyShapeRebuild", delegate() - { - _mass = CalculateMass(); // changing the shape changes the mass - CreateGeomAndObject(true); - }); - return true; + public override uint LocalID { + set { _localID = value; } + get { return _localID; } } - public override bool Grabbed { - set { _grabbed = value; - } + public override bool Grabbed { + set { _grabbed = value; + } } - public override bool Selected { + public override bool Selected { set { _isSelected = value; - PhysicsScene.TaintedObject("BSPrim.setSelected", delegate() + _scene.TaintedObject("BSPrim.setSelected", delegate() { - DetailLog("{0},BSPrim.selected,taint,selected={1}", LocalID, _isSelected); - SetObjectDynamic(false); + SetObjectDynamic(); }); - } + } } public override void CrossingFailure() { return; } @@ -206,255 +232,158 @@ public sealed class BSPrim : BSPhysObject BSPrim parent = obj as BSPrim; if (parent != null) { - BSPhysObject parentBefore = Linkset.LinksetRoot; - int childrenBefore = Linkset.NumberOfChildren; + DebugLog("{0}: link {1}/{2} to {3}", LogHeader, _avName, _localID, parent.LocalID); + BSPrim parentBefore = _linkset.LinksetRoot; + int childrenBefore = _linkset.NumberOfChildren; - Linkset = parent.Linkset.AddMeToLinkset(this); + _linkset = parent.Linkset.AddMeToLinkset(this); - DetailLog("{0},BSPrim.link,call,parentBefore={1}, childrenBefore=={2}, parentAfter={3}, childrenAfter={4}", - LocalID, parentBefore.LocalID, childrenBefore, Linkset.LinksetRoot.LocalID, Linkset.NumberOfChildren); + DetailLog("{0},BSPrim.link,call,parentBefore={1}, childrenBefore=={2}, parentAfter={3}, childrenAfter={4}", + LocalID, parentBefore.LocalID, childrenBefore, _linkset.LinksetRoot.LocalID, _linkset.NumberOfChildren); } - return; + return; } // delink me from my linkset public override void delink() { // TODO: decide if this parent checking needs to happen at taint time // Race condition here: if link() and delink() in same simulation tick, the delink will not happen + DebugLog("{0}: delink {1}/{2}. Parent={3}", LogHeader, _avName, _localID, + _linkset.LinksetRoot._avName+"/"+_linkset.LinksetRoot.LocalID.ToString()); - BSPhysObject parentBefore = Linkset.LinksetRoot; - int childrenBefore = Linkset.NumberOfChildren; + BSPrim parentBefore = _linkset.LinksetRoot; + int childrenBefore = _linkset.NumberOfChildren; + + _linkset = _linkset.RemoveMeFromLinkset(this); - Linkset = Linkset.RemoveMeFromLinkset(this); - - DetailLog("{0},BSPrim.delink,parentBefore={1},childrenBefore={2},parentAfter={3},childrenAfter={4}, ", - LocalID, parentBefore.LocalID, childrenBefore, Linkset.LinksetRoot.LocalID, Linkset.NumberOfChildren); - return; + DetailLog("{0},BSPrim.delink,parentBefore={1},childrenBefore={2},parentAfter={3},childrenAfter={4}, ", + LocalID, parentBefore.LocalID, childrenBefore, _linkset.LinksetRoot.LocalID, _linkset.NumberOfChildren); + return; } // Set motion values to zero. // Do it to the properties so the values get set in the physics engine. // Push the setting of the values to the viewer. // Called at taint time! - public override void ZeroMotion() + public void ZeroMotion() { _velocity = OMV.Vector3.Zero; _acceleration = OMV.Vector3.Zero; _rotationalVelocity = OMV.Vector3.Zero; - // Zero some other properties in the physics engine - BulletSimAPI.ClearAllForces2(PhysBody.ptr); + // Zero some other properties directly into the physics engine + BulletSimAPI.SetVelocity2(Body.Ptr, OMV.Vector3.Zero); + BulletSimAPI.SetAngularVelocity2(Body.Ptr, OMV.Vector3.Zero); + BulletSimAPI.SetInterpolation2(Body.Ptr, OMV.Vector3.Zero, OMV.Vector3.Zero); + BulletSimAPI.ClearForces2(Body.Ptr); } public override void LockAngularMotion(OMV.Vector3 axis) - { - DetailLog("{0},BSPrim.LockAngularMotion,call,axis={1}", LocalID, axis); + { + // DetailLog("{0},BSPrim.LockAngularMotion,call,axis={1}", LocalID, axis); return; } - public override OMV.Vector3 RawPosition - { - get { return _position; } - set { _position = value; } - } - public override OMV.Vector3 Position { - get { - // child prims move around based on their parent. Need to get the latest location - if (!Linkset.IsRoot(this)) - _position = Linkset.Position(this); + public override OMV.Vector3 Position { + get { + if (!_linkset.IsRoot(this)) + // child prims move around based on their parent. Need to get the latest location + _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID); // don't do the GetObjectPosition for root elements because this function is called a zillion times - // _position = BulletSimAPI.GetObjectPosition2(PhysicsScene.World.ptr, BSBody.ptr); - return _position; - } + // _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID); + return _position; + } set { - // If you must push the position into the physics engine, use ForcePosition. - if (_position == value) - { - return; - } _position = value; // TODO: what does it mean to set the position of a child prim?? Rebuild the constraint? - PositionSanityCheck(); - PhysicsScene.TaintedObject("BSPrim.setPosition", delegate() + _scene.TaintedObject("BSPrim.setPosition", delegate() { // DetailLog("{0},BSPrim.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation); - BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation); - ActivateIfPhysical(false); - }); - } - } - public override OMV.Vector3 ForcePosition { - get { - _position = BulletSimAPI.GetPosition2(PhysBody.ptr); - return _position; - } - set { - _position = value; - PositionSanityCheck(); - BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation); - ActivateIfPhysical(false); - } - } - - // Check that the current position is sane and, if not, modify the position to make it so. - // Check for being below terrain and being out of bounds. - // Returns 'true' of the position was made sane by some action. - private bool PositionSanityCheck() - { - bool ret = false; - - // If totally below the ground, move the prim up - // TODO: figure out the right solution for this... only for dynamic objects? - /* - float terrainHeight = PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(_position); - if (Position.Z < terrainHeight) - { - DetailLog("{0},BSPrim.PositionAdjustUnderGround,call,pos={1},terrain={2}", LocalID, _position, terrainHeight); - _position.Z = terrainHeight + 2.0f; - ret = true; - } - */ - if ((CurrentCollisionFlags & CollisionFlags.BS_FLOATS_ON_WATER) != 0) - { - float waterHeight = PhysicsScene.GetWaterLevelAtXYZ(_position); - // TODO: a floating motor so object will bob in the water - if (Position.Z < waterHeight) - { - _position.Z = waterHeight; - ret = true; - } - } - - // TODO: check for out of bounds - return ret; - } - - // A version of the sanity check that also makes sure a new position value is - // pushed to the physics engine. This routine would be used by anyone - // who is not already pushing the value. - private bool PositionSanityCheck(bool inTaintTime) - { - bool ret = false; - if (PositionSanityCheck()) - { - // The new position value must be pushed into the physics engine but we can't - // just assign to "Position" because of potential call loops. - PhysicsScene.TaintedObject(inTaintTime, "BSPrim.PositionSanityCheck", delegate() - { - DetailLog("{0},BSPrim.PositionSanityCheck,taint,pos={1},orient={2}", LocalID, _position, _orientation); - ForcePosition = _position; + BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation); }); - ret = true; - } - return ret; + } } // Return the effective mass of the object. // If there are multiple items in the linkset, add them together for the root public override float Mass - { + { get { - return Linkset.LinksetMass; - // return _mass; + return _linkset.LinksetMass; } } // used when we only want this prim's mass and not the linkset thing - public override float RawMass { - get { return _mass; } - } - // Set the physical mass to the passed mass. - // Note that this does not change _mass! - public override void UpdatePhysicalMassProperties(float physMass) - { - if (IsStatic) - { - BulletSimAPI.SetMassProps2(PhysBody.ptr, 0f, OMV.Vector3.Zero); - BulletSimAPI.UpdateInertiaTensor2(PhysBody.ptr); - } - else - { - OMV.Vector3 localInertia = BulletSimAPI.CalculateLocalInertia2(PhysShape.ptr, physMass); - BulletSimAPI.SetMassProps2(PhysBody.ptr, physMass, localInertia); - // center of mass is at the zero of the object - BulletSimAPI.SetCenterOfMassByPosRot2(PhysBody.ptr, ForcePosition, ForceOrientation); - // BulletSimAPI.UpdateInertiaTensor2(BSBody.ptr); - DetailLog("{0},BSPrim.UpdateMassProperties,mass={1},localInertia={2}", LocalID, physMass, localInertia); - } - } + public float MassRaw { get { return _mass; } } // Is this used? public override OMV.Vector3 CenterOfMass { - get { return Linkset.CenterOfMass; } + get { return _linkset.CenterOfMass; } } // Is this used? public override OMV.Vector3 GeometricCenter { - get { return Linkset.GeometricCenter; } + get { return _linkset.GeometricCenter; } } - public override OMV.Vector3 Force { - get { return _force; } + public override OMV.Vector3 Force { + get { return _force; } set { _force = value; - PhysicsScene.TaintedObject("BSPrim.setForce", delegate() + _scene.TaintedObject("BSPrim.setForce", delegate() { // DetailLog("{0},BSPrim.setForce,taint,force={1}", LocalID, _force); - BulletSimAPI.SetObjectForce2(PhysBody.ptr, _force); + // BulletSimAPI.SetObjectForce(_scene.WorldID, _localID, _force); + BulletSimAPI.SetObjectForce2(Body.Ptr, _force); }); - } + } } - public override int VehicleType { + public override int VehicleType { get { return (int)_vehicle.Type; // if we are a vehicle, return that type - } + } set { Vehicle type = (Vehicle)value; - - // Tell the scene about the vehicle so it will get processing each frame. - PhysicsScene.VehicleInSceneTypeChanged(this, type); - - PhysicsScene.TaintedObject("setVehicleType", delegate() + BSPrim vehiclePrim = this; + _scene.TaintedObject("setVehicleType", delegate() { // Done at taint time so we're sure the physics engine is not using the variables // Vehicle code changes the parameters for this vehicle type. _vehicle.ProcessTypeChange(type); - ActivateIfPhysical(false); + // Tell the scene about the vehicle so it will get processing each frame. + _scene.VehicleInSceneTypeChanged(this, type); }); - } + } } - public override void VehicleFloatParam(int param, float value) + public override void VehicleFloatParam(int param, float value) { - PhysicsScene.TaintedObject("BSPrim.VehicleFloatParam", delegate() + _scene.TaintedObject("BSPrim.VehicleFloatParam", delegate() { - _vehicle.ProcessFloatVehicleParam((Vehicle)param, value); - ActivateIfPhysical(false); + _vehicle.ProcessFloatVehicleParam((Vehicle)param, value, _scene.LastSimulatedTimestep); }); } - public override void VehicleVectorParam(int param, OMV.Vector3 value) + public override void VehicleVectorParam(int param, OMV.Vector3 value) { - PhysicsScene.TaintedObject("BSPrim.VehicleVectorParam", delegate() + _scene.TaintedObject("BSPrim.VehicleVectorParam", delegate() { - _vehicle.ProcessVectorVehicleParam((Vehicle)param, value); - ActivateIfPhysical(false); + _vehicle.ProcessVectorVehicleParam((Vehicle)param, value, _scene.LastSimulatedTimestep); }); } - public override void VehicleRotationParam(int param, OMV.Quaternion rotation) + public override void VehicleRotationParam(int param, OMV.Quaternion rotation) { - PhysicsScene.TaintedObject("BSPrim.VehicleRotationParam", delegate() + _scene.TaintedObject("BSPrim.VehicleRotationParam", delegate() { _vehicle.ProcessRotationVehicleParam((Vehicle)param, rotation); - ActivateIfPhysical(false); }); } - public override void VehicleFlags(int param, bool remove) + public override void VehicleFlags(int param, bool remove) { - PhysicsScene.TaintedObject("BSPrim.VehicleFlags", delegate() + _scene.TaintedObject("BSPrim.VehicleFlags", delegate() { _vehicle.ProcessVehicleFlags(param, remove); }); @@ -462,355 +391,143 @@ public sealed class BSPrim : BSPhysObject // Called each simulation step to advance vehicle characteristics. // Called from Scene when doing simulation step so we're in taint processing time. - public override void StepVehicle(float timeStep) + public void StepVehicle(float timeStep) { - if (IsPhysical && _vehicle.IsActive) - { + if (IsPhysical) _vehicle.Step(timeStep); - /* // TEST TEST DEBUG DEBUG -- trying to reduce the extra action of Bullet simulation step - PhysicsScene.PostTaintObject("BSPrim.StepVehicles", LocalID, delegate() - { - // This resets the interpolation values and recomputes the tensor variables - BulletSimAPI.SetCenterOfMassByPosRot2(BSBody.ptr, ForcePosition, ForceOrientation); - }); - */ - } } // Allows the detection of collisions with inherently non-physical prims. see llVolumeDetect for more public override void SetVolumeDetect(int param) { bool newValue = (param != 0); - if (_isVolumeDetect != newValue) + _isVolumeDetect = newValue; + _scene.TaintedObject("BSPrim.SetVolumeDetect", delegate() { - _isVolumeDetect = newValue; - PhysicsScene.TaintedObject("BSPrim.SetVolumeDetect", delegate() - { - // DetailLog("{0},setVolumeDetect,taint,volDetect={1}", LocalID, _isVolumeDetect); - SetObjectDynamic(true); - }); - } - return; + SetObjectDynamic(); + }); + return; } - public override OMV.Vector3 Velocity { - get { return _velocity; } + + public override OMV.Vector3 Velocity { + get { return _velocity; } set { _velocity = value; - PhysicsScene.TaintedObject("BSPrim.setVelocity", delegate() + _scene.TaintedObject("BSPrim.setVelocity", delegate() { // DetailLog("{0},BSPrim.SetVelocity,taint,vel={1}", LocalID, _velocity); - BulletSimAPI.SetLinearVelocity2(PhysBody.ptr, _velocity); + BulletSimAPI.SetObjectVelocity(_scene.WorldID, LocalID, _velocity); }); - } - } - public override OMV.Vector3 ForceVelocity { - get { return _velocity; } - set { - _velocity = value; - BulletSimAPI.SetLinearVelocity2(PhysBody.ptr, _velocity); - } + } } - public override OMV.Vector3 Torque { - get { return _torque; } - set { - _torque = value; - AddAngularForce(_torque, false, false); + public override OMV.Vector3 Torque { + get { return _torque; } + set { _torque = value; // DetailLog("{0},BSPrim.SetTorque,call,torque={1}", LocalID, _torque); - } + } } - public override float CollisionScore { - get { return _collisionScore; } - set { _collisionScore = value; - } + public override float CollisionScore { + get { return _collisionScore; } + set { _collisionScore = value; + } } - public override OMV.Vector3 Acceleration { + public override OMV.Vector3 Acceleration { get { return _acceleration; } set { _acceleration = value; } } - public override OMV.Quaternion RawOrientation - { - get { return _orientation; } - set { _orientation = value; } - } - public override OMV.Quaternion Orientation { + public override OMV.Quaternion Orientation { get { - // Children move around because tied to parent. Get a fresh value. - if (!Linkset.IsRoot(this)) + if (!_linkset.IsRoot(this)) { - _orientation = Linkset.Orientation(this); + // Children move around because tied to parent. Get a fresh value. + _orientation = BulletSimAPI.GetObjectOrientation(_scene.WorldID, LocalID); } return _orientation; - } + } set { - if (_orientation == value) - return; _orientation = value; // TODO: what does it mean if a child in a linkset changes its orientation? Rebuild the constraint? - PhysicsScene.TaintedObject("BSPrim.setOrientation", delegate() + _scene.TaintedObject("BSPrim.setOrientation", delegate() { - // _position = BulletSimAPI.GetObjectPosition2(PhysicsScene.World.ptr, BSBody.ptr); + // _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID); // DetailLog("{0},BSPrim.setOrientation,taint,pos={1},orient={2}", LocalID, _position, _orientation); - BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation); + BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation); }); - } + } } - // Go directly to Bullet to get/set the value. - public override OMV.Quaternion ForceOrientation - { - get - { - _orientation = BulletSimAPI.GetOrientation2(PhysBody.ptr); - return _orientation; - } - set - { - _orientation = value; - BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation); - } + public override int PhysicsActorType { + get { return _physicsActorType; } + set { _physicsActorType = value; + } } - public override int PhysicsActorType { - get { return _physicsActorType; } - set { _physicsActorType = value; } - } - public override bool IsPhysical { - get { return _isPhysical; } + public override bool IsPhysical { + get { return _isPhysical; } set { - if (_isPhysical != value) + _isPhysical = value; + _scene.TaintedObject("BSPrim.setIsPhysical", delegate() { - _isPhysical = value; - PhysicsScene.TaintedObject("BSPrim.setIsPhysical", delegate() - { - // DetailLog("{0},setIsPhysical,taint,isPhys={1}", LocalID, _isPhysical); - SetObjectDynamic(true); - // whether phys-to-static or static-to-phys, the object is not moving. - ZeroMotion(); - }); - } - } + SetObjectDynamic(); + }); + } } // An object is static (does not move) if selected or not physical - public override bool IsStatic + private bool IsStatic { get { return _isSelected || !IsPhysical; } } // An object is solid if it's not phantom and if it's not doing VolumeDetect - public override bool IsSolid + private bool IsSolid { get { return !IsPhantom && !_isVolumeDetect; } } // Make gravity work if the object is physical and not selected - // Called at taint-time!! - private void SetObjectDynamic(bool forceRebuild) - { - // Recreate the physical object if necessary - CreateGeomAndObject(forceRebuild); - } - - // Convert the simulator's physical properties into settings on BulletSim objects. - // There are four flags we're interested in: - // IsStatic: Object does not move, otherwise the object has mass and moves - // isSolid: other objects bounce off of this object - // isVolumeDetect: other objects pass through but can generate collisions - // collisionEvents: whether this object returns collision events - private void UpdatePhysicalParameters() - { - // DetailLog("{0},BSPrim.UpdatePhysicalParameters,entry,body={1},shape={2}", LocalID, BSBody, BSShape); - - // Mangling all the physical properties requires the object not be in the physical world. - // This is a NOOP if the object is not in the world (BulletSim and Bullet ignore objects not found). - BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, PhysBody.ptr); - - // Set up the object physicalness (does gravity and collisions move this object) - MakeDynamic(IsStatic); - - // Update vehicle specific parameters (after MakeDynamic() so can change physical parameters) - _vehicle.Refresh(); - - // Arrange for collision events if the simulator wants them - EnableCollisions(SubscribedEvents()); - - // Make solid or not (do things bounce off or pass through this object). - MakeSolid(IsSolid); - - BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, PhysBody.ptr); - - // Rebuild its shape - BulletSimAPI.UpdateSingleAabb2(PhysicsScene.World.ptr, PhysBody.ptr); - - // Collision filter can be set only when the object is in the world - if (PhysBody.collisionFilter != 0 || PhysBody.collisionMask != 0) - { - BulletSimAPI.SetCollisionFilterMask2(PhysBody.ptr, (uint)PhysBody.collisionFilter, (uint)PhysBody.collisionMask); - } - - // Recompute any linkset parameters. - // When going from non-physical to physical, this re-enables the constraints that - // had been automatically disabled when the mass was set to zero. - Linkset.Refresh(this); - - DetailLog("{0},BSPrim.UpdatePhysicalParameters,taintExit,static={1},solid={2},mass={3},collide={4},cf={5:X},body={6},shape={7}", - LocalID, IsStatic, IsSolid, _mass, SubscribedEvents(), CurrentCollisionFlags, PhysBody, PhysShape); - } - - // "Making dynamic" means changing to and from static. - // When static, gravity does not effect the object and it is fixed in space. - // When dynamic, the object can fall and be pushed by others. - // This is independent of its 'solidness' which controls what passes through - // this object and what interacts with it. - private void MakeDynamic(bool makeStatic) + // No locking here because only called when it is safe + private void SetObjectDynamic() { - if (makeStatic) - { - // Become a Bullet 'static' object type - CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(PhysBody.ptr, CollisionFlags.CF_STATIC_OBJECT); - // Stop all movement - ZeroMotion(); - // Center of mass is at the center of the object - BulletSimAPI.SetCenterOfMassByPosRot2(Linkset.LinksetRoot.PhysBody.ptr, _position, _orientation); - // Mass is zero which disables a bunch of physics stuff in Bullet - UpdatePhysicalMassProperties(0f); - // Set collision detection parameters - if (PhysicsScene.Params.ccdMotionThreshold > 0f) - { - BulletSimAPI.SetCcdMotionThreshold2(PhysBody.ptr, PhysicsScene.Params.ccdMotionThreshold); - BulletSimAPI.SetCcdSweptSphereRadius2(PhysBody.ptr, PhysicsScene.Params.ccdSweptSphereRadius); - } - // There can be special things needed for implementing linksets - Linkset.MakeStatic(this); - // The activation state is 'disabled' so Bullet will not try to act on it. - BulletSimAPI.ForceActivationState2(PhysBody.ptr, ActivationState.DISABLE_SIMULATION); - // Start it out sleeping and physical actions could wake it up. - // BulletSimAPI.ForceActivationState2(BSBody.ptr, ActivationState.ISLAND_SLEEPING); - - PhysBody.collisionFilter = CollisionFilterGroups.StaticObjectFilter; - PhysBody.collisionMask = CollisionFilterGroups.StaticObjectMask; - } - else - { - // Not a Bullet static object - CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(PhysBody.ptr, CollisionFlags.CF_STATIC_OBJECT); - - // Set various physical properties so internal dynamic properties will get computed correctly as they are set - BulletSimAPI.SetFriction2(PhysBody.ptr, PhysicsScene.Params.defaultFriction); - BulletSimAPI.SetRestitution2(PhysBody.ptr, PhysicsScene.Params.defaultRestitution); - - // per http://www.bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=3382 - // Since this can be called multiple times, only zero forces when becoming physical - // BulletSimAPI.ClearAllForces2(BSBody.ptr); + // RA: remove this for the moment. + // The problem is that dynamic objects are hulls so if we are becoming physical + // the shape has to be checked and possibly built. + // Maybe a VerifyCorrectPhysicalShape() routine? + // RecreateGeomAndObject(); - // For good measure, make sure the transform is set through to the motion state - BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation); + // Bullet wants static objects to have a mass of zero + float mass = IsStatic ? 0f : _mass; - // Center of mass is at the center of the object - BulletSimAPI.SetCenterOfMassByPosRot2(Linkset.LinksetRoot.PhysBody.ptr, _position, _orientation); - - // A dynamic object has mass - UpdatePhysicalMassProperties(RawMass); - - // Set collision detection parameters - if (PhysicsScene.Params.ccdMotionThreshold > 0f) - { - BulletSimAPI.SetCcdMotionThreshold2(PhysBody.ptr, PhysicsScene.Params.ccdMotionThreshold); - BulletSimAPI.SetCcdSweptSphereRadius2(PhysBody.ptr, PhysicsScene.Params.ccdSweptSphereRadius); - } - - // Various values for simulation limits - BulletSimAPI.SetDamping2(PhysBody.ptr, PhysicsScene.Params.linearDamping, PhysicsScene.Params.angularDamping); - BulletSimAPI.SetDeactivationTime2(PhysBody.ptr, PhysicsScene.Params.deactivationTime); - BulletSimAPI.SetSleepingThresholds2(PhysBody.ptr, PhysicsScene.Params.linearSleepingThreshold, PhysicsScene.Params.angularSleepingThreshold); - BulletSimAPI.SetContactProcessingThreshold2(PhysBody.ptr, PhysicsScene.Params.contactProcessingThreshold); - - // There might be special things needed for implementing linksets. - Linkset.MakeDynamic(this); - - // Force activation of the object so Bullet will act on it. - // Must do the ForceActivationState2() to overcome the DISABLE_SIMULATION from static objects. - BulletSimAPI.ForceActivationState2(PhysBody.ptr, ActivationState.ACTIVE_TAG); - // BulletSimAPI.Activate2(BSBody.ptr, true); - - PhysBody.collisionFilter = CollisionFilterGroups.ObjectFilter; - PhysBody.collisionMask = CollisionFilterGroups.ObjectMask; - } - } - - // "Making solid" means that other object will not pass through this object. - // To make transparent, we create a Bullet ghost object. - // Note: This expects to be called from the UpdatePhysicalParameters() routine as - // the functions after this one set up the state of a possibly newly created collision body. - private void MakeSolid(bool makeSolid) - { - CollisionObjectTypes bodyType = (CollisionObjectTypes)BulletSimAPI.GetBodyType2(PhysBody.ptr); - if (makeSolid) - { - // Verify the previous code created the correct shape for this type of thing. - if ((bodyType & CollisionObjectTypes.CO_RIGID_BODY) == 0) - { - m_log.ErrorFormat("{0} MakeSolid: physical body of wrong type for solidity. id={1}, type={2}", LogHeader, LocalID, bodyType); - } - CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(PhysBody.ptr, CollisionFlags.CF_NO_CONTACT_RESPONSE); - } - else - { - if ((bodyType & CollisionObjectTypes.CO_GHOST_OBJECT) == 0) - { - m_log.ErrorFormat("{0} MakeSolid: physical body of wrong type for non-solidness. id={1}, type={2}", LogHeader, LocalID, bodyType); - } - CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(PhysBody.ptr, CollisionFlags.CF_NO_CONTACT_RESPONSE); - PhysBody.collisionFilter = CollisionFilterGroups.VolumeDetectFilter; - PhysBody.collisionMask = CollisionFilterGroups.VolumeDetectMask; - } - } + BulletSimAPI.SetObjectProperties(_scene.WorldID, LocalID, IsStatic, IsSolid, SubscribedEvents(), mass); - // Enable physical actions. Bullet will keep sleeping non-moving physical objects so - // they need waking up when parameters are changed. - // Called in taint-time!! - private void ActivateIfPhysical(bool forceIt) - { - if (IsPhysical) - BulletSimAPI.Activate2(PhysBody.ptr, forceIt); - } + // recompute any linkset parameters + _linkset.Refresh(this); - // Turn on or off the flag controlling whether collision events are returned to the simulator. - private void EnableCollisions(bool wantsCollisionEvents) - { - if (wantsCollisionEvents) - { - CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(PhysBody.ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); - } - else - { - CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(PhysBody.ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); - } + CollisionFlags cf = BulletSimAPI.GetCollisionFlags2(Body.Ptr); + // DetailLog("{0},BSPrim.SetObjectDynamic,taint,static={1},solid={2},mass={3}, cf={4}", LocalID, IsStatic, IsSolid, mass, cf); } // prims don't fly - public override bool Flying { - get { return _flying; } - set { - _flying = value; - } + public override bool Flying { + get { return _flying; } + set { _flying = value; } } - public override bool SetAlwaysRun { - get { return _setAlwaysRun; } - set { _setAlwaysRun = value; } + public override bool SetAlwaysRun { + get { return _setAlwaysRun; } + set { _setAlwaysRun = value; } } - public override bool ThrottleUpdates { - get { return _throttleUpdates; } - set { _throttleUpdates = value; } + public override bool ThrottleUpdates { + get { return _throttleUpdates; } + set { _throttleUpdates = value; } } public override bool IsColliding { - get { return (CollidingStep == PhysicsScene.SimulationStep); } - set { _isColliding = value; } + get { return (_collidingStep == _scene.SimulationStep); } + set { _isColliding = value; } } public override bool CollidingGround { - get { return (CollidingGroundStep == PhysicsScene.SimulationStep); } - set { _collidingGround = value; } + get { return (_collidingGroundStep == _scene.SimulationStep); } + set { _collidingGround = value; } } - public override bool CollidingObj { - get { return _collidingObj; } - set { _collidingObj = value; } + public override bool CollidingObj { + get { return _collidingObj; } + set { _collidingObj = value; } } public bool IsPhantom { get { @@ -820,19 +537,10 @@ public sealed class BSPrim : BSPhysObject return false; } } - public override bool FloatOnWater { - set { - _floatOnWater = value; - PhysicsScene.TaintedObject("BSPrim.setFloatOnWater", delegate() - { - if (_floatOnWater) - CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(PhysBody.ptr, CollisionFlags.BS_FLOATS_ON_WATER); - else - CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(PhysBody.ptr, CollisionFlags.BS_FLOATS_ON_WATER); - }); - } + public override bool FloatOnWater { + set { _floatOnWater = value; } } - public override OMV.Vector3 RotationalVelocity { + public override OMV.Vector3 RotationalVelocity { get { /* OMV.Vector3 pv = OMV.Vector3.Zero; @@ -844,76 +552,58 @@ public sealed class BSPrim : BSPhysObject */ return _rotationalVelocity; - } + } set { _rotationalVelocity = value; // m_log.DebugFormat("{0}: RotationalVelocity={1}", LogHeader, _rotationalVelocity); - PhysicsScene.TaintedObject("BSPrim.setRotationalVelocity", delegate() + _scene.TaintedObject("BSPrim.setRotationalVelocity", delegate() { - DetailLog("{0},BSPrim.SetRotationalVel,taint,rotvel={1}", LocalID, _rotationalVelocity); - BulletSimAPI.SetAngularVelocity2(PhysBody.ptr, _rotationalVelocity); + // DetailLog("{0},BSPrim.SetRotationalVel,taint,rotvel={1}", LocalID, _rotationalVelocity); + BulletSimAPI.SetObjectAngularVelocity(_scene.WorldID, LocalID, _rotationalVelocity); }); - } - } - public override OMV.Vector3 ForceRotationalVelocity { - get { - return _rotationalVelocity; - } - set { - _rotationalVelocity = value; - BulletSimAPI.SetAngularVelocity2(PhysBody.ptr, _rotationalVelocity); - } + } } - public override bool Kinematic { - get { return _kinematic; } - set { _kinematic = value; + public override bool Kinematic { + get { return _kinematic; } + set { _kinematic = value; // m_log.DebugFormat("{0}: Kinematic={1}", LogHeader, _kinematic); - } + } } - public override float Buoyancy { - get { return _buoyancy; } + public override float Buoyancy { + get { return _buoyancy; } set { _buoyancy = value; - PhysicsScene.TaintedObject("BSPrim.setBuoyancy", delegate() + _scene.TaintedObject("BSPrim.setBuoyancy", delegate() { - ForceBuoyancy = _buoyancy; + // DetailLog("{0},BSPrim.SetBuoyancy,taint,buoy={1}", LocalID, _buoyancy); + BulletSimAPI.SetObjectBuoyancy(_scene.WorldID, _localID, _buoyancy); }); - } - } - public override float ForceBuoyancy { - get { return _buoyancy; } - set { - _buoyancy = value; - // DetailLog("{0},BSPrim.setForceBuoyancy,taint,buoy={1}", LocalID, _buoyancy); - // Buoyancy is faked by changing the gravity applied to the object - float grav = PhysicsScene.Params.gravity * (1f - _buoyancy); - BulletSimAPI.SetGravity2(PhysBody.ptr, new OMV.Vector3(0f, 0f, grav)); - } + } } // Used for MoveTo - public override OMV.Vector3 PIDTarget { - set { _PIDTarget = value; } + public override OMV.Vector3 PIDTarget { + set { _PIDTarget = value; } } - public override bool PIDActive { - set { _usePID = value; } + public override bool PIDActive { + set { _usePID = value; } } - public override float PIDTau { - set { _PIDTau = value; } + public override float PIDTau { + set { _PIDTau = value; } } // Used for llSetHoverHeight and maybe vehicle height // Hover Height will override MoveTo target's Z - public override bool PIDHoverActive { + public override bool PIDHoverActive { set { _useHoverPID = value; } } - public override float PIDHoverHeight { + public override float PIDHoverHeight { set { _PIDHoverHeight = value; } } - public override PIDHoverType PIDHoverType { + public override PIDHoverType PIDHoverType { set { _PIDHoverType = value; } } - public override float PIDHoverTau { + public override float PIDHoverTau { set { _PIDHoverTao = value; } } @@ -925,9 +615,6 @@ public sealed class BSPrim : BSPhysObject private List m_accumulatedForces = new List(); public override void AddForce(OMV.Vector3 force, bool pushforce) { - AddForce(force, pushforce, false); - } - public void AddForce(OMV.Vector3 force, bool pushforce, bool inTaintTime) { // for an object, doesn't matter if force is a pushforce or not if (force.IsFinite()) { @@ -937,78 +624,56 @@ public sealed class BSPrim : BSPhysObject } else { - m_log.WarnFormat("{0}: Got a NaN force applied to a prim. LocalID={1}", LogHeader, LocalID); + m_log.WarnFormat("{0}: Got a NaN force applied to a Character", LogHeader); return; } - PhysicsScene.TaintedObject(inTaintTime, "BSPrim.AddForce", delegate() + _scene.TaintedObject("BSPrim.AddForce", delegate() { OMV.Vector3 fSum = OMV.Vector3.Zero; lock (m_accumulatedForces) { - // Sum the accumulated additional forces for one big force to apply once. foreach (OMV.Vector3 v in m_accumulatedForces) { fSum += v; } m_accumulatedForces.Clear(); } - DetailLog("{0},BSPrim.AddForce,taint,force={1}", LocalID, fSum); - if (fSum != OMV.Vector3.Zero) - BulletSimAPI.ApplyCentralForce2(PhysBody.ptr, fSum); + // DetailLog("{0},BSPrim.AddObjectForce,taint,force={1}", LocalID, _force); + BulletSimAPI.AddObjectForce2(Body.Ptr, fSum); }); } - private List m_accumulatedAngularForces = new List(); - public override void AddAngularForce(OMV.Vector3 force, bool pushforce) { - AddAngularForce(force, pushforce, false); + public override void AddAngularForce(OMV.Vector3 force, bool pushforce) { + // DetailLog("{0},BSPrim.AddAngularForce,call,angForce={1},push={2}", LocalID, force, pushforce); + // m_log.DebugFormat("{0}: AddAngularForce. f={1}, push={2}", LogHeader, force, pushforce); } - public void AddAngularForce(OMV.Vector3 force, bool pushforce, bool inTaintTime) - { - if (force.IsFinite()) - { - // _force += force; - lock (m_accumulatedAngularForces) - m_accumulatedAngularForces.Add(new OMV.Vector3(force)); - } - else - { - m_log.WarnFormat("{0}: Got a NaN force applied to a prim. LocalID={1}", LogHeader, LocalID); - return; - } - PhysicsScene.TaintedObject(inTaintTime, "BSPrim.AddAngularForce", delegate() + public override void SetMomentum(OMV.Vector3 momentum) { + // DetailLog("{0},BSPrim.SetMomentum,call,mom={1}", LocalID, momentum); + } + public override void SubscribeEvents(int ms) { + _subscribedEventsMs = ms; + if (ms > 0) { - OMV.Vector3 fSum = OMV.Vector3.Zero; - lock (m_accumulatedAngularForces) - { - // Sum the accumulated additional forces for one big force to apply once. - foreach (OMV.Vector3 v in m_accumulatedAngularForces) - { - fSum += v; - } - m_accumulatedAngularForces.Clear(); - } - DetailLog("{0},BSPrim.AddAngularForce,taint,aForce={1}", LocalID, fSum); - if (fSum != OMV.Vector3.Zero) + // make sure first collision happens + _nextCollisionOkTime = Util.EnvironmentTickCount() - _subscribedEventsMs; + + Scene.TaintedObject("BSPrim.SubscribeEvents", delegate() { - BulletSimAPI.ApplyTorque2(PhysBody.ptr, fSum); - _torque = fSum; - } - }); + BulletSimAPI.AddToCollisionFlags2(Body.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); + }); + } } - // A torque impulse. - public void ApplyTorqueImpulse(OMV.Vector3 impulse, bool inTaintTime) - { - OMV.Vector3 applyImpulse = impulse; - PhysicsScene.TaintedObject(inTaintTime, "BSPrim.ApplyTorqueImpulse", delegate() + public override void UnSubscribeEvents() { + _subscribedEventsMs = 0; + Scene.TaintedObject("BSPrim.UnSubscribeEvents", delegate() { - DetailLog("{0},BSPrim.ApplyTorqueImpulse,taint,tImpulse={1}", LocalID, applyImpulse); - BulletSimAPI.ApplyTorqueImpulse2(PhysBody.ptr, applyImpulse); + BulletSimAPI.RemoveFromCollisionFlags2(Body.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); }); } - - public override void SetMomentum(OMV.Vector3 momentum) { - // DetailLog("{0},BSPrim.SetMomentum,call,mom={1}", LocalID, momentum); + public override bool SubscribedEvents() { + return (_subscribedEventsMs > 0); } + #region Mass Calculation private float CalculateMass() @@ -1017,19 +682,19 @@ public sealed class BSPrim : BSPhysObject float tmp; float returnMass = 0; - float hollowAmount = (float)BaseShape.ProfileHollow * 2.0e-5f; - float hollowVolume = hollowAmount * hollowAmount; - - switch (BaseShape.ProfileShape) + float hollowAmount = (float)_pbs.ProfileHollow * 2.0e-5f; + float hollowVolume = hollowAmount * hollowAmount; + + switch (_pbs.ProfileShape) { case ProfileShape.Square: // default box - if (BaseShape.PathCurve == (byte)Extrusion.Straight) + if (_pbs.PathCurve == (byte)Extrusion.Straight) { if (hollowAmount > 0.0) { - switch (BaseShape.HollowShape) + switch (_pbs.HollowShape) { case HollowShape.Square: case HollowShape.Same: @@ -1053,19 +718,19 @@ public sealed class BSPrim : BSPhysObject } } - else if (BaseShape.PathCurve == (byte)Extrusion.Curve1) + else if (_pbs.PathCurve == (byte)Extrusion.Curve1) { - //a tube + //a tube - volume *= 0.78539816339e-2f * (float)(200 - BaseShape.PathScaleX); - tmp= 1.0f -2.0e-2f * (float)(200 - BaseShape.PathScaleY); + volume *= 0.78539816339e-2f * (float)(200 - _pbs.PathScaleX); + tmp= 1.0f -2.0e-2f * (float)(200 - _pbs.PathScaleY); volume -= volume*tmp*tmp; - + if (hollowAmount > 0.0) { hollowVolume *= hollowAmount; - - switch (BaseShape.HollowShape) + + switch (_pbs.HollowShape) { case HollowShape.Square: case HollowShape.Same: @@ -1090,13 +755,13 @@ public sealed class BSPrim : BSPhysObject case ProfileShape.Circle: - if (BaseShape.PathCurve == (byte)Extrusion.Straight) + if (_pbs.PathCurve == (byte)Extrusion.Straight) { volume *= 0.78539816339f; // elipse base if (hollowAmount > 0.0) { - switch (BaseShape.HollowShape) + switch (_pbs.HollowShape) { case HollowShape.Same: case HollowShape.Circle: @@ -1118,19 +783,19 @@ public sealed class BSPrim : BSPhysObject } } - else if (BaseShape.PathCurve == (byte)Extrusion.Curve1) + else if (_pbs.PathCurve == (byte)Extrusion.Curve1) { - volume *= 0.61685027506808491367715568749226e-2f * (float)(200 - BaseShape.PathScaleX); - tmp = 1.0f - .02f * (float)(200 - BaseShape.PathScaleY); + volume *= 0.61685027506808491367715568749226e-2f * (float)(200 - _pbs.PathScaleX); + tmp = 1.0f - .02f * (float)(200 - _pbs.PathScaleY); volume *= (1.0f - tmp * tmp); - + if (hollowAmount > 0.0) { // calculate the hollow volume by it's shape compared to the prim shape hollowVolume *= hollowAmount; - switch (BaseShape.HollowShape) + switch (_pbs.HollowShape) { case HollowShape.Same: case HollowShape.Circle: @@ -1154,7 +819,7 @@ public sealed class BSPrim : BSPhysObject break; case ProfileShape.HalfCircle: - if (BaseShape.PathCurve == (byte)Extrusion.Curve1) + if (_pbs.PathCurve == (byte)Extrusion.Curve1) { volume *= 0.52359877559829887307710723054658f; } @@ -1162,7 +827,7 @@ public sealed class BSPrim : BSPhysObject case ProfileShape.EquilateralTriangle: - if (BaseShape.PathCurve == (byte)Extrusion.Straight) + if (_pbs.PathCurve == (byte)Extrusion.Straight) { volume *= 0.32475953f; @@ -1170,7 +835,7 @@ public sealed class BSPrim : BSPhysObject { // calculate the hollow volume by it's shape compared to the prim shape - switch (BaseShape.HollowShape) + switch (_pbs.HollowShape) { case HollowShape.Same: case HollowShape.Triangle: @@ -1195,11 +860,11 @@ public sealed class BSPrim : BSPhysObject volume *= (1.0f - hollowVolume); } } - else if (BaseShape.PathCurve == (byte)Extrusion.Curve1) + else if (_pbs.PathCurve == (byte)Extrusion.Curve1) { volume *= 0.32475953f; - volume *= 0.01f * (float)(200 - BaseShape.PathScaleX); - tmp = 1.0f - .02f * (float)(200 - BaseShape.PathScaleY); + volume *= 0.01f * (float)(200 - _pbs.PathScaleX); + tmp = 1.0f - .02f * (float)(200 - _pbs.PathScaleY); volume *= (1.0f - tmp * tmp); if (hollowAmount > 0.0) @@ -1207,7 +872,7 @@ public sealed class BSPrim : BSPhysObject hollowVolume *= hollowAmount; - switch (BaseShape.HollowShape) + switch (_pbs.HollowShape) { case HollowShape.Same: case HollowShape.Triangle: @@ -1247,26 +912,26 @@ public sealed class BSPrim : BSPhysObject float profileBegin; float profileEnd; - if (BaseShape.PathCurve == (byte)Extrusion.Straight || BaseShape.PathCurve == (byte)Extrusion.Flexible) + if (_pbs.PathCurve == (byte)Extrusion.Straight || _pbs.PathCurve == (byte)Extrusion.Flexible) { - taperX1 = BaseShape.PathScaleX * 0.01f; + taperX1 = _pbs.PathScaleX * 0.01f; if (taperX1 > 1.0f) taperX1 = 2.0f - taperX1; taperX = 1.0f - taperX1; - taperY1 = BaseShape.PathScaleY * 0.01f; + taperY1 = _pbs.PathScaleY * 0.01f; if (taperY1 > 1.0f) taperY1 = 2.0f - taperY1; taperY = 1.0f - taperY1; } else { - taperX = BaseShape.PathTaperX * 0.01f; + taperX = _pbs.PathTaperX * 0.01f; if (taperX < 0.0f) taperX = -taperX; taperX1 = 1.0f - taperX; - taperY = BaseShape.PathTaperY * 0.01f; + taperY = _pbs.PathTaperY * 0.01f; if (taperY < 0.0f) taperY = -taperY; taperY1 = 1.0f - taperY; @@ -1276,18 +941,20 @@ public sealed class BSPrim : BSPhysObject volume *= (taperX1 * taperY1 + 0.5f * (taperX1 * taperY + taperX * taperY1) + 0.3333333333f * taperX * taperY); - pathBegin = (float)BaseShape.PathBegin * 2.0e-5f; - pathEnd = 1.0f - (float)BaseShape.PathEnd * 2.0e-5f; + pathBegin = (float)_pbs.PathBegin * 2.0e-5f; + pathEnd = 1.0f - (float)_pbs.PathEnd * 2.0e-5f; volume *= (pathEnd - pathBegin); // this is crude aproximation - profileBegin = (float)BaseShape.ProfileBegin * 2.0e-5f; - profileEnd = 1.0f - (float)BaseShape.ProfileEnd * 2.0e-5f; + profileBegin = (float)_pbs.ProfileBegin * 2.0e-5f; + profileEnd = 1.0f - (float)_pbs.ProfileEnd * 2.0e-5f; volume *= (profileEnd - profileBegin); returnMass = _density * volume; - /* Comment out code that computes the mass of the linkset. That is done in the Linkset class. + /* + * This change means each object keeps its own mass and the Mass property + * will return the sum if we're part of a linkset. if (IsRootOfLinkset) { foreach (BSPrim prim in _childrenPrims) @@ -1300,42 +967,296 @@ public sealed class BSPrim : BSPhysObject if (returnMass <= 0) returnMass = 0.0001f; - if (returnMass > PhysicsScene.MaximumObjectMass) - returnMass = PhysicsScene.MaximumObjectMass; + if (returnMass > _scene.MaximumObjectMass) + returnMass = _scene.MaximumObjectMass; return returnMass; }// end CalculateMass #endregion Mass Calculation - // Rebuild the geometry and object. - // This is called when the shape changes so we need to recreate the mesh/hull. - // Called at taint-time!!! - private void CreateGeomAndObject(bool forceRebuild) + // Create the geometry information in Bullet for later use + // The objects needs a hull if it's physical otherwise a mesh is enough + // No locking here because this is done when we know physics is not simulating + // if 'forceRebuild' is true, the geometry is rebuilt. Otherwise a previously built version is used + // Returns 'true' if the geometry was rebuilt + private bool CreateGeom(bool forceRebuild) { - // If this prim is part of a linkset, we must remove and restore the physical - // links if the body is rebuilt. - bool needToRestoreLinkset = false; - - // Create the correct physical representation for this type of object. - // Updates BSBody and BSShape with the new information. - // Ignore 'forceRebuild'. This routine makes the right choices and changes of necessary. - // Returns 'true' if either the body or the shape was changed. - PhysicsScene.Shapes.GetBodyAndShape(false, PhysicsScene.World, this, null, delegate(BulletBody dBody) + // the mesher thought this was too simple to mesh. Use a native Bullet collision shape. + bool ret = false; + if (!_scene.NeedsMeshing(_pbs)) { - // Called if the current prim body is about to be destroyed. - // Remove all the physical dependencies on the old body. - // (Maybe someday make the changing of BSShape an event handled by BSLinkset.) - needToRestoreLinkset = Linkset.RemoveBodyDependencies(this); - }); + if (_pbs.ProfileShape == ProfileShape.HalfCircle && _pbs.PathCurve == (byte)Extrusion.Curve1) + { + // if (_size.X == _size.Y && _size.Y == _size.Z && _size.X == _size.Z) + // { + // m_log.DebugFormat("{0}: CreateGeom: Defaulting to sphere of size {1}", LogHeader, _size); + if (forceRebuild || (_shapeType != ShapeData.PhysicsShapeType.SHAPE_SPHERE)) + { + // DetailLog("{0},BSPrim.CreateGeom,sphere (force={1}", LocalID, forceRebuild); + _shapeType = ShapeData.PhysicsShapeType.SHAPE_SPHERE; + // Bullet native objects are scaled by the Bullet engine so pass the size in + _scale = _size; + // TODO: do we need to check for and destroy a mesh or hull that might have been left from before? + ret = true; + } + // } + } + else + { + // m_log.DebugFormat("{0}: CreateGeom: Defaulting to box. lid={1}, type={2}, size={3}", LogHeader, LocalID, _shapeType, _size); + if (forceRebuild || (_shapeType != ShapeData.PhysicsShapeType.SHAPE_BOX)) + { + // DetailLog("{0},BSPrim.CreateGeom,box (force={1})", LocalID, forceRebuild); + _shapeType = ShapeData.PhysicsShapeType.SHAPE_BOX; + _scale = _size; + // TODO: do we need to check for and destroy a mesh or hull that might have been left from before? + ret = true; + } + } + } + else + { + if (IsPhysical) + { + if (forceRebuild || _hullKey == 0) + { + // physical objects require a hull for interaction. + // This will create the mesh if it doesn't already exist + CreateGeomHull(); + ret = true; + } + } + else + { + if (forceRebuild || _meshKey == 0) + { + // Static (non-physical) objects only need a mesh for bumping into + CreateGeomMesh(); + ret = true; + } + } + } + return ret; + } + + // No locking here because this is done when we know physics is not simulating + private void CreateGeomMesh() + { + float lod = _pbs.SculptEntry ? _scene.SculptLOD : _scene.MeshLOD; + ulong newMeshKey = (ulong)_pbs.GetMeshKey(_size, lod); + // m_log.DebugFormat("{0}: CreateGeomMesh: lID={1}, oldKey={2}, newKey={3}", LogHeader, _localID, _meshKey, newMeshKey); + + // if this new shape is the same as last time, don't recreate the mesh + if (_meshKey == newMeshKey) return; + + // DetailLog("{0},BSPrim.CreateGeomMesh,create,key={1}", LocalID, newMeshKey); + // Since we're recreating new, get rid of any previously generated shape + if (_meshKey != 0) + { + // m_log.DebugFormat("{0}: CreateGeom: deleting old mesh. lID={1}, Key={2}", LogHeader, _localID, _meshKey); + // DetailLog("{0},BSPrim.CreateGeomMesh,deleteOld,key={1}", LocalID, _meshKey); + BulletSimAPI.DestroyMesh(_scene.WorldID, _meshKey); + _mesh = null; + _meshKey = 0; + } + + _meshKey = newMeshKey; + // always pass false for physicalness as this creates some sort of bounding box which we don't need + _mesh = _scene.mesher.CreateMesh(_avName, _pbs, _size, lod, false); + + int[] indices = _mesh.getIndexListAsInt(); + List vertices = _mesh.getVertexList(); + + float[] verticesAsFloats = new float[vertices.Count * 3]; + int vi = 0; + foreach (OMV.Vector3 vv in vertices) + { + verticesAsFloats[vi++] = vv.X; + verticesAsFloats[vi++] = vv.Y; + verticesAsFloats[vi++] = vv.Z; + } + + // m_log.DebugFormat("{0}: CreateGeomMesh: calling CreateMesh. lid={1}, key={2}, indices={3}, vertices={4}", + // LogHeader, _localID, _meshKey, indices.Length, vertices.Count); + BulletSimAPI.CreateMesh(_scene.WorldID, _meshKey, indices.GetLength(0), indices, + vertices.Count, verticesAsFloats); + + _shapeType = ShapeData.PhysicsShapeType.SHAPE_MESH; + // meshes are already scaled by the meshmerizer + _scale = new OMV.Vector3(1f, 1f, 1f); + // DetailLog("{0},BSPrim.CreateGeomMesh,done", LocalID); + return; + } + + // No locking here because this is done when we know physics is not simulating + private void CreateGeomHull() + { + float lod = _pbs.SculptEntry ? _scene.SculptLOD : _scene.MeshLOD; + ulong newHullKey = (ulong)_pbs.GetMeshKey(_size, lod); + // m_log.DebugFormat("{0}: CreateGeomHull: lID={1}, oldKey={2}, newKey={3}", LogHeader, _localID, _hullKey, newHullKey); + + // if the hull hasn't changed, don't rebuild it + if (newHullKey == _hullKey) return; - if (needToRestoreLinkset) + // DetailLog("{0},BSPrim.CreateGeomHull,create,oldKey={1},newKey={2}", LocalID, _hullKey, newHullKey); + + // Since we're recreating new, get rid of any previously generated shape + if (_hullKey != 0) { - // If physical body dependencies were removed, restore them - Linkset.RestoreBodyDependencies(this); + // m_log.DebugFormat("{0}: CreateGeom: deleting old hull. Key={1}", LogHeader, _hullKey); + // DetailLog("{0},BSPrim.CreateGeomHull,deleteOldHull,key={1}", LocalID, _hullKey); + BulletSimAPI.DestroyHull(_scene.WorldID, _hullKey); + _hullKey = 0; + } + + _hullKey = newHullKey; + + // Make sure the underlying mesh exists and is correct + CreateGeomMesh(); + + int[] indices = _mesh.getIndexListAsInt(); + List vertices = _mesh.getVertexList(); + + //format conversion from IMesh format to DecompDesc format + List convIndices = new List(); + List convVertices = new List(); + for (int ii = 0; ii < indices.GetLength(0); ii++) + { + convIndices.Add(indices[ii]); + } + foreach (OMV.Vector3 vv in vertices) + { + convVertices.Add(new float3(vv.X, vv.Y, vv.Z)); + } + + // setup and do convex hull conversion + _hulls = new List(); + DecompDesc dcomp = new DecompDesc(); + dcomp.mIndices = convIndices; + dcomp.mVertices = convVertices; + ConvexBuilder convexBuilder = new ConvexBuilder(HullReturn); + // create the hull into the _hulls variable + convexBuilder.process(dcomp); + + // Convert the vertices and indices for passing to unmanaged. + // The hull information is passed as a large floating point array. + // The format is: + // convHulls[0] = number of hulls + // convHulls[1] = number of vertices in first hull + // convHulls[2] = hull centroid X coordinate + // convHulls[3] = hull centroid Y coordinate + // convHulls[4] = hull centroid Z coordinate + // convHulls[5] = first hull vertex X + // convHulls[6] = first hull vertex Y + // convHulls[7] = first hull vertex Z + // convHulls[8] = second hull vertex X + // ... + // convHulls[n] = number of vertices in second hull + // convHulls[n+1] = second hull centroid X coordinate + // ... + // + // TODO: is is very inefficient. Someday change the convex hull generator to return + // data structures that do not need to be converted in order to pass to Bullet. + // And maybe put the values directly into pinned memory rather than marshaling. + int hullCount = _hulls.Count; + int totalVertices = 1; // include one for the count of the hulls + foreach (ConvexResult cr in _hulls) + { + totalVertices += 4; // add four for the vertex count and centroid + totalVertices += cr.HullIndices.Count * 3; // we pass just triangles + } + float[] convHulls = new float[totalVertices]; + + convHulls[0] = (float)hullCount; + int jj = 1; + foreach (ConvexResult cr in _hulls) + { + // copy vertices for index access + float3[] verts = new float3[cr.HullVertices.Count]; + int kk = 0; + foreach (float3 ff in cr.HullVertices) + { + verts[kk++] = ff; + } + + // add to the array one hull's worth of data + convHulls[jj++] = cr.HullIndices.Count; + convHulls[jj++] = 0f; // centroid x,y,z + convHulls[jj++] = 0f; + convHulls[jj++] = 0f; + foreach (int ind in cr.HullIndices) + { + convHulls[jj++] = verts[ind].x; + convHulls[jj++] = verts[ind].y; + convHulls[jj++] = verts[ind].z; + } } - // Make sure the properties are set on the new object - UpdatePhysicalParameters(); + // create the hull definition in Bullet + // m_log.DebugFormat("{0}: CreateGeom: calling CreateHull. lid={1}, key={2}, hulls={3}", LogHeader, _localID, _hullKey, hullCount); + BulletSimAPI.CreateHull(_scene.WorldID, _hullKey, hullCount, convHulls); + _shapeType = ShapeData.PhysicsShapeType.SHAPE_HULL; + // meshes are already scaled by the meshmerizer + _scale = new OMV.Vector3(1f, 1f, 1f); + // DetailLog("{0},BSPrim.CreateGeomHull,done", LocalID); + return; + } + + // Callback from convex hull creater with a newly created hull. + // Just add it to the collection of hulls for this shape. + private void HullReturn(ConvexResult result) + { + _hulls.Add(result); + return; + } + + // Create an object in Bullet if it has not already been created + // No locking here because this is done when the physics engine is not simulating + // Returns 'true' if an object was actually created. + private bool CreateObject() + { + // this routine is called when objects are rebuilt. + + // the mesh or hull must have already been created in Bullet + ShapeData shape; + FillShapeInfo(out shape); + // m_log.DebugFormat("{0}: CreateObject: lID={1}, shape={2}", LogHeader, _localID, shape.Type); + bool ret = BulletSimAPI.CreateObject(_scene.WorldID, shape); + + // the CreateObject() may have recreated the rigid body. Make sure we have the latest. + Body = new BulletBody(LocalID, BulletSimAPI.GetBodyHandle2(_scene.World.Ptr, LocalID)); + + return ret; + } + + // Copy prim's info into the BulletSim shape description structure + public void FillShapeInfo(out ShapeData shape) + { + shape.ID = _localID; + shape.Type = _shapeType; + shape.Position = _position; + shape.Rotation = _orientation; + shape.Velocity = _velocity; + shape.Scale = _scale; + shape.Mass = _isPhysical ? _mass : 0f; + shape.Buoyancy = _buoyancy; + shape.HullKey = _hullKey; + shape.MeshKey = _meshKey; + shape.Friction = _friction; + shape.Restitution = _restitution; + shape.Collidable = (!IsPhantom) ? ShapeData.numericTrue : ShapeData.numericFalse; + shape.Static = _isPhysical ? ShapeData.numericFalse : ShapeData.numericTrue; + } + + + // Rebuild the geometry and object. + // This is called when the shape changes so we need to recreate the mesh/hull. + // No locking here because this is done when the physics engine is not simulating + private void RecreateGeomAndObject() + { + // m_log.DebugFormat("{0}: RecreateGeomAndObject. lID={1}", LogHeader, _localID); + if (CreateGeom(true)) + CreateObject(); return; } @@ -1356,7 +1277,7 @@ public sealed class BSPrim : BSPhysObject const float ACCELERATION_TOLERANCE = 0.01f; const float ROTATIONAL_VELOCITY_TOLERANCE = 0.01f; - public override void UpdateProperties(EntityProperties entprop) + public void UpdateProperties(EntityProperties entprop) { /* UpdatedProperties changed = 0; @@ -1404,7 +1325,7 @@ public sealed class BSPrim : BSPhysObject // Don't check for damping here -- it's done in BulletSim and SceneObjectPart. // Updates only for individual prims and for the root object of a linkset. - if (Linkset.IsRoot(this)) + if (_linkset.IsRoot(this)) { // Assign to the local variables so the normal set action does not happen _position = entprop.Position; @@ -1413,32 +1334,69 @@ public sealed class BSPrim : BSPhysObject _acceleration = entprop.Acceleration; _rotationalVelocity = entprop.RotationalVelocity; - // remember the current and last set values - LastEntityProperties = CurrentEntityProperties; - CurrentEntityProperties = entprop; - - PositionSanityCheck(true); - - OMV.Vector3 direction = OMV.Vector3.UnitX * _orientation; - DetailLog("{0},BSPrim.UpdateProperties,call,pos={1},orient={2},dir={3},vel={4},rotVel={5}", - LocalID, _position, _orientation, direction, _velocity, _rotationalVelocity); - - // BulletSimAPI.DumpRigidBody2(PhysicsScene.World.ptr, BSBody.ptr); // DEBUG DEBUG DEBUG + // m_log.DebugFormat("{0}: RequestTerseUpdate. id={1}, ch={2}, pos={3}, rot={4}, vel={5}, acc={6}, rvel={7}", + // LogHeader, LocalID, changed, _position, _orientation, _velocity, _acceleration, _rotationalVelocity); + // DetailLog("{0},BSPrim.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5}", + // LocalID, _position, _orientation, _velocity, _acceleration, _rotationalVelocity); base.RequestPhysicsterseUpdate(); } /* else { - // For debugging, report the movement of children + // For debugging, we also report the movement of children DetailLog("{0},BSPrim.UpdateProperties,child,pos={1},orient={2},vel={3},accel={4},rotVel={5}", - LocalID, entprop.Position, entprop.Rotation, entprop.Velocity, + LocalID, entprop.Position, entprop.Rotation, entprop.Velocity, entprop.Acceleration, entprop.RotationalVelocity); } */ + } + + // I've collided with something + CollisionEventUpdate collisionCollection; + public void Collide(uint collidingWith, ActorTypes type, OMV.Vector3 contactPoint, OMV.Vector3 contactNormal, float pentrationDepth) + { + // m_log.DebugFormat("{0}: Collide: ms={1}, id={2}, with={3}", LogHeader, _subscribedEventsMs, LocalID, collidingWith); + + // The following lines make IsColliding() and IsCollidingGround() work + _collidingStep = _scene.SimulationStep; + if (collidingWith == BSScene.TERRAIN_ID || collidingWith == BSScene.GROUNDPLANE_ID) + { + _collidingGroundStep = _scene.SimulationStep; + } + + // DetailLog("{0},BSPrim.Collison,call,with={1}", LocalID, collidingWith); + + // if someone is subscribed to collision events.... + if (_subscribedEventsMs != 0) { + // throttle the collisions to the number of milliseconds specified in the subscription + int nowTime = _scene.SimulationNowTime; + if (nowTime >= _nextCollisionOkTime) { + _nextCollisionOkTime = nowTime + _subscribedEventsMs; - // The linkset implimentation might want to know about this. - Linkset.UpdateProperties(this); + if (collisionCollection == null) + collisionCollection = new CollisionEventUpdate(); + collisionCollection.AddCollider(collidingWith, new ContactPoint(contactPoint, contactNormal, pentrationDepth)); + } + } + } + + // The scene is telling us it's time to pass our collected collisions into the simulator + public void SendCollisions() + { + if (collisionCollection != null && collisionCollection.Count > 0) + { + base.SendCollisionUpdate(collisionCollection); + // The collisionCollection structure is passed around in the simulator. + // Make sure we don't have a handle to that one and that a new one is used next time. + collisionCollection = null; + } + } + + // Invoke the detailed logger and output something if it's enabled. + private void DetailLog(string msg, params Object[] args) + { + Scene.PhysicsLogging.Write(msg, args); } } } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs index 740f339..a31c578 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs @@ -39,88 +39,96 @@ using log4net; using OpenMetaverse; // TODOs for BulletSim (for BSScene, BSPrim, BSCharacter and BulletSim) -// Test sculpties (verified that they don't work) +// Debug linkset +// Test with multiple regions in one simulator +// Adjust character capsule size when height is adjusted (ScenePresence.SetHeight) +// Test sculpties // Compute physics FPS reasonably // Based on material, set density and friction -// Don't use constraints in linksets of non-physical objects. Means having to move children manually. +// More efficient memory usage when passing hull information from BSPrim to BulletSim +// Move all logic out of the C++ code and into the C# code for easier future modifications. // Four states of prim: Physical, regular, phantom and selected. Are we modeling these correctly? // In SL one can set both physical and phantom (gravity, does not effect others, makes collisions with ground) // At the moment, physical and phantom causes object to drop through the terrain // Physical phantom objects and related typing (collision options ) +// Use collision masks for collision with terrain and phantom objects // Check out llVolumeDetect. Must do something for that. -// Use collision masks for collision with terrain and phantom objects -// More efficient memory usage when passing hull information from BSPrim to BulletSim // Should prim.link() and prim.delink() membership checking happen at taint time? -// Mesh sharing. Use meshHash to tell if we already have a hull of that shape and only create once. +// changing the position and orientation of a linked prim must rebuild the constraint with the root. +// Mesh sharing. Use meshHash to tell if we already have a hull of that shape and only create once // Do attachments need to be handled separately? Need collision events. Do not collide with VolumeDetect +// Implement the genCollisions feature in BulletSim::SetObjectProperties (don't pass up unneeded collisions) // Implement LockAngularMotion // Decide if clearing forces is the right thing to do when setting position (BulletSim::SetObjectTranslation) +// Does NeedsMeshing() really need to exclude all the different shapes? // Remove mesh and Hull stuff. Use mesh passed to bullet and use convexdecom from bullet. // Add PID movement operations. What does ScenePresence.MoveToTarget do? // Check terrain size. 128 or 127? // Raycast -// +// namespace OpenSim.Region.Physics.BulletSPlugin { -public sealed class BSScene : PhysicsScene, IPhysicsParameters +public class BSScene : PhysicsScene, IPhysicsParameters { private static readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); private static readonly string LogHeader = "[BULLETS SCENE]"; - // The name of the region we're working for. - public string RegionName { get; private set; } + public void DebugLog(string mm, params Object[] xx) { if (ShouldDebugLog) m_log.DebugFormat(mm, xx); } public string BulletSimVersion = "?"; - public Dictionary PhysObjects; - public BSShapeCollection Shapes; - - // Keeping track of the objects with collisions so we can report begin and end of a collision - public HashSet ObjectsWithCollisions = new HashSet(); - public HashSet ObjectsWithNoMoreCollisions = new HashSet(); - // Keep track of all the avatars so we can send them a collision event - // every tick so OpenSim will update its animation. - private HashSet m_avatars = new HashSet(); - - // List of all the objects that have vehicle properties and should be called - // to update each physics step. - private List m_vehicles = new List(); + private Dictionary m_avatars = new Dictionary(); + private Dictionary m_prims = new Dictionary(); + private HashSet m_avatarsWithCollisions = new HashSet(); + private HashSet m_primsWithCollisions = new HashSet(); + private List m_vehicles = new List(); + private float[] m_heightMap; + private float m_waterLevel; + private uint m_worldID; + public uint WorldID { get { return m_worldID; } } // let my minuions use my logger public ILog Logger { get { return m_log; } } - public IMesher mesher; - // Level of Detail values kept as float because that's what the Meshmerizer wants - public float MeshLOD { get; private set; } - public float MeshMegaPrimLOD { get; private set; } - public float MeshMegaPrimThreshold { get; private set; } - public float SculptLOD { get; private set; } + private bool m_initialized = false; - public uint WorldID { get; private set; } - public BulletSim World { get; private set; } + private int m_detailedStatsStep = 0; + + public IMesher mesher; + private float m_meshLOD; + public float MeshLOD + { + get { return m_meshLOD; } + } + private float m_sculptLOD; + public float SculptLOD + { + get { return m_sculptLOD; } + } - // All the constraints that have been allocated in this instance. - public BSConstraintCollection Constraints { get; private set; } + private BulletSim m_worldSim; + public BulletSim World + { + get { return m_worldSim; } + } + private BSConstraintCollection m_constraintCollection; + public BSConstraintCollection Constraints + { + get { return m_constraintCollection; } + } - // Simulation parameters private int m_maxSubSteps; private float m_fixedTimeStep; private long m_simulationStep = 0; public long SimulationStep { get { return m_simulationStep; } } - private int m_taintsToProcessPerStep; + + public float LastSimulatedTimestep { get; private set; } // A value of the time now so all the collision and update routines do not have to get their own // Set to 'now' just before all the prims and actors are called for collisions and updates - public int SimulationNowTime { get; private set; } - - // True if initialized and ready to do simulation steps - private bool m_initialized = false; - - // Flag which is true when processing taints. - // Not guaranteed to be correct all the time (don't depend on this) but good for debugging. - public bool InTaintTime { get; private set; } + private int m_simulationNowTime; + public int SimulationNowTime { get { return m_simulationNowTime; } } - // Pinned memory used to pass step information between managed and unmanaged private int m_maxCollisionsPerFrame; private CollisionDesc[] m_collisionArray; private GCHandle m_collisionArrayPinnedHandle; @@ -129,19 +137,14 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters private EntityProperties[] m_updateArray; private GCHandle m_updateArrayPinnedHandle; - public bool ShouldMeshSculptedPrim { get; private set; } // cause scuplted prims to get meshed - public bool ShouldForceSimplePrimMeshing { get; private set; } // if a cube or sphere, let Bullet do internal shapes - public bool ShouldUseHullsForPhysicalObjects { get; private set; } // 'true' if should create hulls for physical objects + private bool _meshSculptedPrim = true; // cause scuplted prims to get meshed + private bool _forceSimplePrimMeshing = false; // if a cube or sphere, let Bullet do internal shapes public float PID_D { get; private set; } // derivative public float PID_P { get; private set; } // proportional public const uint TERRAIN_ID = 0; // OpenSim senses terrain with a localID of zero public const uint GROUNDPLANE_ID = 1; - public const uint CHILDTERRAIN_ID = 2; // Terrain allocated based on our mega-prim childre start here - - private float m_waterLevel; - public BSTerrainManager TerrainManager { get; private set; } public ConfigurationParameters Params { @@ -151,18 +154,13 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters { get { return new Vector3(0f, 0f, Params.gravity); } } - // Just the Z value of the gravity - public float DefaultGravityZ + + private float m_maximumObjectMass; + public float MaximumObjectMass { - get { return Params.gravity; } + get { return m_maximumObjectMass; } } - public float MaximumObjectMass { get; private set; } - - // When functions in the unmanaged code must be called, it is only - // done at a known time just before the simulation step. The taint - // system saves all these function calls and executes them in - // order before the simulation. public delegate void TaintCallback(); private struct TaintCallbackEntry { @@ -174,19 +172,15 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters callback = c; } } - private Object _taintLock = new Object(); // lock for using the next object - private List _taintOperations; - private Dictionary _postTaintOperations; - private List _postStepOperations; + private List _taintedObjects; + private Object _taintLock = new Object(); // A pointer to an instance if this structure is passed to the C++ code - // Used to pass basic configuration values to the unmanaged code. ConfigurationParameters[] m_params; GCHandle m_paramsHandle; - // Handle to the callback used by the unmanaged code to call into the managed code. - // Used for debug logging. - // Need to store the handle in a persistant variable so it won't be freed. + public bool ShouldDebugLog { get; private set; } + private BulletSimAPI.DebugLogCallback m_DebugLogCallbackHandle; // Sometimes you just have to log everything. @@ -195,26 +189,17 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters private string m_physicsLoggingDir; private string m_physicsLoggingPrefix; private int m_physicsLoggingFileMinutes; - // 'true' of the vehicle code is to log lots of details - public bool VehicleLoggingEnabled { get; private set; } - #region Construction and Initialization + private bool m_vehicleLoggingEnabled; + public bool VehicleLoggingEnabled { get { return m_vehicleLoggingEnabled; } } + public BSScene(string identifier) { m_initialized = false; - // we are passed the name of the region we're working for. - RegionName = identifier; } public override void Initialise(IMesher meshmerizer, IConfigSource config) { - mesher = meshmerizer; - _taintOperations = new List(); - _postTaintOperations = new Dictionary(); - _postStepOperations = new List(); - PhysObjects = new Dictionary(); - Shapes = new BSShapeCollection(this); - // Allocate pinned memory to pass parameters. m_params = new ConfigurationParameters[1]; m_paramsHandle = GCHandle.Alloc(m_params, GCHandleType.Pinned); @@ -230,7 +215,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters // Enable very detailed logging. // By creating an empty logger when not logging, the log message invocation code - // can be left in and every call doesn't have to check for null. + // can be left in and every call doesn't have to check for null. if (m_physicsLoggingEnabled) { PhysicsLogging = new Logging.LogWriter(m_physicsLoggingDir, m_physicsLoggingPrefix, m_physicsLoggingFileMinutes); @@ -240,43 +225,39 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters PhysicsLogging = new Logging.LogWriter(); } - // If Debug logging level, enable logging from the unmanaged code - m_DebugLogCallbackHandle = null; + // Get the version of the DLL + // TODO: this doesn't work yet. Something wrong with marshaling the returned string. + // BulletSimVersion = BulletSimAPI.GetVersion(); + // m_log.WarnFormat("{0}: BulletSim.dll version='{1}'", LogHeader, BulletSimVersion); + + // if Debug, enable logging from the unmanaged code if (m_log.IsDebugEnabled || PhysicsLogging.Enabled) { m_log.DebugFormat("{0}: Initialize: Setting debug callback for unmanaged code", LogHeader); if (PhysicsLogging.Enabled) - // The handle is saved in a variable to make sure it doesn't get freed after this call m_DebugLogCallbackHandle = new BulletSimAPI.DebugLogCallback(BulletLoggerPhysLog); else m_DebugLogCallbackHandle = new BulletSimAPI.DebugLogCallback(BulletLogger); + // the handle is saved in a variable to make sure it doesn't get freed after this call + BulletSimAPI.SetDebugLogCallback(m_DebugLogCallbackHandle); } - // Get the version of the DLL - // TODO: this doesn't work yet. Something wrong with marshaling the returned string. - // BulletSimVersion = BulletSimAPI.GetVersion(); - // m_log.WarnFormat("{0}: BulletSim.dll version='{1}'", LogHeader, BulletSimVersion); + _taintedObjects = new List(); - // The bounding box for the simulated world. The origin is 0,0,0 unless we're - // a child in a mega-region. - // Bullet actually doesn't care about the extents of the simulated - // area. It tracks active objects no matter where they are. - Vector3 worldExtent = new Vector3(Constants.RegionSize, Constants.RegionSize, Constants.RegionHeight); + mesher = meshmerizer; + // The bounding box for the simulated world + Vector3 worldExtent = new Vector3(Constants.RegionSize, Constants.RegionSize, 8192f); // m_log.DebugFormat("{0}: Initialize: Calling BulletSimAPI.Initialize.", LogHeader); - World = new BulletSim(0, this, BulletSimAPI.Initialize2(worldExtent, m_paramsHandle.AddrOfPinnedObject(), + m_worldID = BulletSimAPI.Initialize(worldExtent, m_paramsHandle.AddrOfPinnedObject(), m_maxCollisionsPerFrame, m_collisionArrayPinnedHandle.AddrOfPinnedObject(), - m_maxUpdatesPerFrame, m_updateArrayPinnedHandle.AddrOfPinnedObject(), - m_DebugLogCallbackHandle)); - - Constraints = new BSConstraintCollection(World); + m_maxUpdatesPerFrame, m_updateArrayPinnedHandle.AddrOfPinnedObject()); - TerrainManager = new BSTerrainManager(this); - TerrainManager.CreateInitialGroundPlaneAndTerrain(); + // Initialization to support the transition to a new API which puts most of the logic + // into the C# code so it is easier to modify and add to. + m_worldSim = new BulletSim(m_worldID, this, BulletSimAPI.GetSimHandle2(m_worldID)); + m_constraintCollection = new BSConstraintCollection(World); - m_log.WarnFormat("{0} Linksets implemented with {1}", LogHeader, (BSLinkset.LinksetImplementation)Params.linksetImplementation); - - InTaintTime = false; m_initialized = true; } @@ -300,13 +281,10 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters // Very detailed logging for physics debugging m_physicsLoggingEnabled = pConfig.GetBoolean("PhysicsLoggingEnabled", false); m_physicsLoggingDir = pConfig.GetString("PhysicsLoggingDir", "."); - m_physicsLoggingPrefix = pConfig.GetString("PhysicsLoggingPrefix", "physics-%REGIONNAME%-"); + m_physicsLoggingPrefix = pConfig.GetString("PhysicsLoggingPrefix", "physics-"); m_physicsLoggingFileMinutes = pConfig.GetInt("PhysicsLoggingFileMinutes", 5); // Very detailed logging for vehicle debugging - VehicleLoggingEnabled = pConfig.GetBoolean("VehicleLoggingEnabled", false); - - // Do any replacements in the parameters - m_physicsLoggingPrefix = m_physicsLoggingPrefix.Replace("%REGIONNAME%", RegionName); + m_vehicleLoggingEnabled = pConfig.GetBoolean("VehicleLoggingEnabled", false); } } } @@ -331,50 +309,12 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters { m_log.Debug("[BULLETS UNMANAGED]:" + msg); } - + // Called directly from unmanaged code so don't do much private void BulletLoggerPhysLog(string msg) { - DetailLog("[BULLETS UNMANAGED]:" + msg); - } - - public override void Dispose() - { - // m_log.DebugFormat("{0}: Dispose()", LogHeader); - - // make sure no stepping happens while we're deleting stuff - m_initialized = false; - - TerrainManager.ReleaseGroundPlaneAndTerrain(); - - foreach (KeyValuePair kvp in PhysObjects) - { - kvp.Value.Destroy(); - } - PhysObjects.Clear(); - - // Now that the prims are all cleaned up, there should be no constraints left - if (Constraints != null) - { - Constraints.Dispose(); - Constraints = null; - } - - if (Shapes != null) - { - Shapes.Dispose(); - Shapes = null; - } - - // Anything left in the unmanaged code should be cleaned out - BulletSimAPI.Shutdown2(World.ptr); - - // Not logging any more - PhysicsLogging.Close(); + PhysicsLogging.Write("[BULLETS UNMANAGED]:" + msg); } - #endregion // Construction and Initialization - - #region Prim and Avatar addition and removal public override PhysicsActor AddAvatar(string avName, Vector3 position, Vector3 size, bool isFlying) { @@ -389,13 +329,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters if (!m_initialized) return null; BSCharacter actor = new BSCharacter(localID, avName, this, position, size, isFlying); - lock (PhysObjects) PhysObjects.Add(localID, actor); - - // TODO: Remove kludge someday. - // We must generate a collision for avatars whether they collide or not. - // This is required by OpenSim to update avatar animations, etc. - lock (m_avatars) m_avatars.Add(actor); - + lock (m_avatars) m_avatars.Add(localID, actor); return actor; } @@ -410,9 +344,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters { try { - lock (PhysObjects) PhysObjects.Remove(actor.LocalID); - // Remove kludge someday - lock (m_avatars) m_avatars.Remove(bsactor); + lock (m_avatars) m_avatars.Remove(actor.LocalID); } catch (Exception e) { @@ -430,11 +362,11 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters BSPrim bsprim = prim as BSPrim; if (bsprim != null) { - DetailLog("{0},RemovePrim,call", bsprim.LocalID); + // DetailLog("{0},RemovePrim,call", bsprim.LocalID); // m_log.DebugFormat("{0}: RemovePrim. id={1}/{2}", LogHeader, bsprim.Name, bsprim.LocalID); try { - lock (PhysObjects) PhysObjects.Remove(bsprim.LocalID); + lock (m_prims) m_prims.Remove(bsprim.LocalID); } catch (Exception e) { @@ -456,21 +388,18 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters if (!m_initialized) return null; - DetailLog("{0},AddPrimShape,call", localID); + // DetailLog("{0},AddPrimShape,call", localID); BSPrim prim = new BSPrim(localID, primName, this, position, size, rotation, pbs, isPhysical); - lock (PhysObjects) PhysObjects.Add(localID, prim); + lock (m_prims) m_prims.Add(localID, prim); return prim; } // This is a call from the simulator saying that some physical property has been updated. - // The BulletSim driver senses the changing of relevant properties so this taint + // The BulletSim driver senses the changing of relevant properties so this taint // information call is not needed. public override void AddPhysicsActorTaint(PhysicsActor prim) { } - #endregion // Prim and Avatar addition and removal - - #region Simulation // Simulate one timestep public override float Simulate(float timeStep) { @@ -479,45 +408,34 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters int collidersCount = 0; IntPtr collidersPtr; - int beforeTime = 0; - int simTime = 0; + LastSimulatedTimestep = timeStep; // prevent simulation until we've been initialized - if (!m_initialized) return 5.0f; + if (!m_initialized) return 10.0f; + + int simulateStartTime = Util.EnvironmentTickCount(); // update the prim states while we know the physics engine is not busy - int numTaints = _taintOperations.Count; ProcessTaints(); // Some of the prims operate with special vehicle properties ProcessVehicles(timeStep); - numTaints += _taintOperations.Count; ProcessTaints(); // the vehicles might have added taints // step the physical world one interval m_simulationStep++; int numSubSteps = 0; - try { - // DumpVehicles(); // DEBUG - if (PhysicsLogging.Enabled) beforeTime = Util.EnvironmentTickCount(); - - numSubSteps = BulletSimAPI.PhysicsStep2(World.ptr, timeStep, m_maxSubSteps, m_fixedTimeStep, + numSubSteps = BulletSimAPI.PhysicsStep(m_worldID, timeStep, m_maxSubSteps, m_fixedTimeStep, out updatedEntityCount, out updatedEntitiesPtr, out collidersCount, out collidersPtr); - - if (PhysicsLogging.Enabled) simTime = Util.EnvironmentTickCountSubtract(beforeTime); - DetailLog("{0},Simulate,call, frame={1}, nTaints={2}, simTime={3}, substeps={4}, updates={5}, colliders={6}", - DetailLogZero, m_simulationStep, numTaints, simTime, numSubSteps, updatedEntityCount, collidersCount); - // DumpVehicles(); // DEBUG + // DetailLog("{0},Simulate,call, substeps={1}, updates={2}, colliders={3}", DetailLogZero, numSubSteps, updatedEntityCount, collidersCount); } catch (Exception e) { - m_log.WarnFormat("{0},PhysicsStep Exception: nTaints={1}, substeps={2}, updates={3}, colliders={4}, e={5}", - LogHeader, numTaints, numSubSteps, updatedEntityCount, collidersCount, e); - DetailLog("{0},PhysicsStepException,call, nTaints={1}, substeps={2}, updates={3}, colliders={4}", - DetailLogZero, numTaints, numSubSteps, updatedEntityCount, collidersCount); - updatedEntityCount = 0; + m_log.WarnFormat("{0},PhysicsStep Exception: substeps={1}, updates={2}, colliders={3}, e={4}", LogHeader, numSubSteps, updatedEntityCount, collidersCount, e); + // DetailLog("{0},PhysicsStepException,call, substeps={1}, updates={2}, colliders={3}", DetailLogZero, numSubSteps, updatedEntityCount, collidersCount); + // updatedEntityCount = 0; collidersCount = 0; } @@ -525,7 +443,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters // Don't have to use the pointers passed back since we know it is the same pinned memory we passed in // Get a value for 'now' so all the collision and update routines don't have to get their own - SimulationNowTime = Util.EnvironmentTickCount(); + m_simulationNowTime = Util.EnvironmentTickCount(); // If there were collisions, process them by sending the event to the prim. // Collisions must be processed before updates. @@ -544,32 +462,19 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters // The above SendCollision's batch up the collisions on the objects. // Now push the collisions into the simulator. - if (ObjectsWithCollisions.Count > 0) - { - foreach (BSPhysObject bsp in ObjectsWithCollisions) - if (!bsp.SendCollisions()) - { - // If the object is done colliding, see that it's removed from the colliding list - ObjectsWithNoMoreCollisions.Add(bsp); - } - } - - // This is a kludge to get avatar movement updates. - // The simulator expects collisions for avatars even if there are have been no collisions. - // The event updates avatar animations and stuff. - // If you fix avatar animation updates, remove this overhead and let normal collision processing happen. - foreach (BSPhysObject bsp in m_avatars) - if (!ObjectsWithCollisions.Contains(bsp)) // don't call avatars twice - bsp.SendCollisions(); - - // Objects that are done colliding are removed from the ObjectsWithCollisions list. - // Not done above because it is inside an iteration of ObjectWithCollisions. - if (ObjectsWithNoMoreCollisions.Count > 0) - { - foreach (BSPhysObject po in ObjectsWithNoMoreCollisions) - ObjectsWithCollisions.Remove(po); - ObjectsWithNoMoreCollisions.Clear(); - } + foreach (BSPrim bsp in m_primsWithCollisions) + bsp.SendCollisions(); + m_primsWithCollisions.Clear(); + + // This is a kludge to get avatar movement updated. + // Don't send collisions only if there were collisions -- send everytime. + // ODE sends collisions even if there are none and this is used to update + // avatar animations and stuff. + // foreach (BSCharacter bsc in m_avatarsWithCollisions) + // bsc.SendCollisions(); + foreach (KeyValuePair kvp in m_avatars) + kvp.Value.SendCollisions(); + m_avatarsWithCollisions.Clear(); // If any of the objects had updated properties, tell the object it has been changed by the physics engine if (updatedEntityCount > 0) @@ -577,310 +482,320 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters for (int ii = 0; ii < updatedEntityCount; ii++) { EntityProperties entprop = m_updateArray[ii]; - BSPhysObject pobj; - if (PhysObjects.TryGetValue(entprop.ID, out pobj)) + BSPrim prim; + if (m_prims.TryGetValue(entprop.ID, out prim)) + { + prim.UpdateProperties(entprop); + continue; + } + BSCharacter actor; + if (m_avatars.TryGetValue(entprop.ID, out actor)) { - pobj.UpdateProperties(entprop); + actor.UpdateProperties(entprop); + continue; } } } - ProcessPostStepTaints(); - - // This causes the unmanaged code to output ALL the values found in ALL the objects in the world. - // Only enable this in a limited test world with few objects. - // BulletSimAPI.DumpAllInfo2(World.ptr); // DEBUG DEBUG DEBUG + // If enabled, call into the physics engine to dump statistics + if (m_detailedStatsStep > 0) + { + if ((m_simulationStep % m_detailedStatsStep) == 0) + { + BulletSimAPI.DumpBulletStatistics(); + } + } - // The physics engine returns the number of milliseconds it simulated this call. - // These are summed and normalized to one second and divided by 1000 to give the reported physics FPS. - // We multiply by 55 to give a recognizable running rate (55 or less). - return numSubSteps * m_fixedTimeStep * 1000 * 55; - // return timeStep * 1000 * 55; + // this is a waste since the outside routine also calcuates the physics simulation + // period. TODO: There should be a way of computing physics frames from simulator computation. + // long simulateTotalTime = Util.EnvironmentTickCountSubtract(simulateStartTime); + // return (timeStep * (float)simulateTotalTime); + + // TODO: FIX THIS: fps calculation possibly wrong. + // This calculation says 1/timeStep is the ideal frame rate. Any time added to + // that by the physics simulation gives a slower frame rate. + long totalSimulationTime = Util.EnvironmentTickCountSubtract(simulateStartTime); + if (totalSimulationTime >= timeStep) + return 0; + return 1f / (timeStep + totalSimulationTime); } // Something has collided - private void SendCollision(uint localID, uint collidingWith, Vector3 collidePoint, Vector3 collideNormal, float penetration) + private void SendCollision(uint localID, uint collidingWith, Vector3 collidePoint, Vector3 collideNormal, float penitration) { - if (localID <= TerrainManager.HighestTerrainID) + if (localID == TERRAIN_ID || localID == GROUNDPLANE_ID) { return; // don't send collisions to the terrain } - BSPhysObject collider; - if (!PhysObjects.TryGetValue(localID, out collider)) - { - // If the object that is colliding cannot be found, just ignore the collision. - DetailLog("{0},BSScene.SendCollision,colliderNotInObjectList,id={1},with={2}", DetailLogZero, localID, collidingWith); + ActorTypes type = ActorTypes.Prim; + if (collidingWith == TERRAIN_ID || collidingWith == GROUNDPLANE_ID) + type = ActorTypes.Ground; + else if (m_avatars.ContainsKey(collidingWith)) + type = ActorTypes.Agent; + + BSPrim prim; + if (m_prims.TryGetValue(localID, out prim)) { + prim.Collide(collidingWith, type, collidePoint, collideNormal, penitration); + m_primsWithCollisions.Add(prim); return; } - - // The terrain is not in the physical object list so 'collidee' can be null when Collide() is called. - BSPhysObject collidee = null; - PhysObjects.TryGetValue(collidingWith, out collidee); - - // DetailLog("{0},BSScene.SendCollision,collide,id={1},with={2}", DetailLogZero, localID, collidingWith); - - if (collider.Collide(collidingWith, collidee, collidePoint, collideNormal, penetration)) - { - // If a collision was posted, remember to send it to the simulator - ObjectsWithCollisions.Add(collider); + BSCharacter actor; + if (m_avatars.TryGetValue(localID, out actor)) { + actor.Collide(collidingWith, type, collidePoint, collideNormal, penitration); + m_avatarsWithCollisions.Add(actor); + return; } - return; } - #endregion // Simulation - public override void GetResults() { } - #region Terrain - public override void SetTerrain(float[] heightMap) { - TerrainManager.SetTerrain(heightMap); + m_heightMap = heightMap; + this.TaintedObject("BSScene.SetTerrain", delegate() + { + BulletSimAPI.SetHeightmap(m_worldID, m_heightMap); + }); } - public override void SetWaterLevel(float baseheight) + // Someday we will have complex terrain with caves and tunnels + // For the moment, it's flat and convex + public float GetTerrainHeightAtXYZ(Vector3 loc) { - m_waterLevel = baseheight; - } - // Someday.... - public float GetWaterLevelAtXYZ(Vector3 loc) - { - return m_waterLevel; + return GetTerrainHeightAtXY(loc.X, loc.Y); } - public override void DeleteTerrain() + public float GetTerrainHeightAtXY(float tX, float tY) { - // m_log.DebugFormat("{0}: DeleteTerrain()", LogHeader); + if (tX < 0 || tX >= Constants.RegionSize || tY < 0 || tY >= Constants.RegionSize) + return 30; + return m_heightMap[((int)tX) * Constants.RegionSize + ((int)tY)]; } - // Although no one seems to check this, I do support combining. - public override bool SupportsCombining() + public override void SetWaterLevel(float baseheight) { - return TerrainManager.SupportsCombining(); + m_waterLevel = baseheight; + // TODO: pass to physics engine so things will float? } - // This call says I am a child to region zero in a mega-region. 'pScene' is that - // of region zero, 'offset' is my offset from regions zero's origin, and - // 'extents' is the largest XY that is handled in my region. - public override void Combine(PhysicsScene pScene, Vector3 offset, Vector3 extents) + public float GetWaterLevel() { - TerrainManager.Combine(pScene, offset, extents); + return m_waterLevel; } - // Unhook all the combining that I know about. - public override void UnCombine(PhysicsScene pScene) + public override void DeleteTerrain() { - TerrainManager.UnCombine(pScene); + // m_log.DebugFormat("{0}: DeleteTerrain()", LogHeader); } - #endregion // Terrain - - public override Dictionary GetTopColliders() + public override void Dispose() { - return new Dictionary(); - } + // m_log.DebugFormat("{0}: Dispose()", LogHeader); - public override bool IsThreaded { get { return false; } } + // make sure no stepping happens while we're deleting stuff + m_initialized = false; - #region Taints + foreach (KeyValuePair kvp in m_avatars) + { + kvp.Value.Destroy(); + } + m_avatars.Clear(); - // Calls to the PhysicsActors can't directly call into the physics engine - // because it might be busy. We delay changes to a known time. - // We rely on C#'s closure to save and restore the context for the delegate. - public void TaintedObject(String ident, TaintCallback callback) - { - if (!m_initialized) return; + foreach (KeyValuePair kvp in m_prims) + { + kvp.Value.Destroy(); + } + m_prims.Clear(); - lock (_taintLock) + // Now that the prims are all cleaned up, there should be no constraints left + if (m_constraintCollection != null) { - _taintOperations.Add(new TaintCallbackEntry(ident, callback)); + m_constraintCollection.Dispose(); + m_constraintCollection = null; } - return; - } + // Anything left in the unmanaged code should be cleaned out + BulletSimAPI.Shutdown(WorldID); - // Sometimes a potentially tainted operation can be used in and out of taint time. - // This routine executes the command immediately if in taint-time otherwise it is queued. - public void TaintedObject(bool inTaintTime, string ident, TaintCallback callback) - { - if (inTaintTime) - callback(); - else - TaintedObject(ident, callback); + // Not logging any more + PhysicsLogging.Close(); } - // When someone tries to change a property on a BSPrim or BSCharacter, the object queues - // a callback into itself to do the actual property change. That callback is called - // here just before the physics engine is called to step the simulation. - public void ProcessTaints() + public override Dictionary GetTopColliders() { - InTaintTime = true; - ProcessRegularTaints(); - ProcessPostTaintTaints(); - InTaintTime = false; + return new Dictionary(); } - private void ProcessRegularTaints() + public override bool IsThreaded { get { return false; } } + + /// + /// Routine to figure out if we need to mesh this prim with our mesher + /// + /// + /// true if the prim needs meshing + public bool NeedsMeshing(PrimitiveBaseShape pbs) { - if (_taintOperations.Count > 0) // save allocating new list if there is nothing to process + // most of this is redundant now as the mesher will return null if it cant mesh a prim + // but we still need to check for sculptie meshing being enabled so this is the most + // convenient place to do it for now... + + // int iPropertiesNotSupportedDefault = 0; + + if (pbs.SculptEntry && !_meshSculptedPrim) { - int taintCount = m_taintsToProcessPerStep; - TaintCallbackEntry oneCallback = new TaintCallbackEntry(); - while (_taintOperations.Count > 0 && taintCount-- > 0) + // Render sculpties as boxes + return false; + } + + // if it's a standard box or sphere with no cuts, hollows, twist or top shear, return false since Bullet + // can use an internal representation for the prim + if (!_forceSimplePrimMeshing) + { + if ((pbs.ProfileShape == ProfileShape.Square && pbs.PathCurve == (byte)Extrusion.Straight) + || (pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1 + && pbs.Scale.X == pbs.Scale.Y && pbs.Scale.Y == pbs.Scale.Z)) { - bool gotOne = false; - lock (_taintLock) - { - if (_taintOperations.Count > 0) - { - oneCallback = _taintOperations[0]; - _taintOperations.RemoveAt(0); - gotOne = true; - } - } - if (gotOne) + + if (pbs.ProfileBegin == 0 && pbs.ProfileEnd == 0 + && pbs.ProfileHollow == 0 + && pbs.PathTwist == 0 && pbs.PathTwistBegin == 0 + && pbs.PathBegin == 0 && pbs.PathEnd == 0 + && pbs.PathTaperX == 0 && pbs.PathTaperY == 0 + && pbs.PathScaleX == 100 && pbs.PathScaleY == 100 + && pbs.PathShearX == 0 && pbs.PathShearY == 0) { - try - { - DetailLog("{0},BSScene.ProcessTaints,doTaint,id={1}", DetailLogZero, oneCallback.ident); - oneCallback.callback(); - } - catch (Exception e) - { - DetailLog("{0},BSScene.ProcessTaints,doTaintException,id={1}", DetailLogZero, oneCallback.ident); // DEBUG DEBUG DEBUG - m_log.ErrorFormat("{0}: ProcessTaints: {1}: Exception: {2}", LogHeader, oneCallback.ident, e); - } + return false; } } - /* - // swizzle a new list into the list location so we can process what's there - List oldList; - lock (_taintLock) + } + + /* TODO: verify that the mesher will now do all these shapes + if (pbs.ProfileHollow != 0) + iPropertiesNotSupportedDefault++; + + if ((pbs.PathBegin != 0) || pbs.PathEnd != 0) + iPropertiesNotSupportedDefault++; + + if ((pbs.PathTwistBegin != 0) || (pbs.PathTwist != 0)) + iPropertiesNotSupportedDefault++; + + if ((pbs.ProfileBegin != 0) || pbs.ProfileEnd != 0) + iPropertiesNotSupportedDefault++; + + if ((pbs.PathScaleX != 100) || (pbs.PathScaleY != 100)) + iPropertiesNotSupportedDefault++; + + if ((pbs.PathShearX != 0) || (pbs.PathShearY != 0)) + iPropertiesNotSupportedDefault++; + + if (pbs.ProfileShape == ProfileShape.Circle && pbs.PathCurve == (byte)Extrusion.Straight) + iPropertiesNotSupportedDefault++; + + if (pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1 && (pbs.Scale.X != pbs.Scale.Y || pbs.Scale.Y != pbs.Scale.Z || pbs.Scale.Z != pbs.Scale.X)) + iPropertiesNotSupportedDefault++; + + if (pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte) Extrusion.Curve1) + iPropertiesNotSupportedDefault++; + + // test for torus + if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.Square) + { + if (pbs.PathCurve == (byte)Extrusion.Curve1) { - oldList = _taintedObjects; - _taintedObjects = new List(); + iPropertiesNotSupportedDefault++; } - - foreach (TaintCallbackEntry tcbe in oldList) + } + else if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.Circle) + { + if (pbs.PathCurve == (byte)Extrusion.Straight) { - try - { - DetailLog("{0},BSScene.ProcessTaints,doTaint,id={1}", DetailLogZero, tcbe.ident); // DEBUG DEBUG DEBUG - tcbe.callback(); - } - catch (Exception e) - { - m_log.ErrorFormat("{0}: ProcessTaints: {1}: Exception: {2}", LogHeader, tcbe.ident, e); - } + iPropertiesNotSupportedDefault++; + } + // ProfileCurve seems to combine hole shape and profile curve so we need to only compare against the lower 3 bits + else if (pbs.PathCurve == (byte)Extrusion.Curve1) + { + iPropertiesNotSupportedDefault++; } - oldList.Clear(); - */ } - } - - // Schedule an update to happen after all the regular taints are processed. - // Note that new requests for the same operation ("ident") for the same object ("ID") - // will replace any previous operation by the same object. - public void PostTaintObject(String ident, uint ID, TaintCallback callback) - { - if (!m_initialized) return; - - string uniqueIdent = ident + "-" + ID.ToString(); - lock (_taintLock) + else if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.HalfCircle) { - _postTaintOperations[uniqueIdent] = new TaintCallbackEntry(uniqueIdent, callback); + if (pbs.PathCurve == (byte)Extrusion.Curve1 || pbs.PathCurve == (byte)Extrusion.Curve2) + { + iPropertiesNotSupportedDefault++; + } } - - return; - } - - private void ProcessPostTaintTaints() - { - if (_postTaintOperations.Count > 0) + else if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.EquilateralTriangle) { - Dictionary oldList; - lock (_taintLock) + if (pbs.PathCurve == (byte)Extrusion.Straight) { - oldList = _postTaintOperations; - _postTaintOperations = new Dictionary(); + iPropertiesNotSupportedDefault++; } - - foreach (KeyValuePair kvp in oldList) + else if (pbs.PathCurve == (byte)Extrusion.Curve1) { - try - { - DetailLog("{0},BSScene.ProcessPostTaintTaints,doTaint,id={1}", DetailLogZero, kvp.Key); // DEBUG DEBUG DEBUG - kvp.Value.callback(); - } - catch (Exception e) - { - m_log.ErrorFormat("{0}: ProcessPostTaintTaints: {1}: Exception: {2}", LogHeader, kvp.Key, e); - } + iPropertiesNotSupportedDefault++; } - oldList.Clear(); } + if (iPropertiesNotSupportedDefault == 0) + { + return false; + } + */ + return true; } - public void PostStepTaintObject(String ident, TaintCallback callback) + // Calls to the PhysicsActors can't directly call into the physics engine + // because it might be busy. We delay changes to a known time. + // We rely on C#'s closure to save and restore the context for the delegate. + public void TaintedObject(String ident, TaintCallback callback) { if (!m_initialized) return; lock (_taintLock) - { - _postStepOperations.Add(new TaintCallbackEntry(ident, callback)); - } - + _taintedObjects.Add(new TaintCallbackEntry(ident, callback)); return; } - private void ProcessPostStepTaints() + // When someone tries to change a property on a BSPrim or BSCharacter, the object queues + // a callback into itself to do the actual property change. That callback is called + // here just before the physics engine is called to step the simulation. + public void ProcessTaints() { - if (_postStepOperations.Count > 0) + if (_taintedObjects.Count > 0) // save allocating new list if there is nothing to process { + // swizzle a new list into the list location so we can process what's there List oldList; lock (_taintLock) { - oldList = _postStepOperations; - _postStepOperations = new List(); + oldList = _taintedObjects; + _taintedObjects = new List(); } foreach (TaintCallbackEntry tcbe in oldList) { try { - DetailLog("{0},BSScene.ProcessPostStepTaints,doTaint,id={1}", DetailLogZero, tcbe.ident); // DEBUG DEBUG DEBUG tcbe.callback(); } catch (Exception e) { - m_log.ErrorFormat("{0}: ProcessPostStepTaints: {1}: Exception: {2}", LogHeader, tcbe.ident, e); + m_log.ErrorFormat("{0}: ProcessTaints: {1}: Exception: {2}", LogHeader, tcbe.ident, e); } } oldList.Clear(); } } - public bool AssertInTaintTime(string whereFrom) - { - if (!InTaintTime) - { - DetailLog("{0},BSScene.AssertInTaintTime,NOT IN TAINT TIME,Region={1},Where={2}", DetailLogZero, RegionName, whereFrom); - m_log.ErrorFormat("{0} NOT IN TAINT TIME!! Region={1}, Where={2}", LogHeader, RegionName, whereFrom); - Util.PrintCallStack(); - } - return InTaintTime; - } - - #endregion // Taints - #region Vehicles public void VehicleInSceneTypeChanged(BSPrim vehic, Vehicle newType) { - RemoveVehiclePrim(vehic); - if (newType != Vehicle.TYPE_NONE) + if (newType == Vehicle.TYPE_NONE) { - // make it so the scene will call us each tick to do vehicle things + RemoveVehiclePrim(vehic); + } + else + { + // make it so the scene will call us each tick to do vehicle things AddVehiclePrim(vehic); } } @@ -912,22 +827,21 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters } // Some prims have extra vehicle actions - // Called at taint time! + // no locking because only called when physics engine is not busy private void ProcessVehicles(float timeStep) { - foreach (BSPhysObject pobj in m_vehicles) + foreach (BSPrim prim in m_vehicles) { - pobj.StepVehicle(timeStep); + prim.StepVehicle(timeStep); } } #endregion Vehicles - #region INI and command line parameter processing + #region Parameters delegate void ParamUser(BSScene scene, IConfig conf, string paramName, float val); delegate float ParamGet(BSScene scene); delegate void ParamSet(BSScene scene, string paramName, uint localID, float val); - delegate void SetOnObject(BSScene scene, BSPhysObject obj, float val); private struct ParameterDefn { @@ -937,7 +851,6 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters public ParamUser userParam; // get the value from the configuration file public ParamGet getter; // return the current value stored for this parameter public ParamSet setter; // set the current value for this parameter - public SetOnObject onObject; // set the value on an object in the physical domain public ParameterDefn(string n, string d, float v, ParamUser u, ParamGet g, ParamSet s) { name = n; @@ -946,17 +859,6 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters userParam = u; getter = g; setter = s; - onObject = null; - } - public ParameterDefn(string n, string d, float v, ParamUser u, ParamGet g, ParamSet s, SetOnObject o) - { - name = n; - desc = d; - defaultValue = v; - userParam = u; - getter = g; - setter = s; - onObject = o; } } @@ -967,7 +869,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters // getters and setters. // It is easiest to find an existing definition and copy it. // Parameter values are floats. Booleans are converted to a floating value. - // + // // A ParameterDefn() takes the following parameters: // -- the text name of the parameter. This is used for console input and ini file. // -- a short text description of the parameter. This shows up in the console listing. @@ -978,7 +880,6 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters // // The single letter parameters for the delegates are: // s = BSScene - // o = BSPhysObject // p = string parameter name // l = localID of referenced object // v = float value @@ -987,40 +888,25 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters { new ParameterDefn("MeshSculptedPrim", "Whether to create meshes for sculpties", ConfigurationParameters.numericTrue, - (s,cf,p,v) => { s.ShouldMeshSculptedPrim = cf.GetBoolean(p, s.BoolNumeric(v)); }, - (s) => { return s.NumericBool(s.ShouldMeshSculptedPrim); }, - (s,p,l,v) => { s.ShouldMeshSculptedPrim = s.BoolNumeric(v); } ), + (s,cf,p,v) => { s._meshSculptedPrim = cf.GetBoolean(p, s.BoolNumeric(v)); }, + (s) => { return s.NumericBool(s._meshSculptedPrim); }, + (s,p,l,v) => { s._meshSculptedPrim = s.BoolNumeric(v); } ), new ParameterDefn("ForceSimplePrimMeshing", "If true, only use primitive meshes for objects", ConfigurationParameters.numericFalse, - (s,cf,p,v) => { s.ShouldForceSimplePrimMeshing = cf.GetBoolean(p, s.BoolNumeric(v)); }, - (s) => { return s.NumericBool(s.ShouldForceSimplePrimMeshing); }, - (s,p,l,v) => { s.ShouldForceSimplePrimMeshing = s.BoolNumeric(v); } ), - new ParameterDefn("UseHullsForPhysicalObjects", "If true, create hulls for physical objects", - ConfigurationParameters.numericTrue, - (s,cf,p,v) => { s.ShouldUseHullsForPhysicalObjects = cf.GetBoolean(p, s.BoolNumeric(v)); }, - (s) => { return s.NumericBool(s.ShouldUseHullsForPhysicalObjects); }, - (s,p,l,v) => { s.ShouldUseHullsForPhysicalObjects = s.BoolNumeric(v); } ), + (s,cf,p,v) => { s._forceSimplePrimMeshing = cf.GetBoolean(p, s.BoolNumeric(v)); }, + (s) => { return s.NumericBool(s._forceSimplePrimMeshing); }, + (s,p,l,v) => { s._forceSimplePrimMeshing = s.BoolNumeric(v); } ), - new ParameterDefn("MeshLevelOfDetail", "Level of detail to render meshes (32, 16, 8 or 4. 32=most detailed)", + new ParameterDefn("MeshLOD", "Level of detail to render meshes (32, 16, 8 or 4. 32=most detailed)", 8f, - (s,cf,p,v) => { s.MeshLOD = (float)cf.GetInt(p, (int)v); }, - (s) => { return s.MeshLOD; }, - (s,p,l,v) => { s.MeshLOD = v; } ), - new ParameterDefn("MeshLevelOfDetailMegaPrim", "Level of detail to render meshes larger than threshold meters", - 16f, - (s,cf,p,v) => { s.MeshMegaPrimLOD = (float)cf.GetInt(p, (int)v); }, - (s) => { return s.MeshMegaPrimLOD; }, - (s,p,l,v) => { s.MeshMegaPrimLOD = v; } ), - new ParameterDefn("MeshLevelOfDetailMegaPrimThreshold", "Size (in meters) of a mesh before using MeshMegaPrimLOD", - 10f, - (s,cf,p,v) => { s.MeshMegaPrimThreshold = (float)cf.GetInt(p, (int)v); }, - (s) => { return s.MeshMegaPrimThreshold; }, - (s,p,l,v) => { s.MeshMegaPrimThreshold = v; } ), - new ParameterDefn("SculptLevelOfDetail", "Level of detail to render sculpties (32, 16, 8 or 4. 32=most detailed)", + (s,cf,p,v) => { s.m_meshLOD = cf.GetInt(p, (int)v); }, + (s) => { return (float)s.m_meshLOD; }, + (s,p,l,v) => { s.m_meshLOD = (int)v; } ), + new ParameterDefn("SculptLOD", "Level of detail to render sculpties (32, 16, 8 or 4. 32=most detailed)", 32f, - (s,cf,p,v) => { s.SculptLOD = (float)cf.GetInt(p, (int)v); }, - (s) => { return s.SculptLOD; }, - (s,p,l,v) => { s.SculptLOD = v; } ), + (s,cf,p,v) => { s.m_sculptLOD = cf.GetInt(p, (int)v); }, + (s) => { return (float)s.m_sculptLOD; }, + (s,p,l,v) => { s.m_sculptLOD = (int)v; } ), new ParameterDefn("MaxSubStep", "In simulation step, maximum number of substeps", 10f, @@ -1042,16 +928,11 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters (s,cf,p,v) => { s.m_maxUpdatesPerFrame = cf.GetInt(p, (int)v); }, (s) => { return (float)s.m_maxUpdatesPerFrame; }, (s,p,l,v) => { s.m_maxUpdatesPerFrame = (int)v; } ), - new ParameterDefn("MaxTaintsToProcessPerStep", "Number of update taints to process before each simulation step", - 100f, - (s,cf,p,v) => { s.m_taintsToProcessPerStep = cf.GetInt(p, (int)v); }, - (s) => { return (float)s.m_taintsToProcessPerStep; }, - (s,p,l,v) => { s.m_taintsToProcessPerStep = (int)v; } ), new ParameterDefn("MaxObjectMass", "Maximum object mass (10000.01)", 10000.01f, - (s,cf,p,v) => { s.MaximumObjectMass = cf.GetFloat(p, v); }, - (s) => { return (float)s.MaximumObjectMass; }, - (s,p,l,v) => { s.MaximumObjectMass = v; } ), + (s,cf,p,v) => { s.m_maximumObjectMass = cf.GetFloat(p, v); }, + (s) => { return (float)s.m_maximumObjectMass; }, + (s,p,l,v) => { s.m_maximumObjectMass = v; } ), new ParameterDefn("PID_D", "Derivitive factor for motion smoothing", 2200f, @@ -1088,118 +969,104 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters -9.80665f, (s,cf,p,v) => { s.m_params[0].gravity = cf.GetFloat(p, v); }, (s) => { return s.m_params[0].gravity; }, - (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].gravity, p, PhysParameterEntry.APPLY_TO_NONE, v); }, - (s,o,v) => { BulletSimAPI.SetGravity2(s.World.ptr, new Vector3(0f,0f,v)); } ), + (s,p,l,v) => { s.m_params[0].gravity = v; s.TaintedUpdateParameter(p,l,v); } ), new ParameterDefn("LinearDamping", "Factor to damp linear movement per second (0.0 - 1.0)", 0f, (s,cf,p,v) => { s.m_params[0].linearDamping = cf.GetFloat(p, v); }, (s) => { return s.m_params[0].linearDamping; }, - (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].linearDamping, p, l, v); }, - (s,o,v) => { BulletSimAPI.SetDamping2(o.PhysBody.ptr, v, v); } ), + (s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].linearDamping, p, l, v); } ), new ParameterDefn("AngularDamping", "Factor to damp angular movement per second (0.0 - 1.0)", 0f, (s,cf,p,v) => { s.m_params[0].angularDamping = cf.GetFloat(p, v); }, (s) => { return s.m_params[0].angularDamping; }, - (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].angularDamping, p, l, v); }, - (s,o,v) => { BulletSimAPI.SetDamping2(o.PhysBody.ptr, v, v); } ), + (s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].angularDamping, p, l, v); } ), new ParameterDefn("DeactivationTime", "Seconds before considering an object potentially static", 0.2f, (s,cf,p,v) => { s.m_params[0].deactivationTime = cf.GetFloat(p, v); }, (s) => { return s.m_params[0].deactivationTime; }, - (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].deactivationTime, p, l, v); }, - (s,o,v) => { BulletSimAPI.SetDeactivationTime2(o.PhysBody.ptr, v); } ), + (s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].deactivationTime, p, l, v); } ), new ParameterDefn("LinearSleepingThreshold", "Seconds to measure linear movement before considering static", 0.8f, (s,cf,p,v) => { s.m_params[0].linearSleepingThreshold = cf.GetFloat(p, v); }, (s) => { return s.m_params[0].linearSleepingThreshold; }, - (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].linearSleepingThreshold, p, l, v); }, - (s,o,v) => { BulletSimAPI.SetSleepingThresholds2(o.PhysBody.ptr, v, v); } ), + (s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].linearSleepingThreshold, p, l, v); } ), new ParameterDefn("AngularSleepingThreshold", "Seconds to measure angular movement before considering static", 1.0f, (s,cf,p,v) => { s.m_params[0].angularSleepingThreshold = cf.GetFloat(p, v); }, (s) => { return s.m_params[0].angularSleepingThreshold; }, - (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].angularSleepingThreshold, p, l, v); }, - (s,o,v) => { BulletSimAPI.SetSleepingThresholds2(o.PhysBody.ptr, v, v); } ), + (s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].angularSleepingThreshold, p, l, v); } ), new ParameterDefn("CcdMotionThreshold", "Continuious collision detection threshold (0 means no CCD)" , 0f, // set to zero to disable (s,cf,p,v) => { s.m_params[0].ccdMotionThreshold = cf.GetFloat(p, v); }, (s) => { return s.m_params[0].ccdMotionThreshold; }, - (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].ccdMotionThreshold, p, l, v); }, - (s,o,v) => { BulletSimAPI.SetCcdMotionThreshold2(o.PhysBody.ptr, v); } ), + (s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].ccdMotionThreshold, p, l, v); } ), new ParameterDefn("CcdSweptSphereRadius", "Continuious collision detection test radius" , 0f, (s,cf,p,v) => { s.m_params[0].ccdSweptSphereRadius = cf.GetFloat(p, v); }, (s) => { return s.m_params[0].ccdSweptSphereRadius; }, - (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].ccdSweptSphereRadius, p, l, v); }, - (s,o,v) => { BulletSimAPI.SetCcdSweptSphereRadius2(o.PhysBody.ptr, v); } ), + (s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].ccdSweptSphereRadius, p, l, v); } ), new ParameterDefn("ContactProcessingThreshold", "Distance between contacts before doing collision check" , 0.1f, (s,cf,p,v) => { s.m_params[0].contactProcessingThreshold = cf.GetFloat(p, v); }, (s) => { return s.m_params[0].contactProcessingThreshold; }, - (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].contactProcessingThreshold, p, l, v); }, - (s,o,v) => { BulletSimAPI.SetContactProcessingThreshold2(o.PhysBody.ptr, v); } ), + (s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].contactProcessingThreshold, p, l, v); } ), new ParameterDefn("TerrainFriction", "Factor to reduce movement against terrain surface" , 0.5f, (s,cf,p,v) => { s.m_params[0].terrainFriction = cf.GetFloat(p, v); }, (s) => { return s.m_params[0].terrainFriction; }, - (s,p,l,v) => { s.m_params[0].terrainFriction = v; /* TODO: set on real terrain */} ), + (s,p,l,v) => { s.m_params[0].terrainFriction = v; s.TaintedUpdateParameter(p,l,v); } ), new ParameterDefn("TerrainHitFraction", "Distance to measure hit collisions" , 0.8f, (s,cf,p,v) => { s.m_params[0].terrainHitFraction = cf.GetFloat(p, v); }, (s) => { return s.m_params[0].terrainHitFraction; }, - (s,p,l,v) => { s.m_params[0].terrainHitFraction = v; /* TODO: set on real terrain */ } ), + (s,p,l,v) => { s.m_params[0].terrainHitFraction = v; s.TaintedUpdateParameter(p,l,v); } ), new ParameterDefn("TerrainRestitution", "Bouncyness" , 0f, (s,cf,p,v) => { s.m_params[0].terrainRestitution = cf.GetFloat(p, v); }, (s) => { return s.m_params[0].terrainRestitution; }, - (s,p,l,v) => { s.m_params[0].terrainRestitution = v; /* TODO: set on real terrain */ } ), + (s,p,l,v) => { s.m_params[0].terrainRestitution = v; s.TaintedUpdateParameter(p,l,v); } ), new ParameterDefn("AvatarFriction", "Factor to reduce movement against an avatar. Changed on avatar recreation.", - 0.2f, + 0.5f, (s,cf,p,v) => { s.m_params[0].avatarFriction = cf.GetFloat(p, v); }, (s) => { return s.m_params[0].avatarFriction; }, - (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarFriction, p, l, v); } ), - new ParameterDefn("AvatarStandingFriction", "Avatar friction when standing. Changed on avatar recreation.", - 10f, - (s,cf,p,v) => { s.m_params[0].avatarStandingFriction = cf.GetFloat(p, v); }, - (s) => { return s.m_params[0].avatarStandingFriction; }, - (s,p,l,v) => { s.m_params[0].avatarStandingFriction = v; } ), + (s,p,l,v) => { s.UpdateParameterAvatars(ref s.m_params[0].avatarFriction, p, l, v); } ), new ParameterDefn("AvatarDensity", "Density of an avatar. Changed on avatar recreation.", 60f, (s,cf,p,v) => { s.m_params[0].avatarDensity = cf.GetFloat(p, v); }, (s) => { return s.m_params[0].avatarDensity; }, - (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarDensity, p, l, v); } ), + (s,p,l,v) => { s.UpdateParameterAvatars(ref s.m_params[0].avatarDensity, p, l, v); } ), new ParameterDefn("AvatarRestitution", "Bouncyness. Changed on avatar recreation.", 0f, (s,cf,p,v) => { s.m_params[0].avatarRestitution = cf.GetFloat(p, v); }, (s) => { return s.m_params[0].avatarRestitution; }, - (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarRestitution, p, l, v); } ), + (s,p,l,v) => { s.UpdateParameterAvatars(ref s.m_params[0].avatarRestitution, p, l, v); } ), new ParameterDefn("AvatarCapsuleRadius", "Radius of space around an avatar", 0.37f, (s,cf,p,v) => { s.m_params[0].avatarCapsuleRadius = cf.GetFloat(p, v); }, (s) => { return s.m_params[0].avatarCapsuleRadius; }, - (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarCapsuleRadius, p, l, v); } ), + (s,p,l,v) => { s.UpdateParameterAvatars(ref s.m_params[0].avatarCapsuleRadius, p, l, v); } ), new ParameterDefn("AvatarCapsuleHeight", "Default height of space around avatar", 1.5f, (s,cf,p,v) => { s.m_params[0].avatarCapsuleHeight = cf.GetFloat(p, v); }, (s) => { return s.m_params[0].avatarCapsuleHeight; }, - (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarCapsuleHeight, p, l, v); } ), + (s,p,l,v) => { s.UpdateParameterAvatars(ref s.m_params[0].avatarCapsuleHeight, p, l, v); } ), new ParameterDefn("AvatarContactProcessingThreshold", "Distance from capsule to check for collisions", 0.1f, (s,cf,p,v) => { s.m_params[0].avatarContactProcessingThreshold = cf.GetFloat(p, v); }, (s) => { return s.m_params[0].avatarContactProcessingThreshold; }, - (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarContactProcessingThreshold, p, l, v); } ), + (s,p,l,v) => { s.UpdateParameterAvatars(ref s.m_params[0].avatarContactProcessingThreshold, p, l, v); } ), new ParameterDefn("MaxPersistantManifoldPoolSize", "Number of manifolds pooled (0 means default of 4096)", - 0f, + 0f, // zero to disable (s,cf,p,v) => { s.m_params[0].maxPersistantManifoldPoolSize = cf.GetFloat(p, v); }, (s) => { return s.m_params[0].maxPersistantManifoldPoolSize; }, (s,p,l,v) => { s.m_params[0].maxPersistantManifoldPoolSize = v; } ), new ParameterDefn("MaxCollisionAlgorithmPoolSize", "Number of collisions pooled (0 means default of 4096)", - 0f, + 0f, // zero to disable (s,cf,p,v) => { s.m_params[0].maxCollisionAlgorithmPoolSize = cf.GetFloat(p, v); }, (s) => { return s.m_params[0].maxCollisionAlgorithmPoolSize; }, (s,p,l,v) => { s.m_params[0].maxCollisionAlgorithmPoolSize = v; } ), @@ -1214,12 +1081,12 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters (s) => { return s.m_params[0].shouldForceUpdateAllAabbs; }, (s,p,l,v) => { s.m_params[0].shouldForceUpdateAllAabbs = v; } ), new ParameterDefn("ShouldRandomizeSolverOrder", "Enable for slightly better stacking interaction", - ConfigurationParameters.numericTrue, + ConfigurationParameters.numericFalse, (s,cf,p,v) => { s.m_params[0].shouldRandomizeSolverOrder = s.NumericBool(cf.GetBoolean(p, s.BoolNumeric(v))); }, (s) => { return s.m_params[0].shouldRandomizeSolverOrder; }, (s,p,l,v) => { s.m_params[0].shouldRandomizeSolverOrder = v; } ), new ParameterDefn("ShouldSplitSimulationIslands", "Enable splitting active object scanning islands", - ConfigurationParameters.numericTrue, + ConfigurationParameters.numericFalse, (s,cf,p,v) => { s.m_params[0].shouldSplitSimulationIslands = s.NumericBool(cf.GetBoolean(p, s.BoolNumeric(v))); }, (s) => { return s.m_params[0].shouldSplitSimulationIslands; }, (s,p,l,v) => { s.m_params[0].shouldSplitSimulationIslands = v; } ), @@ -1234,11 +1101,6 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters (s) => { return s.m_params[0].numberOfSolverIterations; }, (s,p,l,v) => { s.m_params[0].numberOfSolverIterations = v; } ), - new ParameterDefn("LinksetImplementation", "Type of linkset implementation (0=Constraint, 1=Compound, 2=Manual)", - (float)BSLinkset.LinksetImplementation.Compound, - (s,cf,p,v) => { s.m_params[0].linksetImplementation = cf.GetFloat(p,v); }, - (s) => { return s.m_params[0].linksetImplementation; }, - (s,p,l,v) => { s.m_params[0].linksetImplementation = v; } ), new ParameterDefn("LinkConstraintUseFrameOffset", "For linksets built with constraints, enable frame offsetFor linksets built with constraints, enable frame offset.", ConfigurationParameters.numericFalse, (s,cf,p,v) => { s.m_params[0].linkConstraintUseFrameOffset = s.NumericBool(cf.GetBoolean(p, s.BoolNumeric(v))); }, @@ -1259,27 +1121,28 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters (s,cf,p,v) => { s.m_params[0].linkConstraintTransMotorMaxForce = cf.GetFloat(p, v); }, (s) => { return s.m_params[0].linkConstraintTransMotorMaxForce; }, (s,p,l,v) => { s.m_params[0].linkConstraintTransMotorMaxForce = v; } ), - new ParameterDefn("LinkConstraintCFM", "Amount constraint can be violated. 0=no violation, 1=infinite. Default=0.1", - 0.1f, + new ParameterDefn("LinkConstraintCFM", "Amount constraint can be violated. 0=none, 1=all. Default=0", + 0.0f, (s,cf,p,v) => { s.m_params[0].linkConstraintCFM = cf.GetFloat(p, v); }, (s) => { return s.m_params[0].linkConstraintCFM; }, (s,p,l,v) => { s.m_params[0].linkConstraintCFM = v; } ), new ParameterDefn("LinkConstraintERP", "Amount constraint is corrected each tick. 0=none, 1=all. Default = 0.2", - 0.1f, + 0.2f, (s,cf,p,v) => { s.m_params[0].linkConstraintERP = cf.GetFloat(p, v); }, (s) => { return s.m_params[0].linkConstraintERP; }, (s,p,l,v) => { s.m_params[0].linkConstraintERP = v; } ), - new ParameterDefn("LinkConstraintSolverIterations", "Number of solver iterations when computing constraint. (0 = Bullet default)", - 40, - (s,cf,p,v) => { s.m_params[0].linkConstraintSolverIterations = cf.GetFloat(p, v); }, - (s) => { return s.m_params[0].linkConstraintSolverIterations; }, - (s,p,l,v) => { s.m_params[0].linkConstraintSolverIterations = v; } ), - new ParameterDefn("LogPhysicsStatisticsFrames", "Frames between outputting detailed phys stats. (0 is off)", + new ParameterDefn("DetailedStats", "Frames between outputting detailed phys stats. (0 is off)", 0f, - (s,cf,p,v) => { s.m_params[0].physicsLoggingFrames = cf.GetInt(p, (int)v); }, - (s) => { return (float)s.m_params[0].physicsLoggingFrames; }, - (s,p,l,v) => { s.m_params[0].physicsLoggingFrames = (int)v; } ), + (s,cf,p,v) => { s.m_detailedStatsStep = cf.GetInt(p, (int)v); }, + (s) => { return (float)s.m_detailedStatsStep; }, + (s,p,l,v) => { s.m_detailedStatsStep = (int)v; } ), + new ParameterDefn("ShouldDebugLog", "Enables detailed DEBUG log statements", + ConfigurationParameters.numericFalse, + (s,cf,p,v) => { s.ShouldDebugLog = cf.GetBoolean(p, s.BoolNumeric(v)); }, + (s) => { return s.NumericBool(s.ShouldDebugLog); }, + (s,p,l,v) => { s.ShouldDebugLog = s.BoolNumeric(v); } ), + }; // Convert a boolean to our numeric true and false values @@ -1337,12 +1200,11 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters private PhysParameterEntry[] SettableParameters = new PhysParameterEntry[1]; - // This creates an array in the correct format for returning the list of - // parameters. This is used by the 'list' option of the 'physics' command. private void BuildParameterTable() { if (SettableParameters.Length < ParameterDefinitions.Length) { + List entries = new List(); for (int ii = 0; ii < ParameterDefinitions.Length; ii++) { @@ -1387,54 +1249,60 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters return ret; } + // check to see if we are updating a parameter for a particular or all of the prims + protected void UpdateParameterPrims(ref float loc, string parm, uint localID, float val) + { + List operateOn; + lock (m_prims) operateOn = new List(m_prims.Keys); + UpdateParameterSet(operateOn, ref loc, parm, localID, val); + } + + // check to see if we are updating a parameter for a particular or all of the avatars + protected void UpdateParameterAvatars(ref float loc, string parm, uint localID, float val) + { + List operateOn; + lock (m_avatars) operateOn = new List(m_avatars.Keys); + UpdateParameterSet(operateOn, ref loc, parm, localID, val); + } + // update all the localIDs specified // If the local ID is APPLY_TO_NONE, just change the default value // If the localID is APPLY_TO_ALL change the default value and apply the new value to all the lIDs // If the localID is a specific object, apply the parameter change to only that object - private void UpdateParameterObject(ref float defaultLoc, string parm, uint localID, float val) + protected void UpdateParameterSet(List lIDs, ref float defaultLoc, string parm, uint localID, float val) { - List objectIDs = new List(); switch (localID) { case PhysParameterEntry.APPLY_TO_NONE: defaultLoc = val; // setting only the default value - // This will cause a call into the physical world if some operation is specified (SetOnObject). - objectIDs.Add(TERRAIN_ID); - TaintedUpdateParameter(parm, objectIDs, val); break; case PhysParameterEntry.APPLY_TO_ALL: defaultLoc = val; // setting ALL also sets the default value - lock (PhysObjects) objectIDs = new List(PhysObjects.Keys); - TaintedUpdateParameter(parm, objectIDs, val); + List objectIDs = lIDs; + string xparm = parm.ToLower(); + float xval = val; + TaintedObject("BSScene.UpdateParameterSet", delegate() { + foreach (uint lID in objectIDs) + { + BulletSimAPI.UpdateParameter(m_worldID, lID, xparm, xval); + } + }); break; - default: + default: // setting only one localID - objectIDs.Add(localID); - TaintedUpdateParameter(parm, objectIDs, val); + TaintedUpdateParameter(parm, localID, val); break; } } // schedule the actual updating of the paramter to when the phys engine is not busy - private void TaintedUpdateParameter(string parm, List lIDs, float val) + protected void TaintedUpdateParameter(string parm, uint localID, float val) { + uint xlocalID = localID; + string xparm = parm.ToLower(); float xval = val; - List xlIDs = lIDs; - string xparm = parm; - TaintedObject("BSScene.UpdateParameterSet", delegate() { - ParameterDefn thisParam; - if (TryGetParameter(xparm, out thisParam)) - { - if (thisParam.onObject != null) - { - foreach (uint lID in xlIDs) - { - BSPhysObject theObject = null; - PhysObjects.TryGetValue(lID, out theObject); - thisParam.onObject(this, theObject, xval); - } - } - } + TaintedObject("BSScene.TaintedUpdateParameter", delegate() { + BulletSimAPI.UpdateParameter(m_worldID, xlocalID, xparm, xval); }); } @@ -1458,24 +1326,12 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters #endregion Runtime settable parameters - // Debugging routine for dumping detailed physical information for vehicle prims - private void DumpVehicles() - { - foreach (BSPrim prim in m_vehicles) - { - BulletSimAPI.DumpRigidBody2(World.ptr, prim.PhysBody.ptr); - BulletSimAPI.DumpCollisionShape2(World.ptr, prim.PhysShape.ptr); - } - } - // Invoke the detailed logger and output something if it's enabled. public void DetailLog(string msg, params Object[] args) { PhysicsLogging.Write(msg, args); - // Add the Flush() if debugging crashes. Gets all the messages written out. - PhysicsLogging.Flush(); } - // Used to fill in the LocalID when there isn't one. It's the correct number of characters. + // used to fill in the LocalID when there isn't one public const string DetailLogZero = "0000000000"; } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs deleted file mode 100755 index 29a23c0..0000000 --- a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs +++ /dev/null @@ -1,1000 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyrightD - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -using System; -using System.Collections.Generic; -using System.Text; -using OMV = OpenMetaverse; -using OpenSim.Framework; -using OpenSim.Region.Physics.Manager; -using OpenSim.Region.Physics.ConvexDecompositionDotNet; - -namespace OpenSim.Region.Physics.BulletSPlugin -{ -public sealed class BSShapeCollection : IDisposable -{ - private static string LogHeader = "[BULLETSIM SHAPE COLLECTION]"; - - private BSScene PhysicsScene { get; set; } - - private Object m_collectionActivityLock = new Object(); - - // Description of a Mesh - private struct MeshDesc - { - public IntPtr ptr; - public int referenceCount; - public DateTime lastReferenced; - public UInt64 shapeKey; - } - - // Description of a hull. - // Meshes and hulls have the same shape hash key but we only need hulls for efficient collision calculations. - private struct HullDesc - { - public IntPtr ptr; - public int referenceCount; - public DateTime lastReferenced; - public UInt64 shapeKey; - } - - // The sharable set of meshes and hulls. Indexed by their shape hash. - private Dictionary Meshes = new Dictionary(); - private Dictionary Hulls = new Dictionary(); - - public BSShapeCollection(BSScene physScene) - { - PhysicsScene = physScene; - } - - public void Dispose() - { - // TODO!!!!!!!!! - } - - // Callbacks called just before either the body or shape is destroyed. - // Mostly used for changing bodies out from under Linksets. - // Useful for other cases where parameters need saving. - // Passing 'null' says no callback. - public delegate void ShapeDestructionCallback(BulletShape shape); - public delegate void BodyDestructionCallback(BulletBody body); - - // Called to update/change the body and shape for an object. - // First checks the shape and updates that if necessary then makes - // sure the body is of the right type. - // Return 'true' if either the body or the shape changed. - // 'shapeCallback' and 'bodyCallback' are, if non-null, functions called just before - // the current shape or body is destroyed. This allows the caller to remove any - // higher level dependencies on the shape or body. Mostly used for LinkSets to - // remove the physical constraints before the body is destroyed. - // Called at taint-time!! - public bool GetBodyAndShape(bool forceRebuild, BulletSim sim, BSPhysObject prim, - ShapeDestructionCallback shapeCallback, BodyDestructionCallback bodyCallback) - { - PhysicsScene.AssertInTaintTime("BSShapeCollection.GetBodyAndShape"); - - bool ret = false; - - // This lock could probably be pushed down lower but building shouldn't take long - lock (m_collectionActivityLock) - { - // Do we have the correct geometry for this type of object? - // Updates prim.BSShape with information/pointers to shape. - // Returns 'true' of BSShape is changed to a new shape. - bool newGeom = CreateGeom(forceRebuild, prim, shapeCallback); - // If we had to select a new shape geometry for the object, - // rebuild the body around it. - // Updates prim.BSBody with information/pointers to requested body - // Returns 'true' if BSBody was changed. - bool newBody = CreateBody((newGeom || forceRebuild), prim, PhysicsScene.World, - prim.PhysShape, bodyCallback); - ret = newGeom || newBody; - } - DetailLog("{0},BSShapeCollection.GetBodyAndShape,taintExit,force={1},ret={2},body={3},shape={4}", - prim.LocalID, forceRebuild, ret, prim.PhysBody, prim.PhysShape); - - return ret; - } - - // Track another user of a body. - // We presume the caller has allocated the body. - // Bodies only have one user so the body is just put into the world if not already there. - public void ReferenceBody(BulletBody body, bool inTaintTime) - { - lock (m_collectionActivityLock) - { - DetailLog("{0},BSShapeCollection.ReferenceBody,newBody,body={1}", body.ID, body); - PhysicsScene.TaintedObject(inTaintTime, "BSShapeCollection.ReferenceBody", delegate() - { - if (!BulletSimAPI.IsInWorld2(body.ptr)) - { - BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, body.ptr); - DetailLog("{0},BSShapeCollection.ReferenceBody,addedToWorld,ref={1}", body.ID, body); - } - }); - } - } - - // Release the usage of a body. - // Called when releasing use of a BSBody. BSShape is handled separately. - public void DereferenceBody(BulletBody body, bool inTaintTime, BodyDestructionCallback bodyCallback ) - { - if (body.ptr == IntPtr.Zero) - return; - - lock (m_collectionActivityLock) - { - PhysicsScene.TaintedObject(inTaintTime, "BSShapeCollection.DereferenceBody", delegate() - { - DetailLog("{0},BSShapeCollection.DereferenceBody,DestroyingBody,body={1},inTaintTime={2}", - body.ID, body, inTaintTime); - // If the caller needs to know the old body is going away, pass the event up. - if (bodyCallback != null) bodyCallback(body); - - if (BulletSimAPI.IsInWorld2(body.ptr)) - { - BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, body.ptr); - DetailLog("{0},BSShapeCollection.DereferenceBody,removingFromWorld. Body={1}", body.ID, body); - } - - // Zero any reference to the shape so it is not freed when the body is deleted. - BulletSimAPI.SetCollisionShape2(PhysicsScene.World.ptr, body.ptr, IntPtr.Zero); - BulletSimAPI.DestroyObject2(PhysicsScene.World.ptr, body.ptr); - }); - } - } - - // Track the datastructures and use count for a shape. - // When creating a hull, this is called first to reference the mesh - // and then again to reference the hull. - // Meshes and hulls for the same shape have the same hash key. - // NOTE that native shapes are not added to the mesh list or removed. - // Returns 'true' if this is the initial reference to the shape. Otherwise reused. - public bool ReferenceShape(BulletShape shape) - { - bool ret = false; - switch (shape.type) - { - case ShapeData.PhysicsShapeType.SHAPE_MESH: - MeshDesc meshDesc; - if (Meshes.TryGetValue(shape.shapeKey, out meshDesc)) - { - // There is an existing instance of this mesh. - meshDesc.referenceCount++; - DetailLog("{0},BSShapeCollection.ReferenceShape,existingMesh,key={1},cnt={2}", - BSScene.DetailLogZero, shape.shapeKey.ToString("X"), meshDesc.referenceCount); - } - else - { - // This is a new reference to a mesh - meshDesc.ptr = shape.ptr; - meshDesc.shapeKey = shape.shapeKey; - // We keep a reference to the underlying IMesh data so a hull can be built - meshDesc.referenceCount = 1; - DetailLog("{0},BSShapeCollection.ReferenceShape,newMesh,key={1},cnt={2}", - BSScene.DetailLogZero, shape.shapeKey.ToString("X"), meshDesc.referenceCount); - ret = true; - } - meshDesc.lastReferenced = System.DateTime.Now; - Meshes[shape.shapeKey] = meshDesc; - break; - case ShapeData.PhysicsShapeType.SHAPE_HULL: - HullDesc hullDesc; - if (Hulls.TryGetValue(shape.shapeKey, out hullDesc)) - { - // There is an existing instance of this hull. - hullDesc.referenceCount++; - DetailLog("{0},BSShapeCollection.ReferenceShape,existingHull,key={1},cnt={2}", - BSScene.DetailLogZero, shape.shapeKey.ToString("X"), hullDesc.referenceCount); - } - else - { - // This is a new reference to a hull - hullDesc.ptr = shape.ptr; - hullDesc.shapeKey = shape.shapeKey; - hullDesc.referenceCount = 1; - DetailLog("{0},BSShapeCollection.ReferenceShape,newHull,key={1},cnt={2}", - BSScene.DetailLogZero, shape.shapeKey.ToString("X"), hullDesc.referenceCount); - ret = true; - - } - hullDesc.lastReferenced = System.DateTime.Now; - Hulls[shape.shapeKey] = hullDesc; - break; - case ShapeData.PhysicsShapeType.SHAPE_UNKNOWN: - break; - default: - // Native shapes are not tracked and they don't go into any list - break; - } - return ret; - } - - // Release the usage of a shape. - public void DereferenceShape(BulletShape shape, bool inTaintTime, ShapeDestructionCallback shapeCallback) - { - if (shape.ptr == IntPtr.Zero) - return; - - PhysicsScene.TaintedObject(inTaintTime, "BSShapeCollection.DereferenceShape", delegate() - { - if (shape.ptr != IntPtr.Zero) - { - if (shape.isNativeShape) - { - // Native shapes are not tracked and are released immediately - DetailLog("{0},BSShapeCollection.DereferenceShape,deleteNativeShape,ptr={1},taintTime={2}", - BSScene.DetailLogZero, shape.ptr.ToString("X"), inTaintTime); - if (shapeCallback != null) shapeCallback(shape); - BulletSimAPI.DeleteCollisionShape2(PhysicsScene.World.ptr, shape.ptr); - } - else - { - switch (shape.type) - { - case ShapeData.PhysicsShapeType.SHAPE_HULL: - DereferenceHull(shape, shapeCallback); - break; - case ShapeData.PhysicsShapeType.SHAPE_MESH: - DereferenceMesh(shape, shapeCallback); - break; - case ShapeData.PhysicsShapeType.SHAPE_COMPOUND: - DereferenceCompound(shape, shapeCallback); - break; - case ShapeData.PhysicsShapeType.SHAPE_UNKNOWN: - break; - default: - break; - } - } - } - }); - } - - // Count down the reference count for a mesh shape - // Called at taint-time. - private void DereferenceMesh(BulletShape shape, ShapeDestructionCallback shapeCallback) - { - MeshDesc meshDesc; - if (Meshes.TryGetValue(shape.shapeKey, out meshDesc)) - { - meshDesc.referenceCount--; - // TODO: release the Bullet storage - if (shapeCallback != null) shapeCallback(shape); - meshDesc.lastReferenced = System.DateTime.Now; - Meshes[shape.shapeKey] = meshDesc; - DetailLog("{0},BSShapeCollection.DereferenceMesh,shape={1},refCnt={2}", - BSScene.DetailLogZero, shape, meshDesc.referenceCount); - - } - } - - // Count down the reference count for a hull shape - // Called at taint-time. - private void DereferenceHull(BulletShape shape, ShapeDestructionCallback shapeCallback) - { - HullDesc hullDesc; - if (Hulls.TryGetValue(shape.shapeKey, out hullDesc)) - { - hullDesc.referenceCount--; - // TODO: release the Bullet storage (aging old entries?) - - // Tell upper layers that, if they have dependencies on this shape, this link is going away - if (shapeCallback != null) shapeCallback(shape); - - hullDesc.lastReferenced = System.DateTime.Now; - Hulls[shape.shapeKey] = hullDesc; - DetailLog("{0},BSShapeCollection.DereferenceHull,shape={1},refCnt={2}", - BSScene.DetailLogZero, shape, hullDesc.referenceCount); - } - } - - // Remove a reference to a compound shape. - // Taking a compound shape apart is a little tricky because if you just delete the - // physical shape, it will free all the underlying children. We can't do that because - // they could be shared. So, this removes each of the children from the compound and - // dereferences them separately before destroying the compound collision object itself. - // Called at taint-time. - private void DereferenceCompound(BulletShape shape, ShapeDestructionCallback shapeCallback) - { - if (!BulletSimAPI.IsCompound2(shape.ptr)) - { - // Failed the sanity check!! - PhysicsScene.Logger.ErrorFormat("{0} Attempt to free a compound shape that is not compound!! type={1}, ptr={2}", - LogHeader, shape.type, shape.ptr.ToString("X")); - DetailLog("{0},BSShapeCollection.DereferenceCompound,notACompoundShape,type={1},ptr={2}", - BSScene.DetailLogZero, shape.type, shape.ptr.ToString("X")); - return; - } - - int numChildren = BulletSimAPI.GetNumberOfCompoundChildren2(shape.ptr); - DetailLog("{0},BSShapeCollection.DereferenceCompound,shape={1},children={2}", BSScene.DetailLogZero, shape, numChildren); - - for (int ii = numChildren - 1; ii >= 0; ii--) - { - IntPtr childShape = BulletSimAPI.RemoveChildShapeFromCompoundShapeIndex2(shape.ptr, ii); - DereferenceAnonCollisionShape(childShape); - } - BulletSimAPI.DeleteCollisionShape2(PhysicsScene.World.ptr, shape.ptr); - } - - // Sometimes we have a pointer to a collision shape but don't know what type it is. - // Figure out type and call the correct dereference routine. - // Called at taint-time. - private void DereferenceAnonCollisionShape(IntPtr cShape) - { - MeshDesc meshDesc; - HullDesc hullDesc; - - BulletShape shapeInfo = new BulletShape(cShape); - if (TryGetMeshByPtr(cShape, out meshDesc)) - { - shapeInfo.type = ShapeData.PhysicsShapeType.SHAPE_MESH; - shapeInfo.shapeKey = meshDesc.shapeKey; - } - else - { - if (TryGetHullByPtr(cShape, out hullDesc)) - { - shapeInfo.type = ShapeData.PhysicsShapeType.SHAPE_HULL; - shapeInfo.shapeKey = hullDesc.shapeKey; - } - else - { - if (BulletSimAPI.IsCompound2(cShape)) - { - shapeInfo.type = ShapeData.PhysicsShapeType.SHAPE_COMPOUND; - } - else - { - if (BulletSimAPI.IsNativeShape2(cShape)) - { - shapeInfo.isNativeShape = true; - shapeInfo.type = ShapeData.PhysicsShapeType.SHAPE_BOX; // (technically, type doesn't matter) - } - } - } - } - - DetailLog("{0},BSShapeCollection.DereferenceAnonCollisionShape,shape={1}", BSScene.DetailLogZero, shapeInfo); - - if (shapeInfo.type != ShapeData.PhysicsShapeType.SHAPE_UNKNOWN) - { - DereferenceShape(shapeInfo, true, null); - } - else - { - PhysicsScene.Logger.ErrorFormat("{0} Could not decypher shape type. Region={1}, addr={2}", - LogHeader, PhysicsScene.RegionName, cShape.ToString("X")); - } - } - - // Create the geometry information in Bullet for later use. - // The objects needs a hull if it's physical otherwise a mesh is enough. - // if 'forceRebuild' is true, the geometry is unconditionally rebuilt. For meshes and hulls, - // shared geometries will be used. If the parameters of the existing shape are the same - // as this request, the shape is not rebuilt. - // Info in prim.BSShape is updated to the new shape. - // Returns 'true' if the geometry was rebuilt. - // Called at taint-time! - private bool CreateGeom(bool forceRebuild, BSPhysObject prim, ShapeDestructionCallback shapeCallback) - { - bool ret = false; - bool haveShape = false; - - if (!haveShape && prim.PreferredPhysicalShape == ShapeData.PhysicsShapeType.SHAPE_AVATAR) - { - // an avatar capsule is close to a native shape (it is not shared) - ret = GetReferenceToNativeShape(prim, ShapeData.PhysicsShapeType.SHAPE_AVATAR, - ShapeData.FixedShapeKey.KEY_CAPSULE, shapeCallback); - DetailLog("{0},BSShapeCollection.CreateGeom,avatarCapsule,shape={1}", prim.LocalID, prim.PhysShape); - ret = true; - haveShape = true; - } - - // Compound shapes are handled special as they are rebuilt from scratch. - // This isn't too great a hardship since most of the child shapes will already been created. - if (!haveShape && prim.PreferredPhysicalShape == ShapeData.PhysicsShapeType.SHAPE_COMPOUND) - { - ret = GetReferenceToCompoundShape(prim, shapeCallback); - DetailLog("{0},BSShapeCollection.CreateGeom,compoundShape,shape={1}", prim.LocalID, prim.PhysShape); - haveShape = true; - } - - if (!haveShape) - { - ret = CreateGeomNonSpecial(forceRebuild, prim, shapeCallback); - } - - return ret; - } - - // Create a mesh/hull shape or a native shape if 'nativeShapePossible' is 'true'. - private bool CreateGeomNonSpecial(bool forceRebuild, BSPhysObject prim, ShapeDestructionCallback shapeCallback) - { - bool ret = false; - bool haveShape = false; - bool nativeShapePossible = true; - PrimitiveBaseShape pbs = prim.BaseShape; - - // If the prim attributes are simple, this could be a simple Bullet native shape - if (!haveShape - && pbs != null - && nativeShapePossible - && ((pbs.SculptEntry && !PhysicsScene.ShouldMeshSculptedPrim) - || (pbs.ProfileBegin == 0 && pbs.ProfileEnd == 0 - && pbs.ProfileHollow == 0 - && pbs.PathTwist == 0 && pbs.PathTwistBegin == 0 - && pbs.PathBegin == 0 && pbs.PathEnd == 0 - && pbs.PathTaperX == 0 && pbs.PathTaperY == 0 - && pbs.PathScaleX == 100 && pbs.PathScaleY == 100 - && pbs.PathShearX == 0 && pbs.PathShearY == 0) ) ) - { - // It doesn't look like Bullet scales spheres so make sure the scales are all equal - if ((pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1) - && pbs.Scale.X == pbs.Scale.Y && pbs.Scale.Y == pbs.Scale.Z) - { - haveShape = true; - if (forceRebuild - || prim.Scale != prim.Size - || prim.PhysShape.type != ShapeData.PhysicsShapeType.SHAPE_SPHERE - ) - { - ret = GetReferenceToNativeShape(prim, ShapeData.PhysicsShapeType.SHAPE_SPHERE, - ShapeData.FixedShapeKey.KEY_SPHERE, shapeCallback); - DetailLog("{0},BSShapeCollection.CreateGeom,sphere,force={1},shape={2}", - prim.LocalID, forceRebuild, prim.PhysShape); - } - } - if (!haveShape && pbs.ProfileShape == ProfileShape.Square && pbs.PathCurve == (byte)Extrusion.Straight) - { - haveShape = true; - if (forceRebuild - || prim.Scale != prim.Size - || prim.PhysShape.type != ShapeData.PhysicsShapeType.SHAPE_BOX - ) - { - ret = GetReferenceToNativeShape( prim, ShapeData.PhysicsShapeType.SHAPE_BOX, - ShapeData.FixedShapeKey.KEY_BOX, shapeCallback); - DetailLog("{0},BSShapeCollection.CreateGeom,box,force={1},shape={2}", - prim.LocalID, forceRebuild, prim.PhysShape); - } - } - } - - // If a simple shape is not happening, create a mesh and possibly a hull. - if (!haveShape && pbs != null) - { - ret = CreateGeomMeshOrHull(prim, shapeCallback); - } - - return ret; - } - - public bool CreateGeomMeshOrHull(BSPhysObject prim, ShapeDestructionCallback shapeCallback) - { - - bool ret = false; - // Note that if it's a native shape, the check for physical/non-physical is not - // made. Native shapes work in either case. - if (prim.IsPhysical && PhysicsScene.ShouldUseHullsForPhysicalObjects) - { - // Update prim.BSShape to reference a hull of this shape. - ret = GetReferenceToHull(prim,shapeCallback); - DetailLog("{0},BSShapeCollection.CreateGeom,hull,shape={1},key={2}", - prim.LocalID, prim.PhysShape, prim.PhysShape.shapeKey.ToString("X")); - } - else - { - ret = GetReferenceToMesh(prim, shapeCallback); - DetailLog("{0},BSShapeCollection.CreateGeom,mesh,shape={1},key={2}", - prim.LocalID, prim.PhysShape, prim.PhysShape.shapeKey.ToString("X")); - } - return ret; - } - - // Creates a native shape and assignes it to prim.BSShape. - // "Native" shapes are never shared. they are created here and destroyed in DereferenceShape(). - private bool GetReferenceToNativeShape(BSPhysObject prim, - ShapeData.PhysicsShapeType shapeType, ShapeData.FixedShapeKey shapeKey, - ShapeDestructionCallback shapeCallback) - { - // release any previous shape - DereferenceShape(prim.PhysShape, true, shapeCallback); - - // Bullet native objects are scaled by the Bullet engine so pass the size in - prim.Scale = prim.Size; - - BulletShape newShape = BuildPhysicalNativeShape(prim, shapeType, shapeKey); - - // Don't need to do a 'ReferenceShape()' here because native shapes are not shared. - DetailLog("{0},BSShapeCollection.AddNativeShapeToPrim,create,newshape={1},scale={2}", - prim.LocalID, newShape, prim.Scale); - - prim.PhysShape = newShape; - return true; - } - - private BulletShape BuildPhysicalNativeShape(BSPhysObject prim, ShapeData.PhysicsShapeType shapeType, - ShapeData.FixedShapeKey shapeKey) - { - BulletShape newShape; - // Need to make sure the passed shape information is for the native type. - ShapeData nativeShapeData = new ShapeData(); - nativeShapeData.Type = shapeType; - nativeShapeData.ID = prim.LocalID; - nativeShapeData.Scale = prim.Scale; - nativeShapeData.Size = prim.Scale; - nativeShapeData.MeshKey = (ulong)shapeKey; - nativeShapeData.HullKey = (ulong)shapeKey; - - if (shapeType == ShapeData.PhysicsShapeType.SHAPE_AVATAR) - { - newShape = new BulletShape( - BulletSimAPI.BuildCapsuleShape2(PhysicsScene.World.ptr, 1f, 1f, prim.Scale) - , shapeType); - DetailLog("{0},BSShapeCollection.BuiletPhysicalNativeShape,capsule,scale={1}", prim.LocalID, prim.Scale); - } - else - { - newShape = new BulletShape(BulletSimAPI.BuildNativeShape2(PhysicsScene.World.ptr, nativeShapeData), shapeType); - } - if (newShape.ptr == IntPtr.Zero) - { - PhysicsScene.Logger.ErrorFormat("{0} BuildPhysicalNativeShape failed. ID={1}, shape={2}", - LogHeader, prim.LocalID, shapeType); - } - newShape.shapeKey = (System.UInt64)shapeKey; - newShape.isNativeShape = true; - - return newShape; - } - - // Builds a mesh shape in the physical world and updates prim.BSShape. - // Dereferences previous shape in BSShape and adds a reference for this new shape. - // Returns 'true' of a mesh was actually built. Otherwise . - // Called at taint-time! - private bool GetReferenceToMesh(BSPhysObject prim, ShapeDestructionCallback shapeCallback) - { - BulletShape newShape = new BulletShape(IntPtr.Zero); - - float lod; - System.UInt64 newMeshKey = ComputeShapeKey(prim.Size, prim.BaseShape, out lod); - - // if this new shape is the same as last time, don't recreate the mesh - if (newMeshKey == prim.PhysShape.shapeKey && prim.PhysShape.type == ShapeData.PhysicsShapeType.SHAPE_MESH) - return false; - - DetailLog("{0},BSShapeCollection.GetReferenceToMesh,create,oldKey={1},newKey={2}", - prim.LocalID, prim.PhysShape.shapeKey.ToString("X"), newMeshKey.ToString("X")); - - // Since we're recreating new, get rid of the reference to the previous shape - DereferenceShape(prim.PhysShape, true, shapeCallback); - - newShape = CreatePhysicalMesh(prim.PhysObjectName, newMeshKey, prim.BaseShape, prim.Size, lod); - // Take evasive action if the mesh was not constructed. - newShape = VerifyMeshCreated(newShape, prim); - - ReferenceShape(newShape); - - // meshes are already scaled by the meshmerizer - prim.Scale = new OMV.Vector3(1f, 1f, 1f); - prim.PhysShape = newShape; - - return true; // 'true' means a new shape has been added to this prim - } - - private BulletShape CreatePhysicalMesh(string objName, System.UInt64 newMeshKey, PrimitiveBaseShape pbs, OMV.Vector3 size, float lod) - { - IMesh meshData = null; - IntPtr meshPtr = IntPtr.Zero; - MeshDesc meshDesc; - if (Meshes.TryGetValue(newMeshKey, out meshDesc)) - { - // If the mesh has already been built just use it. - meshPtr = meshDesc.ptr; - } - else - { - // Pass false for physicalness as this creates some sort of bounding box which we don't need - meshData = PhysicsScene.mesher.CreateMesh(objName, pbs, size, lod, false); - - if (meshData != null) - { - int[] indices = meshData.getIndexListAsInt(); - List vertices = meshData.getVertexList(); - - float[] verticesAsFloats = new float[vertices.Count * 3]; - int vi = 0; - foreach (OMV.Vector3 vv in vertices) - { - verticesAsFloats[vi++] = vv.X; - verticesAsFloats[vi++] = vv.Y; - verticesAsFloats[vi++] = vv.Z; - } - - // m_log.DebugFormat("{0}: BSShapeCollection.CreatePhysicalMesh: calling CreateMesh. lid={1}, key={2}, indices={3}, vertices={4}", - // LogHeader, prim.LocalID, newMeshKey, indices.Length, vertices.Count); - - meshPtr = BulletSimAPI.CreateMeshShape2(PhysicsScene.World.ptr, - indices.GetLength(0), indices, vertices.Count, verticesAsFloats); - } - } - BulletShape newShape = new BulletShape(meshPtr, ShapeData.PhysicsShapeType.SHAPE_MESH); - newShape.shapeKey = newMeshKey; - - return newShape; - } - - // See that hull shape exists in the physical world and update prim.BSShape. - // We could be creating the hull because scale changed or whatever. - private bool GetReferenceToHull(BSPhysObject prim, ShapeDestructionCallback shapeCallback) - { - BulletShape newShape; - - float lod; - System.UInt64 newHullKey = ComputeShapeKey(prim.Size, prim.BaseShape, out lod); - - // if the hull hasn't changed, don't rebuild it - if (newHullKey == prim.PhysShape.shapeKey && prim.PhysShape.type == ShapeData.PhysicsShapeType.SHAPE_HULL) - return false; - - DetailLog("{0},BSShapeCollection.GetReferenceToHull,create,oldKey={1},newKey={2}", - prim.LocalID, prim.PhysShape.shapeKey.ToString("X"), newHullKey.ToString("X")); - - // Remove usage of the previous shape. - DereferenceShape(prim.PhysShape, true, shapeCallback); - - newShape = CreatePhysicalHull(prim.PhysObjectName, newHullKey, prim.BaseShape, prim.Size, lod); - newShape = VerifyMeshCreated(newShape, prim); - - ReferenceShape(newShape); - - // hulls are already scaled by the meshmerizer - prim.Scale = new OMV.Vector3(1f, 1f, 1f); - prim.PhysShape = newShape; - return true; // 'true' means a new shape has been added to this prim - } - - List m_hulls; - private BulletShape CreatePhysicalHull(string objName, System.UInt64 newHullKey, PrimitiveBaseShape pbs, OMV.Vector3 size, float lod) - { - - IntPtr hullPtr = IntPtr.Zero; - HullDesc hullDesc; - if (Hulls.TryGetValue(newHullKey, out hullDesc)) - { - // If the hull shape already is created, just use it. - hullPtr = hullDesc.ptr; - } - else - { - // Build a new hull in the physical world - // Pass false for physicalness as this creates some sort of bounding box which we don't need - IMesh meshData = PhysicsScene.mesher.CreateMesh(objName, pbs, size, lod, false); - if (meshData != null) - { - - int[] indices = meshData.getIndexListAsInt(); - List vertices = meshData.getVertexList(); - - //format conversion from IMesh format to DecompDesc format - List convIndices = new List(); - List convVertices = new List(); - for (int ii = 0; ii < indices.GetLength(0); ii++) - { - convIndices.Add(indices[ii]); - } - foreach (OMV.Vector3 vv in vertices) - { - convVertices.Add(new float3(vv.X, vv.Y, vv.Z)); - } - - // setup and do convex hull conversion - m_hulls = new List(); - DecompDesc dcomp = new DecompDesc(); - dcomp.mIndices = convIndices; - dcomp.mVertices = convVertices; - ConvexBuilder convexBuilder = new ConvexBuilder(HullReturn); - // create the hull into the _hulls variable - convexBuilder.process(dcomp); - - // Convert the vertices and indices for passing to unmanaged. - // The hull information is passed as a large floating point array. - // The format is: - // convHulls[0] = number of hulls - // convHulls[1] = number of vertices in first hull - // convHulls[2] = hull centroid X coordinate - // convHulls[3] = hull centroid Y coordinate - // convHulls[4] = hull centroid Z coordinate - // convHulls[5] = first hull vertex X - // convHulls[6] = first hull vertex Y - // convHulls[7] = first hull vertex Z - // convHulls[8] = second hull vertex X - // ... - // convHulls[n] = number of vertices in second hull - // convHulls[n+1] = second hull centroid X coordinate - // ... - // - // TODO: is is very inefficient. Someday change the convex hull generator to return - // data structures that do not need to be converted in order to pass to Bullet. - // And maybe put the values directly into pinned memory rather than marshaling. - int hullCount = m_hulls.Count; - int totalVertices = 1; // include one for the count of the hulls - foreach (ConvexResult cr in m_hulls) - { - totalVertices += 4; // add four for the vertex count and centroid - totalVertices += cr.HullIndices.Count * 3; // we pass just triangles - } - float[] convHulls = new float[totalVertices]; - - convHulls[0] = (float)hullCount; - int jj = 1; - foreach (ConvexResult cr in m_hulls) - { - // copy vertices for index access - float3[] verts = new float3[cr.HullVertices.Count]; - int kk = 0; - foreach (float3 ff in cr.HullVertices) - { - verts[kk++] = ff; - } - - // add to the array one hull's worth of data - convHulls[jj++] = cr.HullIndices.Count; - convHulls[jj++] = 0f; // centroid x,y,z - convHulls[jj++] = 0f; - convHulls[jj++] = 0f; - foreach (int ind in cr.HullIndices) - { - convHulls[jj++] = verts[ind].x; - convHulls[jj++] = verts[ind].y; - convHulls[jj++] = verts[ind].z; - } - } - // create the hull data structure in Bullet - hullPtr = BulletSimAPI.CreateHullShape2(PhysicsScene.World.ptr, hullCount, convHulls); - } - } - - BulletShape newShape = new BulletShape(hullPtr, ShapeData.PhysicsShapeType.SHAPE_HULL); - newShape.shapeKey = newHullKey; - - return newShape; // 'true' means a new shape has been added to this prim - } - - // Callback from convex hull creater with a newly created hull. - // Just add it to our collection of hulls for this shape. - private void HullReturn(ConvexResult result) - { - m_hulls.Add(result); - return; - } - - // Compound shapes are always built from scratch. - // This shouldn't be to bad since most of the parts will be meshes that had been built previously. - private bool GetReferenceToCompoundShape(BSPhysObject prim, ShapeDestructionCallback shapeCallback) - { - // Remove reference to the old shape - // Don't need to do this as the shape is freed when the new root shape is created below. - // DereferenceShape(prim.PhysShape, true, shapeCallback); - - BulletShape cShape = new BulletShape( - BulletSimAPI.CreateCompoundShape2(PhysicsScene.World.ptr, false), ShapeData.PhysicsShapeType.SHAPE_COMPOUND); - - // Create the shape for the root prim and add it to the compound shape. Cannot be a native shape. - CreateGeomMeshOrHull(prim, shapeCallback); - BulletSimAPI.AddChildShapeToCompoundShape2(cShape.ptr, prim.PhysShape.ptr, OMV.Vector3.Zero, OMV.Quaternion.Identity); - DetailLog("{0},BSShapeCollection.GetReferenceToCompoundShape,addRootPrim,compShape={1},rootShape={2}", - prim.LocalID, cShape, prim.PhysShape); - - prim.PhysShape = cShape; - - return true; - } - - // Create a hash of all the shape parameters to be used as a key - // for this particular shape. - private System.UInt64 ComputeShapeKey(OMV.Vector3 size, PrimitiveBaseShape pbs, out float retLod) - { - // level of detail based on size and type of the object - float lod = PhysicsScene.MeshLOD; - if (pbs.SculptEntry) - lod = PhysicsScene.SculptLOD; - - // Mega prims usually get more detail because one can interact with shape approximations at this size. - float maxAxis = Math.Max(size.X, Math.Max(size.Y, size.Z)); - if (maxAxis > PhysicsScene.MeshMegaPrimThreshold) - lod = PhysicsScene.MeshMegaPrimLOD; - - retLod = lod; - return pbs.GetMeshKey(size, lod); - } - // For those who don't want the LOD - private System.UInt64 ComputeShapeKey(OMV.Vector3 size, PrimitiveBaseShape pbs) - { - float lod; - return ComputeShapeKey(size, pbs, out lod); - } - - // The creation of a mesh or hull can fail if an underlying asset is not available. - // There are two cases: 1) the asset is not in the cache and it needs to be fetched; - // and 2) the asset cannot be converted (like failed decompression of JPEG2000s). - // The first case causes the asset to be fetched. The second case requires - // us to not loop forever. - // Called after creating a physical mesh or hull. If the physical shape was created, - // just return. - private BulletShape VerifyMeshCreated(BulletShape newShape, BSPhysObject prim) - { - // If the shape was successfully created, nothing more to do - if (newShape.ptr != IntPtr.Zero) - return newShape; - - // If this mesh has an underlying asset and we have not failed getting it before, fetch the asset - if (prim.BaseShape.SculptEntry && !prim.LastAssetBuildFailed && prim.BaseShape.SculptTexture != OMV.UUID.Zero) - { - prim.LastAssetBuildFailed = true; - BSPhysObject xprim = prim; - DetailLog("{0},BSShapeCollection.VerifyMeshCreated,fetchAsset,lID={1},lastFailed={2}", - LogHeader, prim.LocalID, prim.LastAssetBuildFailed); - Util.FireAndForget(delegate - { - RequestAssetDelegate assetProvider = PhysicsScene.RequestAssetMethod; - if (assetProvider != null) - { - BSPhysObject yprim = xprim; // probably not necessary, but, just in case. - assetProvider(yprim.BaseShape.SculptTexture, delegate(AssetBase asset) - { - if (!yprim.BaseShape.SculptEntry) - return; - if (yprim.BaseShape.SculptTexture.ToString() != asset.ID) - return; - - yprim.BaseShape.SculptData = asset.Data; - // This will cause the prim to see that the filler shape is not the right - // one and try again to build the object. - // No race condition with the normal shape setting since the rebuild is at taint time. - yprim.ForceBodyShapeRebuild(false); - - }); - } - }); - } - else - { - if (prim.LastAssetBuildFailed) - { - PhysicsScene.Logger.ErrorFormat("{0} Mesh failed to fetch asset. lID={1}, texture={2}", - LogHeader, prim.LocalID, prim.BaseShape.SculptTexture); - } - } - - // While we figure out the real problem, stick a simple native shape on the object. - BulletShape fillinShape = - BuildPhysicalNativeShape(prim, ShapeData.PhysicsShapeType.SHAPE_BOX, ShapeData.FixedShapeKey.KEY_BOX); - - return fillinShape; - } - - // Create a body object in Bullet. - // Updates prim.BSBody with the information about the new body if one is created. - // Returns 'true' if an object was actually created. - // Called at taint-time. - private bool CreateBody(bool forceRebuild, BSPhysObject prim, BulletSim sim, BulletShape shape, - BodyDestructionCallback bodyCallback) - { - bool ret = false; - - // the mesh, hull or native shape must have already been created in Bullet - bool mustRebuild = (prim.PhysBody.ptr == IntPtr.Zero); - - // If there is an existing body, verify it's of an acceptable type. - // If not a solid object, body is a GhostObject. Otherwise a RigidBody. - if (!mustRebuild) - { - CollisionObjectTypes bodyType = (CollisionObjectTypes)BulletSimAPI.GetBodyType2(prim.PhysBody.ptr); - if (prim.IsSolid && bodyType != CollisionObjectTypes.CO_RIGID_BODY - || !prim.IsSolid && bodyType != CollisionObjectTypes.CO_GHOST_OBJECT) - { - // If the collisionObject is not the correct type for solidness, rebuild what's there - mustRebuild = true; - } - } - - if (mustRebuild || forceRebuild) - { - // Free any old body - DereferenceBody(prim.PhysBody, true, bodyCallback); - - BulletBody aBody; - IntPtr bodyPtr = IntPtr.Zero; - if (prim.IsSolid) - { - bodyPtr = BulletSimAPI.CreateBodyFromShape2(sim.ptr, shape.ptr, - prim.LocalID, prim.RawPosition, prim.RawOrientation); - DetailLog("{0},BSShapeCollection.CreateBody,mesh,ptr={1}", prim.LocalID, bodyPtr.ToString("X")); - } - else - { - bodyPtr = BulletSimAPI.CreateGhostFromShape2(sim.ptr, shape.ptr, - prim.LocalID, prim.ForcePosition, prim.ForceOrientation); - DetailLog("{0},BSShapeCollection.CreateBody,ghost,ptr={1}", prim.LocalID, bodyPtr.ToString("X")); - } - aBody = new BulletBody(prim.LocalID, bodyPtr); - - ReferenceBody(aBody, true); - - prim.PhysBody = aBody; - - ret = true; - } - - return ret; - } - - private bool TryGetMeshByPtr(IntPtr addr, out MeshDesc outDesc) - { - bool ret = false; - MeshDesc foundDesc = new MeshDesc(); - foreach (MeshDesc md in Meshes.Values) - { - if (md.ptr == addr) - { - foundDesc = md; - ret = true; - break; - } - - } - outDesc = foundDesc; - return ret; - } - - private bool TryGetHullByPtr(IntPtr addr, out HullDesc outDesc) - { - bool ret = false; - HullDesc foundDesc = new HullDesc(); - foreach (HullDesc hd in Hulls.Values) - { - if (hd.ptr == addr) - { - foundDesc = hd; - ret = true; - break; - } - - } - outDesc = foundDesc; - return ret; - } - - private void DetailLog(string msg, params Object[] args) - { - if (PhysicsScene.PhysicsLogging.Enabled) - PhysicsScene.DetailLog(msg, args); - } -} -} diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs deleted file mode 100755 index 7c34af2..0000000 --- a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs +++ /dev/null @@ -1,479 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyrightD - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -using System; -using System.Collections.Generic; -using System.Text; - -using OpenSim.Framework; -using OpenSim.Region.Framework; -using OpenSim.Region.CoreModules; -using OpenSim.Region.Physics.Manager; - -using Nini.Config; -using log4net; - -using OpenMetaverse; - -namespace OpenSim.Region.Physics.BulletSPlugin -{ -public sealed class BSTerrainManager -{ - static string LogHeader = "[BULLETSIM TERRAIN MANAGER]"; - - // These height values are fractional so the odd values will be - // noticable when debugging. - public const float HEIGHT_INITIALIZATION = 24.987f; - public const float HEIGHT_INITIAL_LASTHEIGHT = 24.876f; - public const float HEIGHT_GETHEIGHT_RET = 24.765f; - - // If the min and max height are equal, we reduce the min by this - // amount to make sure that a bounding box is built for the terrain. - public const float HEIGHT_EQUAL_FUDGE = 0.2f; - - public const float TERRAIN_COLLISION_MARGIN = 0.0f; - - // Until the whole simulator is changed to pass us the region size, we rely on constants. - public Vector3 DefaultRegionSize = new Vector3(Constants.RegionSize, Constants.RegionSize, Constants.RegionHeight); - - // The scene that I am part of - private BSScene PhysicsScene { get; set; } - - // The ground plane created to keep thing from falling to infinity. - private BulletBody m_groundPlane; - - // If doing mega-regions, if we're region zero we will be managing multiple - // region terrains since region zero does the physics for the whole mega-region. - private Dictionary m_heightMaps; - - // True of the terrain has been modified. - // Used to force recalculation of terrain height after terrain has been modified - private bool m_terrainModified; - - // If we are doing mega-regions, terrains are added from TERRAIN_ID to m_terrainCount. - // This is incremented before assigning to new region so it is the last ID allocated. - private uint m_terrainCount = BSScene.CHILDTERRAIN_ID - 1; - public uint HighestTerrainID { get {return m_terrainCount; } } - - // If doing mega-regions, this holds our offset from region zero of - // the mega-regions. "parentScene" points to the PhysicsScene of region zero. - private Vector3 m_worldOffset; - // If the parent region (region 0), this is the extent of the combined regions - // relative to the origin of region zero - private Vector3 m_worldMax; - private PhysicsScene MegaRegionParentPhysicsScene { get; set; } - - public BSTerrainManager(BSScene physicsScene) - { - PhysicsScene = physicsScene; - m_heightMaps = new Dictionary(); - m_terrainModified = false; - - // Assume one region of default size - m_worldOffset = Vector3.Zero; - m_worldMax = new Vector3(DefaultRegionSize); - MegaRegionParentPhysicsScene = null; - } - - // Create the initial instance of terrain and the underlying ground plane. - // The objects are allocated in the unmanaged space and the pointers are tracked - // by the managed code. - // The terrains and the groundPlane are not added to the list of PhysObjects. - // This is called from the initialization routine so we presume it is - // safe to call Bullet in real time. We hope no one is moving prims around yet. - public void CreateInitialGroundPlaneAndTerrain() - { - // The ground plane is here to catch things that are trying to drop to negative infinity - BulletShape groundPlaneShape = new BulletShape( - BulletSimAPI.CreateGroundPlaneShape2(BSScene.GROUNDPLANE_ID, 1f, TERRAIN_COLLISION_MARGIN), - ShapeData.PhysicsShapeType.SHAPE_GROUNDPLANE); - m_groundPlane = new BulletBody(BSScene.GROUNDPLANE_ID, - BulletSimAPI.CreateBodyWithDefaultMotionState2(groundPlaneShape.ptr, BSScene.GROUNDPLANE_ID, - Vector3.Zero, Quaternion.Identity)); - BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, m_groundPlane.ptr); - BulletSimAPI.UpdateSingleAabb2(PhysicsScene.World.ptr, m_groundPlane.ptr); - // Ground plane does not move - BulletSimAPI.ForceActivationState2(m_groundPlane.ptr, ActivationState.DISABLE_SIMULATION); - // Everything collides with the ground plane. - BulletSimAPI.SetCollisionFilterMask2(m_groundPlane.ptr, - (uint)CollisionFilterGroups.GroundPlaneFilter, (uint)CollisionFilterGroups.GroundPlaneMask); - - Vector3 minTerrainCoords = new Vector3(0f, 0f, HEIGHT_INITIALIZATION - HEIGHT_EQUAL_FUDGE); - Vector3 maxTerrainCoords = new Vector3(DefaultRegionSize.X, DefaultRegionSize.Y, HEIGHT_INITIALIZATION); - int totalHeights = (int)maxTerrainCoords.X * (int)maxTerrainCoords.Y; - float[] initialMap = new float[totalHeights]; - for (int ii = 0; ii < totalHeights; ii++) - { - initialMap[ii] = HEIGHT_INITIALIZATION; - } - UpdateOrCreateTerrain(BSScene.TERRAIN_ID, initialMap, minTerrainCoords, maxTerrainCoords, true); - } - - // Release all the terrain structures we might have allocated - public void ReleaseGroundPlaneAndTerrain() - { - if (m_groundPlane.ptr != IntPtr.Zero) - { - if (BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, m_groundPlane.ptr)) - { - BulletSimAPI.DestroyObject2(PhysicsScene.World.ptr, m_groundPlane.ptr); - } - m_groundPlane.ptr = IntPtr.Zero; - } - - ReleaseTerrain(); - } - - // Release all the terrain we have allocated - public void ReleaseTerrain() - { - foreach (KeyValuePair kvp in m_heightMaps) - { - if (BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, kvp.Value.terrainBody.ptr)) - { - BulletSimAPI.DestroyObject2(PhysicsScene.World.ptr, kvp.Value.terrainBody.ptr); - BulletSimAPI.ReleaseHeightMapInfo2(kvp.Value.Ptr); - } - } - m_heightMaps.Clear(); - } - - // The simulator wants to set a new heightmap for the terrain. - public void SetTerrain(float[] heightMap) { - float[] localHeightMap = heightMap; - PhysicsScene.TaintedObject("TerrainManager.SetTerrain", delegate() - { - if (m_worldOffset != Vector3.Zero && MegaRegionParentPhysicsScene != null) - { - // If a child of a mega-region, we shouldn't have any terrain allocated for us - ReleaseGroundPlaneAndTerrain(); - // If doing the mega-prim stuff and we are the child of the zero region, - // the terrain is added to our parent - if (MegaRegionParentPhysicsScene is BSScene) - { - DetailLog("{0},SetTerrain.ToParent,offset={1},worldMax={2}", - BSScene.DetailLogZero, m_worldOffset, m_worldMax); - ((BSScene)MegaRegionParentPhysicsScene).TerrainManager.UpdateOrCreateTerrain(BSScene.CHILDTERRAIN_ID, - localHeightMap, m_worldOffset, m_worldOffset + DefaultRegionSize, true); - } - } - else - { - // If not doing the mega-prim thing, just change the terrain - DetailLog("{0},SetTerrain.Existing", BSScene.DetailLogZero); - - UpdateOrCreateTerrain(BSScene.TERRAIN_ID, localHeightMap, - m_worldOffset, m_worldOffset + DefaultRegionSize, true); - } - }); - } - - // If called with no mapInfo for the terrain, this will create a new mapInfo and terrain - // based on the passed information. The 'id' should be either the terrain id or - // BSScene.CHILDTERRAIN_ID. If the latter, a new child terrain ID will be allocated and used. - // The latter feature is for creating child terrains for mega-regions. - // If called with a mapInfo in m_heightMaps but the terrain has no body yet (mapInfo.terrainBody.Ptr == 0) - // then a new body and shape is created and the mapInfo is filled. - // This call is used for doing the initial terrain creation. - // If called with a mapInfo in m_heightMaps and there is an existing terrain body, a new - // terrain shape is created and added to the body. - // This call is most often used to update the heightMap and parameters of the terrain. - // (The above does suggest that some simplification/refactoring is in order.) - private void UpdateOrCreateTerrain(uint id, float[] heightMap, Vector3 minCoords, Vector3 maxCoords, bool inTaintTime) - { - DetailLog("{0},BSTerrainManager.UpdateOrCreateTerrain,call,minC={1},maxC={2},inTaintTime={3}", - BSScene.DetailLogZero, minCoords, maxCoords, inTaintTime); - - float minZ = float.MaxValue; - float maxZ = float.MinValue; - Vector2 terrainRegionBase = new Vector2(minCoords.X, minCoords.Y); - - int heightMapSize = heightMap.Length; - for (int ii = 0; ii < heightMapSize; ii++) - { - float height = heightMap[ii]; - if (height < minZ) minZ = height; - if (height > maxZ) maxZ = height; - } - - // The shape of the terrain is from its base to its extents. - minCoords.Z = minZ; - maxCoords.Z = maxZ; - - BulletHeightMapInfo mapInfo; - if (m_heightMaps.TryGetValue(terrainRegionBase, out mapInfo)) - { - // If this is terrain we know about, it's easy to update - - mapInfo.heightMap = heightMap; - mapInfo.minCoords = minCoords; - mapInfo.maxCoords = maxCoords; - mapInfo.minZ = minZ; - mapInfo.maxZ = maxZ; - mapInfo.sizeX = maxCoords.X - minCoords.X; - mapInfo.sizeY = maxCoords.Y - minCoords.Y; - DetailLog("{0},UpdateOrCreateTerrain:UpdateExisting,call,terrainBase={1},minC={2}, maxC={3}, szX={4}, szY={5}", - BSScene.DetailLogZero, terrainRegionBase, mapInfo.minCoords, mapInfo.maxCoords, mapInfo.sizeX, mapInfo.sizeY); - - PhysicsScene.TaintedObject(inTaintTime, "BSScene.UpdateOrCreateTerrain:UpdateExisting", delegate() - { - if (MegaRegionParentPhysicsScene != null) - { - // It's possible that Combine() was called after this code was queued. - // If we are a child of combined regions, we don't create any terrain for us. - DetailLog("{0},UpdateOrCreateTerrain:AmACombineChild,taint", BSScene.DetailLogZero); - - // Get rid of any terrain that may have been allocated for us. - ReleaseGroundPlaneAndTerrain(); - - // I hate doing this, but just bail - return; - } - - if (mapInfo.terrainBody.ptr != IntPtr.Zero) - { - // Updating an existing terrain. - DetailLog("{0},UpdateOrCreateTerrain:UpdateExisting,taint,terrainBase={1},minC={2}, maxC={3}, szX={4}, szY={5}", - BSScene.DetailLogZero, terrainRegionBase, mapInfo.minCoords, mapInfo.maxCoords, mapInfo.sizeX, mapInfo.sizeY); - - // Remove from the dynamics world because we're going to mangle this object - BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, mapInfo.terrainBody.ptr); - - // Get rid of the old terrain - BulletSimAPI.DestroyObject2(PhysicsScene.World.ptr, mapInfo.terrainBody.ptr); - BulletSimAPI.ReleaseHeightMapInfo2(mapInfo.Ptr); - mapInfo.Ptr = IntPtr.Zero; - - /* - // NOTE: This routine is half here because I can't get the terrain shape replacement - // to work. In the short term, the above three lines completely delete the old - // terrain and the code below recreates one from scratch. - // Hopefully the Bullet community will help me out on this one. - - // First, release the old collision shape (there is only one terrain) - BulletSimAPI.DeleteCollisionShape2(m_physicsScene.World.Ptr, mapInfo.terrainShape.Ptr); - - // Fill the existing height map info with the new location and size information - BulletSimAPI.FillHeightMapInfo2(m_physicsScene.World.Ptr, mapInfo.Ptr, mapInfo.ID, - mapInfo.minCoords, mapInfo.maxCoords, mapInfo.heightMap, TERRAIN_COLLISION_MARGIN); - - // Create a terrain shape based on the new info - mapInfo.terrainShape = new BulletShape(BulletSimAPI.CreateTerrainShape2(mapInfo.Ptr)); - - // Stuff the shape into the existing terrain body - BulletSimAPI.SetBodyShape2(m_physicsScene.World.Ptr, mapInfo.terrainBody.Ptr, mapInfo.terrainShape.Ptr); - */ - } - // else - { - // Creating a new terrain. - DetailLog("{0},UpdateOrCreateTerrain:CreateNewTerrain,taint,baseX={1},baseY={2},minZ={3},maxZ={4}", - BSScene.DetailLogZero, mapInfo.minCoords.X, mapInfo.minCoords.Y, minZ, maxZ); - - mapInfo.ID = id; - mapInfo.Ptr = BulletSimAPI.CreateHeightMapInfo2(PhysicsScene.World.ptr, mapInfo.ID, - mapInfo.minCoords, mapInfo.maxCoords, mapInfo.heightMap, TERRAIN_COLLISION_MARGIN); - - // Create the terrain shape from the mapInfo - mapInfo.terrainShape = new BulletShape(BulletSimAPI.CreateTerrainShape2(mapInfo.Ptr), - ShapeData.PhysicsShapeType.SHAPE_TERRAIN); - - // The terrain object initial position is at the center of the object - Vector3 centerPos; - centerPos.X = minCoords.X + (mapInfo.sizeX / 2f); - centerPos.Y = minCoords.Y + (mapInfo.sizeY / 2f); - centerPos.Z = minZ + ((maxZ - minZ) / 2f); - - mapInfo.terrainBody = new BulletBody(mapInfo.ID, - BulletSimAPI.CreateBodyWithDefaultMotionState2(mapInfo.terrainShape.ptr, - id, centerPos, Quaternion.Identity)); - } - - // Make sure the entry is in the heightmap table - m_heightMaps[terrainRegionBase] = mapInfo; - - // Set current terrain attributes - BulletSimAPI.SetFriction2(mapInfo.terrainBody.ptr, PhysicsScene.Params.terrainFriction); - BulletSimAPI.SetHitFraction2(mapInfo.terrainBody.ptr, PhysicsScene.Params.terrainHitFraction); - BulletSimAPI.SetRestitution2(mapInfo.terrainBody.ptr, PhysicsScene.Params.terrainRestitution); - BulletSimAPI.SetCollisionFlags2(mapInfo.terrainBody.ptr, CollisionFlags.CF_STATIC_OBJECT); - - // Return the new terrain to the world of physical objects - BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, mapInfo.terrainBody.ptr); - - // redo its bounding box now that it is in the world - BulletSimAPI.UpdateSingleAabb2(PhysicsScene.World.ptr, mapInfo.terrainBody.ptr); - - BulletSimAPI.SetCollisionFilterMask2(mapInfo.terrainBody.ptr, - (uint)CollisionFilterGroups.TerrainFilter, - (uint)CollisionFilterGroups.TerrainMask); - - // Make sure the new shape is processed. - // BulletSimAPI.Activate2(mapInfo.terrainBody.ptr, true); - // BulletSimAPI.ForceActivationState2(mapInfo.terrainBody.ptr, ActivationState.ISLAND_SLEEPING); - BulletSimAPI.ForceActivationState2(mapInfo.terrainBody.ptr, ActivationState.DISABLE_SIMULATION); - - m_terrainModified = true; - }); - } - else - { - // We don't know about this terrain so either we are creating a new terrain or - // our mega-prim child is giving us a new terrain to add to the phys world - - // if this is a child terrain, calculate a unique terrain id - uint newTerrainID = id; - if (newTerrainID >= BSScene.CHILDTERRAIN_ID) - newTerrainID = ++m_terrainCount; - - float[] heightMapX = heightMap; - Vector3 minCoordsX = minCoords; - Vector3 maxCoordsX = maxCoords; - - DetailLog("{0},UpdateOrCreateTerrain:NewTerrain,call,id={1}, minC={2}, maxC={3}", - BSScene.DetailLogZero, newTerrainID, minCoords, minCoords); - - // Code that must happen at taint-time - PhysicsScene.TaintedObject(inTaintTime, "BSScene.UpdateOrCreateTerrain:NewTerrain", delegate() - { - DetailLog("{0},UpdateOrCreateTerrain:NewTerrain,taint,baseX={1},baseY={2}", BSScene.DetailLogZero, minCoords.X, minCoords.Y); - // Create a new mapInfo that will be filled with the new info - mapInfo = new BulletHeightMapInfo(id, heightMapX, - BulletSimAPI.CreateHeightMapInfo2(PhysicsScene.World.ptr, newTerrainID, - minCoordsX, maxCoordsX, heightMapX, TERRAIN_COLLISION_MARGIN)); - // Put the unfilled heightmap info into the collection of same - m_heightMaps.Add(terrainRegionBase, mapInfo); - // Build the terrain - UpdateOrCreateTerrain(newTerrainID, heightMap, minCoords, maxCoords, true); - - m_terrainModified = true; - }); - } - } - - // Someday we will have complex terrain with caves and tunnels - public float GetTerrainHeightAtXYZ(Vector3 loc) - { - // For the moment, it's flat and convex - return GetTerrainHeightAtXY(loc.X, loc.Y); - } - - // Given an X and Y, find the height of the terrain. - // Since we could be handling multiple terrains for a mega-region, - // the base of the region is calcuated assuming all regions are - // the same size and that is the default. - // Once the heightMapInfo is found, we have all the information to - // compute the offset into the array. - private float lastHeightTX = 999999f; - private float lastHeightTY = 999999f; - private float lastHeight = HEIGHT_INITIAL_LASTHEIGHT; - private float GetTerrainHeightAtXY(float tX, float tY) - { - // You'd be surprized at the number of times this routine is called - // with the same parameters as last time. - if (!m_terrainModified && lastHeightTX == tX && lastHeightTY == tY) - return lastHeight; - - lastHeightTX = tX; - lastHeightTY = tY; - float ret = HEIGHT_GETHEIGHT_RET; - - int offsetX = ((int)(tX / (int)DefaultRegionSize.X)) * (int)DefaultRegionSize.X; - int offsetY = ((int)(tY / (int)DefaultRegionSize.Y)) * (int)DefaultRegionSize.Y; - Vector2 terrainBaseXY = new Vector2(offsetX, offsetY); - - BulletHeightMapInfo mapInfo; - if (m_heightMaps.TryGetValue(terrainBaseXY, out mapInfo)) - { - float regionX = tX - offsetX; - float regionY = tY - offsetY; - int mapIndex = (int)regionY * (int)mapInfo.sizeY + (int)regionX; - try - { - ret = mapInfo.heightMap[mapIndex]; - } - catch - { - // Sometimes they give us wonky values of X and Y. Give a warning and return something. - PhysicsScene.Logger.WarnFormat("{0} Bad request for terrain height. terrainBase={1}, x={2}, y={3}", - LogHeader, terrainBaseXY, regionX, regionY); - ret = HEIGHT_GETHEIGHT_RET; - } - // DetailLog("{0},BSTerrainManager.GetTerrainHeightAtXY,bX={1},baseY={2},szX={3},szY={4},regX={5},regY={6},index={7},ht={8}", - // BSScene.DetailLogZero, offsetX, offsetY, mapInfo.sizeX, mapInfo.sizeY, regionX, regionY, mapIndex, ret); - } - else - { - PhysicsScene.Logger.ErrorFormat("{0} GetTerrainHeightAtXY: terrain not found: region={1}, x={2}, y={3}", - LogHeader, PhysicsScene.RegionName, tX, tY); - } - m_terrainModified = false; - lastHeight = ret; - return ret; - } - - // Although no one seems to check this, I do support combining. - public bool SupportsCombining() - { - return true; - } - - // This routine is called two ways: - // One with 'offset' and 'pScene' zero and null but 'extents' giving the maximum - // extent of the combined regions. This is to inform the parent of the size - // of the combined regions. - // and one with 'offset' as the offset of the child region to the base region, - // 'pScene' pointing to the parent and 'extents' of zero. This informs the - // child of its relative base and new parent. - public void Combine(PhysicsScene pScene, Vector3 offset, Vector3 extents) - { - m_worldOffset = offset; - m_worldMax = extents; - MegaRegionParentPhysicsScene = pScene; - if (pScene != null) - { - // We are a child. - // We want m_worldMax to be the highest coordinate of our piece of terrain. - m_worldMax = offset + DefaultRegionSize; - } - DetailLog("{0},BSTerrainManager.Combine,offset={1},extents={2},wOffset={3},wMax={4}", - BSScene.DetailLogZero, offset, extents, m_worldOffset, m_worldMax); - } - - // Unhook all the combining that I know about. - public void UnCombine(PhysicsScene pScene) - { - // Just like ODE, for the moment a NOP - DetailLog("{0},BSTerrainManager.UnCombine", BSScene.DetailLogZero); - } - - - private void DetailLog(string msg, params Object[] args) - { - PhysicsScene.PhysicsLogging.Write(msg, args); - } -} -} diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs index 702bd77..504bd3c 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs @@ -33,153 +33,38 @@ using OpenMetaverse; namespace OpenSim.Region.Physics.BulletSPlugin { // Classes to allow some type checking for the API -// These hold pointers to allocated objects in the unmanaged space. - -// The physics engine controller class created at initialization public struct BulletSim { - public BulletSim(uint worldId, BSScene bss, IntPtr xx) - { - ptr = xx; - worldID = worldId; - physicsScene = bss; - } - public IntPtr ptr; - public uint worldID; + public BulletSim(uint id, BSScene bss, IntPtr xx) { ID = id; scene = bss; Ptr = xx; } + public uint ID; // The scene is only in here so very low level routines have a handle to print debug/error messages - public BSScene physicsScene; + public BSScene scene; + public IntPtr Ptr; } -// An allocated Bullet btRigidBody public struct BulletBody { - public BulletBody(uint id, IntPtr xx) - { - ID = id; - ptr = xx; - collisionFilter = 0; - collisionMask = 0; - } - public IntPtr ptr; + public BulletBody(uint id, IntPtr xx) { ID = id; Ptr = xx; } + public IntPtr Ptr; public uint ID; - public CollisionFilterGroups collisionFilter; - public CollisionFilterGroups collisionMask; - public override string ToString() - { - StringBuilder buff = new StringBuilder(); - buff.Append(""); - return buff.ToString(); - } -} - -public struct BulletShape -{ - public BulletShape(IntPtr xx) - { - ptr = xx; - type=ShapeData.PhysicsShapeType.SHAPE_UNKNOWN; - shapeKey = 0; - isNativeShape = false; - } - public BulletShape(IntPtr xx, ShapeData.PhysicsShapeType typ) - { - ptr = xx; - type = typ; - shapeKey = 0; - isNativeShape = false; - } - public IntPtr ptr; - public ShapeData.PhysicsShapeType type; - public System.UInt64 shapeKey; - public bool isNativeShape; - public override string ToString() - { - StringBuilder buff = new StringBuilder(); - buff.Append(""); - return buff.ToString(); - } } - // Constraint type values as defined by Bullet -public enum ConstraintType : int -{ - POINT2POINT_CONSTRAINT_TYPE = 3, - HINGE_CONSTRAINT_TYPE, - CONETWIST_CONSTRAINT_TYPE, - D6_CONSTRAINT_TYPE, - SLIDER_CONSTRAINT_TYPE, - CONTACT_CONSTRAINT_TYPE, - D6_SPRING_CONSTRAINT_TYPE, - MAX_CONSTRAINT_TYPE -} - -// An allocated Bullet btConstraint public struct BulletConstraint { - public BulletConstraint(IntPtr xx) - { - ptr = xx; - } - public IntPtr ptr; -} - -// An allocated HeightMapThing which holds various heightmap info. -// Made a class rather than a struct so there would be only one -// instance of this and C# will pass around pointers rather -// than making copies. -public class BulletHeightMapInfo -{ - public BulletHeightMapInfo(uint id, float[] hm, IntPtr xx) { - ID = id; - Ptr = xx; - heightMap = hm; - terrainRegionBase = new Vector2(0f, 0f); - minCoords = new Vector3(100f, 100f, 25f); - maxCoords = new Vector3(101f, 101f, 26f); - minZ = maxZ = 0f; - sizeX = sizeY = 256f; - } - public uint ID; + public BulletConstraint(IntPtr xx) { Ptr = xx; } public IntPtr Ptr; - public float[] heightMap; - public Vector2 terrainRegionBase; - public Vector3 minCoords; - public Vector3 maxCoords; - public float sizeX, sizeY; - public float minZ, maxZ; - public BulletShape terrainShape; - public BulletBody terrainBody; } // =============================================================================== [StructLayout(LayoutKind.Sequential)] -public struct ConvexHull +public struct ConvexHull { Vector3 Offset; int VertexCount; Vector3[] Vertices; } [StructLayout(LayoutKind.Sequential)] -public struct ShapeData +public struct ShapeData { public enum PhysicsShapeType { @@ -190,11 +75,7 @@ public struct ShapeData SHAPE_CYLINDER = 4, SHAPE_SPHERE = 5, SHAPE_MESH = 6, - SHAPE_HULL = 7, - // following defined by BulletSim - SHAPE_GROUNDPLANE = 20, - SHAPE_TERRAIN = 21, - SHAPE_COMPOUND = 22, + SHAPE_HULL = 7 }; public uint ID; public PhysicsShapeType Type; @@ -210,25 +91,13 @@ public struct ShapeData public float Restitution; public float Collidable; // true of things bump into this public float Static; // true if a static object. Otherwise gravity, etc. - public float Solid; // true if object cannot be passed through - public Vector3 Size; // note that bools are passed as floats since bool size changes by language and architecture public const float numericTrue = 1f; public const float numericFalse = 0f; - - // The native shapes have predefined shape hash keys - public enum FixedShapeKey : ulong - { - KEY_BOX = 1, - KEY_SPHERE = 2, - KEY_CONE = 3, - KEY_CYLINDER = 4, - KEY_CAPSULE = 5, - } } [StructLayout(LayoutKind.Sequential)] -public struct SweepHit +public struct SweepHit { public uint ID; public float Fraction; @@ -284,7 +153,6 @@ public struct ConfigurationParameters public float terrainHitFraction; public float terrainRestitution; public float avatarFriction; - public float avatarStandingFriction; public float avatarDensity; public float avatarRestitution; public float avatarCapsuleRadius; @@ -300,45 +168,18 @@ public struct ConfigurationParameters public float shouldEnableFrictionCaching; public float numberOfSolverIterations; - public float linksetImplementation; public float linkConstraintUseFrameOffset; public float linkConstraintEnableTransMotor; public float linkConstraintTransMotorMaxVel; public float linkConstraintTransMotorMaxForce; public float linkConstraintERP; public float linkConstraintCFM; - public float linkConstraintSolverIterations; - - public float physicsLoggingFrames; public const float numericTrue = 1f; public const float numericFalse = 0f; } - -// The states a bullet collision object can have -public enum ActivationState : uint -{ - ACTIVE_TAG = 1, - ISLAND_SLEEPING, - WANTS_DEACTIVATION, - DISABLE_DEACTIVATION, - DISABLE_SIMULATION, -} - -public enum CollisionObjectTypes : int -{ - CO_COLLISION_OBJECT = 1 << 0, - CO_RIGID_BODY = 1 << 1, - CO_GHOST_OBJECT = 1 << 2, - CO_SOFT_BODY = 1 << 3, - CO_HF_FLUID = 1 << 4, - CO_USER_TYPE = 1 << 5, -} - -// Values used by Bullet and BulletSim to control object properties. -// Bullet's "CollisionFlags" has more to do with operations on the -// object (if collisions happen, if gravity effects it, ...). +// Values used by Bullet and BulletSim to control collisions public enum CollisionFlags : uint { CF_STATIC_OBJECT = 1 << 0, @@ -350,54 +191,9 @@ public enum CollisionFlags : uint CF_DISABLE_SPU_COLLISION_PROCESS = 1 << 6, // Following used by BulletSim to control collisions BS_SUBSCRIBE_COLLISION_EVENTS = 1 << 10, - BS_FLOATS_ON_WATER = 1 << 11, - BS_NONE = 0, - BS_ALL = 0xFFFFFFFF, - - // These are the collision flags switched depending on physical state. - // The other flags are used for other things and should not be fooled with. - BS_ACTIVE = CF_STATIC_OBJECT - | CF_KINEMATIC_OBJECT - | CF_NO_CONTACT_RESPONSE -}; - -// Values for collisions groups and masks -public enum CollisionFilterGroups : uint -{ - // Don't use the bit definitions!! Define the use in a - // filter/mask definition below. This way collision interactions - // are more easily debugged. - BNoneFilter = 0, - BDefaultFilter = 1 << 0, - BStaticFilter = 1 << 1, - BKinematicFilter = 1 << 2, - BDebrisFilter = 1 << 3, - BSensorTrigger = 1 << 4, - BCharacterFilter = 1 << 5, - BAllFilter = 0xFFFFFFFF, - // Filter groups defined by BulletSim - BGroundPlaneFilter = 1 << 10, - BTerrainFilter = 1 << 11, - BRaycastFilter = 1 << 12, - BSolidFilter = 1 << 13, - BLinksetFilter = 1 << 14, - - // The collsion filters and masked are defined in one place -- don't want them scattered - AvatarFilter = BCharacterFilter, - AvatarMask = BAllFilter, - ObjectFilter = BSolidFilter, - ObjectMask = BAllFilter, - StaticObjectFilter = BStaticFilter, - StaticObjectMask = BAllFilter, - LinksetFilter = BLinksetFilter, - LinksetMask = BAllFilter & ~BLinksetFilter, - VolumeDetectFilter = BSensorTrigger, - VolumeDetectMask = ~BSensorTrigger, - TerrainFilter = BTerrainFilter, - TerrainMask = BAllFilter & ~BStaticFilter, - GroundPlaneFilter = BGroundPlaneFilter, - GroundPlaneMask = BAllFilter - + BS_VOLUME_DETECT_OBJECT = 1 << 11, + BS_PHANTOM_OBJECT = 1 << 12, + BS_PHYSICAL_OBJECT = 1 << 13, }; // CFM controls the 'hardness' of the constraint. 0=fixed, 0..1=violatable. Default=0 @@ -425,23 +221,14 @@ public enum ConstraintParamAxis : int // =============================================================================== static class BulletSimAPI { -// Link back to the managed code for outputting log messages -[UnmanagedFunctionPointer(CallingConvention.Cdecl)] -public delegate void DebugLogCallback([MarshalAs(UnmanagedType.LPStr)]string msg); - [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] [return: MarshalAs(UnmanagedType.LPStr)] public static extern string GetVersion(); -/* Remove the linkage to the old api methods [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern uint Initialize(Vector3 maxPosition, IntPtr parms, - int maxCollisions, IntPtr collisionArray, - int maxUpdates, IntPtr updateArray, - DebugLogCallback logRoutine); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void CreateInitialGroundPlaneAndTerrain(uint worldID); +public static extern uint Initialize(Vector3 maxPosition, IntPtr parms, + int maxCollisions, IntPtr collisionArray, + int maxUpdates, IntPtr updateArray); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern void SetHeightmap(uint worldID, [MarshalAs(UnmanagedType.LPArray)] float[] heightMap); @@ -455,19 +242,19 @@ public static extern bool UpdateParameter(uint worldID, uint localID, // =============================================================================== [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern int PhysicsStep(uint worldID, float timeStep, int maxSubSteps, float fixedTimeStep, - out int updatedEntityCount, +public static extern int PhysicsStep(uint worldID, float timeStep, int maxSubSteps, float fixedTimeStep, + out int updatedEntityCount, out IntPtr updatedEntitiesPtr, out int collidersCount, out IntPtr collidersPtr); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern bool CreateHull(uint worldID, System.UInt64 meshKey, +public static extern bool CreateHull(uint worldID, System.UInt64 meshKey, int hullCount, [MarshalAs(UnmanagedType.LPArray)] float[] hulls ); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern bool CreateMesh(uint worldID, System.UInt64 meshKey, +public static extern bool CreateMesh(uint worldID, System.UInt64 meshKey, int indexCount, [MarshalAs(UnmanagedType.LPArray)] int[] indices, int verticesCount, [MarshalAs(UnmanagedType.LPArray)] float[] vertices ); @@ -481,6 +268,23 @@ public static extern bool DestroyMesh(uint worldID, System.UInt64 meshKey); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern bool CreateObject(uint worldID, ShapeData shapeData); +/* Remove old functionality +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern void CreateLinkset(uint worldID, int objectCount, ShapeData[] shapeDatas); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern void AddConstraint(uint worldID, uint id1, uint id2, + Vector3 frame1, Quaternion frame1rot, + Vector3 frame2, Quaternion frame2rot, + Vector3 lowLinear, Vector3 hiLinear, Vector3 lowAngular, Vector3 hiAngular); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern bool RemoveConstraintByID(uint worldID, uint id1); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern bool RemoveConstraint(uint worldID, uint id1, uint id2); + */ + [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern Vector3 GetObjectPosition(uint WorldID, uint id); @@ -496,7 +300,6 @@ public static extern bool SetObjectVelocity(uint worldID, uint id, Vector3 veloc [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern bool SetObjectAngularVelocity(uint worldID, uint id, Vector3 angularVelocity); -// Set the current force acting on the object [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern bool SetObjectForce(uint worldID, uint id, Vector3 force); @@ -537,8 +340,10 @@ public static extern Vector3 RecoverFromPenetration(uint worldID, uint id); // =============================================================================== [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern void DumpBulletStatistics(); -*/ + // Log a debug message +[UnmanagedFunctionPointer(CallingConvention.Cdecl)] +public delegate void DebugLogCallback([MarshalAs(UnmanagedType.LPStr)]string msg); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern void SetDebugLogCallback(DebugLogCallback callback); @@ -553,7 +358,6 @@ public static extern void SetDebugLogCallback(DebugLogCallback callback); // The names have a "2" tacked on. This will be removed as the C# code gets rebuilt // and the old code is removed. -// Functions use while converting from API1 to API2. Can be removed when totally converted. [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern IntPtr GetSimHandle2(uint worldID); @@ -564,25 +368,23 @@ public static extern IntPtr GetBodyHandleWorldID2(uint worldID, uint id); public static extern IntPtr GetBodyHandle2(IntPtr world, uint id); // =============================================================================== -// Initialization and simulation [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern IntPtr Initialize2(Vector3 maxPosition, IntPtr parms, int maxCollisions, IntPtr collisionArray, - int maxUpdates, IntPtr updateArray, - DebugLogCallback logRoutine); + int maxUpdates, IntPtr updateArray); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern bool UpdateParameter2(IntPtr world, uint localID, String parm, float value); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void SetHeightMap2(IntPtr world, float[] heightmap); +public static extern void SetHeightmap2(IntPtr world, float[] heightmap); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern void Shutdown2(IntPtr sim); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern int PhysicsStep2(IntPtr world, float timeStep, int maxSubSteps, float fixedTimeStep, - out int updatedEntityCount, + out int updatedEntityCount, out IntPtr updatedEntitiesPtr, out int collidersCount, out IntPtr collidersPtr); @@ -590,98 +392,23 @@ public static extern int PhysicsStep2(IntPtr world, float timeStep, int maxSubSt [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern bool PushUpdate2(IntPtr obj); -// ===================================================================================== -// Mesh, hull, shape and body creation helper routines -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern IntPtr CreateMeshShape2(IntPtr world, - int indicesCount, [MarshalAs(UnmanagedType.LPArray)] int[] indices, - int verticesCount, [MarshalAs(UnmanagedType.LPArray)] float[] vertices ); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern IntPtr CreateHullShape2(IntPtr world, - int hullCount, [MarshalAs(UnmanagedType.LPArray)] float[] hulls); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern IntPtr BuildHullShapeFromMesh2(IntPtr world, IntPtr meshShape); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern IntPtr BuildNativeShape2(IntPtr world, ShapeData shapeData); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern bool IsNativeShape2(IntPtr shape); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern IntPtr BuildCapsuleShape2(IntPtr world, float radius, float height, Vector3 scale); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern IntPtr CreateCompoundShape2(IntPtr sim, bool enableDynamicAabbTree); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern int GetNumberOfCompoundChildren2(IntPtr cShape); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void AddChildShapeToCompoundShape2(IntPtr cShape, IntPtr addShape, Vector3 pos, Quaternion rot); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern IntPtr GetChildShapeFromCompoundShapeIndex2(IntPtr cShape, int indx); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern IntPtr RemoveChildShapeFromCompoundShapeIndex2(IntPtr cShape, int indx); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void RemoveChildShapeFromCompoundShape2(IntPtr cShape, IntPtr removeShape); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern IntPtr DuplicateCollisionShape2(IntPtr sim, IntPtr srcShape, uint id); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern IntPtr CreateBodyFromShapeAndInfo2(IntPtr sim, IntPtr shape, uint id, IntPtr constructionInfo); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern bool DeleteCollisionShape2(IntPtr world, IntPtr shape); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern int GetBodyType2(IntPtr obj); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern IntPtr CreateBodyFromShape2(IntPtr sim, IntPtr shape, uint id, Vector3 pos, Quaternion rot); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern IntPtr CreateBodyWithDefaultMotionState2(IntPtr shape, uint id, Vector3 pos, Quaternion rot); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern IntPtr CreateGhostFromShape2(IntPtr sim, IntPtr shape, uint id, Vector3 pos, Quaternion rot); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern IntPtr AllocateBodyInfo2(IntPtr obj); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void ReleaseBodyInfo2(IntPtr obj); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void DestroyObject2(IntPtr sim, IntPtr obj); - -// ===================================================================================== -// Terrain creation and helper routines +/* [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern IntPtr CreateHeightMapInfo2(IntPtr sim, uint id, Vector3 minCoords, Vector3 maxCoords, - [MarshalAs(UnmanagedType.LPArray)] float[] heightMap, float collisionMargin); +public static extern IntPtr CreateMesh2(IntPtr world, int indicesCount, int* indices, int verticesCount, float* vertices ); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern IntPtr FillHeightMapInfo2(IntPtr sim, IntPtr mapInfo, uint id, Vector3 minCoords, Vector3 maxCoords, - [MarshalAs(UnmanagedType.LPArray)] float[] heightMap, float collisionMargin); +public static extern bool BuildHull2(IntPtr world, IntPtr mesh); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern bool ReleaseHeightMapInfo2(IntPtr heightMapInfo); +public static extern bool ReleaseHull2(IntPtr world, IntPtr mesh); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern IntPtr CreateGroundPlaneShape2(uint id, float height, float collisionMargin); +public static extern bool DestroyMesh2(IntPtr world, IntPtr mesh); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern IntPtr CreateTerrainShape2(IntPtr mapInfo); +public static extern IntPtr CreateObject2(IntPtr world, ShapeData shapeData); +*/ -// ===================================================================================== -// Constraint creation and helper routines [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern IntPtr Create6DofConstraint2(IntPtr world, IntPtr obj1, IntPtr obj2, Vector3 frame1loc, Quaternion frame1rot, @@ -706,7 +433,7 @@ public static extern void SetConstraintEnable2(IntPtr constrain, float numericTr public static extern void SetConstraintNumSolverIterations2(IntPtr constrain, float iterations); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern bool SetFrames2(IntPtr constrain, +public static extern bool SetFrames2(IntPtr constrain, Vector3 frameA, Quaternion frameArot, Vector3 frameB, Quaternion frameBrot); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] @@ -733,108 +460,11 @@ public static extern bool SetConstraintParam2(IntPtr constrain, ConstraintParams [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern bool DestroyConstraint2(IntPtr world, IntPtr constrain); -// ===================================================================================== -// btCollisionWorld entries [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void UpdateSingleAabb2(IntPtr world, IntPtr obj); +public static extern Vector3 AddObjectToWorld2(IntPtr world, IntPtr obj); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void UpdateAabbs2(IntPtr world); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern bool GetForceUpdateAllAabbs2(IntPtr world); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void SetForceUpdateAllAabbs2(IntPtr world, bool force); - -// ===================================================================================== -// btDynamicsWorld entries -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern bool AddObjectToWorld2(IntPtr world, IntPtr obj); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern bool RemoveObjectFromWorld2(IntPtr world, IntPtr obj); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern bool AddConstraintToWorld2(IntPtr world, IntPtr constrain, bool disableCollisionsBetweenLinkedObjects); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern bool RemoveConstraintFromWorld2(IntPtr world, IntPtr constrain); -// ===================================================================================== -// btCollisionObject entries -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern Vector3 GetAnisotripicFriction2(IntPtr constrain); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern Vector3 SetAnisotripicFriction2(IntPtr constrain, Vector3 frict); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern bool HasAnisotripicFriction2(IntPtr constrain); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void SetContactProcessingThreshold2(IntPtr obj, float val); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern float GetContactProcessingThreshold2(IntPtr obj); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern bool IsStaticObject2(IntPtr obj); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern bool IsKinematicObject2(IntPtr obj); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern bool IsStaticOrKinematicObject2(IntPtr obj); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern bool HasContactResponse2(IntPtr obj); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void SetCollisionShape2(IntPtr sim, IntPtr obj, IntPtr shape); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern IntPtr GetCollisionShape2(IntPtr obj); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern int GetActivationState2(IntPtr obj); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void SetActivationState2(IntPtr obj, int state); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void SetDeactivationTime2(IntPtr obj, float dtime); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern float GetDeactivationTime2(IntPtr obj); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void ForceActivationState2(IntPtr obj, ActivationState state); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void Activate2(IntPtr obj, bool forceActivation); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern bool IsActive2(IntPtr obj); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void SetRestitution2(IntPtr obj, float val); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern float GetRestitution2(IntPtr obj); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void SetFriction2(IntPtr obj, float val); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern float GetFriction2(IntPtr obj); - - /* Haven't defined the type 'Transform' -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern Transform GetWorldTransform2(IntPtr obj); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void setWorldTransform2(IntPtr obj, Transform trans); - */ +public static extern Vector3 RemoveObjectFromWorld2(IntPtr world, IntPtr obj); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern Vector3 GetPosition2(IntPtr obj); @@ -843,290 +473,85 @@ public static extern Vector3 GetPosition2(IntPtr obj); public static extern Quaternion GetOrientation2(IntPtr obj); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void SetTranslation2(IntPtr obj, Vector3 position, Quaternion rotation); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern IntPtr GetBroadphaseHandle2(IntPtr obj); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void SetBroadphaseHandle2(IntPtr obj, IntPtr handle); - - /* -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern Transform GetInterpolationWorldTransform2(IntPtr obj); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void SetInterpolationWorldTransform2(IntPtr obj, Transform trans); - */ - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void SetInterpolationLinearVelocity2(IntPtr obj, Vector3 vel); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void SetInterpolationAngularVelocity2(IntPtr obj, Vector3 vel); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void SetInterpolationVelocity2(IntPtr obj, Vector3 linearVel, Vector3 angularVel); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern float GetHitFraction2(IntPtr obj); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void SetHitFraction2(IntPtr obj, float val); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern CollisionFlags GetCollisionFlags2(IntPtr obj); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern CollisionFlags SetCollisionFlags2(IntPtr obj, CollisionFlags flags); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern CollisionFlags AddToCollisionFlags2(IntPtr obj, CollisionFlags flags); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern CollisionFlags RemoveFromCollisionFlags2(IntPtr obj, CollisionFlags flags); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern float GetCcdMotionThreshold2(IntPtr obj); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void SetCcdMotionThreshold2(IntPtr obj, float val); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern float GetCcdSweptSphereRadius2(IntPtr obj); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void SetCcdSweptSphereRadius2(IntPtr obj, float val); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern IntPtr GetUserPointer2(IntPtr obj); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void SetUserPointer2(IntPtr obj, IntPtr val); - -// ===================================================================================== -// btRigidBody entries -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void ApplyGravity2(IntPtr obj); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void SetGravity2(IntPtr obj, Vector3 val); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern Vector3 GetGravity2(IntPtr obj); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void SetDamping2(IntPtr obj, float lin_damping, float ang_damping); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern float GetLinearDamping2(IntPtr obj); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern float GetAngularDamping2(IntPtr obj); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern float GetLinearSleepingThreshold2(IntPtr obj); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern float GetAngularSleepingThreshold2(IntPtr obj); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void ApplyDamping2(IntPtr obj, float timeStep); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void SetMassProps2(IntPtr obj, float mass, Vector3 inertia); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern Vector3 GetLinearFactor2(IntPtr obj); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void SetLinearFactor2(IntPtr obj, Vector3 factor); - - /* -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void SetCenterOfMassTransform2(IntPtr obj, Transform trans); - */ - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void SetCenterOfMassByPosRot2(IntPtr obj, Vector3 pos, Quaternion rot); - -// Add a force to the object as if its mass is one. -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void ApplyCentralForce2(IntPtr obj, Vector3 force); - -// Set the force being applied to the object as if its mass is one. -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void SetObjectForce2(IntPtr obj, Vector3 force); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern Vector3 GetTotalForce2(IntPtr obj); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern Vector3 GetTotalTorque2(IntPtr obj); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern Vector3 GetInvInertiaDiagLocal2(IntPtr obj); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void SetInvInertiaDiagLocal2(IntPtr obj, Vector3 inert); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void SetSleepingThresholds2(IntPtr obj, float lin_threshold, float ang_threshold); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void ApplyTorque2(IntPtr obj, Vector3 torque); +public static extern bool SetTranslation2(IntPtr obj, Vector3 position, Quaternion rotation); -// Apply force at the given point. Will add torque to the object. [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void ApplyForce2(IntPtr obj, Vector3 force, Vector3 pos); +public static extern bool SetVelocity2(IntPtr obj, Vector3 velocity); -// Apply impulse to the object. Same as "ApplycentralForce" but force scaled by object's mass. [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void ApplyCentralImpulse2(IntPtr obj, Vector3 imp); +public static extern bool SetAngularVelocity2(IntPtr obj, Vector3 angularVelocity); -// Apply impulse to the object's torque. Force is scaled by object's mass. [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void ApplyTorqueImpulse2(IntPtr obj, Vector3 imp); +public static extern bool SetObjectForce2(IntPtr obj, Vector3 force); -// Apply impulse at the point given. For is scaled by object's mass and effects both linear and angular forces. [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void ApplyImpulse2(IntPtr obj, Vector3 imp, Vector3 pos); +public static extern bool AddObjectForce2(IntPtr obj, Vector3 force); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void ClearForces2(IntPtr obj); +public static extern bool SetCcdMotionThreshold2(IntPtr obj, float val); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void ClearAllForces2(IntPtr obj); +public static extern bool SetCcdSweepSphereRadius2(IntPtr obj, float val); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void UpdateInertiaTensor2(IntPtr obj); +public static extern bool SetDamping2(IntPtr obj, float lin_damping, float ang_damping); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern Vector3 GetCenterOfMassPosition2(IntPtr obj); +public static extern bool SetDeactivationTime2(IntPtr obj, float val); - /* [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern Transform GetCenterOfMassTransform2(IntPtr obj); - */ +public static extern bool SetSleepingThresholds2(IntPtr obj, float lin_threshold, float ang_threshold); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern Vector3 GetLinearVelocity2(IntPtr obj); +public static extern bool SetContactProcessingThreshold2(IntPtr obj, float val); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern Vector3 GetAngularVelocity2(IntPtr obj); +public static extern bool SetFriction2(IntPtr obj, float val); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void SetLinearVelocity2(IntPtr obj, Vector3 val); +public static extern bool SetRestitution2(IntPtr obj, float val); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void SetAngularVelocity2(IntPtr obj, Vector3 angularVelocity); +public static extern bool SetLinearVelocity2(IntPtr obj, Vector3 val); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern Vector3 GetVelocityInLocalPoint2(IntPtr obj, Vector3 pos); +public static extern bool SetInterpolation2(IntPtr obj, Vector3 lin, Vector3 ang); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void Translate2(IntPtr obj, Vector3 trans); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void UpdateDeactivation2(IntPtr obj, float timeStep); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern bool WantsSleeping2(IntPtr obj); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void SetAngularFactor2(IntPtr obj, float factor); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void SetAngularFactorV2(IntPtr obj, Vector3 factor); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern Vector3 GetAngularFactor2(IntPtr obj); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern bool IsInWorld2(IntPtr obj); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void AddConstraintRef2(IntPtr obj, IntPtr constrain); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void RemoveConstraintRef2(IntPtr obj, IntPtr constrain); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern IntPtr GetConstraintRef2(IntPtr obj, int index); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern int GetNumConstraintRefs2(IntPtr obj); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void SetCollisionFilterMask2(IntPtr body, uint filter, uint mask); - -// ===================================================================================== -// btCollisionShape entries - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern float GetAngularMotionDisc2(IntPtr shape); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern float GetContactBreakingThreshold2(IntPtr shape, float defaultFactor); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern bool IsPolyhedral2(IntPtr shape); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern bool IsConvex2d2(IntPtr shape); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern bool IsConvex2(IntPtr shape); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern bool IsNonMoving2(IntPtr shape); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern bool IsConcave2(IntPtr shape); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern bool IsCompound2(IntPtr shape); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern bool IsSoftBody2(IntPtr shape); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern bool IsInfinite2(IntPtr shape); +public static extern CollisionFlags GetCollisionFlags2(IntPtr obj); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void SetLocalScaling2(IntPtr shape, Vector3 scale); +public static extern IntPtr SetCollisionFlags2(IntPtr obj, CollisionFlags flags); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern Vector3 GetLocalScaling2(IntPtr shape); +public static extern IntPtr AddToCollisionFlags2(IntPtr obj, CollisionFlags flags); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern Vector3 CalculateLocalInertia2(IntPtr shape, float mass); +public static extern IntPtr RemoveFromCollisionFlags2(IntPtr obj, CollisionFlags flags); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern int GetShapeType2(IntPtr shape); +public static extern bool SetMassProps2(IntPtr obj, float mass, Vector3 inertia); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void SetMargin2(IntPtr shape, float val); +public static extern bool UpdateInertiaTensor2(IntPtr obj); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern float GetMargin2(IntPtr shape); +public static extern bool SetGravity2(IntPtr obj, Vector3 val); -// ===================================================================================== -// Debugging [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void DumpRigidBody2(IntPtr sim, IntPtr collisionObject); +public static extern IntPtr ClearForces2(IntPtr obj); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void DumpCollisionShape2(IntPtr sim, IntPtr collisionShape); +public static extern IntPtr ClearAllForces2(IntPtr obj); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void DumpConstraint2(IntPtr sim, IntPtr constrain); +public static extern bool SetMargin2(IntPtr obj, float val); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void DumpAllInfo2(IntPtr sim); +public static extern bool UpdateSingleAabb2(IntPtr world, IntPtr obj); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void DumpMapInfo2(IntPtr sim, IntPtr manInfo); +public static extern bool DestroyObject2(IntPtr world, uint id); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern void DumpPhysicsStatistics2(IntPtr sim); diff --git a/OpenSim/Region/Physics/Manager/PhysicsActor.cs b/OpenSim/Region/Physics/Manager/PhysicsActor.cs index 5af6373..14f65b8 100644 --- a/OpenSim/Region/Physics/Manager/PhysicsActor.cs +++ b/OpenSim/Region/Physics/Manager/PhysicsActor.cs @@ -340,12 +340,6 @@ namespace OpenSim.Region.Physics.Manager /// Getting this returns the velocity calculated by physics scene updates, using factors such as target velocity, /// time to accelerate and collisions. /// - public virtual Vector3 TargetVelocity - { - get { return Velocity; } - set { Velocity = value; } - } - public abstract Vector3 Velocity { get; set; } public abstract Vector3 Torque { get; set; } diff --git a/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs b/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs index c736557..f3b0630 100644 --- a/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs +++ b/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs @@ -100,7 +100,7 @@ namespace OpenSim.Region.Physics.OdePlugin private bool m_hackSentFly = false; private int m_requestedUpdateFrequency = 0; private Vector3 m_taintPosition; - internal bool m_avatarplanted = false; + /// /// Hold set forces so we can process them outside physics calculations. This prevents race conditions if we set force /// while calculatios are going on @@ -413,7 +413,7 @@ namespace OpenSim.Region.Physics.OdePlugin set { m_iscollidingObj = value; - if (value && !m_avatarplanted) + if (value) m_pidControllerActive = false; else m_pidControllerActive = true; diff --git a/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs b/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs index a59f63f..2e78de5 100644 --- a/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs +++ b/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs @@ -67,14 +67,6 @@ namespace OpenSim.Region.Physics.OdePlugin private int m_expectedCollisionContacts = 0; /// - /// Gets collide bits so that we can still perform land collisions if a mesh fails to load. - /// - private int BadMeshAssetCollideBits - { - get { return m_isphysical ? (int)CollisionCategories.Land : 0; } - } - - /// /// Is this prim subject to physics? Even if not, it's still solid for collision purposes. /// public override bool IsPhysical @@ -164,7 +156,7 @@ namespace OpenSim.Region.Physics.OdePlugin private PrimitiveBaseShape _pbs; private OdeScene _parent_scene; - + /// /// The physics space which contains prim geometries /// @@ -3341,6 +3333,7 @@ Console.WriteLine(" JointCreateFixed"); m_material = pMaterial; } + private void CheckMeshAsset() { if (_pbs.SculptEntry && !m_assetFailed && _pbs.SculptTexture != UUID.Zero) @@ -3350,14 +3343,14 @@ Console.WriteLine(" JointCreateFixed"); { RequestAssetDelegate assetProvider = _parent_scene.RequestAssetMethod; if (assetProvider != null) - assetProvider(_pbs.SculptTexture, MeshAssetReceived); + assetProvider(_pbs.SculptTexture, MeshAssetReveived); }); } } - private void MeshAssetReceived(AssetBase asset) + void MeshAssetReveived(AssetBase asset) { - if (asset != null && asset.Data != null && asset.Data.Length > 0) + if (asset.Data != null && asset.Data.Length > 0) { if (!_pbs.SculptEntry) return; @@ -3370,12 +3363,6 @@ Console.WriteLine(" JointCreateFixed"); m_taintshape = true; _parent_scene.AddPhysicsActorTaint(this); } - else - { - m_log.WarnFormat( - "[ODE PRIM]: Could not get mesh/sculpt asset {0} for {1} at {2} in {3}", - _pbs.SculptTexture, Name, _position, _parent_scene.Name); - } } } -} +} \ No newline at end of file diff --git a/OpenSim/Region/Physics/OdePlugin/OdeScene.cs b/OpenSim/Region/Physics/OdePlugin/OdeScene.cs index d53bd90..7a50c4c 100644 --- a/OpenSim/Region/Physics/OdePlugin/OdeScene.cs +++ b/OpenSim/Region/Physics/OdePlugin/OdeScene.cs @@ -501,8 +501,6 @@ namespace OpenSim.Region.Physics.OdePlugin public int physics_logging_interval = 0; public bool physics_logging_append_existing_logfile = false; - private bool avplanted = false; - private bool av_av_collisions_off = false; public d.Vector3 xyz = new d.Vector3(128.1640f, 128.3079f, 25.7600f); public d.Vector3 hpr = new d.Vector3(125.5000f, -17.0000f, 0.0000f); @@ -646,9 +644,6 @@ namespace OpenSim.Region.Physics.OdePlugin avMovementDivisorWalk = physicsconfig.GetFloat("av_movement_divisor_walk", 1.3f); avMovementDivisorRun = physicsconfig.GetFloat("av_movement_divisor_run", 0.8f); avCapRadius = physicsconfig.GetFloat("av_capsule_radius", 0.37f); - avplanted = physicsconfig.GetBoolean("av_planted", false); - av_av_collisions_off = physicsconfig.GetBoolean("av_av_collisions_off", false); - IsAvCapsuleTilted = physicsconfig.GetBoolean("av_capsule_tilted", false); contactsPerCollision = physicsconfig.GetInt("contacts_per_collision", 80); @@ -668,8 +663,6 @@ namespace OpenSim.Region.Physics.OdePlugin meshSculptLOD = physicsconfig.GetFloat("mesh_lod", 32f); MeshSculptphysicalLOD = physicsconfig.GetFloat("mesh_physical_lod", 16f); m_filterCollisions = physicsconfig.GetBoolean("filter_collisions", false); - - if (Environment.OSVersion.Platform == PlatformID.Unix) { @@ -1316,10 +1309,6 @@ namespace OpenSim.Region.Physics.OdePlugin if ((p1 is OdePrim) && (((OdePrim)p1).m_isVolumeDetect)) skipThisContact = true; // No collision on volume detect prims - if (av_av_collisions_off) - if ((p1 is OdeCharacter) && (p2 is OdeCharacter)) - skipThisContact = true; - if (!skipThisContact && (p2 is OdePrim) && (((OdePrim)p2).m_isVolumeDetect)) skipThisContact = true; // No collision on volume detect prims @@ -1983,8 +1972,7 @@ namespace OpenSim.Region.Physics.OdePlugin newAv.Flying = isFlying; newAv.MinimumGroundFlightOffset = minimumGroundFlightOffset; - newAv.m_avatarplanted = avplanted; - + return newAv; } @@ -1999,7 +1987,6 @@ namespace OpenSim.Region.Physics.OdePlugin internal void AddCharacter(OdeCharacter chr) { - chr.m_avatarplanted = avplanted; if (!_characters.Contains(chr)) { _characters.Add(chr); @@ -4320,4 +4307,4 @@ namespace OpenSim.Region.Physics.OdePlugin m_stats[ODEPrimUpdateFrameMsStatName] = 0; } } -} +} \ No newline at end of file diff --git a/OpenSim/Region/RegionCombinerModule/RegionCombinerModule.cs b/OpenSim/Region/RegionCombinerModule/RegionCombinerModule.cs index 905540d..3144d76 100644 --- a/OpenSim/Region/RegionCombinerModule/RegionCombinerModule.cs +++ b/OpenSim/Region/RegionCombinerModule/RegionCombinerModule.cs @@ -39,8 +39,11 @@ using OpenSim.Framework.Console; using OpenSim.Region.Physics.Manager; using Mono.Addins; +[assembly: Addin("RegionCombinerModule", "0.1")] +[assembly: AddinDependency("OpenSim", "0.5")] namespace OpenSim.Region.RegionCombinerModule { + [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] public class RegionCombinerModule : ISharedRegionModule, IRegionCombinerModule { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); @@ -719,21 +722,21 @@ namespace OpenSim.Region.RegionCombinerModule rootConn.ClientEventForwarder = new RegionCombinerClientEventForwarder(rootConn); // Sets up the CoarseLocationUpdate forwarder for this root region - scene.EventManager.OnNewPresence += SetCoarseLocationDelegate; + scene.EventManager.OnNewPresence += SetCourseLocationDelegate; // Adds this root region to a dictionary of regions that are connectable m_regions.Add(scene.RegionInfo.originRegionID, rootConn); } } - private void SetCoarseLocationDelegate(ScenePresence presence) + private void SetCourseLocationDelegate(ScenePresence presence) { - presence.SetSendCoarseLocationMethod(SendCoarseLocationUpdates); + presence.SetSendCourseLocationMethod(SendCourseLocationUpdates); } // This delegate was refactored for non-combined regions. // This combined region version will not use the pre-compiled lists of locations and ids - private void SendCoarseLocationUpdates(UUID sceneId, ScenePresence presence, List coarseLocations, List avatarUUIDs) + private void SendCourseLocationUpdates(UUID sceneId, ScenePresence presence, List coarseLocations, List avatarUUIDs) { RegionConnections connectiondata = null; lock (m_regions) @@ -756,18 +759,18 @@ namespace OpenSim.Region.RegionCombinerModule } }); - DistributeCoarseLocationUpdates(CoarseLocations, AvatarUUIDs, connectiondata, presence); + DistributeCourseLocationUpdates(CoarseLocations, AvatarUUIDs, connectiondata, presence); } - private void DistributeCoarseLocationUpdates(List locations, List uuids, + private void DistributeCourseLocationUpdates(List locations, List uuids, RegionConnections connectiondata, ScenePresence rootPresence) { RegionData[] rdata = connectiondata.ConnectedRegions.ToArray(); //List clients = new List(); - Dictionary updates = new Dictionary(); + Dictionary updates = new Dictionary(); // Root Region entry - RegionCoarseLocationStruct rootupdatedata = new RegionCoarseLocationStruct(); + RegionCourseLocationStruct rootupdatedata = new RegionCourseLocationStruct(); rootupdatedata.Locations = new List(); rootupdatedata.Uuids = new List(); rootupdatedata.Offset = Vector2.Zero; @@ -781,7 +784,7 @@ namespace OpenSim.Region.RegionCombinerModule foreach (RegionData regiondata in rdata) { Vector2 offset = new Vector2(regiondata.Offset.X, regiondata.Offset.Y); - RegionCoarseLocationStruct updatedata = new RegionCoarseLocationStruct(); + RegionCourseLocationStruct updatedata = new RegionCourseLocationStruct(); updatedata.Locations = new List(); updatedata.Uuids = new List(); updatedata.Offset = offset; @@ -807,7 +810,7 @@ namespace OpenSim.Region.RegionCombinerModule if (!updates.ContainsKey(offset)) { // This shouldn't happen - RegionCoarseLocationStruct updatedata = new RegionCoarseLocationStruct(); + RegionCourseLocationStruct updatedata = new RegionCourseLocationStruct(); updatedata.Locations = new List(); updatedata.Uuids = new List(); updatedata.Offset = offset; diff --git a/OpenSim/Region/RegionCombinerModule/RegionCourseLocation.cs b/OpenSim/Region/RegionCombinerModule/RegionCourseLocation.cs index 224ac99..53a678f 100644 --- a/OpenSim/Region/RegionCombinerModule/RegionCourseLocation.cs +++ b/OpenSim/Region/RegionCombinerModule/RegionCourseLocation.cs @@ -33,7 +33,7 @@ using OpenSim.Framework; namespace OpenSim.Region.RegionCombinerModule { - struct RegionCoarseLocationStruct + struct RegionCourseLocationStruct { public List Locations; public List Uuids; diff --git a/OpenSim/Region/RegionCombinerModule/Resources/RegionCombinerModule.addin.xml b/OpenSim/Region/RegionCombinerModule/Resources/RegionCombinerModule.addin.xml deleted file mode 100644 index 13cb8b6..0000000 --- a/OpenSim/Region/RegionCombinerModule/Resources/RegionCombinerModule.addin.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 3bbdbe8..82de06f 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -59,7 +59,6 @@ using GridRegion = OpenSim.Services.Interfaces.GridRegion; using PresenceInfo = OpenSim.Services.Interfaces.PresenceInfo; using PrimType = OpenSim.Region.Framework.Scenes.PrimType; using AssetLandmark = OpenSim.Framework.AssetLandmark; -using RegionFlags = OpenSim.Framework.RegionFlags; using LSL_Float = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLFloat; using LSL_Integer = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLInteger; @@ -113,7 +112,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api protected Dictionary m_userInfoCache = new Dictionary(); protected int EMAIL_PAUSE_TIME = 20; // documented delay value for smtp. - protected ISoundModule m_SoundModule = null; // protected Timer m_ShoutSayTimer; protected int m_SayShoutCount = 0; @@ -161,7 +159,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api m_TransferModule = m_ScriptEngine.World.RequestModuleInterface(); m_UrlModule = m_ScriptEngine.World.RequestModuleInterface(); - m_SoundModule = m_ScriptEngine.World.RequestModuleInterface(); AsyncCommands = new AsyncCommandManager(ScriptEngine); } @@ -344,7 +341,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api return GetLinkParts(m_host, linkType); } - public static List GetLinkParts(SceneObjectPart part, int linkType) + private List GetLinkParts(SceneObjectPart part, int linkType) { List ret = new List(); if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted) @@ -429,40 +426,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api return key; } - /// - /// Return the UUID of the asset matching the specified key or name - /// and asset type. - /// - /// - /// - /// - protected UUID KeyOrName(string k, AssetType type) + // convert a LSL_Rotation to a Quaternion + public static Quaternion Rot2Quaternion(LSL_Rotation r) { - UUID key; - - if (!UUID.TryParse(k, out key)) - { - TaskInventoryItem item = m_host.Inventory.GetInventoryItem(k); - if (item != null && item.Type == (int)type) - key = item.AssetID; - } - else - { - lock (m_host.TaskInventory) - { - foreach (KeyValuePair item in m_host.TaskInventory) - { - if (item.Value.Type == (int)type && item.Value.Name == k) - { - key = item.Value.ItemID; - break; - } - } - } - } - - - return key; + Quaternion q = new Quaternion((float)r.x, (float)r.y, (float)r.z, (float)r.s); + q.Normalize(); + return q; } //These are the implementations of the various ll-functions used by the LSL scripts. @@ -1271,7 +1240,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public LSL_Float llGround(LSL_Vector offset) { m_host.AddScriptLPS(1); - Vector3 pos = m_host.GetWorldPosition() + (Vector3)offset; + Vector3 pos = m_host.GetWorldPosition() + new Vector3((float)offset.x, + (float)offset.y, + (float)offset.z); //Get the slope normal. This gives us the equation of the plane tangent to the slope. LSL_Vector vsn = llGroundNormal(offset); @@ -1521,22 +1492,32 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (part == null || part.ParentGroup.IsDeleted) return; - // First we need to check whether or not we need to clamp the size of a physics-enabled prim + if (scale.x < 0.01) + scale.x = 0.01; + if (scale.y < 0.01) + scale.y = 0.01; + if (scale.z < 0.01) + scale.z = 0.01; + PhysicsActor pa = part.ParentGroup.RootPart.PhysActor; + if (pa != null && pa.IsPhysical) { - scale.x = Math.Max(World.m_minPhys, Math.Min(World.m_maxPhys, scale.x)); - scale.y = Math.Max(World.m_minPhys, Math.Min(World.m_maxPhys, scale.y)); - scale.z = Math.Max(World.m_minPhys, Math.Min(World.m_maxPhys, scale.z)); - } - else - { - // If not physical, then we clamp the scale to the non-physical min/max - scale.x = Math.Max(World.m_minNonphys, Math.Min(World.m_maxNonphys, scale.x)); - scale.y = Math.Max(World.m_minNonphys, Math.Min(World.m_maxNonphys, scale.y)); - scale.z = Math.Max(World.m_minNonphys, Math.Min(World.m_maxNonphys, scale.z)); + if (scale.x > World.m_maxPhys) + scale.x = World.m_maxPhys; + if (scale.y > World.m_maxPhys) + scale.y = World.m_maxPhys; + if (scale.z > World.m_maxPhys) + scale.z = World.m_maxPhys; } + if (scale.x > World.m_maxNonphys) + scale.x = World.m_maxNonphys; + if (scale.y > World.m_maxNonphys) + scale.y = World.m_maxNonphys; + if (scale.z > World.m_maxNonphys) + scale.z = World.m_maxNonphys; + Vector3 tmp = part.Scale; tmp.X = (float)scale.x; tmp.Y = (float)scale.y; @@ -1609,7 +1590,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (face == ScriptBaseClass.ALL_SIDES) face = SceneObjectPart.ALL_SIDES; - m_host.SetFaceColorAlpha(face, color, null); + m_host.SetFaceColor(new Vector3((float)color.x, (float)color.y, (float)color.z), face); } public void SetTexGen(SceneObjectPart part, int face,int style) @@ -2221,7 +2202,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api pos.x > (Constants.RegionSize + 10) || // return FALSE if more than 10 meters into a east-adjacent region. pos.y < -10.0 || // return FALSE if more than 10 meters into a south-adjacent region. pos.y > (Constants.RegionSize + 10) || // return FALSE if more than 10 meters into a north-adjacent region. - pos.z > Constants.RegionHeight // return FALSE if altitude than 4096m + pos.z > 4096 // return FALSE if altitude than 4096m ) ) { @@ -2232,15 +2213,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api // this could possibly be done in the above else-if block, but we're doing the check here to keep the code easier to read. Vector3 objectPos = m_host.ParentGroup.RootPart.AbsolutePosition; - LandData here = World.GetLandData(objectPos); - LandData there = World.GetLandData(pos); + LandData here = World.GetLandData((float)objectPos.X, (float)objectPos.Y); + LandData there = World.GetLandData((float)pos.x, (float)pos.y); // we're only checking prim limits if it's moving to a different parcel under the assumption that if the object got onto the parcel without exceeding the prim limits. bool sameParcel = here.GlobalID == there.GlobalID; - if (!sameParcel && !World.Permissions.CanRezObject( - m_host.ParentGroup.PrimCount, m_host.ParentGroup.OwnerID, pos)) + if (!sameParcel && !World.Permissions.CanObjectEntry(m_host.UUID, false, new Vector3((float)pos.x, (float)pos.y, (float)pos.z))) { return 0; } @@ -2299,15 +2279,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (part.ParentGroup.RootPart == part) { SceneObjectGroup parent = part.ParentGroup; - if (!World.Permissions.CanObjectEntry(parent.UUID, false, (Vector3)toPos)) + Vector3 dest = new Vector3((float)toPos.x, (float)toPos.y, (float)toPos.z); + if (!World.Permissions.CanObjectEntry(parent.UUID, false, dest)) return; Util.FireAndForget(delegate(object x) { - parent.UpdateGroupPosition((Vector3)toPos); + parent.UpdateGroupPosition(dest); }); } else { - part.OffsetPosition = (Vector3)toPos; + part.OffsetPosition = new Vector3((float)toPos.x, (float)toPos.y, (float)toPos.z); SceneObjectGroup parent = part.ParentGroup; parent.HasGroupChanged = true; parent.ScheduleGroupForTerseUpdate(); @@ -2317,7 +2298,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public LSL_Vector llGetPos() { m_host.AddScriptLPS(1); - return m_host.GetWorldPosition(); + Vector3 pos = m_host.GetWorldPosition(); + return new LSL_Vector(pos.X, pos.Y, pos.Z); } public LSL_Vector llGetLocalPos() @@ -2344,9 +2326,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api pos = part.AbsolutePosition; } -// m_log.DebugFormat("[LSL API]: Returning {0} in GetPartLocalPos()", pos); - - return new LSL_Vector(pos); + return new LSL_Vector(pos.X, pos.Y, pos.Z); } public void llSetRot(LSL_Rotation rot) @@ -2354,18 +2334,26 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api m_host.AddScriptLPS(1); // try to let this work as in SL... - if (m_host.ParentID == 0) - { - // special case: If we are root, rotate complete SOG to new rotation - SetRot(m_host, rot); + if (m_host.LinkNum < 2) + { + // Special case: If we are root, rotate complete SOG to new + // rotation. + // We are root if the link number is 0 (single prim) or 1 + // (root prim). ParentID may be nonzero in attachments and + // using it would cause attachments and HUDs to rotate + // to the wrong positions. + + SetRot(m_host, Rot2Quaternion(rot)); } else { // we are a child. The rotation values will be set to the one of root modified by rot, as in SL. Don't ask. - SceneObjectPart rootPart = m_host.ParentGroup.RootPart; - if (rootPart != null) // better safe than sorry + SceneObjectPart rootPart; + if (m_host.ParentGroup != null) // better safe than sorry { - SetRot(m_host, rootPart.RotationOffset * (Quaternion)rot); + rootPart = m_host.ParentGroup.RootPart; + if (rootPart != null) + SetRot(m_host, rootPart.RotationOffset * Rot2Quaternion(rot)); } } @@ -2375,7 +2363,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public void llSetLocalRot(LSL_Rotation rot) { m_host.AddScriptLPS(1); - SetRot(m_host, rot); + + SetRot(m_host, Rot2Quaternion(rot)); ScriptSleep(200); } @@ -2487,7 +2476,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (local != 0) force *= llGetRot(); - m_host.ParentGroup.RootPart.SetForce(force); + m_host.ParentGroup.RootPart.SetForce(new Vector3((float)force.x, (float)force.y, (float)force.z)); } } @@ -2499,7 +2488,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (!m_host.ParentGroup.IsDeleted) { - force = m_host.ParentGroup.RootPart.GetForce(); + Vector3 tmpForce = m_host.ParentGroup.RootPart.GetForce(); + force.x = tmpForce.X; + force.y = tmpForce.Y; + force.z = tmpForce.Z; } return force; @@ -2508,8 +2500,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public LSL_Integer llTarget(LSL_Vector position, double range) { m_host.AddScriptLPS(1); - return m_host.ParentGroup.registerTargetWaypoint(position, - (float)range); + return m_host.ParentGroup.registerTargetWaypoint( + new Vector3((float)position.x, (float)position.y, (float)position.z), (float)range); } public void llTargetRemove(int number) @@ -2521,7 +2513,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public LSL_Integer llRotTarget(LSL_Rotation rot, double error) { m_host.AddScriptLPS(1); - return m_host.ParentGroup.registerRotTargetWaypoint(rot, (float)error); + return m_host.ParentGroup.registerRotTargetWaypoint( + new Quaternion((float)rot.x, (float)rot.y, (float)rot.z, (float)rot.s), (float)error); } public void llRotTargetRemove(int number) @@ -2533,7 +2526,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public void llMoveToTarget(LSL_Vector target, double tau) { m_host.AddScriptLPS(1); - m_host.MoveToTarget(target, (float)tau); + m_host.MoveToTarget(new Vector3((float)target.x, (float)target.y, (float)target.z), (float)tau); } public void llStopMoveToTarget() @@ -2546,7 +2539,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { m_host.AddScriptLPS(1); //No energy force yet - Vector3 v = force; + Vector3 v = new Vector3((float)force.x, (float)force.y, (float)force.z); if (v.Length() > 20000.0f) { v.Normalize(); @@ -2559,13 +2552,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public void llApplyRotationalImpulse(LSL_Vector force, int local) { m_host.AddScriptLPS(1); - m_host.ParentGroup.RootPart.ApplyAngularImpulse(force, local != 0); + m_host.ParentGroup.RootPart.ApplyAngularImpulse(new Vector3((float)force.x, (float)force.y, (float)force.z), local != 0); } public void llSetTorque(LSL_Vector torque, int local) { m_host.AddScriptLPS(1); - m_host.ParentGroup.RootPart.SetAngularImpulse(torque, local != 0); + m_host.ParentGroup.RootPart.SetAngularImpulse(new Vector3((float)torque.x, (float)torque.y, (float)torque.z), local != 0); } public LSL_Vector llGetTorque() @@ -2675,32 +2668,63 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api m_host.AddScriptLPS(1); // send the sound, once, to all clients in range - if (m_SoundModule != null) - { - m_SoundModule.SendSound(m_host.UUID, - KeyOrName(sound, AssetType.Sound), volume, false, 0, - 0, false, false); - } + m_host.SendSound(KeyOrName(sound).ToString(), volume, false, 0, 0, false, false); } + // Xantor 20080528 we should do this differently. + // 1) apply the sound to the object + // 2) schedule full update + // just sending the sound out once doesn't work so well when other avatars come in view later on + // or when the prim gets moved, changed, sat on, whatever + // see large number of mantises (mantes?) + // 20080530 Updated to remove code duplication + // 20080530 Stop sound if there is one, otherwise volume only changes don't work public void llLoopSound(string sound, double volume) { m_host.AddScriptLPS(1); - if (m_SoundModule != null) - { - m_SoundModule.LoopSound(m_host.UUID, KeyOrName(sound), - volume, 20, false); - } + + if (m_host.Sound != UUID.Zero) + llStopSound(); + + m_host.Sound = KeyOrName(sound); + m_host.SoundGain = volume; + m_host.SoundFlags = 1; // looping + m_host.SoundRadius = 20; // Magic number, 20 seems reasonable. Make configurable? + + m_host.ScheduleFullUpdate(); + m_host.SendFullUpdateToAllClients(); } public void llLoopSoundMaster(string sound, double volume) { m_host.AddScriptLPS(1); - if (m_SoundModule != null) + m_host.ParentGroup.LoopSoundMasterPrim = m_host; + lock (m_host.ParentGroup.LoopSoundSlavePrims) { - m_SoundModule.LoopSound(m_host.UUID, KeyOrName(sound), - volume, 20, true); + foreach (SceneObjectPart prim in m_host.ParentGroup.LoopSoundSlavePrims) + { + if (prim.Sound != UUID.Zero) + llStopSound(); + + prim.Sound = KeyOrName(sound); + prim.SoundGain = volume; + prim.SoundFlags = 1; // looping + prim.SoundRadius = 20; // Magic number, 20 seems reasonable. Make configurable? + + prim.ScheduleFullUpdate(); + prim.SendFullUpdateToAllClients(); + } } + if (m_host.Sound != UUID.Zero) + llStopSound(); + + m_host.Sound = KeyOrName(sound); + m_host.SoundGain = volume; + m_host.SoundFlags = 1; // looping + m_host.SoundRadius = 20; // Magic number, 20 seems reasonable. Make configurable? + + m_host.ScheduleFullUpdate(); + m_host.SendFullUpdateToAllClients(); } public void llLoopSoundSlave(string sound, double volume) @@ -2717,39 +2741,61 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api m_host.AddScriptLPS(1); // send the sound, once, to all clients in range - if (m_SoundModule != null) - { - m_SoundModule.SendSound(m_host.UUID, - KeyOrName(sound, AssetType.Sound), volume, false, 0, - 0, true, false); - } + m_host.SendSound(KeyOrName(sound).ToString(), volume, false, 0, 0, true, false); } public void llTriggerSound(string sound, double volume) { m_host.AddScriptLPS(1); - // send the sound, once, to all clients in rangeTrigger or play an attached sound in this part's inventory. - if (m_SoundModule != null) - { - m_SoundModule.SendSound(m_host.UUID, - KeyOrName(sound, AssetType.Sound), volume, true, 0, 0, - false, false); - } + // send the sound, once, to all clients in range + m_host.SendSound(KeyOrName(sound).ToString(), volume, true, 0, 0, false, false); } + // Xantor 20080528: Clear prim data of sound instead public void llStopSound() { m_host.AddScriptLPS(1); - - if (m_SoundModule != null) - m_SoundModule.StopSound(m_host.UUID); + if (m_host.ParentGroup.LoopSoundSlavePrims.Contains(m_host)) + { + if (m_host.ParentGroup.LoopSoundMasterPrim == m_host) + { + foreach (SceneObjectPart part in m_host.ParentGroup.LoopSoundSlavePrims) + { + part.Sound = UUID.Zero; + part.SoundGain = 0; + part.SoundFlags = 0; + part.SoundRadius = 0; + part.ScheduleFullUpdate(); + part.SendFullUpdateToAllClients(); + } + m_host.ParentGroup.LoopSoundMasterPrim = null; + m_host.ParentGroup.LoopSoundSlavePrims.Clear(); + } + else + { + m_host.Sound = UUID.Zero; + m_host.SoundGain = 0; + m_host.SoundFlags = 0; + m_host.SoundRadius = 0; + m_host.ScheduleFullUpdate(); + m_host.SendFullUpdateToAllClients(); + } + } + else + { + m_host.Sound = UUID.Zero; + m_host.SoundGain = 0; + m_host.SoundFlags = 0; + m_host.SoundRadius = 0; + m_host.ScheduleFullUpdate(); + m_host.SendFullUpdateToAllClients(); + } } public void llPreloadSound(string sound) { m_host.AddScriptLPS(1); - if (m_SoundModule != null) - m_SoundModule.PreloadSound(m_host.UUID, KeyOrName(sound), 0); + m_host.PreloadSound(sound); ScriptSleep(1000); } @@ -3077,10 +3123,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api return; } + Vector3 llpos = new Vector3((float)pos.x, (float)pos.y, (float)pos.z); + Vector3 llvel = new Vector3((float)vel.x, (float)vel.y, (float)vel.z); + // need the magnitude later // float velmag = (float)Util.GetMagnitude(llvel); - SceneObjectGroup new_group = World.RezObject(m_host, item, pos, rot, vel, param); + SceneObjectGroup new_group = World.RezObject(m_host, item, llpos, Rot2Quaternion(rot), llvel, param); // If either of these are null, then there was an unknown error. if (new_group == null) @@ -3107,11 +3156,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api PhysicsActor pa = new_group.RootPart.PhysActor; - if (pa != null && pa.IsPhysical && (Vector3)vel != Vector3.Zero) + if (pa != null && pa.IsPhysical && llvel != Vector3.Zero) { float groupmass = new_group.GetMass(); - vel *= -groupmass; - llApplyImpulse(vel, 0); + llvel *= -groupmass; + llApplyImpulse(new LSL_Vector(llvel.X, llvel.Y,llvel.Z), 0); } // Variable script delay? (see (http://wiki.secondlife.com/wiki/LSL_Delay) return; @@ -3162,7 +3211,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api return; } - m_host.StartLookAt((Quaternion)(r3 * r2 * r1), (float)strength, (float)damping); + m_host.StartLookAt(Rot2Quaternion(r3 * r2 * r1), (float)strength, (float)damping); } } @@ -3588,7 +3637,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } else { - m_host.RotLookAt(target, (float)strength, (float)damping); + m_host.RotLookAt(Rot2Quaternion(target), (float)strength, (float)damping); } } @@ -3669,7 +3718,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api protected void TargetOmega(SceneObjectPart part, LSL_Vector axis, double spinrate, double gain) { - part.UpdateAngularVelocity(axis * spinrate); + part.UpdateAngularVelocity(new Vector3((float)(axis.x * spinrate), (float)(axis.y * spinrate), (float)(axis.z * spinrate))); } public LSL_Integer llGetStartParameter() @@ -3883,7 +3932,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api try { foreach (SceneObjectPart part in parts) - part.SetFaceColorAlpha(face, color, null); + part.SetFaceColor(new Vector3((float)color.x, (float)color.y, (float)color.z), face); } finally { @@ -4109,16 +4158,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } /// - /// Returns the name of the child prim or seated avatar matching the - /// specified link number. - /// - /// - /// The number of a link in the linkset or a link-related constant. - /// - /// - /// The name determined to match the specified link number. - /// - /// /// The rules governing the returned name are not simple. The only /// time a blank name is returned is if the target prim has a blank /// name. If no prim with the given link number can be found then @@ -4146,14 +4185,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api /// Mentions NULL_KEY being returned /// http://wiki.secondlife.com/wiki/LlGetLinkName /// Mentions using the LINK_* constants, some of which are negative - /// + /// public LSL_String llGetLinkName(int linknum) { m_host.AddScriptLPS(1); - // simplest case, this prims link number - if (linknum == m_host.LinkNum || linknum == ScriptBaseClass.LINK_THIS) - return m_host.Name; - // parse for sitting avatare-names List nametable = new List(); World.ForEachRootScenePresence(delegate(ScenePresence presence) @@ -4177,6 +4212,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api return nametable[totalprims - linknum]; } + // simplest case, this prims link number + if (m_host.LinkNum == linknum) + return m_host.Name; + // Single prim if (m_host.LinkNum == 0) { @@ -4325,7 +4364,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api World.RegionInfo.RegionName+" "+ m_host.AbsolutePosition.ToString(), agentItem.ID, true, m_host.AbsolutePosition, - bucket, true); + bucket); ScenePresence sp; @@ -4363,7 +4402,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public void llSetText(string text, LSL_Vector color, double alpha) { m_host.AddScriptLPS(1); - Vector3 av3 = Util.Clip(color, 0.0f, 1.0f); + Vector3 av3 = new Vector3(Util.Clip((float)color.x, 0.0f, 1.0f), + Util.Clip((float)color.y, 0.0f, 1.0f), + Util.Clip((float)color.z, 0.0f, 1.0f)); if (text.Length > 254) text = text.Remove(254); @@ -4590,11 +4631,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api ScriptSleep(5000); } - public void llTeleportAgent(string agent, string destination, LSL_Vector targetPos, LSL_Vector targetLookAt) + public void llTeleportAgent(string agent, string destination, LSL_Vector pos, LSL_Vector lookAt) { m_host.AddScriptLPS(1); UUID agentId = new UUID(); + Vector3 targetPos = new Vector3((float)pos.x, (float)pos.y, (float)pos.z); + Vector3 targetLookAt = new Vector3((float)lookAt.x, (float)lookAt.y, (float)lookAt.z); + if (UUID.TryParse(agent, out agentId)) { ScenePresence presence = World.GetScenePresence(agentId); @@ -4623,13 +4667,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } } - public void llTeleportAgentGlobalCoords(string agent, LSL_Vector global_coords, LSL_Vector targetPos, LSL_Vector targetLookAt) + public void llTeleportAgentGlobalCoords(string agent, LSL_Vector global_coords, LSL_Vector pos, LSL_Vector lookAt) { m_host.AddScriptLPS(1); UUID agentId = new UUID(); ulong regionHandle = Utils.UIntsToLong((uint)global_coords.x, (uint)global_coords.y); + Vector3 targetPos = new Vector3((float)pos.x, (float)pos.y, (float)pos.z); + Vector3 targetLookAt = new Vector3((float)lookAt.x, (float)lookAt.y, (float)lookAt.z); if (UUID.TryParse(agent, out agentId)) { ScenePresence presence = World.GetScenePresence(agentId); @@ -4731,7 +4777,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api return; } // TODO: Parameter check logic required. - m_host.CollisionSound = KeyOrName(impact_sound, AssetType.Sound); + UUID soundId = UUID.Zero; + if (!UUID.TryParse(impact_sound, out soundId)) + { + TaskInventoryItem item = m_host.Inventory.GetInventoryItem(impact_sound); + + if (item != null && item.Type == (int)AssetType.Sound) + soundId = item.AssetID; + } + + m_host.CollisionSound = soundId; m_host.CollisionSoundVolume = (float)impact_volume; m_host.CollisionSoundType = 1; } @@ -4917,7 +4972,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api distance_attenuation = 1f / normalized_units; } - Vector3 applied_linear_impulse = impulse; + Vector3 applied_linear_impulse = new Vector3((float)impulse.x, (float)impulse.y, (float)impulse.z); { float impulse_length = applied_linear_impulse.Length(); @@ -5565,15 +5620,25 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api /// separated list. There is a space after /// each comma. /// + public LSL_String llList2CSV(LSL_List src) { + + string ret = String.Empty; + int x = 0; + m_host.AddScriptLPS(1); - return string.Join(", ", - (new List(src.Data)).ConvertAll(o => - { - return o.ToString(); - }).ToArray()); + if (src.Data.Length > 0) + { + ret = src.Data[x++].ToString(); + for (; x < src.Data.Length; x++) + { + ret += ", "+src.Data[x].ToString(); + } + } + + return ret; } /// @@ -5872,36 +5937,27 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api /// Returns the index of the first occurrence of test /// in src. /// - /// Source list - /// List to search for - /// - /// The index number of the point in src where test was found if it was found. - /// Otherwise returns -1 - /// + public LSL_Integer llListFindList(LSL_List src, LSL_List test) { + int index = -1; int length = src.Length - test.Length + 1; m_host.AddScriptLPS(1); // If either list is empty, do not match + if (src.Length != 0 && test.Length != 0) { for (int i = 0; i < length; i++) { - // Why this piece of insanity? This is because most script constants are C# value types (e.g. int) - // rather than wrapped LSL types. Such a script constant does not have int.Equal(LSL_Integer) code - // and so the comparison fails even if the LSL_Integer conceptually has the same value. - // Therefore, here we test Equals on both the source and destination objects. - // However, a future better approach may be use LSL struct script constants (e.g. LSL_Integer(1)). - if (src.Data[i].Equals(test.Data[0]) || test.Data[0].Equals(src.Data[i])) + if (src.Data[i].Equals(test.Data[0])) { int j; for (j = 1; j < test.Length; j++) - if (!(src.Data[i+j].Equals(test.Data[j]) || test.Data[j].Equals(src.Data[i+j]))) + if (!src.Data[i+j].Equals(test.Data[j])) break; - if (j == test.Length) { index = i; @@ -5912,18 +5968,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } return index; + } public LSL_String llGetObjectName() { m_host.AddScriptLPS(1); - return m_host.Name !=null ? m_host.Name : String.Empty; + return m_host.Name!=null?m_host.Name:String.Empty; } public void llSetObjectName(string name) { m_host.AddScriptLPS(1); - m_host.Name = name != null ? name : String.Empty; + m_host.Name = name!=null?name:String.Empty; } public LSL_String llGetDate() @@ -6097,7 +6154,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api flags |= ScriptBaseClass.AGENT_SITTING; } - if (agent.Animator.Animations.ImplicitDefaultAnimation.AnimID + if (agent.Animator.Animations.DefaultAnimation.AnimID == DefaultAvatarAnimations.AnimsUUID["SIT_GROUND_CONSTRAINED"]) { flags |= ScriptBaseClass.AGENT_SITTING; @@ -6254,16 +6311,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api m_host.AddScriptLPS(1); List parts = GetLinkParts(linknumber); - - try + if (parts.Count > 0) { - foreach (SceneObjectPart part in parts) + try + { + foreach (var part in parts) + { + SetTextureAnim(part, mode, face, sizex, sizey, start, length, rate); + } + } + finally { - SetTextureAnim(part, mode, face, sizex, sizey, start, length, rate); } - } - finally - { } } @@ -6293,12 +6352,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api LSL_Vector bottom_south_west) { m_host.AddScriptLPS(1); - if (m_SoundModule != null) - { - m_SoundModule.TriggerSoundLimited(m_host.UUID, - KeyOrName(sound, AssetType.Sound), volume, - bottom_south_west, top_north_east); - } + float radius1 = (float)llVecDist(llGetPos(), top_north_east); + float radius2 = (float)llVecDist(llGetPos(), bottom_south_west); + float radius = Math.Abs(radius1 - radius2); + m_host.SendSound(KeyOrName(sound).ToString(), volume, true, 0, radius, false, false); } public void llEjectFromLand(string pest) @@ -6484,7 +6541,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api //Plug the x,y coordinates of the slope normal into the equation of the plane to get //the height of that point on the plane. The resulting vector gives the slope. - Vector3 vsl = vsn; + Vector3 vsl = new Vector3(); + vsl.X = (float)vsn.x; + vsl.Y = (float)vsn.y; vsl.Z = (float)(((vsn.x * vsn.x) + (vsn.y * vsn.y)) / (-1 * vsn.z)); vsl.Normalize(); //Normalization might be overkill here @@ -6495,7 +6554,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public LSL_Vector llGroundNormal(LSL_Vector offset) { m_host.AddScriptLPS(1); - Vector3 pos = m_host.GetWorldPosition() + (Vector3)offset; + Vector3 pos = m_host.GetWorldPosition() + new Vector3((float)offset.x, + (float)offset.y, + (float)offset.z); // Clamp to valid position if (pos.X < 0) pos.X = 0; @@ -6660,7 +6721,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api List parts = GetLinkParts(linknumber); - foreach (SceneObjectPart part in parts) + foreach (var part in parts) { SetParticleSystem(part, rules); } @@ -6904,17 +6965,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (m_TransferModule != null) { byte[] bucket = new byte[] { (byte)AssetType.Folder }; - - Vector3 pos = m_host.AbsolutePosition; - + GridInstantMessage msg = new GridInstantMessage(World, - m_host.OwnerID, m_host.Name, destID, + m_host.UUID, m_host.Name + ", an object owned by " + + resolveName(m_host.OwnerID) + ",", destID, (byte)InstantMessageDialog.TaskInventoryOffered, - false, string.Format("'{0}'", category), -// We won't go so far as to add a SLURL, but this is the format used by LL as of 2012-10-06 -// false, string.Format("'{0}' ( http://slurl.com/secondlife/{1}/{2}/{3}/{4} )", category, World.Name, (int)pos.X, (int)pos.Y, (int)pos.Z), - folderID, false, pos, - bucket, false); + false, category + "\n" + m_host.Name + " is located at " + + World.RegionInfo.RegionName + " " + + m_host.AbsolutePosition.ToString(), + folderID, true, m_host.AbsolutePosition, + bucket); m_TransferModule.SendInstantMessage(msg, delegate(bool success) {}); } @@ -6950,7 +7010,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (!m_host.ParentGroup.IsDeleted) { - m_host.ParentGroup.RootPart.SetVehicleVectorParam(param, vec); + m_host.ParentGroup.RootPart.SetVehicleVectorParam(param, + new Vector3((float)vec.x, (float)vec.y, (float)vec.z)); } } @@ -6962,7 +7023,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (!m_host.ParentGroup.IsDeleted) { - m_host.ParentGroup.RootPart.SetVehicleRotationParam(param, rot); + m_host.ParentGroup.RootPart.SetVehicleRotationParam(param, Rot2Quaternion(rot)); } } @@ -6992,8 +7053,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (rot.s == 0 && rot.x == 0 && rot.y == 0 && rot.z == 0) rot.s = 1; // ZERO_ROTATION = 0,0,0,1 - part.SitTargetPosition = offset; - part.SitTargetOrientation = rot; + part.SitTargetPosition = new Vector3((float)offset.x, (float)offset.y, (float)offset.z); + part.SitTargetOrientation = Rot2Quaternion(rot); part.ParentGroup.HasGroupChanged = true; } @@ -7096,13 +7157,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public void llSetCameraEyeOffset(LSL_Vector offset) { m_host.AddScriptLPS(1); - m_host.SetCameraEyeOffset(offset); + m_host.SetCameraEyeOffset(new Vector3((float)offset.x, (float)offset.y, (float)offset.z)); } public void llSetCameraAtOffset(LSL_Vector offset) { m_host.AddScriptLPS(1); - m_host.SetCameraAtOffset(offset); + m_host.SetCameraAtOffset(new Vector3((float)offset.x, (float)offset.y, (float)offset.z)); } public LSL_String llDumpList2String(LSL_List src, string seperator) @@ -7124,7 +7185,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public LSL_Integer llScriptDanger(LSL_Vector pos) { m_host.AddScriptLPS(1); - bool result = World.ScriptDanger(m_host.LocalId, pos); + bool result = World.ScriptDanger(m_host.LocalId, new Vector3((float)pos.x, (float)pos.y, (float)pos.z)); if (result) { return 1; @@ -7706,7 +7767,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { m_host.AddScriptLPS(1); - setLinkPrimParams(ScriptBaseClass.LINK_THIS, rules, "llSetPrimitiveParams"); + setLinkPrimParams(ScriptBaseClass.LINK_THIS, rules); ScriptSleep(200); } @@ -7715,12 +7776,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { m_host.AddScriptLPS(1); - setLinkPrimParams(linknumber, rules, "llSetLinkPrimitiveParamsFast"); - - ScriptSleep(200); + setLinkPrimParams(linknumber, rules); } - private void setLinkPrimParams(int linknumber, LSL_List rules, string originFunc) + private void setLinkPrimParams(int linknumber, LSL_List rules) { List parts = new List(); List prims = GetLinkParts(linknumber); @@ -7731,16 +7790,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api parts.Add(p); LSL_List remaining = null; - uint rulesParsed = 0; if (parts.Count > 0) { foreach (object part in parts) { if (part is SceneObjectPart) - remaining = SetPrimParams((SceneObjectPart)part, rules, originFunc, ref rulesParsed); + remaining = SetPrimParams((SceneObjectPart)part, rules); else - remaining = SetPrimParams((ScenePresence)part, rules, originFunc, ref rulesParsed); + remaining = SetPrimParams((ScenePresence)part, rules); } while ((object)remaining != null && remaining.Length > 2) @@ -7759,9 +7817,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api foreach (object part in parts) { if (part is SceneObjectPart) - remaining = SetPrimParams((SceneObjectPart)part, rules, originFunc, ref rulesParsed); + remaining = SetPrimParams((SceneObjectPart)part, rules); else - remaining = SetPrimParams((ScenePresence)part, rules, originFunc, ref rulesParsed); + remaining = SetPrimParams((ScenePresence)part, rules); } } } @@ -7799,7 +7857,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public void llSetLinkPrimitiveParams(int linknumber, LSL_List rules) { - setLinkPrimParams(linknumber, rules, "llSetLinkPrimitiveParams"); llSetLinkPrimitiveParamsFast(linknumber, rules); ScriptSleep(200); } @@ -7827,114 +7884,295 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api return new Vector3((float)x, (float)y, (float)z); } - protected LSL_List SetPrimParams(SceneObjectPart part, LSL_List rules, string originFunc, ref uint rulesParsed) + protected LSL_List SetPrimParams(ScenePresence av, LSL_List rules) { - if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted) - return null; + //This is a special version of SetPrimParams to deal with avatars which are sat on the linkset. int idx = 0; - int idxStart = 0; - - SceneObjectGroup parentgrp = part.ParentGroup; bool positionChanged = false; - LSL_Vector currentPosition = GetPartLocalPos(part); + Vector3 finalPos = Vector3.Zero; try { while (idx < rules.Length) { - ++rulesParsed; int code = rules.GetLSLIntegerItem(idx++); int remain = rules.Length - idx; - idxStart = idx; - - int face; - LSL_Vector v; switch (code) { case (int)ScriptBaseClass.PRIM_POSITION: case (int)ScriptBaseClass.PRIM_POS_LOCAL: - if (remain < 1) - return null; + { + if (remain < 1) + return null; - v=rules.GetVector3Item(idx++); - currentPosition = GetSetPosTarget(part, v, currentPosition); - positionChanged = true; + LSL_Vector v; + v = rules.GetVector3Item(idx++); - break; - case (int)ScriptBaseClass.PRIM_SIZE: - if (remain < 1) - return null; + SceneObjectPart part = World.GetSceneObjectPart(av.ParentID); + if (part == null) + break; - v=rules.GetVector3Item(idx++); - SetScale(part, v); + LSL_Rotation localRot = ScriptBaseClass.ZERO_ROTATION; + LSL_Vector localPos = ScriptBaseClass.ZERO_VECTOR; + if (part.LinkNum > 1) + { + localRot = GetPartLocalRot(part); + localPos = GetPartLocalPos(part); + } - break; - case (int)ScriptBaseClass.PRIM_ROTATION: - if (remain < 1) - return null; + v -= localPos; + v /= localRot; + + LSL_Vector sitOffset = (llRot2Up(new LSL_Rotation(av.Rotation.X, av.Rotation.Y, av.Rotation.Z, av.Rotation.W)) * av.Appearance.AvatarHeight * 0.02638f); + + v = v + 2 * sitOffset; + + av.OffsetPosition = new Vector3((float)v.x, (float)v.y, (float)v.z); + av.SendAvatarDataToAllAgents(); - LSL_Rotation q = rules.GetQuaternionItem(idx++); - // try to let this work as in SL... - if (part.ParentID == 0) - { - // special case: If we are root, rotate complete SOG to new rotation - SetRot(part, q); } - else + break; + + case (int)ScriptBaseClass.PRIM_ROT_LOCAL: + case (int)ScriptBaseClass.PRIM_ROTATION: { - // we are a child. The rotation values will be set to the one of root modified by rot, as in SL. Don't ask. - SceneObjectPart rootPart = part.ParentGroup.RootPart; - SetRot(part, rootPart.RotationOffset * (Quaternion)q); + if (remain < 1) + return null; + + LSL_Rotation r; + r = rules.GetQuaternionItem(idx++); + + SceneObjectPart part = World.GetSceneObjectPart(av.ParentID); + if (part == null) + break; + + LSL_Rotation localRot = ScriptBaseClass.ZERO_ROTATION; + LSL_Vector localPos = ScriptBaseClass.ZERO_VECTOR; + + if (part.LinkNum > 1) + localRot = GetPartLocalRot(part); + + r = r * llGetRootRotation() / localRot; + av.Rotation = new Quaternion((float)r.x, (float)r.y, (float)r.z, (float)r.s); + av.SendAvatarDataToAllAgents(); } + break; + + // parse rest doing nothing but number of parameters error check + case (int)ScriptBaseClass.PRIM_SIZE: + case (int)ScriptBaseClass.PRIM_MATERIAL: + case (int)ScriptBaseClass.PRIM_PHANTOM: + case (int)ScriptBaseClass.PRIM_PHYSICS: + case (int)ScriptBaseClass.PRIM_PHYSICS_SHAPE_TYPE: + case (int)ScriptBaseClass.PRIM_TEMP_ON_REZ: + case (int)ScriptBaseClass.PRIM_NAME: + case (int)ScriptBaseClass.PRIM_DESC: + if (remain < 1) + return null; + idx++; + break; + case (int)ScriptBaseClass.PRIM_GLOW: + case (int)ScriptBaseClass.PRIM_FULLBRIGHT: + case (int)ScriptBaseClass.PRIM_TEXGEN: + if (remain < 2) + return null; + idx += 2; break; case (int)ScriptBaseClass.PRIM_TYPE: if (remain < 3) return null; - code = (int)rules.GetLSLIntegerItem(idx++); - remain = rules.Length - idx; - float hollow; - LSL_Vector twist; - LSL_Vector taper_b; - LSL_Vector topshear; - float revolutions; - float radiusoffset; - float skew; - LSL_Vector holesize; - LSL_Vector profilecut; - switch (code) { case (int)ScriptBaseClass.PRIM_TYPE_BOX: + case (int)ScriptBaseClass.PRIM_TYPE_CYLINDER: + case (int)ScriptBaseClass.PRIM_TYPE_PRISM: if (remain < 6) return null; - - face = (int)rules.GetLSLIntegerItem(idx++); - v = rules.GetVector3Item(idx++); // cut - hollow = (float)rules.GetLSLFloatItem(idx++); - twist = rules.GetVector3Item(idx++); - taper_b = rules.GetVector3Item(idx++); - topshear = rules.GetVector3Item(idx++); - - SetPrimitiveShapeParams(part, face, v, hollow, twist, taper_b, topshear, - (byte)ProfileShape.Square, (byte)Extrusion.Straight); + idx += 6; break; - case (int)ScriptBaseClass.PRIM_TYPE_CYLINDER: - if (remain < 6) + case (int)ScriptBaseClass.PRIM_TYPE_SPHERE: + if (remain < 5) return null; + idx += 5; + break; - face = (int)rules.GetLSLIntegerItem(idx++); // holeshape - v = rules.GetVector3Item(idx++); // cut - hollow = (float)rules.GetLSLFloatItem(idx++); - twist = rules.GetVector3Item(idx++); + case (int)ScriptBaseClass.PRIM_TYPE_TORUS: + case (int)ScriptBaseClass.PRIM_TYPE_TUBE: + case (int)ScriptBaseClass.PRIM_TYPE_RING: + if (remain < 11) + return null; + idx += 11; + break; + + case (int)ScriptBaseClass.PRIM_TYPE_SCULPT: + if (remain < 2) + return null; + idx += 2; + break; + } + break; + + case (int)ScriptBaseClass.PRIM_COLOR: + case (int)ScriptBaseClass.PRIM_TEXT: + case (int)ScriptBaseClass.PRIM_BUMP_SHINY: + case (int)ScriptBaseClass.PRIM_OMEGA: + if (remain < 3) + return null; + idx += 3; + break; + + case (int)ScriptBaseClass.PRIM_TEXTURE: + case (int)ScriptBaseClass.PRIM_POINT_LIGHT: + case (int)ScriptBaseClass.PRIM_PHYSICS_MATERIAL: + if (remain < 5) + return null; + idx += 5; + break; + + case (int)ScriptBaseClass.PRIM_FLEXIBLE: + if (remain < 7) + return null; + + idx += 7; + break; + + case (int)ScriptBaseClass.PRIM_LINK_TARGET: + if (remain < 3) // setting to 3 on the basis that parsing any usage of PRIM_LINK_TARGET that has nothing following it is pointless. + return null; + + return rules.GetSublist(idx, -1); + } + } + } + + finally + { + if (positionChanged) + { + av.OffsetPosition = finalPos; +// av.SendAvatarDataToAllAgents(); + av.SendTerseUpdateToAllClients(); + positionChanged = false; + } + } + return null; + } + + protected LSL_List SetPrimParams(SceneObjectPart part, LSL_List rules) + { + if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted) + return null; + + int idx = 0; + + SceneObjectGroup parentgrp = part.ParentGroup; + + bool positionChanged = false; + LSL_Vector currentPosition = GetPartLocalPos(part); + + try + { + while (idx < rules.Length) + { + int code = rules.GetLSLIntegerItem(idx++); + + int remain = rules.Length - idx; + + int face; + LSL_Vector v; + + switch (code) + { + case (int)ScriptBaseClass.PRIM_POSITION: + case (int)ScriptBaseClass.PRIM_POS_LOCAL: + if (remain < 1) + return null; + + v=rules.GetVector3Item(idx++); + currentPosition = GetSetPosTarget(part, v, currentPosition); + positionChanged = true; + + break; + case (int)ScriptBaseClass.PRIM_SIZE: + if (remain < 1) + return null; + + v=rules.GetVector3Item(idx++); + SetScale(part, v); + + break; + case (int)ScriptBaseClass.PRIM_ROTATION: + if (remain < 1) + return null; + + LSL_Rotation q = rules.GetQuaternionItem(idx++); + SceneObjectPart rootPart = parentgrp.RootPart; + // try to let this work as in SL... + if (rootPart == part) + { + // special case: If we are root, rotate complete SOG to new rotation + SetRot(part, Rot2Quaternion(q)); + } + else + { + // we are a child. The rotation values will be set to the one of root modified by rot, as in SL. Don't ask. + // sounds like sl bug that we need to replicate + SetRot(part, rootPart.RotationOffset * Rot2Quaternion(q)); + } + + break; + + case (int)ScriptBaseClass.PRIM_TYPE: + if (remain < 3) + return null; + + code = (int)rules.GetLSLIntegerItem(idx++); + + remain = rules.Length - idx; + float hollow; + LSL_Vector twist; + LSL_Vector taper_b; + LSL_Vector topshear; + float revolutions; + float radiusoffset; + float skew; + LSL_Vector holesize; + LSL_Vector profilecut; + + switch (code) + { + case (int)ScriptBaseClass.PRIM_TYPE_BOX: + if (remain < 6) + return null; + + face = (int)rules.GetLSLIntegerItem(idx++); + v = rules.GetVector3Item(idx++); // cut + hollow = (float)rules.GetLSLFloatItem(idx++); + twist = rules.GetVector3Item(idx++); + taper_b = rules.GetVector3Item(idx++); + topshear = rules.GetVector3Item(idx++); + + SetPrimitiveShapeParams(part, face, v, hollow, twist, taper_b, topshear, + (byte)ProfileShape.Square, (byte)Extrusion.Straight); + break; + + case (int)ScriptBaseClass.PRIM_TYPE_CYLINDER: + if (remain < 6) + return null; + + face = (int)rules.GetLSLIntegerItem(idx++); // holeshape + v = rules.GetVector3Item(idx++); // cut + hollow = (float)rules.GetLSLFloatItem(idx++); + twist = rules.GetVector3Item(idx++); taper_b = rules.GetVector3Item(idx++); topshear = rules.GetVector3Item(idx++); SetPrimitiveShapeParams(part, face, v, hollow, twist, taper_b, topshear, @@ -8062,7 +8300,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api LSL_Vector color=rules.GetVector3Item(idx++); double alpha=(double)rules.GetLSLFloatItem(idx++); - part.SetFaceColorAlpha(face, color, alpha); + part.SetFaceColor(new Vector3((float)color.x, (float)color.y, (float)color.z), face); + SetAlpha(part, alpha, face); break; @@ -8210,7 +8449,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api string primText = rules.GetLSLStringItem(idx++); LSL_Vector primTextColor = rules.GetVector3Item(idx++); LSL_Float primTextAlpha = rules.GetLSLFloatItem(idx++); - Vector3 av3 = Util.Clip(primTextColor, 0.0f, 1.0f); + Vector3 av3 = new Vector3(Util.Clip((float)primTextColor.x, 0.0f, 1.0f), + Util.Clip((float)primTextColor.y, 0.0f, 1.0f), + Util.Clip((float)primTextColor.z, 0.0f, 1.0f)); part.SetText(primText, av3, Util.Clip((float)primTextAlpha, 0.0f, 1.0f)); break; @@ -8229,7 +8470,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api case (int)ScriptBaseClass.PRIM_ROT_LOCAL: if (remain < 1) return null; - SetRot(part, rules.GetQuaternionItem(idx++)); + LSL_Rotation lr = rules.GetQuaternionItem(idx++); + SetRot(part, Rot2Quaternion(lr)); break; case (int)ScriptBaseClass.PRIM_OMEGA: if (remain < 3) @@ -8239,12 +8481,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api LSL_Float gain = rules.GetLSLFloatItem(idx++); TargetOmega(part, axis, (double)spinrate, (double)gain); break; - case (int)ScriptBaseClass.PRIM_SLICE: - if (remain < 1) - return null; - LSL_Vector slice = rules.GetVector3Item(idx++); - part.UpdateSlice((float)slice.x, (float)slice.y); - break; + case (int)ScriptBaseClass.PRIM_LINK_TARGET: if (remain < 3) // setting to 3 on the basis that parsing any usage of PRIM_LINK_TARGET that has nothing following it is pointless. return null; @@ -8253,12 +8490,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } } } - catch (InvalidCastException e) - { - ShoutError(string.Format( - "{0} error running rule #{1}: arg #{2} ", - originFunc, rulesParsed, idx - idxStart) + e.Message); - } finally { if (positionChanged) @@ -8267,12 +8498,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { SceneObjectGroup parent = part.ParentGroup; Util.FireAndForget(delegate(object x) { - parent.UpdateGroupPosition(currentPosition); + parent.UpdateGroupPosition(new Vector3((float)currentPosition.x, (float)currentPosition.y, (float)currentPosition.z)); }); } else { - part.OffsetPosition = currentPosition; + part.OffsetPosition = new Vector3((float)currentPosition.x, (float)currentPosition.y, (float)currentPosition.z); SceneObjectGroup parent = part.ParentGroup; parent.HasGroupChanged = true; parent.ScheduleGroupForTerseUpdate(); @@ -8561,7 +8792,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api // and standing avatar since server 1.36 LSL_Vector lower; LSL_Vector upper; - if (presence.Animator.Animations.ImplicitDefaultAnimation.AnimID + if (presence.Animator.Animations.DefaultAnimation.AnimID == DefaultAvatarAnimations.AnimsUUID["SIT_GROUND_CONSTRAINED"]) { // This is for ground sitting avatars @@ -8650,22 +8881,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public LSL_List llGetPrimitiveParams(LSL_List rules) { m_host.AddScriptLPS(1); - - LSL_List result = new LSL_List(); - - LSL_List remaining = GetPrimParams(m_host, rules, ref result); - - while (remaining != null && remaining.Length > 2) - { - int linknumber = remaining.GetLSLIntegerItem(0); - rules = remaining.GetSublist(1, -1); - List parts = GetLinkParts(linknumber); - - foreach (SceneObjectPart part in parts) - remaining = GetPrimParams(part, rules, ref result); - } - - return result; + return GetLinkPrimitiveParams(m_host, rules); } public LSL_List llGetLinkPrimitiveParams(int linknumber, LSL_List rules) @@ -8675,103 +8891,358 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api // acording to SL wiki this must indicate a single link number or link_root or link_this. // keep other options as before - List parts; - List avatars; - + List parts = GetLinkParts(linknumber); + List avatars = GetLinkAvatars(linknumber); + LSL_List res = new LSL_List(); - LSL_List remaining = null; - while (rules.Length > 0) + if (parts.Count > 0) { - parts = GetLinkParts(linknumber); - avatars = GetLinkAvatars(linknumber); - - remaining = null; - foreach (SceneObjectPart part in parts) + foreach (var part in parts) { - remaining = GetPrimParams(part, rules, ref res); + LSL_List partRes = GetLinkPrimitiveParams(part, rules); + res += partRes; } + } + if (avatars.Count > 0) + { foreach (ScenePresence avatar in avatars) { - remaining = GetPrimParams(avatar, rules, ref res); - } - - if (remaining != null && remaining.Length > 0) - { - linknumber = remaining.GetLSLIntegerItem(0); - rules = remaining.GetSublist(1, -1); + LSL_List avaRes = GetLinkPrimitiveParams(avatar, rules); + res += avaRes; } } - return res; } - public LSL_List GetPrimParams(SceneObjectPart part, LSL_List rules, ref LSL_List res) + public LSL_List GetLinkPrimitiveParams(ScenePresence avatar, LSL_List rules) { - int idx=0; + // avatars case + // replies as SL wiki + + LSL_List res = new LSL_List(); +// SceneObjectPart sitPart = avatar.ParentPart; // most likelly it will be needed + SceneObjectPart sitPart = World.GetSceneObjectPart(avatar.ParentID); // maybe better do this expensive search for it in case it's gone?? + + int idx = 0; while (idx < rules.Length) { - int code=(int)rules.GetLSLIntegerItem(idx++); - int remain=rules.Length-idx; + int code = (int)rules.GetLSLIntegerItem(idx++); + int remain = rules.Length - idx; switch (code) { case (int)ScriptBaseClass.PRIM_MATERIAL: - res.Add(new LSL_Integer(part.Material)); + res.Add(new LSL_Integer((int)SOPMaterialData.SopMaterial.Flesh)); break; case (int)ScriptBaseClass.PRIM_PHYSICS: - if ((part.GetEffectiveObjectFlags() & (uint)PrimFlags.Physics) != 0) - res.Add(new LSL_Integer(1)); - else res.Add(new LSL_Integer(0)); break; case (int)ScriptBaseClass.PRIM_TEMP_ON_REZ: - if ((part.GetEffectiveObjectFlags() & (uint)PrimFlags.TemporaryOnRez) != 0) - res.Add(new LSL_Integer(1)); - else res.Add(new LSL_Integer(0)); break; case (int)ScriptBaseClass.PRIM_PHANTOM: - if ((part.GetEffectiveObjectFlags() & (uint)PrimFlags.Phantom) != 0) - res.Add(new LSL_Integer(1)); - else res.Add(new LSL_Integer(0)); break; case (int)ScriptBaseClass.PRIM_POSITION: - LSL_Vector v = new LSL_Vector(part.AbsolutePosition.X, - part.AbsolutePosition.Y, - part.AbsolutePosition.Z); - res.Add(v); + + Vector3 pos = avatar.OffsetPosition; + + Vector3 sitOffset = (Zrot(avatar.Rotation)) * (avatar.Appearance.AvatarHeight * 0.02638f *2.0f); + pos -= sitOffset; + + if( sitPart != null) + pos = sitPart.GetWorldPosition() + pos * sitPart.GetWorldRotation(); + + res.Add(new LSL_Vector(pos.X,pos.Y,pos.Z)); break; case (int)ScriptBaseClass.PRIM_SIZE: - res.Add(new LSL_Vector(part.Scale.X, - part.Scale.Y, - part.Scale.Z)); + // as in llGetAgentSize above + res.Add(new LSL_Vector(0.45f, 0.6f, avatar.Appearance.AvatarHeight)); break; case (int)ScriptBaseClass.PRIM_ROTATION: - res.Add(GetPartRot(part)); + Quaternion rot = avatar.Rotation; + if (sitPart != null) + { + rot = sitPart.GetWorldRotation() * rot; // apply sit part world rotation + } + + res.Add(new LSL_Rotation (rot.X, rot.Y, rot.Z, rot.W)); break; case (int)ScriptBaseClass.PRIM_TYPE: - // implementing box - PrimitiveBaseShape Shape = part.Shape; - int primType = (int)part.GetPrimType(); - res.Add(new LSL_Integer(primType)); - double topshearx = (double)(sbyte)Shape.PathShearX / 100.0; // Fix negative values for PathShearX - double topsheary = (double)(sbyte)Shape.PathShearY / 100.0; // and PathShearY. - switch (primType) - { - case ScriptBaseClass.PRIM_TYPE_BOX: - case ScriptBaseClass.PRIM_TYPE_CYLINDER: - case ScriptBaseClass.PRIM_TYPE_PRISM: - res.Add(new LSL_Integer(Shape.ProfileCurve) & 0xf0); // Isolate hole shape nibble. - res.Add(new LSL_Vector(Shape.ProfileBegin / 50000.0, 1 - Shape.ProfileEnd / 50000.0, 0)); + res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TYPE_BOX)); + res.Add(new LSL_Integer(ScriptBaseClass.PRIM_HOLE_DEFAULT)); + res.Add(new LSL_Vector(0f,1.0f,0f)); + res.Add(new LSL_Float(0.0f)); + res.Add(new LSL_Vector(0, 0, 0)); + res.Add(new LSL_Vector(1.0f,1.0f,0f)); + res.Add(new LSL_Vector(0, 0, 0)); + break; + + case (int)ScriptBaseClass.PRIM_TEXTURE: + if (remain < 1) + return res; + + int face = (int)rules.GetLSLIntegerItem(idx++); + if (face == ScriptBaseClass.ALL_SIDES) + { + for (face = 0; face < 21; face++) + { + res.Add(new LSL_String("")); + res.Add(new LSL_Vector(0,0,0)); + res.Add(new LSL_Vector(0,0,0)); + res.Add(new LSL_Float(0.0)); + } + } + else + { + if (face >= 0 && face < 21) + { + res.Add(new LSL_String("")); + res.Add(new LSL_Vector(0,0,0)); + res.Add(new LSL_Vector(0,0,0)); + res.Add(new LSL_Float(0.0)); + } + } + break; + + case (int)ScriptBaseClass.PRIM_COLOR: + if (remain < 1) + return res; + + face = (int)rules.GetLSLIntegerItem(idx++); + + if (face == ScriptBaseClass.ALL_SIDES) + { + for (face = 0; face < 21; face++) + { + res.Add(new LSL_Vector(0,0,0)); + res.Add(new LSL_Float(0)); + } + } + else + { + res.Add(new LSL_Vector(0,0,0)); + res.Add(new LSL_Float(0)); + } + break; + + case (int)ScriptBaseClass.PRIM_BUMP_SHINY: + if (remain < 1) + return res; + face = (int)rules.GetLSLIntegerItem(idx++); + + if (face == ScriptBaseClass.ALL_SIDES) + { + for (face = 0; face < 21; face++) + { + res.Add(new LSL_Integer(ScriptBaseClass.PRIM_SHINY_NONE)); + res.Add(new LSL_Integer(ScriptBaseClass.PRIM_BUMP_NONE)); + } + } + else + { + res.Add(new LSL_Integer(ScriptBaseClass.PRIM_SHINY_NONE)); + res.Add(new LSL_Integer(ScriptBaseClass.PRIM_BUMP_NONE)); + } + break; + + case (int)ScriptBaseClass.PRIM_FULLBRIGHT: + if (remain < 1) + return res; + face = (int)rules.GetLSLIntegerItem(idx++); + + if (face == ScriptBaseClass.ALL_SIDES) + { + for (face = 0; face < 21; face++) + { + res.Add(new LSL_Integer(ScriptBaseClass.FALSE)); + } + } + else + { + res.Add(new LSL_Integer(ScriptBaseClass.FALSE)); + } + break; + + case (int)ScriptBaseClass.PRIM_FLEXIBLE: + res.Add(new LSL_Integer(0)); + res.Add(new LSL_Integer(0));// softness + res.Add(new LSL_Float(0.0f)); // gravity + res.Add(new LSL_Float(0.0f)); // friction + res.Add(new LSL_Float(0.0f)); // wind + res.Add(new LSL_Float(0.0f)); // tension + res.Add(new LSL_Vector(0f,0f,0f)); + break; + + case (int)ScriptBaseClass.PRIM_TEXGEN: + // (PRIM_TEXGEN_DEFAULT, PRIM_TEXGEN_PLANAR) + if (remain < 1) + return res; + face = (int)rules.GetLSLIntegerItem(idx++); + + if (face == ScriptBaseClass.ALL_SIDES) + { + for (face = 0; face < 21; face++) + { + res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_DEFAULT)); + } + } + else + { + res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_DEFAULT)); + } + break; + + case (int)ScriptBaseClass.PRIM_POINT_LIGHT: + res.Add(new LSL_Integer(0)); + res.Add(new LSL_Vector(0f,0f,0f)); + res.Add(new LSL_Float(0f)); // intensity + res.Add(new LSL_Float(0f)); // radius + res.Add(new LSL_Float(0f)); // falloff + break; + + case (int)ScriptBaseClass.PRIM_GLOW: + if (remain < 1) + return res; + face = (int)rules.GetLSLIntegerItem(idx++); + + if (face == ScriptBaseClass.ALL_SIDES) + { + for (face = 0; face < 21; face++) + { + res.Add(new LSL_Float(0f)); + } + } + else + { + res.Add(new LSL_Float(0f)); + } + break; + + case (int)ScriptBaseClass.PRIM_TEXT: + res.Add(new LSL_String("")); + res.Add(new LSL_Vector(0f,0f,0f)); + res.Add(new LSL_Float(1.0f)); + break; + + case (int)ScriptBaseClass.PRIM_NAME: + res.Add(new LSL_String(avatar.Name)); + break; + + case (int)ScriptBaseClass.PRIM_DESC: + res.Add(new LSL_String("")); + break; + + case (int)ScriptBaseClass.PRIM_ROT_LOCAL: + Quaternion lrot = avatar.Rotation; + + if (sitPart != null && sitPart != sitPart.ParentGroup.RootPart) + { + lrot = sitPart.RotationOffset * lrot; // apply sit part rotation offset + } + res.Add(new LSL_Rotation(lrot.X, lrot.Y, lrot.Z, lrot.W)); + break; + + case (int)ScriptBaseClass.PRIM_POS_LOCAL: + Vector3 lpos = avatar.OffsetPosition; // pos relative to sit part + Vector3 lsitOffset = (Zrot(avatar.Rotation)) * (avatar.Appearance.AvatarHeight * 0.02638f * 2.0f); + lpos -= lsitOffset; + + if (sitPart != null && sitPart != sitPart.ParentGroup.RootPart) + { + lpos = sitPart.OffsetPosition + (lpos * sitPart.RotationOffset); // make it relative to root prim + } + res.Add(new LSL_Vector(lpos.X,lpos.Y,lpos.Z)); + break; + + case (int)ScriptBaseClass.PRIM_LINK_TARGET: + if (remain < 3) // setting to 3 on the basis that parsing any usage of PRIM_LINK_TARGET that has nothing following it is pointless. + return res; + LSL_Integer new_linknumber = rules.GetLSLIntegerItem(idx++); + LSL_List new_rules = rules.GetSublist(idx, -1); + + res += llGetLinkPrimitiveParams((int)new_linknumber, new_rules); + return res; + } + } + return res; + } + + public LSL_List GetLinkPrimitiveParams(SceneObjectPart part, LSL_List rules) + { + LSL_List res = new LSL_List(); + int idx=0; + while (idx < rules.Length) + { + int code=(int)rules.GetLSLIntegerItem(idx++); + int remain=rules.Length-idx; + + switch (code) + { + case (int)ScriptBaseClass.PRIM_MATERIAL: + res.Add(new LSL_Integer(part.Material)); + break; + + case (int)ScriptBaseClass.PRIM_PHYSICS: + if ((part.GetEffectiveObjectFlags() & (uint)PrimFlags.Physics) != 0) + res.Add(new LSL_Integer(1)); + else + res.Add(new LSL_Integer(0)); + break; + + case (int)ScriptBaseClass.PRIM_TEMP_ON_REZ: + if ((part.GetEffectiveObjectFlags() & (uint)PrimFlags.TemporaryOnRez) != 0) + res.Add(new LSL_Integer(1)); + else + res.Add(new LSL_Integer(0)); + break; + + case (int)ScriptBaseClass.PRIM_PHANTOM: + if ((part.GetEffectiveObjectFlags() & (uint)PrimFlags.Phantom) != 0) + res.Add(new LSL_Integer(1)); + else + res.Add(new LSL_Integer(0)); + break; + + case (int)ScriptBaseClass.PRIM_POSITION: + LSL_Vector v = new LSL_Vector(part.AbsolutePosition.X, + part.AbsolutePosition.Y, + part.AbsolutePosition.Z); + res.Add(v); + break; + + case (int)ScriptBaseClass.PRIM_SIZE: + res.Add(new LSL_Vector(part.Scale.X, + part.Scale.Y, + part.Scale.Z)); + break; + + case (int)ScriptBaseClass.PRIM_ROTATION: + res.Add(GetPartRot(part)); + break; + + case (int)ScriptBaseClass.PRIM_TYPE: + // implementing box + PrimitiveBaseShape Shape = part.Shape; + int primType = (int)part.GetPrimType(); + res.Add(new LSL_Integer(primType)); + double topshearx = (double)(sbyte)Shape.PathShearX / 100.0; // Fix negative values for PathShearX + double topsheary = (double)(sbyte)Shape.PathShearY / 100.0; // and PathShearY. + switch (primType) + { + case ScriptBaseClass.PRIM_TYPE_BOX: + case ScriptBaseClass.PRIM_TYPE_CYLINDER: + case ScriptBaseClass.PRIM_TYPE_PRISM: + res.Add(new LSL_Integer(Shape.ProfileCurve) & 0xf0); // Isolate hole shape nibble. + res.Add(new LSL_Vector(Shape.ProfileBegin / 50000.0, 1 - Shape.ProfileEnd / 50000.0, 0)); res.Add(new LSL_Float(Shape.ProfileHollow / 50000.0)); res.Add(new LSL_Vector(Shape.PathTwistBegin / 100.0, Shape.PathTwist / 100.0, 0)); res.Add(new LSL_Vector(1 - (Shape.PathScaleX / 100.0 - 1), 1 - (Shape.PathScaleY / 100.0 - 1), 0)); @@ -8845,7 +9316,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api case (int)ScriptBaseClass.PRIM_TEXTURE: if (remain < 1) - return null; + return res; int face = (int)rules.GetLSLIntegerItem(idx++); Primitive.TextureEntry tex = part.Shape.Textures; @@ -8885,7 +9356,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api case (int)ScriptBaseClass.PRIM_COLOR: if (remain < 1) - return null; + return res; face=(int)rules.GetLSLIntegerItem(idx++); @@ -8914,8 +9385,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api case (int)ScriptBaseClass.PRIM_BUMP_SHINY: if (remain < 1) - return null; - + return res; face = (int)rules.GetLSLIntegerItem(idx++); tex = part.Shape.Textures; @@ -8971,8 +9441,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api case (int)ScriptBaseClass.PRIM_FULLBRIGHT: if (remain < 1) - return null; - + return res; face = (int)rules.GetLSLIntegerItem(idx++); tex = part.Shape.Textures; @@ -9026,8 +9495,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api case (int)ScriptBaseClass.PRIM_TEXGEN: // (PRIM_TEXGEN_DEFAULT, PRIM_TEXGEN_PLANAR) if (remain < 1) - return null; - + return res; face = (int)rules.GetLSLIntegerItem(idx++); tex = part.Shape.Textures; @@ -9075,8 +9543,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api case (int)ScriptBaseClass.PRIM_GLOW: if (remain < 1) - return null; - + return res; face = (int)rules.GetLSLIntegerItem(idx++); tex = part.Shape.Textures; @@ -9120,24 +9587,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api case (int)ScriptBaseClass.PRIM_POS_LOCAL: res.Add(new LSL_Vector(GetPartLocalPos(part))); break; - case (int)ScriptBaseClass.PRIM_SLICE: - PrimType prim_type = part.GetPrimType(); - bool useProfileBeginEnd = (prim_type == PrimType.SPHERE || prim_type == PrimType.TORUS || prim_type == PrimType.TUBE || prim_type == PrimType.RING); - res.Add(new LSL_Vector( - (useProfileBeginEnd ? part.Shape.ProfileBegin : part.Shape.PathBegin) / 50000.0, - 1 - (useProfileBeginEnd ? part.Shape.ProfileEnd : part.Shape.PathEnd) / 50000.0, - 0 - )); - break; - case (int)ScriptBaseClass.PRIM_LINK_TARGET: - if(remain < 3) - return null; - return rules.GetSublist(idx, -1); + case (int)ScriptBaseClass.PRIM_LINK_TARGET: + if (remain < 3) // setting to 3 on the basis that parsing any usage of PRIM_LINK_TARGET that has nothing following it is pointless. + return res; + LSL_Integer new_linknumber = rules.GetLSLIntegerItem(idx++); + LSL_List new_rules = rules.GetSublist(idx, -1); + LSL_List tres = llGetLinkPrimitiveParams((int)new_linknumber, new_rules); + res += tres; + return res; } } - - return null; + return res; } public LSL_List llGetPrimMediaParams(int face, LSL_List rules) @@ -10050,10 +10511,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api GridRegion info; - if (World.RegionInfo.RegionName == simulator) - info = new GridRegion(World.RegionInfo); + if (m_ScriptEngine.World.RegionInfo.RegionName == simulator) //Det data for this simulator? + + info = new GridRegion(m_ScriptEngine.World.RegionInfo); else - info = World.GridService.GetRegionByName(m_ScriptEngine.World.RegionInfo.ScopeID, simulator); + info = m_ScriptEngine.World.GridService.GetRegionByName(m_ScriptEngine.World.RegionInfo.ScopeID, simulator); switch (data) { @@ -10063,24 +10525,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api ScriptSleep(1000); return UUID.Zero.ToString(); } - - bool isHypergridRegion = false; - - if (World.RegionInfo.RegionName != simulator && info.RegionSecret != "") - { - // Hypergrid is currently placing real destination region co-ords into RegionSecret. - // But other code can also use this field for a genuine RegionSecret! Therefore, if - // anything is present we need to disambiguate. - // - // FIXME: Hypergrid should be storing this data in a different field. - RegionFlags regionFlags - = (RegionFlags)m_ScriptEngine.World.GridService.GetRegionFlags( - info.ScopeID, info.RegionID); - isHypergridRegion = (regionFlags & RegionFlags.Hyperlink) != 0; - } - - if (isHypergridRegion) + if (m_ScriptEngine.World.RegionInfo.RegionName != simulator) { + //Hypergrid Region co-ordinates uint rx = 0, ry = 0; Utils.LongToUInts(Convert.ToUInt64(info.RegionSecret), out rx, out ry); @@ -10091,7 +10538,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } else { - // Local grid co-oridnates + //Local-cooridnates reply = new LSL_Vector( info.RegionLocX, info.RegionLocY, @@ -10545,20 +10992,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api switch ((ParcelMediaCommandEnum) Convert.ToInt32(aList.Data[i].ToString())) { case ParcelMediaCommandEnum.Url: - list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition).MediaURL)); + list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).MediaURL)); break; case ParcelMediaCommandEnum.Desc: - list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition).Description)); + list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).Description)); break; case ParcelMediaCommandEnum.Texture: - list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition).MediaID.ToString())); + list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).MediaID.ToString())); break; case ParcelMediaCommandEnum.Type: - list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition).MediaType)); + list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).MediaType)); break; case ParcelMediaCommandEnum.Size: - list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition).MediaWidth)); - list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition).MediaHeight)); + list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).MediaWidth)); + list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).MediaHeight)); break; default: ParcelMediaCommandEnum mediaCommandEnum = ParcelMediaCommandEnum.Url; @@ -10728,8 +11175,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api ScenePresence avatar = World.GetScenePresence(detectedParams.Key); if (avatar != null) { - avatar.ControllingClient.SendScriptTeleportRequest(m_host.Name, - simname, pos, lookAt); + avatar.ControllingClient.SendScriptTeleportRequest(m_host.Name, simname, + new Vector3((float)pos.x, (float)pos.y, (float)pos.z), + new Vector3((float)lookAt.x, (float)lookAt.y, (float)lookAt.z)); } ScriptSleep(1000); @@ -10914,30 +11362,31 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public LSL_Float llListStatistics(int operation, LSL_List src) { m_host.AddScriptLPS(1); + LSL_List nums = LSL_List.ToDoubleList(src); switch (operation) { case ScriptBaseClass.LIST_STAT_RANGE: - return src.Range(); + return nums.Range(); case ScriptBaseClass.LIST_STAT_MIN: - return src.Min(); + return nums.Min(); case ScriptBaseClass.LIST_STAT_MAX: - return src.Max(); + return nums.Max(); case ScriptBaseClass.LIST_STAT_MEAN: - return src.Mean(); + return nums.Mean(); case ScriptBaseClass.LIST_STAT_MEDIAN: - return LSL_List.ToDoubleList(src).Median(); + return nums.Median(); case ScriptBaseClass.LIST_STAT_NUM_COUNT: - return src.NumericLength(); + return nums.NumericLength(); case ScriptBaseClass.LIST_STAT_STD_DEV: - return src.StdDev(); + return nums.StdDev(); case ScriptBaseClass.LIST_STAT_SUM: - return src.Sum(); + return nums.Sum(); case ScriptBaseClass.LIST_STAT_SUM_SQUARES: - return src.SumSqrs(); + return nums.SumSqrs(); case ScriptBaseClass.LIST_STAT_GEOMETRIC_MEAN: - return src.GeometricMean(); + return nums.GeometricMean(); case ScriptBaseClass.LIST_STAT_HARMONIC_MEAN: - return src.HarmonicMean(); + return nums.HarmonicMean(); default: return 0.0; } @@ -11295,7 +11744,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public LSL_List llGetParcelDetails(LSL_Vector pos, LSL_List param) { m_host.AddScriptLPS(1); - LandData land = World.GetLandData(pos); + LandData land = World.GetLandData((float)pos.x, (float)pos.y); if (land == null) { return new LSL_List(0); @@ -11463,12 +11912,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api else rot = obj.GetWorldRotation(); - LSL_Rotation objrot = new LSL_Rotation(rot); + LSL_Rotation objrot = new LSL_Rotation(rot.X, rot.Y, rot.Z, rot.W); ret.Add(objrot); } break; case ScriptBaseClass.OBJECT_VELOCITY: - ret.Add(new LSL_Vector(obj.Velocity)); + Vector3 ovel = obj.Velocity; + ret.Add(new LSL_Vector(ovel.X, ovel.Y, ovel.Z)); break; case ScriptBaseClass.OBJECT_OWNER: ret.Add(new LSL_String(obj.OwnerID.ToString())); @@ -11555,12 +12005,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api internal void Deprecated(string command) { - throw new ScriptException("Command deprecated: " + command); + throw new Exception("Command deprecated: " + command); } internal void LSLError(string msg) { - throw new ScriptException("LSL Runtime Error: " + msg); + throw new Exception("LSL Runtime Error: " + msg); } public delegate void AssetRequestCallback(UUID assetID, AssetBase asset); @@ -11681,7 +12131,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api return tid.ToString(); } - public void SetPrimitiveParamsEx(LSL_Key prim, LSL_List rules, string originFunc) + public void SetPrimitiveParamsEx(LSL_Key prim, LSL_List rules) { SceneObjectPart obj = World.GetSceneObjectPart(new UUID(prim)); if (obj == null) @@ -11690,41 +12140,28 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (obj.OwnerID != m_host.OwnerID) return; - uint rulesParsed = 0; - LSL_List remaining = SetPrimParams(obj, rules, originFunc, ref rulesParsed); + LSL_List remaining = SetPrimParams(obj, rules); while ((object)remaining != null && remaining.Length > 2) { LSL_Integer newLink = remaining.GetLSLIntegerItem(0); LSL_List newrules = remaining.GetSublist(1, -1); foreach(SceneObjectPart part in GetLinkParts(obj, newLink)){ - remaining = SetPrimParams(part, newrules, originFunc, ref rulesParsed); + remaining = SetPrimParams(part, newrules); } } } - public LSL_List GetPrimitiveParamsEx(LSL_Key prim, LSL_List rules) + public LSL_List GetLinkPrimitiveParamsEx(LSL_Key prim, LSL_List rules) { SceneObjectPart obj = World.GetSceneObjectPart(new UUID(prim)); + if (obj == null) + return new LSL_List(); - LSL_List result = new LSL_List(); - - if (obj != null && obj.OwnerID != m_host.OwnerID) - { - LSL_List remaining = GetPrimParams(obj, rules, ref result); - - while (remaining != null && remaining.Length > 2) - { - int linknumber = remaining.GetLSLIntegerItem(0); - rules = remaining.GetSublist(1, -1); - List parts = GetLinkParts(linknumber); - - foreach (SceneObjectPart part in parts) - remaining = GetPrimParams(part, rules, ref result); - } - } + if (obj.OwnerID != m_host.OwnerID) + return new LSL_List(); - return result; + return GetLinkPrimitiveParams(obj, rules); } public LSL_Integer llGetLinkNumberOfSides(LSL_Integer link) @@ -12087,8 +12524,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api m_host.AddScriptLPS(1); - Vector3 rayStart = start; - Vector3 rayEnd = end; + Vector3 rayStart = new Vector3((float)start.x, (float)start.y, (float)start.z); + Vector3 rayEnd = new Vector3((float)end.x, (float)end.y, (float)end.z); Vector3 dir = rayEnd - rayStart; float dist = Vector3.Mag(dir); @@ -12662,455 +13099,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } } } - - protected LSL_List SetPrimParams(ScenePresence av, LSL_List rules, string originFunc, ref uint rulesParsed) - { - //This is a special version of SetPrimParams to deal with avatars which are sat on the linkset. - - int idx = 0; - int idxStart = 0; - - bool positionChanged = false; - Vector3 finalPos = Vector3.Zero; - - try - { - while (idx < rules.Length) - { - ++rulesParsed; - int code = rules.GetLSLIntegerItem(idx++); - - int remain = rules.Length - idx; - idxStart = idx; - - switch (code) - { - case (int)ScriptBaseClass.PRIM_POSITION: - case (int)ScriptBaseClass.PRIM_POS_LOCAL: - { - if (remain < 1) - return null; - - LSL_Vector v; - v = rules.GetVector3Item(idx++); - - SceneObjectPart part = World.GetSceneObjectPart(av.ParentID); - if (part == null) - break; - - LSL_Rotation localRot = ScriptBaseClass.ZERO_ROTATION; - LSL_Vector localPos = ScriptBaseClass.ZERO_VECTOR; - if (part.LinkNum > 1) - { - localRot = GetPartLocalRot(part); - localPos = GetPartLocalPos(part); - } - - v -= localPos; - v /= localRot; - - LSL_Vector sitOffset = (llRot2Up(new LSL_Rotation(av.Rotation.X, av.Rotation.Y, av.Rotation.Z, av.Rotation.W)) * av.Appearance.AvatarHeight * 0.02638f); - - v = v + 2 * sitOffset; - - av.OffsetPosition = new Vector3((float)v.x, (float)v.y, (float)v.z); - av.SendAvatarDataToAllAgents(); - - } - break; - - case (int)ScriptBaseClass.PRIM_ROT_LOCAL: - case (int)ScriptBaseClass.PRIM_ROTATION: - { - if (remain < 1) - return null; - - LSL_Rotation r; - r = rules.GetQuaternionItem(idx++); - - SceneObjectPart part = World.GetSceneObjectPart(av.ParentID); - if (part == null) - break; - - LSL_Rotation localRot = ScriptBaseClass.ZERO_ROTATION; - LSL_Vector localPos = ScriptBaseClass.ZERO_VECTOR; - - if (part.LinkNum > 1) - localRot = GetPartLocalRot(part); - - r = r * llGetRootRotation() / localRot; - av.Rotation = new Quaternion((float)r.x, (float)r.y, (float)r.z, (float)r.s); - av.SendAvatarDataToAllAgents(); - } - break; - - // parse rest doing nothing but number of parameters error check - case (int)ScriptBaseClass.PRIM_SIZE: - case (int)ScriptBaseClass.PRIM_MATERIAL: - case (int)ScriptBaseClass.PRIM_PHANTOM: - case (int)ScriptBaseClass.PRIM_PHYSICS: - case (int)ScriptBaseClass.PRIM_PHYSICS_SHAPE_TYPE: - case (int)ScriptBaseClass.PRIM_TEMP_ON_REZ: - case (int)ScriptBaseClass.PRIM_NAME: - case (int)ScriptBaseClass.PRIM_DESC: - if (remain < 1) - return null; - idx++; - break; - - case (int)ScriptBaseClass.PRIM_GLOW: - case (int)ScriptBaseClass.PRIM_FULLBRIGHT: - case (int)ScriptBaseClass.PRIM_TEXGEN: - if (remain < 2) - return null; - idx += 2; - break; - - case (int)ScriptBaseClass.PRIM_TYPE: - if (remain < 3) - return null; - code = (int)rules.GetLSLIntegerItem(idx++); - remain = rules.Length - idx; - switch (code) - { - case (int)ScriptBaseClass.PRIM_TYPE_BOX: - case (int)ScriptBaseClass.PRIM_TYPE_CYLINDER: - case (int)ScriptBaseClass.PRIM_TYPE_PRISM: - if (remain < 6) - return null; - idx += 6; - break; - - case (int)ScriptBaseClass.PRIM_TYPE_SPHERE: - if (remain < 5) - return null; - idx += 5; - break; - - case (int)ScriptBaseClass.PRIM_TYPE_TORUS: - case (int)ScriptBaseClass.PRIM_TYPE_TUBE: - case (int)ScriptBaseClass.PRIM_TYPE_RING: - if (remain < 11) - return null; - idx += 11; - break; - - case (int)ScriptBaseClass.PRIM_TYPE_SCULPT: - if (remain < 2) - return null; - idx += 2; - break; - } - break; - - case (int)ScriptBaseClass.PRIM_COLOR: - case (int)ScriptBaseClass.PRIM_TEXT: - case (int)ScriptBaseClass.PRIM_BUMP_SHINY: - case (int)ScriptBaseClass.PRIM_OMEGA: - if (remain < 3) - return null; - idx += 3; - break; - - case (int)ScriptBaseClass.PRIM_TEXTURE: - case (int)ScriptBaseClass.PRIM_POINT_LIGHT: - case (int)ScriptBaseClass.PRIM_PHYSICS_MATERIAL: - if (remain < 5) - return null; - idx += 5; - break; - - case (int)ScriptBaseClass.PRIM_FLEXIBLE: - if (remain < 7) - return null; - - idx += 7; - break; - - case (int)ScriptBaseClass.PRIM_LINK_TARGET: - if (remain < 3) // setting to 3 on the basis that parsing any usage of PRIM_LINK_TARGET that has nothing following it is pointless. - return null; - - return rules.GetSublist(idx, -1); - } - } - } - catch (InvalidCastException e) - { - ShoutError(string.Format( - "{0} error running rule #{1}: arg #{2} ", - originFunc, rulesParsed, idx - idxStart) + e.Message); - } - finally - { - if (positionChanged) - { - av.OffsetPosition = finalPos; -// av.SendAvatarDataToAllAgents(); - av.SendTerseUpdateToAllClients(); - positionChanged = false; - } - } - return null; - } - - public LSL_List GetPrimParams(ScenePresence avatar, LSL_List rules, ref LSL_List res) - { - // avatars case - // replies as SL wiki - -// SceneObjectPart sitPart = avatar.ParentPart; // most likelly it will be needed - SceneObjectPart sitPart = World.GetSceneObjectPart(avatar.ParentID); // maybe better do this expensive search for it in case it's gone?? - - int idx = 0; - while (idx < rules.Length) - { - int code = (int)rules.GetLSLIntegerItem(idx++); - int remain = rules.Length - idx; - - switch (code) - { - case (int)ScriptBaseClass.PRIM_MATERIAL: - res.Add(new LSL_Integer((int)SOPMaterialData.SopMaterial.Flesh)); - break; - - case (int)ScriptBaseClass.PRIM_PHYSICS: - res.Add(new LSL_Integer(0)); - break; - - case (int)ScriptBaseClass.PRIM_TEMP_ON_REZ: - res.Add(new LSL_Integer(0)); - break; - - case (int)ScriptBaseClass.PRIM_PHANTOM: - res.Add(new LSL_Integer(0)); - break; - - case (int)ScriptBaseClass.PRIM_POSITION: - - Vector3 pos = avatar.OffsetPosition; - - Vector3 sitOffset = (Zrot(avatar.Rotation)) * (avatar.Appearance.AvatarHeight * 0.02638f *2.0f); - pos -= sitOffset; - - if( sitPart != null) - pos = sitPart.GetWorldPosition() + pos * sitPart.GetWorldRotation(); - - res.Add(new LSL_Vector(pos.X,pos.Y,pos.Z)); - break; - - case (int)ScriptBaseClass.PRIM_SIZE: - // as in llGetAgentSize above - res.Add(new LSL_Vector(0.45f, 0.6f, avatar.Appearance.AvatarHeight)); - break; - - case (int)ScriptBaseClass.PRIM_ROTATION: - Quaternion rot = avatar.Rotation; - if (sitPart != null) - { - rot = sitPart.GetWorldRotation() * rot; // apply sit part world rotation - } - - res.Add(new LSL_Rotation (rot.X, rot.Y, rot.Z, rot.W)); - break; - - case (int)ScriptBaseClass.PRIM_TYPE: - res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TYPE_BOX)); - res.Add(new LSL_Integer(ScriptBaseClass.PRIM_HOLE_DEFAULT)); - res.Add(new LSL_Vector(0f,1.0f,0f)); - res.Add(new LSL_Float(0.0f)); - res.Add(new LSL_Vector(0, 0, 0)); - res.Add(new LSL_Vector(1.0f,1.0f,0f)); - res.Add(new LSL_Vector(0, 0, 0)); - break; - - case (int)ScriptBaseClass.PRIM_TEXTURE: - if (remain < 1) - return null; - - int face = (int)rules.GetLSLIntegerItem(idx++); - if (face == ScriptBaseClass.ALL_SIDES) - { - for (face = 0; face < 21; face++) - { - res.Add(new LSL_String("")); - res.Add(new LSL_Vector(0,0,0)); - res.Add(new LSL_Vector(0,0,0)); - res.Add(new LSL_Float(0.0)); - } - } - else - { - if (face >= 0 && face < 21) - { - res.Add(new LSL_String("")); - res.Add(new LSL_Vector(0,0,0)); - res.Add(new LSL_Vector(0,0,0)); - res.Add(new LSL_Float(0.0)); - } - } - break; - - case (int)ScriptBaseClass.PRIM_COLOR: - if (remain < 1) - return null; - - face = (int)rules.GetLSLIntegerItem(idx++); - - if (face == ScriptBaseClass.ALL_SIDES) - { - for (face = 0; face < 21; face++) - { - res.Add(new LSL_Vector(0,0,0)); - res.Add(new LSL_Float(0)); - } - } - else - { - res.Add(new LSL_Vector(0,0,0)); - res.Add(new LSL_Float(0)); - } - break; - - case (int)ScriptBaseClass.PRIM_BUMP_SHINY: - if (remain < 1) - return null; - face = (int)rules.GetLSLIntegerItem(idx++); - - if (face == ScriptBaseClass.ALL_SIDES) - { - for (face = 0; face < 21; face++) - { - res.Add(new LSL_Integer(ScriptBaseClass.PRIM_SHINY_NONE)); - res.Add(new LSL_Integer(ScriptBaseClass.PRIM_BUMP_NONE)); - } - } - else - { - res.Add(new LSL_Integer(ScriptBaseClass.PRIM_SHINY_NONE)); - res.Add(new LSL_Integer(ScriptBaseClass.PRIM_BUMP_NONE)); - } - break; - - case (int)ScriptBaseClass.PRIM_FULLBRIGHT: - if (remain < 1) - return null; - face = (int)rules.GetLSLIntegerItem(idx++); - - if (face == ScriptBaseClass.ALL_SIDES) - { - for (face = 0; face < 21; face++) - { - res.Add(new LSL_Integer(ScriptBaseClass.FALSE)); - } - } - else - { - res.Add(new LSL_Integer(ScriptBaseClass.FALSE)); - } - break; - - case (int)ScriptBaseClass.PRIM_FLEXIBLE: - res.Add(new LSL_Integer(0)); - res.Add(new LSL_Integer(0));// softness - res.Add(new LSL_Float(0.0f)); // gravity - res.Add(new LSL_Float(0.0f)); // friction - res.Add(new LSL_Float(0.0f)); // wind - res.Add(new LSL_Float(0.0f)); // tension - res.Add(new LSL_Vector(0f,0f,0f)); - break; - - case (int)ScriptBaseClass.PRIM_TEXGEN: - // (PRIM_TEXGEN_DEFAULT, PRIM_TEXGEN_PLANAR) - if (remain < 1) - return null; - face = (int)rules.GetLSLIntegerItem(idx++); - - if (face == ScriptBaseClass.ALL_SIDES) - { - for (face = 0; face < 21; face++) - { - res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_DEFAULT)); - } - } - else - { - res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_DEFAULT)); - } - break; - - case (int)ScriptBaseClass.PRIM_POINT_LIGHT: - res.Add(new LSL_Integer(0)); - res.Add(new LSL_Vector(0f,0f,0f)); - res.Add(new LSL_Float(0f)); // intensity - res.Add(new LSL_Float(0f)); // radius - res.Add(new LSL_Float(0f)); // falloff - break; - - case (int)ScriptBaseClass.PRIM_GLOW: - if (remain < 1) - return null; - face = (int)rules.GetLSLIntegerItem(idx++); - - if (face == ScriptBaseClass.ALL_SIDES) - { - for (face = 0; face < 21; face++) - { - res.Add(new LSL_Float(0f)); - } - } - else - { - res.Add(new LSL_Float(0f)); - } - break; - - case (int)ScriptBaseClass.PRIM_TEXT: - res.Add(new LSL_String("")); - res.Add(new LSL_Vector(0f,0f,0f)); - res.Add(new LSL_Float(1.0f)); - break; - - case (int)ScriptBaseClass.PRIM_NAME: - res.Add(new LSL_String(avatar.Name)); - break; - - case (int)ScriptBaseClass.PRIM_DESC: - res.Add(new LSL_String("")); - break; - - case (int)ScriptBaseClass.PRIM_ROT_LOCAL: - Quaternion lrot = avatar.Rotation; - - if (sitPart != null && sitPart != sitPart.ParentGroup.RootPart) - { - lrot = sitPart.RotationOffset * lrot; // apply sit part rotation offset - } - res.Add(new LSL_Rotation(lrot.X, lrot.Y, lrot.Z, lrot.W)); - break; - - case (int)ScriptBaseClass.PRIM_POS_LOCAL: - Vector3 lpos = avatar.OffsetPosition; // pos relative to sit part - Vector3 lsitOffset = (Zrot(avatar.Rotation)) * (avatar.Appearance.AvatarHeight * 0.02638f * 2.0f); - lpos -= lsitOffset; - - if (sitPart != null && sitPart != sitPart.ParentGroup.RootPart) - { - lpos = sitPart.OffsetPosition + (lpos * sitPart.RotationOffset); // make it relative to root prim - } - res.Add(new LSL_Vector(lpos.X,lpos.Y,lpos.Z)); - break; - - case (int)ScriptBaseClass.PRIM_LINK_TARGET: - if (remain < 3) // setting to 3 on the basis that parsing any usage of PRIM_LINK_TARGET that has nothing following it is pointless. - return null; - - return rules.GetSublist(idx, -1); - } - } - - return null; - } } public class NotecardCache diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LS_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LS_Api.cs index ceb4660..795de80 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LS_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LS_Api.cs @@ -304,7 +304,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api case (int)ScriptBaseClass.WL_CLOUD_DETAIL_XY_DENSITY: idx++; iV = rules.GetVector3Item(idx); - wl.cloudDetailXYDensity = iV; + wl.cloudDetailXYDensity = new Vector3((float)iV.x, (float)iV.y, (float)iV.z); break; case (int)ScriptBaseClass.WL_CLOUD_SCALE: idx++; @@ -329,7 +329,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api case (int)ScriptBaseClass.WL_CLOUD_XY_DENSITY: idx++; iV = rules.GetVector3Item(idx); - wl.cloudXYDensity = iV; + wl.cloudXYDensity = new Vector3((float)iV.x, (float)iV.y, (float)iV.z); break; case (int)ScriptBaseClass.WL_DENSITY_MULTIPLIER: idx++; @@ -384,7 +384,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api case (int)ScriptBaseClass.WL_REFLECTION_WAVELET_SCALE: idx++; iV = rules.GetVector3Item(idx); - wl.reflectionWaveletScale = iV; + wl.reflectionWaveletScale = new Vector3((float)iV.x, (float)iV.y, (float)iV.z); break; case (int)ScriptBaseClass.WL_REFRACT_SCALE_ABOVE: idx++; @@ -422,7 +422,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api case (int)ScriptBaseClass.WL_WATER_COLOR: idx++; iV = rules.GetVector3Item(idx); - wl.waterColor = iV; + wl.waterColor = new Vector3((float)iV.x, (float)iV.y, (float)iV.z); break; case (int)ScriptBaseClass.WL_WATER_FOG_DENSITY_EXPONENT: idx++; diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs index 8f34833..7844c75 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs @@ -95,13 +95,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api internal void MODError(string msg) { - throw new ScriptException("MOD Runtime Error: " + msg); + throw new Exception("MOD Runtime Error: " + msg); } - /// - /// Dumps an error message on the debug console. - /// - /// + // + //Dumps an error message on the debug console. + // + internal void MODShoutError(string message) { if (message.Length > 1023) @@ -254,7 +254,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api object[] convertedParms = new object[parms.Length]; for (int i = 0; i < parms.Length; i++) - convertedParms[i] = ConvertFromLSL(parms[i],signature[i], fname); + convertedParms[i] = ConvertFromLSL(parms[i],signature[i]); // now call the function, the contract with the function is that it will always return // non-null but don't trust it completely @@ -294,7 +294,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api /// /// - protected object ConvertFromLSL(object lslparm, Type type, string fname) + protected object ConvertFromLSL(object lslparm, Type type) { // ---------- String ---------- if (lslparm is LSL_String) @@ -310,7 +310,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api // ---------- Integer ---------- else if (lslparm is LSL_Integer) { - if (type == typeof(int) || type == typeof(float)) + if (type == typeof(int)) return (int)(LSL_Integer)lslparm; } @@ -333,7 +333,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { if (type == typeof(OpenMetaverse.Quaternion)) { - return (OpenMetaverse.Quaternion)((LSL_Rotation)lslparm); + LSL_Rotation rot = (LSL_Rotation)lslparm; + return new OpenMetaverse.Quaternion((float)rot.x,(float)rot.y,(float)rot.z,(float)rot.s); } } @@ -342,7 +343,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { if (type == typeof(OpenMetaverse.Vector3)) { - return (OpenMetaverse.Vector3)((LSL_Vector)lslparm); + LSL_Vector vect = (LSL_Vector)lslparm; + return new OpenMetaverse.Vector3((float)vect.x,(float)vect.y,(float)vect.z); } } @@ -359,27 +361,29 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api result[i] = (string)(LSL_String)plist[i]; else if (plist[i] is LSL_Integer) result[i] = (int)(LSL_Integer)plist[i]; - // The int check exists because of the many plain old int script constants in ScriptBase which - // are not LSL_Integers. - else if (plist[i] is int) - result[i] = plist[i]; else if (plist[i] is LSL_Float) result[i] = (float)(LSL_Float)plist[i]; else if (plist[i] is LSL_Key) result[i] = new UUID((LSL_Key)plist[i]); else if (plist[i] is LSL_Rotation) - result[i] = (Quaternion)((LSL_Rotation)plist[i]); + { + LSL_Rotation rot = (LSL_Rotation)plist[i]; + result[i] = new OpenMetaverse.Quaternion((float)rot.x,(float)rot.y,(float)rot.z,(float)rot.s); + } else if (plist[i] is LSL_Vector) - result[i] = (Vector3)((LSL_Vector)plist[i]); + { + LSL_Vector vect = (LSL_Vector)plist[i]; + result[i] = new OpenMetaverse.Vector3((float)vect.x,(float)vect.y,(float)vect.z); + } else - MODError(String.Format("{0}: unknown LSL list element type", fname)); + MODError("unknown LSL list element type"); } return result; } } - MODError(String.Format("{1}: parameter type mismatch; expecting {0}",type.Name, fname)); + MODError(String.Format("parameter type mismatch; expecting {0}",type.Name)); return null; } diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs index 51c8c7e..80111f9 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs @@ -141,8 +141,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api internal bool m_debuggerSafe = false; internal Dictionary m_FunctionPerms = new Dictionary(); - protected IUrlModule m_UrlModule = null; - public void Initialize(IScriptEngine ScriptEngine, SceneObjectPart host, TaskInventoryItem item) { m_ScriptEngine = ScriptEngine; @@ -150,8 +148,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api m_item = item; m_debuggerSafe = m_ScriptEngine.Config.GetBoolean("DebuggerSafe", false); - m_UrlModule = m_ScriptEngine.World.RequestModuleInterface(); - if (m_ScriptEngine.Config.GetBoolean("AllowOSFunctions", false)) m_OSFunctionsEnabled = true; @@ -218,7 +214,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } else { - throw new ScriptException("OSSL Runtime Error: " + msg); + throw new Exception("OSSL Runtime Error: " + msg); } } @@ -786,9 +782,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api // We will launch the teleport on a new thread so that when the script threads are terminated // before teleport in ScriptInstance.GetXMLState(), we don't end up aborting the one doing the teleporting. - Util.FireAndForget(o => World.RequestTeleportLocation( - presence.ControllingClient, regionName, position, - lookat, (uint)TPFlags.ViaLocation)); + Util.FireAndForget( + o => World.RequestTeleportLocation(presence.ControllingClient, regionName, + new Vector3((float)position.x, (float)position.y, (float)position.z), + new Vector3((float)lookat.x, (float)lookat.y, (float)lookat.z), (uint)TPFlags.ViaLocation)); ScriptSleep(5000); @@ -831,9 +828,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api // We will launch the teleport on a new thread so that when the script threads are terminated // before teleport in ScriptInstance.GetXMLState(), we don't end up aborting the one doing the teleporting. - Util.FireAndForget(o => World.RequestTeleportLocation( - presence.ControllingClient, regionHandle, - position, lookat, (uint)TPFlags.ViaLocation)); + Util.FireAndForget( + o => World.RequestTeleportLocation(presence.ControllingClient, regionHandle, + new Vector3((float)position.x, (float)position.y, (float)position.z), + new Vector3((float)lookat.x, (float)lookat.y, (float)lookat.z), (uint)TPFlags.ViaLocation)); ScriptSleep(5000); @@ -1682,11 +1680,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api return; } - MessageObject(objUUID, message); - } - - private void MessageObject(UUID objUUID, string message) - { object[] resobj = new object[] { new LSL_Types.LSLString(m_host.UUID.ToString()), new LSL_Types.LSLString(message) }; SceneObjectPart sceneOP = World.GetSceneObjectPart(objUUID); @@ -1789,24 +1782,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api protected string LoadNotecard(string notecardNameOrUuid) { UUID assetID = CacheNotecard(notecardNameOrUuid); + StringBuilder notecardData = new StringBuilder(); - if (assetID != UUID.Zero) + for (int count = 0; count < NotecardCache.GetLines(assetID); count++) { - StringBuilder notecardData = new StringBuilder(); - - for (int count = 0; count < NotecardCache.GetLines(assetID); count++) - { - string line = NotecardCache.GetLine(assetID, count) + "\n"; - - // m_log.DebugFormat("[OSSL]: From notecard {0} loading line {1}", notecardNameOrUuid, line); - - notecardData.Append(line); - } - - return notecardData.ToString(); + string line = NotecardCache.GetLine(assetID, count) + "\n"; + +// m_log.DebugFormat("[OSSL]: From notecard {0} loading line {1}", notecardNameOrUuid, line); + + notecardData.Append(line); } - return null; + return notecardData.ToString(); } /// @@ -2272,25 +2259,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api CheckThreatLevel(ThreatLevel.High, "osGetLinkPrimitiveParams"); m_host.AddScriptLPS(1); InitLSL(); - // One needs to cast m_LSL_Api because we're using functions not - // on the ILSL_Api interface. - LSL_Api LSL_Api = (LSL_Api)m_LSL_Api; LSL_List retVal = new LSL_List(); - LSL_List remaining = null; - List parts = LSL_Api.GetLinkParts(linknumber); + List parts = ((LSL_Api)m_LSL_Api).GetLinkParts(linknumber); foreach (SceneObjectPart part in parts) { - remaining = LSL_Api.GetPrimParams(part, rules, ref retVal); - } - - while (remaining != null && remaining.Length > 2) - { - linknumber = remaining.GetLSLIntegerItem(0); - rules = remaining.GetSublist(1, -1); - parts = LSL_Api.GetLinkParts(linknumber); - - foreach (SceneObjectPart part in parts) - remaining = LSL_Api.GetPrimParams(part, rules, ref retVal); + retVal += ((LSL_Api)m_LSL_Api).GetLinkPrimitiveParams(part, rules); } return retVal; } @@ -2379,18 +2352,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api return UUID.Zero.ToString(); } } - else - { - OSSLError(string.Format("osNpcCreate: Notecard reference '{0}' not found.", notecard)); - } } + if (appearance == null) + return new LSL_Key(UUID.Zero.ToString()); + UUID ownerID = UUID.Zero; if (owned) ownerID = m_host.OwnerID; UUID x = module.CreateNPC(firstname, lastname, - position, + new Vector3((float) position.x, (float) position.y, (float) position.z), ownerID, senseAsAgent, World, @@ -2453,10 +2425,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api return; string appearanceSerialized = LoadNotecard(notecard); - - if (appearanceSerialized == null) - OSSLError(string.Format("osNpcCreate: Notecard reference '{0}' not found.", notecard)); - OSDMap appearanceOsd = (OSDMap)OSDParser.DeserializeLLSDXml(appearanceSerialized); // OSD a = OSDParser.DeserializeLLSDXml(appearanceSerialized); // Console.WriteLine("appearanceSerialized {0}", appearanceSerialized); @@ -2517,7 +2485,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api return new LSL_Vector(0, 0, 0); } - public void osNpcMoveTo(LSL_Key npc, LSL_Vector pos) + public void osNpcMoveTo(LSL_Key npc, LSL_Vector position) { CheckThreatLevel(ThreatLevel.High, "osNpcMoveTo"); m_host.AddScriptLPS(1); @@ -2532,6 +2500,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (!module.CheckPermissions(npcId, m_host.OwnerID)) return; + Vector3 pos = new Vector3((float) position.x, (float) position.y, (float) position.z); module.MoveToTarget(npcId, World, pos, false, true, false); } } @@ -2551,10 +2520,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (!module.CheckPermissions(npcId, m_host.OwnerID)) return; + Vector3 pos = new Vector3((float)target.x, (float)target.y, (float)target.z); module.MoveToTarget( new UUID(npc.m_string), World, - target, + pos, (options & ScriptBaseClass.OS_NPC_NO_FLY) != 0, (options & ScriptBaseClass.OS_NPC_LAND_AT_TARGET) != 0, (options & ScriptBaseClass.OS_NPC_RUNNING) != 0); @@ -2606,7 +2576,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api ScenePresence sp = World.GetScenePresence(npcId); if (sp != null) - sp.Rotation = rotation; + sp.Rotation = LSL_Api.Rot2Quaternion(rotation); } } @@ -2966,7 +2936,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api avatar.SpeedModifier = (float)SpeedModifier; } - public void osKickAvatar(string FirstName, string SurName, string alert) + public void osKickAvatar(string FirstName,string SurName,string alert) { CheckThreatLevel(ThreatLevel.Severe, "osKickAvatar"); m_host.AddScriptLPS(1); @@ -2980,21 +2950,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api sp.ControllingClient.Kick(alert); // ...and close on our side - sp.Scene.IncomingCloseAgent(sp.UUID, false); + sp.Scene.IncomingCloseAgent(sp.UUID); } }); } - - public LSL_Float osGetHealth(string avatar) - { - CheckThreatLevel(ThreatLevel.None, "osGetHealth"); - m_host.AddScriptLPS(1); - - LSL_Float health = new LSL_Float(-1); - ScenePresence presence = World.GetScenePresence(new UUID(avatar)); - if (presence != null) health = presence.Health; - return health; - } public void osCauseDamage(string avatar, double damage) { @@ -3007,7 +2966,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api ScenePresence presence = World.GetScenePresence(avatarId); if (presence != null) { - LandData land = World.GetLandData(pos); + LandData land = World.GetLandData((float)pos.X, (float)pos.Y); if ((land.Flags & (uint)ParcelFlags.AllowDamage) == (uint)ParcelFlags.AllowDamage) { float health = presence.Health; @@ -3054,7 +3013,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api m_host.AddScriptLPS(1); InitLSL(); - return m_LSL_Api.GetPrimitiveParamsEx(prim, rules); + return m_LSL_Api.GetLinkPrimitiveParamsEx(prim, rules); } public void osSetPrimitiveParams(LSL_Key prim, LSL_List rules) @@ -3063,7 +3022,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api m_host.AddScriptLPS(1); InitLSL(); - m_LSL_Api.SetPrimitiveParamsEx(prim, rules, "osSetPrimitiveParams"); + m_LSL_Api.SetPrimitiveParamsEx(prim, rules); } /// @@ -3295,8 +3254,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } } - #region Attachment commands - public void osForceAttachToAvatar(int attachmentPoint) { CheckThreatLevel(ThreatLevel.High, "osForceAttachToAvatar"); @@ -3386,175 +3343,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api ((LSL_Api)m_LSL_Api).DetachFromAvatar(); } - public LSL_List osGetNumberOfAttachments(LSL_Key avatar, LSL_List attachmentPoints) - { - CheckThreatLevel(ThreatLevel.Moderate, "osGetNumberOfAttachments"); - - m_host.AddScriptLPS(1); - - UUID targetUUID; - ScenePresence target; - LSL_List resp = new LSL_List(); - - if (attachmentPoints.Length >= 1 && UUID.TryParse(avatar.ToString(), out targetUUID) && World.TryGetScenePresence(targetUUID, out target)) - { - foreach (object point in attachmentPoints.Data) - { - LSL_Integer ipoint = new LSL_Integer( - (point is LSL_Integer || point is int || point is uint) ? - (int)point : - 0 - ); - resp.Add(ipoint); - if (ipoint == 0) - { - // indicates zero attachments - resp.Add(new LSL_Integer(0)); - } - else - { - // gets the number of attachments on the attachment point - resp.Add(new LSL_Integer(target.GetAttachments((uint)ipoint).Count)); - } - } - } - - return resp; - } - - public void osMessageAttachments(LSL_Key avatar, string message, LSL_List attachmentPoints, int options) - { - CheckThreatLevel(ThreatLevel.Moderate, "osMessageAttachments"); - m_host.AddScriptLPS(1); - - UUID targetUUID; - ScenePresence target; - - if (attachmentPoints.Length >= 1 && UUID.TryParse(avatar.ToString(), out targetUUID) && World.TryGetScenePresence(targetUUID, out target)) - { - List aps = new List(); - foreach (object point in attachmentPoints.Data) - { - int ipoint; - if (int.TryParse(point.ToString(), out ipoint)) - { - aps.Add(ipoint); - } - } - - List attachments = new List(); - - bool msgAll = aps.Contains(ScriptBaseClass.OS_ATTACH_MSG_ALL); - bool invertPoints = (options & ScriptBaseClass.OS_ATTACH_MSG_INVERT_POINTS) != 0; - - if (msgAll && invertPoints) - { - return; - } - else if (msgAll || invertPoints) - { - attachments = target.GetAttachments(); - } - else - { - foreach (int point in aps) - { - if (point > 0) - { - attachments.AddRange(target.GetAttachments((uint)point)); - } - } - } - - // if we have no attachments at this point, exit now - if (attachments.Count == 0) - { - return; - } - - List ignoreThese = new List(); - - if (invertPoints) - { - foreach (SceneObjectGroup attachment in attachments) - { - if (aps.Contains((int)attachment.AttachmentPoint)) - { - ignoreThese.Add(attachment); - } - } - } - - foreach (SceneObjectGroup attachment in ignoreThese) - { - attachments.Remove(attachment); - } - ignoreThese.Clear(); - - // if inverting removed all attachments to check, exit now - if (attachments.Count < 1) - { - return; - } - - if ((options & ScriptBaseClass.OS_ATTACH_MSG_OBJECT_CREATOR) != 0) - { - foreach (SceneObjectGroup attachment in attachments) - { - if (attachment.RootPart.CreatorID != m_host.CreatorID) - { - ignoreThese.Add(attachment); - } - } - - foreach (SceneObjectGroup attachment in ignoreThese) - { - attachments.Remove(attachment); - } - ignoreThese.Clear(); - - // if filtering by same object creator removed all - // attachments to check, exit now - if (attachments.Count == 0) - { - return; - } - } - - if ((options & ScriptBaseClass.OS_ATTACH_MSG_SCRIPT_CREATOR) != 0) - { - foreach (SceneObjectGroup attachment in attachments) - { - if (attachment.RootPart.CreatorID != m_item.CreatorID) - { - ignoreThese.Add(attachment); - } - } - - foreach (SceneObjectGroup attachment in ignoreThese) - { - attachments.Remove(attachment); - } - ignoreThese.Clear(); - - // if filtering by object creator must match originating - // script creator removed all attachments to check, - // exit now - if (attachments.Count == 0) - { - return; - } - } - - foreach (SceneObjectGroup attachment in attachments) - { - MessageObject(attachment.RootPart.UUID, message); - } - } - } - - #endregion - /// /// Checks if thing is a UUID. /// @@ -3604,166 +3392,5 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api return new LSL_Key(m_host.ParentGroup.FromPartID.ToString()); } - - /// - /// Sets the response type for an HTTP request/response - /// - /// - public void osSetContentType(LSL_Key id, string type) - { - CheckThreatLevel(ThreatLevel.High, "osSetContentType"); - - if (m_UrlModule != null) - m_UrlModule.HttpContentType(new UUID(id),type); - } - - /// Shout an error if the object owner did not grant the script the specified permissions. - /// - /// - /// boolean indicating whether an error was shouted. - protected bool ShoutErrorOnLackingOwnerPerms(int perms, string errorPrefix) - { - m_host.AddScriptLPS(1); - bool fail = false; - if (m_item.PermsGranter != m_host.OwnerID) - { - fail = true; - OSSLShoutError(string.Format("{0}. Permissions not granted to owner.", errorPrefix)); - } - else if ((m_item.PermsMask & perms) == 0) - { - fail = true; - OSSLShoutError(string.Format("{0}. Permissions not granted.", errorPrefix)); - } - - return fail; - } - - protected void DropAttachment(bool checkPerms) - { - if (checkPerms && ShoutErrorOnLackingOwnerPerms(ScriptBaseClass.PERMISSION_ATTACH, "Cannot drop attachment")) - { - return; - } - - IAttachmentsModule attachmentsModule = m_ScriptEngine.World.AttachmentsModule; - ScenePresence sp = attachmentsModule == null ? null : m_host.ParentGroup.Scene.GetScenePresence(m_host.ParentGroup.OwnerID); - - if (attachmentsModule != null && sp != null) - { - attachmentsModule.DetachSingleAttachmentToGround(sp, m_host.ParentGroup.LocalId); - } - } - - protected void DropAttachmentAt(bool checkPerms, LSL_Vector pos, LSL_Rotation rot) - { - if (checkPerms && ShoutErrorOnLackingOwnerPerms(ScriptBaseClass.PERMISSION_ATTACH, "Cannot drop attachment")) - { - return; - } - - IAttachmentsModule attachmentsModule = m_ScriptEngine.World.AttachmentsModule; - ScenePresence sp = attachmentsModule == null ? null : m_host.ParentGroup.Scene.GetScenePresence(m_host.ParentGroup.OwnerID); - - if (attachmentsModule != null && sp != null) - { - attachmentsModule.DetachSingleAttachmentToGround(sp, m_host.ParentGroup.LocalId, pos, rot); - } - } - - public void osDropAttachment() - { - CheckThreatLevel(ThreatLevel.Moderate, "osDropAttachment"); - m_host.AddScriptLPS(1); - - DropAttachment(true); - } - - public void osForceDropAttachment() - { - CheckThreatLevel(ThreatLevel.High, "osForceDropAttachment"); - m_host.AddScriptLPS(1); - - DropAttachment(false); - } - - public void osDropAttachmentAt(LSL_Vector pos, LSL_Rotation rot) - { - CheckThreatLevel(ThreatLevel.Moderate, "osDropAttachmentAt"); - m_host.AddScriptLPS(1); - - DropAttachmentAt(true, pos, rot); - } - - public void osForceDropAttachmentAt(LSL_Vector pos, LSL_Rotation rot) - { - CheckThreatLevel(ThreatLevel.High, "osForceDropAttachmentAt"); - m_host.AddScriptLPS(1); - - DropAttachmentAt(false, pos, rot); - } - - public LSL_Integer osListenRegex(int channelID, string name, string ID, string msg, int regexBitfield) - { - CheckThreatLevel(ThreatLevel.Low, "osListenRegex"); - m_host.AddScriptLPS(1); - UUID keyID; - UUID.TryParse(ID, out keyID); - - // if we want the name to be used as a regular expression, ensure it is valid first. - if ((regexBitfield & ScriptBaseClass.OS_LISTEN_REGEX_NAME) == ScriptBaseClass.OS_LISTEN_REGEX_NAME) - { - try - { - Regex.IsMatch("", name); - } - catch (Exception) - { - OSSLShoutError("Name regex is invalid."); - return -1; - } - } - - // if we want the msg to be used as a regular expression, ensure it is valid first. - if ((regexBitfield & ScriptBaseClass.OS_LISTEN_REGEX_MESSAGE) == ScriptBaseClass.OS_LISTEN_REGEX_MESSAGE) - { - try - { - Regex.IsMatch("", msg); - } - catch (Exception) - { - OSSLShoutError("Message regex is invalid."); - return -1; - } - } - - IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface(); - return (wComm == null) ? -1 : wComm.Listen( - m_host.LocalId, - m_item.ItemID, - m_host.UUID, - channelID, - name, - keyID, - msg, - regexBitfield - ); - } - - public LSL_Integer osRegexIsMatch(string input, string pattern) - { - CheckThreatLevel(ThreatLevel.Low, "osRegexIsMatch"); - m_host.AddScriptLPS(1); - try - { - return Regex.IsMatch(input, pattern) ? 1 : 0; - } - catch (Exception) - { - OSSLShoutError("Possible invalid regular expression detected."); - return 0; - } - } } } diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs index 4dd795d..678f9d5 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs @@ -352,7 +352,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins q = avatar.Rotation; } - LSL_Types.Quaternion r = new LSL_Types.Quaternion(q); + LSL_Types.Quaternion r = new LSL_Types.Quaternion(q.X, q.Y, q.Z, q.W); LSL_Types.Vector3 forward_dir = (new LSL_Types.Vector3(1, 0, 0) * r); double mag_fwd = LSL_Types.Vector3.Mag(forward_dir); @@ -429,8 +429,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins try { Vector3 diff = toRegionPos - fromRegionPos; - double dot = LSL_Types.Vector3.Dot(forward_dir, diff); - double mag_obj = LSL_Types.Vector3.Mag(diff); + LSL_Types.Vector3 obj_dir = new LSL_Types.Vector3(diff.X, diff.Y, diff.Z); + double dot = LSL_Types.Vector3.Dot(forward_dir, obj_dir); + double mag_obj = LSL_Types.Vector3.Mag(obj_dir); ang_obj = Math.Acos(dot / (mag_fwd * mag_obj)); } catch @@ -482,7 +483,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins q = avatar.Rotation; } - LSL_Types.Quaternion r = new LSL_Types.Quaternion(q); + LSL_Types.Quaternion r = new LSL_Types.Quaternion(q.X, q.Y, q.Z, q.W); LSL_Types.Vector3 forward_dir = (new LSL_Types.Vector3(1, 0, 0) * r); double mag_fwd = LSL_Types.Vector3.Mag(forward_dir); bool attached = (SensePoint.ParentGroup.AttachmentPoint != 0); @@ -563,8 +564,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins double ang_obj = 0; try { - LSL_Types.Vector3 obj_dir = new LSL_Types.Vector3( - toRegionPos - fromRegionPos); + Vector3 diff = toRegionPos - fromRegionPos; + LSL_Types.Vector3 obj_dir = new LSL_Types.Vector3(diff.X, diff.Y, diff.Z); double dot = LSL_Types.Vector3.Dot(forward_dir, obj_dir); double mag_obj = LSL_Types.Vector3.Mag(obj_dir); ang_obj = Math.Acos(dot / (mag_fwd * mag_obj)); diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs index 05c20f9..af35258 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs @@ -429,8 +429,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces LSL_Integer llGetLinkNumberOfSides(LSL_Integer link); void llSetPhysicsMaterial(int material_bits, float material_gravity_modifier, float material_restitution, float material_friction, float material_density); - void SetPrimitiveParamsEx(LSL_Key prim, LSL_List rules, string originFunc); + void SetPrimitiveParamsEx(LSL_Key prim, LSL_List rules); + LSL_List GetLinkPrimitiveParamsEx(LSL_Key prim, LSL_List rules); void llSetKeyframedMotion(LSL_List frames, LSL_List options); - LSL_List GetPrimitiveParamsEx(LSL_Key prim, LSL_List rules); } } diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs index c447d1f..8c34ed3 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs @@ -40,75 +40,16 @@ using LSL_Key = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString; namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces { - /// - /// To permit region owners to enable the extended scripting functionality - /// of OSSL, without allowing malicious scripts to access potentially - /// troublesome functions, each OSSL function is assigned a threat level, - /// and access to the functions is granted or denied based on a default - /// threshold set in OpenSim.ini (which can be overridden for individual - /// functions on a case-by-case basis) - /// public enum ThreatLevel { - // Not documented, presumably means permanently disabled ? NoAccess = -1, - - /// - /// Function is no threat at all. It doesn't constitute a threat to - /// either users or the system and has no known side effects. - /// None = 0, - - /// - /// Abuse of this command can cause a nuisance to the region operator, - /// such as log message spew. - /// Nuisance = 1, - - /// - /// Extreme levels of abuse of this function can cause impaired - /// functioning of the region, or very gullible users can be tricked - /// into experiencing harmless effects. - /// VeryLow = 2, - - /// - /// Intentional abuse can cause crashes or malfunction under certain - /// circumstances, which can be easily rectified; or certain users can - /// be tricked into certain situations in an avoidable manner. - /// Low = 3, - - /// - /// Intentional abuse can cause denial of service and crashes with - /// potential of data or state loss; or trusting users can be tricked - /// into embarrassing or uncomfortable situations. - /// Moderate = 4, - - /// - /// Casual abuse can cause impaired functionality or temporary denial - /// of service conditions. Intentional abuse can easily cause crashes - /// with potential data loss, or can be used to trick experienced and - /// cautious users into unwanted situations, or changes global data - /// permanently and without undo ability. - /// High = 5, - - /// - /// Even normal use may, depending on the number of instances, or - /// frequency of use, result in severe service impairment or crash - /// with loss of data, or can be used to cause unwanted or harmful - /// effects on users without giving the user a means to avoid it. - /// VeryHigh = 6, - - /// - /// Even casual use is a danger to region stability, or function allows - /// console or OS command execution, or function allows taking money - /// without consent, or allows deletion or modification of user data, - /// or allows the compromise of sensitive data by design. - /// Severe = 7 }; @@ -157,7 +98,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces void osAvatarPlayAnimation(string avatar, string animation); void osAvatarStopAnimation(string avatar, string animation); - #region Attachment commands + // Attachment commands /// /// Attach the object containing this script to the avatar that owns it without asking for PERMISSION_ATTACH @@ -192,29 +133,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces /// Nothing happens if the object is not attached. void osForceDetachFromAvatar(); - /// - /// Returns a strided list of the specified attachment points and the number of attachments on those points. - /// - /// avatar UUID - /// list of ATTACH_* constants - /// - LSL_List osGetNumberOfAttachments(LSL_Key avatar, LSL_List attachmentPoints); - - /// - /// Sends a specified message to the specified avatar's attachments on - /// the specified attachment points. - /// - /// - /// Behaves as osMessageObject(), without the sending script needing to know the attachment keys in advance. - /// - /// avatar UUID - /// message string - /// list of ATTACH_* constants, or -1 for all attachments. If -1 is specified and OS_ATTACH_MSG_INVERT_POINTS is present in flags, no action is taken. - /// flags further constraining the attachments to deliver the message to. - void osMessageAttachments(LSL_Key avatar, string message, LSL_List attachmentPoints, int flags); - - #endregion - //texture draw functions string osMovePen(string drawList, int x, int y); string osDrawLine(string drawList, int startX, int startY, int endX, int endY); @@ -340,7 +258,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces int osGetSimulatorMemory(); void osKickAvatar(string FirstName,string SurName,string alert); void osSetSpeed(string UUID, LSL_Float SpeedModifier); - LSL_Float osGetHealth(string avatar); void osCauseHealing(string avatar, double healing); void osCauseDamage(string avatar, double damage); LSL_List osGetPrimitiveParams(LSL_Key prim, LSL_List rules); @@ -388,59 +305,5 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces /// /// Rezzing object key or NULL_KEY if rezzed by agent or otherwise unknown. LSL_Key osGetRezzingObject(); - - /// - /// Sets the response type for an HTTP request/response - /// - /// - void osSetContentType(LSL_Key id, string type); - - /// - /// Attempts to drop an attachment to the ground - /// - void osDropAttachment(); - - /// - /// Attempts to drop an attachment to the ground while bypassing the script permissions - /// - void osForceDropAttachment(); - - /// - /// Attempts to drop an attachment at the specified coordinates. - /// - /// - /// - void osDropAttachmentAt(vector pos, rotation rot); - - /// - /// Attempts to drop an attachment at the specified coordinates while bypassing the script permissions - /// - /// - /// - void osForceDropAttachmentAt(vector pos, rotation rot); - - /// - /// Identical to llListen except for a bitfield which indicates which - /// string parameters should be parsed as regex patterns. - /// - /// - /// - /// - /// - /// - /// OS_LISTEN_REGEX_NAME - /// OS_LISTEN_REGEX_MESSAGE - /// - /// - LSL_Integer osListenRegex(int channelID, string name, string ID, - string msg, int regexBitfield); - - /// - /// Wraps to bool Regex.IsMatch(string input, string pattern) - /// - /// string to test for match - /// string to use as pattern - /// boolean - LSL_Integer osRegexIsMatch(string input, string pattern); } } diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs index 0dd5a57..f989cc6 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs @@ -237,58 +237,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase public const int ATTACH_HUD_BOTTOM = 37; public const int ATTACH_HUD_BOTTOM_RIGHT = 38; - #region osMessageAttachments constants - - /// - /// Instructs osMessageAttachements to send the message to attachments - /// on every point. - /// - /// - /// One might expect this to be named OS_ATTACH_ALL, but then one might - /// also expect functions designed to attach or detach or get - /// attachments to work with it too. Attaching a no-copy item to - /// many attachments could be dangerous. - /// when combined with OS_ATTACH_MSG_INVERT_POINTS, will prevent the - /// message from being sent. - /// if combined with OS_ATTACH_MSG_OBJECT_CREATOR or - /// OS_ATTACH_MSG_SCRIPT_CREATOR, could result in no message being - /// sent- this is expected behaviour. - /// - public const int OS_ATTACH_MSG_ALL = -65535; - - /// - /// Instructs osMessageAttachements to invert how the attachment points - /// list should be treated (e.g. go from inclusive operation to - /// exclusive operation). - /// - /// - /// This might be used if you want to deliver a message to one set of - /// attachments and a different message to everything else. With - /// this flag, you only need to build one explicit list for both calls. - /// - public const int OS_ATTACH_MSG_INVERT_POINTS = 1; - - /// - /// Instructs osMessageAttachments to only send the message to - /// attachments with a CreatorID that matches the host object CreatorID - /// - /// - /// This would be used if distributed in an object vendor/updater server. - /// - public const int OS_ATTACH_MSG_OBJECT_CREATOR = 2; - - /// - /// Instructs osMessageAttachments to only send the message to - /// attachments with a CreatorID that matches the sending script CreatorID - /// - /// - /// This might be used if the script is distributed independently of a - /// containing object. - /// - public const int OS_ATTACH_MSG_SCRIPT_CREATOR = 4; - - #endregion - public const int LAND_LEVEL = 0; public const int LAND_RAISE = 1; public const int LAND_LOWER = 2; @@ -381,7 +329,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase public const int PRIM_OMEGA = 32; public const int PRIM_POS_LOCAL = 33; public const int PRIM_LINK_TARGET = 34; - public const int PRIM_SLICE = 35; public const int PRIM_TEXGEN_DEFAULT = 0; public const int PRIM_TEXGEN_PLANAR = 1; @@ -613,7 +560,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase public const int CLICK_ACTION_OPEN = 4; public const int CLICK_ACTION_PLAY = 5; public const int CLICK_ACTION_OPEN_MEDIA = 6; - public const int CLICK_ACTION_ZOOM = 7; // constants for the llDetectedTouch* functions public const int TOUCH_INVALID_FACE = -1; @@ -741,15 +687,5 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase public const int KFM_CMD_PLAY = 0; public const int KFM_CMD_STOP = 1; public const int KFM_CMD_PAUSE = 2; - - /// - /// process name parameter as regex - /// - public const int OS_LISTEN_REGEX_NAME = 0x1; - - /// - /// process message parameter as regex - /// - public const int OS_LISTEN_REGEX_MESSAGE = 0x2; } } diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs index afa9ae0..94405d2 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs @@ -289,7 +289,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase m_OSSL_Functions.osAvatarStopAnimation(avatar, animation); } - #region Attachment commands + // Avatar functions public void osForceAttachToAvatar(int attachmentPoint) { @@ -311,18 +311,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase m_OSSL_Functions.osForceDetachFromAvatar(); } - public LSL_List osGetNumberOfAttachments(LSL_Key avatar, LSL_List attachmentPoints) - { - return m_OSSL_Functions.osGetNumberOfAttachments(avatar, attachmentPoints); - } - - public void osMessageAttachments(LSL_Key avatar, string message, LSL_List attachmentPoints, int flags) - { - m_OSSL_Functions.osMessageAttachments(avatar, message, attachmentPoints, flags); - } - - #endregion - // Texture Draw functions public string osMovePen(string drawList, int x, int y) @@ -877,12 +865,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase { m_OSSL_Functions.osSetSpeed(UUID, SpeedModifier); } - - public LSL_Float osGetHealth(string avatar) - { - return m_OSSL_Functions.osGetHealth(avatar); - } - + public void osCauseDamage(string avatar, double damage) { m_OSSL_Functions.osCauseDamage(avatar, damage); @@ -967,40 +950,5 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase { return m_OSSL_Functions.osGetRezzingObject(); } - - public void osSetContentType(LSL_Key id, string type) - { - m_OSSL_Functions.osSetContentType(id,type); - } - - public void osDropAttachment() - { - m_OSSL_Functions.osDropAttachment(); - } - - public void osForceDropAttachment() - { - m_OSSL_Functions.osForceDropAttachment(); - } - - public void osDropAttachmentAt(vector pos, rotation rot) - { - m_OSSL_Functions.osDropAttachmentAt(pos, rot); - } - - public void osForceDropAttachmentAt(vector pos, rotation rot) - { - m_OSSL_Functions.osForceDropAttachmentAt(pos, rot); - } - - public LSL_Integer osListenRegex(int channelID, string name, string ID, string msg, int regexBitfield) - { - return m_OSSL_Functions.osListenRegex(channelID, name, ID, msg, regexBitfield); - } - - public LSL_Integer osRegexIsMatch(string input, string pattern) - { - return m_OSSL_Functions.osRegexIsMatch(input, pattern); - } } } diff --git a/OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs b/OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs index 03be2ab..17a0d69 100644 --- a/OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs +++ b/OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs @@ -546,8 +546,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools "OpenSim.Region.ScriptEngine.Shared.dll")); parameters.ReferencedAssemblies.Add(Path.Combine(rootPath, "OpenSim.Region.ScriptEngine.Shared.Api.Runtime.dll")); - parameters.ReferencedAssemblies.Add(Path.Combine(rootPath, - "OpenMetaverseTypes.dll")); if (lang == enumCompileType.yp) { diff --git a/OpenSim/Region/ScriptEngine/Shared/Helpers.cs b/OpenSim/Region/ScriptEngine/Shared/Helpers.cs index 22804f5..9e5fb24 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Helpers.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Helpers.cs @@ -164,11 +164,11 @@ namespace OpenSim.Region.ScriptEngine.Shared else { // Set the values from the touch data provided by the client - touchST = new LSL_Types.Vector3(value.STCoord); - touchUV = new LSL_Types.Vector3(value.UVCoord); - touchNormal = new LSL_Types.Vector3(value.Normal); - touchBinormal = new LSL_Types.Vector3(value.Binormal); - touchPos = new LSL_Types.Vector3(value.Position); + touchST = new LSL_Types.Vector3(value.STCoord.X, value.STCoord.Y, value.STCoord.Z); + touchUV = new LSL_Types.Vector3(value.UVCoord.X, value.UVCoord.Y, value.UVCoord.Z); + touchNormal = new LSL_Types.Vector3(value.Normal.X, value.Normal.Y, value.Normal.Z); + touchBinormal = new LSL_Types.Vector3(value.Binormal.X, value.Binormal.Y, value.Binormal.Z); + touchPos = new LSL_Types.Vector3(value.Position.X, value.Position.Y, value.Position.Z); touchFace = value.FaceIndex; } } @@ -189,13 +189,19 @@ namespace OpenSim.Region.ScriptEngine.Shared Country = account.UserCountry; Owner = Key; - Position = new LSL_Types.Vector3(presence.AbsolutePosition); + Position = new LSL_Types.Vector3( + presence.AbsolutePosition.X, + presence.AbsolutePosition.Y, + presence.AbsolutePosition.Z); Rotation = new LSL_Types.Quaternion( presence.Rotation.X, presence.Rotation.Y, presence.Rotation.Z, presence.Rotation.W); - Velocity = new LSL_Types.Vector3(presence.Velocity); + Velocity = new LSL_Types.Vector3( + presence.Velocity.X, + presence.Velocity.Y, + presence.Velocity.Z); Type = 0x01; // Avatar if (presence.PresenceType == PresenceType.Npc) @@ -248,12 +254,16 @@ namespace OpenSim.Region.ScriptEngine.Shared } } - Position = new LSL_Types.Vector3(part.AbsolutePosition); + Position = new LSL_Types.Vector3(part.AbsolutePosition.X, + part.AbsolutePosition.Y, + part.AbsolutePosition.Z); Quaternion wr = part.ParentGroup.GroupRotation; Rotation = new LSL_Types.Quaternion(wr.X, wr.Y, wr.Z, wr.W); - Velocity = new LSL_Types.Vector3(part.Velocity); + Velocity = new LSL_Types.Vector3(part.Velocity.X, + part.Velocity.Y, + part.Velocity.Z); } } diff --git a/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs b/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs index c9c4753..8adf4c5 100644 --- a/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs +++ b/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs @@ -31,11 +31,6 @@ using System.Globalization; using System.Text.RegularExpressions; using OpenSim.Framework; -using OpenMetaverse; -using OMV_Vector3 = OpenMetaverse.Vector3; -using OMV_Vector3d = OpenMetaverse.Vector3d; -using OMV_Quaternion = OpenMetaverse.Quaternion; - namespace OpenSim.Region.ScriptEngine.Shared { [Serializable] @@ -59,20 +54,6 @@ namespace OpenSim.Region.ScriptEngine.Shared z = (float)vector.z; } - public Vector3(OMV_Vector3 vector) - { - x = vector.X; - y = vector.Y; - z = vector.Z; - } - - public Vector3(OMV_Vector3d vector) - { - x = vector.X; - y = vector.Y; - z = vector.Z; - } - public Vector3(double X, double Y, double Z) { x = X; @@ -128,26 +109,6 @@ namespace OpenSim.Region.ScriptEngine.Shared return new list(new object[] { vec }); } - public static implicit operator OMV_Vector3(Vector3 vec) - { - return new OMV_Vector3((float)vec.x, (float)vec.y, (float)vec.z); - } - - public static implicit operator Vector3(OMV_Vector3 vec) - { - return new Vector3(vec); - } - - public static implicit operator OMV_Vector3d(Vector3 vec) - { - return new OMV_Vector3d(vec.x, vec.y, vec.z); - } - - public static implicit operator Vector3(OMV_Vector3d vec) - { - return new Vector3(vec); - } - public static bool operator ==(Vector3 lhs, Vector3 rhs) { return (lhs.x == rhs.x && lhs.y == rhs.y && lhs.z == rhs.z); @@ -361,14 +322,6 @@ namespace OpenSim.Region.ScriptEngine.Shared s = 1; } - public Quaternion(OMV_Quaternion rot) - { - x = rot.X; - y = rot.Y; - z = rot.Z; - s = rot.W; - } - #endregion #region Overriders @@ -415,21 +368,6 @@ namespace OpenSim.Region.ScriptEngine.Shared return new list(new object[] { r }); } - public static implicit operator OMV_Quaternion(Quaternion rot) - { - // LSL quaternions can normalize to 0, normal Quaternions can't. - if (rot.s == 0 && rot.x == 0 && rot.y == 0 && rot.z == 0) - rot.z = 1; // ZERO_ROTATION = 0,0,0,1 - OMV_Quaternion omvrot = new OMV_Quaternion((float)rot.x, (float)rot.y, (float)rot.z, (float)rot.s); - omvrot.Normalize(); - return omvrot; - } - - public static implicit operator Quaternion(OMV_Quaternion rot) - { - return new Quaternion(rot); - } - public static bool operator ==(Quaternion lhs, Quaternion rhs) { // Return true if the fields match: @@ -624,23 +562,12 @@ namespace OpenSim.Region.ScriptEngine.Shared else if (m_data[itemIndex] is LSL_Types.LSLString) return new LSLInteger(m_data[itemIndex].ToString()); else - throw new InvalidCastException(string.Format( - "{0} expected but {1} given", - typeof(LSL_Types.LSLInteger).Name, - m_data[itemIndex] != null ? - m_data[itemIndex].GetType().Name : "null")); + throw new InvalidCastException(); } public LSL_Types.Vector3 GetVector3Item(int itemIndex) { - if(m_data[itemIndex] is LSL_Types.Vector3) - return (LSL_Types.Vector3)m_data[itemIndex]; - else - throw new InvalidCastException(string.Format( - "{0} expected but {1} given", - typeof(LSL_Types.Vector3).Name, - m_data[itemIndex] != null ? - m_data[itemIndex].GetType().Name : "null")); + return (LSL_Types.Vector3)m_data[itemIndex]; } public LSL_Types.Quaternion GetQuaternionItem(int itemIndex) diff --git a/OpenSim/Region/ScriptEngine/Shared/ScriptException.cs b/OpenSim/Region/ScriptEngine/Shared/ScriptException.cs deleted file mode 100644 index f55ba7e..0000000 --- a/OpenSim/Region/ScriptEngine/Shared/ScriptException.cs +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Runtime.Serialization; - -namespace OpenSim.Region.ScriptEngine.Shared -{ - [Serializable] - public class ScriptException : Exception - { - public ScriptException() : base() {} - - public ScriptException(string message) : base(message) {} - - public ScriptException(string message, Exception innerException) : base(message, innerException) {} - - public ScriptException(SerializationInfo info, StreamingContext context) :base(info, context) {} - } -} \ No newline at end of file diff --git a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiListTests.cs b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiListTests.cs deleted file mode 100644 index dd23be8..0000000 --- a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiListTests.cs +++ /dev/null @@ -1,134 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using NUnit.Framework; -using OpenSim.Framework; -using OpenSim.Tests.Common; -using OpenSim.Region.ScriptEngine.Shared; -using OpenSim.Region.Framework.Scenes; -using Nini.Config; -using OpenSim.Region.ScriptEngine.Shared.Api; -using OpenSim.Region.ScriptEngine.Shared.ScriptBase; -using OpenMetaverse; -using OpenSim.Tests.Common.Mock; - -using LSL_Float = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLFloat; -using LSL_Integer = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLInteger; -using LSL_List = OpenSim.Region.ScriptEngine.Shared.LSL_Types.list; -using LSL_String = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString; - -namespace OpenSim.Region.ScriptEngine.Shared.Tests -{ - [TestFixture] - public class LSL_ApiListTests - { - private LSL_Api m_lslApi; - - [SetUp] - public void SetUp() - { - IConfigSource initConfigSource = new IniConfigSource(); - IConfig config = initConfigSource.AddConfig("XEngine"); - config.Set("Enabled", "true"); - - Scene scene = new SceneHelpers().SetupScene(); - SceneObjectPart part = SceneHelpers.AddSceneObject(scene).RootPart; - - XEngine.XEngine engine = new XEngine.XEngine(); - engine.Initialise(initConfigSource); - engine.AddRegion(scene); - - m_lslApi = new LSL_Api(); - m_lslApi.Initialize(engine, part, null); - } - - [Test] - public void TestllListFindList() - { - TestHelpers.InMethod(); - - LSL_List src = new LSL_List(new LSL_Integer(1), new LSL_Integer(2), new LSL_Integer(3)); - - { - // Test for a single item that should be found - int result = m_lslApi.llListFindList(src, new LSL_List(new LSL_Integer(4))); - Assert.That(result, Is.EqualTo(-1)); - } - - { - // Test for a single item that should be found - int result = m_lslApi.llListFindList(src, new LSL_List(new LSL_Integer(2))); - Assert.That(result, Is.EqualTo(1)); - } - - { - // Test for a constant that should be found - int result = m_lslApi.llListFindList(src, new LSL_List(ScriptBaseClass.AGENT)); - Assert.That(result, Is.EqualTo(0)); - } - - { - // Test for a list that should be found - int result = m_lslApi.llListFindList(src, new LSL_List(new LSL_Integer(2), new LSL_Integer(3))); - Assert.That(result, Is.EqualTo(1)); - } - - { - // Test for a single item not in the list - int result = m_lslApi.llListFindList(src, new LSL_List(new LSL_Integer(4))); - Assert.That(result, Is.EqualTo(-1)); - } - - { - // Test for something that should not be cast - int result = m_lslApi.llListFindList(src, new LSL_List(new LSL_String("4"))); - Assert.That(result, Is.EqualTo(-1)); - } - - { - // Test for a list not in the list - int result - = m_lslApi.llListFindList( - src, new LSL_List(new LSL_Integer(2), new LSL_Integer(3), new LSL_Integer(4))); - Assert.That(result, Is.EqualTo(-1)); - } - - { - LSL_List srcWithConstants - = new LSL_List(new LSL_Integer(3), ScriptBaseClass.AGENT, ScriptBaseClass.OS_NPC_LAND_AT_TARGET); - - // Test for constants that appears in the source list that should be found - int result - = m_lslApi.llListFindList(srcWithConstants, new LSL_List(new LSL_Integer(1), new LSL_Integer(2))); - - Assert.That(result, Is.EqualTo(1)); - } - } - } - } \ No newline at end of file diff --git a/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiAppearanceTest.cs b/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiAppearanceTest.cs index c401794..c8718d9 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiAppearanceTest.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiAppearanceTest.cs @@ -75,6 +75,76 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests m_engine.AddRegion(m_scene); } + /// + /// Test creation of an NPC where the appearance data comes from a notecard + /// + [Test] + public void TestOsNpcCreateUsingAppearanceFromNotecard() + { + TestHelpers.InMethod(); +// log4net.Config.XmlConfigurator.Configure(); + + // Store an avatar with a different height from default in a notecard. + UUID userId = TestHelpers.ParseTail(0x1); + float newHeight = 1.9f; + + ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, userId); + sp.Appearance.AvatarHeight = newHeight; + SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, userId, 0x10); + SceneObjectPart part = so.RootPart; + m_scene.AddSceneObject(so); + + OSSL_Api osslApi = new OSSL_Api(); + osslApi.Initialize(m_engine, part, null); + + string notecardName = "appearanceNc"; + osslApi.osOwnerSaveAppearance(notecardName); + + // Try creating a bot using the appearance in the notecard. + string npcRaw = osslApi.osNpcCreate("Jane", "Doe", new LSL_Types.Vector3(128, 128, 128), notecardName); + Assert.That(npcRaw, Is.Not.Null); + + UUID npcId = new UUID(npcRaw); + ScenePresence npc = m_scene.GetScenePresence(npcId); + Assert.That(npc, Is.Not.Null); + Assert.That(npc.Appearance.AvatarHeight, Is.EqualTo(newHeight)); + } + + /// + /// Test creation of an NPC where the appearance data comes from an avatar already in the region. + /// + [Test] + public void TestOsNpcCreateUsingAppearanceFromAvatar() + { + TestHelpers.InMethod(); +// TestHelpers.EnableLogging(); + + // Store an avatar with a different height from default in a notecard. + UUID userId = TestHelpers.ParseTail(0x1); + float newHeight = 1.9f; + + ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, userId); + sp.Appearance.AvatarHeight = newHeight; + SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, userId, 0x10); + SceneObjectPart part = so.RootPart; + m_scene.AddSceneObject(so); + + OSSL_Api osslApi = new OSSL_Api(); + osslApi.Initialize(m_engine, part, null); + + string notecardName = "appearanceNc"; + osslApi.osOwnerSaveAppearance(notecardName); + + // Try creating a bot using the existing avatar's appearance + string npcRaw = osslApi.osNpcCreate("Jane", "Doe", new LSL_Types.Vector3(128, 128, 128), sp.UUID.ToString()); + Assert.That(npcRaw, Is.Not.Null); + + UUID npcId = new UUID(npcRaw); + ScenePresence npc = m_scene.GetScenePresence(npcId); + Assert.That(npc, Is.Not.Null); + Assert.That(npc.Appearance.AvatarHeight, Is.EqualTo(newHeight)); + } + [Test] public void TestOsOwnerSaveAppearance() { diff --git a/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiNpcTests.cs b/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiNpcTests.cs index b49bcc2..25679a6 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiNpcTests.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiNpcTests.cs @@ -36,7 +36,6 @@ using OpenMetaverse; using OpenMetaverse.Assets; using OpenMetaverse.StructuredData; using OpenSim.Framework; -using OpenSim.Region.CoreModules.Avatar.Attachments; using OpenSim.Region.CoreModules.Avatar.AvatarFactory; using OpenSim.Region.OptionalModules.World.NPC; using OpenSim.Region.Framework.Scenes; @@ -72,8 +71,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests config.Set("Enabled", "true"); m_scene = new SceneHelpers().SetupScene(); - SceneHelpers.SetupSceneModules( - m_scene, initConfigSource, new AvatarFactoryModule(), new AttachmentsModule(), new NPCModule()); + SceneHelpers.SetupSceneModules(m_scene, initConfigSource, new AvatarFactoryModule(), new NPCModule()); m_engine = new XEngine.XEngine(); m_engine.Initialise(initConfigSource); @@ -81,191 +79,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests } /// - /// Test creation of an NPC where the appearance data comes from a notecard - /// - [Test] - public void TestOsNpcCreateUsingAppearanceFromNotecard() - { - TestHelpers.InMethod(); - - // Store an avatar with a different height from default in a notecard. - UUID userId = TestHelpers.ParseTail(0x1); - float newHeight = 1.9f; - - ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, userId); - sp.Appearance.AvatarHeight = newHeight; - SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, userId, 0x10); - SceneObjectPart part = so.RootPart; - m_scene.AddSceneObject(so); - - OSSL_Api osslApi = new OSSL_Api(); - osslApi.Initialize(m_engine, part, null); - - string notecardName = "appearanceNc"; - osslApi.osOwnerSaveAppearance(notecardName); - - // Try creating a bot using the appearance in the notecard. - string npcRaw = osslApi.osNpcCreate("Jane", "Doe", new LSL_Types.Vector3(128, 128, 128), notecardName); - Assert.That(npcRaw, Is.Not.Null); - - UUID npcId = new UUID(npcRaw); - ScenePresence npc = m_scene.GetScenePresence(npcId); - Assert.That(npc, Is.Not.Null); - Assert.That(npc.Appearance.AvatarHeight, Is.EqualTo(newHeight)); - } - - [Test] - public void TestOsNpcCreateNotExistingNotecard() - { - TestHelpers.InMethod(); - - UUID userId = TestHelpers.ParseTail(0x1); - - SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, userId, 0x10); - m_scene.AddSceneObject(so); - - OSSL_Api osslApi = new OSSL_Api(); - osslApi.Initialize(m_engine, so.RootPart, null); - - string npcRaw; - bool gotExpectedException = false; - try - { - npcRaw - = osslApi.osNpcCreate("Jane", "Doe", new LSL_Types.Vector3(128, 128, 128), "not existing notecard name"); - } - catch (ScriptException) - { - gotExpectedException = true; - } - - Assert.That(gotExpectedException, Is.True); - } - - /// - /// Test creation of an NPC where the appearance data comes from an avatar already in the region. - /// - [Test] - public void TestOsNpcCreateUsingAppearanceFromAvatar() - { - TestHelpers.InMethod(); -// TestHelpers.EnableLogging(); - - // Store an avatar with a different height from default in a notecard. - UUID userId = TestHelpers.ParseTail(0x1); - float newHeight = 1.9f; - - ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, userId); - sp.Appearance.AvatarHeight = newHeight; - SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, userId, 0x10); - SceneObjectPart part = so.RootPart; - m_scene.AddSceneObject(so); - - OSSL_Api osslApi = new OSSL_Api(); - osslApi.Initialize(m_engine, part, null); - - string notecardName = "appearanceNc"; - osslApi.osOwnerSaveAppearance(notecardName); - - // Try creating a bot using the existing avatar's appearance - string npcRaw = osslApi.osNpcCreate("Jane", "Doe", new LSL_Types.Vector3(128, 128, 128), sp.UUID.ToString()); - Assert.That(npcRaw, Is.Not.Null); - - UUID npcId = new UUID(npcRaw); - ScenePresence npc = m_scene.GetScenePresence(npcId); - Assert.That(npc, Is.Not.Null); - Assert.That(npc.Appearance.AvatarHeight, Is.EqualTo(newHeight)); - } - - [Test] - public void TestOsNpcLoadAppearance() - { - TestHelpers.InMethod(); - - // Store an avatar with a different height from default in a notecard. - UUID userId = TestHelpers.ParseTail(0x1); - float firstHeight = 1.9f; - float secondHeight = 2.1f; - string firstAppearanceNcName = "appearanceNc1"; - string secondAppearanceNcName = "appearanceNc2"; - - ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, userId); - sp.Appearance.AvatarHeight = firstHeight; - SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, userId, 0x10); - SceneObjectPart part = so.RootPart; - m_scene.AddSceneObject(so); - - OSSL_Api osslApi = new OSSL_Api(); - osslApi.Initialize(m_engine, part, null); - - osslApi.osOwnerSaveAppearance(firstAppearanceNcName); - - string npcRaw - = osslApi.osNpcCreate("Jane", "Doe", new LSL_Types.Vector3(128, 128, 128), firstAppearanceNcName); - - // Create a second appearance notecard with a different height - sp.Appearance.AvatarHeight = secondHeight; - osslApi.osOwnerSaveAppearance(secondAppearanceNcName); - - osslApi.osNpcLoadAppearance(npcRaw, secondAppearanceNcName); - - UUID npcId = new UUID(npcRaw); - ScenePresence npc = m_scene.GetScenePresence(npcId); - Assert.That(npc, Is.Not.Null); - Assert.That(npc.Appearance.AvatarHeight, Is.EqualTo(secondHeight)); - } - - [Test] - public void TestOsNpcLoadAppearanceNotExistingNotecard() - { - TestHelpers.InMethod(); - - // Store an avatar with a different height from default in a notecard. - UUID userId = TestHelpers.ParseTail(0x1); - float firstHeight = 1.9f; - float secondHeight = 2.1f; - string firstAppearanceNcName = "appearanceNc1"; - string secondAppearanceNcName = "appearanceNc2"; - - ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, userId); - sp.Appearance.AvatarHeight = firstHeight; - SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, userId, 0x10); - SceneObjectPart part = so.RootPart; - m_scene.AddSceneObject(so); - - OSSL_Api osslApi = new OSSL_Api(); - osslApi.Initialize(m_engine, part, null); - - osslApi.osOwnerSaveAppearance(firstAppearanceNcName); - - string npcRaw - = osslApi.osNpcCreate("Jane", "Doe", new LSL_Types.Vector3(128, 128, 128), firstAppearanceNcName); - - bool gotExpectedException = false; - try - { - osslApi.osNpcLoadAppearance(npcRaw, secondAppearanceNcName); - } - catch (ScriptException) - { - gotExpectedException = true; - } - - Assert.That(gotExpectedException, Is.True); - - UUID npcId = new UUID(npcRaw); - ScenePresence npc = m_scene.GetScenePresence(npcId); - Assert.That(npc, Is.Not.Null); - Assert.That(npc.Appearance.AvatarHeight, Is.EqualTo(firstHeight)); - } - - /// /// Test removal of an owned NPC. /// [Test] public void TestOsNpcRemoveOwned() { TestHelpers.InMethod(); +// log4net.Config.XmlConfigurator.Configure(); // Store an avatar with a different height from default in a notecard. UUID userId = TestHelpers.ParseTail(0x1); diff --git a/OpenSim/Region/ScriptEngine/XEngine/EventManager.cs b/OpenSim/Region/ScriptEngine/XEngine/EventManager.cs index 9405075..5c4174e 100644 --- a/OpenSim/Region/ScriptEngine/XEngine/EventManager.cs +++ b/OpenSim/Region/ScriptEngine/XEngine/EventManager.cs @@ -96,12 +96,9 @@ namespace OpenSim.Region.ScriptEngine.XEngine if (part == null) return; - if ((part.ScriptEvents & scriptEvents.money) == 0) - part = part.ParentGroup.RootPart; - m_log.Debug("Paid: " + objectID + " from " + agentID + ", amount " + amount); -// part = part.ParentGroup.RootPart; + part = part.ParentGroup.RootPart; money(part.LocalId, agentID, amount); } @@ -155,7 +152,9 @@ namespace OpenSim.Region.ScriptEngine.XEngine det[0] = new DetectParams(); det[0].Key = remoteClient.AgentId; det[0].Populate(myScriptEngine.World); - det[0].OffsetPos = offsetPos; + det[0].OffsetPos = new LSL_Types.Vector3(offsetPos.X, + offsetPos.Y, + offsetPos.Z); if (originalID == 0) { @@ -299,7 +298,9 @@ namespace OpenSim.Region.ScriptEngine.XEngine foreach (DetectedObject detobj in col.Colliders) { DetectParams d = new DetectParams(); - d.Position = detobj.posVector; + d.Position = new LSL_Types.Vector3(detobj.posVector.X, + detobj.posVector.Y, + detobj.posVector.Z); d.Populate(myScriptEngine.World); det.Add(d); myScriptEngine.PostObjectEvent(localID, new EventParams( @@ -317,7 +318,9 @@ namespace OpenSim.Region.ScriptEngine.XEngine foreach (DetectedObject detobj in col.Colliders) { DetectParams d = new DetectParams(); - d.Position = detobj.posVector; + d.Position = new LSL_Types.Vector3(detobj.posVector.X, + detobj.posVector.Y, + detobj.posVector.Z); d.Populate(myScriptEngine.World); det.Add(d); myScriptEngine.PostObjectEvent(localID, new EventParams( @@ -334,7 +337,9 @@ namespace OpenSim.Region.ScriptEngine.XEngine foreach (DetectedObject detobj in col.Colliders) { DetectParams d = new DetectParams(); - d.Position = detobj.posVector; + d.Position = new LSL_Types.Vector3(detobj.posVector.X, + detobj.posVector.Y, + detobj.posVector.Z); d.Populate(myScriptEngine.World); det.Add(d); myScriptEngine.PostObjectEvent(localID, new EventParams( @@ -376,8 +381,8 @@ namespace OpenSim.Region.ScriptEngine.XEngine myScriptEngine.PostObjectEvent(localID, new EventParams( "at_target", new object[] { new LSL_Types.LSLInteger(handle), - new LSL_Types.Vector3(targetpos), - new LSL_Types.Vector3(atpos) }, + new LSL_Types.Vector3(targetpos.X,targetpos.Y,targetpos.Z), + new LSL_Types.Vector3(atpos.X,atpos.Y,atpos.Z) }, new DetectParams[0])); } @@ -394,8 +399,8 @@ namespace OpenSim.Region.ScriptEngine.XEngine myScriptEngine.PostObjectEvent(localID, new EventParams( "at_rot_target", new object[] { new LSL_Types.LSLInteger(handle), - new LSL_Types.Quaternion(targetrot), - new LSL_Types.Quaternion(atrot) }, + new LSL_Types.Quaternion(targetrot.X,targetrot.Y,targetrot.Z,targetrot.W), + new LSL_Types.Quaternion(atrot.X,atrot.Y,atrot.Z,atrot.W) }, new DetectParams[0])); } diff --git a/OpenSim/Region/ScriptEngine/XEngine/Tests/XEngineTest.cs b/OpenSim/Region/ScriptEngine/XEngine/Tests/XEngineTest.cs index f331658..f247a0b 100644 --- a/OpenSim/Region/ScriptEngine/XEngine/Tests/XEngineTest.cs +++ b/OpenSim/Region/ScriptEngine/XEngine/Tests/XEngineTest.cs @@ -90,7 +90,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine.Tests // log4net.Config.XmlConfigurator.Configure(); UUID userId = TestHelpers.ParseTail(0x1); -// UUID objectId = TestHelpers.ParseTail(0x100); +// UUID objectId = TestHelpers.ParseTail(0x2); // UUID itemId = TestHelpers.ParseTail(0x3); string itemName = "TestStartScript() Item"; @@ -105,18 +105,12 @@ namespace OpenSim.Region.ScriptEngine.XEngine.Tests m_scene.EventManager.OnChatFromWorld += OnChatFromWorld; - SceneObjectPart partWhereRezzed = m_scene.RezNewScript(userId, itemTemplate); + m_scene.RezNewScript(userId, itemTemplate); m_chatEvent.WaitOne(60000); Assert.That(m_osChatMessageReceived, Is.Not.Null, "No chat message received in TestStartScript()"); Assert.That(m_osChatMessageReceived.Message, Is.EqualTo("Script running")); - - bool running; - TaskInventoryItem scriptItem = partWhereRezzed.Inventory.GetInventoryItem(itemName); - Assert.That( - SceneObjectPartInventory.TryGetScriptInstanceRunning(m_scene, scriptItem, out running), Is.True); - Assert.That(running, Is.True); } private void OnChatFromWorld(object sender, OSChatMessage oscm) diff --git a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs index 9f05666..f6cb7df 100644 --- a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs +++ b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs @@ -656,19 +656,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine if (m_Assemblies.ContainsKey(instance.AssetID)) { string assembly = m_Assemblies[instance.AssetID]; - - try - { - instance.SaveState(assembly); - } - catch (Exception e) - { - m_log.Error( - string.Format( - "[XEngine]: Failed final state save for script {0}.{1}, item UUID {2}, prim UUID {3} in {4}. Exception ", - instance.PrimName, instance.ScriptName, instance.ItemID, instance.ObjectID, World.Name) - , e); - } + instance.SaveState(assembly); } // Clear the event queue and abort the instance thread @@ -790,18 +778,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine assembly = m_Assemblies[i.AssetID]; - try - { - i.SaveState(assembly); - } - catch (Exception e) - { - m_log.Error( - string.Format( - "[XEngine]: Failed to save state of script {0}.{1}, item UUID {2}, prim UUID {3} in {4}. Exception ", - i.PrimName, i.ScriptName, i.ItemID, i.ObjectID, World.Name) - , e); - } + i.SaveState(assembly); } instances.Clear(); @@ -994,8 +971,6 @@ namespace OpenSim.Region.ScriptEngine.XEngine // This delay exists to stop mono problems where script compilation and startup would stop the sim // working properly for the session. System.Threading.Thread.Sleep(m_StartDelay); - - m_log.InfoFormat("[XEngine]: Performing initial script startup on {0}", m_Scene.Name); } object[] o; @@ -1011,13 +986,13 @@ namespace OpenSim.Region.ScriptEngine.XEngine if (m_InitialStartup) if (scriptsStarted % 50 == 0) m_log.InfoFormat( - "[XEngine]: Started {0} scripts in {1}", scriptsStarted, m_Scene.Name); + "[XEngine]: Started {0} scripts in {1}", scriptsStarted, m_Scene.RegionInfo.RegionName); } } if (m_InitialStartup) m_log.InfoFormat( - "[XEngine]: Completed starting {0} scripts on {1}", scriptsStarted, m_Scene.Name); + "[XEngine]: Completed starting {0} scripts on {1}", scriptsStarted, m_Scene.RegionInfo.RegionName); // NOTE: Despite having a lockless queue, this lock is required // to make sure there is never no compile thread while there @@ -1078,13 +1053,11 @@ namespace OpenSim.Region.ScriptEngine.XEngine return false; } - m_log.DebugFormat( - "[XEngine] Loading script {0}.{1}, item UUID {2}, prim UUID {3} @ {4}.{5}", - part.ParentGroup.RootPart.Name, item.Name, itemID, part.UUID, - part.ParentGroup.RootPart.AbsolutePosition, part.ParentGroup.Scene.RegionInfo.RegionName); - UUID assetID = item.AssetID; + //m_log.DebugFormat("[XEngine] Compiling script {0} ({1} on object {2})", + // item.Name, itemID.ToString(), part.ParentGroup.RootPart.Name); + ScenePresence presence = m_Scene.GetScenePresence(item.OwnerID); string assembly = ""; @@ -1262,10 +1235,10 @@ namespace OpenSim.Region.ScriptEngine.XEngine item.Name, startParam, postOnRez, stateSource, m_MaxScriptQueue); -// m_log.DebugFormat( -// "[XEngine] Loaded script {0}.{1}, script UUID {2}, prim UUID {3} @ {4}.{5}", -// part.ParentGroup.RootPart.Name, item.Name, assetID, part.UUID, -// part.ParentGroup.RootPart.AbsolutePosition, part.ParentGroup.Scene.RegionInfo.RegionName); + m_log.DebugFormat( + "[XEngine] Loaded script {0}.{1}, script UUID {2}, prim UUID {3} @ {4}.{5}", + part.ParentGroup.RootPart.Name, item.Name, assetID, part.UUID, + part.ParentGroup.RootPart.AbsolutePosition, part.ParentGroup.Scene.RegionInfo.RegionName); if (presence != null) { @@ -1581,9 +1554,9 @@ namespace OpenSim.Region.ScriptEngine.XEngine else if (p[i] is string) lsl_p[i] = new LSL_Types.LSLString((string)p[i]); else if (p[i] is Vector3) - lsl_p[i] = new LSL_Types.Vector3((Vector3)p[i]); + lsl_p[i] = new LSL_Types.Vector3(((Vector3)p[i]).X, ((Vector3)p[i]).Y, ((Vector3)p[i]).Z); else if (p[i] is Quaternion) - lsl_p[i] = new LSL_Types.Quaternion((Quaternion)p[i]); + lsl_p[i] = new LSL_Types.Quaternion(((Quaternion)p[i]).X, ((Quaternion)p[i]).Y, ((Quaternion)p[i]).Z, ((Quaternion)p[i]).W); else if (p[i] is float) lsl_p[i] = new LSL_Types.LSLFloat((float)p[i]); else @@ -1607,9 +1580,9 @@ namespace OpenSim.Region.ScriptEngine.XEngine else if (p[i] is string) lsl_p[i] = new LSL_Types.LSLString((string)p[i]); else if (p[i] is Vector3) - lsl_p[i] = new LSL_Types.Vector3((Vector3)p[i]); + lsl_p[i] = new LSL_Types.Vector3(((Vector3)p[i]).X, ((Vector3)p[i]).Y, ((Vector3)p[i]).Z); else if (p[i] is Quaternion) - lsl_p[i] = new LSL_Types.Quaternion((Quaternion)p[i]); + lsl_p[i] = new LSL_Types.Quaternion(((Quaternion)p[i]).X, ((Quaternion)p[i]).Y, ((Quaternion)p[i]).Z, ((Quaternion)p[i]).W); else if (p[i] is float) lsl_p[i] = new LSL_Types.LSLFloat((float)p[i]); else diff --git a/OpenSim/Region/UserStatistics/WebStatsModule.cs b/OpenSim/Region/UserStatistics/WebStatsModule.cs index 625eba4..c11ea02 100644 --- a/OpenSim/Region/UserStatistics/WebStatsModule.cs +++ b/OpenSim/Region/UserStatistics/WebStatsModule.cs @@ -61,7 +61,7 @@ namespace OpenSim.Region.UserStatistics /// /// User statistics sessions keyed by agent ID /// - private Dictionary m_sessions = new Dictionary(); + private Dictionary m_sessions = new Dictionary(); private List m_scenes = new List(); private Dictionary reports = new Dictionary(); @@ -319,18 +319,14 @@ namespace OpenSim.Region.UserStatistics private void OnMakeRootAgent(ScenePresence agent) { -// m_log.DebugFormat( -// "[WEB STATS MODULE]: Looking for session {0} for {1} in {2}", -// agent.ControllingClient.SessionId, agent.Name, agent.Scene.Name); - lock (m_sessions) { - UserSession uid; + UserSessionID uid; if (!m_sessions.ContainsKey(agent.UUID)) { UserSessionData usd = UserSessionUtil.newUserSessionData(); - uid = new UserSession(); + uid = new UserSessionID(); uid.name_f = agent.Firstname; uid.name_l = agent.Lastname; uid.session_data = usd; @@ -415,9 +411,9 @@ namespace OpenSim.Region.UserStatistics return String.Empty; } - private UserSession ParseViewerStats(string request, UUID agentID) + private UserSessionID ParseViewerStats(string request, UUID agentID) { - UserSession uid = new UserSession(); + UserSessionID uid = new UserSessionID(); UserSessionData usd; OSD message = OSDParser.DeserializeLLSDXml(request); OSDMap mmap; @@ -429,25 +425,22 @@ namespace OpenSim.Region.UserStatistics if (!m_sessions.ContainsKey(agentID)) { m_log.WarnFormat("[WEB STATS MODULE]: no session for stat disclosure for agent {0}", agentID); - return new UserSession(); + return new UserSessionID(); } - uid = m_sessions[agentID]; - -// m_log.DebugFormat("[WEB STATS MODULE]: Got session {0} for {1}", uid.session_id, agentID); } else { // parse through the beginning to locate the session if (message.Type != OSDType.Map) - return new UserSession(); + return new UserSessionID(); mmap = (OSDMap)message; { UUID sessionID = mmap["session_id"].AsUUID(); if (sessionID == UUID.Zero) - return new UserSession(); + return new UserSessionID(); // search through each session looking for the owner @@ -466,7 +459,7 @@ namespace OpenSim.Region.UserStatistics // can't find a session if (agentID == UUID.Zero) { - return new UserSession(); + return new UserSessionID(); } } } @@ -475,12 +468,12 @@ namespace OpenSim.Region.UserStatistics usd = uid.session_data; if (message.Type != OSDType.Map) - return new UserSession(); + return new UserSessionID(); mmap = (OSDMap)message; { if (mmap["agent"].Type != OSDType.Map) - return new UserSession(); + return new UserSessionID(); OSDMap agent_map = (OSDMap)mmap["agent"]; usd.agent_id = agentID; usd.name_f = uid.name_f; @@ -500,18 +493,17 @@ namespace OpenSim.Region.UserStatistics (float)agent_map["fps"].AsReal()); if (mmap["downloads"].Type != OSDType.Map) - return new UserSession(); + return new UserSessionID(); OSDMap downloads_map = (OSDMap)mmap["downloads"]; usd.d_object_kb = (float)downloads_map["object_kbytes"].AsReal(); usd.d_texture_kb = (float)downloads_map["texture_kbytes"].AsReal(); usd.d_world_kb = (float)downloads_map["workd_kbytes"].AsReal(); -// m_log.DebugFormat("[WEB STATS MODULE]: mmap[\"session_id\"] = [{0}]", mmap["session_id"].AsUUID()); usd.session_id = mmap["session_id"].AsUUID(); if (mmap["system"].Type != OSDType.Map) - return new UserSession(); + return new UserSessionID(); OSDMap system_map = (OSDMap)mmap["system"]; usd.s_cpu = system_map["cpu"].AsString(); @@ -520,13 +512,13 @@ namespace OpenSim.Region.UserStatistics usd.s_ram = system_map["ram"].AsInteger(); if (mmap["stats"].Type != OSDType.Map) - return new UserSession(); + return new UserSessionID(); OSDMap stats_map = (OSDMap)mmap["stats"]; { if (stats_map["failures"].Type != OSDType.Map) - return new UserSession(); + return new UserSessionID(); OSDMap stats_failures = (OSDMap)stats_map["failures"]; usd.f_dropped = stats_failures["dropped"].AsInteger(); usd.f_failed_resends = stats_failures["failed_resends"].AsInteger(); @@ -535,18 +527,18 @@ namespace OpenSim.Region.UserStatistics usd.f_send_packet = stats_failures["send_packet"].AsInteger(); if (stats_map["net"].Type != OSDType.Map) - return new UserSession(); + return new UserSessionID(); OSDMap stats_net = (OSDMap)stats_map["net"]; { if (stats_net["in"].Type != OSDType.Map) - return new UserSession(); + return new UserSessionID(); OSDMap net_in = (OSDMap)stats_net["in"]; usd.n_in_kb = (float)net_in["kbytes"].AsReal(); usd.n_in_pk = net_in["packets"].AsInteger(); if (stats_net["out"].Type != OSDType.Map) - return new UserSession(); + return new UserSessionID(); OSDMap net_out = (OSDMap)stats_net["out"]; usd.n_out_kb = (float)net_out["kbytes"].AsReal(); @@ -557,18 +549,11 @@ namespace OpenSim.Region.UserStatistics uid.session_data = usd; m_sessions[agentID] = uid; - -// m_log.DebugFormat( -// "[WEB STATS MODULE]: Parse data for {0} {1}, session {2}", uid.name_f, uid.name_l, uid.session_id); - return uid; } - private void UpdateUserStats(UserSession uid, SqliteConnection db) + private void UpdateUserStats(UserSessionID uid, SqliteConnection db) { -// m_log.DebugFormat( -// "[WEB STATS MODULE]: Updating user stats for {0} {1}, session {2}", uid.name_f, uid.name_l, uid.session_id); - if (uid.session_id == UUID.Zero) return; @@ -755,6 +740,7 @@ VALUES s.min_ping = ArrayMin_f(__ping); s.max_ping = ArrayMax_f(__ping); s.mode_ping = ArrayMode_f(__ping); + } #region Statistics @@ -999,7 +985,7 @@ VALUES } #region structs - public class UserSession + public struct UserSessionID { public UUID session_id; public UUID region_id; -- cgit v1.1 From 5e0294815f7e3ec83b7e568e1468948ac0ff7331 Mon Sep 17 00:00:00 2001 From: teravus Date: Sat, 17 Nov 2012 03:47:09 -0500 Subject: * Plumbing and basic setting of the GetMesh Cap Throttler. * Last step is to flip the throttle distribution. --- .../ClientStack/Linden/Caps/GetMeshModule.cs | 90 +++++++++++++++++----- .../Region/ClientStack/Linden/UDP/LLClientView.cs | 12 +++ .../Region/ClientStack/Linden/UDP/LLUDPClient.cs | 4 + .../Server/IRCClientView.cs | 5 ++ .../Region/OptionalModules/World/NPC/NPCAvatar.cs | 6 ++ 5 files changed, 99 insertions(+), 18 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/ClientStack/Linden/Caps/GetMeshModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/GetMeshModule.cs index 8deff81..96b48ad 100644 --- a/OpenSim/Region/ClientStack/Linden/Caps/GetMeshModule.cs +++ b/OpenSim/Region/ClientStack/Linden/Caps/GetMeshModule.cs @@ -60,6 +60,7 @@ namespace OpenSim.Region.ClientStack.Linden private IAssetService m_AssetService; private bool m_Enabled = true; private string m_URL; + struct aPollRequest { public PollServiceMeshEventArgs thepoll; @@ -71,6 +72,7 @@ namespace OpenSim.Region.ClientStack.Linden { public Hashtable response; public int bytes; + public int lod; } @@ -112,6 +114,7 @@ namespace OpenSim.Region.ClientStack.Linden // Cap doesn't exist if (m_URL != string.Empty) m_Enabled = true; + } public void AddRegion(Scene pScene) @@ -192,7 +195,7 @@ namespace OpenSim.Region.ClientStack.Linden PollServiceMeshEventArgs args; if (m_pollservices.TryGetValue(user, out args)) { - args.UpdateThrottle(imagethrottle); + args.UpdateThrottle(imagethrottle, p); } } @@ -242,11 +245,12 @@ namespace OpenSim.Region.ClientStack.Linden new Dictionary(); private Scene m_scene; - private CapsDataThrottler m_throttler = new CapsDataThrottler(100000, 1400000, 10000); + private MeshCapsDataThrottler m_throttler; public PollServiceMeshEventArgs(UUID pId, Scene scene) : base(null, null, null, null, pId, int.MaxValue) { m_scene = scene; + m_throttler = new MeshCapsDataThrottler(100000, 1400000, 10000, scene); // x is request id, y is userid HasEvents = (x, y) => { @@ -268,6 +272,7 @@ namespace OpenSim.Region.ClientStack.Linden } finally { + m_throttler.ProcessTime(); responses.Remove(x); } } @@ -323,7 +328,7 @@ namespace OpenSim.Region.ClientStack.Linden response["reusecontext"] = false; lock (responses) - responses[requestID] = new aPollResponse() { bytes = 0, response = response }; + responses[requestID] = new aPollResponse() { bytes = 0, response = response, lod = 0 }; return; } @@ -334,6 +339,7 @@ namespace OpenSim.Region.ClientStack.Linden responses[requestID] = new aPollResponse() { bytes = (int)response["int_bytes"], + lod = (int)response["int_lod"], response = response }; @@ -341,9 +347,9 @@ namespace OpenSim.Region.ClientStack.Linden m_throttler.ProcessTime(); } - internal void UpdateThrottle(int pimagethrottle) + internal void UpdateThrottle(int pimagethrottle, ScenePresence p) { - m_throttler.ThrottleBytes = pimagethrottle; + m_throttler.UpdateThrottle(pimagethrottle, p); } } @@ -398,18 +404,31 @@ namespace OpenSim.Region.ClientStack.Linden } } - internal sealed class CapsDataThrottler + internal sealed class MeshCapsDataThrottler { private volatile int currenttime = 0; private volatile int lastTimeElapsed = 0; private volatile int BytesSent = 0; - private int oversizedImages = 0; - public CapsDataThrottler(int pBytes, int max, int min) + private int Lod3 = 0; + private int Lod2 = 0; + private int Lod1 = 0; + private int UserSetThrottle = 0; + private int UDPSetThrottle = 0; + private int CapSetThrottle = 0; + private float CapThrottleDistributon = 0.30f; + private readonly Scene m_scene; + private ThrottleOutPacketType Throttle; + + public MeshCapsDataThrottler(int pBytes, int max, int min, Scene pScene) { ThrottleBytes = pBytes; lastTimeElapsed = Util.EnvironmentTickCount(); + Throttle = ThrottleOutPacketType.Task; + m_scene = pScene; } + + public bool hasEvents(UUID key, Dictionary responses) { PassTime(); @@ -427,17 +446,23 @@ namespace OpenSim.Region.ClientStack.Linden if (BytesSent + response.bytes <= ThrottleBytes) { BytesSent += response.bytes; - //TimeBasedAction timeBasedAction = new TimeBasedAction { byteRemoval = response.bytes, requestId = key, timeMS = currenttime + 1000, unlockyn = false }; - //m_actions.Add(timeBasedAction); + + return true; + } + // Lod3 Over + else if (response.bytes > ThrottleBytes && Lod3 <= (((ThrottleBytes * .30f) % 50000) + 1)) + { + Interlocked.Increment(ref Lod3); + BytesSent += response.bytes; + return true; } - // Big textures - else if (response.bytes > ThrottleBytes && oversizedImages <= ((ThrottleBytes % 50000) + 1)) + // Lod2 Over + else if (response.bytes > ThrottleBytes && Lod2 <= (((ThrottleBytes * .30f) % 10000) + 1)) { - Interlocked.Increment(ref oversizedImages); + Interlocked.Increment(ref Lod2); BytesSent += response.bytes; - //TimeBasedAction timeBasedAction = new TimeBasedAction { byteRemoval = response.bytes, requestId = key, timeMS = currenttime + (((response.bytes % ThrottleBytes)+1)*1000) , unlockyn = false }; - //m_actions.Add(timeBasedAction); + return true; } else @@ -448,6 +473,11 @@ namespace OpenSim.Region.ClientStack.Linden return haskey; } + public void SubtractBytes(int bytes,int lod) + { + BytesSent -= bytes; + } + public void ProcessTime() { PassTime(); @@ -459,18 +489,42 @@ namespace OpenSim.Region.ClientStack.Linden currenttime = Util.EnvironmentTickCount(); int timeElapsed = Util.EnvironmentTickCountSubtract(currenttime, lastTimeElapsed); //processTimeBasedActions(responses); - if (Util.EnvironmentTickCountSubtract(currenttime, timeElapsed) >= 1000) + if (currenttime - timeElapsed >= 1000) { lastTimeElapsed = Util.EnvironmentTickCount(); BytesSent -= ThrottleBytes; if (BytesSent < 0) BytesSent = 0; if (BytesSent < ThrottleBytes) { - oversizedImages = 0; + Lod3 = 0; + Lod2 = 0; + Lod1 = 0; } } } - public int ThrottleBytes; + private void AlterThrottle(int setting, ScenePresence p) + { + p.ControllingClient.SetAgentThrottleSilent((int)Throttle,setting); + } + + public int ThrottleBytes + { + get { return CapSetThrottle; } + set { CapSetThrottle = value; } + } + + internal void UpdateThrottle(int pimagethrottle, ScenePresence p) + { + // Client set throttle ! + UserSetThrottle = pimagethrottle; + CapSetThrottle = (int)(pimagethrottle*CapThrottleDistributon); + UDPSetThrottle = (int) (pimagethrottle*(100 - CapThrottleDistributon)); + if (CapSetThrottle < 4068) + CapSetThrottle = 4068; // at least two discovery mesh + p.ControllingClient.SetAgentThrottleSilent((int) Throttle, UDPSetThrottle); + ProcessTime(); + + } } } diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index ae9ed7f..533a1a8 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -11884,6 +11884,18 @@ namespace OpenSim.Region.ClientStack.LindenUDP } /// + /// Sets the throttles from values supplied by the client + /// + /// + public void SetAgentThrottleSilent(int throttle, int setting) + { + m_udpClient.ForceThrottleSetting(throttle,setting); + //m_udpClient.SetThrottles(throttles); + + } + + + /// /// Get the current throttles for this client as a packed byte array /// /// Unused diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs index c472176..f675377 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs @@ -682,6 +682,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP if (m_nextOnQueueEmpty == 0) m_nextOnQueueEmpty = 1; } + internal void ForceThrottleSetting(int throttle, int setting) + { + m_throttleCategories[throttle].RequestedDripRate = Math.Max(setting, LLUDPServer.MTU); ; + } /// /// Converts a integer to a diff --git a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs index 28b8293..563fd12 100644 --- a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs +++ b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs @@ -1428,6 +1428,11 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server } + public void SetAgentThrottleSilent(int throttle, int setting) + { + + + } public byte[] GetThrottlesPacked(float multiplier) { return new byte[0]; diff --git a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs index 6c8e2fc..ef53c48 100644 --- a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs +++ b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs @@ -597,6 +597,12 @@ namespace OpenSim.Region.OptionalModules.World.NPC public virtual void SetChildAgentThrottle(byte[] throttle) { } + + public void SetAgentThrottleSilent(int throttle, int setting) + { + + + } public byte[] GetThrottlesPacked(float multiplier) { return new byte[0]; -- cgit v1.1