mirror of
https://github.com/PixarAnimationStudios/OpenSubdiv
synced 2024-12-25 09:11:18 +00:00
first pass at face-varying interpolation for CpuEvalLimit - still
a couple of kinks to be worked out...
This commit is contained in:
parent
f0be0b5799
commit
c18cf5bff2
@ -139,7 +139,8 @@ std::vector<float> g_coarseEdgeSharpness;
|
||||
std::vector<float> g_coarseVertexSharpness;
|
||||
|
||||
enum DrawMode { kUV=0,
|
||||
kVARYING=1 };
|
||||
kVARYING=1,
|
||||
kFACEVARYING=2 };
|
||||
|
||||
int g_running = 1,
|
||||
g_width = 1024,
|
||||
@ -387,7 +388,9 @@ OsdCpuEvalLimitController g_evalCtrl;
|
||||
|
||||
OsdVertexBufferDescriptor g_idesc( /*offset*/ 0, /*legnth*/ 3, /*stride*/ 3 ),
|
||||
g_odesc( /*offset*/ 0, /*legnth*/ 3, /*stride*/ 6 ),
|
||||
g_vdesc( /*offset*/ 3, /*legnth*/ 3, /*stride*/ 6 );
|
||||
g_vdesc( /*offset*/ 3, /*legnth*/ 3, /*stride*/ 6 ),
|
||||
g_fvidesc( /*offset*/ 0, /*legnth*/ 2, /*stride*/ 2 ),
|
||||
g_fvodesc( /*offset*/ 3, /*legnth*/ 2, /*stride*/ 6 );
|
||||
|
||||
std::vector<OsdEvalCoords> g_coords;
|
||||
|
||||
@ -444,8 +447,14 @@ updateGeom() {
|
||||
// The varying data ends-up interleaved in the same g_Q output buffer because
|
||||
// g_Q has a stride of 6 and g_vdesc sets the offset to 3, while g_odesc sets
|
||||
// the offset to 0
|
||||
if (g_drawMode==kVARYING) {
|
||||
g_evalCtx->BindVaryingBuffers( g_idesc, g_varyingData, g_vdesc, g_Q );
|
||||
switch (g_drawMode) {
|
||||
case kVARYING : g_evalCtx->BindVaryingBuffers( g_idesc, g_varyingData, g_vdesc, g_Q ); break;
|
||||
|
||||
case kFACEVARYING : g_evalCtx->BindFaceVaryingBuffers( g_fvidesc, g_fvodesc, g_Q );
|
||||
|
||||
case kUV :
|
||||
|
||||
default : g_evalCtx->UnbindVaryingBuffers(); break;
|
||||
}
|
||||
|
||||
#define USE_OPENMP
|
||||
@ -457,14 +466,17 @@ updateGeom() {
|
||||
int n = g_evalCtrl.EvalLimitSample<OsdCpuVertexBuffer,OsdCpuGLVertexBuffer>( g_coords[i], g_evalCtx, i );
|
||||
|
||||
if (n) {
|
||||
|
||||
// point colors
|
||||
switch (g_drawMode) {
|
||||
case kUV : { float * color = g_Q->BindCpuBuffer() + i * 6 + 3;
|
||||
color[0] = g_coords[i].u;
|
||||
color[1] = 0.0f;
|
||||
color[2] = g_coords[i].v; } break;
|
||||
case kVARYING :
|
||||
|
||||
case kVARYING : break;
|
||||
|
||||
case kFACEVARYING : { g_Q->BindCpuBuffer()[i*6 + 5] = 0.1f;
|
||||
} break;
|
||||
default : break;
|
||||
}
|
||||
#if defined(OPENSUBDIV_HAS_OPENMP) and defined(USE_OPENMP)
|
||||
@ -488,7 +500,7 @@ static void
|
||||
createOsdMesh( const std::string &shape, int level, Scheme scheme=kCatmark ) {
|
||||
|
||||
// Create HBR mesh
|
||||
OsdHbrMesh * hmesh = simpleHbr<OsdVertex>(shape.c_str(), scheme, g_orgPositions);
|
||||
OsdHbrMesh * hmesh = simpleHbr<OsdVertex>(shape.c_str(), scheme, g_orgPositions, true);
|
||||
|
||||
g_positions.resize(g_orgPositions.size(),0.0f);
|
||||
|
||||
@ -504,7 +516,7 @@ createOsdMesh( const std::string &shape, int level, Scheme scheme=kCatmark ) {
|
||||
OsdFarMeshFactory factory( hmesh, level, /*adaptive*/ true);
|
||||
|
||||
delete g_fmesh;
|
||||
g_fmesh = factory.Create(/*fvar*/ false);
|
||||
g_fmesh = factory.Create(/*fvar*/ true);
|
||||
|
||||
int nverts = g_fmesh->GetNumVertices();
|
||||
|
||||
@ -514,15 +526,11 @@ createOsdMesh( const std::string &shape, int level, Scheme scheme=kCatmark ) {
|
||||
delete g_vertexData;
|
||||
g_vertexData = OsdCpuVertexBuffer::Create(3, nverts);
|
||||
|
||||
// Create v-buffer & populate w/ colors
|
||||
delete g_varyingData;
|
||||
|
||||
// Create primvar v-buffer & populate w/ colors or (u,v) data
|
||||
delete g_varyingData; g_varyingData = 0;
|
||||
if (g_drawMode==kVARYING) {
|
||||
g_varyingData = OsdCpuVertexBuffer::Create(3, nverts);
|
||||
|
||||
g_varyingData->UpdateData( &g_varyingColors[0], 0, nverts);
|
||||
} else {
|
||||
g_varyingData = 0;
|
||||
}
|
||||
|
||||
// Create a Compute context, used to "pose" the vertices
|
||||
@ -535,7 +543,7 @@ createOsdMesh( const std::string &shape, int level, Scheme scheme=kCatmark ) {
|
||||
|
||||
// Create eval context & data buffers
|
||||
delete g_evalCtx;
|
||||
g_evalCtx = OsdCpuEvalLimitContext::Create(g_fmesh);
|
||||
g_evalCtx = OsdCpuEvalLimitContext::Create(g_fmesh, /*requireFVarData*/ true);
|
||||
|
||||
delete g_Q;
|
||||
g_Q = OsdCpuGLVertexBuffer::Create(6,nsamples);
|
||||
@ -780,7 +788,7 @@ drawSamples() {
|
||||
glBindVertexArray(g_samplesVAO);
|
||||
|
||||
glPointSize(1.0f);
|
||||
glDrawArrays( GL_POINTS, 0, (int)g_coords.size() );
|
||||
glDrawArrays( GL_POINTS, 0, g_nsamplesFound);
|
||||
glPointSize(1.0f);
|
||||
|
||||
glBindVertexArray(0);
|
||||
@ -1044,6 +1052,7 @@ initHUD()
|
||||
|
||||
g_hud.AddRadioButton(0, "(u,v)", true, 200, 10, callbackDisplayVaryingColors, kUV, 'k');
|
||||
g_hud.AddRadioButton(0, "varying", false, 200, 30, callbackDisplayVaryingColors, kVARYING, 'k');
|
||||
g_hud.AddRadioButton(0, "face-varying", false, 200, 50, callbackDisplayVaryingColors, kFACEVARYING, 'k');
|
||||
|
||||
for (int i = 1; i < 11; ++i) {
|
||||
char level[16];
|
||||
|
@ -67,7 +67,7 @@ namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
OsdCpuEvalLimitContext *
|
||||
OsdCpuEvalLimitContext::Create(FarMesh<OsdVertex> const * farmesh) {
|
||||
OsdCpuEvalLimitContext::Create(FarMesh<OsdVertex> const * farmesh, bool requireFVarData) {
|
||||
|
||||
assert(farmesh);
|
||||
|
||||
@ -75,7 +75,7 @@ OsdCpuEvalLimitContext::Create(FarMesh<OsdVertex> const * farmesh) {
|
||||
if (not farmesh->GetPatchTables())
|
||||
return NULL;
|
||||
|
||||
return new OsdCpuEvalLimitContext(farmesh);
|
||||
return new OsdCpuEvalLimitContext(farmesh, requireFVarData);
|
||||
}
|
||||
|
||||
void
|
||||
@ -85,7 +85,15 @@ OsdCpuEvalLimitContext::EvalData::Unbind() {
|
||||
_inQ=0;
|
||||
|
||||
_outDesc.Reset();
|
||||
_outQ = _outdQu = _outdQv = 0;
|
||||
_outQ = 0;
|
||||
}
|
||||
|
||||
void
|
||||
OsdCpuEvalLimitContext::EvalVertexData::Unbind() {
|
||||
|
||||
EvalData::Unbind();
|
||||
|
||||
_outdQu = _outdQv = 0;
|
||||
}
|
||||
|
||||
void
|
||||
@ -98,7 +106,12 @@ OsdCpuEvalLimitContext::UnbindVaryingBuffers() {
|
||||
_varyingData.Unbind();
|
||||
}
|
||||
|
||||
OsdCpuEvalLimitContext::OsdCpuEvalLimitContext(FarMesh<OsdVertex> const * farmesh) :
|
||||
void
|
||||
OsdCpuEvalLimitContext::UnbindFaceVaryingBuffers() {
|
||||
_faceVaryingData.Unbind();
|
||||
}
|
||||
|
||||
OsdCpuEvalLimitContext::OsdCpuEvalLimitContext(FarMesh<OsdVertex> const * farmesh, bool requireFVarData) :
|
||||
OsdEvalLimitContext(farmesh) {
|
||||
|
||||
FarPatchTables const * patchTables = farmesh->GetPatchTables();
|
||||
@ -137,6 +150,12 @@ OsdCpuEvalLimitContext::OsdCpuEvalLimitContext(FarMesh<OsdVertex> const * farmes
|
||||
}
|
||||
}
|
||||
|
||||
if (requireFVarData) {
|
||||
_fvarwidth = farmesh->GetTotalFVarWidth();
|
||||
if (_fvarwidth>0) {
|
||||
_fvarData = patchTables->GetFVarDataTable();
|
||||
}
|
||||
}
|
||||
|
||||
_patchMap = new FarPatchTables::PatchMap( *patchTables );
|
||||
}
|
||||
|
@ -71,11 +71,18 @@ namespace OPENSUBDIV_VERSION {
|
||||
|
||||
class OsdCpuEvalLimitContext : public OsdEvalLimitContext {
|
||||
public:
|
||||
|
||||
/// \brief Factory
|
||||
/// Returns an EvalLimitContext from the given farmesh.
|
||||
/// Note : the farmesh is expected to be feature-adaptive and have ptex
|
||||
/// coordinates tables.
|
||||
static OsdCpuEvalLimitContext * Create(FarMesh<OsdVertex> const * farmesh);
|
||||
///
|
||||
/// @param farmesh a pointer to an initialized farmesh
|
||||
///
|
||||
/// @param requireFVarData flag for generating face-varying data
|
||||
///
|
||||
static OsdCpuEvalLimitContext * Create(FarMesh<OsdVertex> const * farmesh,
|
||||
bool requireFVarData=false);
|
||||
|
||||
/// Destructor
|
||||
virtual ~OsdCpuEvalLimitContext();
|
||||
@ -99,12 +106,14 @@ public:
|
||||
return _outQ + index * _outDesc.stride;
|
||||
}
|
||||
|
||||
float const * GetOutputDU(int index=0) const {
|
||||
return _outdQu + index * _outDesc.stride;
|
||||
template <class BUFFER>
|
||||
void BindInputData( BUFFER * inQ ) {
|
||||
_inQ = inQ ? inQ->BindCpuBuffer() : 0;
|
||||
}
|
||||
|
||||
float const * GetOutputDV(int index=0) const {
|
||||
return _outdQv + index * _outDesc.stride;
|
||||
template <class BUFFER>
|
||||
void BindOutputData( BUFFER * outQ ) {
|
||||
_outQ = outQ ? outQ->BindCpuBuffer() : 0;
|
||||
}
|
||||
|
||||
bool IsBound() const {
|
||||
@ -114,46 +123,47 @@ public:
|
||||
private:
|
||||
friend class OsdCpuEvalLimitContext;
|
||||
|
||||
EvalData() : _inQ(0), _outQ(0) { }
|
||||
|
||||
OsdVertexBufferDescriptor _inDesc; // input data
|
||||
float * _inQ;
|
||||
|
||||
OsdVertexBufferDescriptor _outDesc; // output data
|
||||
float * _outQ,
|
||||
* _outdQu, // U derivative of output data
|
||||
* _outdQv; // V derivative of output data
|
||||
|
||||
/// Binds the data buffers.
|
||||
///
|
||||
/// @param inDesc vertex / varying data descriptor shared by all input data buffers
|
||||
///
|
||||
/// @param inQ input subidivision data
|
||||
///
|
||||
/// @param outDesc vertex buffer data descriptor shared by all output data buffers
|
||||
///
|
||||
/// @param outQ output vertex data
|
||||
///
|
||||
/// @param outdQu optional output derivative along "u" of the vertex data
|
||||
///
|
||||
/// @param outdQv optional output derivative along "v" of the vertex data
|
||||
///
|
||||
template<class INPUT_BUFFER, class OUTPUT_BUFFER>
|
||||
void Bind( OsdVertexBufferDescriptor const & inDesc, INPUT_BUFFER *inQ,
|
||||
OsdVertexBufferDescriptor const & outDesc, OUTPUT_BUFFER *outQ,
|
||||
OUTPUT_BUFFER *outdQu=0,
|
||||
OUTPUT_BUFFER *outdQv=0);
|
||||
float * _outQ;
|
||||
|
||||
/// Resets the descriptors & pointers
|
||||
void Unbind();
|
||||
};
|
||||
|
||||
EvalData const & GetVertexData() const {
|
||||
return _vertexData;
|
||||
/// Limit evaluation data descriptor with derivatives
|
||||
class EvalVertexData : public EvalData {
|
||||
public:
|
||||
float const * GetOutputDU(int index=0) const {
|
||||
return _outdQu + index * _outDesc.stride;
|
||||
}
|
||||
|
||||
EvalData const & GetVaryingData() const {
|
||||
return _varyingData;
|
||||
float const * GetOutputDV(int index=0) const {
|
||||
return _outdQv + index * _outDesc.stride;
|
||||
}
|
||||
|
||||
template <class BUFFER>
|
||||
void BindOutputDerivData( BUFFER * outdQu, BUFFER * outdQv ) {
|
||||
_outdQu = outdQu ? outdQu->BindCpuBuffer() : 0;
|
||||
_outdQv = outdQv ? outdQv->BindCpuBuffer() : 0;
|
||||
}
|
||||
|
||||
private:
|
||||
friend class OsdCpuEvalLimitContext;
|
||||
|
||||
EvalVertexData() : _outdQu(0), _outdQv(0) { }
|
||||
|
||||
/// Resets the descriptors & pointers
|
||||
void Unbind();
|
||||
|
||||
float * _outdQu, // U derivative of output data
|
||||
* _outdQv; // V derivative of output data
|
||||
};
|
||||
|
||||
|
||||
/// Binds the vertex-interpolated data buffers.
|
||||
///
|
||||
@ -174,12 +184,24 @@ public:
|
||||
OsdVertexBufferDescriptor const & outDesc, OUTPUT_BUFFER *outQ,
|
||||
OUTPUT_BUFFER *outdQu=0,
|
||||
OUTPUT_BUFFER *outdQv=0) {
|
||||
_vertexData.Bind( inDesc, inQ, outDesc, outQ, outdQu, outdQv );
|
||||
_vertexData._inDesc = inDesc;
|
||||
_vertexData.BindInputData( inQ );
|
||||
_vertexData._outDesc = outDesc;
|
||||
_vertexData.BindOutputData( outQ );
|
||||
_vertexData.BindOutputDerivData( outdQu, outdQv );
|
||||
}
|
||||
|
||||
/// Unbind the vertex data buffers
|
||||
void UnbindVertexBuffers();
|
||||
|
||||
/// Returns an Eval data descriptor of the vertex-interpolated data currently
|
||||
/// bound to this EvalLimitContext.
|
||||
EvalVertexData const & GetVertexData() const {
|
||||
return _vertexData;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// Binds the varying-interpolated data buffers.
|
||||
///
|
||||
/// @param inDesc varying buffer data descriptor shared by all input data buffers
|
||||
@ -190,19 +212,59 @@ public:
|
||||
///
|
||||
/// @param outQ output varying data
|
||||
///
|
||||
/// @param outdQu optional output derivative along "u" of the varying data
|
||||
///
|
||||
/// @param outdQv optional output derivative along "v" of the varying data
|
||||
///
|
||||
template<class VARYING_BUFFER, class OUTPUT_BUFFER>
|
||||
void BindVaryingBuffers( OsdVertexBufferDescriptor const & inDesc, VARYING_BUFFER *inQ,
|
||||
OsdVertexBufferDescriptor const & outDesc, OUTPUT_BUFFER *outQ) {
|
||||
_varyingData.Bind( inDesc, inQ, outDesc, outQ );
|
||||
_varyingData._inDesc = inDesc;
|
||||
_varyingData.BindInputData( inQ );
|
||||
_varyingData._outDesc = outDesc;
|
||||
_varyingData.BindOutputData( outQ );
|
||||
}
|
||||
|
||||
/// Unbind the varying data buffers
|
||||
void UnbindVaryingBuffers();
|
||||
|
||||
/// Returns an Eval data descriptor of the varying-interpolated data currently
|
||||
/// bound to this EvalLimitContext.
|
||||
EvalData const & GetVaryingData() const {
|
||||
return _varyingData;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// Binds the face-varying-interpolated data buffers.
|
||||
///
|
||||
/// Note : currently we only support bilinear boundary interpolation rules
|
||||
/// for face-varying data. Although Hbr supports 3 addition smooth rule sets,
|
||||
/// the feature-adaptive patch interpolation code currently does not support
|
||||
/// them, and neither does this EvalContext
|
||||
///
|
||||
/// @param inDesc varying buffer data descriptor shared by all input data buffers
|
||||
///
|
||||
/// @param inQ input varying data
|
||||
///
|
||||
/// @param outDesc varying buffer data descriptor shared by all output data buffers
|
||||
///
|
||||
/// @param outQ output varying data
|
||||
///
|
||||
template<class OUTPUT_BUFFER>
|
||||
void BindFaceVaryingBuffers( OsdVertexBufferDescriptor const & inDesc,
|
||||
OsdVertexBufferDescriptor const & outDesc, OUTPUT_BUFFER *outQ) {
|
||||
_faceVaryingData._inDesc = inDesc;
|
||||
_faceVaryingData._outDesc = outDesc;
|
||||
_faceVaryingData.BindOutputData( outQ );
|
||||
}
|
||||
|
||||
/// Unbind the varying data buffers
|
||||
void UnbindFaceVaryingBuffers();
|
||||
|
||||
/// Returns an Eval data descriptor of the face-varying-interpolated data
|
||||
/// currently bound to this EvalLimitContext.
|
||||
EvalData const & GetFaceVaryingData() const {
|
||||
return _faceVaryingData;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// Returns the vector of patch arrays
|
||||
const FarPatchTables::PatchArrayVector & GetPatchArrayVector() const {
|
||||
@ -229,6 +291,16 @@ public:
|
||||
return &_quadOffsetBuffer[0];
|
||||
}
|
||||
|
||||
/// Returns the face-varying data patch table
|
||||
FarPatchTables::FVarDataTable const & GetFVarData() const {
|
||||
return _fvarData;
|
||||
}
|
||||
|
||||
/// Returns the number of floats in a datum of the face-varying data table
|
||||
int GetFVarWidth() const {
|
||||
return _fvarwidth;
|
||||
}
|
||||
|
||||
/// Returns a map object that can connect a faceId to a list of children patches
|
||||
const FarPatchTables::PatchMap * GetPatchesMap() const {
|
||||
return _patchMap;
|
||||
@ -240,7 +312,7 @@ public:
|
||||
}
|
||||
|
||||
protected:
|
||||
explicit OsdCpuEvalLimitContext(FarMesh<OsdVertex> const * farmesh);
|
||||
explicit OsdCpuEvalLimitContext(FarMesh<OsdVertex> const * farmesh, bool requireFVarData);
|
||||
|
||||
private:
|
||||
|
||||
@ -252,32 +324,18 @@ private:
|
||||
FarPatchTables::VertexValenceTable _vertexValenceBuffer; // extra Gregory patch data buffers
|
||||
FarPatchTables::QuadOffsetTable _quadOffsetBuffer;
|
||||
|
||||
FarPatchTables::FVarDataTable _fvarData;
|
||||
|
||||
FarPatchTables::PatchMap * _patchMap; // map of the sub-patches given a face index
|
||||
|
||||
EvalData _vertexData,
|
||||
_varyingData;
|
||||
EvalVertexData _vertexData; // vertex-interpolated data descriptor
|
||||
EvalData _varyingData, // varying-interpolated data descriptor
|
||||
_faceVaryingData; // face-varying-interpolated data descriptor
|
||||
|
||||
int _maxValence;
|
||||
int _maxValence,
|
||||
_fvarwidth;
|
||||
};
|
||||
|
||||
template<class INPUT_BUFFER, class OUTPUT_BUFFER> void
|
||||
OsdCpuEvalLimitContext::EvalData::Bind( OsdVertexBufferDescriptor const & inDesc,
|
||||
INPUT_BUFFER *inQ,
|
||||
OsdVertexBufferDescriptor const & outDesc,
|
||||
OUTPUT_BUFFER *outQ,
|
||||
OUTPUT_BUFFER *outdQu,
|
||||
OUTPUT_BUFFER *outdQv) {
|
||||
_inDesc = inDesc;
|
||||
_inQ = inQ ? inQ->BindCpuBuffer() : 0;
|
||||
|
||||
_outDesc = outDesc;
|
||||
_outQ = outQ ? outQ->BindCpuBuffer() : 0 ;
|
||||
_outdQu = outdQu ? outdQu->BindCpuBuffer() : 0 ;
|
||||
_outdQv = outdQv ? outdQv->BindCpuBuffer() : 0 ;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
using namespace OPENSUBDIV_VERSION;
|
||||
|
@ -104,8 +104,7 @@ OsdCpuEvalLimitController::_EvalLimitSample( OpenSubdiv::OsdEvalCoords const & c
|
||||
|
||||
unsigned int const * cvs = &context->GetControlVertices()[ parray.GetVertIndex() + handle.vertexOffset ];
|
||||
|
||||
OsdCpuEvalLimitContext::EvalData const & vertexData = context->GetVertexData(),
|
||||
& varyingData = context->GetVaryingData();
|
||||
OsdCpuEvalLimitContext::EvalVertexData const & vertexData = context->GetVertexData();
|
||||
|
||||
// Position lookup pointers at the indexed vertex
|
||||
float const * inQ = vertexData.GetInputData();
|
||||
@ -167,6 +166,8 @@ OsdCpuEvalLimitController::_EvalLimitSample( OpenSubdiv::OsdEvalCoords const & c
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
|
||||
OsdCpuEvalLimitContext::EvalData const & varyingData = context->GetVaryingData();
|
||||
if (varyingData.IsBound()) {
|
||||
|
||||
static int indices[5][4] = { {5, 6,10, 9}, // regular
|
||||
@ -182,13 +183,37 @@ OsdCpuEvalLimitController::_EvalLimitSample( OpenSubdiv::OsdEvalCoords const & c
|
||||
cvs[indices[type][2]],
|
||||
cvs[indices[type][3]] };
|
||||
|
||||
evalVarying( v, u, zeroRing,
|
||||
evalBilinear( v, u, zeroRing,
|
||||
varyingData.GetInputDesc(),
|
||||
varyingData.GetInputData(),
|
||||
varyingData.GetOutputDesc(),
|
||||
const_cast<float *>(varyingData.GetOutputData(index)) );
|
||||
|
||||
}
|
||||
|
||||
// Note : currently we only support bilinear boundary interpolation rules
|
||||
// for face-varying data. Although Hbr supports 3 addition smooth rule sets,
|
||||
// the feature-adaptive patch interpolation code currently does not support
|
||||
// them, and neither does this EvalContext
|
||||
OsdCpuEvalLimitContext::EvalData const & faceVaryingData = context->GetFaceVaryingData();
|
||||
if (faceVaryingData.GetOutputData()) {
|
||||
|
||||
FarPatchTables::FVarDataTable const & fvarData = context->GetFVarData();
|
||||
|
||||
if (not fvarData.empty()) {
|
||||
|
||||
float const * fvar = &fvarData[ handle.serialIndex * 4 * context->GetFVarWidth() ];
|
||||
|
||||
static unsigned int zeroRing[4] = {0,1,2,3};
|
||||
|
||||
evalBilinear( v, u, zeroRing,
|
||||
faceVaryingData.GetInputDesc(),
|
||||
fvar,
|
||||
faceVaryingData.GetOutputDesc(),
|
||||
const_cast<float *>(faceVaryingData.GetOutputData(index)) );
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -69,7 +69,7 @@ namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
void
|
||||
evalVarying(float u, float v,
|
||||
evalBilinear(float u, float v,
|
||||
unsigned int const * vertexIndices,
|
||||
OsdVertexBufferDescriptor const & inDesc,
|
||||
float const * inQ,
|
||||
|
@ -65,7 +65,7 @@ namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
void
|
||||
evalVarying(float u, float v,
|
||||
evalBilinear(float u, float v,
|
||||
unsigned int const * vertexIndices,
|
||||
OsdVertexBufferDescriptor const & inDesc,
|
||||
float const * inQ,
|
||||
|
@ -703,7 +703,7 @@ hbrToObj( OpenSubdiv::HbrMesh<T> * mesh ) {
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
template <class T> OpenSubdiv::HbrMesh<T> *
|
||||
createMesh( Scheme scheme=kCatmark) {
|
||||
createMesh( Scheme scheme=kCatmark, int fvarwidth=0) {
|
||||
|
||||
OpenSubdiv::HbrMesh<T> * mesh = 0;
|
||||
|
||||
@ -711,10 +711,32 @@ createMesh( Scheme scheme=kCatmark) {
|
||||
static OpenSubdiv::HbrLoopSubdivision<T> _loop;
|
||||
static OpenSubdiv::HbrCatmarkSubdivision<T> _catmark;
|
||||
|
||||
static int indices[1] = { 0 },
|
||||
widths[1] = { 2 };
|
||||
|
||||
int const fvarcount = fvarwidth > 0 ? 1 : 0,
|
||||
* fvarindices = fvarwidth > 0 ? indices : NULL,
|
||||
* fvarwidths = fvarwidth > 0 ? widths : NULL;
|
||||
|
||||
|
||||
switch (scheme) {
|
||||
case kBilinear : mesh = new OpenSubdiv::HbrMesh<T>( &_bilinear ); break;
|
||||
case kLoop : mesh = new OpenSubdiv::HbrMesh<T>( &_loop ); break;
|
||||
case kCatmark : mesh = new OpenSubdiv::HbrMesh<T>( &_catmark ); break;
|
||||
case kBilinear : mesh = new OpenSubdiv::HbrMesh<T>( &_bilinear,
|
||||
fvarcount,
|
||||
fvarindices,
|
||||
fvarwidths,
|
||||
fvarwidth ); break;
|
||||
|
||||
case kLoop : mesh = new OpenSubdiv::HbrMesh<T>( &_loop,
|
||||
fvarcount,
|
||||
fvarindices,
|
||||
fvarwidths,
|
||||
fvarwidth ); break;
|
||||
|
||||
case kCatmark : mesh = new OpenSubdiv::HbrMesh<T>( &_catmark,
|
||||
fvarcount,
|
||||
fvarindices,
|
||||
fvarwidths,
|
||||
fvarwidth ); break;
|
||||
}
|
||||
|
||||
return mesh;
|
||||
@ -840,18 +862,54 @@ createTopology( shape const * sh, OpenSubdiv::HbrMesh<T> * mesh, Scheme scheme)
|
||||
mesh->Finish();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
template <class T> void
|
||||
createFaceVaryingUV( shape const * sh, OpenSubdiv::HbrMesh<T> * mesh) {
|
||||
|
||||
if (sh->uvs.empty() or sh->faceuvs.empty())
|
||||
return;
|
||||
|
||||
for (int i=0, idx=0; i<sh->getNfaces(); ++i ) {
|
||||
|
||||
OpenSubdiv::HbrFace<T> * f = mesh->GetFace(i);
|
||||
|
||||
int nv = sh->nvertsPerFace[i];
|
||||
|
||||
OpenSubdiv::HbrHalfedge<T> * e = f->GetFirstEdge();
|
||||
|
||||
for (int j=0; j<nv; ++j, e=e->GetNext()) {
|
||||
|
||||
OpenSubdiv::HbrFVarData<T> & fvt = e->GetOrgVertex()->GetFVarData(f);
|
||||
|
||||
float const * fvdata = &sh->uvs[ sh->faceuvs[idx++] ];
|
||||
|
||||
if (not fvt.IsInitialized()) {
|
||||
fvt.SetAllData(2, fvdata);
|
||||
} else if (not fvt.CompareAll(2, fvdata)) {
|
||||
OpenSubdiv::HbrFVarData<T> & nfvt = e->GetOrgVertex()->NewFVarData(f);
|
||||
nfvt.SetAllData(2, fvdata);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
template <class T> OpenSubdiv::HbrMesh<T> *
|
||||
simpleHbr(char const * shapestr, Scheme scheme, std::vector<float> * verts=0) {
|
||||
simpleHbr(char const * shapestr, Scheme scheme, std::vector<float> * verts=0, bool fvar=false) {
|
||||
|
||||
shape * sh = shape::parseShape( shapestr );
|
||||
|
||||
OpenSubdiv::HbrMesh<T> * mesh = createMesh<T>(scheme);
|
||||
int fvarwidth = fvar ? 2 : 0;
|
||||
|
||||
OpenSubdiv::HbrMesh<T> * mesh = createMesh<T>(scheme, fvarwidth);
|
||||
|
||||
createVertices<T>(sh, mesh, verts);
|
||||
|
||||
createTopology<T>(sh, mesh, scheme);
|
||||
|
||||
if (fvar)
|
||||
createFaceVaryingUV<T>(sh, mesh);
|
||||
|
||||
if (verts)
|
||||
copyVertexPositions<T>(sh,mesh,*verts);
|
||||
|
||||
@ -862,16 +920,21 @@ simpleHbr(char const * shapestr, Scheme scheme, std::vector<float> * verts=0) {
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
template <class T> OpenSubdiv::HbrMesh<T> *
|
||||
simpleHbr(char const * shapestr, Scheme scheme, std::vector<float> & verts) {
|
||||
simpleHbr(char const * shapestr, Scheme scheme, std::vector<float> & verts, bool fvar=false) {
|
||||
|
||||
shape * sh = shape::parseShape( shapestr );
|
||||
|
||||
OpenSubdiv::HbrMesh<T> * mesh = createMesh<T>(scheme);
|
||||
int fvarwidth = fvar ? 2 : 0;
|
||||
|
||||
OpenSubdiv::HbrMesh<T> * mesh = createMesh<T>(scheme, fvarwidth);
|
||||
|
||||
createVertices<T>(sh, mesh, verts);
|
||||
|
||||
createTopology<T>(sh, mesh, scheme);
|
||||
|
||||
if (fvar)
|
||||
createFaceVaryingUV<T>(sh, mesh);
|
||||
|
||||
copyVertexPositions<T>(sh,mesh,verts);
|
||||
|
||||
delete sh;
|
||||
|
Loading…
Reference in New Issue
Block a user