The GltfContainer
component allows to load GLTF models into the scene. The
GltfContainerLoadingState
component allows to track the loading state of the GLTF
model.
parameters:
COMPONENT_ID: 1041
COMPONENT_NAME: core::GltfContainer
CRDT_TYPE: LastWriteWin-Element-Set
parameters:
COMPONENT_ID: 1049
COMPONENT_NAME: core::GltfContainerLoadingState
CRDT_TYPE: LastWriteWin-Element-Set
message PBGltfContainer {
// the GLTF file path as listed in the deployed entity
string src = 1;
// default: 0
optional uint32 visible_meshes_collision_mask = 4;
// default: CL_POINTER | CL_PHYSICS
optional uint32 invisible_meshes_collision_mask = 5;
}
// GltfContainerLoadingState is set by the engine and provides information about
// the current state of the GltfContainer of an entity.
message PBGltfContainerLoadingState {
enum LoadingState {
UNKNOWN = 0;
LOADING = 1;
NOT_FOUND = 2;
FINISHED_WITH_ERROR = 3;
FINISHED = 4;
}
LoadingState current_state = 1;
}
The only supported version of glTF is 2.0. The engine MUST NOT support any other version for this component.
The loading of the glTF will be done by the engine. The src
property will be used
to load the glTF from the deployed entity filesystem (ADR-80).
In the scope of a scene, it is RECOMMENDED that the engine caches the loaded glTF files, so that if the same glTF is used in multiple entities, it is only loaded once. Instancing should be used.
Even though marked as optional by the specification, any protocol that is not
data:
MUST not be supported, i.e. file://
or https://
.
The only resolvable assets for the glTF are the ones deployed along with the .gltf/.glb file.
Those will be resolved using the same mechanism as the src
property of the
component.
Since data:
URLs are a bottleneck for parsing resources, it is RECOMMENDED that
tooling and engines in "developer mode" warn the scene creators about its
performance implications.
As per general performance recommendations, every engine and loader SHOULD implement the following extensions:
KHR_materials_basisu
for texture compression
Due to the fact that the deployments contain hashed assets, it is natural to thing that glTF models inside the engine internally, could be shared across scenes. That is not always true. Here is an example of a scene that uses a glTF model that is not shared with other scenes:
Scene(Hash="A")
└── "box.gltf"(Hash=0x11111111)
└── "assets/texture.png"(Hash=0x123123123)
Scene(Hash="B")
└── "box.gltf"(Hash=0x11111111)
└── "assets/texture.png"(Hash=0xFFFFFFFF)
We can clearly see that regardless of the deployed texture, the glTF model remains exactly the same file. This is a common usecase and if caching is applied, the process MUST be aware of all the dependencies of the glTF itself to prevent a vector of attack (poisoning other scene's models with a different texture).
All animations in a glTF instance MUST be stopped as the default state when a Animator is present in the entity, so the Animator can manually control the state.
If Animator is not present, only the first animation MUST be played in loop state.
Each entity will have its own animation state. The engine MUST provide a way to control the animations of each entity via the Animator component this will be detailed in the (ADR-216).
This version of the component does not specify any way to modify the materials of the models. This is a future work.
All meshes belong either to visible or invisible category. Names of invisible meshes should
end in _collider
(case insensitive). Those meshes MUST be invisible and the rest
of the properties of the mesh (like its position in an animation) should be honored. This
convention is permanent and is not affected by any flag or configuration.
Nodes that are not meshes are also affected by this naming convention. If a node is not a mesh, but it has a direct child that is a mesh, then the mesh MUST be invisible. This behavior only affects the direct children meshes, but not the children of the children and the rest of the descendants.
Collision layers of both visible and invisible meshes are set via
visible_meshes_collision_mask
and invisible_meshes_collision_mask
.
Collision mask set to 0 indicates that collision detection / physics system should ignore
meshes of this group, otherwise an engine MUST generate a collider for each mesh of this group
and set its collision layers accordingly.
It is RECOMMENDED that an engine implements a way to visualize the colliders for debugging purposes, making these meshes visible with a distinctive material.
By default, collision mask of visible meshes is set to 0, but it could be set, for example, to
CL_POINTER
if it is desirable for pointer meshes to receive pointer events.
It is possible that the value of collision masks is changed at runtime, so the engine SHOULD be able to enable/disable the colliders at runtime.
Skinned meshes are not supported for colliders of any kind.
Besides the automatic colliders generated by the engine, it is possible to provide custom colliders with custom masks. This is done by adding a custom property to the glTF file. This is the RECOMMENDED via to provide custom colliders that puts the responsibility of the collider creation in the content creator.
The glTF
extra property
named dcl_collider_mask: uint32
is reserved to the engine and it will be used to
generate the collider with the provided mask.
The dcl_collider_mask
property MUST be a valid uint32
value. If the
value is not valid, the engine MUST ignore it.
The meshes of node names ending in _collider
MUST always be invisible.
This enables both invisible colliders and visible colliders to operate at once.
The extra property dcl_collider_mask
will be used as
MeshCollider.collider_mask
for each mesh if provided.
For cases depending on the complete loading of an asset like calculating raycasts or
colliders, the engine MUST provide a way to report the loading state of the glTF. This is done
via the GltfContainerLoadingState
component. The component provides information
about the current state of loading using the following properties:
message PBGltfContainerLoadingState {
enum LoadingState {
UNKNOWN = 0;
LOADING = 1;
NOT_FOUND = 2;
FINISHED_WITH_ERROR = 3;
FINISHED = 4;
}
LoadingState current_state = 1;
}
Where UNKNOWN
is the default state, LOADING
is the state when the
glTF is being loaded, NOT_FOUND
is the state when the glTF is not found,
FINISHED_WITH_ERROR
is the state when the glTF finished loading but with errors
and FINISHED
is the state when the glTF finished loading without errors.
This component also represents the instancing state of the glTF. If the glTF is instanced, the
current_state
will be FINISHED
. Otherwise, the
current_state
will be LOADING
until the glTF is instanced correctly.
The FINISHED_WITH_ERROR
can be caused by the following errors:
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC 2119 and RFC 8174.