Ejemplo n.º 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);
        }
Ejemplo n.º 2
0
 public ObjectInfo(
     bool weighted,
     GeometryEntry g,
     Matrix bindMatrix,
     SkinEntry skin,
     SceneEntry scene,
     InstanceEntry inst,
     ResourceNode parent,
     NodeEntry node)
 {
     _weighted   = weighted;
     _g          = g;
     _bindMatrix = bindMatrix;
     _skin       = skin;
     _scene      = scene;
     _parent     = parent;
     _node       = node;
     _inst       = inst;
 }
Ejemplo n.º 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;
            }
        }
        static PrimitiveManager DecodePrimitivesWeighted(NodeEntry n, GeometryEntry geo, SkinEntry skin, SceneEntry scene, InfluenceManager infManager, ref string Error)
        {
            PrimitiveManager manager = DecodePrimitives(n._matrix, 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;

            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];
                        inf._weights.Add(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.Count > 1)
                {
                    //Match with manager
                    inf = infManager.FindOrCreate(inf, true);
                    v = new Vertex3(n._matrix * skin._bindMatrix * pVert[i], inf); //World position
                }
                else
                {
                    bone = inf._weights[0].Bone;
                    v = new Vertex3(n._matrix * bone._inverseBindMatrix * skin._bindMatrix * pVert[i], 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];
                Vertex3 v = null;
                if (*pVInd < vertList.Count)
                    v = vertList[*pVInd];
                if (v != null && v._matrixNode != null)
                    if (v._matrixNode.Weights.Count > 1)
                        pNorms[i] = skin._bindMatrix.GetRotationMatrix() * pNorms[i];
                    else
                        pNorms[i] = skin._bindMatrix.GetRotationMatrix() * v._matrixNode.Weights[0].Bone._inverseBindMatrix.GetRotationMatrix() * pNorms[i];
            }

            remap.Dispose();
            return manager;
        }
        static PrimitiveManager DecodePrimitivesUnweighted(NodeEntry n, GeometryEntry geo)
        {
            PrimitiveManager manager = DecodePrimitives(n._matrix, 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(n._matrix * 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();

            return manager;
        }
        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;
        }
Ejemplo n.º 7
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);
        }
Ejemplo n.º 8
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);
        }
Ejemplo n.º 9
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;
            }
        }
Ejemplo n.º 10
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);
        }
        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 ParseLibGeometry()
            {
                GeometryEntry geo;
                while (_reader.BeginElement())
                {
                    if (_reader.Name.Equals("geometry", true))
                    {
                        geo = new GeometryEntry();
                        while (_reader.ReadAttribute())
                        {
                            if (_reader.Name.Equals("id", true))
                                geo._id = (string)_reader.Value;
                            else if (_reader.Name.Equals("name", true))
                                geo._name = (string)_reader.Value;
                        }

                        while (_reader.BeginElement())
                        {
                            if (_reader.Name.Equals("mesh", true))
                            {
                                while (_reader.BeginElement())
                                {
                                    if (_reader.Name.Equals("source", true))
                                        geo._sources.Add(ParseSource());
                                    else if (_reader.Name.Equals("vertices", true))
                                    {
                                        while (_reader.ReadAttribute())
                                            if (_reader.Name.Equals("id", true))
                                                geo._verticesId = (string)_reader.Value;

                                        while (_reader.BeginElement())
                                        {
                                            if (_reader.Name.Equals("input", true))
                                                geo._verticesInput = ParseInput();

                                            _reader.EndElement();
                                        }
                                    }
                                    else if (_reader.Name.Equals("polygons", true))
                                        geo._primitives.Add(ParsePrimitive(PrimitiveType.polygons));
                                    else if (_reader.Name.Equals("polylist", true))
                                        geo._primitives.Add(ParsePrimitive(PrimitiveType.polylist));
                                    else if (_reader.Name.Equals("triangles", true))
                                        geo._primitives.Add(ParsePrimitive(PrimitiveType.triangles));
                                    else if (_reader.Name.Equals("tristrips", true))
                                        geo._primitives.Add(ParsePrimitive(PrimitiveType.tristrips));
                                    else if (_reader.Name.Equals("trifans", true))
                                        geo._primitives.Add(ParsePrimitive(PrimitiveType.trifans));
                                    else if (_reader.Name.Equals("lines", true))
                                        geo._primitives.Add(ParsePrimitive(PrimitiveType.lines));
                                    else if (_reader.Name.Equals("linestrips", true))
                                        geo._primitives.Add(ParsePrimitive(PrimitiveType.linestrips));

                                    _reader.EndElement();
                                }
                            }
                            _reader.EndElement();
                        }

                        _geometry.Add(geo);
                    }
                    _reader.EndElement();
                }
            }