From 712031bb2f70d68c1087b224706b7c82ab485745 Mon Sep 17 00:00:00 2001 From: Beq Date: Wed, 8 Feb 2023 22:16:24 +0000 Subject: [PATCH 1/2] changes towards fixing rigged local mesh WiP --- indra/newview/vjlocalmesh.cpp | 53 +++++++++++++++++--------- indra/newview/vjlocalmesh.h | 17 +++++---- indra/newview/vjlocalmeshimportdae.cpp | 40 ++++++++++++------- 3 files changed, 70 insertions(+), 40 deletions(-) diff --git a/indra/newview/vjlocalmesh.cpp b/indra/newview/vjlocalmesh.cpp index 70e87b31b4..8351366077 100644 --- a/indra/newview/vjlocalmesh.cpp +++ b/indra/newview/vjlocalmesh.cpp @@ -113,8 +113,8 @@ void LLLocalMeshObject::computeObjectBoundingBox() // process any additional faces for (size_t face_iter = 1; face_iter < lod3_faces.size(); ++face_iter) { - auto& current_bbox_min = lod3_faces[face_iter]->getFaceBoundingBox().first; - auto& current_bbox_max = lod3_faces[face_iter]->getFaceBoundingBox().second; + const auto& [current_bbox_min, current_bbox_max] = lod3_faces[face_iter]->getFaceBoundingBox(); + for (size_t array_iter = 0; array_iter < 4; ++array_iter) { @@ -130,30 +130,30 @@ void LLLocalMeshObject::computeObjectTransform(const LLMatrix4& scene_transform) // most things here were tactfully stolen from LLModel::normalizeVolumeFaces() // translation of bounding box to origin + // We will use this to centre the object at the origin (hence the -ve 1/2) mObjectTranslation = mObjectBoundingBox.first; mObjectTranslation += mObjectBoundingBox.second; mObjectTranslation *= -0.5f; - // actual bounding box size - mObjectSize = mObjectBoundingBox.second; - mObjectSize -= mObjectBoundingBox.first; + // actual bounding box size (max-min) + mObjectSize = mObjectBoundingBox.second - mObjectBoundingBox.first; - // make sure all axes of mObjectSize are non zero - for (auto& axis_size : mObjectSize.mV) + // make sure all axes of mObjectSize are non zero (don't adjust the 4th dim) + for ( int i=0; i <3; i++ ) { + auto& axis_size = mObjectSize[i]; // set size of 1.0 if < F_APPROXIMATELY_ZERO if (axis_size <= F_APPROXIMATELY_ZERO) { axis_size = 1.0f; } } - // bounding box scale in a 1Mx3 cube - mObjectScale.set(1.f, 1.f, 1.f); + // object scale is the inverse of the object size + mObjectScale.set(1.f, 1.f, 1.f,1.f); for (int vec_iter = 0; vec_iter < 4; ++vec_iter) { - mObjectScale.mV[vec_iter] = mObjectScale.mV[vec_iter] / mObjectSize.mV[vec_iter]; - } - + mObjectScale[vec_iter] /= mObjectSize[vec_iter]; + } } void LLLocalMeshObject::normalizeFaceValues(LLLocalMeshFileLOD lod_iter) @@ -172,15 +172,18 @@ void LLLocalMeshObject::normalizeFaceValues(LLLocalMeshFileLOD lod_iter) // process current lod for (auto& current_face : lod_faces) { - // first transform the bounding boxes + // first transform the bounding boxes ro be centred at 0,0,0 auto& current_submesh_bbox = current_face->getFaceBoundingBox(); current_submesh_bbox.first += mObjectTranslation; current_submesh_bbox.second += mObjectTranslation; + + LL_INFOS("LocalMesh") << "before squish:" << current_submesh_bbox.first << " " << current_submesh_bbox.second << LL_ENDL; for (int vec_iter = 0; vec_iter < 4; ++vec_iter) { current_submesh_bbox.first.mV[vec_iter] *= mObjectScale.mV[vec_iter]; current_submesh_bbox.second.mV[vec_iter] *= mObjectScale.mV[vec_iter]; } + LL_INFOS("LocalMesh") << "after squish:" << current_submesh_bbox.first << " " << current_submesh_bbox.second << LL_ENDL; // then transform the positions auto& current_face_positions = current_face->getPositions(); @@ -309,13 +312,18 @@ void LLLocalMeshObject::attachSkinInfo() auto skinmap_seeker = gMeshRepo.mSkinMap.find(mSculptID); if (skinmap_seeker == gMeshRepo.mSkinMap.end()) { - gMeshRepo.mSkinMap[mSculptID] = &mMeshSkinInfo; + // Not found create it + mMeshSkinInfoPtr->mMeshID = mSculptID; + gMeshRepo.mSkinMap[mSculptID] = mMeshSkinInfoPtr; + LL_INFOS("LocalMesh") << "Skinmap entry for UUID " << mSculptID << " created with " << std::hex << std::showbase << (void *)mMeshSkinInfoPtr << LL_ENDL; } else { - // NOTE: seems necessary, not tested without. - skinmap_seeker->second = &mMeshSkinInfo; + // found but we will update it to ours + LL_INFOS("LocalMesh") << "Skinmap entry for UUID " << mSculptID << " updated from " << std::hex << std::showbase << (void *)skinmap_seeker->second << " to " << (void *)mMeshSkinInfoPtr << LL_ENDL; + skinmap_seeker->second = mMeshSkinInfoPtr; } + } bool LLLocalMeshObject::getIsRiggedObject() const @@ -326,6 +334,7 @@ bool LLLocalMeshObject::getIsRiggedObject() const // main lod isn't empty if (!main_lod_faces.empty()) { + LL_INFOS("LocalMesh") << "Main lod is not empty" << LL_ENDL; auto& skin = main_lod_faces[0]->getSkin(); if (!skin.empty()) { @@ -750,22 +759,30 @@ void LLLocalMeshFile::applyToVObject(LLUUID viewer_object_id, int object_index, auto current_lod = static_cast(lod_reverse_iter); mLoadedObjectList[object_index]->fillVolume(current_lod); + LL_INFOS("LocalMesh") << "Loaded LOD " << current_lod << LL_ENDL; } - + LL_INFOS("LocalMesh") << "Loaded Object " << object_index << LL_ENDL; if (mLoadedObjectList[object_index]->getIsRiggedObject()) { + LL_INFOS("LocalMesh") << "Object " << object_index << " is rigged" << LL_ENDL; mLoadedObjectList[object_index]->attachSkinInfo(); + target_object->notifySkinInfoLoaded(mLoadedObjectList[object_index]->getObjectMeshSkinInfo()); } if ((!target_object->isAttachment()) && use_scale) { + LL_INFOS("LocalMesh") << "Object " << object_index << " is not attachment" << LL_ENDL; auto scale = mLoadedObjectList[object_index]->getObjectSize(); target_object->setScale(LLVector3(scale), false); } // force refresh (selected/edit mode won't let it redraw otherwise) - gPipeline.markRebuild(target_object->mDrawable, LLDrawable::REBUILD_VOLUME, FALSE); + auto& target_drawable = target_object->mDrawable; + target_drawable->getVOVolume()->forceLOD(LLModel::LOD_LOW); + target_drawable->getVOVolume()->forceLOD(LLModel::LOD_HIGH); + gPipeline.markRebuild(target_drawable, LLDrawable::REBUILD_VOLUME, FALSE); // NOTE: this ^^ (or lod change) causes renderer crash on mesh with degenerate primitives. + LL_INFOS("LocalMesh") << "Object " << object_index << " marked for rebuild" << LL_ENDL; } void LLLocalMeshFile::pushLog(const std::string& who, const std::string& what, bool is_error) diff --git a/indra/newview/vjlocalmesh.h b/indra/newview/vjlocalmesh.h index aa4ce2e8ee..28b294b9a1 100644 --- a/indra/newview/vjlocalmesh.h +++ b/indra/newview/vjlocalmesh.h @@ -107,13 +107,14 @@ class LLLocalMeshObject // getters std::vector>& getFaces(LLLocalMeshFileLOD lod) { return mFaces[lod]; }; std::pair& getObjectBoundingBox() { return mObjectBoundingBox; }; - LLVector4 getObjectTranslation() const { return mObjectTranslation; }; - std::string getObjectName() const { return mObjectName; }; - LLVector4 getObjectSize() const { return mObjectSize; }; - LLVector4 getObjectScale() const { return mObjectScale; }; - LLMeshSkinInfo& getObjectMeshSkinInfo() { return mMeshSkinInfo; }; - LLVolumeParams getVolumeParams() const { return mVolumeParams; }; - bool getIsRiggedObject() const; + LLVector4 getObjectTranslation() const { return mObjectTranslation; }; + std::string getObjectName() const { return mObjectName; }; + LLVector4 getObjectSize() const { return mObjectSize; }; + LLVector4 getObjectScale() const { return mObjectScale; }; + LLPointer getObjectMeshSkinInfo() { return mMeshSkinInfoPtr; }; + void setObjectMeshSkinInfo(LLPointer skininfop ) { mMeshSkinInfoPtr = skininfop; }; + LLVolumeParams getVolumeParams() const { return mVolumeParams; }; + bool getIsRiggedObject() const; private: // internal data keeping @@ -125,7 +126,7 @@ class LLLocalMeshObject LLVector4 mObjectScale; // vovolume - LLMeshSkinInfo mMeshSkinInfo; + LLPointer mMeshSkinInfoPtr{nullptr}; LLUUID mSculptID; LLVolumeParams mVolumeParams; }; diff --git a/indra/newview/vjlocalmeshimportdae.cpp b/indra/newview/vjlocalmeshimportdae.cpp index fc0f63034e..8661496df9 100644 --- a/indra/newview/vjlocalmeshimportdae.cpp +++ b/indra/newview/vjlocalmeshimportdae.cpp @@ -485,8 +485,19 @@ bool LLLocalMeshImportDAE::processSkin(daeDatabase* collada_db, daeElement* coll LLVector4 objct_size = current_object->getObjectSize(); // this is basically the data_out but for skinning data - auto& skininfo = current_object->getObjectMeshSkinInfo(); - + LLPointer skininfop = current_object->getObjectMeshSkinInfo(); + if (skininfop == nullptr) + { + try + { + skininfop = new LLMeshSkinInfo(); + } + catch (const std::bad_alloc& ex) + { + LL_WARNS() << "Failed to allocate skin info with exception: " << ex.what() << LL_ENDL; + return false; + } + } // basically copy-pasted from linden magic LLMatrix4 normalized_transformation; LLMatrix4 mesh_scale; @@ -513,10 +524,10 @@ bool LLLocalMeshImportDAE::processSkin(daeDatabase* collada_db, daeElement* coll mat4_proxy.mMatrix[matrix_i][matrix_j] = bind_matrix_value[matrix_i + (matrix_j * 4)]; } } - skininfo.mBindShapeMatrix.loadu(mat4_proxy); + skininfop->mBindShapeMatrix.loadu(mat4_proxy); // matrix multiplication order matters, so this is as clean as it gets. LLMatrix4a transform{normalized_transformation}; - matMul(transform, skininfo.mBindShapeMatrix, skininfo.mBindShapeMatrix); + matMul(transform, skininfop->mBindShapeMatrix, skininfop->mBindShapeMatrix); } // setup joint map @@ -611,7 +622,7 @@ bool LLLocalMeshImportDAE::processSkin(daeDatabase* collada_db, daeElement* coll // jointlist processing // moved this lambda definition out of the loop below. - auto lambda_process_joint_name = [&skininfo, &joint_map](std::string joint_name) + auto lambda_process_joint_name = [&skininfo = *skininfop, &joint_map](std::string joint_name) { // looking for internal joint name, otherwise use provided name? // seems weird, but ok. @@ -695,13 +706,13 @@ bool LLLocalMeshImportDAE::processSkin(daeDatabase* collada_db, daeElement* coll } } - skininfo.mInvBindMatrix.push_back(LLMatrix4a(current_matrix)); + skininfop->mInvBindMatrix.push_back(LLMatrix4a(current_matrix)); } } } int jointname_number_iter = 0; - for (auto jointname_iterator = skininfo.mJointNames.begin(); jointname_iterator != skininfo.mJointNames.end(); ++jointname_iterator, ++jointname_number_iter) + for (auto jointname_iterator = skininfop->mJointNames.begin(); jointname_iterator != skininfop->mJointNames.end(); ++jointname_iterator, ++jointname_number_iter) { std::string name_lookup = jointname_iterator->mName; if (joint_map.find(name_lookup) == joint_map.end()) @@ -710,25 +721,25 @@ bool LLLocalMeshImportDAE::processSkin(daeDatabase* collada_db, daeElement* coll continue; } - if (skininfo.mInvBindMatrix.size() <= jointname_number_iter) + if (skininfop->mInvBindMatrix.size() <= jointname_number_iter) { // doesn't seem like a critical fail that should invalidate the entire skin, just break and move on? pushLog("DAE Importer", "WARNING: Requesting out of bounds joint named " + name_lookup); break; } - LLMatrix4 newinverse = LLMatrix4(skininfo.mInvBindMatrix[jointname_number_iter].getF32ptr()); + LLMatrix4 newinverse = LLMatrix4(skininfop->mInvBindMatrix[jointname_number_iter].getF32ptr()); auto joint_translation = joint_transforms[name_lookup].getTranslation(); newinverse.setTranslation(joint_translation); - skininfo.mAlternateBindMatrix.push_back( LLMatrix4a(newinverse) ); + skininfop->mAlternateBindMatrix.push_back( LLMatrix4a(newinverse) ); } - size_t bind_count = skininfo.mAlternateBindMatrix.size(); - if ((bind_count > 0) && (bind_count != skininfo.mJointNames.size())) + size_t bind_count = skininfop->mAlternateBindMatrix.size(); + if ((bind_count > 0) && (bind_count != skininfop->mJointNames.size())) { // different number of binds vs jointnames, i hestiate to fail the entire skinmap over this // because it can just be a case of a few additional joints being ignored, unless i'm missing something? - pushLog("DAE Importer", "WARNING: " + std::to_string(skininfo.mJointNames.size()) + " joints were found, but " + std::to_string(bind_count) + " binds matrices were made."); + pushLog("DAE Importer", "WARNING: " + std::to_string(skininfop->mJointNames.size()) + " joints were found, but " + std::to_string(bind_count) + " binds matrices were made."); } //============================== @@ -964,7 +975,8 @@ bool LLLocalMeshImportDAE::processSkin(daeDatabase* collada_db, daeElement* coll weights.push_back(new_wght); } } - + skininfop->updateHash(); + current_object->setObjectMeshSkinInfo(skininfop); return true; } From 9d3470017904cf3bb1503712ee9919c929c16ae2 Mon Sep 17 00:00:00 2001 From: Beq Date: Fri, 10 Feb 2023 02:55:19 +0000 Subject: [PATCH 2/2] experimental workaround to non-rigged to rigged transition bug --- indra/newview/vjlocalmesh.cpp | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/indra/newview/vjlocalmesh.cpp b/indra/newview/vjlocalmesh.cpp index 8351366077..656525e0ab 100644 --- a/indra/newview/vjlocalmesh.cpp +++ b/indra/newview/vjlocalmesh.cpp @@ -778,9 +778,18 @@ void LLLocalMeshFile::applyToVObject(LLUUID viewer_object_id, int object_index, // force refresh (selected/edit mode won't let it redraw otherwise) auto& target_drawable = target_object->mDrawable; - target_drawable->getVOVolume()->forceLOD(LLModel::LOD_LOW); - target_drawable->getVOVolume()->forceLOD(LLModel::LOD_HIGH); - gPipeline.markRebuild(target_drawable, LLDrawable::REBUILD_VOLUME, FALSE); + + if( target_drawable.notNull() ) + { + target_object->markForUpdate(true); + // target_drawable->updateSpatialExtents(); + // target_drawable->movePartition(); + gPipeline.markRebuild(target_drawable, LLDrawable::REBUILD_ALL, true); + if(auto floater_ptr = LLLocalMeshSystem::getInstance()->getFloaterPointer(); floater_ptr != nullptr) + { + floater_ptr->toggleSelectTool(false); + } + } // NOTE: this ^^ (or lod change) causes renderer crash on mesh with degenerate primitives. LL_INFOS("LocalMesh") << "Object " << object_index << " marked for rebuild" << LL_ENDL; }