std::shared_ptr<const MstData> MstData::FromJsonValue(const QJsonValue& value) { auto mst_data = std::make_shared<MstData>(); auto obj = value.toObject(); if (!obj["api_mst_ship"].isArray()) throw BadJsonValue(); if (!obj["api_mst_slotitem"].isArray()) throw BadJsonValue(); for (auto& x : obj["api_mst_ship"].toArray()) { if (!x.isObject()) throw BadJsonValue(); auto x_obj = x.toObject(); MstShip ship; ship.id = GetInt(x_obj, "api_id"); ship.name = GetString(x_obj, "api_name"); mst_data->mst_ship.emplace(ship.id, ship); } for (auto& x : obj["api_mst_slotitem"].toArray()) { if (!x.isObject()) throw BadJsonValue(); auto x_obj = x.toObject(); MstSlotItem slot_item; slot_item.id = GetInt(x_obj, "api_id"); slot_item.name = GetString(x_obj, "api_name"); slot_item.type = GetIntArray(x_obj, "api_type"); mst_data->mst_slot_item.emplace(slot_item.id, slot_item); } return std::const_pointer_cast<const MstData>(mst_data); }
Ship Ship::FromJsonValue(const QJsonValue& value) { Ship ship; auto obj = value.toObject(); ship.id = GetInt(obj, "api_id"); ship.ship_id = GetInt(obj, "api_ship_id"); ship.lv = GetInt(obj, "api_lv"); ship.slot = GetIntArray(obj, "api_slot"); return ship; }
inline void SerializeX(VArchive &ar) { if (ar.IsLoading()) { int iBitCount; ar >> iBitCount; AllocateBitfield(iBitCount); const int iIntCount = GetIntCount(); if (iIntCount>0) ar.Read(GetIntArray(),iIntCount*sizeof(int),"i",iIntCount); } else
const char *ParseNormals(const char *pText, F3DSubObject &sub, const MFMatrix &mat, int numFaces, int *pMatFaces) { SkipToken(pText, "{"); // get num positions int numNormals = GetInt(pText, &pText); sub.normals.resize(numNormals); // read positions for(int a=0; a<numNormals; a++) { sub.normals[a].x = GetFloat(pText, &pText); sub.normals[a].y = GetFloat(pText, &pText); sub.normals[a].z = GetFloat(pText, &pText); sub.normals[a] = ApplyMatrix3(sub.normals[a], mat); sub.normals[a].Normalise3(); if(a < numNormals-1) SkipToken(pText, ","); } SkipToken(pText, ";"); // get num faces int numNormalFaces = GetInt(pText, &pText); MFDebug_Assert(numNormalFaces == numFaces, "Number of normal faces does not match the number of faces in the mesh."); // read faces int face[16], numVerts[16]; MFZeroMemory(numVerts, sizeof(numVerts)); for(int a=0; a<numNormalFaces; a++) { int matSub = pMatFaces ? pMatFaces[a] : 0; int numPoints = GetInt(pText, &pText); GetIntArray(pText, face, numPoints, &pText); for(int b=0; b<numPoints; b++) sub.matSubobjects[matSub].vertices[numVerts[matSub]+b].normal = face[b]; numVerts[matSub] += numPoints; if(a < numNormalFaces-1) SkipToken(pText, ","); } SkipToken(pText, ";"); SkipToken(pText, "}"); return pText; }
const char *ParseMesh(const char *pText, const MFMatrix &mat, const char *pFrameName) { // read name char meshName[64]; const char *pMeshName = GetNextToken(pText, &pText, meshName); if(!MFString_Compare(pMeshName, "{")) pMeshName = pFrameName; else SkipToken(pText, "{"); if(MFString_CaseCmpN(pMeshName, "m_", 2)) { // not a mesh! SkipSection(pText); return pText; } F3DMeshChunk *pMesh = pModel->GetMeshChunk(); F3DSubObject &sub = pMesh->subObjects.push(); MFString_Copy(sub.name, pMeshName); // get num positions int numPositions = GetInt(pText, &pText); sub.positions.resize(numPositions); // read positions for(int a=0; a<numPositions; a++) { sub.positions[a].x = GetFloat(pText, &pText); sub.positions[a].y = GetFloat(pText, &pText); sub.positions[a].z = GetFloat(pText, &pText); sub.positions[a] = ApplyMatrixH(sub.positions[a], mat); if(a < numPositions-1) SkipToken(pText, ","); } SkipToken(pText, ";"); // get num faces int numFaces = GetInt(pText, &pText); // see if we have a material face mapping int *pMatFaces = ParseMaterialList(pText, sub, numFaces); // read faces int face[16], numVerts[16], numTris[16]; MFZeroMemory(numVerts, sizeof(numVerts)); MFZeroMemory(numTris, sizeof(numTris)); for(int a=0; a<numFaces; a++) { int matSub = pMatFaces ? pMatFaces[a] : 0; F3DMaterialSubobject &matsub = sub.matSubobjects[matSub]; int numPoints = GetInt(pText, &pText); MFDebug_Assert(numPoints < 16, "Exceeded maximum 16 points per face..."); GetIntArray(pText, face, numPoints, &pText); int firstVert = numVerts[matSub]; numVerts[matSub] += numPoints; if(matsub.vertices.size() < numVerts[matSub]) matsub.vertices.resize(numVerts[matSub]); int firstTri = numTris[matSub]; numTris[matSub] += numPoints-2; if(matsub.triangles.size() < numTris[matSub]) matsub.triangles.resize(numTris[matSub]); for(int b=0; b<numPoints; b++) matsub.vertices[firstVert+b].position = face[b]; for(int b=0; b<numPoints-2; b++) { matsub.triangles[firstTri+b].v[0] = firstVert+0; matsub.triangles[firstTri+b].v[1] = firstVert+b+1; matsub.triangles[firstTri+b].v[2] = firstVert+b+2; } if(a < numFaces-1) SkipToken(pText, ","); } SkipToken(pText, ";"); const char *pTok = GetNextToken(pText, &pText); while(MFString_Compare(pTok, "}")) { if(!MFString_Compare(pTok, "MeshMaterialList")) { SkipSection(pText); } else if(!MFString_Compare(pTok, "MeshNormals")) { pText = ParseNormals(pText, sub, mat, numFaces, pMatFaces); } else if(!MFString_Compare(pTok, "MeshTextureCoords")) { pText = ParseTexCoords(pText, sub, numPositions); } else if(!MFString_Compare(pTok, "MeshVertexColors")) { pText = ParseColours(pText, sub, numPositions); } else if(!MFString_Compare(pTok, "XSkinMeshHeader")) { SkipToken(pText, "{"); // get num positions int nMaxSkinWeightsPerVertex = GetInt(pText, &pText); int nMaxSkinWeightsPerFace = GetInt(pText, &pText); int nBones = GetInt(pText, &pText); // not yet sure how this helps... /* for(int m=0; m<sub.matSubobjects.size(); m++) { sub.matSubobjects[m].numBones = nBones; } */ SkipToken(pText, "}"); } else if(!MFString_Compare(pTok, "SkinWeights")) { pText = ParseSkinWeights(pText, sub, numPositions); } else if(!MFString_Compare(pTok, "DeclData")) { SkipSection(pText); } else { MFDebug_Warn(4, MFStr("Unknown token '%s'\n", pTok)); SkipSection(pText); } pTok = GetNextToken(pText, &pText); } // we should order the bone weights into the most to least weighting. return pText; }
const char *ParseSkinWeights(const char *pText, F3DSubObject &sub, int numPositions) { SkipToken(pText, "{"); const char *pName = GetString(pText, &pText); // get num weights int numWeights = GetInt(pText, &pText); if(numWeights > 0) MFDebug_Assert(numWeights == numPositions, "Number of weights's does not match the number of verts in the mesh."); int *pIndices = numWeights > 0 ? (int*)MFHeap_Alloc(sizeof(int) * numWeights) : NULL; GetIntArray(pText, pIndices, numWeights, &pText); float *pWeights = numWeights > 0 ? (float*)MFHeap_Alloc(sizeof(float) * numWeights) : NULL; GetFloatArray(pText, pWeights, numWeights, &pText); MFMatrix matrixOffset; GetFloatArray(pText, (float*)&matrixOffset, 16, &pText); SkipToken(pText, ";"); SkipToken(pText, "}"); if(numWeights > 0) { // now we want to do something with all this data... F3DSkeletonChunk *pSC = pModel->GetSkeletonChunk(); int boneID = pSC->FindBone(pName); // if boneID == -1 we dont want to process this data if(boneID == -1) return pText; // check weights are sequential for(int a=0; a<numWeights; a++) MFDebug_Assert(a == pIndices[a], "Weight array is not sequential!"); for(int a=0; a<sub.matSubobjects.size(); a++) ++sub.matSubobjects[a].numBones; // map to faces for(int m=0; m<sub.matSubobjects.size(); m++) { int totalVerts = sub.matSubobjects[m].vertices.size(); for(int a=0; a<totalVerts; a++) { F3DVertex &v = sub.matSubobjects[m].vertices[a]; int i = v.position; const int numBones = sizeof(v.bone)/sizeof(v.bone[0]); if(pWeights[i] != 0.0f) { for(int b=0; b<numBones; b++) { if(v.bone[b] == -1) { v.weight[b] = pWeights[i]; v.bone[b] = boneID; pSC->bones[boneID].bIsSkinned = true; sub.matSubobjects[m].maxWeights = MFMax(sub.matSubobjects[m].maxWeights, b+1); break; } } } } } } return pText; }
int* ParseMaterialList(const char *pText, F3DSubObject &sub, int numFaces) { int *pMatFaces = NULL; const char *pMatList = FindSectionInScope(pText, "MeshMaterialList"); if(pMatList) { SkipToken(pMatList, "MeshMaterialList"); SkipToken(pMatList, "{"); int numMats = GetInt(pMatList, &pMatList); MFDebug_Assert(numMats < 16, "Exceeded maximum 16 materials per subobject..."); int numMatFaces = GetInt(pMatList, &pMatList); MFDebug_Assert(numMatFaces == numFaces, "Number of material faces does not match number of mesh faces"); pMatFaces = (int*)MFHeap_Alloc(sizeof(int)*numMatFaces); GetIntArray(pMatList, pMatFaces, numMatFaces, &pMatList); // process materials... const char *pToken = GetNextToken(pMatList, &pMatList); // MFDebug_Assert(!MFString_Compare(pToken, ";"), "Value is not terminated with a semicolon.\n"); if(!MFString_Compare(pToken, ";")) pToken = GetNextToken(pMatList, &pMatList); while(MFString_Compare(pToken, "}")) { if(!MFString_Compare(pToken, "Material")) { const char *pMatName = GetNextToken(pMatList, &pToken); if(MFString_Compare(pMatName, "{")) pMatList = pToken; else pMatName = "Unknown Material"; int matID = pModel->GetMaterialChunk()->GetMaterialIndexByName(pMatName); F3DMaterialSubobject &matSub = sub.matSubobjects.push(); if(matID != -1) { matSub.materialIndex = matID; SkipSection(pMatList); } else { matSub.materialIndex = pModel->GetMaterialChunk()->materials.size(); F3DMaterial &mat = pModel->GetMaterialChunk()->materials.push(); MFString_CopyN(mat.name, pMatName, 64); SkipToken(pMatList, "{"); mat.diffuse.x = GetFloat(pMatList, &pMatList); mat.diffuse.y = GetFloat(pMatList, &pMatList); mat.diffuse.z = GetFloat(pMatList, &pMatList); mat.diffuse.w = GetFloat(pMatList, &pMatList); SkipToken(pMatList, ";"); mat.specularLevel = GetFloat(pMatList, &pMatList); mat.specular.x = GetFloat(pMatList, &pMatList); mat.specular.y = GetFloat(pMatList, &pMatList); mat.specular.z = GetFloat(pMatList, &pMatList); mat.diffuse.w = 0.0f; SkipToken(pMatList, ";"); mat.emissive.x = GetFloat(pMatList, &pMatList); mat.emissive.y = GetFloat(pMatList, &pMatList); mat.emissive.z = GetFloat(pMatList, &pMatList); mat.emissive.w = 0.0f; SkipToken(pMatList, ";"); // any textures... pToken = GetNextToken(pMatList, &pMatList); while(MFString_Compare(pToken, "}")) { if(!MFString_Compare(pToken, "TextureFilename")) { SkipToken(pMatList, "{"); MFString_Copy(mat.maps[0], GetString(pMatList, &pMatList)); SkipToken(pMatList, "}"); } else { MFDebug_Warn(4, MFStr("Unknown token '%s'\n", pToken)); } pToken = GetNextToken(pMatList, &pMatList); } } } else if(!MFString_Compare(pToken, "{")) { // read material name const char *pMatName = GetNextToken(pMatList, &pMatList); int matID = pModel->GetMaterialChunk()->GetMaterialIndexByName(pMatName); F3DMaterialSubobject &matSub = sub.matSubobjects.push(); if(matID != -1) { matSub.materialIndex = matID; } else { matSub.materialIndex = pModel->GetMaterialChunk()->materials.size(); F3DMaterial &mat = pModel->GetMaterialChunk()->materials.push(); MFString_CopyN(mat.name, pMatName, 64); } pToken = GetNextToken(pMatList, &pMatList); MFDebug_Assert(!MFString_Compare(pToken, "}"), "Scope not closed.\n"); } else { MFDebug_Warn(4, MFStr("Unknown token '%s'\n", pToken)); } pToken = GetNextToken(pMatList, &pMatList); } } return pMatFaces; }