예제 #1
0
        void generateMultiple16bitMeshbuffers(int N)
        {
            Vertex3D[] vertices32bit;
            uint[]     indices32bit;
            generateVerticesAndIndices(N, out vertices32bit, out indices32bit);

            List <Vertex3D> verticesChunk = new List <Vertex3D>();
            List <ushort>   indicesChunk  = new List <ushort>();

            int totalCubes              = N * N * N;
            int indicesInCube           = indices32bit.Length / totalCubes;
            int verticesInCube          = vertices32bit.Length / totalCubes;
            int maximumVerticesPerChunk = ushort.MaxValue;             // must not be more than 0xffff (because we use 16-bit indices)
            int verticesIndexOffset     = 0;

            device.Logger.Log("Batching cubes into 16-bit meshbuffers...");

            for (int cubeIndex = 0; cubeIndex < totalCubes; cubeIndex++)
            {
                // add vertices
                for (int i = 0; i < verticesInCube; i++)
                {
                    verticesChunk.Add(vertices32bit[cubeIndex * verticesInCube + i]);
                }

                // add indices
                for (int i = 0; i < indicesInCube; i++)
                {
                    indicesChunk.Add((ushort)(indices32bit[cubeIndex * indicesInCube + i] - verticesIndexOffset));
                }

                if (verticesChunk.Count + verticesInCube > maximumVerticesPerChunk ||              // if this chunk is full
                    cubeIndex == totalCubes - 1)                        // or this is last cube
                {
                    // we create meshbuffer and add it to the main mesh
                    MeshBuffer mb = MeshBuffer.Create(VertexType.Standard, IndexType._16Bit);
                    mb.SetHardwareMappingHint(HardwareMappingHint.Static, HardwareBufferType.VertexAndIndex);
                    //mb.Append(verticesChunk.ToArray(), indicesChunk.ToArray());
                    mb.Append(verticesChunk.ToArray(), indicesChunk.ToArray());
                    mb.RecalculateBoundingBox();
                    mesh.AddMeshBuffer(mb);
                    mb.Drop();

                    // clean up vertex and index chunks
                    verticesIndexOffset += verticesChunk.Count;
                    verticesChunk.Clear();
                    indicesChunk.Clear();

                    device.Logger.Log(
                        (((cubeIndex + 1) * 100) / totalCubes) + "%: " +
                        mesh + ". ~" +
                        Program.MemUsageText);

                    GC.Collect();
                }
            }
        }
예제 #2
0
        /// <summary>
        /// Generates a MeshBuffer which represents all the vertices and indices for values of y
        /// between y0 and y1, and add it to the mesh.
        /// </summary>
        void addStrip(HeightMap map, ColorFunc cf, int y0, int y1)
        {
            Vertex3D[] vertices = new Vertex3D[(y1 - y0 + 1) * width];
            ushort[]   indices  = new ushort[(y1 - y0) * (width - 1) * 6];          // "6" is a number of indices in 2 triangles (which forms a quad)

            // calculate vertices

            int i = 0;

            for (int y = y0; y <= y1; ++y)
            {
                for (int x = 0; x < width; ++x)
                {
                    float z  = map.GetHeight(x, y);
                    float xf = (float)x / (float)width;
                    float yf = (float)y / (float)height;

                    vertices[i++] = new Vertex3D(
                        new Vector3Df(x, scale * z, y),               // position
                        map.GetNormal(x, y, scale),                   // normal
                        calculate(cf, xf, yf, z),                     // color
                        new Vector2Df(xf, yf)                         // tcoords
                        );
                }
            }

            // calculate indices

            i = 0;
            for (int y = y0; y < y1; ++y)
            {
                for (int x = 0; x < width - 1; ++x)
                {
                    int n = (y - y0) * width + x;
                    indices[i++] = (ushort)n;
                    indices[i++] = (ushort)(n + width);
                    indices[i++] = (ushort)(n + width + 1);
                    indices[i++] = (ushort)(n + width + 1);
                    indices[i++] = (ushort)(n + 1);
                    indices[i++] = (ushort)n;
                }
            }

            // append calculated verices and indices to mesh buffer

            MeshBuffer buf = MeshBuffer.Create(VertexType.Standard, IndexType._16Bit);             // create new buffer

            Mesh.AddMeshBuffer(buf);
            buf.Append(vertices, indices);
            buf.RecalculateBoundingBox();
            buf.Drop();
        }
예제 #3
0
        void generateSingle32BitMeshbuffer(int N)
        {
            Vertex3D[] vertices32bit;
            uint[]     indices32bit;
            generateVerticesAndIndices(N, out vertices32bit, out indices32bit);

            MeshBuffer mb = MeshBuffer.Create(VertexType.Standard, IndexType._32Bit);

            mesh.AddMeshBuffer(mb);
            mb.Drop();

            device.Logger.Log("Appending " +
                              vertices32bit.Length + " vertices and " +
                              indices32bit.Length + " indices to 32-bit meshbuffer...");

            mb.Append(vertices32bit, indices32bit);
            mb.SetHardwareMappingHint(HardwareMappingHint.Static, HardwareBufferType.VertexAndIndex);
        }
