diff options
Diffstat (limited to 'indra/newview/llface.cpp')
-rw-r--r-- | indra/newview/llface.cpp | 201 |
1 files changed, 156 insertions, 45 deletions
diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp index b37073122b..fb4db9a216 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 @@ -895,7 +896,7 @@ LLVector2 LLFace::surfaceToTexture(LLVector2 surface_coord, const LLVector4a& po //VECTORIZE THIS // see if we have a non-default mapping - U8 texgen = getTextureEntry()->getTexGen(); + U8 texgen = tep->getTexGen(); if (texgen != LLTextureEntry::TEX_GEN_DEFAULT) { LLVector4a& center = *(mDrawablep->getVOVolume()->getVolume()->getVolumeFace(mTEOffset).mCenter); @@ -985,8 +986,17 @@ bool LLFace::calcAlignedPlanarTE(const LLFace* align_to, LLVector2* res_st_offs return false; } const LLTextureEntry *orig_tep = align_to->getTextureEntry(); + if (!orig_tep) + { + return false; + } + const LLTextureEntry* tep = getTextureEntry(); + if (!tep) + { + return false; + } if ((orig_tep->getTexGen() != LLTextureEntry::TEX_GEN_PLANAR) || - (getTextureEntry()->getTexGen() != LLTextureEntry::TEX_GEN_PLANAR)) + (tep->getTexGen() != LLTextureEntry::TEX_GEN_PLANAR)) { return false; } @@ -1490,9 +1500,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 { @@ -1565,7 +1575,8 @@ bool LLFace::getGeometryVolume(const LLVolume& volume, bump_t_primary_light_ray.load3((offset_multiple * t_scale * primary_light_ray).mV); } - U8 texgen = getTextureEntry()->getTexGen(); + const LLTextureEntry* tep = getTextureEntry(); + U8 texgen = tep ? tep->getTexGen() : LLTextureEntry::TEX_GEN_DEFAULT; if (rebuild_tcoord && texgen != LLTextureEntry::TEX_GEN_DEFAULT) { //planar texgen needs binormals mVObjp->getVolume()->genTangents(face_index); @@ -1744,7 +1755,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 +1817,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); @@ -2032,7 +2064,12 @@ bool LLFace::getGeometryVolume(const LLVolume& volume, LLStrider<LLColor4U> emissive; mVertexBuffer->getEmissiveStrider(emissive, mGeomIndex, mGeomCount); - U8 glow = (U8) llclamp((S32) (getTextureEntry()->getGlow()*255), 0, 255); + const LLTextureEntry* tep = getTextureEntry(); + U8 glow = 0; + if (tep) + { + glow = (U8)llclamp((S32)(tep->getGlow() * 255), 0, 255); + } LLVector4a src; @@ -2150,7 +2187,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 +2203,98 @@ 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 - LLVOAvatar* avatar = mVObjp->getAvatar(); + LL_PROFILE_ZONE_NAMED_CATEGORY_FACE("calcPixelArea - rigged"); + //override with joint volume face joint bounding boxes + LLVOAvatar* avatar = mVObjp.notNull() ? mVObjp->getAvatar() : nullptr; + 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(); + const LLMeshSkinInfo* skin = vo_volume->getSkinInfo(); + if (skin) + { + 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 +2320,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 +2403,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() && |