我已经使用目标C ++将我从vb.net使用的arcball类移植到了iPhone,但现在我遇到了问题。旋转物体时,一切都很好。一旦平移视图,我的旋转中心就不再像过去那样位于我的对象原点的中心。理想情况下,我希望能够在对象框架中设置旋转点的位置。我不确定在轨迹球程序中我需要做哪些改变才能做到这一点。我所依据的实现可以在以下链接中找到:
http://www.codeproject.com/KB/openGL/Tao_Arcball.aspx
我对它的行为进行了一些小的修改并将其转换为触摸界面,但就我所关注的问题而言,它的行为方式仍与此实现相同。
这些链接解释了四元数和矩阵旋转背后的一些数学原理:
http://www.j3d.org/matrix_faq/matrfaq_latest.html http://www.gamedev.net/reference/articles/article1095.asp http://en.wikipedia.org/wiki/Quaternion_rotation
我想要修改的代码的主要部分如下(在vb.net中):
Public WriteOnly Property Rotation() As Quat4f
Set(ByVal value As Quat4f)
Dim n, s As Single
Dim xs, ys, zs As Single
Dim wx, wy, wz As Single
Dim xx, xy, xz As Single
Dim yy, yz, zz As Single
M = New Single(3, 3) {}
n = (value.x * value.x) + (value.y * value.y) + (value.z * value.z) + (value.w * value.w)
s = If((n > 0.0f), 2.0f / n, 0.0f)
xs = value.x * s
ys = value.y * s
zs = value.z * s
wx = value.w * xs
wy = value.w * ys
wz = value.w * zs
xx = value.x * xs
xy = value.x * ys
xz = value.x * zs
yy = value.y * ys
yz = value.y * zs
zz = value.z * zs
' rotation
M(0, 0) = 1.0f - (yy + zz)
M(0, 1) = xy - wz
M(0, 2) = xz + wy
M(1, 0) = xy + wz
M(1, 1) = 1.0f - (xx + zz)
M(1, 2) = yz - wx
M(2, 0) = xz - wy
M(2, 1) = yz + wx
M(2, 2) = 1.0f - (xx + yy)
M(3, 3) = 1.0f
' translation (pan)
M(0, 3) = pan_Renamed.x
M(1, 3) = pan_Renamed.y
' scale (zoom)
For i As Integer = 0 To 2
For j As Integer = 0 To 2
M(i, j) *= scl
Next j
Next i
End Set
End Property
我几乎想出了如何做到这一点。我已经达到了可以为我的Arcball设置旋转中心的程度,但现在我遇到了另一个问题。当我应用转换来围绕指定的中心点进行旋转时,存在两个问题:
模型跳转到其他位置。我想将模型保持在完全相同的位置和方向。
模型围绕新的中心点进行缩放,但我想让模型缩放关于用户用两根手指触摸的平均点。
对于2号,我想我知道该怎么做,但我需要找出1号才能使2号正常工作。对于数字2,我可以将平均触摸点投影到与近平面平行但穿过零件原点的平面,然后将其作为我的旋转中心直到用户抬起手指。关于1号的任何想法?我用来改变旋转中心的代码如下:
glTranslatef(panVector.x, panVector.y, 0); //panVector is a variable that keeps track of the user panning the model
glMultMatrixf(arcballMatrix); //arcball matrix is the 16 element rotation/scale matrix that controls the model orientation
glTranslatef(-centerOfRotation.x, -centerOfRotation.y, -centerOfRotation.z); //centerOfRotation is a point that is set where I want the center of rotation to be
仅仅为了您的信息,OpenGL以相反的顺序应用矩阵变换,因为它的堆栈如何工作。所以在我的代码中,底线将首先执行,然后从那里开始执行。它有效地移动模型,使其旋转中心位于原点,然后旋转/缩放,然后将模型转换为需要进行平移的模型。
我认为我遇到的问题是我需要在进行平移时添加centerOfRotation,但问题是一旦模型旋转,centerOfRotation点需要以某种方式转换为不同的模型空间。在我旋转模型之前,它工作正常,但一旦引入旋转,一切都会爆炸。
答案 0 :(得分:0)
您可以查看现有的iPhone轨迹球实现,而不是移植到VB.NET弧形球。例如,Bill Dudney不久前写了sample application使用轨迹球在Core Animation上下文中旋转两个图像,可以很容易地修改它以在OpenGL ES中工作(Core Animation和OpenGL ES使用相同的矩阵结构)变换)。
我实现了另一种旋转模型的方法,通过使用X和Y中的触摸移动来围绕屏幕的Y轴和X轴旋转,如用户所见。这可以在我的Molecules应用程序的源代码中找到,也可以在我写的显示三维立方体的sample application内找到。我解释一下这是如何工作的here。
这两种方法仍设法围绕其原点旋转模型,即使它在特定方向上移位。
答案 1 :(得分:0)
好的,我终于弄清楚发生了什么。最糟糕的是,我一直都在正确地做这件事。我遇到的唯一问题是我的三角形射线交叉算法返回了错误的点。我修复了这个问题,现在控件按预期运行,旋转中心从不在屏幕上移动,模型只是移动,因此原点保持在同一位置。进行转换的代码就是我在原帖中提到的:
glTranslatef(panVector.x, panVector.y, 0); //panVector is a variable that keeps track of the user panning the model
glMultMatrixf(arcballMatrix); //arcball matrix is the 16 element rotation/scale matrix that controls the model orientation
glTranslatef(-centerOfRotation.x, -centerOfRotation.y, -centerOfRotation.z); //centerOfRotation is a point that is set where I want the center of rotation to be