Page MenuHome

Alembic: new exporter based on the USD exporter structure
ClosedPublic

Authored by Sybren A. Stüvel (sybren) on May 8 2020, 11:26 AM.

Details

Summary

This patch leverages the AbstractHierarchyIterator to restructure the Alembic exporter. The produced Alembic files have not changed much (details below), as the Alembic writing code has simply been moved from the old exporter to the new. How the export hierarchy is handled changed a lot, though, and also the way in which transforms are computed. As a result, T71395 is fixed.

Differences between the old and new exporter, in terms of the produced Alembic file:

  • Duplicated objects now have a unique numerical suffix.
  • Matrices are computed differently, namely by simply computing the evaluated transform of the object relative to the evaluated transform of its export-parent. This fixes T71395: Alembic - exported file does not keep collection offset, but otherwise should produce the same result as before (but with simpler code).

Compared to the old Alembic exporter, Subdivision modifiers are now disabled in a cleaner, more efficient way (they are disabled when exporting with the "Apply Subdivisions" option is unchecked). Previously the exporter would move to a new frame, disable the modifier, evaluate the object, and enable the modifier again. This is now done before exporting starts, and modifiers are only restored when exporting ends.

Some issues with the old Alembic exporter that have NOT been fixed in this patch:

  • Exporting NURBS patches and curves (see T49114 for example).
  • Exporting flattened hierarchy in combination with dupli-objects. This seems to be broken in the old Alembic exporter as well, but nobody reported this yet.

Diff Detail

Repository
rB Blender
Branch
temp-alembic-exporter-D7664-trimmed-down (branched from master)
Build Status
Buildable 8657
Build 8657: arc lint + arc unit

Event Timeline

Sybren A. Stüvel (sybren) requested review of this revision.May 8 2020, 11:26 AM
Sergey Sharybin (sergey) requested changes to this revision.May 8 2020, 11:47 AM

Just very quick pass. Is hard to review it. I suggest to split the refactor from actual logic changes.

  • You can easily move those axis conversion to a separate file now, do all the changes in other files. You wouldn't even need a review for that since it's no funcitonal changes.
  • I do see changes in the abstract classes. Those should also be able to happen against the current master without involving a huge amount of the new code.

All the above wouldn't cause functional changes, making it easier to review and look into the code if something unforeseen will happen.

After all the abstract code is refactored, the Alembic part will also become just a simple exercise of porting code to a new basement.

Also, when picking C++ language constructions ask yourself: is it really readable? Can it be done in a more explicit and readable way?

