`
jinvasshole
  • 浏览: 771426 次
文章分类
社区版块
存档分类
最新评论

jMonkeyEngine之Camera全攻略

 
阅读更多

昨天弄Camera,本来还以为不难,谁知道却被这个问题困扰了一个晚上。不知怎么地,早上突然一个猜想,然后测试,通过!因此写下本文,供大家一起学习交流。本文所用图片都是本人亲手PS的,所以转载文章、图片请注明出处。谢谢!

想自定义jMonkeyEngine中的Camera一般需要做2件事:

1、 设置摄像机视锥(ViewFrustum)的大小

2、 设置摄像机的位置和朝向

设置视锥(ViewFrustum)一般有以下2个方法:

setFrustum(float near, float far, float left, float right, float top, float bottom)

float near : 最近那个面(屏幕)离摄像机位置(你眼睛)的距离。

float far : 相当于摄像机最远那个面和你眼睛的距离。

float left : 最近那个面向左偏离你眼睛的值。

float right : 最近那个面向右偏离你眼睛的值。

float top : 最近那个面向上偏离你眼睛的值。

float bottom : 最近那个面向下偏离你眼睛的值。

该方法比较直观,也就是当你设置了一个锥体的2个截面和你距离,以及第一个截面的大小。那么你就能确定这个锥体(如下图,省略了rightbottom,原理和topleft一样)。

另一种设置视锥的方法是下面这种:

setFrustumPerspective(float fovY, float aspect, float near, float far)

float fovY : 如果一个摄像机固定,一个物体从被正视到往上移动直到看不到的角度。

float aspect : 屏幕的宽高比。

float near : 最近那个面(屏幕)离摄像机位置(你眼睛)的距离。

float far : 相当于摄像机最远那个面和你眼睛的距离。

这个方法也比较容易理解,看下面的图:

一般float fovY如果你不知道设置什么好,就设置45f,该值应该在0-90之间。你想想,如果你设置了91,那么表示摄像机上下的角度加起来将超过182,也就是你能看到自己后面的东西?而如果设置太小将形成隧道效应。

总体来说,设置视锥还是比较容易。接下来是设置位置和朝向。这很重要,决定了你能不能看到东西,就看这一步了。

设置帧(setFrame

1、 通过setLocation(Vector3f loc)lookAt(Vector3f pos, Vector3f worldUp)组合设置

2、 通过setFrame(Vector3f loc, Quaternion axes)

3、 通过setFrame(Vector3f loc, Vector3f left, Vector3f up, Vector3f dir)

第一种方法比较简单。大家可以试一下,就是设置Camera的位置和它看向的方向。这个我就不说了。

第二种方法我还没试过。当应该和第三种方法原理一样。

我现在就讲讲第三种,正是这种方法困扰了我一天。

先看下面这个图:

setFrame(Vector3f loc, Vector3f left, Vector3f up, Vector3f dir)

其中 loc为摄像机的位置,即视锥的顶点的在世界中的位置。而leftup则定义了camera自己的坐标系。dircamera指向的方向。

//想在图中位置正视box,如下代码

Vector3f loc = new Vector3f(0,0,100);

Vector3f left = new Vector3f(-1,0,0);

Vector3f up = new Vector3f(0,1,0);

Vector3f dir = new Vector3f(0,0,-1);

cam.setFrame(loc, left, up, dir);

up定义了camera的上轴,由于现在该轴和世界坐标系的Y轴一样,因此为(0,1,0),由于我们想让cameraZ轴正向往Z轴负向看。因此dir应该为(0,0,-1),而由于jME中使用右手坐标系统,因此X轴此时就只能是往左。即(-100)。Z轴可以看成是视锥顶点到各个截面中心的连线所指的方向,这个很重要记住!。

注意:很多人(包括我)一开始可能会想到将Camera移动到X轴正向,然后设置dir来从右边观察位于原点的Box。如下代码:

Vector3f loc = new Vector3f(100,0,0);

Vector3f left = new Vector3f(-1,0,0);

Vector3f up = new Vector3f(0,1,0);

Vector3f dir = new Vector3f(-1,0,0);

cam.setFrame(loc, left, up, dir);

你会发现这样根本看不到box

因为camera的坐标轴并没有改变,改变的只是dir。在坐标轴不变的情况下改变dir相当于将camera进行变形操作。而当dirx轴或y轴为同一方向时,整个视锥相当于被压扁。它此时近似已经没有可视范围了,因此不管怎样都看不到东西了。

你还可以试试:

//想从Y轴往下看,也看不到Camera

Vector3f loc = new Vector3f(0, 100,0);

Vector3f left = new Vector3f(-1,0,0);

Vector3f up = new Vector3f(0,1,0);

Vector3f dir = new Vector3f(0, -1,0);

cam.setFrame(loc, left, up, dir);

那么怎样才能在Vector3f loc = new Vector3f(100,0,0);的情况下从右侧观察box能。很简单。确定Y轴,确定dir,让它指向世界坐标X轴负向,最后确定CameraX轴(由右手坐标规则)。

试试:

Vector3f loc = new Vector3f(100,0, 0);

Vector3f left = new Vector3f(0,0,1);

Vector3f up = new Vector3f(0,1,0);

Vector3f dir = new Vector3f(-1,0, 0);

cam.setFrame(loc, left, up, dir);

OK了吧。

不知道怎样会不会让你更好理解一点:想要确定摄像机的朝向,那么先确定它的dir,然后确定up(因为一般都是(010)),然后把dir看成是Z轴,UP则是Y轴,这样就可以确定X轴,就是left

注意:上面的(0,0,1)(0,0,4)指向的是同一个方向,但是使用(004)你会发现box变形了。在这里,leftupdir的数值除了用于计算方向,还代表单位向量的长度。因此,需要计算好。

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics