(* This section is for bug reports and feature requests only. This is NOT a help site. Do not ask help questions here. If you need help, please use stackoverflow. *)
Three.js has 30 uses of Math.atan/atan2:
grep atan three/build/three.js | wc
But JavaScript's Math.atan2(y, x) is extraordinarily slow. In a recent test of 100K 2-triangle geometries (BufferGeometry) the Math.atan2 function was 17-20% of the cpu cost!
This issue is to add a fast, sufficiently accurate atan/atan2 to Three.Math.
Two sites discuss this, many more I'm sure:
https://jsperf.com/is-atan2-fast/9
http://math.stackexchange.com/questions/1098487/atan2-faster-approximation
Up to date system on a 1-year old iMac
Probably Euler and Quaternion are the most critical users.
https://github.com/mrdoob/three.js/search?utf8=%E2%9C%93&q=atan2
@s3ththompson Any plans on speeding up V8's Math.atan2()?
@mrdoob Good question! Do you have a reduced test case that does some non-trivial workload? We can definitely look into it. cc @hashseed @bmeurer
Math.atan2 is currently implemented using the fdlibm algorithm for good precision, which is arguably not the fastest implementation. The concrete implementation can be found in ieee754.cc. I guess if you can provide a good replacement that is faster and has roughly the same precision, we'd be open to use that.
In a recent test of 100K 2-triangle geometries (BufferGeometry) the Math.atan2 function was 17-20% of the cpu cost!
@backspaces Did you have 100K objects in your scene?
Can you identify a three.js example for which atan2 is problematic?
Thanks a lot for the insights @s3ththompson @bmeurer!
When I had to use atan in some primitive shader language that did not have it (cough... flash... cough) I ported this code from Eugene Zatepyakin, Joa Ebert and Patrick Le Clec'h (no idea where they took it from):
public static function atan2(y:Number, x:Number):Number {
var sign:Number = 1.0 - (int(y < 0.0) << 1)
var absYandR:Number = y * sign + 2.220446049250313e-16
var partSignX:Number = (int(x < 0.0) << 1) // [0.0/2.0]
var signX:Number = 1.0 - partSignX // [1.0/-1.0]
absYandR = (x - signX * absYandR) / (signX * x + absYandR)
return ((partSignX + 1.0) * 0.7853981634 + (0.1821 * absYandR * absYandR - 0.9675) * absYandR) * sign
}
it is going to be pretty fast (in something like c) and quite precise too.