From 5e96a9ba31f1b22a260dfac520c503750197b113 Mon Sep 17 00:00:00 2001 From: Takahito Tejima Date: Tue, 15 Sep 2015 09:11:41 -0700 Subject: [PATCH] GregoryBasis optimization. Replace arithmetic operators which uses a temporary object. --- .../far/endCapBSplineBasisPatchFactory.cpp | 11 +- opensubdiv/far/gregoryBasis.cpp | 163 ++++++++++++------ opensubdiv/far/gregoryBasis.h | 78 ++------- 3 files changed, 133 insertions(+), 119 deletions(-) diff --git a/opensubdiv/far/endCapBSplineBasisPatchFactory.cpp b/opensubdiv/far/endCapBSplineBasisPatchFactory.cpp index 95a66e33..41f8ebe0 100644 --- a/opensubdiv/far/endCapBSplineBasisPatchFactory.cpp +++ b/opensubdiv/far/endCapBSplineBasisPatchFactory.cpp @@ -122,8 +122,9 @@ EndCapBSplineBasisPatchFactory::GetPatchPoints( for (int j = 0; j < 4; ++j) { H[i*4+j].Clear(stencilCapacity); for (int k = 0; k < 4; ++k) { - if (isWeightNonZero(Q[i][k])) - H[i*4+j] += (*bezierCP[j+k*4]) * Q[i][k]; + if (isWeightNonZero(Q[i][k])) { + H[i*4+j].AddWithWeight(*bezierCP[j+k*4], Q[i][k]); + } } } } @@ -131,12 +132,14 @@ EndCapBSplineBasisPatchFactory::GetPatchPoints( for (int j = 0; j < 4; ++j) { GregoryBasis::Point p(stencilCapacity); for (int k = 0; k < 4; ++k) { - if (isWeightNonZero(Q[j][k])) p += H[i*4+k] * Q[j][k]; + if (isWeightNonZero(Q[j][k])) { + p.AddWithWeight(H[i*4+k], Q[j][k]); + } } _vertexStencils.push_back(p); } } - + int varyingIndices[] = { 0, 0, 1, 1, 0, 0, 1, 1, 3, 3, 2, 2, diff --git a/opensubdiv/far/gregoryBasis.cpp b/opensubdiv/far/gregoryBasis.cpp index 0527d7be..a80dbfc5 100644 --- a/opensubdiv/far/gregoryBasis.cpp +++ b/opensubdiv/far/gregoryBasis.cpp @@ -113,41 +113,36 @@ GregoryBasis::ProtoBasis::ProtoBasis( valences[4], zerothNeighbors[4]; - Point e0[4], e1[4], org[4]; - // XXX: a temporary hack for the performance issue // ensure Point has a capacity for the neighborhood of // 2 extraordinary verts + 2 regular verts // worse case: n-valence verts at a corner of n-gon. int stencilCapacity = 4/*0-ring*/ + 2*(2*(maxvalence-2)/*1-ring around extraordinaries*/ - + 2/*1-ring around regulars, excluding shared ones*/); + + 2/*1-ring around regulars, excluding shared ones*/); + Point e0[4], e1[4]; for (int i = 0; i < 4; ++i) { P[i].Clear(stencilCapacity); e0[i].Clear(stencilCapacity); e1[i].Clear(stencilCapacity); + V[i].Clear(1); } - Vtr::internal::StackBuffer manifoldRings[4]; + Vtr::internal::StackBuffer manifoldRings[4]; manifoldRings[0].SetSize(maxvalence*2); manifoldRings[1].SetSize(maxvalence*2); manifoldRings[2].SetSize(maxvalence*2); manifoldRings[3].SetSize(maxvalence*2); - Vtr::internal::StackBuffer f(maxvalence); - Vtr::internal::StackBuffer r(maxvalence*4); - + Vtr::internal::StackBuffer f(maxvalence); + Vtr::internal::StackBuffer r(maxvalence*4); // the first phase for (int vid=0; vid<4; ++vid) { - - org[vid] = Point(facePoints[vid], 1.0f, stencilCapacity); - Point const &pos = org[vid]; - // save for varying stencils - V[vid] = Point(facePoints[vid], 1.0f, stencilCapacity); + V[vid].AddWithWeight(facePoints[vid], 1.0f); int ringSize = level.gatherQuadRegularRingAroundVertex( @@ -182,7 +177,7 @@ GregoryBasis::ProtoBasis::ProtoBasis( idx_diagonal_m = (manifoldRings[vid][2*im + 1]); bool boundaryNeighbor = (level.getVertexEdges(idx_neighbor).size() > - level.getVertexFaces(idx_neighbor).size()); + level.getVertexFaces(idx_neighbor).size()); if (fvarChannel>=0) { // XXXX manuelk need logic to check for boundary in fvar @@ -210,11 +205,7 @@ GregoryBasis::ProtoBasis::ProtoBasis( f[i].AddWithWeight(idx_neighbor_p, 2.0f/d); f[i].AddWithWeight(idx_neighbor, 2.0f/d); f[i].AddWithWeight(idx_diagonal, 1.0f/d); - - if (i == 0) - P[vid] = f[i]; - else - P[vid] += f[i]; + P[vid].AddWithWeight(f[i], 1.0f/float(ivalence)); int rid = vid * maxvalence + i; r[rid].Clear(4); @@ -224,8 +215,6 @@ GregoryBasis::ProtoBasis::ProtoBasis( r[rid].AddWithWeight(idx_diagonal_m, -1.0f/6.0f); } - P[vid] /= float(ivalence); - zerothNeighbors[vid] = zerothNeighbor; if (currentNeighbor == 1) { boundaryEdgeNeighbors[1] = boundaryEdgeNeighbors[0]; @@ -233,24 +222,27 @@ GregoryBasis::ProtoBasis::ProtoBasis( for (int i=0; i2) { - P[vid] = (b0 + b1 + pos*4.0f)/6.0f; + P[vid].AddWithWeight(boundaryEdgeNeighbors[0], 1.0f/6.0f); + P[vid].AddWithWeight(boundaryEdgeNeighbors[1], 1.0f/6.0f); + P[vid].AddWithWeight(facePoints[vid], 4.0f/6.0f); } else { - P[vid] = pos; + P[vid].AddWithWeight(facePoints[vid], 1.0f); } float k = float(float(ivalence) - 1.0f); //k is the number of faces float c = cosf(float(M_PI)/k); @@ -259,10 +251,17 @@ GregoryBasis::ProtoBasis::ProtoBasis( float alpha_0k = -((1.0f+2.0f*c)*sqrtf(1.0f+c))/((3.0f*k+c)*sqrtf(1.0f-c)); float beta_0 = s/(3.0f*k + c); - Point diagonal(manifoldRings[vid][2*zerothNeighbor + 1], 1.0f, stencilCapacity); + int idx_diagonal = manifoldRings[vid][2*zerothNeighbor + 1]; - e0[vid] = (b0 - b1)/6.0f; - e1[vid] = pos*gamma + diagonal*beta_0 + (b0 + b1)*alpha_0k; + e0[vid].Clear(stencilCapacity); + e0[vid].AddWithWeight(boundaryEdgeNeighbors[0], 1.0f/6.0f); + e0[vid].AddWithWeight(boundaryEdgeNeighbors[1], -1.0f/6.0f); + + e1[vid].Clear(stencilCapacity); + e1[vid].AddWithWeight(facePoints[vid], gamma); + e1[vid].AddWithWeight(idx_diagonal, beta_0); + e1[vid].AddWithWeight(boundaryEdgeNeighbors[0], alpha_0k); + e1[vid].AddWithWeight(boundaryEdgeNeighbors[1], alpha_0k); for (int x=1; x