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

📄 console.cpp

📁 this a Navier-Stokes equations solver. It support grids contains of multiple connected rectangles. S
💻 CPP
字号:
#include <windows.h>
#include <gl/glut.h>
#include <queue>
#include "../core/mech.h"

#define WORLD_MARGIN	(0.05f)
#define NODE_MARGIN		(0.0f)

enum drawMode{ drawVelocity = 0, drawDensity = 2, drawTherm = 3};
enum drawVectors{ drawNoVectors = 0, drawNormVectors = 1, drawNaturalVectors = 2 };
enum Status{ statusIdle, statusPlaying};
const char *strmode[] = {"velocity","","density","temperature"};
const char *strvectorsmode[] = {"","& scaled vectors","& vectors"};

profiler prof;

mech m;
GLuint mechlist = -1;
rect<int> mechbounds;
node currnode;
int window_width = 512, window_height = 512;
rect<float> view;

float zoom_factor = 1;
float shift_x = 0, shift_y = 0;

float pixel_height;
float mousex = 0, mousey = 0;
int stepno = 0;
drawMode drawmode = drawVelocity;
drawVectors is_draw_vectors = drawNormVectors;
Status status = statusIdle;

float linescale(float x);
float powscale2(float x);
float (*scalef)(float) = powscale2;
const char *strscale = "sqrt";

void hsv2rgb( float *c, float h, float s, float v );
void setup_world(const rect<int> &);
void generate_list(GLuint listid, const list<mech::simple_grid> &grids,drawMode mode);
void draw_text(real x,real y,const char *format,...);

void display();
void reshape(int,int);
void mousef(int,int,int,int);
void mousemove(int,int);
void keyb(unsigned char,int,int);
void speckeyb(int,int,int);

void continuous_calculation();

int main(int argc,char **argv)
{
	glutInitWindowPosition(100,100);
	glutInitWindowSize(512,512);
	glutInit(&argc,argv);
	glutInitDisplayMode(GLUT_RGBA|GLUT_DOUBLE);

	int window = glutCreateWindow("solve viewer");
	glutSetWindow(window);
	glutDisplayFunc(&display);
	glutReshapeFunc(&reshape);
	glutKeyboardFunc(&keyb);
	glutMouseFunc(mousef);
	glutPassiveMotionFunc(mousemove);
	glutSpecialFunc(speckeyb);

	//glEnable(GL_LINE_SMOOTH);
	//glEnable(GL_ALPHA_TEST);
	
	stepno = 0;
	if(m.read_file(argv[1]) < 0)return -1;
	mechbounds = m.get_bounds();

	list<mech::simple_grid> grids = m.lock_grids();
	mechlist = glGenLists(1);
	generate_list(mechlist,grids,drawmode);

	glutMainLoop();

	return 0;
}

void display()
{
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	setup_world(mechbounds);

	glCallList(mechlist);

	draw_text(view.a.x,view.b.y - pixel_height*13,
		"step = %d, dt = %e, dx = %e, dy = %e\n"
		"colorscale = %s\n"
		"mode = %s %s\n"
		"pos %.3fx%.3f\n"
		"v={%f,%f}\nd=%f\nT=%f\n"
		"constants:\n"
		"R=%f mu=%f lambda=%f Cv=%f\n"
		"globals:\n"
		"mass = %f",
		stepno,m.getdt(),m.getdx(),m.getdy(),
		strscale,strmode[drawmode],strvectorsmode[is_draw_vectors],
		mousex,mousey,currnode.u,currnode.v,currnode.rho,currnode.T,
		m.getR(),m.getmu(),m.getlambda(),m.getCv(),
		m.mass());

	glFlush();
	glutSwapBuffers();
}

void mousef(int b,int state,int x,int y)
{
	if(state == GLUT_DOWN){
		mousex = view.a.x + float(x) / float(window_width)  * (view.b.x - view.a.x);
		mousey = view.b.y - float(y) / float(window_height) * (view.b.y - view.a.y);
		currnode = m.at(mousex,mousey);
		//printf("mousef(%d,%d,%f,%f)\n",b,state,mousex,mousey);
		glutPostRedisplay();
	}
}

void mousemove(int x,int y)
{
}

void keyb(unsigned char key,int x,int y)
{
	list<mech::simple_grid> grids;
	switch(tolower(key)){
		case 0x20:// space
			if(status == statusPlaying){
				glutIdleFunc(0);
				status = statusIdle;
			}
			m.solve();
			stepno++;
			grids = m.lock_grids();
			generate_list(mechlist,grids,drawmode);
			break;
		case 0xD:
			if(status != statusPlaying){
				glutIdleFunc(continuous_calculation);
				status = statusPlaying;
			}
			break;
		case '1':
			drawmode = drawTherm;
			grids = m.lock_grids();
			generate_list(mechlist,grids,drawmode);
			break;
		case '2':
			drawmode = drawDensity;
			grids = m.lock_grids();
			generate_list(mechlist,grids,drawmode);
			break;
		case '3':
			drawmode = drawVelocity;
			grids = m.lock_grids();
			generate_list(mechlist,grids,drawmode);
			break;
		case 'v':
			is_draw_vectors = static_cast<drawVectors>((is_draw_vectors + 1) % 3);
			grids = m.lock_grids();
			generate_list(mechlist,grids,drawmode);
			break;
		case '-':
			zoom_factor *= 1.1;
			break;
		case '=':
			zoom_factor /= 1.1;
			break;
		case 'c':
			zoom_factor = 1;
			shift_x = shift_y = 0;
			break;
		case 'q':
			exit(0);
			break;
		default:
			printf("key '%c' not binded\n",key);
			return;
	}
	glutPostRedisplay();
}

void speckeyb(int key,int x,int y)
{
	switch(key){
		case GLUT_KEY_RIGHT:
			shift_x += (mechbounds.b.x - mechbounds.a.x)*zoom_factor/10;
			break;
		case GLUT_KEY_LEFT:
			shift_x -= (mechbounds.b.x - mechbounds.a.x)*zoom_factor/10;
			break;
		case GLUT_KEY_UP:
			shift_y += (mechbounds.b.y - mechbounds.a.y)*zoom_factor/10;
			break;
		case GLUT_KEY_DOWN:
			shift_y -= (mechbounds.b.y - mechbounds.a.y)*zoom_factor/10;
			break;
		default:
			printf("spec key %d not binded\n",key);
			return;
	}
	glutPostRedisplay();
}

void reshape(int width,int height)
{
	//printf("reshape(%d,%d)\n",width,height);
	window_width = width;
	window_height = height;
	glutPostRedisplay();
}

void continuous_calculation()
{
	for(int i = 0; i < 10; i++){
		m.solve();
		stepno++;
	}
	list<mech::simple_grid> grids = m.lock_grids();
	generate_list(mechlist,grids,drawmode);
	glutPostRedisplay();
}

void draw_text(real x,real y,const char *format,...)
{
	va_list list;
	va_start(list,format);
	char buf[0x400];
	_vsnprintf(buf,sizeof(buf),format,list);
	va_end(list);

	glPushMatrix();
	glColor4f(1,1,1,0.5);
	glRasterPos2f(x,y);
	for(size_t i = 0, len = strlen(buf); i < len; i++){
		if(buf[i] == '\n'){
			y -= 13*pixel_height;
			glRasterPos2f(x,y);
			continue;
		}
		glutBitmapCharacter(GLUT_BITMAP_8_BY_13,buf[i]);
	}
	glPopMatrix();
}

void value_to_color(float v,float minv,float maxv,float c[3])
{
	float hue;
	if(minv < maxv)hue = 270 - (v - minv)/(maxv - minv)*270.f;
	else hue = 0;
	hsv2rgb(c,hue,0.7,0.7);
}

void draw_velocity(const list<mech::simple_grid> &grids)
{
	real minv = grids.begin()->minvalue.u;
	real maxv = grids.begin()->maxvalue.u;

	for(list<mech::simple_grid>::const_iterator i = grids.begin(); i != grids.end(); i++){
		if(i->maxvalue.u > maxv)maxv = i->maxvalue.u;
		if(i->minvalue.u < minv)minv = i->minvalue.u;
	}
	minv = scalef(minv);
	maxv = scalef(maxv);

	glBegin(GL_QUADS);
	for(list<mech::simple_grid>::const_iterator i = grids.begin(); i != grids.end(); i++){
		real dx = (i->bound.b.x - i->bound.a.x)/i->width,
			dy = (i->bound.b.y - i->bound.a.y)/i->height;

		for(int y = 0; y < i->height; y++)for(int x = 0; x < i->width; x++){
			const node &n = i->a[x + y*i->width];
			/*float c[3], hue;
			if(minv < maxv)hue = 270 - (n.velocity() - minv)/(maxv - minv)*270.f;
			else hue = 0;
			hsv2rgb(c,hue,0.7,0.7);*/
			float c[3];
			value_to_color(scalef(n.velocity()),minv,maxv,c);
			glColor3fv(c);
			glVertex2f(i->bound.a.x + (x   + NODE_MARGIN)*dx, i->bound.a.y + (y + NODE_MARGIN)*dy);
			glVertex2f(i->bound.a.x + (x+1 - NODE_MARGIN)*dx, i->bound.a.y + (y + NODE_MARGIN)*dy);
			glVertex2f(i->bound.a.x + (x+1 - NODE_MARGIN)*dx, i->bound.a.y + (y+1 - NODE_MARGIN)*dy);
			glVertex2f(i->bound.a.x + (x   + NODE_MARGIN)*dx, i->bound.a.y + (y+1 - NODE_MARGIN)*dy);
		}
	}
	glEnd();		
}

void draw_vectors(const list<mech::simple_grid> &grids,bool normalized)
{
	glColor3f(1,1,1);
	glBegin(GL_LINES);
	for(list<mech::simple_grid>::const_iterator i = grids.begin(); i != grids.end(); i++){
		real dx = (i->bound.b.x - i->bound.a.x)/i->width,
			dy = (i->bound.b.y - i->bound.a.y)/i->height;
		for(int y = 0; y < i->height; y++)for(int x = 0; x < i->width; x++){
			const node *n = i->a + x + y*i->width;
			real l = n->velocity(), u, v;
			if(normalized){
				if(l == 0)l = 1;
				u = dx * n->u/l * 0.9;
				v = dy * n->v/l * 0.9;
			}else{
				u = n->u / i->dx;
				v = n->v / i->dy;
			}
			if(true || l > pixel_height){
				float startx = float(i->bound.a.x) + (x + 0.5f)*dx;
				float starty = float(i->bound.a.y) + (y + 0.5f)*dy;
				glVertex2f(startx, starty);
				glVertex2f(startx + u, starty + 0.1 + v);
			}
		}
	}
	glEnd();
}

