Этот код вызывается перед каждым перерисованием. Я не знаю, как вы вращаетесь/выполняете перевод (таймер или mouseDown), но в любом случае методы, описанные ниже, могут выполняться плавно и естественно для пользователя.
Если ваш объект обрезается ближайшей плоскостью, переместите плоскость ближнего отсечения назад к камере (в этом коде увеличьте 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);
Матрица проецирования, где определяется отсечение усечения. Опять же, если камера слишком близко, мы не сможем установить плоскость ближнего отсечения, чтобы избежать обрезки объекта, если он больше, чем расстояние до нашей камеры от начала координат. В то время как я не вижу причин не устанавливать камеру достаточно далеко, есть причины (точность отбраковки глубины), чтобы не устанавливать плоскость отсечения ближнего/дальнего действия дальше, чем вам нужно.
В этом коде апертура камеры используется напрямую, но если вы используете что-то вроде glFrustum для создания матрицы Projection, неплохо вычислить левую и правую плоскости отсечения из апертуры камеры. Таким образом, вы можете создать эффект масштабирования, изменив апертуру камеры (возможно, в методе 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);
EDIT:.
Вот код, иллюстрирующий, как вычислить левый и правый плоскостей отсечения от апертуры камеры:
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;
}
Я не понимаю ваш вопрос. Вы используете какой-то самодельный отсев, чтобы определить, какие объекты не должны быть нарисованы? Если да, то почему вы просто не делаете этого _after_, вы поворачиваете/переводите их? – HolyBlackCat
Вам нужно опубликовать код о том, как вы создаете матрицу проекции. Если вы понимаете, каковы возможности измерения, это не должно быть проблемой при определении вашей проекционной матрицы с точки зрения приближения/расстояния или апертуры камеры. Это матрица проекции (а не матрица вида), которую вы можете переопределить на лету. – jwlaughton
Если это вам поможет, я разместил код Objective C, иллюстрирующий, как вычисляются матрицы View и Projection. Эти вычисления выполняются «на лету» в методе, который я называю resizeGL. Вы увидите, что отсечение выполняется в матрице проекции. – jwlaughton