Question

I've ported the arcball classes I've been using from vb.net to the iPhone using objective C++, but now I'm having a problem. When I rotate my object, everything is fine. As soon as I pan the view, my center of rotation is no longer at the center of my objects origin like it used to be. Ideally, I'd like to be able to set where in the objects frame of reference the rotation point is. I'm not sure where in the arcball routines I'd need to make changes to do this. The implementation I've based mine off of is found at the below link:

http://www.codeproject.com/KB/openGL/Tao_Arcball.aspx

I've made some small modification to how it behaves and converted it to a touch interface, but how it acts is still the same as this implementation as far as the problem I'm having is concerned.

These links explain some more of the math behind quaternions and matrix rotations:

http://www.j3d.org/matrix_faq/matrfaq_latest.html http://www.gamedev.net/reference/articles/article1095.asp http://en.wikipedia.org/wiki/Quaternion_rotation

The main part of the code that I imagine would have to be modified is below (in 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

Edit:

I've almost figured out how to do this. I've gotten to the point that I can set the center of rotation for my Arcball, but now I've run into another problem. When I apply the transformations to do rotation about a specified center point, there are two problems:

  1. The model jumps to a different location. I'd like to keep the model at the exact same location and orientation.

  2. The model scales about the new center point, but I'd like to have the model scale about the point that is the average of where the user touches with two fingers.

For number 2, I think I know how to do it, but I'll need to figure out number 1 in order to make number 2 work properly. For number 2, I can just project the average touch point to a plane that is parallel to the near plane but goes through the origin of the part, then make that my center of rotation until the user lifts their fingers up. Any ideas on number 1? The code that I use for changing the center of rotation is below:

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

Just for your information, OpenGL applies matrix transformations in reverse order because of how its stacks work. So in my code, the bottom line will be executed first, then on up from there. Effectively it moves the model so its center of rotation is at the origin, then it rotates/scales, then it translates the model where it needs to go for panning.

The problem I believe I'm running into is that I need to add centerOfRotation back when I do my panning, but the problem is that once the model rotates, the centerOfRotation point needs to be transformed somehow to be in a different model space. Before I rotate the model it works fine, but once rotations are introduced, everything blows up.

Was it helpful?

Solution 2

OK, I finally figured out what was going on. The worst part is that I was doing it correctly the whole time. The only problem I was having was my triangle ray intersection algorithm was returning the wrong point. I fixed that issue and now the controls perform as expected, the center of rotation never moves on the screen, the model just moves so the origin stays in the same location. The code to do the transformation was what I mentioned in the original post:

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

OTHER TIPS

Rather than porting across a VB.NET arcball, maybe you could look at an existing iPhone trackball implementation. For example, Bill Dudney wrote a sample application a while ago that uses a trackball to rotate two images within a Core Animation context, something that can easily be modified to work within OpenGL ES (Core Animation and OpenGL ES use identical matrix structures for transforms).

I implemented an alternative way of rotating a model by using touch movement in X and Y to rotate about the Y and X axes of the screen, as seen by the user. This can be found within the source code to my Molecules application, as well as within a sample application I wrote that displays a 3-D cube. I explain a little bit about how this works here.

Both of these approaches still manage to rotate the model about its origin, even if it is displaced in a particular direction.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top