Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Initialize a 4x4 matrix i.e. sdf.M44 #69

Closed
Megidd opened this issue May 8, 2023 · 9 comments · Fixed by #70
Closed

Initialize a 4x4 matrix i.e. sdf.M44 #69

Megidd opened this issue May 8, 2023 · 9 comments · Fixed by #70

Comments

@Megidd
Copy link
Contributor

Megidd commented May 8, 2023

Problem

There is no public method to declare a new instance of sdf.M44 with the initialization of its values.

The fields of the sdf.M44 are all private:

// M44 is a 4x4 matrix.
type M44 struct {
	x00, x01, x02, x03 float64
	x10, x11, x12, x13 float64
	x20, x21, x22, x23 float64
	x30, x31, x32, x33 float64
}

Why

The reason that I'm running into this problem is that I need to create a Quaternion type:

import (
	"math"

	"github.com/deadsy/sdfx/sdf"
	v3 "github.com/deadsy/sdfx/vec/v3"
)

// Quaternion represents a quaternion.
type Quaternion struct {
	W, X, Y, Z float64
}

// FromVectors creates a quaternion representing the rotation from vector a to vector b.
func FromVectors(a, b v3.Vec) Quaternion {
	v := a.Cross(b)
	w := math.Sqrt(a.Length2()*b.Length2())   a.Dot(b)
	q := Quaternion{W: w, X: v.X, Y: v.Y, Z: v.Z}
	return q.Normalize()
}

// Normalize normalizes the quaternion.
func (q Quaternion) Normalize() Quaternion {
	length := math.Sqrt(q.W*q.W   q.X*q.X   q.Y*q.Y   q.Z*q.Z)
	return Quaternion{W: q.W / length, X: q.X / length, Y: q.Y / length, Z: q.Z / length}
}

// ToMatrix converts the quaternion to a 4x4 matrix.
func (q Quaternion) ToMatrix() sdf.M44 {
	xx := q.X * q.X
	yy := q.Y * q.Y
	zz := q.Z * q.Z
	xy := q.X * q.Y
	xz := q.X * q.Z
	yz := q.Y * q.Z
	wx := q.W * q.X
	wy := q.W * q.Y
	wz := q.W * q.Z

	return sdf.M44{
		1 - 2*(yy zz), 2 * (xy - wz), 2 * (xz   wy), 0,
		2 * (xy   wz), 1 - 2*(xx zz), 2 * (yz - wx), 0,
		2 * (xz - wy), 2 * (yz   wx), 1 - 2*(xx yy), 0,
		0, 0, 0, 1,
	}
}

But, the last statement cannot be done, I mean:

	return sdf.M44{
		1 - 2*(yy zz), 2 * (xy - wz), 2 * (xz   wy), 0,
		2 * (xy   wz), 1 - 2*(xx zz), 2 * (yz - wx), 0,
		2 * (xz - wy), 2 * (yz   wx), 1 - 2*(xx yy), 0,
		0, 0, 0, 1,
	}

There is no way to initialize a sdf.M44, as far as I understand. Am I right? 🙄

@deadsy
Copy link
Owner

deadsy commented May 8, 2023

What about just making "Quaternion" an object within the sdf package itself? ie- it would have access to private members within M44.

A couple of other points...

  • Doing m[i][j] = k is probably nicer than doing m.Set(i,j,k)
  • What about M22 and M33?
  • The Get/Set for the vector types were about wanting to access the vector by component index rather than by name. Not so much a private/public thing.

@deadsy
Copy link
Owner

deadsy commented May 8, 2023

btw - looking at M22/33/44 references I think the argument could be made to split off matrix operations into their own package. Maybe Quaternions could join them there.

@Megidd
Copy link
Contributor Author

Megidd commented May 9, 2023

What about just making "Quaternion" an object within the sdf package itself?

... Maybe Quaternions could join them there.

Eventually, I ended up using the Quaternion provided by this Go pkg rather than my own custom Quaternion logic:

https://github.com/go-gl/mathgl

https://github.com/go-gl/mathgl/blob/e426c0894fa41bc41ac04704eef3ac4011b19ecf/mgl32/quat.go#L32

Data types need to be converted of course 🙂

@Megidd
Copy link
Contributor Author

Megidd commented May 9, 2023

  • Doing m[i][j] = k is probably nicer than doing m.Set(i,j,k)

btw - looking at M22/33/44 references I think the argument could be made to split off matrix operations into their own package...

I guess to do the above points, heavy modifications are needed. Probably affecting many other things. Maybe a heavy restructuring needs rigorous testing. A bit risky maybe 🤔

  • What about M22 and M33?

I'm going to modify I modified the PR so that the same Get and Set methods are provided for M22 and M33 too ✔️ Just a simple way to have access to matrix values for now.

@deadsy
Copy link
Owner

deadsy commented May 9, 2023

So are you doing 16 set's to initialise the M44 for your quaternion stuff?
Not very efficient...
What about:

func NewM44(x []float64) M44

which initialises based on up to 16 values out of x

E.g.

m := sdf.NewM33([]float64{
0,1,2,
3,4,5,
6,7,8,
})

@deadsy
Copy link
Owner

deadsy commented May 9, 2023

I'd be curious to benchmark differences between type built with arrays vs type built with named elements.

E.g.

M44 as [16]float64
M44 as struct{x00,x01,x02..... float64}

I guess they should be the same.

The former representation makes any sort of indexed access very simple.
The latter representations is good for 2d/3d vectors where you can do v.X, v.Y, v.Z

But for a matrix maybe I should convert the representation to a x[i] form internally.

@Megidd
Copy link
Contributor Author

Megidd commented May 10, 2023

So are you doing 16 set's to initialise the M44 for your quaternion stuff? Not very efficient... What about:

func NewM44(x []float64) M44

which initialises based on up to 16 values out of x

E.g.

m := sdf.NewM33([]float64{ 0,1,2, 3,4,5, 6,7,8, })

Makes sense. I'm going to modify I modified the PR accordingly 👍

@Megidd
Copy link
Contributor Author

Megidd commented May 10, 2023

I'd be curious to benchmark differences between type built with arrays vs type built with named elements.

E.g.

M44 as [16]float64 M44 as struct{x00,x01,x02..... float64}

I guess they should be the same.

The former representation makes any sort of indexed access very simple. The latter representations is good for 2d/3d vectors where you can do v.X, v.Y, v.Z

But for a matrix maybe I should convert the representation to a x[i] form internally.

https://poe.com/s/GArFor42nHhIhRKhvBVb 🤖

@deadsy
Copy link
Owner

deadsy commented May 10, 2023

Funny. TIL: ChatGPTs opinion is worth about as much as the opinion of any rando on the internet, in fact it's probably an amalgam of the opinion of said randos.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants