简体   繁体   English

gluLookAt和glFrustum带有移动物体

[英]gluLookAt and glFrustum with a moving object

Original Question/Code 原始问题/代码

I am fine tuning the rendering for a 3D object and attempting to implement a camera following the object using gluLookAt because the object's center y position constantly increases once it reaches it's maximum height. 我正在调整3D对象的渲染并尝试使用gluLookAt实现跟随对象的摄像机,因为对象的中心y位置一旦达到其最大高度就会不断增加。 Below is the section of code where I setup the ModelView and Projection matrices: 下面是我设置ModelView和Projection矩阵的代码部分:

float diam = std::max(_framesize, _maxNumRows);
float centerX = _framesize / 2.0f;
float centerY = _maxNumRows / 2.0f + _cameraOffset;
float centerZ = 0.0f;
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glFrustum(centerX - diam,
          centerX + diam,
          centerY - diam,
          centerY + diam,
          diam,
          40 * diam);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(0., 0., 2. * diam, centerX, centerY, centerZ, 0, 1.0, 0.0);

Currently the object displays very far away and appears to move further back into the screen (-z) and down (-y) until it eventually disappears. 目前,该对象显示得非常远,并且似乎进一步移回屏幕(-z)和向下(-y),直到它最终消失。

What am I doing wrong? 我究竟做错了什么? How can I get my surface to appear in the center of the screen, taking up the full view, and the camera moving with the object as it is updated? 如何让我的曲面出现在屏幕中央,占据整个视图,相机随着对象移动而更新?


Updated Code and Current Issue 更新的代码和当前问题

This is my current code, which is now putting the object dead center and filling up my window. 这是我当前的代码,它现在将对象置于死点并填满我的窗口。

float diam = std::max(_framesize, _maxNumRows);
float centerX = _framesize / 2.0f;
float centerY = _maxNumRows / 2.0f + _cameraOffset;
float centerZ = 0.0f;
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(centerX - diam,
          centerX,
          centerY - diam,
          centerY,
          1.0,
          1.0 +  4 * diam);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(centerX, _cameraOffset, diam, centerX, centerY, centerZ, 0, 1.0, 0.0);

I still have one problem when the object being viewed starts moving it does not stay perfectly centered. 当被查看的对象开始移动时,我仍然有一个问题,它不会完全居中。 It appears to almost jitter up by a pixel and then down by 2 pixels when it updates. 它似乎几乎抖动一个像素,然后在更新时下降2个像素。 Eventually the object leaves the current view. 最终,对象离开当前视图。 How can I solve this jitter? 我该如何解决这个抖动?

Your problem is with the understanding what the projection does. 你的问题在于了解投影的作用。 In your case glFrustum . 在你的情况下glFrustum I think the best way to explain glFrustum is by a picture (I just drew -- by hand). 我认为解释glFrustum的最佳方式是通过图片(我只是手绘)。 You start of a space called Eye Space . 你开始了一个名为Eye Space的空间 It's the space your vertices are in after they have been transformed by the modelview matrix. 它是由模型视图矩阵转换后顶点所在的空间。 This space needs to be transformed to a space called Normalized Device Coordinates space. 需要将此空间转换为称为“ 规范化设备坐标”空间的空间。 This happens in a two fold process: 这发生在两个过程中:

  1. The Eye Space is transformed to Clip Space by the projection (matrix) 通过投影(矩阵)将眼睛空间转换为剪辑空间
  2. The perspective divide {X,Y,Z} = {x,y,z}/w is applied, taking it into Normalized Device Coordinate space. 应用透视除以{X,Y,Z} = {x,y,z} / w,将其带入规范化设备坐标空间。

