staticMesh.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <stddef.h>
  4. #include <string.h>
  5. #include <math.h>
  6. #include <float.h>
  7. #include <GL/glew.h>
  8. #include <GL/glx.h>
  9. #include <GL/glu.h>
  10. #include "c3dlas/c3dlas.h"
  11. #include "utilities.h"
  12. #include "objloader.h"
  13. #include "shader.h"
  14. #include "staticMesh.h"
  15. int static parseFaceVertex(char** s, int* info);
  16. struct SolidVertex {
  17. Vector pos;
  18. Vector face_normal;
  19. struct {
  20. float u, v;
  21. } texcoords;
  22. };
  23. static HASH_FN_FOR_TYPE(vector_hash_fn, Vector)
  24. float StaticMesh_setScale(StaticMesh* sm, float newscale) {
  25. sm->scale = newscale;
  26. sm->bbox.rend->scale = newscale;
  27. sm->bbox.rendAxes->scale = newscale;
  28. sm->solid->scale = newscale;
  29. sm->wireframe->scale = newscale;
  30. sm->points->scale = newscale;
  31. return newscale;
  32. }
  33. static void generateSolid(StaticMesh* sm) {
  34. int i, face_cnt;
  35. struct SolidVertex* faces;
  36. face_cnt = sm->faceCnt = VEC_LEN(&sm->vertexIndices) / 3;
  37. faces = malloc(face_cnt * 3 * sizeof(*faces));
  38. CHECK_OOM(faces);
  39. // fill in the faces, calculate face normals
  40. for(i = 0; i < VEC_LEN(&sm->vertexIndices); i += 3) {
  41. Vector* a, *b, *c;
  42. Vector* an, *bn, *cn;
  43. struct SolidVertex* o;
  44. Vector norm;
  45. a = VEC_DATA(&sm->vertices) + VEC_DATA(&sm->vertexIndices)[i];
  46. b = VEC_DATA(&sm->vertices) + VEC_DATA(&sm->vertexIndices)[i+1];
  47. c = VEC_DATA(&sm->vertices) + VEC_DATA(&sm->vertexIndices)[i+2];
  48. if(sm->hasNormals) {
  49. an = VEC_DATA(&sm->normals) + VEC_DATA(&sm->normalIndices)[i];
  50. bn = VEC_DATA(&sm->normals) + VEC_DATA(&sm->normalIndices)[i+1];
  51. cn = VEC_DATA(&sm->normals) + VEC_DATA(&sm->normalIndices)[i+2];
  52. }
  53. else { // use face normals for now
  54. vTriFaceNormal(a, b, c, &norm);
  55. an = bn = cn = &norm;
  56. }
  57. o = faces + i;
  58. // calculate the face normal
  59. //vTriFaceNormal(a, b, c, &norm);
  60. //printf("face %d: [%.2f,%.2f,%.2f] [%.2f,%.2f,%.2f] [%.2f,%.2f,%.2f] \n", i/3, a->x, a->y, a->z, b->x, b->y, b->z, c->x, c->y, c->z);
  61. // fill in the face info
  62. vCopy(a, &o->pos);
  63. vCopy(b, &o[1].pos);
  64. vCopy(c, &o[2].pos);
  65. vCopy(an, &o->face_normal);
  66. vCopy(bn, &(o+1)->face_normal);
  67. vCopy(cn, &(o+2)->face_normal);
  68. o->texcoords.u = VEC_DATA(&sm->texcoords)[VEC_DATA(&sm->textureIndices)[i]].x;
  69. o->texcoords.v = VEC_DATA(&sm->texcoords)[VEC_DATA(&sm->textureIndices)[i]].y;
  70. (o+1)->texcoords.u = VEC_DATA(&sm->texcoords)[VEC_DATA(&sm->textureIndices)[i+1]].x;
  71. (o+1)->texcoords.v = VEC_DATA(&sm->texcoords)[VEC_DATA(&sm->textureIndices)[i+1]].y;
  72. (o+2)->texcoords.u = VEC_DATA(&sm->texcoords)[VEC_DATA(&sm->textureIndices)[i+2]].x;
  73. (o+2)->texcoords.v = VEC_DATA(&sm->texcoords)[VEC_DATA(&sm->textureIndices)[i+2]].y;
  74. }
  75. VAOConfig opts[] = {
  76. // per vertex
  77. {3, GL_FLOAT}, // position
  78. {3, GL_FLOAT}, // face_normal
  79. {2, GL_FLOAT}, // tex
  80. {0, 0}
  81. };
  82. sm->solid = renderable_Create(GL_TRIANGLES, "staticMesh", opts, faces, face_cnt * 3);
  83. if(sm->texPath) {
  84. Renderable_applyTexturePath(sm->solid, sm->texPath);
  85. }
  86. // set status flag
  87. }
  88. static uint64_t edgeLookupHash(void* key) {
  89. return HT_HashFn(key, sizeof(uint64_t));
  90. }
  91. static int edgeLookupCmp(void* a, void* b) {
  92. return (uint64_t)a - (uint64_t)b;
  93. }
  94. static inline uint64_t makeEdgeKey(uint32_t a, uint32_t b) {
  95. return MIN(a, b) | MAX(a, b) << 32;
  96. }
  97. static void generateWireframe(StaticMesh* sm) {
  98. /*
  99. int i, edge_cnt, edge_alloc;
  100. Vector* edges;
  101. // allocate for the worst case scenario of a bunch of independent triangles
  102. edge_alloc = sm->faceCnt * 3 * 2;
  103. edge_cnt = 0;
  104. edges = malloc(edge_alloc * sizeof(*edges));
  105. CHECK_OOM(edges);
  106. // initialize edge lookup hash table
  107. sm->edgeLookup = HT_createCustom(0, edgeLookupHash, edgeLookupCmp);
  108. // edges are considered going from lowest to highest index
  109. for(i = 0; i < sm->indexCnt; i += 3) {
  110. uint32_t ai, bi, ci;
  111. uint64_t e_ab, e_bc, e_ca;
  112. Vector* a, *b, *c, *o;
  113. Vector norm;
  114. ai = sm->indices[i];
  115. bi = sm->indices[i+1];
  116. ci = sm->indices[i+2];
  117. a = VEC_DATA(&sm->vertices) + ai;
  118. b = VEC_DATA(&sm->vertices) + bi;
  119. c = VEC_DATA(&sm->vertices) + ci;
  120. e_ab = makeEdgeKey(ai, bi);
  121. e_bc = makeEdgeKey(ai, bi);
  122. e_ca = makeEdgeKey(ci, ai);
  123. // TODO: unique edge index table?
  124. if(HT_get(sm->edgeLookup, (void*)e_ab, NULL)) {
  125. // not found, add edge
  126. vCopy(a, edges + edge_cnt);
  127. vCopy(b, edges + edge_cnt + 1);
  128. HT_set(sm->edgeLookup, (void*)e_ab, 1);
  129. edge_cnt++;
  130. }
  131. if(HT_get(sm->edgeLookup, (void*)e_bc, NULL)) {
  132. // not found, add edge
  133. vCopy(b, edges + edge_cnt);
  134. vCopy(c, edges + edge_cnt + 1);
  135. HT_set(sm->edgeLookup, (void*)e_bc, 1);
  136. edge_cnt++;
  137. }
  138. if(HT_get(sm->edgeLookup, (void*)e_ab, NULL)) {
  139. // not found, add edge
  140. vCopy(c, edges + edge_cnt);
  141. vCopy(a, edges + edge_cnt + 1);
  142. HT_set(sm->edgeLookup, (void*)e_ca, 1);
  143. edge_cnt++;
  144. }
  145. }
  146. // TODO: realloc?
  147. VAOConfig opts[] = {
  148. // per vertex
  149. {3, GL_FLOAT}, // position
  150. {3, GL_FLOAT}, // face_normal
  151. {0, 0}
  152. };
  153. sm->wireframe = renderable_Create(GL_LINES, "staticMeshWireframe", opts, edges, edge_cnt);
  154. // TODO: set status flag
  155. */
  156. }
  157. static void generatePoints(StaticMesh* sm) {
  158. VAOConfig opts[] = {
  159. // per vertex
  160. {3, GL_FLOAT}, // position
  161. {0, 0}
  162. };
  163. sm->points = renderable_Create(GL_POINTS, "staticMeshPoints", opts, VEC_DATA(&sm->vertices), VEC_LEN(&sm->vertices));
  164. // TODO: set status flag
  165. }
  166. void generateBBox(StaticMesh* sm) {
  167. BoundingBoxVisual_update(
  168. &sm->bbox,
  169. &sm->aabbMin,
  170. &sm->aabbMax
  171. );
  172. Vector v = {5,5,5};
  173. AxesVisual_init(&sm->av, &v);
  174. }
  175. void staticMesh_RegenMeta(StaticMesh* sm) {
  176. StaticMesh_CalcStats(sm);
  177. generateSolid(sm);
  178. // generateWireframe(sm);
  179. generatePoints(sm);
  180. generateBBox(sm);
  181. }
  182. void staticMesh_Init(StaticMesh* sm) {
  183. VEC_INIT(&sm->vertices);
  184. VEC_INIT(&sm->normals);
  185. VEC_INIT(&sm->texcoords);
  186. VEC_INIT(&sm->vertexIndices);
  187. VEC_INIT(&sm->normalIndices);
  188. VEC_INIT(&sm->textureIndices);
  189. VEC_INIT(&sm->edges);
  190. }
  191. StaticMesh* staticMesh_Create() {
  192. StaticMesh* sm;
  193. sm = calloc(1, sizeof(*sm));
  194. CHECK_OOM(sm);
  195. staticMesh_Init(sm);
  196. return sm;
  197. }
  198. // hacky for now
  199. StaticMesh* staticMesh_FromPLY(PLYContents* pc) {
  200. int i;
  201. Vector null = {0,0,0};
  202. StaticMesh* sm;
  203. sm = staticMesh_Create();
  204. VEC_COPY(&sm->vertices, &pc->vertices);
  205. VEC_COPY(&sm->vertexIndices, &pc->faces);
  206. sm->hasTexCoords = 1;
  207. VEC_COPY(&sm->texcoords, &pc->texcoords);
  208. VEC_COPY(&sm->textureIndices, &pc->indicesTex);
  209. sm->hasNormals = 0;
  210. if(pc->texPath) sm->texPath = strdup(pc->texPath);
  211. return sm;
  212. }
  213. // hacky for now, sloppily recreates index data
  214. StaticMesh* staticMesh_LoadOBJ(char* path) {
  215. int i;
  216. StaticMesh* sm;
  217. char* f, *raw;
  218. int chars_read;
  219. Vector tmp;
  220. int tc, vc, nc;
  221. tc = vc = nc = 0;
  222. raw = readFile(path, NULL);
  223. if(!raw) return;
  224. sm = staticMesh_Create();
  225. f = raw;
  226. while(*f) {
  227. char c;
  228. int fd[3][4];
  229. int n, ret;
  230. c = *f;
  231. f++;
  232. if(c == 'f') {
  233. // this loop decomposes polygons into fans of individual triangles
  234. ret = parseFaceVertex(&f, &fd[0]); // the center vertex
  235. ret = parseFaceVertex(&f, &fd[1]); // the next vertex
  236. do {
  237. ret = parseFaceVertex(&f, &fd[2]);
  238. if(ret) break;
  239. VEC_PUSH(&sm->vertexIndices, fd[0][0]-1);
  240. VEC_PUSH(&sm->textureIndices, fd[0][1]-1);
  241. VEC_PUSH(&sm->normalIndices, fd[0][2]-1);
  242. VEC_PUSH(&sm->vertexIndices, fd[1][0]-1);
  243. VEC_PUSH(&sm->textureIndices, fd[1][1]-1);
  244. VEC_PUSH(&sm->normalIndices, fd[1][2]-1);
  245. VEC_PUSH(&sm->vertexIndices, fd[2][0]-1);
  246. VEC_PUSH(&sm->textureIndices, fd[2][1]-1);
  247. VEC_PUSH(&sm->normalIndices, fd[2][2]-1);
  248. // shift the data down
  249. memcpy(&fd[1], &fd[2], sizeof(fd[2]));
  250. } while(1);
  251. }
  252. else if(c == 'v') {
  253. c = *f;
  254. f++;
  255. if(c == ' ') { // vertex
  256. chars_read = 0;
  257. n = sscanf(f, " %f %f %f%n", &tmp.x, &tmp.y, &tmp.z, &chars_read);
  258. VEC_PUSH(&sm->vertices, tmp);
  259. if(n < 3) fprintf(stderr, "error reading vertex\n");
  260. f += chars_read-1;
  261. vc++;
  262. }
  263. else if(c == 't') { // tex coord
  264. chars_read = 0;
  265. tmp.z = 0.0f;
  266. n = sscanf(f, " %f %f%n", &tmp.x, &tmp.y, &chars_read);
  267. VEC_PUSH(&sm->texcoords, tmp);
  268. if(n < 2) fprintf(stderr, "error reading tex coord\n");
  269. f += chars_read-1;
  270. tc++;
  271. }
  272. else if(c == 'n') { // normal
  273. chars_read = 0;
  274. n = sscanf(f, " %f %f %f%n", &tmp.x, &tmp.y, &tmp.z, &chars_read);
  275. VEC_PUSH(&sm->normals, tmp);
  276. if(n < 3) fprintf(stderr, "error reading normal\n");
  277. f += chars_read-1;
  278. nc++;
  279. }
  280. }
  281. else if(c == 'o') {
  282. }
  283. else if(c == 'm') {
  284. }
  285. // skip to the end of the line
  286. while(*f && *f != '\n') f++;
  287. f++;
  288. }
  289. printf("static mesh vertices: %d\n", VEC_LEN(&sm->vertices));
  290. printf("static mesh indices: %d\n", VEC_LEN(&sm->vertexIndices));
  291. return sm;
  292. }
  293. int static parseFaceVertex(char** s, int* info) {
  294. char* end;
  295. int val;
  296. int err, chars_read;
  297. while(**s && (**s == ' ' || **s == '\t' || **s == '\r')) (*s)++;
  298. if(**s == '\n') return 1;
  299. info[3] = 0;
  300. // first
  301. err = strtol_2(*s, &chars_read, &val);
  302. if(err) return 1;
  303. *s += chars_read ;
  304. info[0] = val;
  305. info[3]++;
  306. if(**s != '/') return 0;
  307. (*s)++;
  308. err = strtol_2(*s, &chars_read, &val);
  309. if(err) return 0;
  310. *s += chars_read ;
  311. info[1] = val;
  312. info[3]++;
  313. if(**s != '/') return 0;
  314. (*s)++;
  315. err = strtol_2(*s, &chars_read, &val);
  316. if(err) return 0;
  317. *s += chars_read ;
  318. info[2] = val;
  319. info[3]++;
  320. return 0;
  321. }
  322. void drawStaticMesh(StaticMesh* m, Matrix* view, Matrix* proj) {
  323. m->solid->scale = 1;
  324. renderable_Draw(m->solid, view, proj);
  325. renderable_Draw(m->bbox.rend, view, proj);
  326. renderable_Draw(m->bbox.rendAxes, view, proj);
  327. AxesVisual_render(&m->av, view, proj);
  328. // renderable_Draw(m->points, view, proj);
  329. }
  330. void StaticMesh_CalcStats(StaticMesh* sm) {
  331. int i;
  332. // for calculating the average center point
  333. struct { double x,y,z; } sums;
  334. // for calculating the most extreme points
  335. float px, py, pz, mx, my, mz;
  336. px = py = pz = -FLT_MAX;
  337. mx = my = mz = FLT_MAX;
  338. for(i = 0; i < VEC_LEN(&sm->vertices); i++) {
  339. Vector* v = &VEC_ITEM(&sm->vertices, i);
  340. if(v->x < mx) { mx = v->x; sm->extremes.m_x; }
  341. if(v->x > px) { px = v->x; sm->extremes.p_x; }
  342. if(v->y < my) { my = v->y; sm->extremes.m_y; }
  343. if(v->y > py) { py = v->y; sm->extremes.p_y; }
  344. if(v->z < mz) { mz = v->z; sm->extremes.m_z; }
  345. if(v->z > pz) { pz = v->z; sm->extremes.p_z; }
  346. sums.x += v->x;
  347. sums.y += v->y;
  348. sums.z += v->z;
  349. }
  350. sm->aabbMin.x = mx;
  351. sm->aabbMin.y = my;
  352. sm->aabbMin.z = mz;
  353. sm->aabbMax.x = px;
  354. sm->aabbMax.y = py;
  355. sm->aabbMax.z = pz;
  356. sm->aabbDimensions.x = (px - mx);
  357. sm->aabbDimensions.y = (py - my);
  358. sm->aabbDimensions.z = (pz - mz);
  359. sm->aabbCenter.x = (sm->aabbDimensions.x / 2) + mx;
  360. sm->aabbCenter.y = (sm->aabbDimensions.y / 2) + my;
  361. sm->aabbCenter.z = (sm->aabbDimensions.z / 2) + mz;
  362. sm->meanCenter.x = sums.x / VEC_LEN(&sm->vertices);
  363. sm->meanCenter.y = sums.y / VEC_LEN(&sm->vertices);
  364. sm->meanCenter.z = sums.z / VEC_LEN(&sm->vertices);
  365. }