summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--indra/llmath/llvolume.cpp34
-rwxr-xr-xindra/newview/app_settings/settings.xml11
-rwxr-xr-xindra/newview/llfloatermodelpreview.cpp226
-rw-r--r--indra/newview/llfloatermodelpreview.h2
-rwxr-xr-xindra/newview/llmeshrepository.cpp22
-rw-r--r--indra/newview/llmeshrepository.h6
6 files changed, 252 insertions, 49 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/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index e27397ab1a..c11de57c42 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/llfloatermodelpreview.cpp b/indra/newview/llfloatermodelpreview.cpp
index 04dfcac20b..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"
@@ -1088,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)
@@ -1167,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);
@@ -1744,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)
@@ -2614,6 +2739,7 @@ void LLModelPreview::saveUploadData(const std::string& filename, bool save_skinw
decomp,
empty_hull, save_skinweights, save_joint_positions);
+
data["mesh"][instance.mModel->mLocalID] = str.str();
}
@@ -2626,8 +2752,6 @@ void LLModelPreview::saveUploadData(const std::string& filename, bool save_skinw
out.close();
}
-
-
void LLModelPreview::clearModel(S32 lod)
{
if (lod < 0 || lod > LLModel::LOD_PHYSICS)
@@ -2769,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;
diff --git a/indra/newview/llfloatermodelpreview.h b/indra/newview/llfloatermodelpreview.h
index 5efac91ba3..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.
diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp
index 47dc343f5e..a227627bc1 100755
--- a/indra/newview/llmeshrepository.cpp
+++ b/indra/newview/llmeshrepository.cpp
@@ -3584,6 +3584,19 @@ 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;
@@ -3600,6 +3613,15 @@ LLSD LLModelInstance::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;
diff --git a/indra/newview/llmeshrepository.h b/indra/newview/llmeshrepository.h
index 4d727bf1f2..f0c0f308d5 100644
--- a/indra/newview/llmeshrepository.h
+++ b/indra/newview/llmeshrepository.h
@@ -102,6 +102,8 @@ public:
mDiffuseColor.set(1,1,1,1);
}
+ LLImportMaterial(LLSD& data);
+
LLSD asLLSD();
};
@@ -114,6 +116,7 @@ public:
std::string mLabel;
LLUUID mMeshID;
+ S32 mLocalMeshID;
LLMatrix4 mTransform;
std::vector<LLImportMaterial> mMaterial;
@@ -121,8 +124,11 @@ 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();
};