SH-477 Better mesh streaming cost estimation.

meow-7.2.2
Dave Parks 2011-03-30 18:38:22 -05:00
parent 1aecac62eb
commit 6b9a2d24cc
14 changed files with 357 additions and 330 deletions

View File

@ -2095,11 +2095,6 @@ bool unzip_llsd(LLSD& data, std::istream& is, S32 size)
S32 ret = inflateInit(&strm);
if (ret != Z_OK)
{
llerrs << "WTF?" << llendl;
}
do
{
strm.avail_out = CHUNK;

View File

@ -1333,70 +1333,6 @@ std::string LLModel::getName() const
return mLabel;
}
//static
LLSD LLModel::writeModel(
std::string filename,
LLModel* physics,
LLModel* high,
LLModel* medium,
LLModel* low,
LLModel* impostor,
const convex_hull_decomposition& decomp,
BOOL upload_skin,
BOOL upload_joints,
BOOL nowrite)
{
LLModel::hull dummy_hull;
return writeModel(
filename,
physics,
high,
medium,
low,
impostor,
decomp,
dummy_hull,
upload_skin,
upload_joints,
nowrite);
}
//static
LLSD LLModel::writeModel(
std::string filename,
LLModel* physics,
LLModel* high,
LLModel* medium,
LLModel* low,
LLModel* impostor,
const convex_hull_decomposition& decomp,
const hull& base_hull,
BOOL upload_skin,
BOOL upload_joints,
BOOL nowrite)
{
std::ofstream os(
filename.c_str(),
std::ofstream::out | std::ofstream::binary);
LLSD header = writeModel(
os,
physics,
high,
medium,
low,
impostor,
decomp,
base_hull,
upload_skin,
upload_joints,
nowrite);
os.close();
return header;
}
//static
LLSD LLModel::writeModel(
std::ostream& ostr,
@ -1405,8 +1341,7 @@ LLSD LLModel::writeModel(
LLModel* medium,
LLModel* low,
LLModel* impostor,
const convex_hull_decomposition& decomp,
const hull& base_hull,
const LLModel::Decomposition& decomp,
BOOL upload_skin,
BOOL upload_joints,
BOOL nowrite)
@ -1429,119 +1364,10 @@ LLSD LLModel::writeModel(
mdl["skin"] = high->mSkinInfo.asLLSD(upload_joints);
}
if (!decomp.empty() || !base_hull.empty())
if (!decomp.mBaseHull.empty() ||
!decomp.mHull.empty())
{
//write decomposition block
// ["decomposition"]["HullList"] -- list of 8 bit integers, each entry represents a hull with specified number of points
// ["decomposition"]["PositionDomain"]["Min"/"Max"]
// ["decomposition"]["Position"] -- list of 16-bit integers to be decoded to given domain, encoded 3D points
// ["decomposition"]["Hull"] -- list of 16-bit integers to be decoded to given domain, encoded 3D points representing a single hull approximation of given shape
//get minimum and maximum
LLVector3 min;
if (decomp.empty())
{
min = base_hull[0];
}
else
{
min = decomp[0][0];
}
LLVector3 max = min;
LLSD::Binary hulls(decomp.size());
U32 total = 0;
for (U32 i = 0; i < decomp.size(); ++i)
{
U32 size = decomp[i].size();
total += size;
hulls[i] = (U8) (size);
for (U32 j = 0; j < decomp[i].size(); ++j)
{
update_min_max(min, max, decomp[i][j]);
}
}
for (U32 i = 0; i < base_hull.size(); ++i)
{
update_min_max(min, max, base_hull[i]);
}
mdl["decomposition"]["Min"] = min.getValue();
mdl["decomposition"]["Max"] = max.getValue();
if (!hulls.empty())
{
mdl["decomposition"]["HullList"] = hulls;
}
if (total > 0)
{
LLSD::Binary p(total*3*2);
LLVector3 range = max-min;
U32 vert_idx = 0;
for (U32 i = 0; i < decomp.size(); ++i)
{
for (U32 j = 0; j < decomp[i].size(); ++j)
{
for (U32 k = 0; k < 3; k++)
{
//convert to 16-bit normalized across domain
U16 val = (U16) (((decomp[i][j].mV[k]-min.mV[k])/range.mV[k])*65535);
U8* buff = (U8*) &val;
//write to binary buffer
p[vert_idx++] = buff[0];
p[vert_idx++] = buff[1];
if (vert_idx > p.size())
{
llerrs << "WTF?" << llendl;
}
}
}
}
mdl["decomposition"]["Position"] = p;
}
if (!base_hull.empty())
{
LLSD::Binary p(base_hull.size()*3*2);
LLVector3 range = max-min;
U32 vert_idx = 0;
for (U32 j = 0; j < base_hull.size(); ++j)
{
for (U32 k = 0; k < 3; k++)
{
//convert to 16-bit normalized across domain
U16 val = (U16) (((base_hull[j].mV[k]-min.mV[k])/range.mV[k])*65535);
U8* buff = (U8*) &val;
//write to binary buffer
p[vert_idx++] = buff[0];
p[vert_idx++] = buff[1];
if (vert_idx > p.size())
{
llerrs << "WTF?" << llendl;
}
}
}
mdl["decomposition"]["Hull"] = p;
}
mdl["decomposition"] = decomp.asLLSD();
}
for (U32 idx = 0; idx < MODEL_NAMES_LENGTH; ++idx)
@ -1906,7 +1732,11 @@ void LLModel::updateHullCenters()
mHullPoints += mPhysics.mHull[i].size();
}
mCenterOfHullCenters *= 1.f / mHullPoints;
if (mHullPoints > 0)
{
mCenterOfHullCenters *= 1.f / mHullPoints;
llassert(mPhysics.asLLSD().has("HullList"));
}
}
bool LLModel::loadModel(std::istream& is)
@ -2182,19 +2012,33 @@ void LLModel::Decomposition::fromLLSD(LLSD& decomp)
max.setValue(decomp["Max"]);
range = max-min;
for (U32 i = 0; i < hulls.size(); ++i)
{
U16 count = (hulls[i] == 0) ? 256 : hulls[i];
std::set<U64> valid;
//must have at least 4 points
llassert(count > 3);
for (U32 j = 0; j < count; ++j)
{
U64 test = (U64) p[0] | ((U64) p[1] << 16) | ((U64) p[2] << 32);
//point must be unique
//llassert(valid.find(test) == valid.end());
valid.insert(test);
mHull[i].push_back(LLVector3(
(F32) p[0]/65535.f*range.mV[0]+min.mV[0],
(F32) p[1]/65535.f*range.mV[1]+min.mV[1],
(F32) p[2]/65535.f*range.mV[2]+min.mV[2]));
p += 3;
}
}
//each hull must contain at least 4 unique points
llassert(valid.size() > 3);
}
}
@ -2208,8 +2052,17 @@ void LLModel::Decomposition::fromLLSD(LLSD& decomp)
LLVector3 max;
LLVector3 range;
min.setValue(decomp["Min"]);
max.setValue(decomp["Max"]);
if (decomp.has("Min"))
{
min.setValue(decomp["Min"]);
max.setValue(decomp["Max"]);
}
else
{
min.set(-0.5f, -0.5f, -0.5f);
max.set(0.5f, 0.5f, 0.5f);
}
range = max-min;
U16 count = position.size()/6;
@ -2229,7 +2082,145 @@ void LLModel::Decomposition::fromLLSD(LLSD& decomp)
//but contains no base hull
mBaseHullMesh.clear();;
}
}
LLSD LLModel::Decomposition::asLLSD() const
{
LLSD ret;
if (mBaseHull.empty() && mHull.empty())
{ //nothing to write
return ret;
}
//write decomposition block
// ["decomposition"]["HullList"] -- list of 8 bit integers, each entry represents a hull with specified number of points
// ["decomposition"]["PositionDomain"]["Min"/"Max"]
// ["decomposition"]["Position"] -- list of 16-bit integers to be decoded to given domain, encoded 3D points
// ["decomposition"]["Hull"] -- list of 16-bit integers to be decoded to given domain, encoded 3D points representing a single hull approximation of given shape
//get minimum and maximum
LLVector3 min;
if (mHull.empty())
{
min = mBaseHull[0];
}
else
{
min = mHull[0][0];
}
LLVector3 max = min;
LLSD::Binary hulls(mHull.size());
U32 total = 0;
for (U32 i = 0; i < mHull.size(); ++i)
{
U32 size = mHull[i].size();
total += size;
hulls[i] = (U8) (size);
for (U32 j = 0; j < mHull[i].size(); ++j)
{
update_min_max(min, max, mHull[i][j]);
}
}
for (U32 i = 0; i < mBaseHull.size(); ++i)
{
update_min_max(min, max, mBaseHull[i]);
}
ret["Min"] = min.getValue();
ret["Max"] = max.getValue();
if (!hulls.empty())
{
ret["HullList"] = hulls;
}
if (total > 0)
{
LLSD::Binary p(total*3*2);
LLVector3 range = max-min;
U32 vert_idx = 0;
for (U32 i = 0; i < mHull.size(); ++i)
{
std::set<U64> valid;
llassert(!mHull[i].empty());
for (U32 j = 0; j < mHull[i].size(); ++j)
{
U64 test = 0;
for (U32 k = 0; k < 3; k++)
{
//convert to 16-bit normalized across domain
U16 val = (U16) (((mHull[i][j].mV[k]-min.mV[k])/range.mV[k])*65535);
switch (k)
{
case 0: test = test | (U64) val; break;
case 1: test = test | ((U64) val << 16); break;
case 2: test = test | ((U64) val << 32); break;
};
valid.insert(test);
U8* buff = (U8*) &val;
//write to binary buffer
p[vert_idx++] = buff[0];
p[vert_idx++] = buff[1];
//makes sure we haven't run off the end of the array
llassert(vert_idx <= p.size());
}
}
//must have at least 4 unique points
llassert(valid.size() > 3);
}
ret["Position"] = p;
}
if (!mBaseHull.empty())
{
LLSD::Binary p(mBaseHull.size()*3*2);
LLVector3 range = max-min;
U32 vert_idx = 0;
for (U32 j = 0; j < mBaseHull.size(); ++j)
{
for (U32 k = 0; k < 3; k++)
{
//convert to 16-bit normalized across domain
U16 val = (U16) (((mBaseHull[j].mV[k]-min.mV[k])/range.mV[k])*65535);
U8* buff = (U8*) &val;
//write to binary buffer
p[vert_idx++] = buff[0];
p[vert_idx++] = buff[1];
if (vert_idx > p.size())
{
llerrs << "WTF?" << llendl;
}
}
}
ret["Hull"] = p;
}
return ret;
}
void LLModel::Decomposition::merge(const LLModel::Decomposition* rhs)
@ -2256,5 +2247,10 @@ void LLModel::Decomposition::merge(const LLModel::Decomposition* rhs)
{ //take physics shape mesh from rhs
mPhysicsShapeMesh = rhs->mPhysicsShapeMesh;
}
if (!mHull.empty())
{ //verify
llassert(asLLSD().has("HullList"));
}
}

