Merge branch 'avination' into careminster
Conflicts: OpenSim/Framework/WebUtil.cs OpenSim/Region/Physics/OdePlugin/OdeScene.csavinationmerge
commit
72c925a6c9
|
@ -733,7 +733,8 @@ namespace OpenSim.Framework
|
|||
reqnum, verb, requestUrl);
|
||||
|
||||
int tickstart = Util.EnvironmentTickCount();
|
||||
int tickdata = 0;
|
||||
// int tickdata = 0;
|
||||
int tickdiff = 0;
|
||||
|
||||
Type type = typeof(TRequest);
|
||||
|
||||
|
@ -776,8 +777,8 @@ namespace OpenSim.Framework
|
|||
requestStream.Close();
|
||||
|
||||
// capture how much time was spent writing
|
||||
tickdata = Util.EnvironmentTickCountSubtract(tickstart);
|
||||
|
||||
// useless in this async
|
||||
// tickdata = Util.EnvironmentTickCountSubtract(tickstart);
|
||||
request.BeginGetResponse(delegate(IAsyncResult ar)
|
||||
{
|
||||
response = request.EndGetResponse(ar);
|
||||
|
@ -794,7 +795,8 @@ namespace OpenSim.Framework
|
|||
finally
|
||||
{
|
||||
// Let's not close this
|
||||
//buffer.Close();
|
||||
// yes do close it
|
||||
buffer.Close();
|
||||
respStream.Close();
|
||||
response.Close();
|
||||
}
|
||||
|
@ -862,7 +864,6 @@ namespace OpenSim.Framework
|
|||
}
|
||||
|
||||
// m_log.DebugFormat("[ASYNC REQUEST]: Received {0}", deserial.ToString());
|
||||
|
||||
try
|
||||
{
|
||||
action(deserial);
|
||||
|
@ -877,9 +878,10 @@ namespace OpenSim.Framework
|
|||
}, null);
|
||||
}
|
||||
|
||||
int tickdiff = Util.EnvironmentTickCountSubtract(tickstart);
|
||||
tickdiff = Util.EnvironmentTickCountSubtract(tickstart);
|
||||
if (tickdiff > WebUtil.LongCallTime)
|
||||
{
|
||||
/*
|
||||
string originalRequest = null;
|
||||
|
||||
if (buffer != null)
|
||||
|
@ -898,12 +900,19 @@ namespace OpenSim.Framework
|
|||
tickdiff,
|
||||
tickdata,
|
||||
originalRequest);
|
||||
*/
|
||||
m_log.InfoFormat(
|
||||
"[ASYNC REQUEST]: Slow WebRequest SETUP <{0}> {1} {2} took {3}ms",
|
||||
reqnum,
|
||||
verb,
|
||||
requestUrl,
|
||||
tickdiff);
|
||||
}
|
||||
else if (WebUtil.DebugLevel >= 4)
|
||||
{
|
||||
m_log.DebugFormat(
|
||||
"[WEB UTIL]: HTTP OUT {0} took {1}ms, {2}ms writing",
|
||||
reqnum, tickdiff, tickdata);
|
||||
"[WEB UTIL]: HTTP OUT {0} took {1}ms",
|
||||
reqnum, tickdiff);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -938,6 +947,8 @@ namespace OpenSim.Framework
|
|||
request.Method = verb;
|
||||
string respstring = String.Empty;
|
||||
|
||||
int tickset = Util.EnvironmentTickCountSubtract(tickstart);
|
||||
|
||||
using (MemoryStream buffer = new MemoryStream())
|
||||
{
|
||||
if ((verb == "POST") || (verb == "PUT"))
|
||||
|
@ -1019,6 +1030,7 @@ namespace OpenSim.Framework
|
|||
verb,
|
||||
requestUrl,
|
||||
tickdiff,
|
||||
tickset,
|
||||
tickdata,
|
||||
obj.Length > WebUtil.MaxRequestDiagLength ? obj.Remove(WebUtil.MaxRequestDiagLength) : obj);
|
||||
else if (WebUtil.DebugLevel >= 4)
|
||||
|
|
|
@ -1117,17 +1117,17 @@ namespace OpenSim.Region.ClientStack.Linden
|
|||
else
|
||||
{
|
||||
AddNewInventoryItem(m_HostCapsObj.AgentID, item, (uint)cost);
|
||||
if (client != null)
|
||||
{
|
||||
// let users see anything.. i don't so far
|
||||
string str;
|
||||
if (cost > 0)
|
||||
// dont remember where is money unit name to put here
|
||||
str = "Upload complete. charged " + cost.ToString() + "$";
|
||||
else
|
||||
str = "Upload complete";
|
||||
client.SendAgentAlertMessage(str, true);
|
||||
}
|
||||
// if (client != null)
|
||||
// {
|
||||
// // let users see anything.. i don't so far
|
||||
// string str;
|
||||
// if (cost > 0)
|
||||
// // dont remember where is money unit name to put here
|
||||
// str = "Upload complete. charged " + cost.ToString() + "$";
|
||||
// else
|
||||
// str = "Upload complete";
|
||||
// client.SendAgentAlertMessage(str, true);
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -104,7 +104,7 @@ namespace OpenSim.Region.ClientStack.Linden
|
|||
|
||||
public void RegisterCaps(UUID agentID, Caps caps)
|
||||
{
|
||||
if (!m_scene.RegionInfo.EstateSettings.IsEstateManagerOrOwner(agentID))
|
||||
if (!m_scene.RegionInfo.EstateSettings.IsEstateManagerOrOwner(agentID) && !m_scene.Permissions.IsGod(agentID))
|
||||
return;
|
||||
|
||||
UUID capID = UUID.Random();
|
||||
|
|
|
@ -575,6 +575,7 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
Quaternion current = m_group.GroupRotation;
|
||||
|
||||
Quaternion step = Quaternion.Slerp(m_currentFrame.StartRotation, (Quaternion)m_currentFrame.Rotation, complete);
|
||||
step.Normalize();
|
||||
/* use simpler change detection
|
||||
* float angle = 0;
|
||||
|
||||
|
|
|
@ -4386,8 +4386,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();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
@ -1095,9 +1095,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);
|
||||
}
|
||||
}
|
||||
|
@ -1583,7 +1583,9 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
|
||||
float cost = 0.1f;
|
||||
if (PhysActor != null)
|
||||
// cost += PhysActor.Cost;
|
||||
cost = PhysActor.PhysicsCost;
|
||||
else
|
||||
cost = 0.1f;
|
||||
|
||||
if ((Flags & PrimFlags.Physics) != 0)
|
||||
cost *= (1.0f + 0.01333f * Scale.LengthSquared()); // 0.01333 == 0.04/3
|
||||
|
@ -1596,9 +1598,12 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
{
|
||||
get
|
||||
{
|
||||
|
||||
|
||||
return 0.1f;
|
||||
float cost;
|
||||
if (PhysActor != null)
|
||||
cost = PhysActor.StreamCost;
|
||||
else
|
||||
cost = 1.0f;
|
||||
return 1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1654,8 +1659,8 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
else
|
||||
{
|
||||
PhysActor.PhysicsShapeType = m_physicsShapeType;
|
||||
if (Shape.SculptEntry)
|
||||
CheckSculptAndLoad();
|
||||
// if (Shape.SculptEntry)
|
||||
// CheckSculptAndLoad();
|
||||
}
|
||||
|
||||
if (ParentGroup != null)
|
||||
|
@ -2115,12 +2120,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);
|
||||
// dupe.UpdatePhysicsSubscribedEvents(); // not sure...
|
||||
|
@ -2142,6 +2148,7 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
/// <param name="id">ID of asset received</param>
|
||||
/// <param name="sender">Register</param>
|
||||
/// <param name="asset"></param>
|
||||
/*
|
||||
protected void AssetReceived(string id, Object sender, AssetBase asset)
|
||||
{
|
||||
if (asset != null)
|
||||
|
@ -2151,7 +2158,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);
|
||||
}
|
||||
|
||||
*/
|
||||
/// <summary>
|
||||
/// Do a physics property update for a NINJA joint.
|
||||
/// </summary>
|
||||
|
@ -2341,9 +2348,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);
|
||||
}
|
||||
}
|
||||
|
@ -3128,6 +3135,7 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
/// Set sculpt and mesh data, and tell the physics engine to process the change.
|
||||
/// </summary>
|
||||
/// <param name="texture">The mesh itself.</param>
|
||||
/*
|
||||
public void SculptTextureCallback(AssetBase texture)
|
||||
{
|
||||
if (m_shape.SculptEntry)
|
||||
|
@ -3155,7 +3163,7 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
/// <summary>
|
||||
/// Send a full update to the client for the given part
|
||||
/// </summary>
|
||||
|
@ -4397,7 +4405,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)
|
||||
|
@ -4405,7 +4413,7 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
ParentGroup.Scene.AssetService.Get(m_shape.SculptTexture.ToString(), this, AssetReceived);
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
if (ParentGroup != null)
|
||||
{
|
||||
ParentGroup.HasGroupChanged = true;
|
||||
|
@ -4813,9 +4821,9 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
}
|
||||
}
|
||||
|
||||
if (Shape.SculptEntry)
|
||||
CheckSculptAndLoad();
|
||||
else
|
||||
// if (Shape.SculptEntry)
|
||||
// CheckSculptAndLoad();
|
||||
// else
|
||||
ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(pa);
|
||||
|
||||
if (!building)
|
||||
|
@ -4969,10 +4977,13 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
/// <remarks>
|
||||
/// When the physics engine has finished with it, the sculpt data is discarded to save memory.
|
||||
/// </remarks>
|
||||
/*
|
||||
public void CheckSculptAndLoad()
|
||||
{
|
||||
// m_log.DebugFormat("Processing CheckSculptAndLoad for {0} {1}", Name, LocalId);
|
||||
|
||||
return;
|
||||
|
||||
if (ParentGroup.IsDeleted)
|
||||
return;
|
||||
|
||||
|
@ -4994,7 +5005,7 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
/// <summary>
|
||||
/// Update the texture entry for this part.
|
||||
/// </summary>
|
||||
|
@ -5262,6 +5273,7 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
}
|
||||
|
||||
Quaternion rot = Quaternion.Slerp(RotationOffset,APIDTarget,1.0f/(float)m_APIDIterations);
|
||||
rot.Normalize();
|
||||
UpdateRotation(rot);
|
||||
|
||||
m_APIDIterations--;
|
||||
|
|
|
@ -2190,7 +2190,7 @@ namespace OpenSim.Region.Physics.OdePlugin
|
|||
convex = false;
|
||||
try
|
||||
{
|
||||
_mesh = _parent_scene.mesher.CreateMesh(m_primName, _pbs, _size, (int)LevelOfDetail.High, true,convex);
|
||||
_mesh = _parent_scene.mesher.CreateMesh(m_primName, _pbs, _size, (int)LevelOfDetail.High, true,convex,false);
|
||||
}
|
||||
catch
|
||||
{
|
||||
|
@ -2557,7 +2557,7 @@ namespace OpenSim.Region.Physics.OdePlugin
|
|||
|
||||
try
|
||||
{
|
||||
mesh = _parent_scene.mesher.CreateMesh(oldname, _pbs, _size, (int)LevelOfDetail.High, true, convex);
|
||||
mesh = _parent_scene.mesher.CreateMesh(oldname, _pbs, _size, (int)LevelOfDetail.High, true, convex,false);
|
||||
}
|
||||
catch
|
||||
{
|
||||
|
|
|
@ -37,9 +37,11 @@ namespace OpenSim.Region.Physics.Manager
|
|||
{
|
||||
IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod);
|
||||
IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical);
|
||||
IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical,bool convex);
|
||||
IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical, bool convex, bool forOde);
|
||||
IMesh GetMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical, bool convex);
|
||||
void ReleaseMesh(IMesh mesh);
|
||||
void ExpireReleaseMeshs();
|
||||
void ExpireFileCache();
|
||||
}
|
||||
|
||||
// Values for level of detail to be passed to the mesher.
|
||||
|
@ -57,6 +59,7 @@ namespace OpenSim.Region.Physics.Manager
|
|||
{
|
||||
}
|
||||
|
||||
[Serializable()]
|
||||
[StructLayout(LayoutKind.Explicit)]
|
||||
public struct AMeshKey
|
||||
{
|
||||
|
@ -66,6 +69,13 @@ namespace OpenSim.Region.Physics.Manager
|
|||
public ulong hashA;
|
||||
[FieldOffset(8)]
|
||||
public ulong hashB;
|
||||
[FieldOffset(16)]
|
||||
public ulong hashC;
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return uuid.ToString() + "-" + hashC.ToString("x") ;
|
||||
}
|
||||
}
|
||||
|
||||
public interface IMesh
|
||||
|
@ -81,5 +91,6 @@ namespace OpenSim.Region.Physics.Manager
|
|||
void Append(IMesh newMesh);
|
||||
void TransformLinear(float[,] matrix, float[] offset);
|
||||
Vector3 GetCentroid();
|
||||
Vector3 GetOBB();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -315,6 +315,23 @@ namespace OpenSim.Region.Physics.Manager
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
public virtual float PhysicsCost
|
||||
{
|
||||
get
|
||||
{
|
||||
return 0.1f;
|
||||
}
|
||||
}
|
||||
|
||||
public virtual float StreamCost
|
||||
{
|
||||
get
|
||||
{
|
||||
return 1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Velocity of this actor.
|
||||
/// </summary>
|
||||
|
|
|
@ -106,7 +106,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()
|
||||
{
|
||||
|
@ -246,6 +246,9 @@ namespace OpenSim.Region.Physics.Manager
|
|||
|
||||
public abstract void AddPhysicsActorTaint(PhysicsActor prim);
|
||||
|
||||
|
||||
public virtual void PrepareSimulation() { }
|
||||
|
||||
/// <summary>
|
||||
/// Perform a simulation of the current physics scene over the given timestep.
|
||||
/// </summary>
|
||||
|
|
|
@ -67,7 +67,7 @@ namespace OpenSim.Region.Physics.Manager
|
|||
return CreateMesh(primName, primShape, size, lod, false);
|
||||
}
|
||||
|
||||
public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical, bool convex)
|
||||
public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical, bool convex,bool forOde)
|
||||
{
|
||||
return CreateMesh(primName, primShape, size, lod, false);
|
||||
}
|
||||
|
@ -79,7 +79,14 @@ namespace OpenSim.Region.Physics.Manager
|
|||
|
||||
return null;
|
||||
}
|
||||
|
||||
public IMesh GetMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical, bool convex)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public void ReleaseMesh(IMesh mesh) { }
|
||||
public void ExpireReleaseMeshs() { }
|
||||
public void ExpireFileCache() { }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -148,6 +148,12 @@ namespace OpenSim.Region.Physics.Meshing
|
|||
return Vector3.Zero;
|
||||
}
|
||||
|
||||
// not functional
|
||||
public Vector3 GetOBB()
|
||||
{
|
||||
return new Vector3(0.5f, 0.5f, 0.5f);
|
||||
}
|
||||
|
||||
public void CalcNormals()
|
||||
{
|
||||
int iTriangles = m_triangles.Count;
|
||||
|
@ -253,6 +259,7 @@ namespace OpenSim.Region.Physics.Meshing
|
|||
public void getVertexListAsPtrToFloatArray(out IntPtr vertices, out int vertexStride, out int vertexCount)
|
||||
{
|
||||
// A vertex is 3 floats
|
||||
|
||||
vertexStride = 3 * sizeof(float);
|
||||
|
||||
// If there isn't an unmanaged array allocated yet, do it now
|
||||
|
|
|
@ -74,8 +74,6 @@ namespace OpenSim.Region.Physics.Meshing
|
|||
#endif
|
||||
|
||||
private bool cacheSculptMaps = true;
|
||||
private bool cacheSculptAlphaMaps = true;
|
||||
|
||||
private string decodedSculptMapPath = null;
|
||||
private bool useMeshiesPhysicsMesh = false;
|
||||
|
||||
|
@ -89,16 +87,7 @@ namespace OpenSim.Region.Physics.Meshing
|
|||
IConfig mesh_config = config.Configs["Mesh"];
|
||||
|
||||
decodedSculptMapPath = start_config.GetString("DecodedSculptMapPath","j2kDecodeCache");
|
||||
|
||||
cacheSculptMaps = start_config.GetBoolean("CacheSculptMaps", cacheSculptMaps);
|
||||
|
||||
if (Environment.OSVersion.Platform == PlatformID.Unix)
|
||||
{
|
||||
cacheSculptAlphaMaps = false;
|
||||
}
|
||||
else
|
||||
cacheSculptAlphaMaps = cacheSculptMaps;
|
||||
|
||||
if(mesh_config != null)
|
||||
useMeshiesPhysicsMesh = mesh_config.GetBoolean("UseMeshiesPhysicsMesh", useMeshiesPhysicsMesh);
|
||||
|
||||
|
@ -279,18 +268,15 @@ namespace OpenSim.Region.Physics.Meshing
|
|||
{
|
||||
if (!GenerateCoordsAndFacesFromPrimSculptData(primName, primShape, size, lod, out coords, out faces))
|
||||
return null;
|
||||
// Remove the reference to any JPEG2000 sculpt data so it can be GCed
|
||||
// don't loose it
|
||||
// primShape.SculptData = Utils.EmptyBytes;
|
||||
}
|
||||
// primShape.SculptDataLoaded = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!GenerateCoordsAndFacesFromPrimShapeData(primName, primShape, size, lod, out coords, out faces))
|
||||
return null;
|
||||
}
|
||||
// keep compatible
|
||||
|
||||
// Remove the reference to any JPEG2000 sculpt data so it can be GCed
|
||||
primShape.SculptData = Utils.EmptyBytes;
|
||||
|
||||
int numCoords = coords.Count;
|
||||
|
@ -335,7 +321,7 @@ namespace OpenSim.Region.Physics.Meshing
|
|||
|
||||
if (primShape.SculptData.Length <= 0)
|
||||
{
|
||||
m_log.InfoFormat("[MESH]: asset data for {0} is zero length", primName);
|
||||
// m_log.ErrorFormat("[MESH]: asset data for {0} is zero length", primName);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -496,8 +482,7 @@ namespace OpenSim.Region.Physics.Meshing
|
|||
|
||||
//idata = CSJ2K.J2kImage.FromBytes(primShape.SculptData);
|
||||
|
||||
if (cacheSculptMaps && (cacheSculptAlphaMaps || (((ImageFlags)(idata.Flags) & ImageFlags.HasAlpha) ==0)))
|
||||
// don't cache images with alpha channel in linux since mono can't load them correctly)
|
||||
if (cacheSculptMaps)
|
||||
{
|
||||
try { idata.Save(decodedSculptFileName, ImageFormat.MemoryBmp); }
|
||||
catch (Exception e) { m_log.Error("[SCULPT]: unable to cache sculpt map " + decodedSculptFileName + " " + e.Message); }
|
||||
|
@ -717,7 +702,7 @@ namespace OpenSim.Region.Physics.Meshing
|
|||
return CreateMesh(primName, primShape, size, lod, false);
|
||||
}
|
||||
|
||||
public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical, bool convex)
|
||||
public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical, bool convex, bool forOde)
|
||||
{
|
||||
return CreateMesh(primName, primShape, size, lod, false);
|
||||
}
|
||||
|
@ -763,7 +748,13 @@ namespace OpenSim.Region.Physics.Meshing
|
|||
|
||||
return mesh;
|
||||
}
|
||||
public IMesh GetMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical, bool convex)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public void ReleaseMesh(IMesh imesh) { }
|
||||
public void ExpireReleaseMeshs() { }
|
||||
public void ExpireFileCache() { }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -604,8 +608,8 @@ namespace OpenSim.Region.Physics.OdePlugin
|
|||
break;
|
||||
|
||||
case HollowShape.Circle:
|
||||
// Hollow shape is a perfect cylinder in respect to the cube's scale
|
||||
// Cylinder hollow volume calculation
|
||||
// Hollow shape is a perfect cyllinder in respect to the cube's scale
|
||||
// Cyllinder hollow volume calculation
|
||||
|
||||
hollowVolume *= 0.1963495f * 3.07920140172638f;
|
||||
break;
|
||||
|
@ -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");
|
|||
/// </summary>
|
||||
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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -137,15 +137,8 @@ namespace OpenSim.Region.Physics.OdePlugin
|
|||
ODERayCastRequest[] reqs = m_PendingRequests.ToArray();
|
||||
for (int i = 0; i < reqs.Length; i++)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (reqs[i].callbackMethod != null) // quick optimization here, don't raycast
|
||||
RayCast(reqs[i]); // if there isn't anyone to send results
|
||||
}
|
||||
catch
|
||||
{
|
||||
//Fail silently
|
||||
}
|
||||
if (reqs[i].callbackMethod != null) // quick optimization here, don't raycast
|
||||
RayCast(reqs[i]); // if there isn't anyone to send results
|
||||
}
|
||||
|
||||
m_PendingRequests.Clear();
|
||||
|
|
|
@ -32,24 +32,49 @@ using System.Runtime.InteropServices;
|
|||
using OpenSim.Region.Physics.Manager;
|
||||
using PrimMesher;
|
||||
using OpenMetaverse;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Runtime.Serialization.Formatters.Binary;
|
||||
|
||||
namespace OpenSim.Region.Physics.Meshing
|
||||
{
|
||||
public class MeshBuildingData
|
||||
{
|
||||
public Dictionary<Vertex, int> m_vertices;
|
||||
public List<Triangle> m_triangles;
|
||||
public float m_obbXmin;
|
||||
public float m_obbXmax;
|
||||
public float m_obbYmin;
|
||||
public float m_obbYmax;
|
||||
public float m_obbZmin;
|
||||
public float m_obbZmax;
|
||||
public Vector3 m_centroid;
|
||||
public int m_centroidDiv;
|
||||
}
|
||||
|
||||
[Serializable()]
|
||||
public class Mesh : IMesh
|
||||
{
|
||||
|
||||
private Dictionary<Vertex, int> m_vertices;
|
||||
private List<Triangle> m_triangles;
|
||||
GCHandle m_pinnedVertexes;
|
||||
GCHandle m_pinnedIndex;
|
||||
float[] vertices;
|
||||
int[] indexes;
|
||||
Vector3 m_obb;
|
||||
Vector3 m_obboffset;
|
||||
[NonSerialized()]
|
||||
MeshBuildingData m_bdata;
|
||||
[NonSerialized()]
|
||||
GCHandle vhandler;
|
||||
[NonSerialized()]
|
||||
GCHandle ihandler;
|
||||
[NonSerialized()]
|
||||
IntPtr m_verticesPtr = IntPtr.Zero;
|
||||
int m_vertexCount = 0;
|
||||
[NonSerialized()]
|
||||
IntPtr m_indicesPtr = IntPtr.Zero;
|
||||
[NonSerialized()]
|
||||
int m_vertexCount = 0;
|
||||
[NonSerialized()]
|
||||
int m_indexCount = 0;
|
||||
public float[] m_normals;
|
||||
Vector3 m_centroid;
|
||||
int m_centroidDiv;
|
||||
|
||||
public int RefCount { get; set; }
|
||||
public AMeshKey Key { get; set; }
|
||||
|
||||
private class vertexcomp : IEqualityComparer<Vertex>
|
||||
{
|
||||
|
@ -73,43 +98,119 @@ namespace OpenSim.Region.Physics.Meshing
|
|||
{
|
||||
vertexcomp vcomp = new vertexcomp();
|
||||
|
||||
m_vertices = new Dictionary<Vertex, int>(vcomp);
|
||||
m_triangles = new List<Triangle>();
|
||||
m_centroid = Vector3.Zero;
|
||||
m_centroidDiv = 0;
|
||||
m_bdata = new MeshBuildingData();
|
||||
m_bdata.m_vertices = new Dictionary<Vertex, int>(vcomp);
|
||||
m_bdata.m_triangles = new List<Triangle>();
|
||||
m_bdata.m_centroid = Vector3.Zero;
|
||||
m_bdata.m_centroidDiv = 0;
|
||||
m_bdata.m_obbXmin = float.MaxValue;
|
||||
m_bdata.m_obbXmax = float.MinValue;
|
||||
m_bdata.m_obbYmin = float.MaxValue;
|
||||
m_bdata.m_obbYmax = float.MinValue;
|
||||
m_bdata.m_obbZmin = float.MaxValue;
|
||||
m_bdata.m_obbZmax = float.MinValue;
|
||||
m_obb = new Vector3(0.5f, 0.5f, 0.5f);
|
||||
m_obboffset = Vector3.Zero;
|
||||
}
|
||||
|
||||
public int RefCount { get; set; }
|
||||
|
||||
public AMeshKey Key { get; set; }
|
||||
|
||||
public void Scale(Vector3 scale)
|
||||
public Mesh Scale(Vector3 scale)
|
||||
{
|
||||
if (m_verticesPtr == null || m_indicesPtr == null)
|
||||
return null;
|
||||
|
||||
Mesh result = new Mesh();
|
||||
|
||||
float x = scale.X;
|
||||
float y = scale.Y;
|
||||
float z = scale.Z;
|
||||
|
||||
result.m_obb.X = m_obb.X * x;
|
||||
result.m_obb.Y = m_obb.Y * y;
|
||||
result.m_obb.Z = m_obb.Z * z;
|
||||
result.m_obboffset.X = m_obboffset.X * x;
|
||||
result.m_obboffset.Y = m_obboffset.Y * y;
|
||||
result.m_obboffset.Z = m_obboffset.Z * z;
|
||||
|
||||
result.vertices = new float[vertices.Length];
|
||||
int j = 0;
|
||||
for (int i = 0; i < m_vertexCount; i++)
|
||||
{
|
||||
result.vertices[j] = vertices[j] * x;
|
||||
j++;
|
||||
result.vertices[j] = vertices[j] * y;
|
||||
j++;
|
||||
result.vertices[j] = vertices[j] * z;
|
||||
j++;
|
||||
}
|
||||
|
||||
result.indexes = new int[indexes.Length];
|
||||
indexes.CopyTo(result.indexes,0);
|
||||
|
||||
result.pinMemory();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public Mesh Clone()
|
||||
{
|
||||
Mesh result = new Mesh();
|
||||
|
||||
foreach (Triangle t in m_triangles)
|
||||
if (m_bdata != null)
|
||||
{
|
||||
result.Add(new Triangle(t.v1.Clone(), t.v2.Clone(), t.v3.Clone()));
|
||||
result.m_bdata = new MeshBuildingData();
|
||||
foreach (Triangle t in m_bdata.m_triangles)
|
||||
{
|
||||
result.Add(new Triangle(t.v1.Clone(), t.v2.Clone(), t.v3.Clone()));
|
||||
}
|
||||
result.m_bdata.m_centroid = m_bdata.m_centroid;
|
||||
result.m_bdata.m_centroidDiv = m_bdata.m_centroidDiv;
|
||||
result.m_bdata.m_obbXmin = m_bdata.m_obbXmin;
|
||||
result.m_bdata.m_obbXmax = m_bdata.m_obbXmax;
|
||||
result.m_bdata.m_obbYmin = m_bdata.m_obbYmin;
|
||||
result.m_bdata.m_obbYmax = m_bdata.m_obbYmax;
|
||||
result.m_bdata.m_obbZmin = m_bdata.m_obbZmin;
|
||||
result.m_bdata.m_obbZmax = m_bdata.m_obbZmax;
|
||||
}
|
||||
result.m_centroid = m_centroid;
|
||||
result.m_centroidDiv = m_centroidDiv;
|
||||
result.m_obb = m_obb;
|
||||
result.m_obboffset = m_obboffset;
|
||||
return result;
|
||||
}
|
||||
|
||||
public void addVertexLStats(Vertex v)
|
||||
{
|
||||
float x = v.X;
|
||||
float y = v.Y;
|
||||
float z = v.Z;
|
||||
|
||||
m_bdata.m_centroid.X += x;
|
||||
m_bdata.m_centroid.Y += y;
|
||||
m_bdata.m_centroid.Z += z;
|
||||
m_bdata.m_centroidDiv++;
|
||||
|
||||
if (x > m_bdata.m_obbXmax)
|
||||
m_bdata.m_obbXmax = x;
|
||||
else if (x < m_bdata.m_obbXmin)
|
||||
m_bdata.m_obbXmin = x;
|
||||
|
||||
if (y > m_bdata.m_obbYmax)
|
||||
m_bdata.m_obbYmax = y;
|
||||
else if (y < m_bdata.m_obbYmin)
|
||||
m_bdata.m_obbYmin = y;
|
||||
|
||||
if (z > m_bdata.m_obbZmax)
|
||||
m_bdata.m_obbZmax = z;
|
||||
else if (z < m_bdata.m_obbZmin)
|
||||
m_bdata.m_obbZmin = z;
|
||||
|
||||
}
|
||||
|
||||
|
||||
public void Add(Triangle triangle)
|
||||
{
|
||||
if (m_pinnedIndex.IsAllocated || m_pinnedVertexes.IsAllocated || m_indicesPtr != IntPtr.Zero || m_verticesPtr != IntPtr.Zero)
|
||||
if (m_indicesPtr != IntPtr.Zero || m_verticesPtr != IntPtr.Zero)
|
||||
throw new NotSupportedException("Attempt to Add to a pinned Mesh");
|
||||
// If a vertex of the triangle is not yet in the vertices list,
|
||||
// add it and set its index to the current index count
|
||||
// vertex == seems broken
|
||||
// skip colapsed triangles
|
||||
|
||||
if ((triangle.v1.X == triangle.v2.X && triangle.v1.Y == triangle.v2.Y && triangle.v1.Z == triangle.v2.Z)
|
||||
|| (triangle.v1.X == triangle.v3.X && triangle.v1.Y == triangle.v3.Y && triangle.v1.Z == triangle.v3.Z)
|
||||
|| (triangle.v2.X == triangle.v3.X && triangle.v2.Y == triangle.v3.Y && triangle.v2.Z == triangle.v3.Z)
|
||||
|
@ -118,113 +219,59 @@ namespace OpenSim.Region.Physics.Meshing
|
|||
return;
|
||||
}
|
||||
|
||||
if (m_vertices.Count == 0)
|
||||
if (m_bdata.m_vertices.Count == 0)
|
||||
{
|
||||
m_centroidDiv = 0;
|
||||
m_centroid = Vector3.Zero;
|
||||
m_bdata.m_centroidDiv = 0;
|
||||
m_bdata.m_centroid = Vector3.Zero;
|
||||
}
|
||||
|
||||
if (!m_vertices.ContainsKey(triangle.v1))
|
||||
if (!m_bdata.m_vertices.ContainsKey(triangle.v1))
|
||||
{
|
||||
m_vertices[triangle.v1] = m_vertices.Count;
|
||||
m_centroid.X += triangle.v1.X;
|
||||
m_centroid.Y += triangle.v1.Y;
|
||||
m_centroid.Z += triangle.v1.Z;
|
||||
m_centroidDiv++;
|
||||
m_bdata.m_vertices[triangle.v1] = m_bdata.m_vertices.Count;
|
||||
addVertexLStats(triangle.v1);
|
||||
}
|
||||
if (!m_vertices.ContainsKey(triangle.v2))
|
||||
if (!m_bdata.m_vertices.ContainsKey(triangle.v2))
|
||||
{
|
||||
m_vertices[triangle.v2] = m_vertices.Count;
|
||||
m_centroid.X += triangle.v2.X;
|
||||
m_centroid.Y += triangle.v2.Y;
|
||||
m_centroid.Z += triangle.v2.Z;
|
||||
m_centroidDiv++;
|
||||
m_bdata.m_vertices[triangle.v2] = m_bdata.m_vertices.Count;
|
||||
addVertexLStats(triangle.v2);
|
||||
}
|
||||
if (!m_vertices.ContainsKey(triangle.v3))
|
||||
if (!m_bdata.m_vertices.ContainsKey(triangle.v3))
|
||||
{
|
||||
m_vertices[triangle.v3] = m_vertices.Count;
|
||||
m_centroid.X += triangle.v3.X;
|
||||
m_centroid.Y += triangle.v3.Y;
|
||||
m_centroid.Z += triangle.v3.Z;
|
||||
m_centroidDiv++;
|
||||
m_bdata.m_vertices[triangle.v3] = m_bdata.m_vertices.Count;
|
||||
addVertexLStats(triangle.v3);
|
||||
}
|
||||
m_triangles.Add(triangle);
|
||||
m_bdata.m_triangles.Add(triangle);
|
||||
}
|
||||
|
||||
public Vector3 GetCentroid()
|
||||
{
|
||||
if (m_centroidDiv > 0)
|
||||
return new Vector3(m_centroid.X / m_centroidDiv, m_centroid.Y / m_centroidDiv, m_centroid.Z / m_centroidDiv);
|
||||
else
|
||||
return Vector3.Zero;
|
||||
return m_obboffset;
|
||||
|
||||
}
|
||||
|
||||
public void CalcNormals()
|
||||
public Vector3 GetOBB()
|
||||
{
|
||||
int iTriangles = m_triangles.Count;
|
||||
|
||||
this.m_normals = new float[iTriangles * 3];
|
||||
|
||||
int i = 0;
|
||||
foreach (Triangle t in m_triangles)
|
||||
return m_obb;
|
||||
float x, y, z;
|
||||
if (m_bdata.m_centroidDiv > 0)
|
||||
{
|
||||
float ux, uy, uz;
|
||||
float vx, vy, vz;
|
||||
float wx, wy, wz;
|
||||
|
||||
ux = t.v1.X;
|
||||
uy = t.v1.Y;
|
||||
uz = t.v1.Z;
|
||||
|
||||
vx = t.v2.X;
|
||||
vy = t.v2.Y;
|
||||
vz = t.v2.Z;
|
||||
|
||||
wx = t.v3.X;
|
||||
wy = t.v3.Y;
|
||||
wz = t.v3.Z;
|
||||
|
||||
|
||||
// Vectors for edges
|
||||
float e1x, e1y, e1z;
|
||||
float e2x, e2y, e2z;
|
||||
|
||||
e1x = ux - vx;
|
||||
e1y = uy - vy;
|
||||
e1z = uz - vz;
|
||||
|
||||
e2x = ux - wx;
|
||||
e2y = uy - wy;
|
||||
e2z = uz - wz;
|
||||
|
||||
|
||||
// Cross product for normal
|
||||
float nx, ny, nz;
|
||||
nx = e1y * e2z - e1z * e2y;
|
||||
ny = e1z * e2x - e1x * e2z;
|
||||
nz = e1x * e2y - e1y * e2x;
|
||||
|
||||
// Length
|
||||
float l = (float)Math.Sqrt(nx * nx + ny * ny + nz * nz);
|
||||
float lReciprocal = 1.0f / l;
|
||||
|
||||
// Normalized "normal"
|
||||
//nx /= l;
|
||||
//ny /= l;
|
||||
//nz /= l;
|
||||
|
||||
m_normals[i] = nx * lReciprocal;
|
||||
m_normals[i + 1] = ny * lReciprocal;
|
||||
m_normals[i + 2] = nz * lReciprocal;
|
||||
|
||||
i += 3;
|
||||
x = (m_bdata.m_obbXmax - m_bdata.m_obbXmin) * 0.5f;
|
||||
y = (m_bdata.m_obbYmax - m_bdata.m_obbYmin) * 0.5f;
|
||||
z = (m_bdata.m_obbZmax - m_bdata.m_obbZmin) * 0.5f;
|
||||
}
|
||||
else // ??
|
||||
{
|
||||
x = 0.5f;
|
||||
y = 0.5f;
|
||||
z = 0.5f;
|
||||
}
|
||||
return new Vector3(x, y, z);
|
||||
}
|
||||
|
||||
public List<Vector3> getVertexList()
|
||||
{
|
||||
List<Vector3> result = new List<Vector3>();
|
||||
foreach (Vertex v in m_vertices.Keys)
|
||||
foreach (Vertex v in m_bdata.m_vertices.Keys)
|
||||
{
|
||||
result.Add(new Vector3(v.X, v.Y, v.Z));
|
||||
}
|
||||
|
@ -233,10 +280,10 @@ namespace OpenSim.Region.Physics.Meshing
|
|||
|
||||
private float[] getVertexListAsFloat()
|
||||
{
|
||||
if (m_vertices == null)
|
||||
if (m_bdata.m_vertices == null)
|
||||
throw new NotSupportedException();
|
||||
float[] result = new float[m_vertices.Count * 3];
|
||||
foreach (KeyValuePair<Vertex, int> kvp in m_vertices)
|
||||
float[] result = new float[m_bdata.m_vertices.Count * 3];
|
||||
foreach (KeyValuePair<Vertex, int> kvp in m_bdata.m_vertices)
|
||||
{
|
||||
Vertex v = kvp.Key;
|
||||
int i = kvp.Value;
|
||||
|
@ -249,48 +296,39 @@ namespace OpenSim.Region.Physics.Meshing
|
|||
|
||||
public float[] getVertexListAsFloatLocked()
|
||||
{
|
||||
if (m_pinnedVertexes.IsAllocated)
|
||||
return (float[])(m_pinnedVertexes.Target);
|
||||
|
||||
float[] result = getVertexListAsFloat();
|
||||
m_pinnedVertexes = GCHandle.Alloc(result, GCHandleType.Pinned);
|
||||
// Inform the garbage collector of this unmanaged allocation so it can schedule
|
||||
// the next GC round more intelligently
|
||||
GC.AddMemoryPressure(Buffer.ByteLength(result));
|
||||
|
||||
return result;
|
||||
return null;
|
||||
}
|
||||
|
||||
public void getVertexListAsPtrToFloatArray(out IntPtr vertices, out int vertexStride, out int vertexCount)
|
||||
public void getVertexListAsPtrToFloatArray(out IntPtr _vertices, out int vertexStride, out int vertexCount)
|
||||
{
|
||||
// A vertex is 3 floats
|
||||
vertexStride = 3 * sizeof(float);
|
||||
|
||||
// If there isn't an unmanaged array allocated yet, do it now
|
||||
if (m_verticesPtr == IntPtr.Zero)
|
||||
if (m_verticesPtr == IntPtr.Zero && m_bdata != null)
|
||||
{
|
||||
float[] vertexList = getVertexListAsFloat();
|
||||
vertices = getVertexListAsFloat();
|
||||
// Each vertex is 3 elements (floats)
|
||||
m_vertexCount = vertexList.Length / 3;
|
||||
int byteCount = m_vertexCount * vertexStride;
|
||||
m_verticesPtr = System.Runtime.InteropServices.Marshal.AllocHGlobal(byteCount);
|
||||
System.Runtime.InteropServices.Marshal.Copy(vertexList, 0, m_verticesPtr, m_vertexCount * 3);
|
||||
m_vertexCount = vertices.Length / 3;
|
||||
vhandler = GCHandle.Alloc(vertices, GCHandleType.Pinned);
|
||||
m_verticesPtr = vhandler.AddrOfPinnedObject();
|
||||
GC.AddMemoryPressure(Buffer.ByteLength(vertices));
|
||||
}
|
||||
vertices = m_verticesPtr;
|
||||
_vertices = m_verticesPtr;
|
||||
vertexCount = m_vertexCount;
|
||||
}
|
||||
|
||||
public int[] getIndexListAsInt()
|
||||
{
|
||||
if (m_triangles == null)
|
||||
if (m_bdata.m_triangles == null)
|
||||
throw new NotSupportedException();
|
||||
int[] result = new int[m_triangles.Count * 3];
|
||||
for (int i = 0; i < m_triangles.Count; i++)
|
||||
int[] result = new int[m_bdata.m_triangles.Count * 3];
|
||||
for (int i = 0; i < m_bdata.m_triangles.Count; i++)
|
||||
{
|
||||
Triangle t = m_triangles[i];
|
||||
result[3 * i + 0] = m_vertices[t.v1];
|
||||
result[3 * i + 1] = m_vertices[t.v2];
|
||||
result[3 * i + 2] = m_vertices[t.v3];
|
||||
Triangle t = m_bdata.m_triangles[i];
|
||||
result[3 * i + 0] = m_bdata.m_vertices[t.v1];
|
||||
result[3 * i + 1] = m_bdata.m_vertices[t.v2];
|
||||
result[3 * i + 2] = m_bdata.m_vertices[t.v3];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@ -301,28 +339,19 @@ namespace OpenSim.Region.Physics.Meshing
|
|||
/// <returns></returns>
|
||||
public int[] getIndexListAsIntLocked()
|
||||
{
|
||||
if (m_pinnedIndex.IsAllocated)
|
||||
return (int[])(m_pinnedIndex.Target);
|
||||
|
||||
int[] result = getIndexListAsInt();
|
||||
m_pinnedIndex = GCHandle.Alloc(result, GCHandleType.Pinned);
|
||||
// Inform the garbage collector of this unmanaged allocation so it can schedule
|
||||
// the next GC round more intelligently
|
||||
GC.AddMemoryPressure(Buffer.ByteLength(result));
|
||||
|
||||
return result;
|
||||
return null;
|
||||
}
|
||||
|
||||
public void getIndexListAsPtrToIntArray(out IntPtr indices, out int triStride, out int indexCount)
|
||||
{
|
||||
// If there isn't an unmanaged array allocated yet, do it now
|
||||
if (m_indicesPtr == IntPtr.Zero)
|
||||
if (m_indicesPtr == IntPtr.Zero && m_bdata != null)
|
||||
{
|
||||
int[] indexList = getIndexListAsInt();
|
||||
m_indexCount = indexList.Length;
|
||||
int byteCount = m_indexCount * sizeof(int);
|
||||
m_indicesPtr = System.Runtime.InteropServices.Marshal.AllocHGlobal(byteCount);
|
||||
System.Runtime.InteropServices.Marshal.Copy(indexList, 0, m_indicesPtr, m_indexCount);
|
||||
indexes = getIndexListAsInt();
|
||||
m_indexCount = indexes.Length;
|
||||
ihandler = GCHandle.Alloc(indexes, GCHandleType.Pinned);
|
||||
m_indicesPtr = ihandler.AddrOfPinnedObject();
|
||||
GC.AddMemoryPressure(Buffer.ByteLength(indexes));
|
||||
}
|
||||
// A triangle is 3 ints (indices)
|
||||
triStride = 3 * sizeof(int);
|
||||
|
@ -332,18 +361,16 @@ namespace OpenSim.Region.Physics.Meshing
|
|||
|
||||
public void releasePinned()
|
||||
{
|
||||
if (m_pinnedVertexes.IsAllocated)
|
||||
m_pinnedVertexes.Free();
|
||||
if (m_pinnedIndex.IsAllocated)
|
||||
m_pinnedIndex.Free();
|
||||
if (m_verticesPtr != IntPtr.Zero)
|
||||
{
|
||||
System.Runtime.InteropServices.Marshal.FreeHGlobal(m_verticesPtr);
|
||||
vhandler.Free();
|
||||
vertices = null;
|
||||
m_verticesPtr = IntPtr.Zero;
|
||||
}
|
||||
if (m_indicesPtr != IntPtr.Zero)
|
||||
{
|
||||
System.Runtime.InteropServices.Marshal.FreeHGlobal(m_indicesPtr);
|
||||
ihandler.Free();
|
||||
indexes = null;
|
||||
m_indicesPtr = IntPtr.Zero;
|
||||
}
|
||||
}
|
||||
|
@ -353,29 +380,42 @@ namespace OpenSim.Region.Physics.Meshing
|
|||
/// </summary>
|
||||
public void releaseSourceMeshData()
|
||||
{
|
||||
m_triangles = null;
|
||||
m_vertices = null;
|
||||
if (m_bdata != null)
|
||||
{
|
||||
m_bdata.m_triangles = null;
|
||||
m_bdata.m_vertices = null;
|
||||
}
|
||||
}
|
||||
|
||||
public void releaseBuildingMeshData()
|
||||
{
|
||||
if (m_bdata != null)
|
||||
{
|
||||
m_bdata.m_triangles = null;
|
||||
m_bdata.m_vertices = null;
|
||||
m_bdata = null;
|
||||
}
|
||||
}
|
||||
|
||||
public void Append(IMesh newMesh)
|
||||
{
|
||||
if (m_pinnedIndex.IsAllocated || m_pinnedVertexes.IsAllocated || m_indicesPtr != IntPtr.Zero || m_verticesPtr != IntPtr.Zero)
|
||||
if (m_indicesPtr != IntPtr.Zero || m_verticesPtr != IntPtr.Zero)
|
||||
throw new NotSupportedException("Attempt to Append to a pinned Mesh");
|
||||
|
||||
if (!(newMesh is Mesh))
|
||||
return;
|
||||
|
||||
foreach (Triangle t in ((Mesh)newMesh).m_triangles)
|
||||
foreach (Triangle t in ((Mesh)newMesh).m_bdata.m_triangles)
|
||||
Add(t);
|
||||
}
|
||||
|
||||
// Do a linear transformation of mesh.
|
||||
public void TransformLinear(float[,] matrix, float[] offset)
|
||||
{
|
||||
if (m_pinnedIndex.IsAllocated || m_pinnedVertexes.IsAllocated || m_indicesPtr != IntPtr.Zero || m_verticesPtr != IntPtr.Zero)
|
||||
if (m_indicesPtr != IntPtr.Zero || m_verticesPtr != IntPtr.Zero)
|
||||
throw new NotSupportedException("Attempt to TransformLinear a pinned Mesh");
|
||||
|
||||
foreach (Vertex v in m_vertices.Keys)
|
||||
foreach (Vertex v in m_bdata.m_vertices.Keys)
|
||||
{
|
||||
if (v == null)
|
||||
continue;
|
||||
|
@ -393,10 +433,12 @@ namespace OpenSim.Region.Physics.Meshing
|
|||
{
|
||||
if (path == null)
|
||||
return;
|
||||
if (m_bdata == null)
|
||||
return;
|
||||
String fileName = name + "_" + title + ".raw";
|
||||
String completePath = System.IO.Path.Combine(path, fileName);
|
||||
StreamWriter sw = new StreamWriter(completePath);
|
||||
foreach (Triangle t in m_triangles)
|
||||
foreach (Triangle t in m_bdata.m_triangles)
|
||||
{
|
||||
String s = t.ToStringRaw();
|
||||
sw.WriteLine(s);
|
||||
|
@ -406,7 +448,144 @@ namespace OpenSim.Region.Physics.Meshing
|
|||
|
||||
public void TrimExcess()
|
||||
{
|
||||
m_triangles.TrimExcess();
|
||||
m_bdata.m_triangles.TrimExcess();
|
||||
}
|
||||
|
||||
public void pinMemory()
|
||||
{
|
||||
m_vertexCount = vertices.Length / 3;
|
||||
vhandler = GCHandle.Alloc(vertices, GCHandleType.Pinned);
|
||||
m_verticesPtr = vhandler.AddrOfPinnedObject();
|
||||
GC.AddMemoryPressure(Buffer.ByteLength(vertices));
|
||||
|
||||
m_indexCount = indexes.Length;
|
||||
ihandler = GCHandle.Alloc(indexes, GCHandleType.Pinned);
|
||||
m_indicesPtr = ihandler.AddrOfPinnedObject();
|
||||
GC.AddMemoryPressure(Buffer.ByteLength(indexes));
|
||||
}
|
||||
|
||||
public void PrepForOde()
|
||||
{
|
||||
// If there isn't an unmanaged array allocated yet, do it now
|
||||
if (m_verticesPtr == IntPtr.Zero)
|
||||
vertices = getVertexListAsFloat();
|
||||
|
||||
// If there isn't an unmanaged array allocated yet, do it now
|
||||
if (m_indicesPtr == IntPtr.Zero)
|
||||
indexes = getIndexListAsInt();
|
||||
|
||||
pinMemory();
|
||||
|
||||
float x, y, z;
|
||||
|
||||
if (m_bdata.m_centroidDiv > 0)
|
||||
{
|
||||
m_obboffset = new Vector3(m_bdata.m_centroid.X / m_bdata.m_centroidDiv, m_bdata.m_centroid.Y / m_bdata.m_centroidDiv, m_bdata.m_centroid.Z / m_bdata.m_centroidDiv);
|
||||
x = (m_bdata.m_obbXmax - m_bdata.m_obbXmin) * 0.5f;
|
||||
y = (m_bdata.m_obbYmax - m_bdata.m_obbYmin) * 0.5f;
|
||||
z = (m_bdata.m_obbZmax - m_bdata.m_obbZmin) * 0.5f;
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
m_obboffset = Vector3.Zero;
|
||||
x = 0.5f;
|
||||
y = 0.5f;
|
||||
z = 0.5f;
|
||||
}
|
||||
m_obb = new Vector3(x, y, z);
|
||||
|
||||
releaseBuildingMeshData();
|
||||
}
|
||||
public bool ToStream(Stream st)
|
||||
{
|
||||
if (m_indicesPtr == IntPtr.Zero || m_verticesPtr == IntPtr.Zero)
|
||||
return false;
|
||||
|
||||
BinaryWriter bw = new BinaryWriter(st);
|
||||
bool ok = true;
|
||||
|
||||
try
|
||||
{
|
||||
|
||||
bw.Write(m_vertexCount);
|
||||
bw.Write(m_indexCount);
|
||||
|
||||
for (int i = 0; i < 3 * m_vertexCount; i++)
|
||||
bw.Write(vertices[i]);
|
||||
for (int i = 0; i < m_indexCount; i++)
|
||||
bw.Write(indexes[i]);
|
||||
bw.Write(m_obb.X);
|
||||
bw.Write(m_obb.Y);
|
||||
bw.Write(m_obb.Z);
|
||||
bw.Write(m_obboffset.X);
|
||||
bw.Write(m_obboffset.Y);
|
||||
bw.Write(m_obboffset.Z);
|
||||
}
|
||||
catch
|
||||
{
|
||||
ok = false;
|
||||
}
|
||||
|
||||
if (bw != null)
|
||||
{
|
||||
bw.Flush();
|
||||
bw.Close();
|
||||
}
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
public static Mesh FromStream(Stream st, AMeshKey key)
|
||||
{
|
||||
Mesh mesh = new Mesh();
|
||||
mesh.releaseBuildingMeshData();
|
||||
|
||||
BinaryReader br = new BinaryReader(st);
|
||||
|
||||
bool ok = true;
|
||||
try
|
||||
{
|
||||
mesh.m_vertexCount = br.ReadInt32();
|
||||
mesh.m_indexCount = br.ReadInt32();
|
||||
|
||||
int n = 3 * mesh.m_vertexCount;
|
||||
mesh.vertices = new float[n];
|
||||
for (int i = 0; i < n; i++)
|
||||
mesh.vertices[i] = br.ReadSingle();
|
||||
|
||||
mesh.indexes = new int[mesh.m_indexCount];
|
||||
for (int i = 0; i < mesh.m_indexCount; i++)
|
||||
mesh.indexes[i] = br.ReadInt32();
|
||||
|
||||
mesh.m_obb.X = br.ReadSingle();
|
||||
mesh.m_obb.Y = br.ReadSingle();
|
||||
mesh.m_obb.Z = br.ReadSingle();
|
||||
|
||||
mesh.m_obboffset.X = br.ReadSingle();
|
||||
mesh.m_obboffset.Y = br.ReadSingle();
|
||||
mesh.m_obboffset.Z = br.ReadSingle();
|
||||
}
|
||||
catch
|
||||
{
|
||||
ok = false;
|
||||
}
|
||||
|
||||
br.Close();
|
||||
|
||||
if (ok)
|
||||
{
|
||||
mesh.pinMemory();
|
||||
|
||||
mesh.Key = key;
|
||||
mesh.RefCount = 1;
|
||||
|
||||
return mesh;
|
||||
}
|
||||
|
||||
mesh.vertices = null;
|
||||
mesh.indexes = null;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -42,6 +42,8 @@ using System.Reflection;
|
|||
using System.IO;
|
||||
using ComponentAce.Compression.Libs.zlib;
|
||||
using OpenSim.Region.Physics.ConvexDecompositionDotNet;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Runtime.Serialization.Formatters.Binary;
|
||||
|
||||
namespace OpenSim.Region.Physics.Meshing
|
||||
{
|
||||
|
@ -68,22 +70,22 @@ namespace OpenSim.Region.Physics.Meshing
|
|||
|
||||
// Setting baseDir to a path will enable the dumping of raw files
|
||||
// raw files can be imported by blender so a visual inspection of the results can be done
|
||||
#if SPAM
|
||||
const string baseDir = "rawFiles";
|
||||
#else
|
||||
|
||||
public object diskLock = new object();
|
||||
|
||||
public bool doMeshFileCache = true;
|
||||
|
||||
public string cachePath = "MeshCache";
|
||||
public TimeSpan CacheExpire;
|
||||
public bool doCacheExpire = true;
|
||||
|
||||
// const string baseDir = "rawFiles";
|
||||
private const string baseDir = null; //"rawFiles";
|
||||
#endif
|
||||
|
||||
private bool cacheSculptMaps = true;
|
||||
private bool cacheSculptAlphaMaps = true;
|
||||
|
||||
private string decodedSculptMapPath = null;
|
||||
private bool useMeshiesPhysicsMesh = false;
|
||||
|
||||
private float minSizeForComplexMesh = 0.2f; // prims with all dimensions smaller than this will have a bounding box mesh
|
||||
|
||||
// private Dictionary<ulong, Mesh> m_uniqueMeshes = new Dictionary<ulong, Mesh>();
|
||||
// private Dictionary<ulong, Mesh> m_uniqueReleasedMeshes = new Dictionary<ulong, Mesh>();
|
||||
private Dictionary<AMeshKey, Mesh> m_uniqueMeshes = new Dictionary<AMeshKey, Mesh>();
|
||||
private Dictionary<AMeshKey, Mesh> m_uniqueReleasedMeshes = new Dictionary<AMeshKey, Mesh>();
|
||||
|
||||
|
@ -92,29 +94,29 @@ namespace OpenSim.Region.Physics.Meshing
|
|||
IConfig start_config = config.Configs["Startup"];
|
||||
IConfig mesh_config = config.Configs["Mesh"];
|
||||
|
||||
decodedSculptMapPath = start_config.GetString("DecodedSculptMapPath","j2kDecodeCache");
|
||||
|
||||
cacheSculptMaps = start_config.GetBoolean("CacheSculptMaps", cacheSculptMaps);
|
||||
|
||||
if (Environment.OSVersion.Platform == PlatformID.Unix)
|
||||
{
|
||||
cacheSculptAlphaMaps = false;
|
||||
}
|
||||
else
|
||||
cacheSculptAlphaMaps = cacheSculptMaps;
|
||||
float fcache = 48.0f;
|
||||
// float fcache = 0.02f;
|
||||
|
||||
if(mesh_config != null)
|
||||
{
|
||||
useMeshiesPhysicsMesh = mesh_config.GetBoolean("UseMeshiesPhysicsMesh", useMeshiesPhysicsMesh);
|
||||
if (useMeshiesPhysicsMesh)
|
||||
{
|
||||
doMeshFileCache = mesh_config.GetBoolean("MeshFileCache", doMeshFileCache);
|
||||
cachePath = mesh_config.GetString("MeshFileCachePath", cachePath);
|
||||
fcache = mesh_config.GetFloat("MeshFileCacheExpireHours", fcache);
|
||||
doCacheExpire = mesh_config.GetBoolean("MeshFileCacheDoExpire", doCacheExpire);
|
||||
}
|
||||
else
|
||||
{
|
||||
doMeshFileCache = false;
|
||||
doCacheExpire = false;
|
||||
}
|
||||
}
|
||||
|
||||
CacheExpire = TimeSpan.FromHours(fcache);
|
||||
|
||||
try
|
||||
{
|
||||
if (!Directory.Exists(decodedSculptMapPath))
|
||||
Directory.CreateDirectory(decodedSculptMapPath);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
m_log.WarnFormat("[SCULPT]: Unable to create {0} directory: ", decodedSculptMapPath, e.Message);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -212,7 +214,7 @@ namespace OpenSim.Region.Physics.Meshing
|
|||
/// <param name="size">Size of entire object</param>
|
||||
/// <param name="coords"></param>
|
||||
/// <param name="faces"></param>
|
||||
private void AddSubMesh(OSDMap subMeshData, Vector3 size, List<Coord> coords, List<Face> faces)
|
||||
private void AddSubMesh(OSDMap subMeshData, List<Coord> coords, List<Face> faces)
|
||||
{
|
||||
// Console.WriteLine("subMeshMap for {0} - {1}", primName, Util.GetFormattedXml((OSD)subMeshMap));
|
||||
|
||||
|
@ -245,9 +247,9 @@ namespace OpenSim.Region.Physics.Meshing
|
|||
ushort uZ = Utils.BytesToUInt16(posBytes, i + 4);
|
||||
|
||||
Coord c = new Coord(
|
||||
Utils.UInt16ToFloat(uX, posMin.X, posMax.X) * size.X,
|
||||
Utils.UInt16ToFloat(uY, posMin.Y, posMax.Y) * size.Y,
|
||||
Utils.UInt16ToFloat(uZ, posMin.Z, posMax.Z) * size.Z);
|
||||
Utils.UInt16ToFloat(uX, posMin.X, posMax.X),
|
||||
Utils.UInt16ToFloat(uY, posMin.Y, posMax.Y),
|
||||
Utils.UInt16ToFloat(uZ, posMin.Z, posMax.Z));
|
||||
|
||||
coords.Add(c);
|
||||
}
|
||||
|
@ -271,7 +273,7 @@ namespace OpenSim.Region.Physics.Meshing
|
|||
/// <param name="size"></param>
|
||||
/// <param name="lod"></param>
|
||||
/// <returns></returns>
|
||||
private Mesh CreateMeshFromPrimMesher(string primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool convex)
|
||||
private Mesh CreateMeshFromPrimMesher(string primName, PrimitiveBaseShape primShape, float lod, bool convex)
|
||||
{
|
||||
// m_log.DebugFormat(
|
||||
// "[MESH]: Creating physics proxy for {0}, shape {1}",
|
||||
|
@ -287,18 +289,18 @@ namespace OpenSim.Region.Physics.Meshing
|
|||
if (!useMeshiesPhysicsMesh)
|
||||
return null;
|
||||
|
||||
if (!GenerateCoordsAndFacesFromPrimMeshData(primName, primShape, size, out coords, out faces, convex))
|
||||
if (!GenerateCoordsAndFacesFromPrimMeshData(primName, primShape, out coords, out faces, convex))
|
||||
return null;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!GenerateCoordsAndFacesFromPrimSculptData(primName, primShape, size, lod, out coords, out faces))
|
||||
if (!GenerateCoordsAndFacesFromPrimSculptData(primName, primShape, lod, out coords, out faces))
|
||||
return null;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!GenerateCoordsAndFacesFromPrimShapeData(primName, primShape, size, lod, out coords, out faces))
|
||||
if (!GenerateCoordsAndFacesFromPrimShapeData(primName, primShape, lod, out coords, out faces))
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -333,7 +335,7 @@ namespace OpenSim.Region.Physics.Meshing
|
|||
/// <param name="faces">Faces are added to this list by the method.</param>
|
||||
/// <returns>true if coords and faces were successfully generated, false if not</returns>
|
||||
private bool GenerateCoordsAndFacesFromPrimMeshData(
|
||||
string primName, PrimitiveBaseShape primShape, Vector3 size, out List<Coord> coords, out List<Face> faces, bool convex)
|
||||
string primName, PrimitiveBaseShape primShape, out List<Coord> coords, out List<Face> faces, bool convex)
|
||||
{
|
||||
// m_log.DebugFormat("[MESH]: experimental mesh proxy generation for {0}", primName);
|
||||
|
||||
|
@ -345,7 +347,7 @@ namespace OpenSim.Region.Physics.Meshing
|
|||
|
||||
if (primShape.SculptData.Length <= 0)
|
||||
{
|
||||
m_log.InfoFormat("[MESH]: asset data for {0} is zero length", primName);
|
||||
// m_log.InfoFormat("[MESH]: asset data for {0} is zero length", primName);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -406,7 +408,7 @@ namespace OpenSim.Region.Physics.Meshing
|
|||
OSD decodedMeshOsd = new OSD();
|
||||
byte[] meshBytes = new byte[physSize];
|
||||
System.Buffer.BlockCopy(primShape.SculptData, physOffset, meshBytes, 0, physSize);
|
||||
// byte[] decompressed = new byte[physSize * 5];
|
||||
|
||||
try
|
||||
{
|
||||
using (MemoryStream inMs = new MemoryStream(meshBytes))
|
||||
|
@ -444,13 +446,13 @@ namespace OpenSim.Region.Physics.Meshing
|
|||
// physics_shape is an array of OSDMaps, one for each submesh
|
||||
if (decodedMeshOsd is OSDArray)
|
||||
{
|
||||
// Console.WriteLine("decodedMeshOsd for {0} - {1}", primName, Util.GetFormattedXml(decodedMeshOsd));
|
||||
// Console.WriteLine("decodedMeshOsd for {0} - {1}", primName, Util.GetFormattedXml(decodedMeshOsd));
|
||||
|
||||
decodedMeshOsdArray = (OSDArray)decodedMeshOsd;
|
||||
foreach (OSD subMeshOsd in decodedMeshOsdArray)
|
||||
{
|
||||
if (subMeshOsd is OSDMap)
|
||||
AddSubMesh(subMeshOsd as OSDMap, size, coords, faces);
|
||||
AddSubMesh(subMeshOsd as OSDMap, coords, faces);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -522,9 +524,9 @@ namespace OpenSim.Region.Physics.Meshing
|
|||
t3 = data[ptr++];
|
||||
t3 += data[ptr++] << 8;
|
||||
|
||||
f3 = new float3((t1 * range.X + min.X) * size.X,
|
||||
(t2 * range.Y + min.Y) * size.Y,
|
||||
(t3 * range.Z + min.Z) * size.Z);
|
||||
f3 = new float3((t1 * range.X + min.X),
|
||||
(t2 * range.Y + min.Y),
|
||||
(t3 * range.Z + min.Z));
|
||||
vs.Add(f3);
|
||||
}
|
||||
|
||||
|
@ -621,9 +623,9 @@ namespace OpenSim.Region.Physics.Meshing
|
|||
t3 = data[i++];
|
||||
t3 += data[i++] << 8;
|
||||
|
||||
f3 = new float3((t1 * range.X + min.X) * size.X,
|
||||
(t2 * range.Y + min.Y) * size.Y,
|
||||
(t3 * range.Z + min.Z) * size.Z);
|
||||
f3 = new float3((t1 * range.X + min.X),
|
||||
(t2 * range.Y + min.Y),
|
||||
(t3 * range.Z + min.Z));
|
||||
vs.Add(f3);
|
||||
}
|
||||
|
||||
|
@ -711,35 +713,13 @@ namespace OpenSim.Region.Physics.Meshing
|
|||
/// <param name="faces">Faces are added to this list by the method.</param>
|
||||
/// <returns>true if coords and faces were successfully generated, false if not</returns>
|
||||
private bool GenerateCoordsAndFacesFromPrimSculptData(
|
||||
string primName, PrimitiveBaseShape primShape, Vector3 size, float lod, out List<Coord> coords, out List<Face> faces)
|
||||
string primName, PrimitiveBaseShape primShape, float lod, out List<Coord> coords, out List<Face> faces)
|
||||
{
|
||||
coords = new List<Coord>();
|
||||
faces = new List<Face>();
|
||||
PrimMesher.SculptMesh sculptMesh;
|
||||
Image idata = null;
|
||||
string decodedSculptFileName = "";
|
||||
|
||||
if (cacheSculptMaps && primShape.SculptTexture != UUID.Zero)
|
||||
{
|
||||
decodedSculptFileName = System.IO.Path.Combine(decodedSculptMapPath, "smap_" + primShape.SculptTexture.ToString());
|
||||
try
|
||||
{
|
||||
if (File.Exists(decodedSculptFileName))
|
||||
{
|
||||
idata = Image.FromFile(decodedSculptFileName);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
m_log.Error("[SCULPT]: unable to load cached sculpt map " + decodedSculptFileName + " " + e.Message);
|
||||
|
||||
}
|
||||
//if (idata != null)
|
||||
// m_log.Debug("[SCULPT]: loaded cached map asset for map ID: " + primShape.SculptTexture.ToString());
|
||||
}
|
||||
|
||||
if (idata == null)
|
||||
{
|
||||
if (primShape.SculptData == null || primShape.SculptData.Length == 0)
|
||||
return false;
|
||||
|
||||
|
@ -748,25 +728,15 @@ namespace OpenSim.Region.Physics.Meshing
|
|||
OpenMetaverse.Imaging.ManagedImage unusedData;
|
||||
OpenMetaverse.Imaging.OpenJPEG.DecodeToImage(primShape.SculptData, out unusedData, out idata);
|
||||
|
||||
unusedData = null;
|
||||
|
||||
if (idata == null)
|
||||
{
|
||||
// In some cases it seems that the decode can return a null bitmap without throwing
|
||||
// an exception
|
||||
m_log.WarnFormat("[PHYSICS]: OpenJPEG decoded sculpt data for {0} to a null bitmap. Ignoring.", primName);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
unusedData = null;
|
||||
|
||||
//idata = CSJ2K.J2kImage.FromBytes(primShape.SculptData);
|
||||
|
||||
if (cacheSculptMaps && (cacheSculptAlphaMaps || (((ImageFlags)(idata.Flags) & ImageFlags.HasAlpha) ==0)))
|
||||
// don't cache images with alpha channel in linux since mono can't load them correctly)
|
||||
{
|
||||
try { idata.Save(decodedSculptFileName, ImageFormat.MemoryBmp); }
|
||||
catch (Exception e) { m_log.Error("[SCULPT]: unable to cache sculpt map " + decodedSculptFileName + " " + e.Message); }
|
||||
}
|
||||
}
|
||||
catch (DllNotFoundException)
|
||||
{
|
||||
|
@ -783,7 +753,6 @@ namespace OpenSim.Region.Physics.Meshing
|
|||
m_log.Error("[PHYSICS]: Unable to generate a Sculpty physics proxy. Sculpty texture decode failed: " + ex.Message);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
PrimMesher.SculptMesh.SculptType sculptType;
|
||||
// remove mirror and invert bits
|
||||
|
@ -814,9 +783,7 @@ namespace OpenSim.Region.Physics.Meshing
|
|||
|
||||
idata.Dispose();
|
||||
|
||||
sculptMesh.DumpRaw(baseDir, primName, "primMesh");
|
||||
|
||||
sculptMesh.Scale(size.X, size.Y, size.Z);
|
||||
// sculptMesh.DumpRaw(baseDir, primName, "primMesh");
|
||||
|
||||
coords = sculptMesh.coords;
|
||||
faces = sculptMesh.faces;
|
||||
|
@ -834,7 +801,7 @@ namespace OpenSim.Region.Physics.Meshing
|
|||
/// <param name="faces">Faces are added to this list by the method.</param>
|
||||
/// <returns>true if coords and faces were successfully generated, false if not</returns>
|
||||
private bool GenerateCoordsAndFacesFromPrimShapeData(
|
||||
string primName, PrimitiveBaseShape primShape, Vector3 size, float lod, out List<Coord> coords, out List<Face> faces)
|
||||
string primName, PrimitiveBaseShape primShape, float lod, out List<Coord> coords, out List<Face> faces)
|
||||
{
|
||||
PrimMesh primMesh;
|
||||
coords = new List<Coord>();
|
||||
|
@ -969,9 +936,7 @@ namespace OpenSim.Region.Physics.Meshing
|
|||
}
|
||||
}
|
||||
|
||||
primMesh.DumpRaw(baseDir, primName, "primMesh");
|
||||
|
||||
primMesh.Scale(size.X, size.Y, size.Z);
|
||||
// primMesh.DumpRaw(baseDir, primName, "primMesh");
|
||||
|
||||
coords = primMesh.coords;
|
||||
faces = primMesh.faces;
|
||||
|
@ -985,12 +950,14 @@ namespace OpenSim.Region.Physics.Meshing
|
|||
Byte[] someBytes;
|
||||
|
||||
key.hashB = 5181;
|
||||
key.hashC = 5181;
|
||||
ulong hash = 5381;
|
||||
|
||||
if (primShape.SculptEntry)
|
||||
{
|
||||
key.uuid = primShape.SculptTexture;
|
||||
key.hashB = mdjb2(key.hashB, primShape.SculptType);
|
||||
key.hashC = mdjb2(key.hashC, primShape.SculptType);
|
||||
key.hashC = mdjb2(key.hashC, primShape.PCode);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1002,6 +969,8 @@ namespace OpenSim.Region.Physics.Meshing
|
|||
hash = mdjb2(hash, primShape.PathScaleX);
|
||||
hash = mdjb2(hash, primShape.PathScaleY);
|
||||
hash = mdjb2(hash, primShape.PathShearX);
|
||||
key.hashA = hash;
|
||||
hash = key.hashB;
|
||||
hash = mdjb2(hash, primShape.PathShearY);
|
||||
hash = mdjb2(hash, (byte)primShape.PathTwist);
|
||||
hash = mdjb2(hash, (byte)primShape.PathTwistBegin);
|
||||
|
@ -1013,26 +982,38 @@ namespace OpenSim.Region.Physics.Meshing
|
|||
hash = mdjb2(hash, primShape.ProfileBegin);
|
||||
hash = mdjb2(hash, primShape.ProfileEnd);
|
||||
hash = mdjb2(hash, primShape.ProfileHollow);
|
||||
key.hashA = hash;
|
||||
hash = mdjb2(hash, primShape.PCode);
|
||||
key.hashB = hash;
|
||||
}
|
||||
|
||||
hash = key.hashB;
|
||||
|
||||
someBytes = size.GetBytes();
|
||||
for (int i = 0; i < someBytes.Length; i++)
|
||||
hash = mdjb2(hash, someBytes[i]);
|
||||
hash = key.hashC;
|
||||
|
||||
hash = mdjb2(hash, lod);
|
||||
|
||||
hash &= 0x3fffffffffffffff;
|
||||
if (size == m_MeshUnitSize)
|
||||
{
|
||||
hash = hash << 8;
|
||||
hash |= 8;
|
||||
}
|
||||
else
|
||||
{
|
||||
someBytes = size.GetBytes();
|
||||
for (int i = 0; i < someBytes.Length; i++)
|
||||
hash = mdjb2(hash, someBytes[i]);
|
||||
hash = hash << 8;
|
||||
}
|
||||
|
||||
if (convex)
|
||||
hash |= 0x4000000000000000;
|
||||
hash |= 4;
|
||||
|
||||
if (primShape.SculptEntry)
|
||||
hash |= 0x8000000000000000;
|
||||
{
|
||||
hash |= 1;
|
||||
if (primShape.SculptType == (byte)SculptType.Mesh)
|
||||
hash |= 2;
|
||||
}
|
||||
|
||||
key.hashB = hash;
|
||||
key.hashC = hash;
|
||||
|
||||
return key;
|
||||
}
|
||||
|
@ -1048,35 +1029,74 @@ namespace OpenSim.Region.Physics.Meshing
|
|||
return ((hash << 5) + hash) + (ulong)(c >> 8);
|
||||
}
|
||||
|
||||
|
||||
public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod)
|
||||
{
|
||||
return CreateMesh(primName, primShape, size, lod, false,false);
|
||||
return CreateMesh(primName, primShape, size, lod, false,false,false);
|
||||
}
|
||||
|
||||
public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical)
|
||||
{
|
||||
return CreateMesh(primName, primShape, size, lod, false,false);
|
||||
return CreateMesh(primName, primShape, size, lod, false,false,false);
|
||||
}
|
||||
|
||||
private static Vector3 m_MeshUnitSize = new Vector3(0.5f, 0.5f, 0.5f);
|
||||
public IMesh GetMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical, bool convex)
|
||||
{
|
||||
Mesh mesh = null;
|
||||
|
||||
public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical, bool convex)
|
||||
if (size.X < 0.01f) size.X = 0.01f;
|
||||
if (size.Y < 0.01f) size.Y = 0.01f;
|
||||
if (size.Z < 0.01f) size.Z = 0.01f;
|
||||
|
||||
AMeshKey key = GetMeshUniqueKey(primShape, size, (byte)lod, convex);
|
||||
lock (m_uniqueMeshes)
|
||||
{
|
||||
m_uniqueMeshes.TryGetValue(key, out mesh);
|
||||
|
||||
if (mesh != null)
|
||||
{
|
||||
mesh.RefCount++;
|
||||
return mesh;
|
||||
}
|
||||
}
|
||||
|
||||
// try to find a identical mesh on meshs recently released
|
||||
lock (m_uniqueReleasedMeshes)
|
||||
{
|
||||
m_uniqueReleasedMeshes.TryGetValue(key, out mesh);
|
||||
if (mesh != null)
|
||||
{
|
||||
m_uniqueReleasedMeshes.Remove(key);
|
||||
lock (m_uniqueMeshes)
|
||||
{
|
||||
try
|
||||
{
|
||||
m_uniqueMeshes.Add(key, mesh);
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
mesh.RefCount = 1;
|
||||
return mesh;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static Vector3 m_MeshUnitSize = new Vector3(1.0f, 1.0f, 1.0f);
|
||||
|
||||
public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical, bool convex, bool forOde)
|
||||
{
|
||||
#if SPAM
|
||||
m_log.DebugFormat("[MESH]: Creating mesh for {0}", primName);
|
||||
#endif
|
||||
|
||||
Mesh mesh = null;
|
||||
// ulong key = 0;
|
||||
|
||||
|
||||
if (size.X < 0.01f) size.X = 0.01f;
|
||||
if (size.Y < 0.01f) size.Y = 0.01f;
|
||||
if (size.Z < 0.01f) size.Z = 0.01f;
|
||||
|
||||
// try to find a identical mesh on meshs in use
|
||||
// key = primShape.GetMeshKey(size, lod, convex);
|
||||
|
||||
AMeshKey key = GetMeshUniqueKey(primShape,size,(byte)lod, convex);
|
||||
|
||||
lock (m_uniqueMeshes)
|
||||
|
@ -1098,33 +1118,76 @@ namespace OpenSim.Region.Physics.Meshing
|
|||
{
|
||||
m_uniqueReleasedMeshes.Remove(key);
|
||||
lock (m_uniqueMeshes)
|
||||
m_uniqueMeshes.Add(key, mesh);
|
||||
{
|
||||
try
|
||||
{
|
||||
m_uniqueMeshes.Add(key, mesh);
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
mesh.RefCount = 1;
|
||||
return mesh;
|
||||
}
|
||||
}
|
||||
|
||||
mesh = CreateMeshFromPrimMesher(primName, primShape, size, lod,convex);
|
||||
Mesh UnitMesh = null;
|
||||
AMeshKey unitKey = GetMeshUniqueKey(primShape, m_MeshUnitSize, (byte)lod, convex);
|
||||
|
||||
if (mesh != null)
|
||||
lock (m_uniqueReleasedMeshes)
|
||||
{
|
||||
if ((!isPhysical) && size.X < minSizeForComplexMesh && size.Y < minSizeForComplexMesh && size.Z < minSizeForComplexMesh)
|
||||
m_uniqueReleasedMeshes.TryGetValue(unitKey, out UnitMesh);
|
||||
if (UnitMesh != null)
|
||||
{
|
||||
#if SPAM
|
||||
m_log.Debug("Meshmerizer: prim " + primName + " has a size of " + size.ToString() + " which is below threshold of " +
|
||||
minSizeForComplexMesh.ToString() + " - creating simple bounding box");
|
||||
#endif
|
||||
mesh = CreateBoundingBoxMesh(mesh);
|
||||
mesh.DumpRaw(baseDir, primName, "Z extruded");
|
||||
UnitMesh.RefCount = 1;
|
||||
}
|
||||
}
|
||||
|
||||
// trim the vertex and triangle lists to free up memory
|
||||
mesh.TrimExcess();
|
||||
mesh.Key = key;
|
||||
mesh.RefCount = 1;
|
||||
if (UnitMesh == null && primShape.SculptEntry && doMeshFileCache)
|
||||
UnitMesh = GetFromFileCache(unitKey);
|
||||
|
||||
lock(m_uniqueMeshes)
|
||||
if (UnitMesh == null)
|
||||
{
|
||||
UnitMesh = CreateMeshFromPrimMesher(primName, primShape, lod, convex);
|
||||
|
||||
if (UnitMesh == null)
|
||||
return null;
|
||||
|
||||
UnitMesh.DumpRaw(baseDir, unitKey.ToString(), "Z");
|
||||
|
||||
if (forOde)
|
||||
{
|
||||
// force pinned mem allocation
|
||||
UnitMesh.PrepForOde();
|
||||
}
|
||||
else
|
||||
UnitMesh.TrimExcess();
|
||||
|
||||
UnitMesh.Key = unitKey;
|
||||
UnitMesh.RefCount = 1;
|
||||
|
||||
if (doMeshFileCache && primShape.SculptEntry)
|
||||
StoreToFileCache(unitKey, UnitMesh);
|
||||
|
||||
lock (m_uniqueReleasedMeshes)
|
||||
{
|
||||
try
|
||||
{
|
||||
m_uniqueReleasedMeshes.Add(unitKey, UnitMesh);
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
}
|
||||
|
||||
mesh = UnitMesh.Scale(size);
|
||||
mesh.Key = key;
|
||||
mesh.RefCount = 1;
|
||||
lock (m_uniqueMeshes)
|
||||
{
|
||||
try
|
||||
{
|
||||
m_uniqueMeshes.Add(key, mesh);
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
return mesh;
|
||||
|
@ -1137,21 +1200,27 @@ namespace OpenSim.Region.Physics.Meshing
|
|||
|
||||
Mesh mesh = (Mesh)imesh;
|
||||
|
||||
int curRefCount = mesh.RefCount;
|
||||
curRefCount--;
|
||||
|
||||
if (curRefCount > 0)
|
||||
{
|
||||
mesh.RefCount = curRefCount;
|
||||
return;
|
||||
}
|
||||
|
||||
lock (m_uniqueMeshes)
|
||||
{
|
||||
int curRefCount = mesh.RefCount;
|
||||
curRefCount--;
|
||||
|
||||
if (curRefCount > 0)
|
||||
{
|
||||
mesh.RefCount = curRefCount;
|
||||
return;
|
||||
}
|
||||
|
||||
mesh.RefCount = 0;
|
||||
m_uniqueMeshes.Remove(mesh.Key);
|
||||
lock (m_uniqueReleasedMeshes)
|
||||
m_uniqueReleasedMeshes.Add(mesh.Key, mesh);
|
||||
{
|
||||
try
|
||||
{
|
||||
m_uniqueReleasedMeshes.Add(mesh.Key, mesh);
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1178,10 +1247,170 @@ namespace OpenSim.Region.Physics.Meshing
|
|||
foreach (Mesh m in meshstodelete)
|
||||
{
|
||||
m_uniqueReleasedMeshes.Remove(m.Key);
|
||||
m.releaseSourceMeshData();
|
||||
m.releaseBuildingMeshData();
|
||||
m.releasePinned();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void FileNames(AMeshKey key, out string dir,out string fullFileName)
|
||||
{
|
||||
string id = key.ToString();
|
||||
string init = id.Substring(0, 1);
|
||||
dir = System.IO.Path.Combine(cachePath, init);
|
||||
fullFileName = System.IO.Path.Combine(dir, id);
|
||||
}
|
||||
|
||||
public string FullFileName(AMeshKey key)
|
||||
{
|
||||
string id = key.ToString();
|
||||
string init = id.Substring(0,1);
|
||||
id = System.IO.Path.Combine(init, id);
|
||||
id = System.IO.Path.Combine(cachePath, id);
|
||||
return id;
|
||||
}
|
||||
|
||||
private Mesh GetFromFileCache(AMeshKey key)
|
||||
{
|
||||
Mesh mesh = null;
|
||||
string filename = FullFileName(key);
|
||||
bool ok = true;
|
||||
|
||||
lock (diskLock)
|
||||
{
|
||||
if (File.Exists(filename))
|
||||
{
|
||||
FileStream stream = null;
|
||||
try
|
||||
{
|
||||
stream = File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.Read);
|
||||
BinaryFormatter bformatter = new BinaryFormatter();
|
||||
|
||||
mesh = Mesh.FromStream(stream, key);
|
||||
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
ok = false;
|
||||
m_log.ErrorFormat(
|
||||
"[MESH CACHE]: Failed to get file {0}. Exception {1} {2}",
|
||||
filename, e.Message, e.StackTrace);
|
||||
}
|
||||
|
||||
if (stream != null)
|
||||
stream.Close();
|
||||
|
||||
if (mesh == null || !ok)
|
||||
File.Delete(filename);
|
||||
else
|
||||
File.SetLastAccessTimeUtc(filename, DateTime.UtcNow);
|
||||
}
|
||||
}
|
||||
|
||||
return mesh;
|
||||
}
|
||||
|
||||
private void StoreToFileCache(AMeshKey key, Mesh mesh)
|
||||
{
|
||||
Stream stream = null;
|
||||
bool ok = false;
|
||||
|
||||
// Make sure the target cache directory exists
|
||||
string dir = String.Empty;
|
||||
string filename = String.Empty;
|
||||
|
||||
FileNames(key, out dir, out filename);
|
||||
|
||||
lock (diskLock)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!Directory.Exists(dir))
|
||||
{
|
||||
Directory.CreateDirectory(dir);
|
||||
}
|
||||
|
||||
stream = File.Open(filename, FileMode.Create);
|
||||
ok = mesh.ToStream(stream);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
m_log.ErrorFormat(
|
||||
"[MESH CACHE]: Failed to write file {0}. Exception {1} {2}.",
|
||||
filename, e.Message, e.StackTrace);
|
||||
ok = false;
|
||||
}
|
||||
|
||||
if (stream != null)
|
||||
stream.Close();
|
||||
|
||||
if (File.Exists(filename))
|
||||
{
|
||||
if (ok)
|
||||
File.SetLastAccessTimeUtc(filename, DateTime.UtcNow);
|
||||
else
|
||||
File.Delete(filename);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void ExpireFileCache()
|
||||
{
|
||||
if (!doCacheExpire)
|
||||
return;
|
||||
|
||||
string controlfile = System.IO.Path.Combine(cachePath, "cntr");
|
||||
|
||||
lock (diskLock)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (File.Exists(controlfile))
|
||||
{
|
||||
int ndeleted = 0;
|
||||
int totalfiles = 0;
|
||||
int ndirs = 0;
|
||||
DateTime OlderTime = File.GetLastAccessTimeUtc(controlfile) - CacheExpire;
|
||||
File.SetLastAccessTimeUtc(controlfile, DateTime.UtcNow);
|
||||
|
||||
foreach (string dir in Directory.GetDirectories(cachePath))
|
||||
{
|
||||
try
|
||||
{
|
||||
foreach (string file in Directory.GetFiles(dir))
|
||||
{
|
||||
try
|
||||
{
|
||||
if (File.GetLastAccessTimeUtc(file) < OlderTime)
|
||||
{
|
||||
File.Delete(file);
|
||||
ndeleted++;
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
totalfiles++;
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
ndirs++;
|
||||
}
|
||||
|
||||
if (ndeleted == 0)
|
||||
m_log.InfoFormat("[MESH CACHE]: {0} Files in {1} cache folders, no expires",
|
||||
totalfiles,ndirs);
|
||||
else
|
||||
m_log.InfoFormat("[MESH CACHE]: {0} Files in {1} cache folders, expired {2} files accessed before {3}",
|
||||
totalfiles,ndirs, ndeleted, OlderTime.ToString());
|
||||
}
|
||||
else
|
||||
{
|
||||
m_log.Info("[MESH CACHE]: Expire delayed to next startup");
|
||||
FileStream fs = File.Create(controlfile,4096,FileOptions.WriteThrough);
|
||||
fs.Close();
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -172,7 +172,6 @@ namespace OpenSim.Region.Physics.OdePlugin
|
|||
// force lower density for testing
|
||||
m_density = 3.0f;
|
||||
|
||||
|
||||
mu = parent_scene.AvatarFriction;
|
||||
|
||||
walkDivisor = walk_divisor;
|
||||
|
|
|
@ -0,0 +1,931 @@
|
|||
/*
|
||||
* AJLDuarte 2012
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using OpenSim.Framework;
|
||||
using OpenSim.Region.Physics.Manager;
|
||||
using OdeAPI;
|
||||
using log4net;
|
||||
using Nini.Config;
|
||||
using OpenMetaverse;
|
||||
|
||||
namespace OpenSim.Region.Physics.OdePlugin
|
||||
{
|
||||
public enum MeshState : byte
|
||||
{
|
||||
noNeed = 0,
|
||||
|
||||
loadingAsset = 1,
|
||||
|
||||
AssetOK = 0x0f, // 00001111
|
||||
|
||||
NeedMask = 0x30, // 00110000
|
||||
needMesh = 0x10, // 00010000
|
||||
needAsset = 0x20, // 00100000
|
||||
|
||||
FailMask = 0xC0, // 11000000
|
||||
AssetFailed = 0x40, // 01000000
|
||||
MeshFailed = 0x80, // 10000000
|
||||
|
||||
MeshNoColide = FailMask | needAsset
|
||||
}
|
||||
|
||||
public enum meshWorkerCmnds : byte
|
||||
{
|
||||
nop = 0,
|
||||
addnew,
|
||||
changefull,
|
||||
changesize,
|
||||
changeshapetype,
|
||||
getmesh,
|
||||
}
|
||||
|
||||
public class ODEPhysRepData
|
||||
{
|
||||
public PhysicsActor actor;
|
||||
public PrimitiveBaseShape pbs;
|
||||
public IMesh mesh;
|
||||
|
||||
public Vector3 size;
|
||||
public Vector3 OBB;
|
||||
public Vector3 OBBOffset;
|
||||
|
||||
public float volume;
|
||||
|
||||
public byte shapetype;
|
||||
public bool hasOBB;
|
||||
public bool hasMeshVolume;
|
||||
public MeshState meshState;
|
||||
public UUID? assetID;
|
||||
public meshWorkerCmnds comand;
|
||||
}
|
||||
|
||||
public class ODEMeshWorker
|
||||
{
|
||||
|
||||
private ILog m_log;
|
||||
private OdeScene m_scene;
|
||||
private IMesher m_mesher;
|
||||
|
||||
public bool meshSculptedPrim = true;
|
||||
public bool forceSimplePrimMeshing = false;
|
||||
public float meshSculptLOD = 32;
|
||||
public float MeshSculptphysicalLOD = 32;
|
||||
|
||||
|
||||
private OpenSim.Framework.BlockingQueue<ODEPhysRepData> createqueue = new OpenSim.Framework.BlockingQueue<ODEPhysRepData>();
|
||||
private bool m_running;
|
||||
|
||||
private Thread m_thread;
|
||||
|
||||
public ODEMeshWorker(OdeScene pScene, ILog pLog, IMesher pMesher, IConfig pConfig)
|
||||
{
|
||||
m_scene = pScene;
|
||||
m_log = pLog;
|
||||
m_mesher = pMesher;
|
||||
|
||||
if (pConfig != null)
|
||||
{
|
||||
forceSimplePrimMeshing = pConfig.GetBoolean("force_simple_prim_meshing", forceSimplePrimMeshing);
|
||||
meshSculptedPrim = pConfig.GetBoolean("mesh_sculpted_prim", meshSculptedPrim);
|
||||
meshSculptLOD = pConfig.GetFloat("mesh_lod", meshSculptLOD);
|
||||
MeshSculptphysicalLOD = pConfig.GetFloat("mesh_physical_lod", MeshSculptphysicalLOD);
|
||||
}
|
||||
m_running = true;
|
||||
m_thread = new Thread(DoWork);
|
||||
m_thread.Start();
|
||||
}
|
||||
|
||||
private void DoWork()
|
||||
{
|
||||
m_mesher.ExpireFileCache();
|
||||
|
||||
while(m_running)
|
||||
{
|
||||
ODEPhysRepData nextRep = createqueue.Dequeue();
|
||||
if(!m_running)
|
||||
return;
|
||||
if (nextRep == null)
|
||||
continue;
|
||||
if (m_scene.haveActor(nextRep.actor))
|
||||
{
|
||||
switch (nextRep.comand)
|
||||
{
|
||||
case meshWorkerCmnds.changefull:
|
||||
case meshWorkerCmnds.changeshapetype:
|
||||
case meshWorkerCmnds.changesize:
|
||||
GetMesh(nextRep);
|
||||
if (CreateActorPhysRep(nextRep) && m_scene.haveActor(nextRep.actor))
|
||||
m_scene.AddChange(nextRep.actor, changes.PhysRepData, nextRep);
|
||||
break;
|
||||
case meshWorkerCmnds.getmesh:
|
||||
DoRepDataGetMesh(nextRep);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Stop()
|
||||
{
|
||||
try
|
||||
{
|
||||
m_thread.Abort();
|
||||
createqueue.Clear();
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public void ChangeActorPhysRep(PhysicsActor actor, PrimitiveBaseShape pbs,
|
||||
Vector3 size, byte shapetype)
|
||||
{
|
||||
ODEPhysRepData repData = new ODEPhysRepData();
|
||||
repData.actor = actor;
|
||||
repData.pbs = pbs;
|
||||
repData.size = size;
|
||||
repData.shapetype = shapetype;
|
||||
|
||||
CheckMesh(repData);
|
||||
CalcVolumeData(repData);
|
||||
m_scene.AddChange(actor, changes.PhysRepData, repData);
|
||||
return;
|
||||
}
|
||||
|
||||
public ODEPhysRepData NewActorPhysRep(PhysicsActor actor, PrimitiveBaseShape pbs,
|
||||
Vector3 size, byte shapetype)
|
||||
{
|
||||
ODEPhysRepData repData = new ODEPhysRepData();
|
||||
repData.actor = actor;
|
||||
repData.pbs = pbs;
|
||||
repData.size = size;
|
||||
repData.shapetype = shapetype;
|
||||
|
||||
CheckMesh(repData);
|
||||
CalcVolumeData(repData);
|
||||
m_scene.AddChange(actor, changes.AddPhysRep, repData);
|
||||
return repData;
|
||||
}
|
||||
|
||||
public void RequestMesh(ODEPhysRepData repData)
|
||||
{
|
||||
repData.mesh = null;
|
||||
|
||||
if (repData.meshState == MeshState.needAsset)
|
||||
{
|
||||
PrimitiveBaseShape pbs = repData.pbs;
|
||||
|
||||
// check if we got outdated
|
||||
|
||||
if (!pbs.SculptEntry || pbs.SculptTexture == UUID.Zero)
|
||||
{
|
||||
repData.meshState = MeshState.noNeed;
|
||||
return;
|
||||
}
|
||||
|
||||
repData.assetID = pbs.SculptTexture;
|
||||
repData.meshState = MeshState.loadingAsset;
|
||||
|
||||
repData.comand = meshWorkerCmnds.getmesh;
|
||||
createqueue.Enqueue(repData);
|
||||
}
|
||||
}
|
||||
|
||||
// creates and prepares a mesh to use and calls parameters estimation
|
||||
public bool CreateActorPhysRep(ODEPhysRepData repData)
|
||||
{
|
||||
IMesh mesh = repData.mesh;
|
||||
|
||||
if (mesh != null)
|
||||
{
|
||||
IntPtr vertices, indices;
|
||||
int vertexCount, indexCount;
|
||||
int vertexStride, triStride;
|
||||
|
||||
mesh.getVertexListAsPtrToFloatArray(out vertices, out vertexStride, out vertexCount);
|
||||
mesh.getIndexListAsPtrToIntArray(out indices, out triStride, out indexCount);
|
||||
|
||||
if (vertexCount == 0 || indexCount == 0)
|
||||
{
|
||||
m_log.WarnFormat("[PHYSICS]: Invalid mesh data on prim {0} mesh UUID {1}",
|
||||
repData.actor.Name, repData.pbs.SculptTexture.ToString());
|
||||
repData.meshState = MeshState.MeshFailed;
|
||||
repData.hasOBB = false;
|
||||
repData.mesh = null;
|
||||
m_scene.mesher.ReleaseMesh(mesh);
|
||||
}
|
||||
else
|
||||
{
|
||||
repData.OBBOffset = mesh.GetCentroid();
|
||||
repData.OBB = mesh.GetOBB();
|
||||
repData.hasOBB = true;
|
||||
mesh.releaseSourceMeshData();
|
||||
}
|
||||
}
|
||||
CalcVolumeData(repData);
|
||||
return true;
|
||||
}
|
||||
|
||||
public void AssetLoaded(ODEPhysRepData repData)
|
||||
{
|
||||
if (m_scene.haveActor(repData.actor))
|
||||
{
|
||||
if (needsMeshing(repData.pbs)) // no need for pbs now?
|
||||
{
|
||||
repData.comand = meshWorkerCmnds.changefull;
|
||||
createqueue.Enqueue(repData);
|
||||
}
|
||||
}
|
||||
else
|
||||
repData.pbs.SculptData = Utils.EmptyBytes;
|
||||
}
|
||||
|
||||
public void DoRepDataGetMesh(ODEPhysRepData repData)
|
||||
{
|
||||
if (!repData.pbs.SculptEntry)
|
||||
return;
|
||||
|
||||
if (repData.meshState != MeshState.loadingAsset)
|
||||
return;
|
||||
|
||||
if (repData.assetID == null || repData.assetID == UUID.Zero)
|
||||
return;
|
||||
|
||||
if (repData.assetID != repData.pbs.SculptTexture)
|
||||
return;
|
||||
|
||||
// check if it is in cache
|
||||
GetMesh(repData);
|
||||
if (repData.meshState != MeshState.needAsset)
|
||||
{
|
||||
CreateActorPhysRep(repData);
|
||||
m_scene.AddChange(repData.actor, changes.PhysRepData, repData);
|
||||
return;
|
||||
}
|
||||
|
||||
RequestAssetDelegate assetProvider = m_scene.RequestAssetMethod;
|
||||
if (assetProvider == null)
|
||||
return;
|
||||
ODEAssetRequest asr = new ODEAssetRequest(this, assetProvider, repData, m_log);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Routine to figure out if we need to mesh this prim with our mesher
|
||||
/// </summary>
|
||||
/// <param name="pbs"></param>
|
||||
/// <returns></returns>
|
||||
public bool needsMeshing(PrimitiveBaseShape pbs)
|
||||
{
|
||||
// check sculpts or meshs
|
||||
if (pbs.SculptEntry)
|
||||
{
|
||||
if (meshSculptedPrim)
|
||||
return true;
|
||||
|
||||
if (pbs.SculptType == (byte)SculptType.Mesh) // always do meshs
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (forceSimplePrimMeshing)
|
||||
return true;
|
||||
|
||||
// if it's a standard box or sphere with no cuts, hollows, twist or top shear, return false since ODE can use an internal representation for the prim
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
// following code doesn't give meshs to boxes and spheres ever
|
||||
// and it's odd.. so for now just return true if asked to force meshs
|
||||
// hopefully mesher will fail if doesn't suport so things still get basic boxes
|
||||
|
||||
int iPropertiesNotSupportedDefault = 0;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
// see if we need a mesh and if so if we have a cached one
|
||||
// called with a new repData
|
||||
public void CheckMesh(ODEPhysRepData repData)
|
||||
{
|
||||
PhysicsActor actor = repData.actor;
|
||||
PrimitiveBaseShape pbs = repData.pbs;
|
||||
|
||||
if (!needsMeshing(pbs))
|
||||
{
|
||||
repData.meshState = MeshState.noNeed;
|
||||
return;
|
||||
}
|
||||
|
||||
IMesh mesh = null;
|
||||
|
||||
Vector3 size = repData.size;
|
||||
byte shapetype = repData.shapetype;
|
||||
|
||||
bool convex;
|
||||
|
||||
int clod = (int)LevelOfDetail.High;
|
||||
if (shapetype == 0)
|
||||
convex = false;
|
||||
else
|
||||
{
|
||||
convex = true;
|
||||
if (pbs.SculptType != (byte)SculptType.Mesh)
|
||||
clod = (int)LevelOfDetail.Low;
|
||||
}
|
||||
|
||||
mesh = m_mesher.GetMesh(actor.Name, pbs, size, clod, true, convex);
|
||||
|
||||
if (mesh == null)
|
||||
{
|
||||
if (pbs.SculptEntry)
|
||||
{
|
||||
if (pbs.SculptTexture != null && pbs.SculptTexture != UUID.Zero)
|
||||
{
|
||||
repData.assetID = pbs.SculptTexture;
|
||||
repData.meshState = MeshState.needAsset;
|
||||
}
|
||||
else
|
||||
repData.meshState = MeshState.MeshFailed;
|
||||
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
repData.meshState = MeshState.needMesh;
|
||||
mesh = m_mesher.CreateMesh(actor.Name, pbs, size, clod, true, convex, true);
|
||||
if (mesh == null)
|
||||
{
|
||||
repData.meshState = MeshState.MeshFailed;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
repData.meshState = MeshState.AssetOK;
|
||||
repData.mesh = mesh;
|
||||
|
||||
if (pbs.SculptEntry)
|
||||
{
|
||||
repData.assetID = pbs.SculptTexture;
|
||||
}
|
||||
|
||||
pbs.SculptData = Utils.EmptyBytes;
|
||||
return ;
|
||||
}
|
||||
|
||||
public void GetMesh(ODEPhysRepData repData)
|
||||
{
|
||||
PhysicsActor actor = repData.actor;
|
||||
|
||||
PrimitiveBaseShape pbs = repData.pbs;
|
||||
|
||||
repData.mesh = null;
|
||||
repData.hasOBB = false;
|
||||
|
||||
if (!needsMeshing(pbs))
|
||||
{
|
||||
repData.meshState = MeshState.noNeed;
|
||||
return;
|
||||
}
|
||||
|
||||
if (repData.meshState == MeshState.MeshFailed)
|
||||
return;
|
||||
|
||||
if (pbs.SculptEntry)
|
||||
{
|
||||
if (repData.meshState == MeshState.AssetFailed)
|
||||
{
|
||||
if (pbs.SculptTexture == repData.assetID)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
repData.meshState = MeshState.noNeed;
|
||||
|
||||
IMesh mesh = null;
|
||||
Vector3 size = repData.size;
|
||||
byte shapetype = repData.shapetype;
|
||||
|
||||
bool convex;
|
||||
int clod = (int)LevelOfDetail.High;
|
||||
if (shapetype == 0)
|
||||
convex = false;
|
||||
else
|
||||
{
|
||||
convex = true;
|
||||
if (pbs.SculptType != (byte)SculptType.Mesh)
|
||||
clod = (int)LevelOfDetail.Low;
|
||||
}
|
||||
|
||||
mesh = m_mesher.CreateMesh(actor.Name, pbs, size, clod, true, convex, true);
|
||||
|
||||
if (mesh == null)
|
||||
{
|
||||
if (pbs.SculptEntry)
|
||||
{
|
||||
if (pbs.SculptTexture == UUID.Zero)
|
||||
return;
|
||||
|
||||
repData.assetID = pbs.SculptTexture;
|
||||
|
||||
if (pbs.SculptData == null || pbs.SculptData.Length == 0)
|
||||
{
|
||||
repData.meshState = MeshState.needAsset;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
repData.mesh = mesh;
|
||||
repData.pbs.SculptData = Utils.EmptyBytes;
|
||||
|
||||
if (mesh == null)
|
||||
{
|
||||
if (pbs.SculptEntry)
|
||||
repData.meshState = MeshState.AssetFailed;
|
||||
else
|
||||
repData.meshState = MeshState.MeshFailed;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
repData.meshState = MeshState.AssetOK;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
private void CalculateBasicPrimVolume(ODEPhysRepData repData)
|
||||
{
|
||||
PrimitiveBaseShape _pbs = repData.pbs;
|
||||
Vector3 _size = repData.size;
|
||||
|
||||
float volume = _size.X * _size.Y * _size.Z; // default
|
||||
float tmp;
|
||||
|
||||
float hollowAmount = (float)_pbs.ProfileHollow * 2.0e-5f;
|
||||
float hollowVolume = hollowAmount * hollowAmount;
|
||||
|
||||
switch (_pbs.ProfileShape)
|
||||
{
|
||||
case ProfileShape.Square:
|
||||
// default box
|
||||
|
||||
if (_pbs.PathCurve == (byte)Extrusion.Straight)
|
||||
{
|
||||
if (hollowAmount > 0.0)
|
||||
{
|
||||
switch (_pbs.HollowShape)
|
||||
{
|
||||
case HollowShape.Square:
|
||||
case HollowShape.Same:
|
||||
break;
|
||||
|
||||
case HollowShape.Circle:
|
||||
|
||||
hollowVolume *= 0.78539816339f;
|
||||
break;
|
||||
|
||||
case HollowShape.Triangle:
|
||||
|
||||
hollowVolume *= (0.5f * .5f);
|
||||
break;
|
||||
|
||||
default:
|
||||
hollowVolume = 0;
|
||||
break;
|
||||
}
|
||||
volume *= (1.0f - hollowVolume);
|
||||
}
|
||||
}
|
||||
|
||||
else if (_pbs.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 -= volume * tmp * tmp;
|
||||
|
||||
if (hollowAmount > 0.0)
|
||||
{
|
||||
hollowVolume *= hollowAmount;
|
||||
|
||||
switch (_pbs.HollowShape)
|
||||
{
|
||||
case HollowShape.Square:
|
||||
case HollowShape.Same:
|
||||
break;
|
||||
|
||||
case HollowShape.Circle:
|
||||
hollowVolume *= 0.78539816339f;
|
||||
break;
|
||||
|
||||
case HollowShape.Triangle:
|
||||
hollowVolume *= 0.5f * 0.5f;
|
||||
break;
|
||||
default:
|
||||
hollowVolume = 0;
|
||||
break;
|
||||
}
|
||||
volume *= (1.0f - hollowVolume);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case ProfileShape.Circle:
|
||||
|
||||
if (_pbs.PathCurve == (byte)Extrusion.Straight)
|
||||
{
|
||||
volume *= 0.78539816339f; // elipse base
|
||||
|
||||
if (hollowAmount > 0.0)
|
||||
{
|
||||
switch (_pbs.HollowShape)
|
||||
{
|
||||
case HollowShape.Same:
|
||||
case HollowShape.Circle:
|
||||
break;
|
||||
|
||||
case HollowShape.Square:
|
||||
hollowVolume *= 0.5f * 2.5984480504799f;
|
||||
break;
|
||||
|
||||
case HollowShape.Triangle:
|
||||
hollowVolume *= .5f * 1.27323954473516f;
|
||||
break;
|
||||
|
||||
default:
|
||||
hollowVolume = 0;
|
||||
break;
|
||||
}
|
||||
volume *= (1.0f - hollowVolume);
|
||||
}
|
||||
}
|
||||
|
||||
else if (_pbs.PathCurve == (byte)Extrusion.Curve1)
|
||||
{
|
||||
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 (_pbs.HollowShape)
|
||||
{
|
||||
case HollowShape.Same:
|
||||
case HollowShape.Circle:
|
||||
break;
|
||||
|
||||
case HollowShape.Square:
|
||||
hollowVolume *= 0.5f * 2.5984480504799f;
|
||||
break;
|
||||
|
||||
case HollowShape.Triangle:
|
||||
hollowVolume *= .5f * 1.27323954473516f;
|
||||
break;
|
||||
|
||||
default:
|
||||
hollowVolume = 0;
|
||||
break;
|
||||
}
|
||||
volume *= (1.0f - hollowVolume);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case ProfileShape.HalfCircle:
|
||||
if (_pbs.PathCurve == (byte)Extrusion.Curve1)
|
||||
{
|
||||
volume *= 0.5236f;
|
||||
|
||||
if (hollowAmount > 0.0)
|
||||
{
|
||||
hollowVolume *= hollowAmount;
|
||||
|
||||
switch (_pbs.HollowShape)
|
||||
{
|
||||
case HollowShape.Circle:
|
||||
case HollowShape.Triangle: // diference in sl is minor and odd
|
||||
case HollowShape.Same:
|
||||
break;
|
||||
|
||||
case HollowShape.Square:
|
||||
hollowVolume *= 0.909f;
|
||||
break;
|
||||
|
||||
// case HollowShape.Triangle:
|
||||
// hollowVolume *= .827f;
|
||||
// break;
|
||||
default:
|
||||
hollowVolume = 0;
|
||||
break;
|
||||
}
|
||||
volume *= (1.0f - hollowVolume);
|
||||
}
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
case ProfileShape.EquilateralTriangle:
|
||||
|
||||
if (_pbs.PathCurve == (byte)Extrusion.Straight)
|
||||
{
|
||||
volume *= 0.32475953f;
|
||||
|
||||
if (hollowAmount > 0.0)
|
||||
{
|
||||
|
||||
// calculate the hollow volume by it's shape compared to the prim shape
|
||||
switch (_pbs.HollowShape)
|
||||
{
|
||||
case HollowShape.Same:
|
||||
case HollowShape.Triangle:
|
||||
hollowVolume *= .25f;
|
||||
break;
|
||||
|
||||
case HollowShape.Square:
|
||||
hollowVolume *= 0.499849f * 3.07920140172638f;
|
||||
break;
|
||||
|
||||
case HollowShape.Circle:
|
||||
// Hollow shape is a perfect cyllinder in respect to the cube's scale
|
||||
// Cyllinder hollow volume calculation
|
||||
|
||||
hollowVolume *= 0.1963495f * 3.07920140172638f;
|
||||
break;
|
||||
|
||||
default:
|
||||
hollowVolume = 0;
|
||||
break;
|
||||
}
|
||||
volume *= (1.0f - hollowVolume);
|
||||
}
|
||||
}
|
||||
else if (_pbs.PathCurve == (byte)Extrusion.Curve1)
|
||||
{
|
||||
volume *= 0.32475953f;
|
||||
volume *= 0.01f * (float)(200 - _pbs.PathScaleX);
|
||||
tmp = 1.0f - .02f * (float)(200 - _pbs.PathScaleY);
|
||||
volume *= (1.0f - tmp * tmp);
|
||||
|
||||
if (hollowAmount > 0.0)
|
||||
{
|
||||
|
||||
hollowVolume *= hollowAmount;
|
||||
|
||||
switch (_pbs.HollowShape)
|
||||
{
|
||||
case HollowShape.Same:
|
||||
case HollowShape.Triangle:
|
||||
hollowVolume *= .25f;
|
||||
break;
|
||||
|
||||
case HollowShape.Square:
|
||||
hollowVolume *= 0.499849f * 3.07920140172638f;
|
||||
break;
|
||||
|
||||
case HollowShape.Circle:
|
||||
|
||||
hollowVolume *= 0.1963495f * 3.07920140172638f;
|
||||
break;
|
||||
|
||||
default:
|
||||
hollowVolume = 0;
|
||||
break;
|
||||
}
|
||||
volume *= (1.0f - hollowVolume);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
float taperX1;
|
||||
float taperY1;
|
||||
float taperX;
|
||||
float taperY;
|
||||
float pathBegin;
|
||||
float pathEnd;
|
||||
float profileBegin;
|
||||
float profileEnd;
|
||||
|
||||
if (_pbs.PathCurve == (byte)Extrusion.Straight || _pbs.PathCurve == (byte)Extrusion.Flexible)
|
||||
{
|
||||
taperX1 = _pbs.PathScaleX * 0.01f;
|
||||
if (taperX1 > 1.0f)
|
||||
taperX1 = 2.0f - taperX1;
|
||||
taperX = 1.0f - taperX1;
|
||||
|
||||
taperY1 = _pbs.PathScaleY * 0.01f;
|
||||
if (taperY1 > 1.0f)
|
||||
taperY1 = 2.0f - taperY1;
|
||||
taperY = 1.0f - taperY1;
|
||||
}
|
||||
else
|
||||
{
|
||||
taperX = _pbs.PathTaperX * 0.01f;
|
||||
if (taperX < 0.0f)
|
||||
taperX = -taperX;
|
||||
taperX1 = 1.0f - taperX;
|
||||
|
||||
taperY = _pbs.PathTaperY * 0.01f;
|
||||
if (taperY < 0.0f)
|
||||
taperY = -taperY;
|
||||
taperY1 = 1.0f - taperY;
|
||||
}
|
||||
|
||||
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;
|
||||
volume *= (pathEnd - pathBegin);
|
||||
|
||||
// this is crude aproximation
|
||||
profileBegin = (float)_pbs.ProfileBegin * 2.0e-5f;
|
||||
profileEnd = 1.0f - (float)_pbs.ProfileEnd * 2.0e-5f;
|
||||
volume *= (profileEnd - profileBegin);
|
||||
|
||||
repData.volume = volume;
|
||||
}
|
||||
|
||||
private void CalcVolumeData(ODEPhysRepData repData)
|
||||
{
|
||||
if (repData.hasOBB)
|
||||
{
|
||||
Vector3 OBB = repData.OBB;
|
||||
}
|
||||
else
|
||||
{
|
||||
Vector3 OBB = repData.size;
|
||||
OBB.X *= 0.5f;
|
||||
OBB.Y *= 0.5f;
|
||||
OBB.Z *= 0.5f;
|
||||
|
||||
repData.OBB = OBB;
|
||||
repData.OBBOffset = Vector3.Zero;
|
||||
}
|
||||
|
||||
CalculateBasicPrimVolume(repData);
|
||||
}
|
||||
}
|
||||
|
||||
public class ODEAssetRequest
|
||||
{
|
||||
ODEMeshWorker m_worker;
|
||||
private ILog m_log;
|
||||
ODEPhysRepData repData;
|
||||
|
||||
public ODEAssetRequest(ODEMeshWorker pWorker, RequestAssetDelegate provider,
|
||||
ODEPhysRepData pRepData, ILog plog)
|
||||
{
|
||||
m_worker = pWorker;
|
||||
m_log = plog;
|
||||
repData = pRepData;
|
||||
|
||||
repData.meshState = MeshState.AssetFailed;
|
||||
if (provider == null)
|
||||
return;
|
||||
|
||||
if (repData.assetID == null)
|
||||
return;
|
||||
|
||||
UUID assetID = (UUID) repData.assetID;
|
||||
if (assetID == UUID.Zero)
|
||||
return;
|
||||
|
||||
repData.meshState = MeshState.loadingAsset;
|
||||
provider(assetID, ODEassetReceived);
|
||||
}
|
||||
|
||||
void ODEassetReceived(AssetBase asset)
|
||||
{
|
||||
repData.meshState = MeshState.AssetFailed;
|
||||
if (asset != null)
|
||||
{
|
||||
if (asset.Data != null && asset.Data.Length > 0)
|
||||
{
|
||||
repData.meshState = MeshState.noNeed;
|
||||
|
||||
if (!repData.pbs.SculptEntry)
|
||||
return;
|
||||
if (repData.pbs.SculptTexture != repData.assetID)
|
||||
return;
|
||||
|
||||
repData.pbs.SculptData = new byte[asset.Data.Length];
|
||||
asset.Data.CopyTo(repData.pbs.SculptData,0);
|
||||
repData.meshState = MeshState.AssetOK;
|
||||
m_worker.AssetLoaded(repData);
|
||||
}
|
||||
else
|
||||
m_log.WarnFormat("[PHYSICS]: asset provider returned invalid mesh data for prim {0} asset UUID {1}.",
|
||||
repData.actor.Name, asset.ID.ToString());
|
||||
}
|
||||
else
|
||||
m_log.WarnFormat("[PHYSICS]: asset provider returned null asset fo mesh of prim {0}.",
|
||||
repData.actor.Name);
|
||||
}
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -129,7 +129,7 @@ namespace OpenSim.Region.Physics.OdePlugin
|
|||
req.length = length;
|
||||
req.Normal = direction;
|
||||
req.Origin = position;
|
||||
req.filter = RayFilterFlags.AllPrims;
|
||||
req.filter = RayFilterFlags.AllPrims | RayFilterFlags.land;
|
||||
|
||||
m_PendingRequests.Enqueue(req);
|
||||
}
|
||||
|
@ -288,7 +288,10 @@ namespace OpenSim.Region.Physics.OdePlugin
|
|||
catflags |= CollisionCategories.Water;
|
||||
|
||||
if (catflags != 0)
|
||||
{
|
||||
d.GeomSetCollideBits(ray, (uint)catflags);
|
||||
doSpaceRay(req);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -314,7 +317,8 @@ namespace OpenSim.Region.Physics.OdePlugin
|
|||
///
|
||||
|
||||
private const RayFilterFlags FilterActiveSpace = RayFilterFlags.agent | RayFilterFlags.physical | RayFilterFlags.LSLPhanton;
|
||||
private const RayFilterFlags FilterStaticSpace = RayFilterFlags.water | RayFilterFlags.land | RayFilterFlags.nonphysical | RayFilterFlags.LSLPhanton;
|
||||
// private const RayFilterFlags FilterStaticSpace = RayFilterFlags.water | RayFilterFlags.land | RayFilterFlags.nonphysical | RayFilterFlags.LSLPhanton;
|
||||
private const RayFilterFlags FilterStaticSpace = RayFilterFlags.water | RayFilterFlags.nonphysical | RayFilterFlags.LSLPhanton;
|
||||
|
||||
private void doSpaceRay(ODERayRequest req)
|
||||
{
|
||||
|
@ -323,6 +327,16 @@ namespace OpenSim.Region.Physics.OdePlugin
|
|||
d.SpaceCollide2(ray, m_scene.ActiveSpace, IntPtr.Zero, nearCallback);
|
||||
if ((CurrentRayFilter & FilterStaticSpace) != 0 && (m_contactResults.Count < CurrentMaxCount))
|
||||
d.SpaceCollide2(ray, m_scene.StaticSpace, IntPtr.Zero, nearCallback);
|
||||
if ((CurrentRayFilter & RayFilterFlags.land) != 0 && (m_contactResults.Count < CurrentMaxCount))
|
||||
{
|
||||
// current ode land to ray collisions is very bad
|
||||
// so for now limit its range badly
|
||||
|
||||
if (req.length > 30.0f)
|
||||
d.GeomRaySetLength(ray, 30.0f);
|
||||
|
||||
d.SpaceCollide2(ray, m_scene.GroundSpace, IntPtr.Zero, nearCallback);
|
||||
}
|
||||
|
||||
if (req.callbackMethod is RaycastCallback)
|
||||
{
|
||||
|
|
|
@ -60,6 +60,7 @@ namespace OpenSim.Region.Physics.OdePlugin
|
|||
public int lastframe;
|
||||
}
|
||||
|
||||
|
||||
// colision flags of things others can colide with
|
||||
// rays, sensors, probes removed since can't be colided with
|
||||
// The top space where things are placed provided further selection
|
||||
|
@ -147,6 +148,8 @@ namespace OpenSim.Region.Physics.OdePlugin
|
|||
|
||||
Size,
|
||||
Shape,
|
||||
PhysRepData,
|
||||
AddPhysRep,
|
||||
|
||||
CollidesWater,
|
||||
VolumeDtc,
|
||||
|
@ -230,11 +233,6 @@ namespace OpenSim.Region.Physics.OdePlugin
|
|||
private float minimumGroundFlightOffset = 3f;
|
||||
public float maximumMassObject = 10000.01f;
|
||||
|
||||
public bool meshSculptedPrim = true;
|
||||
public bool forceSimplePrimMeshing = false;
|
||||
|
||||
public float meshSculptLOD = 32;
|
||||
public float MeshSculptphysicalLOD = 32;
|
||||
|
||||
public float geomDefaultDensity = 10.000006836f;
|
||||
|
||||
|
@ -302,6 +300,7 @@ namespace OpenSim.Region.Physics.OdePlugin
|
|||
public IntPtr TopSpace; // the global space
|
||||
public IntPtr ActiveSpace; // space for active prims
|
||||
public IntPtr StaticSpace; // space for the static things around
|
||||
public IntPtr GroundSpace; // space for ground
|
||||
|
||||
// some speedup variables
|
||||
private int spaceGridMaxX;
|
||||
|
@ -313,7 +312,7 @@ namespace OpenSim.Region.Physics.OdePlugin
|
|||
private IntPtr[] staticPrimspaceOffRegion;
|
||||
|
||||
public Object OdeLock;
|
||||
private static Object SimulationLock;
|
||||
public static Object SimulationLock;
|
||||
|
||||
public IMesher mesher;
|
||||
|
||||
|
@ -328,7 +327,7 @@ namespace OpenSim.Region.Physics.OdePlugin
|
|||
private PhysicsScene m_parentScene = null;
|
||||
|
||||
private ODERayCastRequestManager m_rayCastManager;
|
||||
|
||||
public ODEMeshWorker m_meshWorker;
|
||||
|
||||
/* maybe needed if ode uses tls
|
||||
private void checkThread()
|
||||
|
@ -361,6 +360,8 @@ namespace OpenSim.Region.Physics.OdePlugin
|
|||
nearCallback = near;
|
||||
|
||||
m_rayCastManager = new ODERayCastRequestManager(this);
|
||||
|
||||
|
||||
lock (OdeLock)
|
||||
{
|
||||
// Create the world and the first space
|
||||
|
@ -372,6 +373,7 @@ namespace OpenSim.Region.Physics.OdePlugin
|
|||
// now the major subspaces
|
||||
ActiveSpace = d.HashSpaceCreate(TopSpace);
|
||||
StaticSpace = d.HashSpaceCreate(TopSpace);
|
||||
GroundSpace = d.HashSpaceCreate(TopSpace);
|
||||
}
|
||||
catch
|
||||
{
|
||||
|
@ -381,10 +383,12 @@ namespace OpenSim.Region.Physics.OdePlugin
|
|||
d.HashSpaceSetLevels(TopSpace, -2, 8);
|
||||
d.HashSpaceSetLevels(ActiveSpace, -2, 8);
|
||||
d.HashSpaceSetLevels(StaticSpace, -2, 8);
|
||||
d.HashSpaceSetLevels(GroundSpace, 0, 8);
|
||||
|
||||
// demote to second level
|
||||
d.SpaceSetSublevel(ActiveSpace, 1);
|
||||
d.SpaceSetSublevel(StaticSpace, 1);
|
||||
d.SpaceSetSublevel(GroundSpace, 1);
|
||||
|
||||
d.GeomSetCategoryBits(ActiveSpace, (uint)(CollisionCategories.Space |
|
||||
CollisionCategories.Geom |
|
||||
|
@ -402,6 +406,9 @@ namespace OpenSim.Region.Physics.OdePlugin
|
|||
));
|
||||
d.GeomSetCollideBits(StaticSpace, 0);
|
||||
|
||||
d.GeomSetCategoryBits(GroundSpace, (uint)(CollisionCategories.Land));
|
||||
d.GeomSetCollideBits(GroundSpace, 0);
|
||||
|
||||
contactgroup = d.JointGroupCreate(0);
|
||||
//contactgroup
|
||||
|
||||
|
@ -440,9 +447,11 @@ namespace OpenSim.Region.Physics.OdePlugin
|
|||
|
||||
int contactsPerCollision = 80;
|
||||
|
||||
IConfig physicsconfig = null;
|
||||
|
||||
if (m_config != null)
|
||||
{
|
||||
IConfig physicsconfig = m_config.Configs["ODEPhysicsSettings"];
|
||||
physicsconfig = m_config.Configs["ODEPhysicsSettings"];
|
||||
if (physicsconfig != null)
|
||||
{
|
||||
gravityx = physicsconfig.GetFloat("world_gravityx", gravityx);
|
||||
|
@ -469,27 +478,7 @@ namespace OpenSim.Region.Physics.OdePlugin
|
|||
|
||||
geomDefaultDensity = physicsconfig.GetFloat("geometry_default_density", geomDefaultDensity);
|
||||
bodyFramesAutoDisable = physicsconfig.GetInt("body_frames_auto_disable", bodyFramesAutoDisable);
|
||||
/*
|
||||
bodyPIDD = physicsconfig.GetFloat("body_pid_derivative", bodyPIDD);
|
||||
bodyPIDG = physicsconfig.GetFloat("body_pid_gain", bodyPIDG);
|
||||
*/
|
||||
forceSimplePrimMeshing = physicsconfig.GetBoolean("force_simple_prim_meshing", forceSimplePrimMeshing);
|
||||
meshSculptedPrim = physicsconfig.GetBoolean("mesh_sculpted_prim", meshSculptedPrim);
|
||||
meshSculptLOD = physicsconfig.GetFloat("mesh_lod", meshSculptLOD);
|
||||
MeshSculptphysicalLOD = physicsconfig.GetFloat("mesh_physical_lod", MeshSculptphysicalLOD);
|
||||
/*
|
||||
if (Environment.OSVersion.Platform == PlatformID.Unix)
|
||||
{
|
||||
avPIDD = physicsconfig.GetFloat("av_pid_derivative_linux", avPIDD);
|
||||
avPIDP = physicsconfig.GetFloat("av_pid_proportional_linux", avPIDP);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
avPIDD = physicsconfig.GetFloat("av_pid_derivative_win", avPIDD);
|
||||
avPIDP = physicsconfig.GetFloat("av_pid_proportional_win", avPIDP);
|
||||
}
|
||||
*/
|
||||
physics_logging = physicsconfig.GetBoolean("physics_logging", false);
|
||||
physics_logging_interval = physicsconfig.GetInt("physics_logging_interval", 0);
|
||||
physics_logging_append_existing_logfile = physicsconfig.GetBoolean("physics_logging_append_existing_logfile", false);
|
||||
|
@ -499,6 +488,8 @@ namespace OpenSim.Region.Physics.OdePlugin
|
|||
}
|
||||
}
|
||||
|
||||
m_meshWorker = new ODEMeshWorker(this, m_log, meshmerizer, physicsconfig);
|
||||
|
||||
HalfOdeStep = ODE_STEPSIZE * 0.5f;
|
||||
odetimestepMS = (int)(1000.0f * ODE_STEPSIZE +0.5f);
|
||||
|
||||
|
@ -727,6 +718,32 @@ namespace OpenSim.Region.Physics.OdePlugin
|
|||
|
||||
if (b1 != IntPtr.Zero && b2 != IntPtr.Zero && d.AreConnectedExcluding(b1, b2, d.JointType.Contact))
|
||||
return;
|
||||
/*
|
||||
// debug
|
||||
PhysicsActor dp2;
|
||||
if (d.GeomGetClass(g1) == d.GeomClassID.HeightfieldClass)
|
||||
{
|
||||
d.AABB aabb;
|
||||
d.GeomGetAABB(g2, out aabb);
|
||||
float x = aabb.MaxX - aabb.MinX;
|
||||
float y = aabb.MaxY - aabb.MinY;
|
||||
float z = aabb.MaxZ - aabb.MinZ;
|
||||
if (x > 60.0f || y > 60.0f || z > 60.0f)
|
||||
{
|
||||
if (!actor_name_map.TryGetValue(g2, out dp2))
|
||||
m_log.WarnFormat("[PHYSICS]: failed actor mapping for geom 2");
|
||||
else
|
||||
m_log.WarnFormat("[PHYSICS]: land versus large prim geo {0},size {1}, AABBsize <{2},{3},{4}>, at {5} ori {6},({7})",
|
||||
dp2.Name, dp2.Size, x, y, z,
|
||||
dp2.Position.ToString(),
|
||||
dp2.Orientation.ToString(),
|
||||
dp2.Orientation.Length());
|
||||
return;
|
||||
}
|
||||
}
|
||||
//
|
||||
*/
|
||||
|
||||
|
||||
if(d.GeomGetCategoryBits(g1) == (uint)CollisionCategories.VolumeDtc ||
|
||||
d.GeomGetCategoryBits(g1) == (uint)CollisionCategories.VolumeDtc)
|
||||
|
@ -1225,6 +1242,7 @@ namespace OpenSim.Region.Physics.OdePlugin
|
|||
chr.CollidingObj = false;
|
||||
// do colisions with static space
|
||||
d.SpaceCollide2(StaticSpace, chr.Shell, IntPtr.Zero, nearCallback);
|
||||
// no coll with gnd
|
||||
}
|
||||
}
|
||||
catch (AccessViolationException)
|
||||
|
@ -1253,7 +1271,10 @@ namespace OpenSim.Region.Physics.OdePlugin
|
|||
if (!prm.m_outbounds)
|
||||
{
|
||||
if (d.BodyIsEnabled(prm.Body))
|
||||
{
|
||||
d.SpaceCollide2(StaticSpace, prm.collide_geom, IntPtr.Zero, nearCallback);
|
||||
d.SpaceCollide2(GroundSpace, prm.collide_geom, IntPtr.Zero, nearCallback);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1295,6 +1316,15 @@ namespace OpenSim.Region.Physics.OdePlugin
|
|||
_collisionEventPrimRemove.Add(obj);
|
||||
}
|
||||
|
||||
public override float TimeDilation
|
||||
{
|
||||
get { return m_timeDilation; }
|
||||
}
|
||||
|
||||
public override bool SupportsNINJAJoints
|
||||
{
|
||||
get { return false; }
|
||||
}
|
||||
|
||||
#region Add/Remove Entities
|
||||
|
||||
|
@ -1350,59 +1380,6 @@ namespace OpenSim.Region.Physics.OdePlugin
|
|||
((OdeCharacter) actor).Destroy();
|
||||
}
|
||||
|
||||
private PhysicsActor AddPrim(String name, Vector3 position, Vector3 size, Quaternion rotation,
|
||||
PrimitiveBaseShape pbs, bool isphysical, uint localID)
|
||||
{
|
||||
Vector3 pos = position;
|
||||
Vector3 siz = size;
|
||||
Quaternion rot = rotation;
|
||||
|
||||
OdePrim newPrim;
|
||||
lock (OdeLock)
|
||||
{
|
||||
newPrim = new OdePrim(name, this, pos, siz, rot, pbs, isphysical,false,0,localID);
|
||||
|
||||
lock (_prims)
|
||||
_prims.Add(newPrim);
|
||||
}
|
||||
return newPrim;
|
||||
}
|
||||
|
||||
private PhysicsActor AddPrim(String name, Vector3 position, Vector3 size, Quaternion rotation,
|
||||
PrimitiveBaseShape pbs, bool isphysical, bool isPhantom, uint localID)
|
||||
{
|
||||
Vector3 pos = position;
|
||||
Vector3 siz = size;
|
||||
Quaternion rot = rotation;
|
||||
|
||||
OdePrim newPrim;
|
||||
lock (OdeLock)
|
||||
{
|
||||
newPrim = new OdePrim(name, this, pos, siz, rot, pbs, isphysical, isPhantom, 0, localID);
|
||||
|
||||
lock (_prims)
|
||||
_prims.Add(newPrim);
|
||||
}
|
||||
return newPrim;
|
||||
}
|
||||
|
||||
private PhysicsActor AddPrim(String name, Vector3 position, Vector3 size, Quaternion rotation,
|
||||
PrimitiveBaseShape pbs, bool isphysical, bool isPhantom, byte shapeType, uint localID)
|
||||
{
|
||||
Vector3 pos = position;
|
||||
Vector3 siz = size;
|
||||
Quaternion rot = rotation;
|
||||
|
||||
OdePrim newPrim;
|
||||
lock (OdeLock)
|
||||
{
|
||||
newPrim = new OdePrim(name, this, pos, siz, rot, pbs, isphysical, isPhantom, shapeType, localID);
|
||||
|
||||
lock (_prims)
|
||||
_prims.Add(newPrim);
|
||||
}
|
||||
return newPrim;
|
||||
}
|
||||
|
||||
public void addActivePrim(OdePrim activatePrim)
|
||||
{
|
||||
|
@ -1423,44 +1400,39 @@ namespace OpenSim.Region.Physics.OdePlugin
|
|||
}
|
||||
}
|
||||
|
||||
private PhysicsActor AddPrim(String name, Vector3 position, Vector3 size, Quaternion rotation,
|
||||
PrimitiveBaseShape pbs, bool isphysical, bool isPhantom, byte shapeType, uint localID)
|
||||
{
|
||||
OdePrim newPrim;
|
||||
lock (OdeLock)
|
||||
{
|
||||
newPrim = new OdePrim(name, this, position, size, rotation, pbs, isphysical, isPhantom, shapeType, localID);
|
||||
lock (_prims)
|
||||
_prims.Add(newPrim);
|
||||
}
|
||||
return newPrim;
|
||||
}
|
||||
|
||||
public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, Vector3 position,
|
||||
Vector3 size, Quaternion rotation, bool isPhysical, bool isPhantom, uint localid)
|
||||
{
|
||||
return AddPrim(primName, position, size, rotation, pbs, isPhysical, isPhantom, localid);
|
||||
return AddPrim(primName, position, size, rotation, pbs, isPhysical, isPhantom, 0 , localid);
|
||||
}
|
||||
|
||||
|
||||
public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, Vector3 position,
|
||||
Vector3 size, Quaternion rotation, bool isPhysical, uint localid)
|
||||
{
|
||||
#if SPAM
|
||||
m_log.DebugFormat("[PHYSICS]: Adding physics actor to {0}", primName);
|
||||
#endif
|
||||
|
||||
return AddPrim(primName, position, size, rotation, pbs, isPhysical, localid);
|
||||
return AddPrim(primName, position, size, rotation, pbs, isPhysical,false, 0, localid);
|
||||
}
|
||||
|
||||
public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, Vector3 position,
|
||||
Vector3 size, Quaternion rotation, bool isPhysical, bool isPhantom, byte shapeType, uint localid)
|
||||
{
|
||||
#if SPAM
|
||||
m_log.DebugFormat("[PHYSICS]: Adding physics actor to {0}", primName);
|
||||
#endif
|
||||
|
||||
return AddPrim(primName, position, size, rotation, pbs, isPhysical,isPhantom, shapeType, localid);
|
||||
}
|
||||
|
||||
public override float TimeDilation
|
||||
{
|
||||
get { return m_timeDilation; }
|
||||
}
|
||||
|
||||
public override bool SupportsNINJAJoints
|
||||
{
|
||||
get { return false; }
|
||||
}
|
||||
|
||||
|
||||
public void remActivePrim(OdePrim deactivatePrim)
|
||||
{
|
||||
lock (_activeprims)
|
||||
|
@ -1513,6 +1485,28 @@ namespace OpenSim.Region.Physics.OdePlugin
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
public bool havePrim(OdePrim prm)
|
||||
{
|
||||
lock (_prims)
|
||||
return _prims.Contains(prm);
|
||||
}
|
||||
|
||||
public bool haveActor(PhysicsActor actor)
|
||||
{
|
||||
if (actor is OdePrim)
|
||||
{
|
||||
lock (_prims)
|
||||
return _prims.Contains((OdePrim)actor);
|
||||
}
|
||||
else if (actor is OdeCharacter)
|
||||
{
|
||||
lock (_characters)
|
||||
return _characters.Contains((OdeCharacter)actor);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Space Separation Calculation
|
||||
|
@ -1615,135 +1609,6 @@ namespace OpenSim.Region.Physics.OdePlugin
|
|||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Routine to figure out if we need to mesh this prim with our mesher
|
||||
/// </summary>
|
||||
/// <param name="pbs"></param>
|
||||
/// <returns></returns>
|
||||
public bool needsMeshing(PrimitiveBaseShape pbs)
|
||||
{
|
||||
// check sculpts or meshs
|
||||
if (pbs.SculptEntry)
|
||||
{
|
||||
if (meshSculptedPrim)
|
||||
return true;
|
||||
|
||||
if (pbs.SculptType == (byte)SculptType.Mesh) // always do meshs
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (forceSimplePrimMeshing)
|
||||
return true;
|
||||
|
||||
// if it's a standard box or sphere with no cuts, hollows, twist or top shear, return false since ODE can use an internal representation for the prim
|
||||
|
||||
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)
|
||||
{
|
||||
#if SPAM
|
||||
m_log.Warn("NonMesh");
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// following code doesn't give meshs to boxes and spheres ever
|
||||
// and it's odd.. so for now just return true if asked to force meshs
|
||||
// hopefully mesher will fail if doesn't suport so things still get basic boxes
|
||||
|
||||
int iPropertiesNotSupportedDefault = 0;
|
||||
|
||||
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)
|
||||
{
|
||||
#if SPAM
|
||||
m_log.Warn("NonMesh");
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
#if SPAM
|
||||
m_log.Debug("Mesh");
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called to queue a change to a actor
|
||||
|
@ -1766,8 +1631,52 @@ namespace OpenSim.Region.Physics.OdePlugin
|
|||
/// </summary>
|
||||
/// <param name="prim"></param>
|
||||
public override void AddPhysicsActorTaint(PhysicsActor prim)
|
||||
{
|
||||
}
|
||||
|
||||
// does all pending changes generated during region load process
|
||||
public override void PrepareSimulation()
|
||||
{
|
||||
lock (OdeLock)
|
||||
{
|
||||
if (world == IntPtr.Zero)
|
||||
{
|
||||
ChangesQueue.Clear();
|
||||
return;
|
||||
}
|
||||
|
||||
ODEchangeitem item;
|
||||
|
||||
int donechanges = 0;
|
||||
if (ChangesQueue.Count > 0)
|
||||
{
|
||||
m_log.InfoFormat("[ODE] start processing pending actor operations");
|
||||
int tstart = Util.EnvironmentTickCount();
|
||||
|
||||
while (ChangesQueue.Dequeue(out item))
|
||||
{
|
||||
if (item.actor != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (item.actor is OdeCharacter)
|
||||
((OdeCharacter)item.actor).DoAChange(item.what, item.arg);
|
||||
else if (((OdePrim)item.actor).DoAChange(item.what, item.arg))
|
||||
RemovePrimThreadLocked((OdePrim)item.actor);
|
||||
}
|
||||
catch
|
||||
{
|
||||
m_log.WarnFormat("[PHYSICS]: Operation failed for a actor {0} {1}",
|
||||
item.actor.Name, item.what.ToString());
|
||||
}
|
||||
}
|
||||
donechanges++;
|
||||
}
|
||||
int time = Util.EnvironmentTickCountSubtract(tstart);
|
||||
m_log.InfoFormat("[ODE] finished {0} operations in {1}ms", donechanges, time);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is our main simulate loop
|
||||
|
@ -1813,21 +1722,17 @@ namespace OpenSim.Region.Physics.OdePlugin
|
|||
lock(OdeLock)
|
||||
{
|
||||
if (world == IntPtr.Zero)
|
||||
return 0;
|
||||
|
||||
// adjust number of iterations per step
|
||||
|
||||
// try
|
||||
// {
|
||||
d.WorldSetQuickStepNumIterations(world, curphysiteractions);
|
||||
/* }
|
||||
catch (StackOverflowException)
|
||||
{
|
||||
m_log.Error("[PHYSICS]: The operating system wasn't able to allocate enough memory for the simulation. Restarting the sim.");
|
||||
// ode.drelease(world);
|
||||
base.TriggerPhysicsBasedRestart();
|
||||
ChangesQueue.Clear();
|
||||
return 0;
|
||||
}
|
||||
*/
|
||||
|
||||
ODEchangeitem item;
|
||||
|
||||
|
||||
|
||||
d.WorldSetQuickStepNumIterations(world, curphysiteractions);
|
||||
|
||||
while (step_time > HalfOdeStep && nodeframes < 10) //limit number of steps so we don't say here for ever
|
||||
{
|
||||
try
|
||||
|
@ -1835,14 +1740,12 @@ namespace OpenSim.Region.Physics.OdePlugin
|
|||
// clear pointer/counter to contacts to pass into joints
|
||||
m_global_contactcount = 0;
|
||||
|
||||
ODEchangeitem item;
|
||||
|
||||
if(ChangesQueue.Count >0)
|
||||
if (ChangesQueue.Count > 0)
|
||||
{
|
||||
int ttmpstart = Util.EnvironmentTickCount();
|
||||
int ttmp;
|
||||
|
||||
while(ChangesQueue.Dequeue(out item))
|
||||
while (ChangesQueue.Dequeue(out item))
|
||||
{
|
||||
if (item.actor != null)
|
||||
{
|
||||
|
@ -1851,12 +1754,13 @@ namespace OpenSim.Region.Physics.OdePlugin
|
|||
if (item.actor is OdeCharacter)
|
||||
((OdeCharacter)item.actor).DoAChange(item.what, item.arg);
|
||||
else if (((OdePrim)item.actor).DoAChange(item.what, item.arg))
|
||||
RemovePrimThreadLocked((OdePrim)item.actor);
|
||||
RemovePrimThreadLocked((OdePrim)item.actor);
|
||||
}
|
||||
catch
|
||||
{
|
||||
m_log.Warn("[PHYSICS]: doChange failed for a actor");
|
||||
};
|
||||
m_log.WarnFormat("[PHYSICS]: doChange failed for a actor {0} {1}",
|
||||
item.actor.Name, item.what.ToString());
|
||||
}
|
||||
}
|
||||
ttmp = Util.EnvironmentTickCountSubtract(ttmpstart);
|
||||
if (ttmp > 20)
|
||||
|
@ -1994,10 +1898,47 @@ namespace OpenSim.Region.Physics.OdePlugin
|
|||
mesher.ExpireReleaseMeshs();
|
||||
m_lastMeshExpire = now;
|
||||
}
|
||||
|
||||
// information block running in debug only
|
||||
/*
|
||||
int nactivegeoms = d.SpaceGetNumGeoms(ActiveSpace);
|
||||
int nstaticgeoms = d.SpaceGetNumGeoms(StaticSpace);
|
||||
int ntopactivegeoms = d.SpaceGetNumGeoms(ActiveSpace);
|
||||
int ntopstaticgeoms = d.SpaceGetNumGeoms(StaticSpace);
|
||||
int ngroundgeoms = d.SpaceGetNumGeoms(GroundSpace);
|
||||
|
||||
int nactivegeoms = 0;
|
||||
int nactivespaces = 0;
|
||||
|
||||
int nstaticgeoms = 0;
|
||||
int nstaticspaces = 0;
|
||||
IntPtr sp;
|
||||
|
||||
for (int i = 0; i < ntopactivegeoms; i++)
|
||||
{
|
||||
sp = d.SpaceGetGeom(ActiveSpace, i);
|
||||
if (d.GeomIsSpace(sp))
|
||||
{
|
||||
nactivespaces++;
|
||||
nactivegeoms += d.SpaceGetNumGeoms(sp);
|
||||
}
|
||||
else
|
||||
nactivegeoms++;
|
||||
}
|
||||
|
||||
for (int i = 0; i < ntopstaticgeoms; i++)
|
||||
{
|
||||
sp = d.SpaceGetGeom(StaticSpace, i);
|
||||
if (d.GeomIsSpace(sp))
|
||||
{
|
||||
nstaticspaces++;
|
||||
nstaticgeoms += d.SpaceGetNumGeoms(sp);
|
||||
}
|
||||
else
|
||||
nstaticgeoms++;
|
||||
}
|
||||
|
||||
int ntopgeoms = d.SpaceGetNumGeoms(TopSpace);
|
||||
|
||||
int totgeoms = nstaticgeoms + nactivegeoms + ngroundgeoms + 1; // one ray
|
||||
int nbodies = d.NTotalBodies;
|
||||
int ngeoms = d.NTotalGeoms;
|
||||
*/
|
||||
|
@ -2294,7 +2235,9 @@ namespace OpenSim.Region.Physics.OdePlugin
|
|||
offset, thickness, wrap);
|
||||
|
||||
d.GeomHeightfieldDataSetBounds(HeightmapData, hfmin - 1, hfmax + 1);
|
||||
GroundGeom = d.CreateHeightfield(StaticSpace, HeightmapData, 1);
|
||||
|
||||
GroundGeom = d.CreateHeightfield(GroundSpace, HeightmapData, 1);
|
||||
|
||||
if (GroundGeom != IntPtr.Zero)
|
||||
{
|
||||
d.GeomSetCategoryBits(GroundGeom, (uint)(CollisionCategories.Land));
|
||||
|
@ -2415,12 +2358,13 @@ namespace OpenSim.Region.Physics.OdePlugin
|
|||
thickness, wrap);
|
||||
|
||||
// d.GeomUbitTerrainDataSetBounds(HeightmapData, hfmin - 1, hfmax + 1);
|
||||
GroundGeom = d.CreateUbitTerrain(StaticSpace, HeightmapData, 1);
|
||||
GroundGeom = d.CreateUbitTerrain(GroundSpace, HeightmapData, 1);
|
||||
if (GroundGeom != IntPtr.Zero)
|
||||
{
|
||||
d.GeomSetCategoryBits(GroundGeom, (uint)(CollisionCategories.Land));
|
||||
d.GeomSetCollideBits(GroundGeom, 0);
|
||||
|
||||
|
||||
PhysicsActor pa = new NullPhysicsActor();
|
||||
pa.Name = "Terrain";
|
||||
pa.PhysicsActorType = (int)ActorTypes.Ground;
|
||||
|
@ -2599,6 +2543,9 @@ namespace OpenSim.Region.Physics.OdePlugin
|
|||
*/
|
||||
public override void Dispose()
|
||||
{
|
||||
if (m_meshWorker != null)
|
||||
m_meshWorker.Stop();
|
||||
|
||||
lock (OdeLock)
|
||||
{
|
||||
m_rayCastManager.Dispose();
|
||||
|
@ -2633,6 +2580,7 @@ namespace OpenSim.Region.Physics.OdePlugin
|
|||
d.GeomDestroy(GroundGeom);
|
||||
}
|
||||
|
||||
|
||||
RegionTerrain.Clear();
|
||||
|
||||
if (TerrainHeightFieldHeightsHandlers.Count > 0)
|
||||
|
|
Loading…
Reference in New Issue