static void FillBoneController(Exporter* exporter, NiBSBoneLODControllerRef boneCtrl, INode *node) { for (int i=0; i<node->NumberOfChildren(); i++) { INode * child = node->GetChildNode(i); FillBoneController(exporter, boneCtrl, child); TSTR upb; child->GetUserPropBuffer(upb); if (!upb.isNull()) { // Check for bonelod and add bones to bone controller stringlist tokens = TokenizeString(upb.data(), "\r\n", true); for (stringlist::iterator itr = tokens.begin(); itr != tokens.end(); ++itr) { string& line = (*itr); if (wildmatch("*#", line)) { // ends with # stringlist bonelod = TokenizeString(line.c_str(), "#", true); for (stringlist::iterator token = bonelod.begin(); token != bonelod.end(); ++token) { if ( wildmatch("??BoneLOD", (*token).c_str())) { if (++token == bonelod.end()) break; if (strmatch("Bone", (*token).c_str())) { if (++token == bonelod.end()) break; int group = 0; std::stringstream str (*token); str >> group; boneCtrl->AddNodeToGroup(group, exporter->getNode(child)); } } } } } }
bool Exporter::exportUPB(NiNodeRef &root, INode *node) { bool ok = false; if (!mUserPropBuffer) return ok; // Write the actual UPB sans any np_ prefixed strings TSTR upb; node->GetUserPropBuffer(upb); if (!upb.isNull()) { string line; istringstream istr(string(upb), ios_base::out); ostringstream ostr; while (!istr.eof()) { std::getline(istr, line); if (!line.empty() && 0 != line.compare(0, 3, "np_")) ostr << line << endl; } if (!ostr.str().empty()) { NiStringExtraDataRef strings = CreateNiObject<NiStringExtraData>(); strings->SetName("UPB"); strings->SetData(ostr.str()); root->AddExtraData(DynamicCast<NiExtraData>(strings)); ok = true; } } return ok; }
bool bgGlobalMax::CheckFile(Interface* p3DMax) { TSTR strCurrentFileName = FixupName(p3DMax->GetCurFileName()); if (strCurrentFileName.isNull() == false && m_strCurrentFileName == strCurrentFileName) return false; m_MatrixMap.Release(); m_pMtlList.clear(); m_strCurrentFileName = strCurrentFileName; return true; }
Exporter::Result Exporter::exportMesh(NiNodeRef &ninode, INode *node, TimeValue t) { ObjectState os = node->EvalWorldState(t); bool local = !mFlattenHierarchy; TriObject *tri = (TriObject *)os.obj->ConvertToType(t, Class_ID(TRIOBJ_CLASS_ID, 0)); if (!tri) return Skip; Mesh *copymesh = NULL; Mesh *mesh = &tri->GetMesh(); Matrix3 mtx(true), rtx(true); if (Exporter::mCollapseTransforms) { mtx = GetNodeLocalTM(node, t); mtx.NoTrans(); Quat q(mtx); q.MakeMatrix(rtx); mesh = copymesh = new Mesh(*mesh); { int n = mesh->getNumVerts(); for ( unsigned int i = 0; i < n; ++i ) { Point3& vert = mesh->getVert(i); vert = mtx * vert; } mesh->checkNormals(TRUE); #if VERSION_3DSMAX > ((5000<<16)+(15<<8)+0) // Version 6+ MeshNormalSpec *specNorms = mesh->GetSpecifiedNormals (); if (NULL != specNorms) { specNorms->CheckNormals(); for ( unsigned int i = 0; i < specNorms->GetNumNormals(); ++i ) { Point3& norm = specNorms->Normal(i); norm = (rtx * norm).Normalize(); } } #endif } } // Note that calling setVCDisplayData will clear things like normals so we set this up first vector<Color4> vertColors; if (mVertexColors) { bool hasvc = false; if (mesh->mapSupport(MAP_ALPHA)) { mesh->setVCDisplayData(MAP_ALPHA); int n = mesh->getNumVertCol(); if (n > vertColors.size()) vertColors.assign(n, Color4(1.0f, 1.0f, 1.0f, 1.0f)); VertColor *vertCol = mesh->vertColArray; if (vertCol) { for (int i=0; i<n; ++i) { VertColor c = vertCol[ i ]; float a = (c.x + c.y + c.z) / 3.0f; vertColors[i].a = a; hasvc |= (a != 1.0f); } } } if (mesh->mapSupport(0)) { mesh->setVCDisplayData(0); VertColor *vertCol = mesh->vertColArray; int n = mesh->getNumVertCol(); if (n > vertColors.size()) vertColors.assign(n, Color4(1.0f, 1.0f, 1.0f, 1.0f)); if (vertCol) { for (int i=0; i<n; ++i) { VertColor col = vertCol[ i ]; vertColors[i] = Color4(col.x, col.y, col.z, vertColors[i].a); hasvc |= (col.x != 1.0f || col.y != 1.0f || col.z != 1.0f); } } } if (!hasvc) vertColors.clear(); } #if VERSION_3DSMAX <= ((5000<<16)+(15<<8)+0) // Version 5 mesh->checkNormals(TRUE); #else MeshNormalSpec *specNorms = mesh->GetSpecifiedNormals (); if (NULL != specNorms) { specNorms->CheckNormals(); if (specNorms->GetNumNormals() == 0) mesh->checkNormals(TRUE); } else { mesh->checkNormals(TRUE); } #endif Result result = Ok; Modifier* geomMorpherMod = GetMorpherModifier(node); bool noSplit = FALSE; // bool noSplit = (NULL != geomMorpherMod); while (1) { FaceGroups grps; if (!splitMesh(node, *mesh, grps, t, vertColors, noSplit)) { result = Error; break; } bool exportStrips = mTriStrips && (Exporter::mNifVersionInt > VER_4_2_2_0); Matrix44 tm = Matrix44::IDENTITY; if ( mExportExtraNodes || (mExportType != NIF_WO_ANIM && isNodeKeyed(node) ) ) { tm = TOMATRIX4(getObjectTransform(node, t, false) * Inverse(getNodeTransform(node, t, false))); } else { Matrix33 rot; Vector3 trans; objectTransform(rot, trans, node, t, local); tm = Matrix44(trans, rot, 1.0f); } tm = TOMATRIX4(Inverse(mtx)) * tm; TSTR basename = node->NodeName(); TSTR format = (!basename.isNull() && grps.size() > 1) ? "%s:%d" : "%s"; int i=1; FaceGroups::iterator grp; for (grp=grps.begin(); grp!=grps.end(); ++grp, ++i) { string name = FormatString(format, basename.data(), i); NiTriBasedGeomRef shape = makeMesh(ninode, getMaterial(node, grp->first), grp->second, exportStrips); if (shape == NULL) { result = Error; break; } if (node->IsHidden()) shape->SetVisibility(false); shape->SetName(name); shape->SetLocalTransform(tm); if (Exporter::mZeroTransforms) { shape->ApplyTransforms(); } makeSkin(shape, node, grp->second, t); if (geomMorpherMod) { vector<Vector3> verts = shape->GetData()->GetVertices(); exportGeomMorpherControl(geomMorpherMod, verts, shape->GetData()->GetVertexIndices(), shape); shape->GetData()->SetConsistencyFlags(CT_VOLATILE); } } break; } if (tri != os.obj) tri->DeleteMe(); if (copymesh) delete copymesh; return result; }
static INT_PTR CALLBACK MaxNifImportOptionsDlgProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam) { static NifImporter *imp = nullptr; static DWORD dlgRes = IDCANCEL; switch(message) { case WM_INITDIALOG: { dlgRes = IDCANCEL; // Append file version to dialog TSTR version = GetFileVersion((LPTSTR)nullptr); if (!version.isNull()) { TCHAR buffer[256]; GetWindowText(hWnd, buffer, _countof(buffer)); _tcscat(buffer, TEXT(" ")); _tcscat(buffer, version); SetWindowText(hWnd, buffer); } imp = (NifImporter *)lParam; CenterWindow(hWnd,GetParent(hWnd)); CheckDlgButton(hWnd, IDC_CHK_BONES, imp->importBones); CheckDlgButton(hWnd, IDC_CHK_SKIN, imp->enableSkinSupport); CheckDlgButton(hWnd, IDC_CHK_VCOLORS, imp->vertexColorMode); CheckDlgButton(hWnd, IDC_CHK_COLL, imp->enableCollision); EnableWindow(GetDlgItem(hWnd, IDC_CHK_COLL), TRUE); CheckDlgButton(hWnd, IDC_CHK_ANIMATION, imp->enableAnimations); CheckDlgButton(hWnd, IDC_CHK_LIGHTS, imp->enableLights); CheckDlgButton(hWnd, IDC_CHK_CAMERA, imp->enableCameras); //CheckDlgButton(hWnd, IDC_CHK_FURN, imp->); CheckDlgButton(hWnd, IDC_CHK_FLIP_UV, imp->flipUVTextures); CheckDlgButton(hWnd, IDC_CHK_SHOW_TEX, imp->showTextures); CheckDlgButton(hWnd, IDC_CHK_AUTOSMOOTH, imp->enableAutoSmooth); CheckDlgButton(hWnd, IDC_CHK_ILLEGAL, imp->removeIllegalFaces); CheckDlgButton(hWnd, IDC_CHK_REM_BONES, imp->removeUnusedImportedBones); CheckDlgButton(hWnd, IDC_CHK_DUMMY_NODES, imp->importBonesAsDummy); CheckDlgButton(hWnd, IDC_CHK_CLEARANIM, imp->clearAnimation); CheckDlgButton(hWnd, IDC_CHK_KEYNOTES, imp->addNoteTracks); CheckDlgButton(hWnd, IDC_CHK_TIMETAGS, imp->addTimeTags); CheckDlgButton(hWnd, IDC_CHK_IGNORE_ROOT, imp->ignoreRootNode); CheckDlgButton(hWnd, IDC_CHK_USE_SHADER, imp->useNiftoolsShader); CheckDlgButton(hWnd, IDC_CHK_BIPED, imp->useBiped); CheckDlgButton(hWnd, IDC_CHK_UPB, !imp->importUPB); tstring selection = (imp->appSettings) ? imp->appSettings->Name : TEXT("User"); for (AppSettingsMap::iterator itr = TheAppSettings.begin(), end = TheAppSettings.end(); itr != end; ++itr) SendDlgItemMessage(hWnd, IDC_CB_GAME, CB_ADDSTRING, 0, LPARAM(itr->Name.c_str())); SendDlgItemMessage(hWnd, IDC_CB_GAME, CB_SELECTSTRING, WPARAM(-1), LPARAM(selection.c_str())); CheckDlgButton(hWnd, IDC_CHK_AUTO_DETECT, imp->autoDetect); SHAutoComplete(GetDlgItem(hWnd, IDC_ED_SKELETON), SHACF_FILESYSTEM); if (imp->appSettings && imp->importSkeleton) { SetDlgItemText(hWnd, IDC_ED_SKELETON, imp->skeleton.c_str()); } else { EnableWindow(GetDlgItem(hWnd, IDC_STC_SKELETON), FALSE); EnableWindow(GetDlgItem(hWnd, IDC_ED_SKELETON), FALSE); EnableWindow(GetDlgItem(hWnd, IDC_BTN_BROWSE), FALSE); EnableWindow(GetDlgItem(hWnd, IDC_CHK_BIPED), FALSE); EnableWindow(GetDlgItem(hWnd, IDC_CHK_REM_BONES), FALSE); } // Weld Threshold TSTR weldThresh; weldThresh.printf(TEXT("%g"), imp->weldVertexThresh); CheckDlgButton(hWnd, IDC_CHK_WELD, imp->weldVertices); EnableWindow(GetDlgItem(hWnd, IDC_CHK_WELD), TRUE); SetDlgItemText(hWnd, IDC_EDIT_WELDTHRESH, weldThresh); EnableWindow(GetDlgItem(hWnd, IDC_EDIT_WELDTHRESH), imp->weldVertices); ConvertStaticToHyperlink(hWnd, IDC_LBL_LINK); ConvertStaticToHyperlink(hWnd, IDC_LBL_WIKI); NifImportUpdateStatusDlg(imp, hWnd); } return TRUE; case WM_CLOSE: { EndDialog(hWnd, dlgRes); } return TRUE; case WM_COMMAND : { if (HIWORD(wParam) == BN_CLICKED) { TCHAR tmp[MAX_PATH]; switch (LOWORD(wParam)) { case IDOK: imp->importBones = IsDlgButtonChecked(hWnd, IDC_CHK_BONES) ? true : false; imp->enableSkinSupport = IsDlgButtonChecked(hWnd, IDC_CHK_SKIN) ? true : false; imp->vertexColorMode = (int)IsDlgButtonChecked(hWnd, IDC_CHK_VCOLORS); imp->enableCollision = IsDlgButtonChecked(hWnd, IDC_CHK_COLL) ? true : false; imp->enableCameras = IsDlgButtonChecked(hWnd, IDC_CHK_CAMERA) ? true : false; imp->enableLights = IsDlgButtonChecked(hWnd, IDC_CHK_LIGHTS) ? true : false; imp->enableAnimations = IsDlgButtonChecked(hWnd, IDC_CHK_ANIMATION) ? true : false; //IsDlgButtonChecked(hWnd, IDC_CHK_FURN, imp->); imp->flipUVTextures = IsDlgButtonChecked(hWnd, IDC_CHK_FLIP_UV) ? true : false; imp->showTextures = IsDlgButtonChecked(hWnd, IDC_CHK_SHOW_TEX) ? true : false; imp->enableAutoSmooth = IsDlgButtonChecked(hWnd, IDC_CHK_AUTOSMOOTH) ? true : false; imp->removeDegenerateFaces = imp->removeIllegalFaces = IsDlgButtonChecked(hWnd, IDC_CHK_ILLEGAL) ? true : false; imp->removeUnusedImportedBones = IsDlgButtonChecked(hWnd, IDC_CHK_REM_BONES) ? true : false; imp->importBonesAsDummy = IsDlgButtonChecked(hWnd, IDC_CHK_DUMMY_NODES) ? true : false; imp->clearAnimation = IsDlgButtonChecked(hWnd, IDC_CHK_CLEARANIM) ? true : false; imp->addNoteTracks = IsDlgButtonChecked(hWnd, IDC_CHK_KEYNOTES) ? true : false; imp->addTimeTags = IsDlgButtonChecked(hWnd, IDC_CHK_TIMETAGS) ? true : false; imp->useBiped = IsDlgButtonChecked(hWnd, IDC_CHK_BIPED) ? true : false; imp->importUPB = IsDlgButtonChecked(hWnd, IDC_CHK_UPB) ? false : true; imp->ignoreRootNode = IsDlgButtonChecked(hWnd, IDC_CHK_IGNORE_ROOT) ? true : false; imp->useNiftoolsShader = IsDlgButtonChecked(hWnd, IDC_CHK_USE_SHADER) ? true : false; GetDlgItemText(hWnd, IDC_CB_GAME, tmp, MAX_PATH); if (AppSettings *appSettings = FindAppSetting(tmp)) { imp->appSettings = appSettings; } imp->autoDetect = IsDlgButtonChecked(hWnd, IDC_CHK_AUTO_DETECT) ? true : false; GetDlgItemText(hWnd, IDC_ED_SKELETON, tmp, MAX_PATH); imp->skeleton = tmp; // Weld Threshold imp->weldVertices = IsDlgButtonChecked(hWnd, IDC_CHK_WELD)? true : false; GetDlgItemText(hWnd, IDC_EDIT_WELDTHRESH, tmp, MAX_PATH); if (_tcslen(tmp) > 0) imp->weldVertexThresh = (float)_ttof(tmp); EndDialog(hWnd, dlgRes=IDOK); return TRUE; case IDCANCEL: EndDialog(hWnd, dlgRes=IDCANCEL); return TRUE; case IDC_BTN_BROWSE: { TCHAR filter[64], *pfilter=filter; pfilter = _tcscpy(filter, shortDescription); pfilter = _tcscat(pfilter, TEXT(" (*.NIF)")); pfilter += _tcslen(pfilter); *pfilter++ = '\0'; _tcscpy(pfilter, TEXT("*.NIF")); pfilter += _tcslen(pfilter); *pfilter++ = '\0'; *pfilter++ = '\0'; GetDlgItemText(hWnd, IDC_ED_SKELETON, tmp, MAX_PATH); GetLongPathName(tmp, tmp, _countof(tmp)); OPENFILENAME ofn; memset(&ofn, 0, sizeof(ofn)); ofn.lStructSize = sizeof(ofn); ofn.hwndOwner = imp->gi->GetMAXHWnd(); ofn.lpstrFilter = filter; ofn.lpstrFile = tmp; ofn.nMaxFile = _countof(tmp); ofn.lpstrTitle = TEXT("Browse for Skeleton NIF..."); ofn.lpstrDefExt = TEXT("NIF"); ofn.Flags = OFN_HIDEREADONLY|OFN_EXPLORER|OFN_FILEMUSTEXIST|OFN_NOCHANGEDIR|OFN_PATHMUSTEXIST; if (GetOpenFileName(&ofn)) { SetDlgItemText(hWnd, IDC_ED_SKELETON, tmp); } } break; case IDC_CHK_WELD: EnableWindow(GetDlgItem(hWnd, IDC_EDIT_WELDTHRESH), IsDlgButtonChecked(hWnd, IDC_CHK_WELD)); break; case IDC_LBL_LINK: ShellExecute(hWnd, TEXT("open"), imp->webSite, nullptr, nullptr, SW_SHOWNORMAL); break; case IDC_LBL_WIKI: ShellExecute(hWnd, TEXT("open"), imp->wikiSite, nullptr, nullptr, SW_SHOWNORMAL); break; } } else if (HIWORD(wParam) == CBN_SELCHANGE) { if (LOWORD(wParam) == IDC_CB_GAME) { NifImportUpdateStatusDlg(imp, hWnd); } } } break; } return FALSE; }
void Unreal3DExport::WriteScript() { // Write script file { fScript = _tfopen(ScriptFileName,_T("wb")); if( !fScript ) { ProgressMsg.printf(GetString(IDS_ERR_FSCRIPT),ScriptFileName); throw MAXException(ProgressMsg.data()); } TSTR buf; // Write class def _ftprintf( fScript, _T("class %s extends Object;\n\n"), FileName ); // write import _ftprintf( fScript, _T("#exec MESH IMPORT MESH=%s ANIVFILE=%s_a.3D DATAFILE=%s_d.3D \n"), FileName, FileName, FileName ); // write origin & rotation // TODO: figure out why it's incorrect without -1 Point3 porg = OptOffset * OptScale * -1; _ftprintf( fScript, _T("#exec MESH ORIGIN MESH=%s X=%f Y=%f Z=%f PITCH=%d YAW=%d ROLL=%d \n"), FileName, porg.x, porg.y, porg.z, (int)OptRot.x, (int)OptRot.y, (int)OptRot.z ); // write mesh scale Point3 psc( Point3(1.0f/OptScale.x,1.0f/OptScale.y,1.0f/OptScale.z)); _ftprintf( fScript, _T("#exec MESH SCALE MESH=%s X=%f Y=%f Z=%f \n"), FileName, psc.x, psc.y, psc.z ); // write meshmap _ftprintf( fScript, _T("#exec MESHMAP NEW MESHMA=P%s MESH=%smap \n"), FileName, FileName ); // write meshmap scale _ftprintf( fScript, _T("#exec MESHMAP SCALE MESHMAP=%s X=%f Y=%f Z=%f \n"), FileName, psc.x, psc.y, psc.z ); // write sequence _ftprintf( fScript, _T("#exec MESH SEQUENCE MESH=%s SEQ=%s STARTFRAME=%d NUMFRAMES=%d \n"), FileName, _T("All"), 0, FrameCount-1 ); // Get World NoteTrack ReferenceTarget *rtscene = pInt->GetScenePointer(); for( int t=0; t<rtscene->NumNoteTracks(); ++t ) { DefNoteTrack* notetrack = static_cast<DefNoteTrack*>(rtscene->GetNoteTrack(t)); for( int k=0; k<notetrack->keys.Count(); ++k ) { NoteKey* notekey = notetrack->keys[k]; TSTR text = notekey->note; int notetime = notekey->time / pScene->GetSceneTicks(); while( !text.isNull() ) { TSTR cmd = SplitStr(text,_T('\n')); if( MatchPattern(cmd,TSTR(_T("a *")),TRUE) ) { SplitStr(cmd,_T(' ')); TSTR seq = SplitStr(cmd,_T(' ')); int end = _ttoi(SplitStr(cmd,_T(' ')));; TSTR rate = SplitStr(cmd,_T(' ')); TSTR group = SplitStr(cmd,_T(' ')); if( seq.isNull() ) { ProgressMsg.printf(_T("Missing animation name in notekey #%d"),notetime); throw MAXException(ProgressMsg.data()); } if( end <= notetime ) { ProgressMsg.printf(_T("Invalid animation endframe (%d) in notekey #%d"),end,notetime); throw MAXException(ProgressMsg.data()); } int startframe = notetime; int numframes = end - notetime; buf.printf( _T("#exec MESH SEQUENCE MESH=%s SEQ=%s STARTFRAME=%d NUMFRAMES=%d"), FileName, seq, notetime, numframes ); if( !rate.isNull() ) buf.printf( _T("%s RATE=%f"), buf, rate ); if( !group.isNull() ) buf.printf( _T("%s GROUP=%f"), buf, rate ); SeqName = seq; SeqFrame = startframe; buf.printf( _T("%s \n"), buf ); _fputts( buf, fScript ); } else if( MatchPattern(cmd,TSTR(_T("n *")),TRUE) ) { SplitStr(cmd,_T(' ')); TSTR func = SplitStr(cmd,_T(' ')); TSTR time = SplitStr(cmd,_T(' ')); if( func.isNull() ) { ProgressMsg.printf(_T("Missing notify name in notekey #%d"),notetime); throw MAXException(ProgressMsg.data()); } if( time.isNull() ) { ProgressMsg.printf(_T("Missing notify time in notekey #%d"),notetime); throw MAXException(ProgressMsg.data()); } buf.printf( _T("#exec MESH NOTIFY MESH=%s SEQ=%s TIME=%s FUNCTION=%s"), FileName, SeqName, time, func ); _fputts( buf, fScript ); } } } } // TODO: write materials if( Materials.Count() > 0 ) { for( int i=0; i<Materials.Count(); ++i ) { IGameMaterial* mat = Materials[i].Mat; if( mat == NULL ) continue; _ftprintf( fScript, _T("#exec MESHMAP SETTEXTURE MESHMAP=%s NUM=%d TEXTURE=%s \n"), FileName, i, _T("DefaultTexture") ); } } } }