mirror of
https://github.com/bloeys/gglm.git
synced 2025-12-29 05:28:20 +00:00
Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| b9faa2e59e | |||
| 3eb372dec3 | |||
| e6bf7aee10 | |||
| fa25c1f551 |
2
.github/workflows/test-gglm.yml
vendored
2
.github/workflows/test-gglm.yml
vendored
@ -1,4 +1,4 @@
|
||||
name: test-gglm
|
||||
name: "Build and Tests"
|
||||
|
||||
on:
|
||||
create:
|
||||
|
||||
@ -54,5 +54,5 @@ func main() {
|
||||
|
||||
## Notes
|
||||
|
||||
You can check compiler inlining decisions using `go run -gcflags "-m" .`. Some functions look a bit weird compared to similar ones
|
||||
You can check compiler inlining decisions using `go run -gcflags "-m" .`. Some functions look a bit weird
|
||||
because we are trying to reduce function complexity so the compiler inlines.
|
||||
|
||||
@ -28,8 +28,8 @@ 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]}
|
||||
func (m *Mat2) Col(c int) Vec2 {
|
||||
return Vec2{Data: m.Data[c]}
|
||||
}
|
||||
|
||||
// Add m += m2
|
||||
|
||||
@ -31,8 +31,8 @@ func (m *Mat3) String() string {
|
||||
)
|
||||
}
|
||||
|
||||
func (m *Mat3) Col(c int) *Vec3 {
|
||||
return &Vec3{Data: m.Data[c]}
|
||||
func (m *Mat3) Col(c int) Vec3 {
|
||||
return Vec3{Data: m.Data[c]}
|
||||
}
|
||||
|
||||
// Add m += m2
|
||||
|
||||
@ -32,8 +32,8 @@ func (m *Mat4) String() string {
|
||||
)
|
||||
}
|
||||
|
||||
func (m *Mat4) Col(c int) *Vec4 {
|
||||
return &Vec4{Data: m.Data[c]}
|
||||
func (m *Mat4) Col(c int) Vec4 {
|
||||
return Vec4{Data: m.Data[c]}
|
||||
}
|
||||
|
||||
// Add m += m2
|
||||
|
||||
@ -13,24 +13,36 @@ type TrMat struct {
|
||||
Mat4
|
||||
}
|
||||
|
||||
// TranslateVec adds v to the translation components of the transformation matrix
|
||||
func (t *TrMat) TranslateVec(v *Vec3) *TrMat {
|
||||
return t.Translate(v.X(), v.Y(), v.Z())
|
||||
}
|
||||
|
||||
// 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]
|
||||
func (t *TrMat) Translate(x, y, z float32) *TrMat {
|
||||
t.Data[3][0] += x
|
||||
t.Data[3][1] += y
|
||||
t.Data[3][2] += z
|
||||
return t
|
||||
}
|
||||
|
||||
// ScaleVec multiplies the scale components of the transformation matrix by v
|
||||
func (t *TrMat) ScaleVec(v *Vec3) *TrMat {
|
||||
return t.Scale(v.X(), v.Y(), v.Z())
|
||||
}
|
||||
|
||||
// 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]
|
||||
func (t *TrMat) Scale(x, y, z float32) *TrMat {
|
||||
t.Data[0][0] *= z
|
||||
t.Data[1][1] *= y
|
||||
t.Data[2][2] *= z
|
||||
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 {
|
||||
// RotateVec takes a *normalized* axis and angles in radians to rotate around the given axis
|
||||
func (t *TrMat) RotateVec(rads float32, axis *Vec3) *TrMat {
|
||||
|
||||
// Manually inlined
|
||||
|
||||
s := Sin32(rads)
|
||||
c := Cos32(rads)
|
||||
@ -51,20 +63,85 @@ func (t *TrMat) Rotate(rads float32, axis *Vec3) *TrMat {
|
||||
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])).
|
||||
result := Mat4{}
|
||||
|
||||
col0 := t.Col(0)
|
||||
col1 := t.Col(1)
|
||||
col2 := t.Col(2)
|
||||
result.Data[0] = col0.Scale(rotate.Data[0][0]).
|
||||
Add(col1.Scale(rotate.Data[0][1])).
|
||||
Add(col2.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])).
|
||||
col0 = t.Col(0)
|
||||
col1 = t.Col(1)
|
||||
col2 = t.Col(2)
|
||||
result.Data[1] = col0.Scale(rotate.Data[1][0]).
|
||||
Add(col1.Scale(rotate.Data[1][1])).
|
||||
Add(col2.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])).
|
||||
col0 = t.Col(0)
|
||||
col1 = t.Col(1)
|
||||
col2 = t.Col(2)
|
||||
result.Data[2] = col0.Scale(rotate.Data[2][0]).
|
||||
Add(col1.Scale(rotate.Data[2][1])).
|
||||
Add(col2.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
|
||||
}
|
||||
|
||||
// Rotate takes a *normalized* axis and angles in radians to rotate around the given axis
|
||||
func (t *TrMat) Rotate(rads float32, axisX, axisY, axisZ float32) *TrMat {
|
||||
|
||||
s := Sin32(rads)
|
||||
c := Cos32(rads)
|
||||
|
||||
axis := NewVec3(axisX, axisY, axisZ)
|
||||
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{}
|
||||
|
||||
col0 := t.Col(0)
|
||||
col1 := t.Col(1)
|
||||
col2 := t.Col(2)
|
||||
result.Data[0] = col0.Scale(rotate.Data[0][0]).
|
||||
Add(col1.Scale(rotate.Data[0][1])).
|
||||
Add(col2.Scale(rotate.Data[0][2])).
|
||||
Data
|
||||
|
||||
col0 = t.Col(0)
|
||||
col1 = t.Col(1)
|
||||
col2 = t.Col(2)
|
||||
result.Data[1] = col0.Scale(rotate.Data[1][0]).
|
||||
Add(col1.Scale(rotate.Data[1][1])).
|
||||
Add(col2.Scale(rotate.Data[1][2])).
|
||||
Data
|
||||
|
||||
col0 = t.Col(0)
|
||||
col1 = t.Col(1)
|
||||
col2 = t.Col(2)
|
||||
result.Data[2] = col0.Scale(rotate.Data[2][0]).
|
||||
Add(col1.Scale(rotate.Data[2][1])).
|
||||
Add(col2.Scale(rotate.Data[2][2])).
|
||||
Data
|
||||
|
||||
t.Data[0] = result.Data[0]
|
||||
@ -88,8 +165,8 @@ func (t *TrMat) Clone() *TrMat {
|
||||
}
|
||||
}
|
||||
|
||||
func NewTranslationMat(v *Vec3) *TrMat {
|
||||
return &TrMat{
|
||||
func NewTranslationMatVec(v *Vec3) TrMat {
|
||||
return TrMat{
|
||||
Mat4: Mat4{
|
||||
Data: [4][4]float32{
|
||||
{1, 0, 0, 0},
|
||||
@ -101,8 +178,21 @@ func NewTranslationMat(v *Vec3) *TrMat {
|
||||
}
|
||||
}
|
||||
|
||||
func NewScaleMat(v *Vec3) *TrMat {
|
||||
return &TrMat{
|
||||
func NewTranslationMat(posX, posY, posZ float32) TrMat {
|
||||
return TrMat{
|
||||
Mat4: Mat4{
|
||||
Data: [4][4]float32{
|
||||
{1, 0, 0, 0},
|
||||
{0, 1, 0, 0},
|
||||
{0, 0, 1, 0},
|
||||
{posX, posY, posZ, 1},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func NewScaleMatVec(v *Vec3) TrMat {
|
||||
return TrMat{
|
||||
Mat4: Mat4{
|
||||
Data: [4][4]float32{
|
||||
{v.Data[0], 0, 0, 0},
|
||||
@ -114,7 +204,20 @@ func NewScaleMat(v *Vec3) *TrMat {
|
||||
}
|
||||
}
|
||||
|
||||
func NewRotMat(q *Quat) *TrMat {
|
||||
func NewScaleMat(scaleX, scaleY, scaleZ float32) TrMat {
|
||||
return TrMat{
|
||||
Mat4: Mat4{
|
||||
Data: [4][4]float32{
|
||||
{scaleX, 0, 0, 0},
|
||||
{0, scaleY, 0, 0},
|
||||
{0, 0, scaleZ, 0},
|
||||
{0, 0, 0, 1},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func NewRotMatQuat(q *Quat) TrMat {
|
||||
|
||||
//Based on: https://www.weizmann.ac.il/sci-tea/benari/sites/sci-tea.benari/files/uploads/softwareAndLearningMaterials/quaternion-tutorial-2-0-1.pdf
|
||||
//Note: in the reference p0,p1,p2,p3 == w,x,y,z
|
||||
@ -133,7 +236,7 @@ func NewRotMat(q *Quat) *TrMat {
|
||||
|
||||
zw := q.Data[2] * q.Data[3]
|
||||
|
||||
return &TrMat{
|
||||
return TrMat{
|
||||
Mat4: Mat4{
|
||||
Data: [4][4]float32{
|
||||
{2*(ww+xx) - 1, 2 * (zw + xy), 2 * (xz - yw), 0},
|
||||
@ -147,7 +250,7 @@ func NewRotMat(q *Quat) *TrMat {
|
||||
|
||||
// LookAtRH does a right-handed coordinate system lookAt (RH is the default for OpenGL).
|
||||
// Can be used to create the view matrix
|
||||
func LookAtRH(pos, targetPos, worldUp *Vec3) *TrMat {
|
||||
func LookAtRH(pos, targetPos, worldUp *Vec3) TrMat {
|
||||
|
||||
forward := SubVec3(targetPos, pos)
|
||||
forward.Normalize()
|
||||
@ -155,7 +258,7 @@ func LookAtRH(pos, targetPos, worldUp *Vec3) *TrMat {
|
||||
right.Normalize()
|
||||
up := Cross(&right, &forward)
|
||||
|
||||
return &TrMat{
|
||||
return TrMat{
|
||||
Mat4: Mat4{
|
||||
Data: [4][4]float32{
|
||||
{right.Data[0], up.Data[0], -forward.Data[0], 0},
|
||||
@ -169,7 +272,7 @@ func LookAtRH(pos, targetPos, worldUp *Vec3) *TrMat {
|
||||
|
||||
// LookAtLH does a left-handed coordinate system lookAt.
|
||||
// Can be used to create the view matrix
|
||||
func LookAtLH(pos, targetPos, worldUp *Vec3) *TrMat {
|
||||
func LookAtLH(pos, targetPos, worldUp *Vec3) TrMat {
|
||||
|
||||
forward := SubVec3(targetPos, pos)
|
||||
forward.Normalize()
|
||||
@ -177,7 +280,7 @@ func LookAtLH(pos, targetPos, worldUp *Vec3) *TrMat {
|
||||
right.Normalize()
|
||||
up := Cross(&forward, &right)
|
||||
|
||||
return &TrMat{
|
||||
return TrMat{
|
||||
Mat4: Mat4{
|
||||
Data: [4][4]float32{
|
||||
{right.Data[0], up.Data[0], forward.Data[0], 0},
|
||||
@ -190,9 +293,9 @@ func LookAtLH(pos, targetPos, worldUp *Vec3) *TrMat {
|
||||
}
|
||||
|
||||
// Perspective creates a perspective projection matrix
|
||||
func Perspective(fov, aspectRatio, nearClip, farClip float32) *Mat4 {
|
||||
func Perspective(fov, aspectRatio, nearClip, farClip float32) Mat4 {
|
||||
halfFovTan := float32(math.Tan(float64(fov * 0.5)))
|
||||
return &Mat4{
|
||||
return Mat4{
|
||||
Data: [4][4]float32{
|
||||
{1 / (aspectRatio * halfFovTan), 0, 0, 0},
|
||||
{0, 1 / halfFovTan, 0, 0},
|
||||
@ -203,8 +306,8 @@ func Perspective(fov, aspectRatio, nearClip, farClip float32) *Mat4 {
|
||||
}
|
||||
|
||||
// Perspective creates an orthographic projection matrix
|
||||
func Ortho(left, right, top, bottom, nearClip, farClip float32) *TrMat {
|
||||
return &TrMat{
|
||||
func Ortho(left, right, top, bottom, nearClip, farClip float32) TrMat {
|
||||
return TrMat{
|
||||
Mat4: Mat4{
|
||||
Data: [4][4]float32{
|
||||
{2 / (right - left), 0, 0, 0},
|
||||
@ -221,3 +324,21 @@ func NewTrMatId() TrMat {
|
||||
Mat4: NewMat4Id(),
|
||||
}
|
||||
}
|
||||
|
||||
func NewTrMatWithPos(x, y, z float32) TrMat {
|
||||
tr := TrMat{
|
||||
Mat4: NewMat4Id(),
|
||||
}
|
||||
|
||||
tr.Translate(x, y, z)
|
||||
return tr
|
||||
}
|
||||
|
||||
func NewTrMatWithPosVec(pos *Vec3) TrMat {
|
||||
tr := TrMat{
|
||||
Mat4: NewMat4Id(),
|
||||
}
|
||||
|
||||
tr.TranslateVec(pos)
|
||||
return tr
|
||||
}
|
||||
|
||||
@ -27,8 +27,7 @@ func TestNewTrMatId(t *testing.T) {
|
||||
|
||||
func TestNewTranslationMat(t *testing.T) {
|
||||
|
||||
pos := gglm.NewVec3(1, 2, 3)
|
||||
m := gglm.NewTranslationMat(&pos)
|
||||
m := gglm.NewTranslationMat(1, 2, 3)
|
||||
ans := &gglm.TrMat{
|
||||
Mat4: gglm.Mat4{
|
||||
Data: [4][4]float32{
|
||||
@ -47,8 +46,7 @@ func TestNewTranslationMat(t *testing.T) {
|
||||
|
||||
func TestNewScaleMat(t *testing.T) {
|
||||
|
||||
pos := gglm.NewVec3(1, 2, 3)
|
||||
m := gglm.NewScaleMat(&pos)
|
||||
m := gglm.NewScaleMat(1, 2, 3)
|
||||
ans := &gglm.TrMat{
|
||||
Mat4: gglm.Mat4{
|
||||
Data: [4][4]float32{
|
||||
@ -68,7 +66,7 @@ func TestNewScaleMat(t *testing.T) {
|
||||
func TestNewRotMat(t *testing.T) {
|
||||
|
||||
quat := gglm.NewQuatId()
|
||||
m := gglm.NewRotMat(&quat)
|
||||
m := gglm.NewRotMatQuat(&quat)
|
||||
ans := &gglm.TrMat{
|
||||
Mat4: gglm.Mat4{
|
||||
Data: [4][4]float32{
|
||||
|
||||
17
main.go
17
main.go
@ -152,17 +152,16 @@ func main() {
|
||||
println(q.String())
|
||||
|
||||
// Transform
|
||||
translationMat := gglm.NewTranslationMat(&gglm.Vec3{Data: [3]float32{1, 2, 3}})
|
||||
translationMat := gglm.NewTranslationMatVec(&gglm.Vec3{Data: [3]float32{1, 2, 3}})
|
||||
|
||||
rotDegs := gglm.NewVec3(60, 30, 20)
|
||||
quat := gglm.NewQuatEulerVec(rotDegs.AsRad())
|
||||
rotMat := gglm.NewRotMat(&quat)
|
||||
rotMat := gglm.NewRotMatQuat(&quat)
|
||||
|
||||
scale := gglm.NewVec3(1, 1, 1)
|
||||
scaleMat := gglm.NewScaleMat(&scale)
|
||||
scaleMat := gglm.NewScaleMat(1, 1, 1)
|
||||
|
||||
modelMat := gglm.NewTrMatId()
|
||||
modelMat.Mul(translationMat.Mul(rotMat.Mul(scaleMat)))
|
||||
modelMat.Mul(translationMat.Mul(rotMat.Mul(&scaleMat)))
|
||||
|
||||
println("\n\n\n", modelMat.String())
|
||||
|
||||
@ -173,15 +172,13 @@ func main() {
|
||||
println("\n\n", v2Orig.String(), "; ", v2Clone.String())
|
||||
|
||||
// Clone TrMat
|
||||
pos := gglm.NewVec3(1, 2, 3)
|
||||
trMatOrig := gglm.NewTranslationMat(&pos)
|
||||
trMatOrig := gglm.NewTranslationMat(1, 2, 3)
|
||||
trMatClone := trMatOrig.Clone()
|
||||
|
||||
trMatCloneScale := gglm.NewVec3(2, 2, 2)
|
||||
trMatClone.Scale(&trMatCloneScale)
|
||||
trMatClone.ScaleVec(&trMatCloneScale)
|
||||
|
||||
pos = gglm.NewVec3(9, 0, 0)
|
||||
trMatClone.Translate(&pos)
|
||||
trMatClone.Translate(9, 0, 0)
|
||||
println("\n\n", trMatOrig.String(), "; ", trMatClone.String())
|
||||
|
||||
// Quat geo
|
||||
|
||||
Reference in New Issue
Block a user