ani fixed
This commit is contained in:
@@ -0,0 +1,152 @@
|
||||
extends SceneTree
|
||||
|
||||
## Visual regression capture for the local Titanfall motion lab rigs.
|
||||
##
|
||||
## godot --path . --windowed --resolution 800x800 \
|
||||
## --script res://debug/titanfall_motion_capture.gd -- <output-dir> [model.glb]
|
||||
|
||||
const DEFAULT_MODEL := \
|
||||
"res://assets/characters/local_reference/titanfall_motion/mannequin.glb"
|
||||
const SPEED := 13.0
|
||||
|
||||
var _out_dir := "tmp_titanfall_motion_capture"
|
||||
var _model_path := DEFAULT_MODEL
|
||||
var _model: SkinnedPlayerModel
|
||||
|
||||
|
||||
func _initialize() -> void:
|
||||
var args := OS.get_cmdline_user_args()
|
||||
if not args.is_empty():
|
||||
_out_dir = args[0]
|
||||
if args.size() > 1:
|
||||
_model_path = args[1]
|
||||
if not _out_dir.is_absolute_path():
|
||||
_out_dir = ProjectSettings.globalize_path(_out_dir)
|
||||
DirAccess.make_dir_recursive_absolute(_out_dir)
|
||||
call_deferred("_run")
|
||||
|
||||
|
||||
func _run() -> void:
|
||||
var scene := Node3D.new()
|
||||
root.add_child(scene)
|
||||
current_scene = scene
|
||||
var environment_node := WorldEnvironment.new()
|
||||
var environment := Environment.new()
|
||||
environment.background_mode = Environment.BG_COLOR
|
||||
environment.background_color = Color(0.08, 0.09, 0.12)
|
||||
environment.ambient_light_source = Environment.AMBIENT_SOURCE_COLOR
|
||||
environment.ambient_light_color = Color(0.78, 0.82, 0.95)
|
||||
environment.ambient_light_energy = 1.3
|
||||
environment.tonemap_mode = Environment.TONE_MAPPER_FILMIC
|
||||
environment_node.environment = environment
|
||||
scene.add_child(environment_node)
|
||||
var sun := DirectionalLight3D.new()
|
||||
sun.rotation_degrees = Vector3(-35.0, 35.0, 0.0)
|
||||
sun.light_energy = 2.2
|
||||
scene.add_child(sun)
|
||||
var camera := Camera3D.new()
|
||||
scene.add_child(camera)
|
||||
camera.current = true
|
||||
camera.global_position = Vector3(0.0, 1.15, 3.0)
|
||||
camera.look_at(Vector3(0.0, 0.9, 0.0), Vector3.UP)
|
||||
|
||||
var body := CharacterBody3D.new()
|
||||
scene.add_child(body)
|
||||
_model = SkinnedPlayerModel.new()
|
||||
_model.model_path = _model_path
|
||||
_model.first_person_mode = false
|
||||
_model.shadows_only = false
|
||||
body.add_child(_model)
|
||||
for _frame in 60:
|
||||
await process_frame
|
||||
if not _model.loaded:
|
||||
printerr("titanfall_motion_capture: model failed to load")
|
||||
quit(1)
|
||||
return
|
||||
|
||||
await _drive("ground", 0.0, 90)
|
||||
_snap("idle")
|
||||
await _wall(-1.0, Vector3.RIGHT)
|
||||
_snap("wall_left")
|
||||
await _drive("ground", 0.0, 90)
|
||||
await _wall(1.0, Vector3.LEFT)
|
||||
_snap("wall_right")
|
||||
|
||||
_model.set_wall_side(0.0)
|
||||
_model.set_wall_surface(Vector3.ZERO, Vector3.ZERO)
|
||||
_model.set_wall_glide_motion(Vector3.ZERO)
|
||||
await _drive("ground", 0.0, 1)
|
||||
_snap("post_right_01")
|
||||
await _drive("ground", 0.0, 19)
|
||||
_snap("post_right_20")
|
||||
await _drive("ground", 0.0, 70)
|
||||
_snap("post_right_idle")
|
||||
quit()
|
||||
|
||||
|
||||
func _wall(side: float, normal: Vector3) -> void:
|
||||
_model.set_wall_side(side)
|
||||
_model.set_wall_surface(normal, Vector3.ZERO)
|
||||
_model.set_wall_glide_motion(Vector3(0.0, 0.0, -SPEED))
|
||||
await _drive("wall_run", SPEED, 90)
|
||||
|
||||
|
||||
func _drive(state: String, speed: float, frames: int) -> void:
|
||||
for _frame in frames:
|
||||
_model.update_state(state, speed, false)
|
||||
await process_frame
|
||||
|
||||
|
||||
func _snap(name: String) -> void:
|
||||
var image := root.get_viewport().get_texture().get_image()
|
||||
var path := _out_dir.path_join(name + ".png")
|
||||
image.save_png(path)
|
||||
print("titanfall_motion_capture: saved %s metrics=%s" % [
|
||||
path, _pose_metrics()])
|
||||
|
||||
|
||||
func _pose_metrics() -> Dictionary:
|
||||
var roles: Dictionary = _model._rig_info.get("roles", {})
|
||||
var chain := [_model._role_bone("hips", ["hips", "Hips", "pelvis"])]
|
||||
var neck_name := String(roles.get("neck", ""))
|
||||
var head_name := String(roles.get("head", ""))
|
||||
for role in roles.get("spine", []):
|
||||
var name := String(role)
|
||||
if name == neck_name or name == head_name:
|
||||
continue
|
||||
chain.append(RigRoles.find_imported_bone(_model.skeleton, name))
|
||||
var max_torso_joint_angle := 0.0
|
||||
var max_torso_joint := ""
|
||||
for index in range(1, chain.size()):
|
||||
if chain[index - 1] < 0 or chain[index] < 0:
|
||||
continue
|
||||
var parent_pose := _model.skeleton.get_bone_global_pose(chain[index - 1])
|
||||
var child_pose := _model.skeleton.get_bone_global_pose(chain[index])
|
||||
var parent_rest := _model.skeleton.get_bone_global_rest(chain[index - 1])
|
||||
var child_rest := _model.skeleton.get_bone_global_rest(chain[index])
|
||||
var posed_relative := parent_pose.basis.inverse() * child_pose.basis
|
||||
var rest_relative := parent_rest.basis.inverse() * child_rest.basis
|
||||
var joint_angle := posed_relative.get_rotation_quaternion().angle_to(
|
||||
rest_relative.get_rotation_quaternion())
|
||||
if joint_angle > max_torso_joint_angle:
|
||||
max_torso_joint_angle = joint_angle
|
||||
max_torso_joint = _model.skeleton.get_bone_name(chain[index])
|
||||
var max_leg_horizontal_ratio := 0.0
|
||||
for side in ["L", "R"]:
|
||||
var thigh := _model._role_bone("thigh." + side,
|
||||
["thigh." + side, "Left thigh" if side == "L" else "Right thigh"])
|
||||
var shin := _model._role_bone("shin." + side,
|
||||
["shin." + side, "Left shin" if side == "L" else "Right shin"])
|
||||
if thigh < 0 or shin < 0:
|
||||
continue
|
||||
var segment := _model.skeleton.get_bone_global_pose(shin).origin \
|
||||
- _model.skeleton.get_bone_global_pose(thigh).origin
|
||||
segment = _model.skeleton.global_transform.basis * segment
|
||||
if segment.length() > 0.0001:
|
||||
max_leg_horizontal_ratio = maxf(max_leg_horizontal_ratio,
|
||||
Vector2(segment.x, segment.z).length() / segment.length())
|
||||
return {
|
||||
"torso_joint_angle": max_torso_joint_angle,
|
||||
"torso_joint": max_torso_joint,
|
||||
"leg_horizontal_ratio": max_leg_horizontal_ratio,
|
||||
}
|
||||
Reference in New Issue
Block a user