-
Notifications
You must be signed in to change notification settings - Fork 49
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Some new additions, some leaner implementations and one breaking chan…
…ge(!) (#35) * Breaking change(!) cross vec2 (float32 float64) now return a scalar value, not a new vector. Cross-product in 2D is not well-defined but it is changed to the 2D version stated at https://mathworld.wolfram.com/CrossProduct.html . Add Sinus and Cosine for angle between vectors (vec2 vec3 float64 float32) Changed implementation for Angle (vec2 vec3 float32 float64) to utilize Cosine implementation (with math.Acos). Changed implementation for left and right winding (vec2 float32 float64) Duplicated test file for quaternion (float32 float64) * doc fix * rename fmath.Sqrtf to Sqrt and fix build for non amd64 * fix quaternion tests. They were failing due to precision errors in float values. --------- Co-authored-by: Erik Unger <617459+ungerik@users.noreply.github.com> Co-authored-by: Erik Unger <erik@erikunger.com>
- Loading branch information
1 parent
7b69e27
commit 1137f6a
Showing
10 changed files
with
728 additions
and
157 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
package quaternion | ||
|
||
import ( | ||
"fmt" | ||
"math" | ||
"testing" | ||
|
||
"github.com/ungerik/go3d/float64/vec3" | ||
) | ||
|
||
// RotateVec3 rotates v by the rotation represented by the quaternion. | ||
func rotateAndNormalizeVec3(quat *T, v *vec3.T) { | ||
qv := T{v[0], v[1], v[2], 0} | ||
inv := quat.Inverted() | ||
q := Mul3(quat, &qv, &inv) | ||
v[0] = q[0] | ||
v[1] = q[1] | ||
v[2] = q[2] | ||
} | ||
|
||
func TestQuaternionRotateVec3(t *testing.T) { | ||
eularAngles := []vec3.T{ | ||
{90, 20, 21}, | ||
{-90, 0, 0}, | ||
{28, 1043, -38}, | ||
} | ||
vecs := []vec3.T{ | ||
{2, 3, 4}, | ||
{1, 3, -2}, | ||
{-6, 2, 9}, | ||
} | ||
for _, vec := range vecs { | ||
for _, eularAngle := range eularAngles { | ||
func() { | ||
q := FromEulerAngles(eularAngle[1]*math.Pi/180.0, eularAngle[0]*math.Pi/180.0, eularAngle[2]*math.Pi/180.0) | ||
vec_r1 := vec | ||
vec_r2 := vec | ||
magSqr := vec_r1.LengthSqr() | ||
rotateAndNormalizeVec3(&q, &vec_r2) | ||
q.RotateVec3(&vec_r1) | ||
vecd := q.RotatedVec3(&vec) | ||
magSqr2 := vec_r1.LengthSqr() | ||
|
||
if !vecd.PracticallyEquals(&vec_r1, 0.000000000000001) { | ||
t.Logf("test case %v rotates %v failed - vector rotation: %+v, %+v\n", eularAngle, vec, vecd, vec_r1) | ||
t.Fail() | ||
} | ||
|
||
angle := vec3.Angle(&vec_r1, &vec_r2) | ||
length := math.Abs(magSqr - magSqr2) | ||
|
||
if angle > 0.0000001 { | ||
t.Logf("test case %v rotates %v failed - angle difference to large\n", eularAngle, vec) | ||
t.Logf("vectors: %+v, %+v\n", vec_r1, vec_r2) | ||
t.Logf("angle: %v\n", angle) | ||
t.Fail() | ||
} | ||
|
||
if length > 0.000000000001 { | ||
t.Logf("test case %v rotates %v failed - squared length difference to large\n", eularAngle, vec) | ||
t.Logf("vectors: %+v %+v\n", vec_r1, vec_r2) | ||
t.Logf("squared lengths: %v, %v\n", magSqr, magSqr2) | ||
t.Fail() | ||
} | ||
}() | ||
} | ||
} | ||
} | ||
|
||
func TestToEulerAngles(t *testing.T) { | ||
specialValues := []float64{-5, -math.Pi, -2, -math.Pi / 2, 0, math.Pi / 2, 2.4, math.Pi, 3.9} | ||
for _, x := range specialValues { | ||
for _, y := range specialValues { | ||
for _, z := range specialValues { | ||
quat1 := FromEulerAngles(y, x, z) | ||
ry, rx, rz := quat1.ToEulerAngles() | ||
quat2 := FromEulerAngles(ry, rx, rz) | ||
// quat must be equivalent | ||
const e64 = 1e-14 | ||
cond1 := math.Abs(quat1[0]-quat2[0]) < e64 && math.Abs(quat1[1]-quat2[1]) < e64 && math.Abs(quat1[2]-quat2[2]) < e64 && math.Abs(quat1[3]-quat2[3]) < e64 | ||
cond2 := math.Abs(quat1[0]+quat2[0]) < e64 && math.Abs(quat1[1]+quat2[1]) < e64 && math.Abs(quat1[2]+quat2[2]) < e64 && math.Abs(quat1[3]+quat2[3]) < e64 | ||
if !cond1 && !cond2 { | ||
fmt.Printf("test case %v, %v, %v failed\n", x, y, z) | ||
fmt.Printf("result is %v, %v, %v\n", rx, ry, rz) | ||
fmt.Printf("quat1 is %v\n", quat1) | ||
fmt.Printf("quat2 is %v\n", quat2) | ||
t.Fail() | ||
} | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.