Эх сурвалжийг харах

Merge pull request #559 from nekomatata/physics-tests-3d-update

Fixes and adjustments in 3D physics tests
Aaron Franke 4 жил өмнө
parent
commit
1c836ecde9

+ 2 - 2
3d/physics_tests/project.godot

@@ -26,7 +26,7 @@ _global_script_class_icons={
 
 
 [application]
 [application]
 
 
-config/name="Physics Tests"
+config/name="3D Physics Tests"
 run/main_scene="res://main.tscn"
 run/main_scene="res://main.tscn"
 config/icon="res://icon.png"
 config/icon="res://icon.png"
 
 
@@ -71,5 +71,5 @@ restart_test={
 [rendering]
 [rendering]
 
 
 quality/driver/driver_name="GLES2"
 quality/driver/driver_name="GLES2"
-environment/default_clear_color=Color( 0, 0, 0, 1 )
+environment/default_clear_color=Color( 0.184314, 0.184314, 0.184314, 1 )
 quality/filters/msaa=2
 quality/filters/msaa=2

+ 28 - 0
3d/physics_tests/test.gd

@@ -1,10 +1,33 @@
 class_name Test
 class_name Test
 extends Node
 extends Node
 
 
+signal wait_done()
 
 
 var _timer
 var _timer
 var _timer_started = false
 var _timer_started = false
 
 
+var _wait_physics_ticks_counter = 0
+
+
+func _physics_process(_delta):
+	if (_wait_physics_ticks_counter > 0):
+		_wait_physics_ticks_counter -= 1
+		if (_wait_physics_ticks_counter == 0):
+			emit_signal("wait_done")
+
+
+func create_rigidbody_box(size):
+	var template_shape = BoxShape.new()
+	template_shape.extents = 0.5 * size
+
+	var template_collision = CollisionShape.new()
+	template_collision.shape = template_shape
+
+	var template_body = RigidBody.new()
+	template_body.add_child(template_collision)
+
+	return template_body
+
 
 
 func start_timer(timeout):
 func start_timer(timeout):
 	if _timer == null:
 	if _timer == null:
@@ -32,5 +55,10 @@ func is_timer_canceled():
 	return _timer.paused
 	return _timer.paused
 
 
 
 
+func wait_for_physics_ticks(tick_count):
+	_wait_physics_ticks_counter = tick_count
+	return self
+
+
 func _on_timer_done():
 func _on_timer_done():
 	_timer_started = false
 	_timer_started = false

+ 16 - 0
3d/physics_tests/tests.gd

@@ -14,6 +14,22 @@ var _tests = [
 		"id": "Functional Tests/Friction",
 		"id": "Functional Tests/Friction",
 		"path": "res://tests/functional/test_friction.tscn",
 		"path": "res://tests/functional/test_friction.tscn",
 	},
 	},
+	{
+		"id": "Functional Tests/Box Stack",
+		"path": "res://tests/functional/test_stack.tscn",
+	},
+	{
+		"id": "Functional Tests/Box Pyramid",
+		"path": "res://tests/functional/test_pyramid.tscn",
+	},
+	{
+		"id": "Functional Tests/Raycasting",
+		"path": "res://tests/functional/test_raycasting.tscn",
+	},
+	{
+		"id": "Performance Tests/Broadphase",
+		"path": "res://tests/performance/test_perf_broadphase.tscn",
+	},
 	{
 	{
 		"id": "Performance Tests/Contacts",
 		"id": "Performance Tests/Contacts",
 		"path": "res://tests/performance/test_perf_contacts.tscn",
 		"path": "res://tests/performance/test_perf_contacts.tscn",

+ 58 - 0
3d/physics_tests/tests/functional/test_pyramid.gd

@@ -0,0 +1,58 @@
+extends Test
+
+
+export(int, 1, 100) var height = 10
+export(int, 1, 100) var width_max = 100
+export(int, 1, 100) var depth_max = 1
+export(Vector3) var box_size = Vector3(1.0, 1.0, 1.0)
+export(Vector3) var box_spacing = Vector3(0.0, 0.0, 0.0)
+
+
+func _ready():
+	_create_pyramid()
+
+
+func _create_pyramid():
+	var root_node = $Pyramid
+
+	var template_shape = BoxShape.new()
+	template_shape.extents = 0.5 * box_size
+
+	var template_collision = CollisionShape.new()
+	template_collision.shape = template_shape
+
+	var template_body = RigidBody.new()
+	template_body.add_child(template_collision)
+
+	var pos_y = 0.5 * box_size.y + box_spacing.y
+
+	for level in height:
+		var level_index = height - level - 1
+		var num_boxes = 2 * level_index + 1
+		var num_boxes_width = min(num_boxes, width_max)
+		var num_boxes_depth = min(num_boxes, depth_max)
+
+		var row_node = Spatial.new()
+		row_node.transform.origin = Vector3(0.0, pos_y, 0.0)
+		row_node.name = "Row%02d" % (level + 1)
+		root_node.add_child(row_node)
+
+		var pos_x = -0.5 * (num_boxes_width - 1) * (box_size.x + box_spacing.x)
+
+		for box_index_x in num_boxes_width:
+			var pos_z = -0.5 * (num_boxes_depth - 1) * (box_size.z + box_spacing.z)
+
+			for box_index_z in num_boxes_depth:
+				var box_index = box_index_x * box_index_z
+				var box = template_body.duplicate()
+				box.transform.origin = Vector3(pos_x, 0.0, pos_z)
+				box.name = "Box%02d" % (box_index + 1)
+				row_node.add_child(box)
+
+				pos_z += box_size.z + box_spacing.z
+
+			pos_x += box_size.x + box_spacing.x
+
+		pos_y += box_size.y + box_spacing.y
+
+	template_body.queue_free()

+ 16 - 0
3d/physics_tests/tests/functional/test_pyramid.tscn

@@ -0,0 +1,16 @@
+[gd_scene load_steps=4 format=2]
+
+[ext_resource path="res://tests/functional/test_pyramid.gd" type="Script" id=1]
+[ext_resource path="res://tests/static_scene_plane.tscn" type="PackedScene" id=2]
+[ext_resource path="res://utils/camera_orbit.gd" type="Script" id=4]
+
+[node name="Test" type="Spatial"]
+script = ExtResource( 1 )
+
+[node name="Pyramid" type="Spatial" parent="."]
+
+[node name="StaticBodyPlane" parent="." instance=ExtResource( 2 )]
+
+[node name="Camera" type="Camera" parent="."]
+transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 6.62348, 22.9474 )
+script = ExtResource( 4 )

+ 78 - 0
3d/physics_tests/tests/functional/test_raycasting.gd

@@ -0,0 +1,78 @@
+extends Test
+
+
+var _do_raycasts = false
+
+onready var _raycast_visuals = ImmediateGeometry.new()
+
+
+func _ready():
+	var material = SpatialMaterial.new()
+	material.flags_unshaded = true
+	material.vertex_color_use_as_albedo = true
+	_raycast_visuals.material_override = material
+
+	add_child(_raycast_visuals)
+	move_child(_raycast_visuals, get_child_count())
+
+	yield(start_timer(0.5), "timeout")
+	if is_timer_canceled():
+		return
+
+	_do_raycasts = true
+
+
+func _physics_process(_delta):
+	if !_do_raycasts:
+		return
+
+	_do_raycasts = false
+
+	Log.print_log("* Start Raycasting...")
+
+	_raycast_visuals.clear()
+	_raycast_visuals.begin(Mesh.PRIMITIVE_LINES)
+
+	for shape in $Shapes.get_children():
+		var body = shape as PhysicsBody
+		var space_state = body.get_world().direct_space_state
+
+		Log.print_log("* Testing: %s" % body.name)
+
+		var center = body.global_transform.origin
+
+		# Raycast entering from the top.
+		var res = _add_raycast(space_state, center + Vector3(0.0, 2.0, 0.0), center)
+		Log.print_log("Raycast in: %s" % ("HIT" if res else "NO HIT"))
+
+		# Raycast exiting from inside.
+		center.x -= 0.2
+		res = _add_raycast(space_state, center, center - Vector3(0.0, 3.0, 0.0))
+		Log.print_log("Raycast out: %s" % ("HIT" if res else "NO HIT"))
+
+		# Raycast all inside.
+		center.x += 0.4
+		res = _add_raycast(space_state, center, center - Vector3(0.0, 0.8, 0.0))
+		Log.print_log("Raycast inside: %s" % ("HIT" if res else "NO HIT"))
+
+	_raycast_visuals.end()
+
+
+func _add_raycast(space_state, pos_start, pos_end):
+	var result = space_state.intersect_ray(pos_start, pos_end)
+	if result:
+		_raycast_visuals.set_color(Color.green)
+	else:
+		_raycast_visuals.set_color(Color.red.darkened(0.5))
+
+	# Draw raycast line.
+	_raycast_visuals.add_vertex(pos_start)
+	_raycast_visuals.add_vertex(pos_end)
+
+	# Draw raycast arrow.
+	_raycast_visuals.add_vertex(pos_end)
+	_raycast_visuals.add_vertex(pos_end + Vector3(-0.05, 0.1, 0.0))
+	_raycast_visuals.add_vertex(pos_end)
+	_raycast_visuals.add_vertex(pos_end + Vector3(0.05, 0.1, 0.0))
+
+	return result

+ 74 - 0
3d/physics_tests/tests/functional/test_raycasting.tscn

@@ -0,0 +1,74 @@
+[gd_scene load_steps=10 format=2]
+
+[ext_resource path="res://assets/robot_head/godot3_robot_head_collision.tres" type="Shape" id=1]
+[ext_resource path="res://tests/functional/test_raycasting.gd" type="Script" id=2]
+[ext_resource path="res://utils/exception_cylinder.gd" type="Script" id=3]
+[ext_resource path="res://utils/camera_orbit.gd" type="Script" id=4]
+
+[sub_resource type="BoxShape" id=1]
+
+[sub_resource type="CapsuleShape" id=2]
+
+[sub_resource type="CylinderShape" id=3]
+
+[sub_resource type="ConvexPolygonShape" id=4]
+points = PoolVector3Array( -0.7, 0, -0.7, -0.3, 0, 0.8, 0.8, 0, -0.3, 0, -1, 0 )
+
+[sub_resource type="SphereShape" id=5]
+
+[node name="Test" type="Spatial"]
+script = ExtResource( 2 )
+
+[node name="Shapes" type="Spatial" parent="."]
+transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 9.35591, 0 )
+
+[node name="RigidBodyBox" type="RigidBody" parent="Shapes"]
+transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, -6, 0, 0 )
+mode = 3
+
+[node name="CollisionShape" type="CollisionShape" parent="Shapes/RigidBodyBox"]
+transform = Transform( 0.579556, 0.0885213, 0.145926, 0, 0.939693, -0.205212, -0.155291, 0.330366, 0.544604, 0, 0, 0 )
+shape = SubResource( 1 )
+
+[node name="RigidBodyCapsule" type="RigidBody" parent="Shapes"]
+transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, -3, 0, 0 )
+mode = 3
+
+[node name="CollisionShape" type="CollisionShape" parent="Shapes/RigidBodyCapsule"]
+transform = Transform( 0.8, 0, 0, 0, -1.30337e-07, -0.8, 0, 0.8, -1.30337e-07, 0, 0, 0 )
+shape = SubResource( 2 )
+
+[node name="RigidBodyCylinder" type="RigidBody" parent="Shapes"]
+mode = 3
+script = ExtResource( 3 )
+
+[node name="CollisionShape" type="CollisionShape" parent="Shapes/RigidBodyCylinder"]
+transform = Transform( 0.772741, -0.258819, 2.59821e-08, 0.2, 0.933013, -0.207055, 0.0535898, 0.25, 0.772741, 0, 0, 0 )
+shape = SubResource( 3 )
+
+[node name="RigidBodyConvex" type="RigidBody" parent="Shapes"]
+transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 3, -0.210678, 0 )
+mode = 3
+
+[node name="CollisionShape" type="CollisionShape" parent="Shapes/RigidBodyConvex"]
+transform = Transform( 2, 0, 0, 0, 2.89766, -0.517939, 0, 0.776908, 1.93177, 0, 0.3533, 0 )
+shape = SubResource( 4 )
+
+[node name="RigidBodySphere" type="RigidBody" parent="Shapes"]
+transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 6, 0, 0 )
+mode = 3
+
+[node name="CollisionShape" type="CollisionShape" parent="Shapes/RigidBodySphere"]
+transform = Transform( 1.2, 0, 0, 0, 1.2, 0, 0, 0, 1.2, 0, 0, 0 )
+shape = SubResource( 5 )
+
+[node name="StaticBodyHead" type="StaticBody" parent="Shapes"]
+transform = Transform( 2, 0, 0, 0, 2, 0, 0, 0, 2, 0, -6, 3.93357 )
+
+[node name="CollisionShape" type="CollisionShape" parent="Shapes/StaticBodyHead"]
+transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -1, 0 )
+shape = ExtResource( 1 )
+
+[node name="Camera" type="Camera" parent="."]
+transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 5.8667, 11.8164 )
+script = ExtResource( 4 )

