Added support for model importing using assimp

This commit is contained in:
parax0 2015-08-10 09:47:00 -04:00
parent 4fc83f735b
commit 2967a483d9
11 changed files with 222 additions and 2 deletions

View File

@ -162,6 +162,37 @@ void CColor::operator/=(const CColor& other)
*this = (*this / other); *this = (*this / other);
} }
// ************ STATIC ************
CColor CColor::RandomColor(bool transparent)
{
CColor out;
out.r = rand() % 255;
out.g = rand() % 255;
out.b = rand() % 255;
out.a = (transparent ? rand() % 255 : 0);
return out;
}
CColor CColor::RandomLightColor(bool transparent)
{
CColor out;
out.r = 127 + (rand() % 128);
out.g = 127 + (rand() % 128);
out.b = 127 + (rand() % 128);
out.a = (transparent ? 127 + (rand() % 128) : 0);
return out;
}
CColor CColor::RandomDarkColor(bool transparent)
{
CColor out;
out.r = rand() % 128;
out.g = rand() % 128;
out.b = rand() % 128;
out.a = (transparent ? rand() % 128 : 0);
return out;
}
// defining predefined colors // defining predefined colors
const CColor CColor::skRed (u32(0xFF0000FF)); const CColor CColor::skRed (u32(0xFF0000FF));
const CColor CColor::skGreen (u32(0x00FF00FF)); const CColor CColor::skGreen (u32(0x00FF00FF));

View File

@ -36,6 +36,11 @@ public:
CColor operator/(const CColor& other) const; CColor operator/(const CColor& other) const;
void operator/=(const CColor& other); void operator/=(const CColor& other);
// Static
static CColor RandomColor(bool transparent);
static CColor RandomLightColor(bool transparent);
static CColor RandomDarkColor(bool transparent);
// some predefined colors below for ease of use // some predefined colors below for ease of use
static const CColor skRed; static const CColor skRed;
static const CColor skGreen; static const CColor skGreen;

View File

@ -342,3 +342,9 @@ RESOURCES += \
Icons.qrc Icons.qrc
win32:CONFIG(release, debug|release): LIBS += -L$$PWD/../../Libraries/assimp/lib/ -lassimp-vc120-mt
else:win32:CONFIG(debug, debug|release): LIBS += -L$$PWD/../../Libraries/assimp/lib/ -lassimp-vc120-mtd
INCLUDEPATH += $$PWD/../../Libraries/assimp/include
DEPENDPATH += $$PWD/../../Libraries/assimp/include

View File

@ -278,6 +278,12 @@ void CMaterial::SetOptions(EMaterialOptions Options)
mRecalcHash = true; mRecalcHash = true;
} }
void CMaterial::SetVertexDescription(EVertexDescription desc)
{
mVtxDesc = desc;
mRecalcHash = true;
}
void CMaterial::SetBlendMode(GLenum SrcFac, GLenum DstFac) void CMaterial::SetBlendMode(GLenum SrcFac, GLenum DstFac)
{ {
mBlendSrcFac = SrcFac; mBlendSrcFac = SrcFac;

View File

@ -99,6 +99,7 @@ public:
// Setters // Setters
void SetName(const std::string& name); void SetName(const std::string& name);
void SetOptions(EMaterialOptions Options); void SetOptions(EMaterialOptions Options);
void SetVertexDescription(EVertexDescription desc);
void SetBlendMode(GLenum SrcFac, GLenum DstFac); void SetBlendMode(GLenum SrcFac, GLenum DstFac);
void SetKonst(CColor& Konst, u32 KIndex); void SetKonst(CColor& Konst, u32 KIndex);
void SetIndTexture(CTexture *pTex); void SetIndTexture(CTexture *pTex);

View File

@ -576,6 +576,24 @@ void CMaterialLoader::CreateCorruptionPasses(CMaterial *pMat)
} }
} }
CMaterial* CMaterialLoader::LoadAssimpMaterial(const aiMaterial *pAiMat)
{
// todo: generate new material using import values.
CMaterial *pMat = new CMaterial(mVersion, eNoAttributes);
// Create generic custom pass that uses Konst color
CMaterialPass *pPass = new CMaterialPass(pMat);
pPass->SetColorInputs(eZeroRGB, eRasRGB, eKonstRGB, eZeroRGB);
pPass->SetAlphaInputs(eZeroAlpha, eZeroAlpha, eZeroAlpha, eKonstAlpha);
pPass->SetKColorSel(eKonst0_RGB);
pPass->SetKAlphaSel(eKonstOne);
pPass->SetRasSel(eRasColor0A0);
pMat->mKonstColors[0] = CColor::RandomLightColor(false);
pMat->mPasses.push_back(pPass);
return pMat;
}
// ************ STATIC ************ // ************ STATIC ************
CMaterialSet* CMaterialLoader::LoadMaterialSet(CInputStream& Mat, EGame Version) CMaterialSet* CMaterialLoader::LoadMaterialSet(CInputStream& Mat, EGame Version)
{ {
@ -591,3 +609,20 @@ CMaterialSet* CMaterialLoader::LoadMaterialSet(CInputStream& Mat, EGame Version)
return Loader.mpSet; return Loader.mpSet;
} }
CMaterialSet* CMaterialLoader::ImportAssimpMaterials(const aiScene *pScene, EGame targetVersion)
{
CMaterialLoader loader;
loader.mVersion = targetVersion;
CMaterialSet *pOut = new CMaterialSet();
pOut->mMaterials.reserve(pScene->mNumMaterials);
for (u32 iMat = 0; iMat < pScene->mNumMaterials; iMat++)
{
CMaterial *pMat = loader.LoadAssimpMaterial(pScene->mMaterials[iMat]);
pOut->mMaterials.push_back(pMat);
}
return pOut;
}

View File

@ -1,11 +1,13 @@
#ifndef CMATERIALLOADER_H #ifndef CMATERIALLOADER_H
#define CMATERIALLOADER_H #define CMATERIALLOADER_H
#include <FileIO/FileIO.h>
#include "../CMaterialSet.h" #include "../CMaterialSet.h"
#include "../EFormatVersion.h" #include "../EFormatVersion.h"
#include <Core/CResCache.h> #include <Core/CResCache.h>
#include <FileIO/FileIO.h>
#include <assimp/scene.h>
class CMaterialLoader class CMaterialLoader
{ {
// Material data // Material data
@ -32,9 +34,12 @@ class CMaterialLoader
CMaterial* ReadCorruptionMaterial(); CMaterial* ReadCorruptionMaterial();
void CreateCorruptionPasses(CMaterial *pMat); void CreateCorruptionPasses(CMaterial *pMat);
CMaterial* LoadAssimpMaterial(const aiMaterial *pAiMat);
// Static // Static
public: public:
static CMaterialSet* LoadMaterialSet(CInputStream& Mat, EGame Version); static CMaterialSet* LoadMaterialSet(CInputStream& Mat, EGame Version);
static CMaterialSet* ImportAssimpMaterials(const aiScene *pScene, EGame targetVersion);
}; };
#endif // CMATERIALLOADER_H #endif // CMATERIALLOADER_H

View File

