void Skeleton::InitMesh(const aiMesh* paiMesh, unsigned int index) { for (unsigned int i = 0; i < paiMesh->mNumBones; i++) { unsigned int boneIndex = 0; string boneName(paiMesh->mBones[i]->mName.data); if (skeletalBones.find(boneName) == skeletalBones.end()) { // Allocate an index for a new bone boneIndex = nrBones; BoneInfo bi; assimp::CopyMatix(paiMesh->mBones[i]->mOffsetMatrix, bi.BoneOffset); boneInfo.push_back(bi); skeletalBones[boneName] = boneIndex; nrBones++; } else { boneIndex = skeletalBones[boneName]; } for (unsigned int j = 0; j < paiMesh->mBones[i]->mNumWeights; j++) { //uint VertexID = meshEntries[index]->baseVertex + paiMesh->mBones[i]->mWeights[j].mVertexId; float weight = paiMesh->mBones[i]->mWeights[j].mWeight; //boneData[VertexID].AddBoneData(boneIndex, weight); } } }
void Animation::Mesh::LoadBones(unsigned int meshIndex, const aiMesh* mesh, std::vector<VertexInfo>& vertices) { for (unsigned int i = 0; i < mesh->mNumBones; i++) { unsigned int boneIndex = 0; std::string boneName(mesh->mBones[i]->mName.data); if (m_boneMapping.find(boneName) == m_boneMapping.end()) { // Allocate an index for a new bone boneIndex = m_numBones; m_numBones++; BoneInfo bi; m_boneInfo.push_back(bi); Assign(m_boneInfo[boneIndex].boneOffset, mesh->mBones[i]->mOffsetMatrix); m_boneMapping[boneName] = boneIndex; } else { boneIndex = m_boneMapping[boneName]; } for (unsigned int j = 0; j < mesh->mBones[i]->mNumWeights; j++) { unsigned int vertexID = m_meshes[meshIndex].baseVertex + mesh->mBones[i]->mWeights[j].mVertexId; float weight = mesh->mBones[i]->mWeights[j].mWeight; vertices[vertexID].boneData.AddBoneData(boneIndex, weight); } } }
void Mesh::loadBones(unsigned int _meshIndex, const aiMesh* _mesh, std::vector<VertexBoneData>& o_bones) { for (unsigned int i = 0 ; i < _mesh->mNumBones ; ++i) { unsigned int BoneIndex = 0; std::string boneName(_mesh->mBones[i]->mName.data); if (m_boneMapping.find(boneName) == m_boneMapping.end()) { // Allocate an index for a new bone BoneIndex = m_numBones; m_numBones++; BoneInfo bi; m_boneInfo.push_back(bi); // this is the Matrix that transforms from mesh space to bone space in bind pose. m_boneInfo[BoneIndex].boneOffset = AIU::aiMatrix4x4ToNGLMat4(_mesh->mBones[i]->mOffsetMatrix); m_boneMapping[boneName] =BoneIndex; } else { BoneIndex = m_boneMapping[boneName]; } for (unsigned int j = 0 ; j < _mesh->mBones[i]->mNumWeights ; ++j) { unsigned int VertexID = m_entries[_meshIndex].BaseVertex + _mesh->mBones[i]->mWeights[j].mVertexId; float Weight = _mesh->mBones[i]->mWeights[j].mWeight; o_bones[VertexID].addBoneData(BoneIndex, Weight); } } }
void ASmrActor::TransformBone(UPoseableMeshComponent* mesh, SMRJoint* bone) { //Build the local transform for this bone FTransform finalTransform; finalTransform.SetLocation(USmrFunctions::RightCoordToLeft(bone->getPosition())); finalTransform.SetRotation(USmrFunctions::RightCoordToLeft(bone->getOrientation())); if (bone->hasParent()) { //Get the component space transform for the parent bone FName parentName(bone->getParentName().c_str()); FTransform parentTransform = mesh->GetBoneTransformByName(parentName, EBoneSpaces::ComponentSpace); //Convert local transform to component space finalTransform *= parentTransform; } //Convert quaternion to Euler angles and apply to the mesh FVector euler = finalTransform.GetRotation().Euler(); FRotator rotator = FRotator::MakeFromEuler(euler); FName boneName(bone->getName().c_str()); mesh->SetBoneRotationByName(boneName, rotator, EBoneSpaces::ComponentSpace); }
void AMWBattery::PostInitializeComponents() { Super::PostInitializeComponents(); for (uint32 i = 0; i < kMaxLEDs; ++i) { // Attach to its point on the battery mesh FString name("led"); name.AppendInt(i + 1); FName boneName(*name); LEDs[i]->AttachTo(BatteryMesh, boneName, EAttachLocation::SnapToTarget); // Assign common LED static mesh and create dynamic material. LEDs[i]->StaticMesh = LEDMesh; LED_MIDs[i] = LEDs[i]->CreateAndSetMaterialInstanceDynamic(0); } BatteryMID = BatteryMesh->CreateAndSetMaterialInstanceDynamic(0); CurrentCharge = Capacity; CurrentPower = NormalPower; UpdateLEDs(); }
void WeightTableWindow::PaintWeightListLabel() { HDC hdc; PAINTSTRUCT ps; BeginPaint(hWeightListLabel,&ps); EndPaint(hWeightListLabel,&ps); iWeightListLabelBuf->Erase(); hdc = iWeightListLabelBuf->GetDC(); WINDOWPLACEMENT winPos; GetWindowPlacement(hWeightListLabel , &winPos); HFONT hOldFont = (HFONT)SelectObject(hdc, hFixedFont); //5.1.01 int justify = TEXT_LEFT_JUSTIFIED; if (GetRightJustify()) justify = TEXT_RIGHT_JUSTIFIED; if (GetFlipFlopUI()) { //paint in names //draw bone name labels //paint in bone names int y = 0; int x = 0; SetTextColor(hdc,textColor); for (int j = 0; j < numberOfRows; j++) { //if not affacted //if not get weight TSTR boneName("-"); if ((j+firstRow) < activeBones.Count()) { int currentBone = activeBones[j+firstRow]; if ((mod) && (currentBone < mod->BoneData.Count())) { if (mod->BoneData[currentBone].Node) { boneName.printf("%s",mod->BoneData[currentBone].Node->GetName()); PaintCellName(hdc, x, y, buttonWidth, (mod->ModeBoneIndex == currentBone), justify,boneName); y+= textHeight; } } } } } else { int y = 0; int x = 0; //5.1.01 if (justify == TEXT_LEFT_JUSTIFIED) { for (int j = 0; j < numberOfColumns; j++) { //if not affacted //if not get weight TSTR boneName("-"); if ((j+firstColumn) < activeBones.Count()) { int currentBone = activeBones[j+firstColumn]; if ((mod) && (currentBone < mod->BoneData.Count())) { if (mod->BoneData[currentBone].Node) { boneName.printf("%s",mod->BoneData[currentBone].Node->GetName()); //5.1.01 PaintCellName(hdc, x, y,buttonWidth, (mod->ModeBoneIndex == currentBone), justify,boneName); x+= buttonWidth; } } } } } else //5.1.01 { int ct = 0; for (int j = 0; j < numberOfColumns; j++) { if ((j+firstColumn) < activeBones.Count()) { x += buttonWidth ; ct++; } } x -=buttonWidth; for (j = (numberOfColumns-1); j >= 0; j--) { //if not affacted //if not get weight TSTR boneName("-"); if ((j+firstColumn) < activeBones.Count()) { int currentBone = activeBones[j+firstColumn]; if ((mod) && (currentBone < mod->BoneData.Count())) { if (mod->BoneData[currentBone].Node) { boneName.printf("%s",mod->BoneData[currentBone].Node->GetName()); //5.1.01 PaintCellName(hdc, x, y,buttonWidth, (mod->ModeBoneIndex == currentBone), justify,boneName); x-= buttonWidth; } } } } } } BlackBorder(hdc, hWeightListLabel); SelectObject(hdc,GetStockObject(BLACK_PEN)); SelectObject(hdc, hOldFont); iWeightListLabelBuf->Blit(); }
// Imperfect function but hey it's just for testing! Mesh* Assets::loadMeshFromFile(std::string &filePath) { Assimp::Importer importer; const aiScene* scene = importer.ReadFile( filePath, aiProcess_CalcTangentSpace | aiProcess_Triangulate | aiProcess_JoinIdenticalVertices | aiProcess_SortByPType); // If the import failed, report it if( !scene) { std::cout << "Error Loading : " << importer.GetErrorString() << "\n"; return nullptr; } aiMatrix4x4 globalInverseTransform = scene->mRootNode->mTransformation; globalInverseTransform.Inverse(); // Have to manually convert arrays of assimp's own Vector3 class to vectors of glm::vec3 to make it work for now // Later we can implement faster method that uses the array to directly set vao (I hope...) std::vector<glm::vec3> verts; std::vector<unsigned int> indices; std::vector<glm::vec3> normals; std::vector<glm::vec2> uvs; std::vector<glm::vec3> colours; std::vector<glm::vec3> tangents; std::vector<glm::vec3> biTangents; // Assimp conversion here! aiMesh* loadedMesh = scene->mMeshes[0]; std::map<std::string, int> boneMapping; // Lovely bone info struct BoneVertexInfo { int numWeights; glm::ivec4 boneID; glm::vec4 boneWeight; void addWeight(int boneIDZ, float weight) { if(numWeights >= 4) return; boneID[numWeights] = boneIDZ; boneWeight[numWeights] = weight; numWeights +=1; } }; std::vector<BoneVertexInfo> boneInfos; for(int i = 0; i < loadedMesh->mNumVertices; ++i) { verts.push_back(glm::vec3(loadedMesh->mVertices[i].x, loadedMesh->mVertices[i].y, loadedMesh->mVertices[i].z)); if(loadedMesh->HasNormals()) normals.push_back(glm::vec3(loadedMesh->mNormals[i].x, loadedMesh->mNormals[i].y, loadedMesh->mNormals[i].z)); if(loadedMesh->HasTextureCoords(0)) uvs.push_back(glm::vec2(loadedMesh->mTextureCoords[0][i].x, loadedMesh->mTextureCoords[0][i].y)); if(loadedMesh->HasTangentsAndBitangents()) { tangents.push_back (glm::vec3(loadedMesh->mTangents[i].x, loadedMesh->mTangents[i].y, loadedMesh->mTangents[i].z)); biTangents.push_back(glm::vec3(loadedMesh->mBitangents[i].x,loadedMesh->mBitangents[i].y,loadedMesh->mBitangents[i].z)); } colours.push_back(glm::vec3(1.0f, 1.0f, 1.0f)); // Push empty values into boneID and boneWeight vectors BoneVertexInfo boneInfo; boneInfo.numWeights = 0; for(int j = 0; j < 4; ++j) { boneInfo.boneID[j] = 0; boneInfo.boneWeight[j] = 0; } boneInfos.push_back(boneInfo); } for(int i = 0; i < loadedMesh->mNumFaces; ++i) { for(int j = 0; j < loadedMesh->mFaces[i].mNumIndices; ++j) { indices.push_back(loadedMesh->mFaces[i].mIndices[j]); } } // This is where the fun starts for(int i = 0; i < loadedMesh->mNumBones; ++i) // for each bone { std::string boneName(loadedMesh->mBones[i]->mName.data); boneMapping.emplace(boneName, i); } /* for(int i = 0; i < loadedMesh->mNumBones; ++i) // for each bone { std::string boneName(loadedMesh->mBones[i]->mName.data); std::map<std::string, int>::iterator it = boneMapping.find(boneName); int boneID = it->second; // Populate BoneID and BoneWeight vectors for(int j = 0; j < loadedMesh->mBones[i]->mNumWeights; ++j) // for each weight { float weight = loadedMesh->mBones[i]->mWeights[j].mWeight; int vertexID = loadedMesh->mBones[i]->mWeights[j].mVertexId; boneInfos[vertexID].addWeight(boneID, weight); if(weight != 0) { //std::cout << "HELLO!"; } } } */ aiMatrix4x4 BoneOffset; std::vector<aiMatrix4x4> boneDataOffset; for(int i = 0; i < loadedMesh->mNumBones; ++i) // for each bone { std::string boneName(loadedMesh->mBones[i]->mName.data); std::map<std::string, int>::iterator it = boneMapping.find(boneName); int boneID = it->second; boneDataOffset.push_back(BoneOffset); boneDataOffset[i] = loadedMesh->mBones[i]->mOffsetMatrix; // Populate BoneID and BoneWeight vectors for(int j = 0; j < loadedMesh->mBones[i]->mNumWeights; ++j) // for each weight { float weight = loadedMesh->mBones[i]->mWeights[j].mWeight; int vertexID = loadedMesh->mBones[i]->mWeights[j].mVertexId; boneInfos[vertexID].addWeight(boneID, weight); if(weight != 0) { //std::cout << "HELLO!"; } } } /* int bonesCount = 0; for(int i = 0; i < loadedMesh->mNumBones; ++i) // for each bone { std::string boneName(loadedMesh->mBones[i]->mName.data); // Puts in map if not there std::map<std::string, int>::iterator it; it = boneMapping.find(boneName); if(it == boneMapping.end()) // then it can't find it { boneMapping.emplace(boneName, bonesCount); bonesCount ++; } // Get bone index GLint boneIndex = boneMapping.find(boneName)->second; // Store mOffset matrix from Assimp aiBone class? If we need it... // TO DO // Populate BoneID and BoneWeight vectors for(int j = 0; j < loadedMesh->mBones[i]->mNumWeights; ++j) // for each { int vertexID = loadedMesh->mBones[i]->mWeights[j].mVertexId; int weigthNum = boneInfos[vertexID].numWeights; // the number of the weight, up to 3 (coz 4 possible) if(weigthNum >= 4) continue; //too many bones!!! boneInfos[vertexID].numWeights += 1; // add one to num of weights boneInfos[vertexID].boneID[weigthNum] = boneIndex; boneInfos[vertexID].boneWeight[weigthNum] = loadedMesh->mBones[i]->mWeights[j].mWeight; } } */ // This is a horrible stupid way of doing it but can change once you know it works std::vector<glm::ivec4> boneIDs; std::vector<glm::vec4> boneWeights; for(int i = 0; i < boneInfos.size(); ++i) { boneIDs.push_back(boneInfos[i].boneID); boneWeights.push_back(boneInfos[i].boneWeight); } // end horrible way of doing things // Now set mesh properties via vector Mesh* mesh = new Mesh(); mesh->generateBuffers(); mesh->setVerts(verts); mesh->setIndices(indices); mesh->setNormals(normals); mesh->setUvs(uvs); mesh->setColours(colours); mesh->setTangents(tangents); mesh->setBiTangents(biTangents); mesh->setBoneMap(boneMapping); mesh->setBones(boneIDs, boneWeights); mesh->setBoneOffset(boneDataOffset); mesh->setInverseTransform(globalInverseTransform); mesh->setNumJoints(loadedMesh->mNumBones); return mesh; }
Mesh* ModelInterface::loadMesh(aiMesh* ai_mesh, aiMaterial* ai_material, const int index) { Q_UNUSED(index) Mesh* mesh = new Mesh(); QVector3D* vertices = new QVector3D[ai_mesh->mNumVertices]; QVector3D* normals = new QVector3D[ai_mesh->mNumVertices]; QVector3D* tangent = new QVector3D[ai_mesh->mNumVertices]; QVector2D* texCoords = new QVector2D[ai_mesh->mNumVertices]; QVector4D* boneIDs = new QVector4D[ai_mesh->mNumVertices]; QVector4D* weight = new QVector4D[ai_mesh->mNumVertices]; QVector<uint> indices; if(ai_mesh->HasBones() && bones) { for(uint i = 0; i < ai_mesh->mNumBones; ++i) { for(uint j = 0; j < ai_mesh->mBones[i]->mNumWeights; ++j) { QString boneName(ai_mesh->mBones[i]->mName.data); aiVertexWeight w = ai_mesh->mBones[i]->mWeights[j]; int vertexId = w.mVertexId; float weightValue = w.mWeight; int boneID = bones->getBone(boneName)->getId(); addWeightData(&boneIDs[vertexId], &weight[vertexId], boneID, weightValue); } } } for(uint i = 0; i < ai_mesh->mNumVertices; ++i) { vertices[i] = QVector3D(ai_mesh->mVertices[i].x, ai_mesh->mVertices[i].y, ai_mesh->mVertices[i].z); normals[i] = QVector3D(ai_mesh->mNormals[i].x, ai_mesh->mNormals[i].y, ai_mesh->mNormals[i].z); if(ai_mesh->mTangents) tangent[i] = QVector3D(ai_mesh->mTangents[i].x, ai_mesh->mTangents[i].y, ai_mesh->mTangents[i].z); else tangent[i] = QVector3D(1.0f, 0.0f, 0.0f); if(ai_mesh->mTextureCoords[0]) texCoords[i] = QVector2D(ai_mesh->mTextureCoords[0][i].x, ai_mesh->mTextureCoords[0][i].y); else texCoords[i] = QVector2D(0.0f, 0.0f); } for(uint i = 0; i < ai_mesh->mNumFaces; ++i) { aiFace face = ai_mesh->mFaces[i]; for(uint j = 0; j < face.mNumIndices; ++j) indices.push_back(face.mIndices[j]); } loadMaterial(ai_material, mesh); mesh->createVertexArrayObject(); mesh->createBuffer(Mesh::Vertices, vertices, sizeof(QVector3D) * ai_mesh->mNumVertices); mesh->createBuffer(Mesh::Normals, normals, sizeof(QVector3D) * ai_mesh->mNumVertices); mesh->createBuffer(Mesh::TexCoords, texCoords, sizeof(QVector2D) * ai_mesh->mNumVertices); mesh->createBuffer(Mesh::Tangent, tangent, sizeof(QVector3D) * ai_mesh->mNumVertices); mesh->createBuffer(Mesh::Bones, boneIDs, sizeof(QVector4D) * ai_mesh->mNumVertices); mesh->createBuffer(Mesh::Weight, weight, sizeof(QVector4D) * ai_mesh->mNumVertices); mesh->createBuffer(Mesh::Index, indices.data(), sizeof(int) * indices.size()); mesh->setNumFaces(indices.size()); delete[] vertices; delete[] normals; delete[] tangent; delete[] texCoords; delete[] weight; delete[] boneIDs; return mesh; }