MayaFlux 0.5.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
ForceFields.hpp
Go to the documentation of this file.
1#pragma once
2
3#include "Tendency.hpp"
4
6
8
9/**
10 * @brief Radial attraction/repulsion toward an anchor point
11 * @param anchor Target position
12 * @param strength Force magnitude scalar (positive attracts, negative repels)
13 * @return VectorField: glm::vec3 -> glm::vec3
14 *
15 * Force magnitude follows inverse square: strength / max(d², floor).
16 * Direction is normalized delta from evaluation point to anchor.
17 * Floor of 0.1 prevents singularity at the anchor position.
18 */
19inline VectorField point_attractor(const glm::vec3& anchor, float strength)
20{
21 return { .fn = [anchor, strength](const glm::vec3& p) -> glm::vec3 {
22 glm::vec3 delta = anchor - p;
23 float d = glm::length(delta);
24 if (d < 0.001F)
25 return glm::vec3(0.0F);
26 return (delta / d) * (strength / std::max(d * d, 0.1F));
27 } };
28}
29
30/**
31 * @brief Tangential force perpendicular to both an axis and the radius vector.
32 * @param anchor Point the orbit is centred on.
33 * @param axis Orbital axis (e.g. glm::vec3(0, 1, 0) for orbits in the XZ plane).
34 * @param strength Force magnitude, constant with distance.
35 * @return VectorField: glm::vec3 -> glm::vec3
36 *
37 * cross(axis, p - anchor) is perpendicular to the radius vector in the plane
38 * normal to axis, which is the direction that turns radial motion into
39 * revolution rather than a straight collapse or escape. Combine with
40 * point_attractor on the same anchor for an orbit: attraction supplies the
41 * centripetal pull, this supplies the sideways push that keeps the fall from
42 * being straight down. Unlike a true two-body problem this is force-based
43 * rather than velocity-constrained, so orbits drift rather than close
44 * exactly, which reads as organic rather than as a bug.
45 */
46inline VectorField orbital(const glm::vec3& anchor, const glm::vec3& axis, float strength)
47{
48 return { .fn = [anchor, axis, strength](const glm::vec3& p) -> glm::vec3 {
49 glm::vec3 radius = p - anchor;
50 glm::vec3 tangent = glm::cross(axis, radius);
51 float d = glm::length(tangent);
52 if (d < 0.001F)
53 return glm::vec3(0.0F);
54 return (tangent / d) * strength;
55 } };
56}
57
58/**
59 * @brief Uniform random force field using Stochastic infrastructure
60 * @param strength Maximum magnitude per axis
61 * @param rng Stochastic generator instance (captured by value, caller controls seed)
62 * @return VectorField: glm::vec3 -> glm::vec3
63 *
64 * Produces a different random vector on each evaluation. Position input
65 * is ignored: the field is spatially uniform but temporally varying.
66 * For spatially coherent noise, compose with a Perlin/simplex generator.
67 */
69{
70 return { .fn = [strength, rng](const glm::vec3&) mutable -> glm::vec3 {
71 return glm::vec3(
72 rng(-1.0F, 1.0F),
73 rng(-1.0F, 1.0F),
74 rng(-1.0F, 1.0F))
75 * strength;
76 } };
77}
78
79} // namespace MayaFlux::Kinesis::ForceFields
float radius
Unified generative infrastructure for stochastic and procedural algorithms.
VectorField turbulence(float strength, Stochastic::Stochastic rng=Stochastic::Stochastic())
Uniform random force field using Stochastic infrastructure.
VectorField point_attractor(const glm::vec3 &anchor, float strength)
Radial attraction/repulsion toward an anchor point.
VectorField orbital(const glm::vec3 &anchor, const glm::vec3 &axis, float strength)
Tangential force perpendicular to both an axis and the radius vector.
std::function< R(const D &)> fn
Definition Tendency.hpp:23
Typed, composable, stateless callable from domain D to range R.
Definition Tendency.hpp:22