summaryrefslogtreecommitdiff
path: root/indra/newview/llface.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/newview/llface.cpp')
-rw-r--r--indra/newview/llface.cpp174
1 files changed, 132 insertions, 42 deletions
diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp
index df08dcf503..ce68474211 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"
#if LL_LINUX
// Work-around spurious used before init warning on Vector4a
@@ -573,12 +574,14 @@ void LLFace::renderSelected(LLViewerTexture *imagep, const LLColor4& color)
if (LLGLTFMaterial* gltf_mat = te->getGLTFRenderMaterial())
{
vertex_buffer = mVertexBufferGLTF.get();
- vertex_buffer->unmapBuffer();
}
}
// Draw the selection marker using the correctly chosen vertex buffer
- vertex_buffer->setBuffer();
- vertex_buffer->draw(LLRender::TRIANGLES, mIndicesCount, mIndicesIndex);
+ if (vertex_buffer)
+ {
+ vertex_buffer->setBuffer();
+ vertex_buffer->draw(LLRender::TRIANGLES, mIndicesCount, mIndicesIndex);
+ }
}
gGL.popMatrix();
@@ -1217,7 +1220,8 @@ bool LLFace::getGeometryVolume(const LLVolume& volume,
mVertexBufferGLTF = new LLVertexBuffer(mVertexBuffer->getTypeMask());
}
- // Clone the existing vertex buffer into the temporary one
+ // Clone the existing vertex buffer into the temporary one
+ // TODO: factor out the need for mVertexBufferGLTF and make selection highlight shader work with the existing vertex buffer
mVertexBuffer->clone(*mVertexBufferGLTF);
// Recursive call the same function with the argument rebuild_for_gltf set to true
@@ -1225,6 +1229,7 @@ bool LLFace::getGeometryVolume(const LLVolume& volume,
mVertexBufferGLTF.swap(mVertexBufferGLTF, mVertexBuffer);
getGeometryVolume(volume, face_index, mat_vert_in, mat_norm_in, index_offset, force_rebuild, no_debug_assert, true);
mVertexBufferGLTF.swap(mVertexBufferGLTF, mVertexBuffer);
+ mVertexBufferGLTF->unmapBuffer();
}
else if (!tep->isSelected() && mVertexBufferGLTF.notNull())
{
@@ -1483,9 +1488,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
{
@@ -1737,7 +1742,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
@@ -1799,49 +1804,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);
@@ -2159,28 +2185,88 @@ 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;
//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
{
@@ -2206,6 +2292,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();