Collada parser and model uploader. Work in progress.
Sample code:
var parser = new OpenMetaverse.ImportExport.ColladaLoader();
var prims = parser.Load(o.FileName);
if (prims != null && prims.Count > 0)
{
var uploader = new OpenMetaverse.ImportExport.ModelUploader(client, prims);
uploader.PrepareUpload();
}
Note that PrepareUpload performs the upload as well in this initial stage.
TODO:
* Image upload
* Support for quads in addition to triangles
This commit is contained in:
201
OpenMetaverse/ImportExport/Model.cs
Normal file
201
OpenMetaverse/ImportExport/Model.cs
Normal file
@@ -0,0 +1,201 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2014, openmetaverse.org
|
||||
* All rights reserved.
|
||||
*
|
||||
* - Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* - Neither the name of the openmetaverse.org nor the names
|
||||
* of its contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using OpenMetaverse.Rendering;
|
||||
using OpenMetaverse.StructuredData;
|
||||
|
||||
namespace OpenMetaverse.ImportExport
|
||||
{
|
||||
|
||||
public class ModelMaterial
|
||||
{
|
||||
public string ID;
|
||||
public Color4 DiffuseColor = Color4.White;
|
||||
public string Texture;
|
||||
}
|
||||
|
||||
public class ModelFace
|
||||
{
|
||||
public List<Vertex> Vertices = new List<Vertex>();
|
||||
public List<uint> Indices = new List<uint>();
|
||||
public string MaterialID = string.Empty;
|
||||
public ModelMaterial Material = new ModelMaterial();
|
||||
|
||||
public void AddVertex(Vertex v)
|
||||
{
|
||||
int index = -1;
|
||||
|
||||
for (int i = 0; i < Vertices.Count; i++)
|
||||
{
|
||||
if (
|
||||
v.Position == Vertices[i].Position &&
|
||||
v.Normal == Vertices[i].Normal &&
|
||||
v.TexCoord == Vertices[i].TexCoord
|
||||
)
|
||||
{
|
||||
index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (index == -1)
|
||||
{
|
||||
index = Vertices.Count;
|
||||
Vertices.Add(v);
|
||||
}
|
||||
|
||||
Indices.Add((uint)index);
|
||||
}
|
||||
}
|
||||
|
||||
public class ModelPrim
|
||||
{
|
||||
public List<Vector3> Positions;
|
||||
public Vector3 BoundMin = new Vector3(float.MaxValue, float.MaxValue, float.MaxValue);
|
||||
public Vector3 BoundMax = new Vector3(float.MinValue, float.MinValue, float.MinValue);
|
||||
public Vector3 Position;
|
||||
public Vector3 Scale;
|
||||
public Quaternion Rotation = Quaternion.Identity;
|
||||
public List<ModelFace> Faces = new List<ModelFace>();
|
||||
public string ID;
|
||||
public byte[] Asset;
|
||||
|
||||
public void CreateAsset(UUID creator)
|
||||
{
|
||||
OSDMap header = new OSDMap();
|
||||
header["version"] = 1;
|
||||
header["creator"] = creator;
|
||||
header["date"] = DateTime.Now;
|
||||
|
||||
header["rez_position"] = Position;
|
||||
header["rez_scale"] = Scale;
|
||||
|
||||
OSDArray faces = new OSDArray();
|
||||
foreach (var face in Faces)
|
||||
{
|
||||
OSDMap faceMap = new OSDMap();
|
||||
|
||||
// Find UV min/max
|
||||
Vector2 uvMin = new Vector2(float.MaxValue, float.MaxValue);
|
||||
Vector2 uvMax = new Vector2(float.MinValue, float.MinValue);
|
||||
foreach (var v in face.Vertices)
|
||||
{
|
||||
if (v.TexCoord.X < uvMin.X) uvMin.X = v.TexCoord.X;
|
||||
if (v.TexCoord.Y < uvMin.Y) uvMin.Y = v.TexCoord.Y;
|
||||
|
||||
if (v.TexCoord.X > uvMax.X) uvMax.X = v.TexCoord.X;
|
||||
if (v.TexCoord.Y > uvMax.Y) uvMax.Y = v.TexCoord.Y;
|
||||
}
|
||||
OSDMap uvDomain = new OSDMap();
|
||||
uvDomain["Min"] = uvMin;
|
||||
uvDomain["Max"] = uvMax;
|
||||
faceMap["TexCoord0Domain"] = uvDomain;
|
||||
|
||||
|
||||
OSDMap positionDomain = new OSDMap();
|
||||
positionDomain["Min"] = new Vector3(-0.5f, -0.5f, -0.5f);
|
||||
positionDomain["Max"] = new Vector3(0.5f, 0.5f, 0.5f);
|
||||
faceMap["PositionDomain"] = positionDomain;
|
||||
|
||||
List<byte> posBytes = new List<byte>(face.Vertices.Count * sizeof(UInt16) * 3);
|
||||
List<byte> norBytes = new List<byte>(face.Vertices.Count * sizeof(UInt16) * 3);
|
||||
List<byte> uvBytes = new List<byte>(face.Vertices.Count * sizeof(UInt16) * 2);
|
||||
|
||||
foreach (var v in face.Vertices)
|
||||
{
|
||||
posBytes.AddRange(Utils.UInt16ToBytes(Utils.FloatToUInt16(v.Position.X, -0.5f, 0.5f)));
|
||||
posBytes.AddRange(Utils.UInt16ToBytes(Utils.FloatToUInt16(v.Position.Y, -0.5f, 0.5f)));
|
||||
posBytes.AddRange(Utils.UInt16ToBytes(Utils.FloatToUInt16(v.Position.Z, -0.5f, 0.5f)));
|
||||
|
||||
norBytes.AddRange(Utils.UInt16ToBytes(Utils.FloatToUInt16(v.Normal.X, -1f, 1f)));
|
||||
norBytes.AddRange(Utils.UInt16ToBytes(Utils.FloatToUInt16(v.Normal.Y, -1f, 1f)));
|
||||
norBytes.AddRange(Utils.UInt16ToBytes(Utils.FloatToUInt16(v.Normal.Z, -1f, 1f)));
|
||||
|
||||
uvBytes.AddRange(Utils.UInt16ToBytes(Utils.FloatToUInt16(v.TexCoord.X, uvMin.X, uvMax.X)));
|
||||
uvBytes.AddRange(Utils.UInt16ToBytes(Utils.FloatToUInt16(v.TexCoord.Y, uvMin.Y, uvMax.Y)));
|
||||
}
|
||||
|
||||
faceMap["Position"] = posBytes.ToArray();
|
||||
faceMap["Normal"] = norBytes.ToArray();
|
||||
faceMap["TexCoord0"] = uvBytes.ToArray();
|
||||
|
||||
List<byte> indexBytes = new List<byte>(face.Indices.Count * sizeof(UInt16));
|
||||
foreach (var t in face.Indices)
|
||||
{
|
||||
indexBytes.AddRange(Utils.UInt16ToBytes((ushort)t));
|
||||
}
|
||||
faceMap["TriangleList"] = indexBytes.ToArray();
|
||||
|
||||
faces.Add(faceMap);
|
||||
}
|
||||
|
||||
byte[] physicStubBytes = Helpers.ZCompressOSD(PhysicsStub());
|
||||
|
||||
byte[] meshBytes = Helpers.ZCompressOSD(faces);
|
||||
int n = 0;
|
||||
|
||||
OSDMap lodParms = new OSDMap();
|
||||
lodParms["offset"] = n;
|
||||
lodParms["size"] = meshBytes.Length;
|
||||
header["high_lod"] = lodParms;
|
||||
n += meshBytes.Length;
|
||||
|
||||
lodParms = new OSDMap();
|
||||
lodParms["offset"] = n;
|
||||
lodParms["size"] = physicStubBytes.Length;
|
||||
header["physics_convex"] = lodParms;
|
||||
n += physicStubBytes.Length;
|
||||
|
||||
byte[] headerBytes = OSDParser.SerializeLLSDBinary(header, false);
|
||||
n += headerBytes.Length;
|
||||
|
||||
Asset = new byte[n];
|
||||
|
||||
int offset = 0;
|
||||
Buffer.BlockCopy(headerBytes, 0, Asset, offset, headerBytes.Length);
|
||||
offset += headerBytes.Length;
|
||||
|
||||
Buffer.BlockCopy(meshBytes, 0, Asset, offset, meshBytes.Length);
|
||||
offset += meshBytes.Length;
|
||||
|
||||
Buffer.BlockCopy(physicStubBytes, 0, Asset, offset, physicStubBytes.Length);
|
||||
offset += physicStubBytes.Length;
|
||||
|
||||
}
|
||||
|
||||
public static OSD PhysicsStub()
|
||||
{
|
||||
OSDMap ret = new OSDMap();
|
||||
ret["Max"] = new Vector3(0.5f, 0.5f, 0.5f);
|
||||
ret["Min"] = new Vector3(-0.5f, -0.5f, -0.5f);
|
||||
ret["BoundingVerts"] = new byte[] { 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 255, 255, 255, 127, 0, 0, 255, 255, 255, 127, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 0, 0, 255, 255, 0, 0, 255, 127, 255, 255, 255, 255, 255, 255, 0, 0, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 255, 255, 0, 0, 255, 255 };
|
||||
return ret;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user