+ 53 - 0
3d/physics_tests/tests/functional/test_stack.gd

@@ -0,0 +1,53 @@
+extends Test
+
+
+export(int, 1, 100) var height = 10
+export(int, 1, 100) var width = 1
+export(int, 1, 100) var depth = 1
+export(Vector3) var box_size = Vector3(1.0, 1.0, 1.0)
+export(Vector3) var box_spacing = Vector3(0.0, 0.0, 0.0)
+
+
+func _ready():
+	_create_stack()
+
+
+func _create_stack():
+	var root_node = $Stack
+
+	var template_shape = BoxShape.new()
+	template_shape.extents = 0.5 * box_size
+
+	var template_collision = CollisionShape.new()
+	template_collision.shape = template_shape
+
+	var template_body = RigidBody.new()
+	template_body.add_child(template_collision)
+
+	var pos_y = 0.5 * box_size.y + box_spacing.y
+
+	for level in height:
+		var row_node = Spatial.new()
+		row_node.transform.origin = Vector3(0.0, pos_y, 0.0)
+		row_node.name = "Row%02d" % (level + 1)
+		root_node.add_child(row_node)
+
+		var pos_x = -0.5 * (width - 1) * (box_size.x + box_spacing.x)
+
+		for box_index_x in width:
+			var pos_z = -0.5 * (depth - 1) * (box_size.z + box_spacing.z)
+
+			for box_index_z in depth:
+				var box_index = box_index_x * box_index_z
+				var box = template_body.duplicate()
+				box.transform.origin = Vector3(pos_x, 0.0, pos_z)
+				box.name = "Box%02d" % (box_index + 1)
+				row_node.add_child(box)
+
+				pos_z += box_size.z + box_spacing.z
+
+			pos_x += box_size.x + box_spacing.x
+
+		pos_y += box_size.y + box_spacing.y
+
+	template_body.queue_free()

