remove topology data from FarMesh and refactor uniform / adaptive

code paths using FarPatchTables for all serialized topological data.
This commit is contained in:
manuelk 2013-05-15 17:53:40 -07:00
parent b16272d6a5
commit ad3bacbbbb
17 changed files with 383 additions and 476 deletions

View File

@ -86,11 +86,10 @@ MyDrawContext::Create(OpenSubdiv::FarMesh<OpenSubdiv::OsdVertex> const *farMesh,
MyDrawContext *instance = new MyDrawContext();
OpenSubdiv::FarPatchTables const * patchTables = farMesh->GetPatchTables();
if (patchTables) {
return Create(patchTables, requireFVarData);
}
if (instance->allocateUniform(farMesh, requireFVarData))
return instance;
delete instance;
return NULL;
@ -99,11 +98,15 @@ MyDrawContext::Create(OpenSubdiv::FarMesh<OpenSubdiv::OsdVertex> const *farMesh,
MyDrawContext*
MyDrawContext::Create(OpenSubdiv::FarPatchTables const *patchTables, bool requireFVarData)
{
MyDrawContext *instance = new MyDrawContext();
MyDrawContext * result = new MyDrawContext();
if (instance->allocate(patchTables, requireFVarData))
return instance;
delete instance;
if (patchTables) {
if (result->create(patchTables, requireFVarData)) {
return result;
} else {
delete result;
}
}
return NULL;
}

View File

@ -385,7 +385,7 @@ createOsdContext(int level)
g_farmesh->GetNumVertices());
g_drawContext =
OpenSubdiv::OsdGLDrawContext::Create(g_farmesh, g_vertexBuffer);
OpenSubdiv::OsdGLDrawContext::Create(g_farmesh->GetPatchTables(), g_vertexBuffer);
//
// Setup camera positioning based on object bounds. This really has nothing

View File

@ -87,6 +87,12 @@ public:
/// Returns the subdivision method
FarSubdivisionTables<U> const * GetSubdivisionTables() const { return _subdivisionTables; }
/// Returns patch tables
FarPatchTables const * GetPatchTables() const { return _patchTables; }
/// Returns the total number of vertices in the mesh across across all depths
int GetNumVertices() const { return (int)(_vertices.size()); }
/// Returns the list of vertices in the mesh (from subdiv level 0 to N)
std::vector<U> & GetVertices() { return _vertices; }
@ -96,38 +102,17 @@ public:
///
U & GetVertex(int index) { return _vertices[index]; }
/// Returns the list of indices of the vertices of the faces in the mesh
std::vector<int> const & GetFaceVertices(int level) const;
/// Returns the ptex coordinates for each face at a given level. The coordinates
/// are stored as : (int) faceindex / (ushort) u_index / (ushort) v_index
std::vector<FarPtexCoord> const & GetPtexCoordinates(int level) const;
/// Returns the fvar data for each face at a given level. The data
/// is stored as a run of totalFVarWidth floats per-vertex per-face
/// e.g.: for UV data it has the structure of float[p][4][2] where
/// p=primitiveID and totalFVarWidth=2:
/// [ [ uv uv uv uv ] [ uv uv uv uv ] [ ... ] ]
/// prim 0 prim 1
std::vector<float> const & GetFVarData(int level) const;
/// Returns the width of the interleaved face-varying data
int GetTotalFVarWidth() const { return _totalFVarWidth; }
/// Returns patch tables
FarPatchTables const * GetPatchTables() const { return _patchTables; }
/// Returns vertex edit tables
FarVertexEditTables<U> const * GetVertexEdit() const { return _vertexEditTables; }
/// 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; }
bool IsFeatureAdaptive() const { return _patchTables->IsFeatureAdaptive(); }
/// Returns an ordered vector of batches of compute kernels. The kernels
/// describe the sequence of computations required to apply the subdivision
@ -161,15 +146,7 @@ private:
// list of vertices (up to N levels of subdivision)
std::vector<U> _vertices;
// list of vertex indices for each face
std::vector< std::vector<int> > _faceverts;
// ptex coordinates for each face
std::vector< std::vector<FarPtexCoord> > _ptexcoordinates;
// fvar data for each face
std::vector< std::vector<float> > _fvarData;
int _totalFVarWidth; // from hbrMesh
int _totalFVarWidth; // width of the face-varying data
int _numPtexFaces;
};
@ -182,27 +159,6 @@ FarMesh<U>::~FarMesh()
delete _vertexEditTables;
}
template <class U> std::vector<int> const &
FarMesh<U>::GetFaceVertices(int level) const {
if ( (level>=0) and (level<(int)_faceverts.size()) )
return _faceverts[level];
return _faceverts[0];
}
template <class U> std::vector<FarPtexCoord> const &
FarMesh<U>::GetPtexCoordinates(int level) const {
if ( (level>=0) and (level<(int)_faceverts.size()) )
return _ptexcoordinates[level];
return _ptexcoordinates[0];
}
template <class U> std::vector<float> const &
FarMesh<U>::GetFVarData(int level) const {
if ( (level>=0) and (level<(int)_faceverts.size()) )
return _fvarData[level];
return _fvarData[0];
}
} // end namespace OPENSUBDIV_VERSION
using namespace OPENSUBDIV_VERSION;

View File

@ -181,6 +181,7 @@ private:
friend class FarLoopSubdivisionTablesFactory<T,U>;
friend class FarSubdivisionTablesFactory<T,U>;
friend class FarVertexEditTablesFactory<T,U>;
friend class FarPatchTablesFactory<T>;
// Non-copyable, so these are not implemented:
FarMeshFactory( FarMeshFactory const & );
@ -212,23 +213,17 @@ private:
// Calls Hbr to refines the neighbors of v
static void refineVertexNeighbors(HbrVertex<T> * v);
// Densely refine the Hbr mesh
// Uniformly refine the Hbr mesh
static void refine( HbrMesh<T> * mesh, int maxlevel );
// Adaptively refine the Hbr mesh
int refineAdaptive( HbrMesh<T> * mesh, int maxIsolate );
// Generates local sub-face coordinates for Ptex textures
void generatePtexCoordinates( std::vector<FarPtexCoord> & vec, int level );
// Generates local sub-face face-varying UV coordinates
void generateFVarData( std::vector<float> & vec, int level );
// Generates non-adaptive quad topology
// XXXX manuelk we should introduce an equivalent to FarPatchTables for
// non-adaptive stuff
void generateQuadsTopology( std::vector<int> & vec, int level );
typedef std::vector<std::vector< HbrFace<T> *> > FacesList;
// Returns sorted vectors of HbrFace<T> pointers sorted by level
FacesList const & GetFaceList() const { return _facesList; }
private:
HbrMesh<T> * _hbrMesh;
@ -245,8 +240,7 @@ private:
// order of the same vertices in the tables
std::vector<int> _remapTable;
// list of faces sorted by level
std::vector<std::vector< HbrFace<T> *> > _facesList;
FacesList _facesList;
};
template <class T, class U>
@ -303,6 +297,8 @@ FarMeshFactory<T,U>::refine( HbrMesh<T> * mesh, int maxlevel ) {
// faces that have already been refined.
firstface = nfaces;
}
mesh->SetSubdivisionMethod(HbrMesh<T>::k_SubdivisionMethodUniform);
}
// Scan the faces of a mesh and compute the max level of subdivision required
@ -494,12 +490,12 @@ FarMeshFactory<T,U>::refineAdaptive( HbrMesh<T> * mesh, int maxIsolate ) {
// Quad-faces with 2 non-consecutive boundaries need to be flagged
// as "non-patch"
//
// O ******** O ******** O ******** O
// * | | * *** boundary edge
// * | needs | *
// * | flag | * --- regular edge
// * | | *
// O ******** O ******** O ******** O
// o ........ o ........ o ........ o
// . | | . ... b.undary edge
// . | needs | .
// . | flag | . --- regular edge
// . | | .
// o ........ o ........ o ........ o
//
if ( e->IsBoundary() and (not f->_adaptiveFlags.isTagged) and nv==4 ) {
if (e->GetPrev() and (not e->GetPrev()->IsBoundary()) and
@ -583,6 +579,9 @@ FarMeshFactory<T,U>::refineAdaptive( HbrMesh<T> * mesh, int maxIsolate ) {
}
}
}
mesh->SetSubdivisionMethod(HbrMesh<T>::k_SubdivisionMethodFeatureAdaptive);
return maxlevel-1;
}
@ -620,7 +619,6 @@ FarMeshFactory<T,U>::FarMeshFactory( HbrMesh<T> * mesh, int maxlevel, bool adapt
if (not adaptive) {
// Populate the face lists
int fsize=0;
for (int i=0; i<_numFaces; ++i) {
HbrFace<T> * f = mesh->GetFace(i);
@ -657,29 +655,6 @@ FarMeshFactory<T,U>::isLoop(HbrMesh<T> const * mesh) {
return typeid(*(mesh->GetSubdivision()))==typeid(HbrLoopSubdivision<T>);
}
template <class T, class U> void
FarMeshFactory<T,U>::generateQuadsTopology( std::vector<int> & vec, int level ) {
assert( GetHbrMesh() );
int nv=-1;
if ( isCatmark(GetHbrMesh()) or isBilinear(GetHbrMesh()) )
nv=4;
else if ( isLoop(GetHbrMesh()) )
nv=3;
assert(nv>0);
vec.resize( nv * _facesList[level].size(), -1 );
for (int i=0; i<(int)_facesList[level].size(); ++i) {
HbrFace<T> * f = _facesList[level][i];
assert( f and f->GetNumVertices()==nv);
for (int j=0; j<f->GetNumVertices(); ++j)
vec[nv*i+j]=_remapTable[f->GetVertex(j)->GetID()];
}
}
template <class T, class U> void
copyVertex( T & dest, U const & src ) {
}
@ -689,6 +664,19 @@ copyVertex( T & dest, T const & src ) {
dest = src;
}
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;
}
// Computes per-face or per-patch local ptex texture coordinates.
template <class T> FarPtexCoord *
@ -735,42 +723,6 @@ computePtexCoordinate(HbrFace<T> const *f, FarPtexCoord *coord) {
return ++coord;
}
// This currently only supports the Catmark / Bilinear schemes. Loop
template <class T, class U> void
FarMeshFactory<T,U>::generatePtexCoordinates( std::vector<FarPtexCoord> & vec, int level ) {
assert( _hbrMesh );
if (_facesList[0].empty() or _facesList[level][0]->GetPtexIndex() == -1)
return;
vec.resize( _facesList[level].size() );
FarPtexCoord * p = &vec[0];
for (int i=0; i<(int)_facesList[level].size(); ++i) {
HbrFace<T> const * f = _facesList[level][i];
assert(f);
p = computePtexCoordinate(f, p);
}
}
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) {
@ -811,31 +763,6 @@ computeFVarData(HbrFace<T> const *f, const int width, float *coord, bool isAdapt
return coord;
}
// This currently only supports the Catmark / Bilinear schemes. Loop
template <class T, class U> void
FarMeshFactory<T,U>::generateFVarData( std::vector<float> & vec, int level ) {
assert( _hbrMesh );
if (_facesList[0].empty())
return;
// initialize coordinate vector: numFaces*4verts*numFVarDatumPerVert
int totalFVarWidth = _hbrMesh->GetTotalFVarWidth();
vec.resize( _facesList[level].size()*4 * totalFVarWidth, -1.0 );
// pointer will be advanced through vector as we go through faces
float *p = &vec[0];
for (int i=0; i<(int)_facesList[level].size(); ++i) {
HbrFace<T> const * f = _facesList[level][i];
assert(f);
p = computeFVarData(f, totalFVarWidth, p, /*isAdaptive=*/false);
}
}
template <class T, class U> FarMesh<U> *
FarMeshFactory<T,U>::Create( bool requireFVarData ) {
@ -864,7 +791,6 @@ FarMeshFactory<T,U>::Create( bool requireFVarData ) {
for (int i=0; i<GetNumCoarseVertices(); ++i)
copyVertex(result->_vertices[i], GetHbrMesh()->GetVertex(i)->GetData());
}
// Create the element indices tables (patches for adaptive, quads for non-adaptive)
if (isAdaptive()) {
@ -873,35 +799,18 @@ FarMeshFactory<T,U>::Create( bool requireFVarData ) {
// XXXX: currently PatchGregory shader supports up to 29 valence
result->_patchTables = factory.Create(GetMaxLevel()+1, _maxValence, requireFVarData);
assert( result->_patchTables );
if (requireFVarData) {
result->_totalFVarWidth = _hbrMesh->GetTotalFVarWidth();
}
} else {
// XXXX : we should let the client control what to copy, most of this may be irrelevant
result->_faceverts.resize(GetMaxLevel()+1);
for (int l=1; l<=GetMaxLevel(); ++l)
generateQuadsTopology(result->_faceverts[l], l);
// Generate Ptex coordinates
result->_ptexcoordinates.resize(GetMaxLevel()+1);
for (int l=1; l<=GetMaxLevel(); ++l)
generatePtexCoordinates(result->_ptexcoordinates[l], l);
if (requireFVarData) {
// Generate fvar data
result->_totalFVarWidth = _hbrMesh->GetTotalFVarWidth();
result->_fvarData.resize(GetMaxLevel()+1);
for (int l=1; l<=GetMaxLevel(); ++l)
generateFVarData(result->_fvarData[l], l);
}
result->_patchTables = FarPatchTablesFactory<T>::Create(GetHbrMesh(), _facesList, _remapTable, requireFVarData );
}
assert( result->_patchTables );
result->_numPtexFaces = _numPtexFaces;
if (requireFVarData) {
result->_totalFVarWidth = _hbrMesh->GetTotalFVarWidth();
}
// Create VertexEditTables if necessary
if (GetHbrMesh()->HasVertexEdits()) {
result->_vertexEditTables = FarVertexEditTablesFactory<T,U>::Create( this, result, &result->_batches, GetMaxLevel() );

View File

@ -116,9 +116,6 @@ private:
int *voffset, int *poffset, int *qoffset,
std::vector<int> const &vertexOffsets);
// splice quad indices
void spliceQuads(FarMesh<U> *result, FarMeshVector const &meshes);
// splice hierarchical edit tables
FarVertexEditTables<U> * spliceVertexEditTables(FarMesh<U> *farmesh, FarMeshVector const &meshes);
@ -167,11 +164,7 @@ FarMultiMeshFactory<T, U>::Create(std::vector<FarMesh<U> const *> const &meshes)
result->_subdivisionTables = spliceSubdivisionTables(result, meshes);
// splice patch/quad index tables
if ( adaptive ) {
result->_patchTables = splicePatchTables(meshes);
} else {
spliceQuads(result, meshes);
}
result->_patchTables = splicePatchTables(meshes);
// splice vertex edit tables
result->_vertexEditTables = spliceVertexEditTables(result, meshes);
@ -406,23 +399,6 @@ FarMultiMeshFactory<T, U>::spliceSubdivisionTables(FarMesh<U> *farMesh, FarMeshV
return result;
}
template <class T, class U> void
FarMultiMeshFactory<T, U>::spliceQuads(FarMesh<U> *result, FarMeshVector const &meshes) {
result->_faceverts.clear();
result->_faceverts.resize(_maxlevel+1);
// apply vertex offset and concatenate quad indices
for (int l = 0; l <= _maxlevel; ++l) {
int vertexOffset = 0;
for (size_t i = 0; i < meshes.size(); ++i) {
copyWithOffset(std::back_inserter(result->_faceverts[l]),
meshes[i]->_faceverts[l], vertexOffset);
vertexOffset += meshes[i]->GetNumVertices();
}
}
}
template <class T, class U> FarPatchTables::PTable::iterator
FarMultiMeshFactory<T, U>::splicePatch(FarPatchTables::Descriptor desc,
FarMeshVector const &meshes,

117
opensubdiv/far/patchTables.h Executable file → Normal file
View File

@ -148,52 +148,7 @@ struct FarPtexCoord {
bitField.Clear();
}
};
/*
/// \brief Indices for multi-mesh patch arrays
// XXXX manuelk : we should probably derive FarMultiPatchTables for multi-meshes
struct FarPatchCount {
int nonPatch; // reserved for uniform and loop
int regular;
int boundary;
int corner;
int gregory;
int boundaryGregory;
int transitionRegular[5];
int transitionBoundary[5][4];
int transitionCorner[5][4];
/// Constructor.
FarPatchCount() {
nonPatch = regular = boundary = corner = gregory = boundaryGregory = 0;
for (int i = 0; i < 5; ++i) {
transitionRegular[i] = 0;
for (int j = 0; j < 4; ++j) {
transitionBoundary[i][j] = 0;
transitionCorner[i][j] = 0;
}
}
}
/// Adds the indices from another patchTable.
void Append(FarPatchCount const &p) {
nonPatch += p.nonPatch;
regular += p.regular;
boundary += p.boundary;
corner += p.corner;
gregory += p.gregory;
boundaryGregory += p.boundaryGregory;
for (int i = 0; i < 5; ++i) {
transitionRegular[i] += p.transitionRegular[i];
for (int j = 0; j < 4; ++j) {
transitionBoundary[i][j] += p.transitionBoundary[i][j];
transitionCorner[i][j] += p.transitionCorner[i][j];
}
}
}
};
typedef std::vector<FarPatchCount> FarPatchCountVector;
*/
/// \brief Container for patch vertex indices tables
///
/// FarPatchTables contain the lists of vertices for each patch of an adaptive
@ -464,10 +419,28 @@ public:
}
/// Returns all arrays of patches
PatchArrayVector const & GetAllPatchArrays() const {
PatchArrayVector const & GetPatchArrayVector() const {
return _patchArrays;
}
/// Returns a pointer to the vertex indices of uniformly subdivided faces
///
/// @param level the level of subdivision of the faces
///
/// @return a pointer to the first vertex index or NULL if the mesh
/// is not uniformly subdivided or the level cannot be found.
///
unsigned int const * GetFaceVertices(int level) const;
/// Returns the number of faces in a uniformly subdivided mesh at a given level
///
/// @param level the level of subdivision of the faces
///
/// @return the number of faces in the mesh given the subdivision level
/// or -1 if the mesh is not uniform or the level incorrect.
///
int GetNumFaces(int level) const;
/// Returns a vertex valence table used by Gregory patches
VertexValenceTable const & GetVertexValenceTable() const { return _vertexValenceTable; }
@ -478,6 +451,11 @@ public:
PtexCoordinateTable const & GetPtexCoordinatesTable() const { return _ptexTable; }
/// Returns an FVarDataTable for each type of patch
/// The data is stored as a run of totalFVarWidth floats per-vertex per-face
/// e.g.: for UV data it has the structure of float[p][4][2] where
/// p=primitiveID and totalFVarWidth=2:
/// [ [ uv uv uv uv ] [ uv uv uv uv ] [ ... ] ]
/// prim 0 prim 1
FVarDataTable const & GetFVarDataTable() const { return _fvarTable; }
/// Ringsize of Regular Patches in table.
@ -500,6 +478,10 @@ public:
/// Returns max vertex valence
int GetMaxValence() const { return _maxValence; }
/// True if the patches are of feature adaptive types
bool IsFeatureAdaptive() const;
private:
template <class T> friend class FarPatchTablesFactory;
@ -511,9 +493,8 @@ private:
// Private constructor
FarPatchTables( int maxvalence ) : _maxValence(maxvalence) { }
// Vector of descriptors for arrays of patches
PatchArrayVector _patchArrays;
PatchArrayVector _patchArrays; // Vector of descriptors for arrays of patches
PTable _patches; // Indices of the control vertices of the patches
@ -530,7 +511,11 @@ private:
int _maxValence;
};
inline bool
FarPatchTables::IsFeatureAdaptive() const {
return ((not _vertexValenceTable.empty()) and (not _quadOffsetTable.empty()));
}
// Returns the number of control vertices expected for a patch of this type
inline short
FarPatchTables::Descriptor::GetNumControlVertices( FarPatchTables::Type type ) {
@ -591,6 +576,38 @@ FarPatchTables::Descriptor::operator ++ () {
return *this;
}
// Returns a pointer to the vertex indices of uniformly subdivided faces
inline unsigned int const *
FarPatchTables::GetFaceVertices(int level) const {
if (IsFeatureAdaptive())
return NULL;
PatchArrayVector const & parrays = GetPatchArrayVector();
if ( (level-1) < (int)parrays.size() ) {
return &GetPatchTable()[ parrays[level-1].GetVertIndex() ];
}
return NULL;
}
// Returns the number of faces in a uniformly subdivided mesh at a given level
inline int
FarPatchTables::GetNumFaces(int level) const {
if (IsFeatureAdaptive())
return -1;
PatchArrayVector const & parrays = GetPatchArrayVector();
if ( (level-1) < (int)parrays.size() ) {
return parrays[level-1].GetNumPatches();
}
return -1;
}
// Allows ordering of patches by type
inline bool
FarPatchTables::Descriptor::operator < ( Descriptor const other ) const {

126
opensubdiv/far/patchTablesFactory.h Executable file → Normal file
View File

@ -76,7 +76,7 @@ template <class T> class FarPatchTablesFactory {
protected:
template <class X, class Y> friend class FarMeshFactory;
/// Factory constructor
///
/// @param mesh Hbr mesh to generate tables for
@ -87,7 +87,7 @@ protected:
///
FarPatchTablesFactory( HbrMesh<T> const * mesh, int nfaces, std::vector<int> const & remapTable );
/// Returns a FarPatchTables instance
/// Returns a feature-adaptive FarPatchTables instance
///
/// @param maxlevel Highest level of refinement processed
///
@ -99,8 +99,30 @@ protected:
///
FarPatchTables * Create( int maxlevel, int maxvalence, bool requireFVarData=false );
typedef std::vector<std::vector< HbrFace<T> *> > FacesList;
/// Returns a uniform FarPatchTables instance
///
/// @param mesh Hbr mesh to generate tables for
///
/// @param flist vectors of pointers to HbrFace<T> for each level of subdivision
///
/// @param requireFVarData Flag for generating face-varying data
///
/// @param remapTable Vertex remapping table generated by FarMeshFactory
///
/// @return a new instance of FarPatchTables
///
static FarPatchTables * Create( HbrMesh<T> const * mesh,
FacesList const & flist,
std::vector<int> const & remapTable,
bool requireFVarData=false );
private:
typedef FarPatchTables::Descriptor Descriptor;
// Returns true if one of v's neighboring faces has vertices carrying the tag "wasTagged"
static bool vertexHasTaggedNeighbors(HbrVertex<T> * v);
@ -116,6 +138,9 @@ private:
// Populates the Gregory patch quad offsets table
static void getQuadOffsets( HbrFace<T> * f, unsigned int * result );
// Iterates through the faces of an HbrMesh and tags the _adaptiveFlags on faces and vertices
void tagAdaptivePatches( HbrMesh<T> const * mesh, int nfaces );
// Hbr mesh accessor
HbrMesh<T> const * getMesh() const { return _mesh; }
@ -125,6 +150,8 @@ private:
// The number of patch arrays in the mesh
int getNumPatchArrays() const;
static void allocateTables( FarPatchTables * tables, int fvarwidth );
// A convenience container for the different types of feature adaptive patches
template<class TYPE> struct PatchTypes {
TYPE R, // regular patch
@ -213,6 +240,79 @@ FarPatchTablesFactory<T>::computeCornerPatchRotation( HbrFace<T> * f ) {
return rot;
}
template <class T> void
FarPatchTablesFactory<T>::allocateTables( FarPatchTables * tables, int fvarwidth ) {
int nverts = tables->GetNumControlVertices(),
npatches = tables->GetNumPatches();
if (nverts==0 or npatches==0)
return;
// Reserve memory for the tables
tables->_patches.resize( nverts );
// Allocate memory for the ptex coord tables
tables->_ptexTable.resize( npatches );
if (fvarwidth>0) {
tables->_fvarTable.resize( npatches * 4 * fvarwidth );
}
}
template <class T> FarPatchTables *
FarPatchTablesFactory<T>::Create( HbrMesh<T> const * mesh, FacesList const & flist, std::vector<int> const & remapTable, bool requireFVarData ) {
if (flist.size()<2)
return 0;
FarPatchTables * result = new FarPatchTables(0);
// Populate the patch array descriptors
FarPatchTables::PatchArrayVector & parray = result->_patchArrays;
parray.reserve( (int)flist.size() );
bool isLoop = FarMeshFactory<T,T>::isLoop(mesh);
int nv = isLoop ? 3 : 4;
Descriptor desc( isLoop ? FarPatchTables::TRIANGLES : FarPatchTables::QUADS, FarPatchTables::NON_TRANSITION, 0 );
for (int i=1, poffset=0, voffset=0; i<(int)flist.size(); ++i) {
int nfaces = (int)flist[i].size();
parray.push_back( FarPatchTables::PatchArray(desc, voffset, poffset, nfaces, 0 ) );
voffset += nfaces * nv;
poffset += nfaces;
}
int fvarwidth = requireFVarData ? mesh->GetTotalFVarWidth() : 0;
allocateTables( result, fvarwidth );
unsigned int * iptr = &result->_patches[0];
FarPtexCoord * pptr = &result->_ptexTable[0];
float * fptr = requireFVarData ? &result->_fvarTable[0] : 0;
for (int level=1; level<(int)flist.size(); ++level) {
for (int i=0; i<(int)flist[level].size(); ++i) {
HbrFace<T> * f = flist[level][i];
assert( f and f->GetNumVertices()==nv);
for (int j=0; j<f->GetNumVertices(); ++j) {
*iptr++ = remapTable[f->GetVertex(j)->GetID()];
}
pptr = computePtexCoordinate(f, pptr);
if (requireFVarData)
fptr = computeFVarData(f, fvarwidth, fptr, /*isAdaptive=*/false);
}
}
return result;
}
template <class T>
FarPatchTablesFactory<T>::FarPatchTablesFactory( HbrMesh<T> const * mesh, int nfaces, std::vector<int> const & remapTable ) :
@ -544,9 +644,6 @@ FarPatchTablesFactory<T>::Create( int maxlevel, int maxvalence, bool requireFVar
assert(getMesh() and getNumFaces()>0);
typedef FarPatchTables::Descriptor Descriptor;
FarPatchTables * result = new FarPatchTables(maxvalence);
// Populate the patch array descriptors
@ -560,19 +657,9 @@ FarPatchTablesFactory<T>::Create( int maxlevel, int maxvalence, bool requireFVar
pushPatchArray( *it, parray, _patchCtr[it->GetPattern()], &voffset, &poffset, &qoffset );
}
int nverts = result->GetNumControlVertices(),
npatches = result->GetNumPatches(),
fvarwidth = getMesh()->GetTotalFVarWidth();
// Reserve memory for the tables
result->_patches.resize( nverts );
// Allocate memory for the ptex coord tables
result->_ptexTable.resize( npatches );
if (requireFVarData) {
result->_fvarTable.resize( npatches * 4 * fvarwidth );
}
int fvarwidth = requireFVarData ? getMesh()->GetTotalFVarWidth() : 0;
allocateTables( result, fvarwidth );
FarPatchTables::QuadOffsetTable quad_G_C0; // Quad-offsets tables (for Gregory patches)
quad_G_C0.resize(_patchCtr[0].G[0]*4);
@ -583,6 +670,9 @@ FarPatchTablesFactory<T>::Create( int maxlevel, int maxvalence, bool requireFVar
FarPatchTables::QuadOffsetTable::value_type *quad_G_C0_P = quad_G_C0.empty() ? 0 : &quad_G_C0[0];
FarPatchTables::QuadOffsetTable::value_type *quad_G_C1_P = quad_G_C1.empty() ? 0 : &quad_G_C1[0];
// Setup convenience pointers at the beginning of each patch array for each
// table (patches, ptex, fvar)
CVPointers iptrs[6];
PtexPointers pptrs[6];
FVarPointers fptrs[6];

View File

@ -99,9 +99,6 @@ template <class U> class FarSubdivisionTables {
public:
enum TableType {
F_ITa, // face-vertices adjacency indexing table
F_IT, // face-vertices indexing table
E_IT, // edge-vertices adjacency indexing table
E_W, // edge-vertices weights
@ -109,6 +106,9 @@ public:
V_IT, // vertex-vertices indexing table
V_W, // vertex-vertices weights
F_ITa, // face-vertices adjacency indexing table
F_IT, // face-vertices indexing table
TABLE_TYPES_COUNT // number of different types of tables
};

View File

@ -460,6 +460,19 @@ private:
// Faces which are transient
std::vector<HbrFace<T>*> m_transientFaces;
#ifdef HBR_ADAPTIVE
public:
enum SubdivisionMethod {
k_SubdivisionMethodNone,
k_SubdivisionMethodUniform,
k_SubdivisionMethodFeatureAdaptive
};
void SetSubdivisionMethod(SubdivisionMethod method) { _subdivisionMethod=method; }
SubdivisionMethod GetSubdivisionMethod() const { return _subdivisionMethod; }
private:
SubdivisionMethod _subdivisionMethod;
#endif
};
} // end namespace OPENSUBDIV_VERSION

View File

@ -181,7 +181,7 @@ OsdCpuComputeContext::~OsdCpuComputeContext() {
for (size_t i = 0; i < _editTables.size(); ++i) {
delete _editTables[i];
}
if (_vdesc) delete _vdesc;
delete _vdesc;
}
const OsdCpuTable *

View File

@ -167,7 +167,7 @@ public:
/// @param desc Patch descriptor defines the type, pattern, rotation of
/// the patches in the array
///
/// @param range The
/// @param range The range of vertex indices
///
PatchArray(PatchDescriptor desc, FarPatchTables::PatchArray::ArrayRange const & range) :
_desc(desc), _range(range) { }

View File

@ -89,34 +89,6 @@ OsdGLDrawContext::~OsdGLDrawContext()
glDeleteTextures(1, &fvarDataTextureBuffer);
}
OsdGLDrawContext *
OsdGLDrawContext::Create(FarMesh<OsdVertex> const *farMesh, bool requireFVarData)
{
FarPatchTables const * patchTables = farMesh->GetPatchTables();
if (patchTables)
return Create(patchTables, requireFVarData);
// XXX: allocateUniform will be retired once uniform patches are
// integrated into patcharray.
OsdGLDrawContext * instance = new OsdGLDrawContext();
if (instance->allocateUniform(farMesh, requireFVarData))
return instance;
delete instance;
return NULL;
}
OsdGLDrawContext *
OsdGLDrawContext::Create(FarPatchTables const *patchTables, bool requireFVarData)
{
OsdGLDrawContext * instance = new OsdGLDrawContext();
if (instance->allocate(patchTables, requireFVarData))
return instance;
delete instance;
return NULL;
}
bool
OsdGLDrawContext::SupportsAdaptiveTessellation()
{
@ -130,109 +102,8 @@ OsdGLDrawContext::SupportsAdaptiveTessellation()
return false;
}
bool
OsdGLDrawContext::allocateUniform(FarMesh<OsdVertex> const *farMesh,
bool requireFVarData)
{
_isAdaptive = false;
// XXX: farmesh should have FarDensePatchTable for dense mesh indices.
// instead of GetFaceVertices().
const FarSubdivisionTables<OsdVertex> *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);
#if defined(GL_ES_VERSION_2_0)
// 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
/*
OsdPatchArray array;
array.desc.type = kNonPatch;
array.desc.loop = dynamic_cast<const FarLoopSubdivisionTables<OsdVertex>*>(tables) != NULL;
array.firstIndex = 0;
array.numIndices = numIndices;
patchArrays.push_back(array);
*/
// Allocate ptex coordinate buffer
#if defined(GL_ARB_texture_buffer_object) || defined(GL_VERSION_3_1)
GLuint ptexCoordinateBuffer = 0;
glGenTextures(1, &ptexCoordinateTextureBuffer);
glGenBuffers(1, &ptexCoordinateBuffer);
glBindBuffer(GL_TEXTURE_BUFFER, ptexCoordinateBuffer);
const std::vector<FarPtexCoord> &ptexCoordinates =
farMesh->GetPtexCoordinates(level-1);
int size = (int)ptexCoordinates.size() * sizeof(FarPtexCoord);
glBufferData(GL_TEXTURE_BUFFER, size, &(ptexCoordinates[0]), GL_STATIC_DRAW);
glBindTexture(GL_TEXTURE_BUFFER, ptexCoordinateTextureBuffer);
glTexBuffer(GL_TEXTURE_BUFFER, GL_RG32I, ptexCoordinateBuffer);
glBindTexture(GL_TEXTURE_BUFFER, 0);
glDeleteBuffers(1, &ptexCoordinateBuffer);
#endif
// Allocate fvar data buffer if requested (for non-adaptive)
if (requireFVarData) {
#if defined(GL_ARB_texture_buffer_object) || defined(GL_VERSION_3_1)
GLuint fvarDataBuffer = 0;
glGenTextures(1, &fvarDataTextureBuffer);
glGenBuffers(1, &fvarDataBuffer);
glBindBuffer(GL_TEXTURE_BUFFER, fvarDataBuffer);
const std::vector<float> &fvarData = farMesh->GetFVarData(level-1);
int size = (int)fvarData.size() * sizeof(float);
glBufferData(GL_TEXTURE_BUFFER, size, &(fvarData[0]), GL_STATIC_DRAW);
glBindTexture(GL_TEXTURE_BUFFER, fvarDataTextureBuffer);
glTexBuffer(GL_TEXTURE_BUFFER, GL_R32F, fvarDataBuffer);
glDeleteBuffers(1, &fvarDataBuffer);
glBindTexture(GL_TEXTURE_BUFFER, 0);
#endif
}
return true;
}
template <typename T>
GLuint createTextureBuffer(T const &data, GLint format)
GLuint createTextureBuffer(T const &data, GLint format, int offset=0)
{
GLuint buffer = 0, texture = 0;
@ -240,8 +111,8 @@ GLuint createTextureBuffer(T const &data, GLint format)
glGenTextures(1, &texture);
glGenBuffers(1, &buffer);
glBindBuffer(GL_ARRAY_BUFFER, buffer);
glBufferData(GL_ARRAY_BUFFER, data.size() * sizeof(typename T::value_type),
&data[0], GL_STATIC_DRAW);
glBufferData(GL_ARRAY_BUFFER, (data.size()-offset) * sizeof(typename T::value_type),
&data[offset], GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindTexture(GL_TEXTURE_BUFFER, texture);
@ -252,55 +123,123 @@ GLuint createTextureBuffer(T const &data, GLint format)
return texture;
}
OsdGLDrawContext *
OsdGLDrawContext::Create(FarPatchTables const * patchTables, bool requireFVarData) {
if (patchTables) {
OsdGLDrawContext * result = new OsdGLDrawContext();
if (result->create(patchTables, requireFVarData)) {
return result;
} else {
delete result;
}
}
return NULL;
}
bool
OsdGLDrawContext::allocate(FarPatchTables const *patchTables, bool requireFVarData)
{
_isAdaptive = true;
ConvertPatchArrays(patchTables->GetAllPatchArrays(), patchArrays, patchTables->GetMaxValence(), 0);
OsdGLDrawContext::create(FarPatchTables const * patchTables, bool requireFVarData) {
assert(patchTables);
_isAdaptive = patchTables->IsFeatureAdaptive();
// Process PTable
FarPatchTables::PTable const & ptables = patchTables->GetPatchTable();
// Allocate and fill index buffer.
glGenBuffers(1, &patchIndexBuffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, patchIndexBuffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER,
ptables.size() * sizeof(unsigned int), &ptables[0], GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
int patchOffset=0;
// Process PatchArrays
if (IsAdaptive()) {
OsdDrawContext::ConvertPatchArrays(patchTables->GetPatchArrayVector(),
patchArrays, patchTables->GetMaxValence(), 0);
// allocate and initialize additional buffer data
FarPatchTables::VertexValenceTable const &
valenceTable = patchTables->GetVertexValenceTable();
// create vertex valence buffer and vertex texture
if (not valenceTable.empty()) {
vertexValenceTextureBuffer = createTextureBuffer(valenceTable, GL_R32I);
// also create vertex texture buffer (will be updated in UpdateVertexTexture())
glGenTextures(1, &vertexTextureBuffer);
}
// create quad offset table buffer
FarPatchTables::QuadOffsetTable const &
quadOffsetTable = patchTables->GetQuadOffsetTable();
if (not quadOffsetTable.empty())
quadOffsetTextureBuffer = createTextureBuffer(quadOffsetTable, GL_R32I);
} else {
// Create a single OsdPatchArray from the FarPatchTables::PatchArray
// corresponding to the highest level of subdivision
// XXXX manuelk : client code will want control over this
FarPatchTables::PatchArray const & fpa =
*(patchTables->GetPatchArrayVector().rbegin());
OsdDrawContext::PatchDescriptor desc(
fpa.GetDescriptor(), patchTables->GetMaxValence(), 0, 0);
patchArrays.push_back(
OsdDrawContext::PatchArray( desc, fpa.GetArrayRange() ) );
patchOffset = fpa.GetPatchIndex();
#if defined(GL_ES_VERSION_2_0)
// 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
}
// create ptex coordinate buffer
FarPatchTables::PtexCoordinateTable const &
ptexCoordTables = patchTables->GetPtexCoordinatesTable();
// create ptex coordinate buffer
if (not ptexCoordTables.empty())
ptexCoordinateTextureBuffer = createTextureBuffer(ptexCoordTables, GL_RG32I);
ptexCoordinateTextureBuffer = createTextureBuffer(ptexCoordTables, GL_RG32I, patchOffset);
// create fvar data buffer if requested
FarPatchTables::FVarDataTable const &
fvarTables = patchTables->GetFVarDataTable();
// create fvar data buffer if requested
if (requireFVarData and not fvarTables.empty())
fvarDataTextureBuffer = createTextureBuffer(fvarTables, GL_R32F);
// allocate and initialize additional buffer data
FarPatchTables::VertexValenceTable const &
valenceTable = patchTables->GetVertexValenceTable();
// create vertex valence buffer and vertex texture
if (not valenceTable.empty()) {
vertexValenceTextureBuffer = createTextureBuffer(valenceTable, GL_R32I);
// also create vertex texture buffer (will be updated in UpdateVertexTexture())
glGenTextures(1, &vertexTextureBuffer);
}
// create quad offset table buffer
FarPatchTables::QuadOffsetTable const &
quadOffsetTable = patchTables->GetQuadOffsetTable();
if (not quadOffsetTable.empty())
quadOffsetTextureBuffer = createTextureBuffer(quadOffsetTable, GL_R32I);
fvarDataTextureBuffer = createTextureBuffer(fvarTables, GL_R32F, patchOffset);
glBindBuffer(GL_TEXTURE_BUFFER, 0);

View File

@ -85,22 +85,27 @@ public:
virtual ~OsdGLDrawContext();
/// Create a OsdGLDraContext from FarMesh
/// \brienf Create an OsdGLDraContext from FarPatchTables
///
static OsdGLDrawContext *Create(FarMesh<OsdVertex> const *farMesh,
bool requireFVarData=false);
/// Create a OsdGLDraContext from FarPatchTables
/// @param patchTables a valid set of FarPatchTables
///
static OsdGLDrawContext *Create(FarPatchTables const *patchTables,
bool requireFVarData=false);
/// @param requireFVarData set to true to enable face-varying data to be
/// carried over from the Far data structures.
///
static OsdGLDrawContext * Create(FarPatchTables const * patchTables, bool requireFVarData);
/// Set vbo as a vertex texture (for gregory patch drawing)
///
/// @param vbo the vertex buffer object to update
///
template<class VERTEX_BUFFER>
void UpdateVertexTexture(VERTEX_BUFFER *vbo) {
updateVertexTexture(vbo->BindVBO(), vbo->GetNumElements());
}
/// true if the GL version detected supports shader tessellation
static bool SupportsAdaptiveTessellation();
GLuint patchIndexBuffer;
#if defined(GL_ES_VERSION_2_0)
@ -114,19 +119,11 @@ public:
GLuint vertexValenceTextureBuffer;
GLuint quadOffsetTextureBuffer;
/// true if the GL version detected supports shader tessellation
static bool SupportsAdaptiveTessellation();
protected:
OsdGLDrawContext();
// allocate buffers from patchTables
bool allocate(FarPatchTables const *patchTables,
bool requireFVarData);
// XXX: will retire soon
bool allocateUniform(FarMesh<OsdVertex> const *farMesh,
bool requireFVarData);
bool create(FarPatchTables const *patchTables, bool requireFVarData);
void updateVertexTexture(GLuint vbo, int numElements);
};

View File

@ -104,7 +104,7 @@ public:
int numVertices = _farMesh->GetNumVertices();
_vertexBuffer = VertexBuffer::Create(numElements, numVertices);
_computeContext = ComputeContext::Create(_farMesh);
_drawContext = DrawContext::Create(_farMesh, bits.test(MeshFVarData));
_drawContext = DrawContext::Create(_farMesh->GetPatchTables(), bits.test(MeshFVarData));
_drawContext->UpdateVertexTexture(_vertexBuffer);
}
@ -174,7 +174,7 @@ public:
int numVertices = _farMesh->GetNumVertices();
_vertexBuffer = VertexBuffer::Create(numElements, numVertices, _clContext);
_computeContext = ComputeContext::Create(_farMesh, _clContext);
_drawContext = DrawContext::Create(_farMesh, bits.test(MeshFVarData));
_drawContext = DrawContext::Create(_farMesh->GetPatchTables(), bits.test(MeshFVarData));
_drawContext->UpdateVertexTexture(_vertexBuffer);
}

View File

@ -255,7 +255,7 @@ OsdUtilMeshBatchBase<DRAW_CONTEXT>::createPatchArrays(std::vector<FarPatchTables
// XXX: temporary for uniform
int maxLevel = meshVector[i]->GetSubdivisionTables()->GetMaxLevel();
int numQuads = adaptive ? 0 : (int)meshVector[i]->GetFaceVertices(maxLevel-1).size()/4;
int numQuads = adaptive ? 0 : (int)meshVector[i]->GetPatchTables()->GetNumFaces(maxLevel-1);
_quadCounts.push_back(numQuads);
vertexOffset += numVertices;

View File

@ -156,10 +156,10 @@ shim::Subdivider::getRefinedQuads(Buffer* refinedQuads)
}
int level = tables->GetMaxLevel();
const std::vector<int> &indices = self->farMesh->GetFaceVertices(level-1);
int numInts = (int) indices.size();
unsigned int const * indices = self->farMesh->GetPatchTables()->GetFaceVertices(level-1);
int numInts = self->farMesh->GetPatchTables()->GetNumFaces(level-1)*4;
unsigned char* srcBegin = (unsigned char*) &indices[0];
unsigned char* srcEnd = srcBegin + numInts * 4;
unsigned char const * srcBegin = reinterpret_cast<unsigned char const *>(indices);
unsigned char const * srcEnd = srcBegin + numInts * 4;
refinedQuads->assign(srcBegin, srcEnd);
}

View File

@ -157,7 +157,8 @@ typedef OpenSubdiv::HbrVertexOperator<xyzVV> xyzVertexOperator;
typedef OpenSubdiv::FarMesh<xyzVV> fMesh;
typedef OpenSubdiv::FarMeshFactory<xyzVV> fMeshFactory;
typedef OpenSubdiv::FarSubdivisionTables<xyzVV> fMeshSubdivision;
typedef OpenSubdiv::FarSubdivisionTables<xyzVV> fSubdivision;
typedef OpenSubdiv::FarPatchTables fPatches;
static bool g_debugmode = false;
static bool g_dumphbr = false;
@ -247,12 +248,15 @@ static void dumpVerts( fMesh * mesh, int level ) {
//------------------------------------------------------------------------------
static void dumpQuadFaces( fMesh * mesh, int level ) {
std::vector<int> const & fverts = mesh->GetFaceVertices(level);
unsigned int const * fverts = mesh->GetPatchTables()->GetFaceVertices(level);
int nverts = mesh->GetPatchTables()->GetNumFaces(level) * 4;
int ofs = mesh->GetSubdivisionTables()->GetFirstVertexOffset(level);
printf("\t'faces':[\t");
for (size_t i=0; i<(fverts.size()); i+=4) {
for (int i=0; i<nverts; i+=4) {
printf("[%6d, %6d, %6d, %6d], ", fverts[i ]-ofs,
fverts[i+1]-ofs,
fverts[i+2]-ofs,
@ -265,12 +269,15 @@ static void dumpQuadFaces( fMesh * mesh, int level ) {
//------------------------------------------------------------------------------
static void dumpTriFaces( fMesh * mesh, int level ) {
std::vector<int> const & fverts = mesh->GetFaceVertices(level);
unsigned int const * fverts = mesh->GetPatchTables()->GetFaceVertices(level);
int nverts = mesh->GetPatchTables()->GetNumFaces(level) * 3;
int ofs = mesh->GetSubdivisionTables()->GetFirstVertexOffset(level);
printf("\t'faces':[\t");
for (size_t i=0; i<(fverts.size()); i+=3) {
for (int i=0; i<nverts; i+=3) {
printf("[%6d, %6d, %6d], ", fverts[i]-ofs, fverts[i+1]-ofs, fverts[i+2]-ofs );
if (i!=0 and (i+4)%32==0)
printf("\n\t\t\t");