Support multiple texture images per mesh (closes #2) - #21
Merged
Conversation
- Change ReorderUnorganizedTexture::setTextureMat → setTextureMats (vector-based) - Normalize each input texture to 8-bit, 3-channel internally via QuantizeImage + ColorConvertImage - Implement chart-aware texture sampling: each face samples from its UV chart's image - Update MeshReadResult: single texture/texturePath → vectors textures/texturePaths - ReadMesh now loads all referenced textures, preserving chart-index alignment - Add resolve_chart_image_() helper to locate chart texture; report_missing_charts_() warns for unused charts - Update ComputeUVDensity to handle multi-chart meshes with varying image dimensions - Remove ColorConvertNode from ReorderTexture app (normalization now internal) - Graph layer: MeshReadNode exposes images vector; ReorderTextureNode input port imageIn → imagesIn - Add unit tests for multi-chart UV-mapped meshes (camera-path tests to avoid vtkOBBTree degenerate-mesh issue) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
A material that declares no map_Kd arrives as an empty relative path. Resolving it against the OBJ's parent directory would be wrong, so keep the chart's texture/path slots empty instead, preserving the chart i ↔ textures[i] alignment invariant. The reorder step already no-ops on empty charts. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Drop the singular imagePath output port, which had no consumers, and make the plural images port the canonical texture output. The scalar image port is kept as a documented stopgap convenience for single-image consumers (e.g. registration) and is now backed by a getter lambda over imgs_ rather than a duplicated img_ member, so it always reflects images[0]. The full plural-pipeline conversion of downstream consumers is deferred to a future PR. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
This PR adds support for meshes textured by multiple images, closing #2. Each UV chart in a multi-chart mesh (e.g., multi-material OBJ) is now independently textured. The reorder pipeline normalizes all inputs to 8-bit/3-channel internally and samples each face from its UV chart's image, skipping uncolored regions and warning for missing textures.
Changes
Core Library (
core/)setTextureMat()→setTextureMats(std::vector<cv::Mat>)to accept multiple textures indexed by UV chart; removedgetTextureMat()resolve_chart_image_()method resolves a face's texture from its UV chart; returns nullptr if chart is out of range or image is emptyreport_missing_charts_()aggregates and warns once for all charts with no usable imageComputeUVDensity()to scale UV regions by their chart's image dimensions, supporting varying sizes in multi-chart meshesMeshReadResultto usestd::vector<cv::Mat> texturesandstd::vector<std::filesystem::path> texturePaths(replacing scalartextureandtexturePath)ReadMesh()now loads every referenced texture into the vectors, preserving alignment sochart i ↔ textures[i]; materials with no map_Kd (empty path) and missing images are stored as emptycv::Mat/path to maintain indexingGraph Layer (
graph/)imagesport exposing the full texture vector (canonical plural output); keepimageport as a documented stopgap scalar convenience for single-image consumers (backed by a getter lambda returningimages[0])—removeimagePathportimageIninput port →imagesIn(type:std::vector<cv::Mat>)setTextureMat→setTextureMatsApplications (
apps/)ColorConvertNode; connectreorder->imagesIndirectly toreader->imagessetTextureMat()→setTextureMats()Tests (
tests/)TwoChartMeshfixture andReorderMultiTexturetest cases (the first compute-level coverage for this class) covering:SamplesEachChartFromItsImage: every colored pixel is exactly one of the two chart colors, and both charts contributeSkipsFacesWhoseChartHasNoImage: a chart with no supplied image is left as background and triggers the aggregated warningDesign Notes
ReadMesh.cv::Mat) remain uncolored in the output. A single aggregated warning names all affected chart indices; duplicates are deduplicated and sorted for clarity.imageoutput port on MeshReadNode is kept as a convenience for legacy single-texture consumers—it returnsimages[0]via a getter lambda. The pluralimagesport is the canonical output and will become the only path once downstream code migrates.Follow-ups
Testing
ctest: 6/6 suites pass, including the newReorderMultiTexture.*casesCloses #2
🤖 Generated with Claude Code