OpenSubdiv: Add API to evaluate face-varying data
There are move changes along the line to keep everything working from from C.
This commit is contained in:
parent
428743a9b0
commit
c64262a05a
|
@ -383,6 +383,8 @@ TopologyRefinerFactory<TopologyRefinerData>::assignFaceVaryingTopology(
|
|||
const int num_uvs = converter->getNumUVCoordinates(converter);
|
||||
// Fill in per-corner index of the UV.
|
||||
const int channel = createBaseFVarChannel(refiner, num_uvs);
|
||||
// TODO(sergey): Need to check whether converter changed the winding of
|
||||
// face to match OpenSubdiv's expectations.
|
||||
for (int face_index = 0; face_index < num_faces; ++face_index) {
|
||||
Far::IndexArray dst_face_uvs =
|
||||
getBaseFaceFVarValues(refiner, face_index, channel);
|
||||
|
|
|
@ -49,6 +49,10 @@ getFVarLinearInterpolationFromCAPI(
|
|||
return Options::FVAR_LINEAR_NONE;
|
||||
case OSD_FVAR_LINEAR_INTERPOLATION_CORNERS_ONLY:
|
||||
return Options::FVAR_LINEAR_CORNERS_ONLY;
|
||||
case OSD_FVAR_LINEAR_INTERPOLATION_CORNERS_PLUS1:
|
||||
return Options::FVAR_LINEAR_CORNERS_PLUS1;
|
||||
case OSD_FVAR_LINEAR_INTERPOLATION_CORNERS_PLUS2:
|
||||
return Options::FVAR_LINEAR_CORNERS_PLUS2;
|
||||
case OSD_FVAR_LINEAR_INTERPOLATION_BOUNDARIES:
|
||||
return Options::FVAR_LINEAR_BOUNDARIES;
|
||||
case OSD_FVAR_LINEAR_INTERPOLATION_ALL:
|
||||
|
@ -58,6 +62,28 @@ getFVarLinearInterpolationFromCAPI(
|
|||
return Options::FVAR_LINEAR_NONE;
|
||||
}
|
||||
|
||||
OpenSubdiv_FVarLinearInterpolation
|
||||
getCAPIFVarLinearInterpolationFromOSD(
|
||||
OpenSubdiv::Sdc::Options::FVarLinearInterpolation linear_interpolation) {
|
||||
typedef OpenSubdiv::Sdc::Options Options;
|
||||
switch (linear_interpolation) {
|
||||
case Options::FVAR_LINEAR_NONE:
|
||||
return OSD_FVAR_LINEAR_INTERPOLATION_NONE;
|
||||
case Options::FVAR_LINEAR_CORNERS_ONLY:
|
||||
return OSD_FVAR_LINEAR_INTERPOLATION_CORNERS_ONLY;
|
||||
case Options::FVAR_LINEAR_CORNERS_PLUS1:
|
||||
return OSD_FVAR_LINEAR_INTERPOLATION_CORNERS_PLUS1;
|
||||
case Options::FVAR_LINEAR_CORNERS_PLUS2:
|
||||
return OSD_FVAR_LINEAR_INTERPOLATION_CORNERS_PLUS2;
|
||||
case Options::FVAR_LINEAR_BOUNDARIES:
|
||||
return OSD_FVAR_LINEAR_INTERPOLATION_BOUNDARIES;
|
||||
case Options::FVAR_LINEAR_ALL:
|
||||
return OSD_FVAR_LINEAR_INTERPOLATION_ALL;
|
||||
}
|
||||
assert(!"Unknown fvar linear interpolation passed via C-API");
|
||||
return OSD_FVAR_LINEAR_INTERPOLATION_NONE;
|
||||
}
|
||||
|
||||
float getCompatibleEdgeSharpness(const OpenSubdiv_Converter* converter,
|
||||
int edge_index) {
|
||||
if (converter->getNumEdgeFaces(converter, edge_index) == 2) {
|
||||
|
|
|
@ -41,6 +41,11 @@ OpenSubdiv::Sdc::Options::FVarLinearInterpolation
|
|||
getFVarLinearInterpolationFromCAPI(
|
||||
OpenSubdiv_FVarLinearInterpolation linear_interpolation);
|
||||
|
||||
// Similar to above, just other way around.
|
||||
OpenSubdiv_FVarLinearInterpolation
|
||||
getCAPIFVarLinearInterpolationFromOSD(
|
||||
OpenSubdiv::Sdc::Options::FVarLinearInterpolation linear_interpolation);
|
||||
|
||||
// Get edge sharpness in a way which makes OpenSubdiv happy.
|
||||
float getCompatibleEdgeSharpness(const OpenSubdiv_Converter* converter,
|
||||
int edge_index);
|
||||
|
|
|
@ -46,6 +46,9 @@ bool getIsAdaptive(const OpenSubdiv_TopologyRefiner* topology_refiner) {
|
|||
return topology_refiner->internal->settings.is_adaptive;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Query basic topology information from base level.
|
||||
|
||||
int getNumVertices(const OpenSubdiv_TopologyRefiner* topology_refiner) {
|
||||
return getOSDTopologyBaseLevel(topology_refiner)->GetNumVertices();
|
||||
}
|
||||
|
@ -58,6 +61,9 @@ int getNumFaces(const OpenSubdiv_TopologyRefiner* topology_refiner) {
|
|||
return getOSDTopologyBaseLevel(topology_refiner)->GetNumFaces();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// PTex face geometry queries.
|
||||
|
||||
int getNumFaceVertices(const OpenSubdiv_TopologyRefiner* topology_refiner,
|
||||
const int face_index) {
|
||||
const OpenSubdiv::Far::TopologyLevel* base_level =
|
||||
|
@ -97,18 +103,59 @@ void fillFacePtexIndexOffset(const OpenSubdiv_TopologyRefiner* topology_refiner,
|
|||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// Face-varying data.
|
||||
|
||||
int getNumFVarChannels(
|
||||
const struct OpenSubdiv_TopologyRefiner* topology_refiner) {
|
||||
const OpenSubdiv::Far::TopologyLevel* base_level =
|
||||
getOSDTopologyBaseLevel(topology_refiner);
|
||||
return base_level->GetNumFVarChannels();
|
||||
}
|
||||
|
||||
OpenSubdiv_FVarLinearInterpolation getFVarLinearInterpolation(
|
||||
const struct OpenSubdiv_TopologyRefiner* topology_refiner) {
|
||||
return opensubdiv_capi::getCAPIFVarLinearInterpolationFromOSD(
|
||||
getOSDTopologyRefiner(topology_refiner)->GetFVarLinearInterpolation());
|
||||
}
|
||||
|
||||
int getNumFVarValues(
|
||||
const struct OpenSubdiv_TopologyRefiner* topology_refiner,
|
||||
const int channel) {
|
||||
const OpenSubdiv::Far::TopologyLevel* base_level =
|
||||
getOSDTopologyBaseLevel(topology_refiner);
|
||||
return base_level->GetNumFVarValues(channel);
|
||||
}
|
||||
|
||||
const int* getFaceFVarValueIndices(
|
||||
const struct OpenSubdiv_TopologyRefiner* topology_refiner,
|
||||
const int face_index,
|
||||
const int channel) {
|
||||
const OpenSubdiv::Far::TopologyLevel* base_level =
|
||||
getOSDTopologyBaseLevel(topology_refiner);
|
||||
return &base_level->GetFaceFVarValues(face_index, channel)[0];
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// Internal helpers.
|
||||
|
||||
void assignFunctionPointers(OpenSubdiv_TopologyRefiner* topology_refiner) {
|
||||
topology_refiner->getSubdivisionLevel = getSubdivisionLevel;
|
||||
topology_refiner->getIsAdaptive = getIsAdaptive;
|
||||
|
||||
// Basic topology information.
|
||||
topology_refiner->getNumVertices = getNumVertices;
|
||||
topology_refiner->getNumEdges = getNumEdges;
|
||||
topology_refiner->getNumFaces = getNumFaces;
|
||||
topology_refiner->getNumFaceVertices = getNumFaceVertices;
|
||||
|
||||
// PTex face geometry.
|
||||
topology_refiner->getNumFacePtexFaces = getNumFacePtexFaces;
|
||||
topology_refiner->getNumPtexFaces = getNumPtexFaces;
|
||||
topology_refiner->fillFacePtexIndexOffset = fillFacePtexIndexOffset;
|
||||
// Face-varying data.
|
||||
topology_refiner->getNumFVarChannels = getNumFVarChannels;
|
||||
topology_refiner->getFVarLinearInterpolation = getFVarLinearInterpolation;
|
||||
topology_refiner->getNumFVarValues = getNumFVarValues;
|
||||
topology_refiner->getFaceFVarValueIndices = getFaceFVarValueIndices;
|
||||
}
|
||||
|
||||
OpenSubdiv_TopologyRefiner* allocateTopologyRefiner() {
|
||||
|
@ -125,9 +172,14 @@ OpenSubdiv_TopologyRefiner* allocateTopologyRefiner() {
|
|||
OpenSubdiv_TopologyRefiner* openSubdiv_createTopologyRefinerFromConverter(
|
||||
OpenSubdiv_Converter* converter,
|
||||
const OpenSubdiv_TopologyRefinerSettings* settings) {
|
||||
OpenSubdiv_TopologyRefiner* topology_refiner = allocateTopologyRefiner();
|
||||
topology_refiner->internal->osd_topology_refiner =
|
||||
OpenSubdiv::Far::TopologyRefiner* osd_topology_refiner =
|
||||
opensubdiv_capi::createOSDTopologyRefinerFromConverter(converter);
|
||||
if (osd_topology_refiner == NULL) {
|
||||
// Happens on empty or bad topology.
|
||||
return NULL;
|
||||
}
|
||||
OpenSubdiv_TopologyRefiner* topology_refiner = allocateTopologyRefiner();
|
||||
topology_refiner->internal->osd_topology_refiner = osd_topology_refiner;
|
||||
// Store setting which we want to keep track of and which can not be stored
|
||||
// in OpenSubdiv's descriptor yet.
|
||||
topology_refiner->internal->settings = *settings;
|
||||
|
|
|
@ -34,6 +34,21 @@ typedef enum eOpenSubdivEvaluator {
|
|||
OPENSUBDIV_EVALUATOR_GLSL_COMPUTE = (1 << 5),
|
||||
} eOpenSubdivEvaluator;
|
||||
|
||||
typedef enum OpenSubdiv_SchemeType {
|
||||
OSD_SCHEME_BILINEAR,
|
||||
OSD_SCHEME_CATMARK,
|
||||
OSD_SCHEME_LOOP,
|
||||
} OpenSubdiv_SchemeType;
|
||||
|
||||
typedef enum OpenSubdiv_FVarLinearInterpolation {
|
||||
OSD_FVAR_LINEAR_INTERPOLATION_NONE,
|
||||
OSD_FVAR_LINEAR_INTERPOLATION_CORNERS_ONLY,
|
||||
OSD_FVAR_LINEAR_INTERPOLATION_CORNERS_PLUS1,
|
||||
OSD_FVAR_LINEAR_INTERPOLATION_CORNERS_PLUS2,
|
||||
OSD_FVAR_LINEAR_INTERPOLATION_BOUNDARIES,
|
||||
OSD_FVAR_LINEAR_INTERPOLATION_ALL,
|
||||
} OpenSubdiv_FVarLinearInterpolation;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -19,23 +19,12 @@
|
|||
#ifndef OPENSUBDIV_CONVERTER_CAPI_H_
|
||||
#define OPENSUBDIV_CONVERTER_CAPI_H_
|
||||
|
||||
#include "opensubdiv_capi_type.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef enum OpenSubdiv_SchemeType {
|
||||
OSD_SCHEME_BILINEAR,
|
||||
OSD_SCHEME_CATMARK,
|
||||
OSD_SCHEME_LOOP,
|
||||
} OpenSubdiv_SchemeType;
|
||||
|
||||
typedef enum OpenSubdiv_FVarLinearInterpolation {
|
||||
OSD_FVAR_LINEAR_INTERPOLATION_NONE,
|
||||
OSD_FVAR_LINEAR_INTERPOLATION_CORNERS_ONLY,
|
||||
OSD_FVAR_LINEAR_INTERPOLATION_BOUNDARIES,
|
||||
OSD_FVAR_LINEAR_INTERPOLATION_ALL,
|
||||
} OpenSubdiv_FVarLinearInterpolation;
|
||||
|
||||
typedef struct OpenSubdiv_Converter {
|
||||
OpenSubdiv_SchemeType (*getSchemeType)(
|
||||
const struct OpenSubdiv_Converter* converter);
|
||||
|
|
|
@ -21,6 +21,8 @@
|
|||
|
||||
#include <stdint.h> // for bool
|
||||
|
||||
#include "opensubdiv_capi_type.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
@ -45,7 +47,16 @@ typedef struct OpenSubdiv_TopologyRefiner {
|
|||
bool (*getIsAdaptive)(
|
||||
const struct OpenSubdiv_TopologyRefiner* topology_refiner);
|
||||
|
||||
// NOTE: All queries are querying base level.
|
||||
//
|
||||
// TODO(sergey): Consider making it more obvious in function naming,
|
||||
// but since it's unlikely (or at least, will be uncommon use) for API
|
||||
// which queries final geometry, we should be fine with this name for
|
||||
// now.
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// Query basic topology information from base level.
|
||||
|
||||
int (*getNumVertices)(
|
||||
const struct OpenSubdiv_TopologyRefiner* topology_refiner);
|
||||
int (*getNumEdges)(
|
||||
|
@ -56,6 +67,9 @@ typedef struct OpenSubdiv_TopologyRefiner {
|
|||
const struct OpenSubdiv_TopologyRefiner* topology_refiner,
|
||||
const int face_index);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// PTex face geometry queries.
|
||||
|
||||
// Ptex face corresponds to OpenSubdiv's internal "patch" and to Blender's
|
||||
// subdivision grid. The rule commes as:
|
||||
// - Triangle face consist of 3 ptex faces, ordered in the order of
|
||||
|
@ -79,6 +93,31 @@ typedef struct OpenSubdiv_TopologyRefiner {
|
|||
const struct OpenSubdiv_TopologyRefiner* topology_refiner,
|
||||
int* face_ptex_index_offset);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// Face-varying data.
|
||||
|
||||
// Number of face-varying channels (or how they are called in Blender layers).
|
||||
int (*getNumFVarChannels)(
|
||||
const struct OpenSubdiv_TopologyRefiner* topology_refiner);
|
||||
// Get face-varying interpolation type.
|
||||
OpenSubdiv_FVarLinearInterpolation (*getFVarLinearInterpolation)(
|
||||
const struct OpenSubdiv_TopologyRefiner* topology_refiner);
|
||||
// Get total number of face-varying values in a particular channel.
|
||||
int (*getNumFVarValues)(
|
||||
const struct OpenSubdiv_TopologyRefiner* topology_refiner,
|
||||
const int channel);
|
||||
// Get face-varying value indices associated with a particular face.
|
||||
//
|
||||
// This is an array of indices inside of face-varying array, array elements
|
||||
// are aligned with face corners (or loops in Blender terminology).
|
||||
const int* (*getFaceFVarValueIndices)(
|
||||
const struct OpenSubdiv_TopologyRefiner* topology_refiner,
|
||||
const int face_index,
|
||||
const int channel);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// Internal use.
|
||||
|
||||
// Internal storage for the use in this module only.
|
||||
//
|
||||
// Tease: Contains actual OpenSubdiv's refiner and (optionally) some other
|
||||
|
@ -86,6 +125,8 @@ typedef struct OpenSubdiv_TopologyRefiner {
|
|||
struct OpenSubdiv_TopologyRefinerInternal* internal;
|
||||
} OpenSubdiv_TopologyRefiner;
|
||||
|
||||
// NOTE: Will return NULL in cases of bad topology.
|
||||
// NOTE: Mesh without faces is considered a bad topology.
|
||||
OpenSubdiv_TopologyRefiner* openSubdiv_createTopologyRefinerFromConverter(
|
||||
struct OpenSubdiv_Converter* converter,
|
||||
const OpenSubdiv_TopologyRefinerSettings* settings);
|
||||
|
@ -101,7 +142,7 @@ void openSubdiv_deleteTopologyRefiner(
|
|||
// complicated parts of subdivision process.
|
||||
bool openSubdiv_topologyRefinerCompareWithConverter(
|
||||
const OpenSubdiv_TopologyRefiner* topology_refiner,
|
||||
const OpenSubdiv_Converter* converter);
|
||||
const struct OpenSubdiv_Converter* converter);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue