initial support for meshies physics. Must set ini option UseMeshiesPhysicsMesh = true to enable. See file OpenSimDefaults.ini for example.

viewer-2-initial-appearance
dahlia 2010-10-18 04:17:36 -07:00
parent 6df4ca7de1
commit 7fa3335fd5
4 changed files with 97 additions and 40 deletions

View File

@ -40,6 +40,7 @@ using log4net;
using Nini.Config; using Nini.Config;
using System.Reflection; using System.Reflection;
using System.IO; using System.IO;
using ComponentAce.Compression.Libs.zlib;
namespace OpenSim.Region.Physics.Meshing namespace OpenSim.Region.Physics.Meshing
{ {
@ -74,6 +75,7 @@ namespace OpenSim.Region.Physics.Meshing
private bool cacheSculptMaps = true; private bool cacheSculptMaps = true;
private string decodedSculptMapPath = null; private string decodedSculptMapPath = null;
private bool useMeshiesPhysicsMesh = false;
private float minSizeForComplexMesh = 0.2f; // prims with all dimensions smaller than this will have a bounding box mesh private float minSizeForComplexMesh = 0.2f; // prims with all dimensions smaller than this will have a bounding box mesh
@ -85,6 +87,7 @@ namespace OpenSim.Region.Physics.Meshing
decodedSculptMapPath = start_config.GetString("DecodedSculptMapPath","j2kDecodeCache"); decodedSculptMapPath = start_config.GetString("DecodedSculptMapPath","j2kDecodeCache");
cacheSculptMaps = start_config.GetBoolean("CacheSculptMaps", cacheSculptMaps); cacheSculptMaps = start_config.GetBoolean("CacheSculptMaps", cacheSculptMaps);
useMeshiesPhysicsMesh = start_config.GetBoolean("UseMeshiesPhysicsMesh", useMeshiesPhysicsMesh);
try try
{ {
@ -268,73 +271,121 @@ namespace OpenSim.Region.Physics.Meshing
{ {
if (((OpenMetaverse.SculptType)primShape.SculptType) == SculptType.Mesh) if (((OpenMetaverse.SculptType)primShape.SculptType) == SculptType.Mesh)
{ {
// add code for mesh physics proxy generation here if (!useMeshiesPhysicsMesh)
m_log.Debug("[MESH]: mesh proxy generation not implemented yet "); return null;
m_log.Debug("[MESH]: experimental mesh proxy generation");
OSD meshOsd; OSD meshOsd;
if (primShape.SculptData.Length > 0) if (primShape.SculptData.Length <= 0)
{
m_log.Debug("[MESH]: asset data length: " + primShape.SculptData.Length.ToString());
byte[] header = Util.StringToBytes256("<? LLSD/Binary ?>");
////dump to debugging file
//string filename = System.IO.Path.Combine(decodedSculptMapPath, "mesh_" + primShape.SculptTexture.ToString());
//BinaryWriter writer = new BinaryWriter(File.Open(filename, FileMode.Create));
//writer.Write(primShape.SculptData);
//writer.Close();
}
else
{ {
m_log.Error("[MESH]: asset data is zero length"); m_log.Error("[MESH]: asset data is zero length");
return null; return null;
} }
try long start = 0;
using (MemoryStream data = new MemoryStream(primShape.SculptData))
{ {
meshOsd = OSDParser.DeserializeLLSDBinary(primShape.SculptData, true); meshOsd = (OSDMap)OSDParser.DeserializeLLSDBinary(data, true);
} start = data.Position;
catch (Exception e)
{
m_log.Error("[MESH]: exception decoding mesh asset: " + e.ToString());
return null;
} }
if (meshOsd is OSDMap) if (meshOsd is OSDMap)
{ {
OSDMap map = (OSDMap)meshOsd; OSDMap map = (OSDMap)meshOsd;
//foreach (string name in map.Keys)
// m_log.Debug("[MESH]: key:" + name + " value:" + map[name].AsString());
OSDMap physicsParms = (OSDMap)map["physics_shape"]; OSDMap physicsParms = (OSDMap)map["physics_shape"];
int physOffset = physicsParms["offset"].AsInteger(); int physOffset = physicsParms["offset"].AsInteger() + (int)start;
int physSize = physicsParms["size"].AsInteger(); int physSize = physicsParms["size"].AsInteger();
if (physOffset < 0 || physSize == 0) if (physOffset < 0 || physSize == 0)
return null; // no mesh data in asset return null; // no mesh data in asset
m_log.Debug("[MESH]: physOffset:" + physOffset.ToString() + " physSize:" + physSize.ToString()); OSD decodedMeshOsd = new OSD();
//MemoryStream ms = new MemoryStream(primShape.SculptData, physOffset, physSize); byte[] meshBytes = new byte[physSize];
//GZipStream gzStream = new GZipStream(ms, CompressionMode.Decompress); System.Buffer.BlockCopy(primShape.SculptData, physOffset, meshBytes, 0, physSize);
byte[] decompressed = new byte[physSize * 5];
//int maxSize = physSize * 5; // arbitrary guess try
//byte[] readBuffer = new byte[maxSize]; {
{
string filename = System.IO.Path.Combine(decodedSculptMapPath, "meshInput_" + primShape.SculptTexture.ToString());
using (FileStream fs = new FileStream(filename, FileMode.Create))
{
fs.Write(meshBytes, 0, meshBytes.Length);
}
}
//int bytesRead = gzStream.Read(readBuffer, 0, maxSize); using (MemoryStream inMs = new MemoryStream(meshBytes))
{
using (MemoryStream outMs = new MemoryStream())
{
using (ZOutputStream zOut = new ZOutputStream(outMs))
{
byte[] readBuffer = new byte[2048];
int readLen = 0;
while ((readLen = inMs.Read(readBuffer, 0, readBuffer.Length)) > 0)
{
zOut.Write(readBuffer, 0, readLen);
}
zOut.Flush();
outMs.Seek(0, SeekOrigin.Begin);
//OSD physMeshOsd = OSDParser.DeserializeLLSDBinary(readBuffer); byte[] decompressedBuf = outMs.GetBuffer();
decodedMeshOsd = OSDParser.DeserializeLLSDBinary(decompressedBuf, true);
}
}
}
}
catch (Exception e)
{
m_log.Error("[MESH]: exception decoding physical mesh: " + e.ToString());
return null;
}
OSDArray decodedMeshOsdArray = null;
// physics_shape is an array of OSDMaps, one for each submesh
if (decodedMeshOsd is OSDArray)
{
decodedMeshOsdArray = (OSDArray)decodedMeshOsd;
foreach (OSD subMeshOsd in decodedMeshOsdArray)
{
if (subMeshOsd is OSDMap)
{
OSDMap subMeshMap = (OSDMap)subMeshOsd;
OpenMetaverse.Vector3 posMax = ((OSDMap)subMeshMap["PositionDomain"])["Max"].AsVector3();
OpenMetaverse.Vector3 posMin = ((OSDMap)subMeshMap["PositionDomain"])["Min"].AsVector3();
byte[] posBytes = subMeshMap["Position"].AsBinary();
for (int i = 0; i < posBytes.Length; i += 6)
{
ushort uX = Utils.BytesToUInt16(posBytes, i);
ushort uY = Utils.BytesToUInt16(posBytes, i + 2);
ushort uZ = Utils.BytesToUInt16(posBytes, i + 4);
Coord c = new Coord(
Utils.UInt16ToFloat(uX, posMin.X, posMax.X) * size.X,
Utils.UInt16ToFloat(uY, posMin.Y, posMax.Y) * size.Y,
Utils.UInt16ToFloat(uZ, posMin.Z, posMax.Z) * size.Z);
coords.Add(c);
}
byte[] triangleBytes = subMeshMap["TriangleList"].AsBinary();
for (int i = 0; i < triangleBytes.Length; i += 6)
{
ushort v1 = Utils.BytesToUInt16(triangleBytes, i);
ushort v2 = Utils.BytesToUInt16(triangleBytes, i + 2);
ushort v3 = Utils.BytesToUInt16(triangleBytes, i + 4);
Face f = new Face(v1, v2, v3);
faces.Add(f);
}
}
}
}
} }
//just bail out for now until mesh code is finished
return null;
} }
else else
{ {

View File

@ -147,6 +147,12 @@
; to false if you have compatibility problems. ; to false if you have compatibility problems.
;CacheSculptMaps = true ;CacheSculptMaps = true
; if you use Meshmerizer and want collisions for meshies, setting this to true
; will cause OpenSim to attempt to decode meshies assets, extract the physics
; mesh, and use it for collisions. This is currently experimental code and enabling
; it may cause unexpected physics problems.
;UseMeshiesPhysicsMesh = false
; Choose one of the physics engines below ; Choose one of the physics engines below
; OpenDynamicsEngine is by some distance the most developed physics engine ; OpenDynamicsEngine is by some distance the most developed physics engine
; basicphysics effectively does not model physics at all, making all objects phantom ; basicphysics effectively does not model physics at all, making all objects phantom

BIN
bin/zlib.net.dll Normal file

Binary file not shown.

View File

@ -587,7 +587,6 @@
<ReferencePath>../../../../bin/</ReferencePath> <ReferencePath>../../../../bin/</ReferencePath>
<Reference name="System"/> <Reference name="System"/>
<Reference name="System.Drawing"/> <Reference name="System.Drawing"/>
<Reference name="System.IO.Compression;"/>
<Reference name="CSJ2K" path="../../../../bin/"/> <Reference name="CSJ2K" path="../../../../bin/"/>
<Reference name="OpenMetaverseTypes" path="../../../../bin/"/> <Reference name="OpenMetaverseTypes" path="../../../../bin/"/>
<Reference name="OpenMetaverse" path="../../../../bin/"/> <Reference name="OpenMetaverse" path="../../../../bin/"/>
@ -597,6 +596,7 @@
<Reference name="OpenSim.Framework.Console"/> <Reference name="OpenSim.Framework.Console"/>
<Reference name="OpenSim.Region.Physics.Manager"/> <Reference name="OpenSim.Region.Physics.Manager"/>
<Reference name="log4net" path="../../../../bin/"/> <Reference name="log4net" path="../../../../bin/"/>
<Reference name="zlib.net" path="../../../../bin/"/>
<Files> <Files>
<Match pattern="*.cs" recurse="true"/> <Match pattern="*.cs" recurse="true"/>