A pure Go 3D math library.

Related tags

Images tools mathgl

MathGL Build Status GoDoc

This is a Go matrix and vector math library specialized for Open GL graphics capabilities.

This package is made primarily with code generation for the basic vector and matrix operations, though and functionality beyond that is handwritten.

Vectors and matrices are stored in Column Major Order, just like OpenGL, which means the "transpose" argument should be false when passing in vectors and matrices using this package.

This package is split into two sub-packages. The package mgl32 deals with 32-bit floats, and mgl64 deals with 64-bit ones. Generally you'll use the 32-bit ones with OpenGL, but the 64-bit one is available in case you use the double extension or simply want to do higher precision 3D math without OpenGL.

The old repository, before the split between the 32-bit and 64-bit subpackages, is kept at github.com/Jragonmiris/mathgl (the old repository path), but is no longer maintained.

Examples can be found in github.com/go-gl/example.

Why am I not getting what I see on github!?

You're probably using a combination of go get and an old Go version. The go get utility is programmed to look for tags matching the current Go version. Right now there's a tag for Go1.2.2 for instance, so if you haven't upgraded to Go1.3, go get will grab an older API. See the API Changes section for details on the version tagging.


Feel free to submit pull requests for features and bug fixes. Do note that, aside from documentation bugs, meta (travis.yml etc) fixes, example code, and extremely trivial changes (basic accessors) pull requests will not be accepted without tests corresponding to the new code. If it's a bug fix, the test should test the bug.

mgl64 is generated directly from 32-bit version. To reflect your changes run go generate github.com/go-gl/mathgl/mgl32 (or just go generate in mgl32 directory). Also note that since code generation is used in matrix.go and vector.go, no changes should be made to those files directly. Edit matrix.tmpl or vector.tmpl and run go generate.

API Changes

From now on, no major API breaking changes will be made between Go version releases. That means any time any "x" in Go1.x.x increases. Exceptions are made, of course, for bug fixes. If a bug fix necessitates changing semantics of calling software, it will be changed. (An example is the recent update of Transpose which was mistakenly using row major rules). Deprecated functions may also be nuked at major version released. Before any API breaking changes near major releases, the most recent non-breaking commit will be tagged with the previous Go version number (e.g. Go1.2.2). If no such tag exists, one can assume nothing has been broken.

API-Breaking changes made for latest Go release

