added terrain3d
This commit is contained in:
@@ -1 +1 @@
|
||||
uid://6isldwgof4yb
|
||||
uid://b62ppvc03a6b1
|
||||
|
||||
@@ -1 +1 @@
|
||||
uid://bpye6axtbsyq2
|
||||
uid://c444j1ucmv5ti
|
||||
|
||||
@@ -1,34 +1,133 @@
|
||||
extends Node
|
||||
|
||||
var terrain: Terrain3D
|
||||
|
||||
func _ready():
|
||||
|
||||
func _ready() -> void:
|
||||
$UI.player = $Player
|
||||
|
||||
if has_node("RunThisSceneLabel3D"):
|
||||
$RunThisSceneLabel3D.queue_free()
|
||||
|
||||
# Create a terrain
|
||||
var terrain := Terrain3D.new()
|
||||
terrain.assets = Terrain3DAssets.new()
|
||||
terrain.name = "Terrain3D"
|
||||
terrain.set_collision_enabled(false)
|
||||
add_child(terrain, true)
|
||||
terrain.material.world_background = Terrain3DMaterial.NONE
|
||||
|
||||
# Generate 32-bit noise and import it with scale
|
||||
var noise := FastNoiseLite.new()
|
||||
noise.frequency = 0.0005
|
||||
var img: Image = Image.create(2048, 2048, false, Image.FORMAT_RF)
|
||||
for x in 2048:
|
||||
for y in 2048:
|
||||
img.set_pixel(x, y, Color(noise.get_noise_2d(x, y)*0.5, 0., 0., 1.))
|
||||
terrain.data.import_images([img, null, null], Vector3(-1024, 0, -1024), 0.0, 300.0)
|
||||
|
||||
# Enable collision. Enable the first if you wish to see it with Debug/Visible Collision Shapes
|
||||
#terrain.set_show_debug_collision(true)
|
||||
terrain.set_collision_enabled(true)
|
||||
|
||||
terrain = await create_terrain()
|
||||
|
||||
# Enable runtime navigation baking using the terrain
|
||||
# Enable `Debug/Visible Navigation` if you wish to see it
|
||||
$RuntimeNavigationBaker.terrain = terrain
|
||||
$RuntimeNavigationBaker.enabled = true
|
||||
|
||||
|
||||
func create_terrain() -> Terrain3D:
|
||||
# Create textures
|
||||
var green_gr := Gradient.new()
|
||||
green_gr.set_color(0, Color.from_hsv(100./360., .35, .3))
|
||||
green_gr.set_color(1, Color.from_hsv(120./360., .4, .37))
|
||||
var green_ta: Terrain3DTextureAsset = await create_texture_asset("Grass", green_gr, 1024)
|
||||
green_ta.uv_scale = 0.1
|
||||
green_ta.detiling_rotation = 0.1
|
||||
|
||||
var brown_gr := Gradient.new()
|
||||
brown_gr.set_color(0, Color.from_hsv(30./360., .4, .3))
|
||||
brown_gr.set_color(1, Color.from_hsv(30./360., .4, .4))
|
||||
var brown_ta: Terrain3DTextureAsset = await create_texture_asset("Dirt", brown_gr, 1024)
|
||||
brown_ta.uv_scale = 0.03
|
||||
green_ta.detiling_rotation = 0.1
|
||||
|
||||
var grass_ma: Terrain3DMeshAsset = create_mesh_asset("Grass", Color.from_hsv(120./360., .4, .37))
|
||||
|
||||
# Create a terrain
|
||||
var terrain := Terrain3D.new()
|
||||
terrain.name = "Terrain3D"
|
||||
add_child(terrain, true)
|
||||
|
||||
# Set material and assets
|
||||
terrain.material.world_background = Terrain3DMaterial.NONE
|
||||
terrain.material.auto_shader = true
|
||||
terrain.material.set_shader_param("auto_slope", 10)
|
||||
terrain.material.set_shader_param("blend_sharpness", .975)
|
||||
terrain.assets = Terrain3DAssets.new()
|
||||
terrain.assets.set_texture(0, green_ta)
|
||||
terrain.assets.set_texture(1, brown_ta)
|
||||
terrain.assets.set_mesh_asset(0, grass_ma)
|
||||
|
||||
# Generate height map w/ 32-bit noise and import it with scale
|
||||
var noise := FastNoiseLite.new()
|
||||
noise.frequency = 0.0005
|
||||
var img: Image = Image.create_empty(2048, 2048, false, Image.FORMAT_RF)
|
||||
for x in img.get_width():
|
||||
for y in img.get_height():
|
||||
img.set_pixel(x, y, Color(noise.get_noise_2d(x, y), 0., 0., 1.))
|
||||
terrain.region_size = 1024
|
||||
terrain.data.import_images([img, null, null], Vector3(-1024, 0, -1024), 0.0, 150.0)
|
||||
|
||||
# Instance foliage
|
||||
var xforms: Array[Transform3D]
|
||||
var width: int = 100
|
||||
var step: int = 2
|
||||
for x in range(0, width, step):
|
||||
for z in range(0, width, step):
|
||||
var pos := Vector3(x, 0, z) - Vector3(width, 0, width) * .5
|
||||
pos.y = terrain.data.get_height(pos)
|
||||
xforms.push_back(Transform3D(Basis(), pos))
|
||||
terrain.instancer.add_transforms(0, xforms)
|
||||
|
||||
# Enable the next line and `Debug/Visible Collision Shapes` to see collision
|
||||
#terrain.collision.mode = Terrain3DCollision.DYNAMIC_EDITOR
|
||||
|
||||
return terrain
|
||||
|
||||
|
||||
func create_texture_asset(asset_name: String, gradient: Gradient, texture_size: int = 512) -> Terrain3DTextureAsset:
|
||||
# Create noise map
|
||||
var fnl := FastNoiseLite.new()
|
||||
fnl.frequency = 0.004
|
||||
|
||||
# Create albedo noise texture
|
||||
var alb_noise_tex := NoiseTexture2D.new()
|
||||
alb_noise_tex.width = texture_size
|
||||
alb_noise_tex.height = texture_size
|
||||
alb_noise_tex.seamless = true
|
||||
alb_noise_tex.noise = fnl
|
||||
alb_noise_tex.color_ramp = gradient
|
||||
await alb_noise_tex.changed
|
||||
var alb_noise_img: Image = alb_noise_tex.get_image()
|
||||
|
||||
# Create albedo + height texture
|
||||
for x in alb_noise_img.get_width():
|
||||
for y in alb_noise_img.get_height():
|
||||
var clr: Color = alb_noise_img.get_pixel(x, y)
|
||||
clr.a = clr.v # Noise as height
|
||||
alb_noise_img.set_pixel(x, y, clr)
|
||||
alb_noise_img.generate_mipmaps()
|
||||
var albedo := ImageTexture.create_from_image(alb_noise_img)
|
||||
|
||||
# Create normal + rough texture
|
||||
var nrm_noise_tex := NoiseTexture2D.new()
|
||||
nrm_noise_tex.width = texture_size
|
||||
nrm_noise_tex.height = texture_size
|
||||
nrm_noise_tex.as_normal_map = true
|
||||
nrm_noise_tex.seamless = true
|
||||
nrm_noise_tex.noise = fnl
|
||||
await nrm_noise_tex.changed
|
||||
var nrm_noise_img = nrm_noise_tex.get_image()
|
||||
for x in nrm_noise_img.get_width():
|
||||
for y in nrm_noise_img.get_height():
|
||||
var normal_rgh: Color = nrm_noise_img.get_pixel(x, y)
|
||||
normal_rgh.a = 0.8 # Roughness
|
||||
nrm_noise_img.set_pixel(x, y, normal_rgh)
|
||||
nrm_noise_img.generate_mipmaps()
|
||||
var normal := ImageTexture.create_from_image(nrm_noise_img)
|
||||
|
||||
var ta := Terrain3DTextureAsset.new()
|
||||
ta.name = asset_name
|
||||
ta.albedo_texture = albedo
|
||||
ta.normal_texture = normal
|
||||
return ta
|
||||
|
||||
|
||||
func create_mesh_asset(asset_name: String, color: Color) -> Terrain3DMeshAsset:
|
||||
var ma := Terrain3DMeshAsset.new()
|
||||
ma.name = asset_name
|
||||
ma.generated_type = Terrain3DMeshAsset.TYPE_TEXTURE_CARD
|
||||
ma.material_override.albedo_color = color
|
||||
return ma
|
||||
|
||||
@@ -1 +1 @@
|
||||
uid://dd26e3lk8oe1l
|
||||
uid://dakis6gu8b7nm
|
||||
|
||||
@@ -1,8 +1,23 @@
|
||||
@tool
|
||||
extends Node
|
||||
|
||||
@onready var terrain: Terrain3D = find_child("Terrain3D")
|
||||
|
||||
|
||||
func _ready():
|
||||
if not Engine.is_editor_hint() and has_node("UI"):
|
||||
$UI.player = $Player
|
||||
|
||||
# Load Sky3D into the demo environment if enabled
|
||||
if Engine.is_editor_hint() and has_node("Environment") and \
|
||||
Engine.get_singleton(&"EditorInterface").is_plugin_enabled("sky_3d"):
|
||||
$Environment.queue_free()
|
||||
var sky3d = load("res://addons/sky_3d/src/Sky3D.gd").new()
|
||||
sky3d.name = "Sky3D"
|
||||
add_child(sky3d, true)
|
||||
move_child(sky3d, 1)
|
||||
sky3d.owner = self
|
||||
sky3d.current_time = 10
|
||||
sky3d.enable_editor_time = false
|
||||
|
||||
|
||||
|
||||
@@ -1 +1 @@
|
||||
uid://8atelq27qxnq
|
||||
uid://chstoagn42gbr
|
||||
|
||||
@@ -45,6 +45,12 @@ func _physics_process(p_delta: float) -> void:
|
||||
else:
|
||||
_on_velocity_computed(velocity)
|
||||
|
||||
# Ensure enemy doesn't fall through terrain when collision absent
|
||||
if get_parent().terrain:
|
||||
var height: float = get_parent().terrain.data.get_height(global_position)
|
||||
if not is_nan(height):
|
||||
global_position.y = maxf(global_position.y, height)
|
||||
|
||||
|
||||
func _on_velocity_computed(p_safe_velocity: Vector3) -> void:
|
||||
velocity.x = p_safe_velocity.x
|
||||
|
||||
@@ -1 +1 @@
|
||||
uid://cimcukvh7jjo5
|
||||
uid://6j2rrp5f1gjs
|
||||
|
||||
@@ -28,7 +28,7 @@ extends CharacterBody3D
|
||||
|
||||
func _physics_process(p_delta) -> void:
|
||||
var direction: Vector3 = get_camera_relative_input()
|
||||
var h_veloc: Vector2 = Vector2(direction.x, direction.z) * MOVE_SPEED
|
||||
var h_veloc: Vector2 = Vector2(direction.x, direction.z).normalized() * MOVE_SPEED
|
||||
if Input.is_key_pressed(KEY_SHIFT):
|
||||
h_veloc *= 2
|
||||
velocity.x = h_veloc.x
|
||||
@@ -57,7 +57,7 @@ func get_camera_relative_input() -> Vector3:
|
||||
MOVE_SPEED = clamp(MOVE_SPEED + .5, 5, 9999)
|
||||
if Input.is_key_pressed(KEY_KP_SUBTRACT) or Input.is_key_pressed(KEY_MINUS):
|
||||
MOVE_SPEED = clamp(MOVE_SPEED - .5, 5, 9999)
|
||||
return input_dir
|
||||
return input_dir
|
||||
|
||||
|
||||
func _input(p_event: InputEvent) -> void:
|
||||
1
demo/src/Player.gd.uid
Normal file
1
demo/src/Player.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://dajlr3n5wjwmb
|
||||
@@ -1 +0,0 @@
|
||||
uid://dthbn7g43c6m4
|
||||
@@ -79,7 +79,7 @@ func set_template(p_value: NavigationMesh) -> void:
|
||||
|
||||
func parse_scene() -> void:
|
||||
_scene_geometry = NavigationMeshSourceGeometryData3D.new()
|
||||
NavigationMeshGenerator.parse_source_geometry_data(template, _scene_geometry, self)
|
||||
NavigationServer3D.parse_source_geometry_data(template, _scene_geometry, self)
|
||||
|
||||
|
||||
func _update_map_cell_size() -> void:
|
||||
@@ -131,7 +131,7 @@ func _task_bake(p_center: Vector3) -> void:
|
||||
source_geometry.add_faces(faces, Transform3D.IDENTITY)
|
||||
|
||||
if source_geometry.has_data():
|
||||
NavigationMeshGenerator.bake_from_source_geometry_data(nav_mesh, source_geometry)
|
||||
NavigationServer3D.bake_from_source_geometry_data(nav_mesh, source_geometry)
|
||||
_bake_finished.call_deferred(nav_mesh)
|
||||
else:
|
||||
_bake_finished.call_deferred(null)
|
||||
@@ -149,4 +149,3 @@ func _bake_finished(p_nav_mesh: NavigationMesh) -> void:
|
||||
|
||||
bake_finished.emit()
|
||||
assert(!NavigationServer3D.region_get_use_edge_connections(_nav_region.get_region_rid()))
|
||||
|
||||
|
||||
@@ -1 +1 @@
|
||||
uid://br3a8kjyuwoeg
|
||||
uid://brh8x1wnycrl5
|
||||
|
||||
@@ -27,7 +27,7 @@ func _process(p_delta) -> void:
|
||||
UI toggle: F9
|
||||
Render mode: F10
|
||||
Full screen: F11
|
||||
Mouse toggle: Escape
|
||||
Mouse toggle: Escape / F12
|
||||
"""
|
||||
|
||||
|
||||
@@ -47,7 +47,7 @@ func _unhandled_key_input(p_event: InputEvent) -> void:
|
||||
KEY_F11:
|
||||
toggle_fullscreen()
|
||||
get_viewport().set_input_as_handled()
|
||||
KEY_ESCAPE:
|
||||
KEY_ESCAPE, KEY_F12:
|
||||
if Input.get_mouse_mode() == Input.MOUSE_MODE_VISIBLE:
|
||||
Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)
|
||||
else:
|
||||
@@ -62,4 +62,3 @@ func toggle_fullscreen() -> void:
|
||||
DisplayServer.window_set_size(Vector2(1280, 720))
|
||||
else:
|
||||
DisplayServer.window_set_mode(DisplayServer.WINDOW_MODE_EXCLUSIVE_FULLSCREEN)
|
||||
|
||||
|
||||
@@ -1 +1 @@
|
||||
uid://d0otq0fkpg0nh
|
||||
uid://dne6na1m4xku8
|
||||
|
||||
Reference in New Issue
Block a user