SurfaceExtractorTetrahedra.h 38 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995
  1. // David Eberly, Geometric Tools, Redmond WA 98052
  2. // Copyright (c) 1998-2020
  3. // Distributed under the Boost Software License, Version 1.0.
  4. // https://www.boost.org/LICENSE_1_0.txt
  5. // https://www.geometrictools.com/License/Boost/LICENSE_1_0.txt
  6. // Version: 4.0.2019.08.13
  7. #pragma once
  8. #include <Mathematics/SurfaceExtractor.h>
  9. #include <set>
  10. // The level set extraction algorithm implemented here is described
  11. // in the document
  12. // https://www.geometrictools.com/Documentation/ExtractLevelSurfaces.pdf
  13. namespace WwiseGTE
  14. {
  15. // The image type T must be one of the integer types: int8_t, int16_t,
  16. // int32_t, uint8_t, uint16_t or uint32_t. Internal integer computations
  17. // are performed using int64_t. The type Real is for extraction to
  18. // floating-point vertices.
  19. template <typename T, typename Real>
  20. class SurfaceExtractorTetrahedra : public SurfaceExtractor<T, Real>
  21. {
  22. public:
  23. // Convenience type definitions.
  24. typedef typename SurfaceExtractor<T, Real>::Vertex Vertex;
  25. typedef typename SurfaceExtractor<T, Real>::Triangle Triangle;
  26. // The input is a 3D image with lexicographically ordered voxels
  27. // (x,y,z) stored in a linear array. Voxel (x,y,z) is stored in the
  28. // array at location index = x + xBound * (y + yBound * z). The
  29. // inputs xBound, yBound and zBound must each be 2 or larger so that
  30. // there is at least one image cube to process. The inputVoxels must
  31. // be nonnull and point to contiguous storage that contains at least
  32. // xBound * yBound * zBound elements.
  33. SurfaceExtractorTetrahedra(int xBound, int yBound, int zBound, T const* inputVoxels)
  34. :
  35. SurfaceExtractor<T, Real>(xBound, yBound, zBound, inputVoxels),
  36. mNextVertex(0)
  37. {
  38. }
  39. // Extract level surfaces and return rational vertices. Use the
  40. // base-class Extract if you want real-valued vertices.
  41. virtual void Extract(T level, std::vector<Vertex>& vertices,
  42. std::vector<Triangle>& triangles) override
  43. {
  44. // Adjust the image so that the level set is F(x,y,z) = 0.
  45. int64_t levelI64 = static_cast<int64_t>(level);
  46. for (size_t i = 0; i < this->mVoxels.size(); ++i)
  47. {
  48. int64_t inputI64 = static_cast<int64_t>(this->mInputVoxels[i]);
  49. this->mVoxels[i] = inputI64 - levelI64;
  50. }
  51. mVMap.clear();
  52. mESet.clear();
  53. mTSet.clear();
  54. mNextVertex = 0;
  55. vertices.clear();
  56. triangles.clear();
  57. for (int z = 0, zp = 1; zp < this->mZBound; ++z, ++zp)
  58. {
  59. int zParity = (z & 1);
  60. for (int y = 0, yp = 1; yp < this->mYBound; ++y, ++yp)
  61. {
  62. int yParity = (y & 1);
  63. for (int x = 0, xp = 1; xp < this->mXBound; ++x, ++xp)
  64. {
  65. int xParity = (x & 1);
  66. int i000 = x + this->mXBound * (y + this->mYBound * z);
  67. int i100 = i000 + 1;
  68. int i010 = i000 + this->mXBound;
  69. int i110 = i010 + 1;
  70. int i001 = i000 + this->mXYBound;
  71. int i101 = i001 + 1;
  72. int i011 = i001 + this->mXBound;
  73. int i111 = i011 + 1;
  74. int64_t f000 = static_cast<int64_t>(this->mVoxels[i000]);
  75. int64_t f100 = static_cast<int64_t>(this->mVoxels[i100]);
  76. int64_t f010 = static_cast<int64_t>(this->mVoxels[i010]);
  77. int64_t f110 = static_cast<int64_t>(this->mVoxels[i110]);
  78. int64_t f001 = static_cast<int64_t>(this->mVoxels[i001]);
  79. int64_t f101 = static_cast<int64_t>(this->mVoxels[i101]);
  80. int64_t f011 = static_cast<int64_t>(this->mVoxels[i011]);
  81. int64_t f111 = static_cast<int64_t>(this->mVoxels[i111]);
  82. if (xParity ^ yParity ^ zParity)
  83. {
  84. // 1205
  85. ProcessTetrahedron(
  86. xp, y, z, f100,
  87. xp, yp, z, f110,
  88. x, y, z, f000,
  89. xp, y, zp, f101);
  90. // 3027
  91. ProcessTetrahedron(
  92. x, yp, z, f010,
  93. x, y, z, f000,
  94. xp, yp, z, f110,
  95. x, yp, zp, f011);
  96. // 4750
  97. ProcessTetrahedron(
  98. x, y, zp, f001,
  99. x, yp, zp, f011,
  100. xp, y, zp, f101,
  101. x, y, z, f000);
  102. // 6572
  103. ProcessTetrahedron(
  104. xp, yp, zp, f111,
  105. xp, y, zp, f101,
  106. x, yp, zp, f011,
  107. xp, yp, z, f110);
  108. // 0752
  109. ProcessTetrahedron(
  110. x, y, z, f000,
  111. x, yp, zp, f011,
  112. xp, y, zp, f101,
  113. xp, yp, z, f110);
  114. }
  115. else
  116. {
  117. // 0134
  118. ProcessTetrahedron(
  119. x, y, z, f000,
  120. xp, y, z, f100,
  121. x, yp, z, f010,
  122. x, y, zp, f001);
  123. // 2316
  124. ProcessTetrahedron(
  125. xp, yp, z, f110,
  126. x, yp, z, f010,
  127. xp, y, z, f100,
  128. xp, yp, zp, f111);
  129. // 5461
  130. ProcessTetrahedron(
  131. xp, y, zp, f101,
  132. x, y, zp, f001,
  133. xp, yp, zp, f111,
  134. xp, y, z, f100);
  135. // 7643
  136. ProcessTetrahedron(
  137. x, yp, zp, f011,
  138. xp, yp, zp, f111,
  139. x, y, zp, f001,
  140. x, yp, z, f010);
  141. // 6314
  142. ProcessTetrahedron(
  143. xp, yp, zp, f111,
  144. x, yp, z, f010,
  145. xp, y, z, f100,
  146. x, y, zp, f001);
  147. }
  148. }
  149. }
  150. }
  151. // Pack vertices into an array.
  152. vertices.resize(mVMap.size());
  153. for (auto const& element : mVMap)
  154. {
  155. vertices[element.second] = element.first;
  156. }
  157. // Pack edges into an array (computed, but not reported to
  158. // caller).
  159. std::vector<Edge> edges(mESet.size());
  160. size_t i = 0;
  161. for (auto const& element : mESet)
  162. {
  163. edges[i++] = element;
  164. }
  165. // Pack triangles into an array.
  166. triangles.resize(mTSet.size());
  167. i = 0;
  168. for (auto const& element : mTSet)
  169. {
  170. triangles[i++] = element;
  171. }
  172. }
  173. protected:
  174. struct Edge
  175. {
  176. Edge() = default;
  177. Edge(int v0, int v1)
  178. {
  179. if (v0 < v1)
  180. {
  181. v[0] = v0;
  182. v[1] = v1;
  183. }
  184. else
  185. {
  186. v[0] = v1;
  187. v[1] = v0;
  188. }
  189. }
  190. bool operator==(Edge const& other) const
  191. {
  192. return v[0] == other.v[0] && v[1] == other.v[1];
  193. }
  194. bool operator<(Edge const& other) const
  195. {
  196. for (int i = 0; i < 2; ++i)
  197. {
  198. if (v[i] < other.v[i])
  199. {
  200. return true;
  201. }
  202. if (v[i] > other.v[i])
  203. {
  204. return false;
  205. }
  206. }
  207. return false;
  208. }
  209. std::array<int, 2> v;
  210. };
  211. virtual std::array<Real, 3> GetGradient(std::array<Real, 3> const& pos) override
  212. {
  213. std::array<Real, 3> const zero{ (Real)0, (Real)0, (Real)0 };
  214. int x = static_cast<int>(pos[0]);
  215. if (x < 0 || x + 1 >= this->mXBound)
  216. {
  217. return zero;
  218. }
  219. int y = static_cast<int>(pos[1]);
  220. if (y < 0 || y + 1 >= this->mYBound)
  221. {
  222. return zero;
  223. }
  224. int z = static_cast<int>(pos[2]);
  225. if (z < 0 || z + 1 >= this->mZBound)
  226. {
  227. return zero;
  228. }
  229. // Get image values at corners of voxel.
  230. int i000 = x + this->mXBound * (y + this->mYBound * z);
  231. int i100 = i000 + 1;
  232. int i010 = i000 + this->mXBound;
  233. int i110 = i010 + 1;
  234. int i001 = i000 + this->mXYBound;
  235. int i101 = i001 + 1;
  236. int i011 = i001 + this->mXBound;
  237. int i111 = i011 + 1;
  238. Real f000 = static_cast<Real>(this->mVoxels[i000]);
  239. Real f100 = static_cast<Real>(this->mVoxels[i100]);
  240. Real f010 = static_cast<Real>(this->mVoxels[i010]);
  241. Real f110 = static_cast<Real>(this->mVoxels[i110]);
  242. Real f001 = static_cast<Real>(this->mVoxels[i001]);
  243. Real f101 = static_cast<Real>(this->mVoxels[i101]);
  244. Real f011 = static_cast<Real>(this->mVoxels[i011]);
  245. Real f111 = static_cast<Real>(this->mVoxels[i111]);
  246. Real dx = pos[0] - static_cast<Real>(x);
  247. Real dy = pos[1] - static_cast<Real>(y);
  248. Real dz = pos[2] - static_cast<Real>(z);
  249. std::array<Real, 3> grad;
  250. if ((x & 1) ^ (y & 1) ^ (z & 1))
  251. {
  252. if (dx - dy - dz >= (Real)0)
  253. {
  254. // 1205
  255. grad[0] = +f100 - f000;
  256. grad[1] = -f100 + f110;
  257. grad[2] = -f100 + f101;
  258. }
  259. else if (dx - dy + dz <= (Real)0)
  260. {
  261. // 3027
  262. grad[0] = -f010 + f110;
  263. grad[1] = +f010 - f000;
  264. grad[2] = -f010 + f011;
  265. }
  266. else if (dx + dy - dz <= (Real)0)
  267. {
  268. // 4750
  269. grad[0] = -f001 + f101;
  270. grad[1] = -f001 + f011;
  271. grad[2] = +f001 - f000;
  272. }
  273. else if (dx + dy + dz >= (Real)0)
  274. {
  275. // 6572
  276. grad[0] = +f111 - f011;
  277. grad[1] = +f111 - f101;
  278. grad[2] = +f111 - f110;
  279. }
  280. else
  281. {
  282. // 0752
  283. grad[0] = (Real)0.5 * (-f000 - f011 + f101 + f110);
  284. grad[1] = (Real)0.5 * (-f000 + f011 - f101 + f110);
  285. grad[2] = (Real)0.5 * (-f000 + f011 + f101 - f110);
  286. }
  287. }
  288. else
  289. {
  290. if (dx + dy + dz <= (Real)1)
  291. {
  292. // 0134
  293. grad[0] = -f000 + f100;
  294. grad[1] = -f000 + f010;
  295. grad[2] = -f000 + f001;
  296. }
  297. else if (dx + dy - dz >= (Real)1)
  298. {
  299. // 2316
  300. grad[0] = +f110 - f010;
  301. grad[1] = +f110 - f100;
  302. grad[2] = -f110 + f111;
  303. }
  304. else if (dx - dy + dz >= (Real)1)
  305. {
  306. // 5461
  307. grad[0] = +f101 - f001;
  308. grad[1] = -f101 + f111;
  309. grad[2] = +f101 - f100;
  310. }
  311. else if (-dx + dy + dz >= (Real)1)
  312. {
  313. // 7643
  314. grad[0] = -f011 + f111;
  315. grad[1] = +f011 - f001;
  316. grad[2] = +f011 - f010;
  317. }
  318. else
  319. {
  320. // 6314
  321. grad[0] = (Real)0.5 * (f111 - f010 + f100 - f001);
  322. grad[1] = (Real)0.5 * (f111 + f010 - f100 - f001);
  323. grad[2] = (Real)0.5 * (f111 - f010 - f100 + f001);
  324. }
  325. }
  326. return grad;
  327. }
  328. int AddVertex(Vertex const& v)
  329. {
  330. auto iter = mVMap.find(v);
  331. if (iter != mVMap.end())
  332. {
  333. // Vertex already in map, just return its unique index.
  334. return iter->second;
  335. }
  336. else
  337. {
  338. // Vertex not in map, insert it and assign it a unique index.
  339. int i = mNextVertex++;
  340. mVMap.insert(std::make_pair(v, i));
  341. return i;
  342. }
  343. }
  344. void AddEdge(Vertex const& v0, Vertex const& v1)
  345. {
  346. int i0 = AddVertex(v0);
  347. int i1 = AddVertex(v1);
  348. mESet.insert(Edge(i0, i1));
  349. }
  350. void AddTriangle(Vertex const& v0, Vertex const& v1, Vertex const& v2)
  351. {
  352. int i0 = AddVertex(v0);
  353. int i1 = AddVertex(v1);
  354. int i2 = AddVertex(v2);
  355. // Nothing to do if triangle already exists.
  356. Triangle triangle(i0, i1, i2);
  357. if (mTSet.find(triangle) != mTSet.end())
  358. {
  359. return;
  360. }
  361. // Prevent double-sided triangles.
  362. std::swap(triangle.v[1], triangle.v[2]);
  363. if (mTSet.find(triangle) != mTSet.end())
  364. {
  365. return;
  366. }
  367. mESet.insert(Edge(i0, i1));
  368. mESet.insert(Edge(i1, i2));
  369. mESet.insert(Edge(i2, i0));
  370. mTSet.insert(triangle);
  371. }
  372. // Support for extraction with linear interpolation.
  373. void ProcessTetrahedron(
  374. int64_t x0, int64_t y0, int64_t z0, int64_t f0,
  375. int64_t x1, int64_t y1, int64_t z1, int64_t f1,
  376. int64_t x2, int64_t y2, int64_t z2, int64_t f2,
  377. int64_t x3, int64_t y3, int64_t z3, int64_t f3)
  378. {
  379. int64_t xn0, yn0, zn0, d0;
  380. int64_t xn1, yn1, zn1, d1;
  381. int64_t xn2, yn2, zn2, d2;
  382. int64_t xn3, yn3, zn3, d3;
  383. if (f0 != 0)
  384. {
  385. // convert to case +***
  386. if (f0 < 0)
  387. {
  388. f0 = -f0;
  389. f1 = -f1;
  390. f2 = -f2;
  391. f3 = -f3;
  392. }
  393. if (f1 > 0)
  394. {
  395. if (f2 > 0)
  396. {
  397. if (f3 > 0)
  398. {
  399. // ++++
  400. return;
  401. }
  402. else if (f3 < 0)
  403. {
  404. // +++-
  405. d0 = f0 - f3;
  406. xn0 = f0 * x3 - f3 * x0;
  407. yn0 = f0 * y3 - f3 * y0;
  408. zn0 = f0 * z3 - f3 * z0;
  409. d1 = f1 - f3;
  410. xn1 = f1 * x3 - f3 * x1;
  411. yn1 = f1 * y3 - f3 * y1;
  412. zn1 = f1 * z3 - f3 * z1;
  413. d2 = f2 - f3;
  414. xn2 = f2 * x3 - f3 * x2;
  415. yn2 = f2 * y3 - f3 * y2;
  416. zn2 = f2 * z3 - f3 * z2;
  417. AddTriangle(
  418. Vertex(xn0, d0, yn0, d0, zn0, d0),
  419. Vertex(xn1, d1, yn1, d1, zn1, d1),
  420. Vertex(xn2, d2, yn2, d2, zn2, d2));
  421. }
  422. else
  423. {
  424. // +++0
  425. AddVertex(
  426. Vertex(x3, 1, y3, 1, z3, 1));
  427. }
  428. }
  429. else if (f2 < 0)
  430. {
  431. d0 = f0 - f2;
  432. xn0 = f0 * x2 - f2 * x0;
  433. yn0 = f0 * y2 - f2 * y0;
  434. zn0 = f0 * z2 - f2 * z0;
  435. d1 = f1 - f2;
  436. xn1 = f1 * x2 - f2 * x1;
  437. yn1 = f1 * y2 - f2 * y1;
  438. zn1 = f1 * z2 - f2 * z1;
  439. if (f3 > 0)
  440. {
  441. // ++-+
  442. d2 = f3 - f2;
  443. xn2 = f3 * x2 - f2 * x3;
  444. yn2 = f3 * y2 - f2 * y3;
  445. zn2 = f3 * z2 - f2 * z3;
  446. AddTriangle(
  447. Vertex(xn0, d0, yn0, d0, zn0, d0),
  448. Vertex(xn1, d1, yn1, d1, zn1, d1),
  449. Vertex(xn2, d2, yn2, d2, zn2, d2));
  450. }
  451. else if (f3 < 0)
  452. {
  453. // ++--
  454. d2 = f0 - f3;
  455. xn2 = f0 * x3 - f3 * x0;
  456. yn2 = f0 * y3 - f3 * y0;
  457. zn2 = f0 * z3 - f3 * z0;
  458. d3 = f1 - f3;
  459. xn3 = f1 * x3 - f3 * x1;
  460. yn3 = f1 * y3 - f3 * y1;
  461. zn3 = f1 * z3 - f3 * z1;
  462. AddTriangle(
  463. Vertex(xn0, d0, yn0, d0, zn0, d0),
  464. Vertex(xn1, d1, yn1, d1, zn1, d1),
  465. Vertex(xn2, d2, yn2, d2, zn2, d2));
  466. AddTriangle(
  467. Vertex(xn1, d1, yn1, d1, zn1, d1),
  468. Vertex(xn3, d3, yn3, d3, zn3, d3),
  469. Vertex(xn2, d2, yn2, d2, zn2, d2));
  470. }
  471. else
  472. {
  473. // ++-0
  474. AddTriangle(
  475. Vertex(xn0, d0, yn0, d0, zn0, d0),
  476. Vertex(xn1, d1, yn1, d1, zn1, d1),
  477. Vertex(x3, 1, y3, 1, z3, 1));
  478. }
  479. }
  480. else
  481. {
  482. if (f3 > 0)
  483. {
  484. // ++0+
  485. AddVertex(
  486. Vertex(x2, 1, y2, 1, z2, 1));
  487. }
  488. else if (f3 < 0)
  489. {
  490. // ++0-
  491. d0 = f0 - f3;
  492. xn0 = f0 * x3 - f3 * x0;
  493. yn0 = f0 * y3 - f3 * y0;
  494. zn0 = f0 * z3 - f3 * z0;
  495. d1 = f1 - f3;
  496. xn1 = f1 * x3 - f3 * x1;
  497. yn1 = f1 * y3 - f3 * y1;
  498. zn1 = f1 * z3 - f3 * z1;
  499. AddTriangle(
  500. Vertex(xn0, d0, yn0, d0, zn0, d0),
  501. Vertex(xn1, d1, yn1, d1, zn1, d1),
  502. Vertex(x2, 1, y2, 1, z2, 1));
  503. }
  504. else
  505. {
  506. // ++00
  507. AddEdge(
  508. Vertex(x2, 1, y2, 1, z2, 1),
  509. Vertex(x3, 1, y3, 1, z3, 1));
  510. }
  511. }
  512. }
  513. else if (f1 < 0)
  514. {
  515. if (f2 > 0)
  516. {
  517. d0 = f0 - f1;
  518. xn0 = f0 * x1 - f1 * x0;
  519. yn0 = f0 * y1 - f1 * y0;
  520. zn0 = f0 * z1 - f1 * z0;
  521. d1 = f2 - f1;
  522. xn1 = f2 * x1 - f1 * x2;
  523. yn1 = f2 * y1 - f1 * y2;
  524. zn1 = f2 * z1 - f1 * z2;
  525. if (f3 > 0)
  526. {
  527. // +-++
  528. d2 = f3 - f1;
  529. xn2 = f3 * x1 - f1 * x3;
  530. yn2 = f3 * y1 - f1 * y3;
  531. zn2 = f3 * z1 - f1 * z3;
  532. AddTriangle(
  533. Vertex(xn0, d0, yn0, d0, zn0, d0),
  534. Vertex(xn1, d1, yn1, d1, zn1, d1),
  535. Vertex(xn2, d2, yn2, d2, zn2, d2));
  536. }
  537. else if (f3 < 0)
  538. {
  539. // +-+-
  540. d2 = f0 - f3;
  541. xn2 = f0 * x3 - f3 * x0;
  542. yn2 = f0 * y3 - f3 * y0;
  543. zn2 = f0 * z3 - f3 * z0;
  544. d3 = f2 - f3;
  545. xn3 = f2 * x3 - f3 * x2;
  546. yn3 = f2 * y3 - f3 * y2;
  547. zn3 = f2 * z3 - f3 * z2;
  548. AddTriangle(
  549. Vertex(xn0, d0, yn0, d0, zn0, d0),
  550. Vertex(xn1, d1, yn1, d1, zn1, d1),
  551. Vertex(xn2, d2, yn2, d2, zn2, d2));
  552. AddTriangle(
  553. Vertex(xn1, d1, yn1, d1, zn1, d1),
  554. Vertex(xn3, d3, yn3, d3, zn3, d3),
  555. Vertex(xn2, d2, yn2, d2, zn2, d2));
  556. }
  557. else
  558. {
  559. // +-+0
  560. AddTriangle(
  561. Vertex(xn0, d0, yn0, d0, zn0, d0),
  562. Vertex(xn1, d1, yn1, d1, zn1, d1),
  563. Vertex(x3, 1, y3, 1, z3, 1));
  564. }
  565. }
  566. else if (f2 < 0)
  567. {
  568. d0 = f1 - f0;
  569. xn0 = f1 * x0 - f0 * x1;
  570. yn0 = f1 * y0 - f0 * y1;
  571. zn0 = f1 * z0 - f0 * z1;
  572. d1 = f2 - f0;
  573. xn1 = f2 * x0 - f0 * x2;
  574. yn1 = f2 * y0 - f0 * y2;
  575. zn1 = f2 * z0 - f0 * z2;
  576. if (f3 > 0)
  577. {
  578. // +--+
  579. d2 = f1 - f3;
  580. xn2 = f1 * x3 - f3 * x1;
  581. yn2 = f1 * y3 - f3 * y1;
  582. zn2 = f1 * z3 - f3 * z1;
  583. d3 = f2 - f3;
  584. xn3 = f2 * x3 - f3 * x2;
  585. yn3 = f2 * y3 - f3 * y2;
  586. zn3 = f2 * z3 - f3 * z2;
  587. AddTriangle(
  588. Vertex(xn0, d0, yn0, d0, zn0, d0),
  589. Vertex(xn1, d1, yn1, d1, zn1, d1),
  590. Vertex(xn2, d2, yn2, d2, zn2, d2));
  591. AddTriangle(
  592. Vertex(xn1, d1, yn1, d1, zn1, d1),
  593. Vertex(xn3, d3, yn3, d3, zn3, d3),
  594. Vertex(xn2, d2, yn2, d2, zn2, d2));
  595. }
  596. else if (f3 < 0)
  597. {
  598. // +---
  599. d2 = f3 - f0;
  600. xn2 = f3 * x0 - f0 * x3;
  601. yn2 = f3 * y0 - f0 * y3;
  602. zn2 = f3 * z0 - f0 * z3;
  603. AddTriangle(
  604. Vertex(xn0, d0, yn0, d0, zn0, d0),
  605. Vertex(xn1, d1, yn1, d1, zn1, d1),
  606. Vertex(xn2, d2, yn2, d2, zn2, d2));
  607. }
  608. else
  609. {
  610. // +--0
  611. AddTriangle(
  612. Vertex(xn0, d0, yn0, d0, zn0, d0),
  613. Vertex(xn1, d1, yn1, d1, zn1, d1),
  614. Vertex(x3, 1, y3, 1, z3, 1));
  615. }
  616. }
  617. else
  618. {
  619. d0 = f1 - f0;
  620. xn0 = f1 * x0 - f0 * x1;
  621. yn0 = f1 * y0 - f0 * y1;
  622. zn0 = f1 * z0 - f0 * z1;
  623. if (f3 > 0)
  624. {
  625. // +-0+
  626. d1 = f1 - f3;
  627. xn1 = f1 * x3 - f3 * x1;
  628. yn1 = f1 * y3 - f3 * y1;
  629. zn1 = f1 * z3 - f3 * z1;
  630. AddTriangle(
  631. Vertex(xn0, d0, yn0, d0, zn0, d0),
  632. Vertex(xn1, d1, yn1, d1, zn1, d1),
  633. Vertex(x2, 1, y2, 1, z2, 1));
  634. }
  635. else if (f3 < 0)
  636. {
  637. // +-0-
  638. d1 = f3 - f0;
  639. xn1 = f3 * x0 - f0 * x3;
  640. yn1 = f3 * y0 - f0 * y3;
  641. zn1 = f3 * z0 - f0 * z3;
  642. AddTriangle(
  643. Vertex(xn0, d0, yn0, d0, zn0, d0),
  644. Vertex(xn1, d1, yn1, d1, zn1, d1),
  645. Vertex(x2, 1, y2, 1, z2, 1));
  646. }
  647. else
  648. {
  649. // +-00
  650. AddTriangle(
  651. Vertex(xn0, d0, yn0, d0, zn0, d0),
  652. Vertex(x2, 1, y2, 1, z2, 1),
  653. Vertex(x3, 1, y3, 1, z3, 1));
  654. }
  655. }
  656. }
  657. else
  658. {
  659. if (f2 > 0)
  660. {
  661. if (f3 > 0)
  662. {
  663. // +0++
  664. AddVertex(
  665. Vertex(x1, 1, y1, 1, z1, 1));
  666. }
  667. else if (f3 < 0)
  668. {
  669. // +0+-
  670. d0 = f0 - f3;
  671. xn0 = f0 * x3 - f3 * x0;
  672. yn0 = f0 * y3 - f3 * y0;
  673. zn0 = f0 * z3 - f3 * z0;
  674. d1 = f2 - f3;
  675. xn1 = f2 * x3 - f3 * x2;
  676. yn1 = f2 * y3 - f3 * y2;
  677. zn1 = f2 * z3 - f3 * z2;
  678. AddTriangle(
  679. Vertex(xn0, d0, yn0, d0, zn0, d0),
  680. Vertex(xn1, d1, yn1, d1, zn1, d1),
  681. Vertex(x1, 1, y1, 1, z1, 1));
  682. }
  683. else
  684. {
  685. // +0+0
  686. AddEdge(
  687. Vertex(x1, 1, y1, 1, z1, 1),
  688. Vertex(x3, 1, y3, 1, z3, 1));
  689. }
  690. }
  691. else if (f2 < 0)
  692. {
  693. d0 = f2 - f0;
  694. xn0 = f2 * x0 - f0 * x2;
  695. yn0 = f2 * y0 - f0 * y2;
  696. zn0 = f2 * z0 - f0 * z2;
  697. if (f3 > 0)
  698. {
  699. // +0-+
  700. d1 = f2 - f3;
  701. xn1 = f2 * x3 - f3 * x2;
  702. yn1 = f2 * y3 - f3 * y2;
  703. zn1 = f2 * z3 - f3 * z2;
  704. AddTriangle(
  705. Vertex(xn0, d0, yn0, d0, zn0, d0),
  706. Vertex(xn1, d1, yn1, d1, zn1, d1),
  707. Vertex(x1, 1, y1, 1, z1, 1));
  708. }
  709. else if (f3 < 0)
  710. {
  711. // +0--
  712. d1 = f0 - f3;
  713. xn1 = f0 * x3 - f3 * x0;
  714. yn1 = f0 * y3 - f3 * y0;
  715. zn1 = f0 * z3 - f3 * z0;
  716. AddTriangle(
  717. Vertex(xn0, d0, yn0, d0, zn0, d0),
  718. Vertex(xn1, d1, yn1, d1, zn1, d1),
  719. Vertex(x1, 1, y1, 1, z1, 1));
  720. }
  721. else
  722. {
  723. // +0-0
  724. AddTriangle(
  725. Vertex(xn0, d0, yn0, d0, zn0, d0),
  726. Vertex(x1, 1, y1, 1, z1, 1),
  727. Vertex(x3, 1, y3, 1, z3, 1));
  728. }
  729. }
  730. else
  731. {
  732. if (f3 > 0)
  733. {
  734. // +00+
  735. AddEdge(
  736. Vertex(x1, 1, y1, 1, z1, 1),
  737. Vertex(x2, 1, y2, 1, z2, 1));
  738. }
  739. else if (f3 < 0)
  740. {
  741. // +00-
  742. d0 = f0 - f3;
  743. xn0 = f0 * x3 - f3 * x0;
  744. yn0 = f0 * y3 - f3 * y0;
  745. zn0 = f0 * z3 - f3 * z0;
  746. AddTriangle(
  747. Vertex(xn0, d0, yn0, d0, zn0, d0),
  748. Vertex(x1, 1, y1, 1, z1, 1),
  749. Vertex(x2, 1, y2, 1, z2, 1));
  750. }
  751. else
  752. {
  753. // +000
  754. AddTriangle(
  755. Vertex(x1, 1, y1, 1, z1, 1),
  756. Vertex(x2, 1, y2, 1, z2, 1),
  757. Vertex(x3, 1, y3, 1, z3, 1));
  758. }
  759. }
  760. }
  761. }
  762. else if (f1 != 0)
  763. {
  764. // convert to case 0+**
  765. if (f1 < 0)
  766. {
  767. f1 = -f1;
  768. f2 = -f2;
  769. f3 = -f3;
  770. }
  771. if (f2 > 0)
  772. {
  773. if (f3 > 0)
  774. {
  775. // 0+++
  776. AddVertex(
  777. Vertex(x0, 1, y0, 1, z0, 1));
  778. }
  779. else if (f3 < 0)
  780. {
  781. // 0++-
  782. d0 = f2 - f3;
  783. xn0 = f2 * x3 - f3 * x2;
  784. yn0 = f2 * y3 - f3 * y2;
  785. zn0 = f2 * z3 - f3 * z2;
  786. d1 = f1 - f3;
  787. xn1 = f1 * x3 - f3 * x1;
  788. yn1 = f1 * y3 - f3 * y1;
  789. zn1 = f1 * z3 - f3 * z1;
  790. AddTriangle(
  791. Vertex(xn0, d0, yn0, d0, zn0, d0),
  792. Vertex(xn1, d1, yn1, d1, zn1, d1),
  793. Vertex(x0, 1, y0, 1, z0, 1));
  794. }
  795. else
  796. {
  797. // 0++0
  798. AddEdge(
  799. Vertex(x0, 1, y0, 1, z0, 1),
  800. Vertex(x3, 1, y3, 1, z3, 1));
  801. }
  802. }
  803. else if (f2 < 0)
  804. {
  805. d0 = f2 - f1;
  806. xn0 = f2 * x1 - f1 * x2;
  807. yn0 = f2 * y1 - f1 * y2;
  808. zn0 = f2 * z1 - f1 * z2;
  809. if (f3 > 0)
  810. {
  811. // 0+-+
  812. d1 = f2 - f3;
  813. xn1 = f2 * x3 - f3 * x2;
  814. yn1 = f2 * y3 - f3 * y2;
  815. zn1 = f2 * z3 - f3 * z2;
  816. AddTriangle(
  817. Vertex(xn0, d0, yn0, d0, zn0, d0),
  818. Vertex(xn1, d1, yn1, d1, zn1, d1),
  819. Vertex(x0, 1, y0, 1, z0, 1));
  820. }
  821. else if (f3 < 0)
  822. {
  823. // 0+--
  824. d1 = f1 - f3;
  825. xn1 = f1 * x3 - f3 * x1;
  826. yn1 = f1 * y3 - f3 * y1;
  827. zn1 = f1 * z3 - f3 * z1;
  828. AddTriangle(
  829. Vertex(xn0, d0, yn0, d0, zn0, d0),
  830. Vertex(xn1, d1, yn1, d1, zn1, d1),
  831. Vertex(x0, 1, y0, 1, z0, 1));
  832. }
  833. else
  834. {
  835. // 0+-0
  836. AddTriangle(
  837. Vertex(xn0, d0, yn0, d0, zn0, d0),
  838. Vertex(x0, 1, y0, 1, z0, 1),
  839. Vertex(x3, 1, y3, 1, z3, 1));
  840. }
  841. }
  842. else
  843. {
  844. if (f3 > 0)
  845. {
  846. // 0+0+
  847. AddEdge(
  848. Vertex(x0, 1, y0, 1, z0, 1),
  849. Vertex(x2, 1, y2, 1, z2, 1));
  850. }
  851. else if (f3 < 0)
  852. {
  853. // 0+0-
  854. d0 = f1 - f3;
  855. xn0 = f1 * x3 - f3 * x1;
  856. yn0 = f1 * y3 - f3 * y1;
  857. zn0 = f1 * z3 - f3 * z1;
  858. AddTriangle(
  859. Vertex(xn0, d0, yn0, d0, zn0, d0),
  860. Vertex(x0, 1, y0, 1, z0, 1),
  861. Vertex(x2, 1, y2, 1, z2, 1));
  862. }
  863. else
  864. {
  865. // 0+00
  866. AddTriangle(
  867. Vertex(x0, 1, y0, 1, z0, 1),
  868. Vertex(x2, 1, y2, 1, z2, 1),
  869. Vertex(x3, 1, y3, 1, z3, 1));
  870. }
  871. }
  872. }
  873. else if (f2 != 0)
  874. {
  875. // convert to case 00+*
  876. if (f2 < 0)
  877. {
  878. f2 = -f2;
  879. f3 = -f3;
  880. }
  881. if (f3 > 0)
  882. {
  883. // 00++
  884. AddEdge(
  885. Vertex(x0, 1, y0, 1, z0, 1),
  886. Vertex(x1, 1, y1, 1, z1, 1));
  887. }
  888. else if (f3 < 0)
  889. {
  890. // 00+-
  891. d0 = f2 - f3;
  892. xn0 = f2 * x3 - f3 * x2;
  893. yn0 = f2 * y3 - f3 * y2;
  894. zn0 = f2 * z3 - f3 * z2;
  895. AddTriangle(
  896. Vertex(xn0, d0, yn0, d0, zn0, d0),
  897. Vertex(x0, 1, y0, 1, z0, 1),
  898. Vertex(x1, 1, y1, 1, z1, 1));
  899. }
  900. else
  901. {
  902. // 00+0
  903. AddTriangle(
  904. Vertex(x0, 1, y0, 1, z0, 1),
  905. Vertex(x1, 1, y1, 1, z1, 1),
  906. Vertex(x3, 1, y3, 1, z3, 1));
  907. }
  908. }
  909. else if (f3 != 0)
  910. {
  911. // cases 000+ or 000-
  912. AddTriangle(
  913. Vertex(x0, 1, y0, 1, z0, 1),
  914. Vertex(x1, 1, y1, 1, z1, 1),
  915. Vertex(x2, 1, y2, 1, z2, 1));
  916. }
  917. else
  918. {
  919. // case 0000
  920. AddTriangle(
  921. Vertex(x0, 1, y0, 1, z0, 1),
  922. Vertex(x1, 1, y1, 1, z1, 1),
  923. Vertex(x2, 1, y2, 1, z2, 1));
  924. AddTriangle(
  925. Vertex(x0, 1, y0, 1, z0, 1),
  926. Vertex(x1, 1, y1, 1, z1, 1),
  927. Vertex(x3, 1, y3, 1, z3, 1));
  928. AddTriangle(
  929. Vertex(x0, 1, y0, 1, z0, 1),
  930. Vertex(x2, 1, y2, 1, z2, 1),
  931. Vertex(x3, 1, y3, 1, z3, 1));
  932. AddTriangle(
  933. Vertex(x1, 1, y1, 1, z1, 1),
  934. Vertex(x2, 1, y2, 1, z2, 1),
  935. Vertex(x3, 1, y3, 1, z3, 1));
  936. }
  937. }
  938. std::map<Vertex, int> mVMap;
  939. std::set<Edge> mESet;
  940. std::set<Triangle> mTSet;
  941. int mNextVertex;
  942. };
  943. }