You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

100 lines
3.6 KiB
GDScript

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();