Beispiel #1
0
        static PrimitiveManager DecodePrimitivesUnweighted(GeometryEntry geo)
        {
            PrimitiveManager manager = DecodePrimitives(geo);

            Vector3 *      pVert    = null;
            ushort *       pVInd    = (ushort *)manager._indices.Address;
            int            vCount   = 0;
            List <Vertex3> vertList = new List <Vertex3>(manager._pointCount);

            manager._vertices = vertList;

            //Find vertex source
            foreach (SourceEntry s in geo._sources)
            {
                if (s._id == geo._verticesInput._source)
                {
                    UnsafeBuffer b = s._arrayData as UnsafeBuffer;
                    pVert  = (Vector3 *)b.Address;
                    vCount = b.Length / 12;
                    break;
                }
            }

            UnsafeBuffer remap  = new UnsafeBuffer(vCount * 2);
            ushort *     pRemap = (ushort *)remap.Address;

            //Create remap table
            for (int i = 0; i < vCount; i++)
            {
                //Create Vertex and look for match
                Vertex3 v = new Vertex3(pVert[i]);

                int index = 0;
                while (index < vertList.Count)
                {
                    if (v.Equals(vertList[index]))
                    {
                        break;
                    }
                    index++;
                }
                if (index == vertList.Count)
                {
                    vertList.Add(v);
                }

                pRemap[i] = (ushort)index;
            }

            //Remap vertex indices
            for (int i = 0; i < manager._pointCount; i++, pVInd++)
            {
                *pVInd = pRemap[*pVInd];
            }

            remap.Dispose();

            //manager.MergeTempData();
            return(manager);
        }
        private static unsafe void WriteNormalGroup(StreamWriter writer, PrimitiveManager p, bool weight)
        {
            ushort* pIndex = (ushort*)p._indices.Address;
            Vector3 v;

            writer.WriteLine();
            writer.WriteLine("#Normals");
            Vector3* pVert = (Vector3*)p._faceData[1].Address;
            for (int i = 0; i < p._faceData[1].Length / 12; i++)
            {
                //writer.WriteLine("vn {0} {1} {2}", pVert->_x, pVert->_y, (pVert++)->_z);
                if (weight && p._vertices[*pIndex]._matrixNode != null)
                    v = p._vertices[*pIndex++]._matrixNode.Matrix.GetRotationMatrix() * *pVert++;
                else
                    v = *pVert++;
                writer.WriteLine("vn {0} {1} {2}", v._x, v._y, v._z);
            }
        }
Beispiel #3
0
        static void NullWeight(PrimitiveManager manager, GeometryEntry geo)
        {
            Vector3 *      pVert    = null;
            ushort *       pVInd    = (ushort *)manager._indices.Address;
            List <Vertex3> vertList = new List <Vertex3>(manager._pointCount);

            //Find vertex source
            foreach (SourceEntry s in geo._sources)
            {
                if (s._id == geo._verticesInput._source)
                {
                    pVert = (Vector3 *)((UnsafeBuffer)s._arrayData).Address;
                    break;
                }
            }

            //Construct Vertex from new weight
            for (int i = 0; i < manager._pointCount; i++)
            {
                //Create Vertex and look for match
                Vertex3 v     = new Vertex3(pVert[*pVInd]);
                int     index = 0;
                while (index < vertList.Count)
                {
                    if (v.Equals(vertList[i]))
                    {
                        break;
                    }
                    index++;
                }
                if (index == vertList.Count)
                {
                    vertList.Add(v);
                }

                //Assign new index
                *pVInd++ = (ushort)index;
            }
        }
Beispiel #4
0
        private unsafe static void WriteNormalGroup(StreamWriter writer, PrimitiveManager p, bool weight)
        {
            ushort *pIndex = (ushort *)p._indices.Address;
            Vector3 v;

            writer.WriteLine();
            writer.WriteLine("#Normals");
            Vector3 *pVert = (Vector3 *)p._faceData[1].Address;

            for (int i = 0; i < p._faceData[1].Length / 12; i++)
            {
                //writer.WriteLine("vn {0} {1} {2}", pVert->_x, pVert->_y, (pVert++)->_z);
                if (weight && p._vertices[*pIndex]._matrixNode != null)
                {
                    v = p._vertices[*pIndex++]._matrixNode.Matrix.GetRotationMatrix() * *pVert++;
                }
                else
                {
                    v = *pVert++;
                }
                writer.WriteLine("vn {0} {1} {2}", v._x, v._y, v._z);
            }
        }
Beispiel #5
0
        static PrimitiveManager DecodePrimitivesWeighted(GeometryEntry geo, SkinEntry skin, SceneEntry scene, InfluenceManager infManager, ref string Error)
        {
            PrimitiveManager manager = DecodePrimitives(geo);

            MDL0BoneNode[] boneList;
            MDL0BoneNode   bone = null;
            int            boneCount;

            string[]       jointStrings = null;
            byte *         pCmd = stackalloc byte[4];
            int            cmdCount = skin._weightInputs.Count;
            float          weight = 0;
            float *        pWeights = null;
            Vector3 *      pVert = null, pNorms = null;
            ushort *       pVInd    = (ushort *)manager._indices.Address;
            List <Vertex3> vertList = new List <Vertex3>(skin._weightCount);
            Matrix *       pMatrix  = null;

            UnsafeBuffer remap  = new UnsafeBuffer(skin._weightCount * 2);
            ushort *     pRemap = (ushort *)remap.Address;

            pNorms = (Vector3 *)manager._faceData[1].Address;
            //List<int> FixedIndices = new List<int>();

            manager._vertices = vertList;

            //Find vertex source
            foreach (SourceEntry s in geo._sources)
            {
                if (s._id == geo._verticesInput._source)
                {
                    pVert = (Vector3 *)((UnsafeBuffer)s._arrayData).Address;
                    break;
                }
            }

            //Find joint source
            foreach (InputEntry inp in skin._jointInputs)
            {
                if (inp._semantic == SemanticType.JOINT)
                {
                    foreach (SourceEntry src in skin._sources)
                    {
                        if (src._id == inp._source)
                        {
                            jointStrings = src._arrayData as string[];
                            break;
                        }
                    }
                }
                else if (inp._semantic == SemanticType.INV_BIND_MATRIX)
                {
                    foreach (SourceEntry src in skin._sources)
                    {
                        if (src._id == inp._source)
                        {
                            pMatrix = (Matrix *)((UnsafeBuffer)src._arrayData).Address;
                            break;
                        }
                    }
                }
            }

            Error = "There was a problem creating the list of bones for geometry entry " + geo._name;

            //Populate bone list
            boneCount = jointStrings.Length;
            boneList  = new MDL0BoneNode[boneCount];
            for (int i = 0; i < boneCount; i++)
            {
                boneList[i] = scene.FindNode(jointStrings[i])._node as MDL0BoneNode;
            }

            //Build command list
            foreach (InputEntry inp in skin._weightInputs)
            {
                switch (inp._semantic)
                {
                case SemanticType.JOINT:
                    pCmd[inp._offset] = 1;
                    break;

                case SemanticType.WEIGHT:
                    pCmd[inp._offset] = 2;

                    //Get weight source
                    foreach (SourceEntry src in skin._sources)
                    {
                        if (src._id == inp._source)
                        {
                            pWeights = (float *)((UnsafeBuffer)src._arrayData).Address;
                            break;
                        }
                    }

                    break;

                default:
                    pCmd[inp._offset] = 0;
                    break;
                }
            }

            Error = "There was a problem creating vertex influences for geometry entry " + geo._name;

            //Build vertex list and remap table
            for (int i = 0; i < skin._weightCount; i++)
            {
                //Create influence
                int       iCount = skin._weights[i].Length / cmdCount;
                Influence inf    = new Influence(iCount);
                fixed(int *p = skin._weights[i])
                {
                    int *iPtr = p;

                    for (int x = 0; x < iCount; x++)
                    {
                        for (int z = 0; z < cmdCount; z++, iPtr++)
                        {
                            if (pCmd[z] == 1)
                            {
                                bone = boneList[*iPtr];
                            }
                            else if (pCmd[z] == 2)
                            {
                                weight = pWeights[*iPtr];
                            }
                        }
                        //if (bone != null)
                        //    if (bone.Name == "TopN" || bone.Name == "XRotN" || bone.Name == "YRotN" || bone.Name == "TransN" || bone.Name == "ThrowN" || bone.Name == "FacePattern")
                        //        Console.WriteLine(bone.Name);
                        //    else if (bone.Parent != null)
                        //        if (bone.Parent.Name == "FacePattern")
                        //            Console.WriteLine(bone.Name);
                        inf._weights[x] = new BoneWeight(bone, weight);
                    }
                }

                inf.CalcMatrix();

                Error = "There was a problem creating a vertex from the geometry entry " + geo._name + ".\nMake sure that all the vertices are weighted properly.";

                Vertex3 v;
                if (inf._weights.Length > 1)
                {
                    //Match with manager
                    inf = infManager.AddOrCreate(inf);
                    v   = new Vertex3(skin._bindMatrix * pVert[i], inf); //World position
                }
                else
                {
                    bone = inf._weights[0].Bone;
                    v    = new Vertex3(bone._inverseBindMatrix * skin._bindMatrix * pVert[i], bone); //Local position
                }

                ////Create Vertex, set to world position.
                //v = new Vertex3(skin._bindMatrix * pVert[i], inf);
                ////Fix single-bind vertices
                //v.Position = inf._weights[0].Bone._inverseBindMatrix * v.Position;

                ushort index = 0;
                while (index < vertList.Count)
                {
                    if (v.Equals(vertList[index]))
                    {
                        break;
                    }
                    index++;
                }
                if (index == vertList.Count)
                {
                    vertList.Add(v);
                }

                pRemap[i] = index;
            }

            Error = "There was a problem fixing normal rotations for geometry entry " + geo._name;

            //Remap vertex indices and fix normals
            for (int i = 0; i < manager._pointCount; i++, pVInd++)
            {
                *       pVInd = pRemap[*pVInd];
                Vertex3 v     = null;
                if (*pVInd < vertList.Count)
                {
                    v = vertList[*pVInd];
                }
                if (v != null && v._influence != null)
                {
                    if (v._influence.Weights.Length > 1)
                    {
                        pNorms[i] = skin._bindMatrix.GetRotationMatrix() * pNorms[i];
                    }
                    else
                    {
                        pNorms[i] = skin._bindMatrix.GetRotationMatrix() * v._influence.Weights[0].Bone._inverseBindMatrix.GetRotationMatrix() * pNorms[i];
                    }
                }
            }

            remap.Dispose();

            //manager.MergeTempData();
            return(manager);
        }
 public override void Dispose()
 {
     if (_manager != null)
     {
         _manager.Dispose();
         _manager = null;
     }
     base.Dispose();
 }
