Hacktoberfest 2026: the issues maintainers tagged for October, open and beginner-friendly. Browse Hacktoberfest issues

WorldScape3D has no collision near the world origin with vertex_spacing > 1

Open
#1,537 0 comments 0 reactions 0 assignees View on GitHub

Maintainers usually reply within 1 day

@KazW is already working on this.

Since Oct 19, 2026.

  • #1538 by @KazW — open

Assessment

Difficulty
4/5
Estimated time
3-5 days
Newbie friendliness
35/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Active
Tech stack
cpp
Domain
game-dev

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

bug topic:worldscape usability
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
  1. Create a scene with a WorldScape3D with vertex_spacing = 2 and a region at the origin.
  2. Put the camera above (0, 0) and drop a RigidBody3D onto the terrain near the origin.
  3. 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

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from Redot-Engine/redot-engine

All issues in Redot-Engine/redot-engine

Similar issues

More C++ issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.