The visible effect of this is that of kind of a "lens" of OpenGL. 这种可见效果是OpenGL的“镜头”。 In the below picture you can see a green highlighted area (technically it's a 3 volume) in eye space that, is the NDC space backprojected into it. 在下面的图片中,您可以看到眼睛空间中的绿色突出显示区域(技术上是3个体积),即NDC空间反投影到其中。 In the upper case the effect of a symmetric frustum, ie left = -right , top = -bottom is shown. 在大写的情况下,显示了对称平截头体的效果,即left = -righttop = -bottom In the bottom picture an asymmetric frustum, ie left ≠ -right , top ≠ -bottom is shown. 在底部图片中,示出了不对称平截头体,即left ≠ -righttop ≠ -bottom

glFrustum的影响

Take note, that applying such an asymmetry (by your center offset) will not turn, ie rotate your frustum, but skew it. 请注意,应用这种不对称性(通过中心偏移)将不会转动,即旋转平截头体,但会使其偏斜。 The "camera" however will stay at the origin, still pointing down the -Z axis. 然而,“相机”将保持在原点,仍然指向-Z轴。 Of course the center of image projection will shift, but that's not what you want in your case. 当然,图像投影的中心会发生变化,但这不是你想要的。

Skewing the frustum like that has applications. 像那样的平截头体偏斜有应用。 Most importantly it's the correct method to implement the different views of left and right eye an a stereoscopic rendering setup. 最重要的是,实现左眼和右眼的不同视图和立体渲染设置是正确的方法。

The perspective projection matrix generated by glFrustum defines a camera space (the space of vertices that it takes as input) with the camera at the origin . 所产生的透视投影矩阵glFrustum定义相机的空间(即它作为输入顶点的空间)与所述照相机在原点 You are trying to create a perspective matrix with a camera that is not at the origin. 您正在尝试使用不在原点的相机创建透视矩阵。 glFrustum can't do that, so the way you're attempting to do it simply will not work. glFrustum不能这样做,所以你尝试这样做的方式根本行不通。

There are ways to generate a perspective matrix where the camera is not at the origin. 有一些方法可以生成相机不在原点的透视矩阵。 But there's really no point in doing that. 但这样做真的没有意义。

The way a moving camera is generally handled is by simply adding a transform from the world space to the camera space of the perspective projection. 通常处理移动相机的方式是简单地将从世界空间的变换添加到透视投影的相机空间。 This just rotates and translates the world to be relative to the camera. 这只是旋转并将世界转换为相对于相机。 That's the job of gluLookAt . 这是gluLookAt的工作。 But your parameters to that are wrong too. 但你的参数也是错误的。

The first three values are the world space location of the camera. 前三个值是摄像机的世界空间位置。 The next three should be the world-space location that the camera should look at (the position of your object). 接下来的三个应该是相机应该看的世界空间位置(物体的位置)。

The answer by Nicol Bolas pretty much tells what you're doing wrong so I'll skip that. Nicol Bolas的回答几乎告诉你你做错了什么,所以我会跳过它。 You are looking for an solution rather than telling you what is wrong, so let's step right into it. 你正在寻找一个解决方案,而不是告诉你什么是错的,所以让我们直接进入它。

This is code I use for projection matrix: 这是我用于投影矩阵的代码:

glViewport(0, 0, mySize.x, mySize.y);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(fovy, (float)mySize.x/(float)mySize.y, nearPlane, farPlane);

Some words to describe it: glViewport sets the size and position of display place for openGL inside window. 用一些词来形容它:glViewport设置窗口内openGL的显示位置的大小和位置。 Dunno why, I alsways include this for projection update. Dunno为什么,我总是把它包括在投影更新中。 If you use it like me, where mySize is 2D vector specifying window dimensions, openGL render region will ocuppy whole window. 如果你像我一样使用它,其中mySize是指定窗口尺寸的2D矢量,openGL渲染区域将会占据整个窗口。 You should be familiar with 2 next calls and finaly that gluPerspective . 你应该熟悉2个下一个电话,最后是gluPerspective First parameter is your "field of view on Y axis". 第一个参数是您的“Y轴视野”。 It specifies the angle in degrees how much you will see and I never used anything else than 45. It can be used for zooming though, but I prefer to leave that to camera operating. 它指定了你将看到多少度的角度,我从未使用过45以外的任何东西。虽然它可以用于缩放,但我更喜欢将其留给相机操作。 Second parameter is aspect. 第二个参数是方面。 It handles that if you render square and your window sizes aren't in 1:1 ratio, it will be still square. 如果你渲染方形并且你的窗口大小不是1:1的比例,它会处理它,它仍然是方形的。 Third is near clipping plane, geometry closer than this to camera won't get rendered, same with farPlane but on contrary it sets maximum distance in what geometry gets rendered. 第三个是近剪裁平面,几何形状比相机更接近相机不会被渲染,与farPlane相同,但相反它设置了几何体渲染的最大距离。

This is code for modelview matrix 这是modelview矩阵的代码

glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(  camera.GetEye().x,camera.GetEye().y,camera.GetEye().z,
camera.GetLookAt().x,camera.GetLookAt().y,camera.GetLookAt().z,
camera.GetUp().x,camera.GetUp().y,camera.GetUp().z);

And again something you should know: Again, you can use first 2 calls so we skip to gluLookAt . 还有一些你应该知道的事情:再次,你可以使用前2个调用,所以我们跳到gluLookAt I have camera class that handles all the movement, rotations, things like that. 我有相机类来处理所有的运动,旋转,这样的事情。 Eye, LookAt and Up are 3D vectors and these 3 are really everything that camera is specified by. Eye,LookAt和Up是3D矢量,这3个实际上是摄像机指定的所有内容。 Eye is the position of camera, where in space it is. 眼睛是相机的位置,它在空间中。 LookAt is the position of object you're looking at or better the point in 3D space at which you're looking because it can be really anywhere not just center object. LookAt是您正在查看的对象的位置,或更好的3D空间中您正在寻找的点,因为它实际上可以是任何地方而不仅仅是中心对象。 And if you are worried about what's Up vector, it's really simple. 如果你担心怎么了Up矢量,它真的很简单。 It's vector perpedicular to vector(LookAt-Eye), but becuase there's infinite number of such vectors, you must specify one. 它是矢量perpeicular to vector(LookAt-Eye),但是因为有无数个这样的向量,你必须指定一个。 If your camera is at (0,0,0) and you are looking at (0,0,-1) and you want to be standing on your legs, up vector will be (0,1,0) . 如果你的相机位于(0,0,0)并且你正在看(0,0,-1)并且你想要站在你的腿上,向上矢量将是(0,1,0) If you'd like to stand on your head instead, use (0,-1,0) . 如果你想站在头上,请使用(0,-1,0) If you don't get the idea, just write in comment. 如果你没有得到这个想法,那就写下评论吧。

As you don't have any camera class, you need to store these 3 vectors separately by yourself. 由于您没有任何相机类,您需要自己分别存储这3个向量。 I believe you have something like center of 3D object you're moving. 我相信你有像移动3D物体中心的东西。 Set that position as LookAt after every update. 每次更新后将该位置设置为LookAt。 Also in initialization stage(when you're making the 3D object) choose position of camera and up vector. 同样在初始化阶段(当您制作3D对象时)选择摄像机位置和向上矢量。 After every update to object position, update the camera position the same way. 每次更新到对象位置后,以相同的方式更新摄像机位置。 If you move your object 1 point up at Y axis, do the same to camera position. 如果将对象在Y轴上向上移动1点,请对相机位置执行相同操作。 The up vectors remains constant if you don't want to rotate camera. 如果您不想旋转相机,向上矢量保持不变。 And after every such update, call gluLookAt with updated vectors. 在每次这样的更新之后,使用更新的向量调用gluLookAt

For updated post: I don't really get what's happening without bigger frame of reference (but I don't want to know it anyway). 对于更新的帖子:如果没有更大的参考框架,我真的不会得到正在发生的事情(但我还是不想知道它)。 There are few things I get curious about. 我很少有好奇的东西。 If center is 3D vector that stores your object position, why are you setting the center of this object to be in right top corner of your window? 如果center是存储对象位置的3D矢量,为什么要将此对象的中心设置在窗口的右上角? If it's center, you should have those +diam also in 2nd and 4th parameter of glOrtho , and if things get bad by doing this, you are using wrong names for variables or doing something somewhere before this wrong. 如果它是中心,那么你应该在glOrtho第二和第四个参数中使用那些+ diam,如果这样做glOrtho事情变得糟糕,你就会在变量之前使用错误的名称或者在错误之前做某事。 You're setting the LookAt position right in your updated post, but I don't find why you are using those parameters for Eye. 您正在更新的帖子中设置LookAt位置,但我不知道您为Eye使用这些参数的原因。 You should have something more like: centerX, centerY, centerZ-diam as first 3 parameters in gluLookAt . 你应该有更多的东西,如: centerX, centerY, centerZ-diam为前3个参数gluLookAt That gives you the camera on the same X and Y position as your object, but you will be looking on it along Z axis from distance diam 这使得相机在与物体相同的X和Y位置上,但是你将沿着Z轴从距离diam看它

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM