Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

STF - Squirrel Transfer Format

A modular file-format for 3D assets Intended for (not only) game development use-cases.

Please note, STF is work in progress and likely to change.

Install STF support for:

Try to import this example model!

Relevant future implementation targets include: 3dsMax, Unreal Engine, Maya, Bevy, BabylonJs, ...

Concept

STF by itself is merely a shell format. It provides a framework for different modules to parse and serialize resourses.

Resources are stored as Json-objects, identified by a unique ID. Resources can reference binary buffers and each other.

A few modules, including but not limited to stf.prefab, stf.mesh, stf.material or stf.image, are provided by default.

Additional modules can be easily implemented by third parties. Each STF implementation provides an easy and convenient way to hot-load module-plugins.

As the format is focussed on interoperability, the default module for meshes for example stores its data both, triangulated, and the original topology. If it gets imported into a game-engine, the triangulated data will be used, if imported into a modeling tool, the original topology will be imported. This is possible with negligible storage impact.

Learn how STF compares to other 3d file-formats: Comparisons

Anatomy of an STF file

Date: 2025-09-22 17:54:08 • branch: master • commit: 5cf7a55

Installation

Add STF support to:

Date: 2025-09-22 17:54:08 • branch: master • commit: 5cf7a55

Blender Installation

To install the Blender STF extension:

Drag & drop THIS link into an open Blender window!

After the repository has been added, go to PreferencesGet Extensions, search for "stf" and press Install.


Read the User Guide

See the Source Code: Codeberg - GitHub

Date: 2025-09-22 17:54:08 • branch: master • commit: 5cf7a55

Unity Installation

Unity Package Manager

Under WindowPackage Manager+Add package from git URL…​
add the following URL:

https://github.com/emperorofmars/stf_unity.git#upm

VRChat Creator Companion

Add this repository
Then, in the Creator Companion, go to Manage Project and add the STF package.


See the Source Code: Codeberg - GitHub

Date: 2025-09-22 17:54:08 • branch: master • commit: 5cf7a55

Godot Installation

Download the latest release and unpack the addons/stf_godot directory into the addons directory of your Godot project.


See the Source Code: Codeberg - GitHub

Date: 2025-09-22 17:54:08 • branch: master • commit: 5cf7a55

STF Format

Introduction

STF is a binary file format, containing a binary header, a Json definition and a set of binary buffers.

The Json definition contains meta information, arbitrary resources and buffer references. Resources have a type property, and are identified by a unique ID as a string. Based on a resources type, a module gets selected which provides support to import & export it.

The minimum required set of supported modules is specified in Modules.

STF implementations must provide an easy to use plugin system for modules. If in any way possible, modules should be hot-loadable at runtime.

Key Facts

  • The file extension for stf binary files is .stf.
  • The media-type for stf binary files is model/stf+binary.
  • The STF binary header is stored in little endian byte order.
  • The Json definition is encoded as utf8.
  • STF uses the same coordinate system as glTF 2.0. (See glTF-2.0. coordinate-system-and-units)

Binary Format

An STF binary file consists of a binary header, a json-definition, and zero or more binary buffers.

Length (Bytes)Content
4Magic number: STF0
4STF binary format version major
4STF binary format version minor
4Number of buffers, including the Json definiton buffer
8 * {number of buffers}Buffer lengths in bytes
{length of all buffers}Buffers

The Json definition is the first and only required buffer.

Json Definition

The root Json element is an object. It contains 3 properties: stf, resources and buffers.

stf object

The stf object holds meta information.

stf object properties:

KeyRequiredTypeDescription
version_majorYesIntMajor version of STF
version_minorYesIntMinor version of STF
rootYesresource-IDID of the root resource
metaNoMap<String, String>Meta information such as authors, license or documentation link.
generatorNoStringThe name of the STF implementation that created this file.
timestampNoStringTimestamp as a String in the ISO format.
metric_multiplierNoFloatWhich number represents one meter. The default value is 1.0.

The root resource must be a stf.prefab. It represents the assets scene-hierarchy.

stf object example

"stf": {
	"version_major": 0,
	"version_minor": 0,
	"meta": {
		"asset_name": "STF Example 1"
	},
	"metric_multiplier": 1.0,
	"root": "5f1ea7e8-ee26-46c9-91dc-cd002cb9b0a5"
}

resources object

The resources object is a map of resource objects identified by an ID.

The various resource objects describe the files actual content. Any further properties are defined by each resources module.

Resource object general properties:

KeyRequiredTypeDescription
typeYesStringType of the resource.
referenced_resourcesNoListIDs of resources this resource references.
referenced_buffersNoListIDs of buffers this resource references.
nameNoStringDisplay name of the resource.
version_majorNoIntMajor version of this resource. The default value is 0.
version_minorNoIntMajor version of this resource. The default value is 0.
degradedNoBooleanHas this resource lost information at some point, but retained the same ID. The default is False.

If a referenced resource is not contained within the Json keys children, root_nodes, components or instance, it must be additionally stored in the referenced_resources field. This is only required for non-default modules.

