snappy 3.3__cp310-cp310-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (541) hide show
  1. snappy/CyOpenGL.cpython-310-aarch64-linux-gnu.so +0 -0
  2. snappy/SnapPy.cpython-310-aarch64-linux-gnu.so +0 -0
  3. snappy/SnapPy.ico +0 -0
  4. snappy/SnapPy.png +0 -0
  5. snappy/SnapPyHP.cpython-310-aarch64-linux-gnu.so +0 -0
  6. snappy/__init__.py +534 -0
  7. snappy/app.py +604 -0
  8. snappy/app_menus.py +372 -0
  9. snappy/browser.py +998 -0
  10. snappy/cache.py +25 -0
  11. snappy/canonical.py +249 -0
  12. snappy/cusps/__init__.py +280 -0
  13. snappy/cusps/cusp_area_matrix.py +98 -0
  14. snappy/cusps/cusp_areas_from_matrix.py +96 -0
  15. snappy/cusps/maximal_cusp_area_matrix.py +136 -0
  16. snappy/cusps/short_slopes_for_cusp.py +217 -0
  17. snappy/cusps/test.py +22 -0
  18. snappy/cusps/trig_cusp_area_matrix.py +63 -0
  19. snappy/database.py +454 -0
  20. snappy/db_utilities.py +79 -0
  21. snappy/decorated_isosig.py +717 -0
  22. snappy/dev/__init__.py +0 -0
  23. snappy/dev/extended_ptolemy/__init__.py +8 -0
  24. snappy/dev/extended_ptolemy/closed.py +106 -0
  25. snappy/dev/extended_ptolemy/complexVolumesClosed.py +149 -0
  26. snappy/dev/extended_ptolemy/direct.py +42 -0
  27. snappy/dev/extended_ptolemy/extended.py +406 -0
  28. snappy/dev/extended_ptolemy/giac_helper.py +43 -0
  29. snappy/dev/extended_ptolemy/giac_rur.py +129 -0
  30. snappy/dev/extended_ptolemy/gluing.py +46 -0
  31. snappy/dev/extended_ptolemy/phc_wrapper.py +220 -0
  32. snappy/dev/extended_ptolemy/printMatrices.py +70 -0
  33. snappy/dev/vericlosed/__init__.py +1 -0
  34. snappy/dev/vericlosed/computeApproxHyperbolicStructureNew.py +159 -0
  35. snappy/dev/vericlosed/computeApproxHyperbolicStructureOrb.py +90 -0
  36. snappy/dev/vericlosed/computeVerifiedHyperbolicStructure.py +111 -0
  37. snappy/dev/vericlosed/gimbalLoopFinder.py +130 -0
  38. snappy/dev/vericlosed/hyperbolicStructure.py +313 -0
  39. snappy/dev/vericlosed/krawczykCertifiedEdgeLengthsEngine.py +165 -0
  40. snappy/dev/vericlosed/oneVertexTruncatedComplex.py +122 -0
  41. snappy/dev/vericlosed/orb/__init__.py +1 -0
  42. snappy/dev/vericlosed/orb/orb_solution_for_snappea_finite_triangulation_mac +0 -0
  43. snappy/dev/vericlosed/parseVertexGramMatrixFile.py +47 -0
  44. snappy/dev/vericlosed/polishApproxHyperbolicStructure.py +61 -0
  45. snappy/dev/vericlosed/test.py +54 -0
  46. snappy/dev/vericlosed/truncatedComplex.py +176 -0
  47. snappy/dev/vericlosed/verificationError.py +58 -0
  48. snappy/dev/vericlosed/verifyHyperbolicStructureEngine.py +177 -0
  49. snappy/doc/_images/SnapPy-196.png +0 -0
  50. snappy/doc/_images/m004_paper_plane_on_systole.jpg +0 -0
  51. snappy/doc/_images/m125_paper_plane.jpg +0 -0
  52. snappy/doc/_images/mac.png +0 -0
  53. snappy/doc/_images/o9_00000_systole_paper_plane.jpg +0 -0
  54. snappy/doc/_images/o9_00000_systole_paper_plane_closer.jpg +0 -0
  55. snappy/doc/_images/plink-action.png +0 -0
  56. snappy/doc/_images/ubuntu.png +0 -0
  57. snappy/doc/_images/win7.png +0 -0
  58. snappy/doc/_sources/additional_classes.rst.txt +40 -0
  59. snappy/doc/_sources/bugs.rst.txt +14 -0
  60. snappy/doc/_sources/censuses.rst.txt +52 -0
  61. snappy/doc/_sources/credits.rst.txt +81 -0
  62. snappy/doc/_sources/development.rst.txt +261 -0
  63. snappy/doc/_sources/index.rst.txt +215 -0
  64. snappy/doc/_sources/installing.rst.txt +249 -0
  65. snappy/doc/_sources/manifold.rst.txt +6 -0
  66. snappy/doc/_sources/manifoldhp.rst.txt +46 -0
  67. snappy/doc/_sources/news.rst.txt +425 -0
  68. snappy/doc/_sources/other.rst.txt +25 -0
  69. snappy/doc/_sources/platonic_census.rst.txt +20 -0
  70. snappy/doc/_sources/plink.rst.txt +102 -0
  71. snappy/doc/_sources/ptolemy.rst.txt +66 -0
  72. snappy/doc/_sources/ptolemy_classes.rst.txt +42 -0
  73. snappy/doc/_sources/ptolemy_examples1.rst.txt +298 -0
  74. snappy/doc/_sources/ptolemy_examples2.rst.txt +363 -0
  75. snappy/doc/_sources/ptolemy_examples3.rst.txt +301 -0
  76. snappy/doc/_sources/ptolemy_examples4.rst.txt +61 -0
  77. snappy/doc/_sources/ptolemy_prelim.rst.txt +105 -0
  78. snappy/doc/_sources/screenshots.rst.txt +21 -0
  79. snappy/doc/_sources/snap.rst.txt +87 -0
  80. snappy/doc/_sources/snappy.rst.txt +28 -0
  81. snappy/doc/_sources/spherogram.rst.txt +103 -0
  82. snappy/doc/_sources/todo.rst.txt +47 -0
  83. snappy/doc/_sources/triangulation.rst.txt +11 -0
  84. snappy/doc/_sources/tutorial.rst.txt +49 -0
  85. snappy/doc/_sources/verify.rst.txt +210 -0
  86. snappy/doc/_sources/verify_internals.rst.txt +79 -0
  87. snappy/doc/_static/SnapPy-horizontal-128.png +0 -0
  88. snappy/doc/_static/SnapPy.ico +0 -0
  89. snappy/doc/_static/_sphinx_javascript_frameworks_compat.js +123 -0
  90. snappy/doc/_static/basic.css +906 -0
  91. snappy/doc/_static/css/badge_only.css +1 -0
  92. snappy/doc/_static/css/fonts/Roboto-Slab-Bold.woff +0 -0
  93. snappy/doc/_static/css/fonts/Roboto-Slab-Bold.woff2 +0 -0
  94. snappy/doc/_static/css/fonts/Roboto-Slab-Regular.woff +0 -0
  95. snappy/doc/_static/css/fonts/Roboto-Slab-Regular.woff2 +0 -0
  96. snappy/doc/_static/css/fonts/fontawesome-webfont.eot +0 -0
  97. snappy/doc/_static/css/fonts/fontawesome-webfont.svg +2671 -0
  98. snappy/doc/_static/css/fonts/fontawesome-webfont.ttf +0 -0
  99. snappy/doc/_static/css/fonts/fontawesome-webfont.woff +0 -0
  100. snappy/doc/_static/css/fonts/fontawesome-webfont.woff2 +0 -0
  101. snappy/doc/_static/css/fonts/lato-bold-italic.woff +0 -0
  102. snappy/doc/_static/css/fonts/lato-bold-italic.woff2 +0 -0
  103. snappy/doc/_static/css/fonts/lato-bold.woff +0 -0
  104. snappy/doc/_static/css/fonts/lato-bold.woff2 +0 -0
  105. snappy/doc/_static/css/fonts/lato-normal-italic.woff +0 -0
  106. snappy/doc/_static/css/fonts/lato-normal-italic.woff2 +0 -0
  107. snappy/doc/_static/css/fonts/lato-normal.woff +0 -0
  108. snappy/doc/_static/css/fonts/lato-normal.woff2 +0 -0
  109. snappy/doc/_static/css/theme.css +4 -0
  110. snappy/doc/_static/doctools.js +149 -0
  111. snappy/doc/_static/documentation_options.js +13 -0
  112. snappy/doc/_static/file.png +0 -0
  113. snappy/doc/_static/fonts/Lato/lato-bold.eot +0 -0
  114. snappy/doc/_static/fonts/Lato/lato-bold.ttf +0 -0
  115. snappy/doc/_static/fonts/Lato/lato-bold.woff +0 -0
  116. snappy/doc/_static/fonts/Lato/lato-bold.woff2 +0 -0
  117. snappy/doc/_static/fonts/Lato/lato-bolditalic.eot +0 -0
  118. snappy/doc/_static/fonts/Lato/lato-bolditalic.ttf +0 -0
  119. snappy/doc/_static/fonts/Lato/lato-bolditalic.woff +0 -0
  120. snappy/doc/_static/fonts/Lato/lato-bolditalic.woff2 +0 -0
  121. snappy/doc/_static/fonts/Lato/lato-italic.eot +0 -0
  122. snappy/doc/_static/fonts/Lato/lato-italic.ttf +0 -0
  123. snappy/doc/_static/fonts/Lato/lato-italic.woff +0 -0
  124. snappy/doc/_static/fonts/Lato/lato-italic.woff2 +0 -0
  125. snappy/doc/_static/fonts/Lato/lato-regular.eot +0 -0
  126. snappy/doc/_static/fonts/Lato/lato-regular.ttf +0 -0
  127. snappy/doc/_static/fonts/Lato/lato-regular.woff +0 -0
  128. snappy/doc/_static/fonts/Lato/lato-regular.woff2 +0 -0
  129. snappy/doc/_static/fonts/RobotoSlab/roboto-slab-v7-bold.eot +0 -0
  130. snappy/doc/_static/fonts/RobotoSlab/roboto-slab-v7-bold.ttf +0 -0
  131. snappy/doc/_static/fonts/RobotoSlab/roboto-slab-v7-bold.woff +0 -0
  132. snappy/doc/_static/fonts/RobotoSlab/roboto-slab-v7-bold.woff2 +0 -0
  133. snappy/doc/_static/fonts/RobotoSlab/roboto-slab-v7-regular.eot +0 -0
  134. snappy/doc/_static/fonts/RobotoSlab/roboto-slab-v7-regular.ttf +0 -0
  135. snappy/doc/_static/fonts/RobotoSlab/roboto-slab-v7-regular.woff +0 -0
  136. snappy/doc/_static/fonts/RobotoSlab/roboto-slab-v7-regular.woff2 +0 -0
  137. snappy/doc/_static/jquery.js +2 -0
  138. snappy/doc/_static/js/badge_only.js +1 -0
  139. snappy/doc/_static/js/theme.js +1 -0
  140. snappy/doc/_static/js/versions.js +228 -0
  141. snappy/doc/_static/language_data.js +192 -0
  142. snappy/doc/_static/minus.png +0 -0
  143. snappy/doc/_static/plus.png +0 -0
  144. snappy/doc/_static/pygments.css +75 -0
  145. snappy/doc/_static/searchtools.js +635 -0
  146. snappy/doc/_static/snappy_furo.css +33 -0
  147. snappy/doc/_static/snappy_sphinx_rtd_theme.css +42 -0
  148. snappy/doc/_static/sphinx_highlight.js +154 -0
  149. snappy/doc/additional_classes.html +1500 -0
  150. snappy/doc/bugs.html +132 -0
  151. snappy/doc/censuses.html +453 -0
  152. snappy/doc/credits.html +184 -0
  153. snappy/doc/development.html +385 -0
  154. snappy/doc/doc-latest/additional_classes.html +1500 -0
  155. snappy/doc/doc-latest/bugs.html +132 -0
  156. snappy/doc/doc-latest/censuses.html +453 -0
  157. snappy/doc/doc-latest/credits.html +184 -0
  158. snappy/doc/doc-latest/development.html +385 -0
  159. snappy/doc/doc-latest/genindex.html +1349 -0
  160. snappy/doc/doc-latest/index.html +287 -0
  161. snappy/doc/doc-latest/installing.html +346 -0
  162. snappy/doc/doc-latest/manifold.html +3632 -0
  163. snappy/doc/doc-latest/manifoldhp.html +180 -0
  164. snappy/doc/doc-latest/news.html +438 -0
  165. snappy/doc/doc-latest/objects.inv +0 -0
  166. snappy/doc/doc-latest/other.html +160 -0
  167. snappy/doc/doc-latest/platonic_census.html +376 -0
  168. snappy/doc/doc-latest/plink.html +210 -0
  169. snappy/doc/doc-latest/ptolemy.html +253 -0
  170. snappy/doc/doc-latest/ptolemy_classes.html +1144 -0
  171. snappy/doc/doc-latest/ptolemy_examples1.html +409 -0
  172. snappy/doc/doc-latest/ptolemy_examples2.html +471 -0
  173. snappy/doc/doc-latest/ptolemy_examples3.html +414 -0
  174. snappy/doc/doc-latest/ptolemy_examples4.html +195 -0
  175. snappy/doc/doc-latest/ptolemy_prelim.html +248 -0
  176. snappy/doc/doc-latest/py-modindex.html +165 -0
  177. snappy/doc/doc-latest/screenshots.html +141 -0
  178. snappy/doc/doc-latest/search.html +135 -0
  179. snappy/doc/doc-latest/searchindex.js +1 -0
  180. snappy/doc/doc-latest/snap.html +202 -0
  181. snappy/doc/doc-latest/snappy.html +181 -0
  182. snappy/doc/doc-latest/spherogram.html +1346 -0
  183. snappy/doc/doc-latest/todo.html +166 -0
  184. snappy/doc/doc-latest/triangulation.html +1676 -0
  185. snappy/doc/doc-latest/tutorial.html +159 -0
  186. snappy/doc/doc-latest/verify.html +330 -0
  187. snappy/doc/doc-latest/verify_internals.html +1235 -0
  188. snappy/doc/genindex.html +1349 -0
  189. snappy/doc/index.html +287 -0
  190. snappy/doc/installing.html +346 -0
  191. snappy/doc/manifold.html +3632 -0
  192. snappy/doc/manifoldhp.html +180 -0
  193. snappy/doc/news.html +438 -0
  194. snappy/doc/objects.inv +0 -0
  195. snappy/doc/other.html +160 -0
  196. snappy/doc/platonic_census.html +376 -0
  197. snappy/doc/plink.html +210 -0
  198. snappy/doc/ptolemy.html +253 -0
  199. snappy/doc/ptolemy_classes.html +1144 -0
  200. snappy/doc/ptolemy_examples1.html +409 -0
  201. snappy/doc/ptolemy_examples2.html +471 -0
  202. snappy/doc/ptolemy_examples3.html +414 -0
  203. snappy/doc/ptolemy_examples4.html +195 -0
  204. snappy/doc/ptolemy_prelim.html +248 -0
  205. snappy/doc/py-modindex.html +165 -0
  206. snappy/doc/screenshots.html +141 -0
  207. snappy/doc/search.html +135 -0
  208. snappy/doc/searchindex.js +1 -0
  209. snappy/doc/snap.html +202 -0
  210. snappy/doc/snappy.html +181 -0
  211. snappy/doc/spherogram.html +1346 -0
  212. snappy/doc/todo.html +166 -0
  213. snappy/doc/triangulation.html +1676 -0
  214. snappy/doc/tutorial.html +159 -0
  215. snappy/doc/verify.html +330 -0
  216. snappy/doc/verify_internals.html +1235 -0
  217. snappy/drilling/__init__.py +456 -0
  218. snappy/drilling/barycentric.py +103 -0
  219. snappy/drilling/constants.py +5 -0
  220. snappy/drilling/crush.py +270 -0
  221. snappy/drilling/cusps.py +125 -0
  222. snappy/drilling/debug.py +242 -0
  223. snappy/drilling/epsilons.py +6 -0
  224. snappy/drilling/exceptions.py +55 -0
  225. snappy/drilling/moves.py +620 -0
  226. snappy/drilling/peripheral_curves.py +210 -0
  227. snappy/drilling/perturb.py +188 -0
  228. snappy/drilling/shorten.py +36 -0
  229. snappy/drilling/subdivide.py +274 -0
  230. snappy/drilling/test.py +23 -0
  231. snappy/drilling/test_cases.py +132 -0
  232. snappy/drilling/tracing.py +351 -0
  233. snappy/exceptions.py +26 -0
  234. snappy/export_stl.py +120 -0
  235. snappy/exterior_to_link/__init__.py +2 -0
  236. snappy/exterior_to_link/barycentric_geometry.py +463 -0
  237. snappy/exterior_to_link/exceptions.py +6 -0
  238. snappy/exterior_to_link/geodesic_map.json +14408 -0
  239. snappy/exterior_to_link/hyp_utils.py +112 -0
  240. snappy/exterior_to_link/link_projection.py +323 -0
  241. snappy/exterior_to_link/main.py +198 -0
  242. snappy/exterior_to_link/mcomplex_with_expansion.py +261 -0
  243. snappy/exterior_to_link/mcomplex_with_link.py +687 -0
  244. snappy/exterior_to_link/mcomplex_with_memory.py +162 -0
  245. snappy/exterior_to_link/pl_utils.py +491 -0
  246. snappy/exterior_to_link/put_in_S3.py +156 -0
  247. snappy/exterior_to_link/rational_linear_algebra.py +130 -0
  248. snappy/exterior_to_link/rational_linear_algebra_wrapped.py +135 -0
  249. snappy/exterior_to_link/simplify_to_base_tri.py +114 -0
  250. snappy/exterior_to_link/stored_moves.py +475 -0
  251. snappy/exterior_to_link/test.py +31 -0
  252. snappy/filedialog.py +28 -0
  253. snappy/geometric_structure/__init__.py +212 -0
  254. snappy/geometric_structure/cusp_neighborhood/__init__.py +3 -0
  255. snappy/geometric_structure/cusp_neighborhood/complex_cusp_cross_section.py +691 -0
  256. snappy/geometric_structure/cusp_neighborhood/cusp_cross_section_base.py +480 -0
  257. snappy/geometric_structure/cusp_neighborhood/exceptions.py +41 -0
  258. snappy/geometric_structure/cusp_neighborhood/real_cusp_cross_section.py +294 -0
  259. snappy/geometric_structure/cusp_neighborhood/tiles_for_cusp_neighborhood.py +156 -0
  260. snappy/geometric_structure/cusp_neighborhood/vertices.py +35 -0
  261. snappy/geometric_structure/geodesic/__init__.py +0 -0
  262. snappy/geometric_structure/geodesic/add_core_curves.py +152 -0
  263. snappy/geometric_structure/geodesic/avoid_core_curves.py +369 -0
  264. snappy/geometric_structure/geodesic/canonical_representatives.py +52 -0
  265. snappy/geometric_structure/geodesic/check_away_from_core_curve.py +60 -0
  266. snappy/geometric_structure/geodesic/constants.py +6 -0
  267. snappy/geometric_structure/geodesic/exceptions.py +22 -0
  268. snappy/geometric_structure/geodesic/fixed_points.py +106 -0
  269. snappy/geometric_structure/geodesic/geodesic_start_point_info.py +435 -0
  270. snappy/geometric_structure/geodesic/graph_trace_helper.py +67 -0
  271. snappy/geometric_structure/geodesic/line.py +30 -0
  272. snappy/geometric_structure/geodesic/multiplicity.py +127 -0
  273. snappy/geometric_structure/geodesic/tiles_for_geodesic.py +128 -0
  274. snappy/geometric_structure/test.py +22 -0
  275. snappy/gui.py +121 -0
  276. snappy/horoviewer.py +443 -0
  277. snappy/hyperboloid/__init__.py +212 -0
  278. snappy/hyperboloid/distances.py +259 -0
  279. snappy/hyperboloid/horoball.py +19 -0
  280. snappy/hyperboloid/line.py +35 -0
  281. snappy/hyperboloid/point.py +9 -0
  282. snappy/hyperboloid/triangle.py +29 -0
  283. snappy/info_icon.gif +0 -0
  284. snappy/infowindow.py +65 -0
  285. snappy/isometry_signature.py +389 -0
  286. snappy/len_spec/__init__.py +609 -0
  287. snappy/len_spec/geodesic_info.py +129 -0
  288. snappy/len_spec/geodesic_key_info_dict.py +116 -0
  289. snappy/len_spec/geodesic_piece.py +146 -0
  290. snappy/len_spec/geometric_structure.py +182 -0
  291. snappy/len_spec/geometry.py +136 -0
  292. snappy/len_spec/length_spectrum_geodesic_info.py +185 -0
  293. snappy/len_spec/spine.py +128 -0
  294. snappy/len_spec/test.py +24 -0
  295. snappy/len_spec/test_cases.py +69 -0
  296. snappy/len_spec/tile.py +276 -0
  297. snappy/len_spec/word.py +86 -0
  298. snappy/manifolds/HTWKnots/alternating.gz +0 -0
  299. snappy/manifolds/HTWKnots/nonalternating.gz +0 -0
  300. snappy/manifolds/__init__.py +3 -0
  301. snappy/margulis/__init__.py +332 -0
  302. snappy/margulis/cusp_neighborhood_neighborhood.py +66 -0
  303. snappy/margulis/geodesic_neighborhood.py +152 -0
  304. snappy/margulis/margulis_info.py +21 -0
  305. snappy/margulis/mu_from_neighborhood_pair.py +175 -0
  306. snappy/margulis/neighborhood.py +29 -0
  307. snappy/margulis/test.py +22 -0
  308. snappy/math_basics.py +187 -0
  309. snappy/matrix.py +525 -0
  310. snappy/number.py +657 -0
  311. snappy/numeric_output_checker.py +345 -0
  312. snappy/pari.py +41 -0
  313. snappy/phone_home.py +57 -0
  314. snappy/polyviewer.py +259 -0
  315. snappy/ptolemy/__init__.py +17 -0
  316. snappy/ptolemy/component.py +103 -0
  317. snappy/ptolemy/coordinates.py +2290 -0
  318. snappy/ptolemy/fieldExtensions.py +153 -0
  319. snappy/ptolemy/findLoops.py +473 -0
  320. snappy/ptolemy/geometricRep.py +59 -0
  321. snappy/ptolemy/homology.py +165 -0
  322. snappy/ptolemy/magma/default.magma_template +229 -0
  323. snappy/ptolemy/magma/radicalsOfPrimaryDecomposition.magma_template +79 -0
  324. snappy/ptolemy/manifoldMethods.py +395 -0
  325. snappy/ptolemy/matrix.py +350 -0
  326. snappy/ptolemy/numericalSolutionsToGroebnerBasis.py +113 -0
  327. snappy/ptolemy/polynomial.py +856 -0
  328. snappy/ptolemy/processComponents.py +173 -0
  329. snappy/ptolemy/processFileBase.py +247 -0
  330. snappy/ptolemy/processFileDispatch.py +46 -0
  331. snappy/ptolemy/processMagmaFile.py +392 -0
  332. snappy/ptolemy/processRurFile.py +150 -0
  333. snappy/ptolemy/ptolemyGeneralizedObstructionClass.py +102 -0
  334. snappy/ptolemy/ptolemyObstructionClass.py +64 -0
  335. snappy/ptolemy/ptolemyVariety.py +995 -0
  336. snappy/ptolemy/ptolemyVarietyPrimeIdealGroebnerBasis.py +140 -0
  337. snappy/ptolemy/reginaWrapper.py +698 -0
  338. snappy/ptolemy/regina_testing_files/DT_mcbbiceaibjklmdfgh__sl2_c0.magma_out.bz2 +0 -0
  339. snappy/ptolemy/regina_testing_files/DT_mcbbiceaibjklmdfgh__sl2_c1.magma_out.bz2 +0 -0
  340. snappy/ptolemy/regina_testing_files/DT_mcbbiceaibjklmdfgh__sl2_c2.magma_out.bz2 +0 -0
  341. snappy/ptolemy/regina_testing_files/DT_mcbbiceaibjklmdfgh__sl2_c3.magma_out.bz2 +0 -0
  342. snappy/ptolemy/regina_testing_files/DT_mcbbiceaibjklmdfgh__sl2_c4.magma_out.bz2 +0 -0
  343. snappy/ptolemy/regina_testing_files/DT_mcbbiceaibjklmdfgh__sl2_c5.magma_out.bz2 +0 -0
  344. snappy/ptolemy/regina_testing_files/DT_mcbbiceaibjklmdfgh__sl2_c6.magma_out.bz2 +0 -0
  345. snappy/ptolemy/regina_testing_files/DT_mcbbiceaibjklmdfgh__sl2_c7.magma_out.bz2 +0 -0
  346. snappy/ptolemy/regina_testing_files_generalized/m003__sl3_c0.magma_out.bz2 +0 -0
  347. snappy/ptolemy/regina_testing_files_generalized/m003__sl3_c1.magma_out.bz2 +0 -0
  348. snappy/ptolemy/regina_testing_files_generalized/m015__sl2_c0.magma_out.bz2 +0 -0
  349. snappy/ptolemy/regina_testing_files_generalized/m015__sl2_c1.magma_out.bz2 +0 -0
  350. snappy/ptolemy/regina_testing_files_generalized/m015__sl3_c0.magma_out.bz2 +0 -0
  351. snappy/ptolemy/regina_testing_files_generalized/m015__sl3_c1.magma_out.bz2 +0 -0
  352. snappy/ptolemy/rur.py +545 -0
  353. snappy/ptolemy/solutionsToPrimeIdealGroebnerBasis.py +277 -0
  354. snappy/ptolemy/test.py +1126 -0
  355. snappy/ptolemy/testing_files/3_1__sl2_c0.magma_out.bz2 +0 -0
  356. snappy/ptolemy/testing_files/3_1__sl2_c1.magma_out.bz2 +0 -0
  357. snappy/ptolemy/testing_files/4_1__sl2_c0.magma_out.bz2 +0 -0
  358. snappy/ptolemy/testing_files/4_1__sl2_c1.magma_out.bz2 +0 -0
  359. snappy/ptolemy/testing_files/4_1__sl3_c0.magma_out.bz2 +0 -0
  360. snappy/ptolemy/testing_files/4_1__sl4_c0.magma_out.bz2 +0 -0
  361. snappy/ptolemy/testing_files/4_1__sl4_c1.magma_out.bz2 +0 -0
  362. snappy/ptolemy/testing_files/5_2__sl2_c0.magma_out.bz2 +0 -0
  363. snappy/ptolemy/testing_files/5_2__sl2_c1.magma_out.bz2 +0 -0
  364. snappy/ptolemy/testing_files/DT_mcbbiceaibjklmdfgh__sl2_c0.magma_out.bz2 +0 -0
  365. snappy/ptolemy/testing_files/DT_mcbbiceaibjklmdfgh__sl2_c1.magma_out.bz2 +0 -0
  366. snappy/ptolemy/testing_files/DT_mcbbiceaibjklmdfgh__sl2_c2.magma_out.bz2 +0 -0
  367. snappy/ptolemy/testing_files/DT_mcbbiceaibjklmdfgh__sl2_c3.magma_out.bz2 +0 -0
  368. snappy/ptolemy/testing_files/DT_mcbbiceaibjklmdfgh__sl2_c4.magma_out.bz2 +0 -0
  369. snappy/ptolemy/testing_files/DT_mcbbiceaibjklmdfgh__sl2_c5.magma_out.bz2 +0 -0
  370. snappy/ptolemy/testing_files/DT_mcbbiceaibjklmdfgh__sl2_c6.magma_out.bz2 +0 -0
  371. snappy/ptolemy/testing_files/DT_mcbbiceaibjklmdfgh__sl2_c7.magma_out.bz2 +0 -0
  372. snappy/ptolemy/testing_files/data/pgl2/OrientableCuspedCensus/03_tetrahedra/m019__sl2_c0.magma_out +95 -0
  373. snappy/ptolemy/testing_files/data/pgl2/OrientableCuspedCensus/03_tetrahedra/m019__sl2_c1.magma_out +95 -0
  374. snappy/ptolemy/testing_files/m015__sl3_c0.magma_out.bz2 +0 -0
  375. snappy/ptolemy/testing_files/m135__sl2_c0.magma_out.bz2 +0 -0
  376. snappy/ptolemy/testing_files/m135__sl2_c1.magma_out.bz2 +0 -0
  377. snappy/ptolemy/testing_files/m135__sl2_c2.magma_out.bz2 +0 -0
  378. snappy/ptolemy/testing_files/m135__sl2_c3.magma_out.bz2 +0 -0
  379. snappy/ptolemy/testing_files/m135__sl2_c4.magma_out.bz2 +0 -0
  380. snappy/ptolemy/testing_files/m135__sl2_c5.magma_out.bz2 +0 -0
  381. snappy/ptolemy/testing_files/m135__sl2_c6.magma_out.bz2 +0 -0
  382. snappy/ptolemy/testing_files/m135__sl2_c7.magma_out.bz2 +0 -0
  383. snappy/ptolemy/testing_files/s000__sl2_c0.magma_out.bz2 +0 -0
  384. snappy/ptolemy/testing_files/s000__sl2_c1.magma_out.bz2 +0 -0
  385. snappy/ptolemy/testing_files/t00000__sl2_c0.magma_out.bz2 +0 -0
  386. snappy/ptolemy/testing_files/t00000__sl2_c1.magma_out.bz2 +0 -0
  387. snappy/ptolemy/testing_files/v0000__sl2_c0.magma_out.bz2 +0 -0
  388. snappy/ptolemy/testing_files/v0000__sl2_c1.magma_out.bz2 +0 -0
  389. snappy/ptolemy/testing_files/v0000__sl2_c2.magma_out.bz2 +0 -0
  390. snappy/ptolemy/testing_files/v0000__sl2_c3.magma_out.bz2 +0 -0
  391. snappy/ptolemy/testing_files_generalized/m003__sl2_c0.magma_out.bz2 +0 -0
  392. snappy/ptolemy/testing_files_generalized/m003__sl2_c1.magma_out.bz2 +0 -0
  393. snappy/ptolemy/testing_files_generalized/m003__sl3_c0.magma_out.bz2 +0 -0
  394. snappy/ptolemy/testing_files_generalized/m003__sl3_c1.magma_out.bz2 +0 -0
  395. snappy/ptolemy/testing_files_generalized/m004__sl2_c0.magma_out.bz2 +0 -0
  396. snappy/ptolemy/testing_files_generalized/m004__sl2_c1.magma_out.bz2 +0 -0
  397. snappy/ptolemy/testing_files_generalized/m015__sl2_c1.magma_out.bz2 +0 -0
  398. snappy/ptolemy/testing_files_generalized/m015__sl3_c0.magma_out.bz2 +0 -0
  399. snappy/ptolemy/testing_files_rur/m052__sl3_c0.rur.bz2 +0 -0
  400. snappy/ptolemy/utilities.py +236 -0
  401. snappy/raytracing/__init__.py +64 -0
  402. snappy/raytracing/additional_horospheres.py +64 -0
  403. snappy/raytracing/additional_len_spec_choices.py +63 -0
  404. snappy/raytracing/cohomology_fractal.py +197 -0
  405. snappy/raytracing/eyeball.py +124 -0
  406. snappy/raytracing/finite_raytracing_data.py +237 -0
  407. snappy/raytracing/finite_viewer.py +590 -0
  408. snappy/raytracing/geodesic_tube_info.py +174 -0
  409. snappy/raytracing/geodesics.py +246 -0
  410. snappy/raytracing/geodesics_window.py +258 -0
  411. snappy/raytracing/gui_utilities.py +293 -0
  412. snappy/raytracing/hyperboloid_navigation.py +556 -0
  413. snappy/raytracing/hyperboloid_utilities.py +234 -0
  414. snappy/raytracing/ideal_raytracing_data.py +592 -0
  415. snappy/raytracing/inside_viewer.py +974 -0
  416. snappy/raytracing/pack.py +22 -0
  417. snappy/raytracing/raytracing_data.py +126 -0
  418. snappy/raytracing/raytracing_view.py +454 -0
  419. snappy/raytracing/shaders/Eye.png +0 -0
  420. snappy/raytracing/shaders/NonGeometric.png +0 -0
  421. snappy/raytracing/shaders/__init__.py +101 -0
  422. snappy/raytracing/shaders/fragment.glsl +1744 -0
  423. snappy/raytracing/test.py +29 -0
  424. snappy/raytracing/tooltip.py +146 -0
  425. snappy/raytracing/upper_halfspace_utilities.py +98 -0
  426. snappy/raytracing/view_scale_controller.py +98 -0
  427. snappy/raytracing/zoom_slider/__init__.py +263 -0
  428. snappy/raytracing/zoom_slider/inward.png +0 -0
  429. snappy/raytracing/zoom_slider/inward18.png +0 -0
  430. snappy/raytracing/zoom_slider/outward.png +0 -0
  431. snappy/raytracing/zoom_slider/outward18.png +0 -0
  432. snappy/raytracing/zoom_slider/test.py +20 -0
  433. snappy/sage_helper.py +119 -0
  434. snappy/settings.py +407 -0
  435. snappy/shell.py +53 -0
  436. snappy/snap/__init__.py +117 -0
  437. snappy/snap/character_varieties.py +375 -0
  438. snappy/snap/find_field.py +372 -0
  439. snappy/snap/fox_milnor.py +271 -0
  440. snappy/snap/fundamental_polyhedron.py +569 -0
  441. snappy/snap/generators.py +39 -0
  442. snappy/snap/interval_reps.py +81 -0
  443. snappy/snap/kernel_structures.py +128 -0
  444. snappy/snap/mcomplex_base.py +18 -0
  445. snappy/snap/nsagetools.py +716 -0
  446. snappy/snap/peripheral/__init__.py +1 -0
  447. snappy/snap/peripheral/dual_cellulation.py +219 -0
  448. snappy/snap/peripheral/link.py +127 -0
  449. snappy/snap/peripheral/peripheral.py +159 -0
  450. snappy/snap/peripheral/surface.py +522 -0
  451. snappy/snap/peripheral/test.py +35 -0
  452. snappy/snap/polished_reps.py +335 -0
  453. snappy/snap/shapes.py +152 -0
  454. snappy/snap/slice_obs_HKL/__init__.py +194 -0
  455. snappy/snap/slice_obs_HKL/basics.py +236 -0
  456. snappy/snap/slice_obs_HKL/direct.py +217 -0
  457. snappy/snap/slice_obs_HKL/poly_norm.py +212 -0
  458. snappy/snap/slice_obs_HKL/rep_theory.py +424 -0
  459. snappy/snap/t3mlite/__init__.py +2 -0
  460. snappy/snap/t3mlite/arrow.py +243 -0
  461. snappy/snap/t3mlite/corner.py +22 -0
  462. snappy/snap/t3mlite/edge.py +172 -0
  463. snappy/snap/t3mlite/face.py +37 -0
  464. snappy/snap/t3mlite/files.py +211 -0
  465. snappy/snap/t3mlite/homology.py +53 -0
  466. snappy/snap/t3mlite/linalg.py +419 -0
  467. snappy/snap/t3mlite/mcomplex.py +1499 -0
  468. snappy/snap/t3mlite/perm4.py +320 -0
  469. snappy/snap/t3mlite/setup.py +12 -0
  470. snappy/snap/t3mlite/simplex.py +199 -0
  471. snappy/snap/t3mlite/spun.py +297 -0
  472. snappy/snap/t3mlite/surface.py +519 -0
  473. snappy/snap/t3mlite/test.py +20 -0
  474. snappy/snap/t3mlite/test_vs_regina.py +86 -0
  475. snappy/snap/t3mlite/tetrahedron.py +109 -0
  476. snappy/snap/t3mlite/vertex.py +42 -0
  477. snappy/snap/test.py +139 -0
  478. snappy/snap/utilities.py +288 -0
  479. snappy/test.py +213 -0
  480. snappy/test_cases.py +263 -0
  481. snappy/testing.py +131 -0
  482. snappy/tiling/__init__.py +2 -0
  483. snappy/tiling/dict_based_set.py +79 -0
  484. snappy/tiling/floor.py +49 -0
  485. snappy/tiling/hyperboloid_dict.py +54 -0
  486. snappy/tiling/iter_utils.py +78 -0
  487. snappy/tiling/lifted_tetrahedron.py +22 -0
  488. snappy/tiling/lifted_tetrahedron_set.py +54 -0
  489. snappy/tiling/quotient_dict.py +70 -0
  490. snappy/tiling/real_hash_dict.py +164 -0
  491. snappy/tiling/test.py +23 -0
  492. snappy/tiling/tile.py +224 -0
  493. snappy/tiling/triangle.py +33 -0
  494. snappy/tkterminal.py +920 -0
  495. snappy/twister/__init__.py +20 -0
  496. snappy/twister/main.py +646 -0
  497. snappy/twister/surfaces/S_0_1 +3 -0
  498. snappy/twister/surfaces/S_0_2 +3 -0
  499. snappy/twister/surfaces/S_0_4 +7 -0
  500. snappy/twister/surfaces/S_0_4_Lantern +8 -0
  501. snappy/twister/surfaces/S_1 +3 -0
  502. snappy/twister/surfaces/S_1_1 +4 -0
  503. snappy/twister/surfaces/S_1_2 +5 -0
  504. snappy/twister/surfaces/S_1_2_5 +6 -0
  505. snappy/twister/surfaces/S_2 +6 -0
  506. snappy/twister/surfaces/S_2_1 +8 -0
  507. snappy/twister/surfaces/S_2_heeg +10 -0
  508. snappy/twister/surfaces/S_3 +8 -0
  509. snappy/twister/surfaces/S_3_1 +10 -0
  510. snappy/twister/surfaces/S_4_1 +12 -0
  511. snappy/twister/surfaces/S_5_1 +14 -0
  512. snappy/twister/surfaces/heeg_fig8 +9 -0
  513. snappy/twister/twister_core.cpython-310-aarch64-linux-gnu.so +0 -0
  514. snappy/upper_halfspace/__init__.py +146 -0
  515. snappy/upper_halfspace/ideal_point.py +29 -0
  516. snappy/verify/__init__.py +13 -0
  517. snappy/verify/canonical.py +542 -0
  518. snappy/verify/complex_volume/__init__.py +18 -0
  519. snappy/verify/complex_volume/adjust_torsion.py +86 -0
  520. snappy/verify/complex_volume/closed.py +168 -0
  521. snappy/verify/complex_volume/compute_ptolemys.py +90 -0
  522. snappy/verify/complex_volume/cusped.py +56 -0
  523. snappy/verify/complex_volume/extended_bloch.py +201 -0
  524. snappy/verify/cusp_translations.py +85 -0
  525. snappy/verify/edge_equations.py +80 -0
  526. snappy/verify/exceptions.py +254 -0
  527. snappy/verify/hyperbolicity.py +224 -0
  528. snappy/verify/interval_newton_shapes_engine.py +523 -0
  529. snappy/verify/interval_tree.py +400 -0
  530. snappy/verify/krawczyk_shapes_engine.py +518 -0
  531. snappy/verify/real_algebra.py +286 -0
  532. snappy/verify/shapes.py +25 -0
  533. snappy/verify/square_extensions.py +1005 -0
  534. snappy/verify/test.py +72 -0
  535. snappy/verify/volume.py +128 -0
  536. snappy/version.py +2 -0
  537. snappy-3.3.dist-info/METADATA +58 -0
  538. snappy-3.3.dist-info/RECORD +541 -0
  539. snappy-3.3.dist-info/WHEEL +6 -0
  540. snappy-3.3.dist-info/entry_points.txt +2 -0
  541. snappy-3.3.dist-info/top_level.txt +28 -0
@@ -0,0 +1,1744 @@
1
+ #version 150
2
+
3
+ // GLSL version 1.50 corresponds to OpenGL 3.2 which is the version we target.
4
+
5
+ // History:
6
+ //
7
+ // This code was mostly written by Matthias Goerner during the
8
+ // "Illustrating Mathematics" workshop at ICERM in Fall 2019.
9
+ //
10
+ // Parts of it are taken from Cohomology fractals at
11
+ // https://github.com/henryseg/cohomology_fractals/tree/master/shaders
12
+ // The authors of Cohomology fractals and its history are listed at
13
+ // https://github.com/henryseg/cohomology_fractals/blob/master/README.md
14
+ //
15
+
16
+ #define COLOR_SCHEME 1
17
+
18
+ //--------------------------------------------
19
+ //Global Variables
20
+ //--------------------------------------------
21
+ out vec4 out_FragColor;
22
+
23
+ //-------------------------------------------
24
+ //Translation & Utility Variables
25
+ //--------------------------------------------
26
+
27
+ uniform vec2 screenResolution;
28
+ uniform float viewScale;
29
+ uniform bool crosshairs;
30
+
31
+ uniform int currentTetIndex;
32
+ uniform mat4 currentBoost;
33
+ uniform float currentWeight;
34
+
35
+ uniform int maxSteps;
36
+ uniform float maxDist;
37
+ uniform int subpixelCount;
38
+ uniform float edgeThicknessParam;
39
+ uniform float contrast;
40
+
41
+ const int perspectiveTypeMaterial = 0;
42
+ const int perspectiveTypeIdeal = 1;
43
+ const int perspectiveTypeHyperideal = 2;
44
+
45
+ uniform int perspectiveType;
46
+ uniform int viewMode;
47
+ uniform int multiScreenShot;
48
+ uniform vec2 tile;
49
+ uniform vec2 numTiles;
50
+ uniform bool noGradient;
51
+ uniform bool showElevation = false;
52
+
53
+ // Convention: ##NAME## names a compile time constant.
54
+ // The string ##NAME## is replaced by the code in __init__.py
55
+ // by looking up its value in the dictionary constants_dict.
56
+
57
+ layout (std140) uniform TetrahedraCombinatorics
58
+ {
59
+ int otherTetNums[4 * ##num_tets##];
60
+ int otherFaceNums[4 * ##num_tets##];
61
+ };
62
+
63
+ uniform float weights[4 * ##num_tets##];
64
+
65
+ layout (std140) uniform TetrahedraBasics
66
+ {
67
+ vec4 R13Vertices[4 * ##num_tets##];
68
+ vec4 planes[4 * ##num_tets##];
69
+ mat4 SO13tsfms[4 * ##num_tets##];
70
+ };
71
+
72
+ layout (std140) uniform Colors
73
+ {
74
+ int face_color_indices[4 * ##num_tets##];
75
+ int edge_color_indices[6 * ##num_tets##];
76
+ int vertex_color_indices[4 * ##num_tets##];
77
+ };
78
+
79
+ uniform bool desaturate_edges = false;
80
+
81
+ uniform float gradientThresholds[5];
82
+ uniform vec3 gradientColours[5];
83
+
84
+ uniform float edgeTubeRadiusParam;
85
+
86
+ uniform float lightBias;
87
+ uniform float lightFalloff;
88
+ uniform float brightness;
89
+ const vec4 lightSourcePosition = vec4(1.0, 0.0, 0.7, 0.0);
90
+
91
+ uniform bool isNonGeometric;
92
+ uniform sampler2D nonGeometricTexture;
93
+ uniform sampler2D eyeTexture;
94
+
95
+ const int num_tets = ##num_tets##;
96
+ const int num_edges = ##num_edges##;
97
+ const int num_cusps = ##num_cusps##;
98
+
99
+ #if ##finiteTrig##
100
+ layout (std140) uniform TetrahedraEdges
101
+ {
102
+ // Ends of edge 01 are 0 + 12 * tetNum and 1 + 12 * tetNum
103
+ // Ends of edge 02 are 2 + 12 * tetNum and 3 + 12 * tetNum
104
+ // Ends of edge 12 are 4 + 12 * tetNum and 5 + 12 * tetNum
105
+ // Ends of edge 03 ...
106
+ // Ends of edge 13 ...
107
+ // Ends of edge 23 are 10 + 12 * tetNum and 11 + 12 * tetNum
108
+ //
109
+ // Also see edgeToVertices
110
+ vec4 R13EdgeEnds[12 * ##num_tets##];
111
+ };
112
+
113
+ uniform float vertexSphereRadiusParam;
114
+
115
+ #else
116
+
117
+ // For an incomplete cusp, the Margulis tube is a cylinder about
118
+ // the geodesic the triangulation spins about. In other words,
119
+ // it is the cylinder fixed by the peripheral group of that cusp.
120
+ // We encode it by its two end points and cosh(radius)^2/2.
121
+ layout (std140) uniform MargulisTubes
122
+ {
123
+ vec4 margulisTubeTails[4 * ##num_tets##];
124
+ vec4 margulisTubeHeads[4 * ##num_tets##];
125
+ };
126
+ uniform float margulisTubeRadiusParams[4 * ##num_tets##];
127
+
128
+ #if defined(num_geodesic_segments) && num_geodesic_segments > 0
129
+ layout (std140) uniform geodesics
130
+ {
131
+ vec4 geodesicTails[num_geodesic_segments];
132
+ vec4 geodesicHeads[num_geodesic_segments];
133
+ int geodesicIndex[num_geodesic_segments];
134
+ float geodesicTubeRadiusParam[num_geodesic_segments];
135
+ int geodesicOffsets[##num_tets## + 1];
136
+ };
137
+ #endif
138
+
139
+ #if !defined(num_eyeballs)
140
+ #define num_eyeballs 0
141
+ #endif
142
+
143
+ #if num_eyeballs > 0
144
+ layout (std140) uniform eyeballs
145
+ {
146
+ vec4 eyeballPositions[num_eyeballs];
147
+ mat4 eyeballInvEmbeddings[num_eyeballs];
148
+ mat4 eyeballEmbeddings[num_eyeballs];
149
+ int eyeballOffsets[##num_tets## + 1];
150
+ };
151
+ uniform float eyeballRadius;
152
+
153
+ #if eyeball_type == 2
154
+ float eyeballRadiusParam = cosh(eyeballRadius) * cosh(eyeballRadius);
155
+ #else
156
+ float space_ship_width = 0.4;
157
+ float space_ship_fold_width = 0.13;
158
+ float space_ship_fold_height = 0.3;
159
+
160
+ vec4 space_ship_top_plane = vec4(0.0, 0.0, -1.0, 0.0);
161
+ vec4 space_ship_edges[2] = vec4[2](
162
+ vec4(0.0, 1.0 / space_ship_width, 0.0, 1.0),
163
+ vec4(0.0, -1.0 / space_ship_width, 0.0, 1.0));
164
+ vec4 space_ship_folds[2] = vec4[2](
165
+ vec4(0.0, 1.0 / space_ship_fold_width, 1.0 / space_ship_fold_height, 1.0),
166
+ vec4(0.0, -1.0 / space_ship_fold_width, 1.0 / space_ship_fold_height, 1.0));
167
+ float b = length(vec2(space_ship_fold_height, 1.0));
168
+ vec4 space_ship_back_plane = vec4(sinh(eyeballRadius), 0.0, 0.0, -b * cosh(eyeballRadius));
169
+ #endif
170
+
171
+ #endif
172
+
173
+ uniform float horosphereScales[4 * ##num_tets##];
174
+
175
+ #if defined(num_additional_horospheres) && num_additional_horospheres > 0
176
+ layout (std140) uniform additionalHorospheres
177
+ {
178
+ vec4 horosphereVec[num_additional_horospheres];
179
+ int horosphereCuspIndex[num_additional_horospheres];
180
+ int horosphereOffsets[##num_tets## + 1];
181
+ };
182
+
183
+ #endif
184
+
185
+ #if defined(has_edge_midpoints)
186
+ layout (std140) uniform edgeMidpoints
187
+ {
188
+ vec4 edgeMidpointVec[6 * ##num_tets##];
189
+ };
190
+
191
+ uniform float edgeMidpointRadiusParam;
192
+ #endif
193
+
194
+ // cosh(r)^2 where r is the radius of the sphere
195
+ // about the center of the tetrahedron.
196
+ uniform float insphereRadiusParams[##num_tets##];
197
+
198
+ // Matrix to convert between coordinates where the cusp is at
199
+ // infinity and the space of the tetrahedron
200
+ layout (std140) uniform TetCuspMatrices
201
+ {
202
+ mat4 tetToCuspMatrices[4 * ##num_tets##];
203
+ mat4 cuspToTetMatrices[4 * ##num_tets##];
204
+ };
205
+
206
+ uniform vec2 logAdjustments[4 * ##num_tets##];
207
+ uniform mat2 toStandardTorusMatrices[4 * ##num_tets##];
208
+
209
+ const float peripheralCurveThickness = 0.015;
210
+
211
+ #if COLOR_SCHEME == 1
212
+ const vec3 longitudeColor = vec3( 1.0 , 1.0 , 1.0 );
213
+ const vec3 meridianColor = vec3( 0.5 , 0.5 , 0.5 );
214
+ #else
215
+ const vec3 longitudeColor = vec3( 1.0 , 0.2 , 0.2 );
216
+ const vec3 meridianColor = vec3( 0.2 , 1.0 , 0.2 );
217
+ #endif
218
+
219
+ #endif
220
+
221
+ // Colouring function. All components are in the range [0...1], including hue.
222
+ // from http://lolengine.net/blog/2013/07/27/rgb-to-hsv-in-glsl
223
+ vec3 hsv2rgb(vec3 c)
224
+ {
225
+ vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
226
+ vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);
227
+ return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);
228
+ }
229
+
230
+ // Lorentz dot product with signature -+++
231
+ float
232
+ R13Dot(vec4 u, vec4 v)
233
+ {
234
+ return - u.x*v.x + u.y*v.y + u.z*v.z + u.w*v.w;
235
+ }
236
+
237
+ vec4
238
+ R13Normalise(vec4 v)
239
+ {
240
+ return v * inversesqrt(abs(R13Dot(v,v)));
241
+ }
242
+
243
+ // Given a direction vector and a point on the hyperbolic model, produces
244
+ // a unit tangent vector (in Minkowski space) at that point.
245
+ //
246
+ // It does by subtracting a suitable multiple of point from direction to
247
+ // make it orthogonal to point and then normalising.
248
+ vec4
249
+ makeUnitTangentVector(vec4 dir, vec4 point)
250
+ {
251
+ // Make dir orthogonal to point.
252
+ // Note that R13Dot(point, point) == -1, so we add instead of
253
+ // subtract.
254
+ vec4 t = dir + R13Dot(dir, point) * point;
255
+
256
+ return R13Normalise(t);
257
+ }
258
+
259
+ float
260
+ geodesicParameterPlanes(vec4 samplePoint, vec4 dualPoint1, vec4 dualPoint2){
261
+ // "distance" from a geodesic defined by two (assumed perpendicular) geodesic planes, this is not quite distance, need to asinh(sqrt( result ))
262
+
263
+ float dot1 = -R13Dot(samplePoint, dualPoint1);
264
+ vec4 dualPointPerp = R13Normalise(dualPoint2 - R13Dot(dualPoint1, dualPoint2) * dualPoint1); // should be precalculated if this is a main feature
265
+ float dot2 = -R13Dot(samplePoint, dualPointPerp);
266
+
267
+ return dot1*dot1 + dot2*dot2;
268
+ }
269
+
270
+ float
271
+ triangleBdryParam(vec4 samplePoint, int tetNum, int exit_face){
272
+ vec4 exit_dual_point = planes[4*tetNum + exit_face];
273
+ float smallest_p = 100000000.0;
274
+ for(int face=0; face<4; face++){
275
+ if(face != exit_face){ // find p when we hit that face
276
+ int index = 4*tetNum + face;
277
+ float new_p = geodesicParameterPlanes(samplePoint, exit_dual_point, planes[index]);
278
+ if(new_p < smallest_p){
279
+ smallest_p = new_p;
280
+ }
281
+ }
282
+ }
283
+ return smallest_p;
284
+ }
285
+
286
+ /// --- Ray-trace code --- ///
287
+
288
+ // Kind of object a ray hit.
289
+
290
+ const int object_type_nothing = 0;
291
+ const int object_type_face = 1;
292
+ const int object_type_edge_cylinder_enter = 2;
293
+ const int object_type_edge_cylinder_exit = 3;
294
+ const int object_type_horosphere_enter = 4;
295
+ const int object_type_horosphere_exit = 5;
296
+ const int object_type_edge_fan = 6;
297
+ const int object_type_insphere = 7;
298
+ const int object_type_vertex_sphere = 8;
299
+ const int object_type_margulis_tube_enter = 9;
300
+ const int object_type_margulis_tube_exit = 10;
301
+ const int object_type_elevation_enter = 11;
302
+ const int object_type_elevation_exit = 12;
303
+ const int object_type_geodesic_tube = 13;
304
+ const int object_type_additional_horosphere = 14;
305
+ const int object_type_eyeball = 15;
306
+ const int object_type_edge_midpoint = 16;
307
+
308
+ // A ray consists of a point in the hyperbolid model and a
309
+ // unit tangent vector dir orthogonal to the point with respect
310
+ // to the Lorentz product.
311
+ struct Ray
312
+ {
313
+ vec4 point;
314
+ vec4 dir;
315
+ };
316
+
317
+ // Ray with extra information what object was hit.
318
+ struct RayHit
319
+ {
320
+ Ray ray;
321
+ // What tetrahedron we are in.
322
+ int tet_num;
323
+ vec4 light_source;
324
+ // Distance the ray traveled from eye so far
325
+ float dist;
326
+ float weight;
327
+ float distWhenLeavingCusp;
328
+ // Type of object hit
329
+ int object_type;
330
+ // Index of object (within the tetrahedron), e.g.,
331
+ // 0-3 for horospheres, 0-5 for edges.
332
+ int object_index;
333
+
334
+ int object_subindex;
335
+ };
336
+
337
+ bool traceInsideVertexNeighborhood()
338
+ {
339
+ #if num_eyeballs > 0
340
+ return eyeballOffsets[##num_tets##] > 0;
341
+ #else
342
+ return false;
343
+ #endif
344
+ }
345
+
346
+ // We distinguish between:
347
+ // - colored ray hits: the geometry is lit, e.g., the cylinder
348
+ // about an edge reacts to light)
349
+ // - valued ray hits: we use a value such as the distance or cohomology
350
+ // fractal weight to compute a color using a color gradient
351
+ //
352
+ // Note that for subsampling, we need to average the value before
353
+ // applying the color gradient.
354
+ //
355
+ bool isColored(RayHit ray_hit)
356
+ {
357
+ return !(
358
+ ray_hit.object_type == object_type_nothing ||
359
+ ray_hit.object_type == object_type_face);
360
+ }
361
+
362
+ vec4
363
+ pointAdvancedByParam(Ray ray, float p)
364
+ {
365
+ return R13Normalise(ray.point + p * ray.dir );
366
+ }
367
+
368
+ // Advances ray by distance atanh(p).
369
+ //
370
+ // It is often more convenient to work with tanh(distance) rather than
371
+ // distance and we refer to tanh(distance) as "distParam".
372
+ void
373
+ advanceRayByDistParam(inout Ray ray, float p)
374
+ {
375
+ ray.point = pointAdvancedByParam(ray, p);
376
+ ray.dir = makeUnitTangentVector(ray.dir, ray.point);
377
+ }
378
+
379
+ // Returned as distParam by some methods to indicate that ray does not
380
+ // intersect object.
381
+ const float unreachableDistParam = 1000.0;
382
+
383
+ // Returns the real roots of the equation a * x^2 + b * x + c = 0, but
384
+ // each root is returned only if it is less than min_val.
385
+ // The existence of no such root is indicated by returning
386
+ // unreachableDistParam.
387
+ vec2
388
+ realRootsOfQuadratic(float a, float b, float c,
389
+ float min_val)
390
+ {
391
+ float d = b * b - 4 * a * c;
392
+ if (d < 0) {
393
+ return vec2(unreachableDistParam, unreachableDistParam);;
394
+ }
395
+ float offset = sign(a) * sqrt(d);
396
+ vec2 result = vec2(-b - offset, -b + offset) / (2 * a);
397
+ if (result.y < min_val) {
398
+ return vec2(unreachableDistParam, unreachableDistParam);;
399
+ }
400
+ if (result.x < min_val) {
401
+ return vec2(unreachableDistParam, result.y);
402
+ }
403
+ return result;
404
+ }
405
+
406
+ //--------------------------------------------
407
+ // Ray intersections
408
+ //
409
+ // Functions to compute the distParam (tanh(distance)) for the intersection
410
+ // of a ray with some object. Only the intersection of the ray entering an
411
+ // object is returned. No intersection is indicated by unreachableDistParam.
412
+
413
+ // Intersection with plane.
414
+ // The plane is given by all points such that the inner product
415
+ // of the point and the planeEqn is zero.
416
+ float
417
+ distParamForPlaneIntersection(Ray ray,
418
+ vec4 planeEqn)
419
+ {
420
+ // solve:
421
+ // R13Dot(planeEqn, ray.point + p * ray.dir) = 0
422
+ // R13Dot(planeEqn, ray.point) + p * R13Dot(planeEqn, ray.dir) = 0
423
+
424
+ float denom = R13Dot(planeEqn, ray.dir);
425
+ if(denom == 0.0) {
426
+ return unreachableDistParam;
427
+ }
428
+ return -R13Dot(planeEqn, ray.point) / denom;
429
+ }
430
+
431
+ // Intersection with sphere about given center (in hyperboloid model).
432
+ // The last parameter is the cosh(radius)^2.
433
+ vec2
434
+ distParamsForSphereIntersection(Ray ray,
435
+ vec4 center, float sphereRadiusParam)
436
+ {
437
+ float startDot = R13Dot(center, ray.point);
438
+ float dirDot = R13Dot(center, ray.dir);
439
+
440
+ return realRootsOfQuadratic(
441
+ dirDot * dirDot + sphereRadiusParam,
442
+ 2.0 * dirDot * startDot,
443
+ startDot * startDot - sphereRadiusParam,
444
+ 0.0);
445
+ }
446
+
447
+ // Intersection with horosphere defined by given light-like vector.
448
+ // The horosphere consists of all points such that the inner product
449
+ // with the light-like vector is -1.
450
+ vec2
451
+ distParamsForHorosphereIntersection(Ray ray,
452
+ vec4 horosphere)
453
+ {
454
+ return distParamsForSphereIntersection(ray, horosphere, 1);
455
+ }
456
+
457
+ // Intersection with cylinder about the geodesic with the two given
458
+ // (light-like) endpoints.
459
+ // tubeRadiusParam is cosh(radius)^2/2.
460
+ // This function can detect intersections of the ray that happen
461
+ // some distance before the start point of the ray. To use this feature,
462
+ // set minDistParam to a negative value, namely to tanh(-distance),
463
+ // where distance is how far back we want to track the ray.
464
+ vec2
465
+ distParamsForTubeIntersection(Ray ray,
466
+ vec4[2] endpoints,
467
+ float tubeRadiusParam,
468
+ float minDistParam)
469
+ {
470
+ // The points p (with R13Dot(p,p) = -1) on a tube about a
471
+ // geodesic are given by
472
+ //
473
+ // -tubeRadiusParam * R13Dot(endpoints[0], endpoints[1])
474
+ // = R13Dot(endpoints[0],p) * R13Dot(endpoints[1],p)
475
+ //
476
+ // To see this, note that the isometries of the tube about
477
+ // the geodesic act on the light-like endpoints by multiplying
478
+ // them by s and 1/s, respectively, where s > 0. It is easy
479
+ // to check that the equation is invariant under this action.
480
+ //
481
+ // To compute the tubeRadiusParam in terms of the tube radius,
482
+ // place the endpoints at (1,-1,0,0) and (1,1,0,0) and p at
483
+ // (cosh(radius),0,sinh(radius),0). We obtain
484
+ //
485
+ // tubeRadiusParam = cosh(radius)^2/2
486
+ //
487
+ // The ray is parameterized by
488
+ //
489
+ // p = p0 / sqrt(-R13Dot(p0, p0))
490
+ //
491
+ // where
492
+ // p0 = ray.point + t * ray.dir.
493
+ //
494
+ // Putting p into the above equation and multiplying by
495
+ // -R13Dot(p0, p0), we obtain a quadratic equation we can solve for.
496
+
497
+ float start0Dot = R13Dot(endpoints[0], ray.point);
498
+ float dir0Dot = R13Dot(endpoints[0], ray.dir);
499
+ float start1Dot = R13Dot(endpoints[1], ray.point);
500
+ float dir1Dot = R13Dot(endpoints[1], ray.dir);
501
+ float endDot = R13Dot(endpoints[0], endpoints[1]);
502
+
503
+ return realRootsOfQuadratic(
504
+ dir0Dot * dir1Dot - endDot * tubeRadiusParam,
505
+ start0Dot * dir1Dot + start1Dot * dir0Dot,
506
+ start0Dot * start1Dot + endDot * tubeRadiusParam,
507
+ minDistParam);
508
+ }
509
+
510
+ //--------------------------------------------
511
+ // Object normals
512
+ //
513
+ // Function to compute the normal of an object at the given point
514
+
515
+
516
+ // Normal for a sphere about the center.
517
+ vec4
518
+ normalForSphere(vec4 point, vec4 center)
519
+ {
520
+ vec4 t = center - point;
521
+
522
+ return makeUnitTangentVector(t, point);
523
+ }
524
+
525
+ // Normal for a cylinder between the two given (light-like) endpoints.
526
+ vec4
527
+ normalForTube(vec4 point, vec4[2] endpoints)
528
+ {
529
+ vec4 t = endpoints[0] * R13Dot(point, endpoints[1])
530
+ + endpoints[1] * R13Dot(point, endpoints[0]);
531
+
532
+ return - makeUnitTangentVector(t, point);
533
+ }
534
+
535
+ //--------------------------------------------
536
+ // Object helpers
537
+ //
538
+ // Various helpers to obtain object representations from
539
+ // the uniforms.
540
+
541
+ // Indices of vertices that are the end points of an edge.
542
+ //
543
+ // Needs to be consistent with SnapPy/t3m conventions
544
+ // (i.e., t3m's OneSubsimplices).
545
+ const ivec2[6] edgeToVertices = ivec2[](ivec2(0, 1),
546
+ ivec2(0, 2),
547
+ ivec2(1, 2),
548
+ ivec2(0, 3),
549
+ ivec2(1, 3),
550
+ ivec2(2, 3));
551
+
552
+ // The two endpoints of an edge of a tetrahedron
553
+ vec4[2]
554
+ endpointsForEdge(int tet, int edge)
555
+ {
556
+ #if ##finiteTrig##
557
+ return vec4[](R13EdgeEnds[12 * tet + 2 * edge ],
558
+ R13EdgeEnds[12 * tet + 2 * edge + 1]);
559
+ #else
560
+ return vec4[](R13Vertices[4 * tet + edgeToVertices[edge].x],
561
+ R13Vertices[4 * tet + edgeToVertices[edge].y]);
562
+ #endif
563
+ }
564
+
565
+ #if !##finiteTrig##
566
+ // The two endpoints of a Margulis tube.
567
+ vec4[2]
568
+ endpointsForMargulisTube(int index)
569
+ {
570
+ return vec4[](margulisTubeTails[index],
571
+ margulisTubeHeads[index]);
572
+ }
573
+
574
+ // The equation for the horosphere about a vertex in a tetrahedron.
575
+ // index is 4 * tetIndex + vertex.
576
+ vec4
577
+ horosphereEqn(int index)
578
+ {
579
+ return horosphereScales[index] * R13Vertices[index];
580
+ }
581
+
582
+ #if defined(num_geodesic_segments) && num_geodesic_segments > 0
583
+ // The two endpoints of a geodesic
584
+ vec4[2]
585
+ endpointsForGeodesic(int index)
586
+ {
587
+ return vec4[](geodesicTails[index],
588
+ geodesicHeads[index]);
589
+ }
590
+ #endif
591
+
592
+ #endif
593
+
594
+ vec4
595
+ normalForRayHit(RayHit ray_hit)
596
+ {
597
+ #if ##finiteTrig##
598
+ if(ray_hit.object_type == object_type_vertex_sphere) {
599
+ int index = 4 * ray_hit.tet_num + ray_hit.object_index;
600
+ return normalForSphere(ray_hit.ray.point, R13Vertices[index]);
601
+ }
602
+ #else
603
+ if(ray_hit.object_type == object_type_insphere) {
604
+ return normalForSphere(ray_hit.ray.point, vec4(1,0,0,0));
605
+ }
606
+
607
+ if(ray_hit.object_type == object_type_horosphere_enter) {
608
+ int index = 4 * ray_hit.tet_num + ray_hit.object_index;
609
+ return horosphereEqn(index) - ray_hit.ray.point;
610
+ }
611
+
612
+ if(ray_hit.object_type == object_type_horosphere_exit) {
613
+ int index = 4 * ray_hit.tet_num + ray_hit.object_index;
614
+ return ray_hit.ray.point - horosphereEqn(index);
615
+ }
616
+
617
+ if(ray_hit.object_type == object_type_margulis_tube_enter) {
618
+ int index = 4 * ray_hit.tet_num + ray_hit.object_index;
619
+ return normalForTube(
620
+ ray_hit.ray.point,
621
+ endpointsForMargulisTube(index));
622
+ }
623
+
624
+ if(ray_hit.object_type == object_type_margulis_tube_exit) {
625
+ int index = 4 * ray_hit.tet_num + ray_hit.object_index;
626
+ return - normalForTube(
627
+ ray_hit.ray.point,
628
+ endpointsForMargulisTube(index));
629
+ }
630
+
631
+ #if defined(num_geodesic_segments) && num_geodesic_segments > 0
632
+ if (ray_hit.object_type == object_type_geodesic_tube) {
633
+ return normalForTube(
634
+ ray_hit.ray.point,
635
+ endpointsForGeodesic(ray_hit.object_index));
636
+ }
637
+ #endif
638
+
639
+ #if defined(num_additional_horospheres) && num_additional_horospheres > 0
640
+ if (ray_hit.object_type == object_type_additional_horosphere) {
641
+ return horosphereVec[ray_hit.object_index] - ray_hit.ray.point;
642
+ }
643
+ #endif
644
+
645
+ #if num_eyeballs > 0
646
+ if (ray_hit.object_type == object_type_eyeball) {
647
+ #if eyeball_type == 2
648
+ return normalForSphere(
649
+ ray_hit.ray.point, eyeballPositions[ray_hit.object_index]);
650
+ #else
651
+ vec4 local_normal;
652
+ if (ray_hit.object_subindex == 0) {
653
+ local_normal = space_ship_top_plane;
654
+ } else {
655
+ local_normal = R13Normalise(space_ship_folds[ray_hit.object_subindex - 1]);
656
+ }
657
+ vec4 normal = local_normal * eyeballEmbeddings[ray_hit.object_index];
658
+
659
+ if (R13Dot(ray_hit.ray.dir, normal) > 0) {
660
+ return normal;
661
+ } else {
662
+ return -normal;
663
+ }
664
+ #endif
665
+ }
666
+ #endif
667
+
668
+ #if defined(has_edge_midpoints)
669
+ if (ray_hit.object_type == object_type_edge_midpoint) {
670
+ int index = 6 * ray_hit.tet_num + ray_hit.object_index;
671
+ return normalForSphere(ray_hit.ray.point, edgeMidpointVec[index]);
672
+ }
673
+ #endif
674
+
675
+ #endif
676
+
677
+ if(ray_hit.object_type == object_type_edge_fan ||
678
+ ray_hit.object_type == object_type_elevation_enter ||
679
+ ray_hit.object_type == object_type_elevation_exit) {
680
+ int index = 4 * ray_hit.tet_num + ray_hit.object_index;
681
+ return planes[index];
682
+ }
683
+
684
+ if(ray_hit.object_type == object_type_edge_cylinder_enter) {
685
+ return normalForTube(
686
+ ray_hit.ray.point,
687
+ endpointsForEdge(ray_hit.tet_num, ray_hit.object_index));
688
+ }
689
+
690
+ if(ray_hit.object_type == object_type_edge_cylinder_exit) {
691
+ return - normalForTube(
692
+ ray_hit.ray.point,
693
+ endpointsForEdge(ray_hit.tet_num, ray_hit.object_index));
694
+ }
695
+
696
+ return vec4(0,1,0,0);
697
+ }
698
+
699
+ // Convert point in hyperboloid model to upper halfspace
700
+ // model.
701
+ // The vec3 result corresponds to result.x + result.y * i + result.z * j,
702
+ // i.e., the last component of the vec3 is the height.
703
+ vec3
704
+ hyperboloidToUpperHalfspace(vec4 h)
705
+ {
706
+ vec3 klein = h.yzw / h.x;
707
+ vec3 poincare = klein / (1.0 + sqrt(1.0 - dot(klein, klein)));
708
+ vec3 denom_helper = vec3(poincare.x - 1.0, poincare.yz);
709
+ float denom = dot(denom_helper, denom_helper);
710
+
711
+ return vec3(2.0 * poincare.yz, 1.0 - dot(poincare, poincare)) / denom;
712
+ }
713
+
714
+ #if !##finiteTrig##
715
+ // Compute the coordinates of a ray hit on a horosphere in the upper
716
+ // half space model such that the cusp is at infinity.
717
+ vec3
718
+ preferredUpperHalfspaceCoordinates(RayHit ray_hit)
719
+ {
720
+ int index = 4 * ray_hit.tet_num + ray_hit.object_index;
721
+
722
+ return hyperboloidToUpperHalfspace(
723
+ ray_hit.ray.point * tetToCuspMatrices[index]);
724
+ }
725
+
726
+ vec2
727
+ complexLog(vec2 z)
728
+ {
729
+ return vec2(log(length(z)), atan(z.y, z.x));
730
+ }
731
+
732
+ vec2
733
+ MLCoordinatesForRayHit(RayHit rayHit)
734
+ {
735
+ int index = 4 * rayHit.tet_num + rayHit.object_index;
736
+
737
+ vec3 pointUpperHalfspace = preferredUpperHalfspaceCoordinates(rayHit);
738
+ vec2 z = pointUpperHalfspace.xy;
739
+
740
+ if (rayHit.object_type == object_type_margulis_tube_enter ||
741
+ rayHit.object_type == object_type_margulis_tube_exit) {
742
+ z = complexLog(z) + logAdjustments[index];
743
+ }
744
+
745
+ return z * toStandardTorusMatrices[index];
746
+ }
747
+
748
+ int
749
+ peripheralCurveForMLCoordinates(vec2 ml_coordinates)
750
+ {
751
+ // Map R^2->torus
752
+ vec2 f = fract(ml_coordinates);
753
+
754
+ if ( f.y < peripheralCurveThickness ||
755
+ f.y > 1.0 - peripheralCurveThickness) {
756
+ return 2;
757
+ }
758
+
759
+ if ( f.x < peripheralCurveThickness ||
760
+ f.x > 1.0 - peripheralCurveThickness) {
761
+ return 1;
762
+ }
763
+
764
+ return 0;
765
+ }
766
+ #endif
767
+
768
+ // Compute the SO13 transform corresponding to the PSL(2,C)-matrix
769
+ // [[1, z], [0, 1]].
770
+ // Special case of the kernel's Moebius_to_O31 for upper unit triangular
771
+ // matrices.
772
+ mat4
773
+ parabolicSO13(vec2 z)
774
+ {
775
+ float t = dot(z, z) / 2.0;
776
+
777
+ return mat4( 1.0 + t, - t, z.x, z.y,
778
+ t, 1.0 - t, z.x, z.y,
779
+ z.x, -z.x, 1.0, 0.0,
780
+ z.y, -z.y, 0.0, 1.0 );
781
+ }
782
+
783
+ // Compute the SO13 transform corresponding to the PGL(2,C)-matrix
784
+ // [[ exp(z), 0], [0, 1]].
785
+ // Special case of the kernel's Moebius_to_O31 for diagonal matrices.
786
+ mat4
787
+ loxodromicSO13(vec2 z)
788
+ {
789
+ return mat4( cosh(z.x), sinh(z.x), 0.0, 0.0,
790
+ sinh(z.x), cosh(z.x), 0.0, 0.0,
791
+ 0.0, 0.0, cos(z.y), -sin(z.y),
792
+ 0.0, 0.0, sin(z.y), cos(z.y) );
793
+ }
794
+
795
+ void
796
+ ray_trace_through_hyperboloid_tet(inout RayHit ray_hit)
797
+ {
798
+ int entry_object_type = ray_hit.object_type;
799
+ int entry_object_index = ray_hit.object_index;
800
+
801
+ ///Given shape of a tet and a ray, find where the ray exits and through which face
802
+ float smallest_p = 100000000.0;
803
+
804
+ float horosphere_exit_param = -unreachableDistParam;
805
+
806
+ #if !##finiteTrig##
807
+ for (int vertex = 0; vertex < 4; vertex++) {
808
+ int index = 4 * ray_hit.tet_num + vertex;
809
+ if ( horosphereScales[index] != 0.0 ||
810
+ margulisTubeRadiusParams[index] > 0.50001) {
811
+
812
+ vec2 params;
813
+ if (horosphereScales[index] != 0.0) {
814
+ params = distParamsForHorosphereIntersection(
815
+ ray_hit.ray,
816
+ horosphereEqn(index));
817
+ } else {
818
+ params = distParamsForTubeIntersection(
819
+ ray_hit.ray,
820
+ endpointsForMargulisTube(index),
821
+ margulisTubeRadiusParams[index],
822
+ 0.0);
823
+ }
824
+
825
+ if (params.x < smallest_p) {
826
+ smallest_p = params.x;
827
+ if (horosphereScales[index] != 0.0) {
828
+ ray_hit.object_type = object_type_horosphere_enter;
829
+ } else {
830
+ ray_hit.object_type = object_type_margulis_tube_enter;
831
+ }
832
+ ray_hit.object_index = vertex;
833
+ }
834
+
835
+ if (traceInsideVertexNeighborhood()) {
836
+ if (params.y < smallest_p) {
837
+ horosphere_exit_param = params.y;
838
+ ray_hit.distWhenLeavingCusp = ray_hit.dist + atanh(params.y);
839
+
840
+ RayHit new_hit = ray_hit;
841
+ new_hit.object_index = vertex;
842
+ advanceRayByDistParam(new_hit.ray, params.y);
843
+
844
+ if (peripheralCurveForMLCoordinates(
845
+ MLCoordinatesForRayHit(new_hit)) > 0) {
846
+ smallest_p = params.y;
847
+
848
+ if (horosphereScales[index] != 0.0) {
849
+ ray_hit.object_type = object_type_horosphere_exit;
850
+ } else {
851
+ ray_hit.object_type = object_type_margulis_tube_exit;
852
+ }
853
+ ray_hit.object_index = vertex;
854
+ }
855
+ }
856
+ }
857
+ }
858
+ }
859
+ #endif
860
+
861
+ for(int face = 0; face < 4; face++) {
862
+ if (entry_object_type != object_type_face || entry_object_index != face) {
863
+ // find p when we hit that face
864
+ int index = 4 * ray_hit.tet_num + face;
865
+ if(R13Dot(ray_hit.ray.dir, planes[index]) > 0.0){
866
+ float p = distParamForPlaneIntersection(ray_hit.ray, planes[index]);
867
+ // if ((-10000.0 <= p) && (p < smallest_p)) {
868
+ if (p < smallest_p) {
869
+ /// negative values are ok if we have to go backwards a little to get through the face we are a little the wrong side of
870
+ /// Although this can apparently get caught in infinite loops in an edge
871
+
872
+ /// if we are on an edge then we don't in fact move as we go through this tet: t = 0.0
873
+ /// also allow tiny negative values, which will come up from floating point errors.
874
+ /// surface normals check should ensure that even in this case we make progress through
875
+ /// the triangles around an edge
876
+ smallest_p = p;
877
+ ray_hit.object_type = object_type_face;
878
+ ray_hit.object_index = face;
879
+ }
880
+ }
881
+ }
882
+ }
883
+
884
+ #if ##finiteTrig##
885
+ if (vertexSphereRadiusParam > 1.0001) {
886
+ for (int vertex = 0; vertex < 4; vertex++) {
887
+ int index = 4 * ray_hit.tet_num + vertex;
888
+ float p = distParamsForSphereIntersection(
889
+ ray_hit.ray,
890
+ R13Vertices[index],
891
+ vertexSphereRadiusParam).x;
892
+ if (p < smallest_p) {
893
+ smallest_p = p;
894
+ ray_hit.object_type = object_type_vertex_sphere;
895
+ ray_hit.object_index = vertex;
896
+ }
897
+ }
898
+ }
899
+ #else
900
+ {
901
+ float r = insphereRadiusParams[ray_hit.tet_num];
902
+
903
+ if (r > 1.0001) {
904
+ float p = distParamsForSphereIntersection(
905
+ ray_hit.ray,
906
+ vec4(1,0,0,0),
907
+ r).x;
908
+ if (p < smallest_p && (!traceInsideVertexNeighborhood() ||
909
+ p > horosphere_exit_param)) {
910
+ smallest_p = p;
911
+ ray_hit.object_type = object_type_insphere;
912
+ ray_hit.object_index = 0;
913
+ }
914
+ }
915
+ }
916
+
917
+ #if defined(has_edge_midpoints)
918
+ {
919
+ for (int edge = 0; edge < 6; edge++) {
920
+ int index = 6 * ray_hit.tet_num + edge;
921
+ float p = distParamsForSphereIntersection(
922
+ ray_hit.ray,
923
+ edgeMidpointVec[index],
924
+ edgeMidpointRadiusParam).x;
925
+ if (p < smallest_p) {
926
+ smallest_p = p;
927
+ ray_hit.object_type = object_type_edge_midpoint;
928
+ ray_hit.object_index = edge;
929
+ }
930
+ }
931
+ }
932
+ #endif
933
+
934
+ #if defined(num_geodesic_segments) && num_geodesic_segments > 0
935
+ for (int index = geodesicOffsets[ray_hit.tet_num];
936
+ index < geodesicOffsets[ray_hit.tet_num + 1];
937
+ index++) {
938
+
939
+ vec2 params = distParamsForTubeIntersection(
940
+ ray_hit.ray,
941
+ endpointsForGeodesic(index),
942
+ geodesicTubeRadiusParam[index],
943
+ 0.0);
944
+
945
+ if (params.x < smallest_p && (!traceInsideVertexNeighborhood() ||
946
+ params.x > horosphere_exit_param)) {
947
+ smallest_p = params.x;
948
+ ray_hit.object_type = object_type_geodesic_tube;
949
+ ray_hit.object_index = index;
950
+ }
951
+ }
952
+ #endif
953
+
954
+ #if defined(num_additional_horospheres) && num_additional_horospheres > 0
955
+ for (int index = horosphereOffsets[ray_hit.tet_num];
956
+ index < horosphereOffsets[ray_hit.tet_num + 1];
957
+ index++) {
958
+
959
+ vec2 params = distParamsForHorosphereIntersection(
960
+ ray_hit.ray,
961
+ horosphereVec[index]);
962
+
963
+ if (params.x < smallest_p) {
964
+ smallest_p = params.x;
965
+ ray_hit.object_type = object_type_additional_horosphere;
966
+ ray_hit.object_index = index;
967
+ }
968
+ }
969
+ #endif
970
+
971
+ #if num_eyeballs > 0
972
+ for (int index = eyeballOffsets[ray_hit.tet_num];
973
+ index < eyeballOffsets[ray_hit.tet_num + 1];
974
+ index++) {
975
+
976
+ #if eyeball_type == 2
977
+ vec2 params = distParamsForSphereIntersection(
978
+ ray_hit.ray,
979
+ eyeballPositions[index],
980
+ eyeballRadiusParam);
981
+
982
+ if (params.x < smallest_p) {
983
+ smallest_p = params.x;
984
+ ray_hit.object_type = object_type_eyeball;
985
+ ray_hit.object_index = index;
986
+ }
987
+ #else
988
+ Ray local_ray;
989
+ local_ray.point = ray_hit.ray.point * eyeballInvEmbeddings[index];
990
+ local_ray.dir = ray_hit.ray.dir * eyeballInvEmbeddings[index];
991
+
992
+ {
993
+ float param = distParamForPlaneIntersection(local_ray, vec4(0.0, 0.0, 1.0, 0.0));
994
+
995
+ if (param > 0 && param < smallest_p) {
996
+ if (ray_hit.dist + atanh(param) > 0.001) {
997
+ vec4 hit_point = pointAdvancedByParam(local_ray, param);
998
+ if ((dot(hit_point, space_ship_folds[0]) < 0.0 ||
999
+ dot(hit_point, space_ship_folds[1]) < 0.0) &&
1000
+ dot(hit_point, space_ship_back_plane) > 0.0 &&
1001
+ dot(hit_point, space_ship_edges[0]) > 0.0 &&
1002
+ dot(hit_point, space_ship_edges[1]) > 0.0) {
1003
+ smallest_p = param;
1004
+ ray_hit.object_type = object_type_eyeball;
1005
+ ray_hit.object_index = index;
1006
+ ray_hit.object_subindex = 0;
1007
+ }
1008
+ }
1009
+ }
1010
+ }
1011
+
1012
+ for (int s = 0; s < 2; s++) {
1013
+ float param = distParamForPlaneIntersection(local_ray, space_ship_folds[s]);
1014
+
1015
+ if (param > 0 && param < smallest_p) {
1016
+ if (ray_hit.dist + atanh(param) > 0.001) {
1017
+ vec4 hit_point = pointAdvancedByParam(local_ray, param);
1018
+
1019
+ if (dot(hit_point, space_ship_back_plane) > 0.0 &&
1020
+ dot(hit_point, space_ship_top_plane) > 0.0 &&
1021
+ dot(hit_point, space_ship_folds[1-s]) > 0.0) {
1022
+
1023
+ smallest_p = param;
1024
+ ray_hit.object_type = object_type_eyeball;
1025
+ ray_hit.object_index = index;
1026
+ ray_hit.object_subindex = 1 + s;
1027
+ }
1028
+ }
1029
+ }
1030
+ }
1031
+ #endif
1032
+ }
1033
+ #endif
1034
+
1035
+ #endif
1036
+
1037
+ if (edgeTubeRadiusParam > 0.500001) {
1038
+
1039
+ #if ##finiteTrig##
1040
+ float backDistParam = 0.0;
1041
+ #else
1042
+ float backDistParam = tanh(ray_hit.distWhenLeavingCusp-ray_hit.dist);
1043
+ #endif
1044
+
1045
+ for (int edge = 0; edge < 6; edge++) {
1046
+
1047
+ vec2 params = distParamsForTubeIntersection(
1048
+ ray_hit.ray,
1049
+ endpointsForEdge(ray_hit.tet_num, edge),
1050
+ edgeTubeRadiusParam,
1051
+ backDistParam);
1052
+
1053
+ if (params.x < smallest_p && (!traceInsideVertexNeighborhood() ||
1054
+ params.x > horosphere_exit_param)) {
1055
+ smallest_p = params.x;
1056
+ ray_hit.object_type = object_type_edge_cylinder_enter;
1057
+ ray_hit.object_index = edge;
1058
+ }
1059
+ if (params.y < smallest_p && (!traceInsideVertexNeighborhood() ||
1060
+ params.y > horosphere_exit_param)) {
1061
+ smallest_p = params.y;
1062
+ ray_hit.object_type = object_type_edge_cylinder_exit;
1063
+ ray_hit.object_index = edge;
1064
+ }
1065
+ }
1066
+ }
1067
+
1068
+ ray_hit.dist += atanh(smallest_p);
1069
+ advanceRayByDistParam(ray_hit.ray, smallest_p);
1070
+
1071
+ if(edgeThicknessParam > 0.00001) {
1072
+ if (ray_hit.object_type == object_type_face) {
1073
+ if (!traceInsideVertexNeighborhood() ||
1074
+ smallest_p > horosphere_exit_param) {
1075
+ if(triangleBdryParam(ray_hit.ray.point, ray_hit.tet_num, ray_hit.object_index) < edgeThicknessParam) {
1076
+ ray_hit.object_type = object_type_edge_fan;
1077
+ }
1078
+ }
1079
+ }
1080
+ }
1081
+ }
1082
+
1083
+ int
1084
+ is_elevation_hit(float old_weight, float new_weight)
1085
+ {
1086
+ const float eps = 1e-4;
1087
+ float o = old_weight - eps;
1088
+ float n = new_weight - eps;
1089
+
1090
+ if (o * n < 0.0) {
1091
+ if (n < 0.0) {
1092
+ return object_type_elevation_enter;
1093
+ } else {
1094
+ return object_type_elevation_exit;
1095
+ }
1096
+ }
1097
+
1098
+ return object_type_nothing;
1099
+ }
1100
+
1101
+ void
1102
+ ray_trace(inout RayHit ray_hit) {
1103
+
1104
+ for(int i = 0; i < maxSteps; i++){
1105
+ ray_trace_through_hyperboloid_tet(ray_hit);
1106
+
1107
+ if (ray_hit.object_type != object_type_face) {
1108
+ break;
1109
+ }
1110
+
1111
+ if (ray_hit.dist > maxDist) {
1112
+ break;
1113
+ }
1114
+
1115
+ // in fact pow(sinh(radius in hyperbolic units),2.0). However, sinh^2 is monotonic for
1116
+ // positive values so we get correct behaviour by comparing without the sinh^2.
1117
+ int index = 4 * ray_hit.tet_num + ray_hit.object_index;
1118
+
1119
+ float new_weight = ray_hit.weight + weights[ index ];
1120
+
1121
+ if (showElevation) {
1122
+ int elevation_object_type =
1123
+ is_elevation_hit(ray_hit.weight, new_weight);
1124
+
1125
+ if (elevation_object_type != object_type_nothing) {
1126
+ ray_hit.object_type = elevation_object_type;
1127
+ break;
1128
+ }
1129
+ }
1130
+
1131
+ ray_hit.weight = new_weight;
1132
+
1133
+ ray_hit.object_index = otherFaceNums[ index ];
1134
+ mat4 tsfm = SO13tsfms[ index ];
1135
+
1136
+ ray_hit.light_source = ray_hit.light_source * tsfm;
1137
+ ray_hit.ray.point = ray_hit.ray.point * tsfm;
1138
+ ray_hit.ray.dir = R13Normalise( ray_hit.ray.dir * tsfm );
1139
+ ray_hit.tet_num = otherTetNums[ index ];
1140
+ }
1141
+ }
1142
+
1143
+
1144
+
1145
+ /// --- Colour gradient code --- ///
1146
+
1147
+ int find_band(float t, float thresholds[5]){
1148
+ for(int j = 1; j < 4; j++) {
1149
+ if(t < thresholds[j]) {
1150
+ return j;
1151
+ }
1152
+ }
1153
+ return 4;
1154
+ }
1155
+
1156
+ vec3 general_gradient(float t, float thresholds[5], vec3 colours[5]){
1157
+ int i = find_band(t, thresholds);
1158
+ return mix(colours[i-1],
1159
+ colours[i],
1160
+ (t - thresholds[i-1])/(thresholds[i] - thresholds[i-1]));
1161
+ }
1162
+
1163
+ // Given the (average) value for a ray hit, apply gradient to get
1164
+ // color.
1165
+ vec3 colorForValue(float value)
1166
+ {
1167
+ if (noGradient) {
1168
+ return vec3(value);
1169
+ }
1170
+
1171
+ value = contrast * value;
1172
+ value = 0.5 + 0.5 * value/ (abs(value) + 1.0); //faster than atan, similar
1173
+
1174
+ return general_gradient(value, gradientThresholds, gradientColours);
1175
+ }
1176
+
1177
+ struct MaterialParams
1178
+ {
1179
+ vec3 ambient;
1180
+ vec3 diffuse;
1181
+ vec3 specular;
1182
+
1183
+ float shininess;
1184
+ };
1185
+
1186
+ MaterialParams
1187
+ material_params(RayHit ray_hit)
1188
+ {
1189
+ MaterialParams result;
1190
+
1191
+ result.diffuse = vec3(0.2, 0.6, 0.3);
1192
+ result.ambient = 0.5 * result.diffuse;
1193
+ result.specular = vec3(0.5, 0.5, 0.5);
1194
+ result.shininess = 20;
1195
+
1196
+ #if ##finiteTrig##
1197
+ if (ray_hit.object_type == object_type_vertex_sphere) {
1198
+ int index = 4 * ray_hit.tet_num + ray_hit.object_index;
1199
+ int color_index = vertex_color_indices[index];
1200
+
1201
+ result.diffuse = hsv2rgb(vec3(float(color_index)/float(num_cusps), 0.25, 1.0));
1202
+ result.ambient = 0.5 * result.diffuse;
1203
+ }
1204
+ #else
1205
+ if (ray_hit.object_type == object_type_horosphere_enter ||
1206
+ ray_hit.object_type == object_type_horosphere_exit ||
1207
+ ray_hit.object_type == object_type_margulis_tube_enter ||
1208
+ ray_hit.object_type == object_type_margulis_tube_exit) {
1209
+
1210
+ int index = 4 * ray_hit.tet_num + ray_hit.object_index;
1211
+ int color_index = vertex_color_indices[index];
1212
+
1213
+ #if COLOR_SCHEME == 1
1214
+ result.diffuse = hsv2rgb(vec3(float(color_index)/float(num_cusps), 0.25, 1.0));
1215
+ #else
1216
+ result.diffuse =
1217
+ vec3(0.5, 0.5, 0.5)
1218
+ + sin(color_index) * vec3( 0.3, -0.3, 0.0)
1219
+ + cos(color_index) * vec3(0.15, 0.15, -0.3);
1220
+ #endif
1221
+ result.ambient = 0.5 * result.diffuse;
1222
+
1223
+ int peripheralCurve =
1224
+ peripheralCurveForMLCoordinates(
1225
+ MLCoordinatesForRayHit(ray_hit));
1226
+
1227
+ if (peripheralCurve == 1) {
1228
+ result.diffuse = longitudeColor;
1229
+ result.ambient = result.diffuse;
1230
+ }
1231
+ if (peripheralCurve == 2) {
1232
+ result.diffuse = meridianColor;
1233
+ result.ambient = result.diffuse;
1234
+ }
1235
+ }
1236
+
1237
+ if (ray_hit.object_type == object_type_insphere) {
1238
+ result.diffuse = hsv2rgb(vec3(float(ray_hit.tet_num)/float(num_tets), 0.5, 1.0));
1239
+
1240
+ result.diffuse *= 0.5;
1241
+
1242
+ result.ambient = 0.5 * result.diffuse;
1243
+ }
1244
+
1245
+ #endif
1246
+
1247
+ if (ray_hit.object_type == object_type_edge_fan) {
1248
+ int index = 4 * ray_hit.tet_num + ray_hit.object_index;
1249
+ int color_index = face_color_indices[index];
1250
+ result.diffuse = hsv2rgb(vec3(float(color_index)/float(2*num_tets), 0.75, 0.5));
1251
+ result.ambient = 0.5 * result.diffuse;
1252
+ }
1253
+
1254
+ if (ray_hit.object_type == object_type_edge_cylinder_enter) {
1255
+ int index = 6 * ray_hit.tet_num + ray_hit.object_index;
1256
+ int color_index = edge_color_indices[index];
1257
+
1258
+ //using num_tets = num_edges
1259
+
1260
+ #if COLOR_SCHEME == 1
1261
+ result.diffuse = hsv2rgb(
1262
+ vec3(float(color_index)/float(num_edges),
1263
+ desaturate_edges ? 0.24 : 1.0,
1264
+ 1.0));
1265
+ #else
1266
+ result.diffuse =
1267
+ vec3(0.5, 0.5, 0.5)
1268
+ + sin(color_index) * vec3( 0.3, -0.3, 0.0)
1269
+ + cos(color_index) * vec3(0.15, 0.15, -0.3);
1270
+ #endif
1271
+
1272
+ result.ambient = 0.5 * result.diffuse;
1273
+ }
1274
+
1275
+ if (ray_hit.object_type == object_type_edge_cylinder_exit) {
1276
+ int index = 6 * ray_hit.tet_num + ray_hit.object_index;
1277
+ int color_index = edge_color_indices[index];
1278
+
1279
+ //using num_tets = num_edges
1280
+ result.diffuse = 0.3 * hsv2rgb(vec3(float(color_index)/float(num_tets), 1.0, 1.0));
1281
+ result.ambient = 0.5 * result.diffuse;
1282
+ }
1283
+
1284
+ if (ray_hit.object_type == object_type_elevation_enter) {
1285
+ result.diffuse = vec3(0.3,0.7,0.3);
1286
+ result.ambient = 0.5 * result.diffuse;
1287
+ }
1288
+
1289
+ if (ray_hit.object_type == object_type_elevation_exit) {
1290
+ result.diffuse = vec3(0.7,0.3,0.3);
1291
+ result.ambient = 0.5 * result.diffuse;
1292
+ }
1293
+
1294
+ #if defined(num_geodesic_segments) && num_geodesic_segments > 0
1295
+ if (ray_hit.object_type == object_type_geodesic_tube) {
1296
+ int index = geodesicIndex[ray_hit.object_index];
1297
+
1298
+ // The user wants to switch geodesics off and on while
1299
+ // their colors stay stable.
1300
+ //
1301
+ // Thus, we cannot divide the color circle equally.
1302
+ //
1303
+ // Instead, we multiply the index by the golden angle
1304
+ // pi * (3 - sqrt(5)) radians
1305
+ // so that no geodesics hit the same color.
1306
+ //
1307
+ // For hsv2rgb, we need to divide by 2 * pi:
1308
+ //
1309
+ float goldenAngleBy2Pi = 0.3819660112501051;
1310
+
1311
+ result.diffuse = hsv2rgb(vec3(float(index) * goldenAngleBy2Pi + 0.1, 1.0, 1.0));
1312
+
1313
+ result.ambient = 0.5 * result.diffuse;
1314
+ }
1315
+ #endif
1316
+
1317
+ #if defined(num_additional_horospheres) && num_additional_horospheres > 0
1318
+ if (ray_hit.object_type == object_type_additional_horosphere) {
1319
+ int index = horosphereCuspIndex[ray_hit.object_index];
1320
+
1321
+ // Similar to geodesic colors.
1322
+ float goldenAngleBy2Pi = 0.3819660112501051;
1323
+
1324
+ result.diffuse = hsv2rgb(vec3(float(index) * goldenAngleBy2Pi + 0.3, 1.0, 1.0));
1325
+
1326
+ result.ambient = 0.5 * result.diffuse;
1327
+ }
1328
+ #endif
1329
+
1330
+ #if num_eyeballs > 0
1331
+ if (ray_hit.object_type == object_type_eyeball) {
1332
+
1333
+ #if eyeball_type == 2
1334
+ vec4 pt = ray_hit.ray.point * eyeballInvEmbeddings[ray_hit.object_index];
1335
+ vec3 d = normalize(pt.yzw);
1336
+
1337
+ vec2 tex_coords = vec2(0.5) + vec2(atan(d.x, -d.z) / 2, asin(d.y)) / radians(180);
1338
+
1339
+ result.diffuse = texture(eyeTexture, tex_coords).xyz;
1340
+ result.ambient = 0.5 * result.diffuse;
1341
+ #else
1342
+ result.diffuse = vec3(0.7, 0.7, 0.7);
1343
+ result.ambient = 0.8 * result.diffuse;
1344
+ #endif
1345
+ }
1346
+ #endif
1347
+
1348
+ #if defined(has_edge_midpoints)
1349
+ if (ray_hit.object_type == object_type_edge_midpoint) {
1350
+ result.diffuse = vec3(0.8,0.8,0.3);
1351
+ result.ambient = 0.5 * result.diffuse;
1352
+ }
1353
+ #endif
1354
+
1355
+ return result;
1356
+ }
1357
+
1358
+ // Compute the value for a valued ray hit (see isColored for explanation)
1359
+ float valueForRayHit(RayHit ray_hit)
1360
+ {
1361
+ if (viewMode == 0) {
1362
+ return ray_hit.weight;
1363
+ } else if (viewMode == 1) {
1364
+ return 0.5 * ray_hit.dist;
1365
+ } else {
1366
+ return float(ray_hit.tet_num);
1367
+ }
1368
+ }
1369
+
1370
+ // Apply lighting for a colored ray hit (see isColored for explanation)
1371
+ vec3 colorForRayHit(RayHit ray_hit)
1372
+ {
1373
+ MaterialParams material = material_params(ray_hit);
1374
+
1375
+ vec4 normal = normalForRayHit(ray_hit);
1376
+
1377
+ vec4 light_position = R13Normalise(ray_hit.light_source);
1378
+
1379
+ // Distance of light source to origin where the eye ray started
1380
+ float light_dist_origin = acosh(-R13Dot(R13Normalise(vec4(1,0,0.7,0)), vec4(1, 0, 0, 0)));
1381
+
1382
+ // Distance of light source to ray hit
1383
+ float unsafe_dist = acosh(-R13Dot(ray_hit.ray.point, light_position));
1384
+
1385
+ // Use triangle inequality to limit distance
1386
+ float dist = clamp(unsafe_dist,
1387
+ ray_hit.dist - light_dist_origin,
1388
+ ray_hit.dist + light_dist_origin);
1389
+
1390
+
1391
+ vec4 light_dir_at_hit = makeUnitTangentVector(
1392
+ - light_position, ray_hit.ray.point);
1393
+
1394
+ float normal_light = clamp(R13Dot(normal, light_dir_at_hit), 0, 1);
1395
+
1396
+ vec4 half_angle = R13Normalise(light_dir_at_hit + ray_hit.ray.dir);
1397
+
1398
+ float blinn_term =
1399
+ normal_light > 0.0
1400
+ ? pow(clamp(R13Dot(half_angle, normal), 0, 1), material.shininess)
1401
+ : 0.0;
1402
+
1403
+ return brightness * (material.ambient
1404
+ + material.diffuse * normal_light
1405
+ + material.specular * blinn_term ) / pow((dist + lightBias) / lightBias, lightFalloff);
1406
+ }
1407
+
1408
+ /// --- Graph-trace code --- ///
1409
+
1410
+ int faceFurthest(vec4 v, int tet_num, int entry_face)
1411
+ {
1412
+ int result = -1;
1413
+ float biggest_amount = 0.0000001;
1414
+ for (int face = 0; face < 4; face++) {
1415
+ if (entry_face != face) {
1416
+ float amount = R13Dot( v, planes[4 * tet_num + face] );
1417
+ if (amount > biggest_amount) {
1418
+ biggest_amount = amount;
1419
+ result = face;
1420
+ }
1421
+ }
1422
+ }
1423
+ return result;
1424
+ }
1425
+
1426
+ void graph_trace(inout RayHit ray)
1427
+ {
1428
+ int entry_face = -1;
1429
+ mat4 tsfm = mat4(1.0);
1430
+
1431
+ for(int i = 0; i < maxSteps; i++) {
1432
+ int face = faceFurthest(ray.ray.point, ray.tet_num, entry_face);
1433
+ if (face == -1) {
1434
+ break;
1435
+ }
1436
+
1437
+ int index = 4 * ray.tet_num + face;
1438
+ entry_face = otherFaceNums[ index ];
1439
+ ray.tet_num = otherTetNums[ index ];
1440
+ ray.weight += weights[ index ];
1441
+ ray.ray.point = ray.ray.point * SO13tsfms[ index ];
1442
+ ray.ray.dir = ray.ray.dir * SO13tsfms[ index ];
1443
+ ray.light_source = ray.light_source * SO13tsfms[ index ];
1444
+ }
1445
+ }
1446
+
1447
+ /// --- Ray init pt and directions code --- ///
1448
+
1449
+ Ray get_ray_eye_space(vec2 xy)
1450
+ {
1451
+ Ray result;
1452
+
1453
+ if (perspectiveType == perspectiveTypeMaterial) {
1454
+ result.point = vec4(1.0,0.0,0.0,0.0);
1455
+ result.dir = R13Normalise(vec4(0.0, 2.0 * xy, -1.0));
1456
+ } else if (perspectiveType == perspectiveTypeIdeal) {
1457
+ // parabolic transformation magic by Saul
1458
+ float r2 = 0.5 * dot(xy, xy);
1459
+ result.point = vec4(r2 + 1.0, xy, r2);
1460
+ result.dir = vec4(r2, xy, r2 - 1.0);
1461
+ } else { // perspectiveTypeHyperIdeal
1462
+ result.point = R13Normalise(vec4(1.0, 2.0 * xy, 0.0));
1463
+ result.dir = vec4(0.0, 0.0, 0.0, -1.0);
1464
+ }
1465
+
1466
+ return result;
1467
+ }
1468
+
1469
+ #if ##finiteTrig##
1470
+ bool
1471
+ leaveVertexNeighborhood(inout RayHit rayHit)
1472
+ {
1473
+ if (vertexSphereRadiusParam <= 1.0001) {
1474
+ return false;
1475
+ }
1476
+
1477
+ float smallest_p = unreachableDistParam;
1478
+
1479
+ // For all vertices
1480
+ for (int vertex = 0; vertex < 4; vertex++) {
1481
+ int index = 4 * rayHit.tet_num + vertex;
1482
+ vec2 params = distParamsForSphereIntersection(
1483
+ rayHit.ray,
1484
+ R13Vertices[index],
1485
+ vertexSphereRadiusParam);
1486
+ if (params.x == unreachableDistParam) {
1487
+ if (params.y < smallest_p) {
1488
+ smallest_p = params.y;
1489
+ rayHit.object_type = object_type_vertex_sphere;
1490
+ rayHit.object_index = vertex;
1491
+ }
1492
+ }
1493
+ }
1494
+
1495
+ if (smallest_p < unreachableDistParam) {
1496
+ rayHit.dist += atanh(smallest_p);
1497
+ rayHit.distWhenLeavingCusp = rayHit.dist;
1498
+ advanceRayByDistParam(rayHit.ray, smallest_p);
1499
+ graph_trace(rayHit);
1500
+ }
1501
+
1502
+ return false;
1503
+ }
1504
+
1505
+ #else
1506
+
1507
+ // Determine whether the ray starts in a horosphere or
1508
+ // Margulis tube.
1509
+ // If yes, move the ray to the point where we exit the
1510
+ // horosphere and set rayHit.object_type to horosphere.
1511
+ //
1512
+ // The result is true if we are inside a horosphere AND
1513
+ // the ray is hitting a peripheral curve on the horosphere.
1514
+ //
1515
+ // For optimization, leaveVertexNeighborhood will also apply a
1516
+ // parabolic transformation to the ray trying to bring the
1517
+ // where we exit the horosphere closer to the entry point.
1518
+ bool
1519
+ leaveVertexNeighborhood(inout RayHit rayHit)
1520
+ {
1521
+ float smallest_p = unreachableDistParam;
1522
+
1523
+ // For all vertices
1524
+ for (int vertex = 0; vertex < 4; vertex++) {
1525
+ int index = 4 * rayHit.tet_num + vertex;
1526
+ // corresponding to complete cusps
1527
+ if (horosphereScales[index] != 0.0) {
1528
+ vec2 params = distParamsForHorosphereIntersection(
1529
+ rayHit.ray, horosphereEqn(index));
1530
+ if (params.x == unreachableDistParam) {
1531
+ // We are in the horosphere
1532
+ if (params.y < smallest_p) {
1533
+ // Remember this
1534
+ smallest_p = params.y;
1535
+ rayHit.object_type = object_type_horosphere_exit;
1536
+ rayHit.object_index = vertex;
1537
+ }
1538
+ }
1539
+ } else if (margulisTubeRadiusParams[index] > 0.50001) {
1540
+ vec2 params = distParamsForTubeIntersection(
1541
+ rayHit.ray,
1542
+ endpointsForMargulisTube(index),
1543
+ margulisTubeRadiusParams[index],
1544
+ 0.0);
1545
+ if (params.x == unreachableDistParam) {
1546
+ if (params.y < smallest_p) {
1547
+ smallest_p = params.y;
1548
+ rayHit.object_type = object_type_margulis_tube_exit;
1549
+ rayHit.object_index = vertex;
1550
+ }
1551
+ }
1552
+ }
1553
+ }
1554
+
1555
+ // We are in a horosphere.
1556
+ if (smallest_p < unreachableDistParam) {
1557
+
1558
+ // Book-keeping and advancing the ray to the exit
1559
+ // point
1560
+ rayHit.dist += smallest_p < 1.0 ? atanh(smallest_p) : 20.0;
1561
+ rayHit.distWhenLeavingCusp = rayHit.dist;
1562
+ advanceRayByDistParam(rayHit.ray, smallest_p);
1563
+
1564
+ int index = 4 * rayHit.tet_num + rayHit.object_index;
1565
+
1566
+ vec2 ml = MLCoordinatesForRayHit(rayHit);
1567
+
1568
+ // Compute the coordinates of exit point in upper half space
1569
+ // such that the cusp is at infinity
1570
+ // Use complex part ignoring height in upper halfspace
1571
+
1572
+ // Check whether we hit peripheral curve
1573
+ if (peripheralCurveForMLCoordinates(ml) > 0) {
1574
+ // Hit peripheral curve
1575
+ return true;
1576
+ }
1577
+
1578
+ // Compute suitable multiple of merdian and longitude translation
1579
+ // bringing the exit point into the fundamental parallelogram
1580
+ // near zero.
1581
+ vec2 c = -round(ml) * inverse(toStandardTorusMatrices[index]);
1582
+
1583
+ mat4 tsfmCuspSpace =
1584
+ (rayHit.object_type == object_type_horosphere_exit)
1585
+ ? parabolicSO13(c)
1586
+ : loxodromicSO13(c);
1587
+
1588
+ // Convert O13 matrix from space where cusp was at infinity
1589
+ // to space of tetrahedron
1590
+ mat4 tsfm =
1591
+ tetToCuspMatrices[index] *
1592
+ tsfmCuspSpace *
1593
+ cuspToTetMatrices[index];
1594
+
1595
+ // And apply transformation to ray.
1596
+ rayHit.light_source = rayHit.light_source * tsfm;
1597
+ rayHit.ray.point = rayHit.ray.point * tsfm;
1598
+ rayHit.ray.dir = R13Normalise( rayHit.ray.dir * tsfm );
1599
+
1600
+ // If we are inside a horosphere, leaveVertexNeighborhood has computed
1601
+ // the point where we leave the horosphere. But that point
1602
+ // might not be inside the current tetrahedron, so fix it.
1603
+ graph_trace(rayHit);
1604
+ }
1605
+
1606
+ return false;
1607
+ }
1608
+
1609
+ #endif
1610
+
1611
+ RayHit computeRayHit(vec2 xy){
1612
+ Ray ray_eye_space = get_ray_eye_space(xy);
1613
+
1614
+ RayHit ray_tet_space;
1615
+ ray_tet_space.ray.point = ray_eye_space.point * currentBoost;
1616
+ ray_tet_space.ray.dir = ray_eye_space.dir * currentBoost;
1617
+ ray_tet_space.dist = 0.0;
1618
+ ray_tet_space.distWhenLeavingCusp = 0.0;
1619
+ ray_tet_space.weight = currentWeight;
1620
+ ray_tet_space.tet_num = currentTetIndex;
1621
+ ray_tet_space.light_source = R13Normalise(lightSourcePosition * currentBoost);
1622
+ ray_tet_space.object_type = object_type_nothing;
1623
+ ray_tet_space.object_index = -1;
1624
+
1625
+ // If using a camera where the ray's do not
1626
+ // all start from a common point, transform ray first
1627
+ // to be inside a tetrahedron.
1628
+ if (perspectiveType != perspectiveTypeMaterial) {
1629
+ graph_trace(ray_tet_space);
1630
+ }
1631
+
1632
+ if (!traceInsideVertexNeighborhood()) {
1633
+ // Check whether we are in a horosphere or Margulis tube and if yes,
1634
+ // whether the ray hit a peripheral curve.
1635
+ if (leaveVertexNeighborhood(ray_tet_space)) {
1636
+ // If we hit a peripheral curve, leaveVertexNeighborhood has
1637
+ // given us the intersection point and we can immediately shade.
1638
+ return ray_tet_space;
1639
+ }
1640
+ }
1641
+
1642
+ // In all other cases, we need to raytrace before we shade.
1643
+ ray_trace(ray_tet_space);
1644
+
1645
+ return ray_tet_space;
1646
+ }
1647
+
1648
+ vec3 sampleNonGeometricTexture(vec2 fragCoord)
1649
+ {
1650
+ vec2 coord = gl_FragCoord.xy - 0.5 * screenResolution.xy;
1651
+ coord.x /= 320.0;
1652
+ coord.y /= -100.0;
1653
+ coord += vec2(0.5, 0.5);
1654
+
1655
+ if (coord.x < 0.002 || coord.x > 0.99 || coord.y < 0.01 || coord.y > 0.99) {
1656
+ return vec3(0.0);
1657
+ }
1658
+
1659
+ return texture(nonGeometricTexture, coord).xyz;
1660
+ }
1661
+
1662
+
1663
+ void main(){
1664
+
1665
+ // Show text "Non-geometric"
1666
+ if (isNonGeometric) {
1667
+ out_FragColor = vec4(sampleNonGeometricTexture(gl_FragCoord.xy), 1.0);
1668
+ return;
1669
+ }
1670
+
1671
+ vec2 xy = (gl_FragCoord.xy - 0.5*screenResolution.xy) /
1672
+ min(screenResolution.x,screenResolution.y);
1673
+ if(multiScreenShot == 1) {
1674
+ // Return multiple 4096x4096 screenshots that can be combined in, e.g. Photoshop.
1675
+ // Here screenResolution is really tileResolution;
1676
+ xy = (xy + tile - 0.5*(numTiles - vec2(1.0,1.0))) / numTiles.x;
1677
+ }
1678
+
1679
+ float min_depth = 1;
1680
+ vec3 total_color = vec3(0);
1681
+ int num_valued_subpixels = 0;
1682
+ float total_value = 0;
1683
+
1684
+ for(int i=0; i<subpixelCount; i++){
1685
+ for(int j=0; j<subpixelCount; j++){
1686
+ vec2 offset =
1687
+ ( vec2(float(1+2*i), float(1+2*j))/float(2*subpixelCount) - vec2(0.5,0.5) )
1688
+ / screenResolution.x / numTiles.x;
1689
+ vec2 scaled_xy = xy + offset;
1690
+ if (perspectiveType != perspectiveTypeHyperideal) {
1691
+ scaled_xy *= viewScale;
1692
+ }
1693
+
1694
+ bool outsideView =
1695
+ perspectiveType == perspectiveTypeHyperideal &&
1696
+ length(scaled_xy) >= 0.5;
1697
+
1698
+ if (outsideView) {
1699
+ total_color += vec3(1.0, 1.0, 1.0);
1700
+ } else {
1701
+ RayHit ray_hit = computeRayHit(scaled_xy);
1702
+ if (ray_hit.object_type != object_type_nothing) {
1703
+ min_depth = min(min_depth, tanh(ray_hit.dist));
1704
+ if (isColored(ray_hit)) {
1705
+ // Accumulate color for colored subpixels.
1706
+ total_color += colorForRayHit(ray_hit);
1707
+ } else {
1708
+ // Accumulate value for valued subpixels.
1709
+ // Count number of valued subpixels so that we can
1710
+ // compute average value.
1711
+ num_valued_subpixels += 1;
1712
+ total_value += valueForRayHit(ray_hit);
1713
+ }
1714
+ }
1715
+ }
1716
+ }
1717
+ }
1718
+
1719
+ if (num_valued_subpixels > 0) {
1720
+ // Average value of valued ray hits.
1721
+ float value = total_value / num_valued_subpixels;
1722
+
1723
+ // Compute gradient and add to total color.
1724
+ //
1725
+ // The contribution of the gradient color is proportional
1726
+ // to the number of valued subsamples for this pixel.
1727
+ total_color += num_valued_subpixels * colorForValue(value);
1728
+ }
1729
+
1730
+ // Divide by total number of subsamples.
1731
+ out_FragColor = vec4(total_color / float(subpixelCount * subpixelCount), 1);
1732
+
1733
+ if (crosshairs) {
1734
+ vec2 coord = gl_FragCoord.xy - floor(0.5 * screenResolution.xy) + vec2(0.5, 0.5);
1735
+ if (abs(coord.x) < 0.1 && abs(coord.y) < 0.1 * screenResolution.x) {
1736
+ out_FragColor.rgb = vec3(1.0) - out_FragColor.rgb;
1737
+ }
1738
+ if (abs(coord.y) < 0.1 && abs(coord.x) < 0.1 * screenResolution.x) {
1739
+ out_FragColor.rgb = vec3(1.0) - out_FragColor.rgb;
1740
+ }
1741
+ }
1742
+
1743
+ gl_FragDepth = min_depth;
1744
+ }