-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathEnclosedRegionOffsetOp.cs
120 lines (92 loc) · 3.99 KB
/
EnclosedRegionOffsetOp.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using g3;
namespace gs
{
public class EnclosedRegionOffsetOp : ParametricVectorDisplacementMapOp
{
Vector3d normal;
public Vector3d Normal {
get { return normal; }
set { normal = value; base.invalidate(); }
}
double offset_distance;
public double PushPullDistance {
get { return offset_distance; }
set { offset_distance = value; base.invalidate(); }
}
IFalloffFunction falloff;
public IFalloffFunction Falloff {
get { return falloff; }
set { falloff = value.Duplicate(); base.invalidate(); }
}
ISampledCurve3dSourceOp curve_source;
public ISampledCurve3dSourceOp CurveSource {
get { return curve_source; }
set {
if (curve_source != null)
curve_source.OperatorModified -= on_source_modified;
curve_source = value;
if (curve_source != null )
curve_source.OperatorModified += on_source_modified;
base.invalidate();
}
}
public EnclosedRegionOffsetOp(IMeshSourceOp meshSource = null) : base(meshSource)
{
Normal = Vector3d.AxisY;
offset_distance = 0.25f;
falloff = new WyvillFalloff() { ConstantRange = 0.25f };
}
protected override void Update_GenerateMap()
{
base.begin_update();
if ( MeshSource == null )
throw new Exception("EnclosedRegionOffsetOp: must set valid MeshSource to compute!");
if ( MeshSource.HasSpatial == false)
throw new Exception("EnclosedRegionOffsetOp: MeshSource must have spatial data structure!");
IMesh imesh = MeshSource.GetIMesh();
if (imesh.HasVertexNormals == false)
throw new Exception("EnclosedRegionOffsetOp: input mesh does not have surface normals...");
if (imesh is DMesh3 == false)
throw new Exception("EnclosedRegionOffsetOp: in current implementation, input mesh must be a DMesh3. Ugh.");
DMesh3 mesh = imesh as DMesh3;
ISpatial spatial = MeshSource.GetSpatial();
DCurve3 curve = new DCurve3(CurveSource.GetICurve());
MeshFacesFromLoop loop = new MeshFacesFromLoop(mesh, curve, spatial);
// [RMS] this is all f'n ugly!
MeshVertexSelection selection = new MeshVertexSelection(mesh);
selection.SelectTriangleVertices(loop.InteriorTriangles);
// [TODO] do this inline w/ loop below? but then no maxdist!
Dictionary<int, double> dists = new Dictionary<int, double>();
double max_dist = 0;
foreach ( int vid in selection ) {
Vector3d v = mesh.GetVertex(vid);
int inearseg; double nearsegt;
double min_dist_sqr = curve.DistanceSquared(v, out inearseg, out nearsegt);
min_dist_sqr = Math.Sqrt(min_dist_sqr);
max_dist = Math.Max(min_dist_sqr, max_dist);
dists[vid] = min_dist_sqr;
}
lock (Displacement) {
Displacement.Clear();
Displacement.Resize(mesh.MaxVertexID);
// todo: can do this in parallel...
foreach (int vid in selection) {
//Vector3d v = mesh.GetVertex(vid);
// [TODO]...
double dist = max_dist - dists[vid];
double falloff = Falloff.FalloffT(dist / max_dist);
Vector3d n = mesh.GetVertexNormal(vid);
n = n - n.Dot(normal) * normal;
n.Normalize();
Displacement[vid] = falloff * offset_distance * n;
}
}
// smooth it?
base.complete_update();
}
}
}