Giter Club home page Giter Club logo

Comments (9)

matheusmdx avatar matheusmdx commented on July 16, 2024 3

I tested the code and was able to get a backtrace:

LocalVector<BVH_Tree<GodotCollisionObject3D,2,2,128,GodotBroadPhase3DBVH::UserPairTestFunction<GodotCollisionObject3D>,GodotBroadPhase3DBVH::UserCullTestFunction<GodotCollisionObject3D>,1,AABB,Vector3>::TLeaf,unsigned int,1,0>::operator[](unsigned int p_index) Line 177 (c:\Users\Matheus\Downloads\Godot Source\core\templates\local_vector.h:177)
PooledList<BVH_Tree<GodotCollisionObject3D,2,2,128,GodotBroadPhase3DBVH::UserPairTestFunction<GodotCollisionObject3D>,GodotBroadPhase3DBVH::UserCullTestFunction<GodotCollisionObject3D>,1,AABB,Vector3>::TLeaf,unsigned int,1,0>::operator[](unsigned int p_index) Line 90 (c:\Users\Matheus\Downloads\Godot Source\core\templates\pooled_list.h:90)
BVH_Tree<GodotCollisionObject3D,2,2,128,GodotBroadPhase3DBVH::UserPairTestFunction<GodotCollisionObject3D>,GodotBroadPhase3DBVH::UserCullTestFunction<GodotCollisionObject3D>,1,AABB,Vector3>::_node_get_leaf(BVH_Tree<GodotCollisionObject3D,2,2,128,GodotBroadPhase3DBVH::UserPairTestFunction<GodotCollisionObject3D>,GodotBroadPhase3DBVH::UserCullTestFunction<GodotCollisionObject3D>,1,AABB,Vector3>::TNode & tnode) Line 44 (c:\Users\Matheus\Downloads\Godot Source\core\math\bvh_misc.inc:44)
BVH_Tree<GodotCollisionObject3D,2,2,128,GodotBroadPhase3DBVH::UserPairTestFunction<GodotCollisionObject3D>,GodotBroadPhase3DBVH::UserCullTestFunction<GodotCollisionObject3D>,1,AABB,Vector3>::_node_add_item(unsigned int p_node_id, unsigned int p_ref_id, const BVH_ABB<AABB,Vector3> & p_aabb) Line 399 (c:\Users\Matheus\Downloads\Godot Source\core\math\bvh_tree.h:399)
BVH_Tree<GodotCollisionObject3D,2,2,128,GodotBroadPhase3DBVH::UserPairTestFunction<GodotCollisionObject3D>,GodotBroadPhase3DBVH::UserCullTestFunction<GodotCollisionObject3D>,1,AABB,Vector3>::split_leaf_complex(unsigned int p_node_id, const BVH_ABB<AABB,Vector3> & p_added_item_aabb) Line 269 (c:\Users\Matheus\Downloads\Godot Source\core\math\bvh_split.inc:269)
BVH_Tree<GodotCollisionObject3D,2,2,128,GodotBroadPhase3DBVH::UserPairTestFunction<GodotCollisionObject3D>,GodotBroadPhase3DBVH::UserCullTestFunction<GodotCollisionObject3D>,1,AABB,Vector3>::split_leaf(unsigned int p_node_id, const BVH_ABB<AABB,Vector3> & p_added_item_aabb) Line 191 (c:\Users\Matheus\Downloads\Godot Source\core\math\bvh_split.inc:191)
BVH_Tree<GodotCollisionObject3D,2,2,128,GodotBroadPhase3DBVH::UserPairTestFunction<GodotCollisionObject3D>,GodotBroadPhase3DBVH::UserCullTestFunction<GodotCollisionObject3D>,1,AABB,Vector3>::_logic_choose_item_add_node(unsigned int p_node_id, const BVH_ABB<AABB,Vector3> & p_aabb) Line 212 (c:\Users\Matheus\Downloads\Godot Source\core\math\bvh_logic.inc:212)
BVH_Tree<GodotCollisionObject3D,2,2,128,GodotBroadPhase3DBVH::UserPairTestFunction<GodotCollisionObject3D>,GodotBroadPhase3DBVH::UserCullTestFunction<GodotCollisionObject3D>,1,AABB,Vector3>::item_add(GodotCollisionObject3D * p_userdata, bool p_active, const AABB & p_aabb, int p_subindex, unsigned int p_tree_id, unsigned int p_tree_collision_mask, bool p_invisible) Line 60 (c:\Users\Matheus\Downloads\Godot Source\core\math\bvh_public.inc:60)
BVH_Manager<GodotCollisionObject3D,2,1,128,GodotBroadPhase3DBVH::UserPairTestFunction<GodotCollisionObject3D>,GodotBroadPhase3DBVH::UserCullTestFunction<GodotCollisionObject3D>,AABB,Vector3,1>::create(GodotCollisionObject3D * p_userdata, bool p_active, unsigned int p_tree_id, unsigned int p_tree_collision_mask, const AABB & p_aabb, int p_subindex) Line 118 (c:\Users\Matheus\Downloads\Godot Source\core\math\bvh.h:118)
GodotBroadPhase3DBVH::create(GodotCollisionObject3D * p_object, int p_subindex, const AABB & p_aabb, bool p_static) Line 38 (c:\Users\Matheus\Downloads\Godot Source\servers\physics_3d\godot_broad_phase_3d_bvh.cpp:38)
GodotCollisionObject3D::_update_shapes() Line 177 (c:\Users\Matheus\Downloads\Godot Source\servers\physics_3d\godot_collision_object_3d.cpp:177)
GodotCollisionObject3D::_shape_changed() Line 236 (c:\Users\Matheus\Downloads\Godot Source\servers\physics_3d\godot_collision_object_3d.cpp:236)
GodotPhysicsServer3D::_update_shapes() Line 1736 (c:\Users\Matheus\Downloads\Godot Source\servers\physics_3d\godot_physics_server_3d.cpp:1736)
GodotPhysicsServer3D::body_test_motion(RID p_body, const PhysicsServer3D::MotionParameters & p_parameters, PhysicsServer3D::MotionResult * r_result) Line 920 (c:\Users\Matheus\Downloads\Godot Source\servers\physics_3d\godot_physics_server_3d.cpp:920)
PhysicsServer3DWrapMT::body_test_motion(RID p_body, const PhysicsServer3D::MotionParameters & p_parameters, PhysicsServer3D::MotionResult * r_result) Line 263 (c:\Users\Matheus\Downloads\Godot Source\servers\physics_server_3d_wrap_mt.h:263)
PhysicsBody3D::move_and_collide(const PhysicsServer3D::MotionParameters & p_parameters, PhysicsServer3D::MotionResult & r_result, bool p_test_only, bool p_cancel_sliding) Line 109 (c:\Users\Matheus\Downloads\Godot Source\scene\3d\physics\physics_body_3d.cpp:109)
CharacterBody3D::_move_and_slide_grounded(double p_delta, bool p_was_on_floor) Line 159 (c:\Users\Matheus\Downloads\Godot Source\scene\3d\physics\character_body_3d.cpp:159)
CharacterBody3D::move_and_slide() Line 108 (c:\Users\Matheus\Downloads\Godot Source\scene\3d\physics\character_body_3d.cpp:108)
call_with_validated_variant_args_ret_helper<CharacterBody3D,bool>(CharacterBody3D * p_instance, bool(CharacterBody3D::*)() p_method, const Variant * * p_args, Variant * r_ret, IndexSequence<> __formal) Line 375 (c:\Users\Matheus\Downloads\Godot Source\core\variant\binder_common.h:375)
call_with_validated_object_instance_args_ret<CharacterBody3D,bool>(CharacterBody3D * base, bool(CharacterBody3D::*)() p_method, const Variant * * p_args, Variant * r_ret) Line 663 (c:\Users\Matheus\Downloads\Godot Source\core\variant\binder_common.h:663)
MethodBindTR<CharacterBody3D,bool>::validated_call(Object * p_object, const Variant * * p_args, Variant * r_ret) Line 537 (c:\Users\Matheus\Downloads\Godot Source\core\object\method_bind.h:537)
GDScriptFunction::call(GDScriptInstance * p_instance, const Variant * * p_args, int p_argcount, Callable::CallError & r_err, GDScriptFunction::CallState * p_state) Line 1989 (c:\Users\Matheus\Downloads\Godot Source\modules\gdscript\gdscript_vm.cpp:1989)
GDScriptInstance::callp(const StringName & p_method, const Variant * * p_args, int p_argcount, Callable::CallError & r_error) Line 1970 (c:\Users\Matheus\Downloads\Godot Source\modules\gdscript\gdscript.cpp:1970)
Node::_gdvirtual__physics_process_call<0>(double arg1) Line 351 (c:\Users\Matheus\Downloads\Godot Source\scene\main\node.h:351)
Node::_notification(int p_notification) Line 62 (c:\Users\Matheus\Downloads\Godot Source\scene\main\node.cpp:62)
Node::_notificationv(int p_notification, bool p_reversed) Line 49 (c:\Users\Matheus\Downloads\Godot Source\scene\main\node.h:49)
Node3D::_notificationv(int p_notification, bool p_reversed) Line 52 (c:\Users\Matheus\Downloads\Godot Source\scene\3d\node_3d.h:52)
CollisionObject3D::_notificationv(int p_notification, bool p_reversed) Line 38 (c:\Users\Matheus\Downloads\Godot Source\scene\3d\physics\collision_object_3d.h:38)
PhysicsBody3D::_notificationv(int p_notification, bool p_reversed) Line 41 (c:\Users\Matheus\Downloads\Godot Source\scene\3d\physics\physics_body_3d.h:41)
CharacterBody3D::_notificationv(int p_notification, bool p_reversed) Line 38 (c:\Users\Matheus\Downloads\Godot Source\scene\3d\physics\character_body_3d.h:38)
Object::notification(int p_notification, bool p_reversed) Line 902 (c:\Users\Matheus\Downloads\Godot Source\core\object\object.cpp:902)
SceneTree::_process_group(SceneTree::ProcessGroup * p_group, bool p_physics) Line 965 (c:\Users\Matheus\Downloads\Godot Source\scene\main\scene_tree.cpp:965)
SceneTree::_process(bool p_physics) Line 1050 (c:\Users\Matheus\Downloads\Godot Source\scene\main\scene_tree.cpp:1050)
SceneTree::physics_process(double p_time) Line 492 (c:\Users\Matheus\Downloads\Godot Source\scene\main\scene_tree.cpp:492)
Main::iteration() Line 3983 (c:\Users\Matheus\Downloads\Godot Source\main\main.cpp:3983)
OS_Windows::run() Line 1673 (c:\Users\Matheus\Downloads\Godot Source\platform\windows\os_windows.cpp:1673)
widechar_main(int argc, wchar_t * * argv) Line 181 (c:\Users\Matheus\Downloads\Godot Source\platform\windows\godot_windows.cpp:181)
_main() Line 206 (c:\Users\Matheus\Downloads\Godot Source\platform\windows\godot_windows.cpp:206)
main(int argc, char * * argv) Line 220 (c:\Users\Matheus\Downloads\Godot Source\platform\windows\godot_windows.cpp:220)
WinMain(HINSTANCE__ * hInstance, HINSTANCE__ * hPrevInstance, char * lpCmdLine, int nCmdShow) Line 234 (c:\Users\Matheus\Downloads\Godot Source\platform\windows\godot_windows.cpp:234)
[Inline Frame] invoke_main() Line 102 (d:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl:102)
__scrt_common_main_seh() Line 288 (d:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl:288)
kernel32.dll!00007ffeaf277344() (Unknown Source:0)
ntdll.dll!00007ffeaf63cc91() (Unknown Source:0)

