1 /*
2     field.h: Routines for averaging orientations and directions subject
3     to various symmetry conditions. Also contains the Optimizer class which
4     uses these routines to smooth fields hierarchically.
5 
6     This file is part of the implementation of
7 
8         Instant Field-Aligned Meshes
9         Wenzel Jakob, Daniele Panozzo, Marco Tarini, and Olga Sorkine-Hornung
10         In ACM Transactions on Graphics (Proc. SIGGRAPH Asia 2015)
11 
12     All rights reserved. Use of this source code is governed by a
13     BSD-style license that can be found in the LICENSE.txt file.
14 */
15 
16 #pragma once
17 
18 
19 #include "hierarchy.h"
20 #include <map>
21 
22 /* Rotation helper functions */
23 extern Vector3f rotate60(const Vector3f &d, const Vector3f &n);
24 extern Vector3f rotate90(const Vector3f &d, const Vector3f &n);
25 extern Vector3f rotate180(const Vector3f &d, const Vector3f &n);
26 extern Vector3f rotate60_by(const Vector3f &d, const Vector3f &n, int amount);
27 extern Vector3f rotate90_by(const Vector3f &d, const Vector3f &n, int amount);
28 extern Vector3f rotate180_by(const Vector3f &d, const Vector3f &n, int amount);
29 extern Vector2i rshift60(Vector2i shift, int amount);
30 extern Vector2i rshift90(Vector2i shift, int amount);
31 extern Vector2i rshift180(Vector2i shift, int amount);
32 extern Vector3f rotate_vector_into_plane(Vector3f q, const Vector3f &source_normal, const Vector3f &target_normal);
33 
34 /* Extrinsic & intrinsic orientation symmetry functors */
35 extern std::pair<Vector3f, Vector3f>
36 compat_orientation_intrinsic_2(const Vector3f &q0, const Vector3f &n0,
37                                const Vector3f &q1, const Vector3f &n1);
38 
39 extern std::pair<Vector3f, Vector3f>
40 compat_orientation_intrinsic_4(const Vector3f &q0, const Vector3f &n0,
41                                const Vector3f &q1, const Vector3f &n1);
42 
43 extern std::pair<Vector3f, Vector3f>
44 compat_orientation_intrinsic_4_knoeppel(const Vector3f &q0, const Vector3f &n0,
45                                         const Vector3f &q1, const Vector3f &n1);
46 
47 extern std::pair<Vector3f, Vector3f>
48 compat_orientation_intrinsic_6(const Vector3f &q0, const Vector3f &n0,
49                                const Vector3f &q1, const Vector3f &n1);
50 
51 extern std::pair<Vector3f, Vector3f>
52 compat_orientation_extrinsic_2(const Vector3f &q0, const Vector3f &n0,
53                                const Vector3f &q1, const Vector3f &n1);
54 
55 extern std::pair<Vector3f, Vector3f>
56 compat_orientation_extrinsic_4(const Vector3f &q0, const Vector3f &n0,
57                                const Vector3f &q1, const Vector3f &n1);
58 
59 extern std::pair<Vector3f, Vector3f>
60 compat_orientation_extrinsic_6(const Vector3f &q0, const Vector3f &n0,
61                                const Vector3f &q1, const Vector3f &n1);
62 
63 extern std::pair<int, int>
64 compat_orientation_extrinsic_index_2(const Vector3f &q0, const Vector3f &n0,
65                                      const Vector3f &q1, const Vector3f &n1);
66 
67 extern std::pair<int, int>
68 compat_orientation_extrinsic_index_4(const Vector3f &q0, const Vector3f &n0,
69                                      const Vector3f &q1, const Vector3f &n1);
70 
71 extern std::pair<int, int>
72 compat_orientation_extrinsic_index_6(const Vector3f &q0, const Vector3f &n0,
73                                      const Vector3f &q1, const Vector3f &n1);
74 
75 extern std::pair<int, int>
76 compat_orientation_intrinsic_index_2(const Vector3f &q0, const Vector3f &n0,
77                                      const Vector3f &q1, const Vector3f &n1);
78 
79 extern std::pair<int, int>
80 compat_orientation_intrinsic_index_4(const Vector3f &q0, const Vector3f &n0,
81                                      const Vector3f &q1, const Vector3f &n1);
82 
83 extern std::pair<int, int>
84 compat_orientation_intrinsic_index_6(const Vector3f &q0, const Vector3f &n0,
85                                      const Vector3f &q1, const Vector3f &n1);
86 
87 /* Extrinsic & intrinsic position symmetry functors */
88 extern std::pair<Vector3f, Vector3f> compat_position_extrinsic_3(
89     const Vector3f &p0, const Vector3f &n0, const Vector3f &q0,
90     const Vector3f &o0, const Vector3f &p1, const Vector3f &n1,
91     const Vector3f &q1, const Vector3f &o1, Float scale, Float inv_scale);
92 
93 extern std::pair<Vector3f, Vector3f> compat_position_extrinsic_4(
94     const Vector3f &p0, const Vector3f &n0, const Vector3f &q0,
95     const Vector3f &o0, const Vector3f &p1, const Vector3f &n1,
96     const Vector3f &q1, const Vector3f &o1, Float scale, Float inv_scale);
97 
98 extern std::pair<Vector2i, Vector2i> compat_position_extrinsic_index_3(
99     const Vector3f &p0, const Vector3f &n0, const Vector3f &q0,
100     const Vector3f &o0, const Vector3f &p1, const Vector3f &n1,
101     const Vector3f &q1, const Vector3f &o1, Float scale, Float inv_scale,
102     Float *error = nullptr);
103 
104 extern std::pair<Vector2i, Vector2i> compat_position_extrinsic_index_4(
105     const Vector3f &p0, const Vector3f &n0, const Vector3f &q0,
106     const Vector3f &o0, const Vector3f &p1, const Vector3f &n1,
107     const Vector3f &q1, const Vector3f &o1, Float scale, Float inv_scale,
108     Float *error = nullptr);
109 
110 extern std::pair<Vector3f, Vector3f> compat_position_intrinsic_3(
111     const Vector3f &p0, const Vector3f &n0, const Vector3f &q0,
112     const Vector3f &o0, const Vector3f &p1, const Vector3f &n1,
113     const Vector3f &q1, const Vector3f &o1, Float scale, Float inv_scale);
114 
115 extern std::pair<Vector3f, Vector3f> compat_position_intrinsic_4(
116     const Vector3f &p0, const Vector3f &n0, const Vector3f &q0,
117     const Vector3f &o0, const Vector3f &p1, const Vector3f &n1,
118     const Vector3f &q1, const Vector3f &o1, Float scale, Float inv_scale);
119 
120 extern std::pair<Vector2i, Vector2i> compat_position_intrinsic_index_3(
121     const Vector3f &p0, const Vector3f &n0, const Vector3f &q0,
122     const Vector3f &o0, const Vector3f &p1, const Vector3f &n1,
123     const Vector3f &q1, const Vector3f &o1, Float scale, Float inv_scale,
124     Float *error = nullptr);
125 
126 extern std::pair<Vector2i, Vector2i> compat_position_intrinsic_index_4(
127     const Vector3f &p0, const Vector3f &n0, const Vector3f &q0,
128     const Vector3f &o0, const Vector3f &p1, const Vector3f &n1,
129     const Vector3f &q1, const Vector3f &o1, Float scale, Float inv_scale,
130     Float *error = nullptr);
131 
132 /* Optimization kernels */
133 
134 extern Float optimize_orientations(
135     MultiResolutionHierarchy &mRes, int level, bool extrinsic, int rosy,
136     const std::function<void(uint32_t)> &progress);
137 
138 extern Float optimize_positions(
139     MultiResolutionHierarchy &mRes, int level, bool extrinsic, int posy,
140     const std::function<void(uint32_t)> &progress);
141 
142 /* Singularity computation */
143 
144 extern void compute_orientation_singularities(
145     const MultiResolutionHierarchy &mRes, std::map<uint32_t, uint32_t> &sing,
146     bool extrinsic, int rosy);
147 
148 extern void
149 compute_position_singularities(const MultiResolutionHierarchy &mRes,
150                                const std::map<uint32_t, uint32_t> &orient_sing,
151                                std::map<uint32_t, Vector2i> &pos_sing,
152                                bool extrinsic, int rosy, int posy);
153 
154 /* Field optimizer (invokes optimization kernels in a separate thread) */
155 
156 class Serializer;
157 class Optimizer {
158 public:
159     Optimizer(MultiResolutionHierarchy &mRes, bool interactive);
160     void save(Serializer &state);
161     void load(const Serializer &state);
162 
stop()163     void stop() {
164         if (mOptimizeOrientations)
165             mRes.propagateSolution(mRoSy);
166         mOptimizePositions = mOptimizeOrientations = false;
167         notify();
168     }
169 
shutdown()170     void shutdown() { mRunning = false; notify(); mThread.join(); }
171 
active()172     bool active() { return mOptimizePositions | mOptimizeOrientations; }
notify()173     inline void notify() { mCond.notify_all(); }
174 
175     void optimizeOrientations(int level);
176 
177     void optimizePositions(int level);
178 
179     void wait();
180 
setExtrinsic(bool extrinsic)181     void setExtrinsic(bool extrinsic) { mExtrinsic = extrinsic; }
extrinsic()182     bool extrinsic() const { return mExtrinsic; }
183 
setRoSy(int rosy)184     void setRoSy(int rosy) { mRoSy = rosy; }
rosy()185     int rosy() const { return mRoSy; }
setPoSy(int posy)186     void setPoSy(int posy) { mPoSy = posy; }
posy()187     int posy() const { return mPoSy; }
setLevel(int level)188     void setLevel(int level) { mLevel = level; }
level()189     int level() const { return mLevel; }
progress()190     Float progress() const { return mProgress; }
191 
192 #ifdef VISUALIZE_ERROR
error()193     const VectorXf &error() { return mError; }
194 #endif
195 
moveSingularity(const std::vector<uint32_t> & path,bool orientations)196     void moveSingularity(const std::vector<uint32_t> &path, bool orientations) {
197         std::lock_guard<ordered_lock> lock(mRes.mutex());
198         mAttractorStrokes.push_back(std::make_pair(orientations, path));
199         setLevel(0);
200     }
201 
202     void run();
203 protected:
204     MultiResolutionHierarchy &mRes;
205     std::vector<std::pair<bool, std::vector<uint32_t>>> mAttractorStrokes;
206     bool mRunning;
207     bool mOptimizeOrientations;
208     bool mOptimizePositions;
209     std::thread mThread;
210     std::condition_variable_any mCond;
211     int mLevel, mLevelIterations;
212     bool mHierarchical;
213     int mRoSy, mPoSy;
214     bool mExtrinsic;
215     bool mInteractive;
216     double mLastUpdate;
217     Float mProgress;
218 #ifdef VISUALIZE_ERROR
219     VectorXf mError;
220 #endif
221     Timer<> mTimer;
222 };
223