144 lines
4.0 KiB
HLSL
144 lines
4.0 KiB
HLSL
#ifndef __matrix_hlsl_
|
|
#define __matrix_hlsl_
|
|
|
|
// Sets the rotation of a translation matrix "m" by the quaternion value "q".
|
|
float4x4 SetMatrixRotationWithQuaternion(float4x4 m, float4 q)
|
|
{
|
|
// See e.g. http://www.geometrictools.com/Documentation/LinearAlgebraicQuaternions.pdf .
|
|
|
|
float x = q.x;
|
|
float y = q.y;
|
|
float z = q.z;
|
|
float w = q.w;
|
|
m[0][0] = 1 - 2 * (y * y + z * z);
|
|
m[0][1] = 2 * (x * y - z * w);
|
|
m[0][2] = 2 * (x * z + y * w);
|
|
m[1][0] = 2 * (x * y + z * w);
|
|
m[1][1] = 1 - 2 * (x * x + z * z);
|
|
m[1][2] = 2 * (y * z - x * w);
|
|
m[2][0] = 2 * (x * z - y * w);
|
|
m[2][1] = 2 * (y * z + x * w);
|
|
m[2][2] = 1 - 2 * (x * x + y * y);
|
|
|
|
return m;
|
|
}
|
|
|
|
/// https://www.3dgep.com/3d-math-primer-for-game-programmers-matrices/
|
|
/// n : axis
|
|
/// a : angle in radians
|
|
/// A 3D rotation about an arbitrary axis n by an angle of a
|
|
float4x4 MatrixRotate(float3 n, float a)
|
|
{
|
|
float cosa = cos(a);
|
|
float sina = sin(a);
|
|
|
|
return float4x4(
|
|
n.x * n.x * (1 - cosa) + cosa,
|
|
n.x * n.y * (1 - cosa) - n.z * sina,
|
|
n.x * n.z * (1 - cosa) + n.y * sina,
|
|
0,
|
|
n.x * n.y * (1 - cosa) + n.z * sina,
|
|
n.y * n.y * (1 - cosa) + cosa,
|
|
n.y * n.z * (1 - cosa) - n.x * sina,
|
|
0,
|
|
n.x * n.z * (1 - cosa) - n.y * sina,
|
|
n.y * n.z * (1 - cosa) + n.x * sina,
|
|
n.z * n.z * (1 - cosa) + cosa,
|
|
0,
|
|
0, 0, 0, 1
|
|
);
|
|
}
|
|
|
|
// m: matrix to scale
|
|
// angle: angles for x,y,z
|
|
// returns rotation matrix
|
|
float4x4 MatrixRotateXYZ(float3 angle)
|
|
{
|
|
// rotate at x axis
|
|
float4x4 mX = MatrixRotate(float3(1, 0, 0), radians(angle.x));
|
|
// rotate at y axis
|
|
float4x4 mY = MatrixRotate(float3(0, 1, 0), radians(angle.y));
|
|
// rotate at z axis
|
|
float4x4 mYmX = mul(mY, mX);
|
|
float4x4 mZ = MatrixRotate(float3(mYmX[0][2], mYmX[1][2], mYmX[2][2]), radians(angle.z));
|
|
// return result
|
|
return mul(mul(mZ, mY), mX);
|
|
}
|
|
|
|
|
|
// Scales the matrix "m" by "scale" scales for x,y,z.
|
|
float4x4 SetScaleOfMatrix(float4x4 m, float3 scale)
|
|
{
|
|
m._m00_m10_m20_m30 = m._m00_m10_m20_m30 * scale.x / length(m._m00_m10_m20_m30);
|
|
m._m01_m11_m21_m31 = m._m01_m11_m21_m31 * scale.y / length(m._m01_m11_m21_m31);
|
|
m._m02_m12_m22_m32 = m._m02_m12_m22_m32 * scale.z / length(m._m02_m12_m22_m32);
|
|
|
|
return m;
|
|
}
|
|
|
|
// Scales the matrix "m" by "scale" scales for x,y,z.
|
|
float4x4 SetScaleOfMatrixPercentage(float4x4 m, float3 scale)
|
|
{
|
|
m._m00_m10_m20_m30 = m._m00_m10_m20_m30 * scale.x;
|
|
m._m01_m11_m21_m31 = m._m01_m11_m21_m31 * scale.y;
|
|
m._m02_m12_m22_m32 = m._m02_m12_m22_m32 * scale.z;
|
|
|
|
return m;
|
|
}
|
|
|
|
// Generates a Matrix4x4 from position, rotation and scale.
|
|
float4x4 TRS(in float3 position, in float4x4 rotationMatrix, in float3 scale)
|
|
{
|
|
// start with rotation matrix and set scale
|
|
float4x4 result = SetScaleOfMatrix(rotationMatrix, scale);
|
|
// set position
|
|
result._m03_m13_m23 = position;
|
|
// return result
|
|
return result;
|
|
}
|
|
|
|
// Returns a quaternion that represents a rotation of "angle" degrees along "axis".
|
|
float4 AngleAxis(float3 axis, float angle)
|
|
{
|
|
// Calculate the sin( theta / 2) once for optimization
|
|
double factor = sin(angle / 2.0);
|
|
|
|
// Calculate the x, y and z of the quaternion
|
|
double x = axis.x * factor;
|
|
double y = axis.y * factor;
|
|
double z = axis.z * factor;
|
|
|
|
// Calcualte the w value by cos( theta / 2 )
|
|
double w = cos(angle / 2.0);
|
|
|
|
return normalize(float4(x, y, z, w));
|
|
}
|
|
|
|
// Quaternion Multiplication.
|
|
float4 QuatMul(float4 q1, float4 q)
|
|
{
|
|
float w_val = q1.w * q.w - q1.x * q.x - q1.y * q.y - q1.z * q.z;
|
|
float x_val = q1.w * q.x + q1.x * q.w + q1.y * q.z - q1.z * q.y;
|
|
float y_val = q1.w * q.y + q1.y * q.w + q1.z * q.x - q1.x * q.z;
|
|
float z_val = q1.w * q.z + q1.z * q.w + q1.x * q.y - q1.y * q.x;
|
|
|
|
q1.w = w_val;
|
|
q1.x = x_val;
|
|
q1.y = y_val;
|
|
q1.z = z_val;
|
|
|
|
return q1;
|
|
}
|
|
|
|
// Returns a quaternion that represents a rotation from "from" to "to" vectors.
|
|
float4 FromToRotation(float3 from, float3 to)
|
|
{
|
|
float4 q;
|
|
float3 a = cross(from, to);
|
|
q.xyz = a;
|
|
q.w = sqrt((length(to) * length(to))) + dot(from, to);
|
|
q = normalize(q);
|
|
|
|
return q;
|
|
}
|
|
#endif |