/indra/newview/llfloatermodelpreview.cpp
C++ | 2236 lines | 1677 code | 365 blank | 194 comment | 273 complexity | ec1ea93da092dfb0a77706f06582b3f6 MD5 | raw file
Possible License(s): LGPL-2.1
Large files files are truncated, but you can click here to view the full file
- /**
- * @file llfloatermodelpreview.cpp
- * @brief LLFloaterModelPreview class implementation
- *
- * $LicenseInfo:firstyear=2004&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
- #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"
- #include "dom/domBind_material.h"
- #include "dom/domCOLLADA.h"
- #include "dom/domConstants.h"
- #include "dom/domController.h"
- #include "dom/domEffect.h"
- #include "dom/domGeometry.h"
- #include "dom/domInstance_geometry.h"
- #include "dom/domInstance_material.h"
- #include "dom/domInstance_node.h"
- #include "dom/domInstance_effect.h"
- #include "dom/domMaterial.h"
- #include "dom/domMatrix.h"
- #include "dom/domNode.h"
- #include "dom/domProfile_COMMON.h"
- #include "dom/domRotate.h"
- #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"
- #include "llfilepicker.h"
- #include "llimagebmp.h"
- #include "llimagetga.h"
- #include "llimagejpeg.h"
- #include "llimagepng.h"
- #include "llagent.h"
- #include "llbutton.h"
- #include "llcombobox.h"
- #include "lldatapacker.h"
- #include "lldrawable.h"
- #include "lldrawpoolavatar.h"
- #include "llrender.h"
- #include "llface.h"
- #include "lleconomy.h"
- #include "llfocusmgr.h"
- #include "llfloaterperms.h"
- #include "lliconctrl.h"
- #include "llmatrix4a.h"
- #include "llmenubutton.h"
- #include "llmeshrepository.h"
- #include "llnotificationsutil.h"
- #include "llsdutil_math.h"
- #include "lltextbox.h"
- #include "lltoolmgr.h"
- #include "llui.h"
- #include "llvector4a.h"
- #include "llviewercamera.h"
- #include "llviewerwindow.h"
- #include "llvoavatar.h"
- #include "llvoavatarself.h"
- #include "pipeline.h"
- #include "lluictrlfactory.h"
- #include "llviewercontrol.h"
- #include "llviewermenu.h"
- #include "llviewermenufile.h"
- #include "llviewerregion.h"
- #include "llviewertexturelist.h"
- #include "llstring.h"
- #include "llbutton.h"
- #include "llcheckboxctrl.h"
- #include "llradiogroup.h"
- #include "llsdserialize.h"
- #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;
- LLFloaterModelPreview* LLFloaterModelPreview::sInstance = NULL;
- std::list<LLModelLoader*> LLModelLoader::sActiveLoaderList;
- const S32 PREVIEW_BORDER_WIDTH = 2;
- const S32 PREVIEW_RESIZE_HANDLE_SIZE = S32(RESIZE_HANDLE_WIDTH * OO_SQRT2) + PREVIEW_BORDER_WIDTH;
- 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);
- std::string lod_name[NUM_LOD+1] =
- {
- "lowest",
- "low",
- "medium",
- "high",
- "I went off the end of the lod_name array. Me so smart."
- };
- std::string lod_triangles_name[NUM_LOD+1] =
- {
- "lowest_triangles",
- "low_triangles",
- "medium_triangles",
- "high_triangles",
- "I went off the end of the lod_triangles_name array. Me so smart."
- };
- std::string lod_vertices_name[NUM_LOD+1] =
- {
- "lowest_vertices",
- "low_vertices",
- "medium_vertices",
- "high_vertices",
- "I went off the end of the lod_vertices_name array. Me so smart."
- };
- std::string lod_status_name[NUM_LOD+1] =
- {
- "lowest_status",
- "low_status",
- "medium_status",
- "high_status",
- "I went off the end of the lod_status_name array. Me so smart."
- };
- std::string lod_icon_name[NUM_LOD+1] =
- {
- "status_icon_lowest",
- "status_icon_low",
- "status_icon_medium",
- "status_icon_high",
- "I went off the end of the lod_status_name array. Me so smart."
- };
- std::string lod_status_image[NUM_LOD+1] =
- {
- "ModelImport_Status_Good",
- "ModelImport_Status_Warning",
- "ModelImport_Status_Error",
- "I went off the end of the lod_status_image array. Me so smart."
- };
- std::string lod_label_name[NUM_LOD+1] =
- {
- "lowest_label",
- "low_label",
- "medium_label",
- "high_label",
- "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
- inline F32 dot3fpu(const LLVector4a& a, const LLVector4a& b)
- {
- volatile F32 p0 = a[0] * b[0];
- volatile F32 p1 = a[1] * b[1];
- volatile F32 p2 = a[2] * b[2];
- return p0 + p1 + p2;
- }
- bool ll_is_degenerate(const LLVector4a& a, const LLVector4a& b, const LLVector4a& c, F32 tolerance = LL_DEGENERACY_TOLERANCE)
- {
- // small area check
- {
- LLVector4a edge1; edge1.setSub( a, b );
- LLVector4a edge2; edge2.setSub( a, c );
- //////////////////////////////////////////////////////////////////////////
- /// Linden Modified
- //////////////////////////////////////////////////////////////////////////
- // If no one edge is more than 10x longer than any other edge, we weaken
- // the tolerance by a factor of 1e-4f.
- LLVector4a edge3; edge3.setSub( c, b );
- const F32 len1sq = edge1.dot3(edge1).getF32();
- const F32 len2sq = edge2.dot3(edge2).getF32();
- const F32 len3sq = edge3.dot3(edge3).getF32();
- bool abOK = (len1sq <= 100.f * len2sq) && (len1sq <= 100.f * len3sq);
- bool acOK = (len2sq <= 100.f * len1sq) && (len1sq <= 100.f * len3sq);
- bool cbOK = (len3sq <= 100.f * len1sq) && (len1sq <= 100.f * len2sq);
- if ( abOK && acOK && cbOK )
- {
- tolerance *= 1e-4f;
- }
- //////////////////////////////////////////////////////////////////////////
- /// End Modified
- //////////////////////////////////////////////////////////////////////////
- LLVector4a cross; cross.setCross3( edge1, edge2 );
- LLVector4a edge1b; edge1b.setSub( b, a );
- LLVector4a edge2b; edge2b.setSub( b, c );
- LLVector4a crossb; crossb.setCross3( edge1b, edge2b );
- if ( ( cross.dot3(cross).getF32() < tolerance ) || ( crossb.dot3(crossb).getF32() < tolerance ))
- {
- return true;
- }
- }
- // point triangle distance check
- {
- LLVector4a Q; Q.setSub(a, b);
- LLVector4a R; R.setSub(c, b);
- const F32 QQ = dot3fpu(Q, Q);
- const F32 RR = dot3fpu(R, R);
- const F32 QR = dot3fpu(R, Q);
- volatile F32 QQRR = QQ * RR;
- volatile F32 QRQR = QR * QR;
- F32 Det = (QQRR - QRQR);
- if( Det == 0.0f )
- {
- return true;
- }
- }
- return false;
- }
- bool validate_face(const LLVolumeFace& face)
- {
- for (U32 i = 0; i < face.mNumIndices; ++i)
- {
- if (face.mIndices[i] >= face.mNumVertices)
- {
- llwarns << "Face has invalid index." << llendl;
- return false;
- }
- }
- if (face.mNumIndices % 3 != 0 || face.mNumIndices == 0)
- {
- llwarns << "Face has invalid number of indices." << llendl;
- return false;
- }
- /*const LLVector4a scale(0.5f);
- for (U32 i = 0; i < face.mNumIndices; i+=3)
- {
- U16 idx1 = face.mIndices[i];
- U16 idx2 = face.mIndices[i+1];
- U16 idx3 = face.mIndices[i+2];
- LLVector4a v1; v1.setMul(face.mPositions[idx1], scale);
- LLVector4a v2; v2.setMul(face.mPositions[idx2], scale);
- LLVector4a v3; v3.setMul(face.mPositions[idx3], scale);
- if (ll_is_degenerate(v1,v2,v3))
- {
- llwarns << "Degenerate face found!" << llendl;
- return false;
- }
- }*/
- return true;
- }
- bool validate_model(const LLModel* mdl)
- {
- if (mdl->getNumVolumeFaces() == 0)
- {
- llwarns << "Model has no faces!" << llendl;
- return false;
- }
- for (S32 i = 0; i < mdl->getNumVolumeFaces(); ++i)
- {
- if (mdl->getVolumeFace(i).mNumVertices == 0)
- {
- llwarns << "Face has no vertices." << llendl;
- return false;
- }
- if (mdl->getVolumeFace(i).mNumIndices == 0)
- {
- llwarns << "Face has no indices." << llendl;
- return false;
- }
- if (!validate_face(mdl->getVolumeFace(i)))
- {
- return false;
- }
- }
- return true;
- }
- BOOL stop_gloderror()
- {
- GLuint error = glodGetError();
- if (error != GLOD_NO_ERROR)
- {
- llwarns << "GLOD error detected, cannot generate LOD: " << std::hex << error << llendl;
- return TRUE;
- }
- return FALSE;
- }
- LLMeshFilePicker::LLMeshFilePicker(LLModelPreview* mp, S32 lod)
- : LLFilePickerThread(LLFilePicker::FFLOAD_COLLADA)
- {
- mMP = mp;
- mLOD = lod;
- }
- void LLMeshFilePicker::notify(const std::string& filename)
- {
- mMP->loadModel(mFile, mLOD);
- }
- //-----------------------------------------------------------------------------
- // LLFloaterModelPreview()
- //-----------------------------------------------------------------------------
- LLFloaterModelPreview::LLFloaterModelPreview(const LLSD& 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++)
- {
- mLODMode[i] = 1;
- }
- }
- //-----------------------------------------------------------------------------
- // postBuild()
- //-----------------------------------------------------------------------------
- BOOL LLFloaterModelPreview::postBuild()
- {
- if (!LLFloater::postBuild())
- {
- return FALSE;
- }
- childSetCommitCallback("cancel_btn", onCancel, this);
- childSetCommitCallback("crease_angle", onGenerateNormalsCommit, this);
- getChild<LLCheckBoxCtrl>("gen_normals")->setCommitCallback(boost::bind(&LLFloaterModelPreview::toggleGenarateNormals, this));
- childSetCommitCallback("lod_generate", onAutoFillCommit, 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"));
- childSetAction("ok_btn", onUpload, this);
- childDisable("ok_btn");
- childSetAction("reset_btn", onReset, this);
- childSetCommitCallback("preview_lod_combo", onPreviewLODCommit, this);
- childSetCommitCallback("upload_skin", onUploadSkinCommit, this);
- childSetCommitCallback("upload_joints", onUploadJointsCommit, this);
- childSetCommitCallback("import_scale", onImportScaleCommit, this);
- childSetCommitCallback("pelvis_offset", onPelvisOffsetCommit, 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");
- initDecompControls();
- LLView* preview_panel = getChild<LLView>("preview_panel");
- mPreviewRect = preview_panel->getRect();
- initModelPreview();
- //set callbacks for left click on line editor rows
- for (U32 i = 0; i <= LLModel::LOD_HIGH; i++)
- {
- LLTextBox* text = getChild<LLTextBox>(lod_label_name[i]);
- if (text)
- {
- text->setMouseDownCallback(boost::bind(&LLModelPreview::setPreviewLOD, mModelPreview, i));
- }
- text = getChild<LLTextBox>(lod_triangles_name[i]);
- if (text)
- {
- text->setMouseDownCallback(boost::bind(&LLModelPreview::setPreviewLOD, mModelPreview, i));
- }
- text = getChild<LLTextBox>(lod_vertices_name[i]);
- if (text)
- {
- text->setMouseDownCallback(boost::bind(&LLModelPreview::setPreviewLOD, mModelPreview, i));
- }
- text = getChild<LLTextBox>(lod_status_name[i]);
- if (text)
- {
- 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;
- }
- //-----------------------------------------------------------------------------
- // LLFloaterModelPreview()
- //-----------------------------------------------------------------------------
- LLFloaterModelPreview::~LLFloaterModelPreview()
- {
- sInstance = NULL;
-
- if ( mModelPreview )
- {
- delete mModelPreview;
- }
- if (mGLName)
- {
- LLImageGL::deleteTextures(1, &mGLName );
- }
- delete mStatusLock;
- mStatusLock = NULL;
- }
- 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[ctrl->getName()] = !mModelPreview->mViewOption[ctrl->getName()];
-
- mModelPreview->refresh();
- }
- }
- bool LLFloaterModelPreview::isViewOptionChecked(const LLSD& userdata)
- {
- if (mModelPreview)
- {
- return mModelPreview->mViewOption[userdata.asString()];
- }
- return false;
- }
- bool LLFloaterModelPreview::isViewOptionEnabled(const LLSD& userdata)
- {
- return childIsEnabled(userdata.asString());
- }
- void LLFloaterModelPreview::setViewOptionEnabled(const std::string& option, bool enabled)
- {
- childSetEnabled(option, enabled);
- }
- void LLFloaterModelPreview::enableViewOption(const std::string& option)
- {
- setViewOptionEnabled(option, true);
- }
- void LLFloaterModelPreview::disableViewOption(const std::string& option)
- {
- setViewOptionEnabled(option, false);
- }
- void LLFloaterModelPreview::loadModel(S32 lod)
- {
- mModelPreview->mLoading = true;
- (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)
- {
- LLFloaterModelPreview *fp =(LLFloaterModelPreview *)userdata;
- if (!fp->mModelPreview)
- {
- return;
- }
- fp->mModelPreview->mDirty = true;
- fp->toggleCalculateButton(true);
- fp->mModelPreview->refresh();
- }
- //static
- void LLFloaterModelPreview::onPelvisOffsetCommit( LLUICtrl*, void* userdata )
- {
- LLFloaterModelPreview *fp =(LLFloaterModelPreview*)userdata;
- if (!fp->mModelPreview)
- {
- return;
- }
- fp->mModelPreview->mDirty = true;
- fp->toggleCalculateButton(true);
- fp->mModelPreview->refresh();
- }
- //static
- void LLFloaterModelPreview::onUploadJointsCommit(LLUICtrl*,void* userdata)
- {
- LLFloaterModelPreview *fp =(LLFloaterModelPreview *)userdata;
- if (!fp->mModelPreview)
- {
- return;
- }
- fp->mModelPreview->refresh();
- }
- //static
- void LLFloaterModelPreview::onUploadSkinCommit(LLUICtrl*,void* userdata)
- {
- LLFloaterModelPreview *fp =(LLFloaterModelPreview *)userdata;
- if (!fp->mModelPreview)
- {
- return;
- }
- fp->mModelPreview->refresh();
- fp->mModelPreview->resetPreviewTarget();
- fp->mModelPreview->clearBuffers();
- }
- //static
- void LLFloaterModelPreview::onPreviewLODCommit(LLUICtrl* ctrl, void* userdata)
- {
- LLFloaterModelPreview *fp =(LLFloaterModelPreview *)userdata;
- if (!fp->mModelPreview)
- {
- return;
- }
- S32 which_mode = 0;
- LLComboBox* combo = (LLComboBox*) ctrl;
- which_mode = (NUM_LOD-1)-combo->getFirstSelectedIndex(); // combo box list of lods is in reverse order
- fp->mModelPreview->setPreviewLOD(which_mode);
- }
- //static
- void LLFloaterModelPreview::onGenerateNormalsCommit(LLUICtrl* ctrl, void* userdata)
- {
- LLFloaterModelPreview* fp = (LLFloaterModelPreview*) userdata;
- fp->mModelPreview->generateNormals();
- }
- void LLFloaterModelPreview::toggleGenarateNormals()
- {
- bool enabled = childGetValue("gen_normals").asBoolean();
- childSetEnabled("crease_angle", enabled);
- }
- //static
- void LLFloaterModelPreview::onExplodeCommit(LLUICtrl* ctrl, void* userdata)
- {
- LLFloaterModelPreview* fp = LLFloaterModelPreview::sInstance;
- fp->mModelPreview->refresh();
- }
- //static
- void LLFloaterModelPreview::onAutoFillCommit(LLUICtrl* ctrl, void* userdata)
- {
- LLFloaterModelPreview* fp = (LLFloaterModelPreview*) userdata;
- fp->mModelPreview->genLODs();
- }
- void LLFloaterModelPreview::onLODParamCommit(S32 lod, bool enforce_tri_limit)
- {
- mModelPreview->onLODParamCommit(lod, enforce_tri_limit);
- }
- //-----------------------------------------------------------------------------
- // draw()
- //-----------------------------------------------------------------------------
- void LLFloaterModelPreview::draw()
- {
- LLFloater::draw();
- LLRect r = getRect();
- mModelPreview->update();
- 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)));
- }
- else
- if ( mModelPreview->getLoadState() == LLModelLoader::ERROR_PARSING )
- {
- childSetTextArg("status", "[STATUS]", getString("status_parse_error"));
- toggleCalculateButton(false);
- }
- else
- {
- childSetTextArg("status", "[STATUS]", getString("status_idle"));
- }
- }
- childSetTextArg("prim_cost", "[PRIM_COST]", llformat("%d", mModelPreview->mResourceCost));
- childSetTextArg("description_label", "[TEXTURES]", llformat("%d", mModelPreview->mTextureSet.size()));
- if (mModelPreview)
- {
- gGL.color3f(1.f, 1.f, 1.f);
- gGL.getTexUnit(0)->bind(mModelPreview);
- LLView* preview_panel = getChild<LLView>("preview_panel");
- LLRect rect = preview_panel->getRect();
- if (rect != mPreviewRect)
- {
- mModelPreview->refresh();
- mPreviewRect = preview_panel->getRect();
- }
- gGL.begin( LLRender::QUADS );
- {
- gGL.texCoord2f(0.f, 1.f);
- gGL.vertex2i(mPreviewRect.mLeft, mPreviewRect.mTop-1);
- gGL.texCoord2f(0.f, 0.f);
- gGL.vertex2i(mPreviewRect.mLeft, mPreviewRect.mBottom);
- gGL.texCoord2f(1.f, 0.f);
- gGL.vertex2i(mPreviewRect.mRight-1, mPreviewRect.mBottom);
- gGL.texCoord2f(1.f, 1.f);
- gGL.vertex2i(mPreviewRect.mRight-1, mPreviewRect.mTop-1);
- }
- gGL.end();
- gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
- }
- }
- //-----------------------------------------------------------------------------
- // handleMouseDown()
- //-----------------------------------------------------------------------------
- BOOL LLFloaterModelPreview::handleMouseDown(S32 x, S32 y, MASK mask)
- {
- if (mPreviewRect.pointInRect(x, y))
- {
- bringToFront( x, y );
- gFocusMgr.setMouseCapture(this);
- gViewerWindow->hideCursor();
- mLastMouseX = x;
- mLastMouseY = y;
- return TRUE;
- }
- return LLFloater::handleMouseDown(x, y, mask);
- }
- //-----------------------------------------------------------------------------
- // handleMouseUp()
- //-----------------------------------------------------------------------------
- BOOL LLFloaterModelPreview::handleMouseUp(S32 x, S32 y, MASK mask)
- {
- gFocusMgr.setMouseCapture(FALSE);
- gViewerWindow->showCursor();
- return LLFloater::handleMouseUp(x, y, mask);
- }
- //-----------------------------------------------------------------------------
- // handleHover()
- //-----------------------------------------------------------------------------
- BOOL LLFloaterModelPreview::handleHover (S32 x, S32 y, MASK mask)
- {
- MASK local_mask = mask & ~MASK_ALT;
- if (mModelPreview && hasMouseCapture())
- {
- if (local_mask == MASK_PAN)
- {
- // pan here
- mModelPreview->pan((F32)(x - mLastMouseX) * -0.005f, (F32)(y - mLastMouseY) * -0.005f);
- }
- else if (local_mask == MASK_ORBIT)
- {
- F32 yaw_radians = (F32)(x - mLastMouseX) * -0.01f;
- F32 pitch_radians = (F32)(y - mLastMouseY) * 0.02f;
- mModelPreview->rotate(yaw_radians, pitch_radians);
- }
- else
- {
- F32 yaw_radians = (F32)(x - mLastMouseX) * -0.01f;
- F32 zoom_amt = (F32)(y - mLastMouseY) * 0.02f;
- mModelPreview->rotate(yaw_radians, 0.f);
- mModelPreview->zoom(zoom_amt);
- }
- mModelPreview->refresh();
- LLUI::setMousePositionLocal(this, mLastMouseX, mLastMouseY);
- }
- if (!mPreviewRect.pointInRect(x, y) || !mModelPreview)
- {
- return LLFloater::handleHover(x, y, mask);
- }
- else if (local_mask == MASK_ORBIT)
- {
- gViewerWindow->setCursor(UI_CURSOR_TOOLCAMERA);
- }
- else if (local_mask == MASK_PAN)
- {
- gViewerWindow->setCursor(UI_CURSOR_TOOLPAN);
- }
- else
- {
- gViewerWindow->setCursor(UI_CURSOR_TOOLZOOMIN);
- }
- return TRUE;
- }
- //-----------------------------------------------------------------------------
- // handleScrollWheel()
- //-----------------------------------------------------------------------------
- BOOL LLFloaterModelPreview::handleScrollWheel(S32 x, S32 y, S32 clicks)
- {
- if (mPreviewRect.pointInRect(x, y) && mModelPreview)
- {
- mModelPreview->zoom((F32)clicks * -0.2f);
- mModelPreview->refresh();
- }
- return TRUE;
- }
- /*virtual*/
- void LLFloaterModelPreview::onOpen(const LLSD& key)
- {
- requestAgentUploadPermissions();
- }
- //static
- void LLFloaterModelPreview::onPhysicsParamCommit(LLUICtrl* ctrl, void* data)
- {
- if (LLConvexDecomposition::getInstance() == NULL)
- {
- llinfos << "convex decomposition tool is a stub on this platform. cannot get decomp." << llendl;
- return;
- }
- if (sInstance)
- {
- LLCDParam* param = (LLCDParam*) data;
- std::string name(param->mName);
- LLSD value = ctrl->getValue();
- if("Retain%" == name)
- {
- value = ctrl->getValue().asReal() / RETAIN_COEFFICIENT;
- }
- sInstance->mDecompParams[name] = value;
- if (name == "Simplify Method")
- {
- bool show_retain = false;
- bool show_detail = true;
- if (ctrl->getValue().asInteger() == 0)
- {
- 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);
- }
- }
- }
- //static
- void LLFloaterModelPreview::onPhysicsStageExecute(LLUICtrl* ctrl, void* data)
- {
- LLCDStageData* stage_data = (LLCDStageData*) data;
- std::string stage = stage_data->mName;
- if (sInstance)
- {
- if (!sInstance->mCurRequest.empty())
- {
- llinfos << "Decomposition request still pending." << llendl;
- return;
- }
- if (sInstance->mModelPreview)
- {
- for (S32 i = 0; i < sInstance->mModelPreview->mModel[LLModel::LOD_PHYSICS].size(); ++i)
- {
- LLModel* mdl = sInstance->mModelPreview->mModel[LLModel::LOD_PHYSICS][i];
- DecompRequest* request = new DecompRequest(stage, mdl);
- sInstance->mCurRequest.insert(request);
- gMeshRepo.mDecompThread->submitRequest(request);
- }
- }
- if (stage == "Decompose")
- {
- 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");
- }
- }
- }
- //static
- void LLFloaterModelPreview::onPhysicsBrowse(LLUICtrl* ctrl, void* userdata)
- {
- sInstance->loadModel(LLModel::LOD_PHYSICS);
- }
- //static
- void LLFloaterModelPreview::onPhysicsUseLOD(LLUICtrl* ctrl, void* userdata)
- {
- 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);
- }
- LLModelPreview *model_preview = sInstance->mModelPreview;
- if (model_preview)
- {
- model_preview->refresh();
- model_preview->updateStatusMessages();
- }
- }
- //static
- void LLFloaterModelPreview::onCancel(LLUICtrl* ctrl, void* data)
- {
- if (sInstance)
- {
- sInstance->closeFloater(false);
- }
- }
- //static
- void LLFloaterModelPreview::onPhysicsStageCancel(LLUICtrl* ctrl, void*data)
- {
- if (sInstance)
- {
- for (std::set<LLPointer<DecompRequest> >::iterator iter = sInstance->mCurRequest.begin();
- iter != sInstance->mCurRequest.end(); ++iter)
- {
- DecompRequest* req = *iter;
- req->mContinue = 0;
- }
- sInstance->mCurRequest.clear();
- if (sInstance->mModelPreview)
- {
- sInstance->mModelPreview->updateStatusMessages();
- }
- }
- }
- void LLFloaterModelPreview::initDecompControls()
- {
- LLSD key;
- childSetCommitCallback("simplify_cancel", onPhysicsStageCancel, NULL);
- childSetCommitCallback("decompose_cancel", onPhysicsStageCancel, NULL);
- childSetCommitCallback("physics_lod_combo", onPhysicsUseLOD, NULL);
- childSetCommitCallback("physics_browse", onPhysicsBrowse, NULL);
- static const LLCDStageData* stage = NULL;
- static S32 stage_count = 0;
- if (!stage && LLConvexDecomposition::getInstance() != NULL)
- {
- stage_count = LLConvexDecomposition::getInstance()->getStages(&stage);
- }
- static const LLCDParam* param = NULL;
- static S32 param_count = 0;
- if (!param && LLConvexDecomposition::getInstance() != NULL)
- {
- param_count = LLConvexDecomposition::getInstance()->getParameters(¶m);
- }
- for (S32 j = stage_count-1; j >= 0; --j)
- {
- LLButton* button = getChild<LLButton>(stage[j].mName);
- if (button)
- {
- button->setCommitCallback(onPhysicsStageExecute, (void*) &stage[j]);
- }
- gMeshRepo.mDecompThread->mStageID[stage[j].mName] = j;
- // protected against stub by stage_count being 0 for stub above
- LLConvexDecomposition::getInstance()->registerCallback(j, LLPhysicsDecomp::llcdCallback);
- //llinfos << "Physics decomp stage " << stage[j].mName << " (" << j << ") parameters:" << llendl;
- //llinfos << "------------------------------------" << llendl;
- for (S32 i = 0; i < param_count; ++i)
- {
- if (param[i].mStage != j)
- {
- continue;
- }
- std::string name(param[i].mName ? param[i].mName : "");
- std::string description(param[i].mDescription ? param[i].mDescription : "");
- std::string type = "unknown";
- llinfos << name << " - " << description << llendl;
- if (param[i].mType == LLCDParam::LLCD_FLOAT)
- {
- mDecompParams[param[i].mName] = LLSD(param[i].mDefault.mFloat);
- //llinfos << "Type: float, Default: " << param[i].mDefault.mFloat << llendl;
- 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);
- slider->setIncrement(param[i].mDetails.mRange.mDelta.mFloat);
- slider->setValue(param[i].mDefault.mFloat);
- slider->setCommitCallback(onPhysicsParamCommit, (void*) ¶m[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*) ¶m[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*) ¶m[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;
- 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);
- slider->setIncrement(param[i].mDetails.mRange.mDelta.mIntOrEnumValue);
- slider->setValue(param[i].mDefault.mIntOrEnumValue);
- slider->setCommitCallback(onPhysicsParamCommit, (void*) ¶m[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*) ¶m[i]);
- }
- }
- else if (param[i].mType == LLCDParam::LLCD_BOOLEAN)
- {
- mDecompParams[param[i].mName] = LLSD(param[i].mDefault.mBool);
- //llinfos << "Type: boolean, Default: " << (param[i].mDefault.mBool ? "True" : "False") << llendl;
- LLCheckBoxCtrl* check_box = getChild<LLCheckBoxCtrl>(name);
- if (check_box)
- {
- check_box->setValue(param[i].mDefault.mBool);
- check_box->setCommitCallback(onPhysicsParamCommit, (void*) ¶m[i]);
- }
- }
- else if (param[i].mType == LLCDParam::LLCD_ENUM)
- {
- mDecompParams[param[i].mName] = LLSD(param[i].mDefault.mIntOrEnumValue);
- //llinfos << "Type: enum, Default: " << param[i].mDefault.mIntOrEnumValue << llendl;
- { //plug into combo box
- //llinfos << "Accepted values: " << llendl;
- LLComboBox* combo_box = getChild<LLComboBox>(name);
- for (S32 k = 0; k < param[i].mDetails.mEnumValues.mNumEnums; ++k)
- {
- //llinfos << param[i].mDetails.mEnumValues.mEnumsArray[k].mValue
- // << " - " << param[i].mDetails.mEnumValues.mEnumsArray[k].mName << llendl;
- 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);
- combo_box->setCommitCallback(onPhysicsParamCommit, (void*) ¶m[i]);
- }
- //llinfos << "----" << llendl;
- }
- //llinfos << "-----------------------------" << llendl;
- }
- }
- 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()
- //-----------------------------------------------------------------------------
- // static
- void LLFloaterModelPreview::onMouseCaptureLostModelPreview(LLMouseHandler* handler)
- {
- gViewerWindow->showCursor();
- }
- //-----------------------------------------------------------------------------
- // LLModelLoader
- //-----------------------------------------------------------------------------
- LLModelLoader::LLModelLoader( std::string filename, S32 lod, LLModelPreview* preview, JointTransformMap& jointMap,
- std::deque<std::string>& jointsFromNodes )
- : mJointList( jointMap )
- , mJointsFromNode( jointsFromNodes )
- , LLThread("Model Loader"), mFilename(filename), mLod(lod), mPreview(preview), mFirstTransform(TRUE), mNumOfFetchingTextures(0)
- {
- mJointMap["mPelvis"] = "mPelvis";
- mJointMap["mTorso"] = "mTorso";
- mJointMap["mChest"] = "mChest";
- mJointMap["mNeck"] = "mNeck";
- mJointMap["mHead"] = "mHead";
- mJointMap["mSkull"] = "mSkull";
- mJointMap["mEyeRight"] = "mEyeRight";
- mJointMap["mEyeLeft"] = "mEyeLeft";
- mJointMap["mCollarLeft"] = "mCollarLeft";
- mJointMap["mShoulderLeft"] = "mShoulderLeft";
- mJointMap["mElbowLeft"] = "mElbowLeft";
- mJointMap["mWristLeft"] = "mWristLeft";
- mJointMap["mCollarRight"] = "mCollarRight";
- mJointMap["mShoulderRight"] = "mShoulderRight";
- mJointMap["mElbowRight"] = "mElbowRight";
- mJointMap["mWristRight"] = "mWristRight";
- mJointMap["mHipRight"] = "mHipRight";
- mJointMap["mKneeRight"] = "mKneeRight";
- mJointMap["mAnkleRight"] = "mAnkleRight";
- mJointMap["mFootRight"] = "mFootRight";
- mJointMap["mToeRight"] = "mToeRight";
- mJointMap["mHipLeft"] = "mHipLeft";
- mJointMap["mKneeLeft"] = "mKneeLeft";
- mJointMap["mAnkleLeft"] = "mAnkleLeft";
- mJointMap["mFootLeft"] = "mFootLeft";
- mJointMap["mToeLeft"] = "mToeLeft";
- mJointMap["avatar_mPelvis"] = "mPelvis";
- mJointMap["avatar_mTorso"] = "mTorso";
- mJointMap["avatar_mChest"] = "mChest";
- mJointMap["avatar_mNeck"] = "mNeck";
- mJointMap["avatar_mHead"] = "mHead";
- mJointMap["avatar_mSkull"] = "mSkull";
- mJointMap["avatar_mEyeRight"] = "mEyeRight";
- mJointMap["avatar_mEyeLeft"] = "mEyeLeft";
- mJointMap["avatar_mCollarLeft"] = "mCollarLeft";
- mJointMap["avatar_mShoulderLeft"] = "mShoulderLeft";
- mJointMap["avatar_mElbowLeft"] = "mElbowLeft";
- mJointMap["avatar_mWristLeft"] = "mWristLeft";
- mJointMap["avatar_mCollarRight"] = "mCollarRight";
- mJointMap["avatar_mShoulderRight"] = "mShoulderRight";
- mJointMap["avatar_mElbowRight"] = "mElbowRight";
- mJointMap["avatar_mWristRight"] = "mWristRight";
- mJointMap["avatar_mHipRight"] = "mHipRight";
- mJointMap["avatar_mKneeRight"] = "mKneeRight";
- mJointMap["avatar_mAnkleRight"] = "mAnkleRight";
- mJointMap["avatar_mFootRight"] = "mFootRight";
- mJointMap["avatar_mToeRight"] = "mToeRight";
- mJointMap["avatar_mHipLeft"] = "mHipLeft";
- mJointMap["avatar_mKneeLeft"] = "mKneeLeft";
- mJointMap["avatar_mAnkleLeft"] = "mAnkleLeft";
- mJointMap["avatar_mFootLeft"] = "mFootLeft";
- mJointMap["avatar_mToeLeft"] = "mToeLeft";
- mJointMap["hip"] = "mPelvis";
- mJointMap["abdomen"] = "mTorso";
- mJointMap["chest"] = "mChest";
- mJointMap["neck"] = "mNeck";
- mJointMap["head"] = "mHead";
- mJointMap["figureHair"] = "mSkull";
- mJointMap["lCollar"] = "mCollarLeft";
- mJointMap["lShldr"] = "mShoulderLeft";
- mJointMap["lForeArm"] = "mElbowLeft";
- mJointMap["lHand"] = "mWristLeft";
- mJointMap["rCollar"] = "mCollarRight";
- mJointMap["rShldr"] = "mShoulderRight";
- mJointMap["rForeArm"] = "mElbowRight";
- mJointMap["rHand"] = "mWristRight";
- mJointMap["rThigh"] = "mHipRight";
- mJointMap["rShin"] = "mKneeRight";
- mJointMap["rFoot"] = "mFootRight";
- mJointMap["lThigh"] = "mHipLeft";
- mJointMap["lShin"] = "mKneeLeft";
- mJointMap["lFoot"] = "mFootLeft";
- if (mPreview)
- {
- //only try to load from slm if viewer is configured to do so and this is the
- //initial model load (not an LoD or physics shape)
- mTrySLM = gSavedSettings.getBOOL("MeshImportUseSLM") && mPreview->mUploadData.empty();
- mPreview->setLoadState(STARTING);
- }
- else
- {
- mTrySLM = false;
- }
- assert_main_thread();
- sActiveLoaderList.push_back(this) ;
- }
- LLModelLoader::~LLModelLoader()
- {
- assert_main_thread();
- sActiveLoaderList.remove(this);
- }
- void stretch_extents(LLModel* model, LLMatrix4a& mat, LLVector4a& min, LLVector4a& max, BOOL& first_transform)
- {
- LLVector4a box[] =
- {
- LLVector4a(-1, 1,-1),
- LLVector4a(-1, 1, 1),
- LLVector4a(-1,-1,-1),
- LLVector4a(-1,-1, 1),
- LLVector4a( 1, 1,-1),
- LLVector4a( 1, 1, 1),
- LLVector4a( 1,-1,-1),
- LLVector4a( 1,-1, 1),
- };
- for (S32 j = 0; j < model->getNumVolumeFaces(); ++j)
- {
- const LLVolumeFace& face = model->getVolumeFace(j);
- LLVector4a center;
- center.setAdd(face.mExtents[0], face.mExtents[1]);
- center.mul(0.5f);
- LLVector4a size;
- size.setSub(face.mExtents[1],face.mExtents[0]);
- size.mul(0.5f);
- for (U32 i = 0; i < 8; i++)
- {
- LLVector4a t;
- t.setMul(size, box[i]);
- t.add(center);
- LLVector4a v;
- mat.affineTransform(t, v);
- if (first_transform)
- {
- first_transform = FALSE;
- min = max = v;
- }
- else
- {
- update_min_max(min, max, v);
- }
- }
- }
- }
- void stretch_extents(LLModel* model, LLMatrix4& mat, LLVector3& min, LLVector3& max, BOOL& first_transform)
- {
- LLVector4a mina, maxa;
- LLMatrix4a mata;
- mata.loadu(mat);
- mina.load3(min.mV);
- maxa.load3(max.mV);
- stretch_extents(model, mata, mina, maxa, first_transform);
- min.set(mina.getF32ptr());
- max.set(maxa.getF32ptr());
- }
- void LLModelLoader::run()
- {
- doLoadModel();
- doOnIdleOneTime(boost::bind(&LLModelLoader::loadModelCallback,this));
- }
- bool LLModelLoader::doLoadModel()
- {
- //first, look for a .slm file of the same name that was modified later
- //than the .dae
- if (mTrySLM)
- {
- std::string filename = mFilename;
-
- std::string::size_type i = filename.rfind(".");
- if (i != std::string::npos)
- {
- filename.replace(i, filename.size()-1, ".slm");
- llstat slm_status;
- if (LLFile::stat(filename, &slm_status) == 0)
- { //slm file exists
- llstat dae_status;
- if (LLFile::stat(mFilename, &dae_status) != 0 ||
- dae_status.st_mtime < slm_status.st_mtime)
- {
- if (loadFromSLM(filename))
- { //slm successfully loaded, if this fails, fall through and
- //try loading from dae
- mLod = -1; //successfully loading from an slm implicitly sets all
- //LoDs
- return true;
- }
- }
- }
- }
- }
- //no suitable slm exists, load from the .dae file
- DAE dae;
- domCOLLADA* dom = dae.open(mFilename);
-
- 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);
-
- daeDocument* doc = dae.getDoc(mFilename);
- if (!doc)
- {
- llwarns << "can't find internal doc" << llendl;
- return false;
- }
-
- daeElement* root = doc->getDomRoot();
- if (!root)
- {
- llwarns << "document has no root" << llendl;
- return false;
- }
-
- //Verify some basic properties of the dae
- //1. Basic validity check on controller
- U32 controllerCount = (int) db->getElementCount( NULL, "controller" );
- bool result = false;
- for ( int i=0; i<controllerCount; ++i )
- {
- domController* pController = NULL;
- db->getElement( (daeElement**) &pController, i , NULL, "controller" );
- result = mPreview->verifyController( pController );
- if (!result)
- {
- setLoadState( ERROR_PARSING );
- return true;
- }
- }
- //get unit scale
- mTransform.setIdentity();
-
- domAsset::domUnit* unit = daeSafeCast<domAsset::domUnit>(root->getDescendant(daeElement::matchType(domAsset::domUnit::ID())));
-
- if (unit)
- {
- F32 meter = unit->getMeter();
- mTransform.mMatrix[0][0] = meter;
- mTransform.mMatrix[1][1] = meter;
- mTransform.mMatrix[2][2] = meter;
- }
-
- //get up axis rotation
- LLMatrix4 rotation;
-
- domUpAxisType up = UPAXISTYPE_Y_UP; // default is Y_UP
- domAsset::domUp_axis* up_axis =
- daeSafeCast<domAsset::domUp_axis>(root->getDescendant(daeElement::matchType(domAsset::domUp_axis::ID())));
-
- if (up_axis)
- {
- up = up_axis->getValue();
- }
-
- if (up == UPAXISTYPE_X_UP)
- {
- rotation.initRotation(0.0f, 90.0f * DEG_TO_RAD, 0.0f);
- }
- else if (up == UPAXISTYPE_Y_UP)
- {
- rotation.initRotation(90.0f * DEG_TO_RAD, 0.0f, 0.0f);
- }
-
- rotation *= mTransform;
- mTransform = rotation;
-
-
- for (daeInt idx = 0; idx < count; ++idx)
- { //build map of domEntities to LLModel
- domMesh* mesh = NULL;
- db->getElement((daeElement**) &mesh, idx, NULL, COLLADA_TYPE_MESH);
-
- if (mesh)
- {
- LLPointer<LLModel> model = LLModel::loadModelFromDomMesh(mesh);
-
- if(model->getStatus() != LLModel::NO_ERRORS)
- {
- setLoadState(ERROR_PARSING + model->getStatus()) ;
- return false; //abort
- }
- if (model.notNull() && validate_model(model))
- {
- mModelList.push_back(model);
- mModel[mesh] = model;
- }
- }
- }
-
- count = db->getElementCount(NULL, COLLADA_TYPE_SKIN);
- for (daeInt idx = 0; idx < count; ++idx)
- { //add skinned meshes as instances
- domSkin* skin = NULL;
- db->getElement((daeElement**) &skin, idx, NULL, COLLADA_TYPE_SKIN);
-
- if (skin)
- {
- domGeometry* geom = daeSafeCast<domGeometry>(skin->getSource().getElement());
-
- if (geom)
- {
- domMesh* mesh = geom->getMesh();
- if (mesh)
- {
- LLModel* model = mModel[mesh];
- if (model)
- {
- LLVector3 mesh_scale_vector;
- LLVector3 mesh_translation_vector;
- model->getNormalizedScaleTranslation(mesh_scale_vector, mesh_translation_vector);
-
- LLMatrix4 normalized_transformation;
- normalized_transformation.setTranslation(mesh_translation_vector);
-
- LLMatrix4 mesh_scale;
- mesh_scale.initScale(mesh_scale_vector);
- mesh_scale *= normalized_transformation;
- normalized_transformation = mesh_scale;
-
- glh::matrix4f inv_mat((F32*) normalized_transformation.mMatrix);
- inv_mat = inv_mat.inverse();
- LLMatrix4 inverse_normalized_transformation(inv_mat.m);
-
- domSkin::domBind_shape_matrix* bind_mat = skin->getBind_shape_matrix();
-
- if (bind_mat)
- { //get bind shape matrix
- domFloat4x4& dom_value = bind_mat->getValue();
-
- LLMeshSkinInfo& skin_info = model->mSkinInfo;
- for (int i = 0; i < 4; i++)
- {
- for(int j = 0; j < 4; j++)
- {
- skin_info.mBindShapeMatrix.mMatrix[i][j] = dom_value[i + j*4];
- }
- }
-
- LLMatrix4 trans = normalized_transformation;
- trans *= skin_info.mBindShapeMatrix;
- skin_info.mBindShapeMatrix = trans;
- }
-
-
- //Some collada setup for accessing the skeleton
- daeElement* pElement = 0;
- dae.getDatabase()->getElement( &pElement, 0, 0, "skeleton" );
-
- //Try to get at the skeletal instance controller
- domInstance_controller::domSkeleton* pSkeleton = daeSafeCast<domInstance_controller::domSkeleton>( pElement );
- bool missingSkeletonOrScene = false;
-
- //If no skeleton, do a breadth-first search to get at specific joints
- bool rootNode = false;
- bool skeletonWithNoRootNode = false;
-
- //Need to test for a skeleton that does not have a root node
- //This occurs when your instance controller does not have an associated scene
- if ( pSkeleton )
- {
- daeElement* pSkeletonRootNode = pSkeleton->getValue().getElement();
- if ( pSkeletonRootNode )
- {
- rootNode = true;
- }
- else
- {
- skeletonWithNoRootNode = true;
- }
- }
- if ( !pSkeleton || !rootNode )
- {
- daeElement* pScene = root->getDescendant("visual_scene");
- if ( !pScene )
- {
- llwarns<<"No visual scene - unable to parse bone offsets "<<llendl;
- missingSkeletonOrScene = true;
- }
- else
- {
- //Get the children at this level
- daeTArray< daeSmartRef<daeElement> > children = pScene->getChildren();
- S32 childCount = children.getCount();
-
- //Process any children that are joints
- //Not all children are joints, some code be ambient lights, cameras, geometry etc..
- for (S32 i = 0; i < childCount; ++i)
- {
- domNode* pNode = daeSafeCast<domNode>(children[i]);
- if ( isNodeAJoint( pNode ) )
- {
- processJointNode( pNode, mJointList );
- }
- }
- }
- }
- else
- //Has Skeleton
- {
- //Get the root node of the skeleton
- daeElement* pSkeletonRootNode = pSkeleton->getValue().getElement();
- if ( pSkeletonRootNode )
- {
- //Once we have the root node - start acccessing it's joint components
- const int jointCnt = mJointMap.size();
- std::map<std::string, std::string> :: const_iterator jointIt = mJointMap.begin();
-
- //Loop over all the possible joints within the .dae - using the allowed joint list in the ctor.
- for ( int i=0; i<jointCnt; ++i, ++jointIt )
- {
- //Build a joint for the resolver to work with
- char str[64]={0};
- sprintf(str,"./%s",(*jointIt).first.c_str() );
- //llwarns<<"Joint "<< str <<llendl;
-
- //Setup the resolver
- daeSIDResolver resolver( p…
Large files files are truncated, but you can click here to view the full file