Skip to content

Various improvements - #100

Merged
HeDo88TH merged 36 commits into
OpenDroneMap:masterfrom
pragmaware:personal/szymon/20260729-improve-output-merge
Sep 25, 2026
Merged

HeDo88TH merged 36 commits into
OpenDroneMap:masterfrom
pragmaware:personal/szymon/20260729-improve-output-merge

Conversation

@pragmaware

@pragmaware pragmaware commented Jul 29, 2026 •

Copy link
Copy Markdown
Contributor

This PR contains several improvements including texture packing speed-ups, geometric error estimation, tile overlap, glb support, setting presets and some bug fixes. Look at the individual commits for more information.

I am aware of the fact that this is complicated to evaluate and merge. It's the result of a work I'm doing on a real project and unfortunately I didn't have time to make smaller PRs. You can merge it as it is, cherry-pick some commits, use some as inspiration or ignore everything altogether...

However, the bugfixes are certainly useful. Also the direct *.glb support is interesting because it then allows to run the draco encoder on each tile significantly reducing the output size.

pragmaware added 21 commits July 5, 2026 04:39
… instead of double.Epsilon (which allows only zero difference)
…60729-improve-output-merge

# Conflicts:
#	Obj2Gltf/GltfConverterOptions.cs
#	Obj2Tiles.Library/Geometry/MeshT.cs
#	Obj2Tiles/Options.cs
#	Obj2Tiles/Program.cs
#	Obj2Tiles/Stages/SplitStage.cs
#	Obj2Tiles/Stages/TilingStage.cs
#	Obj2Tiles/Utils.cs
#	README.md
…separate value (one usually wants good quality there)
…separate value (one usually wants good quality there)
@gojushin

Copy link
Copy Markdown
Contributor

Woah. Geometric error estimation and .glb support, are two things I already planned to also look into, some time in the future!
Good stuff!!
This would also set the stage for potential future 3d-tiles 2.0 compatibility!

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR extends Obj2Tiles’ pipeline (Decimation → Splitting → Tiling) with new output/quality controls and several geometry/MTL/texture-handling improvements, including support for emitting plain GLB tile content (3D Tiles 1.1) and more robust geometric-error estimation.

Changes:

  • Add GLB tile output path (alongside legacy b3dm) plus CLI preset support and additional CLI knobs.
  • Introduce per-tile metrics (TileBounds) and new geometric error estimation modes/factors used by the tiling stage.
  • Improve splitting/texture/material handling (tile overlap + deterministic nudge, normal-map parsing/ignoring, texture subfolder fallback, texture quality controls) and performance tweaks (bin pack prune optimization).

Reviewed changes

Copilot reviewed 35 out of 35 changed files in this pull request and generated 8 comments.

Show a summary per file
File Description
TODO Adds roadmap notes for future work
README.md Documents new CLI options and defaults
Obj2Tiles/Utils.cs Enhances dependency copying and adds GLB conversion
Obj2Tiles/Stages/TilingStage.cs Adds GLB output and geometric-error estimation modes
Obj2Tiles/Stages/TileBounds.cs Introduces per-tile bounds + edge metrics record
Obj2Tiles/Stages/SplitStage.cs Propagates overlap/normal-map/quality options; returns TileBounds
Obj2Tiles/Stages/Model/ObjMesh.cs Optimizes OBJ writing via attribute deduplication
Obj2Tiles/Stages/DecimationStage.cs Adds decimation modes and normal-map ignore option
Obj2Tiles/Program.cs Adds preset application and wires new options through pipeline
Obj2Tiles/Options.cs Adds many new CLI options (preset, GLB, overlap, error modes, etc.)
Obj2Tiles.Test/ThreeTzArchiveTests.cs Updates tests for TileBounds mapping
Obj2Tiles.Test/StagesTests.cs Updates stage tests; adds dependency-copy fallback test
Obj2Tiles.Test/ObjParserGltfTests.cs Adds tests for normal-map parsing and glTF validity
Obj2Tiles.sln.DotSettings.user Updates Rider user settings file (likely accidental)
Obj2Tiles.Library/Materials/Material.cs Adds texture-subfolder fallback and normal-map aliases/ignoring
Obj2Tiles.Library/Geometry/VertexUtils.cs Canonicalizes edge endpoints to avoid split cracks
Obj2Tiles.Library/Geometry/Vertex3.cs Fixes equality implementation and epsilon usage
Obj2Tiles.Library/Geometry/Vertex2.cs Switches equality epsilon to Common.Epsilon
Obj2Tiles.Library/Geometry/MeshUtils.cs Adds overlap splitting + deterministic nudge; MTL ignoreNormalMaps
Obj2Tiles.Library/Geometry/MeshT.cs Adds Translate, edge metrics, UV island logic fixes, normal map PNG handling
Obj2Tiles.Library/Geometry/Mesh.cs Adds Translate and edge metrics
Obj2Tiles.Library/Geometry/IMesh.cs Extends interface with Translate and edge metrics
Obj2Tiles.Library/Geometry/Box3.cs Adds Diagonal() helper
Obj2Tiles.Library/Common.cs Replaces unusable epsilon with machine epsilon constant
Obj2Tiles.Library/Algos/MaxRectanglesBinPack.cs Optimizes free-rectangle pruning performance
Obj2Tiles.Library.Test/MtlParsingTests.cs Adds tests for normal-map aliases and texture-subfolder fallback
Obj2Gltf/WaveFront/MtlParser.cs Adds bump/map_Bump support for normal maps
Obj2Gltf/GltfConverterOptions.cs Adds UnlitMaterials option
Obj2Gltf/Gltf/Material.cs Adds material Extensions dictionary support
Obj2Gltf/Converter.cs Adds unlit material support; fixes normal-map-only TEXCOORD emission
MeshDecimatorCore/SimplificationOptions.cs Updates defaults/docs for vertex link epsilon and UV seam/foldover docs
MeshDecimatorCore/Math/Vector4d.cs Updates epsilon constant to machine epsilon
MeshDecimatorCore/Math/Vector3d.cs Updates epsilon constant to machine epsilon
MeshDecimatorCore/Math/Vector2d.cs Updates epsilon constant to machine epsilon
MeshDecimatorCore/Algorithms/FastQuadricMeshSimplification.cs Adds verbose decimation statistics logging
Comments suppressed due to low confidence (3)

