Skip to content

Support box-projected UVs for CSG subtractMeshes#511

Merged
tracygardner merged 26 commits intomainfrom
codex/investigate-material-visibility-issue
Apr 6, 2026
Merged

Support box-projected UVs for CSG subtractMeshes#511
tracygardner merged 26 commits intomainfrom
codex/investigate-material-visibility-issue

Conversation

@tracygardner
Copy link
Copy Markdown
Contributor

@tracygardner tracygardner commented Apr 6, 2026

Motivation

  • Provide an option to generate box-projected UVs for result geometry produced by CSG subtraction so textures can be applied predictably after boolean operations.
  • Allow callers to pass options (including uvProjection and uvScale) into subtractMeshes and its internal merge/individual flows.

Description

  • Added applyBoxProjectionUV(mesh, uvScale) which computes box-projected UVs from vertex positions and normals and sets the UV vertex buffer on the mesh.
  • Extended subtractMeshes signature to accept either an approach string or an options object and forward options into subtractMeshesMerge and subtractMeshesIndividual as applicable.
  • Applied applyBoxProjectionUV to the resultMesh in both merge and individual subtraction code paths when options.uvProjection === "box", using options.uvScale for scaling.
  • Added a unit test in tests/materials.test.js that exercises box-projected UVs for subtractMeshes and asserts UV presence and scaling behavior.

Testing

  • Executed the unit tests for materials including tests/materials.test.js which contains the new should support box-projected UVs for subtractMeshes test; all tests passed.

Codex Task

Summary by CodeRabbit

  • New Features

    • Box-projected UV mapping for mesh subtraction with configurable UV scale; can be forced or auto-applied when existing UVs are missing or unusable.
    • Subtraction APIs now accept options to control UV projection and behavior.
  • Bug Fixes

    • Safer handling when input meshes contain non-finite or incompatible vertex data: subtraction falls back to a safe merge path and logs when CSG is skipped.
  • Tests

    • Added tests validating box-projected UVs, UV scale effects, and auto-application when UVs are absent.

@cloudflare-workers-and-pages
Copy link
Copy Markdown

cloudflare-workers-and-pages bot commented Apr 6, 2026

Deploying flockdev with  Cloudflare Pages  Cloudflare Pages

Latest commit: 941ca1c
Status: ✅  Deploy successful!
Preview URL: https://7bb70675.flockdev.pages.dev
Branch Preview URL: https://codex-investigate-material-v.flockdev.pages.dev

View logs

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 6, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds optional box-projection UV generation to CSG subtraction results, makes normalization warnings conditional, and adds pre-checks to skip CSG merges for meshes with non-finite or mismatched vertex attribute kinds, falling back to Mesh.MergeMeshes. Subtraction APIs now accept an options object forwarded to implementations.

Changes

Cohort / File(s) Summary
CSG API & UV Helpers
api/csg.js
Reworked CSG pipeline: normalizeMeshAttributesForMerge(meshes) now accepts { logWarning }. Added applyBoxProjectionUV, hasUsableUVs, shouldApplyBoxProjection, hasNonFinitePositions, sanitizeMeshVertexDataForCSG, and meshesHaveMatchingAttributeKinds. CSG merge is gated on finite positions and matching attribute kinds; non-conforming inputs skip CSG2 and fallback to Mesh.MergeMeshes. Subtraction APIs updated to accept options and conditionally apply box-projected UVs before applying result properties.
Tests: UV Projection Behavior
tests/materials.test.js
Added test cases exercising flock.subtractMeshes UV handling: explicit uvProjection: "box" with varying uvScale (verifies UV presence and scale effect) and auto-projection when UVs are missing (verifies finite UVs and non-degenerate UV range).

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐇 I nudged their verts and checked each face,

I warned when numbers went out of place,
I wrapped the cuts with tiny boxed UV,
Scaled patterns singing from seam to seam,
Hooray — clean meshes hop into dream.

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

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.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: adding support for box-projected UVs in the CSG subtractMeshes functionality, which aligns with the primary objectives and the bulk of the code changes.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/investigate-material-visibility-issue

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.

Copy link
Copy Markdown

@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)
tests/materials.test.js (1)

757-823: Good test coverage for UV projection feature.

The test properly validates that:

  1. UV data is generated when uvProjection: "box" is specified
  2. The uvScale parameter affects UV magnitude proportionally

One consideration: if CSG operations fail (return null), getMeshByName would return null and getVerticesData would throw. You could add a guard assertion to improve error diagnostics:

const meshA = flock.scene.getMeshByName("uvSubtractA");
const meshB = flock.scene.getMeshByName("uvSubtractB");
expect(meshA, "uvSubtractA mesh should exist after subtraction").to.exist;
expect(meshB, "uvSubtractB mesh should exist after subtraction").to.exist;

This would provide clearer failure messages if CSG operations fail for environment-specific reasons.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/materials.test.js` around lines 757 - 823, The test calls
getVerticesData on meshes returned by flock.scene.getMeshByName("uvSubtractA")
and "uvSubtractB" without guarding for null if CSG failed; add explicit
assertions such as expect(meshA, "uvSubtractA mesh should exist after
subtraction").to.exist and expect(meshB, "uvSubtractB mesh should exist after
subtraction").to.exist before calling meshA.getVerticesData(...) /
meshB.getVerticesData(...) so failures report clear diagnostics (referenced
symbols: flock.scene.getMeshByName, meshA, meshB, getVerticesData,
"uvSubtractA", "uvSubtractB").
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@tests/materials.test.js`:
- Around line 757-823: The test calls getVerticesData on meshes returned by
flock.scene.getMeshByName("uvSubtractA") and "uvSubtractB" without guarding for
null if CSG failed; add explicit assertions such as expect(meshA, "uvSubtractA
mesh should exist after subtraction").to.exist and expect(meshB, "uvSubtractB
mesh should exist after subtraction").to.exist before calling
meshA.getVerticesData(...) / meshB.getVerticesData(...) so failures report clear
diagnostics (referenced symbols: flock.scene.getMeshByName, meshA, meshB,
getVerticesData, "uvSubtractA", "uvSubtractB").

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: bd82ef66-87a5-480a-bf6e-05f789241429

📥 Commits

Reviewing files that changed from the base of the PR and between fa8ec0b and 2e3fabc.

📒 Files selected for processing (2)
  • api/csg.js
  • tests/materials.test.js

Copy link
Copy Markdown

@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.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
api/csg.js (1)

1-1: ⚠️ Potential issue | 🟡 Minor

Address Prettier formatting warning.

The pipeline indicates Prettier found formatting issues. Run prettier --write api/csg.js to fix the style violations before merging.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@api/csg.js` at line 1, Prettier reported style violations in api/csg.js (the
top-level variable declaration "flock"); run the formatter and commit the
result: execute prettier --write api/csg.js (or your project's formatting task)
to reformat the file, verify that the change only affects style (e.g.,
spacing/semicolons around the "let flock;" declaration), then add and commit the
updated file so the pipeline warning is resolved.
🧹 Nitpick comments (1)
api/csg.js (1)

196-197: Negative uvScale values will pass validation and produce negative texturePhysicalSize.

The check uvScale !== 0 allows negative values through, which would result in a negative texturePhysicalSize. Depending on how setSizeBasedBoxUVs handles this, it could produce inverted or unexpected UV mapping.

🔧 Proposed fix to reject non-positive scales
-  const scale = Number.isFinite(uvScale) && uvScale !== 0 ? uvScale : 1;
+  const scale = Number.isFinite(uvScale) && uvScale > 0 ? uvScale : 1;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@api/csg.js` around lines 196 - 197, The current validation for uvScale uses
uvScale !== 0 which allows negative values and yields a negative
texturePhysicalSize; update the logic that computes scale so it only accepts
positive finite uvScale (e.g. Number.isFinite(uvScale) && uvScale > 0) and fall
back to 1 otherwise, ensuring texturePhysicalSize = 4 / scale is always
positive; adjust any downstream assumptions in setSizeBasedBoxUVs or callers to
rely on a guaranteed positive texturePhysicalSize.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@api/csg.js`:
- Line 1: Prettier reported style violations in api/csg.js (the top-level
variable declaration "flock"); run the formatter and commit the result: execute
prettier --write api/csg.js (or your project's formatting task) to reformat the
file, verify that the change only affects style (e.g., spacing/semicolons around
the "let flock;" declaration), then add and commit the updated file so the
pipeline warning is resolved.

---

Nitpick comments:
In `@api/csg.js`:
- Around line 196-197: The current validation for uvScale uses uvScale !== 0
which allows negative values and yields a negative texturePhysicalSize; update
the logic that computes scale so it only accepts positive finite uvScale (e.g.
Number.isFinite(uvScale) && uvScale > 0) and fall back to 1 otherwise, ensuring
texturePhysicalSize = 4 / scale is always positive; adjust any downstream
assumptions in setSizeBasedBoxUVs or callers to rely on a guaranteed positive
texturePhysicalSize.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: ec6f5c6d-245a-4183-a0e2-04f67464a059

📥 Commits

Reviewing files that changed from the base of the PR and between 6e922ae and 16a10ea.

📒 Files selected for processing (1)
  • api/csg.js

Copy link
Copy Markdown

@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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
api/csg.js (1)

1-1: ⚠️ Potential issue | 🟡 Minor

Address Prettier formatting issue to pass CI.

The pipeline reports a Prettier formatting issue. Run npx prettier --write api/csg.js to fix.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@api/csg.js` at line 1, The file declares the top-level variable "flock" and
fails CI due to Prettier formatting; run the formatter (e.g., execute `npx
prettier --write api/csg.js`) or apply the project's Prettier config to reformat
api/csg.js so the declaration for "flock" and the rest of the file conform to
the repository's style rules, then commit the formatted file.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@api/csg.js`:
- Around line 481-485: Update the console.warn message inside the mergeMeshes
logic to include the missing word "to": change the string passed to console.warn
in the mergeMeshes branch from "[mergeMeshes] Skipping CSG merge due non-finite
positions; using Mesh.MergeMeshes fallback." to "[mergeMeshes] Skipping CSG
merge due to non-finite positions; using Mesh.MergeMeshes fallback." so the
warning reads correctly.

---

Outside diff comments:
In `@api/csg.js`:
- Line 1: The file declares the top-level variable "flock" and fails CI due to
Prettier formatting; run the formatter (e.g., execute `npx prettier --write
api/csg.js`) or apply the project's Prettier config to reformat api/csg.js so
the declaration for "flock" and the rest of the file conform to the repository's
style rules, then commit the formatted file.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 70e42788-9b23-476b-b146-3e8d7e4e4371

📥 Commits

Reviewing files that changed from the base of the PR and between 16a10ea and a10493b.

📒 Files selected for processing (1)
  • api/csg.js

api/csg.js Outdated
Comment on lines 481 to 485
} else {
console.warn(
"[mergeMeshes] Skipping CSG merge due non-finite positions; using Mesh.MergeMeshes fallback.",
);
emptyMeshes.forEach((m) => m.dispose());
console.warn("[mergeMeshes] CSG merge attempt failed:", error);
csgSucceeded = false;
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Minor typo in warning message.

Missing "to" in the console warning.

Proposed fix
           } else {
             console.warn(
-              "[mergeMeshes] Skipping CSG merge due non-finite positions; using Mesh.MergeMeshes fallback.",
+              "[mergeMeshes] Skipping CSG merge due to non-finite positions; using Mesh.MergeMeshes fallback.",
             );
           }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
} else {
console.warn(
"[mergeMeshes] Skipping CSG merge due non-finite positions; using Mesh.MergeMeshes fallback.",
);
emptyMeshes.forEach((m) => m.dispose());
console.warn("[mergeMeshes] CSG merge attempt failed:", error);
csgSucceeded = false;
}
} else {
console.warn(
"[mergeMeshes] Skipping CSG merge due to non-finite positions; using Mesh.MergeMeshes fallback.",
);
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@api/csg.js` around lines 481 - 485, Update the console.warn message inside
the mergeMeshes logic to include the missing word "to": change the string passed
to console.warn in the mergeMeshes branch from "[mergeMeshes] Skipping CSG merge
due non-finite positions; using Mesh.MergeMeshes fallback." to "[mergeMeshes]
Skipping CSG merge due to non-finite positions; using Mesh.MergeMeshes
fallback." so the warning reads correctly.

@tracygardner tracygardner merged commit fca07dc into main Apr 6, 2026
9 checks passed
@tracygardner tracygardner deleted the codex/investigate-material-visibility-issue branch April 6, 2026 19:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant