diff options
Diffstat (limited to 'indra/newview/llfloatermodelpreview.cpp')
-rw-r--r-- | indra/newview/llfloatermodelpreview.cpp | 211 |
1 files changed, 198 insertions, 13 deletions
diff --git a/indra/newview/llfloatermodelpreview.cpp b/indra/newview/llfloatermodelpreview.cpp index 2a3bd37129..f21d60dd03 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; } @@ -314,15 +413,17 @@ BOOL LLFloaterModelPreview::postBuild() childSetCommitCallback("pelvis_offset", onPelvisOffsetCommit, this); childSetCommitCallback("lod_file_or_limit", refresh, this); - childSetCommitCallback("physics_load_radio", refresh, this); + childSetCommitCallback("physics_load_radio", onPhysicsLoadRadioCommit, this); //childSetCommitCallback("physics_optimize", refresh, this); //childSetCommitCallback("physics_use_hull", refresh, this); childDisable("upload_skin"); childDisable("upload_joints"); - + childDisable("ok_btn"); + childSetCommitCallback("confirm_checkbox", refresh, this); + mViewOptionMenuButton = getChild<LLMenuButton>("options_gear_btn"); mCommitCallbackRegistrar.add("ModelImport.ViewOption.Action", boost::bind(&LLFloaterModelPreview::onViewOptionChecked, this, _2)); @@ -470,6 +571,29 @@ void LLFloaterModelPreview::onPelvisOffsetCommit( LLUICtrl*, void* userdata ) } //static +void LLFloaterModelPreview::onPhysicsLoadRadioCommit( LLUICtrl*, void *userdata) +{ + LLFloaterModelPreview* fmp = LLFloaterModelPreview::sInstance; + if (fmp) + { + if (fmp->childGetValue("physics_use_lod").asBoolean()) + { + onPhysicsUseLOD(NULL,NULL); + } + if (fmp->childGetValue("physics_load_from_file").asBoolean()) + { + + } + LLModelPreview *model_preview = fmp->mModelPreview; + if (model_preview) + { + model_preview->refresh(); + model_preview->updateStatusMessages(); + } + } +} + +//static void LLFloaterModelPreview::onUploadJointsCommit(LLUICtrl*,void* userdata) { LLFloaterModelPreview *fp =(LLFloaterModelPreview *)userdata; @@ -1634,7 +1758,7 @@ bool LLModelLoader::doLoadModel() { if (pos.getCount() <= j+2) { - llerrs << "WTF?" << llendl; + llerrs << "Invalid position array size." << llendl; } LLVector3 v(pos[j], pos[j+1], pos[j+2]); @@ -2296,8 +2420,11 @@ void LLModelLoader::processElement(daeElement* element) { domFloat3 dom_value = scale->getValue(); + + LLVector3 scale_vector = LLVector3(dom_value[0], dom_value[1], dom_value[2]); + scale_vector.abs(); // Set all values positive, since we don't currently support mirrored meshes LLMatrix4 scaling; - scaling.initScale(LLVector3(dom_value[0], dom_value[1], dom_value[2])); + scaling.initScale(scale_vector); scaling *= mTransform; mTransform = scaling; @@ -2675,7 +2802,8 @@ U32 LLModelPreview::calcResourceCost() if (mFMP && mModelLoader) { - if ( getLoadState() < LLModelLoader::ERROR_PARSING ) + const BOOL confirmed_checkbox = mFMP->getChild<LLCheckBoxCtrl>("confirm_checkbox")->getValue().asBoolean(); + if ( getLoadState() < LLModelLoader::ERROR_PARSING && confirmed_checkbox ) { mFMP->childEnable("ok_btn"); } @@ -2817,7 +2945,8 @@ void LLModelPreview::rebuildUploadData() F32 max_scale = 0.f; - if ( mBaseScene.size() > 0 ) + const BOOL confirmed_checkbox = mFMP->getChild<LLCheckBoxCtrl>("confirm_checkbox")->getValue().asBoolean(); + if ( mBaseScene.size() > 0 && confirmed_checkbox ) { mFMP->childEnable("ok_btn"); } @@ -3221,6 +3350,8 @@ void LLModelPreview::loadModelCallback(S32 lod) } mLoading = false; + if (mFMP) + mFMP->getChild<LLCheckBoxCtrl>("confirm_checkbox")->set(FALSE); refresh(); mModelLoadedSignal(); @@ -3752,7 +3883,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"); @@ -3853,7 +4012,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; + } } } @@ -3876,7 +4038,8 @@ void LLModelPreview::updateStatusMessages() } } - if ( upload_ok && !errorStateFromLoader && skinAndRigOk ) + const BOOL confirmed_checkbox = mFMP->getChild<LLCheckBoxCtrl>("confirm_checkbox")->getValue().asBoolean(); + if ( upload_ok && !errorStateFromLoader && skinAndRigOk && !has_degenerate && confirmed_checkbox) { mFMP->childEnable("ok_btn"); } @@ -4238,11 +4401,7 @@ void LLModelPreview::genBuffers(S32 lod, bool include_skin_weights) const LLModel::weight_list& weight_list = base_mdl->getJointInfluences(pos); LLVector4 w(0,0,0,0); - if (weight_list.size() > 4) - { - llerrs << "WTF?" << llendl; - } - + for (U32 i = 0; i < weight_list.size(); ++i) { F32 wght = llmin(weight_list[i].mWeight, 0.999999f); @@ -4666,6 +4825,32 @@ BOOL LLModelPreview::render() glLineWidth(3.f); glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); buffer->drawRange(LLRender::TRIANGLES, 0, buffer->getNumVerts()-1, buffer->getNumIndices(), 0); + + { //show degenerate triangles + LLStrider<LLVector3> pos_strider; + buffer->getVertexStrider(pos_strider, 0); + LLVector4a* pos = (LLVector4a*) pos_strider.get(); + + LLGLDepthTest depth(GL_TRUE, GL_FALSE, GL_ALWAYS); + LLGLDisable cull(GL_CULL_FACE); + LLStrider<U16> idx; + buffer->getIndexStrider(idx, 0); + + glColor4f(1.f,0.f,0.f,1.f); + const LLVector4a scale(0.5f); + 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::TRIANGLES, 3, i); + } + } + } + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); glLineWidth(1.f); } |