diff --git a/Common/CColor.cpp b/Common/CColor.cpp index 728d25c1..23ae8d85 100644 --- a/Common/CColor.cpp +++ b/Common/CColor.cpp @@ -162,6 +162,37 @@ void CColor::operator/=(const CColor& 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 const CColor CColor::skRed (u32(0xFF0000FF)); const CColor CColor::skGreen (u32(0x00FF00FF)); diff --git a/Common/CColor.h b/Common/CColor.h index ead6611c..70fd6980 100644 --- a/Common/CColor.h +++ b/Common/CColor.h @@ -36,6 +36,11 @@ public: CColor operator/(const CColor& other) const; 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 static const CColor skRed; static const CColor skGreen; diff --git a/PrimeWorldEditor.pro b/PrimeWorldEditor.pro index 6b011208..9726f2df 100644 --- a/PrimeWorldEditor.pro +++ b/PrimeWorldEditor.pro @@ -342,3 +342,9 @@ RESOURCES += \ 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 diff --git a/Resource/CMaterial.cpp b/Resource/CMaterial.cpp index aab68b71..7741fa92 100644 --- a/Resource/CMaterial.cpp +++ b/Resource/CMaterial.cpp @@ -278,6 +278,12 @@ void CMaterial::SetOptions(EMaterialOptions Options) mRecalcHash = true; } +void CMaterial::SetVertexDescription(EVertexDescription desc) +{ + mVtxDesc = desc; + mRecalcHash = true; +} + void CMaterial::SetBlendMode(GLenum SrcFac, GLenum DstFac) { mBlendSrcFac = SrcFac; diff --git a/Resource/CMaterial.h b/Resource/CMaterial.h index 924e7c41..b01b3018 100644 --- a/Resource/CMaterial.h +++ b/Resource/CMaterial.h @@ -99,6 +99,7 @@ public: // Setters void SetName(const std::string& name); void SetOptions(EMaterialOptions Options); + void SetVertexDescription(EVertexDescription desc); void SetBlendMode(GLenum SrcFac, GLenum DstFac); void SetKonst(CColor& Konst, u32 KIndex); void SetIndTexture(CTexture *pTex); diff --git a/Resource/factory/CMaterialLoader.cpp b/Resource/factory/CMaterialLoader.cpp index 8b58d872..3dbc6ff8 100644 --- a/Resource/factory/CMaterialLoader.cpp +++ b/Resource/factory/CMaterialLoader.cpp @@ -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 ************ CMaterialSet* CMaterialLoader::LoadMaterialSet(CInputStream& Mat, EGame Version) { @@ -591,3 +609,20 @@ CMaterialSet* CMaterialLoader::LoadMaterialSet(CInputStream& Mat, EGame Version) 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; +} diff --git a/Resource/factory/CMaterialLoader.h b/Resource/factory/CMaterialLoader.h index d8a1c5c6..862c9d80 100644 --- a/Resource/factory/CMaterialLoader.h +++ b/Resource/factory/CMaterialLoader.h @@ -1,11 +1,13 @@ #ifndef CMATERIALLOADER_H #define CMATERIALLOADER_H -#include #include "../CMaterialSet.h" #include "../EFormatVersion.h" #include +#include +#include + class CMaterialLoader { // Material data @@ -32,9 +34,12 @@ class CMaterialLoader CMaterial* ReadCorruptionMaterial(); void CreateCorruptionPasses(CMaterial *pMat); + CMaterial* LoadAssimpMaterial(const aiMaterial *pAiMat); + // Static public: static CMaterialSet* LoadMaterialSet(CInputStream& Mat, EGame Version); + static CMaterialSet* ImportAssimpMaterials(const aiScene *pScene, EGame targetVersion); }; #endif // CMATERIALLOADER_H diff --git a/Resource/factory/CModelLoader.cpp b/Resource/factory/CModelLoader.cpp index 107a89aa..de61ef10 100644 --- a/Resource/factory/CModelLoader.cpp +++ b/Resource/factory/CModelLoader.cpp @@ -5,6 +5,7 @@ CModelLoader::CModelLoader() { mFlags = eNoFlags; + mNumVertices = 0; } CModelLoader::~CModelLoader() @@ -272,6 +273,99 @@ void CModelLoader::LoadSurfaceHeaderDKCR(CInputStream& Model, SSurface *pSurf) 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 ************ CModel* CModelLoader::LoadCMDL(CInputStream& CMDL) { @@ -451,6 +545,27 @@ CModel* CModelLoader::LoadCorruptionWorldModel(CInputStream &MREA, CBlockMgrIn & 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) { switch (Version) diff --git a/Resource/factory/CModelLoader.h b/Resource/factory/CModelLoader.h index 15111a0e..08b9775e 100644 --- a/Resource/factory/CModelLoader.h +++ b/Resource/factory/CModelLoader.h @@ -8,6 +8,7 @@ #include #include #include +#include class CModelLoader { @@ -28,6 +29,7 @@ private: CAABox mAABox; EGame mVersion; + u32 mNumVertices; std::vector mPositions; std::vector mNormals; std::vector mColors; @@ -49,11 +51,13 @@ private: SSurface* LoadSurface(CInputStream& Model); void LoadSurfaceHeaderPrime(CInputStream& Model, SSurface *pSurf); void LoadSurfaceHeaderDKCR(CInputStream& Model, SSurface *pSurf); + SSurface* LoadAssimpMesh(const aiMesh *pMesh, CMaterialSet *pSet); public: static CModel* LoadCMDL(CInputStream& CMDL); 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* ImportAssimpNode(const aiNode *pNode, const aiScene *pScene, CMaterialSet& matSet); static EGame GetFormatVersion(u32 Version); }; diff --git a/Resource/model/CModel.cpp b/Resource/model/CModel.cpp index 77a2bb5e..3d0d4f76 100644 --- a/Resource/model/CModel.cpp +++ b/Resource/model/CModel.cpp @@ -10,6 +10,17 @@ CModel::CModel() : CBasicModel() mTriangleCount = 0; } +CModel::CModel(CMaterialSet *pSet, bool ownsMatSet) +{ + mHasOwnMaterials = ownsMatSet; + mHasOwnSurfaces = true; + mVertexCount = 0; + mTriangleCount = 0; + + mMaterialSets.resize(1); + mMaterialSets[0] = pSet; +} + CModel::~CModel() { if (mHasOwnMaterials) @@ -99,6 +110,7 @@ void CModel::DrawSurface(ERenderOptions Options, u32 Surface, u32 MatSet) // Draw IBOs mVBO.Bind(); + glLineWidth(1.f); for (u32 iIBO = 0; iIBO < mSubmeshIndexBuffers[Surface].size(); iIBO++) { diff --git a/Resource/model/CModel.h b/Resource/model/CModel.h index f1689433..5e97fe10 100644 --- a/Resource/model/CModel.h +++ b/Resource/model/CModel.h @@ -20,7 +20,7 @@ class CModel : public CBasicModel public: CModel(); - CModel(CMaterialSet *pSet); + CModel(CMaterialSet *pSet, bool ownsMatSet); ~CModel(); void BufferGL();