152 lines
5.6 KiB
C#
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();
|
|
}
|
|
} |