aboutsummaryrefslogtreecommitdiff
path: root/assets/addons/voxel-core/classes/voxel_tool.gd
diff options
context:
space:
mode:
Diffstat (limited to 'assets/addons/voxel-core/classes/voxel_tool.gd')
-rw-r--r--assets/addons/voxel-core/classes/voxel_tool.gd227
1 files changed, 227 insertions, 0 deletions
diff --git a/assets/addons/voxel-core/classes/voxel_tool.gd b/assets/addons/voxel-core/classes/voxel_tool.gd
new file mode 100644
index 0000000..bba14aa
--- /dev/null
+++ b/assets/addons/voxel-core/classes/voxel_tool.gd
@@ -0,0 +1,227 @@
+tool
+class_name VoxelTool
+extends Reference
+# Used to construct a Mesh with provided VoxelSet
+# and by specifying voxel faces individually.
+
+
+
+class Surface:
+ ## Public Variables
+ # Index of the last vertex in Mesh being constructed
+ var index : int
+
+ var material : SpatialMaterial
+
+ # SurfaceTool used to construct Mesh
+ var surface_tool : SurfaceTool
+
+
+
+ ## Built-In Virtual Methods
+ func _init() -> void:
+ index = 0
+ surface_tool = SurfaceTool.new()
+ surface_tool.begin(Mesh.PRIMITIVE_TRIANGLES)
+
+
+
+## Private Variables
+# Flag indicating whether uv mapping should be applied to constructed mesh
+var _uv_voxels := false
+
+# Contains Surfaces being constructed
+var _surfaces := {}
+
+# VoxelSet used when constructing Mesh, is set on begin
+var _voxel_set : VoxelSet = null
+
+
+
+## Public Methods
+# Called before constructing mesh, takes the VoxelSet with which Mesh will be constructed
+func begin(voxel_set : VoxelSet = null, uv_voxels := false) -> void:
+ clear()
+ _uv_voxels = uv_voxels and voxel_set.uv_ready()
+ _voxel_set = voxel_set
+
+
+# Clear all information
+func clear() -> void:
+ _uv_voxels = false
+ _surfaces.clear()
+ _voxel_set = null
+
+
+# Returns a constructed ArrayMesh
+func commit() -> ArrayMesh:
+ var mesh := ArrayMesh.new()
+ for surface_id in _surfaces:
+ var surface : Surface = _surfaces[surface_id]
+ var submesh = surface.surface_tool.commit_to_arrays()
+ mesh.add_surface_from_arrays(
+ Mesh.PRIMITIVE_TRIANGLES,
+ submesh)
+ mesh.surface_set_name(mesh.get_surface_count() - 1, surface_id)
+ mesh.surface_set_material(mesh.get_surface_count() - 1, surface.material)
+ clear()
+ return mesh
+
+
+# Adds a voxel face to Mesh with given vertex positions and voxel data
+# voxel : Dictioanry<String, Variant> : voxel data to use
+# face : Vector3 : face of voxel to generate
+# bottom_right : Vector3 : grid position of bottom right vertex pertaining to face
+# bottom_left : Vector3 : grid position of bottom left vertex pertaining to face, if not given botttom right is used
+# top_right : Vector3 : grid position of top right vertex pertaining to face, if not given botttom right is used
+# top_left : Vector3 : grid position of top left vertex pertaining to face, if not given botttom right is used
+func add_face(
+ voxel : Dictionary,
+ face : Vector3,
+ bottom_right : Vector3,
+ bottom_left := Vector3.INF,
+ top_right := Vector3.INF,
+ top_left := Vector3.INF) -> void:
+ bottom_right = bottom_right
+ if bottom_left == Vector3.INF: bottom_left = bottom_right
+ if top_right == Vector3.INF: top_right = bottom_right
+ if top_left == Vector3.INF: top_left = bottom_right
+
+ var color := Voxel.get_face_color(voxel, face)
+ var uv := Voxel.get_face_uv(voxel, face) if _uv_voxels else -Vector2.ONE
+ var uv_surface := uv != -Vector2.ONE
+
+ var material := Voxel.get_material(voxel)
+
+ var metal := Voxel.get_metallic(voxel)
+ var specular := Voxel.get_specular(voxel)
+ var rough := Voxel.get_roughness(voxel)
+ var energy := Voxel.get_energy(voxel)
+ var energy_color := Voxel.get_energy_color(voxel)
+
+ var surface_id := str(material) if material > -1 else (str(metal) + "," + str(specular) + "," + str(rough) + "," + str(energy) + "," + str(energy_color))
+ if uv_surface:
+ surface_id += "_uv"
+ var surface : Surface = _surfaces.get(surface_id)
+ if not is_instance_valid(surface):
+ surface = Surface.new()
+
+ surface.material = _voxel_set.get_material(material) if is_instance_valid(_voxel_set) else null
+ if is_instance_valid(surface.material):
+ surface.material = surface.material.duplicate()
+ else:
+ surface.material = SpatialMaterial.new()
+
+ surface.material.metallic = metal
+ surface.material.metallic_specular = specular
+ surface.material.roughness = rough
+ if energy > 0.0:
+ surface.material.emission_enabled = true
+ surface.material.emission = energy_color
+ surface.material.emission_energy = energy
+
+ if surface.material is SpatialMaterial:
+ surface.material.vertex_color_use_as_albedo = true
+ if uv_surface:
+ surface.material.albedo_texture = _voxel_set.tiles
+
+ _surfaces[surface_id] = surface
+
+ surface.surface_tool.add_normal(face)
+ surface.surface_tool.add_color(color)
+
+ match face:
+ Vector3.RIGHT:
+ if uv_surface:
+ surface.surface_tool.add_uv((uv + Vector2.RIGHT) * _voxel_set.uv_scale())
+ surface.surface_tool.add_vertex((top_left + Vector3.RIGHT + Vector3.UP) * Voxel.VoxelWorldSize)
+ if uv_surface:
+ surface.surface_tool.add_uv((uv + Vector2.ONE) * _voxel_set.uv_scale())
+ surface.surface_tool.add_vertex((bottom_left + Vector3.RIGHT) * Voxel.VoxelWorldSize)
+ if uv_surface:
+ surface.surface_tool.add_uv((uv) * _voxel_set.uv_scale())
+ surface.surface_tool.add_vertex((top_right + Vector3.ONE) * Voxel.VoxelWorldSize)
+ if uv_surface:
+ surface.surface_tool.add_uv((uv + Vector2.DOWN) * _voxel_set.uv_scale())
+ surface.surface_tool.add_vertex((bottom_right + Vector3.RIGHT + Vector3.BACK) * Voxel.VoxelWorldSize)
+ Vector3.LEFT:
+ if uv_surface:
+ surface.surface_tool.add_uv((uv + Vector2.DOWN) * _voxel_set.uv_scale())
+ surface.surface_tool.add_vertex((bottom_left) * Voxel.VoxelWorldSize)
+ if uv_surface:
+ surface.surface_tool.add_uv((uv) * _voxel_set.uv_scale())
+ surface.surface_tool.add_vertex((top_left + Vector3.UP) * Voxel.VoxelWorldSize)
+ if uv_surface:
+ surface.surface_tool.add_uv((uv + Vector2.ONE) * _voxel_set.uv_scale())
+ surface.surface_tool.add_vertex((bottom_right + Vector3.BACK) * Voxel.VoxelWorldSize)
+ if uv_surface:
+ surface.surface_tool.add_uv((uv + Vector2.RIGHT) * _voxel_set.uv_scale())
+ surface.surface_tool.add_vertex((top_right + Vector3.UP + Vector3.BACK) * Voxel.VoxelWorldSize)
+ Vector3.UP:
+ if uv_surface:
+ surface.surface_tool.add_uv((uv + Vector2.DOWN) * _voxel_set.uv_scale())
+ surface.surface_tool.add_vertex((top_left + Vector3.UP + Vector3.BACK) * Voxel.VoxelWorldSize)
+ if uv_surface:
+ surface.surface_tool.add_uv((uv) * _voxel_set.uv_scale())
+ surface.surface_tool.add_vertex((bottom_left + Vector3.UP) * Voxel.VoxelWorldSize)
+ if uv_surface:
+ surface.surface_tool.add_uv((uv + Vector2.ONE) * _voxel_set.uv_scale())
+ surface.surface_tool.add_vertex((top_right + Vector3.ONE) * Voxel.VoxelWorldSize)
+ if uv_surface:
+ surface.surface_tool.add_uv((uv + Vector2.RIGHT) * _voxel_set.uv_scale())
+ surface.surface_tool.add_vertex((bottom_right + Vector3.RIGHT + Vector3.UP) * Voxel.VoxelWorldSize)
+ Vector3.DOWN:
+ if uv_surface:
+ surface.surface_tool.add_uv((uv + Vector2.DOWN) * _voxel_set.uv_scale())
+ surface.surface_tool.add_vertex((top_right + Vector3.RIGHT + Vector3.BACK) * Voxel.VoxelWorldSize)
+ if uv_surface:
+ surface.surface_tool.add_uv((uv) * _voxel_set.uv_scale())
+ surface.surface_tool.add_vertex((bottom_right + Vector3.RIGHT) * Voxel.VoxelWorldSize)
+ if uv_surface:
+ surface.surface_tool.add_uv((uv + Vector2.ONE) * _voxel_set.uv_scale())
+ surface.surface_tool.add_vertex((top_left + Vector3.BACK) * Voxel.VoxelWorldSize)
+ if uv_surface:
+ surface.surface_tool.add_uv((uv + Vector2.RIGHT) * _voxel_set.uv_scale())
+ surface.surface_tool.add_vertex((bottom_left) * Voxel.VoxelWorldSize)
+ Vector3.FORWARD:
+ if uv_surface:
+ surface.surface_tool.add_uv((uv + Vector2.ONE) * _voxel_set.uv_scale())
+ surface.surface_tool.add_vertex((bottom_right + Vector3.RIGHT) * Voxel.VoxelWorldSize)
+ if uv_surface:
+ surface.surface_tool.add_uv((uv + Vector2.RIGHT) * _voxel_set.uv_scale())
+ surface.surface_tool.add_vertex((top_right + Vector3.RIGHT + Vector3.UP) * Voxel.VoxelWorldSize)
+ if uv_surface:
+ surface.surface_tool.add_uv((uv + Vector2.DOWN) * _voxel_set.uv_scale())
+ surface.surface_tool.add_vertex((bottom_left) * Voxel.VoxelWorldSize)
+ if uv_surface:
+ surface.surface_tool.add_uv((uv) * _voxel_set.uv_scale())
+ surface.surface_tool.add_vertex((top_left + Vector3.UP) * Voxel.VoxelWorldSize)
+ Vector3.BACK:
+ if uv_surface:
+ surface.surface_tool.add_uv((uv + Vector2.RIGHT) * _voxel_set.uv_scale())
+ surface.surface_tool.add_vertex((top_right + Vector3.ONE) * Voxel.VoxelWorldSize)
+ if uv_surface:
+ surface.surface_tool.add_uv((uv + Vector2.ONE) * _voxel_set.uv_scale())
+ surface.surface_tool.add_vertex((bottom_right + Vector3.RIGHT + Vector3.BACK) * Voxel.VoxelWorldSize)
+ if uv_surface:
+ surface.surface_tool.add_uv((uv) * _voxel_set.uv_scale())
+ surface.surface_tool.add_vertex((top_left + Vector3.UP + Vector3.BACK) * Voxel.VoxelWorldSize)
+ if uv_surface:
+ surface.surface_tool.add_uv((uv + Vector2.DOWN) * _voxel_set.uv_scale())
+ surface.surface_tool.add_vertex((bottom_left + Vector3.BACK) * Voxel.VoxelWorldSize)
+
+ surface.index += 4
+ surface.surface_tool.add_index(surface.index - 4)
+ surface.surface_tool.add_index(surface.index - 3)
+ surface.surface_tool.add_index(surface.index - 2)
+ surface.surface_tool.add_index(surface.index - 3)
+ surface.surface_tool.add_index(surface.index - 1)
+ surface.surface_tool.add_index(surface.index - 2)
+
+
+# Adds all the faces of a voxel to Mesh at given position and with voxel data
+# voxel : Dictioanry<String, Variant> : voxel data to use
+# grid : Vector3 : voxel grid position of voxel
+func add_faces(voxel : Dictionary, grid : Vector3) -> void:
+ for face in Voxel.Faces:
+ add_face(voxel, face, grid)