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.1 KiB
		
	
	
	
		
			GDScript
		
	
			
		
		
	
	
			100 lines
		
	
	
		
			3.1 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();
 |