+ 16 - 0
3d/physics_tests/tests/functional/test_stack.tscn

@@ -0,0 +1,16 @@
+[gd_scene load_steps=4 format=2]
+
+[ext_resource path="res://tests/functional/test_stack.gd" type="Script" id=1]
+[ext_resource path="res://tests/static_scene_plane.tscn" type="PackedScene" id=2]
+[ext_resource path="res://utils/camera_orbit.gd" type="Script" id=4]
+
+[node name="Test" type="Spatial"]
+script = ExtResource( 1 )
+
+[node name="Stack" type="Spatial" parent="."]
+
+[node name="StaticBodyPlane" parent="." instance=ExtResource( 2 )]
+
+[node name="Camera" type="Camera" parent="."]
+transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 4.53602, 12.2684 )
+script = ExtResource( 4 )

+ 155 - 0
3d/physics_tests/tests/performance/test_perf_broadphase.gd

@@ -0,0 +1,155 @@
+extends Test
+
+
+const BOX_SIZE = Vector3(0.8, 0.8, 0.8)
+const BOX_SPACE = Vector3(1.0, 1.0, 1.0)
+
+export(int, 1, 1000) var row_size = 20
+export(int, 1, 1000) var column_size = 20
+export(int, 1, 1000) var depth_size = 20
+
+var _objects = []
+
+var _log_physics = false
+var _log_physics_time = 0
+var _log_physics_time_start = 0
+
+
+func _ready():
+	_create_objects()
+
+	_log_physics_start()
+	yield(wait_for_physics_ticks(5), "wait_done")
+	_log_physics_stop()
+
+	yield(start_timer(1.0), "timeout")
+	if is_timer_canceled():
+		return
+
+	_add_objects()
+
+	_log_physics_start()
+	yield(wait_for_physics_ticks(5), "wait_done")
+	_log_physics_stop()
+
+	yield(start_timer(1.0), "timeout")
+	if is_timer_canceled():
+		return
+
+	_move_objects()
+
+	_log_physics_start()
+	yield(wait_for_physics_ticks(5), "wait_done")
+	_log_physics_stop()
+
+	yield(start_timer(1.0), "timeout")
+	if is_timer_canceled():
+		return
+
+	_remove_objects()
+
+	_log_physics_start()
+	yield(wait_for_physics_ticks(5), "wait_done")
+	_log_physics_stop()
+
+	yield(start_timer(1.0), "timeout")
+	if is_timer_canceled():
+		return
+
+	Log.print_log("* Done.")
+
+
+func _exit_tree():
+	for object in _objects:
+		object.free()
+
+
+func _physics_process(_delta):
+	if _log_physics:
+		var time = OS.get_ticks_usec()
+		var time_delta = time - _log_physics_time
+		var time_total = time - _log_physics_time_start
+		_log_physics_time = time
+		Log.print_log("  Physics Tick: %.3f ms (total = %.3f ms)" % [0.001 * time_delta, 0.001 * time_total])
+
+
+func _log_physics_start():
+	_log_physics = true
+	_log_physics_time_start = OS.get_ticks_usec()
+	_log_physics_time = _log_physics_time_start
+
+
+func _log_physics_stop():
+	_log_physics = false
+
+
+func _create_objects():
+	_objects.clear()
+
+	var template_body = create_rigidbody_box(BOX_SIZE)
+	template_body.gravity_scale = 0.0
+
+	Log.print_log("* Creating objects...")
+	var timer = OS.get_ticks_usec()
+
+	var pos_x = -0.5 * (row_size - 1) * BOX_SPACE.x
+
+	for row in row_size:
+		var pos_y = -0.5 * (column_size - 1) * BOX_SPACE.y
+
+		for column in column_size:
+			var pos_z = -0.5 * (depth_size - 1) * BOX_SPACE.z
+
+			for depth in depth_size:
+				var box = template_body.duplicate()
+				box.transform.origin = Vector3(pos_x, pos_y, pos_z)
+				box.name = "Box%03d" % (row * column + 1)
+				_objects.push_back(box)
+
+				pos_z += BOX_SPACE.z
+
+			pos_y += BOX_SPACE.y
+
+		pos_x += BOX_SPACE.x
+
+	timer = OS.get_ticks_usec() - timer
+	Log.print_log("  Create Time: %.3f ms" % (0.001 * timer))
+
+	template_body.queue_free()
+
+
+func _add_objects():
+	var root_node = $Objects
+
+	Log.print_log("* Adding objects...")
+	var timer = OS.get_ticks_usec()
+
+	for object in _objects:
+		root_node.add_child(object)
+
+	timer = OS.get_ticks_usec() - timer
+	Log.print_log("  Add Time: %.3f ms" % (0.001 * timer))
+
+
+func _move_objects():
+	Log.print_log("* Moving objects...")
+	var timer = OS.get_ticks_usec()
+
+	for object in _objects:
+		object.transform.origin += BOX_SPACE
+
+	timer = OS.get_ticks_usec() - timer
+	Log.print_log("  Move Time: %.3f ms" % (0.001 * timer))
+
+
+func _remove_objects():
+	var root_node = $Objects
+
+	Log.print_log("* Removing objects...")
+	var timer = OS.get_ticks_usec()
+
+	for object in _objects:
+		root_node.remove_child(object)
+
+	timer = OS.get_ticks_usec() - timer
+	Log.print_log("  Remove Time: %.3f ms" % (0.001 * timer))

