很抱歉我之前没有明确解释过我的问题,我改变如下。看起来解决方案是即时更改投影矩阵?让我做一些研究,看看如何正确地做到这一点。
我的情况是:===> 说,现在,我在windows7下的窗口中创建了一个3D框,并启用了透视模式。从用户的角度来看,当用户移动(旋转/翻译)此框时,当框不在窗口时,应该剪切/(部分隐藏),这是正确的。但是当盒子在窗口内移动时,盒子应该总是完全显示(没有剪裁!),对吗?但我的问题是,有时,当用户在窗口内移动框时,他会看到此框的某些部分被剪裁(例如,此框的一个顶点被剪掉)。没有限制用户可以移动此框。
我的理解是:===> 当用户移动盒子时,这个盒子没有截止,这就是为什么它被剪裁了。 在这种情况下,我的代码应该在运行中调整平截头体(然后,投影矩阵被更改)或动态调整相机(也许,调整近远平面)或做其他事情?
我的问题是:===> 什么是避免这种剪辑的流行技术?并确保用户感觉他们正在顺利移动盒子,没有任何“混蛋”(就像突然,当用户移动盒子时,盒子的位置被跳到另一个位置(因为我们的平截头体突然变大)。 我认为这是一个非常经典的问题,应该有一个完美的解决方案。任何代码/参考都表示赞赏!
我附上了一张图片来展示问题。
谢谢!
答案 0 :(得分:0)
我怀疑你的视锥体太窄了。因此,当您旋转对象时,它的一部分移动到可视区域之外。作为实验,尝试增加您的平截头体角度,将您的远值增加到1000或甚至10000,然后将相机从中心向后移动(z平面上的负值更高)。这应该会产生一个非常大的平截头体,您的对象应该适合它。运行你的项目并旋转 - 如果裁剪效果消失,你知道你的问题是截头锥体或模型比例(或两者)。
答案 1 :(得分:0)
这在我身上发生,并且调整透视矩阵不允许在.5以下的近平面没有我所有的对象消失。
然后我在某处读到: 深度钳制。 -对顶点Z位置的裁剪行为 (即:-w_c \ le z_c \ le w_c)可以通过激活深度夹紧来关闭。
glEnable(GL_DEPTH_CLAMP);
我可以靠近我的物体而不会被剪掉。
我不知道这样做是否会导致其他问题,但是到目前为止,我还没有遇到任何问题。
答案 2 :(得分:-3)
在每次重绘之前调用此代码。我不知道你是如何旋转/翻译的(计时器或鼠标),但无论如何,下面描述的方法可以顺利完成并且对用户来说是自然的。
如果您的物体被近处平面剪裁,请将近切割平面移回相机(在此代码中,增加VIEWPLANEOFFSET)。如果相机距离太近而无法让近处飞机向后移动足够远,则可能还需要将相机移回。
如果您的物体被左,右,顶部或底部剪裁平面剪裁,请调整相机光圈。
这将在下面详细讨论。
// ******************************* Distance of The Camera from the Origin
cameraRadius = sqrtf((camera.viewPos.x * camera.viewPos.x) + (camera.viewPos.y * camera.viewPos.y) + (camera.viewPos.z * camera.viewPos.z));
GLfloat phi = atanf(camera.viewPos.x/cameraRadius);
GLfloat theta = atanf(camera.viewPos.y/cameraRadius);
camera.viewUp.x = cosf(theta) * sinf(phi);
camera.viewUp.y = cosf(theta);
camera.viewUp.z = sinf(theta) * sinf(phi);
您将看到View矩阵,我们只定义相机(眼睛)位置和视图方向。这里还没有剪辑,但相机位置将限制我们可以看到的内容,如果它太靠近物体,我们将限制我们如何设置附近截止飞机。我无法想到任何不将相机放回相当远的原因。
// ********************************************** Make the View Matrix
viewMatrix = GLKMatrix4MakeLookAt(camera.viewPos.x, camera.viewPos.y, camera.viewPos.z, camera.viewPos.x + camera.viewDir.x, camera.viewPos.y + camera.viewDir.y, camera.viewPos.z + camera.viewDir.z, camera.viewUp.x, camera.viewUp.y, camera.viewUp.z);
Projection矩阵是定义裁剪平截头体的位置。同样,如果相机距离太近,我们将无法设置近截止平面,以避免在物体距离原点的距离大于物体时剪切物体。虽然我看不出任何理由不将相机设置得相当远,但有理由(深度剔除的准确性)不要将近/远剪裁平面设置得比你需要的更远。
在此代码中,直接使用相机光圈,但如果您使用glFrustum之类的东西来创建投影矩阵,则从相机光圈计算左右剪裁平面是个不错的主意。这样,您可以通过改变相机光圈(可能是mouseDown方法)来创建缩放效果,这样用户就可以根据自己的喜好放大或缩小。增大光圈有效地缩小。有效地减小光圈放大。
// ********************************************** Make Projection Matrix
GLfloat aspectRatio;
GLfloat cameraNear, cameraFar;
// The Camera Near and Far Cutoff Planes
cameraNear = cameraRadius - VIEWPLANEOFFSET;
if (cameraNear < 0.00001)
cameraNear = 0.00001;
cameraFar = cameraRadius + VIEWPLANEOFFSET;
if (cameraFar < 1.0)
cameraFar = 1.0;
// Get The Current Frame
NSRect viewRect = [self frame];
camera.viewWidth = viewRect.size.width;
camera.viewHeight = viewRect.size.height;
// Calculate the Ratio of The View Width / View Height
aspectRatio = viewRect.size.width / viewRect.size.height;
float fieldOfView = GLKMathDegreesToRadians(camera.aperture);
projectionMatrix = GLKMatrix4MakePerspective(fieldOfView, aspectRatio, cameraNear, cameraFar);
编辑:
以下是一些说明如何从相机光圈计算左右剪裁平面的代码:
GLfloat ratio, apertureHalfAngle, width;
GLfloat cameraLeft, cameraRight, cameraTop, cameraBottom, cameraNear, cameraFar;
GLfloat shapeSize = 3.0;
GLfloat cameraRadius;
// Distance of The Camera from the Origin
cameraRadius = sqrtf((camera.viewPos.x * camera.viewPos.x) + (camera.viewPos.y * camera.viewPos.y) + (camera.viewPos.z * camera.viewPos.z));
// The Camera Near and Far Cutoff Planes
cameraNear = cameraRadius - (shapeSize * 0.5);
if (cameraNear < 0.00001)
cameraNear = 0.00001;
cameraFar = cameraRadius + (shapeSize * 0.5);
if (cameraFar < 1.0)
cameraFar = 1.0;
// Calculte the camera Aperture Half Angle (radians) from the Camera Aperture (degrees)
apertureHalfAngle = (camera.aperture / 2) * PI / 180.0; // half aperture degrees to radians
// Calculate the Width from 0 of the Left and Right Camera Cutoffs
// We Use Camera Radius Rather Than Camera Near For Our Own Reasons
width = cameraRadius * tanf(apertureHalfAngle);
NSRect viewRect = [self bounds];
camera.viewWidth = viewRect.size.width;
camera.viewHeight = viewRect.size.height;
// Calculate the Ratio of The View Width / View Height
ratio = camera.viewWidth / camera.viewHeight;
// Calculate the Camera Left, Right, Top and Bottom
if (ratio >= 1.0)
{
cameraLeft = -ratio * width;
cameraRight = ratio * width;
cameraTop = width;
cameraBottom = -width;
} else {
cameraLeft = -width;
cameraRight = width;
cameraTop = width / ratio;
cameraBottom = -width / ratio;
}