diff --git a/examples/common/patchColors.cpp b/examples/common/patchColors.cpp index d6a78206..056443e3 100644 --- a/examples/common/patchColors.cpp +++ b/examples/common/patchColors.cpp @@ -56,26 +56,25 @@ static float _colors[5][7][4] = {{{1.0f, 1.0f, 1.0f, 1.0f}, // regular {0.25f, 0.25f, 0.25f, 1.0f}, // corner pattern 3 {0.25f, 0.25f, 0.25f, 1.0f}}}; // corner pattern 4 -typedef OpenSubdiv::Far::PatchTables FarPatchTables; - +typedef OpenSubdiv::Far::PatchDescriptor Descriptor; float const * -getAdaptivePatchColor(FarPatchTables::Descriptor const & desc) { +getAdaptivePatchColor(Descriptor const & desc) { - if (desc.GetPattern()==FarPatchTables::NON_TRANSITION) { - return _colors[0][(int)(desc.GetType()-FarPatchTables::REGULAR)]; + if (desc.GetPattern()==Descriptor::NON_TRANSITION) { + return _colors[0][(int)(desc.GetType()-Descriptor::REGULAR)]; } else { - return _colors[(int)(desc.GetType()-FarPatchTables::REGULAR)+1][(int)desc.GetPattern()-1]; + return _colors[(int)(desc.GetType()-Descriptor::REGULAR)+1][(int)desc.GetPattern()-1]; } } float const * getAdaptivePatchColor(OpenSubdiv::Osd::DrawContext::PatchDescriptor const & desc) { - if (desc.GetPattern()==FarPatchTables::NON_TRANSITION) { - return _colors[0][(int)(desc.GetType()-FarPatchTables::REGULAR)]; + if (desc.GetPattern()==Descriptor::NON_TRANSITION) { + return _colors[0][(int)(desc.GetType()-Descriptor::REGULAR)]; } else { - return _colors[(int)(desc.GetType()-FarPatchTables::REGULAR)+1][(int)desc.GetPattern()-1]; + return _colors[(int)(desc.GetType()-Descriptor::REGULAR)+1][(int)desc.GetPattern()-1]; } } diff --git a/examples/common/patchColors.h b/examples/common/patchColors.h index b4fc6986..bad5d740 100644 --- a/examples/common/patchColors.h +++ b/examples/common/patchColors.h @@ -32,7 +32,7 @@ // returns a unique color for each type of feature-adaptive patches float const * getAdaptivePatchColor(OpenSubdiv::Osd::DrawContext::PatchDescriptor const & desc); -float const * getAdaptivePatchColor(OpenSubdiv::Far::PatchTables::Descriptor const & desc); +float const * getAdaptivePatchColor(OpenSubdiv::Far::PatchDescriptor const & desc); #endif /* COMMON_PATCH_COLORS_H */ diff --git a/examples/glEvalLimit/glEvalLimit.cpp b/examples/glEvalLimit/glEvalLimit.cpp index e8f2caa9..d43e79d4 100644 --- a/examples/glEvalLimit/glEvalLimit.cpp +++ b/examples/glEvalLimit/glEvalLimit.cpp @@ -295,7 +295,7 @@ updateGeom() { color[2] = coord.t; } break; case kRANDOM : // no update needed - case kVARYING : + case kVARYING : case kFACEVARYING : break; default : break; @@ -724,8 +724,8 @@ display() { g_hud.DrawString(10, -40, "CPU Draw : %.3f ms", drawCpuTime); g_hud.DrawString(10, -20, "FPS : %3.1f", fps); - if (g_drawMode==kFACEVARYING and g_evalCtx->GetFVarData().empty()) { - static char msg[21] = "No Face-Varying Data"; + if (g_drawMode==kFACEVARYING) { + static char msg[] = "Face-varying interpolation not implemented yet"; g_hud.DrawString(g_width/2-20/2*8, g_height/2, msg); } @@ -831,10 +831,10 @@ keyboard(GLFWwindow *, int key, int /* scancode */, int event, int /* mods */) { case '-': setSamples(false); break; - case '[': if (g_particles) { + case '[': if (g_particles) { g_particles->SetSpeed(g_particles->GetSpeed()-0.1f); } break; - case ']': if (g_particles) { + case ']': if (g_particles) { g_particles->SetSpeed(g_particles->GetSpeed()+0.1f); } break; diff --git a/examples/glFVarViewer/glFVarViewer.cpp b/examples/glFVarViewer/glFVarViewer.cpp index 83a65a74..0e04e80e 100644 --- a/examples/glFVarViewer/glFVarViewer.cpp +++ b/examples/glFVarViewer/glFVarViewer.cpp @@ -564,8 +564,10 @@ EffectDrawRegistry::_CreateDrawSourceConfig(DescType const & desc) { const char *glslVersion = "#version 330\n"; #endif - if (desc.first.GetType() == OpenSubdiv::Far::PatchTables::QUADS or - desc.first.GetType() == OpenSubdiv::Far::PatchTables::TRIANGLES) { + typedef OpenSubdiv::Far::PatchDescriptor Descriptor; + + if (desc.first.GetType() == Descriptor::QUADS or + desc.first.GetType() == Descriptor::TRIANGLES) { sconfig->vertexShader.source = shaderSource; sconfig->vertexShader.version = glslVersion; sconfig->vertexShader.AddDefine("VERTEX_SHADER"); @@ -584,12 +586,12 @@ EffectDrawRegistry::_CreateDrawSourceConfig(DescType const & desc) { sconfig->commonShader.AddDefine("OSD_FVAR_WIDTH", "2"); - if (desc.first.GetType() == OpenSubdiv::Far::PatchTables::QUADS) { + if (desc.first.GetType() == Descriptor::QUADS) { // uniform catmark, bilinear sconfig->geometryShader.AddDefine("PRIM_QUAD"); sconfig->fragmentShader.AddDefine("PRIM_QUAD"); sconfig->commonShader.AddDefine("UNIFORM_SUBDIVISION"); - } else if (desc.first.GetType() == OpenSubdiv::Far::PatchTables::TRIANGLES) { + } else if (desc.first.GetType() == Descriptor::TRIANGLES) { // uniform loop sconfig->geometryShader.AddDefine("PRIM_TRI"); sconfig->fragmentShader.AddDefine("PRIM_TRI"); @@ -820,15 +822,15 @@ display() { OpenSubdiv::Osd::DrawContext::PatchArray const & patch = patches[i]; OpenSubdiv::Osd::DrawContext::PatchDescriptor desc = patch.GetDescriptor(); - OpenSubdiv::Far::PatchTables::Type patchType = desc.GetType(); + OpenSubdiv::Far::PatchDescriptor::Type patchType = desc.GetType(); GLenum primType; switch (patchType) { - case OpenSubdiv::Far::PatchTables::QUADS: + case OpenSubdiv::Far::PatchDescriptor::QUADS: primType = GL_LINES_ADJACENCY; break; - case OpenSubdiv::Far::PatchTables::TRIANGLES: + case OpenSubdiv::Far::PatchDescriptor::TRIANGLES: primType = GL_TRIANGLES; break; default: @@ -887,15 +889,15 @@ display() { OpenSubdiv::Osd::DrawContext::PatchArray const & patch = patches[i]; OpenSubdiv::Osd::DrawContext::PatchDescriptor desc = patch.GetDescriptor(); - OpenSubdiv::Far::PatchTables::Type patchType = desc.GetType(); + OpenSubdiv::Far::PatchDescriptor::Type patchType = desc.GetType(); GLenum primType; switch (patchType) { - case OpenSubdiv::Far::PatchTables::QUADS: + case OpenSubdiv::Far::PatchDescriptor::QUADS: primType = GL_LINES_ADJACENCY; break; - case OpenSubdiv::Far::PatchTables::TRIANGLES: + case OpenSubdiv::Far::PatchDescriptor::TRIANGLES: primType = GL_TRIANGLES; break; default: diff --git a/examples/glPtexViewer/glPtexViewer.cpp b/examples/glPtexViewer/glPtexViewer.cpp index 7eadd4fc..31ba3ce6 100644 --- a/examples/glPtexViewer/glPtexViewer.cpp +++ b/examples/glPtexViewer/glPtexViewer.cpp @@ -728,14 +728,14 @@ EffectDrawRegistry::_CreateDrawSourceConfig(DescType const & desc) { #endif int nverts = 4; - if (desc.first.GetType() == OpenSubdiv::Far::PatchTables::QUADS) { + if (desc.first.GetType() == OpenSubdiv::Far::PatchDescriptor::QUADS) { sconfig->vertexShader.source = g_shaderSource; sconfig->vertexShader.version = glslVersion; sconfig->vertexShader.AddDefine("VERTEX_SHADER"); if (effect.displacement) { sconfig->geometryShader.AddDefine("FLAT_NORMALS"); } - } else if (desc.first.GetType() == OpenSubdiv::Far::PatchTables::LINES) { + } else if (desc.first.GetType() == OpenSubdiv::Far::PatchDescriptor::LINES) { nverts = 2; sconfig->vertexShader.source = g_shaderSource; sconfig->vertexShader.version = glslVersion; @@ -1578,14 +1578,14 @@ drawModel() { OpenSubdiv::Osd::DrawContext::PatchArray const & patch = patches[i]; OpenSubdiv::Osd::DrawContext::PatchDescriptor desc = patch.GetDescriptor(); - OpenSubdiv::Far::PatchTables::Type patchType = desc.GetType(); + OpenSubdiv::Far::PatchDescriptor::Type patchType = desc.GetType(); GLenum primType; switch (patchType) { - case OpenSubdiv::Far::PatchTables::QUADS: + case OpenSubdiv::Far::PatchDescriptor::QUADS: primType = GL_LINES_ADJACENCY; break; - case OpenSubdiv::Far::PatchTables::TRIANGLES: + case OpenSubdiv::Far::PatchDescriptor::TRIANGLES: primType = GL_TRIANGLES; break; default: @@ -1749,10 +1749,11 @@ drawCageEdges() { Effect effect; effect.value = 0; + + typedef OpenSubdiv::Far::PatchDescriptor FDesc; + OpenSubdiv::Osd::DrawContext::PatchDescriptor desc( - OpenSubdiv::Far::PatchTables::Descriptor(OpenSubdiv::Far::PatchTables::LINES, - OpenSubdiv::Far::PatchTables::NON_TRANSITION, 0), - 0, 0, 0); + FDesc(FDesc::LINES, FDesc::NON_TRANSITION, 0), 0, 0, 0); EffectDrawRegistry::ConfigType *config = getInstance(effect, desc); glUseProgram(config->program); diff --git a/examples/glPtexViewer/imageshader.glsl b/examples/glPtexViewer/imageshader.glsl index 0a6b9bcf..60bdae41 100644 --- a/examples/glPtexViewer/imageshader.glsl +++ b/examples/glPtexViewer/imageshader.glsl @@ -81,7 +81,11 @@ void main() uniform float alpha = 1.0; void main() { - outColor = alpha * texture(colorMap, outUV); + //background color as a vertical grey ramp + vec4 fgColor = texture(colorMap, outUV); + vec4 bgColor = vec4(mix(0.1, 0.5, sin(outUV.y*3.14159))); + + outColor = mix(bgColor, fgColor, fgColor.a); } #endif diff --git a/examples/glShareTopology/glShareTopology.cpp b/examples/glShareTopology/glShareTopology.cpp index 717a3ce3..4843aca2 100644 --- a/examples/glShareTopology/glShareTopology.cpp +++ b/examples/glShareTopology/glShareTopology.cpp @@ -764,8 +764,8 @@ EffectDrawRegistry::_CreateDrawSourceConfig(DescType const & desc) { const char *glslVersion = "#version 330\n"; #endif - if (desc.first.GetType() == Far::PatchTables::QUADS or - desc.first.GetType() == Far::PatchTables::TRIANGLES) { + if (desc.first.GetType() == Far::PatchDescriptor::QUADS or + desc.first.GetType() == Far::PatchDescriptor::TRIANGLES) { sconfig->vertexShader.source = shaderSource; sconfig->vertexShader.version = glslVersion; sconfig->vertexShader.AddDefine("VERTEX_SHADER"); @@ -781,12 +781,12 @@ EffectDrawRegistry::_CreateDrawSourceConfig(DescType const & desc) { sconfig->fragmentShader.version = glslVersion; sconfig->fragmentShader.AddDefine("FRAGMENT_SHADER"); - if (desc.first.GetType() == Far::PatchTables::QUADS) { + if (desc.first.GetType() == Far::PatchDescriptor::QUADS) { // uniform catmark, bilinear sconfig->geometryShader.AddDefine("PRIM_QUAD"); sconfig->fragmentShader.AddDefine("PRIM_QUAD"); sconfig->commonShader.AddDefine("UNIFORM_SUBDIVISION"); - } else if (desc.first.GetType() == Far::PatchTables::TRIANGLES) { + } else if (desc.first.GetType() == Far::PatchDescriptor::TRIANGLES) { // uniform loop sconfig->geometryShader.AddDefine("PRIM_TRI"); sconfig->fragmentShader.AddDefine("PRIM_TRI"); @@ -1020,15 +1020,15 @@ drawPatches(Osd::DrawContext::PatchArrayVector const &patches, Osd::DrawContext::PatchArray const & patch = patches[i]; Osd::DrawContext::PatchDescriptor desc = patch.GetDescriptor(); - Far::PatchTables::Type patchType = desc.GetType(); + Far::PatchDescriptor::Type patchType = desc.GetType(); GLenum primType; switch(patchType) { - case Far::PatchTables::QUADS: + case Far::PatchDescriptor::QUADS: primType = GL_LINES_ADJACENCY; break; - case Far::PatchTables::TRIANGLES: + case Far::PatchDescriptor::TRIANGLES: primType = GL_TRIANGLES; break; default: diff --git a/examples/glViewer/glViewer.cpp b/examples/glViewer/glViewer.cpp index 3f05a116..00a820aa 100644 --- a/examples/glViewer/glViewer.cpp +++ b/examples/glViewer/glViewer.cpp @@ -840,6 +840,8 @@ protected: EffectDrawRegistry::SourceConfigType * EffectDrawRegistry::_CreateDrawSourceConfig(DescType const & desc) { + typedef OpenSubdiv::Far::PatchDescriptor Descriptor; + Effect effect = desc.second; SourceConfigType * sconfig = @@ -853,8 +855,8 @@ EffectDrawRegistry::_CreateDrawSourceConfig(DescType const & desc) const char *glslVersion = "#version 330\n"; #endif - if (desc.first.GetType() == OpenSubdiv::Far::PatchTables::QUADS or - desc.first.GetType() == OpenSubdiv::Far::PatchTables::TRIANGLES) { + if (desc.first.GetType() == Descriptor::QUADS or + desc.first.GetType() == Descriptor::TRIANGLES) { sconfig->vertexShader.source = shaderSource; sconfig->vertexShader.version = glslVersion; sconfig->vertexShader.AddDefine("VERTEX_SHADER"); @@ -870,12 +872,12 @@ EffectDrawRegistry::_CreateDrawSourceConfig(DescType const & desc) sconfig->fragmentShader.version = glslVersion; sconfig->fragmentShader.AddDefine("FRAGMENT_SHADER"); - if (desc.first.GetType() == OpenSubdiv::Far::PatchTables::QUADS) { + if (desc.first.GetType() == Descriptor::QUADS) { // uniform catmark, bilinear sconfig->geometryShader.AddDefine("PRIM_QUAD"); sconfig->fragmentShader.AddDefine("PRIM_QUAD"); sconfig->commonShader.AddDefine("UNIFORM_SUBDIVISION"); - } else if (desc.first.GetType() == OpenSubdiv::Far::PatchTables::TRIANGLES) { + } else if (desc.first.GetType() == Descriptor::TRIANGLES) { // uniform loop sconfig->geometryShader.AddDefine("PRIM_TRI"); sconfig->fragmentShader.AddDefine("PRIM_TRI"); @@ -1169,7 +1171,7 @@ display() { OpenSubdiv::Osd::DrawContext::PatchArray const & patch = patches[i]; OpenSubdiv::Osd::DrawContext::PatchDescriptor desc = patch.GetDescriptor(); - OpenSubdiv::Far::PatchTables::Type patchType = desc.GetType(); + OpenSubdiv::Far::PatchDescriptor::Type patchType = desc.GetType(); int patchPattern = desc.GetPattern(); int patchRotation = desc.GetRotation(); int subPatch = desc.GetSubPatch(); @@ -1182,10 +1184,10 @@ display() { GLenum primType; switch(patchType) { - case OpenSubdiv::Far::PatchTables::QUADS: + case OpenSubdiv::Far::PatchDescriptor::QUADS: primType = GL_LINES_ADJACENCY; break; - case OpenSubdiv::Far::PatchTables::TRIANGLES: + case OpenSubdiv::Far::PatchDescriptor::TRIANGLES: primType = GL_TRIANGLES; break; default: @@ -1276,51 +1278,53 @@ display() { if (g_hud.IsVisible()) { + typedef OpenSubdiv::Far::PatchDescriptor Descriptor; + double fps = 1.0/elapsed; if (g_displayPatchCounts) { int x = -280; int y = -480; g_hud.DrawString(x, y, "NonPatch : %d", - patchCount[OpenSubdiv::Far::PatchTables::QUADS][0][0]); y += 20; + patchCount[Descriptor::QUADS][0][0]); y += 20; g_hud.DrawString(x, y, "Regular : %d", - patchCount[OpenSubdiv::Far::PatchTables::REGULAR][0][0]); y+= 20; + patchCount[Descriptor::REGULAR][0][0]); y+= 20; g_hud.DrawString(x, y, "Boundary : %d", - patchCount[OpenSubdiv::Far::PatchTables::BOUNDARY][0][0]); y+= 20; + patchCount[Descriptor::BOUNDARY][0][0]); y+= 20; g_hud.DrawString(x, y, "Corner : %d", - patchCount[OpenSubdiv::Far::PatchTables::CORNER][0][0]); y+= 20; + patchCount[Descriptor::CORNER][0][0]); y+= 20; g_hud.DrawString(x, y, "Single Crease : %d", - patchCount[OpenSubdiv::Far::PatchTables::SINGLE_CREASE][0][0]); y+= 20; + patchCount[Descriptor::SINGLE_CREASE][0][0]); y+= 20; g_hud.DrawString(x, y, "Gregory : %d", - patchCount[OpenSubdiv::Far::PatchTables::GREGORY][0][0]); y+= 20; + patchCount[Descriptor::GREGORY][0][0]); y+= 20; g_hud.DrawString(x, y, "Boundary Gregory : %d", - patchCount[OpenSubdiv::Far::PatchTables::GREGORY_BOUNDARY][0][0]); y+= 20; + patchCount[Descriptor::GREGORY_BOUNDARY][0][0]); y+= 20; g_hud.DrawString(x, y, "Trans. Regular : %d %d %d %d %d", - patchCount[OpenSubdiv::Far::PatchTables::REGULAR][OpenSubdiv::Far::PatchTables::PATTERN0][0], - patchCount[OpenSubdiv::Far::PatchTables::REGULAR][OpenSubdiv::Far::PatchTables::PATTERN1][0], - patchCount[OpenSubdiv::Far::PatchTables::REGULAR][OpenSubdiv::Far::PatchTables::PATTERN2][0], - patchCount[OpenSubdiv::Far::PatchTables::REGULAR][OpenSubdiv::Far::PatchTables::PATTERN3][0], - patchCount[OpenSubdiv::Far::PatchTables::REGULAR][OpenSubdiv::Far::PatchTables::PATTERN4][0]); y+= 20; + patchCount[Descriptor::REGULAR][Descriptor::PATTERN0][0], + patchCount[Descriptor::REGULAR][Descriptor::PATTERN1][0], + patchCount[Descriptor::REGULAR][Descriptor::PATTERN2][0], + patchCount[Descriptor::REGULAR][Descriptor::PATTERN3][0], + patchCount[Descriptor::REGULAR][Descriptor::PATTERN4][0]); y+= 20; for (int i=0; i < 5; i++) { g_hud.DrawString(x, y, "Trans. Boundary%d : %d %d %d %d", i, - patchCount[OpenSubdiv::Far::PatchTables::BOUNDARY][i+1][0], - patchCount[OpenSubdiv::Far::PatchTables::BOUNDARY][i+1][1], - patchCount[OpenSubdiv::Far::PatchTables::BOUNDARY][i+1][2], - patchCount[OpenSubdiv::Far::PatchTables::BOUNDARY][i+1][3]); y+= 20; + patchCount[Descriptor::BOUNDARY][i+1][0], + patchCount[Descriptor::BOUNDARY][i+1][1], + patchCount[Descriptor::BOUNDARY][i+1][2], + patchCount[Descriptor::BOUNDARY][i+1][3]); y+= 20; } for (int i=0; i < 5; i++) { g_hud.DrawString(x, y, "Trans. Corner%d : %d %d %d %d", i, - patchCount[OpenSubdiv::Far::PatchTables::CORNER][i+1][0], - patchCount[OpenSubdiv::Far::PatchTables::CORNER][i+1][1], - patchCount[OpenSubdiv::Far::PatchTables::CORNER][i+1][2], - patchCount[OpenSubdiv::Far::PatchTables::CORNER][i+1][3]); y+= 20; + patchCount[Descriptor::CORNER][i+1][0], + patchCount[Descriptor::CORNER][i+1][1], + patchCount[Descriptor::CORNER][i+1][2], + patchCount[Descriptor::CORNER][i+1][3]); y+= 20; } for (int i=0; i < 5; i++) { g_hud.DrawString(x, y, "Trans. Single Crease%d : %d %d %d %d", i, - patchCount[OpenSubdiv::Far::PatchTables::SINGLE_CREASE][i+1][0], - patchCount[OpenSubdiv::Far::PatchTables::SINGLE_CREASE][i+1][1], - patchCount[OpenSubdiv::Far::PatchTables::SINGLE_CREASE][i+1][2], - patchCount[OpenSubdiv::Far::PatchTables::SINGLE_CREASE][i+1][3]); y+= 20; + patchCount[Descriptor::SINGLE_CREASE][i+1][0], + patchCount[Descriptor::SINGLE_CREASE][i+1][1], + patchCount[Descriptor::SINGLE_CREASE][i+1][2], + patchCount[Descriptor::SINGLE_CREASE][i+1][3]); y+= 20; } } diff --git a/examples/vtrViewer/gl_mesh.cpp b/examples/vtrViewer/gl_mesh.cpp index da5b91e7..e84879d6 100644 --- a/examples/vtrViewer/gl_mesh.cpp +++ b/examples/vtrViewer/gl_mesh.cpp @@ -473,8 +473,8 @@ setEdge(std::vector & vbo, int edge, float const * vertData, int v0, int memcpy(dst1+3, color, sizeof(float)*3); } inline int -getRingSize(OpenSubdiv::Far::PatchTables::Descriptor desc) { - if (desc.GetType()==OpenSubdiv::Far::PatchTables::GREGORY_BASIS) { +getRingSize(OpenSubdiv::Far::PatchDescriptor desc) { + if (desc.GetType()==OpenSubdiv::Far::PatchDescriptor::GREGORY_BASIS) { return 4; } else { return desc.GetNumControlVertices(); @@ -510,23 +510,17 @@ GLMesh::initializeBuffers(Options options, TopologyRefiner const & refiner, } } - typedef OpenSubdiv::Far::PatchTables PatchTables; - - PatchTables::PTable const & ptable = - patchTables.GetPatchTable(); - - PatchTables::PatchArrayVector const & parrays = - patchTables.GetPatchArrayVector(); + typedef OpenSubdiv::Far::PatchDescriptor Descriptor; { // edge color component ------------------------------ int nedges = 0; - for (int i=0; i<(int)parrays.size(); ++i) { + for (int array=0; array<(int)patchTables.GetNumPatchArrays(); ++array) { - int ncvs = parrays[i].GetDescriptor().GetNumControlVertices(); + int ncvs = getRingSize(patchTables.GetPatchArrayDescriptor(array)); - nedges += parrays[i].GetNumPatches() * getNumEdges(ncvs); + nedges += patchTables.GetNumPatches(array) * getNumEdges(ncvs); } std::vector & vbo = _vbo[COMP_EDGE]; vbo.resize(nedges * 2 * 6); @@ -540,23 +534,25 @@ GLMesh::initializeBuffers(Options options, TopologyRefiner const & refiner, float const * color=solidColor; - for (int i=0, edge=0; i<(int)parrays.size(); ++i) { + for (int array=0, edge=0; array<(int)patchTables.GetNumPatchArrays(); ++array) { - PatchTables::PatchArray const & pa = parrays[i]; + OpenSubdiv::Far::PatchDescriptor desc = + patchTables.GetPatchArrayDescriptor(array); if (options.edgeColorMode==EDGECOLOR_BY_PATCHTYPE) { - color = getAdaptivePatchColor(pa.GetDescriptor()); + color = getAdaptivePatchColor(desc); } - int ncvs = getRingSize(pa.GetDescriptor()); + int ncvs = getRingSize(desc); - OpenSubdiv::Far::Index const * cvs = &ptable[pa.GetVertIndex()]; + for (int patch=0; patch)); } // Returns the number of patches based on the patch type in the descriptor - TYPE & getValue( Far::PatchTables::Descriptor desc ); + TYPE & getValue( Descriptor desc ); // Counts the number of arrays required to store each type of patch used // in the primitive @@ -476,26 +476,20 @@ private: typedef PatchTypes FVarPointers; typedef PatchTypes Counter; - // Creates a PatchArray and appends it to a vector and keeps track of both - // vertex and patch offsets - static void pushPatchArray( Descriptor desc, - Far::PatchTables::PatchArrayVector & parray, - int npatches, int * voffset, int * poffset, int * qoffset ); - }; //------------------------------------------------------------------------------ template TYPE & -Far::PatchTablesFactory::PatchTypes::getValue( Far::PatchTables::Descriptor desc ) { +Far::PatchTablesFactory::PatchTypes::getValue( Far::PatchDescriptor desc ) { switch (desc.GetType()) { - case Far::PatchTables::REGULAR : return R[desc.GetPattern()]; - case Far::PatchTables::SINGLE_CREASE : break; - case Far::PatchTables::BOUNDARY : return B[desc.GetPattern()][desc.GetRotation()]; - case Far::PatchTables::CORNER : return C[desc.GetPattern()][desc.GetRotation()]; - case Far::PatchTables::GREGORY : return G; - case Far::PatchTables::GREGORY_BOUNDARY : return GB; - case Far::PatchTables::GREGORY_BASIS : return GP; + case Far::PatchDescriptor::REGULAR : return R[desc.GetPattern()]; + case Far::PatchDescriptor::SINGLE_CREASE : break; + case Far::PatchDescriptor::BOUNDARY : return B[desc.GetPattern()][desc.GetRotation()]; + case Far::PatchDescriptor::CORNER : return C[desc.GetPattern()][desc.GetRotation()]; + case Far::PatchDescriptor::GREGORY : return G; + case Far::PatchDescriptor::GREGORY_BOUNDARY : return GB; + case Far::PatchDescriptor::GREGORY_BASIS : return GP; default : assert(0); } // can't be reached (suppress compiler warning) @@ -574,7 +568,7 @@ Far::PatchTablesFactory::computeCornerPatchRotation( Hface * f ) { } return rot; } - +/* int Far::PatchTablesFactory::getNumPatches( Far::PatchTables::PatchArrayVector const & parrays ) { @@ -585,37 +579,31 @@ Far::PatchTablesFactory::getNumPatches( Far::PatchTables::PatchArrayVector const return result; } - +*/ //------------------------------------------------------------------------------ void Far::PatchTablesFactory::allocateTables( Far::PatchTables * tables, int /* nlevels */, int fvarwidth ) { - PatchTables::PatchArrayVector const & parrays = tables->GetPatchArrayVector(); - int nverts = 0, npatches = 0; - for (int i=0; i<(int)parrays.size(); ++i) { - - int nps = parrays[i].GetNumPatches(), - ncvs = parrays[i].GetDescriptor().GetNumControlVertices(); - - npatches += nps; - nverts += ncvs * nps; + for (int i=0; iGetNumPatchArrays(); ++i) { + npatches += tables->GetNumPatches(i); + nverts += tables->GetNumControlVertices(i); } if (nverts==0 or npatches==0) return; - tables->_patches.resize( nverts ); + tables->_patchVerts.resize( nverts ); tables->_paramTable.resize( npatches ); if (fvarwidth>0) { - Far::PatchTables::PatchArrayVector const & parrays = tables->GetPatchArrayVector(); - int nfvarverts = 0; - for (int i=0; i<(int)parrays.size(); ++i) { - nfvarverts += parrays[i].GetNumPatches() * - (parrays[i].GetDescriptor().GetType() == Far::PatchTables::TRIANGLES ? 3 : 4); - } + //Far::PatchTables::PatchArrayVector const & parrays = tables->GetPatchArrayVector(); + //int nfvarverts = 0; + //for (int i=0; i<(int)parrays.size(); ++i) { + // nfvarverts += parrays[i].GetNumPatches() * + // (parrays[i].GetDescriptor().GetType() == Far::PatchTables::TRIANGLES ? 3 : 4); + //} //tables->_fvarData._data.resize( nfvarverts * fvarwidth ); @@ -707,17 +695,17 @@ Far::PatchTablesFactory::Create(Hmesh & mesh, int maxvalence) { switch (boundaryVerts) { case 0 : { // Regular patch - patchCtr.R[Far::PatchTables::NON_TRANSITION]++; + patchCtr.R[Far::PatchDescriptor::NON_TRANSITION]++; } break; case 2 : { // Boundary patch f->_adaptiveFlags.rots=computeBoundaryPatchRotation(f); - patchCtr.B[Far::PatchTables::NON_TRANSITION][0]++; + patchCtr.B[Far::PatchDescriptor::NON_TRANSITION][0]++; } break; case 3 : { // Corner patch f->_adaptiveFlags.rots=computeCornerPatchRotation(f); - patchCtr.C[Far::PatchTables::NON_TRANSITION][0]++; + patchCtr.C[Far::PatchDescriptor::NON_TRANSITION][0]++; } break; default : break; @@ -838,17 +826,15 @@ Far::PatchTablesFactory::Create(Hmesh & mesh, int maxvalence) { Far::PatchTables * result = new Far::PatchTables(maxvalence); // Populate the patch array descriptors - Far::PatchTables::PatchArrayVector & parray = result->_patchArrays; - parray.reserve( patchCtr.getNumPatchArrays() ); + result->reservePatchArrays(patchCtr.getNumPatchArrays()); - typedef PatchTables::DescriptorVector DescVec; + typedef Far::PatchDescriptorVector DescVec; - DescVec const & catmarkDescs = Far::PatchTables::GetAdaptiveDescriptors(Sdc::TYPE_CATMARK); + DescVec const & catmarkDescs = Far::PatchDescriptor::GetAdaptivePatchDescriptors(Sdc::TYPE_CATMARK); int voffset=0, poffset=0, qoffset=0; for (DescVec::const_iterator it=catmarkDescs.begin(); it!=catmarkDescs.end(); ++it) { - - pushPatchArray( *it, parray, patchCtr.getValue(*it), &voffset, &poffset, &qoffset ); + result->pushPatchArray(*it, patchCtr.getValue(*it), &voffset, &poffset, &qoffset ); } //result->_fvarData._fvarWidth = fvarwidth; @@ -858,7 +844,7 @@ Far::PatchTablesFactory::Create(Hmesh & mesh, int maxvalence) { allocateTables( result, 0, fvarwidth ); if ((patchCtr.G > 0) or (patchCtr.GB > 0)) { // Quad-offsets tables (for Gregory patches) - result->_quadOffsetTable.resize( patchCtr.G*4 + patchCtr.GB*4 ); + result->_quadOffsetsTable.resize( patchCtr.G*4 + patchCtr.GB*4 ); } // Setup convenience pointers at the beginning of each patch array for each @@ -869,20 +855,17 @@ Far::PatchTablesFactory::Create(Hmesh & mesh, int maxvalence) { for (DescVec::const_iterator it=catmarkDescs.begin(); it!=catmarkDescs.end(); ++it) { - Far::PatchTables::PatchArray * pa = result->findPatchArray(*it); - - if (not pa) + Index arrayIndex = result->findPatchArray(*it); + if (arrayIndex==Vtr::INDEX_INVALID) { continue; + } - iptrs.getValue( *it ) = &result->_patches[pa->GetVertIndex()]; - pptrs.getValue( *it ) = &result->_paramTable[pa->GetPatchIndex()]; - - //if (fvarwidth>0) - // fptrs.getValue( *it ) = &result->_fvarData._data[pa->GetPatchIndex() * 4 * fvarwidth]; + iptrs.getValue( *it ) = result->getPatchArrayVertices(arrayIndex).begin(); + pptrs.getValue( *it ) = result->getPatchParams(arrayIndex).begin(); } - Far::PatchTables::QuadOffsetTable::value_type *quad_G_C0_P = patchCtr.G>0 ? &result->_quadOffsetTable[0] : 0; - Far::PatchTables::QuadOffsetTable::value_type *quad_G_C1_P = patchCtr.GB>0 ? &result->_quadOffsetTable[patchCtr.G*4] : 0; + unsigned int * quad_G_C0_P = patchCtr.G>0 ? &result->_quadOffsetsTable[0] : 0, + * quad_G_C1_P = patchCtr.GB>0 ? &result->_quadOffsetsTable[patchCtr.G*4] : 0; // Populate patch index tables with vertex indices for (int i=0; i_adaptiveFlags.patchType==Hface::kFull) { if (not f->_adaptiveFlags.isExtraordinary and f->_adaptiveFlags.bverts!=1) { - int pattern = Far::PatchTables::NON_TRANSITION, + int pattern = Far::PatchDescriptor::NON_TRANSITION, rot = 0; switch (f->_adaptiveFlags.bverts) { @@ -1216,7 +1199,7 @@ Far::PatchTablesFactory::getOneRing(Hface const * f, //------------------------------------------------------------------------------ // Populate the quad-offsets table used by Gregory patches void -Far::PatchTablesFactory::getQuadOffsets(Hface const * f, Far::Index * result) { +Far::PatchTablesFactory::getQuadOffsets(Hface const * f, unsigned int * result) { assert(result and f and f->GetNumVertices()==4); diff --git a/examples/vtrViewer/vtrViewer.cpp b/examples/vtrViewer/vtrViewer.cpp index d16745e8..2d9fcf55 100644 --- a/examples/vtrViewer/vtrViewer.cpp +++ b/examples/vtrViewer/vtrViewer.cpp @@ -119,7 +119,7 @@ int g_displayPatchColor = 1, g_currentPatch = 0, g_Adaptive = true; -OpenSubdiv::Far::PatchTables::Descriptor g_currentPatchDesc; +OpenSubdiv::Far::PatchDescriptor g_currentPatchDesc; float g_rotate[2] = {0, 0}, g_dolly = 5, @@ -503,38 +503,30 @@ createPatchNumbers(OpenSubdiv::Far::PatchTables const & patchTables, if (not g_currentPatch) return; - int patchID = g_currentPatch-1; - - OpenSubdiv::Far::PatchTables::PatchArrayVector const & parrays = - patchTables.GetPatchArrayVector(); + int patchID = g_currentPatch-1, + patchArray = -1; // Find PatchArray containing our patch - OpenSubdiv::Far::PatchTables::PatchArray const * pa=0; - for (int i=0; i<(int)parrays.size(); ++i) { - int npatches = parrays[i].GetNumPatches(); + for (int array=0; array<(int)patchTables.GetNumPatchArrays(); ++array) { + int npatches = patchTables.GetNumPatches(array); if (patchID >= npatches) { patchID -= npatches; } else { - pa = &parrays[i]; + patchArray = array; break; } } - if (not pa) { + if (patchArray==-1) { return; } - OpenSubdiv::Far::PatchTables::PTable const & ptable = - patchTables.GetPatchTable(); + g_currentPatchDesc = patchTables.GetPatchArrayDescriptor(patchArray); - g_currentPatchDesc = pa->GetDescriptor(); - - int ncvs = g_currentPatchDesc.GetNumControlVertices(); - - OpenSubdiv::Far::Index const * cvs = - &ptable[pa->GetVertIndex()] + ncvs*patchID; + OpenSubdiv::Far::IndexArray const cvs = + patchTables.GetPatchVertices(patchArray, patchID); static char buf[16]; - for (int i=0; iPrint3D(vertexBuffer[cvs[i]].GetPos(), buf, 1); } @@ -549,16 +541,14 @@ static void createGregoryBasis(OpenSubdiv::Far::PatchTables const & patchTables, std::vector const & vertexBuffer) { - typedef OpenSubdiv::Far::PatchTables FPatchTables; - - FPatchTables::PatchArrayVector const & parrays = - patchTables.GetPatchArrayVector(); + typedef OpenSubdiv::Far::PatchTables PatchTables; + typedef OpenSubdiv::Far::PatchDescriptor PatchDescriptor; int npatches = 0; - for (int i=0; i<(int)parrays.size(); ++i) { - FPatchTables::PatchArray const & pa = parrays[i]; - if (pa.GetDescriptor().GetType()==FPatchTables::GREGORY_BASIS) { - npatches = pa.GetNumPatches(); + for (int array=0; array<(int)patchTables.GetNumPatchArrays(); ++array) { + if (patchTables.GetPatchArrayDescriptor(array).GetType()== + PatchDescriptor::GREGORY_BASIS) { + npatches = patchTables.GetNumPatches(array); break; } } @@ -619,16 +609,7 @@ static void createPtexNumbers(OpenSubdiv::Far::PatchTables const & patchTables, std::vector const & vertexBuffer) { - typedef OpenSubdiv::Far::PatchTables FPatchTables; - - FPatchTables::PatchParamTable const & pparams = - patchTables.GetPatchParamTable(); - - FPatchTables::PTable const & ptable = - patchTables.GetPatchTable(); - - FPatchTables::PatchArrayVector const & parrays = - patchTables.GetPatchArrayVector(); + typedef OpenSubdiv::Far::PatchDescriptor Descriptor; static char buf[16]; @@ -637,25 +618,22 @@ createPtexNumbers(OpenSubdiv::Far::PatchTables const & patchTables, corner[4] = {1, 2, 4, 5}, gregory[4] = {0, 1, 2, 3}; - for (int i=0, patch=0; i<(int)parrays.size(); ++i) { + for (int array=0; array<(int)patchTables.GetNumPatchArrays(); ++array) { - FPatchTables::PatchArray const & pa = parrays[i]; + for (int patch=0; patch<(int)patchTables.GetNumPatches(array); ++patch) { - for (int j=0; j<(int)pa.GetNumPatches(); ++j, ++patch) { - - int ncvs = pa.GetDescriptor().GetNumControlVertices(); - - OpenSubdiv::Far::Index const * cvs = - &ptable[pa.GetVertIndex()] + ncvs*j; + OpenSubdiv::Far::IndexArray const cvs = + patchTables.GetPatchVertices(array, patch); int * remap = 0; - switch (pa.GetDescriptor().GetType()) { - case FPatchTables::REGULAR: remap = regular; break; - case FPatchTables::SINGLE_CREASE: remap = boundary; break; - case FPatchTables::BOUNDARY: remap = boundary; break; - case FPatchTables::CORNER: remap = corner; break; - case FPatchTables::GREGORY: - case FPatchTables::GREGORY_BOUNDARY: remap = gregory; break; + switch (patchTables.GetPatchArrayDescriptor(array).GetType()) { + case Descriptor::REGULAR: remap = regular; break; + case Descriptor::SINGLE_CREASE: remap = boundary; break; + case Descriptor::BOUNDARY: remap = boundary; break; + case Descriptor::CORNER: remap = corner; break; + case Descriptor::GREGORY: + case Descriptor::GREGORY_BOUNDARY: + case Descriptor::GREGORY_BASIS: remap = gregory; break; default: assert(0); } @@ -665,7 +643,7 @@ createPtexNumbers(OpenSubdiv::Far::PatchTables const & patchTables, center.AddWithWeight(vertexBuffer[cvs[remap[k]]], 0.25f); } - snprintf(buf, 16, "%d", pparams[patch].faceIndex); + snprintf(buf, 16, "%d", patchTables.GetPatchParam(array, patch).faceIndex); g_font->Print3D(center.GetPos(), buf, 1); } } diff --git a/opensubdiv/far/CMakeLists.txt b/opensubdiv/far/CMakeLists.txt index 0b746edd..d9e8aa67 100644 --- a/opensubdiv/far/CMakeLists.txt +++ b/opensubdiv/far/CMakeLists.txt @@ -26,6 +26,7 @@ # source & headers set(SOURCE_FILES gregoryBasis.cpp + patchDescriptor.cpp patchMap.cpp patchTables.cpp patchTablesFactory.cpp @@ -42,6 +43,7 @@ set(PUBLIC_HEADER_FILES gregoryBasis.h kernelBatch.h kernelBatchDispatcher.h + patchDescriptor.h patchParam.h patchMap.h patchTables.h diff --git a/opensubdiv/far/patchDescriptor.cpp b/opensubdiv/far/patchDescriptor.cpp new file mode 100644 index 00000000..45b3ebb4 --- /dev/null +++ b/opensubdiv/far/patchDescriptor.cpp @@ -0,0 +1,112 @@ +// +// Copyright 2014 DreamWorks Animation LLC. +// +// Licensed under the Apache License, Version 2.0 (the "Apache License") +// with the following modification; you may not use this file except in +// compliance with the Apache License and the following modification to it: +// Section 6. Trademarks. is deleted and replaced with: +// +// 6. Trademarks. This License does not grant permission to use the trade +// names, trademarks, service marks, or product names of the Licensor +// and its affiliates, except as required to comply with Section 4(c) of +// the License and to reproduce the content of the NOTICE file. +// +// You may obtain a copy of the Apache License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the Apache License with the above modification is +// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the Apache License for the specific +// language governing permissions and limitations under the Apache License. +// + +#include "../far/patchDescriptor.h" + +#include + +namespace OpenSubdiv { +namespace OPENSUBDIV_VERSION { + +namespace Far { + + +// +// Lists of patch Descriptors for each subdivision scheme +// + +static PatchDescriptorVector const & +getAdaptiveCatmarkDescriptors() { + + static PatchDescriptorVector _descriptors; + + if (_descriptors.empty()) { + + _descriptors.reserve(72); + + // non-transition patches : 7 + for (int i=PatchDescriptor::REGULAR; + i<=PatchDescriptor::GREGORY_BASIS; ++i) { + + _descriptors.push_back( + PatchDescriptor(i, PatchDescriptor::NON_TRANSITION, 0)); + } + + // transition patches (1 + 4 * 3) * 5 = 65 + for (int i=PatchDescriptor::PATTERN0; i<=PatchDescriptor::PATTERN4; ++i) { + + _descriptors.push_back( + PatchDescriptor(PatchDescriptor::REGULAR, i, 0) ); + + // 4 rotations for single-crease, boundary and corner patches + for (int j=0; j<4; ++j) { + _descriptors.push_back( + PatchDescriptor(PatchDescriptor::SINGLE_CREASE, i, j)); + } + + for (int j=0; j<4; ++j) { + _descriptors.push_back( + PatchDescriptor(PatchDescriptor::BOUNDARY, i, j)); + } + + for (int j=0; j<4; ++j) { + _descriptors.push_back( + PatchDescriptor(PatchDescriptor::CORNER, i, j)); + } + } + } + return _descriptors; +} +static PatchDescriptorVector const & +getAdaptiveLoopDescriptors() { + + static PatchDescriptorVector _descriptors; + + if (_descriptors.empty()) { + _descriptors.reserve(1); + _descriptors.push_back( + PatchDescriptor(PatchDescriptor::LOOP, PatchDescriptor::NON_TRANSITION, 0) ); + } + return _descriptors; +} +PatchDescriptorVector const & +PatchDescriptor::GetAdaptivePatchDescriptors(Sdc::Type type) { + + static PatchDescriptorVector _empty; + + switch (type) { + case Sdc::TYPE_BILINEAR : return _empty; + case Sdc::TYPE_CATMARK : return getAdaptiveCatmarkDescriptors(); + case Sdc::TYPE_LOOP : return getAdaptiveLoopDescriptors(); + default: + assert(0); + } + return _empty; +} + + +} // end namespace Far + +} // end namespace OPENSUBDIV_VERSION +} // end namespace OpenSubdiv diff --git a/opensubdiv/far/patchDescriptor.h b/opensubdiv/far/patchDescriptor.h new file mode 100644 index 00000000..c901d125 --- /dev/null +++ b/opensubdiv/far/patchDescriptor.h @@ -0,0 +1,238 @@ +// +// Copyright 2013 Pixar +// +// Licensed under the Apache License, Version 2.0 (the "Apache License") +// with the following modification; you may not use this file except in +// compliance with the Apache License and the following modification to it: +// Section 6. Trademarks. is deleted and replaced with: +// +// 6. Trademarks. This License does not grant permission to use the trade +// names, trademarks, service marks, or product names of the Licensor +// and its affiliates, except as required to comply with Section 4(c) of +// the License and to reproduce the content of the NOTICE file. +// +// You may obtain a copy of the Apache License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the Apache License with the above modification is +// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the Apache License for the specific +// language governing permissions and limitations under the Apache License. +// + +#ifndef FAR_PATCH_DESCRIPTOR_H +#define FAR_PATCH_DESCRIPTOR_H + +#include "../version.h" + +#include "../sdc/type.h" + +#include + +namespace OpenSubdiv { +namespace OPENSUBDIV_VERSION { + +namespace Far { + +/// \brief Describes the type of a patch +/// +/// Uniquely identifies all the different types of patches +/// +/// * Uniformly subdivided meshes contain bilinear patches of either QUADS +/// or TRIANGLES +/// +/// * Adaptively subdivided meshes contain bicubic patches of types REGULAR, +/// BOUNDARY, SINGLE_CREASE, CORNER, GREGORY, GREGORY_BOUNDARY, GREGOYR_BASIS. +/// These bicubic patches are also further distinguished by a transition +/// pattern as well as a rotational orientation. +/// +/// Bitfield layout : +/// +/// Field | Bits | Content +/// -----------|:----:|------------------------------------------------------ +/// _type | 4 | patch type +/// _pattern | 3 | patch transition pattern +/// _rotation | 2 | patch rotation +/// +class PatchDescriptor { + +public: + + enum Type { + NON_PATCH = 0, ///< undefined + + POINTS, ///< points (useful for cage drawing) + LINES, ///< lines (useful for cage drawing) + + QUADS, ///< bilinear quads-only patches + TRIANGLES, ///< bilinear triangles-only mesh + + LOOP, ///< Loop patch + + REGULAR, ///< feature-adaptive bicubic patches + SINGLE_CREASE, + BOUNDARY, + CORNER, + GREGORY, + GREGORY_BOUNDARY, + GREGORY_BASIS + }; + + enum TransitionPattern { + NON_TRANSITION = 0, + PATTERN0, + PATTERN1, + PATTERN2, + PATTERN3, + PATTERN4 + }; + +public: + + /// \brief Default constructor. + PatchDescriptor() : + _type(NON_PATCH), _pattern(NON_TRANSITION), _rotation(0) {} + + /// \brief Constructor + PatchDescriptor(int type, int pattern, unsigned char rotation) : + _type(type), _pattern(pattern), _rotation(rotation) { } + + /// \brief Copy Constructor + PatchDescriptor( PatchDescriptor const & d ) : + _type(d.GetType()), _pattern(d.GetPattern()), _rotation(d.GetRotation()) { } + + /// \brief Returns the type of the patch + Type GetType() const { + return (Type)_type; + } + + /// \brief Returns the transition pattern of the patch if any (5 types) + TransitionPattern GetPattern() const { + return (TransitionPattern)_pattern; + } + + /// \brief Returns the rotation of the patch (4 rotations) + unsigned char GetRotation() const { + return (unsigned char)_rotation; + } + + /// \brief Returns the number of control vertices expected for a patch of the + /// type described + static inline short GetNumControlVertices( Type t ); + + static inline short GetNumFVarControlVertices( Type t ); + + /// \brief Returns the number of control vertices expected for a patch of the + /// type described + short GetNumControlVertices() const { + return GetNumControlVertices( this->GetType() ); + } + + /// \brief Returns the number of control vertices expected for a patch of the + /// type described + short GetNumFVarControlVertices() const { + return GetNumFVarControlVertices( this->GetType() ); + } + + /// \brief Number of control vertices of Regular Patches in table. + static short GetRegularPatchSize() { return 16; } + + /// \brief Number of control vertices of Boundary Patches in table. + static short GetBoundaryPatchSize() { return 12; } + + /// \brief Number of control vertices of Boundary Patches in table. + static short GetCornerPatchSize() { return 9; } + + /// \brief Number of control vertices of Gregory (and Gregory Boundary) Patches in table. + static short GetGregoryPatchSize() { return 4; } + + /// \brief Number of control vertices of Gregory patch basis (20) + static short GetGregoryBasisPatchSize() { return 20; } + + + /// \brief Returns a vector of all the legal patch descriptors for the + /// given adaptive subdivision scheme + static std::vector const & GetAdaptivePatchDescriptors(Sdc::Type type); + + /// \brief Allows ordering of patches by type + inline bool operator < ( PatchDescriptor const other ) const; + + /// \brief True if the descriptors are identical + inline bool operator == ( PatchDescriptor const other ) const; + +private: + friend class PatchTablesFactory; + + unsigned int _type:4; + unsigned int _pattern:3; + unsigned int _rotation:2; +}; + +typedef std::vector PatchDescriptorVector; + +// Returns the number of control vertices expected for a patch of this type +inline short +PatchDescriptor::GetNumControlVertices( Type type ) { + switch (type) { + case REGULAR : return GetRegularPatchSize(); + case SINGLE_CREASE : return GetRegularPatchSize(); + case QUADS : return 4; + case GREGORY : + case GREGORY_BOUNDARY : return GetGregoryPatchSize(); + case GREGORY_BASIS : return GetGregoryBasisPatchSize(); + case BOUNDARY : return GetBoundaryPatchSize(); + case CORNER : return GetCornerPatchSize(); + case TRIANGLES : return 3; + case LINES : return 2; + case POINTS : return 1; + default : return -1; + } +} + +// Returns the number of face-varying control vertices expected for a patch of this type +inline short +PatchDescriptor::GetNumFVarControlVertices( Type type ) { + switch (type) { + case REGULAR : // We only support bilinear interpolation for now, + case SINGLE_CREASE : + case QUADS : // so all these patches only carry 4 CVs. + case GREGORY : + case GREGORY_BOUNDARY : + case GREGORY_BASIS : + case BOUNDARY : + case CORNER : return 4; + case TRIANGLES : return 3; + case LINES : return 2; + case POINTS : return 1; + default : return -1; + } +} + +// Allows ordering of patches by type +inline bool +PatchDescriptor::operator < ( PatchDescriptor const other ) const { + return _pattern < other._pattern or ((_pattern == other._pattern) and + (_type < other._type or ((_type == other._type) and + (_rotation < other._rotation)))); +} + +// True if the descriptors are identical +inline bool +PatchDescriptor::operator == ( PatchDescriptor const other ) const { + return _pattern == other._pattern and + _type == other._type and + _rotation == other._rotation; +} + + + +} // end namespace Far + +} // end namespace OPENSUBDIV_VERSION +using namespace OPENSUBDIV_VERSION; + +} // end namespace OpenSubdiv + +#endif /* FAR_PATCH_DESCRIPTOR_H */ diff --git a/opensubdiv/far/patchMap.cpp b/opensubdiv/far/patchMap.cpp index 3a12d951..052ec310 100644 --- a/opensubdiv/far/patchMap.cpp +++ b/opensubdiv/far/patchMap.cpp @@ -65,42 +65,36 @@ PatchMap::addChild( QuadTree & quadtree, QuadNode * parent, int quadrant ) { void PatchMap::initialize( PatchTables const & patchTables ) { - int nfaces = 0, npatches = (int)patchTables.GetNumPatchesTotal(); + int nfaces = 0, + narrays = (int)patchTables.GetNumPatchArrays(), + npatches = (int)patchTables.GetNumPatchesTotal(); - if (not npatches) + if (not narrays or not npatches) return; - PatchTables::PatchArrayVector const & patchArrays = - patchTables.GetPatchArrayVector(); - - PatchTables::PatchParamTable const & paramTable = - patchTables.GetPatchParamTable(); - // populate subpatch handles vector _handles.resize(npatches); - for (int arrayIdx=0, current=0; arrayIdx<(int)patchArrays.size(); ++arrayIdx) { - PatchTables::PatchArray const & parray = patchArrays[arrayIdx]; + for (int parray=0, current=0; parray quadtree; @@ -111,23 +105,21 @@ PatchMap::initialize( PatchTables const & patchTables ) { quadtree.resize(nfaces); // populate the quadtree from the FarPatchArrays sub-patches - for (int i=0, handleIdx=0; i<(int)patchArrays.size(); ++i) { + for (Index parray=0, handleIndex=0; parraySetChild( handleIdx ); + node->SetChild( handleIndex ); continue; } @@ -136,7 +128,7 @@ PatchMap::initialize( PatchTables const & patchTables ) { pdepth = bits.NonQuadRoot() ? depth-2 : depth-1, half = 1 << pdepth; - for (unsigned char k=0; k> 1; @@ -145,10 +137,10 @@ PatchMap::initialize( PatchTables const & patchTables ) { half = delta; - if (k==pdepth) { + if (j==pdepth) { // we have reached the depth of the sub-patch : add a leaf assert( not node->children[quadrant].isSet ); - node->SetChild(quadrant, handleIdx, true); + node->SetChild(quadrant, handleIndex, true); break; } else { // travel down the child node of the corresponding quadrant diff --git a/opensubdiv/far/patchParam.h b/opensubdiv/far/patchParam.h index b18c62bf..0f3723c3 100644 --- a/opensubdiv/far/patchParam.h +++ b/opensubdiv/far/patchParam.h @@ -45,25 +45,25 @@ namespace Far { /// but has to be remapped to a specific layout for uv textures. /// /// Bitfield layout : -/// -/// Field | Bits | Content +/// +/// Field | Bits | Content /// -----------|:----:|------------------------------------------------------ -/// level | 4 | the subdivision level of the patch -/// nonquad | 1 | whether the patch is the child of a non-quad face -/// rotation | 2 | patch rotations necessary to match CCW face-winding -/// v | 10 | log2 value of u parameter at first patch corner -/// u | 10 | log2 value of v parameter at first patch corner -/// reserved1 | 5 | padding -/// +/// level | 4 | the subdivision level of the patch +/// nonquad | 1 | whether the patch is the child of a non-quad face +/// rotation | 2 | patch rotations necessary to match CCW face-winding +/// v | 10 | log2 value of u parameter at first patch corner +/// u | 10 | log2 value of v parameter at first patch corner +/// reserved1 | 5 | padding +/// /// Note : the bitfield is not expanded in the struct due to differences in how /// GPU & CPU compilers pack bit-fields and endian-ness. /// struct PatchParam { Index faceIndex:32; // Ptex face index - + struct BitField { unsigned int field:32; - + /// \brief Sets the values of the bit fields /// /// @param u value of the u parameter for the first corner of the face @@ -73,13 +73,7 @@ struct PatchParam { /// @param depth subdivision level of the patch /// @param nonquad true if the root face is not a quad /// - void Set( short u, short v, unsigned char rots, unsigned char depth, bool nonquad ) { - field = (u << 17) | - (v << 7) | - (rots << 5) | - ((nonquad ? 1:0) << 4) | - (nonquad ? depth+1 : depth); - } + void Set( short u, short v, unsigned char rots, unsigned char depth, bool nonquad ); /// \brief Returns the log2 value of the u parameter at the top left corner of /// the patch @@ -94,34 +88,32 @@ struct PatchParam { /// \brief True if the parent coarse face is a non-quad bool NonQuadRoot() const { return (field >> 4) & 0x1; } - - /// \brief Returns the fratcion of normalized parametric space covered by the + + /// \brief Returns the fratcion of normalized parametric space covered by the /// sub-patch. float GetParamFraction() const; - /// \brief Returns the level of subdivision of the patch + /// \brief Returns the level of subdivision of the patch unsigned char GetDepth() const { return (unsigned char)(field & 0xf); } - /// The (u,v) pair is normalized to this sub-parametric space. + /// The (u,v) pair is normalized to this sub-parametric space. /// /// @param u u parameter - /// /// @param v v parameter /// void Normalize( float & u, float & v ) const; - + /// \brief Rotate (u,v) pair to compensate for transition pattern and boundary /// orientations. /// /// @param u u parameter - /// /// @param v v parameter /// void Rotate( float & u, float & v ) const; /// \brief Resets the values to 0 void Clear() { field = 0; } - + } bitField; /// \brief Sets the values of the bit fields @@ -139,15 +131,29 @@ struct PatchParam { faceIndex = faceid; bitField.Set(u,v,rots,depth,nonquad); } - + /// \brief Resets everything to 0 - void Clear() { + void Clear() { faceIndex = 0; bitField.Clear(); } }; -inline float +typedef std::vector PatchParamTable; + +typedef Vtr::Array PatchParamArray; + +inline void +PatchParam::BitField::Set( short u, short v, unsigned char rots, unsigned char depth, bool nonquad ) { + field = (u << 17) | + (v << 7) | + (rots << 5) | + ((nonquad ? 1:0) << 4) | + (nonquad ? depth+1 : depth); +} + + +inline float PatchParam::BitField::GetParamFraction( ) const { if (NonQuadRoot()) { return 1.0f / float( 1 << (GetDepth()-1) ); @@ -170,7 +176,7 @@ PatchParam::BitField::Normalize( float & u, float & v ) const { v = (v - pv) / frac; } -inline void +inline void PatchParam::BitField::Rotate( float & u, float & v ) const { switch( GetRotation() ) { case 0 : break; diff --git a/opensubdiv/far/patchTables.cpp b/opensubdiv/far/patchTables.cpp index 6acf87b8..4647fd8f 100644 --- a/opensubdiv/far/patchTables.cpp +++ b/opensubdiv/far/patchTables.cpp @@ -91,6 +91,58 @@ getBSplineWeights(float t, float point[4], float deriv[3]) { } } +void +getBoxSplineWeights(float v, float w, float B[12]) +{ + float u = 1.0f - v - w; + + // + // The 12 basis functions of the quartic box spline (unscaled by their common + // factor of 1/12 until later, and formatted to make it easy to spot any + // typing errors): + // + // 15 terms for the 3 points above the triangle corners + // 9 terms for the 3 points on faces opposite the triangle edges + // 2 terms for the 6 points on faces opposite the triangle corners + // + // Powers of each variable for notational convenience: + float u2 = u*u; + float u3 = u*u2; + float u4 = u*u3; + float v2 = v*v; + float v3 = v*v2; + float v4 = v*v3; + float w2 = w*w; + float w3 = w*w2; + float w4 = w*w3; + + // And now the basis functions: + B[ 0] = u4 + 2.0f*u3*v; + B[ 1] = u4 + 2.0f*u3*w; + B[ 8] = w4 + 2.0f*w3*u; + B[11] = w4 + 2.0f*w3*v; + B[ 9] = v4 + 2.0f*v3*w; + B[ 5] = v4 + 2.0f*v3*u; + + B[ 2] = u4 + 2.0f*u3*w + 6.0f*u3*v + 6.0f*u2*v*w + 12.0f*u2*v2 + + v4 + 2.0f*v3*w + 6.0f*v3*u + 6.0f*v2*u*w; + B[ 4] = w4 + 2.0f*w3*v + 6.0f*w3*u + 6.0f*w2*u*v + 12.0f*w2*u2 + + u4 + 2.0f*u3*v + 6.0f*u3*w + 6.0f*u2*v*w; + B[10] = v4 + 2.0f*v3*u + 6.0f*v3*w + 6.0f*v2*w*u + 12.0f*v2*w2 + + w4 + 2.0f*w3*u + 6.0f*w3*v + 6.0f*w3*u*v; + + B[ 3] = v4 + 6*v3*w + 8*v3*u + 36*v2*w*u + 24*v2*u2 + 24*v*u3 + + w4 + 6*w3*v + 8*w3*u + 36*w2*v*u + 24*w2*u2 + 24*w*u3 + 6*u4 + 60*u2*v*w + 12*v2*w2; + B[ 6] = w4 + 6*w3*u + 8*w3*v + 36*w2*u*v + 24*w2*v2 + 24*w*v3 + + u4 + 6*u3*w + 8*u3*v + 36*u2*v*w + 24*u2*v2 + 24*u*v3 + 6*v4 + 60*v2*w*u + 12*w2*u2; + B[ 7] = u4 + 6*u3*v + 8*u3*w + 36*u2*v*w + 24*u2*w2 + 24*u*w3 + + v4 + 6*v3*u + 8*v3*w + 36*v2*u*w + 24*v2*w2 + 24*v*w3 + 6*w4 + 60*w2*u*v + 12*u2*v2; + + for (int i = 0; i < 12; ++i) { + B[i] *= 1.0f / 12.0f; + } +} + void PatchTables::getBasisWeightsAtUV(TensorBasis basis, PatchParam::BitField bits, float s, float t, float point[16], float deriv1[16], float deriv2[16]) { @@ -164,31 +216,30 @@ PatchTables::getBasisWeightsAtUV(TensorBasis basis, PatchParam::BitField bits, } } -// -// Constructor -// -PatchTables::PatchTables(PatchArrayVector const & patchArrays, - PTable const & patches, - VertexValenceTable const * vertexValences, - QuadOffsetTable const * quadOffsets, - StencilTables const * endcapStencilTables, - PatchParamTable const * patchParams, - FVarPatchTables const * fvarPatchTables, - int maxValence) : - _maxValence(maxValence), - _numPtexFaces(0), - _patchArrays(patchArrays), - _patches(patches), - _endcapStencilTables(endcapStencilTables), - _fvarPatchTables(fvarPatchTables) { +PatchTables::PatchTables(int maxvalence) : + _maxValence(maxvalence), _endcapStencilTables(0), _fvarPatchTables(0) { } - // copy other tables if exist - if (vertexValences) - _vertexValenceTable = *vertexValences; - if (quadOffsets) - _quadOffsetTable = *quadOffsets; - if (patchParams) - _paramTable = *patchParams; +// Copy constructor +// XXXX manuelk we need to eliminate this constructor (C++11 smart pointers) +PatchTables::PatchTables(PatchTables const & src) : + _maxValence(src._maxValence), + _numPtexFaces(src._numPtexFaces), + _patchArrays(src._patchArrays), + _patchVerts(src._patchVerts), + _paramTable(src._paramTable), +#ifdef ENDCAP_TOPOPOLGY + _endcapTopology(src._endcapTopology), +#endif + _quadOffsetsTable(src._quadOffsetsTable), + _vertexValenceTable(src._vertexValenceTable), + _sharpnessIndices(src._sharpnessIndices), + _sharpnessValues(src._sharpnessValues) { + + _endcapStencilTables = src._endcapStencilTables ? + new StencilTables(*src._endcapStencilTables) : 0; + + _fvarPatchTables = src._fvarPatchTables ? + new FVarPatchTables(*src._fvarPatchTables) : 0; } PatchTables::~PatchTables() { @@ -196,149 +247,230 @@ PatchTables::~PatchTables() { delete _fvarPatchTables; } +// +// PatchArrays +// + +struct PatchTables::PatchArray { + + PatchArray(PatchDescriptor d, int np, Index v, Index p, Index qo) : + desc(d), numPatches(np), vertIndex(v), + patchIndex(p), quadOffsetIndex (qo) { } + + PatchDescriptor desc; // type of patches in the array + + int numPatches; // number of patches in the array + + Index vertIndex, // index to the first control vertex + patchIndex, // index of the first patch in the array + quadOffsetIndex; // index of the first quad offset entry +}; + +inline PatchTables::PatchArray & +PatchTables::getPatchArray(Index arrayIndex) { + assert(arrayIndex<(Index)GetNumPatchArrays()); + return _patchArrays[arrayIndex]; +} + +inline PatchTables::PatchArray const & +PatchTables::getPatchArray(Index arrayIndex) const { + assert(arrayIndex<(Index)GetNumPatchArrays()); + return _patchArrays[arrayIndex]; +} + +void +PatchTables::reservePatchArrays(int numPatchArrays) { + _patchArrays.reserve(numPatchArrays); +} + +inline int +getPatchSize(PatchDescriptor desc) { + int size = desc.GetNumControlVertices(); + // XXXX manuelk we do not store the topology for Gregory Basis + // patch types yet - so point to the 4 corners of the 0-ring + if (desc.GetType() == PatchDescriptor::GREGORY_BASIS) { + size = 4; + } + return size; +} + +void +PatchTables::pushPatchArray(PatchDescriptor desc, int npatches, + Index * vidx, Index * pidx, Index * qoidx) { + + if (npatches>0) { + _patchArrays.push_back(PatchArray( + desc, npatches, *vidx, *pidx, qoidx ? *qoidx : 0)); + int nverts = getPatchSize(desc); + *vidx += npatches * nverts; + *pidx += npatches; + if (qoidx) { + *qoidx += (desc.GetType() == PatchDescriptor::GREGORY) ? + npatches*nverts : 0; + } + } +} + +Index * +PatchTables::getSharpnessIndices(int arrayIndex) { + return &_sharpnessIndices[getPatchArray(arrayIndex).patchIndex]; +} + +float * +PatchTables::getSharpnessValues(int arrayIndex) { + return &_sharpnessValues[getPatchArray(arrayIndex).patchIndex]; +} + +PatchDescriptor +PatchTables::GetPatchDescriptor(PatchHandle const & handle) const { + return getPatchArray(handle.arrayIndex).desc; +} + +PatchDescriptor +PatchTables::GetPatchArrayDescriptor(int arrayIndex) const { + return getPatchArray(arrayIndex).desc; +} + +int +PatchTables::GetNumPatchArrays() const { + return (int)_patchArrays.size(); +} +int +PatchTables::GetNumPatches(int arrayIndex) const { + return getPatchArray(arrayIndex).numPatches; +} +int +PatchTables::GetNumControlVertices(int arrayIndex) const { + PatchArray const & pa = getPatchArray(arrayIndex); + return pa.numPatches * getPatchSize(pa.desc); +} + +IndexArray +PatchTables::getPatchArrayVertices(int arrayIndex) { + PatchArray const & pa = getPatchArray(arrayIndex); + int size = getPatchSize(pa.desc); + assert(pa.vertIndex<(Index)_patchVerts.size()); + return IndexArray(&_patchVerts[pa.vertIndex], pa.numPatches * size); +} +IndexArray const +PatchTables::GetPatchArrayVertices(int arrayIndex) const { + PatchArray const & pa = getPatchArray(arrayIndex); + int size = getPatchSize(pa.desc); + assert(pa.vertIndex<(Index)_patchVerts.size()); + return IndexArray(&_patchVerts[pa.vertIndex], pa.numPatches * size); +} + +IndexArray const +PatchTables::GetPatchVertices(PatchHandle const & handle) const { + PatchArray const & pa = getPatchArray(handle.arrayIndex); + + Index vert = pa.vertIndex; + // XXXX manuelk we do not store the topology for Gregory Basis + // patch types yet - so point to the 4 corners of the 0-ring + vert += (pa.desc.GetType() == PatchDescriptor::GREGORY_BASIS) ? + handle.vertIndex / 5 : handle.vertIndex; + assert(vert<(Index)_patchVerts.size()); + return IndexArray(&_patchVerts[vert], getPatchSize(pa.desc)); +} +IndexArray const +PatchTables::GetPatchVertices(int arrayIndex, int patchIndex) const { + PatchArray const & pa = getPatchArray(arrayIndex); + int size = getPatchSize(pa.desc); + assert((pa.vertIndex + patchIndex*size)<(Index)_patchVerts.size()); + return IndexArray(&_patchVerts[pa.vertIndex + patchIndex*size], size); +} + +PatchParam +PatchTables::GetPatchParam(PatchHandle const & handle) const { + assert(handle.patchIndex < (Index)_paramTable.size()); + return _paramTable[handle.patchIndex]; +} +PatchParam +PatchTables::GetPatchParam(int arrayIndex, int patchIndex) const { + PatchArray const & pa = getPatchArray(arrayIndex); + assert((pa.patchIndex + patchIndex) < (int)_paramTable.size()); + return _paramTable[pa.patchIndex + patchIndex]; +} +PatchParamArray +PatchTables::getPatchParams(int arrayIndex) { + PatchArray const & pa = getPatchArray(arrayIndex); + return PatchParamArray(&_paramTable[pa.patchIndex], pa.numPatches); +} +PatchParamArray const +PatchTables::GetPatchParams(int arrayIndex) const { + PatchArray const & pa = getPatchArray(arrayIndex); + return PatchParamArray(&_paramTable[pa.patchIndex], pa.numPatches); +} + +float +PatchTables::GetSingleCreasePatchSharpnessValue(PatchHandle const & handle) const { + assert((handle.patchIndex) < (int)_sharpnessIndices.size()); + Index index = _sharpnessIndices[handle.patchIndex]; + if (index == Vtr::INDEX_INVALID) { + return 0.0f; + } + assert(index < (Index)_sharpnessValues.size()); + return _sharpnessValues[index]; +} +float +PatchTables::GetSingleCreasePatchSharpnessValue(int arrayIndex, int patchIndex) const { + PatchArray const & pa = getPatchArray(arrayIndex); + assert((pa.patchIndex + patchIndex) < (int)_sharpnessIndices.size()); + Index index = _sharpnessIndices[pa.patchIndex + patchIndex]; + if (index == Vtr::INDEX_INVALID) { + return 0.0f; + } + assert(index < (Index)_sharpnessValues.size()); + return _sharpnessValues[index]; +} + +PatchTables::QuadOffsetsArray const +PatchTables::GetPatchQuadOffsets(PatchHandle const & handle) const { + PatchArray const & pa = getPatchArray(handle.arrayIndex); + return Vtr::Array(&_quadOffsetsTable[pa.quadOffsetIndex + handle.vertIndex], 4); +} + +IndexArray +PatchTables::getFVarVerts(int arrayIndex, int channel) { + PatchArray const & pa = getPatchArray(arrayIndex); + assert(_fvarPatchTables and (channel<(int)_fvarPatchTables->_channels.size())); + std::vector & verts = _fvarPatchTables->_channels[channel].patchVertIndices; + int ofs = pa.patchIndex * pa.desc.GetNumFVarControlVertices(); + return IndexArray(&verts[ofs],pa.numPatches * pa.desc.GetNumFVarControlVertices()); +} + bool PatchTables::IsFeatureAdaptive() const { - // the vertex valence table is only used by Gregory patches, so the PatchTables - // contain feature adaptive patches if this is not empty. - if (not _vertexValenceTable.empty()) + // check for presence of tables only used by adaptive patches + if (not _vertexValenceTable.empty() or _endcapStencilTables) return true; // otherwise, we have to check each patch array - PatchArrayVector const & parrays = GetPatchArrayVector(); - for (int i=0; i<(int)parrays.size(); ++i) { - if (parrays[i].GetDescriptor().GetType() >= REGULAR and - parrays[i].GetDescriptor().GetType() <= GREGORY_BASIS) + for (int i=0; i=PatchDescriptor::REGULAR and + desc.GetType()<=PatchDescriptor::GREGORY_BASIS) { return true; + } } return false; } + int PatchTables::GetNumPatchesTotal() const { // there is one PatchParam record for each patch in the mesh - return (int)GetPatchParamTable().size(); + return (int)_paramTable.size(); } -// -// Uniform accessors -// -PatchTables::PatchArray const * -PatchTables::GetUniformPatchArray(int level) const { - - if (IsFeatureAdaptive()) - return NULL; - - PatchArrayVector const & parrays = GetPatchArrayVector(); - - if (parrays.empty()) - return NULL; - - if (level < 1) { - return &(*parrays.rbegin()); - } else if ((level-1) < (int)parrays.size() ) { - return &parrays[level-1]; - } - - return NULL; -} -Index const * -PatchTables::GetUniformFaceVertices(int level) const { - - PatchArray const * parray = GetUniformPatchArray(level); - - if (parray) { - return &GetPatchTable()[ parray->GetVertIndex() ]; - } - return NULL; -} -int -PatchTables::GetNumUniformFaces(int level) const { - - PatchArray const * parray = GetUniformPatchArray(level); - - if (parray) { - return parray->GetNumPatches(); - } - return -1; -} - -// -// Returns a pointer to the array of patches matching the descriptor -// -PatchTables::PatchArray * -PatchTables::findPatchArray( PatchTables::Descriptor desc ) { - +// Returns the first array of patches matching the descriptor +Index +PatchTables::findPatchArray(PatchDescriptor desc) { for (int i=0; i<(int)_patchArrays.size(); ++i) { - if (_patchArrays[i].GetDescriptor()==desc) - return &_patchArrays[i]; + if (_patchArrays[i].desc==desc) + return i; } - return 0; -} - - -// -// Lists of patch Descriptors for each subdivision scheme -// -PatchTables::DescriptorVector const & -PatchTables::getAdaptiveCatmarkDescriptors() { - - static DescriptorVector _descriptors; - - if (_descriptors.empty()) { - - _descriptors.reserve(71); - - // non-transition patches : 6 - for (int i=REGULAR; i<=GREGORY_BASIS; ++i) { - _descriptors.push_back( Descriptor(i, NON_TRANSITION, 0) ); - } - - // transition patches (1 + 4 * 3) * 5 = 65 - for (int i=PATTERN0; i<=PATTERN4; ++i) { - - _descriptors.push_back( Descriptor(REGULAR, i, 0) ); - - // 4 rotations for single-crease, boundary and corner patches - for (int j=0; j<4; ++j) { - _descriptors.push_back( Descriptor(SINGLE_CREASE, i, j) ); - } - - for (int j=0; j<4; ++j) { - _descriptors.push_back( Descriptor(BOUNDARY, i, j) ); - } - - for (int j=0; j<4; ++j) { - _descriptors.push_back( Descriptor(CORNER, i, j) ); - } - } - } - return _descriptors; -} - -PatchTables::DescriptorVector const & -PatchTables::getAdaptiveLoopDescriptors() { - - static DescriptorVector _descriptors; - - if (_descriptors.empty()) { - _descriptors.reserve(1); - _descriptors.push_back( Descriptor(LOOP, NON_TRANSITION, 0) ); - } - return _descriptors; -} - -PatchTables::DescriptorVector const & -PatchTables::GetAdaptiveDescriptors(Sdc::Type type) { - - static DescriptorVector _empty; - - switch (type) { - case Sdc::TYPE_CATMARK : return getAdaptiveCatmarkDescriptors(); - case Sdc::TYPE_LOOP : return getAdaptiveLoopDescriptors(); - default: - assert(0); - } - return _empty; + return Vtr::INDEX_INVALID; } } // end namespace Far diff --git a/opensubdiv/far/patchTables.h b/opensubdiv/far/patchTables.h index c0830dfb..8f3e3993 100644 --- a/opensubdiv/far/patchTables.h +++ b/opensubdiv/far/patchTables.h @@ -27,12 +27,11 @@ #include "../version.h" +#include "../far/patchDescriptor.h" #include "../far/patchParam.h" #include "../far/stencilTables.h" #include "../far/types.h" -#include "../sdc/type.h" - #include #include #include @@ -44,349 +43,197 @@ namespace OPENSUBDIV_VERSION { namespace Far { -/// \brief Container for patch vertex indices tables +/// \brief Container for arrays of parametric patches /// -/// PatchTables contain the lists of vertices for each patch of an adaptive -/// mesh representation. +/// PatchTables contain topology and parametric information about the patches +/// generated by the Refinement process. Patches in the tables are sorted into +/// arrays based on their PatchDescriptor Type. /// class PatchTables { public: - typedef std::vector PTable; - typedef std::vector VertexValenceTable; - typedef std::vector QuadOffsetTable; - typedef std::vector PatchParamTable; - - enum Type { - NON_PATCH = 0, ///< undefined - - POINTS, ///< points (useful for cage drawing) - LINES, ///< lines (useful for cage drawing) - - QUADS, ///< bilinear quads-only patches - TRIANGLES, ///< bilinear triangles-only mesh - - LOOP, ///< Loop patch (currently unsupported) - - REGULAR, ///< feature-adaptive bicubic patches - SINGLE_CREASE, - BOUNDARY, - CORNER, - GREGORY, - GREGORY_BOUNDARY, - GREGORY_BASIS - }; - - enum TransitionPattern { - NON_TRANSITION = 0, - PATTERN0, - PATTERN1, - PATTERN2, - PATTERN3, - PATTERN4 - }; - -public: - - /// \brief Describes the type of a patch - /// - /// Uniquely identifies all the types of patches in a mesh : - /// - /// * Raw polygon meshes are identified as POLYGONS and can contain faces - /// with arbitrary number of vertices - /// - /// * Uniformly subdivided meshes contain bilinear patches of either QUADS - /// or TRIANGLES - /// - /// * Adaptively subdivided meshes contain bicubic patches of types REGULAR, - /// BOUNDARY, CORNER, GREGORY, GREGORY_BOUNDARY. These bicubic patches are - /// also further distinguished by a transition pattern as well as a rotational - /// orientation. - /// - class Descriptor { - - public: - /// \brief Default constructor. - Descriptor() : - _type(NON_PATCH), _pattern(NON_TRANSITION), _rotation(0) {} - - /// \brief Constructor - Descriptor(int type, int pattern, unsigned char rotation) : - _type(type), _pattern(pattern), _rotation(rotation) { } - - /// \brief Copy Constructor - Descriptor( Descriptor const & d ) : - _type(d.GetType()), _pattern(d.GetPattern()), _rotation(d.GetRotation()) { } - - /// \brief Returns the type of the patch - Type GetType() const { - return (Type)_type; - } - - /// \brief Returns the transition pattern of the patch if any (5 types) - TransitionPattern GetPattern() const { - return (TransitionPattern)_pattern; - } - - /// \brief Returns the rotation of the patch (4 rotations) - unsigned char GetRotation() const { - return (unsigned char)_rotation; - } - - /// \brief Returns the number of control vertices expected for a patch of the - /// type described - static inline short GetNumControlVertices( Type t ); - - static inline short GetNumFVarControlVertices( Type t ); - - /// \brief Returns the number of control vertices expected for a patch of the - /// type described - short GetNumControlVertices() const { - return GetNumControlVertices( this->GetType() ); - } - - /// \brief Returns the number of control vertices expected for a patch of the - /// type described - short GetNumFVarControlVertices() const { - return GetNumFVarControlVertices( this->GetType() ); - } - - /// \brief Allows ordering of patches by type - inline bool operator < ( Descriptor const other ) const; - - /// \brief True if the descriptors are identical - inline bool operator == ( Descriptor const other ) const; - - private: - friend class PatchTablesFactory; - - unsigned int _type:4; - unsigned int _pattern:3; - unsigned int _rotation:2; - }; - - typedef std::vector DescriptorVector; - - /// \brief Returns a vector of all the legal patch descriptors for the - /// given adaptive subdivision scheme - static DescriptorVector const & GetAdaptiveDescriptors(Sdc::Type type); - - -public: - - /// \brief Array of patches of the same type - class PatchArray { - - public: - /// \brief Constructor. - /// - /// @param desc descriptor information for the patches in - /// the array - /// - /// @param vertIndex absolute index to the first control vertex - /// of the first patch in the PTable - /// - /// @param patchIndex absolute index of the first patch in the - /// array - /// - /// @param npatches number of patches in the array - /// - /// @param quadOffsetIndex absolute index of the first quad offset - /// entry - /// - PatchArray( Descriptor desc, Index vertIndex, Index patchIndex, - Index npatches, Index quadOffsetIndex ) : - _desc(desc), _range(vertIndex, patchIndex, npatches, quadOffsetIndex) { } - - /// Returns a patch descriptor defining the type of patches in the array - Descriptor GetDescriptor() const { - return _desc; - } - - /// \brief Describes the range of patches in a PatchArray - struct ArrayRange { - - /// \brief Constructor - /// - /// @param vIndex absolute index to the first control vertex - /// of the first patch in the PTable - /// - /// @param pIndex absolute index of the first patch in the - /// array - /// - /// @param npatches number of patches in the array - /// - /// @param qoIndex absolute index of the first quad offset - /// entry - /// - ArrayRange( Index vIndex, Index pIndex, int npatches, Index qoIndex ) : - npatches(npatches), vertIndex(vIndex), patchIndex(pIndex), - quadOffsetIndex(qoIndex) { } - - int npatches; ///< number of patches in the array - - Index vertIndex, ///< absolute index to the first control vertex of the first patch in the PTable - patchIndex, ///< absolute index of the first patch in the array - quadOffsetIndex; ///< absolute index of the first quad offset entry - }; - - /// \brief Returns a array range struct - ArrayRange const & GetArrayRange() const { - return _range; - } - - /// \brief Returns the index of the first control vertex of the first patch - /// of this array in the global PTable - Index GetVertIndex() const { - return _range.vertIndex; - } - - /// \brief Returns the global index of the first patch in this array (Used to - /// access param / fvar table data) - Index GetPatchIndex() const { - return _range.patchIndex; - } - - /// \brief Returns the number of patches in the array - int GetNumPatches() const { - return _range.npatches; - } - - /// \brief Returns the index to the first entry in the QuadOffsetTable - Index GetQuadOffsetIndex() const { - return _range.quadOffsetIndex; - } - - private: - friend class PatchTablesFactory; - - Descriptor _desc; // type of patches in the array - - ArrayRange _range; // index locators in the array - }; - - typedef std::vector PatchArrayVector; - /// \brief Handle that can be used as unique patch identifier within PatchTables - struct PatchHandle { - Index patchArrayIdx, ///< OsdPatchArray containing the patch - patchIdx, ///< Index of the patch in the OsdPatchArray - vertexOffset; ///< Relative offset to the first CV of the patch in the patch array + class PatchHandle { + // XXXX manuelk members will eventually be private once FVar + // interpolation is implemented fully + public: + + friend class PatchTables; + friend class PatchMap; + + Index arrayIndex, // Array index of the patch + patchIndex, // Absolute Index of the patch + vertIndex; // Relative offset to the first CV of the patch in array }; - /// \brief Get the table of patch control vertices - PTable const & GetPatchTable() const { return _patches; } +public: - /// \brief Returns a pointer to the array of patches matching the descriptor - PatchArray const * GetPatchArray( Descriptor desc ) const { - return const_cast(this)->findPatchArray( desc ); - } + /// \brief Copy constructor + PatchTables(PatchTables const & src); - /// \brief Returns all arrays of patches - PatchArrayVector const & GetPatchArrayVector() const { - return _patchArrays; - } - - /// brief Returns a pointer to the PatchArry of uniformly subdivided faces at 'level' - /// - /// @param level the level of subdivision of the faces (returns the highest - /// level by default) - /// - /// @return a pointer to the PatchArray or NULL if the mesh is not uniformly - /// subdivided or the level cannot be found. - /// - PatchArray const * GetUniformPatchArray(int level=0) const; - - /// \brief Returns a pointer to the vertex indices of uniformly subdivided faces - /// - /// In uniform mode the PatchTablesFactory can be set to generate either a - /// patch array containing the faces at the highest level of subdivision, or - /// a range of arrays, corresponding to multiple successive levels of subdivision. - /// - /// Note : level '0' is not the coarse mesh. Currently there is no path in the - /// factories to convert the coarse mesh to PatchTables. - /// - /// @param level the level of subdivision of the faces (returns the highest - /// level by default) - /// - /// @return a pointer to the first vertex index or NULL if the mesh - /// is not uniformly subdivided or the level cannot be found. - /// - Index const * GetUniformFaceVertices(int level=0) const; - - /// \brief Returns the number of faces in a uniformly subdivided mesh at a given level - /// - /// In uniform mode the PatchTablesFactory can be set to generate either a - /// patch array containing the faces at the highest level of subdivision, or - /// a range of arrays, corresponding to multiple successive levels of subdivision. - /// - /// Note : level '0' is not the coarse mesh. Currently there is no path in the - /// factories to convert the coarse mesh to PatchTables. - /// - /// @param level the level of subdivision of the faces (returns the highest - /// level by default) - /// - /// @return the number of faces in the mesh given the subdivision level - /// or -1 if the mesh is not uniform or the level is incorrect. - /// - int GetNumUniformFaces(int level=0) const; - - /// \brief Returns a vertex valence table used by Gregory patches - VertexValenceTable const & GetVertexValenceTable() const { return _vertexValenceTable; } - - /// \brief Returns a quad offsets table used by Gregory patches - QuadOffsetTable const & GetQuadOffsetTable() const { return _quadOffsetTable; } - - /// \brief Returns a stencil table for the control vertices of end-cap patches - StencilTables const * GetEndCapStencilTables() const { return _endcapStencilTables; } - - /// \brief Returns a PatchParamTable for each type of patch - PatchParamTable const & GetPatchParamTable() const { return _paramTable; } - - /// \brief Returns a sharpness index table for each type of patch (if exists) - std::vector const &GetSharpnessIndexTable() const { return _sharpnessIndexTable; } - - /// \brief Returns sharpness values (if exists) - std::vector const &GetSharpnessValues() const { return _sharpnessValues; } - - /// \brief Number of control vertices of Regular Patches in table. - static short GetRegularPatchSize() { return 16; } - - /// \brief Number of control vertices of Boundary Patches in table. - static short GetBoundaryPatchSize() { return 12; } - - /// \brief Number of control vertices of Boundary Patches in table. - static short GetCornerPatchSize() { return 9; } - - /// \brief Number of control vertices of Gregory (and Gregory Boundary) Patches in table. - static short GetGregoryPatchSize() { return 4; } - - /// \brief Number of control vertices of Gregory patch basis (20) - static short GetGregoryBasisSize() { return 20; } - - /// \brief Returns the total number of patches stored in the tables - int GetNumPatchesTotal() const; - - /// \brief Returns the total number of control vertex indices in the tables - int GetNumControlVerticesTotal() const { - return (int)_patches.size(); - } - - /// \brief Returns max vertex valence - int GetMaxValence() const { return _maxValence; } + /// \brief Destructor + ~PatchTables(); /// \brief True if the patches are of feature adaptive types bool IsFeatureAdaptive() const; - /// \brief Returns the total number of vertices in the mesh across across all depths + /// \brief Returns the total number of control vertex indices in the tables + int GetNumControlVerticesTotal() const { + return (int)_patchVerts.size(); + } + + /// \brief Returns the total number of patches stored in the tables + int GetNumPatchesTotal() const; + + /// \brief Returns max vertex valence + int GetMaxValence() const { return _maxValence; } + + /// \brief Returns the total number of ptex faces in the mesh int GetNumPtexFaces() const { return _numPtexFaces; } + + //@{ + /// @name Direct accessors + /// + /// \warning These direct accessors are left for convenience, but they are + /// likely going to be deprecated in future releases + /// + + typedef std::vector PatchVertsTable; + + /// \brief Get the table of patch control vertices + PatchVertsTable const & GetPatchControlVerticesTable() const { return _patchVerts; } + + /// \brief Returns the PatchParamTable (PatchParams order matches patch array sorting) + PatchParamTable const & GetPatchParamTable() const { return _paramTable; } + + /// \brief Returns a sharpness index table for each patch (if exists) + std::vector const &GetSharpnessIndexTable() const { return _sharpnessIndices; } + + /// \brief Returns sharpness values table + std::vector const &GetSharpnessValues() const { return _sharpnessValues; } + + typedef std::vector QuadOffsetsTable; + + /// \brief Returns the quad-offsets table + QuadOffsetsTable const & GetQuadOffsetsTable() const { + return _quadOffsetsTable; + } + //@} + + //@{ + /// @name Individual patches + /// + /// \anchor individual_patches + /// + /// \brief Accessors for individual patches + /// + + /// \brief Returns the PatchDescriptor for the patches in array 'array' + PatchDescriptor GetPatchDescriptor(PatchHandle const & handle) const; + + /// \brief Returns the control vertex indices for the patch identified by 'handle' + IndexArray const GetPatchVertices(PatchHandle const & handle) const; + + /// \brief Returns a PatchParam for the patch identified by 'handle' + PatchParam GetPatchParam(PatchHandle const & handle) const; + + /// \brief Returns the control vertex indices for the patch 'patch' in array 'array' + IndexArray const GetPatchVertices(int array, int patch) const; + + /// \brief Returns the PatchParam for the patch 'patch' in array 'array' + PatchParam GetPatchParam(int array, int patch) const; + //@} + + + //@{ + /// @name Arrays of patches + /// + /// \anchor arrays_of_patches + /// + /// \brief Accessors for arrays of patches of the same type + /// + + /// \brief Returns the number of patch arrays in the table + int GetNumPatchArrays() const; + + /// \brief Returns the number of patches in patch array 'array' + int GetNumPatches(int array) const; + + /// \brief Returns the number of control vertices in patch array 'array' + int GetNumControlVertices(int array) const; + + /// \brief Returns the PatchDescriptor for the patches in array 'array' + PatchDescriptor GetPatchArrayDescriptor(int array) const; + + /// \brief Returns the control vertex indices for the patches in array 'array' + IndexArray const GetPatchArrayVertices(int array) const; + + /// \brief Returns the PatchParams for the patches in array 'array' + PatchParamArray const GetPatchParams(int array) const; + //@} + + + //@{ + /// @name End-Cap patches + /// + /// \anchor end_cap_patches + /// + /// \brief Accessors for end-cap patch additional data + /// + + typedef Vtr::Array QuadOffsetsArray; + + /// \brief Returns the 'QuadOffsets' for the Gregory patch identified by 'handle' + QuadOffsetsArray const GetPatchQuadOffsets(PatchHandle const & handle) const; + + typedef std::vector VertexValenceTable; + + /// \brief Returns the 'VertexValences' table (vertex neighborhoods table) + VertexValenceTable const & GetVertexValenceTable() const { + return _vertexValenceTable; + } + + /// \brief Returns a stencil table for the control vertices of end-cap patches + StencilTables const * GetEndCapStencilTables() const { return _endcapStencilTables; } + + Index GetEndCapStencilIndex(PatchHandle const & handle) const { + return handle.vertIndex; + } + //@} + + + //@{ + /// @name Single-crease patches + /// + /// \anchor single_crease_patches + /// + /// \brief Accessors for single-crease patch edge sharpness + /// + + /// \brief Returns the crease sharpness for the patch identified by 'handle' + /// if it is a single-crease patch, or 0.0f + float GetSingleCreasePatchSharpnessValue(PatchHandle const & handle) const; + + /// \brief Returns the crease sharpness for the patch 'patch' in array 'array' + /// if it is a single-crease patch, or 0.0f + float GetSingleCreasePatchSharpnessValue(int array, int patch) const; + //@} + + //@{ + /// @name Face-varying + /// + /// \anchor face_varying + /// /// \brief Face-varying patch vertex indices tables /// /// FVarPatchTables contain the topology for face-varying primvar data /// channels. The patch ordering matches that of PatchTables PatchArrays. /// + /// \note bi-cubic face-varying limit interpolation is not implemented yet : + /// this code will change soon + /// class FVarPatchTables { public: @@ -405,6 +252,7 @@ public: } private: + friend class PatchTables; friend class PatchTablesFactory; struct Channel { @@ -413,42 +261,14 @@ public: std::vector patchVertIndices; // face-varying vertex indices }; + private: + std::vector _channels; // face-varying primvar channels }; /// \brief Returns the face-varying patches FVarPatchTables const * GetFVarPatchTables() const { return _fvarPatchTables; } - - /// \brief Public constructor - /// - /// @param patchArrays Vector of descriptors and ranges for arrays of patches - /// - /// @param patches Indices of the control vertices of the patches - /// - /// @param vertexValences Vertex valance table - /// - /// @param quadOffsets Quad offset table - /// - /// @param endcapStencilTables StencilTables used to generate the 20 CV basis - /// of Gregory patches - /// - /// @param fvarPatchTables Indices of the face-varying control vertices of the patches - /// - /// @param patchParams Local patch parameterization - /// - /// @param maxValence Highest vertex valence allowed in the mesh - /// - PatchTables(PatchArrayVector const & patchArrays, - PTable const & patches, - VertexValenceTable const * vertexValences, - QuadOffsetTable const * quadOffsets, - StencilTables const * endcapStencilTables, - PatchParamTable const * patchParams, - FVarPatchTables const * fvarPatchTables, - int maxValence); - - /// \brief Destructor - ~PatchTables(); + //@} public: @@ -592,10 +412,13 @@ public: template void Limit(PatchHandle const & handle, float s, float t, T const & src, U & dst) const; -private: +protected: friend class PatchTablesFactory; + // Factory constructor + PatchTables(int maxvalence); + enum TensorBasis { BASIS_BEZIER, BASIS_BSPLINE @@ -606,21 +429,38 @@ private: static void getBasisWeightsAtUV(TensorBasis basis, PatchParam::BitField bits, float s, float t, float point[16], float deriv1[16], float deriv2[16]); -private: +protected: - // Returns the array of patches of type "desc", or NULL if there aren't any in the primitive - PatchArray * findPatchArray( Descriptor desc ); + void reservePatchArrays(int numPatchArrays); - static DescriptorVector const & getBilinearDescriptors(); - static DescriptorVector const & getAdaptiveCatmarkDescriptors(); - static DescriptorVector const & getAdaptiveLoopDescriptors(); + void pushPatchArray(PatchDescriptor desc, + int npatches, Index * vidx, Index * pidx, Index * qoidx=0); - // Factory constructor - PatchTables(int maxvalence) : _maxValence(maxvalence), - _endcapStencilTables(0), _fvarPatchTables(0) { } + Index findPatchArray(PatchDescriptor desc); + + IndexArray getPatchArrayVertices(int arrayIndex); + PatchParamArray getPatchParams(int arrayIndex); + + Index * getSharpnessIndices(Index arrayIndex); + float * getSharpnessValues(Index arrayIndex); + + IndexArray getFVarVerts(int arrayIndex, int channel); private: + // + // Patch arrays + // + + struct PatchArray; + + PatchArray & getPatchArray(Index arrayIndex); + PatchArray const & getPatchArray(Index arrayIndex) const; + +private: + + typedef std::vector PatchArrayVector; + // // Topology // @@ -629,7 +469,9 @@ private: _numPtexFaces; // total number of ptex faces PatchArrayVector _patchArrays; // Vector of descriptors for arrays of patches - PTable _patches; // Indices of the control vertices of the patches + + std::vector _patchVerts; // Indices of the control vertices of the patches + PatchParamTable _paramTable; // PatchParam bitfields (one per patch) // @@ -640,81 +482,25 @@ private: StencilTables const * _endcapStencilTables; #ifdef ENDCAP_TOPOPOLGY - PTable _endcapTopology; + std::vector _endcapTopology; #endif + QuadOffsetsTable _quadOffsetsTable; // Quad offsets (for Gregory patches) VertexValenceTable _vertexValenceTable; // Vertex valence table (for Gregory patches) - QuadOffsetTable _quadOffsetTable; // Quad offsets table (for Gregory patches) // // Face-varying data // - FVarPatchTables const * _fvarPatchTables; // sparse face-varying patch table (one per patch) + FVarPatchTables * _fvarPatchTables; // sparse face-varying patch table (one per patch) // // 'single-crease' patch sharpness tables // - std::vector _sharpnessIndexTable; // Indices of single-crease sharpness (one per patch) - std::vector _sharpnessValues; // Sharpness values. - - + std::vector _sharpnessIndices; // Indices of single-crease sharpness (one per patch) + std::vector _sharpnessValues; // Sharpness values. }; -// Returns the number of control vertices expected for a patch of this type -inline short -PatchTables::Descriptor::GetNumControlVertices( PatchTables::Type type ) { - switch (type) { - case REGULAR : return PatchTables::GetRegularPatchSize(); - case SINGLE_CREASE : return PatchTables::GetRegularPatchSize(); - case QUADS : return 4; - case GREGORY : - case GREGORY_BOUNDARY : return PatchTables::GetGregoryPatchSize(); - case GREGORY_BASIS : return PatchTables::GetGregoryBasisSize(); - case BOUNDARY : return PatchTables::GetBoundaryPatchSize(); - case CORNER : return PatchTables::GetCornerPatchSize(); - case TRIANGLES : return 3; - case LINES : return 2; - case POINTS : return 1; - default : return -1; - } -} - -// Returns the number of face-varying control vertices expected for a patch of this type -inline short -PatchTables::Descriptor::GetNumFVarControlVertices( PatchTables::Type type ) { - switch (type) { - case REGULAR : // We only support bilinear interpolation for now, - case SINGLE_CREASE : - case QUADS : // so all these patches only carry 4 CVs. - case GREGORY : - case GREGORY_BOUNDARY : - case GREGORY_BASIS : - case BOUNDARY : - case CORNER : return 4; - case TRIANGLES : return 3; - case LINES : return 2; - case POINTS : return 1; - default : return -1; - } -} - -// Allows ordering of patches by type -inline bool -PatchTables::Descriptor::operator < ( Descriptor const other ) const { - return _pattern < other._pattern or ((_pattern == other._pattern) and - (_type < other._type or ((_type == other._type) and - (_rotation < other._rotation)))); -} - -// True if the descriptors are identical -inline bool -PatchTables::Descriptor::operator == ( Descriptor const other ) const { - return _pattern == other._pattern and - _type == other._type and - _rotation == other._rotation; -} - template inline void PatchTables::InterpolateBilinear(Index const * cvs, float s, float t, @@ -934,22 +720,16 @@ PatchTables::Interpolate(PatchHandle const & handle, float s, float t, assert(not IsFeatureAdaptive()); - PatchTables::PatchArray const & parray = - _patchArrays[handle.patchArrayIdx]; - assert(parray.GetDescriptor().GetType()==QUADS); - - Index const * cvs = - &_patches[parray.GetVertIndex() + handle.vertexOffset]; + IndexArray cvs = GetPatchVertices(handle); PatchParam::BitField const & bits = - _paramTable[handle.patchIdx].bitField; - + _paramTable[handle.patchIndex].bitField; bits.Normalize(s,t); dst.Clear(); - InterpolateBilinear(cvs, s, t, src, dst); + InterpolateBilinear(cvs.begin(), s, t, src, dst); } // Interpolates the limit position of a parametric location on a patch @@ -960,54 +740,50 @@ PatchTables::Limit(PatchHandle const & handle, float s, float t, assert(IsFeatureAdaptive()); - PatchTables::PatchArray const & parray = - _patchArrays[handle.patchArrayIdx]; - - PatchParam::BitField const & bits = - _paramTable[handle.patchIdx].bitField; + PatchParam::BitField const & bits = _paramTable[handle.patchIndex].bitField; bits.Normalize(s,t); - Type ptype = parray.GetDescriptor().GetType(); + PatchDescriptor::Type ptype = + GetPatchArrayDescriptor(handle.arrayIndex).GetType(); dst.Clear(); float Q[16], Qd1[16], Qd2[16]; - if (ptype>=REGULAR and ptype<=CORNER) { + if (ptype>=PatchDescriptor::REGULAR and ptype<=PatchDescriptor::CORNER) { getBasisWeightsAtUV(BASIS_BSPLINE, bits, s, t, Q, Qd1, Qd2); - Index const * cvs = - &_patches[parray.GetVertIndex() + handle.vertexOffset]; + IndexArray cvs = GetPatchVertices(handle); switch (ptype) { - case REGULAR: - InterpolateRegularPatch(cvs, Q, Qd1, Qd2, src, dst); + case PatchDescriptor::REGULAR: + InterpolateRegularPatch(cvs.begin(), Q, Qd1, Qd2, src, dst); break; - case SINGLE_CREASE: + case PatchDescriptor::SINGLE_CREASE: // TODO: implement InterpolateSingleCreasePatch(). //InterpolateRegularPatch(cvs, Q, Qd1, Qd2, src, dst); break; - case BOUNDARY: - InterpolateBoundaryPatch(cvs, Q, Qd1, Qd2, src, dst); + case PatchDescriptor::BOUNDARY: + InterpolateBoundaryPatch(cvs.begin(), Q, Qd1, Qd2, src, dst); break; - case CORNER: - InterpolateCornerPatch(cvs, Q, Qd1, Qd2, src, dst); + case PatchDescriptor::CORNER: + InterpolateCornerPatch(cvs.begin(), Q, Qd1, Qd2, src, dst); break; - case GREGORY: - case GREGORY_BOUNDARY: + case PatchDescriptor::GREGORY: + case PatchDescriptor::GREGORY_BOUNDARY: assert(0); break; default: assert(0); } - } else if (ptype==GREGORY_BASIS) { + } else if (ptype==PatchDescriptor::GREGORY_BASIS) { assert(_endcapStencilTables); getBasisWeightsAtUV(BASIS_BEZIER, bits, s, t, Q, Qd1, Qd2); - InterpolateGregoryPatch(_endcapStencilTables, handle.vertexOffset, + InterpolateGregoryPatch(_endcapStencilTables, handle.vertIndex, s, t, Q, Qd1, Qd2, src, dst); } else { diff --git a/opensubdiv/far/patchTablesFactory.cpp b/opensubdiv/far/patchTablesFactory.cpp index 8ff15b00..c301246c 100644 --- a/opensubdiv/far/patchTablesFactory.cpp +++ b/opensubdiv/far/patchTablesFactory.cpp @@ -58,15 +58,15 @@ struct PatchTypes { PatchTypes() { std::memset(this, 0, sizeof(PatchTypes)); } // Returns the number of patches based on the patch type in the descriptor - TYPE & getValue( PatchTables::Descriptor desc ) { + TYPE & getValue( PatchDescriptor desc ) { switch (desc.GetType()) { - case PatchTables::REGULAR : return R[desc.GetPattern()]; - case PatchTables::SINGLE_CREASE : return S[desc.GetPattern()][desc.GetRotation()]; - case PatchTables::BOUNDARY : return B[desc.GetPattern()][desc.GetRotation()]; - case PatchTables::CORNER : return C[desc.GetPattern()][desc.GetRotation()]; - case PatchTables::GREGORY : return G; - case PatchTables::GREGORY_BOUNDARY : return GB; - case PatchTables::GREGORY_BASIS : return GP; + case PatchDescriptor::REGULAR : return R[desc.GetPattern()]; + case PatchDescriptor::SINGLE_CREASE : return S[desc.GetPattern()][desc.GetRotation()]; + case PatchDescriptor::BOUNDARY : return B[desc.GetPattern()][desc.GetRotation()]; + case PatchDescriptor::CORNER : return C[desc.GetPattern()][desc.GetRotation()]; + case PatchDescriptor::GREGORY : return G; + case PatchDescriptor::GREGORY_BOUNDARY : return GB; + case PatchDescriptor::GREGORY_BASIS : return GP; default : assert(0); } // can't be reached (suppress compiler warning) @@ -386,52 +386,27 @@ namespace { } } // namespace anon - -// Indirection for number of control vertices for a given patch to allow -// override for patch types with dynamic basis (like stencil-based Gregory -// end caps) -static int -GetNumControlVertices(PatchTables::Descriptor const & desc) { - - int result = desc.GetNumControlVertices(); - - // The Gregory basis patch uses 20 control vertices generated from - // a dedicated stencil table which stores its vertex indices. However, - // for varying interpolation, we need the vertex indices of the 0-ring - // stored in the _patches indexing table. - if (desc.GetType()==PatchTables::GREGORY_BASIS) { - result = 4; - } - return result; -} - // // Reserves tables based on the contents of the PatchArrayVector in the PatchTables: // void PatchTablesFactory::allocateTables(PatchTables * tables, int /* nlevels */, bool hasSharpness) { - PatchTables::PatchArrayVector const & parrays = tables->GetPatchArrayVector(); - int ncvs = 0, npatches = 0; - for (int i=0; i<(int)parrays.size(); ++i) { - - int nps = parrays[i].GetNumPatches(), - ringsize = GetNumControlVertices(parrays[i].GetDescriptor()); - - npatches += nps; - ncvs += ringsize * nps; + for (int i=0; iGetNumPatchArrays(); ++i) { + npatches += tables->GetNumPatches(i); + ncvs += tables->GetNumControlVertices(i); } if (ncvs==0 or npatches==0) return; - tables->_patches.resize( ncvs ); + tables->_patchVerts.resize( ncvs ); tables->_paramTable.resize( npatches ); if (hasSharpness) { - tables->_sharpnessIndexTable.resize( npatches ); + tables->_sharpnessIndices.resize( npatches, Vtr::INDEX_INVALID ); } } @@ -441,8 +416,6 @@ PatchTablesFactory::allocateFVarTables( TopologyRefiner const & refiner, assert( refiner.GetNumFVarChannels()>0 ); - PatchTables::PatchArrayVector const & parrays = tables.GetPatchArrayVector(); - FVarPatchTables * fvarTables = new FVarPatchTables; fvarTables->_channels.resize( refiner.GetNumFVarChannels() ); @@ -458,11 +431,11 @@ PatchTablesFactory::allocateFVarTables( TopologyRefiner const & refiner, refiner.GetNumFacesTotal() : refiner.GetNumFaces(maxlevel); - assert(not parrays.empty()); - nverts *= parrays[0].GetDescriptor().GetNumFVarControlVertices(); - if (options.triangulateQuads) + assert(tables.GetNumPatchArrays()>0); + nverts *= tables.GetPatchArrayDescriptor(0).GetNumFVarControlVertices(); + if (options.triangulateQuads) { nverts *= 2; - + } assert(nverts>0); fvarTables->_channels[channel].patchVertIndices.resize(nverts); } @@ -471,9 +444,9 @@ PatchTablesFactory::allocateFVarTables( TopologyRefiner const & refiner, assert( tables.IsFeatureAdaptive() ); int nverts=0; - for (int i=0; i<(int)parrays.size(); ++i) { - nverts += parrays[i].GetNumPatches() * - parrays[i].GetDescriptor().GetNumFVarControlVertices(); + for (int i=0; i0); @@ -485,22 +458,6 @@ PatchTablesFactory::allocateFVarTables( TopologyRefiner const & refiner, return fvarTables; } -// -// Creates a PatchArray and appends it to a vector and keeps track of both -// vertex and patch offsets -// -void -PatchTablesFactory::pushPatchArray( PatchTables::Descriptor desc, - PatchTables::PatchArrayVector & parray, - int npatches, int * voffset, int * poffset, int * qoffset ) { - if (npatches>0) { - parray.push_back( PatchTables::PatchArray(desc, *voffset, *poffset, npatches, *qoffset) ); - *voffset += npatches * GetNumControlVertices(desc); - *qoffset += (desc.GetType() == PatchTables::GREGORY) ? npatches * GetNumControlVertices(desc) : 0; - *poffset += npatches; - } -} - // // Populates the face-varying data buffer 'coord' for the given face, returning // a pointer to the next descriptor @@ -647,12 +604,13 @@ gatherGregoryBasisTopology(Vtr::Level const& level, Index faceIndex, int numVert return numVertices; } #endif + // // Populate the quad-offsets table used by Gregory patches // void PatchTablesFactory::getQuadOffsets( - Vtr::Level const& level, Index faceIndex, Index offsets[]) { + Vtr::Level const& level, Index faceIndex, unsigned int offsets[]) { Vtr::IndexArray fVerts = level.getFaceVertices(faceIndex); @@ -736,27 +694,19 @@ PatchTablesFactory::createUniform( TopologyRefiner const & refiner, Options opti int maxvalence = refiner.getLevel(0).getMaxValence(), maxlevel = refiner.GetMaxLevel(), firstlevel = options.generateAllLevels ? 0 : maxlevel, - nlevels = maxlevel-firstlevel+1, - nCVs = 0; + nlevels = maxlevel-firstlevel+1; - PatchTables::Type ptype = PatchTables::NON_PATCH; + PatchDescriptor::Type ptype = PatchDescriptor::NON_PATCH; if (options.triangulateQuads) { - ptype = PatchTables::TRIANGLES; + ptype = PatchDescriptor::TRIANGLES; } else { switch (refiner.GetSchemeType()) { case Sdc::TYPE_BILINEAR : - case Sdc::TYPE_CATMARK : ptype = PatchTables::QUADS; break; - case Sdc::TYPE_LOOP : ptype = PatchTables::TRIANGLES; break; + case Sdc::TYPE_CATMARK : ptype = PatchDescriptor::QUADS; break; + case Sdc::TYPE_LOOP : ptype = PatchDescriptor::TRIANGLES; break; } } - assert(ptype!=PatchTables::NON_PATCH); - - switch (ptype) { - case PatchTables::TRIANGLES: nCVs=3; break; - case PatchTables::QUADS: nCVs=4; break; - default: - assert(0); - } + assert(ptype!=PatchDescriptor::NON_PATCH); // // Create the instance of the tables and allocate and initialize its members. @@ -765,10 +715,9 @@ PatchTablesFactory::createUniform( TopologyRefiner const & refiner, Options opti tables->_numPtexFaces = refiner.GetNumPtexFaces(); - PatchTables::PatchArrayVector & parrays = tables->_patchArrays; - parrays.reserve( nlevels ); + tables->reservePatchArrays(nlevels); - Descriptor desc( ptype, PatchTables::NON_TRANSITION, 0 ); + PatchDescriptor desc(ptype, PatchDescriptor::NON_TRANSITION, 0); // generate patch arrays for (int level=firstlevel, poffset=0, voffset=0; level<=maxlevel; ++level) { @@ -783,9 +732,7 @@ PatchTablesFactory::createUniform( TopologyRefiner const & refiner, Options opti npatches *= 2; if (level>=firstlevel) { - parrays.push_back(PatchTables::PatchArray(desc, voffset, poffset, npatches, 0)); - voffset += npatches * nCVs; - poffset += npatches; + tables->pushPatchArray(desc, npatches, &voffset, &poffset, 0); } } @@ -799,7 +746,7 @@ PatchTablesFactory::createUniform( TopologyRefiner const & refiner, Options opti // // Now populate the patches: // - Index * iptr = &tables->_patches[0]; + Index * iptr = &tables->_patchVerts[0]; PatchParam * pptr = &tables->_paramTable[0]; Index ** fptr = 0; @@ -900,18 +847,16 @@ PatchTablesFactory::createAdaptive( TopologyRefiner const & refiner, Options opt PatchTables * tables = new PatchTables(maxValence); // Populate the patch array descriptors - PatchTables::PatchArrayVector & parray = tables->_patchArrays; - parray.reserve( patchInventory.getNumPatchArrays() ); - + tables->reservePatchArrays(patchInventory.getNumPatchArrays()); // sort through the inventory and push back non-empty patch arrays - typedef PatchTables::DescriptorVector DescVec; + typedef PatchDescriptorVector DescVec; - DescVec const & descs = PatchTables::GetAdaptiveDescriptors(Sdc::TYPE_CATMARK); + DescVec const & descs = PatchDescriptor::GetAdaptivePatchDescriptors(Sdc::TYPE_CATMARK); int voffset=0, poffset=0, qoffset=0; for (DescVec::const_iterator it=descs.begin(); it!=descs.end(); ++it) { - pushPatchArray(*it, parray, patchInventory.getValue(*it), &voffset, &poffset, &qoffset ); + tables->pushPatchArray(*it, patchInventory.getValue(*it), &voffset, &poffset, &qoffset ); } tables->_numPtexFaces = refiner.GetNumPtexFaces(); @@ -926,7 +871,7 @@ PatchTablesFactory::createAdaptive( TopologyRefiner const & refiner, Options opt // Specifics for Gregory patches if ((patchInventory.G > 0) or (patchInventory.GB > 0)) { - tables->_quadOffsetTable.resize( patchInventory.G*4 + patchInventory.GB*4 ); + tables->_quadOffsetsTable.resize( patchInventory.G*4 + patchInventory.GB*4 ); } // @@ -1184,38 +1129,39 @@ PatchTablesFactory::populateAdaptivePatches( TopologyRefiner const & refiner, PatchFVarPointers fptrs; SharpnessIndexPointers sptrs; - typedef PatchTables::DescriptorVector DescVec; + typedef PatchDescriptorVector DescVec; - DescVec const & descs = PatchTables::GetAdaptiveDescriptors(Sdc::TYPE_CATMARK); + DescVec const & descs = PatchDescriptor::GetAdaptivePatchDescriptors(Sdc::TYPE_CATMARK); for (DescVec::const_iterator it=descs.begin(); it!=descs.end(); ++it) { - PatchTables::PatchArray * pa = tables->findPatchArray(*it); + Index arrayIndex = tables->findPatchArray(*it); - if (not pa) continue; + if (arrayIndex==Vtr::INDEX_INVALID) { + continue; + } - iptrs.getValue( *it ) = &tables->_patches[pa->GetVertIndex()]; - pptrs.getValue( *it ) = &tables->_paramTable[pa->GetPatchIndex()]; + iptrs.getValue( *it ) = tables->getPatchArrayVertices(arrayIndex).begin(); + pptrs.getValue( *it ) = tables->getPatchParams(arrayIndex).begin(); if (patchInventory.hasSingleCreasedPatches()) { - sptrs.getValue( *it ) = &tables->_sharpnessIndexTable[pa->GetPatchIndex()]; + sptrs.getValue( *it ) = tables->getSharpnessIndices(arrayIndex); } if (tables->_fvarPatchTables) { - int nchannels = refiner.GetNumFVarChannels(), - ncvs = pa->GetDescriptor().GetNumFVarControlVertices(); // XXXX manuelk this will break with bi-cubic fvar interp !!! + // XXXX manuelk revisit when implementing bi-cubic fvar interp !!! + int nchannels = refiner.GetNumFVarChannels(); Index ** fptr = (Index **)alloca(nchannels*sizeof(Index *)); for (int channel=0; channel_fvarPatchTables-> - _channels[channel].patchVertIndices[pa->GetPatchIndex()*ncvs]; + fptr[channel] = tables->getFVarVerts(arrayIndex, channel).begin(); } fptrs.getValue( *it ) = fptr; } } - PatchTables::QuadOffsetTable::value_type *quad_G_C0_P = patchInventory.G>0 ? &tables->_quadOffsetTable[0] : 0; - PatchTables::QuadOffsetTable::value_type *quad_G_C1_P = patchInventory.GB>0 ? &tables->_quadOffsetTable[patchInventory.G*4] : 0; + unsigned int * quad_G_C0_P = patchInventory.G>0 ? &tables->_quadOffsetsTable[0] : 0, + * quad_G_C1_P = patchInventory.GB>0 ? &tables->_quadOffsetsTable[patchInventory.G*4] : 0; std::vector gregoryVertexFlags; @@ -1451,7 +1397,7 @@ PatchTablesFactory::populateAdaptivePatches( TopologyRefiner const & refiner, if ((patchInventory.G > 0) or (patchInventory.GB > 0)) { const int SizePerVertex = 2*tables->_maxValence + 1; - PatchTables::VertexValenceTable & vTable = tables->_vertexValenceTable; + std::vector & vTable = tables->_vertexValenceTable; vTable.resize(refiner.GetNumVerticesTotal() * SizePerVertex); int vOffset = 0; diff --git a/opensubdiv/far/patchTablesFactory.h b/opensubdiv/far/patchTablesFactory.h index 6e7c0cd3..00d112dd 100644 --- a/opensubdiv/far/patchTablesFactory.h +++ b/opensubdiv/far/patchTablesFactory.h @@ -84,7 +84,6 @@ public: private: - typedef PatchTables::Descriptor Descriptor; typedef PatchTables::FVarPatchTables FVarPatchTables; static PatchTables * createUniform( TopologyRefiner const & refiner, Options options ); @@ -110,14 +109,10 @@ private: PatchTables const & tables, Options options ); - static void pushPatchArray( PatchTables::Descriptor desc, - PatchTables::PatchArrayVector & parray, - int npatches, int * voffset, int * poffset, int * qoffset ); - static PatchParam * computePatchParam( TopologyRefiner const & refiner, int level, int face, int rotation, PatchParam * coord ); - static void getQuadOffsets(Vtr::Level const & level, int face, Index * result); + static void getQuadOffsets(Vtr::Level const & level, int face, unsigned int * result); static int assignSharpnessIndex( PatchTables *tables, float sharpness ); diff --git a/opensubdiv/osd/cpuEvalLimitContext.cpp b/opensubdiv/osd/cpuEvalLimitContext.cpp index 747e7ee4..f505ac94 100644 --- a/opensubdiv/osd/cpuEvalLimitContext.cpp +++ b/opensubdiv/osd/cpuEvalLimitContext.cpp @@ -36,70 +36,19 @@ namespace OPENSUBDIV_VERSION { namespace Osd { CpuEvalLimitContext * -CpuEvalLimitContext::Create(Far::PatchTables const & patchTables, bool requireFVarData) { +CpuEvalLimitContext::Create(Far::PatchTables const & patchTables) { // there is no limit with uniform subdivision if (not patchTables.IsFeatureAdaptive()) return NULL; - - return new CpuEvalLimitContext(patchTables, requireFVarData); + + return new CpuEvalLimitContext(patchTables); } -CpuEvalLimitContext::CpuEvalLimitContext(Far::PatchTables const & patchTables, bool requireFVarData) : - EvalLimitContext(patchTables) { - - // copy the data from the FarTables - _patches = patchTables.GetPatchTable(); - - _patchArrays = patchTables.GetPatchArrayVector(); - - _vertexValenceTable = patchTables.GetVertexValenceTable(); - - _quadOffsetTable = patchTables.GetQuadOffsetTable(); - - if (patchTables.GetEndCapStencilTables()) { - _endcapStencilTables = *patchTables.GetEndCapStencilTables(); - } - - _maxValence = patchTables.GetMaxValence(); - - // Copy the bitfields, the faceId will be the key to our map - int npatches = patchTables.GetNumPatchesTotal(); - - _patchBitFields.reserve(npatches); - - Far::PatchTables::PatchParamTable const & ptxTable = - patchTables.GetPatchParamTable(); - - if ( not ptxTable.empty() ) { - - Far::PatchParam const * pptr = &ptxTable[0]; - - for (int arrayId = 0; arrayId < (int)_patchArrays.size(); ++arrayId) { - - Far::PatchTables::PatchArray const & pa = _patchArrays[arrayId]; - - for (int j=0; j < pa.GetNumPatches(); ++j) { - _patchBitFields.push_back( pptr++->bitField ); - } - } - } - - // Copy the face-varying table if necessary - if (requireFVarData) { -/* XXXX manuelk do fvar stuff here - _fvarwidth = patchTables.GetFVarData().GetFVarWidth(); - if (_fvarwidth>0) { - _fvarData = patchTables.GetFVarData().GetAllData(); - } -*/ - } - - _patchMap = new Far::PatchMap( patchTables ); -} - -CpuEvalLimitContext::~CpuEvalLimitContext() { - delete _patchMap; +CpuEvalLimitContext::CpuEvalLimitContext(Far::PatchTables const & patchTables) : + EvalLimitContext(patchTables), + _patchTables(patchTables), + _patchMap(patchTables) { } } // end namespace Osd diff --git a/opensubdiv/osd/cpuEvalLimitContext.h b/opensubdiv/osd/cpuEvalLimitContext.h index 089b2adf..11a2f8b0 100644 --- a/opensubdiv/osd/cpuEvalLimitContext.h +++ b/opensubdiv/osd/cpuEvalLimitContext.h @@ -28,7 +28,6 @@ #include "../version.h" #include "../osd/evalLimitContext.h" -#include "../osd/vertexDescriptor.h" #include "../far/patchTables.h" #include "../far/patchMap.h" @@ -38,10 +37,6 @@ namespace OpenSubdiv { namespace OPENSUBDIV_VERSION { -namespace Far { - class StencilTables; -} - namespace Osd { class CpuEvalLimitContext : public EvalLimitContext { @@ -52,85 +47,26 @@ public: /// Note : the patchtables is expected to be feature-adaptive and have ptex /// coordinates tables. /// - /// @param patchTables a pointer to an initialized Far::PatchTables + /// @param patchTables a pointer to an initialized Far::PatchTables /// - /// @param requireFVarData flag for generating face-varying data - /// - static CpuEvalLimitContext * Create(Far::PatchTables const &patchTables, - bool requireFVarData=false); + static CpuEvalLimitContext * Create(Far::PatchTables const &patchTables); - virtual ~CpuEvalLimitContext(); - - - /// Returns the vector of patch arrays - const Far::PatchTables::PatchArrayVector & GetPatchArrayVector() const { - return _patchArrays; + Far::PatchTables const & GetPatchTables() const { + return _patchTables; } - /// Returns the vector of per-patch parametric data - const std::vector & GetPatchBitFields() const { - return _patchBitFields; - } - - /// The ordered array of control vertex indices for all the patches - const std::vector & GetControlVertices() const { - return _patches; - } - - /// Returns the vertex-valence buffer used for Gregory patch computations - Far::PatchTables::VertexValenceTable const & GetVertexValenceTable() const { - return _vertexValenceTable; - } - - /// Returns the Quad-Offsets buffer used for Gregory patch computations - Far::PatchTables::QuadOffsetTable const & GetQuadOffsetTable() const { - return _quadOffsetTable; - } - - Far::StencilTables const & GetEndCapStencilTables() const { - return _endcapStencilTables; - } - - /// Returns the face-varying data patch table - std::vector const & GetFVarData() const { - return _fvarData; - } - - /// Returns the number of floats in a datum of the face-varying data table - int GetFVarWidth() const { - return _fvarwidth; - } - - /// Returns a map that can connect a faceId to a list of children patches Far::PatchMap const & GetPatchMap() const { - return *_patchMap; - } - - /// Returns the highest valence of the vertices in the buffers - int GetMaxValence() const { - return _maxValence; + return _patchMap; } protected: - explicit CpuEvalLimitContext(Far::PatchTables const & patchTables, bool requireFVarData); + + explicit CpuEvalLimitContext(Far::PatchTables const & patchTables); private: - // Topology data for a mesh - Far::PatchTables::PatchArrayVector _patchArrays; // patch descriptor for each patch in the mesh - Far::PatchTables::PTable _patches; // patch control vertices - std::vector _patchBitFields; // per-patch parametric info - - Far::PatchTables::VertexValenceTable _vertexValenceTable; // extra Gregory patch data buffers - Far::PatchTables::QuadOffsetTable _quadOffsetTable; - Far::StencilTables _endcapStencilTables; - - std::vector _fvarData; - - Far::PatchMap * _patchMap; // map of the sub-patches given a face index - - int _maxValence, - _fvarwidth; + Far::PatchTables const _patchTables; // Patch topology data + Far::PatchMap const _patchMap; // Patch search accelerator }; diff --git a/opensubdiv/osd/cpuEvalLimitController.cpp b/opensubdiv/osd/cpuEvalLimitController.cpp index 13be2a56..ad288820 100644 --- a/opensubdiv/osd/cpuEvalLimitController.cpp +++ b/opensubdiv/osd/cpuEvalLimitController.cpp @@ -23,6 +23,7 @@ // #include "../osd/cpuEvalLimitController.h" +#include "../osd/cpuEvalLimitContext.h" #include "../osd/cpuEvalLimitKernel.h" #include "../far/patchTables.h" @@ -37,16 +38,11 @@ CpuEvalLimitController::CpuEvalLimitController() { CpuEvalLimitController::~CpuEvalLimitController() { } - // normalize & rotate (u,v) to the sub-patch inline void -computeSubPatchCoords( CpuEvalLimitContext * context, unsigned int patchIdx, float & u, float & v ) { - - Far::PatchParam::BitField bits = context->GetPatchBitFields()[ patchIdx ]; - - bits.Normalize( u, v ); - - bits.Rotate( u, v ); +computeSubPatchCoords(Far::PatchParam pparam, float & u, float & v ) { + pparam.bitField.Normalize(u, v); + pparam.bitField.Rotate(u, v); } // Vertex interpolation of a sample at the limit @@ -57,23 +53,15 @@ CpuEvalLimitController::EvalLimitSample( LimitLocation const & coord, float * outQ, float * outDQU, float * outDQV ) const { + typedef Far::PatchDescriptor Desc; float s=coord.s, t=coord.t; Far::PatchMap::Handle const * handle = context->GetPatchMap().FindPatch( coord.ptexIndex, s, t ); - - // the map may not be able to return a handle if there is a hole or the face - // index is incorrect - if (not handle) - return 0; - - computeSubPatchCoords(context, handle->patchIdx, s, t); - - Far::PatchTables::PatchArray const & parray = context->GetPatchArrayVector()[ handle->patchArrayIdx ]; - - Far::Index const * cvs = - &context->GetControlVertices()[ parray.GetVertIndex() + handle->vertexOffset ]; + if (not handle) { + return 0; // no handle if there is a hole or 'coord' is incorrect + } VertexData const & vertexData = _currentBindState.vertexData; @@ -83,57 +71,65 @@ CpuEvalLimitController::EvalLimitSample( LimitLocation const & coord, * outDu = outDQU ? outDQU + outDesc.offset : 0, * outDv = outDQV ? outDQV + outDesc.offset : 0; - switch( parray.GetDescriptor().GetType() ) { + Far::PatchTables const & ptables = context->GetPatchTables(); - case Far::PatchTables::REGULAR : evalBSpline( t, s, cvs, - vertexData.inDesc, - vertexData.in, - outDesc, - out, outDu, outDv ); - break; + computeSubPatchCoords(ptables.GetPatchParam(*handle), s, t); - case Far::PatchTables::BOUNDARY : evalBoundary( t, s, cvs, - vertexData.inDesc, - vertexData.in, - outDesc, - out, outDu, outDv ); - break; + Far::IndexArray cvs = ptables.GetPatchVertices(*handle); - case Far::PatchTables::CORNER : evalCorner( t, s, cvs, - vertexData.inDesc, - vertexData.in, - outDesc, - out, outDu, outDv ); - break; - case Far::PatchTables::GREGORY : evalGregory( t, s, cvs, - &context->GetVertexValenceTable()[0], - &context->GetQuadOffsetTable()[ parray.GetQuadOffsetIndex() + handle->vertexOffset ], - context->GetMaxValence(), - vertexData.inDesc, - vertexData.in, - outDesc, - out, outDu, outDv ); - break; + Far::PatchDescriptor desc = ptables.GetPatchDescriptor(*handle); + switch( desc.GetType() ) { + case Desc::REGULAR : evalBSpline( t, s, cvs.begin(), + vertexData.inDesc, + vertexData.in, + outDesc, + out, outDu, outDv ); + break; - case Far::PatchTables::GREGORY_BOUNDARY : - evalGregoryBoundary( t, s, cvs, - &context->GetVertexValenceTable()[0], - &context->GetQuadOffsetTable()[ parray.GetQuadOffsetIndex() + handle->vertexOffset ], - context->GetMaxValence(), - vertexData.inDesc, - vertexData.in, - outDesc, - out, outDu, outDv ); - break; - case Far::PatchTables::GREGORY_BASIS : - assert(context->GetEndCapStencilTables().GetNumStencils()>0); - evalGregoryBasis( t, s, - context->GetEndCapStencilTables(), - handle->vertexOffset, - vertexData.inDesc, - vertexData.in, - vertexData.outDesc, - out, outDu, outDv ); + case Desc::BOUNDARY : evalBoundary( t, s, cvs.begin(), + vertexData.inDesc, + vertexData.in, + outDesc, + out, outDu, outDv ); + break; + + case Desc::CORNER : evalCorner( t, s, cvs.begin(), + vertexData.inDesc, + vertexData.in, + outDesc, + out, outDu, outDv ); + break; + case Desc::GREGORY : evalGregory( t, s, cvs.begin(), + &ptables.GetVertexValenceTable()[0], + ptables.GetPatchQuadOffsets(*handle).begin(), + ptables.GetMaxValence(), + vertexData.inDesc, + vertexData.in, + outDesc, + out, outDu, outDv ); + break; + + case Desc::GREGORY_BOUNDARY : evalGregoryBoundary( t, s, cvs.begin(), + &ptables.GetVertexValenceTable()[0], + ptables.GetPatchQuadOffsets(*handle).begin(), + ptables.GetMaxValence(), + vertexData.inDesc, + vertexData.in, + outDesc, + out, outDu, outDv ); + break; + case Desc::GREGORY_BASIS : { + Far::StencilTables const * stencils = + ptables.GetEndCapStencilTables(); + assert(stencils and stencils->GetNumStencils()>0); + evalGregoryBasis( t, s, + *stencils, + ptables.GetEndCapStencilIndex(*handle), + vertexData.inDesc, + vertexData.in, + vertexData.outDesc, + out, outDu, outDv ); + } break; default: assert(0); } @@ -147,27 +143,25 @@ int CpuEvalLimitController::_EvalLimitSample( LimitLocation const & coords, CpuEvalLimitContext * context, unsigned int index ) const { + typedef Far::PatchDescriptor Desc; + float s=coords.s, t=coords.t; Far::PatchMap::Handle const * handle = context->GetPatchMap().FindPatch( coords.ptexIndex, s, t ); - - // the map may not be able to return a handle if there is a hole or the face - // index is incorrect - if (not handle) - return 0; - - computeSubPatchCoords(context, handle->patchIdx, s, t); - - Far::PatchTables::PatchArray const & parray = - context->GetPatchArrayVector()[ handle->patchArrayIdx ]; + if (not handle) { + return 0; // no handle if there is a hole or 'coord' is incorrect + } VertexData const & vertexData = _currentBindState.vertexData; - if (vertexData.in) { + Far::PatchTables const & ptables = context->GetPatchTables(); - Far::Index const * cvs = - &context->GetControlVertices()[ parray.GetVertIndex() + handle->vertexOffset ]; + Far::PatchDescriptor desc = ptables.GetPatchDescriptor(*handle); + + Far::IndexArray cvs = ptables.GetPatchVertices(*handle); + + if (vertexData.in) { int offset = vertexData.outDesc.stride * index; @@ -177,59 +171,60 @@ CpuEvalLimitController::_EvalLimitSample( LimitLocation const & coords, * outDu = vertexData.outDu ? vertexData.outDu+offset : 0, * outDv = vertexData.outDv ? vertexData.outDv+offset : 0; - // Based on patch type - go execute interpolation - switch( parray.GetDescriptor().GetType() ) { + computeSubPatchCoords(ptables.GetPatchParam(*handle), s, t); - case Far::PatchTables::REGULAR : evalBSpline( t, s, cvs, - vertexData.inDesc, - vertexData.in, - vertexData.outDesc, - out, outDu, outDv ); - break; + switch(desc.GetType()) { + case Desc::REGULAR : evalBSpline( t, s, cvs.begin(), + vertexData.inDesc, + vertexData.in, + vertexData.outDesc, + out, outDu, outDv ); + break; - case Far::PatchTables::BOUNDARY : evalBoundary( t, s, cvs, - vertexData.inDesc, - vertexData.in, - vertexData.outDesc, - out, outDu, outDv ); - break; + case Desc::BOUNDARY : evalBoundary( t, s, cvs.begin(), + vertexData.inDesc, + vertexData.in, + vertexData.outDesc, + out, outDu, outDv ); + break; - case Far::PatchTables::CORNER : evalCorner( t, s, cvs, - vertexData.inDesc, - vertexData.in, - vertexData.outDesc, - out, outDu, outDv ); - break; - case Far::PatchTables::GREGORY : evalGregory( t, s, cvs, - &context->GetVertexValenceTable()[0], - &context->GetQuadOffsetTable()[ parray.GetQuadOffsetIndex() + handle->vertexOffset ], - context->GetMaxValence(), - vertexData.inDesc, - vertexData.in, - vertexData.outDesc, - out, outDu, outDv ); - break; + case Desc::CORNER : evalCorner( t, s, cvs.begin(), + vertexData.inDesc, + vertexData.in, + vertexData.outDesc, + out, outDu, outDv ); + break; + case Desc::GREGORY : evalGregory( t, s, cvs.begin(), + &ptables.GetVertexValenceTable()[0], + ptables.GetPatchQuadOffsets(*handle).begin(), + ptables.GetMaxValence(), + vertexData.inDesc, + vertexData.in, + vertexData.outDesc, + out, outDu, outDv ); + break; - case Far::PatchTables::GREGORY_BOUNDARY : - evalGregoryBoundary( t, s, cvs, - &context->GetVertexValenceTable()[0], - &context->GetQuadOffsetTable()[ parray.GetQuadOffsetIndex() + handle->vertexOffset ], - context->GetMaxValence(), - vertexData.inDesc, - vertexData.in, - vertexData.outDesc, - out, outDu, outDv ); - break; - case Far::PatchTables::GREGORY_BASIS : - assert(context->GetEndCapStencilTables().GetNumStencils()>0); - evalGregoryBasis( s, t, - context->GetEndCapStencilTables(), - handle->vertexOffset, - vertexData.inDesc, - vertexData.in, - vertexData.outDesc, - out, outDu, outDv ); - break; + case Desc::GREGORY_BOUNDARY : evalGregoryBoundary( t, s, cvs.begin(), + &ptables.GetVertexValenceTable()[0], + ptables.GetPatchQuadOffsets(*handle).begin(), + ptables.GetMaxValence(), + vertexData.inDesc, + vertexData.in, + vertexData.outDesc, + out, outDu, outDv ); + break; + case Desc::GREGORY_BASIS : { + Far::StencilTables const * stencils = + ptables.GetEndCapStencilTables(); + assert(stencils and stencils->GetNumStencils()>0); + evalGregoryBasis( s, t, + *stencils, + ptables.GetEndCapStencilIndex(*handle), + vertexData.inDesc, + vertexData.in, + vertexData.outDesc, + out, outDu, outDv ); + } break; default: assert(0); } @@ -246,29 +241,18 @@ CpuEvalLimitController::_EvalLimitSample( LimitLocation const & coords, {0, 1, 2, 3} }; // no permutation int const * permute = 0; - switch (parray.GetDescriptor().GetType()) { - case Far::PatchTables::REGULAR : permute = zeroRings[0]; break; - case Far::PatchTables::SINGLE_CREASE : - case Far::PatchTables::BOUNDARY : permute = zeroRings[1]; break; - case Far::PatchTables::CORNER : permute = zeroRings[2]; break; - case Far::PatchTables::GREGORY : - case Far::PatchTables::GREGORY_BOUNDARY : - case Far::PatchTables::GREGORY_BASIS : permute = zeroRings[3]; break; + switch (desc.GetType()) { + case Desc::REGULAR : permute = zeroRings[0]; break; + case Desc::SINGLE_CREASE : + case Desc::BOUNDARY : permute = zeroRings[1]; break; + case Desc::CORNER : permute = zeroRings[2]; break; + case Desc::GREGORY : + case Desc::GREGORY_BOUNDARY : + case Desc::GREGORY_BASIS : permute = zeroRings[3]; break; default: assert(0); }; - Far::Index const * cvs = &context->GetControlVertices()[parray.GetVertIndex()]; - if (parray.GetDescriptor().GetType()==Far::PatchTables::GREGORY_BASIS) { - // XXXX Far::PatchMap stores vertexOffset based on a ringsize of 20 for - // Gregory patch, stored in a stencil table. The Ptable however - // contains the 0-ring with 4 vertices only, so we need to adjust - // this offset - cvs += handle->vertexOffset / 5; - } else { - cvs += handle->vertexOffset; - } - int offset = varyingData.outDesc.stride * index; Far::Index zeroRing[4] = { cvs[permute[0]], @@ -285,28 +269,25 @@ CpuEvalLimitController::_EvalLimitSample( LimitLocation const & coords, } // Note : currently we only support bilinear boundary interpolation rules - // for face-varying data. Although Hbr supports 3 additional smooth rule - // sets, the feature-adaptive patch interpolation code currently does not - // support them, and neither does this EvalContext. + // for limit face-varying data. FacevaryingData const & facevaryingData = _currentBindState.facevaryingData; - if (facevaryingData.out) { - - std::vector const & fvarData = context->GetFVarData(); - - if (not fvarData.empty()) { + if (facevaryingData.in and facevaryingData.out) { int offset = facevaryingData.outDesc.stride * index; static int const zeroRing[4] = {0,1,2,3}; + // XXXX manuelk this assumes FVar data is ordered with 4 CVs / patch : + // bi-cubic FVar interpolation will require proper topology + // accessors in Far::PatchTables and this code will change evalBilinear( t, s, zeroRing, facevaryingData.inDesc, - &fvarData[ handle->patchIdx * 4 * context->GetFVarWidth() ], + &facevaryingData.in[handle->patchIndex*4*facevaryingData.outDesc.stride], facevaryingData.outDesc, facevaryingData.out+offset); - } + } return 1; } diff --git a/opensubdiv/osd/cpuEvalLimitController.h b/opensubdiv/osd/cpuEvalLimitController.h index 00ad4c3a..e3d290e4 100644 --- a/opensubdiv/osd/cpuEvalLimitController.h +++ b/opensubdiv/osd/cpuEvalLimitController.h @@ -27,7 +27,6 @@ #include "../version.h" -#include "../osd/cpuEvalLimitContext.h" #include "../osd/vertexDescriptor.h" namespace OpenSubdiv { @@ -35,6 +34,9 @@ namespace OPENSUBDIV_VERSION { namespace Osd { +struct LimitLocation; +class CpuEvalLimitContext; + /// \brief CPU controler for limit surface evaluation. /// /// A CPU-driven controller that can be called to evaluate samples on the limit @@ -123,14 +125,17 @@ public: /// /// @param iDesc data descriptor shared by all input data buffers /// + /// @param inQ input face-varying data + /// /// @param oDesc data descriptor shared by all output data buffers /// /// @param outQ output face-varying data /// - template - void BindFacevaryingBuffers( VertexBufferDescriptor const & iDesc, + template + void BindFacevaryingBuffers( VertexBufferDescriptor const & iDesc, INPUT_BUFFER *inQ, VertexBufferDescriptor const & oDesc, OUTPUT_BUFFER *outQ ) { _currentBindState.facevaryingData.inDesc = iDesc; + _currentBindState.facevaryingData.in = inQ ? inQ->BindCpuBuffer() : 0; _currentBindState.facevaryingData.outDesc = oDesc; _currentBindState.facevaryingData.out = outQ ? outQ->BindCpuBuffer() : 0; @@ -238,17 +243,18 @@ protected: // Facevarying interpolated streams struct FacevaryingData { - FacevaryingData() : out(0) { } + FacevaryingData() : in(0), out(0) { } void Reset() { - out = NULL; + in = out = NULL; inDesc.Reset(); outDesc.Reset(); } VertexBufferDescriptor inDesc, - outDesc; - float * out; + outDesc; + float * in, + * out; }; diff --git a/opensubdiv/osd/cpuEvalLimitKernel.cpp b/opensubdiv/osd/cpuEvalLimitKernel.cpp index 47e677fe..69dc3448 100644 --- a/opensubdiv/osd/cpuEvalLimitKernel.cpp +++ b/opensubdiv/osd/cpuEvalLimitKernel.cpp @@ -399,9 +399,9 @@ evalGregoryBasis(float u, float v, Far::StencilTables const & basisStencils, int stencilIndex, VertexBufferDescriptor const & inDesc, - float const * inQ, + float const * inQ, VertexBufferDescriptor const & outDesc, - float * outQ, + float * outQ, float * outDQU, float * outDQV ) { @@ -634,7 +634,7 @@ void evalGregory(float u, float v, Far::Index const * vertexIndices, Far::Index const * vertexValenceBuffer, - Far::Index const * quadOffsetBuffer, + unsigned int const * quadOffsetBuffer, int maxValence, VertexBufferDescriptor const & inDesc, float const * inQ, @@ -761,7 +761,7 @@ evalGregory(float u, float v, int ip = (vid+1)%4; int im = (vid+3)%4; int n = valences[vid]; - Far::Index const *quadOffsets = quadOffsetBuffer; + unsigned int const *quadOffsets = quadOffsetBuffer; int start = quadOffsets[vid] & 0x00ff; int prev = (quadOffsets[vid] & 0xff00) / 256; @@ -892,7 +892,7 @@ void evalGregoryBoundary(float u, float v, Far::Index const * vertexIndices, Far::Index const * vertexValenceBuffer, - Far::Index const * quadOffsetBuffer, + unsigned int const * quadOffsetBuffer, int maxValence, VertexBufferDescriptor const & inDesc, float const * inQ, @@ -1109,7 +1109,7 @@ evalGregoryBoundary(float u, float v, n = abs(valences[vid]), ivalence = n; - Far::Index const *quadOffsets = quadOffsetBuffer; + unsigned int const *quadOffsets = quadOffsetBuffer; int vofs = vid * length; diff --git a/opensubdiv/osd/cpuEvalLimitKernel.h b/opensubdiv/osd/cpuEvalLimitKernel.h index 2a97f474..f9d921da 100644 --- a/opensubdiv/osd/cpuEvalLimitKernel.h +++ b/opensubdiv/osd/cpuEvalLimitKernel.h @@ -49,17 +49,17 @@ evalBilinear(float u, float v, float * outQ); void -evalBSpline(float u, float v, +evalBSpline(float u, float v, Far::Index const * vertexIndices, VertexBufferDescriptor const & inDesc, - float const * inQ, + float const * inQ, VertexBufferDescriptor const & outDesc, - float * outQ, + float * outQ, float * outDQU, float * outDQV ); void -evalBoundary(float u, float v, +evalBoundary(float u, float v, Far::Index const * vertexIndices, VertexBufferDescriptor const & inDesc, float const * inQ, @@ -69,7 +69,7 @@ evalBoundary(float u, float v, float * outDQV ); void -evalCorner(float u, float v, +evalCorner(float u, float v, Far::Index const * vertexIndices, VertexBufferDescriptor const & inDesc, float const * inQ, @@ -83,9 +83,9 @@ evalGregoryBasis(float u, float v, Far::StencilTables const & basisStencils, int stencilIndex, VertexBufferDescriptor const & inDesc, - float const * inQ, + float const * inQ, VertexBufferDescriptor const & outDesc, - float * outQ, + float * outQ, float * outDQU, float * outDQV ); @@ -93,12 +93,12 @@ void evalGregory(float u, float v, Far::Index const * vertexIndices, Far::Index const * vertexValenceBuffer, - Far::Index const * quadOffsetBuffer, + unsigned int const * quadOffsetBuffer, int maxValence, VertexBufferDescriptor const & inDesc, - float const * inQ, + float const * inQ, VertexBufferDescriptor const & outDesc, - float * outQ, + float * outQ, float * outDQU, float * outDQV ); @@ -106,7 +106,7 @@ void evalGregoryBoundary(float u, float v, Far::Index const * vertexIndices, Far::Index const * vertexValenceBuffer, - Far::Index const * quadOffsetBuffer, + unsigned int const * quadOffsetBuffer, int maxValence, VertexBufferDescriptor const & inDesc, float const * inQ, diff --git a/opensubdiv/osd/cpuSmoothNormalContext.cpp b/opensubdiv/osd/cpuSmoothNormalContext.cpp index 885e1c79..e3519098 100644 --- a/opensubdiv/osd/cpuSmoothNormalContext.cpp +++ b/opensubdiv/osd/cpuSmoothNormalContext.cpp @@ -23,6 +23,9 @@ // #include "../osd/cpuSmoothNormalContext.h" +#include "../far/topologyRefiner.h" + +#include namespace OpenSubdiv { namespace OPENSUBDIV_VERSION { @@ -30,19 +33,30 @@ namespace OPENSUBDIV_VERSION { namespace Osd { CpuSmoothNormalContext::CpuSmoothNormalContext( - Far::PatchTables const *patchTables, bool resetMemory) : + Far::TopologyRefiner const & refiner, int level, bool resetMemory) : _numVertices(0), _resetMemory(resetMemory) { - // copy the data from the FarTables - _patches = patchTables->GetPatchTable(); + int nfaces = refiner.GetNumFaces(level), + nverts = nfaces * 4; - _patchArrays = patchTables->GetPatchArrayVector(); + _faceVerts.resize(nverts); + Far::Index * dest = &_faceVerts[0]; + + for (int face=0; face0) and + (level>0) and (level namespace OpenSubdiv { namespace OPENSUBDIV_VERSION { +namespace Far { + class TopologyRefiner; +} + namespace Osd { class CpuSmoothNormalContext : private NonCopyable { @@ -44,7 +49,9 @@ public: /// Creates an CpuComputeContext instance /// - /// @param patchTables The Far::PatchTables used for this Context. + /// @param refiner The uniformly refined Far::TopologyRefiner + /// + /// @param level Refinement level used to generate normals /// /// @param resetMemory Set to true if the target vertex buffer needs its /// memory reset before accumulating the averaged normals. @@ -53,7 +60,7 @@ public: /// been reset and this step can be skipped to save time. /// static CpuSmoothNormalContext * Create( - Far::PatchTables const *patchTables, bool resetMemory=false); + Far::TopologyRefiner const & refiner, int level, bool resetMemory=false); /// Binds a vertex and a varying data buffers to the context. Binding ensures /// that data buffers are properly inter-operated between Contexts and @@ -93,16 +100,21 @@ public: _numVertices = 0; } - /// Returns the vector of patch arrays - Far::PatchTables::PatchArrayVector const & GetPatchArrayVector() const { - return _patchArrays; + Far::Index const * GetFaceVertices() const { + return &_faceVerts[0]; } - /// The ordered array of control vertex indices for all the patches - Far::PatchTables::PTable const & GetControlVertices() const { - return _patches; + + int GetNumFaces() const { + return (int)_faceVerts.size()/4; } + /// Returns the number of vertices in output vertex buffer + int GetNumVertices() const { + return _numVertices; + } + + /// Returns a pointer to the data of the input buffer float const * GetCurrentInputVertexBuffer() const { return _iBuffer; @@ -124,11 +136,6 @@ public: return _oDesc; } - /// Returns the number of vertices in output vertex buffer - int GetNumVertices() const { - return _numVertices; - } - /// Returns whether the controller needs to reset the vertex buffer before /// accumulating smooth normals bool GetResetMemory() const { @@ -143,14 +150,13 @@ public: protected: // Constructor - explicit CpuSmoothNormalContext( - Far::PatchTables const *patchTables, bool resetMemory); + explicit CpuSmoothNormalContext(Far::TopologyRefiner const & refiner, + int level, bool resetMemory); private: // Topology data for a mesh - Far::PatchTables::PatchArrayVector _patchArrays; // patch descriptor for each patch in the mesh - Far::PatchTables::PTable _patches; // patch control vertices + std::vector _faceVerts; // patch control vertices VertexBufferDescriptor _iDesc, _oDesc; diff --git a/opensubdiv/osd/cpuSmoothNormalController.cpp b/opensubdiv/osd/cpuSmoothNormalController.cpp index 8255d9ec..3e7b8fd6 100644 --- a/opensubdiv/osd/cpuSmoothNormalController.cpp +++ b/opensubdiv/osd/cpuSmoothNormalController.cpp @@ -58,57 +58,42 @@ void CpuSmoothNormalController::_smootheNormals( float const * iBuffer = context->GetCurrentInputVertexBuffer() + iDesc.offset; float * oBuffer = context->GetCurrentOutputVertexBuffer() + oDesc.offset; - Far::PatchTables::PTable const & cvs = context->GetControlVertices(); + int nfaces = context->GetNumFaces(), + nverts = context->GetNumVertices(); - Far::PatchTables::PatchArrayVector const & parrays = context->GetPatchArrayVector(); - - if (cvs.empty() or parrays.empty() or (not iBuffer) or (not oBuffer)) { - return; - } - - for (int i=0; i<(int)parrays.size(); ++i) { - - Far::PatchTables::PatchArray const & pa = parrays[i]; - - Far::PatchTables::Type type = pa.GetDescriptor().GetType(); - - - if (type==Far::PatchTables::QUADS or type==Far::PatchTables::TRIANGLES) { - - int nv = Far::PatchTables::Descriptor::GetNumControlVertices(type); - - // if necessary, reset all normal values to 0 - if (context->GetResetMemory()) { - float * ptr = oBuffer; - for (int j=0; jGetNumVertices(); ++j, ptr += oDesc.stride) { - memset(ptr, 0, oDesc.length*sizeof(float)); - } - } - - for (int j=0, idx=pa.GetVertIndex(); j<(int)pa.GetNumPatches(); ++j, idx+=nv) { - - - float const * p0 = iBuffer + cvs[idx+0]*iDesc.stride, - * p1 = iBuffer + cvs[idx+1]*iDesc.stride, - * p2 = iBuffer + cvs[idx+2]*iDesc.stride; - - // compute face normal - float n[3]; - cross( n, p0, p1, p2 ); - - // add normal to all vertices of the face - for (int k=0; kGetResetMemory()) { + if (oDesc.length == oDesc.stride) { + memset(oBuffer, 0, nverts*oDesc.length*sizeof(float)); + } else { + float * ptr = oBuffer; + for (int j=0; jGetFaceVertices(); + for (int face=0; facecommonShader.AddDefine("OSD_NUM_ELEMENTS", ss.str()); } - if (desc.GetPattern() == Far::PatchTables::NON_TRANSITION) { + if (desc.GetPattern() == Far::PatchDescriptor::NON_TRANSITION) { switch (desc.GetType()) { - case Far::PatchTables::REGULAR: + case Far::PatchDescriptor::REGULAR: sconfig->vertexShader.source = bsplineShaderSource; sconfig->vertexShader.target = "vs_5_0"; sconfig->vertexShader.entry = "vs_main_patches"; @@ -97,7 +97,7 @@ D3D11DrawRegistryBase::_CreateDrawSourceConfig( sconfig->domainShader.target = "ds_5_0"; sconfig->domainShader.entry = "ds_main_patches"; break; - case Far::PatchTables::BOUNDARY: + case Far::PatchDescriptor::BOUNDARY: sconfig->vertexShader.source = bsplineShaderSource; sconfig->vertexShader.target = "vs_5_0"; sconfig->vertexShader.entry = "vs_main_patches"; @@ -109,7 +109,7 @@ D3D11DrawRegistryBase::_CreateDrawSourceConfig( sconfig->domainShader.target = "ds_5_0"; sconfig->domainShader.entry = "ds_main_patches"; break; - case Far::PatchTables::CORNER: + case Far::PatchDescriptor::CORNER: sconfig->vertexShader.source = bsplineShaderSource; sconfig->vertexShader.target = "vs_5_0"; sconfig->vertexShader.entry = "vs_main_patches"; @@ -121,7 +121,7 @@ D3D11DrawRegistryBase::_CreateDrawSourceConfig( sconfig->domainShader.target = "ds_5_0"; sconfig->domainShader.entry = "ds_main_patches"; break; - case Far::PatchTables::GREGORY: + case Far::PatchDescriptor::GREGORY: sconfig->vertexShader.source = gregoryShaderSource; sconfig->vertexShader.target = "vs_5_0"; sconfig->vertexShader.entry = "vs_main_patches"; @@ -132,7 +132,7 @@ D3D11DrawRegistryBase::_CreateDrawSourceConfig( sconfig->domainShader.target = "ds_5_0"; sconfig->domainShader.entry = "ds_main_patches"; break; - case Far::PatchTables::GREGORY_BOUNDARY: + case Far::PatchDescriptor::GREGORY_BOUNDARY: sconfig->vertexShader.source = gregoryShaderSource; sconfig->vertexShader.target = "vs_5_0"; sconfig->vertexShader.entry = "vs_main_patches"; @@ -179,9 +179,9 @@ D3D11DrawRegistryBase::_CreateDrawSourceConfig( sconfig->hullShader.AddDefine("OSD_TRANSITION_ROTATE", ss.str()); sconfig->domainShader.AddDefine("OSD_TRANSITION_ROTATE", ss.str()); - if (desc.GetType() == Far::PatchTables::BOUNDARY) { + if (desc.GetType() == Far::PatchDescriptor::BOUNDARY) { sconfig->hullShader.AddDefine("OSD_PATCH_BOUNDARY"); - } else if (desc.GetType() == Far::PatchTables::CORNER) { + } else if (desc.GetType() == Far::PatchDescriptor::CORNER) { sconfig->hullShader.AddDefine("OSD_PATCH_CORNER"); } } diff --git a/opensubdiv/osd/drawContext.cpp b/opensubdiv/osd/drawContext.cpp index ee67d044..1aaf9fad 100644 --- a/opensubdiv/osd/drawContext.cpp +++ b/opensubdiv/osd/drawContext.cpp @@ -34,16 +34,18 @@ namespace Osd { DrawContext::~DrawContext() {} void -DrawContext::ConvertPatchArrays(Far::PatchTables::PatchArrayVector const &farPatchArrays, - DrawContext::PatchArrayVector &osdPatchArrays, - int maxValence, int numElements) { +DrawContext::ConvertPatchArrays(Far::PatchTables const &patchTables, + PatchArrayVector &osdPatchArrays, int maxValence, int numElements) { // create patch arrays for drawing (while duplicating subpatches for transition patch arrays) static int subPatchCounts[] = { 1, 3, 4, 4, 4, 2 }; // number of subpatches for patterns int numTotalPatchArrays = 0; - for (int i = 0; i < (int)farPatchArrays.size(); ++i) { - Far::PatchTables::TransitionPattern pattern = farPatchArrays[i].GetDescriptor().GetPattern(); + for (int array=0; array < patchTables.GetNumPatchArrays(); ++array) { + + Far::PatchDescriptor::TransitionPattern pattern = + patchTables.GetPatchArrayDescriptor(array).GetPattern(); + numTotalPatchArrays += subPatchCounts[(int)pattern]; } @@ -51,24 +53,50 @@ DrawContext::ConvertPatchArrays(Far::PatchTables::PatchArrayVector const &farPat osdPatchArrays.clear(); osdPatchArrays.reserve(numTotalPatchArrays); - for (int i = 0; i < (int)farPatchArrays.size(); ++i) { - Far::PatchTables::TransitionPattern pattern = farPatchArrays[i].GetDescriptor().GetPattern(); - int numSubPatches = subPatchCounts[(int)pattern]; + int narrays = patchTables.GetNumPatchArrays(); + for (int array=0, pidx=0, vidx=0, qidx=0; array & dst) { + + dst.resize(patchTables.GetNumControlVerticesTotal()); + Index * ptr = &dst[0]; + + int narrays = patchTables.GetNumPatchArrays(); + for (int array=0; array FVarData; protected: + static void packPatchVerts(Far::PatchTables const & patchTables, + std::vector & dst); + static void packFVarData(Far::PatchTables const & patchTables, - int fvarWidth, FVarData const & src, FVarData & dst); + int fvarWidth, FVarData const & src, FVarData & dst); // XXXX: move to private member PatchArrayVector _patchArrays; diff --git a/opensubdiv/osd/evalLimitContext.h b/opensubdiv/osd/evalLimitContext.h index ff07a7bd..0e2c90f5 100644 --- a/opensubdiv/osd/evalLimitContext.h +++ b/opensubdiv/osd/evalLimitContext.h @@ -40,9 +40,7 @@ namespace Osd { /// \brief Coordinates set on a limit surface /// -class LimitLocation { - -public: +struct LimitLocation { LimitLocation() { } @@ -56,7 +54,7 @@ public: /// LimitLocation(int f, float x, float y) : ptexIndex(f), s(x), t(y) { } - int ptexIndex; ///< ptex face index + int ptexIndex; ///< ptex face index float s, t; ///< parametric location on face }; diff --git a/opensubdiv/osd/glDrawContext.cpp b/opensubdiv/osd/glDrawContext.cpp index a570eb9d..e8288e7d 100644 --- a/opensubdiv/osd/glDrawContext.cpp +++ b/opensubdiv/osd/glDrawContext.cpp @@ -119,7 +119,7 @@ GLDrawContext::create(Far::PatchTables const & patchTables, int numVertexElement _isAdaptive = patchTables.IsFeatureAdaptive(); // Process PTable - Far::PatchTables::PTable const & ptables = patchTables.GetPatchTable(); + Far::PatchTables::PatchVertsTable const & ptables = patchTables.GetPatchControlVerticesTable(); glGenBuffers(1, &_patchIndexBuffer); @@ -137,8 +137,8 @@ GLDrawContext::create(Far::PatchTables const & patchTables, int numVertexElement glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); } - DrawContext::ConvertPatchArrays(patchTables.GetPatchArrayVector(), - _patchArrays, patchTables.GetMaxValence(), numVertexElements); + DrawContext::ConvertPatchArrays(patchTables, _patchArrays, + patchTables.GetMaxValence(), numVertexElements); // allocate and initialize additional buffer data @@ -156,15 +156,15 @@ GLDrawContext::create(Far::PatchTables const & patchTables, int numVertexElement // create quad offset table buffer - Far::PatchTables::QuadOffsetTable const & - quadOffsetTable = patchTables.GetQuadOffsetTable(); + Far::PatchTables::QuadOffsetsTable const & + quadOffsetTable = patchTables.GetQuadOffsetsTable(); if (not quadOffsetTable.empty()) _quadOffsetsTextureBuffer = createTextureBuffer(quadOffsetTable, GL_R32I); // create ptex coordinate buffer - Far::PatchTables::PatchParamTable const & + Far::PatchParamTable const & patchParamTables = patchTables.GetPatchParamTable(); if (not patchParamTables.empty()) { diff --git a/opensubdiv/osd/glDrawRegistry.cpp b/opensubdiv/osd/glDrawRegistry.cpp index 6c28c534..6b73ba44 100644 --- a/opensubdiv/osd/glDrawRegistry.cpp +++ b/opensubdiv/osd/glDrawRegistry.cpp @@ -67,11 +67,11 @@ GLDrawRegistryBase::_CreateDrawSourceConfig( GLDrawSourceConfig * sconfig = _NewDrawSourceConfig(); sconfig->commonShader.source = commonShaderSource; - + if (IsPtexEnabled()) { sconfig->commonShader.source += ptexShaderSource; } - + { std::ostringstream ss; ss << (int)desc.GetMaxValence(); @@ -81,9 +81,9 @@ GLDrawRegistryBase::_CreateDrawSourceConfig( sconfig->commonShader.AddDefine("OSD_NUM_ELEMENTS", ss.str()); } - if (desc.GetPattern() == Far::PatchTables::NON_TRANSITION) { + if (desc.GetPattern() == Far::PatchDescriptor::NON_TRANSITION) { switch (desc.GetType()) { - case Far::PatchTables::REGULAR: + case Far::PatchDescriptor::REGULAR: sconfig->vertexShader.source = bsplineShaderSource; sconfig->vertexShader.version = "#version 410\n"; sconfig->vertexShader.AddDefine("OSD_PATCH_VERTEX_BSPLINE_SHADER"); @@ -94,7 +94,7 @@ GLDrawRegistryBase::_CreateDrawSourceConfig( sconfig->tessEvalShader.version = "#version 410\n"; sconfig->tessEvalShader.AddDefine("OSD_PATCH_TESS_EVAL_BSPLINE_SHADER"); break; - case Far::PatchTables::SINGLE_CREASE: + case Far::PatchDescriptor::SINGLE_CREASE: sconfig->vertexShader.source = bsplineShaderSource; sconfig->vertexShader.version = "#version 410\n"; sconfig->vertexShader.AddDefine("OSD_PATCH_VERTEX_BSPLINE_SHADER"); @@ -107,7 +107,7 @@ GLDrawRegistryBase::_CreateDrawSourceConfig( sconfig->tessEvalShader.AddDefine("OSD_PATCH_TESS_EVAL_BSPLINE_SHADER"); sconfig->tessEvalShader.AddDefine("OSD_PATCH_SINGLE_CREASE"); break; - case Far::PatchTables::BOUNDARY: + case Far::PatchDescriptor::BOUNDARY: sconfig->vertexShader.source = bsplineShaderSource; sconfig->vertexShader.version = "#version 410\n"; sconfig->vertexShader.AddDefine("OSD_PATCH_VERTEX_BSPLINE_SHADER"); @@ -119,7 +119,7 @@ GLDrawRegistryBase::_CreateDrawSourceConfig( sconfig->tessEvalShader.version = "#version 410\n"; sconfig->tessEvalShader.AddDefine("OSD_PATCH_TESS_EVAL_BSPLINE_SHADER"); break; - case Far::PatchTables::CORNER: + case Far::PatchDescriptor::CORNER: sconfig->vertexShader.source = bsplineShaderSource; sconfig->vertexShader.version = "#version 410\n"; sconfig->vertexShader.AddDefine("OSD_PATCH_VERTEX_BSPLINE_SHADER"); @@ -131,7 +131,7 @@ GLDrawRegistryBase::_CreateDrawSourceConfig( sconfig->tessEvalShader.version = "#version 410\n"; sconfig->tessEvalShader.AddDefine("OSD_PATCH_TESS_EVAL_BSPLINE_SHADER"); break; - case Far::PatchTables::GREGORY: + case Far::PatchDescriptor::GREGORY: sconfig->vertexShader.source = gregoryShaderSource; sconfig->vertexShader.version = "#version 410\n"; sconfig->vertexShader.AddDefine("OSD_PATCH_VERTEX_GREGORY_SHADER"); @@ -142,7 +142,7 @@ GLDrawRegistryBase::_CreateDrawSourceConfig( sconfig->tessEvalShader.version = "#version 410\n"; sconfig->tessEvalShader.AddDefine("OSD_PATCH_TESS_EVAL_GREGORY_SHADER"); break; - case Far::PatchTables::GREGORY_BOUNDARY: + case Far::PatchDescriptor::GREGORY_BOUNDARY: sconfig->vertexShader.source = gregoryShaderSource; sconfig->vertexShader.version = "#version 410\n"; sconfig->vertexShader.AddDefine("OSD_PATCH_VERTEX_GREGORY_SHADER"); @@ -189,12 +189,12 @@ GLDrawRegistryBase::_CreateDrawSourceConfig( sconfig->tessControlShader.AddDefine("OSD_TRANSITION_ROTATE", ss.str()); sconfig->tessEvalShader.AddDefine("OSD_TRANSITION_ROTATE", ss.str()); - if (desc.GetType() == Far::PatchTables::SINGLE_CREASE) { + if (desc.GetType() == Far::PatchDescriptor::SINGLE_CREASE) { sconfig->tessControlShader.AddDefine("OSD_PATCH_SINGLE_CREASE"); sconfig->tessEvalShader.AddDefine("OSD_PATCH_SINGLE_CREASE"); - } else if (desc.GetType() == Far::PatchTables::BOUNDARY) { + } else if (desc.GetType() == Far::PatchDescriptor::BOUNDARY) { sconfig->tessControlShader.AddDefine("OSD_PATCH_BOUNDARY"); - } else if (desc.GetType() == Far::PatchTables::CORNER) { + } else if (desc.GetType() == Far::PatchDescriptor::CORNER) { sconfig->tessControlShader.AddDefine("OSD_PATCH_CORNER"); } } @@ -258,7 +258,7 @@ _CompileShader( GLDrawConfig * GLDrawRegistryBase::_CreateDrawConfig( DrawContext::PatchDescriptor const & /* desc */, - GLDrawSourceConfig const * sconfig) + GLDrawSourceConfig const * sconfig) { assert(sconfig); diff --git a/opensubdiv/osd/ompSmoothNormalController.cpp b/opensubdiv/osd/ompSmoothNormalController.cpp index c774121c..8de17494 100644 --- a/opensubdiv/osd/ompSmoothNormalController.cpp +++ b/opensubdiv/osd/ompSmoothNormalController.cpp @@ -51,6 +51,56 @@ cross(float *n, const float *p0, const float *p1, const float *p2) { n[2] *= rn; } +void OmpSmoothNormalController::_smootheNormals( + CpuSmoothNormalContext * context) { + + VertexBufferDescriptor const & iDesc = context->GetInputVertexDescriptor(), + & oDesc = context->GetOutputVertexDescriptor(); + + assert(iDesc.length==3 and oDesc.length==3); + + float * oBuffer = context->GetCurrentOutputVertexBuffer() + oDesc.offset; + if (context->GetResetMemory()) { + +#pragma omp parallel for + for (int j=0; jGetNumVertices(); ++j) { + float * ptr = oBuffer + j * oDesc.stride; + memset(ptr, 0, oDesc.length*sizeof(float)); + } + } + + { // note: quads only ! + float const * iBuffer = context->GetCurrentInputVertexBuffer() + iDesc.offset; + + Far::Index const * fverts = context->GetFaceVertices(); + + int nfaces = context->GetNumFaces(); + +#pragma omp parallel for + for (int i=0; iGetInputVertexDescriptor(), - & oDesc = context->GetOutputVertexDescriptor(); + & oDesc = context->GetOutputVertexDescriptor(); assert(iDesc.length==3 and oDesc.length==3); - float const * iBuffer = context->GetCurrentInputVertexBuffer() + iDesc.offset; float * oBuffer = context->GetCurrentOutputVertexBuffer() + oDesc.offset; + if (context->GetResetMemory()) { - std::vector const & verts = context->GetControlVertices(); - - Far::PatchTables::PatchArrayVector const & parrays = context->GetPatchArrayVector(); - - if (verts.empty() or parrays.empty() or (not iBuffer) or (not oBuffer)) { - return; + TBBResetKernel resetKernel(oBuffer, oDesc.stride); + tbb::blocked_range range(0, context->GetNumVertices(), grain_size); + tbb::parallel_for(range, resetKernel); } - for (int i=0; i<(int)parrays.size(); ++i) { + { // note: quads only ! + float const * iBuffer = context->GetCurrentInputVertexBuffer() + iDesc.offset; - Far::PatchTables::PatchArray const & pa = parrays[i]; + Far::Index const * fverts = context->GetFaceVertices(); - Far::PatchTables::Type type = pa.GetDescriptor().GetType(); + int nfaces = context->GetNumFaces(); - if (type==Far::PatchTables::QUADS or type==Far::PatchTables::TRIANGLES) { + TBBSmoothNormalKernel smoothNormalkernel( iBuffer, + iDesc.stride, + oBuffer, + oDesc.stride, + fverts, 4 ); - - // if necessary, reset all normal values to 0 - if (context->GetResetMemory()) { - - TBBResetKernel resetKernel(oBuffer, oDesc.stride); - tbb::blocked_range range(0, context->GetNumVertices(), grain_size); - tbb::parallel_for(range, resetKernel); - } - - { - int nv = Far::PatchTables::Descriptor::GetNumControlVertices(type); - TBBSmoothNormalKernel smoothNormalkernel( iBuffer, - iDesc.stride, - oBuffer, - oDesc.stride, - &verts[pa.GetVertIndex()], - nv); - - tbb::blocked_range range(0, pa.GetNumPatches(), grain_size); - tbb::parallel_for(range, smoothNormalkernel); - } - - } + tbb::blocked_range range(0, nfaces, grain_size); + tbb::parallel_for(range, smoothNormalkernel); } }