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
		
	
| 
											2 years ago
										 | 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(); |