summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDave Parks <davep@lindenlab.com>2010-10-06 01:17:12 -0500
committerDave Parks <davep@lindenlab.com>2010-10-06 01:17:12 -0500
commit24e0d62a5eb3299a877d7a6b37e1881ec3d1ca0c (patch)
treee019607213c23f83f17431237f9c45979c5395d5
parent98d622551d9466d1153dedfbdd721becf8c38cd9 (diff)
Added mandatory single hull simplification to mesh upload.
-rw-r--r--indra/llprimitive/llmodel.cpp90
-rw-r--r--indra/llprimitive/llmodel.h6
-rw-r--r--indra/newview/llfloatermodelpreview.cpp20
-rw-r--r--indra/newview/llmeshrepository.cpp541
-rw-r--r--indra/newview/llmeshrepository.h26
-rw-r--r--indra/newview/llspatialpartition.cpp39
6 files changed, 557 insertions, 165 deletions
diff --git a/indra/llprimitive/llmodel.cpp b/indra/llprimitive/llmodel.cpp
index 1cada567e9..d6369b3387 100644
--- a/indra/llprimitive/llmodel.cpp
+++ b/indra/llprimitive/llmodel.cpp
@@ -1290,9 +1290,16 @@ LLModel* LLModel::loadModelFromDomMesh(domMesh *mesh)
//static
LLSD LLModel::writeModel(std::string filename, LLModel* physics, LLModel* high, LLModel* medium, LLModel* low, LLModel* impostor, LLModel::physics_shape& 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, LLModel::physics_shape& decomp, LLModel::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, upload_skin, upload_joints, nowrite);
+ LLSD header = writeModel(os, physics, high, medium, low, impostor, decomp, base_hull, upload_skin, upload_joints, nowrite);
os.close();
@@ -1300,7 +1307,7 @@ LLSD LLModel::writeModel(std::string filename, LLModel* physics, LLModel* high,
}
//static
-LLSD LLModel::writeModel(std::ostream& ostr, LLModel* physics, LLModel* high, LLModel* medium, LLModel* low, LLModel* impostor, LLModel::physics_shape& decomp, bool upload_skin, bool upload_joints, bool nowrite)
+LLSD LLModel::writeModel(std::ostream& ostr, LLModel* physics, LLModel* high, LLModel* medium, LLModel* low, LLModel* impostor, LLModel::physics_shape& decomp, LLModel::hull& base_hull, bool upload_skin, bool upload_joints, bool nowrite)
{
LLSD mdl;
@@ -1359,15 +1366,27 @@ LLSD LLModel::writeModel(std::ostream& ostr, LLModel* physics, LLModel* high, LL
}
- if (!decomp.empty())
+ if (!decomp.empty() || !base_hull.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 = decomp[0][0];
+ LLVector3 min;
+
+ if (decomp.empty())
+ {
+ min = base_hull[0];
+ }
+ else
+ {
+ min = decomp[0][0];
+ }
+
LLVector3 max = min;
LLSD::Binary hulls(decomp.size());
@@ -1386,23 +1405,64 @@ LLSD LLModel::writeModel(std::ostream& ostr, LLModel* physics, LLModel* high, LL
}
}
+ 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();
- mdl["decomposition"]["HullList"] = hulls;
-
- LLSD::Binary p(total*3*2);
- LLVector3 range = max-min;
+ if (!hulls.empty())
+ {
+ mdl["decomposition"]["HullList"] = hulls;
+ }
- U32 vert_idx = 0;
- for (U32 i = 0; i < decomp.size(); ++i)
+ if (total > 0)
{
- for (U32 j = 0; j < decomp[i].size(); ++j)
+ 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) (((decomp[i][j].mV[k]-min.mV[k])/range.mV[k])*65535);
+ U16 val = (U16) (((base_hull[j].mV[k]-min.mV[k])/range.mV[k])*65535);
U8* buff = (U8*) &val;
//write to binary buffer
@@ -1415,9 +1475,9 @@ LLSD LLModel::writeModel(std::ostream& ostr, LLModel* physics, LLModel* high, LL
}
}
}
+
+ mdl["decomposition"]["Hull"] = p;
}
-
- mdl["decomposition"]["Position"] = p;
}
for (U32 idx = 0; idx < MODEL_NAMES_LENGTH; ++idx)
diff --git a/indra/llprimitive/llmodel.h b/indra/llprimitive/llmodel.h
index ec21ef2fcd..d043015f74 100644
--- a/indra/llprimitive/llmodel.h
+++ b/indra/llprimitive/llmodel.h
@@ -57,11 +57,13 @@ public:
//physics shape is a vector of convex hulls
//each convex hull is a set of points
- typedef std::vector<std::vector<LLVector3> > physics_shape;
+ typedef std::vector<LLVector3> hull;
+ typedef std::vector<hull> physics_shape;
LLModel(LLVolumeParams& params, F32 detail);
static LLSD writeModel(std::string filename, LLModel* physics, LLModel* high, LLModel* medium, LLModel* low, LLModel* imposotr, LLModel::physics_shape& physics_shape, bool upload_skin, bool upload_joints, bool nowrite = FALSE);
- static LLSD writeModel(std::ostream& ostr, LLModel* physics, LLModel* high, LLModel* medium, LLModel* low, LLModel* imposotr, LLModel::physics_shape& physics_shape, 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, LLModel::physics_shape& physics_shape, LLModel::hull& base_hull, bool upload_skin, bool upload_joints, bool nowrite = FALSE);
+ static LLSD writeModel(std::ostream& ostr, LLModel* physics, LLModel* high, LLModel* medium, LLModel* low, LLModel* imposotr, LLModel::physics_shape& physics_shape, LLModel::hull& base_hull, bool upload_skin, bool upload_joints, bool nowrite = FALSE);
static LLSD writeModelToStream(std::ostream& ostr, LLSD& mdl, BOOL nowrite = FALSE);
static LLModel* loadModelFromAsset(std::string filename, S32 lod);
static LLModel* loadModelFromDae(std::string filename);
diff --git a/indra/newview/llfloatermodelpreview.cpp b/indra/newview/llfloatermodelpreview.cpp
index 82d3a07345..deb2eff351 100644
--- a/indra/newview/llfloatermodelpreview.cpp
+++ b/indra/newview/llfloatermodelpreview.cpp
@@ -900,7 +900,8 @@ void LLFloaterModelPreview::showDecompFloater()
// protected against stub by stage_count being 0 for stub above
LLConvexDecomposition::getInstance()->registerCallback(j, LLPhysicsDecomp::llcdCallback);
- llinfos << "Physics decomp stage " << j << " parameters:" << llendl;
+ llinfos << "Physics decomp stage " << stage[j].mName << " (" << j << ") parameters:" << llendl;
+ llinfos << "------------------------------------" << llendl;
for (S32 i = 0; i < param_count; ++i)
{
@@ -912,11 +913,15 @@ void LLFloaterModelPreview::showDecompFloater()
std::string name(param[i].mName ? param[i].mName : "");
std::string description(param[i].mDescription ? param[i].mDescription : "");
+ std::string type = "unknown";
+
llinfos << name << " - " << description << llendl;
if (param[i].mType == LLCDParam::LLCD_FLOAT)
{
mDecompParams[param[i].mName] = LLSD(param[i].mDefault.mFloat);
+ llinfos << "Type: float, Default: " << param[i].mDefault.mFloat << llendl;
+
LLSliderCtrl::Params p;
p.name(name);
p.label(name);
@@ -935,6 +940,7 @@ void LLFloaterModelPreview::showDecompFloater()
else if (param[i].mType == LLCDParam::LLCD_INTEGER)
{
mDecompParams[param[i].mName] = LLSD(param[i].mDefault.mIntOrEnumValue);
+ llinfos << "Type: integer, Default: " << param[i].mDefault.mIntOrEnumValue << llendl;
LLSliderCtrl::Params p;
p.name(name);
p.label(name);
@@ -952,6 +958,8 @@ void LLFloaterModelPreview::showDecompFloater()
else if (param[i].mType == LLCDParam::LLCD_BOOLEAN)
{
mDecompParams[param[i].mName] = LLSD(param[i].mDefault.mBool);
+ llinfos << "Type: boolean, Default: " << (param[i].mDefault.mBool ? "True" : "False") << llendl;
+
LLCheckBoxCtrl::Params p;
p.rect(LLRect(left, cur_y, right, cur_y-20));
p.name(name);
@@ -967,6 +975,8 @@ void LLFloaterModelPreview::showDecompFloater()
{
S32 cur_x = left;
mDecompParams[param[i].mName] = LLSD(param[i].mDefault.mIntOrEnumValue);
+ llinfos << "Type: enum, Default: " << param[i].mDefault.mIntOrEnumValue << llendl;
+
{ //add label
LLTextBox::Params p;
const LLFontGL* font = (LLFontGL*) p.font();
@@ -987,9 +997,13 @@ void LLFloaterModelPreview::showDecompFloater()
p.label(name);
p.tool_tip(description);
+ llinfos << "Accepted values: " << llendl;
LLComboBox* combo_box = LLUICtrlFactory::create<LLComboBox>(p);
for (S32 k = 0; k < param[i].mDetails.mEnumValues.mNumEnums; ++k)
{
+ llinfos << param[i].mDetails.mEnumValues.mEnumsArray[k].mValue
+ << " - " << param[i].mDetails.mEnumValues.mEnumsArray[k].mName << llendl;
+
combo_box->add(param[i].mDetails.mEnumValues.mEnumsArray[k].mName,
LLSD::Integer(param[i].mDetails.mEnumValues.mEnumsArray[k].mValue));
}
@@ -997,8 +1011,12 @@ void LLFloaterModelPreview::showDecompFloater()
combo_box->setCommitCallback(onPhysicsParamCommit, (void*) &param[i]);
mDecompFloater->addChild(combo_box);
cur_y += 30;
+
}
+
+ llinfos << "----" << llendl;
}
+ llinfos << "-----------------------------" << llendl;
}
}
diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp
index eae5cf59f0..681748694c 100644
--- a/indra/newview/llmeshrepository.cpp
+++ b/indra/newview/llmeshrepository.cpp
@@ -1069,43 +1069,93 @@ bool LLMeshRepoThread::decompositionReceived(const LLUUID& mesh_id, U8* data, S3
LLMeshDecomposition* d = new LLMeshDecomposition();
d->mMeshID = mesh_id;
- // 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();
+ if (decomp.has("HullList"))
+ {
+ // 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();
+
+ U16* p = (U16*) &position[0];
- U16* p = (U16*) &position[0];
+ d->mHull.resize(hulls.size());
- d->mHull.resize(hulls.size());
+ LLVector3 min;
+ LLVector3 max;
+ LLVector3 range;
- LLVector3 min;
- LLVector3 max;
- LLVector3 range;
+ min.setValue(decomp["Min"]);
+ max.setValue(decomp["Max"]);
+ range = max-min;
- min.setValue(decomp["Min"]);
- max.setValue(decomp["Max"]);
- range = max-min;
+ for (U32 i = 0; i < hulls.size(); ++i)
+ {
+ U16 count = (hulls[i] == 0) ? 256 : hulls[i];
+
+ for (U32 j = 0; j < count; ++j)
+ {
+ d->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;
+ }
- for (U32 i = 0; i < hulls.size(); ++i)
+ }
+
+ //get mesh for decomposition
+ for (U32 i = 0; i < d->mHull.size(); ++i)
+ {
+ LLCDHull hull;
+ hull.mNumVertices = d->mHull[i].size();
+ hull.mVertexBase = d->mHull[i][0].mV;
+ hull.mVertexStrideBytes = 12;
+
+ LLCDMeshData mesh;
+ LLCDResult res = LLCD_OK;
+ if (LLConvexDecomposition::getInstance() != NULL)
+ {
+ res = LLConvexDecomposition::getInstance()->getMeshFromHull(&hull, &mesh);
+ }
+ if (res != LLCD_OK)
+ {
+ llwarns << "could not get mesh from hull from convex decomposition lib." << llendl;
+ return false;
+ }
+
+
+ d->mMesh.push_back(get_vertex_buffer_from_mesh(mesh));
+ }
+ }
+
+ if (decomp.has("Hull"))
{
- U16 count = (hulls[i] == 0) ? 256 : hulls[i];
+ const LLSD::Binary& position = decomp["Hull"].asBinary();
+
+ U16* p = (U16*) &position[0];
+
+ LLVector3 min;
+ LLVector3 max;
+ LLVector3 range;
+
+ min.setValue(decomp["Min"]);
+ max.setValue(decomp["Max"]);
+ range = max-min;
+
+ U16 count = position.size()/6;
for (U32 j = 0; j < count; ++j)
{
- d->mHull[i].push_back(LLVector3(
+ d->mBaseHull.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;
}
-
- }
-
- //get mesh for decomposition
- for (U32 i = 0; i < d->mHull.size(); ++i)
- {
+
+ //get mesh for decomposition
LLCDHull hull;
- hull.mNumVertices = d->mHull[i].size();
- hull.mVertexBase = d->mHull[i][0].mV;
+ hull.mNumVertices = d->mBaseHull.size();
+ hull.mVertexBase = d->mBaseHull[0].mV;
hull.mVertexStrideBytes = 12;
LLCDMeshData mesh;
@@ -1120,9 +1170,8 @@ bool LLMeshRepoThread::decompositionReceived(const LLUUID& mesh_id, U8* data, S3
return false;
}
-
- d->mMesh.push_back(get_vertex_buffer_from_mesh(mesh));
- }
+ d->mBaseHullMesh = get_vertex_buffer_from_mesh(mesh);
+ }
mDecompositionQ.push(d);
}
@@ -1160,6 +1209,63 @@ LLMeshUploadThread::~LLMeshUploadThread()
}
+LLMeshUploadThread::DecompRequest::DecompRequest(LLModel* mdl, LLModel* base_model, LLMeshUploadThread* thread)
+{
+ mStage = "single_hull";
+ mModel = mdl;
+ mBaseModel = base_model;
+ 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;
+ }
+ }
+
+ mThread->mFinalDecomp = this;
+ mThread->mPhysicsComplete = false;
+}
+
+void LLMeshUploadThread::DecompRequest::completed()
+{
+ if (mThread->mFinalDecomp == this)
+ {
+ mThread->mPhysicsComplete = true;
+ }
+
+ if (mHull.size() != 1)
+ {
+ llerrs << "WTF?" << llendl;
+ }
+
+ mThread->mHullMap[mBaseModel] = mHull[0];
+}
+
void LLMeshUploadThread::run()
{
mCurlRequest = new LLCurlRequest();
@@ -1202,8 +1308,31 @@ void LLMeshUploadThread::run()
}
}
}
- }
+ //queue up models for hull generation
+ LLModel* physics = NULL;
+
+ if (data.mModel[LLModel::LOD_PHYSICS].notNull())
+ {
+ physics = data.mModel[LLModel::LOD_PHYSICS];
+ }
+ else if (data.mModel[LLModel::LOD_MEDIUM].notNull())
+ {
+ physics = data.mModel[LLModel::LOD_MEDIUM];
+ }
+ else
+ {
+ physics = data.mModel[LLModel::LOD_HIGH];
+ }
+
+ if (!physics)
+ {
+ llerrs << "WTF?" << llendl;
+ }
+
+ DecompRequest* request = new DecompRequest(physics, data.mBaseModel, this);
+ gMeshRepo.mDecompThread->submitRequest(request);
+ }
//upload textures
bool done = false;
@@ -2209,6 +2338,8 @@ void LLMeshUploadThread::sendCostRequest(LLMeshUploadData& data)
data.mModel[LLModel::LOD_PHYSICS]->mPhysicsShape :
data.mBaseModel->mPhysicsShape;
+ LLModel::hull dummy_hull;
+
LLSD header = LLModel::writeModel(ostr,
data.mModel[LLModel::LOD_PHYSICS],
data.mModel[LLModel::LOD_HIGH],
@@ -2216,6 +2347,7 @@ void LLMeshUploadThread::sendCostRequest(LLMeshUploadData& data)
data.mModel[LLModel::LOD_LOW],
data.mModel[LLModel::LOD_IMPOSTOR],
phys_shape,
+ dummy_hull,
mUploadSkin,
mUploadJoints,
true);
@@ -2295,6 +2427,8 @@ void LLMeshUploadThread::doUploadModel(LLMeshUploadData& data)
data.mModel[LLModel::LOD_PHYSICS]->mPhysicsShape :
data.mBaseModel->mPhysicsShape;
+
+
LLModel::writeModel(ostr,
data.mModel[LLModel::LOD_PHYSICS],
data.mModel[LLModel::LOD_HIGH],
@@ -2302,6 +2436,7 @@ void LLMeshUploadThread::doUploadModel(LLMeshUploadData& data)
data.mModel[LLModel::LOD_LOW],
data.mModel[LLModel::LOD_IMPOSTOR],
phys_shape,
+ mHullMap[data.mBaseModel],
mUploadSkin,
mUploadJoints);
@@ -2475,6 +2610,8 @@ LLSD LLMeshUploadThread::createObject(LLModelInstance& instance)
perm.setNextOwnerBits(gAgent.getID(), LLUUID::null, TRUE, LLFloaterPerms::getNextOwnerPerms());
perm.setGroupBits(gAgent.getID(), LLUUID::null, TRUE, LLFloaterPerms::getGroupPerms());
perm.setEveryoneBits(gAgent.getID(), LLUUID::null, TRUE, LLFloaterPerms::getEveryonePerms());
+ perm.setOwnerAndGroup(gAgent.getID(), gAgent.getID(), LLUUID::null, false);
+ perm.setCreator(gAgent.getID());
object_params["permissions"] = ll_create_sd_from_permissions(perm);
@@ -2635,159 +2772,269 @@ S32 LLPhysicsDecomp::llcdCallback(const char* status, S32 p1, S32 p2)
return 1;
}
-void LLPhysicsDecomp::run()
+void LLPhysicsDecomp::setMeshData(LLCDMeshData& mesh)
{
- LLConvexDecomposition::initSystem();
- mInited = true;
+ mesh.mVertexBase = mCurRequest->mPositions[0].mV;
+ mesh.mVertexStrideBytes = 12;
+ mesh.mNumVertices = mCurRequest->mPositions.size();
- while (!mQuitting)
+ mesh.mIndexType = LLCDMeshData::INT_16;
+ mesh.mIndexBase = &(mCurRequest->mIndices[0]);
+ mesh.mIndexStrideBytes = 6;
+
+ mesh.mNumTriangles = mCurRequest->mIndices.size()/3;
+
+ LLCDResult ret = LLCD_OK;
+ if (LLConvexDecomposition::getInstance() != NULL)
{
- mSignal->wait();
- while (!mQuitting && !mRequestQ.empty())
- {
- mCurRequest = mRequestQ.front();
- mRequestQ.pop();
+ ret = LLConvexDecomposition::getInstance()->setMeshData(&mesh);
+ }
- LLCDMeshData mesh;
- S32 stage = mStageID[mCurRequest->mStage];
+ if (ret)
+ {
+ llerrs << "Convex Decomposition thread valid but could not set mesh data" << llendl;
+ }
+}
- //load data intoLLCD
- if (stage == 0)
- {
- mesh.mVertexBase = mCurRequest->mPositions[0].mV;
- mesh.mVertexStrideBytes = 12;
- mesh.mNumVertices = mCurRequest->mPositions.size();
+void LLPhysicsDecomp::doDecomposition()
+{
+ LLCDMeshData mesh;
+ S32 stage = mStageID[mCurRequest->mStage];
- mesh.mIndexType = LLCDMeshData::INT_16;
- mesh.mIndexBase = &(mCurRequest->mIndices[0]);
- mesh.mIndexStrideBytes = 6;
-
- mesh.mNumTriangles = mCurRequest->mIndices.size()/3;
+ //load data intoLLCD
+ if (stage == 0)
+ {
+ setMeshData(mesh);
+ }
+
+ //build parameter map
+ std::map<std::string, const LLCDParam*> param_map;
- LLCDResult ret = LLCD_OK;
- if (LLConvexDecomposition::getInstance() != NULL)
- {
- ret = LLConvexDecomposition::getInstance()->setMeshData(&mesh);
- }
+ const LLCDParam* params;
+ S32 param_count = LLConvexDecomposition::getInstance()->getParameters(&params);
+
+ for (S32 i = 0; i < param_count; ++i)
+ {
+ param_map[params[i].mName] = params+i;
+ }
- if (ret)
- {
- llerrs << "Convex Decomposition thread valid but could not set mesh data" << llendl;
- }
- }
+ //set parameter values
+ for (decomp_params::iterator iter = mCurRequest->mParams.begin(); iter != mCurRequest->mParams.end(); ++iter)
+ {
+ const std::string& name = iter->first;
+ const LLSD& value = iter->second;
+ const LLCDParam* param = param_map[name];
- //build parameter map
- std::map<std::string, const LLCDParam*> param_map;
+ if (param == NULL)
+ { //couldn't find valid parameter
+ continue;
+ }
- const LLCDParam* params;
- S32 param_count = LLConvexDecomposition::getInstance()->getParameters(&params);
-
- for (S32 i = 0; i < param_count; ++i)
- {
- param_map[params[i].mName] = params+i;
- }
+ U32 ret = LLCD_OK;
- //set parameter values
- for (decomp_params::iterator iter = mCurRequest->mParams.begin(); iter != mCurRequest->mParams.end(); ++iter)
- {
- const std::string& name = iter->first;
- const LLSD& value = iter->second;
+ if (param->mType == LLCDParam::LLCD_FLOAT)
+ {
+ ret = LLConvexDecomposition::getInstance()->setParam(param->mName, (F32) value.asReal());
+ }
+ else if (param->mType == LLCDParam::LLCD_INTEGER ||
+ param->mType == LLCDParam::LLCD_ENUM)
+ {
+ ret = LLConvexDecomposition::getInstance()->setParam(param->mName, value.asInteger());
+ }
+ else if (param->mType == LLCDParam::LLCD_BOOLEAN)
+ {
+ ret = LLConvexDecomposition::getInstance()->setParam(param->mName, value.asBoolean());
+ }
- const LLCDParam* param = param_map[name];
+ if (ret)
+ {
+ llerrs << "WTF?" << llendl;
+ }
+ }
- if (param == NULL)
- { //couldn't find valid parameter
- continue;
- }
+ mCurRequest->setStatusMessage("Executing.");
- U32 ret = LLCD_OK;
+ LLCDResult ret = LLCD_OK;
+
+ if (LLConvexDecomposition::getInstance() != NULL)
+ {
+ ret = LLConvexDecomposition::getInstance()->executeStage(stage);
+ }
- if (param->mType == LLCDParam::LLCD_FLOAT)
- {
- ret = LLConvexDecomposition::getInstance()->setParam(param->mName, (F32) value.asReal());
- }
- else if (param->mType == LLCDParam::LLCD_INTEGER ||
- param->mType == LLCDParam::LLCD_ENUM)
- {
- ret = LLConvexDecomposition::getInstance()->setParam(param->mName, value.asInteger());
- }
- else if (param->mType == LLCDParam::LLCD_BOOLEAN)
- {
- ret = LLConvexDecomposition::getInstance()->setParam(param->mName, value.asBoolean());
- }
+ if (ret)
+ {
+ llerrs << "Convex Decomposition thread valid but could not execute stage " << stage << llendl;
+ }
- if (ret)
- {
- llerrs << "WTF?" << llendl;
- }
- }
+ mCurRequest->setStatusMessage("Reading results");
+
+ S32 num_hulls =0;
+ if (LLConvexDecomposition::getInstance() != NULL)
+ {
+ num_hulls = LLConvexDecomposition::getInstance()->getNumHullsFromStage(stage);
+ }
+
+ mMutex->lock();
+ mCurRequest->mHull.clear();
+ mCurRequest->mHull.resize(num_hulls);
- mCurRequest->setStatusMessage("Executing.");
+ mCurRequest->mHullMesh.clear();
+ mCurRequest->mHullMesh.resize(num_hulls);
+ mMutex->unlock();
- LLCDResult ret = LLCD_OK;
-
- if (LLConvexDecomposition::getInstance() != NULL)
- {
- ret = LLConvexDecomposition::getInstance()->executeStage(stage);
- }
+ for (S32 i = 0; i < num_hulls; ++i)
+ {
+ std::vector<LLVector3> p;
+ LLCDHull hull;
+ // if LLConvexDecomposition is a stub, num_hulls should have been set to 0 above, and we should not reach this code
+ LLConvexDecomposition::getInstance()->getHullFromStage(stage, i, &hull);
- if (ret)
- {
- llerrs << "Convex Decomposition thread valid but could not execute stage " << stage << llendl;
- }
+ const F32* v = hull.mVertexBase;
- mCurRequest->setStatusMessage("Reading results");
+ for (S32 j = 0; j < hull.mNumVertices; ++j)
+ {
+ LLVector3 vert(v[0], v[1], v[2]);
+ p.push_back(vert);
+ v = (F32*) (((U8*) v) + hull.mVertexStrideBytes);
+ }
+
+ LLCDMeshData mesh;
+ // if LLConvexDecomposition is a stub, num_hulls should have been set to 0 above, and we should not reach this code
+ LLConvexDecomposition::getInstance()->getMeshFromStage(stage, i, &mesh);
- S32 num_hulls =0;
- if (LLConvexDecomposition::getInstance() != NULL)
- {
- num_hulls = LLConvexDecomposition::getInstance()->getNumHullsFromStage(stage);
- }
+ mCurRequest->mHullMesh[i] = get_vertex_buffer_from_mesh(mesh);
+
+ mMutex->lock();
+ mCurRequest->mHull[i] = p;
+ mMutex->unlock();
+ }
+
+ {
+ LLMutexLock lock(mMutex);
+
+ mCurRequest->setStatusMessage("Done.");
+ mCurRequest->completed();
+
+ mCurRequest = NULL;
+ }
+}
+
+void LLPhysicsDecomp::doDecompositionSingleHull()
+{
+ LLCDMeshData mesh;
+
+ setMeshData(mesh);
- mMutex->lock();
- mCurRequest->mHull.clear();
- mCurRequest->mHull.resize(num_hulls);
+
+ //set all parameters to default
+ std::map<std::string, const LLCDParam*> param_map;
- mCurRequest->mHullMesh.clear();
- mCurRequest->mHullMesh.resize(num_hulls);
- mMutex->unlock();
+ const LLCDParam* params;
+ S32 param_count = LLConvexDecomposition::getInstance()->getParameters(&params);
+
+ LLConvexDecomposition* decomp = LLConvexDecomposition::getInstance();
- for (S32 i = 0; i < num_hulls; ++i)
- {
- std::vector<LLVector3> p;
- LLCDHull hull;
- // if LLConvexDecomposition is a stub, num_hulls should have been set to 0 above, and we should not reach this code
- LLConvexDecomposition::getInstance()->getHullFromStage(stage, i, &hull);
+ for (S32 i = 0; i < param_count; ++i)
+ {
+ decomp->setParam(params[i].mName, params[i].mDefault.mIntOrEnumValue);
+ }
- const F32* v = hull.mVertexBase;
+ const S32 STAGE_DECOMPOSE = mStageID["Decompose"];
+ const S32 STAGE_SIMPLIFY = mStageID["Simplify"];
+ const S32 DECOMP_PREVIEW = 0;
+ const S32 SIMPLIFY_RETAIN = 0;
+
+ decomp->setParam("Decompose Quality", DECOMP_PREVIEW);
+ decomp->setParam("Simplify Method", SIMPLIFY_RETAIN);
+ decomp->setParam("Retain%", 0.f);
- for (S32 j = 0; j < hull.mNumVertices; ++j)
- {
- LLVector3 vert(v[0], v[1], v[2]);
- p.push_back(vert);
- v = (F32*) (((U8*) v) + hull.mVertexStrideBytes);
- }
-
- LLCDMeshData mesh;
- // if LLConvexDecomposition is a stub, num_hulls should have been set to 0 above, and we should not reach this code
- LLConvexDecomposition::getInstance()->getMeshFromStage(stage, i, &mesh);
+ LLCDResult ret = LLCD_OK;
+ ret = decomp->executeStage(STAGE_DECOMPOSE);
+
+ if (ret)
+ {
+ llerrs << "Could not execute decomposition stage when attempting to create single hull." << llendl;
+ }
- mCurRequest->mHullMesh[i] = get_vertex_buffer_from_mesh(mesh);
+ ret = decomp->executeStage(STAGE_SIMPLIFY);
+
+ if (ret)
+ {
+ llerrs << "Could not execute simiplification stage when attempting to create single hull." << llendl;
+ }
+
+ S32 num_hulls =0;
+ if (LLConvexDecomposition::getInstance() != NULL)
+ {
+ num_hulls = LLConvexDecomposition::getInstance()->getNumHullsFromStage(STAGE_SIMPLIFY);
+ }
+
+ mMutex->lock();
+ mCurRequest->mHull.clear();
+ mCurRequest->mHull.resize(num_hulls);
+ mCurRequest->mHullMesh.clear();
+ mMutex->unlock();
+
+ for (S32 i = 0; i < num_hulls; ++i)
+ {
+ std::vector<LLVector3> p;
+ LLCDHull hull;
+ // if LLConvexDecomposition is a stub, num_hulls should have been set to 0 above, and we should not reach this code
+ LLConvexDecomposition::getInstance()->getHullFromStage(STAGE_SIMPLIFY, i, &hull);
+
+ const F32* v = hull.mVertexBase;
+
+ for (S32 j = 0; j < hull.mNumVertices; ++j)
+ {
+ LLVector3 vert(v[0], v[1], v[2]);
+ p.push_back(vert);
+ v = (F32*) (((U8*) v) + hull.mVertexStrideBytes);
+ }
- mMutex->lock();
- mCurRequest->mHull[i] = p;
- mMutex->unlock();
- }
+ mMutex->lock();
+ mCurRequest->mHull[i] = p;
+ mMutex->unlock();
+ }
+
+ {
+ LLMutexLock lock(mMutex);
+ mCurRequest->completed();
+ mCurRequest = NULL;
+ }
+}
+
+void LLPhysicsDecomp::run()
+{
+ LLConvexDecomposition::initSystem();
+ mInited = true;
+
+ LLConvexDecomposition* decomp = LLConvexDecomposition::getInstance();
+
+ const LLCDStageData* stages;
+ S32 num_stages = decomp->getStages(&stages);
+ for (S32 i = 0; i < num_stages; i++)
+ {
+ mStageID[stages[i].mName] = i;
+ }
+
+ while (!mQuitting)
+ {
+ mSignal->wait();
+ while (!mQuitting && !mRequestQ.empty())
+ {
+ mCurRequest = mRequestQ.front();
+ mRequestQ.pop();
+
+ if (mCurRequest->mStage == "single_hull")
{
- LLMutexLock lock(mMutex);
-
- mCurRequest->setStatusMessage("Done.");
- mCurRequest->completed();
-
- mCurRequest = NULL;
+ doDecompositionSingleHull();
}
+ else
+ {
+ doDecomposition();
+ }
}
}
diff --git a/indra/newview/llmeshrepository.h b/indra/newview/llmeshrepository.h
index e7270cc47d..4f790227b1 100644
--- a/indra/newview/llmeshrepository.h
+++ b/indra/newview/llmeshrepository.h
@@ -144,8 +144,10 @@ public:
LLUUID mMeshID;
LLModel::physics_shape mHull;
+ LLModel::hull mBaseHull;
std::vector<LLPointer<LLVertexBuffer> > mMesh;
+ LLPointer<LLVertexBuffer> mBaseHullMesh;
};
class LLPhysicsDecomp : public LLThread
@@ -189,6 +191,10 @@ public:
static S32 llcdCallback(const char*, S32, S32);
void cancel();
+ void setMeshData(LLCDMeshData& mesh);
+ void doDecomposition();
+ void doDecompositionSingleHull();
+
virtual void run();
std::map<std::string, S32> mStageID;
@@ -337,6 +343,26 @@ public:
class LLMeshUploadThread : public LLThread
{
public:
+ class DecompRequest : public LLPhysicsDecomp::Request
+ {
+ public:
+ LLPointer<LLModel> mModel;
+ LLPointer<LLModel> mBaseModel;
+
+ LLMeshUploadThread* mThread;
+
+ DecompRequest(LLModel* mdl, LLModel* base_model, LLMeshUploadThread* thread);
+
+ S32 statusCallback(const char* status, S32 p1, S32 p2) { return 1; }
+ void completed();
+ };
+
+ LLPointer<DecompRequest> mFinalDecomp;
+ bool mPhysicsComplete;
+
+ typedef std::map<LLPointer<LLModel>, std::vector<LLVector3> > hull_map;
+ hull_map mHullMap;
+
typedef std::vector<LLModelInstance> instance_list;
instance_list mInstanceList;
diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp
index 148c222014..b99829c3e4 100644
--- a/indra/newview/llspatialpartition.cpp
+++ b/indra/newview/llspatialpartition.cpp
@@ -2800,6 +2800,38 @@ S32 get_physics_detail(const LLVolumeParams& volume_params, const LLVector3& sca
return detail;
}
+void renderMeshBaseHull(LLVOVolume* volume, U32 data_mask, LLColor4& color)
+{
+ LLUUID mesh_id = volume->getVolume()->getParams().getSculptID();
+ const LLMeshDecomposition* decomp = gMeshRepo.getDecomposition(mesh_id);
+
+ if (decomp)
+ {
+ gGL.pushMatrix();
+ glMultMatrixf((F32*) volume->getRelativeXform().mMatrix);
+
+ gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+
+ LLVertexBuffer* buff = decomp->mBaseHullMesh;
+
+ buff->setBuffer(data_mask);
+
+ glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
+ glColor3fv(color.mV);
+ buff->drawArrays(LLRender::TRIANGLES, 0, buff->getNumVerts());
+ glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+
+ {
+ LLGLEnable blend(GL_BLEND);
+ gGL.setSceneBlendType(LLRender::BT_ALPHA);
+ LLGLDepthTest depth(GL_TRUE, GL_FALSE);
+ glColor4fv(color.mV);
+ buff->drawArrays(LLRender::TRIANGLES, 0, buff->getNumVerts());
+ }
+ gGL.popMatrix();
+ }
+}
+
void renderPhysicsShape(LLDrawable* drawable, LLVOVolume* volume)
{
U8 physics_type = volume->getPhysicsShapeType();
@@ -2875,6 +2907,13 @@ void renderPhysicsShape(LLDrawable* drawable, LLVOVolume* volume)
gGL.popMatrix();
}
}
+ else if (type == LLPhysicsShapeBuilderUtil::PhysicsShapeSpecification::USER_CONVEX)
+ {
+ if (volume->isMesh())
+ {
+ renderMeshBaseHull(volume, data_mask, color);
+ }
+ }
else if (type == LLPhysicsShapeBuilderUtil::PhysicsShapeSpecification::BOX)
{
gGL.pushMatrix();