Commit Graph

63 Commits

Author SHA1 Message Date
Aras Pranckevicius
9439ac41eb I/O tests: change all_geometry scene to not have subd surface, and always print obj failure output diff details
The all_objects.blend test scene (in subversion tests repo) contained an
object with a subdivision surface. Which changes vertex positions
slightly, depending on used OpenSubDiv version and the compile flags. It
seems that the intent of the test was "test export of meshes that use
modifiers", so I changed that object to be a cube with a simple "taper"
modifier instead.

While at it, changed OBJ exporter test code to always print the
"expected and what we got" text difference details, when a test fails.
Much easier to see than just "the files are different" output. The code
to print that was behind an off by default flag for some reason.

This diff should get comitted together with updated all_objects templates
in subversion tests repo.

Reviewed By: Sebastian Parborg
Differential Revision: https://developer.blender.org/D14597
2022-04-08 15:09:22 +03:00
Campbell Barton
8dd3387eb7 Cleanup: spelling & poor wording in code & comments 2022-04-06 19:08:10 +10:00
Hans Goudey
edcbf741df Refactor: Evaluate surface objects as mesh components
This commit furthers some of the changes that were started in
rBb9febb54a492 and subsequent commits by changing the way surface
objects are presented to render engines and other users of evaluated
objects in the same way. Instead of presenting evaluated surface objects
as an `OB_SURF` object with an evaluated mesh, `OB_SURF` objects
can now have an evaluated geometry set, which uses the same system
as other object types to deal with multi-type evaluated data.

This clarification makes it more obvious that lots of code that dealt
with the `DispList` type isn't used. It wasn't before either, now it's
just *by design*. Over 1100 lines can be removed. The legacy curve
draw cache code is much simpler now too. The idea behind the further
removal of `DispList` is that it's better to focus optimization efforts
on a single mesh data structure.

One expected functional change is that the evaluated mesh from surface
objects can now be used in geometry nodes with the object info node.

Cycles and the OBJ IO tests had to be tweaked to avoid using evaluated
surface objects instead of the newly exposed mesh objects.

Differential Revision: https://developer.blender.org/D14550
2022-04-05 11:31:18 -05:00
Campbell Barton
744369c114 Cleanup: move doc-strings into headers
- The comment for create_normals was moved into an inline note
  as it's not related to the public API.
- Use a colon after parameters.

Ref T92709
2022-04-05 07:49:36 +10:00
Campbell Barton
22184f3aee Cleanup: spelling in comments 2022-04-05 07:39:40 +10:00
Aras Pranckevicius
d6f5b02940 OBJ: fix printf specifier compile warning on some compilers 2022-04-04 17:37:13 +03:00
Aras Pranckevicius
a56f53ad56 OBJ: fix mac/linux tests and compile warnings in the new obj importer
Related to D13958
2022-04-04 14:58:45 +03:00
Ankit Meel
e6a9b22384 OBJ: New C++ based wavefront OBJ importer
This takes state of soc-2020-io-performance branch as it was at
e9bbfd0c8c7 (2021 Oct 31), merges latest master (2022 Apr 4),
adds a bunch of tests, and fixes a bunch of stuff found by said
tests. The fixes are detailed in the differential.

Timings on my machine (Windows, VS2022 release build, AMD Ryzen
5950X 32 threads):

- Rungholt minecraft level (269MB file, 1 mesh): 54.2s -> 14.2s
  (memory usage: 7.0GB -> 1.9GB).
- Blender 3.0 splash scene: "I waited for 90 minutes and gave up"
  -> 109s. Now, this time is not great, but at least 20% of the
  time is spent assigning unique names for the imported objects
  (the scene has 24 thousand objects). This is not specific to obj
  importer, but rather a general issue across blender overall.

Test suite file updates done in Subversion tests repository.

Reviewed By: @howardt, @sybren
Differential Revision: https://developer.blender.org/D13958
2022-04-04 13:36:10 +03:00
Aras Pranckevicius
d120a083da Fix T96763: New OBJ Exporter Incorrectly saving the materials in the MTL file
Original report (T96763) only reported the issue of double-space before the texture path, but while adding test coverage I found some other issues that I fixed while at it:

