Skip to content

Mac os build#1

Merged
fernandotonon merged 3 commits into
masterfrom
macOS-build
Jan 10, 2023
Merged

Mac os build#1
fernandotonon merged 3 commits into
masterfrom
macOS-build

Conversation

@fernandotonon
Copy link
Copy Markdown
Owner

No description provided.

Fernando Tonon added 3 commits January 10, 2023 16:38
* master:
  Update README.md
  Update README.md
  cleaned use of Ogre Deprecated code
  Update README.md
  minor fixes
  Added script validation to avoid crashing
  Change Editor Palette
  Removed deprecated calls and minor improvements
  Update README.md
  Update README.md
  Update README.md
  Update README.md
  Update README.md
  Added Polygon Mode and Scroll Anim to Material Editor

# Conflicts:
#	src/CMakeLists.txt
#	src/PrimitiveObject.cpp
@fernandotonon fernandotonon merged commit 3614c10 into master Jan 10, 2023
@fernandotonon fernandotonon deleted the macOS-build branch January 10, 2023 21:41
fernandotonon added a commit that referenced this pull request Apr 28, 2026
Three issues from the PR review:

1. Codex P1: buildClosedEdgeLoop only checked graph degree, so any
   closed cycle of selected edges (e.g. the perimeter of an existing
   face) passed through. Filling such a cycle stacked overlapping
   triangles on the live geometry. Added a per-edge boundary check
   (each selected edge must touch exactly one face) before the loop
   walk, refusing interior-edge cycles upfront.

2. CodeRabbit Major: HalfEdgeMesh::fillSelection's duplicate-triangle
   check was gated on n == 3, leaving n > 3 fans free to recreate
   existing tris on their first sub-triangle. Replaced the gate with a
   per-fan-triangle check: every (apex, v_i, v_{i+1}) tri is checked
   against existing faces incident to the apex. Added a regression
   test (FillSelectionRejectsLargerFanThatDuplicatesExistingTri).

