/* =============================================================================== CubeSpin.mc : 自転する立方体を表示 =============================================================================== Copyright (C) 2010-2013 Masahiko Watanabe Edition History: 2010.11.27 初版( GK Library: Rev.2010.11.20 使用 ) 2013.02.15 MikoScript3(ユニコード版)用に変更 -----------------------------------------------------------------------------*/ /*****/ // GK Library のモジュールをロードする場合 #include #include #include if( ::Module.Include( "GkLibrary" ) > 0 ) Main( argc, argv ); return; /*****/ /****** // GK Library のソースをインクルードする場合 #include Main( argc, argv ); return; /*****/ //----------------------------------------------------------------------------- // デバッグプリント無効化(リリース時) #set pc #comment #set pv // デバッグプリント有効化(デバッグ時) //#set pc print //#set pv print #set p print //----------------------------------------------------------------------------- /// マクロ定義 /// #set WndTitle "自転する立方体" // ウィンドウ表題 #set WndXo // ウィンドウの左端位置(空白はデフォールト位置) #set WndYo // ウィンドウの上端位置(空白はデフォールト位置) #set FigXd 480 // 図形描画領域の幅 #set FigYd 480 // 図形描画領域の高さ #set VF_Timer 101 // 画面更新タイマー識別値 #set VF_Rate 30 // 画面更新回数/秒 //----------------------------------------------------------------------------- // OpenGL 関連のマクロ定義 #set GL_AMBIENT 0x1200 #set GL_BACK 0x0405 #set GL_CCW 0x0901 #set GL_COLOR_BUFFER_BIT 0x00004000 #set GL_CULL_FACE 0x0B44 #set GL_DEPTH_BUFFER_BIT 0x00000100 #set GL_DEPTH_TEST 0x0B71 #set GL_DIFFUSE 0x1201 #set GL_FRONT 0x0404 #set GL_LIGHT0 0x4000 #set GL_LIGHTING 0x0B50 #set GL_MODELVIEW 0x1700 #set GL_POSITION 0x1203 #set GL_PROJECTION 0x1701 #set GL_QUADS 0x0007 #set GL_SHININESS 0x1601 #set GL_SPECULAR 0x1202 #set PFD_DOUBLEBUFFER 0x00000001 #set PFD_DRAW_TO_WINDOW 0x00000004 #set PFD_MAIN_PLANE 0 #set PFD_SUPPORT_OPENGL 0x00000020 #set PFD_TYPE_RGBA 0 //============================================================================= function Main( argc, argv ) { #pc "開始"; ^DefValue = null; if( SetupOpenGL() == #OK ) { class ^MainWindow : ::GK.Window {} R = ::GK.Rect( 0, 0, #FigXd, #FigYd ); ::GK.Window.GetAdjRect( R ); ^MainWindow.Construct( #WndTitle, #WndXo, #WndYo, R.Xd, R.Yd ); ^MainWindow.Open(); ^MainWindow.StartTimer( #VF_Timer, 1000 / #VF_Rate ); ::GK.WindowMsgLoop(); delete ^MainWindow; } DeleteOpenGL(); #pc "終了"; } //----------------------------------------------------------------------------- function ^MainWindow.OnCreate() { #pc "OnCreate"; if( .InizOpenGL() != #OK ) { print "OpenGL 初期設定エラー!"; .Close(); } ^glClearColor( 0.0'sfv, 0.2'sfv, 0.5'sfv, 1.0'sfv ); // 背景色 ^glClearDepth( 1.0 ); ^glEnable( #GL_DEPTH_TEST ); ^glEnable( #GL_CULL_FACE ); ^glCullFace( #GL_BACK ); ^glFrontFace( #GL_CCW ); ^glEnable( #GL_LIGHT0 ); LightDir'FLOAT(4) = { 0.0, -1.0, -1.0, 0.0 }; // 光源方向 ^glLightfv( #GL_LIGHT0 , #GL_POSITION, LightDir ); Ambient 'FLOAT(4) = { 0.5, 0.5, 0.5, 1.0 }; // 環境光 Diffuse 'FLOAT(4) = { 1.0, 1.0, 1.0, 1.0 }; // 拡散光 Specular'FLOAT(4) = { 1.0, 1.0, 1.0, 1.0 }; // 鏡面光 ^glLightfv( #GL_LIGHT0, #GL_AMBIENT , Ambient ); ^glLightfv( #GL_LIGHT0, #GL_DIFFUSE , Diffuse ); ^glLightfv( #GL_LIGHT0, #GL_SPECULAR, Specular ); ^glEnable( #GL_LIGHTING ); .InizFigData(); // 描画データの設定 } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - function ^MainWindow.OnDestroy() { #pc "OnDestroy"; .StopTimer( #VF_Timer ); .TermOpenGL(); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - function ^MainWindow.OnSize() { #pc "OnSize", .gc.Xd, .gc.Yd, .Min?(); if( .gc.Xd <= 0 || .gc.Yd <= 0 ) return; ^glViewport( 0, 0, .gc.Xd, .gc.Yd ); ^glMatrixMode( #GL_PROJECTION ); ^glLoadIdentity(); // 透視投影 ^gluPerspective( 15.0, .gc.Xd'float / .gc.Yd, 1.0, 100.0 ); ^gluLookAt( 0.0, 0.0, 10.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0 ); // 直投影 //Cx = .gc.Xd'float / #FigXd; //Cy = .gc.Yd'float / #FigXd; //^glOrtho( -Cx, +Cx, -Cy, +Cy, -100.0, 100.0 ); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - function ^MainWindow.OnPaint() { #pc "OnPaint"; ^glClear( #GL_COLOR_BUFFER_BIT | #GL_DEPTH_BUFFER_BIT ); // 立方体の素材を指定 ^glMaterialfv( #GL_FRONT, #GL_AMBIENT , .Cube.Ambient ); ^glMaterialfv( #GL_FRONT, #GL_DIFFUSE , .Cube.Diffuse ); ^glMaterialfv( #GL_FRONT, #GL_SPECULAR , .Cube.Specular ); ^glMaterialf ( #GL_FRONT, #GL_SHININESS, .Cube.Shininess'sfv ); // 立方体を自転させる変換行列を設定 ^glMatrixMode( #GL_MODELVIEW ); ^glLoadIdentity(); ^glRotated( .Angle, 1.0, 0.0, 0.0 ); // X軸周りに回転 ^glRotated( .Angle, 0.0, 1.0, 0.0 ); // Y軸周りに回転 ^glRotated( .Angle, 0.0, 0.0, 1.0 ); // Z軸周りに回転 //^glScaled( 0.8, 0.8, 0.8 ); // 拡大/縮小 ^glTranslated( -0.5, -0.5, -0.5 ); // 立方体の中心を原点に移動 // 立方体の各面を描画 ^glBegin( #GL_QUADS ); for( j = 0; j < 6 ; j++ ) { ^glNormal3dv( .Cube.Normal( j, 0 )'addr ); for( i = 0 ; i < 4 ; i++ ) ^glVertex3dv( .Cube.Vertex( .Cube.Face( j, i ), 0 )'addr ); } ^glEnd(); ^glFinish(); ^SwapBuffers( .gc.hdc ); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - function ^MainWindow.OnTimer( id ) { //#pc "OnTimer: ", id; if( id == #VF_Timer ) { .Angle = ( .Angle + 1.0 ) % 360.0; .InvalidateRect(); } } //----------------------------------------------------------------------------- function ^MainWindow.InizOpenGL() // OpenGL の初期設定 { #pc "InizOpenGL"; PIXELFORMATDESCRIPTOR ::= { .nSize 'USHORT; .nVersion 'USHORT = 1; .dwFlags 'ULONG = #PFD_DRAW_TO_WINDOW | #PFD_SUPPORT_OPENGL | #PFD_DOUBLEBUFFER ; .iPixelType 'UBYTE = #PFD_TYPE_RGBA; .cColorBits 'UBYTE = 24; // 24-bit color depth .cRedBits 'UBYTE = 0; // color bits ignored .cRedShift 'UBYTE = 0; // 〃 .cGreenBits 'UBYTE = 0; // 〃 .cGreenShift 'UBYTE = 0; // 〃 .cBlueBits 'UBYTE = 0; // 〃 .cBlueShift 'UBYTE = 0; // 〃 .cAlphaBits 'UBYTE = 0; // no alpha buffer .cAlphaShift 'UBYTE = 0; // shift bit ignored .cAccumBits 'UBYTE = 0; // accum bits ignored .cAccumRedBits 'UBYTE = 0; // 〃 .cAccumGreenBits'UBYTE = 0; // 〃 .cAccumBlueBits 'UBYTE = 0; // 〃 .cAccumAlphaBits'UBYTE = 0; // 〃 .cDepthBits 'UBYTE = 32; // 32-bit z-buffer .cStencilBits 'UBYTE = 0; // no stencil buffer .cAuxBuffers 'UBYTE = 0; // no auxiliary buffer .iLayerType 'UBYTE = #PFD_MAIN_PLANE; // main layer .bReserved 'UBYTE = 0; .dwLayerMask 'ULONG = 0; // layer masks ignored .dwVisibleMask 'ULONG = 0; // 〃 .dwDamageMask 'ULONG = 0; // 〃 } PIXELFORMATDESCRIPTOR.nSize = PIXELFORMATDESCRIPTOR'size; pfd = ::Buffer( PIXELFORMATDESCRIPTOR.nSize ); pfd.Write( PIXELFORMATDESCRIPTOR ); pfd.Seek(0); if(( i = ^ChoosePixelFormat( .gc.hdc, pfd )) <= 0 ) return #NG; if( ^SetPixelFormat( .gc.hdc, i, pfd ) == #FALSE ) return #NG; if(( .hRC = ^wglCreateContext( .gc.hdc )) == #NULL ) return #NG; if( ^wglMakeCurrent( .gc.hdc, .hRC ) == #FALSE ) return #NG; return #OK; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - function ^MainWindow.TermOpenGL() // OpenGL の終了設定 { #pc "TermOpenGL"; ^wglMakeCurrent( #NULL, #NULL ); ^wglDeleteContext( .hRC ); } //----------------------------------------------------------------------------- function ^MainWindow.InizFigData() { .Cube ::= { .Vertex'DOUBLE( 8, 3 ) = // 立方体の各頂点 { { 0, 0, 0 }, { 1, 0, 0 }, { 1, 1, 0 }, { 0, 1, 0 }, { 0, 0, 1 }, { 1, 0, 1 }, { 1, 1, 1 }, { 0, 1, 1 } }; .Face'BYTE( 6, 4 ) = // 立方体の各面を構成する頂点のインデックス { { 3, 2, 1, 0 }, { 2, 6, 5, 1 }, { 6, 7, 4, 5 }, { 7, 3, 0, 4 }, { 0, 1, 5, 4 }, { 7, 6, 2, 3 } }; .Normal'DOUBLE( 6, 3 ); // 立方体の各面の法線ベクトル CalcNormal( .Vertex, .Face, .Normal ); // 立方体の材質 .Ambient 'FLOAT(4) = { 0.20, 0.50, 0.50, 1.0 }; // 環境光反射率 .Diffuse 'FLOAT(4) = { 0.40, 1.00, 1.00, 1.0 }; // 拡散光反射率 .Specular'FLOAT(4) = { 0.10, 0.30, 0.30, 1.0 }; // 鏡面光反射率 .Shininess = 10.0; // 鏡面率 } .Angle = 0.0; // 立方体の回転角度(単位:°) } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - function CalcNormal( V, F, N ) // 各面の法線ベクトルを計算する { m = F'count( 1 ); // 面数 for( i = 0 ; i < m ; i++ ) { ( P0, P1, P2 ) = ( F( i, 0 ), F( i, 1 ), F( i, 2 ) ); ( Ax, Ay, Az ) = ( V( P2, 0 ) - V( P0, 0 ), V( P2, 1 ) - V( P0, 1 ), V( P2, 2 ) - V( P0, 2 )); ( Bx, By, Bz ) = ( V( P1, 0 ) - V( P0, 0 ), V( P1, 1 ) - V( P0, 1 ), V( P1, 2 ) - V( P0, 2 )); ( X, Y, Z ) = ( Ay * Bz - Az * By, Az * Bx - Ax * Bz, Ax * By - Ay * Bx ); D = ::Math.sqrt( X*X + Y*Y + Z*Z ); ( N( i, 0 ), N( i, 1 ), N( i, 2 )) = ( X / D, Y / D, Z / D ); } } //============================================================================= function SetupOpenGL() // OpenGL のAPIを取得(必要分のみ) { #pv ^ChoosePixelFormat = ::GK.Gdi32.GetEntry( "ChoosePixelFormat" ); #pv ^SetPixelFormat = ::GK.Gdi32.GetEntry( "SetPixelFormat" ); #pv ^GetPixelFormat = ::GK.Gdi32.GetEntry( "GetPixelFormat" ); #pv ^DescribePixelFormat = ::GK.Gdi32.GetEntry( "DescribePixelFormat" ); #pv ^SwapBuffers = ::GK.Gdi32.GetEntry( "SwapBuffers" ); #pv ^GetEnhMetaFilePixelFormat = ::GK.Gdi32.GetEntry( "GetEnhMetaFilePixelFormat" ); #pv ^GL = ::DLL.Link( "OPENGL32", "sys" ); if( ^GL == null ) { #p "OPENGL32.DLL not found!"; return #NG; } #pv ^GLU = ::DLL.Link( "GLU32", "sys" ); if( ^GLU == null ) { #p "GLU32.DLL not found!"; return #NG; } #pv ^glBegin = ^GL.GetEntry( "glBegin" ); #pv ^glClear = ^GL.GetEntry( "glClear" ); #pv ^glClearColor = ^GL.GetEntry( "glClearColor" ); #pv ^glClearDepth = ^GL.GetEntry( "glClearDepth" ); #pv ^glCullFace = ^GL.GetEntry( "glCullFace" ); #pv ^glEnable = ^GL.GetEntry( "glEnable" ); #pv ^glEnd = ^GL.GetEntry( "glEnd" ); #pv ^glFinish = ^GL.GetEntry( "glFinish" ); #pv ^glFrontFace = ^GL.GetEntry( "glFrontFace" ); #pv ^glLightfv = ^GL.GetEntry( "glLightfv" ); #pv ^glLoadIdentity = ^GL.GetEntry( "glLoadIdentity" ); #pv ^glMaterialf = ^GL.GetEntry( "glMaterialf" ); #pv ^glMaterialfv = ^GL.GetEntry( "glMaterialfv" ); #pv ^glMatrixMode = ^GL.GetEntry( "glMatrixMode" ); #pv ^glNormal3dv = ^GL.GetEntry( "glNormal3dv" ); #pv ^glOrtho = ^GL.GetEntry( "glOrtho" ); #pv ^glRotated = ^GL.GetEntry( "glRotated" ); #pv ^glScaled = ^GL.GetEntry( "glScaled" ); #pv ^glTranslated = ^GL.GetEntry( "glTranslated" ); #pv ^gluLookAt = ^GLU.GetEntry( "gluLookAt" ); #pv ^gluPerspective = ^GLU.GetEntry( "gluPerspective" ); #pv ^glVertex3dv = ^GL.GetEntry( "glVertex3dv" ); #pv ^glViewport = ^GL.GetEntry( "glViewport" ); #pv ^wglCreateContext = ^GL.GetEntry( "wglCreateContext" ); #pv ^wglDeleteContext = ^GL.GetEntry( "wglDeleteContext" ); #pv ^wglMakeCurrent = ^GL.GetEntry( "wglMakeCurrent" ); return #OK; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - function DeleteOpenGL() { delete ^GL; delete ^GLU; } //-----------------------------------------------------------------------------