@ -5,6 +5,7 @@
CModelLoader::CModelLoader() CModelLoader::CModelLoader()
{ {
mFlags = eNoFlags; mFlags = eNoFlags;
mNumVertices = 0;
} }
CModelLoader::~CModelLoader() CModelLoader::~CModelLoader()
@ -272,6 +273,99 @@ void CModelLoader::LoadSurfaceHeaderDKCR(CInputStream& Model, SSurface *pSurf)
Model.SeekToBoundary(32); Model.SeekToBoundary(32);
} }
SSurface* CModelLoader::LoadAssimpMesh(const aiMesh *pMesh, CMaterialSet *pSet)
{
// Create vertex description and assign it to material
CMaterial *pMat = pSet->MaterialByIndex(pMesh->mMaterialIndex);
EVertexDescription desc = pMat->VtxDesc();
if (desc == eNoAttributes)
{
if (pMesh->HasPositions()) desc |= ePosition;
if (pMesh->HasNormals()) desc |= eNormal;
for (u32 iUV = 0; iUV < pMesh->GetNumUVChannels(); iUV++)
desc |= (eTex0 << (iUV * 2));
pMat->SetVertexDescription(desc);
}
// Create surface
SSurface *pSurf = new SSurface();
pSurf->MaterialID = pMesh->mMaterialIndex;
if (pMesh->mNumFaces > 0)
{
pSurf->Primitives.resize(1);
SSurface::SPrimitive& prim = pSurf->Primitives[0];
// Check primitive type on first face
u32 numIndices = pMesh->mFaces[0].mNumIndices;
if (numIndices == 1) prim.Type = eGX_Points;
else if (numIndices == 2) prim.Type = eGX_Lines;
else if (numIndices == 3) prim.Type = eGX_Triangles;
// Generate bounding box, center point, and reflection projection
pSurf->CenterPoint = CVector3f::skZero;
pSurf->ReflectionDirection = CVector3f::skZero;
for (u32 iVtx = 0; iVtx < pMesh->mNumVertices; iVtx++)
{
aiVector3D aiPos = pMesh->mVertices[iVtx];
pSurf->AABox.ExpandBounds(CVector3f(aiPos.x, aiPos.y, aiPos.z));
if (pMesh->HasNormals()) {
aiVector3D aiNrm = pMesh->mNormals[iVtx];
pSurf->ReflectionDirection += CVector3f(aiNrm.x, aiNrm.y, aiNrm.z);
}
}
pSurf->CenterPoint = pSurf->AABox.Center();
if (pMesh->HasNormals())
pSurf->ReflectionDirection /= pMesh->mNumVertices;
else
pSurf->ReflectionDirection = CVector3f(1.f, 0.f, 0.f);
// Set vertex/triangle count
pSurf->VertexCount = pMesh->mNumVertices;
pSurf->TriangleCount = (prim.Type == eGX_Triangles ? pMesh->mNumFaces : 0);
// Create primitive
for (u32 iFace = 0; iFace < pMesh->mNumFaces; iFace++)
{
for (u32 iIndex = 0; iIndex < numIndices; iIndex++)
{
u32 index = pMesh->mFaces[iFace].mIndices[iIndex];
// Create vertex and add it to the primitive
CVertex vert;
vert.ArrayPosition = index + mNumVertices;
if (pMesh->HasPositions()) {
aiVector3D aiPos = pMesh->mVertices[index];
vert.Position = CVector3f(aiPos.x, aiPos.y, aiPos.z);
}
if (pMesh->HasNormals()) {
aiVector3D aiNrm = pMesh->mNormals[index];
vert.Normal = CVector3f(aiNrm.x, aiNrm.y, aiNrm.z);
}
for (u32 iTex = 0; iTex < pMesh->GetNumUVChannels(); iTex++) {
aiVector3D aiTex = pMesh->mTextureCoords[iTex][index];
vert.Tex[iTex] = CVector2f(aiTex.x, aiTex.y);
}
prim.Vertices.push_back(vert);
}
}
mNumVertices += pMesh->mNumVertices;
}
return pSurf;
}
// ************ STATIC ************ // ************ STATIC ************
CModel* CModelLoader::LoadCMDL(CInputStream& CMDL) CModel* CModelLoader::LoadCMDL(CInputStream& CMDL)
{ {
@ -451,6 +545,27 @@ CModel* CModelLoader::LoadCorruptionWorldModel(CInputStream &MREA, CBlockMgrIn &
return pModel; return pModel;
} }
CModel* CModelLoader::ImportAssimpNode(const aiNode *pNode, const aiScene *pScene, CMaterialSet& matSet)
{
CModelLoader loader;
loader.mpModel = new CModel(&matSet, true);
loader.mpModel->mSurfaces.reserve(pNode->mNumMeshes);
for (u32 iMesh = 0; iMesh < pNode->mNumMeshes; iMesh++)
{
u32 meshIndex = pNode->mMeshes[iMesh];
const aiMesh *pMesh = pScene->mMeshes[meshIndex];
SSurface *pSurf = loader.LoadAssimpMesh(pMesh, &matSet);
loader.mpModel->mSurfaces.push_back(pSurf);
loader.mpModel->mAABox.ExpandBounds(pSurf->AABox);
loader.mpModel->mVertexCount += pSurf->VertexCount;
loader.mpModel->mTriangleCount += pSurf->TriangleCount;
}
return loader.mpModel;
}
EGame CModelLoader::GetFormatVersion(u32 Version) EGame CModelLoader::GetFormatVersion(u32 Version)
{ {
switch (Version) switch (Version)

View File

@ -8,6 +8,7 @@
#include <FileIO/FileIO.h> #include <FileIO/FileIO.h>
#include <Core/CResCache.h> #include <Core/CResCache.h>
#include <Common/EnumUtil.h> #include <Common/EnumUtil.h>
#include <assimp/scene.h>
class CModelLoader class CModelLoader
{ {
@ -28,6 +29,7 @@ private:
CAABox mAABox; CAABox mAABox;
EGame mVersion; EGame mVersion;
u32 mNumVertices;
std::vector<CVector3f> mPositions; std::vector<CVector3f> mPositions;
std::vector<CVector3f> mNormals; std::vector<CVector3f> mNormals;
std::vector<CColor> mColors; std::vector<CColor> mColors;
@ -49,11 +51,13 @@ private:
SSurface* LoadSurface(CInputStream& Model); SSurface* LoadSurface(CInputStream& Model);
void LoadSurfaceHeaderPrime(CInputStream& Model, SSurface *pSurf); void LoadSurfaceHeaderPrime(CInputStream& Model, SSurface *pSurf);
void LoadSurfaceHeaderDKCR(CInputStream& Model, SSurface *pSurf); void LoadSurfaceHeaderDKCR(CInputStream& Model, SSurface *pSurf);
SSurface* LoadAssimpMesh(const aiMesh *pMesh, CMaterialSet *pSet);
public: public:
static CModel* LoadCMDL(CInputStream& CMDL); static CModel* LoadCMDL(CInputStream& CMDL);
static CModel* LoadWorldModel(CInputStream& MREA, CBlockMgrIn& BlockMgr, CMaterialSet& MatSet, EGame Version); static CModel* LoadWorldModel(CInputStream& MREA, CBlockMgrIn& BlockMgr, CMaterialSet& MatSet, EGame Version);
static CModel* LoadCorruptionWorldModel(CInputStream& MREA, CBlockMgrIn& BlockMgr, CMaterialSet& MatSet, u32 HeaderSecNum, u32 GPUSecNum, EGame Version); static CModel* LoadCorruptionWorldModel(CInputStream& MREA, CBlockMgrIn& BlockMgr, CMaterialSet& MatSet, u32 HeaderSecNum, u32 GPUSecNum, EGame Version);
static CModel* ImportAssimpNode(const aiNode *pNode, const aiScene *pScene, CMaterialSet& matSet);
static EGame GetFormatVersion(u32 Version); static EGame GetFormatVersion(u32 Version);
}; };

View File

@ -10,6 +10,17 @@ CModel::CModel() : CBasicModel()
mTriangleCount = 0; mTriangleCount = 0;
} }
CModel::CModel(CMaterialSet *pSet, bool ownsMatSet)
{
mHasOwnMaterials = ownsMatSet;
mHasOwnSurfaces = true;
mVertexCount = 0;
mTriangleCount = 0;
mMaterialSets.resize(1);
mMaterialSets[0] = pSet;
}
CModel::~CModel() CModel::~CModel()
{ {
if (mHasOwnMaterials) if (mHasOwnMaterials)
@ -99,6 +110,7 @@ void CModel::DrawSurface(ERenderOptions Options, u32 Surface, u32 MatSet)
// Draw IBOs // Draw IBOs
mVBO.Bind(); mVBO.Bind();
glLineWidth(1.f);
for (u32 iIBO = 0; iIBO < mSubmeshIndexBuffers[Surface].size(); iIBO++) for (u32 iIBO = 0; iIBO < mSubmeshIndexBuffers[Surface].size(); iIBO++)
{ {

View File

@ -20,7 +20,7 @@ class CModel : public CBasicModel
public: public:
CModel(); CModel();
CModel(CMaterialSet *pSet); CModel(CMaterialSet *pSet, bool ownsMatSet);
~CModel(); ~CModel();
void BufferGL(); void BufferGL();