@developerz.ai/ts23d 0.0.0-stage → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/agents/bug-hunter.md +21 -0
- package/.claude/agents/docs-author.md +13 -0
- package/.claude/agents/dx-auditor.md +14 -0
- package/.claude/agents/primitive-author.md +22 -0
- package/.claude/agents/recipe-author.md +36 -0
- package/.claude/agents/visual-reviewer.md +23 -0
- package/.claude/commands/feature.md +28 -0
- package/.claude/commands/new-recipe.md +19 -0
- package/.claude/commands/release.md +14 -0
- package/.claude/commands/verify.md +9 -0
- package/.claude/skills/author-recipe/SKILL.md +93 -0
- package/CHANGELOG.md +90 -0
- package/CLAUDE.md +85 -0
- package/LICENSE +21 -0
- package/README.md +385 -2
- package/dist/chunk-6b05mnmx.js +19 -0
- package/dist/chunk-6b05mnmx.js.map +11 -0
- package/dist/chunk-7rtfjh9f.js +45 -0
- package/dist/chunk-7rtfjh9f.js.map +10 -0
- package/dist/chunk-8j4c28jt.js +4085 -0
- package/dist/chunk-8j4c28jt.js.map +46 -0
- package/dist/chunk-d1fv6hrm.js +2532 -0
- package/dist/chunk-d1fv6hrm.js.map +43 -0
- package/dist/chunk-dbq4qf52.js +902 -0
- package/dist/chunk-dbq4qf52.js.map +25 -0
- package/dist/chunk-drna2rny.js +836 -0
- package/dist/chunk-drna2rny.js.map +17 -0
- package/dist/chunk-dxvypr7y.js +89 -0
- package/dist/chunk-dxvypr7y.js.map +11 -0
- package/dist/chunk-f6yme003.js +1589 -0
- package/dist/chunk-f6yme003.js.map +30 -0
- package/dist/chunk-hg7pf34j.js +465 -0
- package/dist/chunk-hg7pf34j.js.map +19 -0
- package/dist/chunk-jq4e17tj.js +1031 -0
- package/dist/chunk-jq4e17tj.js.map +21 -0
- package/dist/chunk-y63c6zcv.js +2668 -0
- package/dist/chunk-y63c6zcv.js.map +53 -0
- package/dist/cli/args.d.ts +30 -0
- package/dist/cli/bin.d.ts +2 -0
- package/dist/cli/bin.js +348 -0
- package/dist/cli/bin.js.map +15 -0
- package/dist/cli/load.d.ts +2 -0
- package/dist/cli/manifest.d.ts +53 -0
- package/dist/cli/render-cmds.d.ts +12 -0
- package/dist/cli/run.d.ts +1 -0
- package/dist/cli/texture-cache.d.ts +4 -0
- package/dist/core/asset.d.ts +10 -0
- package/dist/core/definition.d.ts +155 -0
- package/dist/core/errors.d.ts +17 -0
- package/dist/core/family.d.ts +23 -0
- package/dist/core/index.d.ts +9 -0
- package/dist/core/index.js +69 -0
- package/dist/core/index.js.map +9 -0
- package/dist/core/mesh.d.ts +35 -0
- package/dist/core/part.d.ts +114 -0
- package/dist/core/png.d.ts +1 -0
- package/dist/core/rng.d.ts +12 -0
- package/dist/core/transform.d.ts +20 -0
- package/dist/core/vec.d.ts +11 -0
- package/dist/core/world.d.ts +16 -0
- package/dist/export/bin-writer.d.ts +16 -0
- package/dist/export/container.d.ts +3 -0
- package/dist/export/credits.d.ts +4 -0
- package/dist/export/glb-options.d.ts +48 -0
- package/dist/export/glb.d.ts +8 -0
- package/dist/export/hierarchy.d.ts +23 -0
- package/dist/export/index.d.ts +5 -0
- package/dist/export/index.js +40 -0
- package/dist/export/index.js.map +9 -0
- package/dist/export/lights.d.ts +8 -0
- package/dist/export/lod-coverage.d.ts +12 -0
- package/dist/export/materials.d.ts +23 -0
- package/dist/export/merge-pivots.d.ts +6 -0
- package/dist/export/metadata.d.ts +21 -0
- package/dist/export/motion.d.ts +9 -0
- package/dist/export/optimize-parts.d.ts +26 -0
- package/dist/export/primitive.d.ts +3 -0
- package/dist/export/tangents.d.ts +2 -0
- package/dist/export/textures.d.ts +22 -0
- package/dist/export/version.d.ts +2 -0
- package/dist/grammar/index.d.ts +2 -0
- package/dist/grammar/index.js +16 -0
- package/dist/grammar/index.js.map +9 -0
- package/dist/grammar/split.d.ts +21 -0
- package/dist/grammar/whyte.d.ts +5 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.js +457 -0
- package/dist/index.js.map +9 -0
- package/dist/kinds/building.d.ts +44 -0
- package/dist/kinds/faces.d.ts +27 -0
- package/dist/kinds/head-armour.d.ts +5 -0
- package/dist/kinds/head-beard.d.ts +6 -0
- package/dist/kinds/head-bust.d.ts +5 -0
- package/dist/kinds/head-extras.d.ts +15 -0
- package/dist/kinds/head-face.d.ts +8 -0
- package/dist/kinds/head-garb.d.ts +4 -0
- package/dist/kinds/head-geom.d.ts +7 -0
- package/dist/kinds/head-hair.d.ts +4 -0
- package/dist/kinds/head-layout.d.ts +29 -0
- package/dist/kinds/head-mesh.d.ts +31 -0
- package/dist/kinds/head-mouth.d.ts +4 -0
- package/dist/kinds/head-params.d.ts +116 -0
- package/dist/kinds/head-presets.d.ts +19 -0
- package/dist/kinds/head-rim.d.ts +10 -0
- package/dist/kinds/head-tone.d.ts +10 -0
- package/dist/kinds/head-torso.d.ts +35 -0
- package/dist/kinds/head.d.ts +39 -0
- package/dist/kinds/hull-lines.d.ts +65 -0
- package/dist/kinds/hull-skin.d.ts +6 -0
- package/dist/kinds/hull.d.ts +14 -0
- package/dist/kinds/index.d.ts +16 -0
- package/dist/kinds/index.js +78 -0
- package/dist/kinds/index.js.map +9 -0
- package/dist/kinds/mass.d.ts +15 -0
- package/dist/kinds/openings.d.ts +30 -0
- package/dist/kinds/planned.d.ts +6 -0
- package/dist/kinds/roof-chimney.d.ts +16 -0
- package/dist/kinds/roof-shape.d.ts +64 -0
- package/dist/kinds/roof.d.ts +31 -0
- package/dist/kinds/vegetation-fronds.d.ts +15 -0
- package/dist/kinds/vegetation-impostor.d.ts +9 -0
- package/dist/kinds/vegetation-leaves.d.ts +15 -0
- package/dist/kinds/vegetation-mesh.d.ts +21 -0
- package/dist/kinds/vegetation-params.d.ts +90 -0
- package/dist/kinds/vegetation-presets.d.ts +20 -0
- package/dist/kinds/vegetation-skeleton.d.ts +20 -0
- package/dist/kinds/vegetation.d.ts +42 -0
- package/dist/kinds/vehicle.d.ts +42 -0
- package/dist/material/cc0.d.ts +4 -0
- package/dist/material/define.d.ts +34 -0
- package/dist/material/generator.d.ts +4 -0
- package/dist/material/index.d.ts +9 -0
- package/dist/material/index.js +70 -0
- package/dist/material/index.js.map +9 -0
- package/dist/material/library.d.ts +7 -0
- package/dist/material/material-def.d.ts +30 -0
- package/dist/material/paint/bond.d.ts +3 -0
- package/dist/material/paint/canvas.d.ts +39 -0
- package/dist/material/paint/cell.d.ts +4 -0
- package/dist/material/paint/cells-round.d.ts +5 -0
- package/dist/material/paint/cells.d.ts +7 -0
- package/dist/material/paint/compose.d.ts +5 -0
- package/dist/material/paint/concrete.d.ts +3 -0
- package/dist/material/paint/courses.d.ts +31 -0
- package/dist/material/paint/decode-png.d.ts +6 -0
- package/dist/material/paint/default-sheet.d.ts +4 -0
- package/dist/material/paint/fabric.d.ts +4 -0
- package/dist/material/paint/foliage-broad.d.ts +5 -0
- package/dist/material/paint/foliage-common.d.ts +35 -0
- package/dist/material/paint/foliage-compound.d.ts +4 -0
- package/dist/material/paint/foliage-conifer.d.ts +5 -0
- package/dist/material/paint/foliage-raster.d.ts +26 -0
- package/dist/material/paint/foliage.d.ts +3 -0
- package/dist/material/paint/image-strip.d.ts +4 -0
- package/dist/material/paint/kit.d.ts +5 -0
- package/dist/material/paint/masks.d.ts +3 -0
- package/dist/material/paint/metal.d.ts +3 -0
- package/dist/material/paint/noise.d.ts +9 -0
- package/dist/material/paint/normal.d.ts +8 -0
- package/dist/material/paint/orm.d.ts +8 -0
- package/dist/material/paint/planks.d.ts +3 -0
- package/dist/material/paint/plates.d.ts +3 -0
- package/dist/material/paint/shapes.d.ts +8 -0
- package/dist/material/paint/slate.d.ts +3 -0
- package/dist/material/paint/stamp.d.ts +3 -0
- package/dist/material/paint/strip.d.ts +3 -0
- package/dist/material/paint/surface.d.ts +5 -0
- package/dist/material/paint/types.d.ts +65 -0
- package/dist/material/paint/validate.d.ts +3 -0
- package/dist/material/palette.d.ts +14 -0
- package/dist/material/shader-godot.d.ts +2 -0
- package/dist/material/shader-three.d.ts +2 -0
- package/dist/material/shader.d.ts +46 -0
- package/dist/material/slots.d.ts +5 -0
- package/dist/material/texture-source.d.ts +34 -0
- package/dist/material/trim-sheet.d.ts +38 -0
- package/dist/neural/generator.d.ts +25 -0
- package/dist/neural/images.d.ts +17 -0
- package/dist/neural/index.d.ts +2 -0
- package/dist/neural/index.js +14 -0
- package/dist/neural/index.js.map +9 -0
- package/dist/passes/bake-ao.d.ts +17 -0
- package/dist/passes/grime.d.ts +15 -0
- package/dist/passes/index.d.ts +6 -0
- package/dist/passes/index.js +22 -0
- package/dist/passes/index.js.map +9 -0
- package/dist/passes/livery.d.ts +19 -0
- package/dist/passes/optimize-cache.d.ts +15 -0
- package/dist/passes/optimize-weld.d.ts +15 -0
- package/dist/passes/optimize.d.ts +28 -0
- package/dist/passes/ray-grid.d.ts +23 -0
- package/dist/passes/weighted-normals.d.ts +8 -0
- package/dist/primitives/beam.d.ts +17 -0
- package/dist/primitives/bevel-box.d.ts +13 -0
- package/dist/primitives/box.d.ts +16 -0
- package/dist/primitives/cell.d.ts +20 -0
- package/dist/primitives/check.d.ts +12 -0
- package/dist/primitives/closed.d.ts +11 -0
- package/dist/primitives/erosion.d.ts +22 -0
- package/dist/primitives/font-5x7.d.ts +3 -0
- package/dist/primitives/heightfield.d.ts +16 -0
- package/dist/primitives/index.d.ts +23 -0
- package/dist/primitives/index.js +81 -0
- package/dist/primitives/index.js.map +9 -0
- package/dist/primitives/lathe-facets.d.ts +8 -0
- package/dist/primitives/lathe.d.ts +26 -0
- package/dist/primitives/lattice.d.ts +30 -0
- package/dist/primitives/loft.d.ts +15 -0
- package/dist/primitives/mc-table.d.ts +2 -0
- package/dist/primitives/member.d.ts +19 -0
- package/dist/primitives/noise.d.ts +34 -0
- package/dist/primitives/planar.d.ts +10 -0
- package/dist/primitives/prism.d.ts +13 -0
- package/dist/primitives/sculpt-edit.d.ts +56 -0
- package/dist/primitives/sculpt-tree.d.ts +23 -0
- package/dist/primitives/sculpt.d.ts +27 -0
- package/dist/primitives/sdf-grid.d.ts +17 -0
- package/dist/primitives/sdf-ops.d.ts +37 -0
- package/dist/primitives/sdf.d.ts +21 -0
- package/dist/primitives/strip-uv.d.ts +11 -0
- package/dist/primitives/surface-nets.d.ts +7 -0
- package/dist/primitives/sweep.d.ts +19 -0
- package/dist/primitives/terrain-color.d.ts +30 -0
- package/dist/primitives/terrain-grid.d.ts +36 -0
- package/dist/primitives/text-layout.d.ts +22 -0
- package/dist/primitives/text.d.ts +27 -0
- package/dist/primitives/tiled.d.ts +22 -0
- package/dist/primitives/transport.d.ts +17 -0
- package/dist/primitives/triangulate.d.ts +2 -0
- package/dist/primitives/value-noise.d.ts +10 -0
- package/dist/qa/checks.d.ts +11 -0
- package/dist/qa/clash.d.ts +2 -0
- package/dist/qa/floating.d.ts +5 -0
- package/dist/qa/gates.d.ts +12 -0
- package/dist/qa/geometry.d.ts +21 -0
- package/dist/qa/index.d.ts +12 -0
- package/dist/qa/index.js +78 -0
- package/dist/qa/index.js.map +9 -0
- package/dist/qa/inside.d.ts +12 -0
- package/dist/qa/inspect.d.ts +18 -0
- package/dist/qa/lods.d.ts +12 -0
- package/dist/qa/measures.d.ts +4 -0
- package/dist/qa/occlusion.d.ts +3 -0
- package/dist/qa/sanity.d.ts +7 -0
- package/dist/qa/types.d.ts +12 -0
- package/dist/render/beauty.d.ts +40 -0
- package/dist/render/camera.d.ts +33 -0
- package/dist/render/depth-map.d.ts +38 -0
- package/dist/render/font.d.ts +1 -0
- package/dist/render/ground.d.ts +13 -0
- package/dist/render/index.d.ts +10 -0
- package/dist/render/index.js +47 -0
- package/dist/render/index.js.map +9 -0
- package/dist/render/lighting.d.ts +27 -0
- package/dist/render/lod-strip.d.ts +5 -0
- package/dist/render/metrics.d.ts +37 -0
- package/dist/render/options.d.ts +28 -0
- package/dist/render/photo-match.d.ts +19 -0
- package/dist/render/raster.d.ts +25 -0
- package/dist/render/resolve.d.ts +11 -0
- package/dist/render/review-prompt.d.ts +2 -0
- package/dist/render/review-warnings.d.ts +34 -0
- package/dist/render/review.d.ts +24 -0
- package/dist/render/scene.d.ts +18 -0
- package/dist/render/shade.d.ts +22 -0
- package/dist/render/sheet.d.ts +15 -0
- package/dist/render/texture.d.ts +15 -0
- package/dist/render/thumbnail.d.ts +8 -0
- package/dist/render/vis-buffer.d.ts +18 -0
- package/dist/testing/assert.d.ts +21 -0
- package/dist/testing/compiled.d.ts +15 -0
- package/dist/testing/hash.d.ts +1 -0
- package/dist/testing/index.d.ts +4 -0
- package/dist/testing/index.js +134 -0
- package/dist/testing/index.js.map +13 -0
- package/dist/testing/snapshot.d.ts +13 -0
- package/docs/README.md +56 -0
- package/docs/architecture/README.md +68 -0
- package/docs/architecture/adding-a-kind.md +44 -0
- package/docs/architecture/adding-a-primitive.md +49 -0
- package/docs/architecture/errors.md +47 -0
- package/docs/architecture/glb-production.md +214 -0
- package/docs/architecture/gltf-capabilities.md +117 -0
- package/docs/architecture/materials.md +151 -0
- package/docs/decisions/001-recipe-compiler-over-ai-meshes.md +27 -0
- package/docs/decisions/002-typescript-not-json.md +22 -0
- package/docs/decisions/003-shared-trim-sheet.md +21 -0
- package/docs/decisions/004-z-up-metres.md +21 -0
- package/docs/decisions/005-zero-runtime-deps.md +21 -0
- package/docs/decisions/006-single-package-subpath-exports.md +20 -0
- package/docs/decisions/007-cpu-contact-sheets.md +21 -0
- package/docs/decisions/008-surface-materials.md +21 -0
- package/docs/decisions/009-gltf-front-axis.md +21 -0
- package/docs/decisions/README.md +15 -0
- package/docs/idea/01-vision.md +117 -0
- package/docs/idea/02-dsl.md +343 -0
- package/docs/idea/03-ir.md +97 -0
- package/docs/idea/04-materials.md +114 -0
- package/docs/idea/05-agent-loop.md +141 -0
- package/docs/idea/06-qa.md +101 -0
- package/docs/idea/07-what-fits.md +45 -0
- package/docs/idea/08-neural-adapters.md +78 -0
- package/docs/idea/09-kinds.md +105 -0
- package/docs/idea/10-sculpting.md +166 -0
- package/docs/idea/11-materials-authoring.md +132 -0
- package/docs/idea/12-blender-bridge.md +136 -0
- package/docs/idea/13-asset-pipeline-research.md +89 -0
- package/docs/landscape.md +49 -0
- package/docs/plans/roadmap.md +139 -0
- package/examples/build-with-bun.ts +41 -0
- package/llms.txt +47 -0
- package/package.json +100 -4
- package/recipes/README.md +38 -0
- package/recipes/asteroid/README.md +46 -0
- package/recipes/asteroid/asteroid.ts +336 -0
- package/recipes/boulders/README.md +28 -0
- package/recipes/boulders/boulders.ts +117 -0
- package/recipes/boxcar/README.md +53 -0
- package/recipes/boxcar/boxcar.ts +1000 -0
- package/recipes/cargo_container_scifi/README.md +52 -0
- package/recipes/cargo_container_scifi/cargo_container_scifi.ts +461 -0
- package/recipes/dropship/README.md +84 -0
- package/recipes/dropship/dropship.ts +1144 -0
- package/recipes/eiffel_tower/README.md +110 -0
- package/recipes/eiffel_tower/eiffel_tower.ts +781 -0
- package/recipes/goblin_head/README.md +75 -0
- package/recipes/goblin_head/goblin_head.ts +38 -0
- package/recipes/human_head/README.md +68 -0
- package/recipes/human_head/human_head.ts +38 -0
- package/recipes/loco_440/README.md +32 -0
- package/recipes/loco_440/loco_440.ts +1404 -0
- package/recipes/material_swatches/README.md +21 -0
- package/recipes/material_swatches/material_swatches.ts +189 -0
- package/recipes/mountain_range/README.md +45 -0
- package/recipes/mountain_range/mountain_range.ts +128 -0
- package/recipes/oak/README.md +30 -0
- package/recipes/oak/oak.ts +19 -0
- package/recipes/orc_head/README.md +78 -0
- package/recipes/orc_head/orc_head.ts +41 -0
- package/recipes/palm/README.md +30 -0
- package/recipes/palm/palm.ts +19 -0
- package/recipes/pine/README.md +29 -0
- package/recipes/pine/pine.ts +19 -0
- package/recipes/signal_gantry/README.md +36 -0
- package/recipes/signal_gantry/signal_gantry.ts +522 -0
- package/recipes/station_halt/README.md +39 -0
- package/recipes/station_halt/station_halt.ts +722 -0
- package/recipes/t34/README.md +44 -0
- package/recipes/t34/t34.ts +1068 -0
- package/recipes/tiger_1/README.md +75 -0
- package/recipes/tiger_1/tiger_1.ts +1370 -0
- package/recipes/water_tower/README.md +40 -0
- package/recipes/water_tower/water_tower.ts +542 -0
- package/src/cli/args.ts +125 -0
- package/src/cli/bin.ts +7 -0
- package/src/cli/load.ts +17 -0
- package/src/cli/manifest.ts +95 -0
- package/src/cli/render-cmds.ts +66 -0
- package/src/cli/run.ts +192 -0
- package/src/cli/texture-cache.ts +24 -0
- package/src/core/asset.ts +129 -0
- package/src/core/definition.ts +156 -0
- package/src/core/errors.ts +50 -0
- package/src/core/family.ts +50 -0
- package/src/core/index.ts +66 -0
- package/src/core/mesh.ts +114 -0
- package/src/core/part.ts +130 -0
- package/src/core/png.ts +49 -0
- package/src/core/rng.ts +49 -0
- package/src/core/transform.ts +90 -0
- package/src/core/vec.ts +26 -0
- package/src/core/world.ts +80 -0
- package/src/export/bin-writer.ts +79 -0
- package/src/export/container.ts +35 -0
- package/src/export/credits.ts +25 -0
- package/src/export/glb-options.ts +53 -0
- package/src/export/glb.ts +187 -0
- package/src/export/hierarchy.ts +122 -0
- package/src/export/index.ts +34 -0
- package/src/export/lights.ts +49 -0
- package/src/export/lod-coverage.ts +71 -0
- package/src/export/materials.ts +126 -0
- package/src/export/merge-pivots.ts +146 -0
- package/src/export/metadata.ts +62 -0
- package/src/export/motion.ts +70 -0
- package/src/export/optimize-parts.ts +80 -0
- package/src/export/primitive.ts +35 -0
- package/src/export/tangents.ts +75 -0
- package/src/export/textures.ts +88 -0
- package/src/export/version.ts +6 -0
- package/src/grammar/index.ts +4 -0
- package/src/grammar/split.ts +87 -0
- package/src/grammar/whyte.ts +20 -0
- package/src/index.ts +14 -0
- package/src/kinds/building.ts +153 -0
- package/src/kinds/faces.ts +138 -0
- package/src/kinds/head-armour.ts +181 -0
- package/src/kinds/head-beard.ts +133 -0
- package/src/kinds/head-bust.ts +184 -0
- package/src/kinds/head-extras.ts +150 -0
- package/src/kinds/head-face.ts +242 -0
- package/src/kinds/head-garb.ts +181 -0
- package/src/kinds/head-geom.ts +31 -0
- package/src/kinds/head-hair.ts +193 -0
- package/src/kinds/head-layout.ts +63 -0
- package/src/kinds/head-mesh.ts +195 -0
- package/src/kinds/head-mouth.ts +111 -0
- package/src/kinds/head-params.ts +162 -0
- package/src/kinds/head-presets.ts +155 -0
- package/src/kinds/head-rim.ts +128 -0
- package/src/kinds/head-tone.ts +52 -0
- package/src/kinds/head-torso.ts +230 -0
- package/src/kinds/head.ts +176 -0
- package/src/kinds/hull-lines.ts +160 -0
- package/src/kinds/hull-skin.ts +83 -0
- package/src/kinds/hull.ts +209 -0
- package/src/kinds/index.ts +63 -0
- package/src/kinds/mass.ts +110 -0
- package/src/kinds/openings.ts +141 -0
- package/src/kinds/planned.ts +12 -0
- package/src/kinds/roof-chimney.ts +100 -0
- package/src/kinds/roof-shape.ts +230 -0
- package/src/kinds/roof.ts +250 -0
- package/src/kinds/vegetation-fronds.ts +126 -0
- package/src/kinds/vegetation-impostor.ts +118 -0
- package/src/kinds/vegetation-leaves.ts +168 -0
- package/src/kinds/vegetation-mesh.ts +174 -0
- package/src/kinds/vegetation-params.ts +147 -0
- package/src/kinds/vegetation-presets.ts +184 -0
- package/src/kinds/vegetation-skeleton.ts +168 -0
- package/src/kinds/vegetation.ts +199 -0
- package/src/kinds/vehicle.ts +144 -0
- package/src/material/cc0.ts +41 -0
- package/src/material/define.ts +130 -0
- package/src/material/generator.ts +63 -0
- package/src/material/index.ts +60 -0
- package/src/material/library.ts +196 -0
- package/src/material/material-def.ts +84 -0
- package/src/material/paint/bond.ts +60 -0
- package/src/material/paint/canvas.ts +101 -0
- package/src/material/paint/cell.ts +39 -0
- package/src/material/paint/cells-round.ts +119 -0
- package/src/material/paint/cells.ts +111 -0
- package/src/material/paint/compose.ts +53 -0
- package/src/material/paint/concrete.ts +62 -0
- package/src/material/paint/courses.ts +85 -0
- package/src/material/paint/decode-png.ts +106 -0
- package/src/material/paint/default-sheet.ts +73 -0
- package/src/material/paint/fabric.ts +63 -0
- package/src/material/paint/foliage-broad.ts +126 -0
- package/src/material/paint/foliage-common.ts +93 -0
- package/src/material/paint/foliage-compound.ts +135 -0
- package/src/material/paint/foliage-conifer.ts +143 -0
- package/src/material/paint/foliage-raster.ts +196 -0
- package/src/material/paint/foliage.ts +23 -0
- package/src/material/paint/image-strip.ts +88 -0
- package/src/material/paint/kit.ts +37 -0
- package/src/material/paint/masks.ts +46 -0
- package/src/material/paint/metal.ts +109 -0
- package/src/material/paint/noise.ts +52 -0
- package/src/material/paint/normal.ts +52 -0
- package/src/material/paint/orm.ts +108 -0
- package/src/material/paint/planks.ts +101 -0
- package/src/material/paint/plates.ts +72 -0
- package/src/material/paint/shapes.ts +28 -0
- package/src/material/paint/slate.ts +52 -0
- package/src/material/paint/stamp.ts +40 -0
- package/src/material/paint/strip.ts +48 -0
- package/src/material/paint/surface.ts +60 -0
- package/src/material/paint/types.ts +94 -0
- package/src/material/paint/validate.ts +74 -0
- package/src/material/palette.ts +46 -0
- package/src/material/shader-godot.ts +77 -0
- package/src/material/shader-three.ts +103 -0
- package/src/material/shader.ts +100 -0
- package/src/material/slots.ts +18 -0
- package/src/material/texture-source.ts +86 -0
- package/src/material/trim-sheet.ts +166 -0
- package/src/neural/generator.ts +37 -0
- package/src/neural/images.ts +27 -0
- package/src/neural/index.ts +10 -0
- package/src/passes/bake-ao.ts +183 -0
- package/src/passes/grime.ts +37 -0
- package/src/passes/index.ts +8 -0
- package/src/passes/livery.ts +66 -0
- package/src/passes/optimize-cache.ts +175 -0
- package/src/passes/optimize-weld.ts +147 -0
- package/src/passes/optimize.ts +85 -0
- package/src/passes/ray-grid.ts +237 -0
- package/src/passes/weighted-normals.ts +125 -0
- package/src/primitives/beam.ts +60 -0
- package/src/primitives/bevel-box.ts +140 -0
- package/src/primitives/box.ts +90 -0
- package/src/primitives/cell.ts +115 -0
- package/src/primitives/check.ts +49 -0
- package/src/primitives/closed.ts +74 -0
- package/src/primitives/erosion.ts +183 -0
- package/src/primitives/font-5x7.ts +117 -0
- package/src/primitives/heightfield.ts +101 -0
- package/src/primitives/index.ts +56 -0
- package/src/primitives/lathe-facets.ts +45 -0
- package/src/primitives/lathe.ts +174 -0
- package/src/primitives/lattice.ts +131 -0
- package/src/primitives/loft.ts +174 -0
- package/src/primitives/mc-table.ts +41 -0
- package/src/primitives/member.ts +130 -0
- package/src/primitives/noise.ts +157 -0
- package/src/primitives/planar.ts +55 -0
- package/src/primitives/prism.ts +85 -0
- package/src/primitives/sculpt-edit.ts +212 -0
- package/src/primitives/sculpt-tree.ts +226 -0
- package/src/primitives/sculpt.ts +80 -0
- package/src/primitives/sdf-grid.ts +131 -0
- package/src/primitives/sdf-ops.ts +145 -0
- package/src/primitives/sdf.ts +83 -0
- package/src/primitives/strip-uv.ts +26 -0
- package/src/primitives/surface-nets.ts +161 -0
- package/src/primitives/sweep.ts +162 -0
- package/src/primitives/terrain-color.ts +85 -0
- package/src/primitives/terrain-grid.ts +137 -0
- package/src/primitives/text-layout.ts +85 -0
- package/src/primitives/text.ts +197 -0
- package/src/primitives/tiled.ts +93 -0
- package/src/primitives/transport.ts +85 -0
- package/src/primitives/triangulate.ts +42 -0
- package/src/primitives/value-noise.ts +62 -0
- package/src/qa/checks.ts +110 -0
- package/src/qa/clash.ts +177 -0
- package/src/qa/floating.ts +63 -0
- package/src/qa/gates.ts +126 -0
- package/src/qa/geometry.ts +187 -0
- package/src/qa/index.ts +28 -0
- package/src/qa/inside.ts +114 -0
- package/src/qa/inspect.ts +107 -0
- package/src/qa/lods.ts +97 -0
- package/src/qa/measures.ts +67 -0
- package/src/qa/occlusion.ts +166 -0
- package/src/qa/sanity.ts +137 -0
- package/src/qa/types.ts +17 -0
- package/src/render/beauty.ts +115 -0
- package/src/render/camera.ts +142 -0
- package/src/render/depth-map.ts +191 -0
- package/src/render/font.ts +76 -0
- package/src/render/ground.ts +87 -0
- package/src/render/index.ts +34 -0
- package/src/render/lighting.ts +121 -0
- package/src/render/lod-strip.ts +34 -0
- package/src/render/metrics.ts +147 -0
- package/src/render/options.ts +81 -0
- package/src/render/photo-match.ts +28 -0
- package/src/render/raster.ts +143 -0
- package/src/render/resolve.ts +109 -0
- package/src/render/review-prompt.ts +59 -0
- package/src/render/review-warnings.ts +92 -0
- package/src/render/review.ts +103 -0
- package/src/render/scene.ts +119 -0
- package/src/render/shade.ts +204 -0
- package/src/render/sheet.ts +88 -0
- package/src/render/texture.ts +97 -0
- package/src/render/thumbnail.ts +75 -0
- package/src/render/vis-buffer.ts +119 -0
- package/src/testing/assert.ts +115 -0
- package/src/testing/compiled.ts +31 -0
- package/src/testing/hash.ts +14 -0
- package/src/testing/index.ts +14 -0
- package/src/testing/snapshot.ts +37 -0
- package/src/types/gltf-validator.d.ts +13 -0
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
// A hull's lines plan as functions, no mesh: deck-edge plan (half-breadth), sheer (deck-edge
|
|
2
|
+
// height), keel/stem/counter profile and the section shape at any station. Waterline at z = 0,
|
|
3
|
+
// bow toward +X, x = 0 amidships. Sections are superellipse quarters (n = 2 round bilge, 4 hard
|
|
4
|
+
// bilge), going V toward the ends; the stem is where the keel line rises to meet the sheer.
|
|
5
|
+
|
|
6
|
+
import { Ts23dError, type Vec3 } from '../core/index.ts';
|
|
7
|
+
|
|
8
|
+
export interface HullColors {
|
|
9
|
+
/** Above the boot-top. */
|
|
10
|
+
readonly topsides: Vec3;
|
|
11
|
+
/** Below the waterline (antifouling). */
|
|
12
|
+
readonly bottom: Vec3;
|
|
13
|
+
/** The boot-top band at the waterline. Default near-black. */
|
|
14
|
+
readonly boot?: Vec3;
|
|
15
|
+
readonly deck: Vec3;
|
|
16
|
+
/** Inside of the bulwarks and the cap rail. Default = topsides. */
|
|
17
|
+
readonly bulwark?: Vec3;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export interface HullOptions {
|
|
21
|
+
/** Length overall at the deck, metres. */
|
|
22
|
+
readonly length: number;
|
|
23
|
+
/** Maximum beam at the deck edge. */
|
|
24
|
+
readonly beam: number;
|
|
25
|
+
/** Keel below the waterline. */
|
|
26
|
+
readonly draft: number;
|
|
27
|
+
/** Deck edge above the waterline amidships (lowest point of the sheer). */
|
|
28
|
+
readonly freeboard: number;
|
|
29
|
+
/** Sheer rise of the deck edge at [bow, stern] above amidships. Default [0.035, 0.012]·L. */
|
|
30
|
+
readonly sheer?: readonly [number, number];
|
|
31
|
+
/** 'round' (cruiser / tug) or 'transom' (flat stern). Default 'round'. */
|
|
32
|
+
readonly stern?: 'round' | 'transom';
|
|
33
|
+
/** Transom half-width as a share of the half-beam. Default 0.75. */
|
|
34
|
+
readonly transomWidth?: number;
|
|
35
|
+
/** Bilge: section superellipse exponent, 1.5 (soft V) … 5 (barge). Default 3. */
|
|
36
|
+
readonly fullness?: number;
|
|
37
|
+
/** Plan entrance exponent at the bow: 1.4 sharp … 3 bluff. Default 2. */
|
|
38
|
+
readonly entrance?: number;
|
|
39
|
+
/** Deck-edge breadth over waterline breadth − 1. Default 0.06. */
|
|
40
|
+
readonly flare?: number;
|
|
41
|
+
/** Bottom deadrise, degrees. Default 5. */
|
|
42
|
+
readonly deadriseDeg?: number;
|
|
43
|
+
/** Bulwark height above the deck, metres; 0 = none. Default 0. */
|
|
44
|
+
readonly bulwark?: number;
|
|
45
|
+
/** Deck camber at the centreline, metres. Default beam / 50. */
|
|
46
|
+
readonly camber?: number;
|
|
47
|
+
/** Height of the boot-top band above the waterline. Default 0.3. */
|
|
48
|
+
readonly bootTop?: number;
|
|
49
|
+
readonly colors: HullColors;
|
|
50
|
+
/** A rubbing strake / fender along each side just below the sheer (LOD0/1). */
|
|
51
|
+
readonly fender?: { readonly color: Vec3; readonly radius?: number };
|
|
52
|
+
/** Waterline amidships. Default [0, 0, 0]. */
|
|
53
|
+
readonly at?: Vec3;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export interface HullLines {
|
|
57
|
+
readonly L: number;
|
|
58
|
+
/** Deck-edge half-breadth at x (outer hull). */
|
|
59
|
+
readonly halfBreadth: (x: number) => number;
|
|
60
|
+
/** Deck-edge height at x (sheer line), relative to the waterline. */
|
|
61
|
+
readonly deck: (x: number) => number;
|
|
62
|
+
/** Keel / stem / counter height at x. */
|
|
63
|
+
readonly keel: (x: number) => number;
|
|
64
|
+
/** Section point at x for θ ∈ [0, π/2] (0 = keel, π/2 = deck edge), starboard (y ≥ 0). */
|
|
65
|
+
readonly section: (x: number, theta: number) => [number, number];
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const bad = (cause: string, fix: string): Ts23dError =>
|
|
69
|
+
new Ts23dError('T3D_RECIPE_INVALID', { cause, fix });
|
|
70
|
+
|
|
71
|
+
export function validateHull(o: HullOptions): void {
|
|
72
|
+
const dims = [o.length, o.beam, o.draft, o.freeboard];
|
|
73
|
+
if (!dims.every((v) => v > 0 && Number.isFinite(v)))
|
|
74
|
+
throw bad(
|
|
75
|
+
`hull length/beam/draft/freeboard = ${dims.join(' / ')}`,
|
|
76
|
+
'give all four in metres, > 0 (a harbour tug: 30 / 9 / 4 / 1.2)',
|
|
77
|
+
);
|
|
78
|
+
if (o.beam > o.length * 0.8)
|
|
79
|
+
throw bad(
|
|
80
|
+
`hull beam ${o.beam} is over 0.8 × length ${o.length}`,
|
|
81
|
+
'check the numbers: length/beam is 2.5–4 for tugs, 6–9 for ships',
|
|
82
|
+
);
|
|
83
|
+
const n = o.fullness ?? 3;
|
|
84
|
+
if (!(n >= 1.2 && n <= 8)) throw bad(`hull fullness is ${n}`, 'use 1.5 (soft V) … 5 (barge)');
|
|
85
|
+
const tw = o.transomWidth ?? 0.75;
|
|
86
|
+
if (!(tw > 0 && tw <= 1))
|
|
87
|
+
throw bad(`hull transomWidth is ${tw}`, 'use a share 0.3–1 of the half-beam');
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const smooth = (t: number): number => (t <= 0 ? 0 : t >= 1 ? 1 : t * t * (3 - 2 * t));
|
|
91
|
+
|
|
92
|
+
export function hullLines(o: HullOptions): HullLines {
|
|
93
|
+
validateHull(o);
|
|
94
|
+
const L = o.length;
|
|
95
|
+
const half = L / 2;
|
|
96
|
+
const [sb, ss] = o.sheer ?? [0.035 * L, 0.012 * L];
|
|
97
|
+
const round = (o.stern ?? 'round') === 'round';
|
|
98
|
+
const tw = o.transomWidth ?? 0.75;
|
|
99
|
+
const pe = o.entrance ?? 2;
|
|
100
|
+
const n = o.fullness ?? 3;
|
|
101
|
+
const flare = o.flare ?? 0.06;
|
|
102
|
+
const dead = Math.tan(((o.deadriseDeg ?? 5) * Math.PI) / 180);
|
|
103
|
+
// Parallel middle body and where the keel starts to rise, as shares of L.
|
|
104
|
+
const xf = 0.1 * L;
|
|
105
|
+
const xa = -0.15 * L;
|
|
106
|
+
const kf = 0.22 * L;
|
|
107
|
+
const ka = -0.25 * L;
|
|
108
|
+
const deck = (x: number): number => {
|
|
109
|
+
const u = x / half;
|
|
110
|
+
return o.freeboard + (u > 0 ? sb : ss) * u * u;
|
|
111
|
+
};
|
|
112
|
+
const plan = (x: number): number => {
|
|
113
|
+
if (x > xf) return 1 - ((x - xf) / (half - xf)) ** pe;
|
|
114
|
+
if (x < xa) {
|
|
115
|
+
const v = Math.min(1, (xa - x) / (xa + half));
|
|
116
|
+
return round ? Math.sqrt(Math.max(0, 1 - v * v)) : 1 - (1 - tw) * v * v;
|
|
117
|
+
}
|
|
118
|
+
return 1;
|
|
119
|
+
};
|
|
120
|
+
const halfBreadth = (x: number): number => (o.beam / 2) * Math.max(0, plan(x));
|
|
121
|
+
const counter = round ? 0.35 * o.freeboard : 0.15 * o.freeboard;
|
|
122
|
+
const keel = (x: number): number => {
|
|
123
|
+
if (x > kf) {
|
|
124
|
+
const u = Math.min(1, (x - kf) / (half - kf));
|
|
125
|
+
return -o.draft + (deck(half) + o.draft) * u ** 2;
|
|
126
|
+
}
|
|
127
|
+
if (x < ka) {
|
|
128
|
+
const v = Math.min(1, (ka - x) / (ka + half));
|
|
129
|
+
return -o.draft + (counter + o.draft) * v ** 1.6;
|
|
130
|
+
}
|
|
131
|
+
return -o.draft;
|
|
132
|
+
};
|
|
133
|
+
const section = (x: number, theta: number): [number, number] => {
|
|
134
|
+
const f = plan(x);
|
|
135
|
+
// Fine ends go V-sectioned; the middle body keeps the full bilge.
|
|
136
|
+
const ns = 1.2 + (n - 1.2) * smooth(f / 0.8);
|
|
137
|
+
const s = Math.sin(theta) ** (2 / ns);
|
|
138
|
+
const c = Math.cos(theta) ** (2 / ns);
|
|
139
|
+
const zk = keel(x);
|
|
140
|
+
const zd = deck(x);
|
|
141
|
+
const zf = 1 - c;
|
|
142
|
+
const y = halfBreadth(x) * (1 - flare + flare * zf * zf) * s;
|
|
143
|
+
return [y, zk + (zd - zk) * zf + dead * y * c];
|
|
144
|
+
};
|
|
145
|
+
return { L, halfBreadth, deck, keel, section };
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/** θ where the section crosses height z (bisection; the section rises monotonically). */
|
|
149
|
+
export function thetaAt(lines: HullLines, x: number, z: number): number {
|
|
150
|
+
let lo = 0;
|
|
151
|
+
let hi = Math.PI / 2;
|
|
152
|
+
if (lines.section(x, lo)[1] >= z) return lo;
|
|
153
|
+
if (lines.section(x, hi)[1] <= z) return hi;
|
|
154
|
+
for (let i = 0; i < 40; i++) {
|
|
155
|
+
const mid = (lo + hi) / 2;
|
|
156
|
+
if (lines.section(x, mid)[1] < z) lo = mid;
|
|
157
|
+
else hi = mid;
|
|
158
|
+
}
|
|
159
|
+
return (lo + hi) / 2;
|
|
160
|
+
}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
// Skinning for hull-like surfaces: a station × column grid of points becomes quads with smooth
|
|
2
|
+
// normals (central differences; collapsed rows such as a stem head borrow their neighbour's), and
|
|
3
|
+
// any column range can be emitted as its own colour band, mirrored to port for a symmetric hull.
|
|
4
|
+
|
|
5
|
+
import type { MeshBuilder, Vec3 } from '../core/index.ts';
|
|
6
|
+
import { stripRect } from '../material/index.ts';
|
|
7
|
+
|
|
8
|
+
export type Grid = Vec3[][];
|
|
9
|
+
const sub3 = (a: Vec3, b: Vec3): Vec3 => [a[0] - b[0], a[1] - b[1], a[2] - b[2]];
|
|
10
|
+
const cross3 = (a: Vec3, b: Vec3): Vec3 => [
|
|
11
|
+
a[1] * b[2] - a[2] * b[1],
|
|
12
|
+
a[2] * b[0] - a[0] * b[2],
|
|
13
|
+
a[0] * b[1] - a[1] * b[0],
|
|
14
|
+
];
|
|
15
|
+
|
|
16
|
+
/** Smooth normals over a station × column grid (outward = tj × ti for the starboard side). */
|
|
17
|
+
export function normalsOf(g: Grid): Grid {
|
|
18
|
+
const R = g.length;
|
|
19
|
+
const out: Grid = g.map((row, i) =>
|
|
20
|
+
row.map((p, j) => {
|
|
21
|
+
const r = (k: number): Vec3[] => g[Math.max(0, Math.min(R - 1, k))] ?? row;
|
|
22
|
+
const ti = sub3(r(i + 1)[j] ?? p, r(i - 1)[j] ?? p);
|
|
23
|
+
const tj = sub3(row[Math.min(row.length - 1, j + 1)] ?? p, row[Math.max(0, j - 1)] ?? p);
|
|
24
|
+
const n = cross3(tj, ti);
|
|
25
|
+
const l = Math.hypot(...n);
|
|
26
|
+
return l < 1e-9 ? ([0, 0, 0] as Vec3) : ([n[0] / l, n[1] / l, n[2] / l] as Vec3);
|
|
27
|
+
}),
|
|
28
|
+
);
|
|
29
|
+
// Collapsed rows (stem head, round stern post) borrow the nearest row's normals.
|
|
30
|
+
for (let i = 0; i < R; i++) {
|
|
31
|
+
const row = out[i] ?? [];
|
|
32
|
+
row.forEach((n, j) => {
|
|
33
|
+
if (n[0] || n[1] || n[2]) return;
|
|
34
|
+
for (let d = 1; d < R; d++) {
|
|
35
|
+
const m = out[i - d]?.[j] ?? out[i + d]?.[j];
|
|
36
|
+
if (m && (m[0] || m[1] || m[2])) {
|
|
37
|
+
row[j] = m;
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
return out;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/** Emit columns [j0, j1] of a starboard grid and its port mirror. */
|
|
47
|
+
export function emitBand(
|
|
48
|
+
b: MeshBuilder,
|
|
49
|
+
g: Grid,
|
|
50
|
+
nrm: Grid,
|
|
51
|
+
j0: number,
|
|
52
|
+
j1: number,
|
|
53
|
+
color: Vec3,
|
|
54
|
+
mirror: boolean,
|
|
55
|
+
): void {
|
|
56
|
+
const rect = stripRect('plain');
|
|
57
|
+
for (const side of mirror ? [1, -1] : [1]) {
|
|
58
|
+
const ids = g.map((row, i) =>
|
|
59
|
+
row.slice(j0, j1 + 1).map((p, k) => {
|
|
60
|
+
const n = nrm[i]?.[j0 + k] ?? [0, 0, 1];
|
|
61
|
+
return b.vertex({
|
|
62
|
+
p: [p[0], p[1] * side, p[2]],
|
|
63
|
+
n: [n[0], n[1] * side, n[2]],
|
|
64
|
+
uv: [
|
|
65
|
+
rect.u0 + p[0] / rect.metres,
|
|
66
|
+
rect.v0 + (k / Math.max(1, j1 - j0)) * (rect.v1 - rect.v0),
|
|
67
|
+
],
|
|
68
|
+
color,
|
|
69
|
+
});
|
|
70
|
+
}),
|
|
71
|
+
);
|
|
72
|
+
for (let i = 0; i + 1 < ids.length; i++) {
|
|
73
|
+
for (let k = 0; k < j1 - j0; k++) {
|
|
74
|
+
const a = ids[i]?.[k] ?? 0;
|
|
75
|
+
const c = ids[i]?.[k + 1] ?? 0;
|
|
76
|
+
const e = ids[i + 1]?.[k + 1] ?? 0;
|
|
77
|
+
const d = ids[i + 1]?.[k] ?? 0;
|
|
78
|
+
if (side > 0) b.quad(a, c, e, d);
|
|
79
|
+
else b.quad(a, d, e, c);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
// Vessel hulls from the lines plan (hull-lines.ts): a smooth-shaded shell skinned over stations
|
|
2
|
+
// (denser toward bow and stern), split at the waterline and boot-top so the paint bands are crisp,
|
|
3
|
+
// optional bulwarks with a cap rail, a cambered plank deck laid in true-scale bands fore and aft,
|
|
4
|
+
// and a flat transom. Waterline at `at` z, bow +X. LOD = stations × section points, nothing else.
|
|
5
|
+
|
|
6
|
+
import {
|
|
7
|
+
type BuildContext,
|
|
8
|
+
type Lod,
|
|
9
|
+
type Mesh,
|
|
10
|
+
MeshBuilder,
|
|
11
|
+
merge,
|
|
12
|
+
translate,
|
|
13
|
+
type Vec3,
|
|
14
|
+
} from '../core/index.ts';
|
|
15
|
+
import { stripRect } from '../material/index.ts';
|
|
16
|
+
import { sweep, triangulate } from '../primitives/index.ts';
|
|
17
|
+
import { dedupe, stripScale } from './faces.ts';
|
|
18
|
+
import { type HullLines, type HullOptions, hullLines, thetaAt } from './hull-lines.ts';
|
|
19
|
+
import { emitBand, type Grid, normalsOf } from './hull-skin.ts';
|
|
20
|
+
|
|
21
|
+
export type { HullColors, HullLines, HullOptions } from './hull-lines.ts';
|
|
22
|
+
|
|
23
|
+
/** Width of one deck band (one V of the wood strip); LOD2 squeezes the whole beam into one. */
|
|
24
|
+
const deckBand = (o: HullOptions, lod: Lod): number => (lod === 2 ? o.beam : stripScale('wood'));
|
|
25
|
+
|
|
26
|
+
/** Plank deck between the bulwarks: bands `wood` scale wide, planks running fore and aft. */
|
|
27
|
+
function deckMesh(o: HullOptions, ln: HullLines, xs: readonly number[], inset: number, lod: Lod) {
|
|
28
|
+
const b = new MeshBuilder();
|
|
29
|
+
const rect = stripRect('wood');
|
|
30
|
+
const w = deckBand(o, lod);
|
|
31
|
+
const camber = o.camber ?? o.beam / 50;
|
|
32
|
+
const yd = (x: number): number => Math.max(0, ln.halfBreadth(x) - inset);
|
|
33
|
+
for (let y0 = -Math.ceil(o.beam / 2 / w) * w; y0 < o.beam / 2; y0 += w) {
|
|
34
|
+
const at = (x: number, y: number): Vec3 => {
|
|
35
|
+
const h = yd(x);
|
|
36
|
+
const c = Math.max(-h, Math.min(h, y));
|
|
37
|
+
return [x, c, ln.deck(x) + (h > 0 ? camber * (1 - (c / h) ** 2) : 0)];
|
|
38
|
+
};
|
|
39
|
+
for (let i = 0; i + 1 < xs.length; i++) {
|
|
40
|
+
const x0 = xs[i] ?? 0;
|
|
41
|
+
const x1 = xs[i + 1] ?? 0;
|
|
42
|
+
const q = [at(x0, y0), at(x0, y0 + w), at(x1, y0 + w), at(x1, y0)];
|
|
43
|
+
if (
|
|
44
|
+
Math.abs((q[1]?.[1] ?? 0) - (q[0]?.[1] ?? 0)) +
|
|
45
|
+
Math.abs((q[2]?.[1] ?? 0) - (q[3]?.[1] ?? 0)) <
|
|
46
|
+
1e-6
|
|
47
|
+
)
|
|
48
|
+
continue;
|
|
49
|
+
const ids = q.map((p) =>
|
|
50
|
+
b.vertex({
|
|
51
|
+
p,
|
|
52
|
+
n: [0, 0, 1],
|
|
53
|
+
uv: [rect.u0 + p[0] / rect.metres, rect.v0 + ((p[1] - y0) / w) * (rect.v1 - rect.v0)],
|
|
54
|
+
color: o.colors.deck,
|
|
55
|
+
}),
|
|
56
|
+
);
|
|
57
|
+
b.quad(ids[0] ?? 0, ids[3] ?? 0, ids[2] ?? 0, ids[1] ?? 0);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
return b.build();
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export interface HullMesh {
|
|
64
|
+
/** Shell (+ bulwarks + transom). */
|
|
65
|
+
readonly shell: Mesh;
|
|
66
|
+
readonly deck: Mesh;
|
|
67
|
+
readonly lines: HullLines;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export function hullMesh(o: HullOptions, lod: Lod = 0): HullMesh {
|
|
71
|
+
const ln = hullLines(o);
|
|
72
|
+
const half = o.length / 2;
|
|
73
|
+
const stations = [36, 18, 8][lod] ?? 8;
|
|
74
|
+
const na = [6, 3, 2][lod] ?? 2;
|
|
75
|
+
const nc = [4, 2, 1][lod] ?? 1;
|
|
76
|
+
// Cosine spacing: stations crowd the bow and stern where the shape turns.
|
|
77
|
+
const xs = Array.from(
|
|
78
|
+
{ length: stations + 1 },
|
|
79
|
+
(_, i) => -half + (o.length * (1 - Math.cos((Math.PI * i) / stations))) / 2,
|
|
80
|
+
);
|
|
81
|
+
const boot = o.bootTop ?? 0.3;
|
|
82
|
+
const hb = o.bulwark ?? 0;
|
|
83
|
+
const tb = 0.12;
|
|
84
|
+
const grid: Grid = xs.map((x) => {
|
|
85
|
+
const tw = thetaAt(ln, x, 0);
|
|
86
|
+
const tbt = thetaAt(ln, x, boot);
|
|
87
|
+
const row: Vec3[] = [];
|
|
88
|
+
const seg = (t0: number, t1: number, k: number, first: boolean) => {
|
|
89
|
+
for (let i = first ? 0 : 1; i <= k; i++) {
|
|
90
|
+
const [y, z] = ln.section(x, t0 + ((t1 - t0) * i) / k);
|
|
91
|
+
row.push([x, y, z]);
|
|
92
|
+
}
|
|
93
|
+
};
|
|
94
|
+
seg(0, tw, na, true);
|
|
95
|
+
seg(tw, tbt, 1, false);
|
|
96
|
+
seg(tbt, Math.PI / 2, nc, false);
|
|
97
|
+
return row;
|
|
98
|
+
});
|
|
99
|
+
const nrm = normalsOf(grid);
|
|
100
|
+
for (const row of nrm) {
|
|
101
|
+
const n = row[0];
|
|
102
|
+
if (n) {
|
|
103
|
+
const l = Math.hypot(n[0], n[2]) || 1;
|
|
104
|
+
row[0] = [n[0] / l, 0, n[2] / l];
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
const b = new MeshBuilder();
|
|
108
|
+
const c = o.colors;
|
|
109
|
+
emitBand(b, grid, nrm, 0, na, c.bottom, true);
|
|
110
|
+
emitBand(b, grid, nrm, na, na + 1, c.boot ?? [0.06, 0.06, 0.06], true);
|
|
111
|
+
emitBand(b, grid, nrm, na + 1, na + 1 + nc, c.topsides, true);
|
|
112
|
+
const parts = [b.build()];
|
|
113
|
+
if (hb > 0) parts.push(bulwarks(o, ln, xs, hb, tb));
|
|
114
|
+
if (o.fender && lod < 2) parts.push(...fenders(o.fender, ln, xs, lod));
|
|
115
|
+
if ((o.stern ?? 'round') === 'transom') {
|
|
116
|
+
const x = xs[0] ?? -half;
|
|
117
|
+
const star = (grid[0] ?? []).map((p) => p);
|
|
118
|
+
if (hb > 0) star.push([x, ln.halfBreadth(x), ln.deck(x) + hb]);
|
|
119
|
+
const port = [...star].reverse().map((p): Vec3 => [p[0], -p[1], p[2]]);
|
|
120
|
+
// Without bulwarks the transom's top follows the deck camber through the deck's band seams.
|
|
121
|
+
const yd = ln.halfBreadth(x);
|
|
122
|
+
const arc: Vec3[] = [];
|
|
123
|
+
const w = deckBand(o, lod);
|
|
124
|
+
for (let y = Math.ceil(o.beam / 2 / w) * w; y > -o.beam / 2; y -= w) {
|
|
125
|
+
if (hb === 0 && Math.abs(y) < yd - 1e-9)
|
|
126
|
+
arc.push([x, y, ln.deck(x) + (o.camber ?? o.beam / 50) * (1 - (y / yd) ** 2)]);
|
|
127
|
+
}
|
|
128
|
+
parts.push(transom(dedupe([...port.slice(0, -1), ...star, ...arc]), c.topsides));
|
|
129
|
+
}
|
|
130
|
+
const at = o.at ?? [0, 0, 0];
|
|
131
|
+
return {
|
|
132
|
+
shell: translate(merge(parts), at),
|
|
133
|
+
deck: translate(deckMesh(o, ln, xs, hb > 0 ? tb : 0, lod), at),
|
|
134
|
+
lines: ln,
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/** Bulwark: outer plate up from the deck edge, cap rail, inner face down to the deck. */
|
|
139
|
+
function bulwarks(
|
|
140
|
+
o: HullOptions,
|
|
141
|
+
ln: HullLines,
|
|
142
|
+
xs: readonly number[],
|
|
143
|
+
hb: number,
|
|
144
|
+
tb: number,
|
|
145
|
+
): Mesh {
|
|
146
|
+
const g: Grid = xs.map((x) => {
|
|
147
|
+
const y = ln.halfBreadth(x);
|
|
148
|
+
const z = ln.deck(x);
|
|
149
|
+
const yi = Math.max(0, y - tb);
|
|
150
|
+
return [
|
|
151
|
+
[x, y, z],
|
|
152
|
+
[x, y, z + hb],
|
|
153
|
+
[x, yi, z + hb],
|
|
154
|
+
[x, yi, z],
|
|
155
|
+
];
|
|
156
|
+
});
|
|
157
|
+
const b = new MeshBuilder();
|
|
158
|
+
const top = o.colors.bulwark ?? o.colors.topsides;
|
|
159
|
+
// Each face its own band so the corners stay crisp.
|
|
160
|
+
for (const [j0, color] of [
|
|
161
|
+
[0, o.colors.topsides],
|
|
162
|
+
[1, top],
|
|
163
|
+
[2, top],
|
|
164
|
+
] as const) {
|
|
165
|
+
const sliced = g.map((row) => row.slice(j0, j0 + 2));
|
|
166
|
+
emitBand(b, sliced, normalsOf(sliced), 0, 1, color, true);
|
|
167
|
+
}
|
|
168
|
+
return b.build();
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/** Rubbing strake / tyre fender along each side just below the sheer. */
|
|
172
|
+
function fenders(
|
|
173
|
+
f: NonNullable<HullOptions['fender']>,
|
|
174
|
+
ln: HullLines,
|
|
175
|
+
xs: readonly number[],
|
|
176
|
+
lod: Lod,
|
|
177
|
+
) {
|
|
178
|
+
const r = f.radius ?? 0.15;
|
|
179
|
+
return [1, -1].map((side) =>
|
|
180
|
+
sweep({
|
|
181
|
+
section: { radius: r, segments: lod === 0 ? 8 : 5 },
|
|
182
|
+
path: xs.map((x): Vec3 => [x, side * (ln.halfBreadth(x) + r * 0.4), ln.deck(x) - r * 1.2]),
|
|
183
|
+
color: f.color,
|
|
184
|
+
caps: true,
|
|
185
|
+
}),
|
|
186
|
+
);
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/** Flat stern plate facing −X (ear-clipped: the bulwark notch makes it non-convex). */
|
|
190
|
+
function transom(points: readonly Vec3[], color: Vec3): Mesh {
|
|
191
|
+
const b = new MeshBuilder();
|
|
192
|
+
const rect = stripRect('plain');
|
|
193
|
+
const ids = points.map((p) =>
|
|
194
|
+
b.vertex({ p, n: [-1, 0, 0], uv: [rect.u0 + p[1] / rect.metres, rect.v0], color }),
|
|
195
|
+
);
|
|
196
|
+
// CCW in (y, z) faces +X, so each triangle is reversed to face aft.
|
|
197
|
+
for (const [i, j, k] of triangulate(points.map((p) => [p[1], p[2]])))
|
|
198
|
+
b.tri(ids[i] ?? 0, ids[k] ?? 0, ids[j] ?? 0);
|
|
199
|
+
return b.build();
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/** Add `name` (shell) and `name_deck` parts; returns the lines for placing deckhouses and fittings. */
|
|
203
|
+
export function hull(ctx: BuildContext, o: HullOptions & { readonly name?: string }): HullLines {
|
|
204
|
+
const name = o.name ?? 'hull';
|
|
205
|
+
const m = hullMesh(o, ctx.lod);
|
|
206
|
+
ctx.part(name, m.shell);
|
|
207
|
+
ctx.part(`${name}_deck`, m.deck);
|
|
208
|
+
return m.lines;
|
|
209
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
// Public API of /kinds: domain builders (buildings, vehicles, vessels, vegetation) recipes compose.
|
|
2
|
+
|
|
3
|
+
export { type FacadeOptions, facade, type SetbackTier, type Side, setbacks } from './building.ts';
|
|
4
|
+
export {
|
|
5
|
+
HEAD_RES,
|
|
6
|
+
type HeadInfo,
|
|
7
|
+
type HeadOptions,
|
|
8
|
+
type HeadOverrides,
|
|
9
|
+
head,
|
|
10
|
+
headEdits,
|
|
11
|
+
headParams,
|
|
12
|
+
} from './head.ts';
|
|
13
|
+
export {
|
|
14
|
+
type BeardStyle,
|
|
15
|
+
type BustStyle,
|
|
16
|
+
checkHead,
|
|
17
|
+
type EarShape,
|
|
18
|
+
type HairStyle,
|
|
19
|
+
type HeadColors,
|
|
20
|
+
type HeadParams,
|
|
21
|
+
} from './head-params.ts';
|
|
22
|
+
// Presets by race name (`head(ctx, { race: 'orc' })`); HEADS.orc etc. for tweaking. The bare
|
|
23
|
+
// preset names (`orc`, `human`) stay internal: too generic for the top-level barrel.
|
|
24
|
+
export { HEADS, type HeadPreset } from './head-presets.ts';
|
|
25
|
+
export {
|
|
26
|
+
type HullColors,
|
|
27
|
+
type HullLines,
|
|
28
|
+
type HullMesh,
|
|
29
|
+
type HullOptions,
|
|
30
|
+
hull,
|
|
31
|
+
hullMesh,
|
|
32
|
+
} from './hull.ts';
|
|
33
|
+
export { hullLines } from './hull-lines.ts';
|
|
34
|
+
export { type MassOptions, mass } from './mass.ts';
|
|
35
|
+
export { type OpeningOptions, type OpeningSide, opening } from './openings.ts';
|
|
36
|
+
export { creature } from './planned.ts';
|
|
37
|
+
export { type RoofInfo, type RoofMeshOptions, roof, roofInfo, roofMesh } from './roof.ts';
|
|
38
|
+
export type { RoofChimney } from './roof-chimney.ts';
|
|
39
|
+
export {
|
|
40
|
+
type RoofOptions,
|
|
41
|
+
type RoofSide,
|
|
42
|
+
type RoofType,
|
|
43
|
+
ridgeHeight,
|
|
44
|
+
roofHeightAt,
|
|
45
|
+
} from './roof-shape.ts';
|
|
46
|
+
export {
|
|
47
|
+
type TreeFamilyParams,
|
|
48
|
+
type TreeInfo,
|
|
49
|
+
type TreeOptions,
|
|
50
|
+
tree,
|
|
51
|
+
treeParams,
|
|
52
|
+
treeReal,
|
|
53
|
+
trees,
|
|
54
|
+
} from './vegetation.ts';
|
|
55
|
+
export type {
|
|
56
|
+
BranchLevel,
|
|
57
|
+
CrownShape,
|
|
58
|
+
LeafParams,
|
|
59
|
+
LeafShape,
|
|
60
|
+
TreeParams,
|
|
61
|
+
} from './vegetation-params.ts';
|
|
62
|
+
export { birch, oak, palm, pine, SPECIES, type SpeciesName, willow } from './vegetation-presets.ts';
|
|
63
|
+
export { axle, propeller, trackRun, whyteAxles } from './vehicle.ts';
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
// A building mass (walls block) whose masonry is laid at TRUE scale: every side is cut into
|
|
2
|
+
// course bands of the strip's `scaleMetres`, all starting from the ground line, so brick courses
|
|
3
|
+
// match across sides and across stacked masses. `box` stretches one strip band over the whole face
|
|
4
|
+
// — fine for trim, wrong for a 6 m brick wall. LOD2 keeps one quad per side (V squeezed).
|
|
5
|
+
|
|
6
|
+
import { type Lod, type Mesh, MeshBuilder, Ts23dError, type Vec3 } from '../core/index.ts';
|
|
7
|
+
import type { StripId } from '../material/index.ts';
|
|
8
|
+
import { emitFace } from './faces.ts';
|
|
9
|
+
|
|
10
|
+
export interface MassOptions {
|
|
11
|
+
/** Width (X), depth (Y), height (Z). */
|
|
12
|
+
readonly size: Vec3;
|
|
13
|
+
/** Centre of the base. */
|
|
14
|
+
readonly at?: Vec3;
|
|
15
|
+
readonly color: Vec3;
|
|
16
|
+
readonly strip?: StripId;
|
|
17
|
+
/** Courses start at this world z (default 0, the ground) so stacked masses line up. */
|
|
18
|
+
readonly courseOrigin?: number;
|
|
19
|
+
/** Skip faces nobody sees (bottom on the ground, top under a roof, a party wall). */
|
|
20
|
+
readonly omit?: readonly ('top' | 'bottom' | 'front' | 'back' | 'left' | 'right')[];
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export function mass(o: MassOptions, lod: Lod = 0): Mesh {
|
|
24
|
+
const [w, d, h] = o.size;
|
|
25
|
+
if (!(w > 0 && d > 0 && h > 0))
|
|
26
|
+
throw new Ts23dError('T3D_RECIPE_INVALID', {
|
|
27
|
+
cause: `mass size is [${o.size.join(', ')}]`,
|
|
28
|
+
fix: 'give width (X), depth (Y) and height (Z) in metres, all > 0',
|
|
29
|
+
});
|
|
30
|
+
const [cx, cy, z0] = o.at ?? [0, 0, 0];
|
|
31
|
+
const [x0, x1, y0, y1, z1] = [cx - w / 2, cx + w / 2, cy - d / 2, cy + d / 2, z0 + h];
|
|
32
|
+
const b = new MeshBuilder();
|
|
33
|
+
const strip = o.strip ?? 'brick';
|
|
34
|
+
const origin: Vec3 = [0, 0, o.courseOrigin ?? 0];
|
|
35
|
+
const sides: [NonNullable<MassOptions['omit']>[number], Vec3, Vec3[]][] = [
|
|
36
|
+
[
|
|
37
|
+
'front',
|
|
38
|
+
[1, 0, 0],
|
|
39
|
+
[
|
|
40
|
+
[x1, y0, z0],
|
|
41
|
+
[x1, y1, z0],
|
|
42
|
+
[x1, y1, z1],
|
|
43
|
+
[x1, y0, z1],
|
|
44
|
+
],
|
|
45
|
+
],
|
|
46
|
+
[
|
|
47
|
+
'back',
|
|
48
|
+
[-1, 0, 0],
|
|
49
|
+
[
|
|
50
|
+
[x0, y1, z0],
|
|
51
|
+
[x0, y0, z0],
|
|
52
|
+
[x0, y0, z1],
|
|
53
|
+
[x0, y1, z1],
|
|
54
|
+
],
|
|
55
|
+
],
|
|
56
|
+
[
|
|
57
|
+
'left',
|
|
58
|
+
[0, 1, 0],
|
|
59
|
+
[
|
|
60
|
+
[x1, y1, z0],
|
|
61
|
+
[x0, y1, z0],
|
|
62
|
+
[x0, y1, z1],
|
|
63
|
+
[x1, y1, z1],
|
|
64
|
+
],
|
|
65
|
+
],
|
|
66
|
+
[
|
|
67
|
+
'right',
|
|
68
|
+
[0, -1, 0],
|
|
69
|
+
[
|
|
70
|
+
[x0, y0, z0],
|
|
71
|
+
[x1, y0, z0],
|
|
72
|
+
[x1, y0, z1],
|
|
73
|
+
[x0, y0, z1],
|
|
74
|
+
],
|
|
75
|
+
],
|
|
76
|
+
];
|
|
77
|
+
for (const [name, normal, points] of sides) {
|
|
78
|
+
if (o.omit?.includes(name)) continue;
|
|
79
|
+
emitFace(b, {
|
|
80
|
+
points,
|
|
81
|
+
normal,
|
|
82
|
+
up: [0, 0, 1],
|
|
83
|
+
vOrigin: origin,
|
|
84
|
+
color: o.color,
|
|
85
|
+
strip,
|
|
86
|
+
banded: lod < 2,
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
for (const [name, z, s] of [
|
|
90
|
+
['top', z1, 1],
|
|
91
|
+
['bottom', z0, -1],
|
|
92
|
+
] as const) {
|
|
93
|
+
if (o.omit?.includes(name)) continue;
|
|
94
|
+
emitFace(b, {
|
|
95
|
+
points: [
|
|
96
|
+
[x0, y0, z],
|
|
97
|
+
[x1, y0, z],
|
|
98
|
+
[x1, y1, z],
|
|
99
|
+
[x0, y1, z],
|
|
100
|
+
],
|
|
101
|
+
normal: [0, 0, s],
|
|
102
|
+
up: [0, 1, 0],
|
|
103
|
+
vOrigin: [cx, y0, z],
|
|
104
|
+
color: o.color,
|
|
105
|
+
strip: 'plain',
|
|
106
|
+
banded: false,
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
return b.build();
|
|
110
|
+
}
|