summaryrefslogtreecommitdiff
path: root/indra/newview/llfloatermodelpreview.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/newview/llfloatermodelpreview.cpp')
-rwxr-xr-x[-rw-r--r--]indra/newview/llfloatermodelpreview.cpp1862
1 files changed, 1187 insertions, 675 deletions
diff --git a/indra/newview/llfloatermodelpreview.cpp b/indra/newview/llfloatermodelpreview.cpp
index ab6753b4be..7448f2bb2a 100644..100755
--- a/indra/newview/llfloatermodelpreview.cpp
+++ b/indra/newview/llfloatermodelpreview.cpp
@@ -26,6 +26,10 @@
#include "llviewerprecompiledheaders.h"
+#if LL_MSVC
+#pragma warning (disable : 4263)
+#pragma warning (disable : 4264)
+#endif
#include "dae.h"
//#include "dom.h"
#include "dom/domAsset.h"
@@ -47,6 +51,10 @@
#include "dom/domScale.h"
#include "dom/domTranslate.h"
#include "dom/domVisual_scene.h"
+#if LL_MSVC
+#pragma warning (default : 4263)
+#pragma warning (default : 4264)
+#endif
#include "llfloatermodelpreview.h"
@@ -71,6 +79,7 @@
#include "llmatrix4a.h"
#include "llmenubutton.h"
#include "llmeshrepository.h"
+#include "llnotificationsutil.h"
#include "llsdutil_math.h"
#include "lltextbox.h"
#include "lltoolmgr.h"
@@ -95,12 +104,19 @@
#include "llsliderctrl.h"
#include "llspinctrl.h"
#include "lltoggleablemenu.h"
+#include "lltrans.h"
#include "llvfile.h"
#include "llvfs.h"
#include "llcallbacklist.h"
#include "llviewerobjectlist.h"
#include "llanimationstates.h"
+#include "llviewernetwork.h"
+#include "llviewershadermgr.h"
#include "glod/glod.h"
+#include <boost/algorithm/string.hpp>
+
+
+const S32 SLM_SUPPORTED_VERSION = 3;
//static
S32 LLFloaterModelPreview::sUploadAmount = 10;
@@ -113,6 +129,19 @@ const S32 PREVIEW_HPAD = PREVIEW_RESIZE_HANDLE_SIZE;
const S32 PREF_BUTTON_HEIGHT = 16 + 7 + 16;
const S32 PREVIEW_TEXTURE_HEIGHT = 300;
+// "Retain%" decomp parameter has values from 0.0 to 1.0 by 0.01
+// But according to the UI spec for upload model floater, this parameter
+// should be represented by Retain spinner with values from 1 to 100 by 1.
+// To achieve this, RETAIN_COEFFICIENT is used while creating spinner
+// and when value is requested from spinner.
+const double RETAIN_COEFFICIENT = 100;
+
+// "Cosine%" decomp parameter has values from 0.9 to 1 by 0.001
+// But according to the UI spec for upload model floater, this parameter
+// should be represented by Smooth combobox with only 10 values.
+// So this const is used as a size of Smooth combobox list.
+const S32 SMOOTH_VALUES_NUMBER = 10;
+
void drawBoxOutline(const LLVector3& pos, const LLVector3& size);
@@ -178,6 +207,13 @@ std::string lod_label_name[NUM_LOD+1] =
"I went off the end of the lod_label_name array. Me so smart."
};
+std::string colladaVersion[VERSIONTYPE_COUNT+1] =
+{
+ "1.4.0",
+ "1.4.1",
+ "Unsupported"
+};
+
#define LL_DEGENERACY_TOLERANCE 1e-7f
@@ -353,13 +389,16 @@ void LLMeshFilePicker::notify(const std::string& filename)
// LLFloaterModelPreview()
//-----------------------------------------------------------------------------
LLFloaterModelPreview::LLFloaterModelPreview(const LLSD& key) :
-LLFloater(key)
+LLFloaterModelUploadBase(key),
+mUploadBtn(NULL),
+mCalculateBtn(NULL)
{
sInstance = this;
mLastMouseX = 0;
mLastMouseY = 0;
mGLName = 0;
mStatusLock = new LLMutex(NULL);
+ mModelPreview = NULL;
mLODMode[LLModel::LOD_HIGH] = 0;
for (U32 i = 0; i < LLModel::LOD_HIGH; i++)
@@ -378,32 +417,35 @@ BOOL LLFloaterModelPreview::postBuild()
return FALSE;
}
- childSetAction("lod_browse", onBrowseLOD, this);
-
childSetCommitCallback("cancel_btn", onCancel, this);
childSetCommitCallback("crease_angle", onGenerateNormalsCommit, this);
- childSetCommitCallback("generate_normals", onGenerateNormalsCommit, this);
+ getChild<LLCheckBoxCtrl>("gen_normals")->setCommitCallback(boost::bind(&LLFloaterModelPreview::toggleGenarateNormals, this));
childSetCommitCallback("lod_generate", onAutoFillCommit, this);
- childSetCommitCallback("lod_mode", onLODParamCommit, this);
- childSetCommitCallback("lod_error_threshold", onLODParamCommit, this);
- childSetCommitCallback("lod_triangle_limit", onLODParamCommitTriangleLimit, this);
- childSetCommitCallback("build_operator", onLODParamCommit, this);
- childSetCommitCallback("queue_mode", onLODParamCommit, this);
- childSetCommitCallback("border_mode", onLODParamCommit, this);
- childSetCommitCallback("share_tolerance", onLODParamCommit, this);
+ for (S32 lod = 0; lod <= LLModel::LOD_HIGH; ++lod)
+ {
+ LLComboBox* lod_source_combo = getChild<LLComboBox>("lod_source_" + lod_name[lod]);
+ lod_source_combo->setCommitCallback(boost::bind(&LLFloaterModelPreview::onLoDSourceCommit, this, lod));
+ lod_source_combo->setCurrentByIndex(mLODMode[lod]);
+
+ getChild<LLButton>("lod_browse_" + lod_name[lod])->setCommitCallback(boost::bind(&LLFloaterModelPreview::onBrowseLOD, this, lod));
+ getChild<LLComboBox>("lod_mode_" + lod_name[lod])->setCommitCallback(boost::bind(&LLFloaterModelPreview::onLODParamCommit, this, lod, false));
+ getChild<LLSpinCtrl>("lod_error_threshold_" + lod_name[lod])->setCommitCallback(boost::bind(&LLFloaterModelPreview::onLODParamCommit, this, lod, false));
+ getChild<LLSpinCtrl>("lod_triangle_limit_" + lod_name[lod])->setCommitCallback(boost::bind(&LLFloaterModelPreview::onLODParamCommit, this, lod, true));
+ }
+
+ childSetCommitCallback("upload_skin", boost::bind(&LLFloaterModelPreview::toggleCalculateButton, this), NULL);
+ childSetCommitCallback("upload_joints", boost::bind(&LLFloaterModelPreview::toggleCalculateButton, this), NULL);
+ childSetCommitCallback("upload_textures", boost::bind(&LLFloaterModelPreview::toggleCalculateButton, this), NULL);
childSetTextArg("status", "[STATUS]", getString("status_idle"));
- //childSetLabelArg("ok_btn", "[AMOUNT]", llformat("%d",sUploadAmount));
childSetAction("ok_btn", onUpload, this);
childDisable("ok_btn");
childSetAction("reset_btn", onReset, this);
- childSetAction("clear_materials", onClearMaterials, this);
-
childSetCommitCallback("preview_lod_combo", onPreviewLODCommit, this);
childSetCommitCallback("upload_skin", onUploadSkinCommit, this);
@@ -412,28 +454,14 @@ BOOL LLFloaterModelPreview::postBuild()
childSetCommitCallback("import_scale", onImportScaleCommit, this);
childSetCommitCallback("pelvis_offset", onPelvisOffsetCommit, this);
- childSetCommitCallback("lod_file_or_limit", refresh, this);
- childSetCommitCallback("physics_load_radio", onPhysicsLoadRadioCommit, this);
- //childSetCommitCallback("physics_optimize", refresh, this);
- //childSetCommitCallback("physics_use_hull", refresh, this);
+ getChild<LLCheckBoxCtrl>("show_edges")->setCommitCallback(boost::bind(&LLFloaterModelPreview::onViewOptionChecked, this, _1));
+ getChild<LLCheckBoxCtrl>("show_physics")->setCommitCallback(boost::bind(&LLFloaterModelPreview::onViewOptionChecked, this, _1));
+ getChild<LLCheckBoxCtrl>("show_textures")->setCommitCallback(boost::bind(&LLFloaterModelPreview::onViewOptionChecked, this, _1));
+ getChild<LLCheckBoxCtrl>("show_skin_weight")->setCommitCallback(boost::bind(&LLFloaterModelPreview::onViewOptionChecked, this, _1));
+ getChild<LLCheckBoxCtrl>("show_joint_positions")->setCommitCallback(boost::bind(&LLFloaterModelPreview::onViewOptionChecked, this, _1));
childDisable("upload_skin");
childDisable("upload_joints");
-
- childDisable("ok_btn");
-
- childSetCommitCallback("confirm_checkbox", refresh, this);
-
- mViewOptionMenuButton = getChild<LLMenuButton>("options_gear_btn");
-
- mCommitCallbackRegistrar.add("ModelImport.ViewOption.Action", boost::bind(&LLFloaterModelPreview::onViewOptionChecked, this, _2));
- mEnableCallbackRegistrar.add("ModelImport.ViewOption.Check", boost::bind(&LLFloaterModelPreview::isViewOptionChecked, this, _2));
- mEnableCallbackRegistrar.add("ModelImport.ViewOption.Enabled", boost::bind(&LLFloaterModelPreview::isViewOptionEnabled, this, _2));
-
-
-
- mViewOptionMenu = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>("menu_model_import_gear_default.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
- mViewOptionMenuButton->setMenu(mViewOptionMenu, LLMenuButton::MP_BOTTOM_LEFT);
initDecompControls();
@@ -441,9 +469,7 @@ BOOL LLFloaterModelPreview::postBuild()
mPreviewRect = preview_panel->getRect();
- mModelPreview = new LLModelPreview(512, 512, this );
- mModelPreview->setPreviewTarget(16.f);
- mModelPreview->setDetailsCallback(boost::bind(&LLFloaterModelPreview::setDetails, this, _1, _2, _3, _4, _5));
+ initModelPreview();
//set callbacks for left click on line editor rows
for (U32 i = 0; i <= LLModel::LOD_HIGH; i++)
@@ -472,6 +498,30 @@ BOOL LLFloaterModelPreview::postBuild()
text->setMouseDownCallback(boost::bind(&LLModelPreview::setPreviewLOD, mModelPreview, i));
}
}
+ std::string current_grid = LLGridManager::getInstance()->getGridLabel();
+ std::transform(current_grid.begin(),current_grid.end(),current_grid.begin(),::tolower);
+ std::string validate_url;
+ if (current_grid == "agni")
+ {
+ validate_url = "http://secondlife.com/my/account/mesh.php";
+ }
+ else if (current_grid == "damballah")
+ {
+ // Staging grid has its own naming scheme.
+ validate_url = "http://secondlife-staging.com/my/account/mesh.php";
+ }
+ else
+ {
+ validate_url = llformat("http://secondlife.%s.lindenlab.com/my/account/mesh.php",current_grid.c_str());
+ }
+ getChild<LLTextBox>("warning_message")->setTextArg("[VURL]", validate_url);
+
+ mUploadBtn = getChild<LLButton>("ok_btn");
+ mCalculateBtn = getChild<LLButton>("calculate_btn");
+
+ mCalculateBtn->setClickedCallback(boost::bind(&LLFloaterModelPreview::onClickCalculateBtn, this));
+
+ toggleCalculateButton(true);
return TRUE;
}
@@ -497,11 +547,24 @@ LLFloaterModelPreview::~LLFloaterModelPreview()
mStatusLock = NULL;
}
-void LLFloaterModelPreview::onViewOptionChecked(const LLSD& userdata)
+void LLFloaterModelPreview::initModelPreview()
+{
+ if (mModelPreview)
+ {
+ delete mModelPreview;
+ }
+
+ mModelPreview = new LLModelPreview(512, 512, this );
+ mModelPreview->setPreviewTarget(16.f);
+ mModelPreview->setDetailsCallback(boost::bind(&LLFloaterModelPreview::setDetails, this, _1, _2, _3, _4, _5));
+ mModelPreview->setModelUpdatedCallback(boost::bind(&LLFloaterModelPreview::toggleCalculateButton, this, _1));
+}
+
+void LLFloaterModelPreview::onViewOptionChecked(LLUICtrl* ctrl)
{
if (mModelPreview)
{
- mModelPreview->mViewOption[userdata.asString()] = !mModelPreview->mViewOption[userdata.asString()];
+ mModelPreview->mViewOption[ctrl->getName()] = !mModelPreview->mViewOption[ctrl->getName()];
mModelPreview->refresh();
}
@@ -519,12 +582,12 @@ bool LLFloaterModelPreview::isViewOptionChecked(const LLSD& userdata)
bool LLFloaterModelPreview::isViewOptionEnabled(const LLSD& userdata)
{
- return !mViewOptionDisabled[userdata.asString()];
+ return childIsEnabled(userdata.asString());
}
void LLFloaterModelPreview::setViewOptionEnabled(const std::string& option, bool enabled)
{
- mViewOptionDisabled[option] = !enabled;
+ childSetEnabled(option, enabled);
}
void LLFloaterModelPreview::enableViewOption(const std::string& option)
@@ -544,6 +607,30 @@ void LLFloaterModelPreview::loadModel(S32 lod)
(new LLMeshFilePicker(mModelPreview, lod))->getFile();
}
+void LLFloaterModelPreview::loadModel(S32 lod, const std::string& file_name, bool force_disable_slm)
+{
+ mModelPreview->mLoading = true;
+
+ mModelPreview->loadModel(file_name, lod, force_disable_slm);
+}
+
+void LLFloaterModelPreview::onClickCalculateBtn()
+{
+ mModelPreview->rebuildUploadData();
+
+ bool upload_skinweights = childGetValue("upload_skin").asBoolean();
+ bool upload_joint_positions = childGetValue("upload_joints").asBoolean();
+
+ mUploadModelUrl.clear();
+
+ gMeshRepo.uploadModel(mModelPreview->mUploadData, mModelPreview->mPreviewScale,
+ childGetValue("upload_textures").asBoolean(), upload_skinweights, upload_joint_positions, mUploadModelUrl, false,
+ getWholeModelFeeObserverHandle());
+
+ toggleCalculateButton(false);
+ mUploadBtn->setEnabled(false);
+}
+
//static
void LLFloaterModelPreview::onImportScaleCommit(LLUICtrl*,void* userdata)
{
@@ -554,7 +641,10 @@ void LLFloaterModelPreview::onImportScaleCommit(LLUICtrl*,void* userdata)
return;
}
- fp->mModelPreview->calcResourceCost();
+ fp->mModelPreview->mDirty = true;
+
+ fp->toggleCalculateButton(true);
+
fp->mModelPreview->refresh();
}
//static
@@ -566,31 +656,12 @@ void LLFloaterModelPreview::onPelvisOffsetCommit( LLUICtrl*, void* userdata )
{
return;
}
- fp->mModelPreview->calcResourceCost();
- fp->mModelPreview->refresh();
-}
-//static
-void LLFloaterModelPreview::onPhysicsLoadRadioCommit( LLUICtrl*, void *userdata)
-{
- LLFloaterModelPreview* fmp = LLFloaterModelPreview::sInstance;
- if (fmp)
- {
- if (fmp->childGetValue("physics_use_lod").asBoolean())
- {
- onPhysicsUseLOD(NULL,NULL);
- }
- if (fmp->childGetValue("physics_load_from_file").asBoolean())
- {
-
- }
- LLModelPreview *model_preview = fmp->mModelPreview;
- if (model_preview)
- {
- model_preview->refresh();
- model_preview->updateStatusMessages();
- }
- }
+ fp->mModelPreview->mDirty = true;
+
+ fp->toggleCalculateButton(true);
+
+ fp->mModelPreview->refresh();
}
//static
@@ -615,8 +686,6 @@ void LLFloaterModelPreview::onUploadSkinCommit(LLUICtrl*,void* userdata)
{
return;
}
-
- fp->mModelPreview->calcResourceCost();
fp->mModelPreview->refresh();
fp->mModelPreview->resetPreviewTarget();
fp->mModelPreview->clearBuffers();
@@ -649,6 +718,12 @@ void LLFloaterModelPreview::onGenerateNormalsCommit(LLUICtrl* ctrl, void* userda
fp->mModelPreview->generateNormals();
}
+void LLFloaterModelPreview::toggleGenarateNormals()
+{
+ bool enabled = childGetValue("gen_normals").asBoolean();
+ childSetEnabled("crease_angle", enabled);
+}
+
//static
void LLFloaterModelPreview::onExplodeCommit(LLUICtrl* ctrl, void* userdata)
{
@@ -665,18 +740,9 @@ void LLFloaterModelPreview::onAutoFillCommit(LLUICtrl* ctrl, void* userdata)
fp->mModelPreview->genLODs();
}
-//static
-void LLFloaterModelPreview::onLODParamCommit(LLUICtrl* ctrl, void* userdata)
+void LLFloaterModelPreview::onLODParamCommit(S32 lod, bool enforce_tri_limit)
{
- LLFloaterModelPreview* fp = (LLFloaterModelPreview*) userdata;
- fp->mModelPreview->onLODParamCommit(false);
-}
-
-//static
-void LLFloaterModelPreview::onLODParamCommitTriangleLimit(LLUICtrl* ctrl, void* userdata)
-{
- LLFloaterModelPreview* fp = (LLFloaterModelPreview*) userdata;
- fp->mModelPreview->onLODParamCommit(true);
+ mModelPreview->onLODParamCommit(lod, enforce_tri_limit);
}
@@ -692,6 +758,11 @@ void LLFloaterModelPreview::draw()
if (!mModelPreview->mLoading)
{
+ if ( mModelPreview->getLoadState() == LLModelLoader::ERROR_MATERIALS )
+ {
+ childSetTextArg("status", "[STATUS]", getString("status_material_mismatch"));
+ }
+ else
if ( mModelPreview->getLoadState() > LLModelLoader::ERROR_PARSING )
{
childSetTextArg("status", "[STATUS]", getString(LLModel::getStatusString(mModelPreview->getLoadState() - LLModelLoader::ERROR_PARSING)));
@@ -700,6 +771,7 @@ void LLFloaterModelPreview::draw()
if ( mModelPreview->getLoadState() == LLModelLoader::ERROR_PARSING )
{
childSetTextArg("status", "[STATUS]", getString("status_parse_error"));
+ toggleCalculateButton(false);
}
else
{
@@ -710,28 +782,6 @@ void LLFloaterModelPreview::draw()
childSetTextArg("prim_cost", "[PRIM_COST]", llformat("%d", mModelPreview->mResourceCost));
childSetTextArg("description_label", "[TEXTURES]", llformat("%d", mModelPreview->mTextureSet.size()));
- if (!mCurRequest.empty())
- {
- LLMutexLock lock(mStatusLock);
- childSetTextArg("status", "[STATUS]", mStatusMessage);
- }
- else
- {
- childSetVisible("Simplify", true);
- childSetVisible("simplify_cancel", false);
- childSetVisible("Decompose", true);
- childSetVisible("decompose_cancel", false);
- }
-
- U32 resource_cost = mModelPreview->mResourceCost*10;
-
- if (childGetValue("upload_textures").asBoolean())
- {
- resource_cost += mModelPreview->mTextureSet.size()*10;
- }
-
- childSetLabelArg("ok_btn", "[AMOUNT]", llformat("%d", resource_cost));
-
if (mModelPreview)
{
gGL.color3f(1.f, 1.f, 1.f);
@@ -864,6 +914,12 @@ BOOL LLFloaterModelPreview::handleScrollWheel(S32 x, S32 y, S32 clicks)
return TRUE;
}
+/*virtual*/
+void LLFloaterModelPreview::onOpen(const LLSD& key)
+{
+ requestAgentUploadPermissions();
+}
+
//static
void LLFloaterModelPreview::onPhysicsParamCommit(LLUICtrl* ctrl, void* data)
{
@@ -877,20 +933,32 @@ void LLFloaterModelPreview::onPhysicsParamCommit(LLUICtrl* ctrl, void* data)
{
LLCDParam* param = (LLCDParam*) data;
std::string name(param->mName);
- sInstance->mDecompParams[name] = ctrl->getValue();
+
+ LLSD value = ctrl->getValue();
+
+ if("Retain%" == name)
+ {
+ value = ctrl->getValue().asReal() / RETAIN_COEFFICIENT;
+ }
+
+ sInstance->mDecompParams[name] = value;
if (name == "Simplify Method")
{
- if (ctrl->getValue().asInteger() == 0)
- {
- sInstance->childSetVisible("Retain%", true);
- sInstance->childSetVisible("Detail Scale", false);
- }
- else
+ bool show_retain = false;
+ bool show_detail = true;
+
+ if (ctrl->getValue().asInteger() == 0)
{
- sInstance->childSetVisible("Retain%", false);
- sInstance->childSetVisible("Detail Scale", true);
+ show_retain = true;
+ show_detail = false;
}
+
+ sInstance->childSetVisible("Retain%", show_retain);
+ sInstance->childSetVisible("Retain%_label", show_retain);
+
+ sInstance->childSetVisible("Detail Scale", show_detail);
+ sInstance->childSetVisible("Detail Scale label", show_detail);
}
}
}
@@ -925,12 +993,14 @@ void LLFloaterModelPreview::onPhysicsStageExecute(LLUICtrl* ctrl, void* data)
sInstance->setStatusMessage(sInstance->getString("decomposing"));
sInstance->childSetVisible("Decompose", false);
sInstance->childSetVisible("decompose_cancel", true);
+ sInstance->childDisable("Simplify");
}
else if (stage == "Simplify")
{
sInstance->setStatusMessage(sInstance->getString("simplifying"));
sInstance->childSetVisible("Simplify", false);
sInstance->childSetVisible("simplify_cancel", true);
+ sInstance->childDisable("Decompose");
}
}
}
@@ -944,14 +1014,38 @@ void LLFloaterModelPreview::onPhysicsBrowse(LLUICtrl* ctrl, void* userdata)
//static
void LLFloaterModelPreview::onPhysicsUseLOD(LLUICtrl* ctrl, void* userdata)
{
- S32 which_mode = 3;
+ S32 num_lods = 4;
+ S32 which_mode;
+
LLCtrlSelectionInterface* iface = sInstance->childGetSelectionInterface("physics_lod_combo");
if (iface)
{
which_mode = iface->getFirstSelectedIndex();
}
+ else
+ {
+ llwarns << "no iface" << llendl;
+ return;
+ }
+
+ if (which_mode <= 0)
+ {
+ llwarns << "which_mode out of range, " << which_mode << llendl;
+ }
+
+ S32 file_mode = iface->getItemCount() - 1;
+ if (which_mode < file_mode)
+ {
+ S32 which_lod = num_lods - which_mode;
+ sInstance->mModelPreview->setPhysicsFromLOD(which_lod);
+ }
- sInstance->mModelPreview->setPhysicsFromLOD(which_mode);
+ LLModelPreview *model_preview = sInstance->mModelPreview;
+ if (model_preview)
+ {
+ model_preview->refresh();
+ model_preview->updateStatusMessages();
+ }
}
//static
@@ -976,6 +1070,11 @@ void LLFloaterModelPreview::onPhysicsStageCancel(LLUICtrl* ctrl, void*data)
}
sInstance->mCurRequest.clear();
+
+ if (sInstance->mModelPreview)
+ {
+ sInstance->mModelPreview->updateStatusMessages();
+ }
}
}
@@ -1038,8 +1137,9 @@ void LLFloaterModelPreview::initDecompControls()
mDecompParams[param[i].mName] = LLSD(param[i].mDefault.mFloat);
//llinfos << "Type: float, Default: " << param[i].mDefault.mFloat << llendl;
- LLSliderCtrl* slider = getChild<LLSliderCtrl>(name);
- if (slider)
+
+ LLUICtrl* ctrl = getChild<LLUICtrl>(name);
+ if (LLSliderCtrl* slider = dynamic_cast<LLSliderCtrl*>(ctrl))
{
slider->setMinValue(param[i].mDetails.mRange.mLow.mFloat);
slider->setMaxValue(param[i].mDetails.mRange.mHigh.mFloat);
@@ -1047,14 +1147,49 @@ void LLFloaterModelPreview::initDecompControls()
slider->setValue(param[i].mDefault.mFloat);
slider->setCommitCallback(onPhysicsParamCommit, (void*) &param[i]);
}
+ else if (LLSpinCtrl* spinner = dynamic_cast<LLSpinCtrl*>(ctrl))
+ {
+ bool is_retain_ctrl = "Retain%" == name;
+ double coefficient = is_retain_ctrl ? RETAIN_COEFFICIENT : 1.f;
+
+ spinner->setMinValue(param[i].mDetails.mRange.mLow.mFloat * coefficient);
+ spinner->setMaxValue(param[i].mDetails.mRange.mHigh.mFloat * coefficient);
+ spinner->setIncrement(param[i].mDetails.mRange.mDelta.mFloat * coefficient);
+ spinner->setValue(param[i].mDefault.mFloat * coefficient);
+ spinner->setCommitCallback(onPhysicsParamCommit, (void*) &param[i]);
+ }
+ else if (LLComboBox* combo_box = dynamic_cast<LLComboBox*>(ctrl))
+ {
+ float min = param[i].mDetails.mRange.mLow.mFloat;
+ float max = param[i].mDetails.mRange.mHigh.mFloat;
+ float delta = param[i].mDetails.mRange.mDelta.mFloat;
+
+ if ("Cosine%" == name)
+ {
+ createSmoothComboBox(combo_box, min, max);
+ }
+ else
+ {
+ for(float value = min; value <= max; value += delta)
+ {
+ std::string label = llformat("%.1f", value);
+ combo_box->add(label, value, ADD_BOTTOM, true);
+ }
+ combo_box->setValue(param[i].mDefault.mFloat);
+
+ }
+
+ combo_box->setCommitCallback(onPhysicsParamCommit, (void*) &param[i]);
+ }
}
else if (param[i].mType == LLCDParam::LLCD_INTEGER)
{
mDecompParams[param[i].mName] = LLSD(param[i].mDefault.mIntOrEnumValue);
//llinfos << "Type: integer, Default: " << param[i].mDefault.mIntOrEnumValue << llendl;
- LLSliderCtrl* slider = getChild<LLSliderCtrl>(name);
- if (slider)
+
+ LLUICtrl* ctrl = getChild<LLUICtrl>(name);
+ if (LLSliderCtrl* slider = dynamic_cast<LLSliderCtrl*>(ctrl))
{
slider->setMinValue(param[i].mDetails.mRange.mLow.mIntOrEnumValue);
slider->setMaxValue(param[i].mDetails.mRange.mHigh.mIntOrEnumValue);
@@ -1062,6 +1197,16 @@ void LLFloaterModelPreview::initDecompControls()
slider->setValue(param[i].mDefault.mIntOrEnumValue);
slider->setCommitCallback(onPhysicsParamCommit, (void*) &param[i]);
}
+ else if (LLComboBox* combo_box = dynamic_cast<LLComboBox*>(ctrl))
+ {
+ for(int k = param[i].mDetails.mRange.mLow.mIntOrEnumValue; k<=param[i].mDetails.mRange.mHigh.mIntOrEnumValue; k+=param[i].mDetails.mRange.mDelta.mIntOrEnumValue)
+ {
+ std::string name = llformat("%.1d", k);
+ combo_box->add(name, k, ADD_BOTTOM, true);
+ }
+ combo_box->setValue(param[i].mDefault.mIntOrEnumValue);
+ combo_box->setCommitCallback(onPhysicsParamCommit, (void*) &param[i]);
+ }
}
else if (param[i].mType == LLCDParam::LLCD_BOOLEAN)
{
@@ -1089,7 +1234,11 @@ void LLFloaterModelPreview::initDecompControls()
//llinfos << param[i].mDetails.mEnumValues.mEnumsArray[k].mValue
// << " - " << param[i].mDetails.mEnumValues.mEnumsArray[k].mName << llendl;
- combo_box->add(param[i].mDetails.mEnumValues.mEnumsArray[k].mName,
+ std::string name(param[i].mDetails.mEnumValues.mEnumsArray[k].mName);
+ std::string localized_name;
+ bool is_localized = LLTrans::findString(localized_name, name);
+
+ combo_box->add(is_localized ? localized_name : name,
LLSD::Integer(param[i].mDetails.mEnumValues.mEnumsArray[k].mValue));
}
combo_box->setValue(param[i].mDefault.mIntOrEnumValue);
@@ -1105,6 +1254,22 @@ void LLFloaterModelPreview::initDecompControls()
childSetCommitCallback("physics_explode", LLFloaterModelPreview::onExplodeCommit, this);
}
+void LLFloaterModelPreview::createSmoothComboBox(LLComboBox* combo_box, float min, float max)
+{
+ float delta = (max - min) / SMOOTH_VALUES_NUMBER;
+ int ilabel = 0;
+
+ combo_box->add("0 (none)", ADD_BOTTOM, true);
+
+ for(float value = min + delta; value < max; value += delta)
+ {
+ std::string label = (++ilabel == SMOOTH_VALUES_NUMBER) ? "10 (max)" : llformat("%.1d", ilabel);
+ combo_box->add(label, value, ADD_BOTTOM, true);
+ }
+
+
+}
+
//-----------------------------------------------------------------------------
// onMouseCaptureLost()
//-----------------------------------------------------------------------------
@@ -1329,9 +1494,26 @@ bool LLModelLoader::doLoadModel()
if (!dom)
{
+ llinfos<<" Error with dae - traditionally indicates a corrupt file."<<llendl;
+ setLoadState( ERROR_PARSING );
return false;
}
-
+ //Dom version
+ daeString domVersion = dae.getDomVersion();
+ std::string sldom(domVersion);
+ llinfos<<"Collada Importer Version: "<<sldom<<llendl;
+ //Dae version
+ domVersionType docVersion = dom->getVersion();
+ //0=1.4
+ //1=1.4.1
+ //2=Currently unsupported, however may work
+ if (docVersion > 1 )
+ {
+ docVersion = VERSIONTYPE_COUNT;
+ }
+ llinfos<<"Dae version "<<colladaVersion[docVersion]<<llendl;
+
+
daeDatabase* db = dae.getDatabase();
daeInt count = db->getElementCount(NULL, COLLADA_TYPE_MESH);
@@ -1480,8 +1662,7 @@ bool LLModelLoader::doLoadModel()
LLMatrix4 trans = normalized_transformation;
trans *= skin_info.mBindShapeMatrix;
- skin_info.mBindShapeMatrix = trans;
-
+ skin_info.mBindShapeMatrix = trans;
}
@@ -1554,7 +1735,7 @@ bool LLModelLoader::doLoadModel()
{
//Build a joint for the resolver to work with
char str[64]={0};
- sprintf(str,"./%s",(*jointIt).second.c_str() );
+ sprintf(str,"./%s",(*jointIt).first.c_str() );
//llwarns<<"Joint "<< str <<llendl;
//Setup the resolver
@@ -1565,15 +1746,22 @@ bool LLModelLoader::doLoadModel()
if ( pJoint )
{
//Pull out the translate id and store it in the jointTranslations map
- daeSIDResolver jointResolver( pJoint, "./translate" );
- domTranslate* pTranslate = daeSafeCast<domTranslate>( jointResolver.getElement() );
+ daeSIDResolver jointResolverA( pJoint, "./translate" );
+ domTranslate* pTranslateA = daeSafeCast<domTranslate>( jointResolverA.getElement() );
+ daeSIDResolver jointResolverB( pJoint, "./location" );
+ domTranslate* pTranslateB = daeSafeCast<domTranslate>( jointResolverB.getElement() );
LLMatrix4 workingTransform;
//Translation via SID
- if ( pTranslate )
+ if ( pTranslateA )
+ {
+ extractTranslation( pTranslateA, workingTransform );
+ }
+ else
+ if ( pTranslateB )
{
- extractTranslation( pTranslate, workingTransform );
+ extractTranslation( pTranslateB, workingTransform );
}
else
{
@@ -1585,9 +1773,15 @@ bool LLModelLoader::doLoadModel()
missingSkeletonOrScene = true;
}
else
+ if ( pTranslateElement )
{
extractTranslationViaElement( pTranslateElement, workingTransform );
}
+ else
+ {
+ extractTranslationViaSID( pJoint, workingTransform );
+ }
+
}
//Store the joint transform w/respect to it's name.
@@ -1684,7 +1878,7 @@ bool LLModelLoader::doLoadModel()
}
}
- model->mSkinInfo.mInvBindMatrix.push_back(mat);
+ model->mSkinInfo.mInvBindMatrix.push_back(mat);
}
}
}
@@ -1692,7 +1886,7 @@ bool LLModelLoader::doLoadModel()
}
//Now that we've parsed the joint array, let's determine if we have a full rig
- //(which means we have all the joints that are required for an avatar versus
+ //(which means we have all the joint sthat are required for an avatar versus
//a skinned asset attached to a node in a file that contains an entire skeleton,
//but does not use the skeleton).
buildJointToNodeMappingFromScene( root );
@@ -1883,8 +2077,11 @@ bool LLModelLoader::doLoadModel()
mesh_scale *= transformation;
transformation = mesh_scale;
- std::vector<LLImportMaterial> materials;
- materials.resize(model->getNumVolumeFaces());
+ std::map<std::string, LLImportMaterial> materials;
+ for (U32 i = 0; i < model->mMaterialList.size(); ++i)
+ {
+ materials[model->mMaterialList[i]] = LLImportMaterial();
+ }
mScene[transformation].push_back(LLModelInstance(model, model->mLabel, transformation, materials));
stretch_extents(model, transformation, mExtents[0], mExtents[1], mFirstTransform);
}
@@ -1946,6 +2143,11 @@ bool LLModelLoader::loadFromSLM(const std::string& filename)
//build model list for each LoD
model_list model[LLModel::NUM_LODS];
+ if (data["version"].asInteger() != SLM_SUPPORTED_VERSION)
+ { //unsupported version
+ return false;
+ }
+
LLSD& mesh = data["mesh"];
LLVolumeParams volume_params;
@@ -1968,10 +2170,6 @@ bool LLModelLoader::loadFromSLM(const std::string& filename)
mPreview->critiqueRigForUploadApplicability( loaded_model->mSkinInfo.mJointNames );
}
}
- else
- {
- llassert(model[lod].empty());
- }
}
}
@@ -1980,6 +2178,14 @@ bool LLModelLoader::loadFromSLM(const std::string& filename)
return false;
}
+ // Set name.
+ std::string name = data["name"];
+ if (!name.empty())
+ {
+ model[LLModel::LOD_HIGH][0]->mLabel = name;
+ }
+
+
//load instance list
model_instance_list instance_list;
@@ -2092,15 +2298,37 @@ void LLModelLoader::processJointToNodeMapping( domNode* pNode )
mJointsFromNode.push_front( pNode->getName() );
}
//2. Handle the kiddo's
- daeTArray< daeSmartRef<daeElement> > childOfChild = pNode->getChildren();
- S32 childOfChildCount = childOfChild.getCount();
- for (S32 i = 0; i < childOfChildCount; ++i)
+ processChildJoints( pNode );
+ }
+ else
+ {
+ //Determine if the're any children wrt to this failed node.
+ //This occurs when an armature is exported and ends up being what essentially amounts to
+ //as the root for the visual_scene
+ if ( pNode )
{
- domNode* pChildNode = daeSafeCast<domNode>( childOfChild[i] );
- if ( pChildNode )
- {
- processJointToNodeMapping( pChildNode );
- }
+ processChildJoints( pNode );
+ }
+ else
+ {
+ llinfos<<"Node is NULL"<<llendl;
+ }
+
+ }
+}
+//-----------------------------------------------------------------------------
+// processChildJoint()
+//-----------------------------------------------------------------------------
+void LLModelLoader::processChildJoints( domNode* pParentNode )
+{
+ daeTArray< daeSmartRef<daeElement> > childOfChild = pParentNode->getChildren();
+ S32 childOfChildCount = childOfChild.getCount();
+ for (S32 i = 0; i < childOfChildCount; ++i)
+ {
+ domNode* pChildNode = daeSafeCast<domNode>( childOfChild[i] );
+ if ( pChildNode )
+ {
+ processJointToNodeMapping( pChildNode );
}
}
}
@@ -2125,15 +2353,11 @@ void LLModelPreview::critiqueRigForUploadApplicability( const std::vector<std::s
setRigValidForJointPositionUpload( true );
}
- if ( isRigLegacyOK )
- {
+ if ( isRigLegacyOK)
+ {
setLegacyRigValid( true );
}
- if ( getRigWithSceneParity() && isJointPositionUploadOK )
- {
- setResetJointFlag( true );
- }
}
//-----------------------------------------------------------------------------
// critiqueJointToNodeMappingFromScene()
@@ -2173,12 +2397,7 @@ void LLModelPreview::critiqueJointToNodeMappingFromScene( void )
//2. Partial rig but w/o parity between the scene and joint array
if ( result )
{
- setResetJointFlag( true );
setRigWithSceneParity( true );
- }
- else
- {
- setResetJointFlag( false );
}
}
//-----------------------------------------------------------------------------
@@ -2267,14 +2486,17 @@ void LLModelLoader::loadTextures()
{
for(U32 i = 0 ; i < iter->second.size(); i++)
{
- for(U32 j = 0 ; j < iter->second[i].mMaterial.size() ; j++)
+ for(std::map<std::string, LLImportMaterial>::iterator j = iter->second[i].mMaterial.begin();
+ j != iter->second[i].mMaterial.end(); ++j)
{
- if(!iter->second[i].mMaterial[j].mDiffuseMapFilename.empty())
+ LLImportMaterial& material = j->second;
+
+ if(!material.mDiffuseMapFilename.empty())
{
- iter->second[i].mMaterial[j].mDiffuseMap =
- LLViewerTextureManager::getFetchedTextureFromUrl("file://" + iter->second[i].mMaterial[j].mDiffuseMapFilename, TRUE, LLViewerTexture::BOOST_PREVIEW);
- iter->second[i].mMaterial[j].mDiffuseMap->setLoadedCallback(LLModelPreview::textureLoadedCallback, 0, TRUE, FALSE, mPreview, NULL, FALSE);
- iter->second[i].mMaterial[j].mDiffuseMap->forceToSaveRawImage(0, F32_MAX);
+ material.mDiffuseMap =
+ LLViewerTextureManager::getFetchedTextureFromUrl("file://" + material.mDiffuseMapFilename, TRUE, LLViewerTexture::BOOST_PREVIEW);
+ material.mDiffuseMap->setLoadedCallback(LLModelPreview::textureLoadedCallback, 0, TRUE, FALSE, mPreview, NULL, FALSE);
+ material.mDiffuseMap->forceToSaveRawImage(0, F32_MAX);
mNumOfFetchingTextures++ ;
}
}
@@ -2292,8 +2514,20 @@ void LLModelLoader::loadTextures()
//-----------------------------------------------------------------------------
bool LLModelLoader::isNodeAJoint( domNode* pNode )
{
- if ( !pNode || pNode->getName() == NULL)
+ if ( !pNode )
{
+ llinfos<<"Created node is NULL"<<llendl;
+ return false;
+ }
+
+ if ( pNode->getName() == NULL )
+ {
+ llinfos<<"Parsed node has no name "<<llendl;
+ //Attempt to write the node id, if possible (aids in debugging the visual scene)
+ if ( pNode->getId() )
+ {
+ llinfos<<"Parsed node ID: "<<pNode->getId()<<llendl;
+ }
return false;
}
@@ -2403,10 +2637,43 @@ void LLModelLoader::extractTranslation( domTranslate* pTranslate, LLMatrix4& tra
//-----------------------------------------------------------------------------
void LLModelLoader::extractTranslationViaElement( daeElement* pTranslateElement, LLMatrix4& transform )
{
- domTranslate* pTranslateChild = dynamic_cast<domTranslate*>( pTranslateElement );
- domFloat3 translateChild = pTranslateChild->getValue();
- LLVector3 singleJointTranslation( translateChild[0], translateChild[1], translateChild[2] );
- transform.setTranslation( singleJointTranslation );
+ if ( pTranslateElement )
+ {
+ domTranslate* pTranslateChild = dynamic_cast<domTranslate*>( pTranslateElement );
+ domFloat3 translateChild = pTranslateChild->getValue();
+ LLVector3 singleJointTranslation( translateChild[0], translateChild[1], translateChild[2] );
+ transform.setTranslation( singleJointTranslation );
+ }
+}
+//-----------------------------------------------------------------------------
+// extractTranslationViaSID()
+//-----------------------------------------------------------------------------
+void LLModelLoader::extractTranslationViaSID( daeElement* pElement, LLMatrix4& transform )
+{
+ if ( pElement )
+ {
+ daeSIDResolver resolver( pElement, "./transform" );
+ domMatrix* pMatrix = daeSafeCast<domMatrix>( resolver.getElement() );
+ //We are only extracting out the translational component atm
+ LLMatrix4 workingTransform;
+ if ( pMatrix )
+ {
+ domFloat4x4 domArray = pMatrix->getValue();
+ for ( int i = 0; i < 4; i++ )
+ {
+ for( int j = 0; j < 4; j++ )
+ {
+ workingTransform.mMatrix[i][j] = domArray[i + j*4];
+ }
+ }
+ LLVector3 trans = workingTransform.getTranslation();
+ transform.setTranslation( trans );
+ }
+ }
+ else
+ {
+ llwarns<<"Element is nonexistent - empty/unsupported node."<<llendl;
+ }
}
//-----------------------------------------------------------------------------
// processJointNode()
@@ -2426,13 +2693,20 @@ void LLModelLoader::processJointNode( domNode* pNode, JointTransformMap& jointTr
LLMatrix4 workingTransform;
//Pull out the translate id and store it in the jointTranslations map
- daeSIDResolver jointResolver( pNode, "./translate" );
- domTranslate* pTranslate = daeSafeCast<domTranslate>( jointResolver.getElement() );
+ daeSIDResolver jointResolverA( pNode, "./translate" );
+ domTranslate* pTranslateA = daeSafeCast<domTranslate>( jointResolverA.getElement() );
+ daeSIDResolver jointResolverB( pNode, "./location" );
+ domTranslate* pTranslateB = daeSafeCast<domTranslate>( jointResolverB.getElement() );
//Translation via SID was successful
- if ( pTranslate )
+ if ( pTranslateA )
{
- extractTranslation( pTranslate, workingTransform );
+ extractTranslation( pTranslateA, workingTransform );
+ }
+ else
+ if ( pTranslateB )
+ {
+ extractTranslation( pTranslateB, workingTransform );
}
else
{
@@ -2574,7 +2848,13 @@ void LLModelLoader::processElement( daeElement* element, bool& badElement )
{
LLMatrix4 transformation = mTransform;
- std::vector<LLImportMaterial> materials = getMaterials(model, instance_geo);
+ if (mTransform.determinant() < 0)
+ { //negative scales are not supported
+ llinfos << "Negative scale detected, unsupported transform. domInstance_geometry: " << LLModel::getElementLabel(instance_geo) << llendl;
+ badElement = true;
+ }
+
+ std::map<std::string, LLImportMaterial> materials = getMaterials(model, instance_geo);
// adjust the transformation to compensate for mesh normalization
LLVector3 mesh_scale_vector;
@@ -2618,7 +2898,8 @@ void LLModelLoader::processElement( daeElement* element, bool& badElement )
//process children
daeTArray< daeSmartRef<daeElement> > children = element->getChildren();
- for (S32 i = 0; i < children.getCount(); i++)
+ int childCount = children.getCount();
+ for (S32 i = 0; i < childCount; i++)
{
processElement(children[i],badElement);
}
@@ -2630,9 +2911,9 @@ void LLModelLoader::processElement( daeElement* element, bool& badElement )
}
}
-std::vector<LLImportMaterial> LLModelLoader::getMaterials(LLModel* model, domInstance_geometry* instance_geo)
+std::map<std::string, LLImportMaterial> LLModelLoader::getMaterials(LLModel* model, domInstance_geometry* instance_geo)
{
- std::vector<LLImportMaterial> materials;
+ std::map<std::string, LLImportMaterial> materials;
for (int i = 0; i < model->mMaterialList.size(); i++)
{
LLImportMaterial import_material;
@@ -2679,7 +2960,8 @@ std::vector<LLImportMaterial> LLModelLoader::getMaterials(LLModel* model, domIns
}
}
- materials.push_back(import_material);
+ import_material.mBinding = model->mMaterialList[i];
+ materials[model->mMaterialList[i]] = import_material;
}
return materials;
@@ -2917,15 +3199,6 @@ U32 LLModelPreview::calcResourceCost()
rebuildUploadData();
- if (mFMP && mModelLoader)
- {
- const BOOL confirmed_checkbox = mFMP->getChild<LLCheckBoxCtrl>("confirm_checkbox")->getValue().asBoolean();
- if ( getLoadState() < LLModelLoader::ERROR_PARSING && confirmed_checkbox )
- {
- mFMP->childEnable("ok_btn");
- }
- }
-
//Upload skin is selected BUT check to see if the joints coming in from the asset were malformed.
if ( mFMP && mFMP->childGetValue("upload_skin").asBoolean() )
{
@@ -2933,16 +3206,9 @@ U32 LLModelPreview::calcResourceCost()
if ( uploadingJointPositions && !isRigValidForJointPositionUpload() )
{
mFMP->childDisable("ok_btn");
- }
- else
- if ( !isLegacyRigValid() )
- {
- mFMP->childDisable("ok_btn");
- }
- //ok_btn should not have been changed unless something was wrong with joint list
+ }
}
- U32 cost = 0;
std::set<LLModel*> accounted;
U32 num_points = 0;
U32 num_hulls = 0;
@@ -2990,8 +3256,7 @@ U32 LLModelPreview::calcResourceCost()
mFMP->childGetValue("upload_skin").asBoolean(),
mFMP->childGetValue("upload_joints").asBoolean(),
TRUE);
- cost += gMeshRepo.calcResourceCost(ret);
-
+
num_hulls += decomp.mHull.size();
for (U32 i = 0; i < decomp.mHull.size(); ++i)
{
@@ -3011,7 +3276,7 @@ U32 LLModelPreview::calcResourceCost()
F32 z_length = z_transformed.normalize();
LLVector3 scale = LLVector3(x_length, y_length, z_length);
- F32 radius = scale.length()*debug_scale;
+ F32 radius = scale.length()*0.5f*debug_scale;
streaming_cost += LLMeshRepository::getStreamingCost(ret, radius);
}
@@ -3023,16 +3288,15 @@ U32 LLModelPreview::calcResourceCost()
updateStatusMessages();
- return cost;
+ return (U32) streaming_cost;
}
void LLFloaterModelPreview::setDetails(F32 x, F32 y, F32 z, F32 streaming_cost, F32 physics_cost)
{
+ assert_main_thread();
childSetTextArg("import_dimensions", "[X]", llformat("%.3f", x));
childSetTextArg("import_dimensions", "[Y]", llformat("%.3f", y));
childSetTextArg("import_dimensions", "[Z]", llformat("%.3f", z));
- childSetTextArg("streaming cost", "[COST]", llformat("%.3f", streaming_cost));
- childSetTextArg("physics cost", "[COST]", llformat("%.3f", physics_cost));
}
@@ -3047,14 +3311,10 @@ void LLModelPreview::rebuildUploadData()
std::string requested_name = mFMP->getChild<LLUICtrl>("description_form")->getValue().asString();
+ std::string metric = mFMP->getChild<LLUICtrl>("model_category_combo")->getValue().asString();
LLSpinCtrl* scale_spinner = mFMP->getChild<LLSpinCtrl>("import_scale");
- if (!scale_spinner)
- {
- llerrs << "floater_model_preview.xml MUST contain import_scale spinner." << llendl;
- }
-
F32 scale = scale_spinner->getValue().asReal();
LLMatrix4 scale_mat;
@@ -3062,10 +3322,24 @@ void LLModelPreview::rebuildUploadData()
F32 max_scale = 0.f;
- const BOOL confirmed_checkbox = mFMP->getChild<LLCheckBoxCtrl>("confirm_checkbox")->getValue().asBoolean();
- if ( mBaseScene.size() > 0 && confirmed_checkbox )
+ //reorder materials to match mBaseModel
+ for (U32 i = 0; i < LLModel::NUM_LODS-1; i++)
{
- mFMP->childEnable("ok_btn");
+ if (mBaseModel.size() == mModel[i].size())
+ {
+ for (U32 j = 0; j < mBaseModel.size(); ++j)
+ {
+
+ int refFaceCnt = 0;
+ int modelFaceCnt = 0;
+
+ if ( !mModel[i][j]->matchMaterialOrder(mBaseModel[j], refFaceCnt, modelFaceCnt ) )
+ {
+ setLoadState( LLModelLoader::ERROR_MATERIALS );
+ mFMP->childDisable( "calculate_btn" );
+ }
+ }
+ }
}
for (LLModelLoader::scene::iterator iter = mBaseScene.begin(); iter != mBaseScene.end(); ++iter)
@@ -3096,6 +3370,7 @@ void LLModelPreview::rebuildUploadData()
if (base_model)
{
base_model->mRequestedLabel = requested_name;
+ base_model->mMetric = metric;
}
S32 idx = 0;
@@ -3107,24 +3382,33 @@ void LLModelPreview::rebuildUploadData()
}
}
- for (U32 i = 0; i < LLModel::NUM_LODS; i++)
- { //fill LOD slots based on reference model index
- if (!mModel[i].empty())
- {
- instance.mLOD[i] = mModel[i][idx];
- }
- else
- {
- instance.mLOD[i] = NULL;
+ if(idx < mBaseModel.size())
+ {
+ for (U32 i = 0; i < LLModel::NUM_LODS; i++)
+ { //fill LOD slots based on reference model index
+ if (mModel[i].size() > idx)
+ {
+ instance.mLOD[i] = mModel[i][idx];
+ }
+ else
+ {
+ instance.mLOD[i] = NULL;
+ }
}
}
-
instance.mTransform = mat;
mUploadData.push_back(instance);
}
}
- F32 max_import_scale = DEFAULT_MAX_PRIM_SCALE/max_scale;
+ F32 max_import_scale = (DEFAULT_MAX_PRIM_SCALE-0.1f)/max_scale;
+
+ F32 max_axis = llmax(mPreviewScale.mV[0], mPreviewScale.mV[1]);
+ max_axis = llmax(max_axis, mPreviewScale.mV[2]);
+ max_axis *= 2.f;
+
+ //clamp scale so that total imported model bounding box is smaller than 240m on a side
+ max_import_scale = llmin(max_import_scale, 240.f/max_axis);
scale_spinner->setMaxValue(max_import_scale);
@@ -3164,6 +3448,12 @@ void LLModelPreview::saveUploadData(const std::string& filename, bool save_skinw
LLSD data;
+ data["version"] = SLM_SUPPORTED_VERSION;
+ if (!mBaseModel.empty())
+ {
+ data["name"] = mBaseModel[0]->getName();
+ }
+
S32 mesh_id = 0;
//build list of unique models and initialize local id
@@ -3190,7 +3480,7 @@ void LLModelPreview::saveUploadData(const std::string& filename, bool save_skinw
instance.mLOD[LLModel::LOD_LOW],
instance.mLOD[LLModel::LOD_IMPOSTOR],
decomp,
- save_skinweights, save_joint_positions);
+ save_skinweights, save_joint_positions, FALSE, TRUE);
data["mesh"][instance.mModel->mLocalID] = str.str();
@@ -3217,12 +3507,19 @@ void LLModelPreview::clearModel(S32 lod)
mScene[lod].clear();
}
-void LLModelPreview::loadModel(std::string filename, S32 lod)
+void LLModelPreview::loadModel(std::string filename, S32 lod, bool force_disable_slm)
{
assert_main_thread();
LLMutexLock lock(this);
+ if (lod < LLModel::LOD_IMPOSTOR || lod > LLModel::NUM_LODS - 1)
+ {
+ llwarns << "Invalid level of detail: " << lod << llendl;
+ assert(lod >= LLModel::LOD_IMPOSTOR && lod < LLModel::NUM_LODS);
+ return;
+ }
+
// This triggers if you bring up the file picker and then hit CANCEL.
// Just use the previous model (if any) and ignore that you brought up
// the file picker.
@@ -3254,6 +3551,11 @@ void LLModelPreview::loadModel(std::string filename, S32 lod)
mModelLoader = new LLModelLoader(filename, lod, this, mJointTransformMap, mJointsFromNode );
+ if (force_disable_slm)
+ {
+ mModelLoader->mTrySLM = false;
+ }
+
mModelLoader->start();
mFMP->childSetTextArg("status", "[STATUS]", mFMP->getString("status_reading_file"));
@@ -3263,11 +3565,12 @@ void LLModelPreview::loadModel(std::string filename, S32 lod)
if ( getLoadState() >= LLModelLoader::ERROR_PARSING )
{
mFMP->childDisable("ok_btn");
+ mFMP->childDisable( "calculate_btn" );
}
if (lod == mPreviewLOD)
{
- mFMP->childSetText("lod_file", mLODFile[mPreviewLOD]);
+ mFMP->childSetText("lod_file_" + lod_name[lod], mLODFile[lod]);
}
else if (lod == LLModel::LOD_PHYSICS)
{
@@ -3296,6 +3599,12 @@ void LLModelPreview::setPhysicsFromLOD(S32 lod)
void LLModelPreview::clearIncompatible(S32 lod)
{
+ //Don't discard models if specified model is the physic rep
+ if ( lod == LLModel::LOD_PHYSICS )
+ {
+ return;
+ }
+
for (U32 i = 0; i <= LLModel::LOD_HIGH; i++)
{ //clear out any entries that aren't compatible with this model
if (i != lod)
@@ -3468,7 +3777,17 @@ void LLModelPreview::loadModelCallback(S32 lod)
mLoading = false;
if (mFMP)
+ {
mFMP->getChild<LLCheckBoxCtrl>("confirm_checkbox")->set(FALSE);
+ if (!mBaseModel.empty())
+ {
+ if (mFMP->getChild<LLUICtrl>("description_form")->getValue().asString().empty())
+ {
+ const std::string& model_name = mBaseModel[0]->getName();
+ mFMP->getChild<LLUICtrl>("description_form")->setValue(model_name);
+ }
+ }
+ }
refresh();
mModelLoadedSignal();
@@ -3524,45 +3843,16 @@ void LLModelPreview::generateNormals()
updateStatusMessages();
}
-void LLModelPreview::clearMaterials()
+void LLModelPreview::genLODs(S32 which_lod, U32 decimation, bool enforce_tri_limit)
{
- for (LLModelLoader::scene::iterator iter = mScene[mPreviewLOD].begin(); iter != mScene[mPreviewLOD].end(); ++iter)
- { //for each transform in current scene
- for (LLModelLoader::model_instance_list::iterator model_iter = iter->second.begin(); model_iter != iter->second.end(); ++model_iter)
- { //for each instance with that transform
- LLModelInstance& source_instance = *model_iter;
- LLModel* source = source_instance.mModel;
-
- for (S32 i = 0; i < source->getNumVolumeFaces(); ++i)
- { //for each face in instance
- LLImportMaterial& source_material = source_instance.mMaterial[i];
-
- //clear material info
- source_material.mDiffuseColor = LLColor4(1,1,1,1);
- source_material.mDiffuseMap = NULL;
- source_material.mDiffuseMapFilename.clear();
- source_material.mDiffuseMapLabel.clear();
- source_material.mFullbright = false;
- }
- }
- }
-
- mVertexBuffer[mPreviewLOD].clear();
-
- if (mPreviewLOD == LLModel::LOD_HIGH)
+ // Allow LoD from -1 to LLModel::LOD_PHYSICS
+ if (which_lod < -1 || which_lod > LLModel::NUM_LODS - 1)
{
- mBaseScene = mScene[mPreviewLOD];
- mBaseModel = mModel[mPreviewLOD];
- clearGLODGroup();
- mVertexBuffer[5].clear();
+ llwarns << "Invalid level of detail: " << which_lod << llendl;
+ assert(which_lod >= -1 && which_lod < LLModel::NUM_LODS);
+ return;
}
- mResourceCost = calcResourceCost();
- refresh();
-}
-
-void LLModelPreview::genLODs(S32 which_lod, U32 decimation, bool enforce_tri_limit)
-{
if (mBaseModel.empty())
{
return;
@@ -3570,6 +3860,15 @@ void LLModelPreview::genLODs(S32 which_lod, U32 decimation, bool enforce_tri_lim
LLVertexBuffer::unbind();
+ bool no_ff = LLGLSLShader::sNoFixedFunction;
+ LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr;
+ LLGLSLShader::sNoFixedFunction = false;
+
+ if (shader)
+ {
+ shader->unbind();
+ }
+
stop_gloderror();
static U32 cur_name = 1;
@@ -3592,111 +3891,41 @@ void LLModelPreview::genLODs(S32 which_lod, U32 decimation, bool enforce_tri_lim
U32 lod_mode = 0;
- LLCtrlSelectionInterface* iface = mFMP->childGetSelectionInterface("lod_mode");
- if (iface)
- {
- lod_mode = iface->getFirstSelectedIndex();
- }
- mRequestedLoDMode[mPreviewLOD] = lod_mode;
-
- F32 lod_error_threshold = mFMP->childGetValue("lod_error_threshold").asReal();
+ F32 lod_error_threshold = 0;
- if (lod_mode == 0)
+ // The LoD should be in range from Lowest to High
+ if (which_lod > -1 && which_lod < NUM_LOD)
{
- lod_mode = GLOD_TRIANGLE_BUDGET;
- if (which_lod != -1)
+ LLCtrlSelectionInterface* iface = mFMP->childGetSelectionInterface("lod_mode_" + lod_name[which_lod]);
+ if (iface)
{
- limit = mFMP->childGetValue("lod_triangle_limit").asInteger();
+ lod_mode = iface->getFirstSelectedIndex();
}
- }
- else
- {
- lod_mode = GLOD_ERROR_THRESHOLD;
- }
- U32 build_operator = 0;
-
- iface = mFMP->childGetSelectionInterface("build_operator");
- if (iface)
- {
- build_operator = iface->getFirstSelectedIndex();
+ lod_error_threshold = mFMP->childGetValue("lod_error_threshold_" + lod_name[which_lod]).asReal();
}
- mRequestedBuildOperator[mPreviewLOD] = build_operator;
- if (build_operator == 0)
- {
- build_operator = GLOD_OPERATOR_EDGE_COLLAPSE;
- }
- else
- {
- build_operator = GLOD_OPERATOR_HALF_EDGE_COLLAPSE;
- }
-
- U32 queue_mode=0;
- iface = mFMP->childGetSelectionInterface("queue_mode");
- if (iface)
- {
- queue_mode = iface->getFirstSelectedIndex();
- }
- mRequestedQueueMode[mPreviewLOD] = queue_mode;
-
- if (queue_mode == 0)
- {
- queue_mode = GLOD_QUEUE_GREEDY;
- }
- else if (queue_mode == 1)
- {
- queue_mode = GLOD_QUEUE_LAZY;
- }
- else
+ if (which_lod != -1)
{
- queue_mode = GLOD_QUEUE_INDEPENDENT;
+ mRequestedLoDMode[which_lod] = lod_mode;
}
- U32 border_mode = 0;
-
- iface = mFMP->childGetSelectionInterface("border_mode");
- if (iface)
+ if (lod_mode == 0)
{
- border_mode = iface->getFirstSelectedIndex();
- }
- mRequestedBorderMode[mPreviewLOD] = border_mode;
+ lod_mode = GLOD_TRIANGLE_BUDGET;
- if (border_mode == 0)
- {
- border_mode = GLOD_BORDER_UNLOCK;
+ // The LoD should be in range from Lowest to High
+ if (which_lod > -1 && which_lod < NUM_LOD)
+ {
+ limit = mFMP->childGetValue("lod_triangle_limit_" + lod_name[which_lod]).asInteger();
+ }
}
else
{
- border_mode = GLOD_BORDER_LOCK;
+ lod_mode = GLOD_ERROR_THRESHOLD;
}
bool object_dirty = false;
- if (border_mode != mBuildBorderMode)
- {
- mBuildBorderMode = border_mode;
- object_dirty = true;
- }
-
- if (queue_mode != mBuildQueueMode)
- {
- mBuildQueueMode = queue_mode;
- object_dirty = true;
- }
-
- if (build_operator != mBuildOperator)
- {
- mBuildOperator = build_operator;
- object_dirty = true;
- }
-
- F32 share_tolerance = mFMP->childGetValue("share_tolerance").asReal();
- if (share_tolerance != mBuildShareTolerance)
- {
- mBuildShareTolerance = share_tolerance;
- object_dirty = true;
- }
- mRequestedShareTolerance[mPreviewLOD] = share_tolerance;
if (mGroup == 0)
{
@@ -3734,28 +3963,18 @@ void LLModelPreview::genLODs(S32 which_lod, U32 decimation, bool enforce_tri_lim
U32 tri_count = 0;
for (U32 i = 0; i < mVertexBuffer[5][mdl].size(); ++i)
{
- mVertexBuffer[5][mdl][i]->setBuffer(type_mask);
+ LLVertexBuffer* buff = mVertexBuffer[5][mdl][i];
+ buff->setBuffer(type_mask & buff->getTypeMask());
+
U32 num_indices = mVertexBuffer[5][mdl][i]->getNumIndices();
if (num_indices > 2)
{
- glodInsertElements(mObject[mdl], i, GL_TRIANGLES, num_indices, GL_UNSIGNED_SHORT, mVertexBuffer[5][mdl][i]->getIndicesPointer(), 0, 0.f);
+ glodInsertElements(mObject[mdl], i, GL_TRIANGLES, num_indices, GL_UNSIGNED_SHORT, (U8*) mVertexBuffer[5][mdl][i]->getIndicesPointer(), 0, 0.f);
}
tri_count += num_indices/3;
stop_gloderror();
}
- glodObjectParameteri(mObject[mdl], GLOD_BUILD_OPERATOR, build_operator);
- stop_gloderror();
-
- glodObjectParameteri(mObject[mdl], GLOD_BUILD_QUEUE_MODE, queue_mode);
- stop_gloderror();
-
- glodObjectParameteri(mObject[mdl], GLOD_BUILD_BORDER_MODE, border_mode);
- stop_gloderror();
-
- glodObjectParameterf(mObject[mdl], GLOD_BUILD_SHARE_TOLERANCE, share_tolerance);
- stop_gloderror();
-
glodBuildObject(mObject[mdl]);
stop_gloderror();
}
@@ -3856,20 +4075,22 @@ void LLModelPreview::genLODs(S32 which_lod, U32 decimation, bool enforce_tri_lim
for (GLint i = 0; i < patch_count; ++i)
{
+ type_mask = mVertexBuffer[5][base][i]->getTypeMask();
+
LLPointer<LLVertexBuffer> buff = new LLVertexBuffer(type_mask, 0);
if (sizes[i*2+1] > 0 && sizes[i*2] > 0)
{
buff->allocateBuffer(sizes[i*2+1], sizes[i*2], true);
buff->setBuffer(type_mask);
- glodFillElements(mObject[base], names[i], GL_UNSIGNED_SHORT, buff->getIndicesPointer());
+ glodFillElements(mObject[base], names[i], GL_UNSIGNED_SHORT, (U8*) buff->getIndicesPointer());
stop_gloderror();
}
else
{ //this face was eliminated, create a dummy triangle (one vertex, 3 indices, all 0)
buff->allocateBuffer(1, 3, true);
- memset(buff->getMappedData(), 0, buff->getSize());
- memset(buff->getIndicesPointer(), 0, buff->getIndicesSize());
+ memset((U8*) buff->getMappedData(), 0, buff->getSize());
+ memset((U8*) buff->getIndicesPointer(), 0, buff->getIndicesSize());
}
buff->validateRange(0, buff->getNumVerts()-1, buff->getNumIndices(), 0);
@@ -3880,8 +4101,15 @@ void LLModelPreview::genLODs(S32 which_lod, U32 decimation, bool enforce_tri_lim
LLStrider<U16> index;
buff->getVertexStrider(pos);
- buff->getNormalStrider(norm);
- buff->getTexCoord0Strider(tc);
+ if (type_mask & LLVertexBuffer::MAP_NORMAL)
+ {
+ buff->getNormalStrider(norm);
+ }
+ if (type_mask & LLVertexBuffer::MAP_TEXCOORD0)
+ {
+ buff->getTexCoord0Strider(tc);
+ }
+
buff->getIndexStrider(index);
target_model->setVolumeFaceData(names[i], pos, norm, tc, index, buff->getNumVerts(), buff->getNumIndices());
@@ -3939,6 +4167,13 @@ void LLModelPreview::genLODs(S32 which_lod, U32 decimation, bool enforce_tri_lim
mResourceCost = calcResourceCost();
+ LLVertexBuffer::unbind();
+ LLGLSLShader::sNoFixedFunction = no_ff;
+ if (shader)
+ {
+ shader->bind();
+ }
+
/*if (which_lod == -1 && mScene[LLModel::LOD_PHYSICS].empty())
{ //build physics scene
mScene[LLModel::LOD_PHYSICS] = mScene[LLModel::LOD_LOW];
@@ -4087,18 +4322,20 @@ void LLModelPreview::updateStatusMessages()
}
else if (!verts[lod].empty())
{
+ S32 sum_verts_higher_lod = 0;
+ S32 sum_verts_this_lod = 0;
for (U32 i = 0; i < verts[lod].size(); ++i)
{
- S32 max_verts = i < verts[lod+1].size() ? verts[lod+1][i] : 0;
+ sum_verts_higher_lod += ((i < verts[lod+1].size()) ? verts[lod+1][i] : 0);
+ sum_verts_this_lod += verts[lod][i];
+ }
- if (max_verts > 0)
- {
- if (verts[lod][i] > max_verts)
- { //too many vertices in this lod
- message = "mesh_status_too_many_vertices";
- upload_status[lod] = 2;
- }
- }
+ if ((sum_verts_higher_lod > 0) &&
+ (sum_verts_this_lod > sum_verts_higher_lod))
+ {
+ //too many vertices in this lod
+ message = "mesh_status_too_many_vertices";
+ upload_status[lod] = 2;
}
}
}
@@ -4119,6 +4356,8 @@ void LLModelPreview::updateStatusMessages()
icon = mFMP->getChild<LLIconCtrl>("lod_status_message_icon");
icon->setImage(img);
}
+
+ updateLodControls(lod);
}
@@ -4147,12 +4386,7 @@ void LLModelPreview::updateStatusMessages()
if ( uploadingJointPositions && !isRigValidForJointPositionUpload() )
{
skinAndRigOk = false;
- }
- else
- if ( !isLegacyRigValid() )
- {
- skinAndRigOk = false;
- }
+ }
}
if(upload_ok && mModelLoader)
@@ -4163,12 +4397,7 @@ void LLModelPreview::updateStatusMessages()
}
}
- const BOOL confirmed_checkbox = mFMP->getChild<LLCheckBoxCtrl>("confirm_checkbox")->getValue().asBoolean();
- if ( upload_ok && !errorStateFromLoader && skinAndRigOk && !has_degenerate && confirmed_checkbox)
- {
- mFMP->childEnable("ok_btn");
- }
- else
+ if (!upload_ok || errorStateFromLoader || !skinAndRigOk || has_degenerate)
{
mFMP->childDisable("ok_btn");
}
@@ -4235,12 +4464,14 @@ void LLModelPreview::updateStatusMessages()
{
fmp->enableViewOption("show_physics");
mViewOption["show_physics"] = true;
+ fmp->childSetValue("show_physics", true);
}
}
else
{
fmp->disableViewOption("show_physics");
mViewOption["show_physics"] = false;
+ fmp->childSetValue("show_physics", false);
}
@@ -4248,7 +4479,7 @@ void LLModelPreview::updateStatusMessages()
//fmp->childSetEnabled("physics_optimize", !use_hull);
- bool enable = phys_tris > 0 || phys_hulls > 0;
+ bool enable = (phys_tris > 0 || phys_hulls > 0) && fmp->mCurRequest.empty();
//enable = enable && !use_hull && fmp->childGetValue("physics_optimize").asBoolean();
//enable/disable "analysis" UI
@@ -4260,7 +4491,7 @@ void LLModelPreview::updateStatusMessages()
child = panel->findNextSibling(child);
}
- enable = phys_hulls > 0;
+ enable = phys_hulls > 0 && fmp->mCurRequest.empty();
//enable/disable "simplification" UI
panel = fmp->getChild<LLPanel>("physics simplification");
child = panel->getFirstChild();
@@ -4269,132 +4500,48 @@ void LLModelPreview::updateStatusMessages()
child->setEnabled(enable);
child = panel->findNextSibling(child);
}
- }
-
- const char* lod_controls[] =
- {
- "lod_mode",
- "lod_triangle_limit",
- "lod_error_tolerance",
- "build_operator_text",
- "queue_mode_text",
- "border_mode_text",
- "share_tolerance_text",
- "build_operator",
- "queue_mode",
- "border_mode",
- "share_tolerance"
- };
- const U32 num_lod_controls = sizeof(lod_controls)/sizeof(char*);
-
- const char* file_controls[] =
- {
- "lod_browse",
- "lod_file"
- };
- const U32 num_file_controls = sizeof(file_controls)/sizeof(char*);
-
- if (fmp)
- {
- //enable/disable controls based on radio groups
- if (mFMP->childGetValue("lod_from_file").asBoolean())
- {
- fmp->mLODMode[mPreviewLOD] = 0;
- for (U32 i = 0; i < num_file_controls; ++i)
- {
- mFMP->childEnable(file_controls[i]);
- }
- for (U32 i = 0; i < num_lod_controls; ++i)
- {
- mFMP->childDisable(lod_controls[i]);
- }
- }
- else if (mFMP->childGetValue("lod_none").asBoolean())
+ if (fmp->mCurRequest.empty())
{
- fmp->mLODMode[mPreviewLOD] = 2;
- for (U32 i = 0; i < num_file_controls; ++i)
- {
- mFMP->childDisable(file_controls[i]);
- }
+ fmp->childSetVisible("Simplify", true);
+ fmp->childSetVisible("simplify_cancel", false);
+ fmp->childSetVisible("Decompose", true);
+ fmp->childSetVisible("decompose_cancel", false);
- for (U32 i = 0; i < num_lod_controls; ++i)
+ if (phys_hulls > 0)
{
- mFMP->childDisable(lod_controls[i]);
+ fmp->childEnable("Simplify");
}
-
- if (!mModel[mPreviewLOD].empty())
+
+ if (phys_tris || phys_hulls > 0)
{
- mModel[mPreviewLOD].clear();
- mScene[mPreviewLOD].clear();
- mVertexBuffer[mPreviewLOD].clear();
-
- //this can cause phasing issues with the UI, so reenter this function and return
- updateStatusMessages();
- return;
+ fmp->childEnable("Decompose");
}
}
else
- { // auto generate, also the default case for wizard which has no radio selection
- fmp->mLODMode[mPreviewLOD] = 1;
-
- //don't actually regenerate lod when refreshing UI
- mLODFrozen = true;
-
- for (U32 i = 0; i < num_file_controls; ++i)
- {
- mFMP->childDisable(file_controls[i]);
- }
-
- for (U32 i = 0; i < num_lod_controls; ++i)
- {
- mFMP->childEnable(lod_controls[i]);
- }
-
- //if (threshold)
- {
- LLSpinCtrl* threshold = mFMP->getChild<LLSpinCtrl>("lod_error_threshold");
- LLSpinCtrl* limit = mFMP->getChild<LLSpinCtrl>("lod_triangle_limit");
-
- limit->setMaxValue(mMaxTriangleLimit);
- limit->forceSetValue(mRequestedTriangleCount[mPreviewLOD]);
-
- threshold->forceSetValue(mRequestedErrorThreshold[mPreviewLOD]);
-
- mFMP->getChild<LLComboBox>("lod_mode")->selectNthItem(mRequestedLoDMode[mPreviewLOD]);
- mFMP->getChild<LLComboBox>("build_operator")->selectNthItem(mRequestedBuildOperator[mPreviewLOD]);
- mFMP->getChild<LLComboBox>("queue_mode")->selectNthItem(mRequestedQueueMode[mPreviewLOD]);
- mFMP->getChild<LLComboBox>("border_mode")->selectNthItem(mRequestedBorderMode[mPreviewLOD]);
- mFMP->getChild<LLSpinCtrl>("share_tolerance")->setValue(mRequestedShareTolerance[mPreviewLOD]);
-
- if (mRequestedLoDMode[mPreviewLOD] == 0)
- {
- limit->setVisible(true);
- threshold->setVisible(false);
-
- limit->setMaxValue(mMaxTriangleLimit);
- limit->setIncrement(mMaxTriangleLimit/32);
- }
- else
- {
- limit->setVisible(false);
- threshold->setVisible(true);
- }
- }
-
- mLODFrozen = false;
+ {
+ fmp->childEnable("simplify_cancel");
+ fmp->childEnable("decompose_cancel");
}
}
- if (mFMP->childGetValue("physics_load_from_file").asBoolean())
+
+ LLCtrlSelectionInterface* iface = fmp->childGetSelectionInterface("physics_lod_combo");
+ S32 which_mode = 0;
+ S32 file_mode = 1;
+ if (iface)
+ {
+ which_mode = iface->getFirstSelectedIndex();
+ file_mode = iface->getItemCount() - 1;
+ }
+
+ if (which_mode == file_mode)
{
- mFMP->childDisable("physics_lod_combo");
mFMP->childEnable("physics_file");
mFMP->childEnable("physics_browse");
}
else
{
- mFMP->childEnable("physics_lod_combo");
mFMP->childDisable("physics_file");
mFMP->childDisable("physics_browse");
}
@@ -4412,6 +4559,124 @@ void LLModelPreview::updateStatusMessages()
crease->forceSetValue(mRequestedCreaseAngle[mPreviewLOD]);
}
+ mModelUpdatedSignal(true);
+
+}
+
+void LLModelPreview::updateLodControls(S32 lod)
+{
+ if (lod < LLModel::LOD_IMPOSTOR || lod > LLModel::LOD_HIGH)
+ {
+ llwarns << "Invalid level of detail: " << lod << llendl;
+ assert(lod >= LLModel::LOD_IMPOSTOR && lod <= LLModel::LOD_HIGH);
+ return;
+ }
+
+ const char* lod_controls[] =
+ {
+ "lod_mode_",
+ "lod_triangle_limit_",
+ "lod_error_threshold_"
+ };
+ const U32 num_lod_controls = sizeof(lod_controls)/sizeof(char*);
+
+ const char* file_controls[] =
+ {
+ "lod_browse_",
+ "lod_file_",
+ };
+ const U32 num_file_controls = sizeof(file_controls)/sizeof(char*);
+
+ LLFloaterModelPreview* fmp = LLFloaterModelPreview::sInstance;
+ if (!fmp) return;
+
+ LLComboBox* lod_combo = mFMP->findChild<LLComboBox>("lod_source_" + lod_name[lod]);
+ if (!lod_combo) return;
+
+ S32 lod_mode = lod_combo->getCurrentIndex();
+ if (lod_mode == 0) // LoD from file
+ {
+ fmp->mLODMode[lod] = 0;
+ for (U32 i = 0; i < num_file_controls; ++i)
+ {
+ mFMP->childShow(file_controls[i] + lod_name[lod]);
+ }
+
+ for (U32 i = 0; i < num_lod_controls; ++i)
+ {
+ mFMP->childHide(lod_controls[i] + lod_name[lod]);
+ }
+ }
+ else if (lod_mode == 2) // use LoD above
+ {
+ fmp->mLODMode[lod] = 2;
+ for (U32 i = 0; i < num_file_controls; ++i)
+ {
+ mFMP->childHide(file_controls[i] + lod_name[lod]);
+ }
+
+ for (U32 i = 0; i < num_lod_controls; ++i)
+ {
+ mFMP->childHide(lod_controls[i] + lod_name[lod]);
+ }
+
+ if (lod < LLModel::LOD_HIGH)
+ {
+ mModel[lod] = mModel[lod + 1];
+ mScene[lod] = mScene[lod + 1];
+ mVertexBuffer[lod].clear();
+
+ // Also update lower LoD
+ if (lod > LLModel::LOD_IMPOSTOR)
+ {
+ updateLodControls(lod - 1);
+ }
+ }
+ }
+ else // auto generate, the default case for all LoDs except High
+ {
+ fmp->mLODMode[lod] = 1;
+
+ //don't actually regenerate lod when refreshing UI
+ mLODFrozen = true;
+
+ for (U32 i = 0; i < num_file_controls; ++i)
+ {
+ mFMP->childHide(file_controls[i] + lod_name[lod]);
+ }
+
+ for (U32 i = 0; i < num_lod_controls; ++i)
+ {
+ mFMP->childShow(lod_controls[i] + lod_name[lod]);
+ }
+
+
+ LLSpinCtrl* threshold = mFMP->getChild<LLSpinCtrl>("lod_error_threshold_" + lod_name[lod]);
+ LLSpinCtrl* limit = mFMP->getChild<LLSpinCtrl>("lod_triangle_limit_" + lod_name[lod]);
+
+ limit->setMaxValue(mMaxTriangleLimit);
+ limit->forceSetValue(mRequestedTriangleCount[lod]);
+
+ threshold->forceSetValue(mRequestedErrorThreshold[lod]);
+
+ mFMP->getChild<LLComboBox>("lod_mode_" + lod_name[lod])->selectNthItem(mRequestedLoDMode[lod]);
+
+ if (mRequestedLoDMode[lod] == 0)
+ {
+ limit->setVisible(true);
+ threshold->setVisible(false);
+
+ limit->setMaxValue(mMaxTriangleLimit);
+ limit->setIncrement(mMaxTriangleLimit/32);
+ }
+ else
+ {
+ limit->setVisible(false);
+ threshold->setVisible(true);
+ }
+
+ mLODFrozen = false;
+ }
}
void LLModelPreview::setPreviewTarget(F32 distance)
@@ -4485,7 +4750,7 @@ void LLModelPreview::genBuffers(S32 lod, bool include_skin_weights)
bool skinned = include_skin_weights && !mdl->mSkinWeights.empty();
- U32 mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_TEXCOORD0;
+ U32 mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_TEXCOORD0 ;
if (skinned)
{
@@ -4503,8 +4768,6 @@ void LLModelPreview::genBuffers(S32 lod, bool include_skin_weights)
LLStrider<LLVector4> weights_strider;
vb->getVertexStrider(vertex_strider);
- vb->getNormalStrider(normal_strider);
- vb->getTexCoord0Strider(tc_strider);
vb->getIndexStrider(index_strider);
if (skinned)
@@ -4513,8 +4776,18 @@ void LLModelPreview::genBuffers(S32 lod, bool include_skin_weights)
}
LLVector4a::memcpyNonAliased16((F32*) vertex_strider.get(), (F32*) vf.mPositions, num_vertices*4*sizeof(F32));
- LLVector4a::memcpyNonAliased16((F32*) tc_strider.get(), (F32*) vf.mTexCoords, num_vertices*2*sizeof(F32));
- LLVector4a::memcpyNonAliased16((F32*) normal_strider.get(), (F32*) vf.mNormals, num_vertices*4*sizeof(F32));
+
+ if (vf.mTexCoords)
+ {
+ vb->getTexCoord0Strider(tc_strider);
+ LLVector4a::memcpyNonAliased16((F32*) tc_strider.get(), (F32*) vf.mTexCoords, num_vertices*2*sizeof(F32));
+ }
+
+ if (vf.mNormals)
+ {
+ vb->getNormalStrider(normal_strider);
+ LLVector4a::memcpyNonAliased16((F32*) normal_strider.get(), (F32*) vf.mNormals, num_vertices*4*sizeof(F32));
+ }
if (skinned)
{
@@ -4610,6 +4883,42 @@ void LLModelPreview::createPreviewAvatar( void )
}
}
+void LLModelPreview::addEmptyFace( LLModel* pTarget )
+{
+ U32 type_mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_TEXCOORD0;
+
+ LLPointer<LLVertexBuffer> buff = new LLVertexBuffer(type_mask, 0);
+
+ buff->allocateBuffer(1, 3, true);
+ memset( (U8*) buff->getMappedData(), 0, buff->getSize() );
+ memset( (U8*) buff->getIndicesPointer(), 0, buff->getIndicesSize() );
+
+ buff->validateRange( 0, buff->getNumVerts()-1, buff->getNumIndices(), 0 );
+
+ LLStrider<LLVector3> pos;
+ LLStrider<LLVector3> norm;
+ LLStrider<LLVector2> tc;
+ LLStrider<U16> index;
+
+ buff->getVertexStrider(pos);
+
+ if ( type_mask & LLVertexBuffer::MAP_NORMAL )
+ {
+ buff->getNormalStrider(norm);
+ }
+ if ( type_mask & LLVertexBuffer::MAP_TEXCOORD0 )
+ {
+ buff->getTexCoord0Strider(tc);
+ }
+
+ buff->getIndexStrider(index);
+
+ //resize face array
+ int faceCnt = pTarget->getNumVolumeFaces();
+ pTarget->setNumVolumeFaces( faceCnt+1 );
+ pTarget->setVolumeFaceData( faceCnt+1, pos, norm, tc, index, buff->getNumVerts(), buff->getNumIndices() );
+
+}
//-----------------------------------------------------------------------------
// render()
//-----------------------------------------------------------------------------
@@ -4620,6 +4929,8 @@ BOOL LLModelPreview::render()
LLMutexLock lock(this);
mNeedsUpdate = FALSE;
+ bool use_shaders = LLGLSLShader::sNoFixedFunction;
+
bool edges = mViewOption["show_edges"];
bool joint_positions = mViewOption["show_joint_positions"];
bool skin_weight = mViewOption["show_skin_weight"];
@@ -4636,25 +4947,33 @@ BOOL LLModelPreview::render()
LLGLDisable fog(GL_FOG);
{
+ if (use_shaders)
+ {
+ gUIProgram.bind();
+ }
//clear background to blue
- glMatrixMode(GL_PROJECTION);
+ gGL.matrixMode(LLRender::MM_PROJECTION);
gGL.pushMatrix();
- glLoadIdentity();
- glOrtho(0.0f, width, 0.0f, height, -1.0f, 1.0f);
+ gGL.loadIdentity();
+ gGL.ortho(0.0f, width, 0.0f, height, -1.0f, 1.0f);
- glMatrixMode(GL_MODELVIEW);
+ gGL.matrixMode(LLRender::MM_MODELVIEW);
gGL.pushMatrix();
- glLoadIdentity();
+ gGL.loadIdentity();
gGL.color4f(0.169f, 0.169f, 0.169f, 1.f);
gl_rect_2d_simple( width, height );
- glMatrixMode(GL_PROJECTION);
+ gGL.matrixMode(LLRender::MM_PROJECTION);
gGL.popMatrix();
- glMatrixMode(GL_MODELVIEW);
+ gGL.matrixMode(LLRender::MM_MODELVIEW);
gGL.popMatrix();
+ if (use_shaders)
+ {
+ gUIProgram.unbind();
+ }
}
LLFloaterModelPreview* fmp = LLFloaterModelPreview::sInstance;
@@ -4691,12 +5010,12 @@ BOOL LLModelPreview::render()
if (has_skin_weights)
{ //model has skin weights, enable view options for skin weights and joint positions
- if (fmp)
+ if (fmp && isLegacyRigValid() )
{
fmp->enableViewOption("show_skin_weight");
fmp->setViewOptionEnabled("show_joint_positions", skin_weight);
+ mFMP->childEnable("upload_skin");
}
- mFMP->childEnable("upload_skin");
}
else
{
@@ -4721,14 +5040,29 @@ BOOL LLModelPreview::render()
mFMP->childSetValue("upload_joints", false);
upload_joints = false;
}
-
- mFMP->childSetEnabled("upload_joints", upload_skin);
+
+ //Only enable joint offsets if it passed the earlier critiquing
+ if ( isRigValidForJointPositionUpload() )
+ {
+ mFMP->childSetEnabled("upload_joints", upload_skin);
+ }
F32 explode = mFMP->childGetValue("physics_explode").asReal();
glClear(GL_DEPTH_BUFFER_BIT);
- LLRect preview_rect = mFMP->getChildView("preview_panel")->getRect();
+ LLRect preview_rect;
+
+ LLFloaterModelWizard* floater_wizard = dynamic_cast<LLFloaterModelWizard*>(mFMP);
+ if (floater_wizard)
+ {
+ preview_rect = floater_wizard->getPreviewRect();
+ }
+ else
+ {
+ preview_rect = mFMP->getChildView("preview_panel")->getRect();
+ }
+
F32 aspect = (F32) preview_rect.getWidth()/preview_rect.getHeight();
LLViewerCamera::getInstance()->setAspect(aspect);
@@ -4752,7 +5086,7 @@ BOOL LLModelPreview::render()
refresh();
}
- glLoadIdentity();
+ gGL.loadIdentity();
gPipeline.enableLightsPreview();
LLQuaternion camera_rot = LLQuaternion(mCameraPitch, LLVector3::y_axis) *
@@ -4765,6 +5099,8 @@ BOOL LLModelPreview::render()
target_pos); // point of interest
+ z_near = llclamp(z_far * 0.001f, 0.001f, 0.1f);
+
LLViewerCamera::getInstance()->setPerspective(FALSE, mOrigin.mX, mOrigin.mY, width, height, FALSE, z_near, z_far);
stop_glerror();
@@ -4773,6 +5109,13 @@ BOOL LLModelPreview::render()
const F32 BRIGHTNESS = 0.9f;
gGL.color3f(BRIGHTNESS, BRIGHTNESS, BRIGHTNESS);
+ const U32 type_mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_TEXCOORD0;
+
+ if (use_shaders)
+ {
+ gObjectPreviewProgram.bind();
+ }
+
LLGLEnable normalize(GL_NORMALIZE);
if (!mBaseModel.empty() && mVertexBuffer[5].empty())
@@ -4784,6 +5127,8 @@ BOOL LLModelPreview::render()
if (!mModel[mPreviewLOD].empty())
{
+ mFMP->childEnable("reset_btn");
+
bool regen = mVertexBuffer[mPreviewLOD].empty();
if (!regen)
{
@@ -4795,6 +5140,24 @@ BOOL LLModelPreview::render()
}
}
+ //make sure material lists all match
+ for (U32 i = 0; i < LLModel::NUM_LODS-1; i++)
+ {
+ if (mBaseModel.size() == mModel[i].size())
+ {
+ for (U32 j = 0; j < mBaseModel.size(); ++j)
+ {
+ int refFaceCnt = 0;
+ int modelFaceCnt = 0;
+
+ if ( !mModel[i][j]->matchMaterialOrder(mBaseModel[j], refFaceCnt, modelFaceCnt ) )
+ {
+ mFMP->childDisable( "calculate_btn" );
+ }
+ }
+ }
+ }
+
if (regen)
{
genBuffers(mPreviewLOD, skin_weight);
@@ -4816,34 +5179,42 @@ BOOL LLModelPreview::render()
gGL.pushMatrix();
LLMatrix4 mat = instance.mTransform;
- glMultMatrixf((GLfloat*) mat.mMatrix);
+ gGL.multMatrix((GLfloat*) mat.mMatrix);
for (U32 i = 0; i < mVertexBuffer[mPreviewLOD][model].size(); ++i)
{
LLVertexBuffer* buffer = mVertexBuffer[mPreviewLOD][model][i];
-
- buffer->setBuffer(LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_TEXCOORD0);
+
+ buffer->setBuffer(type_mask & buffer->getTypeMask());
if (textures)
{
- glColor4fv(instance.mMaterial[i].mDiffuseColor.mV);
- if (i < instance.mMaterial.size() && instance.mMaterial[i].mDiffuseMap.notNull())
+ int materialCnt = instance.mModel->mMaterialList.size();
+ if ( i < materialCnt )
{
- if (instance.mMaterial[i].mDiffuseMap->getDiscardLevel() > -1)
+ const std::string& binding = instance.mModel->mMaterialList[i];
+ const LLImportMaterial& material = instance.mMaterial[binding];
+
+ gGL.diffuseColor4fv(material.mDiffuseColor.mV);
+
+ if (material.mDiffuseMap.notNull())
{
- gGL.getTexUnit(0)->bind(instance.mMaterial[i].mDiffuseMap, true);
- mTextureSet.insert(instance.mMaterial[i].mDiffuseMap.get());
+ if (material.mDiffuseMap->getDiscardLevel() > -1)
+ {
+ gGL.getTexUnit(0)->bind(material.mDiffuseMap, true);
+ mTextureSet.insert(material.mDiffuseMap.get());
+ }
}
}
}
else
{
- glColor4f(1,1,1,1);
+ gGL.diffuseColor4f(1,1,1,1);
}
buffer->drawRange(LLRender::TRIANGLES, 0, buffer->getNumVerts()-1, buffer->getNumIndices(), 0);
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
- glColor3f(0.4f, 0.4f, 0.4f);
+ gGL.diffuseColor3f(0.4f, 0.4f, 0.4f);
if (edges)
{
@@ -4860,184 +5231,197 @@ BOOL LLModelPreview::render()
if (physics)
{
glClear(GL_DEPTH_BUFFER_BIT);
- LLGLEnable blend(GL_BLEND);
- gGL.blendFunc(LLRender::BF_ONE, LLRender::BF_ZERO);
-
- for (LLMeshUploadThread::instance_list::iterator iter = mUploadData.begin(); iter != mUploadData.end(); ++iter)
+
+ for (U32 i = 0; i < 2; i++)
{
- LLModelInstance& instance = *iter;
+ if (i == 0)
+ { //depth only pass
+ gGL.setColorMask(false, false);
+ }
+ else
+ {
+ gGL.setColorMask(true, true);
+ }
- LLModel* model = instance.mLOD[LLModel::LOD_PHYSICS];
+ //enable alpha blending on second pass but not first pass
+ LLGLState blend(GL_BLEND, i);
+
+ gGL.blendFunc(LLRender::BF_SOURCE_ALPHA, LLRender::BF_ONE_MINUS_SOURCE_ALPHA);
- if (!model)
+ for (LLMeshUploadThread::instance_list::iterator iter = mUploadData.begin(); iter != mUploadData.end(); ++iter)
{
- continue;
- }
+ LLModelInstance& instance = *iter;
- gGL.pushMatrix();
- LLMatrix4 mat = instance.mTransform;
+ LLModel* model = instance.mLOD[LLModel::LOD_PHYSICS];
- glMultMatrixf((GLfloat*) mat.mMatrix);
+ if (!model)
+ {
+ continue;
+ }
+ gGL.pushMatrix();
+ LLMatrix4 mat = instance.mTransform;
- bool render_mesh = true;
+ gGL.multMatrix((GLfloat*) mat.mMatrix);
- LLPhysicsDecomp* decomp = gMeshRepo.mDecompThread;
- if (decomp)
- {
- LLMutexLock(decomp->mMutex);
- LLModel::Decomposition& physics = model->mPhysics;
+ bool render_mesh = true;
- if (!physics.mHull.empty())
+ LLPhysicsDecomp* decomp = gMeshRepo.mDecompThread;
+ if (decomp)
{
- render_mesh = false;
+ LLMutexLock(decomp->mMutex);
- if (physics.mMesh.empty())
- { //build vertex buffer for physics mesh
- gMeshRepo.buildPhysicsMesh(physics);
- }
+ LLModel::Decomposition& physics = model->mPhysics;
+
+ if (!physics.mHull.empty())
+ {
+ render_mesh = false;
+
+ if (physics.mMesh.empty())
+ { //build vertex buffer for physics mesh
+ gMeshRepo.buildPhysicsMesh(physics);
+ }
- if (!physics.mMesh.empty())
- { //render hull instead of mesh
- for (U32 i = 0; i < physics.mMesh.size(); ++i)
- {
- if (explode > 0.f)
+ if (!physics.mMesh.empty())
+ { //render hull instead of mesh
+ for (U32 i = 0; i < physics.mMesh.size(); ++i)
{
- gGL.pushMatrix();
+ if (explode > 0.f)
+ {
+ gGL.pushMatrix();
- LLVector3 offset = model->mHullCenter[i]-model->mCenterOfHullCenters;
- offset *= explode;
+ LLVector3 offset = model->mHullCenter[i]-model->mCenterOfHullCenters;
+ offset *= explode;
- gGL.translatef(offset.mV[0], offset.mV[1], offset.mV[2]);
- }
+ gGL.translatef(offset.mV[0], offset.mV[1], offset.mV[2]);
+ }
- static std::vector<LLColor4U> hull_colors;
+ static std::vector<LLColor4U> hull_colors;
- if (i+1 >= hull_colors.size())
- {
- hull_colors.push_back(LLColor4U(rand()%128+127, rand()%128+127, rand()%128+127, 255));
- }
+ if (i+1 >= hull_colors.size())
+ {
+ hull_colors.push_back(LLColor4U(rand()%128+127, rand()%128+127, rand()%128+127, 128));
+ }
glColor4ubv(hull_colors[i].mV);
- LLVertexBuffer::drawArrays(LLRender::TRIANGLES, physics.mMesh[i].mPositions, physics.mMesh[i].mNormals);
+ LLVertexBuffer::drawArrays(LLRender::TRIANGLES, physics.mMesh[i].mPositions, physics.mMesh[i].mNormals);
- if (explode > 0.f)
- {
- gGL.popMatrix();
+ if (explode > 0.f)
+ {
+ gGL.popMatrix();
+ }
}
}
}
}
- }
- if (render_mesh)
- {
- if (mVertexBuffer[LLModel::LOD_PHYSICS].empty())
- {
- genBuffers(LLModel::LOD_PHYSICS, false);
- }
- for (U32 i = 0; i < mVertexBuffer[LLModel::LOD_PHYSICS][model].size(); ++i)
+ if (render_mesh)
{
- LLVertexBuffer* buffer = mVertexBuffer[LLModel::LOD_PHYSICS][model][i];
-
- buffer->setBuffer(LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_TEXCOORD0);
+ if (mVertexBuffer[LLModel::LOD_PHYSICS].empty())
+ {
+ genBuffers(LLModel::LOD_PHYSICS, false);
+ }
+ for (U32 i = 0; i < mVertexBuffer[LLModel::LOD_PHYSICS][model].size(); ++i)
+ {
+ LLVertexBuffer* buffer = mVertexBuffer[LLModel::LOD_PHYSICS][model][i];
- buffer->drawRange(LLRender::TRIANGLES, 0, buffer->getNumVerts()-1, buffer->getNumIndices(), 0);
- gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
- glColor4f(0.4f, 0.4f, 0.0f, 0.4f);
+ gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+ gGL.diffuseColor4f(0.4f, 0.4f, 0.0f, 0.4f);
- buffer->drawRange(LLRender::TRIANGLES, 0, buffer->getNumVerts()-1, buffer->getNumIndices(), 0);
+ buffer->setBuffer(type_mask & buffer->getTypeMask());
+ buffer->drawRange(LLRender::TRIANGLES, 0, buffer->getNumVerts()-1, buffer->getNumIndices(), 0);
- glColor3f(1.f, 1.f, 0.f);
+ gGL.diffuseColor3f(1.f, 1.f, 0.f);
- glLineWidth(2.f);
- glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
- buffer->drawRange(LLRender::TRIANGLES, 0, buffer->getNumVerts()-1, buffer->getNumIndices(), 0);
+ glLineWidth(2.f);
+ glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
+ buffer->drawRange(LLRender::TRIANGLES, 0, buffer->getNumVerts()-1, buffer->getNumIndices(), 0);
- glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
- glLineWidth(1.f);
+ glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+ glLineWidth(1.f);
+ }
}
- }
-
- gGL.popMatrix();
- }
- glLineWidth(3.f);
- glPointSize(8.f);
- gPipeline.enableLightsFullbright(LLColor4::white);
- //show degenerate triangles
- LLGLDepthTest depth(GL_TRUE, GL_TRUE, GL_ALWAYS);
- LLGLDisable cull(GL_CULL_FACE);
- glColor4f(1.f,0.f,0.f,1.f);
- const LLVector4a scale(0.5f);
-
- for (LLMeshUploadThread::instance_list::iterator iter = mUploadData.begin(); iter != mUploadData.end(); ++iter)
- {
- LLModelInstance& instance = *iter;
+ gGL.popMatrix();
+ }
- LLModel* model = instance.mLOD[LLModel::LOD_PHYSICS];
+ glLineWidth(3.f);
+ glPointSize(8.f);
+ gPipeline.enableLightsFullbright(LLColor4::white);
+ //show degenerate triangles
+ LLGLDepthTest depth(GL_TRUE, GL_TRUE, GL_ALWAYS);
+ LLGLDisable cull(GL_CULL_FACE);
+ gGL.diffuseColor4f(1.f,0.f,0.f,1.f);
+ const LLVector4a scale(0.5f);
- if (!model)
+ for (LLMeshUploadThread::instance_list::iterator iter = mUploadData.begin(); iter != mUploadData.end(); ++iter)
{
- continue;
- }
+ LLModelInstance& instance = *iter;
- gGL.pushMatrix();
- LLMatrix4 mat = instance.mTransform;
+ LLModel* model = instance.mLOD[LLModel::LOD_PHYSICS];
- glMultMatrixf((GLfloat*) mat.mMatrix);
+ if (!model)
+ {
+ continue;
+ }
+ gGL.pushMatrix();
+ LLMatrix4 mat = instance.mTransform;
- LLPhysicsDecomp* decomp = gMeshRepo.mDecompThread;
- if (decomp)
- {
- LLMutexLock(decomp->mMutex);
+ gGL.multMatrix((GLfloat*) mat.mMatrix);
- LLModel::Decomposition& physics = model->mPhysics;
- if (physics.mHull.empty())
+ LLPhysicsDecomp* decomp = gMeshRepo.mDecompThread;
+ if (decomp)
{
- if (mVertexBuffer[LLModel::LOD_PHYSICS].empty())
+ LLMutexLock(decomp->mMutex);
+
+ LLModel::Decomposition& physics = model->mPhysics;
+
+ if (physics.mHull.empty())
{
- genBuffers(LLModel::LOD_PHYSICS, false);
- }
+ if (mVertexBuffer[LLModel::LOD_PHYSICS].empty())
+ {
+ genBuffers(LLModel::LOD_PHYSICS, false);
+ }
- for (U32 i = 0; i < mVertexBuffer[LLModel::LOD_PHYSICS][model].size(); ++i)
- {
- LLVertexBuffer* buffer = mVertexBuffer[LLModel::LOD_PHYSICS][model][i];
+ for (U32 i = 0; i < mVertexBuffer[LLModel::LOD_PHYSICS][model].size(); ++i)
+ {
+ LLVertexBuffer* buffer = mVertexBuffer[LLModel::LOD_PHYSICS][model][i];
- buffer->setBuffer(LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_TEXCOORD0);
+ buffer->setBuffer(type_mask & buffer->getTypeMask());
- LLStrider<LLVector3> pos_strider;
- buffer->getVertexStrider(pos_strider, 0);
- LLVector4a* pos = (LLVector4a*) pos_strider.get();
+ LLStrider<LLVector3> pos_strider;
+ buffer->getVertexStrider(pos_strider, 0);
+ LLVector4a* pos = (LLVector4a*) pos_strider.get();
- LLStrider<U16> idx;
- buffer->getIndexStrider(idx, 0);
-
- for (U32 i = 0; i < buffer->getNumIndices(); i += 3)
- {
- LLVector4a v1; v1.setMul(pos[*idx++], scale);
- LLVector4a v2; v2.setMul(pos[*idx++], scale);
- LLVector4a v3; v3.setMul(pos[*idx++], scale);
+ LLStrider<U16> idx;
+ buffer->getIndexStrider(idx, 0);
- if (ll_is_degenerate(v1,v2,v3))
+ for (U32 i = 0; i < buffer->getNumIndices(); i += 3)
{
- buffer->draw(LLRender::LINE_LOOP, 3, i);
- buffer->draw(LLRender::POINTS, 3, i);
+ LLVector4a v1; v1.setMul(pos[*idx++], scale);
+ LLVector4a v2; v2.setMul(pos[*idx++], scale);
+ LLVector4a v3; v3.setMul(pos[*idx++], scale);
+
+ if (ll_is_degenerate(v1,v2,v3))
+ {
+ buffer->draw(LLRender::LINE_LOOP, 3, i);
+ buffer->draw(LLRender::POINTS, 3, i);
+ }
}
}
}
}
- }
- gGL.popMatrix();
+ gGL.popMatrix();
+ }
+ glLineWidth(1.f);
+ glPointSize(1.f);
+ gPipeline.enableLightsPreview();
+ gGL.setSceneBlendType(LLRender::BT_ALPHA);
}
- glLineWidth(1.f);
- glPointSize(1.f);
- gPipeline.enableLightsPreview();
- gGL.setSceneBlendType(LLRender::BT_ALPHA);
}
}
else
@@ -5051,7 +5435,16 @@ BOOL LLModelPreview::render()
if (joint_positions)
{
+ LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr;
+ if (shader)
+ {
+ gDebugProgram.bind();
+ }
getPreviewAvatar()->renderCollisionVolumes();
+ if (shader)
+ {
+ shader->bind();
+ }
}
for (LLModelLoader::scene::iterator iter = mScene[mPreviewLOD].begin(); iter != mScene[mPreviewLOD].end(); ++iter)
@@ -5090,7 +5483,7 @@ BOOL LLModelPreview::render()
}
}
- for (U32 j = 0; j < buffer->getRequestedVerts(); ++j)
+ for (U32 j = 0; j < buffer->getNumVerts(); ++j)
{
LLMatrix4 final_mat;
final_mat.mMatrix[0][0] = final_mat.mMatrix[1][1] = final_mat.mMatrix[2][2] = final_mat.mMatrix[3][3] = 0.f;
@@ -5132,11 +5525,14 @@ BOOL LLModelPreview::render()
position[j] = v;
}
- buffer->setBuffer(LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_TEXCOORD0);
- glColor4fv(instance.mMaterial[i].mDiffuseColor.mV);
+ const std::string& binding = instance.mModel->mMaterialList[i];
+ const LLImportMaterial& material = instance.mMaterial[binding];
+
+ buffer->setBuffer(type_mask & buffer->getTypeMask());
+ gGL.diffuseColor4fv(material.mDiffuseColor.mV);
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
buffer->draw(LLRender::TRIANGLES, buffer->getNumIndices(), 0);
- glColor3f(0.4f, 0.4f, 0.4f);
+ gGL.diffuseColor3f(0.4f, 0.4f, 0.4f);
if (edges)
{
@@ -5153,6 +5549,11 @@ BOOL LLModelPreview::render()
}
}
+ if (use_shaders)
+ {
+ gObjectPreviewProgram.unbind();
+ }
+
gGL.popMatrix();
return TRUE;
@@ -5202,8 +5603,7 @@ void LLModelPreview::setPreviewLOD(S32 lod)
LLComboBox* combo_box = mFMP->getChild<LLComboBox>("preview_lod_combo");
combo_box->setCurrentByIndex((NUM_LOD-1)-mPreviewLOD); // combo box list of lods is in reverse order
- mFMP->childSetTextArg("lod_table_footer", "[DETAIL]", mFMP->getString(lod_name[mPreviewLOD]));
- mFMP->childSetText("lod_file", mLODFile[mPreviewLOD]);
+ mFMP->childSetText("lod_file_" + lod_name[mPreviewLOD], mLODFile[mPreviewLOD]);
// the wizard has three lod drop downs
LLComboBox* combo_box2 = mFMP->getChild<LLComboBox>("preview_lod_combo2");
@@ -5224,25 +5624,16 @@ void LLModelPreview::setPreviewLOD(S32 lod)
mFMP->childSetColor(lod_triangles_name[i], color);
mFMP->childSetColor(lod_vertices_name[i], color);
}
-
- LLFloaterModelPreview* fmp = LLFloaterModelPreview::sInstance;
- if (fmp)
- {
- LLRadioGroup* radio = fmp->getChild<LLRadioGroup>("lod_file_or_limit");
- radio->selectNthItem(fmp->mLODMode[mPreviewLOD]);
- }
}
refresh();
updateStatusMessages();
}
-//static
-void LLFloaterModelPreview::onBrowseLOD(void* data)
+void LLFloaterModelPreview::onBrowseLOD(S32 lod)
{
assert_main_thread();
- LLFloaterModelPreview* mp = (LLFloaterModelPreview*) data;
- mp->loadModel(mp->mModelPreview->mPreviewLOD);
+ loadModel(lod);
}
//static
@@ -5251,9 +5642,16 @@ void LLFloaterModelPreview::onReset(void* user_data)
assert_main_thread();
LLFloaterModelPreview* fmp = (LLFloaterModelPreview*) user_data;
+ fmp->childDisable("reset_btn");
LLModelPreview* mp = fmp->mModelPreview;
std::string filename = mp->mLODFile[3];
- mp->loadModel(filename,3);
+
+ fmp->resetDisplayOptions();
+ //reset model preview
+ fmp->initModelPreview();
+
+ mp = fmp->mModelPreview;
+ mp->loadModel(filename,3,true);
}
//static
@@ -5263,6 +5661,8 @@ void LLFloaterModelPreview::onUpload(void* user_data)
LLFloaterModelPreview* mp = (LLFloaterModelPreview*) user_data;
+ mp->mUploadBtn->setEnabled(false);
+
mp->mModelPreview->rebuildUploadData();
bool upload_skinweights = mp->childGetValue("upload_skin").asBoolean();
@@ -5271,31 +5671,17 @@ void LLFloaterModelPreview::onUpload(void* user_data)
mp->mModelPreview->saveUploadData(upload_skinweights, upload_joint_positions);
gMeshRepo.uploadModel(mp->mModelPreview->mUploadData, mp->mModelPreview->mPreviewScale,
- mp->childGetValue("upload_textures").asBoolean(), upload_skinweights, upload_joint_positions);
-
- mp->closeFloater(false);
+ mp->childGetValue("upload_textures").asBoolean(), upload_skinweights, upload_joint_positions, mp->mUploadModelUrl,
+ true, LLHandle<LLWholeModelFeeObserver>(), mp->getWholeModelUploadObserverHandle());
}
-//static
-void LLFloaterModelPreview::onClearMaterials(void* user_data)
-{
- LLFloaterModelPreview* mp = (LLFloaterModelPreview*) user_data;
- mp->mModelPreview->clearMaterials();
-}
-
-//static
-void LLFloaterModelPreview::refresh(LLUICtrl* ctrl, void* user_data)
+void LLFloaterModelPreview::refresh()
{
+ sInstance->toggleCalculateButton(true);
sInstance->mModelPreview->mDirty = true;
}
-void LLFloaterModelPreview::updateResourceCost()
-{
- U32 cost = mModelPreview->mResourceCost;
- childSetLabelArg("ok_btn", "[AMOUNT]", llformat("%d",cost));
-}
-
//static
void LLModelPreview::textureLoadedCallback( BOOL success, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* src_aux, S32 discard_level, BOOL final, void* userdata )
{
@@ -5311,12 +5697,11 @@ void LLModelPreview::textureLoadedCallback( BOOL success, LLViewerFetchedTexture
}
}
-void LLModelPreview::onLODParamCommit(bool enforce_tri_limit)
+void LLModelPreview::onLODParamCommit(S32 lod, bool enforce_tri_limit)
{
if (!mLODFrozen)
{
- genLODs(mPreviewLOD, 3, enforce_tri_limit);
- updateStatusMessages();
+ genLODs(lod, 3, enforce_tri_limit);
refresh();
}
}
@@ -5339,6 +5724,111 @@ void LLFloaterModelPreview::setStatusMessage(const std::string& msg)
mStatusMessage = msg;
}
+void LLFloaterModelPreview::toggleCalculateButton()
+{
+ toggleCalculateButton(true);
+}
+
+void LLFloaterModelPreview::toggleCalculateButton(bool visible)
+{
+ mCalculateBtn->setVisible(visible);
+
+ bool uploadingSkin = childGetValue("upload_skin").asBoolean();
+ bool uploadingJointPositions = childGetValue("upload_joints").asBoolean();
+ if ( uploadingSkin )
+ {
+ //Disable the calculate button *if* the rig is invalid - which is determined during the critiquing process
+ if ( uploadingJointPositions && !mModelPreview->isRigValidForJointPositionUpload() )
+ {
+ mCalculateBtn->setVisible( false );
+ }
+ }
+
+ mUploadBtn->setVisible(!visible);
+ mUploadBtn->setEnabled(mHasUploadPerm && !mUploadModelUrl.empty());
+
+ if (visible)
+ {
+ std::string tbd = getString("tbd");
+ childSetTextArg("prim_weight", "[EQ]", tbd);
+ childSetTextArg("download_weight", "[ST]", tbd);
+ childSetTextArg("server_weight", "[SIM]", tbd);
+ childSetTextArg("physics_weight", "[PH]", tbd);
+ childSetTextArg("upload_fee", "[FEE]", tbd);
+ childSetTextArg("price_breakdown", "[STREAMING]", tbd);
+ childSetTextArg("price_breakdown", "[PHYSICS]", tbd);
+ childSetTextArg("price_breakdown", "[INSTANCES]", tbd);
+ childSetTextArg("price_breakdown", "[TEXTURES]", tbd);
+ childSetTextArg("price_breakdown", "[MODEL]", tbd);
+ }
+}
+
+void LLFloaterModelPreview::onLoDSourceCommit(S32 lod)
+{
+ mModelPreview->updateLodControls(lod);
+ refresh();
+}
+
+void LLFloaterModelPreview::resetDisplayOptions()
+{
+ std::map<std::string,bool>::iterator option_it = mModelPreview->mViewOption.begin();
+
+ for(;option_it != mModelPreview->mViewOption.end(); ++option_it)
+ {
+ LLUICtrl* ctrl = getChild<LLUICtrl>(option_it->first);
+ ctrl->setValue(false);
+ }
+}
+
+void LLFloaterModelPreview::onModelPhysicsFeeReceived(const LLSD& result, std::string upload_url)
+{
+ mModelPhysicsFee = result;
+ mModelPhysicsFee["url"] = upload_url;
+
+ doOnIdleOneTime(boost::bind(&LLFloaterModelPreview::handleModelPhysicsFeeReceived,this));
+}
+
+void LLFloaterModelPreview::handleModelPhysicsFeeReceived()
+{
+ const LLSD& result = mModelPhysicsFee;
+ mUploadModelUrl = result["url"].asString();
+
+ childSetTextArg("prim_weight", "[EQ]", llformat("%0.3f", result["resource_cost"].asReal()));
+ childSetTextArg("download_weight", "[ST]", llformat("%0.3f", result["model_streaming_cost"].asReal()));
+ childSetTextArg("server_weight", "[SIM]", llformat("%0.3f", result["simulation_cost"].asReal()));
+ childSetTextArg("physics_weight", "[PH]", llformat("%0.3f", result["physics_cost"].asReal()));
+ childSetTextArg("upload_fee", "[FEE]", llformat("%d", result["upload_price"].asInteger()));
+ childSetTextArg("price_breakdown", "[STREAMING]", llformat("%d", result["upload_price_breakdown"]["mesh_streaming"].asInteger()));
+ childSetTextArg("price_breakdown", "[PHYSICS]", llformat("%d", result["upload_price_breakdown"]["mesh_physics"].asInteger()));
+ childSetTextArg("price_breakdown", "[INSTANCES]", llformat("%d", result["upload_price_breakdown"]["mesh_instance"].asInteger()));
+ childSetTextArg("price_breakdown", "[TEXTURES]", llformat("%d", result["upload_price_breakdown"]["texture"].asInteger()));
+ childSetTextArg("price_breakdown", "[MODEL]", llformat("%d", result["upload_price_breakdown"]["model"].asInteger()));
+ childSetVisible("upload_fee", true);
+ childSetVisible("price_breakdown", true);
+ mUploadBtn->setEnabled(mHasUploadPerm && !mUploadModelUrl.empty());
+}
+
+void LLFloaterModelPreview::setModelPhysicsFeeErrorStatus(U32 status, const std::string& reason)
+{
+ llwarns << "LLFloaterModelPreview::setModelPhysicsFeeErrorStatus(" << status << " : " << reason << ")" << llendl;
+ doOnIdleOneTime(boost::bind(&LLFloaterModelPreview::toggleCalculateButton, this, true));
+}
+
+/*virtual*/
+void LLFloaterModelPreview::onModelUploadSuccess()
+{
+ assert_main_thread();
+ closeFloater(false);
+}
+
+/*virtual*/
+void LLFloaterModelPreview::onModelUploadFailure()
+{
+ assert_main_thread();
+ toggleCalculateButton(true);
+ mUploadBtn->setEnabled(true);
+}
+
S32 LLFloaterModelPreview::DecompRequest::statusCallback(const char* status, S32 p1, S32 p2)
{
if (mContinue)
@@ -5378,3 +5868,25 @@ void LLFloaterModelPreview::DecompRequest::completed()
llassert(sInstance->mCurRequest.find(this) == sInstance->mCurRequest.end());
}
}
+
+void dump_llsd_to_file(const LLSD& content, std::string filename);
+
+void LLFloaterModelPreview::onPermissionsReceived(const LLSD& result)
+{
+ dump_llsd_to_file(result,"perm_received.xml");
+ std::string upload_status = result["mesh_upload_status"].asString();
+ // BAP HACK: handle "" for case that MeshUploadFlag cap is broken.
+ mHasUploadPerm = (("" == upload_status) || ("valid" == upload_status));
+
+ //mUploadBtn->setEnabled(mHasUploadPerm);
+ mUploadBtn->setEnabled(mHasUploadPerm && !mUploadModelUrl.empty());
+ getChild<LLTextBox>("warning_title")->setVisible(!mHasUploadPerm);
+ getChild<LLTextBox>("warning_message")->setVisible(!mHasUploadPerm);
+}
+
+void LLFloaterModelPreview::setPermissonsErrorStatus(U32 status, const std::string& reason)
+{
+ llwarns << "LLFloaterModelPreview::setPermissonsErrorStatus(" << status << " : " << reason << ")" << llendl;
+
+ LLNotificationsUtil::add("MeshUploadPermError");
+}