⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 main.c

📁 游戏编程精粹6第中关于粒子的实时流体仿真系统,对入门的游戏开发者很有帮助.
💻 C
📖 第 1 页 / 共 2 页
字号:
#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(&center, 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 + -