poisson distribution of cows
authorEleni Maria Stea <estea@igalia.com>
Wed, 23 Aug 2017 21:27:31 +0000 (00:27 +0300)
committerEleni Maria Stea <estea@igalia.com>
Wed, 23 Aug 2017 21:27:31 +0000 (00:27 +0300)
external/libimago
src/main.cc
src/morph_renderer.cc
src/morph_renderer.h

index 843ac48..2228b92 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 843ac48c7cd58166bb9dc0d49097c1b0ae7e2029
+Subproject commit 2228b925b87ee5458bd59611c11fc98c051446cc
index 1734fc6..cbe6ed6 100644 (file)
@@ -27,6 +27,7 @@
 static bool init(Gfx_API api);
 static void cleanup();
 static void display();
+static bool gen_poisson(std::vector<Vec2> &points, float min_dist, float radius);
 
 /* glfw callbacks */
 
@@ -60,11 +61,13 @@ static OrbitCamera *camera;
 
 static float fog_density;
 
+static int num_cows = 400;
+static float cow_gap = 4;
 static Scene *cow_scene;
-static Object *cow_object;
 static MorphRenderer *cow_rend;
 
 static Terrain terrain;
+static TerrainParams p;
 static Texture *skybox_tex;
 static Texture *terrain_tex;
 static Material terrain_mat;
@@ -127,23 +130,6 @@ static bool init(Gfx_API api)
 
        camera = new OrbitCamera;
 
-       cow_scene = new Scene;
-       if(!cow_scene->load("data/spot/spot.obj")) {
-               fprintf(stderr, "Failed to load scene: spot.obj.\n");
-               return false;
-       }
-
-       cow_rend = new MorphRenderer;
-       cow_rend->camera = camera;
-       cow_rend->scene = cow_scene;
-
-       if(!cow_rend->create()) {
-               fprintf(stderr, "Failed to create renderer for cows.\n");
-               return false;
-       }
-
-       cow_object = cow_scene->objects[0];
-
        terrain_tex = gfx_create_texture();
        if(!terrain_tex->load("data/grass.jpeg")) {
                fprintf(stderr, "Failed to load ground texture.\n");
@@ -156,7 +142,6 @@ static bool init(Gfx_API api)
                return false;
        }
 
-       TerrainParams p;
        p.xsz = 200;
        p.ysz = 200;
        p.max_height = 30;
@@ -185,14 +170,55 @@ static bool init(Gfx_API api)
 
        skybox_tex = gfx_create_texture();
        skybox_tex->load("data/cubemap/cubemap.hdr");
-       // skybox_tex->load("data/cubemap/irradiance.hdr");
+       //irr_tex->load("data/cubemap/irradiance.hdr");
        terrain_rend->set_sky_tex(skybox_tex);
 
        if(!terrain_rend->create()) {
                fprintf(stderr, "terrain fail\n");
                return false;
        }
+       terrain_rend->fog_density = fog_density;
+
+       cow_scene = new Scene;
+       if(!cow_scene->load("data/spot/spot.obj")) {
+               fprintf(stderr, "Failed to load scene: spot.obj.\n");
+               return false;
+       }
+
+       cow_rend = new MorphRenderer;
+       cow_rend->camera = camera;
+       cow_rend->scene = cow_scene;
+       cow_rend->fog_density = fog_density;
+
+       if(!cow_rend->create()) {
+               fprintf(stderr, "Failed to create renderer for cows.\n");
+               return false;
+       }
+
+       /* create cow objects */
+       Object *cow0 = cow_scene->objects[0];
+       cow0->transform.rotation_y(M_PI);
+       cow_scene->objects.clear();
+
+       float disk_radius = std::min(p.xsz, p.ysz) / 2.0 * 0.65;
+       std::vector<Vec2> cow_pos;
 
+       for(int i=0; i<num_cows; i++) {
+               Object *cow = new Object;
+               *cow = *cow0;
+
+               if (!gen_poisson(cow_pos, cow_gap, disk_radius))
+                       goto cowgen_end;
+               Vec2 pos = cow_pos.back();
+               float y = terrain.get_height(Vec3(pos.x, 1, pos.y));
+
+               cow->transform.translate(pos.x, y, pos.y);
+               cow_scene->objects.push_back(cow);
+       }
+
+cowgen_end:
+       printf("generated: %d cows from %d\n", (int)cow_pos.size(), num_cows);
+       delete cow0;
        return true;
 }
 
@@ -204,7 +230,6 @@ static void cleanup()
        delete cow_scene;
        delete cow_rend;
 
-//TODO
        delete terrain_tex;
        delete terrain_rend;
        gfx_cleanup();
@@ -228,13 +253,13 @@ static void clbk_key(GLFWwindow *win, int key, int scancode, int action, int mod
                        move_camera = !move_camera;
                        break;
 
-               case 'F':
-                       fog_density = fog_density < 1 - 0.0009 ? fog_density + 0.0001 : 1;
-                       break;
+               // case 'F':
+               //      fog_density = fog_density < 1 - 0.0009 ? fog_density + 0.0001 : 1;
+               //      break;
 
-               case 'U':
-                       fog_density = fog_density > 0.0001 ? fog_density - 0.0001 : 0;
-                       break;
+               // case 'U':
+               //      fog_density = fog_density > 0.0001 ? fog_density - 0.0001 : 0;
+               //      break;
 
                default:
                        break;
@@ -325,12 +350,33 @@ static void display()
 
        gfx_clear(0.1, 0.1, 0.1);
 
-       printf("fog_density: %f\n", fog_density);
-       terrain_rend->fog_density = fog_density;
        terrain_rend->draw();
-
-       cow_pos.y = terrain.get_height(cow_pos);
-       cow_object->transform.translation(cow_pos);
-       cow_rend->fog_density = fog_density;
        cow_rend->draw();
+}
+
+static bool gen_poisson(std::vector<Vec2> &points, float min_dist, float radius)
+{
+       /* poisson radius */
+       for (int i = 0; i < 1000; i++)
+       {
+               float angle = (float)rand() / (float)RAND_MAX * 2 * M_PI;
+               float r = sqrt((float)rand() / (float)RAND_MAX) * radius;
+
+               Vec2 p;
+               p.x = cos(angle) * r;
+               p.y = sin(angle) * r;
+
+               bool valid = true; 
+               for(size_t j=0; j<points.size(); j++) {
+                       if(length_sq(points[j] - p) < min_dist * min_dist) {
+                               valid = false;
+                               break;
+                       }
+               }
+               if(valid) {
+                       points.push_back(p);
+                       return true;
+               }
+       }
+       return false;
 }
\ No newline at end of file
index 601c335..ce6f1b0 100644 (file)
@@ -54,16 +54,9 @@ void MorphRenderer::draw() const
        sprog->use();
 
        for(size_t i=0; i<scene->objects.size(); i++) {
+               float t = (sin(time_sec + 7.3 * noise(i * M_PI)) + 1) * 0.5;
+               if (t_loc != -1)
+                       sprog->set_uniformf(t_loc, t);
                draw_object(scene->objects[i]);
        }
-}
-
-void MorphRenderer::draw_object(Object *object) const
-{
-       float t =  (sin(time_sec) + 1) * 0.5;
-
-       if(t_loc != -1)
-               sprog->set_uniformf(t_loc, t);
-
-       Renderer::draw_object(object);
 }
\ No newline at end of file
index aebb922..c939b4b 100644 (file)
@@ -7,8 +7,6 @@ class MorphRenderer : public Renderer {
 protected:
        int t_loc;
 
-       virtual void draw_object(Object *object) const override;
-
 public:
        MorphRenderer();
        virtual ~MorphRenderer();