refactor(M03): extract M2 placement transform resolver
This commit is contained in:
@@ -0,0 +1,110 @@
|
||||
class_name M2PlacementTransformResolver
|
||||
extends RefCounted
|
||||
|
||||
## Stateless ADT M2 placement orientation and origin-correction rules.
|
||||
|
||||
const CLIFFROCK_WORLD_YAW_OFFSET := PI
|
||||
const WATERFALL_WORLD_YAW_OFFSET := PI * 0.5
|
||||
|
||||
|
||||
## Resolves the unscaled Godot-space basis for one ADT M2 placement.
|
||||
func resolve_basis(rotation_radians: Vector3, relative_m2_path: String = "") -> Basis:
|
||||
if not _is_waterfall_path(relative_m2_path):
|
||||
return _resolve_regular_basis(rotation_radians, relative_m2_path)
|
||||
|
||||
var placement_basis := Basis.from_euler(rotation_radians)
|
||||
return (
|
||||
Basis(Vector3.UP, WATERFALL_WORLD_YAW_OFFSET)
|
||||
* placement_basis
|
||||
* Basis(
|
||||
_resolve_waterfall_local_fall_axis(relative_m2_path),
|
||||
_resolve_waterfall_sheet_twist(relative_m2_path)
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
## Resolves local origin compensation for a twisted waterfall sheet. Regular
|
||||
## models and waterfall models without a measured anchor return zero.
|
||||
func resolve_origin_offset(
|
||||
rotation_radians: Vector3,
|
||||
relative_m2_path: String,
|
||||
scale_value: float
|
||||
) -> Vector3:
|
||||
if not _is_waterfall_path(relative_m2_path):
|
||||
return Vector3.ZERO
|
||||
var twist_radians := _resolve_waterfall_sheet_twist(relative_m2_path)
|
||||
if is_zero_approx(twist_radians):
|
||||
return Vector3.ZERO
|
||||
var anchor_local_position := _resolve_waterfall_sheet_twist_anchor(relative_m2_path)
|
||||
if anchor_local_position == Vector3.ZERO:
|
||||
return Vector3.ZERO
|
||||
var placement_basis := (
|
||||
Basis(Vector3.UP, WATERFALL_WORLD_YAW_OFFSET)
|
||||
* Basis.from_euler(rotation_radians)
|
||||
)
|
||||
var twisted_basis := placement_basis * Basis(
|
||||
_resolve_waterfall_local_fall_axis(relative_m2_path),
|
||||
twist_radians
|
||||
)
|
||||
return (
|
||||
placement_basis * anchor_local_position
|
||||
- twisted_basis * anchor_local_position
|
||||
) * maxf(scale_value, 0.0001)
|
||||
|
||||
|
||||
func _resolve_regular_basis(rotation_radians: Vector3, relative_m2_path: String) -> Basis:
|
||||
if not _is_elwynn_cliffrock_path(relative_m2_path):
|
||||
return Basis.from_euler(rotation_radians)
|
||||
return (
|
||||
Basis(Vector3.UP, rotation_radians.y + CLIFFROCK_WORLD_YAW_OFFSET)
|
||||
* Basis(Vector3.BACK, rotation_radians.x)
|
||||
* Basis(Vector3.RIGHT, -rotation_radians.z)
|
||||
)
|
||||
|
||||
|
||||
func _is_waterfall_path(relative_m2_path: String) -> bool:
|
||||
var model_name := _normalized_model_name(relative_m2_path)
|
||||
return model_name == "newwaterfall" or model_name == "elwynntallwaterfall01"
|
||||
|
||||
|
||||
func _is_elwynn_cliffrock_path(relative_m2_path: String) -> bool:
|
||||
var model_name := _normalized_model_name(relative_m2_path)
|
||||
return model_name == "elwynncliffrock01" or model_name == "elwynncliffrock02"
|
||||
|
||||
|
||||
func _normalized_model_name(relative_m2_path: String) -> String:
|
||||
return relative_m2_path.replace("\\", "/").to_lower().get_file().get_basename()
|
||||
|
||||
|
||||
func _resolve_waterfall_local_fall_axis(relative_m2_path: String) -> Vector3:
|
||||
var normalized_path := relative_m2_path.replace("\\", "/").to_lower()
|
||||
if normalized_path.ends_with("newwaterfall.m2") or normalized_path.ends_with("newwaterfall.mdx"):
|
||||
return Vector3(-0.138742, 0.990329, 0.0).normalized()
|
||||
if (
|
||||
normalized_path.ends_with("elwynntallwaterfall01.m2")
|
||||
or normalized_path.ends_with("elwynntallwaterfall01.mdx")
|
||||
):
|
||||
return Vector3(-0.068962, 0.997619, 0.0).normalized()
|
||||
return Vector3.UP
|
||||
|
||||
|
||||
func _resolve_waterfall_sheet_twist(relative_m2_path: String) -> float:
|
||||
var normalized_path := relative_m2_path.replace("\\", "/").to_lower()
|
||||
if normalized_path.ends_with("newwaterfall.m2") or normalized_path.ends_with("newwaterfall.mdx"):
|
||||
return PI * 0.5
|
||||
if (
|
||||
normalized_path.ends_with("elwynntallwaterfall01.m2")
|
||||
or normalized_path.ends_with("elwynntallwaterfall01.mdx")
|
||||
):
|
||||
return -PI * 0.5
|
||||
return 0.0
|
||||
|
||||
|
||||
func _resolve_waterfall_sheet_twist_anchor(relative_m2_path: String) -> Vector3:
|
||||
var normalized_path := relative_m2_path.replace("\\", "/").to_lower()
|
||||
if (
|
||||
normalized_path.ends_with("elwynntallwaterfall01.m2")
|
||||
or normalized_path.ends_with("elwynntallwaterfall01.mdx")
|
||||
):
|
||||
return Vector3(-2.667799, 89.62273, 0.00129)
|
||||
return Vector3.ZERO
|
||||
Reference in New Issue
Block a user