From ae035a0d66604e25b1277c4fa303aea8d798e719 Mon Sep 17 00:00:00 2001 From: Graham Linden Date: Tue, 22 Apr 2014 08:58:38 -0700 Subject: Modify importer to (optionally) improve debug output, perform name-based LOD association, and handle models with many materials. --- indra/newview/CMakeLists.txt | 2 - indra/newview/app_settings/settings.xml | 22 + indra/newview/llcallbacklist.cpp | 305 ---- indra/newview/llcallbacklist.h | 72 - indra/newview/llfloatermodelpreview.cpp | 2846 ++++++------------------------- indra/newview/llfloatermodelpreview.h | 121 +- indra/newview/llmeshrepository.cpp | 281 ++- indra/newview/llmeshrepository.h | 50 +- 8 files changed, 770 insertions(+), 2929 deletions(-) delete mode 100755 indra/newview/llcallbacklist.cpp delete mode 100755 indra/newview/llcallbacklist.h (limited to 'indra/newview') diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 0bf0152b30..889e26b532 100755 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -132,7 +132,6 @@ set(viewer_SOURCE_FILES llbreadcrumbview.cpp llbrowsernotification.cpp llbuycurrencyhtml.cpp - llcallbacklist.cpp llcallingcard.cpp llcapabilitylistener.cpp llcaphttpsender.cpp @@ -720,7 +719,6 @@ set(viewer_HEADER_FILES llbox.h llbreadcrumbview.h llbuycurrencyhtml.h - llcallbacklist.h llcallingcard.h llcapabilitylistener.h llcapabilityprovider.h diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index de11309394..4343c7f70c 100755 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -2,6 +2,28 @@ + ImporterDebug + + Comment + Enable debug output to more precisely identify sources of import errors. Warning: the output can slow down import on many machines. + Persist + 0 + Type + Integer + Value + 0 + + IMShowTime + + Comment + Enable(disable) timestamp showing in the chat. + Persist + 1 + Type + Boolean + Value + 1 + IMShowTime Comment diff --git a/indra/newview/llcallbacklist.cpp b/indra/newview/llcallbacklist.cpp deleted file mode 100755 index 79ec43dfe9..0000000000 --- a/indra/newview/llcallbacklist.cpp +++ /dev/null @@ -1,305 +0,0 @@ -/** - * @file llcallbacklist.cpp - * @brief A simple list of callback functions to call. - * - * $LicenseInfo:firstyear=2001&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" - -#include "llcallbacklist.h" -#include "lleventtimer.h" - -// Library includes -#include "llerror.h" - - -// -// Globals -// -LLCallbackList gIdleCallbacks; - -// -// Member functions -// - -LLCallbackList::LLCallbackList() -{ - // nothing -} - -LLCallbackList::~LLCallbackList() -{ -} - - -void LLCallbackList::addFunction( callback_t func, void *data) -{ - if (!func) - { - llerrs << "LLCallbackList::addFunction - function is NULL" << llendl; - return; - } - - // only add one callback per func/data pair - callback_pair_t t(func, data); - callback_list_t::iterator iter = std::find(mCallbackList.begin(), mCallbackList.end(), t); - if (iter == mCallbackList.end()) - { - mCallbackList.push_back(t); - } -} - - -BOOL LLCallbackList::containsFunction( callback_t func, void *data) -{ - callback_pair_t t(func, data); - callback_list_t::iterator iter = std::find(mCallbackList.begin(), mCallbackList.end(), t); - if (iter != mCallbackList.end()) - { - return TRUE; - } - else - { - return FALSE; - } -} - - -BOOL LLCallbackList::deleteFunction( callback_t func, void *data) -{ - callback_pair_t t(func, data); - callback_list_t::iterator iter = std::find(mCallbackList.begin(), mCallbackList.end(), t); - if (iter != mCallbackList.end()) - { - mCallbackList.erase(iter); - return TRUE; - } - else - { - return FALSE; - } -} - - -void LLCallbackList::deleteAllFunctions() -{ - mCallbackList.clear(); -} - - -void LLCallbackList::callFunctions() -{ - for (callback_list_t::iterator iter = mCallbackList.begin(); iter != mCallbackList.end(); ) - { - callback_list_t::iterator curiter = iter++; - curiter->first(curiter->second); - } -} - -// Shim class to allow arbitrary boost::bind -// expressions to be run as one-time idle callbacks. -class OnIdleCallbackOneTime -{ -public: - OnIdleCallbackOneTime(nullary_func_t callable): - mCallable(callable) - { - } - static void onIdle(void *data) - { - gIdleCallbacks.deleteFunction(onIdle, data); - OnIdleCallbackOneTime* self = reinterpret_cast(data); - self->call(); - delete self; - } - void call() - { - mCallable(); - } -private: - nullary_func_t mCallable; -}; - -void doOnIdleOneTime(nullary_func_t callable) -{ - OnIdleCallbackOneTime* cb_functor = new OnIdleCallbackOneTime(callable); - gIdleCallbacks.addFunction(&OnIdleCallbackOneTime::onIdle,cb_functor); -} - -// Shim class to allow generic boost functions to be run as -// recurring idle callbacks. Callable should return true when done, -// false to continue getting called. -class OnIdleCallbackRepeating -{ -public: - OnIdleCallbackRepeating(bool_func_t callable): - mCallable(callable) - { - } - // Will keep getting called until the callable returns true. - static void onIdle(void *data) - { - OnIdleCallbackRepeating* self = reinterpret_cast(data); - bool done = self->call(); - if (done) - { - gIdleCallbacks.deleteFunction(onIdle, data); - delete self; - } - } - bool call() - { - return mCallable(); - } -private: - bool_func_t mCallable; -}; - -void doOnIdleRepeating(bool_func_t callable) -{ - OnIdleCallbackRepeating* cb_functor = new OnIdleCallbackRepeating(callable); - gIdleCallbacks.addFunction(&OnIdleCallbackRepeating::onIdle,cb_functor); -} - -class NullaryFuncEventTimer: public LLEventTimer -{ -public: - NullaryFuncEventTimer(nullary_func_t callable, F32 seconds): - LLEventTimer(seconds), - mCallable(callable) - { - } - -private: - BOOL tick() - { - mCallable(); - return TRUE; - } - - nullary_func_t mCallable; -}; - -// Call a given callable once after specified interval. -void doAfterInterval(nullary_func_t callable, F32 seconds) -{ - new NullaryFuncEventTimer(callable, seconds); -} - -class BoolFuncEventTimer: public LLEventTimer -{ -public: - BoolFuncEventTimer(bool_func_t callable, F32 seconds): - LLEventTimer(seconds), - mCallable(callable) - { - } -private: - BOOL tick() - { - return mCallable(); - } - - bool_func_t mCallable; -}; - -// Call a given callable every specified number of seconds, until it returns true. -void doPeriodically(bool_func_t callable, F32 seconds) -{ - new BoolFuncEventTimer(callable, seconds); -} - -#ifdef _DEBUG - -void test1(void *data) -{ - S32 *s32_data = (S32 *)data; - llinfos << "testfunc1 " << *s32_data << llendl; -} - - -void test2(void *data) -{ - S32 *s32_data = (S32 *)data; - llinfos << "testfunc2 " << *s32_data << llendl; -} - - -void -LLCallbackList::test() -{ - S32 a = 1; - S32 b = 2; - LLCallbackList *list = new LLCallbackList; - - llinfos << "Testing LLCallbackList" << llendl; - - if (!list->deleteFunction(NULL)) - { - llinfos << "passed 1" << llendl; - } - else - { - llinfos << "error, removed function from empty list" << llendl; - } - - // llinfos << "This should crash" << llendl; - // list->addFunction(NULL); - - list->addFunction(&test1, &a); - list->addFunction(&test1, &a); - - llinfos << "Expect: test1 1, test1 1" << llendl; - list->callFunctions(); - - list->addFunction(&test1, &b); - list->addFunction(&test2, &b); - - llinfos << "Expect: test1 1, test1 1, test1 2, test2 2" << llendl; - list->callFunctions(); - - if (list->deleteFunction(&test1, &b)) - { - llinfos << "passed 3" << llendl; - } - else - { - llinfos << "error removing function" << llendl; - } - - llinfos << "Expect: test1 1, test1 1, test2 2" << llendl; - list->callFunctions(); - - list->deleteAllFunctions(); - - llinfos << "Expect nothing" << llendl; - list->callFunctions(); - - llinfos << "nothing :-)" << llendl; - - delete list; - - llinfos << "test complete" << llendl; -} - -#endif // _DEBUG diff --git a/indra/newview/llcallbacklist.h b/indra/newview/llcallbacklist.h deleted file mode 100755 index 0516c9cdb4..0000000000 --- a/indra/newview/llcallbacklist.h +++ /dev/null @@ -1,72 +0,0 @@ -/** - * @file llcallbacklist.h - * @brief A simple list of callback functions to call. - * - * $LicenseInfo:firstyear=2001&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$ - */ - -#ifndef LL_LLCALLBACKLIST_H -#define LL_LLCALLBACKLIST_H - -#include "llstl.h" - -class LLCallbackList -{ -public: - typedef void (*callback_t)(void*); - - LLCallbackList(); - ~LLCallbackList(); - - void addFunction( callback_t func, void *data = NULL ); // register a callback, which will be called as func(data) - BOOL containsFunction( callback_t func, void *data = NULL ); // true if list already contains the function/data pair - BOOL deleteFunction( callback_t func, void *data = NULL ); // removes the first instance of this function/data pair from the list, false if not found - void callFunctions(); // calls all functions - void deleteAllFunctions(); - - static void test(); - -protected: - // Use a list so that the callbacks are ordered in case that matters - typedef std::pair callback_pair_t; - typedef std::list callback_list_t; - callback_list_t mCallbackList; -}; - -typedef boost::function nullary_func_t; -typedef boost::function bool_func_t; - -// Call a given callable once in idle loop. -void doOnIdleOneTime(nullary_func_t callable); - -// Repeatedly call a callable in idle loop until it returns true. -void doOnIdleRepeating(bool_func_t callable); - -// Call a given callable once after specified interval. -void doAfterInterval(nullary_func_t callable, F32 seconds); - -// Call a given callable every specified number of seconds, until it returns true. -void doPeriodically(bool_func_t callable, F32 seconds); - -extern LLCallbackList gIdleCallbacks; - -#endif diff --git a/indra/newview/llfloatermodelpreview.cpp b/indra/newview/llfloatermodelpreview.cpp index 855836af7a..01809d38c1 100755 --- a/indra/newview/llfloatermodelpreview.cpp +++ b/indra/newview/llfloatermodelpreview.cpp @@ -26,35 +26,8 @@ #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 "llmodelloader.h" +#include "lldaeloader.h" #include "llfloatermodelpreview.h" @@ -112,16 +85,13 @@ #include "llanimationstates.h" #include "llviewernetwork.h" #include "llviewershadermgr.h" + #include "glod/glod.h" #include - -const S32 SLM_SUPPORTED_VERSION = 3; - //static S32 LLFloaterModelPreview::sUploadAmount = 10; LLFloaterModelPreview* LLFloaterModelPreview::sInstance = NULL; -std::list LLModelLoader::sActiveLoaderList; const S32 PREVIEW_BORDER_WIDTH = 2; const S32 PREVIEW_RESIZE_HANDLE_SIZE = S32(RESIZE_HANDLE_WIDTH * OO_SQRT2) + PREVIEW_BORDER_WIDTH; @@ -207,190 +177,37 @@ 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 - -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) +BOOL stop_gloderror() { + GLuint error = glodGetError(); - for (U32 v = 0; v < face.mNumVertices; v++) - { - if(face.mPositions && !face.mPositions[v].isFinite3()) - { - llwarns << "NaN position data in face found!" << llendl; - return false; - } - - if(face.mNormals && !face.mNormals[v].isFinite3()) - { - llwarns << "NaN normal data in face found!" << llendl; - return false; - } - } - - 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) + if (error != GLOD_NO_ERROR) { - llwarns << "Face has invalid number of indices." << llendl; - return false; + llwarns << "GLOD error detected, cannot generate LOD: " << std::hex << error << llendl; + return TRUE; } - - /*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; + return FALSE; } -bool validate_model(const LLModel* mdl) +LLViewerFetchedTexture* bindMaterialDiffuseTexture(const LLImportMaterial& material) { - if (mdl->getNumVolumeFaces() == 0) - { - llwarns << "Model has no faces!" << llendl; - return false; - } + LLViewerFetchedTexture *texture = LLViewerTextureManager::getFetchedTexture(material.getDiffuseMap(), FTT_DEFAULT, TRUE, LLGLTexture::BOOST_PREVIEW); - for (S32 i = 0; i < mdl->getNumVolumeFaces(); ++i) + if (texture) { - 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))) + if (texture->getDiscardLevel() > -1) { - return false; + gGL.getTexUnit(0)->bind(texture, true); + return texture; } } - 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; + return NULL; } - LLMeshFilePicker::LLMeshFilePicker(LLModelPreview* mp, S32 lod) - : LLFilePickerThread(LLFilePicker::FFLOAD_COLLADA) +: LLFilePickerThread(LLFilePicker::FFLOAD_COLLADA) { mMP = mp; mLOD = lod; @@ -401,6 +218,29 @@ void LLMeshFilePicker::notify(const std::string& filename) mMP->loadModel(mFile, mLOD); } +void FindModel(LLModelLoader::scene& scene, const std::string& name_to_match, LLModel*& baseModelOut, LLMatrix4& matOut) +{ + LLModelLoader::scene::iterator base_iter = scene.begin(); + bool found = false; + while (!found && (base_iter != scene.end())) + { + matOut = base_iter->first; + + LLModelLoader::model_instance_list::iterator base_instance_iter = base_iter->second.begin(); + while (!found && (base_instance_iter != base_iter->second.end())) + { + LLModelInstance& base_instance = *base_instance_iter++; + LLModel* base_model = base_instance.mModel; + + if (base_model && (base_model->mLabel == name_to_match)) + { + baseModelOut = base_model; + return; + } + } + base_iter++; + } +} //----------------------------------------------------------------------------- // LLFloaterModelPreview() @@ -535,16 +375,9 @@ BOOL LLFloaterModelPreview::postBuild() mUploadBtn = getChild("ok_btn"); mCalculateBtn = getChild("calculate_btn"); - if (LLConvexDecomposition::getInstance() != NULL) - { - mCalculateBtn->setClickedCallback(boost::bind(&LLFloaterModelPreview::onClickCalculateBtn, this)); + mCalculateBtn->setClickedCallback(boost::bind(&LLFloaterModelPreview::onClickCalculateBtn, this)); - toggleCalculateButton(true); - } - else - { - mCalculateBtn->setEnabled(false); - } + toggleCalculateButton(true); return TRUE; } @@ -801,7 +634,7 @@ void LLFloaterModelPreview::draw() else if ( mModelPreview->getLoadState() == LLModelLoader::ERROR_PARSING ) { - childSetTextArg("status", "[STATUS]", getString("status_parse_error")); + childSetTextArg("status", "[STATUS]", getString("status_parse_error_dae")); toggleCalculateButton(false); } else @@ -1262,1859 +1095,52 @@ void LLFloaterModelPreview::initDecompControls() LLComboBox* combo_box = getChild(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& 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."<getVersion(); - //0=1.4 - //1=1.4.1 - //2=Currently unsupported, however may work - if (docVersion > 1 ) - { - docVersion = VERSIONTYPE_COUNT; - } - llinfos<<"Dae version "<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; igetElement( (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(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(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 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(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( pElement ); - bool missingSkeletonOrScene = false; - - //If no skeleton, do a breadth-first search to get at specific joints - bool rootNode = 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; - } - - } - if ( !pSkeleton || !rootNode ) - { - daeElement* pScene = root->getDescendant("visual_scene"); - if ( !pScene ) - { - llwarns<<"No visual scene - unable to parse bone offsets "< > 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(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 :: 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( resolver.getElement() ); - if ( pJoint ) - { - //Pull out the translate id and store it in the jointTranslations map - daeSIDResolver jointResolverA( pJoint, "./translate" ); - domTranslate* pTranslateA = daeSafeCast( jointResolverA.getElement() ); - daeSIDResolver jointResolverB( pJoint, "./location" ); - domTranslate* pTranslateB = daeSafeCast( jointResolverB.getElement() ); - - LLMatrix4 workingTransform; - - //Translation via SID - if ( pTranslateA ) - { - extractTranslation( pTranslateA, workingTransform ); - } - else - if ( pTranslateB ) - { - extractTranslation( pTranslateB, workingTransform ); - } - else - { - //Translation via child from element - daeElement* pTranslateElement = getChildFromElement( pJoint, "translate" ); - if ( pTranslateElement && pTranslateElement->typeID() != domTranslate::ID() ) - { - llwarns<< "The found element is not a translate node" <getJoints(); - - domInputLocal_Array& joint_input = joints->getInput_array(); - - for (size_t i = 0; i < joint_input.getCount(); ++i) - { - domInputLocal* input = joint_input.get(i); - xsNMTOKEN semantic = input->getSemantic(); - - if (strcmp(semantic, COMMON_PROFILE_INPUT_JOINT) == 0) - { //found joint source, fill model->mJointMap and model->mSkinInfo.mJointNames - daeElement* elem = input->getSource().getElement(); - - domSource* source = daeSafeCast(elem); - if (source) - { - - - domName_array* names_source = source->getName_array(); - - if (names_source) - { - domListOfNames &names = names_source->getValue(); - - for (size_t j = 0; j < names.getCount(); ++j) - { - std::string name(names.get(j)); - if (mJointMap.find(name) != mJointMap.end()) - { - name = mJointMap[name]; - } - model->mSkinInfo.mJointNames.push_back(name); - model->mSkinInfo.mJointMap[name] = j; - } - } - else - { - domIDREF_array* names_source = source->getIDREF_array(); - if (names_source) - { - xsIDREFS& names = names_source->getValue(); - - for (size_t j = 0; j < names.getCount(); ++j) - { - std::string name(names.get(j).getID()); - if (mJointMap.find(name) != mJointMap.end()) - { - name = mJointMap[name]; - } - model->mSkinInfo.mJointNames.push_back(name); - model->mSkinInfo.mJointMap[name] = j; - } - } - } - } - } - else if (strcmp(semantic, COMMON_PROFILE_INPUT_INV_BIND_MATRIX) == 0) - { //found inv_bind_matrix array, fill model->mInvBindMatrix - domSource* source = daeSafeCast(input->getSource().getElement()); - if (source) - { - domFloat_array* t = source->getFloat_array(); - if (t) - { - domListOfFloats& transform = t->getValue(); - S32 count = transform.getCount()/16; - - for (S32 k = 0; k < count; ++k) - { - LLMatrix4 mat; - - for (int i = 0; i < 4; i++) - { - for(int j = 0; j < 4; j++) - { - mat.mMatrix[i][j] = transform[k*16 + i + j*4]; - } - } - - model->mSkinInfo.mInvBindMatrix.push_back(mat); - } - } - } - } - } - - //Now that we've parsed the joint array, let's determine if we have a full rig - //(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 ); - mPreview->critiqueRigForUploadApplicability( model->mSkinInfo.mJointNames ); - - if ( !missingSkeletonOrScene ) - { - //Set the joint translations on the avatar - if it's a full mapping - //The joints are reset in the dtor - if ( mPreview->getRigWithSceneParity() ) - { - std::map :: const_iterator masterJointIt = mJointMap.begin(); - std::map :: const_iterator masterJointItEnd = mJointMap.end(); - for (;masterJointIt!=masterJointItEnd;++masterJointIt ) - { - std::string lookingForJoint = (*masterJointIt).first.c_str(); - - if ( mJointList.find( lookingForJoint ) != mJointList.end() ) - { - //llinfos<<"joint "<getPreviewAvatar()->getJoint( lookingForJoint ); - if ( pJoint ) - { - pJoint->storeCurrentXform( jointTransform.getTranslation() ); - } - else - { - //Most likely an error in the asset. - llwarns<<"Tried to apply joint position from .dae, but it did not exist in the avatar rig." << llendl; - } - } - } - } - } //missingSkeletonOrScene - - - //We need to construct the alternate bind matrix (which contains the new joint positions) - //in the same order as they were stored in the joint buffer. The joints associated - //with the skeleton are not stored in the same order as they are in the exported joint buffer. - //This remaps the skeletal joints to be in the same order as the joints stored in the model. - std::vector :: const_iterator jointIt = model->mSkinInfo.mJointNames.begin(); - const int jointCnt = model->mSkinInfo.mJointNames.size(); - for ( int i=0; imSkinInfo.mInvBindMatrix[i]; - newInverse.setTranslation( mJointList[lookingForJoint].getTranslation() ); - model->mSkinInfo.mAlternateBindMatrix.push_back( newInverse ); - } - else - { - llwarns<<"Possibly misnamed/missing joint [" <getVertices(); - if (verts) - { - domInputLocal_Array& inputs = verts->getInput_array(); - for (size_t i = 0; i < inputs.getCount() && model->mPosition.empty(); ++i) - { - if (strcmp(inputs[i]->getSemantic(), COMMON_PROFILE_INPUT_POSITION) == 0) - { - domSource* pos_source = daeSafeCast(inputs[i]->getSource().getElement()); - if (pos_source) - { - domFloat_array* pos_array = pos_source->getFloat_array(); - if (pos_array) - { - domListOfFloats& pos = pos_array->getValue(); - - for (size_t j = 0; j < pos.getCount(); j += 3) - { - if (pos.getCount() <= j+2) - { - llerrs << "Invalid position array size." << llendl; - } - - LLVector3 v(pos[j], pos[j+1], pos[j+2]); - - //transform from COLLADA space to volume space - v = v * inverse_normalized_transformation; - - model->mPosition.push_back(v); - } - } - } - } - } - } - - //grab skin weights array - domSkin::domVertex_weights* weights = skin->getVertex_weights(); - if (weights) - { - domInputLocalOffset_Array& inputs = weights->getInput_array(); - domFloat_array* vertex_weights = NULL; - for (size_t i = 0; i < inputs.getCount(); ++i) - { - if (strcmp(inputs[i]->getSemantic(), COMMON_PROFILE_INPUT_WEIGHT) == 0) - { - domSource* weight_source = daeSafeCast(inputs[i]->getSource().getElement()); - if (weight_source) - { - vertex_weights = weight_source->getFloat_array(); - } - } - } - - if (vertex_weights) - { - domListOfFloats& w = vertex_weights->getValue(); - domListOfUInts& vcount = weights->getVcount()->getValue(); - domListOfInts& v = weights->getV()->getValue(); - - U32 c_idx = 0; - for (size_t vc_idx = 0; vc_idx < vcount.getCount(); ++vc_idx) - { //for each vertex - daeUInt count = vcount[vc_idx]; - - //create list of weights that influence this vertex - LLModel::weight_list weight_list; - - for (daeUInt i = 0; i < count; ++i) - { //for each weight - daeInt joint_idx = v[c_idx++]; - daeInt weight_idx = v[c_idx++]; - - if (joint_idx == -1) - { - //ignore bindings to bind_shape_matrix - continue; - } - - F32 weight_value = w[weight_idx]; - - weight_list.push_back(LLModel::JointWeight(joint_idx, weight_value)); - } - - //sort by joint weight - std::sort(weight_list.begin(), weight_list.end(), LLModel::CompareWeightGreater()); - - std::vector wght; - - F32 total = 0.f; - - for (U32 i = 0; i < llmin((U32) 4, (U32) weight_list.size()); ++i) - { //take up to 4 most significant weights - if (weight_list[i].mWeight > 0.f) - { - wght.push_back( weight_list[i] ); - total += weight_list[i].mWeight; - } - } - - F32 scale = 1.f/total; - if (scale != 1.f) - { //normalize weights - for (U32 i = 0; i < wght.size(); ++i) - { - wght[i].mWeight *= scale; - } - } - - model->mSkinWeights[model->mPosition[vc_idx]] = wght; - } - - //add instance to scene for this model - - LLMatrix4 transformation = mTransform; - // adjust the transformation to compensate for mesh normalization - - LLMatrix4 mesh_translation; - mesh_translation.setTranslation(mesh_translation_vector); - mesh_translation *= transformation; - transformation = mesh_translation; - - LLMatrix4 mesh_scale; - mesh_scale.initScale(mesh_scale_vector); - mesh_scale *= transformation; - transformation = mesh_scale; - - std::map 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); - } - } - } - } - } - } - } - - daeElement* scene = root->getDescendant("visual_scene"); - - if (!scene) - { - llwarns << "document has no visual_scene" << llendl; - setLoadState( ERROR_PARSING ); - return true; - } - - setLoadState( DONE ); - - bool badElement = false; - - processElement( scene, badElement ); - - if ( badElement ) - { - setLoadState( ERROR_PARSING ); - } - - return true; -} - -void LLModelLoader::setLoadState(U32 state) -{ - if (mPreview) - { - mPreview->setLoadState(state); - } -} - -bool LLModelLoader::loadFromSLM(const std::string& filename) -{ - //only need to populate mScene with data from slm - llstat stat; - - if (LLFile::stat(filename, &stat)) - { //file does not exist - return false; - } - - S32 file_size = (S32) stat.st_size; - - llifstream ifstream(filename, std::ifstream::in | std::ifstream::binary); - LLSD data; - LLSDSerialize::fromBinary(data, ifstream, file_size); - ifstream.close(); - - //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; - volume_params.setType(LL_PCODE_PROFILE_SQUARE, LL_PCODE_PATH_LINE); - - for (S32 lod = 0; lod < LLModel::NUM_LODS; ++lod) - { - for (U32 i = 0; i < mesh.size(); ++i) - { - std::stringstream str(mesh[i].asString()); - LLPointer loaded_model = new LLModel(volume_params, (F32) lod); - if (loaded_model->loadModel(str)) - { - loaded_model->mLocalID = i; - model[lod].push_back(loaded_model); - - if (lod == LLModel::LOD_HIGH && !loaded_model->mSkinInfo.mJointNames.empty()) - { - //check to see if rig is valid - mPreview->critiqueRigForUploadApplicability( loaded_model->mSkinInfo.mJointNames ); - } - } - } - } - - if (model[LLModel::LOD_HIGH].empty()) - { //failed to load high lod - 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; - - LLSD& instance = data["instance"]; - - for (U32 i = 0; i < instance.size(); ++i) - { - //deserialize instance list - instance_list.push_back(LLModelInstance(instance[i])); - - //match up model instance pointers - S32 idx = instance_list[i].mLocalMeshID; - - for (U32 lod = 0; lod < LLModel::NUM_LODS; ++lod) - { - if (!model[lod].empty()) - { - instance_list[i].mLOD[lod] = model[lod][idx]; - } - } - - instance_list[i].mModel = model[LLModel::LOD_HIGH][idx]; - } - - - //convert instance_list to mScene - mFirstTransform = TRUE; - for (U32 i = 0; i < instance_list.size(); ++i) - { - LLModelInstance& cur_instance = instance_list[i]; - mScene[cur_instance.mTransform].push_back(cur_instance); - stretch_extents(cur_instance.mModel, cur_instance.mTransform, mExtents[0], mExtents[1], mFirstTransform); - } - - setLoadState( DONE ); - - return true; -} - -//static -bool LLModelLoader::isAlive(LLModelLoader* loader) -{ - if(!loader) - { - return false ; - } - - std::list::iterator iter = sActiveLoaderList.begin() ; - for(; iter != sActiveLoaderList.end() && (*iter) != loader; ++iter) ; - - return *iter == loader ; -} - -void LLModelLoader::loadModelCallback() -{ - assert_main_thread(); - - if (mPreview) - { - mPreview->loadModelCallback(mLod); - } - - while (!isStopped()) - { //wait until this thread is stopped before deleting self - apr_sleep(100); - } - - //doubel check if "this" is valid before deleting it, in case it is aborted during running. - if(!isAlive(this)) - { - return ; - } - - //cleanup model loader - if (mPreview) - { - mPreview->mModelLoader = NULL; - } - - delete this; -} -//----------------------------------------------------------------------------- -// buildJointToNodeMappingFromScene() -//----------------------------------------------------------------------------- -void LLModelLoader::buildJointToNodeMappingFromScene( daeElement* pRoot ) -{ - daeElement* pScene = pRoot->getDescendant("visual_scene"); - if ( pScene ) - { - daeTArray< daeSmartRef > children = pScene->getChildren(); - S32 childCount = children.getCount(); - for (S32 i = 0; i < childCount; ++i) - { - domNode* pNode = daeSafeCast(children[i]); - processJointToNodeMapping( pNode ); - } - } -} -//----------------------------------------------------------------------------- -// processJointToNodeMapping() -//----------------------------------------------------------------------------- -void LLModelLoader::processJointToNodeMapping( domNode* pNode ) -{ - if ( isNodeAJoint( pNode ) ) - { - //1.Store the parent - std::string nodeName = pNode->getName(); - if ( !nodeName.empty() ) - { - mJointsFromNode.push_front( pNode->getName() ); - } - //2. Handle the kiddo's - 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 ) - { - processChildJoints( pNode ); - } - else - { - llinfos<<"Node is NULL"< > childOfChild = pParentNode->getChildren(); - S32 childOfChildCount = childOfChild.getCount(); - for (S32 i = 0; i < childOfChildCount; ++i) - { - domNode* pChildNode = daeSafeCast( childOfChild[i] ); - if ( pChildNode ) - { - processJointToNodeMapping( pChildNode ); - } - } -} - -//----------------------------------------------------------------------------- -// critiqueRigForUploadApplicability() -//----------------------------------------------------------------------------- -void LLModelPreview::critiqueRigForUploadApplicability( const std::vector &jointListFromAsset ) -{ - critiqueJointToNodeMappingFromScene(); - - //Determines the following use cases for a rig: - //1. It is suitable for upload with skin weights & joint positions, or - //2. It is suitable for upload as standard av with just skin weights - - bool isJointPositionUploadOK = isRigSuitableForJointPositionUpload( jointListFromAsset ); - bool isRigLegacyOK = isRigLegacy( jointListFromAsset ); - - //It's OK that both could end up being true, both default to false - if ( isJointPositionUploadOK ) - { - setRigValidForJointPositionUpload( true ); - } - - if ( isRigLegacyOK) - { - setLegacyRigValid( true ); - } - -} -//----------------------------------------------------------------------------- -// critiqueJointToNodeMappingFromScene() -//----------------------------------------------------------------------------- -void LLModelPreview::critiqueJointToNodeMappingFromScene( void ) -{ - //Do the actual nodes back the joint listing from the dae? - //if yes then this is a fully rigged asset, otherwise it's just a partial rig - - std::deque::iterator jointsFromNodeIt = mJointsFromNode.begin(); - std::deque::iterator jointsFromNodeEndIt = mJointsFromNode.end(); - bool result = true; - - if ( !mJointsFromNode.empty() ) - { - for ( ;jointsFromNodeIt!=jointsFromNodeEndIt;++jointsFromNodeIt ) - { - std::string name = *jointsFromNodeIt; - if ( mJointTransformMap.find( name ) != mJointTransformMap.end() ) - { - continue; - } - else - { - llinfos<<"critiqueJointToNodeMappingFromScene is missing a: "< &jointListFromAsset ) -{ - //No joints in asset - if ( jointListFromAsset.size() == 0 ) - { - return false; - } - - bool result = false; - - std::deque :: const_iterator masterJointIt = mMasterLegacyJointList.begin(); - std::deque :: const_iterator masterJointEndIt = mMasterLegacyJointList.end(); - - std::vector :: const_iterator modelJointIt = jointListFromAsset.begin(); - std::vector :: const_iterator modelJointItEnd = jointListFromAsset.end(); - - for ( ;masterJointIt!=masterJointEndIt;++masterJointIt ) - { - result = false; - modelJointIt = jointListFromAsset.begin(); - - for ( ;modelJointIt!=modelJointItEnd; ++modelJointIt ) - { - if ( *masterJointIt == *modelJointIt ) - { - result = true; - break; - } - } - if ( !result ) - { - llinfos<<" Asset did not contain the joint (if you're u/l a fully rigged asset w/joint positions - it is required)." << *masterJointIt<< llendl; - break; - } - } - return result; -} -//----------------------------------------------------------------------------- -// isRigSuitableForJointPositionUpload() -//----------------------------------------------------------------------------- -bool LLModelPreview::isRigSuitableForJointPositionUpload( const std::vector &jointListFromAsset ) -{ - bool result = false; - - std::deque :: const_iterator masterJointIt = mMasterJointList.begin(); - std::deque :: const_iterator masterJointEndIt = mMasterJointList.end(); - - std::vector :: const_iterator modelJointIt = jointListFromAsset.begin(); - std::vector :: const_iterator modelJointItEnd = jointListFromAsset.end(); - - for ( ;masterJointIt!=masterJointEndIt;++masterJointIt ) - { - result = false; - modelJointIt = jointListFromAsset.begin(); - - for ( ;modelJointIt!=modelJointItEnd; ++modelJointIt ) - { - if ( *masterJointIt == *modelJointIt ) - { - result = true; - break; - } - } - if ( !result ) - { - llinfos<<" Asset did not contain the joint (if you're u/l a fully rigged asset w/joint positions - it is required)." << *masterJointIt<< llendl; - break; - } - } - return result; -} - - -//called in the main thread -void LLModelLoader::loadTextures() -{ - BOOL is_paused = isPaused() ; - pause() ; //pause the loader - - for(scene::iterator iter = mScene.begin(); iter != mScene.end(); ++iter) - { - for(U32 i = 0 ; i < iter->second.size(); i++) - { - for(std::map::iterator j = iter->second[i].mMaterial.begin(); - j != iter->second[i].mMaterial.end(); ++j) - { - LLImportMaterial& material = j->second; - - if(!material.mDiffuseMapFilename.empty()) - { - material.mDiffuseMap = - LLViewerTextureManager::getFetchedTextureFromUrl("file://" + material.mDiffuseMapFilename, FTT_LOCAL_FILE, TRUE, LLGLTexture::BOOST_PREVIEW); - material.mDiffuseMap->setLoadedCallback(LLModelPreview::textureLoadedCallback, 0, TRUE, FALSE, mPreview, NULL, FALSE); - material.mDiffuseMap->forceToSaveRawImage(0, F32_MAX); - mNumOfFetchingTextures++ ; - } - } - } - } - - if(!is_paused) - { - unpause() ; - } -} - -//----------------------------------------------------------------------------- -// isNodeAJoint() -//----------------------------------------------------------------------------- -bool LLModelLoader::isNodeAJoint( domNode* pNode ) -{ - if ( !pNode ) - { - llinfos<<"Created node is NULL"<getName() == NULL ) - { - llinfos<<"Parsed node has no name "<getId() ) - { - llinfos<<"Parsed node ID: "<getId()<getName() ) != mJointMap.end() ) - { - return true; - } - - return false; -} -//----------------------------------------------------------------------------- -// verifyCount -//----------------------------------------------------------------------------- -bool LLModelPreview::verifyCount( int expected, int result ) -{ - if ( expected != result ) - { - llinfos<< "Error: (expected/got)"<getSkin(); - - if ( pSkin ) - { - xsAnyURI & uri = pSkin->getSource(); - domElement* pElement = uri.getElement(); - - if ( !pElement ) - { - llinfos<<"Can't resolve skin source"<getTypeName(); - if ( stricmp(type_str, "geometry") == 0 ) - { - //Skin is reference directly by geometry and get the vertex count from skin - domSkin::domVertex_weights* pVertexWeights = pSkin->getVertex_weights(); - U32 vertexWeightsCount = pVertexWeights->getCount(); - domGeometry* pGeometry = (domGeometry*) (domElement*) uri.getElement(); - domMesh* pMesh = pGeometry->getMesh(); - - if ( pMesh ) - { - //Get vertex count from geometry - domVertices* pVertices = pMesh->getVertices(); - if ( !pVertices ) - { - llinfos<<"No vertices!"<getInput_array()[0]->getSource(); - domSource* pSource = (domSource*) (domElement*) src.getElement(); - U32 verticesCount = pSource->getTechnique_common()->getAccessor()->getCount(); - result = verifyCount( verticesCount, vertexWeightsCount ); - if ( !result ) - { - return result; - } - } - } - - U32 vcountCount = (U32) pVertexWeights->getVcount()->getValue().getCount(); - result = verifyCount( vcountCount, vertexWeightsCount ); - if ( !result ) - { - return result; - } - - domInputLocalOffset_Array& inputs = pVertexWeights->getInput_array(); - U32 sum = 0; - for (size_t i=0; igetVcount()->getValue()[i]; - } - result = verifyCount( sum * inputs.getCount(), (domInt) pVertexWeights->getV()->getValue().getCount() ); - } - } - - return result; -} - -//----------------------------------------------------------------------------- -// extractTranslation() -//----------------------------------------------------------------------------- -void LLModelLoader::extractTranslation( domTranslate* pTranslate, LLMatrix4& transform ) -{ - domFloat3 jointTrans = pTranslate->getValue(); - LLVector3 singleJointTranslation( jointTrans[0], jointTrans[1], jointTrans[2] ); - transform.setTranslation( singleJointTranslation ); -} -//----------------------------------------------------------------------------- -// extractTranslationViaElement() -//----------------------------------------------------------------------------- -void LLModelLoader::extractTranslationViaElement( daeElement* pTranslateElement, LLMatrix4& transform ) -{ - if ( pTranslateElement ) - { - domTranslate* pTranslateChild = dynamic_cast( 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( 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."<getName() == NULL) - { - llwarns << "nameless node, can't process" << llendl; - return; - } - - //llwarns<<"ProcessJointNode# Node:" <getName()<( jointResolverA.getElement() ); - daeSIDResolver jointResolverB( pNode, "./location" ); - domTranslate* pTranslateB = daeSafeCast( jointResolverB.getElement() ); - - //Translation via SID was successful - if ( pTranslateA ) - { - extractTranslation( pTranslateA, workingTransform ); - } - else - if ( pTranslateB ) - { - extractTranslation( pTranslateB, workingTransform ); - } - else - { - //Translation via child from element - daeElement* pTranslateElement = getChildFromElement( pNode, "translate" ); - if ( !pTranslateElement || pTranslateElement->typeID() != domTranslate::ID() ) - { - //llwarns<< "The found element is not a translate node" <( jointResolver.getElement() ); - if ( pMatrix ) - { - //llinfos<<"A matrix SID was however found!"<getValue(); - for ( int i = 0; i < 4; i++ ) - { - for( int j = 0; j < 4; j++ ) - { - workingTransform.mMatrix[i][j] = domArray[i + j*4]; - } - } - } - else - { - llwarns<< "The found element is not translate or matrix node - most likely a corrupt export!" <getName() ] = workingTransform; - - //2. handle the nodes children - - //Gather and handle the incoming nodes children - daeTArray< daeSmartRef > childOfChild = pNode->getChildren(); - S32 childOfChildCount = childOfChild.getCount(); - - for (S32 i = 0; i < childOfChildCount; ++i) - { - domNode* pChildNode = daeSafeCast( childOfChild[i] ); - if ( pChildNode ) - { - processJointNode( pChildNode, jointTransforms ); - } - } -} -//----------------------------------------------------------------------------- -// getChildFromElement() -//----------------------------------------------------------------------------- -daeElement* LLModelLoader::getChildFromElement( daeElement* pElement, std::string const & name ) -{ - daeElement* pChildOfElement = pElement->getChild( name.c_str() ); - if ( pChildOfElement ) - { - return pChildOfElement; - } - llwarns<< "Could not find a child [" << name << "] for the element: \"" << pElement->getAttribute("id") << "\"" << llendl; - return NULL; -} - -void LLModelLoader::processElement( daeElement* element, bool& badElement ) -{ - LLMatrix4 saved_transform = mTransform; - - domTranslate* translate = daeSafeCast(element); - if (translate) - { - domFloat3 dom_value = translate->getValue(); - - LLMatrix4 translation; - translation.setTranslation(LLVector3(dom_value[0], dom_value[1], dom_value[2])); - - translation *= mTransform; - mTransform = translation; - } - - domRotate* rotate = daeSafeCast(element); - if (rotate) - { - domFloat4 dom_value = rotate->getValue(); - - LLMatrix4 rotation; - rotation.initRotTrans(dom_value[3] * DEG_TO_RAD, LLVector3(dom_value[0], dom_value[1], dom_value[2]), LLVector3(0, 0, 0)); - - rotation *= mTransform; - mTransform = rotation; - } - - domScale* scale = daeSafeCast(element); - if (scale) - { - domFloat3 dom_value = scale->getValue(); - - - LLVector3 scale_vector = LLVector3(dom_value[0], dom_value[1], dom_value[2]); - scale_vector.abs(); // Set all values positive, since we don't currently support mirrored meshes - LLMatrix4 scaling; - scaling.initScale(scale_vector); - - scaling *= mTransform; - mTransform = scaling; - } - - domMatrix* matrix = daeSafeCast(element); - if (matrix) - { - domFloat4x4 dom_value = matrix->getValue(); - - LLMatrix4 matrix_transform; - - for (int i = 0; i < 4; i++) - { - for(int j = 0; j < 4; j++) - { - matrix_transform.mMatrix[i][j] = dom_value[i + j*4]; - } - } - - matrix_transform *= mTransform; - mTransform = matrix_transform; - } - - domInstance_geometry* instance_geo = daeSafeCast(element); - if (instance_geo) - { - domGeometry* geo = daeSafeCast(instance_geo->getUrl().getElement()); - if (geo) - { - domMesh* mesh = daeSafeCast(geo->getDescendant(daeElement::matchType(domMesh::ID()))); - if (mesh) - { - LLModel* model = mModel[mesh]; - if (model) - { - LLMatrix4 transformation = mTransform; - - 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 materials = getMaterials(model, instance_geo); - - // adjust the transformation to compensate for mesh normalization - LLVector3 mesh_scale_vector; - LLVector3 mesh_translation_vector; - model->getNormalizedScaleTranslation(mesh_scale_vector, mesh_translation_vector); - - LLMatrix4 mesh_translation; - mesh_translation.setTranslation(mesh_translation_vector); - mesh_translation *= transformation; - transformation = mesh_translation; - - LLMatrix4 mesh_scale; - mesh_scale.initScale(mesh_scale_vector); - mesh_scale *= transformation; - transformation = mesh_scale; - - std::string label = getElementLabel(instance_geo); - mScene[transformation].push_back(LLModelInstance(model, label, transformation, materials)); - - stretch_extents(model, transformation, mExtents[0], mExtents[1], mFirstTransform); - } - } - } - else - { - llinfos<<"Unable to resolve geometry URL."<(element); - if (instance_node) - { - daeElement* instance = instance_node->getUrl().getElement(); - if (instance) - { - processElement(instance,badElement); - } - } - - //process children - daeTArray< daeSmartRef > children = element->getChildren(); - int childCount = children.getCount(); - for (S32 i = 0; i < childCount; i++) - { - processElement(children[i],badElement); - } - - domNode* node = daeSafeCast(element); - if (node) - { //this element was a node, restore transform before processiing siblings - mTransform = saved_transform; - } -} - -std::map LLModelLoader::getMaterials(LLModel* model, domInstance_geometry* instance_geo) -{ - std::map materials; - for (int i = 0; i < model->mMaterialList.size(); i++) - { - LLImportMaterial import_material; - - domInstance_material* instance_mat = NULL; - - domBind_material::domTechnique_common* technique = - daeSafeCast(instance_geo->getDescendant(daeElement::matchType(domBind_material::domTechnique_common::ID()))); - - if (technique) - { - daeTArray< daeSmartRef > inst_materials = technique->getChildrenByType(); - for (int j = 0; j < inst_materials.getCount(); j++) - { - std::string symbol(inst_materials[j]->getSymbol()); - - if (symbol == model->mMaterialList[i]) // found the binding - { - instance_mat = inst_materials[j]; - } - } - } - - if (instance_mat) - { - domMaterial* material = daeSafeCast(instance_mat->getTarget().getElement()); - if (material) - { - domInstance_effect* instance_effect = - daeSafeCast(material->getDescendant(daeElement::matchType(domInstance_effect::ID()))); - if (instance_effect) - { - domEffect* effect = daeSafeCast(instance_effect->getUrl().getElement()); - if (effect) - { - domProfile_COMMON* profile = - daeSafeCast(effect->getDescendant(daeElement::matchType(domProfile_COMMON::ID()))); - if (profile) - { - import_material = profileToMaterial(profile); - } - } - } - } - } - - import_material.mBinding = model->mMaterialList[i]; - materials[model->mMaterialList[i]] = import_material; - } - - return materials; -} - -LLImportMaterial LLModelLoader::profileToMaterial(domProfile_COMMON* material) -{ - LLImportMaterial mat; - mat.mFullbright = FALSE; - - daeElement* diffuse = material->getDescendant("diffuse"); - if (diffuse) - { - domCommon_color_or_texture_type_complexType::domTexture* texture = - daeSafeCast(diffuse->getDescendant("texture")); - if (texture) - { - domCommon_newparam_type_Array newparams = material->getNewparam_array(); - for (S32 i = 0; i < newparams.getCount(); i++) - { - domFx_surface_common* surface = newparams[i]->getSurface(); - if (surface) - { - domFx_surface_init_common* init = surface->getFx_surface_init_common(); - if (init) - { - domFx_surface_init_from_common_Array init_from = init->getInit_from_array(); + //llinfos << param[i].mDetails.mEnumValues.mEnumsArray[k].mValue + // << " - " << param[i].mDetails.mEnumValues.mEnumsArray[k].mName << llendl; - if (init_from.getCount() > i) - { - domImage* image = daeSafeCast(init_from[i]->getValue().getElement()); - if (image) - { - // we only support init_from now - embedded data will come later - domImage::domInit_from* init = image->getInit_from(); - if (init) - { - mat.mDiffuseMapFilename = cdom::uriToNativePath(init->getValue().str()); - mat.mDiffuseMapLabel = getElementLabel(material); - } - } - } + 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]); } - } - } - - domCommon_color_or_texture_type_complexType::domColor* color = - daeSafeCast(diffuse->getDescendant("color")); - if (color) - { - domFx_color_common domfx_color = color->getValue(); - LLColor4 value = LLColor4(domfx_color[0], domfx_color[1], domfx_color[2], domfx_color[3]); - mat.mDiffuseColor = value; - } - } - daeElement* emission = material->getDescendant("emission"); - if (emission) - { - LLColor4 emission_color = getDaeColor(emission); - if (((emission_color[0] + emission_color[1] + emission_color[2]) / 3.0) > 0.25) - { - mat.mFullbright = TRUE; + //llinfos << "----" << llendl; + } + //llinfos << "-----------------------------" << llendl; } } - return mat; + childSetCommitCallback("physics_explode", LLFloaterModelPreview::onExplodeCommit, this); } -// try to get a decent label for this element -std::string LLModelLoader::getElementLabel(daeElement *element) +void LLFloaterModelPreview::createSmoothComboBox(LLComboBox* combo_box, float min, float max) { - // if we have a name attribute, use it - std::string name = element->getAttribute("name"); - if (name.length()) - { - return name; - } + float delta = (max - min) / SMOOTH_VALUES_NUMBER; + int ilabel = 0; - // if we have an ID attribute, use it - if (element->getID()) - { - return std::string(element->getID()); - } + combo_box->add("0 (none)", ADD_BOTTOM, true); - // if we have a parent, use it - daeElement* parent = element->getParent(); - if (parent) + for(float value = min + delta; value < max; value += delta) { - // if parent has a name, use it - std::string name = parent->getAttribute("name"); - if (name.length()) - { - return name; - } - - // if parent has an ID, use it - if (parent->getID()) - { - return std::string(parent->getID()); - } + std::string label = (++ilabel == SMOOTH_VALUES_NUMBER) ? "10 (max)" : llformat("%.1d", ilabel); + combo_box->add(label, value, ADD_BOTTOM, true); } - // try to use our type - daeString element_name = element->getElementName(); - if (element_name) - { - return std::string(element_name); - } - // if all else fails, use "object" - return std::string("object"); } -LLColor4 LLModelLoader::getDaeColor(daeElement* element) +//----------------------------------------------------------------------------- +// onMouseCaptureLost() +//----------------------------------------------------------------------------- +// static +void LLFloaterModelPreview::onMouseCaptureLostModelPreview(LLMouseHandler* handler) { - LLColor4 value; - domCommon_color_or_texture_type_complexType::domColor* color = - daeSafeCast(element->getDescendant("color")); - if (color) - { - domFx_color_common domfx_color = color->getValue(); - value = LLColor4(domfx_color[0], domfx_color[1], domfx_color[2], domfx_color[3]); - } - - return value; + gViewerWindow->showCursor(); } //----------------------------------------------------------------------------- @@ -3171,51 +1197,20 @@ LLModelPreview::LLModelPreview(S32 width, S32 height, LLFloater* fmp) glodInit(); - //move into joint mapper class - //1. joints for joint offset verification - mMasterJointList.push_front("mPelvis"); - mMasterJointList.push_front("mTorso"); - mMasterJointList.push_front("mChest"); - mMasterJointList.push_front("mNeck"); - mMasterJointList.push_front("mHead"); - mMasterJointList.push_front("mCollarLeft"); - mMasterJointList.push_front("mShoulderLeft"); - mMasterJointList.push_front("mElbowLeft"); - mMasterJointList.push_front("mWristLeft"); - mMasterJointList.push_front("mCollarRight"); - mMasterJointList.push_front("mShoulderRight"); - mMasterJointList.push_front("mElbowRight"); - mMasterJointList.push_front("mWristRight"); - mMasterJointList.push_front("mHipRight"); - mMasterJointList.push_front("mKneeRight"); - mMasterJointList.push_front("mFootRight"); - mMasterJointList.push_front("mHipLeft"); - mMasterJointList.push_front("mKneeLeft"); - mMasterJointList.push_front("mFootLeft"); - //2. legacy joint list - used to verify rigs that will not be using joint offsets - mMasterLegacyJointList.push_front("mPelvis"); - mMasterLegacyJointList.push_front("mTorso"); - mMasterLegacyJointList.push_front("mChest"); - mMasterLegacyJointList.push_front("mNeck"); - mMasterLegacyJointList.push_front("mHead"); - mMasterLegacyJointList.push_front("mHipRight"); - mMasterLegacyJointList.push_front("mKneeRight"); - mMasterLegacyJointList.push_front("mFootRight"); - mMasterLegacyJointList.push_front("mHipLeft"); - mMasterLegacyJointList.push_front("mKneeLeft"); - mMasterLegacyJointList.push_front("mFootLeft"); - createPreviewAvatar(); } LLModelPreview::~LLModelPreview() { - if (mModelLoader) - { - mModelLoader->mPreview = NULL; - mModelLoader = NULL; - } - //*HACK : *TODO : turn this back on when we understand why this crashes + // glod apparently has internal mem alignment issues that are angering + // the heap-check code in windows, these should be hunted down in that + // TP code, if possible + // + // kernel32.dll!HeapFree() + 0x14 bytes + // msvcr100.dll!free(void * pBlock) Line 51 C + // glod.dll!glodGetGroupParameteriv() + 0x119 bytes + // glod.dll!glodShutdown() + 0x77 bytes + // //glodShutdown(); } @@ -3281,7 +1276,9 @@ U32 LLModelPreview::calcResourceCost() decomp, mFMP->childGetValue("upload_skin").asBoolean(), mFMP->childGetValue("upload_joints").asBoolean(), - TRUE); + TRUE, + FALSE, + instance.mModel->mSubmodelID); num_hulls += decomp.mHull.size(); for (U32 i = 0; i < decomp.mHull.size(); ++i) @@ -3348,29 +1345,9 @@ void LLModelPreview::rebuildUploadData() F32 max_scale = 0.f; - //reorder materials to match mBaseModel - 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 ) ) - { - setLoadState( LLModelLoader::ERROR_MATERIALS ); - mFMP->childDisable( "calculate_btn" ); - } - } - } - } - for (LLModelLoader::scene::iterator iter = mBaseScene.begin(); iter != mBaseScene.end(); ++iter) { //for each transform in scene - LLMatrix4 mat = iter->first; + LLMatrix4 mat = iter->first; // compute position LLVector3 position = LLVector3(0, 0, 0) * mat; @@ -3387,41 +1364,176 @@ void LLModelPreview::rebuildUploadData() mat *= scale_mat; - for (LLModelLoader::model_instance_list::iterator model_iter = iter->second.begin(); model_iter != iter->second.end(); ++model_iter) - { //for each instance with said transform applied - LLModelInstance instance = *model_iter; + for (LLModelLoader::model_instance_list::iterator model_iter = iter->second.begin(); model_iter != iter->second.end();) + { //for each instance with said transform applied + LLModelInstance instance = *model_iter++; LLModel* base_model = instance.mModel; - if (base_model) + if (base_model && !requested_name.empty()) { base_model->mRequestedLabel = requested_name; base_model->mMetric = metric; } - S32 idx = 0; - for (idx = 0; idx < mBaseModel.size(); ++idx) - { //find reference instance for this model - if (mBaseModel[idx] == base_model) - { - break; - } + for (int i = LLModel::NUM_LODS - 1; i >= LLModel::LOD_IMPOSTOR; i--) + { // Fill LOD slots by finding matching meshes by label with name extensions + // in the appropriate scene for each LOD. This fixes all kinds of issues + // where the indexed method below fails in spectacular fashion. + // If you don't take the time to name your LOD and PHYS meshes + // with the name of their corresponding mesh in the HIGH LOD, + // then the indexed method will be attempted below. + + LLModel* lod_model = NULL; + LLMatrix4 transform; + + std::string name_to_match = instance.mLabel; + llassert(!name_to_match.empty()); + + switch (i) + { + case LLModel::LOD_IMPOSTOR: name_to_match += "_LOD0"; break; + case LLModel::LOD_LOW: name_to_match += "_LOD1"; break; + case LLModel::LOD_MEDIUM: name_to_match += "_LOD2"; break; + case LLModel::LOD_PHYSICS: name_to_match += "_PHYS"; break; + case LLModel::LOD_HIGH: break; + } + + FindModel(mScene[i], name_to_match, lod_model, transform); + + S32 importerDebug = gSavedSettings.getS32("ImporterDebug"); + + // Fall back to old method of index-based association if + // we could not find a match based on the mesh names + // + if (lod_model) + { + + if (i == LLModel::LOD_PHYSICS) + { + if (importerDebug > 0) + { + llinfos << "Assigning collision for " << instance.mLabel << " to match " << lod_model->mLabel << llendl; + } + instance.mLOD[i] = lod_model; + } + else + { + if (importerDebug > 0) + { + llinfos << "Assigning LOD" << i << " for " << instance.mLabel << " to found match " << lod_model->mLabel << llendl; + } + instance.mLOD[i] = lod_model; + } + } + else + { + int searchLOD = (i > LLModel::LOD_HIGH) ? LLModel::LOD_HIGH : i; + while ((searchLOD <= LLModel::LOD_HIGH) && !lod_model) + { + std::string name_to_match = instance.mLabel; + llassert(!name_to_match.empty()); + + switch (searchLOD) + { + case LLModel::LOD_IMPOSTOR: name_to_match += "_LOD0"; break; + case LLModel::LOD_LOW: name_to_match += "_LOD1"; break; + case LLModel::LOD_MEDIUM: name_to_match += "_LOD2"; break; + case LLModel::LOD_PHYSICS: name_to_match += "_PHYS"; break; + case LLModel::LOD_HIGH: break; + } + + // See if we can find an appropriately named model in LOD 'searchLOD' + // + FindModel(mScene[searchLOD], name_to_match, lod_model, transform); + searchLOD++; + } + + // Fall back to old method of index-based association if + // we could not find a match based on the mesh names at all. + // + if (lod_model) + { + if (i == LLModel::LOD_PHYSICS) + { + if (importerDebug > 0) + { + llinfos << "Falling back collision for " << instance.mLabel << " to " << lod_model->mLabel << llendl; + } + instance.mLOD[i] = lod_model; + } + else + { + if (importerDebug > 0) + { + llinfos << "Falling back LOD" << i << " for " << instance.mLabel << " to found " << lod_model->mLabel << llendl; + } + instance.mLOD[i] = lod_model; + } + } + else + { + S32 idx = 0; + for (idx = 0; idx < mBaseModel.size(); ++idx) + { //find reference instance for this model + if (mBaseModel[idx] == base_model) + { + if (importerDebug > 0) + { + llinfos << "Falling back to model index " << idx << " for LOD " << i << " of " << instance.mLabel << llendl; + } + break; + } + } + + // If the model list for the current LOD includes that index... + // + if (mModel[i].size() > idx) + { + // Assign that index from the model list for our LOD as the LOD model for this instance + // + lod_model = mModel[i][idx]; + instance.mLOD[i] = lod_model; + if (i == LLModel::LOD_PHYSICS) + { + if (importerDebug > 0) + { + llinfos << "Indexed fallback to model index " << idx << ": LOD " << i << " named " << lod_model->mLabel << " for collision for " << instance.mLabel << llendl; + } + } + else + { + if (importerDebug > 0) + { + llinfos << "Indexed fallback to model index " << idx << " LOD " << i << " named " << lod_model->mLabel << " for LOD " << i << " for " << instance.mLabel << llendl; + } + } + } + else + { + if (importerDebug > 0) + { + llinfos << "List of models for LOD " << i << " did not include index " << idx << llendl; + } + } + } + } } - 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; - } + LLModel* high_lod_model = instance.mLOD[LLModel::LOD_HIGH]; + llassert(high_lod_model); + + for (U32 i = 0; i < LLModel::NUM_LODS-1; i++) + { + int refFaceCnt = 0; + int modelFaceCnt = 0; + llassert(instance.mLOD[i]); + if (instance.mLOD[i] && !instance.mLOD[i]->matchMaterialOrder(high_lod_model, refFaceCnt, modelFaceCnt ) ) + { + setLoadState( LLModelLoader::ERROR_MATERIALS ); + mFMP->childDisable( "calculate_btn" ); } - } + } instance.mTransform = mat; mUploadData.push_back(instance); } @@ -3493,7 +1605,6 @@ void LLModelPreview::saveUploadData(const std::string& filename, bool save_skinw meshes.insert(instance.mModel); std::stringstream str; - LLModel::Decomposition& decomp = instance.mLOD[LLModel::LOD_PHYSICS].notNull() ? instance.mLOD[LLModel::LOD_PHYSICS]->mPhysics : @@ -3506,8 +1617,8 @@ 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, FALSE, TRUE); - + save_skinweights, save_joint_positions, + FALSE, TRUE, instance.mModel->mSubmodelID); data["mesh"][instance.mModel->mLocalID] = str.str(); } @@ -3575,7 +1686,16 @@ void LLModelPreview::loadModel(std::string filename, S32 lod, bool force_disable clearGLODGroup(); } - mModelLoader = new LLModelLoader(filename, lod, this, mJointTransformMap, mJointsFromNode ); + mModelLoader = new LLDAELoader( + filename, + lod, + &LLModelPreview::loadedCallback, + &LLModelPreview::lookupJointByName, + &LLModelPreview::loadTextures, + &LLModelPreview::stateChangedCallback, + this, + mJointTransformMap, + mJointsFromNode ); if (force_disable_slm) { @@ -3683,9 +1803,15 @@ void LLModelPreview::loadModelCallback(S32 lod) if(getLoadState() >= LLModelLoader::ERROR_PARSING) { mLoading = false ; + mModelLoader = NULL; return ; } + // Copy determinations about rig so UI will reflect them + // + setRigValidForJointPositionUpload(mModelLoader->isRigValidForJointPositionUpload()); + setLegacyRigValid(mModelLoader->isLegacyRigValid()); + mModelLoader->loadTextures() ; if (lod == -1) @@ -3720,6 +1846,11 @@ void LLModelPreview::loadModelCallback(S32 lod) //override displayed model with current LoD list_iter->mModel = list_iter->mLOD[lod]; + if (!list_iter->mModel) + { + continue; + } + //add current model to current LoD's model list (LLModel::mLocalID makes a good vector index) S32 idx = list_iter->mModel->mLocalID; @@ -3728,7 +1859,7 @@ void LLModelPreview::loadModelCallback(S32 lod) mModel[lod].resize(idx+1); } - mModel[lod][idx] = list_iter->mModel; + mModel[lod][idx] = list_iter->mModel; if (!list_iter->mModel->mSkinWeights.empty()) { skin_weights = true; @@ -3817,6 +1948,8 @@ void LLModelPreview::loadModelCallback(S32 lod) refresh(); mModelLoadedSignal(); + + mModelLoader = NULL; } void LLModelPreview::resetPreviewTarget() @@ -4104,6 +2237,19 @@ void LLModelPreview::genLODs(S32 which_lod, U32 decimation, bool enforce_tri_lim volume_params.setType(LL_PCODE_PROFILE_SQUARE, LL_PCODE_PATH_LINE); mModel[lod][mdl_idx] = new LLModel(volume_params, 0.f); + std::string name = base->mLabel; + + switch (lod) + { + case LLModel::LOD_IMPOSTOR: name += "_LOD0"; break; + case LLModel::LOD_LOW: name += "_LOD1"; break; + case LLModel::LOD_MEDIUM: name += "_LOD2"; break; + case LLModel::LOD_PHYSICS: name += "_PHYS"; break; + case LLModel::LOD_HIGH: break; + } + + mModel[lod][mdl_idx]->mLabel = name; + GLint* sizes = new GLint[patch_count*2]; glodGetObjectParameteriv(mObject[base], GLOD_PATCH_SIZES, sizes); stop_gloderror(); @@ -4216,17 +2362,6 @@ void LLModelPreview::genLODs(S32 which_lod, U32 decimation, bool enforce_tri_lim { shader->bind(); } - - /*if (which_lod == -1 && mScene[LLModel::LOD_PHYSICS].empty()) - { //build physics scene - mScene[LLModel::LOD_PHYSICS] = mScene[LLModel::LOD_LOW]; - mModel[LLModel::LOD_PHYSICS] = mModel[LLModel::LOD_LOW]; - - for (U32 i = 1; i < mModel[LLModel::LOD_PHYSICS].size(); ++i) - { - mPhysicsQ.push(mModel[LLModel::LOD_PHYSICS][i]); - } - }*/ } void LLModelPreview::updateStatusMessages() @@ -4243,43 +2378,88 @@ void LLModelPreview::updateStatusMessages() S32 total_verts[LLModel::NUM_LODS]; S32 total_submeshes[LLModel::NUM_LODS]; - for (S32 lod = 0; lod < LLModel::NUM_LODS; ++lod) + for (U32 i = 0; i < LLModel::NUM_LODS-1; i++) + { + total_tris[i] = 0; + total_verts[i] = 0; + total_submeshes[i] = 0; + } + + for (LLMeshUploadThread::instance_list::iterator iter = mUploadData.begin(); iter != mUploadData.end(); ++iter) { - //initialize total for this lod to 0 - total_tris[lod] = total_verts[lod] = total_submeshes[lod] = 0; + LLModelInstance& instance = *iter; + + LLModel* model_high_lod = instance.mLOD[LLModel::LOD_HIGH]; + llassert(model_high_lod); - for (LLModelLoader::scene::iterator iter = mScene[lod].begin(), endIter = mScene[lod].end(); iter != endIter; ++iter) + for (U32 i = 0; i < LLModel::NUM_LODS-1; i++) { - for (LLModelLoader::model_instance_list::iterator instance = iter->second.begin(), end_instance = iter->second.end(); instance != end_instance; ++instance) - { - LLModel* model = instance->mModel; - if (model) - { - //for each model in the lod - S32 cur_tris = 0; - S32 cur_verts = 0; - S32 cur_submeshes = model->getNumVolumeFaces(); + LLModel* lod_model = instance.mLOD[i]; + llassert(lod_model); + if (!lod_model) + { + setLoadState( LLModelLoader::ERROR_MATERIALS ); + mFMP->childDisable( "calculate_btn" ); + } - for (S32 j = 0; j < cur_submeshes; ++j) - { //for each submesh (face), add triangles and vertices to current total - const LLVolumeFace& face = model->getVolumeFace(j); - cur_tris += face.mNumIndices/3; - cur_verts += face.mNumVertices; - } + int refFaceCnt = 0; + int modelFaceCnt = 0; - //add this model to the lod total - total_tris[lod] += cur_tris; - total_verts[lod] += cur_verts; - total_submeshes[lod] += cur_submeshes; + if (!lod_model->matchMaterialOrder(model_high_lod, refFaceCnt, modelFaceCnt ) ) + { + setLoadState( LLModelLoader::ERROR_MATERIALS ); + mFMP->childDisable( "calculate_btn" ); + } + + if (lod_model) + { + //for each model in the lod + S32 cur_tris = 0; + S32 cur_verts = 0; + S32 cur_submeshes = lod_model->getNumVolumeFaces(); - //store this model's counts to asset data - tris[lod].push_back(cur_tris); - verts[lod].push_back(cur_verts); - submeshes[lod].push_back(cur_submeshes); + for (S32 j = 0; j < cur_submeshes; ++j) + { //for each submesh (face), add triangles and vertices to current total + const LLVolumeFace& face = lod_model->getVolumeFace(j); + cur_tris += face.mNumIndices/3; + cur_verts += face.mNumVertices; } + + std::string instance_name = instance.mLabel; + + S32 importerDebug = gSavedSettings.getS32("ImporterDebug"); + if (importerDebug > 0) + { + // Useful for debugging generalized complaints below about total submeshes which don't have enough + // context to address exactly what needs to be fixed to move towards compliance with the rules. + // + llinfos << "Instance " << lod_model->mLabel << " LOD " << i << " Verts: " << cur_verts << llendl; + llinfos << "Instance " << lod_model->mLabel << " LOD " << i << " Tris: " << cur_tris << llendl; + llinfos << "Instance " << lod_model->mLabel << " LOD " << i << " Faces: " << cur_submeshes << llendl; + + if (importerDebug > 1) + { + LLModel::material_list::iterator mat_iter = lod_model->mMaterialList.begin(); + while (mat_iter != lod_model->mMaterialList.end()) + { + llinfos << "Instance " << lod_model->mLabel << " LOD " << i << " Material " << *(mat_iter) << llendl; + mat_iter++; + } + } + } + + //add this model to the lod total + total_tris[i] += cur_tris; + total_verts[i] += cur_verts; + total_submeshes[i] += cur_submeshes; + + //store this model's counts to asset data + tris[i].push_back(cur_tris); + verts[i].push_back(cur_verts); + submeshes[i].push_back(cur_submeshes); } } - } + } if (mMaxTriangleLimit == 0) { @@ -4293,28 +2473,36 @@ void LLModelPreview::updateStatusMessages() const LLVector4a scale(0.5f); for (U32 i = 0; i < mModel[lod].size() && !has_degenerate; ++i) { //for each model in the lod - if (mModel[lod][i]->mPhysics.mHull.empty()) + if (mModel[lod][i] && mModel[lod][i]->mPhysics.mHull.empty()) { //no decomp exists S32 cur_submeshes = mModel[lod][i]->getNumVolumeFaces(); for (S32 j = 0; j < cur_submeshes && !has_degenerate; ++j) { //for each submesh (face), add triangles and vertices to current total - const LLVolumeFace& face = mModel[lod][i]->getVolumeFace(j); - for (S32 k = 0; k < face.mNumIndices && !has_degenerate; ) + LLVolumeFace& face = mModel[lod][i]->getVolumeFace(j); + for (S32 k = 0; (k < face.mNumIndices) && !has_degenerate; ) { - LLVector4a v1; v1.setMul(face.mPositions[face.mIndices[k++]], scale); - LLVector4a v2; v2.setMul(face.mPositions[face.mIndices[k++]], scale); - LLVector4a v3; v3.setMul(face.mPositions[face.mIndices[k++]], scale); + U16 index_a = face.mIndices[k+0]; + U16 index_b = face.mIndices[k+1]; + U16 index_c = face.mIndices[k+2]; + + LLVector4a v1; v1.setMul(face.mPositions[index_a], scale); + LLVector4a v2; v2.setMul(face.mPositions[index_b], scale); + LLVector4a v3; v3.setMul(face.mPositions[index_c], scale); if (ll_is_degenerate(v1,v2,v3)) { has_degenerate = true; } + else + { + k += 3; + } } } } } } - + mFMP->childSetTextArg("submeshes_info", "[SUBMESHES]", llformat("%d", total_submeshes[LLModel::LOD_HIGH])); std::string mesh_status_na = mFMP->getString("mesh_status_na"); @@ -4417,13 +2605,16 @@ void LLModelPreview::updateStatusMessages() { LLModel* mdl = mModel[LLModel::LOD_PHYSICS][i]; - for (U32 j = 0; upload_ok && j < mdl->mPhysics.mHull.size(); ++j) + if (mdl) { - if (mdl->mPhysics.mHull[j].size() > 256) + for (U32 j = 0; upload_ok && j < mdl->mPhysics.mHull.size(); ++j) { - upload_ok = false; + if (mdl->mPhysics.mHull[j].size() > 256) + { + upload_ok = false; + } } - } + } } bool errorStateFromLoader = getLoadState() >= LLModelLoader::ERROR_PARSING ? true : false; @@ -4939,6 +3130,58 @@ void LLModelPreview::createPreviewAvatar( void ) } } +void LLModelPreview::loadedCallback( + LLModelLoader::scene& scene, + LLModelLoader::model_list& model_list, + S32 lod, + void* opaque) +{ + LLModelPreview* pPreview = static_cast< LLModelPreview* >(opaque); + if (pPreview) + { + pPreview->loadModelCallback(lod); + } +} + +void LLModelPreview::stateChangedCallback(U32 state,void* opaque) +{ + LLModelPreview* pPreview = static_cast< LLModelPreview* >(opaque); + if (pPreview) + { + pPreview->setLoadState(state); + } +} + +LLJoint* LLModelPreview::lookupJointByName(const std::string& str, void* opaque) +{ + LLModelPreview* pPreview = static_cast< LLModelPreview* >(opaque); + if (pPreview) + { + return pPreview->getPreviewAvatar()->getJoint(str); + } + return NULL; +} + +U32 LLModelPreview::loadTextures(LLImportMaterial& material,void* opaque) +{ + (void)opaque; + + if (material.mDiffuseMapFilename.size()) + { + material.mOpaqueData = new LLPointer< LLViewerFetchedTexture >; + LLPointer< LLViewerFetchedTexture >& tex = (*reinterpret_cast< LLPointer< LLViewerFetchedTexture > * >(material.mOpaqueData)); + + tex = LLViewerTextureManager::getFetchedTextureFromUrl("file://" + material.mDiffuseMapFilename, FTT_LOCAL_FILE, TRUE, LLGLTexture::BOOST_PREVIEW); + tex->setLoadedCallback(LLModelPreview::textureLoadedCallback, 0, TRUE, FALSE, opaque, NULL, FALSE); + tex->forceToSaveRawImage(0, F32_MAX); + material.setDiffuseMap(tex->getID()); // record tex ID + return 1; + } + + material.mOpaqueData = NULL; + return 0; +} + void LLModelPreview::addEmptyFace( LLModel* pTarget ) { U32 type_mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_TEXCOORD0; @@ -5181,24 +3424,6 @@ 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); @@ -5212,62 +3437,61 @@ BOOL LLModelPreview::render() LLModel* model = instance.mLOD[mPreviewLOD]; - if (!model) - { - continue; - } + if (!model) + { + continue; + } - gGL.pushMatrix(); - LLMatrix4 mat = instance.mTransform; + gGL.pushMatrix(); + LLMatrix4 mat = instance.mTransform; - gGL.multMatrix((GLfloat*) mat.mMatrix); + gGL.multMatrix((GLfloat*) mat.mMatrix); - for (U32 i = 0; i < mVertexBuffer[mPreviewLOD][model].size(); ++i) - { - LLVertexBuffer* buffer = mVertexBuffer[mPreviewLOD][model][i]; + for (U32 i = 0; i < mVertexBuffer[mPreviewLOD][model].size(); ++i) + { + LLVertexBuffer* buffer = mVertexBuffer[mPreviewLOD][model][i]; - buffer->setBuffer(type_mask & buffer->getTypeMask()); + buffer->setBuffer(type_mask & buffer->getTypeMask()); - if (textures) - { - int materialCnt = instance.mModel->mMaterialList.size(); - if ( i < materialCnt ) + if (textures) { - const std::string& binding = instance.mModel->mMaterialList[i]; - const LLImportMaterial& material = instance.mMaterial[binding]; + int materialCnt = instance.mModel->mMaterialList.size(); + if ( i < materialCnt ) + { + const std::string& binding = instance.mModel->mMaterialList[i]; + const LLImportMaterial& material = instance.mMaterial[binding]; - gGL.diffuseColor4fv(material.mDiffuseColor.mV); + gGL.diffuseColor4fv(material.mDiffuseColor.mV); - if (material.mDiffuseMap.notNull()) - { - if (material.mDiffuseMap->getDiscardLevel() > -1) + // Find the tex for this material, bind it, and add it to our set + // + LLViewerFetchedTexture* tex = bindMaterialDiffuseTexture(material); + if (tex) { - gGL.getTexUnit(0)->bind(material.mDiffuseMap, true); - mTextureSet.insert(material.mDiffuseMap.get()); + mTextureSet.insert(tex); } } } - } - else - { - gGL.diffuseColor4f(1,1,1,1); - } - - buffer->drawRange(LLRender::TRIANGLES, 0, buffer->getNumVerts()-1, buffer->getNumIndices(), 0); - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - gGL.diffuseColor3f(0.4f, 0.4f, 0.4f); + else + { + gGL.diffuseColor4f(1,1,1,1); + } - if (edges) - { - glLineWidth(3.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); + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + gGL.diffuseColor3f(0.4f, 0.4f, 0.4f); + + if (edges) + { + glLineWidth(3.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); + } } + gGL.popMatrix(); } - gGL.popMatrix(); - } if (physics) { @@ -5295,97 +3519,97 @@ BOOL LLModelPreview::render() LLModel* model = instance.mLOD[LLModel::LOD_PHYSICS]; - if (!model) - { - continue; - } + if (!model) + { + continue; + } - gGL.pushMatrix(); - LLMatrix4 mat = instance.mTransform; + gGL.pushMatrix(); + LLMatrix4 mat = instance.mTransform; gGL.multMatrix((GLfloat*) mat.mMatrix); - bool render_mesh = true; + bool render_mesh = true; - LLPhysicsDecomp* decomp = gMeshRepo.mDecompThread; - if (decomp) - { - LLMutexLock(decomp->mMutex); + LLPhysicsDecomp* decomp = gMeshRepo.mDecompThread; + if (decomp) + { + LLMutexLock(decomp->mMutex); - LLModel::Decomposition& physics = model->mPhysics; + LLModel::Decomposition& physics = model->mPhysics; - if (!physics.mHull.empty()) - { - render_mesh = false; + if (!physics.mHull.empty()) + { + render_mesh = false; - if (physics.mMesh.empty()) - { //build vertex buffer for physics mesh - gMeshRepo.buildPhysicsMesh(physics); - } + 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 hull_colors; + static std::vector hull_colors; - if (i+1 >= hull_colors.size()) - { - hull_colors.push_back(LLColor4U(rand()%128+127, rand()%128+127, rand()%128+127, 128)); - } + if (i+1 >= hull_colors.size()) + { + hull_colors.push_back(LLColor4U(rand()%128+127, rand()%128+127, rand()%128+127, 128)); + } - gGL.diffuseColor4ubv(hull_colors[i].mV); - LLVertexBuffer::drawArrays(LLRender::TRIANGLES, physics.mMesh[i].mPositions, physics.mMesh[i].mNormals); + gGL.diffuseColor4ubv(hull_colors[i].mV); + 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]; + 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]; - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - gGL.diffuseColor4f(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->setBuffer(type_mask & buffer->getTypeMask()); - 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); - gGL.diffuseColor3f(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(); - } + gGL.popMatrix(); + } glLineWidth(3.f); glPointSize(8.f); @@ -5572,13 +3796,13 @@ BOOL LLModelPreview::render() buffer->setBuffer(type_mask & buffer->getTypeMask()); gGL.diffuseColor4fv(material.mDiffuseColor.mV); gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - if (material.mDiffuseMap.notNull()) + + // Find the tex for this material, bind it, and add it to our set + // + LLViewerFetchedTexture* tex = bindMaterialDiffuseTexture(material); + if (tex) { - if (material.mDiffuseMap->getDiscardLevel() > -1) - { - gGL.getTexUnit(0)->bind(material.mDiffuseMap, true); - mTextureSet.insert(material.mDiffuseMap.get()); - } + mTextureSet.insert(tex); } buffer->draw(LLRender::TRIANGLES, buffer->getNumIndices(), 0); diff --git a/indra/newview/llfloatermodelpreview.h b/indra/newview/llfloatermodelpreview.h index e588418f7b..9948bb35a8 100755 --- a/indra/newview/llfloatermodelpreview.h +++ b/indra/newview/llfloatermodelpreview.h @@ -37,6 +37,8 @@ #include "llviewermenufile.h" #include "llfloatermodeluploadbase.h" +#include "lldaeloader.h" + class LLComboBox; class LLJoint; class LLViewerJointMesh; @@ -45,103 +47,18 @@ class LLTextBox; class LLVertexBuffer; class LLModelPreview; class LLFloaterModelPreview; +class DAE; class daeElement; class domProfile_COMMON; class domInstance_geometry; class domNode; class domTranslate; class domController; +class domSkin; +class domMesh; class LLMenuButton; class LLToggleableMenu; -typedef std::map JointTransformMap; -typedef std::map:: iterator JointTransformMapIt; - -const S32 NUM_LOD = 4; - -class LLModelLoader : public LLThread -{ -public: - typedef enum - { - STARTING = 0, - READING_FILE, - CREATING_FACES, - GENERATING_VERTEX_BUFFERS, - GENERATING_LOD, - DONE, - ERROR_PARSING, //basically loading failed - ERROR_MATERIALS, - } eLoadState; - - U32 mState; - std::string mFilename; - S32 mLod; - LLModelPreview* mPreview; - LLMatrix4 mTransform; - BOOL mFirstTransform; - LLVector3 mExtents[2]; - bool mTrySLM; - - std::map > mModel; - - typedef std::vector > model_list; - model_list mModelList; - - typedef std::vector model_instance_list; - - typedef std::map scene; - - scene mScene; - - typedef std::queue > model_queue; - - //queue of models that need a physics rep - model_queue mPhysicsQ; - - LLModelLoader( std::string filename, S32 lod, LLModelPreview* preview, JointTransformMap& jointMap, - std::deque& jointsFromNodes ); - ~LLModelLoader() ; - - virtual void run(); - bool doLoadModel(); - bool loadFromSLM(const std::string& filename); - void loadModelCallback(); - - void loadTextures() ; //called in the main thread. - void processElement(daeElement* element, bool& badElement); - std::map getMaterials(LLModel* model, domInstance_geometry* instance_geo); - LLImportMaterial profileToMaterial(domProfile_COMMON* material); - std::string getElementLabel(daeElement *element); - LLColor4 getDaeColor(daeElement* element); - - daeElement* getChildFromElement( daeElement* pElement, std::string const & name ); - - bool isNodeAJoint( domNode* pNode ); - void processJointNode( domNode* pNode, std::map& jointTransforms ); - void extractTranslation( domTranslate* pTranslate, LLMatrix4& transform ); - void extractTranslationViaElement( daeElement* pTranslateElement, LLMatrix4& transform ); - void extractTranslationViaSID( daeElement* pElement, LLMatrix4& transform ); - - void setLoadState(U32 state); - - void buildJointToNodeMappingFromScene( daeElement* pRoot ); - void processJointToNodeMapping( domNode* pNode ); - void processChildJoints( domNode* pParentNode ); - - //map of avatar joints as named in COLLADA assets to internal joint names - std::map mJointMap; - JointTransformMap& mJointList; - std::deque& mJointsFromNode; - - S32 mNumOfFetchingTextures ; //updated in the main thread - bool areTexturesReady() { return !mNumOfFetchingTextures; } //called in the main thread. - -private: - static std::list sActiveLoaderList; - static bool isAlive(LLModelLoader* loader) ; -}; - class LLFloaterModelPreview : public LLFloaterModelUploadBase { public: @@ -358,21 +275,14 @@ public: void setHasPivot( bool val ) { mHasPivot = val; } void setModelPivot( const LLVector3& pivot ) { mModelPivot = pivot; } - //Determines the viability of an asset to be used as an avatar rig (w or w/o joint upload caps) - void critiqueRigForUploadApplicability( const std::vector &jointListFromAsset ); - void critiqueJointToNodeMappingFromScene( void ); //Is a rig valid so that it can be used as a criteria for allowing for uploading of joint positions //Accessors for joint position upload friendly rigs const bool isRigValidForJointPositionUpload( void ) const { return mRigValidJointUpload; } void setRigValidForJointPositionUpload( bool rigValid ) { mRigValidJointUpload = rigValid; } - bool isRigSuitableForJointPositionUpload( const std::vector &jointListFromAsset ); - //Determines if a rig is a legacy from the joint list - bool isRigLegacy( const std::vector &jointListFromAsset ); + //Accessors for the legacy rigs const bool isLegacyRigValid( void ) const { return mLegacyRigValid; } - void setLegacyRigValid( bool rigValid ) { mLegacyRigValid = rigValid; } - //Verify that a controller matches vertex counts - bool verifyController( domController* pController ); + void setLegacyRigValid( bool rigValid ) { mLegacyRigValid = rigValid; } static void textureLoadedCallback( BOOL success, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* src_aux, S32 discard_level, BOOL final, void* userdata ); @@ -387,6 +297,14 @@ public: LLVector3 getTranslationForJointOffset( std::string joint ); +protected: + + static void loadedCallback(LLModelLoader::scene& scene,LLModelLoader::model_list& model_list, S32 lod, void* opaque); + static void stateChangedCallback(U32 state, void* opaque); + + static LLJoint* lookupJointByName(const std::string&, void* opaque); + static U32 loadTextures(LLImportMaterial& material, void* opaque); + private: //Utility function for controller vertex compare bool verifyCount( int expected, int result ); @@ -452,7 +370,7 @@ private: U32 mMaxTriangleLimit; LLMeshUploadThread::instance_list mUploadData; - std::set mTextureSet; + std::set mTextureSet; //map of vertex buffers to models (one vertex buffer in vector per face in model std::map > > mVertexBuffer[LLModel::NUM_LODS+1]; @@ -470,11 +388,10 @@ private: bool mLegacyRigValid; bool mLastJointUpdate; + + JointSet mJointsFromNode; + JointTransformMap mJointTransformMap; - std::deque mMasterJointList; - std::deque mMasterLegacyJointList; - std::deque mJointsFromNode; - JointTransformMap mJointTransformMap; LLPointer mPreviewAvatar; }; diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp index 5afd2cb329..f36fb971b5 100755 --- a/indra/newview/llmeshrepository.cpp +++ b/indra/newview/llmeshrepository.cpp @@ -498,6 +498,12 @@ void get_vertex_buffer_from_mesh(LLCDMeshData& mesh, LLModel::PhysicsMesh& res, } } +LLViewerFetchedTexture* LLMeshUploadThread::FindViewerTexture(const LLImportMaterial& material) +{ + LLPointer< LLViewerFetchedTexture > * ppTex = static_cast< LLPointer< LLViewerFetchedTexture > * >(material.mOpaqueData); + return ppTex ? (*ppTex).get() : NULL; +} + volatile S32 LLMeshRepoThread::sActiveHeaderRequests = 0; volatile S32 LLMeshRepoThread::sActiveLODRequests = 0; U32 LLMeshRepoThread::sMaxConcurrentRequests = 1; @@ -2027,6 +2033,14 @@ void LLMeshUploadThread::wholeModelToLLSD(LLSD& dest, bool include_textures) { LLMeshUploadData data; data.mBaseModel = iter->first; + + if (data.mBaseModel->mSubmodelID) + { + // These are handled below to insure correct parenting order on creation + // due to map walking being based on model address (aka random) + continue; + } + LLModelInstance& first_instance = *(iter->second.begin()); for (S32 i = 0; i < 5; i++) { @@ -2064,7 +2078,10 @@ void LLMeshUploadThread::wholeModelToLLSD(LLSD& dest, bool include_textures) data.mModel[LLModel::LOD_IMPOSTOR], decomp, mUploadSkin, - mUploadJoints); + mUploadJoints, + FALSE, + FALSE, + data.mBaseModel->mSubmodelID); data.mAssetData = ostr.str(); std::string str = ostr.str(); @@ -2098,17 +2115,26 @@ void LLMeshUploadThread::wholeModelToLLSD(LLSD& dest, bool include_textures) instance_entry["scale"] = ll_sd_from_vector3(scale); instance_entry["material"] = LL_MCODE_WOOD; - instance_entry["physics_shape_type"] = (U8)(LLViewerObject::PHYSICS_SHAPE_CONVEX_HULL); + instance_entry["physics_shape_type"] = data.mModel[LLModel::LOD_PHYSICS].notNull() ? (U8)(LLViewerObject::PHYSICS_SHAPE_PRIM) : (U8)(LLViewerObject::PHYSICS_SHAPE_CONVEX_HULL); instance_entry["mesh"] = mesh_index[data.mBaseModel]; instance_entry["face_list"] = LLSD::emptyArray(); - S32 end = llmin((S32)data.mBaseModel->mMaterialList.size(), data.mBaseModel->getNumVolumeFaces()) ; + // We want to be able to allow more than 8 materials... + // + S32 end = llmin((S32)instance.mMaterial.size(), instance.mModel->getNumVolumeFaces()) ; + for (S32 face_num = 0; face_num < end; face_num++) { LLImportMaterial& material = instance.mMaterial[data.mBaseModel->mMaterialList[face_num]]; LLSD face_entry = LLSD::emptyMap(); - LLViewerFetchedTexture *texture = material.mDiffuseMap.get(); + + LLViewerFetchedTexture *texture = NULL; + + if (material.mDiffuseMapFilename.size()) + { + texture = FindViewerTexture(material); + } if ((texture != NULL) && (textures.find(texture) == textures.end())) @@ -2123,9 +2149,171 @@ void LLMeshUploadThread::wholeModelToLLSD(LLSD& dest, bool include_textures) { LLPointer upload_file = LLViewerTextureList::convertToUploadFile(texture->getSavedRawImage()); + + if (!upload_file.isNull() && upload_file->getDataSize()) + { + texture_str.write((const char*) upload_file->getData(), upload_file->getDataSize()); + } + } + } + + if (texture != NULL && + mUploadTextures && + texture_index.find(texture) == texture_index.end()) + { + texture_index[texture] = texture_num; + std::string str = texture_str.str(); + res["texture_list"][texture_num] = LLSD::Binary(str.begin(),str.end()); + texture_num++; + } + + // Subset of TextureEntry fields. + if (texture != NULL && mUploadTextures) + { + face_entry["image"] = texture_index[texture]; + face_entry["scales"] = 1.0; + face_entry["scalet"] = 1.0; + face_entry["offsets"] = 0.0; + face_entry["offsett"] = 0.0; + face_entry["imagerot"] = 0.0; + } + face_entry["diffuse_color"] = ll_sd_from_color4(material.mDiffuseColor); + face_entry["fullbright"] = material.mFullbright; + instance_entry["face_list"][face_num] = face_entry; + } + + res["instance_list"][instance_num] = instance_entry; + instance_num++; + } + } + + for (instance_map::iterator iter = mInstance.begin(); iter != mInstance.end(); ++iter) + { + LLMeshUploadData data; + data.mBaseModel = iter->first; + + if (!data.mBaseModel->mSubmodelID) + { + // These were handled above already... + // + continue; + } + + LLModelInstance& first_instance = *(iter->second.begin()); + for (S32 i = 0; i < 5; i++) + { + data.mModel[i] = first_instance.mLOD[i]; + } + + if (mesh_index.find(data.mBaseModel) == mesh_index.end()) + { + // Have not seen this model before - create a new mesh_list entry for it. + if (model_name.empty()) + { + model_name = data.mBaseModel->getName(); + } + + if (model_metric.empty()) + { + model_metric = data.mBaseModel->getMetric(); + } + + std::stringstream ostr; + + LLModel::Decomposition& decomp = + data.mModel[LLModel::LOD_PHYSICS].notNull() ? + data.mModel[LLModel::LOD_PHYSICS]->mPhysics : + data.mBaseModel->mPhysics; + + decomp.mBaseHull = mHullMap[data.mBaseModel]; + + LLSD mesh_header = LLModel::writeModel( + ostr, + data.mModel[LLModel::LOD_PHYSICS], + data.mModel[LLModel::LOD_HIGH], + data.mModel[LLModel::LOD_MEDIUM], + data.mModel[LLModel::LOD_LOW], + data.mModel[LLModel::LOD_IMPOSTOR], + decomp, + mUploadSkin, + mUploadJoints, + FALSE, + FALSE, + data.mBaseModel->mSubmodelID); + + data.mAssetData = ostr.str(); + std::string str = ostr.str(); + + res["mesh_list"][mesh_num] = LLSD::Binary(str.begin(),str.end()); + mesh_index[data.mBaseModel] = mesh_num; + mesh_num++; + } + + // For all instances that use this model + for (instance_list::iterator instance_iter = iter->second.begin(); + instance_iter != iter->second.end(); + ++instance_iter) + { + + LLModelInstance& instance = *instance_iter; + + LLSD instance_entry; + + for (S32 i = 0; i < 5; i++) + { + data.mModel[i] = instance.mLOD[i]; + } + + LLVector3 pos, scale; + LLQuaternion rot; + LLMatrix4 transformation = instance.mTransform; + decomposeMeshMatrix(transformation,pos,rot,scale); + instance_entry["position"] = ll_sd_from_vector3(pos); + instance_entry["rotation"] = ll_sd_from_quaternion(rot); + instance_entry["scale"] = ll_sd_from_vector3(scale); + + instance_entry["material"] = LL_MCODE_WOOD; + instance_entry["physics_shape_type"] = (U8)(LLViewerObject::PHYSICS_SHAPE_NONE); + instance_entry["mesh"] = mesh_index[data.mBaseModel]; + + instance_entry["face_list"] = LLSD::emptyArray(); + + // We want to be able to allow more than 8 materials... + // + S32 end = llmin((S32)instance.mMaterial.size(), instance.mModel->getNumVolumeFaces()) ; + + for (S32 face_num = 0; face_num < end; face_num++) + { + LLImportMaterial& material = instance.mMaterial[data.mBaseModel->mMaterialList[face_num]]; + LLSD face_entry = LLSD::emptyMap(); + + LLViewerFetchedTexture *texture = NULL; + + if (material.mDiffuseMapFilename.size()) + { + texture = FindViewerTexture(material); + } + + if ((texture != NULL) && + (textures.find(texture) == textures.end())) + { + textures.insert(texture); + } + + std::stringstream texture_str; + if (texture != NULL && include_textures && mUploadTextures) + { + if(texture->hasSavedRawImage()) + { + LLPointer upload_file = + LLViewerTextureList::convertToUploadFile(texture->getSavedRawImage()); + + if (!upload_file.isNull() && upload_file->getDataSize()) + { texture_str.write((const char*) upload_file->getData(), upload_file->getDataSize()); } } + } if (texture != NULL && mUploadTextures && @@ -3756,37 +3944,6 @@ void LLMeshUploadThread::decomposeMeshMatrix(LLMatrix4& transformation, result_rot = quat_rotation; } -bool LLImportMaterial::operator<(const LLImportMaterial &rhs) const -{ - if (mDiffuseMap != rhs.mDiffuseMap) - { - return mDiffuseMap < rhs.mDiffuseMap; - } - - if (mDiffuseMapFilename != rhs.mDiffuseMapFilename) - { - return mDiffuseMapFilename < rhs.mDiffuseMapFilename; - } - - if (mDiffuseMapLabel != rhs.mDiffuseMapLabel) - { - return mDiffuseMapLabel < rhs.mDiffuseMapLabel; - } - - if (mDiffuseColor != rhs.mDiffuseColor) - { - return mDiffuseColor < rhs.mDiffuseColor; - } - - if (mBinding != rhs.mBinding) - { - return mBinding < rhs.mBinding; - } - - return mFullbright < rhs.mFullbright; -} - - void LLMeshRepository::updateInventory(inventory_data data) { LLMutexLock lock(mMeshMutex); @@ -4372,60 +4529,6 @@ void LLPhysicsDecomp::Request::setStatusMessage(const std::string& msg) mStatusMessage = msg; } -LLModelInstance::LLModelInstance(LLSD& data) -{ - mLocalMeshID = data["mesh_id"].asInteger(); - mLabel = data["label"].asString(); - mTransform.setValue(data["transform"]); - - for (U32 i = 0; i < data["material"].size(); ++i) - { - LLImportMaterial mat(data["material"][i]); - mMaterial[mat.mBinding] = mat; - } -} - - -LLSD LLModelInstance::asLLSD() -{ - LLSD ret; - - ret["mesh_id"] = mModel->mLocalID; - ret["label"] = mLabel; - ret["transform"] = mTransform.getValue(); - - U32 i = 0; - for (std::map::iterator iter = mMaterial.begin(); iter != mMaterial.end(); ++iter) - { - ret["material"][i++] = iter->second.asLLSD(); - } - - return ret; -} - -LLImportMaterial::LLImportMaterial(LLSD& data) -{ - mDiffuseMapFilename = data["diffuse"]["filename"].asString(); - mDiffuseMapLabel = data["diffuse"]["label"].asString(); - mDiffuseColor.setValue(data["diffuse"]["color"]); - mFullbright = data["fullbright"].asBoolean(); - mBinding = data["binding"].asString(); -} - - -LLSD LLImportMaterial::asLLSD() -{ - LLSD ret; - - ret["diffuse"]["filename"] = mDiffuseMapFilename; - ret["diffuse"]["label"] = mDiffuseMapLabel; - ret["diffuse"]["color"] = mDiffuseColor.getValue(); - ret["fullbright"] = mFullbright; - ret["binding"] = mBinding; - - return ret; -} - void LLMeshRepository::buildPhysicsMesh(LLModel::Decomposition& decomp) { decomp.mMesh.resize(decomp.mHull.size()); diff --git a/indra/newview/llmeshrepository.h b/indra/newview/llmeshrepository.h index 39280bea3a..688cd01a87 100755 --- a/indra/newview/llmeshrepository.h +++ b/indra/newview/llmeshrepository.h @@ -90,54 +90,6 @@ public: } }; -class LLImportMaterial -{ -public: - LLPointer mDiffuseMap; - std::string mDiffuseMapFilename; - std::string mDiffuseMapLabel; - std::string mBinding; - LLColor4 mDiffuseColor; - bool mFullbright; - - bool operator<(const LLImportMaterial ¶ms) const; - - LLImportMaterial() - : mFullbright(false) - { - mDiffuseColor.set(1,1,1,1); - } - - LLImportMaterial(LLSD& data); - - LLSD asLLSD(); -}; - -class LLModelInstance -{ -public: - LLPointer mModel; - LLPointer mLOD[5]; - - std::string mLabel; - - LLUUID mMeshID; - S32 mLocalMeshID; - - LLMatrix4 mTransform; - std::map mMaterial; - - LLModelInstance(LLModel* model, const std::string& label, LLMatrix4& transform, std::map& materials) - : mModel(model), mLabel(label), mTransform(transform), mMaterial(materials) - { - mLocalMeshID = -1; - } - - LLModelInstance(LLSD& data); - - LLSD asLLSD(); -}; - class LLPhysicsDecomp : public LLThread { public: @@ -483,6 +435,8 @@ public: // Inherited from LLCore::HttpHandler virtual void onCompleted(LLCore::HttpHandle handle, LLCore::HttpResponse * response); + LLViewerFetchedTexture* FindViewerTexture(const LLImportMaterial& material); + private: LLHandle mFeeObserverHandle; LLHandle mUploadObserverHandle; -- cgit v1.2.3 From cf143bd4610dc279f1aa790e0b37fbad5c86f654 Mon Sep 17 00:00:00 2001 From: Graham Linden Date: Thu, 29 May 2014 04:59:41 -0700 Subject: Fix files apparently missed by whomever did the great log macro renaming (pox be upon them) --- indra/newview/llinventoryobserver.cpp | 2 +- indra/newview/lllogchat.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/llinventoryobserver.cpp b/indra/newview/llinventoryobserver.cpp index 2cbf9bb8b6..26643d8671 100755 --- a/indra/newview/llinventoryobserver.cpp +++ b/indra/newview/llinventoryobserver.cpp @@ -702,7 +702,7 @@ void LLInventoryCategoriesObserver::changed(U32 mask) LLViewerInventoryCategory* category = gInventory.getCategory(cat_id); if (!category) { - llwarns << "Category : Category id = " << cat_id << " disappeared" << llendl; + LL_WARNS() << "Category : Category id = " << cat_id << " disappeared" << LL_ENDL; cat_data.mCallback(); // Keep track of those deleted categories so we can remove them deleted_categories_ids.push_back(cat_id); diff --git a/indra/newview/lllogchat.cpp b/indra/newview/lllogchat.cpp index 06e517a861..cadbc16f1e 100755 --- a/indra/newview/lllogchat.cpp +++ b/indra/newview/lllogchat.cpp @@ -1022,7 +1022,7 @@ void LLLoadHistoryThread::run() { loadHistory(mFileName, mMessages, mLoadParams); int count = mMessages->size(); - llinfos << "mMessages->size(): " << count << llendl; + LL_INFOS() << "mMessages->size(): " << count << LL_ENDL; setFinished(); } } -- cgit v1.2.3