diff options
author | cosmic-linden <111533034+cosmic-linden@users.noreply.github.com> | 2024-08-29 09:10:46 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-08-29 09:10:46 -0700 |
commit | 0b062be30862e645bb9a660067f9783d63e2fa34 (patch) | |
tree | ce69eccb188bb07195f70f283a9346171f18a708 | |
parent | e26261c7f936d697a96b964723498f3e989017d8 (diff) | |
parent | f23f28c8f9ccc36e8f70beb63b58b3114246a09c (diff) |
Merge pull request #2449 from secondlife/v-2421
secondlife/viewer#2421: Do not calculate and store silhouette edges for nearly every geometric prim with a corner
-rw-r--r-- | indra/llmath/llvolume.cpp | 415 | ||||
-rw-r--r-- | indra/llmath/llvolume.h | 15 |
2 files changed, 246 insertions, 184 deletions
diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp index 56ac22ca18..700e61467b 100644 --- a/indra/llmath/llvolume.cpp +++ b/indra/llmath/llvolume.cpp @@ -2710,7 +2710,7 @@ bool LLVolume::unpackVolumeFacesInternal(const LLSD& mdl) } -bool LLVolume::isMeshAssetLoaded() +bool LLVolume::isMeshAssetLoaded() const { return mIsMeshAssetLoaded; } @@ -2733,7 +2733,7 @@ void LLVolume::setMeshAssetUnavaliable(bool unavaliable) } } -bool LLVolume::isMeshAssetUnavaliable() +bool LLVolume::isMeshAssetUnavaliable() const { return mIsMeshAssetUnavaliable; } @@ -3730,6 +3730,207 @@ S32 LLVolume::getNumTriangles(S32* vcount) const return triangle_count; } +void LLVolumeFace::generateSilhouetteEdge(const LLVolume* volume, std::vector<S32>& edge) const +{ + llassert(edge.empty()); // edge is supposed to be a scratch array + + if (volume->isMeshAssetLoaded()) { return; } + + if (mTypeMask & CAP_MASK) + { + // Logic copied from LLVolumeFace::createCap - indicates a face created via + // createUnCutCubeCap. + if (!(mTypeMask & HOLLOW_MASK) && + !(mTypeMask & OPEN_MASK) && + ((volume->getParams().getPathParams().getBegin()==0.0f)&& + (volume->getParams().getPathParams().getEnd()==1.0f))&& + (volume->getParams().getProfileParams().getCurveType()==LL_PCODE_PROFILE_SQUARE && + volume->getParams().getPathParams().getCurveType()==LL_PCODE_PATH_LINE) + ) + { + LL_PROFILE_ZONE_NAMED_CATEGORY_VOLUME("llvfgse - CAP_MASK"); + + const LLAlignedArray<LLVector4a,64>& profile = volume->getProfile().mProfile; + S32 grid_size = (profile.size()-1)/4; + edge.resize(mNumIndices); + llassert(edge.size() == 6*grid_size*grid_size); + + S32 cur_edge = 0; + for(S32 gx = 0;gx<grid_size;gx++) + { + for(S32 gy = 0;gy<grid_size;gy++) + { + if (mTypeMask & TOP_MASK) + { + + S32 edge_value = grid_size * 2 * gy + gx * 2; + + if (gx > 0) + { + edge[cur_edge++] = edge_value; + } + else + { + edge[cur_edge++] = -1; // Mark face to higlight it + } + + if (gy < grid_size - 1) + { + edge[cur_edge++] = edge_value; + } + else + { + edge[cur_edge++] = -1; + } + + edge[cur_edge++] = edge_value; + + if (gx < grid_size - 1) + { + edge[cur_edge++] = edge_value; + } + else + { + edge[cur_edge++] = -1; + } + + if (gy > 0) + { + edge[cur_edge++] = edge_value; + } + else + { + edge[cur_edge++] = -1; + } + + edge[cur_edge++] = edge_value; + } + else + { + S32 edge_value = grid_size * 2 * gy + gx * 2; + + if (gy > 0) + { + edge[cur_edge++] = edge_value; + } + else + { + edge[cur_edge++] = -1; + } + + if (gx < grid_size - 1) + { + edge[cur_edge++] = edge_value; + } + else + { + edge[cur_edge++] = -1; + } + + edge[cur_edge++] = edge_value; + + if (gy < grid_size - 1) + { + edge[cur_edge++] = edge_value; + } + else + { + edge[cur_edge++] = -1; + } + + if (gx > 0) + { + edge[cur_edge++] = edge_value; + } + else + { + edge[cur_edge++] = -1; + } + + edge[cur_edge++] = edge_value; + } + } + } + } + } + else if ((mTypeMask & END_MASK) || (mTypeMask & SIDE_MASK)) + { + LL_PROFILE_ZONE_NAMED_CATEGORY_VOLUME("llvfgse - END_MASK or SIDE_MASK"); + + edge.resize(mNumIndices); + llassert(edge.size() == 6*(mNumS-1)*(mNumT-1)); + + S32 cur_edge = 0; + const bool flat_face = mTypeMask & FLAT_MASK; + for (S32 t = 0; t < (mNumT-1); t++) + { + for (S32 s = 0; s < (mNumS-1); s++) + { + // bottom left/top right neighbor face + edge[cur_edge++] = (mNumS-1)*2*t+s*2+1; + + if (t < mNumT-2) + { // top right/top left neighbor face + edge[cur_edge++] = (mNumS-1)*2*(t+1)+s*2+1; + } + else if (mNumT <= 3 || volume->getPath().isOpen()) + { // no neighbor + edge[cur_edge++] = -1; + } + else + { // wrap on T + edge[cur_edge++] = s*2+1; + } + + if (s > 0) + { // top left/bottom left neighbor face + edge[cur_edge++] = (mNumS-1)*2*t+s*2-1; + } + else if (flat_face || volume->getProfile().isOpen()) + { // no neighbor + edge[cur_edge++] = -1; + } + else + { // wrap on S + edge[cur_edge++] = (mNumS-1)*2*t+(mNumS-2)*2+1; + } + + if (t > 0) + { // bottom left/bottom right neighbor face + edge[cur_edge++] = (mNumS-1)*2*(t-1)+s*2; + } + else if (mNumT <= 3 || volume->getPath().isOpen()) + { // no neighbor + edge[cur_edge++] = -1; + } + else + { // wrap on T + edge[cur_edge++] = (mNumS-1)*2*(mNumT-2)+s*2; + } + + if (s < mNumS-2) + { // bottom right/top right neighbor face + edge[cur_edge++] = (mNumS-1)*2*t+(s+1)*2; + } + else if (flat_face || volume->getProfile().isOpen()) + { // no neighbor + edge[cur_edge++] = -1; + } + else + { // wrap on S + edge[cur_edge++] = (mNumS-1)*2*t; + } + + // top right/bottom left neighbor face + edge[cur_edge++] = (mNumS-1)*2*t+s*2; + } + } + } + else + { + LL_ERRS() << "Unknown/uninitialized face type!" << LL_ENDL; + } +} //----------------------------------------------------------------------------- // generateSilhouetteVertices() @@ -3761,6 +3962,13 @@ void LLVolume::generateSilhouetteVertices(std::vector<LLVector3> &vertices, } S32 cur_index = 0; + // Scratch array for per-face silhouette edge information. This also has a + // lot of dev-only debug information that we might not care about anymore. + // (see DEBUG_SILHOUETTE_EDGE_MAP) + // *TODO: Consider removing the debug associated with + // DEBUG_SILHOUETTE_EDGE_MAP, and remove its associated computational + // overhead in generateSilhouetteEdge. + std::vector<S32> edge; //for each face for (face_list_t::iterator iter = mVolumeFaces.begin(); iter != mVolumeFaces.end(); ++iter) @@ -3768,7 +3976,16 @@ void LLVolume::generateSilhouetteVertices(std::vector<LLVector3> &vertices, LLVolumeFace& face = *iter; if (!(face_mask & (0x1 << cur_index++)) || - face.mNumIndices == 0 || face.mEdge.empty()) + face.mNumIndices == 0) + { + continue; + } + // Attempt to generate "edge" info for this silhouette, which is used + // for some prims. If the edge array remains empty, then this + // silhouette generation method is not supported for this face. + edge.clear(); + face.generateSilhouetteEdge(this, edge); + if (edge.empty()) { continue; } @@ -3782,7 +3999,7 @@ void LLVolume::generateSilhouetteVertices(std::vector<LLVector3> &vertices, { for (S32 k = 0; k < 3; k++) { - S32 index = face.mEdge[j * 3 + k]; + S32 index = edge[j * 3 + k]; if (index == -1) { @@ -3834,7 +4051,7 @@ void LLVolume::generateSilhouetteVertices(std::vector<LLVector3> &vertices, //for each edge for (S32 k = 0; k < 3; k++) { - S32 nIndex = face.mEdge[j*3+k]; + S32 nIndex = edge[j*3+k]; if (nIndex <= -1) { continue; } @@ -3949,7 +4166,7 @@ void LLVolume::generateSilhouetteVertices(std::vector<LLVector3> &vertices, // *FIX IF NEEDED: this does not deal with neighboring degenerate faces for (S32 k = 0; k < 3; k++) { - S32 index = face.mEdge[j*3+k]; + S32 index = edge[j*3+k]; if (index != -1) { fFacing[j] = fFacing[index]; @@ -3961,10 +4178,10 @@ void LLVolume::generateSilhouetteVertices(std::vector<LLVector3> &vertices, //for each edge for (S32 k = 0; k < 3; k++) { - S32 index = face.mEdge[j*3+k]; + S32 index = edge[j*3+k]; if (index != -1 && fFacing[index] == (AWAY | TOWARDS)) { //our neighbor is degenerate, make him face our direction - fFacing[face.mEdge[j*3+k]] = fFacing[j]; + fFacing[edge[j*3+k]] = fFacing[j]; continue; } @@ -5775,30 +5992,16 @@ bool LLVolumeFace::createUnCutCubeCap(LLVolume* volume, bool partial_build) if (!partial_build) { + LL_PROFILE_ZONE_NAMED_CATEGORY_VOLUME("llvfcuccm - generate indices"); + resizeIndices(grid_size*grid_size*6); - if (!volume->isMeshAssetLoaded()) - { - S32 size = grid_size * grid_size * 6; - try - { - mEdge.resize(size); - } - catch (std::bad_alloc&) - { - LL_WARNS("LLVOLUME") << "Resize of mEdge to " << size << " failed" << LL_ENDL; - return false; - } - } U16* out = mIndices; S32 idxs[] = {0,1,(grid_size+1)+1,(grid_size+1)+1,(grid_size+1),0}; - int cur_edge = 0; - for(S32 gx = 0;gx<grid_size;gx++) { - for(S32 gy = 0;gy<grid_size;gy++) { if (mTypeMask & TOP_MASK) @@ -5808,47 +6011,6 @@ bool LLVolumeFace::createUnCutCubeCap(LLVolume* volume, bool partial_build) *out++ = ((gy*(grid_size+1))+gx+idxs[i]); } - S32 edge_value = grid_size * 2 * gy + gx * 2; - - if (gx > 0) - { - mEdge[cur_edge++] = edge_value; - } - else - { - mEdge[cur_edge++] = -1; // Mark face to higlight it - } - - if (gy < grid_size - 1) - { - mEdge[cur_edge++] = edge_value; - } - else - { - mEdge[cur_edge++] = -1; - } - - mEdge[cur_edge++] = edge_value; - - if (gx < grid_size - 1) - { - mEdge[cur_edge++] = edge_value; - } - else - { - mEdge[cur_edge++] = -1; - } - - if (gy > 0) - { - mEdge[cur_edge++] = edge_value; - } - else - { - mEdge[cur_edge++] = -1; - } - - mEdge[cur_edge++] = edge_value; } else { @@ -5856,48 +6018,6 @@ bool LLVolumeFace::createUnCutCubeCap(LLVolume* volume, bool partial_build) { *out++ = ((gy*(grid_size+1))+gx+idxs[i]); } - - S32 edge_value = grid_size * 2 * gy + gx * 2; - - if (gy > 0) - { - mEdge[cur_edge++] = edge_value; - } - else - { - mEdge[cur_edge++] = -1; - } - - if (gx < grid_size - 1) - { - mEdge[cur_edge++] = edge_value; - } - else - { - mEdge[cur_edge++] = -1; - } - - mEdge[cur_edge++] = edge_value; - - if (gy < grid_size - 1) - { - mEdge[cur_edge++] = edge_value; - } - else - { - mEdge[cur_edge++] = -1; - } - - if (gx > 0) - { - mEdge[cur_edge++] = edge_value; - } - else - { - mEdge[cur_edge++] = -1; - } - - mEdge[cur_edge++] = edge_value; } } } @@ -6377,6 +6497,8 @@ void LLVolumeFace::createTangents() void LLVolumeFace::resizeVertices(S32 num_verts) { + LL_PROFILE_ZONE_SCOPED_CATEGORY_VOLUME; + ll_aligned_free<64>(mPositions); //DO NOT free mNormals and mTexCoords as they are part of mPositions buffer ll_aligned_free_16(mTangents); @@ -6499,6 +6621,8 @@ void LLVolumeFace::allocateJointIndices(S32 num_verts) void LLVolumeFace::resizeIndices(S32 num_indices) { + LL_PROFILE_ZONE_SCOPED_CATEGORY_VOLUME; + ll_aligned_free_16(mIndices); llassert(num_indices % 3 == 0); @@ -6591,19 +6715,6 @@ bool LLVolumeFace::createSide(LLVolume* volume, bool partial_build) { resizeVertices(num_vertices); resizeIndices(num_indices); - - if (!volume->isMeshAssetLoaded()) - { - try - { - mEdge.resize(num_indices); - } - catch (std::bad_alloc&) - { - LL_WARNS("LLVOLUME") << "Resize of mEdge to " << num_indices << " failed" << LL_ENDL; - return false; - } - } } LL_CHECK_MEMORY @@ -6618,6 +6729,7 @@ bool LLVolumeFace::createSide(LLVolume* volume, bool partial_build) bool test = (mTypeMask & INNER_MASK) && (mTypeMask & FLAT_MASK) && mNumS > 2; // Copy the vertices into the array + { LL_PROFILE_ZONE_NAMED_CATEGORY_VOLUME("llvfcs - copy verts"); for (t = mBeginT; t < end_t; t++) { tt = path_data[t].mTexT; @@ -6702,6 +6814,7 @@ bool LLVolumeFace::createSide(LLVolume* volume, bool partial_build) cur_vertex++; } } + } LL_CHECK_MEMORY mCenter->clear(); @@ -6755,11 +6868,11 @@ bool LLVolumeFace::createSide(LLVolume* volume, bool partial_build) mCenter->mul(0.5f); S32 cur_index = 0; - S32 cur_edge = 0; - bool flat_face = mTypeMask & FLAT_MASK; if (!partial_build) { + LL_PROFILE_ZONE_NAMED_CATEGORY_VOLUME("llvfcs - generate indices"); + // Now we generate the indices. for (t = 0; t < (mNumT-1); t++) { @@ -6771,64 +6884,6 @@ bool LLVolumeFace::createSide(LLVolume* volume, bool partial_build) mIndices[cur_index++] = s + mNumS*t; //bottom left mIndices[cur_index++] = s+1 + mNumS*t; //bottom right mIndices[cur_index++] = s+1 + mNumS*(t+1); //top right - - // bottom left/top right neighbor face - mEdge[cur_edge++] = (mNumS-1)*2*t+s*2+1; - - if (t < mNumT-2) - { // top right/top left neighbor face - mEdge[cur_edge++] = (mNumS-1)*2*(t+1)+s*2+1; - } - else if (mNumT <= 3 || volume->getPath().isOpen()) - { // no neighbor - mEdge[cur_edge++] = -1; - } - else - { // wrap on T - mEdge[cur_edge++] = s*2+1; - } - - if (s > 0) - { // top left/bottom left neighbor face - mEdge[cur_edge++] = (mNumS-1)*2*t+s*2-1; - } - else if (flat_face || volume->getProfile().isOpen()) - { // no neighbor - mEdge[cur_edge++] = -1; - } - else - { // wrap on S - mEdge[cur_edge++] = (mNumS-1)*2*t+(mNumS-2)*2+1; - } - - if (t > 0) - { // bottom left/bottom right neighbor face - mEdge[cur_edge++] = (mNumS-1)*2*(t-1)+s*2; - } - else if (mNumT <= 3 || volume->getPath().isOpen()) - { // no neighbor - mEdge[cur_edge++] = -1; - } - else - { // wrap on T - mEdge[cur_edge++] = (mNumS-1)*2*(mNumT-2)+s*2; - } - - if (s < mNumS-2) - { // bottom right/top right neighbor face - mEdge[cur_edge++] = (mNumS-1)*2*t+(s+1)*2; - } - else if (flat_face || volume->getProfile().isOpen()) - { // no neighbor - mEdge[cur_edge++] = -1; - } - else - { // wrap on S - mEdge[cur_edge++] = (mNumS-1)*2*t; - } - - // top right/bottom left neighbor face - mEdge[cur_edge++] = (mNumS-1)*2*t+s*2; } } } diff --git a/indra/llmath/llvolume.h b/indra/llmath/llvolume.h index bbb2a16b0b..27c5fc5a49 100644 --- a/indra/llmath/llvolume.h +++ b/indra/llmath/llvolume.h @@ -918,6 +918,15 @@ public: // Get a reference to the octree, which may be null const LLVolumeOctree* getOctree() const; + // Part of silhouette generation (used by selection outlines) + // Populates the provided edge array with numbers corresponding to + // *partial* logic of whether a particular index should be rendered + // as a silhouette edge. -1 indicates the index should be rendered as a + // silhouette edge. See generateSilhouetteVertices for the full logic. + // Silhouette edges can only be generated for some types of prims. If a + // silhouette edge cannot be generated, the edge array will be left empty. + void generateSilhouetteEdge(const LLVolume* volume, std::vector<S32>& edge) const; + enum { SINGLE_MASK = 0x0001, @@ -963,8 +972,6 @@ public: // indexes for mPositions/mNormals/mTexCoords U16* mIndices; - std::vector<S32> mEdge; - //list of skin weights for rigged volumes // format is mWeights[vertex_index].mV[influence] = <joint_index>.<weight> // mWeights.size() should be empty or match mVertices.size() @@ -1113,9 +1120,9 @@ private: public: virtual void setMeshAssetLoaded(bool loaded); - virtual bool isMeshAssetLoaded(); + virtual bool isMeshAssetLoaded() const; virtual void setMeshAssetUnavaliable(bool unavaliable); - virtual bool isMeshAssetUnavaliable(); + virtual bool isMeshAssetUnavaliable() const; protected: bool mUnique; |