-
-
Notifications
You must be signed in to change notification settings - Fork 36.1k
Matrix4: Avoid NaN values when scale is zero
#32440
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
Merged
+29
−4
Merged
Changes from 2 commits
Commits
Show all changes
8 commits
Select commit
Hold shift + click to select a range
605b589
Fix: Handle zero scale in Matrix4.extractRotation
Om-Mishra09 2c2c43a
Fix: Apply zero-scale safety to decompose() for consistency
Om-Mishra09 d5d18b4
Refactor: Use identity basis fallback in extractRotation, revert deco…
Om-Mishra09 1843933
Feat: Apply identity fallback to extractBasis as requested
Om-Mishra09 0111597
Style: Fix ESLint padded-blocks errors
Om-Mishra09 7bf0c6f
Refactor: Use determinant check for zero-scale robustness
Om-Mishra09 b96ed88
Refactor: Add determinant guard to decompose() as requested
Om-Mishra09 2fa0485
Update Matrix4.js
Mugen87 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
After some thinking about this change I see it as follows:
I don't think the proposed solution for
extractRotation()is ideal. When the scale is zero and thus the length of the respective matrix column, the method should use the identity basis vector for that column. You can't derive a meaningful rotation from a zero scaled basis vector. The identity basis which is essentially the untransformed default direction makes most sense as a fallback to me. I would try to implement the method like so:@WestLangley What do you think?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I do not see how we can support setting scale to zero.
You can't extract a quaternion from a matrix that is not of full rank -- nor from one that is not orthogonal. And the approach that @Mugen87 has proposed is not invertible.
It would be best to add that this method requires the matrix, at a minimum, to be of full rank.
Also, the method name
extractRotationis misleading. A rotation in three.js represents a pure rotation. The columns in the input matrix may not be orthogonal.Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I understand there are limitations but we should change something to at least avoid
NaNvalues. Can you please recommend an approach with the most plausible result? As far as I understand, the suggested version from my previous comment produces at least an orthogonal matrix.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Mugen87 I have applied your suggested implementation (Identity fallback) to
extractRotation.I reverted my changes to
decompose()for now to keep this consistent. Should I leavedecomposeas-is, or should I apply this same Identity fallback logic to it as well?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I understand you want to support setting
matrix.scale( 0, 0, 0 ). When users do that, the quaternion and position are retained. Restoring the scale to the previous value restores the transform.You are trying to get this particular method to work on an invalid input transform having less than full rank.
Instead of avoiding NaN's, I think we should avoid invalid inputs.
I do not think that is true. You can end up with two basis vectors being identical. Here is a sample input matrix with zero scale on one axis.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My point is: We usually do not check user input or sanitize arguments. And it's hard to forecast how APIs are used and how transformation matrices end up. My goal was to make certain math methods more robust so we do not end up with values that completely break rendering. My feeling is sometimes you expect a consistency level in our math modules which is not always "required" in a 3D engine. So even if from a mathematical standpoint an implementation might produce "incorrect" results, it can be still be beneficial from a development point of view.
So I vote to merge a solution that avoids
NaNvalues.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You are arguing that it is better to silently return an incorrect answer than to flag invalid inputs.
If you want to support zero scale values, I suggest starting with
mesh.matrix.decompose()and (somehow) ensure it avoidsNaNs withmesh.scale.set( 0, 1, 1 ).That method is attempting to extract a pure rotation from a non full-rank matrix, which is not possible.