[DANGER UNTESTED] ODE mesh assets. Other plugins will not do meshs/sculpts

now
avinationmerge
UbitUmarov 2012-10-07 01:20:52 +01:00
parent 5254c0de8f
commit 78ce7a0a04
7 changed files with 650 additions and 1070 deletions

View File

@ -4299,8 +4299,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>

View File

@ -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);
} }
} }
@ -1654,8 +1654,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 +2115,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 +2143,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 +2153,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 +2343,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);
} }
} }
@ -3125,6 +3127,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)
@ -3152,7 +3155,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>
@ -4377,7 +4380,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)
@ -4385,7 +4388,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;
@ -4793,9 +4796,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)
@ -4898,6 +4901,7 @@ 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);
@ -4925,7 +4929,7 @@ namespace OpenSim.Region.Framework.Scenes
} }
} }
} }
*/
/// <summary> /// <summary>
/// Update the texture entry for this part. /// Update the texture entry for this part.
/// </summary> /// </summary>

View File

@ -74,10 +74,6 @@ namespace OpenSim.Region.Physics.Meshing
private const string baseDir = null; //"rawFiles"; private const string baseDir = null; //"rawFiles";
#endif #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
@ -92,29 +88,9 @@ 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);
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);
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>
@ -444,7 +420,7 @@ namespace OpenSim.Region.Physics.Meshing
// physics_shape is an array of OSDMaps, one for each submesh // physics_shape is an array of OSDMaps, one for each submesh
if (decodedMeshOsd is OSDArray) if (decodedMeshOsd is OSDArray)
{ {
// Console.WriteLine("decodedMeshOsd for {0} - {1}", primName, Util.GetFormattedXml(decodedMeshOsd)); // Console.WriteLine("decodedMeshOsd for {0} - {1}", primName, Util.GetFormattedXml(decodedMeshOsd));
decodedMeshOsdArray = (OSDArray)decodedMeshOsd; decodedMeshOsdArray = (OSDArray)decodedMeshOsd;
foreach (OSD subMeshOsd in decodedMeshOsdArray) foreach (OSD subMeshOsd in decodedMeshOsdArray)
@ -717,29 +693,7 @@ namespace OpenSim.Region.Physics.Meshing
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 +702,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 +727,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
@ -1048,7 +991,6 @@ 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);

View File

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

View File

@ -18,26 +18,63 @@ using OpenMetaverse;
namespace OpenSim.Region.Physics.OdePlugin namespace OpenSim.Region.Physics.OdePlugin
{ {
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 float physCost;
public float streamCost;
public byte shapetype;
public bool hasOBB;
public bool hasMeshVolume;
public AssetState assetState;
public UUID? assetID;
public meshWorkerCmnds comand;
}
public class ODEMeshWorker public class ODEMeshWorker
{ {
private ILog m_log; private ILog m_log;
private OdeScene m_scene; private OdeScene m_scene;
private IMesher m_mesher; private IMesher m_mesher;
public bool meshSculptedPrim = true; public bool meshSculptedPrim = true;
public bool forceSimplePrimMeshing = false; public bool forceSimplePrimMeshing = false;
public float meshSculptLOD = 32; public float meshSculptLOD = 32;
public float MeshSculptphysicalLOD = 32; public float MeshSculptphysicalLOD = 32;
private IntPtr m_workODEspace = IntPtr.Zero;
public ODEMeshWorker(OdeScene pScene, ILog pLog, IMesher pMesher, IntPtr pWorkSpace, IConfig pConfig) 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_scene = pScene;
m_log = pLog; m_log = pLog;
m_mesher = pMesher; m_mesher = pMesher;
m_workODEspace = pWorkSpace;
if (pConfig != null) if (pConfig != null)
{ {
@ -46,8 +83,177 @@ namespace OpenSim.Region.Physics.OdePlugin
meshSculptLOD = pConfig.GetFloat("mesh_lod", meshSculptLOD); meshSculptLOD = pConfig.GetFloat("mesh_lod", meshSculptLOD);
MeshSculptphysicalLOD = pConfig.GetFloat("mesh_physical_lod", MeshSculptphysicalLOD); MeshSculptphysicalLOD = pConfig.GetFloat("mesh_physical_lod", MeshSculptphysicalLOD);
} }
m_running = true;
m_thread = new Thread(DoWork);
m_thread.Start();
} }
private void DoWork()
{
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:
if (CreateActorPhysRep(nextRep) && m_scene.haveActor(nextRep.actor))
m_scene.AddChange(nextRep.actor, changes.PhysRepData, nextRep);
break;
case meshWorkerCmnds.addnew:
if (CreateActorPhysRep(nextRep))
m_scene.AddChange(nextRep.actor, changes.AddPhysRep, nextRep);
break;
case meshWorkerCmnds.getmesh:
DoRepDataGetMesh(nextRep);
break;
}
}
}
}
public void Stop()
{
m_running = false;
m_thread.Abort();
}
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;
// if (CheckMeshDone(repData))
{
CheckMeshDone(repData);
CalcVolumeData(repData);
m_scene.AddChange(actor, changes.PhysRepData, repData);
return;
}
// repData.comand = meshWorkerCmnds.changefull;
// createqueue.Enqueue(repData);
}
public void 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;
// bool done = CheckMeshDone(repData);
CheckMeshDone(repData);
CalcVolumeData(repData);
m_scene.AddChange(actor, changes.AddPhysRep, repData);
// if (done)
return;
// repData.comand = meshWorkerCmnds.addnew;
// createqueue.Enqueue(repData);
}
public void RequestMeshAsset(ODEPhysRepData repData)
{
if (repData.assetState != AssetState.needAsset)
return;
if (repData.assetID == null || repData.assetID == UUID.Zero)
return;
repData.mesh = null;
repData.assetState = AssetState.loadingAsset;
repData.comand = meshWorkerCmnds.getmesh;
createqueue.Enqueue(repData);
}
public bool CreateActorPhysRep(ODEPhysRepData repData)
{
getMesh(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.assetState = AssetState.AssetFailed;
repData.hasOBB = false;
repData.mesh = null;
m_scene.mesher.ReleaseMesh(mesh);
}
else
{
repData.OBBOffset = mesh.GetCentroid();
repData.OBB = mesh.GetOBB();
repData.hasOBB = true;
repData.physCost = 0.0013f * (float)indexCount;
// todo
repData.streamCost = 1.0f;
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);
}
}
}
public void DoRepDataGetMesh(ODEPhysRepData repData)
{
if (!repData.pbs.SculptEntry)
return;
if (repData.assetState != AssetState.loadingAsset)
return;
if (repData.assetID == null || repData.assetID == UUID.Zero)
return;
if (repData.assetID != repData.pbs.SculptTexture)
return;
RequestAssetDelegate assetProvider = m_scene.RequestAssetMethod;
if (assetProvider == null)
return;
ODEAssetRequest asr = new ODEAssetRequest(this, assetProvider, repData, m_log);
}
/// <summary> /// <summary>
/// Routine to figure out if we need to mesh this prim with our mesher /// Routine to figure out if we need to mesh this prim with our mesher
/// </summary> /// </summary>
@ -169,194 +375,151 @@ namespace OpenSim.Region.Physics.OdePlugin
return true; return true;
} }
public IMesh getMesh(PhysicsActor actor, PrimitiveBaseShape ppbs, Vector3 psize, byte pshapetype) public bool CheckMeshDone(ODEPhysRepData repData)
{ {
if (!(actor is OdePrim)) PhysicsActor actor = repData.actor;
return null; PrimitiveBaseShape pbs = repData.pbs;
repData.mesh = null;
repData.hasOBB = false;
if (!needsMeshing(pbs))
{
repData.assetState = AssetState.noNeedAsset;
return true;
}
if (pbs.SculptEntry)
{
if (repData.assetState == AssetState.AssetFailed)
{
if (pbs.SculptTexture == repData.assetID)
return true;
}
}
else
{
repData.assetState = AssetState.noNeedAsset;
repData.assetID = null;
}
IMesh mesh = null; IMesh mesh = null;
PrimitiveBaseShape pbs = ppbs;
Vector3 size = psize;
byte shapetype = pshapetype;
if (needsMeshing(pbs)) Vector3 size = repData.size;
byte shapetype = repData.shapetype;
bool convex;
int clod = (int)LevelOfDetail.High;
if (shapetype == 0)
convex = false;
else
{ {
bool convex; convex = true;
int clod = (int)LevelOfDetail.High; if (pbs.SculptType != (byte)SculptType.Mesh)
if (shapetype == 0) clod = (int)LevelOfDetail.Low;
convex = false; }
else mesh = m_mesher.GetMesh(actor.Name, pbs, size, clod, true, convex);
if (mesh == null)
{
if (pbs.SculptEntry)
{ {
convex = true; if (pbs.SculptTexture != null && pbs.SculptTexture != UUID.Zero)
if (pbs.SculptType != (byte)SculptType.Mesh) {
clod = (int)LevelOfDetail.Low; repData.assetID = pbs.SculptTexture;
} repData.assetState = AssetState.needAsset;
mesh = m_mesher.GetMesh(actor.Name, pbs, size, clod, true, convex);
if (mesh == null)
{
if (!pbs.SculptEntry)
return m_mesher.CreateMesh(actor.Name, pbs, size, clod, true, convex);
if (pbs.SculptTexture == UUID.Zero)
return null;
if (pbs.SculptType != (byte)SculptType.Mesh)
{ // check for sculpt decoded image on cache)
if (File.Exists(System.IO.Path.Combine("j2kDecodeCache", "smap_" + pbs.SculptTexture.ToString())))
return m_mesher.CreateMesh(actor.Name, pbs, size, clod, true, convex);
} }
else
if (pbs.SculptData != null && pbs.SculptData.Length > 0) repData.assetState = AssetState.AssetFailed;
return m_mesher.CreateMesh(actor.Name, pbs, size, clod, true, convex);
ODEAssetRequest asr;
RequestAssetDelegate assetProvider = m_scene.RequestAssetMethod;
if (assetProvider != null)
asr = new ODEAssetRequest(this, assetProvider, actor, pbs, m_log);
return null;
} }
}
return mesh;
}
private bool GetTriMeshGeo(ODEPhysRepData repData)
{
IntPtr vertices, indices;
IntPtr triMeshData = IntPtr.Zero;
IntPtr geo = IntPtr.Zero;
int vertexCount, indexCount;
int vertexStride, triStride;
PhysicsActor actor = repData.actor;
IMesh mesh = repData.mesh;
if (mesh == null)
{
mesh = getMesh(repData.actor, repData.pbs, repData.size, repData.shapetype);
}
if (mesh == null)
return false;
mesh.getVertexListAsPtrToFloatArray(out vertices, out vertexStride, out vertexCount); // Note, that vertices are fixed in unmanaged heap
mesh.getIndexListAsPtrToIntArray(out indices, out triStride, out indexCount); // Also fixed, needs release after usage
if (vertexCount == 0 || indexCount == 0)
{
m_log.WarnFormat("[PHYSICS]: Invalid mesh data on prim {0} mesh UUID {1}",
actor.Name, repData.pbs.SculptTexture.ToString());
mesh.releaseSourceMeshData();
return false; return false;
} }
repData.OBBOffset = mesh.GetCentroid(); repData.mesh = mesh;
repData.OBB = mesh.GetOBB(); if (pbs.SculptEntry)
repData.hasOBB = true;
repData.physCost = 0.0013f * (float)indexCount;
mesh.releaseSourceMeshData();
try
{ {
triMeshData = d.GeomTriMeshDataCreate(); repData.assetState = AssetState.AssetOK;
repData.assetID = pbs.SculptTexture;
d.GeomTriMeshDataBuildSimple(triMeshData, vertices, vertexStride, vertexCount, indices, indexCount, triStride); pbs.SculptData = Utils.EmptyBytes;
d.GeomTriMeshDataPreprocess(triMeshData);
m_scene.waitForSpaceUnlock(m_workODEspace);
geo = d.CreateTriMesh(m_workODEspace, triMeshData, null, null, null);
} }
catch (Exception e)
{
m_log.ErrorFormat("[PHYSICS]: SetGeom Mesh failed for {0} exception: {1}", actor.Name, e);
if (triMeshData != IntPtr.Zero)
{
d.GeomTriMeshDataDestroy(triMeshData);
repData.triMeshData = IntPtr.Zero;
}
repData.geo = IntPtr.Zero;
return false;
}
repData.geo = geo;
repData.triMeshData = triMeshData;
repData.curSpace = m_workODEspace;
return true; return true;
} }
public ODEPhysRepData CreateActorPhysRep(PhysicsActor actor, PrimitiveBaseShape pbs, IMesh pMesh, Vector3 size, byte shapetype)
public bool getMesh(ODEPhysRepData repData)
{ {
ODEPhysRepData repData = new ODEPhysRepData(); PhysicsActor actor = repData.actor;
repData.actor = actor; PrimitiveBaseShape pbs = repData.pbs;
repData.pbs = pbs;
repData.mesh = pMesh;
repData.size = size;
repData.shapetype = shapetype;
IntPtr geo = IntPtr.Zero; repData.mesh = null;
bool hasMesh = false; repData.hasOBB = false;
if (needsMeshing(pbs))
if (!needsMeshing(pbs))
return false;
if (pbs.SculptEntry)
{ {
if (GetTriMeshGeo(repData)) if (repData.assetState == AssetState.AssetFailed)
hasMesh = true; {
else if (pbs.SculptTexture == repData.assetID)
repData.NoColide = true; return true;
}
} }
if (!hasMesh) repData.assetState = AssetState.noNeedAsset;
IMesh mesh = null;
Vector3 size = repData.size;
byte shapetype = repData.shapetype;
bool convex;
int clod = (int)LevelOfDetail.High;
if (shapetype == 0)
convex = false;
else
{ {
if (pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1 convex = true;
&& size.X == size.Y && size.Y == size.Z) if (pbs.SculptType != (byte)SculptType.Mesh)
{ // it's a sphere clod = (int)LevelOfDetail.Low;
m_scene.waitForSpaceUnlock(m_workODEspace); }
try mesh = m_mesher.GetMesh(actor.Name, pbs, size, clod, true, convex);
if (mesh == null)
{
if (pbs.SculptEntry)
{
if (pbs.SculptTexture == UUID.Zero)
return false;
repData.assetID = pbs.SculptTexture;
repData.assetState = AssetState.AssetOK;
if (pbs.SculptData == null || pbs.SculptData.Length == 0)
{ {
geo = d.CreateSphere(m_workODEspace, size.X * 0.5f); repData.assetState = AssetState.needAsset;
} return false;
catch (Exception e)
{
m_log.WarnFormat("[PHYSICS]: Create sphere failed: {0}", e);
return null;
}
}
else
{// do it as a box
m_scene.waitForSpaceUnlock(m_workODEspace);
try
{
//Console.WriteLine(" CreateGeom 4");
geo = d.CreateBox(m_workODEspace, size.X, size.Y, size.Z);
}
catch (Exception e)
{
m_log.Warn("[PHYSICS]: Create box failed: {0}", e);
return null;
} }
} }
repData.physCost = 0.1f; mesh = m_mesher.CreateMesh(actor.Name, pbs, size, clod, true, convex);
repData.streamCost = 1.0f;
repData.geo = geo;
} }
repData.curSpace = m_workODEspace; repData.mesh = mesh;
repData.pbs.SculptData = Utils.EmptyBytes;
CalcVolumeData(repData); if (mesh == null)
{
if (pbs.SculptEntry)
repData.assetState = AssetState.AssetFailed;
return repData; return false;
} }
public void ChangeActorPhysRep(PhysicsActor actor, PrimitiveBaseShape pbs, if (pbs.SculptEntry)
Vector3 size, byte shapetype, MeshWorkerChange what) repData.assetState = AssetState.AssetOK;
{
ODEPhysRepData repData = CreateActorPhysRep(actor, pbs, null, size, shapetype); return true;
repData.changed |= what;
if (repData != null && actor != null)
((OdePrim)actor).AddChange(changes.PhysRepData, repData);
} }
private void CalculateBasicPrimVolume(ODEPhysRepData repData) private void CalculateBasicPrimVolume(ODEPhysRepData repData)
@ -662,46 +825,12 @@ namespace OpenSim.Region.Physics.OdePlugin
private void CalcVolumeData(ODEPhysRepData repData) private void CalcVolumeData(ODEPhysRepData repData)
{ {
float volume;
Vector3 OBB = repData.size;
Vector3 OBBoffset;
IntPtr geo = repData.geo;
if (geo == IntPtr.Zero || repData.triMeshData == IntPtr.Zero)
{
OBB.X *= 0.5f;
OBB.Y *= 0.5f;
OBB.Z *= 0.5f;
repData.OBB = OBB;
repData.OBBOffset = Vector3.Zero;
}
else if (!repData.hasOBB) // should this happen?
{
d.AABB AABB;
d.GeomGetAABB(geo, out AABB); // get the AABB from engine geom
OBB.X = (AABB.MaxX - AABB.MinX) * 0.5f;
OBB.Y = (AABB.MaxY - AABB.MinY) * 0.5f;
OBB.Z = (AABB.MaxZ - AABB.MinZ) * 0.5f;
repData.OBB = OBB;
OBBoffset.X = (AABB.MaxX + AABB.MinX) * 0.5f;
OBBoffset.Y = (AABB.MaxY + AABB.MinY) * 0.5f;
OBBoffset.Z = (AABB.MaxZ + AABB.MinZ) * 0.5f;
repData.OBBOffset = Vector3.Zero;
}
// also its own inertia and mass
// keep using basic shape mass for now
CalculateBasicPrimVolume(repData);
if (repData.hasOBB) if (repData.hasOBB)
{ {
OBB = repData.OBB; Vector3 OBB = repData.OBB;
float pc = repData.physCost; float pc = repData.physCost;
float psf = OBB.X * (OBB.Y + OBB.Z) + OBB.Y * OBB.Z; float psf = OBB.X * (OBB.Y + OBB.Z) + OBB.Y * OBB.Z;
psf *= 1.33f * .2f; psf *= 1.33f * .2f;
pc *= psf; pc *= psf;
if (pc < 0.1f) if (pc < 0.1f)
pc = 0.1f; pc = 0.1f;
@ -709,54 +838,79 @@ namespace OpenSim.Region.Physics.OdePlugin
repData.physCost = pc; repData.physCost = pc;
} }
else else
{
Vector3 OBB = repData.size;
OBB.X *= 0.5f;
OBB.Y *= 0.5f;
OBB.Z *= 0.5f;
repData.OBB = OBB;
repData.OBBOffset = Vector3.Zero;
repData.physCost = 0.1f; repData.physCost = 0.1f;
repData.streamCost = 1.0f;
}
CalculateBasicPrimVolume(repData);
} }
} }
public class ODEAssetRequest public class ODEAssetRequest
{ {
PhysicsActor m_actor;
ODEMeshWorker m_worker; ODEMeshWorker m_worker;
PrimitiveBaseShape m_pbs;
private ILog m_log; private ILog m_log;
ODEPhysRepData repData;
public ODEAssetRequest(ODEMeshWorker pWorker, RequestAssetDelegate provider, public ODEAssetRequest(ODEMeshWorker pWorker, RequestAssetDelegate provider,
PhysicsActor pActor, PrimitiveBaseShape ppbs, ILog plog) ODEPhysRepData pRepData, ILog plog)
{ {
m_actor = pActor;
m_worker = pWorker; m_worker = pWorker;
m_pbs = ppbs;
m_log = plog; m_log = plog;
repData = pRepData;
repData.assetState = AssetState.AssetFailed;
if (provider == null) if (provider == null)
return; return;
UUID assetID = m_pbs.SculptTexture; if (repData.assetID == null)
return;
UUID assetID = (UUID) repData.assetID;
if (assetID == UUID.Zero) if (assetID == UUID.Zero)
return; return;
repData.assetState = AssetState.loadingAsset;
provider(assetID, ODEassetReceived); provider(assetID, ODEassetReceived);
} }
void ODEassetReceived(AssetBase asset) void ODEassetReceived(AssetBase asset)
{ {
if (m_actor != null && m_pbs != null) repData.assetState = AssetState.AssetFailed;
if (asset != null)
{ {
if (asset != null) if (asset.Data != null && asset.Data.Length > 0)
{ {
if (asset.Data != null && asset.Data.Length > 0) if (!repData.pbs.SculptEntry)
{ return;
m_pbs.SculptData = asset.Data; if (repData.pbs.SculptTexture != repData.assetID)
m_actor.Shape = m_pbs; return;
}
else // asset get may return a pointer to the same asset data
m_log.WarnFormat("[PHYSICS]: asset provider returned invalid mesh data for prim {0} asset UUID {1}.", // for similar prims and we destroy with it
m_actor.Name, asset.ID.ToString()); // so waste a lot of time stressing gc and hoping it clears things
// TODO avoid this
repData.pbs.SculptData = new byte[asset.Data.Length];
asset.Data.CopyTo(repData.pbs.SculptData,0);
repData.assetState = AssetState.AssetOK;
m_worker.AssetLoaded(repData);
} }
else else
m_log.WarnFormat("[PHYSICS]: asset provider returned null asset fo mesh of prim {0}.", m_log.WarnFormat("[PHYSICS]: asset provider returned invalid mesh data for prim {0} asset UUID {1}.",
m_actor.Name); 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

View File

@ -60,29 +60,6 @@ namespace OpenSim.Region.Physics.OdePlugin
public int lastframe; public int lastframe;
} }
public class ODEPhysRepData
{
public PhysicsActor actor;
public IntPtr geo = IntPtr.Zero;
public IntPtr triMeshData = IntPtr.Zero;
public IMesh mesh;
public IntPtr curSpace = IntPtr.Zero;
public PrimitiveBaseShape pbs;
public Vector3 size = Vector3.Zero;
public Vector3 OBB = Vector3.Zero;
public Vector3 OBBOffset = Vector3.Zero;
public float volume;
public float physCost = 0.0f;
public float streamCost = 0;
public MeshWorkerChange changed;
public byte shapetype = 0;
public bool NoColide = false;
public bool hasOBB = false;
public bool hasMeshVolume = false;
}
// 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
@ -133,13 +110,16 @@ namespace OpenSim.Region.Physics.OdePlugin
light = 7 // compatibility with old viewers light = 7 // compatibility with old viewers
} }
[Flags]
public enum MeshWorkerChange : uint public enum AssetState : byte
{ {
none = 0, noNeedAsset = 0,
size = 1, needAsset = 1,
shape = 2, loadingAsset = 2,
shapetype = 3, procAsset = 3,
AssetOK = 4,
AssetFailed = 0xff
} }
public enum changes : int public enum changes : int
@ -180,6 +160,7 @@ namespace OpenSim.Region.Physics.OdePlugin
Size, Size,
Shape, Shape,
PhysRepData, PhysRepData,
AddPhysRep,
CollidesWater, CollidesWater,
VolumeDtc, VolumeDtc,
@ -330,7 +311,6 @@ 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 WorkSpace; // no collisions work space
// some speedup variables // some speedup variables
private int spaceGridMaxX; private int spaceGridMaxX;
@ -342,7 +322,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;
@ -403,7 +383,6 @@ 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);
WorkSpace = d.HashSpaceCreate(TopSpace);
} }
catch catch
{ {
@ -413,12 +392,10 @@ 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(WorkSpace, -2, 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(WorkSpace, 1);
d.GeomSetCategoryBits(ActiveSpace, (uint)(CollisionCategories.Space | d.GeomSetCategoryBits(ActiveSpace, (uint)(CollisionCategories.Space |
CollisionCategories.Geom | CollisionCategories.Geom |
@ -436,8 +413,6 @@ namespace OpenSim.Region.Physics.OdePlugin
)); ));
d.GeomSetCollideBits(StaticSpace, 0); d.GeomSetCollideBits(StaticSpace, 0);
d.GeomSetCategoryBits(WorkSpace, 0);
d.GeomSetCollideBits(WorkSpace, 0);
contactgroup = d.JointGroupCreate(0); contactgroup = d.JointGroupCreate(0);
//contactgroup //contactgroup
@ -518,7 +493,7 @@ namespace OpenSim.Region.Physics.OdePlugin
} }
} }
m_meshWorker = new ODEMeshWorker(this, m_log, meshmerizer, WorkSpace, physicsconfig); 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);
@ -1316,6 +1291,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
@ -1371,59 +1355,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)
{ {
@ -1444,44 +1375,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)
@ -1534,6 +1460,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
@ -1707,19 +1655,8 @@ namespace OpenSim.Region.Physics.OdePlugin
if (world == IntPtr.Zero) if (world == IntPtr.Zero)
return 0; return 0;
// adjust number of iterations per step d.WorldSetQuickStepNumIterations(world, curphysiteractions);
// try
// {
d.WorldSetQuickStepNumIterations(world, curphysiteractions);
/* }
catch (StackOverflowException)
{
m_log.Error("[PHYSICS]: The operating system wasn't able to allocate enough memory for the simulation. Restarting the sim.");
// ode.drelease(world);
base.TriggerPhysicsBasedRestart();
}
*/
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
@ -1747,8 +1684,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)
@ -2491,6 +2429,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();