Beispiel #7
0
        //private static void WriteTriFan(StreamWriter writer, Primitive p)
        //{
        //    if ((p._vertexIndices == null) || (p._normalIndices == null))
        //        return;

        //    writer.WriteLine();
        //    writer.WriteLine("#Trifan");
        //    int count = p._elementCount - 2;
        //    if (p._uvIndices[0] != null)
        //        for (int i = 0; i < count; i++)
        //            writer.WriteLine(String.Format("f {0}/{1}/{2} {3}/{4}/{5} {6}/{7}/{8}",
        //                p._vertexIndices[0] + 1, p._uvIndices[0][0] + 1, p._normalIndices[0] + 1,
        //                p._vertexIndices[i + 1] + 1, p._uvIndices[0][i + 1] + 1, p._normalIndices[i + 1] + 1,
        //                p._vertexIndices[i + 2] + 1, p._uvIndices[0][i + 2] + 1, p._normalIndices[i + 2] + 1));
        //    else
        //        for (int i = 0; i < count; i++)
        //            writer.WriteLine(String.Format("f {0}//{1} {2}//{3} {4}//{5}",
        //                    p._vertexIndices[0] + 1, p._normalIndices[0] + 1,
        //                    p._vertexIndices[i + 1] + 1, p._normalIndices[i + 1] + 1,
        //                    p._vertexIndices[i + 2] + 1, p._normalIndices[i + 2] + 1));
        //}
        //private static void WriteTriStrip(StreamWriter writer, Primitive p)
        //{
        //    if ((p._vertexIndices == null) || (p._normalIndices == null))
        //        return;

        //    writer.WriteLine();
        //    writer.WriteLine("#Tristrip");
        //    int count = p._elementCount - 2;
        //    int l1 = 0, l2 = 2;
        //    if (p._uvIndices[0] != null)
        //        for (int i = 0; i < count; i++)
        //        {
        //            if ((i & 1) == 0)
        //            {
        //                l1 = i;
        //                l2 = i + 1;
        //            }
        //            else
        //            {
        //                l1 = i + 1;
        //                l2 = i;
        //            }
        //            writer.WriteLine(String.Format("f {0}/{1}/{2} {3}/{4}/{5} {6}/{7}/{8}",
        //                p._vertexIndices[l1] + 1, p._uvIndices[0][l1] + 1, p._normalIndices[l1] + 1,
        //                p._vertexIndices[l2] + 1, p._uvIndices[0][l2] + 1, p._normalIndices[l2] + 1,
        //                p._vertexIndices[i + 2] + 1, p._uvIndices[0][i + 2] + 1, p._normalIndices[i + 2] + 1));
        //        }
        //    else
        //        for (int i = 0; i < count; i++)
        //        {
        //            if ((i & 1) == 0)
        //            {
        //                l1 = i;
        //                l2 = i + 1;
        //            }
        //            else
        //            {
        //                l1 = i + 1;
        //                l2 = i;
        //            }
        //            writer.WriteLine(String.Format("f {0}//{1} {2}//{3} {4}//{5}",
        //                    p._vertexIndices[l1] + 1, p._normalIndices[l1] + 1,
        //                    p._vertexIndices[l2] + 1, p._normalIndices[l2] + 1,
        //                    p._vertexIndices[i + 2] + 1, p._normalIndices[i + 2] + 1));
        //        }
        //}
        //private static void WriteTriList(StreamWriter writer, Primitive p)
        //{
        //    if ((p._vertexIndices == null) || (p._normalIndices == null))
        //        return;

        //    writer.WriteLine();
        //    writer.WriteLine("#Trilist");
        //    int count = p._elementCount / 3;
        //    if (p._uvIndices[0] != null)
        //        for (int i = 0, x = 0; i < count; i++, x += 3)
        //            writer.WriteLine(String.Format("f {0}/{1}/{2} {3}/{4}/{5} {6}/{7}/{8}",
        //                p._vertexIndices[x] + 1, p._uvIndices[0][x] + 1, p._normalIndices[x] + 1,
        //                p._vertexIndices[x + 1] + 1, p._uvIndices[0][x + 1] + 1, p._normalIndices[x + 1] + 1,
        //                p._vertexIndices[x + 2] + 1, p._uvIndices[0][x + 2] + 1, p._normalIndices[x + 2] + 1));
        //    else
        //        for (int i = 0, x = 0; i < count; i++, x += 3)
        //            writer.WriteLine(String.Format("f {0}//{1} {2}//{3} {4}//{5}",
        //                p._vertexIndices[x] + 1, p._normalIndices[x] + 1,
        //                p._vertexIndices[x + 1] + 1, p._normalIndices[x + 1] + 1,
        //                p._vertexIndices[x + 2] + 1, p._normalIndices[x + 2] + 1));
        //}
        private unsafe static void WriteTriList(StreamWriter writer, PrimitiveManager p)
        {
            uint[] pData = p._triangles._indices;
            uint   x     = 0;

            ushort *pVert = (ushort *)p._indices.Address;

            bool hasUVs   = p._faceData[4] != null;
            bool hasNorms = p._faceData[1] != null;

            writer.WriteLine();
            writer.WriteLine("#Trilist");

            int count = p._triangles._elementCount / 3;

            //Loop through triangles
            for (int tri = 0; tri < count; tri++)
            {
                //writer.WriteLine("s " + i); //Smoothing groups don't seem to do anything
                writer.Write("f "); //Face

                //Loop through triangle points
                for (int pt = 0; pt < 3; pt++)
                {
                    uint index = pData[x++];

                    //Loop through vertices, uvs, normals
                    for (int asset = 0; asset < 3; asset++)
                    {
                        if (asset != 0)        //Not a point start
                        {
                            writer.Write("/"); //Asset divider
                        }
                        //If no UVs, there's a double slash
                        if (!hasUVs && asset == 1)
                        {
                            continue;
                        }

                        if (asset == 0) //Vertex index
                        {
                            writer.Write((pVert[index] + 1).ToString());
                        }
                        else
                        {
                            writer.Write((index + 1).ToString());
                        }

                        if (asset == 2)  //Point is done
                        {
                            if (pt == 2) //Last point
                            {
                                writer.WriteLine();
                            }
                            else //Still more points to go
                            {
                                writer.Write(" ");
                            }
                        }
                    }
                }
            }
        }
        static PrimitiveManager DecodePrimitives(Matrix nodeMatrix, GeometryEntry geo)
        {
            uint[] pTriarr = null, pLinarr = null;
            uint pTri = 0, pLin = 0;
            long* pInDataList = stackalloc long[12];
            long* pOutDataList = stackalloc long[12];
            int* pData = stackalloc int[16];
            int faces = 0, lines = 0, points = 0;
            ushort fIndex = 0, lIndex = 0, temp;

            PrimitiveDecodeCommand* pCmd = (PrimitiveDecodeCommand*)pData;
            byte** pInData = (byte**)pInDataList;
            byte** pOutData = (byte**)pOutDataList;

            PrimitiveManager manager = new PrimitiveManager();

            //Assign vertex source
            foreach (SourceEntry s in geo._sources)
                if (s._id == geo._verticesInput._source)
                {
                    pInData[0] = (byte*)((UnsafeBuffer)s._arrayData).Address;
                    break;
                }

            foreach (PrimitiveEntry prim in geo._primitives)
            {
                //Get face/line count
                if (prim._type == PrimitiveType.lines || prim._type == PrimitiveType.linestrips)
                    lines += prim._faceCount;
                else
                    faces += prim._faceCount;

                //Get point total
                points += prim._pointCount;

                //Signal storage buffers and set type offsets
                foreach (InputEntry inp in prim._inputs)
                {
                    int offset = -1;

                    switch (inp._semantic)
                    {
                        case SemanticType.VERTEX: offset = 0; break;
                        case SemanticType.NORMAL: offset = 1; break;
                        case SemanticType.COLOR: if (inp._set < 2) offset = 2 + inp._set; break;
                        case SemanticType.TEXCOORD: if (inp._set < 8) offset = 4 + inp._set; break;
                    }

                    if (offset != -1)
                        manager._dirty[offset] = true;

                    inp._outputOffset = offset;
                }
            }
            manager._pointCount = points;

            //Create primitives
            if (faces > 0)
            {
                manager._triangles = new NewPrimitive(faces * 3, BeginMode.Triangles);
                pTriarr = manager._triangles._indices;
            }
            if (lines > 0)
            {
                manager._lines = new NewPrimitive(lines * 2, BeginMode.Lines);
                pLinarr = manager._lines._indices;
            }

            manager._indices = new UnsafeBuffer(points * 2);
            //Create face buffers and assign output pointers
            for (int i = 0; i < 12; i++)
                if (manager._dirty[i])
                {
                    int stride;
                    if (i == 0) stride = 2;
                    else if (i == 1) stride = 12;
                    else if (i < 4) stride = 4;
                    else stride = 8;
                    manager._faceData[i] = new UnsafeBuffer(points * stride);
                    if (i == 0)
                        pOutData[i] = (byte*)manager._indices.Address;
                    else
                        pOutData[i] = (byte*)manager._faceData[i].Address;
                }

            //Decode primitives
            foreach (PrimitiveEntry prim in geo._primitives)
            {
                int count = prim._inputs.Count;
                //Map inputs to command sequence
                foreach (InputEntry inp in prim._inputs)
                {
                    if (inp._outputOffset == -1)
                        pCmd[inp._offset].Cmd = 0;
                    else
                    {
                        pCmd[inp._offset].Cmd = (byte)inp._semantic;
                        pCmd[inp._offset].Index = (byte)inp._outputOffset;

                        //Assign input buffer
                        foreach (SourceEntry src in geo._sources)
                            if (src._id == inp._source)
                            {
                                pInData[inp._outputOffset] = (byte*)((UnsafeBuffer)src._arrayData).Address;
                                break;
                            }
                    }
                }

                //Decode face data using command list
                foreach (PrimitiveFace f in prim._faces)
                    fixed (ushort* p = f._pointIndices)
                        RunPrimitiveCmd(nodeMatrix, pInData, pOutData, pCmd, count, p, f._pointCount);

                //Process point indices
                switch (prim._type)
                {
                    case PrimitiveType.triangles:
                        count = prim._faceCount * 3;
                        while (count-- > 0)
                            pTriarr[pTri++] = fIndex++;
                        break;
                    case PrimitiveType.trifans:
                    case PrimitiveType.polygons:
                    case PrimitiveType.polylist:
                        foreach (PrimitiveFace f in prim._faces)
                        {
                            count = f._pointCount - 2;
                            temp = fIndex;
                            fIndex += 2;
                            while (count-- > 0)
                            {
                                pTriarr[pTri++] = temp;
                                pTriarr[pTri++] = (uint)(fIndex - 1);
                                pTriarr[pTri++] = fIndex++;
                            }
                        }
                        break;
                    case PrimitiveType.tristrips:
                        foreach (PrimitiveFace f in prim._faces)
                        {
                            count = f._pointCount;
                            fIndex += 2;
                            for (int i = 2; i < count; i++)
                            {
                                if ((i & 1) == 0)
                                {
                                    pTriarr[pTri++] = (uint)(fIndex - 2);
                                    pTriarr[pTri++] = (uint)(fIndex - 1);
                                    pTriarr[pTri++] = fIndex++;
                                }
                                else
                                {
                                    pTriarr[pTri++] = (uint)(fIndex - 2);
                                    pTriarr[pTri++] = fIndex;
                                    pTriarr[pTri++] = (uint)(fIndex++ - 1);
                                }
                            }
                        }
                        break;

                    case PrimitiveType.linestrips:
                        foreach (PrimitiveFace f in prim._faces)
                        {
                            count = f._pointCount - 1;
                            lIndex++;
                            while (count-- > 0)
                            {
                                pLinarr[pLin++] = (uint)(lIndex - 1);
                                pLinarr[pLin++] = lIndex++;
                            }
                        }
                        break;

                    case PrimitiveType.lines:
                        foreach (PrimitiveFace f in prim._faces)
                        {
                            count = f._pointCount * 2;
                            while (count-- > 0)
                                pLinarr[pLin++] = lIndex++;
                        }
                        break;
                }
            }
            return manager;
        }
