00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "lux.h"
00025 #include "renderwindow.h"
00026
00027
00028 #ifdef LUX_USE_OPENGL
00029
00030
00031 GlWindow::GlWindow(int x,int y,int w,int h,const char *lab): Fl_Gl_Window(x,y,w,h,lab), texture_w(256), texture_h(256){
00032 offset_x=offset_y=scale_xo2=scale_yo2=0;
00033 lastx=lasty=0;
00034 image_w=image_h=0;
00035 tiles_x=tiles_y=tiles_nr=0;
00036 scale=1.0f;
00037 scale_exp=0;
00038 scale_xo=scale_yo=0;
00039 image_ptr = NULL;
00040 image_changed = false;
00041 mode(FL_RGB | FL_ALPHA | FL_DEPTH | FL_DOUBLE);
00042 end();
00043 }
00044
00045 GlWindow::~GlWindow(){
00046 }
00047
00048 void GlWindow::update_image(){
00049 image_changed = true;
00050 }
00051
00052 void GlWindow::set_image(Fl_RGB_Image *img){
00053 image_ptr = img;
00054 }
00055
00056 void GlWindow::resize(int X,int Y,int W,int H){
00057
00058 offset_x+=(W-w())/2;
00059 offset_y+=(H-h())/2;
00060
00061 if((image_w-scale_xo)*scale+scale_xo2+offset_x-10<0)
00062 offset_x = (int)( 10-scale_xo2-(image_w-scale_xo)*scale );
00063 if((0-scale_xo)*scale+scale_xo2+offset_x+10>W-1)
00064 offset_x = (int)( W-1-10-scale_xo2-(0-scale_xo)*scale );
00065 if((image_h-scale_yo)*scale+scale_yo2+offset_y-10<0)
00066 offset_y = (int)( 10-scale_yo2-(image_h-scale_yo)*scale );
00067 if((0-scale_yo)*scale+scale_yo2+offset_y+10>H-1)
00068 offset_y = (int)( H-1-10-scale_yo2-(0-scale_yo)*scale );
00069 Fl_Gl_Window::resize(X,Y,W,H);
00070 }
00071
00072 int GlWindow::handle(int event){
00073 if(event==FL_ENTER){
00074 fl_cursor(FL_CURSOR_CROSS);
00075 return 1;
00076 }
00077 if(event==FL_LEAVE){
00078 fl_cursor(FL_CURSOR_DEFAULT);
00079 return 1;
00080 }
00081 if(event==FL_PUSH){
00082 if(image_ptr==NULL) return 1;
00083 lastx=Fl::event_x();
00084 lasty=Fl::event_y();
00085 int button=Fl::event_button();
00086 if(button==3){
00087
00088 scale_xo = (int)( Fl::event_x() /scale-scale_xo2/scale-offset_x/scale+scale_xo );
00089 scale_yo = (int)( (h()-1-Fl::event_y())/scale-scale_yo2/scale-offset_y/scale+scale_yo );
00090
00091 if(scale_xo<0) scale_xo=0;
00092 if(scale_xo>image_w-1) scale_xo=image_w-1;
00093 if(scale_yo<0) scale_yo=0;
00094 if(scale_yo>image_h-1) scale_yo=image_h-1;
00095
00096 scale_exp=0;
00097 scale=1.0f;
00098
00099 scale_xo2=Fl::event_x();
00100 scale_yo2=h()-1-Fl::event_y();
00101 offset_x=offset_y=0;
00102 redraw();
00103 }
00104 if(button==2){
00105 scale=min(w()/(float)image_w, h()/(float)image_h);
00106 scale_exp=floor(log((float)scale)/log(2.0f)*2+0.5f)/2;
00107 scale_xo2=w()/2;
00108 scale_yo2=h()/2;
00109 scale_xo=image_w/2;
00110 scale_yo=image_h/2;
00111 offset_x=0;
00112 offset_y=0;
00113 redraw();
00114 }
00115 return 1;
00116 }
00117 if(event==FL_DRAG){
00118 if(image_ptr==NULL || !Fl::event_state(FL_BUTTON1)) return 1;
00119 fl_cursor(FL_CURSOR_MOVE);
00120
00121 int offset_x_new=offset_x+Fl::event_x()-lastx;
00122 int offset_y_new=offset_y-(Fl::event_y()-lasty);
00123
00124 if((image_w-scale_xo)*scale+scale_xo2+offset_x_new-10>=0 && (0-scale_xo)*scale+scale_xo2+offset_x_new+10<=w()-1)
00125 offset_x=offset_x_new;
00126 if((image_h-scale_yo)*scale+scale_yo2+offset_y_new-10>=0 && (0-scale_yo)*scale+scale_yo2+offset_y_new+10<=h()-1)
00127 offset_y=offset_y_new;
00128 lastx=Fl::event_x();
00129 lasty=Fl::event_y();
00130 redraw();
00131 return 1;
00132 }
00133
00134 if(event==FL_MOUSEWHEEL){
00135 if(image_ptr==NULL) return 1;
00136 if(Fl::event_dy()<0){
00137 if(scale>=4)
00138 return 1;
00139 }else{
00140 if(scale<=1 && scale*image_w<w()*0.5f && scale*image_h<h()*0.5f)
00141 return 1;
00142 }
00143
00144 scale_xo = (int)( Fl::event_x() /scale-scale_xo2/scale-offset_x/scale+scale_xo );
00145 scale_yo = (int)( (h()-1-Fl::event_y())/scale-scale_yo2/scale-offset_y/scale+scale_yo );
00146
00147 if(scale_xo<0) scale_xo=0;
00148 if(scale_xo>image_w-1) scale_xo=image_w-1;
00149 if(scale_yo<0) scale_yo=0;
00150 if(scale_yo>image_h-1) scale_yo=image_h-1;
00151
00152 scale_exp+=-(Fl::event_dy()>0?1:-1)*0.5f;
00153 scale=pow(2.0f,scale_exp);
00154
00155 scale_xo2=Fl::event_x();
00156 scale_yo2=h()-1-Fl::event_y();
00157 offset_x=offset_y=0;
00158 redraw();
00159 return 1;
00160 }
00161 return Fl_Gl_Window::handle(event);
00162 }
00163
00164 void GlWindow::draw(void){
00165 if (!valid()) {
00166 valid(1);
00167 glLoadIdentity();
00168 glViewport(0,0,w(),h());
00169 glOrtho(0,w(),0,h(),-1,1);
00170 glClearColor(0.5,0.5,0.5,1.0);
00171 }
00172
00173 glClear(GL_COLOR_BUFFER_BIT);
00174
00175 static bool firstDraw = true;
00176 if(firstDraw && image_ptr){
00177 firstDraw=false;
00178 image_w=image_ptr->w();
00179 image_h=image_ptr->h();
00180 tiles_x=image_w/texture_w+1;
00181 tiles_y=image_h/texture_h+1;
00182 tiles_nr=tiles_x*tiles_y;
00183 for(int i=0; i<tiles_nr; i++){
00184 glBindTexture (GL_TEXTURE_2D, i+1);
00185 glPixelStorei (GL_UNPACK_ALIGNMENT, 1);
00186 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
00187 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
00188 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
00189 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
00190 glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
00191 glTexImage2D (GL_TEXTURE_2D, 0, GL_RGB, texture_w, texture_h, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
00192 }
00193 image_changed=true;
00194
00195 scale_xo2=-image_w/2+w()/2;
00196 scale_yo2=-image_h/2+h()/2;
00197 }
00198
00199 if(image_ptr){
00200 glPushMatrix();
00201
00202 glTranslatef(offset_x,offset_y,0);
00203 glTranslatef(scale_xo2,scale_yo2,0);
00204 glScalef(scale,scale,1);
00205 glTranslatef(-scale_xo,-scale_yo,0);
00206
00207 glEnable (GL_TEXTURE_2D);
00208
00209 for(int i=0; i<tiles_nr; i++){
00210 int tile_w = i%tiles_x==tiles_x-1?image_w%texture_w:texture_w;
00211 int tile_h = i/tiles_x==tiles_y-1?image_h%texture_h:texture_h;
00212 glBindTexture (GL_TEXTURE_2D, i+1);
00213 if(image_changed)
00214 for(int j=0; j<tile_h; j++)
00215 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, j, tile_w, 1, GL_RGB, GL_UNSIGNED_BYTE, *image_ptr->data()+(((i%tiles_x)*texture_w)*3 + ((tiles_y-1-i/tiles_x)*texture_h+(texture_h-1-j)-(tiles_y*texture_h-image_h))*image_w*3));
00216
00217 glBegin (GL_QUADS);
00218 glTexCoord2f ( 0.0f, 0.0f );
00219 glVertex3f ( (i%tiles_x)*texture_w + 0.0f, (i/tiles_x)*texture_h + 0.0f, 0.0f );
00220 glTexCoord2f ( 1.0f*tile_w/texture_w, 0.0f );
00221 glVertex3f ( (i%tiles_x)*texture_w + tile_w, (i/tiles_x)*texture_h + 0.0f, 0.0f );
00222 glTexCoord2f ( 1.0f*tile_w/texture_w, 1.0f*tile_h/texture_h );
00223 glVertex3f ( (i%tiles_x)*texture_w + tile_w, (i/tiles_x)*texture_h + tile_h, 0.0f );
00224 glTexCoord2f ( 0.0f, 1.0f*tile_h/texture_h );
00225 glVertex3f ( (i%tiles_x)*texture_w + 0.0f, (i/tiles_x)*texture_h + tile_h, 0.0f );
00226 glEnd ();
00227 }
00228 glDisable (GL_TEXTURE_2D);
00229 glPopMatrix();
00230 image_changed=false;
00231 }else{
00232 glColor3f(1.0, 1.0, 1.0);
00233 glBegin(GL_LINE_STRIP); glVertex2f(w(), h()); glVertex2f(0, 0); glEnd();
00234 glBegin(GL_LINE_STRIP); glVertex2f(w(), 0); glVertex2f(0, h()); glEnd();
00235 }
00236
00237 glFlush();
00238 }
00239
00240 #endif // LUX_USE_OPENGL
00241
00242
00243
00244 RenderWindow::RenderWindow(int x,int y,int w,int h,Fl_Color col_back,Fl_Color col_renderback,const char *lab,bool opengl_enabled)
00245 : Fl_Group(x,y,w,h,lab), opengl_enabled(opengl_enabled){
00246 box(FL_FLAT_BOX);
00247 color(col_back);
00248 labelsize(11);
00249 align(FL_ALIGN_CENTER|FL_ALIGN_INSIDE);
00250 image_ptr = NULL;
00251 #ifndef LUX_USE_OPENGL
00252 opengl_enabled = false;
00253 #endif // LUX_USE_OPENGL
00254 if(opengl_enabled){
00255 groupwin = NULL;
00256 glwin = new GlWindow(x,y,w,h,"");
00257 }else{
00258 glwin = NULL;
00259 groupwin = new Fl_Group(x,y,w,h,"");
00260 groupwin->box(FL_FLAT_BOX);
00261 groupwin->color(col_renderback);
00262 groupwin->labelsize(1);
00263 groupwin->align(FL_ALIGN_CENTER);
00264 groupwin->end();
00265 }
00266 end();
00267 }
00268 void RenderWindow::update_image(){
00269 image_ptr->uncache();
00270 if(opengl_enabled)
00271 glwin->update_image();
00272 }
00273 void RenderWindow::set_image(Fl_RGB_Image *img){
00274 if(img==NULL) return;
00275 image_ptr=img;
00276 if(opengl_enabled)
00277 glwin->set_image(img);
00278 else
00279 groupwin->image(img);
00280 }
00281