- Incorrectly emits two spaces between `map_Xx` keyword and the texture path, leading to some 3rd party software not finding the textures,
- Emissive texture map (`map_Ke`) was not exported,
- When Mapping node is used on the texture UVs, the "Location" and "Scale" values were mixed up (location written as "scale", scale written as "location).

Added gtest coverage.

Reviewed By: Howard Trickey

Differential Revision: https://developer.blender.org/D14519
2022-04-01 14:59:19 +03:00
Aras Pranckevicius
e2e4c1daaa OBJ: use fmt library instead of sprintf for faster formatting
On Windows/MSVC this gives a minor (~20%) speedup presumably due to a faster float/int formatter. On macOS (Xcode13), this gives a massive speedup, since snprintf that is in system libraries ends up spending almost all the time inside some locale-related mutex lock.

The actual exporter code becomes quite a bit smaller too, since it does not have to do any juggling to support std::string arguments, and the buffer handling code is smaller as well.

Windows (VS2022 release build, Ryzen 5950X 32 threads) timings:
- Blender 3.0 splash scene (2.4GB obj): 4.57s -> 3.86s
- Monkey subdivided level 6 (330MB obj): 1.10s -> 0.99s

macOS (Xcode 13 release build, Apple M1Max) timings:
- Blender 3.0 splash scene (2.4GB obj): 21.03s -> 5.52s
- Monkey subdivided level 6 (330MB obj): 3.28s -> 1.20s

Linux (ThreadRipper 3960X 48 threads) timings:
- Blender 3.0 splash scene (2.4GB obj): 10.10s -> 4.40s
- Monkey subdivided level 6 (330MB obj): 2.16s -> 1.37s

The produced obj/mtl files are identical to before.

Reviewed By: Howard Trickey, Dalai Felinto

Differential Revision: https://developer.blender.org/D13998
2022-03-27 14:25:48 +03:00
Sergey Sharybin
03df72ee4e Implement C++ methods for DNA structures
This change makes it possible to add implementation of common
C++ methods for DNA structures which helps ensuring unsafe
operations like shallow copy are done explicitly.

For example, creating a shallow copy used to be:

  Object temp_object = *input_object;

In the C++ context it was seen like the temp_object is
properly decoupled from the input object, while in the
reality is it not. Now this code becomes:

  Object temp_object = blender:🧬:shallow_copy(*input_object);

The copy and move constructor and assignment operators are
now explicitly disabled.

Other than a more explicit resource management this change
also solves a lot of warnings generated by the implicitly
defined copy constructors w.r.t dealing with deprecated fields.
These warnings were generated by Apple Clang when a shallow
object copy was created via implicitly defined copy constructor.

In order to enable C++ methods for DNA structures a newly added
macro `DNA_DEFINE_CXX_METHODS()` is to be used:

  tpyedef struct Object {
    DNA_DEFINE_CXX_METHODS(Object)
    ...
  } Object;

For the shallow copy use `blender:🧬:shallow_copy()`.

The implementation of the memcpy is hidden via an internal DNA
function to avoid pulling `string.h` into every DNA header.
This means that the solution does not affect on the headers
dependencies.

---

Ideally `DNA_shallow_copy` would be defined in a more explicit
header, but don;t think we have a suitable one already. Maybe
we can introduce `DNA_access.h` ?

Differential Revision: https://developer.blender.org/D14427
2022-03-25 11:45:50 +01:00
Sergey Sharybin
484af996aa Revert "Implement C++ methods for DNA structures"
This reverts commit 8c44793228.

Apparently, this generated a lot of warnings in GCC.

Didn't find a quick solution and is it not something I want to be
trading between (more quiet Clang in an expense of less quiet GCC).

Will re-iterate on the patch are re-commit it.
2022-03-25 10:57:13 +01:00
Sergey Sharybin
8c44793228 Implement C++ methods for DNA structures
This change makes it possible to add implementation of common
C++ methods for DNA structures which helps ensuring unsafe
operations like shallow copy are done explicitly.

For example, creating a shallow copy used to be:

  Object temp_object = *input_object;

In the C++ context it was seen like the temp_object is
properly decoupled from the input object, while in the
reality is it not. Now this code becomes:

  Object temp_object = blender:🧬:shallow_copy(*input_object);

The copy and move constructor and assignment operators are
now explicitly disabled.

Other than a more explicit resource management this change
also solves a lot of warnings generated by the implicitly
defined copy constructors w.r.t dealing with deprecated fields.
These warnings were generated by Apple Clang when a shallow
object copy was created via implicitly defined copy constructor.

In order to enable C++ methods for DNA structures a newly added
macro `DNA_DEFINE_CXX_METHODS()` is to be used:

  tpyedef struct Object {
    DNA_DEFINE_CXX_METHODS(Object)
    ...
  } Object;

For the shallow copy use `blender:🧬:shallow_copy()`.

The implementation of the memcpy is hidden via an internal DNA
function to avoid pulling `string.h` into every DNA header.
This means that the solution does not affect on the headers
dependencies.

---

Ideally `DNA_shallow_copy` would be defined in a more explicit
header, but don;t think we have a suitable one already. Maybe
we can introduce `DNA_access.h` ?

Differential Revision: https://developer.blender.org/D14427
2022-03-25 10:37:56 +01:00
Dalai Felinto
7a028330d2 Cleanup: clang-format 2022-03-24 11:01:12 +01:00
Hans Goudey
aeb2c2afaf Cleanup: Clang tidy
- Deprecated headers
- Else after return
- Inconsistent parameter names (I used the most recently modified)
- Raw string literals
2022-03-23 23:24:54 -05:00
Sergey Sharybin
3d5d8b7f71 Cleanup: Run clang-format on the OBJ exporter 2022-03-23 12:43:03 +01:00
Hans Goudey
64cd927519 Fix T96308: Mesh to BMesh conversion doesn't calculate vertex normals
Currently there is a "calc_face_normal" argument to mesh to bmesh
conversion, but vertex normals had always implicitly inherited whatever
dirty state the mesh input's vertex normals were in. Probably they were
most often assumed to not be dirty, but this was never really correct in
the general case.

Ever since the refactor to move vertex normals out of mesh vertices,
cfa53e0fbe, the copying logic has been explicit: copy the
normals when they are not dirty. But it turns out that more control is
needed, and sometimes normals should be calculated for the resulting
BMesh.

This commit adds an option to the conversion to calculate vertex
normals, true by default. In almost all places except the decimate
and edge split modifiers, I just copied the value of the
"calc_face_normals" argument.

Differential Revision: https://developer.blender.org/D14406
2022-03-22 09:33:50 -05:00
Aras Pranckevicius
8c072cdc93 Obj: try to fix Linux tests
Related to previous D14368 bug fix, the sorting
operator was not necessarily a stable order sort.
2022-03-22 06:39:50 +02:00
Brecht Van Lommel
fab14f7854 Fix build when using WITH_TBB=OFF after recent changes
And wrap tbb::parallel_sort in blender namespace similar to other TBB
functionality.
2022-03-22 01:30:19 +01:00
Aras Pranckevicius
eb1755be35 Fix T96511: New OBJ exporter no longer groups faces by material
Old python exporter in 3.0 and earlier ordered faces by material,
but the new C++ exporter in 3.1+ did not, and was just writing them
in whatever is the order of the mesh data structure.

This mostly does not cause problems, except in some apps e.g.
Procreate -- for large enough meshes, this lack of
"order by material" (which ends up having more usemtl lines)
ends up creating more mesh subsets than necessary inside Procreate.

The change is not computationally heavy, e.g. exporting 6-level
subdivided Monkey mesh goes 1085ms -> 1105ms on my machine.

Reviewed By: @howardt
Differential Revision: https://developer.blender.org/D14368
2022-03-21 20:20:09 +02:00
Aras Pranckevicius
b9123b806f Fix T96470 new obj exporter writing material groups
This is patch D14349 from Aras Pranckevicius.

The logic in the code was _completely different_ from the documentation
and what the python exporter in 3.0 did. The new code assumed that
"export material groups" meant "append material name to the object name",
and was only ever kicking in when the "export object groups" option was
also checked. But the proper behavior (as in 3.0 exporter & the online docs),
is to emit g objectname_materialname before each usemtl line. Which is something entirely else.
2022-03-20 08:59:16 -04:00
Aras Pranckevicius
5bfdaaa800 Fix T96415: new OBJ exporter was applying scaling factor incorrectly
This is patch D14347 from Aras Pranckevicius.

Instead of scaling "the scene" (i.e. transform vertices by object matrix,
then multiply by scale factor), it was instead first applying the scale
factor in local space, and then transforming by the object matrix.
2022-03-19 17:14:53 -04:00
Aras Pranckevicius
8aa365745a Fix T96430: new OBJ exporter wrong normals for non-uniform scale, and wrong face order for negative scale
This applies patch D14343 from Aras Pranckevicius, with a description:

The new 3.1+ OBJ exporter did not have correct logic when faced with
non-uniform & mirrored (negative on odd number of axes) object scale:

- Normals were not transformed correctly (should use inverse transpose of the matrix),
 and were not normalized,
- Face order was not "flipped" when transform has negative scale on odd number of axes
 (visible when using "face orientation" viewport overlay).
2022-03-19 16:20:22 -04:00
Aras Pranckevicius
70720c42c2 Fix T96303: C++ OBJ exporter needs presets and skip modifiers.
This patch, D14303, from Aras Pranckevicius adds presets to the OBJ exporter,
and also adds a checkbox (default on) to apply modifiers before export.
2022-03-13 12:04:52 -04:00
Campbell Barton
aa500c4fca Cleanup: use back-slash for doxygen commands, color after parameters 2022-03-02 12:11:08 +11:00
Hans Goudey
ddf189892c Cleanup: Rename original curve object type enum
This commit renames enums related the "Curve" object type and ID type
to add `_LEGACY` to the end. The idea is to make our aspirations clearer
in the code and to avoid ambiguities between `CURVE` and `CURVES`.

Ref T95355

To summarize for the record, the plans are:
- In the short/medium term, replace the `Curve` object data type with
 `Curves`
- In the longer term (no immediate plans), use a proper data block for
  3D text and surfaces.

Differential Revision: https://developer.blender.org/D14114
2022-02-18 09:50:29 -06:00
Hans Goudey
a9f023e226 BLI: Change dependencies in vector math files
This patch reverses the dependency between `BLI_math_vec_types.hh` and
`BLI_math_vector.hh`. Now the higher level `blender::math` functions
depend on the header that defines the types they work with, rather than
the other way around.

The initial goal was to allow defining an `enable_if` in the types header
and using it in the math header. But I also think this operations to types
dependency is more natural anyway.

This required changing the includes some files used from the type
header to the math implementation header. I took that change a bit
further removing the C vector math header from the C++ header;
I think that helps to make the transition between the two systems
clearer.

Differential Revision: https://developer.blender.org/D14112
2022-02-15 10:27:03 -06:00
Campbell Barton
c434782e3a File headers: SPDX License migration
Use a shorter/simpler license convention, stops the header taking so
much space.

Follow the SPDX license specification: https://spdx.org/licenses

- C/C++/objc/objc++
- Python
- Shell Scripts
- CMake, GNUmakefile

While most of the source tree has been included

- `./extern/` was left out.
- `./intern/cycles` & `./intern/atomic` are also excluded because they
  use different header conventions.

doc/license/SPDX-license-identifiers.txt has been added to list SPDX all
used identifiers.

See P2788 for the script that automated these edits.

Reviewed By: brecht, mont29, sergey

Ref D14069
2022-02-11 09:14:36 +11:00
Sergey Sharybin
ad77b52abc Correction to previous Clang strict warning commit
Need to only pop diagnostic if it was really pushed.

Pointed out by Aras Pranckevicius, thanks!
2022-02-10 16:05:11 +01:00
Sergey Sharybin
9e9355190c Fix compilation with strict Clang flags
There is no `-Wformat-truncation` warning in Clang, so tweak checks
around diagnostics pragma accordingly.
2022-02-10 10:55:50 +01:00
Howard Trickey
f199f03994 Merge branch 'blender-v3.1-release' 2022-02-06 15:00:21 -05:00
Aras Pranckevicius
1d59a7aa77 Fix T95384: new obj exporter inaccurate roughness value in new exporter.
Fixes T95384. New exporter was missing a fix for T94516 that recently got applied to the python exporter.

Also changed the obj export tests code so that when save_failing_test_output is requested and MTL result is different from the golden expectation, it is saved as well, similar to how it's done for the OBJ file result.
2022-02-06 14:53:07 -05:00
Aras Pranckevicius
9261bc9476 Further speedup of new obj exporter.
This change from Aras further parallelizes wihin large meshes (the previous one
just parallelized over objects).

Some stats: on A Windows machine, AMD Ryzen (32 threads):

(one mesh) Monkey subdivided to level 6: 4.9s -> 1.2s (blender 3.1 was 6.3s; 3.0 was 49.4s).
(one mesh) "Rungholt" minecraft level: 8.5s -> 2.9s (3.1 was 10.5s; 3.0 was 73.7s).
(lots of meshes) Blender 3 splash: 6.2s -> 5.2s (3.1 was 48.9s; 3.0 was 392.3s).

On a Linux machine (Threadripper, 48 threads, writing to SSD):
Monkey - 5.08s -> 1.18s (4.2x speedup)
Rungholt - 9.52s -> 3.22s (2.95x speedup)
Blender 3 splash - 5.91s -> 4.61s (1.28x speedup)

For details see patch D14028.
2022-02-06 14:28:22 -05:00
Howard Trickey
94c0a59f95 Merge branch 'blender-v3.1-release'
Also fixed conflicts due to the change in file writing in the new obj exporter
in master, and fixed one of the tests that was added in master but not 3.1.
2022-02-05 18:04:30 -05:00
Aras Pranckevicius
c24b2cdebf Fix T95360, new 3.1 obj exporter losing nurbs curve "endpoint".
The new wavefront .obj exporter in 3.1 was producing slightly invalid parm line syntax (missing u), and was not setting first/last N params to zeroes and ones for curves with "endpoint" flag properly.
2022-02-05 17:51:03 -05:00
Campbell Barton
d82372aee3 Cleanup: spelling in comments 2022-02-02 13:53:46 +11:00
Jeroen Bakker
2216699c64 Cleanup: Change NULL to nullptr. 2022-01-31 15:43:13 +01:00
Aras Pranckevicius
1f7013fb90 Speed up the new OBJ exporter via bigger write buffer and parallelization.
This is a patch from Aras Pranckevicius, D13927. See that patch for full
details. On Windows, the many small fprintfs were taking up a large amount
of time and significant speedup comes from using snprintf into chained buffers,
and writing them all out later.
On both Windows and Linux, parallelizing the processing by Object can also lead
to a significant increase in speed.
The 3.0 splash screen scene exports 8 times faster than the current C++ exporter
on a Windows machine with 32 threads, and 5.8 times faster on a Linux machine
with 48 threads.

There is admittedly more memory usage for this, but it is still using 25 times
less memory than the old python exporter on the 3.0 splash screen scene, so
this seems an acceptable tradeoff. If use cases come up for exporting obj files
that exceed the memory size of users, a flag could be added to not parallelize
and write the buffers out every so often.
2022-01-30 15:03:31 -05:00
Aras Pranckevicius
07514def19 Fix T95328, new obj exporter not exporting custom normals.
Previously, the new obj exporter was only exporting per-vertex normals for faces
marked as "smooth". But a face can have custom normals, as soon as the normals
data layer exists. This change makes it follow the behavior of USD & Collada
exporters and the old Python one, which also export per-vertex normals as soon
as the layer is there. (From Patch D13957.)
2022-01-30 13:48:03 -05:00
Campbell Barton
43e3a33082 Cleanup: spelling in comments 2022-01-24 14:35:23 +11:00
Aras Pranckevicius
9350005d8b Fix T13879 new OBJ exporter not saving files with Unicode characters.
Need to use BLI_fopen instead of fopen.
2022-01-21 20:14:01 -05:00
Howard Trickey
54d69a2fd1 Fix new OBJ exporter to handle instancing.
The new OBJ exporter did not handle object instances.
The fix is to use a dependency graph iterator, asking for instances.
Unfortunately that iterator makes a temporary copy of instance objects
that does not persist past the iteration, but we need to save all the
objects and meshes to write later, so the Object has to be copied now.

This changed some unit tests. Even though the tests don't have instancing,
the iterator also picks up some Text objects as Mesh ones (which is a good
thing), resulting in two more objects in the all_objects.obj file output.
2022-01-21 14:37:33 -05:00
Ankit Meel
36c40760a5 .obj: simplify templates in FileHandler, add comments
- Remove redundant template from `FormattingSyntax`.
- Replace one enable_if with static assert for readability
- Add comments

No functional change expected.

Reviewed by: jacqueslucke
Differential Revision: https://developer.blender.org/D13882
2022-01-21 15:28:04 +05:30
Campbell Barton
eb3ff1d6f9 Cleanup: spelling in comments 2022-01-20 11:59:20 +11:00
Campbell Barton
1d536c21dd Cleanup: clang-format 2022-01-20 11:59:20 +11:00
Howard Trickey
6dd89afa96 Fix obj exporter tests by deduping normals and printing with less precision.
Some new obj exporter tests were disabled because the normals were different
in the last decimal place on different platforms.
The old python exporter deduped normals with their coordinates rounded to
four decimal places. This change does the same in the new exporter.
On one test, this produced a file 25% smaller and even ran 10% faster.
2022-01-17 23:22:40 -05:00
Howard Trickey
9109ea0b96 Disable some failing new obj exporter tests.
The switch to how normals are kept has led to tiny differences in
the normal output values on different platforms. Disabling the failing
tests while working on a solution to this problem.
2022-01-14 12:34:07 -05:00
Hans Goudey
cfa53e0fbe Refactor: Move normals out of MVert, lazy calculation
As described in T91186, this commit moves mesh vertex normals into a
contiguous array of float vectors in a custom data layer, how face
normals are currently stored.

The main interface is documented in `BKE_mesh.h`. Vertex and face
normals are now calculated on-demand and cached, retrieved with an
"ensure" function. Since the logical state of a mesh is now "has
normals when necessary", they can be retrieved from a `const` mesh.

The goal is to use on-demand calculation for all derived data, but
leave room for eager calculation for performance purposes (modifier
evaluation is threaded, but viewport data generation is not).

**Benefits**
This moves us closer to a SoA approach rather than the current AoS
paradigm. Accessing a contiguous `float3` is much more efficient than
retrieving data from a larger struct. The memory requirements for
accessing only normals or vertex locations are smaller, and at the
cost of more memory usage for just normals, they now don't have to
be converted between float and short, which also simplifies code

In the future, the remaining items can be removed from `MVert`,
leaving only `float3`, which has similar benefits (see T93602).

Removing the combination of derived and original data makes it
conceptually simpler to only calculate normals when necessary.
This is especially important now that we have more opportunities
for temporary meshes in geometry nodes.

**Performance**
In addition to the theoretical future performance improvements by
making `MVert == float3`, I've done some basic performance testing
on this patch directly. The data is fairly rough, but it gives an idea
about where things stand generally.
 - Mesh line primitive 4m Verts: 1.16x faster (36 -> 31 ms),
   showing that accessing just `MVert` is now more efficient.
 - Spring Splash Screen: 1.03-1.06 -> 1.06-1.11 FPS, a very slight
   change that at least shows there is no regression.
 - Sprite Fright Snail Smoosh: 3.30-3.40 -> 3.42-3.50 FPS, a small
   but observable speedup.
 - Set Position Node with Scaled Normal: 1.36x faster (53 -> 39 ms),
   shows that using normals in geometry nodes is faster.
 - Normal Calculation 1.6m Vert Cube: 1.19x faster (25 -> 21 ms),
   shows that calculating normals is slightly faster now.
 - File Size of 1.6m Vert Cube: 1.03x smaller (214.7 -> 208.4 MB),
   Normals are not saved in files, which can help with large meshes.

As for memory usage, it may be slightly more in some cases, but
I didn't observe any difference in the production files I tested.

**Tests**
Some modifiers and cycles test results need to be updated with this
commit, for two reasons:
 - The subdivision surface modifier is not responsible for calculating
   normals anymore. In master, the modifier creates different normals
   than the result of the `Mesh` normal calculation, so this is a bug
   fix.
 - There are small differences in the results of some modifiers that
   use normals because they are not converted to and from `short`
   anymore.

**Future improvements**
 - Remove `ModifierTypeInfo::dependsOnNormals`. Code in each modifier
   already retrieves normals if they are needed anyway.
 - Copy normals as part of a better CoW system for attributes.
 - Make more areas use lazy instead of eager normal calculation.
 - Remove `BKE_mesh_normals_tag_dirty` in more places since that is
   now the default state of a new mesh.
 - Possibly apply a similar change to derived face corner normals.

Differential Revision: https://developer.blender.org/D12770
2022-01-13 14:38:25 -06:00
Jeroen Bakker
0882069095 Cleanup: codestyle obj_exporter_tests.cc. 2022-01-12 13:02:28 +01:00
Jeroen Bakker
1552b86b55 Cleanup: Not needed if statement around delete. 2022-01-12 13:02:28 +01:00