fortran66のブログ

fortran について書きます。

ARToolKit 中のサンプル SimpleTest の方がより基本的なプログラムのようなので、こちらをいじることにします。

mainLoop 中での描画ルーチン draw を Fortran で記述したルーチンに置き換えます。

サンプルを少し書き換えて、立方体の上にワイヤーフレームの球を乗せています。

C 側の変更点は mainLoop 中の draw を、Fortran で記述した draw2 の呼び出しへの書き換えです。

/* get the transformation between the marker and the real camera */
arGetTransMat(&marker_info[k], patt_center, patt_width, patt_trans);
draw2();
argSwapBuffers();
}

Fortran 側で厄介なのは、ARToolKit ライブラリのサブルーチンの引数などのインターフェースの記述です。サブルーチンの引き数が、値呼び出しか、参照呼出しか注意が必要です。グローバル変数の扱いは Intel のマニュアル通りでうまく行きます。2次元配列は Fortran と C では行と列が入れ替わっていますのでこれも注意が必要です。

SUBROUTINE draw2() BIND(C)
USE, INTRINSIC :: ISO_C_BINDING 
USE opengl_gl
USE opengl_glu
USE opengl_glut
IMPLICIT NONE
!
INTERFACE
 SUBROUTINE argDrawMode3D() BIND(C)
 !DEC$ ATTRIBUTES C, DECORATE, ALIAS:'argDrawMode3D' :: argDrawMode3D 
 END SUBROUTINE argDrawMode3D
 !
 SUBROUTINE argDraw3dCamera(ix, iy) BIND(C)
 USE opengl_gl
 !DEC$ ATTRIBUTES C, DECORATE, ALIAS:'argDraw3dCamera' :: argDraw3dCamera
 INTEGER(glcint), VALUE :: ix, iy 
 END SUBROUTINE argDraw3dCamera
 !
 SUBROUTINE argConvGlpara(x, y) BIND(C)
 USE opengl_gl
 !DEC$ ATTRIBUTES C, DECORATE, ALIAS:'argConvGlpara' :: argConvGlpara
 REAL(gldouble) :: x(4, 3), y(4, 4) 
 END SUBROUTINE argConvGlpara
END INTERFACE
!
! global variable
!DEC$ ATTRIBUTES C, EXTERN :: patt_trans
REAL(gldouble) :: patt_trans(4, 3)
!
REAL(gldouble) :: gl_para(4, 4)
REAL(glfloat ) :: mat_ambient(4) = (/0.0, 0.0, 1.0, 1.0/)
REAL(glfloat ) :: mat_flash(4)   = (/0.0, 0.0, 1.0, 1.0/)
REAL(glfloat ) :: mat_flash_shiny(1) = (/50.0/)
REAL(glfloat ) :: light_position(4)  = (/100.0,-200.0,200.0,0.0/)
REAL(glfloat ) :: ambi(4)            = (/0.1, 0.1, 0.1, 0.1/)
REAL(glfloat ) :: lightZeroColor(4)  = (/0.9, 0.9, 0.9, 0.1/)
!    
CALL argDrawMode3D()
CALL argDraw3dCamera( 0, 0 )
CALL glClearDepth( 1.0_gldouble )
CALL glClear(GL_DEPTH_BUFFER_BIT)
CALL glEnable(GL_DEPTH_TEST)
CALL glDepthFunc(GL_LEQUAL)
!    /* load the camera transformation matrix */
CALL argConvGlpara(patt_trans, gl_para)
CALL glMatrixMode(GL_MODELVIEW)
CALL glLoadMatrixd( gl_para )
CALL glEnable(GL_LIGHTING)
CALL glEnable(GL_LIGHT0)
CALL glLightfv(GL_LIGHT0, GL_POSITION, light_position)
CALL glLightfv(GL_LIGHT0, GL_AMBIENT, ambi)
CALL glLightfv(GL_LIGHT0, GL_DIFFUSE, lightZeroColor)
CALL glMaterialfv(GL_FRONT, GL_SPECULAR, mat_flash)
CALL glMaterialfv(GL_FRONT, GL_SHININESS, mat_flash_shiny)	
CALL glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient)
CALL glMatrixMode(GL_MODELVIEW)
CALL glTranslatef( 0.0_glfloat, 0.0_glfloat, 25.0_glfloat )
CALL glutSolidCube( 50.0_gldouble )
CALL glTranslatef( 0.0_glfloat, 0.0_glfloat, 50.0_glfloat )
CALL glutWireSphere( 30.0_gldouble, 10, 10 )
CALL glDisable( GL_LIGHTING )
CALL glDisable( GL_DEPTH_TEST )
RETURN
END SUBROUTINE draw2