diff options
Diffstat (limited to 'indra/newview/llfloatermodelpreview.cpp')
-rwxr-xr-x | indra/newview/llfloatermodelpreview.cpp | 566 |
1 files changed, 456 insertions, 110 deletions
diff --git a/indra/newview/llfloatermodelpreview.cpp b/indra/newview/llfloatermodelpreview.cpp index ce977b33bb..a808cc47a2 100755 --- a/indra/newview/llfloatermodelpreview.cpp +++ b/indra/newview/llfloatermodelpreview.cpp @@ -82,6 +82,7 @@ #include "llvoavatarself.h" #include "pipeline.h" #include "lluictrlfactory.h" +#include "llviewercontrol.h" #include "llviewermenu.h" #include "llviewermenufile.h" #include "llviewerregion.h" @@ -90,6 +91,7 @@ #include "llbutton.h" #include "llcheckboxctrl.h" #include "llradiogroup.h" +#include "llsdserialize.h" #include "llsliderctrl.h" #include "llspinctrl.h" #include "lltoggleablemenu.h" @@ -109,6 +111,8 @@ const S32 PREVIEW_HPAD = PREVIEW_RESIZE_HANDLE_SIZE; const S32 PREF_BUTTON_HEIGHT = 16 + 7 + 16; const S32 PREVIEW_TEXTURE_HEIGHT = 300; +const F32 MAXIMUM_PIVOT_OFFSET = 64.0f; + void drawBoxOutline(const LLVector3& pos, const LLVector3& size); @@ -275,11 +279,6 @@ BOOL LLFloaterModelPreview::postBuild() return FALSE; } - - - - - childSetAction("lod_browse", onBrowseLOD, this); childSetCommitCallback("cancel_btn", onCancel, this); @@ -302,6 +301,8 @@ BOOL LLFloaterModelPreview::postBuild() childSetAction("ok_btn", onUpload, this); childDisable("ok_btn"); + childSetAction("reset_btn", onReset, this); + childSetAction("clear_materials", onClearMaterials, this); childSetCommitCallback("preview_lod_combo", onPreviewLODCommit, this); @@ -320,8 +321,6 @@ BOOL LLFloaterModelPreview::postBuild() childDisable("upload_skin"); childDisable("upload_joints"); - childDisable("pelvis_offset"); - childDisable("ok_btn"); mViewOptionMenuButton = getChild<LLMenuButton>("options_gear_btn"); @@ -382,14 +381,17 @@ BOOL LLFloaterModelPreview::postBuild() LLFloaterModelPreview::~LLFloaterModelPreview() { sInstance = NULL; - - const LLModelLoader *model_loader = mModelPreview->mModelLoader; - if (model_loader && model_loader->mResetJoints) + + if ( mModelPreview && mModelPreview->getResetJointFlag() ) { gAgentAvatarp->resetJointPositions(); } - delete mModelPreview; + + if ( mModelPreview ) + { + delete mModelPreview; + } if (mGLName) { @@ -572,7 +574,14 @@ void LLFloaterModelPreview::draw() if (!mModelPreview->mLoading) { - childSetTextArg("status", "[STATUS]", getString("status_idle")); + if ( mModelPreview->getLoadState() > LLModelLoader::ERROR_PARSING ) + { + childSetTextArg("status", "[STATUS]", getString(LLModel::getStatusString(mModelPreview->getLoadState() - LLModelLoader::ERROR_PARSING))); + } + else + { + childSetTextArg("status", "[STATUS]", getString("status_idle")); + } } childSetTextArg("prim_cost", "[PRIM_COST]", llformat("%d", mModelPreview->mResourceCost)); @@ -986,7 +995,7 @@ void LLFloaterModelPreview::onMouseCaptureLostModelPreview(LLMouseHandler* handl // LLModelLoader //----------------------------------------------------------------------------- LLModelLoader::LLModelLoader(std::string filename, S32 lod, LLModelPreview* preview) -: LLThread("Model Loader"), mFilename(filename), mLod(lod), mPreview(preview), mFirstTransform(TRUE), mResetJoints( FALSE ) +: LLThread("Model Loader"), mFilename(filename), mLod(lod), mPreview(preview), mFirstTransform(TRUE) { mJointMap["mPelvis"] = "mPelvis"; mJointMap["mTorso"] = "mTorso"; @@ -1087,8 +1096,15 @@ LLModelLoader::LLModelLoader(std::string filename, S32 lod, LLModelPreview* prev 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; + } } void stretch_extents(LLModel* model, LLMatrix4a& mat, LLVector4a& min, LLVector4a& max, BOOL& first_transform) @@ -1166,6 +1182,38 @@ void LLModelLoader::run() 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); @@ -1239,6 +1287,12 @@ bool LLModelLoader::doLoadModel() { LLPointer<LLModel> model = LLModel::loadModelFromDomMesh(mesh); + if(model->getStatus() != LLModel::NO_ERRORS) + { + setLoadState(ERROR_PARSING + model->getStatus()) ; + return true ; //abort + } + if (model.notNull() && validate_model(model)) { mModelList.push_back(model); @@ -1287,17 +1341,19 @@ bool LLModelLoader::doLoadModel() { //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++) { - model->mBindShapeMatrix.mMatrix[i][j] = dom_value[i + j*4]; + skin_info.mBindShapeMatrix.mMatrix[i][j] = dom_value[i + j*4]; } } LLMatrix4 trans = normalized_transformation; - trans *= model->mBindShapeMatrix; - model->mBindShapeMatrix = trans; + trans *= skin_info.mBindShapeMatrix; + skin_info.mBindShapeMatrix = trans; } @@ -1436,7 +1492,7 @@ bool LLModelLoader::doLoadModel() xsNMTOKEN semantic = input->getSemantic(); if (strcmp(semantic, COMMON_PROFILE_INPUT_JOINT) == 0) - { //found joint source, fill model->mJointMap and model->mJointList + { //found joint source, fill model->mJointMap and model->mSkinInfo.mJointNames daeElement* elem = input->getSource().getElement(); domSource* source = daeSafeCast<domSource>(elem); @@ -1457,8 +1513,8 @@ bool LLModelLoader::doLoadModel() { name = mJointMap[name]; } - model->mJointList.push_back(name); - model->mJointMap[name] = j; + model->mSkinInfo.mJointNames.push_back(name); + model->mSkinInfo.mJointMap[name] = j; } } else @@ -1475,8 +1531,8 @@ bool LLModelLoader::doLoadModel() { name = mJointMap[name]; } - model->mJointList.push_back(name); - model->mJointMap[name] = j; + model->mSkinInfo.mJointNames.push_back(name); + model->mSkinInfo.mJointMap[name] = j; } } } @@ -1505,7 +1561,7 @@ bool LLModelLoader::doLoadModel() } } - model->mInvBindMatrix.push_back(mat); + model->mSkinInfo.mInvBindMatrix.push_back(mat); } } } @@ -1516,17 +1572,17 @@ bool LLModelLoader::doLoadModel() //(which means we have all the joints that 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). - mPreview->setRigValid( doesJointArrayContainACompleteRig( model->mJointList ) ); - if ( !skeletonWithNoRootNode && !model->mJointList.empty() && mPreview->isRigValid() ) + mPreview->setRigValid( doesJointArrayContainACompleteRig( model->mSkinInfo.mJointNames ) ); + if ( !skeletonWithNoRootNode && !model->mSkinInfo.mJointNames.empty() && mPreview->isRigValid() ) { - mResetJoints = true; + mPreview->setResetJointFlag( true ); } if ( !missingSkeletonOrScene ) { //Set the joint translations on the avatar - if it's a full mapping //The joints are reset in the dtor - if ( mResetJoints ) + if ( mPreview->getResetJointFlag() ) { std::map<std::string, std::string> :: const_iterator masterJointIt = mJointMap.begin(); std::map<std::string, std::string> :: const_iterator masterJointItEnd = mJointMap.end(); @@ -1557,8 +1613,8 @@ bool LLModelLoader::doLoadModel() //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<std::string> :: const_iterator jointIt = model->mJointList.begin(); - const int jointCnt = model->mJointList.size(); + std::vector<std::string> :: const_iterator jointIt = model->mSkinInfo.mJointNames.begin(); + const int jointCnt = model->mSkinInfo.mJointNames.size(); for ( int i=0; i<jointCnt; ++i, ++jointIt ) { std::string lookingForJoint = (*jointIt).c_str(); @@ -1567,9 +1623,9 @@ bool LLModelLoader::doLoadModel() if ( jointTransforms.find( lookingForJoint ) != jointTransforms.end() ) { LLMatrix4 jointTransform = jointTransforms[lookingForJoint]; - LLMatrix4 newInverse = model->mInvBindMatrix[i]; + LLMatrix4 newInverse = model->mSkinInfo.mInvBindMatrix[i]; newInverse.setTranslation( jointTransforms[lookingForJoint].getTranslation() ); - model->mAlternateBindMatrix.push_back( newInverse ); + model->mSkinInfo.mAlternateBindMatrix.push_back( newInverse ); } else { @@ -1743,12 +1799,103 @@ void LLModelLoader::setLoadState(U32 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]; + + 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<LLModel> 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->setRigValid( doesJointArrayContainACompleteRig( loaded_model->mSkinInfo.mJointNames ) ); + } + } + else + { + llassert(model[lod].empty()); + } + } + } + + if (model[LLModel::LOD_HIGH].empty()) + { //failed to load high lod + return false; + } + + //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; +} + void LLModelLoader::loadModelCallback() { if (mPreview) { - mPreview->loadModelCallback(mLod); - mPreview->mModelLoader = NULL; + mPreview->loadModelCallback(mLod); } while (!isStopped()) @@ -1756,6 +1903,12 @@ void LLModelLoader::loadModelCallback() apr_sleep(100); } + //cleanup model loader + if (mPreview) + { + mPreview->mModelLoader = NULL; + } + delete this; } @@ -1781,8 +1934,19 @@ void LLModelLoader::handlePivotPoint( daeElement* pRoot ) if ( pTranslate ) { extractTranslation( pTranslate, workingTransform ); - mPreview->setModelPivot( workingTransform.getTranslation() ); - mPreview->setHasPivot( true ); + LLVector3 pivotTrans = workingTransform.getTranslation(); + if ( pivotTrans[VX] > MAXIMUM_PIVOT_OFFSET || pivotTrans[VX] < -MAXIMUM_PIVOT_OFFSET || + pivotTrans[VY] > MAXIMUM_PIVOT_OFFSET || pivotTrans[VY] < -MAXIMUM_PIVOT_OFFSET || + pivotTrans[VZ] > MAXIMUM_PIVOT_OFFSET || pivotTrans[VZ] < -MAXIMUM_PIVOT_OFFSET ) + { + llwarns<<"Asset Pivot Node contains an offset that is too large - values should be within (-"<<MAXIMUM_PIVOT_OFFSET<<","<<MAXIMUM_PIVOT_OFFSET<<")."<<llendl; + mPreview->setHasPivot( false ); + } + else + { + mPreview->setModelPivot( pivotTrans ); + mPreview->setHasPivot( true ); + } } } } @@ -2293,6 +2457,7 @@ LLModelPreview::LLModelPreview(S32 width, S32 height, LLFloater* fmp) : LLViewerDynamicTexture(width, height, 3, ORDER_MIDDLE, FALSE), LLMutex(NULL) , mPelvisZOffset( 0.0f ) , mRigValid( false ) +, mResetJoints( false ) { mNeedsUpdate = TRUE; mCameraDistance = 0.f; @@ -2332,6 +2497,7 @@ LLModelPreview::~LLModelPreview() { if (mModelLoader) { + delete mModelLoader; mModelLoader->mPreview = NULL; } //*HACK : *TODO : turn this back on when we understand why this crashes @@ -2346,7 +2512,7 @@ U32 LLModelPreview::calcResourceCost() if (mFMP && mModelLoader) { - if ( getLoadState() != LLModelLoader::ERROR_PARSING ) + if ( getLoadState() < LLModelLoader::ERROR_PARSING ) { mFMP->childEnable("ok_btn"); } @@ -2368,8 +2534,13 @@ U32 LLModelPreview::calcResourceCost() U32 num_hulls = 0; F32 debug_scale = mFMP ? mFMP->childGetValue("import_scale").asReal() : 1.f; - mPelvisZOffset = mFMP ? mFMP->childGetValue("pelvis_offset").asReal() : 32.0f; + mPelvisZOffset = mFMP ? mFMP->childGetValue("pelvis_offset").asReal() : 3.0f; + if ( mFMP && mFMP->childGetValue("upload_joints").asBoolean() ) + { + gAgentAvatarp->setPelvisOffset( mPelvisZOffset ); + } + F32 streaming_cost = 0.f; F32 physics_cost = 0.f; for (U32 i = 0; i < mUploadData.size(); ++i) @@ -2380,28 +2551,37 @@ U32 LLModelPreview::calcResourceCost() { accounted.insert(instance.mModel); - LLModel::convex_hull_decomposition& decomp = + LLModel::Decomposition& decomp = instance.mLOD[LLModel::LOD_PHYSICS] ? - instance.mLOD[LLModel::LOD_PHYSICS]->mConvexHullDecomp : - instance.mModel->mConvexHullDecomp; - - LLSD ret = LLModel::writeModel( - "", - instance.mLOD[4], - instance.mLOD[3], - instance.mLOD[2], - instance.mLOD[1], - instance.mLOD[0], - decomp, - mFMP->childGetValue("upload_skin").asBoolean(), - mFMP->childGetValue("upload_joints").asBoolean(), - TRUE); + instance.mLOD[LLModel::LOD_PHYSICS]->mPhysics : + instance.mModel->mPhysics; + + //update instance skin info for each lods pelvisZoffset + for ( int j=0; j<LLModel::NUM_LODS; ++j ) + { + if ( instance.mLOD[j] ) + { + instance.mLOD[j]->mSkinInfo.mPelvisOffset = mPelvisZOffset; + } + } + + std::stringstream ostr; + LLSD ret = LLModel::writeModel(ostr, + instance.mLOD[4], + instance.mLOD[3], + instance.mLOD[2], + instance.mLOD[1], + instance.mLOD[0], + decomp, + mFMP->childGetValue("upload_skin").asBoolean(), + mFMP->childGetValue("upload_joints").asBoolean(), + TRUE); cost += gMeshRepo.calcResourceCost(ret); - num_hulls += decomp.size(); - for (U32 i = 0; i < decomp.size(); ++i) + num_hulls += decomp.mHull.size(); + for (U32 i = 0; i < decomp.mHull.size(); ++i) { - num_points += decomp[i].size(); + num_points += decomp.mHull[i].size(); } //calculate streaming cost @@ -2561,6 +2741,75 @@ void LLModelPreview::rebuildUploadData() } +void LLModelPreview::saveUploadData(bool save_skinweights, bool save_joint_positions) +{ + if (!mLODFile[LLModel::LOD_HIGH].empty()) + { + std::string filename = mLODFile[LLModel::LOD_HIGH]; + + std::string::size_type i = filename.rfind("."); + if (i != std::string::npos) + { + filename.replace(i, filename.size()-1, ".slm"); + saveUploadData(filename, save_skinweights, save_joint_positions); + } + } +} + +void LLModelPreview::saveUploadData(const std::string& filename, bool save_skinweights, bool save_joint_positions) +{ + if (!gSavedSettings.getBOOL("MeshImportUseSLM")) + { + return; + } + + std::set<LLPointer<LLModel> > meshes; + std::map<LLModel*, std::string> mesh_binary; + + LLModel::hull empty_hull; + + LLSD data; + + S32 mesh_id = 0; + + //build list of unique models and initialize local id + for (U32 i = 0; i < mUploadData.size(); ++i) + { + LLModelInstance& instance = mUploadData[i]; + + if (meshes.find(instance.mModel) == meshes.end()) + { + instance.mModel->mLocalID = mesh_id++; + meshes.insert(instance.mModel); + + std::stringstream str; + + LLModel::Decomposition& decomp = + instance.mLOD[LLModel::LOD_PHYSICS].notNull() ? + instance.mLOD[LLModel::LOD_PHYSICS]->mPhysics : + instance.mModel->mPhysics; + + LLModel::writeModel(str, + instance.mLOD[LLModel::LOD_PHYSICS], + instance.mLOD[LLModel::LOD_HIGH], + instance.mLOD[LLModel::LOD_MEDIUM], + instance.mLOD[LLModel::LOD_LOW], + instance.mLOD[LLModel::LOD_IMPOSTOR], + decomp, + save_skinweights, save_joint_positions); + + + data["mesh"][instance.mModel->mLocalID] = str.str(); + } + + data["instance"][i] = instance.asLLSD(); + } + + llofstream out(filename, std::ios_base::out | std::ios_base::binary); + LLSDSerialize::toBinary(data, out); + out.flush(); + out.close(); +} void LLModelPreview::clearModel(S32 lod) { @@ -2617,7 +2866,7 @@ void LLModelPreview::loadModel(std::string filename, S32 lod) setPreviewLOD(lod); - if ( getLoadState() == LLModelLoader::ERROR_PARSING ) + if ( getLoadState() >= LLModelLoader::ERROR_PARSING ) { mFMP->childDisable("ok_btn"); } @@ -2699,44 +2948,129 @@ void LLModelPreview::loadModelCallback(S32 lod) LLMutexLock lock(this); if (!mModelLoader) { + mLoading = false ; return; } + if(getLoadState() >= LLModelLoader::ERROR_PARSING) + { + mLoading = false ; + return ; + } mModelLoader->loadTextures() ; - mModel[lod] = mModelLoader->mModelList; - mScene[lod] = mModelLoader->mScene; - mVertexBuffer[lod].clear(); - if (lod == LLModel::LOD_PHYSICS) - { - mPhysicsMesh.clear(); - } + if (lod == -1) + { //populate all LoDs from model loader scene + mBaseModel.clear(); + mBaseScene.clear(); - setPreviewLOD(lod); + bool skin_weights = false; + bool joint_positions = false; + for (S32 lod = 0; lod < LLModel::NUM_LODS; ++lod) + { //for each LoD - if (lod == LLModel::LOD_HIGH) - { //save a copy of the highest LOD for automatic LOD manipulation - if (mBaseModel.empty()) - { //first time we've loaded a model, auto-gen LoD - mGenLOD = true; + //clear scene and model info + mScene[lod].clear(); + mModel[lod].clear(); + mVertexBuffer[lod].clear(); + + if (mModelLoader->mScene.begin()->second[0].mLOD[lod].notNull()) + { //if this LoD exists in the loaded scene + + //copy scene to current LoD + mScene[lod] = mModelLoader->mScene; + + //touch up copied scene to look like current LoD + for (LLModelLoader::scene::iterator iter = mScene[lod].begin(); iter != mScene[lod].end(); ++iter) + { + LLModelLoader::model_instance_list& list = iter->second; + + for (LLModelLoader::model_instance_list::iterator list_iter = list.begin(); list_iter != list.end(); ++list_iter) + { + //override displayed model with current LoD + list_iter->mModel = list_iter->mLOD[lod]; + + //add current model to current LoD's model list (LLModel::mLocalID makes a good vector index) + S32 idx = list_iter->mModel->mLocalID; + + if (mModel[lod].size() <= idx) + { //stretch model list to fit model at given index + mModel[lod].resize(idx+1); + } + + mModel[lod][idx] = list_iter->mModel; + if (!list_iter->mModel->mSkinWeights.empty()) + { + skin_weights = true; + + if (!list_iter->mModel->mSkinInfo.mAlternateBindMatrix.empty()) + { + joint_positions = true; + } + } + } + } + } } - mBaseModel = mModel[lod]; - clearGLODGroup(); + if (mFMP) + { + LLFloaterModelPreview* fmp = (LLFloaterModelPreview*) mFMP; - mBaseScene = mScene[lod]; - mVertexBuffer[5].clear(); - } + if (skin_weights) + { //enable uploading/previewing of skin weights if present in .slm file + fmp->enableViewOption("show_skin_weight"); + mViewOption["show_skin_weight"] = true; + fmp->childSetValue("upload_skin", true); + } - clearIncompatible(lod); + if (joint_positions) + { + fmp->enableViewOption("show_joint_positions"); + mViewOption["show_joint_positions"] = true; + fmp->childSetValue("upload_joints", true); + } + } - mDirty = true; + //copy high lod to base scene for LoD generation + mBaseScene = mScene[LLModel::LOD_HIGH]; + mBaseModel = mModel[LLModel::LOD_HIGH]; - if (lod == LLModel::LOD_HIGH) - { + mDirty = true; resetPreviewTarget(); } + else + { //only replace given LoD + mModel[lod] = mModelLoader->mModelList; + mScene[lod] = mModelLoader->mScene; + mVertexBuffer[lod].clear(); + + setPreviewLOD(lod); + + if (lod == LLModel::LOD_HIGH) + { //save a copy of the highest LOD for automatic LOD manipulation + if (mBaseModel.empty()) + { //first time we've loaded a model, auto-gen LoD + mGenLOD = true; + } + + mBaseModel = mModel[lod]; + clearGLODGroup(); + + mBaseScene = mScene[lod]; + mVertexBuffer[5].clear(); + } + + clearIncompatible(lod); + + mDirty = true; + + if (lod == LLModel::LOD_HIGH) + { + resetPreviewTarget(); + } + } mLoading = false; refresh(); @@ -2746,8 +3080,12 @@ void LLModelPreview::loadModelCallback(S32 lod) void LLModelPreview::resetPreviewTarget() { - mPreviewTarget = (mModelLoader->mExtents[0] + mModelLoader->mExtents[1]) * 0.5f; - mPreviewScale = (mModelLoader->mExtents[1] - mModelLoader->mExtents[0]) * 0.5f; + if ( mModelLoader ) + { + mPreviewTarget = (mModelLoader->mExtents[0] + mModelLoader->mExtents[1]) * 0.5f; + mPreviewScale = (mModelLoader->mExtents[1] - mModelLoader->mExtents[0]) * 0.5f; + } + setPreviewTarget(mPreviewScale.magVec()*2.f); } @@ -2832,11 +3170,6 @@ void LLModelPreview::genLODs(S32 which_lod, U32 decimation, bool enforce_tri_lim return; } - if (which_lod == LLModel::LOD_PHYSICS) - { //clear physics mesh map - mPhysicsMesh.clear(); - } - LLVertexBuffer::unbind(); stop_gloderror(); @@ -3165,11 +3498,7 @@ void LLModelPreview::genLODs(S32 which_lod, U32 decimation, bool enforce_tri_lim //of an open problem). target_model->mPosition = base->mPosition; target_model->mSkinWeights = base->mSkinWeights; - target_model->mJointMap = base->mJointMap; - target_model->mJointList = base->mJointList; - target_model->mInvBindMatrix = base->mInvBindMatrix; - target_model->mBindShapeMatrix = base->mBindShapeMatrix; - target_model->mAlternateBindMatrix = base->mAlternateBindMatrix; + target_model->mSkinInfo = base->mSkinInfo; //copy material list target_model->mMaterialList = base->mMaterialList; @@ -3362,7 +3691,7 @@ void LLModelPreview::updateStatusMessages() } } - bool errorStateFromLoader = getLoadState() == LLModelLoader::ERROR_PARSING ? true : false; + bool errorStateFromLoader = getLoadState() >= LLModelLoader::ERROR_PARSING ? true : false; bool skinAndRigOk = true; bool uploadingSkin = mFMP->childGetValue("upload_skin").asBoolean(); @@ -3389,7 +3718,7 @@ void LLModelPreview::updateStatusMessages() LLModel* model = mModel[LLModel::LOD_PHYSICS][i]; S32 cur_submeshes = model->getNumVolumeFaces(); - LLModel::convex_hull_decomposition& decomp = model->mConvexHullDecomp; + LLModel::convex_hull_decomposition& decomp = model->mPhysics.mHull; if (!decomp.empty()) { @@ -3968,9 +4297,9 @@ BOOL LLModelPreview::render() glColor4fv(instance.mMaterial[i].mDiffuseColor.mV); if (i < instance.mMaterial.size() && instance.mMaterial[i].mDiffuseMap.notNull()) { - gGL.getTexUnit(0)->bind(instance.mMaterial[i].mDiffuseMap, true); if (instance.mMaterial[i].mDiffuseMap->getDiscardLevel() > -1) { + gGL.getTexUnit(0)->bind(instance.mMaterial[i].mDiffuseMap, true); mTextureSet.insert(instance.mMaterial[i].mDiffuseMap.get()); } } @@ -4026,12 +4355,17 @@ BOOL LLModelPreview::render() { LLMutexLock(decomp->mMutex); - std::map<LLPointer<LLModel>, std::vector<LLPointer<LLVertexBuffer> > >::iterator iter = - mPhysicsMesh.find(model); - if (iter != mPhysicsMesh.end()) + LLModel::Decomposition& physics = model->mPhysics; + + if (physics.mMesh.empty()) + { //build vertex buffer for physics mesh + gMeshRepo.buildPhysicsMesh(physics); + } + + if (!physics.mMesh.empty()) { //render hull instead of mesh render_mesh = false; - for (U32 i = 0; i < iter->second.size(); ++i) + for (U32 i = 0; i < physics.mMesh.size(); ++i) { if (explode > 0.f) { @@ -4050,14 +4384,8 @@ BOOL LLModelPreview::render() hull_colors.push_back(LLColor4U(rand()%128+127, rand()%128+127, rand()%128+127, 255)); } - LLVertexBuffer* buff = iter->second[i]; - if (buff) - { - buff->setBuffer(LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_NORMAL); - glColor4ubv(hull_colors[i].mV); - buff->drawArrays(LLRender::TRIANGLES, 0, buff->getNumVerts()); - } + LLVertexBuffer::drawArrays(LLRender::TRIANGLES, physics.mMesh[i].mPositions, physics.mMesh[i].mNormals); if (explode > 0.f) { @@ -4141,12 +4469,12 @@ BOOL LLModelPreview::render() //build matrix palette LLMatrix4 mat[64]; - for (U32 j = 0; j < model->mJointList.size(); ++j) + for (U32 j = 0; j < model->mSkinInfo.mJointNames.size(); ++j) { - LLJoint* joint = avatar->getJoint(model->mJointList[j]); + LLJoint* joint = avatar->getJoint(model->mSkinInfo.mJointNames[j]); if (joint) { - mat[j] = model->mInvBindMatrix[j]; + mat[j] = model->mSkinInfo.mInvBindMatrix[j]; mat[j] *= joint->getWorldMatrix(); } } @@ -4187,7 +4515,7 @@ BOOL LLModelPreview::render() //VECTORIZE THIS LLVector3 v(face.mPositions[j].getF32ptr()); - v = v * model->mBindShapeMatrix; + v = v * model->mSkinInfo.mBindShapeMatrix; v = v * final_mat; position[j] = v; @@ -4266,9 +4594,12 @@ void LLModelPreview::setPreviewLOD(S32 lod) mFMP->childSetTextArg("lod_table_footer", "[DETAIL]", mFMP->getString(lod_name[mPreviewLOD])); mFMP->childSetText("lod_file", mLODFile[mPreviewLOD]); - // the wizard has two lod drop downs + // the wizard has three lod drop downs LLComboBox* combo_box2 = mFMP->getChild<LLComboBox>("preview_lod_combo2"); combo_box2->setCurrentByIndex((NUM_LOD-1)-mPreviewLOD); // combo box list of lods is in reverse order + + LLComboBox* combo_box3 = mFMP->getChild<LLComboBox>("preview_lod_combo3"); + combo_box3->setCurrentByIndex((NUM_LOD-1)-mPreviewLOD); // combo box list of lods is in reverse order LLColor4 highlight_color = LLUIColorTable::instance().getColor("MeshImportTableHighlightColor"); LLColor4 normal_color = LLUIColorTable::instance().getColor("MeshImportTableNormalColor"); @@ -4304,6 +4635,17 @@ void LLFloaterModelPreview::onBrowseLOD(void* data) } //static +void LLFloaterModelPreview::onReset(void* user_data) +{ + assert_main_thread(); + + LLFloaterModelPreview* fmp = (LLFloaterModelPreview*) user_data; + LLModelPreview* mp = fmp->mModelPreview; + std::string filename = mp->mLODFile[3]; + mp->loadModel(filename,3); +} + +//static void LLFloaterModelPreview::onUpload(void* user_data) { assert_main_thread(); @@ -4317,8 +4659,13 @@ void LLFloaterModelPreview::onUpload(void* user_data) mp->mModelPreview->rebuildUploadData(); + bool upload_skinweights = mp->childGetValue("upload_skin").asBoolean(); + bool upload_joint_positions = mp->childGetValue("upload_joints").asBoolean(); + + mp->mModelPreview->saveUploadData(upload_skinweights, upload_joint_positions); + gMeshRepo.uploadModel(mp->mModelPreview->mUploadData, mp->mModelPreview->mPreviewScale, - mp->childGetValue("upload_textures").asBoolean(), mp->childGetValue("upload_skin"), mp->childGetValue("upload_joints")); + mp->childGetValue("upload_textures").asBoolean(), upload_skinweights, upload_joint_positions); mp->closeFloater(false); } @@ -4429,7 +4776,6 @@ void LLFloaterModelPreview::DecompRequest::completed() { if (sInstance->mModelPreview) { - sInstance->mModelPreview->mPhysicsMesh[mModel] = mHullMesh; sInstance->mModelPreview->mDirty = true; LLFloaterModelPreview::sInstance->mModelPreview->refresh(); } |