#include "StdAfx.h" #include "ModelFile.h" #include "NiFilename.h" static char* GetToken(char*& pcLine) { //忽略前面的空格 while(*pcLine == ' ' || *pcLine == '\t') ++pcLine; char* pcToken = pcLine; int i = 0; while(*pcLine && *pcLine != ' ' && *pcLine != '\t') { if(*pcLine == '=') //字符串里面用等号标示空格 *pcLine = ' '; ++pcLine; } if(*pcLine != '\0') { *pcLine = '\0'; pcLine++; } return pcToken; } static char* GetObjectName(char*& pcMesh) { char* name = pcMesh; while(*pcMesh && *pcMesh != '\\' && *pcMesh != '/') ++pcMesh; if(*pcMesh != '\0') { *pcMesh = '\0'; ++pcMesh; } return name; } static NiAVObject* GetSubObjectByName(NiNode* pkNode, const NiFixedString& kName) { NiAVObject* pkAVObject; for(unsigned int i = 0; i < pkNode->GetArrayCount(); ++i) { pkAVObject = pkNode->GetAt(i); if(pkAVObject) { if(pkAVObject->GetName() == kName) return pkAVObject; if(pkAVObject->IsNode()) { pkAVObject = GetSubObjectByName((NiNode*)pkAVObject, kName); if(pkAVObject) return pkAVObject; } } } return NULL; } static NiAVObject* GetAVObject(NiAVObject* pkRoot, char* pcMesh) { NiAVObject* pkAVObject = pkRoot; char* name; while(true) { name = GetObjectName(pcMesh); if(name[0]) { if(pkAVObject->IsLeaf()) return NULL; pkAVObject = GetSubObjectByName((NiNode*)pkAVObject, name); if(pkAVObject == NULL) return NULL; } else break; } if(pkAVObject == pkRoot) return NULL; return pkAVObject; } void CModelFile::ProcessTexture(char* pcLine) { char* pcMesh = GetToken(pcLine); NiAVObject* pkAVObject = GetAVObject(m_pkRoot, pcMesh); if(pkAVObject == NULL) { return; } char* pcType = GetToken(pcLine); char* pcTextureName = GetToken(pcLine); NiTexturingPropertyPtr spTexturingProp = (NiTexturingProperty*)pkAVObject->GetProperty(NiTexturingProperty::GetType()); if(spTexturingProp == NULL && pcTextureName[0] == '\0') return; if(spTexturingProp == NULL) { spTexturingProp = NiTCreate(); pkAVObject->AttachProperty(spTexturingProp); } NiTexturingProperty::Map* pkMap = NULL; NiTexture* pkTexture = NULL; if(pcTextureName[0] != '\0') { char acTextureName[512]; NiSprintf(acTextureName, sizeof(acTextureName), "%s%s", (const char*)m_kFilePath, pcTextureName); pkTexture = g_ResMgr->LoadTexture(acTextureName); } if(_stricmp(pcType, "base") == 0) { if(pkTexture) { pkMap = spTexturingProp->GetBaseMap(); if(pkMap == NULL) { pkMap = NiTCreate(); spTexturingProp->SetBaseMap(pkMap); } pkMap->SetTexture(pkTexture); } else { spTexturingProp->SetBaseMap(NULL); } } else if(_stricmp(pcType, "glow") == 0) { if(pkTexture) { pkMap = spTexturingProp->GetGlowMap(); if(pkMap == NULL) { pkMap = NiTCreate(); spTexturingProp->SetGlowMap(pkMap); } pkMap->SetTexture(pkTexture); } else { spTexturingProp->SetGlowMap(NULL); } } else if(_stricmp(pcType, "dark") == 0) { if(pkTexture) { pkMap = spTexturingProp->GetDarkMap(); if(pkMap == NULL) { pkMap = NiTCreate(); spTexturingProp->SetDarkMap(pkMap); } pkMap->SetTexture(pkTexture); } else { spTexturingProp->SetDarkMap(NULL); } } else if(_stricmp(pcType, "detail") == 0) { if(pkTexture) { pkMap = spTexturingProp->GetDetailMap(); if(pkMap == NULL) { pkMap = NiTCreate(); spTexturingProp->SetDetailMap(pkMap); } pkMap->SetTexture(pkTexture); } else { spTexturingProp->SetDetailMap(NULL); } } if(pkMap == NULL && pkTexture) g_ResMgr->FreeTexture(pkTexture); //此Texture没有用到 else if( pkTexture ) { int i = 0; for(; i < ARRAY_SIZE(m_pkResNode->m_aTextures); ++i) { if( m_pkResNode->m_aTextures[i] == NULL ) { m_pkResNode->m_aTextures[i] = pkTexture->GetName(); NiGlobalStringTable::IncRefCount((NiGlobalStringTable::GlobalStringHandle&)m_pkResNode->m_aTextures[i]); break; } } NIASSERT(i < ARRAY_SIZE(m_pkResNode->m_aTextures)) } } void CModelFile::ProcessShader(char* pcLine) { char* pcMesh = GetToken(pcLine); NiGeometry* pkGeometry = NiDynamicCast(NiGeometry, GetAVObject(m_pkRoot, pcMesh)); if(pkGeometry == NULL) return; char* pcShader = GetToken(pcLine); if(pcShader[0] == '\0') { if(pkGeometry->GetSkinInstance()) { pkGeometry->ApplyAndSetActiveMaterial("FXSkinningSY"); } else { pkGeometry->ApplyAndSetActiveMaterial("FXSY"); } } else if(_stricmp(pcShader, "default") == 0) pkGeometry->ApplyAndSetActiveMaterial("NiStandardMaterial"); else pkGeometry->ApplyAndSetActiveMaterial(pcShader); } void CModelFile::ProcessLine(char* pcLine) { //第一个单词是命令 char* pcCmd = GetToken(pcLine); if(_stricmp(pcCmd, "texture") == 0) { ProcessTexture(pcLine); } else if(_stricmp(pcCmd, "shader") == 0) { ProcessShader(pcLine); } } MfResNode* CModelFile::Load(const NiFixedString& kName) { m_uiLine = 0; if(!IsMfFile(kName)) return NULL; NiFile* pkFile = NiFile::GetFile(kName, NiFile::READ_ONLY); if(!pkFile || !*pkFile) { NiDelete pkFile; return NULL; } char acLine[512]; pkFile->GetLine(acLine, sizeof(acLine)); m_uiLine = 1; char acBuffer[NI_MAX_PATH]; NiFilename kFilename(kName); kFilename.SetFilename(""); kFilename.SetExt(""); kFilename.GetFullPath(acBuffer, NI_MAX_PATH); NiPath::Standardize(acBuffer); m_kFilePath = acBuffer; strcat_s(acBuffer, acLine); CFixedString kRefName = MakeStandardName(acBuffer); m_pkRoot = g_ResMgr->LoadNif(kRefName); if(m_pkRoot == NULL) { NiDelete pkFile; return NULL; } m_pkResNode = NiNew MfResNode(m_pkRoot); m_pkResNode->m_aNifs[0] = kRefName; NiGlobalStringTable::IncRefCount((NiGlobalStringTable::GlobalStringHandle&)m_pkResNode->m_aNifs[0]); while(pkFile->GetLine(acLine, sizeof(acLine))) { ProcessLine(acLine); m_uiLine++; } NiDelete pkFile; m_pkRoot->UpdateProperties(); m_pkRoot->Update(0.f); return m_pkResNode; }