+ 13 - 0
3d/physics_tests/tests/performance/test_perf_broadphase.tscn

@@ -0,0 +1,13 @@
+[gd_scene load_steps=3 format=2]
+
+[ext_resource path="res://tests/performance/test_perf_broadphase.gd" type="Script" id=1]
+[ext_resource path="res://utils/camera_orbit.gd" type="Script" id=5]
+
+[node name="Test" type="Spatial"]
+script = ExtResource( 1 )
+
+[node name="Objects" type="Spatial" parent="."]
+
+[node name="Camera" type="Camera" parent="."]
+transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 29.8407 )
+script = ExtResource( 5 )

+ 9 - 3
3d/physics_tests/tests/performance/test_perf_contacts.gd

@@ -10,7 +10,7 @@ const OPTION_TYPE_SPHERE = "Shape type/Sphere"
 export(Array) var spawns = Array()
 export(Array) var spawns = Array()
 
 
 export(int) var spawn_count = 100
 export(int) var spawn_count = 100
-export(int, 1, 10) var spawn_multipiler = 5
+export(int, 1, 10) var spawn_multiplier = 5
 
 
 var _object_templates = []
 var _object_templates = []
 
 
@@ -36,6 +36,11 @@ func _ready():
 	_start_all_types()
 	_start_all_types()
 
 
 
 
