diff options
author | Erik Kundiman <erik@megapahit.org> | 2024-09-28 18:01:02 +0800 |
---|---|---|
committer | Erik Kundiman <erik@megapahit.org> | 2024-10-18 18:38:25 +0800 |
commit | ad3cbb9f75c4ea7f0473225afc034c403b54fc82 (patch) | |
tree | 4e4239e97a405d2820e26a4f2215ad8ccb88af7e /indra/newview/llface.cpp | |
parent | 7fdb350e487acc35b26de6e243ff27f94185d3a5 (diff) | |
parent | 64c055f9be03861661f8c211ae36ba0db489b12d (diff) |
Merge remote-tracking branch 'secondlife/release/2024.09-ExtraFPS' into 2024.09-ExtraFPS
Diffstat (limited to 'indra/newview/llface.cpp')
-rw-r--r-- | indra/newview/llface.cpp | 174 |
1 files changed, 134 insertions, 40 deletions
diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp index b37073122b..7717dba1af 100644 --- a/indra/newview/llface.cpp +++ b/indra/newview/llface.cpp @@ -56,6 +56,7 @@ #include "llvoavatar.h" #include "llsculptidsize.h" #include "llmeshrepository.h" +#include "llskinningutil.h" #define LL_MAX_INDICES_COUNT 1000000 @@ -1490,9 +1491,9 @@ bool LLFace::getGeometryVolume(const LLVolume& volume, } //TODO -- cache this (check profile marker above)? - glh::matrix4f m((F32*) skin->mBindShapeMatrix.getF32ptr()); - m = m.inverse().transpose(); - mat_normal.loadu(m.m); + glm::mat4 m = glm::make_mat4((F32*)skin->mBindShapeMatrix.getF32ptr()); + m = glm::transpose(glm::inverse(m)); + mat_normal.loadu(glm::value_ptr(m)); } else { @@ -1744,7 +1745,7 @@ bool LLFace::getGeometryVolume(const LLVolume& volume, { //bump mapped or has material, just do the whole expensive loop LL_PROFILE_ZONE_NAMED_CATEGORY_FACE("getGeometryVolume - texgen default"); - std::vector<LLVector2> bump_tc; + LLStrider<LLVector2> bump_tc; if (mat && !mat->getNormalID().isNull()) { //writing out normal and specular texture coordinates, not bump offsets @@ -1806,49 +1807,70 @@ bool LLFace::getGeometryVolume(const LLVolume& volume, } const bool do_xform = (xforms & xform_channel) != XFORM_NONE; + // hold onto strider to front of TC array for use later + bump_tc = dst; - for (S32 i = 0; i < num_vertices; i++) { - LLVector2 tc(vf.mTexCoords[i]); - - LLVector4a& norm = vf.mNormals[i]; - - LLVector4a& center = *(vf.mCenter); - - if (texgen != LLTextureEntry::TEX_GEN_DEFAULT) + // NOTE: split TEX_GEN_PLANAR implementation to reduce branchiness of inner loop + // These are per-vertex operations and every little bit counts + if (texgen == LLTextureEntry::TEX_GEN_PLANAR) { - LLVector4a vec = vf.mPositions[i]; + LL_PROFILE_ZONE_NAMED_CATEGORY_FACE("tgd - planar"); + for (S32 i = 0; i < num_vertices; i++) + { + LLVector2 tc(vf.mTexCoords[i]); + LLVector4a& norm = vf.mNormals[i]; + LLVector4a& center = *(vf.mCenter); + LLVector4a vec = vf.mPositions[i]; - vec.mul(scalea); + vec.mul(scalea); - if (texgen == LLTextureEntry::TEX_GEN_PLANAR) - { planarProjection(tc, norm, center, vec); - } - } - if (tex_mode && mTextureMatrix) - { - LLVector3 tmp(tc.mV[0], tc.mV[1], 0.f); - tmp = tmp * *mTextureMatrix; - tc.mV[0] = tmp.mV[0]; - tc.mV[1] = tmp.mV[1]; + if (tex_mode && mTextureMatrix) + { + LLVector3 tmp(tc.mV[0], tc.mV[1], 0.f); + tmp = tmp * *mTextureMatrix; + tc.mV[0] = tmp.mV[0]; + tc.mV[1] = tmp.mV[1]; + } + else if (do_xform) + { + xform(tc, cos_ang, sin_ang, os, ot, ms, mt); + } + + *dst++ = tc; + } } - else if (do_xform) + else { - xform(tc, cos_ang, sin_ang, os, ot, ms, mt); - } + LL_PROFILE_ZONE_NAMED_CATEGORY_FACE("tgd - transform"); - *dst++ = tc; - if (do_bump) - { - bump_tc.push_back(tc); + for (S32 i = 0; i < num_vertices; i++) + { + LLVector2 tc(vf.mTexCoords[i]); + + if (tex_mode && mTextureMatrix) + { + LLVector3 tmp(tc.mV[0], tc.mV[1], 0.f); + tmp = tmp * *mTextureMatrix; + tc.mV[0] = tmp.mV[0]; + tc.mV[1] = tmp.mV[1]; + } + else if (do_xform) + { + xform(tc, cos_ang, sin_ang, os, ot, ms, mt); + } + + *dst++ = tc; + } } } } if ((!mat && !gltf_mat) && do_bump) { + LL_PROFILE_ZONE_NAMED_CATEGORY_FACE("tgd - do bump"); mVertexBuffer->getTexCoord1Strider(tex_coords1, mGeomIndex, mGeomCount); mVObjp->getVolume()->genTangents(face_index); @@ -2150,7 +2172,7 @@ F32 LLFace::getTextureVirtualSize() face_area = mPixelArea / llclamp(texel_area, 0.015625f, 128.f); } - face_area = LLFace::adjustPixelArea(mImportanceToCamera, face_area) ; + face_area = LLFace::adjustPixelArea(mImportanceToCamera, face_area); if(face_area > LLViewerTexture::sMinLargeImageSize) //if is large image, shrink face_area by considering the partial overlapping. { if(mImportanceToCamera > LEAST_IMPORTANCE_FOR_LARGE_IMAGE && mTexture[LLRender::DIFFUSE_MAP].notNull() && mTexture[LLRender::DIFFUSE_MAP]->isLargeImage()) @@ -2166,29 +2188,96 @@ F32 LLFace::getTextureVirtualSize() bool LLFace::calcPixelArea(F32& cos_angle_to_view_dir, F32& radius) { + constexpr F32 PIXEL_AREA_UPDATE_PERIOD = 0.1f; + // this is an expensive operation and the result is valid (enough) for several frames + // don't update every frame + if (gFrameTimeSeconds - mLastPixelAreaUpdate < PIXEL_AREA_UPDATE_PERIOD) + { + return true; + } + LL_PROFILE_ZONE_SCOPED_CATEGORY_FACE; - //VECTORIZE THIS //get area of circle around face - LLVector4a center; LLVector4a size; - if (isState(LLFace::RIGGED)) { - //override with avatar bounding box + LL_PROFILE_ZONE_NAMED_CATEGORY_FACE("calcPixelArea - rigged"); + //override with joint volume face joint bounding boxes LLVOAvatar* avatar = mVObjp->getAvatar(); + bool hasRiggedExtents = false; + if (avatar && avatar->mDrawable) { - center.load3(avatar->getPositionAgent().mV); - const LLVector4a* exts = avatar->mDrawable->getSpatialExtents(); - size.setSub(exts[1], exts[0]); + LLVolume* volume = mVObjp->getVolume(); + if (volume) + { + LLVolumeFace& face = volume->getVolumeFace(mTEOffset); + + auto& rigInfo = face.mJointRiggingInfoTab; + + if (rigInfo.needsUpdate()) + { + LLVOVolume* vo_volume = (LLVOVolume*)mVObjp.get(); + LLVOAvatar* avatar = mVObjp->getAvatar(); + const LLMeshSkinInfo* skin = vo_volume->getSkinInfo(); + LLSkinningUtil::updateRiggingInfo(skin, avatar, face); + } + + // calculate the world space bounding box of the face by combining the bounding boxes of all the joints + LLVector4a& minp = mRiggedExtents[0]; + LLVector4a& maxp = mRiggedExtents[1]; + minp = LLVector4a(FLT_MAX, FLT_MAX, FLT_MAX); + maxp = LLVector4a(-FLT_MAX, -FLT_MAX, -FLT_MAX); + + for (S32 i = 0; i < rigInfo.size(); i++) + { + auto& jointInfo = rigInfo[i]; + if (jointInfo.isRiggedTo()) + { + LLJoint* joint = avatar->getJoint(i); + + if (joint) + { + LLVector4a jointPos; + + LLMatrix4a worldMat; + worldMat.loadu((F32*)&joint->getWorldMatrix().mMatrix[0][0]); + + LLVector4a extents[2]; + + matMulBoundBox(worldMat, jointInfo.getRiggedExtents(), extents); + + minp.setMin(minp, extents[0]); + maxp.setMax(maxp, extents[1]); + hasRiggedExtents = true; + } + } + } + } } - else + + if (!hasRiggedExtents) { + // no rigged extents, zero out bounding box and skip update + mRiggedExtents[0] = mRiggedExtents[1] = LLVector4a(0.f, 0.f, 0.f); + return false; } + + center.setAdd(mRiggedExtents[1], mRiggedExtents[0]); + center.mul(0.5f); + size.setSub(mRiggedExtents[1], mRiggedExtents[0]); + } + else if (mDrawablep && mVObjp.notNull() && mVObjp->getPartitionType() == LLViewerRegion::PARTITION_PARTICLE && mDrawablep->getSpatialGroup()) + { // use box of spatial group for particles (over approximates size, but we don't actually have a good size per particle) + LLSpatialGroup* group = mDrawablep->getSpatialGroup(); + const LLVector4a* extents = group->getExtents(); + size.setSub(extents[1], extents[0]); + center.setAdd(extents[1], extents[0]); + center.mul(0.5f); } else { @@ -2214,6 +2303,10 @@ bool LLFace::calcPixelArea(F32& cos_angle_to_view_dir, F32& radius) F32 app_angle = atanf((F32) sqrt(size_squared) / dist); radius = app_angle*LLDrawable::sCurPixelAngle; mPixelArea = radius*radius * 3.14159f; + + // remember last update time, add 10% noise to avoid all faces updating at the same time + mLastPixelAreaUpdate = gFrameTimeSeconds + ll_frand() * PIXEL_AREA_UPDATE_PERIOD * 0.1f; + LLVector4a x_axis; x_axis.load3(camera->getXAxis().mV); cos_angle_to_view_dir = lookAt.dot3(x_axis).getF32(); @@ -2293,6 +2386,7 @@ const F32 FACE_IMPORTANCE_TO_CAMERA_OVER_ANGLE[FACE_IMPORTANCE_LEVEL][2] = // //static F32 LLFace::calcImportanceToCamera(F32 cos_angle_to_view_dir, F32 dist) { + LL_PROFILE_ZONE_SCOPED_CATEGORY_FACE; F32 importance = 0.f ; if(cos_angle_to_view_dir > LLViewerCamera::getInstance()->getCosHalfFov() && |