Exemple #1
0
        public ChunkBlock GetNeighbor(Side side)
        {
            if (chunk == null)
                throw new InvalidOperationException("Chunk is null.");

            ChunkBlock neighbor;

            neighbor.chunk = chunk;
            neighbor.position = position + side.Direction;

            if (!neighbor.chunk.Contains(neighbor.position))
            {
                neighbor.chunk = chunk.GetNeighborChunk(side);
                neighbor.position += chunk.Size * side.Reverse().Direction;
            }

            return neighbor;
        }
        float CalculateAmbientOcclusion(ref ChunkBlock chunkBlock, Side side)
        {
            const float occlusionPerFace = 1 / 5f;

            // 1 は一切遮蔽されていない状態を表す。
            float occlustion = 1;

            var mySide = side.Reverse();

            // 面隣接ブロックに対して面隣接ブロックが存在する場合、遮蔽と判定。
            for (int i = 0; i < Side.Count; i++)
            {
                var s = Side.Items[i];

                // 自身に対する方向はスキップ。
                if (mySide == s) continue;

                // 遮蔽ブロック位置。
                var occluderBlockLocation = chunkBlock.GetNeighbor(s);

                // 遮蔽ブロック インデックス。
                var occluderBlockIndex = occluderBlockLocation.GetBlockIndex();

                // 未定と空の場合は非遮蔽。
                if (occluderBlockIndex == null || occluderBlockIndex == Block.EmptyIndex) continue;

                // ブロック情報を取得。
                var occluderBlock = Chunk.Region.BlockCatalog[occluderBlockIndex.Value];

                // 対象とする面が存在しない場合は非遮蔽。
                if (occluderBlock.Mesh.MeshParts[s.Reverse()] == null) continue;

                // 流体ブロックは非遮蔽。
                if (occluderBlock.Fluid) continue;

                // 半透明ブロックは非遮蔽。
                if (occluderBlock.Translucent) continue;

                // 遮蔽度で減算。
                occlustion -= occlusionPerFace;
            }

            return occlustion;
        }