OpenTK/ONGGL-用鼠标旋转相机
本文关键字:旋转 相机 鼠标 ONGGL- OpenTK | 更新日期: 2023-09-27 18:15:48
背景
我当前显示的对象将始终位于原点。我有一个函数,可以增加我的x和y角度,然后计算相机的新x,y,z坐标:
Public Sub update_rotation()
If cam.manual_lookat = True Then
If camangley >= 360 Then
camangley = camangley - 360
End If
If camanglex >= 360 Then
camanglex = camanglex - 360
End If
If camangley < 0 Then
camangley = 360 + camangley
End If
If camanglex < 0 Then
camanglex = 360 + camanglex
End If
If camangley > 90 And camangley <= 270 Then
cam.invert_y = True
Else
cam.invert_y = False
End If
camx = distance * -Sin(camanglex * (PI / 180)) * Cos((camangley) * (PI / 180))
camy = distance * -Sin((camangley) * (PI / 180))
camz = distance * Cos((camanglex) * (PI / 180)) * Cos((camangley) * (PI / 180))
cam.Position.X = camx
cam.Position.Y = camy
cam.Position.Z = camz
cam.lookat.X = 0
cam.lookat.Y = 0
cam.lookat.Z = 0
' Label2.Text = camanglex & "," & camangley
End If
End Sub
我已经设置为使用键盘事件。。X按钮添加到camanglex变量,Y按钮添加到camangley变量,Z按钮添加到距离变量。
用这种方式,用键盘,一切都很好。
问题
我现在试着用鼠标代替键盘来处理旋转。我相信这只是一个数学问题,但我如何计算新的camanglex和camangley变量,或者直接计算新的camx、camy和camz变量,以确定我的相机的新位置?
我有一个鼠标功能,可以捕捉鼠标坐标,但计算部分有问题。
如果您想围绕对象进行动态观察,您可以跟踪鼠标在假球体上的路径(有时称为轨迹球(。有一个轨道控制的工作示例。
这里有一个类似的伪代码草图:
mouseDownEventFunction(event) {
computeDragPoint (event.mouseX, event.mouseY, &oldDragPoint);
isMouseDown = true;
}
mouseUpEventFunction(event) {
isMouseDown = false;
}
mouseMoveEventFunction(event) {
if (isMouseDown) {
computeDragPoint (event.mouseX, event.mouseY, &newDragPoint);
rotateCamera (oldDragPoint, newDragPoint);
oldDragPoint = newDragPoint;
}
}
在这里我们可以找到轨迹球上的一个点:
/* we want to ray trace a point on face side of fake sphere.
dragPoint* is our result*/
computeDragPoint(int x, int y, Vector3* dragPoint) {
/* normalize x and y to [-1, 1] so they match flat circle position on screen.
And assign this to dragPoint->x and dragPoint->y.
This part depends on what you want to achieve and input units of x, y.
Keep in mind aspect ratio */
dragPoint->x = (2*x/screenWidth - 0.5) * (screenHeight/screenWidth);
dragPoint->y = 2*y/screenHeight - 0.5;
dragPoint->x /= sqrt(dragPoint->x*dragPoint->x + dragPoint->y*dragPoint->y);
dragPoint->y /= sqrt(dragPoint->x*dragPoint->x + dragPoint->y*dragPoint->y);
/* Then having two values in [-1,1] compute corresponding z */
float tmp = dragPoint->x*dragPoint->x + dragPoint->y*dragPoint->y;
if (tmp > 1) {
dragPoint.x /= sqrt(tmp);
dragPoint.y /= sqrt(tmp);
}
dragPoint->z = -sqrt (1 - dragPoint->x^2 - dragPoint->y^2) || 0;
}
旋转数学可以用四元数来完成(如果你不想使用四元数,也可以只使用欧拉角的矩阵(:
rotateCamera(oldDragPoint, newDragPoint) {
Quaternion quat = new Quaternion (Config.AngleX, Config.AngleY, Config.AngleZ);
quat.normalize();
Quaternion deltaQuat = new Quaternion();
deltaQuat = deltaQuat.setFromUnitVectors(oldDragPoint, newDragPoint);
quat = quat.multiply(deltaQuat);
quat.normalize();
Vector3 resultAngles = Vector3();
resultAngles.setFromQuaternion(quat);
setCameraPositionFromAngles(resultAngles);
}
在setCameraPositionFromAngles(resultAngles(中,通过对初始相机位置应用三个基本旋转来设置最终的X、Y、Z坐标。所以你的主要参数是resultAngles。你更新角度,然后设置位置。
也许这个工作示例可以更好地解释。