Schroedingers-Hat / jsphys

Libraries for physics simulation on javascript canvas
GNU Affero General Public License v3.0
11 stars 1 forks source link

Clicky change frame code #55

Closed Schroedingers-Hat closed 12 years ago

Schroedingers-Hat commented 13 years ago

this // If the new frame is basically the same as the old frame, don't bother. if (Math.sqrt(quat4.spaceDot(XShift, XShift)) < 0.0001 && Math.sqrt(quat4.spaceDot(obj.COM.V, obj.COM.V)) < 0.0001) { return;

is going to cause some confusion if we go to make demos at ordinary (non-relativistic) speeds/scales @capnrefsmmat i take it you put it there to stop people repeatedly clicking on some object they're at/right beside or similar?

capnrefsmmat commented 13 years ago

I put it there because, at the time, translating to a frame identical to the current frame caused problems -- everything turned to NaN. I'm not sure if this is still the case or if there's a better way to fix it.

Schroedingers-Hat commented 13 years ago

Ah, there's probably a divide by zero or an imaginary somewhere. Should be able to fix it by refactoring an equation somewhere. Will keep this open as a bug until we need this feature.

Schroedingers-Hat commented 13 years ago

Poked through things a bit, this looks like it's probably the same issue as 59 Things that will help: 64 bit precision, will give you another 9 orders of magnitude before this comes into effect (if it is the problem). Re-factoring some of the maths: Many of the formulae can be rearranged to reduce the effect of (or eliminate) subtracting numbers that are close/dividing by things close to zero, etc

Schroedingers-Hat commented 13 years ago

Found it, figures it'd be in the least pleasant piece of maths.

function cBoostMat(boostV,c) { var boostMagSq=boostV[1]_boostV[1]+boostV[2]_boostV[2]; var gamma=vToGamma(boostV); return (mat4.create([gamma, -boostV[1]_gamma, -boostV[2]_gamma, 0, -boostV[1]_gamma, 1+(gamma-1)_boostV[1]_boostV[1]/boostMagSq, (gamma-1)_boostV[1]_boostV[2]/boostMagSq, 0, -boostV[2]_gamma, (gamma-1)_boostV[1]_boostV[2]/boostMagSq, 1+(gamma-1)_boostV[2]_boostV[2]/boostMagSq, 0, 0, 0, 0, 1 ])); };

This goes a bit whack as boostmagsq and gamma -1 approach zero. Expanding gamma out and re-factoring might help. @capnrefsmmat I don't suppose you feel like some algebra? ^_^

capnrefsmmat commented 13 years ago

A helpful reference:

http://download.oracle.com/docs/cd/E19957-01/806-3568/ncg_goldberg.html#700

As gamma approaches 1, we get catastrophic cancellation. Right? We can try to refactor the equations as explained in the article.

(Now, is it a different problem that causes gamma < 1 in issue #59?)

Schroedingers-Hat commented 13 years ago

Ah, catastrophic cancellation, that's a good name for it. I was struggling to describe. :D There is another almost identical issue that pops up sometimes (59 is a combination of both issues) where 1-blah approaches zero and we take a square root, resulting in NaNs when round-off makes it negative. Refactoring equations doesn't work quite as well here as they're often too simple.

capnrefsmmat commented 13 years ago

So do you think 64-bit values are the best option, or should we give refactoring a shot?

Schroedingers-Hat commented 13 years ago

Well, 64 bit may be a good idea regardless as we get ~5000 acceleration/rotations before round-off becomes detectable. Re-factoring that matrix will help with this. There are also going to be some values which we have to put manual checks on regardless (64 bit won't help as some things are dividing/multiplying by exactly zero).

capnrefsmmat commented 13 years ago

Refactoring equations doesn't work quite as well here as they're often too simple.

Re-factoring that matrix will help with this.

So wait... should I try to refactor it, following the catastrophic cancellation instructions, or not?

Positions are currently represented using glMatrix's quat4, which defaults to Float32Array. Just set glMatrixArrayType = Float64Array somewhere before any quat4s are defined and you can test the impact of 64-bit floats. I'm curious to see if it has any performance impact.

Schroedingers-Hat commented 13 years ago

I'll probably get around to doing it eventually, but it'd be great if you feel like having a go. There's a copy of the matrix here: http://en.wikipedia.org/wiki/Lorentz_transformation#Matrix_form you can leave Bz (boostV[3]) as 0, or include it in the calculations, it won't make any difference right now (but may be useful later).

when I said 'Refactoring equations doesn't work quite as well here as they're often too simple.' I was talking about a couple of other bits, where I've already done it the lazy way rather than refactoring. Such as this (the Math.max.... ): this.radialVPast = (quat4.spaceDot(this.XView, this.V) / Math.max(Math.sqrt(Math.abs( quat4.spaceDot(this.XView, this.XView) )),1e-10) / this.V[0]);

I'd like to keep that sort of thing to places where errors are not cumulative though.

capnrefsmmat commented 13 years ago

I'll have a go at it later tonight.

Schroedingers-Hat commented 13 years ago

Tried the 64 bit thing out. Seemed to slow things down by 10-20% for our calculations. Doesn't seem to effect drawing time, so the impact overall is negligable (~5%).

In the quick test (w/ or w/o 64 bit) drawing seemed to be a lot slower than it was previously (~ an order of magnitude). Could just be because I had lots of large things all on top of one another (along with text visible), as I couldn't be bothered re-creating the random-generation code.

capnrefsmmat commented 13 years ago

@Schroedingers-Hat: I'm working on fixing cBoostMat's units first. The matrix form of the Lorentz transformation uses beta_x, beta_y, and so on, which I presume would be V[1]/c, V[2]/c, and so on. However, the velocity matrix is run through quat4.scale before being passed to cBoostMat and each element is divided by V[0] (gamma, I presume), and if I divide each velocity term by c I get incorrect frame changes. Could you explain what the quat4.scale does and how this should work? Am I misreading the meaning of beta_x?

(Also, I assume that boostMagSq has to be divided by c^2 as well.)

Schroedingers-Hat commented 13 years ago

Dividing everything by V0 would make it dimension-less. Looks like I did it so that the V I passed to cBoostMat would be three-velocity not four-velocity. Suggestions: Either rename it to make this fact more apparent (traditional symbol for V/c (this value) is Beta, so maybe B?) Write a new function with a slightly different name, and I'll go through and replace it on a step by step basis.

Other info, quat4.scale(a,b,c) works as follows the quat4 a is scaled linearly by the scalar b and stored in c if it is present. If not, it is edited in place.

glMatrix non obsfucated source is here http://code.google.com/p/glmatrix/source/browse/glMatrix.js

capnrefsmmat commented 13 years ago

f8eab49a86 significantly changes the behavior of cBoostMat. We should check whether this issue still exists, and if so, start nailing it down to specific variables and expressions to be adjusted.

capnrefsmmat commented 12 years ago

The original problem (translating to a frame identical to the current frame caused problems) no longer causes issues, so I'm going to call this closed.