Compare commits

...
This repository has been archived on 2025-04-11. You can view files and clone it, but cannot push or open issues or pull requests.

7 commits

Author SHA1 Message Date
Riley Trautman
4694921b46 Use par_iter where it counts 2017-11-19 01:07:26 -06:00
Riley Trautman
a47dd96fa1 Use BufWriter to buffer writes, uncomment par_iters 2017-11-19 00:00:32 -06:00
Riley Trautman
bc736c2ead Change scale 2017-11-18 22:29:59 -06:00
Riley Trautman
27d1ac08d2 Play with noise 2017-11-18 22:15:16 -06:00
Riley Trautman
bd03665407 Merge branch 'development' into parallel 2017-11-18 19:37:41 -06:00
Riley Trautman
b42ae84a55 Don't print a bunch 2017-11-18 18:55:07 -06:00
Riley Trautman
ad5392c9eb Use Rayon to be parallel 2017-11-18 18:52:42 -06:00
3 changed files with 89 additions and 87 deletions

View file

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

View file

@ -12,14 +12,6 @@ v 1 0 3
v 1 1 3
v 1 1 0
v 1 0 0
v 2 0 0
v 2 1 3
v 2 1 0
v 2 0 3
v 3 0 3
v 3 1 3
v 3 1 0
v 3 0 0
# 0 UV coordinates
@ -46,16 +38,4 @@ f 1//5 7//5 8//5
f 7//5 1//5 3//5
f 1//6 5//6 4//6
f 5//6 1//6 8//6
f 9//1 10//1 11//1
f 10//1 9//1 12//1
f 10//2 13//2 14//2
f 13//2 10//2 12//2
f 13//3 15//3 14//3
f 15//3 13//3 16//3
f 15//4 10//4 14//4
f 10//4 15//4 11//4
f 9//5 15//5 16//5
f 15//5 9//5 11//5
f 9//6 13//6 12//6
f 13//6 9//6 16//6

View file

@ -4,20 +4,22 @@
extern crate obj;
extern crate noise;
extern crate cgmath;
extern crate rayon;
use std::io::Result;
use std::path::Path;
use std::f32::consts::PI;
use std::fs::File;
use std::io::Write;
use std::io::{BufWriter, Write};
use obj::{Obj, SimplePolygon, IndexTuple};
use noise::Fbm;
//use noise::Seedable;
//use noise::MultiFractal;
use noise::MultiFractal;
use noise::NoiseModule;
use cgmath::Vector3;
use cgmath::ElementWise;
use rayon::prelude::*;
// A function called test that takes in 1 32-bit integer
// and returns a 32-bit integer.
/*
@ -45,12 +47,11 @@ fn distance_a_to_b(ax: f32, ay: f32, bx: f32, by: f32) -> f32 {
}
fn return_at(x: f32, y: f32, fbmnoise: &Fbm<f32>) -> f32 {
let n = 20.0 * fbmnoise.get([x, y]);
let n = n - n.floor();
let zero_to_one_noise = (1.0 + fbmnoise.get([x, y])) * 0.5;
let z = 0.0f32;
let m = z.max(1.0 - 1.0 * distance_a_to_b(x, y, 0.5, 0.5));
let m = distance_a_to_b(x, y, 0.5, 0.5);
return (m * 0.15) + (n * 0.85);
return (zero_to_one_noise * 0.90) + (m * 0.10);
}
fn find_l_w(obj: &Obj<SimplePolygon>) -> (f32, f32) {
@ -85,16 +86,8 @@ fn find_l_w(obj: &Obj<SimplePolygon>) -> (f32, f32) {
* 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(length: f32, width: f32, angle: f32) -> Vector3<f32> {
Vector3::new(length * angle.cos(), width * angle.sin(), 0.0)
}
fn duplicate(
positions: Vec<Vector3<f32>>,
positions: &[Vector3<f32>],
translation: Vector3<f32>,
height_scalar: f32,
) -> Vec<Vector3<f32>> {
@ -104,14 +97,14 @@ fn duplicate(
Vector3::new(
point.x + translation.x,
point.y + translation.y,
point.z * height_scalar,
point.z * height_scalar * 2.0,
)
})
.collect()
}
fn generate_city(
positions: Vec<Vector3<f32>>,
positions: &[Vector3<f32>],
layers: i32,
spacing: f32,
length: f32,
@ -120,65 +113,95 @@ fn generate_city(
let length = length + spacing;
let width = width + spacing;
let mut temp = Vector3::new(0.0, 0.0, 0.0);
let fbm: Fbm<f32> = Fbm::new()
.set_octaves(1)
.set_frequency(6.0)
.set_persistence(3.0)
.set_lacunarity(30.0);
let mut coord = Vector3::new(0.5, 0.5, 0.0);
let mut output_positions = duplicate(
positions,
Vector3::new(0.0, 0.0, 0.0),
return_at(0.5, 0.5, &fbm),
);
let fbm: Fbm<f32> = Fbm::new();
let rest_vec: Vec<_> = (1..layers)
.into_par_iter()
.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);
(1..layers).fold(positions.clone(), |acc_positions, current_layer| {
temp.x = -length * (current_layer as f32);
temp.y = -width * (current_layer as f32);
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)
};
(0..(current_layer * 8)).fold(acc_positions, |mut acc_positions, current_duplicate| {
let translation = current_layer as f32 *
Vector3::new(length * unit_translation.x, width * unit_translation.y, 0.0);
let angle = calculate_angle(current_duplicate, current_layer);
// gets into range -1 to +1
let coord = 1.0 / 5.0 *
translation.mul_element_wise(
Vector3::new(1.0 / length as f32, 1.0 / width as f32, 0.0),
);
let translation = calculate_translation(length, width, angle);
temp += translation;
// gets into range -0.4 to +0.4
let coord = 0.4 * coord;
coord += translation.mul_element_wise(Vector3::new(
(2.0 / (layers as f32 * 2.0 - 1.0)),
(2.0 / (layers as f32 * 2.0 - 1.0)),
0.0,
));
// gets into range 0.1 to 0.9
let coord = coord + Vector3::new(0.5, 0.5, 0.0);
let height_scalar = return_at(coord.x, coord.y, &fbm);
let height_scalar = return_at(coord.x, coord.y, &fbm);
acc_positions.extend(duplicate(positions.clone(), temp, height_scalar));
acc_positions
duplicate(&positions, translation, height_scalar)
})
.collect::<Vec<_>>()
})
})
.collect();
output_positions.extend(rest_vec);
output_positions
}
fn copy_faces(
faces: Vec<Vec<IndexTuple>>,
faces: &[Vec<IndexTuple>],
n_positions: usize,
layers: usize,
) -> Vec<Vec<IndexTuple>> {
(0..(2 * layers - 1).pow(2)).fold(Vec::new(), |mut acc_faces, current_value| {
let offset = n_positions * current_value + 1;
(0..(2 * layers - 1).pow(2))
.into_par_iter()
.flat_map(|current_value| {
let offset = n_positions * current_value + 1;
acc_faces.extend(faces.iter().map(|current_face| {
current_face
faces
.iter()
.map(|index_tuple| {
IndexTuple(
index_tuple.0 + offset,
index_tuple.1.map(|i| i + offset),
index_tuple.2.map(|j| j + offset),
)
.map(|current_face| {
current_face
.iter()
.map(|index_tuple| {
IndexTuple(
index_tuple.0 + offset,
index_tuple.1.map(|i| i + offset),
index_tuple.2.map(|j| j + offset),
)
})
.collect()
})
.collect()
}));
acc_faces
})
.collect::<Vec<_>>()
})
.collect()
}
fn save(filename: &Path, positions: Vec<Vector3<f32>>, faces: Vec<Vec<IndexTuple>>) {
let mut file = File::create(filename).unwrap();
let mut file = BufWriter::new(File::create(filename).unwrap());
for pos in positions {
write!(file, "v {} {} {}\n", pos[0], pos[1], pos[2]).unwrap();
@ -202,34 +225,32 @@ fn save(filename: &Path, positions: Vec<Vector3<f32>>, faces: Vec<Vec<IndexTuple
fn main() {
let path = Path::new("data/test.obj");
let path = Path::new("data/teapot.obj");
let maybe_obj: Result<Obj<SimplePolygon>> = Obj::load(&path);
if let Ok(obj) = maybe_obj {
println!("Position: {:?}", obj.position);
let layers = 10;
let spacing = 1.0;
let (length, width) = find_l_w(&obj);
println!("Length: {} Width: {}", length, width);
let input_positions = obj.position
let input_positions: Vec<_> = obj.position
.iter()
.map(|point| Vector3::new(point[0], point[1], point[2]))
.collect();
let output_positions = generate_city(input_positions, layers, spacing, length, width);
println!("Objects: {:?}", obj.objects[0].groups[0].polys[0]);
let output_positions = generate_city(&input_positions, layers, spacing, length, width);
let output_faces = copy_faces(
obj.objects[0].groups[0].polys.clone(),
&obj.objects[0].groups[0].polys,
obj.position.len(),
layers as usize,
);
save(Path::new("build/noice.obj"), output_positions, output_faces);
save(
Path::new("target/noice.obj"),
output_positions,
output_faces,
);
}
}