A referenced buffer must be additionally stored in the referenced_buffers field. This is only required for non-default modules.

Resource Kinds

Resources can be Data, Node, Instance and Component kinds. Each of these kinds has additional properties.

The information about what kind a resource is, must be known by the resource-type's implementation and is not contained in STF files itself.

Data

Suppport for module plugins of this kind is required.

Data resource properties:

KeyRequiredTypeDescription
fallbackNoResource-IDID of a resource that should be used in case this one's type is not supported in this implementation
componentsNoListComponent resource IDs
Node

For now only stf.node and stf.bone exist. Suppport for module plugins of this kind is not required.

Node resource properties:

KeyRequiredTypeDescription
enabledNobooleanTrue by default
childrenNoListIDs of child-nodes
componentsNoListComponent resource IDs
Instance

They represent an instance of a data resource in the scene hierarchy. These include for example mesh or armature instances. Instances can provide data relevant for the instance of the resource, such as an armatures pose or meshes blendshape value or material assignments. An instance resource can be referenced only once by a Node resource. Suppport for module plugins of this kind is required.

Instance resource properties:

KeyRequiredTypeDescription
enabledNobooleanTrue by default
Component

They Represents additional functionality or information for Data and Node resources. A component resource can be referenced only once by a Data or Node resource. Suppport for module plugins of this kind is required.

Component resource properties:

KeyRequiredTypeDescription
enabledNobooleanTrue by default
overridesNoListReferences Component kind types that should not be processed, if this type is supported

resources object example

"resources": {
	"b5f96f63-d5ce-4210-b4d6-8f43fbf557dd": {
		"type": "stf.material",
		"name": "Body Material",
		"properties": {
			"albedo.texture": {
				"type": "image",
				"values": [
					{
						"image": "f518a35d-d788-4692-a2dd-84d036d259e8"
					}
				]
			}
		}
	},
	"60b9192c-0c82-434b-b1cf-27d8add2c071": {
		"type": "stf.image",
		"name": "Awesome Texture.png",
		"format": "png",
		"buffer": "d07b09a0-3184-4a39-8650-d1fc90c64df2",
		"data_type": "color"
	},
	"3ca7f62c-b2a8-4315-bb1d-e4c6118ead70": {
		"type": "stf.texture",
		"resolution": [2048, 2048],
		"quality": 0.7,
		"texture_type": "color",
		"downscale_priority": 0
	}
}

buffers object

The buffers object is a map of buffer objects identified by an ID. Each buffer object has a type property. Any further properties are defined in the buffer-type's definition.

For now, stf.buffer.included is the only supported buffer type. Support for hot-loading different buffer-types is not required.

stf.buffer.included

This type represents a buffer contained in the same file.

stf.buffer.included properties:

KeyRequiredTypeDescription
indexYesIntIndex of the binary buffer in the file. An index of 0 means the first buffer after the Json definition buffer.

buffers object example

"buffers": {
	"2c04d7f9-96cd-4867-baf3-2a54d4d31a67": {
		"type": "stf.buffer.included",
		"index": 666
	}
}

Minimal Definition Example

Default Cube.stf

