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 #if defined(__WXOSX_COCOA__) || defined(__WXCOCOA__) || defined(__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 #include <sstream>
00038
00039 #if defined (__WXMAC__) && !(__WXOSX_COCOA__)
00040 #define cimg_display_type 3
00041 #else
00042 #define cimg_display_type 0
00043 #endif
00044 #ifdef LUX_USE_CONFIG_H
00045 #include "config.h"
00046
00047 #ifdef PNG_FOUND
00048 #define cimg_use_png 1
00049 #endif
00050
00051 #ifdef JPEG_FOUND
00052 #define cimg_use_jpeg 1
00053 #endif
00054
00055 #ifdef TIFF_FOUND
00056 #define cimg_use_tiff 1
00057 #endif
00058
00059
00060 #else //LUX_USE_CONFIG_H
00061 #define cimg_use_png 1
00062 #define cimg_use_tiff 1
00063 #define cimg_use_jpeg 1
00064 #endif //LUX_USE_CONFIG_H
00065
00066 #define cimg_debug 0 // Disable modal window in CImg exceptions.
00067 #include "cimg.h"
00068
00069 #include "lux.h"
00070 #include "api.h"
00071 #include "wx/mstream.h"
00072
00073 using namespace lux;
00074
00075 BEGIN_EVENT_TABLE(LuxGLViewer, wxWindow)
00076 EVT_PAINT (LuxGLViewer::OnPaint)
00077 EVT_SIZE (LuxGLViewer::OnSize)
00078 EVT_MOUSE_EVENTS (LuxGLViewer::OnMouse)
00079 EVT_ERASE_BACKGROUND (LuxGLViewer::OnEraseBackground)
00080 EVT_TIMER (wxID_ANY, LuxGLViewer::OnTimer)
00081 END_EVENT_TABLE()
00082
00083 int glAttribList[] = {WX_GL_RGBA, WX_GL_DOUBLEBUFFER, 0};
00084
00085 LuxGLViewer::LuxGLViewer(wxWindow *parent, int textureW, int textureH)
00086 #if defined(__WXOSX_COCOA__) || defined(__WXCOCOA__)
00087 : wxGLCanvas(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0, wxGLCanvasName, glAttribList), wxViewerBase(), m_glContext(this), m_textureW(textureW), m_textureH(textureH){
00088 #elif defined(__WXMAC__)
00089 : wxGLCanvas(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0, wxGLCanvasName, glAttribList), wxViewerBase(), m_glContext(NULL,this,wxNullPalette,NULL), m_textureW(textureW), m_textureH(textureH){
00090 #else
00091 : wxGLCanvas(parent, wxID_ANY, glAttribList), wxViewerBase(), m_glContext(this), m_textureW(textureW), m_textureH(textureH) {
00092 #endif
00093 m_imageW = m_imageH = 0;
00094 m_tilesX = m_tilesY = m_tilesNr = 0;
00095 m_tileTextureNames = NULL;
00096 m_preScaleOffsetX = m_preScaleOffsetY = 0;
00097 m_postScaleOffsetX = m_postScaleOffsetY = 0;
00098 m_scale = 1.0f;
00099 m_scaleExp = 0;
00100 m_viewX = m_viewY = m_viewW = m_viewH = 0;
00101 m_windowW = m_windowH = m_prevWindowW = m_prevWindowH = 0;
00102 m_prevMouseX = m_prevMouseY = 0;
00103 m_logoData = NULL;
00104 m_logoDataSize = 0;
00105
00106 m_stipple = 0x00FF;
00107 m_animTimer = new wxTimer(this, ID_ANIMATIONUPDATE);
00108 m_animTimer->Start(125, wxTIMER_CONTINUOUS);
00109
00110 m_useAlpha = false;
00111 m_texturesReady = false;
00112 m_selectionChanged = false;
00113 m_refreshMarchingAntsOnly = false;
00114 m_trackMousePos = false;
00115 m_rulersEnabled = true;
00116 m_rulerSize = 13;
00117 m_rulersNormalized = false;
00118
00119 m_controlMode = PANZOOM;
00120 m_displayMode = EMPTY_VIEW;
00121
00122 SetCursor(wxCURSOR_CROSS);
00123 }
00124
00125 LuxGLViewer::~LuxGLViewer() {
00126 if(m_tileTextureNames!=NULL) delete [] m_tileTextureNames;
00127 if(m_animTimer->IsRunning())
00128 m_animTimer->Stop();
00129 delete m_animTimer;
00130 }
00131
00132 void LuxGLViewer::OnPaint(wxPaintEvent& event) {
00133 #if defined(__WXMAC__)
00134 SetCurrent();
00135 #else
00136 SetCurrent(m_glContext);
00137 #endif
00138 wxPaintDC(this);
00139
00140 if (!m_refreshMarchingAntsOnly) {
00141 glClearColor(0.5, 0.5, 0.5, 1.0);
00142 }
00143 glViewport(0, 0, m_windowW, m_windowH);
00144 glMatrixMode(GL_PROJECTION);
00145 glLoadIdentity();
00146 glOrtho(0, m_windowW, 0, m_windowH, -1, 1);
00147 if (!m_refreshMarchingAntsOnly) {
00148 glClear(GL_COLOR_BUFFER_BIT);
00149 }
00150
00151 if( !m_texturesReady && ((m_displayMode==RENDER_VIEW && ( luxStatistics("sceneIsReady") || luxStatistics("filmIsReady") )) || m_displayMode==LOGO_VIEW) ) {
00152 m_fontgen.Init();
00153 CreateTextures();
00154 m_texturesReady = true;
00155 m_imageChanged = true;
00156
00157
00158 m_preScaleOffsetX = m_preScaleOffsetY = 0;
00159 m_scale = 1.0f;
00160 m_scaleExp = 0.0f;
00161 m_postScaleOffsetX = -m_imageW/2 + m_viewW/2 + m_viewX;
00162 m_postScaleOffsetY = -m_imageH/2 + m_viewH/2 + m_viewY;
00163 }
00164
00165 glMatrixMode(GL_MODELVIEW);
00166 glLoadIdentity();
00167
00168 glTranslatef(m_postScaleOffsetX, m_postScaleOffsetY, 0.f);
00169 glScalef(m_scale, m_scale, 1.f);
00170 glTranslatef(-m_preScaleOffsetX, -m_preScaleOffsetY, 0.f);
00171
00172 if( m_texturesReady && (m_displayMode==RENDER_VIEW || m_displayMode==LOGO_VIEW) && !m_refreshMarchingAntsOnly ) {
00173
00174 glEnable(GL_TEXTURE_2D);
00175 for(int y = 0; y < m_tilesY; y++){
00176 for(int x = 0; x < m_tilesX; x++){
00177 int offX = x*m_textureW;
00178 int offY = y*m_textureH;
00179 int tileW = min(m_textureW, m_imageW - offX);
00180 int tileH = min(m_textureH, m_imageH - offY);
00181 glBindTexture (GL_TEXTURE_2D, m_tileTextureNames[y*m_tilesX+x]);
00182 if( m_imageChanged && m_displayMode==RENDER_VIEW && m_texturesReady && ( luxStatistics("sceneIsReady") || luxStatistics("filmIsReady") ) ) {
00183
00184 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
00185 glPixelStorei(GL_UNPACK_SKIP_PIXELS, offX);
00186 glPixelStorei(GL_UNPACK_SKIP_ROWS, offY);
00187 glPixelStorei(GL_UNPACK_ROW_LENGTH, m_imageW);
00188 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, tileW, tileH, GL_RGB, GL_UNSIGNED_BYTE, luxFramebuffer());
00189 }
00190 if( m_useAlpha ){
00191 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
00192 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
00193 glEnable(GL_BLEND);
00194 }else{
00195 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
00196 }
00197 glBegin(GL_QUADS);
00198 glTexCoord2f( 0.0f, 0.0f);
00199 glVertex3f( x*m_textureW + 0.0f, m_imageH - (y*m_textureH + 0.0f), 0.0f);
00200 glTexCoord2f(1.0f*tileW/m_textureW, 0.0f);
00201 glVertex3f( x*m_textureW + tileW, m_imageH - (y*m_textureH + 0.0f), 0.0f);
00202 glTexCoord2f(1.0f*tileW/m_textureW, 1.0f*tileH/m_textureH);
00203 glVertex3f( x*m_textureW + tileW, m_imageH - (y*m_textureH + tileH), 0.0f);
00204 glTexCoord2f( 0.0f, 1.0f*tileH/m_textureH);
00205 glVertex3f( x*m_textureW + 0.0f, m_imageH - (y*m_textureH + tileH), 0.0f);
00206 glEnd();
00207 if( m_useAlpha ) glDisable(GL_BLEND);
00208 }
00209 }
00210 glDisable(GL_TEXTURE_2D);
00211 m_imageChanged = false;
00212 if( m_rulersEnabled && m_displayMode==RENDER_VIEW ) DrawRulers();
00213 }
00214
00215 if (m_selection.HasSize()) {
00216
00217 DrawMarchingAnts(m_selection, 1.0, 1.0, 1.0);
00218 }
00219 if (m_highlightSel.HasSize()) {
00220
00221 DrawMarchingAnts(m_highlightSel, 1.0, 0.0, 0.0);
00222 }
00223 m_refreshMarchingAntsOnly = false;
00224
00225 glFlush();
00226 SwapBuffers();
00227 }
00228
00229 void LuxGLViewer::OnEraseBackground(wxEraseEvent &event) {
00230
00231
00232 return;
00233 }
00234
00235 void LuxGLViewer::OnSize(wxSizeEvent &event) {
00236 wxGLCanvas::OnSize(event);
00237
00238 GetClientSize(&m_windowW, &m_windowH);
00239 if(m_rulersEnabled){
00240 m_viewX = m_rulerSize;
00241 m_viewY = 0;
00242 m_viewW = m_windowW-m_rulerSize;
00243 if(m_viewW<0) m_viewW = 0;
00244 m_viewH = m_windowH-m_rulerSize;
00245 if(m_viewH<0) m_viewH = 0;
00246 }else{
00247 m_viewX = 0;
00248 m_viewY = 0;
00249 m_viewW = m_windowW;
00250 m_viewH = m_windowH;
00251 }
00252
00253 if(m_texturesReady) {
00254
00255 m_postScaleOffsetX += (m_windowW - m_prevWindowW)/2;
00256 m_postScaleOffsetY += (m_windowH - m_prevWindowH)/2;
00257
00258 Point p0 = TransformPoint(Point(0, 0));
00259 Point p1 = TransformPoint(Point(m_imageW, m_imageH));
00260 if(p1.x-30<0) m_postScaleOffsetX = 30 -(p1.x - m_postScaleOffsetX);
00261 else if(p0.x+30>m_windowW-1) m_postScaleOffsetX = m_windowW-1 -30 -(p0.x - m_postScaleOffsetX);
00262 if(p1.y-30<0) m_postScaleOffsetY = 30 -(p1.y - m_postScaleOffsetY);
00263 else if(p0.y+30>m_windowH-1) m_postScaleOffsetY = m_windowH-1 -30 -(p0.y - m_postScaleOffsetY);
00264 }
00265 m_prevWindowW = m_windowW;
00266 m_prevWindowH = m_windowH;
00267
00268 Refresh();
00269 }
00270
00271 void LuxGLViewer::OnMouse(wxMouseEvent &event) {
00272 if( !(m_displayMode==RENDER_VIEW && m_texturesReady) ) {
00273 event.Skip();
00274 return;
00275 }
00276 if(m_controlMode == PANZOOM) {
00277 if(event.GetEventType() == wxEVT_LEFT_DOWN) {
00278 SetCursor(wxCURSOR_HAND);
00279 event.Skip();
00280 } else if(event.GetEventType() == wxEVT_LEFT_UP) {
00281 SetCursor(wxCURSOR_CROSS);
00282 } else if(event.GetEventType() == wxEVT_MIDDLE_DOWN) {
00283 m_preScaleOffsetX = 0;
00284 m_preScaleOffsetY = 0;
00285 m_scale = min(m_viewW/(float)m_imageW, m_viewH/(float)m_imageH);
00286 if(m_scale<=0) m_scale = 1;
00287 m_scaleExp = floor(log((float)m_scale)/log(2.0f)*2+0.5f)/2;
00288 m_postScaleOffsetX = (int)((m_viewW - m_imageW*m_scale)/2 + 0.5f) + m_viewX;
00289 m_postScaleOffsetY = (int)((m_viewH - m_imageH*m_scale)/2 + 0.5f) + m_viewY;
00290 Refresh();
00291 } else if(event.GetEventType() == wxEVT_RIGHT_DOWN) {
00292
00293 Point p = InverseTransformPoint(Point(event.GetX(), m_windowH-1 -event.GetY()));
00294 m_preScaleOffsetX = p.x;
00295 m_preScaleOffsetY = p.y;
00296
00297 if(m_preScaleOffsetX<0) m_preScaleOffsetX = 0;
00298 if(m_preScaleOffsetX>m_imageW-1) m_preScaleOffsetX = m_imageW-1;
00299 if(m_preScaleOffsetY<0) m_preScaleOffsetY = 0;
00300 if(m_preScaleOffsetY>m_imageH-1) m_preScaleOffsetY = m_imageH-1;
00301
00302 m_scaleExp = 0;
00303 m_scale = 1.0f;
00304
00305 m_postScaleOffsetX = event.GetX();
00306 m_postScaleOffsetY = m_windowH-1 - event.GetY();
00307 Refresh();
00308 } else if(event.GetEventType() == wxEVT_MOTION) {
00309 if(event.Dragging() && event.m_leftDown) {
00310
00311 int newOffsetX = m_postScaleOffsetX + (event.GetX()-m_prevMouseX);
00312 int newOffsetY = m_postScaleOffsetY - (event.GetY()-m_prevMouseY);
00313
00314 Point p0 = TransformPoint(Point(0, 0));
00315 Point p1 = TransformPoint(Point(m_imageW, m_imageH));
00316 if( p1.x -m_postScaleOffsetX +newOffsetX -30 >= 0 &&
00317 p0.x -m_postScaleOffsetX +newOffsetX +30 <= m_windowW-1)
00318 m_postScaleOffsetX = newOffsetX;
00319 if( p1.y -m_postScaleOffsetY +newOffsetY -30 >= 0 &&
00320 p0.y -m_postScaleOffsetY +newOffsetY +30 <= m_windowH-1)
00321 m_postScaleOffsetY = newOffsetY;
00322 if(!m_rulersEnabled) Refresh();
00323 }
00324 } else if(event.GetEventType() == wxEVT_MOUSEWHEEL) {
00325 if( (event.GetWheelRotation() > 0 && m_scale < 8) ||
00326 (event.GetWheelRotation() < 0 && (m_scale > 1 || m_scale*m_imageW > m_windowW*0.5f || m_scale*m_imageH > m_windowH*0.5f))) {
00327
00328 Point p = InverseTransformPoint(Point(event.GetX(), m_windowH-1 -event.GetY()));
00329 m_preScaleOffsetX = p.x;
00330 m_preScaleOffsetY = p.y;
00331
00332 if(m_preScaleOffsetX < 0) m_preScaleOffsetX = 0;
00333 if(m_preScaleOffsetX > m_imageW-1) m_preScaleOffsetX = m_imageW-1;
00334 if(m_preScaleOffsetY < 0) m_preScaleOffsetY = 0;
00335 if(m_preScaleOffsetY > m_imageH-1) m_preScaleOffsetY = m_imageH-1;
00336
00337 m_scaleExp += (event.GetWheelRotation()>0?1:-1)*0.5f;
00338 m_scale = pow(2.0f, m_scaleExp);
00339
00340 m_postScaleOffsetX = event.GetX();
00341 m_postScaleOffsetY = m_windowH-1 - event.GetY();
00342 Refresh();
00343 }
00344 } else {
00345 event.Skip();
00346 }
00347 } else if(m_controlMode == SELECTION) {
00348 if(event.GetEventType() == wxEVT_LEFT_DOWN) {
00349 Point p = InverseTransformPoint(Point(event.GetX(), m_windowH-1 -event.GetY()));
00350 m_selection.SetBounds(p.x, p.x, p.y, p.y);
00351 } else if(event.GetEventType() == wxEVT_LEFT_UP) {
00352 boost::shared_ptr<wxViewerSelection> selection(new wxViewerSelection(m_selection));
00353 Point p = InverseTransformPoint(Point(event.GetX(), m_windowH-1 -event.GetY()));
00354 selection->SetCorner2(p.x, p.y);
00355 wxViewerEvent viewerEvent(selection, wxEVT_LUX_VIEWER_SELECTION);
00356 GetEventHandler()->AddPendingEvent(viewerEvent);
00357 } else if(event.GetEventType() == wxEVT_MOTION) {
00358 if(event.Dragging() && event.m_leftDown) {
00359 int oldX, oldY;
00360 m_selection.GetCorner2(oldX, oldY);
00361 Point p = InverseTransformPoint(Point(event.GetX(), m_windowH-1 -event.GetY()));
00362 if ((p.x != oldX) || (p.y != oldY)) {
00363 m_selection.SetCorner2(p.x, p.y);
00364 m_selectionChanged = true;
00365 }
00366 }
00367 }
00368 }
00369
00370 m_prevMouseX = event.GetX();
00371 m_prevMouseY = event.GetY();
00372 if(event.GetEventType() == wxEVT_ENTER_WINDOW){
00373 m_trackMousePos = true;
00374 } else if(event.GetEventType() == wxEVT_LEAVE_WINDOW){
00375 m_trackMousePos = false;
00376 if(m_rulersEnabled) Refresh();
00377 } else if(event.GetEventType() == wxEVT_MOTION){
00378 m_trackMousePos = true;
00379 if(m_rulersEnabled) Refresh();
00380 }
00381 }
00382
00383 wxWindow* LuxGLViewer::GetWindow() {
00384 return this;
00385 }
00386
00387 wxViewerSelection LuxGLViewer::GetSelection() {
00388 return m_selection;
00389 }
00390
00391 void LuxGLViewer::SetMode(wxViewerMode mode) {
00392 if( mode==EMPTY_VIEW ){
00393 DeleteTextures();
00394 m_texturesReady = false;
00395 m_displayMode = EMPTY_VIEW;
00396 Refresh();
00397 }else if( mode==LOGO_VIEW ){
00398 if(m_displayMode!=LOGO_VIEW && m_logoData!=NULL){
00399 DeleteTextures();
00400 m_texturesReady = false;
00401 m_displayMode = LOGO_VIEW;
00402 Refresh();
00403 }
00404 }else if( mode==RENDER_VIEW ){
00405 if(m_displayMode!=RENDER_VIEW){
00406 DeleteTextures();
00407 m_texturesReady = false;
00408 m_displayMode = RENDER_VIEW;
00409 Refresh();
00410 }
00411 }else{
00412 if( mode!=m_controlMode ){
00413 m_controlMode = mode;
00414 Refresh();
00415 }
00416 }
00417
00418 }
00419
00420 void LuxGLViewer::SetRulersEnabled(bool enabled, bool normalized){
00421 m_rulersEnabled = enabled;
00422 m_rulersNormalized = normalized;
00423 if(m_rulersEnabled){
00424 m_viewX = m_rulerSize;
00425 m_viewY = 0;
00426 m_viewW = m_windowW-m_rulerSize;
00427 if(m_viewW<0) m_viewW = 0;
00428 m_viewH = m_windowH-m_rulerSize;
00429 if(m_viewH<0) m_viewH = 0;
00430 }else{
00431 m_viewX = 0;
00432 m_viewY = 0;
00433 m_viewW = m_windowW;
00434 m_viewH = m_windowH;
00435 }
00436 Refresh();
00437 }
00438
00439 void LuxGLViewer::SetZoom(const wxViewerSelection *selection) {
00440 int x1, x2, y1, y2;
00441 selection->GetBounds(x1,x2,y1,y2);
00442 int selMaxX = min(m_imageW, max(x1, x2));
00443 int selMaxY = min(m_imageH, max(y1, y2));
00444 int selMinX = max(0, min(x1, x2));
00445 int selMinY = max(0, min(y1, y2));
00446 float exactScale = min((float)m_viewW/(selMaxX-selMinX), (float)m_viewH/(selMaxY-selMinY));
00447
00448 if(isinf(exactScale))
00449 exactScale = min(m_viewW, m_viewH);
00450
00451
00452 m_preScaleOffsetX = (selMaxX + selMinX)/2.0;
00453 m_preScaleOffsetY = (selMaxY + selMinY)/2.0;
00454 m_scaleExp = log(exactScale)/log(2.0);
00455 m_scale = exactScale;
00456 m_postScaleOffsetX = m_viewW/2.0 + m_viewX;
00457 m_postScaleOffsetY = m_viewH/2.0-1 + m_viewY;
00458 Refresh();
00459 }
00460
00461 void LuxGLViewer::SetSelection(const wxViewerSelection *selection) {
00462 if (!selection) {
00463 m_selection.Clear();
00464 } else {
00465 m_selection = *selection;
00466 }
00467 Refresh();
00468 }
00469
00470 void LuxGLViewer::SetHighlight(const wxViewerSelection *selection) {
00471 if (!selection) {
00472 m_highlightSel.Clear();
00473 } else {
00474 m_highlightSel = *selection;
00475 }
00476 Refresh();
00477 }
00478
00479 void LuxGLViewer::Reload() {
00480 m_imageChanged = true;
00481 Refresh();
00482 }
00483
00484 void LuxGLViewer::Reset() {
00485 DeleteTextures();
00486 m_texturesReady = false;
00487 Refresh();
00488 }
00489
00490 void LuxGLViewer::OnTimer(wxTimerEvent &event) {
00491 if (!m_selection.HasSize() && !m_highlightSel.HasSize()) return;
00492
00493 m_stipple = ((m_stipple >> 15) | (m_stipple << 1)) & 0xFFFF;
00494 if (!m_selectionChanged) {
00495 m_refreshMarchingAntsOnly = true;
00496 }
00497 m_selectionChanged = false;
00498 this->Refresh();
00499 }
00500
00501 void LuxGLViewer::CreateTextures(){
00502 if( m_texturesReady ) return;
00503 unsigned char* logo_buf = NULL;
00504
00505 if( m_displayMode==RENDER_VIEW ){
00506 m_useAlpha = false;
00507 m_imageW = luxStatistics("filmXres");
00508 m_imageH = luxStatistics("filmYres");
00509 }else{
00510 m_useAlpha = true;
00511 wxMemoryInputStream stream( m_logoData, m_logoDataSize );
00512 wxImage logo_img( stream, wxBITMAP_TYPE_ANY, -1 );
00513 m_imageW = logo_img.GetWidth();
00514 m_imageH = logo_img.GetHeight();
00515 logo_buf = new unsigned char[m_imageW*m_imageH];
00516 for(int i=0;i<m_imageW*m_imageH;i++)
00517 logo_buf[i] = 255-logo_img.GetData()[i*3+0];
00518 }
00519
00520 m_tilesX = ceil((float)m_imageW/m_textureW);
00521 m_tilesY = ceil((float)m_imageH/m_textureH);
00522 m_tilesNr = m_tilesX*m_tilesY;
00523
00524 glEnable(GL_TEXTURE_2D);
00525 m_tileTextureNames = new unsigned int[m_tilesNr];
00526 glGenTextures(m_tilesNr, (GLuint*) m_tileTextureNames);
00527 if( m_displayMode==RENDER_VIEW ){
00528 for(int i = 0; i < m_tilesNr; i++){
00529 glBindTexture(GL_TEXTURE_2D, m_tileTextureNames[i]);
00530 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
00531 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
00532 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
00533 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
00534 glTexImage2D(GL_TEXTURE_2D, 0, m_useAlpha?GL_RGBA:GL_RGB, m_textureW, m_textureH, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
00535 }
00536 }else{
00537
00538 unsigned char *tileImg = new unsigned char[4*m_textureW*m_textureH];
00539
00540 for (int i = 0; i < m_textureH; i++) {
00541 for (int j = 0; j < m_textureW; j++) {
00542
00543 for (int k = 0; k < 3; k++)
00544 tileImg[(i*m_textureW+j)*4+k] = 255;
00545 }
00546 }
00547
00548 for(int y = 0; y < m_tilesY; y++){
00549 for(int x = 0; x < m_tilesX; x++){
00550 int offX = x*m_textureW;
00551 int offY = y*m_textureH;
00552 int tileW = min(m_textureW, m_imageW - offX);
00553 int tileH = min(m_textureH, m_imageH - offY);
00554
00555 glBindTexture (GL_TEXTURE_2D, m_tileTextureNames[y*m_tilesX+x]);
00556 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
00557 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
00558 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
00559 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
00560 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
00561
00562 for (int i = 0; i < tileH; i++) {
00563 for (int j = 0; j < tileW; j++) {
00564
00565
00566 tileImg[(i*tileW+j)*4+3] = logo_buf[(offY+i)*m_imageW+(offX+j)]/16;
00567 }
00568 }
00569
00570 glTexImage2D(GL_TEXTURE_2D, 0, m_useAlpha?GL_RGBA:GL_RGB, m_textureW, m_textureH, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
00571
00572 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, tileW, tileH, GL_RGBA, GL_UNSIGNED_BYTE, tileImg);
00573 }
00574 }
00575
00576 delete[] tileImg;
00577 }
00578
00579 glDisable(GL_TEXTURE_2D);
00580 if(logo_buf!=NULL) delete [] logo_buf;
00581
00582 }
00583
00584 void LuxGLViewer::DeleteTextures() {
00585 if(m_tilesNr>0 && m_tileTextureNames!=NULL) glDeleteTextures(m_tilesNr, (GLuint*) m_tileTextureNames);
00586 if(m_tileTextureNames!=NULL) delete [] m_tileTextureNames;
00587 m_tileTextureNames = NULL;
00588 m_tilesNr = m_tilesX = m_tilesY = 0;
00589 }
00590
00591 lux::Point LuxGLViewer::TransformPoint(const Point &p){
00592 return Point( (p.x - m_preScaleOffsetX)*m_scale + m_postScaleOffsetX,
00593 (p.y - m_preScaleOffsetY)*m_scale + m_postScaleOffsetY);
00594 }
00595
00596 lux::Point LuxGLViewer::InverseTransformPoint(const Point &p){
00597 return Point( (p.x - m_postScaleOffsetX)/m_scale + m_preScaleOffsetX,
00598 (p.y - m_postScaleOffsetY)/m_scale + m_preScaleOffsetY);
00599 }
00600
00601 void LuxGLViewer::DrawMarchingAnts(const wxViewerSelection &selection, float red, float green, float blue) {
00602 int x1, x2, y1, y2;
00603 selection.GetBounds(x1, x2, y1, y2);
00604
00605 glEnable(GL_LINE_STIPPLE);
00606
00607 glLineWidth(2.0);
00608
00609 glLineStipple(1, m_stipple);
00610 glBegin(GL_LINE_STRIP);
00611 glColor3f(0.0, 0.0, 0.0);
00612 glVertex3i(x1, y1, 0.0);
00613 glVertex3i(x1, y2, 0.0);
00614 glVertex3i(x2, y2, 0.0);
00615 glVertex3i(x2, y1, 0.0);
00616 glVertex3i(x1, y1, 0.0);
00617 glEnd();
00618
00619 glLineStipple(1, ~m_stipple);
00620 glBegin(GL_LINE_STRIP);
00621 glColor3f(red, green, blue);
00622 glVertex3i(x1, y1, 0.0);
00623 glVertex3i(x1, y2, 0.0);
00624 glVertex3i(x2, y2, 0.0);
00625 glVertex3i(x2, y1, 0.0);
00626 glVertex3i(x1, y1, 0.0);
00627 glEnd();
00628
00629 glDisable(GL_LINE_STIPPLE);
00630 }
00631
00632 void LuxGLViewer::DrawRulers(){
00633 float tickSpacing;
00634 float tickDist;
00635
00636 if(m_rulersNormalized){
00637 float unitLength=max(m_imageW,m_imageH);
00638 tickSpacing = 1.f/10;
00639 tickDist = tickSpacing*unitLength*m_scale;
00640 while(tickDist>30){
00641 tickSpacing /= 2;
00642 if(tickSpacing*unitLength*m_scale>30)
00643 tickSpacing /= 5;
00644 tickDist = tickSpacing*unitLength*m_scale;
00645 }
00646 }else{
00647 tickSpacing = 10;
00648 tickDist = tickSpacing*m_scale;
00649 while((tickDist<5 || tickDist>15) && tickSpacing>1){
00650 if(tickDist<5) tickSpacing *= 2;
00651 else tickSpacing = (int)tickSpacing/2;
00652 if(tickSpacing<1) tickSpacing = 1;
00653 tickDist = tickSpacing*m_scale;
00654 }
00655 }
00656
00657 Point p0 = TransformPoint(Point(0, 0));
00658 float x_offset=p0.x;
00659 float y_offset=p0.y;
00660
00661 glPushMatrix();
00662 glLoadIdentity();
00663 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
00664 glEnable(GL_BLEND);
00665
00666
00667 glColor4f(0.2f, 0.2f, 0.2f, 0.7f);
00668 glBegin(GL_QUADS);
00669 glVertex2f( 0.0f, m_windowH-m_rulerSize );
00670 glVertex2f( m_windowW, m_windowH-m_rulerSize );
00671 glVertex2f( m_windowW, m_windowH );
00672 glVertex2f( 0.0f, m_windowH );
00673
00674 glVertex2f( 0.0f, 0.0f );
00675 glVertex2f( m_rulerSize, 0.0f );
00676 glVertex2f( m_rulerSize, m_windowH );
00677 glVertex2f( 0.0f, m_windowH );
00678 glEnd();
00679
00680
00681 glLineWidth(1);
00682 glColor4f(0.2f, 0.2f, 0.2f, 0.7f);
00683 glBegin(GL_LINES);
00684 glVertex2f( 0.0f, m_windowH-m_rulerSize + 0.5f );
00685 glVertex2f( m_windowW, m_windowH-m_rulerSize + 0.5f );
00686
00687 glVertex2f( m_rulerSize - 0.5f, 0.0f );
00688 glVertex2f( m_rulerSize - 0.5f, m_windowH );
00689 glEnd();
00690
00691
00692
00693
00694 int tick_length, count;
00695 float x_start_offset;
00696 if(x_offset>=0){
00697 count = 0;
00698 x_start_offset = x_offset;
00699 }else{
00700 count = floor(-x_offset/tickDist);
00701 x_start_offset = fmod(x_offset, tickDist);
00702 }
00703 glScissor(m_rulerSize, m_windowH-m_rulerSize, m_windowW-m_rulerSize, m_rulerSize);
00704 glEnable(GL_SCISSOR_TEST);
00705 glLineWidth(1);
00706 glColor3f(0.8f, 0.8f, 0.8f);
00707 glBegin(GL_QUADS);
00708 for(float x=x_start_offset;x<m_windowW;x+=tickDist){
00709 if( count%10==0 ){
00710 tick_length=m_rulerSize-1;
00711 }else if( count%5==0 ){
00712 tick_length=m_rulerSize/2-1;
00713 }else{
00714 tick_length=m_rulerSize/4-1;
00715 }
00716 count++;
00717 glVertex2f( x + 0.0f, m_windowH-m_rulerSize );
00718 glVertex2f( x + 1.0f, m_windowH-m_rulerSize );
00719 glVertex2f( x + 1.0f, m_windowH-m_rulerSize+tick_length );
00720 glVertex2f( x + 0.0f, m_windowH-m_rulerSize+tick_length );
00721 }
00722 glEnd();
00723
00724 if(m_trackMousePos){
00725 glColor4f(1.0f, 1.0f, 1.0f, 0.7f);
00726 glBegin(GL_TRIANGLES);
00727 glVertex2f( m_prevMouseX + 0.5f, m_windowH-m_rulerSize );
00728 glVertex2f( m_prevMouseX + 0.5f - 5.0f, m_windowH-m_rulerSize + 5.0f );
00729 glVertex2f( m_prevMouseX + 0.5f + 5.0f, m_windowH-m_rulerSize + 5.0f );
00730 glEnd();
00731 glBegin(GL_QUADS);
00732 glVertex2f( m_prevMouseX - 4.0f, m_windowH-m_rulerSize + 5.0f );
00733 glVertex2f( m_prevMouseX + 5.0f, m_windowH-m_rulerSize + 5.0f );
00734 glVertex2f( m_prevMouseX + 5.0f, m_windowH-m_rulerSize + 6.0f );
00735 glVertex2f( m_prevMouseX - 4.0f, m_windowH-m_rulerSize + 6.0f );
00736 glEnd();
00737 }
00738 glColor3f(1.0f, 1.0f, 1.0f);
00739 glDisable(GL_BLEND);
00740
00741
00742 if(x_offset>=0){
00743 count = 0;
00744 x_start_offset = x_offset;
00745 }else{
00746 count = floor(-x_offset/(tickDist*10))*10;
00747 x_start_offset = fmod(x_offset, tickDist*10);
00748 }
00749 std::ostringstream ss;
00750 for(float x=x_start_offset;x<m_windowW;x+=tickDist*10){
00751 ss.str("");
00752 ss<<count*tickSpacing;
00753 m_fontgen.DrawText(ss.str().c_str(), x+3, m_windowH-10);
00754 count+=10;
00755 }
00756 glDisable(GL_SCISSOR_TEST);
00757
00758
00759
00760
00761 float y_start_offset;
00762 if(y_offset+m_imageH*m_scale<=m_windowH){
00763 count = 0;
00764 y_start_offset = y_offset+m_imageH*m_scale;
00765 }else{
00766 count = floor((y_offset+m_imageH*m_scale-m_windowH)/tickDist);
00767 y_start_offset = fmod(y_offset+m_imageH*m_scale-m_windowH, tickDist) + m_windowH;
00768 }
00769 glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
00770 glEnable(GL_BLEND);
00771 glScissor(0, 0, m_rulerSize, m_windowH-m_rulerSize);
00772 glEnable(GL_SCISSOR_TEST);
00773 glLineWidth(1);
00774 glColor3f(0.8f, 0.8f, 0.8f);
00775 glBegin(GL_QUADS);
00776 for(float y=y_start_offset;y>0;y-=tickDist){
00777 if( count%10==0 ){
00778 tick_length=m_rulerSize-1;
00779 }else if( count%5==0 ){
00780 tick_length=m_rulerSize/2-1;
00781 }else{
00782 tick_length=m_rulerSize/4-1;
00783 }
00784 count++;
00785 glVertex2f( m_rulerSize-tick_length, y - 1.0f );
00786 glVertex2f( m_rulerSize, y - 1.0f );
00787 glVertex2f( m_rulerSize, y - 0.0f );
00788 glVertex2f( m_rulerSize-tick_length, y - 0.0f );
00789 }
00790 glEnd();
00791
00792 if(m_trackMousePos){
00793 glColor4f(1.0f, 1.0f, 1.0f, 0.7f);
00794 glBegin(GL_TRIANGLES);
00795 glVertex2f( m_rulerSize, m_windowH - m_prevMouseY - 0.5f );
00796 glVertex2f( m_rulerSize - 5.0f, m_windowH - m_prevMouseY - 0.5f + 5.0f );
00797 glVertex2f( m_rulerSize - 5.0f, m_windowH - m_prevMouseY - 0.5f - 5.0f );
00798 glEnd();
00799 glBegin(GL_QUADS);
00800 glVertex2f( m_rulerSize - 6.0f, m_windowH - m_prevMouseY - 5.0f );
00801 glVertex2f( m_rulerSize - 5.0f, m_windowH - m_prevMouseY - 5.0f );
00802 glVertex2f( m_rulerSize - 5.0f, m_windowH - m_prevMouseY + 4.0f );
00803 glVertex2f( m_rulerSize - 6.0f, m_windowH - m_prevMouseY + 4.0f );
00804 glEnd();
00805 }
00806 glColor3f(1.0f, 1.0f, 1.0f);
00807 glDisable(GL_BLEND);
00808
00809
00810 if(y_offset+m_imageH*m_scale<=m_windowH){
00811 count = 0;
00812 y_start_offset = y_offset+m_imageH*m_scale;
00813 }else{
00814 count = floor((y_offset+m_imageH*m_scale-m_windowH)/(tickDist*10))*10;
00815 y_start_offset = fmod(y_offset+m_imageH*m_scale-m_windowH, tickDist*10) + m_windowH;
00816 }
00817
00818 for(float y=y_start_offset;y>0;y-=tickDist*10){
00819 ss.str("");
00820 ss<<count*tickSpacing;
00821 m_fontgen.DrawText(ss.str().c_str(), 10, y-2, true);
00822 count+=10;
00823 }
00824 glDisable(GL_SCISSOR_TEST);
00825
00826 glPopMatrix();
00827 }
00828
00829 LuxGLViewer::FontGenerator::FontGenerator(){
00830 isInitialized = false;
00831 }
00832
00833 void LuxGLViewer::FontGenerator::Init(){
00834 if(isInitialized) return;
00835 m_texW=512;
00836 m_texH=16;
00837 glEnable(GL_TEXTURE_2D);
00838 glGenTextures(1, (GLuint*)&m_texName);
00839 glBindTexture(GL_TEXTURE_2D, m_texName);
00840 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
00841 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
00842 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
00843 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
00844 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_texW, m_texH, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
00845 glDisable(GL_TEXTURE_2D);
00846 isInitialized = true;
00847 }
00848
00849 LuxGLViewer::FontGenerator::~FontGenerator(){
00850 }
00851
00852 void LuxGLViewer::FontGenerator::DrawText(const char* text, int x, int y, bool vertical){
00853 if(!isInitialized) return;
00854
00855 cimg_library::CImg<unsigned char> img(1,1,0,1);
00856 unsigned char fg[] = {255};
00857 unsigned char bg[] = {0};
00858 img.draw_text(text,0,0,fg,bg);
00859 int w = img.width;
00860 int h = img.height;
00861 if(w==0 || w>(int)m_texW || h==0 || h>(int)m_texH) return;
00862
00863 glEnable(GL_TEXTURE_2D);
00864 glBindTexture(GL_TEXTURE_2D, m_texName);
00865 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
00866 glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
00867 glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
00868 glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
00869 glPixelTransferf( GL_RED_BIAS, 1.0f );
00870 glPixelTransferf( GL_GREEN_BIAS, 1.0f );
00871 glPixelTransferf( GL_BLUE_BIAS, 1.0f );
00872
00873 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, GL_ALPHA, GL_UNSIGNED_BYTE, img.ptr());
00874
00875 glPixelTransferf( GL_RED_BIAS, 0.0f );
00876 glPixelTransferf( GL_GREEN_BIAS, 0.0f );
00877 glPixelTransferf( GL_BLUE_BIAS, 0.0f );
00878
00879 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
00880 glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
00881 glEnable(GL_BLEND);
00882 glBegin(GL_QUADS);
00883 if(!vertical){
00884 glTexCoord2f( 0.0f, 1.0f*h/m_texH ); glVertex2f( x, y );
00885 glTexCoord2f( 1.0f*w/m_texW, 1.0f*h/m_texH ); glVertex2f( x + w, y );
00886 glTexCoord2f( 1.0f*w/m_texW, 0.0f ); glVertex2f( x + w, y + h );
00887 glTexCoord2f( 0.0f, 0.0f ); glVertex2f( x, y + h );
00888 }else{
00889 glTexCoord2f( 0.0f, 1.0f*h/m_texH ); glVertex2f( x, y - w );
00890 glTexCoord2f( 1.0f*w/m_texW, 1.0f*h/m_texH ); glVertex2f( x, y );
00891 glTexCoord2f( 1.0f*w/m_texW, 0.0f ); glVertex2f( x - h, y );
00892 glTexCoord2f( 0.0f, 0.0f) ; glVertex2f( x - h, y - w );
00893 }
00894 glEnd();
00895 glDisable(GL_BLEND);
00896 glDisable(GL_TEXTURE_2D);
00897
00898 }
00899
00900 #endif // LUX_USE_OPENGL