Quaternion에서 회전 행렬
Result
FORCEINLINE explicit Quaternion(const Rotator & InRotator){
float cy = cosf(Math::Deg2Rad(InRotator.Yaw * 0.5f)), sy = sinf(Math::Deg2Rad(InRotator.Yaw * 0.5f));
float cp = cosf(Math::Deg2Rad(InRotator.Pitch * 0.5f)), sp = sinf(Math::Deg2Rad(InRotator.Pitch * 0.5f));
float cr = cosf(Math::Deg2Rad(InRotator.Roll * 0.5f)), sr = sinf(Math::Deg2Rad(InRotator.Roll * 0.5f));
W = cy * cp * cr + sy * sp * sr;
X = cy * sp * cr + sy * cp * sr;
Y = sy * cp * cr - cy * sp * sr;
Z = cy * cp * sr - sy * sp * cr;
}
오일러 각 정보를 받아 Quaternion으로 변환
Result
FORCEINLINE Matrix4x4 Quaternion::RotationMatrix() const {
Matrix4x4 result; float xs = X * X, ys = Y * Y, zs = Z * Z;
float wx = W * X, wy = W * Y, wz = W * Z;
float xy = X * Y, xz = X * Z;
float yz = Y * Z;
result.Cols[0] = Vector4(1.f - 2.f * (ys + zs), 2.f * (xy + wz), 2.f * (xz - wy), 0.f);
result.Cols[1] = Vector4(2.f * (xy - wz), 1.f - 2.f * (xs + zs), 2.f * (wx + yz), 0.f);
result.Cols[2] = Vector4(2.f * (wy + xz), 2.f * (yz - wx), 1.f - 2.f * (xs + ys), 0.f);
result.Cols[3] = Vector4(0.f, 0.f, 0.f, 1.f); return result; }
Quaterion에서 오일러 각 정보로 변환
Roll
Pitch
Yaw
Result
FORCEINLINE Rotator Quaternion::ToRotator() const {
Rotator Rot;
float pitchHalfRad = W * X - Y * Z;
float yawY = 2.f * (W * Y + X * Z);
float yawX = 1.f - 2.f * (X * X + Y * Y);
Rot.Yaw = Math::Rad2Deg(atan2f(yawY, yawX));
float singularity = 0.499999f;
if (pitchHalfRad > singularity) {
Rot.Pitch = 90.f;
Rot.Roll = Rot.Yaw - Math::Rad2Deg(2.f * atan2f(Y, W));
}
else if (pitchHalfRad < -singularity) {
Rot.Pitch = -90.f;
Rot.Roll = -Rot.Yaw + Math::Rad2Deg(2.f * atan2f(Y, W));
}
else
{
Rot.Pitch = Math::Rad2Deg(asinf(2.f * pitchHalfRad));
Rot.Roll = Math::Rad2Deg(atan2f(2.f * (W * Z + X * Y), 1.f - 2.f * (Z * Z + X * X))); }
return Rot; }
Quaternion의 Slerp를 구현을 위한 공식
Lerp
Slerp
Result
Quaternion Quaternion::Lerp(const Quaternion& q1, const Quaternion& q2, const float& t) {
Quaternion result;
result = q1 * (1.f - t) + q2 * t;
result.Normalize(); return result;
}
Quaternion Quaternion::Slerp(const Quaternion& q1, const Quaternion& q2, const float& t) {
Quaternion result;
float cosTheta = Math::Clamp(q1.W * q2.W + q1.X * q2.X + q1.Y * q2.Y + q1.Z * q2.Z, -1.f, 1.f);
float s1, s2;
if (-0.99999f < cosTheta && cosTheta < 0.99999f) {
float theta = acosf(cosTheta);
float invSin = 1.f / sinf(theta);
s1 = sinf((1.f - t) * theta) * invSin;
s2 = sinf(t * theta) * invSin; }
else {
return Lerp(q1, q2, t);
}
q = q1 * s1 + q2 * s2;
return result;
}
'Programming > Soft Renderer_2020' 카테고리의 다른 글
GameEngine 3D : 사원수 대수, 사원수 회전, 사원수의 활용 (1) | 2020.07.16 |
---|---|
GameEngine 3D : Frustum Culling, Euler angle, Rodrigues Rotation (0) | 2020.07.02 |
GameEngine 3D : Backface Culling, Perspective Projection (0) | 2020.06.25 |
GameEngine 3D : Space, Rotation, Camera (0) | 2020.06.17 |
지수 함수, 맥클로린 급수 (0) | 2020.06.12 |