mesh 생성

반응형


이전 작업이 파일로부터 mesh를 읽어들이는 것이었다면 이번 작업은
mesh를 구성하는것이다.
기본적으로는 dx9 같이 몇몇개의 서브셋으로 구성되어져 있다.
하지만 생성하는 절차와 사용하는 api가 조금 다르다.

ID3DX10Mesh* mesh = NULL;          // 메시 - (정점, 인덱스, 속성버퍼를 가진다)

1. 정점 구조체의 형식을 결정하고 d3d10_input_element_desc 구조체를 준비하고 입력레이아웃을 생성
D3D10_INPUT_ELEMENT_DESC elements[] =
 {
  { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D10_INPUT_PER_VERTEX_DATA, 0 },
  { "NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D10_INPUT_PER_VERTEX_DATA, 0 },
  { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 24, D3D10_INPUT_PER_VERTEX_DATA, 0 },
 };

 
 // 입력레이아웃을 생성한다.
 D3D10_PASS_DESC passDesc;
 UINT numElements = COUNT_ARR(elements);
 pkTechnique->GetPassByIndex(0)->GetDesc(&passDesc);
 hr = pkDevice->CreateInputLayout(elements, numElements, passDesc.pIAInputSignature, passDesc.IAInputSignatureSize, &inputLayout);

2. d3dx10createmesh를 호출하여 비어있는 메시를 생성.
 HRESULT hr = D3DX10CreateMesh(pkDevice, elements, numElements, "POSITION", 24, 12, 0, &mesh);


3. 정점, 인덱스 속성버퍼에 데이터를 채운다.
 SimpleVertex vertices[] = { // 박스를 생성함.
.....
}

esh->GetVertexBuffer(0, &pVBuffer10)
pVBuffer10->Map(reinterpret_cast<void**>(&pRawVertices10), &stRawVertices10)
memcpy_s(pRawVertices10, stRawVertices10, (const void*)&vertices[0], sizeof(SimpleVertex)*24);
 pVBuffer10->Unmap();
SAFE_RELEASE(pVBuffer10);

WORD indices[] =
 {
  ....
 };

 ID3DX10MeshBuffer* pIBuffer10 = NULL;
 if(FAILED(mesh->GetIndexBuffer(&pIBuffer10)))
 {
  MessageBox( NULL, TEXT("Unable to retrieve D3DX10 mesh's index buffer."), TEXT("Error"), MB_OK );
  return false;
 }
 SIZE_T stRawIndices10 = 0;
 unsigned __int16* pRawIndices10 = NULL;
 if( FAILED( pIBuffer10->Map( reinterpret_cast< void** >( &pRawIndices10 ), &stRawIndices10 ) ) )
 {
  MessageBox( NULL, TEXT("Unable to Map() D3DX10's index buffer!"), TEXT("Error"), MB_OK );
  return false;
 }
 memcpy_s( pRawIndices10, stRawIndices10, (const void *) &indices[0], 36 * sizeof( unsigned __int16 ) );
 pIBuffer10->Unmap();
 SAFE_RELEASE(pIBuffer10);

4. 속성버퍼를 편리하게 생성하기 위해 속성버퍼에 대응하는 정보를 가지는 속성표를 만든다.
 DWORD dwInputTableSize = numSubsets;
 D3DX10_ATTRIBUTE_RANGE* pNewAttrTable = new D3DX10_ATTRIBUTE_RANGE[dwInputTableSize];
 for(DWORD i=0; i<dwInputTableSize; i++)
 {
  pNewAttrTable[i].AttribId  = i;  // 속성 ID
  pNewAttrTable[i].FaceStart  = i*4;  // 현재 서브셋에 속한 삼각형들의 시작 삼각형에 대한 인덱스 버퍼에서의 오프셋
  pNewAttrTable[i].FaceCount  = 4;  // 서브셋 내의 삼각형 갯수
  pNewAttrTable[i].VertexStart = i*8;  // 서현재 서브셋과 연결된 정점들의 시작 정덤에 대한 정점버퍼에서의 오프셋
  pNewAttrTable[i].VertexCount = 8;  // 현재 서브셋 내의 정점의 갯수
 }

 // 속성표로부터 속성버퍼를 만든다.
 hr = mesh->SetAttributeTable(pNewAttrTable, static_cast<UINT>(dwInputTableSize));
 hr = mesh->GenerateAttributeBufferFromTable();

5. 선택적으로 메시의 인접정보를 생성하고 최적화를 수행한다.
esh->GenerateAdjacencyAndPointReps(0.0f)
mesh->Optimize(D3DX10_MESHOPT_COMPACT | D3DX10_MESHOPT_ATTR_SORT | D3DX10_MESHOPT_VERTEX_CACHE, NULL, NULL)

6. 텍스쳐 로드
WCHAR* textureFilenames[numSubsets] = { L"brick0.jpg", L"brick1.jpg", L"brick2.jpg" };
 materials = new Material10[numSubsets];
 for (int i=0; i<numSubsets; i++)
 {
  materials[i].ambient=D3DXVECTOR4(1,1,1,1); //RGBA
  materials[i].diffuse=D3DXVECTOR4(1,1,1,1); //RGBA
  materials[i].specular=D3DXVECTOR4(1,1,1,1); //RGBA
  materials[i].emissive=D3DXVECTOR4(1,1,1,1); //RGBA
  materials[i].sharpness=10.0f;
  
  7. 텍스처를 로드한다.
  WCHAR* textureFilenames[numSubsets] = { L"brick0.jpg", L"brick1.jpg", L"brick2.jpg" };
 materials = new Material10[numSubsets];
 for (int i=0; i<numSubsets; i++)
 {
  materials[i].ambient=D3DXVECTOR4(1,1,1,1); //RGBA
  materials[i].diffuse=D3DXVECTOR4(1,1,1,1); //RGBA
  materials[i].specular=D3DXVECTOR4(1,1,1,1); //RGBA
  materials[i].emissive=D3DXVECTOR4(1,1,1,1); //RGBA
  materials[i].sharpness=10.0f;
  
  // 텍스처를 로드한다.
  hr = D3DX10CreateShaderResourceViewFromFile(pkDevice, textureFilenames[i], NULL, NULL, &materials[i].tex, NULL);
  }

8. mesh를 장치에 제출. - 메시데이터 수정시 다시 제출해야 한다.
 mesh->CommitToDevice();

.fx
fx에서는 그다지 볼게 없다.
텍스쳐 처리를 위해 추가된 부분만을 보면 된다.

Texture2D texDiffuse;
RasterizerState Culling {
 FillMode = SOLID;    // WIREFRAME이면 와이어 프레임
 CullMode = BACK;
 FrontCounterClockwise = false; // dx에서 사용하는 시계반대방향.
};

SamplerState samLinear {
 Filter = MIN_MAG_MIP_LINEAR;
 AddressU = Wrap;
 AddressV = Wrap;
};

float4 PS( PS_INPUT input ) : SV_Target
{
 float fLighting = saturate( dot( input.normal, vLightDir ) );
 float4 cAmbient = float4(0.3f, 0.3f, 0.3f, 1.0f);
 fLighting += cAmbient;

 float4 cDiffuse = texDiffuse.Sample( samLinear, input.tex ) * fLighting;
 cDiffuse.a = 1;
 return cDiffuse;
}

technique10 Render
{
 pass P0
 {
  SetVertexShader( CompileShader( vs_4_0, VS() ) );
  SetGeometryShader( NULL );
  SetPixelShader( CompileShader( ps_4_0, PS() ) );

  SetRasterizerState( Culling );
  }
}

'Study > Directx 10' 카테고리의 다른 글

경계볼륨 - 경계구, 경계상자  (0) 2010.05.11
3ds mesh file load  (0) 2010.05.11
3ds 로드, 가상트랙볼  (0) 2010.05.09
카메라 클래스 - 쿼터니온  (5) 2010.05.08
카메라 클래스 - 오일러  (0) 2010.05.07
TAGS.

Comments