Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

I'm trying to re-create an arcball example from a Nehe, where an object can be rotated in a more realistic way while floating in the air (in my game the object is attached to the player at a distance like for example the Physics Gun) however I'm having trouble getting this to work with UDK.

I have created an LGArcBall which follows the example from Nehe and I've compared outputs from this with the example code.

I think where my problem lies is what I do to the Quaternion that is returned from the LGArcBall.

Currently I am taking the returned Quaternion converting it to a rotation matrix. Getting the product of the last rotation (set when the object is first clicked) and then returning that into a Rotator and setting that to the objects rotation.

If you could point me in the right direction that would be great, my code can be found below.

class LGArcBall extends Object;

var Quat StartRotation;
var Vector StartVector;
var float AdjustWidth, AdjustHeight, Epsilon;

function SetBounds(float NewWidth, float NewHeight) 
{
    AdjustWidth = 1.0f / ((NewWidth  - 1.0f) * 0.5f);
    AdjustHeight = 1.0f / ((NewHeight - 1.0f) * 0.5f);
}

function StartDrag(Vector2D startPoint, Quat rotation) 
{
    StartVector = MapToSphere(startPoint);
}

function Quat Update(Vector2D currentPoint) 
{
    local Vector currentVector, perp;
    local Quat newRot;

    //Map the new point to the sphere
    currentVector = MapToSphere(currentPoint);

    //Compute the vector perpendicular to the start and current
    perp = startVector cross currentVector;

    //Make sure our length is larger than Epsilon
    if (VSize(perp) > Epsilon) 
    {
        //Return the perpendicular vector as the transform
        newRot.X = perp.X;
        newRot.Y = perp.Y;
        newRot.Z = perp.Z;

        //In the quaternion values, w is cosine (theta / 2), where
        //theta is the rotation angle
        newRot.W = startVector dot currentVector;
    }
    else 
    {
        //The two vectors coincide, so return an identity transform
        newRot.X = 0.0f;
        newRot.Y = 0.0f;
        newRot.Z = 0.0f;
        newRot.W = 0.0f;
    }

    return newRot;
}

function Vector MapToSphere(Vector2D point) 
{
    local float x, y, length, norm;
    local Vector result;

    //Transform the mouse coords to [-1..1]
    //and inverse the Y coord
    x = (point.X * AdjustWidth) - 1.0f;
    y = 1.0f - (point.Y * AdjustHeight);

    length = (x * x) + (y * y);

    //If the point is mapped outside of the sphere 
    //( length > radius squared)
    if (length > 1.0f) 
    {
        norm = 1.0f / Sqrt(length);

        //Return the "normalized" vector, a point on the sphere
        result.X = x * norm;
        result.Y = y * norm;
        result.Z = 0.0f;
    }
    else //It's inside of the sphere
    {
        //Return a vector to the point mapped inside the sphere
        //sqrt(radius squared - length)
        result.X = x;
        result.Y = y;
        result.Z = Sqrt(1.0f - length);
    }

    return result;
}

DefaultProperties
{
    Epsilon = 0.000001f
}

I'm then attempting to rotate that object when the mouse is dragged, with the following update code in my PlayerController.

    //Get Mouse Position
    MousePosition.X = LGMouseInterfacePlayerInput(PlayerInput).MousePosition.X;
    MousePosition.Y = LGMouseInterfacePlayerInput(PlayerInput).MousePosition.Y;

    newQuat = ArcBall.Update(MousePosition);

    rotMatrix = MakeRotationMatrix(QuatToRotator(newQuat));
    rotMatrix = rotMatrix * LastRot;

    LGMoveableActor(movingPawn.CurrentUseableObject).SetPhysics(EPhysics.PHYS_Rotating);
    LGMoveableActor(movingPawn.CurrentUseableObject).SetRotation(MatrixGetRotator(rotMatrix));
share|improve this question
    
Could you describe how your code is behaving versus how you expect it to behave? –  SpartanDonut Mar 22 '12 at 11:21
    
The rotation given from the code is difficult to explain, however I'll give it a go. When moving the mouse to the left or right it will pitch up and down, then from there if you move the mouse up and down it will roll, eventually with more up and down movement it will begin to yaw around. So the affect is far from natural for ArcBall. –  opdude Mar 23 '12 at 14:28

1 Answer 1

If I understand your problem correctly then it's the most typical problem while implementing any arcballs :)

Problem: Currently if you're moving left-right you will rotate your object around some axis. BUT when you move slightly up or down, then your local axes will change. Now, when you move left-right again you will get the different rotation than before and that produces an unwanted roll rotation.

Solution: It's really simple - instead of rotating slightly your object with every mouse move just remember your mouse X,Y and object rotation at some 'MouseDown' event. Then for every mouse movement compute X,Y difference and use it to modify your initial orientation. All math equations are the same, but always use the orientation from beginning of mouse dragging, instead of last frame.

I'm not sure if I explained it simply enough, if you still have any doubts just ask.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.