source/blender/io/alembic/intern/abc_axis_conversion.h
27–31 ↗(On Diff #24518)

Why not BLI_INLINE ?

source/blender/io/usd/intern/abstract_hierarchy_iterator.h
234–237 ↗(On Diff #24518)

Can't say I am happy with this new semantic. You use std::pair<AbstractHierarchyWriter *, bool> here in the function prototype, where it is hard to tell what is this about, but then you use std::tie(writer, created)when you actually use this function.

Seems too much verbosity, without immediate clear reasoning for it.

First thing you can do is to explain in the comment when and why this created is needed. You can also explain that it actually means that when created is false and writer is not nullptr it means that writer is actually usable, is just was creates some time ago.

Second thing you can do is to wrap this into the named struct:

struct WriterInfo {
  AbstractHierarchyWriter* writer;

  // Is set to truth when ensure_writer() did not find existing writer and did create a new one.
  // Is set to false when writer has been re-used or when allocation of the new one has failed.
  bool newly_created;
}

P.S. You might want to have some helper methods there like constructor, maybe cast to bool so you can do if (!writer_info) { return; } and things like that. If you do that, suggest making it a class then.

tests/gtests/alembic/abc_export_test.cc
110

You are mixing doubles and floats.

This revision now requires changes to proceed.May 8 2020, 11:47 AM

Just to state the obvious, the refactor can also be done in multiple commits. For example, refactor ensure_writer as one change, add determine_graph_index_object as another change.
Some of the stuff will be trivial and will not require review. Some of the stuff would still need to go through review, but will go much faster.

Just very quick pass. Is hard to review it. I suggest to split the refactor from actual logic changes.

👍

  • You can easily move those axis conversion to a separate file now, do all the changes in other files. You wouldn't even need a review for that since it's no funcitonal changes.
  • I do see changes in the abstract classes. Those should also be able to happen against the current master without involving a huge amount of the new code.

I have a bunch of commits in master now for all the little cleanups & safe changes.

Other changes will be offered in separate diffs (D7669, D7670, D7672). Once those are all accepted, I'll update this diff with the remaining changes. Please don't bother with this diff until then ;-)

Sybren A. Stüvel (sybren) planned changes to this revision.May 8 2020, 5:49 PM
Sybren A. Stüvel (sybren) marked an inline comment as done.Jun 19 2020, 5:03 PM
Sybren A. Stüvel (sybren) added inline comments.
source/blender/io/alembic/intern/abc_axis_conversion.h
27–31 ↗(On Diff #24518)

Has always been in there (rB61050f75b13e), I'll replace it in a separate commit.

Sybren A. Stüvel (sybren) marked an inline comment as done.
Sybren A. Stüvel (sybren) edited the summary of this revision. (Show Details)

Extracted a lot of cleanups, these have been committed to master already.

Sybren A. Stüvel (sybren) edited the summary of this revision. (Show Details)
  • No longer mixing float and double in unit tests
Sybren A. Stüvel (sybren) marked an inline comment as done.Jun 19 2020, 5:21 PM

Logic seems fine from reading. Testing I'd leave to you :)

There are some inlined comments mainly about language usage.

source/blender/io/alembic/exporter/abc_archive.cc
64

Buffer is too generic. time_str ?

72

Any specific reason to use std::size_t instead of size_t ?
time_str_len ?

I would also suggest moving this time-to-string logic to an own function.
Maybe even returning string. Performance hit is neglectable, but from API is more clear.

209

In the future use unique_ptr.

245–248

See other comment about deisgnated initializers.

source/blender/io/alembic/exporter/abc_archive.h
44

I don't think you need this. io is the parent namespace, regular symbol resolution in C++ will find ExportSubset for you.

That was the entire idea of putting blender as parent namespace, so you can get rid of using statements.

source/blender/io/alembic/exporter/abc_export_capi.cc
47–50

Its an old code, but using namespace is highly discouraged.

167–172

This is confusing.

I do no think you need struct in C++. You should be able to simply Scene *scene.

For the readability never omit parameter names, wrap them into comment instead: Scene * /*scene*/ (and this is where having * next to the type ;)

But then also, why you discard explicitly passed scene and go via the context?

179–180

Any specific reason to use MEM_mallocN instead of new ?

See MEM_CXX_CLASS_ALLOC_FUNCS.

source/blender/io/alembic/exporter/abc_hierarchy_iterator.cc
72

Are you up- or down- casting here? Hard to tell because there is no indications in this patch.

94

You don't need to cast for delete. Unless the destructor is NOT marked as virtual (which it should be).

149–155

Designated initializers are part of the C standard, they are not part of C++ standard.

In some compilers and settings they appear to work if you provide all fields in exact order of their declaration. They will not work the same as in C.

I would strongly advice against using them.

247–255

This can be changed:

unique_ptr<MyClass*> object(new MyClass());
if (error_happenned) {
  return nullptr;
}
return object.release();
source/blender/io/alembic/exporter/abc_hierarchy_iterator.h
51–52

See the inlined comment about designated initialized below.

If you don't sue them you can't have these fields const. Make them non-const and use const qualifier to the variable itself:

const ABCWriterConstructorArgs my_args = Foo();
73

override implies virtual, so from the language point of view it's file.

For the readability it's arguably better to have explicit virtual anyway. However, some of the tidy warnings considers this bad readability.

Anyway, need to be consistent at least. Here you rely on implicit virtual but few lines above you explicitly mark virtual.

source/blender/io/alembic/exporter/abc_subdiv_disabler.h
45–48

explicit

Unless is absolutely needed mark all single-argument constructors as explicit.

source/blender/io/alembic/exporter/abc_writer_abstract.h
29–30

Move extern "C" to headers as much as possible.

source/blender/io/alembic/exporter/abc_writer_mesh.cc
196–199

Ideally should be in own function, for readability.

207–208

triangulated_mesh

source/blender/io/alembic/exporter/abc_writer_nurbs.cc
52

Is OK, but not super nice. "Just" iterate the list.

tests/gtests/alembic/abc_export_test.cc
17

Put tests into the namespace. Discourage using namespace

Sybren A. Stüvel (sybren) marked 14 inline comments as done.

I've handled all the remarks marked as 'Done'. The other ones I also fully agree with, and will deal with outside this patch in a later commit as they are basically commenting on pre-existing code (this isn't always clear from only looking at the diff on Phabricator).

  • Removed using blender::io::... and using namespace blender::io::...
  • Removed use of designated initialisers
  • Clarfied situation at ABC_export(Scene *). The explicitly passed Scene * can be avoided altogether, but that's for a different commit.
  • Consistently use virtual when using override.
  • Clarified cast to ABCAbstractWriter *
  • No cast when deleting
  • Use unique_ptr instead of explicitly deleting.
  • explicit single-arg constructors
  • Removed extern "C" { ... }
  • triangulatedtriangulated_mesh
  • Move unit test into the same namespace as the code under test
source/blender/io/alembic/exporter/abc_export_capi.cc
179–180

I un-did the change here, so that this code remains untouched. Will address this comment in a future commit.

Grumpy Frog approves ;)

This revision is now accepted and ready to land.Jun 26 2020, 2:20 PM