Archived
Private
Public Access
1
0
This repository has been archived on 2026-02-04. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
2022-11-12 13:10:03 +01:00

152 lines
5.6 KiB
C#

using System.Collections.Generic;
using UnityEngine;
namespace Assets.Scripts {
public class Chunk {
public ChunkCoord coord;
private GameObject _chunkObject;
private MeshRenderer _meshRenderer;
private MeshFilter _meshFilter;
private int _vertexIndex = 0;
private readonly List<Vector3> _vertices = new List<Vector3>();
private readonly List<int> _triangles = new List<int>();
private readonly List<Vector2> _uvs = new List<Vector2>();
private readonly byte[,,] _voxelMap = new byte[VoxelData.ChunkWidth, VoxelData.ChunkHeight, VoxelData.ChunkWidth];
private World _world;
public Chunk(ChunkCoord _coord, World world) {
coord = _coord;
_world = world;
_chunkObject = new GameObject();
_meshFilter = _chunkObject.AddComponent<MeshFilter>();
_meshRenderer = _chunkObject.AddComponent<MeshRenderer>();
_meshRenderer.material = _world.material;
_chunkObject.transform.SetParent(_world.transform);
_chunkObject.transform.position =
new Vector3(coord.x * VoxelData.ChunkWidth, 0, coord.z * VoxelData.ChunkWidth);
_chunkObject.name = "Chunk [" + coord.x + ":" + coord.z + "]";
PopulateVoxelMap();
CreateMeshData();
CreateMesh();
}
private void PopulateVoxelMap() {
for (int y = 0; y < VoxelData.ChunkHeight; y++) {
for (int x = 0; x < VoxelData.ChunkWidth; x++) {
for (int z = 0; z < VoxelData.ChunkWidth; z++) {
_voxelMap[x, y, z] = _world.GenerateBlock(new Vector3(x, y, z) + Position);
}
}
}
}
private void CreateMeshData() {
for (int y = 0; y < VoxelData.ChunkHeight; y++) {
for (int x = 0; x < VoxelData.ChunkWidth; x++) {
for (int z = 0; z < VoxelData.ChunkWidth; z++) {
if (!_world.blockTypes[_voxelMap[x, y, z]].isSolid) continue;
AddVoxelDataToChunk(new Vector3(x, y, z));
}
}
}
}
public bool IsActive {
get { return _chunkObject.activeSelf; }
set { _chunkObject.SetActive(value); }
}
public Vector3 Position {
get { return _chunkObject.transform.position; }
}
private bool CheckVoxel(Vector3 pos) {
int x = Mathf.FloorToInt(pos.x);
int y = Mathf.FloorToInt(pos.y);
int z = Mathf.FloorToInt(pos.z);
if (!IsVoxelInChunk(x, y, z))
return _world.blockTypes[_world.GenerateBlock(pos + Position)].isSolid;
return _world.blockTypes[_voxelMap[x, y, z]].isSolid;
}
private void AddVoxelDataToChunk(Vector3 pos) {
for (int p = 0; p < 6; p++) {
if (CheckVoxel(pos + VoxelData.FaceChecks[p])) continue;
byte blockID = _voxelMap[(int)pos.x, (int)pos.y, (int)pos.z];
_vertices.Add(pos + VoxelData.VoxelVerts[VoxelData.VoxelTris[p, 0]]);
_vertices.Add(pos + VoxelData.VoxelVerts[VoxelData.VoxelTris[p, 1]]);
_vertices.Add(pos + VoxelData.VoxelVerts[VoxelData.VoxelTris[p, 2]]);
_vertices.Add(pos + VoxelData.VoxelVerts[VoxelData.VoxelTris[p, 3]]);
AddTexture(_world.blockTypes[blockID].GetTextureID(p));
_triangles.Add(_vertexIndex);
_triangles.Add(_vertexIndex + 1);
_triangles.Add(_vertexIndex + 2);
_triangles.Add(_vertexIndex + 2);
_triangles.Add(_vertexIndex + 1);
_triangles.Add(_vertexIndex + 3);
_vertexIndex += 4;
}
}
private void CreateMesh() {
Mesh mesh = new Mesh();
mesh.vertices = _vertices.ToArray();
mesh.triangles = _triangles.ToArray();
mesh.uv = _uvs.ToArray();
mesh.RecalculateNormals();
_meshFilter.mesh = mesh;
}
private void AddTexture(int textureID) {
float y = textureID / VoxelData.TextureAtlasSizeInBlocks;
float x = textureID - (y * VoxelData.TextureAtlasSizeInBlocks);
x *= VoxelData.NormalizedBlockTextureSize;
y *= VoxelData.NormalizedBlockTextureSize;
y = 1f - y - VoxelData.NormalizedBlockTextureSize;
_uvs.Add(new Vector2(x, y));
_uvs.Add(new Vector2(x, y + VoxelData.NormalizedBlockTextureSize));
_uvs.Add(new Vector2(x + VoxelData.NormalizedBlockTextureSize, y));
_uvs.Add(new Vector2(x + VoxelData.NormalizedBlockTextureSize, y + VoxelData.NormalizedBlockTextureSize));
}
private bool IsVoxelInChunk(int x, int y, int z) {
return !(x < 0 || x > VoxelData.ChunkWidth - 1 ||
y < 0 || y > VoxelData.ChunkHeight - 1 ||
z < 0 || z > VoxelData.ChunkWidth - 1);
}
}
public class ChunkCoord {
public int x;
public int z;
public ChunkCoord(int _x, int _z) {
this.x = _x;
this.z = _z;
}
public override bool Equals(object obj) {
if (!(obj is ChunkCoord)) return false;
ChunkCoord other = (ChunkCoord) obj;
return (other.x == x && other.z == z);
}
public override int GetHashCode() => base.GetHashCode();
}
}