[Taken]Fix issue #783 & #764#805
Conversation
| store.x = (FastMath.nextRandomFloat() * 2f - 1f) * radius; | ||
| store.y = (FastMath.nextRandomFloat() * 2f - 1f) * radius; | ||
| store.z = (FastMath.nextRandomFloat() * 2f - 1f) * radius; | ||
| store.addLocal(center); |
There was a problem hiding this comment.
Now it creates a random point within a box of the desired side length (=radius) around the center.
The Do-while loop is still necessary to skip the samples outside the sphere
There was a problem hiding this comment.
mhhh... wouldn't it be simpler to do;
store.x = FastMath.nextRandomFloat();
store.y = FastMath.nextRandomFloat();
store.z = FastMath.nextRandomFloat();
store.normalizeLocal(); // <- random direction
store.multLocal(radius); // <- mult by the radius to be inside the sphere radius
store.addLocal(center); // <- relocate around the center.
No loop needed and the normalize ensure that the point is inside the sphere.
There was a problem hiding this comment.
It would be simpler, but would not be uniformly distributed.
There was a problem hiding this comment.
Uh yeah first the x2-1 should stay to allow negative values. But then just take à random length between 0 and radius, and you break the uniformity.
There was a problem hiding this comment.
I might be wrong, but I think there is needs to more probability mass on the points with bigger radius than on the inner points. So if you normalize and then scale with a value between 0 and radius, that distribution must not be uniform, but something like u'=sqrt(1-u^2), as TehLeo suggested.
|
Yes, just as shaman pointed out, it got to pick an uniform point on a sphere. The current method, picks a random point in a box, repeatedly until the point is in the sphere. It forgets to add the center. Here are two methods: Or a method without a while loop. (ref: https://math.stackexchange.com/questions/87230/picking-random-points-in-the-volume-of-sphere-with-uniform-probability ) |
Nehon
left a comment
There was a problem hiding this comment.
getRandomrPoint must be changed.
As a rule of thumb, for the future, I prefer you do one separate PR for each issue. It's a lot simpler to review.
| store.x = (FastMath.nextRandomFloat() * 2f - 1f) * radius; | ||
| store.y = (FastMath.nextRandomFloat() * 2f - 1f) * radius; | ||
| store.z = (FastMath.nextRandomFloat() * 2f - 1f) * radius; | ||
| store.addLocal(center); |
There was a problem hiding this comment.
mhhh... wouldn't it be simpler to do;
store.x = FastMath.nextRandomFloat();
store.y = FastMath.nextRandomFloat();
store.z = FastMath.nextRandomFloat();
store.normalizeLocal(); // <- random direction
store.multLocal(radius); // <- mult by the radius to be inside the sphere radius
store.addLocal(center); // <- relocate around the center.
No loop needed and the normalize ensure that the point is inside the sphere.
|
I see. Next time I will make separated PR. |
|
I've checked your changes. It creates random points within a sphere volume. See the two methods I posted in the comment above. |
|
ok, let me see.. |
|
Almost there. Except the line:
I have to say you are really trying to change the code I provided, which is fine, but try to understand the problem as well. The random point was already selected uniformly within unit sphere volume within the while loop. Thus change that line back to. |
|
Oh my.. I finally understand that line now. |
|
@TehLeo good for you? |
|
Yes, all is fine with #764 . |
|
@jmecn Could you please rebase -i your PR so that it's only 2 commits one for each issue? |
|
@Nehon never use rebase before. But I think I can have a try. |
|
Here is a nice an thorough explanation https://git-scm.com/book/en/v2/Git-Tools-Rewriting-History Edit: that's why I prefer 1 issue per PR because Github allows me to squash all your commits into one. |
Fix issue #783
Fix infinity loop in EmitterSphereShape. issue #764 I test on both method: public void getRandomPoint1(Vector3f store) { float l = FastMath.pow(FastMath.nextRandomFloat(), 1f / 3f); float u = FastMath.nextRandomFloat() * 2f - 1f; float o = FastMath.nextRandomFloat() * FastMath.TWO_PI; store.z = l * u; u = 1f / FastMath.fastInvSqrt(1f - u * u); store.x = l * u * FastMath.cos(o); store.y = l * u * FastMath.sin(o); store.multLocal(radius); store.addLocal(center); } public void getRandomPoint2(Vector3f store) { do { store.x = (FastMath.nextRandomFloat() * 2f - 1f); store.y = (FastMath.nextRandomFloat() * 2f - 1f); store.z = (FastMath.nextRandomFloat() * 2f - 1f); } while (store.lengthSquared() > 1); store.multLocal(radius); store.addLocal(center); } // Test public void testGetRandomPoint() { int n = 1000000; long start = System.nanoTime(); for (int i = 0; i < n; i++) { getRandomPoint1(store); } long time1 = System.nanoTime() - start; start = System.nanoTime(); for (int i = 0; i < n; i++) { getRandomPoint2(store); } long time2 = System.nanoTime() - start; System.out.println("t1:" + time1); System.out.println("t2:" + time2); System.out.println("t1/t2:" + (float) time1 / time2); } Result: t1:352272158 t2:94436324 t1/t2:3.7302613 Method2 seems nearly 4 times faster than method1.
|
@Nehon sir I have conbined the commits, please check my code. |
|
Perfect, nice work. |
|
Why this pr build failed? any reason? |
|
Seems like an error with the buildserver (all buildlogs are null/empty) , I suggest to just commit a extra space or similar somewhere, so that it is triggered again. |
|
No don't commit again I'll relaunch the build |
Fix issue #783 & #764