Skip to content

@awaken/assets ​

Asset storage, the shared import IR, every model/engine importer, and the persistence formats. It depends on @awaken/core and @awaken/render (for MeshData, Material, and texture types).

This package is the seam between importing (turning a Unity/Godot/Unreal/glTF project into engine data) and shipping (writing that data to a binary project or a self-contained game file).

ts
import { AssetStore, spawnImportedScene, encodeProject, bundleToSceneFile } from "@awaken/assets";

AssetStore ​

The in-memory library of everything a scene references, keyed by string id. It is data-only - the renderer uploads from it, the animation system reads skeletons/clips/skins from it.

MemberTypeDescription
meshesMap<string, MeshData>Geometry by mesh id.
texturesMap<string, TextureData>Device-neutral texture pixels by id.
materialsMap<string, Material>Authored materials by id.
skeletons / clips / skinsMap<string, …>Skeletal-animation assets (skins keyed by the skinned mesh id).
revisionnumberBumped on every add/replace, so a per-frame uploader can skip re-scanning when nothing changed.
addMesh/addTexture/addMaterial/addSkeleton/addClip/addSkin(id, data) => voidRegister an asset.
addSound(id, bytes, mime) => voidRegister an imported sound (encoded bytes, decoded by the audio engine at load). See Audio.
has/hasTexture/hasMaterial, list/listTextures/listMaterials-Membership + key listing.

TextureData stores pixels device-neutral (data is RGBA8, with an optional role), so the renderer can compress for the local GPU at upload - a project ships safely to any device.

Import IR (types) ​

Every importer produces the same ImportedScene intermediate representation, so one consumer (spawnImportedScene) handles all sources. See the Import Overview for the pipeline philosophy.

SymbolShapeDescription
ImportedScene{ meshes: ImportedMesh[]; roots: ImportedNode[]; skeletons?; clips? }The whole imported scene.
ImportedMesh{ id; data: MeshData; color; modelName?; submesh?; skin? }One mesh + its default colour and optional per-vertex skin binding.
ImportedNode{ name; position; rotation; scale; meshId; children; animator? }One node in the imported hierarchy.

spawnImportedScene ​

The single consumer of the IR: register the scene's assets in an AssetStore, then instantiate its node hierarchy into a World as GameObjects with MeshRenderer components.

