@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,902 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Ts23dError2,
|
|
3
|
+
merge2,
|
|
4
|
+
encodePng2,
|
|
5
|
+
quatFromAxisAngle2,
|
|
6
|
+
worldTransforms2,
|
|
7
|
+
toWorld2,
|
|
8
|
+
rotateZ2,
|
|
9
|
+
worldMeshes2
|
|
10
|
+
} from "./chunk-hg7pf34j.js";
|
|
11
|
+
import {
|
|
12
|
+
hex2,
|
|
13
|
+
stripCredits2
|
|
14
|
+
} from "./chunk-y63c6zcv.js";
|
|
15
|
+
import {
|
|
16
|
+
optimize2
|
|
17
|
+
} from "./chunk-drna2rny.js";
|
|
18
|
+
|
|
19
|
+
// src/export/bin-writer.ts
|
|
20
|
+
var ARRAY_BUFFER = 34962;
|
|
21
|
+
var ELEMENT_ARRAY_BUFFER = 34963;
|
|
22
|
+
var FLOAT = 5126;
|
|
23
|
+
var UINT32 = 5125;
|
|
24
|
+
var UINT16 = 5123;
|
|
25
|
+
|
|
26
|
+
class BinWriter {
|
|
27
|
+
chunks = [];
|
|
28
|
+
length = 0;
|
|
29
|
+
views = [];
|
|
30
|
+
accessors = [];
|
|
31
|
+
push(bytes, target) {
|
|
32
|
+
const pad = (4 - this.length % 4) % 4;
|
|
33
|
+
if (pad) {
|
|
34
|
+
this.chunks.push(new Uint8Array(pad));
|
|
35
|
+
this.length += pad;
|
|
36
|
+
}
|
|
37
|
+
this.views.push({
|
|
38
|
+
buffer: 0,
|
|
39
|
+
byteOffset: this.length,
|
|
40
|
+
byteLength: bytes.byteLength,
|
|
41
|
+
...target ? { target } : {}
|
|
42
|
+
});
|
|
43
|
+
this.chunks.push(bytes);
|
|
44
|
+
this.length += bytes.byteLength;
|
|
45
|
+
return this.views.length - 1;
|
|
46
|
+
}
|
|
47
|
+
accessor(data, type, target, bounds = false, normalized = false) {
|
|
48
|
+
const view = this.push(new Uint8Array(data.buffer, data.byteOffset, data.byteLength), target);
|
|
49
|
+
const width = { SCALAR: 1, VEC2: 2, VEC3: 3, VEC4: 4 }[type];
|
|
50
|
+
const acc = {
|
|
51
|
+
bufferView: view,
|
|
52
|
+
componentType: data instanceof Uint32Array ? UINT32 : data instanceof Uint16Array ? UINT16 : FLOAT,
|
|
53
|
+
count: data.length / width,
|
|
54
|
+
type,
|
|
55
|
+
...normalized ? { normalized: true } : {}
|
|
56
|
+
};
|
|
57
|
+
if (bounds) {
|
|
58
|
+
const min = Array(width).fill(Infinity);
|
|
59
|
+
const max = Array(width).fill(-Infinity);
|
|
60
|
+
for (let i = 0;i < data.length; i++) {
|
|
61
|
+
const k = i % width;
|
|
62
|
+
const v = data[i] ?? 0;
|
|
63
|
+
if (v < (min[k] ?? 0))
|
|
64
|
+
min[k] = v;
|
|
65
|
+
if (v > (max[k] ?? 0))
|
|
66
|
+
max[k] = v;
|
|
67
|
+
}
|
|
68
|
+
acc["min"] = min;
|
|
69
|
+
acc["max"] = max;
|
|
70
|
+
}
|
|
71
|
+
this.accessors.push(acc);
|
|
72
|
+
return this.accessors.length - 1;
|
|
73
|
+
}
|
|
74
|
+
bytes() {
|
|
75
|
+
const out = new Uint8Array(Math.ceil(this.length / 4) * 4);
|
|
76
|
+
let o = 0;
|
|
77
|
+
for (const c of this.chunks) {
|
|
78
|
+
out.set(c, o);
|
|
79
|
+
o += c.byteLength;
|
|
80
|
+
}
|
|
81
|
+
return out;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// src/export/container.ts
|
|
86
|
+
function packGlb(gltf, body) {
|
|
87
|
+
let json = new TextEncoder().encode(JSON.stringify(gltf));
|
|
88
|
+
const jsonPad = (4 - json.byteLength % 4) % 4;
|
|
89
|
+
if (jsonPad) {
|
|
90
|
+
const padded = new Uint8Array(json.byteLength + jsonPad).fill(32);
|
|
91
|
+
padded.set(json);
|
|
92
|
+
json = padded;
|
|
93
|
+
}
|
|
94
|
+
const total = 12 + 8 + json.byteLength + 8 + body.byteLength;
|
|
95
|
+
const out = new Uint8Array(total);
|
|
96
|
+
const dv = new DataView(out.buffer);
|
|
97
|
+
dv.setUint32(0, 1179937895, true);
|
|
98
|
+
dv.setUint32(4, 2, true);
|
|
99
|
+
dv.setUint32(8, total, true);
|
|
100
|
+
dv.setUint32(12, json.byteLength, true);
|
|
101
|
+
dv.setUint32(16, 1313821514, true);
|
|
102
|
+
out.set(json, 20);
|
|
103
|
+
const binAt = 20 + json.byteLength;
|
|
104
|
+
dv.setUint32(binAt, body.byteLength, true);
|
|
105
|
+
dv.setUint32(binAt + 4, 5130562, true);
|
|
106
|
+
out.set(body, binAt + 8);
|
|
107
|
+
return out;
|
|
108
|
+
}
|
|
109
|
+
function concat(a, b) {
|
|
110
|
+
const out = new Uint8Array(a.byteLength + b.byteLength);
|
|
111
|
+
out.set(a);
|
|
112
|
+
out.set(b, a.byteLength);
|
|
113
|
+
return out;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// src/export/credits.ts
|
|
117
|
+
function creditsOf(asset) {
|
|
118
|
+
const out = new Set;
|
|
119
|
+
for (const p of asset.parts) {
|
|
120
|
+
const uv = p.mesh?.uvs;
|
|
121
|
+
if (!uv)
|
|
122
|
+
continue;
|
|
123
|
+
const v = new Float32Array(uv.length >> 1);
|
|
124
|
+
for (let i = 0;i < v.length; i++)
|
|
125
|
+
v[i] = uv[i * 2 + 1] ?? 0;
|
|
126
|
+
for (const c of stripCredits2(v))
|
|
127
|
+
out.add(c);
|
|
128
|
+
}
|
|
129
|
+
return [...out].sort();
|
|
130
|
+
}
|
|
131
|
+
function withCredits(asset, meta) {
|
|
132
|
+
const credits = creditsOf(asset);
|
|
133
|
+
if (!credits.length)
|
|
134
|
+
return meta;
|
|
135
|
+
return { ...meta, credits: [...meta?.credits ?? [], ...credits] };
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// src/export/lights.ts
|
|
139
|
+
var LIGHTS = "KHR_lights_punctual";
|
|
140
|
+
function between(a, b) {
|
|
141
|
+
const d = a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
|
|
142
|
+
if (d < -0.999999)
|
|
143
|
+
return [1, 0, 0, 0];
|
|
144
|
+
const c = [a[1] * b[2] - a[2] * b[1], a[2] * b[0] - a[0] * b[2], a[0] * b[1] - a[1] * b[0]];
|
|
145
|
+
const w = 1 + d;
|
|
146
|
+
const n = Math.hypot(c[0], c[1], c[2], w);
|
|
147
|
+
return [c[0] / n, c[1] / n, c[2] / n, w / n];
|
|
148
|
+
}
|
|
149
|
+
var num = (v, fallback) => typeof v === "number" && Number.isFinite(v) ? v : fallback;
|
|
150
|
+
function lightOf(part) {
|
|
151
|
+
const s = part.socket;
|
|
152
|
+
if (s?.kind !== "light")
|
|
153
|
+
return null;
|
|
154
|
+
const d = s.data ?? {};
|
|
155
|
+
const type = d["light"] === "point" || d["light"] === "directional" ? d["light"] : "spot";
|
|
156
|
+
const color = typeof d["color"] === "string" ? hex2(d["color"]) : [1, 1, 1];
|
|
157
|
+
const dir = s.dir ?? [1, 0, 0];
|
|
158
|
+
const len = Math.hypot(...dir) || 1;
|
|
159
|
+
const outer = Math.min(89, num(d["cone"], 30)) * Math.PI / 180;
|
|
160
|
+
const inner = Math.min(outer * 0.999, num(d["inner"], 0) * Math.PI / 180);
|
|
161
|
+
const range = num(d["range"], 0);
|
|
162
|
+
return {
|
|
163
|
+
light: {
|
|
164
|
+
name: part.name,
|
|
165
|
+
type,
|
|
166
|
+
color,
|
|
167
|
+
intensity: num(d["intensity"], type === "directional" ? 3 : type === "point" ? 20 : 100),
|
|
168
|
+
...range > 0 && type !== "directional" ? { range } : {},
|
|
169
|
+
...type === "spot" ? { spot: { innerConeAngle: inner, outerConeAngle: outer } } : {}
|
|
170
|
+
},
|
|
171
|
+
rotation: between([0, 0, -1], [dir[0] / len, dir[1] / len, dir[2] / len])
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
// src/export/motion.ts
|
|
176
|
+
var LOOP_SECONDS = 4;
|
|
177
|
+
var cyclesOf = (rate) => Math.max(1, Math.round(Math.abs(rate) * LOOP_SECONDS)) * Math.sign(rate || 1);
|
|
178
|
+
var timeAccessors = new WeakMap;
|
|
179
|
+
function times(bin, keys) {
|
|
180
|
+
const t = new Float32Array(keys + 1).map((_, i) => i / keys * LOOP_SECONDS);
|
|
181
|
+
const byBin = timeAccessors.get(bin) ?? new Map;
|
|
182
|
+
timeAccessors.set(bin, byBin);
|
|
183
|
+
let input = byBin.get(keys);
|
|
184
|
+
if (input === undefined) {
|
|
185
|
+
input = bin.accessor(t, "SCALAR", undefined, true);
|
|
186
|
+
byBin.set(keys, input);
|
|
187
|
+
}
|
|
188
|
+
return { input, t };
|
|
189
|
+
}
|
|
190
|
+
function motionChannel(bin, motion, node, rest) {
|
|
191
|
+
const rate = motion.kind === "spin" ? motion.rps : motion.hz;
|
|
192
|
+
const cycles = cyclesOf(rate);
|
|
193
|
+
const keys = Math.max(24, Math.abs(cycles) * (motion.kind === "spin" ? 12 : 16));
|
|
194
|
+
const { input, t } = times(bin, keys);
|
|
195
|
+
const phase = (time) => time / LOOP_SECONDS * cycles * Math.PI * 2;
|
|
196
|
+
const wave = (time) => motion.kind !== "spin" && motion.oneWay ? (1 - Math.cos(phase(time))) / 2 : Math.sin(phase(time));
|
|
197
|
+
if (motion.kind === "slide") {
|
|
198
|
+
const values = new Float32Array((keys + 1) * 3);
|
|
199
|
+
t.forEach((time, i) => {
|
|
200
|
+
const s = wave(time);
|
|
201
|
+
values.set([0, 1, 2].map((k) => (rest[k] ?? 0) + (motion.offset[k] ?? 0) * s), i * 3);
|
|
202
|
+
});
|
|
203
|
+
return {
|
|
204
|
+
sampler: { input, output: bin.accessor(values, "VEC3"), interpolation: "LINEAR" },
|
|
205
|
+
channel: { target: { node, path: "translation" } }
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
const values = new Float32Array((keys + 1) * 4);
|
|
209
|
+
const peak = motion.kind === "sway" ? motion.degrees * Math.PI / 180 : 0;
|
|
210
|
+
t.forEach((time, i) => {
|
|
211
|
+
const angle = motion.kind === "spin" ? phase(time) : peak * wave(time);
|
|
212
|
+
values.set(quatFromAxisAngle2(motion.axis, angle), i * 4);
|
|
213
|
+
});
|
|
214
|
+
return {
|
|
215
|
+
sampler: { input, output: bin.accessor(values, "VEC4"), interpolation: "LINEAR" },
|
|
216
|
+
channel: { target: { node, path: "rotation" } }
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
// src/export/tangents.ts
|
|
221
|
+
function tangentsOf(m) {
|
|
222
|
+
const n = m.positions.length / 3;
|
|
223
|
+
const tan = new Float32Array(n * 3);
|
|
224
|
+
const bit = new Float32Array(n * 3);
|
|
225
|
+
const P = m.positions;
|
|
226
|
+
const U = m.uvs;
|
|
227
|
+
for (let t = 0;t < m.indices.length; t += 3) {
|
|
228
|
+
const a = m.indices[t] ?? 0;
|
|
229
|
+
const b = m.indices[t + 1] ?? 0;
|
|
230
|
+
const c = m.indices[t + 2] ?? 0;
|
|
231
|
+
const e1x = (P[b * 3] ?? 0) - (P[a * 3] ?? 0);
|
|
232
|
+
const e1y = (P[b * 3 + 1] ?? 0) - (P[a * 3 + 1] ?? 0);
|
|
233
|
+
const e1z = (P[b * 3 + 2] ?? 0) - (P[a * 3 + 2] ?? 0);
|
|
234
|
+
const e2x = (P[c * 3] ?? 0) - (P[a * 3] ?? 0);
|
|
235
|
+
const e2y = (P[c * 3 + 1] ?? 0) - (P[a * 3 + 1] ?? 0);
|
|
236
|
+
const e2z = (P[c * 3 + 2] ?? 0) - (P[a * 3 + 2] ?? 0);
|
|
237
|
+
const du1 = (U[b * 2] ?? 0) - (U[a * 2] ?? 0);
|
|
238
|
+
const dv1 = -((U[b * 2 + 1] ?? 0) - (U[a * 2 + 1] ?? 0));
|
|
239
|
+
const du2 = (U[c * 2] ?? 0) - (U[a * 2] ?? 0);
|
|
240
|
+
const dv2 = -((U[c * 2 + 1] ?? 0) - (U[a * 2 + 1] ?? 0));
|
|
241
|
+
const det = du1 * dv2 - du2 * dv1;
|
|
242
|
+
if (Math.abs(det) < 0.000000000001)
|
|
243
|
+
continue;
|
|
244
|
+
const r = 1 / det;
|
|
245
|
+
const tx = (e1x * dv2 - e2x * dv1) * r;
|
|
246
|
+
const ty = (e1y * dv2 - e2y * dv1) * r;
|
|
247
|
+
const tz = (e1z * dv2 - e2z * dv1) * r;
|
|
248
|
+
const bx = (e2x * du1 - e1x * du2) * r;
|
|
249
|
+
const by = (e2y * du1 - e1y * du2) * r;
|
|
250
|
+
const bz = (e2z * du1 - e1z * du2) * r;
|
|
251
|
+
for (const v of [a, b, c]) {
|
|
252
|
+
tan[v * 3] = (tan[v * 3] ?? 0) + tx;
|
|
253
|
+
tan[v * 3 + 1] = (tan[v * 3 + 1] ?? 0) + ty;
|
|
254
|
+
tan[v * 3 + 2] = (tan[v * 3 + 2] ?? 0) + tz;
|
|
255
|
+
bit[v * 3] = (bit[v * 3] ?? 0) + bx;
|
|
256
|
+
bit[v * 3 + 1] = (bit[v * 3 + 1] ?? 0) + by;
|
|
257
|
+
bit[v * 3 + 2] = (bit[v * 3 + 2] ?? 0) + bz;
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
const out = new Float32Array(n * 4);
|
|
261
|
+
for (let v = 0;v < n; v++) {
|
|
262
|
+
const nx = m.normals[v * 3] ?? 0;
|
|
263
|
+
const ny = m.normals[v * 3 + 1] ?? 0;
|
|
264
|
+
const nz = m.normals[v * 3 + 2] ?? 1;
|
|
265
|
+
let tx = tan[v * 3] ?? 0;
|
|
266
|
+
let ty = tan[v * 3 + 1] ?? 0;
|
|
267
|
+
let tz = tan[v * 3 + 2] ?? 0;
|
|
268
|
+
const d = nx * tx + ny * ty + nz * tz;
|
|
269
|
+
tx -= nx * d;
|
|
270
|
+
ty -= ny * d;
|
|
271
|
+
tz -= nz * d;
|
|
272
|
+
let len = Math.hypot(tx, ty, tz);
|
|
273
|
+
if (len < 0.00000001) {
|
|
274
|
+
[tx, ty, tz] = Math.abs(nx) < 0.9 ? [0, -nz, ny] : [nz, 0, -nx];
|
|
275
|
+
len = Math.hypot(tx, ty, tz) || 1;
|
|
276
|
+
}
|
|
277
|
+
tx /= len;
|
|
278
|
+
ty /= len;
|
|
279
|
+
tz /= len;
|
|
280
|
+
const cx = ny * tz - nz * ty;
|
|
281
|
+
const cy = nz * tx - nx * tz;
|
|
282
|
+
const cz = nx * ty - ny * tx;
|
|
283
|
+
const w = cx * (bit[v * 3] ?? 0) + cy * (bit[v * 3 + 1] ?? 0) + cz * (bit[v * 3 + 2] ?? 0);
|
|
284
|
+
out.set([tx, ty, tz, w < 0 ? -1 : 1], v * 4);
|
|
285
|
+
}
|
|
286
|
+
return out;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
// src/export/primitive.ts
|
|
290
|
+
function writePrimitive(bin, m, material, tangents) {
|
|
291
|
+
const colors = new Uint16Array(m.colors.length / 3 * 4);
|
|
292
|
+
const q = (v) => Math.round(Math.min(1, Math.max(0, v)) * 65535);
|
|
293
|
+
for (let i = 0;i < m.colors.length / 3; i++)
|
|
294
|
+
colors.set([q(m.colors[i * 3] ?? 1), q(m.colors[i * 3 + 1] ?? 1), q(m.colors[i * 3 + 2] ?? 1), 65535], i * 4);
|
|
295
|
+
return {
|
|
296
|
+
attributes: {
|
|
297
|
+
POSITION: bin.accessor(m.positions, "VEC3", ARRAY_BUFFER, true),
|
|
298
|
+
NORMAL: bin.accessor(m.normals, "VEC3", ARRAY_BUFFER),
|
|
299
|
+
TEXCOORD_0: bin.accessor(m.uvs, "VEC2", ARRAY_BUFFER),
|
|
300
|
+
COLOR_0: bin.accessor(colors, "VEC4", ARRAY_BUFFER, false, true),
|
|
301
|
+
...tangents ? { TANGENT: bin.accessor(tangentsOf(m), "VEC4", ARRAY_BUFFER) } : {}
|
|
302
|
+
},
|
|
303
|
+
indices: bin.accessor(m.positions.length / 3 <= 65535 ? Uint16Array.from(m.indices) : m.indices, "SCALAR", ELEMENT_ARRAY_BUFFER),
|
|
304
|
+
material
|
|
305
|
+
};
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
// src/export/hierarchy.ts
|
|
309
|
+
var newDoc = (bin) => ({
|
|
310
|
+
bin,
|
|
311
|
+
nodes: [],
|
|
312
|
+
meshes: [],
|
|
313
|
+
lights: [],
|
|
314
|
+
samplers: [],
|
|
315
|
+
channels: [],
|
|
316
|
+
motionSamplers: new Map,
|
|
317
|
+
lightIndex: new Map
|
|
318
|
+
});
|
|
319
|
+
function attach(doc, parentId, id) {
|
|
320
|
+
const parent = doc.nodes[parentId];
|
|
321
|
+
if (!parent)
|
|
322
|
+
return;
|
|
323
|
+
parent["children"] = [...parent["children"] ?? [], id];
|
|
324
|
+
}
|
|
325
|
+
function lightIndexOf(doc, light) {
|
|
326
|
+
const key = JSON.stringify(light);
|
|
327
|
+
const known = doc.lightIndex.get(key);
|
|
328
|
+
if (known !== undefined)
|
|
329
|
+
return known;
|
|
330
|
+
doc.lights.push(light);
|
|
331
|
+
doc.lightIndex.set(key, doc.lights.length - 1);
|
|
332
|
+
return doc.lights.length - 1;
|
|
333
|
+
}
|
|
334
|
+
function addMotion(doc, part, id) {
|
|
335
|
+
if (!part.motion)
|
|
336
|
+
return;
|
|
337
|
+
const key = JSON.stringify([part.motion, part.at]);
|
|
338
|
+
let sampler = doc.motionSamplers.get(key);
|
|
339
|
+
let channel;
|
|
340
|
+
if (sampler === undefined) {
|
|
341
|
+
const written = motionChannel(doc.bin, part.motion, id, part.at);
|
|
342
|
+
doc.samplers.push(written.sampler);
|
|
343
|
+
sampler = doc.samplers.length - 1;
|
|
344
|
+
doc.motionSamplers.set(key, sampler);
|
|
345
|
+
channel = written.channel;
|
|
346
|
+
} else {
|
|
347
|
+
channel = {
|
|
348
|
+
target: { node: id, path: part.motion.kind === "slide" ? "translation" : "rotation" }
|
|
349
|
+
};
|
|
350
|
+
}
|
|
351
|
+
doc.channels.push({ ...channel, sampler });
|
|
352
|
+
}
|
|
353
|
+
function writeHierarchy(doc, asset, rootName, o) {
|
|
354
|
+
doc.nodes.push({ name: rootName, children: [] });
|
|
355
|
+
const root = doc.nodes.length - 1;
|
|
356
|
+
const index = new Map;
|
|
357
|
+
asset.parts.forEach((part, i) => {
|
|
358
|
+
const node = { name: part.name, translation: [...part.at] };
|
|
359
|
+
if (part.yaw)
|
|
360
|
+
node["rotation"] = [...quatFromAxisAngle2([0, 0, 1], part.yaw)];
|
|
361
|
+
if (part.emitter || part.socket) {
|
|
362
|
+
node["extras"] = {
|
|
363
|
+
ts23d: {
|
|
364
|
+
...part.emitter ? { emitter: part.emitter } : {},
|
|
365
|
+
...part.socket ? { socket: part.socket } : {}
|
|
366
|
+
}
|
|
367
|
+
};
|
|
368
|
+
}
|
|
369
|
+
if (part.mesh && part.mesh.indices.length > 0) {
|
|
370
|
+
doc.meshes.push({
|
|
371
|
+
name: part.name,
|
|
372
|
+
primitives: [writePrimitive(doc.bin, part.mesh, o.materialOf(part, i), o.withSheet)]
|
|
373
|
+
});
|
|
374
|
+
node["mesh"] = doc.meshes.length - 1;
|
|
375
|
+
}
|
|
376
|
+
doc.nodes.push(node);
|
|
377
|
+
const id = doc.nodes.length - 1;
|
|
378
|
+
index.set(part.name, id);
|
|
379
|
+
attach(doc, part.parent === null ? root : index.get(part.parent) ?? root, id);
|
|
380
|
+
const lit = lightOf(part);
|
|
381
|
+
if (lit) {
|
|
382
|
+
doc.nodes.push({
|
|
383
|
+
name: `${part.name}_light`,
|
|
384
|
+
rotation: [...lit.rotation],
|
|
385
|
+
extensions: { [LIGHTS]: { light: lightIndexOf(doc, lit.light) } }
|
|
386
|
+
});
|
|
387
|
+
attach(doc, id, doc.nodes.length - 1);
|
|
388
|
+
}
|
|
389
|
+
if (o.animations)
|
|
390
|
+
addMotion(doc, part, id);
|
|
391
|
+
});
|
|
392
|
+
return root;
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
// src/export/lod-coverage.ts
|
|
396
|
+
var MSFT_LOD2 = "MSFT_lod";
|
|
397
|
+
var SCREEN_COVERAGE2 = "MSFT_screencoverage";
|
|
398
|
+
var tris = (a) => a.parts.reduce((s, p) => s + (p.mesh ? p.mesh.indices.length / 3 : 0), 0);
|
|
399
|
+
function extent(a) {
|
|
400
|
+
if (a.real)
|
|
401
|
+
return Math.max(a.real.length, a.real.width, a.real.height);
|
|
402
|
+
const lo = [Infinity, Infinity, Infinity];
|
|
403
|
+
const hi = [-Infinity, -Infinity, -Infinity];
|
|
404
|
+
for (const mesh of worldMeshes2(a.parts).values()) {
|
|
405
|
+
const p = mesh.positions;
|
|
406
|
+
for (let i = 0;i < p.length; i++) {
|
|
407
|
+
const k = i % 3;
|
|
408
|
+
const v = p[i] ?? 0;
|
|
409
|
+
lo[k] = Math.min(lo[k] ?? 0, v);
|
|
410
|
+
hi[k] = Math.max(hi[k] ?? 0, v);
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
return Math.max(0, ...hi.map((h, k) => h - (lo[k] ?? 0)));
|
|
414
|
+
}
|
|
415
|
+
var clamp = (v, lo, hi) => Math.min(hi, Math.max(lo, v));
|
|
416
|
+
var round = (v) => Math.round(v * 1000) / 1000;
|
|
417
|
+
function defaultCoverage2(lods) {
|
|
418
|
+
const byLod = new Map(lods.map((a) => [a.lod, tris(a)]));
|
|
419
|
+
const top = lods[0];
|
|
420
|
+
const t0 = Math.max(1, top ? tris(top) : 1);
|
|
421
|
+
const ratio = (lod) => (byLod.get(lod) ?? t0) / t0;
|
|
422
|
+
const c1 = round(clamp(Math.sqrt(ratio(1)), 0.1, 0.6));
|
|
423
|
+
const c2 = round(clamp(Math.sqrt(ratio(2)), 0.02, c1 / 2));
|
|
424
|
+
const cull = top && extent(top) >= 10 ? 0.002 : 0.01;
|
|
425
|
+
return [c1, c2, Math.min(cull, round(c2 / 2))];
|
|
426
|
+
}
|
|
427
|
+
function checkCoverage2(c, asset) {
|
|
428
|
+
const [a = -1, b = -1, cull = -1] = c;
|
|
429
|
+
if (c.length !== 3 || !(a < 1 && a > b && b > cull && cull >= 0))
|
|
430
|
+
throw new Ts23dError2("T3D_RECIPE_INVALID", {
|
|
431
|
+
cause: `lodCoverage ${JSON.stringify(c)} on '${asset}' is not strictly descending in [0, 1)`,
|
|
432
|
+
fix: "give [LOD0→LOD1, LOD1→LOD2, cull] screen-height fractions, e.g. [0.5, 0.2, 0.01]; 0 = never cull"
|
|
433
|
+
});
|
|
434
|
+
}
|
|
435
|
+
function coverageFor2(levels, c) {
|
|
436
|
+
return levels.map((_, j) => {
|
|
437
|
+
const next = levels[j + 1];
|
|
438
|
+
return next === undefined ? c[2] : c[next - 1] ?? c[2];
|
|
439
|
+
});
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
// src/export/materials.ts
|
|
443
|
+
var MATERIALS = {
|
|
444
|
+
opaque: {
|
|
445
|
+
name: "ts23d_trim",
|
|
446
|
+
pbrMetallicRoughness: {
|
|
447
|
+
baseColorFactor: [1, 1, 1, 1],
|
|
448
|
+
metallicFactor: 0,
|
|
449
|
+
roughnessFactor: 0.8
|
|
450
|
+
}
|
|
451
|
+
},
|
|
452
|
+
cutout: {
|
|
453
|
+
name: "ts23d_trim_cutout",
|
|
454
|
+
alphaMode: "MASK",
|
|
455
|
+
alphaCutoff: 0.5,
|
|
456
|
+
doubleSided: true,
|
|
457
|
+
pbrMetallicRoughness: {
|
|
458
|
+
baseColorFactor: [1, 1, 1, 1],
|
|
459
|
+
metallicFactor: 0,
|
|
460
|
+
roughnessFactor: 0.9
|
|
461
|
+
}
|
|
462
|
+
},
|
|
463
|
+
glass: {
|
|
464
|
+
name: "ts23d_glass",
|
|
465
|
+
alphaMode: "BLEND",
|
|
466
|
+
pbrMetallicRoughness: {
|
|
467
|
+
baseColorFactor: [1, 1, 1, 0.25],
|
|
468
|
+
metallicFactor: 0,
|
|
469
|
+
roughnessFactor: 0.05
|
|
470
|
+
},
|
|
471
|
+
extensions: {
|
|
472
|
+
KHR_materials_transmission: { transmissionFactor: 1 },
|
|
473
|
+
KHR_materials_volume: { thicknessFactor: 0.01 },
|
|
474
|
+
KHR_materials_ior: { ior: 1.5 }
|
|
475
|
+
}
|
|
476
|
+
},
|
|
477
|
+
translucent: {
|
|
478
|
+
name: "ts23d_translucent",
|
|
479
|
+
alphaMode: "BLEND",
|
|
480
|
+
pbrMetallicRoughness: {
|
|
481
|
+
baseColorFactor: [1, 1, 1, 0.6],
|
|
482
|
+
metallicFactor: 0,
|
|
483
|
+
roughnessFactor: 0.35
|
|
484
|
+
},
|
|
485
|
+
extensions: {
|
|
486
|
+
KHR_materials_transmission: { transmissionFactor: 0.6 },
|
|
487
|
+
KHR_materials_volume: { thicknessFactor: 0.02 },
|
|
488
|
+
KHR_materials_ior: { ior: 1.45 }
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
};
|
|
492
|
+
var ORDER = ["opaque", "cutout", "glass", "translucent"];
|
|
493
|
+
function textured(m, surface) {
|
|
494
|
+
const pbr = m["pbrMetallicRoughness"];
|
|
495
|
+
const own = surface === "opaque" || surface === "cutout";
|
|
496
|
+
return {
|
|
497
|
+
...m,
|
|
498
|
+
pbrMetallicRoughness: {
|
|
499
|
+
...pbr,
|
|
500
|
+
baseColorTexture: { index: 0 },
|
|
501
|
+
metallicRoughnessTexture: { index: 2 },
|
|
502
|
+
...own ? { metallicFactor: 1, roughnessFactor: 1 } : {}
|
|
503
|
+
},
|
|
504
|
+
normalTexture: { index: 1 },
|
|
505
|
+
occlusionTexture: { index: 2 }
|
|
506
|
+
};
|
|
507
|
+
}
|
|
508
|
+
function materialsFor(used, withSheet = false) {
|
|
509
|
+
const present = ORDER.filter((s) => s === "opaque" || used.has(s));
|
|
510
|
+
const index = new Map(present.map((s, i) => [s, i]));
|
|
511
|
+
const ext = new Set;
|
|
512
|
+
for (const s of present)
|
|
513
|
+
for (const e of Object.keys(MATERIALS[s]["extensions"] ?? {}))
|
|
514
|
+
ext.add(e);
|
|
515
|
+
const materials = present.map((s) => withSheet ? textured(MATERIALS[s], s) : MATERIALS[s]);
|
|
516
|
+
return { materials, index, extensionsUsed: [...ext].sort() };
|
|
517
|
+
}
|
|
518
|
+
var EMISSIVE_STRENGTH = "KHR_materials_emissive_strength";
|
|
519
|
+
function glowMaterial(rule, i, withSheet) {
|
|
520
|
+
const base = withSheet ? textured(MATERIALS.opaque, "opaque") : MATERIALS.opaque;
|
|
521
|
+
const strength = rule.strength ?? 4;
|
|
522
|
+
return {
|
|
523
|
+
...base,
|
|
524
|
+
name: `ts23d_glow_${i}`,
|
|
525
|
+
emissiveFactor: [...rule.color ?? [1, 0.85, 0.6]],
|
|
526
|
+
...strength !== 1 ? { extensions: { [EMISSIVE_STRENGTH]: { emissiveStrength: strength } } } : {}
|
|
527
|
+
};
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
// src/export/merge-pivots.ts
|
|
531
|
+
var isPivot = (p) => p.mesh === null || p.motion !== null;
|
|
532
|
+
var glowLayer = new WeakMap;
|
|
533
|
+
var globRe = (pattern) => new RegExp(`^${pattern.replace(/[.+^${}()|[\]\\]/g, "\\$&").replaceAll("*", ".*").replaceAll("?", ".")}$`);
|
|
534
|
+
var SURFACES = ["cutout", "glass", "translucent"];
|
|
535
|
+
function intoPivot(mesh, part, pivot) {
|
|
536
|
+
const positions = new Float32Array(mesh.positions.length);
|
|
537
|
+
const normals = new Float32Array(mesh.normals.length);
|
|
538
|
+
for (let i = 0;i < positions.length; i += 3) {
|
|
539
|
+
const w = toWorld2(part, [
|
|
540
|
+
mesh.positions[i] ?? 0,
|
|
541
|
+
mesh.positions[i + 1] ?? 0,
|
|
542
|
+
mesh.positions[i + 2] ?? 0
|
|
543
|
+
]);
|
|
544
|
+
positions.set(rotateZ2([w[0] - pivot.origin[0], w[1] - pivot.origin[1], w[2] - pivot.origin[2]], -pivot.yaw), i);
|
|
545
|
+
normals.set(rotateZ2(rotateZ2([mesh.normals[i] ?? 0, mesh.normals[i + 1] ?? 0, mesh.normals[i + 2] ?? 0], part.yaw), -pivot.yaw), i);
|
|
546
|
+
}
|
|
547
|
+
return { ...mesh, positions, normals };
|
|
548
|
+
}
|
|
549
|
+
function mergeToPivots2(asset, glow = []) {
|
|
550
|
+
const glowRes = glow.map((globs) => globs.map(globRe));
|
|
551
|
+
const glowOf = (name) => glowRes.findIndex((rs) => rs.some((r) => r.test(name)));
|
|
552
|
+
const byName = new Map(asset.parts.map((p) => [p.name, p]));
|
|
553
|
+
const xf = worldTransforms2(asset.parts);
|
|
554
|
+
const ROOT = "body";
|
|
555
|
+
const identity = { origin: [0, 0, 0], yaw: 0 };
|
|
556
|
+
const pivotOf = (p) => {
|
|
557
|
+
let cur = p.parent ? byName.get(p.parent) : undefined;
|
|
558
|
+
while (cur && !isPivot(cur))
|
|
559
|
+
cur = cur.parent ? byName.get(cur.parent) : undefined;
|
|
560
|
+
return cur?.name ?? ROOT;
|
|
561
|
+
};
|
|
562
|
+
const extra = new Map;
|
|
563
|
+
const bucket = (pivot, surface, mesh, g = -1) => {
|
|
564
|
+
const k = `${pivot}|${g >= 0 ? `glow_${g}` : surface ?? "opaque"}`;
|
|
565
|
+
extra.set(k, [...extra.get(k) ?? [], mesh]);
|
|
566
|
+
};
|
|
567
|
+
for (const p of asset.parts) {
|
|
568
|
+
if (!p.mesh)
|
|
569
|
+
continue;
|
|
570
|
+
const g = glowOf(p.name);
|
|
571
|
+
if (isPivot(p)) {
|
|
572
|
+
bucket(p.name, p.surface, p.mesh, g);
|
|
573
|
+
continue;
|
|
574
|
+
}
|
|
575
|
+
const pivot = pivotOf(p);
|
|
576
|
+
const t = xf.get(p.name) ?? identity;
|
|
577
|
+
const pt = pivot === ROOT ? identity : xf.get(pivot) ?? identity;
|
|
578
|
+
bucket(pivot, p.surface, intoPivot(p.mesh, t, pt), g);
|
|
579
|
+
}
|
|
580
|
+
const parts = [];
|
|
581
|
+
const layers = (pivot, parent) => {
|
|
582
|
+
for (const surface of SURFACES) {
|
|
583
|
+
const meshes = extra.get(`${pivot}|${surface}`);
|
|
584
|
+
if (!meshes)
|
|
585
|
+
continue;
|
|
586
|
+
parts.push({
|
|
587
|
+
name: `${pivot}_${surface}`,
|
|
588
|
+
mesh: merge2(meshes),
|
|
589
|
+
at: [0, 0, 0],
|
|
590
|
+
parent,
|
|
591
|
+
yaw: 0,
|
|
592
|
+
motion: null,
|
|
593
|
+
surface
|
|
594
|
+
});
|
|
595
|
+
}
|
|
596
|
+
glow.forEach((_, g) => {
|
|
597
|
+
const meshes = extra.get(`${pivot}|glow_${g}`);
|
|
598
|
+
if (!meshes)
|
|
599
|
+
return;
|
|
600
|
+
const part = {
|
|
601
|
+
name: `${pivot}_glow_${g}`,
|
|
602
|
+
mesh: merge2(meshes),
|
|
603
|
+
at: [0, 0, 0],
|
|
604
|
+
parent,
|
|
605
|
+
yaw: 0,
|
|
606
|
+
motion: null
|
|
607
|
+
};
|
|
608
|
+
glowLayer.set(part, g);
|
|
609
|
+
parts.push(part);
|
|
610
|
+
});
|
|
611
|
+
};
|
|
612
|
+
const body = extra.get(`${ROOT}|opaque`);
|
|
613
|
+
if (body)
|
|
614
|
+
parts.push({
|
|
615
|
+
name: ROOT,
|
|
616
|
+
mesh: merge2(body),
|
|
617
|
+
at: [0, 0, 0],
|
|
618
|
+
parent: null,
|
|
619
|
+
yaw: 0,
|
|
620
|
+
motion: null
|
|
621
|
+
});
|
|
622
|
+
layers(ROOT, null);
|
|
623
|
+
for (const p of asset.parts) {
|
|
624
|
+
if (!isPivot(p))
|
|
625
|
+
continue;
|
|
626
|
+
const own = extra.get(`${p.name}|opaque`);
|
|
627
|
+
const { surface: _drop, ...rest } = p;
|
|
628
|
+
parts.push({ ...rest, mesh: own ? merge2(own) : null });
|
|
629
|
+
layers(p.name, p.name);
|
|
630
|
+
}
|
|
631
|
+
return { ...asset, parts };
|
|
632
|
+
}
|
|
633
|
+
|
|
634
|
+
// src/export/version.ts
|
|
635
|
+
var VERSION = "0.2.0";
|
|
636
|
+
var GENERATOR = `@developerz.ai/ts23d ${VERSION}`;
|
|
637
|
+
|
|
638
|
+
// src/export/metadata.ts
|
|
639
|
+
var XMP = "KHR_xmp_json_ld";
|
|
640
|
+
var alt = (value) => ({
|
|
641
|
+
"@type": "rdf:Alt",
|
|
642
|
+
"rdf:_1": { "@language": "x-default", "@value": value }
|
|
643
|
+
});
|
|
644
|
+
function metadata(name, meta) {
|
|
645
|
+
const asset = {
|
|
646
|
+
version: "2.0",
|
|
647
|
+
generator: GENERATOR,
|
|
648
|
+
...meta?.copyright ? { copyright: meta.copyright } : {}
|
|
649
|
+
};
|
|
650
|
+
if (!meta)
|
|
651
|
+
return { asset, used: [] };
|
|
652
|
+
const packet = {
|
|
653
|
+
"@context": {
|
|
654
|
+
dc: "http://purl.org/dc/elements/1.1/",
|
|
655
|
+
rdf: "http://www.w3.org/1999/02/22-rdf-syntax-ns#",
|
|
656
|
+
xmp: "http://ns.adobe.com/xap/1.0/",
|
|
657
|
+
xmpRights: "http://ns.adobe.com/xap/1.0/rights/"
|
|
658
|
+
},
|
|
659
|
+
"dc:title": alt(meta.title ?? name),
|
|
660
|
+
...meta.description ? { "dc:description": alt(meta.description) } : {},
|
|
661
|
+
...meta.creators?.length ? { "dc:creator": { "@list": [...meta.creators] } } : {},
|
|
662
|
+
...meta.copyright ? { "dc:rights": alt(meta.copyright) } : {},
|
|
663
|
+
...meta.license ? { "xmpRights:UsageTerms": alt(meta.license) } : {},
|
|
664
|
+
...meta.sources?.length ? { "dc:relation": { "@set": [...meta.sources] } } : {},
|
|
665
|
+
...meta.credits?.length ? { "dc:contributor": { "@set": [...meta.credits] } } : {},
|
|
666
|
+
"xmp:CreatorTool": GENERATOR
|
|
667
|
+
};
|
|
668
|
+
return {
|
|
669
|
+
asset: { ...asset, extensions: { [XMP]: { packet: 0 } } },
|
|
670
|
+
extensions: { [XMP]: { packets: [packet] } },
|
|
671
|
+
used: [XMP]
|
|
672
|
+
};
|
|
673
|
+
}
|
|
674
|
+
|
|
675
|
+
// src/export/optimize-parts.ts
|
|
676
|
+
function summarize2(parts, optimized) {
|
|
677
|
+
const sum = (f) => parts.reduce((s, r) => s + f(r), 0);
|
|
678
|
+
const tb = sum((r) => r.trianglesBefore);
|
|
679
|
+
const ta = sum((r) => r.trianglesAfter);
|
|
680
|
+
const mean = (f, by, w) => by ? sum((r) => f(r) * (w === "b" ? r.trianglesBefore : r.trianglesAfter)) / by : 0;
|
|
681
|
+
return {
|
|
682
|
+
optimized,
|
|
683
|
+
verticesBefore: sum((r) => r.verticesBefore),
|
|
684
|
+
verticesAfter: sum((r) => r.verticesAfter),
|
|
685
|
+
trianglesBefore: tb,
|
|
686
|
+
trianglesAfter: ta,
|
|
687
|
+
degenerate: sum((r) => r.degenerate),
|
|
688
|
+
duplicate: sum((r) => r.duplicate),
|
|
689
|
+
acmrBefore: mean((r) => r.acmrBefore, tb, "b"),
|
|
690
|
+
acmr: mean((r) => r.acmr, ta, "a"),
|
|
691
|
+
atvrBefore: mean((r) => r.atvrBefore, tb, "b"),
|
|
692
|
+
atvr: mean((r) => r.atvr, ta, "a"),
|
|
693
|
+
parts
|
|
694
|
+
};
|
|
695
|
+
}
|
|
696
|
+
function optimizeParts2(asset, o) {
|
|
697
|
+
const reports = [];
|
|
698
|
+
const parts = asset.parts.map((p) => {
|
|
699
|
+
if (!p.mesh || p.mesh.indices.length === 0)
|
|
700
|
+
return p;
|
|
701
|
+
if (o === false) {
|
|
702
|
+
const v = p.mesh.positions.length / 3;
|
|
703
|
+
const t = p.mesh.indices.length / 3;
|
|
704
|
+
reports.push({
|
|
705
|
+
part: p.name,
|
|
706
|
+
verticesBefore: v,
|
|
707
|
+
verticesAfter: v,
|
|
708
|
+
trianglesBefore: t,
|
|
709
|
+
trianglesAfter: t,
|
|
710
|
+
degenerate: 0,
|
|
711
|
+
duplicate: 0,
|
|
712
|
+
acmrBefore: 0,
|
|
713
|
+
acmr: 0,
|
|
714
|
+
atvrBefore: 0,
|
|
715
|
+
atvr: 0
|
|
716
|
+
});
|
|
717
|
+
return p;
|
|
718
|
+
}
|
|
719
|
+
const { mesh, report } = optimize2(p.mesh, o);
|
|
720
|
+
reports.push({ part: p.name, ...report });
|
|
721
|
+
return { ...p, mesh };
|
|
722
|
+
});
|
|
723
|
+
return { asset: { ...asset, parts }, report: summarize2(reports, o !== false) };
|
|
724
|
+
}
|
|
725
|
+
|
|
726
|
+
// src/export/textures.ts
|
|
727
|
+
var SHEET_MAPS2 = ["albedo", "normal", "orm"];
|
|
728
|
+
var sheetFileName2 = (map, prefix = "trim_sheet") => `${prefix}_${map}.png`;
|
|
729
|
+
var LINEAR = 9729;
|
|
730
|
+
var LINEAR_MIPMAP_LINEAR = 9987;
|
|
731
|
+
var REPEAT = 10497;
|
|
732
|
+
var CLAMP_TO_EDGE = 33071;
|
|
733
|
+
var pngCache = new WeakMap;
|
|
734
|
+
function sheetPngs2(sheet) {
|
|
735
|
+
const hit = pngCache.get(sheet);
|
|
736
|
+
if (hit)
|
|
737
|
+
return hit;
|
|
738
|
+
const pngs = {
|
|
739
|
+
albedo: encodePng2(sheet.size, sheet.size, sheet.albedo),
|
|
740
|
+
normal: encodePng2(sheet.size, sheet.size, sheet.normal),
|
|
741
|
+
orm: encodePng2(sheet.size, sheet.size, sheet.orm)
|
|
742
|
+
};
|
|
743
|
+
pngCache.set(sheet, pngs);
|
|
744
|
+
return pngs;
|
|
745
|
+
}
|
|
746
|
+
var isExternal = (s) => ("external" in s);
|
|
747
|
+
function sheetGltf(sheet, views, offset) {
|
|
748
|
+
const textures = SHEET_MAPS2.map((_, i) => ({ sampler: 0, source: i }));
|
|
749
|
+
const samplers = [
|
|
750
|
+
{ magFilter: LINEAR, minFilter: LINEAR_MIPMAP_LINEAR, wrapS: REPEAT, wrapT: CLAMP_TO_EDGE }
|
|
751
|
+
];
|
|
752
|
+
if (isExternal(sheet)) {
|
|
753
|
+
const images = SHEET_MAPS2.map((m) => ({
|
|
754
|
+
name: `trim_sheet_${m}`,
|
|
755
|
+
uri: sheetFileName2(m, sheet.prefix)
|
|
756
|
+
}));
|
|
757
|
+
return { json: { images, textures, samplers }, tail: new Uint8Array };
|
|
758
|
+
}
|
|
759
|
+
const pngs = sheetPngs2(sheet);
|
|
760
|
+
const parts = [];
|
|
761
|
+
const images = [];
|
|
762
|
+
let at = offset;
|
|
763
|
+
for (const m of SHEET_MAPS2) {
|
|
764
|
+
const png = pngs[m];
|
|
765
|
+
views.push({ buffer: 0, byteOffset: at, byteLength: png.byteLength });
|
|
766
|
+
images.push({ name: `trim_sheet_${m}`, bufferView: views.length - 1, mimeType: "image/png" });
|
|
767
|
+
const pad = (4 - png.byteLength % 4) % 4;
|
|
768
|
+
parts.push(png, new Uint8Array(pad));
|
|
769
|
+
at += png.byteLength + pad;
|
|
770
|
+
}
|
|
771
|
+
const tail = new Uint8Array(at - offset);
|
|
772
|
+
let o = 0;
|
|
773
|
+
for (const p of parts) {
|
|
774
|
+
tail.set(p, o);
|
|
775
|
+
o += p.byteLength;
|
|
776
|
+
}
|
|
777
|
+
return { json: { images, textures, samplers }, tail };
|
|
778
|
+
}
|
|
779
|
+
|
|
780
|
+
// src/export/glb.ts
|
|
781
|
+
var Z_UP_TO_Y_UP = [-0.5, -0.5, -0.5, 0.5];
|
|
782
|
+
function restClip(bin, roots) {
|
|
783
|
+
const input = bin.accessor(new Float32Array([0, 1]), "SCALAR", undefined, true);
|
|
784
|
+
const output = bin.accessor(new Float32Array([...Z_UP_TO_Y_UP, ...Z_UP_TO_Y_UP]), "VEC4");
|
|
785
|
+
return {
|
|
786
|
+
name: "rest",
|
|
787
|
+
samplers: [{ input, output, interpolation: "STEP" }],
|
|
788
|
+
channels: roots.map((node) => ({ sampler: 0, target: { node, path: "rotation" } }))
|
|
789
|
+
};
|
|
790
|
+
}
|
|
791
|
+
function toGlb2(input, o = {}) {
|
|
792
|
+
return exportGlb2(input, o).glb;
|
|
793
|
+
}
|
|
794
|
+
function exportGlb2(input, o = {}) {
|
|
795
|
+
const { glb, reports } = exportLodGlb2([input], o);
|
|
796
|
+
return { glb, report: reports[0] ?? summarize2([], false) };
|
|
797
|
+
}
|
|
798
|
+
function toLodGlb2(lods, o = {}) {
|
|
799
|
+
return exportLodGlb2(lods, o).glb;
|
|
800
|
+
}
|
|
801
|
+
function checkGlow(rules) {
|
|
802
|
+
for (const r of rules)
|
|
803
|
+
if ((r.strength ?? 4) < 0 || (r.color ?? [0, 0, 0]).some((c) => c < 0 || c > 1))
|
|
804
|
+
throw new Ts23dError2("T3D_RECIPE_INVALID", {
|
|
805
|
+
cause: `glow rule for ${JSON.stringify(r.parts)} has a colour outside 0..1 or a negative strength`,
|
|
806
|
+
fix: "colour is linear 0..1 (hex() converts sRGB); brightness goes in `strength`"
|
|
807
|
+
});
|
|
808
|
+
}
|
|
809
|
+
function checkLods(lods) {
|
|
810
|
+
const names = new Set(lods.map((l) => l.name));
|
|
811
|
+
const levels = lods.map((l) => l.lod);
|
|
812
|
+
if (lods.length === 0 || names.size !== 1 || levels.some((l, i) => i > 0 && l <= (levels[i - 1] ?? 0)))
|
|
813
|
+
throw new Ts23dError2("T3D_RECIPE_INVALID", {
|
|
814
|
+
cause: `exportLodGlb got LODs [${levels.join(", ")}] of [${[...names].join(", ")}]`,
|
|
815
|
+
fix: "pass compile(asset, { lod }) results of ONE asset, highest detail first: LOD0, LOD1, LOD2"
|
|
816
|
+
});
|
|
817
|
+
}
|
|
818
|
+
function prepare(input, o, glow) {
|
|
819
|
+
const opt = o.optimize === false ? false : o.optimize === true ? {} : o.optimize ?? {};
|
|
820
|
+
const merged = o.keepParts ? input : mergeToPivots2(input, glow.map((g) => g.parts));
|
|
821
|
+
const { asset, report } = optimizeParts2(merged, opt);
|
|
822
|
+
const glowRes = glow.map((g) => g.parts.map(globRe));
|
|
823
|
+
const glowOf = (p, i) => glowLayer.get(merged.parts[i] ?? p) ?? (o.keepParts ? glowRes.findIndex((rs) => rs.some((r) => r.test(p.name))) : -1);
|
|
824
|
+
return { asset, report, glowOf };
|
|
825
|
+
}
|
|
826
|
+
function exportLodGlb2(lods, o = {}) {
|
|
827
|
+
checkLods(lods);
|
|
828
|
+
const top = lods[0];
|
|
829
|
+
const glow = o.glow ?? top.glow ?? [];
|
|
830
|
+
checkGlow(glow);
|
|
831
|
+
const preps = lods.map((l) => prepare(l, o, glow));
|
|
832
|
+
const withSheet = o.sheet !== undefined;
|
|
833
|
+
const mats = materialsFor(new Set(preps.flatMap((p) => p.asset.parts.flatMap((q) => q.surface ? [q.surface] : []))), withSheet);
|
|
834
|
+
const glowAt = mats.materials.length;
|
|
835
|
+
const materials = [...mats.materials, ...glow.map((g, i) => glowMaterial(g, i, withSheet))];
|
|
836
|
+
const doc = newDoc(new BinWriter);
|
|
837
|
+
const roots = preps.map(({ asset, glowOf }, k) => writeHierarchy(doc, asset, k === 0 ? asset.name : `${asset.name}_LOD${asset.lod}`, {
|
|
838
|
+
withSheet,
|
|
839
|
+
animations: o.animations === true,
|
|
840
|
+
materialOf: (part, i) => {
|
|
841
|
+
const g = glowOf(part, i);
|
|
842
|
+
return g >= 0 ? glowAt + g : mats.index.get(part.surface ?? "opaque") ?? 0;
|
|
843
|
+
}
|
|
844
|
+
}));
|
|
845
|
+
for (const r of roots) {
|
|
846
|
+
const node = doc.nodes[r];
|
|
847
|
+
if (node)
|
|
848
|
+
node["rotation"] = Z_UP_TO_Y_UP;
|
|
849
|
+
}
|
|
850
|
+
const coverage = [];
|
|
851
|
+
const rootNode = doc.nodes[0];
|
|
852
|
+
if (roots.length > 1 && rootNode) {
|
|
853
|
+
const c = o.lodCoverage ?? top.lodCoverage ?? defaultCoverage2(lods);
|
|
854
|
+
checkCoverage2(c, top.name);
|
|
855
|
+
coverage.push(...coverageFor2(lods.map((l) => l.lod), c));
|
|
856
|
+
rootNode["extensions"] = { [MSFT_LOD2]: { ids: roots.slice(1) } };
|
|
857
|
+
rootNode["extras"] = { [SCREEN_COVERAGE2]: coverage };
|
|
858
|
+
}
|
|
859
|
+
const { bin, lights, samplers, channels } = doc;
|
|
860
|
+
const animations = channels.length ? [restClip(bin, roots), { name: "run", samplers, channels }] : [];
|
|
861
|
+
const geometry = bin.bytes();
|
|
862
|
+
const tex = o.sheet ? sheetGltf(o.sheet, bin.views, geometry.byteLength) : null;
|
|
863
|
+
const body = tex?.tail.byteLength ? concat(geometry, tex.tail) : geometry;
|
|
864
|
+
const meta = metadata(top.name, withCredits(top, o.meta ?? top.meta));
|
|
865
|
+
const used = [
|
|
866
|
+
...mats.extensionsUsed,
|
|
867
|
+
...glow.some((g) => (g.strength ?? 4) !== 1) ? [EMISSIVE_STRENGTH] : [],
|
|
868
|
+
...lights.length ? [LIGHTS] : [],
|
|
869
|
+
...coverage.length ? [MSFT_LOD2] : [],
|
|
870
|
+
...meta.used
|
|
871
|
+
].sort();
|
|
872
|
+
const extensions = {
|
|
873
|
+
...lights.length ? { [LIGHTS]: { lights } } : {},
|
|
874
|
+
...meta.extensions ?? {}
|
|
875
|
+
};
|
|
876
|
+
const gltf = {
|
|
877
|
+
asset: meta.asset,
|
|
878
|
+
extras: {
|
|
879
|
+
kind: top.kind,
|
|
880
|
+
lod: coverage.length ? lods.map((l) => l.lod) : top.lod,
|
|
881
|
+
units: "metres",
|
|
882
|
+
up: "Z (rotated to glTF Y-up at the root)"
|
|
883
|
+
},
|
|
884
|
+
...used.length ? { extensionsUsed: used } : {},
|
|
885
|
+
...Object.keys(extensions).length ? { extensions } : {},
|
|
886
|
+
scene: 0,
|
|
887
|
+
scenes: [{ name: top.name, nodes: [0] }],
|
|
888
|
+
nodes: doc.nodes,
|
|
889
|
+
meshes: doc.meshes,
|
|
890
|
+
materials,
|
|
891
|
+
...tex ? tex.json : {},
|
|
892
|
+
buffers: [{ byteLength: body.byteLength }],
|
|
893
|
+
bufferViews: bin.views,
|
|
894
|
+
accessors: bin.accessors,
|
|
895
|
+
...animations.length ? { animations } : {}
|
|
896
|
+
};
|
|
897
|
+
return { glb: packGlb(gltf, body), reports: preps.map((p) => p.report), coverage };
|
|
898
|
+
}
|
|
899
|
+
export { MSFT_LOD2, SCREEN_COVERAGE2, defaultCoverage2, checkCoverage2, coverageFor2, mergeToPivots2, summarize2, optimizeParts2, SHEET_MAPS2, sheetFileName2, sheetPngs2, toGlb2, exportGlb2, toLodGlb2, exportLodGlb2 };
|
|
900
|
+
|
|
901
|
+
//# debugId=48DF0BBA03847F0964756E2164756E21
|
|
902
|
+
//# sourceMappingURL=chunk-dbq4qf52.js.map
|