Arcball Problems with UDK

Posted by opdude on Game Development See other posts from Game Development or by opdude
Published on 2012-03-22T09:28:17Z Indexed on 2012/03/22 17:44 UTC
Read the original article Hit count: 286

Filed under:

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));

© Game Development or respective owner

Related posts about rotation