Skip to content
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

How to mirror Camera around X-axis? #3001

Closed
roxlu opened this issue Aug 25, 2020 · 14 comments · Fixed by #3108
Closed

How to mirror Camera around X-axis? #3001

roxlu opened this issue Aug 25, 2020 · 14 comments · Fixed by #3108
Assignees

Comments

@roxlu
Copy link
Contributor

roxlu commented Aug 25, 2020

I want to mirror my scene around the X-axis so I tried to flip the X-axis by setting the X scale of my camera matrix to -1 but this results in a pure black scene. I'm trying to get the same behavior as in Blender. For example, consider this scene where I've set the X scaling to -1 of the default camera. When viewing through the default viewport camera you see the normal scene (w/o the X-mirroring).

image

Then, when I look through the camera with the -1 X scaling, I get:

image

When I render my scene without the negative X scaling it renders fine.

Is there an obvious answer to why this doesn't work in Filament? I've got an idea what might cause this in my engine, but before I dive into that I was wondering if there is a simple explanation why this might be an issue with Filament.

@romainguy
Copy link
Collaborator

This probably changes the winding of faces. Try disabling backface culling?

@prideout
Copy link
Contributor

prideout commented Aug 25, 2020

Instead of mirroring inside the camera matrix, you can apply the mirror using TransformManager, in which case Filament will do the right thing. Filament auto-reverses triangle winding in this scenario (search for reversedWindingOrder in Scene.cpp)

@romainguy
Copy link
Collaborator

You could try to create a root transform, apply the scale on that, and parent everything else in the scene to that room transform.

@roxlu
Copy link
Contributor Author

roxlu commented Aug 26, 2020

Thanks for the suggestions! Going to dive into this.

@roxlu
Copy link
Contributor Author

roxlu commented Aug 26, 2020

I've looked into this and applying a scaling on the Z-axis does work now but the result looks strange; I can't really describe what's going on but maybe the material properties are wrong? Note that instead of mirroring the X axis as described above I'm mirroring on the Z axis.

A: Here is an image without mirroring on the Z axis and a video.

filament-axis-flip-test-render-no-flipping-v3-top-view

B: With mirroring on the Z axis and a video.
filament-axis-flip-test-render-yes-flipping-v3-top-view

I did another test with a test environment map to see if I could see if something obviously was wrong.

C: No mirroring, and a video.
filament-axis-flip-test-render-no-flipping-v2-top-view

D: With mirroring, and a video.
filament-axis-flip-test-render-yes-flipping-v2-top-view

The test environment map:
test-environment-map

I'm not entirely sure why the colors change so much, it's not something I would have expected.

Any thoughts what might cause this?

@romainguy
Copy link
Collaborator

Looks like the normals are pointing the wrong way.

@roxlu
Copy link
Contributor Author

roxlu commented Aug 26, 2020

Thanks, the normals seem wrong indeed. Am I doing something wrong when applying the transformation mabye:

void FilaNode::testTransform() {

    // Get instance and create mirror matrix.
    filament::TransformManager& tm = ctx->getEngineRef().getTransformManager();
    filament::TransformManager::Instance ti = tm.getInstance(fila_entity);
    filament::math::mat4f scale;
    scale[2][2] = -1;

    /* Apply */
    const filament::math::mat4f curr_mat = tm.getTransform(ti);
    tm.setTransform(ti, scale * curr_mat);
  }

A. Rendering the shading_normal without mirroring:

filament-no-mirror-z-normals

B. Rendering the shading_normal with mirroring:
filament-yes-mirror-z-normals

@romainguy romainguy reopened this Aug 26, 2020
@romainguy
Copy link
Collaborator

@pixelflinger @prideout

@prideout
Copy link
Contributor

prideout commented Aug 26, 2020

The glTF spec merely says this:

Implementation Note: If the determinant of the transform is a negative value,
the winding order of the mesh triangle faces should be reversed. This
supports negative scales for mirroring geometry.