+func _exit_tree():
+	for object_template in _object_templates:
+		object_template.free()
+
+
 func _on_option_selected(option):
 func _on_option_selected(option):
 	cancel_timer()
 	cancel_timer()
 
 
@@ -123,9 +128,10 @@ func _spawn_objects(type_index):
 
 
 		Log.print_log("* Spawning: " + template_node.name)
 		Log.print_log("* Spawning: " + template_node.name)
 
 
-		for _index in range(spawn_multipiler):
-			for _node_index in spawn_count / spawn_multipiler:
+		for _index in range(spawn_multiplier):
+			for _node_index in spawn_count / spawn_multiplier:
 				var node = template_node.duplicate() as Spatial
 				var node = template_node.duplicate() as Spatial
+				node.transform.origin = Vector3.ZERO
 				spawn_parent.add_child(node)
 				spawn_parent.add_child(node)
 
 
 
 

+ 3 - 16
3d/physics_tests/tests/static_scene.tscn

@@ -1,25 +1,12 @@
-[gd_scene load_steps=5 format=2]
+[gd_scene load_steps=4 format=2]
 
 
 [ext_resource path="res://assets/robot_head/godot3_robot_head_collision.tres" type="Shape" id=1]
 [ext_resource path="res://assets/robot_head/godot3_robot_head_collision.tres" type="Shape" id=1]
 [ext_resource path="res://assets/robot_head/godot3_robot_head.mesh" type="ArrayMesh" id=2]
 [ext_resource path="res://assets/robot_head/godot3_robot_head.mesh" type="ArrayMesh" id=2]
