Compare commits

...

15 Commits

76 changed files with 1519 additions and 124 deletions

View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2024 DmitriySalnikov
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the Software), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, andor sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -0,0 +1,157 @@
![icon](/images/icon_3d_128.png)
# Debug drawing utility for Godot
This is an add-on for debug drawing in 3D and for some 2D overlays, which is written in `C++` and can be used with `GDScript` or `C#`.
Based on my previous addon, which was developed [only for C#](https://github.com/DmitriySalnikov/godot_debug_draw_cs), and which was inspired by [Zylann's GDScript addon](https://github.com/Zylann/godot_debug_draw)
## [Documentation](https://dd3d.dmitriysalnikov.ru/docs/)
## [Godot 3 version](https://github.com/DmitriySalnikov/godot_debug_draw_3d/tree/godot_3)
## Support me
Your support adds motivation to develop my public projects.
<a href="https://boosty.to/dmitriysalnikov/donate"><img src="/docs/images/boosty.png" alt="Boosty" width=150px/></a>
<a href="#"><img src="/docs/images/USDT-TRC20.png" alt="USDT-TRC20" width=150px/></a>
<b>USDT-TRC20 TEw934PrsffHsAn5M63SoHYRuZo984EF6v</b>
## Features
3D:
* Arrow
* Billboard opaque square
* Box
* Camera Frustum
* Cylinder
* Gizmo
* Grid
* Line
* Line Path
* Line with Arrow
* Plane
* Points
* Position 3D (3 crossing axes)
* Sphere
* 3D Text
2D:
* **[Work in progress]**
Overlay:
* Text (with grouping and coloring)
Precompiled for:
* Windows
* Linux (built on Ubuntu 22.04)
* macOS (10.15+)
* Android (5.0+)
* iOS
* Web (Firefox is supported by Godot 4.3+)
This addon supports working with several World3D and different Viewports.
There is also a no depth test mode and other settings that can be changed for each instance.
This library supports double-precision builds, for more information, [see the documentation](https://dd3d.dmitriysalnikov.ru/docs/?page=md_docs_2DoublePrecision.html).
## [Interactive Web Demo](https://dd3d.dmitriysalnikov.ru/demo/)
[![screenshot_web](/images/screenshot_web.png)](https://dd3d.dmitriysalnikov.ru/demo/)
## Download
To download, use the [Godot Asset Library](https://godotengine.org/asset-library/asset/1766) or use one of the stable versions from the [GitHub Releases](https://github.com/DmitriySalnikov/godot_debug_draw_3d/releases) page.
For versions prior to `1.4.5`, just download one of the `source codes` in the assets. For newer versions, download `debug-draw-3d_[version].zip`.
### Installation
* Close editor
* Copy `addons/debug_draw_3d` to your `addons` folder, create it if the folder doesn't exist
* Launch editor
## Examples
More examples can be found in the `examples_dd3d/` folder.
Simple test:
```gdscript
func _process(delta: float) -> void:
var _time = Time.get_ticks_msec() / 1000.0
var box_pos = Vector3(0, sin(_time * 4), 0)
var line_begin = Vector3(-1, sin(_time * 4), 0)
var line_end = Vector3(1, cos(_time * 4), 0)
DebugDraw3D.draw_box(box_pos, Quaternion.IDENTITY, Vector3(1, 2, 1), Color(0, 1, 0))
DebugDraw3D.draw_line(line_begin, line_end, Color(1, 1, 0))
DebugDraw2D.set_text("Time", _time)
DebugDraw2D.set_text("Frames drawn", Engine.get_frames_drawn())
DebugDraw2D.set_text("FPS", Engine.get_frames_per_second())
DebugDraw2D.set_text("delta", delta)
```
![screenshot_1](/images/screenshot_1.png)
An example of using scoped configs:
```gdscript
@tool
extends Node3D
func _ready():
# Set the base scoped_config.
# Each frame will be reset to these scoped values.
DebugDraw3D.scoped_config().set_thickness(0.1).set_center_brightness(0.6)
func _process(delta):
# Draw using the base scoped config.
DebugDraw3D.draw_box(Vector3.ZERO, Quaternion.IDENTITY, Vector3.ONE * 2, Color.CORNFLOWER_BLUE)
if true:
# Create a scoped config that will exist until exiting this if.
var _s = DebugDraw3D.new_scoped_config().set_thickness(0).set_center_brightness(0.1)
# Draw with a thickness of 0
DebugDraw3D.draw_box(Vector3.ZERO, Quaternion.IDENTITY, Vector3.ONE, Color.RED)
# If necessary, the values inside this scope can be changed
# even before each call to draw_*.
_s.set_thickness(0.05)
DebugDraw3D.draw_box(Vector3(1,0,1), Quaternion.IDENTITY, Vector3.ONE * 1, Color.BLUE_VIOLET)
```
![screenshot_5](/images/screenshot_5.png)
> [!TIP]
>
> If you want to use a non-standard Viewport for rendering a 3d scene, then do not forget to specify it in the scoped config!
## API
This project has a separate [documentation](https://dd3d.dmitriysalnikov.ru/docs/) page.
Also, a list of all functions is available in the documentation inside the editor (see `DebugDraw3D` and `DebugDraw2D`).
![screenshot_4](/images/screenshot_4.png)
## Known issues and limitations
The text in the keys and values of a text group cannot contain multi-line strings.
The entire text overlay can only be placed in one corner.
[Frustum of Camera3D does not take into account the window size from ProjectSettings](https://github.com/godotengine/godot/issues/70362).
## More screenshots
`DebugDrawDemoScene.tscn` in editor
![screenshot_2](/images/screenshot_2.png)
`DebugDrawDemoScene.tscn` in play mode
![screenshot_3](/images/screenshot_3.png)

View File

@ -0,0 +1,153 @@
[configuration]
entry_symbol = "debug_draw_3d_library_init"
compatibility_minimum = "4.2.2"
reloadable = false
[dependencies]
; example.x86_64 = { "relative or absolute path to the dependency" : "the path relative to the exported project", }
; -------------------------------------
; debug
macos = { }
windows.x86_64 = { }
linux.x86_64 = { }
; by default godot is using threads
web.wasm32.nothreads = {}
web.wasm32 = {}
android.arm32 = { }
android.arm64 = { }
android.x86_32 = { }
android.x86_64 = { }
ios = {}
; -------------------------------------
; release no debug draw
macos.template_release = { }
windows.template_release.x86_64 = { }
linux.template_release.x86_64 = { }
web.template_release.wasm32.nothreads = { }
web.template_release.wasm32 = { }
android.template_release.arm32 = { }
android.template_release.arm64 = { }
android.template_release.x86_32 = { }
android.template_release.x86_64 = { }
ios.template_release = {}
; -------------------------------------
; release forced debug draw
macos.template_release.forced_dd3d = { }
windows.template_release.x86_64.forced_dd3d = { }
linux.template_release.x86_64.forced_dd3d = { }
web.template_release.wasm32.nothreads.forced_dd3d = { }
web.template_release.wasm32.forced_dd3d = { }
ios.template_release.forced_dd3d = {}
[libraries]
; -------------------------------------
; debug
macos = "libs/libdd3d.macos.editor.universal.framework"
windows.x86_64 = "libs/libdd3d.windows.editor.x86_64.dll"
linux.x86_64 = "libs/libdd3d.linux.editor.x86_64.so"
web.wasm32.nothreads = "libs/libdd3d.web.template_debug.wasm32.wasm"
web.wasm32 = "libs/libdd3d.web.template_debug.wasm32.threads.wasm"
android.arm32 = "libs/libdd3d.android.template_debug.arm32.so"
android.arm64 = "libs/libdd3d.android.template_debug.arm64.so"
android.x86_32 = "libs/libdd3d.android.template_debug.x86_32.so"
android.x86_64 = "libs/libdd3d.android.template_debug.x86_64.so"
ios = "libs/libdd3d.ios.template_debug.universal.dylib"
; -------------------------------------
; release no debug draw
macos.template_release = "libs/libdd3d.macos.template_release.universal.framework"
windows.template_release.x86_64 = "libs/libdd3d.windows.template_release.x86_64.dll"
linux.template_release.x86_64 = "libs/libdd3d.linux.template_release.x86_64.so"
web.template_release.wasm32.nothreads = "libs/libdd3d.web.template_release.wasm32.wasm"
web.template_release.wasm32 = "libs/libdd3d.web.template_release.wasm32.threads.wasm"
android.template_release.arm32 = "libs/libdd3d.android.template_release.arm32.so"
android.template_release.arm64 = "libs/libdd3d.android.template_release.arm64.so"
android.template_release.x86_32 = "libs/libdd3d.android.template_release.x86_32.so"
android.template_release.x86_64 = "libs/libdd3d.android.template_release.x86_64.so"
ios.template_release = "libs/libdd3d.ios.template_release.universal.dylib"
; -------------------------------------
; release forced debug draw
macos.template_release.forced_dd3d = "libs/libdd3d.macos.template_release.universal.enabled.framework"
windows.template_release.x86_64.forced_dd3d = "libs/libdd3d.windows.template_release.x86_64.enabled.dll"
linux.template_release.x86_64.forced_dd3d = "libs/libdd3d.linux.template_release.x86_64.enabled.so"
web.template_release.wasm32.nothreads.forced_dd3d = "libs/libdd3d.web.template_release.wasm32.enabled.wasm"
web.template_release.wasm32.forced_dd3d = "libs/libdd3d.web.template_release.wasm32.threads.enabled.wasm"
ios.template_release.forced_dd3d = "libs/libdd3d.ios.template_release.universal.enabled.dylib"
; -------------------------------------
; DOUBLE PRECISION
; -------------------------------------
; -------------------------------------
; debug
macos.double = "libs/libdd3d.macos.editor.universal.double.framework"
windows.x86_64.double = "libs/libdd3d.windows.editor.x86_64.double.dll"
linux.x86_64.double = "libs/libdd3d.linux.editor.x86_64.double.so"
web.wasm32.nothreads.double = "libs/libdd3d.web.template_debug.wasm32.double.wasm"
web.wasm32.double = "libs/libdd3d.web.template_debug.wasm32.threads.double.wasm"
android.arm32.double = "libs/libdd3d.android.template_debug.arm32.double.so"
android.arm64.double = "libs/libdd3d.android.template_debug.arm64.double.so"
android.x86_32.double = "libs/libdd3d.android.template_debug.x86_32.double.so"
android.x86_64.double = "libs/libdd3d.android.template_debug.x86_64.double.so"
ios.double = "libs/libdd3d.ios.template_debug.universal.dylib"
; -------------------------------------
; release no debug draw
macos.template_release.double = "libs/libdd3d.macos.template_release.universal.double.framework"
windows.template_release.x86_64.double = "libs/libdd3d.windows.template_release.x86_64.double.dll"
linux.template_release.x86_64.double = "libs/libdd3d.linux.template_release.x86_64.double.so"
web.template_release.wasm32.nothreads.double = "libs/libdd3d.web.template_release.wasm32.double.wasm"
web.template_release.wasm32.double = "libs/libdd3d.web.template_release.wasm32.threads.double.wasm"
android.template_release.arm32.double = "libs/libdd3d.android.template_release.arm32.double.so"
android.template_release.arm64.double = "libs/libdd3d.android.template_release.arm64.double.so"
android.template_release.x86_32.double = "libs/libdd3d.android.template_release.x86_32.double.so"
android.template_release.x86_64.double = "libs/libdd3d.android.template_release.x86_64.double.so"
ios.template_release.double = "libs/libdd3d.ios.template_release.universal.double.dylib"
; -------------------------------------
; release forced debug draw
macos.template_release.forced_dd3d.double = "libs/libdd3d.macos.template_release.universal.enabled.double.framework"
windows.template_release.x86_64.forced_dd3d.double = "libs/libdd3d.windows.template_release.x86_64.enabled.double.dll"
linux.template_release.x86_64.forced_dd3d.double = "libs/libdd3d.linux.template_release.x86_64.enabled.double.so"
web.template_release.wasm32.nothreads.forced_dd3d.double = "libs/libdd3d.web.template_release.wasm32.enabled.double.wasm"
web.template_release.wasm32.forced_dd3d.double = "libs/libdd3d.web.template_release.wasm32.threads.enabled.double.wasm"
ios.template_release.forced_dd3d.double = "libs/libdd3d.ios.template_release.universal.enabled.double.dylib"

View File

@ -0,0 +1 @@
uid://svqaxfp5kyrl

View File

View File

@ -0,0 +1,37 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>libdd3d.macos.editor.universal.dylib</string>
<key>CFBundleName</key>
<string>Debug Draw 3D</string>
<key>CFBundleDisplayName</key>
<string>Debug Draw 3D</string>
<key>CFBundleIdentifier</key>
<string>ru.dmitriysalnikov.dd3d</string>
<key>NSHumanReadableCopyright</key>
<string>Copyright (c) Dmitriy Salnikov.</string>
<key>CFBundleVersion</key>
<string>1.5.1</string>
<key>CFBundleShortVersionString</key>
<string>1.5.1</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CSResourcesFileMapped</key>
<true/>
<key>DTPlatformName</key>
<string>macosx</string>
<key>LSMinimumSystemVersion</key>
<string>10.14</string>
<key>CFBundleSupportedPlatforms</key>
<array>
<string>MacOSX</string>
</array>
</dict>
</plist>

View File

@ -0,0 +1,37 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>libdd3d.macos.template_release.universal.enabled.dylib</string>
<key>CFBundleName</key>
<string>Debug Draw 3D</string>
<key>CFBundleDisplayName</key>
<string>Debug Draw 3D</string>
<key>CFBundleIdentifier</key>
<string>ru.dmitriysalnikov.dd3d</string>
<key>NSHumanReadableCopyright</key>
<string>Copyright (c) Dmitriy Salnikov.</string>
<key>CFBundleVersion</key>
<string>1.5.1</string>
<key>CFBundleShortVersionString</key>
<string>1.5.1</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CSResourcesFileMapped</key>
<true/>
<key>DTPlatformName</key>
<string>macosx</string>
<key>LSMinimumSystemVersion</key>
<string>10.14</string>
<key>CFBundleSupportedPlatforms</key>
<array>
<string>MacOSX</string>
</array>
</dict>
</plist>

View File

@ -0,0 +1,37 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>libdd3d.macos.template_release.universal.dylib</string>
<key>CFBundleName</key>
<string>Debug Draw 3D</string>
<key>CFBundleDisplayName</key>
<string>Debug Draw 3D</string>
<key>CFBundleIdentifier</key>
<string>ru.dmitriysalnikov.dd3d</string>
<key>NSHumanReadableCopyright</key>
<string>Copyright (c) Dmitriy Salnikov.</string>
<key>CFBundleVersion</key>
<string>1.5.1</string>
<key>CFBundleShortVersionString</key>
<string>1.5.1</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CSResourcesFileMapped</key>
<true/>
<key>DTPlatformName</key>
<string>macosx</string>
<key>LSMinimumSystemVersion</key>
<string>10.14</string>
<key>CFBundleSupportedPlatforms</key>
<array>
<string>MacOSX</string>
</array>
</dict>
</plist>

View File

@ -0,0 +1,103 @@
// Voronoi fractal steel material
// Based on https://www.shadertoy.com/view/4sl3Dr
shader_type spatial;
uniform vec2 uv_scale = vec2(1.0);
uniform float edge_sharpness = 0.25;
uniform vec3 base_color: source_color = vec3(1.0);
uniform int octaves = 3;
uniform float octave_dropoff = 0.7;
uniform float octave_scale = 3.0;
uniform float metallic = 1.0;
uniform float roughness_scale = 1.0;
uniform float bump_strength = 1.0;
// 1D random numbers
float rand(float n)
{
return fract(sin(n) * 43758.5453123374897);
}
// 2D random numbers
vec2 rand2(vec2 p)
{
return fract(vec2(sin(p.x * 591.32 + p.y * 154.077), cos(p.x * 391.32 + p.y * 49.077)));
}
// 1D noise
float noise1(float p)
{
float fl = floor(p);
float fc = fract(p);
return mix(rand(fl), rand(fl + 1.0), fc);
}
// voronoi distance noise, based on iq's articles
float voronoi(vec2 x)
{
vec2 p = floor(x);
vec2 f = fract(x);
vec2 res = vec2(8.0);
for(float j = -1.0; j <= 1.0; j ++)
{
for(float i = -1.0; i <= 1.0; i ++)
{
vec2 b = vec2(i, j);
vec2 r = vec2(b) - f + rand2(p + b);
// chebyshev distance, one of many ways to do this
float d = max(abs(r.x), abs(r.y));
if(d < res.x)
{
res.y = res.x;
res.x = d;
}
else if(d < res.y)
{
res.y = d;
}
}
}
return res.y - res.x;
}
void fragment() {
vec2 uv = (UV - 0.5) * 2.0 * uv_scale;
float value = 0.0;
// Octaves
float a = 0.6;
float f = 1.0;
for(int i = 0; i < octaves; i++) {
float v1 = voronoi(uv * f + 5.0);
float v2 = 0.0;
// Sharp edges
v1 = 1.0 - smoothstep(0.0, edge_sharpness, v1);
// noise as intensity map
v2 = a * (noise1(v1 * 5.5 + 0.1));
value += v2;
f *= octave_scale;
a *= octave_dropoff;
}
// Use value as bump map
float dZ = 1.0 / bump_strength;
vec3 nmap = normalize(vec3(dFdx(value), dFdy(value), dZ));
NORMAL_MAP = nmap / 2.0 + 1.0;
ALBEDO = value * base_color;
ROUGHNESS = value * roughness_scale;
METALLIC = metallic;
}

View File

@ -0,0 +1 @@
uid://c0gt2lo07w7w

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -27,11 +27,15 @@ gdscript/warnings/unsafe_method_access=2
gdscript/warnings/unsafe_cast=1
gdscript/warnings/unsafe_call_argument=2
[debug_draw_3d]
settings/addon_root_folder="res://addons/debug_draw_3d"
settings/updates/check_for_updates=false
[display]
window/size/viewport_width=1920
window/size/viewport_height=1080
window/vsync/vsync_mode=0
[dotnet]
@ -132,19 +136,27 @@ debug_4={
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194335,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
]
}
debug_speed_up={
"deadzone": 0.2,
"events": [Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"button_mask":8,"position":Vector2(160, 1),"global_position":Vector2(169, 47),"factor":1.0,"button_index":4,"canceled":false,"pressed":true,"double_click":false,"script":null)
]
}
debug_speed_down={
"deadzone": 0.2,
"events": [Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"button_mask":16,"position":Vector2(145, 7),"global_position":Vector2(154, 53),"factor":1.0,"button_index":5,"canceled":false,"pressed":true,"double_click":false,"script":null)
]
}
[layer_names]
3d_render/layer_1="Global Noise Layer"
3d_render/layer_1="High Detail"
3d_render/layer_2="Medium Detail"
3d_render/layer_3="Low Detail"
3d_render/layer_10="Global Noise Layer"
3d_physics/layer_1="World Geometry"
3d_physics/layer_2="Player"
3d_physics/layer_3="Layer 3"
[rendering]
lights_and_shadows/directional_shadow/size=8192
lights_and_shadows/directional_shadow/soft_shadow_filter_quality=3
lights_and_shadows/positional_shadow/soft_shadow_filter_quality=3
anti_aliasing/quality/msaa_3d=3
anti_aliasing/quality/screen_space_aa=1
anti_aliasing/quality/use_debanding=true

View File

@ -2,17 +2,19 @@ class_name DebugMovement extends Node
## Movement controller for debug flight
const ACCELERATION := 10.0
const SPEED_SCALE_FACTOR := 1.2
@export var enabled := false
@export var normal_speed := 160.0
@export var fast_speed := 320.0
@export var speed_scale := 1.0
@onready var character: CharacterBody3D = get_parent()
func get_speed() -> float:
return fast_speed if Input.is_action_pressed("sprint") else normal_speed
return speed_scale * (fast_speed if Input.is_action_pressed("sprint") else normal_speed)
func _physics_process(delta: float) -> void:
@ -30,3 +32,11 @@ func _physics_process(delta: float) -> void:
character.velocity = character.velocity.lerp(motion, weight)
character.move_and_slide()
func _unhandled_input(event: InputEvent) -> void:
if enabled:
if event.is_action_pressed("debug_speed_up"):
speed_scale *= SPEED_SCALE_FACTOR
elif event.is_action_pressed("debug_speed_down"):
speed_scale /= SPEED_SCALE_FACTOR

View File

@ -67,6 +67,7 @@ script = ExtResource("1_5f2sf")
shape = SubResource("CapsuleShape3D_qnmj6")
[node name="MeshInstance3D" type="MeshInstance3D" parent="."]
layers = 7
gi_mode = 0
mesh = SubResource("CapsuleMesh_4anbu")
@ -94,11 +95,12 @@ rebound_time_curve = SubResource("Curve_ylhto")
script = ExtResource("1_rxibo")
priority = 1
tween_resource = SubResource("Resource_244u8")
noise_emitter_layer = 1
noise_emitter_layer = 512
metadata/_custom_type_script = "uid://csjccrhj5wnx7"
[node name="MeshInstance3D" type="MeshInstance3D" parent="CameraOffset/CameraController/StrafeBankEffect/FallKickEffect/PhantomCamera3D"]
transform = Transform3D(1, 0, 0, 0, -4.371139e-08, -1, 0, 1, -4.371139e-08, 0, 0, -0.45)
layers = 7
gi_mode = 0
mesh = SubResource("CapsuleMesh_o822w")
@ -118,6 +120,8 @@ metadata/_custom_type_script = "uid://d11erhxna68vd"
[node name="DebugMovement" type="Node" parent="."]
unique_name_in_owner = true
script = ExtResource("10_ylhto")
normal_speed = 500.0
fast_speed = 1000.0
metadata/_custom_type_script = "uid://htwqrc73xg7q"
[node name="DebugHUD" type="CanvasLayer" parent="." node_paths=PackedStringArray("player")]

13
src/util/auto_range.gd Normal file
View File

@ -0,0 +1,13 @@
class_name AutoRange extends Node
## Component that automatically adjusts the visibility range of its parent to match LOD bounds
@export var lod: WorldGen.LOD
@export_range(0.0, 1.0) var end_margin_pct := 0.05
func _ready() -> void:
var target: GeometryInstance3D = get_parent()
target.visibility_range_end = WorldGenManager.get_lod_radius(lod)
target.visibility_range_end_margin = end_margin_pct * target.visibility_range_end
queue_free()

View File

@ -0,0 +1 @@
uid://cv0o1lirqeq44

View File

@ -1,45 +0,0 @@
class_name Chunk extends Node3D
## A discrete generated chunk of the world
const SIZE := Vector2(64, 64)
const SCENE := preload("res://src/world/generation/chunk/chunk.tscn")
@export var construct_offset := Vector2(0.1, 0.0)
@export var construct_height_factor := 300.0
@export var construct_height_threshold := 30.0
func chunk_position() -> Vector2:
return Chunk.world_to_chunk(position)
func generate() -> void:
# TODO: this
print_debug("Generating chunk at ", chunk_position())
# Let's generate a building...
var construct_noise := WorldGenManager.noise.get_noise_2dv(chunk_position() + construct_offset)
var construct_height := construct_noise * construct_height_factor
if construct_height > construct_height_threshold:
print_debug("GENERATING CONSTRUCT")
var construct := CSGBox3D.new()
add_child(construct)
construct.size = Vector3(60, construct_height, 60)
construct.position = Vector3(2, construct_height / 2, 2)
construct.collision_layer = 1
construct.use_collision = true
static func chunk_to_world(chunk_pos: Vector2) -> Vector3:
return Vector3(chunk_pos.x * SIZE.x, 0, chunk_pos.y * SIZE.y)
static func world_to_chunk(world_pos: Vector3) -> Vector2:
return Vector2(world_pos.x / SIZE.x, world_pos.z / SIZE.y)
static func generate_chunk(chunk_pos: Vector2) -> Chunk:
var instance: Chunk = SCENE.instantiate()
instance.position = Chunk.chunk_to_world(chunk_pos)
instance.generate()
return instance

View File

@ -1 +0,0 @@
uid://chqpqe4anvamd

View File

@ -1,23 +0,0 @@
[gd_scene load_steps=4 format=3 uid="uid://crs68yhijqkca"]
[ext_resource type="Script" uid="uid://chqpqe4anvamd" path="res://src/world/generation/chunk/chunk.gd" id="1_87ter"]
[sub_resource type="PlaneMesh" id="PlaneMesh_0cma0"]
size = Vector2(64, 64)
subdivide_width = 64
subdivide_depth = 64
center_offset = Vector3(32, 0, 32)
[sub_resource type="ConvexPolygonShape3D" id="ConvexPolygonShape3D_87ter"]
points = PackedVector3Array(1.9073486e-06, 0, 1.9073486e-06, 1.9073486e-06, 0, 64, 64, 0, 1.9073486e-06, 64, 0, 64)
[node name="Chunk" type="Node3D"]
script = ExtResource("1_87ter")
[node name="MeshInstance3D" type="MeshInstance3D" parent="."]
mesh = SubResource("PlaneMesh_0cma0")
[node name="StaticBody3D" type="StaticBody3D" parent="MeshInstance3D"]
[node name="CollisionShape3D" type="CollisionShape3D" parent="MeshInstance3D/StaticBody3D"]
shape = SubResource("ConvexPolygonShape3D_87ter")

View File

@ -0,0 +1,370 @@
[gd_scene load_steps=11 format=3 uid="uid://nllc8ljmn37g"]
[ext_resource type="Script" uid="uid://drk82eeqk2mjs" path="res://src/world/generation/feature/generation_feature.gd" id="1_ek7o7"]
[ext_resource type="Material" uid="uid://0ja682cfcvu3" path="res://assets/materials/shaders/megalith_base.material" id="2_pko82"]
[ext_resource type="Material" uid="uid://bjbctidts4k5b" path="res://assets/materials/shaders/megalith_interior.material" id="3_yw1ox"]
[ext_resource type="PackedScene" uid="uid://cwygxhknl2h8r" path="res://src/world/generation/layer/metro_grid_layer/metro_grid_layer.tscn" id="4_fy7wq"]
[ext_resource type="Script" uid="uid://cv0o1lirqeq44" path="res://src/util/auto_range.gd" id="4_kox75"]
[sub_resource type="PlaneMesh" id="PlaneMesh_pko82"]
size = Vector2(100000, 100000)
[sub_resource type="ConcavePolygonShape3D" id="ConcavePolygonShape3D_ek7o7"]
data = PackedVector3Array(50000, 0, 50000, -50000, 0, 50000, 50000, 0, -50000, -50000, 0, 50000, -50000, 0, -50000, 50000, 0, -50000)
[sub_resource type="Curve" id="Curve_0w44q"]
_limits = [1.0, 6.0, 0.0, 1.0]
_data = [Vector2(0, 6), 0.0, -14.656702, 0, 0, Vector2(1, 1), 0.0, 0.0, 0, 0]
point_count = 2
[sub_resource type="Curve" id="Curve_amoo5"]
_limits = [1.0, 20.0, 0.0, 1.0]
_data = [Vector2(0, 1), 0.0, 0.0, 0, 0, Vector2(1, 20), 0.0, 0.0, 0, 0]
point_count = 2
[sub_resource type="Curve" id="Curve_kox75"]
_limits = [0.0, 4.0, 0.0, 1.0]
_data = [Vector2(0, 4), 0.0, 0.0, 0, 0]
point_count = 1
[node name="Arcology" type="Node3D"]
script = ExtResource("1_ek7o7")
metadata/_custom_type_script = "uid://drk82eeqk2mjs"
[node name="InnerPyramid" type="CSGCylinder3D" parent="."]
transform = Transform3D(0.70710677, 0, 0.70710677, 0, 1, 0, -0.70710677, 0, 0.70710677, 50000, 30000, 50000)
layers = 4
visibility_range_fade_mode = 1
use_collision = true
radius = 60000.0
height = 60000.0
sides = 4
cone = true
smooth_faces = false
[node name="OuterPyramid" type="CSGCylinder3D" parent="InnerPyramid"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 5000, 0)
layers = 4
radius = 70000.0
height = 70000.0
sides = 4
cone = true
smooth_faces = false
material = ExtResource("2_pko82")
[node name="TopCutoff" type="CSGBox3D" parent="InnerPyramid/OuterPyramid"]
transform = Transform3D(0.70710677, 0, -0.70710677, 0, 1, 0, 0.70710677, 0, 0.70710677, 0, 30000, 0)
layers = 4
operation = 2
size = Vector3(100000, 80000, 100000)
[node name="Slots" type="CSGCombiner3D" parent="InnerPyramid"]
transform = Transform3D(0.70710677, 0, -0.70710677, 0, 1, 0, 0.70710677, 0, 0.70710677, 0, -18000, 0)
layers = 4
operation = 2
[node name="CSGBox3D2" type="CSGBox3D" parent="InnerPyramid/Slots"]
transform = Transform3D(0.99999994, 0, 0, 0, 1, 0, 0, 0, 0.99999994, 0, 0, 0)
layers = 4
size = Vector3(100000, 30000, 10000)
material = ExtResource("3_yw1ox")
[node name="CSGBox3D3" type="CSGBox3D" parent="InnerPyramid/Slots"]
transform = Transform3D(-4.3711385e-08, 0, 0.99999994, 0, 1, 0, -0.99999994, 0, -4.3711385e-08, 0, 0, 0)
layers = 4
size = Vector3(100000, 30000, 10000)
material = ExtResource("3_yw1ox")
[node name="AutoRange" type="Node" parent="InnerPyramid"]
script = ExtResource("4_kox75")
lod = 1
end_margin_pct = 0.01
metadata/_custom_type_script = "uid://cv0o1lirqeq44"
[node name="WorldFloor" type="MeshInstance3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 50000, 0, 50000)
layers = 4
mesh = SubResource("PlaneMesh_pko82")
[node name="StaticBody3D" type="StaticBody3D" parent="WorldFloor"]
[node name="CollisionShape3D" type="CollisionShape3D" parent="WorldFloor/StaticBody3D"]
shape = SubResource("ConcavePolygonShape3D_ek7o7")
[node name="AutoRange" type="Node" parent="WorldFloor"]
script = ExtResource("4_kox75")
lod = 1
end_margin_pct = 0.01
metadata/_custom_type_script = "uid://cv0o1lirqeq44"
[node name="MetroQuadrant" type="Node3D" parent="."]
[node name="OuterMetro" type="Node3D" parent="MetroQuadrant"]
[node name="MetroGridLayer" parent="MetroQuadrant/OuterMetro" instance=ExtResource("4_fy7wq")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 55, 0, 55)
bounding_box = AABB(0, 0, 0, 49088, 400, 448)
noise_offset = Vector3(1, 1, 1)
[node name="MetroGridLayer2" parent="MetroQuadrant/OuterMetro" instance=ExtResource("4_fy7wq")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 55, 0, 503)
bounding_box = AABB(0, 0, 0, 448, 400, 48640)
noise_offset = Vector3(1, 1, 1)
[node name="InnerMetro" type="Node3D" parent="MetroQuadrant"]
[node name="MetroGridLayer" parent="MetroQuadrant/InnerMetro" instance=ExtResource("4_fy7wq")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 45047, 0, 503)
construct_height_factor_x = SubResource("Curve_0w44q")
construct_height_factor_z = SubResource("Curve_amoo5")
bounding_box = AABB(0, 0, 0, 4096, 400, 44480)
noise_offset = Vector3(1, 1, 1)
[node name="MetroGridLayer2" parent="MetroQuadrant/InnerMetro" instance=ExtResource("4_fy7wq")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 503, 0, 45047)
construct_height_factor_x = SubResource("Curve_amoo5")
construct_height_factor_z = SubResource("Curve_0w44q")
bounding_box = AABB(0, 0, 0, 44480, 400, 4096)
noise_offset = Vector3(1, 1, 1)
[node name="UpperMetro" type="Node3D" parent="MetroQuadrant"]
[node name="MetroGridLayer" parent="MetroQuadrant/UpperMetro" instance=ExtResource("4_fy7wq")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 18900, 25000, 18900)
simple_construct_threshold = 0.4
construct_height_factor_x = SubResource("Curve_kox75")
bounding_box = AABB(0, 0, 0, 5632, 400, 5632)
debug = true
noise_scale = Vector3(0.01, 0.01, 0.01)
[node name="MetroGridLayer2" parent="MetroQuadrant/UpperMetro" instance=ExtResource("4_fy7wq")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 28700, 25000, 18900)
simple_construct_threshold = 0.4
construct_height_factor_x = SubResource("Curve_kox75")
bounding_box = AABB(0, 0, 0, 5632, 400, 5632)
noise_scale = Vector3(0.01, 0.01, 0.01)
[node name="MetroGridLayer3" parent="MetroQuadrant/UpperMetro" instance=ExtResource("4_fy7wq")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 38500, 25000, 18900)
simple_construct_threshold = 0.4
construct_height_factor_x = SubResource("Curve_kox75")
bounding_box = AABB(0, 0, 0, 5632, 400, 5632)
noise_scale = Vector3(0.01, 0.01, 0.01)
[node name="MetroGridLayer4" parent="MetroQuadrant/UpperMetro" instance=ExtResource("4_fy7wq")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 18900, 25000, 28700)
simple_construct_threshold = 0.4
construct_height_factor_x = SubResource("Curve_kox75")
bounding_box = AABB(0, 0, 0, 5632, 400, 5632)
noise_scale = Vector3(0.01, 0.01, 0.01)
[node name="MetroGridLayer5" parent="MetroQuadrant/UpperMetro" instance=ExtResource("4_fy7wq")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 18900, 25000, 38500)
simple_construct_threshold = 0.4
construct_height_factor_x = SubResource("Curve_kox75")
bounding_box = AABB(0, 0, 0, 5632, 400, 5632)
noise_scale = Vector3(0.01, 0.01, 0.01)
[node name="MetroQuadrant2" type="Node3D" parent="."]
transform = Transform3D(-4.371139e-08, 0, 1, 0, 1, 0, -1, 0, -4.371139e-08, 0, 0, 100000)
[node name="OuterMetro" type="Node3D" parent="MetroQuadrant2"]
[node name="MetroGridLayer" parent="MetroQuadrant2/OuterMetro" instance=ExtResource("4_fy7wq")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 55, 0, 55)
bounding_box = AABB(0, 0, 0, 49088, 400, 448)
noise_offset = Vector3(1, 1, 1)
[node name="MetroGridLayer2" parent="MetroQuadrant2/OuterMetro" instance=ExtResource("4_fy7wq")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 55, 0, 503)
bounding_box = AABB(0, 0, 0, 448, 400, 48640)
noise_offset = Vector3(1, 1, 1)
[node name="InnerMetro" type="Node3D" parent="MetroQuadrant2"]
[node name="MetroGridLayer" parent="MetroQuadrant2/InnerMetro" instance=ExtResource("4_fy7wq")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 45047, 0, 503)
construct_height_factor_x = SubResource("Curve_0w44q")
construct_height_factor_z = SubResource("Curve_amoo5")
bounding_box = AABB(0, 0, 0, 4096, 400, 44480)
noise_offset = Vector3(1, 1, 1)
[node name="MetroGridLayer2" parent="MetroQuadrant2/InnerMetro" instance=ExtResource("4_fy7wq")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 503, 0, 45047)
construct_height_factor_x = SubResource("Curve_amoo5")
construct_height_factor_z = SubResource("Curve_0w44q")
bounding_box = AABB(0, 0, 0, 44480, 400, 4096)
noise_offset = Vector3(1, 1, 1)
[node name="UpperMetro" type="Node3D" parent="MetroQuadrant2"]
[node name="MetroGridLayer" parent="MetroQuadrant2/UpperMetro" instance=ExtResource("4_fy7wq")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 18900, 25000, 18900)
simple_construct_threshold = 0.4
construct_height_factor_x = SubResource("Curve_kox75")
bounding_box = AABB(0, 0, 0, 5632, 400, 5632)
noise_scale = Vector3(0.01, 0.01, 0.01)
[node name="MetroGridLayer2" parent="MetroQuadrant2/UpperMetro" instance=ExtResource("4_fy7wq")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 28700, 25000, 18900)
simple_construct_threshold = 0.4
construct_height_factor_x = SubResource("Curve_kox75")
bounding_box = AABB(0, 0, 0, 5632, 400, 5632)
noise_scale = Vector3(0.01, 0.01, 0.01)
[node name="MetroGridLayer3" parent="MetroQuadrant2/UpperMetro" instance=ExtResource("4_fy7wq")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 38500, 25000, 18900)
simple_construct_threshold = 0.4
construct_height_factor_x = SubResource("Curve_kox75")
bounding_box = AABB(0, 0, 0, 5632, 400, 5632)
noise_scale = Vector3(0.01, 0.01, 0.01)
[node name="MetroGridLayer4" parent="MetroQuadrant2/UpperMetro" instance=ExtResource("4_fy7wq")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 18900, 25000, 28700)
simple_construct_threshold = 0.4
construct_height_factor_x = SubResource("Curve_kox75")
bounding_box = AABB(0, 0, 0, 5632, 400, 5632)
noise_scale = Vector3(0.01, 0.01, 0.01)
[node name="MetroGridLayer5" parent="MetroQuadrant2/UpperMetro" instance=ExtResource("4_fy7wq")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 18900, 25000, 38500)
simple_construct_threshold = 0.4
construct_height_factor_x = SubResource("Curve_kox75")
bounding_box = AABB(0, 0, 0, 5632, 400, 5632)
noise_scale = Vector3(0.01, 0.01, 0.01)
[node name="MetroQuadrant3" type="Node3D" parent="."]
transform = Transform3D(-1, 0, -8.742278e-08, 0, 1, 0, 8.742278e-08, 0, -1, 100000, 0, 100000)
[node name="OuterMetro" type="Node3D" parent="MetroQuadrant3"]
[node name="MetroGridLayer" parent="MetroQuadrant3/OuterMetro" instance=ExtResource("4_fy7wq")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 55, 0, 55)
bounding_box = AABB(0, 0, 0, 49088, 400, 448)
noise_offset = Vector3(1, 1, 1)
[node name="MetroGridLayer2" parent="MetroQuadrant3/OuterMetro" instance=ExtResource("4_fy7wq")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 55, 0, 503)
bounding_box = AABB(0, 0, 0, 448, 400, 48640)
noise_offset = Vector3(1, 1, 1)
[node name="InnerMetro" type="Node3D" parent="MetroQuadrant3"]
[node name="MetroGridLayer" parent="MetroQuadrant3/InnerMetro" instance=ExtResource("4_fy7wq")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 45047, 0, 503)
construct_height_factor_x = SubResource("Curve_0w44q")
construct_height_factor_z = SubResource("Curve_amoo5")
bounding_box = AABB(0, 0, 0, 4096, 400, 44480)
noise_offset = Vector3(1, 1, 1)
[node name="MetroGridLayer2" parent="MetroQuadrant3/InnerMetro" instance=ExtResource("4_fy7wq")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 503, 0, 45047)
construct_height_factor_x = SubResource("Curve_amoo5")
construct_height_factor_z = SubResource("Curve_0w44q")
bounding_box = AABB(0, 0, 0, 44480, 400, 4096)
noise_offset = Vector3(1, 1, 1)
[node name="UpperMetro" type="Node3D" parent="MetroQuadrant3"]
[node name="MetroGridLayer" parent="MetroQuadrant3/UpperMetro" instance=ExtResource("4_fy7wq")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 18900, 25000, 18900)
simple_construct_threshold = 0.4
construct_height_factor_x = SubResource("Curve_kox75")
bounding_box = AABB(0, 0, 0, 5632, 400, 5632)
noise_scale = Vector3(0.01, 0.01, 0.01)
[node name="MetroGridLayer2" parent="MetroQuadrant3/UpperMetro" instance=ExtResource("4_fy7wq")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 28700, 25000, 18900)
simple_construct_threshold = 0.4
construct_height_factor_x = SubResource("Curve_kox75")
bounding_box = AABB(0, 0, 0, 5632, 400, 5632)
noise_scale = Vector3(0.01, 0.01, 0.01)
[node name="MetroGridLayer3" parent="MetroQuadrant3/UpperMetro" instance=ExtResource("4_fy7wq")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 38500, 25000, 18900)
simple_construct_threshold = 0.4
construct_height_factor_x = SubResource("Curve_kox75")
bounding_box = AABB(0, 0, 0, 5632, 400, 5632)
noise_scale = Vector3(0.01, 0.01, 0.01)
[node name="MetroGridLayer4" parent="MetroQuadrant3/UpperMetro" instance=ExtResource("4_fy7wq")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 18900, 25000, 28700)
simple_construct_threshold = 0.4
construct_height_factor_x = SubResource("Curve_kox75")
bounding_box = AABB(0, 0, 0, 5632, 400, 5632)
noise_scale = Vector3(0.01, 0.01, 0.01)
[node name="MetroGridLayer5" parent="MetroQuadrant3/UpperMetro" instance=ExtResource("4_fy7wq")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 18900, 25000, 38500)
simple_construct_threshold = 0.4
construct_height_factor_x = SubResource("Curve_kox75")
bounding_box = AABB(0, 0, 0, 5632, 400, 5632)
noise_scale = Vector3(0.01, 0.01, 0.01)
[node name="MetroQuadrant4" type="Node3D" parent="."]
transform = Transform3D(-4.371139e-08, 0, -1, 0, 1, 0, 1, 0, -4.371139e-08, 100000, 0, 0)
[node name="OuterMetro" type="Node3D" parent="MetroQuadrant4"]
[node name="MetroGridLayer" parent="MetroQuadrant4/OuterMetro" instance=ExtResource("4_fy7wq")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 55, 0, 55)
bounding_box = AABB(0, 0, 0, 49088, 400, 448)
noise_offset = Vector3(1, 1, 1)
[node name="MetroGridLayer2" parent="MetroQuadrant4/OuterMetro" instance=ExtResource("4_fy7wq")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 55, 0, 503)
bounding_box = AABB(0, 0, 0, 448, 400, 48640)
noise_offset = Vector3(1, 1, 1)
[node name="InnerMetro" type="Node3D" parent="MetroQuadrant4"]
[node name="MetroGridLayer" parent="MetroQuadrant4/InnerMetro" instance=ExtResource("4_fy7wq")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 45047, 0, 503)
construct_height_factor_x = SubResource("Curve_0w44q")
construct_height_factor_z = SubResource("Curve_amoo5")
bounding_box = AABB(0, 0, 0, 4096, 400, 44480)
noise_offset = Vector3(1, 1, 1)
[node name="MetroGridLayer2" parent="MetroQuadrant4/InnerMetro" instance=ExtResource("4_fy7wq")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 503, 0, 45047)
construct_height_factor_x = SubResource("Curve_amoo5")
construct_height_factor_z = SubResource("Curve_0w44q")
bounding_box = AABB(0, 0, 0, 44480, 400, 4096)
noise_offset = Vector3(1, 1, 1)
[node name="UpperMetro" type="Node3D" parent="MetroQuadrant4"]
[node name="MetroGridLayer" parent="MetroQuadrant4/UpperMetro" instance=ExtResource("4_fy7wq")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 18900, 25000, 18900)
simple_construct_threshold = 0.4
construct_height_factor_x = SubResource("Curve_kox75")
bounding_box = AABB(0, 0, 0, 5632, 400, 5632)
noise_scale = Vector3(0.01, 0.01, 0.01)
[node name="MetroGridLayer2" parent="MetroQuadrant4/UpperMetro" instance=ExtResource("4_fy7wq")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 28700, 25000, 18900)
simple_construct_threshold = 0.4
construct_height_factor_x = SubResource("Curve_kox75")
bounding_box = AABB(0, 0, 0, 5632, 400, 5632)
noise_scale = Vector3(0.01, 0.01, 0.01)
[node name="MetroGridLayer3" parent="MetroQuadrant4/UpperMetro" instance=ExtResource("4_fy7wq")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 38500, 25000, 18900)
simple_construct_threshold = 0.4
construct_height_factor_x = SubResource("Curve_kox75")
bounding_box = AABB(0, 0, 0, 5632, 400, 5632)
noise_scale = Vector3(0.01, 0.01, 0.01)
[node name="MetroGridLayer4" parent="MetroQuadrant4/UpperMetro" instance=ExtResource("4_fy7wq")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 18900, 25000, 28700)
simple_construct_threshold = 0.4
construct_height_factor_x = SubResource("Curve_kox75")
bounding_box = AABB(0, 0, 0, 5632, 400, 5632)
noise_scale = Vector3(0.01, 0.01, 0.01)
[node name="MetroGridLayer5" parent="MetroQuadrant4/UpperMetro" instance=ExtResource("4_fy7wq")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 18900, 25000, 38500)
simple_construct_threshold = 0.4
construct_height_factor_x = SubResource("Curve_kox75")
bounding_box = AABB(0, 0, 0, 5632, 400, 5632)
noise_scale = Vector3(0.01, 0.01, 0.01)

View File

@ -0,0 +1,29 @@
[gd_scene load_steps=5 format=3 uid="uid://dawv6mbpr4d3c"]
[ext_resource type="Script" uid="uid://drk82eeqk2mjs" path="res://src/world/generation/feature/generation_feature.gd" id="1_ydt4o"]
[ext_resource type="Script" uid="uid://cv0o1lirqeq44" path="res://src/util/auto_range.gd" id="2_q70le"]
[sub_resource type="PlaneMesh" id="PlaneMesh_ydt4o"]
size = Vector2(100000, 100000)
[sub_resource type="ConcavePolygonShape3D" id="ConcavePolygonShape3D_q70le"]
data = PackedVector3Array(50000, 0, 50000, -50000, 0, 50000, 50000, 0, -50000, -50000, 0, 50000, -50000, 0, -50000, 50000, 0, -50000)
[node name="Empty" type="Node3D"]
script = ExtResource("1_ydt4o")
metadata/_custom_type_script = "uid://drk82eeqk2mjs"
[node name="WorldFloor" type="MeshInstance3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 50000, 0, 50000)
layers = 4
mesh = SubResource("PlaneMesh_ydt4o")
[node name="StaticBody3D" type="StaticBody3D" parent="WorldFloor"]
[node name="CollisionShape3D" type="CollisionShape3D" parent="WorldFloor/StaticBody3D"]
shape = SubResource("ConcavePolygonShape3D_q70le")
[node name="AutoRange" type="Node" parent="WorldFloor"]
script = ExtResource("2_q70le")
lod = 1
metadata/_custom_type_script = "uid://cv0o1lirqeq44"

View File

@ -0,0 +1,43 @@
class_name GenerationFeature extends GeneratedElement
## Base class for world features generated during worldgen.
## Set of sub-layers that require generation at each LOD
var sub_layers: Dictionary[WorldGen.LOD, Dictionary] = {
WorldGen.LOD.LOW: {},
WorldGen.LOD.MEDIUM: {},
WorldGen.LOD.HIGH: {},
}
## Set of LODs at which this feature has been generated
var generated: Dictionary[WorldGen.LOD, bool] = {}
func _ready() -> void:
_discover_sub_layers(self)
func _discover_sub_layers(node: Node) -> void:
if node is GenerationLayer:
for lod in WorldGen.LOD_LIST:
sub_layers[lod][node] = false
for c: Node in node.get_children():
# Do not walk outside of this scene
if c.owner in [owner, self]:
_discover_sub_layers(c)
func _generate(lod: WorldGen.LOD) -> bool:
if lod not in generated:
generate_feature(lod)
generated[lod] = true
for layer: GenerationLayer in sub_layers[lod]:
if layer.generate(lod):
sub_layers[lod].erase(layer)
return not sub_layers[lod]
## Generate elements of this feature. Called by default on the first call to `probe` for this lod.
func generate_feature(_lod: WorldGen.LOD) -> void:
pass # Implemented in derived type

View File

@ -0,0 +1 @@
uid://drk82eeqk2mjs

View File

@ -0,0 +1,15 @@
class_name MetroConstructSimple extends GenerationFeature
@export var min_height := 48.0
@export var height_factor := 200.0
@onready var construct_box: CSGBox3D = %ConstructBox
func generate_feature(lod: WorldGen.LOD) -> void:
match lod:
WorldGen.LOD.MEDIUM:
var value := absf(sample_noise())
var height := value * height_factor + min_height
construct_box.position.y = height / 2
construct_box.size.y = height

View File

@ -0,0 +1 @@
uid://dq5xadqwyspyh

View File

@ -0,0 +1,44 @@
[gd_scene load_steps=5 format=3 uid="uid://beno0v5dxtwqs"]
[ext_resource type="Script" uid="uid://dq5xadqwyspyh" path="res://src/world/generation/feature/metro/metro_construct_simple/metro_construct_simple.gd" id="1_jv74y"]
[ext_resource type="Script" uid="uid://cv0o1lirqeq44" path="res://src/util/auto_range.gd" id="2_74b57"]
[sub_resource type="PlaneMesh" id="PlaneMesh_lhl33"]
size = Vector2(64, 64)
subdivide_width = 4
subdivide_depth = 4
[sub_resource type="ConvexPolygonShape3D" id="ConvexPolygonShape3D_y2o1w"]
points = PackedVector3Array(-31.999998, 0, -31.999998, -31.999998, 0, 31.999998, 32, 0, -31.999998, 32, 0, 31.999998)
[node name="MetroConstructSimple" type="Node3D"]
script = ExtResource("1_jv74y")
generated_lods = 6
metadata/_custom_type_script = "uid://drk82eeqk2mjs"
[node name="WorldFloor" type="MeshInstance3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 32, 0, 32)
layers = 2
mesh = SubResource("PlaneMesh_lhl33")
[node name="StaticBody3D" type="StaticBody3D" parent="WorldFloor"]
[node name="CollisionShape3D" type="CollisionShape3D" parent="WorldFloor/StaticBody3D"]
shape = SubResource("ConvexPolygonShape3D_y2o1w")
[node name="AutoRange" type="Node" parent="WorldFloor"]
script = ExtResource("2_74b57")
lod = 2
metadata/_custom_type_script = "uid://cv0o1lirqeq44"
[node name="ConstructBox" type="CSGBox3D" parent="."]
unique_name_in_owner = true
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 32, 24, 32)
layers = 2
use_collision = true
size = Vector3(48, 48, 48)
[node name="AutoRange" type="Node" parent="ConstructBox"]
script = ExtResource("2_74b57")
lod = 2
metadata/_custom_type_script = "uid://cv0o1lirqeq44"

View File

@ -0,0 +1,30 @@
[gd_scene load_steps=5 format=3 uid="uid://cgvg7n525g18l"]
[ext_resource type="Script" uid="uid://drk82eeqk2mjs" path="res://src/world/generation/feature/generation_feature.gd" id="1_e5j5s"]
[ext_resource type="Script" uid="uid://cv0o1lirqeq44" path="res://src/util/auto_range.gd" id="2_xbnbu"]
[sub_resource type="PlaneMesh" id="PlaneMesh_e5j5s"]
size = Vector2(64, 64)
subdivide_width = 4
subdivide_depth = 4
[sub_resource type="ConvexPolygonShape3D" id="ConvexPolygonShape3D_e5j5s"]
points = PackedVector3Array(-31.999998, 0, -31.999998, -31.999998, 0, 31.999998, 32, 0, -31.999998, 32, 0, 31.999998)
[node name="MetroEmpty" type="Node3D"]
script = ExtResource("1_e5j5s")
metadata/_custom_type_script = "uid://drk82eeqk2mjs"
[node name="WorldFloor" type="MeshInstance3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 32, 0, 32)
mesh = SubResource("PlaneMesh_e5j5s")
[node name="StaticBody3D" type="StaticBody3D" parent="WorldFloor"]
[node name="CollisionShape3D" type="CollisionShape3D" parent="WorldFloor/StaticBody3D"]
shape = SubResource("ConvexPolygonShape3D_e5j5s")
[node name="AutoRange" type="Node" parent="WorldFloor"]
script = ExtResource("2_xbnbu")
lod = 2
metadata/_custom_type_script = "uid://cv0o1lirqeq44"

View File

@ -0,0 +1,40 @@
class_name GeneratedElement extends Node3D
## Base class for all generated world elements
@export_flags("Low", "Medium", "High") var generated_lods := 0b111
## Scale to apply to position before sampling world generation noise.
@export var noise_scale := Vector3.ONE
## Offset to apply to position before sampling world generation noise.
@export var noise_offset := Vector3.ZERO
## Generate this element at the given level of detail.
##
## Returns `true` if the element has completed generation at this LOD.
## Some composite elements may require multiple `generate` calls to complete generation.
func generate(lod: WorldGen.LOD) -> bool:
if lod & generated_lods:
return _generate(lod)
return true
## Generate this element at the given level of detail.
##
## This method is called by `generate` and should be overridden by derived types with
## custom generation logic.
## Returns `true` if the element has completed generation at this LOD.
## Some composite elements may require multiple `generate` calls to complete generation.
func _generate(_lod: WorldGen.LOD) -> bool:
return true # Implemented by derived types.
## Sample world generation noise at this element's position with scale & offset.
func sample_noise() -> float:
return sample_noise_at(global_position)
## Sample world generation noise at the given point, applying this element's scale & offset.
func sample_noise_at(pos: Vector3) -> float:
return WorldGenManager.noise.get_noise_3dv(pos * noise_scale + noise_offset)

View File

@ -0,0 +1 @@
uid://c7x4yin558csb

View File

@ -1,21 +1,24 @@
class_name GeneratedWorld extends Node3D
@export var generation_radius := 6.0
var chunks: Dictionary[Vector2, Chunk] = {}
var elements: Dictionary[WorldGen.LOD, Dictionary] = {
WorldGen.LOD.LOW: {},
WorldGen.LOD.MEDIUM: {},
WorldGen.LOD.HIGH: {},
}
func get_chunk(chunk_pos: Vector2) -> Chunk:
if chunk_pos not in chunks:
var chunk := Chunk.generate_chunk(chunk_pos)
add_child(chunk)
chunks[chunk_pos] = chunk
return chunks[chunk_pos]
func _ready() -> void:
for c: Node in get_children():
if c is GeneratedElement:
for lod in WorldGen.LOD_LIST:
if not elements[lod]:
elements[lod] = {}
elements[lod][c] = false
func _process(_delta: float) -> void:
var camera := get_viewport().get_camera_3d()
var center := Chunk.world_to_chunk(camera.global_position)
for x in range(center.x - generation_radius, center.x + generation_radius):
for y in range(center.y - generation_radius, center.y + generation_radius):
get_chunk(Vector2(x, y))
# Probe all child generation layers & features each frame
for lod in WorldGen.LOD_LIST:
for element: GeneratedElement in elements[lod]:
if element.generate(lod):
elements[lod].erase(element)

View File

@ -1,6 +1,9 @@
[gd_scene load_steps=2 format=3 uid="uid://cop4mkrv70yhc"]
[gd_scene load_steps=3 format=3 uid="uid://cop4mkrv70yhc"]
[ext_resource type="Script" uid="uid://dka00cyvfr21t" path="res://src/world/generation/generated_world.gd" id="1_m2u13"]
[ext_resource type="PackedScene" uid="uid://dlhc1te2ip8vg" path="res://src/world/generation/layer/arcology_grid_layer/arcology_grid_layer.tscn" id="2_k55gd"]
[node name="GeneratedWorld" type="Node3D"]
script = ExtResource("1_m2u13")
[node name="ArcologyGridLayer" parent="." instance=ExtResource("2_k55gd")]

View File

@ -0,0 +1,27 @@
class_name ArcologyGridLayer extends GridLayer
## Grid with each cell possibly generating an arcology
@export var arcology_feature_scene: PackedScene
@export var empty_feature_scene: PackedScene
@export var arcology_probability := 0.1
var features: Dictionary[Vector2, GenerationFeature] = {}
func generate_grid(lod: WorldGen.LOD, grid_pos: Vector2) -> bool:
# Generate if needed
if grid_pos not in features:
var feature: GenerationFeature
var sample := absf(sample_noise_at_grid(grid_pos))
print_debug("Sampled ", sample, " at ", grid_pos)
if sample < arcology_probability:
print_debug("Generating arcology at ", grid_pos)
feature = arcology_feature_scene.instantiate()
else:
feature = empty_feature_scene.instantiate()
add_child(feature)
feature.global_position = local_to_world(grid_pos)
features[grid_pos] = feature
# Probe feature
return features[grid_pos].generate(lod)

View File

@ -0,0 +1 @@
uid://kp8r23lsylpk

View File

@ -0,0 +1,13 @@
[gd_scene load_steps=4 format=3 uid="uid://dlhc1te2ip8vg"]
[ext_resource type="Script" uid="uid://kp8r23lsylpk" path="res://src/world/generation/layer/arcology_grid_layer/arcology_grid_layer.gd" id="1_85eh3"]
[ext_resource type="PackedScene" uid="uid://nllc8ljmn37g" path="res://src/world/generation/feature/arcology/arcology.tscn" id="2_pxyh5"]
[ext_resource type="PackedScene" uid="uid://dawv6mbpr4d3c" path="res://src/world/generation/feature/arcology/empty.tscn" id="3_p6bke"]
[node name="ArcologyGridLayer" type="Node3D"]
script = ExtResource("1_85eh3")
arcology_feature_scene = ExtResource("2_pxyh5")
empty_feature_scene = ExtResource("3_p6bke")
grid_size = Vector2(100000, 100000)
noise_scale = Vector3(2, 2, 2)
metadata/_custom_type_script = "uid://kp8r23lsylpk"

View File

@ -0,0 +1,4 @@
class_name GenerationLayer extends GeneratedElement
## A composite layer of world generation logic.
# TODO what else goes here?

View File

@ -0,0 +1 @@
uid://ciq8lxydnfc77

View File

@ -0,0 +1,49 @@
@tool
class_name BoundedGridDebugView extends Node3D
## Helper component that draws the AABB of a bounded grid in the editor
@export var debug_color := Color("#a486006b"):
set(value):
debug_color = value
if box:
_set_debug_box_color(debug_color)
var mesh_instance: MeshInstance3D
var box: BoxMesh
var material: StandardMaterial3D
@onready var target: BoundedGridLayer = get_parent()
func _ready() -> void:
# Don't want these during runtime
if not Engine.is_editor_hint():
queue_free()
# Initialize box drawing components
if not mesh_instance:
mesh_instance = MeshInstance3D.new()
add_child(mesh_instance)
if not box:
box = BoxMesh.new()
if not material:
material = StandardMaterial3D.new()
mesh_instance.mesh = box
box.material = material
material.transparency = BaseMaterial3D.TRANSPARENCY_ALPHA
material.shading_mode = BaseMaterial3D.SHADING_MODE_UNSHADED
_set_debug_box_color(debug_color)
_set_debug_box_shape(target.bounding_box)
func _set_debug_box_color(color: Color) -> void:
material.albedo_color = color
func _set_debug_box_shape(aabb: AABB) -> void:
mesh_instance.position = aabb.position + aabb.size / 2
box.size = aabb.size
func _process(_delta: float) -> void:
_set_debug_box_shape(target.bounding_box)

View File

@ -0,0 +1 @@
uid://r74iif2we4bu

View File

@ -0,0 +1,64 @@
class_name BoundedGridLayer extends GridLayer
## A layer that generates tiles in a locally-constrained grid.
## Bounding box for the grid on the local XZ plane.
##
## Note that only feature handles are checked to be within the bounding box.
@export var bounding_box: AABB
@export var debug := false
func _ready() -> void:
var grid := _plane_size()
for lod in WorldGen.LOD_LIST:
for i in grid.x:
for j in grid.y:
_generation_grid[lod][Vector2(i, j)] = false
func _generate(lod: WorldGen.LOD) -> bool:
var center := WorldGenManager.get_generation_point()
var radius := WorldGenManager.get_lod_radius(lod)
# Only generate if the bounding box is within generation radius.
if absf((center * global_transform).y) + bounding_box.size.y < radius:
var rad_diff := Vector3(radius, 0, radius)
# Translate probe box limits to grid space
var a := world_to_local(center - rad_diff).floor()
var b := world_to_local(center + rad_diff).floor()
var grid_low := Vector2(minf(a.x, b.x), minf(a.y, b.y))
var grid_high := Vector2(maxf(a.x, b.x), maxf(a.y, b.y))
var grid_max := _plane_size().floor()
# Constrain to bounding box
var x_min := maxf(grid_low.x, 0)
var x_max := minf(grid_high.x + 1, grid_max.x)
var y_min := maxf(grid_low.y, 0)
var y_max := minf(grid_high.y + 1, grid_max.y)
# Probe everything within radius
for i in range(x_min, x_max):
for j in range(y_min, y_max):
var pt := Vector2(i, j)
if pt in _generation_grid[lod]:
if generate_grid(lod, pt):
_generation_grid[lod].erase(pt)
# Return false if there are still grid points to be generated
return not _generation_grid[lod]
func _plane_size() -> Vector2:
return Vector2(bounding_box.size.x / grid_size.x, bounding_box.size.z / grid_size.y)
func local_to_world(local_pos: Vector2) -> Vector3:
var v3_pos := Vector3(local_pos.x * grid_size.x, 0, local_pos.y * grid_size.y)
return global_transform * (bounding_box.position + v3_pos)
func world_to_local(world_pos: Vector3) -> Vector2:
var rel_pos := world_pos * global_transform - bounding_box.position
return Vector2(rel_pos.x / grid_size.x, rel_pos.z / grid_size.y)

View File

@ -0,0 +1 @@
uid://bo2pmuy3dn5y4

View File

@ -0,0 +1,55 @@
class_name GridLayer extends GenerationLayer
## A layer that generates tiles on an infinite grid
## Size of a grid tile in the local XZ plane.
@export var grid_size: Vector2
var _generation_grid: Dictionary[WorldGen.LOD, Dictionary] = {
WorldGen.LOD.LOW: {},
WorldGen.LOD.MEDIUM: {},
WorldGen.LOD.HIGH: {},
}
func _generate(lod: WorldGen.LOD) -> bool:
var center := WorldGenManager.get_generation_point()
var radius := WorldGenManager.get_lod_radius(lod)
var rad_diff := Vector3(radius, 0, radius)
# Translate probe box limits to grid space
var a := world_to_local(center - rad_diff).floor()
var b := world_to_local(center + rad_diff).floor()
var grid_low := Vector2(minf(a.x, b.x), minf(a.y, b.y))
var grid_high := Vector2(maxf(a.x, b.x), maxf(a.y, b.y))
# Probe everything within radius
for i in range(grid_low.x, grid_high.x + 1):
for j in range(grid_low.y, grid_high.y + 1):
var pt := Vector2(i, j)
if pt not in _generation_grid[lod]:
if generate_grid(lod, pt):
_generation_grid[lod][pt] = true
# The grid is infinite, so there will always be more to generate
return false
## Generate the given grid position.
##
## Like `generate`, this returns `true` when generation is complete.
func generate_grid(_lod: WorldGen.LOD, _grid_pos: Vector2) -> bool:
return true # Implement in derived type
func local_to_world(local_pos: Vector2) -> Vector3:
var v3_pos := Vector3(local_pos.x * grid_size.x, 0, local_pos.y * grid_size.y)
return global_transform * v3_pos
func world_to_local(world_pos: Vector3) -> Vector2:
var rel_pos := world_pos * global_transform
return Vector2(rel_pos.x / grid_size.x, rel_pos.z / grid_size.y)
func sample_noise_at_grid(grid_pos: Vector2) -> float:
return sample_noise_at(local_to_world(grid_pos))

View File

@ -0,0 +1 @@
uid://nq1cuemdrtn2

View File

@ -0,0 +1,36 @@
extends BoundedGridLayer
## Procedural cityscape generation
@export var empty_scene: PackedScene
@export var simple_construct_scene: PackedScene
@export_group("Construct Parameters")
@export var simple_construct_threshold := 0.3
@export var construct_height_factor_x: Curve
@export var construct_height_factor_z: Curve
var features: Dictionary[Vector2, GenerationFeature] = {}
func generate_simple_construct(grid_pos: Vector2) -> MetroConstructSimple:
var instance: MetroConstructSimple = simple_construct_scene.instantiate()
var sample_pos := grid_pos / _plane_size()
if construct_height_factor_x:
instance.height_factor *= construct_height_factor_x.sample(sample_pos.x)
if construct_height_factor_z:
instance.height_factor *= construct_height_factor_z.sample(sample_pos.y)
return instance
func generate_grid(lod: WorldGen.LOD, grid_pos: Vector2) -> bool:
if grid_pos not in features:
var feature: GenerationFeature
var sample := absf(sample_noise_at(local_to_world(grid_pos)))
if sample > simple_construct_threshold:
feature = generate_simple_construct(grid_pos)
else:
feature = empty_scene.instantiate()
add_child(feature)
feature.global_position = local_to_world(grid_pos)
features[grid_pos] = feature
return features[grid_pos].generate(lod)

View File

@ -0,0 +1 @@
uid://d25t2340sdrox

View File

@ -0,0 +1,17 @@
[gd_scene load_steps=5 format=3 uid="uid://cwygxhknl2h8r"]
[ext_resource type="Script" uid="uid://d25t2340sdrox" path="res://src/world/generation/layer/metro_grid_layer/metro_grid_layer.gd" id="1_ng6r6"]
[ext_resource type="PackedScene" uid="uid://cgvg7n525g18l" path="res://src/world/generation/feature/metro/metro_empty.tscn" id="2_47xjc"]
[ext_resource type="PackedScene" uid="uid://beno0v5dxtwqs" path="res://src/world/generation/feature/metro/metro_construct_simple/metro_construct_simple.tscn" id="3_woad2"]
[ext_resource type="Script" uid="uid://r74iif2we4bu" path="res://src/world/generation/layer/grid_layer/bounded_grid_debug_view.gd" id="4_woad2"]
[node name="MetroGridLayer" type="Node3D"]
script = ExtResource("1_ng6r6")
empty_scene = ExtResource("2_47xjc")
simple_construct_scene = ExtResource("3_woad2")
grid_size = Vector2(64, 64)
generated_lods = 6
[node name="BoundedGridDebugView" type="Node3D" parent="."]
script = ExtResource("4_woad2")
metadata/_custom_type_script = "uid://r74iif2we4bu"

View File

@ -1,4 +1,43 @@
class_name WorldGenManagerType extends Node
class_name WorldGen extends Node
## Global autoloaded singleton controller for worldgen parameters
## Worldgen uses custom levels of detail, distinct from mesh LODs.
enum LOD {
LOW = 0b001,
MEDIUM = 0b010,
HIGH = 0b100,
}
## List of LODs, for iteration convenience.
const LOD_LIST: Array[WorldGen.LOD] = [LOD.LOW, LOD.MEDIUM, LOD.HIGH]
@export var noise: FastNoiseLite
## Generate features with the lowest detail, like large distant structures, within this radius
@export var low_detail_radius := 100000.0
## Generate features with medium detail, like buildings, within this radius
@export var med_detail_radius := 8192.0
## Generate features with high detail, like small complicated objects, within this radius
@export var high_detail_radius := 128.0
## Get the world-space coordinate to generate around.
func get_generation_point() -> Vector3:
var viewport := get_viewport()
if viewport:
var camera := viewport.get_camera_3d()
if camera:
return camera.global_position
return Vector3.ZERO
## Get the generation radius for a given LOD.
func get_lod_radius(lod: LOD) -> float:
match lod:
LOD.LOW:
return low_detail_radius
LOD.MEDIUM:
return med_detail_radius
LOD.HIGH:
return high_detail_radius
return -1

View File

@ -3,7 +3,9 @@
[ext_resource type="Script" uid="uid://7frynyj4vspc" path="res://src/world/generation/worldgen_manager/worldgen_manager.gd" id="1_7xvag"]
[sub_resource type="FastNoiseLite" id="FastNoiseLite_7xvag"]
noise_type = 0
frequency = 0.1
offset = Vector3(1024, 1024, 1024)
[node name="WorldGenManager" type="Node"]
script = ExtResource("1_7xvag")

File diff suppressed because one or more lines are too long