Skip to content

glTF2 : Fix ( An error occurs when it is 0 )#6544

Merged
kimkulling merged 2 commits intoassimp:masterfrom
copycd:master
Mar 16, 2026
Merged

glTF2 : Fix ( An error occurs when it is 0 )#6544
kimkulling merged 2 commits intoassimp:masterfrom
copycd:master

Conversation

@copycd
Copy link
Copy Markdown
Contributor

@copycd copycd commented Feb 26, 2026

29187.zip

I attached a file that used at test.

Summary by CodeRabbit

  • Bug Fixes
    • Improved glTF2 asset import reliability and efficiency by avoiding unnecessary face allocation and processing in edge cases where meshes have no triangle faces. Import behavior for typical meshes remains unchanged, reducing wasted work and lowering the chance of import-related errors for empty or degenerate geometry.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Feb 26, 2026

📝 Walkthrough

Walkthrough

The glTF2 importer now skips allocation and population of triangle faces when nFaces == 0 in the indexed TRIANGLES branch, guarding face construction to avoid unnecessary work or invalid access.

Changes

Cohort / File(s) Summary
glTF2 Importer Face Construction
code/AssetLib/glTF2/glTF2Importer.cpp
Add nFaces > 0 guard to TRIANGLES indexed branch so face array allocation and filling only occur when faces exist.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Suggested labels

Bug

Suggested reviewers

  • kimkulling

Poem

🐰 A loader hops through code so neat,
Guarding faces with careful feet.
If triangles are none, it skips the race,
Keeping meshes tidy in their place. ✨

🚥 Pre-merge checks | ✅ 1 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title refers to a glTF2 fix when 'it is 0', which aligns with the changeset that guards face allocation with nFaces > 0 condition, but the phrasing is vague and doesn't clearly specify what becomes 0 or what error is fixed. Clarify the title to be more specific, e.g., 'glTF2: Fix face allocation error when nFaces is zero' or 'glTF2: Guard against zero face count in mesh import'.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
📝 Coding Plan
  • Generate coding plan for human review comments

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Tip

CodeRabbit can use Trivy to scan for security misconfigurations and secrets in Infrastructure as Code files.

Add a .trivyignore file to your project to customize which findings Trivy reports.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
code/AssetLib/glTF2/glTF2Importer.cpp (1)

769-775: Clean up the comment and consider consistency with other primitive modes.

The fix correctly prevents an unnecessary allocation and a subsequent DeadlyImportError when the index buffer results in zero faces. However, there are two concerns:

  1. The comment // copycd:: than > 0 appears to be a personal note and is unclear. Please replace it with a descriptive comment explaining the intent.

  2. This guard is only applied to the indexed TRIANGLES case. The same issue exists for:

    • Other indexed primitive modes (POINTS at line 729, LINES at line 742, LINE_LOOP/LINE_STRIP at line 752, TRIANGLE_STRIP at line 780, TRIANGLE_FAN at line 795)
    • The non-indexed TRIANGLES case at line 850
    • Other non-indexed primitive modes

Consider applying consistent guards to these cases as well.

