Skip to content

Conversation

@vkovec
Copy link
Contributor

@vkovec vkovec commented Oct 30, 2020

Purpose of this PR

Ticket/Jira #: USDU-9

Edit: After investigation this is an error with this specific USD file and not the import code. Changes reverted and added a unit test

If a mesh is lefthanded orientation in the USD file, then it will be partially converted despite being lefthanded already. Fixed to check if mesh is lefthanded earlier and convert accordingly.

Before fix (compared to FBX version exported from Maya, on right):
image

After fix (compared to FBX version exported from Maya, on right):
image

Testing

Functional Testing status:

Added an automated test to compare left vs right handed import.

Manual Test:

  1. Create a left handed mesh in USD (or use the one linked to the issue)
  2. In Unity, run USD > Import as GameObjects
  3. In the Unity Asset, under "Advanced", change the "Change Handedness" settings, refresh and check that result is as expected.

Performance Testing status:

Should not affect performance.

Overall Product Risks

Complexity:

Low

Halo Effect:

Low

Additional information

Note to reviewers:

Reminder:

  • Add entry in CHANGELOG.md (if applicable)

Copy link
Contributor

@judubu judubu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Damn, I looked at this code so many times before, and still I missed it!
Good job.

@judubu judubu requested review from jcowles and thomas-tu October 30, 2020 19:34
@vkovec vkovec marked this pull request as ready for review October 30, 2020 20:28
}

[Test]
public void TestLeftHandedUsdImport()
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there is probably a better way to test this, adding this for now to check that the same cube is handled differently whether it is right or left handed.

@jcowles
Copy link
Contributor

jcowles commented Nov 2, 2020

This should also fix issue #76 which has a repro.

At first glance what you have seems correct, but I want to read over it more carefully later today

This is awesome!

Copy link
Contributor

@jcowles jcowles left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is awesome, thanks for the fix!

Comment on lines 97 to 99
NUnit.Framework.Assert.That(cubeMesh.vertices, Is.Not.EqualTo(leftHandedCubeMesh.vertices));
NUnit.Framework.Assert.That(cubeMesh.triangles, Is.Not.EqualTo(leftHandedCubeMesh.triangles));
NUnit.Framework.Assert.That(cubeMesh.normals, Is.Not.EqualTo(leftHandedCubeMesh.normals));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it enough to compare the data of two import results? Shouldn't we also test the generated mesh against a baked version to ensure the result we get is correct?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is actually a really good point -- especially with a symmetrical mesh like a Cube, you might even be getting identical results, but the floating point error alone might make them look different.

Does Is.Not.EqualTo use a fuzzy/epsilon comparison? If so, is the epsilon small enough to work here?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do like NOT using a baked/golden result though, because it makes the test more robust to other changes and avoids needing to ratchet a baseline.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It should call Equals(), however, looking at the Vector3 documentation it looks like == is safer than Equals for approximate comparison, so I'll change this to be more explicit.

Copy link
Contributor

@jcowles jcowles left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice, LGTM!

@jcowles
Copy link
Contributor

jcowles commented Nov 6, 2020

I approved this, leaving it up to you how to handle the conversation about testing

@@ -0,0 +1,112 @@
using NUnit.Framework;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just noticed, no copyright disclaimer was added to this file

@jcowles
Copy link
Contributor

jcowles commented Nov 9, 2020

Thanks for incorporating all the feedback on this one!
And nice work :)

@cguer cguer self-requested a review November 11, 2020 19:12
Copy link
Contributor

@cguer cguer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm always a bit confused about what the "truth" is when reviewing handedness changes but I noticed one possibly weird behavior testing the assets from the case.

Note: The images below are using the FBX importer in 2019.4, NOT with the new Bake Axis Conversion in 2020.1+. (should I?)

USD version 1.0.3 (last release)
When the Change Handedness parameter is set to Slow And Safe As FBX, the USD geometry matches exactly the FBX geometry
usd_vs_fbx_packman

