par_shapes.h 71 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136
  1. // SHAPES :: https://github.com/prideout/par
  2. // Simple C library for creation and manipulation of triangle meshes.
  3. //
  4. // The API is divided into three sections:
  5. //
  6. // - Generators. Create parametric surfaces, platonic solids, etc.
  7. // - Queries. Ask a mesh for its axis-aligned bounding box, etc.
  8. // - Transforms. Rotate a mesh, merge it with another, add normals, etc.
  9. //
  10. // In addition to the comment block above each function declaration, the API
  11. // has informal documentation here:
  12. //
  13. // https://prideout.net/shapes
  14. //
  15. // For our purposes, a "mesh" is a list of points and a list of triangles; the
  16. // former is a flattened list of three-tuples (32-bit floats) and the latter is
  17. // also a flattened list of three-tuples (16-bit uints). Triangles are always
  18. // oriented such that their front face winds counter-clockwise.
  19. //
  20. // Optionally, meshes can contain 3D normals (one per vertex), and 2D texture
  21. // coordinates (one per vertex). That's it! If you need something fancier,
  22. // look elsewhere.
  23. //
  24. // Distributed under the MIT License, see bottom of file.
  25. #ifndef PAR_SHAPES_H
  26. #define PAR_SHAPES_H
  27. #ifdef __cplusplus
  28. extern "C" {
  29. #endif
  30. #include <stdint.h>
  31. #if !defined(_MSC_VER)
  32. # include <stdbool.h>
  33. #else // MSVC
  34. # if _MSC_VER >= 1800
  35. # include <stdbool.h>
  36. # else // stdbool.h missing prior to MSVC++ 12.0 (VS2013)
  37. # define bool int
  38. # define true 1
  39. # define false 0
  40. # endif
  41. #endif
  42. #ifndef PAR_SHAPES_T
  43. #define PAR_SHAPES_T uint16_t
  44. #endif
  45. typedef struct par_shapes_mesh_s {
  46. float* points; // Flat list of 3-tuples (X Y Z X Y Z...)
  47. int npoints; // Number of points
  48. PAR_SHAPES_T* triangles; // Flat list of 3-tuples (I J K I J K...)
  49. int ntriangles; // Number of triangles
  50. float* normals; // Optional list of 3-tuples (X Y Z X Y Z...)
  51. float* tcoords; // Optional list of 2-tuples (U V U V U V...)
  52. } par_shapes_mesh;
  53. void par_shapes_free_mesh(par_shapes_mesh*);
  54. // Generators ------------------------------------------------------------------
  55. // Instance a cylinder that sits on the Z=0 plane using the given tessellation
  56. // levels across the UV domain. Think of "slices" like a number of pizza
  57. // slices, and "stacks" like a number of stacked rings. Height and radius are
  58. // both 1.0, but they can easily be changed with par_shapes_scale.
  59. par_shapes_mesh* par_shapes_create_cylinder(int slices, int stacks);
  60. // Cone is similar to cylinder but the radius diminishes to zero as Z increases.
  61. // Again, height and radius are 1.0, but can be changed with par_shapes_scale.
  62. par_shapes_mesh* par_shapes_create_cone(int slices, int stacks);
  63. // Create a donut that sits on the Z=0 plane with the specified inner radius.
  64. // The outer radius can be controlled with par_shapes_scale.
  65. par_shapes_mesh* par_shapes_create_torus(int slices, int stacks, float radius);
  66. // Create a sphere with texture coordinates and small triangles near the poles.
  67. par_shapes_mesh* par_shapes_create_parametric_sphere(int slices, int stacks);
  68. // Approximate a sphere with a subdivided icosahedron, which produces a nice
  69. // distribution of triangles, but no texture coordinates. Each subdivision
  70. // level scales the number of triangles by four, so use a very low number.
  71. par_shapes_mesh* par_shapes_create_subdivided_sphere(int nsubdivisions);
  72. // More parametric surfaces.
  73. par_shapes_mesh* par_shapes_create_klein_bottle(int slices, int stacks);
  74. par_shapes_mesh* par_shapes_create_trefoil_knot(int slices, int stacks,
  75. float radius);
  76. par_shapes_mesh* par_shapes_create_hemisphere(int slices, int stacks);
  77. par_shapes_mesh* par_shapes_create_plane(int slices, int stacks);
  78. // Create a parametric surface from a callback function that consumes a 2D
  79. // point in [0,1] and produces a 3D point.
  80. typedef void (*par_shapes_fn)(float const*, float*, void*);
  81. par_shapes_mesh* par_shapes_create_parametric(par_shapes_fn, int slices,
  82. int stacks, void* userdata);
  83. // Rounded cuboid generator and a utility function for generating textures.
  84. par_shapes_mesh* par_shapes_create_rounded_cuboid(int slices, int stacks, float radius,
  85. float width, float height, float depth, int face_resolution);
  86. void par_shapes_map_rounded_cuboid(float radius, float width, float height, float depth,
  87. int face_resolution, const int st_in[2], float xyz_out[3]);
  88. // Generate points for a 20-sided polyhedron that fits in the unit sphere.
  89. // Texture coordinates and normals are not generated.
  90. par_shapes_mesh* par_shapes_create_icosahedron();
  91. // Generate points for a 12-sided polyhedron that fits in the unit sphere.
  92. // Again, texture coordinates and normals are not generated.
  93. par_shapes_mesh* par_shapes_create_dodecahedron();
  94. // More platonic solids.
  95. par_shapes_mesh* par_shapes_create_octahedron();
  96. par_shapes_mesh* par_shapes_create_tetrahedron();
  97. par_shapes_mesh* par_shapes_create_cube();
  98. // Generate an orientable disk shape in 3-space. Does not include normals or
  99. // texture coordinates.
  100. par_shapes_mesh* par_shapes_create_disk(float radius, int slices,
  101. float const* center, float const* normal);
  102. // Create an empty shape. Useful for building scenes with merge_and_free.
  103. par_shapes_mesh* par_shapes_create_empty();
  104. // Generate a rock shape that sits on the Y=0 plane, and sinks into it a bit.
  105. // This includes smooth normals but no texture coordinates. Each subdivision
  106. // level scales the number of triangles by four, so use a very low number.
  107. par_shapes_mesh* par_shapes_create_rock(int seed, int nsubdivisions);
  108. // Create trees or vegetation by executing a recursive turtle graphics program.
  109. // The program is a list of command-argument pairs. See the unit test for
  110. // an example. Texture coordinates and normals are not generated.
  111. par_shapes_mesh* par_shapes_create_lsystem(char const* program, int slices,
  112. int maxdepth);
  113. // Queries ---------------------------------------------------------------------
  114. // Dump out a text file conforming to the venerable OBJ format.
  115. void par_shapes_export(par_shapes_mesh const*, char const* objfile);
  116. // Take a pointer to 6 floats and set them to min xyz, max xyz.
  117. void par_shapes_compute_aabb(par_shapes_mesh const* mesh, float* aabb);
  118. // Make a deep copy of a mesh. To make a brand new copy, pass null to "target".
  119. // To avoid memory churn, pass an existing mesh to "target".
  120. par_shapes_mesh* par_shapes_clone(par_shapes_mesh const* mesh,
  121. par_shapes_mesh* target);
  122. // Transformations -------------------------------------------------------------
  123. void par_shapes_merge(par_shapes_mesh* dst, par_shapes_mesh const* src);
  124. void par_shapes_translate(par_shapes_mesh*, float x, float y, float z);
  125. void par_shapes_rotate(par_shapes_mesh*, float radians, float const* axis);
  126. void par_shapes_scale(par_shapes_mesh*, float x, float y, float z);
  127. void par_shapes_merge_and_free(par_shapes_mesh* dst, par_shapes_mesh* src);
  128. // Reverse the winding of a run of faces. Useful when drawing the inside of
  129. // a Cornell Box. Pass 0 for nfaces to reverse every face in the mesh.
  130. void par_shapes_invert(par_shapes_mesh*, int startface, int nfaces);
  131. // Remove all triangles whose area is less than minarea.
  132. void par_shapes_remove_degenerate(par_shapes_mesh*, float minarea);
  133. // Dereference the entire index buffer and replace the point list.
  134. // This creates an inefficient structure, but is useful for drawing facets.
  135. // If create_indices is true, a trivial "0 1 2 3..." index buffer is generated.
  136. void par_shapes_unweld(par_shapes_mesh* mesh, bool create_indices);
  137. // Merge colocated verts, build a new index buffer, and return the
  138. // optimized mesh. Epsilon is the maximum distance to consider when
  139. // welding vertices. The mapping argument can be null, or a pointer to
  140. // npoints integers, which gets filled with the mapping from old vertex
  141. // indices to new indices.
  142. par_shapes_mesh* par_shapes_weld(par_shapes_mesh const*, float epsilon,
  143. PAR_SHAPES_T* mapping);
  144. // Compute smooth normals by averaging adjacent facet normals.
  145. void par_shapes_compute_normals(par_shapes_mesh* m);
  146. // Global Config ---------------------------------------------------------------
  147. void par_shapes_set_epsilon_welded_normals(float epsilon);
  148. void par_shapes_set_epsilon_degenerate_sphere(float epsilon);
  149. // Advanced --------------------------------------------------------------------
  150. void par_shapes__compute_welded_normals(par_shapes_mesh* m);
  151. void par_shapes__connect(par_shapes_mesh* scene, par_shapes_mesh* cylinder,
  152. int slices);
  153. #ifndef PAR_PI
  154. #define PAR_PI (3.14159265359)
  155. #define PAR_MIN(a, b) (a > b ? b : a)
  156. #define PAR_MAX(a, b) (a > b ? a : b)
  157. #define PAR_CLAMP(v, lo, hi) PAR_MAX(lo, PAR_MIN(hi, v))
  158. #define PAR_SWAP(T, A, B) { T tmp = B; B = A; A = tmp; }
  159. #define PAR_SQR(a) ((a) * (a))
  160. #endif
  161. #ifndef PAR_MALLOC
  162. #define PAR_MALLOC(T, N) ((T*) malloc(N * sizeof(T)))
  163. #define PAR_CALLOC(T, N) ((T*) calloc(N * sizeof(T), 1))
  164. #define PAR_REALLOC(T, BUF, N) ((T*) realloc(BUF, sizeof(T) * (N)))
  165. #define PAR_FREE(BUF) free(BUF)
  166. #endif
  167. #ifdef __cplusplus
  168. }
  169. #endif
  170. // -----------------------------------------------------------------------------
  171. // END PUBLIC API
  172. // -----------------------------------------------------------------------------
  173. #ifdef PAR_SHAPES_IMPLEMENTATION
  174. #include <stdlib.h>
  175. #include <stdio.h>
  176. #include <assert.h>
  177. #include <float.h>
  178. #include <string.h>
  179. #include <math.h>
  180. #include <errno.h>
  181. static float par_shapes__epsilon_welded_normals = 0.001;
  182. static float par_shapes__epsilon_degenerate_sphere = 0.0001;
  183. static void par_shapes__sphere(float const* uv, float* xyz, void*);
  184. static void par_shapes__hemisphere(float const* uv, float* xyz, void*);
  185. static void par_shapes__plane(float const* uv, float* xyz, void*);
  186. static void par_shapes__klein(float const* uv, float* xyz, void*);
  187. static void par_shapes__cylinder(float const* uv, float* xyz, void*);
  188. static void par_shapes__cone(float const* uv, float* xyz, void*);
  189. static void par_shapes__torus(float const* uv, float* xyz, void*);
  190. static void par_shapes__trefoil(float const* uv, float* xyz, void*);
  191. struct osn_context;
  192. static int par__simplex_noise(int64_t seed, struct osn_context** ctx);
  193. static void par__simplex_noise_free(struct osn_context* ctx);
  194. static double par__simplex_noise2(struct osn_context* ctx, double x, double y);
  195. static void par_shapes__copy3(float* result, float const* a)
  196. {
  197. result[0] = a[0];
  198. result[1] = a[1];
  199. result[2] = a[2];
  200. }
  201. static float par_shapes__dot3(float const* a, float const* b)
  202. {
  203. return b[0] * a[0] + b[1] * a[1] + b[2] * a[2];
  204. }
  205. static void par_shapes__transform3(float* p, float const* x, float const* y,
  206. float const* z)
  207. {
  208. float px = par_shapes__dot3(p, x);
  209. float py = par_shapes__dot3(p, y);
  210. float pz = par_shapes__dot3(p, z);
  211. p[0] = px;
  212. p[1] = py;
  213. p[2] = pz;
  214. }
  215. static void par_shapes__cross3(float* result, float const* a, float const* b)
  216. {
  217. float x = (a[1] * b[2]) - (a[2] * b[1]);
  218. float y = (a[2] * b[0]) - (a[0] * b[2]);
  219. float z = (a[0] * b[1]) - (a[1] * b[0]);
  220. result[0] = x;
  221. result[1] = y;
  222. result[2] = z;
  223. }
  224. static void par_shapes__mix3(float* d, float const* a, float const* b, float t)
  225. {
  226. float x = b[0] * t + a[0] * (1 - t);
  227. float y = b[1] * t + a[1] * (1 - t);
  228. float z = b[2] * t + a[2] * (1 - t);
  229. d[0] = x;
  230. d[1] = y;
  231. d[2] = z;
  232. }
  233. static void par_shapes__scale3(float* result, float a)
  234. {
  235. result[0] *= a;
  236. result[1] *= a;
  237. result[2] *= a;
  238. }
  239. static void par_shapes__normalize3(float* v)
  240. {
  241. float lsqr = sqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]);
  242. if (lsqr > 0) {
  243. par_shapes__scale3(v, 1.0f / lsqr);
  244. }
  245. }
  246. static void par_shapes__subtract3(float* result, float const* a)
  247. {
  248. result[0] -= a[0];
  249. result[1] -= a[1];
  250. result[2] -= a[2];
  251. }
  252. static void par_shapes__add3(float* result, float const* a)
  253. {
  254. result[0] += a[0];
  255. result[1] += a[1];
  256. result[2] += a[2];
  257. }
  258. static float par_shapes__sqrdist3(float const* a, float const* b)
  259. {
  260. float dx = a[0] - b[0];
  261. float dy = a[1] - b[1];
  262. float dz = a[2] - b[2];
  263. return dx * dx + dy * dy + dz * dz;
  264. }
  265. void par_shapes__compute_welded_normals(par_shapes_mesh* m)
  266. {
  267. const float epsilon = par_shapes__epsilon_welded_normals;
  268. m->normals = PAR_MALLOC(float, m->npoints * 3);
  269. PAR_SHAPES_T* weldmap = PAR_MALLOC(PAR_SHAPES_T, m->npoints);
  270. par_shapes_mesh* welded = par_shapes_weld(m, epsilon, weldmap);
  271. par_shapes_compute_normals(welded);
  272. float* pdst = m->normals;
  273. for (int i = 0; i < m->npoints; i++, pdst += 3) {
  274. int d = weldmap[i];
  275. float const* pnormal = welded->normals + d * 3;
  276. pdst[0] = pnormal[0];
  277. pdst[1] = pnormal[1];
  278. pdst[2] = pnormal[2];
  279. }
  280. PAR_FREE(weldmap);
  281. par_shapes_free_mesh(welded);
  282. }
  283. par_shapes_mesh* par_shapes_create_cylinder(int slices, int stacks)
  284. {
  285. if (slices < 3 || stacks < 1) {
  286. return 0;
  287. }
  288. return par_shapes_create_parametric(par_shapes__cylinder, slices,
  289. stacks, 0);
  290. }
  291. par_shapes_mesh* par_shapes_create_cone(int slices, int stacks)
  292. {
  293. if (slices < 3 || stacks < 1) {
  294. return 0;
  295. }
  296. return par_shapes_create_parametric(par_shapes__cone, slices,
  297. stacks, 0);
  298. }
  299. par_shapes_mesh* par_shapes_create_parametric_sphere(int slices, int stacks)
  300. {
  301. if (slices < 3 || stacks < 3) {
  302. return 0;
  303. }
  304. par_shapes_mesh* m = par_shapes_create_parametric(par_shapes__sphere,
  305. slices, stacks, 0);
  306. par_shapes_remove_degenerate(m, par_shapes__epsilon_degenerate_sphere);
  307. return m;
  308. }
  309. par_shapes_mesh* par_shapes_create_hemisphere(int slices, int stacks)
  310. {
  311. if (slices < 3 || stacks < 3) {
  312. return 0;
  313. }
  314. par_shapes_mesh* m = par_shapes_create_parametric(par_shapes__hemisphere,
  315. slices, stacks, 0);
  316. par_shapes_remove_degenerate(m, par_shapes__epsilon_degenerate_sphere);
  317. return m;
  318. }
  319. par_shapes_mesh* par_shapes_create_torus(int slices, int stacks, float radius)
  320. {
  321. if (slices < 3 || stacks < 3) {
  322. return 0;
  323. }
  324. assert(radius <= 1.0 && "Use smaller radius to avoid self-intersection.");
  325. assert(radius >= 0.1 && "Use larger radius to avoid self-intersection.");
  326. void* userdata = (void*) &radius;
  327. return par_shapes_create_parametric(par_shapes__torus, slices,
  328. stacks, userdata);
  329. }
  330. par_shapes_mesh* par_shapes_create_klein_bottle(int slices, int stacks)
  331. {
  332. if (slices < 3 || stacks < 3) {
  333. return 0;
  334. }
  335. par_shapes_mesh* mesh = par_shapes_create_parametric(
  336. par_shapes__klein, slices, stacks, 0);
  337. int face = 0;
  338. for (int stack = 0; stack < stacks; stack++) {
  339. for (int slice = 0; slice < slices; slice++, face += 2) {
  340. if (stack < 27 * stacks / 32) {
  341. par_shapes_invert(mesh, face, 2);
  342. }
  343. }
  344. }
  345. par_shapes__compute_welded_normals(mesh);
  346. return mesh;
  347. }
  348. par_shapes_mesh* par_shapes_create_trefoil_knot(int slices, int stacks,
  349. float radius)
  350. {
  351. if (slices < 3 || stacks < 3) {
  352. return 0;
  353. }
  354. assert(radius <= 3.0 && "Use smaller radius to avoid self-intersection.");
  355. assert(radius >= 0.5 && "Use larger radius to avoid self-intersection.");
  356. void* userdata = (void*) &radius;
  357. return par_shapes_create_parametric(par_shapes__trefoil, slices,
  358. stacks, userdata);
  359. }
  360. par_shapes_mesh* par_shapes_create_plane(int slices, int stacks)
  361. {
  362. if (slices < 1 || stacks < 1) {
  363. return 0;
  364. }
  365. return par_shapes_create_parametric(par_shapes__plane, slices,
  366. stacks, 0);
  367. }
  368. par_shapes_mesh* par_shapes_create_parametric(par_shapes_fn fn,
  369. int slices, int stacks, void* userdata)
  370. {
  371. par_shapes_mesh* mesh = PAR_CALLOC(par_shapes_mesh, 1);
  372. // Generate verts.
  373. mesh->npoints = (slices + 1) * (stacks + 1);
  374. mesh->points = PAR_CALLOC(float, 3 * mesh->npoints);
  375. float uv[2];
  376. float xyz[3];
  377. float* points = mesh->points;
  378. for (int stack = 0; stack < stacks + 1; stack++) {
  379. uv[0] = (float) stack / stacks;
  380. for (int slice = 0; slice < slices + 1; slice++) {
  381. uv[1] = (float) slice / slices;
  382. fn(uv, xyz, userdata);
  383. *points++ = xyz[0];
  384. *points++ = xyz[1];
  385. *points++ = xyz[2];
  386. }
  387. }
  388. // Generate texture coordinates.
  389. mesh->tcoords = PAR_CALLOC(float, 2 * mesh->npoints);
  390. float* uvs = mesh->tcoords;
  391. for (int stack = 0; stack < stacks + 1; stack++) {
  392. uv[0] = (float) stack / stacks;
  393. for (int slice = 0; slice < slices + 1; slice++) {
  394. uv[1] = (float) slice / slices;
  395. *uvs++ = uv[0];
  396. *uvs++ = uv[1];
  397. }
  398. }
  399. // Generate faces.
  400. mesh->ntriangles = 2 * slices * stacks;
  401. mesh->triangles = PAR_CALLOC(PAR_SHAPES_T, 3 * mesh->ntriangles);
  402. int v = 0;
  403. PAR_SHAPES_T* face = mesh->triangles;
  404. for (int stack = 0; stack < stacks; stack++) {
  405. for (int slice = 0; slice < slices; slice++) {
  406. int next = slice + 1;
  407. *face++ = v + slice + slices + 1;
  408. *face++ = v + next;
  409. *face++ = v + slice;
  410. *face++ = v + slice + slices + 1;
  411. *face++ = v + next + slices + 1;
  412. *face++ = v + next;
  413. }
  414. v += slices + 1;
  415. }
  416. par_shapes__compute_welded_normals(mesh);
  417. return mesh;
  418. }
  419. void par_shapes_free_mesh(par_shapes_mesh* mesh)
  420. {
  421. PAR_FREE(mesh->points);
  422. PAR_FREE(mesh->triangles);
  423. PAR_FREE(mesh->normals);
  424. PAR_FREE(mesh->tcoords);
  425. PAR_FREE(mesh);
  426. }
  427. void par_shapes_export(par_shapes_mesh const* mesh, char const* filename)
  428. {
  429. FILE* objfile = fopen(filename, "wt");
  430. float const* points = mesh->points;
  431. float const* tcoords = mesh->tcoords;
  432. float const* norms = mesh->normals;
  433. PAR_SHAPES_T const* indices = mesh->triangles;
  434. if (tcoords && norms) {
  435. for (int nvert = 0; nvert < mesh->npoints; nvert++) {
  436. fprintf(objfile, "v %f %f %f\n", points[0], points[1], points[2]);
  437. fprintf(objfile, "vt %f %f\n", tcoords[0], tcoords[1]);
  438. fprintf(objfile, "vn %f %f %f\n", norms[0], norms[1], norms[2]);
  439. points += 3;
  440. norms += 3;
  441. tcoords += 2;
  442. }
  443. for (int nface = 0; nface < mesh->ntriangles; nface++) {
  444. int a = 1 + *indices++;
  445. int b = 1 + *indices++;
  446. int c = 1 + *indices++;
  447. fprintf(objfile, "f %d/%d/%d %d/%d/%d %d/%d/%d\n",
  448. a, a, a, b, b, b, c, c, c);
  449. }
  450. } else if (norms) {
  451. for (int nvert = 0; nvert < mesh->npoints; nvert++) {
  452. fprintf(objfile, "v %f %f %f\n", points[0], points[1], points[2]);
  453. fprintf(objfile, "vn %f %f %f\n", norms[0], norms[1], norms[2]);
  454. points += 3;
  455. norms += 3;
  456. }
  457. for (int nface = 0; nface < mesh->ntriangles; nface++) {
  458. int a = 1 + *indices++;
  459. int b = 1 + *indices++;
  460. int c = 1 + *indices++;
  461. fprintf(objfile, "f %d//%d %d//%d %d//%d\n", a, a, b, b, c, c);
  462. }
  463. } else if (tcoords) {
  464. for (int nvert = 0; nvert < mesh->npoints; nvert++) {
  465. fprintf(objfile, "v %f %f %f\n", points[0], points[1], points[2]);
  466. fprintf(objfile, "vt %f %f\n", tcoords[0], tcoords[1]);
  467. points += 3;
  468. tcoords += 2;
  469. }
  470. for (int nface = 0; nface < mesh->ntriangles; nface++) {
  471. int a = 1 + *indices++;
  472. int b = 1 + *indices++;
  473. int c = 1 + *indices++;
  474. fprintf(objfile, "f %d/%d %d/%d %d/%d\n", a, a, b, b, c, c);
  475. }
  476. } else {
  477. for (int nvert = 0; nvert < mesh->npoints; nvert++) {
  478. fprintf(objfile, "v %f %f %f\n", points[0], points[1], points[2]);
  479. points += 3;
  480. }
  481. for (int nface = 0; nface < mesh->ntriangles; nface++) {
  482. int a = 1 + *indices++;
  483. int b = 1 + *indices++;
  484. int c = 1 + *indices++;
  485. fprintf(objfile, "f %d %d %d\n", a, b, c);
  486. }
  487. }
  488. fclose(objfile);
  489. }
  490. static void par_shapes__sphere(float const* uv, float* xyz, void* userdata)
  491. {
  492. float phi = uv[0] * PAR_PI;
  493. float theta = uv[1] * 2 * PAR_PI;
  494. xyz[0] = cosf(theta) * sinf(phi);
  495. xyz[1] = sinf(theta) * sinf(phi);
  496. xyz[2] = cosf(phi);
  497. }
  498. static void par_shapes__hemisphere(float const* uv, float* xyz, void* userdata)
  499. {
  500. float phi = uv[0] * PAR_PI;
  501. float theta = uv[1] * PAR_PI;
  502. xyz[0] = cosf(theta) * sinf(phi);
  503. xyz[1] = sinf(theta) * sinf(phi);
  504. xyz[2] = cosf(phi);
  505. }
  506. static void par_shapes__plane(float const* uv, float* xyz, void* userdata)
  507. {
  508. xyz[0] = uv[0];
  509. xyz[1] = uv[1];
  510. xyz[2] = 0;
  511. }
  512. static void par_shapes__klein(float const* uv, float* xyz, void* userdata)
  513. {
  514. float u = uv[0] * PAR_PI;
  515. float v = uv[1] * 2 * PAR_PI;
  516. u = u * 2;
  517. if (u < PAR_PI) {
  518. xyz[0] = 3 * cosf(u) * (1 + sinf(u)) + (2 * (1 - cosf(u) / 2)) *
  519. cosf(u) * cosf(v);
  520. xyz[2] = -8 * sinf(u) - 2 * (1 - cosf(u) / 2) * sinf(u) * cosf(v);
  521. } else {
  522. xyz[0] = 3 * cosf(u) * (1 + sinf(u)) + (2 * (1 - cosf(u) / 2)) *
  523. cosf(v + PAR_PI);
  524. xyz[2] = -8 * sinf(u);
  525. }
  526. xyz[1] = -2 * (1 - cosf(u) / 2) * sinf(v);
  527. }
  528. static void par_shapes__cylinder(float const* uv, float* xyz, void* userdata)
  529. {
  530. float theta = uv[1] * 2 * PAR_PI;
  531. xyz[0] = sinf(theta);
  532. xyz[1] = cosf(theta);
  533. xyz[2] = uv[0];
  534. }
  535. static void par_shapes__cone(float const* uv, float* xyz, void* userdata)
  536. {
  537. float r = 1.0f - uv[0];
  538. float theta = uv[1] * 2 * PAR_PI;
  539. xyz[0] = r * sinf(theta);
  540. xyz[1] = r * cosf(theta);
  541. xyz[2] = uv[0];
  542. }
  543. static void par_shapes__torus(float const* uv, float* xyz, void* userdata)
  544. {
  545. float major = 1;
  546. float minor = *((float*) userdata);
  547. float theta = uv[0] * 2 * PAR_PI;
  548. float phi = uv[1] * 2 * PAR_PI;
  549. float beta = major + minor * cosf(phi);
  550. xyz[0] = cosf(theta) * beta;
  551. xyz[1] = sinf(theta) * beta;
  552. xyz[2] = sinf(phi) * minor;
  553. }
  554. static void par_shapes__trefoil(float const* uv, float* xyz, void* userdata)
  555. {
  556. float minor = *((float*) userdata);
  557. const float a = 0.5f;
  558. const float b = 0.3f;
  559. const float c = 0.5f;
  560. const float d = minor * 0.1f;
  561. const float u = (1 - uv[0]) * 4 * PAR_PI;
  562. const float v = uv[1] * 2 * PAR_PI;
  563. const float r = a + b * cos(1.5f * u);
  564. const float x = r * cos(u);
  565. const float y = r * sin(u);
  566. const float z = c * sin(1.5f * u);
  567. float q[3];
  568. q[0] =
  569. -1.5f * b * sin(1.5f * u) * cos(u) - (a + b * cos(1.5f * u)) * sin(u);
  570. q[1] =
  571. -1.5f * b * sin(1.5f * u) * sin(u) + (a + b * cos(1.5f * u)) * cos(u);
  572. q[2] = 1.5f * c * cos(1.5f * u);
  573. par_shapes__normalize3(q);
  574. float qvn[3] = {q[1], -q[0], 0};
  575. par_shapes__normalize3(qvn);
  576. float ww[3];
  577. par_shapes__cross3(ww, q, qvn);
  578. xyz[0] = x + d * (qvn[0] * cos(v) + ww[0] * sin(v));
  579. xyz[1] = y + d * (qvn[1] * cos(v) + ww[1] * sin(v));
  580. xyz[2] = z + d * ww[2] * sin(v);
  581. }
  582. void par_shapes_set_epsilon_welded_normals(float epsilon) {
  583. par_shapes__epsilon_welded_normals = epsilon;
  584. }
  585. void par_shapes_set_epsilon_degenerate_sphere(float epsilon) {
  586. par_shapes__epsilon_degenerate_sphere = epsilon;
  587. }
  588. void par_shapes_merge(par_shapes_mesh* dst, par_shapes_mesh const* src)
  589. {
  590. PAR_SHAPES_T offset = dst->npoints;
  591. int npoints = dst->npoints + src->npoints;
  592. int vecsize = sizeof(float) * 3;
  593. dst->points = PAR_REALLOC(float, dst->points, 3 * npoints);
  594. memcpy(dst->points + 3 * dst->npoints, src->points, vecsize * src->npoints);
  595. dst->npoints = npoints;
  596. if (src->normals || dst->normals) {
  597. dst->normals = PAR_REALLOC(float, dst->normals, 3 * npoints);
  598. if (src->normals) {
  599. memcpy(dst->normals + 3 * offset, src->normals,
  600. vecsize * src->npoints);
  601. }
  602. }
  603. if (src->tcoords || dst->tcoords) {
  604. int uvsize = sizeof(float) * 2;
  605. dst->tcoords = PAR_REALLOC(float, dst->tcoords, 2 * npoints);
  606. if (src->tcoords) {
  607. memcpy(dst->tcoords + 2 * offset, src->tcoords,
  608. uvsize * src->npoints);
  609. }
  610. }
  611. int ntriangles = dst->ntriangles + src->ntriangles;
  612. dst->triangles = PAR_REALLOC(PAR_SHAPES_T, dst->triangles, 3 * ntriangles);
  613. PAR_SHAPES_T* ptriangles = dst->triangles + 3 * dst->ntriangles;
  614. PAR_SHAPES_T const* striangles = src->triangles;
  615. for (int i = 0; i < src->ntriangles; i++) {
  616. *ptriangles++ = offset + *striangles++;
  617. *ptriangles++ = offset + *striangles++;
  618. *ptriangles++ = offset + *striangles++;
  619. }
  620. dst->ntriangles = ntriangles;
  621. }
  622. par_shapes_mesh* par_shapes_create_disk(float radius, int slices,
  623. float const* center, float const* normal)
  624. {
  625. par_shapes_mesh* mesh = PAR_CALLOC(par_shapes_mesh, 1);
  626. mesh->npoints = slices + 1;
  627. mesh->points = PAR_MALLOC(float, 3 * mesh->npoints);
  628. float* points = mesh->points;
  629. *points++ = 0;
  630. *points++ = 0;
  631. *points++ = 0;
  632. for (int i = 0; i < slices; i++) {
  633. float theta = i * PAR_PI * 2 / slices;
  634. *points++ = radius * cos(theta);
  635. *points++ = radius * sin(theta);
  636. *points++ = 0;
  637. }
  638. float nnormal[3] = {normal[0], normal[1], normal[2]};
  639. par_shapes__normalize3(nnormal);
  640. mesh->normals = PAR_MALLOC(float, 3 * mesh->npoints);
  641. float* norms = mesh->normals;
  642. for (int i = 0; i < mesh->npoints; i++) {
  643. *norms++ = nnormal[0];
  644. *norms++ = nnormal[1];
  645. *norms++ = nnormal[2];
  646. }
  647. mesh->ntriangles = slices;
  648. mesh->triangles = PAR_MALLOC(PAR_SHAPES_T, 3 * mesh->ntriangles);
  649. PAR_SHAPES_T* triangles = mesh->triangles;
  650. for (int i = 0; i < slices; i++) {
  651. *triangles++ = 0;
  652. *triangles++ = 1 + i;
  653. *triangles++ = 1 + (i + 1) % slices;
  654. }
  655. float k[3] = {0, 0, -1};
  656. float axis[3];
  657. par_shapes__cross3(axis, nnormal, k);
  658. par_shapes__normalize3(axis);
  659. par_shapes_rotate(mesh, acos(nnormal[2]), axis);
  660. par_shapes_translate(mesh, center[0], center[1], center[2]);
  661. return mesh;
  662. }
  663. par_shapes_mesh* par_shapes_create_empty()
  664. {
  665. return PAR_CALLOC(par_shapes_mesh, 1);
  666. }
  667. void par_shapes_translate(par_shapes_mesh* m, float x, float y, float z)
  668. {
  669. float* points = m->points;
  670. for (int i = 0; i < m->npoints; i++) {
  671. *points++ += x;
  672. *points++ += y;
  673. *points++ += z;
  674. }
  675. }
  676. void par_shapes_rotate(par_shapes_mesh* mesh, float radians, float const* axis)
  677. {
  678. float s = sinf(radians);
  679. float c = cosf(radians);
  680. float x = axis[0];
  681. float y = axis[1];
  682. float z = axis[2];
  683. float xy = x * y;
  684. float yz = y * z;
  685. float zx = z * x;
  686. float oneMinusC = 1.0f - c;
  687. float col0[3] = {
  688. (((x * x) * oneMinusC) + c),
  689. ((xy * oneMinusC) + (z * s)), ((zx * oneMinusC) - (y * s))
  690. };
  691. float col1[3] = {
  692. ((xy * oneMinusC) - (z * s)),
  693. (((y * y) * oneMinusC) + c), ((yz * oneMinusC) + (x * s))
  694. };
  695. float col2[3] = {
  696. ((zx * oneMinusC) + (y * s)),
  697. ((yz * oneMinusC) - (x * s)), (((z * z) * oneMinusC) + c)
  698. };
  699. float* p = mesh->points;
  700. for (int i = 0; i < mesh->npoints; i++, p += 3) {
  701. float x = col0[0] * p[0] + col1[0] * p[1] + col2[0] * p[2];
  702. float y = col0[1] * p[0] + col1[1] * p[1] + col2[1] * p[2];
  703. float z = col0[2] * p[0] + col1[2] * p[1] + col2[2] * p[2];
  704. p[0] = x;
  705. p[1] = y;
  706. p[2] = z;
  707. }
  708. float* n = mesh->normals;
  709. if (n) {
  710. for (int i = 0; i < mesh->npoints; i++, n += 3) {
  711. float x = col0[0] * n[0] + col1[0] * n[1] + col2[0] * n[2];
  712. float y = col0[1] * n[0] + col1[1] * n[1] + col2[1] * n[2];
  713. float z = col0[2] * n[0] + col1[2] * n[1] + col2[2] * n[2];
  714. n[0] = x;
  715. n[1] = y;
  716. n[2] = z;
  717. }
  718. }
  719. }
  720. void par_shapes_scale(par_shapes_mesh* m, float x, float y, float z)
  721. {
  722. float* points = m->points;
  723. for (int i = 0; i < m->npoints; i++) {
  724. *points++ *= x;
  725. *points++ *= y;
  726. *points++ *= z;
  727. }
  728. float* n = m->normals;
  729. if (n && (x != y || x != z || y != z)) {
  730. x = 1.0f / x;
  731. y = 1.0f / y;
  732. z = 1.0f / z;
  733. for (int i = 0; i < m->npoints; i++, n += 3) {
  734. n[0] *= x;
  735. n[1] *= y;
  736. n[2] *= z;
  737. par_shapes__normalize3(n);
  738. }
  739. }
  740. }
  741. void par_shapes_merge_and_free(par_shapes_mesh* dst, par_shapes_mesh* src)
  742. {
  743. par_shapes_merge(dst, src);
  744. par_shapes_free_mesh(src);
  745. }
  746. void par_shapes_compute_aabb(par_shapes_mesh const* m, float* aabb)
  747. {
  748. float* points = m->points;
  749. aabb[0] = aabb[3] = points[0];
  750. aabb[1] = aabb[4] = points[1];
  751. aabb[2] = aabb[5] = points[2];
  752. points += 3;
  753. for (int i = 1; i < m->npoints; i++, points += 3) {
  754. aabb[0] = PAR_MIN(points[0], aabb[0]);
  755. aabb[1] = PAR_MIN(points[1], aabb[1]);
  756. aabb[2] = PAR_MIN(points[2], aabb[2]);
  757. aabb[3] = PAR_MAX(points[0], aabb[3]);
  758. aabb[4] = PAR_MAX(points[1], aabb[4]);
  759. aabb[5] = PAR_MAX(points[2], aabb[5]);
  760. }
  761. }
  762. void par_shapes_invert(par_shapes_mesh* m, int face, int nfaces)
  763. {
  764. nfaces = nfaces ? nfaces : m->ntriangles;
  765. PAR_SHAPES_T* tri = m->triangles + face * 3;
  766. for (int i = 0; i < nfaces; i++) {
  767. PAR_SWAP(PAR_SHAPES_T, tri[0], tri[2]);
  768. tri += 3;
  769. }
  770. }
  771. par_shapes_mesh* par_shapes_create_icosahedron()
  772. {
  773. static float verts[] = {
  774. 0.000, 0.000, 1.000,
  775. 0.894, 0.000, 0.447,
  776. 0.276, 0.851, 0.447,
  777. -0.724, 0.526, 0.447,
  778. -0.724, -0.526, 0.447,
  779. 0.276, -0.851, 0.447,
  780. 0.724, 0.526, -0.447,
  781. -0.276, 0.851, -0.447,
  782. -0.894, 0.000, -0.447,
  783. -0.276, -0.851, -0.447,
  784. 0.724, -0.526, -0.447,
  785. 0.000, 0.000, -1.000
  786. };
  787. static PAR_SHAPES_T faces[] = {
  788. 0,1,2,
  789. 0,2,3,
  790. 0,3,4,
  791. 0,4,5,
  792. 0,5,1,
  793. 7,6,11,
  794. 8,7,11,
  795. 9,8,11,
  796. 10,9,11,
  797. 6,10,11,
  798. 6,2,1,
  799. 7,3,2,
  800. 8,4,3,
  801. 9,5,4,
  802. 10,1,5,
  803. 6,7,2,
  804. 7,8,3,
  805. 8,9,4,
  806. 9,10,5,
  807. 10,6,1
  808. };
  809. par_shapes_mesh* mesh = PAR_CALLOC(par_shapes_mesh, 1);
  810. mesh->npoints = sizeof(verts) / sizeof(verts[0]) / 3;
  811. mesh->points = PAR_MALLOC(float, sizeof(verts) / 4);
  812. memcpy(mesh->points, verts, sizeof(verts));
  813. mesh->ntriangles = sizeof(faces) / sizeof(faces[0]) / 3;
  814. mesh->triangles = PAR_MALLOC(PAR_SHAPES_T, sizeof(faces) / 2);
  815. memcpy(mesh->triangles, faces, sizeof(faces));
  816. return mesh;
  817. }
  818. par_shapes_mesh* par_shapes_create_dodecahedron()
  819. {
  820. static float verts[20 * 3] = {
  821. 0.607, 0.000, 0.795,
  822. 0.188, 0.577, 0.795,
  823. -0.491, 0.357, 0.795,
  824. -0.491, -0.357, 0.795,
  825. 0.188, -0.577, 0.795,
  826. 0.982, 0.000, 0.188,
  827. 0.304, 0.934, 0.188,
  828. -0.795, 0.577, 0.188,
  829. -0.795, -0.577, 0.188,
  830. 0.304, -0.934, 0.188,
  831. 0.795, 0.577, -0.188,
  832. -0.304, 0.934, -0.188,
  833. -0.982, 0.000, -0.188,
  834. -0.304, -0.934, -0.188,
  835. 0.795, -0.577, -0.188,
  836. 0.491, 0.357, -0.795,
  837. -0.188, 0.577, -0.795,
  838. -0.607, 0.000, -0.795,
  839. -0.188, -0.577, -0.795,
  840. 0.491, -0.357, -0.795,
  841. };
  842. static PAR_SHAPES_T pentagons[12 * 5] = {
  843. 0,1,2,3,4,
  844. 5,10,6,1,0,
  845. 6,11,7,2,1,
  846. 7,12,8,3,2,
  847. 8,13,9,4,3,
  848. 9,14,5,0,4,
  849. 15,16,11,6,10,
  850. 16,17,12,7,11,
  851. 17,18,13,8,12,
  852. 18,19,14,9,13,
  853. 19,15,10,5,14,
  854. 19,18,17,16,15
  855. };
  856. int npentagons = sizeof(pentagons) / sizeof(pentagons[0]) / 5;
  857. par_shapes_mesh* mesh = PAR_CALLOC(par_shapes_mesh, 1);
  858. int ncorners = sizeof(verts) / sizeof(verts[0]) / 3;
  859. mesh->npoints = ncorners;
  860. mesh->points = PAR_MALLOC(float, mesh->npoints * 3);
  861. memcpy(mesh->points, verts, sizeof(verts));
  862. PAR_SHAPES_T const* pentagon = pentagons;
  863. mesh->ntriangles = npentagons * 3;
  864. mesh->triangles = PAR_MALLOC(PAR_SHAPES_T, mesh->ntriangles * 3);
  865. PAR_SHAPES_T* tris = mesh->triangles;
  866. for (int p = 0; p < npentagons; p++, pentagon += 5) {
  867. *tris++ = pentagon[0];
  868. *tris++ = pentagon[1];
  869. *tris++ = pentagon[2];
  870. *tris++ = pentagon[0];
  871. *tris++ = pentagon[2];
  872. *tris++ = pentagon[3];
  873. *tris++ = pentagon[0];
  874. *tris++ = pentagon[3];
  875. *tris++ = pentagon[4];
  876. }
  877. return mesh;
  878. }
  879. par_shapes_mesh* par_shapes_create_octahedron()
  880. {
  881. static float verts[6 * 3] = {
  882. 0.000, 0.000, 1.000,
  883. 1.000, 0.000, 0.000,
  884. 0.000, 1.000, 0.000,
  885. -1.000, 0.000, 0.000,
  886. 0.000, -1.000, 0.000,
  887. 0.000, 0.000, -1.000
  888. };
  889. static PAR_SHAPES_T triangles[8 * 3] = {
  890. 0,1,2,
  891. 0,2,3,
  892. 0,3,4,
  893. 0,4,1,
  894. 2,1,5,
  895. 3,2,5,
  896. 4,3,5,
  897. 1,4,5,
  898. };
  899. int ntris = sizeof(triangles) / sizeof(triangles[0]) / 3;
  900. par_shapes_mesh* mesh = PAR_CALLOC(par_shapes_mesh, 1);
  901. int ncorners = sizeof(verts) / sizeof(verts[0]) / 3;
  902. mesh->npoints = ncorners;
  903. mesh->points = PAR_MALLOC(float, mesh->npoints * 3);
  904. memcpy(mesh->points, verts, sizeof(verts));
  905. PAR_SHAPES_T const* triangle = triangles;
  906. mesh->ntriangles = ntris;
  907. mesh->triangles = PAR_MALLOC(PAR_SHAPES_T, mesh->ntriangles * 3);
  908. PAR_SHAPES_T* tris = mesh->triangles;
  909. for (int p = 0; p < ntris; p++) {
  910. *tris++ = *triangle++;
  911. *tris++ = *triangle++;
  912. *tris++ = *triangle++;
  913. }
  914. return mesh;
  915. }
  916. par_shapes_mesh* par_shapes_create_tetrahedron()
  917. {
  918. static float verts[4 * 3] = {
  919. 0.000, 1.333, 0,
  920. 0.943, 0, 0,
  921. -0.471, 0, 0.816,
  922. -0.471, 0, -0.816,
  923. };
  924. static PAR_SHAPES_T triangles[4 * 3] = {
  925. 2,1,0,
  926. 3,2,0,
  927. 1,3,0,
  928. 1,2,3,
  929. };
  930. int ntris = sizeof(triangles) / sizeof(triangles[0]) / 3;
  931. par_shapes_mesh* mesh = PAR_CALLOC(par_shapes_mesh, 1);
  932. int ncorners = sizeof(verts) / sizeof(verts[0]) / 3;
  933. mesh->npoints = ncorners;
  934. mesh->points = PAR_MALLOC(float, mesh->npoints * 3);
  935. memcpy(mesh->points, verts, sizeof(verts));
  936. PAR_SHAPES_T const* triangle = triangles;
  937. mesh->ntriangles = ntris;
  938. mesh->triangles = PAR_MALLOC(PAR_SHAPES_T, mesh->ntriangles * 3);
  939. PAR_SHAPES_T* tris = mesh->triangles;
  940. for (int p = 0; p < ntris; p++) {
  941. *tris++ = *triangle++;
  942. *tris++ = *triangle++;
  943. *tris++ = *triangle++;
  944. }
  945. return mesh;
  946. }
  947. par_shapes_mesh* par_shapes_create_cube()
  948. {
  949. static float verts[8 * 3] = {
  950. 0, 0, 0, // 0
  951. 0, 1, 0, // 1
  952. 1, 1, 0, // 2
  953. 1, 0, 0, // 3
  954. 0, 0, 1, // 4
  955. 0, 1, 1, // 5
  956. 1, 1, 1, // 6
  957. 1, 0, 1, // 7
  958. };
  959. static PAR_SHAPES_T quads[6 * 4] = {
  960. 7,6,5,4, // front
  961. 0,1,2,3, // back
  962. 6,7,3,2, // right
  963. 5,6,2,1, // top
  964. 4,5,1,0, // left
  965. 7,4,0,3, // bottom
  966. };
  967. int nquads = sizeof(quads) / sizeof(quads[0]) / 4;
  968. par_shapes_mesh* mesh = PAR_CALLOC(par_shapes_mesh, 1);
  969. int ncorners = sizeof(verts) / sizeof(verts[0]) / 3;
  970. mesh->npoints = ncorners;
  971. mesh->points = PAR_MALLOC(float, mesh->npoints * 3);
  972. memcpy(mesh->points, verts, sizeof(verts));
  973. PAR_SHAPES_T const* quad = quads;
  974. mesh->ntriangles = nquads * 2;
  975. mesh->triangles = PAR_MALLOC(PAR_SHAPES_T, mesh->ntriangles * 3);
  976. PAR_SHAPES_T* tris = mesh->triangles;
  977. for (int p = 0; p < nquads; p++, quad += 4) {
  978. *tris++ = quad[0];
  979. *tris++ = quad[1];
  980. *tris++ = quad[2];
  981. *tris++ = quad[2];
  982. *tris++ = quad[3];
  983. *tris++ = quad[0];
  984. }
  985. return mesh;
  986. }
  987. typedef struct {
  988. char* cmd;
  989. char* arg;
  990. } par_shapes__command;
  991. typedef struct {
  992. char const* name;
  993. int weight;
  994. int ncommands;
  995. par_shapes__command* commands;
  996. } par_shapes__rule;
  997. typedef struct {
  998. int pc;
  999. float position[3];
  1000. float scale[3];
  1001. par_shapes_mesh* orientation;
  1002. par_shapes__rule* rule;
  1003. } par_shapes__stackframe;
  1004. static par_shapes__rule* par_shapes__pick_rule(const char* name,
  1005. par_shapes__rule* rules, int nrules)
  1006. {
  1007. par_shapes__rule* rule = 0;
  1008. int total = 0;
  1009. for (int i = 0; i < nrules; i++) {
  1010. rule = rules + i;
  1011. if (!strcmp(rule->name, name)) {
  1012. total += rule->weight;
  1013. }
  1014. }
  1015. float r = (float) rand() / RAND_MAX;
  1016. float t = 0;
  1017. for (int i = 0; i < nrules; i++) {
  1018. rule = rules + i;
  1019. if (!strcmp(rule->name, name)) {
  1020. t += (float) rule->weight / total;
  1021. if (t >= r) {
  1022. return rule;
  1023. }
  1024. }
  1025. }
  1026. return rule;
  1027. }
  1028. static par_shapes_mesh* par_shapes__create_turtle()
  1029. {
  1030. const float xaxis[] = {1, 0, 0};
  1031. const float yaxis[] = {0, 1, 0};
  1032. const float zaxis[] = {0, 0, 1};
  1033. par_shapes_mesh* turtle = PAR_CALLOC(par_shapes_mesh, 1);
  1034. turtle->npoints = 3;
  1035. turtle->points = PAR_CALLOC(float, turtle->npoints * 3);
  1036. par_shapes__copy3(turtle->points + 0, xaxis);
  1037. par_shapes__copy3(turtle->points + 3, yaxis);
  1038. par_shapes__copy3(turtle->points + 6, zaxis);
  1039. return turtle;
  1040. }
  1041. static par_shapes_mesh* par_shapes__apply_turtle(par_shapes_mesh* mesh,
  1042. par_shapes_mesh* turtle, float const* pos, float const* scale)
  1043. {
  1044. par_shapes_mesh* m = par_shapes_clone(mesh, 0);
  1045. for (int p = 0; p < m->npoints; p++) {
  1046. float* pt = m->points + p * 3;
  1047. pt[0] *= scale[0];
  1048. pt[1] *= scale[1];
  1049. pt[2] *= scale[2];
  1050. par_shapes__transform3(pt,
  1051. turtle->points + 0, turtle->points + 3, turtle->points + 6);
  1052. pt[0] += pos[0];
  1053. pt[1] += pos[1];
  1054. pt[2] += pos[2];
  1055. }
  1056. return m;
  1057. }
  1058. void par_shapes__connect(par_shapes_mesh* scene, par_shapes_mesh* cylinder,
  1059. int slices)
  1060. {
  1061. int stacks = 1;
  1062. int npoints = (slices + 1) * (stacks + 1);
  1063. assert(scene->npoints >= npoints && "Cannot connect to empty scene.");
  1064. // Create the new point list.
  1065. npoints = scene->npoints + (slices + 1);
  1066. float* points = PAR_MALLOC(float, npoints * 3);
  1067. memcpy(points, scene->points, sizeof(float) * scene->npoints * 3);
  1068. float* newpts = points + scene->npoints * 3;
  1069. memcpy(newpts, cylinder->points + (slices + 1) * 3,
  1070. sizeof(float) * (slices + 1) * 3);
  1071. PAR_FREE(scene->points);
  1072. scene->points = points;
  1073. // Create the new triangle list.
  1074. int ntriangles = scene->ntriangles + 2 * slices * stacks;
  1075. PAR_SHAPES_T* triangles = PAR_MALLOC(PAR_SHAPES_T, ntriangles * 3);
  1076. memcpy(triangles, scene->triangles,
  1077. sizeof(PAR_SHAPES_T) * scene->ntriangles * 3);
  1078. int v = scene->npoints - (slices + 1);
  1079. PAR_SHAPES_T* face = triangles + scene->ntriangles * 3;
  1080. for (int stack = 0; stack < stacks; stack++) {
  1081. for (int slice = 0; slice < slices; slice++) {
  1082. int next = slice + 1;
  1083. *face++ = v + slice + slices + 1;
  1084. *face++ = v + next;
  1085. *face++ = v + slice;
  1086. *face++ = v + slice + slices + 1;
  1087. *face++ = v + next + slices + 1;
  1088. *face++ = v + next;
  1089. }
  1090. v += slices + 1;
  1091. }
  1092. PAR_FREE(scene->triangles);
  1093. scene->triangles = triangles;
  1094. scene->npoints = npoints;
  1095. scene->ntriangles = ntriangles;
  1096. }
  1097. par_shapes_mesh* par_shapes_create_lsystem(char const* text, int slices,
  1098. int maxdepth)
  1099. {
  1100. char* program;
  1101. program = PAR_MALLOC(char, strlen(text) + 1);
  1102. // The first pass counts the number of rules and commands.
  1103. strcpy(program, text);
  1104. char *cmd = strtok(program, " ");
  1105. int nrules = 1;
  1106. int ncommands = 0;
  1107. while (cmd) {
  1108. char *arg = strtok(0, " ");
  1109. if (!arg) {
  1110. puts("lsystem error: unexpected end of program.");
  1111. break;
  1112. }
  1113. if (!strcmp(cmd, "rule")) {
  1114. nrules++;
  1115. } else {
  1116. ncommands++;
  1117. }
  1118. cmd = strtok(0, " ");
  1119. }
  1120. // Allocate space.
  1121. par_shapes__rule* rules = PAR_MALLOC(par_shapes__rule, nrules);
  1122. par_shapes__command* commands = PAR_MALLOC(par_shapes__command, ncommands);
  1123. // Initialize the entry rule.
  1124. par_shapes__rule* current_rule = &rules[0];
  1125. par_shapes__command* current_command = &commands[0];
  1126. current_rule->name = "entry";
  1127. current_rule->weight = 1;
  1128. current_rule->ncommands = 0;
  1129. current_rule->commands = current_command;
  1130. // The second pass fills in the structures.
  1131. strcpy(program, text);
  1132. cmd = strtok(program, " ");
  1133. while (cmd) {
  1134. char *arg = strtok(0, " ");
  1135. if (!strcmp(cmd, "rule")) {
  1136. current_rule++;
  1137. // Split the argument into a rule name and weight.
  1138. char* dot = strchr(arg, '.');
  1139. if (dot) {
  1140. current_rule->weight = atoi(dot + 1);
  1141. *dot = 0;
  1142. } else {
  1143. current_rule->weight = 1;
  1144. }
  1145. current_rule->name = arg;
  1146. current_rule->ncommands = 0;
  1147. current_rule->commands = current_command;
  1148. } else {
  1149. current_rule->ncommands++;
  1150. current_command->cmd = cmd;
  1151. current_command->arg = arg;
  1152. current_command++;
  1153. }
  1154. cmd = strtok(0, " ");
  1155. }
  1156. // For testing purposes, dump out the parsed program.
  1157. #ifdef TEST_PARSE
  1158. for (int i = 0; i < nrules; i++) {
  1159. par_shapes__rule rule = rules[i];
  1160. printf("rule %s.%d\n", rule.name, rule.weight);
  1161. for (int c = 0; c < rule.ncommands; c++) {
  1162. par_shapes__command cmd = rule.commands[c];
  1163. printf("\t%s %s\n", cmd.cmd, cmd.arg);
  1164. }
  1165. }
  1166. #endif
  1167. // Instantiate the aggregated shape and the template shapes.
  1168. par_shapes_mesh* scene = PAR_CALLOC(par_shapes_mesh, 1);
  1169. par_shapes_mesh* tube = par_shapes_create_cylinder(slices, 1);
  1170. par_shapes_mesh* turtle = par_shapes__create_turtle();
  1171. // We're not attempting to support texture coordinates and normals
  1172. // with L-systems, so remove them from the template shape.
  1173. PAR_FREE(tube->normals);
  1174. PAR_FREE(tube->tcoords);
  1175. tube->normals = 0;
  1176. tube->tcoords = 0;
  1177. const float xaxis[] = {1, 0, 0};
  1178. const float yaxis[] = {0, 1, 0};
  1179. const float zaxis[] = {0, 0, 1};
  1180. const float units[] = {1, 1, 1};
  1181. // Execute the L-system program until the stack size is 0.
  1182. par_shapes__stackframe* stack =
  1183. PAR_CALLOC(par_shapes__stackframe, maxdepth);
  1184. int stackptr = 0;
  1185. stack[0].orientation = turtle;
  1186. stack[0].rule = &rules[0];
  1187. par_shapes__copy3(stack[0].scale, units);
  1188. while (stackptr >= 0) {
  1189. par_shapes__stackframe* frame = &stack[stackptr];
  1190. par_shapes__rule* rule = frame->rule;
  1191. par_shapes_mesh* turtle = frame->orientation;
  1192. float* position = frame->position;
  1193. float* scale = frame->scale;
  1194. if (frame->pc >= rule->ncommands) {
  1195. par_shapes_free_mesh(turtle);
  1196. stackptr--;
  1197. continue;
  1198. }
  1199. par_shapes__command* cmd = rule->commands + (frame->pc++);
  1200. #ifdef DUMP_TRACE
  1201. printf("%5s %5s %5s:%d %03d\n", cmd->cmd, cmd->arg, rule->name,
  1202. frame->pc - 1, stackptr);
  1203. #endif
  1204. float value;
  1205. if (!strcmp(cmd->cmd, "shape")) {
  1206. par_shapes_mesh* m = par_shapes__apply_turtle(tube, turtle,
  1207. position, scale);
  1208. if (!strcmp(cmd->arg, "connect")) {
  1209. par_shapes__connect(scene, m, slices);
  1210. } else {
  1211. par_shapes_merge(scene, m);
  1212. }
  1213. par_shapes_free_mesh(m);
  1214. } else if (!strcmp(cmd->cmd, "call") && stackptr < maxdepth - 1) {
  1215. rule = par_shapes__pick_rule(cmd->arg, rules, nrules);
  1216. frame = &stack[++stackptr];
  1217. frame->rule = rule;
  1218. frame->orientation = par_shapes_clone(turtle, 0);
  1219. frame->pc = 0;
  1220. par_shapes__copy3(frame->scale, scale);
  1221. par_shapes__copy3(frame->position, position);
  1222. continue;
  1223. } else {
  1224. value = atof(cmd->arg);
  1225. if (!strcmp(cmd->cmd, "rx")) {
  1226. par_shapes_rotate(turtle, value * PAR_PI / 180.0, xaxis);
  1227. } else if (!strcmp(cmd->cmd, "ry")) {
  1228. par_shapes_rotate(turtle, value * PAR_PI / 180.0, yaxis);
  1229. } else if (!strcmp(cmd->cmd, "rz")) {
  1230. par_shapes_rotate(turtle, value * PAR_PI / 180.0, zaxis);
  1231. } else if (!strcmp(cmd->cmd, "tx")) {
  1232. float vec[3] = {value, 0, 0};
  1233. float t[3] = {
  1234. par_shapes__dot3(turtle->points + 0, vec),
  1235. par_shapes__dot3(turtle->points + 3, vec),
  1236. par_shapes__dot3(turtle->points + 6, vec)
  1237. };
  1238. par_shapes__add3(position, t);
  1239. } else if (!strcmp(cmd->cmd, "ty")) {
  1240. float vec[3] = {0, value, 0};
  1241. float t[3] = {
  1242. par_shapes__dot3(turtle->points + 0, vec),
  1243. par_shapes__dot3(turtle->points + 3, vec),
  1244. par_shapes__dot3(turtle->points + 6, vec)
  1245. };
  1246. par_shapes__add3(position, t);
  1247. } else if (!strcmp(cmd->cmd, "tz")) {
  1248. float vec[3] = {0, 0, value};
  1249. float t[3] = {
  1250. par_shapes__dot3(turtle->points + 0, vec),
  1251. par_shapes__dot3(turtle->points + 3, vec),
  1252. par_shapes__dot3(turtle->points + 6, vec)
  1253. };
  1254. par_shapes__add3(position, t);
  1255. } else if (!strcmp(cmd->cmd, "sx")) {
  1256. scale[0] *= value;
  1257. } else if (!strcmp(cmd->cmd, "sy")) {
  1258. scale[1] *= value;
  1259. } else if (!strcmp(cmd->cmd, "sz")) {
  1260. scale[2] *= value;
  1261. } else if (!strcmp(cmd->cmd, "sa")) {
  1262. scale[0] *= value;
  1263. scale[1] *= value;
  1264. scale[2] *= value;
  1265. }
  1266. }
  1267. }
  1268. PAR_FREE(stack);
  1269. PAR_FREE(program);
  1270. PAR_FREE(rules);
  1271. PAR_FREE(commands);
  1272. return scene;
  1273. }
  1274. void par_shapes_unweld(par_shapes_mesh* mesh, bool create_indices)
  1275. {
  1276. int npoints = mesh->ntriangles * 3;
  1277. float* points = PAR_MALLOC(float, 3 * npoints);
  1278. float* dst = points;
  1279. PAR_SHAPES_T const* index = mesh->triangles;
  1280. for (int i = 0; i < npoints; i++) {
  1281. float const* src = mesh->points + 3 * (*index++);
  1282. *dst++ = src[0];
  1283. *dst++ = src[1];
  1284. *dst++ = src[2];
  1285. }
  1286. PAR_FREE(mesh->points);
  1287. mesh->points = points;
  1288. mesh->npoints = npoints;
  1289. if (create_indices) {
  1290. PAR_SHAPES_T* tris = PAR_MALLOC(PAR_SHAPES_T, 3 * mesh->ntriangles);
  1291. PAR_SHAPES_T* index = tris;
  1292. for (int i = 0; i < mesh->ntriangles * 3; i++) {
  1293. *index++ = i;
  1294. }
  1295. PAR_FREE(mesh->triangles);
  1296. mesh->triangles = tris;
  1297. }
  1298. }
  1299. void par_shapes_compute_normals(par_shapes_mesh* m)
  1300. {
  1301. PAR_FREE(m->normals);
  1302. m->normals = PAR_CALLOC(float, m->npoints * 3);
  1303. PAR_SHAPES_T const* triangle = m->triangles;
  1304. float next[3], prev[3], cp[3];
  1305. for (int f = 0; f < m->ntriangles; f++, triangle += 3) {
  1306. float const* pa = m->points + 3 * triangle[0];
  1307. float const* pb = m->points + 3 * triangle[1];
  1308. float const* pc = m->points + 3 * triangle[2];
  1309. par_shapes__copy3(next, pb);
  1310. par_shapes__subtract3(next, pa);
  1311. par_shapes__copy3(prev, pc);
  1312. par_shapes__subtract3(prev, pa);
  1313. par_shapes__cross3(cp, next, prev);
  1314. par_shapes__add3(m->normals + 3 * triangle[0], cp);
  1315. par_shapes__copy3(next, pc);
  1316. par_shapes__subtract3(next, pb);
  1317. par_shapes__copy3(prev, pa);
  1318. par_shapes__subtract3(prev, pb);
  1319. par_shapes__cross3(cp, next, prev);
  1320. par_shapes__add3(m->normals + 3 * triangle[1], cp);
  1321. par_shapes__copy3(next, pa);
  1322. par_shapes__subtract3(next, pc);
  1323. par_shapes__copy3(prev, pb);
  1324. par_shapes__subtract3(prev, pc);
  1325. par_shapes__cross3(cp, next, prev);
  1326. par_shapes__add3(m->normals + 3 * triangle[2], cp);
  1327. }
  1328. float* normal = m->normals;
  1329. for (int p = 0; p < m->npoints; p++, normal += 3) {
  1330. par_shapes__normalize3(normal);
  1331. }
  1332. }
  1333. static void par_shapes__subdivide(par_shapes_mesh* mesh)
  1334. {
  1335. assert(mesh->npoints == mesh->ntriangles * 3 && "Must be unwelded.");
  1336. int ntriangles = mesh->ntriangles * 4;
  1337. int npoints = ntriangles * 3;
  1338. float* points = PAR_CALLOC(float, npoints * 3);
  1339. float* dpoint = points;
  1340. float const* spoint = mesh->points;
  1341. for (int t = 0; t < mesh->ntriangles; t++, spoint += 9, dpoint += 3) {
  1342. float const* a = spoint;
  1343. float const* b = spoint + 3;
  1344. float const* c = spoint + 6;
  1345. float const* p0 = dpoint;
  1346. float const* p1 = dpoint + 3;
  1347. float const* p2 = dpoint + 6;
  1348. par_shapes__mix3(dpoint, a, b, 0.5);
  1349. par_shapes__mix3(dpoint += 3, b, c, 0.5);
  1350. par_shapes__mix3(dpoint += 3, a, c, 0.5);
  1351. par_shapes__add3(dpoint += 3, a);
  1352. par_shapes__add3(dpoint += 3, p0);
  1353. par_shapes__add3(dpoint += 3, p2);
  1354. par_shapes__add3(dpoint += 3, p0);
  1355. par_shapes__add3(dpoint += 3, b);
  1356. par_shapes__add3(dpoint += 3, p1);
  1357. par_shapes__add3(dpoint += 3, p2);
  1358. par_shapes__add3(dpoint += 3, p1);
  1359. par_shapes__add3(dpoint += 3, c);
  1360. }
  1361. PAR_FREE(mesh->points);
  1362. mesh->points = points;
  1363. mesh->npoints = npoints;
  1364. mesh->ntriangles = ntriangles;
  1365. }
  1366. par_shapes_mesh* par_shapes_create_subdivided_sphere(int nsubd)
  1367. {
  1368. par_shapes_mesh* mesh = par_shapes_create_icosahedron();
  1369. par_shapes_unweld(mesh, false);
  1370. PAR_FREE(mesh->triangles);
  1371. mesh->triangles = 0;
  1372. while (nsubd--) {
  1373. par_shapes__subdivide(mesh);
  1374. }
  1375. for (int i = 0; i < mesh->npoints; i++) {
  1376. par_shapes__normalize3(mesh->points + i * 3);
  1377. }
  1378. mesh->triangles = PAR_MALLOC(PAR_SHAPES_T, 3 * mesh->ntriangles);
  1379. for (int i = 0; i < mesh->ntriangles * 3; i++) {
  1380. mesh->triangles[i] = i;
  1381. }
  1382. par_shapes_mesh* tmp = mesh;
  1383. mesh = par_shapes_weld(mesh, 0.01, 0);
  1384. par_shapes_free_mesh(tmp);
  1385. par_shapes_compute_normals(mesh);
  1386. return mesh;
  1387. }
  1388. par_shapes_mesh* par_shapes_create_rock(int seed, int subd)
  1389. {
  1390. par_shapes_mesh* mesh = par_shapes_create_subdivided_sphere(subd);
  1391. struct osn_context* ctx;
  1392. par__simplex_noise(seed, &ctx);
  1393. for (int p = 0; p < mesh->npoints; p++) {
  1394. float* pt = mesh->points + p * 3;
  1395. float a = 0.25, f = 1.0;
  1396. double n = a * par__simplex_noise2(ctx, f * pt[0], f * pt[2]);
  1397. a *= 0.5; f *= 2;
  1398. n += a * par__simplex_noise2(ctx, f * pt[0], f * pt[2]);
  1399. pt[0] *= 1 + 2 * n;
  1400. pt[1] *= 1 + n;
  1401. pt[2] *= 1 + 2 * n;
  1402. if (pt[1] < 0) {
  1403. pt[1] = -pow(-pt[1], 0.5) / 2;
  1404. }
  1405. }
  1406. par__simplex_noise_free(ctx);
  1407. par_shapes_compute_normals(mesh);
  1408. return mesh;
  1409. }
  1410. par_shapes_mesh* par_shapes_clone(par_shapes_mesh const* mesh,
  1411. par_shapes_mesh* clone)
  1412. {
  1413. if (!clone) {
  1414. clone = PAR_CALLOC(par_shapes_mesh, 1);
  1415. }
  1416. clone->npoints = mesh->npoints;
  1417. clone->points = PAR_REALLOC(float, clone->points, 3 * clone->npoints);
  1418. memcpy(clone->points, mesh->points, sizeof(float) * 3 * clone->npoints);
  1419. clone->ntriangles = mesh->ntriangles;
  1420. clone->triangles = PAR_REALLOC(PAR_SHAPES_T, clone->triangles, 3 *
  1421. clone->ntriangles);
  1422. memcpy(clone->triangles, mesh->triangles,
  1423. sizeof(PAR_SHAPES_T) * 3 * clone->ntriangles);
  1424. if (mesh->normals) {
  1425. clone->normals = PAR_REALLOC(float, clone->normals, 3 * clone->npoints);
  1426. memcpy(clone->normals, mesh->normals,
  1427. sizeof(float) * 3 * clone->npoints);
  1428. }
  1429. if (mesh->tcoords) {
  1430. clone->tcoords = PAR_REALLOC(float, clone->tcoords, 2 * clone->npoints);
  1431. memcpy(clone->tcoords, mesh->tcoords,
  1432. sizeof(float) * 2 * clone->npoints);
  1433. }
  1434. return clone;
  1435. }
  1436. static struct {
  1437. float const* points;
  1438. int gridsize;
  1439. } par_shapes__sort_context;
  1440. static int par_shapes__cmp1(const void *arg0, const void *arg1)
  1441. {
  1442. const int g = par_shapes__sort_context.gridsize;
  1443. // Convert arg0 into a flattened grid index.
  1444. PAR_SHAPES_T d0 = *(const PAR_SHAPES_T*) arg0;
  1445. float const* p0 = par_shapes__sort_context.points + d0 * 3;
  1446. int i0 = (int) p0[0];
  1447. int j0 = (int) p0[1];
  1448. int k0 = (int) p0[2];
  1449. int index0 = i0 + g * j0 + g * g * k0;
  1450. // Convert arg1 into a flattened grid index.
  1451. PAR_SHAPES_T d1 = *(const PAR_SHAPES_T*) arg1;
  1452. float const* p1 = par_shapes__sort_context.points + d1 * 3;
  1453. int i1 = (int) p1[0];
  1454. int j1 = (int) p1[1];
  1455. int k1 = (int) p1[2];
  1456. int index1 = i1 + g * j1 + g * g * k1;
  1457. // Return the ordering.
  1458. if (index0 < index1) return -1;
  1459. if (index0 > index1) return 1;
  1460. return 0;
  1461. }
  1462. static void par_shapes__sort_points(par_shapes_mesh* mesh, int gridsize,
  1463. PAR_SHAPES_T* sortmap)
  1464. {
  1465. // Run qsort over a list of consecutive integers that get deferenced
  1466. // within the comparator function; this creates a reorder mapping.
  1467. for (int i = 0; i < mesh->npoints; i++) {
  1468. sortmap[i] = i;
  1469. }
  1470. par_shapes__sort_context.gridsize = gridsize;
  1471. par_shapes__sort_context.points = mesh->points;
  1472. qsort(sortmap, mesh->npoints, sizeof(PAR_SHAPES_T), par_shapes__cmp1);
  1473. // Apply the reorder mapping to the XYZ coordinate data.
  1474. float* newpts = PAR_MALLOC(float, mesh->npoints * 3);
  1475. PAR_SHAPES_T* invmap = PAR_MALLOC(PAR_SHAPES_T, mesh->npoints);
  1476. float* dstpt = newpts;
  1477. for (int i = 0; i < mesh->npoints; i++) {
  1478. invmap[sortmap[i]] = i;
  1479. float const* srcpt = mesh->points + 3 * sortmap[i];
  1480. *dstpt++ = *srcpt++;
  1481. *dstpt++ = *srcpt++;
  1482. *dstpt++ = *srcpt++;
  1483. }
  1484. PAR_FREE(mesh->points);
  1485. mesh->points = newpts;
  1486. // Apply the inverse reorder mapping to the triangle indices.
  1487. PAR_SHAPES_T* newinds = PAR_MALLOC(PAR_SHAPES_T, mesh->ntriangles * 3);
  1488. PAR_SHAPES_T* dstind = newinds;
  1489. PAR_SHAPES_T const* srcind = mesh->triangles;
  1490. for (int i = 0; i < mesh->ntriangles * 3; i++) {
  1491. *dstind++ = invmap[*srcind++];
  1492. }
  1493. PAR_FREE(mesh->triangles);
  1494. mesh->triangles = newinds;
  1495. // Cleanup.
  1496. memcpy(sortmap, invmap, sizeof(PAR_SHAPES_T) * mesh->npoints);
  1497. PAR_FREE(invmap);
  1498. }
  1499. static void par_shapes__weld_points(par_shapes_mesh* mesh, int gridsize,
  1500. float epsilon, PAR_SHAPES_T* weldmap)
  1501. {
  1502. // Each bin contains a "pointer" (really an index) to its first point.
  1503. // We add 1 because 0 is reserved to mean that the bin is empty.
  1504. // Since the points are spatially sorted, there's no need to store
  1505. // a point count in each bin.
  1506. PAR_SHAPES_T* bins = PAR_CALLOC(PAR_SHAPES_T,
  1507. gridsize * gridsize * gridsize);
  1508. int prev_binindex = -1;
  1509. for (int p = 0; p < mesh->npoints; p++) {
  1510. float const* pt = mesh->points + p * 3;
  1511. int i = (int) pt[0];
  1512. int j = (int) pt[1];
  1513. int k = (int) pt[2];
  1514. int this_binindex = i + gridsize * j + gridsize * gridsize * k;
  1515. if (this_binindex != prev_binindex) {
  1516. bins[this_binindex] = 1 + p;
  1517. }
  1518. prev_binindex = this_binindex;
  1519. }
  1520. // Examine all bins that intersect the epsilon-sized cube centered at each
  1521. // point, and check for colocated points within those bins.
  1522. float const* pt = mesh->points;
  1523. int nremoved = 0;
  1524. for (int p = 0; p < mesh->npoints; p++, pt += 3) {
  1525. // Skip if this point has already been welded.
  1526. if (weldmap[p] != p) {
  1527. continue;
  1528. }
  1529. // Build a list of bins that intersect the epsilon-sized cube.
  1530. int nearby[8];
  1531. int nbins = 0;
  1532. int minp[3], maxp[3];
  1533. for (int c = 0; c < 3; c++) {
  1534. minp[c] = (int) (pt[c] - epsilon);
  1535. maxp[c] = (int) (pt[c] + epsilon);
  1536. }
  1537. for (int i = minp[0]; i <= maxp[0]; i++) {
  1538. for (int j = minp[1]; j <= maxp[1]; j++) {
  1539. for (int k = minp[2]; k <= maxp[2]; k++) {
  1540. int binindex = i + gridsize * j + gridsize * gridsize * k;
  1541. PAR_SHAPES_T binvalue = *(bins + binindex);
  1542. if (binvalue > 0) {
  1543. if (nbins == 8) {
  1544. printf("Epsilon value is too large.\n");
  1545. break;
  1546. }
  1547. nearby[nbins++] = binindex;
  1548. }
  1549. }
  1550. }
  1551. }
  1552. // Check for colocated points in each nearby bin.
  1553. for (int b = 0; b < nbins; b++) {
  1554. int binindex = nearby[b];
  1555. PAR_SHAPES_T binvalue = bins[binindex];
  1556. PAR_SHAPES_T nindex = binvalue - 1;
  1557. assert(nindex < mesh->npoints);
  1558. while (true) {
  1559. // If this isn't "self" and it's colocated, then weld it!
  1560. if (nindex != p && weldmap[nindex] == nindex) {
  1561. float const* thatpt = mesh->points + nindex * 3;
  1562. float dist2 = par_shapes__sqrdist3(thatpt, pt);
  1563. if (dist2 < epsilon) {
  1564. weldmap[nindex] = p;
  1565. nremoved++;
  1566. }
  1567. }
  1568. // Advance to the next point if possible.
  1569. if (++nindex >= mesh->npoints) {
  1570. break;
  1571. }
  1572. // If the next point is outside the bin, then we're done.
  1573. float const* nextpt = mesh->points + nindex * 3;
  1574. int i = (int) nextpt[0];
  1575. int j = (int) nextpt[1];
  1576. int k = (int) nextpt[2];
  1577. int nextbinindex = i + gridsize * j + gridsize * gridsize * k;
  1578. if (nextbinindex != binindex) {
  1579. break;
  1580. }
  1581. }
  1582. }
  1583. }
  1584. PAR_FREE(bins);
  1585. // Apply the weldmap to the vertices.
  1586. int npoints = mesh->npoints - nremoved;
  1587. float* newpts = PAR_MALLOC(float, 3 * npoints);
  1588. float* dst = newpts;
  1589. PAR_SHAPES_T* condensed_map = PAR_MALLOC(PAR_SHAPES_T, mesh->npoints);
  1590. PAR_SHAPES_T* cmap = condensed_map;
  1591. float const* src = mesh->points;
  1592. int ci = 0;
  1593. for (int p = 0; p < mesh->npoints; p++, src += 3) {
  1594. if (weldmap[p] == p) {
  1595. *dst++ = src[0];
  1596. *dst++ = src[1];
  1597. *dst++ = src[2];
  1598. *cmap++ = ci++;
  1599. } else {
  1600. *cmap++ = condensed_map[weldmap[p]];
  1601. }
  1602. }
  1603. assert(ci == npoints);
  1604. PAR_FREE(mesh->points);
  1605. memcpy(weldmap, condensed_map, mesh->npoints * sizeof(PAR_SHAPES_T));
  1606. PAR_FREE(condensed_map);
  1607. mesh->points = newpts;
  1608. mesh->npoints = npoints;
  1609. // Apply the weldmap to the triangle indices and skip the degenerates.
  1610. PAR_SHAPES_T const* tsrc = mesh->triangles;
  1611. PAR_SHAPES_T* tdst = mesh->triangles;
  1612. int ntriangles = 0;
  1613. for (int i = 0; i < mesh->ntriangles; i++, tsrc += 3) {
  1614. PAR_SHAPES_T a = weldmap[tsrc[0]];
  1615. PAR_SHAPES_T b = weldmap[tsrc[1]];
  1616. PAR_SHAPES_T c = weldmap[tsrc[2]];
  1617. if (a != b && a != c && b != c) {
  1618. assert(a < mesh->npoints);
  1619. assert(b < mesh->npoints);
  1620. assert(c < mesh->npoints);
  1621. *tdst++ = a;
  1622. *tdst++ = b;
  1623. *tdst++ = c;
  1624. ntriangles++;
  1625. }
  1626. }
  1627. mesh->ntriangles = ntriangles;
  1628. }
  1629. par_shapes_mesh* par_shapes_weld(par_shapes_mesh const* mesh, float epsilon,
  1630. PAR_SHAPES_T* weldmap)
  1631. {
  1632. par_shapes_mesh* clone = par_shapes_clone(mesh, 0);
  1633. float aabb[6];
  1634. int gridsize = 20;
  1635. float maxcell = gridsize - 1;
  1636. par_shapes_compute_aabb(clone, aabb);
  1637. float scale[3] = {
  1638. aabb[3] == aabb[0] ? 1.0f : maxcell / (aabb[3] - aabb[0]),
  1639. aabb[4] == aabb[1] ? 1.0f : maxcell / (aabb[4] - aabb[1]),
  1640. aabb[5] == aabb[2] ? 1.0f : maxcell / (aabb[5] - aabb[2]),
  1641. };
  1642. par_shapes_translate(clone, -aabb[0], -aabb[1], -aabb[2]);
  1643. par_shapes_scale(clone, scale[0], scale[1], scale[2]);
  1644. PAR_SHAPES_T* sortmap = PAR_MALLOC(PAR_SHAPES_T, mesh->npoints);
  1645. par_shapes__sort_points(clone, gridsize, sortmap);
  1646. bool owner = false;
  1647. if (!weldmap) {
  1648. owner = true;
  1649. weldmap = PAR_MALLOC(PAR_SHAPES_T, mesh->npoints);
  1650. }
  1651. for (int i = 0; i < mesh->npoints; i++) {
  1652. weldmap[i] = i;
  1653. }
  1654. par_shapes__weld_points(clone, gridsize, epsilon, weldmap);
  1655. if (owner) {
  1656. PAR_FREE(weldmap);
  1657. } else {
  1658. PAR_SHAPES_T* newmap = PAR_MALLOC(PAR_SHAPES_T, mesh->npoints);
  1659. for (int i = 0; i < mesh->npoints; i++) {
  1660. newmap[i] = weldmap[sortmap[i]];
  1661. }
  1662. memcpy(weldmap, newmap, sizeof(PAR_SHAPES_T) * mesh->npoints);
  1663. PAR_FREE(newmap);
  1664. }
  1665. PAR_FREE(sortmap);
  1666. par_shapes_scale(clone, 1.0 / scale[0], 1.0 / scale[1], 1.0 / scale[2]);
  1667. par_shapes_translate(clone, aabb[0], aabb[1], aabb[2]);
  1668. return clone;
  1669. }
  1670. // -----------------------------------------------------------------------------
  1671. // BEGIN OPEN SIMPLEX NOISE
  1672. // -----------------------------------------------------------------------------
  1673. #define STRETCH_CONSTANT_2D (-0.211324865405187) // (1 / sqrt(2 + 1) - 1 ) / 2;
  1674. #define SQUISH_CONSTANT_2D (0.366025403784439) // (sqrt(2 + 1) -1) / 2;
  1675. #define STRETCH_CONSTANT_3D (-1.0 / 6.0) // (1 / sqrt(3 + 1) - 1) / 3;
  1676. #define SQUISH_CONSTANT_3D (1.0 / 3.0) // (sqrt(3+1)-1)/3;
  1677. #define STRETCH_CONSTANT_4D (-0.138196601125011) // (1 / sqrt(4 + 1) - 1) / 4;
  1678. #define SQUISH_CONSTANT_4D (0.309016994374947) // (sqrt(4 + 1) - 1) / 4;
  1679. #define NORM_CONSTANT_2D (47.0)
  1680. #define NORM_CONSTANT_3D (103.0)
  1681. #define NORM_CONSTANT_4D (30.0)
  1682. #define DEFAULT_SEED (0LL)
  1683. struct osn_context {
  1684. int16_t* perm;
  1685. int16_t* permGradIndex3D;
  1686. };
  1687. #define ARRAYSIZE(x) (sizeof((x)) / sizeof((x)[0]))
  1688. /*
  1689. * Gradients for 2D. They approximate the directions to the
  1690. * vertices of an octagon from the center.
  1691. */
  1692. static const int8_t gradients2D[] = {
  1693. 5, 2, 2, 5, -5, 2, -2, 5, 5, -2, 2, -5, -5, -2, -2, -5,
  1694. };
  1695. /*
  1696. * Gradients for 3D. They approximate the directions to the
  1697. * vertices of a rhombicuboctahedron from the center, skewed so
  1698. * that the triangular and square facets can be inscribed inside
  1699. * circles of the same radius.
  1700. */
  1701. static const signed char gradients3D[] = {
  1702. -11, 4, 4, -4, 11, 4, -4, 4, 11, 11, 4, 4, 4, 11, 4, 4, 4, 11, -11, -4, 4,
  1703. -4, -11, 4, -4, -4, 11, 11, -4, 4, 4, -11, 4, 4, -4, 11, -11, 4, -4, -4, 11,
  1704. -4, -4, 4, -11, 11, 4, -4, 4, 11, -4, 4, 4, -11, -11, -4, -4, -4, -11, -4,
  1705. -4, -4, -11, 11, -4, -4, 4, -11, -4, 4, -4, -11,
  1706. };
  1707. /*
  1708. * Gradients for 4D. They approximate the directions to the
  1709. * vertices of a disprismatotesseractihexadecachoron from the center,
  1710. * skewed so that the tetrahedral and cubic facets can be inscribed inside
  1711. * spheres of the same radius.
  1712. */
  1713. static const signed char gradients4D[] = {
  1714. 3, 1, 1, 1, 1, 3, 1, 1, 1, 1, 3, 1, 1, 1, 1, 3, -3, 1, 1, 1, -1, 3, 1, 1,
  1715. -1, 1, 3, 1, -1, 1, 1, 3, 3, -1, 1, 1, 1, -3, 1, 1, 1, -1, 3, 1, 1, -1, 1,
  1716. 3, -3, -1, 1, 1, -1, -3, 1, 1, -1, -1, 3, 1, -1, -1, 1, 3, 3, 1, -1, 1, 1,
  1717. 3, -1, 1, 1, 1, -3, 1, 1, 1, -1, 3, -3, 1, -1, 1, -1, 3, -1, 1, -1, 1, -3,
  1718. 1, -1, 1, -1, 3, 3, -1, -1, 1, 1, -3, -1, 1, 1, -1, -3, 1, 1, -1, -1, 3, -3,
  1719. -1, -1, 1, -1, -3, -1, 1, -1, -1, -3, 1, -1, -1, -1, 3, 3, 1, 1, -1, 1, 3,
  1720. 1, -1, 1, 1, 3, -1, 1, 1, 1, -3, -3, 1, 1, -1, -1, 3, 1, -1, -1, 1, 3, -1,
  1721. -1, 1, 1, -3, 3, -1, 1, -1, 1, -3, 1, -1, 1, -1, 3, -1, 1, -1, 1, -3, -3,
  1722. -1, 1, -1, -1, -3, 1, -1, -1, -1, 3, -1, -1, -1, 1, -3, 3, 1, -1, -1, 1, 3,
  1723. -1, -1, 1, 1, -3, -1, 1, 1, -1, -3, -3, 1, -1, -1, -1, 3, -1, -1, -1, 1, -3,
  1724. -1, -1, 1, -1, -3, 3, -1, -1, -1, 1, -3, -1, -1, 1, -1, -3, -1, 1, -1, -1,
  1725. -3, -3, -1, -1, -1, -1, -3, -1, -1, -1, -1, -3, -1, -1, -1, -1, -3,
  1726. };
  1727. static double extrapolate2(
  1728. struct osn_context* ctx, int xsb, int ysb, double dx, double dy)
  1729. {
  1730. int16_t* perm = ctx->perm;
  1731. int index = perm[(perm[xsb & 0xFF] + ysb) & 0xFF] & 0x0E;
  1732. return gradients2D[index] * dx + gradients2D[index + 1] * dy;
  1733. }
  1734. static inline int fastFloor(double x)
  1735. {
  1736. int xi = (int) x;
  1737. return x < xi ? xi - 1 : xi;
  1738. }
  1739. static int allocate_perm(struct osn_context* ctx, int nperm, int ngrad)
  1740. {
  1741. PAR_FREE(ctx->perm);
  1742. PAR_FREE(ctx->permGradIndex3D);
  1743. ctx->perm = PAR_MALLOC(int16_t, nperm);
  1744. if (!ctx->perm) {
  1745. return -ENOMEM;
  1746. }
  1747. ctx->permGradIndex3D = PAR_MALLOC(int16_t, ngrad);
  1748. if (!ctx->permGradIndex3D) {
  1749. PAR_FREE(ctx->perm);
  1750. return -ENOMEM;
  1751. }
  1752. return 0;
  1753. }
  1754. static int par__simplex_noise(int64_t seed, struct osn_context** ctx)
  1755. {
  1756. int rc;
  1757. int16_t source[256];
  1758. int i;
  1759. int16_t* perm;
  1760. int16_t* permGradIndex3D;
  1761. *ctx = PAR_MALLOC(struct osn_context, 1);
  1762. if (!(*ctx)) {
  1763. return -ENOMEM;
  1764. }
  1765. (*ctx)->perm = NULL;
  1766. (*ctx)->permGradIndex3D = NULL;
  1767. rc = allocate_perm(*ctx, 256, 256);
  1768. if (rc) {
  1769. PAR_FREE(*ctx);
  1770. return rc;
  1771. }
  1772. perm = (*ctx)->perm;
  1773. permGradIndex3D = (*ctx)->permGradIndex3D;
  1774. for (i = 0; i < 256; i++) {
  1775. source[i] = (int16_t) i;
  1776. }
  1777. seed = seed * 6364136223846793005LL + 1442695040888963407LL;
  1778. seed = seed * 6364136223846793005LL + 1442695040888963407LL;
  1779. seed = seed * 6364136223846793005LL + 1442695040888963407LL;
  1780. for (i = 255; i >= 0; i--) {
  1781. seed = seed * 6364136223846793005LL + 1442695040888963407LL;
  1782. int r = (int) ((seed + 31) % (i + 1));
  1783. if (r < 0)
  1784. r += (i + 1);
  1785. perm[i] = source[r];
  1786. permGradIndex3D[i] =
  1787. (short) ((perm[i] % (ARRAYSIZE(gradients3D) / 3)) * 3);
  1788. source[r] = source[i];
  1789. }
  1790. return 0;
  1791. }
  1792. static void par__simplex_noise_free(struct osn_context* ctx)
  1793. {
  1794. if (!ctx)
  1795. return;
  1796. if (ctx->perm) {
  1797. PAR_FREE(ctx->perm);
  1798. ctx->perm = NULL;
  1799. }
  1800. if (ctx->permGradIndex3D) {
  1801. PAR_FREE(ctx->permGradIndex3D);
  1802. ctx->permGradIndex3D = NULL;
  1803. }
  1804. PAR_FREE(ctx);
  1805. }
  1806. static double par__simplex_noise2(struct osn_context* ctx, double x, double y)
  1807. {
  1808. // Place input coordinates onto grid.
  1809. double stretchOffset = (x + y) * STRETCH_CONSTANT_2D;
  1810. double xs = x + stretchOffset;
  1811. double ys = y + stretchOffset;
  1812. // Floor to get grid coordinates of rhombus (stretched square) super-cell
  1813. // origin.
  1814. int xsb = fastFloor(xs);
  1815. int ysb = fastFloor(ys);
  1816. // Skew out to get actual coordinates of rhombus origin. We'll need these
  1817. // later.
  1818. double squishOffset = (xsb + ysb) * SQUISH_CONSTANT_2D;
  1819. double xb = xsb + squishOffset;
  1820. double yb = ysb + squishOffset;
  1821. // Compute grid coordinates relative to rhombus origin.
  1822. double xins = xs - xsb;
  1823. double yins = ys - ysb;
  1824. // Sum those together to get a value that determines which region we're in.
  1825. double inSum = xins + yins;
  1826. // Positions relative to origin point.
  1827. double dx0 = x - xb;
  1828. double dy0 = y - yb;
  1829. // We'll be defining these inside the next block and using them afterwards.
  1830. double dx_ext, dy_ext;
  1831. int xsv_ext, ysv_ext;
  1832. double value = 0;
  1833. // Contribution (1,0)
  1834. double dx1 = dx0 - 1 - SQUISH_CONSTANT_2D;
  1835. double dy1 = dy0 - 0 - SQUISH_CONSTANT_2D;
  1836. double attn1 = 2 - dx1 * dx1 - dy1 * dy1;
  1837. if (attn1 > 0) {
  1838. attn1 *= attn1;
  1839. value += attn1 * attn1 * extrapolate2(ctx, xsb + 1, ysb + 0, dx1, dy1);
  1840. }
  1841. // Contribution (0,1)
  1842. double dx2 = dx0 - 0 - SQUISH_CONSTANT_2D;
  1843. double dy2 = dy0 - 1 - SQUISH_CONSTANT_2D;
  1844. double attn2 = 2 - dx2 * dx2 - dy2 * dy2;
  1845. if (attn2 > 0) {
  1846. attn2 *= attn2;
  1847. value += attn2 * attn2 * extrapolate2(ctx, xsb + 0, ysb + 1, dx2, dy2);
  1848. }
  1849. if (inSum <= 1) { // We're inside the triangle (2-Simplex) at (0,0)
  1850. double zins = 1 - inSum;
  1851. if (zins > xins || zins > yins) {
  1852. if (xins > yins) {
  1853. xsv_ext = xsb + 1;
  1854. ysv_ext = ysb - 1;
  1855. dx_ext = dx0 - 1;
  1856. dy_ext = dy0 + 1;
  1857. } else {
  1858. xsv_ext = xsb - 1;
  1859. ysv_ext = ysb + 1;
  1860. dx_ext = dx0 + 1;
  1861. dy_ext = dy0 - 1;
  1862. }
  1863. } else { //(1,0) and (0,1) are the closest two vertices.
  1864. xsv_ext = xsb + 1;
  1865. ysv_ext = ysb + 1;
  1866. dx_ext = dx0 - 1 - 2 * SQUISH_CONSTANT_2D;
  1867. dy_ext = dy0 - 1 - 2 * SQUISH_CONSTANT_2D;
  1868. }
  1869. } else { // We're inside the triangle (2-Simplex) at (1,1)
  1870. double zins = 2 - inSum;
  1871. if (zins < xins || zins < yins) {
  1872. if (xins > yins) {
  1873. xsv_ext = xsb + 2;
  1874. ysv_ext = ysb + 0;
  1875. dx_ext = dx0 - 2 - 2 * SQUISH_CONSTANT_2D;
  1876. dy_ext = dy0 + 0 - 2 * SQUISH_CONSTANT_2D;
  1877. } else {
  1878. xsv_ext = xsb + 0;
  1879. ysv_ext = ysb + 2;
  1880. dx_ext = dx0 + 0 - 2 * SQUISH_CONSTANT_2D;
  1881. dy_ext = dy0 - 2 - 2 * SQUISH_CONSTANT_2D;
  1882. }
  1883. } else { //(1,0) and (0,1) are the closest two vertices.
  1884. dx_ext = dx0;
  1885. dy_ext = dy0;
  1886. xsv_ext = xsb;
  1887. ysv_ext = ysb;
  1888. }
  1889. xsb += 1;
  1890. ysb += 1;
  1891. dx0 = dx0 - 1 - 2 * SQUISH_CONSTANT_2D;
  1892. dy0 = dy0 - 1 - 2 * SQUISH_CONSTANT_2D;
  1893. }
  1894. // Contribution (0,0) or (1,1)
  1895. double attn0 = 2 - dx0 * dx0 - dy0 * dy0;
  1896. if (attn0 > 0) {
  1897. attn0 *= attn0;
  1898. value += attn0 * attn0 * extrapolate2(ctx, xsb, ysb, dx0, dy0);
  1899. }
  1900. // Extra Vertex
  1901. double attn_ext = 2 - dx_ext * dx_ext - dy_ext * dy_ext;
  1902. if (attn_ext > 0) {
  1903. attn_ext *= attn_ext;
  1904. value += attn_ext * attn_ext *
  1905. extrapolate2(ctx, xsv_ext, ysv_ext, dx_ext, dy_ext);
  1906. }
  1907. return value / NORM_CONSTANT_2D;
  1908. }
  1909. void par_shapes_remove_degenerate(par_shapes_mesh* mesh, float mintriarea)
  1910. {
  1911. int ntriangles = 0;
  1912. PAR_SHAPES_T* triangles = PAR_MALLOC(PAR_SHAPES_T, mesh->ntriangles * 3);
  1913. PAR_SHAPES_T* dst = triangles;
  1914. PAR_SHAPES_T const* src = mesh->triangles;
  1915. float next[3], prev[3], cp[3];
  1916. float mincplen2 = (mintriarea * 2) * (mintriarea * 2);
  1917. for (int f = 0; f < mesh->ntriangles; f++, src += 3) {
  1918. float const* pa = mesh->points + 3 * src[0];
  1919. float const* pb = mesh->points + 3 * src[1];
  1920. float const* pc = mesh->points + 3 * src[2];
  1921. par_shapes__copy3(next, pb);
  1922. par_shapes__subtract3(next, pa);
  1923. par_shapes__copy3(prev, pc);
  1924. par_shapes__subtract3(prev, pa);
  1925. par_shapes__cross3(cp, next, prev);
  1926. float cplen2 = par_shapes__dot3(cp, cp);
  1927. if (cplen2 >= mincplen2) {
  1928. *dst++ = src[0];
  1929. *dst++ = src[1];
  1930. *dst++ = src[2];
  1931. ntriangles++;
  1932. }
  1933. }
  1934. mesh->ntriangles = ntriangles;
  1935. PAR_FREE(mesh->triangles);
  1936. mesh->triangles = triangles;
  1937. }
  1938. #endif // PAR_SHAPES_IMPLEMENTATION
  1939. #endif // PAR_SHAPES_H
  1940. // par_shapes is distributed under the MIT license:
  1941. //
  1942. // Copyright (c) 2019 Philip Rideout
  1943. //
  1944. // Permission is hereby granted, free of charge, to any person obtaining a copy
  1945. // of this software and associated documentation files (the "Software"), to deal
  1946. // in the Software without restriction, including without limitation the rights
  1947. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  1948. // copies of the Software, and to permit persons to whom the Software is
  1949. // furnished to do so, subject to the following conditions:
  1950. //
  1951. // The above copyright notice and this permission notice shall be included in
  1952. // all copies or substantial portions of the Software.
  1953. //
  1954. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  1955. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  1956. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  1957. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  1958. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  1959. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  1960. // SOFTWARE.