LibGDX移动旋转的摄像机 [英] LibGDX Moving a Rotated Camera

查看:654
本文介绍了LibGDX移动旋转的摄像机的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我来到我的应用程序,使用LibGDX构建的情况,我需要相机能够旋转,也可以移动的用户,以及能够缩放。我的相机控制移动和缩放相机的美丽,但是,当相机旋转时,相机然后基于该旋转移动。例如,如果相机向左转动45度,并且用户向右拖动以移动相机,则它将向右上方移动,因为这是相机的右侧现在指向的地方。相反,我需要相机总是相对于屏幕/用户输入移动,而不管它的旋转。



我有一个解决这个问题的方法,那就是简单地使用世界坐标来定位相机,而不是基于窗口坐标我试图使用现在。这创建了一个非常不愉快的用户体验,因为它使相机相当不稳定,并导致我的缩放系统的问题。我假设我可以修补这些问题,与大量的调整,但是,因为它已经使用窗口坐标太顺畅,我真的更喜欢走这条路线。



我怀疑这个看似简单的问题有一个优雅的解决方案,我可以做一个简单的计算矩阵或沿着这些线条,但我的知识在OpenGL仍然相当缺乏,我似乎不知道究竟需要什么发生修复它。



=== EDIT ===



用于保存值的对象本质上就是我自己的Vector2版本,它在应用程序的不同部分是必需的。我不太清楚0.7f在那里的确切推理,但大概只是降低运动的敏感性,如果我删除它的问题仍然存在。

  camera.position.set(cameraStartPosition.getX() - ((zoomCurrentPosition.getX() -  zoomStartPosition.getX())* 0.7f),cameraStartPosition.getY ((zoomCurrentPosition.getY() -  zoomStartPosition.getY())* 0.7f),0); 

cameraStartPosition - 用户开始移动相机时的X和Y坐标。 >

zoomStartPosition - 开始缩放的初始触摸的X和Y坐标



zoomCurrentPosition - X和Y坐标控制当前缩放的触摸是



这些中的x和y值直接从touchDown和touchDragged方法获取。如果我放置的代码设置以下代码之后的代码,它创建了我在原始帖子中提到的问题,它移动的方式,它应该,但非常浪潮。

  Vector3 vector = new Vector3(x,y,0); 
camera.unproject(vector);
x =(int)vector.x;
y = CanvasAnywhereMain.HEIGHT - (int)vector.y;


解决方案

轨道摄像机。我会尝试描述你如何处理这个问题。



我希望我的轨道摄像机能够在同一时间围绕X和Y轴旋转,但它不工作。



对我来说,诀窍是:

  Vector3 target = Vector3.zero 
Vector3 right = new Vector()。set(camera.direction).crs(camera.up).nor()

//这个角度通常来自输入处理器中的touchDragged事件
//实现InputProcessor的类,在其中执行计算
deltaAngleX = 1.1f;
deltaAngleY = 1.9f;

//绕X轴旋转
camera.rotateAround(target,right,deltaAngleX);

//绕Y旋转
camera.updateRotation(Vector3.Y,deltaAngleY);

当你围绕Y轴旋转时,一切都很好,因为Y轴不会根据你的X旋转而改变。



但是当你围绕X旋转时,你不能使用Vector3.X,因为这个轴不会相对于您的相机位置和方向。所以我们需要计算你的相机的本地Y轴。为了做到这一点,我们需要知道两个向量的交叉乘积。请参阅维基上的跨产品关于libgdx类引用的crs()

以下代码片段将返回新的Vector3,它将指向相对于当前相机的右轴。注意,由于我们要对该向量进行归一化,因此我们需要调用nor()。



长故事

  Vector3 right = new Vector()。set(direction).crs(up).nor(); 

Crs从两个向量(在我们的例子中为camera.direction和camera.up)创建叉积向量。



我不明白为什么在Vector3中,右边的成员变量没有暴露,或者为什么右向量计算方法不存在,但这将会做的



有了几个代码编辑,你可以移动你的播放器,相机或任何东西在你需要的轴周围。









b $ b

您必须先绕X轴旋转,因为绕Y旋转会改变您需要重新计算的本地X轴(右向量)。


