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)
52 inline vec3f(
const double X,
const double Y,
const double Z)
117 return a.
x *
x + a.
y *
y + a.
z *
z;
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;
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();
135 double input =
dot / len;
140 return (
double)acos(input);
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();
154 if (plane.
x * a.
x + plane.
y * a.
y + plane.
z * a.
z > 0)
155 return (
double)-acos(
dot / len);
157 return (
double)acos(
dot / len);
162 double yy = cos(a) *
y + sin(a) *
z;
163 double zz = cos(a) *
z - sin(a) *
y;
170 double xx = cos(-a) *
x + sin(-a) *
z;
171 double zz = cos(-a) *
z - sin(-a) *
x;
193 double yy = cos(a) *
y + sin(a) *
x;
194 double xx = cos(a) *
x - sin(a) *
y;
224 return (
double)sqrt(
x *
x +
y *
y +
z *
z);
229 double square = sqrt(
x *
x +
y *
y +
z *
z);
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);
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);
288 out = out + attrs[0] * bary.
x;
289 out = out + attrs[1] * bary.
y;
290 out = out + attrs[2] * bary.
z;
294double min(
double v1,
double v2)
308 double m22,
double m23,
double m24,
309 double m33,
double m34,
344 double det(
int a11,
int a12,
int a13,
345 int a21,
int a22,
int a23,
346 int a31,
int a32,
int a33)
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];
355 m[4] + n[4],
m[5] + n[5],
m[6] + n[6],
356 m[7] + n[7],
m[8] + n[8],
430 void simplify_mesh(
int target_count,
double agressiveness = 7,
bool verbose =
false)
439 int deleted_triangles = 0;
440 std::vector<int> deleted0, deleted1;
444 for (
int iteration = 0; iteration < 100; iteration++)
446 if (triangle_count - deleted_triangles <= target_count)
450 if (iteration % 5 == 0)
464 double threshold = 0.000000001 * pow(
double(iteration + 3), agressiveness);
467 if ((verbose) && (iteration % 5 == 0))
469 printf(
"iteration %d - triangles %d threshold %g\n", iteration, triangle_count - deleted_triangles, threshold);
476 if (t.
err[3] > threshold)
483 loopj(0, 3)
if (t.
err[j] < threshold)
488 int i1 = t.
v[(j + 1) % 3];
497 deleted0.resize(v0.
tcount);
498 deleted1.resize(v1.
tcount);
500 if (
flipped(p, i0, i1, v0, v1, deleted0))
503 if (
flipped(p, i1, i0, v1, v0, deleted1))
515 int tstart =
refs.size();
520 int tcount =
refs.size() - tstart;
536 if (triangle_count - deleted_triangles <= target_count)
550 int deleted_triangles = 0;
551 std::vector<int> deleted0, deleted1;
555 for (
int iteration = 0; iteration < 9999; iteration++)
567 double threshold = DBL_EPSILON;
570 printf(
"lossless iteration %d\n", iteration);
577 if (t.
err[3] > threshold)
584 loopj(0, 3)
if (t.
err[j] < threshold)
588 int i1 = t.
v[(j + 1) % 3];
599 deleted0.resize(v0.
tcount);
600 deleted1.resize(v1.
tcount);
603 if (
flipped(p, i0, i1, v0, v1, deleted0))
605 if (
flipped(p, i1, i0, v1, v0, deleted1))
617 int tstart =
refs.size();
622 int tcount =
refs.size() - tstart;
638 if (deleted_triangles <= 0)
640 deleted_triangles = 0;
658 int id1 = t.
v[(s + 1) % 3];
659 int id2 = t.
v[(s + 2) % 3];
661 if (id1 == i1 || id2 == i1)
671 if (fabs(d1.
dot(d2)) > 0.999)
677 if (n.
dot(t.
n) < 0.2)
789 std::vector<int> vcount, vids;
806 int ofs = 0,
id = t.
v[k];
807 while (ofs < vcount.size())
813 if (ofs == vcount.size())
822 loopj(0, vcount.size())
if (vcount[j] == 1)
836 n.
cross(p[1] - p[0], p[2] - p[0]);
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];
900 double det = q.
det(0, 1, 2, 1, 4, 5, 2, 5, 7);
901 if (det != 0 && !border)
905 p_result.
x = -1 / det * (q.
det(1, 2, 3, 4, 5, 6, 5, 7, 8));
906 p_result.
y = 1 / det * (q.
det(0, 2, 3, 1, 5, 6, 2, 7, 8));
907 p_result.
z = -1 / det * (q.
det(0, 1, 3, 1, 4, 6, 2, 5, 8));
916 vec3f p3 = (p1 + p2) / 2;
920 error =
min(error1,
min(error2, error3));
936 while (isspace((
unsigned char)*str))
943 end = str + strlen(str) - 1;
944 while (end > str && isspace((
unsigned char)*end))
954 void load_obj(
const char *filename,
bool process_uv =
false)
960 if (filename == NULL)
962 if ((
char)filename[0] == 0)
964 if ((
fn = fopen(filename,
"rb")) == NULL)
966 printf(
"File %s not found!\n", filename);
970 memset(line, 0, 1000);
973 std::map<std::string, int> material_map;
974 std::vector<vec3f> uvs;
975 std::vector<std::vector<int>> uvMap;
977 while (fgets(line, 1000,
fn) != NULL)
982 if (strncmp(line,
"mtllib", 6) == 0)
986 if (strncmp(line,
"usemtl", 6) == 0)
989 if (material_map.find(usemtl) == material_map.end())
994 material = material_map[usemtl];
997 if (line[0] ==
'v' && line[1] ==
't')
1000 if (sscanf(line,
"vt %lf %lf",
1006 else if (sscanf(line,
"vt %lf %lf %lf",
1007 &uv.
x, &uv.
y, &uv.
z) == 3)
1012 else if (line[0] ==
'v')
1015 if (sscanf(line,
"v %lf %lf %lf",
1016 &v.
p.
x, &v.
p.
y, &v.
p.
z) == 3)
1025 bool tri_ok =
false;
1026 bool has_uv =
false;
1028 if (sscanf(line,
"f %d %d %d",
1029 &integers[0], &integers[1], &integers[2]) == 3)
1033 else if (sscanf(line,
"f %d// %d// %d//",
1034 &integers[0], &integers[1], &integers[2]) == 3)
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)
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)
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)
1064 printf(
"unrecognized sequence\n");
1065 printf(
"%s\n", line);
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;
1076 if (process_uv && has_uv)
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);
1095 if (process_uv && uvs.size())
1101 .uvs[j] = uvs[uvMap[i][j]];
1114 FILE *file = fopen(filename,
"w");
1115 int cur_material = -1;
1120 printf(
"write_obj: can't write data file \"%s\".\n", filename);
1125 fprintf(file,
"mtllib %s\n",
mtllib.c_str());
double min(double v1, double v2)
#define loopk(start_l, end_l)
vec3f interpolate(const vec3f &p, const vec3f &a, const vec3f &b, const vec3f &c, const vec3f attrs[3])
#define loopj(start_l, end_l)
#define loopi(start_l, end_l)
vec3f barycentric(const vec3f &p, const vec3f &a, const vec3f &b, const vec3f &c)
void simplify_mesh_lossless(bool verbose=false)
void write_obj(const char *filename)
void update_mesh(int iteration)
double calculate_error(int id_v1, int id_v2, vec3f &p_result)
bool flipped(vec3f p, int i0, int i1, Vertex &v0, Vertex &v1, std::vector< int > &deleted)
std::vector< std::string > materials
std::vector< Triangle > triangles
std::vector< Vertex > vertices
void update_uvs(int i0, const Vertex &v, const vec3f &p, std::vector< int > &deleted)
char * trimwhitespace(char *str)
void load_obj(const char *filename, bool process_uv=false)
void simplify_mesh(int target_count, double agressiveness=7, bool verbose=false)
void update_triangles(int i0, Vertex &v, std::vector< int > &deleted, int &deleted_triangles)
double vertex_error(SymetricMatrix q, double x, double y, double z)
SymetricMatrix & operator+=(const SymetricMatrix &n)
SymetricMatrix(double a, double b, double c, double d)
double det(int a11, int a12, int a13, int a21, int a22, int a23, int a31, int a32, int a33)
const SymetricMatrix operator+(const SymetricMatrix &n) const
SymetricMatrix(double c=0)
SymetricMatrix(double m11, double m12, double m13, double m14, double m22, double m23, double m24, double m33, double m34, double m44)
double operator[](int c) const
vec3f operator/(const double a) const
vec3f operator*(const double a) const
void clamp(double min, double max)
vec3f operator=(const vec3f a)
static double random_double()
vec3f operator*(const vec3f a) const
static void random_init()
double angle2(const vec3f &v, const vec3f &w)
double dot(const vec3f &a) const
vec3f operator/(const vec3f a) const
vec3f normalize(double desired_length=1)
vec3f operator=(const vector3 a)
static vec3f normalize(vec3f a)
vec3f cross(const vec3f &a, const vec3f &b)
double angle(const vec3f &v)
vec3f operator-(const vec3f &a) const
double random_double_01(double a)
vec3f operator+(const vec3f &a) const
vec3f(const double X, const double Y, const double Z)
vec3f operator+=(const vec3f &a) const