Added mandatory single hull simplification to mesh upload.
parent
98d622551d
commit
24e0d62a5e
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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*) ¶m[i]);
|
||||
mDecompFloater->addChild(combo_box);
|
||||
cur_y += 30;
|
||||
|
||||
}
|
||||
|
||||
llinfos << "----" << llendl;
|
||||
}
|
||||
llinfos << "-----------------------------" << llendl;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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(¶ms);
|
||||
|
||||
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(¶ms);
|
||||
|
||||
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(¶ms);
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
Loading…
Reference in New Issue