3. Codex P2 / CodeRabbit Major: the F shortcut accepted the event
   whenever the selection looked fillable, even when fillSelection()
   returned 0 (e.g. interior edge loop after fix #1, or duplicate-
   triangle rejection after fix #2). Now only swallows the keypress on
   a non-zero return — so F still falls back to Frame-Selection when
   the fill is rejected.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
fernandotonon added a commit that referenced this pull request Apr 28, 2026
* feat(edit): subdivide + fill (Phase 4 topology ops)

Implements the remaining Subdivide and Fill items from issue #259.

HalfEdgeMesh:
  - subdivideFaces: 1-to-4 split with shared midpoints between selected
    faces and T-junction-aware retriangulation of adjacent triangles
    (1/2/3 split-edge cases all handled).
  - fillSelection: 3-N vertex fan-triangulation for vertex fills and
    closed boundary edge loops; refuses cross-submesh, duplicate-tri,
    and orphaned-only inputs.

EditModeController:
  - subdivideSelection wires Face mode (selected tris) and Edge mode
    (incident tris of selected edges) to the HE primitive, captures
    midpoint positions to re-select after the round-trip pack, and
    pushes one EditMeshTopologyCommand for undo.
  - fillSelection wires Vertex mode (set order = fan order) and Edge
    mode (closed-loop detection via degree-2 walk).

UI:
  - Two new toolbar buttons (Subdivide ⊞, Fill ◆) with mode-aware
    enable/visibility.
  - F shortcut fills in edit mode when the selection is fillable;
    otherwise falls through to the existing Frame-Selection behavior.

Tests:
  - 15 new HalfEdgeMesh standalone tests covering both ops, including
    T-junction handling, UV interpolation, cross-submesh rejection,
    and round-trip safety.
  - 7 new controller tests guarded by tryInitOgre (skip on macOS,
    run on Linux CI).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(rtss): register only one RTShaderLib path to avoid duplicate parse

addRTSSResources() registered up to 4 candidate directories, deduplicated
only by canonical path. On macOS dev builds the bundle's interior media/
and the dev-copy at bin/media/ are distinct paths with identical contents,
so both got registered. Ogre re-parses .program scripts per resource
location, and the second pass over ShadowVolumeExtude.program raised
ItemIdentityException on the duplicate Ogre/ShadowBlendVP GpuProgram,
aborting startup.

Pick the FIRST existing RTShaderLib + sibling Main pair and stop. Both
copies hold the same files, so the order doesn't matter functionally —
this just avoids the double-registration.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* test(edit): expand subdivide/fill coverage + document Phase 4

HalfEdgeMesh tests (+8):
  - subdivide every cube face stays closed-manifold
  - subdivide preserves blended bone weights at midpoints
  - splitMask=2 path verified on the quad neighbor
  - cross-submesh subdivide leaves submesh 1 untouched
  - non-adjacent multi-face selection on a cube
  - fill caps a deleted cube face back to closed
  - fill accepts orphaned vertices (post-delete hole-cap flow)
  - fill round-trip safe through toEditableMesh/buildFromEditableMesh

Controller tests (+3):
  - subdivideSelection in edge mode promotes incident faces
  - fillSelection in vertex mode produces a new triangle
  - fillSelection pushes an undo command

Docs:
  - CLAUDE.md keyboard shortcut line notes F's dual role and X/Ctrl+X
    in Edit Mode
  - New "Edit Mode (Phase 4 topology)" section summarising the
    EditModeController + HalfEdgeMesh op set, with a targeted note on
    Subdivide and Fill

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(edit): address Codex P1/P2 + CodeRabbit Major review

Three issues from the PR review:

1. Codex P1: buildClosedEdgeLoop only checked graph degree, so any
   closed cycle of selected edges (e.g. the perimeter of an existing
   face) passed through. Filling such a cycle stacked overlapping
   triangles on the live geometry. Added a per-edge boundary check
   (each selected edge must touch exactly one face) before the loop
   walk, refusing interior-edge cycles upfront.

2. CodeRabbit Major: HalfEdgeMesh::fillSelection's duplicate-triangle
   check was gated on n == 3, leaving n > 3 fans free to recreate
   existing tris on their first sub-triangle. Replaced the gate with a
   per-fan-triangle check: every (apex, v_i, v_{i+1}) tri is checked
   against existing faces incident to the apex. Added a regression
   test (FillSelectionRejectsLargerFanThatDuplicatesExistingTri).

3. Codex P2 / CodeRabbit Major: the F shortcut accepted the event
   whenever the selection looked fillable, even when fillSelection()
   returned 0 (e.g. interior edge loop after fix #1, or duplicate-
   triangle rejection after fix #2). Now only swallows the keypress on
   a non-zero return — so F still falls back to Frame-Selection when
   the fill is rejected.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
fernandotonon added a commit that referenced this pull request May 17, 2026
Addresses Codex P1 findings on PR #578:

## P1 #1 — diff against captured bind positions, not the live buffer

`addMorphTargetFromCurrentEdit` was diffing `EditableMesh` against
positions read from the entity's current GPU vertex buffer. But
edit-mode ops (translate / rotate / scale) call `commitToEntity`
during the gesture — both sides of the subtraction end up identical
in the common flow, so `slice.offsets` stays empty and the command
incorrectly returns no-op even after visible edits.

Fix: snapshot the bind positions once at `EditableMesh::loadFromOgreMesh`
time (`EditableSubMesh::originalPositions`). The snapshot is never
mutated by edit-mode ops, so `vertices[i].position -
originalPositions[i]` recovers the right delta regardless of how
many commits have run since enter-edit-mode.

## P1 #2 — shared-vertex submeshes

The old `readBindPositions` rejected any submesh with
`useSharedVertices=true` (vertexData null in that case). Most
Mixamo-style assets use shared vertices, so morph authoring silently
skipped them.

Fix is implicit in #1: `loadFromOgreMesh` already copies the shared
vertex pool into each affected submesh's `vertices` array; the new
`originalPositions` snapshot is built from that same source, so
shared-vertex submeshes carry their own baseline. The GPU-buffer
read path goes away entirely.

## CodeRabbit minor — null-assert SelectionSet in tests

Added `ASSERT_NE(sel, nullptr)` before `sel->append(entity)` in the
three new authoring tests, matching the slice-A1 pattern. If the
singleton ever fails to initialize, we get a clear assertion failure
instead of a null-deref crash.

## Tests

- `LoadFromEntityTriangleMesh` extended to assert (a) the snapshot
  matches `vertices[].position` after load and (b) mutating
  `vertices[].position` does NOT touch `originalPositions`. Exercises
  the shared-vertex case (the triangle fixture uses shared verts).
- New `AddMorphTargetUndoableViaUndoManager` exercises the full
  add → undo → redo loop through the shared `UndoManager`, with a
  hand-built slice that mirrors what `addMorphTargetFromCurrentEdit`
  will produce once edit-mode capture is wired up end-to-end.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
fernandotonon added a commit that referenced this pull request May 17, 2026
…#578)

* feat(morph): sub-slice A3 — authoring (add from edit, rename, delete)

Last remaining sub-slice of #518. Closes the morph epic's authoring loop:
users can save the current edit-mode geometry as a new morph target,
rename existing targets, and delete unwanted ones. All three operations
are undoable.

## What ships

### `commands/MorphCommands.{h,cpp}` — three QUndoCommand subclasses
- `AddMorphTargetCommand` — create N same-named Ogre::Pose entries (one
  per submesh) plus a matching VAT_POSE Animation. Slices come in as
  sparse `{submeshHandle, {vertexIndex: Vector3f}}` maps so the command
  doesn't depend on EditableMesh — anything that produces deltas can
  drive it (current edit, MCP, future "fix mirror axis" rules…).
- `DeleteMorphTargetCommand` — snapshot the same-named pose offsets at
  construction, drop the pose(s) + Animation + AnimationState on redo,
  rebuild from the snapshot on undo.
- `RenameMorphTargetCommand` — same snapshot-and-rebuild pattern, just
  with a different name on the rebuild side. Ogre 14.5 doesn't expose
  Pose::setName, so destroy-and-recreate is the only path.

### `MorphAnimationManager` — three new Q_INVOKABLE methods
- `addMorphTargetFromCurrentEdit(name)` — reads `EditModeController`'s
  live EditableMesh, diffs every submesh against the mesh's bind
  positions on the GPU buffer, builds the slice list, pushes an
  AddMorphTargetCommand. Falls back to no-op if not in edit mode, no
  vertices moved, or name collides.
- `renameMorphTarget(old, new)` — name-trim, collision check, push.
- `deleteMorphTarget(name)` — existence check, push.

All three resolve the entity from SelectionSet's first entity (same
pattern as the A1/A2 setters), push onto the shared `UndoManager`
stack so Ctrl+Z reverses, and emit `morphTargetsChanged` so the
Inspector re-fetches.

## Tests

8 new GTest cases on `MorphAnimationManager_test.cpp`:
- Add command creates + undoes pose and Animation cleanly.
- Delete command round-trips (poses restored on undo).
- Rename command round-trips (old name restored on undo).
- Rename rejects target-name collisions, no-op self-renames, blank names.
- Delete rejects unknown / empty names; succeeds on a real target.
- Add-from-edit rejects empty / whitespace names before edit-mode check.
- Add-from-edit returns false when no EditableMesh is available
  (i.e. user isn't in edit mode).
- All three methods reject when nothing is selected.

The command path is what's actually under test — the manager wrappers
are thin selection + name-validation glue. We keep direct command
tests because that's where the undo / redo contract lives and it
exercises the pose snapshot / rebuild path without needing an Inspector.

## What's deferred

- **Inspector UI** (Add / Rename / Delete buttons in the Morph Targets
  subgroup) — small but lives in QML, and the last QML change in this
  epic (A5's dope-sheet integration) deterministically crashed
  unrelated tests for reasons I never fully isolated. Doing the UI in
  a separate PR keeps blast radius contained.
- **MCP tools** `add_morph_target` / `rename_morph_target` /
  `delete_morph_target` — straightforward but adds surface; can land
  alongside the Inspector UI.
- **CLI** `qtmesh morph --rename / --delete` — needs export-after-edit
  plumbing through the FBX/glTF morph exporters from A4a/A4b.

#518 status after this slice:

| Sub-slice | Status |
|-|-|
| A1 — Importer + manager + CLI list | shipped (#569) |
| A2 — Inspector subgroup | shipped (#570) |
| A3 — Authoring | **this PR** |
| A4a — glTF export | shipped (#573) |
| A4b — FBX export | shipped (#575) |
| A5 — Controller API | shipped (#576) |
| A5b — Dope-sheet UI | follow-up |
| A6 — MCP tools | shipped (#571) |
| A3b — Inspector / MCP / CLI authoring surface | follow-up |

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(build): add MorphCommands.cpp to tests/ source list

Linker errors on the secondary test binaries (MaterialEditorQML_test,
MaterialEditorQML_qml_test, MaterialEditorQML_perf_test) because they
compile MorphAnimationManager.cpp (which now references the three
MorphCommand constructors) but didn't pick up MorphCommands.cpp.
src/CMakeLists.txt has it; tests/CMakeLists.txt was missing the line.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* review(morph): A3 — capture bind positions on EditableMesh load

Addresses Codex P1 findings on PR #578:

## P1 #1 — diff against captured bind positions, not the live buffer

`addMorphTargetFromCurrentEdit` was diffing `EditableMesh` against
positions read from the entity's current GPU vertex buffer. But
edit-mode ops (translate / rotate / scale) call `commitToEntity`
during the gesture — both sides of the subtraction end up identical
in the common flow, so `slice.offsets` stays empty and the command
incorrectly returns no-op even after visible edits.

Fix: snapshot the bind positions once at `EditableMesh::loadFromOgreMesh`
time (`EditableSubMesh::originalPositions`). The snapshot is never
mutated by edit-mode ops, so `vertices[i].position -
originalPositions[i]` recovers the right delta regardless of how
many commits have run since enter-edit-mode.

## P1 #2 — shared-vertex submeshes

The old `readBindPositions` rejected any submesh with
`useSharedVertices=true` (vertexData null in that case). Most
Mixamo-style assets use shared vertices, so morph authoring silently
skipped them.

Fix is implicit in #1: `loadFromOgreMesh` already copies the shared
vertex pool into each affected submesh's `vertices` array; the new
`originalPositions` snapshot is built from that same source, so
shared-vertex submeshes carry their own baseline. The GPU-buffer
read path goes away entirely.

## CodeRabbit minor — null-assert SelectionSet in tests

Added `ASSERT_NE(sel, nullptr)` before `sel->append(entity)` in the
three new authoring tests, matching the slice-A1 pattern. If the
singleton ever fails to initialize, we get a clear assertion failure
instead of a null-deref crash.

## Tests

- `LoadFromEntityTriangleMesh` extended to assert (a) the snapshot
  matches `vertices[].position` after load and (b) mutating
  `vertices[].position` does NOT touch `originalPositions`. Exercises
  the shared-vertex case (the triangle fixture uses shared verts).
- New `AddMorphTargetUndoableViaUndoManager` exercises the full
  add → undo → redo loop through the shared `UndoManager`, with a
  hand-built slice that mirrors what `addMorphTargetFromCurrentEdit`
  will produce once edit-mode capture is wired up end-to-end.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant