//3次元回転描画 void DrawImpl::rot3D(const Vector2& pos, const Vector2& exRate, float zRot, float xRot, float yRot, int gHandle, int turnFlag){ MATRIX m; int w, h; GetGraphSize(gHandle, &w, &h); w = (int)(w*exRate.x); h = (int)(h*exRate.y); if (turnFlag == TRUE) w *= -1; VECTOR v[4] = { VGet(-(float)w / 2, -(float)h / 2, 0), VGet((float)w / 2, -(float)h / 2, 0) , VGet(-(float)w / 2, (float)h / 2, 0), VGet((float)w / 2, (float)h / 2, 0) }; m = MGetRotZ(zRot); for (int i = 0; i < 4; i++) v[i] = VTransform(v[i], m); if (xRot != 0.0f) { m = MGetRotX(xRot); for (int i = 0; i < 4; i++) v[i] = VTransform(v[i], m); } if (yRot != 0.0f) { m = MGetRotY(yRot); for (int i = 0; i < 4; i++) v[i] = VTransform(v[i], m); } DrawModiGraphF(pos.x + v[0].x, pos.y + v[0].y, pos.x + v[1].x, pos.y + v[1].y, pos.x + v[3].x, pos.y + v[3].y, pos.x + v[2].x, pos.y + v[2].y, gHandle, TRUE); }
void JupiterSystemDiorama::setVertex() { static MATRIX WorkMat; // #### 自転角、公転角から、ローカル座標における位置を計算 m_pPrimalyObj->resetVertex(); // 主星 - 自転 WorkMat = MGetRotY( (float)m_dPrimalyRotateAngle ); // 主星 - ワールド座標に変換 WorkMat = MMult( WorkMat, m_mLocalToWorldMatrix ); // Vertexに反映 m_pPrimalyObj->MatTransVertex( WorkMat ); // 衛星 for( int i=0; i<m_iSatelliteNum; i++ ) { m_cSatelliteObjList[i].resetVertex(); // 自転 WorkMat = MGetRotY( (float)m_dSatelliteRotateAngleList[i] ); // 公転 Vector2D OrbitalPos2D( 1, 0 ); OrbitalPos2D = m_pSatelliteOrbitalRadius[i] * OrbitalPos2D.rot(m_dSatelliteOrbitalAngleList[i]); //Vector3D OrbitalPos3D = OrbitalPos2D.toVector3D(); WorkMat.m[3][0] = OrbitalPos2D.x; WorkMat.m[3][2] = OrbitalPos2D.y; // ワールド座標に変換 WorkMat = MMult( WorkMat, m_mLocalToWorldMatrix ); // 座標変換行列を合成するときは、先に作用させたい行列を MMult の左側に置くこと。 // Vertexに反映 m_cSatelliteObjList[i].MatTransVertex( WorkMat ); // 軌道線 m_cSatelliteOrbitalObjList[i].resetVertex(); m_cSatelliteOrbitalObjList[i].MatTransVertex( m_mLocalToWorldMatrix ); } };
void MODEL :: display(){ /*DrawCapsule3D( VGet(x+600*sinf(rotateY), y+y0+200.0f-500*sinf(rotateX), z+600*cosf(rotateY)), VGet(x-200*sinf(rotateY), y+y0+200.0f+500*sinf(rotateX), z-200*cosf(rotateY)), 210.0f, 2, GetColor(255,255,255), GetColor(255,255,255), FALSE);*/ playTime += 200.0f; if(playTime >= animTime) playTime = 0.0f; mS->move(); mS->display(); MV1RefreshCollInfo(ModelHandle, 39); MATRIX rot = MMult(MMult(MGetRotX(rotateX), MGetRotZ(rotateZ)),MGetRotY(rotateY)); MATRIX trans = MGetTranslate(VGet(x+x0, y+y0, z+z0)); MV1SetMatrix(ModelHandle, MMult(rot, trans)); MV1SetAttachAnimTime(ModelHandle, attachIndex, playTime); MV1DrawModel(ModelHandle); }
// カメラの処理 void Camera_Process( void ) { // パッドの3ボタンか、シフトキーが押されている場合のみ角度変更操作を行う if( CheckHitKey( KEY_INPUT_LSHIFT ) || ( inp.NowInput & PAD_INPUT_C ) ) { // 「←」ボタンが押されていたら水平角度をマイナスする if( inp.NowInput & PAD_INPUT_LEFT ) { cam.AngleH -= CAMERA_ANGLE_SPEED ; // −180度以下になったら角度値が大きくなりすぎないように360度を足す if( cam.AngleH < -DX_PI_F ) { cam.AngleH += DX_TWO_PI_F ; } } // 「→」ボタンが押されていたら水平角度をプラスする if( inp.NowInput & PAD_INPUT_RIGHT ) { cam.AngleH += CAMERA_ANGLE_SPEED ; // 180度以上になったら角度値が大きくなりすぎないように360度を引く if( cam.AngleH > DX_PI_F ) { cam.AngleH -= DX_TWO_PI_F ; } } // 「↑」ボタンが押されていたら垂直角度をマイナスする if( inp.NowInput & PAD_INPUT_UP ) { cam.AngleV -= CAMERA_ANGLE_SPEED ; // ある一定角度以下にはならないようにする if( cam.AngleV < -DX_PI_F / 2.0f + 0.6f ) { cam.AngleV = -DX_PI_F / 2.0f + 0.6f ; } } // 「↓」ボタンが押されていたら垂直角度をプラスする if( inp.NowInput & PAD_INPUT_DOWN ) { cam.AngleV += CAMERA_ANGLE_SPEED ; // ある一定角度以上にはならないようにする if( cam.AngleV > DX_PI_F / 2.0f - 0.6f ) { cam.AngleV = DX_PI_F / 2.0f - 0.6f ; } } } // カメラの注視点はプレイヤー座標から規定値分高い座標 cam.Target = VAdd( pl.CharaInfo.Position, VGet( 0.0f, CAMERA_PLAYER_TARGET_HEIGHT, 0.0f ) ) ; // カメラの座標を決定する { MATRIX RotZ, RotY ; float Camera_Player_Length ; MV1_COLL_RESULT_POLY_DIM HRes ; int HitNum ; // 水平方向の回転はY軸回転 RotY = MGetRotY( cam.AngleH ) ; // 垂直方向の回転はZ軸回転 ) RotZ = MGetRotZ( cam.AngleV ) ; // カメラからプレイヤーまでの初期距離をセット Camera_Player_Length = CAMERA_PLAYER_LENGTH ; // カメラの座標を算出 // X軸にカメラとプレイヤーとの距離分だけ伸びたベクトルを // 垂直方向回転( Z軸回転 )させたあと水平方向回転( Y軸回転 )して更に // 注視点の座標を足したものがカメラの座標 cam.Eye = VAdd( VTransform( VTransform( VGet( -Camera_Player_Length, 0.0f, 0.0f ), RotZ ), RotY ), cam.Target ) ; // 注視点からカメラの座標までの間にステージのポリゴンがあるか調べる HRes = MV1CollCheck_Capsule( stg.ModelHandle, -1, cam.Target, cam.Eye, CAMERA_COLLISION_SIZE ); HitNum = HRes.HitNum ; MV1CollResultPolyDimTerminate( HRes ) ; if( HitNum != 0 ) { float NotHitLength ; float HitLength ; float TestLength ; VECTOR TestPosition ; // あったら無い位置までプレイヤーに近づく // ポリゴンに当たらない距離をセット NotHitLength = 0.0f ; // ポリゴンに当たる距離をセット HitLength = Camera_Player_Length ; do { // 当たるかどうかテストする距離をセット( 当たらない距離と当たる距離の中間 ) TestLength = NotHitLength + ( HitLength - NotHitLength ) / 2.0f ; // テスト用のカメラ座標を算出 TestPosition = VAdd( VTransform( VTransform( VGet( -TestLength, 0.0f, 0.0f ), RotZ ), RotY ), cam.Target ) ; // 新しい座標で壁に当たるかテスト HRes = MV1CollCheck_Capsule( stg.ModelHandle, -1, cam.Target, TestPosition, CAMERA_COLLISION_SIZE ); HitNum = HRes.HitNum ; MV1CollResultPolyDimTerminate( HRes ) ; if( HitNum != 0 ) { // 当たったら当たる距離を TestLength に変更する HitLength = TestLength ; } else { // 当たらなかったら当たらない距離を TestLength に変更する NotHitLength = TestLength ; } // HitLength と NoHitLength が十分に近づいていなかったらループ }while( HitLength - NotHitLength > 0.1f ) ; // カメラの座標をセット cam.Eye = TestPosition ; } } }
void CameraWorkManager::Update_RotateCamOnGazePoint( double timeslice ) { static const double DrugMoveScale=0.005; // ドラッグ量に対する視点の移動量のパラメータ static Vector2D ScreenDrugStartPoint; // マウスでドラッグを開始したスクリーン上の座標を格納 static Vector2D SavedCamDist; // マウスでドラッグを開始したときの、m_dTilt、m_dHead を保持 static bool nowDruging=false; // 今ドラッグ中か? // キー入力から、m_dTilt と m_dHead を更新 //getKeyInput(); // スクロール操作から、カメラと注視点の距離を更新 getMouseWheelInput(timeslice); // マウスによるドラッグ操作により、m_dTilt と m_dHead を更新 if( nowDruging ) { // 今ドラッグ中 // ドラッグ終了したかを判定 if( ( GetMouseInput() & MOUSE_INPUT_LEFT ) == 0 ) { // ドラッグ終了 nowDruging = false; } else { // 今のマウス位置を取得 Point2D pos; GetMousePoint( &(pos.x) , &(pos.y) ); Vector2D CurMousePos( (double)pos.x, (double)pos.y); // m_dTilt と m_dHead を更新 Vector2D NewCamDist = -DrugMoveScale*(CurMousePos-ScreenDrugStartPoint)+SavedCamDist; m_dTilt = NewCamDist.y; m_dHead = NewCamDist.x; } } else { // ドラッグ中でない // ドラッグ開始したかを判定 int button; Point2D pos; if( GetMouseInputLog( &button, &pos.x, &pos.y, TRUE )==0 && ( button & MOUSE_INPUT_LEFT ) != 0 ) { // ドラッグが開始された // ドラッグ開始時の マウス座標を ScreenDrugStartPoint に保持 ScreenDrugStartPoint = pos.toRealVector(); // ドラッグ開始時の m_dTilt、m_dHead の値を SavedCamDist に保持 SavedCamDist.y = m_dTilt; SavedCamDist.x = m_dHead; // ドラッグフラグを立てる nowDruging = true; } } // m_dHead と m_dTilt から、(GazingPointを原点とした)カメラの位置を計算する Vector3D Hedding3D( 1.0, 0, 0 ); Hedding3D = VTransform( Hedding3D.toVECTOR(), MGetRotZ( (float)m_dTilt ) ); // もしかしたら、マイナスにしないと駄目かも Hedding3D = VTransform( Hedding3D.toVECTOR(), MGetRotY( -1*(float)m_dHead ) ); Vector3D toCamPos3D = m_dCamDistFrmFP * Hedding3D ; // ### ビュー行列を生成を確認 // カメラの座標変換行列のz軸向き(=カメラの向き) Vector3D vViewBaseZ = -1 * Hedding3D; // カメラの座標変換行列のy軸向きを仮置き Vector3D vViewBaseY( 0.0, 1.0, 0.0 ); // カメラの座標変換行列のx軸向き(= y × z ) Vector3D vViewBaseX = VCross( vViewBaseY.toVECTOR(), vViewBaseZ.toVECTOR() ); vViewBaseX = vViewBaseX.normalize(); // カメラの座標変換行列のy軸向きを再調整 vViewBaseY = VCross( vViewBaseZ.toVECTOR(), vViewBaseX.toVECTOR() ); // 基底を組み合わせてカメラ座標変換行列(Entityローカル座標)を生成 MATRIX MCamTransMatLocal = MGetAxis1( //MakeMatrixFromBaseVec( vViewBaseX.toVECTOR(), vViewBaseY.toVECTOR(), vViewBaseZ.toVECTOR(), toCamPos3D.toVECTOR() ); MCamTransMatLocal.m[3][1] += m_TrgtHight; // Entity位置だけシフトしたものがワールド座標でのカメラ座標変換行列 MATRIX MCamTransMatWorld = MCamTransMatLocal; MCamTransMatWorld.m[3][0] += m_TargetPos.x; //MCamTransMatWorld.m[3][1] += m_TrgtHight; <- MCamTransMatLocal の段階でシフト MCamTransMatWorld.m[3][2] += m_TargetPos.z; // 逆行列がビュー行列 m_MViewLocal = MInverse( MCamTransMatLocal ); m_MViewWorld = MInverse( MCamTransMatWorld ); // 背景パノラマ球の描画に使用しているため m_vFinalCamPos を参照している m_vFinalCamPos = VTransform( Vector3D( 0,0,0 ).toVECTOR(), MCamTransMatWorld ); };