Conversation
WalkthroughThe Draco.cs file is refactored to introduce new internal GLTF/GLB patching infrastructure. A new Changes
Sequence Diagram(s)sequenceDiagram
participant Draco as Draco.Compress
participant Patcher as GltfExtrasPatcher
participant JSON as JSON Handler
participant GLB as GLB Reader/Writer
participant FileOps as File Operations
Draco->>Draco: Encode with Draco compression
Draco->>Patcher: PatchExtras(encoded_file_path)
alt File is GLB
Patcher->>GLB: Read GLB structure (JSON + BIN chunks)
GLB-->>Patcher: JSON chunk data
Patcher->>JSON: Patch JSON (merge extensions, extras)
JSON-->>Patcher: Updated JSON
Patcher->>Patcher: Inline external images into BIN
Patcher->>GLB: Write updated GLB with new chunks
else File is GLTF
Patcher->>JSON: Parse GLTF JSON
JSON-->>Patcher: JSON data
Patcher->>JSON: Copy node extras & extensions
JSON-->>Patcher: Patched JSON
Patcher->>Patcher: Inline external images, update refs
Patcher->>FileOps: Write updated GLTF & BIN
end
Draco->>FileOps: Rename/move final BIN file
Draco->>FileOps: Clean up intermediate files
Draco->>FileOps: File_MoveOverwrite to destination
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 inconclusive)
✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
Tip 📝 Customizable high-level summaries are now available in beta!You can now customize how CodeRabbit generates the high-level summary in your pull requests — including its content, structure, tone, and formatting.
Example:
Note: This feature is currently in beta for Pro-tier users, and pricing will be announced later. Comment |
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (4)
Common_glTF_Exporter/Export/Draco.cs (4)
15-24: GLB read/write logic looks correct but could be more defensiveThe
GlbDataDTO and theReadGlb/WriteGlbimplementations look structurally correct and match the GLB v2 layout (header + JSON chunk + optional BIN chunk). Padding with spaces for JSON and zeros for BIN is also appropriate.One thing you may want to tighten up (non‑blocking):
- Validate the GLB header when reading:
- Check
magic == 0x46546C67andversion == 2before proceeding.- Optionally ensure
lengthis consistent withfs.Lengthand thatchunkLen0,chunkLen1don’t exceed file length.- Optionally verify
chunkType0 == 'JSON'andchunkType1 == 'BIN\0'before trusting the payload.This would fail fast on corrupted or mis‑labeled files instead of parsing arbitrary data as JSON.
Also applies to: 296-322, 324-359
26-52: Extras and extensions merge behavior is sensible; consider future extension interactionsThe
GltfExtrasPatcherflow (PatchExtras→PatchExtrasGltf/PatchExtrasGlb→PatchNodeLike) plusMergeExtensionsUsedAndRequiredandEnsureExtInArrayis coherent:
- Node
extrasfrom the original are cleanly copied onto the Draco‑encoded file.- Node
extensionsare merged so thatKHR_draco_mesh_compressionfrom the Draco output wins, and other extensions from the original are preserved.- Root‐level
extensionsUsed/extensionsRequiredare unioned, and Draco is ensured inextensionsUsed.Two small considerations (optional):
Other “known” structural extensions
Right nowCopyUnknownExtensionsonly treats"KHR_draco_mesh_compression"as “known”. If you later introduce other structural extensions that Draco also rewrites (e.g., mesh/material related), you may need to add them to the keepKnown set to avoid overwriting encoder‑generated data with the original JSON.Non‑node extras
The patcher only restoresextrasat the node level. If you ever start emittingextrason meshes/materials/scene, they won’t be restored by this pipeline. Not an issue today, but worth documenting.As it stands, this matches the current Revit usage (node extras) and looks good.
Also applies to: 68-88, 89-177
179-295: Image inlining logic is solid; watch for alignment and file deletion side effectsThe
InlineExternalImagesIntoBin_JObject/AppendByteshelpers are generally well thought‑out:
- Ensure
buffers[0]andbufferViewsexist.- Load an existing bin (GLTF) or reuse the GLB BIN chunk.
- Append image bytes, create
bufferViews, and wireimages[i].bufferView+mimeType.- Pad the combined BIN to 4 bytes, while keeping
bufferView.byteLengthequal to the raw image size (excluding padding), which is correct.- Update
buffers[0].byteLengthand optionally delete consumed image files.A couple of subtle behaviors to be aware of:
Alignment assumptions
AppendBytesassumes the incomingbinBytes.Lengthis already 4‑byte aligned (so that the newbyteOffsetis also aligned). This is true for well‑formed GLTF/GLB binaries, but if you ever feed a non‑aligned BIN in here,byteOffsetcould end up misaligned. If you want to guard against that, you could:
- Either pad
binBytesto 4 before the first append, or- Assert that
binBytes.Length % 4 == 0when non‑null.Deleting external image files
removeExternalImageFiles == truewill delete any successfully inlined images atPath.Combine(baseDir, uri). That’s perfectly fine for the “export & embed everything” scenario, but it means:
- The same texture referenced by multiple GLTF/GLB files in the same folder will be removed after the first compression.
- Re‑running compression on the same output directory may find some images missing.
If that behavior is intentional, consider a brief comment, or wiring this flag to a user preference later.
382-388: Compress pipeline changes mostly look good; tighten a few edge casesThe updated
Compresspipeline is cleaner and the integration ofGltfExtrasPatcher.PatchExtrasis nice — it preserves node extras while letting Draco rewrite the geometry. The temp/final naming scheme (*.gltfvs*Temp.gltf, same for*.glb) is consistent.Some details worth calling out:
Order of operations is correct
- Draco encodes into
fileToCompressTemp.- Patcher reads both original and temp, merges extras/extensions, inlines images, and writes back to temp.
- You only delete files after patching completes, so originals are preserved on failure.
- For GLTF, you then move the temp BIN to the final BIN, and patch the GLTF JSON to reference the final BIN name.
This is all sound.
String.Replace‑based renames
binTemp = fileToCompressTemp.Replace(".gltf", ".bin");andbinFinal = fileToCompressTemp.Replace("Temp.gltf", ".bin");will behave correctly for normal paths like.../SceneTemp.gltf.- As a minor robustness improvement, using
Path.ChangeExtensionfor the extension change and a small helper for stripping"Temp"would be less brittle and more self‑documenting.JSON replacement scope
In the GLTF case you replacebinTempNamewithbinFinalNameacross the whole JSON text. That can also touch any string inextrasor custom data that happens to contain the temp bin name. That’s unlikely in practice, but if you want to be strict you could:
- Parse the JSON and update only
buffers[0].uri(and/or other known locations) instead of raw string replacement.File_MoveOverwrite behavior
File_MoveOverwritedeletes the destination if it exists, then moves the source. If deletion fails,File.Movewill throw, which is probably what you want, but note:
- Any IO exceptions from
File.Moveare not caught, so the entire export will fail in that case.- If you ever need more robust behavior,
File.Replacemight be an option to consider on Windows.Overall, the flow is correct; the above points are mostly about making the behavior a bit more explicit and resilient.
Also applies to: 392-395, 424-431, 433-463, 467-474
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
Common_glTF_Exporter/Export/Draco.cs(3 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
Common_glTF_Exporter/Export/Draco.cs (1)
Common_glTF_Exporter/Export/RevitGrids.cs (1)
Export(21-65)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: build
Summary by CodeRabbit