Beispiel #9
0
        private static PrimitiveManager DecodePrimitivesWeighted(
            Matrix bindMatrix,
            GeometryEntry geo,
            SkinEntry skin,
            SceneEntry scene,
            InfluenceManager infManager,
            Type boneType)
        {
            PrimitiveManager manager = DecodePrimitives(geo);

            IBoneNode[] boneList;
            IBoneNode   bone = null;
            int         boneCount;

            string[] jointStringArray = null;
            string   jointString      = null;

            byte *         pCmd = stackalloc byte[4];
            int            cmdCount = skin._weightInputs.Count;
            float          weight = 0;
            float *        pWeights = null;
            Vector3 *      pVert = null, pNorms = null;
            ushort *       pVInd    = (ushort *)manager._indices.Address;
            List <Vertex3> vertList = new List <Vertex3>(skin._weightCount);
            Matrix *       pMatrix  = null;

            UnsafeBuffer remap  = new UnsafeBuffer(skin._weightCount * 2);
            ushort *     pRemap = (ushort *)remap.Address;

            if (manager._faceData[1] != null)
            {
                pNorms = (Vector3 *)manager._faceData[1].Address;
            }

            manager._vertices = vertList;

            //Find vertex source
            foreach (SourceEntry s in geo._sources)
            {
                if (s._id == geo._verticesInput._source)
                {
                    pVert = (Vector3 *)((UnsafeBuffer)s._arrayData).Address;
                    break;
                }
            }

            //Find joint source
            foreach (InputEntry inp in skin._jointInputs)
            {
                if (inp._semantic == SemanticType.JOINT)
                {
                    foreach (SourceEntry src in skin._sources)
                    {
                        if (src._id == inp._source)
                        {
                            jointStringArray = src._arrayData as string[];
                            jointString      = src._arrayDataString;
                            break;
                        }
                    }
                }
                else if (inp._semantic == SemanticType.INV_BIND_MATRIX)
                {
                    foreach (SourceEntry src in skin._sources)
                    {
                        if (src._id == inp._source)
                        {
                            pMatrix = (Matrix *)((UnsafeBuffer)src._arrayData).Address;
                            break;
                        }
                    }
                }
            }

            Error = "There was a problem creating the list of bones for geometry entry " + geo._name;

            //Populate bone list
            boneCount = jointStringArray.Length;
            boneList  = new IBoneNode[boneCount];
            for (int i = 0; i < boneCount; i++)
            {
                NodeEntry entry = scene.FindNode(jointStringArray[i]);
                if (entry != null && entry._node != null)
                {
                    boneList[i] = entry._node as IBoneNode;
                }
                else
                {
                    //Search in reverse!
                    foreach (NodeEntry node in scene._nodes)
                    {
                        if ((entry = RecursiveTestNode(jointString, node)) != null)
                        {
                            if (entry._node != null)
                            {
                                boneList[i] = entry._node as IBoneNode;
                            }

                            break;
                        }
                    }

                    //Couldn't find the bone
                    if (boneList[i] == null)
                    {
                        boneList[i] = Activator.CreateInstance(boneType) as IBoneNode;
                    }
                }
            }

            //Build command list
            foreach (InputEntry inp in skin._weightInputs)
            {
                switch (inp._semantic)
                {
                case SemanticType.JOINT:
                    pCmd[inp._offset] = 1;
                    break;

                case SemanticType.WEIGHT:
                    pCmd[inp._offset] = 2;

                    //Get weight source
                    foreach (SourceEntry src in skin._sources)
                    {
                        if (src._id == inp._source)
                        {
                            pWeights = (float *)((UnsafeBuffer)src._arrayData).Address;
                            break;
                        }
                    }

                    break;

                default:
                    pCmd[inp._offset] = 0;
                    break;
                }
            }

            Error = "There was a problem creating vertex influences for geometry entry " + geo._name;

            //Build vertex list and remap table
            for (int i = 0; i < skin._weightCount; i++)
            {
                //Create influence
                int       iCount = skin._weights[i].Length / cmdCount;
                Influence inf    = new Influence();
                fixed(int *p = skin._weights[i])
                {
                    int *iPtr = p;

                    for (int x = 0; x < iCount; x++)
                    {
                        for (int z = 0; z < cmdCount; z++, iPtr++)
                        {
                            if (pCmd[z] == 1)
                            {
                                bone = boneList[*iPtr];
                            }
                            else if (pCmd[z] == 2)
                            {
                                weight = pWeights[*iPtr];
                            }
                        }

                        inf.AddWeight(new BoneWeight(bone, weight));
                    }
                }

                inf.CalcMatrix();

                Error = "There was a problem creating a vertex from the geometry entry " + geo._name +
                        ".\nMake sure that all the vertices are weighted properly.";

                Vector3 worldPos = bindMatrix * skin._bindMatrix * pVert[i];
                Vertex3 v;
                if (inf.Weights.Count > 1)
                {
                    //Match with manager
                    inf = infManager.FindOrCreate(inf);
                    v   = new Vertex3(worldPos, inf); //World position
                }
                else
                {
                    bone = inf.Weights[0].Bone;
                    v    = new Vertex3(bone.InverseBindMatrix * worldPos, bone); //Local position
                }

                ushort index = 0;
                while (index < vertList.Count)
                {
                    if (v.Equals(vertList[index]))
                    {
                        break;
                    }

                    index++;
                }

                if (index == vertList.Count)
                {
                    vertList.Add(v);
                }

                pRemap[i] = index;
            }

            Error = "There was a problem fixing normal rotations for geometry entry " + geo._name;

            //Remap vertex indices and fix normals
            for (int i = 0; i < manager._pointCount; i++, pVInd++)
            {
                *pVInd = pRemap[*pVInd];

                if (pNorms != null)
                {
                    Vertex3 v = null;
                    if (*pVInd < vertList.Count)
                    {
                        v = vertList[*pVInd];
                    }

                    if (v != null && v.MatrixNode != null)
                    {
                        if (v.MatrixNode.Weights.Count > 1)
                        {
                            pNorms[i] =
                                (bindMatrix *
                                 skin._bindMatrix).GetRotationMatrix() *
                                pNorms[i];
                        }
                        else
                        {
                            pNorms[i] =
                                (v.MatrixNode.Weights[0].Bone.InverseBindMatrix *
                                 bindMatrix *
                                 skin._bindMatrix).GetRotationMatrix() *
                                pNorms[i];
                        }
                    }
                }
            }

            remap.Dispose();
            return(manager);
        }
        private static void WriteUVs(string name, PrimitiveManager p, int set, XmlWriter writer)
        {
            bool first = true;

            _uvs[set] = p.GetUVs(set, true);
            int count = _uvs[set].Length;
            _uvRemap[set] = new List<int>();
            Vector2* ptr = (Vector2*)p._faceData[set + 4].Address;
            for (int i = 0; i < p._pointCount; i++)
                _uvRemap[set].Add(Array.IndexOf(_uvs[set], ptr[i]));

            //Position source
            writer.WriteStartElement("source");
            writer.WriteAttributeString("id", name + "_UVs" + set.ToString());

            //Array start
            writer.WriteStartElement("float_array");
            writer.WriteAttributeString("id", name + "_UVArr" + set.ToString());
            writer.WriteAttributeString("count", (count * 2).ToString());

            for (int i = 0; i < count; i++)
            {
                if (first)
                    first = false;
                else
                    writer.WriteString(" ");

                //Reverse T component to a top-down form
                //writer.WriteString(String.Format("{0} {1}", pData->_x, 1.0 - pData->_y));
                //pData++;
                writer.WriteString(String.Format("{0} {1}", _uvs[set][i]._x.ToString(CultureInfo.InvariantCulture.NumberFormat), (1.0f - _uvs[set][i]._y).ToString(CultureInfo.InvariantCulture.NumberFormat)));
            }

            writer.WriteEndElement(); //int_array

            //Technique
            writer.WriteStartElement("technique_common");

            writer.WriteStartElement("accessor");
            writer.WriteAttributeString("source", "#" + name + "_UVArr" + set.ToString());
            writer.WriteAttributeString("count", count.ToString());
            writer.WriteAttributeString("stride", "2");

            writer.WriteStartElement("param");
            writer.WriteAttributeString("name", "S");
            writer.WriteAttributeString("type", "float");
            writer.WriteEndElement(); //param
            writer.WriteStartElement("param");
            writer.WriteAttributeString("name", "T");
            writer.WriteAttributeString("type", "float");
            writer.WriteEndElement(); //param

            writer.WriteEndElement(); //accessor
            writer.WriteEndElement(); //technique_common

            writer.WriteEndElement(); //source
        }
        private static void WriteNormals(string name, XmlWriter writer, PrimitiveManager p)
        {
            bool first = true;
            ushort* pIndex = (ushort*)p._indices.Address;
            Vector3* pData = (Vector3*)p._faceData[1].Address;
            Vector3 v;

            HashSet<Vector3> list = new HashSet<Vector3>();
            for (int i = 0; i < p._pointCount; i++)
                list.Add(p._vertices[pIndex[i]].GetMatrix().GetRotationMatrix() * pData[i]);

            _normals = new Vector3[list.Count];
            list.CopyTo(_normals);

            int count = _normals.Length;
            _normRemap = new List<int>();
            for (int i = 0; i < p._pointCount; i++)
                _normRemap.Add(Array.IndexOf(_normals, p._vertices[pIndex[i]].GetMatrix().GetRotationMatrix() * pData[i]));

            //Position source
            writer.WriteStartElement("source");
            writer.WriteAttributeString("id", name + "_Normals");

            //Array start
            writer.WriteStartElement("float_array");
            writer.WriteAttributeString("id", name + "_NormArr");
            writer.WriteAttributeString("count", (count * 3).ToString());

            for (int i = 0; i < count; i++)
            {
                if (first)
                    first = false;
                else
                    writer.WriteString(" ");

                v = _normals[i];

                writer.WriteString(String.Format("{0} {1} {2}", v._x.ToString(CultureInfo.InvariantCulture.NumberFormat), v._y.ToString(CultureInfo.InvariantCulture.NumberFormat), v._z.ToString(CultureInfo.InvariantCulture.NumberFormat)));
            }

            writer.WriteEndElement(); //float_array

            //Technique
            writer.WriteStartElement("technique_common");

            writer.WriteStartElement("accessor");
            writer.WriteAttributeString("source", "#" + name + "_NormArr");
            writer.WriteAttributeString("count", count.ToString());
            writer.WriteAttributeString("stride", "3");

            writer.WriteStartElement("param");
            writer.WriteAttributeString("name", "X");
            writer.WriteAttributeString("type", "float");
            writer.WriteEndElement(); //param
            writer.WriteStartElement("param");
            writer.WriteAttributeString("name", "Y");
            writer.WriteAttributeString("type", "float");
            writer.WriteEndElement(); //param
            writer.WriteStartElement("param");
            writer.WriteAttributeString("name", "Z");
            writer.WriteAttributeString("type", "float");
            writer.WriteEndElement(); //param

            writer.WriteEndElement(); //accessor
            writer.WriteEndElement(); //technique_common

            writer.WriteEndElement(); //source
        }
        static PrimitiveManager DecodePrimitivesWeighted(GeometryEntry geo, SkinEntry skin, SceneEntry scene, InfluenceManager infManager)
        {
            PrimitiveManager manager = DecodePrimitives(geo);

            MDL0BoneNode[] boneList;
            MDL0BoneNode   bone = null;
            int            boneCount;

            string[]       jointStrings = null;
            byte *         pCmd         = stackalloc byte[4];
            int            cmdCount     = skin._weightInputs.Count;
            float          weight       = 0;
            float *        pWeights     = null;
            Vector3 *      pVert        = null;
            ushort *       pVInd        = (ushort *)manager._faceData[0].Address;
            List <Vertex3> vertList     = new List <Vertex3>(skin._weightCount);
            Matrix *       pMatrix      = null;

            UnsafeBuffer remap  = new UnsafeBuffer(skin._weightCount * 2);
            ushort *     pRemap = (ushort *)remap.Address;

            manager._vertices = vertList;

            //Find vertex source
            foreach (SourceEntry s in geo._sources)
            {
                if (s._id == geo._verticesInput._source)
                {
                    pVert = (Vector3 *)((UnsafeBuffer)s._arrayData).Address;
                    break;
                }
            }

            //Find joint source
            foreach (InputEntry inp in skin._jointInputs)
            {
                if (inp._semantic == SemanticType.JOINT)
                {
                    foreach (SourceEntry src in skin._sources)
                    {
                        if (src._id == inp._source)
                        {
                            jointStrings = src._arrayData as string[];
                            break;
                        }
                    }
                }
                else if (inp._semantic == SemanticType.INV_BIND_MATRIX)
                {
                    foreach (SourceEntry src in skin._sources)
                    {
                        if (src._id == inp._source)
                        {
                            pMatrix = (Matrix *)((UnsafeBuffer)src._arrayData).Address;
                            break;
                        }
                    }
                }
            }

            //Populate bone list
            boneCount = jointStrings.Length;
            boneList  = new MDL0BoneNode[boneCount];
            for (int i = 0; i < boneCount; i++)
            {
                boneList[i] = scene.FindNode(jointStrings[i])._node as MDL0BoneNode;
            }

            //Build command list
            foreach (InputEntry inp in skin._weightInputs)
            {
                switch (inp._semantic)
                {
                case SemanticType.JOINT:
                    pCmd[inp._offset] = 1;
                    break;

                case SemanticType.WEIGHT:
                    pCmd[inp._offset] = 2;

                    //Get weight source
                    foreach (SourceEntry src in skin._sources)
                    {
                        if (src._id == inp._source)
                        {
                            pWeights = (float *)((UnsafeBuffer)src._arrayData).Address;
                            break;
                        }
                    }

                    break;

                default:
                    pCmd[inp._offset] = 0;
                    break;
                }
            }

            //Build vertex list and remap table
            for (int i = 0; i < skin._weightCount; i++)
            {
                //Create influence
                int       iCount = skin._weights[i].Length / cmdCount;
                Influence inf    = new Influence(iCount);
                fixed(int *p = skin._weights[i])
                {
                    int *iPtr = p;

                    for (int x = 0; x < iCount; x++)
                    {
                        for (int z = 0; z < cmdCount; z++, iPtr++)
                        {
                            if (pCmd[z] == 1)
                            {
                                bone = boneList[*iPtr];
                            }
                            else if (pCmd[z] == 2)
                            {
                                weight = pWeights[*iPtr];
                            }
                        }

                        inf._weights[x] = new BoneWeight(bone, weight);
                    }
                }

                Vertex3 v;
                if (inf._weights.Length > 1)
                {
                    //Match with manager
                    inf = infManager.AddOrCreate(inf);
                    v   = new Vertex3(skin._bindMatrix * pVert[i], inf); //World position
                }
                else
                {
                    bone = inf._weights[0].Bone;
                    v    = new Vertex3(bone._inverseBindMatrix * skin._bindMatrix * pVert[i], bone); //Local position
                }

                //Create Vertex, set to world position.
                //Vertex3 v = new Vertex3(skin._bindMatrix * pVert[i], inf);

                //Fix single-bind vertices
                //if (inf._weights.Length == 1)
                //    v.Position = inf._weights[0].Bone._inverseBindMatrix * v.Position;

                ushort index = 0;
                while (index < vertList.Count)
                {
                    if (v.Equals(vertList[index]))
                    {
                        break;
                    }
                    index++;
                }
                if (index == vertList.Count)
                {
                    vertList.Add(v);
                }

                pRemap[i] = index;
            }

            //Remap vertex indices
            for (int i = 0; i < manager._pointCount; i++, pVInd++)
            {
                *pVInd = pRemap[*pVInd];
            }

            remap.Dispose();

            return(manager);
        }
        private void CreateObject(InstanceEntry inst, NodeEntry node, ResourceNode parent, PrimitiveManager manager, MDL0Node model, DecoderShell shell)
        {
            if (manager != null)
            {
                Error = "There was a problem creating a new object for " + (node._name != null ? node._name : node._id);
                int i = 0;
                foreach (Vertex3 v in manager._vertices)
                    v._index = i++;

                MDL0ObjectNode poly = new MDL0ObjectNode() { _manager = manager };
                poly._manager._polygon = poly;
                poly._name = node._name != null ? node._name : node._id;

                //Attach single-bind
                if (parent != null && parent is MDL0BoneNode)
                    poly.MatrixNode = (MDL0BoneNode)parent;

                //Attach material
                if (inst._material != null)
                    foreach (MaterialEntry mat in shell._materials)
                        if (mat._id == inst._material._target)
                        {
                            (poly._opaMaterial = (mat._node as MDL0MaterialNode))._objects.Add(poly);
                            break;
                        }

                model._numFaces += poly._numFaces = manager._faceCount = manager._pointCount / 3;
                model._numFacepoints += poly._numFacepoints = manager._pointCount;

                poly._parent = model._objGroup;
                model._objList.Add(poly);
            }
        }
        //private static void WriteTriFan(StreamWriter writer, Primitive p)
        //{
        //    if ((p._vertexIndices == null) || (p._normalIndices == null))
        //        return;
        //    writer.WriteLine();
        //    writer.WriteLine("#Trifan");
        //    int count = p._elementCount - 2;
        //    if (p._uvIndices[0] != null)
        //        for (int i = 0; i < count; i++)
        //            writer.WriteLine(String.Format("f {0}/{1}/{2} {3}/{4}/{5} {6}/{7}/{8}",
        //                p._vertexIndices[0] + 1, p._uvIndices[0][0] + 1, p._normalIndices[0] + 1,
        //                p._vertexIndices[i + 1] + 1, p._uvIndices[0][i + 1] + 1, p._normalIndices[i + 1] + 1,
        //                p._vertexIndices[i + 2] + 1, p._uvIndices[0][i + 2] + 1, p._normalIndices[i + 2] + 1));
        //    else
        //        for (int i = 0; i < count; i++)
        //            writer.WriteLine(String.Format("f {0}//{1} {2}//{3} {4}//{5}",
        //                    p._vertexIndices[0] + 1, p._normalIndices[0] + 1,
        //                    p._vertexIndices[i + 1] + 1, p._normalIndices[i + 1] + 1,
        //                    p._vertexIndices[i + 2] + 1, p._normalIndices[i + 2] + 1));
        //}
        //private static void WriteTriStrip(StreamWriter writer, Primitive p)
        //{
        //    if ((p._vertexIndices == null) || (p._normalIndices == null))
        //        return;
        //    writer.WriteLine();
        //    writer.WriteLine("#Tristrip");
        //    int count = p._elementCount - 2;
        //    int l1 = 0, l2 = 2;
        //    if (p._uvIndices[0] != null)
        //        for (int i = 0; i < count; i++)
        //        {
        //            if ((i & 1) == 0)
        //            {
        //                l1 = i;
        //                l2 = i + 1;
        //            }
        //            else
        //            {
        //                l1 = i + 1;
        //                l2 = i;
        //            }
        //            writer.WriteLine(String.Format("f {0}/{1}/{2} {3}/{4}/{5} {6}/{7}/{8}",
        //                p._vertexIndices[l1] + 1, p._uvIndices[0][l1] + 1, p._normalIndices[l1] + 1,
        //                p._vertexIndices[l2] + 1, p._uvIndices[0][l2] + 1, p._normalIndices[l2] + 1,
        //                p._vertexIndices[i + 2] + 1, p._uvIndices[0][i + 2] + 1, p._normalIndices[i + 2] + 1));
        //        }
        //    else
        //        for (int i = 0; i < count; i++)
        //        {
        //            if ((i & 1) == 0)
        //            {
        //                l1 = i;
        //                l2 = i + 1;
        //            }
        //            else
        //            {
        //                l1 = i + 1;
        //                l2 = i;
        //            }
        //            writer.WriteLine(String.Format("f {0}//{1} {2}//{3} {4}//{5}",
        //                    p._vertexIndices[l1] + 1, p._normalIndices[l1] + 1,
        //                    p._vertexIndices[l2] + 1, p._normalIndices[l2] + 1,
        //                    p._vertexIndices[i + 2] + 1, p._normalIndices[i + 2] + 1));
        //        }
        //}
        //private static void WriteTriList(StreamWriter writer, Primitive p)
        //{
        //    if ((p._vertexIndices == null) || (p._normalIndices == null))
        //        return;
        //    writer.WriteLine();
        //    writer.WriteLine("#Trilist");
        //    int count = p._elementCount / 3;
        //    if (p._uvIndices[0] != null)
        //        for (int i = 0, x = 0; i < count; i++, x += 3)
        //            writer.WriteLine(String.Format("f {0}/{1}/{2} {3}/{4}/{5} {6}/{7}/{8}",
        //                p._vertexIndices[x] + 1, p._uvIndices[0][x] + 1, p._normalIndices[x] + 1,
        //                p._vertexIndices[x + 1] + 1, p._uvIndices[0][x + 1] + 1, p._normalIndices[x + 1] + 1,
        //                p._vertexIndices[x + 2] + 1, p._uvIndices[0][x + 2] + 1, p._normalIndices[x + 2] + 1));
        //    else
        //        for (int i = 0, x = 0; i < count; i++, x += 3)
        //            writer.WriteLine(String.Format("f {0}//{1} {2}//{3} {4}//{5}",
        //                p._vertexIndices[x] + 1, p._normalIndices[x] + 1,
        //                p._vertexIndices[x + 1] + 1, p._normalIndices[x + 1] + 1,
        //                p._vertexIndices[x + 2] + 1, p._normalIndices[x + 2] + 1));
        //}
        private static unsafe void WriteTriList(StreamWriter writer, PrimitiveManager p)
        {
            uint[] pData = p._triangles._indices;
            uint x = 0;

            ushort* pVert = (ushort*)p._indices.Address;

            bool hasUVs = p._faceData[4] != null;
            bool hasNorms = p._faceData[1] != null;

            writer.WriteLine();
            writer.WriteLine("#Trilist");

            int count = p._triangles._elementCount / 3;

            //Loop through triangles
            for (int tri = 0; tri < count; tri++)
            {
                //writer.WriteLine("s " + i); //Smoothing groups don't seem to do anything
                writer.Write("f "); //Face

                //Loop through triangle points
                for (int pt = 0; pt < 3; pt++)
                {
                    uint index = pData[x++];

                    //Loop through vertices, uvs, normals
                    for (int asset = 0; asset < 3; asset++)
                    {
                        if (asset != 0) //Not a point start
                            writer.Write("/"); //Asset divider

                        //If no UVs, there's a double slash
                        if (!hasUVs && asset == 1)
                            continue;

                        if (asset == 0) //Vertex index
                            writer.Write((pVert[index] + 1).ToString());
                        else
                            writer.Write((index + 1).ToString());

                        if (asset == 2) //Point is done
                            if (pt == 2) //Last point
                                writer.WriteLine();
                            else //Still more points to go
                                writer.Write(" ");
                    }
                }
            }
        }
Beispiel #15
0
        static void Weight(PrimitiveManager manager, SkinEntry skin, DecoderShell shell, GeometryEntry geo, InfluenceManager iMan)
        {
            MDL0BoneNode[] boneList;
            MDL0BoneNode   bone = null;
            int            boneCount;

            string[]       jointStrings = null;
            byte *         pCmd         = stackalloc byte[4];
            int            cmdCount     = skin._weightInputs.Count;
            float          weight       = 0;
            float *        pWeights     = null;
            Vector3 *      pVert        = null;
            ushort *       pVInd        = (ushort *)manager._indices.Address;
            List <Vertex3> vertList     = new List <Vertex3>(skin._weightCount);

            manager._vertices = vertList;

            //Find vertex source
            foreach (SourceEntry s in geo._sources)
            {
                if (s._id == geo._verticesInput._source)
                {
                    pVert = (Vector3 *)((UnsafeBuffer)s._arrayData).Address;
                    break;
                }
            }

            //Find joint source
            foreach (InputEntry inp in skin._jointInputs)
            {
                if (inp._semantic == SemanticType.JOINT)
                {
                    foreach (SourceEntry src in skin._sources)
                    {
                        if (src._id == inp._source)
                        {
                            jointStrings = src._arrayData as string[];
                            break;
                        }
                    }
                    break;
                }
            }

            //Populate bone list
            boneCount = jointStrings.Length;
            boneList  = new MDL0BoneNode[boneCount];
            for (int i = 0; i < boneCount; i++)
            {
                boneList[i] = shell.FindNode(jointStrings[i])._node as MDL0BoneNode;
            }

            //Build command list
            foreach (InputEntry inp in skin._weightInputs)
            {
                switch (inp._semantic)
                {
                case SemanticType.JOINT:
                    pCmd[inp._offset] = 1;
                    break;

                case SemanticType.WEIGHT:
                    pCmd[inp._offset] = 2;

                    //Get weight source
                    foreach (SourceEntry src in skin._sources)
                    {
                        if (src._id == inp._source)
                        {
                            pWeights = (float *)((UnsafeBuffer)src._arrayData).Address;
                            break;
                        }
                    }

                    break;

                default:
                    pCmd[inp._offset] = 0;
                    break;
                }
            }

            //Construct Vertex from new weight
            for (int i = 0; i < skin._weightCount; i++)
            {
                //Create influence
                int       iCount = skin._weights.Length / cmdCount;
                Influence inf    = new Influence(iCount);
                fixed(int *p = skin._weights[i])
                {
                    int *iPtr = p;

                    for (int x = 0; x < iCount; x++)
                    {
                        for (int z = 0; z < cmdCount; z++, iPtr++)
                        {
                            if (pCmd[z] == 1)
                            {
                                bone = boneList[*iPtr];
                            }
                            else if (pCmd[z] == 2)
                            {
                                weight = pWeights[*iPtr];
                            }
                        }

                        inf._weights[x] = new BoneWeight(bone, weight);
                    }
                }

                //Match with manager
                inf = iMan.AddOrCreateInf(inf);

                //Create Vertex and look for match
                Vertex3 v     = new Vertex3(pVert[*pVInd], inf);
                int     index = 0;
                while (index < vertList.Count)
                {
                    if (v.Equals(vertList[i]))
                    {
                        break;
                    }
                    index++;
                }
                if (index == vertList.Count)
                {
                    vertList.Add(v);
                }

                //Assign new index
                *pVInd++ = (ushort)index;
            }
        }
Beispiel #16
0
        private static PrimitiveManager DecodePrimitives(GeometryEntry geo)
        {
            uint[] pTriarr = null, pLinarr = null;
            uint   pTri = 0, pLin = 0;
            long * pInDataList = stackalloc long[12];
            long * pOutDataList = stackalloc long[12];
            int *  pData = stackalloc int[16];
            int    faces = 0, lines = 0, points = 0;
            uint   fIndex = 0, lIndex = 0, temp;

            PrimitiveDecodeCommand *pCmd = (PrimitiveDecodeCommand *)pData;
            byte **pInData               = (byte **)pInDataList;
            byte **pOutData              = (byte **)pOutDataList;

            PrimitiveManager manager = new PrimitiveManager();

            //Assign vertex source
            foreach (SourceEntry s in geo._sources)
            {
                if (s._id == geo._verticesInput._source)
                {
                    pInData[0] = (byte *)((UnsafeBuffer)s._arrayData).Address;
                    break;
                }
            }

            foreach (PrimitiveEntry prim in geo._primitives)
            {
                //Get face/line count
                if (prim._type == ColladaPrimitiveType.lines || prim._type == ColladaPrimitiveType.linestrips)
                {
                    lines += prim._faceCount;
                }
                else
                {
                    faces += prim._faceCount;
                }

                //Get point total
                points += prim._pointCount;

                //Signal storage buffers and set type offsets
                foreach (InputEntry inp in prim._inputs)
                {
                    int offset = -1;

                    switch (inp._semantic)
                    {
                    case SemanticType.VERTEX:
                        offset = 0;
                        break;

                    case SemanticType.NORMAL:
                        offset = 1;
                        break;

                    case SemanticType.COLOR:
                        if (inp._set < 2)
                        {
                            offset = 2 + inp._set;
                        }

                        break;

                    case SemanticType.TEXCOORD:
                        if (inp._set < 8)
                        {
                            offset = 4 + inp._set;
                        }

                        break;
                    }

                    if (offset != -1)
                    {
                        manager._dirty[offset] = true;
                    }

                    inp._outputOffset = offset;
                }
            }

            manager._pointCount = points;

            //Create primitives
            if (faces > 0)
            {
                manager._triangles = new GLPrimitive(faces * 3, OpenTK.Graphics.OpenGL.PrimitiveType.Triangles);
                pTriarr            = manager._triangles._indices;
            }

            if (lines > 0)
            {
                manager._lines = new GLPrimitive(lines * 2, OpenTK.Graphics.OpenGL.PrimitiveType.Lines);
                pLinarr        = manager._lines._indices;
            }

            manager._indices = new UnsafeBuffer(points * 2);
            //Create face buffers and assign output pointers
            for (int i = 0; i < 12; i++)
            {
                if (manager._dirty[i])
                {
                    int stride;
                    if (i == 0)
                    {
                        stride = 2;
                    }
                    else if (i == 1)
                    {
                        stride = 12;
                    }
                    else if (i < 4)
                    {
                        stride = 4;
                    }
                    else
                    {
                        stride = 8;
                    }

                    manager._faceData[i] = new UnsafeBuffer(points * stride);
                    if (i == 0)
                    {
                        pOutData[i] = (byte *)manager._indices.Address;
                    }
                    else
                    {
                        pOutData[i] = (byte *)manager._faceData[i].Address;
                    }
                }
            }

            //Decode primitives
            foreach (PrimitiveEntry prim in geo._primitives)
            {
                int count = prim._inputs.Count;
                //Map inputs to command sequence
                foreach (InputEntry inp in prim._inputs)
                {
                    if (inp._outputOffset == -1)
                    {
                        pCmd[inp._offset].Cmd = 0;
                    }
                    else
                    {
                        pCmd[inp._offset].Cmd   = (byte)inp._semantic;
                        pCmd[inp._offset].Index = (byte)inp._outputOffset;

                        //Assign input buffer
                        foreach (SourceEntry src in geo._sources)
                        {
                            if (src._id == inp._source)
                            {
                                pInData[inp._outputOffset] = (byte *)((UnsafeBuffer)src._arrayData).Address;
                                break;
                            }
                        }
                    }
                }

                //Decode face data using command list
                foreach (PrimitiveFace f in prim._faces)
                {
                    fixed(ushort *p = f._pointIndices)
                    {
                        RunPrimitiveCmd(pInData, pOutData, pCmd, count, p, f._pointCount);
                    }
                }

                //Process point indices
                switch (prim._type)
                {
                case ColladaPrimitiveType.triangles:
                    count = prim._faceCount * 3;
                    while (count-- > 0)
                    {
                        pTriarr[pTri++] = fIndex++;
                    }

                    break;

                case ColladaPrimitiveType.trifans:
                case ColladaPrimitiveType.polygons:
                case ColladaPrimitiveType.polylist:
                    foreach (PrimitiveFace f in prim._faces)
                    {
                        count   = f._pointCount - 2;
                        temp    = fIndex;
                        fIndex += 2;
                        while (count-- > 0)
                        {
                            pTriarr[pTri++] = temp;
                            pTriarr[pTri++] = fIndex - 1;
                            pTriarr[pTri++] = fIndex++;
                        }
                    }

                    break;

                case ColladaPrimitiveType.tristrips:
                    foreach (PrimitiveFace f in prim._faces)
                    {
                        count   = f._pointCount;
                        fIndex += 2;
                        for (int i = 2; i < count; i++)
                        {
                            if ((i & 1) == 0)
                            {
                                pTriarr[pTri++] = fIndex - 2;
                                pTriarr[pTri++] = fIndex - 1;
                                pTriarr[pTri++] = fIndex++;
                            }
                            else
                            {
                                pTriarr[pTri++] = fIndex - 2;
                                pTriarr[pTri++] = fIndex;
                                pTriarr[pTri++] = fIndex++ - 1;
                            }
                        }
                    }

                    break;

                case ColladaPrimitiveType.linestrips:
                    foreach (PrimitiveFace f in prim._faces)
                    {
                        count = f._pointCount - 1;
                        lIndex++;
                        while (count-- > 0)
                        {
                            pLinarr[pLin++] = lIndex - 1;
                            pLinarr[pLin++] = lIndex++;
                        }
                    }

                    break;

                case ColladaPrimitiveType.lines:
                    foreach (PrimitiveFace f in prim._faces)
                    {
                        count = f._pointCount;
                        while (count-- > 0)
                        {
                            pLinarr[pLin++] = lIndex++;
                        }
                    }

                    break;
                }
            }

            return(manager);
        }
        private static void WriteColors(string name, PrimitiveManager p, int set, XmlWriter writer)
        {
            bool first = true;

            _colors[set] = p.GetColors(set, true);
            int count = _colors[set].Length;
            _colorRemap[set] = new List<int>();
            RGBAPixel* ptr = (RGBAPixel*)p._faceData[set + 2].Address;
            for (int i = 0; i < p._pointCount; i++)
                _colorRemap[set].Add(Array.IndexOf(_colors[set], ptr[i]));

            //Position source
            writer.WriteStartElement("source");
            writer.WriteAttributeString("id", name + "_Colors" + set.ToString());

            //Array start
            writer.WriteStartElement("float_array");
            writer.WriteAttributeString("id", name + "_ColorArr" + set.ToString());
            writer.WriteAttributeString("count", (count * 4).ToString());

            for (int i = 0; i < count; i++)
            {
                if (first)
                    first = false;
                else
                    writer.WriteString(" ");

                RGBAPixel r = _colors[set][i];

                writer.WriteString(String.Format("{0} {1} {2} {3}", r.R * cFactor, r.G * cFactor, r.B * cFactor, r.A * cFactor));
            }

            writer.WriteEndElement(); //int_array

            //Technique
            writer.WriteStartElement("technique_common");

            writer.WriteStartElement("accessor");
            writer.WriteAttributeString("source", "#" + name + "_ColorArr" + set.ToString());
            writer.WriteAttributeString("count", count.ToString());
            writer.WriteAttributeString("stride", "4");

            writer.WriteStartElement("param");
            writer.WriteAttributeString("name", "R");
            writer.WriteAttributeString("type", "float");
            writer.WriteEndElement(); //param
            writer.WriteStartElement("param");
            writer.WriteAttributeString("name", "G");
            writer.WriteAttributeString("type", "float");
            writer.WriteEndElement(); //param
            writer.WriteStartElement("param");
            writer.WriteAttributeString("name", "B");
            writer.WriteAttributeString("type", "float");
            writer.WriteEndElement(); //param
            writer.WriteStartElement("param");
            writer.WriteAttributeString("name", "A");
            writer.WriteAttributeString("type", "float");
            writer.WriteEndElement(); //param

            writer.WriteEndElement(); //accessor
            writer.WriteEndElement(); //technique_common

            writer.WriteEndElement(); //source
        }
        public static unsafe void PMD2MDL0(MDL0Node model)
        {
            model._version = 9;
            model._isImport = true;
            Collada._importOptions = BrawlLib.Properties.Settings.Default.ColladaImportOptions;
            Collada._importOptions._forceCCW = true;
            Collada._importOptions._fltVerts = true;
            Collada._importOptions._fltNrms = true;
            Collada._importOptions._fltUVs = true;

            model.InitGroups();

            List<MDL0BoneNode> BoneCache = new List<MDL0BoneNode>();

            int index = 0;
            if (!String.IsNullOrWhiteSpace(_header._modelNameEnglish))
                model.Name = _header._modelNameEnglish;
            else
                model.Name = _header._modelName;

            if (!String.IsNullOrWhiteSpace(_header._commentEnglish))
                MessageBox.Show(_header._commentEnglish);
            else
                MessageBox.Show(_header._comment);

            ModelBone parent = null;
            foreach (ModelBone b in _bones)
            {
                MDL0BoneNode bone = new MDL0BoneNode();

                if (!String.IsNullOrWhiteSpace(b._boneNameEnglish))
                    bone._name = b._boneNameEnglish;
                else
                    bone._name = b._boneName;

                bone._entryIndex = index++;

                if (b._parentBoneIndex != ushort.MaxValue)
                {
                    parent = _bones[b._parentBoneIndex];
                    foreach (MDL0BoneNode v in model._boneGroup._children)
                        AssignParent(v, b, bone, parent);
                }
                else
                {
                    bone.Parent = model._boneGroup;
                    bone._bindState._scale = new Vector3(1.0f);
                    bone._bindState._translate = new Vector3(b._wPos[0], b._wPos[1], b._wPos[2]);
                    bone._bindState.CalcTransforms();
                    bone.RecalcBindState();
                }

                BoneCache.Add(bone);
            }

            MDL0ShaderNode texSpa = null, tex = null, colorSpa = null, color = null;

            index = 0;
            foreach (ModelMaterial m in _materials)
            {
                MDL0MaterialNode mn = new MDL0MaterialNode();
                mn.Name = "Material" + index++;

                MDL0MaterialRefNode texRef = null;
                MDL0MaterialRefNode spaRef = null;

                if (!String.IsNullOrEmpty(m._textureFileName))
                    if (m._textureFileName.Contains('*'))
                    {
                        string[] names = m._textureFileName.Split('*');
                        if (!String.IsNullOrEmpty(names[0]))
                        {
                            texRef = new MDL0MaterialRefNode();
                            texRef.Name = names[0].Substring(0, names[0].IndexOf('.'));
                        }
                        if (!String.IsNullOrEmpty(names[1]))
                        {
                            spaRef = new MDL0MaterialRefNode();
                            spaRef.Name = names[1].Substring(0, names[1].IndexOf('.'));
                            spaRef.MapMode = MDL0MaterialRefNode.MappingMethod.EnvCamera;
                            spaRef.UWrapMode = MDL0MaterialRefNode.WrapMode.Clamp;
                            spaRef.VWrapMode = MDL0MaterialRefNode.WrapMode.Clamp;
                            spaRef.Projection = Wii.Graphics.TexProjection.STQ;
                            spaRef.InputForm = Wii.Graphics.TexInputForm.ABC1;
                            spaRef.Coordinates = Wii.Graphics.TexSourceRow.Normals;
                            spaRef.Normalize = true;
                        }
                    }
                    else
                    {
                        texRef = new MDL0MaterialRefNode();
                        texRef.Name = m._textureFileName.Substring(0, m._textureFileName.IndexOf('.'));
                        texRef.Coordinates = Wii.Graphics.TexSourceRow.TexCoord0;
                    }

                if (texRef != null)
                {
                    (texRef._texture = model.FindOrCreateTexture(texRef.Name))._references.Add(texRef);
                    texRef._parent = mn;
                    mn._children.Add(texRef);
                }
                if (spaRef != null)
                {
                    (spaRef._texture = model.FindOrCreateTexture(spaRef.Name))._references.Add(spaRef);
                    spaRef._parent = mn;
                    mn._children.Add(spaRef);
                }

                mn._chan1._matColor = new RGBAPixel((byte)(m._diffuseColor[0] * 255), (byte)(m._diffuseColor[1] * 255), (byte)(m._diffuseColor[2] * 255), 255);
                mn._chan1.ColorMaterialSource = GXColorSrc.Register;

                if (texRef != null && spaRef != null)
                {
                    if (texSpa == null)
                    {
                        MDL0ShaderNode n = TexSpaShader;
                        n._parent = model._shadGroup;
                        model._shadList.Add(n);
                        texSpa = n;
                    }
                    mn.ShaderNode = texSpa;
                }
                else if (texRef != null)
                {
                    if (tex == null)
                    {
                        MDL0ShaderNode n = TexShader;
                        n._parent = model._shadGroup;
                        model._shadList.Add(n);
                        tex = n;
                    }
                    mn.ShaderNode = tex;
                }
                else if (spaRef != null)
                {
                    if (colorSpa == null)
                    {
                        MDL0ShaderNode n = ColorSpaShader;
                        n._parent = model._shadGroup;
                        model._shadList.Add(n);
                        colorSpa = n;
                    }
                    mn.ShaderNode = colorSpa;
                }
                else
                {
                    if (color == null)
                    {
                        MDL0ShaderNode n = ColorShader;
                        n._parent = model._shadGroup;
                        model._shadList.Add(n);
                        color = n;
                    }
                    mn.ShaderNode = color;
                }

                mn._parent = model._matGroup;
                model._matList.Add(mn);
            }

            model._numFaces = 0;
            model._numFacepoints = 0;

            int x = 0;
            int offset = 0;
            foreach (ModelMaterial m in _materials)
            {
                PrimitiveManager manager = new PrimitiveManager() { _pointCount = (int)m._faceVertCount };
                MDL0ObjectNode p = new MDL0ObjectNode() { _manager = manager, _opaMaterial = (MDL0MaterialNode)model._matList[x] };
                p._opaMaterial._objects.Add(p);
                p._manager._vertices = new List<Vertex3>();
                p.Name = "polygon" + x++;
                p._parent = model._objGroup;

                model._numFaces += p._numFaces = manager._faceCount = manager._pointCount / 3;
                model._numFacepoints += p._numFacepoints = manager._pointCount;

                p._manager._indices = new UnsafeBuffer((int)m._faceVertCount * 2);
                p._manager._faceData[0] = new UnsafeBuffer((int)m._faceVertCount * 12);
                p._manager._faceData[1] = new UnsafeBuffer((int)m._faceVertCount * 12);
                p._manager._faceData[4] = new UnsafeBuffer((int)m._faceVertCount * 8);

                p._manager._dirty[0] = true;
                p._manager._dirty[1] = true;
                p._manager._dirty[4] = true;

                ushort* Indices = (ushort*)p._manager._indices.Address;
                Vector3* Vertices = (Vector3*)p._manager._faceData[0].Address;
                Vector3* Normals = (Vector3*)p._manager._faceData[1].Address;
                Vector2* UVs = (Vector2*)p._manager._faceData[4].Address;

                manager._triangles = new NewPrimitive((int)m._faceVertCount, BeginMode.Triangles);
                uint[] pTriarr = manager._triangles._indices;
                uint pTri = 0;

                index = 0;
                List<int> usedVertices = new List<int>();
                List<int> vertexIndices = new List<int>();
                for (int s = offset, l = 0; l < (int)m._faceVertCount; l++, s++)
                {
                    ushort i = _faceIndices[s];
                    ModelVertex mv = _vertices[i];
                    ushort j = 0;
                    if (!usedVertices.Contains(i))
                    {
                        Influence inf;
                        BoneWeight weight1 = null, weight2 = null;

                        float weight = ((float)mv._boneWeight / 100.0f).Clamp(0.0f, 1.0f);

                        if (weight > 0.0f && weight < 1.0f)
                        {
                            weight1 = new BoneWeight(BoneCache[mv._boneIndex[0]], weight);
                            weight2 = new BoneWeight(BoneCache[mv._boneIndex[1]], 1.0f - weight);
                        }
                        else if (weight == 0.0f)
                            weight1 = new BoneWeight(BoneCache[mv._boneIndex[1]]);
                        else
                            weight1 = new BoneWeight(BoneCache[mv._boneIndex[0]]);

                        if (weight2 != null)
                            inf = new Influence(new List<BoneWeight> { weight1, weight2 });
                        else
                            inf = new Influence(new List<BoneWeight> { weight1 });

                        Vector3 t = new Vector3();
                        Vertex3 v;
                        t._x = mv._position[0];
                        t._y = mv._position[1];
                        t._z = mv._position[2];
                        if (inf._weights.Count > 1)
                        {
                            inf = model._influences.FindOrCreate(inf, true);
                            inf.CalcMatrix();
                            v = new Vertex3(t, inf);
                        }
                        else
                        {
                            MDL0BoneNode bone = inf._weights[0].Bone;
                            v = new Vertex3(t * bone._inverseBindMatrix, bone);
                        }

                        p._manager._vertices.Add(v);
                        vertexIndices.Add(usedVertices.Count);
                        usedVertices.Add(i);
                        j = (ushort)(usedVertices.Count - 1);
                    }
                    else
                        j = (ushort)vertexIndices[usedVertices.IndexOf(i)];

                    *Indices++ = j;
                    pTriarr[pTri++] = (uint)l;
                    *Vertices++ = p._manager._vertices[j]._position;
                    *Normals++ = mv._normal;
                    *UVs++ = mv._texCoord;
                }
                model._objList.Add(p);
                offset += (int)m._faceVertCount;
            }

            //Check each polygon to see if it can be rigged to a single influence
            if (model._objList != null && model._objList.Count != 0)
                foreach (MDL0ObjectNode p in model._objList)
                {
                    IMatrixNode node = null;
                    bool singlebind = true;

                    foreach (Vertex3 v in p._manager._vertices)
                        if (v._matrixNode != null)
                        {
                            if (node == null)
                                node = v._matrixNode;

                            if (v._matrixNode != node)
                            {
                                singlebind = false;
                                break;
                            }
                        }

                    if (singlebind && p._matrixNode == null)
                    {
                        //Increase reference count ahead of time for rebuild
                        if (p._manager._vertices[0]._matrixNode != null)
                            p._manager._vertices[0]._matrixNode.ReferenceCount++;

                        foreach (Vertex3 v in p._manager._vertices)
                            if (v._matrixNode != null)
                                v._matrixNode.ReferenceCount--;

                        p._nodeId = -2; //Continued on polygon rebuild
                    }
                }

            //foreach (MDL0ObjectNode p in model._objList)
            //    foreach (MDL0MaterialNode m in model._matList)
            //    {
            //        MDL0MaterialNode m2 = p.OpaMaterialNode;

            //        if (m2 == null || m2.ShaderNode != m.ShaderNode || m2.Children.Count != m.Children.Count)
            //            continue;

            //        for (int i = 0; i < m.Children.Count; i++)
            //            if (m2.Children[i].Name != m.Children[i].Name)
            //                continue;

            //        p.OpaMaterialNode = m;
            //        break;
            //    }
            //for (int i = 0; i < model._matList.Count; i++)
            //    if (((MDL0MaterialNode)model._matList[i])._objects.Count == 0)
            //        model._matList.RemoveAt(i--);

            model.CleanGroups();
            model.BuildFromScratch(null);
        }
Beispiel #19
0
        private static unsafe void WriteGeometry(MDL0Node model, XmlWriter writer, bool weightNorms)
        {
            ResourceNode grp = model._polyGroup;

            if (grp == null)
            {
                return;
            }

            writer.WriteStartElement("library_geometries");

            foreach (MDL0PolygonNode poly in grp.Children)
            {
                PrimitiveManager manager = poly._manager;

                //Geometry
                writer.WriteStartElement("geometry");
                writer.WriteAttributeString("id", poly.Name);
                writer.WriteAttributeString("name", poly.Name);

                //Mesh
                writer.WriteStartElement("mesh");

                //Write vertex data first
                WriteVertices(poly._name, manager._vertices, writer);

                //Face assets
                for (int i = 0; i < 12; i++)
                {
                    if (manager._faceData[i] == null)
                    {
                        continue;
                    }

                    switch (i)
                    {
                    case 0:
                        break;

                    case 1:
                        WriteNormals(poly._name, (Vector3 *)manager._faceData[i].Address, manager._pointCount, writer, weightNorms, manager);
                        break;

                    case 2:
                    case 3:
                        WriteColors(poly._name, (RGBAPixel *)manager._faceData[i].Address, manager._pointCount, i - 2, writer);
                        break;

                    default:
                        WriteUVs(poly._name, (Vector2 *)manager._faceData[i].Address, manager._pointCount, i - 4, writer);
                        break;
                    }
                }

                //Vertices
                writer.WriteStartElement("vertices");
                writer.WriteAttributeString("id", poly.Name + "_Vertices");
                writer.WriteStartElement("input");
                writer.WriteAttributeString("semantic", "POSITION");
                writer.WriteAttributeString("source", "#" + poly.Name + "_Positions");
                writer.WriteEndElement(); //input
                writer.WriteEndElement(); //vertices

                //Faces
                if (manager._triangles != null)
                {
                    WritePrimitive(poly, manager._triangles, writer);
                }
                if (manager._lines != null)
                {
                    WritePrimitive(poly, manager._lines, writer);
                }
                if (manager._points != null)
                {
                    WritePrimitive(poly, manager._points, writer);
                }

                //Write primitives
                //WritePrimitiveType(poly, GLPrimitiveType.Lines, writer);
                //WritePrimitiveType(poly, GLPrimitiveType.LineStrip, writer);
                //WritePrimitiveType(poly, GLPrimitiveType.Triangles, writer);
                //WritePrimitiveType(poly, GLPrimitiveType.TriangleFan, writer);
                //WritePrimitiveType(poly, GLPrimitiveType.TriangleStrip, writer);

                writer.WriteEndElement(); //mesh
                writer.WriteEndElement(); //geometry
            }

            writer.WriteEndElement();
        }
        private static void CreateMDL0Object(
            InstanceEntry inst,
            NodeEntry node,
            ResourceNode parent,
            PrimitiveManager manager,
            MDL0Node model,
            DecoderShell shell)
        {
            if (manager != null)
            {
                Error = "There was a problem creating a new object for " + (node._name != null ? node._name : node._id);

                MDL0ObjectNode poly = new MDL0ObjectNode()
                {
                    _manager   = manager,
                    _name      = node._name != null ? node._name : node._id,
                    _drawCalls = new BindingList <DrawCall>()
                };

                //Attach material
                if (inst._material != null)
                {
                    foreach (MaterialEntry mat in shell._materials)
                    {
                        if (mat._id == inst._material._target)
                        {
                            poly._drawCalls.Add(new DrawCall(poly)
                            {
                                MaterialNode = mat._node as MDL0MaterialNode
                            });
                        }
                    }
                }

                model._numTriangles  += poly._numFaces = manager._faceCount = manager._pointCount / 3;
                model._numFacepoints += poly._numFacepoints = manager._pointCount;

                poly._parent = model._objGroup;
                model._objList.Add(poly);

                model.ResetToBindState();

                //Attach single-bind
                if (parent != null && parent is MDL0BoneNode)
                {
                    MDL0BoneNode bone = (MDL0BoneNode)parent;
                    poly.DeferUpdateAssets();
                    poly.MatrixNode = bone;

                    foreach (DrawCall c in poly._drawCalls)
                    {
                        c.VisibilityBoneNode = bone;
                    }
                }
                else if (model._boneList.Count == 0)
                {
                    Error = String.Format("There was a problem rigging {0} to a single bone.", poly._name);

                    Box          box  = poly.GetBox();
                    MDL0BoneNode bone = new MDL0BoneNode()
                    {
                        Scale       = Vector3.One,
                        Translation = (box.Max + box.Min) / 2.0f,
                        _name       = "TransN_" + poly.Name,
                        Parent      = TempRootBone,
                    };

                    poly.DeferUpdateAssets();
                    poly.MatrixNode = bone;
                    ((MDL0BoneNode)TempRootBone).RecalcBindState(true, false, false);

                    foreach (DrawCall c in poly._drawCalls)
                    {
                        c.VisibilityBoneNode = bone;
                    }
                }
                else
                {
                    Error = String.Format("There was a problem checking if {0} is rigged to a single bone.", poly._name);

                    foreach (DrawCall c in poly._drawCalls)
                    {
                        c.VisibilityBoneNode = model._boneList[0] as MDL0BoneNode;
                    }

                    IMatrixNode mtxNode    = null;
                    bool        singlebind = true;

                    foreach (Vertex3 v in poly._manager._vertices)
                    {
                        if (v.MatrixNode != null)
                        {
                            if (mtxNode == null)
                            {
                                mtxNode = v.MatrixNode;
                            }

                            if (v.MatrixNode != mtxNode)
                            {
                                singlebind = false;
                                break;
                            }
                        }
                    }

                    if (singlebind && poly._matrixNode == null)
                    {
                        //Reassign reference entries
                        if (poly._manager._vertices[0].MatrixNode != null)
                        {
                            poly._manager._vertices[0].MatrixNode.Users.Add(poly);
                        }

                        foreach (Vertex3 v in poly._manager._vertices)
                        {
                            if (v.MatrixNode != null)
                            {
                                v.MatrixNode.Users.Remove(v);
                            }
                        }

                        poly._nodeId = -2; //Continued on polygon rebuild
                    }
                }
            }
        }