void generate_list(GLuint listid, const list<mech::simple_grid> &grids,drawMode mode)
{
	//prof.start();
	list<mech::simple_grid>::const_iterator i;
	glNewList(listid,GL_COMPILE);

	if(mode == drawVelocity){
		draw_velocity(grids);
	}else{
		// search for global min and max value into mech
		real minv = grids.begin()->minvalue[mode];
		real maxv = grids.begin()->maxvalue[mode];

		for(i = grids.begin(); i != grids.end(); i++){
			if(i->minvalue[mode] < minv)minv = i->minvalue[mode];
			if(i->maxvalue[mode] > maxv)maxv = i->maxvalue[mode];
		}

		minv = scalef(minv);
		maxv = scalef(maxv);

		glBegin(GL_QUADS);
		for(i = grids.begin(); i != grids.end(); i++){
			real dx = (i->bound.b.x - i->bound.a.x)/i->width,
				dy = (i->bound.b.y - i->bound.a.y)/i->height;

			for(int y = 0; y < i->height; y++)for(int x = 0; x < i->width; x++){
				const node &n = i->a[x + y*i->width];
				/*real c;
				if(minv < maxv)c = (i->a[x + y*i->width][mode] - minv)/(maxv - minv);
				else c = 0;
				glColor3f(c,0,1);*/
				float c[3];
				value_to_color(scalef(i->a[x + y*i->width][mode]),minv,maxv,c);
				glColor3fv(c);
				glVertex2f(i->bound.a.x + (x   + NODE_MARGIN)*dx, i->bound.a.y + (y + NODE_MARGIN)*dy);
				glVertex2f(i->bound.a.x + (x+1 - NODE_MARGIN)*dx, i->bound.a.y + (y + NODE_MARGIN)*dy);
				glVertex2f(i->bound.a.x + (x+1 - NODE_MARGIN)*dx, i->bound.a.y + (y+1 - NODE_MARGIN)*dy);
				glVertex2f(i->bound.a.x + (x   + NODE_MARGIN)*dx, i->bound.a.y + (y+1 - NODE_MARGIN)*dy);
			}
		}
		glEnd();

	}
	if(is_draw_vectors > drawNoVectors){
		draw_vectors(grids,is_draw_vectors == drawNormVectors);
	}

	glColor3f(1,1,1);
	for(i = grids.begin(); i != grids.end(); i++){
		glBegin(GL_LINE_STRIP);
		glVertex2f(i->bound.a.x,i->bound.a.y);
		glVertex2f(i->bound.b.x,i->bound.a.y);
		glVertex2f(i->bound.b.x,i->bound.b.y);
		glVertex2f(i->bound.a.x,i->bound.b.y);
		glVertex2f(i->bound.a.x,i->bound.a.y);
		glEnd();
	}

	glEndList();
	//double sec = prof.get();
	//printf("generate list time %.3f\n",sec);
}

void setup_world(const rect<int> &bounds)
{
	float width = bounds.b.x - bounds.a.x;
	float height = bounds.b.y - bounds.a.y;
	float centerx = (bounds.a.x + bounds.b.x)/2 + shift_x;
	float centery = (bounds.a.y + bounds.b.y)/2 + shift_y;
	float window_ar = float(window_width)/float(window_height);
	float world_ar = width/height;

	if(window_ar < world_ar){
		height = width / window_ar;
	}else{
		width = window_ar * height;
	}

	pixel_height = height*(1 + 2*WORLD_MARGIN)*zoom_factor / window_height;
	view.a.x = centerx - width*(0.5 + WORLD_MARGIN)*zoom_factor;
	view.a.y = centery - height*(0.5 + WORLD_MARGIN)*zoom_factor;
	view.b.x = centerx + width*(0.5 + WORLD_MARGIN)*zoom_factor;
	view.b.y = centery + height*(0.5 + WORLD_MARGIN)*zoom_factor;

	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	gluOrtho2D(view.a.x,view.b.x,view.a.y,view.b.y);
	glViewport(0,0,window_width,window_height);
	glClearColor(0,0,0,1);
	glMatrixMode(GL_MODELVIEW);
}

void hsv2rgb( float *c, float h, float s, float v )
{
	int i;
	float f, p, q, t;
	if( s == 0 ) {
		c[0] = c[1] = c[2] = v;
		return;
	}
	h /= 60;			// sector 0 to 5
	i = floor( h );
	f = h - i;			// factorial part of h
	p = v * ( 1 - s );
	q = v * ( 1 - s * f );
	t = v * ( 1 - s * ( 1 - f ) );
	switch( i ) {
		case 0:
			c[0] = v;
			c[1] = t;
			c[2] = p;
			break;
		case 1:
			c[0] = q;
			c[1] = v;
			c[2] = p;
			break;
		case 2:
			c[0] = p;
			c[1] = v;
			c[2] = t;
			break;
		case 3:
			c[0] = p;
			c[1] = q;
			c[2] = v;
			break;
		case 4:
			c[0] = t;
			c[1] = p;
			c[2] = v;
			break;
		default:		// case 5:
			c[0] = v;
			c[1] = p;
			c[2] = q;
			break;
	}
}

float linescale(float x)
{
	return x;
}

float powscale2(float x)
{
	return powf(x,0.5f);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -