mirror of
https://github.com/PixarAnimationStudios/OpenSubdiv
synced 2024-11-25 04:50:06 +00:00
Merge pull request #284 from nathan-at-digitalfish/add_far_triangulate
Generate triangle patches for a uniformly subdivided mesh
This commit is contained in:
commit
808aabfbc5
@ -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 );
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user