Initial commit: code and output
This commit is contained in:
commit
ebc9fdfdb2
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
/target
|
||||
**/*.rs.bk
|
309
Cargo.lock
generated
Normal file
309
Cargo.lock
generated
Normal file
@ -0,0 +1,309 @@
|
||||
[[package]]
|
||||
name = "approx"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "cgmath"
|
||||
version = "0.17.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"approx 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cloudabi"
|
||||
version = "0.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fuchsia-cprng"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "icosahedron"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"cgmath 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_json 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
version = "0.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.48"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "num-traits"
|
||||
version = "0.2.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "0.4.27"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "0.6.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand"
|
||||
version = "0.6.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand_jitter 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand_os 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand_pcg 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_chacha"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_core"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_core"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "rand_hc"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_isaac"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_jitter"
|
||||
version = "0.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_os"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_pcg"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_xorshift"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rdrand"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc_version"
|
||||
version = "0.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ryu"
|
||||
version = "0.2.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "semver"
|
||||
version = "0.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "semver-parser"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.88"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"serde_derive 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.88"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.38"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "0.15.26"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-xid"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "winapi"
|
||||
version = "0.3.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi-i686-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "winapi-x86_64-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[metadata]
|
||||
"checksum approx 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3c57ff1a5b00753647aebbbcf4ea67fa1e711a65ea7a30eb90dbf07de2485aee"
|
||||
"checksum autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a6d640bee2da49f60a4068a7fae53acde8982514ab7bae8b8cea9e88cbcfd799"
|
||||
"checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12"
|
||||
"checksum cgmath 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)" = "283944cdecc44bf0b8dd010ec9af888d3b4f142844fdbe026c20ef68148d6fe7"
|
||||
"checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f"
|
||||
"checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba"
|
||||
"checksum itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1306f3464951f30e30d12373d31c79fbd52d236e5e896fd92f96ec7babbbe60b"
|
||||
"checksum libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)" = "e962c7641008ac010fa60a7dfdc1712449f29c44ef2d4702394aea943ee75047"
|
||||
"checksum num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0b3a5d7cc97d6d30d8b9bc8fa19bf45349ffe46241e8816f50f62f6d6aaabee1"
|
||||
"checksum proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)" = "4d317f9caece796be1980837fd5cb3dfec5613ebdb04ad0956deea83ce168915"
|
||||
"checksum quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)" = "cdd8e04bd9c52e0342b406469d494fcb033be4bdbe5c606016defbb1681411e1"
|
||||
"checksum rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca"
|
||||
"checksum rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef"
|
||||
"checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b"
|
||||
"checksum rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d0e7a549d590831370895ab7ba4ea0c1b6b011d106b5ff2da6eee112615e6dc0"
|
||||
"checksum rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4"
|
||||
"checksum rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08"
|
||||
"checksum rand_jitter 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7b9ea758282efe12823e0d952ddb269d2e1897227e464919a554f2a03ef1b832"
|
||||
"checksum rand_os 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b7c690732391ae0abafced5015ffb53656abfaec61b342290e5eb56b286a679d"
|
||||
"checksum rand_pcg 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "086bd09a33c7044e56bb44d5bdde5a60e7f119a9e95b0775f545de759a32fe05"
|
||||
"checksum rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c"
|
||||
"checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2"
|
||||
"checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
|
||||
"checksum ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "eb9e9b8cde282a9fe6a42dd4681319bfb63f121b8a8ee9439c6f4107e58a46f7"
|
||||
"checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
|
||||
"checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
|
||||
"checksum serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)" = "9f301d728f2b94c9a7691c90f07b0b4e8a4517181d9461be94c04bddeb4bd850"
|
||||
"checksum serde_derive 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)" = "beed18e6f5175aef3ba670e57c60ef3b1b74d250d962a26604bff4c80e970dd4"
|
||||
"checksum serde_json 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)" = "27dce848e7467aa0e2fcaf0a413641499c0b745452aaca1194d24dedde9e13c9"
|
||||
"checksum syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)" = "f92e629aa1d9c827b2bb8297046c1ccffc57c99b947a680d3ccff1f136a3bee9"
|
||||
"checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc"
|
||||
"checksum winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "92c1eb33641e276cfa214a0522acad57be5c56b10cb348b3c5117db75f3ac4b0"
|
||||
"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||
"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
10
Cargo.toml
Normal file
10
Cargo.toml
Normal file
@ -0,0 +1,10 @@
|
||||
[package]
|
||||
name = "icosahedron"
|
||||
version = "0.1.0"
|
||||
authors = ["Tyler Hallada <tyler@hallada.net>"]
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
cgmath = { version = "0.17.0", features = ["serde"] }
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde_json = "1.0"
|
18
README.md
Normal file
18
README.md
Normal file
@ -0,0 +1,18 @@
|
||||
Still a work in progress.
|
||||
|
||||
Generates the shapes and then serializes them to a JSON file with a list of
|
||||
vertices (`positions`) and a list of triangle faces (`cells`) that index into
|
||||
the list of vertices. Suitable for input into [Three.js's
|
||||
BufferGeometry](https://threejs.org/docs/#api/en/core/BufferGeometry) or
|
||||
[regl](https://github.com/regl-project/regl/blob/gh-pages/example/camera.js).
|
||||
|
||||
Icosahedrons can be generated significantly faster than Three.js's version in
|
||||
JavaScript (which I pretty much copied into Rust).
|
||||
|
||||
Trunacated icosahedrons (I call them hexspheres) are a bit slower to generate
|
||||
since they are made by generating a icosahedron and then subdividing it into
|
||||
hexagon and pentagon faces. I still have some work to do to improve that code.
|
||||
|
||||
I'm still having issues rendering hexspheres of detail level 5 and higher and
|
||||
icosahedrons of detail level of 7 and higher, so I'm not sure if those are
|
||||
accurate.
|
1
output/hexsphere_r1_d0.json
Normal file
1
output/hexsphere_r1_d0.json
Normal file
File diff suppressed because one or more lines are too long
1
output/hexsphere_r1_d1.json
Normal file
1
output/hexsphere_r1_d1.json
Normal file
File diff suppressed because one or more lines are too long
1
output/hexsphere_r1_d2.json
Normal file
1
output/hexsphere_r1_d2.json
Normal file
File diff suppressed because one or more lines are too long
1
output/hexsphere_r1_d3.json
Normal file
1
output/hexsphere_r1_d3.json
Normal file
File diff suppressed because one or more lines are too long
1
output/hexsphere_r1_d4.json
Normal file
1
output/hexsphere_r1_d4.json
Normal file
File diff suppressed because one or more lines are too long
1
output/hexsphere_r1_d5.json
Normal file
1
output/hexsphere_r1_d5.json
Normal file
File diff suppressed because one or more lines are too long
1
output/hexsphere_r1_d6.json
Normal file
1
output/hexsphere_r1_d6.json
Normal file
File diff suppressed because one or more lines are too long
1
output/icosahedron_r1_d0.json
Normal file
1
output/icosahedron_r1_d0.json
Normal file
@ -0,0 +1 @@
|
||||
{"positions":[[-0.8506508,0.0,0.5257311],[0.0,0.5257311,0.8506508],[-0.5257311,0.8506508,0.0],[0.5257311,0.8506508,0.0],[0.0,0.5257311,-0.8506508],[-0.8506508,0.0,-0.5257311],[0.8506508,0.0,0.5257311],[0.0,-0.5257311,0.8506508],[-0.5257311,-0.8506508,0.0],[0.0,-0.5257311,-0.8506508],[0.8506508,0.0,-0.5257311],[0.5257311,-0.8506508,0.0]],"cells":[[0,1,2],[1,3,2],[3,4,2],[4,5,2],[5,0,2],[1,6,3],[0,7,1],[5,8,0],[4,9,5],[3,10,4],[6,7,11],[7,8,11],[8,9,11],[9,10,11],[10,6,11],[6,1,7],[7,0,8],[8,5,9],[9,4,10],[10,3,6]]}
|
1
output/icosahedron_r1_d1.json
Normal file
1
output/icosahedron_r1_d1.json
Normal file
@ -0,0 +1 @@
|
||||
{"positions":[[-0.809017,0.5,0.309017],[-0.309017,0.809017,0.5],[-0.5257311,0.8506508,0.0],[-0.5,0.309017,0.809017],[-0.8506508,0.0,0.5257311],[0.0,0.5257311,0.8506508],[0.0,1.0,0.0],[0.309017,0.809017,0.5],[0.5257311,0.8506508,0.0],[-0.309017,0.809017,-0.5],[0.309017,0.809017,-0.5],[0.0,0.5257311,-0.8506508],[-0.809017,0.5,-0.309017],[-0.5,0.309017,-0.809017],[-0.8506508,0.0,-0.5257311],[-1.0,0.0,0.0],[0.809017,0.5,0.309017],[0.5,0.309017,0.809017],[0.8506508,0.0,0.5257311],[0.0,0.0,1.0],[-0.5,-0.309017,0.809017],[0.0,-0.5257311,0.8506508],[-0.809017,-0.5,0.309017],[-0.809017,-0.5,-0.309017],[-0.5257311,-0.8506508,0.0],[-0.5,-0.309017,-0.809017],[0.0,0.0,-1.0],[0.0,-0.5257311,-0.8506508],[0.5,0.309017,-0.809017],[0.809017,0.5,-0.309017],[0.8506508,0.0,-0.5257311],[0.809017,-0.5,0.309017],[0.309017,-0.809017,0.5],[0.5257311,-0.8506508,0.0],[0.5,-0.309017,0.809017],[0.0,-1.0,0.0],[-0.309017,-0.809017,0.5],[0.309017,-0.809017,-0.5],[-0.309017,-0.809017,-0.5],[0.809017,-0.5,-0.309017],[0.5,-0.309017,-0.809017],[1.0,0.0,0.0]],"cells":[[0,1,2],[0,3,1],[4,3,0],[3,5,1],[1,6,2],[1,7,6],[5,7,1],[7,8,6],[6,9,2],[6,10,9],[8,10,6],[10,11,9],[9,12,2],[9,13,12],[11,13,9],[13,14,12],[12,0,2],[12,15,0],[14,15,12],[15,4,0],[7,16,8],[7,17,16],[5,17,7],[17,18,16],[3,19,5],[3,20,19],[4,20,3],[20,21,19],[15,22,4],[15,23,22],[14,23,15],[23,24,22],[13,25,14],[13,26,25],[11,26,13],[26,27,25],[10,28,11],[10,29,28],[8,29,10],[29,30,28],[31,32,33],[31,34,32],[18,34,31],[34,21,32],[32,35,33],[32,36,35],[21,36,32],[36,24,35],[35,37,33],[35,38,37],[24,38,35],[38,27,37],[37,39,33],[37,40,39],[27,40,37],[40,30,39],[39,31,33],[39,41,31],[30,41,39],[41,18,31],[34,19,21],[34,17,19],[18,17,34],[17,5,19],[36,22,24],[36,20,22],[21,20,36],[20,4,22],[38,25,27],[38,23,25],[24,23,38],[23,14,25],[40,28,30],[40,26,28],[27,26,40],[26,11,28],[41,16,18],[41,29,16],[30,29,41],[29,8,16]]}
|
1
output/icosahedron_r1_d2.json
Normal file
1
output/icosahedron_r1_d2.json
Normal file
File diff suppressed because one or more lines are too long
1
output/icosahedron_r1_d3.json
Normal file
1
output/icosahedron_r1_d3.json
Normal file
File diff suppressed because one or more lines are too long
1
output/icosahedron_r1_d4.json
Normal file
1
output/icosahedron_r1_d4.json
Normal file
File diff suppressed because one or more lines are too long
1
output/icosahedron_r1_d5.json
Normal file
1
output/icosahedron_r1_d5.json
Normal file
File diff suppressed because one or more lines are too long
1
output/icosahedron_r1_d6.json
Normal file
1
output/icosahedron_r1_d6.json
Normal file
File diff suppressed because one or more lines are too long
1
output/icosahedron_r1_d7.json
Normal file
1
output/icosahedron_r1_d7.json
Normal file
File diff suppressed because one or more lines are too long
427
src/main.rs
Normal file
427
src/main.rs
Normal file
@ -0,0 +1,427 @@
|
||||
extern crate cgmath;
|
||||
|
||||
use std::collections::HashMap;
|
||||
use std::fs::File;
|
||||
use std::io::Write;
|
||||
use std::path::Path;
|
||||
|
||||
use cgmath::prelude::*;
|
||||
use cgmath::Vector3;
|
||||
use serde::ser::{SerializeSeq, Serializer};
|
||||
use serde::Serialize;
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Triangle {
|
||||
a: usize,
|
||||
b: usize,
|
||||
c: usize,
|
||||
}
|
||||
|
||||
impl Triangle {
|
||||
fn new(a: usize, b: usize, c: usize) -> Triangle {
|
||||
Triangle { a, b, c }
|
||||
}
|
||||
}
|
||||
|
||||
impl Serialize for Triangle {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
let vec_indices = vec![self.a, self.b, self.c];
|
||||
let mut seq = serializer.serialize_seq(Some(vec_indices.len()))?;
|
||||
for index in vec_indices {
|
||||
seq.serialize_element(&index)?;
|
||||
}
|
||||
seq.end()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct ArraySerializedVector(Vector3<f32>);
|
||||
|
||||
#[derive(Serialize, Debug)]
|
||||
struct Polyhedron {
|
||||
positions: Vec<ArraySerializedVector>,
|
||||
cells: Vec<Triangle>,
|
||||
}
|
||||
|
||||
impl Serialize for ArraySerializedVector {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
let values = vec![self.0.x, self.0.y, self.0.z];
|
||||
let mut seq = serializer.serialize_seq(Some(values.len()))?;
|
||||
for value in values {
|
||||
seq.serialize_element(&value)?;
|
||||
}
|
||||
seq.end()
|
||||
}
|
||||
}
|
||||
|
||||
impl Polyhedron {
|
||||
fn new() -> Polyhedron {
|
||||
Polyhedron {
|
||||
positions: vec![],
|
||||
cells: vec![],
|
||||
}
|
||||
}
|
||||
|
||||
fn new_isocahedron(radius: f32, detail: usize) -> Polyhedron {
|
||||
let t = (1.0 + (5.0 as f32).sqrt()) / 2.0;
|
||||
let base_isocahedron = Polyhedron {
|
||||
positions: vec![
|
||||
ArraySerializedVector(Vector3::new(-1.0, t, 0.0)),
|
||||
ArraySerializedVector(Vector3::new(1.0, t, 0.0)),
|
||||
ArraySerializedVector(Vector3::new(-1.0, -t, 0.0)),
|
||||
ArraySerializedVector(Vector3::new(1.0, -t, 0.0)),
|
||||
ArraySerializedVector(Vector3::new(0.0, -1.0, t)),
|
||||
ArraySerializedVector(Vector3::new(0.0, 1.0, t)),
|
||||
ArraySerializedVector(Vector3::new(0.0, -1.0, -t)),
|
||||
ArraySerializedVector(Vector3::new(0.0, 1.0, -t)),
|
||||
ArraySerializedVector(Vector3::new(t, 0.0, -1.0)),
|
||||
ArraySerializedVector(Vector3::new(t, 0.0, 1.0)),
|
||||
ArraySerializedVector(Vector3::new(-t, 0.0, -1.0)),
|
||||
ArraySerializedVector(Vector3::new(-t, 0.0, 1.0)),
|
||||
],
|
||||
cells: vec![
|
||||
Triangle::new(0, 11, 5),
|
||||
Triangle::new(0, 5, 1),
|
||||
Triangle::new(0, 1, 7),
|
||||
Triangle::new(0, 7, 10),
|
||||
Triangle::new(0, 10, 11),
|
||||
Triangle::new(1, 5, 9),
|
||||
Triangle::new(5, 11, 4),
|
||||
Triangle::new(11, 10, 2),
|
||||
Triangle::new(10, 7, 6),
|
||||
Triangle::new(7, 1, 8),
|
||||
Triangle::new(3, 9, 4),
|
||||
Triangle::new(3, 4, 2),
|
||||
Triangle::new(3, 2, 6),
|
||||
Triangle::new(3, 6, 8),
|
||||
Triangle::new(3, 8, 9),
|
||||
Triangle::new(4, 9, 5),
|
||||
Triangle::new(2, 4, 11),
|
||||
Triangle::new(6, 2, 10),
|
||||
Triangle::new(8, 6, 7),
|
||||
Triangle::new(9, 8, 1),
|
||||
],
|
||||
};
|
||||
let mut subdivided = Polyhedron::new();
|
||||
subdivided.subdivide(base_isocahedron, radius, detail);
|
||||
subdivided
|
||||
}
|
||||
|
||||
fn new_dual_isocahedron(radius: f32, detail: usize) -> Polyhedron {
|
||||
let isocahedron = Polyhedron::new_isocahedron(radius, detail);
|
||||
let mut dual_isocahedron = Polyhedron::new();
|
||||
dual_isocahedron.dual(isocahedron);
|
||||
dual_isocahedron
|
||||
}
|
||||
|
||||
fn subdivide(&mut self, other: Polyhedron, radius: f32, detail: usize) {
|
||||
// TODO: maybe make this part of the polygon stuct to avoid having to pass it around
|
||||
let mut added_vert_cache: HashMap<(i32, i32, i32), usize> = HashMap::new();
|
||||
let precision = 10_f32.powi(4);
|
||||
for triangle in other.cells {
|
||||
let a = other.positions[triangle.a].0;
|
||||
let b = other.positions[triangle.b].0;
|
||||
let c = other.positions[triangle.c].0;
|
||||
self.subdivide_triangle(a, b, c, radius, detail, precision, &mut added_vert_cache);
|
||||
}
|
||||
}
|
||||
|
||||
fn subdivide_triangle(
|
||||
&mut self,
|
||||
a: Vector3<f32>,
|
||||
b: Vector3<f32>,
|
||||
c: Vector3<f32>,
|
||||
radius: f32,
|
||||
detail: usize,
|
||||
precision: f32,
|
||||
added_vert_cache: &mut HashMap<(i32, i32, i32), usize>,
|
||||
) {
|
||||
let cols = 2usize.pow(detail as u32);
|
||||
let mut new_vertices: Vec<Vec<Vector3<f32>>> = vec![];
|
||||
|
||||
for i in 0..=cols {
|
||||
new_vertices.push(vec![]);
|
||||
let aj = a.clone().lerp(c, i as f32 / cols as f32);
|
||||
let bj = b.clone().lerp(c, i as f32 / cols as f32);
|
||||
let rows = cols - i;
|
||||
|
||||
for j in 0..=rows {
|
||||
if j == 0 && i == cols {
|
||||
new_vertices[i].push(aj.normalize() * radius);
|
||||
} else {
|
||||
new_vertices[i]
|
||||
.push(aj.clone().lerp(bj, j as f32 / rows as f32).normalize() * radius);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for i in 0..cols {
|
||||
for j in 0..2 * (cols - i) - 1 {
|
||||
let k = j / 2;
|
||||
|
||||
let mut triangle = Triangle { a: 0, b: 0, c: 0 };
|
||||
if j % 2 == 0 {
|
||||
triangle.a =
|
||||
self.add_position(new_vertices[i][k + 1], precision, added_vert_cache);
|
||||
triangle.b =
|
||||
self.add_position(new_vertices[i + 1][k], precision, added_vert_cache);
|
||||
triangle.c = self.add_position(new_vertices[i][k], precision, added_vert_cache);
|
||||
} else {
|
||||
triangle.a =
|
||||
self.add_position(new_vertices[i][k + 1], precision, added_vert_cache);
|
||||
triangle.b =
|
||||
self.add_position(new_vertices[i + 1][k + 1], precision, added_vert_cache);
|
||||
triangle.c =
|
||||
self.add_position(new_vertices[i + 1][k], precision, added_vert_cache);
|
||||
}
|
||||
|
||||
self.cells.push(triangle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn add_position(
|
||||
&mut self,
|
||||
vertex: Vector3<f32>,
|
||||
precision: f32,
|
||||
added_vert_cache: &mut HashMap<(i32, i32, i32), usize>,
|
||||
) -> usize {
|
||||
let vertex_key = (
|
||||
(vertex.x * precision).round() as i32,
|
||||
(vertex.y * precision).round() as i32,
|
||||
(vertex.z * precision).round() as i32,
|
||||
);
|
||||
if let Some(added_vert_index) = added_vert_cache.get(&vertex_key) {
|
||||
return *added_vert_index;
|
||||
} else {
|
||||
self.positions.push(ArraySerializedVector(vertex));
|
||||
let added_index = self.positions.len() - 1;
|
||||
added_vert_cache.insert(vertex_key, added_index);
|
||||
return added_index;
|
||||
}
|
||||
}
|
||||
|
||||
fn dual(&mut self, other: Polyhedron) {
|
||||
let vert_to_faces = other.vert_to_faces();
|
||||
let original_vert_count = other.positions.len();
|
||||
let triangle_centroids = other.triangle_centroids();
|
||||
let mut mid_centroid_cache: HashMap<(usize, usize), Vector3<f32>> = HashMap::new();
|
||||
let mut hex_count = 0;
|
||||
let mut pent_count = 0;
|
||||
for i in 0..original_vert_count {
|
||||
let faces = &vert_to_faces[&i];
|
||||
if faces.len() == 6 {
|
||||
hex_count += 1;
|
||||
} else {
|
||||
pent_count += 1;
|
||||
}
|
||||
|
||||
let center_point = find_center_of_triangles(faces, &triangle_centroids);
|
||||
|
||||
for face_index in faces {
|
||||
let triangle = &other.cells[*face_index];
|
||||
let other_verts: Vec<usize> = vec![triangle.a, triangle.b, triangle.c]
|
||||
.drain(..)
|
||||
.filter(|vert| *vert != i)
|
||||
.collect();
|
||||
let sorted_triangle = Triangle::new(i, other_verts[0], other_verts[1]);
|
||||
|
||||
let centroid = triangle_centroids[face_index];
|
||||
let mid_b_centroid = other.calculate_mid_centroid(
|
||||
sorted_triangle.b,
|
||||
faces,
|
||||
centroid,
|
||||
&triangle_centroids,
|
||||
&mut mid_centroid_cache,
|
||||
);
|
||||
let mid_c_centroid = other.calculate_mid_centroid(
|
||||
sorted_triangle.c,
|
||||
faces,
|
||||
centroid,
|
||||
&triangle_centroids,
|
||||
&mut mid_centroid_cache,
|
||||
);
|
||||
|
||||
let positions_start = self.positions.len();
|
||||
// TODO: remove duplication here:
|
||||
// push all triangle_centroids at beginning, same index as face_index
|
||||
// push center_point once in outer loop and save index
|
||||
// (is it okay if vertices show up in positions out of order like that?)
|
||||
// -- yes, I think it is okay
|
||||
self.positions.push(ArraySerializedVector(center_point));
|
||||
self.positions.push(ArraySerializedVector(centroid));
|
||||
self.positions.push(ArraySerializedVector(mid_b_centroid));
|
||||
self.positions.push(ArraySerializedVector(mid_c_centroid));
|
||||
|
||||
self.cells.push(Triangle::new(
|
||||
positions_start,
|
||||
positions_start + 1,
|
||||
positions_start + 2,
|
||||
));
|
||||
self.cells.push(Triangle::new(
|
||||
positions_start,
|
||||
positions_start + 1,
|
||||
positions_start + 3,
|
||||
));
|
||||
}
|
||||
}
|
||||
println!("hexagons: {}", hex_count);
|
||||
println!("pentagons: {}", pent_count);
|
||||
}
|
||||
|
||||
fn vert_to_faces(&self) -> HashMap<usize, Vec<usize>> {
|
||||
let mut vert_to_faces: HashMap<usize, Vec<usize>> = HashMap::new();
|
||||
for i in 0..self.cells.len() {
|
||||
let triangle = &self.cells[i];
|
||||
|
||||
if let Some(faces) = vert_to_faces.get_mut(&triangle.a) {
|
||||
faces.push(i);
|
||||
} else {
|
||||
vert_to_faces.insert(triangle.a, vec![i]);
|
||||
}
|
||||
|
||||
if let Some(faces) = vert_to_faces.get_mut(&triangle.b) {
|
||||
faces.push(i);
|
||||
} else {
|
||||
vert_to_faces.insert(triangle.b, vec![i]);
|
||||
}
|
||||
|
||||
if let Some(faces) = vert_to_faces.get_mut(&triangle.c) {
|
||||
faces.push(i);
|
||||
} else {
|
||||
vert_to_faces.insert(triangle.c, vec![i]);
|
||||
}
|
||||
}
|
||||
vert_to_faces
|
||||
}
|
||||
|
||||
fn triangle_centroids(&self) -> HashMap<usize, Vector3<f32>> {
|
||||
let mut triangle_centroids: HashMap<usize, Vector3<f32>> = HashMap::new();
|
||||
for i in 0..self.cells.len() {
|
||||
let a = self.positions[self.cells[i].a].0;
|
||||
let b = self.positions[self.cells[i].b].0;
|
||||
let c = self.positions[self.cells[i].c].0;
|
||||
triangle_centroids.insert(i, calculate_centroid(a, b, c));
|
||||
}
|
||||
triangle_centroids
|
||||
}
|
||||
|
||||
fn calculate_mid_centroid(
|
||||
&self,
|
||||
vertex_index: usize,
|
||||
faces: &Vec<usize>,
|
||||
centroid: Vector3<f32>,
|
||||
triangle_centroids: &HashMap<usize, Vector3<f32>>,
|
||||
mid_centroid_cache: &mut HashMap<(usize, usize), Vector3<f32>>,
|
||||
) -> Vector3<f32> {
|
||||
let adj_face_index = self.find_adjacent_face(vertex_index, faces).unwrap();
|
||||
let adj_centroid = triangle_centroids[&adj_face_index];
|
||||
if let Some(mid_centroid) = mid_centroid_cache.get(&(vertex_index, adj_face_index)) {
|
||||
return *mid_centroid;
|
||||
} else {
|
||||
let mid_centroid = centroid.clone().lerp(adj_centroid, 0.5);
|
||||
mid_centroid_cache.insert((vertex_index, adj_face_index), mid_centroid);
|
||||
return mid_centroid;
|
||||
}
|
||||
}
|
||||
|
||||
fn find_adjacent_face(&self, vertex_index: usize, faces: &Vec<usize>) -> Option<usize> {
|
||||
for face_index in faces {
|
||||
let triangle = &self.cells[*face_index];
|
||||
if triangle.a == vertex_index
|
||||
|| triangle.b == vertex_index
|
||||
|| triangle.c == vertex_index
|
||||
{
|
||||
return Some(*face_index);
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
fn calculate_centroid(pa: Vector3<f32>, pb: Vector3<f32>, pc: Vector3<f32>) -> Vector3<f32> {
|
||||
let vab_half = (pb.clone() - pa) / 2.0;
|
||||
let pab_half = pa.clone() + vab_half;
|
||||
((pc.clone() - pab_half) * (1.0 / 3.0)) + pab_half
|
||||
}
|
||||
|
||||
fn find_center_of_triangles(
|
||||
triangle_indices: &Vec<usize>,
|
||||
triangle_centroids: &HashMap<usize, Vector3<f32>>,
|
||||
) -> Vector3<f32> {
|
||||
let mut center_point: Vector3<f32> = Vector3::new(0.0, 0.0, 0.0);
|
||||
for triangle_index in triangle_indices.iter() {
|
||||
center_point += triangle_centroids[triangle_index];
|
||||
}
|
||||
center_point /= triangle_indices.len() as f32;
|
||||
center_point
|
||||
}
|
||||
|
||||
fn generate_icosahedron_files(dir: &str, param_list: Vec<(f32, usize)>) {
|
||||
for param in param_list {
|
||||
println!(
|
||||
"Generating icosahedron with radius {} and detail {}...",
|
||||
param.0, param.1
|
||||
);
|
||||
let filename = Path::new(dir).join(format!("icosahedron_r{}_d{}.json", param.0, param.1));
|
||||
let mut file = File::create(filename).expect("Can't create file");
|
||||
let icosahedron = Polyhedron::new_isocahedron(param.0, param.1);
|
||||
println!("triangles: {}", icosahedron.cells.len());
|
||||
println!("vertices: {}", icosahedron.positions.len());
|
||||
let icosahedron_json = serde_json::to_string(&icosahedron).expect("Problem serializing");
|
||||
file.write_all(icosahedron_json.as_bytes())
|
||||
.expect("Can't write to file");
|
||||
}
|
||||
}
|
||||
|
||||
fn generate_hexsphere_files(dir: &str, param_list: Vec<(f32, usize)>) {
|
||||
for param in param_list {
|
||||
println!(
|
||||
"Generating hexsphere with radius {} and detail {}...",
|
||||
param.0, param.1
|
||||
);
|
||||
let filename = Path::new(dir).join(format!("hexsphere_r{}_d{}.json", param.0, param.1));
|
||||
let mut file = File::create(filename).expect("Can't create file");
|
||||
let hexsphere = Polyhedron::new_dual_isocahedron(param.0, param.1);
|
||||
println!("triangles: {}", hexsphere.cells.len());
|
||||
println!("vertices: {}", hexsphere.positions.len());
|
||||
let hexsphere_json = serde_json::to_string(&hexsphere).expect("Problem serializing");
|
||||
file.write_all(hexsphere_json.as_bytes())
|
||||
.expect("Can't write to file");
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
generate_hexsphere_files(
|
||||
"output/",
|
||||
vec![
|
||||
(1.0, 0),
|
||||
(1.0, 1),
|
||||
(1.0, 2),
|
||||
(1.0, 3),
|
||||
(1.0, 4),
|
||||
(1.0, 5),
|
||||
(1.0, 6),
|
||||
(1.0, 7),
|
||||
],
|
||||
);
|
||||
generate_icosahedron_files(
|
||||
"output/",
|
||||
vec![
|
||||
(1.0, 0),
|
||||
(1.0, 1),
|
||||
(1.0, 2),
|
||||
(1.0, 3),
|
||||
(1.0, 4),
|
||||
(1.0, 5),
|
||||
(1.0, 6),
|
||||
(1.0, 7),
|
||||
],
|
||||
);
|
||||
}
|
Loading…
Reference in New Issue
Block a user