WorldScape3D has no collision near the world origin with vertex_spacing > 1
Maintainers usually reply within 1 day
Assessment
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Newbie friendliness
- 35/100
Research direction
Start with the reported WorldScape3DCollision::update() path and inspect how unused shapes are parked and checked against the collision centre. Reproduce with vertex_spacing = 2, a camera at the origin, and the supplied scene; verify that collision works near the origin and downward raycasts hit terrain. The reporter says a fix is ready and plans to open a PR, so check for that work before starting.
Written by the indexing model from the issue text.
Description
Tested versions
- Reproducible in:
master(2f04816ffd), local Linux editor build, and the official 26.3-stable build.
System information
CachyOS (Linux 7.2), x86_64.
Issue description
With vertex_spacing above 1, WorldScape3D builds no collision near the world origin while the camera is over it. Physics bodies fall through the terrain, and raycasts miss. Collision appears once the camera moves about 16 units away.
On the official 26.3-stable build with vertex_spacing = 2 and the camera at the origin, 0 of 121 downward raycasts in a 40×40 area hit the terrain. Each update also logs errors like:
ERROR: Index p_index = -1207959516 is out of bounds (size() = 64).
Cause: WorldScape3DCollision::update() parks unused shapes at V3_MAX, then converts every shape's position to int before checking for that value. Converting FLT_MAX to int is undefined behaviour. With vertex_spacing > 1, the position is divided by the spacing, so the < FLT_MAX check passes anyway. GCC 16 at -O2 also drops the check at vertex_spacing = 1. When the collision centre snaps to (0,0), the distance check for parked shapes overflows, so they count as active and no free shapes are left to build collision.
Steps to reproduce
- Create a scene with a
WorldScape3Dwithvertex_spacing = 2and a region at the origin. - Put the camera above (0, 0) and drop a
RigidBody3Donto the terrain near the origin. - It falls through.
Minimal reproduction project (MRP)
Three files plus an empty terrain_data folder. Run the project; after 4 seconds it prints whether each ball landed. On master it prints 0/6 balls landed.
project.godot
config_version=5
[application]
config/name="WorldScape Collision Test"
run/main_scene="res://main.tscn"
main.tscn
[gd_scene load_steps=2 format=3]
[ext_resource type="Script" path="res://main.gd" id="1"]
[node name="Main" type="Node3D"]
script = ExtResource("1")
[node name="Camera3D" type="Camera3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 30, 0)
[node name="DirectionalLight3D" type="DirectionalLight3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 0.707107, 0.707107, 0, -0.707107, 0.707107, 0, 10, 0)
main.gd
extends Node3D
# Builds a flat WorldScape3D region at height 10, with the camera above the
# origin, then drops balls near the origin. Balls that land rest at y ~ 10.5;
# balls with no collision under them fall through.
var balls: Array[RigidBody3D] = []
func _ready() -> void:
var cam := OS.get_environment("WS_CAM")
if cam != "":
var c := cam.split(",")
$Camera3D.position = Vector3(float(c[0]), float(c[1]), float(c[2]))
$Camera3D.look_at(Vector3(20, 10, 20))
var ws := WorldScape3D.new()
ws.data_directory = "res://terrain_data"
ws.collision_mode = 1
var vs := OS.get_environment("WS_VS")
ws.vertex_spacing = float(vs) if vs != "" else 2.0
add_child(ws)
ws.set_camera($Camera3D)
var d = ws.get_data()
d.add_region_blankp(Vector3(1, 0, 1))
var size: float = ws.region_size * ws.vertex_spacing
for x in range(0, int(size), int(ws.vertex_spacing)):
for z in range(0, int(size), int(ws.vertex_spacing)):
d.set_height(Vector3(x, 0, z), 10.0)
d.update_maps()
for p in [Vector2(2, 2), Vector2(8, 8), Vector2(15, 5), Vector2(5, 15), Vector2(25, 25), Vector2(40, 10)]:
_drop(Vector3(p.x, 30, p.y))
print("vertex_spacing: ", ws.vertex_spacing, ", camera: ", $Camera3D.position)
await get_tree().create_timer(4.0).timeout
var landed := 0
for b in balls:
var ok := b.position.y > 5.0
landed += int(ok)
print("ball at (%d, %d): %s" % [b.position.x, b.position.z, "landed" if ok else "FELL THROUGH"])
print("%d/%d balls landed" % [landed, balls.size()])
if OS.has_environment("WS_QUIT"):
get_tree().quit()
func _drop(p: Vector3) -> void:
var b := RigidBody3D.new()
var s := CollisionShape3D.new()
s.shape = SphereShape3D.new()
s.shape.radius = 0.5
b.add_child(s)
var m := MeshInstance3D.new()
m.mesh = SphereMesh.new()
m.mesh.radius = 0.5
m.mesh.height = 1.0
b.add_child(m)
b.position = p
add_child(b)
balls.append(b)
I have a fix ready and will open a PR.
AI disclosure: I used Claude Code to find the cause and draft this report.
- Dominant language
- C++
- Stars
- 6.1k
- Forks
- 337
- Avg merge
- 1d 37m
- Merged PRs (30d)
- 42
Getting set up
- No Dockerfile or Docker Compose file
- Has a pull request template
- Read the contributing guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from Redot-Engine/redot-engine
-
bug topic:animation
Difficulty 3/5 1-2 days Newbie friendliness 54/100
Redot-Engine/redot-engine#1552 · 3 comments ·
Maintainers usually reply within 1 day
-
AnimationTree does not respect AnimationPlayer's speed_scale or the AnimationClip's update modeOpenbug topic:animation
Difficulty 4/5 3-5 days Newbie friendliness 45/100
Redot-Engine/redot-engine#1551 ·
Maintainers usually reply within 1 day
-
bug topic:editor topic:rendering
Difficulty 5/5 Over a week Newbie friendliness 35/100
Redot-Engine/redot-engine#1550 ·
Maintainers usually reply within 1 day
-
bug needs testing topic:core
Difficulty 4/5 3-5 days Newbie friendliness 50/100
Redot-Engine/redot-engine#1549 · 1 reaction ·
Maintainers usually reply within 1 day
-
bug enhancement topic:gdscript
Difficulty 5/5 Over a week Newbie friendliness 35/100
Redot-Engine/redot-engine#1548 ·
Maintainers usually reply within 1 day
All issues in Redot-Engine/redot-engine
Similar issues
-
(S1 - Need confirmation)
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
CleverRaven/Cataclysm-DDA#89212 ·
Maintainers usually reply within 1 day
-
Status: Needs confirmation Status: Needs triage
Difficulty 2/5 1-3 hours Newbie friendliness 70/100
Maintainers usually reply within 1 day
-
ai_p2 comp-dictionary
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
ClickHouse/ClickHouse#127261 ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 82/100
NVIDIA-Omniverse/usd-brep#23 ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
qbittorrent/qBittorrent#25121 ·
Maintainers usually reply within 2 days