fortran66のブログ

fortran について書きます。

OpenGLによる3次元CGプログラミング
作者: 林武文, 加藤清敬
出版社/メーカー: コロナ社


MODULE m_bitmap
IMPLICIT NONE
INTEGER, PARAMETER :: DWORD = 4, LONG = 4, WORD = 2, kBYTE = 1 
TYPE :: T_BITMAPINFOHEADER
 SEQUENCE
 integer(DWORD) biSize ! knowns  DWORD 
 integer(LONG) biWidth ! knowns  LONG 
 integer(LONG) biHeight ! knowns  LONG 
 integer(WORD) biPlanes ! knowns  WORD 
 integer(WORD) biBitCount ! knowns  WORD 
 integer(DWORD) biCompression ! knowns  DWORD 
 integer(DWORD) biSizeImage ! knowns  DWORD 
 integer(LONG) biXPelsPerMeter ! knowns  LONG 
 integer(LONG) biYPelsPerMeter ! knowns  LONG 
 integer(DWORD) biClrUsed ! knowns  DWORD 
 integer(DWORD) biClrImportant ! knowns  DWORD 
END TYPE
!
TYPE :: T_RGBQUAD
 SEQUENCE
 integer(kBYTE) rgbBlue ! knowns  BYTE 
 integer(kBYTE) rgbGreen ! knowns  BYTE 
 integer(kBYTE) rgbRed ! knowns  BYTE 
 integer(kBYTE) rgbReserved ! knowns  BYTE 
END TYPE
!
TYPE :: T_BITMAPFILEHEADER
 SEQUENCE
 CHARACTER(2)   :: bfType
 INTEGER(DWORD) :: bfSize
 INTEGER(WORD)  :: bfReserved1
 INTEGER(WORD)  :: bfReserved2
 INTEGER(DWORD) :: bfOffBits
END TYPE 
CONTAINS
!----------------------------------------------------
SUBROUTINE ReadBitmapFile(text, bih, bcolmap, itmp)
IMPLICIT NONE
CHARACTER(*), INTENT(IN) :: text
TYPE (T_BITMAPINFOHEADER)     , INTENT(OUT) :: bih
TYPE (T_RGBQUAD), ALLOCATABLE, INTENT(OUT) :: bcolmap(:)
INTEGER(1)     , ALLOCATABLE, INTENT(OUT) :: itmp(:)
TYPE (T_BITMAPFILEHEADER) :: bfh
INTEGER :: i, len
INTEGER :: ir = 10
OPEN(ir, file = text, FORM = 'BINARY')
READ(ir) bfh
READ(ir) bih
len = bih%biWidth * bih%biHeight
IF (bih%biBitCount == 8) THEN 
 ALLOCATE(bcolmap(256))
 READ(ir) bcolmap
 ALLOCATE( itmp(len) )
 READ(ir) itmp
ELSE IF (bih%biBitCount == 4) THEN
 ALLOCATE(bcolmap(16))
 READ(ir) bcolmap
 ALLOCATE( itmp(len) )
 itmp = 0
 READ(ir) itmp
 DO i = 1, len, 2
  itmp( (i + 1) / 2) = itmp(i + 1) * 16 + itmp(i)   
 END DO
END IF 
CLOSE(ir)
RETURN
END SUBROUTINE ReadBitmapFile
!----------------------------------------------------
SUBROUTINE ReadBitMapData(text, iwidth, iheight, ipixel)
IMPLICIT NONE
CHARACTER(*), INTENT(IN) :: text
INTEGER, INTENT(OUT) :: iwidth, iheight
INTEGER(1), ALLOCATABLE, INTENT(OUT) :: ipixel(:)
TYPE (T_BITMAPINFOHEADER) :: bih
INTEGER :: istatus, isel
INTEGER :: i, j, k, m
INTEGER :: icounter, icolor
TYPE (T_RGBQUAD), ALLOCATABLE :: bcolmap(:)
INTEGER(1)     , ALLOCATABLE :: idata(:)
!
CALL ReadBitmapFile('tmp.bmp', bih, bcolmap, idata)
iwidth  = bih%biWidth
iheight = bih%biHeight
ALLOCATE( ipixel( 4 * iwidth * iheight ) )
IF (bih%biBitCount == 8) THEN
 DO j = 0, iheight - 1
  DO i = 0, iwidth - 1
   k = 4 * (j * iwidth + i) + 1
   m = idata(j * iwidth + i + 1)
   IF (m < 0) m = 256 + m
   m = m + 1 
   ipixel(k    ) = bcolmap(m)%rgbRed
   ipixel(k + 1) = bcolmap(m)%rgbGreen
   ipixel(k + 2) = bcolmap(m)%rgbBlue
   ipixel(k + 3) = 255
  END DO
 END DO
