📄 main.c
字号:
#ifdef SHADER_EMBEDDED
cz = 0.065f;
#else
cz = 0.035f;
#endif
#ifdef WATER_COLUMN
cz = 0.08f;
cx = 0.023f;
cy = 0.023f;
#endif
s2 = 0.001f;
s3 = 0.0001f;
mat4_set_identity(&rot);
mat4_set_identity(&rotview);
for (x = 0; x < CUBE_LEN_X; x++)
for (y = 0; y < CUBE_LEN_Y; y++)
for (z = 0; z < LEN_Z; z++)
{
i = x + y*CUBE_LEN_X + z*CUBE_LEN_X*CUBE_LEN_Y;
vec3_set(&pos[i], s*(x -CUBE_LEN_X/2)- cx + s2*RANDF(), s*(y - CUBE_LEN_Y/2) - cy + s2*RANDF(), 0.8*s*z - cz);
vec3_set(&vel[i], 0.0f, 0.0f, 0.0f);
}
cpu_sph_create(&cpu, N_PARTICLES, pos, vel, SMOOTHING_LENGTH, VISCOSITY, MASS, STIFF, SEARCH_RADIUS, N_LOOPS);
cpu.n_particles = N_PARTICLES;
printf("Finished initializing %d particles.\n", N_PARTICLES);
}
void init()
{
if (glewInit() != GLEW_OK)
{
fprintf(stderr, "Could not initialize GLEW\n");
exit(1);
}
#ifdef SHADER_EMBEDDED
if ((!GLEW_ARB_fragment_program) || (!GLEW_ARB_vertex_program))
{
gput_printf("GL_ARB_fragment_program, GL_ARB_vertex_program are not supported\n");
exit(1);
}
#endif
gput_printf("Initialized GLEW %s\n", glewGetString(GLEW_VERSION));
gput_init();
sph_render_create(&render);
n_steps = 0;
vec3_set(¢er, 0.0f, 0.0f, 0.0f);
init_particles();
init_obstacles();
// Set the configuration such as grid resolution for Marching Cubes
sph_render_set_config(&render, MC_GRID_LEN, 2, ISO_RADIUS);
vdata = vec3_alloc(N_PARTICLES);
glEnable(GL_LIGHT0);
glEnable(GL_NORMALIZE);
gput_mat_init(&vol_mat);
gput_mat_diffuse(&vol_mat, 0.3f, 0.3f, 1.0f, 0.4f);
gput_mat_specular(&vol_mat, 0.8f, 0.8f, 0.8f, 0.4f);
gput_mat_shininess(&vol_mat, 22);
// Initialize background pbuffer for refraction
init_background_pbuffer();
glGenTextures(1, &wood_tex);
glBindTexture(GL_TEXTURE_2D, wood_tex);
gput_load_texture(GL_TEXTURE_2D, "wood03.bmp");
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
//glClearColor(0.7, 0.7, 0.7, 0.0);
draw_mode = SPH_VOLUME;
animated = FALSE;
init_cubemap();
render_to_background_tex();
#ifdef SHADER_EMBEDDED
print_help();
#endif
}
void reshape(int w, int h)
{
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
void color_by_power(float p)
{
if (p < 1100.0f)
{
glColor3f(0.0f, 0.0f, p/1100.0f);
}
else if (p < 1400.0f)
{
glColor3f(0.0f, p/1400.0f, p/1100.0f);
}
else if (p < 1900.0f)
{
glColor3f(p / 2100.0f, p/1500.0f, 0.0f);
}
else glColor3f(p / 2100.0f, 0.1f, 0.0f);
}
void render_fluid()
{
int i;
cpu_sph_get_pos(&cpu, vdata);
glMatrixMode(GL_MODELVIEW);
glRotatef(-90.0f, 1.0f, 0.0f, 0.0f);
glBindTexture(GL_TEXTURE_2D, wood_tex);
draw_cuboid();
// draw_cube();
// Render fluid as points
if (draw_mode == SPH_POINT)
{
glDisable(GL_TEXTURE_2D);
glPointSize(5.0);
glDisable(GL_LIGHTING);
glBegin(GL_POINTS);
for (i = 0; i < cpu.n_particles; i++)
{
color_by_power(1.0f/cpu.density[i]);
glVertex3fv((GLfloat*)&vdata[i]);
}
glEnd();
}
// Render fluid as volume
else if (draw_mode == SPH_VOLUME)
{
matrix4 inv_rot;
glDisable(GL_LIGHTING);
glActiveTextureARB(GL_TEXTURE0_ARB);
gput_pbuffer_bind(&background_pbuf);
glEnable(GL_TEXTURE_2D);
glActiveTextureARB(GL_TEXTURE1_ARB);
glBindTexture(GL_TEXTURE_CUBE_MAP_ARB, cubemap_tex);
glActiveTextureARB(GL_TEXTURE0_ARB);
glMatrixMode(GL_TEXTURE);
glPushMatrix();
glLoadIdentity();
mat4_invert(&inv_rot, &rotview);
glMultMatrixf((GLfloat*)&inv_rot);
glRotatef(180.0f, 0.0f, 0.0f, 1.0f);
glRotatef(90.0f, 1.0f, 0.0f, 0.0f);
gput_cubemap_enable();
sph_render_draw_surface(&render, ISO_THRESHOLD);
gput_cubemap_disable();
glMatrixMode(GL_TEXTURE);
glPopMatrix();
}
else if (draw_mode == SPH_NODRAW)
{
}
// Render fluid as a set of spheres
else if (draw_mode == SPH_SPHERE)
{
glEnable(GL_CULL_FACE);
glDisable(GL_TEXTURE_2D);
gput_mat_bind(&vol_mat);
glEnable(GL_LIGHTING);
for (i = 0; i < cpu.n_particles; i++)
{
glPushMatrix();
glTranslatef(vdata[i].x, vdata[i].y, vdata[i].z);
switch (i % 4)
{
case 0: gput_mat_diffuse(&vol_mat, 1.0f, 0.1f, 0.1f, 1.0f); break;
case 1: gput_mat_diffuse(&vol_mat, 0.0f, 1.0f, 0.1f, 1.0f); break;
case 2: gput_mat_diffuse(&vol_mat, 0.0f, 0.1f, 1.0f, 1.0f); break;
case 3: gput_mat_diffuse(&vol_mat, 1.0f, 1.0f, 0.1f, 1.0f); break;
}
gput_mat_bind(&vol_mat);
glutSolidSphere(radius, 4, 4);
glPopMatrix();
}
}
}
void display(void)
{
DWORD t;
char buf[200];
// Render scene without fluid to background texture for refraction
render_to_background_tex();
glEnable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
set_projview(60);
gput_cubemap_skybox();
render_fluid();
glFinish();
// For getting frame rate
if (n_frames++ == 50)
{
t = GetTickCount();
sprintf(fps_str, "%.2f fps", n_frames*1000.0f/(t - start_time));
start_time = t;
n_frames = 0;
#ifndef SHADER_EMBEDDED
printf("%s\n", fps_str);
#endif
}
#ifdef SHADER_EMBEDDED
{
sprintf(buf, "%d particles; %s; %s; %s", N_PARTICLES,
(timestep < 0.005f) ? "SLOW" : "FAST",
animated ? "animated" : "stopped",
fps_str);
glutSetWindowTitle(buf);
}
#endif
glutSwapBuffers();
// Caputre each frame
if (saving)
{
sprintf(buf, "images\\frame_%.4d.bmp", image_frame++);
gput_write_screen(buf, win_width, win_height);
}
}
void idle(void)
{
char buf[200];
int i;
for (i = 0; i < N_STEPS; i++)
{
cpu_sph_elapse(&cpu, timestep);
}
n_steps++;
#ifndef SHADER_EMBEDDED
sprintf(buf, "%d particles; %6.3f sec. elapsed; timestep=%f", N_PARTICLES, N_LOOPS*N_STEPS*timestep*n_steps, timestep);
glutSetWindowTitle(buf);
#endif
// Construct surface by Marching Cubes algorithm
sph_render_create_implicit(&render,
MASS*315.0f/(64.0f*M_PI*pow(ISO_RADIUS, 9)),
&vdata[cpu.fluid_start],
cpu.n_fluidp,
&cpu.mat_inv_col,
&cpu);
glutPostRedisplay();
}
void key(unsigned char key, int x, int y)
{
switch(key)
{
case 'v':
sph_render_create_implicit(&render, MASS*315.0f/(64.0f*M_PI*pow(ISO_RADIUS, 9)), &vdata[cpu.fluid_start], cpu.n_fluidp, &cpu.mat_inv_col, &cpu);
glutPostRedisplay();
break;
case 'u':
cpu_sph_init_rigid_body(&cpu);
glutPostRedisplay();
break;
#ifndef SHADER_EMBEDDED
case 'g':
saving = !saving;
break;
case 'e':
cpu_sph_elapse(&cpu, timestep);
glutPostRedisplay();
break;
case 'b':
print_benchmark(&cpu, BENCHMARK_ITR, timestep);
glutPostRedisplay();
break;
#endif /* SHADER_EMBEDDED */
case 't':
if (timestep < 0.005f)
timestep = 0.005f;
else timestep = 0.004f;
break;
case ' ':
if (animated)
{
glutIdleFunc(NULL);
animated = FALSE;
}
else
{
animated = TRUE;
glutIdleFunc(idle);
}
start_time = GetTickCount();
n_frames = 0;
glutPostRedisplay();
break;
case 'm':
#ifdef SHADER_EMBEDDED
if (draw_mode == SPH_VOLUME)
draw_mode = SPH_SPHERE;
else draw_mode = SPH_VOLUME;
#else
draw_mode++;
if (draw_mode > SPH_SPHERE)
draw_mode = SPH_POINT;
#endif
glutPostRedisplay();
break;
case 'q':
exit(0);
}
}
void motion(int x, int y)
{
int dx;
int dy;
float tx;
float ty;
const float THRESHOLD = 0.006f;
if (left_down)
{
//printf("dragged\n");
dx = x - prev_x;
dy = y - prev_y;
if (shift_down)
{
dx = max(-6, min(6, dx));
dy = max(-6, min(6, dy));
mat4_set_identity(&rot);
if (abs(dx) > abs(dy))
mat4_set_rotate(&rot, dx, 0.0f, 0.0f, 1.0f);
else
mat4_set_rotate(&rot, -dy, 1.0f, 0.0f, 0.0f);
//assert(0);
transform_glass(&rot);
}
else
{
if (abs(dx) > abs(dy))
{
azimuth += dx;
// zenith += dx;
}
else
{
zenith -= dy;
}
mat4_set_rotate(&rotview, azimuth, 0.0f, 1.0f, 0.0f);
mat4_mull_rotate(&rotview, zenith, 1.0f, 0.0f, 0.0f);
glutPostRedisplay();
}
prev_x = x;
prev_y = y;
}
else if (right_down)
{
matrix4 m;
dx = x - prev_x;
dy = y - prev_y;
//gput_printf("dx=%d, dy=%d\n", dx, dy);
tx = dx*0.0009f;
ty = dy*0.0009f;
tx = glg_clamp(tx, -THRESHOLD, THRESHOLD);
ty = glg_clamp(ty, -THRESHOLD, THRESHOLD);
//mat4_set_translate(&m, -tx, ty, 0);
mat4_set_translate(&m, -tx, 0, -ty);
transform_glass(&m);
prev_x = x;
prev_y = y;
//glutPostRedisplay();
}
}
void mouse(int button, int state, int x, int y)
{
if (state == GLUT_DOWN)
{
prev_x = x;
prev_y = y;
if (button == GLUT_LEFT_BUTTON)
left_down = TRUE;
else if (button == GLUT_RIGHT_BUTTON)
right_down = TRUE;
}
else if (state == GLUT_UP)
{
if (button == GLUT_LEFT_BUTTON)
left_down = FALSE;
else if (button == GLUT_RIGHT_BUTTON)
right_down = FALSE;
}
shift_down = glutGetModifiers() & GLUT_ACTIVE_SHIFT;
}
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
glutInitWindowSize(win_width, win_height);
glutCreateWindow(argv[0]);
printf("GL_VERSION: %s\n", (char *) glGetString(GL_VERSION));
printf("GL_RENDERER: %s\n", (char *) glGetString(GL_RENDERER));
printf("GL_VENDOR: %s\n", (char *) glGetString(GL_VENDOR));
init();
glutMouseFunc(mouse);
glutMotionFunc(motion);
glutReshapeFunc(reshape);
glutDisplayFunc(display);
glutKeyboardFunc(key);
glutMainLoop();
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -