/* NOTES:
* - whistle hhgg music
- * - colliding particles merge
* - select objects and center camera on them
- * - tesselate only where necessary
*/
struct Particle {
/* gravitational strength */
#define GRAV_STR 16.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 Vec2 grid_to_pos(int gx, int gy);
static Particle *alloc_particle();
void free_particle(Particle *p);
+static bool pause;
+
static float grid[GRID_SIZE * GRID_SIZE];
static Particle *grid_part[GRID_SIZE * GRID_SIZE];
static Texture *grid_tex;
static Mesh *pmesh;
static unsigned int particle_sdr;
+static Vec2 cam_pos;
static float cam_theta;
static float cam_dist = 100.0f;
-static Vec2 *targ_pos;
+static Vec2 *targ_pos = &cam_pos;
static Mat4 view_matrix, proj_matrix;
+static bool wireframe;
+
// emitter placement data (filled by event handlers, completed in update)
static bool emit_place_pending;
static Vec2 emit_place_pos;
static void simstep()
{
+ if(pause) return;
+
// move existing particles
Particle *p = plist;
while(p) {
p->vel += grad * SIM_DT;
p->pos += p->vel * SIM_DT;
+ // if it moved outside of the simulation field, remove it
+ int gx = pos_to_grid_x_noclamp(p->pos.x);
+ int gy = pos_to_grid_y_noclamp(p->pos.y);
+ if(gx < 0 || gx >= GRID_SIZE || gy < 0 || gy >= GRID_SIZE) {
+ Particle *next = p->next;
+ grid_part[gidx] = 0;
+ remove_particle(p);
+ free_particle(p);
+ p = next;
+ continue;
+ }
+
// find the grid cell it's moving to
int gidx_next = pos_to_grid(p->pos.x, p->pos.y);
p->vis_height = 0.0f;//-grid[gidx_next] * field_scale;
glMatrixMode(GL_MODELVIEW);
glLoadMatrixf(view_matrix[0]);
- glPushAttrib(GL_ENABLE_BIT);
- glDisable(GL_CULL_FACE);
-
// draw gravitational field
- glEnable(GL_TEXTURE_2D);
+ if(wireframe) {
+ glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
+
+ float amb[] = {0.5, 0.5, 0.5, 1.0};
+ glLightModelfv(GL_LIGHT_MODEL_AMBIENT, amb);
+ } else {
+ float amb[] = {0.01, 0.01, 0.01, 1.0};
+ glLightModelfv(GL_LIGHT_MODEL_AMBIENT, amb);
+ }
+
bind_texture(gvis_tex, 0);
bind_texture(grid_tex, 1);
glPatchParameteri(GL_PATCH_VERTICES, 4);
draw_quadmesh(&field_mesh, GL_PATCHES);
+ if(wireframe) {
+ glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+ }
+
// draw particles
glUseProgram(particle_sdr);
glUseProgram(0);
- glPopAttrib();
-
assert(glGetError() == GL_NO_ERROR);
}
set_uniform_float(field_sdr, "field_scale", field_scale);
break;
+ case 'w':
+ wireframe = !wireframe;
+ break;
+
+ case ' ':
+ pause = !pause;
+ break;
+
default:
break;
}
prev_x = x;
prev_y = y;
+ if(game_bnstate(0)) {
+ float pan_speed = pow(cam_dist, 1.5) * 0.00035; // magic
+ Vec2 dir = rotate(Vec2(dx, dy) * pan_speed, deg_to_rad(cam_theta));
+ cam_pos.x -= dir.x;
+ cam_pos.y -= dir.y;
+ }
+
if(game_bnstate(2)) {
cam_theta += dx * 0.5;
}
if(cam_dist > MAX_CAM_DIST) cam_dist = MAX_CAM_DIST;
}
+static int pos_to_grid_x_noclamp(float x)
+{
+ return ((x / (float)FIELD_SIZE) + 0.5f) * (float)GRID_SIZE;
+}
+
+static int pos_to_grid_y_noclamp(float y)
+{
+ return ((y / (float)FIELD_SIZE) + 0.5f) * (float)GRID_SIZE;
+}
static int pos_to_grid(float x, float y)
{
- int gx = ((x / (float)FIELD_SIZE) + 0.5f) * (float)GRID_SIZE;
- int gy = ((y / (float)FIELD_SIZE) + 0.5f) * (float)GRID_SIZE;
+ int gx = pos_to_grid_x_noclamp(x);
+ int gy = pos_to_grid_y_noclamp(y);
if(gx < 0) gx = 0;
if(gx >= GRID_SIZE) gx = GRID_SIZE - 1;
int idx = i * vverts + j;
*iptr++ = idx;
- *iptr++ = idx + vverts;
- *iptr++ = idx + vverts + 1;
*iptr++ = idx + 1;
+ *iptr++ = idx + vverts + 1;
+ *iptr++ = idx + vverts;
}
v += dv;