1 /*
2 main.cpp -- Instant Meshes application entry point
3
4 This file is part of the implementation of
5
6 Instant Field-Aligned Meshes
7 Wenzel Jakob, Daniele Panozzo, Marco Tarini, and Olga Sorkine-Hornung
8 In ACM Transactions on Graphics (Proc. SIGGRAPH Asia 2015)
9
10 All rights reserved. Use of this source code is governed by a
11 BSD-style license that can be found in the LICENSE.txt file.
12 */
13
14 #include "batch.h"
15 #include "viewer.h"
16 #include "serializer.h"
17 #include <thread>
18 #include <cstdlib>
19
20 /* Force usage of discrete GPU on laptops */
21 NANOGUI_FORCE_DISCRETE_GPU();
22
23 int nprocs = -1;
24
main(int argc,char ** argv)25 int main(int argc, char **argv) {
26 std::vector<std::string> args;
27 bool extrinsic = true, dominant = false, align_to_boundaries = false;
28 bool fullscreen = false, help = false, deterministic = false, compat = false;
29 int rosy = 4, posy = 4, face_count = -1, vertex_count = -1;
30 uint32_t knn_points = 10, smooth_iter = 2;
31 Float crease_angle = -1, scale = -1;
32 std::string batchOutput;
33 #if defined(__APPLE__)
34 bool launched_from_finder = false;
35 #endif
36
37 try {
38 for (int i=1; i<argc; ++i) {
39 if (strcmp("--fullscreen", argv[i]) == 0 || strcmp("-F", argv[i]) == 0) {
40 fullscreen = true;
41 } else if (strcmp("--help", argv[i]) == 0 || strcmp("-h", argv[i]) == 0) {
42 help = true;
43 } else if (strcmp("--deterministic", argv[i]) == 0 || strcmp("-d", argv[i]) == 0) {
44 deterministic = true;
45 } else if (strcmp("--intrinsic", argv[i]) == 0 || strcmp("-i", argv[i]) == 0) {
46 extrinsic = false;
47 } else if (strcmp("--boundaries", argv[i]) == 0 || strcmp("-b", argv[i]) == 0) {
48 align_to_boundaries = true;
49 } else if (strcmp("--threads", argv[i]) == 0 || strcmp("-t", argv[i]) == 0) {
50 if (++i >= argc) {
51 cerr << "Missing thread count!" << endl;
52 return -1;
53 }
54 nprocs = str_to_uint32_t(argv[i]);
55 } else if (strcmp("--smooth", argv[i]) == 0 || strcmp("-S", argv[i]) == 0) {
56 if (++i >= argc) {
57 cerr << "Missing smoothing iteration count argument!" << endl;
58 return -1;
59 }
60 smooth_iter = str_to_uint32_t(argv[i]);
61 } else if (strcmp("--knn", argv[i]) == 0 || strcmp("-k", argv[i]) == 0) {
62 if (++i >= argc) {
63 cerr << "Missing knn point count argument!" << endl;
64 return -1;
65 }
66 knn_points = str_to_uint32_t(argv[i]);
67 } else if (strcmp("--crease", argv[i]) == 0 || strcmp("-c", argv[i]) == 0) {
68 if (++i >= argc) {
69 cerr << "Missing crease angle argument!" << endl;
70 return -1;
71 }
72 crease_angle = str_to_float(argv[i]);
73 } else if (strcmp("--rosy", argv[i]) == 0 || strcmp("-r", argv[i]) == 0) {
74 if (++i >= argc) {
75 cerr << "Missing rotation symmetry type!" << endl;
76 return -1;
77 }
78 rosy = str_to_int32_t(argv[i]);
79 } else if (strcmp("--posy", argv[i]) == 0 || strcmp("-p", argv[i]) == 0) {
80 if (++i >= argc) {
81 cerr << "Missing position symmetry type!" << endl;
82 return -1;
83 }
84 posy = str_to_int32_t(argv[i]);
85 if (posy == 6)
86 posy = 3;
87 } else if (strcmp("--scale", argv[i]) == 0 || strcmp("-s", argv[i]) == 0) {
88 if (++i >= argc) {
89 cerr << "Missing scale argument!" << endl;
90 return -1;
91 }
92 scale = str_to_float(argv[i]);
93 } else if (strcmp("--faces", argv[i]) == 0 || strcmp("-f", argv[i]) == 0) {
94 if (++i >= argc) {
95 cerr << "Missing face count argument!" << endl;
96 return -1;
97 }
98 face_count = str_to_int32_t(argv[i]);
99 } else if (strcmp("--vertices", argv[i]) == 0 || strcmp("-v", argv[i]) == 0) {
100 if (++i >= argc) {
101 cerr << "Missing vertex count argument!" << endl;
102 return -1;
103 }
104 vertex_count = str_to_int32_t(argv[i]);
105 } else if (strcmp("--output", argv[i]) == 0 || strcmp("-o", argv[i]) == 0) {
106 if (++i >= argc) {
107 cerr << "Missing batch mode output file argument!" << endl;
108 return -1;
109 }
110 batchOutput = argv[i];
111 } else if (strcmp("--dominant", argv[i]) == 0 || strcmp("-D", argv[i]) == 0) {
112 dominant = true;
113 } else if (strcmp("--compat", argv[i]) == 0 || strcmp("-C", argv[i]) == 0) {
114 compat = true;
115 #if defined(__APPLE__)
116 } else if (strncmp("-psn", argv[i], 4) == 0) {
117 launched_from_finder = true;
118 #endif
119 } else {
120 if (strncmp(argv[i], "-", 1) == 0) {
121 cerr << "Invalid argument: \"" << argv[i] << "\"!" << endl;
122 help = true;
123 }
124 args.push_back(argv[i]);
125 }
126 }
127 } catch (const std::exception &e) {
128 cout << "Error: " << e.what() << endl;
129 help = true;
130 }
131
132 if ((posy != 3 && posy != 4) || (rosy != 2 && rosy != 4 && rosy != 6)) {
133 cerr << "Error: Invalid symmetry type!" << endl;
134 help = true;
135 }
136
137 int nConstraints = 0;
138 nConstraints += scale > 0 ? 1 : 0;
139 nConstraints += face_count > 0 ? 1 : 0;
140 nConstraints += vertex_count > 0 ? 1 : 0;
141
142 if (nConstraints > 1) {
143 cerr << "Error: Only one of the --scale, --face and --vertices parameters can be used at once!" << endl;
144 help = true;
145 }
146
147 if (args.size() > 1 || help || (!batchOutput.empty() && args.size() == 0)) {
148 cout << "Syntax: " << argv[0] << " [options] <input mesh / point cloud / application state snapshot>" << endl;
149 cout << "Options:" << endl;
150 cout << " -o, --output <output> Writes to the specified PLY/OBJ output file in batch mode" << endl;
151 cout << " -t, --threads <count> Number of threads used for parallel computations" << endl;
152 cout << " -d, --deterministic Prefer (slower) deterministic algorithms" << endl;
153 cout << " -c, --crease <degrees> Dihedral angle threshold for creases" << endl;
154 cout << " -S, --smooth <iter> Number of smoothing & ray tracing reprojection steps (default: 2)" << endl;
155 cout << " -D, --dominant Generate a tri/quad dominant mesh instead of a pure tri/quad mesh" << endl;
156 cout << " -i, --intrinsic Intrinsic mode (extrinsic is the default)" << endl;
157 cout << " -b, --boundaries Align to boundaries (only applies when the mesh is not closed)" << endl;
158 cout << " -r, --rosy <number> Specifies the orientation symmetry type (2, 4, or 6)" << endl;
159 cout << " -p, --posy <number> Specifies the position symmetry type (4 or 6)" << endl;
160 cout << " -s, --scale <scale> Desired world space length of edges in the output" << endl;
161 cout << " -f, --faces <count> Desired face count of the output mesh" << endl;
162 cout << " -v, --vertices <count> Desired vertex count of the output mesh" << endl;
163 cout << " -C, --compat Compatibility mode to load snapshots from old software versions" << endl;
164 cout << " -k, --knn <count> Point cloud mode: number of adjacent points to consider" << endl;
165 cout << " -F, --fullscreen Open a full-screen window" << endl;
166 cout << " -h, --help Display this message" << endl;
167 return -1;
168 }
169
170 if (args.size() == 0)
171 cout << "Running in GUI mode, start with -h for instructions on batch mode." << endl;
172
173 tbb::task_scheduler_init init(nprocs == -1 ? tbb::task_scheduler_init::automatic : nprocs);
174
175 if (!batchOutput.empty() && args.size() == 1) {
176 try {
177 batch_process(args[0], batchOutput, rosy, posy, scale, face_count,
178 vertex_count, crease_angle, extrinsic,
179 align_to_boundaries, smooth_iter, knn_points,
180 !dominant, deterministic);
181 return 0;
182 } catch (const std::exception &e) {
183 cerr << "Caught runtime error : " << e.what() << endl;
184 return -1;
185 }
186 }
187
188 try {
189 nanogui::init();
190
191 #if defined(__APPLE__)
192 if (launched_from_finder)
193 nanogui::chdir_to_bundle_parent();
194 #endif
195
196 {
197 nanogui::ref<Viewer> viewer = new Viewer(fullscreen, deterministic);
198 viewer->setVisible(true);
199
200 if (args.size() == 1) {
201 if (Serializer::isSerializedFile(args[0])) {
202 viewer->loadState(args[0], compat);
203 } else {
204 viewer->loadInput(args[0], crease_angle,
205 scale, face_count, vertex_count,
206 rosy, posy, knn_points);
207 viewer->setExtrinsic(extrinsic);
208 }
209 }
210
211 nanogui::mainloop();
212 }
213
214 nanogui::shutdown();
215 } catch (const std::runtime_error &e) {
216 std::string error_msg = std::string("Caught a fatal error: ") + std::string(e.what());
217 #if defined(_WIN32)
218 MessageBoxA(nullptr, error_msg.c_str(), NULL, MB_ICONERROR | MB_OK);
219 #else
220 std::cerr << error_msg << endl;
221 #endif
222 return -1;
223 }
224
225 return EXIT_SUCCESS;
226 }
227