CARLA
 
载入中...
搜索中...
未找到
Simplify.h
浏览该文件的文档.
1/////////////////////////////////////////////
2//
3// Mesh Simplification Tutorial
4//
5// (C) by Sven Forstmann in 2014
6//
7// License : MIT
8// http://opensource.org/licenses/MIT
9//
10// https://github.com/sp4cerat/Fast-Quadric-Mesh-Simplification
11//
12// 5/2016: Chris Rorden created minimal version for OSX/Linux/Windows compile
13
14#include <iostream>
15#include <fstream>
16#include <algorithm>
17#include <string.h>
18#include <stdio.h>
19#include <stdlib.h>
20#include <map>
21#include <vector>
22#include <string>
23#include <math.h>
24#include <float.h> //FLT_EPSILON, DBL_EPSILON
25
26#define loopi(start_l, end_l) for (int i = start_l; i < end_l; ++i)
27#define loopi(start_l, end_l) for (int i = start_l; i < end_l; ++i)
28#define loopj(start_l, end_l) for (int j = start_l; j < end_l; ++j)
29#define loopk(start_l, end_l) for (int k = start_l; k < end_l; ++k)
30
31struct vector3
32{
33 double x, y, z;
34};
35
36struct vec3f
37{
38 double x, y, z;
39
40 inline vec3f(void) {}
41
42 // inline vec3f operator =( vector3 a )
43 // { vec3f b ; b.x = a.x; b.y = a.y; b.z = a.z; return b;}
44
45 inline vec3f(vector3 a)
46 {
47 x = a.x;
48 y = a.y;
49 z = a.z;
50 }
51
52 inline vec3f(const double X, const double Y, const double Z)
53 {
54 x = X;
55 y = Y;
56 z = Z;
57 }
58
59 inline vec3f operator+(const vec3f &a) const
60 {
61 return vec3f(x + a.x, y + a.y, z + a.z);
62 }
63
64 inline vec3f operator+=(const vec3f &a) const
65 {
66 return vec3f(x + a.x, y + a.y, z + a.z);
67 }
68
69 inline vec3f operator*(const double a) const
70 {
71 return vec3f(x * a, y * a, z * a);
72 }
73
74 inline vec3f operator*(const vec3f a) const
75 {
76 return vec3f(x * a.x, y * a.y, z * a.z);
77 }
78
79 inline vec3f v3() const
80 {
81 return vec3f(x, y, z);
82 }
83
84 inline vec3f operator=(const vector3 a)
85 {
86 x = a.x;
87 y = a.y;
88 z = a.z;
89 return *this;
90 }
91
92 inline vec3f operator=(const vec3f a)
93 {
94 x = a.x;
95 y = a.y;
96 z = a.z;
97 return *this;
98 }
99
100 inline vec3f operator/(const vec3f a) const
101 {
102 return vec3f(x / a.x, y / a.y, z / a.z);
103 }
104
105 inline vec3f operator-(const vec3f &a) const
106 {
107 return vec3f(x - a.x, y - a.y, z - a.z);
108 }
109
110 inline vec3f operator/(const double a) const
111 {
112 return vec3f(x / a, y / a, z / a);
113 }
114
115 inline double dot(const vec3f &a) const
116 {
117 return a.x * x + a.y * y + a.z * z;
118 }
119
120 inline vec3f cross(const vec3f &a, const vec3f &b)
121 {
122 x = a.y * b.z - a.z * b.y;
123 y = a.z * b.x - a.x * b.z;
124 z = a.x * b.y - a.y * b.x;
125 return *this;
126 }
127
128 inline double angle(const vec3f &v)
129 {
130 vec3f a = v, b = *this;
131 double dot = v.x * x + v.y * y + v.z * z;
132 double len = a.length() * b.length();
133 if (len == 0)
134 len = 0.00001f;
135 double input = dot / len;
136 if (input < -1)
137 input = -1;
138 if (input > 1)
139 input = 1;
140 return (double)acos(input);
141 }
142
143 inline double angle2(const vec3f &v, const vec3f &w)
144 {
145 vec3f a = v, b = *this;
146 double dot = a.x * b.x + a.y * b.y + a.z * b.z;
147 double len = a.length() * b.length();
148 if (len == 0)
149 len = 1;
150
151 vec3f plane;
152 plane.cross(b, w);
153
154 if (plane.x * a.x + plane.y * a.y + plane.z * a.z > 0)
155 return (double)-acos(dot / len);
156
157 return (double)acos(dot / len);
158 }
159
160 inline vec3f rot_x(double a)
161 {
162 double yy = cos(a) * y + sin(a) * z;
163 double zz = cos(a) * z - sin(a) * y;
164 y = yy;
165 z = zz;
166 return *this;
167 }
168 inline vec3f rot_y(double a)
169 {
170 double xx = cos(-a) * x + sin(-a) * z;
171 double zz = cos(-a) * z - sin(-a) * x;
172 x = xx;
173 z = zz;
174 return *this;
175 }
176 inline void clamp(double min, double max)
177 {
178 if (x < min)
179 x = min;
180 if (y < min)
181 y = min;
182 if (z < min)
183 z = min;
184 if (x > max)
185 x = max;
186 if (y > max)
187 y = max;
188 if (z > max)
189 z = max;
190 }
191 inline vec3f rot_z(double a)
192 {
193 double yy = cos(a) * y + sin(a) * x;
194 double xx = cos(a) * x - sin(a) * y;
195 y = yy;
196 x = xx;
197 return *this;
198 }
199 inline vec3f invert()
200 {
201 x = -x;
202 y = -y;
203 z = -z;
204 return *this;
205 }
206 inline vec3f frac()
207 {
208 return vec3f(
209 x - double(int(x)),
210 y - double(int(y)),
211 z - double(int(z)));
212 }
213
214 inline vec3f integer()
215 {
216 return vec3f(
217 double(int(x)),
218 double(int(y)),
219 double(int(z)));
220 }
221
222 inline double length() const
223 {
224 return (double)sqrt(x * x + y * y + z * z);
225 }
226
227 inline vec3f normalize(double desired_length = 1)
228 {
229 double square = sqrt(x * x + y * y + z * z);
230 /*
231 if (square <= 0.00001f )
232 {
233 x=1;y=0;z=0;
234 return *this;
235 }*/
236 // double len = desired_length / square;
237 x /= square;
238 y /= square;
239 z /= square;
240
241 return *this;
242 }
244
245 static void random_init();
246 static double random_double();
247 static vec3f random();
248
249 static int random_number;
250
251 double random_double_01(double a)
252 {
253 double rnf = a * 14.434252 + a * 364.2343 + a * 4213.45352 + a * 2341.43255 + a * 254341.43535 + a * 223454341.3523534245 + 23453.423412;
254 int rni = ((int)rnf) % 100000;
255 return double(rni) / (100000.0f - 1.0f);
256 }
257
259 {
260 x = (double)random_double_01(x);
261 y = (double)random_double_01(y);
262 z = (double)random_double_01(z);
263 return *this;
264 }
265};
266
267vec3f barycentric(const vec3f &p, const vec3f &a, const vec3f &b, const vec3f &c)
268{
269 vec3f v0 = b - a;
270 vec3f v1 = c - a;
271 vec3f v2 = p - a;
272 double d00 = v0.dot(v0);
273 double d01 = v0.dot(v1);
274 double d11 = v1.dot(v1);
275 double d20 = v2.dot(v0);
276 double d21 = v2.dot(v1);
277 double denom = d00 * d11 - d01 * d01;
278 double v = (d11 * d20 - d01 * d21) / denom;
279 double w = (d00 * d21 - d01 * d20) / denom;
280 double u = 1.0 - v - w;
281 return vec3f(u, v, w);
282}
283
284vec3f interpolate(const vec3f &p, const vec3f &a, const vec3f &b, const vec3f &c, const vec3f attrs[3])
285{
286 vec3f bary = barycentric(p, a, b, c);
287 vec3f out = vec3f(0, 0, 0);
288 out = out + attrs[0] * bary.x;
289 out = out + attrs[1] * bary.y;
290 out = out + attrs[2] * bary.z;
291 return out;
292}
293
294double min(double v1, double v2)
295{
296 return fmin(v1, v2);
297}
298
300{
301
302public:
303 // Constructor
304
305 SymetricMatrix(double c = 0) { loopi(0, 10) m[i] = c; }
306
307 SymetricMatrix(double m11, double m12, double m13, double m14,
308 double m22, double m23, double m24,
309 double m33, double m34,
310 double m44)
311 {
312 m[0] = m11;
313 m[1] = m12;
314 m[2] = m13;
315 m[3] = m14;
316 m[4] = m22;
317 m[5] = m23;
318 m[6] = m24;
319 m[7] = m33;
320 m[8] = m34;
321 m[9] = m44;
322 }
323
324 // Make plane
325
326 SymetricMatrix(double a, double b, double c, double d)
327 {
328 m[0] = a * a;
329 m[1] = a * b;
330 m[2] = a * c;
331 m[3] = a * d;
332 m[4] = b * b;
333 m[5] = b * c;
334 m[6] = b * d;
335 m[7] = c * c;
336 m[8] = c * d;
337 m[9] = d * d;
338 }
339
340 double operator[](int c) const { return m[c]; }
341
342 // Determinant
343
344 double det(int a11, int a12, int a13,
345 int a21, int a22, int a23,
346 int a31, int a32, int a33)
347 {
348 double det = m[a11] * m[a22] * m[a33] + m[a13] * m[a21] * m[a32] + m[a12] * m[a23] * m[a31] - m[a13] * m[a22] * m[a31] - m[a11] * m[a23] * m[a32] - m[a12] * m[a21] * m[a33];
349 return det;
350 }
351
353 {
354 return SymetricMatrix(m[0] + n[0], m[1] + n[1], m[2] + n[2], m[3] + n[3],
355 m[4] + n[4], m[5] + n[5], m[6] + n[6],
356 m[7] + n[7], m[8] + n[8],
357 m[9] + n[9]);
358 }
359
361 {
362 m[0] += n[0];
363 m[1] += n[1];
364 m[2] += n[2];
365 m[3] += n[3];
366 m[4] += n[4];
367 m[5] += n[5];
368 m[6] += n[6];
369 m[7] += n[7];
370 m[8] += n[8];
371 m[9] += n[9];
372 return *this;
373 }
374
375 double m[10];
376};
377///////////////////////////////////////////
378
379namespace Simplify
380{
381 // Global Variables & Strctures
383 {
387 COLOR = 8
388 };
389 struct Triangle
390 {
391 int v[3];
392 double err[4];
397 };
405 struct Ref
406 {
408 };
409
411 {
412 public:
413 std::vector<Triangle> triangles;
414 std::vector<Vertex> vertices;
415 std::vector<Ref> refs;
416 std::string mtllib;
417 std::vector<std::string> materials;
418
419 // Helper functions
420
421 //
422 // Main simplification function
423 //
424 // target_count : target nr. of triangles
425 // agressiveness : sharpness to increase the threshold.
426 // 5..8 are good numbers
427 // more iterations yield higher quality
428 //
429
430 void simplify_mesh(int target_count, double agressiveness = 7, bool verbose = false)
431 {
432 // init
433 loopi(0, triangles.size())
434 {
435 triangles[i].deleted = 0;
436 }
437
438 // main iteration loop
439 int deleted_triangles = 0;
440 std::vector<int> deleted0, deleted1;
441 int triangle_count = triangles.size();
442 // int iteration = 0;
443 // loop(iteration,0,100)
444 for (int iteration = 0; iteration < 100; iteration++)
445 {
446 if (triangle_count - deleted_triangles <= target_count)
447 break;
448
449 // update mesh once in a while
450 if (iteration % 5 == 0)
451 {
452 update_mesh(iteration);
453 }
454
455 // clear dirty flag
456 loopi(0, triangles.size()) triangles[i].dirty = 0;
457
458 //
459 // All triangles with edges below the threshold will be removed
460 //
461 // The following numbers works well for most models.
462 // If it does not, try to adjust the 3 parameters
463 //
464 double threshold = 0.000000001 * pow(double(iteration + 3), agressiveness);
465
466 // target number of triangles reached ? Then break
467 if ((verbose) && (iteration % 5 == 0))
468 {
469 printf("iteration %d - triangles %d threshold %g\n", iteration, triangle_count - deleted_triangles, threshold);
470 }
471
472 // remove vertices & mark deleted triangles
473 loopi(0, triangles.size())
474 {
475 Triangle &t = triangles[i];
476 if (t.err[3] > threshold)
477 continue;
478 if (t.deleted)
479 continue;
480 if (t.dirty)
481 continue;
482
483 loopj(0, 3) if (t.err[j] < threshold)
484 {
485
486 int i0 = t.v[j];
487 Vertex &v0 = vertices[i0];
488 int i1 = t.v[(j + 1) % 3];
489 Vertex &v1 = vertices[i1];
490 // Border check
491 if (v0.border || v1.border)
492 continue;
493
494 // Compute vertex to collapse to
495 vec3f p;
496 calculate_error(i0, i1, p);
497 deleted0.resize(v0.tcount); // normals temporarily
498 deleted1.resize(v1.tcount); // normals temporarily
499 // don't remove if flipped
500 if (flipped(p, i0, i1, v0, v1, deleted0))
501 continue;
502
503 if (flipped(p, i1, i0, v1, v0, deleted1))
504 continue;
505
506 if ((t.attr & TEXCOORD) == TEXCOORD)
507 {
508 update_uvs(i0, v0, p, deleted0);
509 update_uvs(i0, v1, p, deleted1);
510 }
511
512 // not flipped, so remove edge
513 v0.p = p;
514 v0.q = v1.q + v0.q;
515 int tstart = refs.size();
516
517 update_triangles(i0, v0, deleted0, deleted_triangles);
518 update_triangles(i0, v1, deleted1, deleted_triangles);
519
520 int tcount = refs.size() - tstart;
521
522 if (tcount <= v0.tcount)
523 {
524 // save ram
525 if (tcount)
526 memcpy(&refs[v0.tstart], &refs[tstart], tcount * sizeof(Ref));
527 }
528 else
529 // append
530 v0.tstart = tstart;
531
532 v0.tcount = tcount;
533 break;
534 }
535 // done?
536 if (triangle_count - deleted_triangles <= target_count)
537 break;
538 }
539 }
540 // clean up mesh
541 compact_mesh();
542 } // simplify_mesh()
543
544 void simplify_mesh_lossless(bool verbose = false)
545 {
546 // init
547 loopi(0, triangles.size()) triangles[i].deleted = 0;
548
549 // main iteration loop
550 int deleted_triangles = 0;
551 std::vector<int> deleted0, deleted1;
552
553 // int iteration = 0;
554 // loop(iteration,0,100)
555 for (int iteration = 0; iteration < 9999; iteration++)
556 {
557 // update mesh constantly
558 update_mesh(iteration);
559 // clear dirty flag
560 loopi(0, triangles.size()) triangles[i].dirty = 0;
561 //
562 // All triangles with edges below the threshold will be removed
563 //
564 // The following numbers works well for most models.
565 // If it does not, try to adjust the 3 parameters
566 //
567 double threshold = DBL_EPSILON; // 1.0E-3 EPS;
568 if (verbose)
569 {
570 printf("lossless iteration %d\n", iteration);
571 }
572
573 // remove vertices & mark deleted triangles
574 loopi(0, triangles.size())
575 {
576 Triangle &t = triangles[i];
577 if (t.err[3] > threshold)
578 continue;
579 if (t.deleted)
580 continue;
581 if (t.dirty)
582 continue;
583
584 loopj(0, 3) if (t.err[j] < threshold)
585 {
586 int i0 = t.v[j];
587 Vertex &v0 = vertices[i0];
588 int i1 = t.v[(j + 1) % 3];
589 Vertex &v1 = vertices[i1];
590
591 // Border check
592 if (v0.border != v1.border)
593 continue;
594
595 // Compute vertex to collapse to
596 vec3f p;
597 calculate_error(i0, i1, p);
598
599 deleted0.resize(v0.tcount); // normals temporarily
600 deleted1.resize(v1.tcount); // normals temporarily
601
602 // don't remove if flipped
603 if (flipped(p, i0, i1, v0, v1, deleted0))
604 continue;
605 if (flipped(p, i1, i0, v1, v0, deleted1))
606 continue;
607
608 if ((t.attr & TEXCOORD) == TEXCOORD)
609 {
610 update_uvs(i0, v0, p, deleted0);
611 update_uvs(i0, v1, p, deleted1);
612 }
613
614 // not flipped, so remove edge
615 v0.p = p;
616 v0.q = v1.q + v0.q;
617 int tstart = refs.size();
618
619 update_triangles(i0, v0, deleted0, deleted_triangles);
620 update_triangles(i0, v1, deleted1, deleted_triangles);
621
622 int tcount = refs.size() - tstart;
623
624 if (tcount <= v0.tcount)
625 {
626 // save ram
627 if (tcount)
628 memcpy(&refs[v0.tstart], &refs[tstart], tcount * sizeof(Ref));
629 }
630 else
631 // append
632 v0.tstart = tstart;
633
634 v0.tcount = tcount;
635 break;
636 }
637 }
638 if (deleted_triangles <= 0)
639 break;
640 deleted_triangles = 0;
641 } // for each iteration
642 // clean up mesh
643 compact_mesh();
644 } // simplify_mesh_lossless()
645
646 // Check if a triangle flips when this edge is removed
647
648 bool flipped(vec3f p, int i0, int i1, Vertex &v0, Vertex &v1, std::vector<int> &deleted)
649 {
650
651 loopk(0, v0.tcount)
652 {
653 Triangle &t = triangles[refs[v0.tstart + k].tid];
654 if (t.deleted)
655 continue;
656
657 int s = refs[v0.tstart + k].tvertex;
658 int id1 = t.v[(s + 1) % 3];
659 int id2 = t.v[(s + 2) % 3];
660
661 if (id1 == i1 || id2 == i1) // delete ?
662 {
663
664 deleted[k] = 1;
665 continue;
666 }
667 vec3f d1 = vertices[id1].p - p;
668 d1.normalize();
669 vec3f d2 = vertices[id2].p - p;
670 d2.normalize();
671 if (fabs(d1.dot(d2)) > 0.999)
672 return true;
673 vec3f n;
674 n.cross(d1, d2);
675 n.normalize();
676 deleted[k] = 0;
677 if (n.dot(t.n) < 0.2)
678 return true;
679 }
680 return false;
681 }
682
683 // update_uvs
684
685 void update_uvs(int i0, const Vertex &v, const vec3f &p, std::vector<int> &deleted)
686 {
687 loopk(0, v.tcount)
688 {
689 Ref &r = refs[v.tstart + k];
690 Triangle &t = triangles[r.tid];
691 if (t.deleted)
692 continue;
693 if (deleted[k])
694 continue;
695 vec3f p1 = vertices[t.v[0]].p;
696 vec3f p2 = vertices[t.v[1]].p;
697 vec3f p3 = vertices[t.v[2]].p;
698 t.uvs[r.tvertex] = interpolate(p, p1, p2, p3, t.uvs);
699 }
700 }
701
702 // Update triangle connections and edge error after a edge is collapsed
703
704 void update_triangles(int i0, Vertex &v, std::vector<int> &deleted, int &deleted_triangles)
705 {
706 vec3f p;
707 loopk(0, v.tcount)
708 {
709 Ref &r = refs[v.tstart + k];
710 Triangle &t = triangles[r.tid];
711 if (t.deleted)
712 continue;
713 if (deleted[k])
714 {
715 t.deleted = 1;
716 deleted_triangles++;
717 continue;
718 }
719 t.v[r.tvertex] = i0;
720 t.dirty = 1;
721 t.err[0] = calculate_error(t.v[0], t.v[1], p);
722 t.err[1] = calculate_error(t.v[1], t.v[2], p);
723 t.err[2] = calculate_error(t.v[2], t.v[0], p);
724 t.err[3] = min(t.err[0], min(t.err[1], t.err[2]));
725 refs.push_back(r);
726 }
727 }
728
729 // compact triangles, compute edge error and build reference list
730
731 void update_mesh(int iteration)
732 {
733 if (iteration > 0) // compact triangles
734 {
735 int dst = 0;
736 loopi(0, triangles.size()) if (!triangles[i].deleted)
737 {
738 triangles[dst++] = triangles[i];
739 }
740 triangles.resize(dst);
741 }
742 //
743
744 // Init Reference ID list
745 loopi(0, vertices.size())
746 {
747 vertices[i].tstart = 0;
748 vertices[i].tcount = 0;
749 }
750
751 loopi(0, triangles.size())
752 {
753 Triangle &t = triangles[i];
754 loopj(0, 3) vertices[t.v[j]].tcount++;
755 }
756 int tstart = 0;
757 loopi(0, vertices.size())
758 {
759 Vertex &v = vertices[i];
760 v.tstart = tstart;
761 tstart += v.tcount;
762 v.tcount = 0;
763 }
764
765 // Write References
766 refs.resize(triangles.size() * 3);
767 loopi(0, triangles.size())
768 {
769 Triangle &t = triangles[i];
770 loopj(0, 3)
771 {
772 Vertex &v = vertices[t.v[j]];
773 refs[v.tstart + v.tcount].tid = i;
774 refs[v.tstart + v.tcount].tvertex = j;
775 v.tcount++;
776 }
777 }
778
779 // Init Quadrics by Plane & Edge Errors
780 //
781 // required at the beginning ( iteration == 0 )
782 // recomputing during the simplification is not required,
783 // but mostly improves the result for closed meshes
784 //
785 if (iteration == 0)
786 {
787 // Identify boundary : vertices[].border=0,1
788
789 std::vector<int> vcount, vids;
790
791 loopi(0, vertices.size())
792 vertices[i]
793 .border = 0;
794
795 loopi(0, vertices.size())
796 {
797 Vertex &v = vertices[i];
798 vcount.clear();
799 vids.clear();
800 loopj(0, v.tcount)
801 {
802 int k = refs[v.tstart + j].tid;
803 Triangle &t = triangles[k];
804 loopk(0, 3)
805 {
806 int ofs = 0, id = t.v[k];
807 while (ofs < vcount.size())
808 {
809 if (vids[ofs] == id)
810 break;
811 ofs++;
812 }
813 if (ofs == vcount.size())
814 {
815 vcount.push_back(1);
816 vids.push_back(id);
817 }
818 else
819 vcount[ofs]++;
820 }
821 }
822 loopj(0, vcount.size()) if (vcount[j] == 1)
823 vertices[vids[j]]
824 .border = 1;
825 }
826 // initialize errors
827 loopi(0, vertices.size())
828 vertices[i]
829 .q = SymetricMatrix(0.0);
830
831 loopi(0, triangles.size())
832 {
833 Triangle &t = triangles[i];
834 vec3f n, p[3];
835 loopj(0, 3) p[j] = vertices[t.v[j]].p;
836 n.cross(p[1] - p[0], p[2] - p[0]);
837 n.normalize();
838 t.n = n;
839 loopj(0, 3) vertices[t.v[j]].q =
840 vertices[t.v[j]].q + SymetricMatrix(n.x, n.y, n.z, -n.dot(p[0]));
841 }
842 loopi(0, triangles.size())
843 {
844 // Calc Edge Error
845 Triangle &t = triangles[i];
846 vec3f p;
847 loopj(0, 3) t.err[j] = calculate_error(t.v[j], t.v[(j + 1) % 3], p);
848 t.err[3] = min(t.err[0], min(t.err[1], t.err[2]));
849 }
850 }
851 }
852
853 // Finally compact mesh before exiting
854
856 {
857 int dst = 0;
858 loopi(0, vertices.size())
859 {
860 vertices[i].tcount = 0;
861 }
862 loopi(0, triangles.size()) if (!triangles[i].deleted)
863 {
864 Triangle &t = triangles[i];
865 triangles[dst++] = t;
866 loopj(0, 3) vertices[t.v[j]].tcount = 1;
867 }
868 triangles.resize(dst);
869 dst = 0;
870 loopi(0, vertices.size()) if (vertices[i].tcount)
871 {
872 vertices[i].tstart = dst;
873 vertices[dst].p = vertices[i].p;
874 dst++;
875 }
876 loopi(0, triangles.size())
877 {
878 Triangle &t = triangles[i];
879 loopj(0, 3) t.v[j] = vertices[t.v[j]].tstart;
880 }
881 vertices.resize(dst);
882 }
883
884 // Error between vertex and Quadric
885
886 double vertex_error(SymetricMatrix q, double x, double y, double z)
887 {
888 return q[0] * x * x + 2 * q[1] * x * y + 2 * q[2] * x * z + 2 * q[3] * x + q[4] * y * y + 2 * q[5] * y * z + 2 * q[6] * y + q[7] * z * z + 2 * q[8] * z + q[9];
889 }
890
891 // Error for one edge
892
893 double calculate_error(int id_v1, int id_v2, vec3f &p_result)
894 {
895 // compute interpolated vertex
896
897 SymetricMatrix q = vertices[id_v1].q + vertices[id_v2].q;
898 bool border = vertices[id_v1].border & vertices[id_v2].border;
899 double error = 0;
900 double det = q.det(0, 1, 2, 1, 4, 5, 2, 5, 7);
901 if (det != 0 && !border)
902 {
903
904 // q_delta is invertible
905 p_result.x = -1 / det * (q.det(1, 2, 3, 4, 5, 6, 5, 7, 8)); // vx = A41/det(q_delta)
906 p_result.y = 1 / det * (q.det(0, 2, 3, 1, 5, 6, 2, 7, 8)); // vy = A42/det(q_delta)
907 p_result.z = -1 / det * (q.det(0, 1, 3, 1, 4, 6, 2, 5, 8)); // vz = A43/det(q_delta)
908
909 error = vertex_error(q, p_result.x, p_result.y, p_result.z);
910 }
911 else
912 {
913 // det = 0 -> try to find best result
914 vec3f p1 = vertices[id_v1].p;
915 vec3f p2 = vertices[id_v2].p;
916 vec3f p3 = (p1 + p2) / 2;
917 double error1 = vertex_error(q, p1.x, p1.y, p1.z);
918 double error2 = vertex_error(q, p2.x, p2.y, p2.z);
919 double error3 = vertex_error(q, p3.x, p3.y, p3.z);
920 error = min(error1, min(error2, error3));
921 if (error1 == error)
922 p_result = p1;
923 if (error2 == error)
924 p_result = p2;
925 if (error3 == error)
926 p_result = p3;
927 }
928 return error;
929 }
930
931 char *trimwhitespace(char *str)
932 {
933 char *end;
934
935 // Trim leading space
936 while (isspace((unsigned char)*str))
937 str++;
938
939 if (*str == 0) // All spaces?
940 return str;
941
942 // Trim trailing space
943 end = str + strlen(str) - 1;
944 while (end > str && isspace((unsigned char)*end))
945 end--;
946
947 // Write new null terminator
948 *(end + 1) = 0;
949
950 return str;
951 }
952
953 // Option : Load OBJ
954 void load_obj(const char *filename, bool process_uv = false)
955 {
956 vertices.clear();
957 triangles.clear();
958 // printf ( "Loading Objects %s ... \n",filename);
959 FILE *fn;
960 if (filename == NULL)
961 return;
962 if ((char)filename[0] == 0)
963 return;
964 if ((fn = fopen(filename, "rb")) == NULL)
965 {
966 printf("File %s not found!\n", filename);
967 return;
968 }
969 char line[1000];
970 memset(line, 0, 1000);
971 int vertex_cnt = 0;
972 int material = -1;
973 std::map<std::string, int> material_map;
974 std::vector<vec3f> uvs;
975 std::vector<std::vector<int>> uvMap;
976
977 while (fgets(line, 1000, fn) != NULL)
978 {
979 Vertex v;
980 vec3f uv;
981
982 if (strncmp(line, "mtllib", 6) == 0)
983 {
984 mtllib = trimwhitespace(&line[7]);
985 }
986 if (strncmp(line, "usemtl", 6) == 0)
987 {
988 std::string usemtl = trimwhitespace(&line[7]);
989 if (material_map.find(usemtl) == material_map.end())
990 {
991 material_map[usemtl] = materials.size();
992 materials.push_back(usemtl);
993 }
994 material = material_map[usemtl];
995 }
996
997 if (line[0] == 'v' && line[1] == 't')
998 {
999 if (line[2] == ' ')
1000 if (sscanf(line, "vt %lf %lf",
1001 &uv.x, &uv.y) == 2)
1002 {
1003 uv.z = 0;
1004 uvs.push_back(uv);
1005 }
1006 else if (sscanf(line, "vt %lf %lf %lf",
1007 &uv.x, &uv.y, &uv.z) == 3)
1008 {
1009 uvs.push_back(uv);
1010 }
1011 }
1012 else if (line[0] == 'v')
1013 {
1014 if (line[1] == ' ')
1015 if (sscanf(line, "v %lf %lf %lf",
1016 &v.p.x, &v.p.y, &v.p.z) == 3)
1017 {
1018 vertices.push_back(v);
1019 }
1020 }
1021 int integers[9];
1022 if (line[0] == 'f')
1023 {
1024 Triangle t;
1025 bool tri_ok = false;
1026 bool has_uv = false;
1027
1028 if (sscanf(line, "f %d %d %d",
1029 &integers[0], &integers[1], &integers[2]) == 3)
1030 {
1031 tri_ok = true;
1032 }
1033 else if (sscanf(line, "f %d// %d// %d//",
1034 &integers[0], &integers[1], &integers[2]) == 3)
1035 {
1036 tri_ok = true;
1037 }
1038 else if (sscanf(line, "f %d//%d %d//%d %d//%d",
1039 &integers[0], &integers[3],
1040 &integers[1], &integers[4],
1041 &integers[2], &integers[5]) == 6)
1042 {
1043 tri_ok = true;
1044 }
1045 else if (sscanf(line, "f %d/%d/%d %d/%d/%d %d/%d/%d",
1046 &integers[0], &integers[6], &integers[3],
1047 &integers[1], &integers[7], &integers[4],
1048 &integers[2], &integers[8], &integers[5]) == 9)
1049 {
1050 tri_ok = true;
1051 has_uv = true;
1052 }
1053 else // Add Support for v/vt only meshes
1054 if (sscanf(line, "f %d/%d %d/%d %d/%d",
1055 &integers[0], &integers[6],
1056 &integers[1], &integers[7],
1057 &integers[2], &integers[8]) == 6)
1058 {
1059 tri_ok = true;
1060 has_uv = true;
1061 }
1062 else
1063 {
1064 printf("unrecognized sequence\n");
1065 printf("%s\n", line);
1066 while (1)
1067 ;
1068 }
1069 if (tri_ok)
1070 {
1071 t.v[0] = integers[0] - 1 - vertex_cnt;
1072 t.v[1] = integers[1] - 1 - vertex_cnt;
1073 t.v[2] = integers[2] - 1 - vertex_cnt;
1074 t.attr = 0;
1075
1076 if (process_uv && has_uv)
1077 {
1078 std::vector<int> indices;
1079 indices.push_back(integers[6] - 1 - vertex_cnt);
1080 indices.push_back(integers[7] - 1 - vertex_cnt);
1081 indices.push_back(integers[8] - 1 - vertex_cnt);
1082 uvMap.push_back(indices);
1083 t.attr |= TEXCOORD;
1084 }
1085
1086 t.material = material;
1087 // geo.triangles.push_back ( tri );
1088 triangles.push_back(t);
1089 // state_before = state;
1090 // state ='f';
1091 }
1092 }
1093 }
1094
1095 if (process_uv && uvs.size())
1096 {
1097 loopi(0, triangles.size())
1098 {
1099 loopj(0, 3)
1100 triangles[i]
1101 .uvs[j] = uvs[uvMap[i][j]];
1102 }
1103 }
1104
1105 fclose(fn);
1106
1107 // printf("load_obj: vertices = %lu, triangles = %lu, uvs = %lu\n", vertices.size(), triangles.size(), uvs.size() );
1108 } // load_obj()
1109
1110 // Optional : Store as OBJ
1111
1112 void write_obj(const char *filename)
1113 {
1114 FILE *file = fopen(filename, "w");
1115 int cur_material = -1;
1116 bool has_uv = (triangles.size() && (triangles[0].attr & TEXCOORD) == TEXCOORD);
1117
1118 if (!file)
1119 {
1120 printf("write_obj: can't write data file \"%s\".\n", filename);
1121 exit(0);
1122 }
1123 if (!mtllib.empty())
1124 {
1125 fprintf(file, "mtllib %s\n", mtllib.c_str());
1126 }
1127 loopi(0, vertices.size())
1128 {
1129 // fprintf(file, "v %lf %lf %lf\n", vertices[i].p.x,vertices[i].p.y,vertices[i].p.z);
1130 fprintf(file, "v %g %g %g\n", vertices[i].p.x, vertices[i].p.y, vertices[i].p.z); // more compact: remove trailing zeros
1131 }
1132 if (has_uv)
1133 {
1134 loopi(0, triangles.size()) if (!triangles[i].deleted)
1135 {
1136 fprintf(file, "vt %g %g\n", triangles[i].uvs[0].x, triangles[i].uvs[0].y);
1137 fprintf(file, "vt %g %g\n", triangles[i].uvs[1].x, triangles[i].uvs[1].y);
1138 fprintf(file, "vt %g %g\n", triangles[i].uvs[2].x, triangles[i].uvs[2].y);
1139 }
1140 }
1141 int uv = 1;
1142 loopi(0, triangles.size()) if (!triangles[i].deleted)
1143 {
1144 if (has_uv)
1145 {
1146 fprintf(file, "f %d/%d %d/%d %d/%d\n", triangles[i].v[0] + 1, uv, triangles[i].v[1] + 1, uv + 1, triangles[i].v[2] + 1, uv + 2);
1147 uv += 3;
1148 }
1149 else
1150 {
1151 fprintf(file, "f %d %d %d\n", triangles[i].v[0] + 1, triangles[i].v[1] + 1, triangles[i].v[2] + 1);
1152 }
1153 // fprintf(file, "f %d// %d// %d//\n", triangles[i].v[0]+1, triangles[i].v[1]+1, triangles[i].v[2]+1); //more compact: remove trailing zeros
1154 }
1155 fclose(file);
1156 }
1157 };
1158
1159}
1160///////////////////////////////////////////
double min(double v1, double v2)
Definition Simplify.h:294
#define loopk(start_l, end_l)
Definition Simplify.h:29
vec3f interpolate(const vec3f &p, const vec3f &a, const vec3f &b, const vec3f &c, const vec3f attrs[3])
Definition Simplify.h:284
#define loopj(start_l, end_l)
Definition Simplify.h:28
#define loopi(start_l, end_l)
Definition Simplify.h:26
vec3f barycentric(const vec3f &p, const vec3f &a, const vec3f &b, const vec3f &c)
Definition Simplify.h:267
void simplify_mesh_lossless(bool verbose=false)
Definition Simplify.h:544
void write_obj(const char *filename)
Definition Simplify.h:1112
void update_mesh(int iteration)
Definition Simplify.h:731
double calculate_error(int id_v1, int id_v2, vec3f &p_result)
Definition Simplify.h:893
bool flipped(vec3f p, int i0, int i1, Vertex &v0, Vertex &v1, std::vector< int > &deleted)
Definition Simplify.h:648
std::vector< std::string > materials
Definition Simplify.h:417
std::vector< Triangle > triangles
Definition Simplify.h:413
std::vector< Vertex > vertices
Definition Simplify.h:414
void update_uvs(int i0, const Vertex &v, const vec3f &p, std::vector< int > &deleted)
Definition Simplify.h:685
char * trimwhitespace(char *str)
Definition Simplify.h:931
std::vector< Ref > refs
Definition Simplify.h:415
void load_obj(const char *filename, bool process_uv=false)
Definition Simplify.h:954
void simplify_mesh(int target_count, double agressiveness=7, bool verbose=false)
Definition Simplify.h:430
void update_triangles(int i0, Vertex &v, std::vector< int > &deleted, int &deleted_triangles)
Definition Simplify.h:704
double vertex_error(SymetricMatrix q, double x, double y, double z)
Definition Simplify.h:886
SymetricMatrix & operator+=(const SymetricMatrix &n)
Definition Simplify.h:360
SymetricMatrix(double a, double b, double c, double d)
Definition Simplify.h:326
double m[10]
Definition Simplify.h:375
double det(int a11, int a12, int a13, int a21, int a22, int a23, int a31, int a32, int a33)
Definition Simplify.h:344
const SymetricMatrix operator+(const SymetricMatrix &n) const
Definition Simplify.h:352
SymetricMatrix(double c=0)
Definition Simplify.h:305
SymetricMatrix(double m11, double m12, double m13, double m14, double m22, double m23, double m24, double m33, double m34, double m44)
Definition Simplify.h:307
double operator[](int c) const
Definition Simplify.h:340
static double fn[10]
Definition odrSpiral.cpp:85
SymetricMatrix q
Definition Simplify.h:402
double y
Definition Simplify.h:38
vec3f rot_y(double a)
Definition Simplify.h:168
vec3f random01_fxyz()
Definition Simplify.h:258
vec3f operator/(const double a) const
Definition Simplify.h:110
static int random_number
Definition Simplify.h:249
vec3f rot_x(double a)
Definition Simplify.h:160
vec3f frac()
Definition Simplify.h:206
vec3f operator*(const double a) const
Definition Simplify.h:69
void clamp(double min, double max)
Definition Simplify.h:176
vec3f operator=(const vec3f a)
Definition Simplify.h:92
static double random_double()
vec3f operator*(const vec3f a) const
Definition Simplify.h:74
vec3f(void)
Definition Simplify.h:40
static void random_init()
double length() const
Definition Simplify.h:222
vec3f integer()
Definition Simplify.h:214
double angle2(const vec3f &v, const vec3f &w)
Definition Simplify.h:143
vec3f invert()
Definition Simplify.h:199
double dot(const vec3f &a) const
Definition Simplify.h:115
vec3f(vector3 a)
Definition Simplify.h:45
vec3f operator/(const vec3f a) const
Definition Simplify.h:100
double z
Definition Simplify.h:38
vec3f normalize(double desired_length=1)
Definition Simplify.h:227
vec3f operator=(const vector3 a)
Definition Simplify.h:84
vec3f rot_z(double a)
Definition Simplify.h:191
static vec3f normalize(vec3f a)
vec3f cross(const vec3f &a, const vec3f &b)
Definition Simplify.h:120
double angle(const vec3f &v)
Definition Simplify.h:128
vec3f operator-(const vec3f &a) const
Definition Simplify.h:105
double random_double_01(double a)
Definition Simplify.h:251
vec3f operator+(const vec3f &a) const
Definition Simplify.h:59
vec3f(const double X, const double Y, const double Z)
Definition Simplify.h:52
static vec3f random()
double x
Definition Simplify.h:38
vec3f v3() const
Definition Simplify.h:79
vec3f operator+=(const vec3f &a) const
Definition Simplify.h:64
double y
Definition Simplify.h:33
double z
Definition Simplify.h:33
double x
Definition Simplify.h:33