예제 #4
0
        /// <summary>
        /// Read mesh chunk and buffer infos.
        /// </summary>
        public void LoadData(CR2WFile meshFile)
        {
            // IMPLEMENTED FROM jlouis' witcherconverter
            // http://jlouisb.users.sourceforge.net/
            // https://bitbucket.org/jlouis/witcherconverter

            SBufferInfos bufferInfos = new SBufferInfos();

            // *************** READ CHUNK INFOS ***************
            foreach (var chunk in meshFile.chunks)
            {
                if (chunk.Type == "CMesh")
                {
                    List <SVertexBufferInfos> vertexBufferInfos = new List <SVertexBufferInfos>();
                    var cookedDatas = chunk.GetVariableByName("cookedData") as CVector;
                    foreach (var cookedData in cookedDatas.variables)
                    {
                        switch (cookedData.Name)
                        {
                        case "renderChunks":
                        {
                            var bytes = ((CByteArray)cookedData).Bytes;
                            using (MemoryStream ms = new MemoryStream(bytes))
                                using (BinaryReader br = new BinaryReader(ms))
                                {
                                    var nbBuffers = br.ReadByte();
                                    for (uint i = 0; i < nbBuffers; i++)
                                    {
                                        SVertexBufferInfos buffInfo = new SVertexBufferInfos();

                                        br.BaseStream.Position       += 1; // Unknown
                                        buffInfo.verticesCoordsOffset = br.ReadUInt32();
                                        buffInfo.uvOffset             = br.ReadUInt32();
                                        buffInfo.normalsOffset        = br.ReadUInt32();

                                        br.BaseStream.Position += 9;     // Unknown
                                        buffInfo.indicesOffset  = br.ReadUInt32();
                                        br.BaseStream.Position += 1;     // 0x1D

                                        buffInfo.nbVertices     = br.ReadUInt16();
                                        buffInfo.nbIndices      = br.ReadUInt32();
                                        br.BaseStream.Position += 3;             // Unknown
                                        buffInfo.lod            = br.ReadByte(); // lod ?

                                        vertexBufferInfos.Add(buffInfo);
                                    }
                                }
                            break;
                        }

                        case "indexBufferOffset":
                        {
                            bufferInfos.indexBufferOffset = uint.Parse(cookedData.ToString());
                            break;
                        }

                        case "indexBufferSize":
                        {
                            bufferInfos.indexBufferSize = uint.Parse(cookedData.ToString());
                            break;
                        }

                        case "vertexBufferOffset":
                        {
                            bufferInfos.vertexBufferOffset = uint.Parse(cookedData.ToString());
                            break;
                        }

                        case "vertexBufferSize":
                        {
                            bufferInfos.vertexBufferSize = uint.Parse(cookedData.ToString());
                            break;
                        }

                        case "quantizationOffset":
                        {
                            bufferInfos.quantizationOffset.X = float.Parse((cookedData as CVector).variables[0].ToString());
                            bufferInfos.quantizationOffset.Y = float.Parse((cookedData as CVector).variables[1].ToString());
                            bufferInfos.quantizationOffset.Z = float.Parse((cookedData as CVector).variables[2].ToString());
                            break;
                        }

                        case "quantizationScale":
                        {
                            bufferInfos.quantizationScale.X = float.Parse((cookedData as CVector).variables[0].ToString());
                            bufferInfos.quantizationScale.Y = float.Parse((cookedData as CVector).variables[1].ToString());
                            bufferInfos.quantizationScale.Z = float.Parse((cookedData as CVector).variables[2].ToString());
                            break;
                        }

                        case "bonePositions":
                        {
                            foreach (CVector item in cookedData as CArray)
                            {
                                if (item.variables.Count == 4)
                                {
                                    Vector3Df pos = new Vector3Df();
                                    pos.X = (item.variables[0] as CFloat).val;
                                    pos.Y = (item.variables[1] as CFloat).val;
                                    pos.Z = (item.variables[2] as CFloat).val;
                                    bonePositions.Add(pos);
                                }
                            }
                            break;
                        }
                        }
                    }
                    bufferInfos.verticesBuffer = vertexBufferInfos;
                    var meshChunks = chunk.GetVariableByName("chunks") as CArray;
                    foreach (var meshChunk in meshChunks.array)
                    {
                        SMeshInfos meshInfo = new SMeshInfos();
                        foreach (var meshinfo in (meshChunk as CVector).variables)
                        {
                            switch (meshinfo.Name)
                            {
                            case "numVertices":
                            {
                                meshInfo.numVertices = uint.Parse(meshinfo.ToString());
                                break;
                            }

                            case "numIndices":
                            {
                                meshInfo.numIndices = uint.Parse(meshinfo.ToString());
                                break;
                            }

                            case "numBonesPerVertex":
                            {
                                meshInfo.numBonesPerVertex = uint.Parse(meshinfo.ToString());
                                break;
                            }

                            case "firstVertex":
                            {
                                meshInfo.firstVertex = uint.Parse(meshinfo.ToString());
                                break;
                            }

                            case "firstIndex":
                            {
                                meshInfo.firstIndex = uint.Parse(meshinfo.ToString());
                                break;
                            }

                            case "vertexType":
                            {
                                if ((meshinfo as CName).Value == "MVT_StaticMesh")
                                {
                                    meshInfo.vertexType = SMeshInfos.EMeshVertexType.EMVT_STATIC;
                                }
                                else if ((meshinfo as CName).Value == "MVT_SkinnedMesh")
                                {
                                    meshInfo.vertexType = SMeshInfos.EMeshVertexType.EMVT_SKINNED;
                                }
                                break;
                            }

                            case "materialID":
                            {
                                meshInfo.materialID = uint.Parse(meshinfo.ToString());
                                break;
                            }
                            }
                        }
                        CData.meshInfos.Add(meshInfo);
                    }

                    // TODO: Create a more reliable solution
                    var unknownBytes = chunk.unknownBytes.Bytes;
                    using (var ms = new MemoryStream(unknownBytes))
                        using (var br = new BinaryReader(ms))
                        {
                            long prevPos    = 0;
                            bool correctPos = false;
                            do
                            {
                                prevPos = br.BaseStream.Position;
                                CData.boneData.nbBones = (uint)br.ReadBit6();

                                if (CData.boneData.nbBones == bonePositions.Count)
                                {
                                    var backPos = br.BaseStream.Position;
                                    correctPos = true;
                                    for (int i = 0; i < CData.boneData.nbBones; i++)
                                    {
                                        var stringIdx = br.ReadUInt16();
                                        if (stringIdx == 0 || stringIdx >= meshFile.names.Count)
                                        {
                                            CData.boneData.nbBones = 0;
                                            correctPos             = false;
                                            break;
                                        }
                                    }
                                    br.BaseStream.Position = backPos;
                                }
                            } while (CData.boneData.nbBones != bonePositions.Count && br.BaseStream.Position < unknownBytes.Length && !correctPos);

                            if (br.BaseStream.Position < unknownBytes.Length)
                            {
                                br.BaseStream.Position = prevPos;
                                CData.boneData.nbBones = (uint)br.ReadBit6();
                                for (uint i = 0; i < CData.boneData.nbBones; i++)
                                {
                                    var stringIdx = br.ReadUInt16();
                                    CData.boneData.jointNames.Add(meshFile.names[stringIdx].str);
                                }
                                br.ReadBit6();
                                for (uint i = 0; i < CData.boneData.nbBones; i++)
                                {
                                    Matrix matrix = new Matrix();
                                    for (int j = 0; j < 16; j++)
                                    {
                                        var value = br.ReadSingle();
                                        matrix.SetElement(j, value);
                                    }
                                    CData.boneData.boneMatrices.Add(matrix);
                                }
                            }
                        }
                }
                else if (chunk.Type == "CMaterialInstance")
                {
                    CData.materialInstances.Add(chunk.data as CMaterialInstance);
                }
            }

            // *************** READ MESH BUFFER INFOS ***************
            foreach (var meshInfo in CData.meshInfos)
            {
                SVertexBufferInfos vBufferInf = new SVertexBufferInfos();
                uint nbVertices        = 0;
                uint firstVertexOffset = 0;
                uint nbIndices         = 0;
                uint firstIndiceOffset = 0;
                for (int i = 0; i < bufferInfos.verticesBuffer.Count; i++)
                {
                    nbVertices += bufferInfos.verticesBuffer[i].nbVertices;
                    if (nbVertices > meshInfo.firstVertex)
                    {
                        vBufferInf = bufferInfos.verticesBuffer[i];
                        // the index of the first vertex in the buffer
                        firstVertexOffset = meshInfo.firstVertex - (nbVertices - vBufferInf.nbVertices);
                        break;
                    }
                }
                for (int i = 0; i < bufferInfos.verticesBuffer.Count; i++)
                {
                    nbIndices += bufferInfos.verticesBuffer[i].nbIndices;
                    if (nbIndices > meshInfo.firstIndex)
                    {
                        vBufferInf        = bufferInfos.verticesBuffer[i];
                        firstIndiceOffset = meshInfo.firstIndex - (nbIndices - vBufferInf.nbIndices);
                        break;
                    }
                }

                // Load only best LOD
                if (vBufferInf.lod == 1)
                {
                    using (BinaryReader br = new BinaryReader(File.Open(meshFile.FileName + ".1.buffer", FileMode.Open)))
                    {
                        uint vertexSize = 8;
                        if (meshInfo.vertexType == SMeshInfos.EMeshVertexType.EMVT_SKINNED)
                        {
                            vertexSize += meshInfo.numBonesPerVertex * 2;
                        }

                        br.BaseStream.Seek(vBufferInf.verticesCoordsOffset + firstVertexOffset * vertexSize, SeekOrigin.Begin);

                        List <Vertex3D> vertex3DCoords = new List <Vertex3D>();
                        Color           defaultColor   = new Color(255, 255, 255, 255);
                        for (uint i = 0; i < meshInfo.numVertices; i++)
                        {
                            ushort x = br.ReadUInt16();
                            ushort y = br.ReadUInt16();
                            ushort z = br.ReadUInt16();
                            ushort w = br.ReadUInt16();

                            if (meshInfo.vertexType == SMeshInfos.EMeshVertexType.EMVT_SKINNED)
                            {
                                //sr.BaseStream.Seek(meshInfo.numBonesPerVertex * 2, SeekOrigin.Current);
                                byte[] skinningData = new byte[meshInfo.numBonesPerVertex * 2];
                                br.BaseStream.Read(skinningData, 0, (int)meshInfo.numBonesPerVertex * 2);

                                for (uint j = 0; j < meshInfo.numBonesPerVertex; ++j)
                                {
                                    uint  boneId  = skinningData[j];
                                    uint  weight  = skinningData[j + meshInfo.numBonesPerVertex];
                                    float fweight = weight / 255.0f;

                                    if (weight != 0)
                                    {
                                        var vertexSkinningEntry = new W3_DataCache.VertexSkinningEntry();
                                        vertexSkinningEntry.boneId       = boneId;
                                        vertexSkinningEntry.meshBufferId = 0;
                                        vertexSkinningEntry.vertexId     = i;
                                        vertexSkinningEntry.strength     = fweight;
                                        CData.w3_DataCache.vertices.Add(vertexSkinningEntry);
                                    }
                                }
                            }

                            Vertex3D vertex3DCoord = new Vertex3D();
                            vertex3DCoord.Position = new Vector3Df(x, y, z) / 65535f * bufferInfos.quantizationScale + bufferInfos.quantizationOffset;
                            vertex3DCoord.Color    = defaultColor;
                            vertex3DCoords.Add(vertex3DCoord);
                        }

                        br.BaseStream.Seek(vBufferInf.uvOffset + firstVertexOffset * 4, SeekOrigin.Begin);

                        for (int i = 0; i < meshInfo.numVertices; i++)
                        {
                            float uf = br.ReadHalfFloat();
                            float vf = br.ReadHalfFloat();

                            Vertex3D vertex3DCoord = vertex3DCoords[i];
                            vertex3DCoord.TCoords = new Vector2Df(uf, vf);
                            vertex3DCoords[i]     = vertex3DCoord;
                        }

                        // Indices -------------------------------------------------------------------
                        br.BaseStream.Seek(bufferInfos.indexBufferOffset + vBufferInf.indicesOffset + firstIndiceOffset * 2, SeekOrigin.Begin);

                        List <ushort> indices = new List <ushort>();
                        for (int i = 0; i < meshInfo.numIndices; i++)
                        {
                            indices.Add(0);
                        }

                        for (int i = 0; i < meshInfo.numIndices; i++)
                        {
                            ushort index = br.ReadUInt16();

                            // Indice need to be inversed for the normals
                            if (i % 3 == 0)
                            {
                                indices[i] = index;
                            }
                            else if (i % 3 == 1)
                            {
                                indices[i + 1] = index;
                            }
                            else if (i % 3 == 2)
                            {
                                indices[i - 1] = index;
                            }
                        }

                        MeshBuffer meshBuff = MeshBuffer.Create(VertexType.Standard, IndexType._16Bit);
                        CData.staticMesh.AddMeshBuffer(meshBuff);
                        meshBuff.Append(vertex3DCoords, indices);
                        meshBuff.RecalculateBoundingBox();
                        meshBuff.Drop();
                    }
                }
            }
        }
예제 #5
0
        /// <summary>
        /// Read mesh chunk and buffer infos.
        /// </summary>
        public void LoadData(CR2WFile meshFile)
        {
            // IMPLEMENTED FROM jlouis' witcherconverter
            // http://jlouisb.users.sourceforge.net/
            // https://bitbucket.org/jlouis/witcherconverter

            SBufferInfos bufferInfos = new SBufferInfos();

            // *************** READ CHUNK INFOS ***************
            foreach (var chunk in meshFile.Chunks)
            {
                if (chunk.REDType == "CMesh" && chunk.data is CMesh cmesh)
                {
                    List <SVertexBufferInfos> vertexBufferInfos = new List <SVertexBufferInfos>();
                    SMeshCookedData           meshCookedData    = cmesh.CookedData;


                    var bytes = meshCookedData.RenderChunks.Bytes;
                    using (MemoryStream ms = new MemoryStream(bytes))
                        using (BinaryReader br = new BinaryReader(ms))
                        {
                            var nbBuffers = br.ReadByte();
                            for (uint i = 0; i < nbBuffers; i++)
                            {
                                SVertexBufferInfos buffInfo = new SVertexBufferInfos();

                                br.BaseStream.Position       += 1; // Unknown
                                buffInfo.verticesCoordsOffset = br.ReadUInt32();
                                buffInfo.uvOffset             = br.ReadUInt32();
                                buffInfo.normalsOffset        = br.ReadUInt32();

                                br.BaseStream.Position += 9; // Unknown
                                buffInfo.indicesOffset  = br.ReadUInt32();
                                br.BaseStream.Position += 1; // 0x1D

                                buffInfo.nbVertices     = br.ReadUInt16();
                                buffInfo.nbIndices      = br.ReadUInt32();
                                buffInfo.materialID     = br.ReadByte();
                                br.BaseStream.Position += 2;             // Unknown
                                buffInfo.lod            = br.ReadByte(); // lod ?

                                vertexBufferInfos.Add(buffInfo);
                            }
                        }

                    bufferInfos.indexBufferOffset = meshCookedData.IndexBufferOffset.val;
                    bufferInfos.indexBufferSize   = meshCookedData.IndexBufferSize.val;
                    //bufferInfos.vertexBufferOffset = meshCookedData.vertexBufferOffset.val; //FIXME
                    bufferInfos.vertexBufferSize     = meshCookedData.VertexBufferSize.val;
                    bufferInfos.quantizationOffset.X = meshCookedData.QuantizationOffset.X.val;
                    bufferInfos.quantizationOffset.Y = meshCookedData.QuantizationOffset.Y.val;
                    bufferInfos.quantizationOffset.Z = meshCookedData.QuantizationOffset.Z.val;
                    bufferInfos.quantizationScale.X  = meshCookedData.QuantizationScale.X.val;
                    bufferInfos.quantizationScale.Y  = meshCookedData.QuantizationScale.Y.val;
                    bufferInfos.quantizationScale.Z  = meshCookedData.QuantizationScale.Z.val;

                    if (meshCookedData.BonePositions != null)
                    {
                        foreach (var item in meshCookedData.BonePositions)
                        {
                            Vector3Df pos = new Vector3Df();
                            pos.X = item.X.val;
                            pos.Y = item.Y.val;
                            pos.Z = item.Z.val;
                            bonePositions.Add(pos);
                        }
                    }


                    bufferInfos.verticesBuffer = vertexBufferInfos;
                    CArray <SMeshChunkPacked> meshChunks = cmesh.Chunks;
                    foreach (SMeshChunkPacked meshChunk in meshChunks.Elements)
                    {
                        SMeshInfos meshInfo = new SMeshInfos();

                        meshInfo.numVertices       = meshChunk.NumVertices == null ? 0 : meshChunk.NumVertices.val;
                        meshInfo.numIndices        = meshChunk.NumIndices == null ? 0 : meshChunk.NumIndices.val;
                        meshInfo.numBonesPerVertex = meshChunk.NumBonesPerVertex == null ? (uint)0 : meshChunk.NumBonesPerVertex.val;
                        meshInfo.firstVertex       = meshChunk.FirstVertex == null ? 0 : meshChunk.FirstVertex.val;
                        meshInfo.firstIndex        = meshChunk.FirstIndex == null ? 0 : meshChunk.FirstIndex.val;
                        meshInfo.materialID        = meshChunk.MaterialID == null ? 0 : meshChunk.MaterialID.val;

                        if (meshChunk.VertexType != null)
                        {
                            if (meshChunk.VertexType.WrappedEnum == Enums.EMeshVertexType.MVT_StaticMesh)
                            {
                                meshInfo.vertexType = SMeshInfos.EMeshVertexType.EMVT_STATIC;
                            }
                            else if (meshChunk.VertexType.WrappedEnum == Enums.EMeshVertexType.MVT_SkinnedMesh)
                            {
                                meshInfo.vertexType = SMeshInfos.EMeshVertexType.EMVT_SKINNED;
                            }
                        }

                        CData.meshInfos.Add(meshInfo);
                    }

                    // bone names and matrices
                    CBufferVLQInt32 <CName>      boneNames    = cmesh.BoneNames;
                    CBufferVLQInt32 <CMatrix4x4> bonematrices = cmesh.Bonematrices;
                    CData.boneData.nbBones = (uint)boneNames.elements.Count;
                    for (int i = 0; i < CData.boneData.nbBones; i++)
                    {
                        CName name = boneNames.elements[i];
                        CData.boneData.jointNames.Add(name.Value);

                        CMatrix4x4 cmatrix = bonematrices.elements[i];
                        Matrix     matrix  = new Matrix();
                        for (int j = 0; j < 16; j++)
                        {
                            float value = (cmatrix.fields[j] as CFloat).val;
                            matrix.SetElement(j, value);
                        }
                        CData.boneData.boneMatrices.Add(matrix);
                    }
                }

                else if (chunk.REDType == "CMaterialInstance")
                {
                    CData.materialInstances.Add(chunk.data as CMaterialInstance);
                }
            }

            // *************** READ MESH BUFFER INFOS ***************
            foreach (var meshInfo in CData.meshInfos)
            {
                SVertexBufferInfos vBufferInf = new SVertexBufferInfos();
                uint nbVertices        = 0;
                uint firstVertexOffset = 0;
                uint nbIndices         = 0;
                uint firstIndiceOffset = 0;
                for (int i = 0; i < bufferInfos.verticesBuffer.Count; i++)
                {
                    nbVertices += bufferInfos.verticesBuffer[i].nbVertices;
                    if (nbVertices > meshInfo.firstVertex)
                    {
                        vBufferInf = bufferInfos.verticesBuffer[i];
                        // the index of the first vertex in the buffer
                        firstVertexOffset = meshInfo.firstVertex - (nbVertices - vBufferInf.nbVertices);
                        break;
                    }
                }
                for (int i = 0; i < bufferInfos.verticesBuffer.Count; i++)
                {
                    nbIndices += bufferInfos.verticesBuffer[i].nbIndices;
                    if (nbIndices > meshInfo.firstIndex)
                    {
                        vBufferInf        = bufferInfos.verticesBuffer[i];
                        firstIndiceOffset = meshInfo.firstIndex - (nbIndices - vBufferInf.nbIndices);
                        break;
                    }
                }

                // Load only best LOD
                if (vBufferInf.lod == 1)
                {
                    using (BinaryReader br = new BinaryReader(File.Open(meshFile.FileName + ".1.buffer", FileMode.Open)))
                    {
                        uint vertexSize = 8;
                        if (meshInfo.vertexType == SMeshInfos.EMeshVertexType.EMVT_SKINNED)
                        {
                            vertexSize += meshInfo.numBonesPerVertex * 2;
                        }

                        br.BaseStream.Seek(vBufferInf.verticesCoordsOffset + firstVertexOffset * vertexSize, SeekOrigin.Begin);

                        List <Vertex3D> vertex3DCoords = new List <Vertex3D>();
                        Color           defaultColor   = new Color(255, 255, 255, 255);
                        for (uint i = 0; i < meshInfo.numVertices; i++)
                        {
                            ushort x = br.ReadUInt16();
                            ushort y = br.ReadUInt16();
                            ushort z = br.ReadUInt16();
                            ushort w = br.ReadUInt16();

                            if (meshInfo.vertexType == SMeshInfos.EMeshVertexType.EMVT_SKINNED)
                            {
                                //sr.BaseStream.Seek(meshInfo.numBonesPerVertex * 2, SeekOrigin.Current);
                                byte[] skinningData = new byte[meshInfo.numBonesPerVertex * 2];
                                br.BaseStream.Read(skinningData, 0, (int)meshInfo.numBonesPerVertex * 2);

                                for (uint j = 0; j < meshInfo.numBonesPerVertex; ++j)
                                {
                                    uint  boneId  = skinningData[j];
                                    uint  weight  = skinningData[j + meshInfo.numBonesPerVertex];
                                    float fweight = weight / 255.0f;

                                    if (weight != 0)
                                    {
                                        var vertexSkinningEntry = new W3_DataCache.VertexSkinningEntry();
                                        vertexSkinningEntry.boneId       = boneId;
                                        vertexSkinningEntry.meshBufferId = 0;
                                        vertexSkinningEntry.vertexId     = i;
                                        vertexSkinningEntry.strength     = fweight;
                                        CData.w3_DataCache.vertices.Add(vertexSkinningEntry);
                                    }
                                }
                            }

                            Vertex3D vertex3DCoord = new Vertex3D();
                            vertex3DCoord.Position = new Vector3Df(x, y, z) / 65535f * bufferInfos.quantizationScale + bufferInfos.quantizationOffset;
                            vertex3DCoord.Color    = defaultColor;
                            vertex3DCoords.Add(vertex3DCoord);
                        }

                        br.BaseStream.Seek(vBufferInf.uvOffset + firstVertexOffset * 4, SeekOrigin.Begin);

                        for (int i = 0; i < meshInfo.numVertices; i++)
                        {
                            float uf = br.ReadHalfFloat();
                            float vf = br.ReadHalfFloat();

                            Vertex3D vertex3DCoord = vertex3DCoords[i];
                            vertex3DCoord.TCoords = new Vector2Df(uf, vf);
                            vertex3DCoords[i]     = vertex3DCoord;
                        }

                        // Indices -------------------------------------------------------------------
                        br.BaseStream.Seek(bufferInfos.indexBufferOffset + vBufferInf.indicesOffset + firstIndiceOffset * 2, SeekOrigin.Begin);

                        List <ushort> indices = new List <ushort>();
                        for (int i = 0; i < meshInfo.numIndices; i++)
                        {
                            indices.Add(0);
                        }

                        for (int i = 0; i < meshInfo.numIndices; i++)
                        {
                            ushort index = br.ReadUInt16();

                            // Indice need to be inversed for the normals
                            if (i % 3 == 0)
                            {
                                indices[i] = index;
                            }
                            else if (i % 3 == 1)
                            {
                                indices[i + 1] = index;
                            }
                            else if (i % 3 == 2)
                            {
                                indices[i - 1] = index;
                            }
                        }

                        MeshBuffer meshBuff = MeshBuffer.Create(VertexType.Standard, IndexType._16Bit);
                        meshBuff.Append(vertex3DCoords.ToArray(), indices.ToArray());
                        meshBuff.RecalculateBoundingBox();
                        CData.staticMesh.AddMeshBuffer(meshBuff);
                        meshBuff.Drop();
                    }
                }
            }
        }