ELSE IF (bih%biBitCount == 4) THEN
 icounter = 0
 DO j = 0, iheight - 1
  DO i = 0, iwidth - 1
   icounter = icounter + 1
   icolor = idata(icounter)
!   IF (icolor < 0) icolor = icolor + 256 ! 
   ipixel(k    ) = bcolmap(icolor)%rgbRed
   ipixel(k + 1) = bcolmap(icolor)%rgbGreen
   ipixel(k + 2) = bcolmap(icolor)%rgbBlue
   ipixel(k + 3) = 255
  END DO
 END DO
END IF
DEALLOCATE(bcolmap, idata)
RETURN
END SUBROUTINE ReadBitMapData
!----------------------------------------------------
END MODULE m_bitmap
!====================================================
MODULE m_callback
USE opengl_gl
USE opengl_glu
USE opengl_glut
USE :: m_bitmap
IMPLICIT NONE
INTEGER(GLCINT), PARAMETER :: KEY_ESC = 27
INTEGER(GLcint) :: ixBegin = 0, iyBegin = 0
INTEGER(GLcint) :: mButton
REAL(GLfloat) :: distance, twist, elevation, azimuth
REAL(GLdouble) :: dnear = 1.0_gldouble, far = 30.0_gldouble, fovy = 60.0_gldouble
CONTAINS
!---------------------------------------------------------
SUBROUTINE display()
IMPLICIT NONE
REAL(glfloat) :: diffuse(4)  = (/ 0.0_glfloat, 0.0_glfloat, 1.0_glfloat, 1.0_glfloat /)
REAL(glfloat) :: specular(4) = (/ 1.0_glfloat, 1.0_glfloat, 1.0_glfloat, 1.0_glfloat /)
REAL(glfloat) :: ambient(4)  = (/ 0.1_glfloat, 0.1_glfloat, 0.1_glfloat, 1.0_glfloat /)
CALL glClear( IOR(GL_COLOR_BUFFER_BIT, GL_DEPTH_BUFFER_BIT) )
!
CALL glPushMatrix()
CALL polarview( )
CALL glEnable( GL_DEPTH_TEST )
CALL glEnable( GL_TEXTURE_2D )
!
CALL glMaterialfv( GL_FRONT, GL_DIFFUSE  , diffuse   ) 
CALL glMaterialfv( GL_FRONT, GL_SPECULAR , specular  )
CALL glMaterialfv( GL_FRONT, GL_AMBIENT  , ambient   )
CALL glMaterialf ( GL_FRONT, GL_SHININESS, 128.0_glfloat )
CALL glEnable( GL_LIGHTING )
!
CALL glBindTexture( GL_TEXTURE_2D, 1 )
CALL glBegin( GL_QUADS )
 CALL glTexCoord2f( 0.0_glfloat, 0.0_glfloat )
 CALL glVertex3f  (-0.5_glfloat,-0.5_glfloat, 0.5_glfloat )
 CALL glTexCoord2f( 0.0_glfloat, 1.0_glfloat )
 CALL glVertex3f  (-0.5_glfloat, 0.5_glfloat, 0.5_glfloat )
 CALL glTexCoord2f( 1.0_glfloat, 1.0_glfloat )
 CALL glVertex3f  ( 0.5_glfloat, 0.5_glfloat, 0.5_glfloat )
 CALL glTexCoord2f( 1.0_glfloat, 0.0_glfloat )
 CALL glVertex3f  ( 0.5_glfloat,-0.5_glfloat, 0.5_glfloat )
CALL glEnd()
CALL glBegin( GL_QUADS )
 CALL glTexCoord2f( 0.0_glfloat, 0.0_glfloat )
 CALL glVertex3f  (-0.5_glfloat,-0.5_glfloat,-0.5_glfloat )
 CALL glTexCoord2f( 0.0_glfloat, 1.0_glfloat )
 CALL glVertex3f  (-0.5_glfloat, 0.5_glfloat,-0.5_glfloat )
 CALL glTexCoord2f( 1.0_glfloat, 1.0_glfloat )
 CALL glVertex3f  ( 0.5_glfloat, 0.5_glfloat,-0.5_glfloat )
 CALL glTexCoord2f( 1.0_glfloat, 0.0_glfloat )
 CALL glVertex3f  ( 0.5_glfloat,-0.5_glfloat,-0.5_glfloat )
