Removed multi-level interpolation methods of Far::PrimvarRefiner

- removed all of the multi-level Interpolate...() methods taking T*, U*
    - made all single-level methods consistent wrt usage of T&, U&
    - replaced usage in regressions, tutorials and examples
    - additional minor improvements to far/tutorials
This commit is contained in:
barfowl 2015-05-29 22:21:50 -07:00
parent b4d1d09ab9
commit 5b854c8534
10 changed files with 481 additions and 496 deletions

View File

@ -649,7 +649,14 @@ createFarGLMesh(Shape * shape, int maxlevel) {
float const * ptr = &shape->uvs[i*2];
values[i].SetPosition(ptr[0], ptr[1], 0.0f);
}
Far::PrimvarRefiner(*refiner).InterpolateFaceVarying(values, values + nCoarseValues);
int lastLevel = refiner->GetMaxLevel();
Vertex * src = values;
for (int level = 1; level <= lastLevel; ++level) {
Vertex * dst = src + refiner->GetLevel(level-1).GetNumFVarValues(channel);
Far::PrimvarRefiner(*refiner).InterpolateFaceVarying(level, src, dst, channel);
src = dst;
}
}
}
@ -701,7 +708,13 @@ createFarGLMesh(Shape * shape, int maxlevel) {
// TopologyRefiner interpolation
//
// populate buffer with Far interpolated vertex data
Far::PrimvarRefiner(*refiner).Interpolate(verts, verts + ncoarseverts);
int lastLevel = refiner->GetMaxLevel();
Vertex * src = verts;
for (int level = 1; level <= lastLevel; ++level) {
Vertex * dst = src + refiner->GetLevel(level-1).GetNumVertices();
Far::PrimvarRefiner(*refiner).Interpolate(level, src, dst);
src = dst;
}
//printf(" %f ms (interpolate)\n", float(s.GetElapsed())*1000.0f);
//printf(" %f ms (total)\n", float(s.GetTotalElapsed())*1000.0f);

View File

@ -659,7 +659,13 @@ MayaPolySmooth::compute( const MPlug& plug, MDataBlock& data ) {
std::vector<Vertex> refinedVerts(
refiner->GetNumVerticesTotal() - refiner->GetLevel(0).GetNumVertices());
OpenSubdiv::Far::PrimvarRefiner(*refiner).Interpolate(controlVerts, &refinedVerts.at(0));
Vertex * srcVerts = controlVerts;
Vertex * dstVerts = &refinedVerts[0];
for (int level = 1; level <= subdivisionLevel; ++level) {
OpenSubdiv::Far::PrimvarRefiner(*refiner).Interpolate(level, srcVerts, dstVerts);
srcVerts = dstVerts;
dstVerts += refiner->GetLevel(level).GetNumVertices();
}
// == Convert subdivided OpenSubdiv mesh to MFnMesh Data outputMesh =============

View File

@ -98,22 +98,11 @@ public:
/// Far tutorials</a> for code examples.
///
/// \brief Apply vertex interpolation weights to a primvar buffer
///
/// The destination buffer must allocate an array of data for all the refined
/// vertices (at least GetNumVerticesTotal()-GetLevel(0).GetNumVertices())
///
/// @param src Source primvar buffer (\ref templating control vertex data)
///
/// @param dst Destination primvar buffer (\ref templating refined vertex data)
///
template <class T, class U> void Interpolate(T const * src, U * dst) const;
/// \brief Apply vertex interpolation weights to a primvar buffer for a single
/// level level of refinement.
///
/// The destination buffer must allocate an array of data for all the
/// refined vertices (at least GetLevel(level).GetNumVertices())
/// refined vertices, i.e. at least refiner.GetLevel(level).GetNumVertices()
///
/// @param level The refinement level
///
@ -123,21 +112,6 @@ public:
///
template <class T, class U> void Interpolate(int level, T const & src, U & dst) const;
/// \brief Apply varying interpolation weights to a primvar buffer
///
/// This method is useful if the varying primvar data does not need to be
/// re-computed over time.
///
/// The destination buffer must allocate an array of data for all the refined
/// vertices (at least GetNumVerticesTotal()-GetLevel(0).GetNumVertices())
///
/// @param src Source primvar buffer (\ref templating control vertex data)
///
/// @param dst Destination primvar buffer (\ref templating refined vertex data)
///
template <class T, class U> void InterpolateVarying(T const * src, U * dst) const;
/// \brief Apply only varying interpolation weights to a primvar buffer
/// for a single level level of refinement.
///
@ -145,7 +119,7 @@ public:
/// re-computed over time.
///
/// The destination buffer must allocate an array of data for all the
/// refined vertices (at least GetLevel(level).GetNumVertices())
/// refined vertices, i.e. at least refiner.GetLevel(level).GetNumVertices()
///
/// @param level The refinement level
///
@ -155,43 +129,56 @@ public:
///
template <class T, class U> void InterpolateVarying(int level, T const & src, U & dst) const;
/// \brief Apply uniform (per-face) primvar data between levels.
/// \brief Refine uniform (per-face) primvar data between levels.
///
/// Data is simply copied from a parent face to its child faces and does not involve
/// any weighting. Setting the source primvar data for the base level to be the index
/// of each face allows the propagation of the base face to primvar data for child
/// faces in all levels.
///
template <class T, class U> void InterpolateFaceUniform(T const * src, U * dst) const;
/// The destination buffer must allocate an array of data for all the refined faces,
/// i.e. at least refiner.GetLevel(level).GetNumFaces()
///
/// @param level The refinement level
///
/// @param src Source primvar buffer
///
/// @param dst Destination primvar buffer
///
template <class T, class U> void InterpolateFaceUniform(int level, T const & src, U & dst) const;
/// \brief Apply face-varying interpolation weights to a primvar buffer
// associated with a particular face-varying channel
/// associated with a particular face-varying channel.
///
/// Unlike vertex and varying primvar buffers, there is not a 1-to-1 correspondence
/// between vertices and face-varying values -- typically there are more face-varying
/// values than vertices. Each face-varying channel is also independent in how its
/// values relate to the vertices.
///
/// The destination buffer must allocate an array of data for all the refined values,
/// i.e. at least refiner.GetLevel(level).GetNumFVarValues(channel).
///
template <class T, class U> void InterpolateFaceVarying(T const * src, U * dst, int channel = 0) const;
template <class T, class U> void InterpolateFaceVarying(int level, T const & src, U & dst, int channel = 0) const;
template <class T, class U> void LimitFaceVarying(T const & src, U * dst, int channel = 0) const;
/// \brief Apply vertex interpolation limit weights to a primvar buffer
/// \brief Apply limit weights to a primvar buffer
///
/// The source buffer must refer to an array of previously interpolated
/// vertex data for the last refinement level. The destination buffer
/// must allocate an array for all vertices at the last refinement level
/// (at least GetLevel(GetMaxLevel()).GetNumVertices())
/// must allocate an array for all vertices at the last refinement level,
/// i.e. at least refiner.GetLevel(refiner.GetMaxLevel()).GetNumVertices()
///
/// @param src Source primvar buffer (refined vertex data) for last level
/// @param src Source primvar buffer (refined data) for last level
///
/// @param dst Destination primvar buffer (vertex data at the limit)
/// @param dst Destination primvar buffer (data at the limit)
///
template <class T, class U> void Limit(T const & src, U & dstPos) const;
template <class T, class U, class U1, class U2>
void Limit(T const & src, U & dstPos, U1 & dstTan1, U2 & dstTan2) const;
template <class T, class U> void LimitFaceVarying(T const & src, U & dst, int channel = 0) const;
//@}
private:
@ -200,21 +187,19 @@ private:
PrimvarRefiner(PrimvarRefiner const & src) : _refiner(src._refiner) { }
PrimvarRefiner & operator=(PrimvarRefiner const &) { return *this; }
template <Sdc::SchemeType SCHEME, class T, class U> void interpolateChildVertsFromFaces(Vtr::internal::Refinement const &, T const & src, U & dst) const;
template <Sdc::SchemeType SCHEME, class T, class U> void interpolateChildVertsFromEdges(Vtr::internal::Refinement const &, T const & src, U & dst) const;
template <Sdc::SchemeType SCHEME, class T, class U> void interpolateChildVertsFromVerts(Vtr::internal::Refinement const &, T const & src, U & dst) const;
template <Sdc::SchemeType SCHEME, class T, class U> void interpFromFaces(int, T const &, U &) const;
template <Sdc::SchemeType SCHEME, class T, class U> void interpFromEdges(int, T const &, U &) const;
template <Sdc::SchemeType SCHEME, class T, class U> void interpFromVerts(int, T const &, U &) const;
template <class T, class U> void varyingInterpolateChildVertsFromFaces(Vtr::internal::Refinement const &, T const & src, U & dst) const;
template <class T, class U> void varyingInterpolateChildVertsFromEdges(Vtr::internal::Refinement const &, T const & src, U & dst) const;
template <class T, class U> void varyingInterpolateChildVertsFromVerts(Vtr::internal::Refinement const &, T const & src, U & dst) const;
template <Sdc::SchemeType SCHEME, class T, class U> void interpFVarFromFaces(int, T const &, U &, int) const;
template <Sdc::SchemeType SCHEME, class T, class U> void interpFVarFromEdges(int, T const &, U &, int) const;
template <Sdc::SchemeType SCHEME, class T, class U> void interpFVarFromVerts(int, T const &, U &, int) const;
template <Sdc::SchemeType SCHEME, class T, class U> void faceVaryingInterpolateChildVertsFromFaces(Vtr::internal::Refinement const &, T const & src, U & dst, int channel) const;
template <Sdc::SchemeType SCHEME, class T, class U> void faceVaryingInterpolateChildVertsFromEdges(Vtr::internal::Refinement const &, T const & src, U & dst, int channel) const;
template <Sdc::SchemeType SCHEME, class T, class U> void faceVaryingInterpolateChildVertsFromVerts(Vtr::internal::Refinement const &, T const & src, U & dst, int channel) const;
template <Sdc::SchemeType SCHEME, class T, class U, class U1, class U2>
void limit(T const & src, U & pos, U1 * tan1, U2 * tan2) const;
template <Sdc::SchemeType SCHEME, class T, class U, class U1, class U2> void limit(T const & src, U & pos, U1 * tan1, U2 * tan2) const;
template <Sdc::SchemeType SCHEME, class T, class U> void faceVaryingLimit(T const & src, U * dst, int channel) const;
template <Sdc::SchemeType SCHEME, class T, class U>
void limitFVar(T const & src, U * dst, int channel) const;
private:
@ -266,58 +251,220 @@ private:
};
template <class T, class U>
inline void
PrimvarRefiner::Interpolate(T const * src, U * dst) const {
for (int level = 1; level <= _refiner.GetMaxLevel(); ++level) {
Interpolate(level, src, dst);
src = dst;
dst += _refiner.GetLevel(level).GetNumVertices();
}
}
//
// Public entry points to the methods. Queries of the scheme type and its
// use as a template parameter in subsequent implementation will be factored
// out of a later release:
//
template <class T, class U>
inline void
PrimvarRefiner::Interpolate(int level, T const & src, U & dst) const {
assert(level>0 and level<=(int)_refiner._refinements.size());
Vtr::internal::Refinement const & refinement = _refiner.getRefinement(level-1);
switch (_refiner._subdivType) {
case Sdc::SCHEME_CATMARK:
interpolateChildVertsFromFaces<Sdc::SCHEME_CATMARK>(refinement, src, dst);
interpolateChildVertsFromEdges<Sdc::SCHEME_CATMARK>(refinement, src, dst);
interpolateChildVertsFromVerts<Sdc::SCHEME_CATMARK>(refinement, src, dst);
interpFromFaces<Sdc::SCHEME_CATMARK>(level, src, dst);
interpFromEdges<Sdc::SCHEME_CATMARK>(level, src, dst);
interpFromVerts<Sdc::SCHEME_CATMARK>(level, src, dst);
break;
case Sdc::SCHEME_LOOP:
interpolateChildVertsFromFaces<Sdc::SCHEME_LOOP>(refinement, src, dst);
interpolateChildVertsFromEdges<Sdc::SCHEME_LOOP>(refinement, src, dst);
interpolateChildVertsFromVerts<Sdc::SCHEME_LOOP>(refinement, src, dst);
interpFromFaces<Sdc::SCHEME_LOOP>(level, src, dst);
interpFromEdges<Sdc::SCHEME_LOOP>(level, src, dst);
interpFromVerts<Sdc::SCHEME_LOOP>(level, src, dst);
break;
case Sdc::SCHEME_BILINEAR:
interpolateChildVertsFromFaces<Sdc::SCHEME_BILINEAR>(refinement, src, dst);
interpolateChildVertsFromEdges<Sdc::SCHEME_BILINEAR>(refinement, src, dst);
interpolateChildVertsFromVerts<Sdc::SCHEME_BILINEAR>(refinement, src, dst);
interpFromFaces<Sdc::SCHEME_BILINEAR>(level, src, dst);
interpFromEdges<Sdc::SCHEME_BILINEAR>(level, src, dst);
interpFromVerts<Sdc::SCHEME_BILINEAR>(level, src, dst);
break;
}
}
template <class T, class U>
inline void
PrimvarRefiner::InterpolateFaceVarying(int level, T const & src, U & dst, int channel) const {
assert(level>0 and level<=(int)_refiner._refinements.size());
switch (_refiner._subdivType) {
case Sdc::SCHEME_CATMARK:
interpFVarFromFaces<Sdc::SCHEME_CATMARK>(level, src, dst, channel);
interpFVarFromEdges<Sdc::SCHEME_CATMARK>(level, src, dst, channel);
interpFVarFromVerts<Sdc::SCHEME_CATMARK>(level, src, dst, channel);
break;
case Sdc::SCHEME_LOOP:
interpFVarFromFaces<Sdc::SCHEME_LOOP>(level, src, dst, channel);
interpFVarFromEdges<Sdc::SCHEME_LOOP>(level, src, dst, channel);
interpFVarFromVerts<Sdc::SCHEME_LOOP>(level, src, dst, channel);
break;
case Sdc::SCHEME_BILINEAR:
interpFVarFromFaces<Sdc::SCHEME_BILINEAR>(level, src, dst, channel);
interpFVarFromEdges<Sdc::SCHEME_BILINEAR>(level, src, dst, channel);
interpFVarFromVerts<Sdc::SCHEME_BILINEAR>(level, src, dst, channel);
break;
}
}
template <class T, class U>
inline void
PrimvarRefiner::Limit(T const & src, U & dst) const {
if (_refiner.getLevel(_refiner.GetMaxLevel()).getNumVertexEdgesTotal() == 0) {
Error(FAR_RUNTIME_ERROR,
"Cannot compute limit points -- last level of refinement does not include full topology.");
return;
}
switch (_refiner._subdivType) {
case Sdc::SCHEME_CATMARK:
limit<Sdc::SCHEME_CATMARK>(src, dst, (U*)0, (U*)0);
break;
case Sdc::SCHEME_LOOP:
limit<Sdc::SCHEME_LOOP>(src, dst, (U*)0, (U*)0);
break;
case Sdc::SCHEME_BILINEAR:
limit<Sdc::SCHEME_BILINEAR>(src, dst, (U*)0, (U*)0);
break;
}
}
template <class T, class U, class U1, class U2>
inline void
PrimvarRefiner::Limit(T const & src, U & dstPos, U1 & dstTan1, U2 & dstTan2) const {
if (_refiner.getLevel(_refiner.GetMaxLevel()).getNumVertexEdgesTotal() == 0) {
Error(FAR_RUNTIME_ERROR,
"Cannot compute limit points -- last level of refinement does not include full topology.");
return;
}
switch (_refiner._subdivType) {
case Sdc::SCHEME_CATMARK:
limit<Sdc::SCHEME_CATMARK>(src, dstPos, &dstTan1, &dstTan2);
break;
case Sdc::SCHEME_LOOP:
limit<Sdc::SCHEME_LOOP>(src, dstPos, &dstTan1, &dstTan2);
break;
case Sdc::SCHEME_BILINEAR:
limit<Sdc::SCHEME_BILINEAR>(src, dstPos, &dstTan1, &dstTan2);
break;
}
}
template <class T, class U>
inline void
PrimvarRefiner::LimitFaceVarying(T const & src, U & dst, int channel) const {
if (_refiner.getLevel(_refiner.GetMaxLevel()).getNumVertexEdgesTotal() == 0) {
Error(FAR_RUNTIME_ERROR,
"Cannot compute limit points -- last level of refinement does not include full topology.");
return;
}
switch (_refiner._subdivType) {
case Sdc::SCHEME_CATMARK:
limitFVar<Sdc::SCHEME_CATMARK>(src, dst, channel);
break;
case Sdc::SCHEME_LOOP:
limitFVar<Sdc::SCHEME_LOOP>(src, dst, channel);
break;
case Sdc::SCHEME_BILINEAR:
limitFVar<Sdc::SCHEME_BILINEAR>(src, dst, channel);
break;
}
}
template <class T, class U>
inline void
PrimvarRefiner::InterpolateFaceUniform(int level, T const & src, U & dst) const {
assert(level>0 and level<=(int)_refiner._refinements.size());
Vtr::internal::Refinement const & refinement = _refiner.getRefinement(level-1);
Vtr::internal::Level const & child = refinement.child();
for (int cFace = 0; cFace < child.getNumFaces(); ++cFace) {
Vtr::Index pFace = refinement.getChildFaceParentFace(cFace);
dst[cFace] = src[pFace];
}
}
template <class T, class U>
inline void
PrimvarRefiner::InterpolateVarying(int level, T const & src, U & dst) const {
assert(level>0 and level<=(int)_refiner._refinements.size());
Vtr::internal::Refinement const & refinement = _refiner.getRefinement(level-1);
Vtr::internal::Level const & parent = refinement.parent();
//
// Group values to interolate based on origin -- note that there may
// be none originating from faces:
//
if (refinement.getNumChildVerticesFromFaces() > 0) {
for (int face = 0; face < parent.getNumFaces(); ++face) {
Vtr::Index cVert = refinement.getFaceChildVertex(face);
if (Vtr::IndexIsValid(cVert)) {
// Apply the weights to the parent face's vertices:
ConstIndexArray fVerts = parent.getFaceVertices(face);
float fVaryingWeight = 1.0f / (float) fVerts.size();
dst[cVert].Clear();
for (int i = 0; i < fVerts.size(); ++i) {
dst[cVert].AddWithWeight(src[fVerts[i]], fVaryingWeight);
}
}
}
}
for (int edge = 0; edge < parent.getNumEdges(); ++edge) {
Vtr::Index cVert = refinement.getEdgeChildVertex(edge);
if (Vtr::IndexIsValid(cVert)) {
// Apply the weights to the parent edges's vertices
ConstIndexArray eVerts = parent.getEdgeVertices(edge);
dst[cVert].Clear();
dst[cVert].AddWithWeight(src[eVerts[0]], 0.5f);
dst[cVert].AddWithWeight(src[eVerts[1]], 0.5f);
}
}
for (int vert = 0; vert < parent.getNumVertices(); ++vert) {
Vtr::Index cVert = refinement.getVertexChildVertex(vert);
if (Vtr::IndexIsValid(cVert)) {
// Essentially copy the parent vertex:
dst[cVert].Clear();
dst[cVert].AddWithWeight(src[vert], 1.0f);
}
}
}
//
// Internal implementation methods -- grouping vertices to be interpolated
// based on the type of parent component from which they originated:
//
template <Sdc::SchemeType SCHEME, class T, class U>
inline void
PrimvarRefiner::interpolateChildVertsFromFaces(
Vtr::internal::Refinement const & refinement, T const & src, U & dst) const {
PrimvarRefiner::interpFromFaces(int level, T const & src, U & dst) const {
Vtr::internal::Refinement const & refinement = _refiner.getRefinement(level-1);
Vtr::internal::Level const & parent = refinement.parent();
if (refinement.getNumChildVerticesFromFaces() == 0) return;
Sdc::Scheme<SCHEME> scheme(_refiner._subdivOptions);
const Vtr::internal::Level& parent = refinement.parent();
Vtr::internal::StackBuffer<float,16> fVertWeights(parent.getMaxValence());
for (int face = 0; face < parent.getNumFaces(); ++face) {
@ -346,14 +493,14 @@ PrimvarRefiner::interpolateChildVertsFromFaces(
template <Sdc::SchemeType SCHEME, class T, class U>
inline void
PrimvarRefiner::interpolateChildVertsFromEdges(
Vtr::internal::Refinement const & refinement, T const & src, U & dst) const {
PrimvarRefiner::interpFromEdges(int level, T const & src, U & dst) const {
Vtr::internal::Refinement const & refinement = _refiner.getRefinement(level-1);
Vtr::internal::Level const & parent = refinement.parent();
Vtr::internal::Level const & child = refinement.child();
Sdc::Scheme<SCHEME> scheme(_refiner._subdivOptions);
const Vtr::internal::Level& parent = refinement.parent();
const Vtr::internal::Level& child = refinement.child();
Vtr::internal::EdgeInterface eHood(parent);
float eVertWeights[2];
@ -415,14 +562,14 @@ PrimvarRefiner::interpolateChildVertsFromEdges(
template <Sdc::SchemeType SCHEME, class T, class U>
inline void
PrimvarRefiner::interpolateChildVertsFromVerts(
Vtr::internal::Refinement const & refinement, T const & src, U & dst) const {
PrimvarRefiner::interpFromVerts(int level, T const & src, U & dst) const {
Vtr::internal::Refinement const & refinement = _refiner.getRefinement(level-1);
Vtr::internal::Level const & parent = refinement.parent();
Vtr::internal::Level const & child = refinement.child();
Sdc::Scheme<SCHEME> scheme(_refiner._subdivOptions);
const Vtr::internal::Level& parent = refinement.parent();
const Vtr::internal::Level& child = refinement.child();
Vtr::internal::VertexInterface vHood(parent, child);
Vtr::internal::StackBuffer<float,32> weightBuffer(2*parent.getMaxValence());
@ -482,199 +629,25 @@ PrimvarRefiner::interpolateChildVertsFromVerts(
}
}
//
// Face-uniform "interpolation":
//
template <class T, class U>
inline void
PrimvarRefiner::InterpolateFaceUniform(T const * src, U * dst) const {
for (int level = 1; level <= _refiner.GetMaxLevel(); ++level) {
InterpolateFaceUniform(level, src, dst);
src = dst;
dst += _refiner.GetLevel(level).GetNumFaces();
}
}
template <class T, class U>
inline void
PrimvarRefiner::InterpolateFaceUniform(int level, T const & src, U & dst) const {
assert(level>0 and level<=(int)_refiner._refinements.size());
Vtr::internal::Refinement const & refinement = _refiner.getRefinement(level-1);
Vtr::internal::Level const & child = refinement.child();
for (int cFace = 0; cFace < child.getNumFaces(); ++cFace) {
Vtr::Index pFace = refinement.getChildFaceParentFace(cFace);
dst[cFace] = src[pFace];
}
}
//
// Varying only interpolation
// Internal face-varying implementation details:
//
template <class T, class U>
inline void
PrimvarRefiner::InterpolateVarying(T const * src, U * dst) const {
for (int level = 1; level <= _refiner.GetMaxLevel(); ++level) {
InterpolateVarying(level, src, dst);
src = dst;
dst += _refiner.GetLevel(level).GetNumVertices();
}
}
template <class T, class U>
inline void
PrimvarRefiner::InterpolateVarying(int level, T const & src, U & dst) const {
assert(level>0 and level<=(int)_refiner._refinements.size());
Vtr::internal::Refinement const & refinement = _refiner.getRefinement(level-1);
varyingInterpolateChildVertsFromFaces(refinement, src, dst);
varyingInterpolateChildVertsFromEdges(refinement, src, dst);
varyingInterpolateChildVertsFromVerts(refinement, src, dst);
}
template <class T, class U>
inline void
PrimvarRefiner::varyingInterpolateChildVertsFromFaces(
Vtr::internal::Refinement const & refinement, T const & src, U & dst) const {
if (refinement.getNumChildVerticesFromFaces() == 0) return;
const Vtr::internal::Level& parent = refinement.parent();
for (int face = 0; face < parent.getNumFaces(); ++face) {
Vtr::Index cVert = refinement.getFaceChildVertex(face);
if (!Vtr::IndexIsValid(cVert))
continue;
ConstIndexArray fVerts = parent.getFaceVertices(face);
float fVaryingWeight = 1.0f / (float) fVerts.size();
// Apply the weights to the parent face's vertices:
dst[cVert].Clear();
for (int i = 0; i < fVerts.size(); ++i) {
dst[cVert].AddWithWeight(src[fVerts[i]], fVaryingWeight);
}
}
}
template <class T, class U>
inline void
PrimvarRefiner::varyingInterpolateChildVertsFromEdges(
Vtr::internal::Refinement const & refinement, T const & src, U & dst) const {
const Vtr::internal::Level& parent = refinement.parent();
for (int edge = 0; edge < parent.getNumEdges(); ++edge) {
Vtr::Index cVert = refinement.getEdgeChildVertex(edge);
if (!Vtr::IndexIsValid(cVert))
continue;
// Declare and compute mask weights for this vertex relative to its parent edge:
ConstIndexArray eVerts = parent.getEdgeVertices(edge);
// Apply the weights to the parent edges's vertices
dst[cVert].Clear();
dst[cVert].AddWithWeight(src[eVerts[0]], 0.5f);
dst[cVert].AddWithWeight(src[eVerts[1]], 0.5f);
}
}
template <class T, class U>
inline void
PrimvarRefiner::varyingInterpolateChildVertsFromVerts(
Vtr::internal::Refinement const & refinement, T const & src, U & dst) const {
const Vtr::internal::Level& parent = refinement.parent();
for (int vert = 0; vert < parent.getNumVertices(); ++vert) {
Vtr::Index cVert = refinement.getVertexChildVertex(vert);
if (!Vtr::IndexIsValid(cVert))
continue;
// Apply the weights to the parent vertex
dst[cVert].Clear();
dst[cVert].AddWithWeight(src[vert], 1.0f);
}
}
//
// Face-varying only interpolation
//
template <class T, class U>
inline void
PrimvarRefiner::InterpolateFaceVarying(T const * src, U * dst, int channel) const {
for (int level = 1; level <= _refiner.GetMaxLevel(); ++level) {
InterpolateFaceVarying(level, src, dst, channel);
src = dst;
dst += _refiner.getLevel(level).getNumFVarValues();
}
}
template <class T, class U>
inline void
PrimvarRefiner::InterpolateFaceVarying(int level, T const & src, U & dst, int channel) const {
assert(level>0 and level<=(int)_refiner._refinements.size());
Vtr::internal::Refinement const & refinement = _refiner.getRefinement(level-1);
switch (_refiner._subdivType) {
case Sdc::SCHEME_CATMARK:
faceVaryingInterpolateChildVertsFromFaces<Sdc::SCHEME_CATMARK>(refinement, src, dst, channel);
faceVaryingInterpolateChildVertsFromEdges<Sdc::SCHEME_CATMARK>(refinement, src, dst, channel);
faceVaryingInterpolateChildVertsFromVerts<Sdc::SCHEME_CATMARK>(refinement, src, dst, channel);
break;
case Sdc::SCHEME_LOOP:
faceVaryingInterpolateChildVertsFromFaces<Sdc::SCHEME_LOOP>(refinement, src, dst, channel);
faceVaryingInterpolateChildVertsFromEdges<Sdc::SCHEME_LOOP>(refinement, src, dst, channel);
faceVaryingInterpolateChildVertsFromVerts<Sdc::SCHEME_LOOP>(refinement, src, dst, channel);
break;
case Sdc::SCHEME_BILINEAR:
faceVaryingInterpolateChildVertsFromFaces<Sdc::SCHEME_BILINEAR>(refinement, src, dst, channel);
faceVaryingInterpolateChildVertsFromEdges<Sdc::SCHEME_BILINEAR>(refinement, src, dst, channel);
faceVaryingInterpolateChildVertsFromVerts<Sdc::SCHEME_BILINEAR>(refinement, src, dst, channel);
break;
}
}
template <Sdc::SchemeType SCHEME, class T, class U>
inline void
PrimvarRefiner::faceVaryingInterpolateChildVertsFromFaces(
Vtr::internal::Refinement const & refinement, T const & src, U & dst, int channel) const {
PrimvarRefiner::interpFVarFromFaces(int level, T const & src, U & dst, int channel) const {
Vtr::internal::Refinement const & refinement = _refiner.getRefinement(level-1);
if (refinement.getNumChildVerticesFromFaces() == 0) return;
Sdc::Scheme<SCHEME> scheme(_refiner._subdivOptions);
const Vtr::internal::Level& parentLevel = refinement.parent();
const Vtr::internal::Level& childLevel = refinement.child();
Vtr::internal::Level const & parentLevel = refinement.parent();
Vtr::internal::Level const & childLevel = refinement.child();
const Vtr::internal::FVarLevel& parentFVar = *parentLevel._fvarChannels[channel];
const Vtr::internal::FVarLevel& childFVar = *childLevel._fvarChannels[channel];
Vtr::internal::FVarLevel const & parentFVar = *parentLevel._fvarChannels[channel];
Vtr::internal::FVarLevel const & childFVar = *childLevel._fvarChannels[channel];
Vtr::internal::StackBuffer<float,16> fValueWeights(parentLevel.getMaxValence());
@ -710,17 +683,18 @@ PrimvarRefiner::faceVaryingInterpolateChildVertsFromFaces(
template <Sdc::SchemeType SCHEME, class T, class U>
inline void
PrimvarRefiner::faceVaryingInterpolateChildVertsFromEdges(
Vtr::internal::Refinement const & refinement, T const & src, U & dst, int channel) const {
PrimvarRefiner::interpFVarFromEdges(int level, T const & src, U & dst, int channel) const {
Vtr::internal::Refinement const & refinement = _refiner.getRefinement(level-1);
Sdc::Scheme<SCHEME> scheme(_refiner._subdivOptions);
const Vtr::internal::Level& parentLevel = refinement.parent();
const Vtr::internal::Level& childLevel = refinement.child();
Vtr::internal::Level const & parentLevel = refinement.parent();
Vtr::internal::Level const & childLevel = refinement.child();
const Vtr::internal::FVarRefinement& refineFVar = *refinement._fvarChannels[channel];
const Vtr::internal::FVarLevel& parentFVar = *parentLevel._fvarChannels[channel];
const Vtr::internal::FVarLevel& childFVar = *childLevel._fvarChannels[channel];
Vtr::internal::FVarRefinement const & refineFVar = *refinement._fvarChannels[channel];
Vtr::internal::FVarLevel const & parentFVar = *parentLevel._fvarChannels[channel];
Vtr::internal::FVarLevel const & childFVar = *childLevel._fvarChannels[channel];
//
// Allocate and intialize (if linearly interpolated) interpolation weights for
@ -853,17 +827,18 @@ PrimvarRefiner::faceVaryingInterpolateChildVertsFromEdges(
template <Sdc::SchemeType SCHEME, class T, class U>
inline void
PrimvarRefiner::faceVaryingInterpolateChildVertsFromVerts(
Vtr::internal::Refinement const & refinement, T const & src, U & dst, int channel) const {
PrimvarRefiner::interpFVarFromVerts(int level, T const & src, U & dst, int channel) const {
Vtr::internal::Refinement const & refinement = _refiner.getRefinement(level-1);
Sdc::Scheme<SCHEME> scheme(_refiner._subdivOptions);
const Vtr::internal::Level& parentLevel = refinement.parent();
const Vtr::internal::Level& childLevel = refinement.child();
Vtr::internal::Level const & parentLevel = refinement.parent();
Vtr::internal::Level const & childLevel = refinement.child();
const Vtr::internal::FVarRefinement& refineFVar = *refinement._fvarChannels[channel];
const Vtr::internal::FVarLevel& parentFVar = *parentLevel._fvarChannels[channel];
const Vtr::internal::FVarLevel& childFVar = *childLevel._fvarChannels[channel];
Vtr::internal::FVarRefinement const & refineFVar = *refinement._fvarChannels[channel];
Vtr::internal::FVarLevel const & parentFVar = *parentLevel._fvarChannels[channel];
Vtr::internal::FVarLevel const & childFVar = *childLevel._fvarChannels[channel];
bool isLinearFVar = parentFVar._isLinear;
@ -1017,52 +992,6 @@ PrimvarRefiner::faceVaryingInterpolateChildVertsFromVerts(
}
}
template <class T, class U>
inline void
PrimvarRefiner::Limit(T const & src, U & dst) const {
if (_refiner.getLevel(_refiner.GetMaxLevel()).getNumVertexEdgesTotal() == 0) {
Error(FAR_RUNTIME_ERROR,
"Cannot compute limit points -- last level of refinement does not include full topology.");
return;
}
switch (_refiner._subdivType) {
case Sdc::SCHEME_CATMARK:
limit<Sdc::SCHEME_CATMARK>(src, dst, (U*)0, (U*)0);
break;
case Sdc::SCHEME_LOOP:
limit<Sdc::SCHEME_LOOP>(src, dst, (U*)0, (U*)0);
break;
case Sdc::SCHEME_BILINEAR:
limit<Sdc::SCHEME_BILINEAR>(src, dst, (U*)0, (U*)0);
break;
}
}
template <class T, class U, class U1, class U2>
inline void
PrimvarRefiner::Limit(T const & src, U & dstPos, U1 & dstTan1, U2 & dstTan2) const {
if (_refiner.getLevel(_refiner.GetMaxLevel()).getNumVertexEdgesTotal() == 0) {
Error(FAR_RUNTIME_ERROR,
"Cannot compute limit points -- last level of refinement does not include full topology.");
return;
}
switch (_refiner._subdivType) {
case Sdc::SCHEME_CATMARK:
limit<Sdc::SCHEME_CATMARK>(src, dstPos, &dstTan1, &dstTan2);
break;
case Sdc::SCHEME_LOOP:
limit<Sdc::SCHEME_LOOP>(src, dstPos, &dstTan1, &dstTan2);
break;
case Sdc::SCHEME_BILINEAR:
limit<Sdc::SCHEME_BILINEAR>(src, dstPos, &dstTan1, &dstTan2);
break;
}
}
template <Sdc::SchemeType SCHEME, class T, class U, class U1, class U2>
inline void
PrimvarRefiner::limit(T const & src, U & dstPos, U1 * dstTan1Ptr, U2 * dstTan2Ptr) const {
@ -1197,32 +1126,9 @@ PrimvarRefiner::limit(T const & src, U & dstPos, U1 * dstTan1Ptr, U2 * dstTan2Pt
}
}
template <class T, class U>
inline void
PrimvarRefiner::LimitFaceVarying(T const & src, U * dst, int channel) const {
if (_refiner.getLevel(_refiner.GetMaxLevel()).getNumVertexEdgesTotal() == 0) {
Error(FAR_RUNTIME_ERROR,
"Cannot compute limit points -- last level of refinement does not include full topology.");
return;
}
switch (_refiner._subdivType) {
case Sdc::SCHEME_CATMARK:
faceVaryingLimit<Sdc::SCHEME_CATMARK>(src, dst, channel);
break;
case Sdc::SCHEME_LOOP:
faceVaryingLimit<Sdc::SCHEME_LOOP>(src, dst, channel);
break;
case Sdc::SCHEME_BILINEAR:
faceVaryingLimit<Sdc::SCHEME_BILINEAR>(src, dst, channel);
break;
}
}
template <Sdc::SchemeType SCHEME, class T, class U>
inline void
PrimvarRefiner::faceVaryingLimit(T const & src, U * dst, int channel) const {
PrimvarRefiner::limitFVar(T const & src, U * dst, int channel) const {
Sdc::Scheme<SCHEME> scheme(_refiner._subdivOptions);

View File

@ -45,40 +45,52 @@ InterpolateFVarData(OpenSubdiv::Far::TopologyRefiner & refiner,
int channel = 0, // shapes only have 1 UV channel
fvarWidth = 2;
int numValuesTotal = refiner.GetNumFVarValuesTotal(channel),
numValues0 = refiner.GetLevel(0).GetNumFVarValues(channel);
int maxlevel = refiner.GetMaxLevel(),
numValuesM = refiner.GetLevel(maxlevel).GetNumFVarValues(channel),
numValuesTotal = refiner.GetNumFVarValuesTotal(channel);
if (shape.uvs.empty() or numValuesTotal<=0) {
return;
}
OpenSubdiv::Far::PrimvarRefiner primvarRefiner(refiner);
if (refiner.IsUniform()) {
std::vector<FVarVertex> buffer(numValuesTotal);
int maxlevel = refiner.GetMaxLevel(),
numValuesM = refiner.GetLevel(maxlevel).GetNumFVarValues(channel);
memcpy(&buffer[0], &shape.uvs[0], shape.uvs.size()*sizeof(float));
OpenSubdiv::Far::PrimvarRefiner(refiner).InterpolateFaceVarying(
&buffer[0], &buffer[numValues0], channel);
// we only keep the highest level of refinement !
// For uniform we only keep the highest level of refinement:
fvarData.resize(numValuesM * fvarWidth);
memcpy(&fvarData[0],
&buffer[numValuesTotal-numValuesM], numValuesM*sizeof(FVarVertex));
std::vector<FVarVertex> buffer(numValuesTotal - numValuesM);
FVarVertex * src = &buffer[0];
memcpy(src, &shape.uvs[0], shape.uvs.size()*sizeof(float));
// Defer the last level to treat separately with its alternate destination:
for (int level = 1; level < maxlevel; ++level) {
FVarVertex * dst = src + refiner.GetLevel(level-1).GetNumFVarValues(channel);
primvarRefiner.InterpolateFaceVarying(level, src, dst, channel);
src = dst;
}
FVarVertex * dst = reinterpret_cast<FVarVertex *>(&fvarData[0]);
primvarRefiner.InterpolateFaceVarying(maxlevel, src, dst, channel);
} else {
// For adaptive we keep all levels:
fvarData.resize(numValuesTotal * fvarWidth);
FVarVertex * src = reinterpret_cast<FVarVertex *>(&fvarData[0]),
* dst = src + numValues0;
FVarVertex * src = reinterpret_cast<FVarVertex *>(&fvarData[0]);
memcpy(src, &shape.uvs[0], shape.uvs.size()*sizeof(float));
OpenSubdiv::Far::PrimvarRefiner(refiner).InterpolateFaceVarying(
src, dst, channel);
for (int level = 1; level <= maxlevel; ++level) {
FVarVertex * dst = src + refiner.GetLevel(level-1).GetNumFVarValues(channel);
primvarRefiner.InterpolateFaceVarying(level, src, dst, channel);
src = dst;
}
}
}

View File

@ -162,10 +162,15 @@ InterpolateVtrVertexData(const char *shapeStr, Scheme scheme, int maxlevel,
shape->verts[i*3+2]);
}
T * verts = &data[0];
T * srcVerts = &data[0];
T * dstVerts = srcVerts + refiner->GetLevel(0).GetNumVertices();
OpenSubdiv::Far::PrimvarRefiner primvarRefiner(*refiner);
OpenSubdiv::Far::PrimvarRefiner(*refiner).Interpolate(
verts, verts+refiner->GetLevel(0).GetNumVertices());
for (int i = 1; i <= refiner->GetMaxLevel(); ++i) {
primvarRefiner.Interpolate(i, srcVerts, dstVerts);
srcVerts = dstVerts;
dstVerts += refiner->GetLevel(i).GetNumVertices();
}
delete shape;
return refiner;

View File

@ -27,7 +27,7 @@
// Tutorial description:
//
// This tutorial presents in a very succint way the requisite steps to
// instantiate a Far mesh from simple topological data.
// instantiate and refine a mesh with Far from simple topological data.
//
#include <opensubdiv/far/topologyRefinerFactory.h>
@ -144,28 +144,33 @@ int main(int, char **) {
// Interpolate vertex primvar data
Far::PrimvarRefiner(*refiner).Interpolate(verts, verts + nCoarseVerts);
Far::PrimvarRefiner primvarRefiner(*refiner);
Vertex * src = verts;
for (int level = 1; level <= maxlevel; ++level) {
Vertex * dst = src + refiner->GetLevel(level-1).GetNumVertices();
primvarRefiner.Interpolate(level, src, dst);
src = dst;
}
{ // Output OBJ of the highest level refined -----------
Far::TopologyLevel const & refLastLevel = refiner->GetLevel(maxlevel);
// Print vertex positions
for (int level=0, firstVert=0; level<=maxlevel; ++level) {
int nverts = refLastLevel.GetNumVertices();
int nfaces = refLastLevel.GetNumFaces();
if (level==maxlevel) {
for (int vert=0; vert<refLastLevel.GetNumVertices(); ++vert) {
float const * pos = verts[firstVert+vert].GetPosition();
printf("v %f %f %f\n", pos[0], pos[1], pos[2]);
}
} else {
firstVert += refiner->GetLevel(level).GetNumVertices();
}
// Print vertex positions
int firstOfLastVerts = refiner->GetNumVerticesTotal() - nverts;
for (int vert = 0; vert < nverts; ++vert) {
float const * pos = verts[firstOfLastVerts + vert].GetPosition();
printf("v %f %f %f\n", pos[0], pos[1], pos[2]);
}
// Print faces
for (int face=0; face<refLastLevel.GetNumFaces(); ++face) {
for (int face = 0; face < nfaces; ++face) {
Far::ConstIndexArray fverts = refLastLevel.GetFaceVertices(face);

View File

@ -449,28 +449,33 @@ int main(int, char **) {
// Interpolate vertex primvar data
Far::PrimvarRefiner(*refiner).Interpolate(verts, verts + nCoarseVerts);
Far::PrimvarRefiner primvarRefiner(*refiner);
Vertex * src = verts;
for (int level = 1; level <= maxlevel; ++level) {
Vertex * dst = src + refiner->GetLevel(level-1).GetNumVertices();
primvarRefiner.Interpolate(level, src, dst);
src = dst;
}
{ // Output OBJ of the highest level refined -----------
Far::TopologyLevel const & refLastLevel = refiner->GetLevel(maxlevel);
// Print vertex positions
for (int level=0, firstVert=0; level<=maxlevel; ++level) {
int nverts = refLastLevel.GetNumVertices();
int nfaces = refLastLevel.GetNumFaces();
if (level==maxlevel) {
for (int vert=0; vert<refLastLevel.GetNumVertices(); ++vert) {
float const * pos = verts[firstVert+vert].GetPosition();
printf("v %f %f %f\n", pos[0], pos[1], pos[2]);
}
} else {
firstVert += refiner->GetLevel(level).GetNumVertices();
}
// Print vertex positions
int firstOfLastVerts = refiner->GetNumVerticesTotal() - nverts;
for (int vert = 0; vert < nverts; ++vert) {
float const * pos = verts[firstOfLastVerts + vert].GetPosition();
printf("v %f %f %f\n", pos[0], pos[1], pos[2]);
}
// Print faces
for (int face=0; face<refLastLevel.GetNumFaces(); ++face) {
for (int face = 0; face < nfaces; ++face) {
Far::ConstIndexArray fverts = refLastLevel.GetFaceVertices(face);

View File

@ -27,7 +27,7 @@
// Tutorial description:
//
// Building on tutorial 0, this example shows how to instantiate a simple mesh,
// refine it uniformly and then interpolate both additional primvar data.
// refine it uniformly and then interpolate additional sets of primvar data.
//
#include <opensubdiv/far/topologyRefinerFactory.h>
@ -38,53 +38,48 @@
//------------------------------------------------------------------------------
// Vertex container implementation.
//
// We are adding a per-vertex color attribute to our Vertex interface.
// We are adding a per-vertex color attribute to our primvar data. While they
// are separate properties and exist in separate buffers (as when read from an
// Alembic file) they are both of the form float[3] and so we can use the same
// underlying type.
//
struct Vertex {
// While color and position may be the same, we'll make the color a "varying"
// primvar, e.g. it is constrained to being linearly interpolated between
// vertices, rather than smoothly like position and other vertex data.
//
struct Point3 {
// Minimal required interface ----------------------
Vertex() { }
Point3() { }
void Clear( void * =0 ) {
_position[0]=_position[1]=_position[2]=0.0f;
_color[0]=_color[1]=_color[2]=0.0f;
_point[0]=_point[1]=_point[2]=0.0f;
}
void AddWithWeight(Vertex const & src, float weight) {
_position[0]+=weight*src._position[0];
_position[1]+=weight*src._position[1];
_position[2]+=weight*src._position[2];
_color[0]+=weight*src._color[0];
_color[1]+=weight*src._color[1];
_color[2]+=weight*src._color[2];
void AddWithWeight(Point3 const & src, float weight) {
_point[0]+=weight*src._point[0];
_point[1]+=weight*src._point[1];
_point[2]+=weight*src._point[2];
}
// Public interface ------------------------------------
void SetPosition(float x, float y, float z) {
_position[0]=x;
_position[1]=y;
_position[2]=z;
void SetPoint(float x, float y, float z) {
_point[0]=x;
_point[1]=y;
_point[2]=z;
}
const float * GetPosition() const {
return _position;
}
void SetColor(float x, float y, float z) {
_color[0]=x;
_color[1]=y;
_color[2]=z;
}
const float * GetColor() const {
return _color;
const float * GetPoint() const {
return _point;
}
private:
float _position[3],
_color[3];
float _point[3];
};
typedef Point3 VertexPosition;
typedef Point3 VertexColor;
//------------------------------------------------------------------------------
// Cube geometry from catmark_cube.h
static float g_verts[8][3] = {{ -0.5f, -0.5f, 0.5f },
@ -132,40 +127,68 @@ int main(int, char **) {
// Uniformly refine the topolgy up to 'maxlevel'
refiner->RefineUniform(Far::TopologyRefiner::UniformOptions(maxlevel));
// Allocate a buffer for vertex primvar data. The buffer length is set to
// be the sum of all children vertices up to the highest level of refinement.
std::vector<Vertex> vbuffer(refiner->GetNumVerticesTotal());
Vertex * verts = &vbuffer[0];
// Initialize coarse mesh primvar data
// Allocate buffers for vertex primvar data.
//
// We assume we received the coarse data for the mesh in separate buffers
// from some other source, e.g. an Alembic file. Meanwhile, we want buffers
// for the last/finest subdivision level to persist. We have no interest
// in the intermediate levels.
//
// Determine the sizes for our needs:
int nCoarseVerts = g_nverts;
for (int i=0; i<nCoarseVerts; ++i) {
int nFineVerts = refiner->GetLevel(maxlevel).GetNumVertices();
int nTotalVerts = refiner->GetNumVerticesTotal();
int nTempVerts = nTotalVerts - nCoarseVerts - nFineVerts;
verts[i].SetPosition(g_verts[i][0], g_verts[i][1], g_verts[i][2]);
// Allocate and intialize the primvar data for the original coarse vertices:
std::vector<VertexPosition> coarsePosBuffer(nCoarseVerts);
std::vector<VertexColor> coarseClrBuffer(nCoarseVerts);
verts[i].SetColor(g_colors[i][0], g_colors[i][1], g_colors[i][2]);
for (int i = 0; i < nCoarseVerts; ++i) {
coarsePosBuffer[i].SetPoint(g_verts[i][0], g_verts[i][1], g_verts[i][2]);
coarseClrBuffer[i].SetPoint(g_colors[i][0], g_colors[i][1], g_colors[i][2]);
}
// Allocate intermediate and final storage to be populated:
std::vector<VertexPosition> tempPosBuffer(nTempVerts);
std::vector<VertexPosition> finePosBuffer(nFineVerts);
// Interpolate all primvar data
Far::PrimvarRefiner(*refiner).Interpolate(verts, verts + nCoarseVerts);
std::vector<VertexColor> tempClrBuffer(nTempVerts);
std::vector<VertexColor> fineClrBuffer(nFineVerts);
// Interpolate all primvar data -- separate buffers can be populated on
// separate threads if desired:
VertexPosition * srcPos = &coarsePosBuffer[0];
VertexPosition * dstPos = &tempPosBuffer[0];
VertexColor * srcClr = &coarseClrBuffer[0];
VertexColor * dstClr = &tempClrBuffer[0];
Far::PrimvarRefiner primvarRefiner(*refiner);
for (int level = 1; level < maxlevel; ++level) {
primvarRefiner.Interpolate( level, srcPos, dstPos);
primvarRefiner.InterpolateVarying(level, srcClr, dstClr);
srcPos = dstPos, dstPos += refiner->GetLevel(level).GetNumVertices();
srcClr = dstClr, dstClr += refiner->GetLevel(level).GetNumVertices();
}
// Interpolate the last level into the separate buffers for our final data:
primvarRefiner.Interpolate( maxlevel, srcPos, finePosBuffer);
primvarRefiner.InterpolateVarying(maxlevel, srcClr, fineClrBuffer);
{ // Visualization with Maya : print a MEL script that generates colored
// particles at the location of the refined vertices (don't forget to
// turn shading on in the viewport to see the colors)
int nverts = refiner->GetLevel(maxlevel).GetNumVertices();
// Position the 'verts' pointer to the first vertex of our 'maxlevel' level
for (int level=0; level<maxlevel; ++level) {
verts += refiner->GetLevel(level).GetNumVertices();
}
int nverts = nFineVerts;
// Output particle positions
printf("particle ");
for (int vert=0; vert<nverts; ++vert) {
float const * pos = verts[vert].GetPosition();
for (int vert = 0; vert < nverts; ++vert) {
float const * pos = finePosBuffer[vert].GetPoint();
printf("-p %f %f %f\n", pos[0], pos[1], pos[2]);
}
printf(";\n");
@ -178,8 +201,8 @@ int main(int, char **) {
// Set per-particle color values from our primvar data
printf("setAttr \"particleShape1.rgbPP\" -type \"vectorArray\" %d ", nverts);
for (int vert=0; vert<nverts; ++vert) {
float const * color = verts[vert].GetColor();
for (int vert = 0; vert < nverts; ++vert) {
float const * color = fineClrBuffer[vert].GetPoint();
printf("%f %f %f\n", color[0], color[1], color[2]);
}
printf(";\n");

View File

@ -200,22 +200,18 @@ int main(int, char **) {
refiner->RefineUniform(refineOptions);
}
// Allocate & interpolate the 'vertex' primvar data (see tutorial 2 for
// Allocate and initialize the 'vertex' primvar data (see tutorial 2 for
// more details).
std::vector<Vertex> vbuffer(refiner->GetNumVerticesTotal());
Vertex * verts = &vbuffer[0];
int nCoarseVerts = g_nverts;
for (int i=0; i<nCoarseVerts; ++i) {
for (int i=0; i<g_nverts; ++i) {
verts[i].SetPosition(g_verts[i][0], g_verts[i][1], g_verts[i][2]);
}
Far::PrimvarRefiner(*refiner).Interpolate(verts, verts + nCoarseVerts);
// Allocate & interpolate the 'face-varying' primvar data
int channel = 0,
nCoarseFVVerts = refiner->GetLevel(0).GetNumFVarValues(channel);
// Allocate and initialize the single channel of 'face-varying' primvar data
int channel = 0;
std::vector<FVarVertex> fvBuffer(refiner->GetNumFVarValuesTotal(channel));
FVarVertex * fvVerts = &fvBuffer[0];
@ -225,53 +221,62 @@ int main(int, char **) {
fvVerts[i].v = g_uvs[i][1];
}
Far::PrimvarRefiner(*refiner).InterpolateFaceVarying(fvVerts, fvVerts + nCoarseFVVerts, channel);
// Interpolate both vertex and face-varying primvar data
Far::PrimvarRefiner primvarRefiner(*refiner);
Vertex * srcVert = verts;
FVarVertex * srcFVar = fvVerts;
for (int level = 1; level <= maxlevel; ++level) {
Vertex * dstVert = srcVert + refiner->GetLevel(level-1).GetNumVertices();
FVarVertex * dstFVar = srcFVar + refiner->GetLevel(level-1).GetNumFVarValues(channel);
primvarRefiner.Interpolate(level, srcVert, dstVert);
primvarRefiner.InterpolateFaceVarying(level, srcFVar, dstFVar, channel);
srcVert = dstVert;
srcFVar = dstFVar;
}
{ // Output OBJ of the highest level refined -----------
Far::TopologyLevel const & refLastLevel = refiner->GetLevel(maxlevel);
// Print vertex positions
for (int level=0, firstVert=0; level<=maxlevel; ++level) {
int nverts = refLastLevel.GetNumVertices();
int nuvs = refLastLevel.GetNumFVarValues(channel);
int nfaces = refLastLevel.GetNumFaces();
if (level==maxlevel) {
for (int vert=0; vert<refLastLevel.GetNumVertices(); ++vert) {
float const * pos = verts[firstVert+vert].GetPosition();
printf("v %f %f %f\n", pos[0], pos[1], pos[2]);
}
} else {
firstVert += refiner->GetLevel(level).GetNumVertices();
}
// Print vertex positions
int firstOfLastVerts = refiner->GetNumVerticesTotal() - nverts;
for (int vert = 0; vert < nverts; ++vert) {
float const * pos = verts[firstOfLastVerts + vert].GetPosition();
printf("v %f %f %f\n", pos[0], pos[1], pos[2]);
}
// Print uvs
for (int level=0, firstVert=0; level<=maxlevel; ++level) {
int firstOfLastUvs = refiner->GetNumFVarValuesTotal(channel) - nuvs;
if (level==maxlevel) {
for (int vert=0; vert<refLastLevel.GetNumFVarValues(channel); ++vert) {
FVarVertex const & uv = fvVerts[firstVert+vert];
printf("vt %f %f\n", uv.u, uv.v);
}
} else {
firstVert += refiner->GetLevel(level).GetNumFVarValues(channel);
}
for (int fvvert = 0; fvvert < nuvs; ++fvvert) {
FVarVertex const & uv = fvVerts[firstOfLastUvs + fvvert];
printf("vt %f %f\n", uv.u, uv.v);
}
// Print faces
for (int face=0; face<refLastLevel.GetNumFaces(); ++face) {
for (int face = 0; face < nfaces; ++face) {
Far::ConstIndexArray fverts = refLastLevel.GetFaceVertices(face),
fvverts = refLastLevel.GetFVarFaceValues(face, channel);
Far::ConstIndexArray fverts = refLastLevel.GetFaceVertices(face);
Far::ConstIndexArray fuvs = refLastLevel.GetFVarFaceValues(face, channel);
// all refined Catmark faces should be quads
assert(fverts.size()==4 and fvverts.size()==4);
assert(fverts.size()==4 and fuvs.size()==4);
printf("f ");
for (int vert=0; vert<fverts.size(); ++vert) {
// OBJ uses 1-based arrays...
printf("%d/%d ", fverts[vert]+1, fvverts[vert]+1);
printf("%d/%d ", fverts[vert]+1, fuvs[vert]+1);
}
printf("\n");
}

View File

@ -167,7 +167,12 @@ int main(int, char **) {
// Interpolate vertex primvar data : they are the control vertices
// of the limit patches (see far_tutorial_0 for details)
Far::PrimvarRefiner(*refiner).Interpolate(&verts[0], &verts[g_nverts]);
Vertex * src = &verts[0];
for (int level = 1; level <= maxIsolation; ++level) {
Vertex * dst = src + refiner->GetLevel(level-1).GetNumVertices();
Far::PrimvarRefiner(*refiner).Interpolate(level, src, dst);
src = dst;
}
// Evaluate local points from interpolated vertex primvars.
patchTable->ComputeLocalPointValues(&verts[0], &verts[nRefinerVertices]);