Xfiles

GamePrograming : 2007. 4. 19. 10:33
반응형

XFiles

실제 코딩하여서 D3DXCreate* 계열의 함수를 통해 구체나 원통 간단한 물체를 만들수있지만, 복잡한 물체를 만든다고 하면 상당히 지루하고 소모적인 작업이 된다.

이런 귀찬은 작업을 도와주기 위하여 3D모델러라 불리는 특수한 프로그램등이 개발되었다.

이런 작업툴들로 메쉬 데이터를 만들고 파일로 저장할 수 있으며, XFile포멧이라 불리는 특수한 메쉬 파일 포멧으로 추출할수 있다.

XFile이 가진 장점은 DirectX가 이 파일 포멧을 정의하고 있어서 별다른 준비과정 없이, 이 파일을 D3DX라이브러리에서 이용이 가능하다는 점이다.

- XFile 읽어들이는 함수는 D3DXLoadMeshFromX 함수를 이용하며 내용은 다음과 같다

HRESULT D3DXLoadMeshFromX (
LPCSTR pFilename,
DWORD Options,
LPDIRECT3DDEVICE9 pDevice,
LPD3DXBUFFER *ppAdjacency,
LPD3DXBUFFER *ppMaterials,
LPD3DXBUFFER *ppEffectInstances,
PDWORD pNumMaterials,
LPD3DXMESH *ppMesh
);

pFilename - 읽어들이고자 하는 XFile의 파일명
Options - 메쉬를 만드는데 이용될 하나 이상의 플래그, 여러가지가 있으나 자주 이용되는것은 다음과 같다
D3DXMESH_32BIT - 32비트 인덱스를 이용하게 된다.
D3DXMESH_MANAGED - 메모리 풀 내에 보관된다.
D3DXMESH_WRITEONLY - 메쉬데이터는 쓰기만 허용된다.
D3DXMESH_DYNAMIC - 메쉬데이터가 동적으로 만들어진다.
pDevice - 메쉬와 연계될 장치
ppAdjacency - 메쉬 근접 정보를 위한 DWORD배열을 포함하는 버퍼리턴
ppMaterials - 메쉬 재질 정보를 위한 D3DXMATERIAL 구조체를 리턴
ppEffectInstances - D3DXEFFECTINSTANCE 구조체 배열을 포함하는 ID3DXBuffer리턴,
pNumMaterials - 매쉬의 재질수를 리턴(ppMaterials로 받은 D3DXMATERIAL 배열 내 요소의수)
ppMesh - XFile기하정보로 채워진 ID3DXMesh 객체를 리턴

-버텍스 법선 생성

XFile에 버텍스 법선 데이터가 전혀 포함되지 않은 경우도 있을 수 있다. 만약 법선 데이터가 없다면 조명을 위해 직접 버텍스 법선 데이터를 계산해 내야 한다.
메쉬의 버텍스 법선은 D3DXComputeNormals 함수를 통해 만들어 낼수 있다.

HRESULT D3DXComputeNormals (
LPD3DXBASEMESH pMesh,
const DWORD *pAdjacency
};

pMesh - 법선을 계산하려는 메쉬
pAdjacency - 인접 정보

*이때 pMesh로 전달할 메쉬객체는 D3DFVF_NORMAL 플래그를 가지고 있어야 한다. 이 플래그가 없다면 D3DXComputeNormals를 이용하기 전에 먼저 메쉬를 복제하고 이때 D3DFVF_NORMAL 플래그를 넣어준다.

// 메쉬가 버텍스 포멧으로 D3DFVF_NORMAL을 가지고 있는가?
if ( !(pMesh->GetFVF() & D3DFVF_NORMAL) )
{
          //가지고 있지 않다면 메쉬를 복제하고 D3DFVF_NORMAL을 추가한다.
          ID3DXMesh* pTempMesh = 0;
          pMesh->CloneMeshFVF(
          D3DXMESH_MANAGED,
          pMesh->GetFVF() | D3DFVF_NORMAL, //이곳에 추가
          Device,&pTemeMesh );
          // 법선을 계산한다.
          D3DXComputeNormals( pTempMesh, 0 );
          pMesh->Release(); // 기존메쉬를 제거한다
          pMesh = pTempMesh; // 기존메쉬를 법선이 계산된 메쉬로 지정한다.
}

프로그레시브 메쉬
- 프로그레시브 메쉬란 메쉬를 여러 조건에 따라 단순화하거나 단순화한 과정을 되돌리는것을 의미한다.
- 작동원리는 텍스쳐에서 밉맵을 이용하는것과 유사하다.
- 텍스쳐이용시 멀리있는 물체에 고해상도에 텍스쳐를 이용하는것은 낭비인것과 같이 멀리있는 메쉬는 가까이있는 메쉬처럼 복잡한 표현이 필요가 없기 때문이다.
- 프로그레시브 메쉬는 원본보다 세밀해질수 없다.
- 프로그레시브 메쉬는 D3DXGeneratePMesh 함수를 이용하며 내용은 다음과 같다.

HRESULT D3DXGeneratePMESH (
          LPD3DXMESH pMesh,
          CONST DWORD *pAdjacency,
          CONST LPD3DXATTRIBUTEWEIGHTS pVertexAttributeWeights,
          CONST FLOAT *pVertexWeights,
          DWORD MinValue,
          DWORD Options,
          LPD3DXPMESH *ppMesh
);


pMesh - 프로그레시브 메쉬를 생성하고자 하는 원본 메쉬
pAdjacency - pMesh의 인접 정보
pVertexAttributeWeights - pMesh내의 i번째 버텍스의 속성영향을 지정, 속성영향은 단순화 과정중 버텍스가 제거될 확률을 결정한다.
pVertexWeights - pMesh내의 i번째버텍스의 개수를 가지는 float배열, 영향력이 높을수록 단순화 과정중 제거될 확률이 줄어든다.
MinValue - 단순화의 결과로 얻어질 최소한의 면이나 버텍스, 면인지 버텍스인지는 Options플래그에 의해서 판단
Options - MinValue의 값이 면인지 버텍스인지 판별
D3DXMESHSIMP_VERTEX - MinValue값이 버텍스
D3DXMESHSIMP_FACE - MinValue값이 면
ppMesh - 프로그레시브가 생성된 메쉬리턴
ID3DXMesh* SourceMesh = 0; // 처음 파일을 읽어들일 메쉬
ID3DXPMesh* PMesh = 0; // 프로그레시브 메쉬

hr = D3DXGeneratePMesh(
SourceMesh,
(DWORD*)adjBuffer->GetBufferPointer(), // 근접정보
0, // 기본 버텍스 속성 영향력
0, // 기본 버텍스 영향력
1, // 최대한 단순화한다.
D3DXMESHSIMP_FACE, // 면의 수로 단순화한다.
&PMesh);

d3d::Release<ID3DXMesh*>(SourceMesh); // 원본메쉬제거
d3d::Release<ID3DXBuffer*>(adjBuffer); // 근접정보 제거
//이때 이상태로 그대로 렌더링을 하면 가장 낮은 해상도로 렌더링이 된다.
//처음에 최대 해상도로 메쉬를 렌더링하려면 다음과 같은 방법으로 최대 면수를 지정해준다.
DWORD maxFaces = PMesh->GetMaxFaces(); // PMesh의 최대 면수를 가져온다.
PMesh->SetNumFaces(maxFaces); // pMesh의 면수를 최대면수로 지정.
// 여기서 A키가 눌렸으면 면을 늘리고 S키가 눌렸으면 면을 줄이는 작업을한다.
// PMesh의 현재 면 수를 구한다.
int numFaces = PMesh->GetNumFaces();
// A키가 눌렸을때 면을 추가한다. 지정된 값을 넘겼을경우
// SetNumFaces()는 자동으로 최대 값으로 고정시킨다.
if ( ::GetAsyncKeyState('A') & 0x8000f )
{
          // ID3DXPMesh 인터페이스의 내부적 구현의 특성 때문에 하나의 면을
          // 더하는 것으로는 메쉬 내의 면의 수가 변하지 않는 경우가 있다.
          // 즉, 면의 수를 확실하게 늘리기 위해서는 두 개의 면을 한 번에 추가해야 할 수도 있다.
          PMesh->SetNumFaces(numFaces + 1);
          if(PMesh->GetNumFaces() == numFaces)
          pMesh->SetNumFaces(numFaces+2);
}
// S키가 눌렸을때 면을 감소시킨다. 지정된 값이 경계보다 작은 경우
// SetNumFaces()는 자동으로 최소 값으로 고정시킨다.
if( ::GetAsuncKeyState('S') & 0x8000f )
          pMesh->SetNumFaces(numFaces - 1);
          //프로그레시브 메쉬를 렌더링할때는 기존의 메쉬를 렌더링 할때와 동일하다.

