2015-01-22 5 views
-1

Извините, что я раньше не объяснял свой вопрос, я изменился, как показано ниже. И похоже, что решение заключается в том, чтобы изменить матрицу проекции «на лету»? Позвольте мне сделать некоторые исследования, чтобы увидеть, как это сделать правильно.opengl: избегать обрезки в перспективном режиме?

Мой сценарий: ===> Скажем, теперь я создал 3D-окно в окне под Windows7 с включенным режимом перспективы. С точки зрения пользователей, когда пользователи перемещают (поворачивают/переводят) это поле, когда окно выходит из окна, оно должно быть обрезано/(частично скрыто), это правильно. Но когда окно перемещается внутри окна, поле всегда должно быть показано полностью (не обрезано!), Правильно? Но моя проблема в том, что когда пользователи перемещают окно внутри окна, он видит, что некоторые части этого окна обрезаны (например, одна вершина этого окна отсечена). Нет предела тому, сколько пользователей может переместить этот ящик.

Мое понимание: ===> Когда пользователи перемещают коробку, этот ящик выходит из усечения, поэтому его обрезают. В этом случае мой код должен регулировать усечение на лету (тогда изменяется матрас проекции) или настраивать камеру на лету (возможно, отрегулировать ближнюю дальность полета) или сделать что-то еще?

Мой вопрос: ===> Какова популярная техника, чтобы избежать такого отсечения? И убедитесь, что пользователи чувствуют, что они плавно перемещаются, не имея какого-либо «рывка» (например, внезапно местоположение коробки перепрыгивает в другое место (потому что наше усечение внезапно сильно меняется), когда пользователи перемещают ящик). Я думаю, что это очень классическая проблема, должно быть идеальное решение. Любой код/​​ссылки приветствуются!

Прикрепленный файл, чтобы показать возникшую проблему. enter image description here

спасибо!

+0

Я не понимаю ваш вопрос. Вы используете какой-то самодельный отсев, чтобы определить, какие объекты не должны быть нарисованы? Если да, то почему вы просто не делаете этого _after_, вы поворачиваете/переводите их? – HolyBlackCat

+0

Вам нужно опубликовать код о том, как вы создаете матрицу проекции. Если вы понимаете, каковы возможности измерения, это не должно быть проблемой при определении вашей проекционной матрицы с точки зрения приближения/расстояния или апертуры камеры. Это матрица проекции (а не матрица вида), которую вы можете переопределить на лету. – jwlaughton

+0

Если это вам поможет, я разместил код Objective C, иллюстрирующий, как вычисляются матрицы View и Projection. Эти вычисления выполняются «на лету» в методе, который я называю resizeGL. Вы увидите, что отсечение выполняется в матрице проекции. – jwlaughton

ответ

-3

Этот код вызывается перед каждым перерисованием. Я не знаю, как вы вращаетесь/выполняете перевод (таймер или 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; 
} 
+0

Это не отвечает на вопрос. –

+0

@NoahWitherspoon Возможно, это потому, что вопрос был неясным. Спасибо за помощь, которую вы дали. – jwlaughton

+0

Вопрос нечеткий, но он явно спрашивает об отсечении в виде усечения, о котором ваш код не вникает в подробности. Некоторое объяснение идей там сделало бы это достойным ответом. –

0

Я подозреваю, что ваш усечка слишком узкая. Таким образом, когда вы вращаете свой объект, его части перемещаются за пределы видимой области. В качестве эксперимента попробуйте увеличить угол усечения, увеличивая значение Far до значения 1000 или даже 10000 и двигайте камеру дальше от центра (более высокое отрицательное значение на плоскости z). Это должно создать очень большую усеченность, в которой ваш объект должен соответствовать. Запустите проект и поверните - если эффект отсечения исчезнет, ​​вы знаете, что ваша проблема связана либо с усечкой, либо с модельной шкалой (или с обоими).