OverviewFilesCommitsIssuesDocsReleasesPeers

proc-nodes / src / graph / domain_adapt.h

55 lines · c ref:
#ifndef PROC_NODES_DOMAIN_ADAPT_H
#define PROC_NODES_DOMAIN_ADAPT_H

#include "../core/proc_mesh.h"
#include "socket_value.h"

namespace godot {

// A FIELD CONSUMED ON ANOTHER DOMAIN MUST BE ADAPTED, NOT INDEXED.
//
// Blender evaluates a field on the CONSUMER's domain. Store Named Attribute
// with domain=CORNER fed a point field gives corner i the value of ITS VERTEX;
// on domain=FACE it averages the face's vertices. proc-nodes read the field at
// index i directly, so on a 3x2 grid (6 points, 8 corners) corner 1 got vertex
// 1's value where Blender gives vertex 2's, and corners 6 and 7 -- past the end
// of the point array -- came back ZERO. Nothing caught it because nothing could
// read a corner-domain value out of the engine at all.
//
// EVERY RULE BELOW WAS MEASURED against Blender 5.2 on a 4x3 grid, storing on
// one domain and reading back on another, never inferred:
//
//   point  -> corner   the corner's vertex (a gather, exact)
//   point  -> face     mean over the face's vertices
//   point  -> edge     mean over the edge's two vertices
//   corner -> point    mean over the corners using that vertex
//   corner -> face     mean over the face's corners
//   corner -> edge     mean over the corner owning the edge and the NEXT corner
//   face   -> corner   broadcast (a corner belongs to exactly one face)
//   face   -> point    mean over the faces touching that vertex
//   face   -> edge     mean over the faces owning that edge
//   edge   -> point    mean over the edges touching that vertex
//   edge   -> face     mean over the face's own edges
//   edge   -> corner   mean of the corner's OWN edge and the PREVIOUS corner's
//
// and the mixers, which are NOT uniform and are the reason this was measured
// rather than assumed:
//
//   float/vector/color   arithmetic mean
//   int                  mean, rounded half UP -- 4.5 -> 5, so not banker's
//   bool                 ALL, except FROM FACE and edge->point, which are ANY
//
// A single mechanism covers all twelve: build the list of source elements
// contributing to each destination element, then mix. Gather and broadcast are
// the degenerate one-contributor case.

// Adapt p_val from p_from to p_to over p_mesh. A non-field value, or p_from ==
// p_to, is returned unchanged. r_ok is false when the pair is not adaptable
// (no mesh, or a non-mesh domain), and the caller must then NOT pretend.
SocketValue adapt_field_to_domain(const SocketValue &p_val, AttrDomain p_from,
		AttrDomain p_to, const Ref<ProcMesh> &p_mesh, bool *r_ok = nullptr);

} // namespace godot

#endif // PROC_NODES_DOMAIN_ADAPT_H