411 lines
13 KiB
C#
411 lines
13 KiB
C#
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
|
|
public class Chunk : MonoBehaviour {
|
|
|
|
public enum Direction {x_neg, y_neg, z_neg, x_pos, y_pos, z_pos};
|
|
|
|
// rawData:
|
|
public const int N_CHUNK_SIDELENGTH = 16; // FIXME: bad naming
|
|
|
|
public const int N_CHUNK_SIDELENGTH_SQRD = 256; //16 * 16
|
|
public const int N_CHUNK_BLOCKS=4096; //16*16*16
|
|
|
|
private int[] data = new int[N_CHUNK_BLOCKS];
|
|
|
|
protected MeshFilter meshFilter;
|
|
|
|
protected List<Vector3> vertices;
|
|
protected List<int> tris;
|
|
protected List<Vector3> normals;
|
|
protected List<Color> colors;
|
|
|
|
protected int[] chunk_position = new int[3] {0,0,0};
|
|
protected Vector3Int chunk_position_vec;
|
|
|
|
public int[] ChunkPosition
|
|
{
|
|
get
|
|
{
|
|
return chunk_position;
|
|
}
|
|
set
|
|
{
|
|
chunk_position = value;
|
|
chunk_position_vec = new Vector3Int(value[0], value[1], value[2]);
|
|
}
|
|
}
|
|
|
|
public Vector3Int ChunkPositionVec
|
|
{
|
|
get
|
|
{
|
|
return chunk_position_vec;
|
|
}
|
|
set
|
|
{
|
|
chunk_position_vec = value;
|
|
chunk_position = new int[3] {value.x, value.y, value.z};
|
|
}
|
|
}
|
|
|
|
protected Chunk[] neighbor_chunks = new Chunk[6];
|
|
|
|
public Chunk[] NeighborChunks
|
|
{
|
|
get
|
|
{
|
|
return neighbor_chunks;
|
|
}
|
|
}
|
|
|
|
public int[] Data
|
|
{
|
|
get
|
|
{
|
|
return data;
|
|
}
|
|
|
|
set
|
|
{
|
|
data = value;
|
|
}
|
|
}
|
|
|
|
public void ConnectChunk(Chunk chunk, Direction direction)
|
|
{
|
|
neighbor_chunks[(int) direction] = chunk;
|
|
chunk.neighbor_chunks[((int) direction + 3) % 6] = this;
|
|
|
|
}
|
|
|
|
void Awake()
|
|
{
|
|
meshFilter = this.gameObject.AddComponent<MeshFilter>();
|
|
|
|
meshFilter.mesh.MarkDynamic();
|
|
|
|
vertices = new List<Vector3>();
|
|
tris = new List<int>();
|
|
normals = new List<Vector3>();
|
|
colors = new List<Color>();
|
|
|
|
}
|
|
|
|
// Use this for initialization
|
|
void Start () {
|
|
|
|
}
|
|
|
|
public void SetDataFromMessageObject(MessageObject mo)
|
|
{
|
|
if (mo.data == null)
|
|
{
|
|
throw new System.Exception("received empty data block");
|
|
}
|
|
|
|
if (mo.data.Length != 4096)
|
|
{
|
|
throw new System.Exception("bad data received");
|
|
}
|
|
|
|
Data = mo.data;
|
|
}
|
|
|
|
|
|
public void Index2Coords(int i, int[] coords)
|
|
{
|
|
coords[0] = i % N_CHUNK_SIDELENGTH;
|
|
coords[1] = (i / N_CHUNK_SIDELENGTH) % N_CHUNK_SIDELENGTH;
|
|
coords[2] = i / (N_CHUNK_SIDELENGTH * N_CHUNK_SIDELENGTH);
|
|
}
|
|
|
|
public int Coords2Index(int[] coords)
|
|
{
|
|
return coords[0] + coords[1] * N_CHUNK_SIDELENGTH + coords[2] * N_CHUNK_SIDELENGTH_SQRD;
|
|
}
|
|
|
|
protected Color CalculateColor(int[] coords)
|
|
{
|
|
return Color.blue + (((float)coords[1] + chunk_position[1] * N_CHUNK_SIDELENGTH) / (float)WorldManager.Instance.WorldHeight) * (Color.green - Color.blue);
|
|
}
|
|
|
|
protected void AddPlane(Vector3 normal, Vector3 pos, Color color)
|
|
{
|
|
|
|
/*
|
|
plane looks like this:
|
|
b
|
|
/|
|
|
/ |
|
|
/ |
|
|
normal a |
|
|
<------|-+---------+pos (center of cube)
|
|
| c
|
|
| /
|
|
| /
|
|
|/
|
|
d
|
|
|
|
*/
|
|
|
|
Vector3 a,b,c,d;
|
|
|
|
Vector3 normal_flipped = Vector3.one - normal;
|
|
float half_normal;
|
|
|
|
if (normal.x * normal.x > 0)
|
|
{
|
|
half_normal = .5f * normal.x;
|
|
a = new Vector3(half_normal, half_normal, half_normal);
|
|
b = new Vector3(half_normal, half_normal, -half_normal);
|
|
c = new Vector3(half_normal, -half_normal, -half_normal);
|
|
d = new Vector3(half_normal, -half_normal, half_normal);
|
|
}
|
|
else if (normal.y * normal.y > 0)
|
|
{
|
|
half_normal = .5f * normal.y;
|
|
a = new Vector3( half_normal, half_normal, half_normal);
|
|
b = new Vector3(-half_normal, half_normal, half_normal);
|
|
c = new Vector3(-half_normal, half_normal, -half_normal);
|
|
d = new Vector3( half_normal, half_normal, -half_normal);
|
|
}
|
|
else
|
|
{
|
|
half_normal = .5f * normal.z;
|
|
a = new Vector3( half_normal, half_normal, half_normal);
|
|
b = new Vector3( half_normal, -half_normal, half_normal);
|
|
c = new Vector3(-half_normal, -half_normal, half_normal);
|
|
d = new Vector3(-half_normal, half_normal, half_normal);
|
|
}
|
|
|
|
a += pos;
|
|
b += pos;
|
|
c += pos;
|
|
d += pos;
|
|
|
|
int n = vertices.Count;
|
|
|
|
vertices.Add(a);
|
|
vertices.Add(half_normal > 0 ? d : b); // forcing clockwise built triangles
|
|
vertices.Add(c);
|
|
vertices.Add(half_normal > 0 ? b : d);
|
|
|
|
tris.Add(n + 0);
|
|
tris.Add(n + 1);
|
|
tris.Add(n + 2);
|
|
|
|
tris.Add(n + 2);
|
|
tris.Add(n + 3);
|
|
tris.Add(n + 0);
|
|
|
|
normals.Add(normal);
|
|
normals.Add(normal);
|
|
normals.Add(normal);
|
|
normals.Add(normal);
|
|
|
|
colors.Add(color);
|
|
colors.Add(color);
|
|
colors.Add(color);
|
|
colors.Add(color);
|
|
}
|
|
|
|
// Build the chunk mesh from ground up
|
|
public void BuildMesh()
|
|
{
|
|
|
|
vertices.Clear();
|
|
tris.Clear();
|
|
normals.Clear();
|
|
colors.Clear();
|
|
|
|
int i = 0;
|
|
int[] pos = new int[3];
|
|
int[] pos_buffer = new int[3];
|
|
|
|
Index2Coords(i, pos);
|
|
|
|
// iterate through the raw data:
|
|
foreach (int d in Data)
|
|
{
|
|
int k = 0;
|
|
if (d == 0)
|
|
{
|
|
// since there is air here, the adjacent blocks are visible. So we will draw the adjacent sides
|
|
|
|
// manually go through 6 neighbors:
|
|
|
|
pos_buffer[0] = pos[0];
|
|
pos_buffer[1] = pos[1];
|
|
pos_buffer[2] = pos[2];
|
|
|
|
// x axis
|
|
if (pos[0] > 0)
|
|
{
|
|
pos_buffer[0] -= 1;
|
|
k = Coords2Index(pos_buffer);
|
|
if (Data[k] != 0)
|
|
{
|
|
AddPlane(Vector3.right, new Vector3(pos_buffer[0], pos_buffer[1], pos_buffer[2]), CalculateColor(pos_buffer));
|
|
}
|
|
pos_buffer[0] += 1;
|
|
|
|
}
|
|
else if (neighbor_chunks[(int)Direction.x_neg])
|
|
{
|
|
//wraparound
|
|
pos_buffer[0] = N_CHUNK_SIDELENGTH - 1;
|
|
k = Coords2Index(pos_buffer);
|
|
pos_buffer[0] = -1;
|
|
if (neighbor_chunks[(int) Direction.x_neg].Data[k] != 0)
|
|
{
|
|
AddPlane(Vector3.right, new Vector3(pos_buffer[0], pos_buffer[1], pos_buffer[2]), CalculateColor(pos_buffer));
|
|
}
|
|
pos_buffer[0] = 0;
|
|
}
|
|
|
|
if (pos[0] + 1 < N_CHUNK_SIDELENGTH)
|
|
{
|
|
pos_buffer[0] += 1;
|
|
k = Coords2Index(pos_buffer);
|
|
if (Data[k] != 0)
|
|
{
|
|
AddPlane(Vector3.left, new Vector3(pos_buffer[0], pos_buffer[1], pos_buffer[2]), CalculateColor(pos_buffer));
|
|
}
|
|
pos_buffer[0] -= 1;
|
|
}
|
|
else if (neighbor_chunks[(int)Direction.x_pos])
|
|
{
|
|
//wraparound
|
|
pos_buffer[0] = 0;
|
|
k = Coords2Index(pos_buffer);
|
|
pos_buffer[0] = N_CHUNK_SIDELENGTH;
|
|
if (neighbor_chunks[(int) Direction.x_pos].Data[k] != 0)
|
|
{
|
|
AddPlane(Vector3.left, new Vector3(pos_buffer[0], pos_buffer[1], pos_buffer[2]), CalculateColor(pos_buffer));
|
|
|
|
}
|
|
pos_buffer[0] = N_CHUNK_SIDELENGTH - 1;
|
|
}
|
|
|
|
// y axis
|
|
if (pos[1] > 0)
|
|
{
|
|
pos_buffer[1] -= 1;
|
|
k = Coords2Index(pos_buffer);
|
|
if (Data[k] != 0)
|
|
{
|
|
AddPlane(Vector3.up, new Vector3(pos_buffer[0], pos_buffer[1], pos_buffer[2]), CalculateColor(pos_buffer));
|
|
}
|
|
pos_buffer[1] += 1;
|
|
|
|
}
|
|
else if (neighbor_chunks[(int)Direction.y_neg])
|
|
{
|
|
//wraparound
|
|
pos_buffer[1] = N_CHUNK_SIDELENGTH - 1;
|
|
k = Coords2Index(pos_buffer);
|
|
pos_buffer[1] = -1;
|
|
if (neighbor_chunks[(int) Direction.y_neg].Data[k] != 0)
|
|
{
|
|
AddPlane(Vector3.up, new Vector3(pos_buffer[0], pos_buffer[1], pos_buffer[2]), CalculateColor(pos_buffer));
|
|
}
|
|
pos_buffer[1] = 0;
|
|
|
|
}
|
|
|
|
if (pos[1] + 1 < N_CHUNK_SIDELENGTH)
|
|
{
|
|
pos_buffer[1] += 1;
|
|
k = Coords2Index(pos_buffer);
|
|
if (Data[k] != 0)
|
|
{
|
|
AddPlane(Vector3.down, new Vector3(pos_buffer[0], pos_buffer[1], pos_buffer[2]), CalculateColor(pos_buffer));
|
|
}
|
|
pos_buffer[1] -= 1;
|
|
}
|
|
else if (neighbor_chunks[(int)Direction.y_pos])
|
|
{
|
|
//wraparound
|
|
pos_buffer[1] = 0;
|
|
k = Coords2Index(pos_buffer);
|
|
pos_buffer[1] = N_CHUNK_SIDELENGTH;
|
|
if (neighbor_chunks[(int) Direction.y_pos].Data[k] != 0)
|
|
{
|
|
AddPlane(Vector3.down, new Vector3(pos_buffer[0], pos_buffer[1], pos_buffer[2]), CalculateColor(pos_buffer));
|
|
}
|
|
pos_buffer[1] = N_CHUNK_SIDELENGTH - 1;
|
|
}
|
|
|
|
// z axis
|
|
if (pos[2] > 0)
|
|
{
|
|
pos_buffer[2] -= 1;
|
|
k = Coords2Index(pos_buffer);
|
|
if (Data[k] != 0)
|
|
{
|
|
AddPlane(Vector3.forward, new Vector3(pos_buffer[0], pos_buffer[1], pos_buffer[2]), CalculateColor(pos_buffer));
|
|
}
|
|
pos_buffer[2] += 1;
|
|
|
|
}
|
|
else if (neighbor_chunks[(int)Direction.z_neg])
|
|
{
|
|
//wraparound
|
|
pos_buffer[2] = N_CHUNK_SIDELENGTH - 1;
|
|
k = Coords2Index(pos_buffer);
|
|
pos_buffer[2] = -1;
|
|
if (neighbor_chunks[(int) Direction.z_neg].Data[k] != 0)
|
|
{
|
|
AddPlane(Vector3.forward, new Vector3(pos_buffer[0], pos_buffer[1], pos_buffer[2]), CalculateColor(pos_buffer));
|
|
}
|
|
pos_buffer[2] = 0;
|
|
}
|
|
|
|
if (pos[2] + 1 < N_CHUNK_SIDELENGTH)
|
|
{
|
|
pos_buffer[2] += 1;
|
|
k = Coords2Index(pos_buffer);
|
|
if (Data[k] != 0)
|
|
{
|
|
AddPlane(Vector3.back, new Vector3(pos_buffer[0], pos_buffer[1], pos_buffer[2]), CalculateColor(pos_buffer));
|
|
}
|
|
pos_buffer[2] -= 1;
|
|
}
|
|
else if (neighbor_chunks[(int)Direction.z_pos])
|
|
{
|
|
//wraparound
|
|
pos_buffer[2] = 0;
|
|
k = Coords2Index(pos_buffer);
|
|
pos_buffer[2] = N_CHUNK_SIDELENGTH;
|
|
if (neighbor_chunks[(int) Direction.z_pos].Data[k] != 0)
|
|
{
|
|
AddPlane(Vector3.back, new Vector3(pos_buffer[0], pos_buffer[1], pos_buffer[2]), CalculateColor(pos_buffer));
|
|
}
|
|
pos_buffer[2] = N_CHUNK_SIDELENGTH - 1;
|
|
}
|
|
}
|
|
|
|
i += 1;
|
|
|
|
Index2Coords(i, pos);
|
|
|
|
}
|
|
}
|
|
|
|
public void AssignMesh()
|
|
{
|
|
meshFilter.mesh.Clear();
|
|
meshFilter.mesh.vertices = vertices.ToArray();
|
|
meshFilter.mesh.triangles = tris.ToArray();
|
|
meshFilter.mesh.normals = normals.ToArray();
|
|
meshFilter.mesh.colors = colors.ToArray();
|
|
}
|
|
|
|
// Update is called once per frame
|
|
void Update () {
|
|
//Pulse();
|
|
}
|
|
}
|