26#define loopi(start_l, end_l) for (size_t i = static_cast<size_t>(start_l); i < static_cast<size_t>(end_l); ++i)
27#define loopj(start_l, end_l) for (size_t j = static_cast<size_t>(start_l); j < static_cast<size_t>(end_l); ++j)
28#define loopk(start_l, end_l) for (size_t k = static_cast<size_t>(start_l); k < static_cast<size_t>(end_l); ++k)
50 inline vec3f(
const double X,
const double Y,
const double Z)
115 return a.
x *
x + a.
y *
y + a.
z *
z;
120 x = a.
y * b.
z - a.
z * b.
y;
121 y = a.
z * b.
x - a.
x * b.
z;
122 z = a.
x * b.
y - a.
y * b.
x;
128 vec3f a = v, b = *
this;
129 double dot = v.
x *
x + v.
y *
y + v.
z *
z;
130 double len = a.
length() * b.length();
133 double input =
dot / len;
143 vec3f a = v, b = *
this;
144 double dot = a.
x * b.x + a.
y * b.y + a.
z * b.z;
145 double len = a.
length() * b.length();
152 if (plane.
x * a.
x + plane.
y * a.
y + plane.
z * a.
z > 0)
153 return -acos(
dot / len);
155 return acos(
dot / len);
160 double yy = cos(a) *
y + sin(a) *
z;
161 double zz = cos(a) *
z - sin(a) *
y;
168 double xx = cos(-a) *
x + sin(-a) *
z;
169 double zz = cos(-a) *
z - sin(-a) *
x;
191 double yy = cos(a) *
y + sin(a) *
x;
192 double xx = cos(a) *
x - sin(a) *
y;
222 return sqrt(
x *
x +
y *
y +
z *
z);
227 double square = sqrt(
x *
x +
y *
y +
z *
z);
244 double rnf = a * 14.434252 + a * 364.2343 + a * 4213.45352 + a * 2341.43255 + a * 254341.43535 + a * 223454341.3523534245 + 23453.423412;
245 int rni =
static_cast<int>(rnf) % 100000;
246 return double(rni) / (100000.0f - 1.0f);
263 double d00 = v0.
dot(v0);
264 double d01 = v0.
dot(v1);
265 double d11 = v1.
dot(v1);
266 double d20 = v2.
dot(v0);
267 double d21 = v2.
dot(v1);
268 double denom = d00 * d11 - d01 * d01;
269 double v = (d11 * d20 - d01 * d21) / denom;
270 double w = (d00 * d21 - d01 * d20) / denom;
271 double u = 1.0 - v - w;
272 return vec3f(u, v, w);
279 out = out + attrs[0] * bary.
x;
280 out = out + attrs[1] * bary.
y;
281 out = out + attrs[2] * bary.
z;
285double min(
double v1,
double v2)
299 double m22,
double m23,
double m24,
300 double m33,
double m34,
335 double det(
int a11,
int a12,
int a13,
336 int a21,
int a22,
int a23,
337 int a31,
int a32,
int a33)
339 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];
346 m[4] + n[4],
m[5] + n[5],
m[6] + n[6],
347 m[7] + n[7],
m[8] + n[8],
421 void simplify_mesh(
int target_count,
double agressiveness = 7,
bool verbose =
false)
430 int deleted_triangles = 0;
431 std::vector<int> deleted0, deleted1;
432 int triangle_count =
static_cast<int>(
triangles.size());
435 for (
int iteration = 0; iteration < 100; iteration++)
437 if (triangle_count - deleted_triangles <= target_count)
441 if (iteration % 5 == 0)
455 double threshold = 0.000000001 * pow(
double(iteration + 3), agressiveness);
458 if ((verbose) && (iteration % 5 == 0))
460 printf(
"iteration %d - triangles %d threshold %g\n", iteration, triangle_count - deleted_triangles, threshold);
467 if (t.
err[3] > threshold)
474 loopj(0, 3)
if (t.
err[j] < threshold)
479 int i1 = t.
v[(j + 1) % 3];
488 deleted0.resize(
static_cast<size_t>(v0.
tcount));
489 deleted1.resize(
static_cast<size_t>(v1.
tcount));
491 if (
flipped(p, i0, i1, v0, v1, deleted0))
494 if (
flipped(p, i1, i0, v1, v0, deleted1))
506 int tstart =
static_cast<int>(
refs.size());
511 int tcount =
static_cast<int>(
refs.size()) - tstart;
517 memcpy(&
refs[
static_cast<size_t>(v0.
tstart)], &
refs[
static_cast<size_t>(tstart)],
static_cast<size_t>(tcount) *
sizeof(
Ref));
527 if (triangle_count - deleted_triangles <= target_count)
541 int deleted_triangles = 0;
542 std::vector<int> deleted0, deleted1;
546 for (
int iteration = 0; iteration < 9999; iteration++)
558 double threshold = DBL_EPSILON;
561 printf(
"lossless iteration %d\n", iteration);
568 if (t.
err[3] > threshold)
575 loopj(0, 3)
if (t.
err[j] < threshold)
579 int i1 = t.
v[(j + 1) % 3];
590 deleted0.resize(
static_cast<size_t>(v0.
tcount));
591 deleted1.resize(
static_cast<size_t>(v1.
tcount));
594 if (
flipped(p, i0, i1, v0, v1, deleted0))
596 if (
flipped(p, i1, i0, v1, v0, deleted1))
608 int tstart =
static_cast<int>(
refs.size());
613 int tcount =
static_cast<int>(
refs.size()) - tstart;
619 memcpy(&
refs[
static_cast<size_t>(v0.
tstart)], &
refs[
static_cast<size_t>(tstart)],
static_cast<size_t>(tcount) *
sizeof(
Ref));
629 if (deleted_triangles <= 0)
631 deleted_triangles = 0;
648 int s =
refs[
static_cast<size_t>(v0.
tstart) + k].tvertex;
649 int id1 = t.
v[(s + 1) % 3];
650 int id2 = t.
v[(s + 2) % 3];
652 if (id1 == i1 || id2 == i1)
662 if (fabs(d1.
dot(d2)) > 0.999)
668 if (n.
dot(t.
n) < 0.2)
710 t.v[
static_cast<size_t>(r.
tvertex)] = i0;
715 t.err[3] =
min(t.err[0],
min(t.err[1], t.err[2]));
765 refs[
static_cast<size_t>(v.
tstart + v.
tcount)].tvertex =
static_cast<int>(j);
780 std::vector<int> vcount, vids;
793 int k =
refs[
static_cast<size_t>(v.
tstart) + j].tid;
799 while (ofs < vcount.size())
805 if (ofs == vcount.size())
814 loopj(0, vcount.size())
if (vcount[j] == 1)
815 vertices[
static_cast<size_t>(vids[j])]
828 n.
cross(p[1] - p[0], p[2] - p[0]);
864 vertices[i].tstart =
static_cast<int>(dst);
880 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];
890 bool border =
vertices[
static_cast<size_t>(id_v1)].border &
vertices[
static_cast<size_t>(id_v2)].border;
892 double det = q.
det(0, 1, 2, 1, 4, 5, 2, 5, 7);
893 if (det != 0 && !border)
897 p_result.
x = -1 / det * (q.
det(1, 2, 3, 4, 5, 6, 5, 7, 8));
898 p_result.
y = 1 / det * (q.
det(0, 2, 3, 1, 5, 6, 2, 7, 8));
899 p_result.
z = -1 / det * (q.
det(0, 1, 3, 1, 4, 6, 2, 5, 8));
908 vec3f p3 = (p1 + p2) / 2;
912 error =
min(error1,
min(error2, error3));
928 while (isspace(
static_cast<unsigned char>(*str)))
935 end = str + strlen(str) - 1;
936 while (end > str && isspace(
static_cast<unsigned char>(*end)))
946 void load_obj(
const char *filename,
bool process_uv =
false)
952 if (filename == NULL)
954 if (
static_cast<char>(filename[0]) == 0)
956 if ((
fn = fopen(filename,
"rb")) == NULL)
958 printf(
"File %s not found!\n", filename);
962 memset(line, 0, 1000);
965 std::map<std::string, int> material_map;
966 std::vector<vec3f> uvs;
967 std::vector<std::vector<int>> uvMap;
969 while (fgets(line, 1000,
fn) != NULL)
974 if (strncmp(line,
"mtllib", 6) == 0)
978 if (strncmp(line,
"usemtl", 6) == 0)
981 if (material_map.find(usemtl) == material_map.end())
983 material_map[usemtl] =
static_cast<int>(
materials.size());
986 material = material_map[usemtl];
989 if (line[0] ==
'v' && line[1] ==
't')
993 if (sscanf(line,
"vt %lf %lf",
999 else if (sscanf(line,
"vt %lf %lf %lf",
1000 &uv.
x, &uv.
y, &uv.
z) == 3)
1006 else if (line[0] ==
'v')
1009 if (sscanf(line,
"v %lf %lf %lf",
1010 &v.
p.
x, &v.
p.
y, &v.
p.
z) == 3)
1019 bool tri_ok =
false;
1020 bool has_uv =
false;
1022 if (sscanf(line,
"f %d %d %d",
1023 &integers[0], &integers[1], &integers[2]) == 3)
1027 else if (sscanf(line,
"f %d// %d// %d//",
1028 &integers[0], &integers[1], &integers[2]) == 3)
1032 else if (sscanf(line,
"f %d//%d %d//%d %d//%d",
1033 &integers[0], &integers[3],
1034 &integers[1], &integers[4],
1035 &integers[2], &integers[5]) == 6)
1039 else if (sscanf(line,
"f %d/%d/%d %d/%d/%d %d/%d/%d",
1040 &integers[0], &integers[6], &integers[3],
1041 &integers[1], &integers[7], &integers[4],
1042 &integers[2], &integers[8], &integers[5]) == 9)
1048 if (sscanf(line,
"f %d/%d %d/%d %d/%d",
1049 &integers[0], &integers[6],
1050 &integers[1], &integers[7],
1051 &integers[2], &integers[8]) == 6)
1058 printf(
"unrecognized sequence\n");
1059 printf(
"%s\n", line);
1065 t.
v[0] = integers[0] - 1 - vertex_cnt;
1066 t.
v[1] = integers[1] - 1 - vertex_cnt;
1067 t.
v[2] = integers[2] - 1 - vertex_cnt;
1070 if (process_uv && has_uv)
1072 std::vector<int> indices;
1073 indices.push_back(integers[6] - 1 - vertex_cnt);
1074 indices.push_back(integers[7] - 1 - vertex_cnt);
1075 indices.push_back(integers[8] - 1 - vertex_cnt);
1076 uvMap.push_back(indices);
1089 if (process_uv && uvs.size())
1095 .uvs[j] = uvs[
static_cast<size_t>(uvMap[i][j])];
1108 FILE *file = fopen(filename,
"w");
1113 printf(
"write_obj: can't write data file \"%s\".\n", filename);
1118 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)
bool flipped(vec3f p, int, int i1, Vertex &v0, Vertex &, std::vector< int > &deleted)
void write_obj(const char *filename)
void update_mesh(int iteration)
double calculate_error(int id_v1, int id_v2, vec3f &p_result)
std::vector< std::string > materials
std::vector< Triangle > triangles
std::vector< Vertex > vertices
char * trimwhitespace(char *str)
void update_uvs(int, const Vertex &v, const vec3f &p, std::vector< int > &deleted)
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 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 normalize(double=1)
vec3f(const double X, const double Y, const double Z)
vec3f operator+=(const vec3f &a) const