MayaFlux 1.0.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
FieldTargets.hpp
Go to the documentation of this file.
1#pragma once
2
3#include "Influence.hpp"
4
8
9namespace MayaFlux::Nexus {
10
11namespace detail {
12
13 template <typename D, typename R>
15 {
16 return { .fn = [cell](const D& d) -> R { return cell->fn ? cell->fn(d) : R(0.0F); } };
17 }
18
19} // namespace detail
20
21/**
22 * @brief Target that feeds an influence of fields into an operator's vertex attributes.
23 * @tparam Field Kinesis::VectorField, SpatialField or UVField, matching @p target.
24 * @param op FieldOperator, as a raw pointer from create_operator or a shared_ptr.
25 * @param target Vertex attribute mask the field drives.
26 *
27 * Binds one forwarding field to @p op now, and every time the influence runs the
28 * target replaces what that field forwards to. Other fields bound to the same
29 * target are left alone, which unbinding and rebinding each tick would not do.
30 * The operator is not retained. The influence and the operator must run on the
31 * same tick domain.
32 */
33template <typename Field, typename Operator>
34[[nodiscard]] typename Influence<Field>::Target bind_field(
35 const Operator& op,
37{
38 auto cell = std::make_shared<Field>();
39 op->bind(target, detail::forwarding(cell));
40 return [cell](const Field& field) { *cell = field; };
41}
42
43/**
44 * @brief Same as above, for one slot of a MeshFieldOperator.
45 * @param slot Slot index the field drives.
46 */
47template <typename Field, typename Operator>
48[[nodiscard]] typename Influence<Field>::Target bind_field(
49 const Operator& op,
50 uint32_t slot,
52{
53 auto cell = std::make_shared<Field>();
54 op->bind(slot, target, detail::forwarding(cell));
55 return [cell](const Field& field) { *cell = field; };
56}
57
58/**
59 * @brief Target that feeds an influence of vector fields into a PhysicsOperator as a force.
60 * @param op PhysicsOperator, as a raw pointer from create_operator or a shared_ptr.
61 *
62 * Adds one forwarding force field now, and every time the influence runs the
63 * target replaces what that field forwards to. Force fields already added to
64 * @p op are left alone. The operator is not retained.
65 */
66template <typename Operator>
67[[nodiscard]] Influence<Kinesis::VectorField>::Target bind_force(const Operator& op)
68{
69 auto cell = std::make_shared<Kinesis::VectorField>();
70 op->add_force_field(detail::forwarding(cell));
71 return [cell](const Kinesis::VectorField& field) { *cell = field; };
72}
73
74/**
75 * @brief Target that feeds an influence of vector fields into one instance's position.
76 * @param op InstanceFieldOperator, as a raw pointer or a shared_ptr.
77 * @param slot Instance slot the field drives.
78 */
79template <typename Operator>
80[[nodiscard]] Influence<Kinesis::VectorField>::Target bind_position(const Operator& op, uint32_t slot)
81{
82 auto cell = std::make_shared<Kinesis::VectorField>();
83 op->bind_position(slot, detail::forwarding(cell));
84 return [cell](const Kinesis::VectorField& field) { *cell = field; };
85}
86
87/**
88 * @brief Target that feeds an influence of transform functions into one slot.
89 * @param op InstanceFieldOperator or MeshTransformOperator, raw pointer or shared_ptr.
90 * @param slot Slot the function drives.
91 *
92 * The influence's value is the operator's own TransformField: for an
93 * InstanceFieldOperator a function from the slot's current transform to its next
94 * one, for a MeshTransformOperator a function from accumulated seconds to the
95 * slot's local transform.
96 */
97template <typename Operator>
98[[nodiscard]] auto bind_transform(const Operator& op, uint32_t slot)
99{
100 using Transform = typename std::remove_cvref_t<decltype(*op)>::TransformField;
101
102 auto cell = std::make_shared<Transform>();
103 if constexpr (requires { op->bind_transform(slot, std::declval<Transform>()); }) {
104 op->bind_transform(slot, [cell](const glm::mat4& current) {
105 return *cell ? (*cell)(current) : current;
106 });
107 } else {
108 op->bind(slot, [cell](float seconds) {
109 return *cell ? (*cell)(seconds) : glm::mat4(1.0F);
110 });
111 }
112 return typename Influence<Transform>::Target { [cell](const Transform& field) { *cell = field; } };
113}
114
115/**
116 * @brief Target that moves or resizes an Expanse's bounds from an influence of boxes.
117 * @param expanse Expanse, raw pointer or shared_ptr, retained by the target.
118 */
119template <typename Region>
120[[nodiscard]] Influence<Kinesis::AABB3D>::Target bind_bounds(const Region& expanse)
121{
122 return [expanse](const Kinesis::AABB3D& bounds) { expanse->set_bounds(bounds); };
123}
124
125/**
126 * @brief Target that sets the parameter block of a GpuFieldOperator's parametric fields.
127 * @param op GpuFieldOperator, raw pointer or shared_ptr; retained by the target.
128 *
129 * The influence's value is the vec4 parametric fields receive as their third
130 * argument. It is pushed every dispatch, so nothing is rebound or recompiled.
131 */
132template <typename Operator>
133[[nodiscard]] Influence<glm::vec4>::Target bind_params(const Operator& op)
134{
135 return [op](const glm::vec4& params) { op->set_params(params); };
136}
137
138/**
139 * @brief Target that pushes an influence's value to a GPU executor as push constants.
140 * @tparam T Trivially copyable struct matching the shader's push constant layout.
141 * @param target An operator with push_constants (MeshFieldOperator,
142 * InstanceFieldOperator) or a shader processor with set_push_constant_data;
143 * raw pointer or shared_ptr, retained by the target.
144 *
145 * For an operator this arms the next dispatch of its executor. This is how an
146 * Agent's state reaches a slot-transform kernel, for example one assembled from
147 * a DualField of mat4 through ShaderSpec::Assemble::function(). For a shader
148 * processor the push block is grown to hold T at @p offset here, so a shader
149 * that already declares it is not drawn before the block exists. A shader that
150 * keeps push constants of its own passes the byte offset after them and
151 * declares both in one block.
152 */
153template <typename T, typename Receiver>
154[[nodiscard]] typename Influence<T>::Target bind_push_constants(const Receiver& target, size_t offset = 0)
155{
156 if constexpr (requires { target->get_push_constant_data(); }) {
157 if (target->get_push_constant_data().size() < offset + sizeof(T)) {
158 target->set_push_constant_size(offset + sizeof(T));
159 }
160 }
161
162 return [target, offset](const T& data) {
163 if constexpr (requires { target->push_constants(data); }) {
164 target->push_constants(data);
165 } else {
166 if (target->get_push_constant_data().size() < offset + sizeof(T)) {
167 target->set_push_constant_size(offset + sizeof(T));
168 }
169 std::memcpy(target->get_push_constant_data().data() + offset, &data, sizeof(T));
170 }
171 };
172}
173
174/**
175 * @brief Target that pushes an InfluenceBlock to a render processor for the library's lit shaders.
176 * @param target A render processor, raw pointer or shared_ptr, retained by the target.
177 * @param offset Byte offset of the block when the shader keeps push constants ahead of it.
178 *
179 * Pairs with InfluenceBlock::from as the producer.
180 */
181template <typename Receiver>
182[[nodiscard]] Influence<InfluenceBlock>::Target bind_influence_block(const Receiver& target, size_t offset = 0)
183{
184 return bind_push_constants<InfluenceBlock>(target, offset);
185}
186
187} // namespace MayaFlux::Nexus
uint64_t offset
Definition Composite.cpp:10
glm::vec2 current
std::function< void(const T &)> Target
Definition Influence.hpp:94
FieldTarget
What a Tendency drives when applied to a vertex record.
Kinesis::Tendency< D, R > forwarding(const std::shared_ptr< Kinesis::Tendency< D, R > > &cell)
Influence< Field >::Target bind_field(const Operator &op, Kinesis::FieldTarget target)
Target that feeds an influence of fields into an operator's vertex attributes.
Influence< InfluenceBlock >::Target bind_influence_block(const Receiver &target, size_t offset=0)
Target that pushes an InfluenceBlock to a render processor for the library's lit shaders.
auto bind_transform(const Operator &op, uint32_t slot)
Target that feeds an influence of transform functions into one slot.
Influence< T >::Target bind_push_constants(const Receiver &target, size_t offset=0)
Target that pushes an influence's value to a GPU executor as push constants.
Influence< Kinesis::VectorField >::Target bind_force(const Operator &op)
Target that feeds an influence of vector fields into a PhysicsOperator as a force.
Influence< Kinesis::VectorField >::Target bind_position(const Operator &op, uint32_t slot)
Target that feeds an influence of vector fields into one instance's position.
Influence< glm::vec4 >::Target bind_params(const Operator &op)
Target that sets the parameter block of a GpuFieldOperator's parametric fields.
Influence< Kinesis::AABB3D >::Target bind_bounds(const Region &expanse)
Target that moves or resizes an Expanse's bounds from an influence of boxes.
Axis-aligned bounding box in 3D world space.
Definition Bounds.hpp:188
std::function< R(const D &)> fn
Definition Tendency.hpp:23
Typed, composable, stateless callable from domain D to range R.
Definition Tendency.hpp:22