blob: 49416a681c899cbb36c9a582815076923159786b [file] [log] [blame]
// Written by Christian Bienia and Richard O. Lee
// This file contains code to visualize the fluid interactively
// Requires the GLUT library
#include <cstdlib>
#include <iostream>
#include <GL/glut.h>
#include "fluid.hpp"
#include "fluidview.hpp"
float rotX = 0.f;
float rotY = 0.f;
float moveX = 0.f;
float moveY = 0.03f;
float depth = -0.2f;
bool rot = false;
bool move = false;
bool zoom = false;
int oldX, oldY;
//function pointer to function that advances fluid by one frame
void (*_AdvanceFrame)();
//pointers to fluid state variables
int *_numCells;
Cell **_cells;
int **_cnumPars;
extern Vec3 vMin;
extern Vec3 vMax;
void InitVisualizationMode(int *argc, char *argv[], void (*AdvanceFrame)(), int *numCells, Cell **cells, int **cnumPars)
{
glutInit(argc, argv);
glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE);
glutInitWindowSize(640, 480);
glutInitWindowPosition(50, 50);
glutCreateWindow("PARSEC Fluidanimate - Visualization Mode");
glEnable(GL_CULL_FACE);
glEnable(GL_DEPTH_TEST);
glShadeModel(GL_FLAT);
glClearColor(0.f, 0.f, 0.f, 0.f);
const float la[] = { 0.1f, 0.1f, 0.1f, 0.f };
const float ld[] = { 0.5f, 0.5f, 0.5f, 0.f };
glLightfv(GL_LIGHT0, GL_AMBIENT, la);
glLightfv(GL_LIGHT0, GL_DIFFUSE, ld);
glEnable(GL_LIGHT0);
glEnable(GL_LIGHTING);
glEnable(GL_COLOR_MATERIAL);
glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);
_AdvanceFrame = AdvanceFrame;
_numCells = numCells;
_cells = cells;
_cnumPars = cnumPars;
}
////////////////////////////////////////////////////////////////////////////////
void Reshape(int width, int height)
{
glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45., GLdouble(width)/GLdouble(height), 0.1, 100.);
glMatrixMode(GL_MODELVIEW);
}
////////////////////////////////////////////////////////////////////////////////
void Idle()
{
glutPostRedisplay();
}
////////////////////////////////////////////////////////////////////////////////
fptype prior_y_Max = 0;
fptype y_Tot = 0;
fptype prior_y_Tot = 0;
fptype prior_y_Ave = 0;
static int DisplayFrameNumber = 0;
void Display()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
std::cout << "Advancing frame (" << DisplayFrameNumber++ << ")..." << std::endl << std::flush;
_AdvanceFrame();
glLoadIdentity();
glTranslatef(moveX, moveY, depth);
glRotatef(rotX, 1.f, 0.f, 0.f);
glRotatef(rotY, 0.f, 1.f, 0.f);
GLfloat lp[] = { 1.f, 2.f, 3.f, 0.f };
glLightfv(GL_LIGHT0, GL_POSITION, lp);
glColor3f(1,1,1);
glLineWidth(3.f);
glBegin(GL_LINES);
const float yardstick = domainMin.y + (domainMax.y-domainMin.y)*0.11f;
glVertex3f(domainMin.x, domainMin.y, domainMin.z);
glVertex3f(domainMin.x, yardstick, domainMin.z);
glVertex3f(domainMax.x, domainMin.y, domainMin.z);
glVertex3f(domainMax.x, yardstick, domainMin.z);
glVertex3f(domainMin.x, domainMin.y, domainMax.z);
glVertex3f(domainMin.x, yardstick, domainMax.z);
glVertex3f(domainMax.x, domainMin.y, domainMax.z);
glVertex3f(domainMax.x, yardstick, domainMax.z);
glEnd();
glColor3f(0.f, 0.5f, 0.8f);
glPointSize(2.f);
glBegin(GL_POINTS);
vMax.y = domainMin.y;
y_Tot = 0;
fptype surface = domainMin.y + prior_y_Ave*2.0;
for(int i = 0; i < *_numCells; ++i)
{
Cell *cell = &(*_cells)[i];
int np = (*_cnumPars)[i];
for(int j = 0; j < np; ++j)
{
#define USE_track_velocity
#if defined(USE_track_velocity)
// track velocity
Vec3 v = cell->v[j % PARTICLES_PER_CELL];
vMin.x = std::min(vMin.x,v.x);
vMax.x = std::max(vMax.x,v.x);
vMin.y = std::min(vMin.y,v.y);
vMax.y = std::max(vMax.y,v.y);
vMin.z = std::min(vMin.z,v.z);
vMax.z = std::max(vMax.z,v.z);
glColor3f(
(v.x - vMin.x) / (vMax.x - vMin.x),
(v.y - vMin.y) / (vMax.y - vMin.y),
(v.z - vMin.z) / (vMax.z - vMin.z));
#else
// track y displacement
fptype y = cell->p[j % PARTICLES_PER_CELL].y;
y_Tot += y - domainMin.y;
vMax.y = std::max(vMax.y,y);
prior_y_Max = std::max(vMax.y,prior_y_Max);
glColor3f(
0.5f,
0.5f + (float)((y - surface) / (prior_y_Max - surface)),
0.5f);
#endif
glVertex3f(cell->p[j % PARTICLES_PER_CELL].x, cell->p[j % PARTICLES_PER_CELL].y, cell->p[j % PARTICLES_PER_CELL].z);
//move pointer to next cell in list if end of array is reached
if(j % PARTICLES_PER_CELL == PARTICLES_PER_CELL-1) {
cell = cell->next;
}
}
}
#if defined(USE_track_velocity)
vMin *= 0.99;
// avoid vMin == vMax (causes divide by 0)
vMax.x = std::max(vMax.x * 0.99, vMin.x + epsilon);
vMax.y = std::max(vMax.y * 0.99, vMin.y + epsilon);
vMax.z = std::max(vMax.z * 0.99, vMin.z + epsilon);
#else
prior_y_Max = vMax.y;
prior_y_Ave = y_Tot / (fptype)*_numCells;
#endif
glEnd();
glFlush();
glutSwapBuffers();
}
////////////////////////////////////////////////////////////////////////////////
void ApplyImpulse(Vec3 const &impulse)
{
for(int i = 0; i < *_numCells; ++i)
{
Cell *cell = &(*_cells)[i];
int np = (*_cnumPars)[i];
for(int j = 0; j < np; ++j)
{
cell->hv[j % PARTICLES_PER_CELL] += impulse;
//move pointer to next cell in list if end of array is reached
if(j % PARTICLES_PER_CELL == PARTICLES_PER_CELL-1) {
cell = cell->next;
}
}
}
}
////////////////////////////////////////////////////////////////////////////////
void Keyboard(unsigned char key, int x, int y)
{
switch(key)
{
case 'a': ApplyImpulse(Vec3(-1.f, 0.f, 0.f)); break;
case 'd': ApplyImpulse(Vec3(1.f, 0.f, 0.f)); break;
case 'e': ApplyImpulse(Vec3(0.f, -1.f, 0.f)); break;
case 'q': ApplyImpulse(Vec3(0.f, 1.f, 0.f)); break;
case 'w': ApplyImpulse(Vec3(0.f, 0.f, -1.f)); break;
case 's': ApplyImpulse(Vec3(0.f, 0.f, 1.f)); break;
case 27: // escape
exit(0);
break;
}
glutPostRedisplay();
}
////////////////////////////////////////////////////////////////////////////////
void Mouse(int button, int state, int x, int y)
{
if(button == GLUT_LEFT_BUTTON)
rot = (state == GLUT_DOWN);
else if(button == GLUT_MIDDLE_BUTTON)
move = (state == GLUT_DOWN);
else if(button == GLUT_RIGHT_BUTTON)
zoom = (state == GLUT_DOWN);
oldX = x;
oldY = y;
}
////////////////////////////////////////////////////////////////////////////////
void Motion(int x, int y)
{
if(rot)
{
rotX += float(y - oldY) * 0.5f;
rotY += float(x - oldX) * 0.5f;
}
if(move)
{
moveX += float(x - oldX) * 0.01f;
moveY -= float(y - oldY) * 0.01f;
}
if(zoom)
depth += float(y - oldY) * 0.05f;
oldX = x;
oldY = y;
}
void Visualize() {
glutReshapeFunc(Reshape);
glutIdleFunc(Idle);
glutDisplayFunc(Display);
glutKeyboardFunc(Keyboard);
glutMouseFunc(Mouse);
glutMotionFunc(Motion);
glutMainLoop();
}