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);
|
reqnum, verb, requestUrl);
|
||||||
|
|
||||||
int tickstart = Util.EnvironmentTickCount();
|
int tickstart = Util.EnvironmentTickCount();
|
||||||
int tickdata = 0;
|
// int tickdata = 0;
|
||||||
|
int tickdiff = 0;
|
||||||
|
|
||||||
Type type = typeof(TRequest);
|
Type type = typeof(TRequest);
|
||||||
|
|
||||||
|
@ -776,8 +777,8 @@ namespace OpenSim.Framework
|
||||||
requestStream.Close();
|
requestStream.Close();
|
||||||
|
|
||||||
// capture how much time was spent writing
|
// capture how much time was spent writing
|
||||||
tickdata = Util.EnvironmentTickCountSubtract(tickstart);
|
// useless in this async
|
||||||
|
// tickdata = Util.EnvironmentTickCountSubtract(tickstart);
|
||||||
request.BeginGetResponse(delegate(IAsyncResult ar)
|
request.BeginGetResponse(delegate(IAsyncResult ar)
|
||||||
{
|
{
|
||||||
response = request.EndGetResponse(ar);
|
response = request.EndGetResponse(ar);
|
||||||
|
@ -794,7 +795,8 @@ namespace OpenSim.Framework
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
// Let's not close this
|
// Let's not close this
|
||||||
//buffer.Close();
|
// yes do close it
|
||||||
|
buffer.Close();
|
||||||
respStream.Close();
|
respStream.Close();
|
||||||
response.Close();
|
response.Close();
|
||||||
}
|
}
|
||||||
|
@ -862,7 +864,6 @@ namespace OpenSim.Framework
|
||||||
}
|
}
|
||||||
|
|
||||||
// m_log.DebugFormat("[ASYNC REQUEST]: Received {0}", deserial.ToString());
|
// m_log.DebugFormat("[ASYNC REQUEST]: Received {0}", deserial.ToString());
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
action(deserial);
|
action(deserial);
|
||||||
|
@ -877,9 +878,10 @@ namespace OpenSim.Framework
|
||||||
}, null);
|
}, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
int tickdiff = Util.EnvironmentTickCountSubtract(tickstart);
|
tickdiff = Util.EnvironmentTickCountSubtract(tickstart);
|
||||||
if (tickdiff > WebUtil.LongCallTime)
|
if (tickdiff > WebUtil.LongCallTime)
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
string originalRequest = null;
|
string originalRequest = null;
|
||||||
|
|
||||||
if (buffer != null)
|
if (buffer != null)
|
||||||
|
@ -898,12 +900,19 @@ namespace OpenSim.Framework
|
||||||
tickdiff,
|
tickdiff,
|
||||||
tickdata,
|
tickdata,
|
||||||
originalRequest);
|
originalRequest);
|
||||||
|
*/
|
||||||
|
m_log.InfoFormat(
|
||||||
|
"[ASYNC REQUEST]: Slow WebRequest SETUP <{0}> {1} {2} took {3}ms",
|
||||||
|
reqnum,
|
||||||
|
verb,
|
||||||
|
requestUrl,
|
||||||
|
tickdiff);
|
||||||
}
|
}
|
||||||
else if (WebUtil.DebugLevel >= 4)
|
else if (WebUtil.DebugLevel >= 4)
|
||||||
{
|
{
|
||||||
m_log.DebugFormat(
|
m_log.DebugFormat(
|
||||||
"[WEB UTIL]: HTTP OUT {0} took {1}ms, {2}ms writing",
|
"[WEB UTIL]: HTTP OUT {0} took {1}ms",
|
||||||
reqnum, tickdiff, tickdata);
|
reqnum, tickdiff);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -938,6 +947,8 @@ namespace OpenSim.Framework
|
||||||
request.Method = verb;
|
request.Method = verb;
|
||||||
string respstring = String.Empty;
|
string respstring = String.Empty;
|
||||||
|
|
||||||
|
int tickset = Util.EnvironmentTickCountSubtract(tickstart);
|
||||||
|
|
||||||
using (MemoryStream buffer = new MemoryStream())
|
using (MemoryStream buffer = new MemoryStream())
|
||||||
{
|
{
|
||||||
if ((verb == "POST") || (verb == "PUT"))
|
if ((verb == "POST") || (verb == "PUT"))
|
||||||
|
@ -1019,6 +1030,7 @@ namespace OpenSim.Framework
|
||||||
verb,
|
verb,
|
||||||
requestUrl,
|
requestUrl,
|
||||||
tickdiff,
|
tickdiff,
|
||||||
|
tickset,
|
||||||
tickdata,
|
tickdata,
|
||||||
obj.Length > WebUtil.MaxRequestDiagLength ? obj.Remove(WebUtil.MaxRequestDiagLength) : obj);
|
obj.Length > WebUtil.MaxRequestDiagLength ? obj.Remove(WebUtil.MaxRequestDiagLength) : obj);
|
||||||
else if (WebUtil.DebugLevel >= 4)
|
else if (WebUtil.DebugLevel >= 4)
|
||||||
|
|
|
@ -1117,17 +1117,17 @@ namespace OpenSim.Region.ClientStack.Linden
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
AddNewInventoryItem(m_HostCapsObj.AgentID, item, (uint)cost);
|
AddNewInventoryItem(m_HostCapsObj.AgentID, item, (uint)cost);
|
||||||
if (client != null)
|
// if (client != null)
|
||||||
{
|
// {
|
||||||
// let users see anything.. i don't so far
|
// // let users see anything.. i don't so far
|
||||||
string str;
|
// string str;
|
||||||
if (cost > 0)
|
// if (cost > 0)
|
||||||
// dont remember where is money unit name to put here
|
// // dont remember where is money unit name to put here
|
||||||
str = "Upload complete. charged " + cost.ToString() + "$";
|
// str = "Upload complete. charged " + cost.ToString() + "$";
|
||||||
else
|
// else
|
||||||
str = "Upload complete";
|
// str = "Upload complete";
|
||||||
client.SendAgentAlertMessage(str, true);
|
// client.SendAgentAlertMessage(str, true);
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -104,7 +104,7 @@ namespace OpenSim.Region.ClientStack.Linden
|
||||||
|
|
||||||
public void RegisterCaps(UUID agentID, Caps caps)
|
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;
|
return;
|
||||||
|
|
||||||
UUID capID = UUID.Random();
|
UUID capID = UUID.Random();
|
||||||
|
|
|
@ -575,6 +575,7 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
Quaternion current = m_group.GroupRotation;
|
Quaternion current = m_group.GroupRotation;
|
||||||
|
|
||||||
Quaternion step = Quaternion.Slerp(m_currentFrame.StartRotation, (Quaternion)m_currentFrame.Rotation, complete);
|
Quaternion step = Quaternion.Slerp(m_currentFrame.StartRotation, (Quaternion)m_currentFrame.Rotation, complete);
|
||||||
|
step.Normalize();
|
||||||
/* use simpler change detection
|
/* use simpler change detection
|
||||||
* float angle = 0;
|
* float angle = 0;
|
||||||
|
|
||||||
|
|
|
@ -4386,8 +4386,8 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
|
|
||||||
SceneObjectPart[] parts = m_parts.GetArray();
|
SceneObjectPart[] parts = m_parts.GetArray();
|
||||||
|
|
||||||
for (int i = 0; i < parts.Length; i++)
|
// for (int i = 0; i < parts.Length; i++)
|
||||||
parts[i].CheckSculptAndLoad();
|
// parts[i].CheckSculptAndLoad();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
@ -1095,9 +1095,9 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
{
|
{
|
||||||
actor.Size = m_shape.Scale;
|
actor.Size = m_shape.Scale;
|
||||||
|
|
||||||
if (Shape.SculptEntry)
|
// if (Shape.SculptEntry)
|
||||||
CheckSculptAndLoad();
|
// CheckSculptAndLoad();
|
||||||
else
|
// else
|
||||||
ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor);
|
ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1583,7 +1583,9 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
|
|
||||||
float cost = 0.1f;
|
float cost = 0.1f;
|
||||||
if (PhysActor != null)
|
if (PhysActor != null)
|
||||||
// cost += PhysActor.Cost;
|
cost = PhysActor.PhysicsCost;
|
||||||
|
else
|
||||||
|
cost = 0.1f;
|
||||||
|
|
||||||
if ((Flags & PrimFlags.Physics) != 0)
|
if ((Flags & PrimFlags.Physics) != 0)
|
||||||
cost *= (1.0f + 0.01333f * Scale.LengthSquared()); // 0.01333 == 0.04/3
|
cost *= (1.0f + 0.01333f * Scale.LengthSquared()); // 0.01333 == 0.04/3
|
||||||
|
@ -1596,9 +1598,12 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
|
float cost;
|
||||||
|
if (PhysActor != null)
|
||||||
return 0.1f;
|
cost = PhysActor.StreamCost;
|
||||||
|
else
|
||||||
|
cost = 1.0f;
|
||||||
|
return 1.0f;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1654,8 +1659,8 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
PhysActor.PhysicsShapeType = m_physicsShapeType;
|
PhysActor.PhysicsShapeType = m_physicsShapeType;
|
||||||
if (Shape.SculptEntry)
|
// if (Shape.SculptEntry)
|
||||||
CheckSculptAndLoad();
|
// CheckSculptAndLoad();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ParentGroup != null)
|
if (ParentGroup != null)
|
||||||
|
@ -2115,12 +2120,13 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
|
|
||||||
if (userExposed)
|
if (userExposed)
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
if (dupe.m_shape.SculptEntry && dupe.m_shape.SculptTexture != UUID.Zero)
|
if (dupe.m_shape.SculptEntry && dupe.m_shape.SculptTexture != UUID.Zero)
|
||||||
{
|
{
|
||||||
ParentGroup.Scene.AssetService.Get(
|
ParentGroup.Scene.AssetService.Get(
|
||||||
dupe.m_shape.SculptTexture.ToString(), dupe, dupe.AssetReceived);
|
dupe.m_shape.SculptTexture.ToString(), dupe, dupe.AssetReceived);
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
bool UsePhysics = ((dupe.Flags & PrimFlags.Physics) != 0);
|
bool UsePhysics = ((dupe.Flags & PrimFlags.Physics) != 0);
|
||||||
dupe.DoPhysicsPropertyUpdate(UsePhysics, true);
|
dupe.DoPhysicsPropertyUpdate(UsePhysics, true);
|
||||||
// dupe.UpdatePhysicsSubscribedEvents(); // not sure...
|
// dupe.UpdatePhysicsSubscribedEvents(); // not sure...
|
||||||
|
@ -2142,6 +2148,7 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
/// <param name="id">ID of asset received</param>
|
/// <param name="id">ID of asset received</param>
|
||||||
/// <param name="sender">Register</param>
|
/// <param name="sender">Register</param>
|
||||||
/// <param name="asset"></param>
|
/// <param name="asset"></param>
|
||||||
|
/*
|
||||||
protected void AssetReceived(string id, Object sender, AssetBase asset)
|
protected void AssetReceived(string id, Object sender, AssetBase asset)
|
||||||
{
|
{
|
||||||
if (asset != null)
|
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",
|
// "[SCENE OBJECT PART]: Part {0} {1} requested mesh/sculpt data for asset id {2} from asset service but received no data",
|
||||||
// Name, UUID, id);
|
// Name, UUID, id);
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Do a physics property update for a NINJA joint.
|
/// Do a physics property update for a NINJA joint.
|
||||||
/// </summary>
|
/// </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
|
// If this part is a sculpt then delay the physics update until we've asynchronously loaded the
|
||||||
// mesh data.
|
// mesh data.
|
||||||
if (Shape.SculptEntry)
|
// if (Shape.SculptEntry)
|
||||||
CheckSculptAndLoad();
|
// CheckSculptAndLoad();
|
||||||
else
|
// else
|
||||||
ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(pa);
|
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.
|
/// Set sculpt and mesh data, and tell the physics engine to process the change.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="texture">The mesh itself.</param>
|
/// <param name="texture">The mesh itself.</param>
|
||||||
|
/*
|
||||||
public void SculptTextureCallback(AssetBase texture)
|
public void SculptTextureCallback(AssetBase texture)
|
||||||
{
|
{
|
||||||
if (m_shape.SculptEntry)
|
if (m_shape.SculptEntry)
|
||||||
|
@ -3155,7 +3163,7 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Send a full update to the client for the given part
|
/// Send a full update to the client for the given part
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -4397,7 +4405,7 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
public void UpdateExtraParam(ushort type, bool inUse, byte[] data)
|
public void UpdateExtraParam(ushort type, bool inUse, byte[] data)
|
||||||
{
|
{
|
||||||
m_shape.ReadInUpdateExtraParam(type, inUse, data);
|
m_shape.ReadInUpdateExtraParam(type, inUse, data);
|
||||||
|
/*
|
||||||
if (type == 0x30)
|
if (type == 0x30)
|
||||||
{
|
{
|
||||||
if (m_shape.SculptEntry && m_shape.SculptTexture != UUID.Zero)
|
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);
|
ParentGroup.Scene.AssetService.Get(m_shape.SculptTexture.ToString(), this, AssetReceived);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
if (ParentGroup != null)
|
if (ParentGroup != null)
|
||||||
{
|
{
|
||||||
ParentGroup.HasGroupChanged = true;
|
ParentGroup.HasGroupChanged = true;
|
||||||
|
@ -4813,9 +4821,9 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Shape.SculptEntry)
|
// if (Shape.SculptEntry)
|
||||||
CheckSculptAndLoad();
|
// CheckSculptAndLoad();
|
||||||
else
|
// else
|
||||||
ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(pa);
|
ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(pa);
|
||||||
|
|
||||||
if (!building)
|
if (!building)
|
||||||
|
@ -4969,10 +4977,13 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
/// <remarks>
|
/// <remarks>
|
||||||
/// When the physics engine has finished with it, the sculpt data is discarded to save memory.
|
/// When the physics engine has finished with it, the sculpt data is discarded to save memory.
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
|
/*
|
||||||
public void CheckSculptAndLoad()
|
public void CheckSculptAndLoad()
|
||||||
{
|
{
|
||||||
// m_log.DebugFormat("Processing CheckSculptAndLoad for {0} {1}", Name, LocalId);
|
// m_log.DebugFormat("Processing CheckSculptAndLoad for {0} {1}", Name, LocalId);
|
||||||
|
|
||||||
|
return;
|
||||||
|
|
||||||
if (ParentGroup.IsDeleted)
|
if (ParentGroup.IsDeleted)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -4994,7 +5005,7 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Update the texture entry for this part.
|
/// Update the texture entry for this part.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -5262,6 +5273,7 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
}
|
}
|
||||||
|
|
||||||
Quaternion rot = Quaternion.Slerp(RotationOffset,APIDTarget,1.0f/(float)m_APIDIterations);
|
Quaternion rot = Quaternion.Slerp(RotationOffset,APIDTarget,1.0f/(float)m_APIDIterations);
|
||||||
|
rot.Normalize();
|
||||||
UpdateRotation(rot);
|
UpdateRotation(rot);
|
||||||
|
|
||||||
m_APIDIterations--;
|
m_APIDIterations--;
|
||||||
|
|
|
@ -2190,7 +2190,7 @@ namespace OpenSim.Region.Physics.OdePlugin
|
||||||
convex = false;
|
convex = false;
|
||||||
try
|
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
|
catch
|
||||||
{
|
{
|
||||||
|
@ -2557,7 +2557,7 @@ namespace OpenSim.Region.Physics.OdePlugin
|
||||||
|
|
||||||
try
|
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
|
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);
|
||||||
IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical);
|
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 ReleaseMesh(IMesh mesh);
|
||||||
void ExpireReleaseMeshs();
|
void ExpireReleaseMeshs();
|
||||||
|
void ExpireFileCache();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Values for level of detail to be passed to the mesher.
|
// Values for level of detail to be passed to the mesher.
|
||||||
|
@ -57,6 +59,7 @@ namespace OpenSim.Region.Physics.Manager
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Serializable()]
|
||||||
[StructLayout(LayoutKind.Explicit)]
|
[StructLayout(LayoutKind.Explicit)]
|
||||||
public struct AMeshKey
|
public struct AMeshKey
|
||||||
{
|
{
|
||||||
|
@ -66,6 +69,13 @@ namespace OpenSim.Region.Physics.Manager
|
||||||
public ulong hashA;
|
public ulong hashA;
|
||||||
[FieldOffset(8)]
|
[FieldOffset(8)]
|
||||||
public ulong hashB;
|
public ulong hashB;
|
||||||
|
[FieldOffset(16)]
|
||||||
|
public ulong hashC;
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return uuid.ToString() + "-" + hashC.ToString("x") ;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface IMesh
|
public interface IMesh
|
||||||
|
@ -81,5 +91,6 @@ namespace OpenSim.Region.Physics.Manager
|
||||||
void Append(IMesh newMesh);
|
void Append(IMesh newMesh);
|
||||||
void TransformLinear(float[,] matrix, float[] offset);
|
void TransformLinear(float[,] matrix, float[] offset);
|
||||||
Vector3 GetCentroid();
|
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>
|
/// <summary>
|
||||||
/// Velocity of this actor.
|
/// Velocity of this actor.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -106,7 +106,7 @@ namespace OpenSim.Region.Physics.Manager
|
||||||
get { return new NullPhysicsScene(); }
|
get { return new NullPhysicsScene(); }
|
||||||
}
|
}
|
||||||
|
|
||||||
public RequestAssetDelegate RequestAssetMethod { private get; set; }
|
public RequestAssetDelegate RequestAssetMethod { get; set; }
|
||||||
|
|
||||||
public virtual void TriggerPhysicsBasedRestart()
|
public virtual void TriggerPhysicsBasedRestart()
|
||||||
{
|
{
|
||||||
|
@ -246,6 +246,9 @@ namespace OpenSim.Region.Physics.Manager
|
||||||
|
|
||||||
public abstract void AddPhysicsActorTaint(PhysicsActor prim);
|
public abstract void AddPhysicsActorTaint(PhysicsActor prim);
|
||||||
|
|
||||||
|
|
||||||
|
public virtual void PrepareSimulation() { }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Perform a simulation of the current physics scene over the given timestep.
|
/// Perform a simulation of the current physics scene over the given timestep.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -67,7 +67,7 @@ namespace OpenSim.Region.Physics.Manager
|
||||||
return CreateMesh(primName, primShape, size, lod, false);
|
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);
|
return CreateMesh(primName, primShape, size, lod, false);
|
||||||
}
|
}
|
||||||
|
@ -79,7 +79,14 @@ namespace OpenSim.Region.Physics.Manager
|
||||||
|
|
||||||
return null;
|
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 ReleaseMesh(IMesh mesh) { }
|
||||||
public void ExpireReleaseMeshs() { }
|
public void ExpireReleaseMeshs() { }
|
||||||
|
public void ExpireFileCache() { }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -148,6 +148,12 @@ namespace OpenSim.Region.Physics.Meshing
|
||||||
return Vector3.Zero;
|
return Vector3.Zero;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// not functional
|
||||||
|
public Vector3 GetOBB()
|
||||||
|
{
|
||||||
|
return new Vector3(0.5f, 0.5f, 0.5f);
|
||||||
|
}
|
||||||
|
|
||||||
public void CalcNormals()
|
public void CalcNormals()
|
||||||
{
|
{
|
||||||
int iTriangles = m_triangles.Count;
|
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)
|
public void getVertexListAsPtrToFloatArray(out IntPtr vertices, out int vertexStride, out int vertexCount)
|
||||||
{
|
{
|
||||||
// A vertex is 3 floats
|
// A vertex is 3 floats
|
||||||
|
|
||||||
vertexStride = 3 * sizeof(float);
|
vertexStride = 3 * sizeof(float);
|
||||||
|
|
||||||
// If there isn't an unmanaged array allocated yet, do it now
|
// If there isn't an unmanaged array allocated yet, do it now
|
||||||
|
|
|
@ -74,8 +74,6 @@ namespace OpenSim.Region.Physics.Meshing
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
private bool cacheSculptMaps = true;
|
private bool cacheSculptMaps = true;
|
||||||
private bool cacheSculptAlphaMaps = true;
|
|
||||||
|
|
||||||
private string decodedSculptMapPath = null;
|
private string decodedSculptMapPath = null;
|
||||||
private bool useMeshiesPhysicsMesh = false;
|
private bool useMeshiesPhysicsMesh = false;
|
||||||
|
|
||||||
|
@ -89,16 +87,7 @@ namespace OpenSim.Region.Physics.Meshing
|
||||||
IConfig mesh_config = config.Configs["Mesh"];
|
IConfig mesh_config = config.Configs["Mesh"];
|
||||||
|
|
||||||
decodedSculptMapPath = start_config.GetString("DecodedSculptMapPath","j2kDecodeCache");
|
decodedSculptMapPath = start_config.GetString("DecodedSculptMapPath","j2kDecodeCache");
|
||||||
|
|
||||||
cacheSculptMaps = start_config.GetBoolean("CacheSculptMaps", cacheSculptMaps);
|
cacheSculptMaps = start_config.GetBoolean("CacheSculptMaps", cacheSculptMaps);
|
||||||
|
|
||||||
if (Environment.OSVersion.Platform == PlatformID.Unix)
|
|
||||||
{
|
|
||||||
cacheSculptAlphaMaps = false;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
cacheSculptAlphaMaps = cacheSculptMaps;
|
|
||||||
|
|
||||||
if(mesh_config != null)
|
if(mesh_config != null)
|
||||||
useMeshiesPhysicsMesh = mesh_config.GetBoolean("UseMeshiesPhysicsMesh", useMeshiesPhysicsMesh);
|
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))
|
if (!GenerateCoordsAndFacesFromPrimSculptData(primName, primShape, size, lod, out coords, out faces))
|
||||||
return null;
|
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
|
else
|
||||||
{
|
{
|
||||||
if (!GenerateCoordsAndFacesFromPrimShapeData(primName, primShape, size, lod, out coords, out faces))
|
if (!GenerateCoordsAndFacesFromPrimShapeData(primName, primShape, size, lod, out coords, out faces))
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
// keep compatible
|
|
||||||
|
// Remove the reference to any JPEG2000 sculpt data so it can be GCed
|
||||||
primShape.SculptData = Utils.EmptyBytes;
|
primShape.SculptData = Utils.EmptyBytes;
|
||||||
|
|
||||||
int numCoords = coords.Count;
|
int numCoords = coords.Count;
|
||||||
|
@ -335,7 +321,7 @@ namespace OpenSim.Region.Physics.Meshing
|
||||||
|
|
||||||
if (primShape.SculptData.Length <= 0)
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -496,8 +482,7 @@ namespace OpenSim.Region.Physics.Meshing
|
||||||
|
|
||||||
//idata = CSJ2K.J2kImage.FromBytes(primShape.SculptData);
|
//idata = CSJ2K.J2kImage.FromBytes(primShape.SculptData);
|
||||||
|
|
||||||
if (cacheSculptMaps && (cacheSculptAlphaMaps || (((ImageFlags)(idata.Flags) & ImageFlags.HasAlpha) ==0)))
|
if (cacheSculptMaps)
|
||||||
// don't cache images with alpha channel in linux since mono can't load them correctly)
|
|
||||||
{
|
{
|
||||||
try { idata.Save(decodedSculptFileName, ImageFormat.MemoryBmp); }
|
try { idata.Save(decodedSculptFileName, ImageFormat.MemoryBmp); }
|
||||||
catch (Exception e) { m_log.Error("[SCULPT]: unable to cache sculpt map " + decodedSculptFileName + " " + e.Message); }
|
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);
|
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);
|
return CreateMesh(primName, primShape, size, lod, false);
|
||||||
}
|
}
|
||||||
|
@ -763,7 +748,13 @@ namespace OpenSim.Region.Physics.Meshing
|
||||||
|
|
||||||
return mesh;
|
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 ReleaseMesh(IMesh imesh) { }
|
||||||
public void ExpireReleaseMeshs() { }
|
public void ExpireReleaseMeshs() { }
|
||||||
|
public void ExpireFileCache() { }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -100,6 +100,9 @@ namespace OpenSim.Region.Physics.OdePlugin
|
||||||
private Vector3 m_taintAngularLock = Vector3.One;
|
private Vector3 m_taintAngularLock = Vector3.One;
|
||||||
private IntPtr Amotor = IntPtr.Zero;
|
private IntPtr Amotor = IntPtr.Zero;
|
||||||
|
|
||||||
|
private object m_assetsLock = new object();
|
||||||
|
private bool m_assetFailed = false;
|
||||||
|
|
||||||
private Vector3 m_PIDTarget;
|
private Vector3 m_PIDTarget;
|
||||||
private float m_PIDTau;
|
private float m_PIDTau;
|
||||||
private float PID_D = 35f;
|
private float PID_D = 35f;
|
||||||
|
@ -282,6 +285,7 @@ namespace OpenSim.Region.Physics.OdePlugin
|
||||||
}
|
}
|
||||||
|
|
||||||
m_taintadd = true;
|
m_taintadd = true;
|
||||||
|
m_assetFailed = false;
|
||||||
_parent_scene.AddPhysicsActorTaint(this);
|
_parent_scene.AddPhysicsActorTaint(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -604,8 +608,8 @@ namespace OpenSim.Region.Physics.OdePlugin
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case HollowShape.Circle:
|
case HollowShape.Circle:
|
||||||
// Hollow shape is a perfect cylinder in respect to the cube's scale
|
// Hollow shape is a perfect cyllinder in respect to the cube's scale
|
||||||
// Cylinder hollow volume calculation
|
// Cyllinder hollow volume calculation
|
||||||
|
|
||||||
hollowVolume *= 0.1963495f * 3.07920140172638f;
|
hollowVolume *= 0.1963495f * 3.07920140172638f;
|
||||||
break;
|
break;
|
||||||
|
@ -1498,6 +1502,8 @@ Console.WriteLine("CreateGeom:");
|
||||||
mesh = _parent_scene.mesher.CreateMesh(Name, _pbs, _size, _parent_scene.meshSculptLOD, IsPhysical);
|
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.
|
// createmesh returns null when it's a shape that isn't a cube.
|
||||||
// m_log.Debug(m_localID);
|
// m_log.Debug(m_localID);
|
||||||
|
if (mesh == null)
|
||||||
|
CheckMeshAsset();
|
||||||
}
|
}
|
||||||
|
|
||||||
#if SPAM
|
#if SPAM
|
||||||
|
@ -1997,7 +2003,12 @@ Console.WriteLine(" JointCreateFixed");
|
||||||
// Don't need to re-enable body.. it's done in SetMesh
|
// Don't need to re-enable body.. it's done in SetMesh
|
||||||
|
|
||||||
if (_parent_scene.needsMeshing(_pbs))
|
if (_parent_scene.needsMeshing(_pbs))
|
||||||
|
{
|
||||||
mesh = _parent_scene.mesher.CreateMesh(Name, _pbs, _size, meshlod, IsPhysical);
|
mesh = _parent_scene.mesher.CreateMesh(Name, _pbs, _size, meshlod, IsPhysical);
|
||||||
|
if (mesh == null)
|
||||||
|
CheckMeshAsset();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CreateGeom(m_targetSpace, mesh);
|
CreateGeom(m_targetSpace, mesh);
|
||||||
|
@ -2057,6 +2068,8 @@ Console.WriteLine(" JointCreateFixed");
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private void changeshape()
|
private void changeshape()
|
||||||
{
|
{
|
||||||
|
m_taintshape = false;
|
||||||
|
|
||||||
// Cleanup of old prim geometry and Bodies
|
// Cleanup of old prim geometry and Bodies
|
||||||
if (IsPhysical && Body != IntPtr.Zero)
|
if (IsPhysical && Body != IntPtr.Zero)
|
||||||
{
|
{
|
||||||
|
@ -2084,6 +2097,7 @@ Console.WriteLine(" JointCreateFixed");
|
||||||
|
|
||||||
IMesh mesh = null;
|
IMesh mesh = null;
|
||||||
|
|
||||||
|
|
||||||
if (_parent_scene.needsMeshing(_pbs))
|
if (_parent_scene.needsMeshing(_pbs))
|
||||||
{
|
{
|
||||||
// Don't need to re-enable body.. it's done in CreateMesh
|
// 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.
|
// createmesh returns null when it doesn't mesh.
|
||||||
mesh = _parent_scene.mesher.CreateMesh(Name, _pbs, _size, meshlod, IsPhysical);
|
mesh = _parent_scene.mesher.CreateMesh(Name, _pbs, _size, meshlod, IsPhysical);
|
||||||
|
if (mesh == null)
|
||||||
|
CheckMeshAsset();
|
||||||
}
|
}
|
||||||
|
|
||||||
CreateGeom(m_targetSpace, mesh);
|
CreateGeom(m_targetSpace, mesh);
|
||||||
|
@ -2130,7 +2146,7 @@ Console.WriteLine(" JointCreateFixed");
|
||||||
}
|
}
|
||||||
|
|
||||||
resetCollisionAccounting();
|
resetCollisionAccounting();
|
||||||
m_taintshape = false;
|
// m_taintshape = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -2396,6 +2412,7 @@ Console.WriteLine(" JointCreateFixed");
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
_pbs = value;
|
_pbs = value;
|
||||||
|
m_assetFailed = false;
|
||||||
m_taintshape = true;
|
m_taintshape = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3234,5 +3251,37 @@ Console.WriteLine(" JointCreateFixed");
|
||||||
{
|
{
|
||||||
m_material = pMaterial;
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -136,17 +136,10 @@ namespace OpenSim.Region.Physics.OdePlugin
|
||||||
{
|
{
|
||||||
ODERayCastRequest[] reqs = m_PendingRequests.ToArray();
|
ODERayCastRequest[] reqs = m_PendingRequests.ToArray();
|
||||||
for (int i = 0; i < reqs.Length; i++)
|
for (int i = 0; i < reqs.Length; i++)
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
{
|
||||||
if (reqs[i].callbackMethod != null) // quick optimization here, don't raycast
|
if (reqs[i].callbackMethod != null) // quick optimization here, don't raycast
|
||||||
RayCast(reqs[i]); // if there isn't anyone to send results
|
RayCast(reqs[i]); // if there isn't anyone to send results
|
||||||
}
|
}
|
||||||
catch
|
|
||||||
{
|
|
||||||
//Fail silently
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
m_PendingRequests.Clear();
|
m_PendingRequests.Clear();
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,24 +32,49 @@ using System.Runtime.InteropServices;
|
||||||
using OpenSim.Region.Physics.Manager;
|
using OpenSim.Region.Physics.Manager;
|
||||||
using PrimMesher;
|
using PrimMesher;
|
||||||
using OpenMetaverse;
|
using OpenMetaverse;
|
||||||
|
using System.Runtime.Serialization;
|
||||||
|
using System.Runtime.Serialization.Formatters.Binary;
|
||||||
|
|
||||||
namespace OpenSim.Region.Physics.Meshing
|
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
|
public class Mesh : IMesh
|
||||||
{
|
{
|
||||||
|
float[] vertices;
|
||||||
private Dictionary<Vertex, int> m_vertices;
|
int[] indexes;
|
||||||
private List<Triangle> m_triangles;
|
Vector3 m_obb;
|
||||||
GCHandle m_pinnedVertexes;
|
Vector3 m_obboffset;
|
||||||
GCHandle m_pinnedIndex;
|
[NonSerialized()]
|
||||||
|
MeshBuildingData m_bdata;
|
||||||
|
[NonSerialized()]
|
||||||
|
GCHandle vhandler;
|
||||||
|
[NonSerialized()]
|
||||||
|
GCHandle ihandler;
|
||||||
|
[NonSerialized()]
|
||||||
IntPtr m_verticesPtr = IntPtr.Zero;
|
IntPtr m_verticesPtr = IntPtr.Zero;
|
||||||
int m_vertexCount = 0;
|
[NonSerialized()]
|
||||||
IntPtr m_indicesPtr = IntPtr.Zero;
|
IntPtr m_indicesPtr = IntPtr.Zero;
|
||||||
|
[NonSerialized()]
|
||||||
|
int m_vertexCount = 0;
|
||||||
|
[NonSerialized()]
|
||||||
int m_indexCount = 0;
|
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>
|
private class vertexcomp : IEqualityComparer<Vertex>
|
||||||
{
|
{
|
||||||
|
@ -73,43 +98,119 @@ namespace OpenSim.Region.Physics.Meshing
|
||||||
{
|
{
|
||||||
vertexcomp vcomp = new vertexcomp();
|
vertexcomp vcomp = new vertexcomp();
|
||||||
|
|
||||||
m_vertices = new Dictionary<Vertex, int>(vcomp);
|
m_bdata = new MeshBuildingData();
|
||||||
m_triangles = new List<Triangle>();
|
m_bdata.m_vertices = new Dictionary<Vertex, int>(vcomp);
|
||||||
m_centroid = Vector3.Zero;
|
m_bdata.m_triangles = new List<Triangle>();
|
||||||
m_centroidDiv = 0;
|
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 Mesh Scale(Vector3 scale)
|
||||||
|
|
||||||
public void 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()
|
public Mesh Clone()
|
||||||
{
|
{
|
||||||
Mesh result = new Mesh();
|
Mesh result = new Mesh();
|
||||||
|
|
||||||
foreach (Triangle t in m_triangles)
|
if (m_bdata != null)
|
||||||
|
{
|
||||||
|
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.Add(new Triangle(t.v1.Clone(), t.v2.Clone(), t.v3.Clone()));
|
||||||
}
|
}
|
||||||
result.m_centroid = m_centroid;
|
result.m_bdata.m_centroid = m_bdata.m_centroid;
|
||||||
result.m_centroidDiv = m_centroidDiv;
|
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_obb = m_obb;
|
||||||
|
result.m_obboffset = m_obboffset;
|
||||||
return result;
|
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)
|
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");
|
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)
|
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.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)
|
|| (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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_vertices.Count == 0)
|
if (m_bdata.m_vertices.Count == 0)
|
||||||
{
|
{
|
||||||
m_centroidDiv = 0;
|
m_bdata.m_centroidDiv = 0;
|
||||||
m_centroid = Vector3.Zero;
|
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_bdata.m_vertices[triangle.v1] = m_bdata.m_vertices.Count;
|
||||||
m_centroid.X += triangle.v1.X;
|
addVertexLStats(triangle.v1);
|
||||||
m_centroid.Y += triangle.v1.Y;
|
|
||||||
m_centroid.Z += triangle.v1.Z;
|
|
||||||
m_centroidDiv++;
|
|
||||||
}
|
}
|
||||||
if (!m_vertices.ContainsKey(triangle.v2))
|
if (!m_bdata.m_vertices.ContainsKey(triangle.v2))
|
||||||
{
|
{
|
||||||
m_vertices[triangle.v2] = m_vertices.Count;
|
m_bdata.m_vertices[triangle.v2] = m_bdata.m_vertices.Count;
|
||||||
m_centroid.X += triangle.v2.X;
|
addVertexLStats(triangle.v2);
|
||||||
m_centroid.Y += triangle.v2.Y;
|
|
||||||
m_centroid.Z += triangle.v2.Z;
|
|
||||||
m_centroidDiv++;
|
|
||||||
}
|
}
|
||||||
if (!m_vertices.ContainsKey(triangle.v3))
|
if (!m_bdata.m_vertices.ContainsKey(triangle.v3))
|
||||||
{
|
{
|
||||||
m_vertices[triangle.v3] = m_vertices.Count;
|
m_bdata.m_vertices[triangle.v3] = m_bdata.m_vertices.Count;
|
||||||
m_centroid.X += triangle.v3.X;
|
addVertexLStats(triangle.v3);
|
||||||
m_centroid.Y += triangle.v3.Y;
|
|
||||||
m_centroid.Z += triangle.v3.Z;
|
|
||||||
m_centroidDiv++;
|
|
||||||
}
|
}
|
||||||
m_triangles.Add(triangle);
|
m_bdata.m_triangles.Add(triangle);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Vector3 GetCentroid()
|
public Vector3 GetCentroid()
|
||||||
{
|
{
|
||||||
if (m_centroidDiv > 0)
|
return m_obboffset;
|
||||||
return new Vector3(m_centroid.X / m_centroidDiv, m_centroid.Y / m_centroidDiv, m_centroid.Z / m_centroidDiv);
|
|
||||||
else
|
|
||||||
return Vector3.Zero;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void CalcNormals()
|
public Vector3 GetOBB()
|
||||||
{
|
{
|
||||||
int iTriangles = m_triangles.Count;
|
return m_obb;
|
||||||
|
float x, y, z;
|
||||||
this.m_normals = new float[iTriangles * 3];
|
if (m_bdata.m_centroidDiv > 0)
|
||||||
|
|
||||||
int i = 0;
|
|
||||||
foreach (Triangle t in m_triangles)
|
|
||||||
{
|
{
|
||||||
float ux, uy, uz;
|
x = (m_bdata.m_obbXmax - m_bdata.m_obbXmin) * 0.5f;
|
||||||
float vx, vy, vz;
|
y = (m_bdata.m_obbYmax - m_bdata.m_obbYmin) * 0.5f;
|
||||||
float wx, wy, wz;
|
z = (m_bdata.m_obbZmax - m_bdata.m_obbZmin) * 0.5f;
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
else // ??
|
||||||
|
{
|
||||||
|
x = 0.5f;
|
||||||
|
y = 0.5f;
|
||||||
|
z = 0.5f;
|
||||||
|
}
|
||||||
|
return new Vector3(x, y, z);
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Vector3> getVertexList()
|
public List<Vector3> getVertexList()
|
||||||
{
|
{
|
||||||
List<Vector3> result = new List<Vector3>();
|
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));
|
result.Add(new Vector3(v.X, v.Y, v.Z));
|
||||||
}
|
}
|
||||||
|
@ -233,10 +280,10 @@ namespace OpenSim.Region.Physics.Meshing
|
||||||
|
|
||||||
private float[] getVertexListAsFloat()
|
private float[] getVertexListAsFloat()
|
||||||
{
|
{
|
||||||
if (m_vertices == null)
|
if (m_bdata.m_vertices == null)
|
||||||
throw new NotSupportedException();
|
throw new NotSupportedException();
|
||||||
float[] result = new float[m_vertices.Count * 3];
|
float[] result = new float[m_bdata.m_vertices.Count * 3];
|
||||||
foreach (KeyValuePair<Vertex, int> kvp in m_vertices)
|
foreach (KeyValuePair<Vertex, int> kvp in m_bdata.m_vertices)
|
||||||
{
|
{
|
||||||
Vertex v = kvp.Key;
|
Vertex v = kvp.Key;
|
||||||
int i = kvp.Value;
|
int i = kvp.Value;
|
||||||
|
@ -249,48 +296,39 @@ namespace OpenSim.Region.Physics.Meshing
|
||||||
|
|
||||||
public float[] getVertexListAsFloatLocked()
|
public float[] getVertexListAsFloatLocked()
|
||||||
{
|
{
|
||||||
if (m_pinnedVertexes.IsAllocated)
|
return null;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
// A vertex is 3 floats
|
||||||
vertexStride = 3 * sizeof(float);
|
vertexStride = 3 * sizeof(float);
|
||||||
|
|
||||||
// If there isn't an unmanaged array allocated yet, do it now
|
// 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)
|
// Each vertex is 3 elements (floats)
|
||||||
m_vertexCount = vertexList.Length / 3;
|
m_vertexCount = vertices.Length / 3;
|
||||||
int byteCount = m_vertexCount * vertexStride;
|
vhandler = GCHandle.Alloc(vertices, GCHandleType.Pinned);
|
||||||
m_verticesPtr = System.Runtime.InteropServices.Marshal.AllocHGlobal(byteCount);
|
m_verticesPtr = vhandler.AddrOfPinnedObject();
|
||||||
System.Runtime.InteropServices.Marshal.Copy(vertexList, 0, m_verticesPtr, m_vertexCount * 3);
|
GC.AddMemoryPressure(Buffer.ByteLength(vertices));
|
||||||
}
|
}
|
||||||
vertices = m_verticesPtr;
|
_vertices = m_verticesPtr;
|
||||||
vertexCount = m_vertexCount;
|
vertexCount = m_vertexCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int[] getIndexListAsInt()
|
public int[] getIndexListAsInt()
|
||||||
{
|
{
|
||||||
if (m_triangles == null)
|
if (m_bdata.m_triangles == null)
|
||||||
throw new NotSupportedException();
|
throw new NotSupportedException();
|
||||||
int[] result = new int[m_triangles.Count * 3];
|
int[] result = new int[m_bdata.m_triangles.Count * 3];
|
||||||
for (int i = 0; i < m_triangles.Count; i++)
|
for (int i = 0; i < m_bdata.m_triangles.Count; i++)
|
||||||
{
|
{
|
||||||
Triangle t = m_triangles[i];
|
Triangle t = m_bdata.m_triangles[i];
|
||||||
result[3 * i + 0] = m_vertices[t.v1];
|
result[3 * i + 0] = m_bdata.m_vertices[t.v1];
|
||||||
result[3 * i + 1] = m_vertices[t.v2];
|
result[3 * i + 1] = m_bdata.m_vertices[t.v2];
|
||||||
result[3 * i + 2] = m_vertices[t.v3];
|
result[3 * i + 2] = m_bdata.m_vertices[t.v3];
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -301,28 +339,19 @@ namespace OpenSim.Region.Physics.Meshing
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public int[] getIndexListAsIntLocked()
|
public int[] getIndexListAsIntLocked()
|
||||||
{
|
{
|
||||||
if (m_pinnedIndex.IsAllocated)
|
return null;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void getIndexListAsPtrToIntArray(out IntPtr indices, out int triStride, out int indexCount)
|
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 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();
|
indexes = getIndexListAsInt();
|
||||||
m_indexCount = indexList.Length;
|
m_indexCount = indexes.Length;
|
||||||
int byteCount = m_indexCount * sizeof(int);
|
ihandler = GCHandle.Alloc(indexes, GCHandleType.Pinned);
|
||||||
m_indicesPtr = System.Runtime.InteropServices.Marshal.AllocHGlobal(byteCount);
|
m_indicesPtr = ihandler.AddrOfPinnedObject();
|
||||||
System.Runtime.InteropServices.Marshal.Copy(indexList, 0, m_indicesPtr, m_indexCount);
|
GC.AddMemoryPressure(Buffer.ByteLength(indexes));
|
||||||
}
|
}
|
||||||
// A triangle is 3 ints (indices)
|
// A triangle is 3 ints (indices)
|
||||||
triStride = 3 * sizeof(int);
|
triStride = 3 * sizeof(int);
|
||||||
|
@ -332,18 +361,16 @@ namespace OpenSim.Region.Physics.Meshing
|
||||||
|
|
||||||
public void releasePinned()
|
public void releasePinned()
|
||||||
{
|
{
|
||||||
if (m_pinnedVertexes.IsAllocated)
|
|
||||||
m_pinnedVertexes.Free();
|
|
||||||
if (m_pinnedIndex.IsAllocated)
|
|
||||||
m_pinnedIndex.Free();
|
|
||||||
if (m_verticesPtr != IntPtr.Zero)
|
if (m_verticesPtr != IntPtr.Zero)
|
||||||
{
|
{
|
||||||
System.Runtime.InteropServices.Marshal.FreeHGlobal(m_verticesPtr);
|
vhandler.Free();
|
||||||
|
vertices = null;
|
||||||
m_verticesPtr = IntPtr.Zero;
|
m_verticesPtr = IntPtr.Zero;
|
||||||
}
|
}
|
||||||
if (m_indicesPtr != IntPtr.Zero)
|
if (m_indicesPtr != IntPtr.Zero)
|
||||||
{
|
{
|
||||||
System.Runtime.InteropServices.Marshal.FreeHGlobal(m_indicesPtr);
|
ihandler.Free();
|
||||||
|
indexes = null;
|
||||||
m_indicesPtr = IntPtr.Zero;
|
m_indicesPtr = IntPtr.Zero;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -353,29 +380,42 @@ namespace OpenSim.Region.Physics.Meshing
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void releaseSourceMeshData()
|
public void releaseSourceMeshData()
|
||||||
{
|
{
|
||||||
m_triangles = null;
|
if (m_bdata != null)
|
||||||
m_vertices = 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)
|
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");
|
throw new NotSupportedException("Attempt to Append to a pinned Mesh");
|
||||||
|
|
||||||
if (!(newMesh is Mesh))
|
if (!(newMesh is Mesh))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
foreach (Triangle t in ((Mesh)newMesh).m_triangles)
|
foreach (Triangle t in ((Mesh)newMesh).m_bdata.m_triangles)
|
||||||
Add(t);
|
Add(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Do a linear transformation of mesh.
|
// Do a linear transformation of mesh.
|
||||||
public void TransformLinear(float[,] matrix, float[] offset)
|
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");
|
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)
|
if (v == null)
|
||||||
continue;
|
continue;
|
||||||
|
@ -393,10 +433,12 @@ namespace OpenSim.Region.Physics.Meshing
|
||||||
{
|
{
|
||||||
if (path == null)
|
if (path == null)
|
||||||
return;
|
return;
|
||||||
|
if (m_bdata == null)
|
||||||
|
return;
|
||||||
String fileName = name + "_" + title + ".raw";
|
String fileName = name + "_" + title + ".raw";
|
||||||
String completePath = System.IO.Path.Combine(path, fileName);
|
String completePath = System.IO.Path.Combine(path, fileName);
|
||||||
StreamWriter sw = new StreamWriter(completePath);
|
StreamWriter sw = new StreamWriter(completePath);
|
||||||
foreach (Triangle t in m_triangles)
|
foreach (Triangle t in m_bdata.m_triangles)
|
||||||
{
|
{
|
||||||
String s = t.ToStringRaw();
|
String s = t.ToStringRaw();
|
||||||
sw.WriteLine(s);
|
sw.WriteLine(s);
|
||||||
|
@ -406,7 +448,144 @@ namespace OpenSim.Region.Physics.Meshing
|
||||||
|
|
||||||
public void TrimExcess()
|
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 System.IO;
|
||||||
using ComponentAce.Compression.Libs.zlib;
|
using ComponentAce.Compression.Libs.zlib;
|
||||||
using OpenSim.Region.Physics.ConvexDecompositionDotNet;
|
using OpenSim.Region.Physics.ConvexDecompositionDotNet;
|
||||||
|
using System.Runtime.Serialization;
|
||||||
|
using System.Runtime.Serialization.Formatters.Binary;
|
||||||
|
|
||||||
namespace OpenSim.Region.Physics.Meshing
|
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
|
// 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
|
// raw files can be imported by blender so a visual inspection of the results can be done
|
||||||
#if SPAM
|
|
||||||
const string baseDir = "rawFiles";
|
public object diskLock = new object();
|
||||||
#else
|
|
||||||
|
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";
|
private const string baseDir = null; //"rawFiles";
|
||||||
#endif
|
|
||||||
|
|
||||||
private bool cacheSculptMaps = true;
|
|
||||||
private bool cacheSculptAlphaMaps = true;
|
|
||||||
|
|
||||||
private string decodedSculptMapPath = null;
|
|
||||||
private bool useMeshiesPhysicsMesh = false;
|
private bool useMeshiesPhysicsMesh = false;
|
||||||
|
|
||||||
private float minSizeForComplexMesh = 0.2f; // prims with all dimensions smaller than this will have a bounding box mesh
|
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_uniqueMeshes = new Dictionary<AMeshKey, Mesh>();
|
||||||
private Dictionary<AMeshKey, Mesh> m_uniqueReleasedMeshes = 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 start_config = config.Configs["Startup"];
|
||||||
IConfig mesh_config = config.Configs["Mesh"];
|
IConfig mesh_config = config.Configs["Mesh"];
|
||||||
|
|
||||||
decodedSculptMapPath = start_config.GetString("DecodedSculptMapPath","j2kDecodeCache");
|
|
||||||
|
|
||||||
cacheSculptMaps = start_config.GetBoolean("CacheSculptMaps", cacheSculptMaps);
|
float fcache = 48.0f;
|
||||||
|
// float fcache = 0.02f;
|
||||||
if (Environment.OSVersion.Platform == PlatformID.Unix)
|
|
||||||
{
|
|
||||||
cacheSculptAlphaMaps = false;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
cacheSculptAlphaMaps = cacheSculptMaps;
|
|
||||||
|
|
||||||
if(mesh_config != null)
|
if(mesh_config != null)
|
||||||
|
{
|
||||||
useMeshiesPhysicsMesh = mesh_config.GetBoolean("UseMeshiesPhysicsMesh", useMeshiesPhysicsMesh);
|
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>
|
/// <summary>
|
||||||
|
@ -212,7 +214,7 @@ namespace OpenSim.Region.Physics.Meshing
|
||||||
/// <param name="size">Size of entire object</param>
|
/// <param name="size">Size of entire object</param>
|
||||||
/// <param name="coords"></param>
|
/// <param name="coords"></param>
|
||||||
/// <param name="faces"></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));
|
// 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);
|
ushort uZ = Utils.BytesToUInt16(posBytes, i + 4);
|
||||||
|
|
||||||
Coord c = new Coord(
|
Coord c = new Coord(
|
||||||
Utils.UInt16ToFloat(uX, posMin.X, posMax.X) * size.X,
|
Utils.UInt16ToFloat(uX, posMin.X, posMax.X),
|
||||||
Utils.UInt16ToFloat(uY, posMin.Y, posMax.Y) * size.Y,
|
Utils.UInt16ToFloat(uY, posMin.Y, posMax.Y),
|
||||||
Utils.UInt16ToFloat(uZ, posMin.Z, posMax.Z) * size.Z);
|
Utils.UInt16ToFloat(uZ, posMin.Z, posMax.Z));
|
||||||
|
|
||||||
coords.Add(c);
|
coords.Add(c);
|
||||||
}
|
}
|
||||||
|
@ -271,7 +273,7 @@ namespace OpenSim.Region.Physics.Meshing
|
||||||
/// <param name="size"></param>
|
/// <param name="size"></param>
|
||||||
/// <param name="lod"></param>
|
/// <param name="lod"></param>
|
||||||
/// <returns></returns>
|
/// <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(
|
// m_log.DebugFormat(
|
||||||
// "[MESH]: Creating physics proxy for {0}, shape {1}",
|
// "[MESH]: Creating physics proxy for {0}, shape {1}",
|
||||||
|
@ -287,18 +289,18 @@ namespace OpenSim.Region.Physics.Meshing
|
||||||
if (!useMeshiesPhysicsMesh)
|
if (!useMeshiesPhysicsMesh)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
if (!GenerateCoordsAndFacesFromPrimMeshData(primName, primShape, size, out coords, out faces, convex))
|
if (!GenerateCoordsAndFacesFromPrimMeshData(primName, primShape, out coords, out faces, convex))
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (!GenerateCoordsAndFacesFromPrimSculptData(primName, primShape, size, lod, out coords, out faces))
|
if (!GenerateCoordsAndFacesFromPrimSculptData(primName, primShape, lod, out coords, out faces))
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (!GenerateCoordsAndFacesFromPrimShapeData(primName, primShape, size, lod, out coords, out faces))
|
if (!GenerateCoordsAndFacesFromPrimShapeData(primName, primShape, lod, out coords, out faces))
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -333,7 +335,7 @@ namespace OpenSim.Region.Physics.Meshing
|
||||||
/// <param name="faces">Faces are added to this list by the method.</param>
|
/// <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>
|
/// <returns>true if coords and faces were successfully generated, false if not</returns>
|
||||||
private bool GenerateCoordsAndFacesFromPrimMeshData(
|
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);
|
// 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)
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -406,7 +408,7 @@ namespace OpenSim.Region.Physics.Meshing
|
||||||
OSD decodedMeshOsd = new OSD();
|
OSD decodedMeshOsd = new OSD();
|
||||||
byte[] meshBytes = new byte[physSize];
|
byte[] meshBytes = new byte[physSize];
|
||||||
System.Buffer.BlockCopy(primShape.SculptData, physOffset, meshBytes, 0, physSize);
|
System.Buffer.BlockCopy(primShape.SculptData, physOffset, meshBytes, 0, physSize);
|
||||||
// byte[] decompressed = new byte[physSize * 5];
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
using (MemoryStream inMs = new MemoryStream(meshBytes))
|
using (MemoryStream inMs = new MemoryStream(meshBytes))
|
||||||
|
@ -450,7 +452,7 @@ namespace OpenSim.Region.Physics.Meshing
|
||||||
foreach (OSD subMeshOsd in decodedMeshOsdArray)
|
foreach (OSD subMeshOsd in decodedMeshOsdArray)
|
||||||
{
|
{
|
||||||
if (subMeshOsd is OSDMap)
|
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++];
|
||||||
t3 += data[ptr++] << 8;
|
t3 += data[ptr++] << 8;
|
||||||
|
|
||||||
f3 = new float3((t1 * range.X + min.X) * size.X,
|
f3 = new float3((t1 * range.X + min.X),
|
||||||
(t2 * range.Y + min.Y) * size.Y,
|
(t2 * range.Y + min.Y),
|
||||||
(t3 * range.Z + min.Z) * size.Z);
|
(t3 * range.Z + min.Z));
|
||||||
vs.Add(f3);
|
vs.Add(f3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -621,9 +623,9 @@ namespace OpenSim.Region.Physics.Meshing
|
||||||
t3 = data[i++];
|
t3 = data[i++];
|
||||||
t3 += data[i++] << 8;
|
t3 += data[i++] << 8;
|
||||||
|
|
||||||
f3 = new float3((t1 * range.X + min.X) * size.X,
|
f3 = new float3((t1 * range.X + min.X),
|
||||||
(t2 * range.Y + min.Y) * size.Y,
|
(t2 * range.Y + min.Y),
|
||||||
(t3 * range.Z + min.Z) * size.Z);
|
(t3 * range.Z + min.Z));
|
||||||
vs.Add(f3);
|
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>
|
/// <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>
|
/// <returns>true if coords and faces were successfully generated, false if not</returns>
|
||||||
private bool GenerateCoordsAndFacesFromPrimSculptData(
|
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>();
|
coords = new List<Coord>();
|
||||||
faces = new List<Face>();
|
faces = new List<Face>();
|
||||||
PrimMesher.SculptMesh sculptMesh;
|
PrimMesher.SculptMesh sculptMesh;
|
||||||
Image idata = null;
|
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)
|
if (primShape.SculptData == null || primShape.SculptData.Length == 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -748,25 +728,15 @@ namespace OpenSim.Region.Physics.Meshing
|
||||||
OpenMetaverse.Imaging.ManagedImage unusedData;
|
OpenMetaverse.Imaging.ManagedImage unusedData;
|
||||||
OpenMetaverse.Imaging.OpenJPEG.DecodeToImage(primShape.SculptData, out unusedData, out idata);
|
OpenMetaverse.Imaging.OpenJPEG.DecodeToImage(primShape.SculptData, out unusedData, out idata);
|
||||||
|
|
||||||
|
unusedData = null;
|
||||||
|
|
||||||
if (idata == null)
|
if (idata == null)
|
||||||
{
|
{
|
||||||
// In some cases it seems that the decode can return a null bitmap without throwing
|
// In some cases it seems that the decode can return a null bitmap without throwing
|
||||||
// an exception
|
// an exception
|
||||||
m_log.WarnFormat("[PHYSICS]: OpenJPEG decoded sculpt data for {0} to a null bitmap. Ignoring.", primName);
|
m_log.WarnFormat("[PHYSICS]: OpenJPEG decoded sculpt data for {0} to a null bitmap. Ignoring.", primName);
|
||||||
|
|
||||||
return false;
|
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)
|
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);
|
m_log.Error("[PHYSICS]: Unable to generate a Sculpty physics proxy. Sculpty texture decode failed: " + ex.Message);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
PrimMesher.SculptMesh.SculptType sculptType;
|
PrimMesher.SculptMesh.SculptType sculptType;
|
||||||
// remove mirror and invert bits
|
// remove mirror and invert bits
|
||||||
|
@ -814,9 +783,7 @@ namespace OpenSim.Region.Physics.Meshing
|
||||||
|
|
||||||
idata.Dispose();
|
idata.Dispose();
|
||||||
|
|
||||||
sculptMesh.DumpRaw(baseDir, primName, "primMesh");
|
// sculptMesh.DumpRaw(baseDir, primName, "primMesh");
|
||||||
|
|
||||||
sculptMesh.Scale(size.X, size.Y, size.Z);
|
|
||||||
|
|
||||||
coords = sculptMesh.coords;
|
coords = sculptMesh.coords;
|
||||||
faces = sculptMesh.faces;
|
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>
|
/// <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>
|
/// <returns>true if coords and faces were successfully generated, false if not</returns>
|
||||||
private bool GenerateCoordsAndFacesFromPrimShapeData(
|
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;
|
PrimMesh primMesh;
|
||||||
coords = new List<Coord>();
|
coords = new List<Coord>();
|
||||||
|
@ -969,9 +936,7 @@ namespace OpenSim.Region.Physics.Meshing
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
primMesh.DumpRaw(baseDir, primName, "primMesh");
|
// primMesh.DumpRaw(baseDir, primName, "primMesh");
|
||||||
|
|
||||||
primMesh.Scale(size.X, size.Y, size.Z);
|
|
||||||
|
|
||||||
coords = primMesh.coords;
|
coords = primMesh.coords;
|
||||||
faces = primMesh.faces;
|
faces = primMesh.faces;
|
||||||
|
@ -985,12 +950,14 @@ namespace OpenSim.Region.Physics.Meshing
|
||||||
Byte[] someBytes;
|
Byte[] someBytes;
|
||||||
|
|
||||||
key.hashB = 5181;
|
key.hashB = 5181;
|
||||||
|
key.hashC = 5181;
|
||||||
ulong hash = 5381;
|
ulong hash = 5381;
|
||||||
|
|
||||||
if (primShape.SculptEntry)
|
if (primShape.SculptEntry)
|
||||||
{
|
{
|
||||||
key.uuid = primShape.SculptTexture;
|
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
|
else
|
||||||
{
|
{
|
||||||
|
@ -1002,6 +969,8 @@ namespace OpenSim.Region.Physics.Meshing
|
||||||
hash = mdjb2(hash, primShape.PathScaleX);
|
hash = mdjb2(hash, primShape.PathScaleX);
|
||||||
hash = mdjb2(hash, primShape.PathScaleY);
|
hash = mdjb2(hash, primShape.PathScaleY);
|
||||||
hash = mdjb2(hash, primShape.PathShearX);
|
hash = mdjb2(hash, primShape.PathShearX);
|
||||||
|
key.hashA = hash;
|
||||||
|
hash = key.hashB;
|
||||||
hash = mdjb2(hash, primShape.PathShearY);
|
hash = mdjb2(hash, primShape.PathShearY);
|
||||||
hash = mdjb2(hash, (byte)primShape.PathTwist);
|
hash = mdjb2(hash, (byte)primShape.PathTwist);
|
||||||
hash = mdjb2(hash, (byte)primShape.PathTwistBegin);
|
hash = mdjb2(hash, (byte)primShape.PathTwistBegin);
|
||||||
|
@ -1013,26 +982,38 @@ namespace OpenSim.Region.Physics.Meshing
|
||||||
hash = mdjb2(hash, primShape.ProfileBegin);
|
hash = mdjb2(hash, primShape.ProfileBegin);
|
||||||
hash = mdjb2(hash, primShape.ProfileEnd);
|
hash = mdjb2(hash, primShape.ProfileEnd);
|
||||||
hash = mdjb2(hash, primShape.ProfileHollow);
|
hash = mdjb2(hash, primShape.ProfileHollow);
|
||||||
key.hashA = hash;
|
hash = mdjb2(hash, primShape.PCode);
|
||||||
|
key.hashB = hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
hash = key.hashB;
|
hash = key.hashC;
|
||||||
|
|
||||||
someBytes = size.GetBytes();
|
|
||||||
for (int i = 0; i < someBytes.Length; i++)
|
|
||||||
hash = mdjb2(hash, someBytes[i]);
|
|
||||||
|
|
||||||
hash = mdjb2(hash, lod);
|
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)
|
if (convex)
|
||||||
hash |= 0x4000000000000000;
|
hash |= 4;
|
||||||
|
|
||||||
if (primShape.SculptEntry)
|
if (primShape.SculptEntry)
|
||||||
hash |= 0x8000000000000000;
|
{
|
||||||
|
hash |= 1;
|
||||||
|
if (primShape.SculptType == (byte)SculptType.Mesh)
|
||||||
|
hash |= 2;
|
||||||
|
}
|
||||||
|
|
||||||
key.hashB = hash;
|
key.hashC = hash;
|
||||||
|
|
||||||
return key;
|
return key;
|
||||||
}
|
}
|
||||||
|
@ -1048,35 +1029,74 @@ namespace OpenSim.Region.Physics.Meshing
|
||||||
return ((hash << 5) + hash) + (ulong)(c >> 8);
|
return ((hash << 5) + hash) + (ulong)(c >> 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod)
|
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)
|
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
|
#if SPAM
|
||||||
m_log.DebugFormat("[MESH]: Creating mesh for {0}", primName);
|
m_log.DebugFormat("[MESH]: Creating mesh for {0}", primName);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
Mesh mesh = null;
|
Mesh mesh = null;
|
||||||
// ulong key = 0;
|
|
||||||
|
|
||||||
|
|
||||||
if (size.X < 0.01f) size.X = 0.01f;
|
if (size.X < 0.01f) size.X = 0.01f;
|
||||||
if (size.Y < 0.01f) size.Y = 0.01f;
|
if (size.Y < 0.01f) size.Y = 0.01f;
|
||||||
if (size.Z < 0.01f) size.Z = 0.01f;
|
if (size.Z < 0.01f) size.Z = 0.01f;
|
||||||
|
|
||||||
// try to find a identical mesh on meshs in use
|
// try to find a identical mesh on meshs in use
|
||||||
// key = primShape.GetMeshKey(size, lod, convex);
|
|
||||||
AMeshKey key = GetMeshUniqueKey(primShape,size,(byte)lod, convex);
|
AMeshKey key = GetMeshUniqueKey(primShape,size,(byte)lod, convex);
|
||||||
|
|
||||||
lock (m_uniqueMeshes)
|
lock (m_uniqueMeshes)
|
||||||
|
@ -1098,34 +1118,77 @@ namespace OpenSim.Region.Physics.Meshing
|
||||||
{
|
{
|
||||||
m_uniqueReleasedMeshes.Remove(key);
|
m_uniqueReleasedMeshes.Remove(key);
|
||||||
lock (m_uniqueMeshes)
|
lock (m_uniqueMeshes)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
m_uniqueMeshes.Add(key, mesh);
|
m_uniqueMeshes.Add(key, mesh);
|
||||||
|
}
|
||||||
|
catch { }
|
||||||
|
}
|
||||||
mesh.RefCount = 1;
|
mesh.RefCount = 1;
|
||||||
return mesh;
|
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
|
UnitMesh.RefCount = 1;
|
||||||
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");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// trim the vertex and triangle lists to free up memory
|
if (UnitMesh == null && primShape.SculptEntry && doMeshFileCache)
|
||||||
mesh.TrimExcess();
|
UnitMesh = GetFromFileCache(unitKey);
|
||||||
|
|
||||||
|
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.Key = key;
|
||||||
mesh.RefCount = 1;
|
mesh.RefCount = 1;
|
||||||
|
|
||||||
lock (m_uniqueMeshes)
|
lock (m_uniqueMeshes)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
m_uniqueMeshes.Add(key, mesh);
|
m_uniqueMeshes.Add(key, mesh);
|
||||||
}
|
}
|
||||||
|
catch { }
|
||||||
|
}
|
||||||
|
|
||||||
return mesh;
|
return mesh;
|
||||||
}
|
}
|
||||||
|
@ -1137,6 +1200,8 @@ namespace OpenSim.Region.Physics.Meshing
|
||||||
|
|
||||||
Mesh mesh = (Mesh)imesh;
|
Mesh mesh = (Mesh)imesh;
|
||||||
|
|
||||||
|
lock (m_uniqueMeshes)
|
||||||
|
{
|
||||||
int curRefCount = mesh.RefCount;
|
int curRefCount = mesh.RefCount;
|
||||||
curRefCount--;
|
curRefCount--;
|
||||||
|
|
||||||
|
@ -1146,13 +1211,17 @@ namespace OpenSim.Region.Physics.Meshing
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
lock (m_uniqueMeshes)
|
|
||||||
{
|
|
||||||
mesh.RefCount = 0;
|
mesh.RefCount = 0;
|
||||||
m_uniqueMeshes.Remove(mesh.Key);
|
m_uniqueMeshes.Remove(mesh.Key);
|
||||||
lock (m_uniqueReleasedMeshes)
|
lock (m_uniqueReleasedMeshes)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
m_uniqueReleasedMeshes.Add(mesh.Key, mesh);
|
m_uniqueReleasedMeshes.Add(mesh.Key, mesh);
|
||||||
}
|
}
|
||||||
|
catch { }
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ExpireReleaseMeshs()
|
public void ExpireReleaseMeshs()
|
||||||
|
@ -1178,10 +1247,170 @@ namespace OpenSim.Region.Physics.Meshing
|
||||||
foreach (Mesh m in meshstodelete)
|
foreach (Mesh m in meshstodelete)
|
||||||
{
|
{
|
||||||
m_uniqueReleasedMeshes.Remove(m.Key);
|
m_uniqueReleasedMeshes.Remove(m.Key);
|
||||||
m.releaseSourceMeshData();
|
m.releaseBuildingMeshData();
|
||||||
m.releasePinned();
|
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
|
// force lower density for testing
|
||||||
m_density = 3.0f;
|
m_density = 3.0f;
|
||||||
|
|
||||||
|
|
||||||
mu = parent_scene.AvatarFriction;
|
mu = parent_scene.AvatarFriction;
|
||||||
|
|
||||||
walkDivisor = walk_divisor;
|
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.length = length;
|
||||||
req.Normal = direction;
|
req.Normal = direction;
|
||||||
req.Origin = position;
|
req.Origin = position;
|
||||||
req.filter = RayFilterFlags.AllPrims;
|
req.filter = RayFilterFlags.AllPrims | RayFilterFlags.land;
|
||||||
|
|
||||||
m_PendingRequests.Enqueue(req);
|
m_PendingRequests.Enqueue(req);
|
||||||
}
|
}
|
||||||
|
@ -288,8 +288,11 @@ namespace OpenSim.Region.Physics.OdePlugin
|
||||||
catflags |= CollisionCategories.Water;
|
catflags |= CollisionCategories.Water;
|
||||||
|
|
||||||
if (catflags != 0)
|
if (catflags != 0)
|
||||||
|
{
|
||||||
|
d.GeomSetCollideBits(ray, (uint)catflags);
|
||||||
doSpaceRay(req);
|
doSpaceRay(req);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// if we select a geom don't use filters
|
// if we select a geom don't use filters
|
||||||
|
@ -314,7 +317,8 @@ namespace OpenSim.Region.Physics.OdePlugin
|
||||||
///
|
///
|
||||||
|
|
||||||
private const RayFilterFlags FilterActiveSpace = RayFilterFlags.agent | RayFilterFlags.physical | RayFilterFlags.LSLPhanton;
|
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)
|
private void doSpaceRay(ODERayRequest req)
|
||||||
{
|
{
|
||||||
|
@ -323,6 +327,16 @@ namespace OpenSim.Region.Physics.OdePlugin
|
||||||
d.SpaceCollide2(ray, m_scene.ActiveSpace, IntPtr.Zero, nearCallback);
|
d.SpaceCollide2(ray, m_scene.ActiveSpace, IntPtr.Zero, nearCallback);
|
||||||
if ((CurrentRayFilter & FilterStaticSpace) != 0 && (m_contactResults.Count < CurrentMaxCount))
|
if ((CurrentRayFilter & FilterStaticSpace) != 0 && (m_contactResults.Count < CurrentMaxCount))
|
||||||
d.SpaceCollide2(ray, m_scene.StaticSpace, IntPtr.Zero, nearCallback);
|
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)
|
if (req.callbackMethod is RaycastCallback)
|
||||||
{
|
{
|
||||||
|
|
|
@ -60,6 +60,7 @@ namespace OpenSim.Region.Physics.OdePlugin
|
||||||
public int lastframe;
|
public int lastframe;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// colision flags of things others can colide with
|
// colision flags of things others can colide with
|
||||||
// rays, sensors, probes removed since can't be colided with
|
// rays, sensors, probes removed since can't be colided with
|
||||||
// The top space where things are placed provided further selection
|
// The top space where things are placed provided further selection
|
||||||
|
@ -147,6 +148,8 @@ namespace OpenSim.Region.Physics.OdePlugin
|
||||||
|
|
||||||
Size,
|
Size,
|
||||||
Shape,
|
Shape,
|
||||||
|
PhysRepData,
|
||||||
|
AddPhysRep,
|
||||||
|
|
||||||
CollidesWater,
|
CollidesWater,
|
||||||
VolumeDtc,
|
VolumeDtc,
|
||||||
|
@ -230,11 +233,6 @@ namespace OpenSim.Region.Physics.OdePlugin
|
||||||
private float minimumGroundFlightOffset = 3f;
|
private float minimumGroundFlightOffset = 3f;
|
||||||
public float maximumMassObject = 10000.01f;
|
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;
|
public float geomDefaultDensity = 10.000006836f;
|
||||||
|
|
||||||
|
@ -302,6 +300,7 @@ namespace OpenSim.Region.Physics.OdePlugin
|
||||||
public IntPtr TopSpace; // the global space
|
public IntPtr TopSpace; // the global space
|
||||||
public IntPtr ActiveSpace; // space for active prims
|
public IntPtr ActiveSpace; // space for active prims
|
||||||
public IntPtr StaticSpace; // space for the static things around
|
public IntPtr StaticSpace; // space for the static things around
|
||||||
|
public IntPtr GroundSpace; // space for ground
|
||||||
|
|
||||||
// some speedup variables
|
// some speedup variables
|
||||||
private int spaceGridMaxX;
|
private int spaceGridMaxX;
|
||||||
|
@ -313,7 +312,7 @@ namespace OpenSim.Region.Physics.OdePlugin
|
||||||
private IntPtr[] staticPrimspaceOffRegion;
|
private IntPtr[] staticPrimspaceOffRegion;
|
||||||
|
|
||||||
public Object OdeLock;
|
public Object OdeLock;
|
||||||
private static Object SimulationLock;
|
public static Object SimulationLock;
|
||||||
|
|
||||||
public IMesher mesher;
|
public IMesher mesher;
|
||||||
|
|
||||||
|
@ -328,7 +327,7 @@ namespace OpenSim.Region.Physics.OdePlugin
|
||||||
private PhysicsScene m_parentScene = null;
|
private PhysicsScene m_parentScene = null;
|
||||||
|
|
||||||
private ODERayCastRequestManager m_rayCastManager;
|
private ODERayCastRequestManager m_rayCastManager;
|
||||||
|
public ODEMeshWorker m_meshWorker;
|
||||||
|
|
||||||
/* maybe needed if ode uses tls
|
/* maybe needed if ode uses tls
|
||||||
private void checkThread()
|
private void checkThread()
|
||||||
|
@ -361,6 +360,8 @@ namespace OpenSim.Region.Physics.OdePlugin
|
||||||
nearCallback = near;
|
nearCallback = near;
|
||||||
|
|
||||||
m_rayCastManager = new ODERayCastRequestManager(this);
|
m_rayCastManager = new ODERayCastRequestManager(this);
|
||||||
|
|
||||||
|
|
||||||
lock (OdeLock)
|
lock (OdeLock)
|
||||||
{
|
{
|
||||||
// Create the world and the first space
|
// Create the world and the first space
|
||||||
|
@ -372,6 +373,7 @@ namespace OpenSim.Region.Physics.OdePlugin
|
||||||
// now the major subspaces
|
// now the major subspaces
|
||||||
ActiveSpace = d.HashSpaceCreate(TopSpace);
|
ActiveSpace = d.HashSpaceCreate(TopSpace);
|
||||||
StaticSpace = d.HashSpaceCreate(TopSpace);
|
StaticSpace = d.HashSpaceCreate(TopSpace);
|
||||||
|
GroundSpace = d.HashSpaceCreate(TopSpace);
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
|
@ -381,10 +383,12 @@ namespace OpenSim.Region.Physics.OdePlugin
|
||||||
d.HashSpaceSetLevels(TopSpace, -2, 8);
|
d.HashSpaceSetLevels(TopSpace, -2, 8);
|
||||||
d.HashSpaceSetLevels(ActiveSpace, -2, 8);
|
d.HashSpaceSetLevels(ActiveSpace, -2, 8);
|
||||||
d.HashSpaceSetLevels(StaticSpace, -2, 8);
|
d.HashSpaceSetLevels(StaticSpace, -2, 8);
|
||||||
|
d.HashSpaceSetLevels(GroundSpace, 0, 8);
|
||||||
|
|
||||||
// demote to second level
|
// demote to second level
|
||||||
d.SpaceSetSublevel(ActiveSpace, 1);
|
d.SpaceSetSublevel(ActiveSpace, 1);
|
||||||
d.SpaceSetSublevel(StaticSpace, 1);
|
d.SpaceSetSublevel(StaticSpace, 1);
|
||||||
|
d.SpaceSetSublevel(GroundSpace, 1);
|
||||||
|
|
||||||
d.GeomSetCategoryBits(ActiveSpace, (uint)(CollisionCategories.Space |
|
d.GeomSetCategoryBits(ActiveSpace, (uint)(CollisionCategories.Space |
|
||||||
CollisionCategories.Geom |
|
CollisionCategories.Geom |
|
||||||
|
@ -402,6 +406,9 @@ namespace OpenSim.Region.Physics.OdePlugin
|
||||||
));
|
));
|
||||||
d.GeomSetCollideBits(StaticSpace, 0);
|
d.GeomSetCollideBits(StaticSpace, 0);
|
||||||
|
|
||||||
|
d.GeomSetCategoryBits(GroundSpace, (uint)(CollisionCategories.Land));
|
||||||
|
d.GeomSetCollideBits(GroundSpace, 0);
|
||||||
|
|
||||||
contactgroup = d.JointGroupCreate(0);
|
contactgroup = d.JointGroupCreate(0);
|
||||||
//contactgroup
|
//contactgroup
|
||||||
|
|
||||||
|
@ -440,9 +447,11 @@ namespace OpenSim.Region.Physics.OdePlugin
|
||||||
|
|
||||||
int contactsPerCollision = 80;
|
int contactsPerCollision = 80;
|
||||||
|
|
||||||
|
IConfig physicsconfig = null;
|
||||||
|
|
||||||
if (m_config != null)
|
if (m_config != null)
|
||||||
{
|
{
|
||||||
IConfig physicsconfig = m_config.Configs["ODEPhysicsSettings"];
|
physicsconfig = m_config.Configs["ODEPhysicsSettings"];
|
||||||
if (physicsconfig != null)
|
if (physicsconfig != null)
|
||||||
{
|
{
|
||||||
gravityx = physicsconfig.GetFloat("world_gravityx", gravityx);
|
gravityx = physicsconfig.GetFloat("world_gravityx", gravityx);
|
||||||
|
@ -469,27 +478,7 @@ namespace OpenSim.Region.Physics.OdePlugin
|
||||||
|
|
||||||
geomDefaultDensity = physicsconfig.GetFloat("geometry_default_density", geomDefaultDensity);
|
geomDefaultDensity = physicsconfig.GetFloat("geometry_default_density", geomDefaultDensity);
|
||||||
bodyFramesAutoDisable = physicsconfig.GetInt("body_frames_auto_disable", bodyFramesAutoDisable);
|
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 = physicsconfig.GetBoolean("physics_logging", false);
|
||||||
physics_logging_interval = physicsconfig.GetInt("physics_logging_interval", 0);
|
physics_logging_interval = physicsconfig.GetInt("physics_logging_interval", 0);
|
||||||
physics_logging_append_existing_logfile = physicsconfig.GetBoolean("physics_logging_append_existing_logfile", false);
|
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;
|
HalfOdeStep = ODE_STEPSIZE * 0.5f;
|
||||||
odetimestepMS = (int)(1000.0f * 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))
|
if (b1 != IntPtr.Zero && b2 != IntPtr.Zero && d.AreConnectedExcluding(b1, b2, d.JointType.Contact))
|
||||||
return;
|
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 ||
|
if(d.GeomGetCategoryBits(g1) == (uint)CollisionCategories.VolumeDtc ||
|
||||||
d.GeomGetCategoryBits(g1) == (uint)CollisionCategories.VolumeDtc)
|
d.GeomGetCategoryBits(g1) == (uint)CollisionCategories.VolumeDtc)
|
||||||
|
@ -1225,6 +1242,7 @@ namespace OpenSim.Region.Physics.OdePlugin
|
||||||
chr.CollidingObj = false;
|
chr.CollidingObj = false;
|
||||||
// do colisions with static space
|
// do colisions with static space
|
||||||
d.SpaceCollide2(StaticSpace, chr.Shell, IntPtr.Zero, nearCallback);
|
d.SpaceCollide2(StaticSpace, chr.Shell, IntPtr.Zero, nearCallback);
|
||||||
|
// no coll with gnd
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (AccessViolationException)
|
catch (AccessViolationException)
|
||||||
|
@ -1253,7 +1271,10 @@ namespace OpenSim.Region.Physics.OdePlugin
|
||||||
if (!prm.m_outbounds)
|
if (!prm.m_outbounds)
|
||||||
{
|
{
|
||||||
if (d.BodyIsEnabled(prm.Body))
|
if (d.BodyIsEnabled(prm.Body))
|
||||||
|
{
|
||||||
d.SpaceCollide2(StaticSpace, prm.collide_geom, IntPtr.Zero, nearCallback);
|
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);
|
_collisionEventPrimRemove.Add(obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override float TimeDilation
|
||||||
|
{
|
||||||
|
get { return m_timeDilation; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool SupportsNINJAJoints
|
||||||
|
{
|
||||||
|
get { return false; }
|
||||||
|
}
|
||||||
|
|
||||||
#region Add/Remove Entities
|
#region Add/Remove Entities
|
||||||
|
|
||||||
|
@ -1350,59 +1380,6 @@ namespace OpenSim.Region.Physics.OdePlugin
|
||||||
((OdeCharacter) actor).Destroy();
|
((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)
|
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,
|
public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, Vector3 position,
|
||||||
Vector3 size, Quaternion rotation, bool isPhysical, bool isPhantom, uint localid)
|
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,
|
public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, Vector3 position,
|
||||||
Vector3 size, Quaternion rotation, bool isPhysical, uint localid)
|
Vector3 size, Quaternion rotation, bool isPhysical, uint localid)
|
||||||
{
|
{
|
||||||
#if SPAM
|
return AddPrim(primName, position, size, rotation, pbs, isPhysical,false, 0, localid);
|
||||||
m_log.DebugFormat("[PHYSICS]: Adding physics actor to {0}", primName);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return AddPrim(primName, position, size, rotation, pbs, isPhysical, localid);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, Vector3 position,
|
public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, Vector3 position,
|
||||||
Vector3 size, Quaternion rotation, bool isPhysical, bool isPhantom, byte shapeType, uint localid)
|
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);
|
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)
|
public void remActivePrim(OdePrim deactivatePrim)
|
||||||
{
|
{
|
||||||
lock (_activeprims)
|
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
|
#endregion
|
||||||
|
|
||||||
#region Space Separation Calculation
|
#region Space Separation Calculation
|
||||||
|
@ -1615,135 +1609,6 @@ namespace OpenSim.Region.Physics.OdePlugin
|
||||||
|
|
||||||
#endregion
|
#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>
|
/// <summary>
|
||||||
/// Called to queue a change to a actor
|
/// Called to queue a change to a actor
|
||||||
|
@ -1769,6 +1634,50 @@ namespace OpenSim.Region.Physics.OdePlugin
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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>
|
/// <summary>
|
||||||
/// This is our main simulate loop
|
/// This is our main simulate loop
|
||||||
/// It's thread locked by a Mutex in the scene.
|
/// It's thread locked by a Mutex in the scene.
|
||||||
|
@ -1813,21 +1722,17 @@ namespace OpenSim.Region.Physics.OdePlugin
|
||||||
lock(OdeLock)
|
lock(OdeLock)
|
||||||
{
|
{
|
||||||
if (world == IntPtr.Zero)
|
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.");
|
ChangesQueue.Clear();
|
||||||
// ode.drelease(world);
|
return 0;
|
||||||
base.TriggerPhysicsBasedRestart();
|
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
ODEchangeitem item;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
d.WorldSetQuickStepNumIterations(world, curphysiteractions);
|
||||||
|
|
||||||
while (step_time > HalfOdeStep && nodeframes < 10) //limit number of steps so we don't say here for ever
|
while (step_time > HalfOdeStep && nodeframes < 10) //limit number of steps so we don't say here for ever
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
@ -1835,8 +1740,6 @@ namespace OpenSim.Region.Physics.OdePlugin
|
||||||
// clear pointer/counter to contacts to pass into joints
|
// clear pointer/counter to contacts to pass into joints
|
||||||
m_global_contactcount = 0;
|
m_global_contactcount = 0;
|
||||||
|
|
||||||
ODEchangeitem item;
|
|
||||||
|
|
||||||
if (ChangesQueue.Count > 0)
|
if (ChangesQueue.Count > 0)
|
||||||
{
|
{
|
||||||
int ttmpstart = Util.EnvironmentTickCount();
|
int ttmpstart = Util.EnvironmentTickCount();
|
||||||
|
@ -1855,8 +1758,9 @@ namespace OpenSim.Region.Physics.OdePlugin
|
||||||
}
|
}
|
||||||
catch
|
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);
|
ttmp = Util.EnvironmentTickCountSubtract(ttmpstart);
|
||||||
if (ttmp > 20)
|
if (ttmp > 20)
|
||||||
|
@ -1994,10 +1898,47 @@ namespace OpenSim.Region.Physics.OdePlugin
|
||||||
mesher.ExpireReleaseMeshs();
|
mesher.ExpireReleaseMeshs();
|
||||||
m_lastMeshExpire = now;
|
m_lastMeshExpire = now;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// information block running in debug only
|
||||||
/*
|
/*
|
||||||
int nactivegeoms = d.SpaceGetNumGeoms(ActiveSpace);
|
int ntopactivegeoms = d.SpaceGetNumGeoms(ActiveSpace);
|
||||||
int nstaticgeoms = d.SpaceGetNumGeoms(StaticSpace);
|
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 ntopgeoms = d.SpaceGetNumGeoms(TopSpace);
|
||||||
|
|
||||||
|
int totgeoms = nstaticgeoms + nactivegeoms + ngroundgeoms + 1; // one ray
|
||||||
int nbodies = d.NTotalBodies;
|
int nbodies = d.NTotalBodies;
|
||||||
int ngeoms = d.NTotalGeoms;
|
int ngeoms = d.NTotalGeoms;
|
||||||
*/
|
*/
|
||||||
|
@ -2294,7 +2235,9 @@ namespace OpenSim.Region.Physics.OdePlugin
|
||||||
offset, thickness, wrap);
|
offset, thickness, wrap);
|
||||||
|
|
||||||
d.GeomHeightfieldDataSetBounds(HeightmapData, hfmin - 1, hfmax + 1);
|
d.GeomHeightfieldDataSetBounds(HeightmapData, hfmin - 1, hfmax + 1);
|
||||||
GroundGeom = d.CreateHeightfield(StaticSpace, HeightmapData, 1);
|
|
||||||
|
GroundGeom = d.CreateHeightfield(GroundSpace, HeightmapData, 1);
|
||||||
|
|
||||||
if (GroundGeom != IntPtr.Zero)
|
if (GroundGeom != IntPtr.Zero)
|
||||||
{
|
{
|
||||||
d.GeomSetCategoryBits(GroundGeom, (uint)(CollisionCategories.Land));
|
d.GeomSetCategoryBits(GroundGeom, (uint)(CollisionCategories.Land));
|
||||||
|
@ -2415,12 +2358,13 @@ namespace OpenSim.Region.Physics.OdePlugin
|
||||||
thickness, wrap);
|
thickness, wrap);
|
||||||
|
|
||||||
// d.GeomUbitTerrainDataSetBounds(HeightmapData, hfmin - 1, hfmax + 1);
|
// d.GeomUbitTerrainDataSetBounds(HeightmapData, hfmin - 1, hfmax + 1);
|
||||||
GroundGeom = d.CreateUbitTerrain(StaticSpace, HeightmapData, 1);
|
GroundGeom = d.CreateUbitTerrain(GroundSpace, HeightmapData, 1);
|
||||||
if (GroundGeom != IntPtr.Zero)
|
if (GroundGeom != IntPtr.Zero)
|
||||||
{
|
{
|
||||||
d.GeomSetCategoryBits(GroundGeom, (uint)(CollisionCategories.Land));
|
d.GeomSetCategoryBits(GroundGeom, (uint)(CollisionCategories.Land));
|
||||||
d.GeomSetCollideBits(GroundGeom, 0);
|
d.GeomSetCollideBits(GroundGeom, 0);
|
||||||
|
|
||||||
|
|
||||||
PhysicsActor pa = new NullPhysicsActor();
|
PhysicsActor pa = new NullPhysicsActor();
|
||||||
pa.Name = "Terrain";
|
pa.Name = "Terrain";
|
||||||
pa.PhysicsActorType = (int)ActorTypes.Ground;
|
pa.PhysicsActorType = (int)ActorTypes.Ground;
|
||||||
|
@ -2599,6 +2543,9 @@ namespace OpenSim.Region.Physics.OdePlugin
|
||||||
*/
|
*/
|
||||||
public override void Dispose()
|
public override void Dispose()
|
||||||
{
|
{
|
||||||
|
if (m_meshWorker != null)
|
||||||
|
m_meshWorker.Stop();
|
||||||
|
|
||||||
lock (OdeLock)
|
lock (OdeLock)
|
||||||
{
|
{
|
||||||
m_rayCastManager.Dispose();
|
m_rayCastManager.Dispose();
|
||||||
|
@ -2633,6 +2580,7 @@ namespace OpenSim.Region.Physics.OdePlugin
|
||||||
d.GeomDestroy(GroundGeom);
|
d.GeomDestroy(GroundGeom);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
RegionTerrain.Clear();
|
RegionTerrain.Clear();
|
||||||
|
|
||||||
if (TerrainHeightFieldHeightsHandlers.Count > 0)
|
if (TerrainHeightFieldHeightsHandlers.Count > 0)
|
||||||
|
|
Loading…
Reference in New Issue