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.
- snappy/CyOpenGL.cpython-310-aarch64-linux-gnu.so +0 -0
- snappy/SnapPy.cpython-310-aarch64-linux-gnu.so +0 -0
- snappy/SnapPy.ico +0 -0
- snappy/SnapPy.png +0 -0
- snappy/SnapPyHP.cpython-310-aarch64-linux-gnu.so +0 -0
- snappy/__init__.py +534 -0
- snappy/app.py +604 -0
- snappy/app_menus.py +372 -0
- snappy/browser.py +998 -0
- snappy/cache.py +25 -0
- snappy/canonical.py +249 -0
- snappy/cusps/__init__.py +280 -0
- snappy/cusps/cusp_area_matrix.py +98 -0
- snappy/cusps/cusp_areas_from_matrix.py +96 -0
- snappy/cusps/maximal_cusp_area_matrix.py +136 -0
- snappy/cusps/short_slopes_for_cusp.py +217 -0
- snappy/cusps/test.py +22 -0
- snappy/cusps/trig_cusp_area_matrix.py +63 -0
- snappy/database.py +454 -0
- snappy/db_utilities.py +79 -0
- snappy/decorated_isosig.py +717 -0
- snappy/dev/__init__.py +0 -0
- snappy/dev/extended_ptolemy/__init__.py +8 -0
- snappy/dev/extended_ptolemy/closed.py +106 -0
- snappy/dev/extended_ptolemy/complexVolumesClosed.py +149 -0
- snappy/dev/extended_ptolemy/direct.py +42 -0
- snappy/dev/extended_ptolemy/extended.py +406 -0
- snappy/dev/extended_ptolemy/giac_helper.py +43 -0
- snappy/dev/extended_ptolemy/giac_rur.py +129 -0
- snappy/dev/extended_ptolemy/gluing.py +46 -0
- snappy/dev/extended_ptolemy/phc_wrapper.py +220 -0
- snappy/dev/extended_ptolemy/printMatrices.py +70 -0
- snappy/dev/vericlosed/__init__.py +1 -0
- snappy/dev/vericlosed/computeApproxHyperbolicStructureNew.py +159 -0
- snappy/dev/vericlosed/computeApproxHyperbolicStructureOrb.py +90 -0
- snappy/dev/vericlosed/computeVerifiedHyperbolicStructure.py +111 -0
- snappy/dev/vericlosed/gimbalLoopFinder.py +130 -0
- snappy/dev/vericlosed/hyperbolicStructure.py +313 -0
- snappy/dev/vericlosed/krawczykCertifiedEdgeLengthsEngine.py +165 -0
- snappy/dev/vericlosed/oneVertexTruncatedComplex.py +122 -0
- snappy/dev/vericlosed/orb/__init__.py +1 -0
- snappy/dev/vericlosed/orb/orb_solution_for_snappea_finite_triangulation_mac +0 -0
- snappy/dev/vericlosed/parseVertexGramMatrixFile.py +47 -0
- snappy/dev/vericlosed/polishApproxHyperbolicStructure.py +61 -0
- snappy/dev/vericlosed/test.py +54 -0
- snappy/dev/vericlosed/truncatedComplex.py +176 -0
- snappy/dev/vericlosed/verificationError.py +58 -0
- snappy/dev/vericlosed/verifyHyperbolicStructureEngine.py +177 -0
- snappy/doc/_images/SnapPy-196.png +0 -0
- snappy/doc/_images/m004_paper_plane_on_systole.jpg +0 -0
- snappy/doc/_images/m125_paper_plane.jpg +0 -0
- snappy/doc/_images/mac.png +0 -0
- snappy/doc/_images/o9_00000_systole_paper_plane.jpg +0 -0
- snappy/doc/_images/o9_00000_systole_paper_plane_closer.jpg +0 -0
- snappy/doc/_images/plink-action.png +0 -0
- snappy/doc/_images/ubuntu.png +0 -0
- snappy/doc/_images/win7.png +0 -0
- snappy/doc/_sources/additional_classes.rst.txt +40 -0
- snappy/doc/_sources/bugs.rst.txt +14 -0
- snappy/doc/_sources/censuses.rst.txt +52 -0
- snappy/doc/_sources/credits.rst.txt +81 -0
- snappy/doc/_sources/development.rst.txt +261 -0
- snappy/doc/_sources/index.rst.txt +215 -0
- snappy/doc/_sources/installing.rst.txt +249 -0
- snappy/doc/_sources/manifold.rst.txt +6 -0
- snappy/doc/_sources/manifoldhp.rst.txt +46 -0
- snappy/doc/_sources/news.rst.txt +425 -0
- snappy/doc/_sources/other.rst.txt +25 -0
- snappy/doc/_sources/platonic_census.rst.txt +20 -0
- snappy/doc/_sources/plink.rst.txt +102 -0
- snappy/doc/_sources/ptolemy.rst.txt +66 -0
- snappy/doc/_sources/ptolemy_classes.rst.txt +42 -0
- snappy/doc/_sources/ptolemy_examples1.rst.txt +298 -0
- snappy/doc/_sources/ptolemy_examples2.rst.txt +363 -0
- snappy/doc/_sources/ptolemy_examples3.rst.txt +301 -0
- snappy/doc/_sources/ptolemy_examples4.rst.txt +61 -0
- snappy/doc/_sources/ptolemy_prelim.rst.txt +105 -0
- snappy/doc/_sources/screenshots.rst.txt +21 -0
- snappy/doc/_sources/snap.rst.txt +87 -0
- snappy/doc/_sources/snappy.rst.txt +28 -0
- snappy/doc/_sources/spherogram.rst.txt +103 -0
- snappy/doc/_sources/todo.rst.txt +47 -0
- snappy/doc/_sources/triangulation.rst.txt +11 -0
- snappy/doc/_sources/tutorial.rst.txt +49 -0
- snappy/doc/_sources/verify.rst.txt +210 -0
- snappy/doc/_sources/verify_internals.rst.txt +79 -0
- snappy/doc/_static/SnapPy-horizontal-128.png +0 -0
- snappy/doc/_static/SnapPy.ico +0 -0
- snappy/doc/_static/_sphinx_javascript_frameworks_compat.js +123 -0
- snappy/doc/_static/basic.css +906 -0
- snappy/doc/_static/css/badge_only.css +1 -0
- snappy/doc/_static/css/fonts/Roboto-Slab-Bold.woff +0 -0
- snappy/doc/_static/css/fonts/Roboto-Slab-Bold.woff2 +0 -0
- snappy/doc/_static/css/fonts/Roboto-Slab-Regular.woff +0 -0
- snappy/doc/_static/css/fonts/Roboto-Slab-Regular.woff2 +0 -0
- snappy/doc/_static/css/fonts/fontawesome-webfont.eot +0 -0
- snappy/doc/_static/css/fonts/fontawesome-webfont.svg +2671 -0
- snappy/doc/_static/css/fonts/fontawesome-webfont.ttf +0 -0
- snappy/doc/_static/css/fonts/fontawesome-webfont.woff +0 -0
- snappy/doc/_static/css/fonts/fontawesome-webfont.woff2 +0 -0
- snappy/doc/_static/css/fonts/lato-bold-italic.woff +0 -0
- snappy/doc/_static/css/fonts/lato-bold-italic.woff2 +0 -0
- snappy/doc/_static/css/fonts/lato-bold.woff +0 -0
- snappy/doc/_static/css/fonts/lato-bold.woff2 +0 -0
- snappy/doc/_static/css/fonts/lato-normal-italic.woff +0 -0
- snappy/doc/_static/css/fonts/lato-normal-italic.woff2 +0 -0
- snappy/doc/_static/css/fonts/lato-normal.woff +0 -0
- snappy/doc/_static/css/fonts/lato-normal.woff2 +0 -0
- snappy/doc/_static/css/theme.css +4 -0
- snappy/doc/_static/doctools.js +149 -0
- snappy/doc/_static/documentation_options.js +13 -0
- snappy/doc/_static/file.png +0 -0
- snappy/doc/_static/fonts/Lato/lato-bold.eot +0 -0
- snappy/doc/_static/fonts/Lato/lato-bold.ttf +0 -0
- snappy/doc/_static/fonts/Lato/lato-bold.woff +0 -0
- snappy/doc/_static/fonts/Lato/lato-bold.woff2 +0 -0
- snappy/doc/_static/fonts/Lato/lato-bolditalic.eot +0 -0
- snappy/doc/_static/fonts/Lato/lato-bolditalic.ttf +0 -0
- snappy/doc/_static/fonts/Lato/lato-bolditalic.woff +0 -0
- snappy/doc/_static/fonts/Lato/lato-bolditalic.woff2 +0 -0
- snappy/doc/_static/fonts/Lato/lato-italic.eot +0 -0
- snappy/doc/_static/fonts/Lato/lato-italic.ttf +0 -0
- snappy/doc/_static/fonts/Lato/lato-italic.woff +0 -0
- snappy/doc/_static/fonts/Lato/lato-italic.woff2 +0 -0
- snappy/doc/_static/fonts/Lato/lato-regular.eot +0 -0
- snappy/doc/_static/fonts/Lato/lato-regular.ttf +0 -0
- snappy/doc/_static/fonts/Lato/lato-regular.woff +0 -0
- snappy/doc/_static/fonts/Lato/lato-regular.woff2 +0 -0
- snappy/doc/_static/fonts/RobotoSlab/roboto-slab-v7-bold.eot +0 -0
- snappy/doc/_static/fonts/RobotoSlab/roboto-slab-v7-bold.ttf +0 -0
- snappy/doc/_static/fonts/RobotoSlab/roboto-slab-v7-bold.woff +0 -0
- snappy/doc/_static/fonts/RobotoSlab/roboto-slab-v7-bold.woff2 +0 -0
- snappy/doc/_static/fonts/RobotoSlab/roboto-slab-v7-regular.eot +0 -0
- snappy/doc/_static/fonts/RobotoSlab/roboto-slab-v7-regular.ttf +0 -0
- snappy/doc/_static/fonts/RobotoSlab/roboto-slab-v7-regular.woff +0 -0
- snappy/doc/_static/fonts/RobotoSlab/roboto-slab-v7-regular.woff2 +0 -0
- snappy/doc/_static/jquery.js +2 -0
- snappy/doc/_static/js/badge_only.js +1 -0
- snappy/doc/_static/js/theme.js +1 -0
- snappy/doc/_static/js/versions.js +228 -0
- snappy/doc/_static/language_data.js +192 -0
- snappy/doc/_static/minus.png +0 -0
- snappy/doc/_static/plus.png +0 -0
- snappy/doc/_static/pygments.css +75 -0
- snappy/doc/_static/searchtools.js +635 -0
- snappy/doc/_static/snappy_furo.css +33 -0
- snappy/doc/_static/snappy_sphinx_rtd_theme.css +42 -0
- snappy/doc/_static/sphinx_highlight.js +154 -0
- snappy/doc/additional_classes.html +1500 -0
- snappy/doc/bugs.html +132 -0
- snappy/doc/censuses.html +453 -0
- snappy/doc/credits.html +184 -0
- snappy/doc/development.html +385 -0
- snappy/doc/doc-latest/additional_classes.html +1500 -0
- snappy/doc/doc-latest/bugs.html +132 -0
- snappy/doc/doc-latest/censuses.html +453 -0
- snappy/doc/doc-latest/credits.html +184 -0
- snappy/doc/doc-latest/development.html +385 -0
- snappy/doc/doc-latest/genindex.html +1349 -0
- snappy/doc/doc-latest/index.html +287 -0
- snappy/doc/doc-latest/installing.html +346 -0
- snappy/doc/doc-latest/manifold.html +3632 -0
- snappy/doc/doc-latest/manifoldhp.html +180 -0
- snappy/doc/doc-latest/news.html +438 -0
- snappy/doc/doc-latest/objects.inv +0 -0
- snappy/doc/doc-latest/other.html +160 -0
- snappy/doc/doc-latest/platonic_census.html +376 -0
- snappy/doc/doc-latest/plink.html +210 -0
- snappy/doc/doc-latest/ptolemy.html +253 -0
- snappy/doc/doc-latest/ptolemy_classes.html +1144 -0
- snappy/doc/doc-latest/ptolemy_examples1.html +409 -0
- snappy/doc/doc-latest/ptolemy_examples2.html +471 -0
- snappy/doc/doc-latest/ptolemy_examples3.html +414 -0
- snappy/doc/doc-latest/ptolemy_examples4.html +195 -0
- snappy/doc/doc-latest/ptolemy_prelim.html +248 -0
- snappy/doc/doc-latest/py-modindex.html +165 -0
- snappy/doc/doc-latest/screenshots.html +141 -0
- snappy/doc/doc-latest/search.html +135 -0
- snappy/doc/doc-latest/searchindex.js +1 -0
- snappy/doc/doc-latest/snap.html +202 -0
- snappy/doc/doc-latest/snappy.html +181 -0
- snappy/doc/doc-latest/spherogram.html +1346 -0
- snappy/doc/doc-latest/todo.html +166 -0
- snappy/doc/doc-latest/triangulation.html +1676 -0
- snappy/doc/doc-latest/tutorial.html +159 -0
- snappy/doc/doc-latest/verify.html +330 -0
- snappy/doc/doc-latest/verify_internals.html +1235 -0
- snappy/doc/genindex.html +1349 -0
- snappy/doc/index.html +287 -0
- snappy/doc/installing.html +346 -0
- snappy/doc/manifold.html +3632 -0
- snappy/doc/manifoldhp.html +180 -0
- snappy/doc/news.html +438 -0
- snappy/doc/objects.inv +0 -0
- snappy/doc/other.html +160 -0
- snappy/doc/platonic_census.html +376 -0
- snappy/doc/plink.html +210 -0
- snappy/doc/ptolemy.html +253 -0
- snappy/doc/ptolemy_classes.html +1144 -0
- snappy/doc/ptolemy_examples1.html +409 -0
- snappy/doc/ptolemy_examples2.html +471 -0
- snappy/doc/ptolemy_examples3.html +414 -0
- snappy/doc/ptolemy_examples4.html +195 -0
- snappy/doc/ptolemy_prelim.html +248 -0
- snappy/doc/py-modindex.html +165 -0
- snappy/doc/screenshots.html +141 -0
- snappy/doc/search.html +135 -0
- snappy/doc/searchindex.js +1 -0
- snappy/doc/snap.html +202 -0
- snappy/doc/snappy.html +181 -0
- snappy/doc/spherogram.html +1346 -0
- snappy/doc/todo.html +166 -0
- snappy/doc/triangulation.html +1676 -0
- snappy/doc/tutorial.html +159 -0
- snappy/doc/verify.html +330 -0
- snappy/doc/verify_internals.html +1235 -0
- snappy/drilling/__init__.py +456 -0
- snappy/drilling/barycentric.py +103 -0
- snappy/drilling/constants.py +5 -0
- snappy/drilling/crush.py +270 -0
- snappy/drilling/cusps.py +125 -0
- snappy/drilling/debug.py +242 -0
- snappy/drilling/epsilons.py +6 -0
- snappy/drilling/exceptions.py +55 -0
- snappy/drilling/moves.py +620 -0
- snappy/drilling/peripheral_curves.py +210 -0
- snappy/drilling/perturb.py +188 -0
- snappy/drilling/shorten.py +36 -0
- snappy/drilling/subdivide.py +274 -0
- snappy/drilling/test.py +23 -0
- snappy/drilling/test_cases.py +132 -0
- snappy/drilling/tracing.py +351 -0
- snappy/exceptions.py +26 -0
- snappy/export_stl.py +120 -0
- snappy/exterior_to_link/__init__.py +2 -0
- snappy/exterior_to_link/barycentric_geometry.py +463 -0
- snappy/exterior_to_link/exceptions.py +6 -0
- snappy/exterior_to_link/geodesic_map.json +14408 -0
- snappy/exterior_to_link/hyp_utils.py +112 -0
- snappy/exterior_to_link/link_projection.py +323 -0
- snappy/exterior_to_link/main.py +198 -0
- snappy/exterior_to_link/mcomplex_with_expansion.py +261 -0
- snappy/exterior_to_link/mcomplex_with_link.py +687 -0
- snappy/exterior_to_link/mcomplex_with_memory.py +162 -0
- snappy/exterior_to_link/pl_utils.py +491 -0
- snappy/exterior_to_link/put_in_S3.py +156 -0
- snappy/exterior_to_link/rational_linear_algebra.py +130 -0
- snappy/exterior_to_link/rational_linear_algebra_wrapped.py +135 -0
- snappy/exterior_to_link/simplify_to_base_tri.py +114 -0
- snappy/exterior_to_link/stored_moves.py +475 -0
- snappy/exterior_to_link/test.py +31 -0
- snappy/filedialog.py +28 -0
- snappy/geometric_structure/__init__.py +212 -0
- snappy/geometric_structure/cusp_neighborhood/__init__.py +3 -0
- snappy/geometric_structure/cusp_neighborhood/complex_cusp_cross_section.py +691 -0
- snappy/geometric_structure/cusp_neighborhood/cusp_cross_section_base.py +480 -0
- snappy/geometric_structure/cusp_neighborhood/exceptions.py +41 -0
- snappy/geometric_structure/cusp_neighborhood/real_cusp_cross_section.py +294 -0
- snappy/geometric_structure/cusp_neighborhood/tiles_for_cusp_neighborhood.py +156 -0
- snappy/geometric_structure/cusp_neighborhood/vertices.py +35 -0
- snappy/geometric_structure/geodesic/__init__.py +0 -0
- snappy/geometric_structure/geodesic/add_core_curves.py +152 -0
- snappy/geometric_structure/geodesic/avoid_core_curves.py +369 -0
- snappy/geometric_structure/geodesic/canonical_representatives.py +52 -0
- snappy/geometric_structure/geodesic/check_away_from_core_curve.py +60 -0
- snappy/geometric_structure/geodesic/constants.py +6 -0
- snappy/geometric_structure/geodesic/exceptions.py +22 -0
- snappy/geometric_structure/geodesic/fixed_points.py +106 -0
- snappy/geometric_structure/geodesic/geodesic_start_point_info.py +435 -0
- snappy/geometric_structure/geodesic/graph_trace_helper.py +67 -0
- snappy/geometric_structure/geodesic/line.py +30 -0
- snappy/geometric_structure/geodesic/multiplicity.py +127 -0
- snappy/geometric_structure/geodesic/tiles_for_geodesic.py +128 -0
- snappy/geometric_structure/test.py +22 -0
- snappy/gui.py +121 -0
- snappy/horoviewer.py +443 -0
- snappy/hyperboloid/__init__.py +212 -0
- snappy/hyperboloid/distances.py +259 -0
- snappy/hyperboloid/horoball.py +19 -0
- snappy/hyperboloid/line.py +35 -0
- snappy/hyperboloid/point.py +9 -0
- snappy/hyperboloid/triangle.py +29 -0
- snappy/info_icon.gif +0 -0
- snappy/infowindow.py +65 -0
- snappy/isometry_signature.py +389 -0
- snappy/len_spec/__init__.py +609 -0
- snappy/len_spec/geodesic_info.py +129 -0
- snappy/len_spec/geodesic_key_info_dict.py +116 -0
- snappy/len_spec/geodesic_piece.py +146 -0
- snappy/len_spec/geometric_structure.py +182 -0
- snappy/len_spec/geometry.py +136 -0
- snappy/len_spec/length_spectrum_geodesic_info.py +185 -0
- snappy/len_spec/spine.py +128 -0
- snappy/len_spec/test.py +24 -0
- snappy/len_spec/test_cases.py +69 -0
- snappy/len_spec/tile.py +276 -0
- snappy/len_spec/word.py +86 -0
- snappy/manifolds/HTWKnots/alternating.gz +0 -0
- snappy/manifolds/HTWKnots/nonalternating.gz +0 -0
- snappy/manifolds/__init__.py +3 -0
- snappy/margulis/__init__.py +332 -0
- snappy/margulis/cusp_neighborhood_neighborhood.py +66 -0
- snappy/margulis/geodesic_neighborhood.py +152 -0
- snappy/margulis/margulis_info.py +21 -0
- snappy/margulis/mu_from_neighborhood_pair.py +175 -0
- snappy/margulis/neighborhood.py +29 -0
- snappy/margulis/test.py +22 -0
- snappy/math_basics.py +187 -0
- snappy/matrix.py +525 -0
- snappy/number.py +657 -0
- snappy/numeric_output_checker.py +345 -0
- snappy/pari.py +41 -0
- snappy/phone_home.py +57 -0
- snappy/polyviewer.py +259 -0
- snappy/ptolemy/__init__.py +17 -0
- snappy/ptolemy/component.py +103 -0
- snappy/ptolemy/coordinates.py +2290 -0
- snappy/ptolemy/fieldExtensions.py +153 -0
- snappy/ptolemy/findLoops.py +473 -0
- snappy/ptolemy/geometricRep.py +59 -0
- snappy/ptolemy/homology.py +165 -0
- snappy/ptolemy/magma/default.magma_template +229 -0
- snappy/ptolemy/magma/radicalsOfPrimaryDecomposition.magma_template +79 -0
- snappy/ptolemy/manifoldMethods.py +395 -0
- snappy/ptolemy/matrix.py +350 -0
- snappy/ptolemy/numericalSolutionsToGroebnerBasis.py +113 -0
- snappy/ptolemy/polynomial.py +856 -0
- snappy/ptolemy/processComponents.py +173 -0
- snappy/ptolemy/processFileBase.py +247 -0
- snappy/ptolemy/processFileDispatch.py +46 -0
- snappy/ptolemy/processMagmaFile.py +392 -0
- snappy/ptolemy/processRurFile.py +150 -0
- snappy/ptolemy/ptolemyGeneralizedObstructionClass.py +102 -0
- snappy/ptolemy/ptolemyObstructionClass.py +64 -0
- snappy/ptolemy/ptolemyVariety.py +995 -0
- snappy/ptolemy/ptolemyVarietyPrimeIdealGroebnerBasis.py +140 -0
- snappy/ptolemy/reginaWrapper.py +698 -0
- snappy/ptolemy/regina_testing_files/DT_mcbbiceaibjklmdfgh__sl2_c0.magma_out.bz2 +0 -0
- snappy/ptolemy/regina_testing_files/DT_mcbbiceaibjklmdfgh__sl2_c1.magma_out.bz2 +0 -0
- snappy/ptolemy/regina_testing_files/DT_mcbbiceaibjklmdfgh__sl2_c2.magma_out.bz2 +0 -0
- snappy/ptolemy/regina_testing_files/DT_mcbbiceaibjklmdfgh__sl2_c3.magma_out.bz2 +0 -0
- snappy/ptolemy/regina_testing_files/DT_mcbbiceaibjklmdfgh__sl2_c4.magma_out.bz2 +0 -0
- snappy/ptolemy/regina_testing_files/DT_mcbbiceaibjklmdfgh__sl2_c5.magma_out.bz2 +0 -0
- snappy/ptolemy/regina_testing_files/DT_mcbbiceaibjklmdfgh__sl2_c6.magma_out.bz2 +0 -0
- snappy/ptolemy/regina_testing_files/DT_mcbbiceaibjklmdfgh__sl2_c7.magma_out.bz2 +0 -0
- snappy/ptolemy/regina_testing_files_generalized/m003__sl3_c0.magma_out.bz2 +0 -0
- snappy/ptolemy/regina_testing_files_generalized/m003__sl3_c1.magma_out.bz2 +0 -0
- snappy/ptolemy/regina_testing_files_generalized/m015__sl2_c0.magma_out.bz2 +0 -0
- snappy/ptolemy/regina_testing_files_generalized/m015__sl2_c1.magma_out.bz2 +0 -0
- snappy/ptolemy/regina_testing_files_generalized/m015__sl3_c0.magma_out.bz2 +0 -0
- snappy/ptolemy/regina_testing_files_generalized/m015__sl3_c1.magma_out.bz2 +0 -0
- snappy/ptolemy/rur.py +545 -0
- snappy/ptolemy/solutionsToPrimeIdealGroebnerBasis.py +277 -0
- snappy/ptolemy/test.py +1126 -0
- snappy/ptolemy/testing_files/3_1__sl2_c0.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files/3_1__sl2_c1.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files/4_1__sl2_c0.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files/4_1__sl2_c1.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files/4_1__sl3_c0.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files/4_1__sl4_c0.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files/4_1__sl4_c1.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files/5_2__sl2_c0.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files/5_2__sl2_c1.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files/DT_mcbbiceaibjklmdfgh__sl2_c0.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files/DT_mcbbiceaibjklmdfgh__sl2_c1.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files/DT_mcbbiceaibjklmdfgh__sl2_c2.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files/DT_mcbbiceaibjklmdfgh__sl2_c3.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files/DT_mcbbiceaibjklmdfgh__sl2_c4.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files/DT_mcbbiceaibjklmdfgh__sl2_c5.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files/DT_mcbbiceaibjklmdfgh__sl2_c6.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files/DT_mcbbiceaibjklmdfgh__sl2_c7.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files/data/pgl2/OrientableCuspedCensus/03_tetrahedra/m019__sl2_c0.magma_out +95 -0
- snappy/ptolemy/testing_files/data/pgl2/OrientableCuspedCensus/03_tetrahedra/m019__sl2_c1.magma_out +95 -0
- snappy/ptolemy/testing_files/m015__sl3_c0.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files/m135__sl2_c0.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files/m135__sl2_c1.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files/m135__sl2_c2.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files/m135__sl2_c3.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files/m135__sl2_c4.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files/m135__sl2_c5.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files/m135__sl2_c6.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files/m135__sl2_c7.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files/s000__sl2_c0.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files/s000__sl2_c1.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files/t00000__sl2_c0.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files/t00000__sl2_c1.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files/v0000__sl2_c0.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files/v0000__sl2_c1.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files/v0000__sl2_c2.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files/v0000__sl2_c3.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files_generalized/m003__sl2_c0.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files_generalized/m003__sl2_c1.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files_generalized/m003__sl3_c0.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files_generalized/m003__sl3_c1.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files_generalized/m004__sl2_c0.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files_generalized/m004__sl2_c1.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files_generalized/m015__sl2_c1.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files_generalized/m015__sl3_c0.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files_rur/m052__sl3_c0.rur.bz2 +0 -0
- snappy/ptolemy/utilities.py +236 -0
- snappy/raytracing/__init__.py +64 -0
- snappy/raytracing/additional_horospheres.py +64 -0
- snappy/raytracing/additional_len_spec_choices.py +63 -0
- snappy/raytracing/cohomology_fractal.py +197 -0
- snappy/raytracing/eyeball.py +124 -0
- snappy/raytracing/finite_raytracing_data.py +237 -0
- snappy/raytracing/finite_viewer.py +590 -0
- snappy/raytracing/geodesic_tube_info.py +174 -0
- snappy/raytracing/geodesics.py +246 -0
- snappy/raytracing/geodesics_window.py +258 -0
- snappy/raytracing/gui_utilities.py +293 -0
- snappy/raytracing/hyperboloid_navigation.py +556 -0
- snappy/raytracing/hyperboloid_utilities.py +234 -0
- snappy/raytracing/ideal_raytracing_data.py +592 -0
- snappy/raytracing/inside_viewer.py +974 -0
- snappy/raytracing/pack.py +22 -0
- snappy/raytracing/raytracing_data.py +126 -0
- snappy/raytracing/raytracing_view.py +454 -0
- snappy/raytracing/shaders/Eye.png +0 -0
- snappy/raytracing/shaders/NonGeometric.png +0 -0
- snappy/raytracing/shaders/__init__.py +101 -0
- snappy/raytracing/shaders/fragment.glsl +1744 -0
- snappy/raytracing/test.py +29 -0
- snappy/raytracing/tooltip.py +146 -0
- snappy/raytracing/upper_halfspace_utilities.py +98 -0
- snappy/raytracing/view_scale_controller.py +98 -0
- snappy/raytracing/zoom_slider/__init__.py +263 -0
- snappy/raytracing/zoom_slider/inward.png +0 -0
- snappy/raytracing/zoom_slider/inward18.png +0 -0
- snappy/raytracing/zoom_slider/outward.png +0 -0
- snappy/raytracing/zoom_slider/outward18.png +0 -0
- snappy/raytracing/zoom_slider/test.py +20 -0
- snappy/sage_helper.py +119 -0
- snappy/settings.py +407 -0
- snappy/shell.py +53 -0
- snappy/snap/__init__.py +117 -0
- snappy/snap/character_varieties.py +375 -0
- snappy/snap/find_field.py +372 -0
- snappy/snap/fox_milnor.py +271 -0
- snappy/snap/fundamental_polyhedron.py +569 -0
- snappy/snap/generators.py +39 -0
- snappy/snap/interval_reps.py +81 -0
- snappy/snap/kernel_structures.py +128 -0
- snappy/snap/mcomplex_base.py +18 -0
- snappy/snap/nsagetools.py +716 -0
- snappy/snap/peripheral/__init__.py +1 -0
- snappy/snap/peripheral/dual_cellulation.py +219 -0
- snappy/snap/peripheral/link.py +127 -0
- snappy/snap/peripheral/peripheral.py +159 -0
- snappy/snap/peripheral/surface.py +522 -0
- snappy/snap/peripheral/test.py +35 -0
- snappy/snap/polished_reps.py +335 -0
- snappy/snap/shapes.py +152 -0
- snappy/snap/slice_obs_HKL/__init__.py +194 -0
- snappy/snap/slice_obs_HKL/basics.py +236 -0
- snappy/snap/slice_obs_HKL/direct.py +217 -0
- snappy/snap/slice_obs_HKL/poly_norm.py +212 -0
- snappy/snap/slice_obs_HKL/rep_theory.py +424 -0
- snappy/snap/t3mlite/__init__.py +2 -0
- snappy/snap/t3mlite/arrow.py +243 -0
- snappy/snap/t3mlite/corner.py +22 -0
- snappy/snap/t3mlite/edge.py +172 -0
- snappy/snap/t3mlite/face.py +37 -0
- snappy/snap/t3mlite/files.py +211 -0
- snappy/snap/t3mlite/homology.py +53 -0
- snappy/snap/t3mlite/linalg.py +419 -0
- snappy/snap/t3mlite/mcomplex.py +1499 -0
- snappy/snap/t3mlite/perm4.py +320 -0
- snappy/snap/t3mlite/setup.py +12 -0
- snappy/snap/t3mlite/simplex.py +199 -0
- snappy/snap/t3mlite/spun.py +297 -0
- snappy/snap/t3mlite/surface.py +519 -0
- snappy/snap/t3mlite/test.py +20 -0
- snappy/snap/t3mlite/test_vs_regina.py +86 -0
- snappy/snap/t3mlite/tetrahedron.py +109 -0
- snappy/snap/t3mlite/vertex.py +42 -0
- snappy/snap/test.py +139 -0
- snappy/snap/utilities.py +288 -0
- snappy/test.py +213 -0
- snappy/test_cases.py +263 -0
- snappy/testing.py +131 -0
- snappy/tiling/__init__.py +2 -0
- snappy/tiling/dict_based_set.py +79 -0
- snappy/tiling/floor.py +49 -0
- snappy/tiling/hyperboloid_dict.py +54 -0
- snappy/tiling/iter_utils.py +78 -0
- snappy/tiling/lifted_tetrahedron.py +22 -0
- snappy/tiling/lifted_tetrahedron_set.py +54 -0
- snappy/tiling/quotient_dict.py +70 -0
- snappy/tiling/real_hash_dict.py +164 -0
- snappy/tiling/test.py +23 -0
- snappy/tiling/tile.py +224 -0
- snappy/tiling/triangle.py +33 -0
- snappy/tkterminal.py +920 -0
- snappy/twister/__init__.py +20 -0
- snappy/twister/main.py +646 -0
- snappy/twister/surfaces/S_0_1 +3 -0
- snappy/twister/surfaces/S_0_2 +3 -0
- snappy/twister/surfaces/S_0_4 +7 -0
- snappy/twister/surfaces/S_0_4_Lantern +8 -0
- snappy/twister/surfaces/S_1 +3 -0
- snappy/twister/surfaces/S_1_1 +4 -0
- snappy/twister/surfaces/S_1_2 +5 -0
- snappy/twister/surfaces/S_1_2_5 +6 -0
- snappy/twister/surfaces/S_2 +6 -0
- snappy/twister/surfaces/S_2_1 +8 -0
- snappy/twister/surfaces/S_2_heeg +10 -0
- snappy/twister/surfaces/S_3 +8 -0
- snappy/twister/surfaces/S_3_1 +10 -0
- snappy/twister/surfaces/S_4_1 +12 -0
- snappy/twister/surfaces/S_5_1 +14 -0
- snappy/twister/surfaces/heeg_fig8 +9 -0
- snappy/twister/twister_core.cpython-310-aarch64-linux-gnu.so +0 -0
- snappy/upper_halfspace/__init__.py +146 -0
- snappy/upper_halfspace/ideal_point.py +29 -0
- snappy/verify/__init__.py +13 -0
- snappy/verify/canonical.py +542 -0
- snappy/verify/complex_volume/__init__.py +18 -0
- snappy/verify/complex_volume/adjust_torsion.py +86 -0
- snappy/verify/complex_volume/closed.py +168 -0
- snappy/verify/complex_volume/compute_ptolemys.py +90 -0
- snappy/verify/complex_volume/cusped.py +56 -0
- snappy/verify/complex_volume/extended_bloch.py +201 -0
- snappy/verify/cusp_translations.py +85 -0
- snappy/verify/edge_equations.py +80 -0
- snappy/verify/exceptions.py +254 -0
- snappy/verify/hyperbolicity.py +224 -0
- snappy/verify/interval_newton_shapes_engine.py +523 -0
- snappy/verify/interval_tree.py +400 -0
- snappy/verify/krawczyk_shapes_engine.py +518 -0
- snappy/verify/real_algebra.py +286 -0
- snappy/verify/shapes.py +25 -0
- snappy/verify/square_extensions.py +1005 -0
- snappy/verify/test.py +72 -0
- snappy/verify/volume.py +128 -0
- snappy/version.py +2 -0
- snappy-3.3.dist-info/METADATA +58 -0
- snappy-3.3.dist-info/RECORD +541 -0
- snappy-3.3.dist-info/WHEEL +6 -0
- snappy-3.3.dist-info/entry_points.txt +2 -0
- 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
|
+
}
|