I'm trying to add texture loading support in my model loader but i've no idea what to do now (subset problem.)
#include "stdafx.h"
DirectionalLight DirLights[3];
Material Mat;
Model::Model()
{
DirLights[0].Ambient = XMFLOAT4(0.2f, 0.2f, 0.2f, 1.0f);
DirLights[0].Diffuse = XMFLOAT4(0.5f, 0.5f, 0.5f, 1.0f);
DirLights[0].Specular = XMFLOAT4(0.5f, 0.5f, 0.5f, 1.0f);
DirLights[0].Direction = XMFLOAT3(0.0f, 0.0f, 0.0f);
DirLights[1].Ambient = XMFLOAT4(0.2f, 0.2f, 0.2f, 1.0f);
DirLights[1].Diffuse = XMFLOAT4(0.5f, 0.5f, 0.5f, 1.0f);
DirLights[1].Specular = XMFLOAT4(0.5f, 0.5f, 0.5f, 1.0f);
DirLights[1].Direction = XMFLOAT3(0.0f, 0.0f, 0.0f);
DirLights[2].Ambient = XMFLOAT4(0.2f, 0.2f, 0.2f, 1.0f);
DirLights[2].Diffuse = XMFLOAT4(0.5f, 0.5f, 0.5f, 1.0f);
DirLights[2].Specular = XMFLOAT4(0.5f, 0.5f, 0.5f, 1.0f);
DirLights[2].Direction = XMFLOAT3(0.0f, 0.0f, 0.0f);
Mat.Ambient = XMFLOAT4(0.48f, 0.77f, 0.46f, 1.0f);
Mat.Diffuse = XMFLOAT4(0.29f, 1.0f, 0.24f, 1.0f);
Mat.Specular = XMFLOAT4(0.2f, 0.2f, 0.2f, 16.0f);
}
Model::~Model()
{
}
UINT* AttributeBuffer;
void Model::LoadModel(const std::string& filename)
{
Assimp::Importer imp;
const aiScene* pScene = imp.ReadFile(filename,
aiProcess_CalcTangentSpace |
aiProcess_Triangulate |
aiProcess_GenSmoothNormals |
aiProcess_SplitLargeMeshes |
aiProcess_ConvertToLeftHanded |
aiProcess_SortByPType |
aiProcess_PreTransformVertices);
if (pScene == NULL)
ShowError(imp.GetErrorString());
std::vector<Vertex::Basic32> vertices;
std::vector<USHORT> indices;
aiMesh** meshes = pScene->mMeshes;
aiMaterial** mats = pScene->mMaterials;
UINT* meshID;
UINT matID;
aiNode* sceneRoot = pScene->mRootNode;
aiNode** children = sceneRoot->mChildren;
aiNode* child;
UINT i = 0;
bool rootNode = true;
while(i < sceneRoot->mNumChildren)
{
if(rootNode)
{
child = sceneRoot;
rootNode = false;
} else
{
child = children[i];
i++;
}
if(!(child->mNumMeshes > 0))
continue;
meshID = child->mMeshes;
mModel.mSubsetCount += child->mNumMeshes;
for(UINT x = 0; x < child->mNumMeshes; x++)
{
mModel.mNumVertices += meshes[meshID[x]]->mNumVertices;
mModel.mNumFaces += meshes[meshID[x]]->mNumFaces;
}
AttributeBuffer = new UINT[mModel.mNumFaces];
UINT nextVertex = 0;
UINT nextIndex = 0;
for(UINT x = 0; x < child->mNumMeshes; x++)
{
UINT meshStartIndex = nextVertex;
for(UINT j = 0; j < meshes[meshID[x]]->mNumVertices; j++)
{
vertices[nextVertex].Pos.x = meshes[meshID[x]]->mVertices[j].x;
vertices[nextVertex].Pos.y = meshes[meshID[x]]->mVertices[j].y;
vertices[nextVertex].Pos.z = meshes[meshID[x]]->mVertices[j].z;
vertices[nextVertex].Normal.x = meshes[meshID[x]]->mNormals[j].x;
vertices[nextVertex].Normal.y = meshes[meshID[x]]->mNormals[j].y;
vertices[nextVertex].Normal.z = meshes[meshID[x]]->mNormals[j].z;
vertices[nextVertex].Tex.x = meshes[meshID[x]]->mTextureCoords[0][j].x;
vertices[nextVertex].Tex.y = meshes[meshID[x]]->mTextureCoords[0][j].y;
nextVertex++;
}
for(UINT j = 0; j < meshes[meshID[x]]->mNumFaces; j++)
{
UINT n = 0;
if(x != 0)
{
n = j + meshes[meshID[x-1]]->mNumFaces;
} else
{
n = j;
}
indices[nextIndex++] = meshes[meshID[x]]->mFaces[j].mIndices[0] + meshStartIndex;
indices[nextIndex++] = meshes[meshID[x]]->mFaces[j].mIndices[1] + meshStartIndex;
indices[nextIndex++] = meshes[meshID[x]]->mFaces[j].mIndices[2] + meshStartIndex;
AttributeBuffer[n] = meshes[meshID[x]]->mMaterialIndex;
}
}
}
for (UINT j = 0; j < pScene->mNumMaterials; j++)
{
const aiMaterial* mat = pScene->mMaterials[j];
aiString texPath;
if (mat->GetTextureCount(aiTextureType_DIFFUSE) > 0 && mat->GetTexture(aiTextureType_DIFFUSE, 0, &texPath) == AI_SUCCESS)
{
char path[260];
sprintf(path, "Resources\\Textures\\%s", texPath.C_Str());
ID3D11ShaderResourceView* srv = Mgr.CreateTexture(path);
mModel.TextureSRV.push_back(srv);
}
}
std::vector<MeshGeometry::Subset> subsets(mModel.mSubsetCount);
for (int j = 0; j < child->mNumMeshes; j++)
{
aiMesh* mesh = meshes[meshID[j]];
}
XNA::ComputeBoundingAxisAlignedBoxFromPoints(&mModel.box, mModel.mNumVertices, &vertices[0].Pos, sizeof(Vertex::Basic32));
mModel.Mesh.SetSubsetTable(subsets);
mModel.Mesh.SetVertices(&vertices[0], mModel.mNumVertices);
mModel.Mesh.SetIndices(&indices[0], mModel.mNumFaces * 3);
}
bool Model::IntersectAABBFrustum(XNA::AxisAlignedBox& box, CXMMATRIX world)
{
XMVECTOR detView = XMMatrixDeterminant(d3d->m_Cam.View());
XMMATRIX invView = XMMatrixInverse(&detView, d3d->m_Cam.View());
XMMATRIX invWorld = XMMatrixInverse(&XMMatrixDeterminant(world), world);
XMMATRIX toLocal = XMMatrixMultiply(invView, invWorld);
XMVECTOR scale;
XMVECTOR rotQuat;
XMVECTOR translation;
XMMatrixDecompose(&scale, &rotQuat, &translation, toLocal);
XNA::Frustum localspaceFrustum;
XNA::TransformFrustum(&localspaceFrustum, &d3d->m_Frustum, XMVectorGetX(scale), rotQuat, translation);
if (XNA::IntersectAxisAlignedBoxFrustum(&box, &localspaceFrustum) != 0)
return true;
return false;
}
void Model::Rotate(FLOAT X, FLOAT Y, FLOAT Z)
{
static bool x, y, z;
x = true;
y = true;
z = true;
if (X == 0)
x = false;
if (Y == 0)
y = false;
if (Z == 0)
z = false;
if (x)
mModel.World = XMMatrixRotationX(X);
if (y)
mModel.World = XMMatrixRotationY(Y);
if (z)
mModel.World = XMMatrixRotationZ(Z);
}
void Model::Scale(FLOAT X, FLOAT Y, FLOAT Z)
{
mModel.World = XMMatrixScaling(X, Y, Z);
}
void Model::Translate(FLOAT X, FLOAT Y, FLOAT Z)
{
mModel.World = XMMatrixTranslation(X, Y, Z);
}
void Model::SetIdentifyMatrix()
{
mModel.World = XMMatrixIdentity();
}
void Model::Render()
{
if (!IntersectAABBFrustum(mModel.box, mModel.World))
return;
UINT Stride = sizeof(Vertex::Basic32);
UINT Offset = 0;
Effects::BasicFX->SetDirLights(DirLights);
Effects::BasicFX->SetEyePosW(d3d->m_Cam.GetPosition());
ID3DX11EffectTechnique* activeTech = Effects::BasicFX->Light2Tech;
D3DX11_TECHNIQUE_DESC techDesc;
activeTech->GetDesc(&techDesc);
XMMATRIX worldInvTranspose = MathHelper::InverseTranspose(mModel.World);
XMMATRIX worldViewProj = mModel.World * d3d->m_Cam.ViewProj();
Effects::BasicFX->SetWorld(mModel.World);
Effects::BasicFX->SetWorldInvTranspose(worldInvTranspose);
Effects::BasicFX->SetWorldViewProj(worldViewProj);
for(UINT p = 0; p < techDesc.Passes; ++p)
{
activeTech->GetPassByIndex(p)->Apply(0, pDeviceContext);
for (UINT s = 0; s < mModel.mSubsetCount; s++)
{
Effects::BasicFX->SetMaterial(mModel.Materials[s]);
Effects::BasicFX->SetDiffuseMap(mModel.TextureSRV[s]);
mModel.Mesh.Draw(s);
}
}
}
MeshGeometry::MeshGeometry()
{
VertexBuffer = nullptr;
IndexBuffer = nullptr;
IndexBufferFormat = DXGI_FORMAT_R16_UINT;
VertexStride = 0;
}
MeshGeometry::~MeshGeometry()
{
ReleaseCOM(VertexBuffer);
ReleaseCOM(IndexBuffer);
}
void MeshGeometry::SetIndices(const USHORT* indices, UINT count)
{
D3D11_BUFFER_DESC ibd;
ibd.Usage = D3D11_USAGE_IMMUTABLE;
ibd.ByteWidth = sizeof(USHORT) * count;
ibd.BindFlags = D3D11_BIND_INDEX_BUFFER;
ibd.CPUAccessFlags = 0;
ibd.MiscFlags = 0;
ibd.StructureByteStride = 0;
D3D11_SUBRESOURCE_DATA iinitData;
iinitData.pSysMem = indices;
HR(pDevice->CreateBuffer(&ibd, &iinitData, &IndexBuffer));
}
void MeshGeometry::SetSubsetTable(std::vector<Subset>& subsetTable)
{
SubsetTable = subsetTable;
}
void MeshGeometry::Draw(UINT subsetId)
{
UINT offset = 0;
pDeviceContext->IASetVertexBuffers(0, 1, &VertexBuffer, &VertexStride, &offset);
pDeviceContext->IASetIndexBuffer(IndexBuffer, IndexBufferFormat, 0);
pDeviceContext->DrawIndexed(SubsetTable[subsetId].FaceCount * 3, SubsetTable[subsetId].FaceStart * 3, 0);
}
template <typename VertexType>
void MeshGeometry::SetVertices(const VertexType* vertices, UINT count)
{
ReleaseCOM(VertexBuffer);
VertexStride = sizeof(VertexType);
D3D11_BUFFER_DESC vbd;
vbd.Usage = D3D11_USAGE_IMMUTABLE;
vbd.ByteWidth = sizeof(VertexType) * count;
vbd.BindFlags = D3D11_BIND_VERTEX_BUFFER;
vbd.CPUAccessFlags = 0;
vbd.MiscFlags = 0;
vbd.StructureByteStride = 0;
D3D11_SUBRESOURCE_DATA vinitData;
vinitData.pSysMem = vertices;
HR(pDevice->CreateBuffer(&vbd, &vinitData, &VertexBuffer));
}