mirror of
https://github.com/PixarAnimationStudios/OpenSubdiv
synced 2024-11-26 21:40:07 +00:00
remove topology data from FarMesh and refactor uniform / adaptive
code paths using FarPatchTables for all serialized topological data.
This commit is contained in:
parent
b16272d6a5
commit
ad3bacbbbb
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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() );
|
||||
|
@ -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
117
opensubdiv/far/patchTables.h
Executable file → Normal 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
126
opensubdiv/far/patchTablesFactory.h
Executable file → Normal 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];
|
||||
|
@ -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
|
||||
};
|
||||
|
||||
|
@ -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
|
||||
|
@ -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 *
|
||||
|
@ -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) { }
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
};
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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");
|
||||
|
Loading…
Reference in New Issue
Block a user