Code Monkey home page Code Monkey logo

Comments (46)

mrdoob avatar mrdoob commented on May 5, 2024

I don't think moving the whole library to Arrays is a good idea. I still prefer having object.position.x instead of object.position[0]. Matrix4, in the other hand, is mostly used internally.

from three.js.

525c1e21-bd67-4735-ac99-b4b0e5262290 avatar 525c1e21-bd67-4735-ac99-b4b0e5262290 commented on May 5, 2024

object.position.x can still be supported via properties

var vector = [];

vector.__defineGetter__('x', function() { return this[0]; });
vector.__defineGetter__('y', function() { return this[1]; });
vector.__defineGetter__('z', function() { return this[2]; });

vector.__defineSetter__('x', function(value) { this[0] = value; });
vector.__defineSetter__('y', function(value) { this[1] = value; });
vector.__defineSetter__('z', function(value) { this[2] = value; });

vector.x = 0;
vector.y = 1;
vector.z = 2;

console.log(vector.x, vector.y, vector.z);

from three.js.

mrdoob avatar mrdoob commented on May 5, 2024

Hmmm, last time I checked that didn't work on IE9...

I'm testing Matrix4 using Arrays locally and I'm not seeing much change... The graphics API probably being such a bottleneck isn't helping there :) Will continue testing...

from three.js.

525c1e21-bd67-4735-ac99-b4b0e5262290 avatar 525c1e21-bd67-4735-ac99-b4b0e5262290 commented on May 5, 2024

jump in irc if you're around

from three.js.

mrdoob avatar mrdoob commented on May 5, 2024

https://gist.github.com/721717

Am I missing anything? This seems to be 20% slower than using Objects...

from three.js.

525c1e21-bd67-4735-ac99-b4b0e5262290 avatar 525c1e21-bd67-4735-ac99-b4b0e5262290 commented on May 5, 2024

you need to cache the array lookups when they are used more than once. for instance in multiply you are accessing a.array[ 1 ] a few times.

this is how glMatrix does it...

mat4.multiply = function(mat, mat2, dest) {
    if(!dest) { dest = mat }

    // 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];

    var b00 = mat2[0], b01 = mat2[1], b02 = mat2[2], b03 = mat2[3];
    var b10 = mat2[4], b11 = mat2[5], b12 = mat2[6], b13 = mat2[7];
    var b20 = mat2[8], b21 = mat2[9], b22 = mat2[10], b23 = mat2[11];
    var b30 = mat2[12], b31 = mat2[13], b32 = mat2[14], b33 = mat2[15];

    dest[0] = b00*a00 + b01*a10 + b02*a20 + b03*a30;
    dest[1] = b00*a01 + b01*a11 + b02*a21 + b03*a31;
    dest[2] = b00*a02 + b01*a12 + b02*a22 + b03*a32;
    dest[3] = b00*a03 + b01*a13 + b02*a23 + b03*a33;
    dest[4] = b10*a00 + b11*a10 + b12*a20 + b13*a30;
    dest[5] = b10*a01 + b11*a11 + b12*a21 + b13*a31;
    dest[6] = b10*a02 + b11*a12 + b12*a22 + b13*a32;
    dest[7] = b10*a03 + b11*a13 + b12*a23 + b13*a33;
    dest[8] = b20*a00 + b21*a10 + b22*a20 + b23*a30;
    dest[9] = b20*a01 + b21*a11 + b22*a21 + b23*a31;
    dest[10] = b20*a02 + b21*a12 + b22*a22 + b23*a32;
    dest[11] = b20*a03 + b21*a13 + b22*a23 + b23*a33;
    dest[12] = b30*a00 + b31*a10 + b32*a20 + b33*a30;
    dest[13] = b30*a01 + b31*a11 + b32*a21 + b33*a31;
    dest[14] = b30*a02 + b31*a12 + b32*a22 + b33*a32;
    dest[15] = b30*a03 + b31*a13 + b32*a23 + b33*a33;

    return dest;
};

from three.js.

mrdoob avatar mrdoob commented on May 5, 2024

Just tried that. Didn't seem to improve much... :/

from three.js.

525c1e21-bd67-4735-ac99-b4b0e5262290 avatar 525c1e21-bd67-4735-ac99-b4b0e5262290 commented on May 5, 2024

Also, how are you utilising that code?

