From 2f1376850a1d1567503593f90d2264730f0381f9 Mon Sep 17 00:00:00 2001 From: Lean Mendoza Date: Fri, 1 Nov 2024 08:14:37 -0300 Subject: [PATCH] feat: exposing GLTF internals add ADR-253 modification --- .../sdk/components/gltf_container.proto | 2 + .../gltf_container_loading_state.proto | 13 ++++++ .../sdk/components/gltf_node.proto | 42 +++++++++++++++++++ .../sdk/components/gltf_node_state.proto | 20 +++++++++ .../sdk/components/material.proto | 11 +++++ .../sdk/components/mesh_collider.proto | 9 +++- .../sdk/components/mesh_renderer.proto | 11 +++-- public/sdk-components.proto | 2 + 8 files changed, 106 insertions(+), 4 deletions(-) create mode 100644 proto/decentraland/sdk/components/gltf_node.proto create mode 100644 proto/decentraland/sdk/components/gltf_node_state.proto diff --git a/proto/decentraland/sdk/components/gltf_container.proto b/proto/decentraland/sdk/components/gltf_container.proto index 21ddee7d..045e7fba 100644 --- a/proto/decentraland/sdk/components/gltf_container.proto +++ b/proto/decentraland/sdk/components/gltf_container.proto @@ -16,4 +16,6 @@ message PBGltfContainer { optional uint32 visible_meshes_collision_mask = 4; // default: 0 optional uint32 invisible_meshes_collision_mask = 5; // default: CL_POINTER | CL_PHYSICS + + optional bool internal_feedback = 6; // whether receive internal GLTF scene data in the GltfLoading state or not, default: true } diff --git a/proto/decentraland/sdk/components/gltf_container_loading_state.proto b/proto/decentraland/sdk/components/gltf_container_loading_state.proto index 2bd38240..daa39933 100644 --- a/proto/decentraland/sdk/components/gltf_container_loading_state.proto +++ b/proto/decentraland/sdk/components/gltf_container_loading_state.proto @@ -10,4 +10,17 @@ import "decentraland/sdk/components/common/loading_state.proto"; // the current state of the GltfContainer of an entity. message PBGltfContainerLoadingState { common.LoadingState current_state = 1; + repeated string node_paths = 2; // all node paths in the gltf, which can be used with a GltfNode to inspect and modify the gltf contents + repeated string mesh_names = 3; // all meshes in the gltf. unnamed meshes will be auto-assigned a name of the form `MeshX` or `MeshX/PrimitiveY` + // where X is the mesh index and Y is the primitive index (and there is more than 1 primitive). note this may + // conflict with manually named meshes - to avoid any issues make sure all your meshes are explicitly named. + repeated string material_names = 4; // all materials in the gltf. unnamed materials will be auto-assigned a name of the form `MaterialX` where + // X is the material index. note this may conflict with manually named materials - to avoid any issues make + // sure all your materials are explicitly named. + repeated string skin_names = 5; // all mesh skins in the gltf. unnamed skins will be auto-assigned a name of the form `SkinX` where + // X is the skin index. note this may conflict with manually named skins - to avoid any issues make sure all + // your skins are explicitly named. + repeated string animation_names = 6; // all animations in the gltf. unnamed animations will be auto-assigned a name of the form `AnimationX` where + // X is the animation index. note this may conflict with manually named anims - to avoid any issues make sure all + // your animations are explicitly named. } diff --git a/proto/decentraland/sdk/components/gltf_node.proto b/proto/decentraland/sdk/components/gltf_node.proto new file mode 100644 index 00000000..9f2e3503 --- /dev/null +++ b/proto/decentraland/sdk/components/gltf_node.proto @@ -0,0 +1,42 @@ +syntax = "proto3"; +package decentraland.sdk.components; + +import "decentraland/sdk/components/common/id.proto"; +option (common.ecs_component_id) = 1200; + +// a GltfNode links a scene entity with a node from within a gltf, allowing the scene to inspect it or modify it. +// This component must be added to a direct child of an entity with a PbGltfContainer component, or +// to a direct child of another entity with a GltfNode component, and the referenced gltf node must be a descendent of the gltf node +// in the parent. +// The name must match the path of one of the nodes within the Gltf. These are available on the GltfContainerLoadingState component. +// +// The renderer will attach a PbGltfNodeState to the entity describing the state. Once the state is `GNS_READY`, +// - the `Transform` will be updated to match the position of the node within the gltf (relative to the gltf root, or the parent node), +// - a `MeshRenderer` with a GltfMesh mesh type will be added (if the gltf node has a mesh). +// - a `MeshCollider` with a GltfMesh mesh type will be added (if the gltf node has a collider). +// - a `Material` component including a GltfMaterial reference will be added (if the gltf node has a material). +// +// After creation, if an animation moves the node, the `Transform` will be updated. +// +// From the scene, you can modify various components to alter the gltf node: +// - modifying the `Transform` position/rotation/scale will move the node. The position is interpreted relative to the gltf root (or parent node), +// regardless of any intermediate gltf node hierarchy. +// If an animation is playing, the animation takes priority and the scene entity's position will be updated to match the animation. +// - `Visibility` can be added to hide or show the node and it's children in the gltf hierarchy. +// - `MeshRenderer` can be added/modified/removed to create/modify/remove a mesh on the node. +// - `MeshCollider` can be added/modified/removed to create/modify/remove a collider on the node. +// - `Material` can be added or modified to change the material properties. If the gltf node has a material, the original material will be +// used as a base, and any gltf features (e.g. occlusion maps) from the gtlf spec that the renderer supports but that are not exposed in the +// PbMaterial will be maintained. +// +// The scene can add additional entities as children to the gltf node, but structural modifications of the gltf are not possible: +// - changing the scene hierarchy will not change the gltf node hierarchy. Moving the entity out of the gltf will sever the link and +// change the state to `GNS_FAILED`. +// - deleting the scene entity will not delete the gltf node. +// +// Removing the GltfNode will revert any changes to the original gltf. If the GltfNode component is removed and the mesh/collider/material +// are not removed, this will result in a duplication of these components as the previously-linked entity will retain it's components and +// the gltf node will also be displayed. +message PBGltfNode { + string path = 1; // the path of the target node in the Gltf. +} diff --git a/proto/decentraland/sdk/components/gltf_node_state.proto b/proto/decentraland/sdk/components/gltf_node_state.proto new file mode 100644 index 00000000..1ce9512e --- /dev/null +++ b/proto/decentraland/sdk/components/gltf_node_state.proto @@ -0,0 +1,20 @@ +syntax = "proto3"; +package decentraland.sdk.components; + +import "decentraland/sdk/components/common/id.proto"; +option (common.ecs_component_id) = 1201; + +// See the details of the GltfNode component for more information. + +// The state of a linked gltf node. +// If the state is GNSV_FAILED, the renderer may describe the failure in the error string. +message PBGltfNodeState { + GltfNodeStateValue state = 1; + optional string error = 2; +} + +enum GltfNodeStateValue { + GNSV_PENDING = 0; + GNSV_FAILED = 1; + GNSV_READY = 2; +} diff --git a/proto/decentraland/sdk/components/material.proto b/proto/decentraland/sdk/components/material.proto index 3936b27e..cb694175 100644 --- a/proto/decentraland/sdk/components/material.proto +++ b/proto/decentraland/sdk/components/material.proto @@ -54,5 +54,16 @@ message PBMaterial { UnlitMaterial unlit = 1; PbrMaterial pbr = 2; } + + message GltfMaterial { + string gltf_src = 1; + string name = 2; + } + // A gltf material that may provide additional features not supported by the PbMaterial fields. + // If both gltf and material fields are provided, the gltf will be used only for extended features not + // supported by the PbMaterial. + // If this is provided and the `material` field is not provided, the renderer will update the material + // field with data that reflects the gltf material once it is loaded. + optional GltfMaterial gltf = 3; } diff --git a/proto/decentraland/sdk/components/mesh_collider.proto b/proto/decentraland/sdk/components/mesh_collider.proto index 3289566b..913225fb 100644 --- a/proto/decentraland/sdk/components/mesh_collider.proto +++ b/proto/decentraland/sdk/components/mesh_collider.proto @@ -30,6 +30,12 @@ message PBMeshCollider { // SphereMesh is a sphere shape that contains the Entity. message SphereMesh {} + // A collider constructed from a Gltf Mesh. + message GltfMesh { + string gltf_src = 1; // the GLTF file path as listed in the scene's manifest. + string name = 2; // the name of the mesh asset + } + optional uint32 collision_mask = 1; // enabled ColliderLayers (default CL_POINTER | CL_PHYSICS) oneof mesh { @@ -37,6 +43,7 @@ message PBMeshCollider { SphereMesh sphere = 3; CylinderMesh cylinder = 4; PlaneMesh plane = 5; + GltfMesh gltf = 6; } } @@ -59,4 +66,4 @@ enum ColliderLayer { CL_CUSTOM6 = 8192; CL_CUSTOM7 = 16384; CL_CUSTOM8 = 32768; -} \ No newline at end of file +} diff --git a/proto/decentraland/sdk/components/mesh_renderer.proto b/proto/decentraland/sdk/components/mesh_renderer.proto index eee8c134..a6095017 100644 --- a/proto/decentraland/sdk/components/mesh_renderer.proto +++ b/proto/decentraland/sdk/components/mesh_renderer.proto @@ -5,13 +5,11 @@ import "decentraland/sdk/components/common/id.proto"; option (common.ecs_component_id) = 1018; // The MeshRenderer component renders a basic geometric shape for an Entity. It can be a cube, a -// plane, a sphere or a cylinder. +// plane, a sphere, a cylinder, or a Gltf mesh. // // The cube and plane variants can include a UV texture mapping, so specific areas of a material // texture are rendered on different faces of the shape. They are serialized as a sequence of 2D // `float` coordinates, one for each corner of each side of each face. -// -// More complex shapes require the use of a `GltfContainer` component. message PBMeshRenderer { // BoxMesh renders a prism shape. @@ -34,10 +32,17 @@ message PBMeshRenderer { message SphereMesh { } + // A mesh from a Gltf. + message GltfMesh { + string gltf_src = 1; // the GLTF file path as listed in the scene's manifest. + string name = 2; // the name of the mesh asset + } + oneof mesh { BoxMesh box = 1; SphereMesh sphere = 2; CylinderMesh cylinder = 3; PlaneMesh plane = 4; + GltfMesh gltf = 5; } } diff --git a/public/sdk-components.proto b/public/sdk-components.proto index 64d7c6f2..527e6662 100644 --- a/public/sdk-components.proto +++ b/public/sdk-components.proto @@ -16,6 +16,8 @@ import public "decentraland/sdk/components/camera_mode.proto"; import public "decentraland/sdk/components/engine_info.proto"; import public "decentraland/sdk/components/gltf_container.proto"; import public "decentraland/sdk/components/gltf_container_loading_state.proto"; +import public "decentraland/sdk/components/gltf_node.proto"; +import public "decentraland/sdk/components/gltf_node_state.proto"; import public "decentraland/sdk/components/material.proto"; import public "decentraland/sdk/components/mesh_collider.proto"; import public "decentraland/sdk/components/mesh_renderer.proto";