본문 바로가기
기타/3D 메쉬 데이터

[rendering]depthmap & focal, position, viewup

by 혜 림 2022. 2. 8.

 저번 시간에 불러왔던 teapot을 데려오자. 이번엔 반만 있는 애가 아니고 완전한 teapot이다. 

 

 

그냥 렌더링 하면 이렇게 생겼다. 

3D 물체는 3D로 보는게 맞지만, 공유하기에는 불편하다. 마우스로 빙글빙글 회전시킬 수 있지만 그걸 이런 텍스트로 공유하기는 어렵지 않은가? 그래서 이렇게 3D로 그리지 않고 2D로 그리면서, 입체감을 살릴 수도 있다. 렌더링의 기법 중 하나가 바로 그 depth map이다. 

 

 

 

 위 teapot의 depthmap이다. 

 카메라 렌즈로부터 빛을 쏘아서 반사되는 길이? 를 가지고 2D 이미지에 깊이를 반영한다.  

 

    filter = vtk.vtkWindowToImageFilter()
    filter.SetInput(renWin)
    filter.SetScale(1)
    filter.SetInputBufferTypeToZBuffer()
    filter.Update()


    scale = vtk.vtkImageShiftScale()
    scale.SetOutputScalarTypeToUnsignedChar()
    scale.SetInputConnection(filter.GetOutputPort())
    scale.SetShift(0)
    scale.SetScale(-255)
    scale.Update()


    writer = vtk.vtkJPEGWriter()
    writer.SetFileName('tempmap.jpeg')
    writer.SetInputConnection(scale.GetOutputPort())
    writer.Update()
    writer.Write()

 

zbuffer에 대해서 저번 포스팅에서 올렸으니 넘어가고, 그 다음

imageshiftscale은 왜 필요하냐? zbuffer 한 이미지를 저장하려면 point 위치의 부호가 없어야한다. 하지만 zbuffer를 거칠때 xyz 축을 기준으로 하기 때문에 여전히 부호로 point의 위치를 표현한다. 따라서 위와 같이 setoutputscalartypetounsignedchar() 를 이용해서 point 위치를 부호없이 표현한다. 

그다음은 뭐 jpeg 저장이다. 사실 png 저장도 똑같다. 

 


 

하지만 이렇게 옆에서 depthmap 을 찍지 않고 정면에서 찍고 싶다면? 윗면에서 찍고 싶다면? 밑면에서 찍고 싶다면?

 

그때는 크게 2가지의 방법이 있다. 

 

 (1) 물체 자체를 회전시키거나

 (2) 카메라의 위치를 회전시키거나

 

여기서 물체 자체를 회전시키는 건 쉽다. 

참 쉽쥬~

actor.Rotatex(90)

 

하지만 카메라를 회전시키려면 여러가지 생각해주어야 한다. 

 

 (1) focal point

 (2) position

 (3) viewup

 

 아래 그림을 보면 쉽다. 

본문에서 자그마치 3번이나 나오는 이 그림

focal point 는 초점이다. 우리가 보려고 하는 물체의 center를 대충 넣으면 될 것이다. 

 

 

    centerOfMassFilter = vtk.vtkCenterOfMass()
    centerOfMassFilter.SetInputData(polydata)
    centerOfMassFilter.SetUseScalarsAsWeights(False)
    centerOfMassFilter.Update()
    center = centerOfMassFilter.GetCenter()

 

센터는 대충 이렇게 구한다. 

 

ren.GetActiveCamera().SetFocalPoint(center)

 

 

 초점을 polydata의 center로 맞추면 이렇게 된다. 여기가 어디지? teapot 내부다! 

 우리 머리 위에는 지금 teapot의 뚜껑이 달려 있다. 

 

position 은 카메라의 위치다. 우리가 보려고 하는 측면에 카메라를 넣으면 된다. 

오우 이걸 하면서 내가 깨달은 건, xyz 축이 우리가 통상 좌표계에 그리는 xyz 축이랑 다를 수도 있다는 것이다.

언제나 확인확인 하는 습관쓰

 마지막 축만 바꾸어 보면 이렇게 바뀐다. 여전히 초점은 teapot 내부의 center. 

ren.GetActiveCamera().SetPosition(0,0,200)

 z축 값을 바꾸어주면 teapot이랑 가까워졌다가 멀어졌다가 한다. 

 

 

 

ren.GetActiveCamera().SetPosition(0,200,0)

 

y축을 바꿔주면 물체 위로 올라간다. 

 

그런데 여기까지 해놓고 한번 depth map이 어떻게 저장되고 있는지 확인해보자. 

 

내 머릿속처럼 완전히 black out

 

어라리요 이러면 안 되는데...

 

이게 이렇게 된 이유는 우리가 viewup을 보지 않았기 때문이다!

 

viewup이 바뀌지 않고 카메라만 사물의 위로 올라갔기 때문에 카메라는 사물의 위를 찍는다. 

 

즉 카메라가 사물 위로 올라갔기 때문에 카메라의 렌즈도 회전을 해서 아래를 봐야 한다는 거다. 

 

예를 들어 내가 담장 너머의 입실렌티를 보고 싶어서 담정 너머로 얼굴을 내밀었다면 고개도 숙여야 입실렌티가 보인다는 말이다. 

 

벼도 익을수록 고개를 숙인다고.. 우리도 한 번 고개를 숙여보자

 

ren.GetActiveCamera().SetViewUp(0,0,1)

 

다만 한가지 주의할 점은 viewup은 카메라가 보는 방향과 수직이라는 점이다. 헷갈리면 위 사진을 또 참고해라. 

 

 

위 사진에서도 보면 viewup은 위쪽 화살표인데 카메라 렌즈는 옆 화살표다. 

그래서 카메라 렌즈를 아래로 향하게 하려면 viewup을 옆 화살표로 바꿔야 한다. 그러면 카메라 렌즈가 아래 화살표로 바뀐다. 

 

rendering은 문제가 없다. 우리의 직관과 맞게 위에서 잘 보여준다.

 

 

 

이렇게 해도 사실 여전히... depthmap에서는.... 

 

내 머릿속처럼 완전히 black out

그 이유는 cliprange 때문..................

 

 

 

또 이 그림을 참고하자 

보면 fron clipping plane과 back clipping plane이 있다. 각각 near, far 라고도 부른다. 

 

원래 camera를 수정하지 않으면 이 near와 far가 알아서 설정돼서 물체를 잘 잡는다. 

그러나 우리처럼 camera를 바꾸어버리면 이 near와 far도 초기화되기 때문에 설정을 해주어야 한다. 

 

 예컨대 카메라로 무한정 세계너머 우주너머를 보라고 할 수 없으니 range를 지정해주어야 한다는 것이다. 

 

ren.GetActiveCamera().SetClippingRange(-1,7)

 

저 range는 어떻게 해야 제대로 잡을 수 있을지 잘 모르겠다. 그때마다 나는 노가다로 한다. 

 

 

이제서야 depthmap이 찍히는 걸 확인할 수 있다...

그런데 왜 teapot 뚜껑의 꼭지는 안 보이는지 모르겠다......??? 

 

 

 

댓글