I've come to a situation in my application, built using LibGDX, where I need the camera to be able to rotate, and also be moveable by the user, as well as being able to be zoomed. My camera controls for moving and zooming the camera work beautifully, however, when the camera is rotated, the camera is then moved based on that rotation. For example, if the camera is turned 45 degrees to the left, and the user drags to the right to move the camera, it will move towards the upper right, because that is where the right side of the camera is now pointing. Instead, I need the camera to always move relative to the screen/user input, regardless of its rotation.

I do have one solution for this problem, and that is to simply use "world coordinates" to position the camera, rather than basing it on the "window coordinates" I am trying to use now. This creates a very unpleasant user experience though, as it makes the camera fairly choppy and causes problems with my zooming system. I assume I could patch those problems up with a lot of tweaking, however, because it is so much smoother already using the window coordinates, I would really prefer to go that route.

I suspect there is an elegant solution to this seemingly simple problem, where I could do a simple calculation on a matrix or something along those lines, however my knowledge in OpenGL is still pretty lacking and I cannot seem to figure out what exactly needs to happen to fix it. Any ideas from someone more adept with OpenGL and all of this matrices would be greatly appreciated!

===EDIT===

The objects used to hold the values here are essentially just my own version of Vector2, which was required in a different part of the application. I can't quite remember the exact reasoning for the 0.7f in there, but presumably it was just to lower the sensitivity of the movement, and the problem still persists if I remove it.

camera.position.set(cameraStartPosition.getX() - ((zoomCurrentPosition.getX() - zoomStartPosition.getX()) * 0.7f), cameraStartPosition.getY() + ((zoomCurrentPosition.getY() - zoomStartPosition.getY())  * 0.7f), 0);

cameraStartPosition - The X and Y coordinates of the camera when the user starts to move it.

zoomStartPosition - The X and Y coordinates of the initial touch that starts the zoom

zoomCurrentPosition - The X and Y coordinates where the touch that controls the zoom currently is

The x and y values in those are taken directly from the touchDown and touchDragged methods. If I instead place the code that sets those after the following code, it creates the problem I mentioned in the original post, where it moves the way it should, but very choppy.

    Vector3 vector = new Vector3(x, y, 0);
    camera.unproject(vector);
    x = (int) vector.x;
    y = CanvasAnywhereMain.HEIGHT - (int) vector.y;

解决方案

I was dealing with similar problem today when I was programming orbit camera. I will try to describe you how I dealt with this issue.

I wanted my orbit camera to be able to rotate around X and Y axis in the same time, but it was not working. I was able to rotate around this axes only respectively.

The trick for me was:

Vector3 target = Vector3.zero
Vector3 right = new Vector().set(camera.direction).crs(camera.up).nor();

// This angles usualy comes from touchDragged event in your input processor
// class implementing the InputProcessor, where you do your calculations
deltaAngleX = 1.1f;
deltaAngleY = 1.9f;

// Rotate around X axis
camera.rotateAround(target, right, deltaAngleX);

// Rotate around Y
camera.updateRotation(Vector3.Y, deltaAngleY);

When you are rotating around Y axis everything is fine because Y axis does not change depending on your X rotation. You always want to rotate around the world Y axis, not any local one.

But when you are rotating around X you can not use Vector3.X because this axis will not be relative to your camera position and direction. So we need to calculate "local Y" axis of your camera. To do that we need to know what Cross product of two vectors is. Please see Cross product on wiki and crs() on libgdx class reference

Following code fragment will return new Vector3, which will be pointing to the right axis relative to the current camera. Note the nor() call is present because we want to normalize that vector.

Long story short:

Vector3 right = new Vector().set(direction).crs(up).nor();

Crs creates cross product vector from two vectors (in our case camera.direction and camera.up).

I don't understand why in Vector3 the right member variable is not exposed or why right vector calculation method is not present, but this will do the trick anyway

With few code edits you can move your player, camera or anything in the world around the axis you need. You just need to understand the basic Vector operations so I recommend you going trough them

Last note:

You must rotate around X axis first because rotating around Y changes your local X axis which will need to be recalculated (the right vector).

这篇关于LibGDX移动旋转的摄像机的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