par_msquares.h 77 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104
  1. // MSQUARES :: https://github.com/prideout/par
  2. // Converts fp32 grayscale images, or 8-bit color images, into triangles.
  3. //
  4. // For grayscale images, a threshold is specified to determine insideness.
  5. // For color images, an exact color is specified to determine insideness.
  6. // Color images can be r8, rg16, rgb24, or rgba32. For a visual overview of
  7. // the API and all the flags, see:
  8. //
  9. // http://github.prideout.net/marching-squares/
  10. //
  11. // The MIT License
  12. // Copyright (c) 2015 Philip Rideout
  13. #include <stdint.h>
  14. // -----------------------------------------------------------------------------
  15. // BEGIN PUBLIC API
  16. // -----------------------------------------------------------------------------
  17. typedef uint8_t par_byte;
  18. typedef struct par_msquares_meshlist_s par_msquares_meshlist;
  19. // Results of a marching squares operation. Triangles are counter-clockwise.
  20. typedef struct {
  21. float* points; // pointer to XY (or XYZ) vertex coordinates
  22. int npoints; // number of vertex coordinates
  23. uint16_t* triangles; // pointer to 3-tuples of vertex indices
  24. int ntriangles; // number of 3-tuples
  25. int dim; // number of floats per point (either 2 or 3)
  26. uint32_t color; // used only with par_msquares_color_multi
  27. } par_msquares_mesh;
  28. // Polyline boundary extracted from a mesh, composed of one or more chains.
  29. // Counterclockwise chains are solid, clockwise chains are holes. So, when
  30. // serializing to SVG, all chains can be aggregated in a single <path>,
  31. // provided they each terminate with a "Z" and use the default fill rule.
  32. typedef struct {
  33. float* points; // list of XY vertex coordinates
  34. int npoints; // number of vertex coordinates
  35. float** chains; // list of pointers to the start of each chain
  36. uint16_t* lengths; // list of chain lengths
  37. int nchains; // number of chains
  38. } par_msquares_boundary;
  39. // Reverses the "insideness" test.
  40. #define PAR_MSQUARES_INVERT (1 << 0)
  41. // Returns a meshlist with two meshes: one for the inside, one for the outside.
  42. #define PAR_MSQUARES_DUAL (1 << 1)
  43. // Requests that returned meshes have 3-tuple coordinates instead of 2-tuples.
  44. // When using a color-based function, the Z coordinate represents the alpha
  45. // value of the nearest pixel.
  46. #define PAR_MSQUARES_HEIGHTS (1 << 2)
  47. // Applies a step function to the Z coordinates. Requires HEIGHTS and DUAL.
  48. #define PAR_MSQUARES_SNAP (1 << 3)
  49. // Adds extrusion triangles to each mesh other than the lowest mesh. Requires
  50. // the PAR_MSQUARES_HEIGHTS flag to be present.
  51. #define PAR_MSQUARES_CONNECT (1 << 4)
  52. // Enables quick & dirty (not best) simpification of the returned mesh.
  53. #define PAR_MSQUARES_SIMPLIFY (1 << 5)
  54. // Indicates that the "color" argument is ABGR instead of ARGB.
  55. #define PAR_MSQUARES_SWIZZLE (1 << 6)
  56. // Ensures there are no T-junction vertices. (par_msquares_color_multi only)
  57. // Requires the PAR_MSQUARES_SIMPLIFY flag to be disabled.
  58. #define PAR_MSQUARES_CLEAN (1 << 7)
  59. par_msquares_meshlist* par_msquares_grayscale(float const* data, int width,
  60. int height, int cellsize, float threshold, int flags);
  61. par_msquares_meshlist* par_msquares_color(par_byte const* data, int width,
  62. int height, int cellsize, uint32_t color, int bpp, int flags);
  63. par_msquares_mesh const* par_msquares_get_mesh(par_msquares_meshlist*, int n);
  64. int par_msquares_get_count(par_msquares_meshlist*);
  65. void par_msquares_free(par_msquares_meshlist*);
  66. void par_msquares_free_boundary(par_msquares_boundary*);
  67. typedef int (*par_msquares_inside_fn)(int, void*);
  68. typedef float (*par_msquares_height_fn)(float, float, void*);
  69. par_msquares_meshlist* par_msquares_function(int width, int height,
  70. int cellsize, int flags, void* context, par_msquares_inside_fn insidefn,
  71. par_msquares_height_fn heightfn);
  72. par_msquares_meshlist* par_msquares_grayscale_multi(float const* data,
  73. int width, int height, int cellsize, float const* thresholds,
  74. int nthresholds, int flags);
  75. par_msquares_meshlist* par_msquares_color_multi(par_byte const* data, int width,
  76. int height, int cellsize, int bpp, int flags);
  77. par_msquares_boundary* par_msquares_extract_boundary(par_msquares_mesh const* );
  78. #ifndef PAR_HELPERS
  79. #define PAR_HELPERS 1
  80. #define PAR_PI (3.14159265359)
  81. #define PAR_MIN(a, b) (a > b ? b : a)
  82. #define PAR_MAX(a, b) (a > b ? a : b)
  83. #define PAR_CLAMP(v, lo, hi) PAR_MAX(lo, PAR_MIN(hi, v))
  84. #define PAR_MALLOC(T, N) ((T*) malloc(N * sizeof(T)))
  85. #define PAR_CALLOC(T, N) ((T*) calloc(N * sizeof(T), 1))
  86. #define PAR_REALLOC(T, BUF, N) ((T*) realloc(BUF, sizeof(T) * N))
  87. #define PAR_FREE(BUF) free(BUF)
  88. #define PAR_SWAP(T, A, B) { T tmp = B; B = A; A = tmp; }
  89. #define PAR_SQR(a) (a * a)
  90. #endif
  91. // -----------------------------------------------------------------------------
  92. // END PUBLIC API
  93. // -----------------------------------------------------------------------------
  94. #ifdef PAR_MSQUARES_IMPLEMENTATION
  95. #include <stdlib.h>
  96. #include <assert.h>
  97. #include <float.h>
  98. #include <string.h>
  99. typedef struct {
  100. uint16_t* values;
  101. size_t count;
  102. size_t capacity;
  103. } par__uint16list;
  104. typedef struct {
  105. float* points;
  106. int npoints;
  107. uint16_t* triangles;
  108. int ntriangles;
  109. int dim;
  110. uint32_t color;
  111. int nconntriangles;
  112. uint16_t* conntri;
  113. par__uint16list* tjunctions;
  114. } par_msquares__mesh;
  115. struct par_msquares_meshlist_s {
  116. int nmeshes;
  117. par_msquares__mesh** meshes;
  118. };
  119. static int** par_msquares_binary_point_table = 0;
  120. static int** par_msquares_binary_triangle_table = 0;
  121. static int* par_msquares_quaternary_triangle_table[64][4];
  122. static int* par_msquares_quaternary_boundary_table[64][4];
  123. static par_msquares_meshlist* par_msquares__merge(par_msquares_meshlist** lists,
  124. int count, int snap);
  125. static void par_init_tables()
  126. {
  127. char const* BINARY_TABLE =
  128. "0"
  129. "1017"
  130. "1123"
  131. "2023370"
  132. "1756"
  133. "2015560"
  134. "2123756"
  135. "3023035056"
  136. "1345"
  137. "4013034045057"
  138. "2124451"
  139. "3024045057"
  140. "2734467"
  141. "3013034046"
  142. "3124146167"
  143. "2024460";
  144. char const* binary_token = BINARY_TABLE;
  145. par_msquares_binary_point_table = PAR_CALLOC(int*, 16);
  146. par_msquares_binary_triangle_table = PAR_CALLOC(int*, 16);
  147. for (int i = 0; i < 16; i++) {
  148. int ntris = *binary_token - '0';
  149. binary_token++;
  150. par_msquares_binary_triangle_table[i] =
  151. PAR_CALLOC(int, (ntris + 1) * 3);
  152. int* sqrtris = par_msquares_binary_triangle_table[i];
  153. sqrtris[0] = ntris;
  154. int mask = 0;
  155. int* sqrpts = par_msquares_binary_point_table[i] = PAR_CALLOC(int, 7);
  156. sqrpts[0] = 0;
  157. for (int j = 0; j < ntris * 3; j++, binary_token++) {
  158. int midp = *binary_token - '0';
  159. int bit = 1 << midp;
  160. if (!(mask & bit)) {
  161. mask |= bit;
  162. sqrpts[++sqrpts[0]] = midp;
  163. }
  164. sqrtris[j + 1] = midp;
  165. }
  166. }
  167. char const* QUATERNARY_TABLE =
  168. "2024046000"
  169. "3346360301112300"
  170. "3346360301112300"
  171. "3346360301112300"
  172. "3560502523013450"
  173. "2015056212414500"
  174. "4018087785756212313828348450"
  175. "4018087785756212313828348450"
  176. "3560502523013450"
  177. "4018087785756212313828348450"
  178. "2015056212414500"
  179. "4018087785756212313828348450"
  180. "3560502523013450"
  181. "4018087785756212313828348450"
  182. "4018087785756212313828348450"
  183. "2015056212414500"
  184. "3702724745001756"
  185. "2018087212313828348452785756"
  186. "4013034045057112301756"
  187. "4013034045057112301756"
  188. "2023037027347460"
  189. "1701312414616700"
  190. "2018087212313847857568348450"
  191. "2018087212313847857568348450"
  192. "4018087123138028348452785756"
  193. "1701467161262363513450"
  194. "2018087412313883484502785756"
  195. "2018087212313828348452785756"
  196. "4018087123138028348452785756"
  197. "1701467161262363513450"
  198. "2018087212313828348452785756"
  199. "2018087412313883484502785756"
  200. "3702724745001756"
  201. "4013034045057112301756"
  202. "2018087212313828348452785756"
  203. "4013034045057112301756"
  204. "4018087123138028348452785756"
  205. "2018087412313883484502785756"
  206. "1701467161262363513450"
  207. "2018087212313828348452785756"
  208. "2023037027347460"
  209. "2018087212313847857568348450"
  210. "1701312414616700"
  211. "2018087212313847857568348450"
  212. "4018087123138028348452785756"
  213. "2018087212313828348452785756"
  214. "1701467161262363513450"
  215. "2018087412313883484502785756"
  216. "3702724745001756"
  217. "4013034045057112301756"
  218. "4013034045057112301756"
  219. "2018087212313828348452785756"
  220. "4018087123138028348452785756"
  221. "2018087412313883484502785756"
  222. "2018087212313828348452785756"
  223. "1701467161262363513450"
  224. "4018087123138028348452785756"
  225. "2018087212313828348452785756"
  226. "2018087412313883484502785756"
  227. "1701467161262363513450"
  228. "2023037027347460"
  229. "2018087212313847857568348450"
  230. "2018087212313847857568348450"
  231. "1701312414616700";
  232. char const* quaternary_token = QUATERNARY_TABLE;
  233. int* quaternary_values = PAR_CALLOC(int, strlen(QUATERNARY_TABLE));
  234. int* vals = quaternary_values;
  235. for (int i = 0; i < 64; i++) {
  236. int ntris = *quaternary_token++ - '0';
  237. *vals = ntris;
  238. par_msquares_quaternary_triangle_table[i][0] = vals++;
  239. for (int j = 0; j < ntris * 3; j++) {
  240. int pt = *quaternary_token++ - '0';
  241. assert(pt >= 0 && pt < 9);
  242. *vals++ = pt;
  243. }
  244. ntris = *quaternary_token++ - '0';
  245. *vals = ntris;
  246. par_msquares_quaternary_triangle_table[i][1] = vals++;
  247. for (int j = 0; j < ntris * 3; j++) {
  248. int pt = *quaternary_token++ - '0';
  249. assert(pt >= 0 && pt < 9);
  250. *vals++ = pt;
  251. }
  252. ntris = *quaternary_token++ - '0';
  253. *vals = ntris;
  254. par_msquares_quaternary_triangle_table[i][2] = vals++;
  255. for (int j = 0; j < ntris * 3; j++) {
  256. int pt = *quaternary_token++ - '0';
  257. assert(pt >= 0 && pt < 9);
  258. *vals++ = pt;
  259. }
  260. ntris = *quaternary_token++ - '0';
  261. *vals = ntris;
  262. par_msquares_quaternary_triangle_table[i][3] = vals++;
  263. for (int j = 0; j < ntris * 3; j++) {
  264. int pt = *quaternary_token++ - '0';
  265. assert(pt >= 0 && pt < 9);
  266. *vals++ = pt;
  267. }
  268. }
  269. assert(vals == quaternary_values + strlen(QUATERNARY_TABLE));
  270. char const* QUATERNARY_EDGES =
  271. "0000"
  272. "11313100113131001131310013501530"
  273. "115151002188523881258830218852388125883013501530"
  274. "218852388125883011515100218852388125883013501530"
  275. "218852388125883021885238812588301151510015700175"
  276. "2188723881258832788521357131017521357131017513701730"
  277. "11717100218872388127883021887238812788302388702588327885"
  278. "1172713515302188725881027885218872388125883278852388702588327885"
  279. "11727135153021887238812588327885218872588102788515700175"
  280. "213571310175218872388125883278852135713101752388702588327885"
  281. "21887258810278851172713515302188723881258832788513701730"
  282. "21887238812788301171710021887238812788302388702588327885"
  283. "21887238812588327885117271351530218872588102788515700175"
  284. "213571310175213571310175218872388125883278852388702588327885"
  285. "2188725881027885218872388125883278851172713515302388702588327885"
  286. "21887238812588327885218872588102788511727135153013701730"
  287. "2188723881278830218872388127883011717100";
  288. quaternary_token = QUATERNARY_EDGES;
  289. quaternary_values = PAR_CALLOC(int, strlen(QUATERNARY_EDGES));
  290. vals = quaternary_values;
  291. for (int i = 0; i < 64; i++) {
  292. int nedges = *quaternary_token++ - '0';
  293. *vals = nedges;
  294. par_msquares_quaternary_boundary_table[i][0] = vals++;
  295. for (int j = 0; j < nedges * 2; j++) {
  296. int pt = *quaternary_token++ - '0';
  297. assert(pt >= 0 && pt < 9);
  298. *vals++ = pt;
  299. }
  300. nedges = *quaternary_token++ - '0';
  301. *vals = nedges;
  302. par_msquares_quaternary_boundary_table[i][1] = vals++;
  303. for (int j = 0; j < nedges * 2; j++) {
  304. int pt = *quaternary_token++ - '0';
  305. assert(pt >= 0 && pt < 9);
  306. *vals++ = pt;
  307. }
  308. nedges = *quaternary_token++ - '0';
  309. *vals = nedges;
  310. par_msquares_quaternary_boundary_table[i][2] = vals++;
  311. for (int j = 0; j < nedges * 2; j++) {
  312. int pt = *quaternary_token++ - '0';
  313. assert(pt >= 0 && pt < 9);
  314. *vals++ = pt;
  315. }
  316. nedges = *quaternary_token++ - '0';
  317. *vals = nedges;
  318. par_msquares_quaternary_boundary_table[i][3] = vals++;
  319. for (int j = 0; j < nedges * 2; j++) {
  320. int pt = *quaternary_token++ - '0';
  321. assert(pt >= 0 && pt < 9);
  322. *vals++ = pt;
  323. }
  324. }
  325. assert(vals == quaternary_values + strlen(QUATERNARY_EDGES));
  326. }
  327. typedef struct {
  328. float const* data;
  329. float threshold;
  330. float lower_bound;
  331. float upper_bound;
  332. int width;
  333. int height;
  334. } par_gray_context;
  335. static int gray_inside(int location, void* contextptr)
  336. {
  337. par_gray_context* context = (par_gray_context*) contextptr;
  338. return context->data[location] > context->threshold;
  339. }
  340. static int gray_multi_inside(int location, void* contextptr)
  341. {
  342. par_gray_context* context = (par_gray_context*) contextptr;
  343. float val = context->data[location];
  344. float upper = context->upper_bound;
  345. float lower = context->lower_bound;
  346. return val >= lower && val < upper;
  347. }
  348. static float gray_height(float x, float y, void* contextptr)
  349. {
  350. par_gray_context* context = (par_gray_context*) contextptr;
  351. int i = PAR_CLAMP(context->width * x, 0, context->width - 1);
  352. int j = PAR_CLAMP(context->height * y, 0, context->height - 1);
  353. return context->data[i + j * context->width];
  354. }
  355. typedef struct {
  356. par_byte const* data;
  357. par_byte color[4];
  358. int bpp;
  359. int width;
  360. int height;
  361. } par_color_context;
  362. static int color_inside(int location, void* contextptr)
  363. {
  364. par_color_context* context = (par_color_context*) contextptr;
  365. par_byte const* data = context->data + location * context->bpp;
  366. for (int i = 0; i < context->bpp; i++) {
  367. if (data[i] != context->color[i]) {
  368. return 0;
  369. }
  370. }
  371. return 1;
  372. }
  373. static float color_height(float x, float y, void* contextptr)
  374. {
  375. par_color_context* context = (par_color_context*) contextptr;
  376. assert(context->bpp == 4);
  377. int i = PAR_CLAMP(context->width * x, 0, context->width - 1);
  378. int j = PAR_CLAMP(context->height * y, 0, context->height - 1);
  379. int k = i + j * context->width;
  380. return context->data[k * 4 + 3] / 255.0;
  381. }
  382. par_msquares_meshlist* par_msquares_color(par_byte const* data, int width,
  383. int height, int cellsize, uint32_t color, int bpp, int flags)
  384. {
  385. par_color_context context;
  386. context.bpp = bpp;
  387. if (flags & PAR_MSQUARES_SWIZZLE) {
  388. context.color[0] = (color >> 0) & 0xff;
  389. context.color[1] = (color >> 8) & 0xff;
  390. context.color[2] = (color >> 16) & 0xff;
  391. context.color[3] = (color >> 24) & 0xff;
  392. } else {
  393. context.color[0] = (color >> 16) & 0xff;
  394. context.color[1] = (color >> 8) & 0xff;
  395. context.color[2] = (color >> 0) & 0xff;
  396. context.color[3] = (color >> 24) & 0xff;
  397. }
  398. context.data = data;
  399. context.width = width;
  400. context.height = height;
  401. return par_msquares_function(
  402. width, height, cellsize, flags, &context, color_inside, color_height);
  403. }
  404. par_msquares_meshlist* par_msquares_grayscale(float const* data, int width,
  405. int height, int cellsize, float threshold, int flags)
  406. {
  407. par_gray_context context;
  408. context.width = width;
  409. context.height = height;
  410. context.data = data;
  411. context.threshold = threshold;
  412. return par_msquares_function(
  413. width, height, cellsize, flags, &context, gray_inside, gray_height);
  414. }
  415. par_msquares_meshlist* par_msquares_grayscale_multi(float const* data,
  416. int width, int height, int cellsize, float const* thresholds,
  417. int nthresholds, int flags)
  418. {
  419. par_msquares_meshlist* mlists[2];
  420. mlists[0] = PAR_CALLOC(par_msquares_meshlist, 1);
  421. int connect = flags & PAR_MSQUARES_CONNECT;
  422. int snap = flags & PAR_MSQUARES_SNAP;
  423. int heights = flags & PAR_MSQUARES_HEIGHTS;
  424. if (!heights) {
  425. snap = connect = 0;
  426. }
  427. flags &= ~PAR_MSQUARES_INVERT;
  428. flags &= ~PAR_MSQUARES_DUAL;
  429. flags &= ~PAR_MSQUARES_CONNECT;
  430. flags &= ~PAR_MSQUARES_SNAP;
  431. par_gray_context context;
  432. context.width = width;
  433. context.height = height;
  434. context.data = data;
  435. context.lower_bound = -FLT_MAX;
  436. for (int i = 0; i <= nthresholds; i++) {
  437. int mergeconf = i > 0 ? connect : 0;
  438. if (i == nthresholds) {
  439. context.upper_bound = FLT_MAX;
  440. mergeconf |= snap;
  441. } else {
  442. context.upper_bound = thresholds[i];
  443. }
  444. mlists[1] = par_msquares_function(width, height, cellsize, flags,
  445. &context, gray_multi_inside, gray_height);
  446. mlists[0] = par_msquares__merge(mlists, 2, mergeconf);
  447. context.lower_bound = context.upper_bound;
  448. flags |= connect;
  449. }
  450. return mlists[0];
  451. }
  452. par_msquares_mesh const* par_msquares_get_mesh(
  453. par_msquares_meshlist* mlist, int mindex)
  454. {
  455. assert(mlist && mindex < mlist->nmeshes);
  456. return (par_msquares_mesh const*) mlist->meshes[mindex];
  457. }
  458. int par_msquares_get_count(par_msquares_meshlist* mlist)
  459. {
  460. assert(mlist);
  461. return mlist->nmeshes;
  462. }
  463. void par_msquares_free(par_msquares_meshlist* mlist)
  464. {
  465. if (!mlist) {
  466. return;
  467. }
  468. par_msquares__mesh** meshes = mlist->meshes;
  469. for (int i = 0; i < mlist->nmeshes; i++) {
  470. free(meshes[i]->points);
  471. free(meshes[i]->triangles);
  472. free(meshes[i]);
  473. }
  474. free(meshes);
  475. free(mlist);
  476. }
  477. // Combine multiple meshlists by moving mesh pointers, and optionally apply
  478. // a "snap" operation that assigns a single Z value across all verts in each
  479. // mesh. The Z value determined by the mesh's position in the final mesh list.
  480. static par_msquares_meshlist* par_msquares__merge(par_msquares_meshlist** lists,
  481. int count, int snap)
  482. {
  483. par_msquares_meshlist* merged = PAR_CALLOC(par_msquares_meshlist, 1);
  484. merged->nmeshes = 0;
  485. for (int i = 0; i < count; i++) {
  486. merged->nmeshes += lists[i]->nmeshes;
  487. }
  488. merged->meshes = PAR_CALLOC(par_msquares__mesh*, merged->nmeshes);
  489. par_msquares__mesh** pmesh = merged->meshes;
  490. for (int i = 0; i < count; i++) {
  491. par_msquares_meshlist* meshlist = lists[i];
  492. for (int j = 0; j < meshlist->nmeshes; j++) {
  493. *pmesh++ = meshlist->meshes[j];
  494. }
  495. free(meshlist);
  496. }
  497. if (!snap) {
  498. return merged;
  499. }
  500. pmesh = merged->meshes;
  501. float zmin = FLT_MAX;
  502. float zmax = -zmin;
  503. for (int i = 0; i < merged->nmeshes; i++, pmesh++) {
  504. float* pzed = (*pmesh)->points + 2;
  505. for (int j = 0; j < (*pmesh)->npoints; j++, pzed += 3) {
  506. zmin = PAR_MIN(*pzed, zmin);
  507. zmax = PAR_MAX(*pzed, zmax);
  508. }
  509. }
  510. float zextent = zmax - zmin;
  511. pmesh = merged->meshes;
  512. for (int i = 0; i < merged->nmeshes; i++, pmesh++) {
  513. float* pzed = (*pmesh)->points + 2;
  514. float zed = zmin + zextent * i / (merged->nmeshes - 1);
  515. for (int j = 0; j < (*pmesh)->npoints; j++, pzed += 3) {
  516. *pzed = zed;
  517. }
  518. }
  519. if (!(snap & PAR_MSQUARES_CONNECT)) {
  520. return merged;
  521. }
  522. for (int i = 1; i < merged->nmeshes; i++) {
  523. par_msquares__mesh* mesh = merged->meshes[i];
  524. // Find all extrusion points. This is tightly coupled to the
  525. // tessellation code, which generates two "connector" triangles for each
  526. // extruded edge. The first two verts of the second triangle are the
  527. // verts that need to be displaced.
  528. char* markers = PAR_CALLOC(char, mesh->npoints);
  529. int tri = mesh->ntriangles - mesh->nconntriangles;
  530. while (tri < mesh->ntriangles) {
  531. markers[mesh->triangles[tri * 3 + 3]] = 1;
  532. markers[mesh->triangles[tri * 3 + 4]] = 1;
  533. tri += 2;
  534. }
  535. // Displace all extrusion points down to the previous level.
  536. float zed = zmin + zextent * (i - 1) / (merged->nmeshes - 1);
  537. float* pzed = mesh->points + 2;
  538. for (int j = 0; j < mesh->npoints; j++, pzed += 3) {
  539. if (markers[j]) {
  540. *pzed = zed;
  541. }
  542. }
  543. free(markers);
  544. }
  545. return merged;
  546. }
  547. static void par_remove_unreferenced_verts(par_msquares__mesh* mesh)
  548. {
  549. if (mesh->npoints == 0) {
  550. return;
  551. }
  552. char* markers = PAR_CALLOC(char, mesh->npoints);
  553. uint16_t const* ptris = mesh->triangles;
  554. int newnpts = 0;
  555. for (int i = 0; i < mesh->ntriangles * 3; i++, ptris++) {
  556. if (!markers[*ptris]) {
  557. newnpts++;
  558. markers[*ptris] = 1;
  559. }
  560. }
  561. float* newpts = PAR_CALLOC(float, newnpts * mesh->dim);
  562. uint16_t* mapping = PAR_CALLOC(uint16_t, mesh->npoints);
  563. float const* ppts = mesh->points;
  564. float* pnewpts = newpts;
  565. int j = 0;
  566. if (mesh->dim == 3) {
  567. for (int i = 0; i < mesh->npoints; i++, ppts += 3) {
  568. if (markers[i]) {
  569. *pnewpts++ = ppts[0];
  570. *pnewpts++ = ppts[1];
  571. *pnewpts++ = ppts[2];
  572. mapping[i] = j++;
  573. }
  574. }
  575. } else {
  576. for (int i = 0; i < mesh->npoints; i++, ppts += 2) {
  577. if (markers[i]) {
  578. *pnewpts++ = ppts[0];
  579. *pnewpts++ = ppts[1];
  580. mapping[i] = j++;
  581. }
  582. }
  583. }
  584. free(mesh->points);
  585. free(markers);
  586. mesh->points = newpts;
  587. mesh->npoints = newnpts;
  588. for (int i = 0; i < mesh->ntriangles * 3; i++) {
  589. mesh->triangles[i] = mapping[mesh->triangles[i]];
  590. }
  591. free(mapping);
  592. }
  593. par_msquares_meshlist* par_msquares_function(int width, int height,
  594. int cellsize, int flags, void* context, par_msquares_inside_fn insidefn,
  595. par_msquares_height_fn heightfn)
  596. {
  597. assert(width > 0 && width % cellsize == 0);
  598. assert(height > 0 && height % cellsize == 0);
  599. if (flags & PAR_MSQUARES_DUAL) {
  600. int connect = flags & PAR_MSQUARES_CONNECT;
  601. int snap = flags & PAR_MSQUARES_SNAP;
  602. int heights = flags & PAR_MSQUARES_HEIGHTS;
  603. if (!heights) {
  604. snap = connect = 0;
  605. }
  606. flags ^= PAR_MSQUARES_INVERT;
  607. flags &= ~PAR_MSQUARES_DUAL;
  608. flags &= ~PAR_MSQUARES_CONNECT;
  609. par_msquares_meshlist* m[2];
  610. m[0] = par_msquares_function(width, height, cellsize, flags,
  611. context, insidefn, heightfn);
  612. flags ^= PAR_MSQUARES_INVERT;
  613. if (connect) {
  614. flags |= PAR_MSQUARES_CONNECT;
  615. }
  616. m[1] = par_msquares_function(width, height, cellsize, flags,
  617. context, insidefn, heightfn);
  618. return par_msquares__merge(m, 2, snap | connect);
  619. }
  620. int invert = flags & PAR_MSQUARES_INVERT;
  621. // Create the two code tables if we haven't already. These are tables of
  622. // fixed constants, so it's embarassing that we use dynamic memory
  623. // allocation for them. However it's easy and it's one-time-only.
  624. if (!par_msquares_binary_point_table) {
  625. par_init_tables();
  626. }
  627. // Allocate the meshlist and the first mesh.
  628. par_msquares_meshlist* mlist = PAR_CALLOC(par_msquares_meshlist, 1);
  629. mlist->nmeshes = 1;
  630. mlist->meshes = PAR_CALLOC(par_msquares__mesh*, 1);
  631. mlist->meshes[0] = PAR_CALLOC(par_msquares__mesh, 1);
  632. par_msquares__mesh* mesh = mlist->meshes[0];
  633. mesh->dim = (flags & PAR_MSQUARES_HEIGHTS) ? 3 : 2;
  634. int ncols = width / cellsize;
  635. int nrows = height / cellsize;
  636. // Worst case is four triangles and six verts per cell, so allocate that
  637. // much.
  638. int maxtris = ncols * nrows * 4;
  639. int maxpts = ncols * nrows * 6;
  640. int maxedges = ncols * nrows * 2;
  641. // However, if we include extrusion triangles for boundary edges,
  642. // we need space for another 4 triangles and 4 points per cell.
  643. uint16_t* conntris = 0;
  644. int nconntris = 0;
  645. uint16_t* edgemap = 0;
  646. if (flags & PAR_MSQUARES_CONNECT) {
  647. conntris = PAR_CALLOC(uint16_t, maxedges * 6);
  648. maxtris += maxedges * 2;
  649. maxpts += maxedges * 2;
  650. edgemap = PAR_CALLOC(uint16_t, maxpts);
  651. for (int i = 0; i < maxpts; i++) {
  652. edgemap[i] = 0xffff;
  653. }
  654. }
  655. uint16_t* tris = PAR_CALLOC(uint16_t, maxtris * 3);
  656. int ntris = 0;
  657. float* pts = PAR_CALLOC(float, maxpts * mesh->dim);
  658. int npts = 0;
  659. // The "verts" x/y/z arrays are the 4 corners and 4 midpoints around the
  660. // square, in counter-clockwise order. The origin of "triangle space" is at
  661. // the lower-left, although we expect the image data to be in raster order
  662. // (starts at top-left).
  663. float vertsx[8], vertsy[8];
  664. float normalization = 1.0f / PAR_MAX(width, height);
  665. float normalized_cellsize = cellsize * normalization;
  666. int maxrow = (height - 1) * width;
  667. uint16_t* ptris = tris;
  668. uint16_t* pconntris = conntris;
  669. float* ppts = pts;
  670. uint8_t* prevrowmasks = PAR_CALLOC(uint8_t, ncols);
  671. int* prevrowinds = PAR_CALLOC(int, ncols * 3);
  672. // If simplification is enabled, we need to track all 'F' cells and their
  673. // repsective triangle indices.
  674. uint8_t* simplification_codes = 0;
  675. uint16_t* simplification_tris = 0;
  676. uint8_t* simplification_ntris = 0;
  677. if (flags & PAR_MSQUARES_SIMPLIFY) {
  678. simplification_codes = PAR_CALLOC(uint8_t, nrows * ncols);
  679. simplification_tris = PAR_CALLOC(uint16_t, nrows * ncols);
  680. simplification_ntris = PAR_CALLOC(uint8_t, nrows * ncols);
  681. }
  682. // Do the march!
  683. for (int row = 0; row < nrows; row++) {
  684. vertsx[0] = vertsx[6] = vertsx[7] = 0;
  685. vertsx[1] = vertsx[5] = 0.5 * normalized_cellsize;
  686. vertsx[2] = vertsx[3] = vertsx[4] = normalized_cellsize;
  687. vertsy[0] = vertsy[1] = vertsy[2] = normalized_cellsize * (row + 1);
  688. vertsy[4] = vertsy[5] = vertsy[6] = normalized_cellsize * row;
  689. vertsy[3] = vertsy[7] = normalized_cellsize * (row + 0.5);
  690. int northi = row * cellsize * width;
  691. int southi = PAR_MIN(northi + cellsize * width, maxrow);
  692. int northwest = invert ^ insidefn(northi, context);
  693. int southwest = invert ^ insidefn(southi, context);
  694. int previnds[8] = {0};
  695. uint8_t prevmask = 0;
  696. for (int col = 0; col < ncols; col++) {
  697. northi += cellsize;
  698. southi += cellsize;
  699. if (col == ncols - 1) {
  700. northi--;
  701. southi--;
  702. }
  703. int northeast = invert ^ insidefn(northi, context);
  704. int southeast = invert ^ insidefn(southi, context);
  705. int code = southwest | (southeast << 1) | (northwest << 2) |
  706. (northeast << 3);
  707. int const* pointspec = par_msquares_binary_point_table[code];
  708. int ptspeclength = *pointspec++;
  709. int currinds[8] = {0};
  710. uint8_t mask = 0;
  711. uint8_t prevrowmask = prevrowmasks[col];
  712. while (ptspeclength--) {
  713. int midp = *pointspec++;
  714. int bit = 1 << midp;
  715. mask |= bit;
  716. // The following six conditionals perform welding to reduce the
  717. // number of vertices. The first three perform welding with the
  718. // cell to the west; the latter three perform welding with the
  719. // cell to the north.
  720. if (bit == 1 && (prevmask & 4)) {
  721. currinds[midp] = previnds[2];
  722. continue;
  723. }
  724. if (bit == 128 && (prevmask & 8)) {
  725. currinds[midp] = previnds[3];
  726. continue;
  727. }
  728. if (bit == 64 && (prevmask & 16)) {
  729. currinds[midp] = previnds[4];
  730. continue;
  731. }
  732. if (bit == 16 && (prevrowmask & 4)) {
  733. currinds[midp] = prevrowinds[col * 3 + 2];
  734. continue;
  735. }
  736. if (bit == 32 && (prevrowmask & 2)) {
  737. currinds[midp] = prevrowinds[col * 3 + 1];
  738. continue;
  739. }
  740. if (bit == 64 && (prevrowmask & 1)) {
  741. currinds[midp] = prevrowinds[col * 3 + 0];
  742. continue;
  743. }
  744. ppts[0] = vertsx[midp];
  745. ppts[1] = vertsy[midp];
  746. // Adjust the midpoints to a more exact crossing point.
  747. if (midp == 1) {
  748. int begin = southi - cellsize / 2;
  749. int previous = 0;
  750. for (int i = 0; i < cellsize; i++) {
  751. int offset = begin + i / 2 * ((i % 2) ? -1 : 1);
  752. int inside = insidefn(offset, context);
  753. if (i > 0 && inside != previous) {
  754. ppts[0] = normalization *
  755. (col * cellsize + offset - southi + cellsize);
  756. break;
  757. }
  758. previous = inside;
  759. }
  760. } else if (midp == 5) {
  761. int begin = northi - cellsize / 2;
  762. int previous = 0;
  763. for (int i = 0; i < cellsize; i++) {
  764. int offset = begin + i / 2 * ((i % 2) ? -1 : 1);
  765. int inside = insidefn(offset, context);
  766. if (i > 0 && inside != previous) {
  767. ppts[0] = normalization *
  768. (col * cellsize + offset - northi + cellsize);
  769. break;
  770. }
  771. previous = inside;
  772. }
  773. } else if (midp == 3) {
  774. int begin = northi + width * cellsize / 2;
  775. int previous = 0;
  776. for (int i = 0; i < cellsize; i++) {
  777. int offset = begin +
  778. width * (i / 2 * ((i % 2) ? -1 : 1));
  779. int inside = insidefn(offset, context);
  780. if (i > 0 && inside != previous) {
  781. ppts[1] = normalization *
  782. (row * cellsize +
  783. (offset - northi) / (float) width);
  784. break;
  785. }
  786. previous = inside;
  787. }
  788. } else if (midp == 7) {
  789. int begin = northi + width * cellsize / 2 - cellsize;
  790. int previous = 0;
  791. for (int i = 0; i < cellsize; i++) {
  792. int offset = begin +
  793. width * (i / 2 * ((i % 2) ? -1 : 1));
  794. int inside = insidefn(offset, context);
  795. if (i > 0 && inside != previous) {
  796. ppts[1] = normalization *
  797. (row * cellsize +
  798. (offset - northi - cellsize) / (float) width);
  799. break;
  800. }
  801. previous = inside;
  802. }
  803. }
  804. if (mesh->dim == 3) {
  805. ppts[2] = heightfn(ppts[0], ppts[1], context);
  806. }
  807. ppts += mesh->dim;
  808. currinds[midp] = npts++;
  809. }
  810. int const* trianglespec = par_msquares_binary_triangle_table[code];
  811. int trispeclength = *trianglespec++;
  812. if (flags & PAR_MSQUARES_SIMPLIFY) {
  813. simplification_codes[ncols * row + col] = code;
  814. simplification_tris[ncols * row + col] = ntris;
  815. simplification_ntris[ncols * row + col] = trispeclength;
  816. }
  817. // Add triangles.
  818. while (trispeclength--) {
  819. int a = *trianglespec++;
  820. int b = *trianglespec++;
  821. int c = *trianglespec++;
  822. *ptris++ = currinds[c];
  823. *ptris++ = currinds[b];
  824. *ptris++ = currinds[a];
  825. ntris++;
  826. }
  827. // Create two extrusion triangles for each boundary edge.
  828. if (flags & PAR_MSQUARES_CONNECT) {
  829. trianglespec = par_msquares_binary_triangle_table[code];
  830. trispeclength = *trianglespec++;
  831. while (trispeclength--) {
  832. int a = *trianglespec++;
  833. int b = *trianglespec++;
  834. int c = *trianglespec++;
  835. int i = currinds[a];
  836. int j = currinds[b];
  837. int k = currinds[c];
  838. int u = 0, v = 0, w = 0;
  839. if ((a % 2) && (b % 2)) {
  840. u = v = 1;
  841. } else if ((a % 2) && (c % 2)) {
  842. u = w = 1;
  843. } else if ((b % 2) && (c % 2)) {
  844. v = w = 1;
  845. } else {
  846. continue;
  847. }
  848. if (u && edgemap[i] == 0xffff) {
  849. for (int d = 0; d < mesh->dim; d++) {
  850. *ppts++ = pts[i * mesh->dim + d];
  851. }
  852. edgemap[i] = npts++;
  853. }
  854. if (v && edgemap[j] == 0xffff) {
  855. for (int d = 0; d < mesh->dim; d++) {
  856. *ppts++ = pts[j * mesh->dim + d];
  857. }
  858. edgemap[j] = npts++;
  859. }
  860. if (w && edgemap[k] == 0xffff) {
  861. for (int d = 0; d < mesh->dim; d++) {
  862. *ppts++ = pts[k * mesh->dim + d];
  863. }
  864. edgemap[k] = npts++;
  865. }
  866. if ((a % 2) && (b % 2)) {
  867. *pconntris++ = i;
  868. *pconntris++ = j;
  869. *pconntris++ = edgemap[j];
  870. *pconntris++ = edgemap[j];
  871. *pconntris++ = edgemap[i];
  872. *pconntris++ = i;
  873. } else if ((a % 2) && (c % 2)) {
  874. *pconntris++ = edgemap[k];
  875. *pconntris++ = k;
  876. *pconntris++ = i;
  877. *pconntris++ = edgemap[i];
  878. *pconntris++ = edgemap[k];
  879. *pconntris++ = i;
  880. } else if ((b % 2) && (c % 2)) {
  881. *pconntris++ = j;
  882. *pconntris++ = k;
  883. *pconntris++ = edgemap[k];
  884. *pconntris++ = edgemap[k];
  885. *pconntris++ = edgemap[j];
  886. *pconntris++ = j;
  887. }
  888. nconntris += 2;
  889. }
  890. }
  891. // Prepare for the next cell.
  892. prevrowmasks[col] = mask;
  893. prevrowinds[col * 3 + 0] = currinds[0];
  894. prevrowinds[col * 3 + 1] = currinds[1];
  895. prevrowinds[col * 3 + 2] = currinds[2];
  896. prevmask = mask;
  897. northwest = northeast;
  898. southwest = southeast;
  899. for (int i = 0; i < 8; i++) {
  900. previnds[i] = currinds[i];
  901. vertsx[i] += normalized_cellsize;
  902. }
  903. }
  904. }
  905. free(edgemap);
  906. free(prevrowmasks);
  907. free(prevrowinds);
  908. // Perform quick-n-dirty simplification by iterating two rows at a time.
  909. // In no way does this create the simplest possible mesh, but at least it's
  910. // fast and easy.
  911. if (flags & PAR_MSQUARES_SIMPLIFY) {
  912. int in_run = 0, start_run;
  913. // First figure out how many triangles we can eliminate.
  914. int neliminated_triangles = 0;
  915. for (int row = 0; row < nrows - 1; row += 2) {
  916. for (int col = 0; col < ncols; col++) {
  917. int a = simplification_codes[ncols * row + col] == 0xf;
  918. int b = simplification_codes[ncols * row + col + ncols] == 0xf;
  919. if (a && b) {
  920. if (!in_run) {
  921. in_run = 1;
  922. start_run = col;
  923. }
  924. continue;
  925. }
  926. if (in_run) {
  927. in_run = 0;
  928. int run_width = col - start_run;
  929. neliminated_triangles += run_width * 4 - 2;
  930. }
  931. }
  932. if (in_run) {
  933. in_run = 0;
  934. int run_width = ncols - start_run;
  935. neliminated_triangles += run_width * 4 - 2;
  936. }
  937. }
  938. // Build a new index array cell-by-cell. If any given cell is 'F' and
  939. // its neighbor to the south is also 'F', then it's part of a run.
  940. int nnewtris = ntris + nconntris - neliminated_triangles;
  941. uint16_t* newtris = PAR_CALLOC(uint16_t, nnewtris * 3);
  942. uint16_t* pnewtris = newtris;
  943. in_run = 0;
  944. for (int row = 0; row < nrows - 1; row += 2) {
  945. for (int col = 0; col < ncols; col++) {
  946. int cell = ncols * row + col;
  947. int south = cell + ncols;
  948. int a = simplification_codes[cell] == 0xf;
  949. int b = simplification_codes[south] == 0xf;
  950. if (a && b) {
  951. if (!in_run) {
  952. in_run = 1;
  953. start_run = col;
  954. }
  955. continue;
  956. }
  957. if (in_run) {
  958. in_run = 0;
  959. int nw_cell = ncols * row + start_run;
  960. int ne_cell = ncols * row + col - 1;
  961. int sw_cell = nw_cell + ncols;
  962. int se_cell = ne_cell + ncols;
  963. int nw_tri = simplification_tris[nw_cell];
  964. int ne_tri = simplification_tris[ne_cell];
  965. int sw_tri = simplification_tris[sw_cell];
  966. int se_tri = simplification_tris[se_cell];
  967. int nw_corner = nw_tri * 3 + 4;
  968. int ne_corner = ne_tri * 3 + 0;
  969. int sw_corner = sw_tri * 3 + 2;
  970. int se_corner = se_tri * 3 + 1;
  971. *pnewtris++ = tris[se_corner];
  972. *pnewtris++ = tris[sw_corner];
  973. *pnewtris++ = tris[nw_corner];
  974. *pnewtris++ = tris[nw_corner];
  975. *pnewtris++ = tris[ne_corner];
  976. *pnewtris++ = tris[se_corner];
  977. }
  978. int ncelltris = simplification_ntris[cell];
  979. int celltri = simplification_tris[cell];
  980. for (int t = 0; t < ncelltris; t++, celltri++) {
  981. *pnewtris++ = tris[celltri * 3];
  982. *pnewtris++ = tris[celltri * 3 + 1];
  983. *pnewtris++ = tris[celltri * 3 + 2];
  984. }
  985. ncelltris = simplification_ntris[south];
  986. celltri = simplification_tris[south];
  987. for (int t = 0; t < ncelltris; t++, celltri++) {
  988. *pnewtris++ = tris[celltri * 3];
  989. *pnewtris++ = tris[celltri * 3 + 1];
  990. *pnewtris++ = tris[celltri * 3 + 2];
  991. }
  992. }
  993. if (in_run) {
  994. in_run = 0;
  995. int nw_cell = ncols * row + start_run;
  996. int ne_cell = ncols * row + ncols - 1;
  997. int sw_cell = nw_cell + ncols;
  998. int se_cell = ne_cell + ncols;
  999. int nw_tri = simplification_tris[nw_cell];
  1000. int ne_tri = simplification_tris[ne_cell];
  1001. int sw_tri = simplification_tris[sw_cell];
  1002. int se_tri = simplification_tris[se_cell];
  1003. int nw_corner = nw_tri * 3 + 4;
  1004. int ne_corner = ne_tri * 3 + 0;
  1005. int sw_corner = sw_tri * 3 + 2;
  1006. int se_corner = se_tri * 3 + 1;
  1007. *pnewtris++ = tris[se_corner];
  1008. *pnewtris++ = tris[sw_corner];
  1009. *pnewtris++ = tris[nw_corner];
  1010. *pnewtris++ = tris[nw_corner];
  1011. *pnewtris++ = tris[ne_corner];
  1012. *pnewtris++ = tris[se_corner];
  1013. }
  1014. }
  1015. ptris = pnewtris;
  1016. ntris -= neliminated_triangles;
  1017. free(tris);
  1018. tris = newtris;
  1019. free(simplification_codes);
  1020. free(simplification_tris);
  1021. free(simplification_ntris);
  1022. // Remove unreferenced points.
  1023. char* markers = PAR_CALLOC(char, npts);
  1024. ptris = tris;
  1025. int newnpts = 0;
  1026. for (int i = 0; i < ntris * 3; i++, ptris++) {
  1027. if (!markers[*ptris]) {
  1028. newnpts++;
  1029. markers[*ptris] = 1;
  1030. }
  1031. }
  1032. for (int i = 0; i < nconntris * 3; i++) {
  1033. if (!markers[conntris[i]]) {
  1034. newnpts++;
  1035. markers[conntris[i]] = 1;
  1036. }
  1037. }
  1038. float* newpts = PAR_CALLOC(float, newnpts * mesh->dim);
  1039. uint16_t* mapping = PAR_CALLOC(uint16_t, npts);
  1040. ppts = pts;
  1041. float* pnewpts = newpts;
  1042. int j = 0;
  1043. if (mesh->dim == 3) {
  1044. for (int i = 0; i < npts; i++, ppts += 3) {
  1045. if (markers[i]) {
  1046. *pnewpts++ = ppts[0];
  1047. *pnewpts++ = ppts[1];
  1048. *pnewpts++ = ppts[2];
  1049. mapping[i] = j++;
  1050. }
  1051. }
  1052. } else {
  1053. for (int i = 0; i < npts; i++, ppts += 2) {
  1054. if (markers[i]) {
  1055. *pnewpts++ = ppts[0];
  1056. *pnewpts++ = ppts[1];
  1057. mapping[i] = j++;
  1058. }
  1059. }
  1060. }
  1061. free(pts);
  1062. free(markers);
  1063. pts = newpts;
  1064. npts = newnpts;
  1065. for (int i = 0; i < ntris * 3; i++) {
  1066. tris[i] = mapping[tris[i]];
  1067. }
  1068. for (int i = 0; i < nconntris * 3; i++) {
  1069. conntris[i] = mapping[conntris[i]];
  1070. }
  1071. free(mapping);
  1072. }
  1073. // Append all extrusion triangles to the main triangle array.
  1074. // We need them to be last so that they form a contiguous sequence.
  1075. pconntris = conntris;
  1076. for (int i = 0; i < nconntris; i++) {
  1077. *ptris++ = *pconntris++;
  1078. *ptris++ = *pconntris++;
  1079. *ptris++ = *pconntris++;
  1080. ntris++;
  1081. }
  1082. free(conntris);
  1083. // Final cleanup and return.
  1084. assert(npts <= maxpts);
  1085. assert(ntris <= maxtris);
  1086. mesh->npoints = npts;
  1087. mesh->points = pts;
  1088. mesh->ntriangles = ntris;
  1089. mesh->triangles = tris;
  1090. mesh->nconntriangles = nconntris;
  1091. return mlist;
  1092. }
  1093. typedef struct {
  1094. uint16_t outera;
  1095. uint16_t outerb;
  1096. uint16_t innera;
  1097. uint16_t innerb;
  1098. char i;
  1099. char j;
  1100. par_msquares__mesh* mesh;
  1101. int mesh_index;
  1102. } par_connector;
  1103. static par_connector* par_conn_find(par_connector* conns, int nconns,
  1104. char i, char j)
  1105. {
  1106. for (int c = 0; c < nconns; c++) {
  1107. if (conns[c].i == i && conns[c].j == j) {
  1108. return conns + c;
  1109. }
  1110. }
  1111. return 0;
  1112. }
  1113. static int par_msquares_cmp(const void *a, const void *b)
  1114. {
  1115. uint32_t arg1 = *((uint32_t const*) a);
  1116. uint32_t arg2 = *((uint32_t const*) b);
  1117. if (arg1 < arg2) return -1;
  1118. if (arg1 > arg2) return 1;
  1119. return 0;
  1120. }
  1121. typedef int (*par_msquares_code_fn)(int, int, int, int, void*);
  1122. static int par_msquares_multi_code(int sw, int se, int ne, int nw)
  1123. {
  1124. int code[4];
  1125. int ncols = 0;
  1126. code[0] = ncols++;
  1127. if (se == sw) {
  1128. code[1] = code[0];
  1129. } else {
  1130. code[1] = ncols++;
  1131. }
  1132. if (ne == se) {
  1133. code[2] = code[1];
  1134. } else if (ne == sw) {
  1135. code[2] = code[0];
  1136. } else {
  1137. code[2] = ncols++;
  1138. }
  1139. if (nw == ne) {
  1140. code[3] = code[2];
  1141. } else if (nw == se) {
  1142. code[3] = code[1];
  1143. } else if (nw == sw) {
  1144. code[3] = code[0];
  1145. } else {
  1146. code[3] = ncols++;
  1147. }
  1148. return code[0] | (code[1] << 2) | (code[2] << 4) | (code[3] << 6);
  1149. }
  1150. static uint32_t par_msquares_argb(par_byte const* pdata, int bpp)
  1151. {
  1152. uint32_t color = 0;
  1153. if (bpp == 4) {
  1154. color |= pdata[2];
  1155. color |= pdata[1] << 8;
  1156. color |= pdata[0] << 16;
  1157. color |= pdata[3] << 24;
  1158. return color;
  1159. }
  1160. for (int j = 0; j < bpp; j++) {
  1161. color <<= 8;
  1162. color |= pdata[j];
  1163. }
  1164. return color;
  1165. }
  1166. // Merge connective triangles into the primary triangle list.
  1167. static void par_msquares__finalize(par_msquares_meshlist* mlist)
  1168. {
  1169. if (mlist->nmeshes < 2 || mlist->meshes[1]->nconntriangles == 0) {
  1170. return;
  1171. }
  1172. for (int m = 1; m < mlist->nmeshes; m++) {
  1173. par_msquares__mesh* mesh = mlist->meshes[m];
  1174. int ntris = mesh->ntriangles + mesh->nconntriangles;
  1175. uint16_t* triangles = PAR_CALLOC(uint16_t, ntris * 3);
  1176. uint16_t* dst = triangles;
  1177. uint16_t const* src = mesh->triangles;
  1178. for (int t = 0; t < mesh->ntriangles; t++) {
  1179. *dst++ = *src++;
  1180. *dst++ = *src++;
  1181. *dst++ = *src++;
  1182. }
  1183. src = mesh->conntri;
  1184. for (int t = 0; t < mesh->nconntriangles; t++) {
  1185. *dst++ = *src++;
  1186. *dst++ = *src++;
  1187. *dst++ = *src++;
  1188. }
  1189. free(mesh->triangles);
  1190. free(mesh->conntri);
  1191. mesh->triangles = triangles;
  1192. mesh->ntriangles = ntris;
  1193. mesh->conntri = 0;
  1194. mesh->nconntriangles = 0;
  1195. }
  1196. }
  1197. static par__uint16list* par__uint16list_create()
  1198. {
  1199. par__uint16list* list = PAR_CALLOC(par__uint16list, 1);
  1200. list->count = 0;
  1201. list->capacity = 32;
  1202. list->values = PAR_CALLOC(uint16_t, list->capacity);
  1203. return list;
  1204. }
  1205. static void par__uint16list_add3(par__uint16list* list,
  1206. uint16_t a, uint16_t b, uint16_t c)
  1207. {
  1208. if (list->count + 3 > list->capacity) {
  1209. list->capacity *= 2;
  1210. list->values = PAR_REALLOC(uint16_t, list->values, list->capacity);
  1211. }
  1212. list->values[list->count++] = a;
  1213. list->values[list->count++] = b;
  1214. list->values[list->count++] = c;
  1215. }
  1216. static void par__uint16list_free(par__uint16list* list)
  1217. {
  1218. if (list) {
  1219. PAR_FREE(list->values);
  1220. PAR_FREE(list);
  1221. }
  1222. }
  1223. static void par_msquares__repair_tjunctions(par_msquares_meshlist* mlist)
  1224. {
  1225. for (int m = 0; m < mlist->nmeshes; m++) {
  1226. par_msquares__mesh* mesh = mlist->meshes[m];
  1227. par__uint16list* tjunctions = mesh->tjunctions;
  1228. int njunctions = (int) tjunctions->count / 3;
  1229. if (njunctions == 0) {
  1230. continue;
  1231. }
  1232. int ntriangles = mesh->ntriangles + njunctions;
  1233. mesh->triangles = PAR_REALLOC(uint16_t, mesh->triangles,
  1234. ntriangles * 3);
  1235. uint16_t const* jun = tjunctions->values;
  1236. uint16_t* new_triangles = mesh->triangles + mesh->ntriangles * 3;
  1237. int ncreated = 0;
  1238. for (int j = 0; j < njunctions; j++, jun += 3) {
  1239. uint16_t* tri = mesh->triangles;
  1240. int t;
  1241. for (t = 0; t < mesh->ntriangles; t++, tri += 3) {
  1242. int i = -1;
  1243. if (tri[0] == jun[0] && tri[1] == jun[1]) {
  1244. i = 0;
  1245. } else if (tri[1] == jun[0] && tri[2] == jun[1]) {
  1246. i = 1;
  1247. } else if (tri[2] == jun[0] && tri[0] == jun[1]) {
  1248. i = 2;
  1249. } else {
  1250. continue;
  1251. }
  1252. new_triangles[0] = tri[(i + 0) % 3];
  1253. new_triangles[1] = jun[2];
  1254. new_triangles[2] = tri[(i + 2) % 3];
  1255. tri[(i + 0) % 3] = jun[2];
  1256. new_triangles += 3;
  1257. ncreated++;
  1258. break;
  1259. }
  1260. // TODO: Need to investigate the "msquares_multi_diagram.obj" test.
  1261. assert(t != mesh->ntriangles &&
  1262. "Error with T-Junction repair; please disable the CLEAN flag.");
  1263. }
  1264. mesh->ntriangles += ncreated;
  1265. }
  1266. }
  1267. par_msquares_meshlist* par_msquares_color_multi(par_byte const* data, int width,
  1268. int height, int cellsize, int bpp, int flags)
  1269. {
  1270. if (!par_msquares_binary_point_table) {
  1271. par_init_tables();
  1272. }
  1273. const int ncols = width / cellsize;
  1274. const int nrows = height / cellsize;
  1275. const int maxrow = (height - 1) * width;
  1276. const int ncells = ncols * nrows;
  1277. const int dim = (flags & PAR_MSQUARES_HEIGHTS) ? 3 : 2;
  1278. const int west_to_east[9] = { 2, -1, -1, -1, -1, -1, 4, 3, -1 };
  1279. const int north_to_south[9] = { -1, -1, -1, -1, 2, 1, 0, -1, -1 };
  1280. assert(!(flags & PAR_MSQUARES_HEIGHTS) || bpp == 4);
  1281. assert(bpp > 0 && bpp <= 4 && "Bytes per pixel must be 1, 2, 3, or 4.");
  1282. assert(!(flags & PAR_MSQUARES_CLEAN) || !(flags & PAR_MSQUARES_SIMPLIFY));
  1283. assert(!(flags & PAR_MSQUARES_SNAP) &&
  1284. "SNAP is not supported with color_multi");
  1285. assert(!(flags & PAR_MSQUARES_INVERT) &&
  1286. "INVERT is not supported with color_multi");
  1287. assert(!(flags & PAR_MSQUARES_DUAL) &&
  1288. "DUAL is not supported with color_multi");
  1289. // Find all unique colors and ensure there are no more than 256 colors.
  1290. uint32_t colors[256];
  1291. int ncolors = 0;
  1292. par_byte const* pdata = data;
  1293. for (int i = 0; i < width * height; i++, pdata += bpp) {
  1294. uint32_t color = par_msquares_argb(pdata, bpp);
  1295. if (0 == bsearch(&color, colors, ncolors, 4, par_msquares_cmp)) {
  1296. assert(ncolors < 256);
  1297. colors[ncolors++] = color;
  1298. qsort(colors, ncolors, sizeof(uint32_t), par_msquares_cmp);
  1299. }
  1300. }
  1301. // Convert the color image to grayscale using the mapping table.
  1302. par_byte* pixels = PAR_CALLOC(par_byte, width * height);
  1303. pdata = data;
  1304. for (int i = 0; i < width * height; i++, pdata += bpp) {
  1305. uint32_t color = par_msquares_argb(pdata, bpp);
  1306. void* result = bsearch(&color, colors, ncolors, 4, par_msquares_cmp);
  1307. pixels[i] = (uint32_t*) result - &colors[0];
  1308. }
  1309. // Allocate 1 mesh for each color.
  1310. par_msquares_meshlist* mlist = PAR_CALLOC(par_msquares_meshlist, 1);
  1311. mlist->nmeshes = ncolors;
  1312. mlist->meshes = PAR_CALLOC(par_msquares__mesh*, ncolors);
  1313. par_msquares__mesh* mesh;
  1314. int maxtris_per_cell = 6;
  1315. int maxpts_per_cell = 9;
  1316. if (flags & PAR_MSQUARES_CONNECT) {
  1317. maxpts_per_cell += 6;
  1318. }
  1319. for (int i = 0; i < ncolors; i++) {
  1320. mesh = mlist->meshes[i] = PAR_CALLOC(par_msquares__mesh, 1);
  1321. mesh->color = colors[i];
  1322. mesh->points = PAR_CALLOC(float, ncells * maxpts_per_cell * dim);
  1323. mesh->triangles = PAR_CALLOC(uint16_t, ncells * maxtris_per_cell * 3);
  1324. mesh->dim = dim;
  1325. mesh->tjunctions = par__uint16list_create();
  1326. if (flags & PAR_MSQUARES_CONNECT) {
  1327. mesh->conntri = PAR_CALLOC(uint16_t, ncells * 8 * 3);
  1328. }
  1329. }
  1330. // The "verts" x/y/z arrays are the 4 corners and 4 midpoints around the
  1331. // square, in counter-clockwise order, starting at the lower-left. The
  1332. // ninth vert is the center point.
  1333. float vertsx[9], vertsy[9];
  1334. float normalization = 1.0f / PAR_MAX(width, height);
  1335. float normalized_cellsize = cellsize * normalization;
  1336. uint8_t cella[256];
  1337. uint8_t cellb[256];
  1338. uint8_t* currcell = cella;
  1339. uint8_t* prevcell = cellb;
  1340. uint16_t inds0[256 * 9];
  1341. uint16_t inds1[256 * 9];
  1342. uint16_t* currinds = inds0;
  1343. uint16_t* previnds = inds1;
  1344. uint16_t* rowindsa = PAR_CALLOC(uint16_t, ncols * 3 * 256);
  1345. uint8_t* rowcellsa = PAR_CALLOC(uint8_t, ncols * 256);
  1346. uint16_t* rowindsb = PAR_CALLOC(uint16_t, ncols * 3 * 256);
  1347. uint8_t* rowcellsb = PAR_CALLOC(uint8_t, ncols * 256);
  1348. uint16_t* prevrowinds = rowindsa;
  1349. uint16_t* currrowinds = rowindsb;
  1350. uint8_t* prevrowcells = rowcellsa;
  1351. uint8_t* currrowcells = rowcellsb;
  1352. uint32_t* simplification_words = 0;
  1353. if (flags & PAR_MSQUARES_SIMPLIFY) {
  1354. simplification_words = PAR_CALLOC(uint32_t, 2 * nrows * ncols);
  1355. }
  1356. // Do the march!
  1357. for (int row = 0; row < nrows; row++) {
  1358. vertsx[0] = vertsx[6] = vertsx[7] = 0;
  1359. vertsx[1] = vertsx[5] = vertsx[8] = 0.5 * normalized_cellsize;
  1360. vertsx[2] = vertsx[3] = vertsx[4] = normalized_cellsize;
  1361. vertsy[0] = vertsy[1] = vertsy[2] = normalized_cellsize * (row + 1);
  1362. vertsy[4] = vertsy[5] = vertsy[6] = normalized_cellsize * row;
  1363. vertsy[3] = vertsy[7] = vertsy[8] = normalized_cellsize * (row + 0.5);
  1364. int northi = row * cellsize * width;
  1365. int southi = PAR_MIN(northi + cellsize * width, maxrow);
  1366. int nwval = pixels[northi];
  1367. int swval = pixels[southi];
  1368. memset(currrowcells, 0, ncols * 256);
  1369. for (int col = 0; col < ncols; col++) {
  1370. northi += cellsize;
  1371. southi += cellsize;
  1372. if (col == ncols - 1) {
  1373. northi--;
  1374. southi--;
  1375. }
  1376. // Obtain 8-bit code and grab the four corresponding triangle lists.
  1377. int neval = pixels[northi];
  1378. int seval = pixels[southi];
  1379. int code = par_msquares_multi_code(swval, seval, neval, nwval) >> 2;
  1380. int const* trispecs[4] = {
  1381. par_msquares_quaternary_triangle_table[code][0],
  1382. par_msquares_quaternary_triangle_table[code][1],
  1383. par_msquares_quaternary_triangle_table[code][2],
  1384. par_msquares_quaternary_triangle_table[code][3]
  1385. };
  1386. int ntris[4] = {
  1387. *trispecs[0]++,
  1388. *trispecs[1]++,
  1389. *trispecs[2]++,
  1390. *trispecs[3]++
  1391. };
  1392. int const* edgespecs[4] = {
  1393. par_msquares_quaternary_boundary_table[code][0],
  1394. par_msquares_quaternary_boundary_table[code][1],
  1395. par_msquares_quaternary_boundary_table[code][2],
  1396. par_msquares_quaternary_boundary_table[code][3]
  1397. };
  1398. int nedges[4] = {
  1399. *edgespecs[0]++,
  1400. *edgespecs[1]++,
  1401. *edgespecs[2]++,
  1402. *edgespecs[3]++
  1403. };
  1404. int vals[4] = { swval, seval, neval, nwval };
  1405. // Gather topology information.
  1406. par_connector edges[16];
  1407. int ncedges = 0;
  1408. for (int c = 0; c < 4; c++) {
  1409. int color = vals[c];
  1410. par_msquares__mesh* mesh = mlist->meshes[color];
  1411. par_connector edge;
  1412. for (int e = 0; e < nedges[c]; e++) {
  1413. char previndex = edgespecs[c][e * 2];
  1414. char currindex = edgespecs[c][e * 2 + 1];
  1415. edge.i = previndex;
  1416. edge.j = currindex;
  1417. edge.mesh_index = color;
  1418. edge.mesh = mesh;
  1419. edges[ncedges++] = edge;
  1420. }
  1421. }
  1422. assert(ncedges < 16);
  1423. // Push triangles and points into the four affected meshes.
  1424. for (int m = 0; m < ncolors; m++) {
  1425. currcell[m] = 0;
  1426. }
  1427. uint32_t colors = 0;
  1428. uint32_t counts = 0;
  1429. uint16_t* conntris_start[4];
  1430. for (int c = 0; c < 4; c++) {
  1431. int color = vals[c];
  1432. colors |= color << (8 * c);
  1433. counts |= ntris[c] << (8 * c);
  1434. par_msquares__mesh* mesh = mlist->meshes[color];
  1435. float height = (mesh->color >> 24) / 255.0;
  1436. conntris_start[c] = mesh->conntri + mesh->nconntriangles * 3;
  1437. int usedpts[9] = {0};
  1438. uint16_t* pcurrinds = currinds + 9 * color;
  1439. uint16_t const* pprevinds = previnds + 9 * color;
  1440. uint16_t const* pprevrowinds =
  1441. prevrowinds + ncols * 3 * color + col * 3;
  1442. uint8_t prevrowcell = prevrowcells[color * ncols + col];
  1443. float* pdst = mesh->points + mesh->npoints * mesh->dim;
  1444. int previndex, prevflag;
  1445. for (int t = 0; t < ntris[c] * 3; t++) {
  1446. uint16_t index = trispecs[c][t];
  1447. if (usedpts[index]) {
  1448. continue;
  1449. }
  1450. usedpts[index] = 1;
  1451. if (index < 8) {
  1452. currcell[color] |= 1 << index;
  1453. }
  1454. // Vertical welding.
  1455. previndex = north_to_south[index];
  1456. prevflag = (previndex > -1) ? (1 << previndex) : 0;
  1457. if (row > 0 && (prevrowcell & prevflag)) {
  1458. pcurrinds[index] = pprevrowinds[previndex];
  1459. continue;
  1460. }
  1461. // Horizontal welding.
  1462. previndex = west_to_east[index];
  1463. prevflag = (previndex > -1) ? (1 << previndex) : 0;
  1464. if (col > 0 && (prevcell[color] & prevflag)) {
  1465. pcurrinds[index] = pprevinds[previndex];
  1466. continue;
  1467. }
  1468. // Insert brand new point.
  1469. float* vertex = pdst;
  1470. *pdst++ = vertsx[index];
  1471. *pdst++ = 1 - vertsy[index];
  1472. if (mesh->dim == 3) {
  1473. *pdst++ = height;
  1474. }
  1475. pcurrinds[index] = mesh->npoints++;
  1476. // If this is a midpoint, nudge it to the intersection.
  1477. if (index == 1) {
  1478. int begin = southi - cellsize;
  1479. for (int i = 1; i < cellsize + 1; i++) {
  1480. int val = pixels[begin + i];
  1481. if (val != pixels[begin]) {
  1482. vertex[0] = vertsx[0] + normalized_cellsize *
  1483. (float) i / cellsize;
  1484. break;
  1485. }
  1486. }
  1487. } else if (index == 3) {
  1488. int begin = northi;
  1489. for (int i = 1; i < cellsize + 1; i++) {
  1490. int val = pixels[begin + i * width];
  1491. if (val != pixels[begin]) {
  1492. vertex[1] = (1 - vertsy[4]) -
  1493. normalized_cellsize * (float) i / cellsize;
  1494. break;
  1495. }
  1496. }
  1497. }
  1498. }
  1499. // Look for T junctions and note them for later repairs.
  1500. uint8_t prc = prevrowcell;
  1501. if (usedpts[4] && !usedpts[5] && usedpts[6] && (prc & 2)) {
  1502. // Above cell had a middle vert, current cell straddles it.
  1503. par__uint16list_add3(mesh->tjunctions,
  1504. pcurrinds[4], pcurrinds[6], pprevrowinds[1]);
  1505. } else if ((prc & 1) && !(prc & 2) && (prc & 4) && usedpts[5]) {
  1506. // Current cell has a middle vert, above cell straddles it.
  1507. par__uint16list_add3(mesh->tjunctions,
  1508. pprevrowinds[0], pprevrowinds[2], pcurrinds[5]);
  1509. }
  1510. uint8_t pcc = col > 0 ? prevcell[color] : 0;
  1511. if (usedpts[0] && !usedpts[7] && usedpts[6] && (pcc & 8)) {
  1512. // Left cell had a middle vert, current cell straddles it.
  1513. par__uint16list_add3(mesh->tjunctions,
  1514. pcurrinds[6], pcurrinds[0], pprevinds[3]);
  1515. }
  1516. if ((pcc & 4) && !(pcc & 8) && (pcc & 16) && usedpts[7]) {
  1517. // Current cell has a middle vert, left cell straddles it.
  1518. par__uint16list_add3(mesh->tjunctions,
  1519. pprevinds[2], pprevinds[4], pcurrinds[7]);
  1520. }
  1521. // Stamp out the cell's triangle indices for this color.
  1522. uint16_t* tdst = mesh->triangles + mesh->ntriangles * 3;
  1523. mesh->ntriangles += ntris[c];
  1524. for (int t = 0; t < ntris[c] * 3; t++) {
  1525. uint16_t index = trispecs[c][t];
  1526. *tdst++ = pcurrinds[index];
  1527. }
  1528. // Add extrusion points and connective triangles if requested.
  1529. if (!(flags & PAR_MSQUARES_CONNECT)) {
  1530. continue;
  1531. }
  1532. for (int e = 0; e < nedges[c]; e++) {
  1533. int previndex = edgespecs[c][e * 2];
  1534. int currindex = edgespecs[c][e * 2 + 1];
  1535. par_connector* thisedge = par_conn_find(edges,
  1536. ncedges, previndex, currindex);
  1537. thisedge->innera = pcurrinds[previndex];
  1538. thisedge->innerb = pcurrinds[currindex];
  1539. thisedge->outera = mesh->npoints;
  1540. thisedge->outerb = mesh->npoints + 1;
  1541. par_connector* oppedge = par_conn_find(edges,
  1542. ncedges, currindex, previndex);
  1543. if (oppedge->mesh_index > color) continue;
  1544. *pdst++ = vertsx[previndex];
  1545. *pdst++ = 1 - vertsy[previndex];
  1546. if (mesh->dim == 3) {
  1547. *pdst++ = height;
  1548. }
  1549. mesh->npoints++;
  1550. *pdst++ = vertsx[currindex];
  1551. *pdst++ = 1 - vertsy[currindex];
  1552. if (mesh->dim == 3) {
  1553. *pdst++ = height;
  1554. }
  1555. mesh->npoints++;
  1556. uint16_t i0 = mesh->npoints - 1;
  1557. uint16_t i1 = mesh->npoints - 2;
  1558. uint16_t i2 = pcurrinds[previndex];
  1559. uint16_t i3 = pcurrinds[currindex];
  1560. uint16_t* ptr = mesh->conntri +
  1561. mesh->nconntriangles * 3;
  1562. *ptr++ = i2; *ptr++ = i1; *ptr++ = i0;
  1563. *ptr++ = i0; *ptr++ = i3; *ptr++ = i2;
  1564. mesh->nconntriangles += 2;
  1565. }
  1566. }
  1567. // Adjust the positions of the extrusion verts.
  1568. if (flags & PAR_MSQUARES_CONNECT) {
  1569. for (int c = 0; c < 4; c++) {
  1570. int color = vals[c];
  1571. uint16_t* pconninds = conntris_start[c];
  1572. par_msquares__mesh* mesh = mlist->meshes[color];
  1573. for (int e = 0; e < nedges[c]; e++) {
  1574. int previndex = edgespecs[c][e * 2];
  1575. int currindex = edgespecs[c][e * 2 + 1];
  1576. uint16_t i1 = pconninds[1];
  1577. uint16_t i0 = pconninds[2];
  1578. par_connector const* oppedge = par_conn_find(edges,
  1579. ncedges, currindex, previndex);
  1580. if (oppedge->mesh_index > color) continue;
  1581. int d = mesh->dim;
  1582. float* dst = mesh->points;
  1583. float const* src = oppedge->mesh->points;
  1584. dst[i0 * d + 0] = src[oppedge->innera * d + 0];
  1585. dst[i0 * d + 1] = src[oppedge->innera * d + 1];
  1586. dst[i1 * d + 0] = src[oppedge->innerb * d + 0];
  1587. dst[i1 * d + 1] = src[oppedge->innerb * d + 1];
  1588. if (d == 3) {
  1589. dst[i0 * d + 2] = src[oppedge->innera * d + 2];
  1590. dst[i1 * d + 2] = src[oppedge->innerb * d + 2];
  1591. }
  1592. pconninds += 6;
  1593. }
  1594. }
  1595. }
  1596. // Stash the bottom indices for each mesh in this cell to enable
  1597. // vertical as-you-go welding.
  1598. uint8_t* pcurrrowcells = currrowcells;
  1599. uint16_t* pcurrrowinds = currrowinds;
  1600. uint16_t const* pcurrinds = currinds;
  1601. for (int color = 0; color < ncolors; color++) {
  1602. pcurrrowcells[col] = currcell[color];
  1603. pcurrrowcells += ncols;
  1604. pcurrrowinds[col * 3 + 0] = pcurrinds[0];
  1605. pcurrrowinds[col * 3 + 1] = pcurrinds[1];
  1606. pcurrrowinds[col * 3 + 2] = pcurrinds[2];
  1607. pcurrrowinds += ncols * 3;
  1608. pcurrinds += 9;
  1609. }
  1610. // Stash some information later used by simplification.
  1611. if (flags & PAR_MSQUARES_SIMPLIFY) {
  1612. int cell = col + row * ncols;
  1613. simplification_words[cell * 2] = colors;
  1614. simplification_words[cell * 2 + 1] = counts;
  1615. }
  1616. // Advance the cursor.
  1617. nwval = neval;
  1618. swval = seval;
  1619. for (int i = 0; i < 9; i++) {
  1620. vertsx[i] += normalized_cellsize;
  1621. }
  1622. PAR_SWAP(uint8_t*, prevcell, currcell);
  1623. PAR_SWAP(uint16_t*, previnds, currinds);
  1624. }
  1625. PAR_SWAP(uint8_t*, prevrowcells, currrowcells);
  1626. PAR_SWAP(uint16_t*, prevrowinds, currrowinds);
  1627. }
  1628. free(prevrowinds);
  1629. free(prevrowcells);
  1630. free(pixels);
  1631. if (flags & PAR_MSQUARES_CLEAN) {
  1632. par_msquares__repair_tjunctions(mlist);
  1633. }
  1634. for (int m = 0; m < mlist->nmeshes; m++) {
  1635. par_msquares__mesh* mesh = mlist->meshes[m];
  1636. par__uint16list_free(mesh->tjunctions);
  1637. }
  1638. if (!(flags & PAR_MSQUARES_SIMPLIFY)) {
  1639. par_msquares__finalize(mlist);
  1640. return mlist;
  1641. }
  1642. uint8_t* simplification_blocks = PAR_CALLOC(uint8_t, nrows * ncols);
  1643. uint32_t* simplification_tris = PAR_CALLOC(uint32_t, nrows * ncols);
  1644. uint8_t* simplification_ntris = PAR_CALLOC(uint8_t, nrows * ncols);
  1645. // Perform quick-n-dirty simplification by iterating two rows at a time.
  1646. // In no way does this create the simplest possible mesh, but at least it's
  1647. // fast and easy.
  1648. for (uint32_t color = 0; color < (uint32_t) ncolors; color++) {
  1649. par_msquares__mesh* mesh = mlist->meshes[color];
  1650. // Populate the per-mesh info grids.
  1651. int ntris = 0;
  1652. for (int row = 0; row < nrows; row++) {
  1653. for (int col = 0; col < ncols; col++) {
  1654. int cell = ncols * row + col;
  1655. uint32_t colors = simplification_words[cell * 2];
  1656. uint32_t counts = simplification_words[cell * 2 + 1];
  1657. int ncelltris = 0;
  1658. int ncorners = 0;
  1659. if ((colors & 0xff) == color) {
  1660. ncelltris = counts & 0xff;
  1661. ncorners++;
  1662. }
  1663. if (((colors >> 8) & 0xff) == color) {
  1664. ncelltris += (counts >> 8) & 0xff;
  1665. ncorners++;
  1666. }
  1667. if (((colors >> 16) & 0xff) == color) {
  1668. ncelltris += (counts >> 16) & 0xff;
  1669. ncorners++;
  1670. }
  1671. if (((colors >> 24) & 0xff) == color) {
  1672. ncelltris += (counts >> 24) & 0xff;
  1673. ncorners++;
  1674. }
  1675. simplification_ntris[cell] = ncelltris;
  1676. simplification_tris[cell] = ntris;
  1677. simplification_blocks[cell] = ncorners == 4;
  1678. ntris += ncelltris;
  1679. }
  1680. }
  1681. // First figure out how many triangles we can eliminate.
  1682. int in_run = 0, start_run;
  1683. int neliminated_triangles = 0;
  1684. for (int row = 0; row < nrows - 1; row += 2) {
  1685. for (int col = 0; col < ncols; col++) {
  1686. int cell = ncols * row + col;
  1687. int a = simplification_blocks[cell];
  1688. int b = simplification_blocks[cell + ncols];
  1689. if (a && b) {
  1690. if (!in_run) {
  1691. in_run = 1;
  1692. start_run = col;
  1693. }
  1694. continue;
  1695. }
  1696. if (in_run) {
  1697. in_run = 0;
  1698. int run_width = col - start_run;
  1699. neliminated_triangles += run_width * 4 - 2;
  1700. }
  1701. }
  1702. if (in_run) {
  1703. in_run = 0;
  1704. int run_width = ncols - start_run;
  1705. neliminated_triangles += run_width * 4 - 2;
  1706. }
  1707. }
  1708. if (neliminated_triangles == 0) {
  1709. continue;
  1710. }
  1711. // Build a new index array cell-by-cell. If any given cell is 'F' and
  1712. // its neighbor to the south is also 'F', then it's part of a run.
  1713. int nnewtris = mesh->ntriangles - neliminated_triangles;
  1714. uint16_t* newtris = PAR_CALLOC(uint16_t, nnewtris * 3);
  1715. uint16_t* pnewtris = newtris;
  1716. in_run = 0;
  1717. uint16_t* tris = mesh->triangles;
  1718. for (int row = 0; row < nrows - 1; row += 2) {
  1719. for (int col = 0; col < ncols; col++) {
  1720. int cell = ncols * row + col;
  1721. int south = cell + ncols;
  1722. int a = simplification_blocks[cell];
  1723. int b = simplification_blocks[south];
  1724. if (a && b) {
  1725. if (!in_run) {
  1726. in_run = 1;
  1727. start_run = col;
  1728. }
  1729. continue;
  1730. }
  1731. if (in_run) {
  1732. in_run = 0;
  1733. int nw_cell = ncols * row + start_run;
  1734. int ne_cell = ncols * row + col - 1;
  1735. int sw_cell = nw_cell + ncols;
  1736. int se_cell = ne_cell + ncols;
  1737. int nw_tri = simplification_tris[nw_cell];
  1738. int ne_tri = simplification_tris[ne_cell];
  1739. int sw_tri = simplification_tris[sw_cell];
  1740. int se_tri = simplification_tris[se_cell];
  1741. int nw_corner = nw_tri * 3 + 5;
  1742. int ne_corner = ne_tri * 3 + 2;
  1743. int sw_corner = sw_tri * 3 + 0;
  1744. int se_corner = se_tri * 3 + 1;
  1745. *pnewtris++ = tris[nw_corner];
  1746. *pnewtris++ = tris[sw_corner];
  1747. *pnewtris++ = tris[se_corner];
  1748. *pnewtris++ = tris[se_corner];
  1749. *pnewtris++ = tris[ne_corner];
  1750. *pnewtris++ = tris[nw_corner];
  1751. }
  1752. int ncelltris = simplification_ntris[cell];
  1753. int celltri = simplification_tris[cell];
  1754. for (int t = 0; t < ncelltris; t++, celltri++) {
  1755. *pnewtris++ = tris[celltri * 3];
  1756. *pnewtris++ = tris[celltri * 3 + 1];
  1757. *pnewtris++ = tris[celltri * 3 + 2];
  1758. }
  1759. ncelltris = simplification_ntris[south];
  1760. celltri = simplification_tris[south];
  1761. for (int t = 0; t < ncelltris; t++, celltri++) {
  1762. *pnewtris++ = tris[celltri * 3];
  1763. *pnewtris++ = tris[celltri * 3 + 1];
  1764. *pnewtris++ = tris[celltri * 3 + 2];
  1765. }
  1766. }
  1767. if (in_run) {
  1768. in_run = 0;
  1769. int nw_cell = ncols * row + start_run;
  1770. int ne_cell = ncols * row + ncols - 1;
  1771. int sw_cell = nw_cell + ncols;
  1772. int se_cell = ne_cell + ncols;
  1773. int nw_tri = simplification_tris[nw_cell];
  1774. int ne_tri = simplification_tris[ne_cell];
  1775. int sw_tri = simplification_tris[sw_cell];
  1776. int se_tri = simplification_tris[se_cell];
  1777. int nw_corner = nw_tri * 3 + 5;
  1778. int ne_corner = ne_tri * 3 + 2;
  1779. int sw_corner = sw_tri * 3 + 0;
  1780. int se_corner = se_tri * 3 + 1;
  1781. *pnewtris++ = tris[nw_corner];
  1782. *pnewtris++ = tris[sw_corner];
  1783. *pnewtris++ = tris[se_corner];
  1784. *pnewtris++ = tris[se_corner];
  1785. *pnewtris++ = tris[ne_corner];
  1786. *pnewtris++ = tris[nw_corner];
  1787. }
  1788. }
  1789. mesh->ntriangles -= neliminated_triangles;
  1790. free(mesh->triangles);
  1791. mesh->triangles = newtris;
  1792. }
  1793. free(simplification_blocks);
  1794. free(simplification_ntris);
  1795. free(simplification_tris);
  1796. free(simplification_words);
  1797. par_msquares__finalize(mlist);
  1798. for (int i = 0; i < mlist->nmeshes; i++) {
  1799. par_remove_unreferenced_verts(mlist->meshes[i]);
  1800. }
  1801. return mlist;
  1802. }
  1803. void par_msquares_free_boundary(par_msquares_boundary* polygon)
  1804. {
  1805. free(polygon->points);
  1806. free(polygon->chains);
  1807. free(polygon->lengths);
  1808. free(polygon);
  1809. }
  1810. typedef struct par__hedge_s {
  1811. uint32_t key;
  1812. struct par__hvert_s* endvert;
  1813. struct par__hedge_s* opposite;
  1814. struct par__hedge_s* next;
  1815. struct par__hedge_s* prev;
  1816. } par__hedge;
  1817. typedef struct par__hvert_s {
  1818. par__hedge* incoming;
  1819. } par__hvert;
  1820. typedef struct {
  1821. par_msquares_mesh const* mesh;
  1822. par__hvert* verts;
  1823. par__hedge* edges;
  1824. par__hedge** sorted_edges;
  1825. } par__hemesh;
  1826. static int par__hedge_cmp(const void *arg0, const void *arg1)
  1827. {
  1828. par__hedge* he0 = *((par__hedge**) arg0);
  1829. par__hedge* he1 = *((par__hedge**) arg1);
  1830. if (he0->key < he1->key) return -1;
  1831. if (he0->key > he1->key) return 1;
  1832. return 0;
  1833. }
  1834. static par__hedge* par__hedge_find(par__hemesh* hemesh, uint32_t key)
  1835. {
  1836. par__hedge target = {0};
  1837. target.key = key;
  1838. par__hedge* ptarget = &target;
  1839. int nedges = hemesh->mesh->ntriangles * 3;
  1840. par__hedge** result = (par__hedge**) bsearch(&ptarget, hemesh->sorted_edges,
  1841. nedges, sizeof(par__hedge*), par__hedge_cmp);
  1842. return result ? *result : 0;
  1843. }
  1844. static uint32_t par__hedge_key(par__hvert* a, par__hvert* b, par__hvert* s)
  1845. {
  1846. uint32_t ai = a - s;
  1847. uint32_t bi = b - s;
  1848. return (ai << 16) | bi;
  1849. }
  1850. par_msquares_boundary* par_msquares_extract_boundary(
  1851. par_msquares_mesh const* mesh)
  1852. {
  1853. par_msquares_boundary* result = PAR_CALLOC(par_msquares_boundary, 1);
  1854. par__hemesh hemesh = {0};
  1855. hemesh.mesh = mesh;
  1856. int nedges = mesh->ntriangles * 3;
  1857. // Populate all fields of verts and edges, except opposite.
  1858. hemesh.edges = PAR_CALLOC(par__hedge, nedges);
  1859. par__hvert* hverts = hemesh.verts = PAR_CALLOC(par__hvert, mesh->npoints);
  1860. par__hedge* edge = hemesh.edges;
  1861. uint16_t const* tri = mesh->triangles;
  1862. for (int n = 0; n < mesh->ntriangles; n++, edge += 3, tri += 3) {
  1863. edge[0].endvert = hverts + tri[1];
  1864. edge[1].endvert = hverts + tri[2];
  1865. edge[2].endvert = hverts + tri[0];
  1866. hverts[tri[1]].incoming = edge + 0;
  1867. hverts[tri[2]].incoming = edge + 1;
  1868. hverts[tri[0]].incoming = edge + 2;
  1869. edge[0].next = edge + 1;
  1870. edge[1].next = edge + 2;
  1871. edge[2].next = edge + 0;
  1872. edge[0].prev = edge + 2;
  1873. edge[1].prev = edge + 0;
  1874. edge[2].prev = edge + 1;
  1875. edge[0].key = par__hedge_key(edge[2].endvert, edge[0].endvert, hverts);
  1876. edge[1].key = par__hedge_key(edge[0].endvert, edge[1].endvert, hverts);
  1877. edge[2].key = par__hedge_key(edge[1].endvert, edge[2].endvert, hverts);
  1878. }
  1879. // Sort the edges according to their key.
  1880. hemesh.sorted_edges = PAR_CALLOC(par__hedge*, mesh->ntriangles * 3);
  1881. for (int n = 0; n < nedges; n++) {
  1882. hemesh.sorted_edges[n] = hemesh.edges + n;
  1883. }
  1884. qsort(hemesh.sorted_edges, nedges, sizeof(par__hedge*), par__hedge_cmp);
  1885. // Populate the "opposite" field in each edge.
  1886. for (int n = 0; n < nedges; n++) {
  1887. par__hedge* edge = hemesh.edges + n;
  1888. par__hedge* prev = edge->prev;
  1889. par__hvert* start = edge->endvert;
  1890. par__hvert* end = prev->endvert;
  1891. uint32_t key = par__hedge_key(start, end, hverts);
  1892. edge->opposite = par__hedge_find(&hemesh, key);
  1893. }
  1894. // Re-use the sorted_edges array, filling it with boundary edges only.
  1895. // Also create a mapping table to consolidate all boundary verts.
  1896. int nborders = 0;
  1897. for (int n = 0; n < nedges; n++) {
  1898. par__hedge* edge = hemesh.edges + n;
  1899. if (!edge->opposite) {
  1900. hemesh.sorted_edges[nborders++] = edge;
  1901. }
  1902. }
  1903. // Allocate for the worst case (all separate triangles).
  1904. // We'll adjust the lengths later.
  1905. result->nchains = nborders / 3;
  1906. result->npoints = nborders + result->nchains;
  1907. result->points = PAR_CALLOC(float, 2 * result->npoints);
  1908. result->chains = PAR_CALLOC(float*, result->nchains);
  1909. result->lengths = PAR_CALLOC(uint16_t, result->nchains);
  1910. // Iterate over each polyline.
  1911. edge = hemesh.sorted_edges[0];
  1912. int pt = 0;
  1913. int nwritten = 0;
  1914. int nchains = 0;
  1915. while (1) {
  1916. float* points = result->points;
  1917. par__hedge* orig = edge;
  1918. uint16_t index = edge->prev->endvert - hverts;
  1919. result->chains[nchains] = points + pt;
  1920. result->lengths[nchains]++;
  1921. points[pt++] = mesh->points[index * mesh->dim];
  1922. points[pt++] = mesh->points[index * mesh->dim + 1];
  1923. while (1) {
  1924. index = edge->endvert - hverts;
  1925. edge->key = 0;
  1926. nwritten++;
  1927. result->lengths[nchains]++;
  1928. points[pt++] = mesh->points[index * mesh->dim];
  1929. points[pt++] = mesh->points[index * mesh->dim + 1];
  1930. par__hedge* next = edge->next;
  1931. while (next != edge) {
  1932. if (!next->opposite) {
  1933. break;
  1934. }
  1935. next = next->opposite->next;
  1936. }
  1937. edge = next;
  1938. if (edge == orig) {
  1939. break;
  1940. }
  1941. }
  1942. nchains++;
  1943. if (nwritten >= nborders) {
  1944. break;
  1945. }
  1946. for (int i = 0; i < nborders; i++) {
  1947. edge = hemesh.sorted_edges[i];
  1948. if (edge->key) {
  1949. break;
  1950. }
  1951. }
  1952. }
  1953. result->npoints = pt / 2;
  1954. result->nchains = nchains;
  1955. free(hemesh.verts);
  1956. free(hemesh.edges);
  1957. free(hemesh.sorted_edges);
  1958. return result;
  1959. }
  1960. #endif