Ejemplo n.º 1
0
        private bool IsNeighborEmpty(
            ChunkPaletteStorage <Block>[,,] storages,
            int x, int y, int z, BlockFacing facing)
        {
            var cx = 1; var cy = 1; var cz = 1;

            switch (facing)
            {
            case BlockFacing.East: x += 1; if (x >= 16)
                {
                    cx += 1;
                }
                break;

            case BlockFacing.West: x -= 1; if (x < 0)
                {
                    cx -= 1;
                }
                break;

            case BlockFacing.Up: y += 1; if (y >= 16)
                {
                    cy += 1;
                }
                break;

            case BlockFacing.Down: y -= 1; if (y < 0)
                {
                    cy -= 1;
                }
                break;

            case BlockFacing.South: z += 1; if (z >= 16)
                {
                    cz += 1;
                }
                break;

            case BlockFacing.North: z -= 1; if (z < 0)
                {
                    cz -= 1;
                }
                break;
            }
            return(storages[cx, cy, cz]?[x & 0b1111, y & 0b1111, z & 0b1111].Prototype.IsNone ?? true);
Ejemplo n.º 2
0
        public Mesh?Generate(ChunkPos chunkPos)
        {
            var storages = new ChunkPaletteStorage <Block> [3, 3, 3];

            foreach (var(x, y, z) in Neighbors.ALL.Prepend(Neighbor.None))
            {
                if (_chunkStore.TryGetEntityID(chunkPos.Add(x, y, z), out var neighborID))
                {
                    if (_storageStore.TryGet(neighborID, out var storage))
                    {
                        storages[x + 1, y + 1, z + 1] = storage;
                    }
                }
            }
            var centerStorage = storages[1, 1, 1];

            var indexCount  = 0;
            var vertexCount = 0;

            for (var x = 0; x < 16; x++)
            {
                for (var y = 0; y < 16; y++)
                {
                    for (var z = 0; z < 16; z++)
                    {
                        var block = centerStorage[x, y, z];
                        if (block.Prototype.IsNone)
                        {
                            continue;
                        }

                        var blockVertex = new Vector3(x, y, z);
                        var textureCell = _textureCellStore.Get(block.Prototype.ID);

                        foreach (var facing in BlockFacings.ALL)
                        {
                            if (!IsNeighborEmpty(storages, x, y, z, facing))
                            {
                                continue;
                            }

                            if (_indices.Length <= indexCount + 6)
                            {
                                Array.Resize(ref _indices, _indices.Length << 1);
                            }
                            if (_vertices.Length <= vertexCount + 4)
                            {
                                Array.Resize(ref _vertices, _vertices.Length << 1);
                                Array.Resize(ref _normals, _vertices.Length << 1);
                                Array.Resize(ref _uvs, _vertices.Length << 1);
                            }

                            for (var i = 0; i < TRIANGLE_INDICES.Length; i++)
                            {
                                _indices[indexCount++] = (ushort)(vertexCount + TRIANGLE_INDICES[i]);
                            }

                            var normal = facing.ToVector3();
                            for (var i = 0; i < 4; i++)
                            {
                                var offset = OFFSET_PER_FACING[(int)facing][i];
                                _vertices[vertexCount] = blockVertex + offset;
                                _normals[vertexCount]  = normal;
                                _uvs[vertexCount]      = i switch {
                                    0 => textureCell.TopLeft,
                                    1 => textureCell.BottomLeft,
                                    2 => textureCell.BottomRight,
                                    3 => textureCell.TopRight,
                                    _ => throw new InvalidOperationException()
                                };
                                vertexCount++;
                            }
                        }
                    }
                }
            }

            return((indexCount > 0)
                                ? _meshManager.Create(
                       _indices.AsSpan(0, indexCount), _vertices.AsSpan(0, vertexCount),
                       _normals.AsSpan(0, vertexCount), _uvs.AsSpan(0, vertexCount))
                                : (Mesh?)null);
        }
Ejemplo n.º 3
0
        protected override void OnLoad()
        {
            base.OnLoad();
            var(mainCamera, _) = GetAll <Camera>().First();
            Set(mainCamera, (Transform)Matrix4x4.CreateTranslation(0, 26, 0));

            var meshManager = Processors.GetOrThrow <MeshManager>();
            var heartMesh   = meshManager.Load(this, "heart.glb");
            var swordMesh   = meshManager.Load(this, "sword.glb");

            for (var x = -12; x <= 12; x++)
            {
                for (var z = -12; z <= 12; z++)
                {
                    var entity   = Entities.New();
                    var position = Matrix4x4.CreateTranslation(x * 2, 24, z * 2);
                    var rotation = Matrix4x4.CreateRotationY(RND.NextFloat(MathF.PI * 2));
                    Set(entity, (Transform)(rotation * position));
                    Set(entity, RND.Pick(heartMesh, swordMesh));
                }
            }

            var textureManager = Processors.GetOrThrow <TextureManager>();
            var texture        = textureManager.Load(this, "terrain.png");

            var stone = Entities.New();
            var dirt  = Entities.New();
            var grass = Entities.New();

            Set(stone, TextureCoords4.FromGrid(4, 4, 1, 0));
            Set(dirt, TextureCoords4.FromGrid(4, 4, 2, 0));
            Set(grass, TextureCoords4.FromGrid(4, 4, 3, 0));


            void CreateChunk(ChunkPos pos)
            {
                var chunk   = Entities.New();
                var storage = new ChunkPaletteStorage <Block>(default(Block));

                for (var x = 0; x < 16; x++)
                {
                    for (var y = 0; y < 16; y++)
                    {
                        for (var z = 0; z < 16; z++)
                        {
                            var yy = (pos.Y << 4) | y;
                            if (RND.NextBool(0.5 - yy / 48.0))
                            {
                                storage[x, y, z] = new Block((yy > 16) ? grass
                                                                           : (yy > -16) ? dirt
                                                                                        : stone);
                            }
                        }
                    }
                }

                Set(chunk, new Chunk(pos));
                Set(chunk, (Transform)Matrix4x4.CreateTranslation(pos.GetOrigin()));
                Set(chunk, storage);
            }

            var chunkMeshGenerator = new ChunkMeshGenerator(this);
            var chunkStore         = (LookupDictionaryStore <ChunkPos, Chunk>)Components.GetStore <Chunk>();

            void GenerateChunkMesh(ChunkPos pos)
            {
                var chunk     = Entities.GetByID(chunkStore.GetEntityID(pos)) !.Value;
                var chunkMesh = chunkMeshGenerator.Generate(pos);

                if (chunkMesh == null)
                {
                    return;
                }
                Set(chunk, chunkMesh.Value);
                Set(chunk, texture);
            }

            for (var x = -6; x < 6; x++)
            {
                for (var y = -2; y < 2; y++)
                {
                    for (var z = -6; z < 6; z++)
                    {
                        CreateChunk(new ChunkPos(x, y, z));
                    }
                }
            }

            for (var x = -6; x < 6; x++)
            {
                for (var y = -2; y < 2; y++)
                {
                    for (var z = -6; z < 6; z++)
                    {
                        GenerateChunkMesh(new ChunkPos(x, y, z));
                    }
                }
            }
        }