Loading...
Searching...
No Matches
AssetLoader.hpp
1#pragma once
2#include <Threedim/TinyObj.hpp>
3#include <Threedim/TransformHelper.hpp>
4#include <halp/controls.hpp>
5#include <halp/file_port.hpp>
6#include <halp/meta.hpp>
7
8#include <ossia/dataflow/geometry_port.hpp>
9
10#include <Gfx/Graph/GpuResourceRegistry.hpp>
11
12#include <score_plugin_threedim_export.h>
13
14#include <memory>
15#include <string_view>
16
17class QRhiResourceUpdateBatch;
18
19namespace score::gfx
20{
21class RenderList;
22struct Edge;
23}
24
25namespace Threedim
26{
27
28// External scene-file parser registry. An addon shipping a format-specific
29// parser registers itself here so AssetLoader can dispatch to it without a
30// link-time dependency from score-plugin-threedim.
31//
32// The callback takes the same halp::text_file_view the built-in glTF and FBX
33// parsers receive and returns a populated ossia::scene_state, or a null
34// shared_ptr on failure or unhandled input. AssetLoader wraps the state with the
35// Position / Rotation / Scale controls exactly as for the built-ins.
36//
37// Extensions match case-insensitively on the suffix after the final '.'. A
38// duplicate registration replaces the prior one. Calls are thread-safe.
39class SCORE_PLUGIN_THREEDIM_EXPORT AssetLoaderRegistry
40{
41public:
42 using ParseFn = std::shared_ptr<const ossia::scene_state> (*)(
43 const halp::text_file_view&);
44
45 // Register a parser for an extension (without the dot). Safe at
46 // static-init time — the underlying storage is a function-local
47 // Meyers singleton.
48 static void register_parser(std::string_view extension, ParseFn fn);
49
50 // Lookup by lowercased extension. Returns nullptr if no match.
51 static ParseFn lookup(std::string_view extension_lower) noexcept;
52};
53
54// Unified 3D asset loader. Accepts .fbx / .gltf / .glb / .obj / .ply / .stl /
55// .off natively, plus .usd / .usda / .usdc / .usdz when score-addon-academy is
56// loaded and has registered its UsdParser.
57//
58// Dispatch is by file extension:
59// .fbx ufbx (FbxParser's static parser)
60// .gltf / .glb fastgltf (GltfParser's static parser)
61// .obj tinyobjloader + sceneStateFromMeshes
62// .ply miniply + sceneStateFromMeshes
63// .stl / .off vcglib + sceneStateFromMeshes
64// .usd* OpenUSD (academy UsdParser, optional)
65// others AssetLoaderRegistry::lookup(ext)
66//
67// Position / Rotation / Scale controls wrap the loaded scene at a single root
68// TRS through TransformHelper::wrapSceneWithTransform.
69//
70// The geometry-only formats produce a scene with one scene_node per mesh part,
71// each holding a mesh_component over a single shared CPU buffer; FBX and glTF
72// retain their scene hierarchy of lights, cameras, materials, skeletons and
73// animations.
75{
76public:
77 halp_meta(name, "Asset Loader")
78 halp_meta(category, "Visuals/3D")
79 halp_meta(c_name, "asset_loader")
80 halp_meta(description, "Load a 3D asset with its scene hierarchy, geometry and available materials and animations.")
81 halp_meta(authors, "ossia team, ufbx / fastgltf / tinyobj / miniply / vcglib")
82 halp_meta(
83 manual_url,
84 "https://ossia.io/score-docs/processes/asset-loader.html")
85 halp_meta(uuid, "2f6a8c41-7d93-4e5b-b1c8-4e3f9a7d2c5b")
86
88 {
89 std::string_view bytes;
90 std::string_view filename;
91
92 asset_file_view() = default;
93 asset_file_view(const halp::text_file_view& v) noexcept
94 : bytes{v.bytes}
95 , filename{v.filename}
96 {
97 }
98 };
99
100 struct ins
101 {
102 struct asset_t : halp::file_port<"Asset file", asset_file_view>
103 {
104 halp_meta(
105 extensions,
106 "3D assets (*.fbx *.gltf *.glb *.obj *.ply *.stl *.off "
107 "*.splat *.spz "
108 "*.usd *.usda *.usdc *.usdz)");
109 static std::function<void(AssetLoader&)> process(file_type data);
110 } asset;
111
112 PositionControl position;
113 RotationControl rotation;
114 ScaleControl scale;
115
116 // Stamps every primitive_cloud_component emitted by this asset
117 // with `format_id = value` when non-empty. Empty falls back to the
118 // parser's autodetection (PLY column sniffing, .splat / .spz
119 // hardcoded). Used to route unrecognised PLY columns or addon-
120 // produced files through a FlattenedSceneFilterNode in mode 12.
121 struct format_override_t : halp::lineedit<"Format override (auto if empty)", "">
122 {
123 void update(AssetLoader& n) { n.rebuild_format_state(); }
124 } format_override;
125 } inputs;
126
127 struct outs
128 {
129 struct
130 {
131 halp_meta(name, "Scene");
132 ossia::scene_spec scene;
133 uint8_t dirty{0};
134 } scene_out;
135 } outputs;
136
137 void operator()();
138
139 // Render-thread hooks. init() claims a RawTransform slot for the
140 // single root wrapping xform this node emits (TransformHelper's
141 // scene-wrapping transform). update() uploads the current TRS.
142 void init(score::gfx::RenderList& r, QRhiResourceUpdateBatch& res);
143 void update(
144 score::gfx::RenderList& r, QRhiResourceUpdateBatch& res,
146 void release(score::gfx::RenderList& r);
147
148 // Raw scene as parsed from the file — stable as long as the file
149 // doesn't change. The pipeline is:
150 // m_parsed_state (parser output, never mutated)
151 // ↓ applyFormatOverride(format_override.value)
152 // m_overridden_state (format_id rewrites applied, or = parsed)
153 // ↓ wrapSceneWithTransform(position/rotation/scale)
154 // m_wrapped_state (final, published downstream)
155 std::shared_ptr<const ossia::scene_state> m_parsed_state;
156 std::shared_ptr<const ossia::scene_state> m_overridden_state;
157 std::shared_ptr<const ossia::scene_state> m_wrapped_state;
158 std::string m_cached_format_override;
159 CachedTRS m_cached_xform;
160 int64_t m_version_counter{0};
161
162 // Re-runs applyFormatOverride from the parsed state. Triggered by the
163 // lineedit's update() callback when the user edits the override
164 // field; also called once after parsing.
165 void rebuild_format_state();
166
167 score::gfx::GpuResourceRegistry::Slot raw_transform_slot;
168 ossia::gpu_slot_ref m_xform_ref{};
169
170private:
171 void rebuild_wrapped_state();
172};
173
174}
Definition AssetLoader.hpp:75
Definition AssetLoader.hpp:40
List of nodes to be rendered to an output.
Definition RenderList.hpp:33
Graphics rendering pipeline for ossia score.
Definition Filter/PreviewWidget.hpp:11
Definition AssetLoader.hpp:88
Definition AssetLoader.hpp:103
Definition AssetLoader.hpp:122
Definition AssetLoader.hpp:101
Definition AssetLoader.hpp:128
Definition TransformHelper.hpp:26
Definition TinyObj.hpp:98
Definition TinyObj.hpp:103
Definition TinyObj.hpp:107
Connection between two score::gfx::Port.
Definition score-plugin-gfx/Gfx/Graph/Utils.hpp:236
Definition GpuResourceRegistry.hpp:84