if (!meshAsset.Decode())
{
return false;
}
OSDMap MeshData = meshAsset.MeshData;
mesh[0] = new FacetedMesh();
mesh[0].Faces = new ArrayList<Face>();
mesh[0].Prim = prim;
mesh[0].Profile.Faces = new ArrayList<ProfileFace>();
mesh[0].Profile.Positions = new ArrayList<Vector3>();
mesh[0].Path.Points = new ArrayList<PathPoint>();
OSD facesOSD = null;
switch (LOD)
{
default:
case Highest:
facesOSD = MeshData.get("high_lod");
break;
case High:
facesOSD = MeshData.get("medium_lod");
break;
case Medium:
facesOSD = MeshData.get("low_lod");
break;
case Low:
facesOSD = MeshData.get("lowest_lod");
break;
}
if (facesOSD == null || !(facesOSD instanceof OSDArray))
{
return false;
}
OSDArray decodedMeshOsdArray = (OSDArray)facesOSD;
for (int faceNr = 0; faceNr < decodedMeshOsdArray.count(); faceNr++)
{
OSD subMeshOsd = decodedMeshOsdArray.get(faceNr);
// Decode each individual face
if (subMeshOsd instanceof OSDMap)
{
Face oface = new Face();
oface.ID = faceNr;
oface.Vertices = new ArrayList<Vertex>();
oface.Indices = new ArrayList<Integer>();
oface.TextureFace = prim.Textures.GetFace(faceNr);
OSDMap subMeshMap = (OSDMap)subMeshOsd;
Vector3 posMax;
Vector3 posMin;
// If PositionDomain is not specified, the default is from -0.5 to 0.5
if (subMeshMap.containsKey("PositionDomain"))
{
posMax = ((OSDMap)subMeshMap.get("PositionDomain")).get("Max").asVector3();
posMin = ((OSDMap)subMeshMap.get("PositionDomain")).get("Min").asVector3();
}
else
{
posMax = new Vector3(0.5f, 0.5f, 0.5f);
posMin = new Vector3(-0.5f, -0.5f, -0.5f);
}
// Vertex positions
byte[] posBytes = subMeshMap.get("Position").asBinary();
// Normals
byte[] norBytes = null;
if (subMeshMap.containsKey("Normal"))
{
norBytes = subMeshMap.get("Normal").asBinary();
}
// UV texture map
Vector2 texPosMax = Vector2.Zero;
Vector2 texPosMin = Vector2.Zero;
byte[] texBytes = null;
if (subMeshMap.containsKey("TexCoord0"))
{
texBytes = subMeshMap.get("TexCoord0").asBinary();
texPosMax = ((OSDMap)subMeshMap.get("TexCoord0Domain")).get("Max").asVector2();
texPosMin = ((OSDMap)subMeshMap.get("TexCoord0Domain")).get("Min").asVector2();
}
// Extract the vertex position data
// If present normals and texture coordinates too
for (int i = 0; i < posBytes.length; i += 6)
{
int uX = Utils.bytesToUInt16(posBytes, i);
int uY = Utils.bytesToUInt16(posBytes, i + 2);
int uZ = Utils.bytesToUInt16(posBytes, i + 4);
Vertex vx = new Vertex();
vx.Position = new Vector3(
Utils.uint16ToFloat(uX, posMin.X, posMax.X),
Utils.uint16ToFloat(uY, posMin.Y, posMax.Y),
Utils.uint16ToFloat(uZ, posMin.Z, posMax.Z));
if (norBytes != null && norBytes.length >= i + 4)
{
int nX = Utils.bytesToUInt16(norBytes, i);
int nY = Utils.bytesToUInt16(norBytes, i + 2);
int nZ = Utils.bytesToUInt16(norBytes, i + 4);
vx.Normal = new Vector3(
Utils.uint16ToFloat(nX, posMin.X, posMax.X),
Utils.uint16ToFloat(nY, posMin.Y, posMax.Y),
Utils.uint16ToFloat(nZ, posMin.Z, posMax.Z));
}
int vertexIndexOffset = oface.Vertices.size() * 4;
if (texBytes != null && texBytes.length >= vertexIndexOffset + 4)
{
int tX = Utils.bytesToUInt16(texBytes, vertexIndexOffset);
int tY = Utils.bytesToUInt16(texBytes, vertexIndexOffset + 2);
vx.TexCoord = new Vector2(
Utils.uint16ToFloat(tX, texPosMin.X, texPosMax.X),
Utils.uint16ToFloat(tY, texPosMin.Y, texPosMax.Y));
}
oface.Vertices.add(vx);
}
byte[] triangleBytes = subMeshMap.get("TriangleList").asBinary();
for (int i = 0; i < triangleBytes.length; i += 6)
{
int v1 = Utils.bytesToUInt16(triangleBytes, i);
oface.Indices.add(v1);
int v2 = Utils.bytesToUInt16(triangleBytes, i + 2);