|
|
|
|
const Faces = preload("./Faces.gd");
|
|
|
|
|
const vox_to_godot = Basis(Vector3.RIGHT, Vector3.FORWARD, Vector3.UP);
|
|
|
|
|
|
|
|
|
|
func generate(vox, voxel_data, scale, snaptoground):
|
|
|
|
|
var generator = VoxelMeshGenerator.new(vox, voxel_data, scale, snaptoground);
|
|
|
|
|
|
|
|
|
|
return generator.generate_mesh();
|
|
|
|
|
|
|
|
|
|
class MeshGenerator:
|
|
|
|
|
var surfaces = {};
|
|
|
|
|
|
|
|
|
|
func ensure_surface_exists(surface_index: int, color: Color, material: Material):
|
|
|
|
|
if (surfaces.has(surface_index)): return;
|
|
|
|
|
|
|
|
|
|
var st = SurfaceTool.new();
|
|
|
|
|
st.begin(Mesh.PRIMITIVE_TRIANGLES);
|
|
|
|
|
st.set_color(color);
|
|
|
|
|
st.set_material(material);
|
|
|
|
|
surfaces[surface_index] = st;
|
|
|
|
|
|
|
|
|
|
func add_vertex(surface_index: int, vertex: Vector3):
|
|
|
|
|
var st = surfaces[surface_index] as SurfaceTool;
|
|
|
|
|
st.add_vertex(vertex);
|
|
|
|
|
|
|
|
|
|
func combine_surfaces():
|
|
|
|
|
var mesh = null;
|
|
|
|
|
for surface_index in surfaces:
|
|
|
|
|
var surface = surfaces[surface_index] as SurfaceTool;
|
|
|
|
|
surface.index();
|
|
|
|
|
surface.generate_normals();
|
|
|
|
|
mesh = surface.commit(mesh);
|
|
|
|
|
|
|
|
|
|
var new_surface_index = mesh.get_surface_count() - 1;
|
|
|
|
|
var name = str(surface_index);
|
|
|
|
|
mesh.surface_set_name(new_surface_index, name);
|
|
|
|
|
return mesh;
|
|
|
|
|
|
|
|
|
|
class VoxelMeshGenerator:
|
|
|
|
|
var vox;
|
|
|
|
|
var voxel_data = {};
|
|
|
|
|
var scale:float;
|
|
|
|
|
var snaptoground:bool;
|
|
|
|
|
|
|
|
|
|
func _init(vox,voxel_data,scale,snaptoground):
|
|
|
|
|
self.vox = vox;
|
|
|
|
|
self.voxel_data = voxel_data;
|
|
|
|
|
self.scale = scale;
|
|
|
|
|
self.snaptoground = snaptoground;
|
|
|
|
|
|
|
|
|
|
func get_material(voxel):
|
|
|
|
|
var surface_index = voxel_data[voxel];
|
|
|
|
|
return vox.materials[surface_index]
|
|
|
|
|
|
|
|
|
|
func face_is_visible(voxel, face):
|
|
|
|
|
if (not voxel_data.has(voxel + face)):
|
|
|
|
|
return true;
|
|
|
|
|
var local_material = get_material(voxel);
|
|
|
|
|
var adj_material = get_material(voxel + face);
|
|
|
|
|
return adj_material.is_glass() && !local_material.is_glass();
|
|
|
|
|
|
|
|
|
|
func generate_mesh():
|
|
|
|
|
|
|
|
|
|
# Minimum extends of the volume
|
|
|
|
|
var mins :Vector3 = Vector3(1000000, 1000000, 1000000)
|
|
|
|
|
# Maximum extends of the volume
|
|
|
|
|
var maxs :Vector3 = Vector3(-1000000,-1000000,-1000000)
|
|
|
|
|
|
|
|
|
|
# Find bounds
|
|
|
|
|
for v in voxel_data:
|
|
|
|
|
mins.x = min(mins.x, v.x)
|
|
|
|
|
mins.y = min(mins.y, v.y)
|
|
|
|
|
mins.z = min(mins.z, v.z)
|
|
|
|
|
maxs.x = max(maxs.x, v.x)
|
|
|
|
|
maxs.y = max(maxs.y, v.y)
|
|
|
|
|
maxs.z = max(maxs.z, v.z)
|
|
|
|
|
|
|
|
|
|
var vox_to_godot = Basis(Vector3.RIGHT, Vector3.FORWARD, Vector3.UP);
|
|
|
|
|
var yoffset = Vector3(0,0,0);
|
|
|
|
|
if snaptoground : yoffset = Vector3(0, -mins.z * scale, 0);
|
|
|
|
|
var gen = MeshGenerator.new();
|
|
|
|
|
|
|
|
|
|
for voxel in voxel_data:
|
|
|
|
|
var voxelSides = []
|
|
|
|
|
if face_is_visible(voxel, Vector3.UP): voxelSides += Faces.Top
|
|
|
|
|
if face_is_visible(voxel, Vector3.DOWN): voxelSides += Faces.Bottom
|
|
|
|
|
if face_is_visible(voxel, Vector3.LEFT): voxelSides += Faces.Left
|
|
|
|
|
if face_is_visible(voxel, Vector3.RIGHT): voxelSides += Faces.Right
|
|
|
|
|
if face_is_visible(voxel, Vector3.BACK): voxelSides += Faces.Front
|
|
|
|
|
if face_is_visible(voxel, Vector3.FORWARD): voxelSides += Faces.Back
|
|
|
|
|
|
|
|
|
|
var surface_index = voxel_data[voxel];
|
|
|
|
|
var color = vox.colors[surface_index];
|
|
|
|
|
var material = vox.materials[surface_index].get_material(color);
|
|
|
|
|
gen.ensure_surface_exists(surface_index, color, material);
|
|
|
|
|
|
|
|
|
|
for t in voxelSides:
|
|
|
|
|
gen.add_vertex(surface_index, yoffset + vox_to_godot * (t + voxel) * scale);
|
|
|
|
|
|
|
|
|
|
return gen.combine_surfaces();
|