fix FarMultiMeshFactory to work with refactored FarPatchTables.

This commit is contained in:
Takahito Tejima 2013-05-09 19:16:51 -07:00
parent 42f84b78d0
commit 1b879d706f
8 changed files with 185 additions and 121 deletions

View File

@ -134,14 +134,16 @@ public:
int start,
int end,
int tableOffset,
int vertexOffset) :
int vertexOffset,
int meshIndex=0) :
_kernelType(kernelType),
_level(level),
_tableIndex(tableIndex),
_start(start),
_end(end),
_tableOffset(tableOffset),
_vertexOffset(vertexOffset) {
_vertexOffset(vertexOffset),
_meshIndex(meshIndex) {
}
/// Returns the type of kernel to apply to the vertices in the batch.
@ -210,6 +212,12 @@ public:
return & _vertexOffset;
}
/// Returns the mesh index (used in batching)
int GetMeshIndex() const {
return _meshIndex;
}
private:
friend class FarKernelBatchFactory;
template <class X, class Y> friend class FarMultiMeshFactory;
@ -221,6 +229,7 @@ private:
int _end;
int _tableOffset;
int _vertexOffset;
int _meshIndex;
};
typedef std::vector<FarKernelBatch> FarKernelBatchVector;

View File

@ -123,6 +123,9 @@ public:
/// Returns the total number of vertices in the mesh across across all depths
int GetNumVertices() const { return (int)(_vertices.size()); }
/// Returns the total number of vertices in the mesh across across all depths
int GetNumPtexFaces() const { return _numPtexFaces; }
/// True if the mesh tables support the feature-adaptive mode.
bool SupportsFeatureAdaptive() const { return _patchTables!=NULL; }
@ -167,6 +170,8 @@ private:
// fvar data for each face
std::vector< std::vector<float> > _fvarData;
int _totalFVarWidth; // from hbrMesh
int _numPtexFaces;
};
template <class U>

View File

