diff --git a/gglm/geometric.go b/gglm/geometric.go index 810db86..35f586e 100755 --- a/gglm/geometric.go +++ b/gglm/geometric.go @@ -73,3 +73,36 @@ func SqrDistVec4(v1, v2 *Vec4) float32 { w := v1.Data[3] - v2.Data[3] return x*x + y*y + z*z + w*w } + +//ReflectVec2 returns the reflected vector of the incoming vector 'v', and the surface normal 'n'. +// +//Note: n must be normalized or you will get wrong results +func ReflectVec2(v, n *Vec2) *Vec2 { + + //reflectedVec = v − 2*dot(v, norm)*norm + d := 2 * (v.Data[0]*n.Data[0] + v.Data[1]*n.Data[1]) + + return &Vec2{ + Data: [2]float32{ + v.Data[0] - d*n.Data[0], + v.Data[1] - d*n.Data[1], + }, + } +} + +//ReflectVec3 returns the reflected vector of the incoming vector 'v', and the surface normal 'n'. +// +//Note: n must be normalized or you will get wrong results +func ReflectVec3(v, n *Vec3) *Vec3 { + + //reflectedVec = v − 2*dot(v, norm)*norm + d := 2 * (v.Data[0]*n.Data[0] + v.Data[1]*n.Data[1] + v.Data[2]*n.Data[2]) + + return &Vec3{ + Data: [3]float32{ + v.Data[0] - d*n.Data[0], + v.Data[1] - d*n.Data[1], + v.Data[2] - d*n.Data[2], + }, + } +} diff --git a/gglm/geometric_test.go b/gglm/geometric_test.go new file mode 100755 index 0000000..43f9558 --- /dev/null +++ b/gglm/geometric_test.go @@ -0,0 +1,139 @@ +package gglm_test + +import ( + "testing" + + "github.com/bloeys/gglm/gglm" +) + +func TestDotVec2(t *testing.T) { + + v1 := gglm.Vec2{Data: [2]float32{1, 2}} + v2 := gglm.Vec2{Data: [2]float32{3, 4}} + ans := float32(11) + + res := gglm.DotVec2(&v1, &v2) + if res != ans { + t.Errorf("Got: %v; Expected: %v", res, ans) + } +} + +func TestDotVec3(t *testing.T) { + + v1 := gglm.Vec3{Data: [3]float32{1, 2, 3}} + v2 := gglm.Vec3{Data: [3]float32{4, 5, 6}} + ans := float32(32) + + res := gglm.DotVec3(&v1, &v2) + if res != ans { + t.Errorf("Got: %v; Expected: %v", res, ans) + } +} + +func TestDotVec4(t *testing.T) { + + v1 := gglm.Vec4{Data: [4]float32{1, 2, 3, 4}} + v2 := gglm.Vec4{Data: [4]float32{5, 6, 7, 8}} + ans := float32(70) + + res := gglm.DotVec4(&v1, &v2) + if res != ans { + t.Errorf("Got: %v; Expected: %v", res, ans) + } +} + +func TestDistVec2(t *testing.T) { + + v1 := gglm.Vec2{Data: [2]float32{1, 2}} + v2 := gglm.Vec2{Data: [2]float32{3, 4}} + ans := float32(2.828427) + + res := gglm.DistVec2(&v1, &v2) + if res != ans { + t.Errorf("Got: %v; Expected: %v", res, ans) + } +} + +func TestDistVec3(t *testing.T) { + + v1 := gglm.Vec3{Data: [3]float32{1, 2, 3}} + v2 := gglm.Vec3{Data: [3]float32{4, 5, 6}} + ans := float32(5.196152) + + res := gglm.DistVec3(&v1, &v2) + if res != ans { + t.Errorf("Got: %v; Expected: %v", res, ans) + } +} + +func TestDistVec4(t *testing.T) { + + v1 := gglm.Vec4{Data: [4]float32{1, 2, 3, 4}} + v2 := gglm.Vec4{Data: [4]float32{5, 6, 7, 8}} + ans := float32(8) + + res := gglm.DistVec4(&v1, &v2) + if res != ans { + t.Errorf("Got: %v; Expected: %v", res, ans) + } +} + +func TestSqrDistVec2(t *testing.T) { + + v1 := gglm.Vec2{Data: [2]float32{1, 2}} + v2 := gglm.Vec2{Data: [2]float32{3, 4}} + ans := float32(8) + + res := gglm.SqrDistVec2(&v1, &v2) + if res != ans { + t.Errorf("Got: %v; Expected: %v", res, ans) + } +} + +func TestSqrDistVec3(t *testing.T) { + + v1 := gglm.Vec3{Data: [3]float32{1, 2, 3}} + v2 := gglm.Vec3{Data: [3]float32{4, 5, 6}} + ans := float32(27) + + res := gglm.SqrDistVec3(&v1, &v2) + if res != ans { + t.Errorf("Got: %v; Expected: %v", res, ans) + } +} + +func TestSqrDistVec4(t *testing.T) { + + v1 := gglm.Vec4{Data: [4]float32{1, 2, 3, 4}} + v2 := gglm.Vec4{Data: [4]float32{5, 6, 7, 8}} + ans := float32(64) + + res := gglm.SqrDistVec4(&v1, &v2) + if res != ans { + t.Errorf("Got: %v; Expected: %v", res, ans) + } +} + +func TestReflectVec2(t *testing.T) { + + v1 := gglm.Vec2{Data: [2]float32{1, 2}} + n := gglm.Vec2{Data: [2]float32{0, 1}} + ans := gglm.Vec2{Data: [2]float32{1, -2}} + + res := gglm.ReflectVec2(&v1, &n) + if !res.Eq(&ans) { + t.Errorf("Got: %v; Expected: %v", res, ans) + } +} + +func TestReflectVec3(t *testing.T) { + + v1 := gglm.Vec3{Data: [3]float32{1, 2, 3}} + n := gglm.Vec3{Data: [3]float32{0, 1, 0}} + ans := gglm.Vec3{Data: [3]float32{1, -2, 3}} + + res := gglm.ReflectVec3(&v1, &n) + if !res.Eq(&ans) { + t.Errorf("Got: %v; Expected: %v", res, ans) + } +} diff --git a/gglm/scalar.go b/gglm/scalar.go new file mode 100755 index 0000000..69c3e02 --- /dev/null +++ b/gglm/scalar.go @@ -0,0 +1,16 @@ +package gglm + +import "math" + +//F32Epsilon = 0.0000005 +const F32Epsilon float32 = 1e-6 + +//EqF32 true if abs(f1-f2) <= F32Epsilon +func EqF32(f1, f2 float32) bool { + return math.Abs(float64(f1-f2)) <= float64(F32Epsilon) +} + +//EqF32Epsilon true if abs(f1-f2) <= eps +func EqF32Epsilon(f1, f2, eps float32) bool { + return math.Abs(float64(f1-f2)) <= float64(eps) +} diff --git a/main.go b/main.go index 7afdf6f..275abe6 100755 --- a/main.go +++ b/main.go @@ -120,4 +120,10 @@ func main() { vec3A := gglm.Vec3{Data: [3]float32{1, 2, 3}} lol := gglm.MulMat3Vec3(&mat3A, &vec3A) println(lol.String()) + + //ReflectVec2 + vec2B := &gglm.Vec2{Data: [2]float32{4, 5}} + normA := &gglm.Vec2{Data: [2]float32{0, 1}} + rVec2A := gglm.ReflectVec2(vec2B, normA) + println(rVec2A.String()) } diff --git a/main_test.go b/main_test.go index f13e073..2099bcb 100755 --- a/main_test.go +++ b/main_test.go @@ -7,8 +7,8 @@ import ( ) var ( - dotVec2Result float32 = 0 - dotVec3Result float32 = 0 + dotVec2Result float32 + dotVec3Result float32 crossResult *gglm.Vec3 mulMat4Vec4Res *gglm.Vec4 )