It kind of looks like they're still objects...

It's not enough to go from an object with properties to an object with an array instead of the properties. You need to drop all "new THREE.Matrix4()" altogether and go with instantiating arrays.

from three.js.

mrdoob avatar mrdoob commented on May 5, 2024

Why? glMatrix.js also uses objects:

var mat4 = {};

from three.js.

gero3 avatar gero3 commented on May 5, 2024

Some performance increasing:

http://jsperf.com/array-vs-object-matrix-inversion/5

from three.js.

alteredq avatar alteredq commented on May 5, 2024

I'm aware of these things, just I didn't get to test / optimize it yet.

This is a bit black magic, you need not to rub JS implementation in a bad way.

Biggest point for fast math in JS is not creating / destroying objects / arrays all the time and cache access.

WebGL folks have been doing a lot of experiments, there is nice page with live tests of several math libraries by Tojiro:

http://glmatrix.googlecode.com/hg/benchmark/matrix_benchmark.html

Also, to be taken into account, using WebGL-only types may limit reach of CanvasRenderer. Should use fallback to normal JS types.

from three.js.

gero3 avatar gero3 commented on May 5, 2024

actually I made a mistake seems like there is still a huge difference

from three.js.

525c1e21-bd67-4735-ac99-b4b0e5262290 avatar 525c1e21-bd67-4735-ac99-b4b0e5262290 commented on May 5, 2024

Why? glMatrix.js also uses objects:

var mat4 = {};

I'm afraid you might be missing the entire point of my benchmark. In glMatrix objects are only used as container objects for the methods.

With glMatrix and others, when you instantiate a new Vector/Matrix/Quaternion you are only instantiating an array...

mat4.create = function(mat) {
  var dest = new glMatrixArrayType(16);
  if (mat) {
    dest[0] = mat[0];
    dest[1] = mat[1];
    dest[2] = mat[2];
    dest[3] = mat[3];
    dest[4] = mat[4];
    dest[5] = mat[5];
    dest[6] = mat[6];
    dest[7] = mat[7];
    dest[8] = mat[8];
    dest[9] = mat[9];
    dest[10] = mat[10];
    dest[11] = mat[11];
    dest[12] = mat[12];
    dest[13] = mat[13];
    dest[14] = mat[14];
    dest[15] = mat[15];
  }
  return dest;
};

With three.js you are instantiating a new object...

THREE.Matrix4 = function () {};
THREE.Matrix4.prototype = {
    n11: 1, n12: 0, n13: 0, n14: 0,
    n21: 0, n22: 1, n23: 0, n24: 0,
    n31: 0, n32: 0, n33: 1, n34: 0,
    n41: 0, n42: 0, n43: 0, n44: 1
}

Apparently in JS there's a vast difference between creating an object and creating an array.

"mjs is designed around speed and simplicity. For example, it doesn’t attempt to stuff vectors and matrices into JavaScript objects. Because the language offers no operator overloading, there’s very little benefit in treating these types as discrete objects, and lots of performance and memory usage downsides. Instead, it provides a set of functions for performing operations on vectors and matrices, which can be any array-like object. For any function that returns a vector or matrix, an existing array can be passed in to take the result, or the function can create a new one. Array reuse ends up being important because of the potential for expensive garbage collection churn eating away at performance."

gero3 18 minutes ago | link
Some performance increasing:
http://jsperf.com/array-vs-object-matrix-inversion/5

That's a nice improvement but you can optimise the OO version all you like and never approach the speed of using simpler arrays.

from three.js.

gero3 avatar gero3 commented on May 5, 2024

hehe actually, that is not completely true as EWGL-matrixes(which uses a OO version) is actually quite comparable with glmatrix and mjs.

PS: I 'm quite biased in this matter as I'm the developer of EWGL-matrixes and active developer in glmatrix .

from three.js.

525c1e21-bd67-4735-ac99-b4b0e5262290 avatar 525c1e21-bd67-4735-ac99-b4b0e5262290 commented on May 5, 2024

True? I did not realise. I'm actually quite impressed you managed to get it going with objects that fast.

I'm sort of torn between whether or not the OO is worth the slowdown (even if it is only a few ms here and there, matters to me) or if I even prefer it over a functional API.

gero3 - you obviously prefer the OO API over the functional API right? That's the reason EWGL exists?

from three.js.

