CARLA
Simplify.h
Go to the documentation of this file.
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 
31 struct vector3
32 {
33  double x, y, z;
34 };
35 
36 struct 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  }
243  static vec3f normalize(vec3f a);
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 
267 vec3f 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 
284 vec3f 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 
294 double min(double v1, double v2)
295 {
296  return fmin(v1, v2);
297 }
298 
300 {
301 
302 public:
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 
379 namespace Simplify
380 {
381  // Global Variables & Strctures
383  {
385  NORMAL = 2,
386  TEXCOORD = 4,
387  COLOR = 8
388  };
389  struct Triangle
390  {
391  int v[3];
392  double err[4];
393  int deleted, dirty, attr;
395  vec3f uvs[3];
396  int material;
397  };
398  struct Vertex
399  {
401  int tstart, tcount;
403  int border;
404  };
405  struct Ref
406  {
407  int tid, tvertex;
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 ///////////////////////////////////////////
vec3f invert()
Definition: Simplify.h:199
double z
Definition: Simplify.h:38
vec3f normalize(double desired_length=1)
Definition: Simplify.h:227
double vertex_error(SymetricMatrix q, double x, double y, double z)
Definition: Simplify.h:886
SymetricMatrix(double a, double b, double c, double d)
Definition: Simplify.h:326
double operator[](int c) const
Definition: Simplify.h:340
void clamp(double min, double max)
Definition: Simplify.h:176
static int random_number
Definition: Simplify.h:249
vec3f operator*(const double a) const
Definition: Simplify.h:69
static double fn[10]
Definition: odrSpiral.cpp:85
vec3f(const double X, const double Y, const double Z)
Definition: Simplify.h:52
SymetricMatrix & operator+=(const SymetricMatrix &n)
Definition: Simplify.h:360
double y
Definition: Simplify.h:38
vec3f barycentric(const vec3f &p, const vec3f &a, const vec3f &b, const vec3f &c)
Definition: Simplify.h:267
char * trimwhitespace(char *str)
Definition: Simplify.h:931
double x
Definition: Simplify.h:38
vec3f rot_y(double a)
Definition: Simplify.h:168
vec3f operator/(const double a) const
Definition: Simplify.h:110
std::vector< Vertex > vertices
Definition: Simplify.h:414
#define loopj(start_l, end_l)
Definition: Simplify.h:28
vec3f(void)
Definition: Simplify.h:40
const SymetricMatrix operator+(const SymetricMatrix &n) const
Definition: Simplify.h:352
vec3f operator*(const vec3f a) const
Definition: Simplify.h:74
std::vector< Triangle > triangles
Definition: Simplify.h:413
vec3f operator+=(const vec3f &a) const
Definition: Simplify.h:64
double err[4]
Definition: Simplify.h:392
vec3f rot_x(double a)
Definition: Simplify.h:160
vec3f operator+(const vec3f &a) const
Definition: Simplify.h:59
vec3f operator-(const vec3f &a) const
Definition: Simplify.h:105
double random_double_01(double a)
Definition: Simplify.h:251
#define loopk(start_l, end_l)
Definition: Simplify.h:29
double min(double v1, double v2)
Definition: Simplify.h:294
vec3f v3() const
Definition: Simplify.h:79
vec3f operator=(const vector3 a)
Definition: Simplify.h:84
void load_obj(const char *filename, bool process_uv=false)
Definition: Simplify.h:954
double length() const
Definition: Simplify.h:222
double y
Definition: Simplify.h:33
Definition: Simplify.h:36
vec3f(vector3 a)
Definition: Simplify.h:45
void update_uvs(int i0, const Vertex &v, const vec3f &p, std::vector< int > &deleted)
Definition: Simplify.h:685
vec3f frac()
Definition: Simplify.h:206
double calculate_error(int id_v1, int id_v2, vec3f &p_result)
Definition: Simplify.h:893
std::vector< Ref > refs
Definition: Simplify.h:415
void simplify_mesh(int target_count, double agressiveness=7, bool verbose=false)
Definition: Simplify.h:430
SymetricMatrix(double c=0)
Definition: Simplify.h:305
SymetricMatrix q
Definition: Simplify.h:402
vec3f cross(const vec3f &a, const vec3f &b)
Definition: Simplify.h:120
double z
Definition: Simplify.h:33
void update_triangles(int i0, Vertex &v, std::vector< int > &deleted, int &deleted_triangles)
Definition: Simplify.h:704
void simplify_mesh_lossless(bool verbose=false)
Definition: Simplify.h:544
vec3f integer()
Definition: Simplify.h:214
vec3f interpolate(const vec3f &p, const vec3f &a, const vec3f &b, const vec3f &c, const vec3f attrs[3])
Definition: Simplify.h:284
double x
Definition: Simplify.h:33
double det(int a11, int a12, int a13, int a21, int a22, int a23, int a31, int a32, int a33)
Definition: Simplify.h:344
bool flipped(vec3f p, int i0, int i1, Vertex &v0, Vertex &v1, std::vector< int > &deleted)
Definition: Simplify.h:648
void update_mesh(int iteration)
Definition: Simplify.h:731
vec3f operator/(const vec3f a) const
Definition: Simplify.h:100
vec3f random01_fxyz()
Definition: Simplify.h:258
vec3f rot_z(double a)
Definition: Simplify.h:191
vec3f operator=(const vec3f a)
Definition: Simplify.h:92
double angle2(const vec3f &v, const vec3f &w)
Definition: Simplify.h:143
double dot(const vec3f &a) const
Definition: Simplify.h:115
double angle(const vec3f &v)
Definition: Simplify.h:128
std::vector< std::string > materials
Definition: Simplify.h:417
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
void write_obj(const char *filename)
Definition: Simplify.h:1112
#define loopi(start_l, end_l)
Definition: Simplify.h:27