mirror of
https://github.com/godotengine/godot-demo-projects.git
synced 2025-12-16 05:20:06 +01:00
Switch back to Jolt Physics in Voxel demo (#1257)
This commit is contained in:
committed by
GitHub
parent
7d5f9269ca
commit
d7b6f86b0b
@@ -19,7 +19,7 @@ var _selected_block := 6
|
||||
@onready var raycast: RayCast3D = $Head/RayCast3D
|
||||
@onready var camera_attributes: CameraAttributes = $Head/Camera3D.attributes
|
||||
@onready var selected_block_texture: TextureRect = $SelectedBlock
|
||||
@onready var voxel_world: Node = $"../VoxelWorld"
|
||||
@onready var voxel_world: VoxelWorld = $"../VoxelWorld"
|
||||
@onready var crosshair: CenterContainer = $"../PauseMenu/Crosshair"
|
||||
@onready var aim_preview: MeshInstance3D = $AimPreview
|
||||
@onready var neutral_fov: float = camera.fov
|
||||
|
||||
@@ -155,7 +155,7 @@ pick_block={
|
||||
[physics]
|
||||
|
||||
common/physics_ticks_per_second=120
|
||||
3d/physics_engine="GodotPhysics3D"
|
||||
3d/physics_engine="Jolt Physics"
|
||||
common/physics_interpolation=true
|
||||
|
||||
[rendering]
|
||||
|
||||
@@ -4,23 +4,25 @@ extends StaticBody3D
|
||||
# After that, chunks finish setting themselves up in the _ready() function.
|
||||
# If a chunk is changed, its "regenerate" method is called.
|
||||
|
||||
const CHUNK_SIZE = 16 # Keep in sync with TerrainGenerator.
|
||||
const TEXTURE_SHEET_WIDTH = 8
|
||||
|
||||
const CHUNK_LAST_INDEX = CHUNK_SIZE - 1
|
||||
const TEXTURE_TILE_SIZE = 1.0 / TEXTURE_SHEET_WIDTH
|
||||
const CHUNK_SIZE := 16 # Keep in sync with TerrainGenerator.
|
||||
const TEXTURE_SHEET_WIDTH := 8
|
||||
const CHUNK_LAST_INDEX := CHUNK_SIZE - 1
|
||||
const TEXTURE_TILE_SIZE := 1.0 / TEXTURE_SHEET_WIDTH
|
||||
const CHUNK_EXTENTS := Vector3.ONE / 2.0
|
||||
const DIRECTIONS: Array[Vector3i] = [Vector3i.LEFT, Vector3i.RIGHT, Vector3i.DOWN, Vector3i.UP, Vector3i.FORWARD, Vector3i.BACK]
|
||||
|
||||
var data := {}
|
||||
var data: Dictionary[Vector3i, int] = {}
|
||||
var chunk_position := Vector3i()
|
||||
var is_initial_mesh_generated: bool = false
|
||||
var is_initial_mesh_generated := false
|
||||
var mesh_task_id := 0
|
||||
|
||||
var _thread: Thread
|
||||
static var box_shape: BoxShape3D = null
|
||||
|
||||
@onready var voxel_world := get_parent()
|
||||
@onready var voxel_world := get_parent() as VoxelWorld
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
func _init(pos: Vector3i) -> void:
|
||||
chunk_position = pos
|
||||
transform.origin = Vector3(chunk_position * CHUNK_SIZE)
|
||||
name = str(chunk_position)
|
||||
if Settings.world_type == 0:
|
||||
@@ -32,17 +34,27 @@ func _ready() -> void:
|
||||
_generate_chunk_collider()
|
||||
|
||||
|
||||
func _notification(what: int) -> void:
|
||||
if what == NOTIFICATION_PREDELETE:
|
||||
if mesh_task_id >= 1:
|
||||
WorkerThreadPool.wait_for_task_completion(mesh_task_id)
|
||||
mesh_task_id = 0
|
||||
|
||||
|
||||
func try_initial_generate_mesh(all_chunks: Dictionary[Vector3i, Chunk]) -> void:
|
||||
# We can use a thread for mesh generation.
|
||||
for dir in DIRECTIONS:
|
||||
if not all_chunks.has(chunk_position + dir):
|
||||
return
|
||||
is_initial_mesh_generated = true
|
||||
_thread = Thread.new()
|
||||
_thread.start(_generate_chunk_mesh)
|
||||
mesh_task_id = WorkerThreadPool.add_task(_generate_chunk_mesh, true)
|
||||
|
||||
|
||||
func regenerate() -> void:
|
||||
# Making shape changes to bodies with many/complex shapes, while the body is in the scene tree,
|
||||
# can be expensive when using Jolt Physics, so we temporarily remove it from the scene tree.
|
||||
voxel_world.remove_child(self)
|
||||
|
||||
# Clear out all old nodes first.
|
||||
for c in get_children():
|
||||
remove_child(c)
|
||||
@@ -52,18 +64,14 @@ func regenerate() -> void:
|
||||
_generate_chunk_collider()
|
||||
_generate_chunk_mesh()
|
||||
|
||||
voxel_world.add_child(self)
|
||||
|
||||
|
||||
func _generate_chunk_collider() -> void:
|
||||
if data.is_empty():
|
||||
# Avoid errors caused by StaticBody3D not having colliders.
|
||||
_create_block_collider(Vector3.ZERO)
|
||||
collision_layer = 0
|
||||
collision_mask = 0
|
||||
return
|
||||
|
||||
# For each block, generate a collider. Ensure collision layers are enabled.
|
||||
collision_layer = 0xFFFFF
|
||||
collision_mask = 0xFFFFF
|
||||
# For each block, generate a collider.
|
||||
for block_position: Vector3i in data.keys():
|
||||
var block_id: int = data[block_position]
|
||||
if block_id != 27 and block_id != 28:
|
||||
@@ -201,10 +209,13 @@ func _draw_block_face(surface_tool: SurfaceTool, verts: Array[Vector3], uvs: Arr
|
||||
|
||||
|
||||
func _create_block_collider(block_sub_position: Vector3) -> void:
|
||||
if not box_shape:
|
||||
box_shape = BoxShape3D.new()
|
||||
box_shape.extents = CHUNK_EXTENTS
|
||||
|
||||
var collider := CollisionShape3D.new()
|
||||
collider.shape = BoxShape3D.new()
|
||||
collider.shape.extents = Vector3.ONE / 2
|
||||
collider.transform.origin = Vector3(block_sub_position) + Vector3.ONE / 2
|
||||
collider.shape = box_shape
|
||||
collider.transform.origin = block_sub_position + CHUNK_EXTENTS
|
||||
add_child(collider)
|
||||
|
||||
|
||||
|
||||
@@ -3,12 +3,12 @@ extends Resource
|
||||
|
||||
const RANDOM_BLOCK_PROBABILITY = 0.015
|
||||
|
||||
static func empty() -> Dictionary:
|
||||
static func empty() -> Dictionary[Vector3i, int]:
|
||||
return {}
|
||||
|
||||
|
||||
static func random_blocks() -> Dictionary:
|
||||
var random_data := {}
|
||||
static func random_blocks() -> Dictionary[Vector3i, int]:
|
||||
var random_data: Dictionary[Vector3i, int] = {}
|
||||
for x in Chunk.CHUNK_SIZE:
|
||||
for y in Chunk.CHUNK_SIZE:
|
||||
for z in Chunk.CHUNK_SIZE:
|
||||
@@ -19,8 +19,8 @@ static func random_blocks() -> Dictionary:
|
||||
return random_data
|
||||
|
||||
|
||||
static func flat(chunk_position: Vector3i) -> Dictionary:
|
||||
var data := {}
|
||||
static func flat(chunk_position: Vector3i) -> Dictionary[Vector3i, int]:
|
||||
var data: Dictionary[Vector3i, int] = {}
|
||||
|
||||
if chunk_position.y != -1:
|
||||
return data
|
||||
@@ -36,7 +36,7 @@ static func flat(chunk_position: Vector3i) -> Dictionary:
|
||||
|
||||
|
||||
# Used to create the project icon.
|
||||
static func origin_grass(chunk_position: Vector3i) -> Dictionary:
|
||||
static func origin_grass(chunk_position: Vector3i) -> Dictionary[Vector3i, int]:
|
||||
if chunk_position == Vector3i.ZERO:
|
||||
return { Vector3i.ZERO: 3 }
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
class_name VoxelWorld
|
||||
extends Node
|
||||
# This file manages the creation and deletion of Chunks.
|
||||
|
||||
@@ -47,8 +48,7 @@ func _process(_delta: float) -> void:
|
||||
if _chunks.has(chunk_position):
|
||||
continue
|
||||
|
||||
var chunk := Chunk.new()
|
||||
chunk.chunk_position = chunk_position
|
||||
var chunk := Chunk.new(chunk_position)
|
||||
_chunks[chunk_position] = chunk
|
||||
add_child(chunk)
|
||||
chunk.try_initial_generate_mesh(_chunks)
|
||||
@@ -104,11 +104,6 @@ func set_block_global_position(block_global_position: Vector3i, block_id: int) -
|
||||
|
||||
|
||||
func clean_up() -> void:
|
||||
for chunk_position_key: Vector3i in _chunks.keys():
|
||||
var thread: Thread = _chunks[chunk_position_key]._thread
|
||||
if thread:
|
||||
thread.wait_to_finish()
|
||||
|
||||
_chunks = {}
|
||||
set_process(false)
|
||||
|
||||
@@ -129,9 +124,6 @@ func _delete_far_away_chunks(player_chunk: Vector3i) -> void:
|
||||
# Also take the opportunity to delete far away chunks.
|
||||
for chunk_position_key: Vector3i in _chunks.keys():
|
||||
if Vector3(player_chunk).distance_to(Vector3(chunk_position_key)) > _delete_distance:
|
||||
var thread: Thread = _chunks[chunk_position_key]._thread
|
||||
if thread:
|
||||
thread.wait_to_finish()
|
||||
_chunks[chunk_position_key].queue_free()
|
||||
_chunks.erase(chunk_position_key)
|
||||
deleted_this_frame += 1
|
||||
|
||||
Reference in New Issue
Block a user