/****************************************************************************** Copyright (C) 2009 Matteo Lucarelli This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. ******************************************************************************/ // OpenGL/FLTK 2D display with zoom, drag, measures and dynamic grid // Use notes are in header file #include "Fl_gl2display.h" // Fl_gl2displayLabel ////////////////////////////////////////////////////////////////////////////////////////// Fl_gl2displayLabel::Fl_gl2displayLabel(int X, int Y, int W, int H, Fl_gl2display_drawCB *drawCB) : Fl_Box(X,Y,W,H) { m_Display=new Fl_gl2display(X,Y,W,H-20,drawCB); m_Label=new Fl_Output(X,Y+H-20,W,20); m_Label->color(0); m_Label->textcolor(FL_GREEN); m_Label->box(FL_FLAT_BOX); m_Label->textfont(FL_SCREEN); m_Display->setLabel(m_Label); } Fl_gl2displayLabel::~Fl_gl2displayLabel() { delete m_Display; delete m_Label; } GLdouble Fl_gl2displayLabel::getXoffset() { return m_Display->getXoffset(); } GLdouble Fl_gl2displayLabel::getYoffset() { return m_Display->getYoffset(); } GLdouble Fl_gl2displayLabel::getScale() { return m_Display->getScale(); } void Fl_gl2displayLabel::setXoffset(GLdouble val) { return m_Display->setXoffset(val); } void Fl_gl2displayLabel::setYoffset(GLdouble val) { return m_Display->setYoffset(val); } void Fl_gl2displayLabel::setScale(GLdouble val) { return m_Display->setScale(val); } void Fl_gl2displayLabel::draw() { m_Display->redraw(); m_Label->redraw(); } void Fl_gl2displayLabel::setGrid(int minOrder,int maxOrder,int pixFilter,int baseColor, int stepColor) { return m_Display->setGrid(minOrder,maxOrder,pixFilter,baseColor,stepColor); } // Fl_gl2display /////////////////////////////////////////////////////////////////////////////////////////////// Fl_gl2display::Fl_gl2display(int X,int Y,int W,int H, Fl_gl2display_drawCB *drawCB) : Fl_Gl_Window(X,Y,W,H) { m_drawCB=drawCB; glClearColor(0,0,0,0); m_ScaleFactor=1; m_TranslateX=0; m_TranslateY=0; m_doGrid=false; m_Label=NULL; } Fl_gl2display::~Fl_gl2display() { } void Fl_gl2display::refreshLabel() { if (!m_Label) return; char tmp[1024]; snprintf(tmp,1024,"Grid size:%dx%d - Cursor (%.2f,%.2f)",(int)(w()/m_ScaleFactor),(int)(h()/m_ScaleFactor),Fl::event_x()/m_ScaleFactor-m_TranslateX,(h()-Fl::event_y())/m_ScaleFactor-m_TranslateY); m_Label->value(tmp); m_Label->redraw(); } void Fl_gl2display::setGrid(int minOrder,int maxOrder,int pixFilter,int baseColor,int stepColor) { m_doGrid=true; m_minOrder=minOrder; m_maxOrder=maxOrder; m_pixFilter=pixFilter; m_baseColor=baseColor; m_stepColor=stepColor; } void Fl_gl2display::drawGrid() { int color; float i,j,step; // limiti della finestra float xFrom=-m_TranslateX; float xTo=xFrom+w()/m_ScaleFactor; float yFrom=-m_TranslateY; float yTo=yFrom+h()/m_ScaleFactor; glBegin(GL_LINES); color=m_baseColor; for (j=m_minOrder;j<=m_maxOrder;j++){ step=pow(10,j); if (step*m_ScaleFactor<m_pixFilter) continue; if (color>255) color=255; glColor3ub(0,(GLubyte)color,0); color += m_stepColor; for (i=(int)(xFrom/step)*step;i<=(int)(xTo/step)*step;i+=step){ glVertex2d(i,yFrom); glVertex2d(i,yTo); } for (i=(int)(yFrom/step)*step;i<=(int)(yTo/step)*step;i+=step){ glVertex2d(xFrom,i); glVertex2d(xTo,i); } } glColor3ub(0,255,0); glVertex2d(xFrom,0); glVertex2d(xTo,0); glVertex2d(0,yFrom); glVertex2d(0,yTo); glEnd(); } void Fl_gl2display::draw() { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); enable2D(); glPushMatrix(); glScaled(m_ScaleFactor,m_ScaleFactor,0); glTranslated(m_TranslateX,m_TranslateY,0); if (m_doGrid) drawGrid(); if (m_Label) refreshLabel(); m_drawCB(); glPopMatrix(); glViewport(0,0,w(),h()); disable2D(); } void Fl_gl2display::enable2D() { int vPort[4]; glGetIntegerv(GL_VIEWPORT, vPort); glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); glOrtho(0, vPort[2], 0, vPort[3], -1, 1); glMatrixMode(GL_MODELVIEW); glPushMatrix(); glLoadIdentity(); } void Fl_gl2display::disable2D() { glMatrixMode(GL_PROJECTION); glPopMatrix(); glMatrixMode(GL_MODELVIEW); glPopMatrix(); } void Fl_gl2display::resize (int X,int Y, int W, int H) { glViewport(0,0,W,H); Fl_Gl_Window::resize(X,Y,W,H); } int Fl_gl2display::handle(int event) { static int dragx,dragy; switch (event){ case FL_ENTER: cursor(FL_CURSOR_CROSS); return 1; break; case FL_LEAVE: cursor(FL_CURSOR_DEFAULT); return 1; break; case FL_MOUSEWHEEL: if (Fl::event_dy()==-1) m_ScaleFactor *=1.189; if (Fl::event_dy()==1) m_ScaleFactor /=1.189; redraw(); return 1; break; case FL_PUSH: dragx=Fl::event_x(); dragy=Fl::event_y(); return 1; break; case FL_RELEASE: return 1; break; case FL_DRAG: if (Fl::event_button()==1){ m_TranslateX -= (dragx-Fl::event_x())/m_ScaleFactor; m_TranslateY += (dragy-Fl::event_y())/m_ScaleFactor; dragx=Fl::event_x(); dragy=Fl::event_y(); redraw(); return 1; }else if(Fl::event_button()==3){ if ((dragy-Fl::event_y())>0) m_ScaleFactor *=1.044; else if ((dragy-Fl::event_y())<0) m_ScaleFactor /=1.044; dragx=Fl::event_x(); dragy=Fl::event_y(); redraw(); return 1; } break; case FL_MOVE: if (m_Label) refreshLabel(); break; default: break; } return Fl_Gl_Window::handle(event); } GLdouble Fl_gl2display::getXoffset() { return m_TranslateX; } GLdouble Fl_gl2display::getYoffset() { return m_TranslateY; } GLdouble Fl_gl2display::getScale() { return m_ScaleFactor; } void Fl_gl2display::setXoffset(GLdouble val) { m_TranslateX=val; redraw(); } void Fl_gl2display::setYoffset(GLdouble val) { m_TranslateY=val; redraw(); } void Fl_gl2display::setScale(GLdouble val) { m_ScaleFactor=val; redraw(); } void Fl_gl2display::setLabel(Fl_Output* label) { m_Label=label; }