Merge pull request #399 from c64kernal/dev

osd_regression test ported over to new API and small bug fix in vtr
This commit is contained in:
Jeremy Cowles 2015-03-30 22:04:34 -07:00
commit e8a7684d8d
9 changed files with 509 additions and 351 deletions

View File

@ -36,6 +36,7 @@
#include "osd/opencl.h"
#include <cstdio>
#include <string>
static bool HAS_CL_VERSION_1_1 () {
#ifdef OPENSUBDIV_HAS_OPENCL
@ -58,6 +59,11 @@ static bool HAS_CL_VERSION_1_1 () {
}
static bool initCL(cl_context *clContext, cl_command_queue *clQueue)
{
if (!clGetPlatformIDs) {
printf("Error clGetPlatformIDs call not bound.\n");
return false;
}
cl_int ciErrNum;
cl_platform_id cpPlatform = 0;

View File

@ -373,6 +373,11 @@ QuadRefinement::populateEdgeFaceRelation() {
child._edgeFaceIndices.resize( childEdgeFaceIndexSizeEstimate);
child._edgeFaceLocalIndices.resize(childEdgeFaceIndexSizeEstimate);
// Update _maxEdgeFaces from the parent level before calling the
// populateEdgeFacesFromParent methods below, as these may further
// update _maxEdgeFaces.
child._maxEdgeFaces = parent._maxEdgeFaces;
populateEdgeFacesFromParentFaces();
populateEdgeFacesFromParentEdges();
@ -382,8 +387,6 @@ QuadRefinement::populateEdgeFaceRelation() {
child.getOffsetOfEdgeFaces(child.getNumEdges()-1);
child._edgeFaceIndices.resize( childEdgeFaceIndexSizeEstimate);
child._edgeFaceLocalIndices.resize(childEdgeFaceIndexSizeEstimate);
child._maxEdgeFaces = parent._maxEdgeFaces;
}
void

View File

@ -366,6 +366,11 @@ TriRefinement::populateEdgeFaceRelation() {
_child->_edgeFaceIndices.resize(childEdgeFaceIndexSizeEstimate);
_child->_edgeFaceLocalIndices.resize(childEdgeFaceIndexSizeEstimate);
// Update _maxEdgeFaces from the parent level before calling the
// populateEdgeFacesFromParent methods below, as these may further
// update _maxEdgeFaces.
_child->_maxEdgeFaces = _parent->_maxEdgeFaces;
populateEdgeFacesFromParentFaces();
populateEdgeFacesFromParentEdges();
@ -375,8 +380,6 @@ TriRefinement::populateEdgeFaceRelation() {
_child->getOffsetOfEdgeFaces(_child->getNumEdges()-1);
_child->_edgeFaceIndices.resize(childEdgeFaceIndexSizeEstimate);
_child->_edgeFaceLocalIndices.resize(childEdgeFaceIndexSizeEstimate);
_child->_maxEdgeFaces = _parent->_maxEdgeFaces;
}
void

View File

@ -27,6 +27,7 @@ set(REGRESSION_COMMON_SOURCE_FILES
)
set(REGRESSION_COMMON_HEADER_FILES
cmp_utils.h
hbr_utils.h
shape_utils.h
vtr_utils.h

View File

@ -0,0 +1,195 @@
//
// 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.
//
#ifndef CMP_UTILS_H
#define CMP_UTILS_H
#include <far/topologyRefinerFactory.h>
#include "../../regression/common/hbr_utils.h"
//------------------------------------------------------------------------------
// Copies vertex data from hmesh into hbrVertexData reordered to match
// the given refiner and subdivision level. This is used for later easy
// comparison between the two.
template<class T>
void
GetReorderedHbrVertexData(
const OpenSubdiv::Far::TopologyRefiner &refiner,
const OpenSubdiv::HbrMesh<T> &hmesh,
std::vector<T> *hbrVertexData,
std::vector<bool> *hbrVertexOnBoundaryData = NULL)
{
typedef OpenSubdiv::HbrVertex<T> Hvertex;
typedef OpenSubdiv::HbrFace<T> Hface;
typedef OpenSubdiv::HbrHalfedge<T> Hhalfedge;
struct Mapper {
struct LevelMap {
std::vector<Hface *> faces;
std::vector<Hhalfedge *> edges;
std::vector<Hvertex *> verts;
};
std::vector<LevelMap> maps;
Mapper(const OpenSubdiv::Far::TopologyRefiner &refiner,
const OpenSubdiv::HbrMesh<T> &hmesh) {
maps.resize(refiner.GetMaxLevel()+1);
typedef OpenSubdiv::Far::Index Index;
typedef OpenSubdiv::Far::ConstIndexArray ConstIndexArray;
{ // Populate base level
// note : topological ordering is identical between Hbr and Vtr
// for the base level
int nfaces = refiner.GetNumFaces(0),
nedges = refiner.GetNumEdges(0),
nverts = refiner.GetNumVertices(0);
maps[0].faces.resize(nfaces, 0);
maps[0].edges.resize(nedges, 0);
maps[0].verts.resize(nverts, 0);
for (int face=0; face<nfaces; ++face) {
maps[0].faces[face] = hmesh.GetFace(face);
}
for (int edge = 0; edge <nedges; ++edge) {
ConstIndexArray vtrVerts = refiner.GetEdgeVertices(0, edge);
Hvertex const * v0 = hmesh.GetVertex(vtrVerts[0]),
* v1 = hmesh.GetVertex(vtrVerts[1]);
Hhalfedge * e = v0->GetEdge(v1);
if (not e) {
e = v1->GetEdge(v0);
}
assert(e);
maps[0].edges[edge] = e;
}
for (int vert = 0; vert<nverts; ++vert) {
maps[0].verts[vert] = hmesh.GetVertex(vert);
}
}
// Populate refined levels
for (int level=1, ecount=0; level<=refiner.GetMaxLevel(); ++level) {
LevelMap & previous = maps[level-1],
& current = maps[level];
current.faces.resize(refiner.GetNumFaces(level), 0);
current.edges.resize(refiner.GetNumEdges(level), 0);
current.verts.resize(refiner.GetNumVertices(level), 0);
for (int face=0; face < refiner.GetNumFaces(level-1); ++face) {
// populate child faces
Hface * f = previous.faces[face];
ConstIndexArray childFaces = refiner.GetFaceChildFaces(level-1, face);
assert(childFaces.size()==f->GetNumVertices());
for (int i=0; i<childFaces.size(); ++i) {
current.faces[childFaces[i]] = f->GetChild(i);
}
// populate child face-verts
Index childVert = refiner.GetFaceChildVertex(level-1, face);
Hvertex * v = f->Subdivide();
assert(v->GetParentFace());
current.verts[childVert] = v;
}
for (int edge=0; edge < refiner.GetNumEdges(level-1); ++edge) {
// populate child edge-verts
Index childVert = refiner.GetEdgeChildVertex(level-1,edge);
Hhalfedge * e = previous.edges[edge];
Hvertex * v = e->Subdivide();
assert(v->GetParentEdge());
current.verts[childVert] = v;
}
for (int vert = 0; vert < refiner.GetNumVertices(level-1); ++vert) {
// populate child vert-verts
Index childVert = refiner.GetVertexChildVertex(level-1, vert);
Hvertex * v = previous.verts[vert]->Subdivide();
current.verts[childVert] = v;
assert(v->GetParentVertex());
}
// populate child edges
for (int edge=0; edge < refiner.GetNumEdges(level); ++edge) {
ConstIndexArray vtrVerts = refiner.GetEdgeVertices(level, edge);
Hvertex const * v0 = current.verts[vtrVerts[0]],
* v1 = current.verts[vtrVerts[1]];
assert(v0 and v1);
Hhalfedge * e= v0->GetEdge(v1);
if (not e) {
e = v1->GetEdge(v0);
}
assert(e);
current.edges[edge] = e;
}
ecount += refiner.GetNumEdges(level-1);
}
}
};
Mapper mapper(refiner, hmesh);
int nverts = hmesh.GetNumVertices();
assert( nverts==refiner.GetNumVerticesTotal() );
hbrVertexData->resize(nverts);
for (int level=0, ofs=0; level<(refiner.GetMaxLevel()+1); ++level) {
typename Mapper::LevelMap & map = mapper.maps[level];
for (int i=0; i<(int)map.verts.size(); ++i) {
Hvertex * v = map.verts[i];
if (hbrVertexOnBoundaryData) {
(*hbrVertexOnBoundaryData)[ofs] = hbrVertexOnBoundary(v);
}
(*hbrVertexData)[ofs++] = v->GetData();
}
}
}
//------------------------------------------------------------------------------
#endif /* CMP_UTILS_H */

View File

@ -625,4 +625,70 @@ simpleHbr(char const * Shapestr, Scheme scheme, std::vector<float> & verts, bool
return mesh;
}
//------------------------------------------------------------------------------
template <class T>
OpenSubdiv::HbrMesh<T> *
interpolateHbrVertexData(char const * Shapestr, Scheme scheme, int maxlevel) {
// Hbr interpolation
OpenSubdiv::HbrMesh<T> *hmesh = simpleHbr<T>(Shapestr, scheme,
/* verts vector */ 0, /* fvar */ false);
assert(hmesh);
for (int level=0, firstface=0; level<maxlevel; ++level ) {
int nfaces = hmesh->GetNumFaces();
for (int i=firstface; i<nfaces; ++i) {
OpenSubdiv::HbrFace<T> * f = hmesh->GetFace(i);
assert(f->GetDepth()==level);
if (not f->IsHole()) {
f->Refine();
}
}
// Hbr allocates faces sequentially, skip faces that have already been
// refined.
firstface = nfaces;
}
return hmesh;
}
//------------------------------------------------------------------------------
// Returns true if a vertex or any of its parents is on a boundary
template <class T>
bool
hbrVertexOnBoundary(const OpenSubdiv::HbrVertex<T> *v)
{
if (not v)
return false;
if (v->OnBoundary())
return true;
OpenSubdiv::HbrVertex<T> const * pv = v->GetParentVertex();
if (pv)
return hbrVertexOnBoundary(pv);
else {
OpenSubdiv::HbrHalfedge<T> const * pe = v->GetParentEdge();
if (pe) {
return hbrVertexOnBoundary(pe->GetOrgVertex()) or
hbrVertexOnBoundary(pe->GetDestVertex());
} else {
OpenSubdiv::HbrFace<T> const * pf = v->GetParentFace(), * rootf = pf;
while (pf) {
pf = pf->GetParent();
if (pf)
rootf=pf;
}
if (rootf)
for (int i=0; i<rootf->GetNumVertices(); ++i)
if (rootf->GetVertex(i)->OnBoundary())
return true;
}
}
return false;
}
#endif /* HBR_UTILS_H */

View File

@ -124,9 +124,51 @@ GetSdcOptions(Shape const & shape) {
return result;
}
//------------------------------------------------------------------------------
void
InterpolateFVarData(OpenSubdiv::Far::TopologyRefiner & refiner,
Shape const & shape, std::vector<float> & fvarData);
//------------------------------------------------------------------------------
template <class T>
OpenSubdiv::Far::TopologyRefiner *
InterpolateVtrVertexData(const char *shapeStr, Scheme scheme, int maxlevel,
std::vector<T> &data) {
typedef OpenSubdiv::Far::TopologyRefiner FarTopologyRefiner;
typedef OpenSubdiv::Far::TopologyRefinerFactory<Shape> FarTopologyRefinerFactory;
// Vtr interpolation
Shape * shape = Shape::parseObj(shapeStr, scheme);
FarTopologyRefiner * refiner =
FarTopologyRefinerFactory::Create(*shape,
FarTopologyRefinerFactory::Options(
GetSdcType(*shape), GetSdcOptions(*shape)));
assert(refiner);
FarTopologyRefiner::UniformOptions options(maxlevel);
options.fullTopologyInLastLevel=true;
refiner->RefineUniform(options);
// populate coarse mesh positions
data.resize(refiner->GetNumVerticesTotal());
for (int i=0; i<refiner->GetNumVertices(0); i++) {
data[i].SetPosition(shape->verts[i*3+0],
shape->verts[i*3+1],
shape->verts[i*3+2]);
}
T * verts = &data[0];
refiner->Interpolate(verts, verts+refiner->GetNumVertices(0));
delete shape;
return refiner;
}
//------------------------------------------------------------------------------
namespace OpenSubdiv {

View File

@ -46,8 +46,6 @@ GLFWwindow* g_window=0;
#include <stdio.h>
#include <cassert>
#include <far/meshFactory.h>
#include <osd/vertex.h>
#include <osd/cpuVertexBuffer.h>
#include <osd/cpuComputeController.h>
@ -55,6 +53,8 @@ GLFWwindow* g_window=0;
#include <osd/cpuGLVertexBuffer.h>
#include <far/stencilTablesFactory.h>
#ifdef OPENSUBDIV_HAS_CUDA
#endif
@ -67,7 +67,10 @@ GLFWwindow* g_window=0;
#include "../../examples/common/clInit.h" // XXXX TODO move file out of examples
#endif
#include "../../regression/common/cmp_utils.h"
#include "../../regression/common/hbr_utils.h"
#include "../../regression/common/vtr_utils.h"
//
// Regression testing matching Osd to Hbr
@ -82,6 +85,8 @@ GLFWwindow* g_window=0;
//
#define PRECISION 1e-6
using namespace OpenSubdiv;
//------------------------------------------------------------------------------
enum BackendType {
kBackendCPU = 0, // raw CPU
@ -145,21 +150,6 @@ struct xyzVV {
}
}
void ApplyVertexEdit(OpenSubdiv::FarVertexEdit const & edit) {
const float *src = edit.GetEdit();
switch(edit.GetOperation()) {
case OpenSubdiv::FarVertexEdit::Set:
_pos[0] = src[0];
_pos[1] = src[1];
_pos[2] = src[2];
break;
case OpenSubdiv::FarVertexEdit::Add:
_pos[0] += src[0];
_pos[1] += src[1];
_pos[2] += src[2];
break;
}
}
void ApplyMovingVertexEdit(const OpenSubdiv::HbrMovingVertexEdit<xyzVV> &) { }
@ -179,78 +169,60 @@ typedef OpenSubdiv::HbrHalfedge<xyzVV> xyzhalfedge;
typedef OpenSubdiv::HbrFaceOperator<xyzVV> xyzFaceOperator;
typedef OpenSubdiv::HbrVertexOperator<xyzVV> xyzVertexOperator;
typedef OpenSubdiv::HbrMesh<OpenSubdiv::OsdVertex> OsdHbrMesh;
typedef OpenSubdiv::HbrVertex<OpenSubdiv::OsdVertex> OsdHbrVertex;
typedef OpenSubdiv::HbrFace<OpenSubdiv::OsdVertex> OsdHbrFace;
typedef OpenSubdiv::HbrHalfedge<OpenSubdiv::OsdVertex> OsdHbrHalfedge;
typedef OpenSubdiv::Far::TopologyRefiner FarTopologyRefiner;
//------------------------------------------------------------------------------
// Returns true if a vertex or any of its parents is on a boundary
bool
VertexOnBoundary( xyzvertex const * v ) {
if (not v)
return false;
if (v->OnBoundary())
return true;
xyzvertex const * pv = v->GetParentVertex();
if (pv)
return VertexOnBoundary(pv);
else {
xyzhalfedge const * pe = v->GetParentEdge();
if (pe) {
return VertexOnBoundary(pe->GetOrgVertex()) or
VertexOnBoundary(pe->GetDestVertex());
} else {
xyzface const * pf = v->GetParentFace(), * rootf = pf;
while (pf) {
pf = pf->GetParent();
if (pf)
rootf=pf;
}
if (rootf)
for (int i=0; i<rootf->GetNumVertices(); ++i)
if (rootf->GetVertex(i)->OnBoundary())
return true;
}
}
return false;
}
//------------------------------------------------------------------------------
int
checkVertexBuffer( xyzmesh * hmesh, const float * vbData, int numElements, std::vector<int> const & remap) {
checkVertexBuffer(
const FarTopologyRefiner &refiner, xyzmesh * hmesh,
const float * vbData, int numElements) {
int count=0;
float deltaAvg[3] = {0.0f, 0.0f, 0.0f},
deltaCnt[3] = {0.0f, 0.0f, 0.0f};
int nverts = hmesh->GetNumVertices();
std::vector<xyzVV> hbrVertexData;
std::vector<bool> hbrVertexOnBoundaryData;
// Only care about vertex on boundary conditions if the interpolate boundary
// is 'none'
std::vector<bool> *hbrVertexOnBoundaryPtr =
(hmesh->GetInterpolateBoundaryMethod() ==
xyzmesh::k_InterpolateBoundaryNone)
? &hbrVertexOnBoundaryData
: NULL;
GetReorderedHbrVertexData(refiner, *hmesh, &hbrVertexData,
hbrVertexOnBoundaryPtr);
//int nverts = hmesh->GetNumVertices();
int nverts = (int)hbrVertexData.size();
for (int i=0; i<nverts; ++i) {
xyzvertex * hv = hmesh->GetVertex(i);
const float * ov = & vbData[ i * numElements ];
const float * ov = & vbData[ remap[ hv->GetID() ] * numElements ];
// boundary interpolation rules set to "none" produce "undefined" vertices on
// boundary vertices : far does not match hbr for those, so skip comparison.
if ( hmesh->GetInterpolateBoundaryMethod()==xyzmesh::k_InterpolateBoundaryNone and
VertexOnBoundary(hv) )
// boundary interpolation rules set to "none" produce "undefined"
// vertices on boundary vertices : far does not match hbr for those,
// so skip comparison.
if (hbrVertexOnBoundaryPtr and (*hbrVertexOnBoundaryPtr)[i])
continue;
const float *hbrPos = hbrVertexData[i].GetPos();
if ( hv->GetData().GetPos()[0] != ov[0] )
if ( hbrPos[0] != ov[0] )
deltaCnt[0]++;
if ( hv->GetData().GetPos()[1] != ov[1] )
if ( hbrPos[1] != ov[1] )
deltaCnt[1]++;
if ( hv->GetData().GetPos()[2] != ov[2] )
if ( hbrPos[2] != ov[2] )
deltaCnt[2]++;
float delta[3] = { hv->GetData().GetPos()[0] - ov[0],
hv->GetData().GetPos()[1] - ov[1],
hv->GetData().GetPos()[2] - ov[2] };
float delta[3] = { hbrPos[0] - ov[0],
hbrPos[1] - ov[1],
hbrPos[2] - ov[2] };
deltaAvg[0]+=delta[0];
deltaAvg[1]+=delta[1];
@ -259,9 +231,9 @@ checkVertexBuffer( xyzmesh * hmesh, const float * vbData, int numElements, std::
float dist = sqrtf( delta[0]*delta[0]+delta[1]*delta[1]+delta[2]*delta[2]);
if ( dist > PRECISION ) {
printf("// HbrVertex<T> %d fails : dist=%.10f (%.10f %.10f %.10f)"
" (%.10f %.10f %.10f)\n", i, dist, hv->GetData().GetPos()[0],
hv->GetData().GetPos()[1],
hv->GetData().GetPos()[2],
" (%.10f %.10f %.10f)\n", i, dist, hbrPos[0],
hbrPos[1],
hbrPos[2],
ov[0],
ov[1],
ov[2] );
@ -289,77 +261,133 @@ checkVertexBuffer( xyzmesh * hmesh, const float * vbData, int numElements, std::
}
//------------------------------------------------------------------------------
static void
refine( xyzmesh * mesh, int maxlevel ) {
static void
buildStencilTables(
const FarTopologyRefiner &refiner,
Far::StencilTables const **vertexStencils,
Far::StencilTables const **varyingStencils)
{
Far::StencilTablesFactory::Options soptions;
soptions.generateOffsets = true;
soptions.generateIntermediateLevels = true;
for (int l=0; l<maxlevel; ++l ) {
int nfaces = mesh->GetNumFaces();
for (int i=0; i<nfaces; ++i) {
xyzface * f = mesh->GetFace(i);
if (f->GetDepth()==l)
f->Refine();
}
}
*vertexStencils = Far::StencilTablesFactory::Create(refiner, soptions);
soptions.interpolationMode = Far::StencilTablesFactory::INTERPOLATE_VARYING;
*varyingStencils = Far::StencilTablesFactory::Create(refiner, soptions);
}
//------------------------------------------------------------------------------
static int
checkMeshCPU( OpenSubdiv::FarMesh<OpenSubdiv::OsdVertex>* farmesh,
const std::vector<float>& coarseverts,
xyzmesh * refmesh,
const std::vector<int>& remap) {
checkMeshCPU( FarTopologyRefiner *refiner,
const std::vector<xyzVV>& coarseverts,
xyzmesh * refmesh) {
static OpenSubdiv::OsdCpuComputeController *controller = new OpenSubdiv::OsdCpuComputeController();
static Osd::CpuComputeController *controller =
new Osd::CpuComputeController();
Far::StencilTables const *vertexStencils;
Far::StencilTables const *varyingStencils;
buildStencilTables(*refiner, &vertexStencils, &varyingStencils);
Osd::CpuComputeContext *context = Osd::CpuComputeContext::Create(
vertexStencils, varyingStencils);
assert(coarseverts.size() == refiner->GetNumVerticesTotal());
OpenSubdiv::OsdCpuComputeContext *context = OpenSubdiv::OsdCpuComputeContext::Create(farmesh->GetSubdivisionTables(), farmesh->GetVertexEditTables());
Osd::CpuVertexBuffer * vb =
Osd::CpuVertexBuffer::Create(3, refiner->GetNumVerticesTotal());
OpenSubdiv::OsdCpuVertexBuffer * vb = OpenSubdiv::OsdCpuVertexBuffer::Create(3, farmesh->GetNumVertices());
vb->UpdateData( coarseverts[0].GetPos(), 0, (int)coarseverts.size() );
vb->UpdateData( & coarseverts[0], 0, (int)coarseverts.size()/3 );
Far::KernelBatchVector kernelBatches;
kernelBatches.push_back(
Far::StencilTablesFactory::Create(*vertexStencils));
controller->Refine( context, farmesh->GetKernelBatches(), vb );
return checkVertexBuffer(refmesh, vb->BindCpuBuffer(), vb->GetNumElements(), remap);
controller->Compute( context, kernelBatches, vb );
int result = checkVertexBuffer(*refiner, refmesh, vb->BindCpuBuffer(),
vb->GetNumElements());
delete context;
delete vertexStencils;
delete varyingStencils;
delete vb;
return result;
}
//------------------------------------------------------------------------------
static int
checkMeshCPUGL( OpenSubdiv::FarMesh<OpenSubdiv::OsdVertex>* farmesh,
const std::vector<float>& coarseverts,
xyzmesh * refmesh,
const std::vector<int>& remap) {
static OpenSubdiv::OsdCpuComputeController *controller = new OpenSubdiv::OsdCpuComputeController();
checkMeshCPUGL(FarTopologyRefiner *refiner,
const std::vector<xyzVV>& coarseverts,
xyzmesh * refmesh) {
static Osd::CpuComputeController *controller =
new Osd::CpuComputeController();
OpenSubdiv::OsdCpuComputeContext *context = OpenSubdiv::OsdCpuComputeContext::Create(farmesh->GetSubdivisionTables(), farmesh->GetVertexEditTables());
Far::StencilTables const *vertexStencils;
Far::StencilTables const *varyingStencils;
buildStencilTables(*refiner, &vertexStencils, &varyingStencils);
Osd::CpuComputeContext *context = Osd::CpuComputeContext::Create(
vertexStencils, varyingStencils);
OpenSubdiv::OsdCpuGLVertexBuffer * vb = OpenSubdiv::OsdCpuGLVertexBuffer::Create(3, farmesh->GetNumVertices());
Osd::CpuGLVertexBuffer *vb = Osd::CpuGLVertexBuffer::Create(3,
refiner->GetNumVerticesTotal());
vb->UpdateData( & coarseverts[0], 0, (int)coarseverts.size()/3 );
vb->UpdateData( coarseverts[0].GetPos(), 0, (int)coarseverts.size() );
Far::KernelBatchVector kernelBatches;
kernelBatches.push_back(
Far::StencilTablesFactory::Create(*vertexStencils));
controller->Refine( context, farmesh->GetKernelBatches(), vb );
controller->Compute( context, kernelBatches, vb );
return checkVertexBuffer(refmesh, vb->BindCpuBuffer(), vb->GetNumElements(), remap);
int result = checkVertexBuffer(*refiner, refmesh,
vb->BindCpuBuffer(), vb->GetNumElements());
delete context;
delete vertexStencils;
delete varyingStencils;
delete vb;
return result;
}
//------------------------------------------------------------------------------
static int
checkMeshCL( OpenSubdiv::FarMesh<OpenSubdiv::OsdVertex>* farmesh,
const std::vector<float>& coarseverts,
xyzmesh * refmesh,
const std::vector<int>& remap ) {
checkMeshCL( FarTopologyRefiner *refiner,
const std::vector<xyzVV>& coarseverts,
xyzmesh * refmesh) {
#ifdef OPENSUBDIV_HAS_OPENCL
static OpenSubdiv::OsdCLComputeController *controller = new OpenSubdiv::OsdCLComputeController(g_clContext, g_clQueue);
static Osd::CLComputeController *controller =
new Osd::CLComputeController(g_clContext, g_clQueue);
Far::StencilTables const *vertexStencils;
Far::StencilTables const *varyingStencils;
buildStencilTables(*refiner, &vertexStencils, &varyingStencils);
Osd::CLComputeContext *context = Osd::CLComputeContext::Create(g_clContext,
vertexStencils, varyingStencils);
Osd::CLGLVertexBuffer *vb =
Osd::CLGLVertexBuffer::Create(3, refiner->GetNumVerticesTotal(),
g_clContext);
OpenSubdiv::OsdCLComputeContext *context = OpenSubdiv::OsdCLComputeContext::Create(farmesh->GetSubdivisionTables(), farmesh->GetVertexEditTables(), g_clContext);
vb->UpdateData( coarseverts[0].GetPos(), 0, (int)coarseverts.size(),
g_clQueue );
Far::KernelBatchVector kernelBatches;
kernelBatches.push_back(
Far::StencilTablesFactory::Create(*vertexStencils));
OpenSubdiv::OsdCLGLVertexBuffer * vb = OpenSubdiv::OsdCLGLVertexBuffer::Create(3, farmesh->GetNumVertices(), g_clContext);
vb->UpdateData( & coarseverts[0], 0, (int)coarseverts.size()/3, g_clQueue );
controller->Refine( context, farmesh->GetKernelBatches(), vb );
controller->Compute( context, kernelBatches, vb );
// read data back from CL buffer
size_t dataSize = vb->GetNumVertices() * vb->GetNumElements();
@ -367,9 +395,14 @@ checkMeshCL( OpenSubdiv::FarMesh<OpenSubdiv::OsdVertex>* farmesh,
clEnqueueReadBuffer (g_clQueue, vb->BindCLBuffer(g_clQueue), CL_TRUE, 0, dataSize * sizeof(float), data, 0, NULL, NULL);
int result = checkVertexBuffer(refmesh, data, vb->GetNumElements(), remap);
int result = checkVertexBuffer(
*refiner, refmesh, data, vb->GetNumElements());
delete[] data;
delete context;
delete vertexStencils;
delete varyingStencils;
delete vb;
return result;
#else
@ -385,28 +418,29 @@ checkMesh( char const * msg, std::string const & shape, int levels, Scheme schem
printf("- %s (scheme=%d)\n", msg, scheme);
xyzmesh * refmesh = simpleHbr<xyzVV>(shape.c_str(), scheme, 0);
xyzmesh * refmesh =
interpolateHbrVertexData<xyzVV>(shape.c_str(), scheme, levels);
refine( refmesh, levels );
std::vector<xyzVV> vtrVertexData;
std::vector<float> coarseverts;
OsdHbrMesh * hmesh = simpleHbr<OpenSubdiv::OsdVertex>(shape.c_str(), scheme, coarseverts);
OpenSubdiv::FarMeshFactory<OpenSubdiv::OsdVertex> meshFactory(hmesh, levels);
OpenSubdiv::FarMesh<OpenSubdiv::OsdVertex> * farmesh = meshFactory.Create();
std::vector<int> remap = meshFactory.GetRemappingTable();
FarTopologyRefiner *refiner =
InterpolateVtrVertexData(shape.c_str(), scheme, levels,
vtrVertexData);
switch (backend) {
case kBackendCPU : result = checkMeshCPU(farmesh, coarseverts, refmesh, remap); break;
case kBackendCPUGL : result = checkMeshCPUGL(farmesh, coarseverts, refmesh, remap); break;
case kBackendCL : result = checkMeshCL(farmesh, coarseverts, refmesh, remap); break;
case kBackendCPU:
result = checkMeshCPU(refiner, vtrVertexData, refmesh);
break;
case kBackendCPUGL:
result = checkMeshCPUGL(refiner, vtrVertexData, refmesh);
break;
case kBackendCL:
result = checkMeshCL(refiner, vtrVertexData, refmesh);
break;
}
delete hmesh;
delete refmesh;
delete refiner;
return result;
}
@ -449,17 +483,21 @@ int checkBackend(int backend, int levels) {
#define test_catmark_tent
#define test_catmark_tent_creases0
#define test_catmark_tent_creases1
#define test_catmark_square_hedit0
#define test_catmark_square_hedit1
#define test_catmark_square_hedit2
#define test_catmark_square_hedit3
#define test_loop_triangle_edgeonly
#define test_loop_triangle_edgecorner
#define test_loop_icosahedron
#define test_loop_cube
#define test_loop_cube_creases0
#define test_loop_cube_creases1
// Hedits don't yet work.
//#define test_catmark_square_hedit0
//#define test_catmark_square_hedit1
//#define test_catmark_square_hedit2
//#define test_catmark_square_hedit3
// Loop doesn't yet work.
//#define test_loop_triangle_edgeonly
//#define test_loop_triangle_edgecorner
//#define test_loop_icosahedron
//#define test_loop_cube
//#define test_loop_cube_creases0
//#define test_loop_cube_creases1
#define test_bilinear_cube

View File

@ -28,6 +28,7 @@
#include "../../regression/common/hbr_utils.h"
#include "../../regression/common/vtr_utils.h"
#include "../../regression/common/cmp_utils.h"
#include "init_shapes.h"
@ -112,68 +113,11 @@ private:
//------------------------------------------------------------------------------
typedef OpenSubdiv::HbrMesh<xyzVV> Hmesh;
typedef OpenSubdiv::HbrFace<xyzVV> Hface;
typedef OpenSubdiv::HbrVertex<xyzVV> Hvertex;
typedef OpenSubdiv::HbrHalfedge<xyzVV> Hhalfedge;
static Hmesh *
interpolateHbrVertexData(ShapeDesc const & desc, int maxlevel) {
// Hbr interpolation
Hmesh * hmesh = simpleHbr<xyzVV>(desc.data.c_str(), desc.scheme, /*verts vector*/ 0, /*fvar*/ false);
assert(hmesh);
for (int level=0, firstface=0; level<maxlevel; ++level ) {
int nfaces = hmesh->GetNumFaces();
for (int i=firstface; i<nfaces; ++i) {
Hface * f = hmesh->GetFace(i);
assert(f->GetDepth()==level);
if (not f->IsHole()) {
f->Refine();
}
}
// Hbr allocates faces sequentially, skip faces that have already been refined.
firstface = nfaces;
}
return hmesh;
}
//------------------------------------------------------------------------------
typedef OpenSubdiv::Far::TopologyRefiner FarTopologyRefiner;
typedef OpenSubdiv::Far::TopologyRefinerFactory<Shape> FarTopologyRefinerFactory;
static FarTopologyRefiner *
interpolateVtrVertexData(ShapeDesc const & desc, int maxlevel, std::vector<xyzVV> & data) {
// Vtr interpolation
Shape * shape = Shape::parseObj(desc.data.c_str(), desc.scheme);
FarTopologyRefiner * refiner =
FarTopologyRefinerFactory::Create(*shape,
FarTopologyRefinerFactory::Options(GetSdcType(*shape), GetSdcOptions(*shape)));
assert(refiner);
FarTopologyRefiner::UniformOptions options(maxlevel);
options.fullTopologyInLastLevel=true;
refiner->RefineUniform(options);
// populate coarse mesh positions
data.resize(refiner->GetNumVerticesTotal());
for (int i=0; i<refiner->GetNumVertices(0); i++) {
data[i].SetPosition(shape->verts[i*3+0],
shape->verts[i*3+1],
shape->verts[i*3+2]);
}
xyzVV * verts = &data[0];
refiner->Interpolate(verts, verts+refiner->GetNumVertices(0));
delete shape;
return refiner;
}
//------------------------------------------------------------------------------
#ifdef foo
static void
@ -191,129 +135,6 @@ printVertexData(std::vector<xyzVV> const & hbrBuffer, std::vector<xyzVV> const &
}
}
#endif
//------------------------------------------------------------------------------
struct Mapper {
struct LevelMap {
std::vector<Hface *> faces;
std::vector<Hhalfedge *> edges;
std::vector<Hvertex *> verts;
};
std::vector<LevelMap> maps;
Mapper(FarTopologyRefiner * refiner, Hmesh * hmesh) {
assert(refiner and hmesh);
maps.resize(refiner->GetMaxLevel()+1);
typedef OpenSubdiv::Far::Index Index;
typedef OpenSubdiv::Far::ConstIndexArray ConstIndexArray;
{ // Populate base level
// note : topological ordering is identical between Hbr and Vtr for the
// base level
int nfaces = refiner->GetNumFaces(0),
nedges = refiner->GetNumEdges(0),
nverts = refiner->GetNumVertices(0);
maps[0].faces.resize(nfaces, 0);
maps[0].edges.resize(nedges, 0);
maps[0].verts.resize(nverts, 0);
for (int face=0; face<nfaces; ++face) {
maps[0].faces[face] = hmesh->GetFace(face);
}
for (int edge = 0; edge <nedges; ++edge) {
ConstIndexArray vtrVerts = refiner->GetEdgeVertices(0, edge);
Hvertex const * v0 = hmesh->GetVertex(vtrVerts[0]),
* v1 = hmesh->GetVertex(vtrVerts[1]);
Hhalfedge * e = v0->GetEdge(v1);
if (not e) {
e = v1->GetEdge(v0);
}
assert(e);
maps[0].edges[edge] = e;
}
for (int vert = 0; vert<nverts; ++vert) {
maps[0].verts[vert] = hmesh->GetVertex(vert);
}
}
// Populate refined levels
for (int level=1, ecount=0; level<=refiner->GetMaxLevel(); ++level) {
LevelMap & previous = maps[level-1],
& current = maps[level];
current.faces.resize(refiner->GetNumFaces(level), 0);
current.edges.resize(refiner->GetNumEdges(level), 0);
current.verts.resize(refiner->GetNumVertices(level), 0);
for (int face=0; face < refiner->GetNumFaces(level-1); ++face) {
// populate child faces
Hface * f = previous.faces[face];
ConstIndexArray childFaces = refiner->GetFaceChildFaces(level-1, face);
assert(childFaces.size()==f->GetNumVertices());
for (int i=0; i<childFaces.size(); ++i) {
current.faces[childFaces[i]] = f->GetChild(i);
}
// populate child face-verts
Index childVert = refiner->GetFaceChildVertex(level-1, face);
Hvertex * v = f->Subdivide();
assert(v->GetParentFace());
current.verts[childVert] = v;
}
for (int edge=0; edge < refiner->GetNumEdges(level-1); ++edge) {
// populate child edge-verts
Index childVert = refiner->GetEdgeChildVertex(level-1,edge);
Hhalfedge * e = previous.edges[edge];
Hvertex * v = e->Subdivide();
assert(v->GetParentEdge());
current.verts[childVert] = v;
}
for (int vert = 0; vert < refiner->GetNumVertices(level-1); ++vert) {
// populate child vert-verts
Index childVert = refiner->GetVertexChildVertex(level-1, vert);
Hvertex * v = previous.verts[vert]->Subdivide();
current.verts[childVert] = v;
assert(v->GetParentVertex());
}
// populate child edges
for (int edge=0; edge < refiner->GetNumEdges(level); ++edge) {
ConstIndexArray vtrVerts = refiner->GetEdgeVertices(level, edge);
Hvertex const * v0 = current.verts[vtrVerts[0]],
* v1 = current.verts[vtrVerts[1]];
assert(v0 and v1);
Hhalfedge * e= v0->GetEdge(v1);
if (not e) {
e = v1->GetEdge(v0);
}
assert(e);
current.edges[edge] = e;
}
ecount += refiner->GetNumEdges(level-1);
}
}
};
//------------------------------------------------------------------------------
static int
@ -329,32 +150,15 @@ checkMesh(ShapeDesc const & desc, int maxlevel) {
std::vector<xyzVV> hbrVertexData,
vtrVertexData;
Hmesh * hmesh =
interpolateHbrVertexData(desc, maxlevel);
Hmesh * hmesh = interpolateHbrVertexData<xyzVV>(
desc.data.c_str(), desc.scheme, maxlevel);
FarTopologyRefiner * refiner =
interpolateVtrVertexData(desc, maxlevel, vtrVertexData);
InterpolateVtrVertexData<xyzVV>(
desc.data.c_str(), desc.scheme, maxlevel, vtrVertexData);
{ // copy Hbr vertex data into a re-ordered buffer (for easier comparison)
Mapper mapper(refiner, hmesh);
int nverts = hmesh->GetNumVertices();
assert( nverts==refiner->GetNumVerticesTotal() );
hbrVertexData.resize(nverts);
for (int level=0, ofs=0; level<(maxlevel+1); ++level) {
Mapper::LevelMap & map = mapper.maps[level];
for (int i=0; i<(int)map.verts.size(); ++i) {
Hvertex * v = map.verts[i];
hbrVertexData[ofs++] = v->GetData();
}
}
//printVertexData(hbrVertexData, vtrVertexData);
}
// copy Hbr vertex data into a re-ordered buffer (for easier comparison)
GetReorderedHbrVertexData(*refiner, *hmesh, &hbrVertexData);
int nverts = (int)vtrVertexData.size();