-
-
Notifications
You must be signed in to change notification settings - Fork 36.1k
WIP: Support negative scale factors #12720
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
Conversation
|
I would be very happy if a solution to this issue gets merged! Thoughts:
|
How cpu intensive would that be...? |
|
@mrdoob I have not investigated the performance issue, but it does appear that this pattern works in general: var onBeforeRender = function() {
this.frontFaceCW = ( this.isMesh && this.matrixWorld.determinant() < 0 );
};So we a have a proof-of-concept. (In practice, we would have the renderer handle this.) Whether we automate this is up to you. I suppose automation would be handy if a user has a hierarchical model and set a negative scale at the root. Might as well /ping @bhouston for feedback... |
I vote for adding this to the renderer 👌 |
|
Apologies for the 'intrusion', but is this related to the issue where I have to flip some of my skybox textures every time before using them in my game? For example, download a standard set of 6 skybox textures. Apply them in the correct order as 'multi material' as demonstrated in some of the examples and then you see that the bottom and top images are not matching up. Flipping the top and bottom 180 degrees seems to fix it. My skybox mesh is of type If this is it, it would surely explain a lot and I feel kind of silly not figuring this out by myself 😅 |
|
@haroldiedema No. Whatever problems you are facing are not likely related to the issue addressed in this thread. |
Done. The renderer now handles reflections in the world transform automatically. The only example I have found so far that breaks if a negative scale is applied to a root object is |
|
This is a good solution thank you @WestLangley. I am not a fan of the variable name "frontFaceCW", instead I would prefer a more precise "frontFaceWindingOrder = THREE.WindingOrderClockWise", or something like that, but that is just me being perfectionist/difficult. Feel free to ignore me. |
|
BTW I do worry about the performance of this change. Maybe we should confirm it is not a major problem via the examples that have a lot of objects? Do we calculate a matrix inverse for each object when rendering it? If we do, then we are already calculating the determinant and maybe we could piggyback off that change. If we are not calculating it per object per frame then I worry about the performance impact, especially on slow CPU devices like mobile. If it is a blocker in terms of performance, we could add a flag, to the renderer e.g. renderer.autoWindingOrder = true/false that does this change on a per object per frame basis? Most people do not need this functionality. And even us, who do need it, do not need it to be automatic as we know when matrices go negative determinatnt. Thus I believe that there is only a small minority who need this do be done automatically on a per frame, per object basis. |
|
|
||
| for ( var i = 0; i < 256; i ++ ) { | ||
|
|
||
| lut[ i ] = ( i < 16 ? '0' : '' ) + ( i ).toString( 16 ).toUpperCase(); |
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.
Unrelated to this PR, but this caught my attention.
Why are we calling toUpperCase() 256 times instead of 1 time for the final result when the UUID is generated? This looks like a silly performance issue.
edit: Nevermind, I'm blind apparently... I didn't see the for-loop was only executed once until I opened the code in my IDE.
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.
Unrelated to this PR
It is unrelated. Please file a new issue if you feel it is warranted.
|
@bhouston I have the same concerns that you have, which is why this is proposed as a WIP. But to continue the discussion, one advantage of automating this is a hierarchy of meshes can be mirrored by setting a negative scale on a root object or group. There is no need to set a flag on each mesh in the hierarchy. BTW, when automating this, the negative determinant that needs to be checked is on I can change the variable name once there is agreement on an approach. |
|
Any chance you can remove Apart from that it looks good to me 👍 |
|
I'll file a new PR. :) |
It got merged! 😊 |
|
What's the summary here? |
|
I think it was merged. :) |
This PR addresses the issue raised in #4904 -- negative scale in the object matrix.
Users expect
to "just work". The problem is that application of a negative scale (i.e., a reflection in the object matrix) turns a watertight mesh "inside out".
That is, application of a negative scale -- either to a geometry or to a mesh -- flips the normals as it should, but does not alter the winding order, so the front-faces and normals become inconsistent.
Note that the problem is with the winding order, not the normals.
This PR proposes adding a property to a mesh to "invert the winding order".
The advantage of this approach is the original mesh and the mirrored mesh can share the same geometry and material.
This differs from #4904, where the proposal was to add a material property, instead.
Here is a typical use case:
Implementation is simple, as is evident by the diffs.
Issues:
We could automate this by checking the determinant of the object's world matrix every frame, but I don't think that is a good idea.
This solutions does not address the situation where a parent
Group, for example, has a negative scale.We would have to modify the raycasting logic to accommodate this feature.
We need to decide if we want to add a property to the
MeshClass, itself -- or if a flag on the instance is adequate, as is demonstrated here.. . .
This PR is for discussion, and is not intended to be merged.