GithubHelp home page GithubHelp logo

mathgl's People

Contributors

alexvasi avatar aykevl avatar beaubrueggemann avatar bramp avatar db47h avatar der-antikeks avatar dmitshur avatar egonelbre avatar glenkelley avatar hashimthearab avatar hydroflame avatar krux02 avatar luisgargitter avatar myaaaaaaaaa avatar nitrix avatar pwaller avatar quillaja avatar rossmeier avatar slimsag avatar stewi1014 avatar userab1236872 avatar zyl9393 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

mathgl's Issues

Improve code generation with text/template

Issues #30 and #29 are basically on hold because of some of the difficulty in rewriting the code generation. I think it would just plain be easier to rewrite the incredibly ad-hoc, ugly code gen script with text/template.

The new version likely would no longer use the Makefile, and instead directly generate the float64 version due to text/template's greater flexibility.

how to convert glm to mgl32?

//------------------cpp glm code--------------------------------
// Create and compile our GLSL program from the shaders
GLuint programID = LoadShaders( "SimpleTransform.vertexshader", "SingleColor.fragmentshader" );

// Get a handle for our "MVP" uniform
GLuint MatrixID = glGetUniformLocation(programID, "MVP");

// Projection matrix : 45° Field of View, 4:3 ratio, display range : 0.1 unit <-> 100 units
glm::mat4 Projection = glm::perspective(45.0f, 4.0f / 3.0f, 0.1f, 100.0f);
// Or, for an ortho camera :
//glm::mat4 Projection = glm::ortho(-10.0f,10.0f,-10.0f,10.0f,0.0f,100.0f); // In world coordinates

// Camera matrix
glm::mat4 View       = glm::lookAt(
                            glm::vec3(4,3,3), // Camera is at (4,3,3), in World Space
                            glm::vec3(0,0,0), // and looks at the origin
                            glm::vec3(0,1,0)  // Head is up (set to 0,-1,0 to look upside-down)
                       );
// Model matrix : an identity matrix (model will be at the origin)
glm::mat4 Model      = glm::mat4(1.0f);
// Our ModelViewProjection : multiplication of our 3 matrices
glm::mat4 MVP        = Projection * View * Model; // Remember, matrix multiplication is the other way around

Radians vs Degrees

I was just testing some quaternion functions and hit a brick wall: my simple test case was failing!

I mean, it checked out against every other in-program method of computing the rotation, but not my hand computed one. My inkling was to check the source. Yup, QuatRotate and HomogRotate3D use degrees.

It seems like the package is split between degrees and radians, with some functions taking one and some taking another. I think I chose degrees on the methods I did because both GLM and the deprecated OpenGL functions used degrees.

Is there a preference on this? Personally, I prefer radians simply because that's what the math package likes. I don't think degrees are THAT much more intuitive to work with, and it's not a huge deal to make a DegToRad utility function anyway, but I don't want to shake things up too much without input.

MatStack.LeftMul performs same process as Mat.Stack.RightMul

Both mgl32 and mgl64 versions of matstack.MatStack contain a peculiar LeftMul method:

// Left multiplies the current top of the matrix by the
// argument.
func (ms *MatStack) LeftMul(m mgl32.Mat4) {
        (*ms)[len(*ms)-1] = (*ms)[len(*ms)-1].Mul4(m)
}

This incorrectly performs a right multiply (it matches exactly the RightMul implementation). The operands to Mul4 need to be swapped.

Matrix multiplication MulNx1 is incorrect

A matrix mat Mat3x6 with 3 rows and 6 columns multiplicated with a vector v Vec6 should yield a Vec3. But MulNx1 currently expects mat to have 6 rows and tries to produce a Vec6: panic: index out of range.

correction in matmn.go line 416:

//  dst = dst.Resize(len(v.vec))
    dst = dst.Resize(mat.m)

