10 Commits

Author SHA1 Message Date
b39e8e0b80 Actually correct ortho 2021-11-15 09:53:43 +04:00
585d17aa29 Fix ortho func 2021-11-13 23:27:21 +04:00
d4c7755ca8 More benchmarks 2021-11-09 10:28:23 +04:00
2071b351d5 Move benchmarks into relevant test files 2021-11-09 10:19:42 +04:00
300c699e65 Add Ortho func 2021-11-09 10:13:58 +04:00
175d05420c Add perspective func+fix LookAt 2021-11-09 09:55:24 +04:00
d1a4f5ba7c Optimize mat3 mul 2021-11-09 09:36:59 +04:00
9282567928 Optimize mat4 mul 2021-11-09 09:29:45 +04:00
4c30b8b6d3 Use multi-dimensional arrays+ensure storage&comp. is column major 2021-11-09 09:13:16 +04:00
92a3ca3a9c LookAt func 2021-11-07 04:47:53 +04:00
11 changed files with 795 additions and 575 deletions

View File

@ -6,6 +6,13 @@ import (
"github.com/bloeys/gglm/gglm"
)
var (
dotVec2Result, distVec2Result float32
dotVec3Result, distVec3Result float32
reflectVec2Result *gglm.Vec2
crossResult, reflectVec3Result *gglm.Vec3
)
func TestDotVec2(t *testing.T) {
v1 := gglm.Vec2{Data: [2]float32{1, 2}}
@ -137,3 +144,73 @@ func TestReflectVec3(t *testing.T) {
t.Errorf("Got: %v; Expected: %v", res, ans)
}
}
func BenchmarkDotVec2(b *testing.B) {
v1 := &gglm.Vec2{}
v2 := &gglm.Vec2{}
for i := 0; i < b.N; i++ {
dotVec2Result = gglm.DotVec2(v1, v2)
}
}
func BenchmarkDotVec3(b *testing.B) {
v1 := &gglm.Vec3{}
v2 := &gglm.Vec3{}
for i := 0; i < b.N; i++ {
dotVec3Result = gglm.DotVec3(v1, v2)
}
}
func BenchmarkCross(b *testing.B) {
v1 := &gglm.Vec3{}
v2 := &gglm.Vec3{}
for i := 0; i < b.N; i++ {
crossResult = gglm.Cross(v1, v2)
}
}
func BenchmarkDistVec2(b *testing.B) {
v1 := &gglm.Vec2{}
v2 := &gglm.Vec2{}
for i := 0; i < b.N; i++ {
distVec2Result = gglm.DistVec2(v1, v2)
}
}
func BenchmarkDistVec3(b *testing.B) {
v1 := &gglm.Vec3{}
v2 := &gglm.Vec3{}
for i := 0; i < b.N; i++ {
distVec3Result = gglm.DistVec3(v1, v2)
}
}
func BenchmarkReflectVec2(b *testing.B) {
v1 := &gglm.Vec2{}
v2 := &gglm.Vec2{}
for i := 0; i < b.N; i++ {
reflectVec2Result = gglm.ReflectVec2(v1, v2)
}
}
func BenchmarkReflectVec3(b *testing.B) {
v1 := &gglm.Vec3{}
v2 := &gglm.Vec3{}
for i := 0; i < b.N; i++ {
reflectVec3Result = gglm.ReflectVec3(v1, v2)
}
}

View File

