FRP is inherently good for things like games, and it's internally structured like a directed graph (I think).
A scene graph is also inherently good for things like games... (note: I'm referring specifically to composing transform matrices from parent to child, not other issues a full-fledged "scene graph" library typically provides like raycasting, touch detection, etc. In other words the concept described here: https://webglfundamentals.org/webgl/lessons/webgl-scene-graph.html)
Does anyone have advice on how one might structure FRP so that changes would propagate down to children?
On one foot I'm thinking of something sortof like the following (Typescript syntax and untested... using gl-matrix for matrix stuff)
interface Transform {
local: Float32Array
world: Float32Array
}
interface Node {
sLocal: StreamSink<Float32Array>
cTransform: Cell<Transform>
}
const identityTransform = ():Transform => ({
local: mat4.create(),
world: mat4.create()
});
const makeNode = (parent?:Node) {
const sLocal = new StreamSink<Float32Array>();
const cTransform = parent === undefined
? sLocal.hold(identityTransform())
: sLocal.snapshot(parent.cTransform, (newLocal, parentTransform) => ({
local: newLocal
world: mat4.multiply(mat4.create(), parentTransform.world, newLocal);
}))
.hold(identityTransform());
return {
sLocal: sLocal,
cTransform: cTransform
}
}
//usage
const grandparent = makeNode();
const parent = makeNode(grandparent);
const child = makeNode(parent);
grandparent.sLocal.send(mat4.fromTranslation(mat4.create(), [x,y,z]));
//child.cTransform.sample().world should be composed from the tree
Of course instead of setting the local transform explicitly via sLocal.send, it could also be some other source like a Cell (for continuous motion)