[arrayfire] 78/284: add collisions, split vectors into components for performance
Ghislain Vaillant
ghisvail-guest at moszumanska.debian.org
Sun Feb 7 18:59:21 UTC 2016
This is an automated email from the git hooks/post-receive script.
ghisvail-guest pushed a commit to branch debian/experimental
in repository arrayfire.
commit 5507717ce82024f42d1a8c9bba1514215afced5c
Author: syurkevi <stefan at arrayfire.com>
Date: Tue Dec 15 17:07:43 2015 -0500
add collisions, split vectors into components for performance
---
examples/graphics/gravity_sim.cpp | 106 +++++++++++++++++++++++---------------
1 file changed, 65 insertions(+), 41 deletions(-)
diff --git a/examples/graphics/gravity_sim.cpp b/examples/graphics/gravity_sim.cpp
index 77f662f..94d321b 100644
--- a/examples/graphics/gravity_sim.cpp
+++ b/examples/graphics/gravity_sim.cpp
@@ -15,53 +15,72 @@ using namespace af;
using namespace std;
static const int width = 512, height = 512;
+static const int pixels_per_unit = 20;
+af::array p_x;
+af::array p_y;
+af::array vels_x;
+af::array vels_y;
+af::array forces_x;
+af::array forces_y;
-void simulate(af::array &parts, af::array &vels, af::array &forces){
- parts += vels;
+void simulate(float dt){
+ p_x += vels_x * pixels_per_unit * dt;
+ p_y += vels_y * pixels_per_unit * dt;
//calculate distance to center
- float center_coors[2] = { width / 2, height / 2 };
- af::array col = tile(af::array(1, 2, center_coors), parts.dims(0));
- af::array diff = parts - col;
- af::array dist = sqrt( diff.col(0)*diff.col(0) + diff.col(1)*diff.col(1) );
+ af::array diff_x = p_x - width/2;
+ af::array diff_y = p_y - height/2;
+ af::array dist = sqrt( diff_x*diff_x + diff_y*diff_y );
- forces = -1 * diff;
- forces.col(0) /= dist; //normalize force vectors
- forces.col(1) /= dist; //normalize force vectors
+ //calculate normalised force vectors
+ forces_x = -1 * diff_x / dist;
+ forces_y = -1 * diff_y / dist;
+ //update force scaled to time and magnitude constant
+ forces_x *= pixels_per_unit * dt;
+ forces_y *= pixels_per_unit * dt;
+
+ //dampening
+ vels_x *= 1 - (0.005*dt);
+ vels_y *= 1 - (0.005*dt);
//update velocities from forces
- vels += forces;
+ vels_x += forces_x;
+ vels_y += forces_y;
}
-void collisions(af::array &parts, af::array &vels){
+void collisions(){
//clamp particles inside screen border
- parts.col(0) = min(width, max(0, parts.col(0)));
- parts.col(1) = min(height - 1, max(0, parts.col(1)));
+ af::array projected_px = min(width, max(0, p_x));
+ af::array projected_py = min(height - 1, max(0, p_y));
//calculate distance to center
- float center_coors[2] = { width / 2, height / 2 };
- af::array col = tile(af::array(1, 2, center_coors), parts.dims(0));
- af::array diff = parts - col;
- af::array dist = sqrt( diff.col(0)*diff.col(0) + diff.col(1)*diff.col(1) );
+ af::array diff_x = projected_px - width/2;
+ af::array diff_y = projected_py - height/2;
+ af::array dist = sqrt( diff_x*diff_x + diff_y*diff_y );
- /*
//collide with center sphere
- int radius = 50;
- af::array col_ids = dist(dist<radius);
- if(col_ids.dims(0) > 0) {
- //vels(col_ids, span) += -1 * parts(col_ids, span);
- vels(col_ids, span) = 0;
+ const int radius = 50;
+ const float elastic_constant = 0.91f;
+ if(sum<int>(dist<radius) > 0) {
+ vels_x(dist<radius) = -elastic_constant * vels_x(dist<radius);
+ vels_y(dist<radius) = -elastic_constant * vels_y(dist<radius);
+
+ //normalize diff vector
+ diff_x /= dist;
+ diff_y /= dist;
+ //place all particle colliding with sphere on surface
+ p_x(dist<radius) = width/2 + diff_x(dist<radius) * radius;
+ p_y(dist<radius) = height/2 + diff_y(dist<radius) * radius;
}
- */
-
}
+
int main(int argc, char *argv[])
{
try {
- const static int total_particles=200;
+ const static int total_particles = 1000;
static const int reset = 500;
af::info();
@@ -74,39 +93,44 @@ int main(int argc, char *argv[])
const af::array draw_kernel = gaussianKernel(3, 3);
// Generate a random starting state
- af::array particles = af::randu(total_particles,2);
- particles.col(0) *= width;
- particles.col(1) *= height;
+ p_x = af::randu(total_particles) * width;
+ p_y = af::randu(total_particles) * height;
+
+ vels_x = af::randn(total_particles);
+ vels_y = af::randn(total_particles);
- af::array velocities = af::randn(total_particles, 2);
- af::array forces = af::randn(total_particles, 2);
+ forces_x = af::randn(total_particles);
+ forces_y = af::randn(total_particles);
af::array image = af::constant(0, width, height);
af::array ids(total_particles, u32);
+ af::timer timer = af::timer::start();
while(!myWindow.close()) {
+ float dt = af::timer::stop(timer);
+ timer = af::timer::start();
- ids = (particles.col(0).as(u32) * height) + particles.col(1).as(u32);
+ ids = (p_x.as(u32) * height) + p_y.as(u32);
image(ids) += 255;
image = convolve2(image, draw_kernel);
myWindow.image(image);
- image(span, span) = 0;
+ image = af::constant(0, image.dims());
frame_count++;
// Generate a random starting state
if(frame_count % reset == 0) {
- particles = af::randu(total_particles,2);
- particles.col(0) *= width;
- particles.col(1) *= height;
+ p_x = af::randu(total_particles) * width;
+ p_y = af::randu(total_particles) * height;
- velocities = af::randn(total_particles, 2);
+ vels_x = af::randn(total_particles);
+ vels_y = af::randn(total_particles);
}
- //run force simulation and update particles
- simulate(particles, velocities, forces);
-
//check for collisions and adjust velocities accordingly
- collisions(particles, velocities);
+ collisions();
+
+ //run force simulation and update particles
+ simulate(dt);
}
} catch (af::exception& e) {
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-science/packages/arrayfire.git
More information about the debian-science-commits
mailing list