mirror of
https://github.com/PixarAnimationStudios/OpenSubdiv
synced 2024-11-09 13:50:05 +00:00
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:
parent
b4d1d09ab9
commit
5b854c8534
@ -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);
|
||||
|
||||
|
@ -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 =============
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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");
|
||||
|
@ -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");
|
||||
}
|
||||
|
@ -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]);
|
||||
|
Loading…
Reference in New Issue
Block a user