mirror of
https://github.com/bloeys/gglm.git
synced 2025-12-29 05:28:20 +00:00
220 lines
5.4 KiB
Go
Executable File
220 lines
5.4 KiB
Go
Executable File
package gglm
|
|
|
|
import (
|
|
"fmt"
|
|
"math"
|
|
)
|
|
|
|
var _ Mat = &TrMat{}
|
|
var _ fmt.Stringer = &TrMat{}
|
|
|
|
// TrMat represents a transformation matrix
|
|
type TrMat struct {
|
|
Mat4
|
|
}
|
|
|
|
// 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 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 {
|
|
t.Mat4.Mul(&m.Mat4)
|
|
return t
|
|
}
|
|
|
|
func (t *TrMat) Eq(m *TrMat) bool {
|
|
return t.Data == m.Data
|
|
}
|
|
|
|
func (t *TrMat) Clone() *TrMat {
|
|
return &TrMat{
|
|
Mat4: *t.Mat4.Clone(),
|
|
}
|
|
}
|
|
|
|
func NewTranslationMat(v *Vec3) *TrMat {
|
|
return &TrMat{
|
|
Mat4: Mat4{
|
|
Data: [4][4]float32{
|
|
{1, 0, 0, 0},
|
|
{0, 1, 0, 0},
|
|
{0, 0, 1, 0},
|
|
{v.Data[0], v.Data[1], v.Data[2], 1},
|
|
},
|
|
},
|
|
}
|
|
}
|
|
|
|
func NewScaleMat(v *Vec3) *TrMat {
|
|
return &TrMat{
|
|
Mat4: Mat4{
|
|
Data: [4][4]float32{
|
|
{v.Data[0], 0, 0, 0},
|
|
{0, v.Data[1], 0, 0},
|
|
{0, 0, v.Data[2], 0},
|
|
{0, 0, 0, 1},
|
|
},
|
|
},
|
|
}
|
|
}
|
|
|
|
func NewRotMat(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
|
|
|
|
xx := q.Data[0] * q.Data[0]
|
|
yy := q.Data[1] * q.Data[1]
|
|
zz := q.Data[2] * q.Data[2]
|
|
ww := q.Data[3] * q.Data[3]
|
|
|
|
xy := q.Data[0] * q.Data[1]
|
|
xz := q.Data[0] * q.Data[2]
|
|
xw := q.Data[0] * q.Data[3]
|
|
|
|
yz := q.Data[1] * q.Data[2]
|
|
yw := q.Data[1] * q.Data[3]
|
|
|
|
zw := q.Data[2] * q.Data[3]
|
|
|
|
return &TrMat{
|
|
Mat4: Mat4{
|
|
Data: [4][4]float32{
|
|
{2*(ww+xx) - 1, 2 * (zw + xy), 2 * (xz - yw), 0},
|
|
{2 * (xy - zw), 2*(ww+yy) - 1, 2 * (xw + yz), 0},
|
|
{2 * (yw + xz), 2 * (yz - xw), 2*(ww+zz) - 1, 0},
|
|
{0, 0, 0, 1},
|
|
},
|
|
},
|
|
}
|
|
}
|
|
|
|
// 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 {
|
|
|
|
forward := SubVec3(targetPos, pos).Normalize()
|
|
right := Cross(forward, worldUp).Normalize()
|
|
up := Cross(right, forward)
|
|
|
|
return &TrMat{
|
|
Mat4: Mat4{
|
|
Data: [4][4]float32{
|
|
{right.Data[0], up.Data[0], -forward.Data[0], 0},
|
|
{right.Data[1], up.Data[1], -forward.Data[1], 0},
|
|
{right.Data[2], up.Data[2], -forward.Data[2], 0},
|
|
{-DotVec3(pos, right), -DotVec3(pos, up), DotVec3(pos, forward), 1},
|
|
},
|
|
},
|
|
}
|
|
}
|
|
|
|
// LookAtLH does a left-handed coordinate system lookAt.
|
|
// Can be used to create the view matrix
|
|
func LookAtLH(pos, targetPos, worldUp *Vec3) *TrMat {
|
|
|
|
forward := SubVec3(targetPos, pos).Normalize()
|
|
right := Cross(worldUp, forward).Normalize()
|
|
up := Cross(forward, right)
|
|
|
|
return &TrMat{
|
|
Mat4: Mat4{
|
|
Data: [4][4]float32{
|
|
{right.Data[0], up.Data[0], forward.Data[0], 0},
|
|
{right.Data[1], up.Data[1], forward.Data[1], 0},
|
|
{right.Data[2], up.Data[2], forward.Data[2], 0},
|
|
{-DotVec3(pos, right), -DotVec3(pos, up), -DotVec3(pos, forward), 1},
|
|
},
|
|
},
|
|
}
|
|
}
|
|
|
|
// Perspective creates a perspective projection matrix
|
|
func Perspective(fov, aspectRatio, nearClip, farClip float32) *Mat4 {
|
|
halfFovTan := float32(math.Tan(float64(fov * 0.5)))
|
|
return &Mat4{
|
|
Data: [4][4]float32{
|
|
{1 / (aspectRatio * halfFovTan), 0, 0, 0},
|
|
{0, 1 / halfFovTan, 0, 0},
|
|
{0, 0, -(nearClip + farClip) / (farClip - nearClip), -1},
|
|
{0, 0, -(2 * farClip * nearClip) / (farClip - nearClip), 0},
|
|
},
|
|
}
|
|
}
|
|
|
|
// Perspective creates an orthographic projection matrix
|
|
func Ortho(left, right, top, bottom, nearClip, farClip float32) *TrMat {
|
|
return &TrMat{
|
|
Mat4: Mat4{
|
|
Data: [4][4]float32{
|
|
{2 / (right - left), 0, 0, 0},
|
|
{0, 2 / (top - bottom), 0, 0},
|
|
{0, 0, -2 / (farClip - nearClip), 0},
|
|
{-(right + left) / (right - left), -(top + bottom) / (top - bottom), -(farClip + nearClip) / (farClip - nearClip), 1},
|
|
},
|
|
},
|
|
}
|
|
}
|
|
|
|
func NewTrMatId() *TrMat {
|
|
return &TrMat{
|
|
Mat4: *NewMat4Id(),
|
|
}
|
|
}
|