DexModelBase* DexModelMs3dLoader::LoadModel(const char* filename, int32 flag) { getLog()->BeginLog(); int64 Time = getTime()->GetTotalMillSeconds(); getLog()->Log(log_ok, "load ms3d %s...\n", filename); //TODO 把model加入object工程,采用query机制 DexSkinMesh* skinMesh = new DexSkinMesh(); skinMesh->SetMeshType(SkinMeshModelType_MS3D); ifstream inputFile(filename, ios::in | ios::binary | ios::_Nocreate); if (inputFile.fail()) { getLog()->Log(log_error, " load ms3d %s failed!\n"); getLog()->EndLog(); delete skinMesh; return NULL; } inputFile.seekg(0, ios::end); long fileSize = inputFile.tellg(); inputFile.seekg(0, ios::beg); int8 *pBuffer = new int8[fileSize]; inputFile.read((char*)pBuffer, fileSize); inputFile.close(); const int8 *pPtr = pBuffer; const int8 *EndPtr = pBuffer + fileSize; MS3DHeader *pHeader = (MS3DHeader*)pPtr; pPtr += sizeof(MS3DHeader); if (strncmp(pHeader->m_ID, "MS3D000000", 10) != 0) { getLog()->Log(log_error, " load ms3d %s failed! Id error!\n"); getLog()->EndLog(); delete skinMesh; delete[] pBuffer; return NULL; }// "Not a valid Milkshape3D model file." if (pHeader->m_version < 3 || pHeader->m_version > 4) { getLog()->Log(log_error, " load ms3d %s failed! version error!\n"); getLog()->EndLog(); delete skinMesh; return NULL; }// "Unhandled file version. Only Milkshape3D Version 1.3 and 1.4 is supported." ); uint32 nVertices = *(int16*)pPtr; //顶点个数 pPtr += sizeof(int16); MS3DVertex *pVertex = (MS3DVertex*)pPtr; MS3DVertex pVertex22[100]; memcpy(pVertex22, pVertex, sizeof(MS3DVertex)* nVertices); pPtr += sizeof(MS3DVertex)* nVertices; int nTriangles = *(int16*)pPtr; //三角形个数 pPtr += sizeof(int16); MS3DTriangle* Triangles = (MS3DTriangle*)pPtr; pPtr += sizeof(MS3DTriangle)*nTriangles; int nGroups = *(int16*)pPtr; //mesh数量 pPtr += sizeof(int16); for (int i = 0; i < nGroups; i++) { pPtr += sizeof(byte); // flags pPtr += 32; // name int16 iTriangles = *(int16*)pPtr; //这个mesh有多少个三角形 pPtr += sizeof(int16); int16 *pTriangleIndices = (int16*)pPtr; //三角形索引 pPtr += sizeof(int16)* iTriangles; int32 indice_index = 0; DexSkinMesh::DexMesh* mesh = skinMesh->AddMesh(i); //新建mesh DexVector3 tempPos; DexVector3 tempNormal; float tempU, tempV; DexSkinMesh::stMeshVertex tempVertex; for (int j = 0; j < iTriangles; j++) {//解析这个mesh所用到的所有三角形的顶点索引 int triangleIndex = pTriangleIndices[j]; //检测三角形的三个顶点是否可在当前mesh中查找到,需要匹配pos normal uv for (int point = 0; point < 3; ++point) { uint32 iPosIndex = Triangles[triangleIndex].m_vertexIndices[point]; tempPos.Set(pVertex[iPosIndex].m_vertex); tempPos.z *= -1; tempNormal.Set(Triangles[triangleIndex].m_vertexNormals[point]); tempNormal.z *= -1; tempU = Triangles[triangleIndex].m_s[point]; tempV = Triangles[triangleIndex].m_t[point]; bool find = false; for (size_t index = 0; index < mesh->m_vecVertexsBuffer.size(); ++index) { if (mesh->m_vecVertexsBuffer[index].pos == tempPos && mesh->m_vecVertexsBuffer[index].normal == tempNormal && DexMath::Equal(mesh->m_vecVertexsBuffer[index].uv.x, tempU) && DexMath::Equal(mesh->m_vecVertexsBuffer[index].uv.y, tempV)) {//找到已经存在的vertex mesh->AddVertexIndice(index); find = true; break; } } if (!find) {//未找到已存在的,则新建顶点 tempVertex.pos = (tempPos); tempVertex.normal = (tempNormal); tempVertex.uv = DexVector2(tempU, tempV); tempVertex.color = DEXCOLOR_WHITE; tempVertex.JointIndex[0] = pVertex[iPosIndex].m_boneID +1;//第0个是root tempVertex.JointWeights[0] = 1.0f; mesh->AddVertexIndice(mesh->m_vecVertexsBuffer.size()); mesh->m_vecVertexsBuffer.push_back(tempVertex); } } } char materialIndex = *(char*)pPtr; pPtr += sizeof(char); mesh->m_iMaterialId = materialIndex; mesh->m_iTextureId = materialIndex; } int nMaterials = *(int16*)pPtr; pPtr += sizeof(int16); for (int i = 0; i < nMaterials; i++) { MS3DMaterial *pMaterial = (MS3DMaterial*)pPtr; DexMaterial material; dexstrcpy(material.name, pMaterial->m_name); material.diffuse.Set(pMaterial->m_diffuse[0], pMaterial->m_diffuse[1], pMaterial->m_diffuse[2], pMaterial->m_diffuse[3]); material.ambient.Set(pMaterial->m_ambient[0], pMaterial->m_ambient[1], pMaterial->m_ambient[2], pMaterial->m_ambient[3]); material.specular.Set(pMaterial->m_specular[0], pMaterial->m_specular[1], pMaterial->m_specular[2], pMaterial->m_specular[3]); material.emissive.Set(pMaterial->m_emissive[0], pMaterial->m_emissive[1], pMaterial->m_emissive[2], pMaterial->m_emissive[3]); material.power = pMaterial->m_shininess; //还有几个material目前还没支持 char* filename = (char*)malloc(strlen(pMaterial->m_texture) + 1); strcpy(filename, pMaterial->m_texture); skinMesh->AddMaterial(material); skinMesh->AddTexture(filename); pPtr += sizeof(MS3DMaterial); _SafeFree(filename); } float32 framePerSecond = *(float32*)pPtr; pPtr += sizeof(float32); float32 currentTime = *(float32*)pPtr; pPtr += sizeof(float32); float32 totalFrames = *(float32*)pPtr; pPtr += sizeof(float32); int16 jointCount = *(int16*)pPtr; pPtr += sizeof(int16); DexMatrix4x4 baseMatrix; DexMatrix4x4 matrix; DexMatrix4x4 matrixRotateX; DexMatrix4x4 matrixRotateY; DexMatrix4x4 matrixRotateZ; float32 AniTime = 0.0f; float32 minAniTime = 0; for (int i = 1; i <= jointCount; ++i) { baseMatrix.Identity(); matrixRotateX.Identity(); matrixRotateY.Identity(); matrixRotateZ.Identity(); MS3DJoint *ms3dJoint = (MS3DJoint*)pPtr; baseMatrix.RotateX(-ms3dJoint->m_rotation[0]); baseMatrix.RotateY(-ms3dJoint->m_rotation[1]); baseMatrix.RotateZ(ms3dJoint->m_rotation[2]); baseMatrix.Translate(ms3dJoint->m_translation[0], ms3dJoint->m_translation[1], -ms3dJoint->m_translation[2]); DexSkinMesh::Joint* newJoint = skinMesh->FindJoint(i); if (newJoint == NULL) newJoint = skinMesh->AddJoint(i); skinMesh->SetJointInfo(newJoint->id, string(ms3dJoint->m_name), string(ms3dJoint->m_parentName), baseMatrix); int rotationFrames = ms3dJoint->m_numRotationKeyframes; int positionFrames = ms3dJoint->m_numTranslationKeyframes; pPtr += sizeof(MS3DJoint); std::vector<MS3DKeyframe> vec_rotation; std::vector<MS3DKeyframe> vec_position; for (int j = 0; j < rotationFrames; ++j) { MS3DKeyframe* key = (MS3DKeyframe*)pPtr; vec_rotation.push_back(*key); if (key->m_time > AniTime) AniTime = key->m_time; pPtr += sizeof(MS3DKeyframe); } for (int j = 0; j < positionFrames; ++j) { MS3DKeyframe* key = (MS3DKeyframe*)pPtr; vec_position.push_back(*key); if (key->m_time > AniTime) AniTime = key->m_time; pPtr += sizeof(MS3DKeyframe); } //找到有变换的那一帧作为动作的有效开始时间 if (vec_rotation.size() != 0) { minAniTime = vec_rotation[0].m_time; } if (vec_position.size() != 0 && vec_position[0].m_time < minAniTime) { minAniTime = vec_position[0].m_time; } for (size_t k = 0; k < vec_rotation.size(); ++k) { float32 time = vec_rotation[k].m_time; DexVector3 trans; for (size_t t = 0; t < vec_position.size(); ++t) { if (DexMath::Equal(time, vec_position[t].m_time)) {//这一帧还有平移 trans.Set(vec_position[t].m_parameter[0], vec_position[t].m_parameter[1], -vec_position[t].m_parameter[2]); break; } } matrix.Identity(); matrix.RotateX(-vec_rotation[k].m_parameter[0]); matrix.RotateY(-vec_rotation[k].m_parameter[1]); matrix.RotateZ(vec_rotation[k].m_parameter[2]); matrix.Translate(trans); skinMesh->AddJointKeyFrame(newJoint->str_name, time * 1000, matrix * baseMatrix); } for (size_t k = 0; k < vec_position.size(); ++k) { float32 time = vec_position[k].m_time; DexVector3 trans(vec_position[k].m_parameter[0], vec_position[k].m_parameter[1], -vec_position[k].m_parameter[2]); bool _continue; for (size_t t = 0; t < vec_rotation.size(); ++t) { if (DexMath::Equal(time, vec_rotation[t].m_time)) {//找了有旋转的一帧,已经被处理过 _continue = true; break; } } if (_continue) continue; matrix.Identity(); matrix.Translate(trans); skinMesh->AddJointKeyFrame(newJoint->str_name, time * 1000, matrix * baseMatrix); } } //map<int16, Vector<JointVertex>>::iterator ite = joint_Vertexs.find(-1); //if (ite != joint_Vertexs.end()) //{//处理没有绑定的顶点 // for (int v = 0; v < ite->second.size(); ++v) // { // skinMesh->AddVertexJointInfo(ite->second[v].vertexIndex, skinMesh->m_pRootJoint->id, 1.0f); // } //} if (pPtr < EndPtr && pHeader->m_version == 4) { int32 subVersion = *(int32*)pPtr; // comment subVersion, always 1 pPtr += sizeof(subVersion); for (int i = 0; i < 4; ++i) { uint32 numComment = *(uint32*)pPtr; pPtr += sizeof(numComment); for (uint32 j = 0; j < numComment; ++j) { // according to scorpiomidget this field does // not exist for model comments. So avoid to // read it if (i != 3) { pPtr += sizeof(int32); //index } int32 commentLength = *(int32*)pPtr; pPtr += sizeof(commentLength); pPtr += commentLength; } } if (pPtr < EndPtr) { subVersion = *(int32*)pPtr; //vertex subversion pPtr += sizeof(subVersion); // read vertex weights, ignoring data 'extra' from 1.8.2 int16 offset = subVersion == 1 ? 6 : 10; for (int index = 0; index < nVertices; ++index) { MS3DVertexWeights* vertexEx = (MS3DVertexWeights*)pPtr; for (int boneIndex = 0; boneIndex < 3; ++boneIndex) { //if (vertexEx->boneIds[boneIndex] != -1) } pPtr += offset; } } if (pPtr < EndPtr) { subVersion = *(int32*)pPtr; //joint subversion pPtr += sizeof(subVersion); // skip joint colors pPtr += 3 * sizeof(float32)*jointCount; } if (pPtr < EndPtr) { subVersion = *(int32*)pPtr; //model subversion pPtr += sizeof(subVersion); } } delete[] pBuffer; skinMesh->SetMaxAniTime(AniTime * 1000); skinMesh->SetAnimateTime(minAniTime * 1000, AniTime * 1000); //skinMesh->CalculateVertex(); Time = getTime()->GetTotalMillSeconds() - Time; getLog()->Log(log_ok, "load ms3d %s ok, use time %d ms\n", filename, Time); getLog()->EndLog(); return skinMesh; }
void SafeFree (void** freeThis) { _SafeFree(*freeThis); *freeThis = NULL; }