Merge pull request #830 from davidgyu/patch_table_fvarendcaps

Updated Far::EndCap*PatchFactory for fvar patches
This commit is contained in:
barfowl 2016-08-05 19:21:09 -07:00 committed by GitHub
commit 421afbc6e8
7 changed files with 117 additions and 99 deletions

View File

@ -70,15 +70,17 @@ EndCapBSplineBasisPatchFactory::EndCapBSplineBasisPatchFactory(
int numStencilsExpected = std::min(numPatchPointsExpected * 16,
100*1024*1024);
_vertexStencils->reserve(numPatchPointsExpected, numStencilsExpected);
// varying stencils use only 1 index with weight=1.0
_varyingStencils->reserve(numPatchPointsExpected, numPatchPointsExpected);
if (_varyingStencils) {
// varying stencils use only 1 index with weight=1.0
_varyingStencils->reserve(numPatchPointsExpected, numPatchPointsExpected);
}
}
ConstIndexArray
EndCapBSplineBasisPatchFactory::GetPatchPoints(
Vtr::internal::Level const * level, Index thisFace,
Vtr::internal::Level::VSpan const cornerSpans[],
int levelVertOffset) {
int levelVertOffset, int fvarChannel) {
//
// We can only use a faster method directly with B-Splines when we have a
@ -113,10 +115,12 @@ EndCapBSplineBasisPatchFactory::GetPatchPoints(
if (useGregoryPatch) {
return getPatchPointsFromGregoryBasis(
level, thisFace, cornerSpans, facePoints, levelVertOffset);
level, thisFace, cornerSpans, facePoints,
levelVertOffset, fvarChannel);
} else {
return getPatchPoints(
level, thisFace, irregCornerIndex, facePoints, levelVertOffset);
level, thisFace, irregCornerIndex, facePoints,
levelVertOffset, fvarChannel);
}
}
@ -124,18 +128,20 @@ ConstIndexArray
EndCapBSplineBasisPatchFactory::getPatchPointsFromGregoryBasis(
Vtr::internal::Level const * level, Index thisFace,
Vtr::internal::Level::VSpan const cornerSpans[],
ConstIndexArray facePoints, int levelVertOffset) {
ConstIndexArray facePoints, int levelVertOffset, int fvarChannel) {
// XXX: For now, always create new 16 indices for each patch.
// we'll optimize later to share all regular control points with
// other patches as well as to try to make extra ordinary verts watertight.
int offset = _refiner->GetNumVerticesTotal();
int offset = (fvarChannel < 0)
? _refiner->GetNumVerticesTotal()
: _refiner->GetNumFVarValuesTotal(fvarChannel);
for (int i = 0; i < 16; ++i) {
_patchPoints.push_back(_numVertices + offset);
++_numVertices;
}
GregoryBasis::ProtoBasis basis(*level, thisFace, cornerSpans, levelVertOffset, -1);
GregoryBasis::ProtoBasis basis(*level, thisFace, cornerSpans, levelVertOffset, fvarChannel);
// XXX: temporary hack. we should traverse topology and find existing
// vertices if available
//
@ -192,15 +198,17 @@ EndCapBSplineBasisPatchFactory::getPatchPointsFromGregoryBasis(
GregoryBasis::AppendToStencilTable(p, _vertexStencils);
}
}
int varyingIndices[] = { 0, 0, 1, 1,
0, 0, 1, 1,
3, 3, 2, 2,
3, 3, 2, 2,};
for (int i = 0; i < 16; ++i) {
int varyingIndex = facePoints[varyingIndices[i]] + levelVertOffset;
_varyingStencils->_sizes.push_back(1);
_varyingStencils->_indices.push_back(varyingIndex);
_varyingStencils->_weights.push_back(1.0f);
if (_varyingStencils) {
int varyingIndices[] = { 0, 0, 1, 1,
0, 0, 1, 1,
3, 3, 2, 2,
3, 3, 2, 2,};
for (int i = 0; i < 16; ++i) {
int varyingIndex = facePoints[varyingIndices[i]] + levelVertOffset;
_varyingStencils->_sizes.push_back(1);
_varyingStencils->_indices.push_back(varyingIndex);
_varyingStencils->_weights.push_back(1.0f);
}
}
++_numPatches;
@ -210,7 +218,7 @@ EndCapBSplineBasisPatchFactory::getPatchPointsFromGregoryBasis(
void
EndCapBSplineBasisPatchFactory::computeLimitStencils(
Vtr::internal::Level const *level,
ConstIndexArray facePoints, int vid,
ConstIndexArray facePoints, int vid, int fvarChannel,
GregoryBasis::Point *P, GregoryBasis::Point *Ep, GregoryBasis::Point *Em)
{
int maxvalence = level->getMaxValence();
@ -220,7 +228,7 @@ EndCapBSplineBasisPatchFactory::computeLimitStencils(
int ringSize =
level->gatherQuadRegularRingAroundVertex(
facePoints[vid], manifoldRing, /*fvarChannel*/-1);
facePoints[vid], manifoldRing, fvarChannel);
// note: this function has not yet supported boundary.
assert((ringSize & 1) == 0);
@ -284,7 +292,7 @@ ConstIndexArray
EndCapBSplineBasisPatchFactory::getPatchPoints(
Vtr::internal::Level const *level, Index thisFace,
Index extraOrdinaryIndex, ConstIndexArray facePoints,
int levelVertOffset) {
int levelVertOffset, int fvarChannel) {
// Fast B-spline endcap construction.
//
@ -319,7 +327,7 @@ EndCapBSplineBasisPatchFactory::getPatchPoints(
int stencilCapacity = 2*maxvalence + 16;
GregoryBasis::Point P(stencilCapacity), Em(stencilCapacity), Ep(stencilCapacity);
computeLimitStencils(level, facePoints, extraOrdinaryIndex, &P, &Em, &Ep);
computeLimitStencils(level, facePoints, extraOrdinaryIndex, fvarChannel, &P, &Em, &Ep);
P.OffsetIndices(levelVertOffset);
Em.OffsetIndices(levelVertOffset);
Ep.OffsetIndices(levelVertOffset);
@ -473,7 +481,9 @@ EndCapBSplineBasisPatchFactory::getPatchPoints(
// patch point stencils will be stored in this order
// (Em) 6, 7, 8, (Ep) 4, 15, 14, (P) 5
int offset = _refiner->GetNumVerticesTotal();
int offset = (fvarChannel < 0)
? _refiner->GetNumVerticesTotal()
: _refiner->GetNumFVarValuesTotal(fvarChannel);
int varyingIndex0 = facePoints[vid] + levelVertOffset;
int varyingIndex1 = facePoints[(vid+1)&3] + levelVertOffset;
@ -482,31 +492,45 @@ EndCapBSplineBasisPatchFactory::getPatchPoints(
// push back to stencils;
patchPoints[3* vid + 6] = (_numVertices++) + offset;
GregoryBasis::AppendToStencilTable(X6, _vertexStencils);
GregoryBasis::AppendToStencilTable(varyingIndex0, _varyingStencils);
if (_varyingStencils) {
GregoryBasis::AppendToStencilTable(varyingIndex0, _varyingStencils);
}
patchPoints[3*((vid+1)%4) + 4] = (_numVertices++) + offset;
GregoryBasis::AppendToStencilTable(X7, _vertexStencils);
GregoryBasis::AppendToStencilTable(varyingIndex1, _varyingStencils);
if (_varyingStencils) {
GregoryBasis::AppendToStencilTable(varyingIndex1, _varyingStencils);
}
patchPoints[3*((vid+1)%4) + 5] = (_numVertices++) + offset;
GregoryBasis::AppendToStencilTable(X8, _vertexStencils);
GregoryBasis::AppendToStencilTable(varyingIndex1, _varyingStencils);
if (_varyingStencils) {
GregoryBasis::AppendToStencilTable(varyingIndex1, _varyingStencils);
}
patchPoints[3* vid + 4] = (_numVertices++) + offset;
GregoryBasis::AppendToStencilTable(X4, _vertexStencils);
GregoryBasis::AppendToStencilTable(varyingIndex0, _varyingStencils);
if (_varyingStencils) {
GregoryBasis::AppendToStencilTable(varyingIndex0, _varyingStencils);
}
patchPoints[3*((vid+3)%4) + 6] = (_numVertices++) + offset;
GregoryBasis::AppendToStencilTable(X15, _vertexStencils);
GregoryBasis::AppendToStencilTable(varyingIndex3, _varyingStencils);
if (_varyingStencils) {
GregoryBasis::AppendToStencilTable(varyingIndex3, _varyingStencils);
}
patchPoints[3*((vid+3)%4) + 5] = (_numVertices++) + offset;
GregoryBasis::AppendToStencilTable(X14, _vertexStencils);
GregoryBasis::AppendToStencilTable(varyingIndex3, _varyingStencils);
if (_varyingStencils) {
GregoryBasis::AppendToStencilTable(varyingIndex3, _varyingStencils);
}
patchPoints[3*vid + 5] = (_numVertices++) + offset;
GregoryBasis::AppendToStencilTable(X5, _vertexStencils);
GregoryBasis::AppendToStencilTable(varyingIndex0, _varyingStencils);
if (_varyingStencils) {
GregoryBasis::AppendToStencilTable(varyingIndex0, _varyingStencils);
}
// reorder into UV row-column
static int const permuteRegular[16] =

View File

@ -45,8 +45,6 @@ class TopologyRefiner;
class EndCapBSplineBasisPatchFactory {
public:
// XXXX need to add support for face-varying channel stencils
/// \brief This factory accumulates vertex for bspline basis end cap
///
/// @param refiner TopologyRefiner from which to generate patches
@ -76,26 +74,28 @@ public:
///
/// @param levelVertOffset relative offset of patch vertex indices
///
/// @param fvarChannel face-varying channel index
///
ConstIndexArray GetPatchPoints(
Vtr::internal::Level const * level, Index faceIndex,
Vtr::internal::Level::VSpan const cornerSpans[],
int levelVertOffset);
int levelVertOffset, int fvarChannel = -1);
private:
ConstIndexArray getPatchPointsFromGregoryBasis(
Vtr::internal::Level const * level, Index thisFace,
Vtr::internal::Level::VSpan const cornerSpans[],
ConstIndexArray facePoints,
int levelVertOffset);
int levelVertOffset, int fvarChannel);
ConstIndexArray getPatchPoints(
Vtr::internal::Level const *level, Index thisFace,
Index extraOrdinaryIndex, ConstIndexArray facePoints,
int levelVertOffset);
int levelVertOffset, int fvarChannel);
void computeLimitStencils(
Vtr::internal::Level const *level,
ConstIndexArray facePoints, int vid,
ConstIndexArray facePoints, int vid, int fvarChannel,
GregoryBasis::Point *P, GregoryBasis::Point *Ep, GregoryBasis::Point *Em);
StencilTable * _vertexStencils;

View File

@ -63,59 +63,53 @@ EndCapGregoryBasisPatchFactory::EndCapGregoryBasisPatchFactory(
int numStencilsExpected = std::min(numPatchPointsExpected * 16,
100*1024*1024);
_vertexStencils->reserve(numPatchPointsExpected, numStencilsExpected);
// varying stencils use only 1 index with weight=1.0
_varyingStencils->reserve(numPatchPointsExpected, numPatchPointsExpected);
}
//
// Stateless EndCapGregoryBasisPatchFactory
//
GregoryBasis const *
EndCapGregoryBasisPatchFactory::Create(TopologyRefiner const & refiner,
Index faceIndex, int fvarChannel) {
// Gregory patches are end-caps: they only exist on max-level
Vtr::internal::Level const & level = refiner.getLevel(refiner.GetMaxLevel());
// Is this method used/supported? If so, needs corner spans (and vert offset?)...
GregoryBasis::ProtoBasis basis(level, faceIndex, 0, 0, fvarChannel);
GregoryBasis * result = new GregoryBasis;
basis.Copy(result);
// note: this function doesn't create varying stencils.
return result;
if (_varyingStencils) {
// varying stencils use only 1 index with weight=1.0
_varyingStencils->reserve(numPatchPointsExpected, numPatchPointsExpected);
}
}
bool
EndCapGregoryBasisPatchFactory::addPatchBasis(Vtr::internal::Level const & level, Index faceIndex,
Vtr::internal::Level::VSpan const cornerSpans[],
bool verticesMask[4][5],
int levelVertOffset) {
int levelVertOffset,
int fvarChannel) {
// Gather the CVs that influence the Gregory patch and their relative
// weights in a basis
GregoryBasis::ProtoBasis basis(level, faceIndex, cornerSpans, levelVertOffset, -1);
GregoryBasis::ProtoBasis basis(level, faceIndex, cornerSpans, levelVertOffset, fvarChannel);
for (int i = 0; i < 4; ++i) {
if (verticesMask[i][0]) {
GregoryBasis::AppendToStencilTable(basis.P[i], _vertexStencils);
GregoryBasis::AppendToStencilTable(basis.varyingIndex[i], _varyingStencils);
if (_varyingStencils) {
GregoryBasis::AppendToStencilTable(basis.varyingIndex[i], _varyingStencils);
}
}
if (verticesMask[i][1]) {
GregoryBasis::AppendToStencilTable(basis.Ep[i], _vertexStencils);
GregoryBasis::AppendToStencilTable(basis.varyingIndex[i], _varyingStencils);
if (_varyingStencils) {
GregoryBasis::AppendToStencilTable(basis.varyingIndex[i], _varyingStencils);
}
}
if (verticesMask[i][2]) {
GregoryBasis::AppendToStencilTable(basis.Em[i], _vertexStencils);
GregoryBasis::AppendToStencilTable(basis.varyingIndex[i], _varyingStencils);
if (_varyingStencils) {
GregoryBasis::AppendToStencilTable(basis.varyingIndex[i], _varyingStencils);
}
}
if (verticesMask[i][3]) {
GregoryBasis::AppendToStencilTable(basis.Fp[i], _vertexStencils);
GregoryBasis::AppendToStencilTable(basis.varyingIndex[i], _varyingStencils);
if (_varyingStencils) {
GregoryBasis::AppendToStencilTable(basis.varyingIndex[i], _varyingStencils);
}
}
if (verticesMask[i][4]) {
GregoryBasis::AppendToStencilTable(basis.Fm[i], _vertexStencils);
GregoryBasis::AppendToStencilTable(basis.varyingIndex[i], _varyingStencils);
if (_varyingStencils) {
GregoryBasis::AppendToStencilTable(basis.varyingIndex[i], _varyingStencils);
}
}
}
return true;
@ -131,7 +125,7 @@ ConstIndexArray
EndCapGregoryBasisPatchFactory::GetPatchPoints(
Vtr::internal::Level const * level, Index faceIndex,
Vtr::internal::Level::VSpan const cornerSpans[],
int levelVertOffset) {
int levelVertOffset, int fvarChannel) {
// allocate indices (awkward)
// assert(Vtr::INDEX_INVALID==0xFFFFFFFF);
@ -140,7 +134,9 @@ EndCapGregoryBasisPatchFactory::GetPatchPoints(
}
Index * dest = &_patchPoints[_numGregoryBasisPatches * 20];
int gregoryVertexOffset = _refiner->GetNumVerticesTotal();
int gregoryVertexOffset = (fvarChannel < 0)
? _refiner->GetNumVerticesTotal()
: _refiner->GetNumFVarValuesTotal(fvarChannel);
if (_shareBoundaryVertices) {
int levelIndex = level->getDepth();
@ -180,6 +176,10 @@ EndCapGregoryBasisPatchFactory::GetPatchPoints(
// - are also Gregory basis patches
if ((adjFaceIndex != Vtr::INDEX_INVALID) && (adjFaceIndex < faceIndex)) {
if (_levelAndFaceIndices.empty()) {
break;
}
ConstIndexArray aedges = level->getFaceEdges(adjFaceIndex);
int aedge = aedges.FindIndexIn4Tuple(edge);
assert(aedge!=Vtr::INDEX_INVALID);
@ -231,7 +231,7 @@ EndCapGregoryBasisPatchFactory::GetPatchPoints(
}
// add basis
addPatchBasis(*level, faceIndex, cornerSpans, newVerticesMask, levelVertOffset);
addPatchBasis(*level, faceIndex, cornerSpans, newVerticesMask, levelVertOffset, fvarChannel);
++_numGregoryBasisPatches;

View File

@ -44,32 +44,12 @@ class TopologyRefiner;
///
class EndCapGregoryBasisPatchFactory {
public:
//
// Single patch GregoryBasis basis factory
//
/// \brief Instantiates a GregoryBasis from a TopologyRefiner that has been
/// refined adaptively for a given face.
///
/// @param refiner The TopologyRefiner containing the topology
///
/// @param faceIndex The index of the face (level is assumed to be MaxLevel)
///
/// @param fvarChannel Index of face-varying channel topology (default -1)
///
static GregoryBasis const * Create(TopologyRefiner const & refiner,
Index faceIndex, int fvarChannel=-1);
public:
///
/// Multi-patch Gregory stencils factory
///
// XXXX need to add support for face-varying channel stencils
/// \brief This factory accumulates vertex for Gregory basis patch
///
/// @param refiner TopologyRefiner from which to generate patches
@ -101,10 +81,12 @@ public:
/// @param cornerSpans information about topology for each corner of patch
/// @param levelVertOffset relative offset of patch vertex indices
///
/// @param fvarChannel face-varying channel index
///
ConstIndexArray GetPatchPoints(
Vtr::internal::Level const * level, Index faceIndex,
Vtr::internal::Level::VSpan const cornerSpans[],
int levelVertOffset);
int levelVertOffset, int fvarChannel = -1);
private:
@ -112,7 +94,8 @@ private:
/// accumates it
bool addPatchBasis(Vtr::internal::Level const & level, Index faceIndex,
Vtr::internal::Level::VSpan const cornerSpans[],
bool newVerticesMask[4][5], int levelVertOffset);
bool newVerticesMask[4][5],
int levelVertOffset, int fvarChannel);
StencilTable *_vertexStencils;
StencilTable *_varyingStencils;

View File

@ -41,11 +41,13 @@ EndCapLegacyGregoryPatchFactory::EndCapLegacyGregoryPatchFactory(
ConstIndexArray
EndCapLegacyGregoryPatchFactory::GetPatchPoints(
Vtr::internal::Level const * level, Index faceIndex,
Vtr::internal::Level::VSpan const cornerSpans[],
int levelVertOffset) {
Vtr::internal::Level::VSpan const /*cornerSpans*/[],
int levelVertOffset, int fvarChannel) {
// Gregory Regular Patch (4 CVs + quad-offsets / valence tables)
Vtr::ConstIndexArray faceVerts = level->getFaceVertices(faceIndex);
Vtr::ConstIndexArray faceVerts = (fvarChannel < 0)
? level->getFaceVertices(faceIndex)
: level->getFaceFVarValues(faceIndex, fvarChannel);
if (level->getFaceCompositeVTag(faceVerts)._boundary) {
for (int j = 0; j < 4; ++j) {
@ -68,9 +70,11 @@ EndCapLegacyGregoryPatchFactory::GetPatchPoints(
// Populate the quad-offsets table used by Gregory patches
//
static void getQuadOffsets(
Vtr::internal::Level const& level, Index faceIndex, unsigned int offsets[]) {
Vtr::internal::Level const& level, Index faceIndex, unsigned int offsets[], int fvarChannel) {
Vtr::ConstIndexArray fVerts = level.getFaceVertices(faceIndex);
Vtr::ConstIndexArray fVerts = (fvarChannel < 0)
? level.getFaceVertices(faceIndex)
: level.getFaceFVarValues(faceIndex, fvarChannel);
for (int i = 0; i < 4; ++i) {
@ -101,7 +105,8 @@ void
EndCapLegacyGregoryPatchFactory::Finalize(
int maxValence,
PatchTable::QuadOffsetsTable *quadOffsetsTable,
PatchTable::VertexValenceTable *vertexValenceTable)
PatchTable::VertexValenceTable *vertexValenceTable,
int fvarChannel)
{
// populate quad offsets
@ -118,11 +123,11 @@ EndCapLegacyGregoryPatchFactory::Finalize(
PatchTable::QuadOffsetsTable::value_type *p =
&((*quadOffsetsTable)[0]);
for (size_t i = 0; i < numGregoryPatches; ++i) {
getQuadOffsets(maxLevel, _gregoryFaceIndices[i], p);
getQuadOffsets(maxLevel, _gregoryFaceIndices[i], p, fvarChannel);
p += 4;
}
for (size_t i = 0; i < numGregoryBoundaryPatches; ++i) {
getQuadOffsets(maxLevel, _gregoryBoundaryFaceIndices[i], p);
getQuadOffsets(maxLevel, _gregoryBoundaryFaceIndices[i], p, fvarChannel);
p += 4;
}
}

View File

@ -58,14 +58,17 @@ public:
///
/// @param levelVertOffset relative offset of patch vertex indices
///
/// @param fvarChannel face-varying channel index
///
ConstIndexArray GetPatchPoints(
Vtr::internal::Level const * level, Index faceIndex,
Vtr::internal::Level::VSpan const cornerSpans[],
int levelVertOffset);
int levelVertOffset, int fvarChannel = -1);
void Finalize(int maxValence,
PatchTable::QuadOffsetsTable *quadOffsetsTable,
PatchTable::VertexValenceTable *vertexValenceTable);
PatchTable::VertexValenceTable *vertexValenceTable,
int fvarChannel = -1);
private:

View File

@ -347,6 +347,9 @@ gatherEndCapPatchPoints(
int levelVertOffset = (fvarChannel < 0)
? levelVertOffsets[patch.levelIndex]
: levelFVarValueOffsets[fvarChannel][patch.levelIndex];
int refinerChannel = (fvarChannel < 0)
? fvarChannel
: fvarChannelIndices[fvarChannel];
// identify relevant spans around the corner vertices for the irregular patches
// (this is just a stub for now -- leaving the span "size" to zero, as constructed,
@ -354,7 +357,7 @@ gatherEndCapPatchPoints(
Vtr::internal::Level::VSpan cornerSpans[4];
ConstIndexArray cvs = endCapFactory->GetPatchPoints(
level, patch.faceIndex, cornerSpans, levelVertOffset);
level, patch.faceIndex, cornerSpans, levelVertOffset, refinerChannel);
for (int i = 0; i < cvs.size(); ++i) iptrs[i] = cvs[i];
return cvs.size();