placing white holes, and changed to n-body gravitational pull instead of
authorJohn Tsiombikas <nuclear@member.fsf.org>
Thu, 16 Aug 2018 07:00:35 +0000 (10:00 +0300)
committerJohn Tsiombikas <nuclear@member.fsf.org>
Thu, 16 Aug 2018 07:00:35 +0000 (10:00 +0300)
local gradient following. I'm not sure about this last change. I did it
because it would be hard to disregard own influence from the field, but
the way I'm doing it now is extremely heavyweight and negates all the
benefits of the grid I've set up so far

src/game.cc
src/gamescr.cc
src/goatkit/screen.cc
src/goatkit/screen.h
src/main.cc
src/screen.cc
src/screen.h

index 230c619..9d69c69 100644 (file)
@@ -22,8 +22,6 @@ bool game_init()
        glEnable(GL_FRAMEBUFFER_SRGB);
        glEnable(GL_DEPTH_TEST);
        glEnable(GL_CULL_FACE);
        glEnable(GL_FRAMEBUFFER_SRGB);
        glEnable(GL_DEPTH_TEST);
        glEnable(GL_CULL_FACE);
-       glEnable(GL_LIGHTING);
-       glEnable(GL_LIGHT0);
 
        active_screen->start();
        return true;
 
        active_screen->start();
        return true;
@@ -43,7 +41,7 @@ void game_draw()
 
 void game_reshape(int x, int y)
 {
 
 void game_reshape(int x, int y)
 {
-       active_screen->draw();
+       active_screen->reshape(x, y);
 }
 
 void game_keyboard(int key, bool pressed)
 }
 
 void game_keyboard(int key, bool pressed)
index 3eec738..4bac184 100644 (file)
@@ -8,10 +8,12 @@
 #include "sdr.h"
 #include "mesh.h"
 #include "meshgen.h"
 #include "sdr.h"
 #include "mesh.h"
 #include "meshgen.h"
+#include "goatkit/goatkit.h"
 
 /* NOTES:
  * - whistle hhgg music
  * - select objects and center camera on them
 
 /* NOTES:
  * - whistle hhgg music
  * - select objects and center camera on them
+ * - we need to rely on actual collisions instead of grid occupancy
  */
 
 struct Particle {
  */
 
 struct Particle {
@@ -69,6 +71,9 @@ struct QuadMesh {
 /* gravitational strength */
 #define GRAV_STR       16.0f
 
 /* gravitational strength */
 #define GRAV_STR       16.0f
 
+#define INIT_MASS_BUDGET       600.0f
+#define EM_MASS_DEFAULT                100.0f
+
 static int pos_to_grid_x_noclamp(float x);
 static int pos_to_grid_y_noclamp(float y);
 static int pos_to_grid(float x, float y);
 static int pos_to_grid_x_noclamp(float x);
 static int pos_to_grid_y_noclamp(float y);
 static int pos_to_grid(float x, float y);
@@ -116,11 +121,25 @@ static Vec2 *targ_pos = &cam_pos;
 static Mat4 view_matrix, proj_matrix;
 
 static bool wireframe;
 static Mat4 view_matrix, proj_matrix;
 
 static bool wireframe;
+static int mouse_x, mouse_y;
 
 // emitter placement data (filled by event handlers, completed in update)
 static bool emit_place_pending;
 static Vec2 emit_place_pos;
 
 
 // emitter placement data (filled by event handlers, completed in update)
 static bool emit_place_pending;
 static Vec2 emit_place_pos;
 
+static bool placing_emitter;
+
+static float mass_left;
+
+// UI
+static void ui_handler(goatkit::Widget *w, const goatkit::Event &ev, void *cls);
+static int ui_virt_width = 800;
+static int ui_virt_height = 600;
+static goatkit::Screen *ui;
+static goatkit::Button *bn_emitter;
+static goatkit::Slider *slider_mass;
+static bool mouse_over_ui;
+
 
 bool GameScreen::init()
 {
 
 bool GameScreen::init()
 {
@@ -161,9 +180,28 @@ bool GameScreen::init()
                return false;
        }
 
                return false;
        }
 
-       // XXX DBG
-       emit_place_pos = Vec2(0, 0);
-       emit_place_pending = true;
+       mass_left = INIT_MASS_BUDGET;
+
+       ui = new goatkit::Screen;
+       ui->hide();
+
+       bn_emitter = new goatkit::Button;
+       bn_emitter->set_position(5, 5);
+       bn_emitter->set_size(250, 30);
+       bn_emitter->set_text("new white hole");
+       bn_emitter->set_callback(goatkit::EV_CLICK, ui_handler);
+       ui->add_widget(bn_emitter);
+
+       slider_mass = new goatkit::Slider;
+       slider_mass->set_position(300, 5);
+       slider_mass->set_size(400, 30);
+       slider_mass->set_continuous_change(false);
+       slider_mass->set_range(0, mass_left);
+       slider_mass->set_value(EM_MASS_DEFAULT);
+       slider_mass->set_callback(goatkit::EV_CHANGE, ui_handler);
+       ui->add_widget(slider_mass);
+
+       ui->set_visibility_transition(300);
 
        assert(glGetError() == GL_NO_ERROR);
        return true;
 
        assert(glGetError() == GL_NO_ERROR);
        return true;
@@ -176,20 +214,54 @@ void GameScreen::destroy()
        delete grid_tex;
        destroy_quadmesh(&field_mesh);
        delete pmesh;
        delete grid_tex;
        destroy_quadmesh(&field_mesh);
        delete pmesh;
+
+       delete bn_emitter;
+}
+
+void GameScreen::start()
+{
+       ui->show();
+       slider_mass->hide();
+}
+
+void GameScreen::stop()
+{
 }
 
 static void simstep()
 {
        if(pause) return;
 
 }
 
 static void simstep()
 {
        if(pause) return;
 
-       // move existing particles
+       // distribute forces
        Particle *p = plist;
        while(p) {
        Particle *p = plist;
        while(p) {
+               int num_emitters = emitters.size();
+               for(int i=0; i<num_emitters; i++) {
+                       Emitter *em = emitters[i];
+                       Vec2 dir = p->pos - em->pos;
+                       p->vel += dir * em->mass * GRAV_STR * 0.01 / dot(dir, dir) * SIM_DT;
+               }
+
+               Particle *q = plist;
+               while(q) {
+                       if(p != q) {
+                               Vec2 dir = q->pos - p->pos;
+                               float accel = GRAV_STR * q->mass / dot(dir, dir);
+                               p->vel += dir * accel * SIM_DT;
+                       }
+                       q = q->next;
+               }
+               p = p->next;
+       }
+
+       // move existing particles
+       p = plist;
+       while(p) {
                // calculate the field gradient at the particle position
                int gidx = pos_to_grid(p->pos.x, p->pos.y);
                // calculate the field gradient at the particle position
                int gidx = pos_to_grid(p->pos.x, p->pos.y);
-               Vec2 grad = calc_field_grad(gidx) * GRAV_STR;
+               //Vec2 grad = calc_field_grad(gidx) * GRAV_STR;
 
 
-               p->vel += grad * SIM_DT;
+               //p->vel += grad * SIM_DT;
                p->pos += p->vel * SIM_DT;
 
                // if it moved outside of the simulation field, remove it
                p->pos += p->vel * SIM_DT;
 
                // if it moved outside of the simulation field, remove it
@@ -307,11 +379,31 @@ static void simstep()
 
 static void update()
 {
 
 static void update()
 {
+       if(placing_emitter) {
+               float x = (float)mouse_x / (float)win_width;
+               float y = 1.0f - (float)mouse_y / (float)win_height;
+               Ray pick_ray = mouse_pick_ray(x, y, view_matrix, proj_matrix);
+
+               float ndotdir = pick_ray.dir.y;
+               if(fabs(ndotdir) > 1e-6f) {
+                       float ndotpdir = -pick_ray.origin.y;
+                       float t = ndotpdir / ndotdir;
+
+                       x = pick_ray.origin.x + pick_ray.dir.x * t;
+                       y = pick_ray.origin.z + pick_ray.dir.z * t;
+
+                       if(x >= -FIELD_SIZE / 2 && x < FIELD_SIZE / 2 &&
+                                       y >= -FIELD_SIZE / 2 && y < FIELD_SIZE / 2) {
+                               emit_place_pos = Vec2(x, y);
+                       }
+               }
+       }
+
        if(emit_place_pending) {
                emit_place_pending = false;
                Emitter *em = new Emitter;
                em->pos = emit_place_pos;
        if(emit_place_pending) {
                emit_place_pending = false;
                Emitter *em = new Emitter;
                em->pos = emit_place_pos;
-               em->mass = 100;
+               em->mass = slider_mass->get_value();
                em->rate = 10;
                em->chunk = 0.001 * em->mass;
                em->angle = -1;
                em->rate = 10;
                em->chunk = 0.001 * em->mass;
                em->angle = -1;
@@ -319,6 +411,9 @@ static void update()
                em->spawn_pending = 0;
                emitters.push_back(em);
 
                em->spawn_pending = 0;
                emitters.push_back(em);
 
+               mass_left -= em->mass;
+               if(mass_left < 0.0f) mass_left = 0.0f;
+
                Rect cbox;
                calc_contrib_bounds(em->pos, em->mass, &cbox);
                printf("bounds: %d,%d %dx%d\n", cbox.x, cbox.y, cbox.width, cbox.height);
                Rect cbox;
                calc_contrib_bounds(em->pos, em->mass, &cbox);
                printf("bounds: %d,%d %dx%d\n", cbox.x, cbox.y, cbox.width, cbox.height);
@@ -403,11 +498,47 @@ void GameScreen::draw()
 
        glUseProgram(0);
 
 
        glUseProgram(0);
 
+       // draw emitter placement marker if we are in placement mode
+       if(placing_emitter && !mouse_over_ui) {
+               glPushMatrix();
+               glTranslatef(emit_place_pos.x, 0, emit_place_pos.y);
+
+               glBegin(GL_LINES);
+               glColor3f(0, 1, 0);
+               glVertex3f(0, -1000, 0);
+               glVertex3f(0, 1000, 0);
+               glEnd();
+
+               float s = MASS_TO_RADIUS(slider_mass->get_value());
+               if(s < 0.1) s = 0.1;
+               glScalef(s, s, s);
+
+               glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
+               pmesh->draw();
+               glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+
+               glPopMatrix();
+       }
+
+       // draw the UI
+       glMatrixMode(GL_PROJECTION);
+       glLoadIdentity();
+       glOrtho(0, ui_virt_width, ui_virt_height, 0, -1, 1);
+
+       glMatrixMode(GL_MODELVIEW);
+       glLoadIdentity();
+
+       ui->draw();
+
+
        assert(glGetError() == GL_NO_ERROR);
 }
 
 void GameScreen::reshape(int x, int y)
 {
        assert(glGetError() == GL_NO_ERROR);
 }
 
 void GameScreen::reshape(int x, int y)
 {
+       ui_virt_width = x;
+       ui_virt_height = y;
+       ui->set_size(ui_virt_width, ui_virt_height);
 }
 
 
 }
 
 
@@ -467,20 +598,38 @@ void GameScreen::keyboard(int key, bool pressed)
        }
 }
 
        }
 }
 
-static int prev_x, prev_y;
+#define UI_HEIGHT      50
 
 void GameScreen::mbutton(int bn, bool pressed, int x, int y)
 {
 
 void GameScreen::mbutton(int bn, bool pressed, int x, int y)
 {
-       prev_x = x;
-       prev_y = y;
+       mouse_x = x;
+       mouse_y = y;
+
+       mouse_over_ui = y < UI_HEIGHT;
+
+       ui->sysev_mouse_button(bn, pressed, x * ui_virt_width / win_width,
+                       y * ui_virt_height / win_height);
+
+       if(placing_emitter && bn == 0 && pressed && !mouse_over_ui) {
+               emit_place_pending = true;
+               placing_emitter = false;
+               slider_mass->hide();
+       }
 }
 
 void GameScreen::mmotion(int x, int y)
 {
 }
 
 void GameScreen::mmotion(int x, int y)
 {
-       int dx = x - prev_x;
-       int dy = y - prev_y;
-       prev_x = x;
-       prev_y = y;
+       int dx = x - mouse_x;
+       int dy = y - mouse_y;
+       mouse_x = x;
+       mouse_y = y;
+
+       mouse_over_ui = y < UI_HEIGHT;
+
+       ui->sysev_mouse_motion(x * ui_virt_width / win_width, y * ui_virt_height / win_height);
+       if(ui->get_mouse_grab()) {
+               return;
+       }
 
        if(game_bnstate(0)) {
                float pan_speed = pow(cam_dist, 1.5) * 0.00035; // magic
 
        if(game_bnstate(0)) {
                float pan_speed = pow(cam_dist, 1.5) * 0.00035; // magic
@@ -501,6 +650,28 @@ void GameScreen::mwheel(int dir, int x, int y)
        if(cam_dist > MAX_CAM_DIST) cam_dist = MAX_CAM_DIST;
 }
 
        if(cam_dist > MAX_CAM_DIST) cam_dist = MAX_CAM_DIST;
 }
 
+static void ui_handler(goatkit::Widget *w, const goatkit::Event &ev, void *cls)
+{
+       if(w == bn_emitter) {
+               if(placing_emitter) {
+                       placing_emitter = false;
+                       slider_mass->hide();
+               } else {
+                       if(mass_left > 0.0f) {
+                               placing_emitter = true;
+                               slider_mass->set_range(0, mass_left);
+                               slider_mass->set_value(mass_left >= EM_MASS_DEFAULT ? EM_MASS_DEFAULT : mass_left);
+                               slider_mass->show();
+                       }
+               }
+               return;
+       }
+
+       if(w == slider_mass) {
+               printf("foo: %f\n", slider_mass->get_value());
+       }
+}
+
 static int pos_to_grid_x_noclamp(float x)
 {
        return ((x / (float)FIELD_SIZE) + 0.5f) * (float)GRID_SIZE;
 static int pos_to_grid_x_noclamp(float x)
 {
        return ((x / (float)FIELD_SIZE) + 0.5f) * (float)GRID_SIZE;
index 65e734d..2413bcc 100644 (file)
@@ -186,6 +186,11 @@ bool Screen::grab_mouse(Widget *w)
        return false;
 }
 
        return false;
 }
 
+Widget *Screen::get_mouse_grab() const
+{
+       return scr->mgrab;
+}
+
 void Screen::draw() const
 {
        for(size_t i=0; i<scr->widgets.size(); i++) {
 void Screen::draw() const
 {
        for(size_t i=0; i<scr->widgets.size(); i++) {
index d587bae..5483cb8 100644 (file)
@@ -54,6 +54,7 @@ public:
        long get_visibility_transition() const;
 
        bool grab_mouse(Widget *w);
        long get_visibility_transition() const;
 
        bool grab_mouse(Widget *w);
+       Widget *get_mouse_grab() const;
 
        void draw() const;
 
 
        void draw() const;
 
index 4c707d6..fca4fd9 100644 (file)
@@ -99,6 +99,7 @@ void draw_text(float x, float y, float r, float g, float b, const char *fmt, ...
        glLoadIdentity();
        glOrtho(0, win_width, 0, win_height, -1, 1);
 
        glLoadIdentity();
        glOrtho(0, win_width, 0, win_height, -1, 1);
 
+       glPushAttrib(GL_ENABLE_BIT);
        glDisable(GL_LIGHTING);
 
        glRasterPos2f(1, 1);
        glDisable(GL_LIGHTING);
 
        glRasterPos2f(1, 1);
@@ -107,7 +108,7 @@ void draw_text(float x, float y, float r, float g, float b, const char *fmt, ...
                glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18, *text++);
        }
 
                glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18, *text++);
        }
 
-       glEnable(GL_LIGHTING);
+       glPopAttrib();
 
        glPopMatrix();
        glMatrixMode(GL_MODELVIEW);
 
        glPopMatrix();
        glMatrixMode(GL_MODELVIEW);
index 1870796..a0aea2f 100644 (file)
@@ -1,4 +1,5 @@
 #include "screen.h"
 #include "screen.h"
+#include "game.h"
 
 ScreenBase *active_screen;
 MenuScreen *scr_menu;
 
 ScreenBase *active_screen;
 MenuScreen *scr_menu;
@@ -35,6 +36,7 @@ void push_screen(ScreenBase *scr)
        scr->next = active_screen;
        active_screen = scr;
 
        scr->next = active_screen;
        active_screen = scr;
 
+       scr->reshape(win_width, win_height);
        scr->start();
 }
 
        scr->start();
 }
 
index 6978b77..d7cc9da 100644 (file)
@@ -54,6 +54,9 @@ public:
        bool init();
        void destroy();
 
        bool init();
        void destroy();
 
+       void start();
+       void stop();
+
        void draw();
        void reshape(int x, int y);
 
        void draw();
        void reshape(int x, int y);