USD version 1.0.4 (current PR)
There appears to be no difference between Slow And Safe As FBX and Slow And Safe.

Is this the expected behavior?
usd_vs_fbx_pr

@vkovec
Copy link
Contributor Author

vkovec commented Nov 12, 2020

Did some testing with the following software:

  • usdview
  • Maya
  • Cinema4D (same axis system as Unity)

Cinema4D and Maya both seem to export right handed USD files.

I had a hard time finding software to generate left handed USD files, so instead tried making a right handed version of the original hull brush file.
To generate the right handed version, I simply edited all the orientation values in the file to "rightHanded".
Then I did some tests to see how it would be imported compared to the leftHanded version in different software.

All three software listed above imported both the left handed and right handed version in the same way.

In the Maya USD importer, it appears that the orientation is only considered if an object is not doubleSided.
Therefore, I set doubleSided = 0 in both right and left handed files. This time they imported slightly different in usdview and Maya.
(right handed file on left, left handed file on right)
image

In Unity, the right handed version matches the FBX version. See the following two images:

In the below images, the following 4 files were imported into a scene:

  1. an FBX version of the model created by importing the USD into Maya, then exporting as FBX, imported with bake axis conversion disabled.
  2. the original left handed USD. Imported with "Slow and Safe" conversion.
  3. the original USD, edited to change all instances of uniform token orientation = "leftHanded" to uniform token orientation = "rightHanded". Imported with "Slow and Safe" conversion.
  4. Same as 3) but imported with "Slow and Safe as FBX" conversion.

With USD package using fix from this PR:
image

with USD package version 1.0.3 from package manager:
image

  • Note: the FBX imported with bake axis conversion enabled matches 3) in the images.

Based on this information, I may have misunderstood left vs right handed orientation in USD, and the issue seems to be with the file rather than the importer. The file appears to actually be a right handed file.

@jcowles
Copy link
Contributor

jcowles commented Nov 14, 2020

Perhaps this is more helpful, here is a simple USD file with a right and left handed quad:

#usda 1.0

def Xform "World" {

    def Camera "MainCam" {
        double3 xformOp:translate = (0, 0, 10)
        uniform token[] xformOpOrder = [ "xformOp:translate" ] 
        float2 clippingRange = (1, 20)
    }

    def Mesh "RightHanded" {
        token orientation = "rightHanded"
        int[] faceVertexCounts = [4]
        int[] faceVertexIndices = [0, 1, 2, 3]
        point3f[] points = [(0,0,0),
                            (1,0,0),
                            (1,1,0),
                            (0,1,0)]
    }

    def Mesh "LeftHanded" {
        token orientation = "leftHanded"
        int[] faceVertexCounts = [4]
        int[] faceVertexIndices = [0, 3, 2, 1 ]
        point3f[] points = [(-2,0,0),
                            (-1,0,0),
                            (-1,1,0),
                            (-2,1,0)]
    }
}

And this is what it looks like in usdview:
image

And through the camera:
image

@jcowles
Copy link
Contributor

jcowles commented Nov 14, 2020

In the current version of the USD Unity SDK, I get:

image

Which looks correct to me.

I also noticed that the latest revision of this change is effectively a no-op now, right? There is no functional change from stable.

I think Houdini will export left-handed USD files, IIRC.

@jcowles
Copy link
Contributor

jcowles commented Nov 14, 2020

So maybe there was never a bug? facepalm

@vkovec
Copy link
Contributor Author

vkovec commented Nov 16, 2020

I agree it looks like this was never actually a bug. Here is another example with a left handed example file from Houdini:

In Houdini:
image

In usdview:
image

In Maya (not sure why it imports black, otherwise looks correct):
image

In Unity with USD 1.0.3 (package manager):
image

In Unity with this branch:
image

In the last one the normals look off in some areas, in addition to facing the wrong way.

@judubu judubu linked an issue Nov 16, 2020 that may be closed by this pull request
@judubu
Copy link
Contributor

judubu commented Nov 16, 2020

