2015-01-22 3 views
-1

죄송합니다. 이전에 명확하게 질문하지 않았으므로 아래와 같이 변경되었습니다. 솔루션은 투영 매트릭스를 변경하는 것입니다. 올바르게 수행하는 방법을 알아보기 위해 조사를 해봅시다.opengl : 원근법 모드에서 클리핑하지 않습니까?

내 시나리오는 다음과 같습니다. ===> 이제 관점 모드를 사용하는 windows7 아래에 3D 상자를 만들었습니다. 사용자 관점에서 볼 때이 상자를 이동 (회전/변환) 할 때 상자가 창 밖으로 나왔을 때/(부분적으로 숨김)해야합니다. 맞습니다. 그러나 상자가 창 안쪽으로 이동하면 상자는 항상 완전히 표시되어야합니다 (잘리지 않습니다!), 맞습니까? 하지만 내 문제는 때로는 사용자가 창 안쪽으로 상자를 이동하면이 상자의 일부가 잘리는 것을 보게되는 것입니다 (예 :이 상자의 한 정점이 잘립니다). 얼마나 많은 사용자가이 상자를 이동할 수 있는지는 제한이 없습니다.

내 이해 : ===> 사용자가 상자를 이동할 때이 상자는 절두체가 아니므로 잘립니다. 이 경우 필자의 코드는 절두체를 즉석에서 조정 한 다음 (투영 매트 트릭스가 변경됨) 카메라를 즉시 조정해야합니다 (어쩌면 near-far 평면도 조정할 수 있습니다).

내 질문에 : ===> 이런 종류의 클리핑을 피하기 위해 인기있는 기술은 무엇입니까? 사용자가 상자를 움직일 때 갑자기 상자의 위치가 다른 위치로 이동합니다 (갑자기 커서가 크게 변하기 때문에 갑자기 상자가 움직이지 않는다는 느낌). 이것이 아주 고전적인 문제라고 생각합니다. 완벽한 해결책이 있어야합니다. 모든 코드/참조를 부탁드립니다!

문제를 표시하기 위해 그림을 첨부했습니다. enter image description here

감사합니다!

+0

질문이 이해가 가지 않습니다. 어떤 물건을 그려서는 안되는지를 결정하기 위해 어떤 종류의자가 제작 절두체 컬링 (self-made frustum culling)을 사용합니까? 그렇다면, 왜 회전/번역을하지 않은 이유는 무엇입니까? – HolyBlackCat

+0

투영 행렬을 만드는 방법에 대한 코드를 게시해야합니다. 치수의 가능성을 이해한다면 가까운/먼 거리 또는 카메라 조리개의 관점에서 영사 매트릭스를 정의하는 데 아무런 문제가 없어야합니다. 즉석에서 재정의하려는 투영 행렬 (뷰 행렬이 아닙니다)입니다. – jwlaughton

+0

도움이된다면 View 및 Projection 행렬 계산 방법을 보여주는 Objective C 코드를 게시했습니다. 이 계산은 내가 resizeGL이라고 부르는 메소드에서 즉시 수행됩니다. 클리핑이 투영 행렬에서 수행되는 것을 볼 수 있습니다. – jwlaughton

답변

-3

이 코드는 모든 다시 그리기 전에 호출됩니다. 어떻게 회전/변환 (timer 또는 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); 

우리는 카메라 (눈) 위치 및보기 방향 만 정의하는보기 매트릭스를 볼 수 있습니다. 아직 클리핑이 없습니다. 그러나 카메라 위치는 객체에 너무 가까워지면 니어 컷오프 평면을 설정하는 방법이 제한 될 것입니다. 나는 카메라를 공정하게 되돌려 놓지 않을 이유가 없다고 생각한다.

// ********************************************** 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과 같은 것을 사용하여 프로젝션 매트릭스를 만드는 경우 카메라 조리개에서 왼쪽 및 오른쪽 자르기 평면을 계산하는 것이 좋습니다. 이렇게하면 사용자가 좋아하는대로 확대하거나 축소 할 수 있도록 카메라 조리개를 변경하여 줌 효과를 만들 수 있습니다 (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; 
} 
+0

이것은 실제로 질문에 대답하지 않습니다. –

+0

@NoahWitherspoon 질문이 명확하지 않았기 때문일 수 있습니다. 당신이 준 도움에 감사드립니다. – jwlaughton

+0

질문의 종류가 불분명하지만, 코드에 어떤 세부 사항도 포함되어 있지 않은 뷰 절두체의 클리핑에 대해 명확하게 묻습니다. 거기에 대한 아이디어에 대한 설명은 이것이 가치있는 대답이 될 것입니다. –

0

의심 것이다 당신의 절두체가 너무 좁습니다. 그래서, 당신이 그것의 객체 부분을 회전시킬 때 볼 수있는 영역 밖으로 이동하고 있습니다. 실험으로 당신의 원뿔 각을 증가시키고 원거리 값을 1000 또는 10000으로 증가시키고 카메라를 중앙에서 더 멀리 뒤로 이동 시키십시오 (z-면에서 더 높은 음의 값). 이것은 당신의 물체가 들어 맞아야하는 매우 큰 절두체를 생성합니다. 프로젝트를 실행하고 회전합니다. 클리핑 효과가 사라지면 절두체 또는 모형 축척 (또는 둘 다) 문제가 있음을 알 수 있습니다.

관련 문제