diff options
| -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; | 