Also some pics with (maybe useful?) extra info:

Captura 2024-06-13 15-47-10-072691
Captura 2024-06-13 17-41-55-864537
Captura 2024-06-13 17-43-01-480709
Captura 2024-06-13 17-43-31-668880

from godot.

huwpascoe avatar huwpascoe commented on July 16, 2024 2

would this not just disallow generation of blocks with a negative coordinate, as this should be possible.

Ah, sorry, I misunderstood how gridmap works. It actually ranges from -1mil to +1mil

I tested the code and was able to get a backtrace

And that gives us the answer. It looks like the sheer number of collision objects is causing the crash.
Maybe this is a bug as it's not supposed to crash, but it's also going to be slow even if it wasn't...

Suggestion

Use two gridmaps. One for the visual data, that renders however far you'd like, and one for collision that only has the few chunks the player stands in is loaded.

Also, currently every block has it's own material and an identical copy of the source pixel art texture like "Snow_Blocks_PixelArt.png" and "Coal_Blocks_PixelArt.png". If they shared the same material and texture (and not have backface culling disabled) then the framerate can go up a lot.

from godot.

matheusmdx avatar matheusmdx commented on July 16, 2024 2

I did some extra investigation and what i found:

The cause of crash is a implict conversion that happens here:

T &operator[](U p_index) {
return list[p_index];
}

