GLS.Isosurface.pas 64 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562
  1. //
  2. // The graphics engine GLXEngine. The unit of GLScene for Delphi
  3. //
  4. unit GLS.Isosurface;
  5. (*
  6. Polygonising a scalar field by construction of isosurfaces
  7. Algorithms
  8. ----------
  9. Marching Cubes
  10. - Exploits a coarser Mesh then Marching Tetrahedra but produces less triangles
  11. - based on "Marching Cubes: A High Resolution 3D Surface
  12. Construction Algorithm" by W.E.Lorensen and H.E.Cline
  13. - patent free since 2005
  14. Marching Tetrahedra
  15. - Finer Mesh, better feature preservation
  16. - based on "A new tetrahedral tesselation scheme for isosurface generation"
  17. by S.L.Chan and E.O.Purisima
  18. - patent free
  19. Lookuptables
  20. - by Paul Bourke (http://paulbourke.net/geometry/polygonise/)
  21. Overall
  22. - Simple Data Structures to store Mesh.Vertices are calculated and stored twice
  23. or even more often.
  24. *)
  25. interface
  26. {$I Stage.Defines.inc}
  27. // uncomment next line to memorize vertex Density value to further use
  28. // (i.e. mesh color generation)
  29. {.$Define UseDensity}
  30. uses
  31. Stage.VectorGeometry,
  32. GLS.VectorLists,
  33. GLS.Mesh,
  34. GLS.VectorFileObjects,
  35. Stage.VectorTypes,
  36. Stage.VectorTypesExt;
  37. const
  38. ALLOC_SIZE = 65536;
  39. type
  40. TGLMarchingCube = class(TObject)
  41. private
  42. FIsoValue: TScalarValue;
  43. // sliceSize:Longword;
  44. PVertsX: PIntegerArray;
  45. PVertsY: PIntegerArray;
  46. PVertsZ: PIntegerArray;
  47. _Nverts: Integer;
  48. _Ntrigs: Integer;
  49. _Sverts: Integer;
  50. _Strigs: Integer;
  51. PVertices: PVertArray;
  52. PTriangles: PTriangleRecArray;
  53. _i, _j, _k: Longword;
  54. _Cube: array [0 .. 7] of TVoxelRec;
  55. _lut_entry: Byte;
  56. // _case:Byte;
  57. // _config:Byte;
  58. // _subconfig:Byte;
  59. procedure Init_temps;
  60. procedure Init_all;
  61. procedure Init_space;
  62. procedure Clean_temps;
  63. procedure Clean_all(keepFacets: Boolean = False);
  64. procedure Clean_space;
  65. procedure Test_vertex_addiction;
  66. protected
  67. FOriginalMC: Boolean; // now only original MC is implemented
  68. FSizeX: Integer;
  69. FSizeY: Integer;
  70. FSizeZ: Integer;
  71. FxMin: Single;
  72. FxMax: Single;
  73. FyMin: Single;
  74. FyMax: Single;
  75. FzMin: Single;
  76. FzMax: Single;
  77. FStepX: Single;
  78. FStepY: Single;
  79. FStepZ: Single;
  80. VoxelData: PVoxelData;
  81. procedure Process_Cube;
  82. (* function test_face(face:byte):Boolean;
  83. function test_interior(s:Byte):boolean *)
  84. procedure Compute_Intersection_Points;
  85. procedure Add_Triangle(trig: array of Integer; N: Byte; v12: Integer = -1);
  86. function Add_x_vertex: Integer;
  87. function Add_y_vertex: Integer;
  88. function Add_z_vertex: Integer;
  89. function Add_c_vertex: Integer;
  90. function Get_x_grad(i, j, k: Integer): Single;
  91. function Get_y_grad(i, j, k: Integer): Single;
  92. function Get_z_grad(i, j, k: Integer): Single;
  93. function Get_x_vert(i, j, k: Integer): Integer;
  94. function Get_y_vert(i, j, k: Integer): Integer;
  95. function Get_z_vert(i, j, k: Integer): Integer;
  96. procedure Set_x_vert(a_val, i, j, k: Integer);
  97. procedure Set_y_vert(a_val, i, j, k: Integer);
  98. procedure Set_z_vert(a_val, i, j, k: Integer);
  99. function GetVoxelValue(i, j, k: Integer): TScalarValue;
  100. procedure SetVoxelValue(i, j, k: Integer; HfValue: TScalarValue);
  101. function GetVoxelData(i, j, k: Integer): TVoxelRec;
  102. function Voxel(i, j, k: Integer): PVoxelRec;
  103. function Calc_u(v1, v2: Single): Extended; virtual;
  104. public
  105. ScalarField: TScalarField;
  106. constructor Create; overload; virtual;
  107. constructor Create(SizeX, SizeY, SizeZ: Integer;
  108. AIsoValue: TScalarValue = 0.0; xMin: Single = -0.5; xMax: Single = 0.5;
  109. yMin: Single = -0.5; yMax: Single = 0.5; zMin: Single = -0.5;
  110. zMax: Single = 0.5); overload; virtual;
  111. procedure ReDim(ASizeX, ASizeY, ASizeZ: Integer;
  112. xMin, xMax, yMin, yMax, zMin, zMax: Single); virtual;
  113. destructor Destroy; override;
  114. procedure Run; overload;
  115. procedure Run(IsoValue: TScalarValue); overload;
  116. function Internal(AValue: TScalarValue): Boolean; virtual;
  117. procedure FillVoxelData; overload; virtual;
  118. procedure FillVoxelData(AIsoValue: TScalarValue;
  119. AScalarField: TScalarField = nil); overload; virtual;
  120. procedure FillVoxelData(AIsoValue: TScalarValue;
  121. AScalarField: TScalarFieldInt); overload; virtual;
  122. procedure CalcVertices(Vertices: TGLVertexList; Alpha: Single = 1);
  123. procedure CalcMeshObject(AMeshObject: TGLMeshObject; Alpha: Single = 1);
  124. property IsoValue: TScalarValue read FIsoValue write FIsoValue; // TODO
  125. end;
  126. (* 3D isosurface extractor class. This class allows to calculate and exctract
  127. isosurfaces from scalar field voxel models using a given isovalue *)
  128. TGLIsoSurfaceExtractor = class(TObject)
  129. private
  130. Data: TArray3DExt;
  131. Dimensions: array ['x' .. 'z'] of Integer;
  132. // Build Index depending on whether the edges are outside or inside the surface
  133. function BuildIndex(var ADatavals: array of Single; Isovalue: Single): word;
  134. function Interpolate(const V0, V1: TAffineVector;
  135. var Val0, Val1, Isovalue: Single; isPolished: boolean): TVertex;
  136. public
  137. constructor Create(); overload;
  138. constructor Create(Xdim, Ydim, Zdim: Integer;
  139. var AData: TArray3DExt); overload;
  140. destructor Destroy(); override;
  141. procedure AssignData(Xdim, Ydim, Zdim: Integer; var AData: TArray3DExt);
  142. // Launch Marching Cubes
  143. procedure MarchingCubes(Isovalue: Single; out Vertices: TVertexArray;
  144. out Triangles: TIntegerArray; isPolished: boolean);
  145. // Launch Marching Tetrahedra
  146. procedure MarchingTetrahedra(Isovalue: Single; out Vertices: TVertexArray;
  147. out Triangles: TIntegerArray; isPolished: boolean);
  148. end;
  149. // Sphere surface
  150. function SFSphere(X, Y, Z: Extended): TScalarValue;
  151. // Minkowski space (http://mathworld.wolfram.com)
  152. function SFMinkowski(X, Y, Z: Extended): TScalarValue;
  153. // Klein Bottle (http://mathworld.wolfram.com)
  154. function SFKleinBottle(X, Y, Z: Extended): TScalarValue;
  155. // Chmutov-surface-1 (http://mathworld.wolfram.com)
  156. function SFChmutov1(X, Y, Z: Extended): TScalarValue;
  157. // Chmutov-surface-2 (http://mathworld.wolfram.com)
  158. function SFChmutov2(X, Y, Z: Extended): TScalarValue;
  159. // Toroidal surface (phantasy!)
  160. function SFToroidal(X, Y, Z: Extended): TScalarValue;
  161. // Double torus Surface (phantasy!)
  162. function SFDoubleTorus(X, Y, Z: Extended): TScalarValue;
  163. // -------------------------------------------------------------------------
  164. implementation
  165. // -------------------------------------------------------------------------
  166. const
  167. // Classic Cases for Marching Cube TriTable
  168. //
  169. (*
  170. 4----4------5
  171. /| /|
  172. 7 | 5 |
  173. / | / |
  174. 7-----6----6 |
  175. | 8 | 9
  176. | | | |
  177. | 0----0--|---1
  178. 11 / 10 /
  179. | 3 | 1
  180. |/ |/
  181. 3-----2-----2
  182. *)
  183. MC_TRITABLE: array [0 .. 255, 0 .. 15] of Integer = (
  184. (* 0: *) ( -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ),
  185. (* 1: 0, *) ( 0, 8, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ),
  186. (* 2: 1, *) ( 0, 1, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ),
  187. (* 3: 0, 1, *) ( 1, 8, 3, 9, 8, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ),
  188. (* 4: 2, *) ( 1, 2, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ),
  189. (* 5: 0, 2, *) ( 0, 8, 3, 1, 2, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ),
  190. (* 6: 1, 2, *) ( 9, 2, 10, 0, 2, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ),
  191. (* 7: 0, 1, 2, *) ( 2, 8, 3, 2, 10, 8, 10, 9, 8, -1, -1, -1, -1, -1, -1, -1 ),
  192. (* 8: 3, *) ( 3, 11, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ),
  193. (* 9: 0, 3, *) ( 0, 11, 2, 8, 11, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ),
  194. (* 10: 1, 3, *) ( 1, 9, 0, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ),
  195. (* 11: 0, 1, 3, *) ( 1, 11, 2, 1, 9, 11, 9, 8, 11, -1, -1, -1, -1, -1, -1, -1 ),
  196. (* 12: 2, 3, *) ( 3, 10, 1, 11, 10, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ),
  197. (* 13: 0, 2, 3, *) ( 0, 10, 1, 0, 8, 10, 8, 11, 10, -1, -1, -1, -1, -1, -1, -1 ),
  198. (* 14: 1, 2, 3, *) ( 3, 9, 0, 3, 11, 9, 11, 10, 9, -1, -1, -1, -1, -1, -1, -1 ),
  199. (* 15: 0, 1, 2, 3, *) ( 9, 8, 10, 10, 8, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ),
  200. (* 16: 4, *) ( 4, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ),
  201. (* 17: 0, 4, *) ( 4, 3, 0, 7, 3, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ),
  202. (* 18: 1, 4, *) ( 0, 1, 9, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ),
  203. (* 19: 0, 1, 4, *) ( 4, 1, 9, 4, 7, 1, 7, 3, 1, -1, -1, -1, -1, -1, -1, -1 ),
  204. (* 20: 2, 4, *) ( 1, 2, 10, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ),
  205. (* 21: 0, 2, 4, *) ( 3, 4, 7, 3, 0, 4, 1, 2, 10, -1, -1, -1, -1, -1, -1, -1 ),
  206. (* 22: 1, 2, 4, *) ( 9, 2, 10, 9, 0, 2, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1 ),
  207. (* 23: 0, 1, 2, 4, *) ( 2, 10, 9, 2, 9, 7, 2, 7, 3, 7, 9, 4, -1, -1, -1, -1 ),
  208. (* 24: 3, 4, *) ( 8, 4, 7, 3, 11, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ),
  209. (* 25: 0, 3, 4, *) ( 11, 4, 7, 11, 2, 4, 2, 0, 4, -1, -1, -1, -1, -1, -1, -1 ),
  210. (* 26: 1, 3, 4, *) ( 9, 0, 1, 8, 4, 7, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1 ),
  211. (* 27: 0, 1, 3, 4, *) ( 4, 7, 11, 9, 4, 11, 9, 11, 2, 9, 2, 1, -1, -1, -1, -1 ),
  212. (* 28: 2, 3, 4, *) ( 3, 10, 1, 3, 11, 10, 7, 8, 4, -1, -1, -1, -1, -1, -1, -1 ),
  213. (* 29: 0, 2, 3, 4, *) ( 1, 11, 10, 1, 4, 11, 1, 0, 4, 7, 11, 4, -1, -1, -1, -1 ),
  214. (* 30: 1, 2, 3, 4, *) ( 4, 7, 8, 9, 0, 11, 9, 11, 10, 11, 0, 3, -1, -1, -1, -1 ),
  215. (* 31: 0, 1, 2, 3, 4, *) ( 4, 7, 11, 4, 11, 9, 9, 11, 10, -1, -1, -1, -1, -1, -1, -1 ),
  216. (* 32: 5, *) ( 9, 5, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ),
  217. (* 33: 0, 5, *) ( 9, 5, 4, 0, 8, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ),
  218. (* 34: 1, 5, *) ( 0, 5, 4, 1, 5, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ),
  219. (* 35: 0, 1, 5, *) ( 8, 5, 4, 8, 3, 5, 3, 1, 5, -1, -1, -1, -1, -1, -1, -1 ),
  220. (* 36: 2, 5, *) ( 1, 2, 10, 9, 5, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ),
  221. (* 37: 0, 2, 5, *) ( 3, 0, 8, 1, 2, 10, 4, 9, 5, -1, -1, -1, -1, -1, -1, -1 ),
  222. (* 38: 1, 2, 5, *) ( 5, 2, 10, 5, 4, 2, 4, 0, 2, -1, -1, -1, -1, -1, -1, -1 ),
  223. (* 39: 0, 1, 2, 5, *) ( 2, 10, 5, 3, 2, 5, 3, 5, 4, 3, 4, 8, -1, -1, -1, -1 ),
  224. (* 40: 3, 5, *) ( 9, 5, 4, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ),
  225. (* 41: 0, 3, 5, *) ( 0, 11, 2, 0, 8, 11, 4, 9, 5, -1, -1, -1, -1, -1, -1, -1 ),
  226. (* 42: 1, 3, 5, *) ( 0, 5, 4, 0, 1, 5, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1 ),
  227. (* 43: 0, 1, 3, 5, *) ( 2, 1, 5, 2, 5, 8, 2, 8, 11, 4, 8, 5, -1, -1, -1, -1 ),
  228. (* 44: 2, 3, 5, *) ( 10, 3, 11, 10, 1, 3, 9, 5, 4, -1, -1, -1, -1, -1, -1, -1 ),
  229. (* 45: 0, 2, 3, 5, *) ( 4, 9, 5, 0, 8, 1, 8, 10, 1, 8, 11, 10, -1, -1, -1, -1 ),
  230. (* 46: 1, 2, 3, 5, *) ( 5, 4, 0, 5, 0, 11, 5, 11, 10, 11, 0, 3, -1, -1, -1, -1 ),
  231. (* 47: 0, 1, 2, 3, 5, *) ( 5, 4, 8, 5, 8, 10, 10, 8, 11, -1, -1, -1, -1, -1, -1, -1 ),
  232. (* 48: 4, 5, *) ( 9, 7, 8, 5, 7, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ),
  233. (* 49: 0, 4, 5, *) ( 9, 3, 0, 9, 5, 3, 5, 7, 3, -1, -1, -1, -1, -1, -1, -1 ),
  234. (* 50: 1, 4, 5, *) ( 0, 7, 8, 0, 1, 7, 1, 5, 7, -1, -1, -1, -1, -1, -1, -1 ),
  235. (* 51: 0, 1, 4, 5, *) ( 1, 5, 3, 3, 5, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ),
  236. (* 52: 2, 4, 5, *) ( 9, 7, 8, 9, 5, 7, 10, 1, 2, -1, -1, -1, -1, -1, -1, -1 ),
  237. (* 53: 0, 2, 4, 5, *) ( 10, 1, 2, 9, 5, 0, 5, 3, 0, 5, 7, 3, -1, -1, -1, -1 ),
  238. (* 54: 1, 2, 4, 5, *) ( 8, 0, 2, 8, 2, 5, 8, 5, 7, 10, 5, 2, -1, -1, -1, -1 ),
  239. (* 55: 0, 1, 2, 4, 5, *) ( 2, 10, 5, 2, 5, 3, 3, 5, 7, -1, -1, -1, -1, -1, -1, -1 ),
  240. (* 56: 3, 4, 5, *) ( 7, 9, 5, 7, 8, 9, 3, 11, 2, -1, -1, -1, -1, -1, -1, -1 ),
  241. (* 57: 0, 3, 4, 5, *) ( 9, 5, 7, 9, 7, 2, 9, 2, 0, 2, 7, 11, -1, -1, -1, -1 ),
  242. (* 58: 1, 3, 4, 5, *) ( 2, 3, 11, 0, 1, 8, 1, 7, 8, 1, 5, 7, -1, -1, -1, -1 ),
  243. (* 59: 0, 1, 3, 4, 5, *) ( 11, 2, 1, 11, 1, 7, 7, 1, 5, -1, -1, -1, -1, -1, -1, -1 ),
  244. (* 60: 2, 3, 4, 5, *) ( 9, 5, 8, 8, 5, 7, 10, 1, 3, 10, 3, 11, -1, -1, -1, -1 ),
  245. (* 61: 0, 2, 3, 4, 5, *) ( 5, 7, 0, 5, 0, 9, 7, 11, 0, 1, 0, 10, 11, 10, 0, -1 ),
  246. (* 62: 1, 2, 3, 4, 5, *) ( 11, 10, 0, 11, 0, 3, 10, 5, 0, 8, 0, 7, 5, 7, 0, -1 ),
  247. (* 63: 0, 1, 2, 3, 4, 5, *) ( 11, 10, 5, 7, 11, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ),
  248. (* 64: 6, *) ( 10, 6, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ),
  249. (* 65: 0, 6, *) ( 0, 8, 3, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ),
  250. (* 66: 1, 6, *) ( 9, 0, 1, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ),
  251. (* 67: 0, 1, 6, *) ( 1, 8, 3, 1, 9, 8, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1 ),
  252. (* 68: 2, 6, *) ( 1, 6, 5, 2, 6, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ),
  253. (* 69: 0, 2, 6, *) ( 1, 6, 5, 1, 2, 6, 3, 0, 8, -1, -1, -1, -1, -1, -1, -1 ),
  254. (* 70: 1, 2, 6, *) ( 9, 6, 5, 9, 0, 6, 0, 2, 6, -1, -1, -1, -1, -1, -1, -1 ),
  255. (* 71: 0, 1, 2, 6, *) ( 5, 9, 8, 5, 8, 2, 5, 2, 6, 3, 2, 8, -1, -1, -1, -1 ),
  256. (* 72: 3, 6, *) ( 2, 3, 11, 10, 6, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ),
  257. (* 73: 0, 3, 6, *) ( 11, 0, 8, 11, 2, 0, 10, 6, 5, -1, -1, -1, -1, -1, -1, -1 ),
  258. (* 74: 1, 3, 6, *) ( 0, 1, 9, 2, 3, 11, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1 ),
  259. (* 75: 0, 1, 3, 6, *) ( 5, 10, 6, 1, 9, 2, 9, 11, 2, 9, 8, 11, -1, -1, -1, -1 ),
  260. (* 76: 2, 3, 6, *) ( 6, 3, 11, 6, 5, 3, 5, 1, 3, -1, -1, -1, -1, -1, -1, -1 ),
  261. (* 77: 0, 2, 3, 6, *) ( 0, 8, 11, 0, 11, 5, 0, 5, 1, 5, 11, 6, -1, -1, -1, -1 ),
  262. (* 78: 1, 2, 3, 6, *) ( 3, 11, 6, 0, 3, 6, 0, 6, 5, 0, 5, 9, -1, -1, -1, -1 ),
  263. (* 79: 0, 1, 2, 3, 6, *) ( 6, 5, 9, 6, 9, 11, 11, 9, 8, -1, -1, -1, -1, -1, -1, -1 ),
  264. (* 80: 4, 6, *) ( 5, 10, 6, 4, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ),
  265. (* 81: 0, 4, 6, *) ( 4, 3, 0, 4, 7, 3, 6, 5, 10, -1, -1, -1, -1, -1, -1, -1 ),
  266. (* 82: 1, 4, 6, *) ( 1, 9, 0, 5, 10, 6, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1 ),
  267. (* 83: 0, 1, 4, 6, *) ( 10, 6, 5, 1, 9, 7, 1, 7, 3, 7, 9, 4, -1, -1, -1, -1 ),
  268. (* 84: 2, 4, 6, *) ( 6, 1, 2, 6, 5, 1, 4, 7, 8, -1, -1, -1, -1, -1, -1, -1 ),
  269. (* 85: 0, 2, 4, 6, *) ( 1, 2, 5, 5, 2, 6, 3, 0, 4, 3, 4, 7, -1, -1, -1, -1 ),
  270. (* 86: 1, 2, 4, 6, *) ( 8, 4, 7, 9, 0, 5, 0, 6, 5, 0, 2, 6, -1, -1, -1, -1 ),
  271. (* 87: 0, 1, 2, 4, 6, *) ( 7, 3, 9, 7, 9, 4, 3, 2, 9, 5, 9, 6, 2, 6, 9, -1 ),
  272. (* 88: 3, 4, 6, *) ( 3, 11, 2, 7, 8, 4, 10, 6, 5, -1, -1, -1, -1, -1, -1, -1 ),
  273. (* 89: 0, 3, 4, 6, *) ( 5, 10, 6, 4, 7, 2, 4, 2, 0, 2, 7, 11, -1, -1, -1, -1 ),
  274. (* 90: 1, 3, 4, 6, *) ( 0, 1, 9, 4, 7, 8, 2, 3, 11, 5, 10, 6, -1, -1, -1, -1 ),
  275. (* 91: 0, 1, 3, 4, 6, *) ( 9, 2, 1, 9, 11, 2, 9, 4, 11, 7, 11, 4, 5, 10, 6, -1 ),
  276. (* 92: 2, 3, 4, 6, *) ( 8, 4, 7, 3, 11, 5, 3, 5, 1, 5, 11, 6, -1, -1, -1, -1 ),
  277. (* 93: 0, 2, 3, 4, 6, *) ( 5, 1, 11, 5, 11, 6, 1, 0, 11, 7, 11, 4, 0, 4, 11, -1 ),
  278. (* 94: 1, 2, 3, 4, 6, *) ( 0, 5, 9, 0, 6, 5, 0, 3, 6, 11, 6, 3, 8, 4, 7, -1 ),
  279. (* 95: 0, 1, 2, 3, 4, 6, *) ( 6, 5, 9, 6, 9, 11, 4, 7, 9, 7, 11, 9, -1, -1, -1, -1 ),
  280. (* 96: 5, 6, *) ( 10, 4, 9, 6, 4, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ),
  281. (* 97: 0, 5, 6, *) ( 4, 10, 6, 4, 9, 10, 0, 8, 3, -1, -1, -1, -1, -1, -1, -1 ),
  282. (* 98: 1, 5, 6, *) ( 10, 0, 1, 10, 6, 0, 6, 4, 0, -1, -1, -1, -1, -1, -1, -1 ),
  283. (* 99: 0, 1, 5, 6, *) ( 8, 3, 1, 8, 1, 6, 8, 6, 4, 6, 1, 10, -1, -1, -1, -1 ),
  284. (* 100: 2, 5, 6, *) ( 1, 4, 9, 1, 2, 4, 2, 6, 4, -1, -1, -1, -1, -1, -1, -1 ),
  285. (* 101: 0, 2, 5, 6, *) ( 3, 0, 8, 1, 2, 9, 2, 4, 9, 2, 6, 4, -1, -1, -1, -1 ),
  286. (* 102: 1, 2, 5, 6, *) ( 0, 2, 4, 4, 2, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ),
  287. (* 103: 0, 1, 2, 5, 6, *) ( 8, 3, 2, 8, 2, 4, 4, 2, 6, -1, -1, -1, -1, -1, -1, -1 ),
  288. (* 104: 3, 5, 6, *) ( 10, 4, 9, 10, 6, 4, 11, 2, 3, -1, -1, -1, -1, -1, -1, -1 ),
  289. (* 105: 0, 3, 5, 6, *) ( 0, 8, 2, 2, 8, 11, 4, 9, 10, 4, 10, 6, -1, -1, -1, -1 ),
  290. (* 106: 1, 3, 5, 6, *) ( 3, 11, 2, 0, 1, 6, 0, 6, 4, 6, 1, 10, -1, -1, -1, -1 ),
  291. (* 107: 0, 1, 3, 5, 6, *) ( 6, 4, 1, 6, 1, 10, 4, 8, 1, 2, 1, 11, 8, 11, 1, -1 ),
  292. (* 108: 2, 3, 5, 6, *) ( 9, 6, 4, 9, 3, 6, 9, 1, 3, 11, 6, 3, -1, -1, -1, -1 ),
  293. (* 109: 0, 2, 3, 5, 6, *) ( 8, 11, 1, 8, 1, 0, 11, 6, 1, 9, 1, 4, 6, 4, 1, -1 ),
  294. (* 110: 1, 2, 3, 5, 6, *) ( 3, 11, 6, 3, 6, 0, 0, 6, 4, -1, -1, -1, -1, -1, -1, -1 ),
  295. (* 111: 0, 1, 2, 3, 5, 6, *) ( 6, 4, 8, 11, 6, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ),
  296. (* 112: 4, 5, 6, *) ( 7, 10, 6, 7, 8, 10, 8, 9, 10, -1, -1, -1, -1, -1, -1, -1 ),
  297. (* 113: 0, 4, 5, 6, *) ( 0, 7, 3, 0, 10, 7, 0, 9, 10, 6, 7, 10, -1, -1, -1, -1 ),
  298. (* 114: 1, 4, 5, 6, *) ( 10, 6, 7, 1, 10, 7, 1, 7, 8, 1, 8, 0, -1, -1, -1, -1 ),
  299. (* 115: 0, 1, 4, 5, 6, *) ( 10, 6, 7, 10, 7, 1, 1, 7, 3, -1, -1, -1, -1, -1, -1, -1 ),
  300. (* 116: 2, 4, 5, 6, *) ( 1, 2, 6, 1, 6, 8, 1, 8, 9, 8, 6, 7, -1, -1, -1, -1 ),
  301. (* 117: 0, 2, 4, 5, 6, *) ( 2, 6, 9, 2, 9, 1, 6, 7, 9, 0, 9, 3, 7, 3, 9, -1 ),
  302. (* 118: 1, 2, 4, 5, 6, *) ( 7, 8, 0, 7, 0, 6, 6, 0, 2, -1, -1, -1, -1, -1, -1, -1 ),
  303. (* 119: 0, 1, 2, 4, 5, 6, *) ( 7, 3, 2, 6, 7, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ),
  304. (* 120: 3, 4, 5, 6, *) ( 2, 3, 11, 10, 6, 8, 10, 8, 9, 8, 6, 7, -1, -1, -1, -1 ),
  305. (* 121: 0, 3, 4, 5, 6, *) ( 2, 0, 7, 2, 7, 11, 0, 9, 7, 6, 7, 10, 9, 10, 7, -1 ),
  306. (* 122: 1, 3, 4, 5, 6, *) ( 1, 8, 0, 1, 7, 8, 1, 10, 7, 6, 7, 10, 2, 3, 11, -1 ),
  307. (* 123: 0, 1, 3, 4, 5, 6, *) ( 11, 2, 1, 11, 1, 7, 10, 6, 1, 6, 7, 1, -1, -1, -1, -1 ),
  308. (* 124: 2, 3, 4, 5, 6, *) ( 8, 9, 6, 8, 6, 7, 9, 1, 6, 11, 6, 3, 1, 3, 6, -1 ),
  309. (* 125: 0, 2, 3, 4, 5, 6, *) ( 0, 9, 1, 11, 6, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ),
  310. (* 126: 1, 2, 3, 4, 5, 6, *) ( 7, 8, 0, 7, 0, 6, 3, 11, 0, 11, 6, 0, -1, -1, -1, -1 ),
  311. (* 127: 0, 1, 2, 3, 4, 5, 6, *) ( 7, 11, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ),
  312. (* 128: 7, *) ( 7, 6, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ),
  313. (* 129: 0, 7, *) ( 3, 0, 8, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ),
  314. (* 130: 1, 7, *) ( 0, 1, 9, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ),
  315. (* 131: 0, 1, 7, *) ( 8, 1, 9, 8, 3, 1, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1 ),
  316. (* 132: 2, 7, *) ( 10, 1, 2, 6, 11, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ),
  317. (* 133: 0, 2, 7, *) ( 1, 2, 10, 3, 0, 8, 6, 11, 7, -1, -1, -1, -1, -1, -1, -1 ),
  318. (* 134: 1, 2, 7, *) ( 2, 9, 0, 2, 10, 9, 6, 11, 7, -1, -1, -1, -1, -1, -1, -1 ),
  319. (* 135: 0, 1, 2, 7, *) ( 6, 11, 7, 2, 10, 3, 10, 8, 3, 10, 9, 8, -1, -1, -1, -1 ),
  320. (* 136: 3, 7, *) ( 7, 2, 3, 6, 2, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ),
  321. (* 137: 0, 3, 7, *) ( 7, 0, 8, 7, 6, 0, 6, 2, 0, -1, -1, -1, -1, -1, -1, -1 ),
  322. (* 138: 1, 3, 7, *) ( 2, 7, 6, 2, 3, 7, 0, 1, 9, -1, -1, -1, -1, -1, -1, -1 ),
  323. (* 139: 0, 1, 3, 7, *) ( 1, 6, 2, 1, 8, 6, 1, 9, 8, 8, 7, 6, -1, -1, -1, -1 ),
  324. (* 140: 2, 3, 7, *) ( 10, 7, 6, 10, 1, 7, 1, 3, 7, -1, -1, -1, -1, -1, -1, -1 ),
  325. (* 141: 0, 2, 3, 7, *) ( 10, 7, 6, 1, 7, 10, 1, 8, 7, 1, 0, 8, -1, -1, -1, -1 ),
  326. (* 142: 1, 2, 3, 7, *) ( 0, 3, 7, 0, 7, 10, 0, 10, 9, 6, 10, 7, -1, -1, -1, -1 ),
  327. (* 143: 0, 1, 2, 3, 7, *) ( 7, 6, 10, 7, 10, 8, 8, 10, 9, -1, -1, -1, -1, -1, -1, -1 ),
  328. (* 144: 4, 7, *) ( 6, 8, 4, 11, 8, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ),
  329. (* 145: 0, 4, 7, *) ( 3, 6, 11, 3, 0, 6, 0, 4, 6, -1, -1, -1, -1, -1, -1, -1 ),
  330. (* 146: 1, 4, 7, *) ( 8, 6, 11, 8, 4, 6, 9, 0, 1, -1, -1, -1, -1, -1, -1, -1 ),
  331. (* 147: 0, 1, 4, 7, *) ( 9, 4, 6, 9, 6, 3, 9, 3, 1, 11, 3, 6, -1, -1, -1, -1 ),
  332. (* 148: 2, 4, 7, *) ( 6, 8, 4, 6, 11, 8, 2, 10, 1, -1, -1, -1, -1, -1, -1, -1 ),
  333. (* 149: 0, 2, 4, 7, *) ( 1, 2, 10, 3, 0, 11, 0, 6, 11, 0, 4, 6, -1, -1, -1, -1 ),
  334. (* 150: 1, 2, 4, 7, *) ( 4, 11, 8, 4, 6, 11, 0, 2, 9, 2, 10, 9, -1, -1, -1, -1 ),
  335. (* 151: 0, 1, 2, 4, 7, *) ( 10, 9, 3, 10, 3, 2, 9, 4, 3, 11, 3, 6, 4, 6, 3, -1 ),
  336. (* 152: 3, 4, 7, *) ( 8, 2, 3, 8, 4, 2, 4, 6, 2, -1, -1, -1, -1, -1, -1, -1 ),
  337. (* 153: 0, 3, 4, 7, *) ( 0, 4, 2, 4, 6, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ),
  338. (* 154: 1, 3, 4, 7, *) ( 1, 9, 0, 2, 3, 4, 2, 4, 6, 4, 3, 8, -1, -1, -1, -1 ),
  339. (* 155: 0, 1, 3, 4, 7, *) ( 1, 9, 4, 1, 4, 2, 2, 4, 6, -1, -1, -1, -1, -1, -1, -1 ),
  340. (* 156: 2, 3, 4, 7, *) ( 8, 1, 3, 8, 6, 1, 8, 4, 6, 6, 10, 1, -1, -1, -1, -1 ),
  341. (* 157: 0, 2, 3, 4, 7, *) ( 10, 1, 0, 10, 0, 6, 6, 0, 4, -1, -1, -1, -1, -1, -1, -1 ),
  342. (* 158: 1, 2, 3, 4, 7, *) ( 4, 6, 3, 4, 3, 8, 6, 10, 3, 0, 3, 9, 10, 9, 3, -1 ),
  343. (* 159: 0, 1, 2, 3, 4, 7, *) ( 10, 9, 4, 6, 10, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ),
  344. (* 160: 5, 7, *) ( 4, 9, 5, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ),
  345. (* 161: 0, 5, 7, *) ( 0, 8, 3, 4, 9, 5, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1 ),
  346. (* 162: 1, 5, 7, *) ( 5, 0, 1, 5, 4, 0, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1 ),
  347. (* 163: 0, 1, 5, 7, *) ( 11, 7, 6, 8, 3, 4, 3, 5, 4, 3, 1, 5, -1, -1, -1, -1 ),
  348. (* 164: 2, 5, 7, *) ( 9, 5, 4, 10, 1, 2, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1 ),
  349. (* 165: 0, 2, 5, 7, *) ( 6, 11, 7, 1, 2, 10, 0, 8, 3, 4, 9, 5, -1, -1, -1, -1 ),
  350. (* 166: 1, 2, 5, 7, *) ( 7, 6, 11, 5, 4, 10, 4, 2, 10, 4, 0, 2, -1, -1, -1, -1 ),
  351. (* 167: 0, 1, 2, 5, 7, *) ( 3, 4, 8, 3, 5, 4, 3, 2, 5, 10, 5, 2, 11, 7, 6, -1 ),
  352. (* 168: 3, 5, 7, *) ( 7, 2, 3, 7, 6, 2, 5, 4, 9, -1, -1, -1, -1, -1, -1, -1 ),
  353. (* 169: 0, 3, 5, 7, *) ( 9, 5, 4, 0, 8, 6, 0, 6, 2, 6, 8, 7, -1, -1, -1, -1 ),
  354. (* 170: 1, 3, 5, 7, *) ( 3, 6, 2, 3, 7, 6, 1, 5, 0, 5, 4, 0, -1, -1, -1, -1 ),
  355. (* 171: 0, 1, 3, 5, 7, *) ( 6, 2, 8, 6, 8, 7, 2, 1, 8, 4, 8, 5, 1, 5, 8, -1 ),
  356. (* 172: 2, 3, 5, 7, *) ( 9, 5, 4, 10, 1, 6, 1, 7, 6, 1, 3, 7, -1, -1, -1, -1 ),
  357. (* 173: 0, 2, 3, 5, 7, *) ( 1, 6, 10, 1, 7, 6, 1, 0, 7, 8, 7, 0, 9, 5, 4, -1 ),
  358. (* 174: 1, 2, 3, 5, 7, *) ( 4, 0, 10, 4, 10, 5, 0, 3, 10, 6, 10, 7, 3, 7, 10, -1 ),
  359. (* 175: 0, 1, 2, 3, 5, 7, *) ( 7, 6, 10, 7, 10, 8, 5, 4, 10, 4, 8, 10, -1, -1, -1, -1 ),
  360. (* 176: 4, 5, 7, *) ( 6, 9, 5, 6, 11, 9, 11, 8, 9, -1, -1, -1, -1, -1, -1, -1 ),
  361. (* 177: 0, 4, 5, 7, *) ( 3, 6, 11, 0, 6, 3, 0, 5, 6, 0, 9, 5, -1, -1, -1, -1 ),
  362. (* 178: 1, 4, 5, 7, *) ( 0, 11, 8, 0, 5, 11, 0, 1, 5, 5, 6, 11, -1, -1, -1, -1 ),
  363. (* 179: 0, 1, 4, 5, 7, *) ( 6, 11, 3, 6, 3, 5, 5, 3, 1, -1, -1, -1, -1, -1, -1, -1 ),
  364. (* 180: 2, 4, 5, 7, *) ( 1, 2, 10, 9, 5, 11, 9, 11, 8, 11, 5, 6, -1, -1, -1, -1 ),
  365. (* 181: 0, 2, 4, 5, 7, *) ( 0, 11, 3, 0, 6, 11, 0, 9, 6, 5, 6, 9, 1, 2, 10, -1 ),
  366. (* 182: 1, 2, 4, 5, 7, *) ( 11, 8, 5, 11, 5, 6, 8, 0, 5, 10, 5, 2, 0, 2, 5, -1 ),
  367. (* 183: 0, 1, 2, 4, 5, 7, *) ( 6, 11, 3, 6, 3, 5, 2, 10, 3, 10, 5, 3, -1, -1, -1, -1 ),
  368. (* 184: 3, 4, 5, 7, *) ( 5, 8, 9, 5, 2, 8, 5, 6, 2, 3, 8, 2, -1, -1, -1, -1 ),
  369. (* 185: 0, 3, 4, 5, 7, *) ( 9, 5, 6, 9, 6, 0, 0, 6, 2, -1, -1, -1, -1, -1, -1, -1 ),
  370. (* 186: 1, 3, 4, 5, 7, *) ( 1, 5, 8, 1, 8, 0, 5, 6, 8, 3, 8, 2, 6, 2, 8, -1 ),
  371. (* 187: 0, 1, 3, 4, 5, 7, *) ( 1, 5, 6, 2, 1, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ),
  372. (* 188: 2, 3, 4, 5, 7, *) ( 1, 3, 6, 1, 6, 10, 3, 8, 6, 5, 6, 9, 8, 9, 6, -1 ),
  373. (* 189: 0, 2, 3, 4, 5, 7, *) ( 10, 1, 0, 10, 0, 6, 9, 5, 0, 5, 6, 0, -1, -1, -1, -1 ),
  374. (* 190: 1, 2, 3, 4, 5, 7, *) ( 0, 3, 8, 5, 6, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ),
  375. (* 191: 0, 1, 2, 3, 4, 5, 7, *) ( 10, 5, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ),
  376. (* 192: 6, 7, *) ( 11, 5, 10, 7, 5, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ),
  377. (* 193: 0, 6, 7, *) ( 11, 5, 10, 11, 7, 5, 8, 3, 0, -1, -1, -1, -1, -1, -1, -1 ),
  378. (* 194: 1, 6, 7, *) ( 5, 11, 7, 5, 10, 11, 1, 9, 0, -1, -1, -1, -1, -1, -1, -1 ),
  379. (* 195: 0, 1, 6, 7, *) ( 10, 7, 5, 10, 11, 7, 9, 8, 1, 8, 3, 1, -1, -1, -1, -1 ),
  380. (* 196: 2, 6, 7, *) ( 11, 1, 2, 11, 7, 1, 7, 5, 1, -1, -1, -1, -1, -1, -1, -1 ),
  381. (* 197: 0, 2, 6, 7, *) ( 0, 8, 3, 1, 2, 7, 1, 7, 5, 7, 2, 11, -1, -1, -1, -1 ),
  382. (* 198: 1, 2, 6, 7, *) ( 9, 7, 5, 9, 2, 7, 9, 0, 2, 2, 11, 7, -1, -1, -1, -1 ),
  383. (* 199: 0, 1, 2, 6, 7, *) ( 7, 5, 2, 7, 2, 11, 5, 9, 2, 3, 2, 8, 9, 8, 2, -1 ),
  384. (* 200: 3, 6, 7, *) ( 2, 5, 10, 2, 3, 5, 3, 7, 5, -1, -1, -1, -1, -1, -1, -1 ),
  385. (* 201: 0, 3, 6, 7, *) ( 8, 2, 0, 8, 5, 2, 8, 7, 5, 10, 2, 5, -1, -1, -1, -1 ),
  386. (* 202: 1, 3, 6, 7, *) ( 9, 0, 1, 5, 10, 3, 5, 3, 7, 3, 10, 2, -1, -1, -1, -1 ),
  387. (* 203: 0, 1, 3, 6, 7, *) ( 9, 8, 2, 9, 2, 1, 8, 7, 2, 10, 2, 5, 7, 5, 2, -1 ),
  388. (* 204: 2, 3, 6, 7, *) ( 1, 3, 5, 3, 7, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ),
  389. (* 205: 0, 2, 3, 6, 7, *) ( 0, 8, 7, 0, 7, 1, 1, 7, 5, -1, -1, -1, -1, -1, -1, -1 ),
  390. (* 206: 1, 2, 3, 6, 7, *) ( 9, 0, 3, 9, 3, 5, 5, 3, 7, -1, -1, -1, -1, -1, -1, -1 ),
  391. (* 207: 0, 1, 2, 3, 6, 7, *) ( 9, 8, 7, 5, 9, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ),
  392. (* 208: 4, 6, 7, *) ( 5, 8, 4, 5, 10, 8, 10, 11, 8, -1, -1, -1, -1, -1, -1, -1 ),
  393. (* 209: 0, 4, 6, 7, *) ( 5, 0, 4, 5, 11, 0, 5, 10, 11, 11, 3, 0, -1, -1, -1, -1 ),
  394. (* 210: 1, 4, 6, 7, *) ( 0, 1, 9, 8, 4, 10, 8, 10, 11, 10, 4, 5, -1, -1, -1, -1 ),
  395. (* 211: 0, 1, 4, 6, 7, *) ( 10, 11, 4, 10, 4, 5, 11, 3, 4, 9, 4, 1, 3, 1, 4, -1 ),
  396. (* 212: 2, 4, 6, 7, *) ( 2, 5, 1, 2, 8, 5, 2, 11, 8, 4, 5, 8, -1, -1, -1, -1 ),
  397. (* 213: 0, 2, 4, 6, 7, *) ( 0, 4, 11, 0, 11, 3, 4, 5, 11, 2, 11, 1, 5, 1, 11, -1 ),
  398. (* 214: 1, 2, 4, 6, 7, *) ( 0, 2, 5, 0, 5, 9, 2, 11, 5, 4, 5, 8, 11, 8, 5, -1 ),
  399. (* 215: 0, 1, 2, 4, 6, 7, *) ( 9, 4, 5, 2, 11, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ),
  400. (* 216: 3, 4, 6, 7, *) ( 2, 5, 10, 3, 5, 2, 3, 4, 5, 3, 8, 4, -1, -1, -1, -1 ),
  401. (* 217: 0, 3, 4, 6, 7, *) ( 5, 10, 2, 5, 2, 4, 4, 2, 0, -1, -1, -1, -1, -1, -1, -1 ),
  402. (* 218: 1, 3, 4, 6, 7, *) ( 3, 10, 2, 3, 5, 10, 3, 8, 5, 4, 5, 8, 0, 1, 9, -1 ),
  403. (* 219: 0, 1, 3, 4, 6, 7, *) ( 5, 10, 2, 5, 2, 4, 1, 9, 2, 9, 4, 2, -1, -1, -1, -1 ),
  404. (* 220: 2, 3, 4, 6, 7, *) ( 8, 4, 5, 8, 5, 3, 3, 5, 1, -1, -1, -1, -1, -1, -1, -1 ),
  405. (* 221: 0, 2, 3, 4, 6, 7, *) ( 0, 4, 5, 1, 0, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ),
  406. (* 222: 1, 2, 3, 4, 6, 7, *) ( 8, 4, 5, 8, 5, 3, 9, 0, 5, 0, 3, 5, -1, -1, -1, -1 ),
  407. (* 223: 0, 1, 2, 3, 4, 6, 7, *) ( 9, 4, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ),
  408. (* 224: 5, 6, 7, *) ( 4, 11, 7, 4, 9, 11, 9, 10, 11, -1, -1, -1, -1, -1, -1, -1 ),
  409. (* 225: 0, 5, 6, 7, *) ( 0, 8, 3, 4, 9, 7, 9, 11, 7, 9, 10, 11, -1, -1, -1, -1 ),
  410. (* 226: 1, 5, 6, 7, *) ( 1, 10, 11, 1, 11, 4, 1, 4, 0, 7, 4, 11, -1, -1, -1, -1 ),
  411. (* 227: 0, 1, 5, 6, 7, *) ( 3, 1, 4, 3, 4, 8, 1, 10, 4, 7, 4, 11, 10, 11, 4, -1 ),
  412. (* 228: 2, 5, 6, 7, *) ( 4, 11, 7, 9, 11, 4, 9, 2, 11, 9, 1, 2, -1, -1, -1, -1 ),
  413. (* 229: 0, 2, 5, 6, 7, *) ( 9, 7, 4, 9, 11, 7, 9, 1, 11, 2, 11, 1, 0, 8, 3, -1 ),
  414. (* 230: 1, 2, 5, 6, 7, *) ( 11, 7, 4, 11, 4, 2, 2, 4, 0, -1, -1, -1, -1, -1, -1, -1 ),
  415. (* 231: 0, 1, 2, 5, 6, 7, *) ( 11, 7, 4, 11, 4, 2, 8, 3, 4, 3, 2, 4, -1, -1, -1, -1 ),
  416. (* 232: 3, 5, 6, 7, *) ( 2, 9, 10, 2, 7, 9, 2, 3, 7, 7, 4, 9, -1, -1, -1, -1 ),
  417. (* 233: 0, 3, 5, 6, 7, *) ( 9, 10, 7, 9, 7, 4, 10, 2, 7, 8, 7, 0, 2, 0, 7, -1 ),
  418. (* 234: 1, 3, 5, 6, 7, *) ( 3, 7, 10, 3, 10, 2, 7, 4, 10, 1, 10, 0, 4, 0, 10, -1 ),
  419. (* 235: 0, 1, 3, 5, 6, 7, *) ( 1, 10, 2, 8, 7, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ),
  420. (* 236: 2, 3, 5, 6, 7, *) ( 4, 9, 1, 4, 1, 7, 7, 1, 3, -1, -1, -1, -1, -1, -1, -1 ),
  421. (* 237: 0, 2, 3, 5, 6, 7, *) ( 4, 9, 1, 4, 1, 7, 0, 8, 1, 8, 7, 1, -1, -1, -1, -1 ),
  422. (* 238: 1, 2, 3, 5, 6, 7, *) ( 4, 0, 3, 7, 4, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ),
  423. (* 239: 0, 1, 2, 3, 5, 6, 7, *) ( 4, 8, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ),
  424. (* 240: 4, 5, 6, 7, *) ( 9, 10, 8, 10, 11, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ),
  425. (* 241: 0, 4, 5, 6, 7, *) ( 3, 0, 9, 3, 9, 11, 11, 9, 10, -1, -1, -1, -1, -1, -1, -1 ),
  426. (* 242: 1, 4, 5, 6, 7, *) ( 0, 1, 10, 0, 10, 8, 8, 10, 11, -1, -1, -1, -1, -1, -1, -1 ),
  427. (* 243: 0, 1, 4, 5, 6, 7, *) ( 3, 1, 10, 11, 3, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ),
  428. (* 244: 2, 4, 5, 6, 7, *) ( 1, 2, 11, 1, 11, 9, 9, 11, 8, -1, -1, -1, -1, -1, -1, -1 ),
  429. (* 245: 0, 2, 4, 5, 6, 7, *) ( 3, 0, 9, 3, 9, 11, 1, 2, 9, 2, 11, 9, -1, -1, -1, -1 ),
  430. (* 246: 1, 2, 4, 5, 6, 7, *) ( 0, 2, 11, 8, 0, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ),
  431. (* 247: 0, 1, 2, 4, 5, 6, 7, *) ( 3, 2, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ),
  432. (* 248: 3, 4, 5, 6, 7, *) ( 2, 3, 8, 2, 8, 10, 10, 8, 9, -1, -1, -1, -1, -1, -1, -1 ),
  433. (* 249: 0, 3, 4, 5, 6, 7, *) ( 9, 10, 2, 0, 9, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ),
  434. (* 250: 1, 3, 4, 5, 6, 7, *) ( 2, 3, 8, 2, 8, 10, 0, 1, 8, 1, 10, 8, -1, -1, -1, -1 ),
  435. (* 251: 0, 1, 3, 4, 5, 6, 7, *) ( 1, 10, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ),
  436. (* 252: 2, 3, 4, 5, 6, 7, *) ( 1, 3, 8, 9, 1, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ),
  437. (* 253: 0, 2, 3, 4, 5, 6, 7, *) ( 0, 9, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ),
  438. (* 254: 1, 2, 3, 4, 5, 6, 7, *) ( 0, 3, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ),
  439. (* 255: 0, 1, 2, 3, 4, 5, 6, 7, *) ( -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 )
  440. );
  441. // Marching Cube EdgeTable
  442. const
  443. MC_EDGETABLE: array [0 .. 11, 0 .. 1] of Integer = ((0, 1), (1, 2), (2, 3),
  444. (3, 0), (4, 5), (5, 6), (6, 7), (7, 4), (0, 4), (1, 5), (2, 6), (3, 7));
  445. // Marching Tetrahedra TriTable
  446. (*
  447. + 0
  448. /|\
  449. / | \
  450. / | 0
  451. 3 | \
  452. / 2 \
  453. / | \
  454. +----4--------+ 1
  455. 3 \ | /
  456. \ | /
  457. 5 | 1
  458. \ | /
  459. \ | /
  460. \|/
  461. + 2
  462. *)
  463. MT_TRITABLE: array [0 .. 15, 0 .. 6] of Integer =
  464. ((-1, -1, -1, -1, -1, -1, -1), (2, 3, 0, -1, -1, -1, -1),
  465. (4, 1, 0, -1, -1, -1, -1), (2, 4, 1, 3, 4, 2, -1),
  466. (5, 2, 1, -1, -1, -1, -1), (5, 3, 0, 1, 5, 0, -1), (5, 2, 0, 4, 5, 0, -1),
  467. (3, 4, 5, -1, -1, -1, -1), (5, 4, 3, -1, -1, -1, -1),
  468. (0, 5, 4, 0, 2, 5, -1), (0, 5, 1, 0, 3, 5, -1), (1, 2, 5, -1, -1, -1, -1),
  469. (2, 4, 3, 1, 4, 2, -1), (0, 1, 4, -1, -1, -1, -1),
  470. (0, 3, 2, -1, -1, -1, -1), (-1, -1, -1, -1, -1, -1, -1));
  471. // Marching Tetrahedra EdgeTable
  472. MT_EDGETABLE: array [0 .. 5, 0 .. 1] of Integer = ((0, 1), (1, 2), (2, 0),
  473. (0, 3), (1, 3), (2, 3));
  474. // Marching Tetrahedra CubeSplit
  475. MT_CUBESPLIT: array [0 .. 5, 0 .. 3] of Integer = ((0, 5, 1, 6), (0, 1, 2, 6),
  476. (0, 2, 3, 6), (0, 3, 7, 6), (0, 7, 4, 6), (0, 4, 5, 6));
  477. // Test surface functions
  478. function SFSphere(X, Y, Z: Extended): TScalarValue;
  479. begin
  480. Result := sqr(X) + sqr(Y) + sqr(Z)
  481. end;
  482. function SFToroidal(X, Y, Z: Extended): TScalarValue;
  483. const
  484. FScale = 7;
  485. a = 2.5;
  486. begin
  487. X := FScale * X;
  488. Y := FScale * Y;
  489. Z := FScale * Z;
  490. Result := (sqr(sqrt(sqr(X) + sqr(Y)) - a) + sqr(Z)) *
  491. (sqr(sqrt(sqr(Y) + sqr(Z)) - a) + sqr(X)) *
  492. (sqr(sqrt(sqr(Z) + sqr(X)) - a) + sqr(Y));
  493. end;
  494. function SFDoubleTorus(X, Y, Z: Extended): TScalarValue;
  495. const
  496. FScale = 2.25;
  497. begin
  498. X := FScale * X;
  499. Y := FScale * Y;
  500. Z := FScale * Z;
  501. Result := PowerInteger(X, 8) + PowerInteger(X, 4) - 2 * PowerInteger(X, 6) - 2
  502. * sqr(X) * sqr(Y) + 2 * PowerInteger(X, 4) * sqr(Y) +
  503. PowerInteger(Y, 4) + sqr(Z)
  504. end;
  505. function SFChmutov1(X, Y, Z: Extended): TScalarValue;
  506. const
  507. FScale = 2.5;
  508. begin
  509. X := FScale * X;
  510. Y := FScale * Y;
  511. Z := FScale * Z;
  512. Result := 8 * (sqr(X) + sqr(Y) + sqr(Z)) - 8 *
  513. (PowerInteger(X, 4) + PowerInteger(Y, 4) + PowerInteger(Z, 4));
  514. end;
  515. function SFChmutov2(X, Y, Z: Extended): TScalarValue;
  516. const
  517. FScale = 2.5;
  518. begin
  519. X := FScale * X;
  520. Y := FScale * Y;
  521. Z := FScale * Z;
  522. Result := 2 * (sqr(X) * sqr(3 - 4 * sqr(X)) + sqr(Y) * sqr(3 - 4 * sqr(Y)) +
  523. sqr(Z) * sqr(3 - 4 * sqr(Z)));
  524. end;
  525. function SFKleinBottle(X, Y, Z: Extended): TScalarValue;
  526. const
  527. FScale = 7.5;
  528. begin
  529. X := FScale * X;
  530. Y := FScale * Y;
  531. Z := FScale * Z;
  532. Result := (sqr(X) + sqr(Y) + sqr(Z) + 2 * Y - 1) *
  533. (sqr(sqr(X) + sqr(Y) + sqr(Z) - 2 * Y - 1) - 8 * sqr(Z)) + 16 * X * Z *
  534. (sqr(X) + sqr(Y) + sqr(Z) - 2 * Y - 1);
  535. end;
  536. function SFMinkowski(X, Y, Z: Extended): TScalarValue;
  537. const
  538. FScale = 7;
  539. begin
  540. X := FScale * X;
  541. Y := FScale * Y;
  542. Z := FScale * Z;
  543. Result := (sqr(X) - sqr(Y) - sqr(Z) - 2) * (sqr(X) - sqr(Y) - sqr(Z) + 2) *
  544. (sqr(X) - sqr(Y) - sqr(Z) - 4) * (sqr(X) - sqr(Y) - sqr(Z) + 4) *
  545. (sqr(X) - sqr(Y) - sqr(Z));
  546. end;
  547. (* -------------------------------------------------------------------------
  548. Class IsoSurfaceExtractor
  549. Purpose: Extract an Isosurface from volume dataset for given Isovalue
  550. ------------------------------------------------------------------------- *)
  551. function TGLIsoSurfaceExtractor.BuildIndex(var ADatavals: array of Single;
  552. Isovalue: Single): word;
  553. var
  554. i: Integer;
  555. val: word;
  556. begin
  557. val := 1;
  558. Result := 0;
  559. for i := 1 to Length(ADatavals) do
  560. begin
  561. if ADatavals[i - 1] <= Isovalue then // Edge inside surface
  562. Result := Result + val;
  563. val := val * 2;
  564. end;
  565. end;
  566. // Compute intersection point of edge and surface by linear interpolation
  567. function InterpolateRugged(V0, V1: TAffineVector;
  568. var Val0, Val1, Isovalue: Single): TVertex;
  569. var
  570. Diff: Single;
  571. i: Integer;
  572. begin
  573. if Val0 <= Isovalue then
  574. begin
  575. Diff := Val0 / (Val0 + Val1);
  576. for i := 0 to 2 do
  577. Result.V[i] := V0.V[i] + Diff * (V1.V[i] - V0.V[i]);
  578. end
  579. else
  580. begin
  581. Diff := Val1 / (Val0 + Val1);
  582. for i := 0 to 2 do
  583. Result.V[i] := V1.V[i] + Diff * (V0.V[i] - V1.V[i]);
  584. end;
  585. end;
  586. function InterpolatePolished(V0, V1: TAffineVector;
  587. var Val0, Val1, Isovalue: Single): TVertex;
  588. var
  589. w0, w1: Single;
  590. begin
  591. if (Val0 = Val1) then
  592. w1 := 0.5
  593. else
  594. w1 := (Isovalue - Val0) / (Val1 - Val0);
  595. w0 := 1.0 - w1;
  596. Result.X := w0 * V0.X + w1 * V1.X;
  597. Result.Y := w0 * V0.Y + w1 * V1.Y;
  598. Result.Z := w0 * V0.Z + w1 * V1.Z;
  599. end;
  600. //------------------------------------------------------------------
  601. function TGLIsoSurfaceExtractor.Interpolate(const V0, V1: TAffineVector;
  602. var Val0, Val1, Isovalue: Single; isPolished: boolean): TVertex;
  603. begin
  604. if isPolished then
  605. Result := InterpolatePolished(V0, V1, Val0, Val1, Isovalue)
  606. else
  607. Result := InterpolateRugged(V0, V1, Val0, Val1, Isovalue)
  608. end;
  609. procedure TGLIsoSurfaceExtractor.MarchingTetrahedra(Isovalue: Single;
  610. out Vertices: TVertexArray; out Triangles: TIntegerArray; isPolished: boolean);
  611. var
  612. i, j, k: Integer;
  613. index: word;
  614. CubeVertices: array of TAffineVector;
  615. Tetrahedron: array [0 .. 3] of TAffineVector;
  616. DataTetra: array [0 .. 3] of Single;
  617. // Add Triangle to List
  618. procedure AppendTri();
  619. var
  620. edge: byte;
  621. Ver1, Ver2, Ver3: TVertex;
  622. VListlength: Integer;
  623. TListlength: Integer;
  624. begin
  625. edge := 0;
  626. while MT_TRITABLE[index, edge] <> -1 do
  627. begin
  628. Ver1 := Interpolate(Tetrahedron[MT_EDGETABLE[MT_TRITABLE[index, edge], 0]
  629. ], Tetrahedron[MT_EDGETABLE[MT_TRITABLE[index, edge], 1]],
  630. DataTetra[MT_EDGETABLE[MT_TRITABLE[index, edge], 0]],
  631. DataTetra[MT_EDGETABLE[MT_TRITABLE[index, edge], 1]], Isovalue, isPolished);
  632. Ver2 := Interpolate(Tetrahedron[MT_EDGETABLE[MT_TRITABLE[index, edge + 1],
  633. 0]], Tetrahedron[MT_EDGETABLE[MT_TRITABLE[index, edge + 1], 1]],
  634. DataTetra[MT_EDGETABLE[MT_TRITABLE[index, edge + 1], 0]],
  635. DataTetra[MT_EDGETABLE[MT_TRITABLE[index, edge + 1], 1]], Isovalue, isPolished);
  636. Ver3 := Interpolate(Tetrahedron[MT_EDGETABLE[MT_TRITABLE[index, edge + 2],
  637. 0]], Tetrahedron[MT_EDGETABLE[MT_TRITABLE[index, edge + 2], 1]],
  638. DataTetra[MT_EDGETABLE[MT_TRITABLE[index, edge + 2], 0]],
  639. DataTetra[MT_EDGETABLE[MT_TRITABLE[index, edge + 2], 1]], Isovalue, isPolished);
  640. VListlength := Length(Vertices) + 3;
  641. TListlength := Length(Triangles) + 3;
  642. SetLength(Vertices, VListlength);
  643. SetLength(Triangles, TListlength);
  644. Vertices[VListlength - 3] := Ver1;
  645. Vertices[VListlength - 2] := Ver2;
  646. Vertices[VListlength - 1] := Ver3;
  647. Triangles[TListlength - 3] := VListlength - 3;
  648. Triangles[TListlength - 2] := VListlength - 2;
  649. Triangles[TListlength - 1] := VListlength - 1;
  650. edge := edge + 3;
  651. end;
  652. end;
  653. // Split Cube in 6 Tetrahedrons and process each tetrahedron
  654. procedure SplitCube();
  655. var
  656. i, j: Integer;
  657. begin
  658. for i := 0 to 5 do
  659. begin
  660. for j := 0 to 3 do
  661. begin
  662. Tetrahedron[j] := CubeVertices[MT_CUBESPLIT[i, j]];
  663. DataTetra[j] := Data[Trunc(Tetrahedron[j].X),
  664. Trunc(Tetrahedron[j].Y), Trunc(Tetrahedron[j].Z)];
  665. end;
  666. index := BuildIndex(DataTetra, Isovalue);
  667. AppendTri();
  668. end;
  669. end;
  670. begin
  671. (*
  672. 1----2
  673. /| /|
  674. 0----3 |
  675. | 5--|-6
  676. |/ |/
  677. 4----7
  678. *)
  679. SetLength(CubeVertices, 8);
  680. for k := 0 to Dimensions['z'] - 2 do
  681. begin
  682. for j := 0 to Dimensions['y'] - 2 do
  683. begin
  684. for i := 0 to Dimensions['x'] - 2 do
  685. begin
  686. CubeVertices[0] := AffineVectorMake(i, j, k);
  687. CubeVertices[1] := AffineVectorMake(i, j, k + 1);
  688. CubeVertices[2] := AffineVectorMake(i + 1, j, k + 1);
  689. CubeVertices[3] := AffineVectorMake(i + 1, j, k);
  690. CubeVertices[4] := AffineVectorMake(i, j + 1, k);
  691. CubeVertices[5] := AffineVectorMake(i, j + 1, k + 1);
  692. CubeVertices[6] := AffineVectorMake(i + 1, j + 1, k + 1);
  693. CubeVertices[7] := AffineVectorMake(i + 1, j + 1, k);
  694. SplitCube();
  695. end; // for k
  696. end; // for j
  697. end; // for i
  698. end; // ccMT
  699. constructor TGLIsoSurfaceExtractor.Create;
  700. begin
  701. inherited;
  702. end;
  703. constructor TGLIsoSurfaceExtractor.Create(Xdim, Ydim, Zdim: Integer;
  704. var AData: TArray3DExt);
  705. begin
  706. Create();
  707. AssignData(Xdim, Ydim, Zdim, AData);
  708. end;
  709. destructor TGLIsoSurfaceExtractor.Destroy;
  710. begin
  711. inherited;
  712. end;
  713. procedure TGLIsoSurfaceExtractor.AssignData(Xdim, Ydim, Zdim: Integer;
  714. var AData: TArray3DExt);
  715. begin
  716. Dimensions['x'] := Xdim;
  717. Dimensions['y'] := Ydim;
  718. Dimensions['z'] := Zdim;
  719. Data := AData;
  720. end;
  721. //-----------------------------------------------------------------------
  722. procedure TGLIsoSurfaceExtractor.MarchingCubes(Isovalue: Single;
  723. out Vertices: TVertexArray; out Triangles: TIntegerArray; isPolished: boolean);
  724. var
  725. i, j, k: Integer;
  726. index: word;
  727. CubeVertices: array [0 .. 7] of TAffineVector;
  728. CubeData: array [0 .. 7] of Single;
  729. procedure AppendTri();
  730. var
  731. edge: byte;
  732. Ver1, Ver2, Ver3: TVertex;
  733. VListlength: Integer;
  734. TListlength: Integer;
  735. begin
  736. edge := 0;
  737. while MC_TRITABLE[index, edge] <> -1 do
  738. begin
  739. Ver1 := Interpolate(CubeVertices[MC_EDGETABLE[MC_TRITABLE[index, edge], 0]
  740. ], CubeVertices[MC_EDGETABLE[MC_TRITABLE[index, edge], 1]],
  741. CubeData[MC_EDGETABLE[MC_TRITABLE[index, edge], 0]],
  742. CubeData[MC_EDGETABLE[MC_TRITABLE[index, edge], 1]], Isovalue, isPolished);
  743. Ver2 := Interpolate(CubeVertices[MC_EDGETABLE[MC_TRITABLE[index,
  744. edge + 1], 0]], CubeVertices[MC_EDGETABLE[MC_TRITABLE[index, edge + 1],
  745. 1]], CubeData[MC_EDGETABLE[MC_TRITABLE[index, edge + 1], 0]],
  746. CubeData[MC_EDGETABLE[MC_TRITABLE[index, edge + 1], 1]], Isovalue, isPolished);
  747. Ver3 := Interpolate(CubeVertices[MC_EDGETABLE[MC_TRITABLE[index,
  748. edge + 2], 0]], CubeVertices[MC_EDGETABLE[MC_TRITABLE[index, edge + 2],
  749. 1]], CubeData[MC_EDGETABLE[MC_TRITABLE[index, edge + 2], 0]],
  750. CubeData[MC_EDGETABLE[MC_TRITABLE[index, edge + 2], 1]], Isovalue, isPolished);
  751. VListlength := Length(Vertices) + 3;
  752. TListlength := Length(Triangles) + 3;
  753. SetLength(Vertices, VListlength);
  754. SetLength(Triangles, TListlength);
  755. Vertices[VListlength - 3] := Ver1;
  756. Vertices[VListlength - 2] := Ver2;
  757. Vertices[VListlength - 1] := Ver3;
  758. Triangles[TListlength - 3] := VListlength - 3;
  759. Triangles[TListlength - 2] := VListlength - 2;
  760. Triangles[TListlength - 1] := VListlength - 1;
  761. edge := edge + 3;
  762. end;
  763. end;
  764. begin
  765. (*
  766. 7----6
  767. /| /|
  768. 3----2 |
  769. | 4--|-5
  770. |/ |/
  771. 0----1
  772. *)
  773. for i := 0 to Dimensions['x'] - 2 do
  774. begin
  775. for j := 1 to Dimensions['y'] - 1 do
  776. begin
  777. for k := 0 to Dimensions['z'] - 2 do
  778. begin
  779. CubeVertices[0] := AffineVectorMake(i, j, k);
  780. CubeVertices[1] := AffineVectorMake(i + 1, j, k);
  781. CubeVertices[2] := AffineVectorMake(i + 1, j - 1, k);
  782. CubeVertices[3] := AffineVectorMake(i, j - 1, k);
  783. CubeVertices[4] := AffineVectorMake(i, j, k + 1);
  784. CubeVertices[5] := AffineVectorMake(i + 1, j, k + 1);
  785. CubeVertices[6] := AffineVectorMake(i + 1, j - 1, k + 1);
  786. CubeVertices[7] := AffineVectorMake(i, j - 1, k + 1);
  787. CubeData[0] := Data[i, j, k];
  788. CubeData[1] := Data[i + 1, j, k];
  789. CubeData[2] := Data[i + 1, j - 1, k];
  790. CubeData[3] := Data[i, j - 1, k];
  791. CubeData[4] := Data[i, j, k + 1];
  792. CubeData[5] := Data[i + 1, j, k + 1];
  793. CubeData[6] := Data[i + 1, j - 1, k + 1];
  794. CubeData[7] := Data[i, j - 1, k + 1];
  795. Index := BuildIndex(CubeData, Isovalue);
  796. AppendTri();
  797. end; // for k
  798. end; // for j
  799. end; // for i
  800. end;
  801. function TGLMarchingCube.Add_c_vertex: Integer;
  802. var
  803. u: Single;
  804. vid: Integer;
  805. procedure VertexAdd(iv: Integer);
  806. begin
  807. with PVertices^[_Nverts] do
  808. begin
  809. u := u + 1;
  810. P := VectorAdd(P, PVertices[iv].P);
  811. N := VectorAdd(N, PVertices[iv].N);
  812. {$IFDEF UseDensity}
  813. Density := Density + PVertices[iv].Density;
  814. {$ENDIF}
  815. end
  816. end;
  817. begin
  818. Test_Vertex_Addiction;
  819. u := 0;
  820. PVertices^[_Nverts].P := NullVector;
  821. PVertices^[_Nverts].N := NullVector;
  822. {$IFDEF UseDensity}
  823. PVertices^[_Nverts].Density := 0;
  824. {$ENDIF}
  825. Inc(_Nverts);
  826. // Computes the average of the intersection points of the cube
  827. vid := Get_x_vert(_i, _j, _k);
  828. if (vid <> -1) then
  829. VertexAdd(vid);
  830. vid := Get_y_vert(_i + 1, _j, _k);
  831. if (vid <> -1) then
  832. VertexAdd(vid);
  833. vid := Get_x_vert(_i, _j + 1, _k);
  834. if (vid <> -1) then
  835. VertexAdd(vid);
  836. vid := Get_y_vert(_i, _j, _k);
  837. if (vid <> -1) then
  838. VertexAdd(vid);
  839. vid := Get_x_vert(_i, _j, _k + 1);
  840. if (vid <> -1) then
  841. VertexAdd(vid);
  842. vid := Get_y_vert(_i + 1, _j, _k + 1);
  843. if (vid <> -1) then
  844. VertexAdd(vid);
  845. vid := Get_x_vert(_i, _j + 1, _k + 1);
  846. if (vid <> -1) then
  847. VertexAdd(vid);
  848. vid := Get_y_vert(_i, _j, _k + 1);
  849. if (vid <> -1) then
  850. VertexAdd(vid);
  851. vid := Get_z_vert(_i, _j, _k);
  852. if (vid <> -1) then
  853. VertexAdd(vid);
  854. vid := Get_z_vert(_i + 1, _j, _k);
  855. if (vid <> -1) then
  856. VertexAdd(vid);
  857. vid := Get_z_vert(_i + 1, _j + 1, _k);
  858. if (vid <> -1) then
  859. VertexAdd(vid);
  860. vid := Get_z_vert(_i, _j + 1, _k);
  861. if (vid <> -1) then
  862. VertexAdd(vid);
  863. ScaleVector(PVertices^[_Nverts].P, 1 / u);
  864. NormalizeVector(PVertices^[_Nverts].N);
  865. {$IFDEF UseDensity}
  866. PVertices^[_Nverts].Density := PVertices^[_Nverts].Density / u;
  867. {$ENDIF}
  868. Result := _Nverts - 1;
  869. end;
  870. procedure TGLMarchingCube.Add_Triangle(trig: array of Integer; N: Byte;
  871. v12: Integer = -1);
  872. var
  873. tv: array [0 .. 2] of Integer;
  874. t, tmod3: Integer;
  875. begin
  876. for t := 0 to 3 * N - 1 do
  877. begin
  878. tmod3 := t mod 3;
  879. case trig[t] of
  880. 0: tv[tmod3] := Get_x_vert(_i, _j, _k);
  881. 1: tv[tmod3] := Get_y_vert(_i + 1, _j, _k);
  882. 2: tv[tmod3] := Get_x_vert(_i, _j + 1, _k);
  883. 3: tv[tmod3] := Get_y_vert(_i, _j, _k);
  884. 4: tv[tmod3] := Get_x_vert(_i, _j, _k + 1);
  885. 5: tv[tmod3] := Get_y_vert(_i + 1, _j, _k + 1);
  886. 6: tv[tmod3] := Get_x_vert(_i, _j + 1, _k + 1);
  887. 7: tv[tmod3] := Get_y_vert(_i, _j, _k + 1);
  888. 8: tv[tmod3] := Get_z_vert(_i, _j, _k);
  889. 9: tv[tmod3] := Get_z_vert(_i + 1, _j, _k);
  890. 10: tv[tmod3] := Get_z_vert(_i + 1, _j + 1, _k);
  891. 11: tv[tmod3] := Get_z_vert(_i, _j + 1, _k);
  892. 12: tv[tmod3] := v12
  893. end;
  894. if (tv[tmod3] = -1) then
  895. Break;
  896. if (tmod3 = 2) then
  897. begin
  898. if (_Ntrigs >= _Strigs) then
  899. begin
  900. _Strigs := 2 * _Strigs;
  901. ReallocMem(PTriangles, _Strigs * SizeOf(TTriangleRec));
  902. end;
  903. PTriangles^[_Ntrigs].v1 := tv[0];
  904. PTriangles^[_Ntrigs].v2 := tv[1];
  905. PTriangles^[_Ntrigs].v3 := tv[2];
  906. Inc(_Ntrigs);
  907. end
  908. end
  909. end;
  910. function TGLMarchingCube.Calc_u(v1, v2: Single): Extended;
  911. begin
  912. if (abs(FIsoValue - v1) >= 0.00001) then
  913. Result := 1
  914. else if (abs(FIsoValue - v2) >= 0.00001) then
  915. Result := 0
  916. else if (abs(v1 - v2) >= 0.00001) then
  917. Result := (FIsoValue - v1) / (v2 - v1)
  918. else
  919. Result := 0.5
  920. end;
  921. function TGLMarchingCube.add_x_vertex: Integer;
  922. var
  923. u: Single;
  924. begin
  925. Test_Vertex_Addiction;
  926. u := Calc_u(_Cube[0].Density, _Cube[1].Density);
  927. PVertices^[_Nverts].P.X := _Cube[0].P.X + u * FStepX;
  928. PVertices^[_Nverts].P.Y := _Cube[0].P.Y;
  929. PVertices^[_Nverts].P.Z := _Cube[0].P.Z;
  930. PVertices^[_Nverts].N.X := (1 - u) * Get_x_grad(_i, _j, _k) + u * Get_x_grad(_i + 1, _j, _k);
  931. PVertices^[_Nverts].N.Y := (1 - u) * Get_y_grad(_i, _j, _k) + u * Get_y_grad(_i + 1, _j, _k);
  932. PVertices^[_Nverts].N.Z := (1 - u) * Get_z_grad(_i, _j, _k) + u * Get_z_grad(_i + 1, _j, _k);
  933. NormalizeVector(PVertices^[_Nverts].N);
  934. {$IFDEF UseDensity}
  935. PVertices^[_Nverts].Density := _Cube[1].Density;
  936. {$ENDIF}
  937. Inc(_Nverts);
  938. Result := _Nverts - 1;
  939. end;
  940. function TGLMarchingCube.Add_y_vertex: Integer;
  941. var
  942. u: Single;
  943. begin
  944. Test_Vertex_Addiction;
  945. u := Calc_u(_Cube[0].Density, _Cube[3].Density);
  946. PVertices^[_Nverts].P.X := _Cube[0].P.X;
  947. PVertices^[_Nverts].P.Y := _Cube[0].P.Y + u * FStepY;
  948. PVertices^[_Nverts].P.Z := _Cube[0].P.Z;
  949. PVertices^[_Nverts].N.X := (1 - u) * Get_x_grad(_i, _j, _k) + u * Get_x_grad(_i, _j + 1, _k);
  950. PVertices^[_Nverts].N.Y := (1 - u) * Get_y_grad(_i, _j, _k) + u * Get_y_grad(_i, _j + 1, _k);
  951. PVertices^[_Nverts].N.Z := (1 - u) * Get_z_grad(_i, _j, _k) + u * Get_z_grad(_i, _j + 1, _k);
  952. NormalizeVector(PVertices^[_Nverts].N);
  953. {$IFDEF UseDensity}
  954. PVertices^[_Nverts].Density := _Cube[3].Density
  955. {$ENDIF}
  956. Inc(_Nverts);
  957. Result := _Nverts - 1;
  958. end;
  959. function TGLMarchingCube.Add_z_vertex: Integer;
  960. var
  961. u: Single;
  962. begin
  963. Test_Vertex_Addiction;
  964. u := Calc_u(_Cube[0].Density, _Cube[4].Density);
  965. PVertices^[_Nverts].P.X := _Cube[0].P.X;
  966. PVertices^[_Nverts].P.Y := _Cube[0].P.Y;
  967. PVertices^[_Nverts].P.Z := _Cube[0].P.Z + u * FStepZ;;
  968. PVertices^[_Nverts].N.X := (1 - u) * Get_x_grad(_i, _j, _k) + u * Get_x_grad(_i, _j, _k + 1);
  969. PVertices^[_Nverts].N.Y := (1 - u) * Get_y_grad(_i, _j, _k) + u * Get_y_grad(_i, _j, _k + 1);
  970. PVertices^[_Nverts].N.Z := (1 - u) * Get_z_grad(_i, _j, _k) + u * Get_z_grad(_i, _j, _k + 1);
  971. NormalizeVector(PVertices^[_Nverts].N);
  972. {$IFDEF UseDensity}
  973. PVertices^[_Nverts].Density := _Cube[4].Density
  974. {$ENDIF}
  975. Inc(_Nverts);
  976. Result := _Nverts - 1;
  977. end;
  978. procedure TGLMarchingCube.Clean_all(keepFacets: Boolean = False);
  979. begin
  980. Clean_temps;
  981. Clean_space;
  982. if (not keepFacets) then
  983. FreeMem(PVertices);
  984. FreeMem(PTriangles);
  985. PVertices := nil;
  986. PTriangles := nil;
  987. _Nverts := 0;
  988. _Ntrigs := 0;
  989. _Sverts := 0;
  990. _Strigs := 0;
  991. end;
  992. procedure TGLMarchingCube.Clean_space;
  993. begin
  994. if (VoxelData <> nil) then
  995. begin
  996. FreeMem(VoxelData);
  997. VoxelData := nil
  998. end;
  999. FSizeX := 0;
  1000. FSizeY := 0;
  1001. FSizeZ := 0
  1002. end;
  1003. procedure TGLMarchingCube.Clean_temps;
  1004. begin
  1005. FreeMem(PVertsX);
  1006. PVertsX := nil;
  1007. FreeMem(PVertsY);
  1008. PVertsY := nil;
  1009. FreeMem(PVertsZ);
  1010. PVertsZ := nil;
  1011. end;
  1012. procedure TGLMarchingCube.Compute_Intersection_Points;
  1013. var
  1014. k, j, i: Integer;
  1015. begin
  1016. _Cube[0] := GetVoxelData(0, 0, 0);
  1017. _Cube[1] := GetVoxelData(1, 0, 0);
  1018. _Cube[3] := GetVoxelData(0, 1, 0);
  1019. _Cube[4] := GetVoxelData(0, 0, 1);
  1020. (* _step_x:= _Cube[1].P[0] - _Cube[0].P[0] ;
  1021. _step_y:= _Cube[3].P[1] - _Cube[0].P[1] ;
  1022. _step_z:= _Cube[4].P[2] - _Cube[0].P[2] ; *)
  1023. for k := 0 to FSizeZ - 2 do
  1024. begin
  1025. _k := k;
  1026. for j := 0 to FSizeY - 2 do
  1027. begin
  1028. _j := j;
  1029. for i := 0 to FSizeX - 2 do
  1030. begin
  1031. _i := i;
  1032. _Cube[0] := GetVoxelData(_i, _j, _k);
  1033. _Cube[1] := GetVoxelData(_i + 1, _j, _k);
  1034. _Cube[3] := GetVoxelData(_i, _j + 1, _k);
  1035. _Cube[4] := GetVoxelData(_i, _j, _k + 1);
  1036. if (Internal(_Cube[0].Density)) then
  1037. begin
  1038. if (not Internal(_Cube[1].Density)) then
  1039. Set_x_vert(add_x_vertex(), _i, _j, _k);
  1040. if (not Internal(_Cube[3].Density)) then
  1041. set_y_vert(add_y_vertex(), _i, _j, _k);
  1042. if (not Internal(_Cube[4].Density)) then
  1043. set_z_vert(add_z_vertex(), _i, _j, _k);
  1044. end
  1045. else
  1046. begin
  1047. if (Internal(_Cube[1].Density)) then
  1048. Set_x_vert(Add_x_vertex(), _i, _j, _k);
  1049. if (Internal(_Cube[3].Density)) then
  1050. set_y_vert(Add_y_vertex(), _i, _j, _k);
  1051. if (Internal(_Cube[4].Density)) then
  1052. set_z_vert(Add_z_vertex(), _i, _j, _k);
  1053. end
  1054. end
  1055. end
  1056. end
  1057. end;
  1058. procedure TGLMarchingCube.ReDim(ASizeX, ASizeY, ASizeZ: Integer;
  1059. xMin, xMax, yMin, yMax, zMin, zMax: Single);
  1060. begin
  1061. clean_all;
  1062. FSizeX := ASizeX;
  1063. FSizeY := ASizeY;
  1064. FSizeZ := ASizeZ;
  1065. FxMin := xMin;
  1066. FxMax := xMax;
  1067. FyMin := yMin;
  1068. FyMax := yMax;
  1069. FzMin := zMin;
  1070. FzMax := zMax;
  1071. FStepX := (FxMax - FxMin) / (FSizeX - 1);
  1072. FStepY := (FyMax - FyMin) / (FSizeY - 1);
  1073. FStepZ := (FzMax - FzMin) / (FSizeZ - 1);
  1074. VoxelData := nil;
  1075. PVertsX := nil;
  1076. PVertsY := nil;
  1077. PVertsZ := nil;
  1078. _Nverts := 0;
  1079. _Ntrigs := 0;
  1080. _Sverts := 0;
  1081. _Strigs := 0;
  1082. PVertices := nil;
  1083. PTriangles := nil;
  1084. Init_all();
  1085. // FillVoxelData();
  1086. end;
  1087. //------------------------------------------------------------------
  1088. constructor TGLMarchingCube.Create;
  1089. begin
  1090. FOriginalMC := True; // now only original MC is implemented
  1091. FIsoValue := 0;
  1092. ScalarField := nil;
  1093. // SFSphere;//SFKleinBottle;//SFMinkowski;// SFChmutov2;// SFChmutov1;//SFDoubleTorus;// SFToroidal;
  1094. VoxelData := nil;
  1095. PVertsX := nil;
  1096. PVertsY := nil;
  1097. PVertsZ := nil;
  1098. _Nverts := 0;
  1099. _Ntrigs := 0;
  1100. _Sverts := 0;
  1101. _Strigs := 0;
  1102. PVertices := nil;
  1103. PTriangles := nil;
  1104. end;
  1105. //------------------------------------------------------------------
  1106. constructor TGLMarchingCube.Create(SizeX, SizeY, SizeZ: Integer;
  1107. AIsoValue: TScalarValue = 0.0; xMin: Single = -0.5; xMax: Single = 0.5;
  1108. yMin: Single = -0.5; yMax: Single = 0.5; zMin: Single = -0.5;
  1109. zMax: Single = 0.5);
  1110. begin
  1111. FOriginalMC := True; // now only original MC is implemented
  1112. FIsoValue := AIsoValue;
  1113. ScalarField := SFSphere;
  1114. (* ScalarField := SFKleinBottle; SFMinkowski; SFChmutov2;
  1115. SFChmutov1; SFDoubleTorus; SFToroidal; *)
  1116. ReDim(SizeX, SizeY, SizeZ, xMin, xMax, yMin, yMax, zMin, zMax);
  1117. FillVoxelData();
  1118. end;
  1119. destructor TGLMarchingCube.Destroy;
  1120. begin
  1121. Clean_all;
  1122. inherited;
  1123. end;
  1124. function TGLMarchingCube.GetVoxelValue(i, j, k: Integer): TScalarValue;
  1125. begin
  1126. Result := VoxelData^[i + j * FSizeX + k * FSizeX * FSizeY].Density
  1127. end;
  1128. function TGLMarchingCube.GetVoxelData(i, j, k: Integer): TVoxelRec;
  1129. begin
  1130. Result := VoxelData^[i + j * FSizeX + k * FSizeX * FSizeY]
  1131. end;
  1132. function TGLMarchingCube.Get_x_grad(i, j, k: Integer): Single;
  1133. begin
  1134. if (i > 0) then
  1135. if (i < FSizeX - 1) then
  1136. Result := (GetVoxelValue(i + 1, j, k) - GetVoxelValue(i - 1, j, k)) / 2
  1137. else
  1138. Result := GetVoxelValue(i, j, k) - GetVoxelValue(i - 1, j, k)
  1139. else
  1140. Result := GetVoxelValue(i + 1, j, k) - GetVoxelValue(i, j, k)
  1141. end;
  1142. function TGLMarchingCube.Get_x_vert(i, j, k: Integer): Integer;
  1143. begin
  1144. Result := PVertsX^[i + j * FSizeX + k * FSizeX * FSizeY]
  1145. end;
  1146. function TGLMarchingCube.Get_y_grad(i, j, k: Integer): Single;
  1147. begin
  1148. if (j > 0) then
  1149. if (j < FSizeY - 1) then
  1150. Result := (GetVoxelValue(i, j + 1, k) - GetVoxelValue(i, j - 1, k)) / 2
  1151. else
  1152. Result := GetVoxelValue(i, j, k) - GetVoxelValue(i, j - 1, k)
  1153. else
  1154. Result := GetVoxelValue(i, j + 1, k) - GetVoxelValue(i, j, k)
  1155. end;
  1156. function TGLMarchingCube.Get_y_vert(i, j, k: Integer): Integer;
  1157. begin
  1158. Result := PVertsY^[i + j * FSizeX + k * FSizeX * FSizeY]
  1159. end;
  1160. function TGLMarchingCube.Get_z_grad(i, j, k: Integer): Single;
  1161. begin
  1162. if (k > 0) then
  1163. if (k < FSizeZ - 1) then
  1164. Result := (GetVoxelValue(i, j, k + 1) - GetVoxelValue(i, j, k - 1)) / 2
  1165. else
  1166. Result := GetVoxelValue(i, j, k) - GetVoxelValue(i, j, k - 1)
  1167. else
  1168. Result := GetVoxelValue(i, j, k + 1) - GetVoxelValue(i, j, k)
  1169. end;
  1170. function TGLMarchingCube.Get_z_vert(i, j, k: Integer): Integer;
  1171. begin
  1172. Result := PVertsZ^[i + j * FSizeX + k * FSizeX * FSizeY]
  1173. end;
  1174. procedure TGLMarchingCube.Init_all;
  1175. begin
  1176. Init_temps;
  1177. Init_space;
  1178. if (PVertices <> nil) then
  1179. FreeMem(PVertices);
  1180. if (PTriangles <> nil) then
  1181. FreeMem(PTriangles);
  1182. _Nverts := 0;
  1183. _Ntrigs := 0;
  1184. _Sverts := ALLOC_SIZE;
  1185. _Strigs := ALLOC_SIZE;
  1186. GetMem(PVertices, _Sverts * SizeOf(TVertexRec));
  1187. GetMem(PTriangles, _Strigs * SizeOf(TTriangleRec));
  1188. end;
  1189. procedure TGLMarchingCube.Init_space;
  1190. begin
  1191. VoxelData := AllocMem(FSizeX * FSizeY * FSizeZ * SizeOf(TVoxelRec));
  1192. end;
  1193. procedure TGLMarchingCube.Init_temps;
  1194. var
  1195. spaceSize: Longword;
  1196. begin
  1197. spaceSize := FSizeX * FSizeY * FSizeZ;
  1198. GetMem(PVertsX, spaceSize * SizeOf(Integer));
  1199. GetMem(PVertsY, spaceSize * SizeOf(Integer));
  1200. GetMem(PVertsZ, spaceSize * SizeOf(Integer));
  1201. FillChar(PVertsX^, spaceSize * SizeOf(Integer), -1);
  1202. FillChar(PVertsY^, spaceSize * SizeOf(Integer), -1);
  1203. FillChar(PVertsZ^, spaceSize * SizeOf(Integer), -1);
  1204. end;
  1205. function TGLMarchingCube.Internal(AValue: TScalarValue): Boolean;
  1206. begin
  1207. Result := AValue <= FIsoValue
  1208. end;
  1209. procedure TGLMarchingCube.Process_Cube;
  1210. var
  1211. nt: Byte;
  1212. begin
  1213. if (FOriginalMC) then
  1214. begin
  1215. nt := 0;
  1216. while (MC_TRITABLE[_lut_entry][3 * nt] <> -1) do
  1217. Inc(nt);
  1218. add_triangle(MC_TRITABLE[_lut_entry], nt);
  1219. Exit;
  1220. end;
  1221. /// TODO complete algorithm with various tiling...
  1222. end;
  1223. procedure TGLMarchingCube.Run;
  1224. var
  1225. i, j, k, P: Integer;
  1226. begin
  1227. if (PVertsX = nil) then
  1228. begin
  1229. Init_temps;
  1230. _Nverts := 0;
  1231. _Ntrigs := 0;
  1232. end;
  1233. Compute_Intersection_Points;
  1234. for k := 0 to FSizeZ - 2 do
  1235. begin
  1236. _k := k;
  1237. for j := 0 to FSizeY - 2 do
  1238. begin
  1239. _j := j;
  1240. for i := 0 to FSizeX - 2 do
  1241. begin
  1242. _i := i;
  1243. _lut_entry := 0;
  1244. for P := 0 to 7 do
  1245. begin
  1246. _Cube[P] := GetVoxelData(i + ((P xor (P shr 1)) and 1),
  1247. j + ((P shr 1) and 1), k + ((P shr 2) and 1));
  1248. // _Cube[p]:= GetVoxelData( i+((p^(p>>1))&1), j+((p>>1)&1), k+((p>>2)&1) ) ;
  1249. if (Internal(_Cube[P].Density)) then
  1250. _lut_entry := _lut_entry or (1 shl P);
  1251. end;
  1252. process_cube;
  1253. end
  1254. end
  1255. end;
  1256. clean_temps;
  1257. end;
  1258. procedure TGLMarchingCube.Run(IsoValue: TScalarValue);
  1259. begin
  1260. FIsoValue := IsoValue;
  1261. Run
  1262. end;
  1263. procedure TGLMarchingCube.SetVoxelValue(i, j, k: Integer; HfValue: TScalarValue);
  1264. begin
  1265. VoxelData^[i + j * FSizeX + k * FSizeX * FSizeY].Density := HfValue
  1266. end;
  1267. procedure TGLMarchingCube.Set_x_vert(a_val, i, j, k: Integer);
  1268. begin
  1269. PVertsX^[i + j * FSizeX + k * FSizeX * FSizeY] := a_val
  1270. end;
  1271. procedure TGLMarchingCube.Set_y_vert(a_val, i, j, k: Integer);
  1272. begin
  1273. PVertsY^[i + j * FSizeX + k * FSizeX * FSizeY] := a_val
  1274. end;
  1275. procedure TGLMarchingCube.Set_z_vert(a_val, i, j, k: Integer);
  1276. begin
  1277. PVertsZ^[i + j * FSizeX + k * FSizeX * FSizeY] := a_val
  1278. end;
  1279. procedure TGLMarchingCube.Test_vertex_addiction;
  1280. begin
  1281. if _Nverts >= _Sverts then
  1282. begin
  1283. _Sverts := 2 * _Sverts;
  1284. ReallocMem(PVertices, _Sverts * SizeOf(TVertexRec))
  1285. end;
  1286. end;
  1287. function TGLMarchingCube.Voxel(i, j, k: Integer): PVoxelRec;
  1288. begin
  1289. if (k >= FSizeZ) or (j >= FSizeY) or (i >= FSizeX) then
  1290. Result := nil
  1291. else
  1292. Result := @VoxelData^[i + j * FSizeX + k * FSizeX * FSizeY]
  1293. end;
  1294. procedure TGLMarchingCube.FillVoxelData;
  1295. var
  1296. iX, iY, iZ: Integer;
  1297. X, Y, Z: Single;
  1298. begin
  1299. for iX := 0 to FSizeX - 1 do
  1300. begin
  1301. X := FxMin + iX * FStepX;
  1302. for iY := 0 to FSizeY - 1 do
  1303. begin
  1304. Y := FyMin + iY * FStepY;
  1305. for iZ := 0 to FSizeZ - 1 do
  1306. with VoxelData^[iX + iY * FSizeX + iZ * FSizeX * FSizeY] do
  1307. begin
  1308. Z := FzMin + iZ * FStepZ;
  1309. MakeVector(P, X, Y, Z);
  1310. Density := ScalarField(X, Y, Z);
  1311. if Internal(Density) then
  1312. Status := bpInternal
  1313. else
  1314. Status := bpExternal
  1315. end;
  1316. end;
  1317. end;
  1318. end;
  1319. procedure TGLMarchingCube.FillVoxelData(AIsoValue: TScalarValue; AScalarField: TScalarField = nil);
  1320. begin
  1321. FIsoValue := AIsoValue;
  1322. if Assigned(AScalarField) then
  1323. ScalarField := AScalarField;
  1324. FillVoxelData;
  1325. end;
  1326. procedure TGLMarchingCube.FillVoxelData(AIsoValue: TScalarValue; AScalarField: TScalarFieldInt);
  1327. var
  1328. iX, iY, iZ: Integer;
  1329. X, Y, Z: Single;
  1330. begin
  1331. FIsoValue := AIsoValue;
  1332. for iX := 0 to FSizeX - 1 do
  1333. begin
  1334. X := FxMin + iX * FStepX;
  1335. for iY := 0 to FSizeY - 1 do
  1336. begin
  1337. Y := FyMin + iY * FStepY;
  1338. for iZ := 0 to FSizeZ - 1 do
  1339. with VoxelData^[iX + iY * FSizeX + iZ * FSizeX * FSizeY] do
  1340. begin
  1341. Z := FzMin + iZ * FStepZ;
  1342. MakeVector(P, X, Y, Z);
  1343. Density := AScalarField(iX, iY, iZ);
  1344. if Internal(Density) then
  1345. Status := bpInternal
  1346. else
  1347. Status := bpExternal
  1348. end;
  1349. end;
  1350. end;
  1351. end;
  1352. procedure TGLMarchingCube.CalcVertices(Vertices: TGLVertexList;
  1353. Alpha: Single = 1);
  1354. var
  1355. i: Integer;
  1356. vx1, vx2, vx3: TGLVertexData;
  1357. function GetNrmColor(Nrm: TAffineVector): TGLVector;
  1358. begin
  1359. Result.V[0] := 0;
  1360. if Nrm.V[0] > 0.0 then
  1361. Result.V[0] := Result.V[0] + Nrm.V[0];
  1362. if Nrm.V[1] < 0.0 then
  1363. Result.V[0] := Result.V[0] - 0.5 * Nrm.V[1];
  1364. if Nrm.V[2] < 0.0 then
  1365. Result.V[0] := Result.V[0] - 0.5 * Nrm.V[2];
  1366. Result.V[1] := 1;
  1367. if Nrm.V[0] < 0.0 then
  1368. Result.V[1] := Result.V[1] - 0.5 * Nrm.V[0];
  1369. if Nrm.V[1] > 0.0 then
  1370. Result.V[1] := Result.V[1] + Nrm.V[1];
  1371. if Nrm.V[2] < 0.0 then
  1372. Result.V[1] := Result.V[1] - 0.5 * Nrm.V[2];
  1373. Result.V[2] := 0;
  1374. if Nrm.V[0] < 0.0 then
  1375. Result.V[2] := Result.V[2] - 0.5 * Nrm.V[0];
  1376. if Nrm.V[1] < 0.0 then
  1377. Result.V[2] := Result.V[2] - 0.5 * Nrm.V[1];
  1378. if Nrm.V[2] > 0.0 then
  1379. Result.V[2] := Result.V[2] + Nrm.V[2];
  1380. Result.V[3] := 0.3
  1381. end;
  1382. function GetColor(H: TScalarValue): TGLVector;
  1383. begin
  1384. Result := VectorMake(0.890, 0.855, 0.788, Alpha)
  1385. (*
  1386. if H <= 10 then Result:= VectorMake(0.922, 0.957, 0.980, 1.000) //<=10
  1387. else if H <= 50 then Result:= VectorMake(0.541, 0.027, 0.027, 1.000) // 10..50
  1388. else if H <= 300 then Result:= VectorMake(0.941, 0.910, 0.859, 1.000) //50..300
  1389. else if H <= 2000 then Result:= VectorMake(0.965, 0.969, 0.973, 1.000) //350.. 2000
  1390. else if H <= 4000 then Result:= VectorMake(0.890, 0.855, 0.788, 1.000) //2000..4000
  1391. else Result:= VectorMake(0.9, 0.9, 0.6, 1.0)
  1392. *)
  1393. end;
  1394. begin
  1395. Vertices.Clear;
  1396. Vertices.Capacity := 3 * _Ntrigs;
  1397. for i := 0 to _Ntrigs - 1 do
  1398. begin
  1399. vx1.coord := PVertices^[PTriangles^[i].v1].P;
  1400. vx1.normal := PVertices^[PTriangles^[i].v1].N;
  1401. vx2.coord := PVertices^[PTriangles^[i].v2].P;
  1402. vx2.normal := PVertices^[PTriangles^[i].v2].N;
  1403. vx3.coord := PVertices^[PTriangles^[i].v3].P;
  1404. vx3.normal := PVertices^[PTriangles^[i].v3].N;
  1405. {$IFDEF UseDensity}
  1406. vx1.Color := GetColor(PVertices^[PTriangles^[i].v1].Density); // GetNrmColor(vx1.normal);
  1407. vx2.Color := GetColor(PVertices^[PTriangles^[i].v2].Density); // GetNrmColor(vx2.normal);
  1408. vx3.Color := GetColor(PVertices^[PTriangles^[i].v3].Density); // GetNrmColor(vx3.normal);
  1409. {$ELSE}
  1410. vx1.Color := VectorMake(0.890, 0.855, 0.788, Alpha);
  1411. vx2.Color := VectorMake(0.890, 0.855, 0.788, Alpha);
  1412. vx3.Color := VectorMake(0.890, 0.855, 0.788, Alpha);
  1413. {$ENDIF}
  1414. // Vertices.AddVertex3(vx1, vx2, vx3); seems to be correct the next line
  1415. Vertices.AddVertex3(vx3, vx2, vx1);
  1416. end;
  1417. end;
  1418. procedure TGLMarchingCube.CalcMeshObject(AMeshObject: TGLMeshObject; Alpha: Single);
  1419. var
  1420. i: Integer;
  1421. begin
  1422. AMeshObject.Clear;
  1423. AMeshObject.Vertices.Capacity := _Nverts;
  1424. AMeshObject.Normals.Capacity := _Nverts;
  1425. AMeshObject.Colors.Capacity := _Nverts;
  1426. with TFGVertexIndexList.CreateOwned(AMeshObject.FaceGroups) do
  1427. begin
  1428. Mode := fgmmTriangles;
  1429. for i := 0 to _Nverts - 1 do
  1430. begin
  1431. AMeshObject.Vertices.Add(PVertices^[i].P);
  1432. AMeshObject.Normals.Add(PVertices^[i].N);
  1433. // AMeshObject.Normals.Add(VectorScale(PVertices^[i].N, -1));
  1434. // AMeshObject.Colors.Add(VectorMake(0.890, 0.855, 0.788, Alpha));
  1435. end;
  1436. for i := 0 to _Ntrigs - 1 do
  1437. // with PTriangles^[i] do VertexIndices.Add(v1, v2, v3);
  1438. VertexIndices.Add(PTriangles^[i].v3, PTriangles^[i].v2, PTriangles^[i].v1);
  1439. end;
  1440. end;
  1441. end.