diff --git a/src/main/resources/assets/flywheel/flywheel/instance/cull/oriented.glsl b/src/main/resources/assets/flywheel/flywheel/instance/cull/oriented.glsl index d38a3b58c..804fd9597 100644 --- a/src/main/resources/assets/flywheel/flywheel/instance/cull/oriented.glsl +++ b/src/main/resources/assets/flywheel/flywheel/instance/cull/oriented.glsl @@ -5,5 +5,5 @@ void flw_transformBoundingSphere(in FlwInstance i, inout vec3 center, inout floa vec3 pivot = i.pivot; vec3 pos = i.position; - center = rotateVertexByQuat(center - pivot, rotation) + pivot + pos; + center = rotateByQuaternion(center - pivot, rotation) + pivot + pos; } diff --git a/src/main/resources/assets/flywheel/flywheel/instance/oriented.vert b/src/main/resources/assets/flywheel/flywheel/instance/oriented.vert index dc96d1d7f..9b3e39906 100644 --- a/src/main/resources/assets/flywheel/flywheel/instance/oriented.vert +++ b/src/main/resources/assets/flywheel/flywheel/instance/oriented.vert @@ -1,8 +1,8 @@ #include "flywheel:util/quaternion.glsl" void flw_instanceVertex(in FlwInstance i) { - flw_vertexPos = vec4(rotateVertexByQuat(flw_vertexPos.xyz - i.pivot, i.rotation) + i.pivot + i.position, 1.0); - flw_vertexNormal = rotateVertexByQuat(flw_vertexNormal, i.rotation); + flw_vertexPos = vec4(rotateByQuaternion(flw_vertexPos.xyz - i.pivot, i.rotation) + i.pivot + i.position, 1.0); + flw_vertexNormal = rotateByQuaternion(flw_vertexNormal, i.rotation); flw_vertexColor = i.color; flw_vertexLight = i.light / 15.0; } diff --git a/src/main/resources/assets/flywheel/flywheel/util/matrix.glsl b/src/main/resources/assets/flywheel/flywheel/util/matrix.glsl index af8fb301b..0b5e8eabd 100644 --- a/src/main/resources/assets/flywheel/flywheel/util/matrix.glsl +++ b/src/main/resources/assets/flywheel/flywheel/util/matrix.glsl @@ -1,20 +1,35 @@ -mat4 rotate(vec3 axis, float angle) { +mat3 rotation(vec3 axis, float angle) { float s = sin(angle); float c = cos(angle); float oc = 1. - c; vec3 sa = axis * s; - mat4 mr = mat4(1.); - mr[0].xyz = oc * axis.xxz * axis.xyx + vec3(c, sa.z, -sa.y); - mr[1].xyz = oc * axis.xyy * axis.yyz + vec3(-sa.z, c, sa.x); - mr[2].xyz = oc * axis.zyz * axis.xzz + vec3(sa.y, -sa.x, c); - - return mr; + return mat3( + oc * axis.xxz * axis.xyx + vec3(c, sa.z, -sa.y), + oc * axis.xyy * axis.yyz + vec3(-sa.z, c, sa.x), + oc * axis.zyz * axis.xzz + vec3(sa.y, -sa.x, c) + ); } -mat4 rotation(vec3 rot) { - return rotate(vec3(0., 1., 0.), rot.y) * rotate(vec3(0., 0., 1.), rot.z) * rotate(vec3(1., 0., 0.), rot.x); +mat3 rotationDegrees(vec3 axis, float angle) { + return rotation(axis, radians(angle)); +} + +/* + * Create a rotation matrix that rotates the vector `from` to `to`. + * https://iquilezles.org/articles/noacos/ + */ +mat3 rotationAlign(in vec3 from, in vec3 to) { + vec3 v = cross(from, to); + float c = dot(from, to); + float k = 1. / (1. + c); + + return mat3( + k * v * v.xxx + vec3(c, -v.z, v.y), + k * v * v.yyy + vec3(v.z, c, -v.x), + k * v * v.zzz + vec3(-v.y, v.x, c) + ); } mat3 modelToNormal(mat4 mat) { diff --git a/src/main/resources/assets/flywheel/flywheel/util/quaternion.glsl b/src/main/resources/assets/flywheel/flywheel/util/quaternion.glsl index 8db184956..51591518d 100644 --- a/src/main/resources/assets/flywheel/flywheel/util/quaternion.glsl +++ b/src/main/resources/assets/flywheel/flywheel/util/quaternion.glsl @@ -1,12 +1,13 @@ -#define PI_OVER_2 1.5707963268 - -vec4 quat(vec3 axis, float angle) { - float halfAngle = angle * PI_OVER_2 / 180.0; - vec2 cs = sin(vec2(PI_OVER_2 - halfAngle, halfAngle)); // compute sin and cos in one instruction - return vec4(axis.xyz * cs.y, cs.x); +vec4 quaternion(vec3 axis, float angle) { + float halfAngle = angle * 0.5; + return vec4(axis.xyz * sin(halfAngle), cos(halfAngle)); } -vec4 quatMult(vec4 q1, vec4 q2) { +vec4 quaternionDegrees(vec3 axis, float angle) { + return quaternion(axis, radians(angle)); +} + +vec4 multiplyQuaternions(vec4 q1, vec4 q2) { // disgustingly vectorized quaternion multiplication vec4 a = q1.w * q2.xyzw; vec4 b = q1.x * q2.wzxy * vec4(1., -1., 1., -1.); @@ -16,11 +17,15 @@ vec4 quatMult(vec4 q1, vec4 q2) { return a + b + c + d; } -vec3 rotateVertexByQuat(vec3 v, vec4 q) { +vec3 rotateByQuaternion(vec3 v, vec4 q) { vec3 i = q.xyz; return v + 2.0 * cross(i, cross(i, v) + q.w * v); } -vec3 rotateAbout(vec3 v, vec3 axis, float angle) { - return rotateVertexByQuat(v, quat(axis, angle)); +vec3 rotateAxisAngle(vec3 v, vec3 axis, float angle) { + return rotateByQuaternion(v, quaternion(axis, angle)); +} + +vec3 rotateAxisAngleDegrees(vec3 v, vec3 axis, float angle) { + return rotateByQuaternion(v, quaternionDegrees(axis, angle)); }