Merge pull request #894 from Calinou/add-large-world-coordinates-demo

Add a large world coordinates demo
This commit is contained in:
Aaron Franke
2023-06-05 10:25:24 -05:00
committed by GitHub
9 changed files with 542 additions and 0 deletions

View File

@@ -0,0 +1,29 @@
# Large World Coordinates
This project showcases optional support for double-precision rendering
and physics in action.
When using a *single-precision* build, precision errors can be noticeable as soon
as you're more than a few thousand units away from the world origin.
When using a *double-precision* build, meshes will remain stable even when very
far away from the world origin (billions of units away or more).
See the
[Large world coordinates documentation](https://docs.godotengine.org/en/latest/tutorials/physics/large_world_coordinates.html)
for more information.
> **Warning**
>
> Official Godot builds do **not** have double-precision support enabled for performance reasons.
> You need to compile a custom engine build to use double precision support.
Languages: GDScript
Renderer: Forward Mobile
## Screenshots
![Large World Coordinates without double-precision engine build](screenshots/large_world_coordinates_single_precision_build.webp)
![Large World Coordinates with double-precision engine build](screenshots/large_world_coordinates_double_precision_build.webp)

View File

@@ -0,0 +1,62 @@
extends VBoxContainer
const ROT_SPEED = 0.003
const ZOOM_SPEED = 0.5
const MAIN_BUTTONS = MOUSE_BUTTON_MASK_LEFT | MOUSE_BUTTON_MASK_MIDDLE | MOUSE_BUTTON_MASK_RIGHT
@export var camera: Camera3D
@export var camera_holder: Node3D
@export var rotation_x: Node3D
@export var node_to_move: Node3D
@export var rigid_body: RigidBody3D
@onready var zoom := camera.position.z
var base_height: int = ProjectSettings.get_setting("display/window/size/viewport_height")
@onready var rot_x := rotation_x.rotation.x
@onready var rot_y := camera_holder.rotation.y
func _ready() -> void:
if OS.has_feature("double"):
%HelpLabel.text = "Double precision is enabled in this engine build.\nNo shaking should occur at high coordinate levels\n(±65,536 or more on any axis)."
%HelpLabel.add_theme_color_override("font_color", Color(0.667, 1, 0.667))
func _process(delta: float) -> void:
%Coordinates.text = "X: [color=#fb9]%f[/color]\nY: [color=#bfa]%f[/color]\nZ: [color=#9cf]%f[/color]" % [node_to_move.position.x, node_to_move.position.y, node_to_move.position.z]
if %IncrementX.button_pressed:
node_to_move.position.x += 10_000 * delta
if %IncrementY.button_pressed:
node_to_move.position.y += 100_000 * delta
if %IncrementZ.button_pressed:
node_to_move.position.z += 1_000_000 * delta
func _input(event: InputEvent) -> void:
if event is InputEventMouseButton:
if event.button_index == MOUSE_BUTTON_WHEEL_UP:
zoom -= ZOOM_SPEED
if event.button_index == MOUSE_BUTTON_WHEEL_DOWN:
zoom += ZOOM_SPEED
zoom = clampf(zoom, 4, 15)
camera.position.z = zoom
if event is InputEventMouseMotion and event.button_mask & MAIN_BUTTONS:
# Compensate motion speed to be resolution-independent (based on the window height).
var relative_motion: Vector2 = event.relative * DisplayServer.window_get_size().y / base_height
rot_y -= relative_motion.x * ROT_SPEED
rot_x -= relative_motion.y * ROT_SPEED
rot_x = clampf(rot_x, -1.4, 0.16)
camera_holder.transform.basis = Basis.from_euler(Vector3(0, rot_y, 0))
rotation_x.transform.basis = Basis.from_euler(Vector3(rot_x, 0, 0))
func _on_go_to_button_pressed(x_position: int) -> void:
if x_position == 0:
# Reset all coordinates, not just X.
node_to_move.position = Vector3.ZERO
else:
node_to_move.position.x = x_position
func _on_open_documentation_pressed() -> void:
OS.shell_open("https://docs.godotengine.org/en/latest/tutorials/physics/large_world_coordinates.html")

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://dendp8h6s03od"
path="res://.godot/imported/icon.webp-e94f9a68b0f625a567a797079e4d325f.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://icon.webp"
dest_files=["res://.godot/imported/icon.webp-e94f9a68b0f625a567a797079e4d325f.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

View File

@@ -0,0 +1,38 @@
; Engine configuration file.
; It's best edited using the editor UI and not directly,
; since the parameters that go here are not all obvious.
;
; Format:
; [section] ; section goes between []
; param=value ; assign values to parameters
config_version=5
[application]
config/name="Large World Coordinates"
config/description="This project showcases optional support for double-precision rendering
and physics in action."
run/main_scene="res://test.tscn"
config/features=PackedStringArray("4.0")
run/low_processor_mode=true
config/icon="res://icon.webp"
[display]
window/stretch/mode="canvas_items"
window/stretch/aspect="expand"
[physics]
common/physics_ticks_per_second=120
[rendering]
renderer/rendering_method="mobile"
lights_and_shadows/directional_shadow/size=2048
lights_and_shadows/directional_shadow/size.mobile=1024
textures/default_filters/anisotropic_filtering_level=4
anti_aliasing/quality/msaa_3d=2
lights_and_shadows/positional_shadow/atlas_size=2048
lights_and_shadows/positional_shadow/atlas_size.mobile=1024

Binary file not shown.

After

Width:  |  Height:  |  Size: 413 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 417 KiB

View File

@@ -0,0 +1,379 @@
[gd_scene load_steps=23 format=3 uid="uid://37j1wgn5e8e"]
[ext_resource type="Script" path="res://controls.gd" id="1_ojycn"]
[sub_resource type="PhysicalSkyMaterial" id="PhysicalSkyMaterial_i2lbx"]
ground_color = Color(1, 1, 1, 1)
[sub_resource type="Sky" id="Sky_rtoqf"]
sky_material = SubResource("PhysicalSkyMaterial_i2lbx")
[sub_resource type="Environment" id="Environment_ixbrf"]
background_mode = 2
sky = SubResource("Sky_rtoqf")
ambient_light_source = 2
ambient_light_color = Color(1, 1, 1, 1)
ambient_light_energy = 0.3
tonemap_mode = 2
tonemap_white = 6.0
[sub_resource type="BoxMesh" id="BoxMesh_rpkrt"]
size = Vector3(16, 16, 16)
[sub_resource type="Gradient" id="Gradient_bk8jh"]
[sub_resource type="FastNoiseLite" id="FastNoiseLite_p8y4k"]
fractal_octaves = 10
[sub_resource type="NoiseTexture2D" id="NoiseTexture2D_hdp3i"]
seamless = true
color_ramp = SubResource("Gradient_bk8jh")
noise = SubResource("FastNoiseLite_p8y4k")
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_eicib"]
albedo_color = Color(0.317647, 0.317647, 0.317647, 1)
albedo_texture = SubResource("NoiseTexture2D_hdp3i")
roughness_texture = SubResource("NoiseTexture2D_hdp3i")
uv1_scale = Vector3(12, 8, 1)
texture_filter = 5
[sub_resource type="BoxMesh" id="BoxMesh_1f2ne"]
size = Vector3(15, 1, 2)
[sub_resource type="SphereMesh" id="SphereMesh_q0pwk"]
radius = 2.0
height = 4.0
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_ekrgh"]
albedo_color = Color(0.266667, 0.666667, 1, 1)
[sub_resource type="TextMesh" id="TextMesh_oxha3"]
text = "Billboard!"
font_size = 72
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_wvbit"]
metallic = 0.91
roughness = 0.14
emission_enabled = true
emission = Color(0.733333, 0.733333, 0.733333, 1)
clearcoat_enabled = true
clearcoat_roughness = 1.0
backlight = Color(0.74902, 0.976471, 0, 1)
disable_receive_shadows = true
billboard_mode = 1
billboard_keep_scale = true
grow_amount = 4.497
[sub_resource type="TorusMesh" id="TorusMesh_44mpc"]
inner_radius = 2.5
outer_radius = 3.5
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_i8ybo"]
transparency = 1
blend_mode = 1
albedo_color = Color(0.0666667, 0.313726, 0.768627, 1)
[sub_resource type="ParticleProcessMaterial" id="ParticleProcessMaterial_r08do"]
emission_shape = 3
emission_box_extents = Vector3(8, 0, 8)
sub_emitter_mode = 3
sub_emitter_amount_at_collision = 1
collision_mode = 1
collision_friction = 0.0
collision_bounce = 0.2
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_jmbue"]
shading_mode = 0
[sub_resource type="SphereMesh" id="SphereMesh_f1qcl"]
material = SubResource("StandardMaterial3D_jmbue")
radius = 0.05
height = 0.1
radial_segments = 4
rings = 1
[sub_resource type="Animation" id="Animation_c3rry"]
length = 0.001
tracks/0/type = "bezier"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("Move/Text:position:x")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"handle_modes": PackedInt32Array(0),
"points": PackedFloat32Array(0, -0.25, 0, 0.25, 0),
"times": PackedFloat32Array(0)
}
tracks/1/type = "bezier"
tracks/1/imported = false
tracks/1/enabled = true
tracks/1/path = NodePath("Move/Text:position:y")
tracks/1/interp = 1
tracks/1/loop_wrap = true
tracks/1/keys = {
"handle_modes": PackedInt32Array(0),
"points": PackedFloat32Array(3.70893, -0.25, 0, 0.25, 0),
"times": PackedFloat32Array(0)
}
tracks/2/type = "bezier"
tracks/2/imported = false
tracks/2/enabled = true
tracks/2/path = NodePath("Move/Text:position:z")
tracks/2/interp = 1
tracks/2/loop_wrap = true
tracks/2/keys = {
"handle_modes": PackedInt32Array(0),
"points": PackedFloat32Array(2, -0.25, 0, 0.25, 0),
"times": PackedFloat32Array(0)
}
[sub_resource type="Animation" id="Animation_ww6nu"]
resource_name = "move_text_around"
length = 2.0
loop_mode = 1
tracks/0/type = "position_3d"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("Move/Text")
tracks/0/interp = 2
tracks/0/loop_wrap = true
tracks/0/keys = PackedFloat32Array()
tracks/1/type = "bezier"
tracks/1/imported = false
tracks/1/enabled = true
tracks/1/path = NodePath("Move/Text:position:x")
tracks/1/interp = 1
tracks/1/loop_wrap = true
tracks/1/keys = {
"handle_modes": PackedInt32Array(0, 0, 0),
"points": PackedFloat32Array(0, -0.25, 0, 0.25, 0, 0, -0.25, 0, 0.25, 0, 0, -0.25, 0, 0.25, 0),
"times": PackedFloat32Array(0, 1, 2)
}
tracks/2/type = "bezier"
tracks/2/imported = false
tracks/2/enabled = true
tracks/2/path = NodePath("Move/Text:position:y")
tracks/2/interp = 1
tracks/2/loop_wrap = true
tracks/2/keys = {
"handle_modes": PackedInt32Array(0, 0, 0),
"points": PackedFloat32Array(3.70893, -0.25, 0, 0.25, 0, 3.70893, -0.25, 0, 0.25, 0, 3.70893, -0.25, 0, 0.25, 0),
"times": PackedFloat32Array(0, 1, 2)
}
tracks/3/type = "bezier"
tracks/3/imported = false
tracks/3/enabled = true
tracks/3/path = NodePath("Move/Text:position:z")
tracks/3/interp = 1
tracks/3/loop_wrap = true
tracks/3/keys = {
"handle_modes": PackedInt32Array(0, 0, 0),
"points": PackedFloat32Array(-2, -0.25, 0, 0.25, 0, 2, -0.25, 0, 0.25, 0, -2, -0.25, 0, 0.25, 0),
"times": PackedFloat32Array(0, 1, 2)
}
[sub_resource type="AnimationLibrary" id="AnimationLibrary_2gye4"]
_data = {
"RESET": SubResource("Animation_c3rry"),
"move_text_around": SubResource("Animation_ww6nu")
}
[node name="Node3D" type="Node3D"]
[node name="DirectionalLight3D" type="DirectionalLight3D" parent="."]
transform = Transform3D(-0.98244, -0.0593698, 0.176879, 0.0241111, 0.899674, 0.435897, -0.185013, 0.432507, -0.882444, 0.181812, 3.12655, 5.93493)
shadow_enabled = true
shadow_bias = 0.04
shadow_blur = 2.0
directional_shadow_fade_start = 1.0
directional_shadow_max_distance = 35.0
[node name="WorldEnvironment" type="WorldEnvironment" parent="."]
environment = SubResource("Environment_ixbrf")
[node name="Move" type="Node3D" parent="."]
[node name="Ground" type="MeshInstance3D" parent="Move"]
transform = Transform3D(-1, 0, -3.82137e-15, 0, 1, -8.74228e-08, 3.82137e-15, -8.74228e-08, -1, -7.45058e-09, -8, 0)
mesh = SubResource("BoxMesh_rpkrt")
skeleton = NodePath("../..")
surface_material_override/0 = SubResource("StandardMaterial3D_eicib")
[node name="GPUParticlesCollisionBox3D" type="GPUParticlesCollisionBox3D" parent="Move/Ground"]
transform = Transform3D(-7.37408e-15, 4.37114e-08, -1, 8.74228e-08, 1, 4.37114e-08, 1, -8.74228e-08, -1.31061e-14, -7.45058e-09, 9.53674e-07, 9.53674e-07)
size = Vector3(16, 16, 16)
[node name="Flat" type="MeshInstance3D" parent="Move"]
transform = Transform3D(1, 0, 0, 0, 0.996195, -0.0871557, 0, 0.0871557, 0.996195, 0, -0.5, 4.9)
mesh = SubResource("BoxMesh_1f2ne")
[node name="Sphere" type="MeshInstance3D" parent="Move"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0)
mesh = SubResource("SphereMesh_q0pwk")
skeleton = NodePath("../..")
surface_material_override/0 = SubResource("StandardMaterial3D_ekrgh")
[node name="GPUParticlesCollisionSphere3D" type="GPUParticlesCollisionSphere3D" parent="Move/Sphere"]
radius = 2.0
[node name="Text" type="MeshInstance3D" parent="Move"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 3.70893, 2)
cast_shadow = 0
mesh = SubResource("TextMesh_oxha3")
surface_material_override/0 = SubResource("StandardMaterial3D_wvbit")
[node name="Torus" type="MeshInstance3D" parent="Move"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0)
mesh = SubResource("TorusMesh_44mpc")
skeleton = NodePath("../..")
surface_material_override/0 = SubResource("StandardMaterial3D_i8ybo")
[node name="CameraHolder" type="Node3D" parent="Move"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -1, 0)
[node name="RotationX" type="Node3D" parent="Move/CameraHolder"]
[node name="Camera3D" type="Camera3D" parent="Move/CameraHolder/RotationX"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 3, 7)
[node name="GPUParticles3D" type="GPUParticles3D" parent="Move"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 13, 0)
amount = 1000
lifetime = 3.0
fixed_fps = 0
interpolate = false
collision_base_size = 0.05
visibility_aabb = AABB(-15.9834, -43.9765, -15.9858, 31.982, 43.9765, 31.9815)
local_coords = true
process_material = SubResource("ParticleProcessMaterial_r08do")
draw_pass_1 = SubResource("SphereMesh_f1qcl")
[node name="Controls" type="VBoxContainer" parent="." node_paths=PackedStringArray("camera", "camera_holder", "rotation_x", "node_to_move", "rigid_body")]
offset_left = 16.0
offset_top = 16.0
offset_right = 350.0
offset_bottom = 399.0
theme_override_constants/separation = 10
script = ExtResource("1_ojycn")
camera = NodePath("../Move/CameraHolder/RotationX/Camera3D")
camera_holder = NodePath("../Move/CameraHolder")
rotation_x = NodePath("../Move/CameraHolder/RotationX")
node_to_move = NodePath("../Move")
rigid_body = NodePath("")
[node name="HelpLabel" type="Label" parent="Controls"]
unique_name_in_owner = true
layout_mode = 2
theme_override_colors/font_color = Color(1, 0.666667, 0.666667, 1)
theme_override_colors/font_outline_color = Color(0, 0, 0, 1)
theme_override_constants/outline_size = 4
text = "Double precision is not enabled in this engine build.
Visible shaking is expected at high coordinate levels
(±65,536 or more on any axis)."
[node name="Button" type="Button" parent="Controls"]
layout_mode = 2
text = "Open Documentation"
[node name="HSeparator" type="HSeparator" parent="Controls"]
layout_mode = 2
[node name="Coordinates" type="RichTextLabel" parent="Controls"]
unique_name_in_owner = true
custom_minimum_size = Vector2(0, 70)
layout_mode = 2
theme_override_colors/font_outline_color = Color(0, 0, 0, 1)
theme_override_constants/outline_size = 4
bbcode_enabled = true
text = "Object coordinates:"
[node name="IncrementX" type="CheckButton" parent="Controls"]
unique_name_in_owner = true
custom_minimum_size = Vector2(320, 0)
layout_mode = 2
size_flags_horizontal = 0
theme_override_colors/font_outline_color = Color(0, 0, 0, 1)
theme_override_constants/outline_size = 4
button_pressed = true
text = "Increment X (10,000 per second)"
[node name="IncrementY" type="CheckButton" parent="Controls"]
unique_name_in_owner = true
custom_minimum_size = Vector2(320, 0)
layout_mode = 2
size_flags_horizontal = 0
theme_override_colors/font_outline_color = Color(0, 0, 0, 1)
theme_override_constants/outline_size = 4
text = "Increment Y (100,000 per second)"
[node name="IncrementZ" type="CheckButton" parent="Controls"]
unique_name_in_owner = true
custom_minimum_size = Vector2(320, 0)
layout_mode = 2
size_flags_horizontal = 0
theme_override_colors/font_outline_color = Color(0, 0, 0, 1)
theme_override_constants/outline_size = 4
text = "Increment Z (1,000,000 per second)"
[node name="GoTo" type="Label" parent="Controls"]
layout_mode = 2
theme_override_colors/font_outline_color = Color(0, 0, 0, 1)
theme_override_constants/outline_size = 4
text = "Go to X coordinate:"
[node name="HFlowContainer" type="HFlowContainer" parent="Controls"]
layout_mode = 2
[node name="Button" type="Button" parent="Controls/HFlowContainer"]
layout_mode = 2
text = "0 (Reset All)"
[node name="Button2" type="Button" parent="Controls/HFlowContainer"]
layout_mode = 2
text = "10,000"
[node name="Button3" type="Button" parent="Controls/HFlowContainer"]
layout_mode = 2
text = "100,000"
[node name="Button4" type="Button" parent="Controls/HFlowContainer"]
layout_mode = 2
text = "1,000,000"
[node name="Button5" type="Button" parent="Controls/HFlowContainer"]
layout_mode = 2
text = "10,000,000"
[node name="Button6" type="Button" parent="Controls/HFlowContainer"]
layout_mode = 2
text = "100,000,000"
[node name="Button7" type="Button" parent="Controls/HFlowContainer"]
layout_mode = 2
text = "1,000,000,000"
[node name="Button8" type="Button" parent="Controls/HFlowContainer"]
layout_mode = 2
text = "1,000,000,000,000"
[node name="Button9" type="Button" parent="Controls/HFlowContainer"]
layout_mode = 2
text = "10,000,000,000,000"
[node name="AnimationPlayer" type="AnimationPlayer" parent="."]
autoplay = "move_text_around"
libraries = {
"": SubResource("AnimationLibrary_2gye4")
}
[connection signal="pressed" from="Controls/Button" to="Controls" method="_on_open_documentation_pressed"]
[connection signal="pressed" from="Controls/HFlowContainer/Button" to="Controls" method="_on_go_to_button_pressed" binds= [0]]
[connection signal="pressed" from="Controls/HFlowContainer/Button2" to="Controls" method="_on_go_to_button_pressed" binds= [10000]]
[connection signal="pressed" from="Controls/HFlowContainer/Button3" to="Controls" method="_on_go_to_button_pressed" binds= [100000]]
[connection signal="pressed" from="Controls/HFlowContainer/Button4" to="Controls" method="_on_go_to_button_pressed" binds= [1000000]]
[connection signal="pressed" from="Controls/HFlowContainer/Button5" to="Controls" method="_on_go_to_button_pressed" binds= [10000000]]
[connection signal="pressed" from="Controls/HFlowContainer/Button6" to="Controls" method="_on_go_to_button_pressed" binds= [100000000]]
[connection signal="pressed" from="Controls/HFlowContainer/Button7" to="Controls" method="_on_go_to_button_pressed" binds= [1000000000]]
[connection signal="pressed" from="Controls/HFlowContainer/Button8" to="Controls" method="_on_go_to_button_pressed" binds= [1000000000000]]
[connection signal="pressed" from="Controls/HFlowContainer/Button9" to="Controls" method="_on_go_to_button_pressed" binds= [10000000000000]]