[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