uniform int tess_level;
+in float dist[gl_MaxPatchVertices];
+
void main()
{
gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;
gl_out[gl_InvocationID].gl_TexCoord[0] = gl_in[gl_InvocationID].gl_TexCoord[0];
gl_out[gl_InvocationID].gl_TexCoord[1] = gl_in[gl_InvocationID].gl_TexCoord[1];
- gl_TessLevelInner[0] = tess_level;
- gl_TessLevelInner[1] = tess_level;
+ const float min_tess_dist = 800.0;
+ float t = clamp(1.0 - dist[0] / min_tess_dist, 0.0, 1.0);
+ int tess = int(t * float(tess_level - 1.0)) + 1;
+
+ gl_TessLevelInner[0] = tess;
+ gl_TessLevelInner[1] = tess;
- gl_TessLevelOuter[0] = tess_level;
- gl_TessLevelOuter[1] = tess_level;
- gl_TessLevelOuter[2] = tess_level;
- gl_TessLevelOuter[3] = tess_level;
+ gl_TessLevelOuter[0] = tess;
+ gl_TessLevelOuter[1] = tess;
+ gl_TessLevelOuter[2] = tess;
+ gl_TessLevelOuter[3] = tess;
}
/* 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 Vec2 *targ_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;
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;
+
default:
break;
}
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;