CALL glEnd()
CALL glBegin( GL_QUADS )
 CALL glTexCoord2f( 0.0_glfloat, 0.0_glfloat )
 CALL glVertex3f  ( 0.5_glfloat,-0.5_glfloat, 0.5_glfloat )
 CALL glTexCoord2f( 0.0_glfloat, 1.0_glfloat )
 CALL glVertex3f  ( 0.5_glfloat,-0.5_glfloat,-0.5_glfloat )
 CALL glTexCoord2f( 1.0_glfloat, 1.0_glfloat )
 CALL glVertex3f  ( 0.5_glfloat, 0.5_glfloat,-0.5_glfloat )
 CALL glTexCoord2f( 1.0_glfloat, 0.0_glfloat )
 CALL glVertex3f  ( 0.5_glfloat, 0.5_glfloat, 0.5_glfloat )
CALL glEnd()
CALL glBegin( GL_QUADS )
 CALL glTexCoord2f( 0.0_glfloat, 0.0_glfloat )
 CALL glVertex3f  (-0.5_glfloat,-0.5_glfloat, 0.5_glfloat )
 CALL glTexCoord2f( 0.0_glfloat, 1.0_glfloat )
 CALL glVertex3f  (-0.5_glfloat,-0.5_glfloat,-0.5_glfloat )
 CALL glTexCoord2f( 1.0_glfloat, 1.0_glfloat )
 CALL glVertex3f  (-0.5_glfloat, 0.5_glfloat,-0.5_glfloat )
 CALL glTexCoord2f( 1.0_glfloat, 0.0_glfloat )
 CALL glVertex3f  (-0.5_glfloat, 0.5_glfloat, 0.5_glfloat )
CALL glEnd()
CALL glBegin( GL_QUADS )
 CALL glTexCoord2f( 0.0_glfloat, 0.0_glfloat )
 CALL glVertex3f  (-0.5_glfloat, 0.5_glfloat,-0.5_glfloat )
 CALL glTexCoord2f( 0.0_glfloat, 1.0_glfloat )
 CALL glVertex3f  (-0.5_glfloat, 0.5_glfloat, 0.5_glfloat )
 CALL glTexCoord2f( 1.0_glfloat, 1.0_glfloat )
 CALL glVertex3f  ( 0.5_glfloat, 0.5_glfloat, 0.5_glfloat )
 CALL glTexCoord2f( 1.0_glfloat, 0.0_glfloat )
 CALL glVertex3f  ( 0.5_glfloat, 0.5_glfloat,-0.5_glfloat )
CALL glEnd()
CALL glBegin( GL_QUADS )
 CALL glTexCoord2f( 0.0_glfloat, 0.0_glfloat )
 CALL glVertex3f  (-0.5_glfloat,-0.5_glfloat,-0.5_glfloat )
 CALL glTexCoord2f( 0.0_glfloat, 1.0_glfloat )
 CALL glVertex3f  (-0.5_glfloat,-0.5_glfloat, 0.5_glfloat )
 CALL glTexCoord2f( 1.0_glfloat, 1.0_glfloat )
 CALL glVertex3f  ( 0.5_glfloat,-0.5_glfloat, 0.5_glfloat )
 CALL glTexCoord2f( 1.0_glfloat, 0.0_glfloat )
 CALL glVertex3f  ( 0.5_glfloat,-0.5_glfloat,-0.5_glfloat )
CALL glEnd()
!
CALL glDisable( GL_TEXTURE_2D )
CALL glPopMatrix()
CALL glDisable( GL_LIGHTING  )
CALL glDIsable( GL_DEPTH_TEST )
CALL glutSwapBuffers() 
RETURN
END SUBROUTINE display
!---------------------------------------------------------
SUBROUTINE myKbd(key, ix, iy)
IMPLICIT NONE
INTEGER(GLcint), INTENT(IN OUT) :: key, ix, iy
SELECT CASE(key)
 CASE (KEY_ESC) 
  STOP
 CASE DEFAULT
  CONTINUE
END SELECT
CALL glutPostRedisplay()
RETURN
END SUBROUTINE myKbd
!---------------------------------------------------------
SUBROUTINE makeImage()
IMPLICIT NONE
INTEGER :: iheight, iwidth
INTEGER(1), ALLOCATABLE :: image(:)
INTEGER :: iret
CALL ReadBitMapData("tmp.bmp", iwidth, iheight, image)
CALL glPixelStorei( GL_UNPACK_ALIGNMENT, 1 )
CALL glBindTexture( GL_TEXTURE_2D, 1 )
CALL glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S    , GL_REPEAT  )
CALL glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T    , GL_REPEAT  )
CALL glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST )
CALL glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST )
CALL glTexImage2D( GL_TEXTURE_2D, 0, 4, iwidth, iheight,0, &
                    GL_RGBA, GL_UNSIGNED_BYTE, image )
CALL glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL )
CALL glEnable ( GL_TEXTURE_2D )
RETURN
END SUBROUTINE makeImage
!---------------------------------------------------------
SUBROUTINE myInit(progname)
IMPLICIT NONE
CHARACTER(LEN = *), INTENT(IN) :: progname
INTEGER(GLcint) :: iwidth = 700, iheight = 700
INTEGER(GLcint) :: iwin
CALL glutInitWindowPosition( 0_glfloat, 0_glfloat )
CALL glutInitWindowSize( iwidth, iheight )
CALL glutInitDisplayMode( IOR(IOR(GLUT_RGBA, GLUT_DEPTH), GLUT_DOUBLE) )
iwin = glutCreateWindow( progname )
CALL glClearColor( 0.0_glfloat, 0.0_glfloat, 0.0_glfloat, 1.0_glfloat )
CALL glutKeyboardFunc( myKbd )
CALL resetview()
CALL makeImage()
CALL glShadeModel( GL_SMOOTH )
CALL glEnable( GL_LIGHT0 )
RETURN
END SUBROUTINE myInit
!---------------------------------------------------------
SUBROUTINE myReshape(iwidth, iheight)
IMPLICIT NONE
INTEGER(glcint), INTENT(IN OUT) :: iwidth, iheight
REAL(GLDOUBLE) :: aspect 
aspect = REAL(iwidth, glfloat) / REAL(iheight, glfloat)
CALL glViewport( 0, 0, iwidth, iheight )
CALL glMatrixMode( GL_PROJECTION )
CALL glLoadIdentity()
CALL gluPerspective( fovy, aspect, dnear, far )
CALL glMatrixMode( GL_MODELVIEW )
RETURN
END SUBROUTINE myReshape
!---------------------------------------------------------
SUBROUTINE polarview()
IMPLICIT NONE
CALL glTranslatef( 0.0_glfloat, 0.0_glfloat, -distance )
CALL glRotatef(-twist    , 0.0_glfloat, 0.0_glfloat, 1.0_glfloat )
CALL glRotatef(-elevation, 1.0_glfloat, 0.0_glfloat, 0.0_glfloat )
CALL glRotatef(-azimuth  , 0.0_glfloat, 1.0_glfloat, 0.0_glfloat )
RETURN
END SUBROUTINE polarview
!---------------------------------------------------------
SUBROUTINE resetview()
IMPLICIT NONE
distance  =   3.0_glfloat
twist     =   0.0_glfloat
elevation = -30.0_glfloat
azimuth   =  30.0_glfloat
RETURN
END SUBROUTINE resetview
!---------------------------------------------------------
SUBROUTINE myMouse( ibutton, istate, ix, iy )
IMPLICIT NONE
INTEGER(GLcint), INTENT(IN OUT) :: ibutton, istate, ix, iy 
IF (istate == GLUT_DOWN) THEN
 ixBegin = ix
 iyBegin = iy
 mButton = ibutton
END IF
RETURN
END SUBROUTINE myMouse
!---------------------------------------------------------
SUBROUTINE myMotion( ix, iy )
IMPLICIT NONE
INTEGER(GLcint), INTENT(IN OUT) :: ix, iy
INTEGER(GLcint) :: ixDisp, iyDisp
ixDisp = ix - ixBegin
iyDisp = iy - iyBegin
SELECT CASE (mButton)
 CASE (GLUT_LEFT_BUTTON)
  azimuth   = azimuth   + ixDisp / 2.0_GLfloat
  elevation = elevation - iyDisp / 2.0_GLfloat
 CASE (GLUT_MIDDLE_BUTTON)
  twist = AMOD( twist + ixDisp, 360.0_GLfloat )
 CASE (GLUT_RIGHT_BUTTON)
  distance = distance - iyDisp / 40.0_GLfloat
 CASE DEFAULT
  CONTINUE
END SELECT 
ixBegin = ix
iyBegin = iy
CALL glutPostRedisplay()
RETURN
END SUBROUTINE myMotion
!---------------------------------------------------------
END MODULE m_callback
!=========================================================
PROGRAM GLUT8
USE m_callback
IMPLICIT NONE
CALL glutInit()
CALL myInit( 'GLUT8-5' )
CALL glutReshapeFunc( myReshape )
CALL glutDisplayFunc( display )
CALL glutMouseFunc  ( myMouse )
CALL glutMotionFunc ( myMotion )
CALL glutMainLoop()
STOP
END PROGRAM GLUT8