Exemplo n.º 1
0
    public static void Export(string path, BlockGroup blockGroup)
    {
        var blockMeshes = new BlockMeshMerger();

        foreach (var block in blockGroup.GetAllBlocks())
        {
            block.WriteToMesh(blockGroup, blockMeshes);
        }

        string dataName = Path.GetFileNameWithoutExtension(path);

        var writer = new StringWriter();

        writer.WriteLine("#Created by Tsumiki Editor");
        writer.WriteLine("");
        writer.WriteLine("mtllib " + dataName + ".mtl");
        writer.WriteLine("");

        // Output Vertices
        foreach (Vector3 v in blockMeshes.vertexPos)
        {
            writer.WriteLine("v " + v.x + " " + v.y + " " + v.z);
        }
        writer.WriteLine("# " + blockMeshes.vertexPos.Count + " vertices");

        // Output Texture Vertices
        foreach (Vector2 vt in blockMeshes.vertexUv)
        {
            writer.WriteLine("vt " + vt.x + " " + (1.0f - vt.y));
        }
        writer.WriteLine("# " + blockMeshes.vertexUv.Count + " texture vertices");

        // Output Faces
        writer.WriteLine("usemtl mat1");
        int facesCount = blockMeshes.triangles.Count / 3;

        for (int i = 0; i < facesCount; i++)
        {
            int i0 = blockMeshes.triangles[i * 3 + 0] + 1;
            int i1 = blockMeshes.triangles[i * 3 + 1] + 1;
            int i2 = blockMeshes.triangles[i * 3 + 2] + 1;
            writer.WriteLine("f " + i0 + "/" + i0 + " " + i1 + "/" + i1 + " " + i2 + "/" + i2);
        }
        writer.WriteLine("# " + blockMeshes.vertexUv.Count + " texture vertices");

        File.WriteAllText(path, writer.ToString(), Encoding.ASCII);
        writer.Dispose();

        // Output Materials
        var mtlWriter = new StringWriter();

        mtlWriter.WriteLine("newmtl mat1");
        mtlWriter.WriteLine("Ka 0.00000 0.00000 0.00000");
        mtlWriter.WriteLine("Kd 0.00000 0.00000 0.00000");
        mtlWriter.WriteLine("Ks 0.00000 0.00000 0.00000");
        mtlWriter.WriteLine("Ns 0.00000");

        File.WriteAllText(Path.ChangeExtension(path, ".mtl"), mtlWriter.ToString(), Encoding.ASCII);
        mtlWriter.Dispose();
    }
Exemplo n.º 2
0
    // ガイド用メッシュを出力
    public void WriteToGuideMesh(BlockGroup blockGroup, BlockMeshMerger mesh)
    {
        BlockShape shape = this.shape;

        bool vertexHasWrote = false;

        for (int i = 0; i < 6; i++)
        {
            // 隣のブロックに完全に覆われていたら省略する
            if (this.IsOcculuded(blockGroup, (BlockDirection)i))
            {
                continue;
            }

            // 壁タイプのガイドは限定的にする
            if (shape.wall > 0)
            {
                int index = this.ToLocalDirection(i);
                if (shape.wall >= 1 && (BlockDirection)index == BlockDirection.Zplus)
                {
                }
                else if (shape.wall >= 2 && (BlockDirection)index == BlockDirection.Xplus)
                {
                }
                else
                {
                    continue;
                }
            }

            // 頂点が書き出されていなければここで書き出す
            if (!vertexHasWrote)
            {
                for (int j = 0; j < EditUtil.cubeVertices.Length; j++)
                {
                    mesh.vertexPos.Add(this.position + EditUtil.cubeVertices[j]);
                }
                vertexHasWrote = true;
            }

            int offset = mesh.vertexPos.Count - EditUtil.cubeVertices.Length;
            mesh.triangles.Add(offset + EditUtil.cubeQuadIndices[i * 4 + 0]);
            mesh.triangles.Add(offset + EditUtil.cubeQuadIndices[i * 4 + 1]);
            mesh.triangles.Add(offset + EditUtil.cubeQuadIndices[i * 4 + 2]);
            mesh.triangles.Add(offset + EditUtil.cubeQuadIndices[i * 4 + 0]);
            mesh.triangles.Add(offset + EditUtil.cubeQuadIndices[i * 4 + 2]);
            mesh.triangles.Add(offset + EditUtil.cubeQuadIndices[i * 4 + 3]);
        }
    }
Exemplo n.º 3
0
    // 表示用メッシュを出力
    public void WriteToMesh(BlockGroup blockGroup, BlockMeshMerger meshMerger)
    {
        BlockShape shape = this.shape;

        if (shape.autoPlacement)
        {
            // 自動配置ブロックの処理
            WriteToMeshAutoPlacement(blockGroup, meshMerger);
        }
        else
        {
            // 6方向ブロックメッシュ
            WriteToMeshStandard(blockGroup, meshMerger);
        }
    }
Exemplo n.º 4
0
    // ルート用メッシュを出力
    public void WriteToRouteMesh(BlockGroup blockGroup, BlockMeshMerger mesh)
    {
        if (!this.IsEnterable(blockGroup))
        {
            return;
        }

        int offset = mesh.vertexPos.Count;

        for (int j = 0; j < 4; j++)
        {
            int     index  = EditUtil.ReversePanelVertexIndex(j, this.direction);
            Vector3 vertex = EditUtil.panelVertices[j];
            vertex.y = this.shape.panelVertices[index] * 0.5f - 0.25f;
            vertex   = EditManager.Instance.ToWorldCoordinate(vertex);
            mesh.vertexPos.Add(this.position + vertex);
        }

        if (this.direction == BlockDirection.Xplus ||
            this.direction == BlockDirection.Xminus
            )
        {
            mesh.triangles.Add(offset + 0);
            mesh.triangles.Add(offset + 2);
            mesh.triangles.Add(offset + 1);
            mesh.triangles.Add(offset + 1);
            mesh.triangles.Add(offset + 2);
            mesh.triangles.Add(offset + 3);
        }
        else
        {
            mesh.triangles.Add(offset + 0);
            mesh.triangles.Add(offset + 3);
            mesh.triangles.Add(offset + 1);
            mesh.triangles.Add(offset + 0);
            mesh.triangles.Add(offset + 2);
            mesh.triangles.Add(offset + 3);
        }
    }
Exemplo n.º 5
0
    // 6方向ブロックメッシュ
    public void WriteToMeshNormal(BlockGroup blockGroup, BlockMeshMerger meshMerger)
    {
        BlockShape shape = this.shape;

        for (int i = 0; i < shape.meshes.Length; i++)
        {
            int index = this.ToLocalDirection(i);

            var mesh = shape.meshes[index];
            if (mesh == null)
            {
                continue;
            }

            // 隣のブロックに完全に覆われていたら省略する
            if (i < 6 && this.CheckOcculusion(blockGroup, (BlockDirection)i))
            {
                continue;
            }

            meshMerger.Merge(mesh, this.position, this.direction, this.textureChips[index], i);
        }
    }
