summaryrefslogtreecommitdiff
path: root/indra
diff options
context:
space:
mode:
Diffstat (limited to 'indra')
-rw-r--r--indra/llmath/llvolume.cpp37
-rw-r--r--indra/llmessage/message_prehash.cpp1
-rw-r--r--indra/llmessage/message_prehash.h1
-rw-r--r--indra/llprimitive/llmodel.cpp79
-rw-r--r--indra/llui/llresmgr.cpp2
-rw-r--r--indra/newview/app_settings/logcontrol.xml2
-rw-r--r--indra/newview/lldrawpoolavatar.cpp10
-rw-r--r--indra/newview/llface.cpp31
-rw-r--r--indra/newview/llfloatermodelpreview.cpp480
-rw-r--r--indra/newview/llfloatermodelwizard.cpp56
-rw-r--r--indra/newview/llfloaterregioninfo.cpp5
-rw-r--r--indra/newview/llfloatertools.cpp10
-rw-r--r--indra/newview/llmanipscale.cpp6
-rwxr-xr-x[-rw-r--r--]indra/newview/llmeshrepository.cpp651
-rw-r--r--indra/newview/llmeshrepository.h12
-rw-r--r--indra/newview/llpanelvolume.cpp15
-rw-r--r--indra/newview/llviewermenufile.cpp76
-rw-r--r--indra/newview/llviewermenufile.h17
-rw-r--r--indra/newview/llviewerregion.cpp73
-rw-r--r--indra/newview/llviewerregion.h7
-rw-r--r--indra/newview/llviewerwindow.cpp2
-rw-r--r--indra/newview/llvovolume.cpp2
22 files changed, 811 insertions, 764 deletions
diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp
index 9eecb7bfe2..8c81f27784 100644
--- a/indra/llmath/llvolume.cpp
+++ b/indra/llmath/llvolume.cpp
@@ -2419,12 +2419,25 @@ bool LLVolume::unpackVolumeFaces(std::istream& is, S32 size)
for (U32 i = 0; i < face_count; ++i)
{
+ LLVolumeFace& face = mVolumeFaces[i];
+
+ if (mdl[i].has("NoGeometry"))
+ { //face has no geometry, continue
+ face.resizeIndices(3);
+ face.resizeVertices(1);
+ memset(face.mPositions, 0, sizeof(LLVector4a));
+ memset(face.mNormals, 0, sizeof(LLVector4a));
+ memset(face.mTexCoords, 0, sizeof(LLVector2));
+ memset(face.mIndices, 0, sizeof(U16)*3);
+ continue;
+ }
+
LLSD::Binary pos = mdl[i]["Position"];
LLSD::Binary norm = mdl[i]["Normal"];
LLSD::Binary tc = mdl[i]["TexCoord0"];
LLSD::Binary idx = mdl[i]["TriangleList"];
- LLVolumeFace& face = mVolumeFaces[i];
+
//copy out indices
face.resizeIndices(idx.size()/2);
@@ -2629,14 +2642,20 @@ bool LLVolume::unpackVolumeFaces(std::istream& is, S32 size)
LLVector4a& min = face.mExtents[0];
LLVector4a& max = face.mExtents[1];
- min.clear();
- max.clear();
- min = max = face.mPositions[0];
-
- for (S32 i = 1; i < face.mNumVertices; ++i)
+ if (face.mNumVertices < 3)
+ { //empty face, use a dummy 1cm (at 1m scale) bounding box
+ min.splat(-0.005f);
+ max.splat(0.005f);
+ }
+ else
{
- min.setMin(min, face.mPositions[i]);
- max.setMax(max, face.mPositions[i]);
+ min = max = face.mPositions[0];
+
+ for (S32 i = 1; i < face.mNumVertices; ++i)
+ {
+ min.setMin(min, face.mPositions[i]);
+ max.setMax(max, face.mPositions[i]);
+ }
}
}
}
@@ -5493,6 +5512,8 @@ LLVolumeFace::LLVolumeFace() :
mOctree(NULL)
{
mExtents = (LLVector4a*) ll_aligned_malloc_16(sizeof(LLVector4a)*3);
+ mExtents[0].splat(-0.5f);
+ mExtents[1].splat(0.5f);
mCenter = mExtents+2;
}
diff --git a/indra/llmessage/message_prehash.cpp b/indra/llmessage/message_prehash.cpp
index 5d03615e53..6133f50637 100644
--- a/indra/llmessage/message_prehash.cpp
+++ b/indra/llmessage/message_prehash.cpp
@@ -742,6 +742,7 @@ char const* const _PREHASH_MoneyData = LLMessageStringTable::getInstance()->getS
char const* const _PREHASH_ObjectDeselect = LLMessageStringTable::getInstance()->getString("ObjectDeselect");
char const* const _PREHASH_NewAssetID = LLMessageStringTable::getInstance()->getString("NewAssetID");
char const* const _PREHASH_ObjectAdd = LLMessageStringTable::getInstance()->getString("ObjectAdd");
+char const* const _PREHASH_SimulatorFeatures = LLMessageStringTable::getInstance()->getString("SimulatorFeatures");
char const* const _PREHASH_RayEndIsIntersection = LLMessageStringTable::getInstance()->getString("RayEndIsIntersection");
char const* const _PREHASH_CompleteAuction = LLMessageStringTable::getInstance()->getString("CompleteAuction");
char const* const _PREHASH_CircuitCode = LLMessageStringTable::getInstance()->getString("CircuitCode");
diff --git a/indra/llmessage/message_prehash.h b/indra/llmessage/message_prehash.h
index 8dc86601e6..f94ee1ed22 100644
--- a/indra/llmessage/message_prehash.h
+++ b/indra/llmessage/message_prehash.h
@@ -742,6 +742,7 @@ extern char const* const _PREHASH_MoneyData;
extern char const* const _PREHASH_ObjectDeselect;
extern char const* const _PREHASH_NewAssetID;
extern char const* const _PREHASH_ObjectAdd;
+extern char const* const _PREHASH_SimulatorFeatures;
extern char const* const _PREHASH_RayEndIsIntersection;
extern char const* const _PREHASH_CompleteAuction;
extern char const* const _PREHASH_CircuitCode;
diff --git a/indra/llprimitive/llmodel.cpp b/indra/llprimitive/llmodel.cpp
index 9ae1bbacf1..b3d5c7b072 100644
--- a/indra/llprimitive/llmodel.cpp
+++ b/indra/llprimitive/llmodel.cpp
@@ -50,7 +50,7 @@ std::string model_names[] =
"low_lod",
"medium_lod",
"high_lod",
- "physics_shape"
+ "physics_mesh"
};
const int MODEL_NAMES_LENGTH = sizeof(model_names) / sizeof(std::string);
@@ -1418,7 +1418,11 @@ LLSD LLModel::writeModel(
if (!decomp.mBaseHull.empty() ||
!decomp.mHull.empty())
{
- mdl["decomposition"] = decomp.asLLSD();
+ mdl["physics_convex"] = decomp.asLLSD();
+ if (!decomp.mHull.empty())
+ { //convex decomposition exists, physics mesh will not be used
+ model[LLModel::LOD_PHYSICS] = NULL;
+ }
}
for (U32 idx = 0; idx < MODEL_NAMES_LENGTH; ++idx)
@@ -1443,8 +1447,9 @@ LLSD LLModel::writeModel(
for (S32 i = 0; i < model[idx]->getNumVolumeFaces(); ++i)
{ //for each face
const LLVolumeFace& face = model[idx]->getVolumeFace(i);
- if (!face.mNumVertices)
+ if (face.mNumVertices < 3)
{ //don't export an empty face
+ mdl[model_names[idx]][i]["NoGeometry"] = true;
continue;
}
LLSD::Binary verts(face.mNumVertices*3*2);
@@ -1477,7 +1482,6 @@ LLSD LLModel::writeModel(
//position + normal
for (U32 k = 0; k < 3; ++k)
{ //for each component
-
//convert to 16-bit normalized across domain
U16 val = (U16) (((pos[k]-min_pos.mV[k])/pos_range.mV[k])*65535);
@@ -1521,7 +1525,6 @@ LLSD LLModel::writeModel(
//write out face data
mdl[model_names[idx]][i]["PositionDomain"]["Min"] = min_pos.getValue();
mdl[model_names[idx]][i]["PositionDomain"]["Max"] = max_pos.getValue();
-
mdl[model_names[idx]][i]["TexCoord0Domain"]["Min"] = min_tc.getValue();
mdl[model_names[idx]][i]["TexCoord0Domain"]["Max"] = max_tc.getValue();
@@ -1614,15 +1617,15 @@ LLSD LLModel::writeModelToStream(std::ostream& ostr, LLSD& mdl, BOOL nowrite)
std::string decomposition;
- if (mdl.has("decomposition"))
+ if (mdl.has("physics_convex"))
{ //write out convex decomposition
- decomposition = zip_llsd(mdl["decomposition"]);
+ decomposition = zip_llsd(mdl["physics_convex"]);
U32 size = decomposition.size();
if (size > 0)
{
- header["decomposition"]["offset"] = (LLSD::Integer) cur_offset;
- header["decomposition"]["size"] = (LLSD::Integer) size;
+ header["physics_convex"]["offset"] = (LLSD::Integer) cur_offset;
+ header["physics_convex"]["size"] = (LLSD::Integer) size;
cur_offset += size;
bytes += size;
}
@@ -1643,11 +1646,6 @@ LLSD LLModel::writeModelToStream(std::ostream& ostr, LLSD& mdl, BOOL nowrite)
cur_offset += size;
bytes += size;
}
- else
- {
- header[model_names[i]]["offset"] = -1;
- header[model_names[i]]["size"] = 0;
- }
}
if (!nowrite)
@@ -1661,7 +1659,7 @@ LLSD LLModel::writeModelToStream(std::ostream& ostr, LLSD& mdl, BOOL nowrite)
if (!decomposition.empty())
{ //write decomposition block
- ostr.write((const char*) decomposition.data(), header["decomposition"]["size"].asInteger());
+ ostr.write((const char*) decomposition.data(), header["physics_convex"]["size"].asInteger());
}
for (S32 i = 0; i < MODEL_NAMES_LENGTH; i++)
@@ -1800,7 +1798,7 @@ bool LLModel::loadModel(std::istream& is)
"low_lod",
"medium_lod",
"high_lod",
- "physics_shape",
+ "physics_mesh",
};
const S32 MODEL_LODS = 5;
@@ -1899,8 +1897,8 @@ bool LLModel::loadSkinInfo(LLSD& header, std::istream &is)
bool LLModel::loadDecomposition(LLSD& header, std::istream& is)
{
- S32 offset = header["decomposition"]["offset"].asInteger();
- S32 size = header["decomposition"]["size"].asInteger();
+ S32 offset = header["physics_convex"]["offset"].asInteger();
+ S32 size = header["physics_convex"]["size"].asInteger();
if (offset >= 0 && size > 0)
{
@@ -2040,7 +2038,7 @@ void LLModel::Decomposition::fromLLSD(LLSD& decomp)
{
// updated for const-correctness. gcc is picky about this type of thing - Nyx
const LLSD::Binary& hulls = decomp["HullList"].asBinary();
- const LLSD::Binary& position = decomp["Position"].asBinary();
+ const LLSD::Binary& position = decomp["Positions"].asBinary();
U16* p = (U16*) &position[0];
@@ -2050,11 +2048,19 @@ 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;
-
for (U32 i = 0; i < hulls.size(); ++i)
{
U16 count = (hulls[i] == 0) ? 256 : hulls[i];
@@ -2070,6 +2076,7 @@ void LLModel::Decomposition::fromLLSD(LLSD& decomp)
//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],
@@ -2084,9 +2091,9 @@ void LLModel::Decomposition::fromLLSD(LLSD& decomp)
}
}
- if (decomp.has("Hull"))
+ if (decomp.has("BoundingVerts"))
{
- const LLSD::Binary& position = decomp["Hull"].asBinary();
+ const LLSD::Binary& position = decomp["BundingVerts"].asBinary();
U16* p = (U16*) &position[0];
@@ -2141,11 +2148,9 @@ LLSD LLModel::Decomposition::asLLSD() const
}
//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
-
+ // ["physics_convex"]["HullList"] -- list of 8 bit integers, each entry represents a hull with specified number of points
+ // ["physics_convex"]["Position"] -- list of 16-bit integers to be decoded to given domain, encoded 3D points
+ // ["physics_convex"]["BoundingVerts"] -- 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;
@@ -2194,6 +2199,8 @@ LLSD LLModel::Decomposition::asLLSD() const
{
LLSD::Binary p(total*3*2);
+ LLVector3 min(-0.5f, -0.5f, -0.5f);
+ LLVector3 max(0.5f, 0.5f, 0.5f);
LLVector3 range = max-min;
U32 vert_idx = 0;
@@ -2209,8 +2216,12 @@ LLSD LLModel::Decomposition::asLLSD() const
U64 test = 0;
for (U32 k = 0; k < 3; k++)
{
+ F32* src = (F32*) (mHull[i][j].mV);
+
+ llassert(src[k] <= 0.501f && src[k] >= -0.501f);
+
//convert to 16-bit normalized across domain
- U16 val = (U16) (((mHull[i][j].mV[k]-min.mV[k])/range.mV[k])*65535);
+ U16 val = (U16) (((src[k]-min.mV[k])/range.mV[k])*65535);
if(valid.size() < 3)
{
@@ -2238,13 +2249,15 @@ LLSD LLModel::Decomposition::asLLSD() const
llassert(valid.size() > 2);
}
- ret["Position"] = p;
+ ret["Positions"] = p;
}
if (!mBaseHull.empty())
{
LLSD::Binary p(mBaseHull.size()*3*2);
+ LLVector3 min(-0.5f, -0.5f, -0.5f);
+ LLVector3 max(0.5f, 0.5f, 0.5f);
LLVector3 range = max-min;
U32 vert_idx = 0;
@@ -2252,6 +2265,8 @@ LLSD LLModel::Decomposition::asLLSD() const
{
for (U32 k = 0; k < 3; k++)
{
+ llassert(mBaseHull[j].mV[k] <= 0.51f && mBaseHull[j].mV[k] >= -0.51f);
+
//convert to 16-bit normalized across domain
U16 val = (U16) (((mBaseHull[j].mV[k]-min.mV[k])/range.mV[k])*65535);
@@ -2267,7 +2282,7 @@ LLSD LLModel::Decomposition::asLLSD() const
}
}
- ret["Hull"] = p;
+ ret["BoundingVerts"] = p;
}
return ret;
diff --git a/indra/llui/llresmgr.cpp b/indra/llui/llresmgr.cpp
index 39385786bc..820e7cb26a 100644
--- a/indra/llui/llresmgr.cpp
+++ b/indra/llui/llresmgr.cpp
@@ -337,7 +337,7 @@ LLLocale::LLLocale(const std::string& locale_string)
char* new_locale_string = setlocale( LC_ALL, locale_string.c_str());
if ( new_locale_string == NULL)
{
- llwarns << "Failed to set locale " << locale_string << llendl;
+ LL_WARNS_ONCE("LLLocale") << "Failed to set locale " << locale_string << LL_ENDL;
setlocale(LC_ALL, SYSTEM_LOCALE.c_str());
}
//else
diff --git a/indra/newview/app_settings/logcontrol.xml b/indra/newview/app_settings/logcontrol.xml
index 937c4e4c6a..9f4e89691f 100644
--- a/indra/newview/app_settings/logcontrol.xml
+++ b/indra/newview/app_settings/logcontrol.xml
@@ -20,6 +20,7 @@
<key>tags</key>
<array>
<string>AppInit</string>
+ <string>Capabilities</string>
<string>SystemInfo</string>
<string>TextureCache</string>
<string>AppCache</string>
@@ -43,6 +44,7 @@
<array>
<!-- sample entry for debugging a specific item -->
<!-- <string>Voice</string> -->
+ <string>Capabilities</string>
</array>
</map>
</array>
diff --git a/indra/newview/lldrawpoolavatar.cpp b/indra/newview/lldrawpoolavatar.cpp
index 870aec4eff..9f790d03fe 100644
--- a/indra/newview/lldrawpoolavatar.cpp
+++ b/indra/newview/lldrawpoolavatar.cpp
@@ -459,14 +459,6 @@ S32 LLDrawPoolAvatar::getNumPasses()
{
return 10;
}
- if (LLPipeline::sImpostorRender)
- {
- return 1;
- }
- else
- {
- return 3;
- }
}
@@ -1419,7 +1411,7 @@ void LLDrawPoolAvatar::updateRiggedFaceVertexBuffer(LLVOAvatar* avatar, LLFace*
void LLDrawPoolAvatar::renderRigged(LLVOAvatar* avatar, U32 type, bool glow)
{
- if (avatar->isSelf() && !gAgent.needsRenderAvatar())
+ if (avatar->isSelf() && !gAgent.needsRenderAvatar() || !gMeshRepo.meshRezEnabled())
{
return;
}
diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp
index 540ed054e9..b6566fcbd0 100644
--- a/indra/newview/llface.cpp
+++ b/indra/newview/llface.cpp
@@ -693,6 +693,19 @@ static void xform(LLVector2 &tex_coord, F32 cosAng, F32 sinAng, F32 offS, F32 of
}
+bool less_than_max_mag(const LLVector4a& vec)
+{
+ LLVector4a MAX_MAG;
+ MAX_MAG.splat(1024.f*1024.f);
+
+ LLVector4a val;
+ val.setAbs(vec);
+
+ S32 lt = val.lessThan(MAX_MAG).getGatheredBits() & 0x7;
+
+ return lt == 0x7;
+}
+
BOOL LLFace::genVolumeBBoxes(const LLVolume &volume, S32 f,
const LLMatrix4& mat_vert_in, const LLMatrix3& mat_normal_in, BOOL global_volume)
{
@@ -727,6 +740,8 @@ BOOL LLFace::genVolumeBBoxes(const LLVolume &volume, S32 f,
min = face.mExtents[0];
max = face.mExtents[1];
+ llassert(less_than_max_mag(min));
+ llassert(less_than_max_mag(max));
//min, max are in volume space, convert to drawable render space
LLVector4a center;
@@ -738,6 +753,9 @@ BOOL LLFace::genVolumeBBoxes(const LLVolume &volume, S32 f,
size.setSub(max, min);
size.mul(0.5f);
+ llassert(less_than_max_mag(min));
+ llassert(less_than_max_mag(max));
+
if (!global_volume)
{
//VECTORIZE THIS
@@ -775,6 +793,8 @@ BOOL LLFace::genVolumeBBoxes(const LLVolume &volume, S32 f,
newMin = newMax = center;
+ llassert(less_than_max_mag(center));
+
for (U32 i = 0; i < 4; i++)
{
LLVector4a delta;
@@ -786,6 +806,9 @@ BOOL LLFace::genVolumeBBoxes(const LLVolume &volume, S32 f,
newMin.setMin(newMin,min);
newMax.setMax(newMax,max);
+
+ llassert(less_than_max_mag(newMin));
+ llassert(less_than_max_mag(newMax));
}
if (!mDrawablep->isActive())
@@ -794,14 +817,22 @@ BOOL LLFace::genVolumeBBoxes(const LLVolume &volume, S32 f,
offset.load3(mDrawablep->getRegion()->getOriginAgent().mV);
newMin.add(offset);
newMax.add(offset);
+
+ llassert(less_than_max_mag(newMin));
+ llassert(less_than_max_mag(newMax));
}
t.setAdd(newMin, newMax);
t.mul(0.5f);
+ llassert(less_than_max_mag(t));
+
//VECTORIZE THIS
mCenterLocal.set(t.getF32ptr());
+ llassert(less_than_max_mag(newMin));
+ llassert(less_than_max_mag(newMax));
+
t.setSub(newMax,newMin);
mBoundingSphereRadius = t.getLength3().getF32()*0.5f;
diff --git a/indra/newview/llfloatermodelpreview.cpp b/indra/newview/llfloatermodelpreview.cpp
index 75fa7b9d1f..751e06c743 100644
--- a/indra/newview/llfloatermodelpreview.cpp
+++ b/indra/newview/llfloatermodelpreview.cpp
@@ -178,6 +178,80 @@ std::string lod_label_name[NUM_LOD+1] =
"I went off the end of the lod_label_name array. Me so smart."
};
+
+#define LL_DEGENERACY_TOLERANCE 1e-7f
+
+inline F32 dot3fpu(const LLVector4a& a, const LLVector4a& b)
+{
+ volatile F32 p0 = a[0] * b[0];
+ volatile F32 p1 = a[1] * b[1];
+ volatile F32 p2 = a[2] * b[2];
+ return p0 + p1 + p2;
+}
+
+bool ll_is_degenerate(const LLVector4a& a, const LLVector4a& b, const LLVector4a& c, F32 tolerance = LL_DEGENERACY_TOLERANCE)
+{
+ // small area check
+ {
+ LLVector4a edge1; edge1.setSub( a, b );
+ LLVector4a edge2; edge2.setSub( a, c );
+ //////////////////////////////////////////////////////////////////////////
+ /// Linden Modified
+ //////////////////////////////////////////////////////////////////////////
+
+ // If no one edge is more than 10x longer than any other edge, we weaken
+ // the tolerance by a factor of 1e-4f.
+
+ LLVector4a edge3; edge3.setSub( c, b );
+ const F32 len1sq = edge1.dot3(edge1).getF32();
+ const F32 len2sq = edge2.dot3(edge2).getF32();
+ const F32 len3sq = edge3.dot3(edge3).getF32();
+ bool abOK = (len1sq <= 100.f * len2sq) && (len1sq <= 100.f * len3sq);
+ bool acOK = (len2sq <= 100.f * len1sq) && (len1sq <= 100.f * len3sq);
+ bool cbOK = (len3sq <= 100.f * len1sq) && (len1sq <= 100.f * len2sq);
+ if ( abOK && acOK && cbOK )
+ {
+ tolerance *= 1e-4f;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ /// End Modified
+ //////////////////////////////////////////////////////////////////////////
+
+ LLVector4a cross; cross.setCross3( edge1, edge2 );
+
+ LLVector4a edge1b; edge1b.setSub( b, a );
+ LLVector4a edge2b; edge2b.setSub( b, c );
+ LLVector4a crossb; crossb.setCross3( edge1b, edge2b );
+
+ if ( ( cross.dot3(cross).getF32() < tolerance ) || ( crossb.dot3(crossb).getF32() < tolerance ))
+ {
+ return true;
+ }
+ }
+
+ // point triangle distance check
+ {
+ LLVector4a Q; Q.setSub(a, b);
+ LLVector4a R; R.setSub(c, b);
+
+ const F32 QQ = dot3fpu(Q, Q);
+ const F32 RR = dot3fpu(R, R);
+ const F32 QR = dot3fpu(R, Q);
+
+ volatile F32 QQRR = QQ * RR;
+ volatile F32 QRQR = QR * QR;
+ F32 Det = (QQRR - QRQR);
+
+ if( Det == 0.0f )
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
bool validate_face(const LLVolumeFace& face)
{
for (U32 i = 0; i < face.mNumIndices; ++i)
@@ -189,6 +263,31 @@ bool validate_face(const LLVolumeFace& face)
}
}
+ if (face.mNumIndices % 3 != 0 || face.mNumIndices == 0)
+ {
+ llwarns << "Face has invalid number of indices." << llendl;
+ return false;
+ }
+
+ /*const LLVector4a scale(0.5f);
+
+ for (U32 i = 0; i < face.mNumIndices; i+=3)
+ {
+ U16 idx1 = face.mIndices[i];
+ U16 idx2 = face.mIndices[i+1];
+ U16 idx3 = face.mIndices[i+2];
+
+ LLVector4a v1; v1.setMul(face.mPositions[idx1], scale);
+ LLVector4a v2; v2.setMul(face.mPositions[idx2], scale);
+ LLVector4a v3; v3.setMul(face.mPositions[idx3], scale);
+
+ if (ll_is_degenerate(v1,v2,v3))
+ {
+ llwarns << "Degenerate face found!" << llendl;
+ return false;
+ }
+ }*/
+
return true;
}
@@ -1187,11 +1286,7 @@ void stretch_extents(LLModel* model, LLMatrix4& mat, LLVector3& min, LLVector3&
void LLModelLoader::run()
{
- if (!doLoadModel())
- {
- mPreview = NULL;
- }
-
+ doLoadModel();
doOnIdleOneTime(boost::bind(&LLModelLoader::loadModelCallback,this));
}
@@ -1322,7 +1417,7 @@ bool LLModelLoader::doLoadModel()
if(model->getStatus() != LLModel::NO_ERRORS)
{
setLoadState(ERROR_PARSING + model->getStatus()) ;
- return true ; //abort
+ return false; //abort
}
if (model.notNull() && validate_model(model))
@@ -2203,87 +2298,87 @@ bool LLModelLoader::isNodeAJoint( domNode* pNode )
//-----------------------------------------------------------------------------
// verifyCount
//-----------------------------------------------------------------------------
-bool LLModelPreview::verifyCount( int expected, int result )
-{
- if ( expected != result )
- {
- llinfos<< "Error: (expected/got)"<<expected<<"/"<<result<<"verts"<<llendl;
- return false;
- }
- return true;
-}
+bool LLModelPreview::verifyCount( int expected, int result )
+{
+ if ( expected != result )
+ {
+ llinfos<< "Error: (expected/got)"<<expected<<"/"<<result<<"verts"<<llendl;
+ return false;
+ }
+ return true;
+}
//-----------------------------------------------------------------------------
// verifyController
//-----------------------------------------------------------------------------
-bool LLModelPreview::verifyController( domController* pController )
-{
-
- bool result = true;
-
- domSkin* pSkin = pController->getSkin();
-
- if ( pSkin )
- {
- xsAnyURI & uri = pSkin->getSource();
- domElement* pElement = uri.getElement();
-
- if ( !pElement )
- {
- llinfos<<"Can't resolve skin source"<<llendl;
- return false;
- }
-
- daeString type_str = pElement->getTypeName();
- if ( stricmp(type_str, "geometry") == 0 )
- {
- //Skin is reference directly by geometry and get the vertex count from skin
- domSkin::domVertex_weights* pVertexWeights = pSkin->getVertex_weights();
- U32 vertexWeightsCount = pVertexWeights->getCount();
- domGeometry* pGeometry = (domGeometry*) (domElement*) uri.getElement();
- domMesh* pMesh = pGeometry->getMesh();
-
- if ( pMesh )
- {
- //Get vertex count from geometry
- domVertices* pVertices = pMesh->getVertices();
- if ( !pVertices )
- {
- llinfos<<"No vertices!"<<llendl;
- return false;
- }
-
- if ( pVertices )
- {
- xsAnyURI src = pVertices->getInput_array()[0]->getSource();
- domSource* pSource = (domSource*) (domElement*) src.getElement();
- U32 verticesCount = pSource->getTechnique_common()->getAccessor()->getCount();
- result = verifyCount( verticesCount, vertexWeightsCount );
- if ( !result )
- {
- return result;
- }
- }
- }
-
- U32 vcountCount = (U32) pVertexWeights->getVcount()->getValue().getCount();
- result = verifyCount( vcountCount, vertexWeightsCount );
- if ( !result )
- {
- return result;
- }
-
- domInputLocalOffset_Array& inputs = pVertexWeights->getInput_array();
- U32 sum = 0;
- for (size_t i=0; i<vcountCount; i++)
- {
- sum += pVertexWeights->getVcount()->getValue()[i];
- }
- result = verifyCount( sum * inputs.getCount(), (domInt) pVertexWeights->getV()->getValue().getCount() );
- }
- }
-
- return result;
-}
+bool LLModelPreview::verifyController( domController* pController )
+{
+
+ bool result = true;
+
+ domSkin* pSkin = pController->getSkin();
+
+ if ( pSkin )
+ {
+ xsAnyURI & uri = pSkin->getSource();
+ domElement* pElement = uri.getElement();
+
+ if ( !pElement )
+ {
+ llinfos<<"Can't resolve skin source"<<llendl;
+ return false;
+ }
+
+ daeString type_str = pElement->getTypeName();
+ if ( stricmp(type_str, "geometry") == 0 )
+ {
+ //Skin is reference directly by geometry and get the vertex count from skin
+ domSkin::domVertex_weights* pVertexWeights = pSkin->getVertex_weights();
+ U32 vertexWeightsCount = pVertexWeights->getCount();
+ domGeometry* pGeometry = (domGeometry*) (domElement*) uri.getElement();
+ domMesh* pMesh = pGeometry->getMesh();
+
+ if ( pMesh )
+ {
+ //Get vertex count from geometry
+ domVertices* pVertices = pMesh->getVertices();
+ if ( !pVertices )
+ {
+ llinfos<<"No vertices!"<<llendl;
+ return false;
+ }
+
+ if ( pVertices )
+ {
+ xsAnyURI src = pVertices->getInput_array()[0]->getSource();
+ domSource* pSource = (domSource*) (domElement*) src.getElement();
+ U32 verticesCount = pSource->getTechnique_common()->getAccessor()->getCount();
+ result = verifyCount( verticesCount, vertexWeightsCount );
+ if ( !result )
+ {
+ return result;
+ }
+ }
+ }
+
+ U32 vcountCount = (U32) pVertexWeights->getVcount()->getValue().getCount();
+ result = verifyCount( vcountCount, vertexWeightsCount );
+ if ( !result )
+ {
+ return result;
+ }
+
+ domInputLocalOffset_Array& inputs = pVertexWeights->getInput_array();
+ U32 sum = 0;
+ for (size_t i=0; i<vcountCount; i++)
+ {
+ sum += pVertexWeights->getVcount()->getValue()[i];
+ }
+ result = verifyCount( sum * inputs.getCount(), (domInt) pVertexWeights->getV()->getValue().getCount() );
+ }
+ }
+
+ return result;
+}
//-----------------------------------------------------------------------------
// extractTranslation()
@@ -2794,7 +2889,7 @@ LLModelPreview::~LLModelPreview()
{
if (mModelLoader)
{
- delete mModelLoader;
+ mModelLoader->mPreview = NULL;
mModelLoader = NULL;
}
//*HACK : *TODO : turn this back on when we understand why this crashes
@@ -3890,7 +3985,35 @@ void LLModelPreview::updateStatusMessages()
mMaxTriangleLimit = total_tris[LLModel::LOD_HIGH];
}
+ bool has_degenerate = false;
+ {//check for degenerate triangles in physics mesh
+ U32 lod = LLModel::LOD_PHYSICS;
+ const LLVector4a scale(0.5f);
+ for (U32 i = 0; i < mModel[lod].size() && !has_degenerate; ++i)
+ { //for each model in the lod
+ if (mModel[lod][i]->mPhysics.mHull.empty())
+ { //no decomp exists
+ S32 cur_submeshes = mModel[lod][i]->getNumVolumeFaces();
+ for (S32 j = 0; j < cur_submeshes && !has_degenerate; ++j)
+ { //for each submesh (face), add triangles and vertices to current total
+ const LLVolumeFace& face = mModel[lod][i]->getVolumeFace(j);
+ for (S32 k = 0; k < face.mNumIndices && !has_degenerate; )
+ {
+ LLVector4a v1; v1.setMul(face.mPositions[face.mIndices[k++]], scale);
+ LLVector4a v2; v2.setMul(face.mPositions[face.mIndices[k++]], scale);
+ LLVector4a v3; v3.setMul(face.mPositions[face.mIndices[k++]], scale);
+
+ if (ll_is_degenerate(v1,v2,v3))
+ {
+ has_degenerate = true;
+ }
+ }
+ }
+ }
+ }
+ }
+
mFMP->childSetTextArg("submeshes_info", "[SUBMESHES]", llformat("%d", total_submeshes[LLModel::LOD_HIGH]));
std::string mesh_status_na = mFMP->getString("mesh_status_na");
@@ -3991,7 +4114,10 @@ void LLModelPreview::updateStatusMessages()
for (U32 j = 0; upload_ok && j < mdl->mPhysics.mHull.size(); ++j)
{
- upload_ok = upload_ok && mdl->mPhysics.mHull[i].size() <= 256;
+ if (mdl->mPhysics.mHull[j].size() > 256)
+ {
+ upload_ok = false;
+ }
}
}
@@ -4015,7 +4141,7 @@ void LLModelPreview::updateStatusMessages()
}
const BOOL confirmed_checkbox = mFMP->getChild<LLCheckBoxCtrl>("confirm_checkbox")->getValue().asBoolean();
- if ( upload_ok && !errorStateFromLoader && skinAndRigOk && confirmed_checkbox)
+ if ( upload_ok && !errorStateFromLoader && skinAndRigOk && !has_degenerate && confirmed_checkbox)
{
mFMP->childEnable("ok_btn");
}
@@ -4740,39 +4866,43 @@ BOOL LLModelPreview::render()
LLModel::Decomposition& physics = model->mPhysics;
- if (physics.mMesh.empty())
- { //build vertex buffer for physics mesh
- gMeshRepo.buildPhysicsMesh(physics);
- }
-
- if (!physics.mMesh.empty())
- { //render hull instead of mesh
+ if (!physics.mHull.empty())
+ {
render_mesh = false;
- for (U32 i = 0; i < physics.mMesh.size(); ++i)
- {
- if (explode > 0.f)
+
+ if (physics.mMesh.empty())
+ { //build vertex buffer for physics mesh
+ gMeshRepo.buildPhysicsMesh(physics);
+ }
+
+ if (!physics.mMesh.empty())
+ { //render hull instead of mesh
+ for (U32 i = 0; i < physics.mMesh.size(); ++i)
{
- gGL.pushMatrix();
+ if (explode > 0.f)
+ {
+ gGL.pushMatrix();
- LLVector3 offset = model->mHullCenter[i]-model->mCenterOfHullCenters;
- offset *= explode;
+ LLVector3 offset = model->mHullCenter[i]-model->mCenterOfHullCenters;
+ offset *= explode;
- gGL.translatef(offset.mV[0], offset.mV[1], offset.mV[2]);
- }
+ gGL.translatef(offset.mV[0], offset.mV[1], offset.mV[2]);
+ }
- static std::vector<LLColor4U> hull_colors;
+ static std::vector<LLColor4U> hull_colors;
- if (i+1 >= hull_colors.size())
- {
- hull_colors.push_back(LLColor4U(rand()%128+127, rand()%128+127, rand()%128+127, 255));
- }
+ if (i+1 >= hull_colors.size())
+ {
+ hull_colors.push_back(LLColor4U(rand()%128+127, rand()%128+127, rand()%128+127, 255));
+ }
- glColor4ubv(hull_colors[i].mV);
- LLVertexBuffer::drawArrays(LLRender::TRIANGLES, physics.mMesh[i].mPositions, physics.mMesh[i].mNormals);
+ glColor4ubv(hull_colors[i].mV);
+ LLVertexBuffer::drawArrays(LLRender::TRIANGLES, physics.mMesh[i].mPositions, physics.mMesh[i].mNormals);
- if (explode > 0.f)
- {
- gGL.popMatrix();
+ if (explode > 0.f)
+ {
+ gGL.popMatrix();
+ }
}
}
}
@@ -4798,9 +4928,10 @@ BOOL LLModelPreview::render()
glColor3f(1.f, 1.f, 0.f);
- glLineWidth(3.f);
+ glLineWidth(2.f);
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
buffer->drawRange(LLRender::TRIANGLES, 0, buffer->getNumVerts()-1, buffer->getNumIndices(), 0);
+
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glLineWidth(1.f);
}
@@ -4809,6 +4940,80 @@ BOOL LLModelPreview::render()
gGL.popMatrix();
}
+ glLineWidth(3.f);
+ glPointSize(8.f);
+ gPipeline.enableLightsFullbright(LLColor4::white);
+ //show degenerate triangles
+ LLGLDepthTest depth(GL_TRUE, GL_TRUE, GL_ALWAYS);
+ LLGLDisable cull(GL_CULL_FACE);
+ glColor4f(1.f,0.f,0.f,1.f);
+ const LLVector4a scale(0.5f);
+
+ for (LLMeshUploadThread::instance_list::iterator iter = mUploadData.begin(); iter != mUploadData.end(); ++iter)
+ {
+ LLModelInstance& instance = *iter;
+
+ LLModel* model = instance.mLOD[LLModel::LOD_PHYSICS];
+
+ if (!model)
+ {
+ continue;
+ }
+
+ gGL.pushMatrix();
+ LLMatrix4 mat = instance.mTransform;
+
+ glMultMatrixf((GLfloat*) mat.mMatrix);
+
+
+ LLPhysicsDecomp* decomp = gMeshRepo.mDecompThread;
+ if (decomp)
+ {
+ LLMutexLock(decomp->mMutex);
+
+ LLModel::Decomposition& physics = model->mPhysics;
+
+ if (physics.mHull.empty())
+ {
+ if (mVertexBuffer[LLModel::LOD_PHYSICS].empty())
+ {
+ genBuffers(LLModel::LOD_PHYSICS, false);
+ }
+
+ for (U32 i = 0; i < mVertexBuffer[LLModel::LOD_PHYSICS][model].size(); ++i)
+ {
+ LLVertexBuffer* buffer = mVertexBuffer[LLModel::LOD_PHYSICS][model][i];
+
+ buffer->setBuffer(LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_TEXCOORD0);
+
+ LLStrider<LLVector3> pos_strider;
+ buffer->getVertexStrider(pos_strider, 0);
+ LLVector4a* pos = (LLVector4a*) pos_strider.get();
+
+ LLStrider<U16> idx;
+ buffer->getIndexStrider(idx, 0);
+
+ for (U32 i = 0; i < buffer->getNumIndices(); i += 3)
+ {
+ LLVector4a v1; v1.setMul(pos[*idx++], scale);
+ LLVector4a v2; v2.setMul(pos[*idx++], scale);
+ LLVector4a v3; v3.setMul(pos[*idx++], scale);
+
+ if (ll_is_degenerate(v1,v2,v3))
+ {
+ buffer->draw(LLRender::LINE_LOOP, 3, i);
+ buffer->draw(LLRender::POINTS, 3, i);
+ }
+ }
+ }
+ }
+ }
+
+ gGL.popMatrix();
+ }
+ glLineWidth(1.f);
+ glPointSize(1.f);
+ gPipeline.enableLightsPreview();
gGL.setSceneBlendType(LLRender::BT_ALPHA);
}
}
@@ -5094,54 +5299,7 @@ LLFloaterModelPreview::DecompRequest::DecompRequest(const std::string& stage, LL
mParams = sInstance->mDecompParams;
//copy out positions and indices
- if (mdl)
- {
- U16 index_offset = 0;
- U16 tri[3] ;
-
- mPositions.clear();
- mIndices.clear();
- mBBox[1] = LLVector3(F32_MIN, F32_MIN, F32_MIN) ;
- mBBox[0] = LLVector3(F32_MAX, F32_MAX, F32_MAX) ;
-
- //queue up vertex positions and indices
- for (S32 i = 0; i < mdl->getNumVolumeFaces(); ++i)
- {
- const LLVolumeFace& face = mdl->getVolumeFace(i);
- if (mPositions.size() + face.mNumVertices > 65535)
- {
- continue;
- }
-
- for (U32 j = 0; j < face.mNumVertices; ++j)
- {
- mPositions.push_back(LLVector3(face.mPositions[j].getF32ptr()));
- for(U32 k = 0 ; k < 3 ; k++)
- {
- mBBox[0].mV[k] = llmin(mBBox[0].mV[k], mPositions[j].mV[k]) ;
- mBBox[1].mV[k] = llmax(mBBox[1].mV[k], mPositions[j].mV[k]) ;
- }
- }
-
- updateTriangleAreaThreshold() ;
-
- for (U32 j = 0; j+2 < face.mNumIndices; j += 3)
- {
- tri[0] = face.mIndices[j] + index_offset ;
- tri[1] = face.mIndices[j + 1] + index_offset ;
- tri[2] = face.mIndices[j + 2] + index_offset ;
-
- if(isValidTriangle(tri[0], tri[1], tri[2]))
- {
- mIndices.push_back(tri[0]);
- mIndices.push_back(tri[1]);
- mIndices.push_back(tri[2]);
- }
- }
-
- index_offset += face.mNumVertices;
- }
- }
+ assignData(mdl) ;
}
void LLFloaterModelPreview::setStatusMessage(const std::string& msg)
diff --git a/indra/newview/llfloatermodelwizard.cpp b/indra/newview/llfloatermodelwizard.cpp
index e44737f39e..707c8288df 100644
--- a/indra/newview/llfloatermodelwizard.cpp
+++ b/indra/newview/llfloatermodelwizard.cpp
@@ -422,8 +422,11 @@ void LLFloaterModelWizard::executePhysicsStage(std::string stage_name)
{
LLModel* mdl = sInstance->mModelPreview->mModel[LLModel::LOD_PHYSICS][i];
DecompRequest* request = new DecompRequest(stage_name, mdl);
- sInstance->mCurRequest.insert(request);
- gMeshRepo.mDecompThread->submitRequest(request);
+ if(request->isValid())
+ {
+ sInstance->mCurRequest.insert(request);
+ gMeshRepo.mDecompThread->submitRequest(request);
+ }
}
}
}
@@ -438,54 +441,7 @@ LLFloaterModelWizard::DecompRequest::DecompRequest(const std::string& stage, LLM
mParams = sInstance->mDecompParams;
//copy out positions and indices
- if (mdl)
- {
- U16 index_offset = 0;
- U16 tri[3] ;
-
- mPositions.clear();
- mIndices.clear();
- mBBox[1] = LLVector3(F32_MIN, F32_MIN, F32_MIN) ;
- mBBox[0] = LLVector3(F32_MAX, F32_MAX, F32_MAX) ;
-
- //queue up vertex positions and indices
- for (S32 i = 0; i < mdl->getNumVolumeFaces(); ++i)
- {
- const LLVolumeFace& face = mdl->getVolumeFace(i);
- if (mPositions.size() + face.mNumVertices > 65535)
- {
- continue;
- }
-
- for (U32 j = 0; j < face.mNumVertices; ++j)
- {
- mPositions.push_back(LLVector3(face.mPositions[j].getF32ptr()));
- for(U32 k = 0 ; k < 3 ; k++)
- {
- mBBox[0].mV[k] = llmin(mBBox[0].mV[k], mPositions[j].mV[k]) ;
- mBBox[1].mV[k] = llmax(mBBox[1].mV[k], mPositions[j].mV[k]) ;
- }
- }
-
- updateTriangleAreaThreshold() ;
-
- for (U32 j = 0; j+2 < face.mNumIndices; j += 3)
- {
- tri[0] = face.mIndices[j] + index_offset ;
- tri[1] = face.mIndices[j + 1] + index_offset ;
- tri[2] = face.mIndices[j + 2] + index_offset ;
-
- if(isValidTriangle(tri[0], tri[1], tri[2]))
- {
- mIndices.push_back(tri[0]);
- mIndices.push_back(tri[1]);
- mIndices.push_back(tri[2]);
- }
- }
-
- index_offset += face.mNumVertices;
- }
- }
+ assignData(mdl) ;
}
diff --git a/indra/newview/llfloaterregioninfo.cpp b/indra/newview/llfloaterregioninfo.cpp
index fc6976755f..6b3e3088d5 100644
--- a/indra/newview/llfloaterregioninfo.cpp
+++ b/indra/newview/llfloaterregioninfo.cpp
@@ -82,6 +82,7 @@
#include "llvlcomposition.h"
#include "lltrans.h"
#include "llagentui.h"
+#include "llmeshrepository.h"
const S32 TERRAIN_TEXTURE_COUNT = 4;
const S32 CORNER_COUNT = 4;
@@ -590,9 +591,7 @@ bool LLPanelRegionGeneralInfo::refreshFromRegion(LLViewerRegion* region)
getChildView("im_btn")->setEnabled(allow_modify);
getChildView("manage_telehub_btn")->setEnabled(allow_modify);
- const bool enable_mesh = gSavedSettings.getBOOL("MeshEnabled") &&
- gAgent.getRegion() &&
- !gAgent.getRegion()->getCapability("GetMesh").empty();
+ const bool enable_mesh = gMeshRepo.meshRezEnabled();
getChildView("mesh_rez_enabled_check")->setVisible(enable_mesh);
getChildView("mesh_rez_enabled_check")->setEnabled(getChildView("mesh_rez_enabled_check")->getEnabled() && enable_mesh);
// Data gets filled in by processRegionInfo
diff --git a/indra/newview/llfloatertools.cpp b/indra/newview/llfloatertools.cpp
index edcb96314b..0d798afdcc 100644
--- a/indra/newview/llfloatertools.cpp
+++ b/indra/newview/llfloatertools.cpp
@@ -86,6 +86,7 @@
#include "llvovolume.h"
#include "lluictrlfactory.h"
#include "llaccountingquotamanager.h"
+#include "llmeshrepository.h"
// Globals
LLFloaterTools *gFloaterTools = NULL;
@@ -423,7 +424,8 @@ void LLFloaterTools::refresh()
// Refresh object and prim count labels
LLLocale locale(LLLocale::USER_LOCALE);
- if ((gAgent.getRegion() && (gAgent.getRegion()->getCapability("GetMesh").empty() || gAgent.getRegion()->getCapability("ObjectAdd").empty())) || !gSavedSettings.getBOOL("MeshEnabled"))
+#if 0
+ if (gMeshRepo.meshRezEnabled())
{
std::string obj_count_string;
LLResMgr::getInstance()->getIntegerString(obj_count_string, LLSelectMgr::getInstance()->getSelection()->getRootObjectCount());
@@ -447,6 +449,7 @@ void LLFloaterTools::refresh()
getChildView("RenderingCost")->setEnabled(have_selection && sShowObjectCost);
}
else
+#endif
{
// Get the number of objects selected
std::string root_object_count_string;
@@ -788,10 +791,7 @@ void LLFloaterTools::updatePopup(LLCoordGL center, MASK mask)
getChildView("Strength:")->setVisible( land_visible);
}
- bool show_mesh_cost = gAgent.getRegion() &&
- !gAgent.getRegion()->getCapability("GetMesh").empty() &&
- gSavedSettings.getBOOL("MeshEnabled") &&
- !gAgent.getRegion()->getCapability("ObjectAdd").empty();
+ bool show_mesh_cost = gMeshRepo.meshRezEnabled();
getChildView("obj_count")->setVisible( !land_visible && !show_mesh_cost);
getChildView("prim_count")->setVisible( !land_visible && !show_mesh_cost);
diff --git a/indra/newview/llmanipscale.cpp b/indra/newview/llmanipscale.cpp
index 673f28e01f..4eb94dfb8e 100644
--- a/indra/newview/llmanipscale.cpp
+++ b/indra/newview/llmanipscale.cpp
@@ -58,6 +58,7 @@
#include "llworld.h"
#include "v2math.h"
#include "llvoavatar.h"
+#include "llmeshrepository.h"
const F32 MAX_MANIP_SELECT_DISTANCE_SQUARED = 11.f * 11.f;
@@ -90,10 +91,7 @@ F32 get_default_max_prim_scale(bool is_flora)
{
// a bit of a hack, but if it's foilage, we don't want to use the
// new larger scale which would result in giant trees and grass
- if (gSavedSettings.getBOOL("MeshEnabled") &&
- gAgent.getRegion() &&
- !gAgent.getRegion()->getCapability("GetMesh").empty() &&
- !gAgent.getRegion()->getCapability("ObjectAdd").empty() &&
+ if (gMeshRepo.meshRezEnabled() &&
!is_flora)
{
return DEFAULT_MAX_PRIM_SCALE;
diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp
index 8f084b9bfc..9855a641ed 100644..100755
--- a/indra/newview/llmeshrepository.cpp
+++ b/indra/newview/llmeshrepository.cpp
@@ -61,6 +61,9 @@
#include "pipeline.h"
#include "llinventorymodel.h"
#include "llfoldertype.h"
+#include "llviewerparcelmgr.h"
+
+#include "boost/lexical_cast.hpp"
#ifndef LL_WINDOWS
#include "netdb.h"
@@ -85,6 +88,12 @@ U32 LLMeshRepository::sPeakKbps = 0;
const U32 MAX_TEXTURE_UPLOAD_RETRIES = 5;
+static S32 dump_num = 0;
+std::string make_dump_name(std::string prefix, S32 num)
+{
+ return prefix + boost::lexical_cast<std::string>(num) + std::string(".xml");
+
+}
void dumpLLSDToFile(const LLSD& content, std::string filename);
std::string header_lod[] =
@@ -459,6 +468,49 @@ public:
};
+void log_upload_error(const LLSD& content,std::string stage)
+{
+ if (content.has("error"))
+ {
+ const LLSD& err = content["error"];
+ llwarns << "mesh upload failed, stage " << stage
+ << " message " << err["message"].asString() << " id " << err["identifier"].asString()
+ << llendl;
+
+ if (content.has("errors"))
+ {
+ const LLSD& err_list = content["errors"];
+ for (LLSD::array_const_iterator it = err_list.beginArray();
+ it != err_list.endArray();
+ ++it)
+ {
+ const LLSD& err_entry = *it;
+ std::string index_info;
+ std::string texture_index_str = err_entry["TextureIndex"].asString();
+ if (!texture_index_str.empty())
+ {
+ index_info += " texture_index: " + texture_index_str;
+ }
+ std::string mesh_index_str = err_entry["MeshIndex"].asString();
+ if (!mesh_index_str.empty())
+ {
+ index_info += " mesh_index: " + mesh_index_str;
+ }
+ llwarns << "mesh err code " << err_entry["error"].asString()
+ << " message " << err_entry["message"]
+ << index_info
+ << llendl;
+ }
+ }
+ }
+ else
+ {
+ llwarns << "bad mesh, no error information available" << llendl;
+ }
+
+
+}
+
class LLModelObjectUploadResponder: public LLCurl::Responder
{
LLSD mObjectAsset;
@@ -498,18 +550,21 @@ public:
//assert_main_thread();
llinfos << "completed" << llendl;
mThread->mPendingUploads--;
- dumpLLSDToFile(content,"whole_model_fee_response.xml");
+ dumpLLSDToFile(content,make_dump_name("whole_model_fee_response_",dump_num));
+ llinfos << "LLWholeModelFeeResponder content: " << content << llendl;
if (isGoodStatus(status))
{
+ llinfos << "fee request succeeded" << llendl;
mThread->mWholeModelUploadURL = content["uploader"].asString();
}
else
{
- llinfos << "upload failed" << llendl;
+ llwarns << "fee request failed" << llendl;
+ log_upload_error(content,"fee");
mThread->mWholeModelUploadURL = "";
}
-
}
+
};
class LLWholeModelUploadResponder: public LLCurl::Responder
@@ -528,13 +583,22 @@ public:
const LLSD& content)
{
//assert_main_thread();
- llinfos << "upload completed" << llendl;
mThread->mPendingUploads--;
- dumpLLSDToFile(content,"whole_model_upload_response.xml");
+ dumpLLSDToFile(content,make_dump_name("whole_model_upload_response_",dump_num));
+ llinfos << "LLWholeModelUploadResponder content: " << content << llendl;
// requested "mesh" asset type isn't actually the type
// of the resultant object, fix it up here.
- mPostData["asset_type"] = "object";
- gMeshRepo.updateInventory(LLMeshRepository::inventory_data(mPostData,content));
+ if (isGoodStatus(status))
+ {
+ llinfos << "upload succeeded" << llendl;
+ mPostData["asset_type"] = "object";
+ gMeshRepo.updateInventory(LLMeshRepository::inventory_data(mPostData,content));
+ }
+ else
+ {
+ llwarns << "upload failed" << llendl;
+ log_upload_error(content,"upload");
+ }
}
};
@@ -829,8 +893,8 @@ bool LLMeshRepoThread::fetchMeshDecomposition(const LLUUID& mesh_id)
if (header_size > 0)
{
- S32 offset = header_size + mMeshHeader[mesh_id]["decomposition"]["offset"].asInteger();
- S32 size = mMeshHeader[mesh_id]["decomposition"]["size"].asInteger();
+ S32 offset = header_size + mMeshHeader[mesh_id]["physics_convex"]["offset"].asInteger();
+ S32 size = mMeshHeader[mesh_id]["physics_convex"]["size"].asInteger();
mHeaderMutex->unlock();
@@ -901,8 +965,8 @@ bool LLMeshRepoThread::fetchMeshPhysicsShape(const LLUUID& mesh_id)
if (header_size > 0)
{
- S32 offset = header_size + mMeshHeader[mesh_id]["physics_shape"]["offset"].asInteger();
- S32 size = mMeshHeader[mesh_id]["physics_shape"]["size"].asInteger();
+ S32 offset = header_size + mMeshHeader[mesh_id]["physics_mesh"]["offset"].asInteger();
+ S32 size = mMeshHeader[mesh_id]["physics_mesh"]["size"].asInteger();
mHeaderMutex->unlock();
@@ -1294,8 +1358,6 @@ LLMeshUploadThread::LLMeshUploadThread(LLMeshUploadThread::instance_list& data,
mOrigin = gAgent.getPositionAgent();
mHost = gAgent.getRegionHost();
- mUploadObjectAssetCapability = gAgent.getRegion()->getCapability("UploadObjectAsset");
- mNewInventoryCapability = gAgent.getRegion()->getCapability("NewFileAgentInventoryVariablePrice");
mWholeModelFeeCapability = gAgent.getRegion()->getCapability("NewFileAgentInventory");
mOrigin += gAgent.getAtAxis() * scale.magVec();
@@ -1315,35 +1377,7 @@ LLMeshUploadThread::DecompRequest::DecompRequest(LLModel* mdl, LLModel* base_mod
mThread = thread;
//copy out positions and indices
- if (mdl)
- {
- U16 index_offset = 0;
-
- mPositions.clear();
- mIndices.clear();
-
- //queue up vertex positions and indices
- for (S32 i = 0; i < mdl->getNumVolumeFaces(); ++i)
- {
- const LLVolumeFace& face = mdl->getVolumeFace(i);
- if (mPositions.size() + face.mNumVertices > 65535)
- {
- continue;
- }
-
- for (U32 j = 0; j < face.mNumVertices; ++j)
- {
- mPositions.push_back(LLVector3(face.mPositions[j].getF32ptr()));
- }
-
- for (U32 j = 0; j < face.mNumIndices; ++j)
- {
- mIndices.push_back(face.mIndices[j]+index_offset);
- }
-
- index_offset += face.mNumVertices;
- }
- }
+ assignData(mdl) ;
mThread->mFinalDecomp = this;
mThread->mPhysicsComplete = false;
@@ -1385,14 +1419,7 @@ BOOL LLMeshUploadThread::isDiscarded()
void LLMeshUploadThread::run()
{
- if (gSavedSettings.getBOOL("MeshUseWholeModelUpload"))
- {
- doWholeModelUpload();
- }
- else
- {
- doIterativeUpload();
- }
+ doWholeModelUpload();
}
void dumpLLSDToFile(const LLSD& content, std::string filename)
@@ -1431,9 +1458,13 @@ void LLMeshUploadThread::wholeModelToLLSD(LLSD& dest, bool include_textures)
{
LLMeshUploadData data;
data.mBaseModel = iter->first;
- LLModelInstance& instance = *(iter->second.begin());
- LLModel* model = instance.mModel;
- if (mesh_index.find(model) == mesh_index.end())
+ LLModelInstance& first_instance = *(iter->second.begin());
+ for (S32 i = 0; i < 5; i++)
+ {
+ data.mModel[i] = first_instance.mLOD[i];
+ }
+
+ if (mesh_index.find(data.mBaseModel) == mesh_index.end())
{
// Have not seen this model before - create a new mesh_list entry for it.
std::string model_name = data.mBaseModel->getName();
@@ -1466,107 +1497,116 @@ void LLMeshUploadThread::wholeModelToLLSD(LLSD& dest, bool include_textures)
std::string str = ostr.str();
res["mesh_list"][mesh_num] = LLSD::Binary(str.begin(),str.end());
- mesh_index[model] = mesh_num;
+ mesh_index[data.mBaseModel] = mesh_num;
mesh_num++;
}
+
+ // For all instances that use this model
+ for (instance_list::iterator instance_iter = iter->second.begin();
+ instance_iter != iter->second.end();
+ ++instance_iter)
+ {
+
+ LLModelInstance& instance = *instance_iter;
- LLSD instance_entry;
+ LLSD instance_entry;
- for (S32 i = 0; i < 5; i++)
- {
- data.mModel[i] = instance.mLOD[i];
- }
+ for (S32 i = 0; i < 5; i++)
+ {
+ data.mModel[i] = instance.mLOD[i];
+ }
- LLVector3 pos, scale;
- LLQuaternion rot;
- LLMatrix4 transformation = instance.mTransform;
- decomposeMeshMatrix(transformation,pos,rot,scale);
- instance_entry["position"] = ll_sd_from_vector3(pos);
- instance_entry["rotation"] = ll_sd_from_quaternion(rot);
- instance_entry["scale"] = ll_sd_from_vector3(scale);
+ LLVector3 pos, scale;
+ LLQuaternion rot;
+ LLMatrix4 transformation = instance.mTransform;
+ decomposeMeshMatrix(transformation,pos,rot,scale);
+ instance_entry["position"] = ll_sd_from_vector3(pos);
+ instance_entry["rotation"] = ll_sd_from_quaternion(rot);
+ instance_entry["scale"] = ll_sd_from_vector3(scale);
- instance_entry["material"] = LL_MCODE_WOOD;
- LLPermissions perm;
- perm.setOwnerAndGroup(gAgent.getID(), gAgent.getID(), LLUUID::null, false);
- perm.setCreator(gAgent.getID());
+ instance_entry["material"] = LL_MCODE_WOOD;
+ LLPermissions perm;
+ perm.setOwnerAndGroup(gAgent.getID(), gAgent.getID(), LLUUID::null, false);
+ perm.setCreator(gAgent.getID());
- perm.initMasks(PERM_ITEM_UNRESTRICTED | PERM_MOVE, //base
- PERM_ITEM_UNRESTRICTED | PERM_MOVE, //owner
- LLFloaterPerms::getEveryonePerms(),
- LLFloaterPerms::getGroupPerms(),
- LLFloaterPerms::getNextOwnerPerms());
- instance_entry["permissions"] = ll_create_sd_from_permissions(perm);
- instance_entry["physics_shape_type"] = (U8)(LLViewerObject::PHYSICS_SHAPE_CONVEX_HULL);
- instance_entry["mesh"] = mesh_index[model];
+ perm.initMasks(PERM_ITEM_UNRESTRICTED | PERM_MOVE, //base
+ PERM_ITEM_UNRESTRICTED | PERM_MOVE, //owner
+ LLFloaterPerms::getEveryonePerms(),
+ LLFloaterPerms::getGroupPerms(),
+ LLFloaterPerms::getNextOwnerPerms());
+ instance_entry["permissions"] = ll_create_sd_from_permissions(perm);
+ instance_entry["physics_shape_type"] = (U8)(LLViewerObject::PHYSICS_SHAPE_CONVEX_HULL);
+ instance_entry["mesh"] = mesh_index[data.mBaseModel];
- if (mUploadTextures)
- {
instance_entry["face_list"] = LLSD::emptyArray();
- for (S32 face_num = 0; face_num < model->getNumVolumeFaces(); face_num++)
+ for (S32 face_num = 0; face_num < data.mBaseModel->getNumVolumeFaces(); face_num++)
{
LLImportMaterial& material = instance.mMaterial[face_num];
LLSD face_entry = LLSD::emptyMap();
LLViewerFetchedTexture *texture = material.mDiffuseMap.get();
- if (texture != NULL)
+ if ((texture != NULL) &&
+ (textures.find(texture) == textures.end()))
{
- if (textures.find(texture) == textures.end())
- {
- textures.insert(texture);
- }
+ textures.insert(texture);
+ }
- std::stringstream ostr;
- if (include_textures) // otherwise data is blank.
+ std::stringstream texture_str;
+ if (texture != NULL && include_textures && mUploadTextures)
+ {
+ // Get binary rep of texture, if needed.
+ LLTextureUploadData data(texture, material.mDiffuseMapLabel);
+ if (!data.mTexture->isRawImageValid())
{
- LLTextureUploadData data(texture, material.mDiffuseMapLabel);
- if (!data.mTexture->isRawImageValid())
- {
- data.mTexture->reloadRawImage(data.mTexture->getDiscardLevel());
- }
-
- LLPointer<LLImageJ2C> upload_file =
- LLViewerTextureList::convertToUploadFile(data.mTexture->getRawImage());
- ostr.write((const char*) upload_file->getData(), upload_file->getDataSize());
+ data.mTexture->reloadRawImage(data.mTexture->getDiscardLevel());
}
+
+ LLPointer<LLImageJ2C> upload_file =
+ LLViewerTextureList::convertToUploadFile(data.mTexture->getRawImage());
+ texture_str.write((const char*) upload_file->getData(), upload_file->getDataSize());
+ }
- if (texture_index.find(texture) == texture_index.end())
- {
- texture_index[texture] = texture_num;
- std::string str = ostr.str();
- res["texture_list"][texture_num] = LLSD::Binary(str.begin(),str.end());
- texture_num++;
- }
+ if (texture != NULL &&
+ mUploadTextures &&
+ texture_index.find(texture) == texture_index.end())
+ {
+ texture_index[texture] = texture_num;
+ std::string str = texture_str.str();
+ res["texture_list"][texture_num] = LLSD::Binary(str.begin(),str.end());
+ texture_num++;
}
// Subset of TextureEntry fields.
- if (texture)
+ if (texture != NULL && mUploadTextures)
{
face_entry["image"] = texture_index[texture];
+ face_entry["scales"] = 1.0;
+ face_entry["scalet"] = 1.0;
+ face_entry["offsets"] = 0.0;
+ face_entry["offsett"] = 0.0;
+ face_entry["imagerot"] = 0.0;
}
- face_entry["scales"] = 1.0;
- face_entry["scalet"] = 1.0;
- face_entry["offsets"] = 0.0;
- face_entry["offsett"] = 0.0;
- face_entry["imagerot"] = 0.0;
- face_entry["colors"] = ll_sd_from_color4(material.mDiffuseColor);
+ face_entry["diffuse_color"] = ll_sd_from_color4(material.mDiffuseColor);
face_entry["fullbright"] = material.mFullbright;
instance_entry["face_list"][face_num] = face_entry;
- }
- }
+ }
- res["instance_list"][instance_num] = instance_entry;
- instance_num++;
+ res["instance_list"][instance_num] = instance_entry;
+ instance_num++;
+ }
}
result["asset_resources"] = res;
- dumpLLSDToFile(result,"whole_model.xml");
+ dumpLLSDToFile(result,make_dump_name("whole_model_",dump_num));
dest = result;
}
void LLMeshUploadThread::doWholeModelUpload()
{
+ dump_num++;
+
mCurlRequest = new LLCurlRequest();
// Queue up models for hull generation (viewer-side)
@@ -1601,7 +1641,10 @@ void LLMeshUploadThread::doWholeModelUpload()
llassert(physics != NULL);
DecompRequest* request = new DecompRequest(physics, data.mBaseModel, this);
- gMeshRepo.mDecompThread->submitRequest(request);
+ if(request->isValid())
+ {
+ gMeshRepo.mDecompThread->submitRequest(request);
+ }
}
while (!mPhysicsComplete)
@@ -1611,7 +1654,7 @@ void LLMeshUploadThread::doWholeModelUpload()
LLSD model_data;
wholeModelToLLSD(model_data,false);
- dumpLLSDToFile(model_data,"whole_model_fee_request.xml");
+ dumpLLSDToFile(model_data,make_dump_name("whole_model_fee_request_",dump_num));
mPendingUploads++;
LLCurlRequest::headers_t headers;
@@ -1633,7 +1676,7 @@ void LLMeshUploadThread::doWholeModelUpload()
LLSD full_model_data;
wholeModelToLLSD(full_model_data, true);
LLSD body = full_model_data["asset_resources"];
- dumpLLSDToFile(body,"whole_model_body.xml");
+ dumpLLSDToFile(body,make_dump_name("whole_model_body_",dump_num));
mCurlRequest->post(mWholeModelUploadURL, headers, body,
new LLWholeModelUploadResponder(this, model_data));
do
@@ -1649,163 +1692,6 @@ void LLMeshUploadThread::doWholeModelUpload()
mFinished = true;
}
-void LLMeshUploadThread::doIterativeUpload()
-{
- if(isDiscarded())
- {
- mFinished = true;
- return ;
- }
-
- mCurlRequest = new LLCurlRequest();
-
- std::set<LLViewerTexture* > textures;
-
- //populate upload queue with relevant models
- for (instance_map::iterator iter = mInstance.begin(); iter != mInstance.end(); ++iter)
- {
- LLMeshUploadData data;
- data.mBaseModel = iter->first;
-
- LLModelInstance& instance = *(iter->second.begin());
-
- for (S32 i = 0; i < 5; i++)
- {
- data.mModel[i] = instance.mLOD[i];
- }
-
- uploadModel(data);
-
- if (mUploadTextures)
- {
- for (std::vector<LLImportMaterial>::iterator material_iter = instance.mMaterial.begin();
- material_iter != instance.mMaterial.end(); ++material_iter)
- {
-
- if (textures.find(material_iter->mDiffuseMap.get()) == textures.end())
- {
- textures.insert(material_iter->mDiffuseMap.get());
-
- LLTextureUploadData data(material_iter->mDiffuseMap.get(), material_iter->mDiffuseMapLabel);
- uploadTexture(data);
- }
- }
- }
-
- //queue up models for hull generation
- LLModel* physics = data.mModel[LLModel::LOD_PHYSICS];
- if (physics == NULL)
- { //no physics model available, use high lod
- physics = data.mModel[LLModel::LOD_HIGH];
- }
-
- DecompRequest* request = new DecompRequest(physics, data.mBaseModel, this);
- gMeshRepo.mDecompThread->submitRequest(request);
- }
-
- while (!mPhysicsComplete)
- {
- apr_sleep(100);
- }
-
- //upload textures
- bool done = false;
- do
- {
- if (!mTextureQ.empty())
- {
- sendCostRequest(mTextureQ.front());
- mTextureQ.pop();
- }
-
- if (!mConfirmedTextureQ.empty())
- {
- doUploadTexture(mConfirmedTextureQ.front());
- mConfirmedTextureQ.pop();
- }
-
- mCurlRequest->process();
-
- done = mTextureQ.empty() && mConfirmedTextureQ.empty();
- }
- while (!done || mCurlRequest->getQueued() > 0);
-
- LLSD object_asset;
- object_asset["objects"] = LLSD::emptyArray();
-
- done = false;
- do
- {
- static S32 count = 0;
- static F32 last_hundred = gFrameTimeSeconds;
- if (gFrameTimeSeconds - last_hundred > 1.f)
- {
- last_hundred = gFrameTimeSeconds;
- count = 0;
- }
-
- //how many requests to push before calling process
- const S32 PUSH_PER_PROCESS = 32;
-
- S32 tcount = llmin(count+PUSH_PER_PROCESS, 100);
-
- while (!mUploadQ.empty() && count < tcount)
- { //send any pending upload requests
- mMutex->lock();
- LLMeshUploadData data = mUploadQ.front();
- mUploadQ.pop();
- mMutex->unlock();
- sendCostRequest(data);
- count++;
- }
-
- tcount = llmin(count+PUSH_PER_PROCESS, 100);
-
- while (!mConfirmedQ.empty() && count < tcount)
- { //process any meshes that have been confirmed for upload
- LLMeshUploadData& data = mConfirmedQ.front();
- doUploadModel(data);
- mConfirmedQ.pop();
- count++;
- }
-
- tcount = llmin(count+PUSH_PER_PROCESS, 100);
-
- while (!mInstanceQ.empty() && count < tcount && !isDiscarded())
- { //create any objects waiting for upload
- count++;
- object_asset["objects"].append(createObject(mInstanceQ.front()));
- mInstanceQ.pop();
- }
-
- mCurlRequest->process();
-
- done = isDiscarded() || (mInstanceQ.empty() && mConfirmedQ.empty() && mUploadQ.empty());
- }
- while (!done || mCurlRequest->getQueued() > 0);
-
- delete mCurlRequest;
- mCurlRequest = NULL;
-
- // now upload the object asset
- std::string url = mUploadObjectAssetCapability;
-
- if (object_asset["objects"][0].has("permissions"))
- { //copy permissions from first available object to be used for coalesced object
- object_asset["permissions"] = object_asset["objects"][0]["permissions"];
- }
-
- if(!isDiscarded())
- {
- mPendingUploads++;
- LLHTTPClient::post(url, object_asset, new LLModelObjectUploadResponder(this,object_asset));
- }
- else
- {
- mFinished = true;
- }
-}
-
void LLMeshUploadThread::uploadModel(LLMeshUploadData& data)
{ //called from arbitrary thread
{
@@ -2234,7 +2120,7 @@ void LLMeshHeaderResponder::completedRaw(U32 status, const std::string& reason,
//just in case skin info or decomposition is at the end of the file (which it shouldn't be)
lod_bytes = llmax(lod_bytes, header["skin"]["offset"].asInteger() + header["skin"]["size"].asInteger());
- lod_bytes = llmax(lod_bytes, header["decomposition"]["offset"].asInteger() + header["decomposition"]["size"].asInteger());
+ lod_bytes = llmax(lod_bytes, header["physics_convex"]["offset"].asInteger() + header["physics_convex"]["size"].asInteger());
S32 header_bytes = (S32) gMeshRepo.mThread->mMeshHeaderSize[mesh_id];
S32 bytes = lod_bytes + header_bytes;
@@ -2522,7 +2408,6 @@ void LLMeshRepository::notifyLoadedMeshes()
if (gAgent.getRegion()->getName() != region_name && gAgent.getRegion()->capabilitiesReceived())
{
region_name = gAgent.getRegion()->getName();
-
mGetMeshCapability = gAgent.getRegion()->getCapability("GetMesh");
}
}
@@ -2860,7 +2745,18 @@ void LLMeshRepository::buildHull(const LLVolumeParams& params, S32 detail)
bool LLMeshRepository::hasPhysicsShape(const LLUUID& mesh_id)
{
LLSD mesh = mThread->getMeshHeader(mesh_id);
- return mesh.has("physics_shape") && mesh["physics_shape"].has("size") && (mesh["physics_shape"]["size"].asInteger() > 0);
+ if (mesh.has("physics_mesh") && mesh["physics_mesh"].has("size") && (mesh["physics_mesh"]["size"].asInteger() > 0))
+ {
+ return true;
+ }
+
+ LLModel::Decomposition* decomp = getDecomposition(mesh_id);
+ if (decomp && !decomp->mHull.empty())
+ {
+ return true;
+ }
+
+ return false;
}
LLSD& LLMeshRepository::getMeshHeader(const LLUUID& mesh_id)
@@ -2916,102 +2812,6 @@ S32 LLMeshRepository::getMeshSize(const LLUUID& mesh_id, S32 lod)
}
-void LLMeshUploadThread::sendCostRequest(LLMeshUploadData& data)
-{
- if(isDiscarded())
- {
- return ;
- }
-
- //write model file to memory buffer
- std::stringstream ostr;
-
- LLModel::Decomposition& decomp =
- data.mModel[LLModel::LOD_PHYSICS].notNull() ?
- data.mModel[LLModel::LOD_PHYSICS]->mPhysics :
- data.mBaseModel->mPhysics;
-
- LLSD header = LLModel::writeModel(
- ostr,
- data.mModel[LLModel::LOD_PHYSICS],
- data.mModel[LLModel::LOD_HIGH],
- data.mModel[LLModel::LOD_MEDIUM],
- data.mModel[LLModel::LOD_LOW],
- data.mModel[LLModel::LOD_IMPOSTOR],
- decomp,
- mUploadSkin,
- mUploadJoints,
- true);
-
- std::string desc = data.mBaseModel->mLabel;
-
- // Grab the total vertex count of the model
- // along with other information for the "asset_resources" map
- // to send to the server.
- LLSD asset_resources = LLSD::emptyMap();
-
-
- std::string url = mNewInventoryCapability;
-
- if (!url.empty())
- {
- LLSD body = generate_new_resource_upload_capability_body(
- LLAssetType::AT_MESH,
- desc,
- desc,
- LLFolderType::FT_MESH,
- LLInventoryType::IT_MESH,
- LLFloaterPerms::getNextOwnerPerms(),
- LLFloaterPerms::getGroupPerms(),
- LLFloaterPerms::getEveryonePerms());
-
- body["asset_resources"] = asset_resources;
-
- mPendingConfirmations++;
- LLCurlRequest::headers_t headers;
-
- data.mPostData = body;
-
- mCurlRequest->post(url, headers, body, new LLMeshCostResponder(data, this));
- }
-}
-
-void LLMeshUploadThread::sendCostRequest(LLTextureUploadData& data)
-{
- if(isDiscarded())
- {
- return ;
- }
-
- if (data.mTexture && data.mTexture->getDiscardLevel() >= 0)
- {
- LLSD asset_resources = LLSD::emptyMap();
-
- std::string url = mNewInventoryCapability;
-
- if (!url.empty())
- {
- LLSD body = generate_new_resource_upload_capability_body(
- LLAssetType::AT_TEXTURE,
- data.mLabel,
- data.mLabel,
- LLFolderType::FT_TEXTURE,
- LLInventoryType::IT_TEXTURE,
- LLFloaterPerms::getNextOwnerPerms(),
- LLFloaterPerms::getGroupPerms(),
- LLFloaterPerms::getEveryonePerms());
-
- body["asset_resources"] = asset_resources;
-
- mPendingConfirmations++;
- LLCurlRequest::headers_t headers;
-
- data.mPostData = body;
- mCurlRequest->post(url, headers, body, new LLTextureCostResponder(data, this));
- }
- }
-}
-
void LLMeshUploadThread::doUploadModel(LLMeshUploadData& data)
{
@@ -3314,8 +3114,8 @@ bool LLImportMaterial::operator<(const LLImportMaterial &rhs) const
void LLMeshRepository::updateInventory(inventory_data data)
{
LLMutexLock lock(mMeshMutex);
- dumpLLSDToFile(data.mPostData,"update_inventory_post_data.xml");
- dumpLLSDToFile(data.mResponse,"update_inventory_response.xml");
+ dumpLLSDToFile(data.mPostData,make_dump_name("update_inventory_post_data_",dump_num));
+ dumpLLSDToFile(data.mResponse,make_dump_name("update_inventory_response_",dump_num));
mInventoryQ.push(data);
}
@@ -3473,15 +3273,18 @@ void LLPhysicsDecomp::setMeshData(LLCDMeshData& mesh)
mesh.mNumTriangles = mCurRequest->mIndices.size()/3;
- LLCDResult ret = LLCD_OK;
- if (LLConvexDecomposition::getInstance() != NULL)
+ if (mesh.mNumTriangles > 0 && mesh.mNumVertices > 2)
{
- ret = LLConvexDecomposition::getInstance()->setMeshData(&mesh);
- }
+ LLCDResult ret = LLCD_OK;
+ if (LLConvexDecomposition::getInstance() != NULL)
+ {
+ ret = LLConvexDecomposition::getInstance()->setMeshData(&mesh);
+ }
- if (ret)
- {
- llerrs << "Convex Decomposition thread valid but could not set mesh data" << llendl;
+ if (ret)
+ {
+ llerrs << "Convex Decomposition thread valid but could not set mesh data" << llendl;
+ }
}
}
@@ -3839,6 +3642,62 @@ void LLPhysicsDecomp::run()
mDone = true;
}
+void LLPhysicsDecomp::Request::assignData(LLModel* mdl)
+{
+ if (!mdl)
+ {
+ return ;
+ }
+
+ U16 index_offset = 0;
+ U16 tri[3] ;
+
+ mPositions.clear();
+ mIndices.clear();
+ mBBox[1] = LLVector3(F32_MIN, F32_MIN, F32_MIN) ;
+ mBBox[0] = LLVector3(F32_MAX, F32_MAX, F32_MAX) ;
+
+ //queue up vertex positions and indices
+ for (S32 i = 0; i < mdl->getNumVolumeFaces(); ++i)
+ {
+ const LLVolumeFace& face = mdl->getVolumeFace(i);
+ if (mPositions.size() + face.mNumVertices > 65535)
+ {
+ continue;
+ }
+
+ for (U32 j = 0; j < face.mNumVertices; ++j)
+ {
+ mPositions.push_back(LLVector3(face.mPositions[j].getF32ptr()));
+ for(U32 k = 0 ; k < 3 ; k++)
+ {
+ mBBox[0].mV[k] = llmin(mBBox[0].mV[k], mPositions[j].mV[k]) ;
+ mBBox[1].mV[k] = llmax(mBBox[1].mV[k], mPositions[j].mV[k]) ;
+ }
+ }
+
+ updateTriangleAreaThreshold() ;
+
+ for (U32 j = 0; j+2 < face.mNumIndices; j += 3)
+ {
+ tri[0] = face.mIndices[j] + index_offset ;
+ tri[1] = face.mIndices[j + 1] + index_offset ;
+ tri[2] = face.mIndices[j + 2] + index_offset ;
+
+ if(isValidTriangle(tri[0], tri[1], tri[2]))
+ {
+ mIndices.push_back(tri[0]);
+ mIndices.push_back(tri[1]);
+ mIndices.push_back(tri[2]);
+ }
+ }
+
+ index_offset += face.mNumVertices;
+ }
+
+ return ;
+}
+
void LLPhysicsDecomp::Request::updateTriangleAreaThreshold()
{
F32 range = mBBox[1].mV[0] - mBBox[0].mV[0] ;
@@ -3955,3 +3814,27 @@ void LLMeshRepository::buildPhysicsMesh(LLModel::Decomposition& decomp)
}
}
}
+
+
+bool LLMeshRepository::meshUploadEnabled()
+{
+ LLViewerRegion *region = gAgent.getRegion();
+ if(gSavedSettings.getBOOL("MeshEnabled") &&
+ LLViewerParcelMgr::getInstance()->allowAgentBuild() &&
+ region)
+ {
+ return region->meshUploadEnabled();
+ }
+ return false;
+}
+
+bool LLMeshRepository::meshRezEnabled()
+{
+ LLViewerRegion *region = gAgent.getRegion();
+ if(gSavedSettings.getBOOL("MeshEnabled") &&
+ region)
+ {
+ return region->meshRezEnabled();
+ }
+ return false;
+}
diff --git a/indra/newview/llmeshrepository.h b/indra/newview/llmeshrepository.h
index 9b80fc02b3..f237c3a60e 100644
--- a/indra/newview/llmeshrepository.h
+++ b/indra/newview/llmeshrepository.h
@@ -161,11 +161,14 @@ public:
virtual void setStatusMessage(const std::string& msg);
+ bool isValid() const {return mPositions.size() > 2 && mIndices.size() > 2 ;}
+
protected:
//internal use
LLVector3 mBBox[2] ;
F32 mTriangleAreaThreshold ;
+ void assignData(LLModel* mdl) ;
void updateTriangleAreaThreshold() ;
bool isValidTriangle(U16 idx1, U16 idx2, U16 idx3) ;
};
@@ -393,8 +396,6 @@ public:
BOOL mDiscarded ;
LLHost mHost;
- std::string mUploadObjectAssetCapability;
- std::string mNewInventoryCapability;
std::string mWholeModelFeeCapability;
std::string mWholeModelUploadURL;
@@ -413,12 +414,10 @@ public:
void uploadTexture(LLTextureUploadData& data);
void doUploadTexture(LLTextureUploadData& data);
- void sendCostRequest(LLTextureUploadData& data);
void priceResult(LLTextureUploadData& data, const LLSD& content);
void onTextureUploaded(LLTextureUploadData& data);
void uploadModel(LLMeshUploadData& data);
- void sendCostRequest(LLMeshUploadData& data);
void doUploadModel(LLMeshUploadData& data);
void onModelUploaded(LLMeshUploadData& data);
void createObjects(LLMeshUploadData& data);
@@ -432,7 +431,6 @@ public:
BOOL isDiscarded();
void doWholeModelUpload();
- void doIterativeUpload();
void wholeModelToLLSD(LLSD& dest, bool include_textures);
@@ -482,6 +480,10 @@ public:
void buildHull(const LLVolumeParams& params, S32 detail);
void buildPhysicsMesh(LLModel::Decomposition& decomp);
+
+ bool meshUploadEnabled();
+ bool meshRezEnabled();
+
LLSD& getMeshHeader(const LLUUID& mesh_id);
diff --git a/indra/newview/llpanelvolume.cpp b/indra/newview/llpanelvolume.cpp
index 7839cdd811..bb87601d20 100644
--- a/indra/newview/llpanelvolume.cpp
+++ b/indra/newview/llpanelvolume.cpp
@@ -530,17 +530,24 @@ void LLPanelVolume::refresh()
getChildView("Light Ambiance")->setVisible( visible);
getChildView("light texture control")->setVisible( visible);
- bool enable_mesh = gSavedSettings.getBOOL("MeshEnabled") &&
- gAgent.getRegion() &&
- !gAgent.getRegion()->getCapability("GetMesh").empty() &&
- !gAgent.getRegion()->getCapability("ObjectAdd").empty();
+ bool enable_mesh = false;
+ LLSD sim_features;
+ LLViewerRegion *region = gAgent.getRegion();
+ if(region)
+ {
+ LLSD sim_features;
+ region->getSimulatorFeatures(sim_features);
+ enable_mesh = sim_features.has("PhysicsShapeTypes");
+ }
getChildView("label physicsshapetype")->setVisible(enable_mesh);
getChildView("Physics Shape Type Combo Ctrl")->setVisible(enable_mesh);
getChildView("Physics Gravity")->setVisible(enable_mesh);
getChildView("Physics Friction")->setVisible(enable_mesh);
getChildView("Physics Density")->setVisible(enable_mesh);
getChildView("Physics Restitution")->setVisible(enable_mesh);
+
+ /* TODO: add/remove individual physics shape types as per the PhysicsShapeTypes simulator features */
}
diff --git a/indra/newview/llviewermenufile.cpp b/indra/newview/llviewermenufile.cpp
index 37640ad0d4..b9293b3b31 100644
--- a/indra/newview/llviewermenufile.cpp
+++ b/indra/newview/llviewermenufile.cpp
@@ -107,9 +107,7 @@ class LLMeshUploadVisible : public view_listener_t
{
bool handleEvent(const LLSD& userdata)
{
- return gSavedSettings.getBOOL("MeshEnabled") &&
- LLViewerParcelMgr::getInstance()->allowAgentBuild() &&
- !gAgent.getRegion()->getCapability("ObjectAdd").empty();
+ return gMeshRepo.meshUploadEnabled();
}
};
@@ -1203,78 +1201,6 @@ void upload_new_resource(
}
}
-BOOL upload_new_variable_price_resource(
- const LLTransactionID &tid,
- LLAssetType::EType asset_type,
- std::string name,
- std::string desc,
- LLFolderType::EType destination_folder_type,
- LLInventoryType::EType inv_type,
- U32 next_owner_perms,
- U32 group_perms,
- U32 everyone_perms,
- const std::string& display_name,
- const LLSD& asset_resources)
-{
- LLAssetID uuid =
- upload_new_resource_prep(
- tid,
- asset_type,
- inv_type,
- name,
- display_name,
- desc);
-
- llinfos << "*** Uploading: " << llendl;
- llinfos << "Type: " << LLAssetType::lookup(asset_type) << llendl;
- llinfos << "UUID: " << uuid << llendl;
- llinfos << "Name: " << name << llendl;
- llinfos << "Desc: " << desc << llendl;
- lldebugs << "Folder: "
- << gInventory.findCategoryUUIDForType((destination_folder_type == LLFolderType::FT_NONE) ? (LLFolderType::EType)asset_type : destination_folder_type) << llendl;
- lldebugs << "Asset Type: " << LLAssetType::lookup(asset_type) << llendl;
-
- std::string url = gAgent.getRegion()->getCapability(
- "NewFileAgentInventoryVariablePrice");
-
- if ( !url.empty() )
- {
- lldebugs
- << "New Agent Inventory variable price upload" << llendl;
-
- // Each of the two capabilities has similar data, so
- // let's reuse that code
-
- LLSD body;
-
- body = generate_new_resource_upload_capability_body(
- asset_type,
- name,
- desc,
- destination_folder_type,
- inv_type,
- next_owner_perms,
- group_perms,
- everyone_perms);
-
- body["asset_resources"] = asset_resources;
-
- LLHTTPClient::post(
- url,
- body,
- new LLNewAgentInventoryVariablePriceResponder(
- uuid,
- asset_type,
- body));
-
- return TRUE;
- }
- else
- {
- return FALSE;
- }
-}
-
LLAssetID generate_asset_id_for_new_upload(const LLTransactionID& tid)
{
if ( gDisconnected )
diff --git a/indra/newview/llviewermenufile.h b/indra/newview/llviewermenufile.h
index 1597821504..3136358b83 100644
--- a/indra/newview/llviewermenufile.h
+++ b/indra/newview/llviewermenufile.h
@@ -68,23 +68,6 @@ void upload_new_resource(
S32 expected_upload_cost,
void *userdata);
-// TODO* : Move all uploads to use this new function
-// since at some point, that upload path will be deprecated and no longer
-// used
-
-// We make a new function here to ensure that previous code is not broken
-BOOL upload_new_variable_price_resource(
- const LLTransactionID& tid,
- LLAssetType::EType type,
- std::string name,
- std::string desc,
- LLFolderType::EType destination_folder_type,
- LLInventoryType::EType inv_type,
- U32 next_owner_perms,
- U32 group_perms,
- U32 everyone_perms,
- const std::string& display_name,
- const LLSD& asset_resources);
LLAssetID generate_asset_id_for_new_upload(const LLTransactionID& tid);
void increase_new_upload_stats(LLAssetType::EType asset_type);
diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp
index e876294ef2..002e0567e4 100644
--- a/indra/newview/llviewerregion.cpp
+++ b/indra/newview/llviewerregion.cpp
@@ -69,6 +69,7 @@
#include "llspatialpartition.h"
#include "stringize.h"
#include "llviewercontrol.h"
+#include "llsdserialize.h"
#ifdef LL_WINDOWS
#pragma warning(disable:4355)
@@ -1140,6 +1141,20 @@ void LLViewerRegion::getInfo(LLSD& info)
info["Region"]["Handle"]["y"] = (LLSD::Integer)y;
}
+void LLViewerRegion::getSimulatorFeatures(LLSD& sim_features)
+{
+ sim_features = mSimulatorFeatures;
+}
+
+void LLViewerRegion::setSimulatorFeatures(const LLSD& sim_features)
+{
+ std::stringstream str;
+
+ LLSDSerialize::toPrettyXML(sim_features, str);
+ llinfos << str.str() << llendl;
+ mSimulatorFeatures = sim_features;
+}
+
LLViewerRegion::eCacheUpdateResult LLViewerRegion::cacheFullUpdate(LLViewerObject* objectp, LLDataPackerBinaryBuffer &dp)
{
U32 local_id = objectp->getLocalID();
@@ -1510,10 +1525,7 @@ void LLViewerRegion::setSeedCapability(const std::string& url)
capabilityNames.append("LandResources");
capabilityNames.append("MapLayer");
capabilityNames.append("MapLayerGod");
- capabilityNames.append("NewAccountingEnabled");
capabilityNames.append("NewFileAgentInventory");
- capabilityNames.append("NewFileAgentInventoryVariablePrice");
- capabilityNames.append("ObjectAdd");
capabilityNames.append("ParcelPropertiesUpdate");
capabilityNames.append("ParcelMediaURLFilterList");
capabilityNames.append("ParcelNavigateMedia");
@@ -1544,7 +1556,6 @@ void LLViewerRegion::setSeedCapability(const std::string& url)
capabilityNames.append("UpdateNotecardTaskInventory");
capabilityNames.append("UpdateScriptTask");
capabilityNames.append("UploadBakedTexture");
- capabilityNames.append("UploadObjectAsset");
capabilityNames.append("ViewerMetrics");
capabilityNames.append("ViewerStartAuction");
capabilityNames.append("ViewerStats");
@@ -1562,6 +1573,42 @@ void LLViewerRegion::setSeedCapability(const std::string& url)
LLHTTPClient::post(url, capabilityNames, mImpl->mHttpResponderPtr);
}
+class SimulatorFeaturesReceived : public LLHTTPClient::Responder
+{
+ LOG_CLASS(SimulatorFeaturesReceived);
+public:
+ SimulatorFeaturesReceived(LLViewerRegion* region)
+ : mRegion(region)
+ { }
+
+
+ void error(U32 statusNum, const std::string& reason)
+ {
+ LL_WARNS2("AppInit", "SimulatorFeatures") << statusNum << ": " << reason << LL_ENDL;
+ }
+
+ void result(const LLSD& content)
+ {
+ if(!mRegion) //region is removed or responder is not created.
+ {
+ return ;
+ }
+
+ mRegion->setSimulatorFeatures(content);
+ }
+
+ static boost::intrusive_ptr<SimulatorFeaturesReceived> build(
+ LLViewerRegion* region)
+ {
+ return boost::intrusive_ptr<SimulatorFeaturesReceived>(
+ new SimulatorFeaturesReceived(region));
+ }
+
+private:
+ LLViewerRegion* mRegion;
+};
+
+
void LLViewerRegion::setCapability(const std::string& name, const std::string& url)
{
if(name == "EventQueueGet")
@@ -1574,6 +1621,11 @@ void LLViewerRegion::setCapability(const std::string& name, const std::string& u
{
LLHTTPSender::setSender(mImpl->mHost, new LLCapHTTPSender(url));
}
+ else if (name == "SimulatorFeatures")
+ {
+ // kick off a request for simulator features
+ LLHTTPClient::get(url, new SimulatorFeaturesReceived(this));
+ }
else
{
mImpl->mCapabilities[name] = url;
@@ -1667,3 +1719,16 @@ std::string LLViewerRegion::getDescription() const
return stringize(*this);
}
+bool LLViewerRegion::meshUploadEnabled() const
+{
+ return (mSimulatorFeatures.has("MeshUploadEnabled") &&
+ mSimulatorFeatures["MeshUploadEnabled"].asBoolean());
+}
+
+bool LLViewerRegion::meshRezEnabled() const
+{
+ return (mSimulatorFeatures.has("MeshRezEnabled") &&
+ mSimulatorFeatures["MeshRezEnabled"].asBoolean());
+}
+
+
diff --git a/indra/newview/llviewerregion.h b/indra/newview/llviewerregion.h
index a6e5c47b86..3811b989e7 100644
--- a/indra/newview/llviewerregion.h
+++ b/indra/newview/llviewerregion.h
@@ -276,6 +276,11 @@ public:
void getInfo(LLSD& info);
+ bool meshRezEnabled() const;
+ bool meshUploadEnabled() const;
+
+ void getSimulatorFeatures(LLSD& info);
+ void setSimulatorFeatures(const LLSD& info);
typedef enum
{
@@ -401,6 +406,8 @@ private:
bool mCapabilitiesReceived;
BOOL mReleaseNotesRequested;
+
+ LLSD mSimulatorFeatures;
};
inline BOOL LLViewerRegion::getAllowDamage() const
diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp
index 34d15a597e..b1441cc281 100644
--- a/indra/newview/llviewerwindow.cpp
+++ b/indra/newview/llviewerwindow.cpp
@@ -601,7 +601,7 @@ public:
ypos += y_inc;
- if (gSavedSettings.getBOOL("MeshEnabled"))
+ if (gMeshRepo.meshRezEnabled())
{
addText(xpos, ypos, llformat("%.3f MB Mesh Data Received", LLMeshRepository::sBytesReceived/(1024.f*1024.f)));
diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp
index 6de334eb82..c5e2c56e4b 100644
--- a/indra/newview/llvovolume.cpp
+++ b/indra/newview/llvovolume.cpp
@@ -3984,7 +3984,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
LLVOVolume* vobj = drawablep->getVOVolume();
- if (vobj->getVolume() && vobj->getVolume()->isTetrahedron())
+ if (vobj->getVolume() && vobj->getVolume()->isTetrahedron() || (vobj->isMesh() && !gMeshRepo.meshRezEnabled()))
{
continue;
}