diff --git a/OpenSim/Framework/Util.cs b/OpenSim/Framework/Util.cs index f520a014f8..0852b49a34 100644 --- a/OpenSim/Framework/Util.cs +++ b/OpenSim/Framework/Util.cs @@ -2148,7 +2148,7 @@ namespace OpenSim.Framework /// the secret part public static bool ParseUniversalUserIdentifier(string value, out UUID uuid, out string url, out string firstname, out string lastname, out string secret) { - uuid = UUID.Zero; url = string.Empty; firstname = "Unknown"; lastname = "User"; secret = string.Empty; + uuid = UUID.Zero; url = string.Empty; firstname = "Unknown"; lastname = "UserUPUUI"; secret = string.Empty; string[] parts = value.Split(';'); if (parts.Length >= 1) diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs index 8056030843..4613344325 100644 --- a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs @@ -371,7 +371,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends foreach (string fid in outstanding) { UUID fromAgentID; - string firstname = "Unknown", lastname = "User"; + string firstname = "Unknown", lastname = "UserFMSFOIN"; if (!GetAgentInfo(client.Scene.RegionInfo.ScopeID, fid, out fromAgentID, out firstname, out lastname)) { m_log.DebugFormat("[FRIENDS MODULE]: skipping malformed friend {0}", fid); @@ -397,7 +397,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends protected virtual bool GetAgentInfo(UUID scopeID, string fid, out UUID agentID, out string first, out string last) { - first = "Unknown"; last = "User"; + first = "Unknown"; last = "UserFMGAI"; if (!UUID.TryParse(fid, out agentID)) return false; diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs b/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs index bf5c0bb46b..b3e3aa2e97 100644 --- a/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs @@ -293,7 +293,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends protected override bool GetAgentInfo(UUID scopeID, string fid, out UUID agentID, out string first, out string last) { - first = "Unknown"; last = "User"; + first = "Unknown"; last = "UserHGGAI"; if (base.GetAgentInfo(scopeID, fid, out agentID, out first, out last)) return true; diff --git a/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs b/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs index 6847e572fb..a720d7bad6 100644 --- a/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs +++ b/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs @@ -157,13 +157,16 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement } else { - string[] names = GetUserNames(uuid); + string[] names; + bool foundRealName = TryGetUserNames(uuid, out names); + if (names.Length == 2) { - //m_log.DebugFormat("[XXX] HandleUUIDNameRequest {0} is {1} {2}", uuid, names[0], names[1]); + if (!foundRealName) + m_log.DebugFormat("[USER MANAGEMENT MODULE]: Sending {0} {1} for {2} to {3} since no bound name found", names[0], names[1], uuid, remote_client.Name); + remote_client.SendNameReply(uuid, names[0], names[1]); } - } } @@ -246,10 +249,15 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement } // search the local cache - foreach (UserData data in m_UserCache.Values) - if (users.Find(delegate(UserData d) { return d.Id == data.Id; }) == null && - (data.FirstName.ToLower().StartsWith(query.ToLower()) || data.LastName.ToLower().StartsWith(query.ToLower()))) - users.Add(data); + lock (m_UserCache) + { + foreach (UserData data in m_UserCache.Values) + { + if (users.Find(delegate(UserData d) { return d.Id == data.Id; }) == null && + (data.FirstName.ToLower().StartsWith(query.ToLower()) || data.LastName.ToLower().StartsWith(query.ToLower()))) + users.Add(data); + } + } AddAdditionalUsers(query, users); @@ -272,17 +280,24 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement } } - private string[] GetUserNames(UUID uuid) + /// + /// Try to get the names bound to the given uuid. + /// + /// True if the name was found, false if not. + /// + /// The array of names if found. If not found, then names[0] = "Unknown" and names[1] = "User" + private bool TryGetUserNames(UUID uuid, out string[] names) { - string[] returnstring = new string[2]; + names = new string[2]; lock (m_UserCache) { if (m_UserCache.ContainsKey(uuid)) { - returnstring[0] = m_UserCache[uuid].FirstName; - returnstring[1] = m_UserCache[uuid].LastName; - return returnstring; + names[0] = m_UserCache[uuid].FirstName; + names[1] = m_UserCache[uuid].LastName; + + return true; } } @@ -290,8 +305,8 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement if (account != null) { - returnstring[0] = account.FirstName; - returnstring[1] = account.LastName; + names[0] = account.FirstName; + names[1] = account.LastName; UserData user = new UserData(); user.FirstName = account.FirstName; @@ -299,14 +314,16 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement lock (m_UserCache) m_UserCache[uuid] = user; + + return true; } else { - returnstring[0] = "Unknown"; - returnstring[1] = "User"; - } + names[0] = "Unknown"; + names[1] = "UserUMMTGUN"; - return returnstring; + return false; + } } #region IUserManagement @@ -342,15 +359,17 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement public string GetUserName(UUID uuid) { - string[] names = GetUserNames(uuid); + string[] names; + TryGetUserNames(uuid, out names); + if (names.Length == 2) { string firstname = names[0]; string lastname = names[1]; return firstname + " " + lastname; - } + return "(hippos)"; } @@ -466,12 +485,13 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement //ignore updates without creator data return; } + //try update unknown users //and creator's home URL's if ((oldUser.FirstName == "Unknown" && !creatorData.Contains ("Unknown")) || (oldUser.HomeURL != null && !creatorData.StartsWith (oldUser.HomeURL))) { m_UserCache.Remove (id); -// m_log.DebugFormat("[USER MANAGEMENT MODULE]: Re-adding user with id {0}, creatorData [{1}] and old HomeURL {2}", id, creatorData,oldUser.HomeURL); + m_log.DebugFormat("[USER MANAGEMENT MODULE]: Re-adding user with id {0}, creatorData [{1}] and old HomeURL {2}", id, creatorData, oldUser.HomeURL); } else { @@ -516,7 +536,7 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement else { user.FirstName = "Unknown"; - user.LastName = "User"; + user.LastName = "UserUMMAU"; } AddUserInternal (user); @@ -547,6 +567,13 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement protected void RegisterConsoleCmds() { + MainConsole.Instance.Commands.AddCommand("Users", true, + "show name", + "show name ", + "Show the bindings between a single user UUID and a user name", + String.Empty, + HandleShowUser); + MainConsole.Instance.Commands.AddCommand("Users", true, "show names", "show names", @@ -555,26 +582,54 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement HandleShowUsers); } - private void HandleShowUsers(string module, string[] cmd) + private void HandleShowUser(string module, string[] cmd) { - lock (m_UserCache) + if (cmd.Length < 3) { - if (m_UserCache.Count == 0) - { - MainConsole.Instance.Output("No users found"); - return; - } - - MainConsole.Instance.Output("UUID User Name"); - 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.OutputFormat("Usage: show name "); return; } + + UUID userId; + if (!ConsoleUtil.TryParseConsoleUuid(MainConsole.Instance, cmd[2], out userId)) + return; + + string[] names; + + UserData ud; + + lock (m_UserCache) + { + if (!m_UserCache.TryGetValue(userId, out ud)) + { + MainConsole.Instance.OutputFormat("No name known for user with id {0}", userId); + return; + } + } + + ConsoleDisplayTable cdt = new ConsoleDisplayTable(); + cdt.AddColumn("UUID", 36); + cdt.AddColumn("Name", 30); + cdt.AddColumn("HomeURL", 40); + cdt.AddRow(userId, string.Format("{0} {1}", ud.FirstName, ud.LastName), ud.HomeURL); + + MainConsole.Instance.Output(cdt.ToString()); + } + + private void HandleShowUsers(string module, string[] cmd) + { + ConsoleDisplayTable cdt = new ConsoleDisplayTable(); + cdt.AddColumn("UUID", 36); + cdt.AddColumn("Name", 30); + cdt.AddColumn("HomeURL", 40); + + lock (m_UserCache) + { + foreach (KeyValuePair kvp in m_UserCache) + cdt.AddRow(kvp.Key, string.Format("{0} {1}", kvp.Value.FirstName, kvp.Value.LastName), kvp.Value.HomeURL); + } + + MainConsole.Instance.Output(cdt.ToString()); } } } \ 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 883045a01a..d093224b3c 100644 --- a/OpenSim/Region/CoreModules/World/Sound/SoundModule.cs +++ b/OpenSim/Region/CoreModules/World/Sound/SoundModule.cs @@ -369,6 +369,15 @@ namespace OpenSim.Region.CoreModules.World.Sound }); } + public void SetSoundQueueing(UUID objectID, bool shouldQueue) + { + SceneObjectPart part; + if (!m_scene.TryGetSceneObjectPart(objectID, out part)) + return; + + part.SoundQueueing = shouldQueue; + } + #endregion } } diff --git a/OpenSim/Region/Framework/Interfaces/ISoundModule.cs b/OpenSim/Region/Framework/Interfaces/ISoundModule.cs index 68af4923d5..8372ddddf8 100644 --- a/OpenSim/Region/Framework/Interfaces/ISoundModule.cs +++ b/OpenSim/Region/Framework/Interfaces/ISoundModule.cs @@ -104,7 +104,6 @@ namespace OpenSim.Region.Framework.Interfaces /// Sound asset ID /// Sound volume /// Triggered or not. - /// /// Sound radius /// Play using sound master /// Play as sound master @@ -123,5 +122,12 @@ namespace OpenSim.Region.Framework.Interfaces /// AABB top north-east corner void TriggerSoundLimited(UUID objectID, UUID sound, double volume, Vector3 min, Vector3 max); + + /// + /// Set whether sounds on the given prim should be queued. + /// + /// + /// + void SetSoundQueueing(UUID objectID, bool shouldQueue); } } \ No newline at end of file diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index 9e644aa2db..2b5a6f9766 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -231,6 +231,13 @@ namespace OpenSim.Region.Framework.Scenes public double SoundRadius; + /// + /// Should sounds played from this prim be queued? + /// + /// + /// This should only be changed by sound modules. It is up to sound modules as to how they interpret this setting. + /// + public bool SoundQueueing { get; set; } public uint TimeStampFull; diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSAPIUnman.cs b/OpenSim/Region/Physics/BulletSPlugin/BSAPIUnman.cs index 231f0f8197..12a0c1717c 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSAPIUnman.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSAPIUnman.cs @@ -251,6 +251,16 @@ public override BulletShape CreateMeshShape(BulletWorld world, BSPhysicsShapeType.SHAPE_MESH); } +public override BulletShape CreateGImpactShape(BulletWorld world, + int indicesCount, int[] indices, + int verticesCount, float[] vertices) +{ + BulletWorldUnman worldu = world as BulletWorldUnman; + return new BulletShapeUnman( + BSAPICPP.CreateGImpactShape2(worldu.ptr, indicesCount, indices, verticesCount, vertices), + BSPhysicsShapeType.SHAPE_GIMPACT); +} + public override BulletShape CreateHullShape(BulletWorld world, int hullCount, float[] hulls) { BulletWorldUnman worldu = world as BulletWorldUnman; @@ -1425,6 +1435,11 @@ 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 CreateGImpactShape2(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); diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSAPIXNA.cs b/OpenSim/Region/Physics/BulletSPlugin/BSAPIXNA.cs index 59780ae8ee..6db5f5e77d 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSAPIXNA.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSAPIXNA.cs @@ -1475,7 +1475,7 @@ private sealed class BulletConstraintXNA : BulletConstraint ret = BSPhysicsShapeType.SHAPE_UNKNOWN; break; case BroadphaseNativeTypes.CONVEX_TRIANGLEMESH_SHAPE_PROXYTYPE: - ret = BSPhysicsShapeType.SHAPE_MESH; + ret = BSPhysicsShapeType.SHAPE_CONVEXHULL; break; case BroadphaseNativeTypes.CONVEX_HULL_SHAPE_PROXYTYPE: ret = BSPhysicsShapeType.SHAPE_HULL; @@ -1503,7 +1503,7 @@ private sealed class BulletConstraintXNA : BulletConstraint ret = BSPhysicsShapeType.SHAPE_CONE; break; case BroadphaseNativeTypes.CONVEX_SHAPE_PROXYTYPE: - ret = BSPhysicsShapeType.SHAPE_UNKNOWN; + ret = BSPhysicsShapeType.SHAPE_CONVEXHULL; break; case BroadphaseNativeTypes.CYLINDER_SHAPE_PROXYTYPE: ret = BSPhysicsShapeType.SHAPE_CYLINDER; @@ -1547,7 +1547,7 @@ private sealed class BulletConstraintXNA : BulletConstraint break; ///Used for GIMPACT Trimesh integration case BroadphaseNativeTypes.GIMPACT_SHAPE_PROXYTYPE: - ret = BSPhysicsShapeType.SHAPE_MESH; + ret = BSPhysicsShapeType.SHAPE_GIMPACT; break; ///Multimaterial mesh case BroadphaseNativeTypes.MULTIMATERIAL_TRIANGLE_MESH_PROXYTYPE: @@ -1820,6 +1820,11 @@ private sealed class BulletConstraintXNA : BulletConstraint return new BulletShapeXNA(meshShape, BSPhysicsShapeType.SHAPE_MESH); } + public override BulletShape CreateGImpactShape(BulletWorld pWorld, int pIndicesCount, int[] indices, int pVerticesCount, float[] verticesAsFloats) + { + // TODO: + return null; + } public static void DumpRaw(ObjectArrayindices, ObjectArray vertices, int pIndicesCount,int pVerticesCount ) { diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSApiTemplate.cs b/OpenSim/Region/Physics/BulletSPlugin/BSApiTemplate.cs index 3378c932d3..6cdc112460 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSApiTemplate.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSApiTemplate.cs @@ -71,6 +71,7 @@ public enum BSPhysicsShapeType SHAPE_HEIGHTMAP = 23, SHAPE_AVATAR = 24, SHAPE_CONVEXHULL= 25, + SHAPE_GIMPACT = 26, }; // The native shapes have predefined shape hash keys @@ -321,6 +322,10 @@ public abstract BulletShape CreateMeshShape(BulletWorld world, int indicesCount, int[] indices, int verticesCount, float[] vertices ); +public abstract BulletShape CreateGImpactShape(BulletWorld world, + int indicesCount, int[] indices, + int verticesCount, float[] vertices ); + public abstract BulletShape CreateHullShape(BulletWorld world, int hullCount, float[] hulls); diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs index ff5b6ab820..48f842e91e 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs @@ -483,8 +483,15 @@ public sealed class BSCharacter : BSPhysObject { // Bullet assumes we know what we are doing when forcing orientation // so it lets us go against all the rules and just compensates for them later. - // This keeps us from flipping the capsule over which the veiwer does not understand. - ForceOrientation = new OMV.Quaternion(0, 0, _orientation.Z,0); + // This forces rotation to be only around the Z axis and doesn't change any of the other axis. + // This keeps us from flipping the capsule over which the veiwer does not understand. + float oRoll, oPitch, oYaw; + _orientation.GetEulerAngles(out oRoll, out oPitch, out oYaw); + OMV.Quaternion trimmedOrientation = OMV.Quaternion.CreateFromEulers(0f, 0f, oYaw); + // DetailLog("{0},BSCharacter.setOrientation,taint,val={1},valDir={2},conv={3},convDir={4}", + // LocalID, _orientation, OMV.Vector3.UnitX * _orientation, + // trimmedOrientation, OMV.Vector3.UnitX * trimmedOrientation); + ForceOrientation = trimmedOrientation; }); } } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSParam.cs b/OpenSim/Region/Physics/BulletSPlugin/BSParam.cs index d33292fe50..5cff66828c 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSParam.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSParam.cs @@ -89,6 +89,8 @@ public static class BSParam public static bool ShouldRemoveZeroWidthTriangles { get; private set; } public static bool ShouldUseBulletHACD { get; set; } public static bool ShouldUseSingleConvexHullForPrims { get; set; } + public static bool ShouldUseGImpactShapeForPrims { get; set; } + public static bool ShouldUseAssetHulls { get; set; } public static float TerrainImplementation { get; set; } public static int TerrainMeshMagnification { get; private set; } @@ -369,6 +371,10 @@ public static class BSParam false ), new ParameterDefn("ShouldUseSingleConvexHullForPrims", "If true, use a single convex hull shape for physical prims", true ), + new ParameterDefn("ShouldUseGImpactShapeForPrims", "If true, use a GImpact shape for prims with cuts and twists", + false ), + new ParameterDefn("UseAssetHulls", "If true, use hull if specified in the mesh asset info", + false ), new ParameterDefn("CrossingFailuresBeforeOutOfBounds", "How forgiving we are about getting into adjactent regions", 5 ), diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs index 3f407ce71a..39f5b0a93b 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs @@ -268,6 +268,12 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters // Do any replacements in the parameters m_physicsLoggingPrefix = m_physicsLoggingPrefix.Replace("%REGIONNAME%", RegionName); } + else + { + BulletEngineName = "BulletUnmanaged"; + m_physicsLoggingEnabled = false; + VehicleLoggingEnabled = false; + } // The material characteristics. BSMaterials.InitializeFromDefaults(Params); @@ -322,6 +328,8 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters BSParam.ShouldUseBulletHACD = false; m_log.InfoFormat("{0} Disabling ShouldUseSingleConvexHullForPrims", LogHeader); BSParam.ShouldUseSingleConvexHullForPrims = false; + m_log.InfoFormat("{0} Disabling ShouldUseGImpactShapeForPrims", LogHeader); + BSParam.ShouldUseGImpactShapeForPrims = false; m_log.InfoFormat("{0} Setting terrain implimentation to Heightmap", LogHeader); BSParam.TerrainImplementation = (float)BSTerrainPhys.TerrainImplementation.Heightmap; break; diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs index 64aaa1503d..32bbc8f5c3 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs @@ -230,6 +230,7 @@ public sealed class BSShapeCollection : IDisposable BSShape potentialHull = null; PrimitiveBaseShape pbs = prim.BaseShape; + // Use a simple, one section convex shape for prims that are probably convex (no cuts or twists) if (BSParam.ShouldUseSingleConvexHullForPrims && pbs != null && !pbs.SculptEntry @@ -238,7 +239,17 @@ public sealed class BSShapeCollection : IDisposable { potentialHull = BSShapeConvexHull.GetReference(m_physicsScene, false /* forceRebuild */, prim); } - else + // Use the GImpact shape if it is a prim that has some concaveness + if (potentialHull == null + && BSParam.ShouldUseGImpactShapeForPrims + && pbs != null + && !pbs.SculptEntry + ) + { + potentialHull = BSShapeGImpact.GetReference(m_physicsScene, false /* forceRebuild */, prim); + } + // If not any of the simple cases, just make a hull + if (potentialHull == null) { potentialHull = BSShapeHull.GetReference(m_physicsScene, false /*forceRebuild*/, prim); } @@ -261,7 +272,7 @@ public sealed class BSShapeCollection : IDisposable } else { - // Update prim.BSShape to reference a mesh of this shape. + // Non-physical objects should be just meshes. BSShape potentialMesh = BSShapeMesh.GetReference(m_physicsScene, false /*forceRebuild*/, prim); // If the current shape is not what is on the prim at the moment, time to change. if (!prim.PhysShape.HasPhysicalShape diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapes.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapes.cs index 6b09468c96..fca4258d0f 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSShapes.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapes.cs @@ -31,6 +31,7 @@ using System.Text; using OpenSim.Framework; using OpenSim.Region.Physics.Manager; +using OpenSim.Region.Physics.Meshing; using OpenSim.Region.Physics.ConvexDecompositionDotNet; using OMV = OpenMetaverse; @@ -422,8 +423,21 @@ public class BSShapeMesh : BSShape outMesh = foundDesc; return ret; } + + public delegate BulletShape CreateShapeCall(BulletWorld world, int indicesCount, int[] indices, int verticesCount, float[] vertices ); private BulletShape CreatePhysicalMesh(BSScene physicsScene, BSPhysObject prim, System.UInt64 newMeshKey, PrimitiveBaseShape pbs, OMV.Vector3 size, float lod) + { + return BSShapeMesh.CreatePhysicalMeshShape(physicsScene, prim, newMeshKey, pbs, size, lod, + (w, iC, i, vC, v) => physicsScene.PE.CreateMeshShape(w, iC, i, vC, v) ); + } + + // Code that uses the mesher to create the index/vertices info for a trimesh shape. + // This is used by the passed 'makeShape' call to create the Bullet mesh shape. + // The actual build call is passed so this logic can be used by several of the shapes that use a + // simple mesh as their base shape. + public static BulletShape CreatePhysicalMeshShape(BSScene physicsScene, BSPhysObject prim, System.UInt64 newMeshKey, + PrimitiveBaseShape pbs, OMV.Vector3 size, float lod, CreateShapeCall makeShape) { BulletShape newShape = new BulletShape(); @@ -484,8 +498,7 @@ public class BSShapeMesh : BSShape if (realIndicesIndex != 0) { - newShape = physicsScene.PE.CreateMeshShape(physicsScene.World, - realIndicesIndex, indices, verticesAsFloats.Length / 3, verticesAsFloats); + newShape = makeShape(physicsScene.World, realIndicesIndex, indices, verticesAsFloats.Length / 3, verticesAsFloats); } else { @@ -563,9 +576,56 @@ public class BSShapeHull : BSShape PrimitiveBaseShape pbs, OMV.Vector3 size, float lod) { BulletShape newShape = new BulletShape(); - IntPtr hullPtr = IntPtr.Zero; + newShape.shapeKey = newHullKey; - if (BSParam.ShouldUseBulletHACD) + // Pass true for physicalness as this prevents the creation of bounding box which is not needed + IMesh meshData = physicsScene.mesher.CreateMesh(prim.PhysObjectName, pbs, size, lod, true /* isPhysical */, false /* shouldCache */, false, false); + + // If there is hull data in the mesh asset, build the hull from that + if (meshData != null && BSParam.ShouldUseAssetHulls) + { + Meshmerizer realMesher = physicsScene.mesher as Meshmerizer; + if (realMesher != null) + { + List> allHulls = realMesher.GetConvexHulls(size); + if (allHulls != null) + { + int hullCount = allHulls.Count; + int totalVertices = 1; // include one for the count of the hulls + // Using the structure described for HACD hulls, create the memory sturcture + // to pass the hull data to the creater. + foreach (List hullVerts in allHulls) + { + totalVertices += 4; // add four for the vertex count and centroid + totalVertices += hullVerts.Count * 3; // one vertex is three dimensions + } + float[] convHulls = new float[totalVertices]; + + convHulls[0] = (float)hullCount; + int jj = 1; + foreach (List hullVerts in allHulls) + { + convHulls[jj + 0] = hullVerts.Count; + convHulls[jj + 1] = 0f; // centroid x,y,z + convHulls[jj + 2] = 0f; + convHulls[jj + 3] = 0f; + jj += 4; + foreach (OMV.Vector3 oneVert in hullVerts) + { + convHulls[jj + 0] = oneVert.X; + convHulls[jj + 1] = oneVert.Y; + convHulls[jj + 2] = oneVert.Z; + jj += 3; + } + } + + // create the hull data structure in Bullet + newShape = physicsScene.PE.CreateHullShape(physicsScene.World, hullCount, convHulls); + } + } + } + // If no hull specified in the asset and we should use Bullet's HACD approximation... + if (!newShape.HasPhysicalShape && BSParam.ShouldUseBulletHACD) { // Build the hull shape from an existing mesh shape. // The mesh should have already been created in Bullet. @@ -594,11 +654,10 @@ public class BSShapeHull : BSShape } physicsScene.DetailLog("{0},BSShapeHull.CreatePhysicalHull,shouldUseBulletHACD,exit,hasBody={1}", prim.LocalID, newShape.HasPhysicalShape); } + // If no hull specified, use our HACD hull approximation. if (!newShape.HasPhysicalShape) { // Build a new hull in the physical world using the C# HACD algorigthm. - // Pass true for physicalness as this prevents the creation of bounding box which is not needed - IMesh meshData = physicsScene.mesher.CreateMesh(prim.PhysObjectName, pbs, size, lod, true /* isPhysical */, false /* shouldCache */, false, false); if (meshData != null) { if (prim.PrimAssetState == BSPhysObject.PrimAssetCondition.Fetched) @@ -805,6 +864,7 @@ public class BSShapeCompound : BSShape // Called at taint-time. private void DereferenceAnonCollisionShape(BSScene physicsScene, BulletShape pShape) { + // TODO: figure a better way to go through all the shape types and find a possible instance. BSShapeMesh meshDesc; if (BSShapeMesh.TryGetMeshByPtr(pShape, out meshDesc)) { @@ -826,17 +886,25 @@ public class BSShapeCompound : BSShape } else { - if (physicsScene.PE.IsCompound(pShape)) + BSShapeGImpact gImpactDesc; + if (BSShapeGImpact.TryGetGImpactByPtr(pShape, out gImpactDesc)) { - BSShapeCompound recursiveCompound = new BSShapeCompound(pShape); - recursiveCompound.Dereference(physicsScene); + gImpactDesc.Dereference(physicsScene); } else { - if (physicsScene.PE.IsNativeShape(pShape)) + if (physicsScene.PE.IsCompound(pShape)) { - BSShapeNative nativeShape = new BSShapeNative(pShape); - nativeShape.Dereference(physicsScene); + BSShapeCompound recursiveCompound = new BSShapeCompound(pShape); + recursiveCompound.Dereference(physicsScene); + } + else + { + if (physicsScene.PE.IsNativeShape(pShape)) + { + BSShapeNative nativeShape = new BSShapeNative(pShape); + nativeShape.Dereference(physicsScene); + } } } } @@ -859,7 +927,7 @@ public class BSShapeConvexHull : BSShape float lod; System.UInt64 newMeshKey = BSShape.ComputeShapeKey(prim.Size, prim.BaseShape, out lod); - physicsScene.DetailLog("{0},BSShapeMesh,getReference,newKey={1},size={2},lod={3}", + physicsScene.DetailLog("{0},BSShapeConvexHull,getReference,newKey={1},size={2},lod={3}", prim.LocalID, newMeshKey.ToString("X"), prim.Size, lod); BSShapeConvexHull retConvexHull = null; @@ -939,6 +1007,97 @@ public class BSShapeConvexHull : BSShape return ret; } } +// ============================================================================================================ +public class BSShapeGImpact : BSShape +{ + private static string LogHeader = "[BULLETSIM SHAPE GIMPACT]"; + public static Dictionary GImpacts = new Dictionary(); + + public BSShapeGImpact(BulletShape pShape) : base(pShape) + { + } + public static BSShape GetReference(BSScene physicsScene, bool forceRebuild, BSPhysObject prim) + { + float lod; + System.UInt64 newMeshKey = BSShape.ComputeShapeKey(prim.Size, prim.BaseShape, out lod); + + physicsScene.DetailLog("{0},BSShapeGImpact,getReference,newKey={1},size={2},lod={3}", + prim.LocalID, newMeshKey.ToString("X"), prim.Size, lod); + + BSShapeGImpact retGImpact = null; + lock (GImpacts) + { + if (GImpacts.TryGetValue(newMeshKey, out retGImpact)) + { + // The mesh has already been created. Return a new reference to same. + retGImpact.IncrementReference(); + } + else + { + retGImpact = new BSShapeGImpact(new BulletShape()); + BulletShape newShape = retGImpact.CreatePhysicalGImpact(physicsScene, prim, newMeshKey, prim.BaseShape, prim.Size, lod); + + // Check to see if mesh was created (might require an asset). + newShape = VerifyMeshCreated(physicsScene, newShape, prim); + if (!newShape.isNativeShape || prim.PrimAssetState == BSPhysObject.PrimAssetCondition.Failed) + { + // If a mesh was what was created, remember the built shape for later sharing. + // Also note that if meshing failed we put it in the mesh list as there is nothing else to do about the mesh. + GImpacts.Add(newMeshKey, retGImpact); + } + + retGImpact.physShapeInfo = newShape; + } + } + return retGImpact; + } + + private BulletShape CreatePhysicalGImpact(BSScene physicsScene, BSPhysObject prim, System.UInt64 newMeshKey, + PrimitiveBaseShape pbs, OMV.Vector3 size, float lod) + { + return BSShapeMesh.CreatePhysicalMeshShape(physicsScene, prim, newMeshKey, pbs, size, lod, + (w, iC, i, vC, v) => physicsScene.PE.CreateGImpactShape(w, iC, i, vC, v) ); + } + + public override BSShape GetReference(BSScene physicsScene, BSPhysObject prim) + { + // Calling this reference means we want another handle to an existing shape + // (usually linksets) so return this copy. + IncrementReference(); + return this; + } + // Dereferencing a compound shape releases the hold on all the child shapes. + public override void Dereference(BSScene physicsScene) + { + lock (GImpacts) + { + this.DecrementReference(); + physicsScene.DetailLog("{0},BSShapeGImpact.Dereference,shape={1}", BSScene.DetailLogZero, this); + // TODO: schedule aging and destruction of unused meshes. + } + } + // Loop through all the known hulls and return the description based on the physical address. + public static bool TryGetGImpactByPtr(BulletShape pShape, out BSShapeGImpact outHull) + { + bool ret = false; + BSShapeGImpact foundDesc = null; + lock (GImpacts) + { + foreach (BSShapeGImpact sh in GImpacts.Values) + { + if (sh.physShapeInfo.ReferenceSame(pShape)) + { + foundDesc = sh; + ret = true; + break; + } + + } + } + outHull = foundDesc; + return ret; + } +} // ============================================================================================================ public class BSShapeAvatar : BSShape diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimTODO.txt b/OpenSim/Region/Physics/BulletSPlugin/BulletSimTODO.txt index 5792ae64e8..df1da63626 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimTODO.txt +++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimTODO.txt @@ -1,16 +1,12 @@ -PROBLEMS TO LOOK INTO +CURRENT PROBLEMS TO FIX AND/OR LOOK AT ================================================= -Nebadon vehicle ride, get up, ride again. Second time vehicle does not act correctly. +Script changing rotation of child prim while vehicle moving (eg turning wheel) causes + the wheel to appear to jump back. Looks like sending position from previous update. +Vehicle ride, get up, ride again. Second time vehicle does not act correctly. Have to rez new vehicle and delete the old to fix situation. Hitting RESET on Nebadon's vehicle while riding causes vehicle to get into odd position state where it will not settle onto ground properly, etc Two of Nebadon vehicles in a sim max the CPU. This is new. -A sitting, active vehicle bobs up and down a small amount. - -CURRENT PRIORITIES -================================================= -Use the HACD convex hull routine in Bullet rather than the C# version. - Speed up hullifying large meshes. Enable vehicle border crossings (at least as poorly as ODE) Terrain skirts Avatar created in previous region and not new region when crossing border @@ -361,4 +357,6 @@ Angular motion around Z moves the vehicle in world Z and not vehicle Z in ODE. Nebadon vehicles turning funny in arena (DONE) Lock axis (DONE 20130401) Terrain detail: double terrain mesh detail (DONE) +Use the HACD convex hull routine in Bullet rather than the C# version. + Speed up hullifying large meshes. (DONE) diff --git a/OpenSim/Region/Physics/Meshing/Meshmerizer.cs b/OpenSim/Region/Physics/Meshing/Meshmerizer.cs index 42929ec4cf..db5d96261f 100644 --- a/OpenSim/Region/Physics/Meshing/Meshmerizer.cs +++ b/OpenSim/Region/Physics/Meshing/Meshmerizer.cs @@ -79,6 +79,8 @@ namespace OpenSim.Region.Physics.Meshing private float minSizeForComplexMesh = 0.2f; // prims with all dimensions smaller than this will have a bounding box mesh + private List> mConvexHulls = null; + private Dictionary m_uniqueMeshes = new Dictionary(); public Meshmerizer(IConfigSource config) @@ -363,6 +365,57 @@ namespace OpenSim.Region.Physics.Meshing else if (map.ContainsKey("high_lod")) physicsParms = (OSDMap)map["high_lod"]; // if all else fails, use highest LOD display mesh and hope it works :) + if (map.ContainsKey("physics_convex")) + { // pull this out also in case physics engine can use it + try + { + OSDMap convexBlock = (OSDMap)map["physics_convex"]; + if (convexBlock.ContainsKey("HullList")) + { + byte[] hullList = convexBlock["HullList"].AsBinary(); + Vector3 min = new Vector3(-0.5f, -0.5f, -0.5f); + if (convexBlock.ContainsKey("Min")) min = convexBlock["Min"].AsVector3(); + Vector3 max = new Vector3(0.5f, 0.5f, 0.5f); + if (convexBlock.ContainsKey("Max")) max = convexBlock["Max"].AsVector3(); + + // decompress and decode hull points + byte[] posBytes = DecompressOsd(convexBlock["Positions"].AsBinary()).AsBinary(); + + List> hulls = new List>(); + int posNdx = 0; + + foreach (byte cnt in hullList) + { + int count = cnt == 0 ? 256 : cnt; + List hull = new List(); + + for (int i = 0; i < count; i++) + { + ushort uX = Utils.BytesToUInt16(posBytes, posNdx); posNdx += 2; + ushort uY = Utils.BytesToUInt16(posBytes, posNdx); posNdx += 2; + ushort uZ = Utils.BytesToUInt16(posBytes, posNdx); posNdx += 2; + + Vector3 pos = new Vector3( + Utils.UInt16ToFloat(uX, min.X, max.X), + Utils.UInt16ToFloat(uY, min.Y, max.Y), + Utils.UInt16ToFloat(uZ, min.Z, max.Z) + ); + + hull.Add(pos); + } + + hulls.Add(hull); + } + + mConvexHulls = hulls; + } + } + catch (Exception e) + { + m_log.WarnFormat("[MESH]: exception decoding convex block: {0}", e.Message); + } + } + if (physicsParms == null) { m_log.WarnFormat("[MESH]: No recognized physics mesh found in mesh asset for {0}", primName); @@ -381,27 +434,7 @@ namespace OpenSim.Region.Physics.Meshing // byte[] decompressed = new byte[physSize * 5]; try { - using (MemoryStream inMs = new MemoryStream(meshBytes)) - { - using (MemoryStream outMs = new MemoryStream()) - { - using (ZOutputStream zOut = new ZOutputStream(outMs)) - { - byte[] readBuffer = new byte[2048]; - int readLen = 0; - while ((readLen = inMs.Read(readBuffer, 0, readBuffer.Length)) > 0) - { - zOut.Write(readBuffer, 0, readLen); - } - zOut.Flush(); - outMs.Seek(0, SeekOrigin.Begin); - - byte[] decompressedBuf = outMs.GetBuffer(); - - decodedMeshOsd = OSDParser.DeserializeLLSDBinary(decompressedBuf); - } - } - } + decodedMeshOsd = DecompressOsd(meshBytes); } catch (Exception e) { @@ -428,6 +461,41 @@ namespace OpenSim.Region.Physics.Meshing return true; } + + /// + /// decompresses a gzipped OSD object + /// + /// the OSD object + /// + /// + private static OSD DecompressOsd(byte[] meshBytes) + { + OSD decodedOsd = null; + + using (MemoryStream inMs = new MemoryStream(meshBytes)) + { + using (MemoryStream outMs = new MemoryStream()) + { + using (ZOutputStream zOut = new ZOutputStream(outMs)) + { + byte[] readBuffer = new byte[2048]; + int readLen = 0; + while ((readLen = inMs.Read(readBuffer, 0, readBuffer.Length)) > 0) + { + zOut.Write(readBuffer, 0, readLen); + } + zOut.Flush(); + outMs.Seek(0, SeekOrigin.Begin); + + byte[] decompressedBuf = outMs.GetBuffer(); + + decodedOsd = OSDParser.DeserializeLLSDBinary(decompressedBuf); + } + } + } + return decodedOsd; + } + /// /// Generate the co-ords and faces necessary to construct a mesh from the sculpt data the accompanies a prim. /// @@ -704,6 +772,27 @@ namespace OpenSim.Region.Physics.Meshing return true; } + /// + /// temporary prototype code - please do not use until the interface has been finalized! + /// + /// value to scale the hull points by + /// a list of hulls if they exist and have been successfully decoded, otherwise null + public List> GetConvexHulls(Vector3 size) + { + if (mConvexHulls == null) + return null; + + List> hulls = new List>(); + foreach (var hull in mConvexHulls) + { + List verts = new List(); + foreach (var vert in hull) + verts.Add(vert * size); + } + + return hulls; + } + public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod) { return CreateMesh(primName, primShape, size, lod, false, true); diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index bc35272f1b..0199461cc7 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -2772,9 +2772,11 @@ 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, - ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, sound, AssetType.Sound), volume, false, 0, - 0, false, false); + m_SoundModule.SendSound( + m_host.UUID, + ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, sound, AssetType.Sound), + volume, false, m_host.SoundQueueing ? (byte)SoundFlags.Queue : (byte)SoundFlags.None, + 0, false, false); } } @@ -12644,6 +12646,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public void llSetSoundQueueing(int queue) { m_host.AddScriptLPS(1); + + if (m_SoundModule != null) + m_SoundModule.SetSoundQueueing(m_host.UUID, queue == ScriptBaseClass.TRUE.value); } public void llCollisionSprite(string impact_sprite) diff --git a/bin/lib32/BulletSim.dll b/bin/lib32/BulletSim.dll index 1e94d05955..d63ee1d917 100755 Binary files a/bin/lib32/BulletSim.dll and b/bin/lib32/BulletSim.dll differ diff --git a/bin/lib32/libBulletSim.so b/bin/lib32/libBulletSim.so index 6216a652d2..03de631029 100755 Binary files a/bin/lib32/libBulletSim.so and b/bin/lib32/libBulletSim.so differ diff --git a/bin/lib64/BulletSim.dll b/bin/lib64/BulletSim.dll index 68cfcc41ea..e155f0e4ac 100755 Binary files a/bin/lib64/BulletSim.dll and b/bin/lib64/BulletSim.dll differ diff --git a/bin/lib64/libBulletSim.so b/bin/lib64/libBulletSim.so index 08c00af019..ac64a401e2 100755 Binary files a/bin/lib64/libBulletSim.so and b/bin/lib64/libBulletSim.so differ diff --git a/prebuild.xml b/prebuild.xml index ef07bdc1e9..c611cb9d13 100644 --- a/prebuild.xml +++ b/prebuild.xml @@ -1878,6 +1878,7 @@ +