Skip to content

Commit b964d63

Browse files
Remove "legacy mode", make deforms more dynamic
1 parent e61db99 commit b964d63

File tree

4 files changed

+68
-116
lines changed

4 files changed

+68
-116
lines changed

source/inochi2d/core/math/deform.d

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,23 +18,23 @@ public:
1818
/**
1919
The base position of the deformable's points.
2020
*/
21-
@property const(vec2)[] basePoints();
21+
@property const(vec2)[] basePoints() @nogc;
2222

2323
/**
2424
The points which may be deformed by the deformer.
2525
*/
26-
@property vec2[] deformPoints();
26+
@property vec2[] deformPoints() @nogc;
2727

2828
/**
2929
The base transform of the object before any
3030
parameters have been applied.
3131
*/
32-
@property Transform baseTransform();
32+
@property Transform baseTransform() @nogc;
3333

3434
/**
3535
World transform of the deformable object.
3636
*/
37-
@property Transform worldTransform();
37+
@property Transform worldTransform() @nogc;
3838

3939
/**
4040
Deforms the IDeformable.

source/inochi2d/core/nodes/deformer/meshdeformer.d

Lines changed: 42 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -26,16 +26,8 @@ private:
2626
Mesh mesh_;
2727
DeformedMesh base_;
2828
DeformedMesh deformed_;
29-
BlendWeight[][] weights_;
3029
vec2[] deformDeltas_;
3130

32-
void clearWeights() {
33-
foreach(i; 0..weights_.length) {
34-
nu_freea(weights_[i]);
35-
}
36-
nu_freea(weights_);
37-
}
38-
3931
protected:
4032
/**
4133
Allows serializing self data (with pretty serializer)
@@ -62,7 +54,7 @@ public:
6254
/**
6355
The mesh
6456
*/
65-
@property Mesh mesh() => mesh_;
57+
@property Mesh mesh() @nogc => mesh_;
6658
final @property void mesh(Mesh value) @nogc {
6759
if (value is mesh_)
6860
return;
@@ -83,8 +75,8 @@ public:
8375
/**
8476
The control points of the deformer.
8577
*/
86-
override @property vec2[] controlPoints() => deformed_.points;
87-
override @property void controlPoints(vec2[] value) {
78+
override @property vec2[] controlPoints() @nogc => deformed_.points;
79+
override @property void controlPoints(vec2[] value) @nogc {
8880
import nulib.math : min;
8981

9082
size_t m = min(value.length, deformed_.points.length);
@@ -94,18 +86,18 @@ public:
9486
/**
9587
The base position of the deformable's points, in world space.
9688
*/
97-
override @property const(vec2)[] basePoints() => base_.points;
89+
override @property const(vec2)[] basePoints() @nogc => base_.points;
9890

9991
/**
10092
The points which may be deformed by a deformer, in world space.
10193
*/
102-
override @property vec2[] deformPoints() => deformed_.points;
94+
override @property vec2[] deformPoints() @nogc => deformed_.points;
10395

10496
// Destructor
10597
~this() {
10698
nu_freea(deformDeltas_);
10799
nogc_delete(deformed_);
108-
this.clearWeights();
100+
nogc_delete(base_);
109101
mesh_.release();
110102
}
111103

@@ -165,75 +157,45 @@ public:
165157
// Use the weights to deform each subpoint by a delta determined
166158
// by the weight to each vertex in their triangle.
167159
foreach(i, mesh; toDeform) {
168-
if (weights_[i].length == 0)
169-
continue;
170-
171160
foreach(j; 0..mesh.deformPoints.length) {
172-
BlendWeight weight = weights_[i][j];
173-
vec2 dfDelta = -(
174-
(deformDeltas_[weight.indices[0]]*weight.weights.x) +
175-
(deformDeltas_[weight.indices[1]]*weight.weights.y) +
176-
(deformDeltas_[weight.indices[2]]*weight.weights.z)
177-
);
178-
mesh.deform(j, dfDelta);
179-
}
180-
}
181-
}
182-
183-
override
184-
void rescan() {
185-
super.rescan();
186-
187-
base_.reset();
188-
base_.pushMatrix(transform!true.matrix);
189-
190-
// Clear weights lists.
191-
if (weights_.length < toDeform.length) {
192-
weights_ = weights_.nu_resize(toDeform.length);
193-
nogc_zeroinit(weights_[0..$]);
194-
}
195-
196-
// Use barycentric coordinates of triangles to calculate
197-
// weights for deformed points.
198-
Triangle[] tris = base_.getTriangles();
199-
foreach(i, df; toDeform) {
200-
201-
// Reset all the data in the weights.
202-
weights_[i] = weights_[i].nu_resize(df.deformPoints.length);
203-
weights_[i][0..$] = BlendWeight.init;
204-
205-
mat4 baseTransformMat = df.baseTransform.matrix;
206-
foreach(j; 0..df.deformPoints.length) {
207-
208-
// NOTE: IDeformable doesn't have the internal mesh reference
209-
// so instead we just multiply the point with their world
210-
// matrix.
211-
vec2 wpt = (baseTransformMat * vec4(df.basePoints[j], 0, 1)).xy;
212-
foreach(k, ref tri; tris) {
213-
vec3 bc = tri.barycentric(wpt);
214-
if (bc.x > 0 && bc.y > 0 && bc.z > 0) {
215-
weights_[i][j] = BlendWeight(
216-
[
217-
mesh_.indices[(k*3)+0],
218-
mesh_.indices[(k*3)+1],
219-
mesh_.indices[(k*3)+2],
220-
],
221-
bc
222-
);
223-
break;
224-
}
161+
vec2 mp = mesh.deformPoints[j];
162+
163+
foreach(k; 0..deformed_.elementCount/3) {
164+
165+
uint[3] idx = [
166+
mesh_.indices[(k*3)+0],
167+
mesh_.indices[(k*3)+1],
168+
mesh_.indices[(k*3)+2],
169+
];
170+
Triangle tri = Triangle(
171+
base_.points[idx[0]],
172+
base_.points[idx[1]],
173+
base_.points[idx[2]],
174+
);
175+
176+
// Do some cheaper checks first.
177+
float minX = min(tri.p1.x, tri.p2.x, tri.p3.x);
178+
float maxX = max(tri.p1.x, tri.p2.x, tri.p3.x);
179+
float minY = min(tri.p1.y, tri.p2.y, tri.p3.y);
180+
float maxY = max(tri.p1.y, tri.p2.y, tri.p3.y);
181+
if (!(minX < mp.x && maxX > mp.x) &&
182+
!(minY < mp.y && maxY > mp.y))
183+
continue;
184+
185+
// Expensive check and barycentric coordinates.
186+
vec3 bc = tri.barycentric(mesh.deformPoints[j]);
187+
if (bc.x < 0 || bc.y < 0 || bc.z < 0)
188+
continue;
189+
190+
mesh.deform(j, -(
191+
(deformDeltas_[idx[0]]*bc.x) +
192+
(deformDeltas_[idx[1]]*bc.y) +
193+
(deformDeltas_[idx[2]]*bc.z)
194+
));
195+
break;
225196
}
226197
}
227198
}
228-
nu_freea(tris);
229199
}
230200
}
231-
mixin Register!(MeshDeformer, in_node_registry);
232-
233-
/**
234-
Weights for meshes
235-
*/
236-
struct BlendWeight {
237-
uint[3] indices = [0, 0, 0];
238-
vec3 weights = vec3(0, 0, 0);
239-
}
201+
mixin Register!(MeshDeformer, in_node_registry);

source/inochi2d/core/nodes/deformer/package.d

Lines changed: 7 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -27,24 +27,17 @@ public import inochi2d.core.nodes.deformer.latticedeformer;
2727
abstract
2828
class Deformer : Node, IDeformable {
2929
private:
30-
bool legacyMode_;
31-
3230
void scanPartsRecurse(Node node) {
3331

3432
// Don't need to scan null nodes
3533
if (node is null) return;
3634

37-
// NOTE: Backwards compatibility mode does not allow
38-
// MeshGroup instances to be nested.
39-
if (legacyMode_ && cast(Deformer)node)
40-
return;
41-
4235
// Do the main check
4336
if (IDeformable deformable = cast(IDeformable)node)
4437
toDeform ~= deformable;
4538

4639
foreach(child; node.children) {
47-
scanPartsRecurse(child);
40+
this.scanPartsRecurse(child);
4841
}
4942
}
5043

@@ -60,13 +53,11 @@ protected:
6053
override
6154
void onSerialize(ref JSONValue object, bool recursive=true) {
6255
super.onSerialize(object, recursive);
63-
object["legacyMode"] = legacyMode_;
6456
}
6557

6658
override
6759
void onDeserialize(ref JSONValue object) {
6860
super.onDeserialize(object);
69-
this.legacyMode_ = object.tryGet!bool("legacyMode", true);
7061
}
7162

7263
/**
@@ -80,15 +71,6 @@ protected:
8071

8172
public:
8273

83-
/**
84-
Whether deformers should act like MeshGroup when selecting
85-
nodes to deform.
86-
*/
87-
final @property bool legacyMode() => legacyMode_;
88-
final @property void legacyMode(bool value) {
89-
this.legacyMode_ = value;
90-
}
91-
9274
~this() { }
9375

9476
/**
@@ -101,28 +83,28 @@ public:
10183
/**
10284
The control points of the deformer.
10385
*/
104-
abstract @property vec2[] controlPoints();
105-
abstract @property void controlPoints(vec2[] value);
86+
abstract @property vec2[] controlPoints() @nogc;
87+
abstract @property void controlPoints(vec2[] value) @nogc;
10688

10789
/**
10890
The base position of the deformable's points.
10991
*/
110-
abstract @property const(vec2)[] basePoints();
92+
abstract @property const(vec2)[] basePoints() @nogc;
11193

11294
/**
11395
Local matrix of the deformable object.
11496
*/
115-
override @property Transform baseTransform() => transform!true;
97+
override @property Transform baseTransform() @nogc => transform!true;
11698

11799
/**
118100
World matrix of the deformable object.
119101
*/
120-
override @property Transform worldTransform() => transform!false;
102+
override @property Transform worldTransform() @nogc => transform!false;
121103

122104
/**
123105
The points which may be deformed by the deformer.
124106
*/
125-
override @property vec2[] deformPoints() => controlPoints();
107+
override @property vec2[] deformPoints() @nogc => controlPoints();
126108

127109
/**
128110
Deforms the IDeformable.

source/inochi2d/core/nodes/drawable/package.d

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ abstract class Drawable : Node, IDeformable {
3535
private:
3636
Mesh mesh_;
3737
DeformedMesh deformed_;
38+
DeformedMesh base_;
3839

3940
protected:
4041

@@ -58,8 +59,10 @@ protected:
5859
override
5960
void onDeserialize(ref JSONValue object) {
6061
super.onDeserialize(object);
61-
this.mesh_ = Mesh.fromMeshData(object.tryGet!MeshData("mesh"));
62-
this.deformed_ = nogc_new!DeformedMesh(mesh_);
62+
63+
this.deformed_ = nogc_new!DeformedMesh();
64+
this.base_ = nogc_new!DeformedMesh();
65+
this.mesh = Mesh.fromMeshData(object.tryGet!MeshData("mesh"));
6366
}
6467

6568
public:
@@ -77,22 +80,23 @@ public:
7780

7881
this.mesh_ = value.retained();
7982
this.deformed_.parent = value;
83+
this.base_.parent = value;
8084
}
8185

8286
/**
8387
Local matrix of the deformable object.
8488
*/
85-
override @property Transform baseTransform() => transform!true;
89+
override @property Transform baseTransform() @nogc => transform!true;
8690

8791
/**
8892
World matrix of the deformable object.
8993
*/
90-
override @property Transform worldTransform() => transform!false;
94+
override @property Transform worldTransform() @nogc => transform!false;
9195

9296
/**
9397
The base position of the deformable's points.
9498
*/
95-
@property const(vec2)[] basePoints() => mesh_.points;
99+
@property const(vec2)[] basePoints() => base_.points;
96100

97101
/**
98102
The points which may be deformed by the deformer.
@@ -125,8 +129,9 @@ public:
125129
this(MeshData data, GUID guid, Node parent = null) {
126130
super(guid, parent);
127131

128-
this.mesh_ = Mesh.fromMeshData(data);
129-
this.deformed_ = nogc_new!DeformedMesh(mesh_);
132+
this.deformed_ = nogc_new!DeformedMesh();
133+
this.base_ = nogc_new!DeformedMesh();
134+
this.mesh = Mesh.fromMeshData(data);
130135
}
131136

132137
/**
@@ -172,6 +177,9 @@ public:
172177
override
173178
void resetDeform() {
174179
deformed_.reset();
180+
181+
base_.reset();
182+
base_.pushMatrix(baseTransform.matrix);
175183
}
176184

177185
/**

0 commit comments

Comments
 (0)