//  for r := range v.vec {
    for r := 0; r < mat.m; r++ {

Also:
func VecN.Set is missing. There is MatMxN.At, MatMxN.Set, VecN.Get but no VecN.Set.

Incorrect coordinate mapping in ScreenToGLCoords and GLToScreenCoords.

Unless I'm mistaken, screen X coordinates are in the range [0, screenWidth-1], not [0, screenWidth] (the same applies to the Y coordinate), and GL's coordinate system maps [screenWidth-1,0] to [1.0,1.0] and [0,screenHeight-1] to [-1.0,-1.0].

So the code for ScreenToGLCoords should be:

func ScreenToGLCoords(x, y int, screenWidth, screenHeight int) (xOut, yOut float64) {
	xOut = 2.0*float64(x)/float64(screenWidth-1) - 1.0
	yOut = -2.0*float64(y)/float64(screenHeight-1) + 1.0

	return
}

Quaternion Setter

At the moment there is no setter for the quaternion data. Also the constructor is private. At the moment, there is no way of creating a custom quaternion from data.

Edit: I found out that quaternions have many problems right now. Multiplication is Wrong and Matrix extraction is wrong.

in Quat Mul w is definitely wrong. The other I don't know.
in Matrix Extraction ... 2_y_z + 2_w_z, 2_x_x - 2_y_y, 0,0,0,0,1} should be ... 2_y_z+2_w_x, 1-2_x_x-2_y_y

http://www.cprogramming.com/tutorial/3d/quaternions.html

Proposal: Move the float64 methods into another package

At the moment, functions that operate on float32 values end in f and float64 end in d (except some outliers in the utilities). It seems more Go-like, and perhaps overall better, to separate the packages into mathgl (root level) and mathgl64 (float64 methods).

This would be an API-breaking change. All methods would lose their suffix, e.g. mathgl.Perspectivef -> mathgl.Perspective.

The makefile would work the same, it would just copy and gofmt -w -r in a separate directory.

One note is that OpenGL only works with float32 values unless a specific extension is enabled (and I don't think the go-gl bindings even support the extension), so the double functionality likely doesn't get much use anyway.

If anybody watching this package has opinions, please voice them.

Random data generation may significantly bias current benchmarks

I took out the random data from one benchmark function and the speed drastically improved (~40 ns/op faster), despite the random data being behind StopTimer calls.

I put in the random data to prevent the compiler from making optimization with constant data and biasing results (since they're really simple functions). However, I made the following simple change to VecSub:

func init() {
        rand.Seed(time.Now().UnixNano())
}

var v1 = Vec4{rand.Float32(), rand.Float32(), rand.Float32(), rand.Float32()}
var v2 = Vec4{rand.Float32(), rand.Float32(), rand.Float32(), rand.Float32()}

func BenchmarkVec4Sub(b *testing.B) {
    for i := 0; i < b.N; i++ {
        v1.Sub(v2)
    }
}

Because the compiler shouldn't be able to do any constant optimization for that (since it's based off the seed at runtime). And got ~12.6 ns/op, which is about as good as a SIMD package I benchmarked (~11.9 ns/op). This is down from previous benchmarks of the form

func BenchmarkVec4Sub(b *testing.B) {
        b.StopTimer()
    r := rand.New(rand.NewSource(int64(time.Now().Nanosecond())))

    for i := 0; i < b.N; i++ {
        b.StopTimer()
        v1 := Vec4{r.Float32(), r.Float32(), r.Float32(), r.Float32()}
        v2 := Vec4{r.Float32(), r.Float32(), r.Float32(), r.Float32()}
        b.StartTimer()

        v1.Sub(v2)
    }
}

Which were clocking ~50.9 ns/op. And also took an age to run. Further, introducing random data in the same form as our current benchmarks to the SIMD package's benchmarks catapaulted it up to the ~40-50ns/op range -- implying there's almost certainly no magical Go compiler trickery going on biasing our benchmarks to an unfairly low number.

This is actually very good news. I'm filing this because I don't have time for the next little bit if someone else wants to do this. I think all Matrix, Vector, and Quaternion benchmarks use random data now. It's not a horifically difficult thing to change, just tedious.

On the other hand, I'm not sure why b.StopTimer is being so finnicky, but it may just be meant for benchmarks at ns/op levels that aren't so low (~40ns/op is nothing compared to something like a graph search).

Perhaps switch to pointers for matrices and vectors

I got an email recently with some bechmarks. The long and short is: once you get to Mat4 size, it is a significant speed improvement (about 13 ns/op for multiplcation) to use a pointer for Mat4. This is a significant API change and would break a lot of existing code. Doing

m := mgl32.Ident4()
m[0] = 5

Would break. Any code that currently uses any of: At and Set for matrices or X, Y, Z, or W for vectors is safe (SetX and the like would likely needed to be added for Vectors).

The way I see it, there are two potential solutions here:

  1. Redo everything to use pointers. This, as mentioned, breaks existing code.
  2. Add functions like func (m *Mat4) MulTo(dst *Mat4, m2 *Mat4) which would have similar semantics to *MatMN.MulMN(dst, m2).

I like option 2, since there's no compatability breakage, but it does clutter the API and people may mistakenly use the slower code without realizing it.

Thoughts?

Vulkan compatibility

It would make sense for this library to support both OpenGL and Vulkan coordinate systems. One difference that comes to mind is that screen coordinates in Vulkan range from 0 to 1 instead of -1 to 1 like in OpenGL.

HomogRotate3DZ is broken

I think HomogRotate3DZ has the wrong sign for the second row; it distorts rather than rotates.

Right now it returns
mathgl.Mat4f{cos, -sin, 0, 0, -sin, cos, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1}

But it should be
mathgl.Mat4f{cos, -sin, 0, 0, sin, cos, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1}

Add common method for number of colums and rows

Currently the library's open methods on matrices do not easily conform to a single unified interface very well.

The At(row, col) -> n function is the only function (save me being blind) that is commonly implemented across all matrix implementations.

I propose that all matrix implementations implement a common interface;

interface {
	At(row, col int) float32 | float64
	NumRows() int
	NumCols() int
}

I personally like the garbage-in garbage-out approach from implementations of .At in this library, but I do feel that all matrices should also provide .NumRows() and .NumCols() like MatMxN does, or some equivalent.

In the case of generalized methods that can operate on matrices of varying dimensions, this would allow one to implement methods that can operate on all matrix implementations in this library using an interface, avoiding the need to duplicate functions or type-switch to find the dimensions of a matrix.

Package feature isolation

As mentioned here:

#22

The core packages are getting a little big. I think it's worth discussing:

  1. Where do new features go?
  2. Should anything be separated out for the next release?

As the answer to 1. I think at this point, anything that's not directly Mat Vec or Quat is definitely out. This means I'll be modifying the AABB pull request to be committed to a separate path. The question is the path, I see two options

github.com/go-gl/mathgl/mgl[32|64]/feature[32|64?]

OR

github.com/go-gl/mathgl/feature[32|64]

While we can't do this due to my guarantee that the API won't break until Go 1.3.1 at the earliest, another option is

github.com/go-gl/mathgl/32/feature

This would move mgl[32|64] to the corresponding direction, e.g. github.com/go-gl/mathgl/32/mgl

As for 2, I'm kind of partial to keeping the current projection/transformation features as-is. You can think of Rotate3D, in a way, as a special constructor for a Mat3. The content in shapes.go is a bit more difficult, I think it could be worth putting that in a shapes or geom package. Thoughts?

Matrix view methods

I got a proposal via email for methods that are essentially Matrix views. These go along with Issue #9 for adding Swizzle operators. A sample of the methods would be:

func (mat Mat4f) Row(index int) Vec4f {
    return Vec4f{mat[index], mat[index+4], mat[index+8], mat[index+12]}
}

func (mat Mat4f) Col(index int) Vec4f {
    return Vec4f{mat[index*4], mat[index*4+1], mat[index*4+2], mat[index*4+3]}
}

// Could be multiple return values
func (mat Mat4f) Rows() [4]Vec4f {
     // return an array matching calling Row on indices 0-4
}

func (mat *Mat4f) SetRow(index int, row Vec4f) {
     mat[index], mat[index+4], mat[index+8], mat[index+12] = row[0], row[1], row[2], row[3]
}

Another possible good method that's missing is an At function for matrices. Currently you have to do the array access yourself, but it would be nice to have a wrapper function for that

func (mat Mat4f) At(row, col int) float32 {
    return mat[col*4+row]
}

func (mat *Mat4f) Set(row, col int, val float32) {
    mat[col*4+row] = val
}

Finally, a Swap method of some sort could be nice for rows and columns

func (mat *Mat4f) SwapRows(r1, r2 int) {
    // Do the essentially the same work as v1,v2 := mat.Row(1), mat.Row(2)
    // mat.SetRow(r2, v1); mat.SetRow(r1, v2)
}

Along with the proposed Swizzle operators, this should allow for fairly sophisticated matrix and vector manipulation.

Swizzle-like functionality

Given the package's glm inspiration, it seems useful to have functions that act like swizzle operators. Obviously strict swizzle is impossible, but functions should emulate the functionality adequately, and be in-lineable, though they do necessarily do an allocation (albeit as long as you're careful, probably only a stack allocation).