So it seems the conclusion is there never was a bug, it's the tilt brush asset that was wrong. Sorry @vkovec for the time wasted, and thanks to everybody that spent time looking into the issue.
If nobody comment I'll close the ticket.

@jcowles
Copy link
Contributor

jcowles commented Nov 17, 2020

It might be nice to keep the Unit test from this PR, but revert the functional changes.

@vkovec
Copy link
Contributor Author

vkovec commented Nov 17, 2020

@judubu @jcowles sorry for the confusion, I have reverted the changes and fixed up the unit tests to match the correct functionality.

@judubu
Copy link
Contributor

judubu commented Nov 17, 2020

Awesome. Thanks @vkovec Ill merge as soon as Yamato turns green.

@judubu judubu merged commit cdd2aed into dev Nov 17, 2020
@judubu judubu deleted the USDU-9/lefthanded-orientation-not-handled-correctly branch November 17, 2020 23:36
judubu added a commit that referenced this pull request Dec 21, 2020
* Remove the "rebuildAll on clone" logic and add guid as mesh names. (FTV-244)

We used to force a rebuild of the hierarchy when a UsdAsset (game object)
was duplicated to avoid sharing meshes and materials.
This caused an issue when game objects created from usd prefabs in
PlayMode where flagged for rebuild, losing all local edits.

I decided to remove the "rebuildAll on clone" logic and keep meshes and
materials shared between copies of UsdAsset imported as game objects.
That's the behavior I expect when I duplicate a usd asset reading the same
location in a usd file. It's also safe to do for skinned meshes as skinning is applied
in a vertex shader and the underlying shared mesh is not deformed.

The only drawback is that it won't work on deformed meshes in the case
you change playback speed between the copies. But the solution is simple,
you just have to reload and rebuild the hierachy in the UsdAsset.

I also set the name of the meshes with a guid to make it obvious that
the meshes are shared.

* Mesh names contains the go name followed by a short guid

* Only mark a mesh as dynamic when it is animated

* [HOTFIX] Fix game object hierarchy when loading as GameObject

The previous change was bypassing the call to UsdMenu.GetDefaultRoot,
creating broken hierarchies using the absolute root of the usd file "/".

(cherry picked from commit 8d9ffd0)

* Rename master to stable in yamato scripts

* TypeBinder: Add option to disable JIT for bindings

* Scene: Remove BG Executor & Async IO

* Logging: Refactor diagnostic delegate

* IL2CPP: Add "Preserve" attribute

* Swig: Add IL2CPP callback support

For IL2CPP to handle callbacks correctly, the must be tagged with MonoPInvokeCallback

* Swig: Fix order of VtValue/VtArray includes

* Tests: Add unit test for IL2CPP Attributes

* Regenerate code

* BUILDING: Update build steps

* Add Linux library

* Add OSX library

* OSX Build: New build with RPATH

* Docs: Add OSX build notes to BUILDING.md

* export texture value scale (e.g. color * texture)

* test data and test scene

* sample data root gameobject for easier testing

* time-to-frames conversion to prevent QuickLook bugs

* added sample data

* coding style

* requested changes

* UPM-CI: update registry path from bintray to artifactory

* fix texture export pathes for exporting from packages

* support texture wrap modes

* wrap mode test data

* move wrapmode to TextureReaderSample

* USD.NET: Update libs

* ShaderExport: Fix merge conflict fallout

* enabled USDZ export from recorder clip with tmp file (matches UsdzExporter logic)

* fixes to USDZ in-memory export, still WIP

* correct scale when exporting USDZ from timeline clip

* added sample data

* cleanup of temp directory handling and naming

* moved USDZ scale into ExportContext

* Tests: Fix meta file name case problem

* Conventions: fix braces

* CI: switch utils to stable to match the stable VM image

* Timeline: Fix playable name

* first rough pass of exporting in-memory textures and render textures, plus some sane handling of failure cases

* random naming of textures to prevent accidental overrides - TODO needs better system that acutally prevents collisions