Removal of EulerToQuat; use AnglesToQuat with the order ZYX instead.

  • QuatLookAtV implementation

    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.

    opened by pwaller 33
  • Vector.go, matrix.go and mgl64 generation

    Vector.go, matrix.go and mgl64 generation

    Fix for issues #34 and #32

    Run go generate mgl32 to make vector.go, matrix.go and mgl64 (or simply go generate in mgl32 directory). I would appreciate any ideas or suggestions.

    All changes to the lib are purely cosmetic (comments, formatting) apart from following:

    • matstack/transformStack is added to mgl64.
    • mgl64/util.go:MinValue = math.SmallestNonzeroFloat64.
    • Left alone type casts like float64(math.Sqrt(float64(...))). I do believe it's a noop.
    • Additional tests for vectors.
    • Moved vectorStatic and matrixStatic files to templates.
    • Order of vector and matrix functions is changed. Diffs are messy. To get nice diffs one can make a couple of trivial changes to old genprog (I will gladly send it to anyone on request).
    opened by alexvasi 16
  • Fix Travis gofmt check.

    Fix Travis gofmt check.

    Currently, the Travis test passes, but the gofmt diff step is not testing what was intended:

    $ diff <(gofmt -d .) <("")
    /home/travis/build.sh: line 250: : command not found
    The command "diff <(gofmt -d .) <("")" exited with 0.

    This PR fixes it. I've also swapped the the two diff parameters and added -u flag to make the diff (if something isn't gofmt-ed) more readable.

    opened by dmitshur 12
  • Perhaps switch to pointers for matrices and vectors

    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.


    opened by UserAB1236872 10
  • Performance of basic vector math operations could be up to a 100 times faster.

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

    Here's a quick benchmark:

    package game
    import (
    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?

    opened by BjarkeCK 9
  • Added AABB support

    Added AABB support

    I added basic support for axis-aligned bounding boxes. I may go slightly further into other simple intersection tests (capsule, sphere, possibly convex hull), but I'm not turning this into a 3D physics package or anything -- you're not going to see bounding volume hierarchies or anything like that. Intersection tests are very useful even for pure graphical applications.

    opened by UserAB1236872 9
  • how to convert glm to mgl32?

    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
    opened by godispy 7
  • Missing world<->screen transforms.

    Missing world<->screen transforms.

    Both GLU and GLM support this with project and unProject functions.

    There's extensive docs on how both work: http://www.opengl.org/sdk/docs/man2/xhtml/gluProject.xml http://www.opengl.org/sdk/docs/man2/xhtml/gluUnProject.xml

    Since these are common transformations I think they should be in on mathgl.

    opened by toqueteos 7
  • Use new x/image/math/{f32,f64} packages internally.

    Use new x/image/math/{f32,f64} packages internally.

    This is an internal code change, public API remains unchanged. No existing code should break.

    The idea is to start using the new x/image/math/{f32,f64} packages that were finally added to Go (external) standard library. This is just a code organization change with no effect, but it will help us guide towards more standardization in the future. The underlying types are identical.

    I've updated genprog/main.go to match, but I could not run it (aside from testing) because of #34.

    Please review.

    One observation I've made from making this PR is that everything works, but x/image/math/... is missing Mat2 type that mathgl has.

    opened by dmitshur 6
  • Fix MatStack.LeftMul implementations.

    Fix MatStack.LeftMul implementations.

    Both mgl32 and mgl64 versions of matstack.MatStack contain incorrect LeftMul methods; they had an implementation identical to RightMul.

    This commit fixes the LeftMul implementations by swapping the operands to Mul4.

    Fixes #37.

    opened by beaubrueggemann 5
  • Add LenSqr functions

    Add LenSqr functions

    Added SqrLen() functions which return squared vector length. This can make some lines shorter when variable names are long, e.g.: worldSpaceFragmentCenter.Dot(worldSpaceFragmentCenter) vs. worldSpaceFragmentCenter.SqrLen() Understandable if not wanted, though. Mostly learning how 2 github over here. Have a nice day.

    opened by Zyl9393 4
  • Quaternion Slerp honors closest distance.

    Quaternion Slerp honors closest distance.


    This is a fix to the quaternion spherical linear interpolation to make it choose the shortest linear path which is the intended behavior in graphical animations.

    • This is glTF's tutorial by Khronos with a reference Slerp implementation (glTF trying to be the standard for 3D model): https://github.com/KhronosGroup/glTF-Tutorials/blob/master/gltfTutorial/gltfTutorial_007_Animations.md#linear
    //make sure we take the shortest path in case dot Product is negative
    if(dotProduct < 0.0)
        nextQuat = -nextQuat
        dotProduct = -dotProduct
    • This is the cglm library (GLM being used by practically every 3D engine out there). https://github.com/recp/cglm/blob/master/include/cglm/quat.h#L701-L704
    if (cosTheta < 0.0f) {
        cosTheta = -cosTheta;

    You'll find that my changes are in the same spirit as them. Added a test too.

    // Make sure we take the shortest path in case dot product is negative.
    if dot < 0.0 {
        q2 = q2.Scale(-1)
        dot = -dot

    This is a very well known problem. Wikipedia documents it here in detail: https://en.wikipedia.org/wiki/Slerp#Quaternion_Slerp

    However, because the covering is double (q and −q map to the same rotation), the rotation path may turn either the "short way" (less than 180°) or the "long way" (more than 180°). Long paths can be prevented by negating one end if the dot product, cos Ω, is negative, thus ensuring that −90° ≤ Ω ≤ 90°.

    I ran into this corner case using mathgl, my fork will stay up until the changes can get upstream: https://github.com/nitrix/mathgl/tree/fix/quat-slerp-closest

    Cheers, Alex.

    opened by nitrix 0
  • Vulkan compatibility

    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.

    opened by jclc 4
  • FloatEqualThreshhold broken ?

    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)

    opened by ghost 6
  • Error while trying to get library: undefined: sync.Pool

    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
    opened by ghost 5
  • Add SIMD

    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.

    opened by UserAB1236872 7
  • v1.0.0(Sep 18, 2020)

    A stable release tag! mathgl is useful and is not changing rapidly at the moment. It's useful to have a tag for Go modules, so here it is!

    Source code(tar.gz)
    Source code(zip)
OpenGL with Golang
OpenGL with Golang
A pure Go package for coordinate transformations.

WGS84 A pure Go package for coordinate transformations. go get github.com/wroge/wgs84 Usage east, north, h := wgs84.LonLat().To(wgs84.ETRS89UTM(32)).R

Malte Wrogemann 93 Nov 25, 2022
Simple ANSi to PNG converter written in pure Go

AnsiGo Description AnsiGo is a simple ANSi to PNG converter written in pure Go. It converts files containing ANSi sequences (.ANS) into PNG images. Fo

Frederic Cambus 51 May 17, 2022
Image processing algorithms in pure Go

bild A collection of parallel image processing algorithms in pure Go. The aim of this project is simplicity in use and development over absolute high

Anthony N. Simon 3.7k Jan 6, 2023
Pure golang image resizing

This package is no longer being updated! Please look for alternatives if that bothers you. Resize Image resizing for the Go programming language with

Jan Schlicht 2.9k Jan 9, 2023
Rich TIFF/BigTIFF/GeoTIFF decoder/encoder for Go (Pure Go/Zero Dependencies)

Go语言QQ群: 102319854, 1055927514 凹语言(凹读音“Wa”)(The Wa Programming Language): https://github.com/wa-lang/wa TIFF for Go Features: Support BigTiff Support

chai2010 45 Nov 16, 2022
Image resizing in pure Go and SIMD

rez Package rez provides image resizing in pure Go and SIMD. Download: go get github.com/bamiaux/rez Full documentation at http://godoc.org/github.com

Benoît Amiaux 208 Dec 11, 2022
NanoVGo NanoVGNanoVGo is pure golang implementation of NanoVG. The same author maintains the NanoGUI.go project mentioned above.

NanoVGo Pure golang implementation of NanoVG. NanoVG is a vector graphics engine inspired by HTML5 Canvas API. DEMO API Reference See GoDoc Porting Me

Yoshiki Shibukawa 143 Dec 6, 2022
Pure Go encoder/decoder of the QOI image format

QOI - The “Quite OK Image” format for fast, lossless image compression package and small utilities in native Go, quite OK implementation See qoi.h for

Xavier-Frédéric Moulet 58 Nov 12, 2022
geoserver is a Go library for manipulating a GeoServer instance via the GeoServer REST API.

Geoserver geoserver Is a Go Package For Manipulating a GeoServer Instance via the GeoServer REST API. How to install: go get -v gopkg.in/hishamkaram/g

Hisham waleed karam 78 Dec 22, 2022
General purpose library for reading, writing and working with OpenStreetMap data

osm This package is a general purpose library for reading, writing and working with OpenStreetMap data in Go (golang). It has the ability to read OSM

Paul Mach 246 Dec 30, 2022
S2 geometry library in Go

Overview S2 is a library for spherical geometry that aims to have the same robustness, flexibility, and performance as the best planar geometry librar

Go 1.5k Jan 8, 2023
Go package for fast high-level image processing powered by libvips C library

bimg Small Go package for fast high-level image processing using libvips via C bindings, providing a simple programmatic API. bimg was designed to be

Tom 2.1k Jan 2, 2023
Image processing library and rendering toolkit for Go.

blend Image processing library and rendering toolkit for Go. (WIP) Installation: This library is compatible with Go1. go get github.com/phrozen/blend

Guillermo Estrada 61 Nov 11, 2022
Go bindings to OpenGL Utility Library

GLU This package offers minimal bindings for GLU functions. Usage go get github.com/go-gl-legacy/glu License Copyright 2012 The go-gl Authors. All ri

go-gl legacy 21 Aug 18, 2018
Go binding for the cairo graphics library

go-cairo Go binding for the cairo graphics library Based on Dethe Elza's version https://bitbucket.org/dethe/gocairo but significantly extended and up

Erik Unger 125 Dec 19, 2022
A library for playing with colors in go (golang).

go-colorful A library for playing with colors in Go. Supports Go 1.13 onwards. Why? I love games. I make games. I love detail and I get lost in detail

Lucas Beyer 1k Dec 30, 2022
A lightning fast image processing and resizing library for Go

govips A lightning fast image processing and resizing library for Go This package wraps the core functionality of libvips image processing library by

David Byttow 816 Jan 8, 2023
This is old and unmaintained code, ignore it. starfish is a simple, SDL based, 2D graphics and user input library for Go. If you intend to work on it, please fork from the 'devel' branch, not 'master'. Current release: 0.12.0

What is starfish? What starfish is: starfish is a simple 2D graphics and user input library for Go built on SDL. What starfish is not: While it is bui

Gary Talent 12 Jun 4, 2019
A library to read, write, and transform Stereolithography (.stl) files in Go.

stl A library to read, write, and transform Stereolithography (.stl) files in Go. It is used in the command line STL manipulation tool stltool. Featur

Hagen Schendel 65 Sep 26, 2022