PDA

View Full Version : World coordinates changes on camera rotation



glararan
08-14-2013, 06:26 AM
Hi,

In my first topic I asked for help with gluUnproject.

My current code is almost finished, but it still have one bug, that's camera rotation.

I tried it explain in following picture:
1108

By my words: On 0 degrees is corrupted world coordinate Z, on -90 degrees is Z fine but X coordinate became corrupted

Source code:


QMatrix4x4 viewMatrix = m_camera->viewMatrix();
QMatrix4x4 modelViewMatrix = viewMatrix * m_modelMatrix;
QMatrix4x4 modelViewProject = m_camera->projectionMatrix() * modelViewMatrix;
QMatrix4x4 inverted = m_viewportMatrix * modelViewProject;

inverted = inverted.inverted();

float posZ;
int posY = (int)m_viewportSize.y() - (int)mouse_position.y() - 1;

m_funcs->glReadPixels((int)mouse_position.x(), posY, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &posZ);

QVector4D clickedPointOnScreen(mouse_position.x(), (float)posY, posZ, 1.0f);
QVector4D clickedPointIn3DOrgn = inverted * clickedPointOnScreen;

clickedPointIn3DOrgn = clickedPointIn3DOrgn / clickedPointIn3DOrgn.w();

terrain_pos = clickedPointIn3DOrgn.toVector3DAffine();

glararan
08-20-2013, 07:00 AM
BUMP, any idea?

thokra
08-20-2013, 07:17 AM
You don't change any camera parameter in that code segment - all you do is query some matrices. The bug is probably somewhere else.

glararan
08-21-2013, 04:27 AM
Yes, I don't change, but it's based on camera matrices, so it must somehow.

I will post here my mouse camera code, if it helps (i'm not really genius in matrices :/ )

mouseMoveEvent(QMouseEvent* e) - parent QGLWidget

m_pos = e->pos();

float dx = 0.4f * (m_pos.x() - m_prevPos.x());
float dy = -0.4f * (m_pos.y() - m_prevPos.y());

m_prevPos = m_pos;

pan(dx);
tilt(dy);

pan + tilt functions : header QGLWidget

// Camera orientation control
void pan(float angle) { m_panAngle = angle; }
void tilt(float angle) { m_tiltAngle = angle; }

update : parent QGLWidget called every 16ms with paint

if(!qFuzzyIsNull(m_panAngle))
{
m_camera->pan(m_panAngle, QVector3D(0.0f, 1.0f, 0.0f));
panAngle += m_panAngle;
m_panAngle = 0.0f;
}

if(panAngle > 360.0f || panAngle < -360.0f)
panAngle = 0.0f;

if(!qFuzzyIsNull(m_tiltAngle))
{
if(tiltAngle + m_tiltAngle > 90.0f || tiltAngle + m_tiltAngle < -90.0f)
{
float copyTAngle = m_tiltAngle;

if(tiltAngle + copyTAngle > 90.0f)
{
while(tiltAngle + copyTAngle - 0.1f > 90.0f)
copyTAngle -= 0.1f;
}
else if(tiltAngle + copyTAngle < -90.0f)
{
while(tiltAngle + copyTAngle + 0.1f < -90.0f)
copyTAngle += 0.1f;
}

m_tiltAngle = copyTAngle;
copyTAngle = 0.0f;
}

m_camera->tilt(m_tiltAngle);
tiltAngle += m_tiltAngle;
m_tiltAngle = 0.0f;
}

camera

void Camera::tilt(const float& angle)
{
QQuaternion q = tiltRotation(angle);
rotate(q);
}

void Camera::pan(const float& angle)
{
QQuaternion q = panRotation(-angle);
rotate(q);
}

void Camera::pan(const float& angle, const QVector3D& axis)
{
QQuaternion q = panRotation(-angle, axis);
rotate(q);
}

QQuaternion Camera::tiltRotation(const float& angle) const
{
Q_D(const Camera);
QVector3D xBasis = QVector3D::crossProduct(d->m_upVector, d->m_cameraToCenter.normalized()).normalized();

return QQuaternion::fromAxisAndAngle(xBasis, -angle);
}

QQuaternion Camera::panRotation(const float& angle) const
{
Q_D(const Camera);
return QQuaternion::fromAxisAndAngle(d->m_upVector, angle);
}

QQuaternion Camera::panRotation(const float& angle, const QVector3D& axis) const
{
return QQuaternion::fromAxisAndAngle(axis, angle);
}

void Camera::rotate(const QQuaternion& q)
{
Q_D(Camera);
d->m_upVector = q.rotatedVector(d->m_upVector);
d->m_cameraToCenter = q.rotatedVector(d->m_cameraToCenter);
d->m_viewCenter = d->m_position + d->m_cameraToCenter;
}

glararan
08-21-2013, 10:50 AM
FIXED thanks to http://www.opengl.org/discussion_boards/showthread.php/171432-gluUnProject-How-to-use-it-in-a-proper-way?p=1204252&viewfull=1#post1204252

I didn't use whole code but just screenPos Z.

So in my case

QVector4D clickedPointOnScreen(mouse_position.x(), (float)posY, posZ, 1.0f);

TO

QVector4D clickedPointOnScreen(mouse_position.x(), (float)posY, 2.0f * posZ - 1.0f, 1.0f);