mirror of
https://github.com/bloeys/gglm.git
synced 2025-12-29 13:38:20 +00:00
Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 051f91288d | |||
| d0ac00b388 | |||
| 971afed401 | |||
| 547d3ad234 | |||
| e45e4d3304 |
@ -22,7 +22,6 @@ gglm currently has the following:
|
||||
## Usage
|
||||
|
||||
```go
|
||||
|
||||
import "github.com/bloeys/gglm/gglm"
|
||||
|
||||
|
||||
@ -43,10 +42,15 @@ func main() {
|
||||
println(v1.Eq(v2))
|
||||
v2.Set(1, 2)
|
||||
println(v1.Eq(v2))
|
||||
|
||||
//This performs: v1 += v2
|
||||
//v1 is returned from the function, so we can chain calls that operate on v1
|
||||
newX := v1.Add(v2).X()
|
||||
println("newX:", newX)
|
||||
}
|
||||
```
|
||||
|
||||
## Notes
|
||||
|
||||
You can check compiler inlining decisions using `go run -gcflags "-m" .`. Some functions look a bit weird compared to similar ones
|
||||
because we are trying to reduce function complexity so the compiler inlines.
|
||||
|
||||
|
||||
31
gglm/quat.go
31
gglm/quat.go
@ -16,7 +16,7 @@ func (q *Quat) Eq(q2 *Quat) bool {
|
||||
return q.Data == q2.Data
|
||||
}
|
||||
|
||||
//Angle returns the angle represented by this quaternion
|
||||
//Angle returns the angle represented by this quaternion in radians
|
||||
func (q *Quat) Angle() float32 {
|
||||
|
||||
if Abs32(q.Data[3]) > CosHalf {
|
||||
@ -74,7 +74,34 @@ func NewQuatEuler(v *Vec3) *Quat {
|
||||
}
|
||||
}
|
||||
|
||||
//AngleAxis rotates rotRad radians around the *normalized* vector rotAxisNorm
|
||||
//Euler takes rotations in radians and produces a rotation that
|
||||
//rotates around the z-axis, y-axis and lastly x-axis.
|
||||
func NewQuatEulerXYZ(x, y, z float32) *Quat {
|
||||
|
||||
//Some other common terminology: x=roll, y=pitch, z=yaw
|
||||
sinX, cosX := Sincos32(x * 0.5)
|
||||
sinY, cosY := Sincos32(y * 0.5)
|
||||
sinZ, cosZ := Sincos32(z * 0.5)
|
||||
|
||||
//This produces a z->y->x multiply order, but its written as XYZ.
|
||||
//This is due to XYZ meaning independent rotation matrices, so Z is applied
|
||||
//first, then Y matrix and lastly X.
|
||||
//See this for more info: https://github.com/godotengine/godot/issues/6816#issuecomment-254592170
|
||||
//
|
||||
//Note: On most conversion tools putting the multiply order (e.g. ZYX for us) is required.
|
||||
return &Quat{
|
||||
Vec4: Vec4{
|
||||
Data: [4]float32{
|
||||
sinX*cosY*cosZ - cosX*sinY*sinZ,
|
||||
cosX*sinY*cosZ + sinX*cosY*sinZ,
|
||||
cosX*cosY*sinZ - sinX*sinY*cosZ,
|
||||
cosX*cosY*cosZ + sinX*sinY*sinZ,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
//NewQuatAngleAxis produces a quaternion thats rotates rotRad radians around the *normalized* vector rotAxisNorm
|
||||
func NewQuatAngleAxis(rotRad float32, rotAxisNorm *Vec3) *Quat {
|
||||
|
||||
s, c := Sincos32(rotRad * 0.5)
|
||||
|
||||
@ -14,6 +14,12 @@ func TestNewQuatEuler(t *testing.T) {
|
||||
if !gglm.EqF32(q.X(), ans.X()) || !gglm.EqF32(q.Y(), ans.Y()) || !gglm.EqF32(q.Z(), ans.Z()) || !gglm.EqF32(q.W(), ans.W()) {
|
||||
t.Errorf("Got: %v; Expected: %v", q.String(), ans.String())
|
||||
}
|
||||
|
||||
q = gglm.NewQuatEulerXYZ(180*gglm.Deg2Rad, 180*gglm.Deg2Rad, 180*gglm.Deg2Rad)
|
||||
|
||||
if !gglm.EqF32(q.X(), ans.X()) || !gglm.EqF32(q.Y(), ans.Y()) || !gglm.EqF32(q.Z(), ans.Z()) || !gglm.EqF32(q.W(), ans.W()) {
|
||||
t.Errorf("Got: %v; Expected: %v", q.String(), ans.String())
|
||||
}
|
||||
}
|
||||
|
||||
func TestNewQuatAngleAxis(t *testing.T) {
|
||||
|
||||
@ -2,56 +2,64 @@ package gglm
|
||||
|
||||
type Swizzle1 interface {
|
||||
X() float32
|
||||
R() float32
|
||||
|
||||
SetX(float32)
|
||||
SetR(float32)
|
||||
|
||||
AddX(float32)
|
||||
|
||||
R() float32
|
||||
SetR(float32)
|
||||
AddR(float32)
|
||||
}
|
||||
|
||||
type Swizzle2 interface {
|
||||
Swizzle1
|
||||
|
||||
Y() float32
|
||||
G() float32
|
||||
|
||||
SetY(float32)
|
||||
SetG(float32)
|
||||
|
||||
AddY(float32)
|
||||
|
||||
SetXY(float32, float32)
|
||||
AddXY(float32, float32)
|
||||
|
||||
G() float32
|
||||
SetG(float32)
|
||||
AddG(float32)
|
||||
|
||||
AddXY(float32, float32)
|
||||
SetRG(float32, float32)
|
||||
AddRG(float32, float32)
|
||||
}
|
||||
|
||||
type Swizzle3 interface {
|
||||
Swizzle2
|
||||
|
||||
Z() float32
|
||||
B() float32
|
||||
|
||||
SetZ(float32)
|
||||
SetB(float32)
|
||||
|
||||
AddZ(float32)
|
||||
|
||||
SetXYZ(float32, float32, float32)
|
||||
AddXYZ(float32, float32, float32)
|
||||
|
||||
B() float32
|
||||
SetB(float32)
|
||||
AddB(float32)
|
||||
|
||||
AddXYZ(float32, float32, float32)
|
||||
SetRGB(float32, float32, float32)
|
||||
AddRGB(float32, float32, float32)
|
||||
}
|
||||
|
||||
type Swizzle4 interface {
|
||||
Swizzle3
|
||||
|
||||
W() float32
|
||||
A() float32
|
||||
|
||||
SetW(float32)
|
||||
SetA(float32)
|
||||
|
||||
AddW(float32)
|
||||
|
||||
SetXYZW(float32, float32, float32, float32)
|
||||
AddXYZW(float32, float32, float32, float32)
|
||||
|
||||
A() float32
|
||||
SetA(float32)
|
||||
AddA(float32)
|
||||
|
||||
AddXYZW(float32, float32, float32, float32)
|
||||
SetRGBA(float32, float32, float32, float32)
|
||||
AddRGBA(float32, float32, float32, float32)
|
||||
}
|
||||
|
||||
10
gglm/vec2.go
10
gglm/vec2.go
@ -62,11 +62,21 @@ func (v *Vec2) AddG(g float32) {
|
||||
v.Data[1] += g
|
||||
}
|
||||
|
||||
func (v *Vec2) SetXY(x, y float32) {
|
||||
v.Data[0] = x
|
||||
v.Data[1] = y
|
||||
}
|
||||
|
||||
func (v *Vec2) AddXY(x, y float32) {
|
||||
v.Data[0] += x
|
||||
v.Data[1] += y
|
||||
}
|
||||
|
||||
func (v *Vec2) SetRG(r, g float32) {
|
||||
v.Data[0] = r
|
||||
v.Data[1] = g
|
||||
}
|
||||
|
||||
func (v *Vec2) AddRG(r, g float32) {
|
||||
v.Data[0] += r
|
||||
v.Data[1] += g
|
||||
|
||||
22
gglm/vec3.go
22
gglm/vec3.go
@ -84,22 +84,44 @@ func (v *Vec3) AddB(b float32) {
|
||||
v.Data[2] += b
|
||||
}
|
||||
|
||||
func (v *Vec3) SetXY(x, y float32) {
|
||||
v.Data[0] = x
|
||||
v.Data[1] = y
|
||||
}
|
||||
|
||||
func (v *Vec3) AddXY(x, y float32) {
|
||||
v.Data[0] += x
|
||||
v.Data[1] += y
|
||||
}
|
||||
|
||||
func (v *Vec3) SetRG(r, g float32) {
|
||||
v.Data[0] = r
|
||||
v.Data[1] = g
|
||||
}
|
||||
|
||||
func (v *Vec3) AddRG(r, g float32) {
|
||||
v.Data[0] += r
|
||||
v.Data[1] += g
|
||||
}
|
||||
|
||||
func (v *Vec3) SetXYZ(x, y, z float32) {
|
||||
v.Data[0] = x
|
||||
v.Data[1] = y
|
||||
v.Data[2] = z
|
||||
}
|
||||
|
||||
func (v *Vec3) AddXYZ(x, y, z float32) {
|
||||
v.Data[0] += x
|
||||
v.Data[1] += y
|
||||
v.Data[2] += z
|
||||
}
|
||||
|
||||
func (v *Vec3) SetRGB(r, g, b float32) {
|
||||
v.Data[0] = r
|
||||
v.Data[1] = g
|
||||
v.Data[2] = b
|
||||
}
|
||||
|
||||
func (v *Vec3) AddRGB(r, g, b float32) {
|
||||
v.Data[0] += r
|
||||
v.Data[1] += g
|
||||
|
||||
36
gglm/vec4.go
36
gglm/vec4.go
@ -108,28 +108,57 @@ func (v *Vec4) AddA(a float32) {
|
||||
v.Data[3] += a
|
||||
}
|
||||
|
||||
func (v *Vec4) SetXY(x, y float32) {
|
||||
v.Data[0] = x
|
||||
v.Data[1] = y
|
||||
}
|
||||
|
||||
func (v *Vec4) AddXY(x, y float32) {
|
||||
v.Data[0] += x
|
||||
v.Data[1] += y
|
||||
}
|
||||
|
||||
func (v *Vec4) SetRG(r, g float32) {
|
||||
v.Data[0] = r
|
||||
v.Data[1] = g
|
||||
}
|
||||
|
||||
func (v *Vec4) AddRG(r, g float32) {
|
||||
v.Data[0] += r
|
||||
v.Data[1] += g
|
||||
}
|
||||
|
||||
func (v *Vec4) SetXYZ(x, y, z float32) {
|
||||
v.Data[0] = x
|
||||
v.Data[1] = y
|
||||
v.Data[2] = z
|
||||
}
|
||||
|
||||
func (v *Vec4) AddXYZ(x, y, z float32) {
|
||||
v.Data[0] += x
|
||||
v.Data[1] += y
|
||||
v.Data[2] += z
|
||||
}
|
||||
|
||||
func (v *Vec4) SetRGB(r, g, b float32) {
|
||||
v.Data[0] = r
|
||||
v.Data[1] = g
|
||||
v.Data[2] = b
|
||||
}
|
||||
|
||||
func (v *Vec4) AddRGB(r, g, b float32) {
|
||||
v.Data[0] += r
|
||||
v.Data[1] += g
|
||||
v.Data[2] += b
|
||||
}
|
||||
|
||||
func (v *Vec4) SetXYZW(x, y, z, w float32) {
|
||||
v.Data[0] = x
|
||||
v.Data[1] = y
|
||||
v.Data[2] = z
|
||||
v.Data[3] = w
|
||||
}
|
||||
|
||||
func (v *Vec4) AddXYZW(x, y, z, w float32) {
|
||||
v.Data[0] += x
|
||||
v.Data[1] += y
|
||||
@ -137,6 +166,13 @@ func (v *Vec4) AddXYZW(x, y, z, w float32) {
|
||||
v.Data[3] += w
|
||||
}
|
||||
|
||||
func (v *Vec4) SetRGBA(r, g, b, a float32) {
|
||||
v.Data[0] = r
|
||||
v.Data[1] = g
|
||||
v.Data[2] = b
|
||||
v.Data[3] = a
|
||||
}
|
||||
|
||||
func (v *Vec4) AddRGBA(r, g, b, a float32) {
|
||||
v.Data[0] += r
|
||||
v.Data[1] += g
|
||||
|
||||
106
gglm/vec_test.go
106
gglm/vec_test.go
@ -102,26 +102,42 @@ func TestVecSwizzleGet(t *testing.T) {
|
||||
func TestVecSwizzleSet(t *testing.T) {
|
||||
|
||||
//Vec2
|
||||
v2 := gglm.NewVec2(0, 0)
|
||||
v2 := gglm.NewVec2(1, 1)
|
||||
ans2 := gglm.NewVec2(1, 2)
|
||||
|
||||
v2.SetX(1)
|
||||
v2.SetY(2)
|
||||
|
||||
if !v2.Eq(ans2) {
|
||||
t.Errorf("Got: %v; Expected: %v", v2.String(), ans2.String())
|
||||
}
|
||||
|
||||
v2 = gglm.NewVec2(1, 1)
|
||||
ans2 = gglm.NewVec2(11, 22)
|
||||
|
||||
v2.SetR(11)
|
||||
v2.SetG(22)
|
||||
if !v2.Eq(ans2) {
|
||||
t.Errorf("Got: %v; Expected: %v", v2.String(), ans2.String())
|
||||
}
|
||||
|
||||
v2 = gglm.NewVec2(1, 1)
|
||||
ans2 = gglm.NewVec2(1, 2)
|
||||
|
||||
v2.SetXY(1, 2)
|
||||
if !v2.Eq(ans2) {
|
||||
t.Errorf("Got: %v; Expected: %v", v2.String(), ans2.String())
|
||||
}
|
||||
|
||||
v2 = gglm.NewVec2(1, 1)
|
||||
ans2 = gglm.NewVec2(11, 22)
|
||||
|
||||
v2.SetRG(11, 22)
|
||||
if !v2.Eq(ans2) {
|
||||
t.Errorf("Got: %v; Expected: %v", v2.String(), ans2.String())
|
||||
}
|
||||
|
||||
//Vec3
|
||||
v3 := gglm.NewVec3(0, 0, 0)
|
||||
v3 := gglm.NewVec3(1, 1, 1)
|
||||
ans3 := gglm.NewVec3(1, 2, 3)
|
||||
|
||||
v3.SetX(1)
|
||||
@ -132,6 +148,7 @@ func TestVecSwizzleSet(t *testing.T) {
|
||||
t.Errorf("Got: %v; Expected: %v", v3.String(), ans3.String())
|
||||
}
|
||||
|
||||
v3 = gglm.NewVec3(1, 1, 1)
|
||||
ans3 = gglm.NewVec3(11, 22, 33)
|
||||
|
||||
v3.SetR(11)
|
||||
@ -142,8 +159,40 @@ func TestVecSwizzleSet(t *testing.T) {
|
||||
t.Errorf("Got: %v; Expected: %v", v3.String(), ans3.String())
|
||||
}
|
||||
|
||||
v3 = gglm.NewVec3(1, 1, 1)
|
||||
ans3 = gglm.NewVec3(1, 2, 1)
|
||||
|
||||
v3.SetXY(1, 2)
|
||||
if !v3.Eq(ans3) {
|
||||
t.Errorf("Got: %v; Expected: %v", v3.String(), ans3.String())
|
||||
}
|
||||
|
||||
v3 = gglm.NewVec3(1, 1, 1)
|
||||
ans3 = gglm.NewVec3(1, 2, 1)
|
||||
|
||||
v3.SetRG(1, 2)
|
||||
if !v3.Eq(ans3) {
|
||||
t.Errorf("Got: %v; Expected: %v", v3.String(), ans3.String())
|
||||
}
|
||||
|
||||
v3 = gglm.NewVec3(1, 1, 1)
|
||||
ans3 = gglm.NewVec3(1, 2, 3)
|
||||
|
||||
v3.SetXYZ(1, 2, 3)
|
||||
if !v3.Eq(ans3) {
|
||||
t.Errorf("Got: %v; Expected: %v", v3.String(), ans3.String())
|
||||
}
|
||||
|
||||
v3 = gglm.NewVec3(1, 1, 1)
|
||||
ans3 = gglm.NewVec3(1, 2, 3)
|
||||
|
||||
v3.SetRGB(1, 2, 3)
|
||||
if !v3.Eq(ans3) {
|
||||
t.Errorf("Got: %v; Expected: %v", v3.String(), ans3.String())
|
||||
}
|
||||
|
||||
//Vec4
|
||||
v4 := gglm.NewVec4(0, 0, 0, 0)
|
||||
v4 := gglm.NewVec4(1, 1, 1, 1)
|
||||
ans4 := gglm.NewVec4(1, 2, 3, 4)
|
||||
|
||||
v4.SetX(1)
|
||||
@ -155,6 +204,7 @@ func TestVecSwizzleSet(t *testing.T) {
|
||||
t.Errorf("Got: %v; Expected: %v", v4.String(), ans4.String())
|
||||
}
|
||||
|
||||
v4 = gglm.NewVec4(1, 1, 1, 1)
|
||||
ans4 = gglm.NewVec4(11, 22, 33, 44)
|
||||
|
||||
v4.SetR(11)
|
||||
@ -165,6 +215,54 @@ func TestVecSwizzleSet(t *testing.T) {
|
||||
if !v4.Eq(ans4) {
|
||||
t.Errorf("Got: %v; Expected: %v", v4.String(), ans4.String())
|
||||
}
|
||||
|
||||
v4 = gglm.NewVec4(1, 1, 1, 1)
|
||||
ans4 = gglm.NewVec4(1, 2, 1, 1)
|
||||
|
||||
v4.SetXY(1, 2)
|
||||
if !v4.Eq(ans4) {
|
||||
t.Errorf("Got: %v; Expected: %v", v4.String(), ans4.String())
|
||||
}
|
||||
|
||||
v4 = gglm.NewVec4(1, 1, 1, 1)
|
||||
ans4 = gglm.NewVec4(1, 2, 1, 1)
|
||||
|
||||
v4.SetRG(1, 2)
|
||||
if !v4.Eq(ans4) {
|
||||
t.Errorf("Got: %v; Expected: %v", v4.String(), ans4.String())
|
||||
}
|
||||
|
||||
v4 = gglm.NewVec4(1, 1, 1, 1)
|
||||
ans4 = gglm.NewVec4(1, 2, 3, 1)
|
||||
|
||||
v4.SetXYZ(1, 2, 3)
|
||||
if !v4.Eq(ans4) {
|
||||
t.Errorf("Got: %v; Expected: %v", v4.String(), ans4.String())
|
||||
}
|
||||
|
||||
v4 = gglm.NewVec4(1, 1, 1, 1)
|
||||
ans4 = gglm.NewVec4(1, 2, 3, 1)
|
||||
|
||||
v4.SetRGB(1, 2, 3)
|
||||
if !v4.Eq(ans4) {
|
||||
t.Errorf("Got: %v; Expected: %v", v4.String(), ans4.String())
|
||||
}
|
||||
|
||||
v4 = gglm.NewVec4(1, 1, 1, 1)
|
||||
ans4 = gglm.NewVec4(1, 2, 3, 4)
|
||||
|
||||
v4.SetXYZW(1, 2, 3, 4)
|
||||
if !v4.Eq(ans4) {
|
||||
t.Errorf("Got: %v; Expected: %v", v4.String(), ans4.String())
|
||||
}
|
||||
|
||||
v4 = gglm.NewVec4(1, 1, 1, 1)
|
||||
ans4 = gglm.NewVec4(1, 2, 3, 4)
|
||||
|
||||
v4.SetRGBA(1, 2, 3, 4)
|
||||
if !v4.Eq(ans4) {
|
||||
t.Errorf("Got: %v; Expected: %v", v4.String(), ans4.String())
|
||||
}
|
||||
}
|
||||
|
||||
func TestVecSwizzleAdd(t *testing.T) {
|
||||
|
||||
7
main.go
7
main.go
@ -64,6 +64,9 @@ func main() {
|
||||
v2.Set(1, 2)
|
||||
println(v1.Eq(v2))
|
||||
|
||||
v1.AddXY(v2.X(), v2.Y())
|
||||
println(v1.String())
|
||||
|
||||
println("V1: " + v1.String())
|
||||
v1.Normalize()
|
||||
println("V1 Normal: " + v1.String())
|
||||
@ -97,6 +100,10 @@ func main() {
|
||||
|
||||
println(gglm.DotVec4(v5, v6))
|
||||
|
||||
v5.Add(v6)
|
||||
v5.AddXYZW(v6.X(), v6.Y(), v6.Z(), v6.W())
|
||||
println(v6.String())
|
||||
|
||||
println("V6: " + v6.String())
|
||||
v6.Normalize()
|
||||
println("V6 Normal: " + v6.String())
|
||||
|
||||
Reference in New Issue
Block a user