mirror of
https://github.com/godotengine/godot-benchmarks.git
synced 2026-09-03 18:14:28 +03:00
Add Physics 3D benchmarks (#76)
* Add Area3D benchmark * Add CharacterBody3D benchmark * Add Raycast3D benchmark * Add SoftBody3D benchmark * Add TriangleMesh benchmark * Set physics 3D benchmarks to run for 10 seconds
This commit is contained in:
committed by
GitHub
parent
5becabc28a
commit
f1ee9ebccb
81
benchmarks/physics/area_3d.gd
Normal file
81
benchmarks/physics/area_3d.gd
Normal file
@@ -0,0 +1,81 @@
|
||||
extends Benchmark
|
||||
|
||||
const SPREAD_H := 20.0
|
||||
const SPREAD_V := 10.0
|
||||
|
||||
|
||||
class TestScene:
|
||||
extends Node3D
|
||||
|
||||
var num_character_bodies: int
|
||||
var num_area_3d: int
|
||||
var visualize := true
|
||||
var area_3d_nodes: Array[Area3D]
|
||||
var time_accum := 0.0
|
||||
var shapes: Array[Shape3D] = [
|
||||
BoxShape3D.new(),
|
||||
CapsuleShape3D.new(),
|
||||
SphereShape3D.new(),
|
||||
]
|
||||
var meshes: Array[Mesh] = [
|
||||
BoxMesh.new(),
|
||||
CapsuleMesh.new(),
|
||||
SphereMesh.new(),
|
||||
]
|
||||
|
||||
func _init(_num_character_bodies: int, _num_area_3d: int, _visualize: bool) -> void:
|
||||
num_character_bodies = _num_character_bodies
|
||||
num_area_3d = _num_area_3d
|
||||
visualize = _visualize
|
||||
|
||||
func _ready() -> void:
|
||||
if visualize:
|
||||
var camera := Camera3D.new()
|
||||
camera.position = Vector3(0.0, 20.0, 20.0)
|
||||
camera.rotate_x(-0.8)
|
||||
add_child(camera)
|
||||
for i in num_character_bodies:
|
||||
var character_body := CharacterBody3D.new()
|
||||
character_body.position = Vector3(
|
||||
randf_range(-SPREAD_H, SPREAD_H),
|
||||
randf_range(0.0, SPREAD_V),
|
||||
randf_range(-SPREAD_H, SPREAD_H)
|
||||
)
|
||||
add_random_shape(character_body)
|
||||
add_child(character_body)
|
||||
|
||||
for i in num_area_3d:
|
||||
var area_2d := Area3D.new()
|
||||
area_2d.position = Vector3(
|
||||
randf_range(-SPREAD_H, SPREAD_H),
|
||||
randf_range(0.0, SPREAD_V),
|
||||
randf_range(-SPREAD_H, SPREAD_H)
|
||||
)
|
||||
add_random_shape(area_2d)
|
||||
add_child(area_2d)
|
||||
area_3d_nodes.append(area_2d)
|
||||
|
||||
func _physics_process(delta: float) -> void:
|
||||
for i in area_3d_nodes.size():
|
||||
time_accum += delta
|
||||
area_3d_nodes[i].position += Vector3(sin(time_accum), 0.0, cos(time_accum)) * 4.0
|
||||
|
||||
func add_random_shape(parent: CollisionObject3D) -> void:
|
||||
var r := randi() % shapes.size()
|
||||
var collision_shape := CollisionShape3D.new()
|
||||
collision_shape.shape = shapes[r]
|
||||
if visualize:
|
||||
var mesh_instance := MeshInstance3D.new()
|
||||
mesh_instance.mesh = meshes[r]
|
||||
parent.add_child(mesh_instance)
|
||||
parent.add_child(collision_shape)
|
||||
|
||||
|
||||
func _init() -> void:
|
||||
benchmark_time = 10e6
|
||||
test_physics = true
|
||||
test_idle = true
|
||||
|
||||
|
||||
func benchmark_1000_area_3d() -> TestScene:
|
||||
return TestScene.new(2000, 1000, true)
|
||||
66
benchmarks/physics/character_body_3d.gd
Normal file
66
benchmarks/physics/character_body_3d.gd
Normal file
@@ -0,0 +1,66 @@
|
||||
extends Benchmark
|
||||
|
||||
const SPEED := 30.0
|
||||
const JUMP_VELOCITY := -40.0
|
||||
const SPREAD_H := 32.0
|
||||
const SPREAD_V := 20.0
|
||||
|
||||
|
||||
class TestScene:
|
||||
extends Node3D
|
||||
|
||||
var grid_map_scene := preload("res://supplemental/gridmap_scene.tscn")
|
||||
var grid_map_node: Node3D
|
||||
var n_of_character_bodies: int
|
||||
var visualize := true
|
||||
var character_bodies: Array[CharacterBody3D] = []
|
||||
var capsule_mesh := CapsuleMesh.new()
|
||||
|
||||
func _init(_n_of_character_bodies: int, _visualize: bool) -> void:
|
||||
n_of_character_bodies = _n_of_character_bodies
|
||||
visualize = _visualize
|
||||
|
||||
func _ready() -> void:
|
||||
grid_map_node = grid_map_scene.instantiate()
|
||||
add_child(grid_map_node)
|
||||
for i in n_of_character_bodies:
|
||||
var body := CharacterBody3D.new()
|
||||
body.position = Vector3(
|
||||
randf_range(-SPREAD_H, SPREAD_H), randf_range(-SPREAD_V, SPREAD_V), 0.0
|
||||
)
|
||||
body.axis_lock_linear_z = true
|
||||
var collision_shape := CollisionShape3D.new()
|
||||
collision_shape.shape = CapsuleShape3D.new()
|
||||
body.add_child(collision_shape)
|
||||
if visualize:
|
||||
var mesh_instance := MeshInstance3D.new()
|
||||
mesh_instance.mesh = capsule_mesh
|
||||
body.add_child(mesh_instance)
|
||||
grid_map_node.add_child(body)
|
||||
character_bodies.append(body)
|
||||
|
||||
func _physics_process(delta: float) -> void:
|
||||
for body in character_bodies:
|
||||
if not body.is_on_floor():
|
||||
body.velocity += body.get_gravity() * delta
|
||||
|
||||
if body.is_on_floor():
|
||||
body.velocity.y = JUMP_VELOCITY
|
||||
|
||||
var direction := randf_range(-1.0, 1.0)
|
||||
if direction:
|
||||
body.velocity.x = direction * SPEED
|
||||
else:
|
||||
body.velocity.x = move_toward(body.velocity.x, 0, SPEED)
|
||||
|
||||
body.move_and_slide()
|
||||
|
||||
|
||||
func _init() -> void:
|
||||
benchmark_time = 10e6
|
||||
test_physics = true
|
||||
test_idle = true
|
||||
|
||||
|
||||
func benchmark_1000_character_bodies_3d() -> TestScene:
|
||||
return TestScene.new(1000, true)
|
||||
56
benchmarks/physics/raycast_3d.gd
Normal file
56
benchmarks/physics/raycast_3d.gd
Normal file
@@ -0,0 +1,56 @@
|
||||
extends Benchmark
|
||||
|
||||
const N_OF_RAYCASTS := 10_000
|
||||
const N_OF_SHAPES := 2000
|
||||
const SPREAD_H := 20.0
|
||||
|
||||
var space: RID
|
||||
var bodies: Array[RID]
|
||||
var shapes: Array[RID]
|
||||
|
||||
|
||||
func _setup_scene() -> void:
|
||||
space = PhysicsServer3D.space_create()
|
||||
PhysicsServer3D.space_set_active(space, true)
|
||||
for i in N_OF_SHAPES:
|
||||
var body := PhysicsServer3D.body_create()
|
||||
var shape: RID
|
||||
var r := randi() % 3
|
||||
match r:
|
||||
0:
|
||||
shape = PhysicsServer3D.box_shape_create()
|
||||
1:
|
||||
shape = PhysicsServer3D.capsule_shape_create()
|
||||
2:
|
||||
shape = PhysicsServer3D.sphere_shape_create()
|
||||
PhysicsServer3D.body_add_shape(body, shape)
|
||||
shapes.append(shape)
|
||||
PhysicsServer3D.body_set_space(body, space)
|
||||
bodies.append(body)
|
||||
var transform := Transform3D()
|
||||
transform.origin = _rand_pos()
|
||||
PhysicsServer3D.body_set_state(body, PhysicsServer3D.BODY_STATE_TRANSFORM, transform)
|
||||
|
||||
|
||||
func _cast_raycasts() -> void:
|
||||
var space_state := PhysicsServer3D.space_get_direct_state(space)
|
||||
for i in N_OF_RAYCASTS:
|
||||
var query := PhysicsRayQueryParameters3D.create(_rand_pos(), _rand_pos())
|
||||
space_state.intersect_ray(query)
|
||||
|
||||
|
||||
func _clear_scene() -> void:
|
||||
for i in shapes.size(): # shapes and bodies should have the same size
|
||||
PhysicsServer3D.free_rid(shapes[i])
|
||||
PhysicsServer3D.free_rid(bodies[i])
|
||||
PhysicsServer3D.free_rid(space)
|
||||
|
||||
|
||||
func _rand_pos() -> Vector3:
|
||||
return Vector3(randf_range(-SPREAD_H, SPREAD_H), 0.0, 0.0)
|
||||
|
||||
|
||||
func benchmark_10_000_raycast_3d() -> void:
|
||||
_setup_scene()
|
||||
_cast_raycasts()
|
||||
_clear_scene()
|
||||
73
benchmarks/physics/softbody_3d.gd
Normal file
73
benchmarks/physics/softbody_3d.gd
Normal file
@@ -0,0 +1,73 @@
|
||||
extends Benchmark
|
||||
|
||||
const SPREAD_H := 20.0
|
||||
const SPREAD_V := 80.0
|
||||
|
||||
|
||||
class TestScene:
|
||||
extends Node3D
|
||||
|
||||
var n_of_rigidbodies: int
|
||||
var visualize := true
|
||||
var shapes: Array[Shape3D] = [
|
||||
BoxShape3D.new(),
|
||||
CapsuleShape3D.new(),
|
||||
SphereShape3D.new(),
|
||||
]
|
||||
var meshes: Array[Mesh] = [
|
||||
BoxMesh.new(),
|
||||
CapsuleMesh.new(),
|
||||
SphereMesh.new(),
|
||||
]
|
||||
|
||||
func _init(_n_of_rigidbodies: int, _visualize: bool) -> void:
|
||||
n_of_rigidbodies = _n_of_rigidbodies
|
||||
visualize = _visualize
|
||||
|
||||
func _ready() -> void:
|
||||
var softbody := SoftBody3D.new()
|
||||
var plane_mesh := PlaneMesh.new()
|
||||
plane_mesh.size = Vector2(60, 60)
|
||||
plane_mesh.subdivide_depth = 21
|
||||
plane_mesh.subdivide_width = 21
|
||||
softbody.mesh = plane_mesh
|
||||
softbody.set_point_pinned(11, true)
|
||||
softbody.set_point_pinned(253, true)
|
||||
softbody.set_point_pinned(275, true)
|
||||
softbody.set_point_pinned(517, true)
|
||||
add_child(softbody)
|
||||
if visualize:
|
||||
var camera := Camera3D.new()
|
||||
camera.position = Vector3(0.0, 20.0, 20.0)
|
||||
camera.rotate_x(-0.8)
|
||||
add_child(camera)
|
||||
|
||||
for i in n_of_rigidbodies:
|
||||
var rigid := RigidBody3D.new()
|
||||
rigid.position = Vector3(
|
||||
randf_range(-SPREAD_H, SPREAD_H),
|
||||
randf_range(0.0, SPREAD_V),
|
||||
randf_range(-SPREAD_H, SPREAD_H)
|
||||
)
|
||||
add_random_shape(rigid)
|
||||
add_child(rigid)
|
||||
|
||||
func add_random_shape(parent: CollisionObject3D) -> void:
|
||||
var r := randi() % shapes.size()
|
||||
var collision_shape := CollisionShape3D.new()
|
||||
collision_shape.shape = shapes[r]
|
||||
if visualize:
|
||||
var mesh_instance := MeshInstance3D.new()
|
||||
mesh_instance.mesh = meshes[r]
|
||||
parent.add_child(mesh_instance)
|
||||
parent.add_child(collision_shape)
|
||||
|
||||
|
||||
func _init() -> void:
|
||||
benchmark_time = 10e6
|
||||
test_physics = true
|
||||
test_idle = true
|
||||
|
||||
|
||||
func benchmark_softbody_3d_500_rigidbodies() -> TestScene:
|
||||
return TestScene.new(500, true)
|
||||
66
benchmarks/physics/triangle_mesh.gd
Normal file
66
benchmarks/physics/triangle_mesh.gd
Normal file
@@ -0,0 +1,66 @@
|
||||
extends Benchmark
|
||||
|
||||
const SPREAD_H := 25.0
|
||||
const SPREAD_V := 10.0
|
||||
|
||||
|
||||
class TestScene:
|
||||
extends Node3D
|
||||
|
||||
var collision_scene := preload("res://supplemental/8ball.glb")
|
||||
var n_of_rigidbodies: int
|
||||
var visualize := true
|
||||
var shapes: Array[Shape3D] = [
|
||||
BoxShape3D.new(),
|
||||
CapsuleShape3D.new(),
|
||||
SphereShape3D.new(),
|
||||
]
|
||||
var meshes: Array[Mesh] = [
|
||||
BoxMesh.new(),
|
||||
CapsuleMesh.new(),
|
||||
SphereMesh.new(),
|
||||
]
|
||||
|
||||
func _init(_n_of_rigidbodies: int, _visualize: bool) -> void:
|
||||
n_of_rigidbodies = _n_of_rigidbodies
|
||||
visualize = _visualize
|
||||
|
||||
func _ready() -> void:
|
||||
var collision_node := collision_scene.instantiate() as Node3D
|
||||
collision_node.rotate_y(PI / 2.0)
|
||||
collision_node.scale = Vector3(7, 7, 7)
|
||||
add_child(collision_node)
|
||||
if visualize:
|
||||
var camera := Camera3D.new()
|
||||
camera.position = Vector3(0.0, 20.0, 20.0)
|
||||
camera.rotate_x(-0.8)
|
||||
add_child(camera)
|
||||
for i in n_of_rigidbodies:
|
||||
var rigid := RigidBody3D.new()
|
||||
rigid.position = Vector3(
|
||||
randf_range(-SPREAD_H, SPREAD_H),
|
||||
randf_range(0.0, SPREAD_V),
|
||||
randf_range(-SPREAD_H, SPREAD_H)
|
||||
)
|
||||
add_random_shape(rigid)
|
||||
add_child(rigid)
|
||||
|
||||
func add_random_shape(parent: CollisionObject3D) -> void:
|
||||
var r := randi() % shapes.size()
|
||||
var collision_shape := CollisionShape3D.new()
|
||||
collision_shape.shape = shapes[r]
|
||||
if visualize:
|
||||
var mesh_instance := MeshInstance3D.new()
|
||||
mesh_instance.mesh = meshes[r]
|
||||
parent.add_child(mesh_instance)
|
||||
parent.add_child(collision_shape)
|
||||
|
||||
|
||||
func _init() -> void:
|
||||
benchmark_time = 10e6
|
||||
test_physics = true
|
||||
test_idle = true
|
||||
|
||||
|
||||
func benchmark_triangle_mesh_3d_1000_rigidbodies() -> TestScene:
|
||||
return TestScene.new(1000, true)
|
||||
BIN
supplemental/8ball.glb
Normal file
BIN
supplemental/8ball.glb
Normal file
Binary file not shown.
39
supplemental/8ball.glb.import
Normal file
39
supplemental/8ball.glb.import
Normal file
@@ -0,0 +1,39 @@
|
||||
[remap]
|
||||
|
||||
importer="scene"
|
||||
importer_version=1
|
||||
type="PackedScene"
|
||||
uid="uid://6i35ubecst4p"
|
||||
path="res://.godot/imported/8ball.glb-f349e8267bede1518210679565847aa4.scn"
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://supplemental/8ball.glb"
|
||||
dest_files=["res://.godot/imported/8ball.glb-f349e8267bede1518210679565847aa4.scn"]
|
||||
|
||||
[params]
|
||||
|
||||
nodes/root_type=""
|
||||
nodes/root_name=""
|
||||
nodes/apply_root_scale=true
|
||||
nodes/root_scale=1.0
|
||||
nodes/import_as_skeleton_bones=false
|
||||
meshes/ensure_tangents=true
|
||||
meshes/generate_lods=true
|
||||
meshes/create_shadow_meshes=true
|
||||
meshes/light_baking=1
|
||||
meshes/lightmap_texel_size=0.2
|
||||
meshes/force_disable_compression=false
|
||||
skins/use_named_skins=true
|
||||
animation/import=true
|
||||
animation/fps=30
|
||||
animation/trimming=false
|
||||
animation/remove_immutable_tracks=true
|
||||
animation/import_rest_as_RESET=false
|
||||
import_script/path=""
|
||||
_subresources={}
|
||||
fbx/importer=0
|
||||
fbx/allow_geometry_helper_nodes=false
|
||||
fbx/embedded_image_handling=1
|
||||
gltf/naming_version=1
|
||||
gltf/embedded_image_handling=1
|
||||
16
supplemental/gridmap_scene.tscn
Normal file
16
supplemental/gridmap_scene.tscn
Normal file
File diff suppressed because one or more lines are too long
43
supplemental/primitive_mesh_library.tres
Normal file
43
supplemental/primitive_mesh_library.tres
Normal file
@@ -0,0 +1,43 @@
|
||||
[gd_resource type="MeshLibrary" load_steps=9 format=3 uid="uid://x303bfmllwmk"]
|
||||
|
||||
[sub_resource type="BoxMesh" id="BoxMesh_mqd7q"]
|
||||
|
||||
[sub_resource type="BoxShape3D" id="BoxShape3D_0i8f0"]
|
||||
|
||||
[sub_resource type="SphereMesh" id="SphereMesh_1yxu2"]
|
||||
|
||||
[sub_resource type="SphereShape3D" id="SphereShape3D_atl5i"]
|
||||
|
||||
[sub_resource type="CylinderMesh" id="CylinderMesh_ox1xu"]
|
||||
|
||||
[sub_resource type="CylinderShape3D" id="CylinderShape3D_v4aqj"]
|
||||
|
||||
[sub_resource type="CapsuleMesh" id="CapsuleMesh_4mk8y"]
|
||||
|
||||
[sub_resource type="CapsuleShape3D" id="CapsuleShape3D_s7i7c"]
|
||||
|
||||
[resource]
|
||||
item/0/name = "Box"
|
||||
item/0/mesh = SubResource("BoxMesh_mqd7q")
|
||||
item/0/mesh_transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0)
|
||||
item/0/shapes = [SubResource("BoxShape3D_0i8f0"), Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0)]
|
||||
item/0/navigation_mesh_transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0)
|
||||
item/0/navigation_layers = 1
|
||||
item/1/name = "Sphere"
|
||||
item/1/mesh = SubResource("SphereMesh_1yxu2")
|
||||
item/1/mesh_transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0)
|
||||
item/1/shapes = [SubResource("SphereShape3D_atl5i"), Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0)]
|
||||
item/1/navigation_mesh_transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0)
|
||||
item/1/navigation_layers = 1
|
||||
item/2/name = "Cylinder"
|
||||
item/2/mesh = SubResource("CylinderMesh_ox1xu")
|
||||
item/2/mesh_transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0)
|
||||
item/2/shapes = [SubResource("CylinderShape3D_v4aqj"), Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0)]
|
||||
item/2/navigation_mesh_transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0)
|
||||
item/2/navigation_layers = 1
|
||||
item/3/name = "Capsule"
|
||||
item/3/mesh = SubResource("CapsuleMesh_4mk8y")
|
||||
item/3/mesh_transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0)
|
||||
item/3/shapes = [SubResource("CapsuleShape3D_s7i7c"), Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0)]
|
||||
item/3/navigation_mesh_transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0)
|
||||
item/3/navigation_layers = 1
|
||||
Reference in New Issue
Block a user