2 FLUIDS v.1 - SPH Fluid Simulator for CPU and GPU
3 Copyright (C) 2009. Rama Hoetzlein, http://www.rchoetzlein.com
6 This software is provided 'as-is', without any express or implied
7 warranty. In no event will the authors be held liable for any damages
8 arising from the use of this software.
10 Permission is granted to anyone to use this software for any purpose,
11 including commercial applications, and to alter it and redistribute it
12 freely, subject to the following restrictions:
14 1. The origin of this software must not be misrepresented; you must not
15 claim that you wrote the original software. If you use this software
16 in a product, an acknowledgment in the product documentation would be
17 appreciated but is not required.
18 2. Altered source versions must be plainly marked as such, and must not be
19 misrepresented as being the original software.
20 3. This notice may not be removed or altered from any source distribution.
29 #include "common_defs.h"
32 #include "fluid_system_host.cuh"
34 #include "fluid_system.h"
35 #include "gl_helper.h"
37 #ifdef _MSC_VER // Windows
50 float window_width = 1024;
51 float window_height = 768;
53 Vector3DF cam_from, cam_angs, cam_to; // Camera stuff
54 Vector3DF obj_from, obj_angs, obj_dang;
55 Vector3DF light[2], light_to[2]; // Light stuff
56 float light_fov, cam_fov;
58 int psys_rate = 0; // Particle stuff
63 bool bHelp = false; // Toggles
66 bool bPntDraw = false;
70 float view_matrix[16]; // View matrix (V)
71 float model_matrix[16]; // Model matrix (M)
72 float proj_matrix[16]; // Projective matrix
75 #define DRAG_OFF 0 // mouse states
78 int last_x = -1, last_y = -1; // mouse vars
87 // Different things we can move around
93 #define MODE_LIGHTPOS 5
97 GLuint screenBufferObject;
98 GLuint depthBufferObject;
101 void drawScene ( float* viewmat, bool bShade )
103 if ( iShade <= 1 && bShade ) {
104 glEnable ( GL_LIGHT0 );
107 GLfloat shininess = 60.0;
109 diff[0] = 0.8f; diff[1] = 0.8f; diff[2] = 0.8f; diff[3] = 1.0f;
110 spec[0] = 1.0f; spec[1] = 1.0f; spec[2] = 1.0f; spec[3] = 1.0f;
111 glMaterialfv (GL_FRONT_AND_BACK, GL_DIFFUSE, &diff[0]);
112 glMaterialfv (GL_FRONT_AND_BACK, GL_SPECULAR, &spec[0]);
113 glMaterialfv (GL_FRONT_AND_BACK, GL_SHININESS, &shininess);
114 glColorMaterial ( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE );
116 glColor3f ( 1, 1, 1 );
117 glLoadMatrixf ( viewmat );
118 glBegin ( GL_QUADS );
119 glNormal3f ( 0, 0, 1 );
120 glVertex3f ( -1000, -1000, 0.0 );
121 glVertex3f ( 1000, -1000, 0.0 );
122 glVertex3f ( 1000, 1000, 0.0 );
123 glVertex3f ( -1000, 1000, 0.0 );
125 glBegin ( GL_LINES );
126 for (float n=-100; n <= 100; n += 20.0 ) {
127 glVertex3f ( -100, n, 0.1 );
128 glVertex3f ( 100, n, 0.1 );
129 glVertex3f ( n, -100, 0.1 );
130 glVertex3f ( n, 100, 0.1 );
134 psys.Draw ( &viewmat[0], 0.8 ); // Draw particles
137 glDisable ( GL_LIGHTING );
138 psys.Draw ( &viewmat[0], 0.55 ); // Draw particles
145 mint::Time start, stop;
150 glDisable ( GL_LIGHTING );
151 glDisable ( GL_DEPTH_TEST );
153 glMatrixMode ( GL_PROJECTION );
155 glScalef ( 2.0/window_width, -2.0/window_height, 1 ); // Setup view (0,0) to (800,600)
156 glTranslatef ( -window_width/2.0, -window_height/2, 0.0);
158 glMatrixMode ( GL_MODELVIEW );
161 glGetFloatv ( GL_MODELVIEW_MATRIX, view_matrix );
165 glColor4f ( 1.0, 1.0, 1.0, 1.0 );
167 strcpy ( disp, "Press H for help." ); drawText ( 10, 20, disp );
171 if ( psys.GetToggle ( USE_CUDA ) ) {
172 sprintf ( disp, "Kernel: USING CUDA (GPU)" ); drawText ( 20, 40, disp );
174 sprintf ( disp, "Kernel: USING CPU" ); drawText ( 20, 40, disp );
177 sprintf ( disp, "KEYBOARD" ); drawText ( 20, 60, disp );
178 sprintf ( disp, "[ ] Next/Prev Demo" ); drawText ( 20, 70, disp );
179 sprintf ( disp, "N M Adjust Max Particles" ); drawText ( 20, 80, disp );
180 sprintf ( disp, "space Pause" ); drawText ( 20, 90, disp );
181 sprintf ( disp, "S Shading mode" ); drawText ( 20, 100, disp );
182 sprintf ( disp, "G Toggle CUDA vs CPU" ); drawText ( 20, 110, disp );
183 sprintf ( disp, "< > Change emitter rate" ); drawText ( 20, 120, disp );
184 sprintf ( disp, "C Move camera /w mouse" ); drawText ( 20, 130, disp );
185 sprintf ( disp, "I Move emitter /w mouse" ); drawText ( 20, 140, disp );
186 sprintf ( disp, "O Change emitter angle" ); drawText ( 20, 150, disp );
187 sprintf ( disp, "L Move light /w mouse" ); drawText ( 20, 160, disp );
188 sprintf ( disp, "X Draw velocity/pressure/color" ); drawText ( 20, 170, disp );
190 Vector3DF vol = psys.GetVec(SPH_VOLMAX);
191 vol -= psys.GetVec(SPH_VOLMIN);
192 sprintf ( disp, "Volume Size: %3.5f %3.2f %3.2f", vol.x, vol.y, vol.z ); drawText ( 20, 190, disp );
193 sprintf ( disp, "Time Step (dt): %3.5f", psys.GetDT () ); drawText ( 20, 200, disp );
194 sprintf ( disp, "Num Particles: %d", psys.NumPoints() ); drawText ( 20, 210, disp );
195 sprintf ( disp, "Simulation Scale: %3.5f", psys.GetParam(SPH_SIMSIZE) ); drawText ( 20, 220, disp );
196 sprintf ( disp, "Simulation Size (m): %3.5f", psys.GetParam(SPH_SIMSCALE) ); drawText ( 20, 230, disp );
197 sprintf ( disp, "Smooth Radius (m): %3.3f", psys.GetParam(SPH_SMOOTHRADIUS) ); drawText ( 20, 240, disp );
198 sprintf ( disp, "Particle Radius (m): %3.3f", psys.GetParam(SPH_PRADIUS) ); drawText ( 20, 250, disp );
199 sprintf ( disp, "Particle Mass (kg): %0.8f", psys.GetParam(SPH_PMASS) ); drawText ( 20, 260, disp );
200 sprintf ( disp, "Rest Density (kg/m^3): %3.3f", psys.GetParam(SPH_RESTDENSITY) ); drawText ( 20, 270, disp );
201 sprintf ( disp, "Viscosity: %3.3f", psys.GetParam(SPH_VISC) ); drawText ( 20, 280, disp );
202 sprintf ( disp, "Internal Stiffness: %3.3f", psys.GetParam(SPH_INTSTIFF) ); drawText ( 20, 290, disp );
203 sprintf ( disp, "Boundary Stiffness: %6.0f", psys.GetParam(SPH_EXTSTIFF) ); drawText ( 20, 300, disp );
204 sprintf ( disp, "Boundary Dampening: %4.3f", psys.GetParam(SPH_EXTDAMP) ); drawText ( 20, 310, disp );
205 sprintf ( disp, "Speed Limiting: %4.3f", psys.GetParam(SPH_LIMIT) ); drawText ( 20, 320, disp );
206 vol = psys.GetVec ( PLANE_GRAV_DIR );
207 sprintf ( disp, "Gravity: %3.2f %3.2f %3.2f", vol.x, vol.y, vol.z ); drawText ( 20, 330, disp );
211 void computeFromPositions ()
213 cam_from.x = cam_to.x + sin( cam_angs.x * DEGtoRAD) * sin( cam_angs.y * DEGtoRAD) * cam_angs.z;
214 cam_from.y = cam_to.y + -cos( cam_angs.x * DEGtoRAD) * sin( cam_angs.y * DEGtoRAD) * cam_angs.z;
215 cam_from.z = cam_to.z + cos( cam_angs.y * DEGtoRAD) * cam_angs.z;
218 void computeProjection ()
220 // ---- Create projection matrix for eye-coordinate transformations
221 glMatrixMode( GL_PROJECTION );
223 gluPerspective ( cam_fov, window_width / ( float ) window_height, 10.0, 800.0 );
225 glGetFloatv ( GL_MODELVIEW_MATRIX, proj_matrix );
231 glMatrixMode ( GL_MODELVIEW );
233 gluLookAt ( cam_from.x, cam_from.y, cam_from.z, cam_to.x, cam_to.y, cam_to.z, 0, 0, 1 );
235 glGetFloatv ( GL_MODELVIEW_MATRIX, view_matrix );
243 mint::Time start, stop;
245 // iso = sin(frame*0.01f );
248 if ( !bPause ) psys.Run ();
253 glEnable ( GL_DEPTH_TEST );
255 // Render depth map shadows
256 start.SetSystemTime ( ACC_NSEC );
260 renderDepthMap_FrameBuffer ( 0, window_width, window_height );
262 renderDepthMap_Clear ( window_width, window_height );
266 // Clear frame buffer
267 if ( iShade<=1 ) glClearColor( 0.29, 0.29, 0.29, 1.0 );
268 else glClearColor ( 0, 0, 0, 0 );
269 glClear ( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
270 glDisable ( GL_CULL_FACE );
271 glShadeModel ( GL_SMOOTH );
273 // Compute camera view
274 computeFromPositions ();
275 computeProjection ();
278 // Draw Shadows (if on)
280 if ( iShade==1 ) renderShadows ( view_matrix );
284 start.SetSystemTime ( ACC_NSEC );
285 glEnable ( GL_LIGHTING );
286 glLoadMatrixf ( view_matrix );
287 drawScene ( view_matrix, true );
288 if ( bTiming) { stop.SetSystemTime ( ACC_NSEC ); stop = stop - start; printf ( "SCENE: %s\n", stop.GetReadableTime().c_str() ); }
298 void reshape ( int width, int height )
300 // set window height and width
301 window_width = (float) width;
302 window_height = (float) height;
303 glViewport( 0, 0, width, height );
308 obj_from = psys.GetVec ( EMIT_POS );
309 obj_angs = psys.GetVec ( EMIT_ANG );
310 obj_dang = psys.GetVec ( EMIT_RATE );
314 void keyboard_func ( unsigned char key, int x, int y )
317 case 'M': case 'm': {
319 if ( psys_nmax > 65535 ) psys_nmax = 65535;
320 psys.SPH_CreateExample ( psys_demo, psys_nmax );
322 case 'N': case 'n': {
324 if ( psys_nmax < 64 ) psys_nmax = 64;
325 psys.SPH_CreateExample ( psys_demo, psys_nmax );
330 psys.SetVec ( EMIT_RATE, Vector3DF(psys_freq, psys_rate, 0) );
334 psys_freq--; if ( psys_freq < 0 ) psys_freq = 0;
335 psys.SetVec ( EMIT_RATE, Vector3DF(psys_freq, psys_rate, 0) );
339 if ( ++psys_rate > 100 ) psys_rate = 100;
340 psys.SetVec ( EMIT_RATE, Vector3DF(psys_freq, psys_rate, 0) );
344 if ( --psys_rate < 0 ) psys_rate = 0;
345 psys.SetVec ( EMIT_RATE, Vector3DF(psys_freq, psys_rate, 0) );
347 case 'g': case 'G': psys.Toggle ( USE_CUDA ); break;
348 case 'f': case 'F': mode = MODE_DOF; break;
350 case 'z': case 'Z': mode = MODE_CAM_TO; break;
351 case 'c': case 'C': mode = MODE_CAM; break;
352 case 'h': case 'H': bHelp = !bHelp; break;
362 if ( ++iClrMode > 2) iClrMode = 0;
363 psys.SetParam ( CLR_MODE, iClrMode );
365 case 'l': case 'L': mode = MODE_LIGHTPOS; break;
366 case 'd': case 'D': {
367 int d = psys.GetParam ( PNT_DRAWMODE ) + 1;
369 psys.SetParam ( PNT_DRAWMODE, d );
371 case 's': case 'S': if ( ++iShade > 2 ) iShade = 0; break;
372 case 27: exit( 0 ); break;
378 //psys.Run (); ptris.Rebuild (); break;
379 bPause = !bPause; break;
381 case '\'': case ';': psys.SPH_CreateExample ( psys_demo, psys_nmax ); break;
382 case 'r': case 'R': psys.SPH_CreateExample ( psys_demo, psys_nmax ); break;
385 if (psys_demo < 0 ) psys_demo = 10;
386 psys.SPH_CreateExample ( psys_demo, psys_nmax );
391 if (psys_demo > 10 ) psys_demo = 0;
392 psys.SPH_CreateExample ( psys_demo, psys_nmax );
401 void mouse_click_func ( int button, int state, int x, int y )
403 if( state == GLUT_DOWN ) {
404 if ( button == GLUT_LEFT_BUTTON ) dragging = DRAG_LEFT;
405 else if ( button == GLUT_RIGHT_BUTTON ) dragging = DRAG_RIGHT;
413 void mouse_move_func ( int x, int y )
420 if ( dragging == DRAG_LEFT ) {
423 if ( cam_angs.x >= 360.0 ) cam_angs.x -= 360.0;
424 if ( cam_angs.x < 0 ) cam_angs.x += 360.0;
425 if ( cam_angs.y >= 180.0 ) cam_angs.y = 180.0;
426 if ( cam_angs.y <= -180.0 ) cam_angs.y = -180.0;
427 printf ( "Cam Ang: %f %f %f\n", cam_angs.x, cam_angs.y, cam_angs.z );
428 printf ( "Cam To: %f %f %f\n", cam_to.x, cam_to.y, cam_to.z );
429 printf ( "Cam FOV: %f\n", cam_fov);
430 } else if ( dragging == DRAG_RIGHT ) {
431 cam_angs.z += dy*.15;
432 if ( cam_angs.z < 0) cam_angs.z = 0;
433 printf ( "Cam Ang: %f %f %f\n", cam_angs.x, cam_angs.y, cam_angs.z );
434 printf ( "Cam To: %f %f %f\n", cam_to.x, cam_to.y, cam_to.z );
435 printf ( "Cam FOV: %f\n", cam_fov );
439 if ( dragging == DRAG_LEFT ) {
442 } else if ( dragging == DRAG_RIGHT ) {
444 if ( cam_to.z < 0) cam_to.z = 0;
448 if ( dragging == DRAG_LEFT ) {
449 obj_angs.x -= dx*0.1;
450 obj_angs.y += dy*0.1;
451 printf ( "Obj Angs: %f %f %f\n", obj_angs.x, obj_angs.y, obj_angs.z );
454 } else if (dragging == DRAG_RIGHT) {
455 obj_angs.z -= dy*.005;
456 printf ( "Obj Angs: %f %f %f\n", obj_angs.x, obj_angs.y, obj_angs.z );
458 psys.SetVec ( EMIT_ANG, Vector3DF ( obj_angs.x, obj_angs.y, obj_angs.z ) );
461 if ( dragging == DRAG_LEFT ) {
464 printf ( "Obj: %f %f %f\n", obj_from.x, obj_from.y, obj_from.z );
465 } else if (dragging == DRAG_RIGHT) {
467 printf ( "Obj: %f %f %f\n", obj_from.x, obj_from.y, obj_from.z );
469 psys.SetVec ( EMIT_POS, Vector3DF ( obj_from.x, obj_from.y, obj_from.z ) );
470 //psys.setPos ( obj_x, obj_y, obj_z, obj_ang, obj_tilt, obj_dist );
473 if ( dragging == DRAG_LEFT ) {
476 printf ( "Light: %f %f %f\n", light[0].x, light[0].y, light[0].z );
477 } else if (dragging == DRAG_RIGHT) {
479 printf ( "Light: %f %f %f\n", light[0].x, light[0].y, light[0].z );
482 setShadowLight ( light[0].x, light[0].y, light[0].z, light_to[0].x, light_to[0].y, light_to[0].z, light_fov );
487 if ( x < 10 || y < 10 || x > 1000 || y > 700 ) {
488 glutWarpPointer ( 1024/2, 768/2 );
505 glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
506 glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST);
508 srand ( time ( 0x0 ) );
510 glClearColor( 0.49, 0.49, 0.49, 1.0 );
511 glShadeModel( GL_SMOOTH );
513 glEnable ( GL_COLOR_MATERIAL );
514 glEnable (GL_DEPTH_TEST);
516 glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
518 glEnable ( GL_TEXTURE_2D );
521 glutDisplayFunc( display );
522 glutReshapeFunc( reshape );
523 glutKeyboardFunc( keyboard_func );
524 glutMouseFunc( mouse_click_func );
525 glutMotionFunc( mouse_move_func );
526 glutIdleFunc( idle_func );
527 glutSetCursor ( GLUT_CURSOR_NONE );
529 cam_angs.x = 29; cam_angs.y = 75; cam_angs.z = 80.0;
530 cam_to.x = 0; cam_to.y = 0; cam_to.z = 5;
533 light[0].x = 39; light[0].y = -60; light[0].z = 43;
534 light_to[0].x = 0; light_to[0].y = 0; light_to[0].z = 0;
536 light[1].x = 15; light[1].y = -5; light[1].z = 145;
537 light_to[1].x = 0; light_to[1].y = 0; light_to[1].z = 0;
542 createShadowTextures();
543 createFrameBuffer ();
544 setShadowLight ( light[0].x, light[0].y, light[0].z, light_to[0].x, light_to[0].y, light_to[0].z, light_fov );
545 setShadowLightColor ( .7, .7, .7, 0.2, 0.2, 0.2 );
548 obj_from.x = 0; obj_from.y = 0; obj_from.z = 20; // emitter
549 obj_angs.x = 118.7; obj_angs.y = 200; obj_angs.z = 1.0;
550 obj_dang.x = 1; obj_dang.y = 1; obj_dang.z = 0;
552 psys.Initialize ( BFLUID, psys_nmax );
553 psys.SPH_CreateExample ( 0, psys_nmax );
554 psys.SetVec ( EMIT_ANG, Vector3DF ( obj_angs.x, obj_angs.y, obj_angs.z ) );
555 psys.SetVec ( EMIT_POS, Vector3DF ( obj_from.x, obj_from.y, obj_from.z ) );
557 psys.SetParam ( PNT_DRAWMODE, int(bPntDraw ? 1:0) );
558 psys.SetParam ( CLR_MODE, iClrMode );
562 int main ( int argc, char **argv )
566 cudaInit( argc, argv );
570 glutInit( &argc, &argv[0] );
571 glutInitDisplayMode( GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH );
572 glutInitWindowPosition( 100, 100 );
573 glutInitWindowSize( (int) window_width, (int) window_height );
574 glutCreateWindow ( "Fluids v.1 (c) 2008, R. Hoetzlein (ZLib)" );
576 // glutFullScreen ();
578 // initialize parameters
581 // wait for something to happen
588 void btCuda_exit(int val)
590 fprintf(stderr, "Press ENTER key to terminate the program\n");