2D 물체 겹침 표현하기

Programming/Graphics 2012. 8. 7. 23:13 by 빠재


오늘은 좌표계 이야기를 좀 해보겠습니다.





갑자기 뜬금없이 저렇게 스크린에 겹친 형태의 사각형을 그리고 싶어졌습니다.


아니면 난이도를 조금 높여서 여자친구에게 프로포즈하기 위해 차 트렁크에서 날려버린 수십개의 풍선들이 겹친 모양을 벽에 수채화로 그리고 싶어졌다고 합시다.


(물론 '비현실적인' 일이니까 가정을 하는 겁니다)


어떻게 그릴 건가요?


종이나 그림판 프로그램이었다면 간단할 겁니다. 위의 그림이라면 먼저 갈색 사각형을 먼저 그린 다음에 파란색 사각형을 그리면 되니까요.





그렇다면 3D로 구현한 2D에서도 그림판처럼 같은 수법이 먹힐까요?


대답은 '아니오' 입니다.


이유도 간단합니다. 비슷한 위치에 있는 물체를 우리가 맘대로 그리는 순서를 정하지 않기 때문입니다.





사실 OpenGL이건 jPCT건, D3D건 같은 위치에 똑같은 모양의 도형이 몇 개 놓여져 있다면 어느 도형이 보이게 될 지는 엔진 마음입니다. 


프로그래머가 하는 일은 단지 물체를 제 위치에 가져다 놓는 것뿐이죠.


그렇다면 엔진으로 구현한 2D상에서 물체를 겹쳐 보이게 하는건 불가능한 일이겠군요? 에, 그건 또 아닙니다.




약간의 트릭을 쓰면 물체의 겹침을 표현할 수가 있습니다. 


바로 Z값을 이용하는 방법입니다.





우리가 만드는 2D에서는 시청자가 마치 3차원 공간이 아닌 x-y평면을 보고 있는 듯한 느낌을 주게 합니다.


Z좌표에 대한 생각을 생략했기 때문에 원근감을 느낄 수 없는 것이지요.


그렇게 보는 사람은 모르지만 내부에서 Z값을 변경해서 가깝고 멀고를 조절한다면 엔진이 각 물체를 그리는 순서를 바꿀 수 있습니다.


아까 맨 처음에 보였던 겹친 사각형 두 개를 실제로 만들면 이렇게 할 수 있습니다.





약간 카메라를 틀은 것뿐인데 이번엔 파란 사각형이 좀 더 앞으로 나온 것 같이 보입니다.








그럼 이걸로 끝일까요?


그랬으면 세상살기 참 편했을 겁니다 ㅠㅠ





만약에 저 두 사각형이 같은 크기였다 할지라도, Z값이 조정된다면 우리가 보는 두 사각형의 크기는 서로 달라집니다.


마치 저멀리 칠판에 놓여있는 칠판지우개보다 선생님이 던져서 내눈앞으로 오는 칠판지우개가 더 커보이는 것처럼요.


따라서 두 사각형의 크기를 똑같이 보이게 하기 위해서 약간의 수학이 필요합니다.




이해를 쉽게 하기 위해 아래 그림이 첨부됩니다.




그림이 이해가 안되더라도 설명은 합니다 -_-


실제 Object는 스크린과 카메라 중간정도에 위치해 있습니다.


하지만 우리가 느끼는 크기는 스크린에 나타는 Projection만큼입니다.


delta는 우리가 조정한 Z값이라고 보면 됩니다.


우리가 delta만큼 Z값을 조정했다면 실제 객체는 위치뿐만 아니라 크기도 같이 조절해 주어야 합니다.




크기조절의 비율은 간단한 비례식에 의해 (length-delta)/length가 나옵니다.




위치의 조정 역시 비례식을 활용하는데, Object의 중점은 Projection의 중점과 cam을 잇는 직선상에 있다는 점을 이용하면 생각보다는 간단하게 이동할 수 있습니다.




제 의사전달 실력이 여기서 드러나는군요 .. 그냥 코드로 보여드리겠습니다.


	//

	// z값이 변할 때 그에 맞게 크기와 위치를 조정한다
	public void setDepth(float depth)
	{
		float delta = depth - this.depth;
		
		// move object
		// depth가 Z좌표임
		SimpleVector curPosition = m_polygon.getTransformedCenter();
		SimpleVector toCam = MainRenderer.getCamera().getPosition().calcSub(curPosition);
		float a = MainRenderer.getCamera().getPosition().z - this.depth;
		toCam.scalarMul(delta/a);
		m_polygon.translate(toCam);
		System.out.println("translate to " + toCam);
		
		// scale
		m_polygon.scale((a-delta)/a);
		
		this.depth = depth;
	}






아무튼 이점을 활용한다면 어느 깊이에서건 크기가 달라지지 않는 정교한 렌더링이 가능해집니다.

'Programming > Graphics' 카테고리의 다른 글

[OpenGL] 수직동기화 끄기  (0) 2014.02.01
Viewport 구현하기  (0) 2012.08.20
jPCT로 2D 렌더링을 구현해보자 - line, fillRect  (0) 2012.07.28
jPCT-AE(1) - main activity부터!  (2) 2012.06.30
Java를 위한 3D 엔진, jPCT  (2) 2012.06.28
Nav