-
-[sub_resource type="PlaneMesh" id=1]
-
-[sub_resource type="ConcavePolygonShape" id=2]
-data = PoolVector3Array( -1, 0, 1, 1, 0, -1, 1, 0, 1, -1, 0, 1, -1, 0, -1, 1, 0, -1 )
+[ext_resource path="res://tests/static_scene_plane.tscn" type="PackedScene" id=3]
 
 
 [node name="StaticScene" type="Spatial"]
 [node name="StaticScene" type="Spatial"]
 
 
-[node name="StaticBodyPlane" type="StaticBody" parent="."]
-
-[node name="MeshInstance" type="MeshInstance" parent="StaticBodyPlane"]
-transform = Transform( 50, 0, 0, 0, 1, 0, 0, 0, 50, 0, 0, 0 )
-mesh = SubResource( 1 )
-material/0 = null
-
-[node name="CollisionShape" type="CollisionShape" parent="StaticBodyPlane"]
-transform = Transform( 50, 0, 0, 0, 1, 0, 0, 0, 50, 0, 0, 0 )
-shape = SubResource( 2 )
+[node name="StaticBodyPlane" parent="." instance=ExtResource( 3 )]
 
 
 [node name="StaticBodyHead" type="StaticBody" parent="."]
 [node name="StaticBodyHead" type="StaticBody" parent="."]
 transform = Transform( 10, 0, 0, 0, 8.66025, 5, 0, -5, 8.66025, 0, -11.1389, 2.29332 )
 transform = Transform( 10, 0, 0, 0, 8.66025, 5, 0, -5, 8.66025, 0, -11.1389, 2.29332 )

+ 17 - 0
3d/physics_tests/tests/static_scene_plane.tscn

@@ -0,0 +1,17 @@
+[gd_scene load_steps=3 format=2]
+
+[sub_resource type="PlaneMesh" id=1]
+
+[sub_resource type="ConcavePolygonShape" id=2]
+data = PoolVector3Array( -1, 0, 1, 1, 0, -1, 1, 0, 1, -1, 0, 1, -1, 0, -1, 1, 0, -1 )
+
+[node name="StaticBodyPlane" type="StaticBody"]
+
+[node name="MeshInstance" type="MeshInstance" parent="."]
+transform = Transform( 50, 0, 0, 0, 1, 0, 0, 0, 50, 0, 0, 0 )
+mesh = SubResource( 1 )
+material/0 = null
+
+[node name="CollisionShape" type="CollisionShape" parent="."]
+transform = Transform( 50, 0, 0, 0, 1, 0, 0, 0, 50, 0, 0, 0 )
+shape = SubResource( 2 )

+ 4 - 0
3d/physics_tests/utils/container_log.gd

@@ -13,6 +13,10 @@ func _enter_tree():
 	remove_child(_entry_template)
 	remove_child(_entry_template)
 
 
 
 
+func _exit_tree():
+	_entry_template.free()
+
+
 func clear():
 func clear():
 	while get_child_count():
 	while get_child_count():
 		var entry = get_child(get_child_count() - 1)
 		var entry = get_child(get_child_count() - 1)