Added mandatory single hull simplification to mesh upload.

meow-7.2.2
Dave Parks 2010-10-06 01:17:12 -05:00
parent 98d622551d
commit 24e0d62a5e
6 changed files with 579 additions and 187 deletions

View File

@ -1289,10 +1289,17 @@ 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;
U32 vert_idx = 0;
for (U32 i = 0; i < decomp.size(); ++i)
if (!hulls.empty())
{
for (U32 j = 0; j < decomp[i].size(); ++j)
mdl["decomposition"]["HullList"] = hulls;
}
if (total > 0)
{
LLSD::Binary p(total*3*2);
LLVector3 range = max-min;
U32 vert_idx = 0;
for (U32 i = 0; i < decomp.size(); ++i)
{
for (U32 j = 0; j < decomp[i].size(); ++j)
{
for (U32 k = 0; k < 3; k++)
{
//convert to 16-bit normalized across domain
U16 val = (U16) (((decomp[i][j].mV[k]-min.mV[k])/range.mV[k])*65535);
U8* buff = (U8*) &val;
//write to binary buffer
p[vert_idx++] = buff[0];
p[vert_idx++] = buff[1];
if (vert_idx > p.size())
{
llerrs << "WTF?" << llendl;
}
}
}
}
mdl["decomposition"]["Position"] = p;
}
if (!base_hull.empty())
{
LLSD::Binary p(base_hull.size()*3*2);
LLVector3 range = max-min;
U32 vert_idx = 0;
for (U32 j = 0; j < base_hull.size(); ++j)
{
for (U32 k = 0; k < 3; k++)
{
//convert to 16-bit normalized across domain
U16 val = (U16) (((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)

View File

@ -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);

View File

@ -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;
}
}

View File

@ -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();
U16* p = (U16*) &position[0];
d->mHull.resize(hulls.size());
LLVector3 min;
LLVector3 max;
LLVector3 range;
min.setValue(decomp["Min"]);
max.setValue(decomp["Max"]);
range = max-min;
for (U32 i = 0; i < hulls.size(); ++i)
if (decomp.has("HullList"))
{
U16 count = (hulls[i] == 0) ? 256 : hulls[i];
// 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];
d->mHull.resize(hulls.size());
LLVector3 min;
LLVector3 max;
LLVector3 range;
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;
}
}
//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"))
{
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,11 +2772,253 @@ S32 LLPhysicsDecomp::llcdCallback(const char* status, S32 p1, S32 p2)
return 1;
}
void LLPhysicsDecomp::setMeshData(LLCDMeshData& mesh)
{
mesh.mVertexBase = mCurRequest->mPositions[0].mV;
mesh.mVertexStrideBytes = 12;
mesh.mNumVertices = mCurRequest->mPositions.size();
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)
{
ret = LLConvexDecomposition::getInstance()->setMeshData(&mesh);
}
if (ret)
{
llerrs << "Convex Decomposition thread valid but could not set mesh data" << llendl;
}
}
void LLPhysicsDecomp::doDecomposition()
{
LLCDMeshData mesh;
S32 stage = mStageID[mCurRequest->mStage];
//load data intoLLCD
if (stage == 0)
{
setMeshData(mesh);
}
//build parameter map
std::map<std::string, const LLCDParam*> param_map;
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;
}
//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];
if (param == NULL)
{ //couldn't find valid parameter
continue;
}
U32 ret = LLCD_OK;
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 << "WTF?" << llendl;
}
}
mCurRequest->setStatusMessage("Executing.");
LLCDResult ret = LLCD_OK;
if (LLConvexDecomposition::getInstance() != NULL)
{
ret = LLConvexDecomposition::getInstance()->executeStage(stage);
}
if (ret)
{
llerrs << "Convex Decomposition thread valid but could not execute stage " << stage << 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->mHullMesh.clear();
mCurRequest->mHullMesh.resize(num_hulls);
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, 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);
}
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);
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);
//set all parameters to default
std::map<std::string, const LLCDParam*> param_map;
const LLCDParam* params;
S32 param_count = LLConvexDecomposition::getInstance()->getParameters(&params);
LLConvexDecomposition* decomp = LLConvexDecomposition::getInstance();
for (S32 i = 0; i < param_count; ++i)
{
decomp->setParam(params[i].mName, params[i].mDefault.mIntOrEnumValue);
}
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);
LLCDResult ret = LLCD_OK;
ret = decomp->executeStage(STAGE_DECOMPOSE);
if (ret)
{
llerrs << "Could not execute decomposition stage when attempting to create single hull." << llendl;
}
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();
}
{
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();
@ -2648,146 +3027,14 @@ void LLPhysicsDecomp::run()
mCurRequest = mRequestQ.front();
mRequestQ.pop();
LLCDMeshData mesh;
S32 stage = mStageID[mCurRequest->mStage];
//load data intoLLCD
if (stage == 0)
if (mCurRequest->mStage == "single_hull")
{
mesh.mVertexBase = mCurRequest->mPositions[0].mV;
mesh.mVertexStrideBytes = 12;
mesh.mNumVertices = mCurRequest->mPositions.size();
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)
{
ret = LLConvexDecomposition::getInstance()->setMeshData(&mesh);
}
if (ret)
{
llerrs << "Convex Decomposition thread valid but could not set mesh data" << llendl;
}
doDecompositionSingleHull();
}
//build parameter map
std::map<std::string, const LLCDParam*> param_map;
const LLCDParam* params;
S32 param_count = LLConvexDecomposition::getInstance()->getParameters(&params);
for (S32 i = 0; i < param_count; ++i)
else
{
param_map[params[i].mName] = params+i;
}
//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];
if (param == NULL)
{ //couldn't find valid parameter
continue;
}
U32 ret = LLCD_OK;
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 << "WTF?" << llendl;
}
}
mCurRequest->setStatusMessage("Executing.");
LLCDResult ret = LLCD_OK;
if (LLConvexDecomposition::getInstance() != NULL)
{
ret = LLConvexDecomposition::getInstance()->executeStage(stage);
}
if (ret)
{
llerrs << "Convex Decomposition thread valid but could not execute stage " << stage << 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->mHullMesh.clear();
mCurRequest->mHullMesh.resize(num_hulls);
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, 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);
}
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);
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;
}
doDecomposition();
}
}
}

View File

@ -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;

View File

@ -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();