Obj2Tiles/Stages/TilingStage.cs:412

  • The XML docs state ToplevelAverageEdgeLength defaults to --error-factor 0.5, but ResolveErrorFactor() defaults edge-length modes to 1.0. Please update this docstring to match behavior.
    Obj2Tiles/Stages/TilingStage.cs:418
  • The XML docs state ToplevelMaximumEdgeLength defaults to --error-factor 0.5, but ResolveErrorFactor() defaults edge-length modes to 1.0. Please update this docstring to match behavior.
    MeshDecimatorCore/SimplificationOptions.cs:49
  • Doc comment typos: “An UV … EnableSmarkLink … boders” should be “A UV … EnableSmartLink … borders” for clarity and to match the actual property name.
        /// An UV foldover edge is a border edge that is duplicated in two distinct
        /// triangles with same UV coordinates (likely normal-related vertex duplication).
        /// This is relevant only if EnableSmarkLink is set to true.
        /// If EnableSmartLink is set to false the UV foldover edges are always treated as boders.
        /// Default value: false

Comment thread Obj2Tiles.Library/Geometry/Vertex3.cs Resolved
Comment thread Obj2Tiles.sln.DotSettings.user Resolved
Comment thread README.md Resolved
Comment thread Obj2Tiles/Stages/TilingStage.cs Resolved
Comment thread README.md Resolved
Comment thread Obj2Tiles/Options.cs Resolved
Comment thread Obj2Tiles/Stages/DecimationStage.cs Resolved
@HeDo88TH HeDo88TH self-assigned this Jul 30, 2026
@HeDo88TH HeDo88TH added enhancement New feature or request bug Something isn't working labels Jul 30, 2026
HeDo88TH added 2 commits July 30, 2026 09:02
…60729-improve-output-merge

# Conflicts:
#	Obj2Tiles/Options.cs
#	Obj2Tiles/Program.cs
@HeDo88TH

Copy link
Copy Markdown
Collaborator

I think we will soon need a separate documentation website!

@HeDo88TH

HeDo88TH commented Jul 30, 2026 •

Copy link
Copy Markdown
Collaborator

I am ready to merge it @pragmaware but, since it is a pretty large PR, do you have any benchmark for these changes?

@pragmaware

pragmaware commented Aug 5, 2026 •

Copy link
Copy Markdown
Contributor Author

I am ready to merge it @pragmaware but, since it is a pretty large PR, do you have any benchmark for these changes?

Hi, I've developed and tested these changes on various large and complex models I'm working on. Mostly drone photogrammetry, often quite messed up. Different creator software, different settings, different exports, different hands...

You can view some of them at https://monumentidigitali.artcentrica.com . Keep in mind that this is a testing website and not all the models have been generated with the same Obj2Tiles version. I think that MANM and Vulci are the latest.

Unfortuntately I'm not able to share the source models as they aren't mine and I don't have the permission to distribute them.

pragmaware and others added 8 commits August 17, 2026 04:45
…g) into PR OpenDroneMap#100

Conflicts in Options.cs, Program.cs and SplitStage.cs resolved by keeping both
parameter sets (overlap, ignoreNormalMaps, fineTextureQuality and
singleMaterialPerPart, globalBounds).

MeshT: the single-material atlas path from OpenDroneMap#99 called the old one-argument
GetEdgesMapper; it now shares the position canonicalization used by the
repack path, so UV-island detection is consistent across both.
…tile size

