Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Vox importer rewrite. New features and fixes #49

Merged
merged 11 commits into from
Jul 27, 2021
2 changes: 1 addition & 1 deletion addons/voxel-core/classes/readers/gpl.gd
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ extends Reference



# Public Methods
## Public Methods
# Reads GPL file, and returns voxel palette
static func read(gpl_file : File) -> Dictionary:
var result := {
Expand Down
2 changes: 1 addition & 1 deletion addons/voxel-core/classes/readers/var.gd
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ extends Reference



# Public Methods
## Public Methods
# Reads var file, returns it's Variant content
static func read(var_file : File) -> Dictionary:
var result := {
Expand Down
503 changes: 446 additions & 57 deletions addons/voxel-core/classes/readers/vox.gd

Large diffs are not rendered by default.

20 changes: 9 additions & 11 deletions addons/voxel-core/classes/voxel.gd
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,6 @@ const Faces := {
Vector3.BACK: [ Vector3.LEFT, Vector3.RIGHT, Vector3.DOWN, Vector3.UP ],
}

# 0.5 means that voxels will have the dimensions of 0.5 x 0.5 x 0.5
const VoxelWorldSize := 0.5



## Public Methods
Expand Down Expand Up @@ -311,20 +308,21 @@ static func clean(voxel : Dictionary) -> void:


# Returns the world position as snapped world position
static func world_to_snapped(world : Vector3) -> Vector3:
return (world / VoxelWorldSize).floor() * VoxelWorldSize
static func world_to_snapped(world : Vector3, voxel_size : float = 0.5) -> Vector3:
return (world / voxel_size).floor() * voxel_size


# Returns the snapped world position as voxel grid position
static func snapped_to_grid(snapped : Vector3) -> Vector3:
return snapped / VoxelWorldSize
static func snapped_to_grid(snapped : Vector3, voxel_size : float = 0.5) -> Vector3:
return snapped / voxel_size


# Returns world position as voxel grid position
static func world_to_grid(world : Vector3) -> Vector3:
return snapped_to_grid(world_to_snapped(world))
static func world_to_grid(world : Vector3, voxel_size : float = 0.5) -> Vector3:
return snapped_to_grid(
world_to_snapped(world, voxel_size), voxel_size)


# Returns voxel grid position as snapped world position
static func grid_to_snapped(grid : Vector3) -> Vector3:
return grid * VoxelWorldSize
static func grid_to_snapped(grid : Vector3, voxel_size : float = 0.5) -> Vector3:
return grid * voxel_size
2 changes: 2 additions & 0 deletions addons/voxel-core/classes/voxel_mesh.gd
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,8 @@ func erase_voxels() -> void:
func update_mesh() -> void:
if not _voxels.empty():
var vt := VoxelTool.new()
vt.set_voxel_size(voxel_size)

var materials := {}
if is_instance_valid(mesh) and mesh is ArrayMesh:
for index in get_surface_material_count():
Expand Down
70 changes: 56 additions & 14 deletions addons/voxel-core/classes/voxel_object.gd
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ export var uv_map := false setget set_uv_map
# Flag indicating the persitant attachment and maintenance of a StaticBody
export var static_body := false setget set_static_body

# Size of each voxel in object
export var voxel_size := 0.5 setget set_voxel_size

# The VoxelSet for this VoxelObject
export(Resource) var voxel_set = null setget set_voxel_set

Expand All @@ -46,7 +49,6 @@ export(Resource) var voxel_set = null setget set_voxel_set
var edit_hint := 0 setget set_edit_hint



# Public Methods
# Sets the EditHint flag, calls update_mesh if needed and not told otherwise
func set_edit_hint(value : int, update := is_inside_tree()) -> void:
Expand All @@ -72,6 +74,14 @@ func set_uv_map(value : bool, update := is_inside_tree()) -> void:
update_mesh()


# Sets the size of each voxel, calls update_mesh if needed and not told otherwise
func set_voxel_size(value : float, update := is_inside_tree()) -> void:
voxel_size = value

if update:
update_mesh()


# Sets static_body, calls update_static_body if needed and not told otherwise
func set_static_body(value : bool, update := is_inside_tree()) -> void:
static_body = value
Expand Down Expand Up @@ -153,9 +163,13 @@ func erase_voxels() -> void:

# Returns 3D axis-aligned bounding box
# volume : Array<Vector3> : Array of grid positions from which to calculate bounds
# return : Dictionary : bounding box, contains: { position : Vector3, size: Vector3 }
# return : Dictionary : bounding box, contains: { position : Vector3, size: Vector3, end: Vector3 }
func get_box(volume := get_voxels()) -> Dictionary:
var box := { "position": Vector3.ZERO, "size": Vector3.ZERO }
var box := {
"position": Vector3.ZERO,
"size": Vector3.ZERO,
"end": Vector3.ZERO,
}

if not volume.empty():
box["position"] = Vector3.INF
Expand All @@ -177,6 +191,23 @@ func get_box(volume := get_voxels()) -> Dictionary:
box["size"].z = voxel_grid.z

box["size"] = (box["size"] - box["position"]).abs() + Vector3.ONE
box["end"] = box["position"] + box["size"]

return box


# Returns 3D axis-aligned bounding box, transformed to global coordinates
# volume : Array<Vector3> : Array of grid positions from which to calculate bounds
# return : Dictionary : bounding box, contains: { position : Vector3, size: Vector3, end: Vector3 }
func get_box_transformed(volume := get_voxels()) -> Dictionary:
var box := get_box(volume)

box.position = box.position * voxel_size
box.end = box.end * voxel_size

box.position = global_transform.xform(box.position)
box.end = global_transform.xform(box.end)
box.size = box.end - box.position

return box

Expand Down Expand Up @@ -205,9 +236,10 @@ func flip(x : bool, y : bool, z : bool, volume := get_voxels()) -> void:
var flipped := {}
for voxel_grid in volume:
flipped[Vector3(
(voxel_grid.x + (1 if z else 0)) * (-1 if z else 1),
(voxel_grid.y + (1 if y else 0)) * (-1 if y else 1),
(voxel_grid.z + (1 if x else 0)) * (-1 if x else 1))] = get_voxel_id(voxel_grid)
(voxel_grid.x + (1 if z else 0)) * (-1 if z else 1),
(voxel_grid.y + (1 if y else 0)) * (-1 if y else 1),
(voxel_grid.z + (1 if x else 0)) * (-1 if x else 1)
)] = get_voxel_id(voxel_grid)
erase_voxel(voxel_grid)
for voxel_grid in flipped:
set_voxel(voxel_grid, flipped[voxel_grid])
Expand All @@ -219,12 +251,14 @@ func flip(x : bool, y : bool, z : bool, volume := get_voxels()) -> void:
# return : Vector3 : Translation necessary to center
func vec_to_center(alignment := Vector3(0.5, 0.5, 0.5), volume := get_voxels()) -> Vector3:
var box := get_box(volume)
alignment = Vector3.ONE - Vector3(
clamp(alignment.x, 0.0, 1.0),
clamp(alignment.y, 0.0, 1.0),
clamp(alignment.z, 0.0, 1.0))
alignment = Vector3(
clamp(alignment.x, 0.0, 1.0),
clamp(alignment.y, 0.0, 1.0),
clamp(alignment.z, 0.0, 1.0)
)
return -box["position"] - (box["size"] * alignment).floor()