{
	"stf": {
		"version_major": 0,
		"version_minor": 0,
		"root": "979c1726-222d-4184-89b1-72f9b2c82d60",
		"asset_info": {
			"asset_name": "Default Cube"
		},
		"generator": "stf_blender",
		"generator_version": "0.0.7",
		"timestamp": "2025-08-04T16:43:03.324405+00:00",
		"metric_multiplier": 1
	},
	"resources": {
		"5ced8683-2dff-49de-aefe-3f02c4856e86": {
			"type": "stf.material",
			"name": "Material",
			"properties": {
				"albedo.color": {
					"type": "color",
					"values": [
						[
							0.800000011920929,
							0.800000011920929,
							0.800000011920929,
							1.0
						]
					]
				},
				"roughness.value": {
					"type": "float",
					"values": [
						0.5
					]
				},
				"metallic.value": {
					"type": "float",
					"values": [
						0.0
					]
				}
			},
			"style_hints": [
				"realistic",
				"pbr"
			],
			"shader_targets": {
				"stfblender": [
					"ShaderNodeBsdfPrincipled"
				]
			}
		},
		"89abf95c-575c-4033-adbc-fffe3f59cdb9": {
			"type": "stf.mesh",
			"name": "Cube",
			"material_slots": [
				"5ced8683-2dff-49de-aefe-3f02c4856e86"
			],
			"float_width": 4,
			"indices_width": 1,
			"vertices": "c69104d6-55a9-4460-a8fc-e2f3a70da3eb",
			"face_corners": "214dd09d-b2eb-4b1f-83bb-c1650222a897",
			"splits": "a7ca9d09-169f-4f65-8af5-265a3e1c1128",
			"split_normals": "497cd907-6bbf-4017-bbf4-bdb57f34a6b4",
			"uvs": [
				{
					"name": "UVMap",
					"uv": "f88f80c6-4b95-4103-88d6-056af49e454b"
				}
			],
			"tris": "f705415c-93c5-48d1-8c12-fa6fc6a976b1",
			"material_indices_width": 1,
			"faces": "42b4c79a-12b9-4fc9-97b0-518bcdef6043",
			"material_indices": "e443faf5-38d0-485a-8f5f-30735c49bf2c",
			"sharp_face_indices": "9c25f6ef-f33b-4aa7-9860-da7427d01bdb",
			"lines": "3d232b23-6deb-41ad-b09e-5805869fff1c",
			"sharp_edges": "cc4206c5-2ff7-4d28-9e90-f4d3c6a8130a",
			"components": [
				"4ab71531-2a97-4d63-b574-3ab760290f4a"
			]
		},
		"4ab71531-2a97-4d63-b574-3ab760290f4a": {
			"type": "stfexp.mesh.seams",
			"indices_width": 1,
			"referenced_buffers": [
				"29e557ab-6f20-4302-9396-a2287cda0b6e"
			],
			"seams": "29e557ab-6f20-4302-9396-a2287cda0b6e"
		},
		"9742257e-e1b3-424f-882f-33c44c746d98": {
			"type": "stf.instance.mesh",
			"name": "",
			"mesh": "89abf95c-575c-4033-adbc-fffe3f59cdb9"
		},
		"25f8b224-46a3-404c-a15a-8594f2c9e8fc": {
			"type": "stf.node",
			"name": "Cube",
			"children": [],
			"trs": [
				[
					0.0,
					0.0,
					-0.0
				],
				[
					0.0,
					0.0,
					-0.0,
					1.0
				],
				[
					1.0,
					1.0,
					1.0
				]
			],
			"instance": "9742257e-e1b3-424f-882f-33c44c746d98"
		},
		"53650c64-eb81-4873-a4f0-4e274c02597f": {
			"type": "stf.node",
			"name": "Light",
			"children": [],
			"trs": [
				[
					4.076245307922363,
					5.903861999511719,
					-1.0054539442062378
				],
				[
					0.16907574236392975,
					0.7558803558349609,
					-0.27217137813568115,
					0.570947527885437
				],
				[
					1.0,
					1.0,
					0.9999999403953552
				]
			]
		},
		"57d85e39-1994-4604-b4fc-4acd76a5f635": {
			"type": "stf.node",
			"name": "Camera",
			"children": [],
			"trs": [
				[
					7.358891487121582,
					4.958309173583984,
					6.925790786743164
				],
				[
					0.483536034822464,
					0.33687159419059753,
					-0.20870360732078552,
					0.7804827094078064
				],
				[
					1.0,
					1.0,
					1.0
				]
			]
		},
		"979c1726-222d-4184-89b1-72f9b2c82d60": {
			"type": "stf.prefab",
			"name": "Collection",
			"root_nodes": [
				"25f8b224-46a3-404c-a15a-8594f2c9e8fc",
				"53650c64-eb81-4873-a4f0-4e274c02597f",
				"57d85e39-1994-4604-b4fc-4acd76a5f635"
			],
			"animations": []
		}
	},
	"buffers": {
		"c69104d6-55a9-4460-a8fc-e2f3a70da3eb": {
			"type": "stf.buffer.included",
			"index": 0
		},
		"214dd09d-b2eb-4b1f-83bb-c1650222a897": {
			"type": "stf.buffer.included",
			"index": 1
		},
		"a7ca9d09-169f-4f65-8af5-265a3e1c1128": {
			"type": "stf.buffer.included",
			"index": 2
		},
		"497cd907-6bbf-4017-bbf4-bdb57f34a6b4": {
			"type": "stf.buffer.included",
			"index": 3
		},
		"f88f80c6-4b95-4103-88d6-056af49e454b": {
			"type": "stf.buffer.included",
			"index": 4
		},
		"f705415c-93c5-48d1-8c12-fa6fc6a976b1": {
			"type": "stf.buffer.included",
			"index": 5
		},
		"42b4c79a-12b9-4fc9-97b0-518bcdef6043": {
			"type": "stf.buffer.included",
			"index": 6
		},
		"e443faf5-38d0-485a-8f5f-30735c49bf2c": {
			"type": "stf.buffer.included",
			"index": 7
		},
		"9c25f6ef-f33b-4aa7-9860-da7427d01bdb": {
			"type": "stf.buffer.included",
			"index": 8
		},
		"3d232b23-6deb-41ad-b09e-5805869fff1c": {
			"type": "stf.buffer.included",
			"index": 9
		},
		"cc4206c5-2ff7-4d28-9e90-f4d3c6a8130a": {
			"type": "stf.buffer.included",
			"index": 10
		},
		"29e557ab-6f20-4302-9396-a2287cda0b6e": {
			"type": "stf.buffer.included",
			"index": 11
		}
	}
}
Date: 2025-09-22 17:54:08 • branch: master • commit: 5cf7a55

Comparison to other Formats

FBX

FBX is the industry standard. Unfortunately it is not extensible, undocumented, and its official implementation is proprietary.

Many open-source projects, like Blender and Godot, rely on unofficial reverse engineered implementations, with varying success.

glTF 2.0