#include "core/templates/local_vector.h"
template <typename T, typename U = uint32_t, bool force_trivial = false, bool zero_on_first_request = false>


As you can see the U value is a uint32_t in this template and for some reason tnode.get_leaf_id() is returning a negative value (-2) here

TLeaf &_node_get_leaf(TNode &tnode) {
BVH_ASSERT(tnode.is_leaf());
return _leaves[tnode.get_leaf_id()];
}


The uint32_t variable can't hold negative values, so the code treats the -2 as an overflow and wraps to 4294967294. tnode.get_leaf_id() returns the value of tnode.neg_leaf_id inverting the signal, so that means tnode.neg_leaf_id for some reason is receiving a non-negative value and when tnode.get_leaf_id() inverts the signal, transforms the result in a negative value

struct TNode {
BVHABB_CLASS aabb;
// either number of children if positive
// or leaf id if negative (leaf id 0 is disallowed)
union {
int32_t num_children;
int32_t neg_leaf_id;
};
uint32_t parent_id; // or -1
uint16_t children[MAX_CHILDREN];
// height in the tree, where leaves are 0, and all above are 1+
// (or the highest where there is a tie off)
int32_t height;
bool is_leaf() const { return num_children < 0; }
void set_leaf_id(int id) { neg_leaf_id = -id; }
int get_leaf_id() const { return -neg_leaf_id; }

Considering my assumption is correct, the last question is why tnode.neg_leaf_id is receiving a non-negative value (and is always the same value, 2)

from godot.

AlexLovelock22 avatar AlexLovelock22 commented on July 16, 2024
extends Node3D

# The size of each chunk in blocks
var chunkSize = Vector3(16, 16, 16)

var renderDistance = 20
var generatedChunks = {}
var queue = []
var tasksPerFrame = 1
var current_player_chunk = Vector3(-999, 0, -999)  # Invalid initial chunk position

# The size of the world in chunks
var initialWorldSize = Vector3(8, 1, 8)  # Adjust based on your needs

# Noise generator instance
var noise_generator : FastNoiseLite

# MeshLibrary containing block meshes
@export var mesh_library : MeshLibrary

# GridMap to manage the voxel terrain
@onready var grid_map : GridMap = $GridMap
 
func _ready():
	# Load the mesh library from the provided file
	mesh_library = load("res://Resources/blocks.tres")
	
