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:
2018-07-17 18:06:32 +02:00
parent 428743a9b0
commit c64262a05a
7 changed files with 148 additions and 18 deletions

View File

@@ -383,6 +383,8 @@ TopologyRefinerFactory<TopologyRefinerData>::assignFaceVaryingTopology(
const int num_uvs = converter->getNumUVCoordinates(converter); const int num_uvs = converter->getNumUVCoordinates(converter);
// Fill in per-corner index of the UV. // Fill in per-corner index of the UV.
const int channel = createBaseFVarChannel(refiner, num_uvs); 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) { for (int face_index = 0; face_index < num_faces; ++face_index) {
Far::IndexArray dst_face_uvs = Far::IndexArray dst_face_uvs =
getBaseFaceFVarValues(refiner, face_index, channel); getBaseFaceFVarValues(refiner, face_index, channel);

View File

@@ -49,6 +49,10 @@ getFVarLinearInterpolationFromCAPI(
return Options::FVAR_LINEAR_NONE; return Options::FVAR_LINEAR_NONE;
case OSD_FVAR_LINEAR_INTERPOLATION_CORNERS_ONLY: case OSD_FVAR_LINEAR_INTERPOLATION_CORNERS_ONLY:
return Options::FVAR_LINEAR_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: case OSD_FVAR_LINEAR_INTERPOLATION_BOUNDARIES:
return Options::FVAR_LINEAR_BOUNDARIES; return Options::FVAR_LINEAR_BOUNDARIES;
case OSD_FVAR_LINEAR_INTERPOLATION_ALL: case OSD_FVAR_LINEAR_INTERPOLATION_ALL:
@@ -58,6 +62,28 @@ getFVarLinearInterpolationFromCAPI(
return Options::FVAR_LINEAR_NONE; 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, float getCompatibleEdgeSharpness(const OpenSubdiv_Converter* converter,
int edge_index) { int edge_index) {
if (converter->getNumEdgeFaces(converter, edge_index) == 2) { if (converter->getNumEdgeFaces(converter, edge_index) == 2) {

View File

@@ -41,6 +41,11 @@ OpenSubdiv::Sdc::Options::FVarLinearInterpolation
getFVarLinearInterpolationFromCAPI( getFVarLinearInterpolationFromCAPI(
OpenSubdiv_FVarLinearInterpolation linear_interpolation); 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. // Get edge sharpness in a way which makes OpenSubdiv happy.
float getCompatibleEdgeSharpness(const OpenSubdiv_Converter* converter, float getCompatibleEdgeSharpness(const OpenSubdiv_Converter* converter,
int edge_index); int edge_index);

View File

@@ -46,6 +46,9 @@ bool getIsAdaptive(const OpenSubdiv_TopologyRefiner* topology_refiner) {
return topology_refiner->internal->settings.is_adaptive; return topology_refiner->internal->settings.is_adaptive;
} }
////////////////////////////////////////////////////////////////////////////////
// Query basic topology information from base level.
int getNumVertices(const OpenSubdiv_TopologyRefiner* topology_refiner) { int getNumVertices(const OpenSubdiv_TopologyRefiner* topology_refiner) {
return getOSDTopologyBaseLevel(topology_refiner)->GetNumVertices(); return getOSDTopologyBaseLevel(topology_refiner)->GetNumVertices();
} }
@@ -58,6 +61,9 @@ int getNumFaces(const OpenSubdiv_TopologyRefiner* topology_refiner) {
return getOSDTopologyBaseLevel(topology_refiner)->GetNumFaces(); return getOSDTopologyBaseLevel(topology_refiner)->GetNumFaces();
} }
////////////////////////////////////////////////////////////////////////////////
// PTex face geometry queries.
int getNumFaceVertices(const OpenSubdiv_TopologyRefiner* topology_refiner, int getNumFaceVertices(const OpenSubdiv_TopologyRefiner* topology_refiner,
const int face_index) { const int face_index) {
const OpenSubdiv::Far::TopologyLevel* base_level = 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) { void assignFunctionPointers(OpenSubdiv_TopologyRefiner* topology_refiner) {
topology_refiner->getSubdivisionLevel = getSubdivisionLevel; topology_refiner->getSubdivisionLevel = getSubdivisionLevel;
topology_refiner->getIsAdaptive = getIsAdaptive; topology_refiner->getIsAdaptive = getIsAdaptive;
// Basic topology information.
topology_refiner->getNumVertices = getNumVertices; topology_refiner->getNumVertices = getNumVertices;
topology_refiner->getNumEdges = getNumEdges; topology_refiner->getNumEdges = getNumEdges;
topology_refiner->getNumFaces = getNumFaces; topology_refiner->getNumFaces = getNumFaces;
topology_refiner->getNumFaceVertices = getNumFaceVertices; topology_refiner->getNumFaceVertices = getNumFaceVertices;
// PTex face geometry.
topology_refiner->getNumFacePtexFaces = getNumFacePtexFaces; topology_refiner->getNumFacePtexFaces = getNumFacePtexFaces;
topology_refiner->getNumPtexFaces = getNumPtexFaces; topology_refiner->getNumPtexFaces = getNumPtexFaces;
topology_refiner->fillFacePtexIndexOffset = fillFacePtexIndexOffset; 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() { OpenSubdiv_TopologyRefiner* allocateTopologyRefiner() {
@@ -125,9 +172,14 @@ OpenSubdiv_TopologyRefiner* allocateTopologyRefiner() {
OpenSubdiv_TopologyRefiner* openSubdiv_createTopologyRefinerFromConverter( OpenSubdiv_TopologyRefiner* openSubdiv_createTopologyRefinerFromConverter(
OpenSubdiv_Converter* converter, OpenSubdiv_Converter* converter,
const OpenSubdiv_TopologyRefinerSettings* settings) { const OpenSubdiv_TopologyRefinerSettings* settings) {
OpenSubdiv_TopologyRefiner* topology_refiner = allocateTopologyRefiner(); OpenSubdiv::Far::TopologyRefiner* osd_topology_refiner =
topology_refiner->internal->osd_topology_refiner =
opensubdiv_capi::createOSDTopologyRefinerFromConverter(converter); 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 // Store setting which we want to keep track of and which can not be stored
// in OpenSubdiv's descriptor yet. // in OpenSubdiv's descriptor yet.
topology_refiner->internal->settings = *settings; topology_refiner->internal->settings = *settings;

View File

@@ -34,6 +34,21 @@ typedef enum eOpenSubdivEvaluator {
OPENSUBDIV_EVALUATOR_GLSL_COMPUTE = (1 << 5), OPENSUBDIV_EVALUATOR_GLSL_COMPUTE = (1 << 5),
} eOpenSubdivEvaluator; } 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 #ifdef __cplusplus
} }
#endif #endif

View File

@@ -19,23 +19,12 @@
#ifndef OPENSUBDIV_CONVERTER_CAPI_H_ #ifndef OPENSUBDIV_CONVERTER_CAPI_H_
#define OPENSUBDIV_CONVERTER_CAPI_H_ #define OPENSUBDIV_CONVERTER_CAPI_H_
#include "opensubdiv_capi_type.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #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 { typedef struct OpenSubdiv_Converter {
OpenSubdiv_SchemeType (*getSchemeType)( OpenSubdiv_SchemeType (*getSchemeType)(
const struct OpenSubdiv_Converter* converter); const struct OpenSubdiv_Converter* converter);

View File

@@ -21,6 +21,8 @@
#include <stdint.h> // for bool #include <stdint.h> // for bool
#include "opensubdiv_capi_type.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
@@ -45,7 +47,16 @@ typedef struct OpenSubdiv_TopologyRefiner {
bool (*getIsAdaptive)( bool (*getIsAdaptive)(
const struct OpenSubdiv_TopologyRefiner* topology_refiner); 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. // Query basic topology information from base level.
int (*getNumVertices)( int (*getNumVertices)(
const struct OpenSubdiv_TopologyRefiner* topology_refiner); const struct OpenSubdiv_TopologyRefiner* topology_refiner);
int (*getNumEdges)( int (*getNumEdges)(
@@ -56,6 +67,9 @@ typedef struct OpenSubdiv_TopologyRefiner {
const struct OpenSubdiv_TopologyRefiner* topology_refiner, const struct OpenSubdiv_TopologyRefiner* topology_refiner,
const int face_index); const int face_index);
//////////////////////////////////////////////////////////////////////////////
// PTex face geometry queries.
// Ptex face corresponds to OpenSubdiv's internal "patch" and to Blender's // Ptex face corresponds to OpenSubdiv's internal "patch" and to Blender's
// subdivision grid. The rule commes as: // subdivision grid. The rule commes as:
// - Triangle face consist of 3 ptex faces, ordered in the order of // - 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, const struct OpenSubdiv_TopologyRefiner* topology_refiner,
int* face_ptex_index_offset); 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. // Internal storage for the use in this module only.
// //
// Tease: Contains actual OpenSubdiv's refiner and (optionally) some other // Tease: Contains actual OpenSubdiv's refiner and (optionally) some other
@@ -86,6 +125,8 @@ typedef struct OpenSubdiv_TopologyRefiner {
struct OpenSubdiv_TopologyRefinerInternal* internal; struct OpenSubdiv_TopologyRefinerInternal* internal;
} OpenSubdiv_TopologyRefiner; } OpenSubdiv_TopologyRefiner;
// NOTE: Will return NULL in cases of bad topology.
// NOTE: Mesh without faces is considered a bad topology.
OpenSubdiv_TopologyRefiner* openSubdiv_createTopologyRefinerFromConverter( OpenSubdiv_TopologyRefiner* openSubdiv_createTopologyRefinerFromConverter(
struct OpenSubdiv_Converter* converter, struct OpenSubdiv_Converter* converter,
const OpenSubdiv_TopologyRefinerSettings* settings); const OpenSubdiv_TopologyRefinerSettings* settings);
@@ -101,7 +142,7 @@ void openSubdiv_deleteTopologyRefiner(
// complicated parts of subdivision process. // complicated parts of subdivision process.
bool openSubdiv_topologyRefinerCompareWithConverter( bool openSubdiv_topologyRefinerCompareWithConverter(
const OpenSubdiv_TopologyRefiner* topology_refiner, const OpenSubdiv_TopologyRefiner* topology_refiner,
const OpenSubdiv_Converter* converter); const struct OpenSubdiv_Converter* converter);
#ifdef __cplusplus #ifdef __cplusplus
} }