1 /**
2     Inochi2D Deformer Nodes
3 
4     Copyright: 
5         Copyright © 2020-2026, Inochi2D Project
6     
7     License:
8         $(LINK2 https://github.com/Inochi2D/inochi2d/blob/main/LICENSE, BSD 2-clause License)
9     
10     Authors:
11         Luna Nielsen
12 */
13 module inochi2d.nodes.deformer;
14 import inochi2d.nodes;
15 import inochi2d.common;
16 import inochi2d.core;
17 import numem.core.traits;
18 import nulib;
19 import numem;
20 
21 public import inochi2d.nodes.deformer.meshdeformer;
22 public import inochi2d.nodes.deformer.latticedeformer;
23 
24 /**
25     A node which deforms the vertex data of nodes beneath
26     it.
27 
28     Deformations happen in world space
29 */
30 @TypeId("Deformer", IN_MAKE_TAG!(0, 2))
31 @TypeIdAbstract
32 abstract
33 class Deformer : Node, IDeformable {
34 private:
35 @nogc:
36     weak_vector!IDeformable toDeform_;
37 
38     void scanPartsRecurse(Node node) {
39 
40         // Don't need to scan null nodes
41         if (node is null)
42             return;
43 
44         // Do the main check
45         if (IDeformable deformable = cast(IDeformable)node)
46             toDeform_ ~= deformable;
47 
48         // Deformers already deform their children, and we deform
49         // them first, so don't exaggerate it through their children
50         if (!cast(Deformer)node) {
51             foreach (child; node.children) {
52                 this.scanPartsRecurse(child);
53             }
54         }
55     }
56 
57 protected:
58 
59     /**
60         Serializes this node to a DataNode.
61 
62         Params:
63             object =    The DataNode to serialize to.
64     */
65     override
66     void onSerialize(ref DataNode object) {
67         super.onSerialize(object);
68     }
69 
70     /**
71         Deserializes this node from a DataNode.
72 
73         Params:
74             object =    The DataNode to deserialize from.
75             state =     The state of the deserializer.
76     */
77     override
78     void onDeserialize(ref DataNode object, ref ModelState state) {
79         super.onDeserialize(object, state);
80     }
81 
82     /**
83         Called when the node is to finalize its deserialization from disk.
84 
85         Params:
86             state =     The state of the deserializer.
87     */
88     override
89     void onFinalize(ref ModelState state) @nogc {
90         super.onFinalize(state);
91         this.rescan();
92     }
93 
94     /**
95         Called when the deformer's internal data should be
96         rebuilt.
97     */
98     void onRebuild() {
99     }
100 
101     /**
102         Called when the node is moved from one parent
103         to another.
104 
105         Params:
106             from =  The node that used to be this node's parent.
107             to =    The node it was moved to.
108             index = The index the node was moved to.
109     */
110     override
111     void onMoved(Node from, Node to, ptrdiff_t index) {
112         this.rescan();
113     }
114 
115 public:
116 
117      ~this() {
118     }
119 
120     /**
121         Constructs a new MeshGroup node
122     */
123     this(Node parent = null) {
124         super(parent);
125     }
126 
127     /**
128         A list of the nodes to deform.
129     */
130     @property IDeformable[] toDeform() => toDeform_[0 .. $];
131 
132     /**
133         The control points of the deformer.
134     */
135     abstract @property vec2[] controlPoints() @nogc;
136     abstract @property void controlPoints(vec2[] value) @nogc;
137 
138     /**
139         The base position of the deformable's points.
140     */
141     abstract @property const(vec2)[] basePoints() @nogc;
142 
143     /**
144         The base matrix of the object before any parameters have been applied.
145     */
146     override @property Basis deformBaseMatrix() @nogc => baseMatrix;
147 
148     /**
149         World matrix of the deformable object.
150     */
151     override @property Basis deformMatrix() @nogc => matrix;
152 
153     /**
154         The points which may be deformed by the deformer.
155     */
156     override @property vec2[] deformPoints() @nogc => controlPoints();
157 
158     /**
159         Deforms the IDeformable.
160 
161         Params:
162             deformed =  The deformation delta.
163             absolute =  Whether the deformation is absolute,
164                         replacing the original deformation.
165     */
166     override void deform(vec2[] deformed, bool absolute) {
167         import nulib.math : min;
168 
169         size_t m = min(deformPoints.length, deformed.length);
170         if (absolute)
171             deformPoints[0 .. m] = deformed[0 .. m];
172         else
173             deformPoints[0 .. m] += deformed[0 .. m];
174     }
175 
176     /**
177         Deforms a single vertex in the IDeformable
178 
179         Params:
180             offset =    The offset into the point list to deform.
181             deform =    The deformation delta.
182             absolute =  Whether the deformation is absolute,
183                         replacing the original deformation.
184     */
185     override void deform(size_t offset, vec2 deform, bool absolute = false) {
186         if (offset >= deformPoints.length)
187             return;
188 
189         if (absolute)
190             deformPoints[offset] = deform;
191         else
192             deformPoints[offset] += deform;
193     }
194 
195     /**
196         Resets the deformation for the IDeformable.
197     */
198     abstract void resetDeform();
199 
200     /**
201         Rescans the children of the deformer.
202     */
203     final void rescan() {
204         toDeform_.clear();
205         foreach (child; children) {
206             this.scanPartsRecurse(child);
207         }
208 
209         // We now know what we're deforming, rebuild.
210         this.onRebuild();
211     }
212 }
213 
214 mixin Register!(Deformer, in_node_registry);
215 
216 /**
217     A deformer look-up-table for a deformer-to-mesh
218     mapping.
219 */
220 struct DeformerLUT(alias mapfn) {
221 @nogc:
222 
223     /**
224         LUT entries
225     */
226     ptrdiff_t[2][] entries;
227 
228     /**
229         Rebuilds the LUT.
230     */
231     void rebuild(Parameters!(mapfn) params) {
232         nu_freea(entries);
233         entries = mapfn(params);
234     }
235 }