View File

@ -71,38 +71,53 @@ public:
//convex_hull_decomposition is a vector of convex hulls
//each convex hull is a set of points
typedef std::vector<std::vector<LLVector3> > convex_hull_decomposition;
typedef std::vector<std::vector<LLVector3> > convex_hull_decomposition;
typedef std::vector<LLVector3> hull;
class PhysicsMesh
{
public:
std::vector<LLVector3> mPositions;
std::vector<LLVector3> mNormals;
void clear()
{
mPositions.clear();
mNormals.clear();
}
bool empty() const
{
return mPositions.empty();
}
};
class Decomposition
{
public:
Decomposition() { }
Decomposition(LLSD& data);
void fromLLSD(LLSD& data);
LLSD asLLSD() const;
void merge(const Decomposition* rhs);
LLUUID mMeshID;
LLModel::convex_hull_decomposition mHull;
LLModel::hull mBaseHull;
std::vector<LLModel::PhysicsMesh> mMesh;
LLModel::PhysicsMesh mBaseHullMesh;
LLModel::PhysicsMesh mPhysicsShapeMesh;
};
LLModel(LLVolumeParams& params, F32 detail);
~LLModel();
bool loadModel(std::istream& is);
bool loadSkinInfo(LLSD& header, std::istream& is);
bool loadDecomposition(LLSD& header, std::istream& is);
static LLSD writeModel(
std::string filename,
LLModel* physics,
LLModel* high,
LLModel* medium,
LLModel* low,
LLModel* imposotr,
const LLModel::convex_hull_decomposition& convex_hull_decomposition,
const LLModel::hull& base_hull,
BOOL upload_skin,
BOOL upload_joints,
BOOL nowrite = FALSE);
static LLSD writeModel(
std::string filename,
LLModel* physics,
LLModel* high,
LLModel* medium,
LLModel* low,
LLModel* imposotr,
const LLModel::convex_hull_decomposition& convex_hull_decomposition,
BOOL upload_skin,
BOOL upload_joints,
BOOL nowrite = FALSE);
static LLSD writeModel(
std::ostream& ostr,
LLModel* physics,
@ -110,11 +125,11 @@ public:
LLModel* medium,
LLModel* low,
LLModel* imposotr,
const LLModel::convex_hull_decomposition& convex_hull_decomposition,
const LLModel::hull& base_hull,
const LLModel::Decomposition& decomp,
BOOL upload_skin,
BOOL upload_joints,
BOOL nowrite = FALSE);
static LLSD writeModelToStream(
std::ostream& ostr,
LLSD& mdl,
@ -220,42 +235,6 @@ public:
//ID for storing this model in a .slm file
S32 mLocalID;
class PhysicsMesh
{
public:
std::vector<LLVector3> mPositions;
std::vector<LLVector3> mNormals;
void clear()
{
mPositions.clear();
mNormals.clear();
}
bool empty() const
{
return mPositions.empty();
}
};
class Decomposition
{
public:
Decomposition() { }
Decomposition(LLSD& data);
void fromLLSD(LLSD& data);
void merge(const Decomposition* rhs);
LLUUID mMeshID;
LLModel::convex_hull_decomposition mHull;
LLModel::hull mBaseHull;
std::vector<LLModel::PhysicsMesh> mMesh;
LLModel::PhysicsMesh mBaseHullMesh;
LLModel::PhysicsMesh mPhysicsShapeMesh;
};
Decomposition mPhysics;
protected:

View File

@ -8974,7 +8974,7 @@
<key>Type</key>
<string>F32</string>
<key>Value</key>
<real>2.0</real>
<real>3.0</real>
</map>
<key>MeshThreadCount</key>
<map>

View File

@ -1093,7 +1093,7 @@ LLModelLoader::LLModelLoader(std::string filename, S32 lod, LLModelPreview* prev
{
//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();
mTrySLM = gSavedSettings.getBOOL("MeshImportUseSLM") && mPreview->mUploadData.empty();
mPreview->setLoadState(STARTING);
}
else
@ -1889,6 +1889,14 @@ void LLModelLoader::loadModelCallback()
{ //wait until this thread is stopped before deleting self
apr_sleep(100);
}
//cleanup model loader
if (mPreview)
{
mPreview->mModelLoader = NULL;
}
delete this;
}
void LLModelLoader::handlePivotPoint( daeElement* pRoot )
@ -2518,13 +2526,13 @@ 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]->mPhysics.mHull :
instance.mModel->mPhysics.mHull;
instance.mLOD[LLModel::LOD_PHYSICS]->mPhysics :
instance.mModel->mPhysics;
LLSD ret = LLModel::writeModel(
"",
std::stringstream ostr;
LLSD ret = LLModel::writeModel(ostr,
instance.mLOD[4],
instance.mLOD[3],
instance.mLOD[2],
@ -2536,10 +2544,10 @@ U32 LLModelPreview::calcResourceCost()
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
@ -2737,10 +2745,10 @@ void LLModelPreview::saveUploadData(const std::string& filename, bool save_skinw
std::stringstream str;
LLModel::convex_hull_decomposition& decomp =
LLModel::Decomposition& decomp =
instance.mLOD[LLModel::LOD_PHYSICS].notNull() ?
instance.mLOD[LLModel::LOD_PHYSICS]->mPhysics.mHull :
instance.mModel->mPhysics.mHull;
instance.mLOD[LLModel::LOD_PHYSICS]->mPhysics :
instance.mModel->mPhysics;
LLModel::writeModel(str,
instance.mLOD[LLModel::LOD_PHYSICS],
@ -2749,7 +2757,7 @@ void LLModelPreview::saveUploadData(const std::string& filename, bool save_skinw
instance.mLOD[LLModel::LOD_LOW],
instance.mLOD[LLModel::LOD_IMPOSTOR],
decomp,
empty_hull, save_skinweights, save_joint_positions);
save_skinweights, save_joint_positions);
data["mesh"][instance.mModel->mLocalID] = str.str();

View File

@ -1535,8 +1535,6 @@ void LLMeshRepoThread::notifyLoadedMeshes()
S32 LLMeshRepoThread::getActualMeshLOD(const LLVolumeParams& mesh_params, S32 lod)
{ //only ever called from main thread
lod = llclamp(lod, 0, 3);
LLMutexLock lock(mHeaderMutex);
mesh_header_map::iterator iter = mMeshHeader.find(mesh_params.getSculptID());
@ -1544,42 +1542,50 @@ S32 LLMeshRepoThread::getActualMeshLOD(const LLVolumeParams& mesh_params, S32 lo
{
LLSD& header = iter->second;
if (header.has("404"))
{
return -1;
}
if (header[header_lod[lod]]["size"].asInteger() > 0)
{
return lod;
}
//search down to find the next available lower lod
for (S32 i = lod-1; i >= 0; --i)
{
if (header[header_lod[i]]["size"].asInteger() > 0)
{
return i;
}
}
//search up to find then ext available higher lod
for (S32 i = lod+1; i < 4; ++i)
{
if (header[header_lod[i]]["size"].asInteger() > 0)
{
return i;
}
}
//header exists and no good lod found, treat as 404
header["404"] = 1;
return -1;
return LLMeshRepository::getActualMeshLOD(header, lod);
}
return lod;
}
//static
S32 LLMeshRepository::getActualMeshLOD(LLSD& header, S32 lod)
{
lod = llclamp(lod, 0, 3);
if (header.has("404"))
{
return -1;
}
if (header[header_lod[lod]]["size"].asInteger() > 0)
{
return lod;
}
//search down to find the next available lower lod
for (S32 i = lod-1; i >= 0; --i)
{
if (header[header_lod[i]]["size"].asInteger() > 0)
{
return i;
}
}
//search up to find then ext available higher lod
for (S32 i = lod+1; i < 4; ++i)
{
if (header[header_lod[i]]["size"].asInteger() > 0)
{
return i;
}
}
//header exists and no good lod found, treat as 404
header["404"] = 1;
return -1;
}
U32 LLMeshRepoThread::getResourceCost(const LLUUID& mesh_id)
{
LLMutexLock lock(mHeaderMutex);
@ -2514,12 +2520,12 @@ bool LLMeshRepository::hasPhysicsShape(const LLUUID& mesh_id)
return mesh.has("physics_shape") && mesh["physics_shape"].has("size") && (mesh["physics_shape"]["size"].asInteger() > 0);
}
const LLSD& LLMeshRepository::getMeshHeader(const LLUUID& mesh_id)
LLSD& LLMeshRepository::getMeshHeader(const LLUUID& mesh_id)
{
return mThread->getMeshHeader(mesh_id);
}
const LLSD& LLMeshRepoThread::getMeshHeader(const LLUUID& mesh_id)
LLSD& LLMeshRepoThread::getMeshHeader(const LLUUID& mesh_id)
{
static LLSD dummy_ret;
if (mesh_id.notNull())
@ -2577,12 +2583,10 @@ void LLMeshUploadThread::sendCostRequest(LLMeshUploadData& data)
//write model file to memory buffer
std::stringstream ostr;
LLModel::convex_hull_decomposition& decomp =
LLModel::Decomposition& decomp =
data.mModel[LLModel::LOD_PHYSICS].notNull() ?
data.mModel[LLModel::LOD_PHYSICS]->mPhysics.mHull :
data.mBaseModel->mPhysics.mHull;
LLModel::hull dummy_hull;
data.mModel[LLModel::LOD_PHYSICS]->mPhysics :
data.mBaseModel->mPhysics;
LLSD header = LLModel::writeModel(
ostr,
@ -2592,7 +2596,6 @@ void LLMeshUploadThread::sendCostRequest(LLMeshUploadData& data)
data.mModel[LLModel::LOD_LOW],
data.mModel[LLModel::LOD_IMPOSTOR],
decomp,
dummy_hull,
mUploadSkin,
mUploadJoints,
true);
@ -2678,10 +2681,12 @@ void LLMeshUploadThread::doUploadModel(LLMeshUploadData& data)
{
std::stringstream ostr;
LLModel::convex_hull_decomposition& decomp =
LLModel::Decomposition& decomp =
data.mModel[LLModel::LOD_PHYSICS].notNull() ?
data.mModel[LLModel::LOD_PHYSICS]->mPhysics.mHull :
data.mBaseModel->mPhysics.mHull;
data.mModel[LLModel::LOD_PHYSICS]->mPhysics :
data.mBaseModel->mPhysics;
decomp.mBaseHull = mHullMap[data.mBaseModel];
LLModel::writeModel(
ostr,
@ -2691,7 +2696,6 @@ void LLMeshUploadThread::doUploadModel(LLMeshUploadData& data)
data.mModel[LLModel::LOD_LOW],
data.mModel[LLModel::LOD_IMPOSTOR],
decomp,
mHullMap[data.mBaseModel],
mUploadSkin,
mUploadJoints);
@ -2939,17 +2943,36 @@ void LLMeshRepository::uploadError(LLSD& args)
}
//static
F32 LLMeshRepository::getStreamingCost(const LLSD& header, F32 radius)
F32 LLMeshRepository::getStreamingCost(LLSD& header, F32 radius, S32* bytes, S32* bytes_visible, S32 lod)
{
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 dlowest = llmin(radius/0.03f, 256.f);
F32 dlow = llmin(radius/0.06f, 256.f);
F32 dmid = llmin(radius/0.24f, 256.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)
{
*bytes = 0;
*bytes += header["lowest_lod"]["size"].asInteger();
*bytes += header["low_lod"]["size"].asInteger();
*bytes += header["medium_lod"]["size"].asInteger();
*bytes += header["high_lod"]["size"].asInteger();
}
if (bytes_visible)
{
lod = LLMeshRepository::getActualMeshLOD(header, lod);
if (lod >= 0 && lod <= 3)
{
*bytes_visible = header[header_lod[lod]]["size"].asInteger();
}
}
if (bytes_high == 0.f)
{
return 0.f;

View File

@ -318,7 +318,7 @@ public:
bool skinInfoReceived(const LLUUID& mesh_id, U8* data, S32 data_size);
bool decompositionReceived(const LLUUID& mesh_id, U8* data, S32 data_size);
bool physicsShapeReceived(const LLUUID& mesh_id, U8* data, S32 data_size);
const LLSD& getMeshHeader(const LLUUID& mesh_id);
LLSD& getMeshHeader(const LLUUID& mesh_id);
void notifyLoadedMeshes();
S32 getActualMeshLOD(const LLVolumeParams& mesh_params, S32 lod);
@ -434,7 +434,7 @@ public:
static U32 sCacheBytesWritten;
static U32 sPeakKbps;
static F32 getStreamingCost(const LLSD& header, F32 radius);
static F32 getStreamingCost(LLSD& header, F32 radius, S32* bytes = NULL, S32* visible_bytes = NULL, S32 detail = -1);
LLMeshRepository();
@ -452,6 +452,7 @@ public:
void notifyDecompositionReceived(LLModel::Decomposition* info);
S32 getActualMeshLOD(const LLVolumeParams& mesh_params, S32 lod);
static S32 getActualMeshLOD(LLSD& header, S32 lod);
U32 calcResourceCost(LLSD& header);
U32 getResourceCost(const LLUUID& mesh_params);
const LLMeshSkinInfo* getSkinInfo(const LLUUID& mesh_id);
@ -462,7 +463,7 @@ public:
void buildHull(const LLVolumeParams& params, S32 detail);
void buildPhysicsMesh(LLModel::Decomposition& decomp);
const LLSD& getMeshHeader(const LLUUID& mesh_id);
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

@ -6374,7 +6374,7 @@ BOOL LLObjectSelection::isEmpty() const
//-----------------------------------------------------------------------------
// getObjectCount() - returns number of non null objects
//-----------------------------------------------------------------------------
S32 LLObjectSelection::getObjectCount(BOOL mesh_adjust)
S32 LLObjectSelection::getObjectCount()
{
cleanupNodes();
S32 count = mList.size();
@ -6478,7 +6478,7 @@ F32 LLObjectSelection::getSelectedLinksetPhysicsCost()
return cost;
}
F32 LLObjectSelection::getSelectedObjectStreamingCost()
F32 LLObjectSelection::getSelectedObjectStreamingCost(S32* total_bytes, S32* visible_bytes)
{
F32 cost = 0.f;
for (list_t::iterator iter = mList.begin(); iter != mList.end(); ++iter)
@ -6488,7 +6488,19 @@ F32 LLObjectSelection::getSelectedObjectStreamingCost()
if (object)
{
cost += object->getStreamingCost();
S32 bytes = 0;
S32 visible = 0;
cost += object->getStreamingCost(&bytes, &visible);
if (total_bytes)
{
*total_bytes += bytes;
}
if (visible_bytes)
{
*visible_bytes += visible;
}
}
}

View File

@ -278,14 +278,14 @@ public:
LLSelectNode* findNode(LLViewerObject* objectp);
// count members
S32 getObjectCount(BOOL mesh_adjust = FALSE);
S32 getObjectCount();
F32 getSelectedObjectCost();
F32 getSelectedLinksetCost();
F32 getSelectedPhysicsCost();
F32 getSelectedLinksetPhysicsCost();
S32 getSelectedObjectRenderCost();
F32 getSelectedObjectStreamingCost();
F32 getSelectedObjectStreamingCost(S32* total_bytes = NULL, S32* visible_bytes = NULL);
U32 getSelectedObjectTriangleCount();
S32 getTECount();

View File

@ -3134,7 +3134,7 @@ F32 LLViewerObject::getLinksetPhysicsCost()
return mLinksetPhysicsCost;
}
F32 LLViewerObject::getStreamingCost()
F32 LLViewerObject::getStreamingCost(S32* bytes, S32* visible_bytes)
{
return 0.f;
}

View File

@ -326,7 +326,7 @@ public:
virtual void setScale(const LLVector3 &scale, BOOL damped = FALSE);
virtual F32 getStreamingCost();
virtual F32 getStreamingCost(S32* bytes = NULL, S32* visible_bytes = NULL);
virtual U32 getTriangleCount();
void setObjectCost(F32 cost);

View File

@ -493,6 +493,10 @@ public:
{
F32 cost = 0.f;
S32 count = 0;
S32 object_count = 0;
S32 total_bytes = 0;
S32 visible_bytes = 0;
const char* label = "Region";
if (LLSelectMgr::getInstance()->getSelection()->getObjectCount() == 0)
{ //region
@ -506,8 +510,13 @@ public:
object->getRegion() == region &&
object->getVolume())
{
cost += object->getStreamingCost();
object_count++;
S32 bytes = 0;
S32 visible = 0;
cost += object->getStreamingCost(&bytes, &visible);
count += object->getTriangleCount();
total_bytes += bytes;
visible_bytes += visible;
}
}
}
@ -515,12 +524,16 @@ public:
else
{
label = "Selection";
cost = LLSelectMgr::getInstance()->getSelection()->getSelectedObjectStreamingCost();
cost = LLSelectMgr::getInstance()->getSelection()->getSelectedObjectStreamingCost(&total_bytes, &visible_bytes);
count = LLSelectMgr::getInstance()->getSelection()->getSelectedObjectTriangleCount();
object_count = LLSelectMgr::getInstance()->getSelection()->getObjectCount();
}
addText(xpos,ypos, llformat("%s streaming cost: %.1f (%.1f KTris)",
label, cost, count/1000.f));
addText(xpos,ypos, llformat("%s streaming cost: %.1f", label, cost));
ypos += y_inc;
addText(xpos, ypos, llformat(" %.1f KTris, %.1f/%.1f KB, %d objects",
count/1024.f, visible_bytes/1024.f, total_bytes/1024.f, object_count));
ypos += y_inc;
}

View File

@ -3082,15 +3082,15 @@ U32 LLVOVolume::getRenderCost(std::set<LLUUID> &textures) const
}
F32 LLVOVolume::getStreamingCost()
F32 LLVOVolume::getStreamingCost(S32* bytes, S32* visible_bytes)
{
if (isMesh())
{
const LLSD& header = gMeshRepo.getMeshHeader(getVolume()->getParams().getSculptID());
LLSD& header = gMeshRepo.getMeshHeader(getVolume()->getParams().getSculptID());
F32 radius = getScale().length();
return LLMeshRepository::getStreamingCost(header, radius);
return LLMeshRepository::getStreamingCost(header, radius, bytes, visible_bytes, mLOD);
}
return 0.f;

View File

@ -130,7 +130,7 @@ public:
const LLMatrix3& getRelativeXformInvTrans() const { return mRelativeXformInvTrans; }
/*virtual*/ const LLMatrix4 getRenderMatrix() const;
U32 getRenderCost(std::set<LLUUID> &textures) const;
/*virtual*/ F32 getStreamingCost();
/*virtual*/ F32 getStreamingCost(S32* bytes = NULL, S32* visible_bytes = NULL);
/*virtual*/ U32 getTriangleCount();
/*virtual*/ BOOL lineSegmentIntersect(const LLVector3& start, const LLVector3& end,
S32 face = -1, // which face to check, -1 = ALL_SIDES