* texture name uses original texture name now if it's in AssetDatabase (random name if dynamic texture)

* allow exporting alpha textures

* sample data added

* formatting and cleanup

* requested changes

* add comment for random naming. Also remove "simplification" if texture is in AssetDB (would lead to collisions with textures with identical names)

* TextureExport: Clarify names and clean up conventions

* fix animation export end time regression

* remove duplicate lines

* Fix: load scope as xform (FTV-417)

#154

Scopes are not Xformable per se but can contain payload and hold variantSets. If we want to be able to set the variant before loading the payload we need to load the Scope as a xform.

* Add comment explaining why Scopes are not added to the PrimMap

* Add tests

* Update Usd.Tests asmdef

* Fix test data path

* Add more tests

* Fix tests assertions

* Revert "Update Usd.Tests asmdef"

This reverts commit 4053d6c

* CI: use package-ci/mac image instead of buildfarm/mac

Fix the following errors:
```
[12:31:47.729 INF] UPM-CI is not compatible with your installed version of Nodejs (v9.8.0). Please use Nodejs v10 or above.
For more information on how to resolve this error, including in CI: https://github.cds.internal.unity3d.com/unity/upm-ci-utils#upm-ci-is-not-compatible
---------
/usr/local/lib/node_modules/upm-ci-utils/scripts/postinstall.js:9
    throw new Error(`Incompatible Nodejs Version (${process.version})`);
    ^

Error: Incompatible Nodejs Version (v9.8.0)
    at checkEngineVersion (/usr/local/lib/node_modules/upm-ci-utils/scripts/postinstall.js:9:11)
    at Object.<anonymous> (/usr/local/lib/node_modules/upm-ci-utils/scripts/postinstall.js:13:1)
    at Module._compile (module.js:649:30)
    at Object.Module._extensions..js (module.js:660:10)
    at Module.load (module.js:561:32)
    at tryModuleLoad (module.js:501:12)
    at Function.Module._load (module.js:493:3)
    at Function.Module.runMain (module.js:690:10)
    at startup (bootstrap_node.js:194:16)
    at bootstrap_node.js:666:3
```

* CI: updating promotion.yml with package-ci.mac image

* added isSRGB support

* added conversion type option to SetupTexture

* add super rough PBR support by using shaders from GLTF repo directly

* remove debug log and clean up code

* ChannelCombiner now supports arbitrary channel combinations and inversions

* added DamagedHelmet + MultiMaterial examples

Damaged helmet is open source, MultiMaterial is from me and I'll opensource it

* sample scene

* Shading: Fix duplicate shader parameter bug

* HDRP: Fix emissive map export

* added HDRP PBR Test assets

* fix transparency issues with HDRP export, add keyword checks for common features

* reduce PBR test set size from 65MB to 13MB

* starting to fix specular/metallic for HDRP export

* add support for exporting textures from disk inside package folders (2019.2+)

* added foundations for normal conversion

* added bumped cubes test data for normals export

* re-add rough normal conversion shader

* normals export from memory should work now, not 100% sure about colorspaces for other exports.

* formatting, correct sRGB setting (off) for data textures

* proper normal conversion for Standard / Built-in render path

* added AO-Planes test

* add conversion method for MaskMap to ORM

* restore helmet normal map (was test map)

* USD 20.08: Update BUILDING.md

* USD 20.08: Update minimal build command

* USD 20.08: Update Python build scripts for Python3

* USD 20.08: Update Swig and third_party headers

* USD 20.08: Add property API exports for UsdCs.dll

* USD 20.08: Upgrade UsdCs to VS2019, Win10

* USD 20.08: Fix assembly info file

* USD 20.08:  Regenerate bindings & libs

* USD 20.08: Fix MaterialSample required by API changes

* USD 20.08: Update USD libs for Windows

* USD 20.08: Update libs for final USD 20.08 build

* CI: Update UPM to run on 2019.4, 2020.1

* Serialization: Use CLS compliant IntPtr conversion