@ -8,15 +8,15 @@ var _ Mat = &Mat2{}
var _ fmt.Stringer = &Mat2{}
type Mat2 struct {
Data [4]float32
Data [2][2]float32
}
func (m *Mat2) Get(row, col int) float32 {
return m.Data[row*2+col]
return m.Data[col][row]
}
func (m *Mat2) Set(row, col int, val float32) {
m.Data[row*2+col] = val
m.Data[col][row] = val
}
func (m *Mat2) Size() MatSize {
@ -25,45 +25,49 @@ func (m *Mat2) Size() MatSize {
func (m *Mat2) String() string {
//+ always shows +/- sign; - means pad to the right; 9 means total of 9 digits (or padding if less); .3 means 3 decimals
return fmt.Sprintf("\n| %+-9.3f %+-9.3f |\n| %+-9.3f %+-9.3f |\n", m.Data[0], m.Data[1], m.Data[2], m.Data[3])
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])
}
//Add m += m2
func (m *Mat2) Add(m2 *Mat2) *Mat2 {
m.Data[0] += m2.Data[0]
m.Data[1] += m2.Data[1]
m.Data[2] += m2.Data[2]
m.Data[3] += m2.Data[3]
m.Data[0][0] += m2.Data[0][0]
m.Data[0][1] += m2.Data[0][1]
m.Data[1][0] += m2.Data[1][0]
m.Data[1][1] += m2.Data[1][1]
return m
}
//Add m -= m2
func (m *Mat2) Sub(m2 *Mat2) *Mat2 {
m.Data[0] -= m2.Data[0]
m.Data[1] -= m2.Data[1]
m.Data[2] -= m2.Data[2]
m.Data[3] -= m2.Data[3]
m.Data[0][0] -= m2.Data[0][0]
m.Data[0][1] -= m2.Data[0][1]
m.Data[1][0] -= m2.Data[1][0]
m.Data[1][1] -= m2.Data[1][1]
return m
}
//Mul m *= m2
func (m *Mat2) Mul(m2 *Mat2) *Mat2 {
m.Data = [4]float32{
m.Data[0]*m2.Data[0] + m.Data[1]*m2.Data[2],
m.Data[0]*m2.Data[1] + m.Data[1]*m2.Data[3],
m.Data[2]*m2.Data[0] + m.Data[3]*m2.Data[2],
m.Data[2]*m2.Data[1] + m.Data[3]*m2.Data[3],
func (m1 *Mat2) Mul(m2 *Mat2) *Mat2 {
m1.Data = [2][2]float32{
{
m1.Data[0][0]*m2.Data[0][0] + m1.Data[1][0]*m2.Data[0][1],
m1.Data[0][1]*m2.Data[0][0] + m1.Data[1][1]*m2.Data[0][1],
},
{
m1.Data[0][0]*m2.Data[1][0] + m1.Data[1][0]*m2.Data[1][1],
m1.Data[0][1]*m2.Data[1][0] + m1.Data[1][1]*m2.Data[1][1],
},
}
return m
return m1
}
//Scale m *= x (element wise multiplication)
func (m *Mat2) Scale(x float32) *Mat2 {
m.Data[0] *= x
m.Data[1] *= x
m.Data[2] *= x
m.Data[3] *= x
m.Data[0][0] *= x
m.Data[0][1] *= x
m.Data[1][0] *= x
m.Data[1][1] *= x
return m
}
@ -78,11 +82,15 @@ func (m *Mat2) Eq(m2 *Mat2) bool {
//AddMat2 m3 = m1 + m2
func AddMat2(m1, m2 *Mat2) *Mat2 {
return &Mat2{
Data: [4]float32{
m1.Data[0] + m2.Data[0],
m1.Data[1] + m2.Data[1],
m1.Data[2] + m2.Data[2],
m1.Data[3] + m2.Data[3],
Data: [2][2]float32{
{
m1.Data[0][0] + m2.Data[0][0],
m1.Data[0][1] + m2.Data[0][1],
},
{
m1.Data[1][0] + m2.Data[1][0],
m1.Data[1][1] + m2.Data[1][1],
},
},
}
}
@ -90,11 +98,15 @@ func AddMat2(m1, m2 *Mat2) *Mat2 {
//SubMat2 m3 = m1 - m2
func SubMat2(m1, m2 *Mat2) *Mat2 {
return &Mat2{
Data: [4]float32{
m1.Data[0] - m2.Data[0],
m1.Data[1] - m2.Data[1],
m1.Data[2] - m2.Data[2],
m1.Data[3] - m2.Data[3],
Data: [2][2]float32{
{
m1.Data[0][0] - m2.Data[0][0],
m1.Data[0][1] - m2.Data[0][1],
},
{
m1.Data[1][0] - m2.Data[1][0],
m1.Data[1][1] - m2.Data[1][1],
},
},
}
}
@ -102,12 +114,15 @@ func SubMat2(m1, m2 *Mat2) *Mat2 {
//MulMat2 m3 = m1 * m2
func MulMat2(m1, m2 *Mat2) *Mat2 {
return &Mat2{
Data: [4]float32{
m1.Data[0]*m2.Data[0] + m1.Data[1]*m2.Data[2],
m1.Data[0]*m2.Data[1] + m1.Data[1]*m2.Data[3],
m1.Data[2]*m2.Data[0] + m1.Data[3]*m2.Data[2],
m1.Data[2]*m2.Data[1] + m1.Data[3]*m2.Data[3],
Data: [2][2]float32{
{
m1.Data[0][0]*m2.Data[0][0] + m1.Data[1][0]*m2.Data[0][1],
m1.Data[0][1]*m2.Data[0][0] + m1.Data[1][1]*m2.Data[0][1],
},
{
m1.Data[0][0]*m2.Data[1][0] + m1.Data[1][0]*m2.Data[1][1],
m1.Data[0][1]*m2.Data[1][0] + m1.Data[1][1]*m2.Data[1][1],
},
},
}
}
@ -116,8 +131,8 @@ func MulMat2(m1, m2 *Mat2) *Mat2 {
func MulMat2Vec2(m1 *Mat2, v1 *Vec2) *Vec2 {
return &Vec2{
Data: [2]float32{
m1.Data[0]*v1.Data[0] + m1.Data[1]*v1.Data[1],
m1.Data[2]*v1.Data[0] + m1.Data[3]*v1.Data[1],
m1.Data[0][0]*v1.Data[0] + m1.Data[1][0]*v1.Data[1],
m1.Data[0][1]*v1.Data[0] + m1.Data[1][1]*v1.Data[1],
},
}
}
@ -125,9 +140,9 @@ func MulMat2Vec2(m1 *Mat2, v1 *Vec2) *Vec2 {
//NewMat2Id returns the 2x2 identity matrix
func NewMat2Id() *Mat2 {
return &Mat2{
Data: [4]float32{
1, 0,
0, 1,
Data: [2][2]float32{
{1, 0},
{0, 1},
},
}
}

View File

@ -25,9 +25,9 @@ func TestMat2GetSet(t *testing.T) {
func TestMat2Id(t *testing.T) {
correctAns := gglm.Mat2{
Data: [4]float32{
1, 0,
0, 1,
Data: [2][2]float32{
{1, 0},
{0, 1},
}}
m1 := gglm.NewMat2Id()
@ -39,20 +39,20 @@ func TestMat2Id(t *testing.T) {
func TestSubMat2(t *testing.T) {
correctAns := gglm.Mat2{
Data: [4]float32{
-4, -4,
-4, -4,
Data: [2][2]float32{
{-4, -4},
{-4, -4},
}}
m1 := &gglm.Mat2{
Data: [4]float32{
1, 2,
3, 4,
Data: [2][2]float32{
{1, 3},
{2, 4},
}}
m2 := &gglm.Mat2{
Data: [4]float32{
5, 6,
7, 8,
Data: [2][2]float32{
{5, 7},
{6, 8},
}}
result := gglm.SubMat2(m1, m2)
@ -70,20 +70,20 @@ func TestSubMat2(t *testing.T) {
func TestAddMat2(t *testing.T) {
correctAns := gglm.Mat2{
Data: [4]float32{
6, 8,
10, 12,
Data: [2][2]float32{
{6, 10},
{8, 12},
}}
m1 := &gglm.Mat2{
Data: [4]float32{
1, 2,
3, 4,
Data: [2][2]float32{
{1, 3},
{2, 4},
}}
m2 := &gglm.Mat2{
Data: [4]float32{
5, 6,
7, 8,
Data: [2][2]float32{
{5, 7},
{6, 8},
}}
result := gglm.AddMat2(m1, m2)
@ -101,20 +101,20 @@ func TestAddMat2(t *testing.T) {
func TestMulMat2(t *testing.T) {
correctAns := gglm.Mat2{
Data: [4]float32{
19, 22,
43, 50,
Data: [2][2]float32{
{19, 43},
{22, 50},
}}
m1 := &gglm.Mat2{
Data: [4]float32{
1, 2,
3, 4,
Data: [2][2]float32{
{1, 3},
{2, 4},
}}
m2 := &gglm.Mat2{
Data: [4]float32{
5, 6,
7, 8,
Data: [2][2]float32{
{5, 7},
{6, 8},
}}
result := gglm.MulMat2(m1, m2)
@ -134,9 +134,9 @@ func TestMulMat2Vec2(t *testing.T) {
correctAns := gglm.Vec2{Data: [2]float32{5, 11}}
m := &gglm.Mat2{
Data: [4]float32{
1, 2,
3, 4,
Data: [2][2]float32{
{1, 3},
{2, 4},
}}
v := &gglm.Vec2{Data: [2]float32{1, 2}}
@ -146,3 +146,13 @@ func TestMulMat2Vec2(t *testing.T) {
t.Errorf("Got: %v; Expected: %v", result.String(), correctAns.String())
}
}
func BenchmarkMulMat2(b *testing.B) {
m1 := gglm.NewMat2Id()
m2 := gglm.NewMat2Id()
for i := 0; i < b.N; i++ {
m1.Mul(m2)
}
}

View File

@ -8,15 +8,15 @@ var _ Mat = &Mat3{}
var _ fmt.Stringer = &Mat3{}
type Mat3 struct {
Data [9]float32
Data [3][3]float32
}
func (m *Mat3) Get(row, col int) float32 {
return m.Data[row*3+col]
return m.Data[col][row]
}
func (m *Mat3) Set(row, col int, val float32) {
m.Data[row*3+col] = val
m.Data[col][row] = val
}
func (m *Mat3) Size() MatSize {
@ -25,66 +25,82 @@ func (m *Mat3) Size() MatSize {
func (m *Mat3) String() string {
return fmt.Sprintf("\n| %+-9.3f %+-9.3f %+-9.3f |\n| %+-9.3f %+-9.3f %+-9.3f |\n| %+-9.3f %+-9.3f %+-9.3f |\n",
m.Data[0], m.Data[1], m.Data[2],
m.Data[3], m.Data[4], m.Data[5],
m.Data[6], m.Data[7], m.Data[8],
m.Data[0][0], m.Data[0][1], m.Data[0][2],
m.Data[1][0], m.Data[1][1], m.Data[1][2],
m.Data[2][0], m.Data[2][1], m.Data[2][2],
)
}
//Add m += m2
func (m *Mat3) Add(m2 *Mat3) *Mat3 {
m.Data[0] += m2.Data[0]
m.Data[1] += m2.Data[1]
m.Data[2] += m2.Data[2]
m.Data[0][0] += m2.Data[0][0]
m.Data[0][1] += m2.Data[0][1]
m.Data[0][2] += m2.Data[0][2]
m.Data[3] += m2.Data[3]
m.Data[4] += m2.Data[4]
m.Data[5] += m2.Data[5]
m.Data[1][0] += m2.Data[1][0]
m.Data[1][1] += m2.Data[1][1]
m.Data[1][2] += m2.Data[1][2]
m.Data[6] += m2.Data[6]
m.Data[7] += m2.Data[7]
m.Data[8] += m2.Data[8]
m.Data[2][0] += m2.Data[2][0]
m.Data[2][1] += m2.Data[2][1]
m.Data[2][2] += m2.Data[2][2]
return m
}
//Add m -= m2
func (m *Mat3) Sub(m2 *Mat3) *Mat3 {
m.Data[0] -= m2.Data[0]
m.Data[1] -= m2.Data[1]
m.Data[2] -= m2.Data[2]
m.Data[0][0] -= m2.Data[0][0]
m.Data[0][1] -= m2.Data[0][1]
m.Data[0][2] -= m2.Data[0][2]
m.Data[3] -= m2.Data[3]
m.Data[4] -= m2.Data[4]
m.Data[5] -= m2.Data[5]
m.Data[1][0] -= m2.Data[1][0]
m.Data[1][1] -= m2.Data[1][1]
m.Data[1][2] -= m2.Data[1][2]
m.Data[6] -= m2.Data[6]
m.Data[7] -= m2.Data[7]
m.Data[8] -= m2.Data[8]
m.Data[2][0] -= m2.Data[2][0]
m.Data[2][1] -= m2.Data[2][1]
m.Data[2][2] -= m2.Data[2][2]
return m
}
//Mul m *= m2
func (m *Mat3) Mul(m2 *Mat3) *Mat3 {
//Indices:
// 0, 1, 2,
// 3, 4, 5,
// 6, 7, 8,
//Array indices:
// 00, 10, 20,
// 01, 11, 21,
// 02, 12, 22,
m.Data = [9]float32{
m.Data[0]*m2.Data[0] + m.Data[1]*m2.Data[3] + m.Data[2]*m2.Data[6],
m.Data[0]*m2.Data[1] + m.Data[1]*m2.Data[4] + m.Data[2]*m2.Data[7],
m.Data[0]*m2.Data[2] + m.Data[1]*m2.Data[5] + m.Data[2]*m2.Data[8],
m00 := m.Data[0][0]
m01 := m.Data[0][1]
m02 := m.Data[0][2]
m.Data[3]*m2.Data[0] + m.Data[4]*m2.Data[3] + m.Data[5]*m2.Data[6],
m.Data[3]*m2.Data[1] + m.Data[4]*m2.Data[4] + m.Data[5]*m2.Data[7],
m.Data[3]*m2.Data[2] + m.Data[4]*m2.Data[5] + m.Data[5]*m2.Data[8],
m10 := m.Data[1][0]
m11 := m.Data[1][1]
m12 := m.Data[1][2]
m.Data[6]*m2.Data[0] + m.Data[7]*m2.Data[3] + m.Data[8]*m2.Data[6],
m.Data[6]*m2.Data[1] + m.Data[7]*m2.Data[4] + m.Data[8]*m2.Data[7],
m.Data[6]*m2.Data[2] + m.Data[7]*m2.Data[5] + m.Data[8]*m2.Data[8],
m20 := m.Data[2][0]
m21 := m.Data[2][1]
m22 := m.Data[2][2]
m.Data = [3][3]float32{
{
m00*m2.Data[0][0] + m10*m2.Data[0][1] + m20*m2.Data[0][2],
m01*m2.Data[0][0] + m11*m2.Data[0][1] + m21*m2.Data[0][2],
m02*m2.Data[0][0] + m12*m2.Data[0][1] + m22*m2.Data[0][2],
},
{
m00*m2.Data[1][0] + m10*m2.Data[1][1] + m20*m2.Data[1][2],
m01*m2.Data[1][0] + m11*m2.Data[1][1] + m21*m2.Data[1][2],
m02*m2.Data[1][0] + m12*m2.Data[1][1] + m22*m2.Data[1][2],
},
{
m00*m2.Data[2][0] + m10*m2.Data[2][1] + m20*m2.Data[2][2],
m01*m2.Data[2][0] + m11*m2.Data[2][1] + m21*m2.Data[2][2],
m02*m2.Data[2][0] + m12*m2.Data[2][1] + m22*m2.Data[2][2],
},
}
return m
}
@ -92,17 +108,17 @@ func (m *Mat3) Mul(m2 *Mat3) *Mat3 {
//Scale m *= x (element wise multiplication)
func (m *Mat3) Scale(x float32) *Mat3 {
m.Data[0] *= x
m.Data[1] *= x
m.Data[2] *= x
m.Data[0][0] *= x
m.Data[0][1] *= x
m.Data[0][2] *= x
m.Data[3] *= x
m.Data[4] *= x
m.Data[5] *= x
m.Data[1][0] *= x
m.Data[1][1] *= x
m.Data[1][2] *= x
m.Data[6] *= x
m.Data[7] *= x
m.Data[8] *= x
m.Data[2][0] *= x
m.Data[2][1] *= x
m.Data[2][2] *= x
return m
}
@ -117,18 +133,22 @@ func (m *Mat3) Eq(m2 *Mat3) bool {
//AddMat3 m3 = m1 + m2
func AddMat3(m1, m2 *Mat3) *Mat3 {
return &Mat3{
Data: [9]float32{
m1.Data[0] + m2.Data[0],
m1.Data[1] + m2.Data[1],
m1.Data[2] + m2.Data[2],
m1.Data[3] + m2.Data[3],
m1.Data[4] + m2.Data[4],
m1.Data[5] + m2.Data[5],
m1.Data[6] + m2.Data[6],
m1.Data[7] + m2.Data[7],
m1.Data[8] + m2.Data[8],
Data: [3][3]float32{
{
m1.Data[0][0] + m2.Data[0][0],
m1.Data[0][1] + m2.Data[0][1],
m1.Data[0][2] + m2.Data[0][2],
},
{
m1.Data[1][0] + m2.Data[1][0],
m1.Data[1][1] + m2.Data[1][1],
m1.Data[1][2] + m2.Data[1][2],
},
{
m1.Data[2][0] + m2.Data[2][0],
m1.Data[2][1] + m2.Data[2][1],
m1.Data[2][2] + m2.Data[2][2],
},
},
}
}
@ -136,37 +156,58 @@ func AddMat3(m1, m2 *Mat3) *Mat3 {
//SubMat3 m3 = m1 - m2
func SubMat3(m1, m2 *Mat3) *Mat3 {
return &Mat3{
Data: [9]float32{
m1.Data[0] - m2.Data[0],
m1.Data[1] - m2.Data[1],
m1.Data[2] - m2.Data[2],
m1.Data[3] - m2.Data[3],
m1.Data[4] - m2.Data[4],
m1.Data[5] - m2.Data[5],
m1.Data[6] - m2.Data[6],
m1.Data[7] - m2.Data[7],
m1.Data[8] - m2.Data[8],
Data: [3][3]float32{
{
m1.Data[0][0] - m2.Data[0][0],
m1.Data[0][1] - m2.Data[0][1],
m1.Data[0][2] - m2.Data[0][2],
},
{
m1.Data[1][0] - m2.Data[1][0],
m1.Data[1][1] - m2.Data[1][1],
m1.Data[1][2] - m2.Data[1][2],
},
{
m1.Data[2][0] - m2.Data[2][0],
m1.Data[2][1] - m2.Data[2][1],
m1.Data[2][2] - m2.Data[2][2],
},
},
}
}
//MulMat3 m3 = m1 * m2
func MulMat3(m1, m2 *Mat3) *Mat3 {
m00 := m1.Data[0][0]
m01 := m1.Data[0][1]
m02 := m1.Data[0][2]
m10 := m1.Data[1][0]
m11 := m1.Data[1][1]
m12 := m1.Data[1][2]
m20 := m1.Data[2][0]
m21 := m1.Data[2][1]
m22 := m1.Data[2][2]
return &Mat3{
Data: [9]float32{
m1.Data[0]*m2.Data[0] + m1.Data[1]*m2.Data[3] + m1.Data[2]*m2.Data[6],
m1.Data[0]*m2.Data[1] + m1.Data[1]*m2.Data[4] + m1.Data[2]*m2.Data[7],
m1.Data[0]*m2.Data[2] + m1.Data[1]*m2.Data[5] + m1.Data[2]*m2.Data[8],
m1.Data[3]*m2.Data[0] + m1.Data[4]*m2.Data[3] + m1.Data[5]*m2.Data[6],
m1.Data[3]*m2.Data[1] + m1.Data[4]*m2.Data[4] + m1.Data[5]*m2.Data[7],
m1.Data[3]*m2.Data[2] + m1.Data[4]*m2.Data[5] + m1.Data[5]*m2.Data[8],
m1.Data[6]*m2.Data[0] + m1.Data[7]*m2.Data[3] + m1.Data[8]*m2.Data[6],
m1.Data[6]*m2.Data[1] + m1.Data[7]*m2.Data[4] + m1.Data[8]*m2.Data[7],
m1.Data[6]*m2.Data[2] + m1.Data[7]*m2.Data[5] + m1.Data[8]*m2.Data[8],
Data: [3][3]float32{
{
m00*m2.Data[0][0] + m10*m2.Data[0][1] + m20*m2.Data[0][2],
m01*m2.Data[0][0] + m11*m2.Data[0][1] + m21*m2.Data[0][2],
m02*m2.Data[0][0] + m12*m2.Data[0][1] + m22*m2.Data[0][2],
},
{
m00*m2.Data[1][0] + m10*m2.Data[1][1] + m20*m2.Data[1][2],
m01*m2.Data[1][0] + m11*m2.Data[1][1] + m21*m2.Data[1][2],
m02*m2.Data[1][0] + m12*m2.Data[1][1] + m22*m2.Data[1][2],
},
{
m00*m2.Data[2][0] + m10*m2.Data[2][1] + m20*m2.Data[2][2],
m01*m2.Data[2][0] + m11*m2.Data[2][1] + m21*m2.Data[2][2],
m02*m2.Data[2][0] + m12*m2.Data[2][1] + m22*m2.Data[2][2],
},
},
}
}
@ -175,9 +216,9 @@ func MulMat3(m1, m2 *Mat3) *Mat3 {
func MulMat3Vec3(m1 *Mat3, v1 *Vec3) *Vec3 {
return &Vec3{
Data: [3]float32{
m1.Data[0]*v1.Data[0] + m1.Data[1]*v1.Data[1] + m1.Data[2]*v1.Data[2],
m1.Data[3]*v1.Data[0] + m1.Data[4]*v1.Data[1] + m1.Data[5]*v1.Data[2],
m1.Data[6]*v1.Data[0] + m1.Data[7]*v1.Data[1] + m1.Data[8]*v1.Data[2],
m1.Data[0][0]*v1.Data[0] + m1.Data[1][0]*v1.Data[1] + m1.Data[2][0]*v1.Data[2],
m1.Data[0][1]*v1.Data[0] + m1.Data[1][1]*v1.Data[1] + m1.Data[2][1]*v1.Data[2],
m1.Data[0][2]*v1.Data[0] + m1.Data[1][2]*v1.Data[1] + m1.Data[2][2]*v1.Data[2],
},
}
}
@ -185,10 +226,10 @@ func MulMat3Vec3(m1 *Mat3, v1 *Vec3) *Vec3 {
//NewMat3Id returns the 3x3 identity matrix
func NewMat3Id() *Mat3 {
return &Mat3{
Data: [9]float32{
1, 0, 0,
0, 1, 0,
0, 0, 1,
Data: [3][3]float32{
{1, 0, 0},
{0, 1, 0},
{0, 0, 1},
},
}
}

View File

@ -30,10 +30,10 @@ func TestMat3GetSet(t *testing.T) {
func TestMat3Id(t *testing.T) {
correctAns := gglm.Mat3{
Data: [9]float32{
1, 0, 0,
0, 1, 0,
0, 0, 1,
Data: [3][3]float32{
{1, 0, 0},
{0, 1, 0},
{0, 0, 1},
}}
m1 := gglm.NewMat3Id()
@ -45,23 +45,23 @@ func TestMat3Id(t *testing.T) {
func TestSubMat3(t *testing.T) {
correctAns := gglm.Mat3{
Data: [9]float32{
-9, -9, -9,
-9, -9, -9,
-9, -9, -9,
Data: [3][3]float32{
{-9, -9, -9},
{-9, -9, -9},
{-9, -9, -9},
}}
m1 := &gglm.Mat3{
Data: [9]float32{
1, 2, 3,
4, 5, 6,
7, 8, 9,
Data: [3][3]float32{
{1, 4, 7},
{2, 5, 8},
{3, 6, 9},
}}
m2 := &gglm.Mat3{
Data: [9]float32{
10, 11, 12,
13, 14, 15,
16, 17, 18,
Data: [3][3]float32{
{10, 13, 16},
{11, 14, 17},
{12, 15, 18},
}}
result := gglm.SubMat3(m1, m2)
@ -79,23 +79,23 @@ func TestSubMat3(t *testing.T) {
func TestAddMat3(t *testing.T) {
correctAns := gglm.Mat3{
Data: [9]float32{
11, 13, 15,
17, 19, 21,
23, 25, 27,
Data: [3][3]float32{
{11, 17, 23},
{13, 19, 25},
{15, 21, 27},
}}
m1 := &gglm.Mat3{
Data: [9]float32{
1, 2, 3,
4, 5, 6,
7, 8, 9,
Data: [3][3]float32{
{1, 4, 7},
{2, 5, 8},
{3, 6, 9},
}}
m2 := &gglm.Mat3{
Data: [9]float32{
10, 11, 12,
13, 14, 15,
16, 17, 18,
Data: [3][3]float32{
{10, 13, 16},
{11, 14, 17},
{12, 15, 18},
}}
result := gglm.AddMat3(m1, m2)
@ -113,23 +113,23 @@ func TestAddMat3(t *testing.T) {
func TestMulMat3(t *testing.T) {
correctAns := gglm.Mat3{
Data: [9]float32{
84, 90, 96,
201, 216, 231,
318, 342, 366,
Data: [3][3]float32{
{84, 201, 318},
{90, 216, 342},
{96, 231, 366},
}}
m1 := &gglm.Mat3{
Data: [9]float32{
1, 2, 3,
4, 5, 6,
7, 8, 9,
Data: [3][3]float32{
{1, 4, 7},
{2, 5, 8},
{3, 6, 9},
}}
m2 := &gglm.Mat3{
Data: [9]float32{
10, 11, 12,
13, 14, 15,
16, 17, 18,
Data: [3][3]float32{
{10, 13, 16},
{11, 14, 17},
{12, 15, 18},
}}
result := gglm.MulMat3(m1, m2)
@ -147,10 +147,10 @@ func TestMulMat3(t *testing.T) {
func TestMulMat3Vec3(t *testing.T) {
m := &gglm.Mat3{
Data: [9]float32{
1, 2, 3,
4, 5, 6,
7, 8, 9,
Data: [3][3]float32{
{1, 4, 7},
{2, 5, 8},
{3, 6, 9},
}}
v := &gglm.Vec3{Data: [3]float32{1, 2, 3}}
@ -161,3 +161,13 @@ func TestMulMat3Vec3(t *testing.T) {
t.Errorf("Got: %v; Expected: %v", result.String(), correctAns.String())
}
}
func BenchmarkMulMat3(b *testing.B) {
m1 := gglm.NewMat3Id()
m2 := gglm.NewMat3Id()
for i := 0; i < b.N; i++ {
m1.Mul(m2)
}
}

View File

@ -8,15 +8,15 @@ var _ Mat = &Mat4{}
var _ fmt.Stringer = &Mat4{}
type Mat4 struct {
Data [16]float32
Data [4][4]float32
}
func (m *Mat4) Get(row, col int) float32 {
return m.Data[row*4+col]
return m.Data[col][row]
}
func (m *Mat4) Set(row, col int, val float32) {
m.Data[row*4+col] = val
m.Data[col][row] = val
}
func (m *Mat4) Size() MatSize {
@ -25,35 +25,35 @@ func (m *Mat4) Size() MatSize {
func (m *Mat4) String() string {
return fmt.Sprintf("\n| %+-9.3f %+-9.3f %+-9.3f %+-9.3f |\n| %+-9.3f %+-9.3f %+-9.3f %+-9.3f |\n| %+-9.3f %+-9.3f %+-9.3f %+-9.3f |\n| %+-9.3f %+-9.3f %+-9.3f %+-9.3f |\n",
m.Data[0], m.Data[1], m.Data[2], m.Data[3],
m.Data[4], m.Data[5], m.Data[6], m.Data[7],
m.Data[8], m.Data[9], m.Data[10], m.Data[11],
m.Data[12], m.Data[13], m.Data[14], m.Data[15],
m.Data[0][0], m.Data[0][1], m.Data[0][2], m.Data[0][3],
m.Data[1][0], m.Data[1][1], m.Data[1][2], m.Data[1][3],
m.Data[2][0], m.Data[2][1], m.Data[2][2], m.Data[2][3],
m.Data[3][0], m.Data[3][1], m.Data[3][2], m.Data[3][3],
)
}
//Add m += m2
func (m *Mat4) Add(m2 *Mat4) *Mat4 {
m.Data[0] += m2.Data[0]
m.Data[1] += m2.Data[1]
m.Data[2] += m2.Data[2]
m.Data[3] += m2.Data[3]
m.Data[0][0] += m2.Data[0][0]
m.Data[0][1] += m2.Data[0][1]
m.Data[0][2] += m2.Data[0][2]
m.Data[0][3] += m2.Data[0][3]
m.Data[4] += m2.Data[4]
m.Data[5] += m2.Data[5]
m.Data[6] += m2.Data[6]
m.Data[7] += m2.Data[7]
m.Data[1][0] += m2.Data[1][0]
m.Data[1][1] += m2.Data[1][1]
m.Data[1][2] += m2.Data[1][2]
m.Data[1][3] += m2.Data[1][3]
m.Data[8] += m2.Data[8]
m.Data[9] += m2.Data[9]
m.Data[10] += m2.Data[10]
m.Data[11] += m2.Data[11]
m.Data[2][0] += m2.Data[2][0]
m.Data[2][1] += m2.Data[2][1]
m.Data[2][2] += m2.Data[2][2]
m.Data[2][3] += m2.Data[2][3]
m.Data[12] += m2.Data[12]
m.Data[13] += m2.Data[13]
m.Data[14] += m2.Data[14]
m.Data[15] += m2.Data[15]
m.Data[3][0] += m2.Data[3][0]
m.Data[3][1] += m2.Data[3][1]
m.Data[3][2] += m2.Data[3][2]
m.Data[3][3] += m2.Data[3][3]
return m
}
@ -61,64 +61,83 @@ func (m *Mat4) Add(m2 *Mat4) *Mat4 {
//Add m -= m2
func (m *Mat4) Sub(m2 *Mat4) *Mat4 {
m.Data[0] -= m2.Data[0]
m.Data[1] -= m2.Data[1]
m.Data[2] -= m2.Data[2]
m.Data[3] -= m2.Data[3]
m.Data[0][0] -= m2.Data[0][0]
m.Data[0][1] -= m2.Data[0][1]
m.Data[0][2] -= m2.Data[0][2]
m.Data[0][3] -= m2.Data[0][3]
m.Data[4] -= m2.Data[4]
m.Data[5] -= m2.Data[5]
m.Data[6] -= m2.Data[6]
m.Data[7] -= m2.Data[7]
m.Data[1][0] -= m2.Data[1][0]
m.Data[1][1] -= m2.Data[1][1]
m.Data[1][2] -= m2.Data[1][2]
m.Data[1][3] -= m2.Data[1][3]
m.Data[8] -= m2.Data[8]
m.Data[9] -= m2.Data[9]
m.Data[10] -= m2.Data[10]
m.Data[11] -= m2.Data[11]
m.Data[2][0] -= m2.Data[2][0]
m.Data[2][1] -= m2.Data[2][1]
m.Data[2][2] -= m2.Data[2][2]
m.Data[2][3] -= m2.Data[2][3]
m.Data[12] -= m2.Data[12]
m.Data[13] -= m2.Data[13]
m.Data[14] -= m2.Data[14]
m.Data[15] -= m2.Data[15]
m.Data[3][0] -= m2.Data[3][0]
m.Data[3][1] -= m2.Data[3][1]
m.Data[3][2] -= m2.Data[3][2]
m.Data[3][3] -= m2.Data[3][3]
return m
}
//Mul m *= m2
func (m *Mat4) Mul(m2 *Mat4) *Mat4 {
//Indices:
// 00, 01, 02, 03,
// 04, 05, 06, 07,
// 08, 09, 10, 11,
// 12, 13, 14, 15,
//Array indices:
// 00, 10, 20, 30,
// 01, 11, 21, 31,
// 02, 12, 22, 32,
// 03, 13, 23, 33,
//Seems to improve performance by ~5% (18ns/op -> 17ns/op).
//Works by improving cache usage by putting 0,4,8,12 together instead of faraway in the array?
a := m2.Data[0]
b := m2.Data[4]
c := m2.Data[8]
d := m2.Data[12]
//Improves performance by ~8%
m00 := m.Data[0][0]
m01 := m.Data[0][1]
m02 := m.Data[0][2]
m03 := m.Data[0][3]
m.Data = [16]float32{
m.Data[0]*a + m.Data[1]*b + m.Data[2]*c + m.Data[3]*d,
m.Data[0]*m2.Data[1] + m.Data[1]*m2.Data[5] + m.Data[2]*m2.Data[9] + m.Data[3]*m2.Data[13],
m.Data[0]*m2.Data[2] + m.Data[1]*m2.Data[6] + m.Data[2]*m2.Data[10] + m.Data[3]*m2.Data[14],
m.Data[0]*m2.Data[3] + m.Data[1]*m2.Data[7] + m.Data[2]*m2.Data[11] + m.Data[3]*m2.Data[15],
m10 := m.Data[1][0]
m11 := m.Data[1][1]
m12 := m.Data[1][2]
m13 := m.Data[1][3]
m.Data[4]*a + m.Data[5]*b + m.Data[6]*c + m.Data[7]*d,
m.Data[4]*m2.Data[1] + m.Data[5]*m2.Data[5] + m.Data[6]*m2.Data[9] + m.Data[7]*m2.Data[13],
m.Data[4]*m2.Data[2] + m.Data[5]*m2.Data[6] + m.Data[6]*m2.Data[10] + m.Data[7]*m2.Data[14],
m.Data[4]*m2.Data[3] + m.Data[5]*m2.Data[7] + m.Data[6]*m2.Data[11] + m.Data[7]*m2.Data[15],
m20 := m.Data[2][0]
m21 := m.Data[2][1]
m22 := m.Data[2][2]
m23 := m.Data[2][3]
m.Data[8]*a + m.Data[9]*b + m.Data[10]*c + m.Data[11]*d,
m.Data[8]*m2.Data[1] + m.Data[9]*m2.Data[5] + m.Data[10]*m2.Data[9] + m.Data[11]*m2.Data[13],
m.Data[8]*m2.Data[2] + m.Data[9]*m2.Data[6] + m.Data[10]*m2.Data[10] + m.Data[11]*m2.Data[14],
m.Data[8]*m2.Data[3] + m.Data[9]*m2.Data[7] + m.Data[10]*m2.Data[11] + m.Data[11]*m2.Data[15],
m30 := m.Data[3][0]
m31 := m.Data[3][1]
m32 := m.Data[3][2]
m33 := m.Data[3][3]
m.Data[12]*a + m.Data[13]*b + m.Data[14]*c + m.Data[15]*d,
m.Data[12]*m2.Data[1] + m.Data[13]*m2.Data[5] + m.Data[14]*m2.Data[9] + m.Data[15]*m2.Data[13],
m.Data[12]*m2.Data[2] + m.Data[13]*m2.Data[6] + m.Data[14]*m2.Data[10] + m.Data[15]*m2.Data[14],
m.Data[12]*m2.Data[3] + m.Data[13]*m2.Data[7] + m.Data[14]*m2.Data[11] + m.Data[15]*m2.Data[15],
m.Data = [4][4]float32{
{
m00*m2.Data[0][0] + m10*m2.Data[0][1] + m20*m2.Data[0][2] + m30*m2.Data[0][3],
m01*m2.Data[0][0] + m11*m2.Data[0][1] + m21*m2.Data[0][2] + m31*m2.Data[0][3],
m02*m2.Data[0][0] + m12*m2.Data[0][1] + m22*m2.Data[0][2] + m32*m2.Data[0][3],
m03*m2.Data[0][0] + m13*m2.Data[0][1] + m23*m2.Data[0][2] + m33*m2.Data[0][3],
},
{
m00*m2.Data[1][0] + m10*m2.Data[1][1] + m20*m2.Data[1][2] + m30*m2.Data[1][3],
m01*m2.Data[1][0] + m11*m2.Data[1][1] + m21*m2.Data[1][2] + m31*m2.Data[1][3],
m02*m2.Data[1][0] + m12*m2.Data[1][1] + m22*m2.Data[1][2] + m32*m2.Data[1][3],
m03*m2.Data[1][0] + m13*m2.Data[1][1] + m23*m2.Data[1][2] + m33*m2.Data[1][3],
},
{
m00*m2.Data[2][0] + m10*m2.Data[2][1] + m20*m2.Data[2][2] + m30*m2.Data[2][3],
m01*m2.Data[2][0] + m11*m2.Data[2][1] + m21*m2.Data[2][2] + m31*m2.Data[2][3],
m02*m2.Data[2][0] + m12*m2.Data[2][1] + m22*m2.Data[2][2] + m32*m2.Data[2][3],
m03*m2.Data[2][0] + m13*m2.Data[2][1] + m23*m2.Data[2][2] + m33*m2.Data[2][3],
},
{
m00*m2.Data[3][0] + m10*m2.Data[3][1] + m20*m2.Data[3][2] + m30*m2.Data[3][3],
m01*m2.Data[3][0] + m11*m2.Data[3][1] + m21*m2.Data[3][2] + m31*m2.Data[3][3],
m02*m2.Data[3][0] + m12*m2.Data[3][1] + m22*m2.Data[3][2] + m32*m2.Data[3][3],
m03*m2.Data[3][0] + m13*m2.Data[3][1] + m23*m2.Data[3][2] + m33*m2.Data[3][3],
},
}
return m
@ -127,25 +146,25 @@ func (m *Mat4) Mul(m2 *Mat4) *Mat4 {
//Scale m *= x (element wise multiplication)
func (m *Mat4) Scale(x float32) *Mat4 {
m.Data[0] *= x
m.Data[1] *= x
m.Data[2] *= x
m.Data[3] *= x
m.Data[0][0] *= x
m.Data[0][1] *= x
m.Data[0][2] *= x
m.Data[0][3] *= x
m.Data[4] *= x
m.Data[5] *= x
m.Data[6] *= x
m.Data[7] *= x
m.Data[1][0] *= x
m.Data[1][1] *= x
m.Data[1][2] *= x
m.Data[1][3] *= x
m.Data[8] *= x
m.Data[9] *= x
m.Data[10] *= x
m.Data[11] *= x
m.Data[2][0] *= x
m.Data[2][1] *= x
m.Data[2][2] *= x
m.Data[2][3] *= x
m.Data[12] *= x
m.Data[13] *= x
m.Data[14] *= x
m.Data[15] *= x
m.Data[3][0] *= x
m.Data[3][1] *= x
m.Data[3][2] *= x
m.Data[3][3] *= x
return m
}
@ -160,26 +179,31 @@ func (m *Mat4) Eq(m2 *Mat4) bool {
//AddMat4 m3 = m1 + m2
func AddMat4(m1, m2 *Mat4) *Mat4 {
return &Mat4{
Data: [16]float32{
m1.Data[0] + m2.Data[0],
m1.Data[1] + m2.Data[1],
m1.Data[2] + m2.Data[2],
m1.Data[3] + m2.Data[3],
m1.Data[4] + m2.Data[4],
m1.Data[5] + m2.Data[5],
m1.Data[6] + m2.Data[6],
m1.Data[7] + m2.Data[7],
m1.Data[8] + m2.Data[8],
m1.Data[9] + m2.Data[9],
m1.Data[10] + m2.Data[10],
m1.Data[11] + m2.Data[11],
m1.Data[12] + m2.Data[12],
m1.Data[13] + m2.Data[13],
m1.Data[14] + m2.Data[14],
m1.Data[15] + m2.Data[15],
Data: [4][4]float32{
{
m1.Data[0][0] + m2.Data[0][0],
m1.Data[0][1] + m2.Data[0][1],
m1.Data[0][2] + m2.Data[0][2],
m1.Data[0][3] + m2.Data[0][3],
},
{
m1.Data[1][0] + m2.Data[1][0],
m1.Data[1][1] + m2.Data[1][1],
m1.Data[1][2] + m2.Data[1][2],
m1.Data[1][3] + m2.Data[1][3],
},
{
m1.Data[2][0] + m2.Data[2][0],
m1.Data[2][1] + m2.Data[2][1],
m1.Data[2][2] + m2.Data[2][2],
m1.Data[2][3] + m2.Data[2][3],
},
{
m1.Data[3][0] + m2.Data[3][0],
m1.Data[3][1] + m2.Data[3][1],
m1.Data[3][2] + m2.Data[3][2],
m1.Data[3][3] + m2.Data[3][3],
},
},
}
}
@ -187,26 +211,31 @@ func AddMat4(m1, m2 *Mat4) *Mat4 {
//SubMat4 m3 = m1 - m2
func SubMat4(m1, m2 *Mat4) *Mat4 {
return &Mat4{
Data: [16]float32{
m1.Data[0] - m2.Data[0],
m1.Data[1] - m2.Data[1],
m1.Data[2] - m2.Data[2],
m1.Data[3] - m2.Data[3],
m1.Data[4] - m2.Data[4],
m1.Data[5] - m2.Data[5],
m1.Data[6] - m2.Data[6],
m1.Data[7] - m2.Data[7],
m1.Data[8] - m2.Data[8],
m1.Data[9] - m2.Data[9],
m1.Data[10] - m2.Data[10],
m1.Data[11] - m2.Data[11],
m1.Data[12] - m2.Data[12],
m1.Data[13] - m2.Data[13],
m1.Data[14] - m2.Data[14],
m1.Data[15] - m2.Data[15],
Data: [4][4]float32{
{
m1.Data[0][0] - m2.Data[0][0],
m1.Data[0][1] - m2.Data[0][1],
m1.Data[0][2] - m2.Data[0][2],
m1.Data[0][3] - m2.Data[0][3],
},
{
m1.Data[1][0] - m2.Data[1][0],
m1.Data[1][1] - m2.Data[1][1],
m1.Data[1][2] - m2.Data[1][2],
m1.Data[1][3] - m2.Data[1][3],
},
{
m1.Data[2][0] - m2.Data[2][0],
m1.Data[2][1] - m2.Data[2][1],
m1.Data[2][2] - m2.Data[2][2],
m1.Data[2][3] - m2.Data[2][3],
},
{
m1.Data[3][0] - m2.Data[3][0],
m1.Data[3][1] - m2.Data[3][1],
m1.Data[3][2] - m2.Data[3][2],
m1.Data[3][3] - m2.Data[3][3],
},
},
}
}
@ -214,32 +243,52 @@ func SubMat4(m1, m2 *Mat4) *Mat4 {
//MulMat4 m3 = m1 * m2
func MulMat4(m1, m2 *Mat4) *Mat4 {
a := m2.Data[0]
b := m2.Data[4]
c := m2.Data[8]
d := m2.Data[12]
m00 := m1.Data[0][0]
m01 := m1.Data[0][1]
m02 := m1.Data[0][2]
m03 := m1.Data[0][3]
m10 := m1.Data[1][0]
m11 := m1.Data[1][1]
m12 := m1.Data[1][2]
m13 := m1.Data[1][3]
m20 := m1.Data[2][0]
m21 := m1.Data[2][1]
m22 := m1.Data[2][2]
m23 := m1.Data[2][3]
m30 := m1.Data[3][0]
m31 := m1.Data[3][1]
m32 := m1.Data[3][2]
m33 := m1.Data[3][3]
return &Mat4{
Data: [16]float32{
m1.Data[0]*a + m1.Data[1]*b + m1.Data[2]*c + m1.Data[3]*d,
m1.Data[0]*m2.Data[1] + m1.Data[1]*m2.Data[5] + m1.Data[2]*m2.Data[9] + m1.Data[3]*m2.Data[13],
m1.Data[0]*m2.Data[2] + m1.Data[1]*m2.Data[6] + m1.Data[2]*m2.Data[10] + m1.Data[3]*m2.Data[14],
m1.Data[0]*m2.Data[3] + m1.Data[1]*m2.Data[7] + m1.Data[2]*m2.Data[11] + m1.Data[3]*m2.Data[15],
m1.Data[4]*a + m1.Data[5]*b + m1.Data[6]*c + m1.Data[7]*d,
m1.Data[4]*m2.Data[1] + m1.Data[5]*m2.Data[5] + m1.Data[6]*m2.Data[9] + m1.Data[7]*m2.Data[13],
m1.Data[4]*m2.Data[2] + m1.Data[5]*m2.Data[6] + m1.Data[6]*m2.Data[10] + m1.Data[7]*m2.Data[14],
m1.Data[4]*m2.Data[3] + m1.Data[5]*m2.Data[7] + m1.Data[6]*m2.Data[11] + m1.Data[7]*m2.Data[15],
m1.Data[8]*a + m1.Data[9]*b + m1.Data[10]*c + m1.Data[11]*d,
m1.Data[8]*m2.Data[1] + m1.Data[9]*m2.Data[5] + m1.Data[10]*m2.Data[9] + m1.Data[11]*m2.Data[13],
m1.Data[8]*m2.Data[2] + m1.Data[9]*m2.Data[6] + m1.Data[10]*m2.Data[10] + m1.Data[11]*m2.Data[14],
m1.Data[8]*m2.Data[3] + m1.Data[9]*m2.Data[7] + m1.Data[10]*m2.Data[11] + m1.Data[11]*m2.Data[15],
m1.Data[12]*a + m1.Data[13]*b + m1.Data[14]*c + m1.Data[15]*d,
m1.Data[12]*m2.Data[1] + m1.Data[13]*m2.Data[5] + m1.Data[14]*m2.Data[9] + m1.Data[15]*m2.Data[13],
m1.Data[12]*m2.Data[2] + m1.Data[13]*m2.Data[6] + m1.Data[14]*m2.Data[10] + m1.Data[15]*m2.Data[14],
m1.Data[12]*m2.Data[3] + m1.Data[13]*m2.Data[7] + m1.Data[14]*m2.Data[11] + m1.Data[15]*m2.Data[15],
Data: [4][4]float32{
{
m00*m2.Data[0][0] + m10*m2.Data[0][1] + m20*m2.Data[0][2] + m30*m2.Data[0][3],
m01*m2.Data[0][0] + m11*m2.Data[0][1] + m21*m2.Data[0][2] + m31*m2.Data[0][3],
m02*m2.Data[0][0] + m12*m2.Data[0][1] + m22*m2.Data[0][2] + m32*m2.Data[0][3],
m03*m2.Data[0][0] + m13*m2.Data[0][1] + m23*m2.Data[0][2] + m33*m2.Data[0][3],
},
{
m00*m2.Data[1][0] + m10*m2.Data[1][1] + m20*m2.Data[1][2] + m30*m2.Data[1][3],
m01*m2.Data[1][0] + m11*m2.Data[1][1] + m21*m2.Data[1][2] + m31*m2.Data[1][3],
m02*m2.Data[1][0] + m12*m2.Data[1][1] + m22*m2.Data[1][2] + m32*m2.Data[1][3],
m03*m2.Data[1][0] + m13*m2.Data[1][1] + m23*m2.Data[1][2] + m33*m2.Data[1][3],
},
{
m00*m2.Data[2][0] + m10*m2.Data[2][1] + m20*m2.Data[2][2] + m30*m2.Data[2][3],
m01*m2.Data[2][0] + m11*m2.Data[2][1] + m21*m2.Data[2][2] + m31*m2.Data[2][3],
m02*m2.Data[2][0] + m12*m2.Data[2][1] + m22*m2.Data[2][2] + m32*m2.Data[2][3],
m03*m2.Data[2][0] + m13*m2.Data[2][1] + m23*m2.Data[2][2] + m33*m2.Data[2][3],
},
{
m00*m2.Data[3][0] + m10*m2.Data[3][1] + m20*m2.Data[3][2] + m30*m2.Data[3][3],
m01*m2.Data[3][0] + m11*m2.Data[3][1] + m21*m2.Data[3][2] + m31*m2.Data[3][3],
m02*m2.Data[3][0] + m12*m2.Data[3][1] + m22*m2.Data[3][2] + m32*m2.Data[3][3],
m03*m2.Data[3][0] + m13*m2.Data[3][1] + m23*m2.Data[3][2] + m33*m2.Data[3][3],
},
},
}
}
@ -248,10 +297,10 @@ func MulMat4(m1, m2 *Mat4) *Mat4 {
func MulMat4Vec4(m1 *Mat4, v1 *Vec4) *Vec4 {
return &Vec4{
Data: [4]float32{
m1.Data[0]*v1.Data[0] + m1.Data[1]*v1.Data[1] + m1.Data[2]*v1.Data[2] + m1.Data[3]*v1.Data[3],
m1.Data[4]*v1.Data[0] + m1.Data[5]*v1.Data[1] + m1.Data[6]*v1.Data[2] + m1.Data[7]*v1.Data[3],
m1.Data[8]*v1.Data[0] + m1.Data[9]*v1.Data[1] + m1.Data[10]*v1.Data[2] + m1.Data[11]*v1.Data[3],
m1.Data[12]*v1.Data[0] + m1.Data[13]*v1.Data[1] + m1.Data[14]*v1.Data[2] + m1.Data[15]*v1.Data[3],
m1.Data[0][0]*v1.Data[0] + m1.Data[1][0]*v1.Data[1] + m1.Data[2][0]*v1.Data[2] + m1.Data[3][0]*v1.Data[3],
m1.Data[0][1]*v1.Data[0] + m1.Data[1][1]*v1.Data[1] + m1.Data[2][1]*v1.Data[2] + m1.Data[3][1]*v1.Data[3],
m1.Data[0][2]*v1.Data[0] + m1.Data[1][2]*v1.Data[1] + m1.Data[2][2]*v1.Data[2] + m1.Data[3][2]*v1.Data[3],
m1.Data[0][3]*v1.Data[0] + m1.Data[1][3]*v1.Data[1] + m1.Data[2][3]*v1.Data[2] + m1.Data[3][3]*v1.Data[3],
},
}
}
@ -259,11 +308,11 @@ func MulMat4Vec4(m1 *Mat4, v1 *Vec4) *Vec4 {
//NewMat4Id returns the 4x4 identity matrix
func NewMat4Id() *Mat4 {
return &Mat4{
Data: [16]float32{
1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
0, 0, 0, 1,
Data: [4][4]float32{
{1, 0, 0, 0},
{0, 1, 0, 0},
{0, 0, 1, 0},
{0, 0, 0, 1},
},
}
}

View File

@ -6,6 +6,10 @@ import (
"github.com/bloeys/gglm/gglm"
)
var (
mulMat4Vec4Res *gglm.Vec4
)
func TestMat4GetSet(t *testing.T) {
m1 := gglm.Mat4{}
@ -35,11 +39,11 @@ func TestMat4GetSet(t *testing.T) {
func TestMat4Id(t *testing.T) {
correctAns := gglm.Mat4{
Data: [16]float32{
1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
0, 0, 0, 1,
Data: [4][4]float32{
{1, 0, 0, 0},
{0, 1, 0, 0},
{0, 0, 1, 0},
{0, 0, 0, 1},
}}
m1 := gglm.NewMat4Id()
@ -51,26 +55,26 @@ func TestMat4Id(t *testing.T) {
func TestSubMat4(t *testing.T) {
correctAns := gglm.Mat4{
Data: [16]float32{
-16, -16, -16, -16,
-16, -16, -16, -16,
-16, -16, -16, -16,
-16, -16, -16, -16,
Data: [4][4]float32{
{-16, -16, -16, -16},
{-16, -16, -16, -16},
{-16, -16, -16, -16},
{-16, -16, -16, -16},
}}
m1 := &gglm.Mat4{
Data: [16]float32{
1, 2, 3, 4,
5, 6, 7, 8,
9, 10, 11, 12,
13, 14, 15, 16,
Data: [4][4]float32{
{1, 5, 9, 13},
{2, 6, 10, 14},
{3, 7, 11, 15},
{4, 8, 12, 16},
}}
m2 := &gglm.Mat4{
Data: [16]float32{
17, 18, 19, 20,
21, 22, 23, 24,
25, 26, 27, 28,
29, 30, 31, 32,
Data: [4][4]float32{
{17, 21, 25, 29},
{18, 22, 26, 30},
{19, 23, 27, 31},
{20, 24, 28, 32},
}}
result := gglm.SubMat4(m1, m2)
@ -88,26 +92,26 @@ func TestSubMat4(t *testing.T) {
func TestAddMat4(t *testing.T) {
correctAns := gglm.Mat4{
Data: [16]float32{
18, 20, 22, 24,
26, 28, 30, 32,
34, 36, 38, 40,
42, 44, 46, 48,
Data: [4][4]float32{
{18, 26, 34, 42},
{20, 28, 36, 44},
{22, 30, 38, 46},
{24, 32, 40, 48},
}}
m1 := &gglm.Mat4{
Data: [16]float32{
1, 2, 3, 4,
5, 6, 7, 8,
9, 10, 11, 12,
13, 14, 15, 16,
Data: [4][4]float32{
{1, 5, 9, 13},
{2, 6, 10, 14},
{3, 7, 11, 15},
{4, 8, 12, 16},
}}
m2 := &gglm.Mat4{
Data: [16]float32{
17, 18, 19, 20,
21, 22, 23, 24,
25, 26, 27, 28,
29, 30, 31, 32,
Data: [4][4]float32{
{17, 21, 25, 29},
{18, 22, 26, 30},
{19, 23, 27, 31},
{20, 24, 28, 32},
}}
result := gglm.AddMat4(m1, m2)
@ -125,26 +129,26 @@ func TestAddMat4(t *testing.T) {
func TestMulMat4(t *testing.T) {
correctAns := gglm.Mat4{
Data: [16]float32{
250, 260, 270, 280,
618, 644, 670, 696,
986, 1028, 1070, 1112,
1354, 1412, 1470, 1528,
Data: [4][4]float32{
{250, 618, 986, 1354},
{260, 644, 1028, 1412},
{270, 670, 1070, 1470},
{280, 696, 1112, 1528},
}}
m1 := &gglm.Mat4{
Data: [16]float32{
1, 2, 3, 4,
5, 6, 7, 8,
9, 10, 11, 12,
13, 14, 15, 16,
Data: [4][4]float32{
{1, 5, 9, 13},
{2, 6, 10, 14},
{3, 7, 11, 15},
{4, 8, 12, 16},
}}
m2 := &gglm.Mat4{
Data: [16]float32{
17, 18, 19, 20,
21, 22, 23, 24,
25, 26, 27, 28,
29, 30, 31, 32,
Data: [4][4]float32{
{17, 21, 25, 29},
{18, 22, 26, 30},
{19, 23, 27, 31},
{20, 24, 28, 32},
}}
result := gglm.MulMat4(m1, m2)
@ -162,11 +166,11 @@ func TestMulMat4(t *testing.T) {
func TestMulMat4Vec4(t *testing.T) {
m := &gglm.Mat4{
Data: [16]float32{
1, 2, 3, 4,
5, 6, 7, 8,
9, 10, 11, 12,
13, 14, 15, 16,
Data: [4][4]float32{
{1, 5, 9, 13},
{2, 6, 10, 14},
{3, 7, 11, 15},
{4, 8, 12, 16},
}}
v := &gglm.Vec4{Data: [4]float32{1, 2, 3, 4}}
@ -177,3 +181,23 @@ func TestMulMat4Vec4(t *testing.T) {
t.Errorf("Got: %v; Expected: %v", result.String(), correctAns.String())
}
}
func BenchmarkMulMat4(b *testing.B) {
m1 := gglm.NewMat4Id()
m2 := gglm.NewMat4Id()
for i := 0; i < b.N; i++ {
m1.Mul(m2)
}
}
func BenchmarkMulMat4Vec4(b *testing.B) {
m1 := gglm.NewMat4Id()
v1 := gglm.Vec4{}
for i := 0; i < b.N; i++ {
mulMat4Vec4Res = gglm.MulMat4Vec4(m1, &v1)
}
}

View File

@ -1,6 +1,9 @@
package gglm
import "fmt"
import (
"fmt"
"math"
)
var _ Mat = &TrMat{}
var _ fmt.Stringer = &TrMat{}
@ -12,16 +15,16 @@ type TrMat struct {
//Translate adds the vector to the translation components of the transformation matrix
func (t *TrMat) Translate(v *Vec3) {
t.Data[3] += v.Data[0]
t.Data[7] += v.Data[1]
t.Data[11] += v.Data[2]
t.Data[3][0] += v.Data[0]
t.Data[3][1] += v.Data[1]
t.Data[3][2] += v.Data[2]
}
//Scale multiplies the vector by the scale components of the transformation matrix
func (t *TrMat) Scale(v *Vec3) {
t.Data[0] *= v.Data[0]
t.Data[5] *= v.Data[1]
t.Data[10] *= v.Data[2]
t.Data[0][0] *= v.Data[0]
t.Data[1][1] *= v.Data[1]
t.Data[2][2] *= v.Data[2]
}
func (t *TrMat) Mul(m *TrMat) *TrMat {
@ -42,11 +45,11 @@ func (t *TrMat) Clone() *TrMat {
func NewTranslationMat(v *Vec3) *TrMat {
return &TrMat{
Mat4: Mat4{
Data: [16]float32{
1, 0, 0, v.Data[0],
0, 1, 0, v.Data[1],
0, 0, 1, v.Data[2],
0, 0, 0, 1,
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},
},
},
}
@ -55,11 +58,11 @@ func NewTranslationMat(v *Vec3) *TrMat {
func NewScaleMat(v *Vec3) *TrMat {
return &TrMat{
Mat4: Mat4{
Data: [16]float32{
v.Data[0], 0, 0, 0,
0, v.Data[1], 0, 0,
0, 0, v.Data[2], 0,
0, 0, 0, 1,
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},
},
},
}
@ -86,11 +89,56 @@ func NewRotMat(q *Quat) *TrMat {
return &TrMat{
Mat4: Mat4{
Data: [16]float32{
2*(ww+xx) - 1, 2 * (xy - zw), 2 * (yw + xz), 0,
2 * (zw + xy), 2*(ww+yy) - 1, 2 * (yz - xw), 0,
2 * (xz - yw), 2 * (xw + yz), 2*(ww+zz) - 1, 0,
0, 0, 0, 1,
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},
},
},
}
}
func LookAt(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},
},
},
}

View File

@ -11,11 +11,11 @@ func TestNewTrMatId(t *testing.T) {
m := gglm.NewTrMatId()
ans := &gglm.TrMat{
Mat4: gglm.Mat4{
Data: [16]float32{
1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
0, 0, 0, 1,
Data: [4][4]float32{
{1, 0, 0, 0},
{0, 1, 0, 0},
{0, 0, 1, 0},
{0, 0, 0, 1},
},
},
}
@ -30,11 +30,11 @@ func TestNewTranslationMat(t *testing.T) {
m := gglm.NewTranslationMat(gglm.NewVec3(1, 2, 3))
ans := &gglm.TrMat{
Mat4: gglm.Mat4{
Data: [16]float32{
1, 0, 0, 1,
0, 1, 0, 2,
0, 0, 1, 3,
0, 0, 0, 1,
Data: [4][4]float32{
{1, 0, 0, 0},
{0, 1, 0, 0},
{0, 0, 1, 0},
{1, 2, 3, 1},
},
},
}
@ -49,11 +49,11 @@ func TestNewScaleMat(t *testing.T) {
m := gglm.NewScaleMat(gglm.NewVec3(1, 2, 3))
ans := &gglm.TrMat{
Mat4: gglm.Mat4{
Data: [16]float32{
1, 0, 0, 0,
0, 2, 0, 0,
0, 0, 3, 0,
0, 0, 0, 1,
Data: [4][4]float32{
{1, 0, 0, 0},
{0, 2, 0, 0},
{0, 0, 3, 0},
{0, 0, 0, 1},
},
},
}
@ -68,11 +68,11 @@ func TestNewRotMat(t *testing.T) {
m := gglm.NewRotMat(gglm.NewQuatId())
ans := &gglm.TrMat{
Mat4: gglm.Mat4{
Data: [16]float32{
1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
0, 0, 0, 1,
Data: [4][4]float32{
{1, 0, 0, 0},
{0, 1, 0, 0},
{0, 0, 1, 0},
{0, 0, 0, 1},
},
},
}

82
main.go
View File

@ -1,23 +1,27 @@
package main
import "github.com/bloeys/gglm/gglm"
import (
"fmt"
"github.com/bloeys/gglm/gglm"
)
func main() {
//Mat3
m1 := &gglm.Mat3{
Data: [9]float32{
1, 2, 3,
4, 5, 6,
7, 8, 9,
Data: [3][3]float32{
{1, 4, 7},
{2, 5, 8},
{3, 6, 9},
},
}
m2 := &gglm.Mat3{
Data: [9]float32{
1, 2, 3,
1, 2, 3,
1, 2, 3,
Data: [3][3]float32{
{1, 1, 1},
{2, 2, 2},
{3, 3, 3},
},
}
@ -28,20 +32,20 @@ func main() {
//Mat4
m4 := &gglm.Mat4{
Data: [16]float32{
1, 2, 3, 4,
5, 6, 7, 8,
9, 10, 11, 12,
13, 14, 15, 16,
Data: [4][4]float32{
{1, 5, 9, 13},
{2, 6, 10, 14},
{3, 7, 11, 15},
{4, 8, 12, 16},
},
}
m5 := &gglm.Mat4{
Data: [16]float32{
1, 2, 3, 4,
1, 2, 3, 4,
1, 2, 3, 4,
1, 2, 3, 4,
Data: [4][4]float32{
{1, 2, 3, 4},
{1, 2, 3, 4},
{1, 2, 3, 4},
{1, 2, 3, 4},
},
}
@ -99,9 +103,9 @@ func main() {
//Mat2Vec2
mat2A := gglm.Mat2{
Data: [4]float32{
1, 2,
3, 4,
Data: [2][2]float32{
{1, 3},
{2, 4},
},
}
@ -110,10 +114,10 @@ func main() {
//Mat3Vec3
mat3A := gglm.Mat3{
Data: [9]float32{
1, 2, 3,
4, 5, 6,
7, 8, 9,
Data: [3][3]float32{
{1, 4, 7},
{2, 5, 8},
{3, 6, 9},
},
}
@ -164,4 +168,30 @@ func main() {
q1 := gglm.NewQuatEuler(gglm.NewVec3(180, 0, 0).AsRad())
q2 := gglm.NewQuatEuler(gglm.NewVec3(0, 180, 0).AsRad())
println(gglm.AngleQuat(q1, q2) * gglm.Rad2Deg)
//LookAt
camPos := gglm.NewVec3(0, 0, 3)
worldUp := gglm.NewVec3(0, 1, 0)
targetPos := gglm.NewVec3(0, 0, 0)
viewMat := gglm.LookAt(camPos, targetPos, worldUp)
println(viewMat.String())
//Mat2Col
mc := gglm.NewMat2Id()
println("===============================")
println(mc.String())
mc.Data = [2][2]float32{
{1, 3},
{2, 4},
}
println(mc.String())
fmt.Printf("Arr: %v", mc.Data)
mc2 := gglm.Mat2{Data: [2][2]float32{
{1, 3},
{2, 4},
}}
println(mc2.Mul(mc).String())
}

View File

@ -1,84 +0,0 @@
package main
import (
"testing"
"github.com/bloeys/gglm/gglm"
)
var (
dotVec2Result float32
dotVec3Result float32
crossResult *gglm.Vec3
mulMat4Vec4Res *gglm.Vec4
)
func BenchmarkDotVec2(b *testing.B) {
v1 := &gglm.Vec2{}
v2 := &gglm.Vec2{}
for i := 0; i < b.N; i++ {
dotVec2Result = gglm.DotVec2(v1, v2)
}
}
func BenchmarkDotVec3(b *testing.B) {
v1 := &gglm.Vec3{}
v2 := &gglm.Vec3{}
for i := 0; i < b.N; i++ {
dotVec3Result = gglm.DotVec3(v1, v2)
}
}
func BenchmarkCross(b *testing.B) {
v1 := &gglm.Vec3{}
v2 := &gglm.Vec3{}
for i := 0; i < b.N; i++ {
crossResult = gglm.Cross(v1, v2)
}
}
func BenchmarkMulMat2(b *testing.B) {
m1 := gglm.NewMat2Id()
m2 := gglm.NewMat2Id()
for i := 0; i < b.N; i++ {
m1.Mul(m2)
}
}
func BenchmarkMulMat3(b *testing.B) {
m1 := gglm.NewMat3Id()
m2 := gglm.NewMat3Id()
for i := 0; i < b.N; i++ {
m1.Mul(m2)
}
}
func BenchmarkMulMat4(b *testing.B) {
m1 := gglm.NewMat4Id()
m2 := gglm.NewMat4Id()
for i := 0; i < b.N; i++ {
m1.Mul(m2)
}
}
func BenchmarkMulMat4Vec4(b *testing.B) {
m1 := gglm.NewMat4Id()
v1 := gglm.Vec4{}
for i := 0; i < b.N; i++ {
mulMat4Vec4Res = gglm.MulMat4Vec4(m1, &v1)
}
}