Merge pull request #284 from nathan-at-digitalfish/add_far_triangulate

Generate triangle patches for a uniformly subdivided mesh
This commit is contained in:
Manuel Kraemer 2014-04-22 11:42:56 -07:00
commit 808aabfbc5
4 changed files with 59 additions and 71 deletions

View File

@ -45,6 +45,7 @@
#include "../far/bilinearSubdivisionTablesFactory.h"
#include "../far/catmarkSubdivisionTablesFactory.h"
#include "../far/loopSubdivisionTablesFactory.h"
#include "../far/patchTables.h"
#include "../far/patchTablesFactory.h"
#include "../far/vertexEditTablesFactory.h"
@ -82,14 +83,18 @@ public:
/// level of isolation around extraordinary topological
/// features.
///
/// @param adaptive Switch between uniform and feature adaptive mode
///
/// @param firstLevel First level of subdivision to use when building the
/// FarMesh. The default -1 only generates a single patch
/// array for the highest level of subdivision)
/// Note : firstLevel is only applicable if adaptive is false
///
/// @param adaptive Switch between uniform and feature adaptive mode
/// @param patchType The type of patch to create: QUADS or TRIANGLES
/// Note : patchType is only applicable if adaptive is false
///
FarMeshFactory(HbrMesh<T> * mesh, int maxlevel, bool adaptive=false, int firstLevel=-1);
FarMeshFactory(HbrMesh<T> * mesh, int maxlevel, bool adaptive=false, int firstLevel=-1,
FarPatchTables::Type patchType=FarPatchTables::QUADS);
/// \brief Create a table-based mesh representation
///
@ -224,6 +229,8 @@ private:
_maxValence,
_numPtexFaces;
FarPatchTables::Type _patchType;
// remapping table to translate vertex ID's between Hbr indices and the
// order of the same vertices in the tables
std::vector<int> _remapTable;
@ -581,7 +588,7 @@ FarMeshFactory<T,U>::refineAdaptive( HbrMesh<T> * mesh, int maxIsolate ) {
// random order, so the builder runs 2 passes over the entire vertex list to
// gather the counters needed to generate the indexing tables.
template <class T, class U>
FarMeshFactory<T,U>::FarMeshFactory( HbrMesh<T> * mesh, int maxlevel, bool adaptive, int firstlevel ) :
FarMeshFactory<T,U>::FarMeshFactory( HbrMesh<T> * mesh, int maxlevel, bool adaptive, int firstlevel, FarPatchTables::Type patchType ) :
_hbrMesh(mesh),
_adaptive(adaptive),
_maxlevel(maxlevel),
@ -591,6 +598,7 @@ FarMeshFactory<T,U>::FarMeshFactory( HbrMesh<T> * mesh, int maxlevel, bool adapt
_numFaces(-1),
_maxValence(4),
_numPtexFaces(-1),
_patchType(patchType),
_facesList(maxlevel+1)
{
_numCoarseVertices = mesh->GetNumVertices();
@ -729,7 +737,7 @@ FarMeshFactory<T,U>::Create( bool requireFVarData ) {
result->_patchTables = factory.Create(GetMaxLevel()+1, _maxValence, _numPtexFaces, fvarwidth);
} else {
result->_patchTables = FarPatchTablesFactory<T>::Create(GetHbrMesh(), _facesList, _remapTable, _firstlevel, _numPtexFaces, fvarwidth );
result->_patchTables = FarPatchTablesFactory<T>::Create(GetHbrMesh(), _facesList, _remapTable, _firstlevel, _patchType, _numPtexFaces, fvarwidth );
}
assert( result->_patchTables );

View File

@ -96,9 +96,11 @@ protected:
/// a single patch array for the highest level of
/// subdivision)
///
/// @param patchType The type of patch to create: QUADS or TRIANGLES
///
/// @param numPtexFaces Number of ptex faces
///
/// @param fvarWidth The width of the interleaved face-varying data
/// @param fvarWidth The width of the interleaved face-varying data
///
/// @return A new instance of FarPatchTables
///
@ -106,6 +108,7 @@ protected:
FacesList const & flist,
std::vector<int> const & remapTable,
int firstLevel=-1,
FarPatchTables::Type patchType=FarPatchTables::QUADS,
int numPtexFaces=0,
int fvarWidth=0 );
@ -301,7 +304,14 @@ FarPatchTablesFactory<T>::allocateTables( FarPatchTables * tables, int nlevels,
tables->_paramTable.resize( npatches );
if (fvarwidth>0) {
tables->_fvarData._data.resize( npatches * 4 * fvarwidth );
FarPatchTables::PatchArrayVector const & parrays = tables->GetPatchArrayVector();
int nfvarverts = 0;
for (int i=0; i<(int)parrays.size(); ++i) {
nfvarverts += parrays[i].GetNumPatches() *
(parrays[i].GetDescriptor().GetType() == FarPatchTables::TRIANGLES ? 3 : 4);
}
tables->_fvarData._data.resize( nfvarverts * fvarwidth );
if (nlevels >1) {
tables->_fvarData._offsets.resize( nlevels );
@ -311,7 +321,9 @@ FarPatchTablesFactory<T>::allocateTables( FarPatchTables * tables, int nlevels,
// Uniform mesh factory (static function because it requires no cached state)
template <class T> FarPatchTables *
FarPatchTablesFactory<T>::Create( HbrMesh<T> const * mesh, FacesList const & flist, std::vector<int> const & remapTable, int firstLevel, int numPtexFaces, int fvarwidth ) {
FarPatchTablesFactory<T>::Create( HbrMesh<T> const * mesh, FacesList const & flist, std::vector<int> const & remapTable, int firstLevel, FarPatchTables::Type patchType, int numPtexFaces, int fvarwidth ) {
assert(patchType == FarPatchTables::QUADS || patchType == FarPatchTables::TRIANGLES);
if (flist.size()<2)
return 0;
@ -319,8 +331,12 @@ FarPatchTablesFactory<T>::Create( HbrMesh<T> const * mesh, FacesList const & fli
FarPatchTables * result = new FarPatchTables(0);
bool isLoop = FarMeshFactory<T,T>::isLoop(mesh);
if (isLoop)
patchType = FarPatchTables::TRIANGLES;
int nv = isLoop ? 3 : 4;
bool triangulateQuads = !isLoop && patchType == FarPatchTables::TRIANGLES;
int nverts = patchType == FarPatchTables::TRIANGLES ? 3 : 4;
int firstArray = firstLevel > -1 ? firstLevel : (int)flist.size()-1,
nlevels = (int)flist.size()-firstArray;
@ -330,17 +346,19 @@ FarPatchTablesFactory<T>::Create( HbrMesh<T> const * mesh, FacesList const & fli
FarPatchTables::PatchArrayVector & parray = result->_patchArrays;
parray.reserve( (int)flist.size() - firstArray );
Descriptor desc( isLoop ? FarPatchTables::TRIANGLES : FarPatchTables::QUADS, FarPatchTables::NON_TRANSITION, 0 );
Descriptor desc( patchType, FarPatchTables::NON_TRANSITION, 0 );
for (int i=1, poffset=0, voffset=0; i<(int)flist.size(); ++i) {
int nfaces = (int)flist[i].size();
int npatches = (int)flist[i].size();
if (triangulateQuads)
npatches *= 2;
if (i>=firstArray) {
parray.push_back( FarPatchTables::PatchArray(desc, voffset, poffset, nfaces, 0 ) );
parray.push_back( FarPatchTables::PatchArray(desc, voffset, poffset, npatches, 0 ) );
voffset += nfaces * nv;
poffset += nfaces;
voffset += npatches * nverts;
poffset += npatches;
}
}
@ -359,7 +377,7 @@ FarPatchTablesFactory<T>::Create( HbrMesh<T> const * mesh, FacesList const & fli
for (int i=0; i<(int)flist[level].size(); ++i) {
HbrFace<T> * f = flist[level][i];
assert( f and f->GetNumVertices()==nv);
assert( f and f->GetNumVertices() == isLoop ? 3 : 4);
for (int j=0; j<f->GetNumVertices(); ++j) {
*iptr++ = remapTable[f->GetVertex(j)->GetID()];
@ -369,10 +387,28 @@ FarPatchTablesFactory<T>::Create( HbrMesh<T> const * mesh, FacesList const & fli
if (fvarwidth>0)
fptr = computeFVarData(f, fvarwidth, fptr, /*isAdaptive=*/false);
if (triangulateQuads) {
// Triangulate the quadrilateral: {v0,v1,v2,v3} -> {v0,v1,v2},{v3,v0,v2}.
*iptr = *(iptr - 4); // copy v0 index
++iptr;
*iptr = *(iptr - 3); // copy v2 index
++iptr;
*pptr = *(pptr - 1); // copy first patch param
++pptr;
for (int j = 0; j < fvarwidth; ++j, ++fptr) {
*fptr = *(fptr - 4 * fvarwidth); // copy v0 fvar data
}
for (int j = 0; j < fvarwidth; ++j, ++fptr) {
*fptr = *(fptr - 3 * fvarwidth); // copy v2 fvar data
}
}
}
if (fvarwidth>0 and (not result->_fvarData._offsets.empty())) {
result->_fvarData._offsets[level-firstArray] = (fvarOffset+=(int)flist[level].size()*4*fvarwidth);
result->_fvarData._offsets[level-firstArray] = (fvarOffset+=(int)flist[level].size()*nverts*fvarwidth);
}
}

View File

@ -60,51 +60,6 @@ OsdDrawContext::ConvertPatchArrays(FarPatchTables::PatchArrayVector const &farPa
osdPatchArrays.push_back(PatchArray(desc, parray.GetArrayRange()));
}
}
/*
#if defined(GL_ES_VERSION_2_0)
// XXX: farmesh should have FarDensePatchTable for dense mesh indices.
// instead of GetFaceVertices().
const FarSubdivisionTables *tables = farMesh->GetSubdivisionTables();
int level = tables->GetMaxLevel();
const std::vector<int> &indices = farMesh->GetFaceVertices(level-1);
int numIndices = (int)indices.size();
// Allocate and fill index buffer.
glGenBuffers(1, &patchIndexBuffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, patchIndexBuffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER,
numIndices * sizeof(unsigned int), &(indices[0]), GL_STATIC_DRAW);
// OpenGLES 2 supports only triangle topologies for filled
// primitives i.e. not QUADS or PATCHES or LINES_ADJACENCY
// For the convenience of clients build build a triangles
// index buffer by splitting quads.
int numQuads = indices.size() / 4;
int numTrisIndices = numQuads * 6;
std::vector<short> trisIndices;
trisIndices.reserve(numTrisIndices);
for (int i=0; i<numQuads; ++i) {
const int * quad = &indices[i*4];
trisIndices.push_back(short(quad[0]));
trisIndices.push_back(short(quad[1]));
trisIndices.push_back(short(quad[2]));
trisIndices.push_back(short(quad[2]));
trisIndices.push_back(short(quad[3]));
trisIndices.push_back(short(quad[0]));
}
// Allocate and fill triangles index buffer.
glGenBuffers(1, &patchTrianglesIndexBuffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, patchTrianglesIndexBuffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER,
numTrisIndices * sizeof(short), &(trisIndices[0]), GL_STATIC_DRAW);
#endif
*/
}
} // end namespace OPENSUBDIV_VERSION

View File

@ -84,13 +84,6 @@ public:
return _patchIndexBuffer;
}
#if defined(GL_ES_VERSION_2_0)
/// Returns the GL a VBO containing a triangulated version of the mesh
GLuint GetPatchTrianglesIndexBUffer() const {
return _patchTrianglesIndexBuffer;
}
#endif
/// Returns the GL texture buffer containing the patch local parameterization
/// data
GLuint GetPatchParamTextureBuffer() const {
@ -122,10 +115,6 @@ public:
protected:
GLuint _patchIndexBuffer;
#if defined(GL_ES_VERSION_2_0)
GLuint _patchTrianglesIndexBuffer;
#endif
GLuint _patchParamTextureBuffer;
GLuint _fvarDataTextureBuffer;