@ -238,7 +238,8 @@ private:
_numVertices,
_numCoarseVertices,
_numFaces,
_maxValence;
_maxValence,
_numPtexFaces;
// remapping table to translate vertex ID's between Hbr indices and the
// order of the same vertices in the tables
@ -597,9 +598,11 @@ FarMeshFactory<T,U>::FarMeshFactory( HbrMesh<T> * mesh, int maxlevel, bool adapt
_numCoarseVertices(-1),
_numFaces(-1),
_maxValence(4),
_numPtexFaces(-1),
_facesList(maxlevel+1)
{
_numCoarseVertices = mesh->GetNumVertices();
_numPtexFaces = getNumPtexFaces(mesh);
// Subdivide the Hbr mesh up to maxlevel.
//
@ -754,6 +757,19 @@ FarMeshFactory<T,U>::generatePtexCoordinates( std::vector<FarPtexCoord> & vec, i
}
}
template <class T> int
getNumPtexFaces(HbrMesh<T> const * hmesh) {
HbrFace<T> * lastface = hmesh->GetFace(hmesh->GetNumFaces()-1);
assert(lastface);
int result = lastface->GetPtexIndex();
result += (hmesh->GetSubdivision()->FaceIsExtraordinary(hmesh, lastface) ?
lastface->GetNumVertices() : 1);
return result;
}
template <class T> float *
computeFVarData(HbrFace<T> const *f, const int width, float *coord, bool isAdaptive) {
@ -883,6 +899,8 @@ FarMeshFactory<T,U>::Create( bool requireFVarData ) {
generateFVarData(result->_fvarData[l], l);
}
}
result->_numPtexFaces = _numPtexFaces;
// Create VertexEditTables if necessary
if (GetHbrMesh()->HasVertexEdits()) {

View File

@ -96,6 +96,10 @@ public:
///
FarMesh<U> * Create(std::vector<FarMesh<U> const *> const &meshes);
std::vector<FarPatchTables::PatchArrayVector> const & GetMultiPatchArrays() {
return _multiPatchArrays;
}
private:
// splice subdivision tables
@ -104,6 +108,14 @@ private:
// splice patch tables
FarPatchTables * splicePatchTables(FarMeshVector const &meshes);
// splice patch array
FarPatchTables::PTable::iterator splicePatch(FarPatchTables::Descriptor desc,
FarMeshVector const &meshes,
FarPatchTables::PatchArrayVector &result,
FarPatchTables::PTable::iterator dstIndexIt,
int *voffset, int *poffset, int *qoffset,
std::vector<int> const &vertexOffsets);
// splice quad indices
void spliceQuads(FarMesh<U> *result, FarMeshVector const &meshes);
@ -112,6 +124,9 @@ private:
int _maxlevel;
int _maxvalence;
// patch arrays for each mesh
std::vector<FarPatchTables::PatchArrayVector> _multiPatchArrays;
};
@ -177,6 +192,12 @@ copyWithOffset(IT dst_iterator, V const &src, int offset) {
std::bind2nd(std::plus<typename V::value_type>(), offset));
}
template <typename V, typename IT> static IT
copyWithOffset(IT dst_iterator, V const &src, int start, int count, int offset) {
return std::transform(src.begin()+start, src.begin()+start+count, dst_iterator,
std::bind2nd(std::plus<typename V::value_type>(), offset));
}
template <typename V, typename IT> static IT
copyWithOffsetF_ITa(IT dst_iterator, V const &src, int offset) {
for (typename V::const_iterator it = src.begin(); it != src.end();) {
@ -402,6 +423,49 @@ FarMultiMeshFactory<T, U>::spliceQuads(FarMesh<U> *result, FarMeshVector const &
}
}
template <class T, class U> FarPatchTables::PTable::iterator
FarMultiMeshFactory<T, U>::splicePatch(FarPatchTables::Descriptor desc,
FarMeshVector const &meshes,
FarPatchTables::PatchArrayVector &result,
FarPatchTables::PTable::iterator dstIndexIt,
int *voffset, int *poffset, int *qoffset,
std::vector<int> const &vertexOffsets)
{
for (size_t i = 0; i < meshes.size(); ++i) {
FarPatchTables const *patchTables = meshes[i]->GetPatchTables();
FarPatchTables::PatchArray const *srcPatchArray = patchTables->GetPatchArray(desc);
if (not srcPatchArray) continue;
// create new patcharray with offset
int vindex = srcPatchArray->GetVertIndex();
int npatch = srcPatchArray->GetNumPatches();
int nvertex = npatch * srcPatchArray->GetDescriptor().GetNumControlVertices();
FarPatchTables::PatchArray patchArray(srcPatchArray->GetDescriptor(),
*voffset,
*poffset,
npatch,
*qoffset);
// append patch array
result.push_back(patchArray);
_multiPatchArrays[i].push_back(patchArray);
// increment offset
*voffset += nvertex;
*poffset += npatch;
*qoffset += (desc.GetType() == FarPatchTables::GREGORY ||
desc.GetType() == FarPatchTables::GREGORY_BOUNDARY) ? npatch * 4 : 0;
// copy index arrays [vindex, vindex+nvertex]
dstIndexIt = copyWithOffset(dstIndexIt,
patchTables->GetPatchTable(),
vindex,
nvertex,
vertexOffsets[i]);
}
return dstIndexIt;
}
template <class T, class U> FarPatchTables *
FarMultiMeshFactory<T, U>::splicePatchTables(FarMeshVector const &meshes) {
@ -411,11 +475,15 @@ FarMultiMeshFactory<T, U>::splicePatchTables(FarMeshVector const &meshes) {
int total_quadOffset1 = 0;
std::vector<int> vertexOffsets;
std::vector<int> gregoryQuadOffsets;
std::vector<int> numGregoryPatches;
int vertexOffset = 0;
int maxValence = 0;
int numTotalIndices = 0;
result->_patchCounts.reserve(meshes.size());
FarPatchCount totalCount;
//result->_patchCounts.reserve(meshes.size());
//FarPatchCount totalCount;
typedef FarPatchTables::Descriptor Descriptor;
// count how many patches exist on each mesh
for (size_t i = 0; i < meshes.size(); ++i) {
@ -425,110 +493,42 @@ FarMultiMeshFactory<T, U>::splicePatchTables(FarMeshVector const &meshes) {
vertexOffsets.push_back(vertexOffset);
vertexOffset += meshes[i]->GetNumVertices();
// accum patch counts. assuming given patch table has one element
const FarPatchCount &patchCount = ptables->GetPatchCounts()[0];
result->_patchCounts.push_back(patchCount);
totalCount.Append(patchCount);
// need to align maxvalence with the highest value
maxValence = std::max(maxValence, ptables->_maxValence);
total_quadOffset0 += (int)ptables->_full._G_IT.first.size();
total_quadOffset1 += (int)ptables->_full._G_B_IT.first.size();
FarPatchTables::PatchArray const *gregory = ptables->GetPatchArray(Descriptor(FarPatchTables::GREGORY, FarPatchTables::NON_TRANSITION, /*rot*/ 0));
FarPatchTables::PatchArray const *gregoryBoundary = ptables->GetPatchArray(Descriptor(FarPatchTables::GREGORY_BOUNDARY, FarPatchTables::NON_TRANSITION, /*rot*/ 0));
int nGregory = gregory ? gregory->GetNumPatches() : 0;
int nGregoryBoundary = gregoryBoundary ? gregoryBoundary->GetNumPatches() : 0;
total_quadOffset0 += nGregory * 4;
total_quadOffset1 += nGregoryBoundary * 4;
numGregoryPatches.push_back(nGregory);
gregoryQuadOffsets.push_back(total_quadOffset0);
numTotalIndices += ptables->GetNumControlVertices();
}
// Allocate full patches
result->_full._R_IT.first.resize(totalCount.regular*16);
result->_full._R_IT.second.resize(totalCount.regular);
result->_full._B_IT.first.resize(totalCount.boundary*12);
result->_full._B_IT.second.resize(totalCount.boundary);
result->_full._C_IT.first.resize(totalCount.corner*9);
result->_full._C_IT.second.resize(totalCount.corner);
result->_full._G_IT.first.resize(totalCount.gregory*4);
result->_full._G_IT.second.resize(totalCount.gregory);
result->_full._G_B_IT.first.resize(totalCount.boundaryGregory*4);
result->_full._G_B_IT.second.resize(totalCount.boundaryGregory);
result->_patches.resize(numTotalIndices);
// Allocate transition Patches
for (int i=0; i<5; ++i) {
result->_transition[i]._R_IT.first.resize(totalCount.transitionRegular[i]*16);
result->_transition[i]._R_IT.second.resize(totalCount.transitionRegular[i]);
for (int j=0; j<4; ++j) {
result->_transition[i]._B_IT[j].first.resize(totalCount.transitionBoundary[i][j]*12);
result->_transition[i]._B_IT[j].second.resize(totalCount.transitionBoundary[i][j]);
result->_transition[i]._C_IT[j].first.resize(totalCount.transitionCorner[i][j]*9);
result->_transition[i]._C_IT[j].second.resize(totalCount.transitionCorner[i][j]);
}
}
// Allocate vertex valence table, quad offset table
if ((result->_full._G_IT.first.size() + result->_full._G_B_IT.first.size()) > 0) {
if (total_quadOffset0 + total_quadOffset1 > 0) {
result->_vertexValenceTable.resize((2*maxValence+1) * vertexOffset);
result->_quadOffsetTable.resize(total_quadOffset0 + total_quadOffset1);
}
typedef struct IndexIterators {
std::vector<unsigned int>::iterator R_P, B_P[4], C_P[4], G_P[2];
} IndexIterator;
// splice tables
// assuming input farmeshes have dense patchtables
typedef struct LevelIterators {
std::vector<unsigned char>::iterator R_P, B_P[4], C_P[4], G_P[2];
} LevelIterator;
IndexIterator full, transition[5];
LevelIterator fullLv, transitionLv[5];
_multiPatchArrays.resize(meshes.size());
// prepare destination iterators
full.R_P = result->_full._R_IT.first.begin();
full.B_P[0] = result->_full._B_IT.first.begin();
full.C_P[0] = result->_full._C_IT.first.begin();
full.G_P[0] = result->_full._G_IT.first.begin();
full.G_P[1] = result->_full._G_B_IT.first.begin();
for (int i = 0; i < 5; ++i) {
transition[i].R_P = result->_transition[i]._R_IT.first.begin();
for (int j = 0 ; j < 4; ++j) {
transition[i].B_P[j] = result->_transition[i]._B_IT[j].first.begin();
transition[i].C_P[j] = result->_transition[i]._C_IT[j].first.begin();
}
}
fullLv.R_P = result->_full._R_IT.second.begin();
fullLv.B_P[0] = result->_full._B_IT.second.begin();
fullLv.C_P[0] = result->_full._C_IT.second.begin();
fullLv.G_P[0] = result->_full._G_IT.second.begin();
fullLv.G_P[1] = result->_full._G_B_IT.second.begin();
for (int i = 0; i < 5; ++i) {
transitionLv[i].R_P = result->_transition[i]._R_IT.second.begin();
for (int j = 0 ; j < 4; ++j) {
transitionLv[i].B_P[j] = result->_transition[i]._B_IT[j].second.begin();
transitionLv[i].C_P[j] = result->_transition[i]._C_IT[j].second.begin();
}
}
int voffset = 0, poffset = 0, qoffset = 0;
FarPatchTables::PTable::iterator dstIndexIt = result->_patches.begin();
// merge tables with vertex index offset
for (size_t i = 0; i < meshes.size(); ++i) {
const FarPatchTables *ptables = meshes[i]->GetPatchTables();
int vertexOffset = vertexOffsets[i];
full.R_P = copyWithOffset(full.R_P, ptables->_full._R_IT.first, vertexOffset);
full.B_P[0] = copyWithOffset(full.B_P[0], ptables->_full._B_IT.first, vertexOffset);
full.C_P[0] = copyWithOffset(full.C_P[0], ptables->_full._C_IT.first, vertexOffset);
full.G_P[0] = copyWithOffset(full.G_P[0], ptables->_full._G_IT.first, vertexOffset);
full.G_P[1] = copyWithOffset(full.G_P[1], ptables->_full._G_B_IT.first, vertexOffset);
fullLv.R_P = copyWithOffset(fullLv.R_P, ptables->_full._R_IT.second, 0);
fullLv.B_P[0] = copyWithOffset(fullLv.B_P[0], ptables->_full._B_IT.second, 0);
fullLv.C_P[0] = copyWithOffset(fullLv.C_P[0], ptables->_full._C_IT.second, 0);
fullLv.G_P[0] = copyWithOffset(fullLv.G_P[0], ptables->_full._G_IT.second, 0);
fullLv.G_P[1] = copyWithOffset(fullLv.G_P[1], ptables->_full._G_B_IT.second, 0);
for (int t = 0; t < 5; ++t) {
transition[t].R_P = copyWithOffset(transition[t].R_P, ptables->_transition[t]._R_IT.first, vertexOffset);
transitionLv[t].R_P = copyWithOffset(transitionLv[t].R_P, ptables->_transition[t]._R_IT.second, 0);
for (int r = 0; r < 4; ++r) {
transition[t].B_P[r] = copyWithOffset(transition[t].B_P[r], ptables->_transition[t]._B_IT[r].first, vertexOffset);
transition[t].C_P[r] = copyWithOffset(transition[t].C_P[r], ptables->_transition[t]._C_IT[r].first, vertexOffset);
transitionLv[t].B_P[r] = copyWithOffset(transitionLv[t].B_P[r], ptables->_transition[t]._B_IT[r].second, 0);
transitionLv[t].C_P[r] = copyWithOffset(transitionLv[t].C_P[r], ptables->_transition[t]._C_IT[r].second, 0);
}
}
// splice all patches
for (FarPatchTables::Descriptor::iterator it = FarPatchTables::Descriptor::begin(); it != FarPatchTables::Descriptor::end(); ++it) {
dstIndexIt = splicePatch(*it, meshes, result->_patchArrays, dstIndexIt, &voffset, &poffset, &qoffset, vertexOffsets);
}
// merge vertexvalence and quadoffset tables
@ -542,17 +542,27 @@ FarMultiMeshFactory<T, U>::splicePatchTables(FarMeshVector const &meshes) {
// merge vertex valence
// note: some prims may not have vertex valence table, but still need a space
// in order to fill following prim's data at appropriate location.
copyWithOffsetVertexValence(VV_IT, ptables->_vertexValenceTable, ptables->_maxValence, maxValence, vertexOffsets[i]);
copyWithOffsetVertexValence(VV_IT,
ptables->_vertexValenceTable,
ptables->_maxValence,
maxValence,
vertexOffsets[i]);
VV_IT += meshes[i]->GetNumVertices() * (2 * maxValence + 1);
// merge quad offsets
int nGregoryQuads = (int)ptables->_full._G_IT.first.size();
Q0_IT = std::copy(ptables->_quadOffsetTable.begin(),
ptables->_quadOffsetTable.begin()+nGregoryQuads,
Q0_IT);
Q1_IT = std::copy(ptables->_quadOffsetTable.begin()+nGregoryQuads,
ptables->_quadOffsetTable.end(),
Q1_IT);
// int nGregoryQuads = (int)ptables->_full._G_IT.first.size();
int nGregoryQuads = numGregoryPatches[i] * 4;
if (nGregoryQuads > 0) {
Q0_IT = std::copy(ptables->_quadOffsetTable.begin(),
ptables->_quadOffsetTable.begin()+nGregoryQuads,
Q0_IT);
}
if (nGregoryQuads < (int)ptables->_quadOffsetTable.size()) {
Q1_IT = std::copy(ptables->_quadOffsetTable.begin()+nGregoryQuads,
ptables->_quadOffsetTable.end(),
Q1_IT);
}
}
return result;

View File

@ -58,8 +58,8 @@ OsdDrawContext::~OsdDrawContext() {}
// Allows ordering of patches by type
bool
OsdDrawContext::PatchDescriptor::operator < ( PatchDescriptor const other ) const {
OsdDrawContext::PatchDescriptor::operator < ( PatchDescriptor const other ) const
{
return _farDesc < other._farDesc or (_farDesc == other._farDesc and
(_subPatch < other._subPatch or ((_subPatch == other._subPatch) and
(_maxValence < other._maxValence or ((_maxValence == other._maxValence) and
@ -68,7 +68,8 @@ OsdDrawContext::PatchDescriptor::operator < ( PatchDescriptor const other ) cons
// True if the descriptors are identical
bool
OsdDrawContext::PatchDescriptor::operator == ( PatchDescriptor const other ) const {
OsdDrawContext::PatchDescriptor::operator == ( PatchDescriptor const other ) const
{
return _farDesc == other._farDesc and
_subPatch == other._subPatch and
_maxValence == other._maxValence and
@ -76,34 +77,34 @@ OsdDrawContext::PatchDescriptor::operator == ( PatchDescriptor const other ) con
}
void
OsdDrawContext::createPatchArrays(FarPatchTables const * patchTables, int numElements) {
int maxValence = patchTables->GetMaxValence();
OsdDrawContext::ConvertPatchArrays(FarPatchTables::PatchArrayVector const &farPatchArrays,
OsdDrawContext::PatchArrayVector &osdPatchArrays,
int maxValence, int numElements)
{
// create patch arrays for drawing (while duplicating subpatches for transition patch arrays)
static int subPatchCounts[] = { 1, 3, 4, 4, 4, 2 }; // number of subpatches for patterns
FarPatchTables::PatchArrayVector const & srcPatchArrays = patchTables->GetAllPatchArrays();
int numTotalPatchArrays = 0;
for (int i = 0; i < (int)srcPatchArrays.size(); ++i) {
FarPatchTables::TransitionPattern pattern = srcPatchArrays[i].GetDescriptor().GetPattern();
for (int i = 0; i < (int)farPatchArrays.size(); ++i) {
FarPatchTables::TransitionPattern pattern = farPatchArrays[i].GetDescriptor().GetPattern();
numTotalPatchArrays += subPatchCounts[(int)pattern];
}
// allocate drawing patch arrays
patchArrays.reserve(numTotalPatchArrays);
for (int i = 0; i < (int)srcPatchArrays.size(); ++i) {
FarPatchTables::TransitionPattern pattern = srcPatchArrays[i].GetDescriptor().GetPattern();
osdPatchArrays.clear();
osdPatchArrays.reserve(numTotalPatchArrays);
for (int i = 0; i < (int)farPatchArrays.size(); ++i) {
FarPatchTables::TransitionPattern pattern = farPatchArrays[i].GetDescriptor().GetPattern();
int numSubPatches = subPatchCounts[(int)pattern];
FarPatchTables::PatchArray const &parray = srcPatchArrays[i];
FarPatchTables::PatchArray const &parray = farPatchArrays[i];
FarPatchTables::Descriptor srcDesc = parray.GetDescriptor();
for (int j = 0; j < numSubPatches; ++j) {
PatchDescriptor desc(srcDesc, maxValence, j, numElements);
patchArrays.push_back(PatchArray(desc, parray.GetArrayRange()));
osdPatchArrays.push_back(PatchArray(desc, parray.GetArrayRange()));
}
}
}

View File

@ -112,6 +112,11 @@ public:
return _numElements;
}
/// Set the number of vertex elements
void SetNumElements(int numElements) {
_numElements = numElements;
}
/// Allows ordering of patches by type
bool operator < ( PatchDescriptor const other ) const;
@ -135,6 +140,11 @@ public:
return _desc;
}
/// Update a patch descriptor
void SetDescriptor(PatchDescriptor desc) {
_desc = desc;
}
/// Returns a array range struct
FarPatchTables::PatchArray::ArrayRange const & GetArrayRange() const {
return _range;
@ -162,10 +172,16 @@ public:
return _range.npatches * _desc.GetNumControlVertices();
}
/// Returns the offset of quad offset table
unsigned int GetQuadOffsetIndex() const {
return _range.quadOffsetIndex;
}
/// Set num patches (used at batch glomming)
void SetNumPatches(int npatches) {
_range.npatches = npatches;
}
private:
PatchDescriptor _desc;
FarPatchTables::PatchArray::ArrayRange _range;
@ -178,6 +194,11 @@ public:
bool IsAdaptive() const { return _isAdaptive; }
static void ConvertPatchArrays(FarPatchTables::PatchArrayVector const &farPatchArrays,
OsdDrawContext::PatchArrayVector &osdPatchArrays,
int maxValence, int numElements);
public: // XXX: move to private member
PatchArrayVector patchArrays;
protected:

View File

@ -222,7 +222,7 @@ OsdGLDrawContext::allocate(FarMesh<OsdVertex> *farMesh,
// adaptive patches
_isAdaptive = true;
createPatchArrays(patchTables, numElements);
ConvertPatchArrays(patchTables->GetAllPatchArrays(), patchArrays, patchTables->GetMaxValence(), numElements);
FarPatchTables::PTable const & ptables = patchTables->GetPatchTable();

View File

@ -120,7 +120,7 @@ public:
/// true if the GL version detected supports shader tessellation
static bool SupportsAdaptiveTessellation();
private:
protected:
bool allocate(FarMesh<OsdVertex> *farMesh,
GLuint vbo, int numElements,
bool requireFVarData);