Beispiel #1
0
        // TODO:
        //
        // 1. Figure out how the bone remap indices work
        // They seem to be tied to the used bone indices somehow
        // Maybe building up an hierarchy as the same indices appear multiple times
        // Indices that aren't in the used bone indices are set to 0xFF
        //
        // 2. Figure out the BoneRLE
        // First byte is the hierarchy index of the affected bone
        // Second byte seems to be something like how many bones it shares weights with on the same material split?
        // 
        // 3. Figure out the inverse matrices
        // I can currently just copy and paste the one from the original file
        // But knowing how to calculate it would be a lot easier

        internal RWSkinPlugin(RWNodeFactory.RWNodeInfo header, BinaryReader reader, RWMesh rwGeometry)
            : base(header)
        {
            int numVertices = rwGeometry.VertexCount;

            m_numBones = reader.ReadByte();
            m_numUsedBones = reader.ReadByte();
            m_numWeightPerVertex = reader.ReadByte();
            m_unused = reader.ReadByte();

            m_usedBoneIndices = reader.ReadBytes(m_numUsedBones);

            m_skinBoneIndices = new byte[numVertices][];
            for (int i = 0; i < numVertices; i++)
            {
                m_skinBoneIndices[i] = reader.ReadBytes(4);
            }

            m_skinBoneWeights = new float[numVertices][];
            for (int i = 0; i < numVertices; i++)
            {
                m_skinBoneWeights[i] = reader.ReadFloatArray(4);
            }

            m_inverseBoneMatrices = new Matrix4x4[m_numBones];
            for (int i = 0; i < BoneCount; i++)
            {
                Matrix4x4 mtx = Matrix4x4.Identity;

                mtx.M11 = reader.ReadSingle(); mtx.M12 = reader.ReadSingle(); mtx.M13 = reader.ReadSingle(); reader.BaseStream.Position += 4;
                mtx.M21 = reader.ReadSingle(); mtx.M22 = reader.ReadSingle(); mtx.M23 = reader.ReadSingle(); reader.BaseStream.Position += 4;
                mtx.M31 = reader.ReadSingle(); mtx.M32 = reader.ReadSingle(); mtx.M33 = reader.ReadSingle(); reader.BaseStream.Position += 4;
                mtx.M41 = reader.ReadSingle(); mtx.M42 = reader.ReadSingle(); mtx.M43 = reader.ReadSingle(); reader.BaseStream.Position += 4;

                m_inverseBoneMatrices[i] = mtx;
            }

            m_boneLimit = reader.ReadInt32();
            m_numMaterialSplit = reader.ReadInt32();
            m_materialSplitNumUsedBones = reader.ReadInt32();

            if (m_numMaterialSplit < 1)
                return;

            m_boneRemapIndices = reader.ReadBytes(m_numBones);

            m_materialSplitSkinInfo = new MaterialSplitSkinInfo[m_numMaterialSplit];
            for (int i = 0; i < m_numMaterialSplit; i++)
                m_materialSplitSkinInfo[i] = new MaterialSplitSkinInfo { UsedBonesStartIndex = reader.ReadByte(), NumUsedBones = reader.ReadByte() };

            m_materialSplitUsedBoneInfo = new MaterialSplitUsedBoneInfo[m_materialSplitNumUsedBones];
            for (int i = 0; i < m_materialSplitNumUsedBones; i++)
                m_materialSplitUsedBoneInfo[i] = new MaterialSplitUsedBoneInfo { UsedBoneHierarchyIndex = reader.ReadByte(), Unknown = reader.ReadByte() };

            PrintInfo();
        }
        /// <summary>
        /// Initialize a new <see cref="RWMeshMaterialSplitData"/> using a <see cref="RWMesh"/> and the primitive type for the split data.
        /// </summary>
        /// <param name="mesh"></param>
        /// <param name="primType"></param>
        public RWMeshMaterialSplitData(RWMesh mesh, RWPrimitiveType primType = RWPrimitiveType.TriangleStrip, RWNode parent = null)
            : base(RWNodeType.MeshMaterialSplitList, parent)
        {
            // set type and prim count
            _primType = primType;
            _numPrimitives = mesh.TriangleCount;

            // pass 1: order the triangles by ascending material id
            var sortedTriangles = mesh.Triangles.OrderBy(tri => tri.MatID).ToArray();

            // pass 2: split the indices
            List<ushort>[] matSplitsIndices = new List<ushort>[mesh.MaterialCount];
            List<ushort> curMatSplitIndices = null;
            int curMatIdx = -1;
            for (int i = 0; i < sortedTriangles.Length; i++)
            {
                var tri = sortedTriangles[i];

                if (tri.MatID > curMatIdx)
                {
                    if (curMatIdx != -1)
                        matSplitsIndices[curMatIdx] = curMatSplitIndices;

                    curMatIdx = tri.MatID;
                    curMatSplitIndices = new List<ushort>();
                }

                curMatSplitIndices.Add(tri.A);
                curMatSplitIndices.Add(tri.B);
                curMatSplitIndices.Add(tri.C);
            }

            matSplitsIndices[curMatIdx] = curMatSplitIndices;

            // pass 3: create the split data
            _splits = new RWMeshMaterialSplit[mesh.MaterialCount];
            for (int i = 0; i < _splits.Length; i++)
            {
                ushort[] matSplitIndices = matSplitsIndices[i].ToArray();

                if (primType == RWPrimitiveType.TriangleStrip)
                {
                    
                    ManagedNvTriStrip.PrimitiveGroup[] primitives = null;

                    if (ManagedNvTriStrip.NvTriStripUtility.Stripify(matSplitIndices, ref primitives))
                    {
                        matSplitIndices = primitives[0].Indices;
                    }
                    else
                    {
                        throw new System.Exception("Failed to generate strips.");
                    }
                    
                    /*
                    NvTriStripDotNet.PrimitiveGroup[] primitives;
                    var tristripper = new NvTriStripDotNet.NvTriStrip();
                    if (tristripper.GenerateStrips(matSplitIndices, out primitives))
                    {
                        matSplitIndices = primitives[0].indices.Cast<ushort>().ToArray();
                    }
                    */
                }

                _splits[i] = new RWMeshMaterialSplit(i, matSplitIndices);
            }
        }