SymbolSignatureDescription
spawnImportedScene(world, scene, store, opts?) => Entity[]Register meshes/skeletons/clips/skins, spawn the node tree, return the root entities. opts.onAnimator is called for skinned nodes so the caller can attach an Animator (the assets layer can't reference the runtime type).
AnimatedNode{ entity; clip; skeleton }Reported for each skinned node via onAnimator.

Importers ​

Each importer parses a source format into an ImportedScene (or a richer result for whole-project imports). They are all generic - no model-pack-specific hardcoding.

FormatEntry point(s)
glTF / GLBimportGltf(bytes, name), parseGlb, parseGltfJson, importModel(bytes, name) (auto-detects glTF/GLB/OBJ)
OBJparseObj(text, idPrefix)
FBX(the fbx module - parsed via importModel / the editor's import flow)
Unity .unitypackageisUnityPackage(entries), parseUnityScene(…), parseMaterial, prefab helpers
Unreal .uasset / projectdecodeUassetStaticMesh, parseUassetTexturePng, isUnrealProject, importUnrealProject(files, onProgress?)
GodotparseGodotText, parseGodotMeshResource, parseGodotMeshSurfaces, plus the godotImport IR types
Retarget / animmakeRetargeter, buildCharSkeleton, buildIdleClip, remapSkin

Awaken file formats also round-trip here: parseMaterialFile/serializeScriptFile/parseScriptFile/serializePrefabFile/parsePrefabFile. See Import Overview and the per-engine pages (Unity, Godot, Unreal, Models).

Geometry helpers ​

SymbolSignatureDescription
weldMesh(m: MeshData) => MeshDataMerge duplicate vertices (shrinks geometry before shipping).
quantizePositions / dequantizePositions(Float32Array) ⇄ (Uint16Array + PosBbox)Positions → u16 over the mesh AABB, and back.
quantizeNormals / dequantizeNormals(Float32Array) ⇄ Int8ArrayNormals → octahedral int8, and back.
quantizeUvs / dequantizeUvs(Float32Array) ⇄ (Uint16Array + UvBbox)UVs → u16 over the UV bbox, and back.

Quantization cuts per-vertex bytes ~32 → ~12 and is idempotent (a value on the grid re-quantizes to the same index), so re-saving never compounds error. It backs both the binary project and the shipped scene file.

Persistence ​

Two output formats, both defined here. Their exact byte-level shapes and version relationship are in Data Formats & Versions.

The binary project (.awaken) ​

A glTF-.glb-style container: a JSON metadata chunk followed by one binary blob holding every mesh/texture byte and every baked clip's keys.

SymbolSignatureDescription
PROJECT_VERSION15Current project format. v15 stores each RGBA texture as a PNG file in the blob instead of deflated pixels; v14 saves the open world once (sceneRef names the library scene it copies) and stores baked clip keys as exact float64 blob spans instead of JSON; v13 gives font faces a family, weight, style and licence; v12 adds Simulations and Time settings; v11 render textures and render layers; v10 compute shaders; v9 App Settings; v8 UI images; v7 deflated texture pixels; v6 adds each script's uses list (the modules it runs jobs on); v5 added a script's language, folding v4's separate modules map into scripts; v4 added native module assets; v3 persisted the skeletal-animation library and particle-effect metadata; v2 quantized meshes; v1 stored raw f32.
ProjectBundleinterfaceThe in-memory round-trip shape: scene, scenes, entry, open (which library scene the open world is, so a reopened project edits that scene and its look, and the export ships those edits), prefabs, scripts, materials, meshMaterials, materialAssets, render, dock, assetSources, meshes[], textures[].
encodeProject(b: ProjectBundle) => Uint8ArraySerialize a bundle to the AWKN binary (quantizes meshes).
decodeProject(bytes: Uint8Array) => ProjectBundleParse it back (dequantizes to Float32Array, so the in-memory MeshData is identical either way).

The shipped scene (SceneFile JSON) ​

The self-contained JSON the standalone player loads as scene.awaken.json.

SymbolSignatureDescription
SCENE_FILE_VERSION1Current ship-file format.
SceneFileinterface{ version, title?, entry?, scene, meshes: MeshJSON[], prefabs?, scenes?, scripts?, compiled?, materials?, meshMaterials?, shaders?, textures?, render? }, plus everything a shipped game needs to animate and play: skeletons?, clips?, skins?, animGraphs?, particleEffects?, uiClips?, fonts?. volumes? is read-only legacy, kept so games exported before volumes became components still grade.
MeshJSONinterfaceOne mesh's geometry as base64 typed-array bytes, optionally quantized (q) with bbox/uvbb; indices are u16 (idx16) when the mesh has < 65536 verts.
ScriptAsset / ScriptMap{ name, source, kind?, language?, uses?, obfuscation? } / Record<string, ScriptAsset>Scripts keyed by stable id, so renaming is safe. kind "editor" or "plugin" is not shipped; language picks the toolchain (typescript by default, or assemblyscript/c, which compile to wasm and run as jobs); uses lists the modules this script runs jobs on. What a script can do is inferred from what it exports, not from language.
meshToJSON(id, data) => MeshJSONEncode one mesh (quantized) for the ship file.
loadScene(world, assets, types, file) => voidLoad a SceneFile into a world + asset store (dequantizes meshes).
loadSkeletalAssets(assets, file) => voidRegister a ship file's skeletons, clips, skins, anim graphs, particle effects and UI clips into an asset store.
bundleToSceneFile(b: ProjectBundle) => SceneFileThe export seam - convert an editor project bundle into the shippable JSON.
normalizeScripts(raw) => ScriptMapAccept the legacy name → source shape and return the current id-keyed shape.

bundleToSceneFile is a pure function, so it currently ships geometry + vertex/material colour but not albedo textures (encoding base64 PNG needs a browser canvas the editor supplies separately). See Export to a game file.

The ship container ​

An optional single-blob binary wrapper around a SceneFile + its meshes (used by the compressed export path).

SymbolSignatureDescription
encodeSceneContainer(base, meshes) => Uint8ArrayPack a SceneFile (sans meshes) + mesh buffers into one blob.
decodeSceneContainer(bytes) => { file, meshes }Unpack it.
isSceneContainer(bytes) => booleanMagic-number check.
compactSceneForShip(scene, types) => SceneJSONDrop editor-only data to slim the shipped scene.

App Settings ​

The project's app identity and store setup, which both exports read. See App Settings.

SymbolSignatureDescription
AppSettingsinterfacename, shortName, id (bundle id), version, build, orientation, icon and launch designs with their images, developerReadout, androidBackup, saveKey, androidKey and store products.
resolveApp(app, sourceName) => ResolvedAppThe app as the exports write it: what is set, the rest derived from the project's file name.
appProblems(app) => string[]Why these settings cannot be exported, one sentence each; empty when they can.
exportedApp(app) => AppSettings | nullThe settings an export writes, or null when the project has none worth writing.
drawIcon / drawLaunchLogo(app, images, ...) => RgbaRender the icon for a target and size (full, or one adaptive-icon layer), and the launch-screen logo.
encodePng / encodeIco(img, opts?) => Uint8ArrayStandard 8-bit PNG (RGB without alpha for the iOS icon); a multi-size .ico.
StoreProduct / StoreSettingsinterfaceOne product the game sells, and the list (at most STORE_MAX_PRODUCTS = 100). See In-app purchases.
isSaveKey(v) => booleanA well-formed save key: 64 hex characters.

Fonts and audio ​

SymbolSignatureDescription
FontAssetinterfaceOne imported font face: bytes, mime, and family, weight, style, variable range and licence. A face from an older project reads as family = its id, weight 400, normal style.
fontFaceMeta / fontFaceRulefunctionsThe face fields worth writing, and the @font-face rule that registers a face at a URL.
isOggOpus / OGG_OPUS_MIME(bytes) => boolean / "audio/ogg; codecs=opus"Detect an Ogg stream carrying Opus, the recommended format: iOS Safari cannot decode Ogg Vorbis. See Audio.

Terrain, clips and update shaders ​

SymbolSignatureDescription
packTerrain / terrainToJSON / terrainFromJSONfunctionsWrite a terrain asset into the project blob or a shipped scene, and read it back. See @awaken/terrain.
packClips(clips, push) => Record<string, PackedClip>Pack baked clip keys into the project blob as exact float64 spans (project v14).
PNG_TEXTURES_VERSION15The first project version whose RGBA textures are stored as PNG files.
CompiledUpdateShader / packUpdateUniformsinterface / functionAn update graph compiled for a Simulation pass, and the uniform block for one pass (the same packing the renderer uses, so the editor preview and a running Simulation agree).
buildRigProfile(skel, id) => RigProfileMap a skeleton onto canonical humanoid slots by name-anchored endpoints and structural paths, for retargeting.
autoTPose(skel, profile) => Record<string, Quat>Pose a rig into the canonical T in its own space.
bakeRetargetedClip(clipTop, charSkel, charAvatar, name, keys?) => AnimationClipRetarget a humanoid clip from its source FBX onto a character. See Animation.

See also ​

Awaken: browser-native WebGPU game engine.