Use Rayon to be parallel

This commit is contained in:
Riley Trautman 2017-11-18 18:52:42 -06:00
parent 16e397b8bf
commit ad5392c9eb
3 changed files with 720 additions and 11899 deletions

View file

@ -10,3 +10,4 @@ license = "MIT"
obj = "0.8" obj = "0.8"
noise = "0.4" noise = "0.4"
cgmath = "0.15.0" cgmath = "0.15.0"
rayon = "0.9"

File diff suppressed because it is too large Load diff

View file

@ -4,10 +4,10 @@
extern crate obj; extern crate obj;
extern crate noise; extern crate noise;
extern crate cgmath; extern crate cgmath;
extern crate rayon;
use std::io::Result; use std::io::Result;
use std::path::Path; use std::path::Path;
use std::f32::consts::PI;
use std::fs::File; use std::fs::File;
use std::io::Write; use std::io::Write;
use obj::{Obj, SimplePolygon, IndexTuple}; use obj::{Obj, SimplePolygon, IndexTuple};
@ -17,7 +17,8 @@ use noise::MultiFractal;
use noise::NoiseModule; use noise::NoiseModule;
use cgmath::Vector3; use cgmath::Vector3;
use cgmath::ElementWise; use cgmath::ElementWise;
use cgmath::Array;
use rayon::prelude::*;
// A function called test that takes in 1 32-bit integer // A function called test that takes in 1 32-bit integer
// and returns a 32-bit integer. // and returns a 32-bit integer.
@ -95,30 +96,21 @@ fn find_l_w(obj: &Obj<SimplePolygon>) -> (f32, f32) {
* to the initial input obj's position. * to the initial input obj's position.
*/ */
fn calculate_angle(current_duplicate: i32, current_layer: i32) -> f32 {
(current_duplicate / (2 * current_layer)) as f32 * (0.5 * PI)
}
fn calculate_translation(current_layer: i32, length: f32, width: f32, angle: f32) -> Vector3<f32> {
Vector3::new(length * angle.cos(), width * angle.sin(), 0.0)
}
fn duplicate( fn duplicate(
positions: Vec<Vector3<f32>>, positions: &[Vector3<f32>],
translation: Vector3<f32>, translation: Vector3<f32>,
height_vec: Vector3<f32>, height_vec: Vector3<f32>,
) -> Vec<Vector3<f32>> { ) -> Vec<Vector3<f32>> {
positions positions
.iter() .par_iter()
.map(|point| { .map(|point| {
//height_vec.mul_element_wise(point.clone()) + translation height_vec.mul_element_wise(point.clone()) + translation
point.clone() + translation
}) })
.collect() .collect()
} }
fn generate_city( fn generate_city(
positions: Vec<Vector3<f32>>, positions: &[Vector3<f32>],
layers: i32, layers: i32,
spacing: f32, spacing: f32,
length: f32, length: f32,
@ -127,55 +119,83 @@ fn generate_city(
let length = length + spacing; let length = length + spacing;
let width = width + spacing; let width = width + spacing;
let mut temp = Vector3::new(0.0, 0.0, 0.0); let height_vec = Vector3::new(1.0, 1.0, 1.0);
//let mut coord = Vector3::new(0.0, 0.0, 0.0); let mut output_positions = Vec::new();
output_positions.extend_from_slice(positions);
(1..layers).fold(positions.clone(), |acc_positions, current_layer| { let rest_vec: Vec<_> = (1..layers)
temp.x = -length * (current_layer as f32); .into_par_iter()
temp.y = -width * (current_layer as f32); .flat_map(|current_layer| {
(0..(current_layer * 8))
.into_par_iter()
.flat_map(|current_duplicate| {
let current_ratio = current_duplicate as f32 / (current_layer as f32 * 8.0);
(0..(current_layer * 8)).fold(acc_positions, |mut acc_positions, current_duplicate| { let unit_translation = if current_ratio <= 1.0 / 4.0 {
Vector3::new(1.0, -1.0 + (current_ratio * 8.0), 0.0)
} else if current_ratio <= 2.0 / 4.0 {
Vector3::new(1.0 - ((current_ratio) - 1.0 / 4.0) * 8.0, 1.0, 0.0)
} else if current_ratio <= 3.0 / 4.0 {
Vector3::new(-1.0, 1.0 - ((current_ratio) - 2.0 / 4.0) * 8.0, 0.0)
} else {
Vector3::new(-1.0 + ((current_ratio) - 3.0 / 4.0) * 8.0, -1.0, 0.0)
};
let angle = calculate_angle(current_duplicate, current_layer); println!(
"layer: {}, x: {}, y: {}",
current_layer,
unit_translation.x,
unit_translation.y
);
let translation = calculate_translation(current_layer, length, width, angle); duplicate(
temp += translation; &positions,
current_layer as f32 *
let height_vec = Vector3::new(1.0, 1.0, 1.0); Vector3::new(
length * unit_translation.x,
let x = Vector3::new(1.0, 1.0, 1.0); width * unit_translation.y,
0.0,
acc_positions.extend(duplicate(positions.clone(), temp, height_vec)); ),
height_vec,
acc_positions )
})
.collect::<Vec<_>>()
}) })
}) .collect();
output_positions.extend(rest_vec);
output_positions
} }
fn copy_faces( fn copy_faces(
faces: Vec<Vec<IndexTuple>>, faces: &[Vec<IndexTuple>],
n_positions: usize, n_positions: usize,
layers: usize, layers: usize,
) -> Vec<Vec<IndexTuple>> { ) -> Vec<Vec<IndexTuple>> {
(0..(2 * layers - 1).pow(2)).fold(Vec::new(), |mut acc_faces, current_value| { (0..(2 * layers - 1).pow(2))
let offset = n_positions * current_value + 1; .into_par_iter()
.flat_map(|current_value| {
let offset = n_positions * current_value + 1;
acc_faces.extend(faces.iter().map(|current_face| { faces
current_face .par_iter()
.iter() .map(|current_face| {
.map(|index_tuple| { current_face
IndexTuple( .iter()
index_tuple.0 + offset, .map(|index_tuple| {
index_tuple.1.map(|i| i + offset), IndexTuple(
index_tuple.2.map(|j| j + offset), index_tuple.0 + offset,
) index_tuple.1.map(|i| i + offset),
index_tuple.2.map(|j| j + offset),
)
})
.collect()
}) })
.collect() .collect::<Vec<_>>()
})); })
.collect()
acc_faces
})
} }
fn save(filename: &Path, positions: Vec<Vector3<f32>>, faces: Vec<Vec<IndexTuple>>) { fn save(filename: &Path, positions: Vec<Vector3<f32>>, faces: Vec<Vec<IndexTuple>>) {
@ -186,7 +206,7 @@ fn save(filename: &Path, positions: Vec<Vector3<f32>>, faces: Vec<Vec<IndexTuple
} }
for face in faces { for face in faces {
write!(file, "f"); write!(file, "f").unwrap();
for value in face { for value in face {
write!(file, " {}/", value.0).unwrap(); write!(file, " {}/", value.0).unwrap();
if let Some(i) = value.1 { if let Some(i) = value.1 {
@ -209,25 +229,25 @@ fn main() {
if let Ok(obj) = maybe_obj { if let Ok(obj) = maybe_obj {
println!("Position: {:?}", obj.position); println!("Position: {:?}", obj.position);
let layers = 10; let layers = 5;
let spacing = 1.0; let spacing = 1.0;
let (length, width) = find_l_w(&obj); let (length, width) = find_l_w(&obj);
println!("Length: {} Width: {}", length, width); println!("Length: {} Width: {}", length, width);
let input_positions = obj.position let input_positions: Vec<_> = obj.position
.iter() .iter()
.map(|point| Vector3::new(point[0], point[1], point[2])) .map(|point| Vector3::new(point[0], point[1], point[2]))
.collect(); .collect();
let output_positions = generate_city(input_positions, layers, spacing, length, width); let output_positions = generate_city(&input_positions, layers, spacing, length, width);
println!("Objects: {:?}", obj.objects[0].groups[0].polys[0]); println!("Objects: {:?}", obj.objects[0].groups[0].polys[0]);
// I have two faces, blurry's the one I'm not. // I have two faces, blurry's the one I'm not.
let output_faces = copy_faces( let output_faces = copy_faces(
obj.objects[0].groups[0].polys.clone(), &obj.objects[0].groups[0].polys,
obj.position.len(), obj.position.len(),
layers as usize, layers as usize,
); );