Examples:

func (vec Vec4f) XYZ() Vec3f {
    return Vec3f{vec[0], vec[1], vec[2]}
}

func (vec Vec4f) WYX Vec3f {
    return Vec3f{vec[3], vec[1], vec[0]}
}

// Autopromotion
func (vec Vec2f) XYZ() Vec3f {
    return Vec3f{vec[0], vec[1], 1.0}
}

One missing feature is the nice property of swizzle assignment; vec1.xyz = vec2. This is undeniably convenient, but impossible in Go. One possible solution is a Set method:

func (vec *Vec4f) SetXYZ(src Vec3f) *Vec4f {
    vec[0], vec[1], vec[2] = src[0], src[1], src[2]
    return vec
}

Alternatively, for non-sparse, ascending cases, we could use copy(vec[startIndex:], src[:]). So XYZ is copy(vec[0:], src[:]) and YZW would be copy(vec[1:], src[:])

The only question here is performance. These functions are nice to have, but how much of a performance hit is vec.SetXYZ(vec2.ZXY()) going to be? My opinion is that it's worth it to offer these for convenience, and allow the individual developer decide whether the performance is okay.

Error while trying to get library: undefined: sync.Pool

I'm trying to get github.com/go-gl/mathgl/mgl32 and getting the following error:

$ go get github.com/go-gl/mathgl/mgl32
# github.com/go-gl/mathgl/mgl32
src/github.com/go-gl/mathgl/mgl32/mempool.go:12: undefined: sync.Pool
src/github.com/go-gl/mathgl/mgl32/mempool.go:29: undefined: sync.Pool
src/github.com/go-gl/mathgl/mgl32/mempool.go:41: undefined: sync.Pool

Here is my version of go:

$ go version
go version go1.2.1 linux/amd64

FloatEqualThreshhold broken ?