예제 #6
0
        private void meshGeneratorThread_generateMesh(int layerIndex)
        {
            GridLayer l = layers[layerIndex];

            if (l.Mesh != null)
            {
                l.Mesh.Drop();
            }

            l.Mesh = Mesh.Create();

            if (gridCubeCount > 0)
            {
                Vertex3D[] cubeVerts       = null;
                ushort[]   cubeInds        = null;
                int        cubeIndex       = maxCubesPerBuffer;    // this way we force buffers to be recreated at next new cube
                int        totalCubesAdded = 0;

                float baseX = -(CubeSize * GridDim) / 2;
                float baseZ = -(CubeSize * GridDim) / 2;

                for (int i = 0; i < GridDim; i++)
                {
                    for (int j = 0; j < GridDim; j++)
                    {
                        if (grid[i, j] == 0)
                        {
                            continue;
                        }

                        // check if current buffer is out of room, if so make a mesh buffer and attach it to the gridMesh and init next cubeVerts&Inds

                        if (cubeIndex == maxCubesPerBuffer)
                        {
                            if (cubeVerts != null && cubeInds != null)
                            {
                                MeshBuffer b = MeshBuffer.Create(VertexType.Standard, IndexType._16Bit);
                                b.Append(cubeVerts, cubeInds);
                                l.Mesh.AddMeshBuffer(b);
                                b.Drop();

                                totalCubesAdded += cubeIndex;
                            }

                            int cubeCount = gridCubeCount - totalCubesAdded;
                            if (cubeCount > maxCubesPerBuffer)
                            {
                                cubeCount = maxCubesPerBuffer;
                            }

                            cubeIndex = 0;
                            cubeVerts = new Vertex3D[cubeCount * 8];                             // 8 verts per cube
                            cubeInds  = new ushort[cubeCount * 3 * 2 * 6];                       // 3 indices per triangle; 2 triangles per face; 6 faces per cube
                        }

                        // build the cube and add it
                        // note: we build 8 vertices cube because we don't need to texture it; if you want to change that (to use texture instead of vertex colors) - you need to build 12 vertices cube and initialize UV coords

                        float x  = baseX + i * CubeSize;
                        float y  = 0;
                        float z  = baseZ + j * CubeSize;
                        int   iv = cubeIndex * 8;

                        cubeVerts[iv + 0] = new Vertex3D(x, y, z);
                        cubeVerts[iv + 1] = new Vertex3D(x + CubeSize, y, z);
                        cubeVerts[iv + 2] = new Vertex3D(x + CubeSize, y + CubeSize, z);
                        cubeVerts[iv + 3] = new Vertex3D(x, y + CubeSize, z);
                        cubeVerts[iv + 4] = new Vertex3D(x, y, z + CubeSize);
                        cubeVerts[iv + 5] = new Vertex3D(x + CubeSize, y, z + CubeSize);
                        cubeVerts[iv + 6] = new Vertex3D(x + CubeSize, y + CubeSize, z + CubeSize);
                        cubeVerts[iv + 7] = new Vertex3D(x, y + CubeSize, z + CubeSize);

                        int ii = cubeIndex * 3 * 2 * 6;

                        // top
                        cubeInds[ii + 0] = (ushort)(iv + 3);
                        cubeInds[ii + 1] = (ushort)(iv + 7);
                        cubeInds[ii + 2] = (ushort)(iv + 6);
                        cubeInds[ii + 3] = (ushort)(iv + 3);
                        cubeInds[ii + 4] = (ushort)(iv + 6);
                        cubeInds[ii + 5] = (ushort)(iv + 2);

                        // front
                        cubeInds[ii + 6]  = (ushort)(iv + 0);
                        cubeInds[ii + 7]  = (ushort)(iv + 3);
                        cubeInds[ii + 8]  = (ushort)(iv + 2);
                        cubeInds[ii + 9]  = (ushort)(iv + 0);
                        cubeInds[ii + 10] = (ushort)(iv + 2);
                        cubeInds[ii + 11] = (ushort)(iv + 1);

                        // right
                        cubeInds[ii + 12] = (ushort)(iv + 1);
                        cubeInds[ii + 13] = (ushort)(iv + 2);
                        cubeInds[ii + 14] = (ushort)(iv + 6);
                        cubeInds[ii + 15] = (ushort)(iv + 1);
                        cubeInds[ii + 16] = (ushort)(iv + 6);
                        cubeInds[ii + 17] = (ushort)(iv + 5);

                        // left
                        cubeInds[ii + 18] = (ushort)(iv + 0);
                        cubeInds[ii + 19] = (ushort)(iv + 4);
                        cubeInds[ii + 20] = (ushort)(iv + 7);
                        cubeInds[ii + 21] = (ushort)(iv + 0);
                        cubeInds[ii + 22] = (ushort)(iv + 7);
                        cubeInds[ii + 23] = (ushort)(iv + 3);

                        // back
                        cubeInds[ii + 24] = (ushort)(iv + 4);
                        cubeInds[ii + 25] = (ushort)(iv + 5);
                        cubeInds[ii + 26] = (ushort)(iv + 6);
                        cubeInds[ii + 27] = (ushort)(iv + 4);
                        cubeInds[ii + 28] = (ushort)(iv + 6);
                        cubeInds[ii + 29] = (ushort)(iv + 7);

                        // bottom
                        cubeInds[ii + 30] = (ushort)(iv + 0);
                        cubeInds[ii + 31] = (ushort)(iv + 1);
                        cubeInds[ii + 32] = (ushort)(iv + 5);
                        cubeInds[ii + 33] = (ushort)(iv + 0);
                        cubeInds[ii + 34] = (ushort)(iv + 5);
                        cubeInds[ii + 35] = (ushort)(iv + 4);

                        cubeIndex++;
                    }
                }

                if (cubeIndex > 0)
                {
                    MeshBuffer b = MeshBuffer.Create(VertexType.Standard, IndexType._16Bit);
                    b.Append(cubeVerts, cubeInds);
                    l.Mesh.AddMeshBuffer(b);
                    b.Drop();
                }

                device.SceneManager.MeshManipulator.SetVertexColors(l.Mesh, cubeColor);
            }

            l.Transform.Rotation = new Vector3Df(gridGeneration * 0.93f, gridGeneration * 0.81f, gridGeneration * 0.69f);

            l.Generation  = gridGeneration;
            l.CubeCount   = gridCubeCount;
            l.MeshIsReady = true;
        }
예제 #7
0
        /// <summary>
        /// Reads mesh buffer infos.
        /// </summary>
        void ReadMeshBufferInfos()
        {
            // IMPLEMENTED FROM jlouis' witcherconverter
            // http://jlouisb.users.sourceforge.net/
            // https://bitbucket.org/jlouis/witcherconverter

            SBufferInfos bufferInfos = new SBufferInfos();

            // *************** READ CHUNK INFOS ***************
            foreach (var chunk in _file.chunks)
            {
                if (chunk.Type == "CMesh")
                {
                    List <SVertexBufferInfos> vertexBufferInfos = new List <SVertexBufferInfos>();
                    var cookedDatas = chunk.GetVariableByName("cookedData") as CVector;
                    foreach (var cookedData in cookedDatas.variables)
                    {
                        switch (cookedData.Name)
                        {
                        case "renderChunks":
                        {
                            var bytes     = ((CByteArray)cookedData).Bytes;
                            var nbBuffers = bytes[0];
                            int curr      = 1;
                            for (uint i = 0; i < nbBuffers; i++)
                            {
                                SVertexBufferInfos buffInfo = new SVertexBufferInfos();

                                curr += 1;         // Unknown
                                buffInfo.verticesCoordsOffset = bytes.SubArray(ref curr, 4).GetUint();
                                buffInfo.uvOffset             = bytes.SubArray(ref curr, 4).GetUint();
                                buffInfo.normalsOffset        = bytes.SubArray(ref curr, 4).GetUint();

                                curr += 9;         // Unknown
                                buffInfo.indicesOffset = bytes.SubArray(ref curr, 4).GetUint();
                                curr += 1;         // 0x1D

                                buffInfo.nbVertices = bytes.SubArray(ref curr, 2).GetUshort();
                                buffInfo.nbIndices  = bytes.SubArray(ref curr, 4).GetUint();
                                curr        += 3;                                     // Unknown
                                buffInfo.lod = bytes.SubArray(ref curr, 1).GetByte(); // lod ?

                                vertexBufferInfos.Add(buffInfo);
                            }
                            break;
                        }

                        case "indexBufferOffset":
                        {
                            bufferInfos.indexBufferOffset = uint.Parse(cookedData.ToString());
                            break;
                        }

                        case "indexBufferSize":
                        {
                            bufferInfos.indexBufferSize = uint.Parse(cookedData.ToString());
                            break;
                        }

                        case "vertexBufferOffset":
                        {
                            bufferInfos.vertexBufferOffset = uint.Parse(cookedData.ToString());
                            break;
                        }

                        case "vertexBufferSize":
                        {
                            bufferInfos.vertexBufferSize = uint.Parse(cookedData.ToString());
                            break;
                        }

                        case "quantizationOffset":
                        {
                            bufferInfos.quantizationOffset.X = float.Parse((cookedData as CVector).variables[0].ToString());
                            bufferInfos.quantizationOffset.Y = float.Parse((cookedData as CVector).variables[1].ToString());
                            bufferInfos.quantizationOffset.Z = float.Parse((cookedData as CVector).variables[2].ToString());
                            break;
                        }

                        case "quantizationScale":
                        {
                            bufferInfos.quantizationScale.X = float.Parse((cookedData as CVector).variables[0].ToString());
                            bufferInfos.quantizationScale.Y = float.Parse((cookedData as CVector).variables[1].ToString());
                            bufferInfos.quantizationScale.Z = float.Parse((cookedData as CVector).variables[2].ToString());
                            break;
                        }

                        case "bonePositions":
                        {
                            foreach (CVector item in cookedData as CArray)
                            {
                                if (item.variables.Count == 4)
                                {
                                    Vector3Df pos = new Vector3Df();
                                    pos.X = (item.variables[0] as CFloat).val;
                                    pos.Y = (item.variables[1] as CFloat).val;
                                    pos.Z = (item.variables[2] as CFloat).val;
                                    bonePositions.Add(pos);
                                }
                            }
                            break;
                        }
                        }
                    }
                    bufferInfos.verticesBuffer = vertexBufferInfos;
                    var meshChunks = chunk.GetVariableByName("chunks") as CArray;
                    foreach (var meshChunk in meshChunks.array)
                    {
                        SMeshInfos meshInfo = new SMeshInfos();
                        foreach (var mesh in (meshChunk as CVector).variables)
                        {
                            switch (mesh.Name)
                            {
                            case "numVertices":
                            {
                                meshInfo.numVertices = uint.Parse(mesh.ToString());
                                break;
                            }

                            case "numIndices":
                            {
                                meshInfo.numIndices = uint.Parse(mesh.ToString());
                                break;
                            }

                            case "numBonesPerVertex":
                            {
                                meshInfo.numBonesPerVertex = uint.Parse(mesh.ToString());
                                break;
                            }

                            case "firstVertex":
                            {
                                meshInfo.firstVertex = uint.Parse(mesh.ToString());
                                break;
                            }

                            case "firstIndex":
                            {
                                meshInfo.firstIndex = uint.Parse(mesh.ToString());
                                break;
                            }

                            case "vertexType":
                            {
                                if ((mesh as CName).Value == "MVT_StaticMesh")
                                {
                                    meshInfo.vertexType = SMeshInfos.EMeshVertexType.EMVT_STATIC;
                                }
                                else if ((mesh as CName).Value == "MVT_SkinnedMesh")
                                {
                                    meshInfo.vertexType = SMeshInfos.EMeshVertexType.EMVT_SKINNED;
                                }
                                break;
                            }

                            case "materialID":
                            {
                                meshInfo.materialID = uint.Parse(mesh.ToString());
                                break;
                            }
                            }
                        }
                        meshInfos.Add(meshInfo);
                    }
                }
                else if (chunk.Type == "CMaterialInstance")
                {
                    materialInstances.Add(chunk.data as CMaterialInstance);
                }
            }

            // *************** READ MESH BUFFER INFOS ***************
            foreach (var meshInfo in meshInfos)
            {
                SVertexBufferInfos vBufferInf = new SVertexBufferInfos();
                uint nbVertices        = 0;
                uint firstVertexOffset = 0;
                uint nbIndices         = 0;
                uint firstIndiceOffset = 0;
                for (int i = 0; i < bufferInfos.verticesBuffer.Count; i++)
                {
                    nbVertices += bufferInfos.verticesBuffer[i].nbVertices;
                    if (nbVertices > meshInfo.firstVertex)
                    {
                        vBufferInf = bufferInfos.verticesBuffer[i];
                        // the index of the first vertex in the buffer
                        firstVertexOffset = meshInfo.firstVertex - (nbVertices - vBufferInf.nbVertices);
                        break;
                    }
                }
                for (int i = 0; i < bufferInfos.verticesBuffer.Count; i++)
                {
                    nbIndices += bufferInfos.verticesBuffer[i].nbIndices;
                    if (nbIndices > meshInfo.firstIndex)
                    {
                        vBufferInf        = bufferInfos.verticesBuffer[i];
                        firstIndiceOffset = meshInfo.firstIndex - (nbIndices - vBufferInf.nbIndices);
                        break;
                    }
                }

                using (StreamReader sr = new StreamReader(_file.FileName + ".1.buffer"))
                {
                    uint vertexSize = 8;
                    if (meshInfo.vertexType == SMeshInfos.EMeshVertexType.EMVT_SKINNED)
                    {
                        vertexSize += meshInfo.numBonesPerVertex * 2;
                    }

                    sr.BaseStream.Seek(vBufferInf.verticesCoordsOffset + firstVertexOffset * vertexSize, SeekOrigin.Begin);

                    List <Vertex3D> vertex3DCoords = new List <Vertex3D>();
                    Color           defaultColor   = new Color(255, 255, 255, 255);
                    for (int i = 0; i < meshInfo.numVertices; i++)
                    {
                        ushort x, y, z, w;

                        byte[] buff = new byte[2];
                        sr.BaseStream.Read(buff, 0, 2);
                        x = buff.GetUshort();
                        sr.BaseStream.Read(buff, 0, 2);
                        y = buff.GetUshort();
                        sr.BaseStream.Read(buff, 0, 2);
                        z = buff.GetUshort();
                        sr.BaseStream.Read(buff, 0, 2);
                        w = buff.GetUshort();

                        // skip skinning data
                        if (meshInfo.vertexType == SMeshInfos.EMeshVertexType.EMVT_SKINNED)
                        {
                            sr.BaseStream.Seek(meshInfo.numBonesPerVertex * 2, SeekOrigin.Current);
                        }

                        Vertex3D vertex3DCoord = new Vertex3D();
                        vertex3DCoord.Position = new Vector3Df(x, y, z) / 65535f * bufferInfos.quantizationScale + bufferInfos.quantizationOffset;
                        vertex3DCoord.Color    = defaultColor;
                        vertex3DCoords.Add(vertex3DCoord);
                    }

                    sr.BaseStream.Seek(vBufferInf.uvOffset + firstVertexOffset * 4, SeekOrigin.Begin);

                    for (int i = 0; i < meshInfo.numVertices; i++)
                    {
                        ushort u, v;

                        byte[] buff = new byte[2];
                        sr.BaseStream.Read(buff, 0, 2);
                        u = buff.GetUshort();
                        sr.BaseStream.Read(buff, 0, 2);
                        v = buff.GetUshort();

                        float uf = u.ToFloat();
                        float vf = v.ToFloat();

                        Vertex3D vertex3DCoord = vertex3DCoords[i];
                        vertex3DCoord.TCoords = new Vector2Df(uf, vf);
                        vertex3DCoords[i]     = vertex3DCoord;
                    }

                    // Indices -------------------------------------------------------------------
                    sr.BaseStream.Seek(bufferInfos.indexBufferOffset + vBufferInf.indicesOffset + firstIndiceOffset * 2, SeekOrigin.Begin);

                    List <ushort> indices = new List <ushort>();
                    for (int i = 0; i < meshInfo.numIndices; i++)
                    {
                        indices.Add(0);
                    }

                    for (int i = 0; i < meshInfo.numIndices; i++)
                    {
                        ushort index;

                        byte[] buff = new byte[2];
                        sr.BaseStream.Read(buff, 0, 2);
                        index = buff.GetUshort();

                        // Indice need to be inversed for the normals
                        if (i % 3 == 0)
                        {
                            indices[i] = index;
                        }
                        else if (i % 3 == 1)
                        {
                            indices[i + 1] = index;
                        }
                        else if (i % 3 == 2)
                        {
                            indices[i - 1] = index;
                        }
                    }

                    MeshBuffer meshBuff = MeshBuffer.Create(VertexType.Standard, IndexType._16Bit);
                    staticMesh.AddMeshBuffer(meshBuff);
                    meshBuff.Append(vertex3DCoords, indices);
                    meshBuff.RecalculateBoundingBox();
                    meshBuff.Drop();
                }
            }

            // *************** READ RIG DATA ***************
            if (RigFile != null)
            {
                foreach (var chunk in RigFile.chunks)
                {
                    if (chunk.Type == "CSkeleton")
                    {
                        var bones = chunk.GetVariableByName("bones") as CArray;
                        meshSkeleton.nbBones = (uint)bones.array.Count;
                        foreach (CVector bone in bones)
                        {
                            var boneName = bone.variables.GetVariableByName("nameAsCName") as CName;
                            meshSkeleton.names.Add(boneName.Value);
                        }
                        var parentIndices = chunk.GetVariableByName("parentIndices") as CArray;
                        foreach (CVariable parentIndex in parentIndices)
                        {
                            meshSkeleton.parentIdx.Add(short.Parse(parentIndex.ToString()));
                        }

                        var unknownBytes = chunk.unknownBytes.Bytes;
                        int currPos      = 0;
                        for (uint i = 0; i < meshSkeleton.nbBones; i++)
                        {
                            Vector3Df position = new Vector3Df();
                            position.X = unknownBytes.SubArray(ref currPos, 4).GetFloat();
                            position.Y = unknownBytes.SubArray(ref currPos, 4).GetFloat();
                            position.Z = unknownBytes.SubArray(ref currPos, 4).GetFloat();
                            unknownBytes.SubArray(ref currPos, 4).GetFloat(); // the w component

                            Quaternion orientation = new Quaternion();
                            orientation.X = unknownBytes.SubArray(ref currPos, 4).GetFloat();
                            orientation.Y = unknownBytes.SubArray(ref currPos, 4).GetFloat();
                            orientation.Z = unknownBytes.SubArray(ref currPos, 4).GetFloat();
                            orientation.W = unknownBytes.SubArray(ref currPos, 4).GetFloat();

                            Vector3Df scale;
                            scale.X = unknownBytes.SubArray(ref currPos, 4).GetFloat();
                            scale.Y = unknownBytes.SubArray(ref currPos, 4).GetFloat();
                            scale.Z = unknownBytes.SubArray(ref currPos, 4).GetFloat();
                            unknownBytes.SubArray(ref currPos, 4).GetFloat(); // the w component

                            Matrix posMat = new Matrix();
                            posMat.Translation = position;

                            Matrix    rotMat = new Matrix();
                            Vector3Df euler  = orientation.ToEuler();
                            // chechNaNErrors(euler);

                            rotMat.SetRotationRadians(euler);

                            Matrix scaleMat = new Matrix();
                            scaleMat.Scale = scale;

                            Matrix localTransform = posMat * rotMat * scaleMat;
                            orientation = orientation.MakeInverse();
                            meshSkeleton.matrix.Add(localTransform);
                            meshSkeleton.positions.Add(position);
                            meshSkeleton.rotations.Add(orientation);
                            meshSkeleton.scales.Add(scale);
                        }
                    }
                }
            }
        }