void Build_CAM4DV1_Matrix_UVN(CAM4DV1_PTR cam, int mode) { MATRIX4X4 mt_inv; MATRIX4X4 mt_uvn; MATRIX4X4 mtmp; //Ïà»úƽÒƾØÕóµÄÄæ¾ØÕó Mat_Init_4X4(&mt_inv, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, -cam->pos.x, -cam->pos.y, -cam->pos.z, 1); if (UVN_MODE_SPHERICAL == mode) { float phi = cam->dir.x; float theta = cam->dir.y; float sin_phi = Fast_Sin(phi); float cos_phi = Fast_Cos(theta); float sin_theta = Fast_Sin(theta); float cos_theta = Fast_Cos(theta); cam->target.x = -1 * sin_phi * sin_theta; cam->target.y = 1 * cos_phi; cam->target.z = 1 * sin_phi * cos_theta; } VECTOR4D_Build(&cam->pos, &cam->target, &cam->n); VECTOR4D_INITXYZ(&cam->v, 0, 1, 0); VECTOR4D_Cross(&cam->v, &cam->n, &cam->u); VECTOR4D_Cross(&cam->n, &cam->u, &cam->v); VECTOR4D_Normalize(&cam->u); VECTOR4D_Normalize(&cam->v); VECTOR4D_Normalize(&cam->n); Mat_Init_4X4(&mt_uvn, cam->u.x, cam->v.x, cam->n.x, 0, cam->u.y, cam->v.y, cam->n.y, 0, cam->u.z, cam->v.z, cam->n.z, 0, 0, 0, 0, 1); Mat_Mul_4X4(&mt_inv, &mt_uvn, &cam->mcam); }
// 使用3D图形算法来获取图片旋转后的四个顶点位置 void C3DTransform::GetQuadByAnimateValue(int nDegreeX, int nDegreeY, int nDegreeZ, int nZOffset, Quad* pOutQuad) { // .局部坐标(以矩形的中心作为局部坐标的原点) float x = (float)m_nSrcWndWidth/2; float y = (float)m_nSrcWndHeight/2; POINT3D pt3dModel[4] = { {-x, y, 0}, {x, y, 0}, {x, -y, 0}, {-x, -y, 0} }; POINT3D pt3DWorld[4] = {0}; POINT3D pt3DCamera[4] = {0}; #pragma region // .局部坐标->世界坐标 { // .以当前值作为角度进行旋转 float fDegreeX = (float)nDegreeX; float fDegreeY = (float)nDegreeY; float fDegreeZ = (float)nDegreeZ; MATRIX_4_4 matTemp1, matTemp2; MATRIX_4_4 matRotateY, matRotateX, matRotateZ; MATRIX_4_4_PTR pLeftArg = NULL; if (0 != fDegreeY) { MAT_IDENTITY_4_4(&matRotateY); matRotateY.M00 = Fast_Cos(fDegreeY); matRotateY.M02 = -Fast_Sin(fDegreeY); matRotateY.M20 = Fast_Sin(fDegreeY); matRotateY.M22 = Fast_Cos(fDegreeY); pLeftArg = &matRotateY; } if (0 != fDegreeX) { MAT_IDENTITY_4_4(&matRotateX); matRotateX.M11 = Fast_Cos(fDegreeX); matRotateX.M12 = Fast_Sin(fDegreeX); matRotateX.M21 = -Fast_Sin(fDegreeX); matRotateX.M22 = Fast_Cos(fDegreeX); if (NULL == pLeftArg) { pLeftArg = &matRotateX; } else { Mat_Mul_4X4(pLeftArg, &matRotateX, &matTemp1); pLeftArg = &matTemp1; } } if (0 != fDegreeZ) { MAT_IDENTITY_4_4(&matRotateZ); matRotateZ.M00 = Fast_Cos(fDegreeZ); matRotateZ.M01 = Fast_Sin(fDegreeZ); matRotateZ.M10 = -Fast_Sin(fDegreeZ); matRotateZ.M11 = Fast_Cos(fDegreeZ); if (NULL == pLeftArg) { pLeftArg = &matRotateZ; } else { Mat_Mul_4X4(pLeftArg, &matRotateZ, &matTemp2); pLeftArg = &matTemp2; } } if (pLeftArg) { for (int i = 0; i < 4; i++) Mat_Mul_VECTOR3D_4X4(&pt3dModel[i], pLeftArg, &pt3DWorld[i]); } else { for (int i = 0; i < 4; i++) { pt3DWorld[i].x = pt3dModel[i].x; pt3DWorld[i].y = pt3dModel[i].y; } } // .由于仍然是平移到世界坐标的 (0,0,0)位置,因此不用计算平移 for (int i = 0; i < 4; i++) { pt3DWorld[i].z += nZOffset; } } #pragma endregion // 相机位置(这里默认将视平面放在与矩形所在面的同一位置,这样透视出来的坐标直接就可以 // 当成屏幕坐标来用了,省了一步操作。 // 但是需要注意的是,如果nCameraPos过小的话看到的图像就会缩小, CAMERA camerpos = {0}; float fCameraPos = 2000.0f; // 相机位置 float d = fCameraPos; // 相机与视平面的距离。将两值设成一样,避免了一次到屏幕坐标的转换 VECTOR4D_INITXYZ(&camerpos.WorldPos, 0,0, -fCameraPos); #pragma region // 世界坐标转换为相机坐标 { // 平移矩阵 MATRIX_4_4 matCameraTrans = {0}; MAT_IDENTITY_4_4(&matCameraTrans); matCameraTrans.M30 = -camerpos.WorldPos.x; matCameraTrans.M31 = -camerpos.WorldPos.y; matCameraTrans.M32 = -camerpos.WorldPos.z; // 相机角度为0,不旋转 for (int i = 0; i < 4; i++) { Mat_Mul_VECTOR3D_4X4(&pt3DWorld[i], &matCameraTrans, &pt3DCamera[i]); } } #pragma endregion #pragma region // 相机坐标转换为透视坐标 POINT3D pt3DPerspectivePos[4]; for (int i = 0; i < 4; i++) { float z = pt3DCamera[i].z; // 这里的z是用于和d相比的距离,不是坐标. 当d值取的比较小时,会导致z为负 float i_z = 1/z; if (pt3DCamera[i].z != 0) { pt3DPerspectivePos[i].x = d * pt3DCamera[i].x * i_z; // nCameraPos相当于d pt3DPerspectivePos[i].y = d * pt3DCamera[i].y * i_z; // } } #pragma endregion // 转换到屏幕坐标上 for (int i = 0; i < 4; ++i) { pt3DPerspectivePos[i].x += (m_nSrcWndWidth>>1); pt3DPerspectivePos[i].y = -pt3DPerspectivePos[i].y; pt3DPerspectivePos[i].y += (m_nSrcWndHeight>>1); } // 赋值给返回值 for (int i = 0; i < 4; i++) { pOutQuad->pos[2*i] = (int)pt3DPerspectivePos[i].x; pOutQuad->pos[2*i+1] = (int)pt3DPerspectivePos[i].y; } }
void Build_CAM4DV1_Matrix_Euler(CAM4DV1_PTR cam, int cam_rot_seq) { MATRIX4X4 mt_inv; MATRIX4X4 mx_inv; MATRIX4X4 my_inv; MATRIX4X4 mz_inv; MATRIX4X4 mrot; MATRIX4X4 mtmp; //Ïà»úƽÒƾØÕóµÄÄæ¾ØÕó Mat_Init_4X4(&mt_inv, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, -cam->pos.x, -cam->pos.y, -cam->pos.z, 1); //Ðýת¾ØÕó //ÌáÈ¡Å·À½Ç float theta_x = cam->dir.x; float theta_y = cam->dir.y; float theta_z = cam->dir.z; float cos_theta = Fast_Cos(theta_x); //cos(-x) = cos(x) float sin_theta = -Fast_Sin(theta_x); //sin(-x) = -sin(x) Mat_Init_4X4(&mx_inv, 1, 0, 0, 0, 0, cos_theta, sin_theta, 0, 0, -sin_theta, cos_theta, 0, 0, 0, 0, 1); cos_theta = Fast_Cos(theta_y); //cos(-x) = cos(x) sin_theta = -Fast_Sin(theta_y); //sin(-x) = -sin(x) Mat_Init_4X4(&my_inv, cos_theta, 0, -sin_theta, 0, 0, 1, 0, 0, sin_theta, 0, cos_theta, 0, 0, 0, 0, 1); cos_theta = Fast_Cos(theta_z); //cos(-x) = cos(x) sin_theta = -Fast_Sin(theta_z); //sin(-x) = -sin(x) Mat_Init_4X4(&mz_inv, cos_theta, sin_theta, 0, 0, -sin_theta, cos_theta, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); switch (cam_rot_seq) { case CAM_ROT_SEQ_XYZ: Mat_Mul_4X4(&mx_inv, &my_inv, &mtmp); Mat_Mul_4X4(&mtmp, &mz_inv, &mrot); break; case CAM_ROT_SEQ_YXZ: Mat_Mul_4X4(&my_inv, &mx_inv, &mtmp); Mat_Mul_4X4(&mtmp, &mz_inv, &mrot); break; case CAM_ROT_SEQ_XZY: Mat_Mul_4X4(&mx_inv, &mz_inv, &mtmp); Mat_Mul_4X4(&mtmp, &my_inv, &mrot); break; case CAM_ROT_SEQ_YZX: Mat_Mul_4X4(&my_inv, &mz_inv, &mtmp); Mat_Mul_4X4(&mtmp, &mx_inv, &mrot); break; case CAM_ROT_SEQ_ZYX: Mat_Mul_4X4(&mz_inv, &my_inv, &mtmp); Mat_Mul_4X4(&mtmp, &mx_inv, &mrot); break; case CAM_ROT_SEQ_ZXY: Mat_Mul_4X4(&mz_inv, &mx_inv, &mtmp); Mat_Mul_4X4(&mtmp, &my_inv, &mrot); break; default: break; } Mat_Mul_4X4(&mt_inv, &mrot, &cam->mcam); }