SH-477 Better mesh streaming cost estimation.
parent
1aecac62eb
commit
6b9a2d24cc
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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"));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -3134,7 +3134,7 @@ F32 LLViewerObject::getLinksetPhysicsCost()
|
|||
return mLinksetPhysicsCost;
|
||||
}
|
||||
|
||||
F32 LLViewerObject::getStreamingCost()
|
||||
F32 LLViewerObject::getStreamingCost(S32* bytes, S32* visible_bytes)
|
||||
{
|
||||
return 0.f;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in New Issue