# A Fast Voxel Traversal Algorithm for Ray Tracing, by John Amanatides
# Algorithm paper: https://web.archive.org/web/20201108160724/http://www.cse.chalmers.se/edu/year/2010/course/TDA361/grid.pdf
# from : Vector3 : World position from which to start raycast
Expand All @@ -240,13 +274,13 @@ func intersect_ray(
var hit := {
"normal": Vector3(),
}
var grid := Voxel.world_to_grid(from)
var grid := Voxel.world_to_grid(from, voxel_size)
var step := Vector3(
1 if direction.x > 0 else -1,
1 if direction.y > 0 else -1,
1 if direction.z > 0 else -1)
var t_delta := direction.inverse().abs()
var dist := from.distance_to(Voxel.world_to_snapped(from))
var dist := from.distance_to(Voxel.world_to_snapped(from, voxel_size))
var t_max := t_delta * dist
var step_index := -1

Expand Down Expand Up @@ -357,10 +391,14 @@ func load_file(source_file : String, new_voxel_set := true) -> int:
# volume : Array<Vector3> : Array of grid positions representing volume of voxels from which to buid ArrayMesh
# vt : VoxelTool : VoxelTool with which ArrayMesh will be built
# return : ArrayMesh : Naive voxel mesh
func naive_volume(volume : Array, vt := VoxelTool.new()) -> ArrayMesh:
func naive_volume(volume : Array, vt : VoxelTool = null) -> ArrayMesh:
if not is_instance_valid(voxel_set):
return null

if not vt:
vt = VoxelTool.new()
vt.set_voxel_size(voxel_size)

vt.begin(voxel_set, uv_map)

for position in volume:
Expand All @@ -375,10 +413,14 @@ func naive_volume(volume : Array, vt := VoxelTool.new()) -> ArrayMesh:
# volume : Array<Vector3> : Array of grid positions representing volume of voxels from which to buid ArrayMesh
# vt : VoxelTool : VoxelTool with which ArrayMesh will be built
# return : ArrayMesh : Greedy voxel mesh
func greed_volume(volume : Array, vt := VoxelTool.new()) -> ArrayMesh:
func greed_volume(volume : Array, vt : VoxelTool = null) -> ArrayMesh:
if not is_instance_valid(voxel_set):
return null

if not vt:
vt = VoxelTool.new()
vt.set_voxel_size(voxel_size)

vt.begin(voxel_set, uv_map)

var faces = Voxel.Faces.duplicate()
Expand Down
57 changes: 33 additions & 24 deletions addons/voxel-core/classes/voxel_tool.gd
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,17 @@ var _surfaces := {}
# VoxelSet used when constructing Mesh, is set on begin
var _voxel_set : VoxelSet = null

# 0.5 means that voxels will have the dimensions of 0.5 x 0.5 x 0.5
var _voxel_size := 0.5


## Public Methods
# Set size of voxels
# 0.5 means that voxels will have the dimensions of 0.5 x 0.5 x 0.5
func set_voxel_size(size: float) -> void:
_voxel_size = size


# Called before constructing mesh, takes the VoxelSet with which Mesh will be constructed
func begin(voxel_set : VoxelSet = null, uv_voxels := false) -> void:
clear()
Expand Down Expand Up @@ -122,6 +130,7 @@ func add_face(

if surface.material is SpatialMaterial:
surface.material.vertex_color_use_as_albedo = true
surface.material.vertex_color_is_srgb = true
if uv_surface:
surface.material.albedo_texture = _voxel_set.tiles

Expand All @@ -134,81 +143,81 @@ func add_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)
surface.surface_tool.add_vertex((top_left + Vector3.RIGHT + Vector3.UP) * _voxel_size)
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)
surface.surface_tool.add_vertex((bottom_left + Vector3.RIGHT) * _voxel_size)
if uv_surface:
surface.surface_tool.add_uv((uv) * _voxel_set.uv_scale())
surface.surface_tool.add_vertex((top_right + Vector3.ONE) * Voxel.VoxelWorldSize)
surface.surface_tool.add_vertex((top_right + Vector3.ONE) * _voxel_size)
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)
surface.surface_tool.add_vertex((bottom_right + Vector3.RIGHT + Vector3.BACK) * _voxel_size)
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)
surface.surface_tool.add_vertex((bottom_left) * _voxel_size)
if uv_surface:
surface.surface_tool.add_uv((uv) * _voxel_set.uv_scale())
surface.surface_tool.add_vertex((top_left + Vector3.UP) * Voxel.VoxelWorldSize)
surface.surface_tool.add_vertex((top_left + Vector3.UP) * _voxel_size)
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)
surface.surface_tool.add_vertex((bottom_right + Vector3.BACK) * _voxel_size)
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)
surface.surface_tool.add_vertex((top_right + Vector3.UP + Vector3.BACK) * _voxel_size)
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)
surface.surface_tool.add_vertex((top_left + Vector3.UP + Vector3.BACK) *_voxel_size)
if uv_surface:
surface.surface_tool.add_uv((uv) * _voxel_set.uv_scale())
surface.surface_tool.add_vertex((bottom_left + Vector3.UP) * Voxel.VoxelWorldSize)
surface.surface_tool.add_vertex((bottom_left + Vector3.UP) * _voxel_size)
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)
surface.surface_tool.add_vertex((top_right + Vector3.ONE) * _voxel_size)
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)
surface.surface_tool.add_vertex((bottom_right + Vector3.RIGHT + Vector3.UP) * _voxel_size)
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)
surface.surface_tool.add_vertex((top_right + Vector3.RIGHT + Vector3.BACK) * _voxel_size)
if uv_surface:
surface.surface_tool.add_uv((uv) * _voxel_set.uv_scale())
surface.surface_tool.add_vertex((bottom_right + Vector3.RIGHT) * Voxel.VoxelWorldSize)
surface.surface_tool.add_vertex((bottom_right + Vector3.RIGHT) * _voxel_size)
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)
surface.surface_tool.add_vertex((top_left + Vector3.BACK) * _voxel_size)
if uv_surface:
surface.surface_tool.add_uv((uv + Vector2.RIGHT) * _voxel_set.uv_scale())
surface.surface_tool.add_vertex((bottom_left) * Voxel.VoxelWorldSize)
surface.surface_tool.add_vertex((bottom_left) * _voxel_size)
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)
surface.surface_tool.add_vertex((bottom_right + Vector3.RIGHT) * _voxel_size)
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)
surface.surface_tool.add_vertex((top_right + Vector3.RIGHT + Vector3.UP) * _voxel_size)
if uv_surface:
surface.surface_tool.add_uv((uv + Vector2.DOWN) * _voxel_set.uv_scale())
surface.surface_tool.add_vertex((bottom_left) * Voxel.VoxelWorldSize)
surface.surface_tool.add_vertex((bottom_left) * _voxel_size)
if uv_surface:
surface.surface_tool.add_uv((uv) * _voxel_set.uv_scale())
surface.surface_tool.add_vertex((top_left + Vector3.UP) * Voxel.VoxelWorldSize)
surface.surface_tool.add_vertex((top_left + Vector3.UP) * _voxel_size)
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)
surface.surface_tool.add_vertex((top_right + Vector3.ONE) * _voxel_size)
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)
surface.surface_tool.add_vertex((bottom_right + Vector3.RIGHT + Vector3.BACK) * _voxel_size)
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)
surface.surface_tool.add_vertex((top_left + Vector3.UP + Vector3.BACK) * _voxel_size)
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.surface_tool.add_vertex((bottom_left + Vector3.BACK) * _voxel_size)

surface.index += 4
surface.surface_tool.add_index(surface.index - 4)
Expand Down
Loading