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