	# Initialize the noise generator
	noise_generator = FastNoiseLite.new()
	noise_generator.noise_type = FastNoiseLite.TYPE_SIMPLEX_SMOOTH
	noise_generator.seed = randi()
	noise_generator.frequency = 0.01  # Controls the frequency of the noise

	# Assign the mesh library to the GridMap
	grid_map.mesh_library = mesh_library
	
func _process(delta):
	var playerPos = getPlayerPos()
	var playerChunk = getPlayerChunk(playerPos)
	
	if playerChunk != current_player_chunk:
		current_player_chunk = playerChunk
		generateChunkAroundPlayer(playerChunk)
		
		
	processQueue()
	generateChunkAroundPlayer(playerChunk)

func generateChunkAroundPlayer(playerChunk: Vector3):
	for x in range(-renderDistance, renderDistance + 1):
		for z in range(-renderDistance, renderDistance + 1):
			var chunkPos = playerChunk + Vector3(x,0,z)
			if not generatedChunks.has(chunkPos):
				queue.append(chunkPos)
	
func processQueue():
	for i in range(min(queue.size(), tasksPerFrame)):
		var chunkPos = queue.pop_front()
		generateChunk(chunkPos)
		generatedChunks[chunkPos] = true

# Function to generate a single chunk of terrain
func generateChunk(playerChunk: Vector3):
	for x in range(chunkSize.x):
		for z in range(chunkSize.z):
			var world_x = int(playerChunk.x * chunkSize.x + x)
			var world_z = int(playerChunk.z * chunkSize.z + z)
			var height = int(noise_generator.get_noise_2d(world_x * 0.1, world_z * 0.1) * 10) + 10
			for y in range(chunkSize.y):
				var world_y = int(y)
				if world_y <= height:
					if noise_generator.get_noise_3d(world_x * 0.1, world_y * 0.1, world_z * 0.1) < 0.5:
						set_block(world_x, world_y, world_z, "Grass")
					elif world_y < height - 3:
						set_block(world_x, world_y, world_z, "Dirt")
					else:
						set_block(world_x, world_y, world_z, "Stone")
					
func getPlayerPos():
	return get_node("/root/Level/Player").global_transform.origin / 2

func getPlayerChunk(playerPosition):
	return Vector3(
		int(floor(playerPosition.x / chunkSize.x)), 
		0,
		int(floor(playerPosition.z / chunkSize.z))
	)

# Function to set a block in the GridMap
func set_block(x: int, y: int, z: int, block_type: String):
	var block_id = mesh_library.find_item_by_name(block_type)
	if block_id >= 0:
		grid_map.set_cell_item(Vector3i(x, y, z), block_id)

This code seems to trigger it just by itself

from godot.

matheusmdx avatar matheusmdx commented on July 16, 2024

Your code can't run because don't have the assets that you use and also don't have the scene tree with the correct nodes, will make debug much more easier if you upload a MRP with everything ready to test

from godot.

AlexLovelock22 avatar AlexLovelock22 commented on July 16, 2024

@matheusmdx Thanks for the reply, I've uploaded the version to github, theres pretty much nothing else there so it's pretty much an MRP. Perhaps you could give it a run? The issue happens when I up the render_distance in level.gd from 12 to like.... 21ish? \https://github.com/AlexLovelock22/VoxelOne

from godot.

huwpascoe avatar huwpascoe commented on July 16, 2024

I'm unable to look at the project currently, but notice that set_block isn't bounds checked and world_x and world_z could be less than zero (-1 == (uint32)4294967294)

func set_block(x: int, y: int, z: int, block_type: String):
	assert(x >= 0 and y >= 0 and z >= 0, "oh no")

from godot.

AlexLovelock22 avatar AlexLovelock22 commented on July 16, 2024

@huwpascoe Thanks for the reply. Correct my if im wrong (beacuse I probably am), but would this not just disallow generation of blocks with a negative coordinate, as this should be possible. Also just realised the code snippet I sent wasnt the full one. The full one is in the repo, Scripts/level.gd. Thanks

from godot.

AlexLovelock22 avatar AlexLovelock22 commented on July 16, 2024

@matheusmdx @huwpascoe
Ah yes, thank you so much guys. I'll give it a go now :D

from godot.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.