diff --git a/code/nel/tools/3d/mesh_utils/assimp_shape.cpp b/code/nel/tools/3d/mesh_utils/assimp_shape.cpp index b6b3163bb..d7eea11fb 100644 --- a/code/nel/tools/3d/mesh_utils/assimp_shape.cpp +++ b/code/nel/tools/3d/mesh_utils/assimp_shape.cpp @@ -89,6 +89,11 @@ inline CRGBA convColor(const aiColor4D &ac) return CRGBA(ac.r * 255.99f, ac.g * 255.99f, ac.b * 255.99f, ac.a * 255.99f); } +inline CUVW convUvw(const aiVector3D &av) +{ + return CUVW(av.x, av.y, av.z); // UH OH COORDINATE CONVERSION ?! +} + bool assimpBuildMesh(CMesh::CMeshBuild &buildMesh, CMeshBase::CMeshBaseBuild &buildBaseMesh, CMeshUtilsContext &context, CNodeContext &nodeContext) { // TODO @@ -98,6 +103,7 @@ bool assimpBuildMesh(CMesh::CMeshBuild &buildMesh, CMeshBase::CMeshBaseBuild &bu // TODO Support skinning const aiNode *node = nodeContext.InternalNode; + nlassert(node->mNumMeshes); // Basic validations before processing starts for (unsigned int mi = 0; mi < node->mNumMeshes; ++mi) @@ -127,12 +133,13 @@ bool assimpBuildMesh(CMesh::CMeshBuild &buildMesh, CMeshBase::CMeshBaseBuild &bu // Default vertex flags buildMesh.VertexFlags = CVertexBuffer::PositionFlag | CVertexBuffer::NormalFlag; - // TODO: UV Channels + // TODO: UV Channels routing to correct texture stage for (uint i = 0; i < CVertexBuffer::MaxStage; ++i) buildMesh.UVRouting[i] = i; // Meshes in assimp are separated per material, so we need to re-merge them for the mesh build process // This process also deduplicates vertices + bool cleanupMesh = false; sint32 numVertices = 0; for (unsigned int mi = 0; mi < node->mNumMeshes; ++mi) numVertices += context.InternalScene->mMeshes[node->mMeshes[mi]]->mNumVertices; @@ -152,7 +159,7 @@ bool assimpBuildMesh(CMesh::CMeshBuild &buildMesh, CMeshBase::CMeshBaseBuild &bu if (vecit == vertexIdentifiers.end()) { buildMesh.Vertices[numVertices] = vec; - vertexIdentifiers[vec] = numVertices; + if (cleanupMesh) vertexIdentifiers[vec] = numVertices; // Don't remap if we don't wan't to lose vertex indices vertexRemapping[mi][vi] = numVertices; ++numVertices; } @@ -172,10 +179,45 @@ bool assimpBuildMesh(CMesh::CMeshBuild &buildMesh, CMeshBase::CMeshBaseBuild &bu numFaces += context.InternalScene->mMeshes[node->mMeshes[mi]]->mNumFaces; buildMesh.Faces.resize(numFaces); numFaces = 0; + unsigned int refNumColorChannels = context.InternalScene->mMeshes[node->mMeshes[0]]->GetNumColorChannels(); + unsigned int refNumUVChannels = context.InternalScene->mMeshes[node->mMeshes[0]]->GetNumUVChannels(); for (unsigned int mi = 0; mi < node->mNumMeshes; ++mi) { const aiMesh *mesh = context.InternalScene->mMeshes[node->mMeshes[mi]]; - unsigned int numColorChannels = mesh->GetNumColorChannels(); // TODO: Maybe needs to be same on all mesh parts + + // Get channel numbers + unsigned int numColorChannels = mesh->GetNumColorChannels(); + if (numColorChannels > 2) + { + tlerror(context.ToolLogger, context.Settings.SourceFilePath.c_str(), + "Shape '%s' has too many color channels in mesh %i (%i channels found)", node->mName.C_Str(), mi, numColorChannels); + } + if (numColorChannels > 0) + { + buildMesh.VertexFlags |= CVertexBuffer::PrimaryColorFlag; + if (numColorChannels > 1) + { + buildMesh.VertexFlags |= CVertexBuffer::SecondaryColorFlag; + } + } + unsigned int numUVChannels = mesh->GetNumUVChannels(); + if (numUVChannels > CVertexBuffer::MaxStage) + { + tlerror(context.ToolLogger, context.Settings.SourceFilePath.c_str(), + "Shape '%s' has too many uv channels in mesh %i (%i channels found)", node->mName.C_Str(), mi, numUVChannels); + numUVChannels = CVertexBuffer::MaxStage; + } + for (unsigned int ui = 0; ui < numUVChannels; ++ui) + buildMesh.VertexFlags |= (CVertexBuffer::TexCoord0 << ui); // TODO: Coord UV tex stage rerouting + + // TODO: Channels do in fact differ between submeshes, so we need to correctly recount and reroute the materials properly + if (numColorChannels != refNumColorChannels) + tlerror(context.ToolLogger, context.Settings.SourceFilePath.c_str(), + "Shape '%s' mismatch of nb color channel in mesh '%i', please contact developer", node->mName.C_Str(), mi); + if (numUVChannels != refNumUVChannels) + tlerror(context.ToolLogger, context.Settings.SourceFilePath.c_str(), + "Shape '%s' mismatch of nb uv channel in mesh '%i', please contact developer", node->mName.C_Str(), mi); + for (unsigned int fi = 0; fi < mesh->mNumFaces; ++fi) { const aiFace &af = mesh->mFaces[fi]; @@ -195,18 +237,43 @@ bool assimpBuildMesh(CMesh::CMeshBuild &buildMesh, CMeshBase::CMeshBaseBuild &bu face.Corner[1].Normal = convVector(mesh->mNormals[af.mIndices[1]]); face.Corner[2].Normal = convVector(mesh->mNormals[af.mIndices[2]]); // TODO: If we want normal maps, we need to add tangent vectors to CFace and build process - // TODO: UV + // UV channels + for (unsigned int ui = 0; ui < numUVChannels; ++ui) // TODO: UV Rerouting + { + face.Corner[0].Uvws[ui] = convUvw(mesh->mTextureCoords[ui][af.mIndices[0]]); + face.Corner[1].Uvws[ui] = convUvw(mesh->mTextureCoords[ui][af.mIndices[1]]); + face.Corner[2].Uvws[ui] = convUvw(mesh->mTextureCoords[ui][af.mIndices[2]]); + } + for (unsigned int ui = numUVChannels; ui < CVertexBuffer::MaxStage; ++ui) + { + face.Corner[0].Uvws[ui] = CUVW(0, 0, 0); + face.Corner[1].Uvws[ui] = CUVW(0, 0, 0); + face.Corner[2].Uvws[ui] = CUVW(0, 0, 0); + } + // Primary and secondary color channels if (numColorChannels > 0) // TODO: Verify { face.Corner[0].Color = convColor(mesh->mColors[0][af.mIndices[0]]); face.Corner[1].Color = convColor(mesh->mColors[0][af.mIndices[1]]); face.Corner[2].Color = convColor(mesh->mColors[0][af.mIndices[2]]); - if (numColorChannels > 1) // TODO: Verify - { - face.Corner[0].Specular = convColor(mesh->mColors[1][af.mIndices[0]]); - face.Corner[1].Specular = convColor(mesh->mColors[1][af.mIndices[1]]); - face.Corner[2].Specular = convColor(mesh->mColors[1][af.mIndices[2]]); - } + } + else + { + face.Corner[0].Color = CRGBA(255, 255, 255, 255); + face.Corner[1].Color = CRGBA(255, 255, 255, 255); + face.Corner[2].Color = CRGBA(255, 255, 255, 255); + } + if (numColorChannels > 1) // TODO: Verify + { + face.Corner[0].Specular = convColor(mesh->mColors[1][af.mIndices[0]]); + face.Corner[1].Specular = convColor(mesh->mColors[1][af.mIndices[1]]); + face.Corner[2].Specular = convColor(mesh->mColors[1][af.mIndices[2]]); + } + else + { + face.Corner[0].Specular = CRGBA(255, 255, 255, 255); + face.Corner[1].Specular = CRGBA(255, 255, 255, 255); + face.Corner[2].Specular = CRGBA(255, 255, 255, 255); } // TODO: Color modulate, alpha, use color alpha for vp tree, etc ++numFaces; diff --git a/code/nel/tools/3d/mesh_utils/mesh_utils.cpp b/code/nel/tools/3d/mesh_utils/mesh_utils.cpp index bfda6e63f..2ea3800a7 100644 --- a/code/nel/tools/3d/mesh_utils/mesh_utils.cpp +++ b/code/nel/tools/3d/mesh_utils/mesh_utils.cpp @@ -247,7 +247,7 @@ void exportShapes(CMeshUtilsContext &context) "Shape '%s' serialization failed!", it->first.c_str()); } } - if (NL3D::CMesh *mesh = dynamic_cast(nodeContext.Shape.getPtr())) + if (NL3D::CMeshBase *mesh = dynamic_cast(nodeContext.Shape.getPtr())) { for (uint mi = 0; mi < mesh->getNbMaterial(); ++mi) {