Builtin Library
- ..
- .metadata92 B
- README.md3.5 KB
- init.luau32.7 KB
- settings.luau747 B
README.md
Model Importer
Claims a mesh-bearing 3D model file in any assimp-supported format
(.fbx, .obj, .dae, .gltf, .glb, .stl, .ply, .3ds,
.blend, .x, and more) and decomposes it into a single
<name>.bundle/ directory. The source file is moved into the bundle
(<name>.bundle/<name>.<ext>) so the link from the derived engine-native
assets back to their origin is never lost, and a settings change can
re-import from it. The keepSource setting decides whether it stays there
once the import is done.
The real source extension flows through to assimp as the format hint, so every supported format parses correctly — the importer is backed by assimp for all 3D formats.
Output layout
<name>.bundle/
<name>.<ext> the original source (moved in; kept while keepSource)
entity_template JSON list of template-entities
mesh/<name>.mesh engine-native mesh bytes
material/<name>.material/mat.yaml one per material something binds
texture/<name>.texture/ one per distinct image: data.ztex, and
source.<ext> in the format the model holds it
animation/<name>.anim AnimAsset-format animation clips
How it fits the importer system
This importer implements only canImport(path, bytes) and
import(ctx). Everything that makes importing correct in a multiplayer,
content-addressed engine lives once in the importer type's shared module
(importer.assetType/shared.module):
- Origin gate — runs on the originating client only; peer-synced
(
remote) writes never re-trigger. - Content gate — re-runs only when the source is new (no
.meta), its checksum changed, or the importer's own settings changed. - Containment skip — once the source lives at
<name>.bundle/<name>.<ext>,asset.containingresolves it to its own bundle and the write is skipped. - Re-entrancy guard — the derived writes (and the source move) don't re-enter dispatch.
ctx.relocateIntoBundle(path) is the shared helper that performs the
move-into-bundle; this importer calls it, then derives mesh/material/
texture/animation assets and the entity_template alongside the moved
source.
Settings
keepSource (default true) keeps the imported model file inside the bundle.
Off, the file is removed once everything the bundle renders from has been
derived from it: the bundle is smaller, and a later settings change has no
original to re-import from. A generation run (the services toolbox) imports
with it off. One import can name it without changing the importer's settings:
asset.import(path, { importerSettings = { model = { keepSource = false } } }).
The importer's own settings.luau also declares textureSettings — the texture
type's settings, embedded rather than restated. Every texture the importer
extracts from a model is created with it as its importer layer, so a world can
import every model's textures crisp, or block-compressed, by setting it once.
A texture the model's own materials bind is created as the type its slot
names — a normal slot as normalMap, a metallic-roughness or occlusion slot as
mask, an albedo / base-colour or emissive slot as color — under whatever
textureSettings names, so its colour space follows what the image is for
rather than what its asset ends up called.
A mesh-free model (animation-only) is ignored here — the
model_animation importer claims it.