public Block Process(BlockSprite blockSprite)
        {
            var block = new Block();

            var w = blockSprite.Width;
            var h = blockSprite.Height;

            for (int y = 0; y < h; y++)
            {
                for (int x = 0; x < w; x++)
                {
                    var color = blockSprite.GetPixel(x, y);

                    // 透明はその位置に要素がないことを表します。
                    if (color.A == 0) continue;

                    var materialIndex = ProcessMaterial(ref block, ref color);

                    // Block は [-8, 7] で 16x16 になっています。

                    var element = new Element
                    {
                        MaterialIndex = materialIndex,
                        Position = new Position
                        {
                            X = x - 8,
                            Y = 7 - y
                        }
                    };

                    block.Elements.Add(element);
                }
            }

            return block;
        }
            /// <summary>
            /// 指定の Element コレクション内について、指定の Element を解析します。
            /// </summary>
            /// <param name="elements">Element コレクション。</param>
            /// <param name="target">解析対象の Element。</param>
            /// <returns>解析結果の ResolvedElement。</returns>
            public static ResolvedElement Resolve(InterElementCollection elements, Element target)
            {
                var resolvedElement = new ResolvedElement(target);

                var targetPosition = target.Position;
                var testPosition = targetPosition;

                testPosition.X = targetPosition.X + 1;
                resolvedElement.SurfaceVisible[(int) CubeSurfaces.East] = !elements.Contains(testPosition);

                testPosition.X = targetPosition.X - 1;
                resolvedElement.SurfaceVisible[(int) CubeSurfaces.West] = !elements.Contains(testPosition);

                testPosition.X = targetPosition.X;

                testPosition.Y = targetPosition.Y + 1;
                resolvedElement.SurfaceVisible[(int) CubeSurfaces.Top] = !elements.Contains(testPosition);

                testPosition.Y = targetPosition.Y - 1;
                resolvedElement.SurfaceVisible[(int) CubeSurfaces.Bottom] = !elements.Contains(testPosition);

                testPosition.Y = targetPosition.Y;

                testPosition.Z = targetPosition.Z - 1;
                resolvedElement.SurfaceVisible[(int) CubeSurfaces.North] = !elements.Contains(testPosition);

                testPosition.Z = targetPosition.Z + 1;
                resolvedElement.SurfaceVisible[(int) CubeSurfaces.South] = !elements.Contains(testPosition);

                return resolvedElement;
            }
 /// <summary>
 /// インスタンスを生成します。
 /// </summary>
 /// <param name="element">Element。</param>
 ResolvedElement(Element element)
     : this()
 {
     Element = element;
     SurfaceVisible = new bool[6];
 }
