Merge branch 'master' into careminster

Conflicts:
	OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
	OpenSim/Region/Physics/BulletSPlugin/BSShapes.cs
	OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
avinationmerge
Melanie 2013-05-24 00:45:08 +01:00
commit 09c2cd0d76
23 changed files with 481 additions and 95 deletions

View File

@ -2148,7 +2148,7 @@ namespace OpenSim.Framework
/// <param name="secret">the secret part</param>
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)

View File

@ -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;

View File

@ -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;

View File

@ -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)
/// <summary>
/// Try to get the names bound to the given uuid.
/// </summary>
/// <returns>True if the name was found, false if not.</returns>
/// <param name='uuid'></param>
/// <param name='names'>The array of names if found. If not found, then names[0] = "Unknown" and names[1] = "User"</param>
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 <uuid>",
"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<UUID, UserData> 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 <uuid>");
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<UUID, UserData> 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());
}
}
}

View File

@ -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
}
}

View File

@ -104,7 +104,6 @@ namespace OpenSim.Region.Framework.Interfaces
/// <param name="sound">Sound asset ID</param>
/// <param name="volume">Sound volume</param>
/// <param name="triggered">Triggered or not.</param>
/// <param name="flags"></param>
/// <param name="radius">Sound radius</param>
/// <param name="useMaster">Play using sound master</param>
/// <param name="isMaster">Play as sound master</param>
@ -123,5 +122,12 @@ namespace OpenSim.Region.Framework.Interfaces
/// <param name="max">AABB top north-east corner</param>
void TriggerSoundLimited(UUID objectID, UUID sound, double volume,
Vector3 min, Vector3 max);
/// <summary>
/// Set whether sounds on the given prim should be queued.
/// </summary>
/// <param name='objectID'></param>
/// <param name='shouldQueue'></param>
void SetSoundQueueing(UUID objectID, bool shouldQueue);
}
}

View File

@ -231,6 +231,13 @@ namespace OpenSim.Region.Framework.Scenes
public double SoundRadius;
/// <summary>
/// Should sounds played from this prim be queued?
/// </summary>
/// <remarks>
/// This should only be changed by sound modules. It is up to sound modules as to how they interpret this setting.
/// </remarks>
public bool SoundQueueing { get; set; }
public uint TimeStampFull;

View File

@ -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);

View File

@ -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(ObjectArray<int>indices, ObjectArray<float> vertices, int pIndicesCount,int pVerticesCount )
{

View File

@ -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);

View File

@ -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;
});
}
}

View File

@ -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<bool>("ShouldUseSingleConvexHullForPrims", "If true, use a single convex hull shape for physical prims",
true ),
new ParameterDefn<bool>("ShouldUseGImpactShapeForPrims", "If true, use a GImpact shape for prims with cuts and twists",
false ),
new ParameterDefn<bool>("UseAssetHulls", "If true, use hull if specified in the mesh asset info",
false ),
new ParameterDefn<int>("CrossingFailuresBeforeOutOfBounds", "How forgiving we are about getting into adjactent regions",
5 ),

View File

@ -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;

View File

@ -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

View File

@ -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<List<OMV.Vector3>> 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<OMV.Vector3> 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<OMV.Vector3> 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<System.UInt64, BSShapeGImpact> GImpacts = new Dictionary<System.UInt64, BSShapeGImpact>();
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

View File

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

View File

@ -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<List<Vector3>> mConvexHulls = null;
private Dictionary<ulong, Mesh> m_uniqueMeshes = new Dictionary<ulong, Mesh>();
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<List<Vector3>> hulls = new List<List<Vector3>>();
int posNdx = 0;
foreach (byte cnt in hullList)
{
int count = cnt == 0 ? 256 : cnt;
List<Vector3> hull = new List<Vector3>();
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;
}
/// <summary>
/// decompresses a gzipped OSD object
/// </summary>
/// <param name="decodedOsd"></param> the OSD object
/// <param name="meshBytes"></param>
/// <returns></returns>
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;
}
/// <summary>
/// Generate the co-ords and faces necessary to construct a mesh from the sculpt data the accompanies a prim.
/// </summary>
@ -704,6 +772,27 @@ namespace OpenSim.Region.Physics.Meshing
return true;
}
/// <summary>
/// temporary prototype code - please do not use until the interface has been finalized!
/// </summary>
/// <param name="size">value to scale the hull points by</param>
/// <returns>a list of hulls if they exist and have been successfully decoded, otherwise null</returns>
public List<List<Vector3>> GetConvexHulls(Vector3 size)
{
if (mConvexHulls == null)
return null;
List<List<Vector3>> hulls = new List<List<Vector3>>();
foreach (var hull in mConvexHulls)
{
List<Vector3> verts = new List<Vector3>();
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);

View File

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

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -1878,6 +1878,7 @@
<Reference name="OpenSim.Region.CoreModules"/>
<Reference name="OpenSim.Framework.Console"/>
<Reference name="OpenSim.Region.Physics.Manager"/>
<Reference name="OpenSim.Region.Physics.Meshing" path="../../../../bin/Physics/"/>
<Reference name="OpenSim.Region.Physics.ConvexDecompositionDotNet"/>
<Reference name="BulletXNA.dll" path="../../../../bin/"/>
<Reference name="log4net.dll" path="../../../../bin/"/>