void Framework::update(){ setFrameRate( 60 ); //元の頂点配列 Vector3 p[ 4 ]; unsigned c[ 4 ]; //わかりやすいように色 p[ 0 ].set( -1000.0, 0.0, -1000.0 ); p[ 1 ].set( -1000.0, 0.0, 1000.0 ); p[ 2 ].set( 1000.0, 0.0, -1000.0 ); p[ 3 ].set( 1000.0, 0.0, 1000.0 ); c[ 0 ] = 0xffff0000; //赤 c[ 1 ] = 0xff00ff00; //緑 c[ 2 ] = 0xff0000ff; //青 c[ 3 ] = 0xffffffff; //白 //ビュー行列を作ろう Matrix34 m; m.setViewTransform( gEyePosition, gEyeTarget ); //この中が本体なのでそっちを参照のこと //行列にベクタをかけて回る for ( int i = 0; i < 4; ++i ){ m.multiply( &p[ i ], p[ i ] ); } //ニアクリップとファークリップ const double nearClip = 1.0; const double farClip = 10000.0; //ニアとファーからZ範囲変換の式を作る const double zConvA = 1.0 / ( nearClip - farClip ); //1/(n-f) const double zConvB = nearClip * zConvA; //n/(n-f) //ハードウェアに渡す準備をする。4次元化 double p4[ 4 ][ 4 ]; for ( int i = 0; i < 4; ++i ){ p4[ i ][ 0 ] = p[ i ].x; //yに640/480をかけて縦横比を調整 p4[ i ][ 1 ] = p[ i ].y * 640.0 / 480.0; //wに範囲変換前のzを「マイナスにして」格納。Z軸が手前向きだとこのマイナスが必要。 p4[ i ][ 3 ] = -p[ i ].z; //z範囲変換 p4[ i ][ 2 ] = zConvA * p[ i ].z + zConvB; //範囲変換もZ軸の向きを //zにwをかけておく。 p4[ i ][ 2 ] *= p4[ i ][ 3 ]; } //四角形を描く。 drawTriangle3DH( p4[ 0 ], p4[ 1 ], p4[ 2 ], 0, 0, 0, c[ 0 ], c[ 1 ], c[ 2 ] ); drawTriangle3DH( p4[ 3 ], p4[ 1 ], p4[ 2 ], 0, 0, 0, c[ 3 ], c[ 1 ], c[ 2 ] ); ++gCount; //視点と注視点を適当にいじる gEyePosition.x = sin( gCount ) * 2000; gEyePosition.z = cos( gCount ) * 2000; gEyePosition.y = 1000.f; gEyeTarget.x = gCount % 100; gEyeTarget.y = gCount % 200; gEyeTarget.z = gCount % 300; }
void Framework::update(){ WindowCreator wc = WindowCreator::instance(); if ( gFirst ){ const char* filename = wc.commandLineString(); if ( filename && filename[ 0 ] != '\0' ){ load( filename ); } gFirst = false; }else{ //ドラッグアンドドロップを処理する int dropN = wc.droppedItemNumber(); if ( dropN > 0 ){ const char* filename = wc.droppedItem( 0 ); //0番以外無視 load( filename ); wc.clearDroppedItem(); //これを呼ぶとfilenameもこわれるので最後に。 } } //カメラ入力反映 Input::Manager im = Input::Manager::instance(); Input::Mouse mouse = im.mouse(); Input::Keyboard keyboard = im.keyboard(); if ( mouse.isOn( Input::Mouse::BUTTON_MIDDLE ) ){ Graphics::Manager().captureScreen( "capture.tga" ); } //ビュー行列を作ろう Vector3 eyePosition = gEyeTarget; eyePosition.z += gEyeDistance; Matrix34 rm; rm.setRotationY( gAngleY ); rm.rotateX( gAngleX ); Vector3 tv( 0.f, 0.f, 1.f ); rm.mul( &tv, tv ); eyePosition.setMadd( gEyeTarget, tv, gEyeDistance ); Matrix34 zrm; zrm.setRotationZ( gAngleZ ); Vector3 up( 0.f, 1.f, 0.f ); zrm.mul( &up, up ); Matrix34 vm; vm.setViewTransform( eyePosition, gEyeTarget, up ); if ( gContainer ){ float x = static_cast< float >( mouse.velocityX() ); float y = static_cast< float >( mouse.velocityY() ); if ( mouse.isOn( Input::Mouse::BUTTON_LEFT ) && mouse.isOn( Input::Mouse::BUTTON_RIGHT ) ){ //両ボタンでZ回転 gAngleZ -= 0.2f * x; gAngleZ -= 0.2f * y; }else if ( mouse.isOn( Input::Mouse::BUTTON_LEFT ) ){ //左ボタン回転 gAngleX -= 0.2f * y; if ( gAngleX > 89.9f ){ gAngleX = 89.9f; }else if ( gAngleX < -89.9f ){ gAngleX = -89.9f; } gAngleY -= 0.5f * x; }else if ( mouse.isOn( Input::Mouse::BUTTON_RIGHT ) ){ //右ボタン、注視点移動 Vector3 xv( vm.m00, vm.m01, vm.m02 ); xv *= x; Vector3 yv( vm.m10, vm.m11, vm.m12 ); yv *= y; gEyeTarget.madd( xv, -0.003f * gEyeDistance ); gEyeTarget.madd( yv, 0.003f * gEyeDistance ); } int w = mouse.wheel(); if ( w < 0 ){ gEyeDistance *= 0.9f; }else if ( w > 0 ){ gEyeDistance *= 1.1f; } } //透視変換行列 Matrix44 pm; pm.setPerspectiveTransform( 60.f, static_cast< float >( width() ), static_cast< float >( height() ), gEyeDistance * 0.01f, gEyeDistance * 10.f ); //次にPVを作る pm *= vm; if ( keyboard.isOn( 'G' ) ){ gAngleX = gAngleY = gAngleZ = 0.f; gEyeTarget = 0.f; } //ライトでもうごかそか Graphics::Manager gm = Graphics::Manager::instance(); gm.setProjectionViewMatrix( pm ); gm.setLightingMode( LIGHTING_PER_PIXEL ); gm.enableDepthTest( true ); gm.enableDepthWrite( true ); gm.setLightColor( 0, Vector3( 1.f, 1.f, 1.f ) ); //白 gm.setLightColor( 1, Vector3( 1.f, 0.7f, 0.7f ) ); //赤 gm.setLightColor( 2, Vector3( 0.7f, 1.f, 0.7f ) ); //緑 gm.setLightColor( 3, Vector3( 0.7f, 0.7f, 1.f ) ); //青 gm.setAmbientColor( Vector3( 0.2f, 0.2f, 0.2f ) ); gm.setEyePosition( eyePosition ); float t = gEyeDistance * 0.4f; float lightIntensity[ 4 ]; for ( int i = 0; i < 4; ++i ){ lightIntensity[ i ] = t; } Vector3 lightPositions[ 4 ]; for ( int i = 0; i < 4; ++i ){ float t = static_cast< float >( gCount * ( i + 1 ) ) / 5.f; float d = gEyeDistance * 2.f; lightPositions[ i ].set( sin( t )*cos( t ) * d, sin( t )*sin( t ) * d, cos( t ) * d ); lightPositions[ i ] += gEyeTarget; } for ( int i = 0; i < 4; ++i ){ gm.setLightPosition( i, lightPositions[ i ] ); gm.setLightIntensity( i, lightIntensity[ i ] ); } for ( int i = 0; i < gModels.size(); ++i ){ gModels[ i ].draw(); } //アニメ切り替え if ( keyboard.isTriggered( ' ' ) ){ if ( gContainer.animationNumber() > 0 ){ ++gAnimationIndex; if ( gAnimationIndex >= gContainer.animationNumber() ){ gAnimationIndex = 0; } for ( int i = 0; i < gTrees.size(); ++i ){ gTrees[ i ].setAnimation( gContainer.animation( gAnimationIndex ) ); } } } for ( int i = 0; i < gTrees.size(); ++i ){ gTrees[ i ].updateAnimation(); gTrees[ i ].draw(); } if ( isEndRequested() ){ gModels.clear(); gTrees.clear(); gContainer.release(); } ++gCount; }
void Framework::update(){ if ( !gDatabase ){ setFrameRate( 60 ); gDatabase = new GraphicsDatabase( "cube.txt" ); gModel = gDatabase->createModel( "cube" ); /*補間の方程式を解く。 p0 = a*t0^2 + b*t0 + c ...(0) p1 = a*t1^2 + b*t1 + c ...(1) 2a*t0 + b = v ...(2) まず一番式の形が単純な(2)を使ってb=の形にする。 b = v - 2a*t0 ...(3) 次に(1)-(0)でcを消す。 p1 - p0 = a(t1^2- t0^2) + b(t1 - t0) ...(4) (4)に(3)を代入してやる。 p1 - p0 = a(t1^2- t0^2) + (v-2a*t0)(t1 - t0) がんばって展開する。 p1 - p0 = a( t1^2 - t0^2 - 2*t0*t1 + 2*t0^2 ) + v(t1-t0) aで整理する a( t0^2 - 2*t0*t1 + t1^2 ) = (p1-p0) - v(t1-t0) ここでaの係数は(t0-t1)^2に因数分解できる。 aについて解けて、 a = ((p1-p0) - v(t1-t0)) / ( t0-t1 )^2 ...(5) 後は(3)を使ってbが出るし、(0)を使ってcも出る。 */ Vector3 v( 0.0, 0.0, 0.0 ); //第一区間の始点の傾きが0としようか。3つ計算するのでベクタ。 //以下XYZで別々の計算をするが、見やすいようにベクタクラスの計算関数は使わない。要素毎計算で行く。 for ( int i = 0; i < N-1; ++i ){ //点の数がNなんだから区間の数はN-1 //見やすいように定数を作る。 Vector3 p0 = gPoints[ i ]; Vector3 p1 = gPoints[ i + 1 ]; double t0 = gTimes[ i ]; double t02 = t0 * t0; double t1 = gTimes[ i + 1 ]; double t10 = t1 - t0; double t102 = t10 * t10; Vector3 a,b,c; //xyzで計算するから全部ベクタ //まずaを求める。 a.x = ( ( p1.x - p0.x ) - v.x*t10 ) / t102; a.y = ( ( p1.y - p0.y ) - v.y*t10 ) / t102; a.z = ( ( p1.z - p0.z ) - v.z*t10 ) / t102; //次がb b.x = v.x - 2.0 * a.x * t0; b.y = v.y - 2.0 * a.y * t0; b.z = v.z - 2.0 * a.z * t0; //最後にc c.x = p0.x - a.x*t02 - b.x*t0; c.y = p0.y - a.y*t02 - b.y*t0; c.z = p0.z - a.z*t02 - b.z*t0; //式を保存 gEquations[ i ][ 0 ] = a; gEquations[ i ][ 1 ] = b; gEquations[ i ][ 2 ] = c; //終点の傾きを計算 v.x = 2.0 * a.x * t1 + b.x; v.y = 2.0 * a.y * t1 + b.y; v.z = 2.0 * a.z * t1 + b.z; } } //ループ処理する。 double period = gTimes[ N - 1 ]; double quot = gT / period; int quotInt = static_cast< int >( quot ); gT -= static_cast< double >( quotInt ) * period; //区間を検索 int last = 0; for ( int i = 0; i < N; ++i ){ if ( gTimes[ i ] > gT ){ break; } last = i; } //式にぶちこんで値を出す Vector3 p; Vector3 a = gEquations[ last ][ 0 ]; Vector3 b = gEquations[ last ][ 1 ]; Vector3 c = gEquations[ last ][ 2 ]; Vector3 p0 = gPoints[ last ]; Vector3 p1 = gPoints[ last + 1 ]; p.x = ( ( a.x * gT ) + b.x ) * gT + c.x; p.y = ( ( a.y * gT ) + b.y ) * gT + c.y; p.z = ( ( a.z * gT ) + b.z ) * gT + c.z; //値が決まった。モデルにセット gModel->setPosition( p ); Matrix44 pm; pm.setPerspectiveTransform( 45.0, width(), height(), 1.0, 10000.0 ); Matrix34 vm; vm.setViewTransform( Vector3( 0.0, 30.0, 30.0 ), Vector3( 0.0, 0.0, 0.0 ) ); pm *= vm; gModel->draw( pm, Vector3( 0.0, 1.0, 0.0 ), Vector3( 1.0, 1.0, 1.0 ), Vector3( 0.2, 0.2, 0.2 ) ); gT += 1.0; if ( isEndRequested() ){ SAFE_DELETE( gModel ); SAFE_DELETE( gDatabase ); } }
void Framework::update(){ if ( gCount == 0 ){ //描画クラスを1000頂点、100バッチで初期化 gPrimitiveRenderer = PrimitiveRenderer::create( 1000, 100 ); //テクスチャロード gTexture = Texture::create( "test.tga" ); while ( !gTexture.isReady() ){ ; //ロード待ち } } //元の頂点配列 Vector3 p[ 4 ]; Vector2 t[ 4 ]; unsigned c[ 4 ]; //わかりやすいように色 p[ 0 ].set( -1.f, -1.f, 0.f ); p[ 1 ].set( -1.f, 1.f, 0.f ); p[ 2 ].set( 1.f, -1.f, 0.f ); p[ 3 ].set( 1.f, 1.f, 0.f ); t[ 0 ].set( 0.f, 0.f ); t[ 1 ].set( 0.f, 1.f ); t[ 2 ].set( 1.f, 0.f ); t[ 3 ].set( 1.f, 1.f ); c[ 0 ] = 0xffff0000; //赤 c[ 1 ] = 0xff00ff00; //緑 c[ 2 ] = 0xff0000ff; //青 c[ 3 ] = 0xffffffff; //白 //ワールド変換(Z回転) Matrix34 wm; wm.setRotationZ( gCount * 2.f ); //ビュー行列を作ろう Vector3 eyePosition; eyePosition.x = sin( gCount / 2.f ) * 4.f; eyePosition.z = cos( gCount / 2.f ) * 4.f; eyePosition.y = 1.f; Vector3 eyeTarget( 0.f, 0.f, 0.f ); Matrix34 vm; vm.setViewTransform( eyePosition, eyeTarget, Vector3( 0.f, 1.f, 0.f ) ); //透視変換行列 Matrix44 pm; pm.setPerspectiveTransform( 60.f, static_cast< float >( width() ), static_cast< float >( height() ), 1.f, 100.f ); //まずVWを作る vm *= wm; //次にPVWを作る pm *= vm; //行列セット gPrimitiveRenderer.setTransform( pm ); //テクスチャセット gPrimitiveRenderer.setTexture( gTexture ); gPrimitiveRenderer.setBlendMode( Graphics::BLEND_LINEAR ); //カウントで何を描くか変えてみよう if ( gCount % 300 > 200 ){ //三角形 gPrimitiveRenderer.addTriangle( p[ 0 ], p[ 1 ], p[ 2 ], t[ 0 ], t[ 1 ], t[ 2 ], c[ 0 ], c[ 1 ], c[ 2 ] ); gPrimitiveRenderer.addTriangle( p[ 3 ], p[ 1 ], p[ 2 ], t[ 3 ], t[ 1 ], t[ 2 ], c[ 3 ], c[ 1 ], c[ 2 ] ); }else if ( gCount % 300 > 100 ){ //線 //線を足す for ( int i = 0; i < 4; ++i ){ for ( int j = i + 1; j < 4; ++j ){ gPrimitiveRenderer.addLine( p[ i ], p[ j ], t[ i ], t[ j ], c[ i ], c[ j ] ); } } }else{ //点 gPrimitiveRenderer.addPoint( p[ 0 ], t[ 0 ], c[ 0 ] ); gPrimitiveRenderer.addPoint( p[ 1 ], t[ 1 ], c[ 1 ] ); gPrimitiveRenderer.addPoint( p[ 2 ], t[ 2 ], c[ 2 ] ); gPrimitiveRenderer.addPoint( p[ 3 ], t[ 3 ], c[ 3 ] ); } //スプライトとか書いてみようか。 //アルファブレンド有効化 gPrimitiveRenderer.setBlendMode( Graphics::BLEND_LINEAR ); Vector2 p2[ 2 ]; p2[ 0 ].set( 0.f, 0.f ); //左上 p2[ 1 ].set( 128.f, 256.f ); //右下 gPrimitiveRenderer.addRectangle( p2[ 0 ], p2[ 1 ], t[ 0 ], t[ 3 ], ( ( gCount % 256 ) << 24 ) | 0xffffff ); //足し終わったので描く gPrimitiveRenderer.draw(); DebugScreen() << frameRate(); ++gCount; if ( isEndRequested() ){ gPrimitiveRenderer.release(); //グローバルなので開放処理が必要 gTexture.release(); } }