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; }
void CASEFile::Parse() { if (m_file == NULL) { return; } CAlertErrHandler errhandler; CTokenizer* tokenizer = CTokenizer::Create(TKF_USES_EOL | TKF_NUMERICIDENTIFIERSTART); tokenizer->SetErrHandler(&errhandler); tokenizer->SetKeywords(s_keywords); tokenizer->SetSymbols(s_symbols); tokenizer->AddParseFile(m_file, 16 * 1024); int tokType = TK_UNDEFINED; while(tokType != TK_EOF) { CToken* curToken = tokenizer->GetToken(); if (curToken->GetType() == TK_EOF) { curToken->Delete(); tokType = TK_EOF; break; } if (curToken->GetType() == TK_EOL) { curToken->Delete(); continue; } if (curToken->GetType() != TK_ASE_ASTERISK) { tokenizer->Error(TKERR_UNEXPECTED_TOKEN); curToken->Delete(); tokenizer->GetToEndOfLine()->Delete(); continue; } curToken->Delete(); curToken = tokenizer->GetToken(); tokType = curToken->GetType(); curToken->Delete(); switch(tokType) { case TK_EOF: break; case TK_GEOMOBJECT: ParseGeomObject(tokenizer); break; case TK_SCENE: ParseScene(tokenizer); break; case TK_MATERIAL_LIST: ParseMaterialList(tokenizer); break; case TK_ASE_COMMENT: ParseComment(tokenizer); break; case TK_3DSMAX_ASCIIEXPORT: ParseAsciiExport(tokenizer); break; default: tokenizer->Error(TKERR_UNEXPECTED_TOKEN); tokenizer->GetToEndOfLine()->Delete(); break; } } }