meshgen.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729
  1. #include <stdlib.h>
  2. #include <stdio.h>
  3. #include <string.h>
  4. #include <math.h>
  5. #include "c3dlas.h"
  6. #include "meshgen.h"
  7. #if 0
  8. // in the x-y plane, 0,0 at the lower left
  9. void mgGenFlatPatch(short width, short height, IndexedPatch* out) {
  10. int cnt; // programming is more fun if you mentally read this as "cunt"
  11. int x, y;
  12. int ii; // index index
  13. cnt = (width + 1) * (height + 1); // plus one for the edge
  14. out->nElements = width * height * 2;
  15. out->nVertices = out->nNormals = cnt;
  16. out->nIndices = out->nElements * 3;
  17. out->width = width;
  18. out->height = height;
  19. out->vertices = (Vector3*)malloc(cnt * sizeof(Vector3));
  20. out->normals = (Vector3*)malloc(cnt * sizeof(Vector3));
  21. out->indices = (short*)malloc(cnt * sizeof(short) * 6); // too big but we'll fix that later
  22. // fill in the vertices and normals
  23. for(y = 0; y < height + 1; y++) {
  24. for(x = 0; x < width + 1; x++) {
  25. Vector3* v, *n;
  26. v = &out->vertices[x+(y*(width+1))];
  27. n = &out->normals[x+(y*(width+1))];
  28. v->x = x; // generate it flat
  29. v->y = y;
  30. v->z = 0.0;
  31. n->x = 0.0;
  32. n->y = 0.0;
  33. n->z = 1.0;
  34. }
  35. }
  36. // fill in the indices
  37. ii = 0;
  38. for(y = 0; y < height; y++) {
  39. for(x = 0; x < width; x++) {
  40. out->indices[ii++] = x + (y * (width + 1));
  41. out->indices[ii++] = (x + 1) + (y * (width + 1));
  42. out->indices[ii++] = (x + 1) + ((y + 1) * (width + 1));
  43. out->indices[ii++] = x + (y * (width + 1));
  44. out->indices[ii++] = (x + 1) + ((y + 1) * (width + 1));
  45. out->indices[ii++] = x + ((y + 1) * (width + 1));
  46. }
  47. }
  48. }
  49. void genIcosahedronPointsf(float radius, Vector3* out, int* count) {
  50. int i;
  51. // scale factor for inscribed sphere
  52. float a = 0.7557613140761707304801337020250013926384447888;
  53. float r = radius / (a * 2);
  54. // this one has edge length 2
  55. Vector3 points[] = {
  56. { 1.0f, 0.0f, F_GOLDEN}, // top edge along x axis
  57. { -1.0f, 0.0f, F_GOLDEN},
  58. { 0.0f, F_GOLDEN, 1.0f}, // triangle tips off that top edge
  59. { 0.0f, -F_GOLDEN, 1.0f},
  60. { F_GOLDEN, 1.0f, 0.0f}, // waistline
  61. { F_GOLDEN, -1.0f, 0.0f},
  62. { -F_GOLDEN, 1.0f, 0.0f},
  63. { -F_GOLDEN, -1.0f, 0.0f},
  64. { 0.0f, F_GOLDEN, -1.0f}, // triangle tips off the bottom edge
  65. { 0.0f, -F_GOLDEN, -1.0f},
  66. { 1.0f, 0.0f, -F_GOLDEN}, // bottom edge along x axis
  67. { -1.0f, 0.0f, -F_GOLDEN}
  68. };
  69. if(count) *count = 12;
  70. for(i = 0; i < 12; i++) {
  71. vScale3p(&points[i], r, &out[i]);
  72. }
  73. }
  74. // top half
  75. void genHalfIcosahedronPointsf(float radius, Vector3* out, int* count) {
  76. int i;
  77. // scale factor for inscribed sphere
  78. float a = 0.7557613140761707304801337020250013926384447888;
  79. float r = radius / (a * 2);
  80. // this one has edge length 2
  81. Vector3 points[] = {
  82. { 1.0f, 0.0f, F_GOLDEN}, // top edge along x axis
  83. { -1.0f, 0.0f, F_GOLDEN},
  84. { 0.0f, F_GOLDEN, 1.0f}, // triangle tips off that top edge
  85. { 0.0f, -F_GOLDEN, 1.0f},
  86. { F_GOLDEN, 1.0f, 0.0f}, // icosahedral waistline
  87. { F_GOLDEN, -1.0f, 0.0f},
  88. { -F_GOLDEN, 1.0f, 0.0f},
  89. { -F_GOLDEN, -1.0f, 0.0f},
  90. { 0.0f, F_GOLDEN, 0.0f}, // half way down the vertical edges
  91. { 0.0f, -F_GOLDEN, 0.0f}
  92. };
  93. if(count) *count = 10;
  94. for(i = 0; i < 10; i++) {
  95. vScale3p(&points[i], r, &out[i]);
  96. }
  97. }
  98. TriangleMesh* genIcosahedronMesh(float radius) {
  99. TriangleMesh* m;
  100. m = malloc(sizeof(*m));
  101. m->vertices = malloc(sizeof(*m->vertices) * 12);
  102. m->indices = malloc(sizeof(*m->indices) * 20 * 3);
  103. m->szVertices = m->vertexCnt = 12;
  104. m->szIndices = m->indexCnt = 20 * 3;
  105. genIcosahedronPointsf(radius, (Vector3*)m->vertices, NULL);
  106. short indices[] = {
  107. // top two triangles
  108. 0, 2, 1,
  109. 1, 0, 3,
  110. // neighbors of those top two triangles
  111. // signs are shared in x and y
  112. 2, 0, 4,
  113. 2, 1, 6,
  114. 3, 0, 5,
  115. 3, 1, 7,
  116. // standing triangle end caps
  117. 0, 5, 6,
  118. 1, 7, 8,
  119. // sideways triangles
  120. // all y values share sign
  121. 3, 9, 5,
  122. 3, 9, 7,
  123. 2, 8, 4,
  124. 2, 8, 6,
  125. // inverted triangle end caps
  126. 10, 5, 6,
  127. 11, 7, 8,
  128. // neighbors of the two bottom triangles
  129. // signs are shared in x and y
  130. 8, 10, 4,
  131. 8, 11, 6,
  132. 9, 10, 5,
  133. 9, 11, 7,
  134. // bottom two triangles
  135. 10, 8, 11,
  136. 11, 10, 9
  137. };
  138. memcpy(m->indices, indices, sizeof(short) * 20 * 3);
  139. return m;
  140. }
  141. // centered, along z axis
  142. TriangleMesh* genHollowCylinder(float innerRadius, float outerRadius, int segments, float length) {
  143. TriangleMesh* m;
  144. int i, j;
  145. float hlen = length / 2;
  146. m = malloc(sizeof(Mesh));
  147. // endcaps with two rows
  148. m->szVertices = m->vertexCnt = segments * 2 * 2;
  149. // two end caps, and two triangles per wall quad, two walls
  150. m->szIndices = m->indexCnt = 3 * (segments * (2 + 2 + 2 + 2));
  151. m->vertices = malloc(sizeof(Vector3) * m->szVertices);
  152. m->indices = malloc(sizeof(short) * m->szIndices);
  153. j = 0;
  154. // outside
  155. for(i = 0; i < segments; i++) {
  156. m->vertices[j].v.x = outerRadius * sin(D_2PI / i);
  157. m->vertices[j].v.y = outerRadius * cos(D_2PI / i);
  158. m->vertices[j++].v.z = -hlen;
  159. }
  160. for(i = 0; i < segments; i++) {
  161. m->vertices[j].v.x = outerRadius * sin(D_2PI / i);
  162. m->vertices[j].v.y = outerRadius * cos(D_2PI / i);
  163. m->vertices[j++].v.z = hlen;
  164. }
  165. // inside
  166. for(i = 0; i < segments; i++) {
  167. m->vertices[j].v.x = innerRadius * sin(D_2PI / i);
  168. m->vertices[j].v.y = innerRadius * cos(D_2PI / i);
  169. m->vertices[j++].v.z = -hlen;
  170. }
  171. for(i = 0; i < segments; i++) {
  172. m->vertices[j].v.x = innerRadius * sin(D_2PI / i);
  173. m->vertices[j].v.y = innerRadius * cos(D_2PI / i);
  174. m->vertices[j++].v.z = hlen;
  175. }
  176. // indices
  177. j = 0;
  178. // TODO
  179. return m;
  180. }
  181. // centered, along z axis
  182. TriangleMesh* genCylinder(float radius, int segments, float length) {
  183. TriangleMesh* m;
  184. int i, j;
  185. float hlen = length / 2;
  186. m = malloc(sizeof(Mesh));
  187. // endcaps plus center points
  188. m->szVertices = m->vertexCnt = segments * 2 + 2;
  189. // two end caps, and two triangles per wall quad
  190. m->szIndices = m->indexCnt = 3 * (segments * (2 + 2));
  191. m->vertices = malloc(sizeof(Vector3) * m->szVertices);
  192. m->indices = malloc(sizeof(short) * m->szIndices);
  193. // vertices
  194. for(i = 0; i < segments; i++) {
  195. m->vertices[i].v.x = radius * sin(D_2PI / i);
  196. m->vertices[i].v.y = radius * cos(D_2PI / i);
  197. m->vertices[i].v.z = -hlen;
  198. }
  199. m->vertices[segments].v.x = 0.0f;
  200. m->vertices[segments].v.y = 0.0f;
  201. m->vertices[segments].v.z = -hlen;
  202. for(i = 0; i < segments; i++) {
  203. m->vertices[segments + 1 + i].v.x = radius * sin(D_2PI / i);
  204. m->vertices[segments + 1 + i].v.y = radius * cos(D_2PI / i);
  205. m->vertices[segments + 1 + i].v.z = hlen;
  206. }
  207. m->vertices[segments * 2 + 1].v.x = 0.0f;
  208. m->vertices[segments * 2 + 1].v.y = 0.0f;
  209. m->vertices[segments * 2 + 1].v.z = hlen;
  210. // indices
  211. j = 0;
  212. // first the starting disk
  213. for(i = 0; i < segments; i++) {
  214. m->indices[j++] = i;
  215. m->indices[j++] = (i + 1) % segments;
  216. m->indices[j++] = segments;
  217. }
  218. // then the second disk
  219. for(i = 0; i < segments; i++) {
  220. m->indices[j++] = segments + 1 + i;
  221. m->indices[j++] = segments + 1 + ((i + 1) % segments);
  222. m->indices[j++] = segments + 1 + segments;
  223. }
  224. //finally the walls
  225. for(i = 0; i < segments; i++) {
  226. m->indices[j++] = i;
  227. m->indices[j++] = (i + 1) % segments;
  228. m->indices[j++] = segments + 1 + ((i + 1) % segments);
  229. m->indices[j++] = i;
  230. m->indices[j++] = segments + 1 + ((i + 1) % segments);
  231. m->indices[j++] = segments + 1 + segments;
  232. }
  233. return m;
  234. }
  235. float* genNoisef(short width, short height, float min, float max) {
  236. int len, i;
  237. float* out, range;
  238. len = width * height;
  239. range = max - min;
  240. out = (float*)malloc(len * sizeof(float));
  241. // no need for super quality math stuff here. it's just randomish junk for textures.
  242. for(i = 0; i < len; i++)
  243. out[i] = (((float)rand() / RAND_MAX) * range) + min;
  244. return out;
  245. }
  246. TriangleMesh* extrudeAlongVector(Vector3* lineStrip, int lineCount, Vector3* v) {
  247. int i;
  248. Mesh* m;
  249. m = malloc(sizeof(Mesh));
  250. // step 1: allocate enough memory for the mesh
  251. m->vertexCnt = (lineCount + 1) * 2;
  252. m->indexCnt = 3 * m->vertexCnt;
  253. m->vertices = malloc(sizeof(Vector3) * m->vertexCnt);
  254. m->indices = malloc(sizeof(short) * m->indexCnt);
  255. // fill in vertices
  256. for(i = 0; i <= lineCount; i++) {
  257. // vCopy3p(&lineStrip[i], &m->vertices[i*2].v);
  258. vAdd3p(&lineStrip[i], v, &m->vertices[(i*2)+1].v);
  259. }
  260. // fill in indices
  261. for(i = 0; i <= lineCount; i++) {
  262. m->indices[(i*6)+0] = i;
  263. m->indices[(i*6)+1] = i + 1;
  264. }
  265. return m;
  266. }
  267. TriangleMesh* allocMesh(int triangles) {
  268. TriangleMesh* m;
  269. m = calloc(sizeof(Mesh), 1);
  270. if(triangles <= 0) return m;
  271. m->vertices = malloc(sizeof(MeshVertex) * triangles);
  272. m->indices = malloc(sizeof(unsigned short) * 3 * triangles);
  273. m->szVertices = 3 * triangles;
  274. m->szIndices = 3 * triangles;
  275. m->vertexCnt = 0;
  276. m->indexCnt = 0;
  277. return m;
  278. }
  279. void growMeshVertices(TriangleMesh* m, int count) {
  280. if(count < m->szVertices) return;
  281. m->vertices = realloc(m->vertices, sizeof(MeshVertex) * count);
  282. m->szVertices = count;
  283. }
  284. void growMeshIndices(TriangleMesh* m, int count) {
  285. if(count < m->szIndices) return;
  286. m->indices = realloc(m->indices, sizeof(MeshVertex) * count);
  287. m->szIndices = count;
  288. }
  289. void checkGrowMesh(TriangleMesh* m, int newVertices, int newIndices) {
  290. if(m->szVertices - m->vertexCnt < newVertices) {
  291. if(m->szVertices < 16) m->szVertices = 16;
  292. // grow by the next multiple of szVertices large enough to fit the requested quantity
  293. growMeshVertices(m, (((m->szVertices + newVertices) / m->szVertices) + 1) * m->szVertices);
  294. }
  295. if(m->szIndices - m->indexCnt < newIndices) {
  296. if(m->szIndices < 16) m->szIndices = 16;
  297. // same as above
  298. growMeshIndices(m, (((m->szIndices + newIndices) / m->szIndices) + 1) * m->szIndices);
  299. }
  300. }
  301. // doesn't check mesh allocation size. Real Programmers(TM) already know how much memory there is.
  302. void appendTriangleFast(TriangleMesh* m, Vector3* v0, Vector3* v1, Vector3* v2) {
  303. int i = m->vertexCnt;
  304. int j = m->indexCnt;
  305. m->indices[j++] = i;
  306. m->indices[j++] = i+1;
  307. m->indices[j++] = i+2;
  308. // vCopy3p(v0, &m->vertices[i++].v);
  309. // vCopy3p(v1, &m->vertices[i++].v);
  310. // vCopy3p(v2, &m->vertices[i++].v);
  311. m->vertexCnt = i;
  312. m->indexCnt = j;
  313. }
  314. void appendTriangle(TriangleMesh* m, Vector3* v0, Vector3* v1, Vector3* v2) {
  315. checkGrowMesh(m, 3, 3);
  316. appendTriangleFast(m, v0, v1, v2);
  317. }
  318. // appends a face of vnct vertices to the mesh
  319. // CW winding, convex polygons only. will be tesselated as a fan pivoting around v[0].
  320. void appendFace(TriangleMesh* m, Vector3* v, int vcnt) {
  321. int i;
  322. checkGrowMesh(m, vcnt, 3 * (vcnt - 2));
  323. for(i = 0; i < vcnt - 2; i++) {
  324. appendTriangleFast(m, &v[0], &v[i+1], &v[i+2]);
  325. }
  326. }
  327. // shitty version
  328. TriangleMesh* makeCube(Matrix* mat, int flat) {
  329. Mesh* m;
  330. int i;
  331. static Vector3 vertices[] = {
  332. // front face
  333. {-.5, -.5, .5},
  334. {-.5, .5, .5},
  335. { .5, .5, .5},
  336. { .5, -.5, .5},
  337. // back face
  338. {-.5, -.5, -.5},
  339. {-.5, .5, -.5},
  340. { .5, .5, -.5},
  341. { .5, -.5, -.5}
  342. };
  343. static unsigned short indices[] = {
  344. 0,1,2, 2,3,0,
  345. 4,5,6, 6,7,4,
  346. 0,1,4, 1,4,5,
  347. 3,4,7, 3,0,4,
  348. 2,5,6, 0,2,5,
  349. 2,3,6, 3,6,7,
  350. };
  351. m = allocMesh(6 * 2);
  352. // transform the vertices
  353. for(i = 0; i < 8; i++)
  354. vMatrixMul3p(&vertices[i], mat, &m->vertices[i].v);
  355. // fill the index buffer
  356. memcpy(m->indices, indices, sizeof(indices));
  357. return m;
  358. }
  359. TriangleMesh* makeCuboid(Vector3* p1, Vector3* p2) {
  360. /*
  361. Mesh* m;
  362. Vector3 min, max;
  363. int i, n;
  364. vMin3p(p1, p2, &min);
  365. vMax3p(p1, p2, &max);
  366. m = allocMesh(6 * 2);
  367. i = 0;
  368. n = 0;
  369. // x+ face
  370. vSet3p(max.x, min.y, min.z, &m->vertices[i++].v);
  371. vSet3p(max.x, min.y, max.z, &m->vertices[i++].v);
  372. vSet3p(max.x, max.y, min.z, &m->vertices[i++].v);
  373. vSet3p(max.x, max.y, max.z, &m->vertices[i++].v);
  374. // x- face
  375. vSet3p(min.x, min.y, min.z, &m->vertices[i++].v);
  376. vSet3p(min.x, min.y, max.z, &m->vertices[i++].v);
  377. vSet3p(min.x, max.y, min.z, &m->vertices[i++].v);
  378. vSet3p(min.x, max.y, max.z, &m->vertices[i++].v);
  379. // y+ face
  380. vSet3p(min.x, max.y, min.z, &m->vertices[i++].v);
  381. vSet3p(min.x, max.y, max.z, &m->vertices[i++].v);
  382. vSet3p(max.x, max.y, min.z, &m->vertices[i++].v);
  383. vSet3p(max.x, max.y, max.z, &m->vertices[i++].v);
  384. // y- face
  385. vSet3p(min.x, min.y, min.z, &m->vertices[i++].v);
  386. vSet3p(min.x, min.y, max.z, &m->vertices[i++].v);
  387. vSet3p(max.x, min.y, min.z, &m->vertices[i++].v);
  388. vSet3p(max.x, min.y, max.z, &m->vertices[i++].v);
  389. // z+ face
  390. vSet3p(min.x, min.y, max.z, &m->vertices[i++].v);
  391. vSet3p(max.x, min.y, max.z, &m->vertices[i++].v);
  392. vSet3p(min.x, max.y, max.z, &m->vertices[i++].v);
  393. vSet3p(max.x, max.y, max.z, &m->vertices[i++].v);
  394. // z- face
  395. vSet3p(min.x, min.y, min.z, &m->vertices[i++].v);
  396. vSet3p(max.x, min.y, min.z, &m->vertices[i++].v);
  397. vSet3p(min.x, max.y, min.z, &m->vertices[i++].v);
  398. vSet3p(max.x, max.y, min.z, &m->vertices[i++].v);
  399. m->vertexCnt = i;
  400. return m;
  401. */
  402. return NULL;
  403. }
  404. // assumes vertices are not shared
  405. void calcFlatNormals(TriangleMesh* m) {
  406. int j, i1, i2, i3;
  407. Vector3 n;
  408. for(j = 0; j < m->indexCnt; j += 3) {
  409. i1 = m->indices[j];
  410. i2 = m->indices[j+1];
  411. i3 = m->indices[j+2];
  412. vTriFaceNormal3p(&m->vertices[i1].v, &m->vertices[i2].v, &m->vertices[i3].v, &n);
  413. // vCopy3p(&n, &m->vertices[i1].n);
  414. // vCopy3p(&n, &m->vertices[i2].n);
  415. // vCopy3p(&n, &m->vertices[i3].n);
  416. }
  417. }
  418. // only works if vertices are welded first.
  419. void calcSmoothNormals(TriangleMesh* m) {
  420. Vector3* sums;
  421. int i, vi0, vi1, vi2;
  422. Vector3 n;
  423. sums = calloc(1, m->vertexCnt * sizeof(Vector3));
  424. for(i = 0; i < m->indexCnt; i += 3) {
  425. vi0 = m->indices[i];
  426. vi1 = m->indices[i];
  427. vi2 = m->indices[i];
  428. vTriFaceNormal3p(&m->vertices[vi0].v, &m->vertices[vi1].v, &m->vertices[vi2].v, &n);
  429. vAdd3p(&n, &sums[vi0], &sums[vi0]);
  430. vAdd3p(&n, &sums[vi1], &sums[vi1]);
  431. vAdd3p(&n, &sums[vi2], &sums[vi2]);
  432. };
  433. for(i = 0; i < m->vertexCnt; i++) {
  434. vNorm3p(&sums[i], &m->vertices[i].n);
  435. }
  436. free(sums);
  437. }
  438. void weldVertices(TriangleMesh* m, float epsilon) {
  439. }
  440. // rewrites a mesh with no vertex reuse. required for flat shading.
  441. // super mega naive version; git-r-done. probably more cache-friendly than fancy ones anyway.
  442. // a few bits of data can probably be collected in previous passes, like newVertexCnt.
  443. void unweldVertices(TriangleMesh* m) {
  444. char* vusage;
  445. int i;
  446. int good_already = 1; // this variable looks silly in camelCase
  447. int newVertexCnt = 0;
  448. int newVIndex;
  449. vusage = calloc(1, sizeof(char) * m->vertexCnt);
  450. // see how many vertices are reused;
  451. for(i = 0; i < m->indexCnt; i++) {
  452. vusage[m->indices[i]]++;
  453. if(vusage[m->indices[i]] > 1) good_already = 0;
  454. }
  455. // return early if no vertices are used twice
  456. if(good_already) {
  457. free(vusage);
  458. return;
  459. }
  460. // calculate new vertex buffer size and realloc if necessary
  461. for(i = 0; i < m->vertexCnt; i++) {
  462. newVertexCnt += vusage[i];
  463. }
  464. if(newVertexCnt > m->szVertices) {
  465. realloc(m->vertices, sizeof(MeshVertex) * newVertexCnt);
  466. m->szVertices = newVertexCnt;
  467. }
  468. // "new" vertices are appended after the last "old" vertex
  469. newVIndex = m->vertexCnt;
  470. for(i = 0; i < m->indexCnt; i++) {
  471. int vi;
  472. vi = m->indices[i];
  473. if(vusage[vi] > 1) {
  474. // copy vertex
  475. memcpy(&m->vertices[vi], &m->vertices[newVIndex], sizeof(MeshVertex));
  476. // update index buffer with new vertex
  477. m->indices[i] = newVIndex;
  478. // mark off one of the "uses"
  479. vusage[vi]--;
  480. newVIndex++;
  481. }
  482. }
  483. m->vertexCnt = newVertexCnt;
  484. free(vusage);
  485. }
  486. MeshSlice* allocMeshSlice(int vcnt, int icnt) {
  487. MeshSlice* ms;
  488. ms = calloc(1, sizeof(MeshSlice));
  489. ms->vertices = calloc(1, vcnt * sizeof(MeshVertex));
  490. ms->indices = calloc(1, icnt * sizeof(short));
  491. ms->szVertices = vcnt;
  492. ms->szIndices = icnt;
  493. return ms;
  494. }
  495. MeshSlice* makeCircle(float radius, int divisions) {
  496. MeshSlice* ms;
  497. int i;
  498. float divf = (float)divisions;
  499. ms = allocMeshSlice(divisions, divisions + 1);
  500. for(i = 0; i < divisions; i++) {
  501. ms->vertices[i].v.x = radius * sin((i / divf) * F_2PI);
  502. ms->vertices[i].v.y = radius * cos((i / divf) * F_2PI);
  503. ms->vertices[i].v.z = 0;
  504. // vCopy3p(&ms->vertices[i].v, &ms->vertices[i].n);
  505. ms->vertices[i].t.u = i / divf;
  506. ms->vertices[i].t.v = 0;
  507. ms->indices[i] = i;
  508. }
  509. ms->indices[divisions] = 0;
  510. ms->vertexCnt = divisions;
  511. ms->indexCnt = divisions + 1;
  512. ms->texDxDy.x = 0;
  513. ms->texDxDy.y = 1;
  514. return ms;
  515. }
  516. void appendBezierSpline(MeshSlice* ms, BezierSpline3* bs, float tolerance, int connectToEnd) {
  517. }
  518. #endif