mirror of
https://github.com/PixarAnimationStudios/OpenSubdiv
synced 2024-12-03 16:31:04 +00:00
Enable GregoryBasis patch.
PatchTablesFactory fills 20 indices topology into patchtable, and use it for eval and draw. note: currently screen-space adaptive tessellation of gregory basis patches is broken and cracks appear around them.
This commit is contained in:
parent
5415bc23b9
commit
24f9dc154b
@ -30,7 +30,7 @@ static float _colors[5][7][4] = {{{1.0f, 1.0f, 1.0f, 1.0f}, // regular
|
|||||||
{0.0f, 1.0f, 0.0f, 1.0f}, // corner
|
{0.0f, 1.0f, 0.0f, 1.0f}, // corner
|
||||||
{1.0f, 1.0f, 0.0f, 1.0f}, // gregory
|
{1.0f, 1.0f, 0.0f, 1.0f}, // gregory
|
||||||
{1.0f, 0.5f, 0.0f, 1.0f}, // gregory boundary
|
{1.0f, 0.5f, 0.0f, 1.0f}, // gregory boundary
|
||||||
{1.0f, 1.0f, 0.0f, 1.0f}}, // gregory basis
|
{1.0f, 0.7f, 0.3f, 1.0f}}, // gregory basis
|
||||||
|
|
||||||
{{0.0f, 1.0f, 1.0f, 1.0f}, // regular pattern 0
|
{{0.0f, 1.0f, 1.0f, 1.0f}, // regular pattern 0
|
||||||
{0.0f, 0.5f, 1.0f, 1.0f}, // regular pattern 1
|
{0.0f, 0.5f, 1.0f, 1.0f}, // regular pattern 1
|
||||||
|
@ -376,26 +376,50 @@ createOsdMesh(ShapeDesc const & shapeDesc, int level) {
|
|||||||
Far::StencilTables const * varyingStencils =
|
Far::StencilTables const * varyingStencils =
|
||||||
Far::StencilTablesFactory::Create(*g_topologyRefiner, soptions);
|
Far::StencilTablesFactory::Create(*g_topologyRefiner, soptions);
|
||||||
|
|
||||||
g_kernelBatches.clear();
|
|
||||||
g_kernelBatches.push_back(Far::StencilTablesFactory::Create(*vertexStencils));
|
|
||||||
|
|
||||||
// Create an Osd Compute context, used to "pose" the vertices with
|
|
||||||
// the stencils tables
|
|
||||||
delete g_computeCtx;
|
|
||||||
g_computeCtx = Osd::CpuComputeContext::Create(vertexStencils, varyingStencils);
|
|
||||||
|
|
||||||
|
|
||||||
// Generate bi-cubic patch tables for the limit surface
|
// Generate bi-cubic patch tables for the limit surface
|
||||||
Far::PatchTablesFactory::Options poptions;
|
Far::PatchTablesFactory::Options poptions;
|
||||||
// optional : pass the vertex stencils so that the factory can generate gregory basis
|
// optional : pass the vertex stencils so that the factory can generate gregory basis
|
||||||
// stencils (faster evaluation)
|
// stencils (faster evaluation)
|
||||||
poptions.adaptiveStencilTables = vertexStencils;
|
poptions.adaptiveStencilTables = vertexStencils;
|
||||||
|
poptions.adaptiveVaryingStencilTables = varyingStencils;
|
||||||
|
|
||||||
Far::PatchTables const * patchTables =
|
Far::PatchTables const * patchTables =
|
||||||
Far::PatchTablesFactory::Create(*g_topologyRefiner, poptions);
|
Far::PatchTablesFactory::Create(*g_topologyRefiner, poptions);
|
||||||
|
|
||||||
|
Far::StencilTables const *inStencils[] = {
|
||||||
|
vertexStencils, patchTables->GetEndCapVertexStencilTables()
|
||||||
|
};
|
||||||
|
Far::StencilTables const *concatStencils =
|
||||||
|
Far::StencilTablesFactory::Create(2, inStencils);
|
||||||
|
|
||||||
|
// add gregory basis vertices FIXME:
|
||||||
|
if (patchTables->GetEndCapVertexStencilTables()) {
|
||||||
|
nverts += patchTables->GetEndCapVertexStencilTables()->GetNumStencils();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Far::StencilTables const *concatVaryingStencils = varyingStencils;
|
||||||
|
if (varyingStencils and patchTables->GetEndCapVaryingStencilTables()) {
|
||||||
|
Far::StencilTables const *inVaryingStencils[] = {
|
||||||
|
varyingStencils, patchTables->GetEndCapVaryingStencilTables()
|
||||||
|
};
|
||||||
|
concatVaryingStencils =
|
||||||
|
Far::StencilTablesFactory::Create(2, inVaryingStencils);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create an Osd Compute context, used to "pose" the vertices with
|
||||||
|
// the stencils tables
|
||||||
|
delete g_computeCtx;
|
||||||
|
g_computeCtx = Osd::CpuComputeContext::Create(concatStencils, concatVaryingStencils);
|
||||||
|
|
||||||
|
|
||||||
// Create a limit Eval context with the patch tables
|
// Create a limit Eval context with the patch tables
|
||||||
delete g_evalCtx;
|
delete g_evalCtx;
|
||||||
g_evalCtx = Osd::CpuEvalLimitContext::Create(*patchTables);
|
g_evalCtx = Osd::CpuEvalLimitContext::Create(*patchTables);
|
||||||
|
|
||||||
|
g_kernelBatches.clear();
|
||||||
|
g_kernelBatches.push_back(Far::StencilTablesFactory::Create(*concatStencils));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
{ // Create vertex primvar buffer for the CVs
|
{ // Create vertex primvar buffer for the CVs
|
||||||
|
@ -56,6 +56,7 @@ static std::vector<ShapeDesc> g_defaultShapes;
|
|||||||
#include <shapes/catmark_fan.h>
|
#include <shapes/catmark_fan.h>
|
||||||
#include <shapes/catmark_flap.h>
|
#include <shapes/catmark_flap.h>
|
||||||
#include <shapes/catmark_flap2.h>
|
#include <shapes/catmark_flap2.h>
|
||||||
|
#include <shapes/catmark_gregory_test0.h>
|
||||||
#include <shapes/catmark_gregory_test1.h>
|
#include <shapes/catmark_gregory_test1.h>
|
||||||
#include <shapes/catmark_gregory_test2.h>
|
#include <shapes/catmark_gregory_test2.h>
|
||||||
#include <shapes/catmark_gregory_test3.h>
|
#include <shapes/catmark_gregory_test3.h>
|
||||||
@ -103,6 +104,7 @@ static void initShapes() {
|
|||||||
g_defaultShapes.push_back( ShapeDesc("catmark_fan", catmark_fan, kCatmark ) );
|
g_defaultShapes.push_back( ShapeDesc("catmark_fan", catmark_fan, kCatmark ) );
|
||||||
g_defaultShapes.push_back( ShapeDesc("catmark_flap", catmark_flap, kCatmark ) );
|
g_defaultShapes.push_back( ShapeDesc("catmark_flap", catmark_flap, kCatmark ) );
|
||||||
g_defaultShapes.push_back( ShapeDesc("catmark_flap2", catmark_flap2, kCatmark ) );
|
g_defaultShapes.push_back( ShapeDesc("catmark_flap2", catmark_flap2, kCatmark ) );
|
||||||
|
g_defaultShapes.push_back( ShapeDesc("catmark_gregory_test0", catmark_gregory_test0, kCatmark ) );
|
||||||
g_defaultShapes.push_back( ShapeDesc("catmark_gregory_test1", catmark_gregory_test1, kCatmark ) );
|
g_defaultShapes.push_back( ShapeDesc("catmark_gregory_test1", catmark_gregory_test1, kCatmark ) );
|
||||||
g_defaultShapes.push_back( ShapeDesc("catmark_gregory_test2", catmark_gregory_test2, kCatmark ) );
|
g_defaultShapes.push_back( ShapeDesc("catmark_gregory_test2", catmark_gregory_test2, kCatmark ) );
|
||||||
g_defaultShapes.push_back( ShapeDesc("catmark_gregory_test3", catmark_gregory_test3, kCatmark ) );
|
g_defaultShapes.push_back( ShapeDesc("catmark_gregory_test3", catmark_gregory_test3, kCatmark ) );
|
||||||
|
@ -1033,6 +1033,7 @@ createOsdMesh(int level, int kernel) {
|
|||||||
OpenSubdiv::Osd::MeshBitset bits;
|
OpenSubdiv::Osd::MeshBitset bits;
|
||||||
bits.set(OpenSubdiv::Osd::MeshAdaptive, doAdaptive);
|
bits.set(OpenSubdiv::Osd::MeshAdaptive, doAdaptive);
|
||||||
bits.set(OpenSubdiv::Osd::MeshPtexData, true);
|
bits.set(OpenSubdiv::Osd::MeshPtexData, true);
|
||||||
|
bits.set(OpenSubdiv::Osd::MeshUseGregoryBasis, true);
|
||||||
|
|
||||||
int numVertexElements = g_adaptive ? 3 : 6;
|
int numVertexElements = g_adaptive ? 3 : 6;
|
||||||
int numVaryingElements = 0;
|
int numVaryingElements = 0;
|
||||||
|
@ -535,6 +535,7 @@ createOsdMesh(ShapeDesc const & shapeDesc, int level, int kernel, Scheme scheme=
|
|||||||
bits.set(OpenSubdiv::Osd::MeshUseSingleCreasePatch, doSingleCreasePatch);
|
bits.set(OpenSubdiv::Osd::MeshUseSingleCreasePatch, doSingleCreasePatch);
|
||||||
bits.set(OpenSubdiv::Osd::MeshInterleaveVarying, interleaveVarying);
|
bits.set(OpenSubdiv::Osd::MeshInterleaveVarying, interleaveVarying);
|
||||||
bits.set(OpenSubdiv::Osd::MeshFVarData, g_displayStyle == kFaceVaryingColor);
|
bits.set(OpenSubdiv::Osd::MeshFVarData, g_displayStyle == kFaceVaryingColor);
|
||||||
|
bits.set(OpenSubdiv::Osd::MeshUseGregoryBasis, true);
|
||||||
|
|
||||||
int numVertexElements = 3;
|
int numVertexElements = 3;
|
||||||
int numVaryingElements =
|
int numVaryingElements =
|
||||||
@ -1157,7 +1158,7 @@ display() {
|
|||||||
g_mesh->GetDrawContext()->GetPatchArrays();
|
g_mesh->GetDrawContext()->GetPatchArrays();
|
||||||
|
|
||||||
// patch drawing
|
// patch drawing
|
||||||
int patchCount[12][6][4]; // [Type][Pattern][Rotation] (see far/patchTables.h)
|
int patchCount[13][6][4]; // [Type][Pattern][Rotation] (see far/patchTables.h)
|
||||||
int numTotalPatches = 0;
|
int numTotalPatches = 0;
|
||||||
int numDrawCalls = 0;
|
int numDrawCalls = 0;
|
||||||
memset(patchCount, 0, sizeof(patchCount));
|
memset(patchCount, 0, sizeof(patchCount));
|
||||||
@ -1300,6 +1301,8 @@ display() {
|
|||||||
patchCount[Descriptor::GREGORY][0][0]); y+= 20;
|
patchCount[Descriptor::GREGORY][0][0]); y+= 20;
|
||||||
g_hud.DrawString(x, y, "Boundary Gregory : %d",
|
g_hud.DrawString(x, y, "Boundary Gregory : %d",
|
||||||
patchCount[Descriptor::GREGORY_BOUNDARY][0][0]); y+= 20;
|
patchCount[Descriptor::GREGORY_BOUNDARY][0][0]); y+= 20;
|
||||||
|
g_hud.DrawString(x, y, "Gregory Basis : %d",
|
||||||
|
patchCount[Descriptor::GREGORY_BASIS][0][0]); y+= 20;
|
||||||
g_hud.DrawString(x, y, "Trans. Regular : %d %d %d %d %d",
|
g_hud.DrawString(x, y, "Trans. Regular : %d %d %d %d %d",
|
||||||
patchCount[Descriptor::REGULAR][Descriptor::PATTERN0][0],
|
patchCount[Descriptor::REGULAR][Descriptor::PATTERN0][0],
|
||||||
patchCount[Descriptor::REGULAR][Descriptor::PATTERN1][0],
|
patchCount[Descriptor::REGULAR][Descriptor::PATTERN1][0],
|
||||||
|
@ -60,6 +60,7 @@ static std::vector<ShapeDesc> g_defaultShapes;
|
|||||||
#include <shapes/catmark_fvar_bound0.h>
|
#include <shapes/catmark_fvar_bound0.h>
|
||||||
#include <shapes/catmark_fvar_bound1.h>
|
#include <shapes/catmark_fvar_bound1.h>
|
||||||
#include <shapes/catmark_fvar_bound2.h>
|
#include <shapes/catmark_fvar_bound2.h>
|
||||||
|
#include <shapes/catmark_gregory_test0.h>
|
||||||
#include <shapes/catmark_gregory_test1.h>
|
#include <shapes/catmark_gregory_test1.h>
|
||||||
#include <shapes/catmark_gregory_test2.h>
|
#include <shapes/catmark_gregory_test2.h>
|
||||||
#include <shapes/catmark_gregory_test3.h>
|
#include <shapes/catmark_gregory_test3.h>
|
||||||
@ -126,6 +127,7 @@ static void initShapes() {
|
|||||||
g_defaultShapes.push_back( ShapeDesc("catmark_fvar_bound0", catmark_fvar_bound0, kCatmark ) );
|
g_defaultShapes.push_back( ShapeDesc("catmark_fvar_bound0", catmark_fvar_bound0, kCatmark ) );
|
||||||
g_defaultShapes.push_back( ShapeDesc("catmark_fvar_bound1", catmark_fvar_bound1, kCatmark ) );
|
g_defaultShapes.push_back( ShapeDesc("catmark_fvar_bound1", catmark_fvar_bound1, kCatmark ) );
|
||||||
g_defaultShapes.push_back( ShapeDesc("catmark_fvar_bound2", catmark_fvar_bound2, kCatmark ) );
|
g_defaultShapes.push_back( ShapeDesc("catmark_fvar_bound2", catmark_fvar_bound2, kCatmark ) );
|
||||||
|
g_defaultShapes.push_back( ShapeDesc("catmark_gregory_test0", catmark_gregory_test0, kCatmark ) );
|
||||||
g_defaultShapes.push_back( ShapeDesc("catmark_gregory_test1", catmark_gregory_test1, kCatmark ) );
|
g_defaultShapes.push_back( ShapeDesc("catmark_gregory_test1", catmark_gregory_test1, kCatmark ) );
|
||||||
g_defaultShapes.push_back( ShapeDesc("catmark_gregory_test2", catmark_gregory_test2, kCatmark ) );
|
g_defaultShapes.push_back( ShapeDesc("catmark_gregory_test2", catmark_gregory_test2, kCatmark ) );
|
||||||
g_defaultShapes.push_back( ShapeDesc("catmark_gregory_test3", catmark_gregory_test3, kCatmark ) );
|
g_defaultShapes.push_back( ShapeDesc("catmark_gregory_test3", catmark_gregory_test3, kCatmark ) );
|
||||||
|
@ -160,6 +160,7 @@ out block {
|
|||||||
void emit(int index, vec3 normal)
|
void emit(int index, vec3 normal)
|
||||||
{
|
{
|
||||||
outpt.v.position = inpt[index].v.position;
|
outpt.v.position = inpt[index].v.position;
|
||||||
|
outpt.v.patchCoord = inpt[index].v.patchCoord;
|
||||||
#ifdef SMOOTH_NORMALS
|
#ifdef SMOOTH_NORMALS
|
||||||
outpt.v.normal = inpt[index].v.normal;
|
outpt.v.normal = inpt[index].v.normal;
|
||||||
#else
|
#else
|
||||||
|
@ -103,7 +103,7 @@ vec2 computeUV( int c )
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uniform float scale=0.025;
|
uniform float scale=0.01;
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
@ -116,10 +116,14 @@ void main()
|
|||||||
|
|
||||||
vec2 ofs = inpt[0].data.xy;
|
vec2 ofs = inpt[0].data.xy;
|
||||||
|
|
||||||
emit(0, scale * (vec2( 1.0, -2.0)+ofs), uv + dim);
|
vec4 clipPos = ProjectionMatrix * inpt[0].position;
|
||||||
emit(1, scale * (vec2( 1.0, 2.0)+ofs), vec2(uv.x+dim.x, uv.y));
|
|
||||||
emit(2, scale * (vec2(-1.0, -2.0)+ofs), vec2(uv.x, uv.y+dim.y));
|
float s = scale * clipPos.w;
|
||||||
emit(3, scale * (vec2(-1.0, 2.0)+ofs), uv);
|
|
||||||
|
emit(0, s * (vec2( 1.0, -2.0)+ofs), uv + dim);
|
||||||
|
emit(1, s * (vec2( 1.0, 2.0)+ofs), vec2(uv.x+dim.x, uv.y));
|
||||||
|
emit(2, s * (vec2(-1.0, -2.0)+ofs), vec2(uv.x, uv.y+dim.y));
|
||||||
|
emit(3, s * (vec2(-1.0, 2.0)+ofs), uv);
|
||||||
|
|
||||||
EndPrimitive();
|
EndPrimitive();
|
||||||
}
|
}
|
||||||
|
@ -59,6 +59,7 @@ static std::vector<ShapeDesc> g_shapes;
|
|||||||
#include <shapes/catmark_fvar_bound0.h>
|
#include <shapes/catmark_fvar_bound0.h>
|
||||||
#include <shapes/catmark_fvar_bound1.h>
|
#include <shapes/catmark_fvar_bound1.h>
|
||||||
#include <shapes/catmark_fvar_bound2.h>
|
#include <shapes/catmark_fvar_bound2.h>
|
||||||
|
#include <shapes/catmark_gregory_test0.h>
|
||||||
#include <shapes/catmark_gregory_test1.h>
|
#include <shapes/catmark_gregory_test1.h>
|
||||||
#include <shapes/catmark_gregory_test2.h>
|
#include <shapes/catmark_gregory_test2.h>
|
||||||
#include <shapes/catmark_gregory_test3.h>
|
#include <shapes/catmark_gregory_test3.h>
|
||||||
@ -76,6 +77,8 @@ static std::vector<ShapeDesc> g_shapes;
|
|||||||
#include <shapes/catmark_tent.h>
|
#include <shapes/catmark_tent.h>
|
||||||
#include <shapes/catmark_torus.h>
|
#include <shapes/catmark_torus.h>
|
||||||
#include <shapes/catmark_torus_creases0.h>
|
#include <shapes/catmark_torus_creases0.h>
|
||||||
|
#include <shapes/catmark_smoothtris0.h>
|
||||||
|
#include <shapes/catmark_smoothtris1.h>
|
||||||
|
|
||||||
#include <shapes/loop_cube_creases0.h>
|
#include <shapes/loop_cube_creases0.h>
|
||||||
#include <shapes/loop_cube_creases1.h>
|
#include <shapes/loop_cube_creases1.h>
|
||||||
@ -113,6 +116,7 @@ static void initShapes() {
|
|||||||
g_shapes.push_back( ShapeDesc("catmark_fvar_bound0", catmark_fvar_bound0, kCatmark ) );
|
g_shapes.push_back( ShapeDesc("catmark_fvar_bound0", catmark_fvar_bound0, kCatmark ) );
|
||||||
g_shapes.push_back( ShapeDesc("catmark_fvar_bound1", catmark_fvar_bound1, kCatmark ) );
|
g_shapes.push_back( ShapeDesc("catmark_fvar_bound1", catmark_fvar_bound1, kCatmark ) );
|
||||||
g_shapes.push_back( ShapeDesc("catmark_fvar_bound2", catmark_fvar_bound2, kCatmark ) );
|
g_shapes.push_back( ShapeDesc("catmark_fvar_bound2", catmark_fvar_bound2, kCatmark ) );
|
||||||
|
g_shapes.push_back( ShapeDesc("catmark_gregory_test0", catmark_gregory_test0, kCatmark ) );
|
||||||
g_shapes.push_back( ShapeDesc("catmark_gregory_test1", catmark_gregory_test1, kCatmark ) );
|
g_shapes.push_back( ShapeDesc("catmark_gregory_test1", catmark_gregory_test1, kCatmark ) );
|
||||||
g_shapes.push_back( ShapeDesc("catmark_gregory_test2", catmark_gregory_test2, kCatmark ) );
|
g_shapes.push_back( ShapeDesc("catmark_gregory_test2", catmark_gregory_test2, kCatmark ) );
|
||||||
g_shapes.push_back( ShapeDesc("catmark_gregory_test3", catmark_gregory_test3, kCatmark ) );
|
g_shapes.push_back( ShapeDesc("catmark_gregory_test3", catmark_gregory_test3, kCatmark ) );
|
||||||
@ -131,6 +135,8 @@ static void initShapes() {
|
|||||||
g_shapes.push_back( ShapeDesc("catmark_tent", catmark_tent, kCatmark ) );
|
g_shapes.push_back( ShapeDesc("catmark_tent", catmark_tent, kCatmark ) );
|
||||||
g_shapes.push_back( ShapeDesc("catmark_torus", catmark_torus, kCatmark ) );
|
g_shapes.push_back( ShapeDesc("catmark_torus", catmark_torus, kCatmark ) );
|
||||||
g_shapes.push_back( ShapeDesc("catmark_torus_creases0", catmark_torus_creases0, kCatmark ) );
|
g_shapes.push_back( ShapeDesc("catmark_torus_creases0", catmark_torus_creases0, kCatmark ) );
|
||||||
|
g_shapes.push_back( ShapeDesc("catmark_smoothtris0", catmark_smoothtris0, kCatmark ) );
|
||||||
|
g_shapes.push_back( ShapeDesc("catmark_smoothtris1", catmark_smoothtris1, kCatmark ) );
|
||||||
g_shapes.push_back( ShapeDesc("catmark_car", catmark_car, kCatmark ) );
|
g_shapes.push_back( ShapeDesc("catmark_car", catmark_car, kCatmark ) );
|
||||||
g_shapes.push_back( ShapeDesc("catmark_bishop", catmark_bishop, kCatmark ) );
|
g_shapes.push_back( ShapeDesc("catmark_bishop", catmark_bishop, kCatmark ) );
|
||||||
|
|
||||||
|
@ -635,23 +635,18 @@ createGregoryBasis(OpenSubdiv::Far::PatchTables const & patchTables,
|
|||||||
typedef OpenSubdiv::Far::PatchDescriptor PatchDescriptor;
|
typedef OpenSubdiv::Far::PatchDescriptor PatchDescriptor;
|
||||||
|
|
||||||
int npatches = 0;
|
int npatches = 0;
|
||||||
|
int patchArray = 0;
|
||||||
for (int array=0; array<(int)patchTables.GetNumPatchArrays(); ++array) {
|
for (int array=0; array<(int)patchTables.GetNumPatchArrays(); ++array) {
|
||||||
if (patchTables.GetPatchArrayDescriptor(array).GetType()==
|
if (patchTables.GetPatchArrayDescriptor(array).GetType()==
|
||||||
PatchDescriptor::GREGORY_BASIS) {
|
PatchDescriptor::GREGORY_BASIS) {
|
||||||
npatches = patchTables.GetNumPatches(array);
|
npatches = patchTables.GetNumPatches(array);
|
||||||
|
patchArray = array;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int nedges = npatches * 20;
|
int nedges = npatches * 20;
|
||||||
std::vector<int> vertsperedge(nedges), edgeindices(nedges*2);
|
std::vector<int> vertsperedge(nedges), edgeindices(nedges*2);
|
||||||
std::vector<Vertex> edgeverts(npatches*20);
|
|
||||||
|
|
||||||
OpenSubdiv::Far::StencilTables const * gstencils =
|
|
||||||
patchTables.GetEndCapStencilTables();
|
|
||||||
assert(gstencils);
|
|
||||||
|
|
||||||
gstencils->UpdateValues(&vertexBuffer[0], &edgeverts[0]);
|
|
||||||
|
|
||||||
for (int patch=0; patch<npatches; ++patch) {
|
for (int patch=0; patch<npatches; ++patch) {
|
||||||
|
|
||||||
@ -664,33 +659,43 @@ createGregoryBasis(OpenSubdiv::Far::PatchTables const & patchTables,
|
|||||||
int offset = patch * 20,
|
int offset = patch * 20,
|
||||||
* vpe = &vertsperedge[offset],
|
* vpe = &vertsperedge[offset],
|
||||||
* indices = &edgeindices[patch * 40];
|
* indices = &edgeindices[patch * 40];
|
||||||
|
|
||||||
|
OpenSubdiv::Far::ConstIndexArray const cvs =
|
||||||
|
patchTables.GetPatchVertices(patchArray, patch);
|
||||||
|
|
||||||
for (int i=0; i<20; ++i) {
|
for (int i=0; i<20; ++i) {
|
||||||
vpe[i] = 2;
|
vpe[i] = 2;
|
||||||
indices[i*2] = basisedges[i*2] + offset;
|
indices[i*2] = cvs[basisedges[i*2]];
|
||||||
indices[i*2+1] = basisedges[i*2+1] + offset;
|
indices[i*2+1] = cvs[basisedges[i*2+1]];
|
||||||
}
|
}
|
||||||
|
|
||||||
Vertex const * verts = &edgeverts[offset];
|
//Vertex const * verts = &edgeverts[offset];
|
||||||
static char buf[16];
|
static char buf[16];
|
||||||
for (int i=0; i<4; ++i) {
|
for (int i=0; i<4; ++i) {
|
||||||
int vid = i * 5;
|
int vid = patch * 20 + i * 5;
|
||||||
snprintf(buf, 16, " P%d", i);
|
|
||||||
g_font->Print3D(verts[vid].GetPos(), buf, 3);
|
const float *P = vertexBuffer[cvs[i*5+0]].GetPos();
|
||||||
snprintf(buf, 16, " Ep%d", i);
|
const float *Ep = vertexBuffer[cvs[i*5+1]].GetPos();
|
||||||
g_font->Print3D(verts[vid+1].GetPos(), buf, 3);
|
const float *Em = vertexBuffer[cvs[i*5+2]].GetPos();
|
||||||
snprintf(buf, 16, " Em%d", i);
|
const float *Fp = vertexBuffer[cvs[i*5+3]].GetPos();
|
||||||
g_font->Print3D(verts[vid+2].GetPos(), buf, 3);
|
const float *Fm = vertexBuffer[cvs[i*5+4]].GetPos();
|
||||||
snprintf(buf, 16, " Fp%d", i);
|
|
||||||
g_font->Print3D(verts[vid+3].GetPos(), buf, 3);
|
snprintf(buf, 16, " P%d (%d)", i, vid);
|
||||||
snprintf(buf, 16, " Fm%d", i);
|
g_font->Print3D(P, buf, 3);
|
||||||
g_font->Print3D(verts[vid+4].GetPos(), buf, 3);
|
snprintf(buf, 16, " Ep%d (%d)", i, vid+1);
|
||||||
|
g_font->Print3D(Ep, buf, 3);
|
||||||
|
snprintf(buf, 16, " Em%d (%d)", i, vid+2);
|
||||||
|
g_font->Print3D(Em, buf, 3);
|
||||||
|
snprintf(buf, 16, " Fp%d (%d)", i, vid+3);
|
||||||
|
g_font->Print3D(Fp, buf, 3);
|
||||||
|
snprintf(buf, 16, " Fm%d (%d)", i, vid+4);
|
||||||
|
g_font->Print3D(Fm, buf, 3);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GLMesh::Options options;
|
GLMesh::Options options;
|
||||||
gregoryWire.Initialize(options, (int)edgeverts.size(), (int)vertsperedge.size(),
|
gregoryWire.Initialize(options, (int)vertexBuffer.size(), (int)vertsperedge.size(),
|
||||||
&vertsperedge[0], &edgeindices[0], (float const * )&edgeverts[0]);
|
&vertsperedge[0], &edgeindices[0], (float const *)&vertexBuffer[0]);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
@ -770,17 +775,6 @@ createVtrMesh(Shape * shape, int maxlevel) {
|
|||||||
// Stencils
|
// Stencils
|
||||||
//
|
//
|
||||||
|
|
||||||
// create vertex primvar data buffer
|
|
||||||
std::vector<Vertex> vertexBuffer(refiner->GetNumVerticesTotal());
|
|
||||||
Vertex * verts = &vertexBuffer[0];
|
|
||||||
|
|
||||||
// copy coarse vertices positions
|
|
||||||
int ncoarseverts = shape->GetNumVertices();
|
|
||||||
for (int i=0; i<ncoarseverts; ++i) {
|
|
||||||
float * ptr = &shape->verts[i*3];
|
|
||||||
verts[i].SetPosition(ptr[0], ptr[1], ptr[2]);
|
|
||||||
}
|
|
||||||
|
|
||||||
//#define no_stencils
|
//#define no_stencils
|
||||||
#ifdef no_stencils
|
#ifdef no_stencils
|
||||||
{
|
{
|
||||||
@ -800,8 +794,6 @@ createVtrMesh(Shape * shape, int maxlevel) {
|
|||||||
|
|
||||||
stencilTables =
|
stencilTables =
|
||||||
OpenSubdiv::Far::StencilTablesFactory::Create(*refiner, options);
|
OpenSubdiv::Far::StencilTablesFactory::Create(*refiner, options);
|
||||||
|
|
||||||
stencilTables->UpdateValues(verts, verts + ncoarseverts);
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -848,6 +840,39 @@ createVtrMesh(Shape * shape, int maxlevel) {
|
|||||||
refiner->InterpolateFaceVarying(values, values + nCoarseValues);
|
refiner->InterpolateFaceVarying(values, values + nCoarseValues);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// note: gregoryBasisStencilTables is owned by patchTables.
|
||||||
|
OpenSubdiv::Far::StencilTables const * gregoryBasisStencilTables =
|
||||||
|
patchTables->GetEndCapVertexStencilTables();
|
||||||
|
|
||||||
|
if (gregoryBasisStencilTables) {
|
||||||
|
OpenSubdiv::Far::StencilTables const *inStencilTables[] = {
|
||||||
|
stencilTables, gregoryBasisStencilTables
|
||||||
|
};
|
||||||
|
OpenSubdiv::Far::StencilTables const *concatStencilTables =
|
||||||
|
concatStencilTables = OpenSubdiv::Far::StencilTablesFactory::Create(
|
||||||
|
2, inStencilTables);
|
||||||
|
delete stencilTables;
|
||||||
|
stencilTables = concatStencilTables;
|
||||||
|
}
|
||||||
|
|
||||||
|
int numTotalVerts = shape->GetNumVertices() + stencilTables->GetNumStencils();
|
||||||
|
|
||||||
|
// create vertex primvar data buffer
|
||||||
|
std::vector<Vertex> vertexBuffer(numTotalVerts);
|
||||||
|
Vertex * verts = &vertexBuffer[0];
|
||||||
|
|
||||||
|
// copy coarse vertices positions
|
||||||
|
int ncoarseverts = shape->GetNumVertices();
|
||||||
|
for (int i=0; i<ncoarseverts; ++i) {
|
||||||
|
float * ptr = &shape->verts[i*3];
|
||||||
|
verts[i].SetPosition(ptr[0], ptr[1], ptr[2]);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// apply stencils
|
||||||
|
//
|
||||||
|
stencilTables->UpdateValues(verts, verts + ncoarseverts);
|
||||||
|
|
||||||
s.Stop();
|
s.Stop();
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -1391,7 +1416,7 @@ initHUD() {
|
|||||||
g_hud.AddCheckBox("Adaptive (`)", g_Adaptive!=0, 10, 350, callbackAdaptive, 0, '`');
|
g_hud.AddCheckBox("Adaptive (`)", g_Adaptive!=0, 10, 350, callbackAdaptive, 0, '`');
|
||||||
|
|
||||||
|
|
||||||
g_hud.AddSlider("Font Scale", 0.0f, 0.1f, 0.025f,
|
g_hud.AddSlider("Font Scale", 0.0f, 0.1f, 0.01f,
|
||||||
-900, -50, 100, false, callbackScale, 0);
|
-900, -50, 100, false, callbackScale, 0);
|
||||||
|
|
||||||
for (int i = 1; i < 11; ++i) {
|
for (int i = 1; i < 11; ++i) {
|
||||||
|
@ -89,7 +89,8 @@ getQuadOffsets(Vtr::Level const & level, Vtr::Index fIndex,
|
|||||||
16 + maxvalence - 3
|
16 + maxvalence - 3
|
||||||
|
|
||||||
// limit valence of 30 because we use a pre-computed closed-form 'ef' table
|
// limit valence of 30 because we use a pre-computed closed-form 'ef' table
|
||||||
static const int MAX_VALENCE=30,
|
// XXXtakahito: revisit here to determine appropriate size
|
||||||
|
static const int MAX_VALENCE=(30*2),
|
||||||
MAX_ELEMS = GetNumMaxElems(MAX_VALENCE);
|
MAX_ELEMS = GetNumMaxElems(MAX_VALENCE);
|
||||||
|
|
||||||
namespace Far {
|
namespace Far {
|
||||||
@ -271,6 +272,9 @@ struct ProtoBasis {
|
|||||||
//
|
//
|
||||||
|
|
||||||
Point P[4], Ep[4], Em[4], Fp[4], Fm[4];
|
Point P[4], Ep[4], Em[4], Fp[4], Fm[4];
|
||||||
|
|
||||||
|
// for varying interpolation
|
||||||
|
Point V[4];
|
||||||
};
|
};
|
||||||
|
|
||||||
int
|
int
|
||||||
@ -293,6 +297,7 @@ ProtoBasis::OffsetIndices(Index offset) {
|
|||||||
Em[vid].OffsetIndices(offset);
|
Em[vid].OffsetIndices(offset);
|
||||||
Fp[vid].OffsetIndices(offset);
|
Fp[vid].OffsetIndices(offset);
|
||||||
Fm[vid].OffsetIndices(offset);
|
Fm[vid].OffsetIndices(offset);
|
||||||
|
V[vid].OffsetIndices(offset);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void
|
void
|
||||||
@ -349,6 +354,8 @@ ProtoBasis::ProtoBasis(Vtr::Level const & level, Index faceIndex, int fvarChanne
|
|||||||
for (int vid=0; vid<4; ++vid) {
|
for (int vid=0; vid<4; ++vid) {
|
||||||
|
|
||||||
org[vid] = facePoints[vid];
|
org[vid] = facePoints[vid];
|
||||||
|
// save for varying stencils
|
||||||
|
V[vid] = facePoints[vid];
|
||||||
|
|
||||||
int ringSize =
|
int ringSize =
|
||||||
level.gatherQuadRegularRingAroundVertex(
|
level.gatherQuadRegularRingAroundVertex(
|
||||||
@ -595,6 +602,8 @@ GregoryBasisFactory::Create(TopologyRefiner const & refiner,
|
|||||||
|
|
||||||
basis.Copy(result->_sizes, &result->_indices[0], &result->_weights[0]);
|
basis.Copy(result->_sizes, &result->_indices[0], &result->_weights[0]);
|
||||||
|
|
||||||
|
// note: this function doesn't create varying stencils.
|
||||||
|
|
||||||
for (int i=0, offset=0; i<20; ++i) {
|
for (int i=0, offset=0; i<20; ++i) {
|
||||||
result->_offsets[i] = offset;
|
result->_offsets[i] = offset;
|
||||||
offset += result->_sizes[i];
|
offset += result->_sizes[i];
|
||||||
@ -607,15 +616,19 @@ GregoryBasisFactory::Create(TopologyRefiner const & refiner,
|
|||||||
// GregoryBasisFactory for Vertex StencilTables
|
// GregoryBasisFactory for Vertex StencilTables
|
||||||
//
|
//
|
||||||
GregoryBasisFactory::GregoryBasisFactory(TopologyRefiner const & refiner,
|
GregoryBasisFactory::GregoryBasisFactory(TopologyRefiner const & refiner,
|
||||||
StencilTables const & stencils,
|
StencilTables const *stencils,
|
||||||
int numpatches, int maxvalence) :
|
StencilTables const *varyingStencils,
|
||||||
|
int numpatches, int maxvalence) :
|
||||||
_currentStencil(0), _refiner(refiner),
|
_currentStencil(0), _refiner(refiner),
|
||||||
_stencils(stencils), _alloc(GetNumMaxElems(maxvalence)) {
|
_stencils(stencils), _varyingStencils(varyingStencils),
|
||||||
|
_alloc(GetNumMaxElems(maxvalence)),
|
||||||
|
_varyingAlloc(GetNumMaxElems(maxvalence)) {
|
||||||
|
|
||||||
// Sanity check: the mesh must be adaptively refined
|
// Sanity check: the mesh must be adaptively refined
|
||||||
assert(not _refiner.IsUniform());
|
assert(not _refiner.IsUniform());
|
||||||
|
|
||||||
_alloc.Resize(numpatches * 20);
|
_alloc.Resize(numpatches * 20);
|
||||||
|
_varyingAlloc.Resize(numpatches * 20);
|
||||||
|
|
||||||
// Gregory limit stencils have indices that are relative to the level
|
// Gregory limit stencils have indices that are relative to the level
|
||||||
// (maxlevel) of subdivision. These indices need to be offset to match
|
// (maxlevel) of subdivision. These indices need to be offset to match
|
||||||
@ -624,9 +637,10 @@ GregoryBasisFactory::GregoryBasisFactory(TopologyRefiner const & refiner,
|
|||||||
// (single weight of 1.0f) as place-holders for coarse mesh vertices,
|
// (single weight of 1.0f) as place-holders for coarse mesh vertices,
|
||||||
// which also needs to be accounted for.
|
// which also needs to be accounted for.
|
||||||
_stencilsOffset=-1;
|
_stencilsOffset=-1;
|
||||||
{ int maxlevel = _refiner.GetMaxLevel(),
|
{
|
||||||
|
int maxlevel = _refiner.GetMaxLevel(),
|
||||||
nverts = _refiner.GetNumVerticesTotal(),
|
nverts = _refiner.GetNumVerticesTotal(),
|
||||||
nstencils = _stencils.GetNumStencils();
|
nstencils = _stencils->GetNumStencils();
|
||||||
if (nstencils==nverts) {
|
if (nstencils==nverts) {
|
||||||
|
|
||||||
// the table contain stencils for the control vertices
|
// the table contain stencils for the control vertices
|
||||||
@ -645,17 +659,20 @@ GregoryBasisFactory::GregoryBasisFactory(TopologyRefiner const & refiner,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
static inline void
|
static inline void
|
||||||
factorizeBasisVertex(StencilTables const & stencils, Point const & p, ProtoStencil dst) {
|
factorizeBasisVertex(StencilTables const * stencils, Point const & p, ProtoStencil dst) {
|
||||||
// Use the Allocator to factorize the Gregory patch influence CVs with the
|
// Use the Allocator to factorize the Gregory patch influence CVs with the
|
||||||
// supporting CVs from the stencil tables.
|
// supporting CVs from the stencil tables.
|
||||||
|
if (!stencils) return;
|
||||||
|
|
||||||
dst.Clear();
|
dst.Clear();
|
||||||
for (int j=0; j<p.GetSize(); ++j) {
|
for (int j=0; j<p.GetSize(); ++j) {
|
||||||
dst.AddWithWeight(stencils,
|
dst.AddWithWeight(*stencils,
|
||||||
p.GetIndices()[j], p.GetWeights()[j]);
|
p.GetIndices()[j], p.GetWeights()[j]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
bool
|
bool
|
||||||
GregoryBasisFactory::AddPatchBasis(Index faceIndex) {
|
GregoryBasisFactory::AddPatchBasis(Index faceIndex,
|
||||||
|
bool verticesMask[4][5]) {
|
||||||
|
|
||||||
// Gregory patches only exist on the hight
|
// Gregory patches only exist on the hight
|
||||||
Vtr::Level const & level = _refiner.getLevel(_refiner.GetMaxLevel());
|
Vtr::Level const & level = _refiner.getLevel(_refiner.GetMaxLevel());
|
||||||
@ -677,21 +694,41 @@ GregoryBasisFactory::AddPatchBasis(Index faceIndex) {
|
|||||||
// expressed as a linear combination of vertices from the coarse control
|
// expressed as a linear combination of vertices from the coarse control
|
||||||
// mesh with no data dependencies
|
// mesh with no data dependencies
|
||||||
for (int i=0; i<4; ++i) {
|
for (int i=0; i<4; ++i) {
|
||||||
int offset = _currentStencil + i * 5;
|
if (verticesMask[i][0]) {
|
||||||
factorizeBasisVertex(_stencils, basis.P[i], _alloc[offset]);
|
factorizeBasisVertex(_stencils, basis.P[i], _alloc[_currentStencil]);
|
||||||
factorizeBasisVertex(_stencils, basis.Ep[i], _alloc[offset+1]);
|
// need varying stencils only for corners
|
||||||
factorizeBasisVertex(_stencils, basis.Em[i], _alloc[offset+2]);
|
factorizeBasisVertex(_varyingStencils, basis.V[i], _varyingAlloc[_currentStencil]);
|
||||||
factorizeBasisVertex(_stencils, basis.Fp[i], _alloc[offset+3]);
|
++_currentStencil;
|
||||||
factorizeBasisVertex(_stencils, basis.Fm[i], _alloc[offset+4]);
|
}
|
||||||
|
if (verticesMask[i][1]) {
|
||||||
|
factorizeBasisVertex(_stencils, basis.Ep[i], _alloc[_currentStencil]);
|
||||||
|
factorizeBasisVertex(_varyingStencils, basis.V[i], _varyingAlloc[_currentStencil]);
|
||||||
|
++_currentStencil;
|
||||||
|
}
|
||||||
|
if (verticesMask[i][2]) {
|
||||||
|
factorizeBasisVertex(_stencils, basis.Em[i], _alloc[_currentStencil]);
|
||||||
|
factorizeBasisVertex(_varyingStencils, basis.V[i], _varyingAlloc[_currentStencil]);
|
||||||
|
++_currentStencil;
|
||||||
|
}
|
||||||
|
if (verticesMask[i][3]) {
|
||||||
|
factorizeBasisVertex(_stencils, basis.Fp[i], _alloc[_currentStencil]);
|
||||||
|
factorizeBasisVertex(_varyingStencils, basis.V[i], _varyingAlloc[_currentStencil]);
|
||||||
|
++_currentStencil;
|
||||||
|
}
|
||||||
|
if (verticesMask[i][4]) {
|
||||||
|
factorizeBasisVertex(_stencils, basis.Fm[i], _alloc[_currentStencil]);
|
||||||
|
factorizeBasisVertex(_varyingStencils, basis.V[i], _varyingAlloc[_currentStencil]);
|
||||||
|
++_currentStencil;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
_currentStencil += 20;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
StencilTables const *
|
StencilTables const *
|
||||||
GregoryBasisFactory::CreateStencilTables(int const permute[20]) {
|
GregoryBasisFactory::createStencilTables(int const permute[20],
|
||||||
|
StencilAllocator &alloc) {
|
||||||
|
|
||||||
int nstencils = (int)_alloc.GetNumStencils(),
|
int nstencils = _currentStencil;
|
||||||
nelems = _alloc.GetNumVerticesTotal();
|
int nelems = alloc.GetNumVerticesTotal();
|
||||||
|
|
||||||
if (nstencils==0 or nelems==0) {
|
if (nstencils==0 or nelems==0) {
|
||||||
return 0;
|
return 0;
|
||||||
@ -716,7 +753,7 @@ GregoryBasisFactory::CreateStencilTables(int const permute[20]) {
|
|||||||
index = baseIndex + permute[localIndex];
|
index = baseIndex + permute[localIndex];
|
||||||
}
|
}
|
||||||
|
|
||||||
*dst._size = _alloc.CopyStencil(index, dst._indices, dst._weights);
|
*dst._size = alloc.CopyStencil(index, dst._indices, dst._weights);
|
||||||
|
|
||||||
dst.Next();
|
dst.Next();
|
||||||
}
|
}
|
||||||
|
@ -116,25 +116,39 @@ public:
|
|||||||
// this factory is active.
|
// this factory is active.
|
||||||
//
|
//
|
||||||
GregoryBasisFactory(TopologyRefiner const & refiner,
|
GregoryBasisFactory(TopologyRefiner const & refiner,
|
||||||
StencilTables const & stencils,
|
StencilTables const * stencils,
|
||||||
int numpatches, int maxvalence);
|
StencilTables const * varyingStencils,
|
||||||
|
int numpatches, int maxvalence);
|
||||||
|
|
||||||
// Creates a basis for the face and adds it to the stencil pool allocator
|
// Creates a basis for the vertices specified in mask on the face and
|
||||||
bool AddPatchBasis(Index faceIndex);
|
// adds it to the stencil pool allocator
|
||||||
|
bool AddPatchBasis(Index faceIndex,
|
||||||
|
bool newVerticesMask[4][5]);
|
||||||
|
|
||||||
// After all the patches have been collected, create the final table
|
// After all the patches have been collected, create the final table
|
||||||
StencilTables const * CreateStencilTables(int const permute[20]=0);
|
StencilTables const * CreateVertexStencilTables(int const permute[20]=0) {
|
||||||
|
return createStencilTables(permute, _alloc);
|
||||||
|
}
|
||||||
|
StencilTables const * CreateVaryingStencilTables(int const permute[20]=0) {
|
||||||
|
return createStencilTables(permute, _varyingAlloc);
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
StencilTables const * createStencilTables(int const permute[20],
|
||||||
|
StencilAllocator &alloc);
|
||||||
|
// XXX: StencilAllocator method's constness needs to be fixed.
|
||||||
|
|
||||||
int _currentStencil;
|
int _currentStencil;
|
||||||
|
|
||||||
TopologyRefiner const & _refiner; // XXXX these should be smart pointers !
|
TopologyRefiner const & _refiner; // XXXX these should be smart pointers !
|
||||||
|
|
||||||
Index _stencilsOffset;
|
Index _stencilsOffset;
|
||||||
|
|
||||||
StencilTables const & _stencils;
|
StencilTables const * _stencils;
|
||||||
|
StencilTables const * _varyingStencils;
|
||||||
StencilAllocator _alloc;
|
StencilAllocator _alloc;
|
||||||
|
StencilAllocator _varyingAlloc;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // end namespace Far
|
} // end namespace Far
|
||||||
|
@ -33,7 +33,9 @@ namespace OPENSUBDIV_VERSION {
|
|||||||
namespace Far {
|
namespace Far {
|
||||||
|
|
||||||
PatchTables::PatchTables(int maxvalence) :
|
PatchTables::PatchTables(int maxvalence) :
|
||||||
_maxValence(maxvalence), _endcapStencilTables(0) { }
|
_maxValence(maxvalence),
|
||||||
|
_endcapVertexStencilTables(0),
|
||||||
|
_endcapVaryingStencilTables(0) { }
|
||||||
|
|
||||||
// Copy constructor
|
// Copy constructor
|
||||||
// XXXX manuelk we need to eliminate this constructor (C++11 smart pointers)
|
// XXXX manuelk we need to eliminate this constructor (C++11 smart pointers)
|
||||||
@ -43,21 +45,21 @@ PatchTables::PatchTables(PatchTables const & src) :
|
|||||||
_patchArrays(src._patchArrays),
|
_patchArrays(src._patchArrays),
|
||||||
_patchVerts(src._patchVerts),
|
_patchVerts(src._patchVerts),
|
||||||
_paramTable(src._paramTable),
|
_paramTable(src._paramTable),
|
||||||
#ifdef ENDCAP_TOPOPOLGY
|
|
||||||
_endcapTopology(src._endcapTopology),
|
|
||||||
#endif
|
|
||||||
_quadOffsetsTable(src._quadOffsetsTable),
|
_quadOffsetsTable(src._quadOffsetsTable),
|
||||||
_vertexValenceTable(src._vertexValenceTable),
|
_vertexValenceTable(src._vertexValenceTable),
|
||||||
_fvarChannels(src._fvarChannels),
|
_fvarChannels(src._fvarChannels),
|
||||||
_sharpnessIndices(src._sharpnessIndices),
|
_sharpnessIndices(src._sharpnessIndices),
|
||||||
_sharpnessValues(src._sharpnessValues) {
|
_sharpnessValues(src._sharpnessValues) {
|
||||||
|
|
||||||
_endcapStencilTables = src._endcapStencilTables ?
|
_endcapVertexStencilTables = src._endcapVertexStencilTables ?
|
||||||
new StencilTables(*src._endcapStencilTables) : 0;
|
new StencilTables(*src._endcapVertexStencilTables) : 0;
|
||||||
|
_endcapVaryingStencilTables = src._endcapVaryingStencilTables ?
|
||||||
|
new StencilTables(*src._endcapVaryingStencilTables) : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
PatchTables::~PatchTables() {
|
PatchTables::~PatchTables() {
|
||||||
delete _endcapStencilTables;
|
delete _endcapVertexStencilTables;
|
||||||
|
delete _endcapVaryingStencilTables;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -242,13 +244,7 @@ PatchTables::setBicubicFVarPatchChannelValues(int channel, int patchSize,
|
|||||||
|
|
||||||
inline int
|
inline int
|
||||||
getPatchSize(PatchDescriptor desc) {
|
getPatchSize(PatchDescriptor desc) {
|
||||||
int size = desc.GetNumControlVertices();
|
return 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
|
void
|
||||||
@ -339,13 +335,7 @@ PatchTables::GetPatchArrayVertices(int arrayIndex) const {
|
|||||||
ConstIndexArray
|
ConstIndexArray
|
||||||
PatchTables::GetPatchVertices(PatchHandle const & handle) const {
|
PatchTables::GetPatchVertices(PatchHandle const & handle) const {
|
||||||
PatchArray const & pa = getPatchArray(handle.arrayIndex);
|
PatchArray const & pa = getPatchArray(handle.arrayIndex);
|
||||||
|
Index vert = pa.vertIndex + handle.vertIndex;
|
||||||
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 ConstIndexArray(&_patchVerts[vert], getPatchSize(pa.desc));
|
return ConstIndexArray(&_patchVerts[vert], getPatchSize(pa.desc));
|
||||||
}
|
}
|
||||||
ConstIndexArray
|
ConstIndexArray
|
||||||
@ -409,7 +399,7 @@ bool
|
|||||||
PatchTables::IsFeatureAdaptive() const {
|
PatchTables::IsFeatureAdaptive() const {
|
||||||
|
|
||||||
// check for presence of tables only used by adaptive patches
|
// check for presence of tables only used by adaptive patches
|
||||||
if (not _vertexValenceTable.empty() or _endcapStencilTables)
|
if (not _vertexValenceTable.empty() or _endcapVertexStencilTables)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
// otherwise, we have to check each patch array
|
// otherwise, we have to check each patch array
|
||||||
|
@ -174,11 +174,9 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// \brief Returns a stencil table for the control vertices of end-cap patches
|
/// \brief Returns a stencil table for the control vertices of end-cap patches
|
||||||
StencilTables const * GetEndCapStencilTables() const { return _endcapStencilTables; }
|
StencilTables const * GetEndCapVertexStencilTables() const { return _endcapVertexStencilTables; }
|
||||||
|
StencilTables const * GetEndCapVaryingStencilTables() const { return _endcapVaryingStencilTables; }
|
||||||
|
|
||||||
Index GetEndCapStencilIndex(PatchHandle const & handle) const {
|
|
||||||
return handle.vertIndex;
|
|
||||||
}
|
|
||||||
//@}
|
//@}
|
||||||
|
|
||||||
|
|
||||||
@ -418,10 +416,8 @@ private:
|
|||||||
|
|
||||||
// XXXX manuelk end-cap stencils will obsolete the other tables
|
// XXXX manuelk end-cap stencils will obsolete the other tables
|
||||||
|
|
||||||
StencilTables const * _endcapStencilTables;
|
StencilTables const * _endcapVertexStencilTables;
|
||||||
#ifdef ENDCAP_TOPOPOLGY
|
StencilTables const * _endcapVaryingStencilTables;
|
||||||
std::vector<Index> _endcapTopology;
|
|
||||||
#endif
|
|
||||||
QuadOffsetsTable _quadOffsetsTable; // Quad offsets (for Gregory patches)
|
QuadOffsetsTable _quadOffsetsTable; // Quad offsets (for Gregory patches)
|
||||||
VertexValenceTable _vertexValenceTable; // Vertex valence table (for Gregory patches)
|
VertexValenceTable _vertexValenceTable; // Vertex valence table (for Gregory patches)
|
||||||
|
|
||||||
@ -494,10 +490,10 @@ PatchTables::Evaluate(PatchHandle const & handle, float s, float t,
|
|||||||
}
|
}
|
||||||
} else if (ptype==PatchDescriptor::GREGORY_BASIS) {
|
} else if (ptype==PatchDescriptor::GREGORY_BASIS) {
|
||||||
|
|
||||||
assert(_endcapStencilTables);
|
assert(_endcapVertexStencilTables);
|
||||||
|
|
||||||
GetBezierWeights(bits, s, t, Q, Qd1, Qd2);
|
GetBezierWeights(bits, s, t, Q, Qd1, Qd2);
|
||||||
InterpolateGregoryPatch(_endcapStencilTables, handle.vertIndex,
|
InterpolateGregoryPatch(_endcapVertexStencilTables, handle.vertIndex,
|
||||||
s, t, Q, Qd1, Qd2, src, dst);
|
s, t, Q, Qd1, Qd2, src, dst);
|
||||||
|
|
||||||
} else if (ptype==PatchDescriptor::QUADS) {
|
} else if (ptype==PatchDescriptor::QUADS) {
|
||||||
|
@ -904,7 +904,6 @@ PatchTablesFactory::computePatchParam(TopologyRefiner const & refiner,
|
|||||||
return ++coord;
|
return ++coord;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef ENDCAP_TOPOPOLGY
|
|
||||||
// XXXX manuelk work in progress for end-cap topology gathering
|
// XXXX manuelk work in progress for end-cap topology gathering
|
||||||
//
|
//
|
||||||
// Populates the topology table used by Gregory-basis patches
|
// Populates the topology table used by Gregory-basis patches
|
||||||
@ -913,17 +912,21 @@ PatchTablesFactory::computePatchParam(TopologyRefiner const & refiner,
|
|||||||
// Note 2: this code attempts to identify basis vertices shared along
|
// Note 2: this code attempts to identify basis vertices shared along
|
||||||
// gregory patch edges
|
// gregory patch edges
|
||||||
static int
|
static int
|
||||||
gatherGregoryBasisTopology(Vtr::Level const& level, Index faceIndex, int numVertices,
|
gatherGregoryBasisTopology(Vtr::Level const& level, Index faceIndex,
|
||||||
PatchFaceTag const * levelPatchTags,
|
int numGregoryBasisPatches,
|
||||||
bool skip[0], std::vector<Index> & basisIndices, PatchTables::PTable & topology) {
|
int numGregoryBasisVertices,
|
||||||
|
PatchFaceTag const * levelPatchTags,
|
||||||
|
std::vector<Index> & basisIndices,
|
||||||
|
PatchTables::PatchVertsTable & topology,
|
||||||
|
bool newVerticesMask[4][5]) {
|
||||||
|
|
||||||
assert(not topology.empty());
|
assert(not topology.empty());
|
||||||
Index * dest = &topology[basisIndices.size()*20];
|
Index * dest = &topology[numGregoryBasisPatches*20];
|
||||||
|
|
||||||
assert(Vtr::INDEX_INVALID==0xFFFFFFFF);
|
assert(Vtr::INDEX_INVALID==0xFFFFFFFF);
|
||||||
memset(dest, 0xFF, 20*sizeof(Index));
|
memset(dest, 0xFF, 20*sizeof(Index));
|
||||||
|
|
||||||
IndexArray fedges = level.getFaceEdges(faceIndex);
|
ConstIndexArray fedges = level.getFaceEdges(faceIndex);
|
||||||
assert(fedges.size()==4);
|
assert(fedges.size()==4);
|
||||||
|
|
||||||
for (int i=0; i<4; ++i) {
|
for (int i=0; i<4; ++i) {
|
||||||
@ -931,7 +934,7 @@ gatherGregoryBasisTopology(Vtr::Level const& level, Index faceIndex, int numVert
|
|||||||
adjface = 0;
|
adjface = 0;
|
||||||
|
|
||||||
{ // Gather adjacent faces
|
{ // Gather adjacent faces
|
||||||
IndexArray adjfaces = level.getEdgeFaces(edge);
|
ConstIndexArray adjfaces = level.getEdgeFaces(edge);
|
||||||
for (int i=0; i<adjfaces.size(); ++i) {
|
for (int i=0; i<adjfaces.size(); ++i) {
|
||||||
if (adjfaces[i]==faceIndex) {
|
if (adjfaces[i]==faceIndex) {
|
||||||
// XXXX manuelk if 'edge' is non-manifold, arbitrarily pick the
|
// XXXX manuelk if 'edge' is non-manifold, arbitrarily pick the
|
||||||
@ -943,12 +946,12 @@ gatherGregoryBasisTopology(Vtr::Level const& level, Index faceIndex, int numVert
|
|||||||
}
|
}
|
||||||
// We are looking for adjacent faces that:
|
// We are looking for adjacent faces that:
|
||||||
// - exist (no boundary)
|
// - exist (no boundary)
|
||||||
// - have alraedy been processed (known CV indices)
|
// - have already been processed (known CV indices)
|
||||||
// - are also Gregory basis patches
|
// - are also Gregory basis patches
|
||||||
if (adjface!=Vtr::INDEX_INVALID and (adjface < faceIndex) and
|
if (adjface!=Vtr::INDEX_INVALID and (adjface < faceIndex) and
|
||||||
(not levelPatchTags[adjface]._isRegular)) {
|
(not levelPatchTags[adjface]._isRegular)) {
|
||||||
|
|
||||||
IndexArray aedges = level.getFaceEdges(adjface);
|
ConstIndexArray aedges = level.getFaceEdges(adjface);
|
||||||
int aedge = aedges.FindIndexIn4Tuple(edge);
|
int aedge = aedges.FindIndexIn4Tuple(edge);
|
||||||
assert(aedge!=Vtr::INDEX_INVALID);
|
assert(aedge!=Vtr::INDEX_INVALID);
|
||||||
|
|
||||||
@ -963,6 +966,11 @@ gatherGregoryBasisTopology(Vtr::Level const& level, Index faceIndex, int numVert
|
|||||||
basisIndices.size(), sizeof(Index), compare::op);
|
basisIndices.size(), sizeof(Index), compare::op);
|
||||||
|
|
||||||
int srcBasisIdx = ptr - &basisIndices[0];
|
int srcBasisIdx = ptr - &basisIndices[0];
|
||||||
|
|
||||||
|
if (!ptr) {
|
||||||
|
// if the adjface is hole, it won't be found
|
||||||
|
break;
|
||||||
|
}
|
||||||
assert(ptr and srcBasisIdx>=0 and srcBasisIdx<(int)basisIndices.size());
|
assert(ptr and srcBasisIdx>=0 and srcBasisIdx<(int)basisIndices.size());
|
||||||
|
|
||||||
// Copy the indices of CVs from the face on the other side of the
|
// Copy the indices of CVs from the face on the other side of the
|
||||||
@ -973,23 +981,26 @@ gatherGregoryBasisTopology(Vtr::Level const& level, Index faceIndex, int numVert
|
|||||||
{15, 16, 2, 0} };
|
{15, 16, 2, 0} };
|
||||||
Index * src = &topology[srcBasisIdx*20];
|
Index * src = &topology[srcBasisIdx*20];
|
||||||
for (int j=0; j<4; ++j) {
|
for (int j=0; j<4; ++j) {
|
||||||
dest[i*4+j] = src[gregoryEdgeVerts[aedge][j]];
|
// invert direction
|
||||||
|
dest[gregoryEdgeVerts[i][3-j]] = src[gregoryEdgeVerts[aedge][j]];
|
||||||
}
|
}
|
||||||
|
|
||||||
skip[i] = true;
|
|
||||||
} else {
|
|
||||||
skip[i] = false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (int i=0; i<20; ++i) {
|
for (int i = 0; i < 4; ++i) {
|
||||||
if (dest[i]==Vtr::INDEX_INVALID) {
|
for (int j = 0; j < 5; ++j) {
|
||||||
dest[i] = numVertices++;
|
if (dest[i*5+j]==Vtr::INDEX_INVALID) {
|
||||||
|
// assign new vertex
|
||||||
|
dest[i*5+j] = numGregoryBasisVertices++;
|
||||||
|
newVerticesMask[i][j] = true;
|
||||||
|
} else {
|
||||||
|
// share vertex
|
||||||
|
newVerticesMask[i][j] = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
basisIndices.push_back(faceIndex);
|
basisIndices.push_back(faceIndex);
|
||||||
return numVertices;
|
return numGregoryBasisVertices;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Indexing sharpnesses
|
// Indexing sharpnesses
|
||||||
@ -1602,27 +1613,37 @@ PatchTablesFactory::populateAdaptivePatches(AdaptiveContext & context) {
|
|||||||
bool hasGregoryPatches =
|
bool hasGregoryPatches =
|
||||||
context.RequiresLegacyGregoryPatches() or context.RequiresGregoryBasisPatches();
|
context.RequiresLegacyGregoryPatches() or context.RequiresGregoryBasisPatches();
|
||||||
GregoryBasisFactory * gregoryStencilsFactory = 0;
|
GregoryBasisFactory * gregoryStencilsFactory = 0;
|
||||||
#ifdef ENDCAP_TOPOPOLGY
|
|
||||||
int numGregoryBasisVertices=0;
|
int numGregoryBasisVertices=0;
|
||||||
|
int numGregoryBasisPatches=0;
|
||||||
std::vector<Index> gregoryBasisIndices;
|
std::vector<Index> gregoryBasisIndices;
|
||||||
#endif
|
std::vector<Index> endcapTopology;
|
||||||
if (hasGregoryPatches) {
|
if (hasGregoryPatches) {
|
||||||
|
|
||||||
StencilTables const * adaptiveStencils = context.options.adaptiveStencilTables;
|
StencilTables const * adaptiveVertexStencils =
|
||||||
if (adaptiveStencils and context.RequiresGregoryBasisPatches()) {
|
context.options.adaptiveStencilTables;
|
||||||
|
StencilTables const * adaptiveVaryingStencils =
|
||||||
|
context.options.adaptiveVaryingStencilTables;
|
||||||
|
|
||||||
|
if (adaptiveVertexStencils and
|
||||||
|
context.RequiresGregoryBasisPatches()) {
|
||||||
|
|
||||||
assert(not context.RequiresLegacyGregoryPatches());
|
assert(not context.RequiresLegacyGregoryPatches());
|
||||||
|
|
||||||
int maxvalence = refiner.GetMaxValence(),
|
int maxvalence = refiner.GetMaxValence(),
|
||||||
npatches = context.patchInventory.GP;
|
npatches = context.patchInventory.GP;
|
||||||
|
|
||||||
gregoryStencilsFactory =
|
|
||||||
new GregoryBasisFactory(refiner, *adaptiveStencils, npatches, maxvalence);
|
|
||||||
|
|
||||||
#ifdef ENDCAP_TOPOPOLGY
|
gregoryStencilsFactory =
|
||||||
|
new GregoryBasisFactory(refiner,
|
||||||
|
adaptiveVertexStencils,
|
||||||
|
adaptiveVaryingStencils,
|
||||||
|
npatches, maxvalence);
|
||||||
|
|
||||||
|
// XXX reconsider these variable names:
|
||||||
|
// gregoryBasisIndices holds patch indices,
|
||||||
|
// endcapTopology contains vert indices.
|
||||||
gregoryBasisIndices.reserve(npatches);
|
gregoryBasisIndices.reserve(npatches);
|
||||||
tables->_endcapTopology.resize(npatches*20);
|
endcapTopology.resize(npatches*20);
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
gregoryVertexFlags.resize(refiner.GetNumVerticesTotal(), false);
|
gregoryVertexFlags.resize(refiner.GetNumVerticesTotal(), false);
|
||||||
}
|
}
|
||||||
@ -1739,19 +1760,24 @@ PatchTablesFactory::populateAdaptivePatches(AdaptiveContext & context) {
|
|||||||
// Gregory basis end-cap (20 CVs - no quad-offsets / valence tables)
|
// Gregory basis end-cap (20 CVs - no quad-offsets / valence tables)
|
||||||
assert(i==refiner.GetMaxLevel());
|
assert(i==refiner.GetMaxLevel());
|
||||||
// Gregory Boundary Patch (4 CVs 0-ring for varying interpolation)
|
// Gregory Boundary Patch (4 CVs 0-ring for varying interpolation)
|
||||||
Vtr::ConstIndexArray faceVerts = level->getFaceVertices(faceIndex);
|
bool newVerticesMask[4][5];
|
||||||
for (int j = 0; j < 4; ++j) {
|
numGregoryBasisVertices = gatherGregoryBasisTopology(*level, faceIndex,
|
||||||
iptrs.GP[j] = faceVerts[j] + levelVertOffset;
|
numGregoryBasisPatches,
|
||||||
gregoryVertexFlags[iptrs.GP[j]] = true;
|
numGregoryBasisVertices,
|
||||||
}
|
levelPatchTags,
|
||||||
iptrs.GP += 4;
|
gregoryBasisIndices,
|
||||||
|
endcapTopology,
|
||||||
|
newVerticesMask);
|
||||||
|
gregoryStencilsFactory->AddPatchBasis(faceIndex, newVerticesMask);
|
||||||
|
|
||||||
#ifdef ENDCAP_TOPOPOLGY
|
// populate 20 indices with offset
|
||||||
bool edgeSkip[4];
|
for (int j = 0; j < 20; ++j) {
|
||||||
numGregoryBasisVertices = gatherGregoryBasisTopology(*level, faceIndex, numGregoryBasisVertices,
|
iptrs.GP[j] = endcapTopology[numGregoryBasisPatches*20+j]
|
||||||
levelPatchTags, edgeSkip, gregoryBasisIndices, tables->_endcapTopology);
|
+ refiner.GetNumVerticesTotal();
|
||||||
#endif
|
}
|
||||||
gregoryStencilsFactory->AddPatchBasis(faceIndex);
|
iptrs.GP += 20;
|
||||||
|
|
||||||
|
++numGregoryBasisPatches;
|
||||||
|
|
||||||
pptrs.GP = computePatchParam(refiner, i, faceIndex, 0, pptrs.GP);
|
pptrs.GP = computePatchParam(refiner, i, faceIndex, 0, pptrs.GP);
|
||||||
|
|
||||||
@ -1807,8 +1833,10 @@ PatchTablesFactory::populateAdaptivePatches(AdaptiveContext & context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (gregoryStencilsFactory) {
|
if (gregoryStencilsFactory) {
|
||||||
tables->_endcapStencilTables =
|
tables->_endcapVertexStencilTables =
|
||||||
gregoryStencilsFactory->CreateStencilTables();
|
gregoryStencilsFactory->CreateVertexStencilTables();
|
||||||
|
tables->_endcapVaryingStencilTables =
|
||||||
|
gregoryStencilsFactory->CreateVaryingStencilTables();
|
||||||
delete gregoryStencilsFactory;
|
delete gregoryStencilsFactory;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -62,7 +62,9 @@ public:
|
|||||||
useFVarQuadEndCaps(true), // XXXX change to false when FVar Gregory is ready
|
useFVarQuadEndCaps(true), // XXXX change to false when FVar Gregory is ready
|
||||||
numFVarChannels(-1),
|
numFVarChannels(-1),
|
||||||
fvarChannelIndices(0),
|
fvarChannelIndices(0),
|
||||||
adaptiveStencilTables(0) { }
|
adaptiveStencilTables(0),
|
||||||
|
adaptiveVaryingStencilTables(0)
|
||||||
|
{ }
|
||||||
|
|
||||||
unsigned int generateAllLevels : 1, ///< Include levels from 'firstLevel' to 'maxLevel' (Uniform mode only)
|
unsigned int generateAllLevels : 1, ///< Include levels from 'firstLevel' to 'maxLevel' (Uniform mode only)
|
||||||
triangulateQuads : 1, ///< Triangulate 'QUADS' primitives (Uniform mode only)
|
triangulateQuads : 1, ///< Triangulate 'QUADS' primitives (Uniform mode only)
|
||||||
@ -79,6 +81,7 @@ public:
|
|||||||
StencilTables const * adaptiveStencilTables; ///< Passing a valid stencil table allows the factory to generate
|
StencilTables const * adaptiveStencilTables; ///< Passing a valid stencil table allows the factory to generate
|
||||||
///< stencils for gregory patches and replace them with a much
|
///< stencils for gregory patches and replace them with a much
|
||||||
///< more efficient basis.
|
///< more efficient basis.
|
||||||
|
StencilTables const * adaptiveVaryingStencilTables;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// \brief Factory constructor for PatchTables
|
/// \brief Factory constructor for PatchTables
|
||||||
|
@ -190,40 +190,53 @@ StencilTablesFactory::Create(TopologyRefiner const & refiner,
|
|||||||
StencilTables const *
|
StencilTables const *
|
||||||
StencilTablesFactory::Create(int numTables, StencilTables const ** tables) {
|
StencilTablesFactory::Create(int numTables, StencilTables const ** tables) {
|
||||||
|
|
||||||
StencilTables * result = new StencilTables;
|
// XXXtakahito:
|
||||||
|
// This function returns NULL for empty inputs or erroneous condition.
|
||||||
|
// It's convenient for skipping varying stencils etc, however,
|
||||||
|
// other Create() API returns an empty stencil instead of NULL.
|
||||||
|
// They need to be consistent.
|
||||||
|
|
||||||
if ( (numTables<=0) or (not tables)) {
|
if ( (numTables<=0) or (not tables)) {
|
||||||
return result;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ncvs = tables[0]->GetNumControlVertices(),
|
int ncvs = -1,
|
||||||
nstencils = 0,
|
nstencils = 0,
|
||||||
nelems = 0;
|
nelems = 0;
|
||||||
|
|
||||||
for (int i=0; i<numTables; ++i) {
|
for (int i=0; i<numTables; ++i) {
|
||||||
|
|
||||||
StencilTables const & st = *tables[i];
|
StencilTables const * st = tables[i];
|
||||||
|
// allow the tables could have a null entry.
|
||||||
|
if (!st) continue;
|
||||||
|
|
||||||
if (st.GetNumControlVertices()!=ncvs) {
|
if (ncvs >= 0 and st->GetNumControlVertices() != ncvs) {
|
||||||
return result;
|
return NULL;
|
||||||
}
|
}
|
||||||
nstencils += st.GetNumStencils();
|
ncvs = st->GetNumControlVertices();
|
||||||
nelems += (int)st.GetControlIndices().size();
|
nstencils += st->GetNumStencils();
|
||||||
|
nelems += (int)st->GetControlIndices().size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ncvs == -1) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
StencilTables * result = new StencilTables;
|
||||||
result->resize(nstencils, nelems);
|
result->resize(nstencils, nelems);
|
||||||
|
|
||||||
unsigned char * sizes = &result->_sizes[0];
|
unsigned char * sizes = &result->_sizes[0];
|
||||||
Index * indices = &result->_indices[0];
|
Index * indices = &result->_indices[0];
|
||||||
float * weights = &result->_weights[0];
|
float * weights = &result->_weights[0];
|
||||||
for (int i=0; i<numTables; ++i) {
|
for (int i=0; i<numTables; ++i) {
|
||||||
StencilTables const & st = *tables[i];
|
StencilTables const * st = tables[i];
|
||||||
|
if (!st) continue;
|
||||||
|
|
||||||
int st_nstencils = st.GetNumStencils(),
|
int st_nstencils = st->GetNumStencils(),
|
||||||
st_nelems = (int)st._indices.size();
|
st_nelems = (int)st->_indices.size();
|
||||||
memcpy(sizes, &st._sizes[0], st_nstencils*sizeof(unsigned char));
|
memcpy(sizes, &st->_sizes[0], st_nstencils*sizeof(unsigned char));
|
||||||
memcpy(indices, &st._indices[0], st_nelems*sizeof(Index));
|
memcpy(indices, &st->_indices[0], st_nelems*sizeof(Index));
|
||||||
memcpy(weights, &st._weights[0], st_nelems*sizeof(float));
|
memcpy(weights, &st->_weights[0], st_nelems*sizeof(float));
|
||||||
|
|
||||||
sizes += st_nstencils;
|
sizes += st_nstencils;
|
||||||
indices += st_nelems;
|
indices += st_nelems;
|
||||||
|
@ -200,6 +200,7 @@ if( OPENGL_FOUND OR OPENGLES_FOUND )
|
|||||||
glslPatchCommon.glsl
|
glslPatchCommon.glsl
|
||||||
glslPatchBSpline.glsl
|
glslPatchBSpline.glsl
|
||||||
glslPatchGregory.glsl
|
glslPatchGregory.glsl
|
||||||
|
glslPatchGregoryBasis.glsl
|
||||||
glslPatchTransition.glsl
|
glslPatchTransition.glsl
|
||||||
glslPtexCommon.glsl
|
glslPtexCommon.glsl
|
||||||
)
|
)
|
||||||
|
@ -105,12 +105,8 @@ CpuEvalLimitController::EvalLimitSample( LimitLocation const & coord,
|
|||||||
outQ, outDQU, outDQV );
|
outQ, outDQU, outDQV );
|
||||||
break;
|
break;
|
||||||
case Desc::GREGORY_BASIS : {
|
case Desc::GREGORY_BASIS : {
|
||||||
Far::StencilTables const * stencils =
|
|
||||||
ptables.GetEndCapStencilTables();
|
|
||||||
assert(stencils and stencils->GetNumStencils()>0);
|
|
||||||
evalGregoryBasis( pparam.bitField, s, t,
|
evalGregoryBasis( pparam.bitField, s, t,
|
||||||
*stencils,
|
cvs.begin(),
|
||||||
ptables.GetEndCapStencilIndex(*handle),
|
|
||||||
vertexData.inDesc,
|
vertexData.inDesc,
|
||||||
vertexData.in,
|
vertexData.in,
|
||||||
vertexData.outDesc,
|
vertexData.outDesc,
|
||||||
@ -206,12 +202,8 @@ CpuEvalLimitController::_EvalLimitSample( LimitLocation const & coords,
|
|||||||
out, outDu, outDv );
|
out, outDu, outDv );
|
||||||
break;
|
break;
|
||||||
case Desc::GREGORY_BASIS : {
|
case Desc::GREGORY_BASIS : {
|
||||||
Far::StencilTables const * stencils =
|
|
||||||
ptables.GetEndCapStencilTables();
|
|
||||||
assert(stencils and stencils->GetNumStencils()>0);
|
|
||||||
evalGregoryBasis( pparam.bitField, s, t,
|
evalGregoryBasis( pparam.bitField, s, t,
|
||||||
*stencils,
|
cvs.begin(),
|
||||||
ptables.GetEndCapStencilIndex(*handle),
|
|
||||||
vertexData.inDesc,
|
vertexData.inDesc,
|
||||||
vertexData.in,
|
vertexData.in,
|
||||||
vertexData.outDesc,
|
vertexData.outDesc,
|
||||||
@ -236,7 +228,8 @@ CpuEvalLimitController::_EvalLimitSample( LimitLocation const & coords,
|
|||||||
static int const zeroRings[6][4] = { {5, 6,10, 9}, // regular
|
static int const zeroRings[6][4] = { {5, 6,10, 9}, // regular
|
||||||
{1, 2, 6, 5}, // boundary / single-crease
|
{1, 2, 6, 5}, // boundary / single-crease
|
||||||
{1, 2, 5, 4}, // corner
|
{1, 2, 5, 4}, // corner
|
||||||
{0, 1, 2, 3} }; // no permutation
|
{0, 1, 2, 3}, // no permutation
|
||||||
|
{0, 5, 10, 15} }; // gregory basis
|
||||||
|
|
||||||
int const * permute = 0;
|
int const * permute = 0;
|
||||||
switch (desc.GetType()) {
|
switch (desc.GetType()) {
|
||||||
@ -245,8 +238,8 @@ CpuEvalLimitController::_EvalLimitSample( LimitLocation const & coords,
|
|||||||
case Desc::BOUNDARY : permute = zeroRings[1]; break;
|
case Desc::BOUNDARY : permute = zeroRings[1]; break;
|
||||||
case Desc::CORNER : permute = zeroRings[2]; break;
|
case Desc::CORNER : permute = zeroRings[2]; break;
|
||||||
case Desc::GREGORY :
|
case Desc::GREGORY :
|
||||||
case Desc::GREGORY_BOUNDARY :
|
case Desc::GREGORY_BOUNDARY : permute = zeroRings[3]; break;
|
||||||
case Desc::GREGORY_BASIS : permute = zeroRings[3]; break;
|
case Desc::GREGORY_BASIS : permute = zeroRings[4]; break;
|
||||||
default:
|
default:
|
||||||
assert(0);
|
assert(0);
|
||||||
};
|
};
|
||||||
|
@ -372,8 +372,7 @@ evalCorner(Far::PatchParam::BitField bits,
|
|||||||
|
|
||||||
void
|
void
|
||||||
evalGregoryBasis(Far::PatchParam::BitField bits, float u, float v,
|
evalGregoryBasis(Far::PatchParam::BitField bits, float u, float v,
|
||||||
Far::StencilTables const & basisStencils,
|
Far::Index const * vertexIndices,
|
||||||
int stencilIndex,
|
|
||||||
VertexBufferDescriptor const & inDesc,
|
VertexBufferDescriptor const & inDesc,
|
||||||
float const * inQ,
|
float const * inQ,
|
||||||
VertexBufferDescriptor const & outDesc,
|
VertexBufferDescriptor const & outDesc,
|
||||||
@ -390,10 +389,10 @@ evalGregoryBasis(Far::PatchParam::BitField bits, float u, float v,
|
|||||||
|
|
||||||
float const *inOffset = inQ + inDesc.offset;
|
float const *inOffset = inQ + inDesc.offset;
|
||||||
|
|
||||||
float * Q = outQ + outDesc.offset;
|
outQ += outDesc.offset;
|
||||||
|
|
||||||
// clear result
|
// clear result
|
||||||
memset(Q, 0, length*sizeof(float));
|
memset(outQ, 0, length*sizeof(float));
|
||||||
if (outDQU) {
|
if (outDQU) {
|
||||||
memset(outDQU, 0, length*sizeof(float));
|
memset(outDQU, 0, length*sizeof(float));
|
||||||
}
|
}
|
||||||
@ -404,22 +403,17 @@ evalGregoryBasis(Far::PatchParam::BitField bits, float u, float v,
|
|||||||
float uu = 1-u,
|
float uu = 1-u,
|
||||||
vv = 1-v;
|
vv = 1-v;
|
||||||
// remark #1572: floating-point equality and inequality comparisons are unreliable
|
// remark #1572: floating-point equality and inequality comparisons are unreliable
|
||||||
#ifdef __INvEL_COMPILER
|
#ifdef __INTEL_COMPILER
|
||||||
#pragma warning diuable 1572
|
#pragma warning disable 1572
|
||||||
#endif
|
#endif
|
||||||
float d11 = u+v; if(u+v==0.0f) d11 = 1.0f;
|
float d11 = u+v; if(u+v==0.0f) d11 = 1.0f;
|
||||||
float d12 = uu+v; if(uu+v==0.0f) d12 = 1.0f;
|
float d12 = uu+v; if(uu+v==0.0f) d12 = 1.0f;
|
||||||
float d21 = u+vv; if(u+vv==0.0f) d21 = 1.0f;
|
float d21 = u+vv; if(u+vv==0.0f) d21 = 1.0f;
|
||||||
float d22 = uu+vv; if(uu+vv==0.0f) d22 = 1.0f;
|
float d22 = uu+vv; if(uu+vv==0.0f) d22 = 1.0f;
|
||||||
#ifdef __INvEL_COMPILER
|
#ifdef __INTEL_COMPILER
|
||||||
#pragma warning enable 1572
|
#pragma warning enable 1572
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
float weights[4][2] = { { u/d11, v/d11 },
|
|
||||||
{ uu/d12, v/d12 },
|
|
||||||
{ u/d21, vv/d21 },
|
|
||||||
{ uu/d22, vv/d22 } };
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// P3 e3- e2+ P2
|
// P3 e3- e2+ P2
|
||||||
// O--------O--------O--------O
|
// O--------O--------O--------O
|
||||||
@ -441,89 +435,44 @@ evalGregoryBasis(Far::PatchParam::BitField bits, float u, float v,
|
|||||||
// P0 e0+ e1- P1
|
// P0 e0+ e1- P1
|
||||||
//
|
//
|
||||||
|
|
||||||
|
float const *v3 = inOffset + vertexIndices[3]*inDesc.stride,
|
||||||
|
*v4 = inOffset + vertexIndices[4]*inDesc.stride,
|
||||||
|
*v8 = inOffset + vertexIndices[8]*inDesc.stride,
|
||||||
|
*v9 = inOffset + vertexIndices[9]*inDesc.stride,
|
||||||
|
*v13 = inOffset + vertexIndices[13]*inDesc.stride,
|
||||||
|
*v14 = inOffset + vertexIndices[14]*inDesc.stride,
|
||||||
|
*v18 = inOffset + vertexIndices[18]*inDesc.stride,
|
||||||
|
*v19 = inOffset + vertexIndices[19]*inDesc.stride;
|
||||||
|
|
||||||
|
float *CP = (float*)alloca(inDesc.length*4*sizeof(float));
|
||||||
|
|
||||||
|
for (int k=0; k<inDesc.length; ++k) {
|
||||||
|
CP[0*inDesc.length + k] = (u * v3[k] + v * v4[k])/d11;
|
||||||
|
CP[1*inDesc.length + k] = (uu * v9[k] + v * v8[k])/d12;
|
||||||
|
CP[2*inDesc.length + k] = (u * v19[k] + vv * v18[k])/d21;
|
||||||
|
CP[3*inDesc.length + k] = (uu * v13[k] + vv * v14[k])/d22;
|
||||||
|
}
|
||||||
|
|
||||||
// XXXX manuelk re-order stencils in factory and get rid of permutation ?
|
// XXXX manuelk re-order stencils in factory and get rid of permutation ?
|
||||||
static int const permute[16] =
|
static int const permute[16] =
|
||||||
{ 0, 1, 7, 5, 2, -1, -1, 6, 16, -1, -1, 12, 15, 17, 11, 10 };
|
{ 0, 1, 7, 5, 2, 3, 8, 6, 16, 18, 13, 12, 15, 17, 11, 10 };
|
||||||
|
|
||||||
int offset = stencilIndex;
|
for (int i=0; i<16; ++i) {
|
||||||
|
|
||||||
for (int i=0, fcount=0; i<16; ++i) {
|
|
||||||
|
|
||||||
int index = permute[i];
|
int index = permute[i];
|
||||||
|
|
||||||
if (index==-1) {
|
float const * in = inOffset + vertexIndices[index]*inDesc.stride;
|
||||||
|
if (index < 0) {
|
||||||
|
in = &CP[-index-1];
|
||||||
|
}
|
||||||
|
|
||||||
// 0-ring vertex: blend 2 extra basis CVs
|
for (int k=0; k<inDesc.length; ++k) {
|
||||||
static int const fpermute[4][2] = { {3, 4}, {9, 8}, {19, 18}, {13, 14} };
|
outQ[k] += BU[i] * in[k];
|
||||||
|
if (outDQU) {
|
||||||
assert(fcount < 4);
|
outDQU[k] += DU[i] * in[k];
|
||||||
int v0 = fpermute[fcount][0],
|
|
||||||
v1 = fpermute[fcount][1];
|
|
||||||
|
|
||||||
Far::Stencil s0 = basisStencils.GetStencil(offset + v0),
|
|
||||||
s1 = basisStencils.GetStencil(offset + v1);
|
|
||||||
|
|
||||||
float w0=weights[fcount][0],
|
|
||||||
w1=weights[fcount][1];
|
|
||||||
|
|
||||||
{
|
|
||||||
Far::Index const * srcIndices = s0.GetVertexIndices();
|
|
||||||
float const * srcWeights = s0.GetWeights();
|
|
||||||
for (int j=0; j<s0.GetSize(); ++j) {
|
|
||||||
float const * in = inOffset + srcIndices[j]*inDesc.stride;
|
|
||||||
float w = BU[i] * w0 * srcWeights[j],
|
|
||||||
dw1 = DU[i] * w0 * srcWeights[j],
|
|
||||||
dw2 = DV[i] * w0 * srcWeights[
|
|
||||||
j];
|
|
||||||
for (int k=0; k<length; ++k) {
|
|
||||||
Q[k] += in[k] * w;
|
|
||||||
if (outDQU) {
|
|
||||||
outDQU[k] += in[k] * dw1;
|
|
||||||
}
|
|
||||||
if (outDQV) {
|
|
||||||
outDQV[k] += in[k] * dw2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
{
|
if (outDQV) {
|
||||||
Far::Index const * srcIndices = s1.GetVertexIndices();
|
outDQV[k] += DV[i] * in[k];
|
||||||
float const * srcWeights = s1.GetWeights();
|
|
||||||
for (int j=0; j<s1.GetSize(); ++j) {
|
|
||||||
float const * in = inOffset + srcIndices[j]*inDesc.stride;
|
|
||||||
float w = BU[i] * w1 * srcWeights[j],
|
|
||||||
dw1 = DU[i] * w1 * srcWeights[j],
|
|
||||||
dw2 = DV[i] * w1 * srcWeights[j];
|
|
||||||
for (int k=0; k<length; ++k) {
|
|
||||||
Q[k] += in[k] * w;
|
|
||||||
if (outDQU) {
|
|
||||||
outDQU[k] += in[k] * dw1;
|
|
||||||
}
|
|
||||||
if (outDQV) {
|
|
||||||
outDQV[k] += in[k] * dw2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
++fcount;
|
|
||||||
} else {
|
|
||||||
Far::Stencil s = basisStencils.GetStencil(offset + index);
|
|
||||||
Far::Index const * srcIndices = s.GetVertexIndices();
|
|
||||||
float const * srcWeights = s.GetWeights();
|
|
||||||
for (int j=0; j<s.GetSize(); ++j) {
|
|
||||||
float const * in = inOffset + srcIndices[j]*inDesc.stride;
|
|
||||||
float w = BU[i] * srcWeights[j],
|
|
||||||
dw1 = DU[i] * srcWeights[j],
|
|
||||||
dw2 = DV[i] * srcWeights[j];
|
|
||||||
for (int k=0; k<length; ++k) {
|
|
||||||
Q[k] += in[k] * w;
|
|
||||||
if (outDQU) {
|
|
||||||
outDQU[k] += in[k] * dw1;
|
|
||||||
}
|
|
||||||
if (outDQV) {
|
|
||||||
outDQV[k] += in[k] * dw2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -86,9 +86,9 @@ evalCorner(Far::PatchParam::BitField bits,
|
|||||||
float * outDQV );
|
float * outDQV );
|
||||||
|
|
||||||
void
|
void
|
||||||
evalGregoryBasis(Far::PatchParam::BitField bits, float u, float v,
|
evalGregoryBasis(Far::PatchParam::BitField bits,
|
||||||
Far::StencilTables const & basisStencils,
|
float u, float v,
|
||||||
int stencilIndex,
|
Far::Index const *vertsIndices,
|
||||||
VertexBufferDescriptor const & inDesc,
|
VertexBufferDescriptor const & inDesc,
|
||||||
float const * inQ,
|
float const * inQ,
|
||||||
VertexBufferDescriptor const & outDesc,
|
VertexBufferDescriptor const & outDesc,
|
||||||
|
@ -52,6 +52,9 @@ static const char *bsplineShaderSource =
|
|||||||
static const char *gregoryShaderSource =
|
static const char *gregoryShaderSource =
|
||||||
#include "glslPatchGregory.gen.h"
|
#include "glslPatchGregory.gen.h"
|
||||||
;
|
;
|
||||||
|
static const char *gregoryBasisShaderSource =
|
||||||
|
#include "glslPatchGregoryBasis.gen.h"
|
||||||
|
;
|
||||||
static const char *transitionShaderSource =
|
static const char *transitionShaderSource =
|
||||||
#include "glslPatchTransition.gen.h"
|
#include "glslPatchTransition.gen.h"
|
||||||
;
|
;
|
||||||
@ -156,6 +159,17 @@ GLDrawRegistryBase::_CreateDrawSourceConfig(
|
|||||||
sconfig->tessEvalShader.AddDefine("OSD_PATCH_TESS_EVAL_GREGORY_SHADER");
|
sconfig->tessEvalShader.AddDefine("OSD_PATCH_TESS_EVAL_GREGORY_SHADER");
|
||||||
sconfig->tessEvalShader.AddDefine("OSD_PATCH_GREGORY_BOUNDARY");
|
sconfig->tessEvalShader.AddDefine("OSD_PATCH_GREGORY_BOUNDARY");
|
||||||
break;
|
break;
|
||||||
|
case Far::PatchDescriptor::GREGORY_BASIS:
|
||||||
|
sconfig->vertexShader.source = gregoryBasisShaderSource;
|
||||||
|
sconfig->vertexShader.version = "#version 410\n";
|
||||||
|
sconfig->vertexShader.AddDefine("OSD_PATCH_VERTEX_GREGORY_BASIS_SHADER");
|
||||||
|
sconfig->tessControlShader.source = gregoryBasisShaderSource;
|
||||||
|
sconfig->tessControlShader.version = "#version 410\n";
|
||||||
|
sconfig->tessControlShader.AddDefine("OSD_PATCH_TESS_CONTROL_GREGORY_BASIS_SHADER");
|
||||||
|
sconfig->tessEvalShader.source = gregoryBasisShaderSource;
|
||||||
|
sconfig->tessEvalShader.version = "#version 410\n";
|
||||||
|
sconfig->tessEvalShader.AddDefine("OSD_PATCH_TESS_EVAL_GREGORY_BASIS_SHADER");
|
||||||
|
break;
|
||||||
default: // POINTS, LINES, QUADS, TRIANGLES
|
default: // POINTS, LINES, QUADS, TRIANGLES
|
||||||
// do nothing
|
// do nothing
|
||||||
break;
|
break;
|
||||||
|
@ -68,14 +68,31 @@ public:
|
|||||||
_drawContext(0)
|
_drawContext(0)
|
||||||
{
|
{
|
||||||
|
|
||||||
GLMeshInterface::refineMesh(*_refiner, level, bits.test(MeshAdaptive), bits.test(MeshUseSingleCreasePatch));
|
GLMeshInterface::refineMesh(*_refiner, level,
|
||||||
|
bits.test(MeshAdaptive),
|
||||||
|
bits.test(MeshUseSingleCreasePatch));
|
||||||
|
|
||||||
int numElements =
|
int numVertexElementsInterleaved = numVertexElements +
|
||||||
initializeVertexBuffers(numVertexElements, numVaryingElements, bits);
|
(bits.test(MeshInterleaveVarying) ? numVaryingElements : 0);
|
||||||
|
int numVaryingElementsNonInterleaved =
|
||||||
|
(bits.test(MeshInterleaveVarying) ? 0 : numVaryingElements);
|
||||||
|
|
||||||
initializeComputeContext(numVertexElements, numVaryingElements);
|
initializeContext(numVertexElements, numVaryingElements,
|
||||||
|
numVertexElementsInterleaved, level, bits);
|
||||||
|
|
||||||
initializeDrawContext(numElements, level, bits);
|
int numVertices = GLMeshInterface::getNumVertices(*_refiner);
|
||||||
|
|
||||||
|
// FIXME: need a better API for numTotalVertices.
|
||||||
|
if (_patchTables->GetEndCapVertexStencilTables()) {
|
||||||
|
numVertices += _patchTables->GetEndCapVertexStencilTables()->GetNumStencils();
|
||||||
|
}
|
||||||
|
|
||||||
|
initializeVertexBuffers(numVertices,
|
||||||
|
numVertexElementsInterleaved,
|
||||||
|
numVaryingElementsNonInterleaved);
|
||||||
|
|
||||||
|
// will retire soon
|
||||||
|
_drawContext->UpdateVertexTexture(_vertexBuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
Mesh(ComputeController * computeController,
|
Mesh(ComputeController * computeController,
|
||||||
@ -170,8 +187,9 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
void initializeComputeContext(int numVertexElements,
|
void initializeContext(int numVertexElements,
|
||||||
int numVaryingElements ) {
|
int numVaryingElements,
|
||||||
|
int numElements, int level, MeshBitset bits) {
|
||||||
|
|
||||||
assert(_refiner);
|
assert(_refiner);
|
||||||
|
|
||||||
@ -185,7 +203,6 @@ private:
|
|||||||
|
|
||||||
vertexStencils = Far::StencilTablesFactory::Create(*_refiner, options);
|
vertexStencils = Far::StencilTablesFactory::Create(*_refiner, options);
|
||||||
|
|
||||||
_kernelBatches.push_back(Far::StencilTablesFactory::Create(*vertexStencils));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (numVaryingElements>0) {
|
if (numVaryingElements>0) {
|
||||||
@ -195,44 +212,69 @@ private:
|
|||||||
varyingStencils = Far::StencilTablesFactory::Create(*_refiner, options);
|
varyingStencils = Far::StencilTablesFactory::Create(*_refiner, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
_computeContext = ComputeContext::Create(vertexStencils, varyingStencils);
|
assert(_refiner);
|
||||||
|
Far::PatchTablesFactory::Options poptions(level);
|
||||||
|
poptions.generateFVarTables = bits.test(MeshFVarData);
|
||||||
|
poptions.useSingleCreasePatch = bits.test(MeshUseSingleCreasePatch);
|
||||||
|
|
||||||
|
if (bits.test(MeshUseGregoryBasis)) {
|
||||||
|
poptions.adaptiveStencilTables = vertexStencils;
|
||||||
|
poptions.adaptiveVaryingStencilTables = varyingStencils;
|
||||||
|
}
|
||||||
|
|
||||||
|
_patchTables = Far::PatchTablesFactory::Create(*_refiner, poptions);
|
||||||
|
|
||||||
|
_drawContext = DrawContext::Create(_patchTables, numElements);
|
||||||
|
|
||||||
|
// XXX: factory API fix needed
|
||||||
|
// merge greogry basis stencils
|
||||||
|
Far::StencilTables const * endCapVertexStencils =
|
||||||
|
_patchTables->GetEndCapVertexStencilTables();
|
||||||
|
|
||||||
|
if (endCapVertexStencils) {
|
||||||
|
Far::StencilTables const * endCapVaryingStencils =
|
||||||
|
_patchTables->GetEndCapVaryingStencilTables();
|
||||||
|
|
||||||
|
// concatinate vertexStencils and endCapStencils.
|
||||||
|
// note that endCapStensils is owned by patchTable.
|
||||||
|
Far::StencilTables const *inStencils[] = {
|
||||||
|
vertexStencils, endCapVertexStencils
|
||||||
|
};
|
||||||
|
Far::StencilTables const *concatStencils =
|
||||||
|
Far::StencilTablesFactory::Create(2, inStencils);
|
||||||
|
|
||||||
|
Far::StencilTables const *inVaryingStencils[] = {
|
||||||
|
varyingStencils, endCapVaryingStencils
|
||||||
|
};
|
||||||
|
Far::StencilTables const *concatVaryingStencils =
|
||||||
|
Far::StencilTablesFactory::Create(2, inVaryingStencils);
|
||||||
|
|
||||||
|
delete vertexStencils;
|
||||||
|
vertexStencils = concatStencils;
|
||||||
|
delete varyingStencils;
|
||||||
|
varyingStencils = concatVaryingStencils;
|
||||||
|
}
|
||||||
|
|
||||||
|
_kernelBatches.push_back(Far::StencilTablesFactory::Create(*vertexStencils));
|
||||||
|
|
||||||
|
_computeContext = ComputeContext::Create(vertexStencils,
|
||||||
|
varyingStencils);
|
||||||
|
|
||||||
delete vertexStencils;
|
delete vertexStencils;
|
||||||
delete varyingStencils;
|
delete varyingStencils;
|
||||||
}
|
}
|
||||||
|
|
||||||
void initializeDrawContext(int numElements, int level, MeshBitset bits) {
|
void initializeVertexBuffers(int numVertices,
|
||||||
|
int numVertexElements,
|
||||||
assert(_refiner and _vertexBuffer);
|
int numVaryingElements) {
|
||||||
|
|
||||||
Far::PatchTablesFactory::Options options(level);
|
|
||||||
options.generateFVarTables = bits.test(MeshFVarData);
|
|
||||||
options.useSingleCreasePatch = bits.test(MeshUseSingleCreasePatch);
|
|
||||||
|
|
||||||
_patchTables = Far::PatchTablesFactory::Create(*_refiner, options);
|
|
||||||
|
|
||||||
_drawContext = DrawContext::Create(_patchTables, numElements);
|
|
||||||
|
|
||||||
_drawContext->UpdateVertexTexture(_vertexBuffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
int initializeVertexBuffers(int numVertexElements,
|
|
||||||
int numVaryingElements, MeshBitset bits) {
|
|
||||||
|
|
||||||
int numVertices = GLMeshInterface::getNumVertices(*_refiner);
|
|
||||||
|
|
||||||
int numElements = numVertexElements +
|
|
||||||
(bits.test(MeshInterleaveVarying) ? numVaryingElements : 0);
|
|
||||||
|
|
||||||
if (numVertexElements) {
|
if (numVertexElements) {
|
||||||
|
_vertexBuffer = VertexBuffer::Create(numVertexElements, numVertices);
|
||||||
_vertexBuffer = VertexBuffer::Create(numElements, numVertices);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (numVaryingElements>0 and (not bits.test(MeshInterleaveVarying))) {
|
if (numVaryingElements) {
|
||||||
_varyingBuffer = VertexBuffer::Create(numVaryingElements, numVertices);
|
_varyingBuffer = VertexBuffer::Create(numVaryingElements, numVertices);
|
||||||
}
|
}
|
||||||
return numElements;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Far::TopologyRefiner * _refiner;
|
Far::TopologyRefiner * _refiner;
|
||||||
@ -280,14 +322,32 @@ public:
|
|||||||
{
|
{
|
||||||
assert(_refiner);
|
assert(_refiner);
|
||||||
|
|
||||||
GLMeshInterface::refineMesh(*_refiner, level, bits.test(MeshAdaptive), bits.test(MeshUseSingleCreasePatch));
|
GLMeshInterface::refineMesh(*_refiner, level,
|
||||||
|
bits.test(MeshAdaptive),
|
||||||
|
bits.test(MeshUseSingleCreasePatch));
|
||||||
|
|
||||||
int numElements =
|
|
||||||
initializeVertexBuffers(numVertexElements, numVaryingElements, bits);
|
|
||||||
|
|
||||||
initializeComputeContext(numVertexElements, numVaryingElements);
|
int numVertexElementsInterleaved = numVertexElements +
|
||||||
|
(bits.test(MeshInterleaveVarying) ? numVaryingElements : 0);
|
||||||
|
int numVaryingElementsNonInterleaved =
|
||||||
|
(bits.test(MeshInterleaveVarying) ? 0 : numVaryingElements);
|
||||||
|
|
||||||
initializeDrawContext(numElements, level, bits);
|
initializeContext(numVertexElements, numVaryingElements,
|
||||||
|
numVertexElementsInterleaved, level, bits);
|
||||||
|
|
||||||
|
int numVertices = GLMeshInterface::getNumVertices(*_refiner);
|
||||||
|
|
||||||
|
// FIXME: need better API for total number of vertices.
|
||||||
|
if (_patchTables->GetEndCapVertexStencilTables()) {
|
||||||
|
numVertices += _patchTables->GetEndCapVertexStencilTables()->GetNumStencils();
|
||||||
|
}
|
||||||
|
|
||||||
|
initializeVertexBuffers(numVertices,
|
||||||
|
numVertexElementsInterleaved,
|
||||||
|
numVaryingElementsNonInterleaved);
|
||||||
|
|
||||||
|
// will retire
|
||||||
|
_drawContext->UpdateVertexTexture(_vertexBuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
Mesh(ComputeController * computeController,
|
Mesh(ComputeController * computeController,
|
||||||
@ -382,9 +442,9 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
void initializeComputeContext(int numVertexElements,
|
void initializeContext(int numVertexElements,
|
||||||
int numVaryingElements ) {
|
int numVaryingElements,
|
||||||
|
int numElements, int level, MeshBitset bits) {
|
||||||
assert(_refiner);
|
assert(_refiner);
|
||||||
|
|
||||||
Far::StencilTablesFactory::Options options;
|
Far::StencilTablesFactory::Options options;
|
||||||
@ -396,8 +456,6 @@ private:
|
|||||||
if (numVertexElements>0) {
|
if (numVertexElements>0) {
|
||||||
|
|
||||||
vertexStencils = Far::StencilTablesFactory::Create(*_refiner, options);
|
vertexStencils = Far::StencilTablesFactory::Create(*_refiner, options);
|
||||||
|
|
||||||
_kernelBatches.push_back(Far::StencilTablesFactory::Create(*vertexStencils));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (numVaryingElements>0) {
|
if (numVaryingElements>0) {
|
||||||
@ -409,41 +467,73 @@ private:
|
|||||||
|
|
||||||
_computeContext = ComputeContext::Create(_clContext, vertexStencils, varyingStencils);
|
_computeContext = ComputeContext::Create(_clContext, vertexStencils, varyingStencils);
|
||||||
|
|
||||||
|
assert(_refiner);
|
||||||
|
|
||||||
|
Far::PatchTablesFactory::Options poptions(level);
|
||||||
|
poptions.generateFVarTables = bits.test(MeshFVarData);
|
||||||
|
poptions.useSingleCreasePatch = bits.test(MeshUseSingleCreasePatch);
|
||||||
|
|
||||||
|
// use gregory stencils
|
||||||
|
if (bits.test(MeshUseGregoryBasis)) {
|
||||||
|
poptions.adaptiveStencilTables = vertexStencils;
|
||||||
|
poptions.adaptiveVaryingStencilTables = varyingStencils;
|
||||||
|
}
|
||||||
|
|
||||||
|
_patchTables = Far::PatchTablesFactory::Create(*_refiner, poptions);
|
||||||
|
|
||||||
|
_drawContext = DrawContext::Create(_patchTables, numElements);
|
||||||
|
|
||||||
|
Far::StencilTables const *endCapVertexStencils =
|
||||||
|
_patchTables->GetEndCapVertexStencilTables();
|
||||||
|
|
||||||
|
if (endCapVertexStencils) {
|
||||||
|
Far::StencilTables const *endCapVaryingStencils =
|
||||||
|
_patchTables->GetEndCapVaryingStencilTables();
|
||||||
|
|
||||||
|
// concatinate vertexStencils and endCapStencils.
|
||||||
|
// note that endCapStensils is owned by patchTable.
|
||||||
|
Far::StencilTables const *inStencils[] = {
|
||||||
|
vertexStencils, endCapVertexStencils
|
||||||
|
};
|
||||||
|
|
||||||
|
Far::StencilTables const *concatStencils =
|
||||||
|
Far::StencilTablesFactory::Create(2, inStencils);
|
||||||
|
|
||||||
|
_kernelBatches.push_back(Far::StencilTablesFactory::Create(*concatStencils));
|
||||||
|
|
||||||
|
Far::StencilTables const *inVaryingStencils[] = {
|
||||||
|
varyingStencils, endCapVaryingStencils
|
||||||
|
};
|
||||||
|
|
||||||
|
Far::StencilTables const *concatVaryingStencils =
|
||||||
|
Far::StencilTablesFactory::Create(2, inVaryingStencils);
|
||||||
|
|
||||||
|
delete vertexStencils;
|
||||||
|
vertexStencils = concatStencils;
|
||||||
|
delete varyingStencils;
|
||||||
|
varyingStencils = concatVaryingStencils;
|
||||||
|
}
|
||||||
|
_kernelBatches.push_back(Far::StencilTablesFactory::Create(*vertexStencils));
|
||||||
|
|
||||||
|
_computeContext = ComputeContext::Create(_clContext,
|
||||||
|
vertexStencils,
|
||||||
|
varyingStencils);
|
||||||
|
|
||||||
delete vertexStencils;
|
delete vertexStencils;
|
||||||
delete varyingStencils;
|
delete varyingStencils;
|
||||||
}
|
}
|
||||||
|
|
||||||
void initializeDrawContext(int numElements, int level, MeshBitset bits) {
|
void initializeVertexBuffers(int numVertices,
|
||||||
|
int numVertexElements,
|
||||||
assert(_refiner and _vertexBuffer);
|
int numVaryingElements) {
|
||||||
|
|
||||||
Far::PatchTablesFactory::Options options(level);
|
|
||||||
options.generateFVarTables = bits.test(MeshFVarData);
|
|
||||||
|
|
||||||
_patchTables = Far::PatchTablesFactory::Create(*_refiner);
|
|
||||||
|
|
||||||
_drawContext = DrawContext::Create(_patchTables, numElements);
|
|
||||||
|
|
||||||
_drawContext->UpdateVertexTexture(_vertexBuffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
int initializeVertexBuffers(int numVertexElements,
|
|
||||||
int numVaryingElements, MeshBitset bits) {
|
|
||||||
|
|
||||||
int numVertices = GLMeshInterface::getNumVertices(*_refiner);
|
|
||||||
|
|
||||||
int numElements = numVertexElements +
|
|
||||||
(bits.test(MeshInterleaveVarying) ? numVaryingElements : 0);
|
|
||||||
|
|
||||||
if (numVertexElements) {
|
if (numVertexElements) {
|
||||||
|
_vertexBuffer = VertexBuffer::Create(numVertexElements, numVertices, _clContext);
|
||||||
_vertexBuffer = VertexBuffer::Create(numElements, numVertices, _clContext);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (numVaryingElements>0 and (not bits.test(MeshInterleaveVarying))) {
|
if (numVaryingElements) {
|
||||||
_varyingBuffer = VertexBuffer::Create(numVaryingElements, numVertices, _clContext);
|
_varyingBuffer = VertexBuffer::Create(numVaryingElements, numVertices, _clContext);
|
||||||
}
|
}
|
||||||
return numElements;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Far::TopologyRefiner * _refiner;
|
Far::TopologyRefiner * _refiner;
|
||||||
|
@ -93,7 +93,9 @@ struct ControlVertex {
|
|||||||
vec4 position;
|
vec4 position;
|
||||||
centroid vec4 patchCoord; // u, v, level, faceID
|
centroid vec4 patchCoord; // u, v, level, faceID
|
||||||
ivec4 ptexInfo; // U offset, V offset, 2^ptexlevel', rotation
|
ivec4 ptexInfo; // U offset, V offset, 2^ptexlevel', rotation
|
||||||
|
#ifdef OSD_ENABLE_PATCH_CULL
|
||||||
ivec3 clipFlag;
|
ivec3 clipFlag;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
struct OutputVertex {
|
struct OutputVertex {
|
||||||
|
294
opensubdiv/osd/glslPatchGregoryBasis.glsl
Normal file
294
opensubdiv/osd/glslPatchGregoryBasis.glsl
Normal file
@ -0,0 +1,294 @@
|
|||||||
|
//
|
||||||
|
// Copyright 2015 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.
|
||||||
|
//
|
||||||
|
|
||||||
|
//----------------------------------------------------------
|
||||||
|
// Patches.VertexGregoryBasis
|
||||||
|
//----------------------------------------------------------
|
||||||
|
#ifdef OSD_PATCH_VERTEX_GREGORY_BASIS_SHADER
|
||||||
|
|
||||||
|
layout(location = 0) in vec4 position;
|
||||||
|
OSD_USER_VARYING_ATTRIBUTE_DECLARE
|
||||||
|
|
||||||
|
out block {
|
||||||
|
ControlVertex v;
|
||||||
|
OSD_USER_VARYING_DECLARE
|
||||||
|
} outpt;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
outpt.v.position = OsdModelViewMatrix() * position;
|
||||||
|
outpt.v.patchCoord = vec4(0);
|
||||||
|
outpt.v.ptexInfo = ivec4(0);
|
||||||
|
OSD_PATCH_CULL_COMPUTE_CLIPFLAGS(position);
|
||||||
|
OSD_USER_VARYING_PER_VERTEX();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//----------------------------------------------------------
|
||||||
|
// Patches.TessControlGregoryBasis
|
||||||
|
//----------------------------------------------------------
|
||||||
|
#ifdef OSD_PATCH_TESS_CONTROL_GREGORY_BASIS_SHADER
|
||||||
|
|
||||||
|
layout(vertices = 20) out;
|
||||||
|
|
||||||
|
in block {
|
||||||
|
ControlVertex v;
|
||||||
|
OSD_USER_VARYING_DECLARE
|
||||||
|
} inpt[];
|
||||||
|
|
||||||
|
out block {
|
||||||
|
ControlVertex v;
|
||||||
|
OSD_USER_VARYING_DECLARE
|
||||||
|
} outpt[];
|
||||||
|
|
||||||
|
#define ID gl_InvocationID
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
outpt[ID].v = inpt[ID].v;
|
||||||
|
OSD_USER_VARYING_PER_CONTROL_POINT(ID, ID);
|
||||||
|
|
||||||
|
int patchLevel = GetPatchLevel();
|
||||||
|
|
||||||
|
// +0.5 to avoid interpolation error of integer value
|
||||||
|
outpt[ID].v.patchCoord = vec4(0, 0,
|
||||||
|
patchLevel+0.5,
|
||||||
|
GetPrimitiveID()+0.5);
|
||||||
|
OSD_COMPUTE_PTEX_COORD_TESSCONTROL_SHADER;
|
||||||
|
|
||||||
|
if (ID == 0) {
|
||||||
|
OSD_PATCH_CULL(OSD_PATCH_INPUT_SIZE);
|
||||||
|
|
||||||
|
// XXX: this metric is not consistent.
|
||||||
|
// we will 1) compute the cage length as before
|
||||||
|
// or 2) compute limit length for all patches.
|
||||||
|
#ifdef OSD_ENABLE_SCREENSPACE_TESSELLATION
|
||||||
|
gl_TessLevelOuter[0] =
|
||||||
|
TessAdaptive(inpt[0].v.position.xyz, inpt[5].v.position.xyz);
|
||||||
|
gl_TessLevelOuter[1] =
|
||||||
|
TessAdaptive(inpt[0].v.position.xyz, inpt[15].v.position.xyz);
|
||||||
|
gl_TessLevelOuter[2] =
|
||||||
|
TessAdaptive(inpt[10].v.position.xyz, inpt[15].v.position.xyz);
|
||||||
|
gl_TessLevelOuter[3] =
|
||||||
|
TessAdaptive(inpt[5].v.position.xyz, inpt[10].v.position.xyz);
|
||||||
|
|
||||||
|
gl_TessLevelInner[0] =
|
||||||
|
max(gl_TessLevelOuter[1], gl_TessLevelOuter[3]);
|
||||||
|
gl_TessLevelInner[1] =
|
||||||
|
max(gl_TessLevelOuter[0], gl_TessLevelOuter[2]);
|
||||||
|
#else
|
||||||
|
gl_TessLevelInner[0] = GetTessLevel(patchLevel);
|
||||||
|
gl_TessLevelInner[1] = GetTessLevel(patchLevel);
|
||||||
|
gl_TessLevelOuter[0] = GetTessLevel(patchLevel);
|
||||||
|
gl_TessLevelOuter[1] = GetTessLevel(patchLevel);
|
||||||
|
gl_TessLevelOuter[2] = GetTessLevel(patchLevel);
|
||||||
|
gl_TessLevelOuter[3] = GetTessLevel(patchLevel);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//----------------------------------------------------------
|
||||||
|
// Patches.TessEvalGregory
|
||||||
|
//----------------------------------------------------------
|
||||||
|
#ifdef OSD_PATCH_TESS_EVAL_GREGORY_BASIS_SHADER
|
||||||
|
|
||||||
|
layout(quads) in;
|
||||||
|
layout(cw) in;
|
||||||
|
|
||||||
|
#if defined OSD_FRACTIONAL_ODD_SPACING
|
||||||
|
layout(fractional_odd_spacing) in;
|
||||||
|
#elif defined OSD_FRACTIONAL_EVEN_SPACING
|
||||||
|
layout(fractional_even_spacing) in;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
in block {
|
||||||
|
ControlVertex v;
|
||||||
|
OSD_USER_VARYING_DECLARE
|
||||||
|
} inpt[];
|
||||||
|
|
||||||
|
out block {
|
||||||
|
OutputVertex v;
|
||||||
|
OSD_USER_VARYING_DECLARE
|
||||||
|
} outpt;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
float u = gl_TessCoord.x,
|
||||||
|
v = gl_TessCoord.y;
|
||||||
|
|
||||||
|
vec3 p[20];
|
||||||
|
|
||||||
|
for (int i = 0; i < 20; ++i) {
|
||||||
|
p[i] = inpt[i].v.position.xyz;
|
||||||
|
}
|
||||||
|
vec3 q[16];
|
||||||
|
|
||||||
|
float U = 1-u, V=1-v;
|
||||||
|
|
||||||
|
float d11 = u+v; if(u+v==0.0f) d11 = 1.0f;
|
||||||
|
float d12 = U+v; if(U+v==0.0f) d12 = 1.0f;
|
||||||
|
float d21 = u+V; if(u+V==0.0f) d21 = 1.0f;
|
||||||
|
float d22 = U+V; if(U+V==0.0f) d22 = 1.0f;
|
||||||
|
|
||||||
|
#if 1
|
||||||
|
q[ 5] = (u*p[3] + v*p[4])/d11;
|
||||||
|
q[ 6] = (U*p[9] + v*p[8])/d12;
|
||||||
|
q[ 9] = (u*p[19] + V*p[18])/d21;
|
||||||
|
q[10] = (U*p[13] + V*p[14])/d22;
|
||||||
|
#else
|
||||||
|
q[ 5] = (p[3] + p[4])/2.0;
|
||||||
|
q[ 6] = (p[9] + p[8])/2.0;
|
||||||
|
q[ 9] = (p[19] + p[18])/2.0;
|
||||||
|
q[10] = (p[13] + p[14])/2.0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
q[ 0] = p[0];
|
||||||
|
q[ 1] = p[1];
|
||||||
|
q[ 2] = p[7];
|
||||||
|
q[ 3] = p[5];
|
||||||
|
q[ 4] = p[2];
|
||||||
|
q[ 7] = p[6];
|
||||||
|
q[ 8] = p[16];
|
||||||
|
q[11] = p[12];
|
||||||
|
q[12] = p[15];
|
||||||
|
q[13] = p[17];
|
||||||
|
q[14] = p[11];
|
||||||
|
q[15] = p[10];
|
||||||
|
|
||||||
|
vec3 WorldPos = vec3(0, 0, 0);
|
||||||
|
vec3 Tangent = vec3(0, 0, 0);
|
||||||
|
vec3 BiTangent = vec3(0, 0, 0);
|
||||||
|
|
||||||
|
#ifdef OSD_COMPUTE_NORMAL_DERIVATIVES
|
||||||
|
float B[4], D[4], C[4];
|
||||||
|
vec3 BUCP[4] = vec3[4](vec3(0,0,0), vec3(0,0,0), vec3(0,0,0), vec3(0,0,0)),
|
||||||
|
DUCP[4] = vec3[4](vec3(0,0,0), vec3(0,0,0), vec3(0,0,0), vec3(0,0,0)),
|
||||||
|
CUCP[4] = vec3[4](vec3(0,0,0), vec3(0,0,0), vec3(0,0,0), vec3(0,0,0));
|
||||||
|
vec3 dUU = vec3(0);
|
||||||
|
vec3 dVV = vec3(0);
|
||||||
|
vec3 dUV = vec3(0);
|
||||||
|
|
||||||
|
Univar4x4(u, B, D, C);
|
||||||
|
|
||||||
|
for (int i=0; i<4; ++i) {
|
||||||
|
for (uint j=0; j<4; ++j) {
|
||||||
|
// reverse face front
|
||||||
|
vec3 A = q[i + 4*j];
|
||||||
|
|
||||||
|
BUCP[i] += A * B[j];
|
||||||
|
DUCP[i] += A * D[j];
|
||||||
|
CUCP[i] += A * C[j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Univar4x4(v, B, D, C);
|
||||||
|
|
||||||
|
for (int i=0; i<4; ++i) {
|
||||||
|
WorldPos += B[i] * BUCP[i];
|
||||||
|
Tangent += B[i] * DUCP[i];
|
||||||
|
BiTangent += D[i] * BUCP[i];
|
||||||
|
dUU += B[i] * CUCP[i];
|
||||||
|
dVV += C[i] * BUCP[i];
|
||||||
|
dUV += D[i] * DUCP[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
int level = int(inpt[0].v.ptexInfo.z);
|
||||||
|
BiTangent *= 3 * level;
|
||||||
|
Tangent *= 3 * level;
|
||||||
|
dUU *= 6 * level;
|
||||||
|
dVV *= 6 * level;
|
||||||
|
dUV *= 9 * level;
|
||||||
|
|
||||||
|
vec3 n = cross(BiTangent, Tangent);
|
||||||
|
vec3 normal = normalize(n);
|
||||||
|
|
||||||
|
float E = dot(Tangent, Tangent);
|
||||||
|
float F = dot(Tangent, BiTangent);
|
||||||
|
float G = dot(BiTangent, BiTangent);
|
||||||
|
float e = dot(normal, dUU);
|
||||||
|
float f = dot(normal, dUV);
|
||||||
|
float g = dot(normal, dVV);
|
||||||
|
|
||||||
|
vec3 Nu = (f*F-e*G)/(E*G-F*F) * Tangent + (e*F-f*E)/(E*G-F*F) * BiTangent;
|
||||||
|
vec3 Nv = (g*F-f*G)/(E*G-F*F) * Tangent + (f*F-g*E)/(E*G-F*F) * BiTangent;
|
||||||
|
|
||||||
|
Nu = Nu/length(n) - n * (dot(Nu,n)/pow(dot(n,n), 1.5));
|
||||||
|
Nv = Nv/length(n) - n * (dot(Nv,n)/pow(dot(n,n), 1.5));
|
||||||
|
|
||||||
|
outpt.v.Nu = Nu;
|
||||||
|
outpt.v.Nv = Nv;
|
||||||
|
|
||||||
|
#else
|
||||||
|
float B[4], D[4];
|
||||||
|
vec3 BUCP[4] = vec3[4](vec3(0,0,0), vec3(0,0,0), vec3(0,0,0), vec3(0,0,0)),
|
||||||
|
DUCP[4] = vec3[4](vec3(0,0,0), vec3(0,0,0), vec3(0,0,0), vec3(0,0,0));
|
||||||
|
|
||||||
|
Univar4x4(u, B, D);
|
||||||
|
|
||||||
|
for (int i=0; i<4; ++i) {
|
||||||
|
for (uint j=0; j<4; ++j) {
|
||||||
|
// reverse face front
|
||||||
|
vec3 A = q[i + 4*j];
|
||||||
|
|
||||||
|
BUCP[i] += A * B[j];
|
||||||
|
DUCP[i] += A * D[j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Univar4x4(v, B, D);
|
||||||
|
|
||||||
|
for (int i=0; i<4; ++i) {
|
||||||
|
WorldPos += B[i] * BUCP[i];
|
||||||
|
Tangent += B[i] * DUCP[i];
|
||||||
|
BiTangent += D[i] * BUCP[i];
|
||||||
|
}
|
||||||
|
int level = int(inpt[0].v.ptexInfo.z);
|
||||||
|
BiTangent *= 3 * level;
|
||||||
|
Tangent *= 3 * level;
|
||||||
|
|
||||||
|
vec3 normal = normalize(cross(BiTangent, Tangent));
|
||||||
|
|
||||||
|
#endif
|
||||||
|
outpt.v.position = vec4(WorldPos, 1.0f);
|
||||||
|
outpt.v.normal = normal;
|
||||||
|
outpt.v.tangent = BiTangent;
|
||||||
|
outpt.v.bitangent = Tangent;
|
||||||
|
|
||||||
|
//OSD_USER_VARYING_PER_EVAL_POINT(vec2(u,v), 0, 3, 1, 2);
|
||||||
|
OSD_USER_VARYING_PER_EVAL_POINT(vec2(u,v), 0, 15, 5, 10);
|
||||||
|
|
||||||
|
outpt.v.patchCoord = inpt[0].v.patchCoord;
|
||||||
|
outpt.v.patchCoord.xy = vec2(v, u);
|
||||||
|
|
||||||
|
OSD_COMPUTE_PTEX_COORD_TESSEVAL_SHADER;
|
||||||
|
|
||||||
|
OSD_DISPLACEMENT_CALLBACK;
|
||||||
|
|
||||||
|
gl_Position = OsdProjectionMatrix() * outpt.v.position;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
@ -51,7 +51,8 @@ enum MeshBits {
|
|||||||
MeshPtexData = 2,
|
MeshPtexData = 2,
|
||||||
MeshFVarData = 3,
|
MeshFVarData = 3,
|
||||||
MeshUseSingleCreasePatch = 4,
|
MeshUseSingleCreasePatch = 4,
|
||||||
NUM_MESH_BITS = 5,
|
MeshUseGregoryBasis = 5,
|
||||||
|
NUM_MESH_BITS = 6,
|
||||||
};
|
};
|
||||||
typedef std::bitset<NUM_MESH_BITS> MeshBitset;
|
typedef std::bitset<NUM_MESH_BITS> MeshBitset;
|
||||||
|
|
||||||
|
21
regression/shapes/catmark_gregory_test0.h
Normal file
21
regression/shapes/catmark_gregory_test0.h
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
static const std::string catmark_gregory_test0 = std::string(
|
||||||
|
"# This file uses centimeters as units for non-parametric coordinates.\n"
|
||||||
|
"v -0.500000 0.204097 -0.500000\n"
|
||||||
|
"v 0.000000 0.117710 -0.500000\n"
|
||||||
|
"v -0.500000 0.142210 -0.000000\n"
|
||||||
|
"v 0.000000 0.000000 0.000000\n"
|
||||||
|
"v -0.500000 0.204097 0.500000\n"
|
||||||
|
"v 0.000000 0.117710 0.500000\n"
|
||||||
|
"v 0.500000 0.348563 -0.003642\n"
|
||||||
|
"vt -0.500000 -0.500000\n"
|
||||||
|
"vt 0.000000 -0.500000\n"
|
||||||
|
"vt -0.500000 -0.000000\n"
|
||||||
|
"vt 0.000000 0.000000\n"
|
||||||
|
"vt -0.500000 0.500000\n"
|
||||||
|
"vt 0.000000 0.500000\n"
|
||||||
|
"vt 0.500000 -0.003642\n"
|
||||||
|
"s 1\n"
|
||||||
|
"f 1/1/1 2/2/2 4/4/4 3/3/3\n"
|
||||||
|
"f 3/3/3 4/4/4 6/6/6 5/5/5\n"
|
||||||
|
"f 2/2/2 7/7/7 6/6/6 4/4/4\n"
|
||||||
|
);
|
Loading…
Reference in New Issue
Block a user