* USD 20.08: Update DLLs after CLS change

* USD v20.08: Build UsdCs for Linux

* USD 20.08: Update initUsd for new plug info path

* USD 20.08: Disable xcode code signing

* USD 20.08: Update OSX libs

* USD 20.08: Update USD version in package manifest

* USD 20.08: Update package version to 1.0.4

* USD 20.08: Update Changelog

* USD 20.08: Clean up share folder in bundle

* USD 20.08: Update OSX libs with correct versions

Alembic version was incorrect.
Updated dependent libs for good measure.

* USD 20.08: Remove unused plugInfo files

* USD 20.08: Remove OSX-specific pluginfo files

These used to be required because .dylib was burned into them, however this is no longer the case.

* USD 20.08: Update initUsd to share common plugInfo path for OSX

* ShaderImport: Default emissive color to white

Fixes #206

* ShaderImport: Emissive fixes for HDRP and light baking

* Package: Remove unused meta file

* Udate version in package.json and bump minimum unity version

* Udate changelog for 1.0.3-preview.2

* Yamato: Convert dummy jobs into proper virtual jobs

* Editor: Remove experimental namespace in 2020.2

* Create PR template based on the one used on Ono

* add null check for scene.AccessMask (USDU-13 #215)

* Maintain material names on import (USDU-91 #213)

* set material name to material path

* add unit test

* update changelog

* use name instead of full path

* Initialize USDPayloads.m_isLoaded with its prim load state (USDU-123) (#214)

* Initialize USDPayloads.m_isLoaded with the USD prim state rather than the policy. Otherwise it won't update accordingly if we load/unload the payloads.

* Better naming for tests class and one of the test.

* Update Changelog

* Simplified check on prim

* Clean up tests

* Fix UsdAsset not dirty (USDU-131) (#218)

* Dirty USDAsset in simple view when there's a change. Otherwise, modifications would be lost.

* Update Changelog

* Fix corrupted scene primMap with invalid prim (USDU-60) (#158, #220)

* Fix the scene primMap that was corrupted with invalid prim (USDU-60)

Now, if user try to read a prim at a path that doesn't exist, the
invalid prim is simply ignored. So, when writting back the prim, it's
written as a new prim at the given path.

* Update CHANGELOG (USDU-60)

* Add tests to USD.NET tests (USDU-60)

* Remove test from unit tests (USDU-60)

Co-authored-by: Julien Dubuisson <julien.dubuisson@unity3d.com>

* Ensure stage are reloaded on Refresh and Reload actions (USDU-58) (#155, #216)

* Force stage reloading on Reload and Refresh action (USDU-58)

UsdStage.Open won't open again a layer that is already open. So if the
layer has changed on disk, it needs either to be closed and re-open or
simply reloaded to get the new changes. Otherwise, USD will keep the
opened layer chached it already has in memory.

* Update Changelog (USDU-58)

* Add Unit Tests (USDU-58)

* Let the editor tick to register testfile change (USDU-58)

* Revert unneeded asmdef changes (USDU-58)

* Fix tests by making sure files' mtimes get modified

* Move data file into appropriate folder

* Remove unsused variable

Co-authored-by: Julien Dubuisson <julien.dubuisson@unity3d.com>
Co-authored-by: Thomas Tu <thomastu@unity3d.com>

* Exporting transform overrides should export usda files (USDU-124) (#222)

* Export overrides: use fileExtension param (USDU-124)

* Update changelog (USDU-124)

* Add all usd extensions to the export dialog (hierarchy and overrides)

Co-authored-by: Julien Dubuisson <julien.dubuisson@unity3d.com>

* Left handed orientation not handled correctly (USDU-9)  (#223)

* check handedness of file before changing axis

* update changelog

* add unit test

* code review fixes

* fix withCamera fbx reference not working on all Unity versions

* code review fix - add parens around &&

* code review fix - use epsilon comparison with Vector3's

* Revert "update changelog"

This reverts commit 4d44add.

* revert changes to MeshImporter

* fix left handed cube tests

- fix tests to work with original import implementation

* remove unused using statement

* Create sparse timesamples (USDU-46) (#221)

* use the UsdUtilsSparseAttrValueWriter to write time samples

* Make sure the transform of the SkelRoot object is set

* add unit test

* update changelog

* disable batchmode when running playmode tests

* commit rebuilt dll

* store SparseValueWriter as member variable

- use SparseValueWriter instead of SparseAttrValueWriter so that map from attribute to SparseAttrValueWriter is stored and SparseAttrValueWriter is not recreated each time a value is set.

* update dll after merge

* Drop Unity 2018 support (#227)

* Samples maintenance (USDU-65 USDU-136) (#226)

* Add some path utilities (USDU-65)

Needed to remove the hard coded paths in the samples.
Tests to come.

* ImportMesh Sample: remove hardcoded path (USDU-65)

* ImportMesh Sample: fix compatibility error (USDU-136)

Sample scene was erroring when loaded in 2019.4 because of an non
longer available component

* Add relative path utilities (USDU-65)

And tests

* ImportMaterials Sample: remove hardcoded path

 (USDU-65)

* ImportMaterials Sample: fix compatibility error

(USDU-136)

* ImportMesh Sample: use relative path utils (USDU-65)

* ExportMesh Sample: fix compatibility error (USDU-136)

* Playable Sample: remove hardcoded path (USDU-65)

* HelloUSD Sample: fix compatibility error (USDU-136)

* Remove unused path functions (USDU-65)

* Playable Sample: add missing asmdef (USDU-65)

* Update the changelog with old PRs and github issue ids (USDU-138) (#224)

* Update the changelog with old PRs and github issue ids.

* Updating package manifest for unity min version and package version

* Add changelog from #170

* Update linux binary from CentOS 7 VM (#230)

* Add .editorconfig and reformat the whole package to Unity standards. (#229)

* Release 2.0.0 (#231)

* [HOTFIX] Fix game object hierarchy when loading as GameObject

The previous change was bypassing the call to UsdMenu.GetDefaultRoot,
creating broken hierarchies using the absolute root of the usd file "/".

* Rename master to stable in yamato scripts

* [HOTFIX] Fix game object hierarchy when loading as GameObject

The previous change was bypassing the call to UsdMenu.GetDefaultRoot,
creating broken hierarchies using the absolute root of the usd file "/".

(cherry picked from commit 8d9ffd0)

* Udate version in package.json and bump minimum unity version

* Udate changelog for 1.0.3-preview.2

* UPM-CI: update registry path from bintray to artifactory

* Update changelog with new version number and release date

* Fix name generation of exported in memory textures

* Move yamato pack job to win10 vm

* Fix post build action on Win and Linux

* Add post build action on OSX

* Remove legacy package-manager-ui package from TestProject

Co-authored-by: Marie Fetiveau <marief@unity3d.com>
Co-authored-by: Lucille Caillaud <lucille.caillaud@unity3d.com>

Co-authored-by: Jeremy Cowles <jeremy.cowles@gmail.com>
Co-authored-by: bokken <ju@unity3d.com>
Co-authored-by: bokken <bokken@Mac-mini.local>
Co-authored-by: Felix Herbst <herbst@prefrontalcortex.de>
Co-authored-by: vkovec <viktoria.kovecses@gmail.com>
Co-authored-by: thomas-tu <45040865+thomas-tu@users.noreply.github.com>
Co-authored-by: Lucille Caillaud <51753559+lucillecaillaud@users.noreply.github.com>
Co-authored-by: Thomas Tu <thomastu@unity3d.com>
Co-authored-by: Marie FETIVEAU <703797+mfe@users.noreply.github.com>
Co-authored-by: Marie Fetiveau <marief@unity3d.com>
Co-authored-by: Lucille Caillaud <lucille.caillaud@unity3d.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

MeshImport: orientation="leftHanded" not handled correctly (FTV-204)

6 participants