agentleFS
ForgeAXForgeAX/forgeax-engine/skills/forgeax-engine-modeling/SKILL.md

forgeax-engine-modeling

Skill70 starsChanged 18 days agoApache-2.0View on GitHub

ForgeaX editable mesh modeling in .pack.ts builds: selectors, labeled operations, curves, surfaces, rigs, UVs, bakes, MeshAsset export and forgeax model tools. Use when creating, changing or checking a game mesh in code.

The file

We split this skill into the rules it gives an agent

2 rules. About 0 are common, 0 are distinctive, and 2 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈0

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 2

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Very specific:

    Look at it: forgeax model render --source <file>.pack.ts --json, then read the PNGs it lists.

    line 63
  2. Very specific:

    Motion: Do not animate by rotating mesh faces.

    line 122

≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

forgeax-engine-modeling

@forgeax/engine/modeling is a deterministic, editable n-gon mesh kernel in pure TypeScript. A .pack.ts build calls it as ordinary functions and returns { 'mesh/<key>': MeshAsset } (plus a scene and clip for rigs) to the existing Pack, Catalog and Renderer owners.

It is not an editor (no viewport to click in; you see your work only through forgeax model render), not a CAD B-rep kernel (curves and surfaces tessellate into the mesh), and not a runtime compiler (players load the exported mesh).

