i want to display .obj file using by directx11, so i was wrote some code and when i try to build, they said nothing special error but there's nothing displayed without silver context. i can't find what's wrong. here is my whole code. please give me some advise.
these code are based on "Introduction to 3D game progrmming with directx 11 by Frank Luna". d3dApp.h is just create window code.
maybe, you will feel this code is too long, i know. i feel sorry about it, but i was try to reduce which is relationless code at drawing. so please, get some toleration and give me some advise. please.
this is my main code
class Read_Pawn : public D3DApp
{
public:
Read_Pawn(HINSTANCE hInstance);
bool Init();
void DrawScene();
private:
XMFLOAT4X4 mView;
XMFLOAT4X4 mProj;
float mTheta;
float mPhi;
float mRadius;
POINT mLastMousePos;
Object Pawn;
};
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE prevInstance, PSTR cmdLine, int showCmd)
{
Read_Pawn Pawn(hInstance);
if (!Pawn.Init())
return 0;
return Pawn.Run();
}
Read_Pawn::Read_Pawn(HINSTANCE hInstance)
: D3DApp(hInstance), mTheta(1.5f*MathHelper::Pi), mPhi(0.25f*MathHelper::Pi), mRadius(5.0f), Pawn("Pawn")
{
mMainWndCaption = L"Pawn Read";
mLastMousePos.x = 0;
mLastMousePos.y = 0;
XMMATRIX I = XMMatrixIdentity();
XMStoreFloat4x4(&mView, I);
XMStoreFloat4x4(&mProj, I);
}
bool Read_Pawn::Init()
{
if (!D3DApp::Init())
return false;
Effects::InitAll(md3dDevice);
Pawn.Init(md3dDevice);
Pawn.Create(md3dDevice, "pawn.obj");
return true;
}
void Read_Pawn::DrawScene()
{
md3dImmediateContext->ClearRenderTargetView(mRenderTargetView, reinterpret_cast<const float*>(&Colors::Silver));
md3dImmediateContext->ClearDepthStencilView(mDepthStencilView, D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, 0);
Pawn.Draw(md3dImmediateContext, &mView, &mProj);
HR(mSwapChain->Present(0, 0));
}
this is my .fx code
cbuffer cbPerObject
{
float4x4 gWorldViewProj;
};
struct VertexIn
{
float3 PosL : POSITION;
float3 Normal : NORMAL;
float2 Texcoord : TEXCOORD0;
};
struct VertexOut
{
float4 PosH : SV_POSITION;
float4 Color : COLOR;
};
VertexOut VS(VertexIn vin)
{
VertexOut vout;
vout.PosH = mul(float4(vin.PosL, 1.0f), gWorldViewProj);
vout.Color = float4(1.0f, 0.0f, 0.0f, 0.0f);
return vout;
}
float4 PS(VertexOut pin) : SV_Target
{
return pin.Color;
}
technique11 LoadVertex
{
pass P0
{
SetVertexShader(CompileShader(vs_5_0, VS()));
SetPixelShader(CompileShader(ps_5_0, PS()));
}
};
this is my effect code head
class Effect
{
public:
Effect(ID3D11Device* pdevice, const std::wstring& filename);
private:
Effect(const Effect& rhs);
protected:
ID3DX11Effect* mFX;
};
class BasicEffect : public Effect
{
public:
BasicEffect(ID3D11Device* pdevice, const std::wstring& filename);
void SetWorldViewProj(CXMMATRIX M) { WorldViewProj->SetMatrix(reinterpret_cast<const float*>(&M)); };
public:
ID3DX11EffectTechnique* pLoadVertex;
ID3DX11EffectMatrixVariable* WorldViewProj;
};
class Effects
{
public:
static void InitAll(ID3D11Device* pdevice);
public:
static BasicEffect* BasicFX;
};
body
Effect::Effect(ID3D11Device* pdevice, const std::wstring& Filename) : mFX(0)
{
std::ifstream fin(Filename, std::ios::binary);
fin.seekg(0, std::ios_base::end);
int size = (int)fin.tellg();
fin.seekg(0, std::ios_base::beg);
std::vector<char> CompiledShader(size);
fin.read(&CompiledShader[0], size);
fin.close();
HR(D3DX11CreateEffectFromMemory(&CompiledShader[0], size, 0, pdevice, &mFX));
}
BasicEffect::BasicEffect(ID3D11Device* pdevice, const std::wstring& Filename) : Effect(pdevice, Filename)
{
pLoadVertex = mFX->GetTechniqueByName("LoadVertex");
WorldViewProj = mFX->GetVariableByName("gWorldViewProj")->AsMatrix();
}
BasicEffect* Effects::BasicFX = 0;
void Effects::InitAll(ID3D11Device* pdevice)
{
_chdir("FX");
BasicFX = new BasicEffect(pdevice, L"Basic.fxo");
_chdir("..");
}
this is my vertex code head
namespace VERTEX
{
struct objVertex
{
XMFLOAT3 position;
XMFLOAT3 normal;
XMFLOAT2 texcoord;
};
}
class InputLayoutDesc
{
public:
static const D3D11_INPUT_ELEMENT_DESC objVertex[3];
};
class InputLayouts
{
public:
static void Init(ID3D11Device* device);
static ID3D11InputLayout* Get_objVertex() { return objVertex; };
private:
static ID3D11InputLayout* objVertex;
};
cpp
const D3D11_INPUT_ELEMENT_DESC InputLayoutDesc::objVertex[3] =
{
{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
{ "NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 },
{ "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 24, D3D11_INPUT_PER_VERTEX_DATA, 0 }
};
ID3D11InputLayout* InputLayouts::objVertex = 0;
void InputLayouts::Init(ID3D11Device* device)
{
D3DX11_PASS_DESC passDesc;
//objVertex
Effects::BasicFX->pLoadVertex->GetPassByIndex(0)->GetDesc(&passDesc);
HR(device->CreateInputLayout(InputLayoutDesc::objVertex, 3, passDesc.pIAInputSignature, passDesc.IAInputSignatureSize, &objVertex));
}
object head
class Object
{
void Init(ID3D11Device* pDevice);
HRESULT Create(ID3D11Device* pDevice, const char* Filename);
void Draw(ID3D11DeviceContext* DeviceContext, XMFLOAT4X4* View, XMFLOAT4X4* Proj);
private:
ID3D11Buffer* pmVB;
ID3D11Buffer* pmIB;
UINT mVCount;
UINT mTCount;
UINT mNCount;
UINT mICount;
XMFLOAT4X4 mWorld;
typedef std::unordered_multimap<UINT, UINT> VertexCache;
VertexCache vertexCache;
std::vector<VERTEX::objVertex> vertices;
private:
HRESULT LoadGeometryFromOBJ(const WCHAR* strFilename, vector<UINT>* vindices);
HRESULT CreateBuffer(ID3D11Device* Device, vector<UINT>* vindices);
DWORD AddVertex(UINT hash, VERTEX::objVertex* pVertex, VertexCache& cache);
};
body
//this code read only vertex without meterial.
void Object::Init(ID3D11Device* pDevice)
{
InputLayouts::Init(pDevice);
}
HRESULT Object::Create(ID3D11Device* pDevice, const char* Filename)
{
vector<UINT> Indices;
wchar_t* strFilename = new wchar_t[MAX_PATH];
mbstowcs(strFilename, Filename, strlen(Filename) + 1);
HR(LoadGeometryFromOBJ(strFilename, &Indices));
HR(CreateBuffer(pDevice, &Indices));
return S_OK;
}
HRESULT Object::LoadGeometryFromOBJ(const WCHAR* strFilename, vector<UINT>* Indices)
{
vector<XMFLOAT3> Positions;
vector<XMFLOAT2> TexCoords;
vector<XMFLOAT3> Normals;
//change directory
_chdir("Models");
std::ifstream InFile;
InFile.open(strFilename);
char strCommand[256] = { 0 };
for (;;)
{
InFile >> strCommand;
if (!InFile)
break;
if (0 == strcmp(strCommand, "#"))
{
// Comment
}
else if (0 == strcmp(strCommand, "v"))
{
// Vertex Position
float x = 0, y = 0, z = 0;
InFile >> x >> y >> z;
Positions.push_back(XMFLOAT3(x, y, z));
mVCount++;
}
else if (0 == strcmp(strCommand, "vt"))
{
// Vertex TexCoord
float u, v;
InFile >> u >> v;
TexCoords.push_back(XMFLOAT2(u, v));
mTCount++;
}
else if (0 == strcmp(strCommand, "vn"))
{
// Vertex Normal
float x, y, z;
InFile >> x >> y >> z;
Normals.push_back(XMFLOAT3(x, y, z));
mNCount++;
}
else if (0 == strcmp(strCommand, "f"))
{
// Face
UINT iPosition, iTexCoord, iNormal;
VERTEX::objVertex vertex;
for (UINT iFace = 0; iFace < 3; iFace++)
{
ZeroMemory(&vertex, sizeof(VERTEX::objVertex));
// OBJ format uses 1-based arrays
InFile >> iPosition;
vertex.position = (Positions)[iPosition - 1];
if ('/' == InFile.peek())
{
InFile.ignore();
if ('/' != InFile.peek())
{
// Optional texture coordinate
InFile >> iTexCoord;
vertex.texcoord = (TexCoords)[iTexCoord - 1];
}
if ('/' == InFile.peek())
{
InFile.ignore();
// Optional vertex normal
InFile >> iNormal;
vertex.normal = (Normals)[iNormal - 1];
}
}
/////////////////////////////////////////////////////////////
DWORD index = AddVertex(iPosition, &vertex, vertexCache);
Indices->push_back((UINT)index);
mICount++;
/////////////////////////////////////////////////////////////
}
}
}
InFile.close();
_chdir("..");
return S_OK;
}
HRESULT Object::CreateBuffer(ID3D11Device* Device, vector<UINT>* indices)
{
D3D11_BUFFER_DESC vbd;
vbd.Usage = D3D11_USAGE_IMMUTABLE;
vbd.ByteWidth = sizeof(VERTEX::objVertex) * mVCount;
vbd.BindFlags = D3D11_BIND_VERTEX_BUFFER;
vbd.CPUAccessFlags = 0;
vbd.MiscFlags = 0;
vbd.StructureByteStride = 0;
D3D11_SUBRESOURCE_DATA vinitData;
vinitData.pSysMem = &(vertices[0]);
HR(Device->CreateBuffer(&vbd, &vinitData, &pmVB));
D3D11_BUFFER_DESC ibd;
ibd.Usage = D3D11_USAGE_IMMUTABLE;
ibd.ByteWidth = sizeof(UINT)* mICount;
ibd.BindFlags = D3D11_BIND_INDEX_BUFFER;
ibd.CPUAccessFlags = 0;
ibd.MiscFlags = 0;
D3D11_SUBRESOURCE_DATA iinitData;
iinitData.pSysMem = &((*indices)[0]);
HR(Device->CreateBuffer(&ibd, &iinitData, &pmIB));
return S_OK;
}
void Object::Draw(ID3D11DeviceContext* Dc, XMFLOAT4X4* View, XMFLOAT4X4* Proj)
{
Dc->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
Dc->IASetInputLayout(InputLayouts::Get_objVertex());
UINT stride = sizeof(VERTEX::objVertex);
UINT offset = 0;
Dc->IASetVertexBuffers(0, 1, &pmVB, &stride, &offset);
Dc->IASetIndexBuffer(pmIB, DXGI_FORMAT_R32_UINT, offset);
XMMATRIX view = XMLoadFloat4x4(View);
XMMATRIX proj = XMLoadFloat4x4(Proj);
XMMATRIX world = XMLoadFloat4x4(&mWorld);
XMMATRIX WorldViewProj = view * proj * world;
Effects::BasicFX->SetWorldViewProj(reinterpret_cast<float*>(&WorldViewProj));
ID3DX11EffectTechnique* tech = Effects::BasicFX->pLoadVertex;
D3DX11_TECHNIQUE_DESC techDesc;
tech->GetDesc(&techDesc);
for (UINT i = 0; i < techDesc.Passes; i++)
{
tech->GetPassByIndex(i)->Apply(0, Dc);
Dc->DrawIndexed(mICount, 0, 0);
}
}
DWORD Object::AddVertex(UINT hash, VERTEX::objVertex* pVertex, VertexCache& cache)
{
auto f = cache.equal_range(hash);
for (auto it = f.first; it != f.second; ++it)
{
auto& tv = vertices[it->second];
if (0 == memcmp(pVertex, &tv, sizeof(VERTEX::objVertex)))
{
return it->second;
}
}
DWORD index = static_cast<UINT>(vertices.size());
vertices.push_back(*pVertex);
VertexCache::value_type entry(hash, index);
cache.insert(entry);
return index;
}