Similar to glTF 2.0, an STF file consists of a Json definition and binary data. Contrary to glTF, STF is made for interchange of 3d assets, not runtime loading or asset-streaming.

GLTF is made to be delivered to the end-user and loaded directly into video-memory. STF is made to be delivered to a games-developer or artist.

Game-engines are responsible for runtime optimization (at asset-import and/or build time), not the 3d file format or 3d modeling tool.

USD

The official OpenUSD FAQ does a better job at explaining this, than the author of this documentation ever could.

USD can instantiate assets from other regular 3D file-formats, similar to how game-engine scenes can instantiate assets from imported 3d models.

USD does not replace regular 3d file-formats and vice versa. STF is a "regular 3d file-formats" in this sense.

Date: 2025-09-22 17:54:08 • branch: master • commit: 5cf7a55

STF Modules

Date: 2025-09-22 17:54:08 • branch: master • commit: 5cf7a55

Core Modules (stf.*)

Modules which every STF implementation must support are in the main namespace stf.*.

Date: 2025-09-22 17:54:08 • branch: master • commit: 5cf7a55

stf.prefab

A prefab represents a hierarchy of nodes.

Properties

KeyRequiredTypeDescription
root_nodesYesListIDs of the root nodes within this prefab
animationsNoListAnimations which originate from this prefab's root

The only allowed type for nodes in root_nodes is stf.node.

Implementations

Json Example

"f23cdae6-3b52-4212-b180-dfdb0fcfcaba": {
	"type": "stf.prefab",
	"name": "Warrior of the Squeak",
	"root_nodes": [
		"bf97e4a7-2aa8-4d90-9a4b-b7fa6223d8e7",
		"899799a1-17a6-439f-a6fb-1017d07f5a04"
	],
	"animations": [
		"b3879585-9587-4362-b6c5-58130e4c03ef",
		"d7d5365a-9d0a-4fab-bbe6-193fb1f23b9e",
		"3e8fb358-4501-41a6-a9f7-57ee47e1ffdb",
		"aeecdee5-eb5c-4923-8b28-f89e3f6769a4",
		"a63aa1f8-b819-4af3-99b4-c62aa5faae71",
		"4c2cc28b-937f-4e27-bc19-7f8dfe2c56d8",
		"4b63a246-e0eb-41c7-a999-ceb237f5f159",
		"798af1e9-7bee-4c46-99b8-4d1510ab46de",
		"c472603c-9bc7-4420-8766-7638df8621a3",
		"4b393856-2189-4e9d-a282-a8810342d8fe",
		"11826e52-f1f8-478d-b4dd-94e91d4a225f",
		"947d80c1-7f75-453f-a32d-00e6f0fb075c"
	],
	"components": [
		"19615892-fdcf-4f23-b47e-b59504b38561",
		"346ebced-a516-426c-879f-dd6a6607fc55",
		"8cd515fa-c589-49e1-a211-dbfd368d6a97"
	]
}
Date: 2025-09-22 17:54:08 • branch: master • commit: 5cf7a55

stf.node

A node that exists in 3d space. It defines its location, rotation and scale relative to its parent.

Properties

KeyRequiredTypeDescription
trsYesTRSThe nodes 3D transform
instanceNoResource-IDReference to an instance-resource.
parent_bindingNoPathPath to the parent resource. Usually, when the parent node is an armature-instance, its the path to a bone within the instantiated armature.

Only other stf.node type resources are allowed as its children. Children may never loop.

Implementations

Json Example

"880c2403-471d-46e4-99ac-0b218f201337": {
	"type": "stf.node",
	"name": "ArmatureHair",
	"enabled": true,
	"children": [
		"0912ff56-e534-4c8e-a99e-d3ef2a9ea8ba"
	],
	"trs": [
		[
			-6.138677122180525e-09,
			1.584037184715271,
			-0.029444340616464615
		],
		[
			-3.725290298461914e-09,
			-4.618527782440651e-14,
			1.7659484985443896e-15,
			1.0
		],
		[
			1.0,
			1.0,
			1.0
		]
	],
	"instance": "73d67945-2937-41c8-b683-7a992cbca5c5",
	"components": [
		"3051ea80-cc8a-4b6a-afce-dd75e1868fa5"
	],
	"parent_binding": [
		"9fac8ebe-54ee-4c97-a193-235fcc5ebe7f",
		"instance",
		"9a6e0ab7-29e4-48b1-ba25-5e0cd86988e7"
	]
}
Date: 2025-09-22 17:54:08 • branch: master • commit: 5cf7a55

stf.armature

A armature represents a hierarchy of bones.

Properties

KeyRequiredTypeDescription
root_bonesYesListIDs of nodes

The only allowed type for nodes in root_bones is stf.bone.

Armatures can be instantiated by stf.instance.armature.

Implementations

Json Example

"90b9fbb6-3e2d-44e5-8821-454c97c8d15a": {
	"type": "stf.armature",
	"name": "Armature",
	"root_bones": [
		"ed9fac3c-1500-436e-9c4e-fd88822be434"
	],
	"components": [
		"1e7c6be0-e53c-4af5-8e2d-c1bdc7c687c5",
		"1b453833-a3c8-4ac8-9d26-7a9e84eb27f9",
		"8324983e-c79f-466b-b21d-b1cdbe5bf229"
	]
}
Date: 2025-09-22 17:54:08 • branch: master • commit: 5cf7a55

