make seperate struct for buffer

This commit is contained in:
Simon Gardling 2021-04-01 13:56:10 -04:00
parent d887b13579
commit af0b9f9222
6 changed files with 63 additions and 24 deletions

View File

@ -1,6 +1,6 @@
use crate::{
grid::Grid,
util::wrap,
buffer::Buf,
};
use rand::{seq::SliceRandom, Rng};
@ -41,8 +41,9 @@ impl Agent {
}
}
// Tick an agent
#[inline]
pub fn tick(&mut self, grid: &Grid, sensor_distance: f32, sensor_angle: f32, rotation_angle: f32, step_distance: f32, width: usize, height: usize) {
pub fn tick(&mut self, buf: &Buf, sensor_distance: f32, sensor_angle: f32, rotation_angle: f32, step_distance: f32, width: usize, height: usize) {
let xc = self.x + cos(self.angle) * sensor_distance;
let yc = self.y + sin(self.angle) * sensor_distance;
@ -55,9 +56,9 @@ impl Agent {
let yr = self.y + sin(agent_add_sens) * sensor_distance;
// We sense from the buffer because this is where we previously combined data from all the grid.
let center = grid.get_buf(xc, yc);
let left = grid.get_buf(xl, yl);
let right = grid.get_buf(xr, yr);
let center = buf.get_buf(xc, yc);
let left = buf.get_buf(xl, yl);
let right = buf.get_buf(xr, yr);
// Rotate and move logic
let mut rng = rand::thread_rng();

39
src/buffer.rs Normal file
View File

@ -0,0 +1,39 @@
#[derive(Debug)]
pub struct Buf {
pub width: usize,
pub height: usize,
pub buf: Vec<f32>,
}
impl Clone for Buf {
fn clone(&self) -> Buf {
Buf {
width: self.width,
height: self.height,
buf: self.buf.clone(),
}
}
}
impl Buf {
pub fn new(width: usize, height: usize, buf: Vec<f32>) -> Self {
Buf {
width,
height,
buf,
}
}
// Truncate x and y and return a corresponding index into the data slice.
fn index(&self, x: f32, y: f32) -> usize {
// x/y can come in negative, hence we shift them by width/height.
let i = (x + self.width as f32) as usize & (self.width - 1);
let j = (y + self.height as f32) as usize & (self.height - 1);
j * self.width + i
}
// Get the buffer value at a given position. The implementation effectively treats data as periodic, hence any finite position will produce a value.
pub fn get_buf(&self, x: f32, y: f32) -> f32 {
self.buf[self.index(x, y)]
}
}

View File

@ -1,6 +1,7 @@
use crate::{
blur::Blur,
agent::Agent,
buffer::Buf,
};
use rand::{distributions::Uniform, Rng};
@ -89,7 +90,8 @@ pub struct Grid {
pub data: Vec<f32>,
// Scratch space for the blur operation.
pub buf: Vec<f32>,
// pub buf: Vec<f32>,
pub buf: Buf,
pub blur: Blur,
pub agents: Vec<Agent>
}
@ -122,7 +124,7 @@ impl Grid {
height,
data,
config: PopulationConfig::new(rng),
buf: vec![0.0; width * height],
buf: Buf::new(width, height, vec![0.0; width * height]),
blur: Blur::new(width),
agents,
}
@ -136,10 +138,12 @@ impl Grid {
j * self.width + i
}
/*
// Get the buffer value at a given position. The implementation effectively treats data as periodic, hence any finite position will produce a value.
pub fn get_buf(&self, x: f32, y: f32) -> f32 {
self.buf[self.index(x, y)]
self.buf.buf[self.index(x, y)]
}
*/
// Add a value to the grid data at a given position.
pub fn deposit(&mut self, x: f32, y: f32) {
@ -151,7 +155,7 @@ impl Grid {
pub fn diffuse(&mut self, radius: usize) {
self.blur.run(
&mut self.data,
&mut self.buf,
&mut self.buf.buf,
self.width,
self.height,
radius as f32,
@ -170,10 +174,10 @@ impl Grid {
..
} = self.config;
let self_imut = self.clone(); // Create immutable copy of self before ticking agents (this is a very bad solution, needs to be improved)
let buf = self.buf.clone();
self.agents.par_iter_mut().for_each(|agent| {
agent.tick(&self_imut,
agent.tick(&buf,
sensor_distance, sensor_angle,
rotation_angle, step_distance,
width, height);
@ -214,7 +218,7 @@ where
T: AsRef<[f32]> + Sync,
{
let datas: Vec<_> = grids.iter().map(|grid| &grid.data).collect();
let bufs: Vec<_> = grids.iter().map(|grid| &grid.buf).collect();
let bufs: Vec<_> = grids.iter().map(|grid| &grid.buf.buf).collect();
// We mutate grid buffers and read grid data. We use unsafe because we need shared/unique borrows on different fields of the same Grid struct.
bufs.iter().enumerate().for_each(|(i, buf)| unsafe {

View File

@ -22,7 +22,7 @@ impl Clone for ThinGridData {
impl ThinGridData {
// Convert Grid to ThinGridData
pub fn from_grid(in_grid: &Grid) -> Self {
pub fn new_from_grid(in_grid: &Grid) -> Self {
ThinGridData {
width: in_grid.width,
height: in_grid.height,
@ -31,9 +31,9 @@ impl ThinGridData {
}
#[allow(dead_code)]
pub fn from_grid_vec(in_grids: Vec<Grid>) -> Vec<Self> {
pub fn new_from_grid_vec(in_grids: Vec<Grid>) -> Vec<Self> {
return in_grids.iter().map(|grid|{
Self::from_grid(grid)
Self::new_from_grid(grid)
}).collect();
}

View File

@ -5,3 +5,4 @@ pub mod model;
mod palette;
mod util; // for math things
mod agent;
mod buffer;

View File

@ -165,14 +165,8 @@ impl Model {
);
}
fn strip_grid_data(grids: Vec<Grid>) -> Vec<ThinGridData> {
return grids.iter().map(|grid| {
ThinGridData::from_grid(grid)
}).collect();
}
fn save_image_data(&mut self) {
let grids = Self::strip_grid_data(self.grids.clone());
let grids = ThinGridData::new_from_grid_vec(self.grids.clone());
let img_data = ImgData::new(grids, self.palette, self.iteration);
self.img_data_vec.push(img_data);
if self.grids[0].width > 1024 && self.grids[0].height > 1024 && self.img_data_vec.len() > 100 {