//============================================================================= // スケールマトリックス生成 //============================================================================= void MATRIX4::Matrix4Scale(MATRIX4 * MtxScl, float x, float y, float z) { Matrix4Identity(MtxScl); MtxScl->m11 = x; MtxScl->m22 = y; MtxScl->m33 = z; }
//============================================================================= // 移動マトリックス生成 //============================================================================= void MATRIX4::Matrix4Translate(MATRIX4 * MtxTrans, float x, float y, float z) { Matrix4Identity(MtxTrans); MtxTrans->m41 = x; MtxTrans->m42 = y; MtxTrans->m43 = z; }
//============================================================================= // ビューポート行列生成 //============================================================================= void MATRIX4::Matrix4Viewport(MATRIX4* Matrix4, float Width, float Height) { Matrix4Identity(Matrix4); Matrix4->m11 = Width * 0.5f; Matrix4->m22 = -Height * 0.5f; Matrix4->m41 = Width * 0.5f; Matrix4->m42 = Height * 0.5f; }
//============================================================================= // XYZ軸回転マトリックス生成 //============================================================================= void MATRIX4::Matrix4Rotation(MATRIX4 * MtxOut, float x, float y, float z) { MATRIX4 mtxRotX, mtxRotY, mtxRotZ; float sinx, cosx, siny, cosy, sinz, cosz; sinx = sinf(x); cosx = cosf(x); siny = sinf(y); cosy = cosf(y); sinz = sinf(z); cosz = cosf(z); // 単位行列作成 Matrix4Identity(MtxOut); Matrix4Identity(&mtxRotX); Matrix4Identity(&mtxRotY); Matrix4Identity(&mtxRotZ); // XYZ回転行列作成 mtxRotX.m22 = cosx; mtxRotX.m23 = sinx; mtxRotX.m32 = -sinx; mtxRotX.m33 = cosx; mtxRotY.m11 = cosy; mtxRotY.m13 = -siny; mtxRotY.m31 = siny; mtxRotY.m33 = cosy; mtxRotZ.m11 = cosz; mtxRotZ.m12 = sinz; mtxRotZ.m21 = -sinz; mtxRotZ.m22 = cosz; // XYZ回転行列の作成 Matrix4Multiply(MtxOut, &mtxRotX, &mtxRotY); Matrix4Multiply(MtxOut, MtxOut, &mtxRotZ); }
/** * クォータニオンから4x4回転行列を取得する * * |1-2(yy+zz), 2(xy+zw), 2(zx-wy), 0| * |2(xy-zw), 1-2(zz+xx), 2(yz+xw), 0| * |2(zx+wy), 2(yz-wx), 1-2(xx+yy), 0| * |0, 0, 0, 1| * * @param [out] _m 回転行列 * @param q クォータニオン */ void Matrix4RotationQuaternion(Matrix4& _m, const Quaternion& q) { Matrix4Identity(_m); _m(0,0) = 1.0f - 2.0f*(q.y*q.y + q.z*q.z); _m(0,1) = 2.0f*(q.x*q.y + q.z*q.w); _m(0,2) = 2.0f*(q.z*q.x - q.w*q.y); _m(1,0) = 2.0f*(q.x*q.y - q.z*q.w); _m(1,1) = 1.0f - 2.0f*(q.z*q.z + q.x*q.x); _m(1,2) = 2.0f*(q.y*q.z + q.x*q.w); _m(2,0) = 2.0f*(q.z*q.x + q.w*q.y); _m(2,1) = 2.0f*(q.y*q.z - q.w*q.x); _m(2,2) = 1.0f - 2.0f*(q.x*q.x + q.y*q.y); }
//============================================================================= // プロジェクション行列生成 //============================================================================= void MATRIX4::Matrix4PerspectiveFovLH(MATRIX4 *Matrix4, float fov, float aspect, float nearZ, float farZ) { Matrix4Identity(Matrix4); float t = 1.0f / tanf(fov * 0.5f); Matrix4->m11 = t / aspect; Matrix4->m22 = t; Matrix4->m33 = farZ / (farZ - nearZ); Matrix4->m43 = (-farZ * nearZ) / (farZ - nearZ); Matrix4->m44 = 0.0f; }
/** * MyApp::Update() * 毎フレームの処理 */ void MyApp::Update() { int i; bool _b = false; float _x = 0, _y = 0; if (HIWORD(GetAsyncKeyState(VK_UP))) { _y = 5.0f; _b = true; } if (HIWORD(GetAsyncKeyState(VK_DOWN))) { _y = -5.0f; _b = true; } if (HIWORD(GetAsyncKeyState(VK_LEFT))) { _x = -5.0f; _b = true; } if (HIWORD(GetAsyncKeyState(VK_RIGHT))) { _x = 5.0f; _b = true; } if (_b) Rotate(Vector2(_x, _y)); // 頂点計算 Vector4 pos(0.0f, 0.0f, 7.0f, 0.0f); // 立体位置 float n = 1; // 焦点距離 Matrix4 M, m; Matrix4Identity(M); // 回転 Quaternion q; QuaternionRotationAxis(q, -angle/180.0f*3.141592f, Vector3(rot, 0)); qRot *= q; Matrix4RotationQuaternion(m, qRot); M *= m; angle -= 0.1f; // ちょっとずつ回転を弱くする if (angle < 0.0f) angle = 0.0f; // 拡縮 Matrix4Scaling(m, scale, scale, scale); M *= m; // 平行移動 Matrix4Translation(m, pos.x, pos.y, pos.z); M *= m; // ビュー変換 Matrix4View(m, Vector3(0, 0, 0), Vector3(0, 0, n), Vector3(0, 1, 0)); M *= m; // 射影行列 Matrix4 Mproj; Matrix4Projection(Mproj, 120.0f/180.0f*3.141592f, (float)SCREEN_W/(float)SCREEN_H, 1, 500); // スクリーン座標変換行列 Matrix4 Mscreen; Matrix4Screen(Mscreen, SCREEN_W, SCREEN_H); for (i = 0; i < CUBE_SIZE; ++i) { // 各種変換 buf[i] = cube[i] * M; // 射影変換 buf[i] = Mproj * buf[i]; buf[i] /= buf[i].w; // スクリーン座標に変換 buf[i] = buf[i] * Mscreen; } // 背景描画 RECT rcBack = {0, 0, SCREEN_W, SCREEN_H}; FillRect(backDC, &rcBack, (HBRUSH)GetStockObject(BLACK_BRUSH)); // 愚直な色変化 static int r = 0xff, g = 0x00, b = 0x00; static int a = 1; switch (a) { case 0: b-=4; if (b <= 0x00) { ++a; b=0x00; } break; case 1: g+=4; if (g >= 0xff) { ++a; g=0xff; } break; case 2: r-=4; if (r <= 0x00) { ++a; r=0x00; } break; case 3: b+=4; if (b >= 0xff) { ++a; b=0xff; } break; case 4: g-=4; if (g <= 0x00) { ++a; g=0x00; } break; case 5: r+=4; if (r >= 0xff) { a=0; r=0xff; } break; } // 図形描画 HPEN hPenOld, hPen; hPen = CreatePen(PS_SOLID, 0, RGB(r, g, b)); hPenOld = (HPEN)SelectObject(backDC, hPen); for (i = 0; i < CUBE_SIZE>>1; ++i) { MoveToEx(backDC, buf[i].x, buf[i].y, NULL); LineTo(backDC, buf[(i+1)&3].x, buf[(i+1)&3].y); MoveToEx(backDC, buf[i+4].x, buf[i+4].y, NULL); LineTo(backDC, buf[4+((i+1)&3)].x, buf[4+((i+1)&3)].y); MoveToEx(backDC, buf[i].x, buf[i].y, NULL); LineTo(backDC, buf[i+4].x, buf[i+4].y); } MoveToEx(backDC, buf[0].x-5, buf[0].y-5, NULL); LineTo(backDC, buf[0].x+5, buf[0].y+5); MoveToEx(backDC, buf[0].x+5, buf[0].y-5, NULL); LineTo(backDC, buf[0].x-5, buf[0].y+5); SelectObject(backDC, hPenOld); DeleteObject(hPen); // 軸描画 Vector2 axis = rot * 50.0f; if (!axis.IsZero()) { axis.y = -axis.y; Vector2 allow1, allow2, u(SCREEN_W>>1, SCREEN_H>>1); Vector2Rotate(allow1, axis, (90.0f+45.0f)/180.0f*3.141592f); allow1.Normalize(); allow1 *= 10; Vector2Rotate(allow2, axis,-(90.0f+45.0f)/180.0f*3.141592f); allow2.Normalize(); allow2 *= 10; axis += u; allow1 += axis; allow2 += axis; hPen = CreatePen(PS_SOLID, 0, RGB(0xff, 0, 0)); hPenOld = (HPEN)SelectObject(backDC, hPen); MoveToEx(backDC, u.x, u.y, NULL); LineTo(backDC, axis.x, axis.y); MoveToEx(backDC, axis.x, axis.y, NULL); LineTo(backDC, allow1.x, allow1.y); MoveToEx(backDC, axis.x, axis.y, NULL); LineTo(backDC, allow2.x, allow2.y); SelectObject(backDC, hPenOld); DeleteObject(hPen); }