5 Commits

Author SHA1 Message Date
f4f06c54b3 Make TrMat funcs chainable+more 32 scalar funcs 2022-01-13 17:51:04 +04:00
80d1c12e2d Update readme 2022-01-13 16:30:17 +04:00
8bb31393b4 Quat axis and angle tests 2022-01-13 16:22:38 +04:00
e4edb7dcec Angle and axis methods for quat 2022-01-13 16:06:13 +04:00
d832e19dab Rotate and Col functions 2022-01-13 15:49:30 +04:00
9 changed files with 169 additions and 11 deletions

View File

@ -1,6 +1,6 @@
# gglm
Fast Go OpenGL Mathematics library inspired by the c++ library [glm](https://github.com/g-truc/glm).
Fast Go OpenGL/Graphics focused Mathematics library inspired by the c++ library [glm](https://github.com/g-truc/glm).
## Notes

View File

@ -1,7 +1,11 @@
package gglm
const (
Pi float32 = 3.14159265359
Deg2Rad float32 = Pi / 180
Rad2Deg float32 = 180 / Pi
Pi float32 = 3.14159265359
Deg2Rad float32 = Pi / 180
Rad2Deg float32 = 180 / Pi
F32Epsilon float32 = 1e-6
//CosHalf is Cos32(0.5)
CosHalf float32 = 0.87758256189
)

View File

@ -28,6 +28,10 @@ func (m *Mat2) String() string {
return fmt.Sprintf("\n| %+-9.3f %+-9.3f |\n| %+-9.3f %+-9.3f |\n", m.Data[0][0], m.Data[0][1], m.Data[1][0], m.Data[1][1])
}
func (m *Mat2) Col(c int) *Vec2 {
return &Vec2{Data: m.Data[c]}
}
//Add m += m2
func (m *Mat2) Add(m2 *Mat2) *Mat2 {
m.Data[0][0] += m2.Data[0][0]

View File

@ -31,6 +31,10 @@ func (m *Mat3) String() string {
)
}
func (m *Mat3) Col(c int) *Vec3 {
return &Vec3{Data: m.Data[c]}
}
//Add m += m2
func (m *Mat3) Add(m2 *Mat3) *Mat3 {

View File

@ -32,6 +32,10 @@ func (m *Mat4) String() string {
)
}
func (m *Mat4) Col(c int) *Vec4 {
return &Vec4{Data: m.Data[c]}
}
//Add m += m2
func (m *Mat4) Add(m2 *Mat4) *Mat4 {

View File

@ -16,6 +16,37 @@ func (q *Quat) Eq(q2 *Quat) bool {
return q.Data == q2.Data
}
//Angle returns the angle represented by this quaternion
func (q *Quat) Angle() float32 {
if Abs32(q.Data[3]) > CosHalf {
a := Asin32(Sqrt32(q.Data[0]*q.Data[0]+q.Data[1]*q.Data[1]+q.Data[2]*q.Data[2])) * 2
if q.Data[3] < 0 {
return Pi*2 - a
}
return a
}
return Acos32(q.Data[3]) * 2
}
//Axis returns the rotation axis represented by this quaternion
func (q *Quat) Axis() *Vec3 {
var t float32 = 1 - q.Data[3]*q.Data[3]
if t <= 0 {
return &Vec3{Data: [3]float32{0, 0, 1}}
}
t = 1 / Sqrt32(t)
return &Vec3{Data: [3]float32{
q.Data[0] * t,
q.Data[1] * t,
q.Data[2] * t,
}}
}
//Euler takes rotations in radians and produces a rotation that
//rotates around the z-axis, y-axis and lastly x-axis.
func NewQuatEuler(v *Vec3) *Quat {

View File

@ -25,3 +25,51 @@ func TestNewQuatAngleAxis(t *testing.T) {
t.Errorf("Got: %v; Expected: %v", q.String(), ans.String())
}
}
func TestQuatAngle(t *testing.T) {
a := gglm.NewQuatAngleAxis(180*gglm.Deg2Rad, gglm.NewVec3(0, 1, 0)).Angle()
var ans float32 = 180.0 * gglm.Deg2Rad
if !gglm.EqF32(a, ans) {
t.Errorf("Got: %v; Expected: %v", a, ans)
}
a = gglm.NewQuatAngleAxis(90*gglm.Deg2Rad, gglm.NewVec3(1, 1, 0).Normalize()).Angle()
ans = 90 * gglm.Deg2Rad
if !gglm.EqF32(a, ans) {
t.Errorf("Got: %v; Expected: %v", a, ans)
}
a = gglm.NewQuatAngleAxis(125*gglm.Deg2Rad, gglm.NewVec3(1, 1, 0).Normalize()).Angle()
ans = 125 * gglm.Deg2Rad
if !gglm.EqF32(a, ans) {
t.Errorf("Got: %v; Expected: %v", a, ans)
}
}
func TestQuatAxis(t *testing.T) {
a := gglm.NewQuatAngleAxis(1, gglm.NewVec3(0, 1, 0)).Axis()
ans := gglm.NewVec3(0, 1, 0)
if !gglm.EqF32(a.X(), ans.X()) || !gglm.EqF32(a.Y(), ans.Y()) || !gglm.EqF32(a.Z(), ans.Z()) {
t.Errorf("Got: %v; Expected: %v", a.String(), ans.String())
}
a = gglm.NewQuatAngleAxis(1, gglm.NewVec3(1, 1, 0).Normalize()).Axis()
ans = gglm.NewVec3(1, 1, 0).Normalize()
if !gglm.EqF32(a.X(), ans.X()) || !gglm.EqF32(a.Y(), ans.Y()) || !gglm.EqF32(a.Z(), ans.Z()) {
t.Errorf("Got: %v; Expected: %v", a.String(), ans.String())
}
a = gglm.NewQuatAngleAxis(1, gglm.NewVec3(67, 46, 32).Normalize()).Axis()
ans = gglm.NewVec3(67, 46, 32).Normalize()
if !gglm.EqF32(a.X(), ans.X()) || !gglm.EqF32(a.Y(), ans.Y()) || !gglm.EqF32(a.Z(), ans.Z()) {
t.Errorf("Got: %v; Expected: %v", a.String(), ans.String())
}
}

View File

@ -2,9 +2,6 @@ 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)
@ -31,7 +28,27 @@ func Acos32(x float32) float32 {
return float32(math.Acos(float64(x)))
}
func Tan32(x float32) float32 {
return float32(math.Tan(float64(x)))
}
func Atan32(x float32) float32 {
return float32(math.Atan(float64(x)))
}
func Atan232(x, y float32) float32 {
return float32(math.Atan2(float64(y), float64(x)))
}
func Sincos32(x float32) (sinx, cosx float32) {
a, b := math.Sincos(float64(x))
return float32(a), float32(b)
}
func Abs32(x float32) float32 {
return float32(math.Abs(float64(x)))
}
func Sqrt32(x float32) float32 {
return float32(math.Sqrt(float64(x)))
}

View File

@ -13,18 +13,64 @@ type TrMat struct {
Mat4
}
//Translate adds the vector to the translation components of the transformation matrix
func (t *TrMat) Translate(v *Vec3) {
//Translate adds v to the translation components of the transformation matrix
func (t *TrMat) Translate(v *Vec3) *TrMat {
t.Data[3][0] += v.Data[0]
t.Data[3][1] += v.Data[1]
t.Data[3][2] += v.Data[2]
return t
}
//Scale multiplies the vector by the scale components of the transformation matrix
func (t *TrMat) Scale(v *Vec3) {
//Scale multiplies the scale components of the transformation matrix by v
func (t *TrMat) Scale(v *Vec3) *TrMat {
t.Data[0][0] *= v.Data[0]
t.Data[1][1] *= v.Data[1]
t.Data[2][2] *= v.Data[2]
return t
}
//Rotate takes a *normalized* axis and angles in radians to rotate around the given axis
func (t *TrMat) Rotate(rads float32, axis *Vec3) *TrMat {
s := Sin32(rads)
c := Cos32(rads)
axis = axis.Normalize()
temp := axis.Clone().Scale(1 - c)
rotate := TrMat{}
rotate.Data[0][0] = c + temp.Data[0]*axis.Data[0]
rotate.Data[0][1] = temp.Data[0]*axis.Data[1] + s*axis.Data[2]
rotate.Data[0][2] = temp.Data[0]*axis.Data[2] - s*axis.Data[1]
rotate.Data[1][0] = temp.Data[1]*axis.Data[0] - s*axis.Data[2]
rotate.Data[1][1] = c + temp.Data[1]*axis.Data[1]
rotate.Data[1][2] = temp.Data[1]*axis.Data[2] + s*axis.Data[0]
rotate.Data[2][0] = temp.Data[2]*axis.Data[0] + s*axis.Data[1]
rotate.Data[2][1] = temp.Data[2]*axis.Data[1] - s*axis.Data[0]
rotate.Data[2][2] = c + temp.Data[2]*axis.Data[2]
result := &Mat4{}
result.Data[0] = t.Col(0).Scale(rotate.Data[0][0]).
Add(t.Col(1).Scale(rotate.Data[0][1])).
Add(t.Col(2).Scale(rotate.Data[0][2])).
Data
result.Data[1] = t.Col(0).Scale(rotate.Data[1][0]).
Add(t.Col(1).Scale(rotate.Data[1][1])).
Add(t.Col(2).Scale(rotate.Data[1][2])).
Data
result.Data[2] = t.Col(0).Scale(rotate.Data[2][0]).
Add(t.Col(1).Scale(rotate.Data[2][1])).
Add(t.Col(2).Scale(rotate.Data[2][2])).
Data
t.Data[0] = result.Data[0]
t.Data[1] = result.Data[1]
t.Data[2] = result.Data[2]
return t
}
func (t *TrMat) Mul(m *TrMat) *TrMat {