00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #ifdef LUX_USE_OPENGL
00024
00025 #include "wxglviewer.h"
00026
00027
00028 #ifdef __WXMAC__
00029 #include "OpenGL/glu.h"
00030 #include "OpenGL/gl.h"
00031 #else
00032 #include <GL/glu.h>
00033 #include <GL/gl.h>
00034 #endif
00035
00036 #include <cmath>
00037
00038 #include "lux.h"
00039 #include "api.h"
00040
00041 using namespace lux;
00042
00043 BEGIN_EVENT_TABLE(LuxGLViewer, wxWindow)
00044 EVT_PAINT (LuxGLViewer::OnPaint)
00045 EVT_SIZE (LuxGLViewer::OnSize)
00046 EVT_MOUSE_EVENTS (LuxGLViewer::OnMouse)
00047 EVT_ERASE_BACKGROUND (LuxGLViewer::OnEraseBackground)
00048 END_EVENT_TABLE()
00049
00050 int glAttribList[] = {WX_GL_RGBA, WX_GL_DOUBLEBUFFER, 0};
00051
00052 LuxGLViewer::LuxGLViewer(wxWindow *parent, int textureW, int textureH)
00053 : wxGLCanvas(parent, wxID_ANY, glAttribList), m_glContext(this), m_textureW(textureW), m_textureH(textureH) {
00054 m_firstDraw = true;
00055 m_offsetX = m_offsetY = 0;
00056 m_scale = 1.0f;
00057 m_scaleExp=0;
00058 m_scaleXo = m_scaleYo = 0;
00059 m_scaleXo2 = m_scaleYo2 = 0;
00060 m_lastX = m_lastY = 0;
00061 SetCursor(wxCURSOR_CROSS);
00062 }
00063
00064 void LuxGLViewer::OnPaint(wxPaintEvent& event) {
00065 SetCurrent(m_glContext);
00066 wxPaintDC(this);
00067 glClearColor(0.5, 0.5, 0.5, 1.0);
00068 glViewport(0, 0, (GLint)GetSize().x, (GLint)GetSize().y);
00069 glLoadIdentity();
00070 glOrtho(0, GetSize().x, 0, GetSize().y, -1, 1);
00071 glClear(GL_COLOR_BUFFER_BIT);
00072
00073 if(luxStatistics("sceneIsReady")) {
00074 if(m_firstDraw) {
00075 m_firstDraw = false;
00076 m_imageW = luxStatistics("filmXres");
00077 m_imageH = luxStatistics("filmYres");
00078
00079
00080 m_tilesX = ceil((float)m_imageW/m_textureW);
00081 m_tilesY = ceil((float)m_imageH/m_textureH);
00082 m_tilesNr = m_tilesX*m_tilesY;
00083 for(int i = 0; i < m_tilesNr; i++){
00084 glBindTexture(GL_TEXTURE_2D, i+1);
00085 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
00086 glPixelStorei(GL_UNPACK_ROW_LENGTH, m_imageW);
00087 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
00088 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
00089 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
00090 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
00091 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
00092 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, m_textureW, m_textureH, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
00093 }
00094 m_imageChanged = true;
00095
00096 m_scaleXo2 = -m_imageW/2 + GetSize().x/2;
00097 m_scaleYo2 = -m_imageH/2 + GetSize().y/2;
00098 }
00099
00100 glPushMatrix();
00101
00102 glTranslatef(m_offsetX, m_offsetY, 0.f);
00103 glTranslatef(m_scaleXo2, m_scaleYo2, 0.f);
00104 glScalef(m_scale, m_scale, 1.f);
00105 glTranslatef(-m_scaleXo, -m_scaleYo, 0.f);
00106
00107 glEnable (GL_TEXTURE_2D);
00108
00109 for(int y = 0; y < m_tilesY; y++){
00110 for(int x = 0; x < m_tilesX; x++){
00111 int offX = x*m_textureW;
00112 int offY = y*m_textureH;
00113 int tileW = min(m_textureW, m_imageW - offX);
00114 int tileH = min(m_textureH, m_imageH - offY);
00115 glBindTexture (GL_TEXTURE_2D, y*m_tilesX+x+1);
00116 if(m_imageChanged) {
00117
00118 glPixelStorei(GL_UNPACK_SKIP_PIXELS, offX);
00119 glPixelStorei(GL_UNPACK_SKIP_ROWS, offY);
00120 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, tileW, tileH, GL_RGB, GL_UNSIGNED_BYTE, luxFramebuffer());
00121 }
00122 glBegin(GL_QUADS);
00123 glTexCoord2f( 0.0f, 0.0f);
00124 glVertex3f( x*m_textureW + 0.0f, m_imageH - (y*m_textureH + 0.0f), 0.0f);
00125 glTexCoord2f(1.0f*tileW/m_textureW, 0.0f);
00126 glVertex3f( x*m_textureW + tileW, m_imageH - (y*m_textureH + 0.0f), 0.0f);
00127 glTexCoord2f(1.0f*tileW/m_textureW, 1.0f*tileH/m_textureH);
00128 glVertex3f( x*m_textureW + tileW, m_imageH - (y*m_textureH + tileH), 0.0f);
00129 glTexCoord2f( 0.0f, 1.0f*tileH/m_textureH);
00130 glVertex3f( x*m_textureW + 0.0f, m_imageH - (y*m_textureH + tileH), 0.0f);
00131 glEnd();
00132 }
00133 }
00134 glDisable(GL_TEXTURE_2D);
00135 glPopMatrix();
00136 }
00137
00138 glFlush();
00139 SwapBuffers();
00140 m_imageChanged=false;
00141 }
00142
00143 void LuxGLViewer::OnEraseBackground(wxEraseEvent &event) {
00144
00145
00146 return;
00147 }
00148
00149 void LuxGLViewer::OnSize(wxSizeEvent &event) {
00150 wxGLCanvas::OnSize(event);
00151
00152 int W, H;
00153 W = event.GetSize().x;
00154 H = event.GetSize().y;
00155
00156 if(!m_firstDraw) {
00157
00158 m_offsetX += (W-m_lastW)/2;
00159 m_offsetY += (H-m_lastH)/2;
00160
00161 if((m_imageW-m_scaleXo)*m_scale+m_scaleXo2+m_offsetX-10<0)
00162 m_offsetX = (int)( 10-m_scaleXo2-(m_imageW-m_scaleXo)*m_scale );
00163 if((0-m_scaleXo)*m_scale+m_scaleXo2+m_offsetX+10>W-1)
00164 m_offsetX = (int)( W-1-10-m_scaleXo2-(0-m_scaleXo)*m_scale );
00165 if((m_imageH-m_scaleYo)*m_scale+m_scaleYo2+m_offsetY-10<0)
00166 m_offsetY = (int)( 10-m_scaleYo2-(m_imageH-m_scaleYo)*m_scale );
00167 if((0-m_scaleYo)*m_scale+m_scaleYo2+m_offsetY+10>H-1)
00168 m_offsetY = (int)( H-1-10-m_scaleYo2-(0-m_scaleYo)*m_scale );
00169 }
00170 m_lastW = W;
00171 m_lastH = H;
00172
00173 Update();
00174 }
00175
00176 void LuxGLViewer::OnMouse(wxMouseEvent &event) {
00177 int W, H;
00178 GetClientSize(&W, &H);
00179
00180
00181 if(m_firstDraw) {
00182 event.Skip();
00183 } else if(event.GetEventType() == wxEVT_LEFT_DOWN) {
00184 SetCursor(wxCURSOR_HAND);
00185 event.Skip();
00186 } else if(event.GetEventType() == wxEVT_LEFT_UP) {
00187 SetCursor(wxCURSOR_CROSS);
00188 } else if(event.GetEventType() == wxEVT_MIDDLE_DOWN) {
00189 m_scale = min(W/(float)m_imageW, H/(float)m_imageH);
00190 m_scaleExp = floor(log((float)m_scale)/log(2.0f)*2+0.5f)/2;
00191 m_scaleXo2 = W/2;
00192 m_scaleYo2 = H/2;
00193 m_scaleXo = m_imageW/2;
00194 m_scaleYo = m_imageH/2;
00195 m_offsetX = 0;
00196 m_offsetY = 0;
00197 wxGLCanvas::Refresh();
00198 } else if(event.GetEventType() == wxEVT_RIGHT_DOWN) {
00199
00200 m_scaleXo = (int)( event.GetX() /m_scale-m_scaleXo2/m_scale-m_offsetX/m_scale+m_scaleXo);
00201 m_scaleYo = (int)((H-1-event.GetY())/m_scale-m_scaleYo2/m_scale-m_offsetY/m_scale+m_scaleYo);
00202
00203 if(m_scaleXo<0) m_scaleXo = 0;
00204 if(m_scaleXo>m_imageW-1) m_scaleXo = m_imageW-1;
00205 if(m_scaleYo<0) m_scaleYo = 0;
00206 if(m_scaleYo>m_imageH-1) m_scaleYo = m_imageH-1;
00207
00208 m_scaleExp = 0;
00209 m_scale = 1.0f;
00210
00211 m_scaleXo2 = event.GetX();
00212 m_scaleYo2 = H-1-event.GetY();
00213 m_offsetX = m_offsetY = 0;
00214 wxGLCanvas::Refresh();
00215 } else if(event.GetEventType() == wxEVT_MOTION) {
00216 if(event.Dragging() && event.m_leftDown) {
00217
00218 int offsetXNew = m_offsetX + (event.GetX()-m_lastX);
00219 int offsetYNew = m_offsetY - (event.GetY()-m_lastY);
00220
00221 if((m_imageW-m_scaleXo)*m_scale+m_scaleXo2+offsetXNew-10>=0 && (0-m_scaleXo)*m_scale+m_scaleXo2+offsetXNew+10<=W-1)
00222 m_offsetX = offsetXNew;
00223 if((m_imageH-m_scaleYo)*m_scale+m_scaleYo2+offsetYNew-10>=0 && (0-m_scaleYo)*m_scale+m_scaleYo2+offsetYNew+10<=H-1)
00224 m_offsetY = offsetYNew;
00225 wxGLCanvas::Refresh();
00226 }
00227 } else if(event.GetEventType() == wxEVT_MOUSEWHEEL) {
00228 if((event.GetWheelRotation() > 0 && m_scale < 4) ||
00229 (event.GetWheelRotation() < 0 && (m_scale > 1 || m_scale*m_imageW > W*0.5f || m_scale*m_imageH > H*0.5f))) {
00230
00231 m_scaleXo = (int)( event.GetX() /m_scale-m_scaleXo2/m_scale-m_offsetX/m_scale+m_scaleXo);
00232 m_scaleYo = (int)((H-1-event.GetY())/m_scale-m_scaleYo2/m_scale-m_offsetY/m_scale+m_scaleYo);
00233
00234 if(m_scaleXo < 0) m_scaleXo = 0;
00235 if(m_scaleXo > m_imageW-1) m_scaleXo = m_imageW-1;
00236 if(m_scaleYo < 0) m_scaleYo = 0;
00237 if(m_scaleYo > m_imageH-1) m_scaleYo = m_imageH-1;
00238
00239 m_scaleExp += (event.GetWheelRotation()>0?1:-1)*0.5f;
00240 m_scale = pow(2.0f, m_scaleExp);
00241
00242 m_scaleXo2 = event.GetX();
00243 m_scaleYo2 = H-1-event.GetY();
00244 m_offsetX = m_offsetY = 0;
00245 wxGLCanvas::Refresh();
00246 }
00247 } else {
00248 event.Skip();
00249 }
00250 m_lastX = event.GetX();
00251 m_lastY = event.GetY();
00252 }
00253
00254 void LuxGLViewer::Refresh(bool eraseBackground, const wxRect* rect) {
00255 m_imageChanged=true;
00256 wxGLCanvas::Refresh(eraseBackground, rect);
00257 }
00258
00259 #endif // LUX_USE_OPENGL