Beispiel #21
0
        private static void WriteNormals(string name, Vector3 *pData, int count, XmlWriter writer, bool weight, PrimitiveManager p)
        {
            bool    first  = true;
            ushort *pIndex = (ushort *)p._indices.Address;
            Vector3 v;

            //Position source
            writer.WriteStartElement("source");
            writer.WriteAttributeString("id", name + "_Normals");

            //Array start
            writer.WriteStartElement("float_array");
            writer.WriteAttributeString("id", name + "_NormArr");
            writer.WriteAttributeString("count", (count * 3).ToString());

            for (int i = 0; i < count; i++)
            {
                if (first)
                {
                    first = false;
                }
                else
                {
                    writer.WriteString(" ");
                }

                if (weight && p._vertices[*pIndex]._influence != null)
                {
                    v = p._vertices[*pIndex++]._influence.Matrix.GetRotationMatrix() * *pData++;
                }
                else
                {
                    v = *pData++;
                }

                writer.WriteString(String.Format("{0} {1} {2}", v._x, v._y, v._z));
            }

            writer.WriteEndElement(); //float_array

            //Technique
            writer.WriteStartElement("technique_common");

            writer.WriteStartElement("accessor");
            writer.WriteAttributeString("source", "#" + name + "_NormArr");
            writer.WriteAttributeString("count", count.ToString());
            writer.WriteAttributeString("stride", "3");

            writer.WriteStartElement("param");
            writer.WriteAttributeString("name", "X");
            writer.WriteAttributeString("type", "float");
            writer.WriteEndElement(); //param
            writer.WriteStartElement("param");
            writer.WriteAttributeString("name", "Y");
            writer.WriteAttributeString("type", "float");
            writer.WriteEndElement(); //param
            writer.WriteStartElement("param");
            writer.WriteAttributeString("name", "Z");
            writer.WriteAttributeString("type", "float");
            writer.WriteEndElement(); //param

            writer.WriteEndElement(); //accessor
            writer.WriteEndElement(); //technique_common

            writer.WriteEndElement(); //source
        }
Beispiel #22
0
        private static unsafe void WritePrimitive(MDL0PolygonNode poly, NewPrimitive prim, XmlWriter writer)
        {
            PrimitiveManager manager = poly._manager;
            int     count;
            int     elements = 0, stride = 0;
            int     set;
            bool    first;
            ushort *pData = (ushort *)prim._indices.Address;
            ushort *pVert = (ushort *)poly._manager._indices.Address;

            switch (prim._type)
            {
            case GLPrimitiveType.Triangles:
                writer.WriteStartElement("triangles");
                stride = 3;
                break;

            case GLPrimitiveType.Lines:
                writer.WriteStartElement("lines");
                stride = 2;
                break;

            case GLPrimitiveType.Points:
                writer.WriteStartElement("points");
                stride = 1;
                break;
            }
            count = prim._elementCount / stride;

            if (poly._material != null)
            {
                writer.WriteAttributeString("material", poly._material.Name);
            }

            writer.WriteAttributeString("count", count.ToString());

            for (int i = 0; i < 12; i++)
            {
                if (manager._faceData[i] == null)
                {
                    continue;
                }

                writer.WriteStartElement("input");

                switch (i)
                {
                case 0:
                    writer.WriteAttributeString("semantic", "VERTEX");
                    writer.WriteAttributeString("source", "#" + poly._name + "_Vertices");
                    break;

                case 1:
                    writer.WriteAttributeString("semantic", "NORMAL");
                    writer.WriteAttributeString("source", "#" + poly._name + "_Normals");
                    break;

                case 2:
                case 3:
                    set = i - 2;
                    writer.WriteAttributeString("semantic", "COLOR");
                    writer.WriteAttributeString("source", "#" + poly._name + "_Colors" + set.ToString());
                    writer.WriteAttributeString("set", set.ToString());
                    break;

                default:
                    set = i - 4;
                    writer.WriteAttributeString("semantic", "TEXCOORD");
                    writer.WriteAttributeString("source", "#" + poly._name + "_UVs" + set.ToString());
                    writer.WriteAttributeString("set", set.ToString());
                    break;
                }

                writer.WriteAttributeString("offset", elements.ToString());
                writer.WriteEndElement(); //input

                elements++;
            }

            for (int i = 0; i < count; i++)
            {
                writer.WriteStartElement("p");
                first = true;
                for (int x = 0; x < stride; x++)
                {
                    int index = *pData++;
                    for (int y = 0; y < elements; y++)
                    {
                        if (first)
                        {
                            first = false;
                        }
                        else
                        {
                            writer.WriteString(" ");
                        }

                        if (y == 0)
                        {
                            writer.WriteString(pVert[index].ToString());
                        }
                        else
                        {
                            writer.WriteString(index.ToString());
                        }
                    }
                }
                writer.WriteEndElement(); //p
            }

            writer.WriteEndElement(); //primitive
        }
        public override bool OnInitialize()
        {
            MDL0Object* header = Header;
            _nodeId = header->_nodeId;

            SetSizeInternal(_totalLength = header->_totalLength);
            _mdl0Offset = header->_mdl0Offset;
            _stringOffset = header->_stringOffset;

            ModelLinker linker = Model._linker;

            MatrixNode = (_nodeId >= 0 && _nodeId < Model._linker.NodeCache.Length) ? Model._linker.NodeCache[_nodeId] : null;

            _vertexFormat = header->_vertexFormat;
            _vertexSpecs = header->_vertexSpecs;
            _arrayFlags = header->_arrayFlags;

            HasPosMatrix = _arrayFlags.HasPosMatrix;
            for (int i = 0; i < 8; i++)
                HasTextureMatrix[i] = _arrayFlags.GetHasTexMatrix(i);

            _numFacepoints = header->_numVertices;
            _numFaces = header->_numFaces;

            _flag = header->_flag;

            _primBufferSize = header->_primitives._bufferSize;
            _primSize = header->_primitives._size;
            _primOffset = header->_primitives._offset;

            _defBufferSize = header->_defintions._bufferSize;
            _defSize = header->_defintions._size;
            _defOffset = header->_defintions._offset;

            _entryIndex = header->_index;

            //Conditional name assignment
            if ((_name == null) && (header->_stringOffset != 0))
                if (!_replaced)
                    _name = header->ResourceString;
                else
                    _name = "polygon" + Index;

            //Link nodes
            if (header->_vertexId >= 0 && Model._vertList != null)
                foreach (MDL0VertexNode v in Model._vertList)
                    if (header->_vertexId == v.ID)
                    {
                        (_vertexNode = v)._objects.Add(this);
                        break;
                    }

            if (header->_normalId >= 0 && Model._normList != null)
                foreach (MDL0NormalNode n in Model._normList)
                    if (header->_normalId == n.ID)
                    {
                        (_normalNode = n)._objects.Add(this);
                        break;
                    }

            int id;
            for (int i = 0; i < 2; i++)
                if ((id = ((bshort*)header->_colorIds)[i]) >= 0 && Model._colorList != null)
                    foreach (MDL0ColorNode c in Model._colorList)
                        if (id == c.ID)
                        {
                            (_colorSet[i] = c)._objects.Add(this);
                            break;
                        }

            for (int i = 0; i < 8; i++)
                if ((id = ((bshort*)header->_uids)[i]) >= 0 && Model._uvList != null)
                    foreach (MDL0UVNode u in Model._uvList)
                        if (id == u.ID)
                        {
                            (_uvSet[i] = u)._objects.Add(this);
                            break;
                        }

            if (Model._version > 9)
            {
                if (header->_furVectorId >= 0)
                    foreach (MDL0FurVecNode v in Model._furVecList)
                        if (header->_furVectorId == v.ID)
                        {
                            (_furVecNode = v)._objects.Add(this);
                            break;
                        }

                if (header->_furLayerCoordId >= 0)
                    foreach (MDL0FurPosNode n in Model._furPosList)
                        if (header->_furLayerCoordId == n.ID)
                        {
                            (_furPosNode = n)._objects.Add(this);
                            break;
                        }
            }

            //Link element indices for rebuild
            _elementIndices[0] = (short)(_vertexNode != null ? _vertexNode.Index : -1);
            _elementIndices[1] = (short)(_normalNode != null ? _normalNode.Index : -1);
            for (int i = 2; i < 4; i++)
                _elementIndices[i] = (short)(_colorSet[i - 2] != null ? _colorSet[i - 2].Index : -1);
            for (int i = 4; i < 12; i++)
                _elementIndices[i] = (short)(_uvSet[i - 4] != null ? _uvSet[i - 4].Index : -1);
            _elementIndices[12] = (short)(_furVecNode != null ? _furVecNode.Index : -1);
            _elementIndices[13] = (short)(_furPosNode != null ? _furPosNode.Index : -1);

            //Create primitive manager
            if (_parent != null)
            {
                int i = 0;
                _manager = new PrimitiveManager(header, Model._assets, linker.NodeCache, this);
                if (_manager._vertices != null)
                    foreach (Vertex3 v in _manager._vertices)
                    {
                        v._index = i++;
                        v._object = this;
                    }
            }

            //Get polygon UVAT groups
            MDL0PolygonDefs* Defs = (MDL0PolygonDefs*)header->DefList;
            UVATGroups = new CPElementSpec(
                (uint)Defs->UVATA,
                (uint)Defs->UVATB,
                (uint)Defs->UVATC);

            //Read internal object node cache and read influence list
            if (Model._linker.NodeCache != null)
            {
                if (_matrixNode == null)
                {
                    _influences = new List<IMatrixNode>();
                    bushort* weights = header->WeightIndices(Model._version);
                    int count = *(bint*)weights; weights += 2;
                    for (int i = 0; i < count; i++)
                        if (*weights < Model._linker.NodeCache.Length)
                            _influences.Add(Model._linker.NodeCache[*weights++]);
                        else
                            weights++;
                }
            }

            //Check for errors
            if (header->_totalLength % 0x20 != 0)
            {
                Model._errors.Add("Object " + Index + " has an improper data length.");
                SignalPropertyChange(); _rebuild = true;
            }
            if ((int)(0x24 + header->_primitives._offset) % 0x20 != 0)
            {
                Model._errors.Add("Object " + Index + " has an improper primitives start offset.");
                SignalPropertyChange(); _rebuild = true;
            }
            if (CheckVertexFormat())
            {
                Model._errors.Add("Object " + Index + " has a facepoint descriptor that does not match its linked nodes.");
                SignalPropertyChange(); _rebuild = true;

                for (int i = 0; i < 2; i++)
                    if (_colorSet[i] != null && _manager._faceData[i + 2] == null)
                    {
                        _manager._faceData[i + 2] = new UnsafeBuffer(_manager._pointCount * 4);
                        _colorChanged[i] = true;
                    }
            }
            if (HasTexMtx && !Weighted)
            {
                Model._errors.Add("Object " + Index + " has texture matrices but is not weighted.");
                for (int i = 0; i < 8; i++)
                    HasTextureMatrix[i] = false;
                SignalPropertyChange();
                _rebuild = true;
            }

            //if (!Weighted)
            //{
            //    bool notFloat = HasANonFloatAsset;
            //    foreach (PrimitiveGroup p in _primGroups)
            //    {
            //        bool o = false;
            //        foreach (PrimitiveHeader ph in p._headers)
            //            if (ph.Type != WiiPrimitiveType.TriangleList && notFloat)
            //            {
            //                Model._errors.Add("Object " + Index + " will explode in-game due to assets that are not written as float.");
            //                SignalPropertyChange();

            //                if (_vertexNode.Format != WiiVertexComponentType.Float)
            //                    _vertexNode._forceRebuild = _vertexNode._forceFloat = true;

            //                if (_normalNode != null && _normalNode.Format != WiiVertexComponentType.Float)
            //                    _normalNode._forceRebuild = _normalNode._forceFloat = true;

            //                for (int i = 4; i < 12; i++)
            //                    if (_uvSet[i - 4] != null && _uvSet[i - 4].Format != WiiVertexComponentType.Float)
            //                        _uvSet[i - 4]._forceRebuild = _uvSet[i - 4]._forceFloat = true;

            //                o = true;
            //                break;
            //            }
            //        if (o)
            //            break;
            //    }
            //}

            return false;
        }