stf.bone

Can only exist within stf.armature.

Properties

KeyRequiredTypeDescription
translationYesTranslationThe position of the bone relative to its armature position.
rotationYesRotationThe rotation of the bones head relative to its armature position.
lengthYesFloatThe bones length
connectedNoBooleanDefault false

Only other stf.bone type resources are allowed as its children.

Implementations

Json Example

"0936400e-013c-475f-bd43-8d3f643e46a3": {
	"type": "stf.bone",
	"name": "LowerArm.R",
	"children": [
		"534a659c-5d6e-4692-9228-2974debbb46e",
		"3ea99969-ff70-48b6-9f47-168367e54296",
		"31832adf-f1eb-4902-9458-9946bbbdb463"
	],
	"connected": true,
	"translation": [
		-0.32599180936813354,
		1.0100003480911255,
		-0.04301619902253151
	],
	"rotation": [
		-0.5354142189025879,
		0.5126163959503174,
		0.5126165747642517,
		0.4333362877368927
	],
	"length": 0.21657702326774597
}
Date: 2025-09-22 17:54:08 • branch: master • commit: 5cf7a55

stf.instance.armature

Instantiates an armature onto a node.

Properties

KeyRequiredTypeDescription
armatureYesResource-IDID of the instantiated armature resource, usually stf.armature
poseNoMap<Resource-ID, TRS>Map of the corresponding bone and TRS.

Implementations

Json Example

"73d67945-2937-41c8-b683-7a992cbca5c5": {
	"type": "stf.instance.armature",
	"name": "",
	"armature": "5251057d-a989-417b-a007-0bbc2fad19d3",
	"pose": {
		"ead3e787-8014-48ac-9af9-37db03edaed6": [
			[ 3.166873430160422e-10, 0.009894609451293945, -0.0011758268810808659 ],
			[ 0.5493189096450806, 9.955886071111308e-08, 6.540119557030266e-08, 0.8356127738952637 ],
			[ 1.0, 1.0, 1.000001072883606 ]
		],
		"793cd8e7-81aa-4034-939b-33fda8582fd8": [
			[ 2.4785646868252798e-09, 0.02414402738213539, -0.010395778343081474 ],
			[ 0.09529310464859009, -2.0173215489194263e-06, -1.7039580768596352e-07, 0.9954492449760437 ],
			[ 1.0, 0.9999999403953552, 0.9999999403953552 ]
		],
		"9a663148-f9a4-4b24-8f4c-7f4d388330dc": [
			[ -3.951510230137956e-09, 0.04944222792983055, 0.016573714092373848 ],
			[ 0.19152779877185822, -3.042036723854835e-06, -5.479599849422812e-07, 0.9814872145652771 ],
			[ 1.0, 0.9999999403953552, 0.9999998807907104 ]
		]
	}
}
Date: 2025-09-22 17:54:08 • branch: master • commit: 5cf7a55

stf.mesh

Datemodel

Face -> Triangle -> Face Corner -> Split -> Vertex

Face: Material Index Split: Normal, UVs, Colors Vertex: Position

Properties

KeyRequiredTypeDescription
float_widthNouintByte-width of float-values
indices_widthNouintByte-width of indices
material_slotsNoList<Resource-ID / null>List of material IDs in the order of the meshes material-slots
verticesYesBuffer-ID3 floats per vertex
face_cornersYesBuffer-IDIndex of the split for each face corner
splitsYesBuffer-IDVertex index for each unique combination of normals, uvs, colors, etc..
split_normalsNoBuffer-ID3 floats per normal
split_colorsNoBuffer-ID4 floats per color (rgba)
trisNoBuffer-ID3 indices per triangle
facesNoBuffer-IDnumber of tris for the face
material_indicesNoBuffer-ID
sharp_edgesNoBuffer-ID
sharp_face_indicesNoBuffer-ID
linesNoBuffer-ID
armatureNoResource-IDID of the armature if the mesh is skinned
weight_lens_widthNouint
bone_indices_widthNouint
bonesNoListBone references in the order by which they will be referenced by bone_indices.
weight_lensNoBuffer-ID
bone_indicesNoBuffer-ID
weightsNoBuffer-ID
uvsNoList
blendshapesNoList
vertex_groupsNoList

UV-Object properties

KeyRequiredTypeDescription
nameYesstring
uvYesBuffer-ID2 floats per split

Blendshape-Object properties

KeyRequiredTypeDescription
nameYesstring
default_valueNofloatdefault: 0
limit_upperNofloatdefault: 1
limit_lowerNofloatdefault: 0
indicesNoBuffer-IDint
position_offsetsYesBuffer-ID3 floats per vertex
split_indicesNoBuffer-IDint
split_normalsNoBuffer-ID3 floats per split

VertexGroup-Object properties

