111 lines
3.8 KiB
GDScript
111 lines
3.8 KiB
GDScript
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
|