gpt4 book ai didi

c++ - 用于旋转网格的 OpenGL ArcBall

转载 作者:太空宇宙 更新时间:2023-11-04 12:40:23 26 4
gpt4 key购买 nike

我正在使用旧版 OpenGL 绘制网格。我现在正在尝试实现一个 arcball 类来用鼠标旋转对象。但是,当我移动鼠标时,对象要么不旋转,要么旋转角度太大。

这是单击鼠标时调用的方法:

void ArcBall::startRotation(int xPos, int yPos) {
int x = xPos - context->getWidth() / 2;
int y = context->getHeight() / 2 - yPos;
startVector = ArcBall::mapCoordinates(x, y).normalized();
endVector = startVector;
rotating = true;
}

这个方法的目的是简单地将鼠标坐标映射到屏幕中心,并将它们映射到边界球体,从而得到一个起始 vector

这是鼠标移动时调用的方法:

void ArcBall::updateRotation(int xPos, int yPos) {
int x = xPos - context->getWidth() / 2;
int y = context->getHeight() / 2 - yPos;
endVector = mapCoordinates(x, y).normalized();
rotationAxis = QVector3D::crossProduct(endVector, startVector).normalized();
angle = (float)qRadiansToDegrees(acos(QVector3D::dotProduct(startVector, endVector)));
rotation.rotate(angle, rotationAxis.x(), rotationAxis.y(), rotationAxis.z());
startVector = endVector;
}

这个方法也是将鼠标坐标映射到屏幕中间,然后计算新的 vector ,并根据这两个 vector 计算旋转轴和角度。

然后我使用

glMultMatrixf(ArcBall::rotation.data());

应用旋转

最佳答案

我建议将鼠标位置存储在您最初在 View 中单击的位置。计算鼠标在窗口坐标中的移动量。移动的距离必须映射到一个角度。旋转轴垂直(垂直)于鼠标移动的方向。结果是对象的旋转类似于 this WebGL 演示。

将当前鼠标位置存储在 startRotation 中。注意存储位置鼠标位置的坐标不是归一化 vector :

// xy normalized device coordinates:
float ndcX = 2.0f * xPos / context->getWidth() - 1.0f;
float ndcY = 1.0 - 2.0f * yPos / context->getHeight();

startVector = QVector3D(ndcX, ndcY, 0.0);

获取updateRotation中的当前位置:

// xy normalized device coordinates:
float ndcX = 2.0f * xPos / context->getWidth() - 1.0f;
float ndcY = 1.0 - 2.0f * yPos / context->getHeight();

endVector = QVector3D(ndcX, ndcY, 0.0);

计算从起始位置到结束位置的 vector :

QVector3D direction = endVector - startVector;

旋转轴垂直于运动方向:

rotationAxis = QVector3D(-direction.y(), direction.x(), 0.0).normalized();

请注意,即使 direction 的类型是 QVector3D,它仍然是一个二维 vector 。它是视口(viewport) XY 平面中的一个 vector ,表示鼠标在视口(viewport)上的移动。 z坐标为0。二维 vector (x, y),可以逆时针旋转90度,(-y, x)

方向 vector 的长度表示旋转的角度。鼠标在整个屏幕上移动会产生一个长度为 2.0 的 vector 。因此,如果在整个屏幕上拖动会导致完全旋转,则 vector 的长度必须乘以 PI。如果要执行 a hlf 旋转,则 PI/2:

angle = (float)qRadiansToDegrees(direction.length() * 3.141593);

最后,新的旋转必须应用于现有的旋转而不是模型:

QMatrix4x4 addRotation;
addRotation.rotate(angle, rotationAxis.x(), rotationAxis.y(), rotationAxis.z());
rotation = addRotation * rotation;

startRotationupdateRotation 方法的最终代码 list :

void ArcBall::startRotation(int xPos, int yPos) {

// xy normalized device coordinates:
float ndcX = 2.0f * xPos / context->getWidth() - 1.0f;
float ndcY = 1.0 - 2.0f * yPos / context->getHeight();

startVector = QVector3D(ndcX, ndcY, 0.0);
endVector = startVector;
rotating = true;
}
void ArcBall::updateRotation(int xPos, int yPos) {

// xy normalized device coordinates:
float ndcX = 2.0f * xPos / context->getWidth() - 1.0f;
float ndcY = 1.0 - 2.0f * yPos / context->getHeight();

endVector = QVector3D(ndcX, ndcY, 0.0);

QVector3D direction = endVector - startVector;
rotationAxis = QVector3D(-direction.y(), direction.x(), 0.0).normalized();
angle = (float)qRadiansToDegrees(direction.length() * 3.141593);

QMatrix4x4 addRotation;
addRotation.rotate(angle, rotationAxis.x(), rotationAxis.y(), rotationAxis.z());
rotation = addRotation * rotation;

startVector = endVector;
}

如果你想绕着物体的向上轴旋转a使物体沿着 View 空间x轴倾斜,那么计算就不同了。首先应用围绕 y 轴的旋转矩阵(向上 vector ),然后应用当前 View 矩阵,最后应用 x 轴上的旋转:

view-matrix = rotate-X * view-matrix * rotate-Y

函数更新轮换必须如下所示:

void ArcBall::updateRotation(int xPos, int yPos) {

// xy normalized device coordinates:
float ndcX = 2.0f * xPos / context->getWidth() - 1.0f;
float ndcY = 1.0 - 2.0f * yPos / context->getHeight();

endVector = QVector3D(ndcX, ndcY, 0.0);

QVector3D direction = endVector - startVector;

float angleY = (float)qRadiansToDegrees(-direction.x() * 3.141593);
float angleX = (float)qRadiansToDegrees(-direction.y() * 3.141593);

QMatrix4x4 rotationX;
rotationX.rotate(angleX, 1.0f 0.0f, 0.0f);

QMatrix4x4 rotationUp;
rotationX.rotate(angleY, 0.0f 1.0f, 0.0f);

rotation = rotationX * rotation * rotationUp;

startVector = endVector;
}

关于c++ - 用于旋转网格的 OpenGL ArcBall,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54498361/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com