Game Dev – 참조를 이용한 Voxel Object의 copy기능 구현

[인스턴스맵]
사용자가 임의로 편집이 가능하고 모두가 공유할 수 있는 맵에선 몬스터를 풀어둘수 없다. 수시로 변형되는 복셀 지형에 쉽게 끼일것이다. 이 상태론 원활한 전투도 수행하지 못한다.
따라서 전투전용의 인스턴스맵을 만든다. 이 타입의 맵은 복셀을 파괴할 순 있지만 복셀을 추가하지는 못한다. 또한 NPC의 이동과 밀접한 관계가 있는 바닥에 대해선 파괴도 허용하지 않는다.
여기서 말하는 인스턴스 맵은 원본이 되는 맵(이하 템플릿맵으로 부른다)의 복사본을 그때그때 만들어서 생성하는 맵이다.
예를 들어 전투필드용 맵을 하나 템플릿으로 만들어두고 전투필드용 템플릿 맵의 복사본 맵을 100개씩 만드는 식이다.

[복셀 데이터를 사용하는 경우의 문제점-해법]
맵을 100개씩 만든다면 당연히 메모리 사용량이 문제가 된다. 따라서 원본 템플릿맵의 지형지물 구조를 가능하면 최대한 그대로 사용한다. 일반적인 게임의 고정된 지형지물이라면 인스턴스맵을 몇개를 만들던 지형지물 데이터에 따른 메모리 증가는 0이다. 하지만 이 게임은 복셀 데이터를 사용하는 맵이므로 지형지물이 변하게 되고 따라서 복셀 데이터는 카피해서 실제로 들고 있어야 한다.
그렇다고 100개씩 되는 맵이 복사본의 데이터를 들고 있는 것은 메모리 낭비가 너무 심하다.
따라서 최대한 원본의 데이터를 사용하고 꼭 필요한 경우에만 복셀 데이터를 생성하도록 한다. 꼭 필요한 경우라고 하면 로켓탄이 충돌하는 등, 복셀 데이터가 변형될 경우다.

[인스턴스맵 구현수순]
1. 복셀 오브젝트의 카피 기능 구현.
2. 참조를 이용한 가짜 복셀 오브젝트의 구현.
3. 가짜 복셀 오브젝트에 진짜 복셀 오브젝트의 기능추가(렌더링, 충돌처리 등).
4. 복셀 오브젝트의 카피 기능을 이용한 복셀 오브젝트 매니저간 카피 기능(복셀 월드간 카피) 구현.
5. 서버에서 인스턴스맵 카피 기능에서 복셀 오브젝트 매니저간 카피 기능을 사용.

[1,2,3 기능 구현]
인스턴스맵에서 중요한 이슈는 다음과 같다.
– source의 데이터 참조
– copy-on-write

source의 복셀 데이터를 읽기 전용으로만 참조해서 사용한다. 지형 충돌처리와 렌더링에는 source의 읽기 전용 데이터로 충분하다. 파괴 이벤트나 편집 이벤트가 발생하여 복셀 데이터를 변형할 일이 생길 경우 copy-on-write로 처리한다.

[참조를 이용한 가짜(?) 복셀 오브젝트 생성]
서버에서 인스턴스맵을 구현하기 전에, 복셀 오브젝트 단위로 카피 기능을 만든다.
카피 모드는 두가지다.
1) 완전한 복셀 데이터를 카피
2) 원본 복셀 오브젝트의 포인터만 들고 있는 카피. 이 경우 복셀 데이터는 생성하지 않는다.

[렌더링 기능]
원본 복셀 오브젝트를 가지고 렌더링을 시도하되 위치 정보만 가짜 복셀 오브젝트의 것을 사용한다.

[충돌처리]
로켓탄 충돌이나 picking등이 해당된다.
어떻게든 가짜 복셀 오브젝트로부터 충돌처리 필요한 삼각형 데이터만 맞게 긁어오면 된다.물론 가짜 복셀 오브젝트는 삼각형 데이터 따위 가지고 있지 않다.
가짜 복셀 오브젝트와 원본 오브젝트의 위치의 offset을 구해서 속도벡터에 해당하는 ray을 이동시킨다.
이 ray로 원본으로부터 삼각형 데이터를 긁어온후 수집한 삼각형들에 대해서 offset을 빼준다. 그러면 가짜 오브젝트 기준의 충돌처리용 삼각형을 긁어온 셈이다.
이후는 기존의 충돌처리 코드를 그대로 사용한다.

이 전략으로 구현했고 잘 돌아간다.
어차피 서버에서 사용할거라서 참조로 만들어진 인스턴스 오브젝트의 경우 렌더링 기능은 필요없지만 서버에 막바로 코딩하면 디버깅이 힘들기 때문에 클라이언트에서 테스트하고 있다. 참조로 만들어진 가짜 복셀 오브젝트도 최대한 완전한 복셀 오브젝트의 기능을 갖도록 하려 한다.

영상에선 CTRL+C로 COPY, CTRL+V로 다른 위치에 복셀 오브젝트를 paste한다. 클라이언트에서 copy & paste를 지원할 생각은 없고 잘 작동하는지 테스트하기 위해서 이런식으로 구현했다.
여기서 paste할때 복셀 데이터와 삼각형 충돌 데이터를 바로 만들지 않고 원본을 참조하는 가짜 복셀 오브젝트를 만든다.
렌더링 시에는 원본 오브젝트 + 좌표의 offset를 이용한다.
로켓이 충돌해서 일부 파괴되는 그 순간에 복셀 데이터를 생성하고 원본과의 링크를 끊는다.

복셀 처리 코드가 꽤 복잡해서 가능할까 싶었는데 하다보니 되긴 된다. 어떻게 해야할지 가닥은 잡았다.


답글 남기기

아래 항목을 채우거나 오른쪽 아이콘 중 하나를 클릭하여 로그 인 하세요:

WordPress.com 로고

WordPress.com의 계정을 사용하여 댓글을 남깁니다. 로그아웃 /  변경 )

Google+ photo

Google+의 계정을 사용하여 댓글을 남깁니다. 로그아웃 /  변경 )

Twitter 사진

Twitter의 계정을 사용하여 댓글을 남깁니다. 로그아웃 /  변경 )

Facebook 사진

Facebook의 계정을 사용하여 댓글을 남깁니다. 로그아웃 /  변경 )

%s에 연결하는 중