@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,52 @@
|
|
|
1
|
+
# Sci-fi cargo container, 20 ft (`cargo_container_scifi`)
|
|
2
|
+
|
|
3
|
+
## Identity
|
|
4
|
+
An **original** futuristic skin on the **real** ISO 668 1CC envelope. Because the envelope is
|
|
5
|
+
real, the container stacks, twist-locks and loads like any 20 ft box, while reading as sci-fi
|
|
6
|
+
cargo. Signature features: an off-white chamfered frame; deep-teal armoured bays (six per side)
|
|
7
|
+
instead of corrugation, with vents and bolt rows; an orange accent band; a glowing green status
|
|
8
|
+
strip over the doors; a keypad; lock bars with cams; ISO corner castings at all eight corners.
|
|
9
|
+
|
|
10
|
+
## Specs
|
|
11
|
+
| Dimension | Value (m) | Source |
|
|
12
|
+
|---|---|---|
|
|
13
|
+
| external length | 6.058 | https://en.wikipedia.org/wiki/ISO_668 · https://www.kscranegroup.com/posts/shipping-container-dimensions-types-and-corner-casting-guide/ |
|
|
14
|
+
| external width | 2.438 | same |
|
|
15
|
+
| external height | 2.591 (8 ft 6 in) | same |
|
|
16
|
+
| corner casting L × W × H | 0.178 × 0.162 × 0.118 | https://marine.albertjagger.co.uk/our-products/cargo-control/corner-castings/iso-corner-casting-top-left-fitment |
|
|
17
|
+
| casting centres across | 2.276 (= 2.438 − 0.162) | derived from the two rows above |
|
|
18
|
+
| door opening (ISO, typical) | ≈ 2.34 × 2.28 | modelled 2.12 × 2.28 between the posts |
|
|
19
|
+
|
|
20
|
+
## Shape language
|
|
21
|
+
- **Big:** frame (four posts plus side and end rails) and the thin shell plates inside it. The
|
|
22
|
+
shell is hollow, so the ajar doors show cargo crates inside.
|
|
23
|
+
- **Medium:** six armour bays per side (two raised panels each), seven roof ribs, a service panel
|
|
24
|
+
on the blind end, door leaves with raised panels.
|
|
25
|
+
- **Small (LOD0):** vent slats on every other bay, bolts, lock-bar cams and handles, hazard
|
|
26
|
+
bands, casting apertures, forklift pockets.
|
|
27
|
+
|
|
28
|
+
## Palette (sRGB)
|
|
29
|
+
Shell `#2f5c63` / `#244a50` · frame `#c9c8bf` · castings `#3a3d40` · accent `#d0661e` ·
|
|
30
|
+
hazard `#d9a421` + `#17181a` · status glow `#5dffb0`.
|
|
31
|
+
|
|
32
|
+
## Parts the engine needs
|
|
33
|
+
| Name | What | Motion |
|
|
34
|
+
|---|---|---|
|
|
35
|
+
| `container` | root group (yaw π, so the door end faces +X) | — |
|
|
36
|
+
| `door_l`, `door_r` | leaves, hinge axis just outside the rear posts | rest closed; one-way sway 90° outward (axis ∓Z); real ISO doors swing 270°, so the engine drives the full swing |
|
|
37
|
+
| `keypad` | child of `door_r` | glow |
|
|
38
|
+
| `status_light` | strip over the doors | glow; socket `status_lamp` (point light) |
|
|
39
|
+
| `casting_0…7` | ISO 1161 castings | sockets `twistlock_0…3` on the top four (`attach`, +Z) |
|
|
40
|
+
| `frame`, `body`, `hinge_l/_r`, `cargo` | static, AO-baked | — |
|
|
41
|
+
|
|
42
|
+
## Markings
|
|
43
|
+
ISO 6346-style ID for an invented owner code: `AXSU` / `204118 1` / `22G1` (the check digit 1 is
|
|
44
|
+
computed by the ISO 6346 rule), stencilled on the bay next to the doors on both sides and between
|
|
45
|
+
the lock bars of the right-hand leaf. Built with `text`.
|
|
46
|
+
|
|
47
|
+
## Open questions
|
|
48
|
+
- `clearOf` lists only the hinge pins (a real interlock); the clashes gate sweeps the real 0–90°
|
|
49
|
+
sector and the recipe's `doorArc` check keeps the swing outward.
|
|
50
|
+
- Closed leaves hang 6.6 cm proud of the rear frame face (hinge outside the posts, as on real
|
|
51
|
+
boxes): overall length 6.12 m vs ISO 6.058 m; the `frame` measures hold the ISO numbers.
|
|
52
|
+
- The crates inside are visible only with the doors open.
|
|
@@ -0,0 +1,461 @@
|
|
|
1
|
+
// Sci-fi cargo container — an ORIGINAL futuristic take on the ISO 668 1CC box (20 ft): the real
|
|
2
|
+
// envelope 6.058 × 2.438 × 2.591 m and ISO 1161 corner castings (178 × 162 × 118 mm), so it stacks
|
|
3
|
+
// and twist-locks with every other container in a scene; the skin is hard-surface sci-fi: a
|
|
4
|
+
// chamfered frame, armoured bays with seams and vents instead of corrugation, a glowing status
|
|
5
|
+
// strip and keypad, lock bars, hazard bands. +X = blind end, −X = doors. See README.md.
|
|
6
|
+
//
|
|
7
|
+
// Engine contract: `door_l` / `door_r` rest closed and swing one way, outward, to 90° about
|
|
8
|
+
// their hinge posts (real ISO doors swing 270°; the engine drives the rest); `status_light` +
|
|
9
|
+
// `keypad` glow; light socket `status_lamp`; `twistlock_*` attach sockets at the top castings.
|
|
10
|
+
|
|
11
|
+
import {
|
|
12
|
+
bakeAo,
|
|
13
|
+
box,
|
|
14
|
+
type Check,
|
|
15
|
+
type CheckFinding,
|
|
16
|
+
cylinder,
|
|
17
|
+
defineAsset,
|
|
18
|
+
grime,
|
|
19
|
+
hex,
|
|
20
|
+
type Mesh,
|
|
21
|
+
merge,
|
|
22
|
+
place,
|
|
23
|
+
planar,
|
|
24
|
+
symmetric,
|
|
25
|
+
text,
|
|
26
|
+
type Vec3,
|
|
27
|
+
} from '@developerz.ai/ts23d';
|
|
28
|
+
|
|
29
|
+
// ── palette: deep teal shell, off-white frame, orange accent ────────────────────────────────────
|
|
30
|
+
const SHELL = hex('#2f5c63');
|
|
31
|
+
const SHELL_DARK = hex('#244a50');
|
|
32
|
+
const FRAME = hex('#c9c8bf');
|
|
33
|
+
const CAST = hex('#3a3d40');
|
|
34
|
+
const DARK = hex('#1c1f21');
|
|
35
|
+
const METAL = hex('#6b7075');
|
|
36
|
+
const ACCENT = hex('#d0661e');
|
|
37
|
+
const HAZARD = hex('#d9a421');
|
|
38
|
+
const BLACK = hex('#17181a');
|
|
39
|
+
const GLOW = hex('#5dffb0');
|
|
40
|
+
const STENCIL = hex('#e4e2d8');
|
|
41
|
+
/** ISO 6346-style marking for an invented owner code; check digit computed (AXSU 204118 → 1). */
|
|
42
|
+
const ID_LINES = ['AXSU', '204118 1', '22G1'] as const;
|
|
43
|
+
|
|
44
|
+
// ── ISO 668 / ISO 1161 numbers ─────────────────────────────────────────────────────────────────
|
|
45
|
+
const L = 6.058;
|
|
46
|
+
const W = 2.438;
|
|
47
|
+
const H = 2.591;
|
|
48
|
+
const CL = 0.178; // casting length (X)
|
|
49
|
+
const CW = 0.162; // casting width (Y)
|
|
50
|
+
const CH = 0.118; // casting height (Z)
|
|
51
|
+
const POST = 0.16;
|
|
52
|
+
const HL = L / 2;
|
|
53
|
+
const HW = W / 2;
|
|
54
|
+
const RECESS = 0.07; // side skin sits this far inside the frame face
|
|
55
|
+
const DOOR_X = -HL - 0.036; // hinge axis x: outside the rear posts, leaves close onto the frame face
|
|
56
|
+
const HINGE_Y = HW - POST + 0.005;
|
|
57
|
+
const LEAF = HINGE_Y - 0.004; // leaf width, to the centre line
|
|
58
|
+
const DOOR_Z0 = 0.2; // door leaves fit between the end rails (0.182 … 2.441 m)
|
|
59
|
+
const DOOR_Z1 = 2.425;
|
|
60
|
+
const SWING = 90; // doors rest closed and swing one way, outward, to square with the box
|
|
61
|
+
const DEG = Math.PI / 180;
|
|
62
|
+
|
|
63
|
+
const bevelled = (size: Vec3, color: Vec3, bevel: number, at: Vec3 = [0, 0, 0]): Mesh =>
|
|
64
|
+
box({ size, color, at, bevel: bevel > 0 && bevel < Math.min(...size) / 2 ? bevel : 0 });
|
|
65
|
+
|
|
66
|
+
/** A flat quad lifted `off` along its normal; CCW seen from the side it faces. */
|
|
67
|
+
function quad(a: Vec3, b: Vec3, c: Vec3, d: Vec3, color: Vec3, off = 0.003): Mesh {
|
|
68
|
+
const u: Vec3 = [b[0] - a[0], b[1] - a[1], b[2] - a[2]];
|
|
69
|
+
const v: Vec3 = [d[0] - a[0], d[1] - a[1], d[2] - a[2]];
|
|
70
|
+
const n: Vec3 = [u[1] * v[2] - u[2] * v[1], u[2] * v[0] - u[0] * v[2], u[0] * v[1] - u[1] * v[0]];
|
|
71
|
+
const l = Math.hypot(...n) || 1;
|
|
72
|
+
const lift = (p: Vec3): Vec3 => [
|
|
73
|
+
p[0] + (n[0] / l) * off,
|
|
74
|
+
p[1] + (n[1] / l) * off,
|
|
75
|
+
p[2] + (n[2] / l) * off,
|
|
76
|
+
];
|
|
77
|
+
return planar({ points: [lift(a), lift(b), lift(c), lift(d)], color });
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/** Yellow/black band from a→b, `up` tall; outward normal = (b − a) × up. */
|
|
81
|
+
function hazard(a: Vec3, b: Vec3, up: Vec3, n: number): Mesh {
|
|
82
|
+
const at = (k: number, t: number): Vec3 => [
|
|
83
|
+
a[0] + ((b[0] - a[0]) * k) / n + up[0] * t,
|
|
84
|
+
a[1] + ((b[1] - a[1]) * k) / n + up[1] * t,
|
|
85
|
+
a[2] + ((b[2] - a[2]) * k) / n + up[2] * t,
|
|
86
|
+
];
|
|
87
|
+
return merge(
|
|
88
|
+
Array.from({ length: n }, (_, k) =>
|
|
89
|
+
quad(at(k, 0), at(k + 1, 0), at(k + 1, 1), at(k, 1), k % 2 ? BLACK : HAZARD),
|
|
90
|
+
),
|
|
91
|
+
);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* The doors' arc (closed → SWING) keeps every leaf corner outside the box (x ≤ rear face): a sign
|
|
96
|
+
* error on the swing axis would push them into the cargo. Mirrors the motion in `build`.
|
|
97
|
+
*/
|
|
98
|
+
const doorArc: Check = () => {
|
|
99
|
+
const out: CheckFinding[] = [];
|
|
100
|
+
for (const s of [1, -1])
|
|
101
|
+
for (let a = 0; a <= SWING; a += 5) {
|
|
102
|
+
const t = -s * a * DEG;
|
|
103
|
+
for (const [x, y] of [
|
|
104
|
+
[0.03, -s * LEAF],
|
|
105
|
+
[-0.03, -s * LEAF],
|
|
106
|
+
] as const) {
|
|
107
|
+
const wx = DOOR_X + x * Math.cos(t) - y * Math.sin(t);
|
|
108
|
+
if (wx > -HL + 0.075)
|
|
109
|
+
out.push({
|
|
110
|
+
message: `door ${s > 0 ? 'r' : 'l'} at ${a}° reaches x ${wx.toFixed(3)} inside the box`,
|
|
111
|
+
fix: 'flip the swing axis so leaves open outward (−X)',
|
|
112
|
+
part: s > 0 ? 'door_r' : 'door_l',
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
return out.slice(0, 2);
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
export const cargo_container_scifi = defineAsset({
|
|
120
|
+
name: 'cargo_container_scifi',
|
|
121
|
+
kind: 'prop',
|
|
122
|
+
description:
|
|
123
|
+
'Original sci-fi 20 ft cargo container on the real ISO 668 envelope with ISO 1161 corner castings; hinged doors',
|
|
124
|
+
tags: ['sci-fi', 'prop', 'container', 'cargo', 'hard-surface'],
|
|
125
|
+
license: 'CC0-1.0',
|
|
126
|
+
sources: [
|
|
127
|
+
'https://en.wikipedia.org/wiki/ISO_668',
|
|
128
|
+
'https://www.kscranegroup.com/posts/shipping-container-dimensions-types-and-corner-casting-guide/',
|
|
129
|
+
'https://marine.albertjagger.co.uk/our-products/cargo-control/corner-castings/iso-corner-casting-top-left-fitment',
|
|
130
|
+
'https://hz-containers.com/en/technical-information/corner-castings-technical-documentation/',
|
|
131
|
+
],
|
|
132
|
+
real: {
|
|
133
|
+
length: L,
|
|
134
|
+
width: W,
|
|
135
|
+
height: H,
|
|
136
|
+
measures: [
|
|
137
|
+
{ label: 'body length', axis: 'x', value: L, parts: ['frame'], source: 'ISO 668 1CC' },
|
|
138
|
+
{ label: 'body width', axis: 'y', value: W, parts: ['frame'], source: 'ISO 668 1CC' },
|
|
139
|
+
{ label: 'body height', axis: 'z', value: H, parts: ['frame'], source: 'ISO 668 8 ft 6 in' },
|
|
140
|
+
{
|
|
141
|
+
label: 'corner casting length',
|
|
142
|
+
axis: 'x',
|
|
143
|
+
value: CL,
|
|
144
|
+
parts: ['casting_0'],
|
|
145
|
+
source: 'ISO 1161 (178 mm)',
|
|
146
|
+
},
|
|
147
|
+
{
|
|
148
|
+
label: 'corner casting height',
|
|
149
|
+
axis: 'z',
|
|
150
|
+
value: CH,
|
|
151
|
+
parts: ['casting_0'],
|
|
152
|
+
source: 'ISO 1161 (118 mm)',
|
|
153
|
+
},
|
|
154
|
+
{
|
|
155
|
+
label: 'casting centres, width',
|
|
156
|
+
axis: 'y',
|
|
157
|
+
value: W - CW,
|
|
158
|
+
between: ['casting_0', 'casting_1'],
|
|
159
|
+
source: 'ISO 1161 (2259 mm)',
|
|
160
|
+
},
|
|
161
|
+
],
|
|
162
|
+
},
|
|
163
|
+
// Measured 8210 / 4434 / 520; headroom ≤ 19%.
|
|
164
|
+
budget: { triangles: [9800, 5200, 620] },
|
|
165
|
+
checks: [symmetric('door_l', 'door_r', 'y'), doorArc],
|
|
166
|
+
glow: [{ parts: ['status_light', 'keypad'], color: GLOW, strength: 6 }],
|
|
167
|
+
build(ctx) {
|
|
168
|
+
const lod = ctx.lod;
|
|
169
|
+
const bv = ctx.pick([0.012, 0.006, 0]);
|
|
170
|
+
const statics: [string, Mesh][] = [];
|
|
171
|
+
// Built with the doors at −X, then turned half a turn so the door end faces +X (the front
|
|
172
|
+
// the gallery's 3/4 shot looks at). Moving doors are children of this yawed root.
|
|
173
|
+
const root = 'container';
|
|
174
|
+
ctx.group(root, { yaw: Math.PI });
|
|
175
|
+
|
|
176
|
+
// ── frame: posts, side + end rails (big) ──────────────────────────────────────────────────
|
|
177
|
+
const frame: Mesh[] = [];
|
|
178
|
+
for (const sx of [-1, 1])
|
|
179
|
+
for (const sy of [-1, 1])
|
|
180
|
+
frame.push(
|
|
181
|
+
bevelled([POST, POST, H - 2 * CH], FRAME, bv, [
|
|
182
|
+
sx * (HL - POST / 2),
|
|
183
|
+
sy * (HW - POST / 2),
|
|
184
|
+
CH,
|
|
185
|
+
]),
|
|
186
|
+
);
|
|
187
|
+
for (const sy of [-1, 1]) {
|
|
188
|
+
frame.push(bevelled([L - 2 * CL, 0.13, 0.16], FRAME, bv, [0, sy * (HW - 0.065), 0.012]));
|
|
189
|
+
frame.push(bevelled([L - 2 * CL, 0.12, 0.14], FRAME, bv, [0, sy * (HW - 0.06), H - 0.15]));
|
|
190
|
+
}
|
|
191
|
+
for (const sx of [-1, 1]) {
|
|
192
|
+
frame.push(bevelled([0.14, W - 2 * CW, 0.17], FRAME, bv, [sx * (HL - 0.07), 0, 0.012]));
|
|
193
|
+
frame.push(bevelled([0.14, W - 2 * CW, 0.14], FRAME, bv, [sx * (HL - 0.07), 0, H - 0.15]));
|
|
194
|
+
}
|
|
195
|
+
// Forklift pockets in the bottom side rails.
|
|
196
|
+
if (lod < 2)
|
|
197
|
+
for (const sy of [-1, 1])
|
|
198
|
+
for (const x of [-1.03, 1.03])
|
|
199
|
+
frame.push(bevelled([0.36, 0.02, 0.1], DARK, 0, [x, sy * (HW + 0.002), 0.04]));
|
|
200
|
+
statics.push(['frame', merge(frame)]);
|
|
201
|
+
|
|
202
|
+
// ── corner castings (ISO 1161): dark oval apertures on the three outer faces ────────────
|
|
203
|
+
const casting = (sx: number, sy: number, top: boolean): Mesh => {
|
|
204
|
+
const m: Mesh[] = [bevelled([CL, CW, CH], CAST, ctx.pick([0.008, 0.004, 0]))];
|
|
205
|
+
if (lod < 2) {
|
|
206
|
+
const t = 0.006; // aperture plates stand 3 mm proud: orientation-free dark insets
|
|
207
|
+
m.push(bevelled([t, 0.064, 0.05], DARK, 0, [(sx * CL) / 2, 0, CH / 2 - 0.025]));
|
|
208
|
+
m.push(bevelled([0.08, t, 0.05], DARK, 0, [0, (sy * CW) / 2, CH / 2 - 0.025]));
|
|
209
|
+
if (top) m.push(bevelled([0.124, 0.064, 0.003], DARK, 0, [0, 0, CH - 0.0015]));
|
|
210
|
+
}
|
|
211
|
+
return merge(m);
|
|
212
|
+
};
|
|
213
|
+
let ci = 0;
|
|
214
|
+
for (const top of [false, true])
|
|
215
|
+
for (const sx of [1, -1])
|
|
216
|
+
for (const sy of [1, -1]) {
|
|
217
|
+
const at: Vec3 = [sx * (HL - CL / 2), sy * (HW - CW / 2), top ? H - CH : 0];
|
|
218
|
+
statics.push([`casting_${ci}`, place(casting(sx, sy, top), { at })]);
|
|
219
|
+
if (top && lod < 2)
|
|
220
|
+
ctx.socket(`twistlock_${ci - 4}`, {
|
|
221
|
+
parent: root,
|
|
222
|
+
kind: 'attach',
|
|
223
|
+
at: [at[0], at[1], H],
|
|
224
|
+
dir: [0, 0, 1],
|
|
225
|
+
});
|
|
226
|
+
ci++;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
// ── shell: thin plates inside the frame (a hollow the doors open onto) ─────────────────────
|
|
230
|
+
const shell: Mesh[] = [
|
|
231
|
+
bevelled([L - 0.3, W - 0.3, 0.04], DARK, 0, [0, 0, 0.15]),
|
|
232
|
+
bevelled([L - 0.3, W - 0.24, 0.04], SHELL_DARK, 0, [0, 0, H - 0.16]),
|
|
233
|
+
bevelled([0.04, W - 0.3, H - 0.32], SHELL, 0, [HL - RECESS, 0, 0.17]),
|
|
234
|
+
];
|
|
235
|
+
for (const sy of [-1, 1])
|
|
236
|
+
shell.push(bevelled([L - 0.32, 0.04, H - 0.32], SHELL, 0, [0, sy * (HW - RECESS), 0.17]));
|
|
237
|
+
|
|
238
|
+
// ── armoured bays on the long sides (medium), seams + vents + bolts (small) ──────────────
|
|
239
|
+
if (lod < 2) {
|
|
240
|
+
const bays = 6;
|
|
241
|
+
const span = L - 2 * CL;
|
|
242
|
+
const bay = span / bays;
|
|
243
|
+
for (const sy of [-1, 1]) {
|
|
244
|
+
const y = sy * (HW - RECESS + 0.02);
|
|
245
|
+
for (let i = 0; i <= bays; i++)
|
|
246
|
+
shell.push(
|
|
247
|
+
bevelled([0.08, 0.05, H - 0.34], SHELL_DARK, bv, [
|
|
248
|
+
-span / 2 + i * bay,
|
|
249
|
+
sy * (HW - RECESS + 0.045),
|
|
250
|
+
0.17,
|
|
251
|
+
]),
|
|
252
|
+
);
|
|
253
|
+
for (let i = 0; i < bays; i++) {
|
|
254
|
+
const cx = -span / 2 + (i + 0.5) * bay;
|
|
255
|
+
shell.push(bevelled([bay - 0.2, 0.03, 0.95], SHELL, bv, [cx, y + sy * 0.015, 1.3]));
|
|
256
|
+
shell.push(bevelled([bay - 0.2, 0.03, 0.85], SHELL, bv, [cx, y + sy * 0.015, 0.33]));
|
|
257
|
+
if (i === 0)
|
|
258
|
+
// Container ID on the upper panel of the bay next to the doors (faces ±Y).
|
|
259
|
+
shell.push(
|
|
260
|
+
...ID_LINES.map((line, k) =>
|
|
261
|
+
text(line, {
|
|
262
|
+
origin: [cx, y + sy * 0.03, 2.05 - k * 0.15],
|
|
263
|
+
along: [-sy, 0, 0],
|
|
264
|
+
height: k === 0 ? 0.11 : 0.09,
|
|
265
|
+
align: 'centre',
|
|
266
|
+
color: STENCIL,
|
|
267
|
+
}),
|
|
268
|
+
),
|
|
269
|
+
);
|
|
270
|
+
if (lod === 0) {
|
|
271
|
+
if (i % 2 === 1)
|
|
272
|
+
for (let k = 0; k < 6; k++)
|
|
273
|
+
shell.push(
|
|
274
|
+
bevelled([bay - 0.45, 0.02, 0.035], DARK, 0, [cx, y + sy * 0.035, 1.5 + k * 0.1]),
|
|
275
|
+
);
|
|
276
|
+
const bolt = cylinder({
|
|
277
|
+
radius: 0.014,
|
|
278
|
+
length: 0.012,
|
|
279
|
+
segments: 6,
|
|
280
|
+
axis: 'y',
|
|
281
|
+
color: METAL,
|
|
282
|
+
});
|
|
283
|
+
for (const bx of [-1, 1])
|
|
284
|
+
for (const bz of [0.36, 1.14, 1.42, 2.2])
|
|
285
|
+
shell.push(place(bolt, { at: [cx + bx * (bay / 2 - 0.15), y + sy * 0.035, bz] }));
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
// Accent band + hazard band along the bottom of each side.
|
|
289
|
+
if (lod === 0) {
|
|
290
|
+
const ax = sy > 0 ? [HL - CL - 0.1, -HL + CL + 0.1] : [-HL + CL + 0.1, HL - CL - 0.1];
|
|
291
|
+
shell.push(
|
|
292
|
+
quad(
|
|
293
|
+
[ax[0] ?? 0, sy * (HW - RECESS + 0.051), 1.21],
|
|
294
|
+
[ax[1] ?? 0, sy * (HW - RECESS + 0.051), 1.21],
|
|
295
|
+
[ax[1] ?? 0, sy * (HW - RECESS + 0.051), 1.27],
|
|
296
|
+
[ax[0] ?? 0, sy * (HW - RECESS + 0.051), 1.27],
|
|
297
|
+
ACCENT,
|
|
298
|
+
0.002,
|
|
299
|
+
),
|
|
300
|
+
);
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
// Roof ribs and blind-end service panel.
|
|
304
|
+
for (let i = 0; i < 7; i++)
|
|
305
|
+
shell.push(
|
|
306
|
+
bevelled([0.1, W - 0.3, 0.05], SHELL_DARK, bv, [-HL + 0.5 + i * 0.84, 0, H - 0.12]),
|
|
307
|
+
);
|
|
308
|
+
shell.push(bevelled([0.05, 1.4, 1.5], SHELL_DARK, bv, [HL - RECESS + 0.03, 0, 0.5]));
|
|
309
|
+
if (lod === 0)
|
|
310
|
+
shell.push(
|
|
311
|
+
hazard([HL - RECESS + 0.06, -0.7, 1.9], [HL - RECESS + 0.06, 0.7, 1.9], [0, 0, 0.12], 10),
|
|
312
|
+
);
|
|
313
|
+
}
|
|
314
|
+
statics.push(['body', grime(merge(shell), { ground: 0.9, groundStrength: 0.35 })]);
|
|
315
|
+
|
|
316
|
+
// ── status strip over the doors (glow) + light socket ────────────────────────────────────
|
|
317
|
+
ctx.part('status_light', bevelled([0.03, 1.6, 0.05], GLOW, 0, [-HL - 0.012, 0, H - 0.12]), {
|
|
318
|
+
parent: root,
|
|
319
|
+
});
|
|
320
|
+
ctx.socket('status_lamp', {
|
|
321
|
+
parent: root,
|
|
322
|
+
kind: 'light',
|
|
323
|
+
at: [-HL - 0.25, 0, H - 0.1],
|
|
324
|
+
dir: [-1, 0, -0.3],
|
|
325
|
+
data: { light: 'point', color: '#5dffb0', intensity: 6, range: 5 },
|
|
326
|
+
});
|
|
327
|
+
|
|
328
|
+
// ── doors: leaf built closed in hinge space, then yawed to its ajar rest pose ─────────────
|
|
329
|
+
// Local +Y ends up on world −Y after the root's half turn: name by the world side.
|
|
330
|
+
for (const [s, side] of [
|
|
331
|
+
[1, 'r'],
|
|
332
|
+
[-1, 'l'],
|
|
333
|
+
] as const) {
|
|
334
|
+
const leaf: Mesh[] = [
|
|
335
|
+
bevelled([0.06, LEAF, DOOR_Z1 - DOOR_Z0], SHELL, bv, [0, -s * (LEAF / 2), 0]),
|
|
336
|
+
// Hinge knuckles on the leaf edge.
|
|
337
|
+
...[0.25, 1.15, 2.05].map((z) =>
|
|
338
|
+
cylinder({
|
|
339
|
+
radius: 0.035,
|
|
340
|
+
length: 0.14,
|
|
341
|
+
segments: ctx.pick([10, 6, 4]),
|
|
342
|
+
color: METAL,
|
|
343
|
+
at: [0, 0, z],
|
|
344
|
+
}),
|
|
345
|
+
),
|
|
346
|
+
];
|
|
347
|
+
if (lod < 2) {
|
|
348
|
+
// Raised armour panel, two lock bars with cams and handles.
|
|
349
|
+
leaf.push(bevelled([0.03, LEAF - 0.2, 1.0], SHELL_DARK, bv, [-0.04, -s * (LEAF / 2), 1.1]));
|
|
350
|
+
leaf.push(
|
|
351
|
+
bevelled([0.03, LEAF - 0.2, 0.75], SHELL_DARK, bv, [-0.04, -s * (LEAF / 2), 0.2]),
|
|
352
|
+
);
|
|
353
|
+
if (s > 0)
|
|
354
|
+
// The same ID between the lock bars of the right-hand leaf (faces −X).
|
|
355
|
+
leaf.push(
|
|
356
|
+
...ID_LINES.map((line, k) =>
|
|
357
|
+
text(line, {
|
|
358
|
+
origin: [-0.055, -s * 0.55, 1.9 - k * 0.12],
|
|
359
|
+
along: [0, -1, 0],
|
|
360
|
+
height: 0.055,
|
|
361
|
+
align: 'centre',
|
|
362
|
+
color: STENCIL,
|
|
363
|
+
}),
|
|
364
|
+
),
|
|
365
|
+
);
|
|
366
|
+
for (const y of [0.32, 0.78]) {
|
|
367
|
+
leaf.push(
|
|
368
|
+
cylinder({
|
|
369
|
+
radius: 0.024,
|
|
370
|
+
length: DOOR_Z1 - DOOR_Z0 - 0.02,
|
|
371
|
+
segments: ctx.pick([8, 6, 4]),
|
|
372
|
+
color: METAL,
|
|
373
|
+
at: [-0.075, -s * y, (DOOR_Z1 - DOOR_Z0) / 2],
|
|
374
|
+
}),
|
|
375
|
+
);
|
|
376
|
+
if (lod === 0) {
|
|
377
|
+
leaf.push(bevelled([0.05, 0.08, 0.1], METAL, 0.008, [-0.08, -s * y, 0.05]));
|
|
378
|
+
leaf.push(
|
|
379
|
+
bevelled([0.05, 0.08, 0.1], METAL, 0.008, [-0.08, -s * y, DOOR_Z1 - DOOR_Z0 - 0.15]),
|
|
380
|
+
);
|
|
381
|
+
leaf.push(bevelled([0.04, 0.05, 0.3], DARK, 0.008, [-0.11, -s * (y + 0.06), 0.95]));
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
if (lod === 0)
|
|
385
|
+
leaf.push(
|
|
386
|
+
hazard(
|
|
387
|
+
// Run along −Y so (b − a) × up = −X: the leaf's outer face.
|
|
388
|
+
[-0.031, s > 0 ? -0.02 : LEAF - 0.02, 0.02],
|
|
389
|
+
[-0.031, s > 0 ? -LEAF + 0.02 : -0.02, 0.02],
|
|
390
|
+
[0, 0, 0.12],
|
|
391
|
+
8,
|
|
392
|
+
),
|
|
393
|
+
);
|
|
394
|
+
}
|
|
395
|
+
// Rests closed; a one-way swing about −s·Z opens the leaf outward (−X) to 90°.
|
|
396
|
+
ctx.part(`door_${side}`, merge(leaf), {
|
|
397
|
+
parent: root,
|
|
398
|
+
at: [DOOR_X, s * HINGE_Y, DOOR_Z0],
|
|
399
|
+
motion: { kind: 'sway', axis: [0, 0, -s], degrees: SWING, hz: 0.15, oneWay: true },
|
|
400
|
+
clearOf: [`hinge_${side}`], // knuckles turn on the hinge pins: a real interlock
|
|
401
|
+
});
|
|
402
|
+
if (s > 0 && lod < 2)
|
|
403
|
+
ctx.part('keypad', bevelled([0.025, 0.12, 0.16], GLOW, 0, [-0.085, -s * 0.55, 1.05]), {
|
|
404
|
+
parent: `door_${side}`,
|
|
405
|
+
});
|
|
406
|
+
}
|
|
407
|
+
// Hinge pins on the rear posts (static), coaxial with the knuckles.
|
|
408
|
+
// Local +Y ends up on world −Y after the root's half turn: name by the world side.
|
|
409
|
+
for (const [s, side] of [
|
|
410
|
+
[1, 'r'],
|
|
411
|
+
[-1, 'l'],
|
|
412
|
+
] as const) {
|
|
413
|
+
const pins = [0.7, 1.6].map((z) =>
|
|
414
|
+
cylinder({
|
|
415
|
+
radius: 0.03,
|
|
416
|
+
length: 0.6,
|
|
417
|
+
segments: ctx.pick([10, 6, 4]),
|
|
418
|
+
color: METAL,
|
|
419
|
+
at: [DOOR_X, s * HINGE_Y, DOOR_Z0 + z],
|
|
420
|
+
}),
|
|
421
|
+
);
|
|
422
|
+
statics.push([
|
|
423
|
+
`hinge_${side}`,
|
|
424
|
+
merge([
|
|
425
|
+
...pins,
|
|
426
|
+
bevelled([0.08, 0.1, 2.0], FRAME, 0, [
|
|
427
|
+
DOOR_X - 0.0,
|
|
428
|
+
s * (HINGE_Y + 0.05),
|
|
429
|
+
DOOR_Z0 + 0.15,
|
|
430
|
+
]),
|
|
431
|
+
]),
|
|
432
|
+
]);
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
// ── a few crates inside, seen through the ajar doors (LOD0 only) ──────────────────────────
|
|
436
|
+
if (lod === 0) {
|
|
437
|
+
const rng = ctx.rng.fork('cargo');
|
|
438
|
+
const crates: Mesh[] = [];
|
|
439
|
+
for (let i = 0; i < 6; i++) {
|
|
440
|
+
const sz = rng.range(0.6, 1.0);
|
|
441
|
+
crates.push(
|
|
442
|
+
bevelled(
|
|
443
|
+
[sz, sz, sz * 0.8],
|
|
444
|
+
rng.pick([hex('#4b5320'), hex('#555a60'), hex('#7a6a4a')]),
|
|
445
|
+
0.02,
|
|
446
|
+
[-1.9 + (i % 3) * 1.2, (i < 3 ? -1 : 1) * 0.5, 0.19],
|
|
447
|
+
),
|
|
448
|
+
);
|
|
449
|
+
}
|
|
450
|
+
statics.push(['cargo', merge(crates)]);
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
const occ = merge(statics.map(([, m]) => m));
|
|
454
|
+
for (const [name, mesh] of statics)
|
|
455
|
+
ctx.part(
|
|
456
|
+
name,
|
|
457
|
+
lod === 0 ? bakeAo(mesh, { samples: 16, radius: 0.6, strength: 0.5 }, occ) : mesh,
|
|
458
|
+
{ parent: root },
|
|
459
|
+
);
|
|
460
|
+
},
|
|
461
|
+
});
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# VTD-20 "Kite" — VTOL troop dropship (`dropship`)
|
|
2
|
+
|
|
3
|
+
## Identity
|
|
4
|
+
An **original** design, made to show the mid-poly hard-surface sci-fi look (the "military
|
|
5
|
+
near-future" prop style of big modern shooters). It copies no franchise ship, name or logo.
|
|
6
|
+
It is a 20 m troop transport that lands on skid gear and loads through a rear ramp. Two tilting
|
|
7
|
+
ducted-fan nacelles on stub wings give it VTOL and thrust vectoring.
|
|
8
|
+
|
|
9
|
+
Signature features: a chamfered, tumblehomed fuselage with a wrap-around canopy; armoured gear
|
|
10
|
+
sponsons along the lower flanks; a dorsal drive hump; big nacelles with hazard-striped intakes and
|
|
11
|
+
glowing exhausts; an upswept tail boom with a V-tail and twin thrusters; a chin gun turret.
|
|
12
|
+
|
|
13
|
+
## Scale references (real aircraft)
|
|
14
|
+
| Dimension | Real reference | Value (m) | Source |
|
|
15
|
+
|---|---|---|---|
|
|
16
|
+
| fuselage length | V-22 Osprey | 17.47 | https://thedefensepost.com/2026/08/03/v-22-osprey-guide/ |
|
|
17
|
+
| stowed width / rotor Ø | V-22 Osprey | 5.6 / 11.6 | https://www.boeing.com/defense/military-rotorcraft/v-22-osprey |
|
|
18
|
+
| height, nacelles vertical | V-22 Osprey | 6.7 | https://thedefensepost.com/2026/08/03/v-22-osprey-guide/ |
|
|
19
|
+
| fuselage length / width | CH-47F Chinook | 15.88 / 3.78 | https://www.boeing.com/defense/military-rotorcraft/h-47-chinook |
|
|
20
|
+
| cabin L × W × H | CH-47 Chinook | 9.3 × 2.29 × 1.98 | https://www.inetres.com/gp/military/ar/rotor/CH-47.html |
|
|
21
|
+
|
|
22
|
+
## Design spec (what `real` / `measures` hold the model to)
|
|
23
|
+
| Dimension | Value (m) | Why |
|
|
24
|
+
|---|---|---|
|
|
25
|
+
| overall L × W × H | 20.2 × 13.4 × 6.0 | between the V-22 (17.5 m fuselage) and a CH-47 with rotors |
|
|
26
|
+
| fuselage width | 3.70 | CH-47 3.78 m |
|
|
27
|
+
| fuselage depth (belly → roof) | 3.00 | CH-47 1.98 m cabin + floor and roof structure |
|
|
28
|
+
| cabin (inside the walls) | 9.9 × 3.54 × 2.84 | 24 troop seats; 2 m headroom under the lamps |
|
|
29
|
+
| nacelle centres | 11.10 | ducted fans sit inboard of where V-22 rotors sit |
|
|
30
|
+
| nacelle length | 4.20 | |
|
|
31
|
+
| main gear track | 4.10 | under the sponsons |
|
|
32
|
+
| ramp width / length | 2.80 / 3.20 | CH-47 ramp is full cabin width (2.29 m) |
|
|
33
|
+
|
|
34
|
+
## Shape language
|
|
35
|
+
- **Big:** the fuselage loft (10-point chamfered section with 0.26 m tumblehome above the waist),
|
|
36
|
+
the sponsons, the dorsal hump, the nacelles and the tail boom. Weighted normals with a
|
|
37
|
+
25–35° hard angle keep the panels flat and the chamfers crisp.
|
|
38
|
+
- **Medium:** bevelled armour plates with 6 cm seams, the crew door, intakes, vents, wing
|
|
39
|
+
panels, gear struts and pads, ramp side rails.
|
|
40
|
+
- **Small (LOD0 only):** canopy frames, panel seams, bolt rows, intake slats, ramp anti-slip ribs,
|
|
41
|
+
antennae, pitot probes, seeded roof greebles (`ctx.rng.fork('greeble')`), hazard bands.
|
|
42
|
+
- **Readability:** hazard stripes mark everything that moves or blows: intake lips, the ramp lip,
|
|
43
|
+
gear pads, the sponson step, fin tips and the wing-tip pivots.
|
|
44
|
+
|
|
45
|
+
## Palette (sRGB)
|
|
46
|
+
| Role | Hex |
|
|
47
|
+
|---|---|
|
|
48
|
+
| hull / roof | `#636b71` / `#788086` |
|
|
49
|
+
| armour panels | `#4b5258` |
|
|
50
|
+
| belly | `#2c3135` |
|
|
51
|
+
| seams, dark metal | `#1f2326`, `#222528` |
|
|
52
|
+
| accent stripe | `#c8641c` |
|
|
53
|
+
| hazard | `#d9a421` + `#17181a` |
|
|
54
|
+
| glass | `#3f7598` (surface `glass`) |
|
|
55
|
+
| thruster glow | `#6fd2ff` (glow strength 8) |
|
|
56
|
+
|
|
57
|
+
## Parts the engine needs
|
|
58
|
+
| Name | What | Motion |
|
|
59
|
+
|---|---|---|
|
|
60
|
+
| `nacelle_l`, `nacelle_r` | engine pods, pivot at the wing-tip bearing | sway ±30° about Y (thrust vectoring) |
|
|
61
|
+
| `fan_l`, `fan_r` | ducted fans (children of the nacelles) | spin 6 rps about Z |
|
|
62
|
+
| `thruster_l`, `thruster_r`, `thruster_tail_l/_r` | exhaust discs | glow |
|
|
63
|
+
| `ramp` | rear loading ramp, pivot on the hinge line | rests closed (40°); one-way sway 62.5° about −Y down to the ground (−22.5°) |
|
|
64
|
+
| `turret` › `gun` | chin turret, twin guns | turret sway ±50° about Z, gun ±12° about Y |
|
|
65
|
+
| `canopy` | windscreen + side glass | surface `glass` |
|
|
66
|
+
| sockets | `nav_l` red (port = +Y), `nav_r` green, `nav_tail` white strobe, `landing_light` spot, `cabin_light`, `muzzle_gun` mount | KHR_lights_punctual |
|
|
67
|
+
| emitters | `thrust_l/_r` (always), `thrust_tail_l/_r` (moving), `downwash_l/_r` dust (moving), `muzzle` (event) | |
|
|
68
|
+
|
|
69
|
+
Static parts, AO-baked against each other: `fuselage`, `sponson_l/_r`, `dorsal`, `tail_boom`,
|
|
70
|
+
`hull_detail`, `cabin` (deck, wall panels, 24 seats), `wing_l/_r`, `gear_l/_r/_nose`,
|
|
71
|
+
`hinge_ramp`, `turret_ring`. Glowing parts: `navlight_l/_r/_tail`, `cabin_lamp`.
|
|
72
|
+
|
|
73
|
+
## Markings
|
|
74
|
+
Hull number `07` in stencil off-white (`#d6d3c8`) on both sponsons (0.45 m) and both faces of
|
|
75
|
+
both fins (0.5 m); `NO STEP` on the wing walkway panels (LOD0). Built with `text`.
|
|
76
|
+
|
|
77
|
+
## Open questions / known gaps
|
|
78
|
+
- The ramp's closed pose leaves a 15 cm seam under the boom: the clash sweep bins the arc in 5°
|
|
79
|
+
steps, so the boom underside was raised to clear the widened bin. `rampArc` still checks the
|
|
80
|
+
ground, which isn't geometry.
|
|
81
|
+
- `clearOf` only lists real interlocks now: `hinge_ramp` (ramp knuckles on the rod),
|
|
82
|
+
`turret_ring` (turret in its ring), `turret` (gun housing in the ball), `wing_*` (nacelle shaft
|
|
83
|
+
in its bearing).
|
|
84
|
+
- No true-arc check for turret and gun beyond the clashes sector sweep.
|