00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include "glcanvas.h"
00026 #include "app.h"
00027 #include "texture.h"
00028 #include "map.h"
00029 #include <wx/tooltip.h>
00030 #include <stdio.h>
00031 #include <math.h>
00032
00033 extern ofstream logFile;
00034
00035 namespace WDS
00036 {
00037
00038
00039 static int g_aGlyphWidths[256] =
00040 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00041 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00042 4, 5, 6, 9, 9, 14, 11, 3, 5, 5, 6, 9, 4, 5, 4, 4,
00043 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 4, 4, 9, 9, 9, 9,
00044 16, 11, 11, 12, 12, 11, 10, 12, 11, 3, 8, 11, 9, 13, 11, 12,
00045 11, 12, 11, 11, 9, 11, 11, 15, 11, 9, 9, 4, 4, 4, 7, 9,
00046 5, 9, 9, 8, 9, 9, 4, 9, 8, 4, 3, 8, 3, 13, 8, 9,
00047 9, 9, 5, 8, 4, 8, 7, 11, 7, 7, 7, 5, 3, 5, 9, 12,
00048 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
00049 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
00050 4, 5, 9, 9, 9, 9, 3, 9, 5, 12, 5, 9, 9, 5, 12, 9,
00051 6, 9, 5, 5, 5, 9, 9, 4, 5, 5, 5, 9, 13, 13, 13, 10,
00052 11, 11, 11, 11, 11, 11, 16, 12, 11, 11, 11, 11, 3, 3, 3, 3,
00053 12, 11, 12, 12, 12, 12, 12, 9, 12, 11, 11, 11, 11, 9, 11, 9,
00054 9, 9, 9, 9, 9, 9, 14, 8, 9, 9, 9, 9, 3, 3, 3, 3,
00055 9, 8, 9, 9, 9, 9, 9, 9, 9, 8, 8, 8, 8, 7, 9, 7
00056 };
00057
00058
00059 BEGIN_EVENT_TABLE(CGLCanvas, wxGLCanvas)
00060 EVT_SIZE(CGLCanvas::OnSize)
00061 EVT_PAINT(CGLCanvas::OnPaint)
00062 EVT_ERASE_BACKGROUND(CGLCanvas::OnEraseBackground)
00063 EVT_KEY_DOWN( CGLCanvas::OnKeyDown )
00064 EVT_MOTION( CGLCanvas::OnMouseMove )
00065 EVT_LEFT_DOWN( CGLCanvas::OnLButtonDown )
00066 EVT_LEFT_UP( CGLCanvas::OnLButtonUp )
00067 EVT_SCROLLWIN( CGLCanvas::OnScrollBar )
00068 EVT_TIMER( 1, CGLCanvas::OnTimer )
00069 END_EVENT_TABLE()
00070
00071
00072
00073
00074
00075 CGLCanvas::CGLCanvas( wxWindow *parent) : wxGLCanvas(parent, (wxGLCanvas*) NULL ),
00076 m_timer(this, 1), m_pFont(0)
00077 {
00078 m_XPos = 0;
00079 m_YPos = 0;
00080 m_fZoom = 1.0f;
00081
00082 m_Width = 0;
00083 m_Height = 0;
00084
00085 #ifdef SHOW_TOOLTIPS
00086 SetToolTip( "Text..." );
00087 #endif
00088 }
00089
00090 CGLCanvas::~CGLCanvas( )
00091 {
00092
00093 DeleteTexture( m_pFont );
00094
00095
00096 TexMap::iterator i = m_aTextures.begin();
00097 for( ; i!=m_aTextures.end(); i++ )
00098 {
00099 CTexture *pTex = i->second;
00100 logFile << "Texture '" << pTex->GetName() << "' still has a RefCount of "
00101 << pTex->GetRefCount() << "." << endl;
00102 delete pTex;
00103 }
00104 m_aTextures.clear();
00105 }
00106
00107
00108
00109
00110
00111 void CGLCanvas::Init()
00112 {
00113 if (!GetContext())
00114 {
00115 cout << "***ERROR: GLCanvas::Init: Kein OpenGL Kontext!" << endl;
00116 return;
00117 }
00118 SetCurrent();
00119
00120
00121 GetClientSize(&m_Width, &m_Height);
00122 glViewport(0, 0, (GLint) m_Width, (GLint) m_Height);
00123
00124
00125 glMatrixMode( GL_PROJECTION );
00126 glLoadIdentity();
00127 glOrtho( 0.0f, m_Width, m_Height, 0.0f, 0.0f, 10.0f);
00128 glMatrixMode( GL_MODELVIEW );
00129
00130
00131 glEnable(GL_TEXTURE_2D);
00132
00133 glDisable( GL_DEPTH_TEST );
00134 glCullFace( GL_BACK );
00135
00136
00137 glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
00138
00139
00140 glEnable( GL_ALPHA_TEST );
00141 glAlphaFunc(GL_GREATER, 0.7f);
00142
00143
00144
00145 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
00146
00147
00148 m_pFont = LoadTexture( "data/font.png", false );
00149
00150
00151 glClear( GL_COLOR_BUFFER_BIT );
00152 SwapBuffers();
00153 }
00154
00155 void CGLCanvas::UpdateView( )
00156 {
00157 ClampView( );
00158 Refresh( );
00159 }
00160
00161 void CGLCanvas::OnPaint( wxPaintEvent& event )
00162 {
00163 wxPaintDC dc(this);
00164 if (!GetContext())
00165 {
00166 cout << "***ERROR: GlCanvas::OnPaint: Kein Kontext" << endl;
00167 return;
00168 }
00169 SetCurrent();
00170
00171
00172 glClear( GL_COLOR_BUFFER_BIT );
00173 glLoadIdentity();
00174
00175
00176 CMap *pMap = wxGetApp().GetMap();
00177
00178 if( pMap )
00179 {
00180 glTranslatef( -m_XPos, -m_YPos, 0.0f );
00181 glScalef( m_fZoom, m_fZoom, 1.0f );
00182
00183
00184 pMap->Draw();
00185
00186
00187
00188
00189
00190
00191 Rect rcMap = pMap->GetBounds();
00192 this->DrawRect( rcMap, 1.0f, 0.0f, 0.0f );
00193 }
00194 else
00195 {
00196
00197 wxString strNoMap = "No map loaded!";
00198
00199 wxRect rcClient = GetClientRect( );
00200 wxPoint ptExtent = GetTextExtent( strNoMap.c_str() );
00201
00202 int x = rcClient.GetRight() / 2 - ptExtent.x / 2;
00203 int y = rcClient.GetBottom() / 2 - ptExtent.y / 2;
00204
00205
00206 DrawText( x, y, 1.0f, 0.0f, 0.0f, 1.0f, strNoMap.c_str() );
00207 }
00208
00209 glFlush();
00210 SwapBuffers();
00211 }
00212
00213 void CGLCanvas::OnSize( wxSizeEvent &event )
00214 {
00215 if (!GetContext())
00216 {
00217
00218 return;
00219 }
00220 SetCurrent();
00221
00222
00223 m_Width = event.GetSize().GetWidth();
00224 m_Height = event.GetSize().GetHeight();
00225
00226 glViewport(0, 0, (GLint) m_Width, (GLint) m_Height);
00227
00228
00229 glMatrixMode( GL_PROJECTION );
00230 glLoadIdentity();
00231 glOrtho( 0.0f, m_Width, m_Height, 0.0f, 0.0f, 10.0f);
00232 glMatrixMode( GL_MODELVIEW );
00233
00234 ClampView();
00235
00236
00237
00238 wxGLCanvas::OnSize(event);
00239
00240
00241 m_timer.Start( 100, true );
00242 }
00243
00244 void CGLCanvas::OnTimer( wxTimerEvent &event)
00245 {
00246
00247 Refresh();
00248 }
00249
00250 void CGLCanvas::OnEraseBackground(wxEraseEvent& event)
00251 {
00252
00253 }
00254
00255
00256
00257
00258
00259 void CGLCanvas::OnKeyDown( wxKeyEvent &event )
00260 {
00261 const int nMove = 20;
00262
00263
00264 switch( event.GetKeyCode() )
00265 {
00266 case WXK_LEFT: ScrollREL( -nMove, 0 ); break;
00267 case WXK_RIGHT: ScrollREL( nMove, 0 ); break;
00268 case WXK_UP: ScrollREL( 0, -nMove ); break;
00269 case WXK_DOWN: ScrollREL( 0, nMove ); break;
00270
00271 default:
00272 event.Skip( );
00273 break;
00274 }
00275 }
00276
00277 void CGLCanvas::OnLButtonDown( wxMouseEvent &event )
00278 {
00279 CaptureMouse();
00280
00281
00282
00283 m_ptMouseOld = event.GetPosition( );
00284
00285 event.Skip( );
00286 }
00287
00288 void CGLCanvas::OnLButtonUp( wxMouseEvent &event )
00289 {
00290
00291 if( GetCapture() == this )
00292 ReleaseMouse();
00293
00294 event.Skip( );
00295 }
00296
00297 void CGLCanvas::OnMouseMove( wxMouseEvent &event )
00298 {
00299
00300 if( event.LeftIsDown() )
00301 {
00302 int dx = m_ptMouseOld.x - event.GetX();
00303 int dy = m_ptMouseOld.y - event.GetY();
00304
00305 if( dx != 0 || dy != 0 )
00306 ScrollREL( dx, dy );
00307 }
00308
00309
00310 m_ptMouseOld = event.GetPosition( );
00311
00312
00313 event.Skip( );
00314 }
00315
00316
00317
00318
00319
00320
00321 void CGLCanvas::ClampView()
00322 {
00323
00324 CMap *pMap = wxGetApp().GetMap();
00325 if( pMap == NULL )
00326 return;
00327
00328 Rect rcMap = pMap->GetBounds();
00329
00330
00331 if( (rcMap.w * m_fZoom) > m_Width )
00332 {
00333
00334 if( m_XPos < rcMap.Left() * m_fZoom )
00335 m_XPos = (int)(rcMap.Left() * m_fZoom);
00336 else if( m_XPos > (rcMap.Right() * m_fZoom - m_Width) )
00337 m_XPos = (int)(rcMap.Right() * m_fZoom - m_Width);
00338 }
00339 else
00340 {
00341
00342 m_XPos = (int)(((rcMap.w * m_fZoom) - m_Width) / 2.0f + rcMap.Left() * m_fZoom);
00343 }
00344
00345
00346 if( (rcMap.h * m_fZoom) > m_Height )
00347 {
00348
00349 if( m_YPos < rcMap.Top() * m_fZoom )
00350 m_YPos = (int)(rcMap.Top() * m_fZoom);
00351 else if( m_YPos > (rcMap.Bottom() * m_fZoom - m_Height) )
00352 m_YPos = (int)(rcMap.Bottom() * m_fZoom - m_Height);
00353 }
00354 else
00355 {
00356
00357 m_YPos = (int)(((rcMap.h * m_fZoom) - m_Height) / 2.0f);
00358 }
00359 }
00360
00361 void CGLCanvas::ClientToOpenGL( int &x, int &y )
00362 {
00363 x = (int)((x + m_XPos) / m_fZoom);
00364 y = (int)((y + m_YPos) / m_fZoom);
00365 }
00366
00367 void CGLCanvas::OpenGLToClient( int &x, int &y )
00368 {
00369 x = (int)((x * m_fZoom ) - m_XPos);
00370 y = (int)((y * m_fZoom ) - m_YPos);
00371 }
00372
00373 void CGLCanvas::OnScrollBar( wxScrollWinEvent &event)
00374 {
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386 event.Skip( );
00387 }
00388
00389
00390
00391
00392
00393
00394 void CGLCanvas::ScrollREL( int dx, int dy )
00395 {
00396 m_XPos += dx;
00397 m_YPos += dy;
00398
00399 ClampView();
00400
00401 Refresh( false );
00402 }
00403
00404
00405
00406
00407
00408 void CGLCanvas::ScrollTo( int x, int y )
00409 {
00410 m_XPos = (int)((x*m_fZoom) - (m_Width / 2.0f));
00411 m_YPos = (int)((y*m_fZoom) - (m_Height / 2.0f));
00412 ClampView( );
00413 Refresh( );
00414 }
00415
00416
00417
00418
00419
00420 void CGLCanvas::ZoomIn()
00421 {
00422 SetZoom( m_fZoom + 0.1f );
00423 }
00424
00425
00426
00427
00428
00429 void CGLCanvas::ZoomOut()
00430 {
00431 SetZoom( m_fZoom - 0.1f );
00432 }
00433
00434
00435
00436
00437
00438 void CGLCanvas::SetZoom( float fZoom )
00439 {
00440
00441 if( fZoom < 0.1f ) fZoom = 0.1f;
00442 if( fZoom > 4.0f ) fZoom = 4.0f;
00443
00444
00445 float fDelta = fZoom / m_fZoom;
00446 if( fDelta == 1.0f )
00447 return;
00448
00449
00450 m_XPos += (int)((m_Width * fDelta - m_Width) / 2.0f + (m_XPos * fDelta - m_XPos));
00451 m_YPos += (int)((m_Height * fDelta - m_Height) / 2.0f + (m_YPos * fDelta - m_YPos));
00452 m_fZoom = fZoom;
00453
00454
00455 ClampView();
00456 Refresh( false );
00457 }
00458
00459
00460
00461
00462 Rect CGLCanvas::GetVisibleRect()
00463 {
00464 Rect rcScreen( (int)(m_XPos * (1/m_fZoom)), (int)(m_YPos * (1/m_fZoom)),
00465 (int)(m_Width * (1/m_fZoom)), (int)(m_Height * (1/m_fZoom)) );
00466 return rcScreen;
00467 }
00468
00469
00470
00471
00472
00473 void CGLCanvas::BeginDraw( float r, float g, float b, float a )
00474 {
00475 glPushAttrib( GL_CURRENT_BIT | GL_COLOR_BUFFER_BIT );
00476 glBindTexture( GL_TEXTURE_2D, 0 );
00477 glDisable( GL_ALPHA_TEST );
00478
00479
00480 if( a < 1.0f )
00481 glEnable( GL_BLEND );
00482
00483 glColor4f( r, g, b, a );
00484 }
00485
00486 void CGLCanvas::EndDraw( )
00487 {
00488 glPopAttrib( );
00489 }
00490
00491 void CGLCanvas::FillRect( const Rect &rcRect, float r, float g, float b, float a )
00492 {
00493 BeginDraw( r, g, b, a );
00494 glRecti( rcRect.x, rcRect.y, rcRect.Right(), rcRect.Bottom() );
00495 EndDraw( );
00496 }
00497
00498 void CGLCanvas::DrawRect( const Rect &rcRect, float r, float g, float b, float a )
00499 {
00500 BeginDraw( r, g, b, a );
00501 glBegin( GL_LINE_LOOP );
00502 glVertex2i( rcRect.Left(), rcRect.Top() );
00503 glVertex2i( rcRect.Left(), rcRect.Bottom() );
00504 glVertex2i( rcRect.Right(), rcRect.Bottom() );
00505 glVertex2i( rcRect.Right(), rcRect.Top() );
00506 glEnd();
00507 EndDraw( );
00508 }
00509
00510 void CGLCanvas::DrawCircle( const wxPoint &ptCenter, int n, float radius,
00511 float r, float g, float b, float a)
00512 {
00513 BeginDraw( r, g, b, a );
00514 glBegin( GL_POLYGON );
00515 {
00516 float step = 2*PI/n;
00517 for( int i=0; i<n; i++ )
00518 {
00519 float r = i * step;
00520 int x = (int)( cos( r ) * radius ) + ptCenter.x;
00521 int y = (int)( sin( r ) * radius ) + ptCenter.y;
00522
00523 glVertex2i( x, y );
00524 }
00525 }
00526 glEnd();
00527 EndDraw();
00528 }
00529
00530 void CGLCanvas::DrawLine( const wxPoint &pt1, const wxPoint &pt2, float width,
00531 float r, float g, float b, float a )
00532 {
00533 BeginDraw( r, g, b, a );
00534 glLineWidth( width );
00535 glBegin( GL_LINES );
00536 {
00537 glVertex2i( pt1.x, pt1.y );
00538 glVertex2i( pt2.x, pt2.y );
00539 }
00540 glEnd();
00541 EndDraw();
00542 }
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552 void CGLCanvas::DrawTextBox( int x, int y, float r, float g, float b, float a, const char *szText )
00553 {
00554 if( m_pFont == NULL || szText == NULL )
00555 return;
00556
00557 wxPoint pt = GetTextExtent( szText );
00558 Rect rcFill( x-2, y-2, pt.x+8, pt.y+2 );
00559
00560 FillRect( rcFill, 0.0f, 0.0f, 0.0f, 0.75f );
00561 DrawText( x, y, r, g, b, a, szText );
00562 }
00563
00564
00565
00566
00567
00568 void CGLCanvas::DrawText( int x, int y, float r, float g, float b, float a, const char *fmt, ...)
00569 {
00570 if( m_pFont == NULL || fmt == NULL )
00571 return;
00572
00573 char szText[1024];
00574 va_list ap;
00575
00576 va_start(ap, fmt);
00577 vsprintf(szText, fmt, ap);
00578 va_end(ap);
00579
00580
00581 m_pFont->Bind();
00582
00583
00584 glPushAttrib( GL_CURRENT_BIT );
00585 glColor4f( r, g, b, a );
00586
00587
00588
00589 GLboolean bAlphaTest = glIsEnabled( GL_ALPHA_TEST );
00590 GLboolean bAlphaBlend = glIsEnabled( GL_BLEND );
00591
00592
00593 if( bAlphaTest ) glDisable( GL_ALPHA_TEST );
00594 if( !bAlphaBlend) glEnable ( GL_BLEND );
00595
00596
00597 for(int i=0; szText[i]; i++)
00598 {
00599 DrawChar( x, y, szText[i] );
00600 x += g_aGlyphWidths[((unsigned char)szText[i])];
00601 }
00602
00603
00604 if( bAlphaTest ) glEnable ( GL_ALPHA_TEST );
00605 if( !bAlphaBlend ) glDisable( GL_BLEND );
00606
00607 glPopAttrib( );
00608 }
00609
00610
00611
00612
00613
00614 void CGLCanvas::DrawChar( int x, int y, unsigned char c)
00615 {
00616 if ( c <= 32 )
00617 return;
00618
00619
00620
00621 int row = c >> 4;
00622 int col = c & 15;
00623
00624 float fw = 1.0f / 16.0f;
00625 float fh = 1.0f / 16.0f;
00626 float frow = row * fh;
00627 float fcol = col * fw;
00628
00629 glBegin(GL_QUADS);
00630 glTexCoord2f(fcol, frow); glVertex2i( x, y );
00631 glTexCoord2f(fcol, frow + fh); glVertex2i( x, y + 16 );
00632 glTexCoord2f(fcol + fw, frow + fh); glVertex2i( x + 16, y + 16 );
00633 glTexCoord2f(fcol + fw, frow); glVertex2i( x + 16, y );
00634 glEnd();
00635 }
00636
00637
00638
00639
00640
00641 wxPoint CGLCanvas::GetTextExtent( const char *szText )
00642 {
00643 wxPoint pt(0, 0);
00644 if( m_pFont == NULL || szText == NULL )
00645 return pt;
00646
00647
00648 pt.y = 16;
00649
00650
00651 for(int i=0; szText[i]; i++)
00652 {
00653 pt.x += g_aGlyphWidths[((unsigned char)szText[i])];
00654 }
00655
00656 return pt;
00657 }
00658
00659
00660
00661
00662
00663
00664
00665
00666
00667 CTexture* CGLCanvas::LoadTexture( string strTexture, bool bMipMap )
00668 {
00669
00670 TexMap::iterator tex = m_aTextures.find( strTexture );
00671 if( tex != m_aTextures.end() )
00672 {
00673 CTexture *pTex = tex->second;
00674 pTex->IncRefCount();
00675 return pTex;
00676 }
00677
00678
00679 wxImage image;
00680 if( image.LoadFile( strTexture.c_str() ) == false )
00681 {
00682 logFile << "ERROR: Unable to load " << strTexture << ". Loading default texture." << endl;
00683
00684
00685 image.Create( 8, 8 );
00686
00687
00688 BYTE *pData = image.GetData();
00689 for( int i=0; i<8*8; i++ )
00690 {
00691 *pData++ = ((i&1) ^ ((i&8)==8)) ? 255 : 0;
00692 *pData++ = 0;
00693 *pData++ = 0;
00694 }
00695 }
00696
00697
00698 CTexture *pTexture = CreateTexture( &image, strTexture, bMipMap );
00699 if( pTexture == NULL )
00700 {
00701 logFile << "ERROR: Unable to create Texture '" << strTexture << "'." << endl;
00702 return NULL;
00703 }
00704
00705
00706 m_aTextures.insert( TexMap::value_type( strTexture, pTexture ) );
00707
00708 return pTexture;
00709 }
00710
00711
00712
00713
00714
00715 CTexture* CGLCanvas::CreateTexture( wxImage *pImage, string strTexture, bool bMipMap )
00716 {
00717
00718 if (!GetContext())
00719 {
00720 cout << "***ERROR: GlCanvas::CreateTexture: Kein Kontext!" << endl;
00721 return false;
00722 }
00723 SetCurrent();
00724
00725
00726 int w = power_of_two( pImage->GetWidth() );
00727 int h = power_of_two( pImage->GetHeight() );
00728 int bpp = 3;
00729
00730
00731 bool bMask = pImage->HasMask();
00732 BYTE mr, mg, mb;
00733 if( bMask )
00734 {
00735 mr = pImage->GetMaskRed();
00736 mg = pImage->GetMaskGreen();
00737 mb = pImage->GetMaskBlue();
00738 bpp = 4;
00739 }
00740
00741
00742 int cols = pImage->GetWidth();
00743 int rows = pImage->GetHeight();
00744 BYTE *dest, *bmp = pImage->GetData();
00745 BYTE *rgba = new BYTE[w * h * bpp];
00746 memset( rgba, 0, w*h*bpp );
00747
00748
00749
00750
00751
00752
00753
00754
00755
00756
00757
00758
00759
00760
00761
00762
00763
00764
00765
00766
00767 for( int row = 0; row < rows; row++ )
00768 {
00769 dest = rgba + row * w * bpp;
00770 for(int col = 0; col < cols; col++)
00771 {
00772 *dest++ = *bmp++;
00773 *dest++ = *bmp++;
00774 *dest++ = *bmp++;
00775
00776 if( bMask )
00777 {
00778 if( dest[-3] == mr && dest[-2] == mg && dest[-1] == mb )
00779 *dest++ = 0;
00780 else
00781 *dest++ = 255;
00782 }
00783 }
00784 }
00785
00786
00787 GLuint nTextureID;
00788 glGenTextures(1, &nTextureID);
00789
00790
00791 glBindTexture(GL_TEXTURE_2D, nTextureID);
00792 if(glGetError() != GL_NO_ERROR)
00793 {
00794 logFile << "***ERROR: CGLCanvas::CreateTexture: glBindTexture failed!" << endl;
00795 return NULL;
00796 }
00797
00798
00799 if( bMipMap )
00800 {
00801 BuildMipmaps( w, h, GL_RGBA, 4, (BYTE*) rgba );
00802 if(glGetError() != GL_NO_ERROR)
00803 {
00804 logFile << "***ERROR: CGLCanvas::CreateTexture: BuildMipmaps failed!" << endl;
00805 return NULL;
00806 }
00807
00808
00809 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
00810 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST );
00811 if(glGetError() != GL_NO_ERROR)
00812 return NULL;
00813 }
00814 else
00815 {
00816 glTexImage2D( GL_TEXTURE_2D, 0, 4, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, (BYTE*)rgba );
00817 if(glGetError() != GL_NO_ERROR)
00818 {
00819 logFile << "***ERROR: CGLCanvas::CreateTexture: glTexImage2D failed!" << endl;
00820 return NULL;
00821 }
00822
00823
00824 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
00825 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
00826 if(glGetError() != GL_NO_ERROR)
00827 return NULL;
00828 }
00829
00830
00831 CTexture *pTexture = new CTexture( strTexture );
00832 pTexture->m_nWidth = w;
00833 pTexture->m_nHeigth = h;
00834 pTexture->m_nOriginalWidth = cols;
00835 pTexture->m_nOriginalHeigth = rows;
00836 pTexture->m_nRefCount = 1;
00837 pTexture->m_nTexureID = nTextureID;
00838
00839
00840 delete [] rgba;
00841
00842 return pTexture;
00843 }
00844
00845
00846
00847
00848
00849
00850
00851 void CGLCanvas::BuildMipmaps(int nWidth, int nHeigth, GLenum nFormat, int nBpp, BYTE *pData)
00852 {
00853 if( nWidth < 1 || nHeigth < 1 )
00854 return;
00855
00856 BYTE *d = pData;
00857 int w = nWidth;
00858 int h = nHeigth;
00859
00860 int nLevel = 0;
00861 while( true )
00862 {
00863
00864 glTexImage2D( GL_TEXTURE_2D, nLevel, nBpp, w, h, 0, nFormat, GL_UNSIGNED_BYTE, d );
00865
00866 if( w == 1 && h == 1)
00867 break;
00868
00869 int neww = (w<2) ? 1 : w/2;
00870 int newh = (h<2) ? 1 : h/2;
00871 BYTE *newd = new BYTE[neww * newh * nBpp];
00872
00873 ScaleForWDS( w, h, d, neww, newh, newd );
00874
00875 if( d != pData )
00876 delete [] d;
00877
00878 nLevel++;
00879 w = neww;
00880 h = newh;
00881 d = newd;
00882 }
00883
00884 if( d != pData )
00885 delete [] d;
00886 }
00887
00888
00889
00890
00891
00892
00893
00894 void CGLCanvas::ScaleForWDS( int inw, int inh, BYTE *in, int outw, int outh, BYTE *out )
00895 {
00896 BYTE *dest, *src;
00897 int sy = (inh == 1 ? 1 : 2);
00898 int sx = (inw == 1 ? 4 : 8);
00899
00900 int r, g, b;
00901 int n;
00902
00903 for( int y=0; y<outh; y++ )
00904 {
00905 dest = out + outw * y * 4;
00906 src = in + inw * y * 4 * sy;
00907 for ( int x=0; x<outw ; x++ )
00908 {
00909 r = g = b = 0;
00910 n = 0;
00911
00912 if( src[3] == 255 )
00913 {
00914 r += src[0]; g += src[1]; b += src[2]; n++;
00915 }
00916
00917 if( inw > 1 && src[7] == 255 )
00918 {
00919 r += src[4]; g += src[5]; b += src[6]; n++;
00920 }
00921
00922 if( inh > 1 && src[inw*4+3] == 255 )
00923 {
00924 r += src[inw*4]; g += src[inw*4+1]; b += src[inw*4+2]; n++;
00925 }
00926
00927 if( inh > 1 && inw > 1 && src[inw*4+7] == 255)
00928 {
00929 r += src[inw*4+4]; g += src[inw*4+5]; b += src[inw*4+6]; n++;
00930 }
00931
00932 if( n > 0 )
00933 {
00934 dest[0] = r / n; dest[1] = g / n; dest[2] = b / n; dest[3] = 255;
00935 }
00936 else
00937 {
00938 dest[3] = 0;
00939 }
00940
00941 dest += 4;
00942 src += sx;
00943 }
00944 }
00945 }
00946
00947 void CGLCanvas::DeleteTexture( CTexture *pTexture )
00948 {
00949 if( !pTexture )
00950 return;
00951
00952 pTexture->DecRefCount();
00953 if( pTexture->m_nRefCount == 0 )
00954 {
00955 TexMap::iterator tex = m_aTextures.find( pTexture->GetName() );
00956 if( tex != m_aTextures.end() )
00957 m_aTextures.erase( tex );
00958 delete pTexture;
00959 }
00960 }
00961
00962
00963
00964
00965 int CGLCanvas::power_of_two(int input)
00966 {
00967 int value = 1;
00968 while ( value < input )
00969 value <<= 1;
00970 return value;
00971 }
00972
00973 }
00974
00975