Exemplo n.º 6
0
    // 自動配置ブロックの処理
    public void WriteToMeshAutoPlacement(BlockGroup blockGroup, BlockMeshMerger meshMerger)
    {
        BlockShape shape = this.shape;
        // 隣接ブロックを取得
        var list = new Vector3[] {
            new Vector3(0, 0, 1), new Vector3(1, 0, 0), new Vector3(0, 0, -1), new Vector3(-1, 0, 0),
            new Vector3(1, 0, 1), new Vector3(1, 0, -1), new Vector3(-1, 0, -1), new Vector3(-1, 0, 1),
            new Vector3(0, 0.5f, 0),
            new Vector3(0, 0.5f, 1), new Vector3(1, 0.5f, 0), new Vector3(0, 0.5f, -1), new Vector3(-1, 0.5f, 0),
        };

        int pattern = 0;

        for (int i = 0; i < list.Length; i++)
        {
            var block = blockGroup.GetBlock(position + EditManager.Instance.ToWorldCoordinate(list[i]));
            if (block != null)
            {
                pattern |= (1 << i);
            }
        }

        for (int i = 0; i < 4; i++)
        {
            bool s1 = (pattern & (1 << (i))) != 0;                          // 隣接1
            bool s2 = (pattern & (1 << ((i + 1) % 4))) != 0;                // 隣接2
            bool s3 = (pattern & (1 << (i + 4))) != 0;                      // 斜め隣接
            bool s4 = (pattern & (1 << 8)) != 0;                            // 上隣接
            bool s5 = (pattern & (1 << (9 + i))) != 0;                      // 上横隣接1
            bool s6 = (pattern & (1 << (9 + (i + 1) % 4))) != 0;            // 上横隣接2

            int meshOffset;
            if (s3)
            {
                if (s1 && s2)
                {
                    meshOffset = (s4 && (s5 || s6)) ? -1 : 0;
                }
                else if (s1)
                {
                    meshOffset = (s4) ? (s5) ? 24 : 32 : 8;
                }
                else if (s2)
                {
                    meshOffset = (s4) ? (s6) ? 28 : 36 : 12;
                }
                else
                {
                    meshOffset = (s4) ? 20 : 4;
                }
            }
            else
            {
                if (s1 && s2)
                {
                    meshOffset = 16;
                }
                else if (s1)
                {
                    meshOffset = (s4) ? (s5) ? 24 : 32 : 8;
                }
                else if (s2)
                {
                    meshOffset = (s4) ? (s6) ? 28 : 36 : 12;
                }
                else
                {
                    meshOffset = (s4) ? 20 : 4;
                }
            }
            if (meshOffset < 0)
            {
                continue;
            }

            var mesh = shape.meshes[6 + meshOffset + i];
            if (mesh == null)
            {
                continue;
            }

            meshMerger.Merge(mesh, this.position, this.direction, Vector3.one,
                             shape.divideChipVert, this.textureChips[6], 0);
        }
    }
Exemplo n.º 7
0
    // 6方向ブロックメッシュ
    public void WriteToMeshStandard(BlockGroup blockGroup, BlockMeshMerger meshMerger)
    {
        BlockShape shape = this.shape;

        for (int i = 0; i < shape.meshes.Length; i++)
        {
            int index = this.ToLocalDirection(i);

            var mesh = shape.meshes[index];
            if (mesh == null)
            {
                continue;
            }

            // 隣のブロックに完全に覆われていたら省略する
            if (i < 6 && this.IsOcculuded(blockGroup, (BlockDirection)i))
            {
                continue;
            }

            // 一番下の底面は省略する
            if ((BlockDirection)i == BlockDirection.Yminus && this.position.y == 0.0f)
            {
                continue;
            }

            Vector3 position = this.position;
            Vector3 scale    = Vector3.one;
            // 側面パネルの場合は分割する
            bool divideChipVert = shape.divideChipVert && i < 6 &&
                                  (BlockDirection)i != BlockDirection.Yplus &&
                                  (BlockDirection)i != BlockDirection.Yminus;
            if (divideChipVert && this.IsCombinable((BlockDirection)i))
            {
                BlockDirection direction = (BlockDirection)i;
                // 上下に2個続いているブロックをまとめる
                if (this.position.y - Math.Floor(this.position.y) >= 0.5f)
                {
                    Block neighborBlock = blockGroup.GetBlock(this.position - new Vector3(0, 0.5f, 0));
                    if (neighborBlock != null && neighborBlock.IsCombinable(direction) &&
                        this.GetTextureChip(direction) == neighborBlock.GetTextureChip(direction))
                    {
                        divideChipVert = false;
                        position.y    -= 0.25f;
                        scale.y        = 2.0f;
                    }
                }
                else
                {
                    Block neighborBlock = blockGroup.GetBlock(this.position + new Vector3(0, 0.5f, 0));
                    if (neighborBlock != null && neighborBlock.IsCombinable(direction) &&
                        this.GetTextureChip(direction) == neighborBlock.GetTextureChip(direction))
                    {
                        if (!neighborBlock.IsOcculuded(blockGroup, direction))
                        {
                            continue;
                        }
                    }
                }
            }

            meshMerger.Merge(mesh, position, this.direction, scale,
                             divideChipVert, this.textureChips[index], i);
        }
    }