I'm first going to ask you guys to confirm this before marking this as a bug. But shouldn't this FloatEqualThreshold(8.742278e-08, 0, 1e-4) return true ? (because it doesn't)

possible error in BezierCurve2D()?

I've been using the bezier curve functions in mgl64 lately, and I might have found an error in BezierCurve2D(). I noticed this when I plotted a cubic curve (4 control points) using the BezierCurve2D() and it did not produce the expected curve. I plotted the same curve using CubicBezierCurve2D() and got the expected result. In this case, I used the control points {4, 5}, {5.2, 6.3556}, {6.2, 4.2444}, {6, 3}.

Here's an image showing the 2 curves. Red is from BezierCurve2D() and green is the expected curve from CubicBezierCurve2D().
error_bezier

The code which produced this is below. I used the gosl/plt package to create the plot.

package main

import (
	"github.com/cpmech/gosl/plt"
	"github.com/go-gl/mathgl/mgl64"
)

func main() {

	// create 4 control points (for cubic curve)
	cPts := []mgl64.Vec2{{4, 5}, {5.2, 6.3556}, {6.2, 4.2444}, {6, 3}}
	// slices for points of bezier curves
	bezierCurve := []mgl64.Vec2{}
	cubicCurve := []mgl64.Vec2{}

	// use control points over t=[0,1] to get points for plot
	for t := 0.0; t <= 1.0; t += 0.01 {
		bezierCurve = append(bezierCurve,
			mgl64.BezierCurve2D(t, cPts))
		cubicCurve = append(cubicCurve,
			mgl64.CubicBezierCurve2D(t, cPts[0], cPts[1], cPts[2], cPts[3]))
	}

	// plot using gosl's plt package
	plt.Reset(true, nil)

	// with BezierCurve2D()
	plt.Plot(MapVec2(X, bezierCurve), MapVec2(Y, bezierCurve),
		&plt.A{C: "#FF0000", Closed: false})
	// with CubicBezierCurve2D()
	plt.Plot(MapVec2(X, cubicCurve), MapVec2(Y, cubicCurve),
		&plt.A{C: "#00FF00", Closed: false})

	for _, p := range cPts { // plot control points
		plt.PlotOne(p.X(), p.Y(), &plt.A{C: "#000000", M: "o"})
	}

	plt.Equal()
	// output image to same directory
	plt.Save(".", "error_bezier")
}

// functions that make it easier to convert a slice of Vec2 into 2 slices of
// x and y floats for plotting

// MapVec2 applies f to each element of slice.
func MapVec2(f func(v mgl64.Vec2) float64, slice []mgl64.Vec2) (rval []float64) {
	for _, v := range slice {
		rval = append(rval, f(v))
	}
	return
}

// X gets the x component of v
func X(v mgl64.Vec2) float64 { return v.X() }

// Y gets the y component of v
func Y(v mgl64.Vec2) float64 { return v.Y() }

Another example with the control points {0, 0}, {1, 3}, {3, 3}, {6, 0}:
error_bezier

QuatLookAtV implementation

The QuatLookAtV function has two implementations, one commented out.

For me, the two implementations do something quite different, and it lead to a lot of building hacks to try and get it to work before realising that the non-matrix implementation just works out of the box as expected.

@Jragonmiris do you have any intuition as to why, or should I try and untangle my example?

From my perspective I would prefer to standardize on the Quat implementation, but I guess first I need to understand why it was written as the matrix implementation.

I also note that to get it to work for my case I had to insert a negative sign on the angle parameter to QuatRotate(), but that might just be that I haven't spent enough time untangling my coordinate system.

Usage with OpenGL

This is probably a stupid question, but I ask because I didn't find the answer on the documentation.
How can I pass a mgl32 vector/matrix to OpenGL?

Consider finding (or writing if need be) a float32 native math library

After writing some benchmarks today (not for this package, just dicking around with benchmarking fast inverse square root compared to Go's stdlib and such), it's become clear that the rampant type conversions are a significant performance hit. "Significant" is in relative terms, but code of the form:

float32(1.0 / math.Sqrt(float64(n)))

takes about 15.5 ns/op compared to 3.5 ns/op for float64-native. I suspected this, hence why this library generally takes a "convert as infrequently as possible" approach. However, I would consider this significant enough to be worth worrying about.

While Go's standard library is written partially in assembly, I don't think it should be too difficult to rewrite (I think most of the assembly conversions would amount to "swap a letter in the instruction names to do 32-bit operations instead"). However, I'd like to look into existing options if they exist before undertaking this.

I did find this, but the repository was deleted for some ominous reason.

Current package state is out of sync with code generation.

If I run make without any changes, it results in non-zero diff.

Also, genprog/main.go is not at all mentioned in the Makefile, so I assume you must be running it manually? According the README, that is how the vector.go and matrix.go files are generated, so it should be a part of the Makefile then. See e3a647b#commitcomment-9978547.

Finally, it's best to move away from Makefiles or other custom solutions for automation/generation and use a more standard go generate approach. The same commands will be executed, it's just a convention that is easier for everyone to follow. See #32 (comment).

Matrix stack

Both OpenGL's old matrix model and GLM provide matrix stacks. I think this is worthing putting in a new package. A Matrix stack is, in essence, a fully-persistent data structure that keeps track of matrix mutations and allows you to roll back and arbitrary number of operations. This is extremely useful for, e.g., scenegraphs.. A sketch of push, for instance:

type MatrixStack []Mat4

func (ms *MatrixStack) Push(m Mat4) error {
    if len(*ms) == 0 {
        return errors.New("Matrix stack is empty, create a new stack or use MatrixStack.Load to add the first matrix")
    }

    prev := (*ms)[len(*ms)-1]
    (*ms) = append(*ms, prev.Mul4(m))

   return nil
}

The biggest question is whether the stack should be Mat4 only (I believe OpenGL took this approach?) or whether there should be support for Mat3 and Mat2 as well. I suspect the basic (push/pop/peek/load) implementation will be fewer than 200 lines per matrix type, so it may be worth just doing all 3.

Package broken with Go 1.13

Attempting to build any project using go 1.13 that depends on this package yields the following error:

verifying golang.org/x/[email protected]/go.mod: golang.org/x/[email protected]/go.mod: reading https://sum.golang.org/lookup/golang.org/x/[email protected]: 410 Gone

This is caused by the above dependency listed in mathgl's go.mod.

Using a local replacement with an updated go.mod seems to resolve the issue, but I don't really want to have to create a fork just for that reason.

Is go 1.13 planned to be supported, or shall I expect to fork this package to host a supported version myself?

Performance of basic vector math operations could be up to a 100 times faster.

Here's a quick benchmark:


package game

import (
	"testing"
	"math"
)

type CustomVec3 struct {
	x float32
	y float32
	z float32
}

func Benchmark_TestVec3(b *testing.B) {
	var customVecs = make([]CustomVec3, 300000)
	var goVecs = make([]Vec3, 300000)

	b.Run("Vec3 Normalize", func(b *testing.B) {
    for j := 0; j < b.N; j++ {
			for i := 0; i < len(goVecs); i++ {
				p := goVecs[i]
				p[0] = 1
				p[1] = 1
				p2 := p
				len := float32(math.Sqrt(float64(p2[0] * p2[0] + p2[1] * p2[1] + p2[2] * p2[2])))
				mul := 1.0 / len
				p2[0] = p2[0] * mul
				p2[1] = p2[1] * mul
				p2[2] = p2[2] * mul
			}
		}
	})

	b.Run("CustomVec3 Normalize", func(b *testing.B) {
    for j := 0; j < b.N; j++ {
			for i := 0; i < len(customVecs); i++ {
				p := customVecs[i]
				p.x = 1
				p.y = 1
				p2 := p
				len := float32(math.Sqrt(float64(p2.x * p2.x + p2.y * p2.y + p2.z * p2.z)))
				mul := 1.0 / len
				p2.x = p2.x * mul
				p2.y = p2.y * mul
				p2.z = p2.z * mul
			}
		}
	})
}

Result:
image

It would also be SO nice to just write v.x, v.y, v.z and so on... Don't know what arguments there is really for using [3]float3 as a data structure. I'm assuming it's bounds checking that makes everything so slow?

Write tests

This package is sorely under-tested. Most of the basic functionality can be assumed to work simply by the fact that the examples work, but a lot of test cases are needed to be sure. Especially for the more ugly methods like determinants and inverse (see #2 ).

No glm::translate and glm::scale?

I'm trying to work with OpenGL using mathgl
But without the glm::translate and glm::scale functions (I mean, there are no such functions for Go), nothing comes out
What to do?

Edit:
I've sorted it out, but I need to get an mvp:

model := mgl32.Mat4{}

view := mgl32.LookAtV(
        mgl32.Vec3{0.0, 0.0, 1.0}, // Camera location in the world
	mgl32.Vec3{0.0, 0.0, 0.0}, // Point camera is looking at
	mgl32.Vec3{0.0, 1.0, 0.0}, // Orientation of camera, change 1 to -1 to flip camera upside down
)

proj := mgl32.Perspective(1.0, float32(width/height), 1.0, 10.0)

mvp := proj * view * model // ERROR: Invalid operation: proj * view * model (the operator * is not defined on mgl32.Mat4)

Possible copy & paste errors in tests

The following checks check the same indices and most likely meant to check different indices:

/src/github.com/go-gl/mathgl/mgl32/vec_test.go:27:5: identical expressions on the left and right side of the '||' operator
/src/github.com/go-gl/mathgl/mgl32/vec_test.go:45:5: identical expressions on the left and right side of the '||' operator
/src/github.com/go-gl/mathgl/mgl32/vec_test.go:63:5: identical expressions on the left and right side of the '||' operator
/src/github.com/go-gl/mathgl/mgl64/vec_test.go:29:5: identical expressions on the left and right side of the '||' operator
/src/github.com/go-gl/mathgl/mgl64/vec_test.go:47:5: identical expressions on the left and right side of the '||' operator
/src/github.com/go-gl/mathgl/mgl64/vec_test.go:65:5: identical expressions on the left and right side of the '||' operator

Add SIMD

This is a miscellaneous issue to adding SIMD. I've been doing a lot of work, and what's become clear is that adding SIMD is something that requires a lot of profiling, this may take a while to come to fruition.

Miscelaneous things I've found:

Using explicit assembly (SIMD or not) for anything on a Vec3 or smaller is NOT WORTH IT because of compiler inlining. This includes the cross product, but I haven't checked vector Len yet. If you disable all compiler optimization (-N) it's usually an improvement. I suppose theoretically, if you could convince the compiler to magically inline your SIMD it would work fine, but you can't so...

(Yes, I know SIMD loads 4 values at a time, you can interleave them and use junk slots for Vec3 and Vec2. I figured it was worth experimenting with)

However, the improvements gained on a Vec4 are big enough to be worth it. Combined with pointers it's a massive improvement (10 ns/op to just over 1 ns/op for some simple operations like addition).

Matrices are still a work in progress, but I'm fairly confident I can do some magic with 4x4 matrix inversion and possibly determinants. We'll see if it matters for 3x3. 4x4 Matrix multiplcation can probably be improved simply by adding a SIMD dot product and using the dot on Row/Col instead of writing out the operation like we're doing now.

Add Scale() method

I have use for a method which takes a vector and returns a new vector where every element is the product of the respective elements of the vector and the elements of the receiver vector, e.g.:

func (v1 Vec3) Scale(v2 Vec3) Vec3{
    return Vec3{v1[0] * v2[0], v1[1] * v2[1], v1[2] * v2[2]}
}

In my case I use it to scale the vertices of a 3D object with a per-axis-controllable factor, which is a common CGI feature to have to provide more artistic control over having just a single factor that gets used for each dimension.

It is trivially implementable and testable. This issue is mostly to discuss method name and whether this is wanted. I'm open to creating an MR if this is ok.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.