master
Dave Parks 2010-09-29 18:10:59 -05:00
commit d95b08c4a6
15 changed files with 352 additions and 75 deletions

View File

@ -1999,7 +1999,7 @@ std::string zip_llsd(LLSD& data)
{
std::stringstream llsd_strm;
LLSDSerialize::serialize(data, llsd_strm, LLSDSerialize::LLSD_BINARY);
LLSDSerialize::toBinary(data, llsd_strm);
const U32 CHUNK = 65536;
@ -2052,7 +2052,7 @@ std::string zip_llsd(LLSD& data)
return std::string();
}
}
while (strm.avail_out == 0);
while (ret == Z_OK);
std::string::size_type size = cur_size;
@ -2060,12 +2060,14 @@ std::string zip_llsd(LLSD& data)
deflateEnd(&strm);
free(output);
#if 0 //verify results work with unzip_llsd
std::istringstream test(result);
LLSD test_sd;
if (!unzip_llsd(test_sd, test, result.size()))
{
llerrs << "Invalid compression result!" << llendl;
}
#endif
return result;
}
@ -2131,7 +2133,7 @@ bool unzip_llsd(LLSD& data, std::istream& is, S32 size)
memcpy(result+cur_size, out, have);
cur_size += have;
} while (strm.avail_out == 0);
} while (ret == Z_OK);
inflateEnd(&strm);
delete [] in;
@ -2145,9 +2147,18 @@ bool unzip_llsd(LLSD& data, std::istream& is, S32 size)
//result now points to the decompressed LLSD block
{
std::string res_str((char*) result, cur_size);
std::istringstream istr(res_str);
if (!LLSDSerialize::deserialize(data, istr, cur_size))
std::string deprecated_header("<? LLSD/Binary ?>");
if (res_str.substr(0, deprecated_header.size()) == deprecated_header)
{
res_str = res_str.substr(deprecated_header.size()+1, cur_size);
}
cur_size = res_str.size();
std::istringstream istr(res_str);
if (!LLSDSerialize::fromBinary(data, istr, cur_size))
{
llwarns << "Failed to unzip LLSD block" << llendl;
free(result);

View File

@ -1660,7 +1660,7 @@ LLSD LLModel::writeModelToStream(std::ostream& ostr, LLSD& mdl, BOOL nowrite)
if (!nowrite)
{
LLSDSerialize::serialize(header, ostr, LLSDSerialize::LLSD_BINARY);
LLSDSerialize::toBinary(header, ostr);
if (!skin.empty())
{ //write skin block

View File

@ -8581,6 +8581,17 @@
<key>Value</key>
<real>1.0</real>
</map>
<key>MeshStreamingCostScaler</key>
<map>
<key>Comment</key>
<string>DEBUG</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>F32</string>
<key>Value</key>
<real>0.25f</real>
</map>
<key>MeshThreadCount</key>
<map>
<key>Comment</key>

View File

@ -300,6 +300,8 @@ BOOL LLFloaterModelPreview::postBuild()
childSetCommitCallback("upload_skin", onUploadSkinCommit, this);
childSetCommitCallback("upload_joints", onUploadJointsCommit, this);
childSetCommitCallback("debug scale", onDebugScaleCommit, this);
childDisable("upload_skin");
childDisable("upload_joints");
@ -353,6 +355,23 @@ void LLFloaterModelPreview::loadModel(S32 lod)
void LLFloaterModelPreview::setLODMode(S32 lod, S32 mode)
{
if (mode == 0)
{
if (lod != LLModel::LOD_PHYSICS)
{
for (S32 i = lod; i > 0; i--)
{
mModelPreview->clearModel(lod);
}
}
else
{
mModelPreview->clearModel(lod);
}
mModelPreview->refresh();
mModelPreview->calcResourceCost();
}
else if (mode == 1)
{
loadModel(lod);
}
@ -367,7 +386,7 @@ void LLFloaterModelPreview::setLODMode(S32 lod, S32 mode)
LLSpinCtrl* lim = getChild<LLSpinCtrl>(limit_name[lod], TRUE);
if (mode == 1) //triangle count
if (mode == 2) //triangle count
{
U32 tri_count = 0;
for (LLModelLoader::model_list::iterator iter = mModelPreview->mBaseModel.begin();
@ -395,6 +414,19 @@ void LLFloaterModelPreview::setLimit(S32 lod, S32 limit)
}
}
//static
void LLFloaterModelPreview::onDebugScaleCommit(LLUICtrl*,void* userdata)
{
LLFloaterModelPreview *fp =(LLFloaterModelPreview *)userdata;
if (!fp->mModelPreview)
{
return;
}
fp->mModelPreview->calcResourceCost();
}
//static
void LLFloaterModelPreview::onUploadJointsCommit(LLUICtrl*,void* userdata)
{
@ -2055,6 +2087,10 @@ U32 LLModelPreview::calcResourceCost()
U32 num_points = 0;
U32 num_hulls = 0;
F32 debug_scale = mFMP->childGetValue("debug scale").asReal();
F32 streaming_cost = 0.f;
for (U32 i = 0; i < mUploadData.size(); ++i)
{
LLModelInstance& instance = mUploadData[i];
@ -2076,18 +2112,35 @@ U32 LLModelPreview::calcResourceCost()
mFMP->childGetValue("upload_joints").asBoolean(),
true);
cost += gMeshRepo.calcResourceCost(ret);
num_hulls += physics_shape.size();
for (U32 i = 0; i < physics_shape.size(); ++i)
{
num_points += physics_shape[i].size();
}
//calculate streaming cost
LLMatrix4 transformation = instance.mTransform;
LLVector3 position = LLVector3(0, 0, 0) * transformation;
LLVector3 x_transformed = LLVector3(1, 0, 0) * transformation - position;
LLVector3 y_transformed = LLVector3(0, 1, 0) * transformation - position;
LLVector3 z_transformed = LLVector3(0, 0, 1) * transformation - position;
F32 x_length = x_transformed.normalize();
F32 y_length = y_transformed.normalize();
F32 z_length = z_transformed.normalize();
LLVector3 scale = LLVector3(x_length, y_length, z_length);
F32 radius = scale.length()*debug_scale;
streaming_cost += LLMeshRepository::getStreamingCost(ret, radius);
}
}
mFMP->childSetTextArg(info_name[LLModel::LOD_PHYSICS], "[HULLS]", llformat("%d",num_hulls));
mFMP->childSetTextArg(info_name[LLModel::LOD_PHYSICS], "[POINTS]", llformat("%d",num_points));
mFMP->childSetTextArg("streaming cost", "[COST]", llformat("%.3f", streaming_cost));
updateStatusMessages();
@ -2136,6 +2189,18 @@ void LLModelPreview::rebuildUploadData()
}
void LLModelPreview::clearModel(S32 lod)
{
if (lod < 0 || lod > LLModel::LOD_PHYSICS)
{
return;
}
mVertexBuffer[lod].clear();
mModel[lod].clear();
mScene[lod].clear();
}
void LLModelPreview::loadModel(std::string filename, S32 lod)
{
LLMutexLock lock(this);
@ -2639,65 +2704,63 @@ void LLModelPreview::genLODs(S32 which_lod)
}
if (which_lod == -1 || mLODMode[which_lod] == 1)
{
//generating LODs for all entries, or this entry has a triangle budget
glodGroupParameteri(mGroup[mdl], GLOD_ADAPT_MODE, GLOD_TRIANGLE_BUDGET);
stop_gloderror();
}
else
{
//this entry uses error mode
glodGroupParameteri(mGroup[mdl], GLOD_ADAPT_MODE, GLOD_OBJECT_SPACE_ERROR);
stop_gloderror();
}
if (which_lod != -1 && mLODMode[which_lod] == 2)
{
glodGroupParameterf(mGroup[mdl], GLOD_OBJECT_SPACE_ERROR_THRESHOLD, llmax(limit/100.f, 0.01f));
stop_gloderror();
}
else
{
glodGroupParameterf(mGroup[mdl], GLOD_OBJECT_SPACE_ERROR_THRESHOLD, 0.025f);
stop_gloderror();
}
//generating LODs for all entries, or this entry has a triangle budget
glodGroupParameteri(mGroup[mdl], GLOD_ADAPT_MODE, GLOD_TRIANGLE_BUDGET);
stop_gloderror();
glodGroupParameterf(mGroup[mdl], GLOD_OBJECT_SPACE_ERROR_THRESHOLD, 0.025f);
stop_gloderror();
}
S32 start = LLModel::LOD_HIGH;
S32 end = 0;
BOOL error_mode = FALSE;
if (which_lod != -1)
{
start = end = which_lod;
if (mLODMode[which_lod] == 2)
{
error_mode = TRUE;
}
}
std::string combo_name[] =
{
"lowest detail combo",
"low detail combo",
"medium detail combo",
"high detail combo",
"physics detail combo"
};
std::string limit_name[] =
{
"lowest limit",
"low limit",
"medium limit",
"high limit",
"physics limit"
};
for (S32 lod = start; lod >= end; --lod)
{
if (!error_mode)
if (which_lod == -1)
{
if (which_lod == -1)
if (lod < start)
{
if (lod < start)
{
triangle_count /= 3;
}
}
else
{
triangle_count = limit;
triangle_count /= 3;
}
}
else
{
triangle_count = limit;
}
LLComboBox* combo_box = mFMP->findChild<LLComboBox>(combo_name[lod]);
combo_box->setCurrentByIndex(2);
LLSpinCtrl* lim = mFMP->getChild<LLSpinCtrl>(limit_name[lod], TRUE);
lim->setMaxValue(base_triangle_count);
lim->setVisible(true);
mModel[lod].clear();
mModel[lod].resize(mBaseModel.size());
mVertexBuffer[lod].clear();
@ -2712,22 +2775,14 @@ void LLModelPreview::genLODs(S32 which_lod)
U32 target_count = U32(mPercentage[base]*triangle_count);
if (error_mode)
{
target_count = base->getNumTriangles();
}
if (target_count < 4)
{
target_count = 4;
}
if (which_lod == -1 || mLODMode[which_lod] == 1)
{
glodGroupParameteri(mGroup[base], GLOD_MAX_TRIANGLES, target_count);
stop_gloderror();
}
glodGroupParameteri(mGroup[base], GLOD_MAX_TRIANGLES, target_count);
stop_gloderror();
glodAdaptGroup(mGroup[base]);
stop_gloderror();

View File

@ -127,6 +127,7 @@ class LLModelPreview : public LLViewerDynamicTexture, public LLMutex
void pan(F32 right, F32 up);
virtual BOOL needsRender() { return mNeedsUpdate; }
void setPreviewLOD(S32 lod);
void clearModel(S32 lod);
void loadModel(std::string filename, S32 lod);
void loadModelCallback(S32 lod);
void genLODs(S32 which_lod = -1);
@ -182,7 +183,7 @@ class LLModelPreview : public LLViewerDynamicTexture, public LLMutex
std::set<LLPointer<LLViewerFetchedTexture> > mTextureSet;
//map of vertex buffers to models (one vertex buffer in vector per face in model
std::map<LLModel*, std::vector<LLPointer<LLVertexBuffer> > > mVertexBuffer[6];
std::map<LLModel*, std::vector<LLPointer<LLVertexBuffer> > > mVertexBuffer[LLModel::NUM_LODS+1];
};
class LLFloaterModelPreview : public LLFloater
@ -227,6 +228,7 @@ protected:
friend class LLPhysicsDecomp;
friend class LLPhysicsDecompFloater;
static void onDebugScaleCommit(LLUICtrl*, void*);
static void onUploadJointsCommit(LLUICtrl*,void*);
static void onUploadSkinCommit(LLUICtrl*,void*);

View File

@ -897,15 +897,24 @@ bool LLMeshRepoThread::headerReceived(const LLVolumeParams& mesh_params, U8* dat
{
std::string res_str((char*) data, data_size);
std::string deprecated_header("<? LLSD/Binary ?>");
if (res_str.substr(0, deprecated_header.size()) == deprecated_header)
{
res_str = res_str.substr(deprecated_header.size()+1, data_size);
header_size = deprecated_header.size()+1;
}
data_size = res_str.size();
std::istringstream stream(res_str);
if (!LLSDSerialize::deserialize(header, stream, data_size))
if (!LLSDSerialize::fromBinary(header, stream, data_size))
{
llwarns << "Mesh header parse error. Not a valid mesh asset!" << llendl;
return false;
}
header_size = stream.tellg();
header_size += stream.tellg();
}
else
{
@ -2121,6 +2130,28 @@ const LLMeshDecomposition* LLMeshRepository::getDecomposition(const LLUUID& mesh
return NULL;
}
const LLSD& LLMeshRepository::getMeshHeader(const LLUUID& mesh_id)
{
return mThread->getMeshHeader(mesh_id);
}
const LLSD& LLMeshRepoThread::getMeshHeader(const LLUUID& mesh_id)
{
static LLSD dummy_ret;
if (mesh_id.notNull())
{
LLMutexLock lock(mHeaderMutex);
mesh_header_map::iterator iter = mMeshHeader.find(mesh_id);
if (iter != mMeshHeader.end())
{
return iter->second;
}
}
return dummy_ret;
}
void LLMeshRepository::uploadModel(std::vector<LLModelInstance>& data, LLVector3& scale, bool upload_textures,
bool upload_skin, bool upload_joints)
{
@ -2493,6 +2524,50 @@ void LLMeshRepository::uploadError(LLSD& args)
mUploadErrorQ.push(args);
}
//static
F32 LLMeshRepository::getStreamingCost(const LLSD& header, F32 radius)
{
F32 dlowest = llmin(radius/0.06f, 256.f);
F32 dlow = llmin(radius/0.24f, 256.f);
F32 dmid = llmin(radius/1.0f, 256.f);
F32 dhigh = 0.f;
F32 bytes_lowest = header["lowest_lod"]["size"].asReal()/1024.f;
F32 bytes_low = header["low_lod"]["size"].asReal()/1024.f;
F32 bytes_mid = header["medium_lod"]["size"].asReal()/1024.f;
F32 bytes_high = header["high_lod"]["size"].asReal()/1024.f;
if (bytes_high == 0.f)
{
return 0.f;
}
if (bytes_mid == 0.f)
{
bytes_mid = bytes_high;
}
if (bytes_low == 0.f)
{
bytes_low = bytes_mid;
}
if (bytes_lowest == 0.f)
{
bytes_lowest = bytes_low;
}
F32 cost = 0.f;
cost += llmax(256.f-dlowest, 1.f)/32.f*bytes_lowest;
cost += llmax(dlowest-dlow, 1.f)/32.f*bytes_low;
cost += llmax(dlow-dmid, 1.f)/32.f*bytes_mid;
cost += llmax(dmid-dhigh, 1.f)/32.f*bytes_high;
cost *= gSavedSettings.getF32("MeshStreamingCostScaler");
return cost;
}
LLPhysicsDecomp::LLPhysicsDecomp()
: LLThread("Physics Decomp")

View File

@ -300,6 +300,7 @@ public:
bool lodReceived(const LLVolumeParams& mesh_params, S32 lod, U8* data, S32 data_size);
bool skinInfoReceived(const LLUUID& mesh_id, U8* data, S32 data_size);
bool decompositionReceived(const LLUUID& mesh_id, U8* data, S32 data_size);
const LLSD& getMeshHeader(const LLUUID& mesh_id);
void notifyLoadedMeshes();
S32 getActualMeshLOD(const LLVolumeParams& mesh_params, S32 lod);
@ -385,6 +386,7 @@ public:
static U32 sCacheBytesWritten;
static U32 sPeakKbps;
static F32 getStreamingCost(const LLSD& header, F32 radius);
LLMeshRepository();
@ -405,6 +407,7 @@ public:
U32 getResourceCost(const LLUUID& mesh_params);
const LLMeshSkinInfo* getSkinInfo(const LLUUID& mesh_id);
const LLMeshDecomposition* getDecomposition(const LLUUID& mesh_id);
const LLSD& getMeshHeader(const LLUUID& mesh_id);
void uploadModel(std::vector<LLModelInstance>& data, LLVector3& scale, bool upload_textures,
bool upload_skin, bool upload_joints);

View File

@ -6230,6 +6230,40 @@ F32 LLObjectSelection::getSelectedObjectCost()
return cost;
}
F32 LLObjectSelection::getSelectedObjectStreamingCost()
{
F32 cost = 0.f;
for (list_t::iterator iter = mList.begin(); iter != mList.end(); ++iter)
{
LLSelectNode* node = *iter;
LLViewerObject* object = node->getObject();
if (object)
{
cost += object->getStreamingCost();
}
}
return cost;
}
U32 LLObjectSelection::getSelectedObjectTriangleCount()
{
U32 count = 0;
for (list_t::iterator iter = mList.begin(); iter != mList.end(); ++iter)
{
LLSelectNode* node = *iter;
LLViewerObject* object = node->getObject();
if (object)
{
count += object->getTriangleCount();
}
}
return count;
}
F32 LLObjectSelection::getSelectedLinksetCost()
{
cleanupNodes();

View File

@ -288,6 +288,8 @@ public:
S32 getObjectCount(BOOL mesh_adjust = FALSE);
F32 getSelectedObjectCost();
F32 getSelectedLinksetCost();
F32 getSelectedObjectStreamingCost();
U32 getSelectedObjectTriangleCount();
S32 getTECount();
S32 getRootObjectCount();

View File

@ -2942,6 +2942,16 @@ F32 LLViewerObject::getObjectCost()
return mObjectCost;
}
F32 LLViewerObject::getStreamingCost()
{
return 0.f;
}
U32 LLViewerObject::getTriangleCount()
{
return 0;
}
F32 LLViewerObject::getLinksetCost()
{
if (mCostStale)

View File

@ -336,6 +336,9 @@ public:
void setObjectCost(F32 cost);
F32 getObjectCost();
virtual F32 getStreamingCost();
virtual U32 getTriangleCount();
void setLinksetCost(F32 cost);
F32 getLinksetCost();

View File

@ -522,6 +522,14 @@ public:
ypos += y_inc;
addText(xpos, ypos, llformat("Selection Streaming Cost: %.3f ", LLSelectMgr::getInstance()->getSelection()->getSelectedObjectStreamingCost()));
ypos += y_inc;
addText(xpos, ypos, llformat("Selection Triangle Count: %.3f Ktris ", LLSelectMgr::getInstance()->getSelection()->getSelectedObjectTriangleCount()/1000.f));
ypos += y_inc;
LLVertexBuffer::sBindCount = LLImageGL::sBindCount =
LLVertexBuffer::sSetCount = LLImageGL::sUniqueCount =
gPipeline.mNumVisibleNodes = LLPipeline::sVisibleLightCount = 0;

View File

@ -3207,6 +3207,45 @@ U32 LLVOVolume::getRenderCost(texture_cost_t &textures) const
}
F32 LLVOVolume::getStreamingCost()
{
std::string header_lod[] =
{
"lowest_lod",
"low_lod",
"medium_lod",
"high_lod"
};
if (isMesh())
{
const LLSD& header = gMeshRepo.getMeshHeader(getVolume()->getParams().getSculptID());
F32 radius = getRadius();
return LLMeshRepository::getStreamingCost(header, radius);
}
return 0.f;
}
U32 LLVOVolume::getTriangleCount()
{
U32 count = 0;
LLVolume* volume = getVolume();
if (volume)
{
for (S32 i = 0; i < volume->getNumVolumeFaces(); ++i)
{
count += volume->getVolumeFace(i).mNumIndices/3;
}
}
return count;
}
//static
void LLVOVolume::preUpdateGeom()
{

View File

@ -136,7 +136,8 @@ public:
/*virtual*/ const LLMatrix4 getRenderMatrix() const;
typedef std::map<LLUUID, S32> texture_cost_t;
U32 getRenderCost(texture_cost_t &textures) const;
/*virtual*/ F32 getStreamingCost();
/*virtual*/ U32 getTriangleCount();
/*virtual*/ BOOL lineSegmentIntersect(const LLVector3& start, const LLVector3& end,
S32 face = -1, // which face to check, -1 = ALL_SIDES
BOOL pick_transparent = FALSE,

View File

@ -49,10 +49,13 @@
</text>
<combo_box bottom_delta="0" left="97" follows="left|top" height="18"
name="high detail combo" width="100" tool_tip="Specify mesh for this level of detail">
<combo_item name="high choose file">
<combo_item name="high none" value="none">
None
</combo_item>
<combo_item name="high choose file" value="file">
Choose File...
</combo_item>
<combo_item name="high triangle limit">
<combo_item name="high triangle limit" value="limit">
Triangle Limit
</combo_item>
</combo_box>
@ -67,10 +70,13 @@
</text>
<combo_box bottom_delta="0" left="97" follows="left|top" height="18"
name="medium detail combo" width="100" tool_tip="Specify mesh for this level of detail">
<combo_item name="medium choose file">
<combo_item name="medium none" value="none">
None
</combo_item>
<combo_item name="medium choose file" value="file">
Choose File...
</combo_item>
<combo_item name="medium triangle limit">
<combo_item name="medium triangle limit" value="limit">
Triangle Limit
</combo_item>
</combo_box>
@ -85,10 +91,13 @@
</text>
<combo_box bottom_delta="0" left="97" follows="left|top" height="18"
name="low detail combo" width="100" tool_tip="Specify mesh for this level of detail">
<combo_item name="low choose file">
<combo_item name="low none" value="none">
None
</combo_item>
<combo_item name="low choose file" value="file">
Choose File...
</combo_item>
<combo_item name="low triangle limit">
<combo_item name="low triangle limit" value="limit">
Triangle Limit
</combo_item>
</combo_box>
@ -101,12 +110,15 @@
<text bottom_delta="35" follows="top|left" height="15" left="10" name="lowest_lod_label">
Lowest LOD:
</text>
<combo_box bottom_delta="0" left="97" folimpostors="left|top" height="18"
<combo_box bottom_delta="0" left="97" follows="left|top" height="18"
name="lowest detail combo" width="100" tool_tip="Specify mesh for this level of detail">
<combo_item name="lowest choose file">
<combo_item name="lowest none" value="none">
None
</combo_item>
<combo_item name="lowest choose file" value="file">
Choose File...
</combo_item>
<combo_item name="lowest triangle limit">
<combo_item name="lowest triangle limit" value="limit">
Triangle Limit
</combo_item>
</combo_box>
@ -121,10 +133,13 @@
</text>
<combo_box bottom_delta="0" left="97" follows="left|top" height="18"
name="physics detail combo" width="100">
<combo_item name="physics choose file">
<combo_item name="physics none" value="none">
None
</combo_item>
<combo_item name="physics choose file" value="file">
Choose File...
</combo_item>
<combo_item name="physics triangle limit">
<combo_item name="physics triangle limit" value="limit">
Triangle Limit...
</combo_item>
</combo_box>
@ -163,4 +178,12 @@
<text bottom_delta="20" left="15" follows="top|left" height="15" name="upload_message">
[MESSAGE]
</text>
</floater>
<text bottom_delta="45" left="15" follows="top|left" height="15" name="debug section">
DEBUG:
</text>
<text bottom_delta="20" left="15" follows="top|left" height="15" name="streaming cost">
Streaming Cost: [COST]
</text>
<spinner bottom_delta="20" label="Scale" left="15" width="120" name="debug scale" decimal_digits="3" increment="1" min_val="0" max_val="64" initial_value="1" tool_tip="Scale to base streaming cost on."/>
</floater>