-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathTransformProbe.cs
More file actions
133 lines (100 loc) · 4.94 KB
/
Copy pathTransformProbe.cs
File metadata and controls
133 lines (100 loc) · 4.94 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
namespace CreatorEngine.Scripts;
/// <summary>
/// Transform 회전·스케일·방향축 바인딩 검증.
///
/// 왕복(쓴 값 == 읽은 값)과 합성(45°+45° == 90°)을 스크립트가 스스로 판정한다.
/// 좌표계 규약에 의존하는 값(Forward 방향 등)은 단정하지 않고 로그로만 남긴다 —
/// 엔진이 왼손 좌표계인지 여기서 다시 못 박으면 규약이 바뀔 때 거짓 실패가 난다.
/// </summary>
public sealed partial class TransformProbe : Behaviour
{
private const float Epsilon = 1e-3f;
private int _passed;
private int _failed;
public override void OnInitialized()
{
Log($"[TransformProbe] 시작 — pos={Transform.LocalPosition} rot={Transform.LocalRotation} scale={Transform.LocalScale}");
CheckScale();
CheckRotation();
CheckCompose();
CheckTranslate();
CheckWorld();
ReportAxes();
if (_failed == 0) Log($"[TransformProbe] 전체 통과 ({_passed}건)");
else LogError($"[TransformProbe] {_failed}건 실패 / {_passed}건 통과");
}
private void CheckScale()
{
Transform.LocalScale = new Float3(2f, 3f, 4f);
Assert("LocalScale 왕복", Near(Transform.LocalScale, new Float3(2f, 3f, 4f)), $"{Transform.LocalScale}");
Transform.LocalScale = Float3.One;
}
private void CheckRotation()
{
Quaternion yaw90 = Quaternion.CreateFromAxisAngle(Float3.Up, MathF.PI * 0.5f);
Transform.LocalRotation = yaw90;
Assert("LocalRotation 왕복", Near(Transform.LocalRotation, yaw90), $"{Transform.LocalRotation} vs {yaw90}");
Transform.LocalRotation = Quaternion.Identity;
}
private void CheckCompose()
{
// 45°를 두 번 더하면 90°가 되어야 한다 — AddLocalRotation의 합성 순서 검증.
Quaternion yaw45 = Quaternion.CreateFromAxisAngle(Float3.Up, MathF.PI * 0.25f);
Quaternion yaw90 = Quaternion.CreateFromAxisAngle(Float3.Up, MathF.PI * 0.5f);
Transform.LocalRotation = Quaternion.Identity;
Transform.Rotate(yaw45);
Transform.Rotate(yaw45);
Assert("Rotate 합성 45+45=90", Near(Transform.LocalRotation, yaw90), $"{Transform.LocalRotation} vs {yaw90}");
Transform.LocalRotation = Quaternion.Identity;
}
private void CheckTranslate()
{
Float3 start = Transform.LocalPosition;
Transform.Translate(new Float3(1f, 2f, 3f));
Assert("Translate 누적", Near(Transform.LocalPosition, start + new Float3(1f, 2f, 3f)),
$"{start} -> {Transform.LocalPosition}");
Transform.LocalPosition = start;
}
private void CheckWorld()
{
// 부모가 없으면 월드 = 로컬이다. 부모가 있으면 환산을 거치므로 값이 달라질 수 있어,
// 여기서는 "쓴 뒤 읽으면 같은 월드 좌표"만 본다.
Float3 start = Transform.WorldPosition;
Float3 target = start + new Float3(5f, 0f, 0f);
Transform.WorldPosition = target;
Assert("WorldPosition 왕복", Near(Transform.WorldPosition, target), $"{Transform.WorldPosition} vs {target}");
Transform.WorldPosition = start;
Quaternion startRotation = Transform.WorldRotation;
Quaternion yaw90 = Quaternion.CreateFromAxisAngle(Float3.Up, MathF.PI * 0.5f);
Transform.WorldRotation = yaw90;
Assert("WorldRotation 왕복", Near(Transform.WorldRotation, yaw90), $"{Transform.WorldRotation} vs {yaw90}");
Transform.WorldRotation = startRotation;
Float3 startScale = Transform.WorldScale;
Float3 targetScale = startScale * 2f;
Transform.WorldScale = targetScale;
Assert("WorldScale 왕복", Near(Transform.WorldScale, targetScale), $"{Transform.WorldScale} vs {targetScale}");
Transform.WorldScale = startScale;
}
/// <summary>좌표계 규약 확인용 — 단정하지 않고 값만 남긴다.</summary>
private void ReportAxes()
{
Transform.LocalRotation = Quaternion.Identity;
Log($"[TransformProbe] 무회전 축 — forward={Transform.Forward} right={Transform.Right} up={Transform.Up}");
Transform.LocalRotation = Quaternion.CreateFromAxisAngle(Float3.Up, MathF.PI * 0.5f);
Log($"[TransformProbe] Yaw 90° 축 — forward={Transform.Forward} right={Transform.Right} up={Transform.Up}");
Transform.LocalRotation = Quaternion.Identity;
}
private void Assert(string name, bool ok, string detail)
{
if (ok) { ++_passed; return; }
++_failed;
LogError($"[TransformProbe] 실패: {name} — {detail}");
}
private static bool Near(Float3 a, Float3 b) => (a - b).Length < Epsilon;
/// <summary>q와 -q는 같은 회전이므로 부호를 맞춰 비교한다.</summary>
private static bool Near(Quaternion a, Quaternion b)
{
float dot = a.X * b.X + a.Y * b.Y + a.Z * b.Z + a.W * b.W;
return MathF.Abs(MathF.Abs(dot) - 1f) < Epsilon;
}
}