Split into bin and lib, add clap, binary format

This commit is contained in:
Tyler Hallada 2019-07-04 16:16:41 -04:00
parent e0fc3c1917
commit 74eac6115e
4 changed files with 370 additions and 89 deletions

106
Cargo.lock generated
View File

@ -1,3 +1,13 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
[[package]]
name = "ansi_term"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]] [[package]]
name = "approx" name = "approx"
version = "0.3.1" version = "0.3.1"
@ -6,6 +16,16 @@ dependencies = [
"num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]]
name = "atty"
version = "0.2.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)",
"termion 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]] [[package]]
name = "autocfg" name = "autocfg"
version = "0.1.2" version = "0.1.2"
@ -16,6 +36,11 @@ name = "bitflags"
version = "1.0.4" version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "byteorder"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
name = "cgmath" name = "cgmath"
version = "0.17.0" version = "0.17.0"
@ -27,6 +52,20 @@ dependencies = [
"serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]]
name = "clap"
version = "2.33.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
"atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
"strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
"textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
"vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]] [[package]]
name = "cloudabi" name = "cloudabi"
version = "0.0.3" version = "0.0.3"
@ -44,7 +83,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
name = "icosahedron" name = "icosahedron"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
"cgmath 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)", "cgmath 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)",
"clap 2.33.0 (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)", "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)", "serde_json 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
@ -64,6 +106,11 @@ name = "num-traits"
version = "0.2.6" version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "numtoa"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
name = "proc-macro2" name = "proc-macro2"
version = "0.4.27" version = "0.4.27"
@ -184,6 +231,19 @@ dependencies = [
"rand_core 0.3.1 (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 = "redox_syscall"
version = "0.1.56"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "redox_termios"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]] [[package]]
name = "rustc_version" name = "rustc_version"
version = "0.2.3" version = "0.2.3"
@ -238,6 +298,11 @@ dependencies = [
"serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]]
name = "strsim"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
name = "syn" name = "syn"
version = "0.15.26" version = "0.15.26"
@ -248,11 +313,40 @@ dependencies = [
"unicode-xid 0.1.0 (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 = "termion"
version = "1.5.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)",
"numtoa 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)",
"redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "textwrap"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "unicode-width"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
name = "unicode-xid" name = "unicode-xid"
version = "0.1.0" version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "vec_map"
version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
name = "winapi" name = "winapi"
version = "0.3.6" version = "0.3.6"
@ -273,15 +367,20 @@ version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
[metadata] [metadata]
"checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
"checksum approx 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3c57ff1a5b00753647aebbbcf4ea67fa1e711a65ea7a30eb90dbf07de2485aee" "checksum approx 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3c57ff1a5b00753647aebbbcf4ea67fa1e711a65ea7a30eb90dbf07de2485aee"
"checksum atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9a7d5b8723950951411ee34d271d99dddcc2035a16ab25310ea2c8cfd4369652"
"checksum autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a6d640bee2da49f60a4068a7fae53acde8982514ab7bae8b8cea9e88cbcfd799" "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 bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12"
"checksum byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a7c3dd8985a7111efc5c80b44e23ecdd8c007de8ade3b96595387e812b957cf5"
"checksum cgmath 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)" = "283944cdecc44bf0b8dd010ec9af888d3b4f142844fdbe026c20ef68148d6fe7" "checksum cgmath 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)" = "283944cdecc44bf0b8dd010ec9af888d3b4f142844fdbe026c20ef68148d6fe7"
"checksum clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9"
"checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" "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 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 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 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 num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0b3a5d7cc97d6d30d8b9bc8fa19bf45349ffe46241e8816f50f62f6d6aaabee1"
"checksum numtoa 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b8f8bdf33df195859076e54ab11ee78a1b208382d3a26ec40d142ffc1ecc49ef"
"checksum proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)" = "4d317f9caece796be1980837fd5cb3dfec5613ebdb04ad0956deea83ce168915" "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 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 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca"
@ -295,6 +394,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum rand_pcg 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "086bd09a33c7044e56bb44d5bdde5a60e7f119a9e95b0775f545de759a32fe05" "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 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 rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2"
"checksum redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)" = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84"
"checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76"
"checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" "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 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 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
@ -302,8 +403,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)" = "9f301d728f2b94c9a7691c90f07b0b4e8a4517181d9461be94c04bddeb4bd850" "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_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 serde_json 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)" = "27dce848e7467aa0e2fcaf0a413641499c0b745452aaca1194d24dedde9e13c9"
"checksum strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
"checksum syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)" = "f92e629aa1d9c827b2bb8297046c1ccffc57c99b947a680d3ccff1f136a3bee9" "checksum syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)" = "f92e629aa1d9c827b2bb8297046c1ccffc57c99b947a680d3ccff1f136a3bee9"
"checksum termion 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6a8fb22f7cde82c8220e5aeacb3258ed7ce996142c77cba193f203515e26c330"
"checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
"checksum unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "882386231c45df4700b275c7ff55b6f3698780a650026380e72dabe76fa46526"
"checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" "checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc"
"checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a"
"checksum winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "92c1eb33641e276cfa214a0522acad57be5c56b10cb348b3c5117db75f3ac4b0" "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-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" "checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"

View File

@ -4,7 +4,18 @@ version = "0.1.0"
authors = ["Tyler Hallada <tyler@hallada.net>"] authors = ["Tyler Hallada <tyler@hallada.net>"]
edition = "2018" edition = "2018"
[lib]
name = "icosahedron"
path = "src/lib.rs"
[[bin]]
name = "icosahedron"
path = "src/bin.rs"
[dependencies] [dependencies]
byteorder = "1.3.2"
clap = "2.33.0"
cgmath = { version = "0.17.0", features = ["serde"] } cgmath = { version = "0.17.0", features = ["serde"] }
rand = "0.6.5"
serde = { version = "1.0", features = ["derive"] } serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0" serde_json = "1.0"

169
src/bin.rs Normal file
View File

@ -0,0 +1,169 @@
#[macro_use]
extern crate clap;
extern crate byteorder;
extern crate icosahedron;
use std::fs::{File, metadata};
use std::io::{BufWriter, Write};
use std::path::Path;
use byteorder::{WriteBytesExt, LittleEndian};
use icosahedron::{Polyhedron};
fn write_to_binary_file(polyhedron: Polyhedron, path: &Path) {
let bin_file = File::create(path).expect("Can't create file");
let mut writer = BufWriter::new(bin_file);
let write_error_message = "Error encountered while writing to binary file";
writer.write_u32::<LittleEndian>(polyhedron.positions.len() as u32)
.expect(write_error_message);
writer.write_u32::<LittleEndian>(polyhedron.cells.len() as u32)
.expect(write_error_message);
for position in polyhedron.positions.iter() {
writer.write_f32::<LittleEndian>(position.0.x).expect(write_error_message);
writer.write_f32::<LittleEndian>(position.0.y).expect(write_error_message);
writer.write_f32::<LittleEndian>(position.0.z).expect(write_error_message);
}
for normal in polyhedron.normals.iter() {
writer.write_f32::<LittleEndian>(normal.0.x).expect(write_error_message);
writer.write_f32::<LittleEndian>(normal.0.y).expect(write_error_message);
writer.write_f32::<LittleEndian>(normal.0.z).expect(write_error_message);
}
for color in polyhedron.colors.iter() {
writer.write_f32::<LittleEndian>(color.0.x).expect(write_error_message);
writer.write_f32::<LittleEndian>(color.0.y).expect(write_error_message);
writer.write_f32::<LittleEndian>(color.0.z).expect(write_error_message);
}
for cell in polyhedron.cells.iter() {
writer.write_u32::<LittleEndian>(cell.a as u32).expect(write_error_message);
writer.write_u32::<LittleEndian>(cell.b as u32).expect(write_error_message);
writer.write_u32::<LittleEndian>(cell.c as u32).expect(write_error_message);
}
}
fn write_to_json_file(polyhedron: Polyhedron, path: &Path) {
let mut json_file = File::create(path).expect("Can't create file");
let json = serde_json::to_string(&polyhedron).expect("Problem serializing");
json_file.write_all(json.as_bytes()).expect("Can't write to file");
}
fn generate_files(dir: &str, format: Format, truncated: bool, colored: bool,
param_list: Vec<(f32, u32)>) {
let mesh_type = if truncated {
"hexsphere"
} else {
"icosahedron"
};
for param in param_list {
println!(
"Generating {} with radius {} and detail {}...",
mesh_type, param.0, param.1
);
let polyhedron = if truncated {
let mut hexsphere = Polyhedron::new_truncated_isocahedron(param.0, param.1);
hexsphere.compute_triangle_normals();
hexsphere
} else {
let mut icosahedron = Polyhedron::new_isocahedron(param.0, param.1);
icosahedron.compute_triangle_normals();
icosahedron
};
let colored_polyhedron = if colored {
let mut colored = Polyhedron::new();
colored.unique_vertices(polyhedron);
colored.assign_random_face_colors();
colored
} else {
polyhedron
};
println!("triangles: {}", colored_polyhedron.cells.len());
println!("vertices: {}", colored_polyhedron.positions.len());
let filename = Path::new(dir).join(
format!("{}_r{}_d{}.{}", mesh_type, param.0, param.1, format.extension())
);
match format {
Format::Bin => write_to_binary_file(colored_polyhedron, &filename),
Format::Json => write_to_json_file(colored_polyhedron, &filename),
};
}
}
arg_enum!{
#[derive(Debug)]
enum Format {
Json,
Bin,
}
}
impl Format {
fn extension(&self) -> String {
match self {
Format::Bin => "bin".to_string(),
Format::Json => "json".to_string(),
}
}
}
fn main() {
let dir_exists = |path: String| {
let path_clone = path.clone();
match metadata(path) {
Ok(metadata) => {
if metadata.is_dir() {
Ok(())
} else {
Err(String::from(format!("Output '{}' is not a directory", &path_clone)))
}
}
Err(_) => Err(String::from(format!("Directory '{}' doesn't exist", &path_clone)))
}
};
let matches = clap_app!(icosahedron =>
(version: "1.0")
(author: "Tyler Hallada <tyler@hallada.net>")
(about: "Generates 3D icosahedra meshes")
(@arg truncated: -t --truncated "Generate truncated icosahedra (hexspheres).")
(@arg colored: -c --colored "Assigns a random color to every face \
(increases vertices count).")
(@arg detail: -d --detail +takes_value default_value("7")
"Maximum detail level to generate. \
Each level multiplies the number of triangles by 4.")
(@arg radius: -r --radius +takes_value default_value("1.0")
"Radius of the polyhedron,")
(@arg format: -f --format +takes_value possible_values(&Format::variants())
default_value("Bin")
"Format to write the files in.")
(@arg output: [OUTPUT] {dir_exists} default_value("output/")
"Directory to write the output files to.")
).get_matches();
let truncated = matches.is_present("truncated");
let colored = matches.is_present("colored");
let detail = value_t!(matches.value_of("detail"), u32).unwrap_or(7);
let radius = value_t!(matches.value_of("radius"), f32).unwrap_or(1.0);
let format = value_t!(matches.value_of("format"), Format).unwrap_or(Format::Bin);
let output = matches.value_of("output").unwrap_or("output/");
let param_list = |detail: u32, radius: f32| -> Vec<(f32, u32)> {
let mut params = vec![];
for detail in 0..(detail + 1) {
params.push((radius, detail));
}
params
};
generate_files(
output,
format,
truncated,
colored,
param_list(detail, radius),
);
}

View File

@ -1,23 +1,22 @@
extern crate cgmath; extern crate cgmath;
extern crate rand;
use std::collections::HashMap; use std::collections::HashMap;
use std::fs::File;
use std::io::Write;
use std::ops::AddAssign; use std::ops::AddAssign;
use std::path::Path;
use cgmath::prelude::*; use cgmath::prelude::*;
use cgmath::Vector3; use cgmath::Vector3;
use rand::prelude::*;
use serde::ser::{SerializeSeq, Serializer}; use serde::ser::{SerializeSeq, Serializer};
use serde::Serialize; use serde::Serialize;
const VERT_CACHE_PRECISION: f32 = 10000_f32; const VERT_CACHE_PRECISION: f32 = 10000_f32;
#[derive(Debug)] #[derive(Debug)]
struct Triangle { pub struct Triangle {
a: usize, pub a: usize,
b: usize, pub b: usize,
c: usize, pub c: usize,
} }
impl Triangle { impl Triangle {
@ -41,13 +40,14 @@ impl Serialize for Triangle {
} }
#[derive(Debug)] #[derive(Debug)]
struct ArraySerializedVector(Vector3<f32>); pub struct ArraySerializedVector(pub Vector3<f32>);
#[derive(Serialize, Debug)] #[derive(Serialize, Debug)]
struct Polyhedron { pub struct Polyhedron {
positions: Vec<ArraySerializedVector>, pub positions: Vec<ArraySerializedVector>,
cells: Vec<Triangle>, pub cells: Vec<Triangle>,
normals: Vec<ArraySerializedVector>, pub normals: Vec<ArraySerializedVector>,
pub colors: Vec<ArraySerializedVector>,
#[serde(skip)] #[serde(skip)]
added_vert_cache: HashMap<(i32, i32, i32), usize>, added_vert_cache: HashMap<(i32, i32, i32), usize>,
faces: Vec<Vec<usize>>, faces: Vec<Vec<usize>>,
@ -74,17 +74,18 @@ impl AddAssign for ArraySerializedVector {
} }
impl Polyhedron { impl Polyhedron {
fn new() -> Polyhedron { pub fn new() -> Polyhedron {
Polyhedron { Polyhedron {
positions: vec![], positions: vec![],
cells: vec![], cells: vec![],
normals: vec![], normals: vec![],
colors: vec![],
added_vert_cache: HashMap::new(), added_vert_cache: HashMap::new(),
faces: vec![], faces: vec![],
} }
} }
fn new_isocahedron(radius: f32, detail: usize) -> Polyhedron { pub fn new_isocahedron(radius: f32, detail: u32) -> Polyhedron {
let t = (1.0 + (5.0 as f32).sqrt()) / 2.0; let t = (1.0 + (5.0 as f32).sqrt()) / 2.0;
let mut base_isocahedron = Polyhedron { let mut base_isocahedron = Polyhedron {
positions: vec![], positions: vec![],
@ -111,6 +112,7 @@ impl Polyhedron {
Triangle::new(9, 8, 1), Triangle::new(9, 8, 1),
], ],
normals: vec![], normals: vec![],
colors: vec![],
added_vert_cache: HashMap::new(), added_vert_cache: HashMap::new(),
faces: vec![], faces: vec![],
}; };
@ -129,17 +131,18 @@ impl Polyhedron {
let mut subdivided = Polyhedron::new(); let mut subdivided = Polyhedron::new();
subdivided.subdivide(base_isocahedron, radius, detail); subdivided.subdivide(base_isocahedron, radius, detail);
subdivided.triangles_to_faces();
subdivided subdivided
} }
fn new_truncated_isocahedron(radius: f32, detail: usize) -> Polyhedron { pub fn new_truncated_isocahedron(radius: f32, detail: u32) -> Polyhedron {
let isocahedron = Polyhedron::new_isocahedron(radius, detail); let isocahedron = Polyhedron::new_isocahedron(radius, detail);
let mut truncated_isocahedron = Polyhedron::new(); let mut truncated_isocahedron = Polyhedron::new();
truncated_isocahedron.truncated(isocahedron); truncated_isocahedron.truncated(isocahedron);
truncated_isocahedron truncated_isocahedron
} }
fn subdivide(&mut self, other: Polyhedron, radius: f32, detail: usize) { fn subdivide(&mut self, other: Polyhedron, radius: f32, detail: u32) {
for triangle in other.cells { for triangle in other.cells {
let a = other.positions[triangle.a].0; let a = other.positions[triangle.a].0;
let b = other.positions[triangle.b].0; let b = other.positions[triangle.b].0;
@ -148,15 +151,21 @@ impl Polyhedron {
} }
} }
fn triangles_to_faces(&mut self) {
for (cell_index, _) in self.cells.iter().enumerate() {
self.faces.push(vec![cell_index]);
}
}
fn subdivide_triangle( fn subdivide_triangle(
&mut self, &mut self,
a: Vector3<f32>, a: Vector3<f32>,
b: Vector3<f32>, b: Vector3<f32>,
c: Vector3<f32>, c: Vector3<f32>,
radius: f32, radius: f32,
detail: usize, detail: u32,
) { ) {
let cols = 2usize.pow(detail as u32); let cols = 2usize.pow(detail);
let mut new_vertices: Vec<Vec<Vector3<f32>>> = vec![]; let mut new_vertices: Vec<Vec<Vector3<f32>>> = vec![];
for i in 0..=cols { for i in 0..=cols {
@ -207,6 +216,8 @@ impl Polyhedron {
self.positions.push(ArraySerializedVector(vertex)); self.positions.push(ArraySerializedVector(vertex));
self.normals self.normals
.push(ArraySerializedVector(Vector3::new(0.0, 0.0, 0.0))); .push(ArraySerializedVector(Vector3::new(0.0, 0.0, 0.0)));
self.colors
.push(ArraySerializedVector(Vector3::new(1.0, 1.0, 1.0)));
let added_index = self.positions.len() - 1; let added_index = self.positions.len() - 1;
self.added_vert_cache.insert(vertex_key, added_index); self.added_vert_cache.insert(vertex_key, added_index);
return added_index; return added_index;
@ -220,7 +231,6 @@ impl Polyhedron {
let mut mid_centroid_cache: HashMap<(usize, usize, usize), Vector3<f32>> = HashMap::new(); let mut mid_centroid_cache: HashMap<(usize, usize, usize), Vector3<f32>> = HashMap::new();
let mut hex_count = 0; let mut hex_count = 0;
let mut pent_count = 0; let mut pent_count = 0;
let mut count = 0;
for i in 0..original_vert_count { for i in 0..original_vert_count {
let faces = &vert_to_faces[&i]; let faces = &vert_to_faces[&i];
if faces.len() == 6 { if faces.len() == 6 {
@ -285,6 +295,34 @@ impl Polyhedron {
println!("pentagons: {}", pent_count); println!("pentagons: {}", pent_count);
} }
pub fn unique_vertices(&mut self, other: Polyhedron) {
for triangle in other.cells {
let vertex_a = other.positions[triangle.a].0;
let vertex_b = other.positions[triangle.b].0;
let vertex_c = other.positions[triangle.c].0;
let normal_a = other.normals[triangle.a].0;
let normal_b = other.normals[triangle.b].0;
let normal_c = other.normals[triangle.c].0;
self.positions.push(ArraySerializedVector(vertex_a));
self.positions.push(ArraySerializedVector(vertex_b));
self.positions.push(ArraySerializedVector(vertex_c));
self.normals.push(ArraySerializedVector(normal_a));
self.normals.push(ArraySerializedVector(normal_b));
self.normals.push(ArraySerializedVector(normal_c));
self.colors
.push(ArraySerializedVector(Vector3::new(1.0, 1.0, 1.0)));
self.colors
.push(ArraySerializedVector(Vector3::new(1.0, 1.0, 1.0)));
self.colors
.push(ArraySerializedVector(Vector3::new(1.0, 1.0, 1.0)));
let added_index = self.positions.len() - 1;
self.cells
.push(Triangle::new(added_index - 2, added_index - 1, added_index));
}
self.faces = other.faces;
}
fn vert_to_faces(&self) -> HashMap<usize, Vec<usize>> { fn vert_to_faces(&self) -> HashMap<usize, Vec<usize>> {
let mut vert_to_faces: HashMap<usize, Vec<usize>> = HashMap::new(); let mut vert_to_faces: HashMap<usize, Vec<usize>> = HashMap::new();
for i in 0..self.cells.len() { for i in 0..self.cells.len() {
@ -375,7 +413,7 @@ impl Polyhedron {
None None
} }
fn compute_triangle_normals(&mut self) { pub fn compute_triangle_normals(&mut self) {
let origin = Vector3::new(0.0, 0.0, 0.0); let origin = Vector3::new(0.0, 0.0, 0.0);
for i in 0..self.cells.len() { for i in 0..self.cells.len() {
let vertex_a = &self.positions[self.cells[i].a].0; let vertex_a = &self.positions[self.cells[i].a].0;
@ -406,7 +444,7 @@ impl Polyhedron {
} }
} }
fn compute_face_normals(&mut self) { pub fn compute_face_normals(&mut self) {
let origin = Vector3::new(0.0, 0.0, 0.0); let origin = Vector3::new(0.0, 0.0, 0.0);
for i in 0..self.faces.len() { for i in 0..self.faces.len() {
let first_cell = &self.cells[self.faces[i][0]]; let first_cell = &self.cells[self.faces[i][0]];
@ -442,6 +480,31 @@ impl Polyhedron {
*normal = ArraySerializedVector(normal.0.normalize()); *normal = ArraySerializedVector(normal.0.normalize());
} }
} }
pub fn assign_random_face_colors(&mut self) {
let mut rng = rand::thread_rng();
for i in 0..self.faces.len() {
let face_color = Vector3::new(rng.gen(), rng.gen(), rng.gen());
for c in 0..self.faces[i].len() {
let face_cell = &self.cells[self.faces[i][c]];
self.colors[face_cell.a] = ArraySerializedVector(face_color);
self.colors[face_cell.b] = ArraySerializedVector(face_color);
self.colors[face_cell.c] = ArraySerializedVector(face_color);
}
}
}
pub fn export_cells(&self) -> Vec<u32> {
let mut cell_vec: Vec<u32> = vec![];
for cell in &self.cells {
cell_vec.push(cell.a as u32);
cell_vec.push(cell.b as u32);
cell_vec.push(cell.c as u32);
}
cell_vec
}
} }
fn calculate_centroid(pa: Vector3<f32>, pb: Vector3<f32>, pc: Vector3<f32>) -> Vector3<f32> { fn calculate_centroid(pa: Vector3<f32>, pb: Vector3<f32>, pc: Vector3<f32>) -> Vector3<f32> {
@ -461,71 +524,3 @@ fn find_center_of_triangles(
center_point /= triangle_indices.len() as f32; center_point /= triangle_indices.len() as f32;
center_point 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 mut icosahedron = Polyhedron::new_isocahedron(param.0, param.1);
icosahedron.compute_triangle_normals();
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 mut hexsphere = Polyhedron::new_truncated_isocahedron(param.0, param.1);
hexsphere.compute_triangle_normals();
// hexsphere.compute_face_normals();
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),
// (1.0, 8),
// (1.0, 9),
],
);
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),
],
);
}