Texture Mapping (same image, all faces)

Category: Graphics - OpenGL

Date: 03-28-2012

Return to Index


 
'One of the more useful/popular features of OpenGL is the ability to
'map an image onto a surface - texture mapping. This snippets shows
'how it is done.
 
'Compiler Comments:
'This code was written to compilete in PBWin10. To compile with PBWin9, split pt
'into pt.x and pt.y as arguments wherever the ChildWindowFromPoint() API is used (1 place).
 
'Primary Code:
'There are 3 basic steps involved:
'1. Create a texture (load from a bitmap file, resource, or create from scratch)
'2. Initialize texture mapping
'3. Attach image to polygons
 
'Creating a texture in memory can be done in several ways. OpenGL requires
'a pointer to RGB color bytes for each pixel, so an array or string can
'be used. Here's the code to use an array of Longs to create the bytes
'needed by OpenGL.
 
   Sub CreateTexture
      Local i,j As Long, sFileName As String
      sFileName = "cowgirl.bmp"
      GetBitMapDimensions(sFileName, imgW, imgH)
      Graphic Bitmap Load sFileName, imgW, imgH To hBMP
      Graphic Attach hBMP, 0
      Dim BMPData(imgW-1,imgH-1)
      For i = 0 to imgW-1
         For j = 0 to imgH-1
            Graphic Get Pixel (i,j) To BMPData(i,imgH-1-j)
         Next j
      Next i
   End Sub
 
'Starting with the OpenGL template that I've released, add this function to
'initialize texture mapping. Call it from the InitializeScene procedure.
   Sub InitializeMapping
      glEnable %gl_texture_2D
      glTexEnvf %gl_texture_env, %gl_texture_env_mode, %gl_modulate
      glBindTexture %gl_texture_2D, 1
      glTexParameteri %gl_texture_2d, %gl_texture_wrap_s, %gl_repeat
      glTexParameteri %gl_texture_2d, %gl_texture_wrap_t, %gl_repeat
      glTexParameteri %gl_texture_2d,%gl_texture_mag_filter,%gl_linear
      glTexParameteri %gl_texture_2d,%gl_texture_min_filter,%gl_linear
      glTexImage2D %gl_texture_2D, 0, %gl_rgb, 100, 100, 0, %gl_rgba, %gl_unsigned_byte, ByVal StrPTR(BMP$)
   End Sub
 
'Finally, the corners of the image must be mapped to the corners of the
'face of each cube. Here's a partial code listing showing how it's done.
'Each vertex of a face is mapped to a corner of the image.
 
   glBegin %gl_quads
       ' Front Face
       glTexCoord2f 0.0, 0.0: glVertex3f -1.0, -1.0, 1.0 ' Bottom Left Of The Texture And Quad
       glTexCoord2f 1.0, 0.0: glVertex3f  1.0, -1.0, 1.0 ' Bottom Right Of The Texture And Quad
       glTexCoord2f 1.0, 1.0: glVertex3f  1.0,  1.0, 1.0 ' Top Right Of The Texture And Quad
       glTexCoord2f 0.0, 1.0: glVertex3f -1.0,  1.0, 1.0 ' Top Left Of The Texture And Quad
   glEnd
 
 
'Compilable Example:
#Compiler PBWin 10
#Compile EXE
#Dim All
#Include "win32api.inc"
#Include "gl.inc"
#Include "glu.inc"
 
%ID_Timer = 1000 : %ID_Label = 1002 : %ID_Graphic = 1003
 
Global hDlg, hDC, hRC, hLabel, hBMP As DWord
Global scalefactor As Single
Global BMPData(), imgW, imgH As Long
 
Function PBMain() As Long
   CreateTexture
   Dialog New Pixels, 0, "OpenGL Example",,, 400, 200,%WS_OverlappedWindow To hDlg
   Control Add Graphic, hDlg, %ID_Graphic, "", 10,10,imgW,imgH
   Graphic Attach hDlg, %ID_Graphic
   Graphic Copy hBMP, 0
   Control Add Label, hdlg, %ID_Label,"",120,10,imgW,imgH, %WS_Child Or %WS_Visible Or %SS_Sunken Or %SS_Notify
   Dialog Show Modal hdlg Call dlgproc
End Function
 