Contract SSOT: packages/modeling/README.md: data model, selection, session contract and a reference map. Each consideration below links one reference/*.md file; open it when the task needs it. Examples, smallest first, with what each teaches: examples/README.md.

Professional know-how (what to look at, trade-offs, thresholds, recovery from failure codes) is in knowledge/; open the topic that matches the task:

TaskTopic
Choosing an approach, blocking out from drawingsdesign-methodology, design-drawings
Vehicles, hard-surface bodies, panel gapsvehicle-design
Smooth surfaces, patch networks, curvature qualitysurface-quality, nsided-patches
Characters, stylized bodies, faces, hairstylized-character
Mechanisms, joints, mobilitymechanism-design
Detail catalog, animation presentationdetail-catalog, animation-presentation
UV cuts, low poly, bakesuv-cuts-lowpoly, baking-uv
Watertight meshes, toleranceswatertight-tolerance

The smallest build

import { definePack, definePackageId } from '@forgeax/engine/pack/source';
import { model, sel } from '@forgeax/engine/modeling';

export default definePack({
  schemaVersion: '2.0.0',
  packageId: definePackageId('01900000-0000-7000-8000-00000000a0de'),
  parameters: [{ name: 'depth', type: 'f32', default: 0.03, minimum: 0.005, maximum: 0.1 }],
  build: ({ values: p }) => {
    const m = model();
    m.box({ size: [0.42, 0.3, 0.36], tag: 'shell' });
    m.inset(sel.tag('shell').and(sel.facing('+z', 10)).largest().one(), {
      thickness: 0.02, region: 'merged', label: 'visor',
    });
    m.extrude(sel.createdBy('visor', 'inner'), { distance: -p.depth, region: 'merged', label: 'visor-depth' });
    m.markSharp(sel.edges.dihedral('>', 40));
    m.uv.project({ mode: 'box', scale: 0.5 });
    m.assign(sel.createdBy('visor-depth', 'top'), 'glow');
    return m.finish({ key: 'helmet', normals: { mode: 'weighted' } });
  },
});

Look at it: forgeax model render --source <file>.pack.ts --json, then read the PNGs it lists. forgeax help model <command> gives exact flags (tools).

Invariants

  • Y-up, +Z is front, meters, angles in degrees. facing('+y') is the top.
  • Selectors are expressions re-evaluated at every call; never keep face or vertex ids. An empty selection fails (model-selection-empty); it never means "all" (sel.all()).
  • Identity is yours to name: a tag survives derivation; an operation's label writes roles read back with sel.createdBy(label, role). Unlabeled operations add no role.
  • Magnitudes have no defaults (distance, thickness, sizes, segment counts).
  • The first failure poisons the session; finish() returns that ModelingError with code, hint and detail.site = { op, opIndex, label }. Fix that call. m.try(() => ...) rolls back a block whose failure should pick another construction.
  • Topology edits leave new faces without UVs: project or unwrap after the last edit; finish() requires complete uv0.
  • Output depends only on source and parameters: no Date, Math.random or fetch; derive variation from a seed.
  • Budgets: a Pack build has 15 s, each forgeax model rebuild 60 s, and a runtime rebuild should stay near 100 ms. Heavy work moves into a cooked MeshJob (tools § Budgets).

Considerations

Each modeling task raises some of these. They have no fixed order, and most tasks skip some.

Purpose and viewing. Who sees the asset, from how far, and whether it moves decide the face budget, the detail level and whether it needs a rig or bakes. A prop seen at game distance needs a clear silhouette and material breaks, not support loops (export § Performance tiers); node packages/modeling/bench/scale-f1.mjs --fixture f1 --out <file> measures kernel scale on a large fixture).

Form source. Pack parameters hold the sizes worth tuning. Reference images become design drawings; m.threeView intersects 2-3 orthographic outlines into a blockout and extrudeContour turns one outline into a prism (drawings, example body-blockout).

Shape strategy. Match the construction to the form, and mix them freely:

FormStart fromReference
Boxy, machined, panelledprimitives, inset, extrude, shell, mirroroperations
Cut-outs, holes, unionsbooleans on closed operandsbooleans
Tubes, frames, cables, springs, branchessweep, loft, pipeNetwork, arraysweep-deform
Organic bodies, heads, creaturesa low cage, then subdivide, creases, arap, deformers; low poly: loft sections, flat normalssweep-deform
Clothing, layers, hair cardsshrinkwrap, layer, strands, knifeartist-editing
Smooth class-A panels, car bodiesNURBS curves and surfaces, patch networkssurfaces
Blobby merges, low-poly facets, retopologyvoxel, simplify, remesh; lowpoly({ slivers }) removes narrow facesvoxels-remesh
Grilles, vents, thin perforations too fine to modelthinHole / thinHoleCheck (a bake recipe, not geometry)uv-bake (example thin-vent)
An existing meshliftoperations

Symmetric forms: model one half and mirror. Build parts in separate functions and append them; a function that builds into a session is the reuse unit (export § Reuse).

Detail. Edge treatment (bevel, fillets, blends, support loops), panel and shut lines, and the mechanical recipes (bolts, hinges, gears, pin joints) are in detail. markSharp sets hard normals as author intent; there is no weld-angle threshold.

Motion. Do not animate by rotating mesh faces. Bind parts to a rig, give joints limits and key a path; its finish exports part meshes, a scene and a clip. Interference, clearance and mobility checks belong to the same owner (rig, examples limb-choreography, door-hinge, transforming-limb).

Appearance. Assign material slots with assign(faces, slot). Procedural Standard materials, textures and text are in materials. UV projection, unwrapping, automatic charts (uv.unwrap / uv.auto accept opt-in refine: 'slim'), trim sheets, and baking a detailed mesh onto a low one are in uv-bake (example armor-bake); cage-clip and stray-detail bake issues now carry clustered findings with a fix hint. For categorical surface masks, set BakeSlot.materialId explicitly and bake materialId; appearance colors and the repeating default palette do not establish material identity.

Seeing and verifying. Render often and look; numbers alone do not reveal a wrong shape. forgeax model render draws real Engine frames (orthographic sheets, wireframe, overlays, sections, x-ray, zebra and curvature). replay shows every step, select tries a selector, history maps faces to source lines, validate finds topology and self-intersection problems (validate({ shells }) reports shell-overlap when a union-once solid still carries overlapping shells), diff compares variants, and pose / interference check rigs (tools, validation). m.checkpoint('name') marks states the tools can render or select.

Delivery. finish({ key, normals }) exports the mesh; normal modes, LODs and cooked jobs are in export; skinned LODs reduce joints with reduceSkinForLod (rig). A rig scene needs the Pack to declare its sceneComponents (rig). model render --materials auto binds the Pack's material/<slot> outputs to slots of the same name (materialBinding reports each slot); model render also returns renderer { backend, adapter, software }; software is true on Lavapipe or SwiftShader, so label pixel-only findings from such a render; bakes and the full scene show in forgeax project preview inside a game project (see forgeax-engine-cli). An offline recipe producing meshes, materials and processed textures can use AssetsJob and assetsJobSources; register it with createMeshJobCooker and forward its cache to bakeMaps. Keep the recipe in the Pack's static import closure; one job serves its declared outputs through the existing Pack producer, without a project-owned cache or baked defaults.

Failure modes

SymptomUsual cause
model-selection-empty on +zZ-up habit; the hint names the axis that would match
Faces picked by index break after an editSelect by tag or label/role instead
finish fails on uv0A topology edit after the UV call; project or unwrap last
model-degenerate on inset, shell or bevelThe magnitude exceeds what the face or wall allows; read expected
model-work-budgetToo many faces, or heavy work inside the build; reduce it or cook a MeshJob
Validate passes but the shape looks wrongValidation checks topology, not the brief; render and compare
Faces stay on an earlier rig partA misspelled label in a binding selected nothing; compare rig.parts()
Faceting or seams on curved formsMissing sharp/smooth intent or too few segments; render --overlays '["sharp"]'
forgeax: command not found in an Engine checkoutRun node packages/engine/dist/bin/forgeax.mjs from the Engine root
model-render-backend-unavailableNo Vulkan device; tools § render names the software driver
Render colors differ from the Pack's materialsmodel render defaults to --materials palette; pass --materials auto, name outputs material/<slot>, and a rig needs finish({ materials }) (rig)
pack-parameter-invalid on loadparameters must be a non-empty array; declare at least one tunable size
model-capability-unavailableOutside this version (ABF/ARAP unwrap, native compute, MCP); build what exists

The closed failure union and its detail shapes: README § Session contract and errors.

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.