mirror of
https://github.com/PixarAnimationStudios/OpenSubdiv
synced 2024-09-19 22:30:05 +00:00
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:
parent
a9c32d6705
commit
b27b55e4a8
@ -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];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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 */
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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:
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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:
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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]);
|
||||
|
@ -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];
|
||||
}
|
||||
|
||||
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;
|
||||
iptrs.getValue( *it ) = result->getPatchArrayVertices(arrayIndex).begin();
|
||||
pptrs.getValue( *it ) = result->getPatchParams(arrayIndex).begin();
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
112
opensubdiv/far/patchDescriptor.cpp
Normal file
112
opensubdiv/far/patchDescriptor.cpp
Normal 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
|
238
opensubdiv/far/patchDescriptor.h
Normal file
238
opensubdiv/far/patchDescriptor.h
Normal 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 */
|
@ -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
|
||||
|
@ -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
|
||||
@ -105,7 +99,6 @@ struct PatchParam {
|
||||
/// 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;
|
||||
@ -114,7 +107,6 @@ struct PatchParam {
|
||||
/// orientations.
|
||||
///
|
||||
/// @param u u parameter
|
||||
///
|
||||
/// @param v v parameter
|
||||
///
|
||||
void Rotate( float & u, float & v ) const;
|
||||
@ -147,6 +139,20 @@ struct PatchParam {
|
||||
}
|
||||
};
|
||||
|
||||
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()) {
|
||||
|
@ -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
|
||||
|
@ -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<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 {
|
||||
|
@ -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;
|
||||
|
@ -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 );
|
||||
|
||||
|
@ -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
|
||||
|
@ -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 {
|
||||
@ -54,83 +49,24 @@ public:
|
||||
///
|
||||
/// @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
|
||||
};
|
||||
|
||||
|
||||
|
@ -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,
|
||||
computeSubPatchCoords(ptables.GetPatchParam(*handle), s, t);
|
||||
|
||||
Far::IndexArray cvs = ptables.GetPatchVertices(*handle);
|
||||
|
||||
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::BOUNDARY : evalBoundary( t, s, cvs,
|
||||
case Desc::BOUNDARY : evalBoundary( t, s, cvs.begin(),
|
||||
vertexData.inDesc,
|
||||
vertexData.in,
|
||||
outDesc,
|
||||
out, outDu, outDv );
|
||||
break;
|
||||
|
||||
case Far::PatchTables::CORNER : evalCorner( t, s, cvs,
|
||||
case Desc::CORNER : evalCorner( t, s, cvs.begin(),
|
||||
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(),
|
||||
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 Far::PatchTables::GREGORY_BOUNDARY :
|
||||
evalGregoryBoundary( t, s, cvs,
|
||||
&context->GetVertexValenceTable()[0],
|
||||
&context->GetQuadOffsetTable()[ parray.GetQuadOffsetIndex() + handle->vertexOffset ],
|
||||
context->GetMaxValence(),
|
||||
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 Far::PatchTables::GREGORY_BASIS :
|
||||
assert(context->GetEndCapStencilTables().GetNumStencils()>0);
|
||||
case Desc::GREGORY_BASIS : {
|
||||
Far::StencilTables const * stencils =
|
||||
ptables.GetEndCapStencilTables();
|
||||
assert(stencils and stencils->GetNumStencils()>0);
|
||||
evalGregoryBasis( t, s,
|
||||
context->GetEndCapStencilTables(),
|
||||
handle->vertexOffset,
|
||||
*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,
|
||||
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,
|
||||
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,
|
||||
case Desc::CORNER : evalCorner( t, s, cvs.begin(),
|
||||
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(),
|
||||
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(),
|
||||
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 Far::PatchTables::GREGORY_BASIS :
|
||||
assert(context->GetEndCapStencilTables().GetNumStencils()>0);
|
||||
case Desc::GREGORY_BASIS : {
|
||||
Far::StencilTables const * stencils =
|
||||
ptables.GetEndCapStencilTables();
|
||||
assert(stencils and stencils->GetNumStencils()>0);
|
||||
evalGregoryBasis( s, t,
|
||||
context->GetEndCapStencilTables(),
|
||||
handle->vertexOffset,
|
||||
*stencils,
|
||||
ptables.GetEndCapStencilIndex(*handle),
|
||||
vertexData.inDesc,
|
||||
vertexData.in,
|
||||
vertexData.outDesc,
|
||||
out, outDu, outDv );
|
||||
break;
|
||||
} 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;
|
||||
}
|
||||
|
@ -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;
|
||||
float * in,
|
||||
* out;
|
||||
};
|
||||
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -93,7 +93,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,
|
||||
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -58,48 +58,36 @@ void CpuSmoothNormalController::_smootheNormals(
|
||||
float const * iBuffer = context->GetCurrentInputVertexBuffer() + iDesc.offset;
|
||||
float * oBuffer = context->GetCurrentOutputVertexBuffer() + oDesc.offset;
|
||||
|
||||
Far::PatchTables::PTable const & cvs = context->GetControlVertices();
|
||||
|
||||
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);
|
||||
int nfaces = context->GetNumFaces(),
|
||||
nverts = context->GetNumVertices();
|
||||
|
||||
// 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<context->GetNumVertices(); ++j, ptr += oDesc.stride) {
|
||||
for (int j=0; j<nverts; ++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) {
|
||||
Far::Index const * fverts = context->GetFaceVertices();
|
||||
for (int face=0; face<nfaces; ++face, fverts+=4) {
|
||||
|
||||
|
||||
float const * p0 = iBuffer + cvs[idx+0]*iDesc.stride,
|
||||
* p1 = iBuffer + cvs[idx+1]*iDesc.stride,
|
||||
* p2 = iBuffer + cvs[idx+2]*iDesc.stride;
|
||||
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 k=0; k<nv; ++k) {
|
||||
for (int i=0; i<4; ++i) {
|
||||
|
||||
float * dst = oBuffer + cvs[idx+k]*oDesc.stride;
|
||||
float * dst = oBuffer + fverts[i]*oDesc.stride;
|
||||
|
||||
dst[0] += n[0];
|
||||
dst[1] += n[1];
|
||||
@ -107,9 +95,6 @@ void CpuSmoothNormalController::_smootheNormals(
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
CpuSmoothNormalController::CpuSmoothNormalController() {
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
@ -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,18 +53,44 @@ 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();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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,12 +124,14 @@ 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
|
||||
@ -137,10 +139,18 @@ public:
|
||||
/// @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,15 +228,17 @@ 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);
|
||||
|
||||
|
@ -40,9 +40,7 @@ namespace Osd {
|
||||
|
||||
/// \brief Coordinates set on a limit surface
|
||||
///
|
||||
class LimitLocation {
|
||||
|
||||
public:
|
||||
struct LimitLocation {
|
||||
|
||||
LimitLocation() { }
|
||||
|
||||
|
@ -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()) {
|
||||
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
@ -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() {
|
||||
}
|
||||
|
||||
|
@ -150,27 +150,7 @@ void TbbSmoothNormalController::_smootheNormals(
|
||||
|
||||
assert(iDesc.length==3 and oDesc.length==3);
|
||||
|
||||
float const * iBuffer = context->GetCurrentInputVertexBuffer() + iDesc.offset;
|
||||
float * oBuffer = context->GetCurrentOutputVertexBuffer() + oDesc.offset;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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) {
|
||||
|
||||
|
||||
// if necessary, reset all normal values to 0
|
||||
if (context->GetResetMemory()) {
|
||||
|
||||
TBBResetKernel resetKernel(oBuffer, oDesc.stride);
|
||||
@ -178,21 +158,22 @@ void TbbSmoothNormalController::_smootheNormals(
|
||||
tbb::parallel_for(range, resetKernel);
|
||||
}
|
||||
|
||||
{
|
||||
int nv = Far::PatchTables::Descriptor::GetNumControlVertices(type);
|
||||
{ // note: quads only !
|
||||
float const * iBuffer = context->GetCurrentInputVertexBuffer() + iDesc.offset;
|
||||
|
||||
Far::Index const * fverts = context->GetFaceVertices();
|
||||
|
||||
int nfaces = context->GetNumFaces();
|
||||
|
||||
TBBSmoothNormalKernel smoothNormalkernel( iBuffer,
|
||||
iDesc.stride,
|
||||
oBuffer,
|
||||
oDesc.stride,
|
||||
&verts[pa.GetVertIndex()],
|
||||
nv);
|
||||
fverts, 4 );
|
||||
|
||||
tbb::blocked_range<int> range(0, pa.GetNumPatches(), grain_size);
|
||||
tbb::blocked_range<int> range(0, nfaces, grain_size);
|
||||
tbb::parallel_for(range, smoothNormalkernel);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TbbSmoothNormalController::TbbSmoothNormalController() {
|
||||
|
Loading…
Reference in New Issue
Block a user