Sign in to follow this  
polar01

Arcball problem

Recommended Posts

Hi,

I'm trying to add an "arc ball" but I have a strange behaviour.
I surely do something wrong, but what :-P So, if someone has an idea of the problem ?

How to reproduce it :
1 - With my arcball, I do an horizontal rotation of 180 degree (all is fine)
2 - I try to do a vertical rotation and the scene rotate in the INVERSE direction

Here is what I do :


void TrackballOperator::OnMouseMove(MouseEventArgs* e)
{
if (e->LeftButtonStatus == Down)
{
Drag(e->x, e->y);

// Update the camera
VNCamera* camera = _surface->GetScene()->GetActiveCamera();
Vector3 at = camera->GetEyeAt();

// eye
Vector3 eye = _startVector - at;
GlobalRotation.Rotate(&eye);
camera->SetEye(eye + at);

// eye up
Vector3 eyeUp = _startVectorUp;
GlobalRotation.Rotate(&eyeUp);
camera->SetEyeUp(eyeUp);
}
}

void TrackballOperator::OnMouseButtonDown(MouseButtonEventArgs* e)
{
if (e->Button == Left)
{
SetBounds(_surface->GetWidth(), _surface->GetHeight());

//---- Reset some datas...
VNCamera* camera = _surface->GetScene()->GetActiveCamera();
_startVector = camera->GetEye();
_startVectorUp = camera->GetEyeUp();

startMouse.x = e->x;
startMouse.y = e->y;

GlobalRotation.AsIdentity();
}
}
void TrackballOperator::MapToSphere(const Vector2* NewPt, Vector3* NewVec) const
{
Vector2 TempPt;
float length;

// Copy paramter into temp point
TempPt = *NewPt;

// Adjust point coords and scale down to range of [-1 ... 1]
TempPt.x = (TempPt.x * this->AdjustWidth) - 1.0f;
TempPt.y = 1.0f - (TempPt.y * this->AdjustHeight);

// Compute the square of the length of the vector to the point from the center
length = (TempPt.x * TempPt.x) + (TempPt.y * TempPt.y);

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

// Compute a normalizing factor (radius / sqrt(length))
norm = 1.0f / sqrtf(length);

// Return the "normalized" vector, a point on the sphere
NewVec->x = TempPt.x * norm;
NewVec->y = TempPt.y * norm;
NewVec->z = 0.0f;
}
else //Else it's on the inside
{
//Return a vector to a point mapped inside the sphere sqrt(radius squared - length)
NewVec->x = TempPt.x;
NewVec->y = TempPt.y;
NewVec->z = sqrtf(1.0f - length);
}
}


void TrackballOperator::Drag(float newX, float newY)
{
endMouse.x = newX;
endMouse.y = newY;

// Map the point to the sphere
Vector3 startPoint;
Vector3 endPoint;
MapToSphere(&startMouse, &startPoint);
MapToSphere(&endMouse, &endPoint);

// Return the quaternion equivalent to the rotation
// Compute the vector perpendicular to the begin and end vectors
Vector3 Perp = Cross(endPoint, startPoint);

startMouse = endMouse;

// Compute the length of the perpendicular vector
Quaternion NewRot;
if (Perp.Length() < EPSILON)
return;

// We're ok, so return the perpendicular vector as the transform after all
NewRot.x = Perp.x;
NewRot.y = Perp.y;
NewRot.z = Perp.z;

// In the quaternion values, w is cosine (theta / 2), where theta is rotation angle
NewRot.w = Dot(startPoint, endPoint);

GlobalRotation = GlobalRotation * NewRot;
}



About the quaternion class :


// Conjugate it
void Conjugate()
{
x = -x;
y = -y;
z = -z;
}

// Calculates the effect of this rotation on a point
// the new point is given by = q * P1 * q'
void Rotate(Vector3* point)
{
//---- Compute the conjugate
Quaternion conj = *this;
conj.Conjugate();

//---- q * P * q'
Quaternion qNode(point->x, point->y, point->z, 0.f);
qNode = *this * qNode * conj;

//---- Set the result
point->x = qNode.x;
point->y = qNode.y;
point->z = qNode.z;
}

Share this post


Link to post
Share on other sites
I think I have found the problem.

I need to set-up my initial quaternion with the camera axis.

So, do you know how to convert 3 Axis (AxisX, AxisY, AxisZ) into a quaternion ?

Thanks for your help

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this