diff --git a/indra/llprimitive/lldaeloader.cpp b/indra/llprimitive/lldaeloader.cpp index 820924be33..47c5fb7924 100644 --- a/indra/llprimitive/lldaeloader.cpp +++ b/indra/llprimitive/lldaeloader.cpp @@ -116,14 +116,17 @@ std::string colladaVersion[VERSIONTYPE_COUNT+1] = "Unsupported" }; -static const std::string lod_suffix[LLModel::NUM_LODS] = -{ - "_LOD0", - "_LOD1", - "_LOD2", - "", - "_PHYS", -}; +// moved to allow configuration +// static const std::string lod_suffix[LLModel::NUM_LODS] = +// { +// "_LOD0", +// "_LOD1", +// "_LOD2", +// "", +// "_PHYS", +// }; +// + const U32 LIMIT_MATERIALS_OUTPUT = 12; @@ -931,7 +934,11 @@ LLDAELoader::LLDAELoader( std::map& jointAliasMap, U32 maxJointsPerMesh, U32 modelLimit, - bool preprocess) + // mesh loader suffix configuration + // bool preprocess) + bool preprocess, + const LODSuffixArray& lod_suffix) + // : LLModelLoader( filename, lod, @@ -947,12 +954,21 @@ LLDAELoader::LLDAELoader( mGeneratedModelLimit(modelLimit), mPreprocessDAE(preprocess) { + // mesh loader suffix configuration + for(int i=0;i } LLDAELoader::~LLDAELoader() { } +//static +LODSuffixArray LLDAELoader::sLODSuffix{};// configurable lod suffixes + struct ModelSort { bool operator()(const LLPointer< LLModel >& lhs, const LLPointer< LLModel >& rhs) @@ -2208,8 +2224,17 @@ void LLDAELoader::processElement( daeElement* element, bool& badElement, DAE* da { label += (char)((int)'a' + model->mSubmodelID); } - - model->mLabel = label + lod_suffix[mLod]; + // Support altenate LOD naming conventions + // model->mLabel = label + sLODSuffix[mLod]; + if ( sLODSuffix[mLod].size() > 0 ) + { + model->mLabel = label + '_' + sLODSuffix[mLod]; + } + else + { + model->mLabel = label; + } + // } else { @@ -2485,13 +2510,19 @@ std::string LLDAELoader::getElementLabel(daeElement *element) // static size_t LLDAELoader::getSuffixPosition(std::string label) { - // Bug fixes in mesh importer by Drake Arconis + // Selectable suffixes //if ((label.find("_LOD") != -1) || (label.find("_PHYS") != -1)) - if ((label.find("_LOD") != std::string::npos) || (label.find("_PHYS") != std::string::npos)) - // + //{ + // return label.rfind('_'); + //} + for(int i=0; i < LLModel::NUM_LODS; i++) { - return label.rfind('_'); + if (sLODSuffix[i].size() && label.find(sLODSuffix[i]) != std::string::npos) + { + return label.rfind('_'); + } } + // return -1; } @@ -2636,8 +2667,17 @@ bool LLDAELoader::loadModelsFromDomMesh(domMesh* mesh, std::vector& mo LLModel* ret = new LLModel(volume_params, 0.f); std::string model_name = getLodlessLabel(mesh); - ret->mLabel = model_name + lod_suffix[mLod]; - + // Support altenate LOD naming conventions + // ret->mLabel = model_name + sLODSuffix[mLod]; + if ( sLODSuffix[mLod].size() > 0 ) + { + ret->mLabel = model_name + '_' + sLODSuffix[mLod]; + } + else + { + ret->mLabel = model_name; + } + // llassert(!ret->mLabel.empty()); // Like a monkey, ready to be shot into space @@ -2695,7 +2735,10 @@ bool LLDAELoader::loadModelsFromDomMesh(domMesh* mesh, std::vector& mo { LLModel* next = new LLModel(volume_params, 0.f); next->mSubmodelID = ++submodelID; - next->mLabel = model_name + (char)((int)'a' + next->mSubmodelID) + lod_suffix[mLod]; + // configurable lod suffixes + // next->mLabel = model_name + (char)((int)'a' + next->mSubmodelID) + lod_suffix[mLod]; + next->mLabel = model_name + (char)((int)'a' + next->mSubmodelID) + sLODSuffix[mLod]; + // next->getVolumeFaces() = remainder; next->mNormalizedScale = ret->mNormalizedScale; next->mNormalizedTranslation = ret->mNormalizedTranslation; diff --git a/indra/llprimitive/lldaeloader.h b/indra/llprimitive/lldaeloader.h index 5d34cb8091..7ed1ea787a 100644 --- a/indra/llprimitive/lldaeloader.h +++ b/indra/llprimitive/lldaeloader.h @@ -39,6 +39,7 @@ class domController; class domSkin; class domMesh; +using LODSuffixArray = std::array; // configurable lod suffixes class LLDAELoader : public LLModelLoader { public: @@ -59,7 +60,11 @@ public: std::map& jointAliasMap, U32 maxJointsPerMesh, U32 modelLimit, - bool preprocess); + // configrable lod suffix support + // bool preprocess); + bool preprocess, + const LODSuffixArray& lod_suffix); + // virtual ~LLDAELoader() ; virtual bool OpenFile(const std::string& filename); @@ -104,6 +109,7 @@ protected: static std::string getLodlessLabel(daeElement *element); static std::string preprocessDAE(std::string filename); + static LODSuffixArray sLODSuffix; // mesh loader suffix configuration private: U32 mGeneratedModelLimit; // Attempt to limit amount of generated submodels diff --git a/indra/llprimitive/llmodel.cpp b/indra/llprimitive/llmodel.cpp index b40de81563..c3f6ee0642 100644 --- a/indra/llprimitive/llmodel.cpp +++ b/indra/llprimitive/llmodel.cpp @@ -634,10 +634,13 @@ void LLModel::generateNormals(F32 angle_cutoff) } } - +extern std::string stripSuffix(std::string); // mesh loader suffix configuration std::string LLModel::getName() const { - return mRequestedLabel.empty() ? mLabel : mRequestedLabel; + // remove the LOD suffix when used as the model name. + // return mRequestedLabel.empty() ? mLabel : mRequestedLabel; + return mRequestedLabel.empty() ? stripSuffix(mLabel) : mRequestedLabel; + // } //static diff --git a/indra/llprimitive/llmodelloader.cpp b/indra/llprimitive/llmodelloader.cpp index 33671b9bd2..3bacbfc522 100644 --- a/indra/llprimitive/llmodelloader.cpp +++ b/indra/llprimitive/llmodelloader.cpp @@ -218,7 +218,7 @@ void LLModelLoader::setLoadState(U32 state) { mStateCallback(state, mOpaqueData); } - +extern std::string stripSuffix(std::string); // mesh loader suffix configuration bool LLModelLoader::loadFromSLM(const std::string& filename) { //only need to populate mScene with data from slm @@ -320,7 +320,10 @@ bool LLModelLoader::loadFromSLM(const std::string& filename) && !instance_label.empty()) { // restore model names - std::string name = instance_label; + // This is going to get confusing here. We are juggling internal LOD names, with potentially overridden user ones. + // std::string name = instance_label; + std::string name = stripSuffix(instance_label); + // switch (lod) { case LLModel::LOD_IMPOSTOR: name += "_LOD0"; break; diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 618df007bf..8c9eda5847 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -9239,6 +9239,62 @@ Backup 0 + FSMeshLowestLodSuffix + + Comment + Suffix to use for Lowest LOD models and files (DAE). + Persist + 1 + Type + String + Value + LOD0 + + FSMeshLowLodSuffix + + Comment + Suffix to use for Low LOD models and files (DAE). + Persist + 1 + Type + String + Value + LOD1 + + FSMeshMediumLodSuffix + + Comment + Suffix to use for Medium LOD models and files (DAE). + Persist + 1 + Type + String + Value + LOD2 + + FSMeshHighLodSuffix + + Comment + Suffix to use for High LOD models and files (DAE). + Persist + 1 + Type + String + Value + + + FSMeshPhysicsSuffix + + Comment + Suffix to use for Physics models and files (DAE). + Persist + 1 + Type + String + Value + PHYS + + FSMeshUploadAutoEnableWeights Comment diff --git a/indra/newview/llfloatermodelpreview.cpp b/indra/newview/llfloatermodelpreview.cpp index 49e036cec6..08eeded896 100644 --- a/indra/newview/llfloatermodelpreview.cpp +++ b/indra/newview/llfloatermodelpreview.cpp @@ -122,6 +122,12 @@ void LLMeshFilePicker::notify(const std::vector& filenames) } } +// support for settings panel of floater +const void updateUDPhysics(const std::vector& filenames, LLFilePicker::ELoadFilter type) +{ + gSavedSettings.setString("FSPhysicsPresetUser1", filenames[0]); +} +// //----------------------------------------------------------------------------- // LLFloaterModelPreview() //----------------------------------------------------------------------------- @@ -146,6 +152,14 @@ mAvatarTabIndex(0) } } +// support for settings panel of floater +//static +void LLFloaterModelPreview::onSelectUDPhysics(LLUICtrl* ctrl, void* userdata) +{ + (new LLFilePickerReplyThread(boost::bind(&updateUDPhysics, _1, _2), LLFilePicker::FFLOAD_COLLADA, false))->getFile(); +} +// + //----------------------------------------------------------------------------- // postBuild() //----------------------------------------------------------------------------- @@ -209,6 +223,9 @@ BOOL LLFloaterModelPreview::postBuild() getChild("mesh_preview_physics_fill_color")->setCommitCallback(preview_refresh_cb); getChild("mesh_preview_degenerate_edge_color")->setCommitCallback(preview_refresh_cb); getChild("mesh_preview_degenerate_fill_color")->setCommitCallback(preview_refresh_cb); + + getChild("lod_suffix_combo")->setCommitCallback(boost::bind(&LLFloaterModelPreview::onSuffixStandardSelected, this, _1)); // mesh loader suffix configuration + getChild("set_user_def_phys")->setCommitCallback(boost::bind(&LLFloaterModelPreview::onSelectUDPhysics, this, _1)); // mesh loader suffix configuration // childDisable("upload_skin"); @@ -1185,6 +1202,75 @@ void LLFloaterModelPreview::onPhysicsUseLOD(LLUICtrl* ctrl, void* userdata) } } +// mesh loader suffix configuration +//static +void LLFloaterModelPreview::onSuffixStandardSelected(LLUICtrl* ctrl, void* userdata) +{ + S32 which{0}; +// SL standard LODs are the reverse of every other game engine (LOD0 least detail) +// SL has no suffix for the HIGH LOD + const std::array sl_suffixes = { + "LOD0", + "LOD1", + "LOD2", + "", + "PHYS" + }; +// Game engines (UE, Unity, CryEngine, Godot, etc.) all use LOD0 as highest. +// They typically also label the high with a suffix too + const std::array std_suffixes = { + "LOD3", + "LOD2", + "LOD1", + "LOD0", + "PHYS" + }; +// Human friendly. When making things manually people naturally use names. + const std::array desc_suffixes = { + "LOWEST", + "LOW", + "MED", + "HIGH", + "PHYS" + }; + + LLCtrlSelectionInterface* iface = sInstance->childGetSelectionInterface("lod_suffix_combo"); + if (iface) + { + which = iface->getFirstSelectedIndex(); + } + else + { + LL_WARNS() << "no UI element found! nothing changed" << LL_ENDL; + return; + } + + switch (which) + { + case 1: // SL + for (int i = 0; i < LLModel::NUM_LODS; i++) + { + gSavedSettings.setString(LLModelPreview::sSuffixVarNames[i], sl_suffixes[i]); + } + break; + case 2: // standard + for (int i = 0; i < LLModel::NUM_LODS; i++) + { + gSavedSettings.setString(LLModelPreview::sSuffixVarNames[i], std_suffixes[i]); + } + break; + case 3: // descriptive english + for (int i = 0; i < LLModel::NUM_LODS; i++) + { + gSavedSettings.setString(LLModelPreview::sSuffixVarNames[i], desc_suffixes[i]); + } + break; + default: + LL_WARNS() << "no standard selected, nothing changed" << LL_ENDL; + break; + }; +} +// //static void LLFloaterModelPreview::onCancel(LLUICtrl* ctrl, void* data) { diff --git a/indra/newview/llfloatermodelpreview.h b/indra/newview/llfloatermodelpreview.h index 1e147cd555..4737a73311 100644 --- a/indra/newview/llfloatermodelpreview.h +++ b/indra/newview/llfloatermodelpreview.h @@ -106,7 +106,7 @@ public: void loadModel(S32 lod, const std::string& file_name, bool force_disable_slm = false); void loadHighLodModel(); - + void onViewOptionChecked(LLUICtrl* ctrl); void onUploadOptionChecked(LLUICtrl* ctrl); bool isViewOptionChecked(const LLSD& userdata); @@ -167,6 +167,8 @@ protected: static void onPhysicsOptimize(LLUICtrl* ctrl, void* userdata); static void onPhysicsDecomposeBack(LLUICtrl* ctrl, void* userdata); static void onPhysicsSimplifyBack(LLUICtrl* ctrl, void* userdata); + static void onSuffixStandardSelected(LLUICtrl* ctrl, void* userdata); // mesh loader suffix configuration + static void onSelectUDPhysics(LLUICtrl* ctrl, void* userdata); // custom setter for upload preview settings tab void draw(); diff --git a/indra/newview/llmodelpreview.cpp b/indra/newview/llmodelpreview.cpp index 97ed39dc54..c49119cb85 100644 --- a/indra/newview/llmodelpreview.cpp +++ b/indra/newview/llmodelpreview.cpp @@ -92,6 +92,17 @@ bool LLModelPreview::sIgnoreLoadedCallback = false; // const F32 SKIN_WEIGHT_CAMERA_DISTANCE = 16.f; +// mesh loader suffix configuration +//static +const std::array LLModelPreview::sSuffixVarNames +{ + "FSMeshLowestLodSuffix", + "FSMeshLowLodSuffix", + "FSMeshMediumLodSuffix", + "FSMeshHighLodSuffix", + "FSMeshPhysicsSuffix" +}; +// LLViewerFetchedTexture* bindMaterialDiffuseTexture(const LLImportMaterial& material) { LLViewerFetchedTexture *texture = LLViewerTextureManager::getFetchedTexture(material.getDiffuseMap(), FTT_DEFAULT, TRUE, LLGLTexture::BOOST_PREVIEW); @@ -110,13 +121,19 @@ LLViewerFetchedTexture* bindMaterialDiffuseTexture(const LLImportMaterial& mater std::string stripSuffix(std::string name) { - // Bug fixes in mesh importer by Drake Arconis + // Selectable suffixes //if ((name.find("_LOD") != -1) || (name.find("_PHYS") != -1)) - if ((name.find("_LOD") != std::string::npos) || (name.find("_PHYS") != std::string::npos)) - // + // { + // return name.substr(0, name.rfind('_')); + // } + for(int i=0; i < LLModel::NUM_LODS; i++) { - return name.substr(0, name.rfind('_')); - } + const auto& suffix = gSavedSettings.getString(LLModelPreview::sSuffixVarNames[i]); + if (suffix.size() && name.find(suffix) != std::string::npos) + { + return name.substr(0, name.rfind('_')); + } + } // return name; } @@ -125,12 +142,24 @@ std::string getLodSuffix(S32 lod) std::string suffix; switch (lod) { - case LLModel::LOD_IMPOSTOR: suffix = "_LOD0"; break; - case LLModel::LOD_LOW: suffix = "_LOD1"; break; - case LLModel::LOD_MEDIUM: suffix = "_LOD2"; break; - case LLModel::LOD_PHYSICS: suffix = "_PHYS"; break; - case LLModel::LOD_HIGH: break; + // selectable suffixes + // case LLModel::LOD_IMPOSTOR: suffix = "_LOD0"; break; + // case LLModel::LOD_LOW: suffix = "_LOD1"; break; + // case LLModel::LOD_MEDIUM: suffix = "_LOD2"; break; + // case LLModel::LOD_PHYSICS: suffix = "_PHYS"; break; + // case LLModel::LOD_HIGH: break; + case LLModel::LOD_IMPOSTOR: suffix = gSavedSettings.getString("FSMeshLowestLodSuffix"); break; + case LLModel::LOD_LOW: suffix = gSavedSettings.getString("FSMeshLowLodSuffix"); break; + case LLModel::LOD_MEDIUM: suffix = gSavedSettings.getString("FSMeshMediumLodSuffix"); break; + case LLModel::LOD_HIGH: suffix = gSavedSettings.getString("FSMeshHighLodSuffix"); break; + case LLModel::LOD_PHYSICS: suffix = gSavedSettings.getString("FSMeshPhysicsSuffix"); break; + default:break; } + if(suffix.size()) + { + suffix = "_" + suffix; + } + // return suffix; } @@ -461,8 +490,10 @@ void LLModelPreview::rebuildUploadData() // then the indexed method will be attempted below. LLMatrix4 transform; - - std::string name_to_match = instance.mLabel; + // user defined LOD names + // std::string name_to_match = instance.mLabel; + std::string name_to_match = stripSuffix(instance.mLabel); + // llassert(!name_to_match.empty()); int extensionLOD; @@ -503,7 +534,10 @@ void LLModelPreview::rebuildUploadData() int searchLOD = (i > LLModel::LOD_HIGH) ? LLModel::LOD_HIGH : i; while ((searchLOD <= LLModel::LOD_HIGH) && !lod_model) { - std::string name_to_match = instance.mLabel; + // user defined LOD names + // std::string name_to_match = instance.mLabel; + std::string name_to_match = stripSuffix(instance.mLabel); + // llassert(!name_to_match.empty()); std::string toAdd = getLodSuffix(searchLOD); @@ -536,6 +570,13 @@ void LLModelPreview::rebuildUploadData() { std::ostringstream out; out << "Attempting to use model index " << idx; + // better debug (watch for dangling single line else) + if(i==4) + { + out << " for PHYS"; + } + else + // out << " for LOD" << i; out << " of " << instance.mLabel; LL_INFOS() << out.str() << LL_ENDL; @@ -881,6 +922,12 @@ void LLModelPreview::loadModel(std::string filename, S32 lod, bool force_disable std::map joint_alias_map; getJointAliases(joint_alias_map); + std::array lod_suffix; + for(int i=0; i < LLModel::NUM_LODS; i++) + { + lod_suffix[i] = gSavedSettings.getString(sSuffixVarNames[i]); + } + mModelLoader = new LLDAELoader( filename, lod, @@ -894,7 +941,10 @@ void LLModelPreview::loadModel(std::string filename, S32 lod, bool force_disable joint_alias_map, LLSkinningUtil::getMaxJointCount(), gSavedSettings.getU32("ImporterModelLimit"), - gSavedSettings.getBOOL("ImporterPreprocessDAE")); + // allow LOD suffix configuration + // gSavedSettings.getBOOL("ImporterPreprocessDAE")); + gSavedSettings.getBOOL("ImporterPreprocessDAE"), + lod_suffix); if (force_disable_slm) { @@ -1230,7 +1280,7 @@ void LLModelPreview::loadModelCallback(S32 loaded_lod) // this actually works like "ImporterLegacyMatching" for this particular LOD for (U32 idx = 0; idx < mModel[loaded_lod].size() && idx < mBaseModel.size(); ++idx) { - std::string name = mBaseModel[idx]->mLabel; + std::string name = stripSuffix(mBaseModel[idx]->mLabel); std::string loaded_name = stripSuffix(mModel[loaded_lod][idx]->mLabel); if (loaded_name != name) @@ -1881,7 +1931,15 @@ void LLModelPreview::genMeshOptimizerLODs(S32 which_lod, S32 meshopt_mode, U32 d volume_params.setType(LL_PCODE_PROFILE_SQUARE, LL_PCODE_PATH_LINE); mModel[lod][mdl_idx] = new LLModel(volume_params, 0.f); - std::string name = base->mLabel + getLodSuffix(lod); + // Support altenate LOD naming conventions + // std::string name = base->mLabel + getLodSuffix(lod); + std::string name = stripSuffix(base->mLabel); + std::string suffix = getLodSuffix(lod); + if ( suffix.size() > 0 ) + { + name += suffix; + } + // mModel[lod][mdl_idx]->mLabel = name; mModel[lod][mdl_idx]->mSubmodelID = base->mSubmodelID; @@ -3167,7 +3225,7 @@ void LLModelPreview::lookupLODModelFiles(S32 lod) // Note: we cannot use gDirUtilp here because the getExtension forces a tolower which would then break uppercase extensions on Linux/Mac std::size_t offset = lod_filename.find_last_of('.'); std::string ext = (offset == std::string::npos || offset == 0) ? "" : lod_filename.substr(offset+1); - lod_filename = gDirUtilp->getDirName(lod_filename) + gDirUtilp->getDirDelimiter() + gDirUtilp->getBaseFileName(lod_filename, true) + getLodSuffix(next_lod) + "." + ext; + lod_filename = gDirUtilp->getDirName(lod_filename) + gDirUtilp->getDirDelimiter() + stripSuffix(gDirUtilp->getBaseFileName(lod_filename, true)) + getLodSuffix(next_lod) + "." + ext; std::ostringstream out; out << "Looking for file: " << lod_filename << " for LOD " << next_lod; LL_DEBUGS("MeshUpload") << out.str() << LL_ENDL; diff --git a/indra/newview/llmodelpreview.h b/indra/newview/llmodelpreview.h index 5712dfbae2..30c9afe842 100644 --- a/indra/newview/llmodelpreview.h +++ b/indra/newview/llmodelpreview.h @@ -120,6 +120,7 @@ class LLModelPreview : public LLViewerDynamicTexture, public LLMutex typedef boost::signals2::signal model_updated_signal_t; public: + static const std::array sSuffixVarNames; // mesh loader suffix configuration typedef enum { diff --git a/indra/newview/skins/default/xui/en/floater_model_preview.xml b/indra/newview/skins/default/xui/en/floater_model_preview.xml index 99e6741e30..5e292c6760 100644 --- a/indra/newview/skins/default/xui/en/floater_model_preview.xml +++ b/indra/newview/skins/default/xui/en/floater_model_preview.xml @@ -1471,30 +1471,187 @@ tool_tip="Automatically show weights in preview for meshes with rigging info" name="mesh_preview_auto_show_weights"/> + LOD Suffixes: + + + Choose a standard or manually edit... + SL Standard (Lowest=LOD0) + Games Engine Standard (Lowest=LOD3) + Words (high,med...) + + - Physics User Defined Preset: + halign="right" + width="60"> + Lowest: - + + Low: + + + + Medium: + + + + High: + + + + Physics: + + + + Physics User Defined Preset: + + + + Physics: @@ -1567,7 +1724,7 @@ control_name="MeshPreviewPhysicsEdgeColor" follows="top|left" left_pad="14" - height="64" + height="48" can_apply_immediately="true" width="120" top_delta="-12" @@ -1577,8 +1734,8 @@ Physics Issues: @@ -1602,7 +1759,7 @@ control_name="MeshPreviewDegenerateEdgeColor" follows="top|left" left_pad="14" - height="64" + height="48" width="120" top_delta="-12" can_apply_immediately="true" @@ -1613,7 +1770,7 @@ control_name="MeshPreviewDegenerateFillColor" follows="top|left" left_pad="24" - height="64" + height="48" width="120" can_apply_immediately="true" label="Bad Triangle Fill"