Split into bin and lib, add clap, binary format
This commit is contained in:
parent
e0fc3c1917
commit
74eac6115e
106
Cargo.lock
generated
106
Cargo.lock
generated
@ -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]]
|
||||
name = "approx"
|
||||
version = "0.3.1"
|
||||
@ -6,6 +16,16 @@ dependencies = [
|
||||
"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]]
|
||||
name = "autocfg"
|
||||
version = "0.1.2"
|
||||
@ -16,6 +36,11 @@ name = "bitflags"
|
||||
version = "1.0.4"
|
||||
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]]
|
||||
name = "cgmath"
|
||||
version = "0.17.0"
|
||||
@ -27,6 +52,20 @@ dependencies = [
|
||||
"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]]
|
||||
name = "cloudabi"
|
||||
version = "0.0.3"
|
||||
@ -44,7 +83,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
name = "icosahedron"
|
||||
version = "0.1.0"
|
||||
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)",
|
||||
"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_json 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
@ -64,6 +106,11 @@ name = "num-traits"
|
||||
version = "0.2.6"
|
||||
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]]
|
||||
name = "proc-macro2"
|
||||
version = "0.4.27"
|
||||
@ -184,6 +231,19 @@ dependencies = [
|
||||
"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]]
|
||||
name = "rustc_version"
|
||||
version = "0.2.3"
|
||||
@ -238,6 +298,11 @@ dependencies = [
|
||||
"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]]
|
||||
name = "syn"
|
||||
version = "0.15.26"
|
||||
@ -248,11 +313,40 @@ dependencies = [
|
||||
"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]]
|
||||
name = "unicode-xid"
|
||||
version = "0.1.0"
|
||||
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]]
|
||||
name = "winapi"
|
||||
version = "0.3.6"
|
||||
@ -273,15 +367,20 @@ version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[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 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 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 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 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 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 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"
|
||||
@ -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_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 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 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"
|
||||
@ -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_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 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 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 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-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"
|
||||
|
11
Cargo.toml
11
Cargo.toml
@ -4,7 +4,18 @@ version = "0.1.0"
|
||||
authors = ["Tyler Hallada <tyler@hallada.net>"]
|
||||
edition = "2018"
|
||||
|
||||
[lib]
|
||||
name = "icosahedron"
|
||||
path = "src/lib.rs"
|
||||
|
||||
[[bin]]
|
||||
name = "icosahedron"
|
||||
path = "src/bin.rs"
|
||||
|
||||
[dependencies]
|
||||
byteorder = "1.3.2"
|
||||
clap = "2.33.0"
|
||||
cgmath = { version = "0.17.0", features = ["serde"] }
|
||||
rand = "0.6.5"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde_json = "1.0"
|
||||
|
169
src/bin.rs
Normal file
169
src/bin.rs
Normal 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),
|
||||
);
|
||||
}
|
@ -1,23 +1,22 @@
|
||||
extern crate cgmath;
|
||||
extern crate rand;
|
||||
|
||||
use std::collections::HashMap;
|
||||
use std::fs::File;
|
||||
use std::io::Write;
|
||||
use std::ops::AddAssign;
|
||||
use std::path::Path;
|
||||
|
||||
use cgmath::prelude::*;
|
||||
use cgmath::Vector3;
|
||||
use rand::prelude::*;
|
||||
use serde::ser::{SerializeSeq, Serializer};
|
||||
use serde::Serialize;
|
||||
|
||||
const VERT_CACHE_PRECISION: f32 = 10000_f32;
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Triangle {
|
||||
a: usize,
|
||||
b: usize,
|
||||
c: usize,
|
||||
pub struct Triangle {
|
||||
pub a: usize,
|
||||
pub b: usize,
|
||||
pub c: usize,
|
||||
}
|
||||
|
||||
impl Triangle {
|
||||
@ -41,13 +40,14 @@ impl Serialize for Triangle {
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct ArraySerializedVector(Vector3<f32>);
|
||||
pub struct ArraySerializedVector(pub Vector3<f32>);
|
||||
|
||||
#[derive(Serialize, Debug)]
|
||||
struct Polyhedron {
|
||||
positions: Vec<ArraySerializedVector>,
|
||||
cells: Vec<Triangle>,
|
||||
normals: Vec<ArraySerializedVector>,
|
||||
pub struct Polyhedron {
|
||||
pub positions: Vec<ArraySerializedVector>,
|
||||
pub cells: Vec<Triangle>,
|
||||
pub normals: Vec<ArraySerializedVector>,
|
||||
pub colors: Vec<ArraySerializedVector>,
|
||||
#[serde(skip)]
|
||||
added_vert_cache: HashMap<(i32, i32, i32), usize>,
|
||||
faces: Vec<Vec<usize>>,
|
||||
@ -74,17 +74,18 @@ impl AddAssign for ArraySerializedVector {
|
||||
}
|
||||
|
||||
impl Polyhedron {
|
||||
fn new() -> Polyhedron {
|
||||
pub fn new() -> Polyhedron {
|
||||
Polyhedron {
|
||||
positions: vec![],
|
||||
cells: vec![],
|
||||
normals: vec![],
|
||||
colors: vec![],
|
||||
added_vert_cache: HashMap::new(),
|
||||
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 mut base_isocahedron = Polyhedron {
|
||||
positions: vec![],
|
||||
@ -111,6 +112,7 @@ impl Polyhedron {
|
||||
Triangle::new(9, 8, 1),
|
||||
],
|
||||
normals: vec![],
|
||||
colors: vec![],
|
||||
added_vert_cache: HashMap::new(),
|
||||
faces: vec![],
|
||||
};
|
||||
@ -129,17 +131,18 @@ impl Polyhedron {
|
||||
|
||||
let mut subdivided = Polyhedron::new();
|
||||
subdivided.subdivide(base_isocahedron, radius, detail);
|
||||
subdivided.triangles_to_faces();
|
||||
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 mut truncated_isocahedron = Polyhedron::new();
|
||||
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 {
|
||||
let a = other.positions[triangle.a].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(
|
||||
&mut self,
|
||||
a: Vector3<f32>,
|
||||
b: Vector3<f32>,
|
||||
c: Vector3<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![];
|
||||
|
||||
for i in 0..=cols {
|
||||
@ -207,6 +216,8 @@ impl Polyhedron {
|
||||
self.positions.push(ArraySerializedVector(vertex));
|
||||
self.normals
|
||||
.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;
|
||||
self.added_vert_cache.insert(vertex_key, 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 hex_count = 0;
|
||||
let mut pent_count = 0;
|
||||
let mut count = 0;
|
||||
for i in 0..original_vert_count {
|
||||
let faces = &vert_to_faces[&i];
|
||||
if faces.len() == 6 {
|
||||
@ -285,6 +295,34 @@ impl Polyhedron {
|
||||
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>> {
|
||||
let mut vert_to_faces: HashMap<usize, Vec<usize>> = HashMap::new();
|
||||
for i in 0..self.cells.len() {
|
||||
@ -375,7 +413,7 @@ impl Polyhedron {
|
||||
None
|
||||
}
|
||||
|
||||
fn compute_triangle_normals(&mut self) {
|
||||
pub fn compute_triangle_normals(&mut self) {
|
||||
let origin = Vector3::new(0.0, 0.0, 0.0);
|
||||
for i in 0..self.cells.len() {
|
||||
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);
|
||||
for i in 0..self.faces.len() {
|
||||
let first_cell = &self.cells[self.faces[i][0]];
|
||||
@ -442,6 +480,31 @@ impl Polyhedron {
|
||||
*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> {
|
||||
@ -461,71 +524,3 @@ fn find_center_of_triangles(
|
||||
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 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),
|
||||
],
|
||||
);
|
||||
}
|
Loading…
Reference in New Issue
Block a user