mrdoob avatar mrdoob commented on May 5, 2024

I see I see. I'll play around with this.

Anyway, a couple of things... As I mention, the bottleneck is not matrices but the graphics API. With WebGL this could easily become a bottleneck but, is the shader the one taking care of matrices multiplications (as far as I'm aware of).

Also, for benchmarking... I think it's better to benchmark transformVector3 / transformVector4 as these are the methods called thousands of times (per polygon) rather than multiply which is called just a bunch of times (per object).

from three.js.

525c1e21-bd67-4735-ac99-b4b0e5262290 avatar 525c1e21-bd67-4735-ac99-b4b0e5262290 commented on May 5, 2024

I just find that going back and forth from the "WebGL/canvas" native-typed arrays to the standard arrays is all that much easier with a math library backed by arrays.

When it comes down to choosing, if you disregard the minor differences in speed between glMatrix and EWGL, I think for sake of interoperability between normal and typed arrays I'm inclined to go with the functional API of glMatrix.

from three.js.

525c1e21-bd67-4735-ac99-b4b0e5262290 avatar 525c1e21-bd67-4735-ac99-b4b0e5262290 commented on May 5, 2024

Also, for benchmarking... I think it's better to benchmark transformVector3 / transformVector4 as these are the methods called thousands of times (per polygon) rather than multiply which is called just a bunch of times (per object).

Good point. I'll bust that out...

from three.js.

gero3 avatar gero3 commented on May 5, 2024

well actually, I use only glmatrix anymore. I think it is easier to use and is easier for crossbrowser development.
EWGL-matrices is actually quite a bit older. That is also why it isn't up to date anymore.

from three.js.

525c1e21-bd67-4735-ac99-b4b0e5262290 avatar 525c1e21-bd67-4735-ac99-b4b0e5262290 commented on May 5, 2024

http://jsperf.com/array-vs-object-vector-transformation

http://jsperf.com/array-vs-object-matrix-inversion

At first I had the allocations in the loop and I think it was screwing with the results.

from three.js.

alteredq avatar alteredq commented on May 5, 2024

With WebGL this could easily become a bottleneck but, is the shader the one taking care of matrices multiplications (as far as I'm aware of).

Unfortunately not completely, even with WebGL still quite a lot of math is done in JS.

Shaders do per-vertex and per-fragment math inside objects. Per-object math (modelview and normal matrix) is computed in JS.

So this can indeed become a bottleneck when you have many objects.

That's why all WebGL folks try to come up with own optimized math libraries.

Other option would be to move really everything into shaders, but this is wasteful, as what otherwise would need to be done once per object would have to be repeated for every vertex.

from three.js.

525c1e21-bd67-4735-ac99-b4b0e5262290 avatar 525c1e21-bd67-4735-ac99-b4b0e5262290 commented on May 5, 2024

Thanks for chiming in alteredq.

mrdoob you might might be interested in the vector transformation results for firefox 4 - ~1/3 increase in speed.

from three.js.

 avatar commented on May 5, 2024

Nice to see this discussion going on. While I don't have the knowledge to completely understand the internals of Three.js, I'm building a very cool demo that mimicks Minecraft (minecraft.net) in a simple way, which will profit very much from any speed increase since it's quite heavy. I'll post an issue here when it's done!

from three.js.

525c1e21-bd67-4735-ac99-b4b0e5262290 avatar 525c1e21-bd67-4735-ac99-b4b0e5262290 commented on May 5, 2024

@fabricasapiens - we're doing the exact same thing ^w^

http://www.youtube.com/watch?v=14A3hw4RGSI

http://dev.dekz.net:8001/ - it's online ATM if you guys want to check it out ;)

from three.js.

525c1e21-bd67-4735-ac99-b4b0e5262290 avatar 525c1e21-bd67-4735-ac99-b4b0e5262290 commented on May 5, 2024

BTW it's multiplayer, me and @dekz are on ATM

from three.js.

525c1e21-bd67-4735-ac99-b4b0e5262290 avatar 525c1e21-bd67-4735-ac99-b4b0e5262290 commented on May 5, 2024

You'll need WebGL/websockets and a creative mind ^w^

from three.js.

 avatar commented on May 5, 2024

:D

I'm there and I see the whole structure, but I don't see any of you add blocks... Do you see mine? Maybe a websockets issue? I'm on Ubuntu 10.04 / Chrome 7 with WebGL.

from three.js.

525c1e21-bd67-4735-ac99-b4b0e5262290 avatar 525c1e21-bd67-4735-ac99-b4b0e5262290 commented on May 5, 2024

I just added a whole bunch. The fact you can see the world is proof the sockets (or a compatible mechanism; we're using socket.io which can fallback) are working.

We're adding chat ATM...

from three.js.

525c1e21-bd67-4735-ac99-b4b0e5262290 avatar 525c1e21-bd67-4735-ac99-b4b0e5262290 commented on May 5, 2024

I'm in the three.js IRC if you want to come and tell me a bit about your game...

from three.js.

 avatar commented on May 5, 2024

Ok, I'll wait for the chat, then join in again :)

I'm off doing some other work right now!

edit: what IRC channel?

from three.js.

525c1e21-bd67-4735-ac99-b4b0e5262290 avatar 525c1e21-bd67-4735-ac99-b4b0e5262290 commented on May 5, 2024

http://webchat.freenode.net/

#three.js

from three.js.

mrdoob avatar mrdoob commented on May 5, 2024

Coding a minecraft-like system is quite an ambitious thing to do. I doubt forking my voxel editor would get someone too far...

from three.js.

525c1e21-bd67-4735-ac99-b4b0e5262290 avatar 525c1e21-bd67-4735-ac99-b4b0e5262290 commented on May 5, 2024

http://dev.dekz.net:8001/

from three.js.

525c1e21-bd67-4735-ac99-b4b0e5262290 avatar 525c1e21-bd67-4735-ac99-b4b0e5262290 commented on May 5, 2024

i have some infrastructure in place for facilitating "chunk" based worlds

http://www.youtube.com/watch?v=yUxKq1sm0xc

from three.js.

 avatar commented on May 5, 2024

People like ambitious things ;-)

from three.js.

mrdoob avatar mrdoob commented on May 5, 2024

Yes, I tried it already. That's not minecraft :P That's a Multiused Voxel editor ;)
For me, minecraft is about walking endlessly in a procedurally generated world that you can also modify. The voxel editor can handle a lot of extension, with some bugs I didn't care to fix yet.

Minecraft world seems to be 64M * 64M * 128 = 524288 Million blocks. Unless what you send across websockets it's a perlin noise seed and all the data of blocks modified I doubt you can send that much information ;)

from three.js.

mrdoob avatar mrdoob commented on May 5, 2024

I would very much like to be proven wrong, of course ^^

from three.js.

 avatar commented on May 5, 2024

I indeed guess that there should be an ID for every random world, so that the clients can generate the world on their own, and then apply the changes. This takes some time initially, but the next time, only the changes from previous time need to be synced...

I guess it is possible, even when it might become a Megabyte or two. Minecraft savefiles are only 2Mb as well...!

from three.js.

gero3 avatar gero3 commented on May 5, 2024

http://jsperf.com/diff-in-speed-for-three-js

some enhancements

from three.js.

 avatar commented on May 5, 2024

just benchmarked a few times with Chrome 7. Some 22% speed improvement!

from three.js.

gero3 avatar gero3 commented on May 5, 2024

http://jsperf.com/diff-in-speed-for-three-js/3

another improvement by taking the assumption that d normally never is different then 1

from three.js.

 avatar commented on May 5, 2024

Any idea how this improvement would impact real FPS usage?

from three.js.

gero3 avatar gero3 commented on May 5, 2024

quite largely actually I think altough it still depends on application to application

from three.js.

mrdoob avatar mrdoob commented on May 5, 2024

Implemented :)
Thanks gero3!

from three.js.

mrdoob avatar mrdoob commented on May 5, 2024

Thanks everyone for all the comments and feedback. I think it's best to leave it to another time. Unfortunately such a change would considerably affect the API.

However, some level of performance inprovement has been achieved here. Thanks again gero3!

from three.js.

xseano avatar xseano commented on May 5, 2024

Check out my project featuring one of the first well-developed boilerplates for 3D rendering (ThreeJS) and server-side physics in NodeJS. Using binary data with the NodeJS WebSocket library, it is extremely optimized, but feedback is much wanted. It is meant to act as a platform for IO games, but is arbitrarily built to be used for almost anything.

from three.js.

Related Issues (20)

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.