-
-
Notifications
You must be signed in to change notification settings - Fork 35.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Vector2/3/4: Avoid divide-by-zero #11253
Conversation
/ping @brianchirls @mattdesl |
Looks good. |
FWIW - I was hit by this in two cases because of a model with 0 length line segments. One case being raycasting silently breaking and producing incorrect results. |
Like I said, this change will hide errors: if you normalize the zero-vector, you will get the zero-vector. Raycaster will generate incorrect results with a zero-length direction vector. Direction vectors must be unit-length in three.js. |
We should protect against divide by zeros when normalizing in a similar way to how it is handled in Industrial Light and Magic's Imath library: https://github.com/openexr/openexr/blob/develop/IlmBase/Imath/ImathVec.h#L1191 I am confused why we are calling the more complex divideScalar( length || 1 ), everywhere instead of the higher level normalize() that has the divide by zero check inside of it. I like to have the check inside normalize() and just use that function everywhere it makes sense. I think most of these divideScalar( length || 1 )s can be replaced with normalize(). |
OK, closing this. |
@WestLangley: wait, why is this closed? It seems like there's some consensus here that a change should be made, even if there's some slight disagreement over the exact implementation. |
@brianchirls The original issue is still open. :) |
@WestLangley said:
Hmm... As far as I understand, @bhouston was in agreement with this PR? |
My understanding was that @bhouston suggested a divide-by-zero check should go in Also, as I said, I was not a fan of my own PR anyway... I know that is somewhat unusual. :) |
Hmm... normalize: function () {
return this.divideScalar( this.length() || 1 );
} Isn't that, effectively, a divide-by-zero check in |
Yes, but it silently returns an incorrect answer if length is zero. I think throwing an error or warning is better.
I understand @bhouston's confusion now. We are not calling it everywhere -- only in methods that need to reuse the value of At the cost of some inefficiency, the test can be localized to |
@WestLangley said :
I've already seen some 3D engine having length as a return value of With this, we could keep the test on As the discussion seems to continue, I await your approval before contributing on this to avoid making various pull requests about the same problem. For now, I will just patch my fork. |
@Ludobaka We return
We use this pattern in the library:
Changing the return value at this point would lead to backward-compatibility issues. |
@mrdoob Restored deleted branch and reopened. If you would like to merge this, I can make any additional changes you request in a follow-up PR. |
Looks good! |
Thanks! |
As discussed in #11241.
This leave the zero-vector unchanged under these methods --and does so without warning.
I am not sure I feel that comfortable with it, but it appears by consensus to be an acceptable trade-off.
/ping @Mugen87 for review