Loading...
Searching...
No Matches
SceneDuplicator.hpp
1#pragma once
2#include <halp/controls.hpp>
3#include <halp/meta.hpp>
4
5#include <ossia/dataflow/geometry_port.hpp>
6
7#include <cstdint>
8#include <memory>
9#include <string>
10
11namespace Threedim
12{
13
14// Scene-graph-level duplicator: given a prototype scene_spec, emits N cloned
15// root nodes placed by a procedural pattern. Complementary to Instancer, which
16// does GPU-primitive instancing -- one mesh, N instances, one draw call, up to
17// a million particles from a single-mesh prototype. This one clones a rich
18// prototype with hierarchy, multiple meshes and lights into N CPU clones, each
19// with its own TRS, scaling to dozens or a few hundred.
20//
21// Materials, animations, skeletons and environment pass through from the
22// prototype unchanged and are shared across clones; only the root-level node
23// tree is cloned, so downstream path-based tooling addresses each clone
24// independently.
25//
26// Patterns: Grid lays `count` clones on an XZ grid with `spacing` at Y=0; Ring
27// puts them on a circle of `radius` in the XZ plane facing outward; Line runs
28// them along +X with `spacing` separation.
29//
30// Each clone's root node is named `<proto_name>_<idx>`, 0-indexed, so
31// SceneDuplicator(prototype=ChairScene, mode=Ring, count=8) yields /Chair_0 to
32// /Chair_7 and ConfigurePrimitive(paths=["/Chair_*"]) addresses them all.
34{
35public:
36 halp_meta(name, "Scene Duplicator")
37 halp_meta(category, "Visuals/3D/Scene")
38 halp_meta(c_name, "scene_duplicator")
39 halp_meta(authors, "ossia team")
40 halp_meta(
41 manual_url,
42 "https://ossia.io/score-docs/processes/scene-duplicator.html")
43 halp_meta(uuid, "9e7a4b3d-5f2c-4a8b-9d1e-6c3f8b5d2a7e")
44
45 enum Pattern
46 {
47 Grid,
48 Ring,
49 Line
50 };
51
52 struct ins
53 {
54 struct
55 {
56 halp_meta(name, "Scene In");
57 ossia::scene_spec scene;
58 uint8_t dirty{0};
59 } scene_in;
60
61 // Port-driven rebuild: controls trigger rebuild(); upstream
62 // scene_in changes detected in operator()().
63 struct : halp::combobox_t<"Pattern", Pattern>
64 {
65 struct range
66 {
67 std::string_view values[3]{"Grid", "Ring", "Line"};
68 int init{0};
69 };
70 void update(SceneDuplicator& n) { n.rebuild(); }
71 } pattern;
72
73 struct : halp::spinbox_i32<"Count", halp::irange{1, 4096, 4}>
74 { void update(SceneDuplicator& n) { n.rebuild(); } } count;
75 struct : halp::hslider_f32<"Spacing", halp::range{0.01, 1000., 2.}>
76 { void update(SceneDuplicator& n) { n.rebuild(); } } spacing;
77 struct : halp::hslider_f32<"Radius", halp::range{0.01, 1000., 5.}>
78 { void update(SceneDuplicator& n) { n.rebuild(); } } radius;
79 // Grid mode: grid is `cols × rows` with cols ≈ round(sqrt(count)).
80 // Exposed as a control so the user can force a specific aspect.
81 // 0 = auto (square-ish).
82 struct : halp::spinbox_i32<"Grid cols", halp::irange{0, 256, 0}>
83 { void update(SceneDuplicator& n) { n.rebuild(); } } grid_cols;
84 } inputs;
85
86 struct outs
87 {
88 struct
89 {
90 halp_meta(name, "Scene Out");
91 ossia::scene_spec scene;
92 uint8_t dirty{0};
93 } scene_out;
94 } outputs;
95
96 void rebuild();
97 void operator()();
98
99 // Stable shared_ptr cached while inputs are unchanged — keeps
100 // ScenePreprocessor's fingerprint fast-path warm.
101 std::shared_ptr<const ossia::scene_state> m_cached_out;
102 uint8_t m_pending_dirty{0xFF};
103 const ossia::scene_state* m_cached_in_state{};
104 int64_t m_cached_in_version{-1};
105 int64_t m_version_counter{0};
106};
107
108}
Definition SceneDuplicator.hpp:34
Definition SceneDuplicator.hpp:53
Definition SceneDuplicator.hpp:87
Definition MIDISync.hpp:126