示例#1
0
 public MeshExportOptions(Matrix4x4 matrix,
                          MeshNormalExportMode normalExportMode = MeshNormalExportMode.Unchanged,
                          bool invertNormals = false,
                          bool reverseFaceWinding = false) {
   Matrix = matrix;
   NormalExportMode = normalExportMode;
   InvertNormals = invertNormals;
   ReverseFaceWinding = reverseFaceWinding;
 }
示例#2
0
        private IModel ImportMesh(byte[] bytes)
        {
            int stride = 1;
            MeshNormalExportMode shadingMode = MeshNormalExportMode.Unchanged;

            HWBinaryResourceChunk headerChunk =
                GetFirstChunkOfType(HWBinaryResourceChunkType.XTD_XTDHeader);
            float tileScale =
                BinaryUtils.ReadFloatBigEndian(bytes,
                                               (int)headerChunk.Offset + 12);
            HWBinaryResourceChunk atlasChunk =
                GetFirstChunkOfType(HWBinaryResourceChunkType.XTD_AtlasChunk);

            int gridSize =
                (int)Math.Round(Math.Sqrt((atlasChunk.Size - 32) /
                                          8)); // Subtract the min/range vector sizes, divide by position + normal size, and sqrt for grid size
            int positionOffset = (int)atlasChunk.Offset + 32;
            int normalOffset   = positionOffset + gridSize * gridSize * 4;

            if (gridSize % stride != 0)
            {
                throw new Exception(
                          $"Grid size {gridSize} is not evenly divisible by stride {stride} - choose a different stride value.");
            }

            // These are stored as ZYX, 4 bytes per component
            Vector3 PosCompMin = BinaryUtils
                                 .ReadVector3BigEndian(
                bytes, (int)atlasChunk.Offset)
                                 .ReverseComponents();
            Vector3 PosCompRange =
                BinaryUtils
                .ReadVector3BigEndian(bytes, (int)atlasChunk.Offset + 16)
                .ReverseComponents();

            var finModel = new ModelImpl(gridSize * gridSize);
            var finMesh  = finModel.Skin.AddMesh();

            var finVertices = new IVertex[gridSize * gridSize];

            // Read vertex offsets/normals and add them to the mesh
            for (int x = 0; x < gridSize; x += stride)
            {
                for (int z = 0; z < gridSize; z += stride)
                {
                    int index =
                        ConvertGridPositionToIndex(new Tuple <int, int>(x, z), gridSize);
                    int offset = index * 4;


                    // Get offset position and normal for this vertex
                    Vector3 position =
                        ReadVector3Compressed(bytes, positionOffset + offset) *
                        PosCompRange -
                        PosCompMin;

                    // Positions are relative to the terrain grid, so shift them by the grid position
                    position += new Vector3(x, 0, z) * tileScale;

                    Vector3 normal =
                        ConvertDirectionVector(
                            Vector3.Normalize(
                                ReadVector3Compressed(bytes, normalOffset + offset) *
                                2.0f -
                                Vector3.One));

                    // Simple UV based on original, non-warped terrain grid
                    Vector3 texCoord = new Vector3(x / ((float)gridSize - 1),
                                                   z / ((float)gridSize - 1), 0);

                    var finVertex =
                        finModel.Skin
                        .AddVertex(position.X, position.Y, position.Z)
                        .SetLocalNormal(normal.X, normal.Y, normal.Z)
                        .SetUv(texCoord.X, texCoord.Y);
                    finVertices[GetVertexIndex(x, z, gridSize)] = finVertex;
                }
            }

            // Generate faces based on terrain grid
            for (int x = 0; x < gridSize - stride; x += stride)
            {
                var triangles = new List <(IVertex, IVertex, IVertex)>();

                for (int z = 0; z < gridSize - stride; z += stride)
                {
                    var a = finVertices[GetVertexIndex(x, z, gridSize)];
                    var b = finVertices[GetVertexIndex(x + stride, z, gridSize)];
                    var c = finVertices[GetVertexIndex(x, z + stride, gridSize)];
                    var d = finVertices[GetVertexIndex(x + stride, z + stride, gridSize)];

                    triangles.Add((a, b, c));
                    triangles.Add((d, c, b));
                }

                finMesh.AddTriangles(triangles.ToArray());
                triangles.Clear();
            }

            return(finModel);
        }