OpenSubdiv/opensubdiv/far/patchTablesFactory.h
George ElKoura 420473b45b Experiment separating out Ptex from TopologyRefiner.
Remove the ptex-specific code from the Far::TopologyRefiner and instead provide it in a separate class Far::PtexIndices.  Clients who need to use the Ptex API need to first build a Far::PtexIndices object by providing it with a refiner.

This has the advantage of keeping the API on the TopologyRefiner a little cleaner.  The ptex methods were const but were mutating state with const_casts.  The new mechanism still achieves the same lazy initialization behavior by forcing clients to instantiate them exactly when needed.

A disadvantage of this approach is that the PatchTablesFactory creates its own PtexIndices and throws it out after the patch tables are created.  This is great if you're never going to need the ptex indices again, but not so great if you will need them again.
2015-04-21 17:34:02 -07:00

209 lines
7.9 KiB
C++

//
// Copyright 2013 Pixar
//
// Licensed under the Apache License, Version 2.0 (the "Apache License")
// with the following modification; you may not use this file except in
// compliance with the Apache License and the following modification to it:
// Section 6. Trademarks. is deleted and replaced with:
//
// 6. Trademarks. This License does not grant permission to use the trade
// names, trademarks, service marks, or product names of the Licensor
// and its affiliates, except as required to comply with Section 4(c) of
// the License and to reproduce the content of the NOTICE file.
//
// You may obtain a copy of the Apache License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the Apache License with the above modification is
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the Apache License for the specific
// language governing permissions and limitations under the Apache License.
//
#ifndef FAR_PATCH_TABLES_FACTORY_H
#define FAR_PATCH_TABLES_FACTORY_H
#include "../version.h"
#include "../far/patchTables.h"
namespace OpenSubdiv {
namespace OPENSUBDIV_VERSION {
// Forward declarations (for internal implementation purposes):
namespace Vtr { class Level; }
namespace Far {
class PtexIndices;
class TopologyRefiner;
class PatchTablesFactoryBase {
public:
// PatchFaceTag
// A simple struct containing all information gathered about a face that is relevant
// to constructing a patch for it (some of these enums should probably be defined more
// as part of PatchTables)
//
// Like the HbrFace<T>::AdaptiveFlags, this struct aggregates all of the face tags
// supporting feature adaptive refinement. For now it is not used elsewhere and can
// remain local to this implementation, but we may want to move it into a header of
// its own if it has greater use later.
//
// Note that several properties being assigned here attempt to do so given a 4-bit
// mask of properties at the edges or vertices of the quad. Still not sure exactly
// what will be done this way, but the goal is to create lookup tables (of size 16
// for the 4 bits) to quickly determine was is needed, rather than iteration and
// branching on the edges or vertices.
//
struct PatchFaceTag {
public:
unsigned int _hasPatch : 1;
unsigned int _isRegular : 1;
unsigned int _transitionMask : 4;
unsigned int _boundaryMask : 4;
unsigned int _boundaryIndex : 2;
unsigned int _boundaryCount : 3;
unsigned int _hasBoundaryEdge : 3;
unsigned int _isSingleCrease : 1;
void clear();
void assignBoundaryPropertiesFromEdgeMask(int boundaryEdgeMask);
void assignBoundaryPropertiesFromVertexMask(int boundaryVertexMask);
void assignTransitionPropertiesFromEdgeMask(int transitionMask) {
_transitionMask = transitionMask;
}
};
typedef std::vector<PatchFaceTag> PatchTagVector;
struct Options {
Options(unsigned int maxIsolation=10) :
generateAllLevels(false),
triangulateQuads(false),
useSingleCreasePatch(false),
maxIsolationLevel(maxIsolation),
generateFVarTables(false),
useFVarQuadEndCaps(true), // XXXX change to false when FVar Gregory is ready
numFVarChannels(-1),
fvarChannelIndices(0)
{ }
unsigned int generateAllLevels : 1, ///< Include levels from 'firstLevel' to 'maxLevel' (Uniform mode only)
triangulateQuads : 1, ///< Triangulate 'QUADS' primitives (Uniform mode only)
useSingleCreasePatch : 1, ///< Use single crease patch
maxIsolationLevel : 4, ///< Cap adaptive feature isolation to the given level (max. 10)
// face-varying
generateFVarTables : 1, ///< Generate face-varying patch tables
useFVarQuadEndCaps : 1; ///< Use bilinear quads as end-caps around extraordinary vertices
int numFVarChannels; ///< Number of channel indices and interpolation modes passed
int const * fvarChannelIndices; ///< List containing the indices of the channels selected for the factory
};
/// \brief Factory constructor for PatchTables
///
/// @param refiner TopologyRefiner from which to generate patches
///
/// @param options Options controlling the creation of the tables
///
/// @return A new instance of PatchTables
///
static PatchTables * Create(TopologyRefiner const & refiner,
PatchTablesFactoryBase::Options options=Options());
protected:
//
// Private helper structures
//
struct AdaptiveContext;
//
// Methods for allocating and managing the patch table data arrays:
//
static PatchTables * createUniform(TopologyRefiner const & refiner, Options options);
static void allocateVertexTables(PatchTables * tables, int nlevels, bool hasSharpness);
static void allocateFVarChannels(TopologyRefiner const & refiner,
Options options, int npatches, PatchTables * tables);
static PatchParam * computePatchParam(TopologyRefiner const & refiner,
PtexIndices const & ptexIndices,
int level, int face, int rotation,
int boundaryMask, int transitionMask, PatchParam * coord);
static int gatherFVarData(AdaptiveContext & state,
int level, Index faceIndex, Index levelFaceOffset, int rotation,
Index const * levelOffsets, Index fofss, Index ** fptrs);
};
/// \brief a templated patchtable factory parameterized by end cap strategy class..
///
///
template <typename ENDCAP_FACTORY>
class PatchTablesFactoryT : public PatchTablesFactoryBase {
public:
/// \brief Factory constructor for PatchTables
///
/// @param refiner TopologyRefiner from which to generate patches
///
/// @param options Options controlling the creation of the tables
///
/// @param endCapFactory If provided, it accumulates end patches
/// for later patch/stencil generation
///
/// @return A new instance of PatchTables
///
static PatchTables * Create(TopologyRefiner const & refiner,
PatchTablesFactoryBase::Options options=Options(),
ENDCAP_FACTORY *endCapFactory=NULL);
private:
static PatchTables * createAdaptive(TopologyRefiner const & refiner, Options options,
ENDCAP_FACTORY *);
//
// High-level methods for identifying and populating patches associated with faces:
//
static void identifyAdaptivePatches(AdaptiveContext & state, ENDCAP_FACTORY *);
static void populateAdaptivePatches(AdaptiveContext & state,
PtexIndices const & ptexIndices, ENDCAP_FACTORY *);
private:
};
/// \brief Default endcap factory (does nothing for end cap)
///
///
class EndCapNoneFactory {
public:
PatchDescriptor::Type GetPatchType(PatchTablesFactoryBase::PatchFaceTag const &) const {
return PatchDescriptor::NON_PATCH;
}
ConstIndexArray GetTopology(Vtr::Level const &/*level*/, Index /*faceIndex*/,
PatchTablesFactoryBase::PatchFaceTag const * /*levelPatchTags*/,
int /*levelVertOffset*/) {
return ConstIndexArray();
}
};
typedef PatchTablesFactoryT<EndCapNoneFactory> PatchTablesFactory;
} // end namespace Far
} // end namespace OPENSUBDIV_VERSION
using namespace OPENSUBDIV_VERSION;
} // end namespace OpenSubdiv
#endif /* FAR_PATCH_TABLES_FACTORY_H */