int MFFileNative_Open(MFFile *pFile, MFOpenData *pOpenData) { MFCALLSTACK; MFDebug_Assert(pOpenData->cbSize == sizeof(MFOpenDataNative), "Incorrect size for MFOpenDataNative structure. Invalid pOpenData."); MFOpenDataNative *pNative = (MFOpenDataNative*)pOpenData; MFDebug_Assert(pOpenData->openFlags & (MFOF_Read|MFOF_Write), "Neither MFOF_Read nor MFOF_Write specified."); MFDebug_Assert((pNative->openFlags & (MFOF_Text|MFOF_Binary)) != (MFOF_Text|MFOF_Binary), "MFOF_Text and MFOF_Binary are mutually exclusive."); const char *pFilename = pNative->pFilename; #if defined(MF_XBOX) || defined(MF_X360) pFilename = FixXBoxFilename(pFilename); #endif if(pOpenData->openFlags & MFOF_CreateDirectory) MFFileNative_CreateDirectory(MFStr_GetFilePath(pFilename)); DWORD access = 0, create = 0; // set the access flags and create mode if(pOpenData->openFlags & MFOF_Read) access |= GENERIC_READ; if(pOpenData->openFlags & (MFOF_Write|MFOF_Append)) { if(pNative->openFlags & MFOF_Append) access |= FILE_APPEND_DATA; else access |= GENERIC_WRITE; if(pNative->openFlags & MFOF_Truncate) create = CREATE_ALWAYS; else create = OPEN_ALWAYS; } else create = OPEN_EXISTING; pFile->pFilesysData = CreateFile(MFString_UFT8AsWChar(pFilename), access, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, create, FILE_ATTRIBUTE_NORMAL, NULL); if(pFile->pFilesysData == INVALID_HANDLE_VALUE) { pFile->pFilesysData = 0; return -1; } LARGE_INTEGER size; if(!GetFileSizeEx(pFile->pFilesysData, &size)) { MFDebug_Warn(2, MFStr("Call: MFFileNative_Open() - Error: Couldn't get size for file '%s'.", pNative->pFilename)); CloseHandle(pFile->pFilesysData); pFile->pFilesysData = 0; return -1; } pFile->createFlags = pOpenData->openFlags; pFile->offset = 0; pFile->length = size.QuadPart; MFString_Copy(pFile->fileIdentifier, pNative->pFilename); return 0; }
void HKStringEntryLogic::Update() { bool shiftL = !!MFInput_Read(Key_LShift, IDD_Keyboard); bool shiftR = !!MFInput_Read(Key_RShift, IDD_Keyboard); bool ctrlL = !!MFInput_Read(Key_LControl, IDD_Keyboard); bool ctrlR = !!MFInput_Read(Key_RControl, IDD_Keyboard); int keyPressed = 0; bool shift = shiftL || shiftR; bool ctrl = ctrlL || ctrlR; #if defined(MF_WINDOWS) if(ctrl && MFInput_WasPressed(Key_C, IDD_Keyboard) && selectionStart != selectionEnd) { BOOL opened = OpenClipboard(apphWnd); if(opened) { int selMin = MFMin(selectionStart, selectionEnd); int selMax = MFMax(selectionStart, selectionEnd); int numChars = selMax-selMin; HANDLE hData = GlobalAlloc(GMEM_MOVEABLE, numChars + 1); char *pString = (char*)GlobalLock(hData); MFString_Copy(pString, GetRenderString().SubStr(selMin, numChars).CStr()); GlobalUnlock(hData); EmptyClipboard(); SetClipboardData(CF_TEXT, hData); CloseClipboard(); } } else if(ctrl && MFInput_WasPressed(Key_X, IDD_Keyboard) && selectionStart != selectionEnd) { BOOL opened = OpenClipboard(apphWnd); if(opened) { int selMin = MFMin(selectionStart, selectionEnd); int selMax = MFMax(selectionStart, selectionEnd); int numChars = selMax-selMin; HANDLE hData = GlobalAlloc(GMEM_MOVEABLE, numChars + 1); char *pString = (char*)GlobalLock(hData); MFString_Copy(pString, GetRenderString().SubStr(selMin, numChars).CStr()); GlobalUnlock(hData); EmptyClipboard(); SetClipboardData(CF_TEXT, hData); CloseClipboard(); ClearSelection(); } } else if(ctrl && MFInput_WasPressed(Key_V, IDD_Keyboard)) { BOOL opened = OpenClipboard(apphWnd); if(opened) { int selMin = MFMin(selectionStart, selectionEnd); int selMax = MFMax(selectionStart, selectionEnd); int numChars = selMax-selMin; HANDLE hData = GetClipboardData(CF_TEXT); MFString paste((const char*)GlobalLock(hData), true); buffer.Replace(selMin, numChars, paste); GlobalUnlock(hData); cursorPos = selMin + paste.NumBytes(); selectionStart = selectionEnd = cursorPos; GlobalUnlock(hData); CloseClipboard(); if((numChars || cursorPos != selMin) && changeCallback) changeCallback(buffer.CStr()); } } else #endif { // check for new keypresses for(int a=0; a<255; a++) { if(MFInput_WasPressed(a, IDD_Keyboard)) { keyPressed = a; holdKey = a; repeatDelay = gRepeatDelay; break; } } // handle repeat keys if(holdKey && MFInput_Read(holdKey, IDD_Keyboard)) { repeatDelay -= MFSystem_TimeDelta(); if(repeatDelay <= 0.f) { keyPressed = holdKey; repeatDelay += gRepeatRate; } } else holdKey = 0; // if there was a new key press if(keyPressed) { switch(keyPressed) { case Key_Backspace: case Key_Delete: { if(selectionStart != selectionEnd) { ClearSelection(); } else { if(keyPressed == Key_Backspace && cursorPos > 0) { buffer.ClearRange(--cursorPos, 1); selectionStart = selectionEnd = cursorPos; if(changeCallback) changeCallback(buffer.CStr()); } else if(keyPressed == Key_Delete && cursorPos < buffer.NumBytes()) { buffer.ClearRange(cursorPos, 1); selectionStart = selectionEnd = cursorPos; if(changeCallback) changeCallback(buffer.CStr()); } } break; } case Key_Left: case Key_Right: case Key_Home: case Key_End: { if(ctrl) { if(keyPressed == Key_Left) { while(cursorPos && MFIsWhite(buffer[cursorPos-1])) --cursorPos; if(MFIsAlphaNumeric(buffer[cursorPos-1])) { while(cursorPos && MFIsAlphaNumeric(buffer[cursorPos-1])) --cursorPos; } else if(cursorPos) { --cursorPos; while(cursorPos && buffer[cursorPos-1] == buffer[cursorPos]) --cursorPos; } } else if(keyPressed == Key_Right) { while(cursorPos < buffer.NumBytes() && MFIsWhite(buffer[cursorPos])) ++cursorPos; if(MFIsAlphaNumeric(buffer[cursorPos])) { while(cursorPos < buffer.NumBytes() && MFIsAlphaNumeric(buffer[cursorPos])) ++cursorPos; } else if(cursorPos < buffer.NumBytes()) { ++cursorPos; while(cursorPos < buffer.NumBytes() && buffer[cursorPos] == buffer[cursorPos-1]) ++cursorPos; } } else if(keyPressed == Key_Home) cursorPos = 0; else if(keyPressed == Key_End) cursorPos = buffer.NumBytes(); } else { if(keyPressed == Key_Left) cursorPos = (!shift && selectionStart != selectionEnd ? MFMin(selectionStart, selectionEnd) : MFMax(cursorPos-1, 0)); else if(keyPressed == Key_Right) cursorPos = (!shift && selectionStart != selectionEnd ? MFMax(selectionStart, selectionEnd) : MFMin(cursorPos+1, buffer.NumBytes())); else if(keyPressed == Key_Home) cursorPos = 0; // TODO: if multiline, go to start of line.. else if(keyPressed == Key_End) cursorPos = buffer.NumBytes(); // TODO: if multiline, go to end of line... } if(shift) selectionEnd = cursorPos; else selectionStart = selectionEnd = cursorPos; break; } default: { bool caps = MFInput_GetKeyboardStatusState(KSS_CapsLock); int ascii = MFInput_KeyToAscii(keyPressed, shift, caps); if(ascii && (!maxLen || buffer.NumBytes() < maxLen-1)) { // check character exclusions if(MFIsNewline(ascii) && type != ST_MultiLine) break; if(ascii == '\t' && type != ST_MultiLine) break; if(type == ST_Numeric && !MFIsNumeric(ascii)) break; if(include) { if(include.FindChar(ascii) < 0) break; } if(exclude) { if(exclude.FindChar(ascii) >= 0) break; } int selMin = MFMin(selectionStart, selectionEnd); int selMax = MFMax(selectionStart, selectionEnd); int selRange = selMax - selMin; const uint16 wstr[] = { (uint16)ascii, 0 }; char insert[5]; MFString_CopyUTF16ToUTF8(insert, wstr); buffer.Replace(selMin, selRange, insert); cursorPos = selMin + 1; selectionStart = selectionEnd = cursorPos; if(changeCallback) changeCallback(buffer.CStr()); } break; } } } } }
void ParseOBJFile(const char *pFilePtr) { const char *pToken = GetNextToken(pFilePtr); while(*pToken != 0) { if(!MFString_CaseCmp(pToken, "o")) { const char *pName = GetRestOfLine(pFilePtr); MFString_Copy(pModel->name, pName); } else if(!MFString_CaseCmp(pToken, "g")) { const char *pName = GetRestOfLine(pFilePtr); if(!vertsInGroup) { // we'll just rename the current subobject, since theres nothing in it.. F3DSubObject &sub = pModel->GetMeshChunk()->subObjects[subObject]; MFString_Copy(sub.name, pName); } else { // probably wanna copy vertex data in at this point.. // and subtract the min from each of the components indices.. CopyDataIntoSubobject(subObject); ++subObject; matSub = 0; minVertIndex = -1; minUVIndex = -1; minNormIndex = -1; maxVertIndex = -1; maxUVIndex = -1; maxNormIndex = -1; vertsInGroup = false; vertsInMatSub = false; F3DSubObject &sub = pModel->GetMeshChunk()->subObjects[subObject]; MFString_Copy(sub.name, pName); } } else if(!MFString_CaseCmp(pToken, "v")) { const char *pX = GetNextToken(pFilePtr); const char *pY = GetNextToken(pFilePtr); const char *pZ = GetNextToken(pFilePtr); pFilePtr = MFSeekNewline(pFilePtr); MFVector v; v.x = (float)atof(pX); v.y = (float)atof(pY); v.z = (float)atof(pZ); v.w = 1.0f; verts.push(v); } else if(!MFString_CaseCmp(pToken, "vt")) { const char *pU = GetNextToken(pFilePtr); const char *pV = GetNextToken(pFilePtr); pFilePtr = MFSeekNewline(pFilePtr); MFVector v; v.x = (float)atof(pU); v.y = (float)atof(pV); v.z = 0.0f; v.w = 1.0f; uvs.push(v); } else if(!MFString_CaseCmp(pToken, "vn")) { const char *pX = GetNextToken(pFilePtr); const char *pY = GetNextToken(pFilePtr); const char *pZ = GetNextToken(pFilePtr); pFilePtr = MFSeekNewline(pFilePtr); MFVector v; v.x = (float)atof(pX); v.y = (float)atof(pY); v.z = (float)atof(pZ); v.w = 1.0f; normals.push(v); } else if(!MFString_CaseCmp(pToken, "f")) { vertsInGroup = true; vertsInMatSub = true; F3DSubObject &sub = pModel->GetMeshChunk()->subObjects[subObject]; const char *pRestOfLine = GetRestOfLine(pFilePtr); int firstVert = sub.matSubobjects[matSub].vertices.size(); pToken = GetNextToken(pRestOfLine); while(*pToken) { const char *pPos = GetNextIndex(pToken); const char *pUV = GetNextIndex(pToken); const char *pNorm = GetNextIndex(pToken); int posid = atoi(pPos); int texid = atoi(pUV); int normid = atoi(pNorm); if(posid < 0) posid = verts.size() - posid; else posid = posid - 1; if(texid < 0) texid = uvs.size() - texid; else texid = texid - 1; if(normid < 0) normid = normals.size() - normid; else normid = normid - 1; minVertIndex = minVertIndex == -1 ? posid : MFMin(minVertIndex, posid); minUVIndex = minUVIndex == -1 ? texid : MFMin(minUVIndex, texid); minNormIndex = minNormIndex == -1 ? normid : MFMin(minNormIndex, normid); maxVertIndex = minVertIndex == -1 ? posid : MFMax(maxVertIndex, posid); maxUVIndex = maxUVIndex == -1 ? texid : MFMax(maxUVIndex, texid); maxNormIndex = maxNormIndex == -1 ? normid : MFMax(maxNormIndex, normid); int vi = sub.matSubobjects[matSub].vertices.size(); int f = vi - firstVert; F3DVertex &vert = sub.matSubobjects[matSub].vertices[firstVert + f]; vert.position = posid; vert.uv1 = texid; vert.normal = normid; // add a triangle if we are up to the third vert or beyond if(f >= 2) { int curVert = sub.matSubobjects[matSub].vertices.size() - 1; F3DTriangle &tri = sub.matSubobjects[matSub].triangles.push(); tri.v[0] = firstVert; tri.v[1] = vi-1; tri.v[2] = vi; } pToken = GetNextToken(pRestOfLine); } } else if(!MFString_CaseCmp(pToken, "usemtl")) { F3DSubObject &sub = pModel->GetMeshChunk()->subObjects[subObject]; if(vertsInGroup && vertsInMatSub) { ++matSub; vertsInMatSub = false; } const char *pName = GetRestOfLine(pFilePtr); sub.matSubobjects[matSub].materialIndex = GetMaterialID(pName); } else if(!MFString_CaseCmp(pToken, "mtllib")) { // load material info? //.. pFilePtr = MFSeekNewline(pFilePtr); } else if(pToken[0] == '#') { pFilePtr = MFSeekNewline(pFilePtr); } else { MFDebug_Warn(2, MFStr("Unknown token encountered in obj file '%s'!", pToken)); pFilePtr = MFSeekNewline(pFilePtr); } pToken = GetNextToken(pFilePtr); } // want to copy vertex data into the last subobject at this point... if(vertsInGroup) { CopyDataIntoSubobject(subObject); } }
int ReadMesh(char** buf, int frmcount, float scale, uint32 flags) { if(!*buf) return 1; MEMesh2 *mesh=(MEMesh2*)*buf; MEMD2_VERTEX *vb; if(!scale) scale=1.0f; *buf+=sizeof(MEMesh2); if(!mesh->vcount || !mesh->icount) return 1; mesh->Scale.x=65525.0f/mesh->Scale.x; mesh->Scale.y=65525.0f/mesh->Scale.y; mesh->Scale.z=65525.0f/mesh->Scale.z; mesh->UVScale.x=65525.0f/mesh->UVScale.x; mesh->UVScale.y=65525.0f/mesh->UVScale.y; F3DSubObject &sub = pModel->GetMeshChunk()->subObjects.push(); MFString_Copy(sub.name, mesh->Name); sub.matSubobjects[0].materialIndex = mesh->MaterialID; // read vertex data for(int a=0; a<frmcount; a++) { vb=(MEMD2_VERTEX*)*buf; if(a == 0) // only first frame for now... { for(int b=0; b<mesh->vcount; b++) { UnpackVertex(&vb[b], mesh, scale, sub); } } *buf+=sizeof(MEMD2_VERTEX)*mesh->vcount; } // read triangles MFDebug_Assert(mesh->icount % 3 == 0, "Incorrect number of indices..."); F3DMaterialSubobject &msub = sub.matSubobjects[0]; uint16 *pI = (uint16*)*buf; int tris =0; int v = 0; for(int a=0; a<mesh->icount; a++) { msub.triangles[tris].v[v] = pI[a]; ++v; if(v>=3) { v = 0; ++tris; } } *buf+=sizeof(unsigned short)*mesh->icount; return 0; }
MF_API MFModel* MFModel_Create(const char *pFilename) { const char* pOriginalFilename = pFilename; // see if it's already loaded MFModelPool::Iterator it = gModelBank.Get(pOriginalFilename); MFModelTemplate *pTemplate = it ? *it : NULL; if(!pTemplate) { char *pTemplateData = NULL; MFFile *hFile = MFFileSystem_Open(MFStr("%s.mdl", pFilename), MFOF_Read|MFOF_Binary); if(hFile) { int64 size = MFFile_GetSize(hFile); if(size > 0) { // allocate memory and load file pTemplateData = (char*)MFHeap_Alloc((size_t)size + MFString_Length(pFilename) + 1); MFFile_Read(hFile, pTemplateData, (size_t)size); MFFile_Close(hFile); MFString_Copy(&pTemplateData[size], pFilename); pFilename = &pTemplateData[size]; } } else { #if defined(ALLOW_LOAD_FROM_SOURCE_DATA) // try to load from source data const char * const pExt[] = { ".f3d", ".dae", ".x", ".ase", ".obj", ".md2", ".md3", ".me2", NULL }; const char * const *ppExt = pExt; MFIntModel *pIM = NULL; while(!pIM && *ppExt) { MFString tempFilename = MFString::Format("%s%s", pFilename, *ppExt); pIM = MFIntModel_CreateFromFile(tempFilename.CStr()); if(pIM) { pFilename = MFString_Copy((char*)MFHeap_Alloc(tempFilename.NumBytes()+1), tempFilename.CStr()); break; } ++ppExt; } if(pIM) { MFIntModel_Optimise(pIM); size_t size; MFIntModel_CreateRuntimeData(pIM, (void**)&pTemplateData, &size, MFSystem_GetCurrentPlatform()); MFFile *pFile = MFFileSystem_Open(MFStr("cache:%s.mdl", pOriginalFilename), MFOF_Write | MFOF_Binary); if(pFile) { MFFile_Write(pFile, pTemplateData, size, false); MFFile_Close(pFile); } MFIntModel_Destroy(pIM); } #endif } if(!pTemplateData) return NULL; // check ID string MFDebug_Assert(*(uint32*)pTemplateData == MFMAKEFOURCC('M', 'D', 'L', '2'), "Incorrect MFModel version."); // store filename for later reference pTemplate = (MFModelTemplate*)pTemplateData; pTemplate->pFilename = pFilename; gModelBank.Add(pOriginalFilename, pTemplate); MFModel_FixUp(pTemplate, true); MFModelDataChunk *pChunk = MFModel_GetDataChunk(pTemplate, MFChunkType_SubObjects); if(pChunk) { MFModelSubObject *pSubobjects = (MFModelSubObject*)pChunk->pData; for(int a=0; a<pChunk->count; a++) { // pSubobjects[a].pMaterial = MFMaterial_Create((char*)pSubobjects[a].pMaterial); for(int b=0; b<pSubobjects[a].numMeshChunks; b++) { MFModel_CreateMeshChunk(MFModel_GetMeshChunkInternal(pTemplate, a, b)); } } } } MFModel *pModel; pModel = (MFModel*)MFHeap_Alloc(sizeof(MFModel)); pModel->worldMatrix = MFMatrix::identity; pModel->modelColour = MFVector::one; pModel->pTemplate = pTemplate; pModel->pAnimation = NULL; ++pTemplate->refCount; return pModel; }
void ParseMEMD2File(char *pBuffer) { char *buf; int a; MEHeader *head; MEMaterial2 *material; bool bWriteOutImage = false; buf=pBuffer; head=(MEHeader*)pBuffer; if(head->ID!=MEMD_ID) { return; } if(!(head->Version>=200 && head->Version<300)) { return; } CalcNormTable(); MFString_Copy(pModel->name, head->Name); MFString_Copy(pModel->author, head->Creator); if(head->SequenceCount) { MESequence2 *pSequences = (MESequence2*)(pBuffer+head->SequenceStart); // do some shit for each one } if(head->MaterialCount) { buf=pBuffer+head->MaterialStart; material=(MEMaterial2*)buf; for(a=0; a<head->MaterialCount; a++) { F3DMaterial &mat = pModel->GetMaterialChunk()->materials.push(); // material name // MFString_Copy(mat.name, material->Name); // use texture name instead of material name char *pTex = material->TextureFileName; pTex += MFString_Length(pTex); while(pTex > material->TextureFileName && pTex[-1] != '/' && pTex[-1] != '\\') { --pTex; } pTex[MFString_Length(pTex) - 4] = NULL; MFString_Copy(mat.name, pTex); // material parameters mat.specularLevel = material->matPower; mat.ambient.x = material->matColours[0].r; mat.ambient.y = material->matColours[0].g; mat.ambient.z = material->matColours[0].b; mat.ambient.w = material->matColours[0].a; buf += 64 + sizeof(v4[4]) + sizeof(float) + sizeof(int); if(material->TextureCount) { buf+=260; if(material->ImageLen) { #if 0 if(bWriteOutImage) { FILE *pFile = fopen(material->TextureFileName, "wb"); if(pFile) { fwrite(material->ImageBuffer, 1, material->ImageLen, pFile); fclose(pFile); } } #endif buf+=material->ImageLen; } } buf+=8; material=(MEMaterial2*)buf; } } if(head->FrameCount&&head->MeshCount) { buf=pBuffer+head->FrameStart; for(a=0; a<head->MeshCount; a++) { ReadMesh(&buf, head->FrameCount, 1.0f, 0); } } return; }
const char *ParseFrame(const char *pText, const MFMatrix &mat, int parentID) { char frameName[64]; const char *pName = GetNextToken(pText, &pText, frameName); MFMatrix worldMatrix = mat; F3DBone *pBone = NULL; if(!MFString_CaseCmpN(pName, "bn_", 3) || !MFString_CaseCmpN(pName, "z_", 2)) { int boneID = pModel->GetSkeletonChunk()->bones.size(); pBone = &pModel->GetSkeletonChunk()->bones[boneID]; F3DBone *pParent = parentID == -1 ? NULL : &pModel->GetSkeletonChunk()->bones[parentID]; parentID = boneID; MFString_Copy(pBone->name, pName); MFString_Copy(pBone->parentName, pParent ? pParent->name : ""); pBone->worldMatrix = mat; } if(MFString_Compare(pName, "{")) SkipToken(pText, "{"); const char *pTok = GetNextToken(pText, &pText); while(MFString_Compare(pTok, "}")) { if(!MFString_Compare(pTok, "Frame")) { pText = ParseFrame(pText, worldMatrix, parentID); } else if(!MFString_Compare(pTok, "FrameTransformMatrix")) { SkipToken(pText, "{"); MFMatrix localMatrix; GetFloatArray(pText, (float*)&localMatrix, 16, &pText); worldMatrix.Multiply(localMatrix, worldMatrix); if(pBone) { pBone->boneMatrix = localMatrix; pBone->worldMatrix = worldMatrix; } SkipToken(pText, ";"); SkipToken(pText, "}"); } else if(!MFString_Compare(pTok, "Mesh")) { gMeshChunks.push(XMeshChunk::Create(worldMatrix, pText, pName)); SkipSection(pText); } else { MFDebug_Warn(4, MFStr("Unexpected token '%s'\n", pTok)); SkipSection(pText); } pTok = GetNextToken(pText, &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; }
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; }
static XMeshChunk Create(const MFMatrix &_mat, const char *_pMesh, const char *pFrameName) { XMeshChunk mc; mc.mat = _mat; mc.pMesh = _pMesh; MFString_Copy(mc.frameName, pFrameName); return mc; }