progmesh.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555
  1. /*
  2. * Progressive Mesh type Polygon Reduction Algorithm
  3. *
  4. * Original version by Stan Melax (c) 1998
  5. * C version by Cloud Wu (c) 2020
  6. *
  7. * The function ProgressiveMesh() takes a model in an "indexed face
  8. * set" sort of way. i.e. Array of vertices and Array of triangles.
  9. * The function then does the polygon reduction algorithm
  10. * internally and reduces the model all the way down to 0
  11. * vertices and then returns the order in which the
  12. * vertices are collapsed and to which neighbor each vertex
  13. * is collapsed to. More specifically the returned "permutation"
  14. * indicates how to reorder your vertices so you can render
  15. * an object by using the first n vertices (for the n
  16. * vertex version). After permuting your vertices, the
  17. * map Array indicates to which vertex each vertex is collapsed to.
  18. */
  19. /*
  20. * The MIT License (MIT)
  21. *
  22. * Copyright (c) 2014 Stan Melax
  23. * Copyright (c) 2020 Cloud Wu
  24. *
  25. * Permission is hereby granted, free of charge, to any person obtaining a copy
  26. * of this software and associated documentation files (the "Software"), to deal
  27. * in the Software without restriction, including without limitation the rights
  28. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  29. * copies of the Software, and to permit persons to whom the Software is
  30. * furnished to do so, subject to the following conditions:
  31. *
  32. * The above copyright notice and this permission notice shall be included in all
  33. * copies or substantial portions of the Software.
  34. *
  35. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  36. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  37. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  38. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  39. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  40. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  41. * SOFTWARE.
  42. */
  43. #include <assert.h>
  44. #include <math.h>
  45. #include <stdlib.h>
  46. #define ARRAY_SIZE 16
  47. struct triangle {
  48. int vertex[3]; // the 3 points (id) that make this tri
  49. float normal[3]; // unit vector orthogonal to this face
  50. };
  51. struct array {
  52. int n;
  53. int cap;
  54. int *buffer;
  55. int tmp[ARRAY_SIZE];
  56. };
  57. struct vertex {
  58. float position[3]; // location of point in euclidean space
  59. int id; // place of vertex in original Array
  60. struct array neighbor; // adjacent vertices
  61. struct array face; // adjacent triangles
  62. float objdist; // cached cost of collapsing edge
  63. int collapse; // candidate vertex (id) for collapse
  64. };
  65. struct mesh {
  66. int n_face;
  67. int n_vertex;
  68. struct vertex *v;
  69. struct triangle *t;
  70. };
  71. // vec3 math
  72. static inline void
  73. vec3_sub(const float v0[3], const float v1[3], float v[3]) {
  74. v[0] = v0[0] - v1[0];
  75. v[1] = v0[1] - v1[1];
  76. v[2] = v0[2] - v1[2];
  77. }
  78. static inline void
  79. vec3_cross(const float a[3], const float b[3], float v[3]) {
  80. v[0] = a[1]*b[2] - a[2]*b[1];
  81. v[1] = a[2]*b[0] - a[0]*b[2];
  82. v[2] = a[0]*b[1] - a[1]*b[0];
  83. }
  84. static inline float
  85. vec3_dot(const float a[3], const float b[3]) {
  86. return a[0]*b[0] + a[1]*b[1] + a[2] * b[2];
  87. }
  88. static inline float
  89. vec3_length(const float v[3]) {
  90. return sqrtf(vec3_dot(v,v));
  91. }
  92. static inline void
  93. vec3_normalize(float v[3]) {
  94. const float invLen = 1.0f/vec3_length(v);
  95. v[0] *= invLen;
  96. v[1] *= invLen;
  97. v[2] *= invLen;
  98. }
  99. // array
  100. static void
  101. array_init(struct array *a) {
  102. a->n = 0;
  103. a->cap = ARRAY_SIZE;
  104. a->buffer = a->tmp;
  105. }
  106. static void
  107. array_deinit(struct array *a) {
  108. if (a->buffer != a->tmp) {
  109. free(a->buffer);
  110. a->buffer = a->tmp;
  111. a->cap = ARRAY_SIZE;
  112. a->n = 0;
  113. }
  114. }
  115. static inline int
  116. array_index(struct array *a, int idx) {
  117. return a->buffer[idx];
  118. }
  119. static void
  120. array_push(struct array *a, int v) {
  121. if (a->n >= a->cap) {
  122. int *old = a->buffer;
  123. a->cap *= 2;
  124. a->buffer = (int *)malloc(a->cap * sizeof(int));
  125. int i;
  126. for (i=0;i<a->n;i++) {
  127. a->buffer[i] = old[i];
  128. }
  129. if (old != a->tmp)
  130. free(old);
  131. }
  132. a->buffer[a->n++] = v;
  133. }
  134. static inline void
  135. array_remove_index(struct array *a, int idx) {
  136. a->buffer[idx] = a->buffer[--a->n];
  137. }
  138. static void
  139. array_remove(struct array *a, int v) {
  140. int i;
  141. for (i=0; i<a->n; i++) {
  142. if (a->buffer[i] == v) {
  143. array_remove_index(a, i);
  144. return;
  145. }
  146. }
  147. }
  148. static inline struct vertex *
  149. Vertex(struct mesh *M, int id) {
  150. return &M->v[id];
  151. }
  152. static inline struct triangle *
  153. Triangle(struct mesh *M, int id) {
  154. return &M->t[id];
  155. }
  156. static inline struct triangle *
  157. Face(struct mesh *M, struct vertex *v, int idx) {
  158. return Triangle(M, array_index(&v->face, idx));
  159. }
  160. static void
  161. AddVertex(struct mesh *M, const float v[3]) {
  162. int id = M->n_vertex++;
  163. struct vertex * tmp = Vertex(M, id);
  164. tmp->position[0] = v[0];
  165. tmp->position[1] = v[1];
  166. tmp->position[2] = v[2];
  167. tmp->id = id;
  168. array_init(&tmp->neighbor);
  169. array_init(&tmp->face);
  170. tmp->objdist = 0;
  171. tmp->collapse = -1;
  172. }
  173. static void
  174. RemoveVertex(struct mesh *M, int id) {
  175. struct vertex * v = Vertex(M, id);
  176. assert(v->id == id);
  177. assert(v->face.n == 0);
  178. int i;
  179. for (i=0;i<v->face.n;i++) {
  180. struct vertex * nv = Vertex(M, array_index(&v->face, i));
  181. array_remove(&nv->neighbor, id);
  182. }
  183. v->id = -1; // invalid vertex id
  184. array_deinit(&v->neighbor);
  185. array_deinit(&v->face);
  186. }
  187. static void
  188. ComputeNormal(struct mesh *M, struct triangle *t) {
  189. struct vertex * v0 = Vertex(M, t->vertex[0]);
  190. struct vertex * v1 = Vertex(M, t->vertex[1]);
  191. struct vertex * v2 = Vertex(M, t->vertex[2]);
  192. float a[3], b[3];
  193. vec3_sub(v1->position, v0->position, a);
  194. vec3_sub(v2->position, v1->position, b);
  195. vec3_cross(a,b, t->normal);
  196. vec3_normalize(t->normal);
  197. }
  198. static void
  199. AddNeighbor(struct mesh *M, int vid, int id) {
  200. struct vertex *v = Vertex(M, vid);
  201. int i;
  202. for (i=0;i<v->neighbor.n;i++) {
  203. if (array_index(&v->neighbor,i) == id)
  204. return;
  205. }
  206. array_push(&v->neighbor, id);
  207. }
  208. #include <stdio.h>
  209. static void
  210. AddTriangle(struct mesh *M, const int v[3]) {
  211. int v0 = v[0];
  212. int v1 = v[1];
  213. int v2 = v[2];
  214. if (v0 == v1 || v0 == v2 || v1 == v2)
  215. return;
  216. assert(v0 < M->n_vertex);
  217. assert(v1 < M->n_vertex);
  218. assert(v2 < M->n_vertex);
  219. int id = M->n_face++;
  220. struct triangle * tmp = Triangle(M, id);
  221. tmp->vertex[0] = v0;
  222. tmp->vertex[1] = v1;
  223. tmp->vertex[2] = v2;
  224. ComputeNormal(M, tmp);
  225. int i;
  226. for(i=0;i<3;i++) {
  227. struct vertex *obj = Vertex(M, v[i]);
  228. array_push(&obj->face, id);
  229. }
  230. AddNeighbor(M, v0, v1);
  231. AddNeighbor(M, v0, v2);
  232. AddNeighbor(M, v1, v0);
  233. AddNeighbor(M, v1, v2);
  234. AddNeighbor(M, v2, v0);
  235. AddNeighbor(M, v2, v1);
  236. }
  237. static int
  238. HasVertex(struct triangle * t, int vid) {
  239. return (t->vertex[0] == vid || t->vertex[1] == vid || t->vertex[2] == vid);
  240. }
  241. static void
  242. RemoveIfNonNeighbor_(struct mesh *M, struct vertex *v, int id) {
  243. int i,j;
  244. for (i=0;i<v->neighbor.n;i++) {
  245. if (array_index(&v->neighbor, i) == id) {
  246. for (j=0;j<v->face.n;j++) {
  247. if (HasVertex(Face(M, v, j), id))
  248. return;
  249. }
  250. // remove from neighbors
  251. array_remove_index(&v->neighbor, i);
  252. return;
  253. }
  254. }
  255. }
  256. static void
  257. RemoveIfNonNeighbor(struct mesh *M, struct vertex *v0, struct vertex *v1) {
  258. if (v0 == NULL || v1 == NULL)
  259. return;
  260. RemoveIfNonNeighbor_(M, v0, v1->id);
  261. RemoveIfNonNeighbor_(M, v1, v0->id);
  262. }
  263. static void
  264. RemoveTriangle(struct mesh *M, int id) {
  265. struct triangle * face = Triangle(M, id);
  266. struct vertex * v[3];
  267. int i;
  268. for (i=0;i<3;i++) {
  269. v[i] = Vertex(M, face->vertex[i]);
  270. if (v[i]->id < 0)
  271. v[i] = NULL;
  272. else {
  273. array_remove(&v[i]->face, id);
  274. }
  275. }
  276. RemoveIfNonNeighbor(M, v[0], v[1]);
  277. RemoveIfNonNeighbor(M, v[1], v[2]);
  278. RemoveIfNonNeighbor(M, v[2], v[0]);
  279. }
  280. static void
  281. ReplaceVertex(struct mesh *M, int faceid, int oldid, int newid) {
  282. struct triangle * face = Triangle(M, faceid);
  283. assert(oldid >=0 && newid >= 0);
  284. assert(HasVertex(face, oldid));
  285. assert(!HasVertex(face, newid));
  286. if(oldid==face->vertex[0]){
  287. face->vertex[0]=newid;
  288. } else if(oldid==face->vertex[1]){
  289. face->vertex[1]=newid;
  290. } else {
  291. face->vertex[2]=newid;
  292. }
  293. struct vertex *vold = Vertex(M, oldid);
  294. struct vertex *vnew = Vertex(M, newid);
  295. array_remove(&vold->face, faceid);
  296. array_push(&vnew->face, faceid);
  297. int i;
  298. for (i = 0; i<3; i++) {
  299. struct vertex *v = Vertex(M, face->vertex[i]);
  300. RemoveIfNonNeighbor(M, vold, v);
  301. }
  302. AddNeighbor(M, face->vertex[0], face->vertex[1]);
  303. AddNeighbor(M, face->vertex[0], face->vertex[2]);
  304. AddNeighbor(M, face->vertex[1], face->vertex[0]);
  305. AddNeighbor(M, face->vertex[1], face->vertex[2]);
  306. AddNeighbor(M, face->vertex[2], face->vertex[0]);
  307. AddNeighbor(M, face->vertex[2], face->vertex[1]);
  308. ComputeNormal(M, face);
  309. }
  310. static void
  311. mesh_init(struct mesh *M, int vert_n, int tri_n) {
  312. M->n_face = 0;
  313. M->n_vertex = 0;
  314. M->v = (struct vertex *)malloc(vert_n * sizeof(struct vertex));
  315. M->t = (struct triangle *)malloc(tri_n * sizeof(struct triangle));
  316. }
  317. static void
  318. mesh_deinit(struct mesh *M) {
  319. free(M->v);
  320. free(M->t);
  321. }
  322. static float
  323. ComputeEdgeCollapseCost(struct mesh *M, struct vertex *u, int vid) {
  324. // if we collapse edge uv by moving u to v then how
  325. // much different will the model change, i.e. how much "error".
  326. // Texture, vertex normal, and border vertex code was removed
  327. // to keep this demo as simple as possible.
  328. // The method of determining cost was designed in order
  329. // to exploit small and coplanar regions for
  330. // effective polygon reduction.
  331. // Is is possible to add some checks here to see if "folds"
  332. // would be generated. i.e. normal of a remaining face gets
  333. // flipped. I never seemed to run into this problem and
  334. // therefore never added code to detect this case.
  335. struct vertex *v = Vertex(M, vid);
  336. float tmp[3];
  337. vec3_sub(v->position, u->position, tmp);
  338. float edgelength = vec3_length(tmp);
  339. float curvature=0;
  340. // find the "sides" triangles that are on the edge uv
  341. struct array sides;
  342. array_init(&sides);
  343. int i,j;
  344. for (i = 0; i<u->face.n; i++) {
  345. if (HasVertex(Face(M, u, i), vid)) {
  346. array_push(&sides, array_index(&u->face, i));
  347. }
  348. }
  349. // use the triangle facing most away from the sides
  350. // to determine our curvature term
  351. for (i = 0; i<u->face.n; i++) {
  352. float mincurv=1; // curve for face i and closer side to it
  353. for (j = 0; j<sides.n; j++) {
  354. float dotprod = vec3_dot(Triangle(M, array_index(&u->face, i))->normal,
  355. Triangle(M, array_index(&sides,j))->normal); // use dot product of face normals.
  356. float t = (1-dotprod)/2.0f;
  357. if (t < mincurv) {
  358. mincurv = t;
  359. }
  360. }
  361. if (mincurv > curvature)
  362. curvature = mincurv;
  363. }
  364. array_deinit(&sides);
  365. // the more coplanar the lower the curvature term
  366. return edgelength * curvature;
  367. }
  368. static void
  369. ComputeEdgeCostAtVertex(struct mesh *M, struct vertex *v) {
  370. // compute the edge collapse cost for all edges that start
  371. // from vertex v. Since we are only interested in reducing
  372. // the object by selecting the min cost edge at each step, we
  373. // only cache the cost of the least cost edge at this vertex
  374. // (in member variable collapse) as well as the value of the
  375. // cost (in member variable objdist).
  376. if (v->neighbor.n == 0) {
  377. // v doesn't have neighbors so it costs nothing to collapse
  378. v->collapse=-1;
  379. v->objdist=-0.01f;
  380. return;
  381. }
  382. v->objdist = 1000000;
  383. v->collapse=-1;
  384. // search all neighboring edges for "least cost" edge
  385. int i;
  386. for (i = 0; i<v->neighbor.n; i++) {
  387. float dist;
  388. dist = ComputeEdgeCollapseCost(M, v, array_index(&v->neighbor, i));
  389. if(dist<v->objdist) {
  390. v->collapse=array_index(&v->neighbor, i); // candidate for edge collapse
  391. v->objdist=dist; // cost of the collapse
  392. }
  393. }
  394. }
  395. static void
  396. ComputeAllEdgeCollapseCosts(struct mesh *M) {
  397. // For all the edges, compute the difference it would make
  398. // to the model if it was collapsed. The least of these
  399. // per vertex is cached in each vertex object.
  400. int i;
  401. for (i = 0; i<M->n_vertex; i++) {
  402. ComputeEdgeCostAtVertex(M, Vertex(M, i));
  403. }
  404. }
  405. static void
  406. Collapse(struct mesh *M, int uid, int vid) {
  407. // Collapse the edge uv by moving vertex u onto v
  408. // Actually remove tris on uv, then update tris that
  409. // have u to have v, and then remove u.
  410. struct vertex *u = Vertex(M, uid);
  411. if(vid < 0) {
  412. // u is a vertex all by itself so just delete it
  413. RemoveVertex(M, uid);
  414. return;
  415. }
  416. struct array tmp;
  417. array_init(&tmp);
  418. int i;
  419. // make tmp a Array of all the neighbors of u
  420. for (i = 0; i<u->neighbor.n; i++) {
  421. array_push(&tmp, array_index(&u->neighbor, i));
  422. }
  423. // delete triangles on edge uv:
  424. {
  425. i = u->face.n;
  426. while (i--) {
  427. if (HasVertex(Face(M, u, i), vid)) {
  428. RemoveTriangle(M, array_index(&u->face, i));
  429. }
  430. }
  431. }
  432. // update remaining triangles to have v instead of u
  433. {
  434. i = u->face.n;
  435. while (i--) {
  436. ReplaceVertex(M, array_index(&u->face, i), uid, vid);
  437. }
  438. }
  439. RemoveVertex(M, uid);
  440. // recompute the edge collapse costs for neighboring vertices
  441. for (i = 0; i<tmp.n; i++) {
  442. ComputeEdgeCostAtVertex(M, Vertex(M, array_index(&tmp, i)));
  443. }
  444. array_deinit(&tmp);
  445. }
  446. static struct vertex *
  447. MinimumCostEdge(struct mesh *M) {
  448. // Find the edge that when collapsed will affect model the least.
  449. // This function actually returns a Vertex, the second vertex
  450. // of the edge (collapse candidate) is stored in the vertex data.
  451. // Serious optimization opportunity here: this function currently
  452. // does a sequential search through an unsorted Array :-(
  453. // Our algorithm could be O(n*lg(n)) instead of O(n*n)
  454. int i;
  455. struct vertex *mn = NULL;
  456. for (i = 0; i<M->n_vertex; i++) {
  457. struct vertex *v = Vertex(M, i);
  458. if (v->id >=0) {
  459. if (mn == NULL || v->objdist < mn->objdist) {
  460. mn = v;
  461. }
  462. }
  463. }
  464. return mn;
  465. }
  466. void
  467. ProgressiveMesh(int vert_n, int vert_stride, const float *v, int tri_n, const int *tri, int *map, int *permutation) {
  468. struct mesh M;
  469. mesh_init(&M, vert_n, tri_n);
  470. // put input data into our data structures M
  471. int i;
  472. const char * tmp = (const char *)v;
  473. for (i=0;i<vert_n;i++) {
  474. AddVertex(&M, (const float *) tmp);
  475. tmp += vert_stride;
  476. }
  477. for (i=0;i<tri_n;i++) {
  478. AddTriangle(&M, &tri[i*3]);
  479. }
  480. ComputeAllEdgeCollapseCosts(&M); // cache all edge collapse costs
  481. for (i = vert_n-1; i>=0; i--) {
  482. // get the next vertex to collapse
  483. struct vertex *mn = MinimumCostEdge(&M);
  484. // keep track of this vertex, i.e. the collapse ordering
  485. permutation[mn->id] = i;
  486. // keep track of vertex to which we collapse to
  487. map[i] = mn->collapse;
  488. // Collapse this edge
  489. Collapse(&M, mn->id, mn->collapse);
  490. }
  491. // reorder the map Array based on the collapse ordering
  492. for (i = 0; i<vert_n; i++) {
  493. map[i] = (map[i]==-1)?0:permutation[map[i]];
  494. }
  495. // The caller of this function should reorder their vertices
  496. // according to the returned "permutation".
  497. mesh_deinit(&M);
  498. }