📄 console.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 + -