main.cpp 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782
  1. #include "pch.h"
  2. const int c_maxVertices = 10000;
  3. const int c_maxFaces = 1000;
  4. const int c_cbBfr = 512;
  5. const int c_ellipse = 0x01;
  6. const int c_oneHull = 0x02;
  7. const int c_writeHull = 0x04;
  8. const int c_writeMesh = 0x08;
  9. const int c_startMesh = 0x10;
  10. const int c_endMesh = 0x20;
  11. bool x2pl(const char* fileIn, const char* fileOut);
  12. bool qh2cvh(const char* file, FILE* fOut, int mode);
  13. bool dat2cvh(const char* file, FILE* fOut);
  14. int main(int argc, char** argv)
  15. {
  16. bool success = false;
  17. if (argc == 3)
  18. {
  19. char bfr[256];
  20. strcpy(bfr, argv[2]);
  21. strcat(bfr, ".cvh");
  22. FILE* fOut = fopen(bfr, "w");
  23. if (fOut)
  24. {
  25. enum Modes
  26. {
  27. c_flatten,
  28. c_extract,
  29. c_bound
  30. } mode;
  31. if (strcmp(argv[1], "-flatten") == 0)
  32. mode = c_flatten;
  33. else if (strcmp(argv[1], "-extract") == 0)
  34. mode = c_extract;
  35. else if (strcmp(argv[1], "-bound") == 0)
  36. mode = c_bound;
  37. char bfrIn[c_cbBfr];
  38. strcpy(bfrIn, argv[2]);
  39. strcat(bfrIn, "flat.x");
  40. char bfrOut[c_cbBfr];
  41. strcpy(bfrOut, argv[2]);
  42. strcat(bfrOut, ".pl");
  43. success = x2pl(bfrIn, bfrOut);
  44. if (success)
  45. {
  46. char bfrSystem[c_cbBfr];
  47. strcpy(bfrSystem, "%fedroot%\\src\\bin\\qhull -o -Tv <");
  48. strcat(bfrSystem, argv[2]);
  49. strcat(bfrSystem, ".pl >");
  50. strcat(bfrSystem, argv[2]);
  51. strcat(bfrSystem, ".qh");
  52. system(bfrSystem);
  53. success = qh2cvh(argv[2], fOut, (mode == c_bound)
  54. ? (c_ellipse | c_startMesh)
  55. : (c_ellipse | c_oneHull | c_writeHull | c_writeMesh | c_startMesh | c_endMesh));
  56. }
  57. if (mode == c_bound)
  58. {
  59. int hullID = -1;
  60. do
  61. {
  62. char bfrHull[c_cbBfr];
  63. sprintf(bfrHull, "%s_%d", argv[2], ++hullID);
  64. char bfrIn[c_cbBfr];
  65. strcpy(bfrIn, bfrHull);
  66. strcat(bfrIn, ".mesh");
  67. char bfrOut[c_cbBfr];
  68. strcpy(bfrOut, bfrHull);
  69. strcat(bfrOut, ".pl");
  70. success = x2pl(bfrIn, bfrOut);
  71. }
  72. while (success);
  73. success = true;
  74. fprintf(fOut, "%5d\n", hullID);
  75. for (int i = 0; ((i < hullID) && success); i++)
  76. {
  77. char bfrHull[c_cbBfr];
  78. sprintf(bfrHull, "%s_%d", argv[2], i);
  79. char bfrSystem[c_cbBfr];
  80. strcpy(bfrSystem, "%fedroot%\\src\\bin\\qhull -o -Tv <");
  81. strcat(bfrSystem, bfrHull);
  82. strcat(bfrSystem, ".pl >");
  83. strcat(bfrSystem, bfrHull);
  84. strcat(bfrSystem, ".qh");
  85. system(bfrSystem);
  86. success = qh2cvh(bfrHull, fOut, (i == hullID - 1)
  87. ? (c_writeHull | c_writeMesh | c_endMesh)
  88. : (c_writeHull | c_writeMesh));
  89. }
  90. }
  91. if (mode != c_flatten)
  92. success = dat2cvh(argv[2], fOut);
  93. fclose(fOut);
  94. }
  95. }
  96. return success ? 0 : -1;
  97. }
  98. bool x2pl(const char* fileIn, const char* fileOut)
  99. {
  100. bool success = false;
  101. FILE* fIn = NULL;
  102. FILE* fOut = NULL;
  103. fIn = fopen(fileIn, "r");
  104. if (fIn)
  105. {
  106. fOut = fopen(fileOut, "w");
  107. if (fOut)
  108. {
  109. success = true;
  110. const int c_cbLine = 512;
  111. char line[c_cbLine];
  112. int nVertices = -2;
  113. while (fgets(line, c_cbLine, fIn) != NULL)
  114. {
  115. if (nVertices == -2)
  116. {
  117. if (strcmp(line, "Mesh {\n"/*}*/) == 0)
  118. nVertices = -1;
  119. }
  120. else if (nVertices == -1)
  121. {
  122. nVertices = atoi(line);
  123. fprintf(fOut, "3 %d %s\n", nVertices, fileIn);
  124. }
  125. else if (nVertices == 0)
  126. break;
  127. else
  128. {
  129. //Write out the vertices, translating ';' to ' '
  130. int nsc = 0;
  131. const char* p = line;
  132. while (true)
  133. {
  134. assert (*p != '\0');
  135. if (*p == ';')
  136. {
  137. if (++nsc == 3)
  138. break;
  139. fputc('\t', fOut);
  140. }
  141. else
  142. fputc(*p, fOut);
  143. p++;
  144. }
  145. fputc('\n', fOut);
  146. nVertices--;
  147. }
  148. }
  149. fclose(fOut);
  150. }
  151. fclose(fIn);
  152. }
  153. return success;
  154. }
  155. struct Vertex
  156. {
  157. Vertex(void)
  158. :
  159. cUsed(0)
  160. {
  161. }
  162. double xyz[3];
  163. int id;
  164. int cUsed;
  165. };
  166. struct Face
  167. {
  168. int ids[3];
  169. };
  170. void swap(double g[3][4], int i, int j)
  171. {
  172. for (int k = 0; (k < 4); k++)
  173. {
  174. double t = g[i][k];
  175. g[i][k] = g[j][k];
  176. g[j][k] = t;
  177. }
  178. }
  179. void subtract(double g[3][4], double f, int i, int j)
  180. {
  181. for (int k = 0; (k < 4); k++)
  182. {
  183. g[i][k] -= g[j][k] * f;
  184. }
  185. }
  186. bool reduce(double g[3][4])
  187. {
  188. if (fabs(g[1][0]) > fabs(g[0][0]))
  189. swap(g, 0, 1);
  190. if (fabs(g[2][0]) > fabs(g[0][0]))
  191. swap(g, 0, 2);
  192. if (fabs(g[0][0]) < 1.0e-4)
  193. return false;
  194. //Reduce the first column
  195. subtract(g, g[1][0] / g[0][0], 1, 0);
  196. g[1][0] = 0.0;
  197. subtract(g, g[2][0] / g[0][0], 2, 0);
  198. g[2][0] = 0.0;
  199. if (fabs(g[2][1]) > fabs(g[1][1]))
  200. swap(g, 1, 2);
  201. if (fabs(g[1][1]) < 1.0e-4)
  202. return false;
  203. //Reduce the second column
  204. subtract(g, g[2][1] / g[1][1], 2, 1);
  205. g[2][1] = 0.0;
  206. //Back solve ...
  207. if (fabs(g[2][2]) < 1.0e-4)
  208. return false;
  209. g[2][3] = g[2][3] / g[2][2];
  210. g[2][2] = 1.0;
  211. subtract(g, g[1][2], 1, 2);
  212. g[1][2] = 0.0f;
  213. subtract(g, g[0][2], 0, 2);
  214. g[0][2] = 0.0f;
  215. assert (g[1][1] != 0.0f);
  216. g[1][3] = g[1][3] / g[1][1];
  217. g[1][1] = 1.0;
  218. subtract(g, g[0][1], 0, 1);
  219. assert (g[0][0] != 0.0f);
  220. g[0][3] = g[0][3] / g[0][0];
  221. g[0][0] = 1.0;
  222. return true;
  223. }
  224. Vertex vertices[c_maxVertices];
  225. Face faces[c_maxFaces];
  226. int vertexIDs[c_maxVertices];
  227. void addAdjacent(int* nAdjacent,
  228. int adjacent[],
  229. int id)
  230. {
  231. if (vertices[id].cUsed > 2)
  232. {
  233. for (int i = 0; (i < *nAdjacent); i++)
  234. {
  235. if (adjacent[i] == id)
  236. return;
  237. }
  238. adjacent[(*nAdjacent)++] = id;
  239. }
  240. }
  241. bool qh2cvh(const char* file, FILE* fOut, int mode)
  242. {
  243. bool success = false;
  244. assert (fOut);
  245. FILE* fIn;
  246. {
  247. char bfr[c_cbBfr];
  248. assert (strlen(file) < c_cbBfr - 10);
  249. strcpy(bfr, file);
  250. strcat(bfr, ".qh");
  251. fIn = fopen(bfr, "r");
  252. }
  253. if (fIn)
  254. {
  255. success = true;
  256. int nVertices = 0;
  257. int nUsedVertices = 0;
  258. int nSingularFaces = 0;
  259. int nFaces = 0;
  260. const int c_cbLine = 512;
  261. char line[c_cbLine];
  262. fgets(line, c_cbLine, fIn); //Skip 1st line
  263. fgets(line, c_cbLine, fIn);
  264. sscanf(line, "%d %d", &nVertices, &nFaces);
  265. //Read in all of the vertices
  266. {
  267. for (int i = 0; (i < nVertices); i++)
  268. {
  269. fgets(line, c_cbLine, fIn);
  270. sscanf(line, "%lf %lf %lf",
  271. &(vertices[i].xyz[0]),
  272. &(vertices[i].xyz[1]),
  273. &(vertices[i].xyz[2]));
  274. vertices[i].cUsed = 0;
  275. }
  276. }
  277. //Read in all of the faces
  278. {
  279. int faceID = 0; //possibly more than one face/line
  280. for (int i = 0; (i < nFaces); i++)
  281. {
  282. fgets(line, c_cbLine, fIn);
  283. int n = atoi(line);
  284. const int c_maxIDs = 20;
  285. assert (n >= 3);
  286. assert (n < c_maxIDs);
  287. int ids[c_maxIDs];
  288. {
  289. const char* p = line;
  290. for (int j = 0; (j < n); j++)
  291. {
  292. p = strchr(p, ' ');
  293. assert (p);
  294. ids[j] = atoi(++p);
  295. }
  296. }
  297. if ((n & 0x01) == 1)
  298. {
  299. //Odd number of vertices
  300. //Remove the last vertex from consideration
  301. faces[faceID].ids[0] = ids[n-2];
  302. faces[faceID].ids[1] = ids[n-1];
  303. faces[faceID].ids[2] = ids[0];
  304. faceID++;
  305. n--;
  306. }
  307. assert ((n & 0x01) == 0);
  308. int p0 = 0;
  309. int p1 = 1;
  310. int p2 = n - 2;
  311. int p3 = n - 1;
  312. while (p2 > p1)
  313. {
  314. faces[faceID].ids[0] = ids[p0];
  315. faces[faceID].ids[1] = ids[p1];
  316. faces[faceID].ids[2] = ids[p2];
  317. faceID++;
  318. faces[faceID].ids[0] = ids[p2];
  319. faces[faceID].ids[1] = ids[p3];
  320. faces[faceID].ids[2] = ids[p0];
  321. faceID++;
  322. p0++;
  323. p1++;
  324. p2--;
  325. p3--;
  326. }
  327. }
  328. nFaces = faceID;
  329. }
  330. //Mark the vertices actually used by faces
  331. {
  332. for (int i = 0; (i < nFaces); i++)
  333. {
  334. for (int j = 0; (j < 3); j++)
  335. vertices[faces[i].ids[j]].cUsed++;
  336. }
  337. }
  338. //Generate IDs for the vertices that are used
  339. {
  340. int vertexID = 0;
  341. for (int i = 0; (i < nVertices); i++)
  342. {
  343. if (vertices[i].cUsed > 2)
  344. {
  345. vertexIDs[vertexID] = i;
  346. vertices[i].id = vertexID++;
  347. }
  348. else
  349. nSingularFaces += vertices[i].cUsed;
  350. }
  351. nUsedVertices = vertexID;
  352. }
  353. double radius = 0.0;
  354. double xyzMin[3] = {0.0, 0.0, 0.0};
  355. double xyzMax[3] = {0.0, 0.0, 0.0};
  356. {
  357. //Find the most distance vertex in the model
  358. for (int i = 0; (i < nUsedVertices); i++)
  359. {
  360. int vertexID = vertexIDs[i];
  361. double r = vertices[vertexID].xyz[0] * vertices[vertexID].xyz[0] +
  362. vertices[vertexID].xyz[1] * vertices[vertexID].xyz[1] +
  363. vertices[vertexID].xyz[2] * vertices[vertexID].xyz[2];
  364. if (r > radius)
  365. radius = r;
  366. for (int j = 0; (j < 3); j++)
  367. {
  368. if (vertices[vertexID].xyz[j] > xyzMax[j])
  369. xyzMax[j] = vertices[vertexID].xyz[j];
  370. if (vertices[vertexID].xyz[j] < xyzMin[j])
  371. xyzMin[j] = vertices[vertexID].xyz[j];
  372. }
  373. }
  374. }
  375. radius = sqrt(radius);
  376. static FILE* fOutMesh;
  377. if (mode & c_startMesh)
  378. {
  379. char bfr[c_cbBfr];
  380. assert (strlen(file) < c_cbBfr - 10);
  381. strcpy(bfr, "..\\artbuild\\");
  382. strcat(bfr, file);
  383. strcat(bfr, "_m.x");
  384. fOutMesh = fopen(bfr, "w");
  385. fprintf(fOutMesh, "xof 0302txt 0064\nHeader { 1; 0; 1; }\n");
  386. }
  387. if (mode & c_writeMesh)
  388. {
  389. fprintf(fOutMesh, "Mesh\n{\n%d;\n", nUsedVertices); //}
  390. //Only print the vertices actually used by the convex hull
  391. {
  392. bool firstF = true;
  393. for (int i = 0; (i < nVertices); i++)
  394. {
  395. if (vertices[i].cUsed > 2)
  396. {
  397. if (firstF)
  398. firstF = false;
  399. else
  400. fputs(",\n", fOutMesh);
  401. fprintf(fOutMesh, "%14.6f;%14.6f;%14.6f;",
  402. -vertices[i].xyz[0],
  403. -vertices[i].xyz[1],
  404. vertices[i].xyz[2]);
  405. }
  406. }
  407. }
  408. //Print the faces with the correct vertex IDs
  409. {
  410. fprintf(fOutMesh, ";\n\n%d;\n", nFaces - nSingularFaces);
  411. bool first = true;
  412. for (int i = 0; (i < nFaces); i++)
  413. {
  414. if ((vertices[faces[i].ids[2]].cUsed > 2) &&
  415. (vertices[faces[i].ids[1]].cUsed > 2) &&
  416. (vertices[faces[0].ids[1]].cUsed > 2))
  417. {
  418. if (first)
  419. first = false;
  420. else
  421. fputs(",\n", fOutMesh);
  422. fprintf(fOutMesh, "3;%d,%d,%d;",
  423. vertices[faces[i].ids[2]].id,
  424. vertices[faces[i].ids[1]].id,
  425. vertices[faces[i].ids[0]].id);
  426. }
  427. }
  428. fputs(";\n", fOutMesh);
  429. }
  430. fprintf(fOutMesh, /*{*/"}\n");
  431. if (mode & c_endMesh)
  432. fclose(fOutMesh);
  433. }
  434. if (mode & c_ellipse)
  435. {
  436. //See if the bounding box is appropriately centered
  437. {
  438. int i;
  439. for (i = 0; (i < 3); i++)
  440. {
  441. if (fabs(xyzMin[i] + xyzMax[i]) > 0.05 * (xyzMax[i] - xyzMin[i]))
  442. break;
  443. }
  444. if (i != 3)
  445. {
  446. printf("***Non-centered cvh: %s\n", file);
  447. printf("\t%f %f\n", fabs(xyzMin[0] + xyzMax[0]), (xyzMax[0] - xyzMin[0]));
  448. printf("\t%f %f\n", fabs(xyzMin[1] + xyzMax[1]), (xyzMax[1] - xyzMin[1]));
  449. printf("\t%f %f\n", fabs(xyzMin[2] + xyzMax[2]), (xyzMax[2] - xyzMin[2]));
  450. }
  451. }
  452. //First attempt: find the best sphere
  453. double aBest = radius;
  454. double bBest = radius;
  455. double cBest = radius;
  456. double vBest = aBest * bBest * cBest;
  457. //Second attempt: find the best ellipse with the same aspect ratio as the bounding box
  458. {
  459. double a = fabs(xyzMin[0]) > fabs(xyzMax[0]) ? fabs(xyzMin[0]) : fabs(xyzMax[0]);
  460. double b = fabs(xyzMin[1]) > fabs(xyzMax[1]) ? fabs(xyzMin[1]) : fabs(xyzMax[1]);
  461. double c = fabs(xyzMin[2]) > fabs(xyzMax[2]) ? fabs(xyzMin[2]) : fabs(xyzMax[2]);
  462. double a2 = a * a;
  463. double b2 = b * b;
  464. double c2 = c * c;
  465. //Now find the fudge factor to make everything "fit"
  466. double rMax = 0.0;
  467. for (int i = 0; (i < nUsedVertices); i++)
  468. {
  469. int vertexID = vertexIDs[i];
  470. double r = (vertices[vertexID].xyz[0] * vertices[vertexID].xyz[0]) / a2 +
  471. (vertices[vertexID].xyz[1] * vertices[vertexID].xyz[1]) / b2 +
  472. (vertices[vertexID].xyz[2] * vertices[vertexID].xyz[2]) / c2;
  473. if (r > rMax)
  474. rMax = r;
  475. }
  476. rMax = sqrt(rMax);
  477. a *= rMax;
  478. b *= rMax;
  479. c *= rMax;
  480. double v = a * b * c;
  481. if (v < vBest)
  482. {
  483. vBest = v;
  484. aBest = a;
  485. bBest = b;
  486. cBest = c;
  487. }
  488. }
  489. //Third attempt ... try to find a better ellipse from the data
  490. {
  491. //Generate the best ellipse (minimum volume) ellipse that contains all of the points.
  492. //Do it the real expensive way: look at all point triples and deduce the radii of the axes
  493. //and then pick the one with the smallest volume
  494. //Ellipse equation:
  495. // (x/a)^2 + (y/b)^2 + (z/c)^2 = 1
  496. //We actually want to solve:
  497. // Minimize: 1.0 / (ra * rb * rc) such that
  498. // ra * x1^2 + rb * y1^2 + rc * z1^2 <= 1
  499. // ...
  500. // ra * xN^2 + rb * yN^2 + rc * zN^2 <= 1
  501. //but since it is too early in the morning to crank out a simplex algorithm, fake it:
  502. //Try all sets of 3 points, find the corresponding ellipse and see if it contains all the
  503. //other points.
  504. double* xyzs[3];
  505. for (int i = 0; (i < nUsedVertices - 2); i++)
  506. {
  507. xyzs[0] = vertices[vertexIDs[i]].xyz;
  508. for (int j = i + 1; (j < nUsedVertices - 1); j++)
  509. {
  510. xyzs[1] = vertices[vertexIDs[j]].xyz;
  511. for (int k = j + 1; (k < nUsedVertices); k++)
  512. {
  513. xyzs[2] = vertices[vertexIDs[k]].xyz;
  514. //Rewrite the ellipse equation
  515. //from: (x/a)^2 + (y/b)^2 + (z/c)^2 = 1
  516. //to: ra x^2 + rb y^2 + rc z^2 = 1 ra = 1.0/a^2; a = sqrt(1.0/ra);
  517. //and solve for xyz1, 2 & 3.
  518. //Setup the gaussian matrix (? ... boy, it has been awhile)
  519. double g[3][4];
  520. {
  521. for (int m = 0; (m < 3); m++)
  522. {
  523. for (int n = 0; (n < 3); n++)
  524. g[m][n] = xyzs[m][n] * xyzs[m][n];
  525. g[m][3] = 1.0f;
  526. }
  527. }
  528. //Reduce the gaussian
  529. if (reduce(g) &&
  530. (g[0][3] > 1.0e-4) &&
  531. (g[1][3] > 1.0e-4) &&
  532. (g[2][3] > 1.0e-4))
  533. {
  534. double a = sqrt(1.0 / g[0][3]);
  535. double b = sqrt(1.0 / g[1][3]);
  536. double c = sqrt(1.0 / g[2][3]);
  537. double v = a * b * c;
  538. if (v < vBest)
  539. {
  540. //Vertify that all of the other points in the convex hull are properly contained.
  541. for (int m = 0; (m < nUsedVertices); m++)
  542. {
  543. double x = vertices[vertexIDs[m]].xyz[0] / a;
  544. double y = vertices[vertexIDs[m]].xyz[1] / b;
  545. double z = vertices[vertexIDs[m]].xyz[2] / c;
  546. if (x*x + y*y + z*z > 1.01f) //Allow a bit of fudging
  547. break;
  548. }
  549. if (m == nUsedVertices)
  550. {
  551. vBest = v;
  552. aBest = a;
  553. bBest = b;
  554. cBest = c;
  555. }
  556. }
  557. }
  558. }
  559. }
  560. }
  561. }
  562. fprintf(fOut, "%16.8f%16.8f%16.8f%16.8f%16.8f\n",
  563. radius,
  564. aBest, bBest, cBest, ((aBest > bBest)
  565. ? ((aBest > cBest) ? aBest : cBest)
  566. : ((bBest > cBest) ? bBest : cBest)) / radius);
  567. }
  568. if (mode & c_oneHull)
  569. fprintf(fOut, "1\n");
  570. //Only print the vertices actually used by the convex hull
  571. if (mode & c_writeHull)
  572. {
  573. int nAdjacencies = 2 * (nUsedVertices + nFaces - nSingularFaces - 2);
  574. fprintf(fOut, "%5d%5d%18.8f%18.8f%18.8f\n",
  575. nUsedVertices, nAdjacencies,
  576. 0.5 * (xyzMin[0] + xyzMax[0]),
  577. 0.5 * (xyzMin[1] + xyzMax[1]),
  578. 0.5 * (xyzMin[2] + xyzMax[2]));
  579. bool firstF = true;
  580. for (int vertexID = 0; (vertexID < nVertices); vertexID++)
  581. {
  582. if (vertices[vertexID].cUsed > 2)
  583. {
  584. fprintf(fOut, "%18.8f%18.8f%18.8f",
  585. vertices[vertexID].xyz[0],
  586. vertices[vertexID].xyz[1],
  587. vertices[vertexID].xyz[2]);
  588. //print the adjacent vertices
  589. const int c_maxAdjacent = c_maxVertices;
  590. int adjacent[c_maxAdjacent];
  591. int nAdjacent = 0;
  592. for (int faceID = 0; (faceID < nFaces); faceID++)
  593. {
  594. //Does this face contain this vertex?
  595. if (vertexID == faces[faceID].ids[0])
  596. {
  597. addAdjacent(&nAdjacent, adjacent, faces[faceID].ids[1]);
  598. addAdjacent(&nAdjacent, adjacent, faces[faceID].ids[2]);
  599. }
  600. else if (vertexID == faces[faceID].ids[1])
  601. {
  602. addAdjacent(&nAdjacent, adjacent, faces[faceID].ids[0]);
  603. addAdjacent(&nAdjacent, adjacent, faces[faceID].ids[2]);
  604. }
  605. else if (vertexID == faces[faceID].ids[2])
  606. {
  607. addAdjacent(&nAdjacent, adjacent, faces[faceID].ids[0]);
  608. addAdjacent(&nAdjacent, adjacent, faces[faceID].ids[1]);
  609. }
  610. }
  611. fprintf(fOut, "%5d\n", nAdjacent);
  612. for (int a = 0; (a < nAdjacent); a++)
  613. fprintf(fOut, "%5d", vertices[adjacent[a]].id);
  614. fputc('\n', fOut);
  615. nAdjacencies -= nAdjacent;
  616. }
  617. }
  618. if (nAdjacencies != 0)
  619. {
  620. printf("Error constructing %s.cvh\n", file);
  621. success = false;
  622. }
  623. }
  624. fclose(fIn);
  625. }
  626. return success;
  627. }
  628. bool dat2cvh(const char* file, FILE* fOut)
  629. {
  630. bool success = false;
  631. char bfr[c_cbBfr];
  632. strcpy(bfr, file);
  633. strcat(bfr, ".dat");
  634. FILE* fIn = fopen(bfr, "r");
  635. if (fIn)
  636. {
  637. success = true;
  638. char line[c_cbBfr];
  639. while (fgets(line, c_cbBfr, fIn) != NULL)
  640. {
  641. fputs(line, fOut);
  642. }
  643. fclose(fIn);
  644. }
  645. return success;
  646. }