Beispiel #4
0
        /// <summary>
        /// 指定された InterBlock の LOD の 1 レベル下位の詳細情報を持つ InterBlock を作成します。
        /// 生成可能な最小の詳細情報を持つ InterBlock のグリッド サイズは 2 です。
        /// </summary>
        /// <param name="highBlock">生成する InterBlock の 1 レベル上位の詳細情報を持つ InterBlock。</param>
        /// <returns>生成された InterBlock。</returns>
        static InterBlock CreateLowDetailLevelInterBlock(InterBlock highBlock)
        {
            if (highBlock.GridSize == 2) throw new ArgumentException("A specified InterBlock has a minimum LOD.");

            var interBlock = new InterBlock();

            // 上位の半分のグリッド数で作成します。
            interBlock.GridSize = highBlock.GridSize / 2;
            interBlock.Materials = highBlock.Materials;
            interBlock.Elements = new InterElementCollection();

            // グリッド位置の最大と最小を計算します。
            int maxGrid = interBlock.GridSize / 2;
            int minGrid = -interBlock.GridSize / 2;

            // 下位は上位 8 グリッドを 1 つのグリッドとします。

            // 判定中に使用する上位 8 グリッドの位置情報を一時的に格納する配列です。
            Position[] hPositions = new Position[8];
            // 判定中に使用する上位 8 グリッドの Material 情報を一時的に格納する配列です。
            int[] hMaterials = new int[8];

            // 上位 8 グリッドずつ判定しながら下位グリッドの情報を決定します。
            for (int z = minGrid; z < maxGrid; z++)
            {
                for (int y = minGrid; y < maxGrid; y++)
                {
                    for (int x = minGrid; x < maxGrid; x++)
                    {
                        int hX = x * 2;
                        int hY = y * 2;
                        int hZ = z * 2;

                        hPositions[0] = new Position(hX, hY, hZ);
                        hPositions[1] = new Position(hX + 1, hY, hZ);
                        hPositions[2] = new Position(hX, hY + 1, hZ);
                        hPositions[3] = new Position(hX + 1, hY + 1, hZ);
                        hPositions[4] = new Position(hX, hY, hZ + 1);
                        hPositions[5] = new Position(hX + 1, hY, hZ + 1);
                        hPositions[6] = new Position(hX, hY + 1, hZ + 1);
                        hPositions[7] = new Position(hX + 1, hY + 1, hZ + 1);

                        for (int i = 0; i < 8; i++)
                        {
                            Element hElement;
                            highBlock.Elements.TryGetItem(hPositions[i], out hElement);
                            hMaterials[i] = (hElement != null) ? hElement.MaterialIndex : -1;
                        }

                        // 出現頻度が最大の Material を調べます。
                        Array.Sort(hMaterials);

                        int maxMaterialIndex = -1;
                        int maxCount = 0;
                        int countingMaterialIndex = -1;
                        int count = 0;
                        for (int i = 0; i < 8; i++)
                        {
                            if (hMaterials[i] == countingMaterialIndex)
                            {
                                count++;
                            }
                            else
                            {
                                if (maxCount <= count)
                                {
                                    maxCount = count;
                                    maxMaterialIndex = countingMaterialIndex;
                                }
                                countingMaterialIndex = hMaterials[i];
                                count = 1;
                            }
                        }
                        // 最後の要素も有効にするために判定します。
                        if (maxCount <= count)
                        {
                            maxCount = count;
                            maxMaterialIndex = countingMaterialIndex;
                        }

                        // 出現頻度が最大の Material で、このグリッドのための Element を作成します。
                        // maxMaterialIndex が -1 の場合はグリッドが空であることを表し、Element を作成しません。
                        if (maxMaterialIndex != -1)
                        {
                            var element = new Element()
                            {
                                MaterialIndex = maxMaterialIndex,
                                Position = new Position(x, y, z)
                            };
                            interBlock.Elements.Add(element);
                        }
                    }
                }
            }

            // Element サイズは上位 InterBlock の 2 倍です。
            interBlock.ElementSize = highBlock.ElementSize * 2;

            return interBlock;
        }
        /// <summary>
        /// 正八面体風のデータを定義する Block を作成します。
        /// </summary>
        /// <returns>作成された Block。</returns>
        Block CreateOctahedronLikeBlock()
        {
            var block = new Block();
            block.Materials = new List<Material>();
            block.Elements = new List<Element>();

            MaterialColor[] diffuses =
            {
                new MaterialColor(255, 255, 255),
                new MaterialColor(255,   0,   0),
                new MaterialColor(  0, 255,   0),
                new MaterialColor(  0,   0, 255),
                new MaterialColor(127, 127,   0),
                new MaterialColor(127,   0, 127),
                new MaterialColor(  0, 127, 127),
                new MaterialColor(  0,   0,   0),
            };
            Material[] materials = new Material[8];
            for (int i = 0; i < 8; i++)
            {
                materials[i] = new Material();
                materials[i].DiffuseColor = diffuses[i];
                block.Materials.Add(materials[i]);
            }

            int materialIndex;
            for (int x = -8; x < 8; x++)
            {
                for (int y = -8; y < 8; y++)
                {
                    for (int z = -8; z < 8; z++)
                    {
                        int testX = (x < 0) ? -x : x + 1;
                        int testY = (y < 0) ? -y : y + 1;
                        int testZ = (z < 0) ? -z : z + 1;

                        if (testX + testY + testZ <= 10)
                        {
                            materialIndex = 0;
                            if (x < 0) materialIndex |= 1;
                            if (y < 0) materialIndex |= 2;
                            if (z < 0) materialIndex |= 4;

                            var element = new Element();
                            element.Position = new Position(x, y, z);
                            element.MaterialIndex = materialIndex;
                            block.Elements.Add(element);
                        }
                    }
                }
            }

            return block;
        }
        /// <summary>
        /// 16 * 16 * 16 の全てを使用した Block を生成します。
        /// </summary>
        Block CreateFullFilledBlock()
        {
            var block = new Block();
            block.Materials = new List<Material>();
            block.Elements = new List<Element>();

            MaterialColor[] diffuses =
            {
                new MaterialColor(255, 255, 255),
                new MaterialColor(255,   0,   0),
                new MaterialColor(  0, 255,   0),
                new MaterialColor(  0,   0, 255),
                new MaterialColor(127, 127,   0),
                new MaterialColor(127,   0, 127),
                new MaterialColor(  0, 127, 127),
                new MaterialColor(  0,   0,   0),
            };
            Material[] materials = new Material[8];
            for (int i = 0; i < 8; i++)
            {
                materials[i] = new Material();
                materials[i].DiffuseColor = diffuses[i];
                block.Materials.Add(materials[i]);
            }

            int materialIndex;
            for (int x = -8; x < 8; x++)
            {
                for (int y = -8; y < 8; y++)
                {
                    for (int z = -8; z < 8; z++)
                    {
                        materialIndex = 0;
                        if (x < 0) materialIndex |= 1;
                        if (y < 0) materialIndex |= 2;
                        if (z < 0) materialIndex |= 4;

                        var element = new Element();
                        element.Position = new Position(x, y, z);
                        element.MaterialIndex = materialIndex;
                        block.Elements.Add(element);
                    }
                }
            }

            return block;
        }
Beispiel #7
0
        public void SetElement(int x, int y, int materialIndex)
        {
            if (x < 0 || gridSize <= x) throw new ArgumentOutOfRangeException("x");
            if (y < 0 || gridSize <= y) throw new ArgumentOutOfRangeException("y");
            if (materialIndex < 0 || workspace.Block.Materials.Count <= materialIndex)
                throw new ArgumentOutOfRangeException("materialIndex");

            var element = elements[x, y];

            if (element == null)
            {
                element = new Element
                {
                    Position = ResolvePosition(x, y),
                    MaterialIndex = materialIndex
                };

                workspace.Block.Elements.Add(element);
                elements[x, y] = element;
            }
            else
            {
                element.MaterialIndex = materialIndex;
            }
        }