CallBack Function dlgproc()
   Local pt As Point
   Local XDelta, YDelta As Single
   Static SpinInWork,XLast,YLast As Long
 
   Select Case CB.Msg
      Case %WM_InitDialog : GetRenderContext
         InitializeScene
         SetTimer(hDlg, %ID_Timer, 50, %NULL)
         ScaleFactor = 1
      Case %WM_Timer      : DrawScene 1,1,0  'redraw with rotation on all 3 axes
      Case %WM_Paint      : DrawScene 0,0,0  'redraw with no rotation
      Case %WM_Size       : Control Set Size hDlg, %ID_Label, Lo(Word, CB.lParam)-130, Hi(Word, CB.lParam)-20
         ResizeScene Lo(Word, CB.lParam)-130, Hi(Word, CB.lParam)-20
         DrawScene 0,0,0  'redraw with no rotation
      Case %WM_Close      : wglmakecurrent %null, %null 'unselect rendering context
         wgldeletecontext hRC        'delete the rendering context
         releasedc hDlg, hDC         'release device context
      Case %WM_MouseWheel
         Select Case Hi(Integer,CB.wParam)
            Case > 0  : ScaleFactor = ScaleFactor + 0.1 : DrawScene 0,0,0
            Case < 0  : ScaleFactor = ScaleFactor - 0.1 : DrawScene 0,0,0
         End Select
      Case %WM_SetCursor
         GetCursorPos pt          'p.x and p.y are in screen coordinates
         ScreenToClient hDlg, pt  'p.x and p.y are now dialog client coordinates
         If GetDlgCtrlID(ChildWindowFromPoint( hDlg, pt )) <> %ID_Label Then Exit Function
         Select Case Hi(Word, CB.lParam)
            Case %WM_LButtonDown
               GetCursorPos pt              'pt has xy screen coordinates
               ScreenToClient hDlg, pt       'pt now has dialog client coordinates
               If pt.y < 0 Then Exit Select
               KillTimer CB.Hndl, %ID_Timer
               SpinInWork = 1
               XLast = Pt.x
               YLast = Pt.y
            Case %WM_MouseMove
               If SpinInWork Then
                  GetCursorPos pt           'pt has xy screen coordinates
                  ScreenToClient hDlg, pt    'pt now has dialog client coordinates
                  If pt.y < 0 Then Exit Select
                  XDelta = XLast - Pt.x
                  YDelta = YLast - Pt.y
                  DrawScene -YDelta, -XDelta, 0
                  XLast = pt.x
                  YLast = pt.y
               End If
            Case %WM_LButtonUp
               SetTimer(hDlg, %ID_Timer, 50, %NULL)
               SpinInWork = 0
         End Select
   End Select
End Function
 
Sub GetRenderContext
   Local pfd As PIXELFORMATDESCRIPTOR   'pixel format properties for device context
   pfd.nSize       =  SizeOf(PIXELFORMATDESCRIPTOR)
   pfd.nVersion    =  1
   pfd.dwFlags     = %pfd_draw_to_window Or %pfd_support_opengl Or %pfd_doublebuffer
   pfd.dwlayermask = %pfd_main_plane
   pfd.iPixelType  = %pfd_type_rgba
   pfd.ccolorbits  = 24
   pfd.cdepthbits  = 24
 
   Control Handle hdlg, %ID_Label To hLabel
   hDC = GetDC(hLabel)
   SetPixelFormat(hDC, ChoosePixelFormat(hDC, pfd), pfd)  'set properties of device context
   hRC = wglCreateContext (hDC)                           'get rendering context
   wglMakeCurrent hDC, hRC                                'make the RC current
End Sub
 
Sub InitializeMapping
   glEnable %gl_texture_2D
   glTexEnvf %gl_texture_env, %gl_texture_env_mode, %gl_modulate
   glBindTexture %gl_texture_2D, 1
   glTexParameteri %gl_texture_2d,%gl_texture_mag_filter,%gl_linear
   glTexParameteri %gl_texture_2d,%gl_texture_min_filter,%gl_linear
   glTexImage2D %gl_texture_2D, 0, %gl_rgb, 100, 100, 0, %gl_rgba, %gl_unsigned_byte, BMPData(0)
End Sub
 
Sub InitializeScene
   InitializeMapping
   glClearColor 0,0,0,0     'sets color to be used with glClear
   glClearDepth 1           'sets zvalue to be used with glClear
   glEnable %gl_depth_test                             'enable depth testing
   glHint %gl_perspective_correction_hint, %gl_nicest  'best quality rendering
   BuildDisplayList 1
End Sub
 
Sub ResizeScene (w As Long, h As Long)
   glViewport 0, 0, w, h               'resize viewport to match window size
   glMatrixMode %gl_projection         'select the projection matrix
   glLoadIdentity                    'reset the projection matrix
   gluPerspective 45, w/h, 0.1, 100  'set frustum using viewport aspect ratio
   glMatrixMode %gl_modelview          'select the modelview matrix
End Sub
 
Sub DrawScene (dx As Single, dy As Single, dz As Single)
   Static anglex, angley, anglez As Single
   glClear %gl_color_buffer_bit Or %gl_depth_buffer_bit  'clear buffers
   glLoadIdentity               'clear the modelview matrix
 
   gluLookAt 0,0,6,0,0,0,0,1,0
 
   glScalef scalefactor, scalefactor, scalefactor
 
   anglex = anglex + dx : glRotatef anglex, 1,0,0
   angley = angley + dy : glRotatef angley, 0,1,0
   anglez = anglez + dz : glRotatef anglez, 0,0,1
 
   glCallList 1
 
   SwapBuffers hDC              'display the buffer (image)
