diff options
author | Karl Berry <karl@freefriends.org> | 2009-07-03 00:02:22 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2009-07-03 00:02:22 +0000 |
commit | c20b61928150008d080bab09e967fcaebc93da81 (patch) | |
tree | bffa7c8765003c0e8f2a40c72479e5caa6f748bd /Build/source/utils/asymptote/glrender.cc | |
parent | 9ec802a431dfe1b27063bac2f8dd9bc58cf997b0 (diff) |
asy 1.79
git-svn-id: svn://tug.org/texlive/trunk@14078 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Build/source/utils/asymptote/glrender.cc')
-rw-r--r-- | Build/source/utils/asymptote/glrender.cc | 188 |
1 files changed, 137 insertions, 51 deletions
diff --git a/Build/source/utils/asymptote/glrender.cc b/Build/source/utils/asymptote/glrender.cc index 8dec9d0405c..38389284c78 100644 --- a/Build/source/utils/asymptote/glrender.cc +++ b/Build/source/utils/asymptote/glrender.cc @@ -87,6 +87,8 @@ bool ignorezoom; int Fitscreen; int Mode; +double Angle; +bool orthographic; double H; double xmin,xmax; double ymin,ymax; @@ -94,7 +96,11 @@ double zmin,zmax; double Xmin,Xmax; double Ymin,Ymax; + +pair Shift; double X,Y; +double cx,cy; +double Xfactor,Yfactor; int minimumsize=50; // Minimum initial rendering window width and height @@ -109,6 +115,7 @@ double *Ambient; double *Specular; bool ViewportLighting; bool queueExport=false; +bool readyAfterExport=false; bool antialias; int x0,y0; @@ -118,6 +125,7 @@ int MenuButton=0; double lastangle; double Zoom; +double Zoom0; double lastzoom; GLfloat Rotate[16]; @@ -212,26 +220,27 @@ void initlighting() void setDimensions(int Width, int Height, double X, double Y) { double Aspect=((double) Width)/Height; - double X0=X*(xmax-xmin)/(lastzoom*Width); - double Y0=Y*(ymax-ymin)/(lastzoom*Height); - if(H == 0.0) { + double X0=(X/Width*lastzoom+Shift.getx()*Xfactor)*(xmax-xmin); + double Y0=(Y/Height*lastzoom+Shift.gety()*Yfactor)*(ymax-ymin); + double Zoominv=1.0/Zoom; + if(orthographic) { double xsize=Xmax-Xmin; double ysize=Ymax-Ymin; if(xsize < ysize*Aspect) { - double r=0.5*ysize*Zoom*Aspect; + double r=0.5*ysize*Aspect*Zoominv; xmin=-r-X0; xmax=r-X0; - ymin=Ymin*Zoom-Y0; - ymax=Ymax*Zoom-Y0; + ymin=Ymin*Zoominv-Y0; + ymax=Ymax*Zoominv-Y0; } else { - double r=0.5*xsize*Zoom/Aspect; - xmin=Xmin*Zoom-X0; - xmax=Xmax*Zoom-X0; + double r=0.5*xsize/(Aspect*Zoom); + xmin=Xmin*Zoominv-X0; + xmax=Xmax*Zoominv-X0; ymin=-r-Y0; ymax=r-Y0; } } else { - double r=H*Zoom; + double r=H*Zoominv; xmin=-r*Aspect-X0; xmax=r*Aspect-X0; ymin=-r-Y0; @@ -244,12 +253,12 @@ void setProjection() glMatrixMode(GL_PROJECTION); glLoadIdentity(); setDimensions(Width,Height,X,Y); - if(H == 0.0) + if(orthographic) glOrtho(xmin,xmax,ymin,ymax,-zmax,-zmin); else glFrustum(xmin,xmax,ymin,ymax,-zmax,-zmin); glMatrixMode(GL_MODELVIEW); - arcball.set_params(vec2(0.5*Width,0.5*Height),arcballRadius/Zoom); + arcball.set_params(vec2(0.5*Width,0.5*Height),arcballRadius*Zoom); } bool capsize(int& width, int& height) @@ -268,8 +277,8 @@ bool capsize(int& width, int& height) void reshape0(int width, int height) { - X=X/Width*width; - Y=Y/Height*height; + X=(X/Width)*width; + Y=(Y/Height)*height; Width=width; Height=height; @@ -283,7 +292,7 @@ void update() lastzoom=Zoom; glLoadIdentity(); double cz=0.5*(zmin+zmax); - glTranslatef(0,0,cz); + glTranslatef(cx,cy,cz); glMultMatrixf(Rotate); glTranslatef(0,0,-cz); setProjection(); @@ -307,7 +316,7 @@ void drawscene(double Width, double Height) triple m(xmin,ymin,zmin); triple M(xmax,ymax,zmax); - double perspective=H == 0.0 ? 0.0 : 1.0/zmax; + double perspective=orthographic ? 0.0 : 1.0/zmax; double size2=hypot(Width,Height); @@ -354,10 +363,7 @@ void Export() trImageBuffer(tr,GL_RGB,GL_UNSIGNED_BYTE,data); setDimensions(fullWidth,fullHeight,X/Width*fullWidth,Y/Width*fullWidth); - if(H == 0.0) - trOrtho(tr,xmin,xmax,ymin,ymax,-zmax,-zmin); - else - trFrustum(tr,xmin,xmax,ymin,ymax,-zmax,-zmin); + (orthographic ? trOrtho : trFrustum)(tr,xmin,xmax,ymin,ymax,-zmax,-zmin); size_t count=0; do { @@ -388,10 +394,12 @@ void Export() outOfMemory(); } setProjection(); - + #ifdef HAVE_LIBPTHREAD - if(glthread) + if(glthread && readyAfterExport) { endwait(readySignal,readyLock); + readyAfterExport=false; + } #endif } @@ -438,12 +446,12 @@ void fullscreen() { Width=screenWidth; Height=screenHeight; + reshape0(Width,Height); #ifdef __CYGWIN__ glutFullScreen(); #else glutPositionWindow(0,0); glutReshapeWindow(Width,Height); - reshape0(Width,Height); glutPostRedisplay(); #endif } @@ -453,6 +461,7 @@ void fitscreen() switch(Fitscreen) { case 0: // Original size { + Xfactor=Yfactor=1.0; setsize(oldWidth,oldHeight,minimumsize); break; } @@ -469,6 +478,8 @@ void fitscreen() } case 2: // Full screen { + Xfactor=((double) screenHeight)/Height; + Yfactor=((double) screenWidth)/Width; fullscreen(); break; } @@ -492,10 +503,11 @@ void updateHandler(int) fitscreen(); } -void exportHandler(int) +void autoExport() { if(!Iconify) glutShowWindow(); + readyAfterExport=true; Export(); if(!Iconify) glutHideWindow(); @@ -508,7 +520,6 @@ void reshape(int width, int height) if(initialize) { initialize=false; signal(SIGUSR1,updateHandler); - signal(SIGUSR2,exportHandler); } } @@ -548,11 +559,28 @@ void display() } } -void move(int x, int y) +void shift(int x, int y) { if(x > 0 && y > 0) { - X += (x-x0)*Zoom; - Y += (y0-y)*Zoom; + double Zoominv=1.0/Zoom; + X += (x-x0)*Zoominv; + Y += (y0-y)*Zoominv; + x0=x; y0=y; + update(); + } +} + +void pan(int x, int y) +{ + if(x > 0 && y > 0) { + if(orthographic) { + double Zoominv=1.0/Zoom; + X += (x-x0)*Zoominv; + Y += (y0-y)*Zoominv; + } else { + cx += (x-x0)*(xmax-xmin)/Width; + cy += (y0-y)*(ymax-ymin)/Height; + } x0=x; y0=y; update(); } @@ -586,7 +614,7 @@ void zoom(int x, int y) Motion=true; static const double limit=log(0.1*DBL_MAX)/log(zoomFactor); lastzoom=Zoom; - double s=zoomFactorStep*(y-y0); + double s=zoomFactorStep*(y0-y); if(fabs(s) < limit) { Zoom *= pow(zoomFactor,s); capzoom(); @@ -601,9 +629,9 @@ void mousewheel(int wheel, int direction, int x, int y) { lastzoom=Zoom; if(direction > 0) - Zoom /= zoomFactor; - else Zoom *= zoomFactor; + else + Zoom /= zoomFactor; capzoom(); setProjection(); @@ -752,7 +780,7 @@ string action(int button, int mod) array *Buttons[]={left,middle,right,wheelup,wheeldown}; array *a=Buttons[button]; size_t size=checkArray(a); - if(Mod >= 0 && Mod < (Int) size) + if(Mod >= 0 && Mod < size) return read<string>(a,Mod); } return ""; @@ -763,10 +791,12 @@ void mouse(int button, int state, int x, int y) string Action=action(button,glutGetModifiers()); if(Action == "zoomin") { + glutMotionFunc(NULL); mousewheel(0,1,x,y); return; } if(Action == "zoomout") { + glutMotionFunc(NULL); mousewheel(0,-1,x,y); return; } @@ -774,6 +804,7 @@ void mouse(int button, int state, int x, int y) if(Action == "zoom/menu") { if(state == GLUT_UP && !Motion) { MenuButton=button; + glutMotionFunc(NULL); glutAttachMenu(button); Menu=true; return; @@ -789,7 +820,10 @@ void mouse(int button, int state, int x, int y) glutMotionFunc(rotate); } else if(Action == "shift") { x0=x; y0=y; - glutMotionFunc(move); + glutMotionFunc(shift); + } else if(Action == "pan") { + x0=x; y0=y; + glutMotionFunc(pan); } else if(Action == "zoom" || Action == "zoom/menu") { y0=y; glutMotionFunc(zoom); @@ -797,8 +831,10 @@ void mouse(int button, int state, int x, int y) lastangle=Degrees(x,y); glutMotionFunc(rotateZ); } - } else + } else { arcball.mouse_up(); + glutMotionFunc(NULL); + } } timeval lasttime; @@ -917,11 +953,12 @@ void spinz() void home() { idle(); - X=Y=0.0; + X=Y=cx=cy=0.0; arcball.init(); glLoadIdentity(); glGetFloatv(GL_MODELVIEW_MATRIX,Rotate); - lastzoom=Zoom=1.0; + lastzoom=Zoom=Zoom0; + setDimensions(Width,Height,0,0); } void write(const char *text, const double *v) @@ -931,18 +968,26 @@ void write(const char *text, const double *v) void camera() { - double cz=0.5*(zmin+zmax); camp::Triple vCamera,vTarget,vUp; + double cz=0.5*(zmin+zmax); + for(int i=0; i < 3; ++i) { double sumCamera=0.0, sumTarget=0.0, sumUp=0.0; + int i4=4*i; for(int j=0; j < 4; ++j) { - sumCamera += T[4*i+j]*(Rotate[4*j+3]-cz*Rotate[4*j+2]); - sumUp += T[4*i+j]*(Rotate[4*j+3]+Rotate[4*j+1]); - sumTarget += T[4*i+j]*Rotate[4*j+3]; + int j4=4*j; + double R0=Rotate[j4]; + double R1=Rotate[j4+1]; + double R2=Rotate[j4+2]; + double R3=Rotate[j4+3]; + double T4ij=T[i4+j]; + sumCamera += T4ij*(R3-cx*R0-cy*R1-cz*R2); + sumUp += T4ij*R1; + sumTarget += T4ij*(R3-cx*R0-cy*R1); } vCamera[i]=sumCamera; - vUp[i]=sumUp-sumTarget; + vUp[i]=sumUp; vTarget[i]=sumTarget; } @@ -950,9 +995,23 @@ void camera() triple Up=triple(vUp); triple Target=triple(vTarget); - cout << "camera=" << Camera << "," << endl + pair viewportshift(X/Width*lastzoom+Shift.getx(), + Y/Height*lastzoom+Shift.gety()); + + cout << "currentprojection=" + << (orthographic ? "orthographic(" : "perspective(") << endl + << "camera=" << Camera << "," << endl << "up=" << Up << "," << endl - << "target=" << Target << endl << endl; + << "target=" << Target << "," << endl; + if(orthographic) + cout << "zoom=" << Zoom; + else + cout << "angle=" << 2.0*atan(tan(0.5*Angle)/Zoom)/radians; + if(viewportshift != pair(0.0,0.0)) + cout << "," << endl << "viewportshift=" << viewportshift; + if(!orthographic) + cout << "," << endl << "autoadjust=false"; + cout << ");" << endl << endl; } void keyboard(unsigned char key, int x, int y) @@ -988,10 +1047,12 @@ void keyboard(unsigned char key, int x, int y) break; case '+': case '=': + case '>': expand(); break; case '-': case '_': + case '<': shrink(); break; case 17: // Ctrl-q @@ -1069,8 +1130,8 @@ void init() // angle=0 means orthographic. void glrender(const string& prefix, const picture *pic, const string& format, - double width, double height, - double angle, const triple& m, const triple& M, double *t, + double width, double height, double angle, double zoom, + const triple& m, const triple& M, const pair& shift, double *t, double *background, size_t nlights, triple *lights, double *diffuse, double *ambient, double *specular, bool Viewportlighting, bool view, int oldpid) @@ -1084,6 +1145,8 @@ void glrender(const string& prefix, const picture *pic, const string& format, static bool initializedView=false; + if(zoom == 0.0) zoom=1.0; + Prefix=prefix; Picture=pic; Format=format; @@ -1096,7 +1159,10 @@ void glrender(const string& prefix, const picture *pic, const string& format, Specular=specular; ViewportLighting=Viewportlighting; View=view; + Angle=angle*radians; + Zoom0=zoom; Oldpid=oldpid; + Shift=shift; Xmin=m.getx(); Xmax=M.getx(); @@ -1104,12 +1170,15 @@ void glrender(const string& prefix, const picture *pic, const string& format, Ymax=M.gety(); zmin=m.getz(); zmax=M.getz(); - H=angle != 0.0 ? -tan(0.5*angle*radians)*zmax : 0.0; - + + orthographic=Angle == 0.0; + H=orthographic ? 0.0 : -tan(0.5*Angle)*zmax; + Menu=false; Motion=true; ignorezoom=false; Mode=0; + Xfactor=Yfactor=1.0; static bool initialize=true; @@ -1171,7 +1240,10 @@ void glrender(const string& prefix, const picture *pic, const string& format, #ifdef HAVE_LIBPTHREAD if(glthread && initializedView) { - if(!View) queueExport=true; + if(!View) { + readyAfterExport=queueExport=true; + } + pthread_kill(mainthread,SIGUSR1); return; } @@ -1209,11 +1281,25 @@ void glrender(const string& prefix, const picture *pic, const string& format, #endif #endif string title=string(settings::PROGRAM)+": "+prefix; + string suffix; for(size_t i=0; i < nbuttons; ++i) { int button=buttons[i]; - if(action(button,0) == "zoom/menu") - title += " [Double click "+buttonnames[i]+" button for menu]"; + if(action(button,0) == "menu") { + suffix="Click "+buttonnames[i]+" button for menu"; + break; + } + } + if(suffix.empty()) { + for(size_t i=0; i < nbuttons; ++i) { + int button=buttons[i]; + if(action(button,0) == "zoom/menu") { + suffix="Double click "+buttonnames[i]+" button for menu"; + break; + } + } } + + title += " ["+suffix+"]"; window=glutCreateWindow(title.c_str()); GLint samplebuf[1]; @@ -1309,7 +1395,7 @@ void glrender(const string& prefix, const picture *pic, const string& format, glutMainLoop(); } else { - exportHandler(0); + autoExport(); if(!glthread) quit(); } } |