- X 파일 포맷
Direct3D의 X 파일 포맷은 처음에 Direct3D 유지 모드(retained mode)에서 사용하기 위해 개발되었고, DirectX 6에서 즉시 모드(immediate mode)에서 사용할 수 있도록 확장되었습니다. X 파일이 앞서 이야기했던 문제들을 어떤 식으로 해결하는지 한번 살펴보도록 하겠습니다.

* 사용자 정의 데이터 형 - X 파일은 사용자에 의해 정의된 템플릿에 의해 동작합니다. 템플릿은 데이터 개체가 어떻게 저장되어야 하는지를 정의합니다. 흔히 사용되는 데이터 형을 위해 미리 정의해 놓은 템플릿도 있는데, d3dfile.cpp 와 rmxftmpl.x 속에 들어있는 헤더 rmxftmpl.h에 선언되어 있습니다. 또한 이를 확인할 수 있는 표시(identification signature)는 헤더 rmxfguid.h에 들어있습니다. 이 파일도 d3dfile.cpp에 포함됩니다.

* 계층적 관계 - 템플릿이 허용하는 데이터 타입들을 선택적 멤버(optional member)라고 하는데, 이런 선택적 멤버들이 데이터 개체의 자식 멤버로 저장됩니다. 이런 자식 멤버들은 다른 데이터 개체일 수도 있고, 다른 개체의 참조(reference)일 수도 있고, 이진(binary) 데이터일 수도 있습니다.

헤더(Header)
이른바 매직 넘버라고 불리는 4바이트 값 xof가 맨 앞에 옵니다. 버전은 03.03이고, 파일 포맷은 txt이면 텍스트 파일, bin이면 바이너리 파일입니다.

추가로, 전통적인 Direct3D 유지 모드에서 지원되는 X 파일에는 Header라고 불리는 템플릿을 사용합니다. 이 템플릿 역시 다른 템플릿과 마찬가지로 rmxftmpl.x 파일에서 찾아볼 수 있습니다.

또 다른 파일 형식은 tzip과 bzip입니다. 각각 MSZip으로 압축된 텍스트와 바이너리 파일을 의미합니다. 그 다음으로, 부동 소수점 데이터 타입은 0064 대신에 0032를 사용합니다.

예시)
xof 0302txt 0064

템플릿(Template)

템플릿은 네 부분으로 되어 있습니다. 템플릿 이름이 먼저 나오는데 이름에는 문자, 숫자 밑줄, 문자를 사용할 수 있는데 숫자가 먼저 나오면 안됩니다. 두번째 부분은 UUID(universally unique identifier), 세 번째 부분은 구성 멤버들의 데이터 타입들이 옵니다. 네 번째 부분은 제한 정도를 표시하는데, 템플릿이 열려있거나(open) 닫혀있거나(closed) 제한되어 있음(restricted)을 표시합니다.

template <template-name> {
          <UUID>
          <member 1>;
          ...
          <member n>;
          [restrictions]
}

예시)
template Mesh {
          <3D82AB44-62DA-11cf-AB39-0020AF71E433>
          DWORD nVertices;
          array Vector vertices[nVertices];
          DWORD nFaces;
          array MeshFace faces[nFaces];
          [ ... ] // An open template
}

template Vector {
          <3D82AB5E-62DA-11cf-AB39-0020AF71E433>
          FLOAT x;
          FLOAT y;
          FLOAT z;
} // A closed template

template FileSystem {
          <UUID>
          STRING name;
          [ Directory <UUID>, File <UUID> ] // A restricted template
}

열려 있는 템플릿은 데이터 타입을 더 받아들일 수 있고, 닫혀 있는 템플릿은 그렇지 못하며, 제한 되어 있는 템플릿은 지정된 데이터 타입만 더 들어올 수 있습니다.

DirectX 파일 템플릿(File Templates)
다음과 같은 템플릿들을 Direct3D 유지 모드(retained mode)에서 사용할 수 있습니다.
자세한 내용은 http://local.wasp.uwa.edu.au/~pbourke/dataformats/directx/#xfilefrm_Template_form 를 참고하세요.

Template Name: Header
Template Name: Vector
Template Name: Coords2d
Template Name: Quaternion
Template Name: Matrix4x4
Template Name: ColorRGBA
Template Name: ColorRGB
Template Name: Indexed Color
Template Name: Boolean
Template Name: Boolean2d
Template Name: Material
Template Name: TextureFilename
Template Name: MeshFace
Template Name: MeshFaceWraps
Template Name: MeshTextureCoords
Template Name: MeshNormals
Template Name: MeshVertexColors
Template Name: MeshMaterialList
Template Name: Mesh
Template Name: FrameTransformMatrix
Template Name: Frame
Template Name: FloatKeys
Template Name: TimedFloatKeys
Template Name: AnimationKey
Template Name: AnimationOptions
Template Name: Animation
Template Name: AnimationSet

X 파일 확장하기.

X 파일의 뒤에 숨겨진 가장 놀라운 가능 중 하나가 확장성입니다. 템플릿들이 정의된 rmxftmpl.x 파일을 생각해 보십시오. 여러분은 직접 만든 템플릿을 추가하여 여러분만의 X 파일 포맷을 만들어 낼 수 있습니다. 예를 들면, 모든 텍스처링 기능을 템플릿으로 만들어 셰이더 개체로 구현해 넣을 수 도 있습니다. 또한, 직접 만든 여러분만의 셰이더 클래스, 충돌 체크, 물리학, 특수 애니메이션, 사운드 파일 등도 구현해 넣을 수 있습니다.

-------------------------------------------------------------------------------------------------------------------------
이 자료는 인터넷(http://www.beeswing.net/zeroboard/zboard.php?id=doc_up&page=1&sn1=&divpage=1&sn=off&ss=on&sc=on&select_arrange=hit&desc=asc&no=11)에서 찾았는데 따로 재 편집 하는 것 보다 그대로 보는 것이 좋을 것 같아서 아예 통채로 퍼왔습니다.

DirectX Graphics의 기초

~ DirectX를 이용한 게임프로그래밍 입문 ~


2.1 시작하며
최근에 컴퓨터의 보급으로 인하여 윈도 상에서 작동하는 게임이 많이 판매되고 있습니다. 또한 최근에는 기업에서 판매하는 게임 외에도 개인이 개발한 게임을 어렵지 않게 발견할 수 있게 되었습니다. 그런 가운데, 초보자에게도 간단하게 게임 프로그램을 구동시킬 수 있는 환경으로 DirectX가 주목받고 있습니다.

제 1 장에서는 3D게임 개발에 있어서 핵심이라 할 수 있는 객체의 조작에 대하여 설명하였습니다. 이번 장에서는 한걸음 나아가 게임 프로그램에 있어서 중요한 부분인 캐릭터에 텍스쳐 입히기, 문자열의 표시, 시점의 이동과 캐릭터 관리에 대하여 설명하도록 하겠습니다. 3D 슈팅게임 제작에 필요한 기술을 그림1에 나타냈습니다.

사용자 삽입 이미지

[ 그림 1. 3D 슈팅게임 제작에 필요한 기술 ]



이번 장에서는 그림1의 STEP 1에 대하여 자세히 설명하겠습니다.

2.2 텍스쳐 입히기
3D 모델에 텍스쳐를 입히는 것은 게임 전체에 깔끔하고 아름다운 색과 형태를 부여하여 게임의 즐거움을 배가시킬 뿐 아니라, 게임의 캐릭터를 결정짓는데 있어서 커다란 도움이 될 것입니다.

텍스쳐는 X파일이나 그 외 3D 객체 등, 모든 객체에 입히는 것이 가능합니다. 게임 프로그램에서 캐릭터를 표현할 경우, X파일을 사용하는 것이 일반적입니다. 그렇기 때문에 이번 절에서는 X파일에 텍스쳐를 입히는 방법에 대하여 설명하도록 하겠습니다. X파일에 텍스쳐를 입히는 개념은 그림2에 나타나 있습니다.

사용자 삽입 이미지

[ 그림 2. 텍스쳐의 개념 ]


2.2.1 X파일 읽어오기
X 파일에 텍스쳐를 입히기 위해서는 우선 X파일을 읽어올 때에 텍스쳐 정보를 얻어와야 합니다. 이번 항에서는 X파일을 읽을 때 D3DXLoadMeshFromX 함수를 사용하겠습니다. D3DXLoadMeshFromX 함수는 X파일의 구조정보 등을 D3DXMATERIAL 구조체 배열로 반환합니다. D3DXMATERIAL 구조체는 DirectX9에서 D3DMATERIAL9 구조체로 포함되어 있습니다. D3DMATERIAL9 구조체는 읽어들인 X파일의 여러가지 재질이나 텍스쳐의 정보 등을 갖고 있습니다. 재질을 예로 들면 X파일의 빛의 정도 같은 조명계산에 사용하는 파라메터가 있습니다. 개발자는 재질의 구조정보를 세밀하게 설정하여 그래픽이 풍부한 캐릭터를 만들어 낼 수 있습니다.

다음으로 X파일을 그리기 위한 텍스쳐 입히기 작업으로 텍스쳐 객체를 생성하는 것이 있습니다. DirectX9에서는 이미지 파일로부터 텍스쳐 객체를 생성하기 위한 편리한 함수가 준비되어 있습니다. 개발자는 D3DXCreateTextureFromFile 함수를 사용함으로써 간단히 텍스쳐 객체를 생성할 수 있습니다. D3DXCreateTextureFromFile 함수의 선언은 다음과 같습니다.

HRESULT D3DXCreateTextureFromFile(
   LPDIRECT3DDEVICE9 pDevice, // 디바이스 객체
   LPCTSTR pSrcFile, // 텍스쳐 이미지의 파일명
   LPDIRECT3DTEXTURE9 *ppTexutre // 텍스쳐 객체의 포인터를 저장하는 주소
   );

X파일을 읽을 때에 텍스쳐 정보를 읽는 코드는 다음과 같습니다.

코드:

BOOL CDXSimpleObject::LoadX(char* fn, LPDIRECT3DDEVICE9 pD3DDevice){    LPD3DXBUFFER pD3DBufMtr;  // D3Dbuffer 객체의 포인터  HRESULT hres;        // COM에러코드  hres = D3DXLoadMeshFromX(    fn,            // 파일명    D3DXMESH_SYSTEMMEM,    // 시스템 메모리 상에 로드    pD3DDevice,        // Direct3Ddevice 객체    NULL,    &pD3DBufMtr,      // D3DXMATERIAL 구조체 배열    NULL,    &m_dwNumMaterials,    // 재질 그룹의 개수를 얻어올 주소    &m_pMesh        // D3DXMESH 객체의 인터페이스를 얻어올 주소    );            // 메시 정보를 X파일로부터 로드      // D3DXMATERIAL 구조체 배열의 포인터를 얻어옴    D3DXMATERIAL* d3dxmatrs =     (D3DXMATERIAL*)pD3DBufMtr->GetBufferPointer();   // LPDIRECT3DTEXTURE9 타입의 배열을 할당  m_ppTextures =   (LPDIRECT3DTEXTURE9*)malloc(sizeof(LPDIRECT3DTEXTURE9) * m_dwNumMaterials);  // D3DMATERIAL9 구조체 배열을 할당  m_pMatrs = (D3DMATERIAL9*)malloc(sizeof(D3DMATERIAL9) * m_dwNumMaterials);  for (int i = 0; i < (int)m_dwNumMaterials; i++)  {    m_pMatrs[i] = d3dxmatrs[i].MatD3D; // 재질 정보를 복사    // D3DXCreateTextureFromFile 함수가 실패했을 경우    if (D3DXCreateTextureFromFile(        pD3DDevice,                 d3dxmatrs[i].pTextureFilename,         &m_ppTextures[i]         ) != S_OK ) // 텍스쳐 이미지 파일명으로부터 텍스쳐 객체를 생성      m_ppTextures[i] = NULL; // D3DXCreateTextureFromFile 함수가 실패하면 텍스쳐는 없음  }  pD3DBufMtr->Release(); // D3DXBUFFER 객체를 해제  return TRUE; // TRUE를 반환하고 종료}

2.2.2 그리기 처리
X파일은 객체를 같은 재질의 면을 기준으로 그룹화하여 관리합니다. 동일한 재질별로 그리기 처리를 하기 때문에 그리기 퍼포먼스가 향상되어 게임 전체 처리속도를 대폭 향상시킬 수 있습니다. X파일의 그리기 처리의 흐름을 그림 3에 나타내었습니다.

사용자 삽입 이미지

[ 그림 3. X파일의 그리기 처리의 흐름도 ]



같은 재질의 그룹별로 그리기를 하는 코드의 예는 다음과 같습니다.

코드:

// 같은 재질의 그룹별로 그리기for (unsigned int u = 0; u < m_dwNumMaterials; u++){  pD3DDevice->SetMaterial(&m_pMatrs[u]); // 디바이스에 재질을 설정  pD3DDevice->SetTexture(0, m_ppTextures[u]); // 디바이스에 텍스쳐를 설정  m_pMesh->DrawSubset(u); // 메시를 그림}

2.3 문자열의 표시
게임에서 제한시간이나 점수 등의 문자정보는 플레이어에게 정보를 제공하는 수단으로 반드시 필요한 것입니다. 예를 들면, 점수는 슈팅게임에서 게임의 달성도나 승패를 판단하는 기준이 됩니다. 이번 절에서는 화면에 문자열을 표시하는 방법에 대해 설명하겠습니다.

2.3.1 문자열 표시의 개요
DirectX는 DirectX8을 지나면서 크게 사양이 변경되었습니다. 문자열의 표시방법도 크게 변경된 기능 중 하나입니다. DirectX8 이전 버전에서는 GDI(Graphics Device Interface)를 사용하여 문자열을 화면에 표시했습니다. 하지만 DirectX8 이후 버전에서는 X-box와의 호환성 문제로 GDI를 사용하여 문자열을 화면에 표시하지 않게 되었습니다. 그래서 DirectX8 이후 버전에서는 DirectX 문자관련 처리용 인터페이스를 사용하여 화면에 문자열을 표시하게 됩니다.

2.3.2 논리글꼴정보의 작성
윈도에는 논리글꼴정보를 작성하기 위한 API 함수로 CreateFont 함수가 준비되어 있습니다. CreateFont 함수를 사용여 논리글꼴정보를 작성할 수 있습니다. CreateFont 함수의 선언은 다음과 같습니다.

HFONT CreateFont(
   int nHeight, // 글꼴의 높이
   int nWidth, // 글꼴의 폭
   int nEscapement, // 기울기
   int nOrientation, // 각도
   int nWeight, // 글꼴의 두께
   DWORD dwItalic, // 이탤릭
   DWORD dwUnderline, // 밑줄
   DWORD dwStrikeOut, // 삭제선
   DWORD dwCharSet, // 문자 코드세트
   DWORD dwOutputPrecision, // 출력정도
   DWORD dwClipPrecision, // 클리핑정도
   DWORD dwQuality, // 품질
   DWORD dwPitchAndFamily, // 피치
   LPCTSTR lpszFace // 글꼴명
);
논리글꼴정보를 세밀하게 설정하여 게임 화면을 더 낫게 할 수 있습니다. CreateFont 함수를 사용하여 논리글꼴정보를 작성하는 코드의 예는 다음과 같습니다.

코드:
HFONT hFont = ::CreateFont(16, 0, 0, 0, 0, 0, 0, 0,         HANGUL_CHARSET, 0, 0, 0, 0, NULL); // 논리글꼴정보를 작성
CreateFont 함수는 파라메터에 0 또는 NULL을 지정하여 기본값을 설정할 수 있습니다. 위 예에서 작성된 논리글꼴의 정보는 문자의 높이를 16포인트로 설정하고 문자 코드세트를 한글로 설정하고 있습니다. 또한 글꼴 이름 파라메터에 NULL로 설정하면, 표준 설정인 경우 굴림이 자동적으로 선택됩니다.
(원문이 일본어인 관계로 원문에는 일본어 코드셋인 SHIFTJIS_CHARSET로 설정되어 있으며 일본어 윈도에서 기본 글꼴은 MS고딕이 설정됩니다. 이에 혼란을 느낄 수가 있어서, 문자코드와 글꼴을 HANGUL_CHARSET과 굴림으로 바꿔서 번역하였습니다. : 역자주)

2.3.3 문자열 그리기
문자열을 화면에 표시하려면 논리글꼴정보를 기반으로 출력할 문자열을 작성하여 화면에 표시해야 합니다. 문자열을 화면에 표시하는 흐름도를 그림 4에 나타냈습니다.

사용자 삽입 이미지

[ 그림 4. 문자열을 화면에 표시하는 흐름도 ]



DirectX에서는 문자열을 화면에 표시하기 위해 ID3DXFont 인터페이스를 사용합니다. DirectX에는 ID3DXFont 인터페이스를 초기화하기 위한 함수로 D3DXCreateFont 함수가 준비되어 있습니다. D3DXCreateFont 함수의 선언은 다음과 같습니다.

INT DrawText(
   LPCSTR pString, // 출력할 문자열
   INT Count, // 출력할 문자열의 바이트 수
   LPRECT pRect, // 문자열을 출력할 영역
   DWORD Format, // 출력 문자열의 양식
   D3DCOLOR Color // 문자의 색
);

DrawText 메써드를 사용하여 화면에 지정한 문자열을 그리는 코드의 예는 다음과 같습니다.
코드:

pD3DXFont->Begin(); // 그리기 시작pD3DXFont->DrawText(psz, strlen(psz), &rc, DT_SINGLELINE, color); // 문자열을 출력pD3DXFont->End(); // 그리기 종료

2.4 시점
게임에 박력이나 현실감을 주어 플레이어를 게임세계에 빠져들게 하기 위해서는 효과적으로 시점을 이동시켜야 합니다. 예를 들어 3D 게임에서 시점의 변경은 게임 전체에 임장감(臨場感)을 주어, 게임 캐릭터와 플레이어가 마치 하나가 된 것 같은 효과를 줄 수 있습니다. 이번 절에서는 시점을 효과적으로 이동시키는 방법에 대해 설명하겠습니다.

2.4.1 시점의 개념
2D 그래픽을 사용한 게임에서는 시점 이동은 화면전체를 스크롤하는 것과 같습니다. 예를 들면 화면전체를 왼쪽으로 스크롤하면 시점이 오른쪽으로 평행이동하는 것을 말합니다. 3D 그래픽을 사용한 게임의 시점이동의 개념은 화면의 스크롤에 의해 시점이동을 표현하기 때문에 2D 그래픽의 시점이동의 개념과 같습니다. 예를 들면 시점을 오른쪽으로 이동시키기 위해서는 3D 공간 전체를 왼쪽으로 이동시키게 됩니다. 또한 시점을 오른쪽으로 회전시키기 위해서는 3D 공간 전체를 왼쪽으로 회전시킵니다.

2.4.2 뷰(View) 변환
시점은 3D 공간에서 위치와 방향을 갖습니다. 시점의 위치는 3D 공간 전체의 이동변환에 의해 변경됩니다. 또한 시점의 방향은 3D 공간전체의 회전변환에 의해 표현됩니다. 그 때문에, 시점을 표현하기 위해서는 회전행렬과 이동행렬을 합성한 뷰 행렬(View matrix)을 생성하는 편리한 함수로 D3DXMatrixLookAtLH가 준비되어 있습니다. D3DXMatrixLookAtLH 함수의 선언은 다음과 같습니다.

D3DXMATRIX *D3DXMatrixLookAtLH(
D3DXMATRIX *pOut, // D3DXMATRIX 구조체의 주소
CONST D3DXVECTOR3 *pEye, // 시점의 위치
CONST D3DXVECTOR3 *pAt, // 시점의 방향
CONST D3DXVECTOR3 *pUp, // 시점의 방향
);
D3DXMatrixLookAtLH 함수를 사용하면, 시점의 위치나 방향을 표현하는 뷰 행렬을 생성할 수 있습니다. 시점의 위치나 방향의 개념을 그림 5에 나타냈습니다.

사용자 삽입 이미지

[ 그림 5. 시점의 개념 ]



D3DXMatrixLookAtLH 함수를 사용하여 뷰 행렬을 생성하는 코드의 예는 다음과 같습니다.

코드:

D3DXMATRIX d3dxmatView; // 뷰 행렬을 저장할 구조체D3DXMatrixLookAtLH(  &d3dxmatView, //  D3DXMATRIX 구조체의 주소  &(D3DXVECTOR3((float)sin(vr * 0.017453f) * 20.0f, 0.0f,     (float)cos(vr * 0.017453f) * 20.0f )), // 시점의 위치  &(D3DXVECTOR3(0.0f, 0.0f, 0.0f)), // 시점의 방향  &(D3DXVECTOR3(0.0f, 1.0f, 0.0f)) // 시점의 방향); // 시점의 위치와 방향을 지정하여 뷰 행렬을 생성

2.5 캐릭터 관리
복수의 캐릭터를 동시에 다루는 것은 게임성을 높이기 위한 중요한 요소입니다. 게임에는 롤플레잉게임이나 슈팅게임 등 다양한 장르가 존재하는데, 복수의 캐릭터를 관리하는 것은 모든 게임 장르에 있어서 반드시 필요한 기술입니다. 복수의 캐릭터를 관리하는 방법에 대해 설명하겠습니다.

2.5.1 캐릭터 관리의 개념
게임성을 높이기 위해서는 복수의 캐릭터를 동시에 다룰 필요가 있습니다. 게임 프로그램에서는 플레이어가 있는 공간 상에 캐릭터를 자유로이 추가, 삭제하는 구조를 가져야 합니다. 게임 프로그램에서의 캐릭터 관리의 개념을 그림 6에 나타냈습니다.

사용자 삽입 이미지

[ 그림 6. 캐릭터 관리의 개념 ]


게임 프로그램에서는 캐릭터를 그룹화하여 관리하는 방법이 일반적입니다. 캐릭터를 그룹화하여 관리하는 방법에는 크게 두가지 장점이 있습니다. 첫 번째로는 캐릭터의 일원관리가 가능하기 때문에 등록과 삭제를 용이하게 할 수 있습니다. 두번째로는 캐릭터의 추가나 삭제 코드를 모든 캐릭터를 통해서 공통화할 수 있기 때문에 개발자는 프로그램을 간결하게 표현할 수 있습니다.

2.5.2 캐릭터의 추가와 삭제
게임 프로그램에서는 복수의 종류의 캐릭터를 관리할 경우 캐릭터의 종류별로 정보를 가져야 합니다. 예를 들어 슈팅게임의 경우, 캐릭터의 위치나 캐릭터의 이동속도 등이 있습니다. 각 캐릭터는 위치나 이동속도 등의 정보를 가짐으로써 캐릭터 1개 1개가 자유로운 움직임을 보장받게 됩니다. 게임 프로그램에서는 각각의 캐릭터에 대한 정보를 클래스가 아닌 구조체로 관리하는 것이 일반적입니다. 캐릭터를 구조체로 관리함으로써, 객체의 생성이나 소멸 등의 처리가 가벼워져 처리속도의 향상을 꾀할 수 있습니다. 캐릭터의 정보를 관리하는 구조체의 선언의 예가 다음에 있습니다.
코드:

Typedef struct _tagNODEINFO{   BOOL bActive; // 플래그   int x, y;     // 위치   int vx, vy;   // 속도} NODEINFO;

게임 프로그램에서는 복수의 구조체변수를 관리함으로써 복수의 캐릭터를 관리할 수 있습니다. 복수의 구조체변수를 관리하는 방법으로는 구조체를 리스트 구조로 관리하는 방법과 구조체를 배열로 관리하는 방법 등 2가지가 있습니다. 구조체를 리스트 구조로 관리하는 방법은 다음 리스트의 첫번째 주소를 보관하는 등 복잡한 처리를 해야합니다. 그렇기 때문에 이번 항에서는 구조체를 배열로 관리하는 방법을 사용하겠습니다. 배열로 관리하는 방법은 구조체변수의 배열 하나에 캐릭터 그룹 하나의 정보를 할당하는 것입니다. 구조체배열에 의한 캐릭터 관리의 개념을 그림 7에 나타냈습니다.

사용자 삽입 이미지

[ 그림 7. 구조체배열에 의한 캐릭터 관리의 개념 ]


구조체변수를 배열로 관리하는 방법에 대한 코드의 예는 다음과 같습니다.

코드:

NODEINFO nodes[MAX_NODES];
MAX_NODE에는 캐릭터의 최대 개수를 지정합니다. 캐릭터 관리용 배열은 문자열정수로 정의합니다.

배열의 각 엔트리는, 엔트리가 미사용인지 아니면 사용중인지의 정보를 포함하고 있습니다. NODEINFO 구조체는 엔트리가 미사용인지 사용중인지의 정보를 멤버변수 bActive에 저장해두고 있습니다. 새로운 캐릭터를 추가할 경우 미사용 엔트리를 찾아서 멤버변수 bActive를 TRUE로 설정하여 사용중이라고 알립니다. 또한 캐릭터를 제거할 경우는 멤버변수 bActive를 FALSE라고 설정하여 미사용상태로 되돌립니다. 캐릭터 추가의 개념을 그림 8에 나타냈습니다.

사용자 삽입 이미지

[ 그림 8. 캐릭터 추가의 개념 ]


캐릭터 추가는 멤버변수 bActive를 TRUE로 설정하는 것으로 나타냅니다. 캐릭터를 추가하는 코드의 예는 다음과 같습니다.

코드:

BOOL CGameObjs::Add(float x, float y, float z, float vx, float vy, float vz){  int idx;  // 배열의 전체 엔트리를 조사  for (idx = 0; idx < MAX_OBJS; idx++)  {    // 미사용상태의 엔트리인 경우    if (!m_objs[idx].bActive)    {      m_objs[idx].bActive = TRUE; // bActive 멤버를 TRUE로 설정하여 사용상태로 바꿈      m_objs[idx].m_fX  = x; // 위치의 x 좌표를 설정      m_objs[idx].m_fY  = y; // 위치의 y 좌표를 설정      m_objs[idx].m_fZ  = z; // 위치의 z 좌표를 설정      m_objs[idx].m_fVX = vx; // 속도의 x 성분을 설정      m_objs[idx].m_fVY = vy; // 속도의 y 성분을 설정      m_objs[idx].m_fVZ = vz; // 속도의 z 성분을 설정      m_objs[idx].m_fR  = 0; // 각도를 0으로 초기화      m_objs[idx].m_iParam1 = 0; // param1 멤버를 0으로 초기화      m_objs[idx].m_iKind = rand() % 3; // 랜덤하게 동작의 종류를 결정      return TRUE; // TRUE를 반환하고 종료    }  }  return FALSE;}
위 코드의 예에는 구조체배열을 처음부터 순차적으로 조사하여, 미사용상태의 배열을 검색합니다. 미사용상태의 배열을 발견한 경우 멤버변수 bActive를 TRUE로 설정하여 구조체배열을 사용중이라고 표시합니다.

2.5.3 캐릭터의 동작
제 2.5.2 항에서는 구조체배열을 이용하여 캐릭터를 그룹화하여 캐릭터를 자유로이 추가하고 삭제하는 처리에 대해 설명했습니다. 이번 항에서는 각 캐릭터에 동작을 부여하는 방법에 대해 설명하겠습니다. 캐릭터의 동작은 캐릭터의 종류에 따라 달라집니다. 예를 들면 적 캐릭터의 이동은 플레이어를 쫓아다닌다던가 플레이어로부터 도망가는 등입니다. 거기에 반해 플레이어의 캐릭터는 플레이어가 자유로이 조작할 수 있게 하기 위해 캐릭터의 동작을 설정하지 않습니다.
코드:
BOOL CGameObjs::Act(void){  int idx;  // 배열 전체의 엔트리를 조사  for (idx = 0; idx < MAX_OBJS; idx++)  {    // 엔트리가 사용중 상태인 경우    if (m_objs[idx].bActive)    {      m_objs[idx].m_fX += m_objs[idx].m_fVX; // x좌표에 속도 x성분을 더함      m_objs[idx].m_fY += m_objs[idx].m_fVY; // y좌표에 속도 y성분을 더함      m_objs[idx].m_fZ += m_objs[idx].m_fVZ; // z좌표에 속도 z성분을 더함      // 캐릭터의 종류별로 동작      Behave(&m_objs[idx]);      // 캐릭터의 높이가 -20 이하가 된 경우      if (m_objs[idx].m_fY < -20.0f)        Delete(&m_objs[idx]); // 캐릭터를 삭제              m_objs[idx].m_fR += 0.1f; // 캐릭터의 각도에 0.1을 추가    }  }  return TRUE;}
위 코드의 예에서는 각 캐릭터를 바운드시키는 처리를 구현하였습니다. 캐릭터는 화면상에 등장하고 떨어지기 시작합니다. 그 후 캐릭터는 한 번 바운드하고 나서 화면 아래로 떨어집니다. 화면상에 표시되지 않는 위치까지 떨어지게 되면 캐릭터는 자기자신을 삭제시킵니다.

2.5.4 캐릭터 동작의 확장
게임에서는 각 캐릭터의 종류에 대응하여 동작이나 상태를 다르게 나타내야 합니다. 예를 들어 슈팅게임에서는 보스캐릭터와 졸병 캐릭터의 동작을 제각각 다르게 나타내야 합니다. 캐릭터의 종류에 따라 서로 다른 동작을 구현하는 방법은 두 가지가 있습니다. 첫번째는 각기 다른 동작을 하는 캐릭터의 종류별로 그룹을 만드는 것입니다. 하지만 이 방법은 프로그램을 복잡하게 만들고 처리가 장황하게 되어버리기 때문에 효과적이지 못합니다. 두번째로 각 캐릭터가 갖고 있는 정보에 동작의 종류를 나타내는 데이터를 추가하는 방법입니다. 전자에 비해 후자를 사용하는 것이 이 캐릭터의 호출을 일원관리할 수 있게 되고, 더욱 고도의 캐릭터 관리를 구현할 수 있게 됩니다. 각 캐릭터의 종류에 대응하여 동작이나 상태를 다르게 하는 코드의 예가 다음에 있습니다.

코드:
void CGameObjs::Behave(GOBJ* pObj){  // 캐릭터 종류별로 동작을 다르게 함  switch(pObj->m_iKind)  {  case 0:    pObj->m_fVY -= 0.02f; // 속도의 y성분에서 0.02를 뺌    break;  case 1:    pObj->m_fVY -= 0.013f; // 속도의 y성분에서 0.013을 뺌    break;  case 2:    pObj->m_fVY -= 0.03f; // 속도의 y성분에서 0.03을 뺌    break;  }    // 캐릭터 종류별로 동작을 다르게 함  switch(pObj->m_iKind)  {  case 0:  case 1:    if (pObj->m_fY < -8.0f && pObj->m_fVY<0 && pObj->m_iParam1 == 0)    {      pObj->m_fY = -8.0f; // 위치를 보정      pObj->m_fVY *= -0.4f; // 속도의 y성분에 -0.4을 곱함 (예전보다 늦게 반대방향으로 되돌아 옴)      pObj->m_iParam1 = 1; // m_iParam1 멤버를 1로 세팅하여, 한 번 바운드 했다는 것을 나타냄    }    break;  case 2:    if (pObj->m_fY < -8.0f && pObj->m_fVY<0 && pObj->m_iParam1 < 2)    {      pObj->m_fY = -8.0f; // 위치를 보정      pObj->m_fVY *= -0.7f; // 속도의 y성분에 -0.7을 곱함 (예전보다 늦게 반대방향으로 되돌아 옴)      pObj->m_iParam1++; // m_iParam1 멤버를 증가시켜, 바운드했던 회수를 기록)    }    break;  }}
위 코드의 예는 이번 장의 샘플 프로그램의 일부분입니다. 위 코드의 예에서는 GOBJ 구조체의 멤버변수 kind의 값에 따라서 객체의 낙하속도, 바운드의 높이나 바운드의 회수를 다르게 하고 있습니다. 샘플 프로그램을 실행시킨 예가 그림 9에 있습니다.

사용자 삽입 이미지

[ 그림 9. 샘플 프로그램의 실행예 ]


2.6 마치며
이번 장에서는 3D 그래픽의 기초부터 한 발 나아가 문자열의 표시나 시점의 이동 등, 게임성을 높이기 위한 기술에 대해 설명했습니다. 또한 게임 프로그램 특유의 기술로써 캐릭터 관리에 대해 자세히 설명했습니다. 캐릭터 관리를 효과적으로 함으로써, 게임 루프를 간결하게 하여 처리속도의 향상을 가져올 수 있습니다.

다음 회에서는 렌즈플레어나 안개효과 등 DirectX Graphics의 특수효과에 대해 설명하겠습니다.

----------------------------------------

DirectX를 이용한 게임프로그래밍 입문
이 연재는 C++ 언어와 DirectX의 기초적인 지식이 있는 분을 대상으로 하고 있습니다.

제 1 장. 3D 게임 프로그래밍의 기초 (2003년 5월 1일)
제 2 장. DirectX Graphics의 기초 (2003년 8월 11일)
제 3 장. DirectX Graphics의 특수효과 (2003년 8월 11일)
제 4 장. 네트워크게임의 입문 (2003년 8월 11일)
제 5 장. 게임 개발 입문 (2003년 8월 21일)
제 6 장. 실전 게임 개발 (2003년 8월 29일)

----------------------------------------

저자약력

다나카 시게노리 (田中 成典)
1986년 칸사이대학 공학부 토목공학과 졸업
1988년 칸사이대학원 공학연구과 토목공학전공박사과정 전기과정 수료
1996년 박사(공학) 수여, 칸사이대학
1997년 칸사이대학 종합정보학부 조교수 (현재)
주요한 저서:
- 쉬운 C의 시작방법, 옴사(社), 1993년
- 건설기술자를 위한 지식정보처리의 실천, 칸사이대학출판부, 1999년
- DirectX8, 공학사, 2001년
- 스텝업 XML, 공학사, 2002년
- Linux 애플리케이션 입문, 모리키타(森北) 출판, 2002년 등

나카야마 코타로 (中山 浩太郎)
2001년 3월 칸사이대학 종합정보학과 졸업
2003년 3월 칸사이대학 대학원 종합정보학연구과 박사과정 전기과정 수료
2003년 4월 칸사이대학 대학원 종합정보학연구과 박사과정 후기과정 입학 (현재)
주요한 저서:
- Web 공방 시리즈 Perl의 달인, 모리키타(森北) 출판, 1999년
- 결정판 Visual Basic, 쿄리츠(共立) 출판, 2000년
- DirectX8, 공학사, 2001년
- Linux 애플리케이션 입문, 모리키타(森北) 출판, 2002년
- 스텝업 Visual C# .NET 입문, 공학사, 2002년 등

나카무라 켄지 (中村 健二)
2000년 4월 칸사이대학 종합정보학부 종합정보학과 입학 (현재)
주요한 저서: DirectX8 & VC++ 3D의 기초와 게임의 제작방법, 공학사, 2002년

키타가와 에츠지 (北川 悦司)
2000년 3월 칸사이대학 종합정보학부 종합정보학과 졸업
2002년 3월 칸사이대학 대학원 종합정보학연구과 박사과정 전기과정 수료
2002년 4월 칸사이대학 대학원 종합정보학연구과 박사과정 후기과정 입학 (현재)
주요한 저서:
- Web 공방 시리즈 Java의 달인, 모리키타(森北) 출판, 1999년
- 디지털 카메라 활용을 통한 디지털사진측량입문, 모리키타(森北) 출판, 2000년
- 스텝업 XML 활용법, 공학사, 2002년

우에야마 사토시 (上山 智士)
2002년 4월 칸사이대학 종합정보학부 종합정보학과 입학 (현재)

스기마치 토시유키 (杉町 敏之)
2003년 3월 칸사이대학 종합정보학부 종합정보학과 졸업
2003년 4월 칸사이대학 대학원 종합정보학연구과 입학 (현재)
주요한 저서: 스텝업 Visual C# .NET 입문, 공학사, 2002년

노나카 카즈키 (野中 一希)
2003년 3월 칸사이대학 종합정보학부 종합정보학과 졸업
2003년 4월 칸사이대학 대학원 종합정보학연구과 입학 (현재)
주요한 저서: 스텝업 Visual C# .NET 입문, 공학사, 2002년

SITELINK :: https://www.microsoft.com/japan/msdn/academic/Articles/DirectX/02/




-------------------------------------------------------------------------------------------------------------------------

자~
이쯤 까지 조사했다.
다른 조 아이들이 조사한 XML과 Xfile 두어개 읽어 보았지만 너무 어렵다.
직접 짜보기 전까지는 뭔소리하는건지 알아먹기 힘들었다.
뭐 이문서 저문서 보기는 많이 봤어도 당췌 뭔소리 하는건지 잘 모르겠다.
코딩해서 모델링 하기가 어려우니까 툴로 그림 그리고 애니메이션 준것을 X File 이라는 DirectX용 파일로 내보내고
그것을 읽어들어서 게임을 만들어라...
X file 이라는 놈은 XML 형태로 되어 있고 DirectX에서는 그것을 잘 읽어 들일 수 있다....
대~충 이런 내용인듯 하다.

우리조는 머리가 나빠서 직접 해보지 않고서는 뭔소린지 모른다.
그래서 직접 해보기로 했다.

인터넷을 뒤졌다.
네이뇬 지식 즐처드셈~ 은 맥스나 마야로 그려서 export 할때 x 파일을 골르면 X file 로 나온댄다.
그래서
Xfile을 만들기 위해서 3D Max로 허접때기 육면체를 하나 그렸다.

사용자 삽입 이미지

자~ 진짜로 그렸다.


그리고서 Export 할랬더니 X파일 포맷 고르는게 없다!
이런 젠장!
속았다.

그래서 이번에는 마야에 있나 해봤따. Maya로 그림을 그렸다. 이번엔 동그라케....

사용자 삽입 이미지

그렸다 동그랗게....



역시나 없다.
속은것인가?

인터넷을 뒤졌다.
역시.... 플러그인이라는 것이 있어야 되는 것이었따.

플러그인을 찾으러 인터넷을 또 뒤졌다.

음... 여러가지 종류의 Xfile 을 만들어주는 플러그인이 있었다.....
세상에는 참 똑똑한 사람들이 쎄고 쎘다.

일단 받아서 깔고...

사용자 삽입 이미지
ㅋㅋㅋ 생겼따.

이름은 귀찬으니 a.x 다.

저장옵션에 보니 뭐 좌표계 설정, file type 설정, 애니메이션, 텍스쳐 컨버젼, 메쉬 옵션 등등이 있었다.
대충 감으로 때려 잡고 저장.

xof 0303txt 0032
template XSkinMeshHeader {
 <3cf169ce-ff7c-44ab-93c0-f78f62d172e2>
 WORD nMaxSkinWeightsPerVertex;
 WORD nMaxSkinWeightsPerFace;
 WORD nBones;
}

template VertexDuplicationIndices {
 <b8d65549-d7c9-4995-89cf-53a9a8b031e3>
 DWORD nIndices;
 DWORD nOriginalVertices;
 array DWORD indices[nIndices];
}

template SkinWeights {
 <6f0d123b-bad2-4167-a0d0-80224f25fabb>
 STRING transformNodeName;
 DWORD nWeights;
 array DWORD vertexIndices[nWeights];
 array FLOAT weights[nWeights];
 Matrix4x4 matrixOffset;
}

template FVFData {
 <b6e70a0e-8ef9-4e83-94ad-ecc8b0c04897>
 DWORD dwFVF;
 DWORD nDWords;
 array DWORD data[nDWords];
}

template EffectInstance {
 <e331f7e4-0559-4cc2-8e99-1cec1657928f>
 STRING EffectFilename;
 [...]
}

template EffectParamFloats {
 <3014b9a0-62f5-478c-9b86-e4ac9f4e418b>
 STRING ParamName;
 DWORD nFloats;
 array FLOAT Floats[nFloats];
}

template EffectParamString {
 <1dbc4c88-94c1-46ee-9076-2c28818c9481>
 STRING ParamName;
 STRING Value;
}

template EffectParamDWord {
 <e13963bc-ae51-4c5d-b00f-cfa3a9d97ce5>
 STRING ParamName;
 DWORD Value;
}


Mesh Box01 {
 20;
 -34.325745;-33.274956;0.000000;,
 61.646240;-33.274956;0.000000;,
 -34.325745;52.189140;0.000000;,
 61.646240;52.189140;0.000000;,
 -34.325745;-33.274956;48.336254;,
 61.646240;-33.274956;48.336254;,
 -34.325745;52.189140;48.336254;,
 61.646240;52.189140;48.336254;,
 -34.325745;-33.274956;0.000000;,
 61.646240;-33.274956;0.000000;,
 61.646240;-33.274956;48.336254;,
 -34.325745;-33.274956;48.336254;,
 61.646240;52.189140;0.000000;,
 61.646240;-33.274956;48.336254;,
 61.646240;52.189140;0.000000;,
 -34.325745;52.189140;0.000000;,
 -34.325745;52.189140;48.336254;,
 61.646240;52.189140;48.336254;,
 -34.325745;52.189140;0.000000;,
 -34.325745;-33.274956;48.336254;;
 12;
 3;0,2,3;,
 3;3,1,0;,
 3;4,5,7;,
 3;7,6,4;,
 3;8,9,10;,
 3;10,11,8;,
 3;1,12,7;,
 3;7,13,1;,
 3;14,15,16;,
 3;16,17,14;,
 3;18,0,19;,
 3;19,6,18;;

 MeshNormals  {
  6;
  0.000000;0.000000;1.000000;,
  0.000000;0.000000;-1.000000;,
  0.000000;1.000000;0.000000;,
  -1.000000;0.000000;0.000000;,
  0.000000;-1.000000;0.000000;,
  1.000000;0.000000;0.000000;;
  12;
  3;0,0,0;,
  3;0,0,0;,
  3;1,1,1;,
  3;1,1,1;,
  3;2,2,2;,
  3;2,2,2;,
  3;3,3,3;,
  3;3,3,3;,
  3;4,4,4;,
  3;4,4,4;,
  3;5,5,5;,
  3;5,5,5;;
 }

 MeshMaterialList  {
  1;
  12;
  0,
  0,
  0,
  0,
  0,
  0,
  0,
  0,
  0,
  0,
  0,
  0;

  Material {
   0.650980;0.898039;0.898039;1.000000;;
   0.000000;
   0.650980;0.898039;0.898039;;
   0.000000;0.000000;0.000000;;
  }
 }

 MeshTextureCoords  {
  20;
  1.000000;1.000000;,
  0.000000;1.000000;,
  1.000000;0.000000;,
  0.000000;0.000000;,
  0.000000;1.000000;,
  1.000000;1.000000;,
  0.000000;0.000000;,
  1.000000;0.000000;,
  0.000000;1.000000;,
  1.000000;1.000000;,
  1.000000;0.000000;,
  0.000000;0.000000;,
  1.000000;1.000000;,
  0.000000;0.000000;,
  0.000000;1.000000;,
  1.000000;1.000000;,
  1.000000;0.000000;,
  0.000000;0.000000;,
  0.000000;1.000000;,
  1.000000;0.000000;;
 }
}

오~ 인터넷에서 보던 그 자료가 정말로 나왔다.
a.x file의 내용이다.
대충 보니 이펙트 파라메타 매트릭스도 나오고 좌표도 나오고 내가 그린 메쉬 Box01 이라는 것도 있고 그러네....

저것을 DirectX 가 해석하는거군....

그런데 저걸 정말 잘 읽어서 사용할 수 있을까?

궁굼해졌다.

그래서 또 인터넷을 뒤저보니... 사람들이 모델링 한것을 DirectX Viewer 라는 것으로 돌려보는 것을 발견!
아!
저 뷰어를 쓰면 Xfile을 그림으로 볼 수 있나 보다....

그런데 DirectX Viewer는 어떻게 까는거지?

인터넷을 또 뒤져.... 아~! DirectX SDK에 포함 되어 있는 거였군....

결국에는 DirectX SDK까지 깔았다.

드디어 나왔다 DirectX Viewer !!!

사용자 삽입 이미지

오~~ 가슴이 뛴다. Xfile을 이거로 열면 다시 그 네모난 사각형이 나오겠거니....

열어보자

저기 오픈을 누르면 고르는게 나온다.

사용자 삽입 이미지

ㅋㅋ 보이는가 ?!
Xfile을 열 수 가 있다.

a.x 를 열어보았다.

켁! 이건 또 뭐야
사용자 삽입 이미지
저 부분에 뭔가 메세지가 막 올라가더니
열린듯 싶더니....

화면에 변화가 없네....?

인터넷에서 봤을때는 저기 화면에 그린게 막 나오고 그러던데....
사용자 삽입 이미지
이것처럼....

아... 뭐야 이건.... 주루룩 올라간 메세지를 보니 뭐 메쉬를 계산하고 어쩌고 저쩌고.... @_@;;;

니미~ 캐 짜증....

이젠 어떻게 해야 되는건가....

껍데기를 안씌워서 그런가?

그래서 인터넷에 있는 X.file 샘플을 아무거나 받아서 열어봤다.

그런데 안나오네?

이거 도데체 무슨 문제지?

지금 진행 상황은 여기 까지 입니다.

이미 좀 아시는 분이 봤을때는 어이상실하는 기초적인 실수 일 수도 있겠지만.....

뭐 초짜가 하다보면 다 그런거 아니겠습니까? 여기서 해결 방법 아시는 분은

좀 도와주십쇼~
-------------------------------------------------------------------------------------------------------------------------

허접한 자료나마 정보 공유를 위하여 웹용으로 편집하였으니 많이들 보시기 바랍니다.

참고한 싸이트

◎게임 개발자 네트워크 (jzsdn)  네이버 카페
cafe.naver.com/jzsdn

◎3D STUDIO MAX 제압하기  네이버 카페
http://cafe.naver.com/maxkill.cafe?iframe_url=/ArticleRead.nhn%3Farticleid=31486

◎3D 자료 저장소
cafe.naver.com/3ddatabank
-------------------------------------------------------------------------------------------------------------------------

아 그리고 조사중에 ASE 파일도 X file 처럼 이용한다는 문서를 많이 보았는데

약간의 설명된 내용을 첨부 합니다.

Q) 확장자가 .x인 것은 무엇인가요?

 2001/03/10/Crc12 

X파일은 다이렉트3D에서 사용할수 있는 3D파일입니다.

3D에서 어떠한 물체를 띄울경우에 그 물체의 버텍스값과 , 텍스쳐가있어야하죠

그런것들을 X파일에서 모두 관리해줍니다. ASE파일도 3D파일이죠.

X파일 역시 ASE와 같은 3D파일입니다. 3DS-> X파일(변환)로 만들어주는 컨버터가 있습니다. 다이렉트 SDK를 깔고 나셔서 Util 폴더를 보시면 안에 X파일로 컨버팅 해주는 프로그램이 있구요 다이렉트X의 유틸리티 클래스에서 기술제공을 해주고 있습니다.

Q) 확장자가 .ase인 것은 무엇인가요?

 2001/2/22/목 천영호 

.ase는 맥스의 익스포트파일중 하나로 그 구성이 텍스트 파일로 되어 있습니다.

그러기에 상당히 파싱하기에 좋고 다루기 쉽다는 장점이 있습니다.

Q) *.ase vs *.x

 2001/2/24/천영호 

저는 *.ase와 *.x의 선택은 무의미하다고 생각합니다. 왜냐하면 실제 게임에서 위의 파일을 그대로 쓰는 경우는 없기 때문이죠. 다 *.ase나 *.x파일에서 필요한 데이터만을 뽑아내어 자신만의 파일포맷을 사용합니다. 그러므로 1차적 공개파일 (데이터가 다 공개되어 있는)의 선택은 그 의미가 없다고 생각합니다.

Q) 왜 ase를 사용하는가? 3DStudio Max 자체 데이터를 사용하면 안되는가?

 2001/2/22/목 천영호 

.max파일은 어떻게 보면 그 자료가 명확하지 않습니다. 실제 이 파일의 내용은 수많은 플러그인의 내용으로 가득차있고 그 플러그인의 수또한 많기 때문에 실제로 이 .max파일 자체의 데이터를 뽑아 낸다는것은 불가능하다고 알고 있습니다.

음.... 위와 같은 내용이구요
ASE는 또 뭔가 궁굼해서 만들어 봤습니다.
3DS MAX에서 ASE는 다른 플러그인을 깔지 않아도 Export 가능 하더군요

*3DSMAX_ASCIIEXPORT 200
*COMMENT "AsciiExport Version  2.00 - Thu Apr 19 11:35:25 2007"
*SCENE {
 *SCENE_FILENAME ""
 *SCENE_FIRSTFRAME 0
 *SCENE_LASTFRAME 100
 *SCENE_FRAMESPEED 30
 *SCENE_TICKSPERFRAME 160
 *SCENE_BACKGROUND_STATIC 0.0000 0.0000 0.0000
 *SCENE_AMBIENT_STATIC 0.0000 0.0000 0.0000
}
*MATERIAL_LIST {
 *MATERIAL_COUNT 0
}
*GEOMOBJECT {
 *NODE_NAME "Box01"
 *NODE_TM {
  *NODE_NAME "Box01"
  *INHERIT_POS 0 0 0
  *INHERIT_ROT 0 0 0
  *INHERIT_SCL 0 0 0
  *TM_ROW0 1.0000 0.0000 0.0000
  *TM_ROW1 0.0000 1.0000 0.0000
  *TM_ROW2 0.0000 0.0000 1.0000
  *TM_ROW3 29.0718 2.1016 0.0000
  *TM_POS 29.0718 2.1016 0.0000
  *TM_ROTAXIS 0.0000 0.0000 0.0000
  *TM_ROTANGLE 0.0000
  *TM_SCALE 1.0000 1.0000 1.0000
  *TM_SCALEAXIS 0.0000 0.0000 0.0000
  *TM_SCALEAXISANG 0.0000
 }
 *MESH {
  *TIMEVALUE 0
  *MESH_NUMVERTEX 8
  *MESH_NUMFACES 12
  *MESH_VERTEX_LIST {
   *MESH_VERTEX    0 -30.1226 -55.6918 0.0000
   *MESH_VERTEX    1 88.2662 -55.6918 0.0000
   *MESH_VERTEX    2 -30.1226 59.8949 0.0000
   *MESH_VERTEX    3 88.2662 59.8949 0.0000
   *MESH_VERTEX    4 -30.1226 -55.6918 74.9562
   *MESH_VERTEX    5 88.2662 -55.6918 74.9562
   *MESH_VERTEX    6 -30.1226 59.8949 74.9562
   *MESH_VERTEX    7 88.2662 59.8949 74.9562
  }
  *MESH_FACE_LIST {
   *MESH_FACE    0:    A:    0 B:    2 C:    3 AB:    1 BC:    1 CA:    0  *MESH_SMOOTHING 2  *MESH_MTLID 1
   *MESH_FACE    1:    A:    3 B:    1 C:    0 AB:    1 BC:    1 CA:    0  *MESH_SMOOTHING 2  *MESH_MTLID 1
   *MESH_FACE    2:    A:    4 B:    5 C:    7 AB:    1 BC:    1 CA:    0  *MESH_SMOOTHING 3  *MESH_MTLID 0
   *MESH_FACE    3:    A:    7 B:    6 C:    4 AB:    1 BC:    1 CA:    0  *MESH_SMOOTHING 3  *MESH_MTLID 0
   *MESH_FACE    4:    A:    0 B:    1 C:    5 AB:    1 BC:    1 CA:    0  *MESH_SMOOTHING 4  *MESH_MTLID 4
   *MESH_FACE    5:    A:    5 B:    4 C:    0 AB:    1 BC:    1 CA:    0  *MESH_SMOOTHING 4  *MESH_MTLID 4
   *MESH_FACE    6:    A:    1 B:    3 C:    7 AB:    1 BC:    1 CA:    0  *MESH_SMOOTHING 5  *MESH_MTLID 3
   *MESH_FACE    7:    A:    7 B:    5 C:    1 AB:    1 BC:    1 CA:    0  *MESH_SMOOTHING 5  *MESH_MTLID 3
   *MESH_FACE    8:    A:    3 B:    2 C:    6 AB:    1 BC:    1 CA:    0  *MESH_SMOOTHING 6  *MESH_MTLID 5
   *MESH_FACE    9:    A:    6 B:    7 C:    3 AB:    1 BC:    1 CA:    0  *MESH_SMOOTHING 6  *MESH_MTLID 5
   *MESH_FACE   10:    A:    2 B:    0 C:    4 AB:    1 BC:    1 CA:    0  *MESH_SMOOTHING 7  *MESH_MTLID 2
   *MESH_FACE   11:    A:    4 B:    6 C:    2 AB:    1 BC:    1 CA:    0  *MESH_SMOOTHING 7  *MESH_MTLID 2
  }
  *MESH_NUMTVERTEX 12
  *MESH_TVERTLIST {
   *MESH_TVERT 0 0.0000 0.0000 0.0000
   *MESH_TVERT 1 1.0000 0.0000 0.0000
   *MESH_TVERT 2 0.0000 1.0000 0.0000
   *MESH_TVERT 3 1.0000 1.0000 0.0000
   *MESH_TVERT 4 0.0000 0.0000 0.0000
   *MESH_TVERT 5 1.0000 0.0000 0.0000
   *MESH_TVERT 6 0.0000 1.0000 0.0000
   *MESH_TVERT 7 1.0000 1.0000 0.0000
   *MESH_TVERT 8 0.0000 0.0000 0.0000
   *MESH_TVERT 9 1.0000 0.0000 0.0000
   *MESH_TVERT 10 0.0000 1.0000 0.0000
   *MESH_TVERT 11 1.0000 1.0000 0.0000
  }
  *MESH_NUMTVFACES 12
  *MESH_TFACELIST {
   *MESH_TFACE 0 9 11 10
   *MESH_TFACE 1 10 8 9
   *MESH_TFACE 2 8 9 11
   *MESH_TFACE 3 11 10 8
   *MESH_TFACE 4 4 5 7
   *MESH_TFACE 5 7 6 4
   *MESH_TFACE 6 0 1 3
   *MESH_TFACE 7 3 2 0
   *MESH_TFACE 8 4 5 7
   *MESH_TFACE 9 7 6 4
   *MESH_TFACE 10 0 1 3
   *MESH_TFACE 11 3 2 0
  }
  *MESH_NUMCVERTEX 0
  *MESH_NORMALS {
   *MESH_FACENORMAL 0 0.0000 0.0000 -1.0000
    *MESH_VERTEXNORMAL 0 0.0000 0.0000 -1.0000
    *MESH_VERTEXNORMAL 2 0.0000 0.0000 -1.0000
    *MESH_VERTEXNORMAL 3 0.0000 0.0000 -1.0000
   *MESH_FACENORMAL 1 0.0000 0.0000 -1.0000
    *MESH_VERTEXNORMAL 3 0.0000 0.0000 -1.0000
    *MESH_VERTEXNORMAL 1 0.0000 0.0000 -1.0000
    *MESH_VERTEXNORMAL 0 0.0000 0.0000 -1.0000
   *MESH_FACENORMAL 2 0.0000 -0.0000 1.0000
    *MESH_VERTEXNORMAL 4 0.0000 0.0000 1.0000
    *MESH_VERTEXNORMAL 5 0.0000 -0.0000 1.0000
    *MESH_VERTEXNORMAL 7 0.0000 0.0000 1.0000
   *MESH_FACENORMAL 3 -0.0000 0.0000 1.0000
    *MESH_VERTEXNORMAL 7 0.0000 0.0000 1.0000
    *MESH_VERTEXNORMAL 6 -0.0000 0.0000 1.0000
    *MESH_VERTEXNORMAL 4 0.0000 0.0000 1.0000
   *MESH_FACENORMAL 4 0.0000 -1.0000 0.0000
    *MESH_VERTEXNORMAL 0 0.0000 -1.0000 0.0000
    *MESH_VERTEXNORMAL 1 0.0000 -1.0000 0.0000
    *MESH_VERTEXNORMAL 5 0.0000 -1.0000 0.0000
   *MESH_FACENORMAL 5 0.0000 -1.0000 0.0000
    *MESH_VERTEXNORMAL 5 0.0000 -1.0000 0.0000
    *MESH_VERTEXNORMAL 4 0.0000 -1.0000 0.0000
    *MESH_VERTEXNORMAL 0 0.0000 -1.0000 0.0000
   *MESH_FACENORMAL 6 1.0000 0.0000 -0.0000
    *MESH_VERTEXNORMAL 1 1.0000 0.0000 0.0000
    *MESH_VERTEXNORMAL 3 1.0000 0.0000 -0.0000
    *MESH_VERTEXNORMAL 7 1.0000 0.0000 0.0000
   *MESH_FACENORMAL 7 1.0000 -0.0000 0.0000
    *MESH_VERTEXNORMAL 7 1.0000 0.0000 0.0000
    *MESH_VERTEXNORMAL 5 1.0000 -0.0000 0.0000
    *MESH_VERTEXNORMAL 1 1.0000 0.0000 0.0000
   *MESH_FACENORMAL 8 0.0000 1.0000 0.0000
    *MESH_VERTEXNORMAL 3 0.0000 1.0000 0.0000
    *MESH_VERTEXNORMAL 2 0.0000 1.0000 0.0000
    *MESH_VERTEXNORMAL 6 0.0000 1.0000 0.0000
   *MESH_FACENORMAL 9 0.0000 1.0000 0.0000
    *MESH_VERTEXNORMAL 6 0.0000 1.0000 0.0000
    *MESH_VERTEXNORMAL 7 0.0000 1.0000 0.0000
    *MESH_VERTEXNORMAL 3 0.0000 1.0000 0.0000
   *MESH_FACENORMAL 10 -1.0000 0.0000 0.0000
    *MESH_VERTEXNORMAL 2 -1.0000 0.0000 0.0000
    *MESH_VERTEXNORMAL 0 -1.0000 0.0000 0.0000
    *MESH_VERTEXNORMAL 4 -1.0000 0.0000 0.0000
   *MESH_FACENORMAL 11 -1.0000 -0.0000 -0.0000
    *MESH_VERTEXNORMAL 4 -1.0000 0.0000 0.0000
    *MESH_VERTEXNORMAL 6 -1.0000 -0.0000 -0.0000
    *MESH_VERTEXNORMAL 2 -1.0000 0.0000 0.0000
  }
 }
 *PROP_MOTIONBLUR 0
 *PROP_CASTSHADOW 1
 *PROP_RECVSHADOW 1
 *WIREFRAME_COLOR 0.1098 0.5843 0.6941
}


위에서 그린 육면체는 ASE 파일로 뽑아낸 겁니다.
X file 과 비슷한것 같네요



마지막으로 Xfile을 활용하는 문서를 찾아냈습니다.

어떤 사람이 이 문서를 보고 칭한 한 글을 써놨더군요

앞으로 유용하게 사용할 수 있을 것 같습니다.

http://hybridego.net/entry/skindparsingmesh-xfile

반응형

'GamePrograming' 카테고리의 다른 글

스킨드 메쉬 직접 구현(엑스파일 파싱)  (0) 2007.04.19
X File Exporter 여러가지...  (0) 2007.04.19
Virtools User Guide 요약한것.  (0) 2007.04.19
Posted by Real_G