toji / gl-matrix Goto Github PK
View Code? Open in Web Editor NEWJavascript Matrix and Vector library for High Performance WebGL apps
Home Page: glmatrix.net
License: MIT License
Javascript Matrix and Vector library for High Performance WebGL apps
Home Page: glmatrix.net
License: MIT License
For the most part, destination as an optional last argument seems to work well in this library. However, for the .set operations, it's a bit confusing, at least for me. Here's why:
For all the binary operators, you have them defined more or less like this:
type.operator = function (lhs, rhs, result)
this roughly corresponds to 'result = lhs operator rhs'.
However, for the set operation - which at least in my case, I think of mentally as the 'equals operator', the definition is:
type.set = function (rhs, lhs)
which corresponds to 'lhs = rhs'.
I spent about 15 minutes tripped up by this and I keep making this mistake as I write more code using gl-matrix. Can you think of any ways to address this? I can see how it might be better to keep dest as the last argument, for consistency.
vec3.unproject allocates a temporary mat4 and MatrixArray(4) ...
Line 389 in 87c6bf1
Line 390 in 87c6bf1
vec3.unproject = function (vec, view, proj, viewport, dest) {
if (!dest) { dest = vec; }
var m = mat4.create();
var v = new MatrixArray(4);
v[0] = (vec[0] - viewport[0]) * 2.0 / viewport[2] - 1.0;
v[1] = (vec[1] - viewport[1]) * 2.0 / viewport[3] - 1.0;
v[2] = 2.0 * vec[2] - 1.0;
v[3] = 1.0;
mat4.multiply(proj, view, m);
if(!mat4.inverse(m)) { return null; }
mat4.multiplyVec4(m, v);
if(v[3] === 0.0) { return null; }
dest[0] = v[0] / v[3];
dest[1] = v[1] / v[3];
dest[2] = v[2] / v[3];
return dest;
};
Should these not be pre-allocated or otherwise reused?
I'd submit a pull-request but I'm still unsure where you want the temporaries to live based on your comment (#3 (comment)) in #3...
I haven't pulled this yet because I'm not sure if having the constants where they are is the right thing for the library. It's good for speed, but I'd like them to have some form of protection against inadvertent changes.
Please advise :)
I think it would be a good idea to add the following to the documentation quat4.inverse:
"Note that if the quat is normalized, it is much faster to use quat4.conjugate"
v should be vec2 not mat2d
mat2d.scale
mat2d.translate
Other functions (multiply
, transpose
, scale
, rotate
, etc.) modify the matrix in place when no dest is provided. mat3.inverse
and mat4.inverse
should do the same, for consistency.
hi - i may have messed up (new to this javascript stuff), but i can't seem to install this via npm (node package manager). any chance you could add it to their registry? thanks, andrew
rad should be Number not mat2
hi, please couldu add a mat4 function for reverse a mat4 to a translation vector and quaternion ? thank's
I was just looking over the code and found these lines here, where the GLMAT_ARRAY_TYPE is not used. Instead Float32Array is used directly:
https://github.com/toji/gl-matrix/blob/master/src/gl-matrix/mat4.js#L29
https://github.com/toji/gl-matrix/blob/master/src/gl-matrix/mat3.js#L29
https://github.com/toji/gl-matrix/blob/master/src/gl-matrix/mat2.js#L29
https://github.com/toji/gl-matrix/blob/master/src/gl-matrix/quat.js#L29
I'm wondering if there is a reason for that? Maybe a required precision?
For me it looks like that makes no sense to not use GLMAT_ARRAY_TYPE there :)
Hi,
In your examples, when creating a perspective matrix, you use gl.uniformMatrix4fv
.
Can you explain why?
Thank you
vec2.add uses the second argument as the target for the result, if do dest supplied, while vec3 uses the first:
vec3.add = function (vec, vec2, dest) {
if (!dest || vec === dest) { <-- first arg is mutable
vec2.add = function(vecA, vecB, dest) {
if (!dest) dest = vecB; <-- second arg is mutable
I'm not sure how you would prefer to address it: via docs or via code (backward compatibility lost). But I think, this is something to remember to v.2.0
This is a proposal for a significant change in the gl-matrix API in the next major (2.x) release, in order to make all dest
arguments explicitly required, instead of optional as they are today.
There has always been a certain degree of confusion about the specifics of the API, particularly concerning what happens when a dest
object is not supplied. Take the following example:
vec3.add(a, b);
It's easy to remember that new vectors tend not to be created (but sometimes they are!), but there is always a question as to where the result goes. Is the result stored in a
or b
? It's documented, but even though I've been using (and helping write!) the library for some time, I'd honestly have to go back to the documentation to double check.
For this reason, I've gotten into the habit of always supplying a dest
, even when I'm reusing one of a
or b
.
Moreover, I'm now looking at benchmark data according to: http://jsperf.com/speed-of-a-conditional-check/2
The benchmarks seem to indicate that there is a moderate performance gain to be had in Chrome and a significant gain to be had in Firefox, by removing the conditional checks required to see if a dest
object has been given. If we alter the API such that dest
is a required object, these checks can be removed.
One last point: the encouragement of good coding practices. Take this example:
mat4.identity()
Today, that will create and return an identity matrix. It's pretty and concise, but at the expense of performance. It's very easy to use calls like this by mistake, and end up producing temporary objects that will be garbage collected. If gl-matrix explicitly requires a dest
, then it looks like:
mat4.identity(mat4.create())
It's a little uglier, which I consider a good thing: ugly code should hopefully lead to refactoring, and the extra scrutiny should lead toward caching and reusing a variable for the computation instead of creating a new one every frame. Also, in this vein, it becomes very easy to do a project-wide search for references to mat4.create
, making it much easier to optimize the code than it would otherwise be.
Thoughts?
The quat4.inverse actually returns the conjungate not the inverse.
See details here:
http://paulbourke.net/miscellaneous/quaternions/
Since I use glMatrix in KickJS I have created a fix in my code.
https://github.com/mortennobel/KickJS/blob/ShadowMap/src/js/math.js#L2364
vec2.scale / vec3.scale / vec4.scale / quat.scale
Parameter b should be Number not vec /quat
On this line of the function quat4.inverse()
, a call to a quat4.dot()
is made, but that function has not been implemented:
https://github.com/toji/gl-matrix/blob/master/gl-matrix.js#L1607
In mat2 array must be 6 value. Please, fix it!
For example: http://simonsarris.com/blog/471-a-transformation-class-for-canvas-to-keep-track-of-the-transformation-matrix
mat3 do not support translate, scale and rotate. Please to FIX!
mat3 is weak matrix.
And mat4.toMat3 translation is 0 (i.e. incorrect convertation).
Returns deprecated dest parameter rather than the new out parameter.
There is a typo in quat.slerp.
quat.slerp = function (out, a, b, t) {
var ax = a[0], ay = a[1], az = a[2], aw = a[3],
bx = b[0], by = b[1], bz = b[2], bw = a[3];
The last assignment should be bw = b[3];
It seems that the ability to use Array objects has been removed in version 2.0 - this seems to be a bit premature with Float32Array allocation still being so slow.
I'm running the old glMatrix v1 release with setMatrixArrayType set to Array as opposed to Float32Arrays. Normally, my program spends about 70% of its time idling with biggest blips in the bottom up view occupying about ~1-2% of the render loop.
However, if I set it to use Float32Arrays it becomes unplayable, with the allocation of temporary Float32Arrays accounting for 30-40% of the render loop.
I could start pooling these temporary vectors, but that could prove to be useless if Float32Arrays ever see the speeds that standard arrays have when allocating (which doesn't seem too far-fetched).
Is v2 set on not having standard Array support?
Copy paste error
Hello,
I run into codepen and found it's nice to place my code.
I used gl-matrix for my codes, so I needed to link gl-matrix raw file.
I had no problem. http://codepen.io/smagch/pen/6/2 http://codepen.io/smagch/pen/5/2
But It's possible that a problem occur if gl-matrix changs the api in the future.
So I think it would be nice to have tags so that people can link specific version of raw gl-matrix easily.
It'll be cinch.
git tag -a v1.3.5 495e3b1416512b60bbe2f00e0074e15757f81d11
git push --tags
This library do not supports:
mat2.inverseVec2(matrix, vec);
Plase, add support.
Hi,
For fun I've tried to replace typed arrays into normal arrays and I was shocked by the results. It's 10 times faster in Chrome. It's also faster in Firefox.
http://jsperf.com/vec3-performances
You might want to switch back to normal arrays as it gives a huge speed up for free :)
I am missing
quat4.fromRotationMatrix
quat4.toMat3
quat4.toMat4
in 2.X
mat4.fromRotationTranslation mentions a quat4.toMat4 but I can't find it.
( and it should be quat.toMat4 I guess. )
quat.rotateY and quat.rotateZ
Change documentation to 'around the Y axis' and 'around the Z axis'
So I've got a bit of free time on my hands and wanted to direct it at something I've been meaning to do for a while: Start the second iteration of the glMatrix library. This issue is to collect feedback on the proposed changes before we go crazy implementing them.
To be clear, the bump to a 2.0 library would indicate breaking of backwards compatibility, and thus several ill considered design decisions/flaws can be corrected without concern about breaking existing usage. The library in it's current form will likely stick around for a while longer and receive a few minor bug fixes, but new features would be 2.0 facing.
A few items that I feel must be part of the refactor:
In addition there are some things that I would like to see
out = a * b
instead of the current out = b * a
. My only reservation here is that it may make porting code slightly more confusing.Float32Array
constructor.Finally, there's a couple of items that have been proposed by the community but that I'm not sold on:
mat4.multiply()
would be mat4Multiply()
. The reason given is that it would be faster (and it would be, if only a little!) but I'm not sure if I like the idea or not.___Self
. a.k.a: vec3.translateSelf(a, [1, 2, 3]);
would alter a
. This would allow us to retain some current functionality and may even be faster is some cases, but the API is pretty large as-is, and I'm a little reluctant to clutter it further.I'm sure there's other items I can add to this list, but that's what I've got off the top of my head. More feedback is appreciated!
The slerp parameter has been renamed t but is still being referenced in the ratio calculations.
The offending lines:
ratioA = Math.sin((1 - slerp) * halfTheta) / sinHalfTheta;
ratioB = Math.sin(slerp * halfTheta) / sinHalfTheta;
What’s the advantage of having determineMatrixArrayType
return MatrixArray
? If the goal is to make that a public API that consumers can call to find out what the MatrixArray
type is, then it’s broken (or very confusing at any rate), because it will reset the type after the consumer has explicitly called setMatrixArrayType
to change the type. With the current behavior it should be called resetMatrixArrayType
.
I would rewrite as either:
function getMatrixArrayType() {
return MatrixArray;
}
// auto-detect the best type to use as glMatrix’s `MatrixArray`
setMatrixArray((typeof Float32Array !== 'undefined') ? Float32Array : Array);
or else:
function getMatrixArrayType() {
return MatrixArray;
}
// auto-detects the best type to use as glMatrix’s `MatrixArray`
function resetMatrixArrayType() {
setMatrixArray((typeof Float32Array !== 'undefined') ? Float32Array : Array);
}
resetMatrixArrayType();
removed
For instance, vec3.add = function (vec, vec2, dest) ...
puts the result into vec
if the dest
is unspecified.
By contrast, vec2.add = function(vecA, vecB, dest) ...
puts the result into vecB
if the dest
is unspecified.
This is horribly confusing and bound to lead to bugs. One variable naming scheme (vec
/vec2
or vecA
/vecB
) and one “missing desc” convention should be chosen, and then should be used consistently throughout.
It looks to me (without examining the code history) like the vec3, etc. code was written first, and then the vec2 code was added by someone who didn’t bother to match the original API convention, and no one bothered to examine the new code.
A coworker suggested that it may be nice to have functions in place that create or set translation, rotation, or scale matrices. I feel like that would be a great idea that could potentially make the library more comfortable to work with for people coming from certain environments.
The basic usage of each function would be:
mat4.makeTranslate([x, y, z], dest);
Which would be functionally identical to:
mat4.identity(dest);
mat4.translate(dest, [x, y, z], dest);
But would allow us to skip some math since we're not worried about the previous matrix state. As with identity
if no dest
is provided we would create a new mat4 and return it. Obviously there's a use case for having similar methods for mat3
as well. I'm not sure about mat2
.
I'm not 100% sold on the name, as I could see it being either make___
, create___
, or set___
. I'm all ears on opinions there. Also, in keeping with the pattern set by the create
functions we may want to consider having variants that take vectors and variants that take individual components.
Inspired by the WebGL lessons site, I created these two functions:
mat4.push = function(m) {
if (typeof m.stack === "undefined") {
m.stack = [];
}
var copy = mat4.create(m);
copy.stack = m.stack;
m.stack.push(copy);
};
mat4.pop = function(m) {
if (typeof m.stack === "undefined" || m.stack.length === 0) {
throw "invalid mat4.pop";
}
mat4.set(m.stack.pop(), m);
};
Usage:
mat4.push(mvMatrix);
... do other transforms
mat4.pop(mvMatrix);
The intention being that any matrix can now be "pushed" or "popped", without need to write functions specific to the current model view matrix variable.
The stack is stored (but only when "push" is used) as an additional array stored on the matrix, and each element in the stack maintains its own reference to that array.
Feel free to include it, if you think it's useful.
"Caclulates the adjugate ..."
Should be
"Calculates the adjugate ... "
hi please add a mat3/4.CreateFromYawPitchRoll() .
look the api of http://msdn.microsoft.com/en-us/library/bb197914.aspx to have any ideas...
add up, forward backward right down left and translation functions to mat4 and mat3 please...
e g : http://msdn.microsoft.com/en-us/library/microsoft.xna.framework.matrix_properties.aspx
Seems like instead of
len = Math.sqrt(x * x + y * y + z * z);
// ...
len = 1 / len;
it would make more sense to do
len = glMath.invsqrt(x * x + y * y + z * z);
Hi,
I was a bit playing with gl-matrix in Dart and I saw on line 493 quat4.fromAxisAngle
but fromAxisAngle
is never defined. Is this on purpose or it's a bug?
First of all, great work! gl-matrix has almost all the features I need so far.
But I think it would be more convenient if mat4.identity(mat4.create()) could be shortened as mat4.identity(). What do you think?
Do a replace all of 'Caclulate' to 'Calculate' :)
Hi,
I just updated my program to work with glMatrix 2.0+. However, I noticed that the function quat4.multiplyVec3 is gone. Is there a replacement with a new name somewhere? Did you guys just forget it by accident?
Thanks in advance for a quick answer.
Tom
Line 337 should be
var x = v[0], y = v[1];
because v is vec2
line: 1350: fn = (far - near); //this doesn't work as expected in opengl
line: 1350: fn = (near - far); //this is correct
line: 1307: dest[10] = -(far + near) / fn; //wrong
line: 1307: dest[10] = (far + near) / fn; //correct
line: 1311: dest[14] = -(far * near * 2) / fn; //wrong
line: 1311: dest[14] = (far * near * 2) / fn; //correct
don't snob me :-)
I propose to add support for TypeScript.
Hi,
The library is missing an operation to multiply 2 vectors component by component. It could be named vec3.mul.
I love the library and have been using it a lot of the past six months. I've built my matrices for open gl using:
mat4.perspective(manta.m_camera.m_fov, manta.m_camera.m_aspect, manta.m_camera.m_near, manta.m_camera.m_far, this.m_projectionMatrix);
...
mat4.lookAt(vEye, vCameraTarget, vUp, cameraMatrix);
...
mat4.multiply(this.m_projectionMatrix, this.m_cameraMatrix, this.m_projectionViewMatrix);
and
gl_Position = uWorldViewProjectionMatrix * vec4(aVertexPosition, 1.0);
in my shader.
But I am having absolutely no luck trying to build a ray from a screen coordinate. I tried:
var invViewMatrix = mat4.create();
mat4.inverse(manta.m_render.m_projectionViewMatrix, invViewMatrix);
var dx = (x / (this.m_viewWidth / 2)) - 1;
var dy = -((y / (this.m_viewHeight / 2)) - 1);
var t1 = [dx, dy, -1, 1.0];
var t2 = [dx, dy, 1, 1.0];
mat4.multiplyVec4(invViewMatrix, t1);
mat4.multiplyVec4(invViewMatrix, t2);
var p1 = vec3.create( [ t1[0] / t1[3], t1[1] / t1[3], t1[2] / t1[3] ]);
var p2 = vec3.create( [ t2[0] / t2[3], t2[1] / t2[3], t1[2] / t2[3] ]);
But this just seems to give me garbage results. Any ideas?
Thanks
The following is from an email I received from Fabrice Bazzaro:
I've worked on the matrix multiplications function (only in the context of 4x4 matrices) and I've potentially found an improvement.
Instead of using 16 cache values for mat2, I use only 4 cache values :
// Cache the matrix values (makes for huge speed increases!)
var a00 = mat[0], a01 = mat[1], a02 = mat[2], a03 = mat[3];
var a10 = mat[4], a11 = mat[5], a12 = mat[6], a13 = mat[7];
var a20 = mat[8], a21 = mat[9], a22 = mat[10], a23 = mat[11];
var a30 = mat[12], a31 = mat[13], a32 = mat[14], a33 = mat[15];
// Cache only the current line of the second matrix
var b0 = mat2[0], b1 = mat2[1], b2 = mat2[2], b3 = mat2[3];
dest[0] = b0*a00 + b1*a10 + b2*a20 + b3*a30;
dest[1] = b0*a01 + b1*a11 + b2*a21 + b3*a31;
dest[2] = b0*a02 + b1*a12 + b2*a22 + b3*a32;
dest[3] = b0*a03 + b1*a13 + b2*a23 + b3*a33;
b0 = mat2[4];
b1 = mat2[5];
b2 = mat2[6];
b3 = mat2[7];
dest[4] = b0*a00 + b1*a10 + b2*a20 + b3*a30;
dest[5] = b0*a01 + b1*a11 + b2*a21 + b3*a31;
dest[6] = b0*a02 + b1*a12 + b2*a22 + b3*a32;
dest[7] = b0*a03 + b1*a13 + b2*a23 + b3*a33;
b0 = mat2[8];
b1 = mat2[9];
b2 = mat2[10];
b3 = mat2[11];
dest[8] = b0*a00 + b1*a10 + b2*a20 + b3*a30;
dest[9] = b0*a01 + b1*a11 + b2*a21 + b3*a31;
dest[10] = b0*a02 + b1*a12 + b2*a22 + b3*a32;
dest[11] = b0*a03 + b1*a13 + b2*a23 + b3*a33;
b0 = mat2[12];
b1 = mat2[13];
b2 = mat2[14];
b3 = mat2[15];
dest[12] = b0*a00 + b1*a10 + b2*a20 + b3*a30;
dest[13] = b0*a01 + b1*a11 + b2*a21 + b3*a31;
dest[14] = b0*a02 + b1*a12 + b2*a22 + b3*a32;
dest[15] = b0*a03 + b1*a13 + b2*a23 + b3*a33;
I've ran a lot of times the benchmark page with the modifications using Chrome and Firefox and it's only significant using Firefox, with Chrome sometimes it's better and sometime no...
It's the first time I'm interesting in sharing and participating in comunity development so I don't know if there is a "process" so I've decided to send you this email.
Perhaps I need to make some other test to validate this modification. If you have the time to give me your opinion, I I'm really interesting.
Sorry about misinterpretation. Working fine.
vec3.direction([0, 0, 0], [0, 0, 1]) returns [0, 0, -1] rather than [0, 0, 1] as expected and as the documentation says it should. I'm on an old release but I checked the latest source and it certainly appears to have the same bug.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.