Skip to content

Commit acbd32c

Browse files
authored
Optimize GLSL/OSL rotate3d using Rodrigues' rotation formula (#2890)
While fixing some issues with the rotate3d for my blender importer, I noticed that we can replace the matrix44 construction for just rotating a vector with Rodrigues' formula: https://en.wikipedia.org/wiki/Rodrigues%27_rotation_formula This PR makes that change. Fidelity test passes with successful results so there was no degradation.
1 parent afc09dd commit acbd32c

2 files changed

Lines changed: 18 additions & 31 deletions

File tree

Lines changed: 9 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,13 @@
1-
mat4 mx_rotationMatrix(vec3 axis, float angle)
2-
{
3-
axis = normalize(axis);
4-
float s = mx_sin(angle);
5-
float c = mx_cos(angle);
6-
float oc = 1.0 - c;
7-
8-
return mat4(oc * axis.x * axis.x + c, oc * axis.x * axis.y - axis.z * s, oc * axis.z * axis.x + axis.y * s, 0.0,
9-
oc * axis.x * axis.y + axis.z * s, oc * axis.y * axis.y + c, oc * axis.y * axis.z - axis.x * s, 0.0,
10-
oc * axis.z * axis.x - axis.y * s, oc * axis.y * axis.z + axis.x * s, oc * axis.z * axis.z + c, 0.0,
11-
0.0, 0.0, 0.0, 1.0);
12-
}
13-
141
void mx_rotate_vector3(vec3 _in, float amount, vec3 axis, out vec3 result)
152
{
3+
// Based on https://en.wikipedia.org/wiki/Rodrigues%27_rotation_formula, where the
4+
// Wikipedia formula follows v' = M * v and MaterialX follows v' = v * M, thus the
5+
// order of parameters to cross are reversed.
6+
7+
axis = normalize(axis);
168
float rotationRadians = mx_radians(amount);
17-
mat4 m = mx_rotationMatrix(axis, rotationRadians);
18-
result = mx_matrix_mul(m, vec4(_in, 1.0)).xyz;
9+
float s = mx_sin(rotationRadians);
10+
float c = mx_cos(rotationRadians);
11+
float oc = 1.0 - c;
12+
result = _in * c + cross(_in, axis) * s + axis * dot(axis, _in) * oc;
1913
}
Lines changed: 9 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,13 @@
1-
matrix rotationMatrix(vector axis, float angle)
2-
{
3-
vector nAxis = normalize(axis);
4-
float s = sin(angle);
5-
float c = cos(angle);
6-
float oc = 1.0 - c;
7-
8-
return matrix(oc * nAxis[0] * nAxis[0] + c, oc * nAxis[0] * nAxis[1] - nAxis[2] * s, oc * nAxis[2] * nAxis[0] + nAxis[1] * s, 0.0,
9-
oc * nAxis[0] * nAxis[1] + nAxis[2] * s, oc * nAxis[1] * nAxis[1] + c, oc * nAxis[1] * nAxis[2] - nAxis[0] * s, 0.0,
10-
oc * nAxis[2] * nAxis[0] - nAxis[1] * s, oc * nAxis[1] * nAxis[2] + nAxis[0] * s, oc * nAxis[2] * nAxis[2] + c, 0.0,
11-
0.0, 0.0, 0.0, 1.0);
12-
}
13-
141
void mx_rotate_vector3(vector _in, float amount, vector axis, output vector result)
152
{
3+
// Based on https://en.wikipedia.org/wiki/Rodrigues%27_rotation_formula, where the
4+
// Wikipedia formula follows v' = M * v and MaterialX follows v' = v * M, thus the
5+
// order of parameters to cross are reversed.
6+
7+
vector nAxis = normalize(axis);
168
float rotationRadians = radians(amount);
17-
matrix m = rotationMatrix(axis, rotationRadians);
18-
vector4 trans = transform(m, vector4(_in[0], _in[1], _in[2], 1.0));
19-
result = vector(trans.x, trans.y, trans.z);
9+
float s = sin(rotationRadians);
10+
float c = cos(rotationRadians);
11+
float oc = 1.0 - c;
12+
result = _in * c + cross(_in, nAxis) * s + nAxis * dot(nAxis, _in) * oc;
2013
}

0 commit comments

Comments
 (0)