diff options
-rw-r--r-- | indra/llmath/llvolume.cpp | 34 | ||||
-rw-r--r-- | indra/llmath/m4math.cpp | 50 | ||||
-rw-r--r-- | indra/llmath/m4math.h | 2 | ||||
-rwxr-xr-x | indra/llprimitive/llmodel.cpp | 1 | ||||
-rwxr-xr-x | indra/llprimitive/llmodel.h | 3 | ||||
-rwxr-xr-x | indra/newview/app_settings/settings.xml | 11 | ||||
-rw-r--r-- | indra/newview/lldrawpoolbump.cpp | 2 | ||||
-rwxr-xr-x | indra/newview/llfloatermodelpreview.cpp | 295 | ||||
-rw-r--r-- | indra/newview/llfloatermodelpreview.h | 6 | ||||
-rwxr-xr-x | indra/newview/llmeshrepository.cpp | 49 | ||||
-rw-r--r-- | indra/newview/llmeshrepository.h | 10 |
11 files changed, 412 insertions, 51 deletions
diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp index c4be176353..7a2f06da8f 100644 --- a/indra/llmath/llvolume.cpp +++ b/indra/llmath/llvolume.cpp @@ -2162,7 +2162,7 @@ BOOL LLVolume::createVolumeFacesFromStream(std::istream& is) LLSD header;
{
- if (!LLSDSerialize::deserialize(header, is, 1024*1024*1024))
+ if (!LLSDSerialize::fromBinary(header, is, 1024*1024*1024))
{
llwarns << "Mesh header parse error. Not a valid mesh asset!" << llendl;
return FALSE;
@@ -2174,34 +2174,18 @@ BOOL LLVolume::createVolumeFacesFromStream(std::istream& is) "lowest_lod",
"low_lod",
"medium_lod",
- "high_lod"
+ "high_lod",
+ "physics_shape",
};
- S32 lod = llclamp((S32) mDetail, 0, 3);
+ const S32 MODEL_LODS = 5;
- while (lod < 4 &&
- (header[nm[lod]]["offset"].asInteger() == -1 ||
- header[nm[lod]]["size"].asInteger() == 0 ))
- {
- ++lod;
- }
-
- if (lod >= 4)
- {
- lod = llclamp((S32) mDetail, 0, 3);
+ S32 lod = llclamp((S32) mDetail, 0, MODEL_LODS);
- while (lod >= 0 &&
- (header[nm[lod]]["offset"].asInteger() == -1 ||
- header[nm[lod]]["size"].asInteger() == 0) )
- {
- --lod;
- }
-
- if (lod < 0)
- {
- llwarns << "Mesh header missing LOD offsets. Not a valid mesh asset!" << llendl;
- return FALSE;
- }
+ if (header[nm[lod]]["offset"].asInteger() == -1 ||
+ header[nm[lod]]["size"].asInteger() == 0 )
+ { //cannot load requested LOD
+ return FALSE;
}
is.seekg(header[nm[lod]]["offset"].asInteger(), std::ios_base::cur);
diff --git a/indra/llmath/m4math.cpp b/indra/llmath/m4math.cpp index 8741400e52..bad4deb4de 100644 --- a/indra/llmath/m4math.cpp +++ b/indra/llmath/m4math.cpp @@ -829,4 +829,54 @@ std::ostream& operator<<(std::ostream& s, const LLMatrix4 &a) return s; } +LLSD LLMatrix4::getValue() const +{ + LLSD ret; + + ret[0] = mMatrix[0][0]; + ret[1] = mMatrix[0][1]; + ret[2] = mMatrix[0][2]; + ret[3] = mMatrix[0][3]; + + ret[4] = mMatrix[1][0]; + ret[5] = mMatrix[1][1]; + ret[6] = mMatrix[1][2]; + ret[7] = mMatrix[1][3]; + + ret[8] = mMatrix[2][0]; + ret[9] = mMatrix[2][1]; + ret[10] = mMatrix[2][2]; + ret[11] = mMatrix[2][3]; + + ret[12] = mMatrix[3][0]; + ret[13] = mMatrix[3][1]; + ret[14] = mMatrix[3][2]; + ret[15] = mMatrix[3][3]; + + return ret; +} + +void LLMatrix4::setValue(const LLSD& data) +{ + mMatrix[0][0] = data[0].asReal(); + mMatrix[0][1] = data[1].asReal(); + mMatrix[0][2] = data[2].asReal(); + mMatrix[0][3] = data[3].asReal(); + + mMatrix[1][0] = data[4].asReal(); + mMatrix[1][1] = data[5].asReal(); + mMatrix[1][2] = data[6].asReal(); + mMatrix[1][3] = data[7].asReal(); + + mMatrix[2][0] = data[8].asReal(); + mMatrix[2][1] = data[9].asReal(); + mMatrix[2][2] = data[10].asReal(); + mMatrix[2][3] = data[11].asReal(); + + mMatrix[3][0] = data[12].asReal(); + mMatrix[3][1] = data[13].asReal(); + mMatrix[3][2] = data[14].asReal(); + mMatrix[3][3] = data[15].asReal(); +} + diff --git a/indra/llmath/m4math.h b/indra/llmath/m4math.h index 3588f36758..a7dce10397 100644 --- a/indra/llmath/m4math.h +++ b/indra/llmath/m4math.h @@ -119,6 +119,8 @@ public: ~LLMatrix4(void); // Destructor + LLSD getValue() const; + void setValue(const LLSD&); ////////////////////////////// // diff --git a/indra/llprimitive/llmodel.cpp b/indra/llprimitive/llmodel.cpp index eed82f924b..3669fef0dc 100755 --- a/indra/llprimitive/llmodel.cpp +++ b/indra/llprimitive/llmodel.cpp @@ -60,6 +60,7 @@ LLModel::LLModel(LLVolumeParams& params, F32 detail) , mPelvisOffset( 0.0f ) { mDecompID = -1; + mLocalID = -1; } LLModel::~LLModel() diff --git a/indra/llprimitive/llmodel.h b/indra/llprimitive/llmodel.h index e9e33bdee5..addf527d8d 100755 --- a/indra/llprimitive/llmodel.h +++ b/indra/llprimitive/llmodel.h @@ -205,6 +205,9 @@ public: std::vector<LLVector3> mHullCenter; U32 mHullPoints; + //ID for storing this model in a .slm file + S32 mLocalID; + protected: void addVolumeFacesFromDomMesh(domMesh* mesh); virtual BOOL createVolumeFacesFromFile(const std::string& file_name); diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 33dcadfc50..176211773f 100755 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -5523,6 +5523,17 @@ <key>Value</key> <real>1</real> </map> + <key>MeshImportUseSLM</key> + <map> + <key>Comment</key> + <string>Use cached copy of last upload for a dae if available instead of loading dae file from scratch.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <real>0</real> + </map> <key>MigrateCacheDirectory</key> <map> <key>Comment</key> diff --git a/indra/newview/lldrawpoolbump.cpp b/indra/newview/lldrawpoolbump.cpp index bbce847fdc..0a642f494b 100644 --- a/indra/newview/lldrawpoolbump.cpp +++ b/indra/newview/lldrawpoolbump.cpp @@ -646,8 +646,6 @@ BOOL LLDrawPoolBump::bindBumpMap(U8 bump_code, LLViewerTexture* texture, F32 vsi break; } - llassert(bump); - if (bump) { if (channel == -2) diff --git a/indra/newview/llfloatermodelpreview.cpp b/indra/newview/llfloatermodelpreview.cpp index ce977b33bb..6145c6c16d 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" @@ -1087,8 +1089,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->mBaseModel.empty(); mPreview->setLoadState(STARTING); } + else + { + mTrySLM = false; + } } void stretch_extents(LLModel* model, LLMatrix4a& mat, LLVector4a& min, LLVector4a& max, BOOL& first_transform) @@ -1166,6 +1175,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); @@ -1743,6 +1784,91 @@ 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->createVolumeFacesFromStream(str)) + { + loaded_model->mLocalID = i; + model[lod].push_back(loaded_model); + } + 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); + } + + return true; +} + void LLModelLoader::loadModelCallback() { if (mPreview) @@ -2561,6 +2687,70 @@ 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) +{ + 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::convex_hull_decomposition& decomp = + instance.mLOD[LLModel::LOD_PHYSICS].notNull() ? + instance.mLOD[LLModel::LOD_PHYSICS]->mConvexHullDecomp : + instance.mModel->mConvexHullDecomp; + + 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, + empty_hull, 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) { @@ -2703,39 +2893,93 @@ void LLModelPreview::loadModelCallback(S32 lod) } 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); + for (S32 lod = 0; lod < LLModel::NUM_LODS; ++lod) + { //for each LoD + //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 - 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; + //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; + } + } + } } - mBaseModel = mModel[lod]; - clearGLODGroup(); + //copy high lod to base scene for LoD generation + mBaseScene = mScene[LLModel::LOD_HIGH]; + mBaseModel = mModel[LLModel::LOD_HIGH]; - mBaseScene = mScene[lod]; - mVertexBuffer[5].clear(); + mDirty = true; + resetPreviewTarget(); } + else + { //only replace given LoD + mModel[lod] = mModelLoader->mModelList; + mScene[lod] = mModelLoader->mScene; + mVertexBuffer[lod].clear(); - clearIncompatible(lod); + if (lod == LLModel::LOD_PHYSICS) + { + mPhysicsMesh.clear(); + } - mDirty = true; + setPreviewLOD(lod); - if (lod == LLModel::LOD_HIGH) - { - resetPreviewTarget(); + + 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; @@ -4317,8 +4561,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); } diff --git a/indra/newview/llfloatermodelpreview.h b/indra/newview/llfloatermodelpreview.h index 910a45f9fe..68fa0fa4c1 100644 --- a/indra/newview/llfloatermodelpreview.h +++ b/indra/newview/llfloatermodelpreview.h @@ -76,6 +76,7 @@ public: LLMatrix4 mTransform; BOOL mFirstTransform; LLVector3 mExtents[2]; + bool mTrySLM; std::map<daeElement*, LLPointer<LLModel> > mModel; @@ -97,6 +98,7 @@ public: virtual void run(); bool doLoadModel(); + bool loadFromSLM(const std::string& filename); void loadModelCallback(); void loadTextures() ; //called in the main thread. @@ -288,6 +290,8 @@ public: void clearMaterials(); U32 calcResourceCost(); void rebuildUploadData(); + void saveUploadData(bool save_skinweights, bool save_joint_poisitions); + void saveUploadData(const std::string& filename, bool save_skinweights, bool save_joint_poisitions); void clearIncompatible(S32 lod); void updateStatusMessages(); void clearGLODGroup(); @@ -332,7 +336,7 @@ public: std::string mLODFile[LLModel::NUM_LODS]; bool mLoading; U32 mLoadState; - + std::map<std::string, bool> mViewOption; //GLOD object parameters (must rebuild object if these change) diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp index 93e773d33b..a227627bc1 100755 --- a/indra/newview/llmeshrepository.cpp +++ b/indra/newview/llmeshrepository.cpp @@ -3584,3 +3584,52 @@ 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) + { + mMaterial.push_back(LLImportMaterial(data["material"][i])); + } +} + + +LLSD LLModelInstance::asLLSD() +{ + LLSD ret; + + ret["mesh_id"] = mModel->mLocalID; + ret["label"] = mLabel; + ret["transform"] = mTransform.getValue(); + + for (U32 i = 0; i < mMaterial.size(); ++i) + { + ret["material"][i] = mMaterial[i].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(); +} + + +LLSD LLImportMaterial::asLLSD() +{ + LLSD ret; + + ret["diffuse"]["filename"] = mDiffuseMapFilename; + ret["diffuse"]["label"] = mDiffuseMapLabel; + ret["diffuse"]["color"] = mDiffuseColor.getValue(); + ret["fullbright"] = mFullbright; + + return ret; +} diff --git a/indra/newview/llmeshrepository.h b/indra/newview/llmeshrepository.h index ccdcc03310..f0c0f308d5 100644 --- a/indra/newview/llmeshrepository.h +++ b/indra/newview/llmeshrepository.h @@ -101,6 +101,10 @@ public: { mDiffuseColor.set(1,1,1,1); } + + LLImportMaterial(LLSD& data); + + LLSD asLLSD(); }; class LLModelInstance @@ -112,6 +116,7 @@ public: std::string mLabel; LLUUID mMeshID; + S32 mLocalMeshID; LLMatrix4 mTransform; std::vector<LLImportMaterial> mMaterial; @@ -119,7 +124,12 @@ public: LLModelInstance(LLModel* model, const std::string& label, LLMatrix4& transform, std::vector<LLImportMaterial>& materials) : mModel(model), mLabel(label), mTransform(transform), mMaterial(materials) { + mLocalMeshID = -1; } + + LLModelInstance(LLSD& data); + + LLSD asLLSD(); }; class LLMeshSkinInfo |