KeyRequiredTypeDescription
nameYesstring
indicesNoBuffer-IDint
weightsYesBuffer-IDfloat per vertex

...TODO

Implementations

Json Example

"783134da-9e2a-4d69-a1f0-59952bc36895": {
	"type": "stf.mesh",
	"name": "Superawesome Mesh",
	"material_slots": [
		"dc07246c-47e9-41bb-b009-5a4eb60303e4"
	],
	"float_width": 4,
	"indices_width": 2,
	"vertices": "23ec5dc3-2e0e-460b-b07d-413e64f9326e",
	"face_corners": "3e6c056e-6dd9-4011-bb14-97cf8e6eaaa0",
	"splits": "c4c432c7-2b1e-4282-92a3-af1a001b08bf",
	"split_normals": "528e70e1-65a1-4155-bff5-cc60fa140d14",
	"uvs": [
		{
			"name": "UVMap",
			"uv": "a0001434-7844-4038-ba8a-2e0540fe65c8"
		}
	],
	"tris": "98ef746d-1023-424b-ac04-2b27540637b6",
	"material_indices_width": 1,
	"faces": "f15060e3-49f1-43d6-a6e9-117984cbe8fe",
	"material_indices": "04a31482-e1cd-437b-be16-be26f164bfdb",
	"sharp_face_indices": "5ef64c4d-0cc8-4ad1-aadc-898b8cc7b436",
	"lines": "13084993-3492-48ca-956b-0ee0766527bf",
	"sharp_edges": "a9d12c37-94d3-43f0-ae48-4a4619416f6e",
	"vertex_groups": [
		{
			"name": "Select Some Things",
			"weights": "14f9133b-fcd4-4c00-95ee-7d8c7dab8bff",
			"indices": "af4f4676-5e26-49fc-a639-4e467076828e"
		},
		{
			"name": "Normal Project Blend Weights",
			"weights": "2a69a2fe-1a2e-4472-a3cf-064762d6b974"
		}
	],
	"blendshapes": [
		{
			"name": "ToggleOff",
			"default_value": 0.0,
			"limit_upper": 1.0,
			"limit_lower": 0.0,
			"indices": "313f0ad4-4933-49bf-8c0c-6957c2750d16",
			"position_offsets": "b4d196a5-1776-460f-8e04-721d7cff5281",
			"split_indices": "c854ed9b-93df-41f5-ab43-e0e9b8ae2625",
			"split_normals": "5fa5f424-6f4e-49c4-82b5-fb8dcaff82ef"
		},
		{
			"name": "Vis_AA",
			"default_value": 0.0,
			"limit_upper": 1.0,
			"limit_lower": 0.0,
			"position_offsets": "9db99d09-0ff7-4f92-896e-0318a31bfd46",
			"split_normals": "949c0d7a-edb7-4d8e-9b9f-c24a56646f65"
		},
		{
			"name": "Vis_IH",
			"default_value": 0.0,
			"limit_upper": 1.0,
			"limit_lower": 0.0,
			"position_offsets": "37118f5c-3dee-4e75-8067-adec146769d0",
			"split_normals": "7c88cbd6-38c2-4755-90aa-54fcd9a880d3"
		}
	],
	"components": [
		"60850594-9bab-4cb2-ac64-657ec5589f5f",
		"5e6c4973-d3cf-423f-aabe-a6a6d0959e40"
	]
}
Date: 2025-09-22 17:54:08 • branch: master • commit: 5cf7a55

stf.instance.mesh

Instantiates a mesh onto a node.

Properties

KeyRequiredTypeDescription
meshYesIDResource-ID of the instantiated mesh resource, usually xref:../data/stf_mesh.adoc[stf.mesh]
armature_instanceNoResource-IDID of a node with an instantiated armature. Usually the instance resource is xref:./stf_instance_armature.adoc[stf.instance.armature]
blendshape_valuesNoList
materialsNoList

Implementations

Json Example

"799b9826-85d9-40a3-a58b-b6489ba60452": {
	"type": "stf.instance.mesh",
	"mesh": "8dedc60f-91cd-4e5e-a032-07dc82358519",
	"armature_instance": "e6ae2ed1-fc53-43ee-ac53-05bf296d5fc1",
	"blendshape_values": [
		null,
		0.3,
		0.65,
		null,
		null,
		null,
		1.0,
		null
	]
},
Date: 2025-09-22 17:54:08 • branch: master • commit: 5cf7a55

stf.material

Properties

KeyRequiredTypeDescription
style_hintsNoListHints on the visual style of the material
shader_targetsNoDict<List>Hints on the target stader per target application
propertiesYesDict<String, Property-Object>Dict of Property-ID as a string to an Object

Property-Object properties

KeyRequiredTypeDescription
typeNoStringType of the value variables
valuesNoListList of values. The value object is determined by the type

The following types for property-values are supported:

float

Json float value

int

Json int value

color

Json array of four floats, corresponding to the RGBA color channels.

image

An Image-Property-Value-Object:

KeyRequiredTypeDescription
imageYesResource-IDID of an stf.image or compatible resource.

TODO: the image object should be expanded with UV-offsets and such