Suggested comment fix
-                    // copycd:: than > 0
+                    // Skip allocation when there are no faces to avoid unnecessary allocation
+                    // and subsequent "Mesh has no faces" error for empty primitives
                     if (nFaces > 0) {
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@code/AssetLib/glTF2/glTF2Importer.cpp` around lines 769 - 775, Replace the
unclear comment "// copycd:: than > 0" with a clear descriptive note (e.g.,
"Only allocate face array when computed face count > 0 to avoid allocating
zero-sized array and subsequent DeadlyImportError") and add the same guard
pattern used here around allocations that use nFaces (i.e., only allocate
faces/new aiFace[nFaces] and iterate when nFaces > 0) for all other indexed
primitive branches (POINTS, LINES, LINE_LOOP, LINE_STRIP, TRIANGLE_STRIP,
TRIANGLE_FAN that use indexBuffer and
SetFaceAndAdvance*/SetFaceAndAdvance2/SetFaceAndAdvance1 calls) and for
non-indexed branches (including the non-indexed TRIANGLES case) so that
facePtr/faces are only created when nFaces > 0 to maintain consistency and
prevent zero-length allocations.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@code/AssetLib/glTF2/glTF2Importer.cpp`:
- Around line 769-775: Replace the unclear comment "// copycd:: than > 0" with a
clear descriptive note (e.g., "Only allocate face array when computed face count
> 0 to avoid allocating zero-sized array and subsequent DeadlyImportError") and
add the same guard pattern used here around allocations that use nFaces (i.e.,
only allocate faces/new aiFace[nFaces] and iterate when nFaces > 0) for all
other indexed primitive branches (POINTS, LINES, LINE_LOOP, LINE_STRIP,
TRIANGLE_STRIP, TRIANGLE_FAN that use indexBuffer and
SetFaceAndAdvance*/SetFaceAndAdvance2/SetFaceAndAdvance1 calls) and for
non-indexed branches (including the non-indexed TRIANGLES case) so that
facePtr/faces are only created when nFaces > 0 to maintain consistency and
prevent zero-length allocations.

ℹ️ Review info

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 10be273 and 23d945c.

📒 Files selected for processing (1)
  • code/AssetLib/glTF2/glTF2Importer.cpp

Copy link
Copy Markdown
Member

@kimkulling kimkulling left a comment

Choose a reason for hiding this comment

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

Looks fine.

@sonarqubecloud
Copy link
Copy Markdown

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@code/AssetLib/glTF2/glTF2Importer.cpp`:
- Around line 769-775: The current indexed TRIANGLES path skips allocating
aiFace array when nFaces == 0 which leaves aim->mNumFaces at 0 and bypasses the
intended no-face validation; restore the previous validity contract by ensuring
faces/facePtr are allocated (or at least aim->mNumFaces is set and the no-face
error path is preserved) even when nFaces == 0. In practice, keep the allocation
guard semantics used previously: allocate faces = new aiFace[nFaces] and set
facePtr, and ensure SetFaceAndAdvance3 is only called within the loop over
count, but if nFaces == 0 explicitly preserve the error/validation behavior for
aim->mNumFaces (matching non-indexed TRIANGLES) so ValidateDataStructure.cpp can
catch the no-face condition. Reference symbols: nFaces, faces, facePtr, aiFace,
count, SetFaceAndAdvance3, and aim->mNumFaces.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: ab3580c7-09e1-48c2-9ab0-256281344c6b

📥 Commits

Reviewing files that changed from the base of the PR and between 23d945c and 59110ce.

📒 Files selected for processing (1)
  • code/AssetLib/glTF2/glTF2Importer.cpp

Comment on lines +769 to 775
// copycd:: than > 0
if (nFaces > 0) {
facePtr = faces = new aiFace[nFaces];
for (unsigned int i = 0; i < count; i += 3) {
SetFaceAndAdvance3(facePtr, aim->mNumVertices, indexBuffer[i], indexBuffer[i + 1], indexBuffer[i + 2]);
}
}
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.

⚠️ Potential issue | 🟠 Major

Preserve no-face validation instead of silently emitting an empty triangle mesh.

At Line 770, skipping allocation when nFaces == 0 bypasses the existing no-face error path, so indexed TRIANGLES can now leave aim->mNumFaces at 0. That conflicts with validation (code/PostProcessing/ValidateDataStructure.cpp, Line 342-Line 344) and with the non-indexed TRIANGLES path behavior.

Proposed fix (keep the allocation guard, keep previous validity contract)
                 case PrimitiveMode_TRIANGLES: {
                     nFaces = count / 3;
                     if (nFaces * 3 != count) {
                         ASSIMP_LOG_WARN("The number of vertices was not compatible with the TRIANGLES mode. Some vertices were dropped.");
                         count = nFaces * 3;
                     }
-                    // copycd:: than > 0
-                    if (nFaces > 0) {
-                        facePtr = faces = new aiFace[nFaces];
-                        for (unsigned int i = 0; i < count; i += 3) {
-                            SetFaceAndAdvance3(facePtr, aim->mNumVertices, indexBuffer[i], indexBuffer[i + 1], indexBuffer[i + 2]);
-                        }
-                    }
+                    if (nFaces == 0) {
+                        throw DeadlyImportError("Mesh \"", aim->mName.C_Str(), "\" has no faces");
+                    }
+                    facePtr = faces = new aiFace[nFaces];
+                    for (unsigned int i = 0; i < count; i += 3) {
+                        SetFaceAndAdvance3(facePtr, aim->mNumVertices, indexBuffer[i], indexBuffer[i + 1], indexBuffer[i + 2]);
+                    }
                     break;
                 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@code/AssetLib/glTF2/glTF2Importer.cpp` around lines 769 - 775, The current
indexed TRIANGLES path skips allocating aiFace array when nFaces == 0 which
leaves aim->mNumFaces at 0 and bypasses the intended no-face validation; restore
the previous validity contract by ensuring faces/facePtr are allocated (or at
least aim->mNumFaces is set and the no-face error path is preserved) even when
nFaces == 0. In practice, keep the allocation guard semantics used previously:
allocate faces = new aiFace[nFaces] and set facePtr, and ensure
SetFaceAndAdvance3 is only called within the loop over count, but if nFaces == 0
explicitly preserve the error/validation behavior for aim->mNumFaces (matching
non-indexed TRIANGLES) so ValidateDataStructure.cpp can catch the no-face
condition. Reference symbols: nFaces, faces, facePtr, aiFace, count,
SetFaceAndAdvance3, and aim->mNumFaces.

@kimkulling kimkulling merged commit fcb1702 into assimp:master Mar 16, 2026
15 checks passed
@kimkulling
Copy link
Copy Markdown
Member

Merged, thank you for your contribution.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: ✅ Done

Development

Successfully merging this pull request may close these issues.

2 participants