/* Specialization for aiVertexWeight */ template<> aiVertexWeight comparer_context :: cmp<aiVertexWeight >(const std::string& name) { const unsigned int mVertexId = cmp<unsigned int>(name+".mVertexId"); const float mWeight = cmp<float>(name+".mWeight"); return aiVertexWeight(mVertexId,mWeight); }
bool CAssimpMesh::ExtractMeshGroup(uint32 Index, const aiMesh* paiMesh) { CMeshGroup *group = new CMeshGroup(); group->SetMaterialIndex(paiMesh->mMaterialIndex ); bool hasTangents = paiMesh->HasTangentsAndBitangents(); bool hasNormals = paiMesh->HasNormals(); std::vector<CGpuVertex> &Vertices = group->GetVertices(); std::vector<ushort16> &Indices = group->GetIndices(); const aiVector3D Zero3D(0.0f, 0.0f, 0.0f); //collect weights on all vertices std::vector<std::vector<aiVertexWeight> > weightsPerVertex(paiMesh->mNumVertices); for (uint32 a = 0; a < paiMesh->mNumBones; a++) { const aiBone* bone = paiMesh->mBones[a]; if(bone == NULL) continue; for (uint32 b = 0; b<bone->mNumWeights; b++) { weightsPerVertex[bone->mWeights[b].mVertexId].push_back(aiVertexWeight(a, bone->mWeights[b].mWeight)); } } //extract vertex attributes ( pos, normal, tex coord, bone indices and weights) for (uint32 i = 0 ; i < paiMesh->mNumVertices ; i++) { //extract vertex pos normal texture coordinates (actually tangent are not extracted) const aiVector3D* pPos = &(paiMesh->mVertices[i]); const aiVector3D* pNormal = &(paiMesh->mNormals[i]); const aiVector3D* pTexCoord = paiMesh->HasTextureCoords(0) ? &(paiMesh->mTextureCoords[0][i]) : &Zero3D; const aiVector3D* pTangCoord = &(paiMesh->mTangents[i]); //fill vertex attributes CGpuVertex v; if(pPos != NULL) v.pos = vec3f(pPos->x, pPos->y, pPos->z); if(pTexCoord != NULL) v.texCoord = vec2f(pTexCoord->x, pTexCoord->y); if(hasNormals && pNormal != NULL) v.normal = vec3f(pNormal->x, pNormal->y, pNormal->z); if(hasTangents && pTangCoord != NULL) v.tangent = vec3f(pTangCoord->x, pTangCoord->y, pTangCoord->z); //extract bone indices and weights if(paiMesh->HasBones()) { //assert(weightsPerVertex[i].size() <= 4); for(uint32 a = 0; a < weightsPerVertex[i].size(); a++) { //fill vertex attributes v.boneIndices[a] = (float32)weightsPerVertex[i][a].mVertexId; v.boneWeights[a] = weightsPerVertex[i][a].mWeight /** 255.f*/; } } //push vertex into buffer Vertices.push_back(v); } //extract indices for (uint32 i = 0 ; i < paiMesh->mNumFaces ; i++) { const aiFace& Face = paiMesh->mFaces[i]; //assert(Face.mNumIndices == 3); Indices.push_back((ushort16)Face.mIndices[0]); Indices.push_back((ushort16)Face.mIndices[1]); Indices.push_back((ushort16)Face.mIndices[2]); } //allocate buffer on gpu if(!group->AllocateOnGpuMemory(kGL_BUFFER_USAGE_HINT_STATIC)) { delete group; return false; } //create mesh bounding box group->CreateBoundingBox(); //push mesh group m_pMeshBuffer->AddGroup(group); return true; }
void Model::mesh_create(Scene &scene, const aiNode &node, const BoneForAssimpBone &boneForAssimpBone) { if (!node.mNumMeshes) { return; } std::string node_name = std::string(node.mName.data); Node *mesh_node = lookup_node(node_name, nodes); assert(mesh_node); //std::cout << "Node '" << mesh_node->name << "' has " << node.mNumMeshes << " mesh(es)" << std::endl; for (unsigned int i = 0; i < node.mNumMeshes; i++) { unsigned int meshIndex = node.mMeshes[i]; aiMesh *assimpMesh = assimp_scene->mMeshes[meshIndex]; //std::unique_ptr<Mesh> mesh_ptr(new Mesh()); //Mesh &m = *mesh_ptr; //auto sub_node = std::unique_ptr<Node>(new Node(key + std::string("_") + std::to_string(i))); Node *parent_node = mesh_node; std::string key(node.mName.data); if (node.mNumMeshes > 1) { auto sub_node = scene.node_create(key + std::string("_") + std::to_string(i), parent_node); mesh_node = sub_node; } Mesh &m = *mesh_node->mesh_create(scene); // Point the mesh to the existing material, corresponding to the index mesh_node->material_set(materials[assimpMesh->mMaterialIndex]); //std::cout << "Node: " << mesh_node->name << " has material " << mesh_node->material << " and num faces/vertices: " << assimpMesh->mNumFaces << "/" << assimpMesh->mNumVertices << std::endl; m.num_faces = assimpMesh->mNumFaces; for (unsigned int ii = 0; ii < assimpMesh->mNumFaces; ii++) { const aiFace &face = assimpMesh->mFaces[ii]; if (face.mNumIndices < 3) { std::cout << "Found degenerate polygon" << std::endl; // degenerate polygon -- no need to draw it } else { assert(face.mNumIndices == 3); for (unsigned int ii = 0; ii < face.mNumIndices; ii++) { unsigned int index = face.mIndices[ii]; m.indices.push_back(index); } } } // Add the bones for skinning. std::vector <std::vector<aiVertexWeight>>weightsPerVertex(assimpMesh->mNumVertices); for (unsigned int ib = 0; ib < assimpMesh->mNumBones; ib++) { const aiBone *assimpBone = assimpMesh->mBones[ib]; Bone *bone = lookup_node(assimpBone, boneForAssimpBone); assert(bone); for (unsigned int iw = 0; iw < assimpBone->mNumWeights; iw++) { int id = assimpBone->mWeights[iw].mVertexId; aiVertexWeight vertexWeight; vertexWeight = aiVertexWeight(bone->index_get(), assimpBone->mWeights[iw].mWeight); weightsPerVertex[id].push_back(vertexWeight); } // The bone matrix specifies how to transform the mesh globally to make it // match the bones. This should end up being the same for all the bones that // are driving the same mesh. Unforutnately this assumes that the skeleton // isn't parented to a moving node. To do this more correctly, we'll need // to make a guess at where the skeleton root is and calculate how to // transform mesh coordinates to skeleton root coordinates. The Mesh::model // will then need to be calculated on each frame as // mesh.model = mesh.skeletonNode->transform_global * mesh.skeletonTransform // We can set mesh.skeletonNode to mesh.node and mesh.skeletonTransform // to identity if the mesh has no bones. glm::mat4 m = bone->skinning_matrix_update(); mesh_node->transform_local_current_set(m); //m.model = bone->joint_node->transform_global * bone->offset_matrix; } if (!assimpMesh->mNumBones) { // m.model = glm::rotate(mesh_node->transform_global, -90.f, glm::vec3(1.f, 0.f, 0.f)); // glm::mat4 m = mesh_node->transform_global_get(); // mesh_node->transform_local_current_set(scene, m); //m.model = right_handed_to_left_handed(mesh_node->transform_global); } if (assimpMesh->mNumBones > 0) { m.bone_indices.resize(assimpMesh->mNumVertices); m.bone_weights.resize(assimpMesh->mNumVertices); } for (unsigned int iv = 0; iv < assimpMesh->mNumVertices; iv++) { m.positions.push_back(glm::vec3(assimpMesh->mVertices[iv].x, assimpMesh->mVertices[iv].y, assimpMesh->mVertices[iv].z)); if (assimpMesh->HasNormals()) { m.normals.push_back(glm::vec3(assimpMesh->mNormals[iv].x, assimpMesh->mNormals[iv].y, assimpMesh->mNormals[iv].z)); } if (assimpMesh->HasTangentsAndBitangents()) { m.tangents.push_back(glm::vec3(assimpMesh->mTangents[iv].x, assimpMesh->mTangents[iv].y,assimpMesh->mTangents[iv].z)); m.bitangents.push_back(glm::vec3(assimpMesh->mBitangents[iv].x, assimpMesh->mBitangents[iv].y, assimpMesh->mBitangents[iv].z)); } unsigned int p = 0; while (assimpMesh->HasTextureCoords(p)) { m.texture_st.push_back(glm::vec2(assimpMesh->mTextureCoords[p][iv].x, assimpMesh->mTextureCoords[p][iv].y)); if (p > 0) { std::cout << "Fragmic warning: more than one set of texture coordinates for one mesh" << std::endl; std::cout << "NOT CURRENTLY SUPPORTED!" << std::endl; } p++; } assert(weightsPerVertex[iv].size() <= 3); for (unsigned int a = 0; a < weightsPerVertex[iv].size(); a++) { int id = weightsPerVertex[iv][a].mVertexId; m.bone_indices[iv][a] = id; m.bone_weights[iv][a] = weightsPerVertex[iv][a].mWeight; } } //m.scale_matrix = glm::scale(glm::mat4(1.0f), mesh_node->original_scaling_get()); //mesh_node->mesh_set(mesh_ptr.get()); mesh_node->armature_set(armature_ptr); if (node.mNumMeshes > 1) { // mesh_node->copy_transform_data(*parent_node); //parent_node->child_add(std::move(sub_node), parent_node->tree_level_get() + 1); } //mesh_node->physics_rigidbody_create(scene); //assets.mesh_add(std::move(mesh_ptr)); mesh_node = lookup_node(node_name, nodes); } }