The bounding-box driven recursion used by --split-strategy GlobalBounding
ignored --overlap entirely. It now shares SplitWithOverlap and the leaf nudge
with the split-point driven recursions.

The nudge that breaks z-fighting in the overlap band was capped at an absolute
0.0001 model units, which is below depth-buffer precision for tiles viewed at
photogrammetry scales. It is now 1e-4 of the tile's bounding-box diagonal,
still capped at 20% of the overlap so it cannot reopen the seam.
The --single-material-per-part atlas wrote the normal map with the diffuse
extension/encoder (JPEG/WebP), contradicting the lossless normal-map rule used
by every other texture path.
- Toplevel* error modes now cascade from the root by pure halving, as
  documented; the root already carries the texture-quality multiplier.
  With the default --lod-texture-scale 0.5 the extra per-LOD multiplier gave
  LOD tiles twice the root's error.
- Every tile's geometric error is capped at its parent's, so renderers never
  refine straight through a LOD.
- --error 0 keeps its previously documented meaning (auto) instead of
  producing a zero root error; negative/non-finite --error, non-positive
  --error-factor and negative --overlap are rejected.
- --preset legacy no longer overrides an explicit --zsplit/-z or --octree.
- --preset standard no longer forces --local when --lat/--lon are given,
  which silently discarded the georeferencing.
Covers the position-canonicalized island detection (shared UVs without shared
geometry, duplicated exporter vertices, UV seams) and checks that the
incremental PruneFreeList keeps the free list pairwise non-containing and
disjoint from used rectangles after every placement.
- FindTextureSubfolder was duplicated in Utils and Material; it now lives
  once in Obj2Tiles.Library.Common.
- README documents --preset, --decimation-mode, --no-zsplit/--no-octree,
  --overlap, --ignore-normal-maps, --glb/--b3dm, --unlit, the normal-map MTL
  keywords, --error 0 = auto and the parent cap on geometric error.
- Help texts updated for the scaled overlap nudge and preset precedence.
- Removed the TODO file and redundant usings.
@HeDo88TH

Copy link
Copy Markdown
Collaborator

Summary of this PR

  • GLB export (--glb/--b3dm): tiles as external .glb (3D Tiles 1.1 style) instead of b3dm blobs.
  • Auto geometric error (default): ErrorEstimationMode options (bbox diagonal, avg/max edge length, Toplevel* variants) + --error-factor.
  • Presets (--preset legacy|standard), explicit flags always win.
  • Tile overlap (--overlap) with deterministic seam-nudge.
  • Normal maps (bump/map_Bump parity, PNG atlases, size limits), --unlit, --decimation-mode, --ignore-normal-maps, --fine-texture-quality, --lod-texture-scale, texture-folder fallback (texture|textures|tex).
  • Perf: incremental free-list pruning + buffer reuse in texture atlas packing.
  • Fixes: Vertex3.Equals copy-paste bug (Y vs Z), != operators, double.Epsilon (=5e-324) replaced by a real tolerance, UV-repacking precision, ObjMesh.WriteObj independent v/vn/vt dedup with index remap.

Maintainer additions

  • Merged master (Added One Material per Mesh Func & "GlobalBounding" Splitting Strategy #99) with conflict resolution + repair of the single-material atlas path (didn't compile combined).
  • --overlap now works with the default GlobalBounding split strategy (was silently ignored); seam nudge is scale-relative (≤1e-4 of tile diagonal, ≤20% of overlap).
  • Geometric-error hierarchy fixed: per-tile error capped by parent, Toplevel* use clean binary cascade — previously children could get 2× parent error (16 violations → 0).
  • --error 0 = auto again; input validation for error/factor/overlap; preset precedence for --no-zsplit/--no-octree and --lat/--lon.
  • Normal atlases always PNG (no lossy compression).
  • +65 tests (309 total), README documents every new switch.

Impact

Fixes several silent-wrong-output cases (bad GE cascades, --error 0, dead --overlap, lossy normals, Vertex3 equality). Better defaults (auto error, one-flag standard preset), faster texture packing, GLB for 1.1 viewers. Fully backwards compatible: b3dm stays default, --preset legacy restores old behavior. Only semantic change: Toplevel* modes now match documented binary halving.

Verification

Build clean (0 warnings), 309 tests passing, CI green, and an 11-config end-to-end sweep with 0 child>parent geometric-error violations in every tileset.

@HeDo88TH
HeDo88TH merged commit 8f14826 into OpenDroneMap:master Sep 25, 2026
1 check passed
pragmaware pushed a commit to pragmaware/Obj2Tiles that referenced this pull request Oct 12, 2026
Upstream (PR OpenDroneMap#100) clamps each tile's estimated error to its parent's, so a
saturated estimate legitimately equals the parent value. The regression guard
stays: strictly-greater-than-parent and non-finite errors still fail the gate.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants