Refactor Far::PatchTables

- split Far::PatchDescriptor into its own class (mirrors Far::PatchParam)
- hide PatchArray as a private internal structure
- add public accessors patterned after Far::TopologyRefiner (returning Vtr::Arrays)
- propagate new API to all dependent code

note: some direct table accessors have not been removed *yet* - see code for details
This commit is contained in:
manuelk 2014-11-25 12:41:19 -08:00
parent a9c32d6705
commit b27b55e4a8
38 changed files with 1593 additions and 1481 deletions

View File

@ -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];
}
}

View File

@ -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 */

View File

@ -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;

View File

@ -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:

View File

@ -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);

View File

@ -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

View File

@ -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:

View File

@ -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;
}
}

View File

@ -473,8 +473,8 @@ setEdge(std::vector<float> & 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<float> & 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<patchTables.GetNumPatches(array); ++patch) {
for (int j=0; j<(int)pa.GetNumPatches(); ++j, cvs+=ncvs) {
OpenSubdiv::Far::IndexArray const cvs =
patchTables.GetPatchVertices(array, patch);
int const * edgeList=getEdgeList(ncvs);
for (int k=0; k<getNumEdges(ncvs); ++k, ++edge) {
for (int k=0; k<getNumEdges(cvs.size()); ++k, ++edge) {
eao[edge*2 ] = edge*2;
eao[edge*2+1] = edge*2+1;
@ -583,37 +579,39 @@ GLMesh::initializeBuffers(Options options, TopologyRefiner const & refiner,
_faceColors.resize(nfaces*4, 1.0f);
// default to solid color
for (int i=0, face=0; i<(int)parrays.size(); ++i) {
for (int array=0, face=0; array<(int)patchTables.GetNumPatchArrays(); ++array) {
PatchTables::PatchArray const & pa = parrays[i];
OpenSubdiv::Far::PatchDescriptor desc =
patchTables.GetPatchArrayDescriptor(array);
int ncvs = getRingSize(pa.GetDescriptor());
//int ncvs = getRingSize(desc);
OpenSubdiv::Far::Index const * cvs = &ptable[pa.GetVertIndex()];
for (int patch=0; patch<patchTables.GetNumPatches(array); ++patch, ++face) {
for (int j=0; j<(int)pa.GetNumPatches(); ++j, ++face, cvs+=ncvs) {
OpenSubdiv::Far::IndexArray const cvs =
patchTables.GetPatchVertices(array, patch);
if (pa.GetDescriptor().GetType()==PatchTables::REGULAR) {
if (desc.GetType()==Descriptor::REGULAR) {
eao[face*4 ] = cvs[ 5];
eao[face*4+1] = cvs[ 6];
eao[face*4+2] = cvs[10];
eao[face*4+3] = cvs[ 9];
} else if (pa.GetDescriptor().GetType()==PatchTables::BOUNDARY) {
} else if (desc.GetType()==Descriptor::BOUNDARY) {
eao[face*4 ] = cvs[ 2];
eao[face*4+1] = cvs[ 6];
eao[face*4+2] = cvs[ 5];
eao[face*4+3] = cvs[ 1];
} else if (pa.GetDescriptor().GetType()==PatchTables::CORNER) {
} else if (desc.GetType()==Descriptor::CORNER) {
eao[face*4 ] = cvs[ 1];
eao[face*4+1] = cvs[ 2];
eao[face*4+2] = cvs[ 5];
eao[face*4+3] = cvs[ 4];
} else {
memcpy(&eao[face*4], cvs, 4*sizeof(OpenSubdiv::Far::Index));
memcpy(&eao[face*4], cvs.begin(), 4*sizeof(OpenSubdiv::Far::Index));
}
if (options.faceColorMode==FACECOLOR_BY_PATCHTYPE) {
float const * color = getAdaptivePatchColor(pa.GetDescriptor());
float const * color = getAdaptivePatchColor(desc);
memcpy(&_faceColors[face*4], color, 4*sizeof(float));
} else {
setSolidColor(&_faceColors[face*4]);

View File

@ -421,7 +421,7 @@ public:
private:
typedef Far::PatchTables::Descriptor Descriptor;
typedef Far::PatchDescriptor Descriptor;
// Returns true if one of v's neighboring faces has vertices carrying the tag "wasTagged"
static bool vertexHasTaggedNeighbors(Hvertex * v);
@ -440,7 +440,7 @@ private:
static Far::Index * getOneRing( Hface const * f, int ringsize, Far::Index const * remap, Far::Index * result );
// Populates the Gregory patch quad offsets table
static void getQuadOffsets( Hface const * f, Far::Index * result );
static void getQuadOffsets( Hface const * f, unsigned int * result );
// The number of patches in the mesh
static int getNumPatches( Far::PatchTables::PatchArrayVector const & parrays );
@ -464,7 +464,7 @@ private:
PatchTypes() { memset(this, 0, sizeof(PatchTypes<TYPE>)); }
// 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<float *> FVarPointers;
typedef PatchTypes<int> 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 <class TYPE> TYPE &
Far::PatchTablesFactory::PatchTypes<TYPE>::getValue( Far::PatchTables::Descriptor desc ) {
Far::PatchTablesFactory::PatchTypes<TYPE>::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; i<tables->GetNumPatchArrays(); ++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<nfaces; ++i) {
@ -896,7 +879,7 @@ Far::PatchTablesFactory::Create(Hmesh & mesh, int maxvalence) {
if (f->_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);

View File

@ -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; i<ncvs; ++i) {
for (int i=0; i<cvs.size(); ++i) {
snprintf(buf, 16, "%d", i);
g_font->Print3D(vertexBuffer[cvs[i]].GetPos(), buf, 1);
}
@ -549,16 +541,14 @@ static void
createGregoryBasis(OpenSubdiv::Far::PatchTables const & patchTables,
std::vector<Vertex> 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<Vertex> 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);
}
}

View File

@ -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

View File

@ -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 <cassert>
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

View File

@ -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 <vector>
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<PatchDescriptor> 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<PatchDescriptor> 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 */

View File

@ -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<narrays; ++parray) {
int ringsize = parray.GetDescriptor().GetNumControlVertices();
PatchParamArray params = patchTables.GetPatchParams(parray);
for (Index j=0; j < parray.GetNumPatches(); ++j) {
int ringsize = patchTables.GetPatchArrayDescriptor(parray).GetNumControlVertices();
PatchParam const & param = paramTable[parray.GetPatchIndex()+j];
for (Index j=0; j < patchTables.GetNumPatches(parray); ++j) {
Handle & h = _handles[current];
h.patchArrayIdx = arrayIdx;
h.patchIdx = current;
h.vertexOffset = j * ringsize;
h.arrayIndex = parray;
h.patchIndex = current;
h.vertIndex = j * ringsize;
nfaces = std::max(nfaces, (int)param.faceIndex);
nfaces = std::max(nfaces, (int)params[j].faceIndex);
++current;
}
}
++nfaces;
// temporary vector to hold the quadtree while under construction
std::vector<QuadNode> 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; parray<narrays; ++parray) {
PatchTables::PatchArray const & parray = patchArrays[i];
PatchParamArray params = patchTables.GetPatchParams(parray);
for (int j=0; j < parray.GetNumPatches(); ++j, ++handleIdx) {
for (int i=0; i < patchTables.GetNumPatches(parray); ++i, ++handleIndex) {
PatchParam const & param = paramTable[parray.GetPatchIndex()+j];
PatchParam::BitField bits = param.bitField;
PatchParam::BitField bits = params[i].bitField;
unsigned char depth = bits.GetDepth();
QuadNode * node = &quadtree[ param.faceIndex ];
QuadNode * node = &quadtree[ params[i].faceIndex ];
if (depth==(bits.NonQuadRoot() ? 1 : 0)) {
// special case : regular BSpline face w/ no sub-patches
node->SetChild( 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<depth; ++k) {
for (unsigned char j=0; j<depth; ++j) {
int delta = half >> 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

View File

@ -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<PatchParam> PatchParamTable;
typedef Vtr::Array<PatchParam> 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;

View File

@ -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<unsigned int>(&_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<Index> & 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<GetNumPatchArrays(); ++i) {
PatchDescriptor const & desc = _patchArrays[i].desc;
if (desc.GetType()>=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

View File

@ -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 <cstdlib>
#include <cassert>
#include <algorithm>
@ -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<Index> PTable;
typedef std::vector<Index> VertexValenceTable;
typedef std::vector<Index> QuadOffsetTable;
typedef std::vector<PatchParam> 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<Descriptor> 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<PatchArray> 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<PatchTables *>(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<int> const &GetSharpnessIndexTable() const { return _sharpnessIndexTable; }
/// \brief Returns sharpness values (if exists)
std::vector<float> 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<Index> 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<Index> const &GetSharpnessIndexTable() const { return _sharpnessIndices; }
/// \brief Returns sharpness values table
std::vector<float> const &GetSharpnessValues() const { return _sharpnessValues; }
typedef std::vector<unsigned int> 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<unsigned int> QuadOffsetsArray;
/// \brief Returns the 'QuadOffsets' for the Gregory patch identified by 'handle'
QuadOffsetsArray const GetPatchQuadOffsets(PatchHandle const & handle) const;
typedef std::vector<Index> 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<Index> patchVertIndices; // face-varying vertex indices
};
private:
std::vector<Channel> _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 <class T, class U> 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<PatchArray> 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<Index> _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<Index> _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<Index> _sharpnessIndexTable; // Indices of single-crease sharpness (one per patch)
std::vector<float> _sharpnessValues; // Sharpness values.
std::vector<Index> _sharpnessIndices; // Indices of single-crease sharpness (one per patch)
std::vector<float> _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 <class T, class U>
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 {

View File

@ -58,15 +58,15 @@ struct PatchTypes {
PatchTypes() { std::memset(this, 0, sizeof(PatchTypes<TYPE>)); }
// 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; i<tables->GetNumPatchArrays(); ++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; i<tables.GetNumPatchArrays(); ++i) {
nverts += tables.GetNumPatches(i) *
tables.GetPatchArrayDescriptor(i).GetNumFVarControlVertices();
}
assert(nverts>0);
@ -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<nchannels; ++channel) {
fptr[channel] = (Index *)&tables->_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<unsigned char> 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<Index> & vTable = tables->_vertexValenceTable;
vTable.resize(refiner.GetNumVerticesTotal() * SizePerVertex);
int vOffset = 0;

View File

@ -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 );

View File

@ -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

View File

@ -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<Far::PatchParam::BitField> & GetPatchBitFields() const {
return _patchBitFields;
}
/// The ordered array of control vertex indices for all the patches
const std::vector<Far::Index> & 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<float> 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<Far::PatchParam::BitField> _patchBitFields; // per-patch parametric info
Far::PatchTables::VertexValenceTable _vertexValenceTable; // extra Gregory patch data buffers
Far::PatchTables::QuadOffsetTable _quadOffsetTable;
Far::StencilTables _endcapStencilTables;
std::vector<float> _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
};

View File

@ -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<float> 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;
}

View File

@ -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<class OUTPUT_BUFFER>
void BindFacevaryingBuffers( VertexBufferDescriptor const & iDesc,
template<class INPUT_BUFFER, class OUTPUT_BUFFER>
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;
};

View File

@ -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;

View File

@ -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,

View File

@ -23,6 +23,9 @@
//
#include "../osd/cpuSmoothNormalContext.h"
#include "../far/topologyRefiner.h"
#include <string.h>
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; face<nfaces; ++face, dest+=4) {
Far::IndexArray fverts = refiner.GetFaceVertices(level, face);
memcpy(dest, fverts.begin(), 4 * sizeof(Far::Index));
}
}
CpuSmoothNormalContext *
CpuSmoothNormalContext::Create(Far::PatchTables const *patchTables, bool resetMemory) {
CpuSmoothNormalContext::Create(Far::TopologyRefiner const & refiner,
int level, bool resetMemory) {
return new CpuSmoothNormalContext(patchTables, resetMemory);
int maxlevel = refiner.GetMaxLevel();
assert((not refiner.IsUniform()) and (maxlevel>0) and
(level>0) and (level<maxlevel));
return new CpuSmoothNormalContext(refiner, level, resetMemory);
}
} // end namespace Osd

View File

@ -30,12 +30,17 @@
#include "../osd/nonCopyable.h"
#include "../osd/vertexDescriptor.h"
#include "../osd/vertex.h"
#include "../far/types.h"
#include "../far/patchTables.h"
#include <vector>
namespace OpenSubdiv {
namespace OPENSUBDIV_VERSION {
namespace Far {
class TopologyRefiner;
}
namespace Osd {
class CpuSmoothNormalContext : private NonCopyable<CpuSmoothNormalContext> {
@ -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<Far::Index> _faceVerts; // patch control vertices
VertexBufferDescriptor _iDesc,
_oDesc;

View File

@ -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; j<context->GetNumVertices(); ++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; k<nv; ++k) {
float * dst = oBuffer + cvs[idx+k]*oDesc.stride;
dst[0] += n[0];
dst[1] += n[1];
dst[2] += n[2];
}
// if necessary, reset all normal values to 0
if (context->GetResetMemory()) {
if (oDesc.length == oDesc.stride) {
memset(oBuffer, 0, nverts*oDesc.length*sizeof(float));
} else {
float * ptr = oBuffer;
for (int j=0; j<nverts; ++j, ptr += oDesc.stride) {
memset(ptr, 0, oDesc.length*sizeof(float));
}
}
}
Far::Index const * fverts = context->GetFaceVertices();
for (int face=0; face<nfaces; ++face, fverts+=4) {
float const * p0 = iBuffer + fverts[0]*iDesc.stride,
* p1 = iBuffer + fverts[1]*iDesc.stride,
* p2 = iBuffer + fverts[2]*iDesc.stride;
// compute face normal
float n[3];
cross( n, p0, p1, p2 );
// add normal to all vertices of the face
for (int i=0; i<4; ++i) {
float * dst = oBuffer + fverts[i]*oDesc.stride;
dst[0] += n[0];
dst[1] += n[1];
dst[2] += n[2];
}
}
}
CpuSmoothNormalController::CpuSmoothNormalController() {

View File

@ -88,8 +88,8 @@ D3D11DrawContext::create(Far::PatchTables const &patchTables,
ConvertPatchArrays(patchTables.GetPatchArrayVector(), _patchArrays, patchTables.GetMaxValence(), numVertexElements);
Far::PatchTables::PTable const & ptables = patchTables.GetPatchTable();
Far::PatchTables::PatchParamTable const & ptexCoordTables = patchTables.GetPatchParamTable();
Far::PatchTables::PatchVertsTable const & ptables = patchTables.GetPatchControlVerticesTable();
Far::PatchParamTable const & ptexCoordTables = patchTables.GetPatchParamTable();
int totalPatchIndices = (int)ptables.size();
int totalPatches = (int)ptexCoordTables.size();
@ -178,8 +178,8 @@ D3D11DrawContext::create(Far::PatchTables const &patchTables,
}
}
Far::PatchTables::QuadOffsetTable const &
quadOffsetTable = patchTables.GetQuadOffsetTable();
Far::PatchTables::QuadOffsetsTable const &
quadOffsetTable = patchTables.GetQuadOffsetsTable();
if (not quadOffsetTable.empty()) {
D3D11_BUFFER_DESC bd;
@ -219,7 +219,7 @@ D3D11DrawContext::SetFVarDataTexture(Far::PatchTables const & patchTables,
if (not fvarData.empty()) {
FVarData fvarDataTable;
packFVarData(patchTables, fvarWidth, fvarData, fvarDataTable);
ID3D11Device *pd3d11Device = NULL;

View File

@ -84,9 +84,9 @@ D3D11DrawRegistryBase::_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.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");
}
}

View File

@ -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<narrays; ++array) {
Far::PatchTables::PatchArray const &parray = farPatchArrays[i];
Far::PatchTables::Descriptor srcDesc = parray.GetDescriptor();
Far::PatchDescriptor srcDesc = patchTables.GetPatchArrayDescriptor(array);
for (int j = 0; j < numSubPatches; ++j) {
PatchDescriptor desc(srcDesc, maxValence, j, numElements);
int npatches = patchTables.GetNumPatches(array),
nsubpatches = subPatchCounts[(int)srcDesc.GetPattern()],
nverts = srcDesc.GetNumControlVertices();
osdPatchArrays.push_back(PatchArray(desc, parray.GetArrayRange()));
for (int i = 0; i < nsubpatches; ++i) {
PatchDescriptor desc(srcDesc, maxValence, i, numElements);
osdPatchArrays.push_back(PatchArray(desc, npatches, vidx, pidx, qidx));
}
vidx += npatches * nverts;
pidx += npatches;
qidx += (srcDesc.GetType() == Far::PatchDescriptor::GREGORY) ? npatches*nverts : 0;
}
}
// note : it is likely that Far::PatchTables::GetPatchControlVerticesTable()
// will eventually be deprecated if control vertices cannot be kept
// in a single linear array of indices. This function will help
// packing patch control vertices for GPU buffers.
void
DrawContext::packPatchVerts(Far::PatchTables const & patchTables,
std::vector<Index> & dst) {
dst.resize(patchTables.GetNumControlVerticesTotal());
Index * ptr = &dst[0];
int narrays = patchTables.GetNumPatchArrays();
for (int array=0; array<narrays; ++array) {
Far::IndexArray verts = patchTables.GetPatchArrayVertices(array);
memcpy(ptr, verts.begin(), verts.size()*sizeof(Index));
ptr += verts.size();
}
}
void
DrawContext::packFVarData(Far::PatchTables const & patchTables,
int fvarWidth, FVarData const & src, FVarData & dst) {
int fvarWidth, FVarData const & src, FVarData & dst) {
assert(fvarWidth and (not src.empty()));

View File

@ -71,18 +71,18 @@ public:
/// @param numElements The size of the vertex and varying data per-vertex
/// (in floats)
///
PatchDescriptor(Far::PatchTables::Descriptor farDesc, unsigned char maxValence,
PatchDescriptor(Far::PatchDescriptor farDesc, unsigned char maxValence,
unsigned char subPatch, unsigned char numElements) :
_farDesc(farDesc), _maxValence(maxValence), _subPatch(subPatch), _numElements(numElements) { }
/// Returns the type of the patch
Far::PatchTables::Type GetType() const {
Far::PatchDescriptor::Type GetType() const {
return _farDesc.GetType();
}
/// Returns the transition pattern of the patch if any (5 types)
Far::PatchTables::TransitionPattern GetPattern() const {
Far::PatchDescriptor::TransitionPattern GetPattern() const {
return _farDesc.GetPattern();
}
@ -124,23 +124,33 @@ public:
bool operator == ( PatchDescriptor const other ) const;
private:
Far::PatchTables::Descriptor _farDesc;
Far::PatchDescriptor _farDesc;
unsigned char _maxValence;
unsigned char _subPatch;
unsigned char _numElements;
};
typedef Far::Index Index;
class PatchArray {
public:
/// Constructor
///
/// @param desc Patch descriptor defines the type, pattern, rotation of
/// the patches in the array
/// @param desc Patch descriptor defines the type, pattern, rotation of
/// the patches in the array
///
/// @param range The range of vertex indices
/// @param npatches The number of patches in the array
///
PatchArray(PatchDescriptor desc, Far::PatchTables::PatchArray::ArrayRange const & range) :
_desc(desc), _range(range) { }
/// @param vertIndex Index of the first control vertex in the array
///
/// @param patchIndex Index of the first patch in the array
///
/// @param qoIndex Index of the first quad-offset entry
///
PatchArray(PatchDescriptor desc, int npatches,
Index vertIndex, Index patchIndex, Index qoIndex) :
_desc(desc), _npatches(npatches),
_vertIndex(vertIndex), _patchIndex(patchIndex), _quadOffsetIndex(qoIndex) { }
/// Returns a patch descriptor defining the type of patches in the array
PatchDescriptor GetDescriptor() const {
@ -152,46 +162,44 @@ public:
_desc = desc;
}
/// Returns a array range struct
Far::PatchTables::PatchArray::ArrayRange const & GetArrayRange() const {
return _range;
}
/// Returns the index of the first control vertex of the first patch
/// of this array in the global PTable
unsigned int GetVertIndex() const {
return _range.vertIndex;
return _vertIndex;
}
/// Returns the global index of the first patch in this array (Used to
/// access ptex / fvar table data)
unsigned int GetPatchIndex() const {
return _range.patchIndex;
return _patchIndex;
}
/// Returns the number of patches in the array
unsigned int GetNumPatches() const {
return _range.npatches;
return _npatches;
}
/// Returns the number of patch indices in the array
unsigned int GetNumIndices() const {
return _range.npatches * _desc.GetNumControlVertices();
return _npatches * _desc.GetNumControlVertices();
}
/// Returns the offset of quad offset table
unsigned int GetQuadOffsetIndex() const {
return _range.quadOffsetIndex;
return _quadOffsetIndex;
}
/// Set num patches (used at batch glomming)
void SetNumPatches(int npatches) {
_range.npatches = npatches;
_npatches = npatches;
}
private:
PatchDescriptor _desc;
Far::PatchTables::PatchArray::ArrayRange _range;
int _npatches;
Index _vertIndex,
_patchIndex,
_quadOffsetIndex;
};
/// Constructor
@ -220,17 +228,19 @@ public:
// processes FarPatchArrays and inserts requisite sub-patches for the arrays
// containing transition patches
static void ConvertPatchArrays(Far::PatchTables::PatchArrayVector const &farPatchArrays,
DrawContext::PatchArrayVector &osdPatchArrays,
int maxValence, int numElements);
static void ConvertPatchArrays(Far::PatchTables const &patchTables,
DrawContext::PatchArrayVector &osdPatchArrays, int maxValence, int numElements);
typedef std::vector<float> FVarData;
protected:
static void packPatchVerts(Far::PatchTables const & patchTables,
std::vector<Index> & 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;

View File

@ -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
};

View File

@ -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()) {

View File

@ -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);

View File

@ -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; j<context->GetNumVertices(); ++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; i<nfaces; ++i) {
int idx = i*4;
float const * p0 = iBuffer + fverts[idx+0]*iDesc.stride,
* p1 = iBuffer + fverts[idx+1]*iDesc.stride,
* p2 = iBuffer + fverts[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 j=0; j<4; ++j) {
float * dst = oBuffer + fverts[idx+j]*oDesc.stride;
dst[0] += n[0];
dst[1] += n[1];
dst[2] += n[2];
}
}
}
}
/*
void OmpSmoothNormalController::_smootheNormals(
CpuSmoothNormalContext * context) {
@ -118,7 +168,7 @@ void OmpSmoothNormalController::_smootheNormals(
}
}
*/
OmpSmoothNormalController::OmpSmoothNormalController() {
}

View File

@ -146,52 +146,33 @@ void TbbSmoothNormalController::_smootheNormals(
CpuSmoothNormalContext * context) {
VertexBufferDescriptor const & iDesc = context->GetInputVertexDescriptor(),
& 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<Far::Index> 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<int> 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<int> 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<int> range(0, pa.GetNumPatches(), grain_size);
tbb::parallel_for(range, smoothNormalkernel);
}
}
tbb::blocked_range<int> range(0, nfaces, grain_size);
tbb::parallel_for(range, smoothNormalkernel);
}
}