AdaptiveSkeletonClimbing3.h 99 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872
  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.2020.01.08
  7. #pragma once
  8. #include <Mathematics/Logger.h>
  9. #include <Mathematics/Array2.h>
  10. #include <Mathematics/Math.h>
  11. #include <Mathematics/TriangleKey.h>
  12. #include <map>
  13. #include <memory>
  14. #include <ostream>
  15. // Extract level surfaces using an adaptive approach to reduce the triangle
  16. // count. The implementation is for the algorithm described in the paper
  17. // Multiresolution Isosurface Extraction with Adaptive Skeleton Climbing
  18. // Tim Poston, Tien-Tsin Wong and Pheng-Ann Heng
  19. // Computer Graphics forum, volume 17, issue 3, September 1998
  20. // pages 137-147
  21. // https://onlinelibrary.wiley.com/doi/abs/10.1111/1467-8659.00261
  22. namespace WwiseGTE
  23. {
  24. // The image type T must be one of the integer types: int8_t, int16_t,
  25. // int32_t, uint8_t, uint16_t or uint32_t. Internal integer computations
  26. // are performed using int64_t. The type Real is for extraction to
  27. // floating-point vertices.
  28. template <typename T, typename Real>
  29. class AdaptiveSkeletonClimbing3
  30. {
  31. public:
  32. // Construction and destruction. The input image is assumed to
  33. // contain (2^N+1)-by-(2^N+1)-by-(2^N+1) elements where N >= 0.
  34. // The organization is lexicographic order for (x,y,z). When
  35. // 'fixBoundary' is set to 'true', image boundary voxels are not
  36. // allowed to merge with any other voxels. This forces highest
  37. // level of detail on the boundary. The idea is that an image too
  38. // large to process by itself can be partitioned into smaller
  39. // subimages and the adaptive skeleton climbing applied to each
  40. // subimage. By forcing highest resolution on the boundary,
  41. // adjacent subimages will not have any cracking problems.
  42. AdaptiveSkeletonClimbing3(int N, T const* inputVoxels,
  43. bool fixBoundary = false)
  44. :
  45. mTwoPowerN(1 << N),
  46. mSize(mTwoPowerN + 1),
  47. mSizeSqr(mSize * mSize),
  48. mInputVoxels(inputVoxels),
  49. mLevel((Real)0),
  50. mFixBoundary(fixBoundary),
  51. mXMerge(mSize, mSize),
  52. mYMerge(mSize, mSize),
  53. mZMerge(mSize, mSize)
  54. {
  55. static_assert(std::is_integral<T>::value && sizeof(T) <= 4,
  56. "Type T must be int{8,16,32}_t or uint{8,16,32}_t.");
  57. if (N <= 0 || mInputVoxels == nullptr)
  58. {
  59. LogError("Invalid input.");
  60. }
  61. for (int i = 0; i < mSize; ++i)
  62. {
  63. for (int j = 0; j < mSize; ++j)
  64. {
  65. mXMerge[i][j] = std::make_shared<LinearMergeTree>(N);
  66. mYMerge[i][j] = std::make_shared<LinearMergeTree>(N);
  67. mZMerge[i][j] = std::make_shared<LinearMergeTree>(N);
  68. }
  69. }
  70. }
  71. // TODO: Refactor this class to have base class SurfaceExtractor.
  72. typedef std::array<Real, 3> Vertex;
  73. typedef std::array<int, 2> Edge;
  74. typedef TriangleKey<true> Triangle;
  75. void Extract(Real level, int depth,
  76. std::vector<Vertex>& vertices, std::vector<Triangle>& triangles)
  77. {
  78. std::vector<Vertex> localVertices;
  79. std::vector<Triangle> localTriangles;
  80. mBoxes.clear();
  81. mLevel = level;
  82. Merge(depth);
  83. Tessellate(localVertices, localTriangles);
  84. vertices = std::move(localVertices);
  85. triangles = std::move(localTriangles);
  86. }
  87. void MakeUnique(std::vector<Vertex>& vertices,
  88. std::vector<Triangle>& triangles)
  89. {
  90. size_t numVertices = vertices.size();
  91. size_t numTriangles = triangles.size();
  92. if (numVertices == 0 || numTriangles == 0)
  93. {
  94. return;
  95. }
  96. // Compute the map of unique vertices and assign to them new and
  97. // unique indices.
  98. std::map<Vertex, int> vmap;
  99. int nextVertex = 0;
  100. for (size_t v = 0; v < numVertices; ++v)
  101. {
  102. // Keep only unique vertices.
  103. auto result = vmap.insert(std::make_pair(vertices[v], nextVertex));
  104. if (result.second)
  105. {
  106. ++nextVertex;
  107. }
  108. }
  109. // Compute the map of unique triangles and assign to them new and
  110. // unique indices.
  111. std::map<Triangle, int> tmap;
  112. int nextTriangle = 0;
  113. for (size_t t = 0; t < numTriangles; ++t)
  114. {
  115. Triangle& triangle = triangles[t];
  116. for (int i = 0; i < 3; ++i)
  117. {
  118. auto iter = vmap.find(vertices[triangle.V[i]]);
  119. LogAssert(iter != vmap.end(), "Expecting the vertex to be in the vmap.");
  120. triangle.V[i] = iter->second;
  121. }
  122. // Keep only unique triangles.
  123. auto result = tmap.insert(std::make_pair(triangle, nextTriangle));
  124. if (result.second)
  125. {
  126. ++nextTriangle;
  127. }
  128. }
  129. // Pack the vertices into an array.
  130. vertices.resize(vmap.size());
  131. for (auto const& element : vmap)
  132. {
  133. vertices[element.second] = element.first;
  134. }
  135. // Pack the triangles into an array.
  136. triangles.resize(tmap.size());
  137. for (auto const& element : tmap)
  138. {
  139. triangles[element.second] = element.first;
  140. }
  141. }
  142. void OrientTriangles(std::vector<Vertex>& vertices,
  143. std::vector<Triangle>& triangles, bool sameDir)
  144. {
  145. for (auto& triangle : triangles)
  146. {
  147. // Get the triangle vertices.
  148. std::array<Real, 3> v0 = vertices[triangle.V[0]];
  149. std::array<Real, 3> v1 = vertices[triangle.V[1]];
  150. std::array<Real, 3> v2 = vertices[triangle.V[2]];
  151. // Construct the triangle normal based on the current
  152. // orientation.
  153. std::array<Real, 3> edge1, edge2, normal;
  154. for (int i = 0; i < 3; ++i)
  155. {
  156. edge1[i] = v1[i] - v0[i];
  157. edge2[i] = v2[i] - v0[i];
  158. }
  159. normal[0] = edge1[1] * edge2[2] - edge1[2] * edge2[1];
  160. normal[1] = edge1[2] * edge2[0] - edge1[0] * edge2[2];
  161. normal[2] = edge1[0] * edge2[1] - edge1[1] * edge2[0];
  162. // Get the image gradient at the vertices.
  163. std::array<Real, 3> grad0 = GetGradient(v0);
  164. std::array<Real, 3> grad1 = GetGradient(v1);
  165. std::array<Real, 3> grad2 = GetGradient(v2);
  166. // Compute the average gradient.
  167. std::array<Real, 3> gradAvr;
  168. for (int i = 0; i < 3; ++i)
  169. {
  170. gradAvr[i] = (grad0[i] + grad1[i] + grad2[i]) / (Real)3;
  171. }
  172. // Compute the dot product of normal and average gradient.
  173. Real dot = gradAvr[0] * normal[0] + gradAvr[1] * normal[1] + gradAvr[2] * normal[2];
  174. // Choose triangle orientation based on gradient direction.
  175. if (sameDir)
  176. {
  177. if (dot < (Real)0)
  178. {
  179. // Wrong orientation, reorder it.
  180. std::swap(triangle.V[1], triangle.V[2]);
  181. }
  182. }
  183. else
  184. {
  185. if (dot > (Real)0)
  186. {
  187. // Wrong orientation, reorder it.
  188. std::swap(triangle.V[1], triangle.V[2]);
  189. }
  190. }
  191. }
  192. }
  193. void ComputeNormals(std::vector<Vertex> const& vertices,
  194. std::vector<Triangle> const& triangles,
  195. std::vector<std::array<Real, 3>>& normals)
  196. {
  197. // Compute a vertex normal to be area-weighted sums of the normals
  198. // to the triangles that share that vertex.
  199. std::array<Real, 3> const zero{ (Real)0, (Real)0, (Real)0 };
  200. normals.resize(vertices.size());
  201. std::fill(normals.begin(), normals.end(), zero);
  202. for (auto const& triangle : triangles)
  203. {
  204. // Get the triangle vertices.
  205. std::array<Real, 3> v0 = vertices[triangle.V[0]];
  206. std::array<Real, 3> v1 = vertices[triangle.V[1]];
  207. std::array<Real, 3> v2 = vertices[triangle.V[2]];
  208. // Construct the triangle normal.
  209. std::array<Real, 3> edge1, edge2, normal;
  210. for (int i = 0; i < 3; ++i)
  211. {
  212. edge1[i] = v1[i] - v0[i];
  213. edge2[i] = v2[i] - v0[i];
  214. }
  215. normal[0] = edge1[1] * edge2[2] - edge1[2] * edge2[1];
  216. normal[1] = edge1[2] * edge2[0] - edge1[0] * edge2[2];
  217. normal[2] = edge1[0] * edge2[1] - edge1[1] * edge2[0];
  218. // Maintain the sum of normals at each vertex.
  219. for (int i = 0; i < 3; ++i)
  220. {
  221. for (int j = 0; j < 3; ++j)
  222. {
  223. normals[triangle.V[i]][j] += normal[j];
  224. }
  225. }
  226. }
  227. // The normal vector storage was used to accumulate the sum of
  228. // triangle normals. Now these vectors must be rescaled to be
  229. // unit length.
  230. for (auto& normal : normals)
  231. {
  232. Real sqrLength = normal[0] * normal[0] + normal[1] * normal[1] + normal[2] * normal[2];
  233. Real length = std::sqrt(sqrLength);
  234. if (length > (Real)0)
  235. {
  236. for (int i = 0; i < 3; ++i)
  237. {
  238. normal[i] /= length;
  239. }
  240. }
  241. else
  242. {
  243. for (int i = 0; i < 3; ++i)
  244. {
  245. normal[i] = (Real)0;
  246. }
  247. }
  248. }
  249. }
  250. // Support for debugging.
  251. void PrintBoxes(std::ostream& output)
  252. {
  253. output << mBoxes.size() << std::endl;
  254. for (size_t i = 0; i < mBoxes.size(); ++i)
  255. {
  256. OctBox const& box = mBoxes[i];
  257. output << "box " << i << ": ";
  258. output << "x0 = " << box.x0 << ", ";
  259. output << "y0 = " << box.y0 << ", ";
  260. output << "z0 = " << box.z0 << ", ";
  261. output << "dx = " << box.dx << ", ";
  262. output << "dy = " << box.dy << ", ";
  263. output << "dz = " << box.dz << std::endl;
  264. }
  265. }
  266. private:
  267. // Helper classes for the skeleton climbing.
  268. struct OctBox
  269. {
  270. OctBox(int inX0, int inY0, int inZ0, int inDX, int inDY, int inDZ,
  271. int inLX, int inLY, int inLZ)
  272. :
  273. x0(inX0), y0(inY0), z0(inZ0),
  274. x1(inX0 + inDX), y1(inY0 + inDY), z1(inZ0 + inDZ),
  275. dx(inDX), dy(inDY), dz(inDZ),
  276. LX(inLX), LY(inLY), LZ(inLZ)
  277. {
  278. }
  279. int x0, y0, z0, x1, y1, z1, dx, dy, dz, LX, LY, LZ;
  280. };
  281. struct MergeBox
  282. {
  283. MergeBox(int stride)
  284. :
  285. xStride(stride), yStride(stride), zStride(stride),
  286. valid(true)
  287. {
  288. }
  289. int xStride, yStride, zStride;
  290. bool valid;
  291. };
  292. class LinearMergeTree
  293. {
  294. public:
  295. LinearMergeTree(int N)
  296. :
  297. mTwoPowerN(1 << N),
  298. mNodes(2 * mTwoPowerN - 1),
  299. mZeroBases(2 * mTwoPowerN - 1)
  300. {
  301. }
  302. enum
  303. {
  304. CFG_NONE = 0,
  305. CFG_INCR = 1,
  306. CFG_DECR = 2,
  307. CFG_MULT = 3,
  308. CFG_ROOT_MASK = 3,
  309. CFG_EDGE = 4,
  310. CFG_ZERO_SUBEDGE = 8
  311. };
  312. bool IsNone(int i) const
  313. {
  314. return (mNodes[i] & CFG_ROOT_MASK) == CFG_NONE;
  315. }
  316. int GetRootType(int i) const
  317. {
  318. return mNodes[i] & CFG_ROOT_MASK;
  319. }
  320. int GetZeroBase(int i) const
  321. {
  322. return mZeroBases[i];
  323. }
  324. void SetEdge(int i)
  325. {
  326. mNodes[i] |= CFG_EDGE;
  327. // Inform all predecessors whether they have a zero subedge.
  328. if (mZeroBases[i] >= 0)
  329. {
  330. while (i > 0)
  331. {
  332. i = (i - 1) / 2;
  333. mNodes[i] |= CFG_ZERO_SUBEDGE;
  334. }
  335. }
  336. }
  337. bool IsZeroEdge(int i) const
  338. {
  339. return mNodes[i] == (CFG_EDGE | CFG_INCR)
  340. || mNodes[i] == (CFG_EDGE | CFG_DECR);
  341. }
  342. bool HasZeroSubedge(int i) const
  343. {
  344. return (mNodes[i] & CFG_ZERO_SUBEDGE) != 0;
  345. }
  346. void SetLevel(Real level, T const* data, int offset, int stride)
  347. {
  348. // Assert: The 'level' is not an image value. Because T is
  349. // an integer type, choose 'level' to be a Real-valued number
  350. // that does not represent an integer.
  351. // Determine the sign changes between pairs of consecutive
  352. // samples.
  353. int firstLeaf = mTwoPowerN - 1;
  354. for (int i = 0, leaf = firstLeaf; i < mTwoPowerN; ++i, ++leaf)
  355. {
  356. int base = offset + stride * i;
  357. Real value0 = static_cast<Real>(data[base]);
  358. Real value1 = static_cast<Real>(data[base + stride]);
  359. if (value0 > level)
  360. {
  361. if (value1 > level)
  362. {
  363. mNodes[leaf] = CFG_NONE;
  364. mZeroBases[leaf] = -1;
  365. }
  366. else
  367. {
  368. mNodes[leaf] = CFG_DECR;
  369. mZeroBases[leaf] = i;
  370. }
  371. }
  372. else // value0 < level
  373. {
  374. if (value1 > level)
  375. {
  376. mNodes[leaf] = CFG_INCR;
  377. mZeroBases[leaf] = i;
  378. }
  379. else
  380. {
  381. mNodes[leaf] = CFG_NONE;
  382. mZeroBases[leaf] = -1;
  383. }
  384. }
  385. }
  386. // Propagate the sign change information up the binary tree.
  387. for (int i = firstLeaf - 1; i >= 0; --i)
  388. {
  389. int twoIp1 = 2 * i + 1, twoIp2 = twoIp1 + 1;
  390. int value0 = mNodes[twoIp1];
  391. int value1 = mNodes[twoIp2];
  392. int combine = (value0 | value1);
  393. mNodes[i] = combine;
  394. if (combine == CFG_INCR)
  395. {
  396. if (value0 == CFG_INCR)
  397. {
  398. mZeroBases[i] = mZeroBases[twoIp1];
  399. }
  400. else
  401. {
  402. mZeroBases[i] = mZeroBases[twoIp2];
  403. }
  404. }
  405. else if (combine == CFG_DECR)
  406. {
  407. if (value0 == CFG_DECR)
  408. {
  409. mZeroBases[i] = mZeroBases[twoIp1];
  410. }
  411. else
  412. {
  413. mZeroBases[i] = mZeroBases[twoIp2];
  414. }
  415. }
  416. else
  417. {
  418. mZeroBases[i] = -1;
  419. }
  420. }
  421. }
  422. private:
  423. int mTwoPowerN;
  424. std::vector<int> mNodes;
  425. std::vector<int> mZeroBases;
  426. };
  427. class VETable
  428. {
  429. public:
  430. VETable()
  431. :
  432. mVertices(18)
  433. {
  434. }
  435. bool IsValidVertex(int i) const
  436. {
  437. return mVertices[i].valid;
  438. }
  439. int GetNumVertices() const
  440. {
  441. return static_cast<int>(mVertices.size());
  442. }
  443. Vertex const& GetVertex(int i) const
  444. {
  445. return mVertices[i].position;
  446. }
  447. void Insert(int i, Real x, Real y, Real z)
  448. {
  449. TVertex& vertex = mVertices[i];
  450. vertex.position = Vertex{ x, y, z };
  451. vertex.valid = true;
  452. }
  453. void Insert(Vertex const& position)
  454. {
  455. mVertices.push_back(TVertex(position));
  456. }
  457. void InsertEdge(int v0, int v1)
  458. {
  459. TVertex& vertex0 = mVertices[v0];
  460. TVertex& vertex1 = mVertices[v1];
  461. vertex0.adjacent[vertex0.adjQuantity] = v1;
  462. ++vertex0.adjQuantity;
  463. vertex1.adjacent[vertex1.adjQuantity] = v0;
  464. ++vertex1.adjQuantity;
  465. }
  466. void RemoveTrianglesEC(std::vector<Vertex>& positions,
  467. std::vector<Triangle>& triangles)
  468. {
  469. // Ear-clip the wireframe to get the triangles.
  470. Triangle triangle;
  471. while (RemoveEC(triangle))
  472. {
  473. int v0 = static_cast<int>(positions.size());
  474. int v1 = v0 + 1;
  475. int v2 = v1 + 1;
  476. triangles.push_back(Triangle(v0, v1, v2));
  477. positions.push_back(mVertices[triangle.V[0]].position);
  478. positions.push_back(mVertices[triangle.V[1]].position);
  479. positions.push_back(mVertices[triangle.V[2]].position);
  480. }
  481. }
  482. void RemoveTrianglesSE(std::vector<Vertex>& positions,
  483. std::vector<Triangle>& triangles)
  484. {
  485. // Compute centroid of vertices.
  486. Vertex centroid = { (Real)0, (Real)0, (Real)0 };
  487. int const vmax = static_cast<int>(mVertices.size());
  488. int i, j, quantity = 0;
  489. for (i = 0; i < vmax; i++)
  490. {
  491. TVertex const& vertex = mVertices[i];
  492. if (vertex.valid)
  493. {
  494. for (j = 0; j < 3; ++j)
  495. {
  496. centroid[j] += vertex.position[j];
  497. }
  498. ++quantity;
  499. }
  500. }
  501. for (j = 0; j < 3; ++j)
  502. {
  503. centroid[j] /= static_cast<Real>(quantity);
  504. }
  505. int v0 = static_cast<int>(positions.size());
  506. positions.push_back(centroid);
  507. int i1 = 18;
  508. int v1 = v0 + 1;
  509. positions.push_back(mVertices[i1].position);
  510. int i2 = mVertices[i1].adjacent[1], v2;
  511. for (i = 0; i < quantity - 1; ++i)
  512. {
  513. v2 = v1 + 1;
  514. positions.push_back(mVertices[i2].position);
  515. triangles.push_back(Triangle(v0, v1, v2));
  516. if (mVertices[i2].adjacent[1] != i1)
  517. {
  518. i1 = i2;
  519. i2 = mVertices[i2].adjacent[1];
  520. }
  521. else
  522. {
  523. i1 = i2;
  524. i2 = mVertices[i2].adjacent[0];
  525. }
  526. v1 = v2;
  527. }
  528. v2 = v0 + 1;
  529. triangles.push_back(Triangle(v0, v1, v2));
  530. }
  531. protected:
  532. void RemoveVertex(int i)
  533. {
  534. TVertex& vertex0 = mVertices[i];
  535. int a0 = vertex0.adjacent[0];
  536. int a1 = vertex0.adjacent[1];
  537. TVertex& adjVertex0 = mVertices[a0];
  538. TVertex& adjVertex1 = mVertices[a1];
  539. int j;
  540. for (j = 0; j < adjVertex0.adjQuantity; j++)
  541. {
  542. if (adjVertex0.adjacent[j] == i)
  543. {
  544. adjVertex0.adjacent[j] = a1;
  545. break;
  546. }
  547. }
  548. for (j = 0; j < adjVertex1.adjQuantity; j++)
  549. {
  550. if (adjVertex1.adjacent[j] == i)
  551. {
  552. adjVertex1.adjacent[j] = a0;
  553. break;
  554. }
  555. }
  556. vertex0.valid = false;
  557. if (adjVertex0.adjQuantity == 2)
  558. {
  559. if (adjVertex0.adjacent[0] == adjVertex0.adjacent[1])
  560. {
  561. adjVertex0.valid = false;
  562. }
  563. }
  564. if (adjVertex1.adjQuantity == 2)
  565. {
  566. if (adjVertex1.adjacent[0] == adjVertex1.adjacent[1])
  567. {
  568. adjVertex1.valid = false;
  569. }
  570. }
  571. }
  572. // ear clipping
  573. bool RemoveEC(Triangle& triangle)
  574. {
  575. int numVertices = static_cast<int>(mVertices.size());
  576. for (int i = 0; i < numVertices; ++i)
  577. {
  578. TVertex const& vertex = mVertices[i];
  579. if (vertex.valid && vertex.adjQuantity == 2)
  580. {
  581. triangle.V[0] = i;
  582. triangle.V[1] = vertex.adjacent[0];
  583. triangle.V[2] = vertex.adjacent[1];
  584. RemoveVertex(i);
  585. return true;
  586. }
  587. }
  588. return false;
  589. }
  590. class TVertex
  591. {
  592. public:
  593. TVertex()
  594. :
  595. adjQuantity(0),
  596. valid(false)
  597. {
  598. }
  599. TVertex(Vertex const& inPosition)
  600. :
  601. position(inPosition),
  602. adjQuantity(0),
  603. valid(true)
  604. {
  605. }
  606. Vertex position;
  607. int adjQuantity;
  608. std::array<int, 4> adjacent;
  609. bool valid;
  610. };
  611. std::vector<TVertex> mVertices;
  612. };
  613. private:
  614. // Support for merging monoboxes.
  615. void Merge(int depth)
  616. {
  617. int x, y, z, offset, stride;
  618. for (y = 0; y < mSize; ++y)
  619. {
  620. for (z = 0; z < mSize; ++z)
  621. {
  622. offset = mSize * (y + mSize * z);
  623. stride = 1;
  624. mXMerge[y][z]->SetLevel(mLevel, mInputVoxels, offset, stride);
  625. }
  626. }
  627. for (x = 0; x < mSize; ++x)
  628. {
  629. for (z = 0; z < mSize; ++z)
  630. {
  631. offset = x + mSizeSqr * z;
  632. stride = mSize;
  633. mYMerge[x][z]->SetLevel(mLevel, mInputVoxels, offset, stride);
  634. }
  635. }
  636. for (x = 0; x < mSize; ++x)
  637. {
  638. for (y = 0; y < mSize; ++y)
  639. {
  640. offset = x + mSize * y;
  641. stride = mSizeSqr;
  642. mZMerge[x][y]->SetLevel(mLevel, mInputVoxels, offset, stride);
  643. }
  644. }
  645. Merge(0, 0, 0, 0, 0, 0, 0, mTwoPowerN, depth);
  646. }
  647. bool Merge(int v, int LX, int LY, int LZ, int x0, int y0, int z0, int stride, int depth)
  648. {
  649. if (stride > 1) // internal nodes
  650. {
  651. int hStride = stride / 2;
  652. int vBase = 8 * v;
  653. int v000 = vBase + 1;
  654. int v100 = vBase + 2;
  655. int v010 = vBase + 3;
  656. int v110 = vBase + 4;
  657. int v001 = vBase + 5;
  658. int v101 = vBase + 6;
  659. int v011 = vBase + 7;
  660. int v111 = vBase + 8;
  661. int LX0 = 2 * LX + 1, LX1 = LX0 + 1;
  662. int LY0 = 2 * LY + 1, LY1 = LY0 + 1;
  663. int LZ0 = 2 * LZ + 1, LZ1 = LZ0 + 1;
  664. int x1 = x0 + hStride, y1 = y0 + hStride, z1 = z0 + hStride;
  665. int dm1 = depth - 1;
  666. bool m000 = Merge(v000, LX0, LY0, LZ0, x0, y0, z0, hStride, dm1);
  667. bool m100 = Merge(v100, LX1, LY0, LZ0, x1, y0, z0, hStride, dm1);
  668. bool m010 = Merge(v010, LX0, LY1, LZ0, x0, y1, z0, hStride, dm1);
  669. bool m110 = Merge(v110, LX1, LY1, LZ0, x1, y1, z0, hStride, dm1);
  670. bool m001 = Merge(v001, LX0, LY0, LZ1, x0, y0, z1, hStride, dm1);
  671. bool m101 = Merge(v101, LX1, LY0, LZ1, x1, y0, z1, hStride, dm1);
  672. bool m011 = Merge(v011, LX0, LY1, LZ1, x0, y1, z1, hStride, dm1);
  673. bool m111 = Merge(v111, LX1, LY1, LZ1, x1, y1, z1, hStride, dm1);
  674. MergeBox r000(hStride), r100(hStride), r010(hStride), r110(hStride);
  675. MergeBox r001(hStride), r101(hStride), r011(hStride), r111(hStride);
  676. if (depth <= 0)
  677. {
  678. if (m000 && m001)
  679. {
  680. DoZMerge(r000, r001, x0, y0, LZ);
  681. }
  682. if (m100 && m101)
  683. {
  684. DoZMerge(r100, r101, x1, y0, LZ);
  685. }
  686. if (m010 && m011)
  687. {
  688. DoZMerge(r010, r011, x0, y1, LZ);
  689. }
  690. if (m110 && m111)
  691. {
  692. DoZMerge(r110, r111, x1, y1, LZ);
  693. }
  694. if (m000 && m010)
  695. {
  696. DoYMerge(r000, r010, x0, LY, z0);
  697. }
  698. if (m100 && m110)
  699. {
  700. DoYMerge(r100, r110, x1, LY, z0);
  701. }
  702. if (m001 && m011)
  703. {
  704. DoYMerge(r001, r011, x0, LY, z1);
  705. }
  706. if (m101 && m111)
  707. {
  708. DoYMerge(r101, r111, x1, LY, z1);
  709. }
  710. if (m000 && m100)
  711. {
  712. DoXMerge(r000, r100, LX, y0, z0);
  713. }
  714. if (m010 && m110)
  715. {
  716. DoXMerge(r010, r110, LX, y1, z0);
  717. }
  718. if (m001 && m101)
  719. {
  720. DoXMerge(r001, r101, LX, y0, z1);
  721. }
  722. if (m011 && m111)
  723. {
  724. DoXMerge(r011, r111, LX, y1, z1);
  725. }
  726. }
  727. if (depth <= 1)
  728. {
  729. if (r000.valid)
  730. {
  731. if (r000.xStride == stride)
  732. {
  733. if (r000.yStride == stride)
  734. {
  735. if (r000.zStride == stride)
  736. {
  737. return true;
  738. }
  739. else
  740. {
  741. AddBox(x0, y0, z0, stride, stride, hStride, LX, LY, LZ0);
  742. }
  743. }
  744. else
  745. {
  746. if (r000.zStride == stride)
  747. {
  748. AddBox(x0, y0, z0, stride, hStride, stride, LX, LY0, LZ);
  749. }
  750. else
  751. {
  752. AddBox(x0, y0, z0, stride, hStride, hStride, LX, LY0, LZ0);
  753. }
  754. }
  755. }
  756. else
  757. {
  758. if (r000.yStride == stride)
  759. {
  760. if (r000.zStride == stride)
  761. {
  762. AddBox(x0, y0, z0, hStride, stride, stride, LX0, LY, LZ);
  763. }
  764. else
  765. {
  766. AddBox(x0, y0, z0, hStride, stride, hStride, LX0, LY, LZ0);
  767. }
  768. }
  769. else
  770. {
  771. if (r000.zStride == stride)
  772. {
  773. AddBox(x0, y0, z0, hStride, hStride, stride, LX0, LY0, LZ);
  774. }
  775. else if (m000)
  776. {
  777. AddBox(x0, y0, z0, hStride, hStride, hStride, LX0, LY0, LZ0);
  778. }
  779. }
  780. }
  781. }
  782. if (r100.valid)
  783. {
  784. if (r100.yStride == stride)
  785. {
  786. if (r100.zStride == stride)
  787. {
  788. AddBox(x1, y0, z0, hStride, stride, stride, LX1, LY, LZ);
  789. }
  790. else
  791. {
  792. AddBox(x1, y0, z0, hStride, stride, hStride, LX1, LY, LZ0);
  793. }
  794. }
  795. else
  796. {
  797. if (r100.zStride == stride)
  798. {
  799. AddBox(x1, y0, z0, hStride, hStride, stride, LX1, LY0, LZ);
  800. }
  801. else if (m100)
  802. {
  803. AddBox(x1, y0, z0, hStride, hStride, hStride, LX1, LY0, LZ0);
  804. }
  805. }
  806. }
  807. if (r010.valid)
  808. {
  809. if (r010.xStride == stride)
  810. {
  811. if (r010.zStride == stride)
  812. {
  813. AddBox(x0, y1, z0, stride, hStride, stride, LX, LY1, LZ);
  814. }
  815. else
  816. {
  817. AddBox(x0, y1, z0, stride, hStride, hStride, LX, LY1, LZ0);
  818. }
  819. }
  820. else
  821. {
  822. if (r010.zStride == stride)
  823. {
  824. AddBox(x0, y1, z0, hStride, hStride, stride, LX0, LY1, LZ);
  825. }
  826. else if (m010)
  827. {
  828. AddBox(x0, y1, z0, hStride, hStride, hStride, LX0, LY1, LZ0);
  829. }
  830. }
  831. }
  832. if (r001.valid)
  833. {
  834. if (r001.xStride == stride)
  835. {
  836. if (r001.yStride == stride)
  837. {
  838. AddBox(x0, y0, z1, stride, stride, hStride, LX, LY, LZ1);
  839. }
  840. else
  841. {
  842. AddBox(x0, y0, z1, stride, hStride, hStride, LX, LY0, LZ1);
  843. }
  844. }
  845. else
  846. {
  847. if (r001.yStride == stride)
  848. {
  849. AddBox(x0, y0, z1, hStride, stride, hStride, LX0, LY, LZ1);
  850. }
  851. else if (m001)
  852. {
  853. AddBox(x0, y0, z1, hStride, hStride, hStride, LX0, LY0, LZ1);
  854. }
  855. }
  856. }
  857. if (r110.valid)
  858. {
  859. if (r110.zStride == stride)
  860. {
  861. AddBox(x1, y1, z0, hStride, hStride, stride, LX1, LY1, LZ);
  862. }
  863. else if (m110)
  864. {
  865. AddBox(x1, y1, z0, hStride, hStride, hStride, LX1, LY1, LZ0);
  866. }
  867. }
  868. if (r101.valid)
  869. {
  870. if (r101.yStride == stride)
  871. {
  872. AddBox(x1, y0, z1, hStride, stride, hStride, LX1, LY, LZ1);
  873. }
  874. else if (m101)
  875. {
  876. AddBox(x1, y0, z1, hStride, hStride, hStride, LX1, LY0, LZ1);
  877. }
  878. }
  879. if (r011.valid)
  880. {
  881. if (r011.xStride == stride)
  882. {
  883. AddBox(x0, y1, z1, stride, hStride, hStride, LX, LY1, LZ1);
  884. }
  885. else if (m011)
  886. {
  887. AddBox(x0, y1, z1, hStride, hStride, hStride, LX0, LY1, LZ1);
  888. }
  889. }
  890. if (r111.valid && m111)
  891. {
  892. AddBox(x1, y1, z1, hStride, hStride, hStride, LX1, LY1, LZ1);
  893. }
  894. }
  895. return false;
  896. }
  897. else // leaf nodes
  898. {
  899. if (mFixBoundary)
  900. {
  901. // Do not allow boundary voxels to merge with any other
  902. // voxels.
  903. AddBox(x0, y0, z0, 1, 1, 1, LX, LY, LZ);
  904. return false;
  905. }
  906. // A leaf box is mergeable with neighbors as long as all its
  907. // faces have 0 or 2 sign changes on the edges. That is, a
  908. // face may not have sign changes on all four edges. If it
  909. // does, the resulting box for tessellating is 1x1x1 and is
  910. // handled separately from boxes of larger dimensions.
  911. // xmin face
  912. int z1 = z0 + 1;
  913. int rt0 = mYMerge[x0][z0]->GetRootType(LY);
  914. int rt1 = mYMerge[x0][z1]->GetRootType(LY);
  915. if ((rt0 | rt1) == LinearMergeTree::CFG_MULT)
  916. {
  917. AddBox(x0, y0, z0, 1, 1, 1, LX, LY, LZ);
  918. return false;
  919. }
  920. // xmax face
  921. int x1 = x0 + 1;
  922. rt0 = mYMerge[x1][z0]->GetRootType(LY);
  923. rt1 = mYMerge[x1][z1]->GetRootType(LY);
  924. if ((rt0 | rt1) == LinearMergeTree::CFG_MULT)
  925. {
  926. AddBox(x0, y0, z0, 1, 1, 1, LX, LY, LZ);
  927. return false;
  928. }
  929. // ymin face
  930. rt0 = mZMerge[x0][y0]->GetRootType(LZ);
  931. rt1 = mZMerge[x1][y0]->GetRootType(LZ);
  932. if ((rt0 | rt1) == LinearMergeTree::CFG_MULT)
  933. {
  934. AddBox(x0, y0, z0, 1, 1, 1, LX, LY, LZ);
  935. return false;
  936. }
  937. // ymax face
  938. int y1 = y0 + 1;
  939. rt0 = mZMerge[x0][y1]->GetRootType(LZ);
  940. rt1 = mZMerge[x1][y1]->GetRootType(LZ);
  941. if ((rt0 | rt1) == LinearMergeTree::CFG_MULT)
  942. {
  943. AddBox(x0, y0, z0, 1, 1, 1, LX, LY, LZ);
  944. return false;
  945. }
  946. // zmin face
  947. rt0 = mXMerge[y0][z0]->GetRootType(LX);
  948. rt1 = mXMerge[y1][z0]->GetRootType(LX);
  949. if ((rt0 | rt1) == LinearMergeTree::CFG_MULT)
  950. {
  951. AddBox(x0, y0, z0, 1, 1, 1, LX, LY, LZ);
  952. return false;
  953. }
  954. // zmax face
  955. rt0 = mXMerge[y0][z1]->GetRootType(LX);
  956. rt1 = mXMerge[y1][z1]->GetRootType(LX);
  957. if ((rt0 | rt1) == LinearMergeTree::CFG_MULT)
  958. {
  959. AddBox(x0, y0, z0, 1, 1, 1, LX, LY, LZ);
  960. return false;
  961. }
  962. return true;
  963. }
  964. }
  965. bool DoXMerge(MergeBox& r0, MergeBox& r1, int LX, int y0, int z0)
  966. {
  967. if (!r0.valid || !r1.valid || r0.yStride != r1.yStride || r0.zStride != r1.zStride)
  968. {
  969. return false;
  970. }
  971. // Boxes are potentially x-mergeable.
  972. int y1 = y0 + r0.yStride, z1 = z0 + r0.zStride;
  973. int incr = 0, decr = 0;
  974. for (int y = y0; y <= y1; ++y)
  975. {
  976. for (int z = z0; z <= z1; ++z)
  977. {
  978. switch (mXMerge[y][z]->GetRootType(LX))
  979. {
  980. case LinearMergeTree::CFG_MULT:
  981. return false;
  982. case LinearMergeTree::CFG_INCR:
  983. ++incr;
  984. break;
  985. case LinearMergeTree::CFG_DECR:
  986. ++decr;
  987. break;
  988. }
  989. }
  990. }
  991. if (incr != 0 && decr != 0)
  992. {
  993. return false;
  994. }
  995. // Strongly mono, x-merge the boxes.
  996. r0.xStride *= 2;
  997. r1.valid = false;
  998. return true;
  999. }
  1000. bool DoYMerge(MergeBox& r0, MergeBox& r1, int x0, int LY, int z0)
  1001. {
  1002. if (!r0.valid || !r1.valid || r0.xStride != r1.xStride || r0.zStride != r1.zStride)
  1003. {
  1004. return false;
  1005. }
  1006. // Boxes are potentially y-mergeable.
  1007. int x1 = x0 + r0.xStride, z1 = z0 + r0.zStride;
  1008. int incr = 0, decr = 0;
  1009. for (int x = x0; x <= x1; ++x)
  1010. {
  1011. for (int z = z0; z <= z1; ++z)
  1012. {
  1013. switch (mYMerge[x][z]->GetRootType(LY))
  1014. {
  1015. case LinearMergeTree::CFG_MULT:
  1016. return false;
  1017. case LinearMergeTree::CFG_INCR:
  1018. ++incr;
  1019. break;
  1020. case LinearMergeTree::CFG_DECR:
  1021. ++decr;
  1022. break;
  1023. }
  1024. }
  1025. }
  1026. if (incr != 0 && decr != 0)
  1027. {
  1028. return false;
  1029. }
  1030. // Strongly mono, y-merge the boxes.
  1031. r0.yStride *= 2;
  1032. r1.valid = false;
  1033. return true;
  1034. }
  1035. bool DoZMerge(MergeBox& r0, MergeBox& r1, int x0, int y0, int LZ)
  1036. {
  1037. if (!r0.valid || !r1.valid || r0.xStride != r1.xStride || r0.yStride != r1.yStride)
  1038. {
  1039. return false;
  1040. }
  1041. // Boxes are potentially z-mergeable.
  1042. int x1 = x0 + r0.xStride, y1 = y0 + r0.yStride;
  1043. int incr = 0, decr = 0;
  1044. for (int x = x0; x <= x1; ++x)
  1045. {
  1046. for (int y = y0; y <= y1; ++y)
  1047. {
  1048. switch (mZMerge[x][y]->GetRootType(LZ))
  1049. {
  1050. case LinearMergeTree::CFG_MULT:
  1051. return false;
  1052. case LinearMergeTree::CFG_INCR:
  1053. ++incr;
  1054. break;
  1055. case LinearMergeTree::CFG_DECR:
  1056. ++decr;
  1057. break;
  1058. }
  1059. }
  1060. }
  1061. if (incr != 0 && decr != 0)
  1062. {
  1063. return false;
  1064. }
  1065. // Strongly mono, z-merge the boxes.
  1066. r0.zStride *= 2;
  1067. r1.valid = false;
  1068. return true;
  1069. }
  1070. void AddBox(int x0, int y0, int z0, int dx, int dy, int dz, int LX, int LY, int LZ)
  1071. {
  1072. OctBox box(x0, y0, z0, dx, dy, dz, LX, LY, LZ);
  1073. mBoxes.push_back(box);
  1074. // Mark box edges in linear merge trees. This information will be
  1075. // used later for extraction.
  1076. mXMerge[box.y0][box.z0]->SetEdge(box.LX);
  1077. mXMerge[box.y0][box.z1]->SetEdge(box.LX);
  1078. mXMerge[box.y1][box.z0]->SetEdge(box.LX);
  1079. mXMerge[box.y1][box.z1]->SetEdge(box.LX);
  1080. mYMerge[box.x0][box.z0]->SetEdge(box.LY);
  1081. mYMerge[box.x0][box.z1]->SetEdge(box.LY);
  1082. mYMerge[box.x1][box.z0]->SetEdge(box.LY);
  1083. mYMerge[box.x1][box.z1]->SetEdge(box.LY);
  1084. mZMerge[box.x0][box.y0]->SetEdge(box.LZ);
  1085. mZMerge[box.x0][box.y1]->SetEdge(box.LZ);
  1086. mZMerge[box.x1][box.y0]->SetEdge(box.LZ);
  1087. mZMerge[box.x1][box.y1]->SetEdge(box.LZ);
  1088. }
  1089. // Support for tessellating monoboxes.
  1090. void Tessellate(std::vector<Vertex>& positions, std::vector<Triangle>& triangles)
  1091. {
  1092. for (size_t i = 0; i < mBoxes.size(); ++i)
  1093. {
  1094. OctBox const& box = mBoxes[i];
  1095. // Get vertices on edges of box.
  1096. VETable table;
  1097. unsigned int type;
  1098. GetVertices(box, type, table);
  1099. if (type == 0)
  1100. {
  1101. continue;
  1102. }
  1103. // Add wireframe edges to table, add face-vertices if
  1104. // necessary.
  1105. if (box.dx > 1 || box.dy > 1 || box.dz > 1)
  1106. {
  1107. // Box is larger than voxel, each face has at most one
  1108. // edge.
  1109. GetXMinEdgesM(box, type, table);
  1110. GetXMaxEdgesM(box, type, table);
  1111. GetYMinEdgesM(box, type, table);
  1112. GetYMaxEdgesM(box, type, table);
  1113. GetZMinEdgesM(box, type, table);
  1114. GetZMaxEdgesM(box, type, table);
  1115. if (table.GetNumVertices() > 18)
  1116. {
  1117. table.RemoveTrianglesSE(positions, triangles);
  1118. }
  1119. else
  1120. {
  1121. table.RemoveTrianglesEC(positions, triangles);
  1122. }
  1123. }
  1124. else
  1125. {
  1126. // The box is a 1x1x1 voxel. Do the full edge analysis
  1127. // but no splitting is required.
  1128. GetXMinEdgesS(box, type, table);
  1129. GetXMaxEdgesS(box, type, table);
  1130. GetYMinEdgesS(box, type, table);
  1131. GetYMaxEdgesS(box, type, table);
  1132. GetZMinEdgesS(box, type, table);
  1133. GetZMaxEdgesS(box, type, table);
  1134. table.RemoveTrianglesEC(positions, triangles);
  1135. }
  1136. }
  1137. }
  1138. Real GetXInterp(int x, int y, int z) const
  1139. {
  1140. int index = x + mSize * (y + mSize * z);
  1141. Real f0 = static_cast<Real>(mInputVoxels[index]);
  1142. ++index;
  1143. Real f1 = static_cast<Real>(mInputVoxels[index]);
  1144. return static_cast<Real>(x) + (mLevel - f0) / (f1 - f0);
  1145. }
  1146. Real GetYInterp(int x, int y, int z) const
  1147. {
  1148. int index = x + mSize * (y + mSize * z);
  1149. Real f0 = static_cast<Real>(mInputVoxels[index]);
  1150. index += mSize;
  1151. Real f1 = static_cast<Real>(mInputVoxels[index]);
  1152. return static_cast<Real>(y) + (mLevel - f0) / (f1 - f0);
  1153. }
  1154. Real GetZInterp(int x, int y, int z) const
  1155. {
  1156. int index = x + mSize * (y + mSize * z);
  1157. Real f0 = static_cast<Real>(mInputVoxels[index]);
  1158. index += mSizeSqr;
  1159. Real f1 = static_cast<Real>(mInputVoxels[index]);
  1160. return static_cast<Real>(z) + (mLevel - f0) / (f1 - f0);
  1161. }
  1162. void GetVertices(OctBox const& box, unsigned int& type, VETable& table)
  1163. {
  1164. int root;
  1165. type = 0;
  1166. // xmin-ymin edge
  1167. root = mZMerge[box.x0][box.y0]->GetZeroBase(box.LZ);
  1168. if (root != -1)
  1169. {
  1170. type |= EB_XMIN_YMIN;
  1171. table.Insert(EI_XMIN_YMIN,
  1172. static_cast<float>(box.x0),
  1173. static_cast<float>(box.y0),
  1174. GetZInterp(box.x0, box.y0, root));
  1175. }
  1176. // xmin-ymax edge
  1177. root = mZMerge[box.x0][box.y1]->GetZeroBase(box.LZ);
  1178. if (root != -1)
  1179. {
  1180. type |= EB_XMIN_YMAX;
  1181. table.Insert(EI_XMIN_YMAX,
  1182. static_cast<float>(box.x0),
  1183. static_cast<float>(box.y1),
  1184. GetZInterp(box.x0, box.y1, root));
  1185. }
  1186. // xmax-ymin edge
  1187. root = mZMerge[box.x1][box.y0]->GetZeroBase(box.LZ);
  1188. if (root != -1)
  1189. {
  1190. type |= EB_XMAX_YMIN;
  1191. table.Insert(EI_XMAX_YMIN,
  1192. static_cast<float>(box.x1),
  1193. static_cast<float>(box.y0),
  1194. GetZInterp(box.x1, box.y0, root));
  1195. }
  1196. // xmax-ymax edge
  1197. root = mZMerge[box.x1][box.y1]->GetZeroBase(box.LZ);
  1198. if (root != -1)
  1199. {
  1200. type |= EB_XMAX_YMAX;
  1201. table.Insert(EI_XMAX_YMAX,
  1202. static_cast<float>(box.x1),
  1203. static_cast<float>(box.y1),
  1204. GetZInterp(box.x1, box.y1, root));
  1205. }
  1206. // xmin-zmin edge
  1207. root = mYMerge[box.x0][box.z0]->GetZeroBase(box.LY);
  1208. if (root != -1)
  1209. {
  1210. type |= EB_XMIN_ZMIN;
  1211. table.Insert(EI_XMIN_ZMIN,
  1212. static_cast<float>(box.x0),
  1213. GetYInterp(box.x0, root, box.z0),
  1214. static_cast<float>(box.z0));
  1215. }
  1216. // xmin-zmax edge
  1217. root = mYMerge[box.x0][box.z1]->GetZeroBase(box.LY);
  1218. if (root != -1)
  1219. {
  1220. type |= EB_XMIN_ZMAX;
  1221. table.Insert(EI_XMIN_ZMAX,
  1222. static_cast<float>(box.x0),
  1223. GetYInterp(box.x0, root, box.z1),
  1224. static_cast<float>(box.z1));
  1225. }
  1226. // xmax-zmin edge
  1227. root = mYMerge[box.x1][box.z0]->GetZeroBase(box.LY);
  1228. if (root != -1)
  1229. {
  1230. type |= EB_XMAX_ZMIN;
  1231. table.Insert(EI_XMAX_ZMIN,
  1232. static_cast<float>(box.x1),
  1233. GetYInterp(box.x1, root, box.z0),
  1234. static_cast<float>(box.z0));
  1235. }
  1236. // xmax-zmax edge
  1237. root = mYMerge[box.x1][box.z1]->GetZeroBase(box.LY);
  1238. if (root != -1)
  1239. {
  1240. type |= EB_XMAX_ZMAX;
  1241. table.Insert(EI_XMAX_ZMAX,
  1242. static_cast<float>(box.x1),
  1243. GetYInterp(box.x1, root, box.z1),
  1244. static_cast<float>(box.z1));
  1245. }
  1246. // ymin-zmin edge
  1247. root = mXMerge[box.y0][box.z0]->GetZeroBase(box.LX);
  1248. if (root != -1)
  1249. {
  1250. type |= EB_YMIN_ZMIN;
  1251. table.Insert(EI_YMIN_ZMIN,
  1252. GetXInterp(root, box.y0, box.z0),
  1253. static_cast<float>(box.y0),
  1254. static_cast<float>(box.z0));
  1255. }
  1256. // ymin-zmax edge
  1257. root = mXMerge[box.y0][box.z1]->GetZeroBase(box.LX);
  1258. if (root != -1)
  1259. {
  1260. type |= EB_YMIN_ZMAX;
  1261. table.Insert(EI_YMIN_ZMAX,
  1262. GetXInterp(root, box.y0, box.z1),
  1263. static_cast<float>(box.y0),
  1264. static_cast<float>(box.z1));
  1265. }
  1266. // ymax-zmin edge
  1267. root = mXMerge[box.y1][box.z0]->GetZeroBase(box.LX);
  1268. if (root != -1)
  1269. {
  1270. type |= EB_YMAX_ZMIN;
  1271. table.Insert(EI_YMAX_ZMIN,
  1272. GetXInterp(root, box.y1, box.z0),
  1273. static_cast<float>(box.y1),
  1274. static_cast<float>(box.z0));
  1275. }
  1276. // ymax-zmax edge
  1277. root = mXMerge[box.y1][box.z1]->GetZeroBase(box.LX);
  1278. if (root != -1)
  1279. {
  1280. type |= EB_YMAX_ZMAX;
  1281. table.Insert(EI_YMAX_ZMAX,
  1282. GetXInterp(root, box.y1, box.z1),
  1283. static_cast<float>(box.y1),
  1284. static_cast<float>(box.z1));
  1285. }
  1286. }
  1287. // Edge extraction for single boxes (1x1x1).
  1288. void GetXMinEdgesS(OctBox const& box, unsigned int type, VETable& table)
  1289. {
  1290. unsigned int faceType = 0;
  1291. if (type & EB_XMIN_YMIN)
  1292. {
  1293. faceType |= 0x01;
  1294. }
  1295. if (type & EB_XMIN_YMAX)
  1296. {
  1297. faceType |= 0x02;
  1298. }
  1299. if (type & EB_XMIN_ZMIN)
  1300. {
  1301. faceType |= 0x04;
  1302. }
  1303. if (type & EB_XMIN_ZMAX)
  1304. {
  1305. faceType |= 0x08;
  1306. }
  1307. switch (faceType)
  1308. {
  1309. case 0:
  1310. return;
  1311. case 3:
  1312. table.InsertEdge(EI_XMIN_YMIN, EI_XMIN_YMAX);
  1313. break;
  1314. case 5:
  1315. table.InsertEdge(EI_XMIN_YMIN, EI_XMIN_ZMIN);
  1316. break;
  1317. case 6:
  1318. table.InsertEdge(EI_XMIN_YMAX, EI_XMIN_ZMIN);
  1319. break;
  1320. case 9:
  1321. table.InsertEdge(EI_XMIN_YMIN, EI_XMIN_ZMAX);
  1322. break;
  1323. case 10:
  1324. table.InsertEdge(EI_XMIN_YMAX, EI_XMIN_ZMAX);
  1325. break;
  1326. case 12:
  1327. table.InsertEdge(EI_XMIN_ZMIN, EI_XMIN_ZMAX);
  1328. break;
  1329. case 15:
  1330. {
  1331. // Four vertices, one per edge, need to disambiguate.
  1332. int i = box.x0 + mSize * (box.y0 + mSize * box.z0);
  1333. // F(x,y,z)
  1334. int64_t f00 = static_cast<int64_t>(mInputVoxels[i]);
  1335. i += mSize;
  1336. // F(x,y+1,z)
  1337. int64_t f10 = static_cast<int64_t>(mInputVoxels[i]);
  1338. i += mSizeSqr;
  1339. // F(x,y+1,z+1)
  1340. int64_t f11 = static_cast<int64_t>(mInputVoxels[i]);
  1341. i -= mSize;
  1342. // F(x,y,z+1)
  1343. int64_t f01 = static_cast<int64_t>(mInputVoxels[i]);
  1344. int64_t det = f00 * f11 - f01 * f10;
  1345. if (det > 0)
  1346. {
  1347. // Disjoint hyperbolic segments, pair <P0,P2>, <P1,P3>.
  1348. table.InsertEdge(EI_XMIN_YMIN, EI_XMIN_ZMIN);
  1349. table.InsertEdge(EI_XMIN_YMAX, EI_XMIN_ZMAX);
  1350. }
  1351. else if (det < 0)
  1352. {
  1353. // Disjoint hyperbolic segments, pair <P0,P3>, <P1,P2>.
  1354. table.InsertEdge(EI_XMIN_YMIN, EI_XMIN_ZMAX);
  1355. table.InsertEdge(EI_XMIN_YMAX, EI_XMIN_ZMIN);
  1356. }
  1357. else
  1358. {
  1359. // Plus-sign configuration, add branch point to
  1360. // tessellation.
  1361. table.Insert(FI_XMIN,
  1362. table.GetVertex(EI_XMIN_ZMIN)[0],
  1363. table.GetVertex(EI_XMIN_ZMIN)[1],
  1364. table.GetVertex(EI_XMIN_YMIN)[2]);
  1365. // Add edges sharing the branch point.
  1366. table.InsertEdge(EI_XMIN_YMIN, FI_XMIN);
  1367. table.InsertEdge(EI_XMIN_YMAX, FI_XMIN);
  1368. table.InsertEdge(EI_XMIN_ZMIN, FI_XMIN);
  1369. table.InsertEdge(EI_XMIN_ZMAX, FI_XMIN);
  1370. }
  1371. break;
  1372. }
  1373. default:
  1374. LogError("The level value cannot be an exact integer.");
  1375. }
  1376. }
  1377. void GetXMaxEdgesS(OctBox const& box, unsigned int type, VETable& table)
  1378. {
  1379. unsigned int faceType = 0;
  1380. if (type & EB_XMAX_YMIN)
  1381. {
  1382. faceType |= 0x01;
  1383. }
  1384. if (type & EB_XMAX_YMAX)
  1385. {
  1386. faceType |= 0x02;
  1387. }
  1388. if (type & EB_XMAX_ZMIN)
  1389. {
  1390. faceType |= 0x04;
  1391. }
  1392. if (type & EB_XMAX_ZMAX)
  1393. {
  1394. faceType |= 0x08;
  1395. }
  1396. switch (faceType)
  1397. {
  1398. case 0:
  1399. return;
  1400. case 3:
  1401. table.InsertEdge(EI_XMAX_YMIN, EI_XMAX_YMAX);
  1402. break;
  1403. case 5:
  1404. table.InsertEdge(EI_XMAX_YMIN, EI_XMAX_ZMIN);
  1405. break;
  1406. case 6:
  1407. table.InsertEdge(EI_XMAX_YMAX, EI_XMAX_ZMIN);
  1408. break;
  1409. case 9:
  1410. table.InsertEdge(EI_XMAX_YMIN, EI_XMAX_ZMAX);
  1411. break;
  1412. case 10:
  1413. table.InsertEdge(EI_XMAX_YMAX, EI_XMAX_ZMAX);
  1414. break;
  1415. case 12:
  1416. table.InsertEdge(EI_XMAX_ZMIN, EI_XMAX_ZMAX);
  1417. break;
  1418. case 15:
  1419. {
  1420. // Four vertices, one per edge, need to disambiguate.
  1421. int i = box.x1 + mSize * (box.y0 + mSize * box.z0);
  1422. // F(x,y,z)
  1423. int64_t f00 = static_cast<int64_t>(mInputVoxels[i]);
  1424. i += mSize;
  1425. // F(x,y+1,z)
  1426. int64_t f10 = static_cast<int64_t>(mInputVoxels[i]);
  1427. i += mSizeSqr;
  1428. // F(x,y+1,z+1)
  1429. int64_t f11 = static_cast<int64_t>(mInputVoxels[i]);
  1430. i -= mSize;
  1431. // F(x,y,z+1)
  1432. int64_t f01 = static_cast<int64_t>(mInputVoxels[i]);
  1433. int64_t det = f00 * f11 - f01 * f10;
  1434. if (det > 0)
  1435. {
  1436. // Disjoint hyperbolic segments, pair <P0,P2>, <P1,P3>.
  1437. table.InsertEdge(EI_XMAX_YMIN, EI_XMAX_ZMIN);
  1438. table.InsertEdge(EI_XMAX_YMAX, EI_XMAX_ZMAX);
  1439. }
  1440. else if (det < 0)
  1441. {
  1442. // Disjoint hyperbolic segments, pair <P0,P3>, <P1,P2>.
  1443. table.InsertEdge(EI_XMAX_YMIN, EI_XMAX_ZMAX);
  1444. table.InsertEdge(EI_XMAX_YMAX, EI_XMAX_ZMIN);
  1445. }
  1446. else
  1447. {
  1448. // Plus-sign configuration, add branch point to
  1449. // tessellation.
  1450. table.Insert(FI_XMAX,
  1451. table.GetVertex(EI_XMAX_ZMIN)[0],
  1452. table.GetVertex(EI_XMAX_ZMIN)[1],
  1453. table.GetVertex(EI_XMAX_YMIN)[2]);
  1454. // Add edges sharing the branch point.
  1455. table.InsertEdge(EI_XMAX_YMIN, FI_XMAX);
  1456. table.InsertEdge(EI_XMAX_YMAX, FI_XMAX);
  1457. table.InsertEdge(EI_XMAX_ZMIN, FI_XMAX);
  1458. table.InsertEdge(EI_XMAX_ZMAX, FI_XMAX);
  1459. }
  1460. break;
  1461. }
  1462. default:
  1463. LogError("The level value cannot be an exact integer.");
  1464. }
  1465. }
  1466. void GetYMinEdgesS(OctBox const& box, unsigned int type, VETable& table)
  1467. {
  1468. unsigned int faceType = 0;
  1469. if (type & EB_XMIN_YMIN)
  1470. {
  1471. faceType |= 0x01;
  1472. }
  1473. if (type & EB_XMAX_YMIN)
  1474. {
  1475. faceType |= 0x02;
  1476. }
  1477. if (type & EB_YMIN_ZMIN)
  1478. {
  1479. faceType |= 0x04;
  1480. }
  1481. if (type & EB_YMIN_ZMAX)
  1482. {
  1483. faceType |= 0x08;
  1484. }
  1485. switch (faceType)
  1486. {
  1487. case 0:
  1488. return;
  1489. case 3:
  1490. table.InsertEdge(EI_XMIN_YMIN, EI_XMAX_YMIN);
  1491. break;
  1492. case 5:
  1493. table.InsertEdge(EI_XMIN_YMIN, EI_YMIN_ZMIN);
  1494. break;
  1495. case 6:
  1496. table.InsertEdge(EI_XMAX_YMIN, EI_YMIN_ZMIN);
  1497. break;
  1498. case 9:
  1499. table.InsertEdge(EI_XMIN_YMIN, EI_YMIN_ZMAX);
  1500. break;
  1501. case 10:
  1502. table.InsertEdge(EI_XMAX_YMIN, EI_YMIN_ZMAX);
  1503. break;
  1504. case 12:
  1505. table.InsertEdge(EI_YMIN_ZMIN, EI_YMIN_ZMAX);
  1506. break;
  1507. case 15:
  1508. {
  1509. // Four vertices, one per edge, need to disambiguate.
  1510. int i = box.x0 + mSize * (box.y0 + mSize * box.z0);
  1511. // F(x,y,z)
  1512. int64_t f00 = static_cast<int64_t>(mInputVoxels[i]);
  1513. ++i;
  1514. // F(x+1,y,z)
  1515. int64_t f10 = static_cast<int64_t>(mInputVoxels[i]);
  1516. i += mSizeSqr;
  1517. // F(x+1,y,z+1)
  1518. int64_t f11 = static_cast<int64_t>(mInputVoxels[i]);
  1519. --i;
  1520. // F(x,y,z+1)
  1521. int64_t f01 = static_cast<int64_t>(mInputVoxels[i]);
  1522. int64_t det = f00 * f11 - f01 * f10;
  1523. if (det > 0)
  1524. {
  1525. // Disjoint hyperbolic segments, pair <P0,P2>, <P1,P3>.
  1526. table.InsertEdge(EI_XMIN_YMIN, EI_YMIN_ZMIN);
  1527. table.InsertEdge(EI_XMAX_YMIN, EI_YMIN_ZMAX);
  1528. }
  1529. else if (det < 0)
  1530. {
  1531. // Disjoint hyperbolic segments, pair <P0,P3>, <P1,P2>.
  1532. table.InsertEdge(EI_XMIN_YMIN, EI_YMIN_ZMAX);
  1533. table.InsertEdge(EI_XMAX_YMIN, EI_YMIN_ZMIN);
  1534. }
  1535. else
  1536. {
  1537. // Plus-sign configuration, add branch point to
  1538. // tessellation.
  1539. table.Insert(FI_YMIN,
  1540. table.GetVertex(EI_YMIN_ZMIN)[0],
  1541. table.GetVertex(EI_XMIN_YMIN)[1],
  1542. table.GetVertex(EI_XMIN_YMIN)[2]);
  1543. // Add edges sharing the branch point.
  1544. table.InsertEdge(EI_XMIN_YMIN, FI_YMIN);
  1545. table.InsertEdge(EI_XMAX_YMIN, FI_YMIN);
  1546. table.InsertEdge(EI_YMIN_ZMIN, FI_YMIN);
  1547. table.InsertEdge(EI_YMIN_ZMAX, FI_YMIN);
  1548. }
  1549. break;
  1550. }
  1551. default:
  1552. LogError("The level value cannot be an exact integer.");
  1553. }
  1554. }
  1555. void GetYMaxEdgesS(OctBox const& box, unsigned int type, VETable& table)
  1556. {
  1557. unsigned int faceType = 0;
  1558. if (type & EB_XMIN_YMAX)
  1559. {
  1560. faceType |= 0x01;
  1561. }
  1562. if (type & EB_XMAX_YMAX)
  1563. {
  1564. faceType |= 0x02;
  1565. }
  1566. if (type & EB_YMAX_ZMIN)
  1567. {
  1568. faceType |= 0x04;
  1569. }
  1570. if (type & EB_YMAX_ZMAX)
  1571. {
  1572. faceType |= 0x08;
  1573. }
  1574. switch (faceType)
  1575. {
  1576. case 0:
  1577. return;
  1578. case 3:
  1579. table.InsertEdge(EI_XMIN_YMAX, EI_XMAX_YMAX);
  1580. break;
  1581. case 5:
  1582. table.InsertEdge(EI_XMIN_YMAX, EI_YMAX_ZMIN);
  1583. break;
  1584. case 6:
  1585. table.InsertEdge(EI_XMAX_YMAX, EI_YMAX_ZMIN);
  1586. break;
  1587. case 9:
  1588. table.InsertEdge(EI_XMIN_YMAX, EI_YMAX_ZMAX);
  1589. break;
  1590. case 10:
  1591. table.InsertEdge(EI_XMAX_YMAX, EI_YMAX_ZMAX);
  1592. break;
  1593. case 12:
  1594. table.InsertEdge(EI_YMAX_ZMIN, EI_YMAX_ZMAX);
  1595. break;
  1596. case 15:
  1597. {
  1598. // Four vertices, one per edge, need to disambiguate.
  1599. int i = box.x0 + mSize * (box.y1 + mSize * box.z0);
  1600. // F(x,y,z)
  1601. int64_t f00 = static_cast<int64_t>(mInputVoxels[i]);
  1602. ++i;
  1603. // F(x+1,y,z)
  1604. int64_t f10 = static_cast<int64_t>(mInputVoxels[i]);
  1605. i += mSizeSqr;
  1606. // F(x+1,y,z+1)
  1607. int64_t f11 = static_cast<int64_t>(mInputVoxels[i]);
  1608. --i;
  1609. // F(x,y,z+1)
  1610. int64_t f01 = static_cast<int64_t>(mInputVoxels[i]);
  1611. int64_t det = f00 * f11 - f01 * f10;
  1612. if (det > 0)
  1613. {
  1614. // Disjoint hyperbolic segments, pair <P0,P2>, <P1,P3>.
  1615. table.InsertEdge(EI_XMIN_YMAX, EI_YMAX_ZMIN);
  1616. table.InsertEdge(EI_XMAX_YMAX, EI_YMAX_ZMAX);
  1617. }
  1618. else if (det < 0)
  1619. {
  1620. // Disjoint hyperbolic segments, pair <P0,P3>, <P1,P2>.
  1621. table.InsertEdge(EI_XMIN_YMAX, EI_YMAX_ZMAX);
  1622. table.InsertEdge(EI_XMAX_YMAX, EI_YMAX_ZMIN);
  1623. }
  1624. else
  1625. {
  1626. // Plus-sign configuration, add branch point to
  1627. // tessellation.
  1628. table.Insert(FI_YMAX,
  1629. table.GetVertex(EI_YMAX_ZMIN)[0],
  1630. table.GetVertex(EI_XMIN_YMAX)[1],
  1631. table.GetVertex(EI_XMIN_YMAX)[2]);
  1632. // Add edges sharing the branch point.
  1633. table.InsertEdge(EI_XMIN_YMAX, FI_YMAX);
  1634. table.InsertEdge(EI_XMAX_YMAX, FI_YMAX);
  1635. table.InsertEdge(EI_YMAX_ZMIN, FI_YMAX);
  1636. table.InsertEdge(EI_YMAX_ZMAX, FI_YMAX);
  1637. }
  1638. break;
  1639. }
  1640. default:
  1641. LogError("The level value cannot be an exact integer.");
  1642. }
  1643. }
  1644. void GetZMinEdgesS(OctBox const& box, unsigned int type, VETable& table)
  1645. {
  1646. unsigned int faceType = 0;
  1647. if (type & EB_XMIN_ZMIN)
  1648. {
  1649. faceType |= 0x01;
  1650. }
  1651. if (type & EB_XMAX_ZMIN)
  1652. {
  1653. faceType |= 0x02;
  1654. }
  1655. if (type & EB_YMIN_ZMIN)
  1656. {
  1657. faceType |= 0x04;
  1658. }
  1659. if (type & EB_YMAX_ZMIN)
  1660. {
  1661. faceType |= 0x08;
  1662. }
  1663. switch (faceType)
  1664. {
  1665. case 0:
  1666. return;
  1667. case 3:
  1668. table.InsertEdge(EI_XMIN_ZMIN, EI_XMAX_ZMIN);
  1669. break;
  1670. case 5:
  1671. table.InsertEdge(EI_XMIN_ZMIN, EI_YMIN_ZMIN);
  1672. break;
  1673. case 6:
  1674. table.InsertEdge(EI_XMAX_ZMIN, EI_YMIN_ZMIN);
  1675. break;
  1676. case 9:
  1677. table.InsertEdge(EI_XMIN_ZMIN, EI_YMAX_ZMIN);
  1678. break;
  1679. case 10:
  1680. table.InsertEdge(EI_XMAX_ZMIN, EI_YMAX_ZMIN);
  1681. break;
  1682. case 12:
  1683. table.InsertEdge(EI_YMIN_ZMIN, EI_YMAX_ZMIN);
  1684. break;
  1685. case 15:
  1686. {
  1687. // Four vertices, one per edge, need to disambiguate.
  1688. int i = box.x0 + mSize * (box.y0 + mSize * box.z0);
  1689. // F(x,y,z)
  1690. int64_t f00 = static_cast<int64_t>(mInputVoxels[i]);
  1691. ++i;
  1692. // F(x+1,y,z)
  1693. int64_t f10 = static_cast<int64_t>(mInputVoxels[i]);
  1694. i += mSize;
  1695. // F(x+1,y+1,z)
  1696. int64_t f11 = static_cast<int64_t>(mInputVoxels[i]);
  1697. --i;
  1698. // F(x,y+1,z)
  1699. int64_t f01 = static_cast<int64_t>(mInputVoxels[i]);
  1700. int64_t det = f00 * f11 - f01 * f10;
  1701. if (det > 0)
  1702. {
  1703. // Disjoint hyperbolic segments, pair <P0,P2>, <P1,P3>.
  1704. table.InsertEdge(EI_XMIN_ZMIN, EI_YMIN_ZMIN);
  1705. table.InsertEdge(EI_XMAX_ZMIN, EI_YMAX_ZMIN);
  1706. }
  1707. else if (det < 0)
  1708. {
  1709. // Disjoint hyperbolic segments, pair <P0,P3>, <P1,P2>.
  1710. table.InsertEdge(EI_XMIN_ZMIN, EI_YMAX_ZMIN);
  1711. table.InsertEdge(EI_XMAX_ZMIN, EI_YMIN_ZMIN);
  1712. }
  1713. else
  1714. {
  1715. // Plus-sign configuration, add branch point to
  1716. // tessellation.
  1717. table.Insert(FI_ZMIN,
  1718. table.GetVertex(EI_YMIN_ZMIN)[0],
  1719. table.GetVertex(EI_XMIN_ZMIN)[1],
  1720. table.GetVertex(EI_XMIN_ZMIN)[2]);
  1721. // Add edges sharing the branch point.
  1722. table.InsertEdge(EI_XMIN_ZMIN, FI_ZMIN);
  1723. table.InsertEdge(EI_XMAX_ZMIN, FI_ZMIN);
  1724. table.InsertEdge(EI_YMIN_ZMIN, FI_ZMIN);
  1725. table.InsertEdge(EI_YMAX_ZMIN, FI_ZMIN);
  1726. }
  1727. break;
  1728. }
  1729. default:
  1730. LogError("The level value cannot be an exact integer.");
  1731. }
  1732. }
  1733. void GetZMaxEdgesS(const OctBox& box, unsigned int type, VETable& table)
  1734. {
  1735. unsigned int faceType = 0;
  1736. if (type & EB_XMIN_ZMAX)
  1737. {
  1738. faceType |= 0x01;
  1739. }
  1740. if (type & EB_XMAX_ZMAX)
  1741. {
  1742. faceType |= 0x02;
  1743. }
  1744. if (type & EB_YMIN_ZMAX)
  1745. {
  1746. faceType |= 0x04;
  1747. }
  1748. if (type & EB_YMAX_ZMAX)
  1749. {
  1750. faceType |= 0x08;
  1751. }
  1752. switch (faceType)
  1753. {
  1754. case 0:
  1755. return;
  1756. case 3:
  1757. table.InsertEdge(EI_XMIN_ZMAX, EI_XMAX_ZMAX);
  1758. break;
  1759. case 5:
  1760. table.InsertEdge(EI_XMIN_ZMAX, EI_YMIN_ZMAX);
  1761. break;
  1762. case 6:
  1763. table.InsertEdge(EI_XMAX_ZMAX, EI_YMIN_ZMAX);
  1764. break;
  1765. case 9:
  1766. table.InsertEdge(EI_XMIN_ZMAX, EI_YMAX_ZMAX);
  1767. break;
  1768. case 10:
  1769. table.InsertEdge(EI_XMAX_ZMAX, EI_YMAX_ZMAX);
  1770. break;
  1771. case 12:
  1772. table.InsertEdge(EI_YMIN_ZMAX, EI_YMAX_ZMAX);
  1773. break;
  1774. case 15:
  1775. {
  1776. // Four vertices, one per edge, need to disambiguate.
  1777. int i = box.x0 + mSize * (box.y0 + mSize * box.z1);
  1778. // F(x,y,z)
  1779. int64_t f00 = static_cast<int64_t>(mInputVoxels[i]);
  1780. i++;
  1781. // F(x+1,y,z)
  1782. int64_t f10 = static_cast<int64_t>(mInputVoxels[i]);
  1783. i += mSize;
  1784. // F(x+1,y+1,z)
  1785. int64_t f11 = static_cast<int64_t>(mInputVoxels[i]);
  1786. i--;
  1787. // F(x,y+1,z)
  1788. int64_t f01 = static_cast<int64_t>(mInputVoxels[i]);
  1789. int64_t det = f00 * f11 - f01 * f10;
  1790. if (det > 0)
  1791. {
  1792. // Disjoint hyperbolic segments, pair <P0,P2>, <P1,P3>.
  1793. table.InsertEdge(EI_XMIN_ZMAX, EI_YMIN_ZMAX);
  1794. table.InsertEdge(EI_XMAX_ZMAX, EI_YMAX_ZMAX);
  1795. }
  1796. else if (det < 0)
  1797. {
  1798. // Disjoint hyperbolic segments, pair <P0,P3>, <P1,P2>.
  1799. table.InsertEdge(EI_XMIN_ZMAX, EI_YMAX_ZMAX);
  1800. table.InsertEdge(EI_XMAX_ZMAX, EI_YMIN_ZMAX);
  1801. }
  1802. else
  1803. {
  1804. // Plus-sign configuration, add branch point to
  1805. // tessellation.
  1806. table.Insert(FI_ZMAX,
  1807. table.GetVertex(EI_YMIN_ZMAX)[0],
  1808. table.GetVertex(EI_XMIN_ZMAX)[1],
  1809. table.GetVertex(EI_XMIN_ZMAX)[2]);
  1810. // Add edges sharing the branch point.
  1811. table.InsertEdge(EI_XMIN_ZMAX, FI_ZMAX);
  1812. table.InsertEdge(EI_XMAX_ZMAX, FI_ZMAX);
  1813. table.InsertEdge(EI_YMIN_ZMAX, FI_ZMAX);
  1814. table.InsertEdge(EI_YMAX_ZMAX, FI_ZMAX);
  1815. }
  1816. break;
  1817. }
  1818. default:
  1819. LogError("The level value cannot be an exact integer.");
  1820. }
  1821. }
  1822. // Edge extraction for merged boxes.
  1823. class Sort0
  1824. {
  1825. public:
  1826. bool operator()(Vertex const& arg0, Vertex const& arg1) const
  1827. {
  1828. if (arg0[0] < arg1[0])
  1829. {
  1830. return true;
  1831. }
  1832. if (arg0[0] > arg1[0])
  1833. {
  1834. return false;
  1835. }
  1836. if (arg0[1] < arg1[1])
  1837. {
  1838. return true;
  1839. }
  1840. if (arg0[1] > arg1[1])
  1841. {
  1842. return false;
  1843. }
  1844. return arg0[2] < arg1[2];
  1845. }
  1846. };
  1847. class Sort1
  1848. {
  1849. public:
  1850. bool operator()(Vertex const& arg0, Vertex const& arg1) const
  1851. {
  1852. if (arg0[2] < arg1[2])
  1853. {
  1854. return true;
  1855. }
  1856. if (arg0[2] > arg1[2])
  1857. {
  1858. return false;
  1859. }
  1860. if (arg0[0] < arg1[0])
  1861. {
  1862. return true;
  1863. }
  1864. if (arg0[0] > arg1[0])
  1865. {
  1866. return false;
  1867. }
  1868. return arg0[1] < arg1[1];
  1869. }
  1870. };
  1871. class Sort2
  1872. {
  1873. public:
  1874. bool operator()(Vertex const& arg0, Vertex const& arg1) const
  1875. {
  1876. if (arg0[1] < arg1[1])
  1877. {
  1878. return true;
  1879. }
  1880. if (arg0[1] > arg1[1])
  1881. {
  1882. return false;
  1883. }
  1884. if (arg0[2] < arg1[2])
  1885. {
  1886. return true;
  1887. }
  1888. if (arg0[2] > arg1[2])
  1889. {
  1890. return false;
  1891. }
  1892. return arg0[0] < arg1[0];
  1893. }
  1894. };
  1895. void GetZMinEdgesM(OctBox const& box, unsigned int type, VETable& table)
  1896. {
  1897. unsigned int faceType = 0;
  1898. if (type & EB_XMIN_ZMIN)
  1899. {
  1900. faceType |= 0x01;
  1901. }
  1902. if (type & EB_XMAX_ZMIN)
  1903. {
  1904. faceType |= 0x02;
  1905. }
  1906. if (type & EB_YMIN_ZMIN)
  1907. {
  1908. faceType |= 0x04;
  1909. }
  1910. if (type & EB_YMAX_ZMIN)
  1911. {
  1912. faceType |= 0x08;
  1913. }
  1914. int end0 = 0, end1 = 0;
  1915. switch (faceType)
  1916. {
  1917. case 0:
  1918. return;
  1919. case 3:
  1920. end0 = EI_XMIN_ZMIN;
  1921. end1 = EI_XMAX_ZMIN;
  1922. break;
  1923. case 5:
  1924. end0 = EI_XMIN_ZMIN;
  1925. end1 = EI_YMIN_ZMIN;
  1926. break;
  1927. case 6:
  1928. end0 = EI_YMIN_ZMIN;
  1929. end1 = EI_XMAX_ZMIN;
  1930. break;
  1931. case 9:
  1932. end0 = EI_XMIN_ZMIN;
  1933. end1 = EI_YMAX_ZMIN;
  1934. break;
  1935. case 10:
  1936. end0 = EI_YMAX_ZMIN;
  1937. end1 = EI_XMAX_ZMIN;
  1938. break;
  1939. case 12:
  1940. end0 = EI_YMIN_ZMIN;
  1941. end1 = EI_YMAX_ZMIN;
  1942. break;
  1943. default:
  1944. LogError("The level value cannot be an exact integer.");
  1945. }
  1946. std::set<Vertex, Sort0> vSet;
  1947. for (int x = box.x0 + 1; x < box.x1; ++x)
  1948. {
  1949. auto const& merge = mYMerge[x][box.z0];
  1950. if (merge->IsZeroEdge(box.LY) || merge->HasZeroSubedge(box.LY))
  1951. {
  1952. int root = merge->GetZeroBase(box.LY);
  1953. vSet.insert(Vertex{
  1954. static_cast<Real>(x),
  1955. GetYInterp(x, root, box.z0),
  1956. static_cast<Real>(box.z0) });
  1957. }
  1958. }
  1959. for (int y = box.y0 + 1; y < box.y1; ++y)
  1960. {
  1961. auto const& merge = mXMerge[y][box.z0];
  1962. if (merge->IsZeroEdge(box.LX) || merge->HasZeroSubedge(box.LX))
  1963. {
  1964. int root = merge->GetZeroBase(box.LX);
  1965. vSet.insert(Vertex{
  1966. GetXInterp(root, y, box.z0),
  1967. static_cast<Real>(y),
  1968. static_cast<Real>(box.z0) });
  1969. }
  1970. }
  1971. // Add subdivision.
  1972. if (vSet.size() == 0)
  1973. {
  1974. table.InsertEdge(end0, end1);
  1975. return;
  1976. }
  1977. Real v0x = std::floor((*vSet.begin())[0]);
  1978. Real v1x = std::floor((*vSet.rbegin())[0]);
  1979. Real e0x = std::floor(table.GetVertex(end0)[0]);
  1980. Real e1x = std::floor(table.GetVertex(end1)[0]);
  1981. if (e1x <= v0x && v1x <= e0x)
  1982. {
  1983. std::swap(end0, end1);
  1984. }
  1985. // Add vertices.
  1986. int v0 = table.GetNumVertices(), v1 = v0;
  1987. for (auto const& position : vSet)
  1988. {
  1989. table.Insert(position);
  1990. }
  1991. // Add edges.
  1992. table.InsertEdge(end0, v1);
  1993. ++v1;
  1994. int const imax = static_cast<int>(vSet.size());
  1995. for (int i = 1; i < imax; ++i, ++v0, ++v1)
  1996. {
  1997. table.InsertEdge(v0, v1);
  1998. }
  1999. table.InsertEdge(v0, end1);
  2000. }
  2001. void GetZMaxEdgesM(OctBox const& box, unsigned int type, VETable& table)
  2002. {
  2003. unsigned int faceType = 0;
  2004. if (type & EB_XMIN_ZMAX)
  2005. {
  2006. faceType |= 0x01;
  2007. }
  2008. if (type & EB_XMAX_ZMAX)
  2009. {
  2010. faceType |= 0x02;
  2011. }
  2012. if (type & EB_YMIN_ZMAX)
  2013. {
  2014. faceType |= 0x04;
  2015. }
  2016. if (type & EB_YMAX_ZMAX)
  2017. {
  2018. faceType |= 0x08;
  2019. }
  2020. int end0 = 0, end1 = 0;
  2021. switch (faceType)
  2022. {
  2023. case 0:
  2024. return;
  2025. case 3:
  2026. end0 = EI_XMIN_ZMAX;
  2027. end1 = EI_XMAX_ZMAX;
  2028. break;
  2029. case 5:
  2030. end0 = EI_XMIN_ZMAX;
  2031. end1 = EI_YMIN_ZMAX;
  2032. break;
  2033. case 6:
  2034. end0 = EI_YMIN_ZMAX;
  2035. end1 = EI_XMAX_ZMAX;
  2036. break;
  2037. case 9:
  2038. end0 = EI_XMIN_ZMAX;
  2039. end1 = EI_YMAX_ZMAX;
  2040. break;
  2041. case 10:
  2042. end0 = EI_YMAX_ZMAX;
  2043. end1 = EI_XMAX_ZMAX;
  2044. break;
  2045. case 12:
  2046. end0 = EI_YMIN_ZMAX;
  2047. end1 = EI_YMAX_ZMAX;
  2048. break;
  2049. default:
  2050. LogError("The level value cannot be an exact integer.");
  2051. }
  2052. std::set<Vertex, Sort0> vSet;
  2053. for (int x = box.x0 + 1; x < box.x1; ++x)
  2054. {
  2055. auto const& merge = mYMerge[x][box.z1];
  2056. if (merge->IsZeroEdge(box.LY) || merge->HasZeroSubedge(box.LY))
  2057. {
  2058. int root = merge->GetZeroBase(box.LY);
  2059. vSet.insert(Vertex{
  2060. static_cast<Real>(x),
  2061. GetYInterp(x, root, box.z1),
  2062. static_cast<Real>(box.z1) });
  2063. }
  2064. }
  2065. for (int y = box.y0 + 1; y < box.y1; ++y)
  2066. {
  2067. auto const& merge = mXMerge[y][box.z1];
  2068. if (merge->IsZeroEdge(box.LX) || merge->HasZeroSubedge(box.LX))
  2069. {
  2070. int root = merge->GetZeroBase(box.LX);
  2071. vSet.insert(Vertex{
  2072. GetXInterp(root, y, box.z1),
  2073. static_cast<Real>(y),
  2074. static_cast<Real>(box.z1) });
  2075. }
  2076. }
  2077. // Add subdivision.
  2078. int v0 = table.GetNumVertices(), v1 = v0;
  2079. if (vSet.size() == 0)
  2080. {
  2081. table.InsertEdge(end0, end1);
  2082. return;
  2083. }
  2084. Real v0x = std::floor((*vSet.begin())[0]);
  2085. Real v1x = std::floor((*vSet.rbegin())[0]);
  2086. Real e0x = std::floor(table.GetVertex(end0)[0]);
  2087. Real e1x = std::floor(table.GetVertex(end1)[0]);
  2088. if (e1x <= v0x && v1x <= e0x)
  2089. {
  2090. std::swap(end0, end1);
  2091. }
  2092. // Add vertices.
  2093. for (auto const& position : vSet)
  2094. {
  2095. table.Insert(position);
  2096. }
  2097. // Add edges.
  2098. table.InsertEdge(end0, v1);
  2099. ++v1;
  2100. int const imax = static_cast<int>(vSet.size());
  2101. for (int i = 1; i < imax; ++i, ++v0, ++v1)
  2102. {
  2103. table.InsertEdge(v0, v1);
  2104. }
  2105. table.InsertEdge(v0, end1);
  2106. }
  2107. void GetYMinEdgesM(OctBox const& box, unsigned int type, VETable& table)
  2108. {
  2109. unsigned int faceType = 0;
  2110. if (type & EB_XMIN_YMIN)
  2111. {
  2112. faceType |= 0x01;
  2113. }
  2114. if (type & EB_XMAX_YMIN)
  2115. {
  2116. faceType |= 0x02;
  2117. }
  2118. if (type & EB_YMIN_ZMIN)
  2119. {
  2120. faceType |= 0x04;
  2121. }
  2122. if (type & EB_YMIN_ZMAX)
  2123. {
  2124. faceType |= 0x08;
  2125. }
  2126. int end0 = 0, end1 = 0;
  2127. switch (faceType)
  2128. {
  2129. case 0:
  2130. return;
  2131. case 3:
  2132. end0 = EI_XMIN_YMIN;
  2133. end1 = EI_XMAX_YMIN;
  2134. break;
  2135. case 5:
  2136. end0 = EI_XMIN_YMIN;
  2137. end1 = EI_YMIN_ZMIN;
  2138. break;
  2139. case 6:
  2140. end0 = EI_YMIN_ZMIN;
  2141. end1 = EI_XMAX_YMIN;
  2142. break;
  2143. case 9:
  2144. end0 = EI_XMIN_YMIN;
  2145. end1 = EI_YMIN_ZMAX;
  2146. break;
  2147. case 10:
  2148. end0 = EI_YMIN_ZMAX;
  2149. end1 = EI_XMAX_YMIN;
  2150. break;
  2151. case 12:
  2152. end0 = EI_YMIN_ZMIN;
  2153. end1 = EI_YMIN_ZMAX;
  2154. break;
  2155. default:
  2156. LogError("The level value cannot be an exact integer.");
  2157. }
  2158. std::set<Vertex, Sort1> vSet;
  2159. for (int x = box.x0 + 1; x < box.x1; ++x)
  2160. {
  2161. auto const& merge = mZMerge[x][box.y0];
  2162. if (merge->IsZeroEdge(box.LZ) || merge->HasZeroSubedge(box.LZ))
  2163. {
  2164. int root = merge->GetZeroBase(box.LZ);
  2165. vSet.insert(Vertex{
  2166. static_cast<Real>(x),
  2167. static_cast<Real>(box.y0),
  2168. GetZInterp(x, box.y0, root) });
  2169. }
  2170. }
  2171. for (int z = box.z0 + 1; z < box.z1; ++z)
  2172. {
  2173. auto const& merge = mXMerge[box.y0][z];
  2174. if (merge->IsZeroEdge(box.LX) || merge->HasZeroSubedge(box.LX))
  2175. {
  2176. int root = merge->GetZeroBase(box.LX);
  2177. vSet.insert(Vertex{
  2178. GetXInterp(root, box.y0, z),
  2179. static_cast<Real>(box.y0),
  2180. static_cast<Real>(z) });
  2181. }
  2182. }
  2183. // Add subdivision.
  2184. int v0 = table.GetNumVertices(), v1 = v0;
  2185. if (vSet.size() == 0)
  2186. {
  2187. table.InsertEdge(end0, end1);
  2188. return;
  2189. }
  2190. Real v0z = std::floor((*vSet.begin())[2]);
  2191. Real v1z = std::floor((*vSet.rbegin())[2]);
  2192. Real e0z = std::floor(table.GetVertex(end0)[2]);
  2193. Real e1z = std::floor(table.GetVertex(end1)[2]);
  2194. if (e1z <= v0z && v1z <= e0z)
  2195. {
  2196. std::swap(end0, end1);
  2197. }
  2198. // Add vertices.
  2199. for (auto const& position : vSet)
  2200. {
  2201. table.Insert(position);
  2202. }
  2203. // Add edges.
  2204. table.InsertEdge(end0, v1);
  2205. ++v1;
  2206. int const imax = static_cast<int>(vSet.size());
  2207. for (int i = 1; i < imax; ++i, ++v0, ++v1)
  2208. {
  2209. table.InsertEdge(v0, v1);
  2210. }
  2211. table.InsertEdge(v0, end1);
  2212. }
  2213. void GetYMaxEdgesM(OctBox const& box, unsigned int type, VETable& table)
  2214. {
  2215. unsigned int faceType = 0;
  2216. if (type & EB_XMIN_YMAX)
  2217. {
  2218. faceType |= 0x01;
  2219. }
  2220. if (type & EB_XMAX_YMAX)
  2221. {
  2222. faceType |= 0x02;
  2223. }
  2224. if (type & EB_YMAX_ZMIN)
  2225. {
  2226. faceType |= 0x04;
  2227. }
  2228. if (type & EB_YMAX_ZMAX)
  2229. {
  2230. faceType |= 0x08;
  2231. }
  2232. int end0 = 0, end1 = 0;
  2233. switch (faceType)
  2234. {
  2235. case 0:
  2236. return;
  2237. case 3:
  2238. end0 = EI_XMIN_YMAX;
  2239. end1 = EI_XMAX_YMAX;
  2240. break;
  2241. case 5:
  2242. end0 = EI_XMIN_YMAX;
  2243. end1 = EI_YMAX_ZMIN;
  2244. break;
  2245. case 6:
  2246. end0 = EI_YMAX_ZMIN;
  2247. end1 = EI_XMAX_YMAX;
  2248. break;
  2249. case 9:
  2250. end0 = EI_XMIN_YMAX;
  2251. end1 = EI_YMAX_ZMAX;
  2252. break;
  2253. case 10:
  2254. end0 = EI_YMAX_ZMAX;
  2255. end1 = EI_XMAX_YMAX;
  2256. break;
  2257. case 12:
  2258. end0 = EI_YMAX_ZMIN;
  2259. end1 = EI_YMAX_ZMAX;
  2260. break;
  2261. default:
  2262. LogError("The level value cannot be an exact integer.");
  2263. }
  2264. std::set<Vertex, Sort1> vSet;
  2265. for (int x = box.x0 + 1; x < box.x1; ++x)
  2266. {
  2267. auto const& merge = mZMerge[x][box.y1];
  2268. if (merge->IsZeroEdge(box.LZ) || merge->HasZeroSubedge(box.LZ))
  2269. {
  2270. int root = merge->GetZeroBase(box.LZ);
  2271. vSet.insert(Vertex{
  2272. static_cast<Real>(x),
  2273. static_cast<Real>(box.y1),
  2274. GetZInterp(x, box.y1, root) });
  2275. }
  2276. }
  2277. for (int z = box.z0 + 1; z < box.z1; ++z)
  2278. {
  2279. auto const& merge = mXMerge[box.y1][z];
  2280. if (merge->IsZeroEdge(box.LX) || merge->HasZeroSubedge(box.LX))
  2281. {
  2282. int root = merge->GetZeroBase(box.LX);
  2283. vSet.insert(Vertex{
  2284. GetXInterp(root, box.y1, z),
  2285. static_cast<Real>(box.y1),
  2286. static_cast<Real>(z) });
  2287. }
  2288. }
  2289. // Add subdivision.
  2290. if (vSet.size() == 0)
  2291. {
  2292. table.InsertEdge(end0, end1);
  2293. return;
  2294. }
  2295. Real v0z = std::floor((*vSet.begin())[2]);
  2296. Real v1z = std::floor((*vSet.rbegin())[2]);
  2297. Real e0z = std::floor(table.GetVertex(end0)[2]);
  2298. Real e1z = std::floor(table.GetVertex(end1)[2]);
  2299. if (e1z <= v0z && v1z <= e0z)
  2300. {
  2301. std::swap(end0, end1);
  2302. }
  2303. // Add vertices.
  2304. int v0 = table.GetNumVertices(), v1 = v0;
  2305. for (auto const& position : vSet)
  2306. {
  2307. table.Insert(position);
  2308. }
  2309. // Add edges.
  2310. table.InsertEdge(end0, v1);
  2311. ++v1;
  2312. int const imax = static_cast<int>(vSet.size());
  2313. for (int i = 1; i < imax; ++i, ++v0, ++v1)
  2314. {
  2315. table.InsertEdge(v0, v1);
  2316. }
  2317. table.InsertEdge(v0, end1);
  2318. }
  2319. void GetXMinEdgesM(OctBox const& box, unsigned int type, VETable& table)
  2320. {
  2321. unsigned int faceType = 0;
  2322. if (type & EB_XMIN_YMIN)
  2323. {
  2324. faceType |= 0x01;
  2325. }
  2326. if (type & EB_XMIN_YMAX)
  2327. {
  2328. faceType |= 0x02;
  2329. }
  2330. if (type & EB_XMIN_ZMIN)
  2331. {
  2332. faceType |= 0x04;
  2333. }
  2334. if (type & EB_XMIN_ZMAX)
  2335. {
  2336. faceType |= 0x08;
  2337. }
  2338. int end0 = 0, end1 = 0;
  2339. switch (faceType)
  2340. {
  2341. case 0:
  2342. return;
  2343. case 3:
  2344. end0 = EI_XMIN_YMIN;
  2345. end1 = EI_XMIN_YMAX;
  2346. break;
  2347. case 5:
  2348. end0 = EI_XMIN_YMIN;
  2349. end1 = EI_XMIN_ZMIN;
  2350. break;
  2351. case 6:
  2352. end0 = EI_XMIN_ZMIN;
  2353. end1 = EI_XMIN_YMAX;
  2354. break;
  2355. case 9:
  2356. end0 = EI_XMIN_YMIN;
  2357. end1 = EI_XMIN_ZMAX;
  2358. break;
  2359. case 10:
  2360. end0 = EI_XMIN_ZMAX;
  2361. end1 = EI_XMIN_YMAX;
  2362. break;
  2363. case 12:
  2364. end0 = EI_XMIN_ZMIN;
  2365. end1 = EI_XMIN_ZMAX;
  2366. break;
  2367. default:
  2368. LogError("The level value cannot be an exact integer.");
  2369. }
  2370. std::set<Vertex, Sort2> vSet;
  2371. for (int z = box.z0 + 1; z < box.z1; ++z)
  2372. {
  2373. auto const& merge = mYMerge[box.x0][z];
  2374. if (merge->IsZeroEdge(box.LY) || merge->HasZeroSubedge(box.LY))
  2375. {
  2376. int root = merge->GetZeroBase(box.LY);
  2377. vSet.insert(Vertex{
  2378. static_cast<Real>(box.x0),
  2379. GetYInterp(box.x0, root, z),
  2380. static_cast<Real>(z) });
  2381. }
  2382. }
  2383. for (int y = box.y0 + 1; y < box.y1; ++y)
  2384. {
  2385. auto const& merge = mZMerge[box.x0][y];
  2386. if (merge->IsZeroEdge(box.LZ) || merge->HasZeroSubedge(box.LZ))
  2387. {
  2388. int root = merge->GetZeroBase(box.LZ);
  2389. vSet.insert(Vertex{
  2390. static_cast<Real>(box.x0),
  2391. static_cast<Real>(y),
  2392. GetZInterp(box.x0, y, root) });
  2393. }
  2394. }
  2395. // Add subdivision.
  2396. int v0 = table.GetNumVertices(), v1 = v0;
  2397. if (vSet.size() == 0)
  2398. {
  2399. table.InsertEdge(end0, end1);
  2400. return;
  2401. }
  2402. Real v0y = std::floor((*vSet.begin())[1]);
  2403. Real v1y = std::floor((*vSet.rbegin())[1]);
  2404. Real e0y = std::floor(table.GetVertex(end0)[1]);
  2405. Real e1y = std::floor(table.GetVertex(end1)[1]);
  2406. if (e1y <= v0y && v1y <= e0y)
  2407. {
  2408. std::swap(end0, end1);
  2409. }
  2410. // Add vertices.
  2411. for (auto const& position : vSet)
  2412. {
  2413. table.Insert(position);
  2414. }
  2415. // Add edges.
  2416. table.InsertEdge(end0, v1);
  2417. ++v1;
  2418. int const imax = static_cast<int>(vSet.size());
  2419. for (int i = 1; i < imax; ++i, ++v0, ++v1)
  2420. {
  2421. table.InsertEdge(v0, v1);
  2422. }
  2423. table.InsertEdge(v0, end1);
  2424. }
  2425. void GetXMaxEdgesM(OctBox const& box, unsigned int type, VETable& table)
  2426. {
  2427. unsigned int faceType = 0;
  2428. if (type & EB_XMAX_YMIN)
  2429. {
  2430. faceType |= 0x01;
  2431. }
  2432. if (type & EB_XMAX_YMAX)
  2433. {
  2434. faceType |= 0x02;
  2435. }
  2436. if (type & EB_XMAX_ZMIN)
  2437. {
  2438. faceType |= 0x04;
  2439. }
  2440. if (type & EB_XMAX_ZMAX)
  2441. {
  2442. faceType |= 0x08;
  2443. }
  2444. int end0 = 0, end1 = 0;
  2445. switch (faceType)
  2446. {
  2447. case 0:
  2448. return;
  2449. case 3:
  2450. end0 = EI_XMAX_YMIN;
  2451. end1 = EI_XMAX_YMAX;
  2452. break;
  2453. case 5:
  2454. end0 = EI_XMAX_YMIN;
  2455. end1 = EI_XMAX_ZMIN;
  2456. break;
  2457. case 6:
  2458. end0 = EI_XMAX_ZMIN;
  2459. end1 = EI_XMAX_YMAX;
  2460. break;
  2461. case 9:
  2462. end0 = EI_XMAX_YMIN;
  2463. end1 = EI_XMAX_ZMAX;
  2464. break;
  2465. case 10:
  2466. end0 = EI_XMAX_ZMAX;
  2467. end1 = EI_XMAX_YMAX;
  2468. break;
  2469. case 12:
  2470. end0 = EI_XMAX_ZMIN;
  2471. end1 = EI_XMAX_ZMAX;
  2472. break;
  2473. default:
  2474. LogError("The level value cannot be an exact integer.");
  2475. }
  2476. std::set<Vertex, Sort2> vSet;
  2477. for (int z = box.z0 + 1; z < box.z1; ++z)
  2478. {
  2479. auto const& merge = mYMerge[box.x1][z];
  2480. if (merge->IsZeroEdge(box.LY) || merge->HasZeroSubedge(box.LY))
  2481. {
  2482. int root = merge->GetZeroBase(box.LY);
  2483. vSet.insert(Vertex{
  2484. static_cast<Real>(box.x1),
  2485. GetYInterp(box.x1, root, z),
  2486. static_cast<Real>(z) });
  2487. }
  2488. }
  2489. for (int y = box.y0 + 1; y < box.y1; y++)
  2490. {
  2491. auto const& merge = mZMerge[box.x1][y];
  2492. if (merge->IsZeroEdge(box.LZ) || merge->HasZeroSubedge(box.LZ))
  2493. {
  2494. int root = merge->GetZeroBase(box.LZ);
  2495. vSet.insert(Vertex{
  2496. static_cast<Real>(box.x1),
  2497. static_cast<Real>(y),
  2498. GetZInterp(box.x1, y, root) });
  2499. }
  2500. }
  2501. // Add subdivision.
  2502. if (vSet.size() == 0)
  2503. {
  2504. table.InsertEdge(end0, end1);
  2505. return;
  2506. }
  2507. Real v0y = std::floor((*vSet.begin())[1]);
  2508. Real v1y = std::floor((*vSet.rbegin())[1]);
  2509. Real e0y = std::floor(table.GetVertex(end0)[1]);
  2510. Real e1y = std::floor(table.GetVertex(end1)[1]);
  2511. if (e1y <= v0y && v1y <= e0y)
  2512. {
  2513. std::swap(end0, end1);
  2514. }
  2515. // Add vertices.
  2516. int v0 = table.GetNumVertices(), v1 = v0;
  2517. for (auto const& position : vSet)
  2518. {
  2519. table.Insert(position);
  2520. }
  2521. // Add edges.
  2522. table.InsertEdge(end0, v1);
  2523. ++v1;
  2524. int const imax = static_cast<int>(vSet.size());
  2525. for (int i = 1; i < imax; ++i, ++v0, ++v1)
  2526. {
  2527. table.InsertEdge(v0, v1);
  2528. }
  2529. table.InsertEdge(v0, end1);
  2530. }
  2531. // Support for normal vector calculations.
  2532. Vertex GetGradient(Vertex const& position) const
  2533. {
  2534. Vertex vzero = { (Real)0, (Real)0, (Real)0 };
  2535. int x = static_cast<int>(position[0]);
  2536. if (x < 0 || x >= mTwoPowerN)
  2537. {
  2538. return vzero;
  2539. }
  2540. int y = static_cast<int>(position[1]);
  2541. if (y < 0 || y >= mTwoPowerN)
  2542. {
  2543. return vzero;
  2544. }
  2545. int z = static_cast<int>(position[2]);
  2546. if (z < 0 || z >= mTwoPowerN)
  2547. {
  2548. return vzero;
  2549. }
  2550. int i000 = x + mSize * (y + mSize * z);
  2551. int i100 = i000 + 1;
  2552. int i010 = i000 + mSize;
  2553. int i110 = i100 + mSize;
  2554. int i001 = i000 + mSizeSqr;
  2555. int i101 = i100 + mSizeSqr;
  2556. int i011 = i010 + mSizeSqr;
  2557. int i111 = i110 + mSizeSqr;
  2558. Real f000 = static_cast<Real>(mInputVoxels[i000]);
  2559. Real f100 = static_cast<Real>(mInputVoxels[i100]);
  2560. Real f010 = static_cast<Real>(mInputVoxels[i010]);
  2561. Real f110 = static_cast<Real>(mInputVoxels[i110]);
  2562. Real f001 = static_cast<Real>(mInputVoxels[i001]);
  2563. Real f101 = static_cast<Real>(mInputVoxels[i101]);
  2564. Real f011 = static_cast<Real>(mInputVoxels[i011]);
  2565. Real f111 = static_cast<Real>(mInputVoxels[i111]);
  2566. Real fx = position[0] - static_cast<Real>(x);
  2567. Real fy = position[1] - static_cast<Real>(y);
  2568. Real fz = position[2] - static_cast<Real>(z);
  2569. Real oneMinusX = (Real)1 - fx;
  2570. Real oneMinusY = (Real)1 - fy;
  2571. Real oneMinusZ = (Real)1 - fz;
  2572. Real tmp0, tmp1;
  2573. Vertex gradient;
  2574. tmp0 = oneMinusY * (f100 - f000) + fy * (f110 - f010);
  2575. tmp1 = oneMinusY * (f101 - f001) + fy * (f111 - f011);
  2576. gradient[0] = oneMinusZ * tmp0 + fz * tmp1;
  2577. tmp0 = oneMinusX * (f010 - f000) + fx * (f110 - f100);
  2578. tmp1 = oneMinusX * (f011 - f001) + fx * (f111 - f101);
  2579. gradient[1] = oneMinusZ * tmp0 + fz * tmp1;
  2580. tmp0 = oneMinusX * (f001 - f000) + fx * (f101 - f100);
  2581. tmp1 = oneMinusX * (f011 - f010) + fx * (f111 - f110);
  2582. gradient[2] = oneMinusY * tmp0 + oneMinusY * tmp1;
  2583. return gradient;
  2584. }
  2585. enum
  2586. {
  2587. EI_XMIN_YMIN = 0,
  2588. EI_XMIN_YMAX = 1,
  2589. EI_XMAX_YMIN = 2,
  2590. EI_XMAX_YMAX = 3,
  2591. EI_XMIN_ZMIN = 4,
  2592. EI_XMIN_ZMAX = 5,
  2593. EI_XMAX_ZMIN = 6,
  2594. EI_XMAX_ZMAX = 7,
  2595. EI_YMIN_ZMIN = 8,
  2596. EI_YMIN_ZMAX = 9,
  2597. EI_YMAX_ZMIN = 10,
  2598. EI_YMAX_ZMAX = 11,
  2599. FI_XMIN = 12,
  2600. FI_XMAX = 13,
  2601. FI_YMIN = 14,
  2602. FI_YMAX = 15,
  2603. FI_ZMIN = 16,
  2604. FI_ZMAX = 17,
  2605. I_QUANTITY = 18,
  2606. EB_XMIN_YMIN = 1 << EI_XMIN_YMIN,
  2607. EB_XMIN_YMAX = 1 << EI_XMIN_YMAX,
  2608. EB_XMAX_YMIN = 1 << EI_XMAX_YMIN,
  2609. EB_XMAX_YMAX = 1 << EI_XMAX_YMAX,
  2610. EB_XMIN_ZMIN = 1 << EI_XMIN_ZMIN,
  2611. EB_XMIN_ZMAX = 1 << EI_XMIN_ZMAX,
  2612. EB_XMAX_ZMIN = 1 << EI_XMAX_ZMIN,
  2613. EB_XMAX_ZMAX = 1 << EI_XMAX_ZMAX,
  2614. EB_YMIN_ZMIN = 1 << EI_YMIN_ZMIN,
  2615. EB_YMIN_ZMAX = 1 << EI_YMIN_ZMAX,
  2616. EB_YMAX_ZMIN = 1 << EI_YMAX_ZMIN,
  2617. EB_YMAX_ZMAX = 1 << EI_YMAX_ZMAX,
  2618. FB_XMIN = 1 << FI_XMIN,
  2619. FB_XMAX = 1 << FI_XMAX,
  2620. FB_YMIN = 1 << FI_YMIN,
  2621. FB_YMAX = 1 << FI_YMAX,
  2622. FB_ZMIN = 1 << FI_ZMIN,
  2623. FB_ZMAX = 1 << FI_ZMAX
  2624. };
  2625. // image data
  2626. int mTwoPowerN, mSize, mSizeSqr;
  2627. T const* mInputVoxels;
  2628. Real mLevel;
  2629. bool mFixBoundary;
  2630. // Trees for linear merging.
  2631. Array2<std::shared_ptr<LinearMergeTree>> mXMerge, mYMerge, mZMerge;
  2632. // monoboxes
  2633. std::vector<OctBox> mBoxes;
  2634. };
  2635. }