- mongodb - 在 MongoDB mapreduce 中,如何展平值对象?
- javascript - 对象传播与 Object.assign
- html - 输入类型 ="submit"Vs 按钮标签它们可以互换吗?
- sql - 使用 MongoDB 而不是 MS SQL Server 的优缺点
我正在实现用于空间可视化的3D引擎,并且正在编写具有以下导航功能的摄像头:
m_dRotationX
为0或pi时,眼睛根本不会向上或向下移动。 (万向节锁?如何避免这种情况?)m_dRotationX
在pi和2pi之间时,眼睛的旋转反转(改变旋转使其在应向下看时向上看,在应向上看时向下看)。 add another rotation onto your transform that rotates the eyePos to be completely in the y-z plane before you apply the transformation, and then another rotation that moves it back afterward. Rotate around the y axis by the following angle immediately before and after applying the yaw-pitch-roll matrix (one of the angles will need to be negated; trying it out is the fastest way to decide which).
double fixAngle = atan2(oEyeTranslated.z,oEyeTranslated.x);
// Adjust this to change rotation speed when dragging (units are radians per pixel mouse moves)
// This is both rotating the eye, and rotating around a point
static const double dRotatePixelScale = 0.001;
// Adjust this to change pan speed (units are meters per pixel mouse moves)
static const double dPanPixelScale = 0.15;
switch (m_eCurrentNavigation) {
case ENavigation::eRotatePoint: {
// Rotating around m_oRotateAroundPos
const double dX = (double)(m_oLastMousePos.x - roMousePos.x) * dRotatePixelScale * D3DX_PI;
const double dY = (double)(m_oLastMousePos.y - roMousePos.y) * dRotatePixelScale * D3DX_PI;
// To rotate around the point, translate so the point is at (0,0,0) (this makes the point
// the origin so the eye rotates around the origin), rotate, translate back
// However, the camera is represented as an eye plus two (X and Y) rotation angles
// This needs to keep the same relative rotation.
// Rotate the eye around the point
const D3DXVECTOR3 oEyeTranslated = m_oEyePos - m_oRotateAroundPos;
D3DXMATRIX oRotationMatrix;
D3DXMatrixRotationYawPitchRoll(&oRotationMatrix, dX, dY, 0.0);
D3DXVECTOR4 oEyeRotated;
D3DXVec3Transform(&oEyeRotated, &oEyeTranslated, &oRotationMatrix);
m_oEyePos = D3DXVECTOR3(oEyeRotated.x, oEyeRotated.y, oEyeRotated.z) + m_oRotateAroundPos;
// Increment rotation to keep the same relative look angles
RotateXAxis(dX);
RotateYAxis(dY);
break;
}
case ENavigation::ePanPlane: {
const double dX = (double)(m_oLastMousePos.x - roMousePos.x) * dPanPixelScale;
const double dY = (double)(m_oLastMousePos.y - roMousePos.y) * dPanPixelScale;
m_oEyePos += GetXAxis() * dX; // GetX/YAxis reads from the view matrix, so increments correctly
m_oEyePos += GetYAxis() * -dY; // Inverted compared to screen coords
break;
}
case ENavigation::eRotateEye: {
// Rotate in radians around local (camera not scene space) X and Y axes
const double dX = (double)(m_oLastMousePos.x - roMousePos.x) * dRotatePixelScale * D3DX_PI;
const double dY = (double)(m_oLastMousePos.y - roMousePos.y) * dRotatePixelScale * D3DX_PI;
RotateXAxis(dX);
RotateYAxis(dY);
break;
}
RotateXAxis
和
RotateYAxis
方法非常简单:
void Camera::RotateXAxis(const double dRadians) {
m_dRotationX += dRadians;
m_dRotationX = fmod(m_dRotationX, 2 * D3DX_PI); // Keep in valid circular range
}
void Camera::RotateYAxis(const double dRadians) {
m_dRotationY += dRadians;
// Limit it so you don't rotate around when looking up and down
m_dRotationY = std::min(m_dRotationY, D3DX_PI * 0.49); // Almost fully up
m_dRotationY = std::max(m_dRotationY, D3DX_PI * -0.49); // Almost fully down
}
void Camera::UpdateView() const {
const D3DXVECTOR3 oEyePos(GetEyePos());
const D3DXVECTOR3 oUpVector(0.0f, 1.0f, 0.0f); // Keep up "up", always.
// Generate a rotation matrix via a quaternion
D3DXQUATERNION oRotationQuat;
D3DXQuaternionRotationYawPitchRoll(&oRotationQuat, m_dRotationX, m_dRotationY, 0.0);
D3DXMATRIX oRotationMatrix;
D3DXMatrixRotationQuaternion(&oRotationMatrix, &oRotationQuat);
// Generate view matrix by looking at a point 1 unit ahead of the eye (transformed by the above
// rotation)
D3DXVECTOR3 oForward(0.0, 0.0, 1.0);
D3DXVECTOR4 oForward4;
D3DXVec3Transform(&oForward4, &oForward, &oRotationMatrix);
D3DXVECTOR3 oTarget = oEyePos + D3DXVECTOR3(oForward4.x, oForward4.y, oForward4.z); // eye pos + look vector = look target position
D3DXMatrixLookAtLH(&m_oViewMatrix, &oEyePos, &oTarget, &oUpVector);
}
最佳答案
在我看来,鉴于您形成 View 矩阵的方式,“滚动”应该是不可能的。不管其他所有代码(其中有些看上去确实有些有趣),当给定D3DXMatrixLookAtLH(&m_oViewMatrix, &oEyePos, &oTarget, &oUpVector);
作为“向上” vector 时,调用[0,1,0]
应该创建一个没有滚动的矩阵,除非oTarget-oEyePos
碰巧与向上 vector 平行。由于您将m_dRotationY
限制在(-.49pi,+。49pi)之内,因此似乎并非如此。
也许您可以弄清如何知道“滚动”正在发生。您是否有一个接地平面,并且该接地平面的水平线偏离水平面?
顺便说一句,在UpdateView
中,D3DXQuaternionRotationYawPitchRoll
似乎完全不必要,因为您可以立即转过来并将其更改为矩阵。只需像在鼠标事件中一样使用D3DXMatrixRotationYawPitchRoll
即可。在相机中使用四元数是因为它们是积累眼坐标中发生的旋转的便捷方法。由于您仅严格使用两个旋转轴,因此累积角度的方法应该很好。 (0,0,1)的 vector 变换也实际上不是必需的。 oRotationMatrix
条目中应该已经具有这些值。
更新
鉴于它不是滚动的,这是问题所在:创建一个旋转矩阵以在世界坐标系中移动眼睛,但您希望俯仰在相机坐标系中发生。由于不允许滚动并且最后执行偏航,因此在世界和相机参照系中偏航始终相同。请看下面的图片:
您的代码对局部俯仰和偏航非常有效,因为它们是在相机坐标中完成的。
但是,当您绕引用点旋转时,您将创建一个以世界坐标表示的旋转矩阵,并使用该矩阵旋转摄影机中心。如果相机的坐标系恰好与世界对齐,则可以正常工作。但是,如果在旋转相机位置之前不检查是否超出俯仰限制,则达到该限制时会出现疯狂的行为。相机将突然开始在世界范围内滑行-仍然围绕引用点“旋转”,但不再改变方向。
如果相机的轴与世界的轴不对齐,将会发生奇怪的事情。在极端情况下,相机根本不会移动,因为您正试图使其旋转。
以上是通常会发生的情况,但是由于您单独处理摄像头方向,因此摄像头实际上不会滚动。
相反,它保持直立状态,但是您正在进行奇怪的翻译。
一种解决方法是(1)始终将相机置于相对于引用点的规范位置和方向,(2)旋转,然后(3)完成后放回相机(例如,类似于将引用点转换为原点,应用偏航-俯仰旋转,然后向后平移的方式)。但是,考虑得更多,这可能不是最好的方法。
更新2
我认为通用人类的答案可能是最好的。问题仍然是如果旋转离轴应应用多少螺距,但是现在,我们将忽略它。也许它将给您可接受的结果。
答案的实质是:在移动鼠标之前,您的摄像头位于 c1 = (_31,_32,_33)
,并通过 M1定位M1 = m_oEyePos
。考虑引用点为 = D3DXMatrixRotationYawPitchRoll(&M_1,m_dRotationX,m_dRotationY,0)
。从摄像机的角度来看,这一点是 a'= M1(a-c1)。
您想将相机的方向更改为 M2 = m_oRotateAroundPos
。 [重要提示:由于您不允许D3DXMatrixRotationYawPitchRoll(&M_2,m_dRotationX+dX,m_dRotationY+dY,0)
落在特定范围之外,因此应确保dY不会违反该限制。]当摄像机改变方向时,您还希望其位置围绕和旋转到一个新点 c2 。这意味着从相机的角度来看,和不会改变。即 M1(a-c1)== M2(a-c2)。
因此,我们求解 c2 (请记住,旋转矩阵的转置与逆矩阵相同):
M2TM1(a-c1)==((a-c2) =>
-M2TM1(a-c1)+ a == c2
现在,如果我们将其视为应用于 c1 的转换,则可以看到它首先被否定,然后由翻译为,然后由 M1 旋转,然后由 M2T 旋转,再次被否定然后再由翻译为。这些是图形库擅长的转换,可以将它们全部压缩为一个转换矩阵。
@Generic Human的答案值得称赞,但是这里有相关代码。当然,您需要实现该功能以在应用音高变化之前对其进行验证,但这很简单。这段代码可能有一些错别字,因为我没有尝试编译:
case ENavigation::eRotatePoint: {
const double dX = (double)(m_oLastMousePos.x - roMousePos.x) * dRotatePixelScale * D3DX_PI;
double dY = (double)(m_oLastMousePos.y - roMousePos.y) * dRotatePixelScale * D3DX_PI;
dY = validatePitch(dY); // dY needs to be kept within bounds so that m_dRotationY is within bounds
D3DXMATRIX oRotationMatrix1; // The camera orientation before mouse-change
D3DXMatrixRotationYawPitchRoll(&oRotationMatrix1, m_dRotationX, m_dRotationY, 0.0);
D3DXMATRIX oRotationMatrix2; // The camera orientation after mouse-change
D3DXMatrixRotationYawPitchRoll(&oRotationMatrix2, m_dRotationX + dX, m_dRotationY + dY, 0.0);
D3DXMATRIX oRotationMatrix2Inv; // The inverse of the orientation
D3DXMatrixTranspose(&oRotationMatrix2Inv,&oRotationMatrix2); // Transpose is the same in this case
D3DXMATRIX oScaleMatrix; // Negative scaling matrix for negating the translation
D3DXMatrixScaling(&oScaleMatrix,-1,-1,-1);
D3DXMATRIX oTranslationMatrix; // Translation by the reference point
D3DXMatrixTranslation(&oTranslationMatrix,
m_oRotateAroundPos.x,m_oRotateAroundPos.y,m_oRotateAroundPos.z);
D3DXMATRIX oTransformMatrix; // The full transform for the eyePos.
// We assume the matrix multiply protects against variable aliasing
D3DXMatrixMultiply(&oTransformMatrix,&oScaleMatrix,&oTranslationMatrix);
D3DXMatrixMultiply(&oTransformMatrix,&oTransformMatrix,&oRotationMatrix1);
D3DXMatrixMultiply(&oTransformMatrix,&oTransformMatrix,&oRotationMatrix2Inv);
D3DXMatrixMultiply(&oTransformMatrix,&oTransformMatrix,&oScaleMatrix);
D3DXMatrixMultiply(&oTransformMatrix,&oTransformMatrix,&oTranslationMatrix);
D3DXVECTOR4 oEyeFinal;
D3DXVec3Transform(&oEyeFinal, &m_oEyePos, &oTransformMatrix);
m_oEyePos = D3DXVECTOR3(oEyeFinal.x, oEyeFinal.y, oEyeFinal.z)
// Increment rotation to keep the same relative look angles
RotateXAxis(dX);
RotateYAxis(dY);
break;
}
关于c++ - 实现复杂的基于旋转的相机,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11470978/
...沮丧。我希望我的游戏仅在横向模式下运行。我已将适当的键/值添加到 Info.plist 文件中,以强制设备方向在启动时正确。 我现在正在尝试旋转 OpenGL 坐标空间以匹配设备的坐标空间。我正
我如何创建一个旋转矩阵,将 X 旋转 a,Y 旋转 b,Z 旋转 c? 我需要公式,除非您使用的是 ardor3d api 的函数/方法。 矩阵是这样设置的 xx, xy, xz, yx, yy, y
假设我有一个包含 3 个 vector 的类(一个用于位置,一个用于缩放,一个用于旋转)我可以使用它们生成一个变换矩阵,该矩阵表示对象在 3D 空间中的位置、旋转和大小。然后我添加对象之间的父/子关系
所以我只是在玩一个小的 javascript 游戏,构建一个 pacman 游戏。你可以在这里看到它:http://codepen.io/acha5066/pen/rOyaPW 不过我对旋转有疑问。你
在我的应用程序中,我有一个 MKMapView,其中显示了多个注释。 map 根据设备的航向旋转。要旋转 map ,请执行以下语句(由方法 locationManager 调用:didUpdateHe
使用此 jquery 插件时:http://code.google.com/p/jqueryrotate/wiki/Documentation我将图像旋转 90 度,无论哪个方向,它们最终都会变得模糊
我有以下代码:CSS: .wrapper { margin:80px auto; width:300px; border:none; } .square { widt
本篇介绍Manim中的两个旋转类的动画,名称差不多,分别是Rotate和Rotating。 Rotate类主要用于对图形对象进行指定角度、围绕特定点的精确旋转,适用于几何图形演示、物理模拟和机械运动
我只想通过小部件的轴移动图像并围绕小部件的中心旋转(就像任何数字绘画软件中的 Canvas ),但它围绕其左顶点旋转...... QPainter p(this); QTransform trans;
我需要先旋转图像,然后再将其加载到 Canvas 中。据我所知,我无法使用 canvas.rotate() 旋转它,因为它会旋转整个场景。 有没有好的JS方法来旋转图片? [不依赖于浏览器的方式] 最
我需要知道我的 Android 设备屏幕何时从一个横向旋转到另一个横向(rotation_90 到 rotation_270)。在我的 Android 服务中,我重新实现了 onConfigurati
**摘要:**本篇文章主要讲解Python调用OpenCV实现图像位移操作、旋转和翻转效果,包括四部分知识:图像缩放、图像旋转、图像翻转、图像平移。 本文分享自华为云社区《[Python图像处理] 六
我只是在玩MTKView中的模板设置;并且,我一直在尝试了解以下内容: 相机的默认位置。 使用MDLMesh和MTKMesh创建基元时的默认位置。 为什么轮换还涉及翻译。 相关代码: matrix_f
我正在尝试使用包 dendexend 创建一个树状图。它创建了非常好的 gg 树状图,但不幸的是,当你把它变成一个“圆圈”时,标签跟不上。我将在下面提供一个示例。 我的距离对象在这里:http://s
我想将一个完整的 ggplot 对象旋转 90°。 我不想使用 coord_flip因为这似乎会干扰 scale="free"和 space="free"使用刻面时。 例如: qplot(as.fac
我目前可以通过首先平移到轴心点然后执行旋转最后平移回原点来围绕轴心点旋转。在我的例子中,我很容易为肩膀做到这一点。但是,我不知道如何为前臂添加绕肘部的旋转。 我已经尝试了以下围绕肘部旋转的前臂: 平移
我想使用此功能旋转然后停止在特定点或角度。现在该元素只是旋转而不停止。代码如下: $(function() { var $elie = $("#bkgimg");
关闭。这个问题需要多问focused 。目前不接受答案。 想要改进此问题吗?更新问题,使其仅关注一个问题 editing this post . 已关闭 4 年前。 Improve this ques
我正在尝试创建一个非常简单的关键帧动画,其中图形通过给定的中点从一个角度旋转到另一个角度。 (目的是能够通过大于 180 度的 OBTUSE 弧角来制作旋转动画,而不是让动画“作弊”并走最短路线,即通
我需要旋转 NSView 实例的框架,使其宽度变为其高度,其高度变为其宽度。该 View 包含一个字符串,并且该字符串也被旋转,这一点很重要。 我查看了 NSView 的 setFrameRotati
我是一名优秀的程序员,十分优秀!