End Sub
 
Sub BuildDisplayList(ListNumber As Long)
   glNewList ListNumber, %gl_compile
   glBegin %gl_quads
   ' Front Face
   glTexCoord2f 0.0, 0.0: glVertex3f -1.0, -1.0, 1.0       ' Bottom Left Of The Texture And Quad
   glTexCoord2f 1.0, 0.0: glVertex3f  1.0, -1.0, 1.0       ' Bottom Right Of The Texture And Quad
   glTexCoord2f 1.0, 1.0: glVertex3f  1.0,  1.0, 1.0       ' Top Right Of The Texture And Quad
   glTexCoord2f 0.0, 1.0: glVertex3f -1.0,  1.0, 1.0       ' Top Left Of The Texture And Quad
   ' Back Face
   glTexCoord2f 1.0, 0.0: glVertex3f -1.0, -1.0, -1.0      ' Bottom Right Of The Texture And Quad
   glTexCoord2f 1.0, 1.0: glVertex3f -1.0,  1.0, -1.0      ' Top Right Of The Texture And Quad
   glTexCoord2f 0.0, 1.0: glVertex3f  1.0,  1.0, -1.0      ' Top Left Of The Texture And Quad
   glTexCoord2f 0.0, 0.0: glVertex3f  1.0, -1.0, -1.0      ' Bottom Left Of The Texture And Quad
   ' Top Face
   glTexCoord2f 0.0, 1.0: glVertex3f -1.0,  1.0, -1.0      ' Top Left Of The Texture And Quad
   glTexCoord2f 0.0, 0.0: glVertex3f -1.0,  1.0,  1.0      ' Bottom Left Of The Texture And Quad
   glTexCoord2f 1.0, 0.0: glVertex3f  1.0,  1.0,  1.0      ' Bottom Right Of The Texture And Quad
   glTexCoord2f 1.0, 1.0: glVertex3f  1.0,  1.0, -1.0      ' Top Right Of The Texture And Quad
   ' Bottom Face
   glTexCoord2f 1.0, 1.0: glVertex3f -1.0, -1.0, -1.0      ' Top Right Of The Texture And Quad
   glTexCoord2f 0.0, 1.0: glVertex3f  1.0, -1.0, -1.0      ' Top Left Of The Texture And Quad
   glTexCoord2f 0.0, 0.0: glVertex3f  1.0, -1.0,  1.0      ' Bottom Left Of The Texture And Quad
   glTexCoord2f 1.0, 0.0: glVertex3f -1.0, -1.0,  1.0      ' Bottom Right Of The Texture And Quad
   ' Right face
   glTexCoord2f 1.0, 0.0: glVertex3f  1.0, -1.0, -1.0      ' Bottom Right Of The Texture And Quad
   glTexCoord2f 1.0, 1.0: glVertex3f  1.0,  1.0, -1.0      ' Top Right Of The Texture And Quad
   glTexCoord2f 0.0, 1.0: glVertex3f  1.0,  1.0,  1.0      ' Top Left Of The Texture And Quad
   glTexCoord2f 0.0, 0.0: glVertex3f  1.0, -1.0,  1.0      ' Bottom Left Of The Texture And Quad
   ' Left Face
   glTexCoord2f 0.0, 0.0: glVertex3f -1.0, -1.0, -1.0      ' Bottom Left Of The Texture And Quad
   glTexCoord2f 1.0, 0.0: glVertex3f -1.0, -1.0,  1.0      ' Bottom Right Of The Texture And Quad
   glTexCoord2f 1.0, 1.0: glVertex3f -1.0,  1.0,  1.0      ' Top Right Of The Texture And Quad
   glTexCoord2f 0.0, 1.0: glVertex3f -1.0,  1.0, -1.0      ' Top Left Of The Texture And Quad
   glEnd
   glEndList
End Sub
 
Sub GetBitMapDimensions(sFileName$, w As Long, h As Long)
   Open sFileName$ For BINARY As #1
   Get #1, 19, w
   Get #1, 23, h
   Close #1
End Sub
 
Sub CreateTexture
   Local i,j As Long, sFileName As String
   sFileName = "cowgirl.bmp"
   GetBitMapDimensions(sFileName, imgW, imgH)
   Graphic Bitmap Load sFileName, imgW, imgH To hBMP
   Graphic Attach hBMP, 0
   Dim BMPData(imgW-1,imgH-1)
   For i = 0 to imgW-1
      For j = 0 to imgH-1
         Graphic Get Pixel (i,j) To BMPData(i,imgH-1-j)
      Next j
   Next i
End Sub
 
'gbs_00614
'Date: 03-10-2012


created by gbSnippets
http://www.garybeene.com/sw/gbsnippets.htm