corrade-vassal – Rev 1

Subversion Repositories:
Rev:
/*
 * 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 byte[] TextureData;
    }

    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();

        Dictionary<Vertex, int> LookUp = new Dictionary<Vertex, int>();

        public void AddVertex(Vertex v)
        {
            int index;

            if (LookUp.ContainsKey(v))
            {
                index = LookUp[v];
            }
            else
            {
                index = Vertices.Count;
                Vertices.Add(v);
                LookUp[v] = index;
            }

            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;

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

    }
}

Generated by GNU Enscript 1.6.5.90.