Implementations

Json Example

"bdf11d99-70d2-42df-8a58-19f1e5238662": {
	"type": "stf.material",
	"name": "Body",
	"style_hints": [
		"realistic",
		"pbr"
	],
	"shader_targets": {
		"stfblender": [
			"ShaderNodeBsdfPrincipled"
		],
		"unity": [
			"PoiyomiToon"
		]
	},
	"properties": {
		"albedo.texture": {
			"type": "image",
			"values": [
				{
					"image": "1bf800ea-1bda-491c-ba89-c7bfa364e239"
				}
			]
		},
		"roughness.texture": {
			"type": "image",
			"values": [
				{
					"image": "155888f8-041c-4fe7-bf57-a558bd7b2137"
				}
			]
		},
		"metallic.texture": {
			"type": "image",
			"values": [
				{
					"image": "937ef22d-5175-4c4b-aa89-51da4c445dd4"
				}
			]
		},
		"normal.texture": {
			"type": "image",
			"values": [
				{
					"image": "e0c8e0ce-f667-49cc-b39a-5fb2dcde48ee"
				}
			]
		}
	}
}
Date: 2025-09-22 17:54:08 • branch: master • commit: 5cf7a55

stf.image

Properties

KeyRequiredTypeDescription
formatYesStringFormat of the image. Officially supported formats are: png, jpg
bufferYesBuffer-IDBuffer containing the image file
data_typeNoStringType of image data. As of not it can be color or non_color.

Implementations

Json Example

"1bf800ea-1bda-491c-ba89-c7bfa364e239": {
	"type": "stf.image",
	"name": "Body_BaseColor.png",
	"format": "png",
	"buffer": "ef192623-cc41-445e-acd7-e435be793e95",
	"data_type": "color",
	"components": [
		"f79c8521-845f-4a6c-a44f-bd2647877e0e"
	]
}
Date: 2025-09-22 17:54:08 • branch: master • commit: 5cf7a55

stf.texture

Information on how an image is to be converted into a GPU texture.

Properties

KeyRequiredTypeDescription
widthYesintWidth of the resulting GPU texture
heightYesintHeight of the resulting GPU texture
downscale_priorityYesintIn case of an enforced memory limit, how quickly should the resolution of the resulting GPU texture reduced.
qualityYesfloatIndicate how much the GPU texture can be compressed. Value range is from 0 to 1. 1 means not compression should be used.
mipmapsYesboolWhether to generate mipmaps

Implementations

Json Example

"f0aa405c-8548-453d-8758-516e5c43d45e": {
	"type": "stf.texture",
	"width": 1024,
	"height": 1024,
	"downscale_priority": 0,
	"quality": 0.800000011920929,
	"mipmaps": true
}
Date: 2025-09-22 17:54:08 • branch: master • commit: 5cf7a55

stf.animation

An animation relative to a prefab.

Properties

KeyRequiredTypeDescription
loopYesstringWhether to loop the animation and how
fpsYesfloat
rangeYesListBeginning and end frame of the animation
bake_on_exportNoboolWhether the animation should be baked on
tracksYesList

Track-Object properties

KeyRequiredTypeDescription
targetYesPathSTF path of the target property
subtracksYesList<Subtrack-Object / null>

Subtrack-Object properties

KeyRequiredTypeDescription
keyframesYesList<Keyframe-Array / null>
bakedNoBuffer-IDBaked values between range[0] and range[1]

Keyframe-Array

IndexTypeDescription
0booltrue if this keyframe is a source of truth, as in not baked or generated.
1floatTimepoint in frames
2floatThe main value
3stringinterpolation type

In case the previous keyframe has an out-tangent, this keyframes in-tangent is added at the last position in the keyframe-array.

IndexTypeDescription
lastfloatIn-tangent x and y offset, present only if the previous keyframe has an out-tangent

Depending on the interpolation type, the following properties are added.

bezier

IndexTypeDescription
4stringtangent type
5ListOut-tangent x and y offset

Implementations

Json Example