However it seems reasonable that we should flip shading normals and do what Blender does. It might be interesting to check behavior in other renderers like Three, Babylon, Unity, and Unreal.

Note to self: our reverse winding feature was added in #1654

I've also filed a bug against the glTF sample repo since this isn't a covered situation.

@stevexbritton
Copy link

Is there any progress on this?
The Android sample-gltf-viewer version 1.9.0 exhibits this problem when "transform" in "transformToUnitCube" is changed to a mirror transform:
val transform = scale(Float3(-scaleFactor, scaleFactor, scaleFactor)) * translation(-center)
The problem is most visible when looking down onto the model.
We want to use reflected versions of our models to save having to produce duplicate models and to reduce download bandwidth.

Thanks in advance,
Steve

@prideout
Copy link
Contributor

I'll take a look.

It would be helpful to have a sample model that provokes the issue without any programmatic changes, since this would allow us to try it out on other popular viewers.

@prideout
Copy link
Contributor

@prideout
Copy link
Contributor

I've reproduced this. Steve's method is the easiest way, or hacking the scale in the first node in the BusterDrone glTF.

I'm still thinking about the best way to fix it for all cases (e.g. with and without provided tangents, clear coat normal, etc).

prideout added a commit that referenced this issue Sep 22, 2020
This was tested by replacing the node 0 scale in BusterDrone with
[-1, 1, 1].

Fixes #3001.
prideout added a commit that referenced this issue Sep 22, 2020
This was tested by replacing the node 0 scale in BusterDrone with
[-1, 1, 1].

Fixes #3001.
prideout added a commit that referenced this issue Sep 22, 2020
This was tested by replacing the node 0 scale in BusterDrone with
[-1, 1, 1].

For future reference, commit f728776 shows when we switched from
transpose(inverse()) to cof().

Fixes #3001.
prideout added a commit that referenced this issue Sep 22, 2020
This was tested by replacing the node 0 scale in BusterDrone with
[-1, 1, 1].

For future reference, commit f728776 shows when we switched from
transpose(inverse()) to cof().

Fixes #3001.
prideout added a commit that referenced this issue Sep 22, 2020
This was tested by replacing the node 0 scale in BusterDrone with
[-1, 1, 1].

For future reference, commit f728776 shows when we switched from
transpose(inverse()) to cof().

Fixes #3001.
prideout added a commit that referenced this issue Sep 22, 2020
This was tested by replacing the node 0 scale in BusterDrone with
[-1, 1, 1].

For future reference, commit f728776 shows when we switched from
transpose(inverse()) to cof(). This was a good change, but before that
particular change, we had a "two wrongs made a right" situation for
mirrored normals.

Fixes #3001.
prideout added a commit that referenced this issue Sep 22, 2020
This was tested by replacing the node 0 scale in BusterDrone with
[-1, 1, 1].

For future reference, commit f728776 shows when we switched from
transpose(inverse()) to cof(). This was a good change, but before that
particular change, we had a "two wrongs made a right" situation for
mirrored normals.

Fixes #3001.
prideout added a commit that referenced this issue Sep 22, 2020
This was tested by replacing the node 0 scale in BusterDrone with
[-1, 1, 1].

For future reference, commit f728776 shows when we switched from
transpose(inverse()) to cof(). This was a good change, but before that
particular change, we had a "two wrongs made a right" situation for
mirrored normals.

Fixes #3001.
prideout added a commit that referenced this issue Sep 22, 2020
This was tested by replacing the node 0 scale in BusterDrone with
[-1, 1, 1].

For future reference, commit f728776 shows when we switched from
transpose(inverse()) to cof(). This was a good change, but before that
particular change, we had a "two wrongs made a right" situation for
mirrored normals.

Fixes #3001.
@stevexbritton
Copy link

I have download release 1.9.3 and it works great with our models, so I just wanted to thanks for fixing this issue so promptly.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
5 participants