"6a60e775-4374-4439-bbbe-49ea5edc9438": {
	"type": "stf.animation",
	"name": "Anim Test",
	"loop": "none",
	"fps": 24,
	"bake_on_export": true,
	"range": [
		1.0,
		16.0
	],
	"tracks": [
		{
			"target": [
				"737c6e44-4269-409b-95a8-cfc8e680a13b",
				"t"
			],
			"subtracks": [
				{
					"keyframes": [
						[
							true,
							1.0,
							-0.7435536980628967,
							"bezier",
							"aligned",
							[
								2.0,
								0.0
							]
						],
						[
							true,
							16.0,
							-0.2216922640800476,
							"bezier",
							"aligned",
							[
								3.0,
								0.0
							],
							[
								-3.0,
								0.0
							]
						]
					],
					"baked": "ba4b975f-3df3-42cf-8508-d527b1468b18"
				},
				{
					"keyframes": [
						[
							true,
							1.0,
							2.200054168701172,
							"bezier",
							"aligned",
							[
								2.0,
								0.0
							]
						],
						[
							true,
							16.0,
							0.4340066909790039,
							"bezier",
							"aligned",
							[
								3.0,
								0.0
							],
							[
								-3.0,
								0.0
							]
						]
					],
					"baked": "591f8e72-d4bc-456f-8420-95a46a687329"
				},
				{
					"keyframes": [
						[
							true,
							1.0,
							1.996330738067627,
							"bezier",
							"aligned",
							[
								2.0,
								0.0
							]
						],
						[
							true,
							16.0,
							0.2330167293548584,
							"bezier",
							"aligned",
							[
								3.0,
								0.0
							],
							[
								-3.0,
								0.0
							]
						]
					],
					"baked": "b1951f62-a79e-4cfb-bb3b-75e431d52ca0"
				}
			]
		},
		{
			"target": [
				"737c6e44-4269-409b-95a8-cfc8e680a13b",
				"instance",
				"blendshape",
				"Key 1",
				"value"
			],
			"subtracks": [
				{
					"keyframes": [
						[
							true,
							1.0,
							0.0,
							"bezier",
							"aligned",
							[
								2.0,
								0.0
							]
						],
						[
							true,
							7.0,
							0.7300613522529602,
							"bezier",
							"aligned",
							[
								3.0,
								0.0
							],
							[
								-2.0,
								0.0
							]
						],
						[
							true,
							16.0,
							0.0,
							"bezier",
							"aligned",
							[
								3.0,
								0.0
							],
							[
								-3.0,
								0.0
							]
						]
					],
					"baked": "fba2e828-e6c9-476f-b47c-d1851bcacc7d"
				}
			]
		}
	]
},
Date: 2025-09-22 17:54:08 • branch: master • commit: 5cf7a55

stfexp.*

Date: 2025-09-22 17:54:08 • branch: master • commit: 5cf7a55

stfexp.mesh.seams

Date: 2025-09-22 17:54:08 • branch: master • commit: 5cf7a55

stfexp.mesh.creases

Date: 2025-09-22 17:54:08 • branch: master • commit: 5cf7a55

stfexp.constraint.twist

Date: 2025-09-22 17:54:08 • branch: master • commit: 5cf7a55

stfexp.constraint.rotation

Date: 2025-09-22 17:54:08 • branch: master • commit: 5cf7a55

stfexp.constraint.translation

Date: 2025-09-22 17:54:08 • branch: master • commit: 5cf7a55

stfexp.constraint.parent

Date: 2025-09-22 17:54:08 • branch: master • commit: 5cf7a55

stfexp.constraint.lookat

Date: 2025-09-22 17:54:08 • branch: master • commit: 5cf7a55

stfexp.lightprobe_anchor

Date: 2025-09-22 17:54:08 • branch: master • commit: 5cf7a55

stfexp.armature.humanoid

Date: 2025-09-22 17:54:08 • branch: master • commit: 5cf7a55

ava.*

Date: 2025-09-22 17:54:08 • branch: master • commit: 5cf7a55

ava.avatar

Date: 2025-09-22 17:54:08 • branch: master • commit: 5cf7a55

ava.collider.sphere

Date: 2025-09-22 17:54:08 • branch: master • commit: 5cf7a55

ava.collider.capsule

Date: 2025-09-22 17:54:08 • branch: master • commit: 5cf7a55

ava.collider.plane

Date: 2025-09-22 17:54:08 • branch: master • commit: 5cf7a55

ava.secondary_motion

Date: 2025-09-22 17:54:08 • branch: master • commit: 5cf7a55

ava.eyerotation.bone

Date: 2025-09-22 17:54:08 • branch: master • commit: 5cf7a55

ava.eyelids.blendshape

Date: 2025-09-22 17:54:08 • branch: master • commit: 5cf7a55

ava.visemes.blendshape

Date: 2025-09-22 17:54:08 • branch: master • commit: 5cf7a55

ava.emotes

Date: 2025-09-22 17:54:08 • branch: master • commit: 5cf7a55

Guides

Date: 2025-09-22 17:54:08 • branch: master • commit: 5cf7a55

STF Blender User Guide

Export - Import

An STF asset is represented by a Blender Collection. By default the Scene Collection is used.

If you wish to use another one, select it and check Use as STF Prefab in the STF Editor panel. If you click the Set as STF export root button, it will be automatically selected on export.

Anything parented to the Collection will be exported.

When an STF file gets imported, it will become its own Collection.

Resources

Everything that can be exported in STF will get its own unique ID. If it is not set on before export, STF will automatically assign one. If STF encounters a duplicate ID, it will reassing it.
By default the Blender name of a resource will be used. It can be optionally overridden.

Component Resources

Resource have Components. These are 'sub-resources' which add additional information/data to their parent resource. Some, like mesh-seams are natively supported by Blender, however most arent.
Components can be added/edited in the Components section of each resources panel.

Date: 2025-09-22 17:54:08 • branch: master • commit: 5cf7a55

Unity

TBD

Date: 2025-09-22 17:54:08 • branch: master • commit: 5cf7a55

Godot

TBD

Date: 2025-09-22 17:54:08 • branch: master • commit: 5cf7a55