[Bf-blender-cvs] [f0f60d7] master: OpenSubdiv: Initial work to support UV maps in textured OSD viewport
Sergey Sharybin
noreply at git.blender.org
Wed Jul 20 14:40:57 CEST 2016
Commit: f0f60d775def20ff3a3699704b33c66712d50c6a
Author: Sergey Sharybin
Date: Tue Jul 19 09:28:54 2016 +0200
Branches: master
https://developer.blender.org/rBf0f60d775def20ff3a3699704b33c66712d50c6a
OpenSubdiv: Initial work to support UV maps in textured OSD viewport
A bit work in progress, currently the following limitations:
- Texture shading only, Material shading will come later
- No UVs subdivision yet
- Always uses active UV and currently changing active UV will
not properly update the viewport.
Well, need to start somewhere :)
===================================================================
M intern/opensubdiv/opensubdiv_capi.cc
M intern/opensubdiv/opensubdiv_capi.h
M intern/opensubdiv/opensubdiv_converter.cc
M intern/opensubdiv/opensubdiv_converter_capi.h
M intern/opensubdiv/opensubdiv_gpu_capi.cc
M intern/opensubdiv/opensubdiv_topology_refiner.h
M source/blender/blenkernel/intern/CCGSubSurf.c
M source/blender/blenkernel/intern/CCGSubSurf_intern.h
M source/blender/blenkernel/intern/CCGSubSurf_opensubdiv.c
M source/blender/blenkernel/intern/CCGSubSurf_opensubdiv_converter.c
M source/blender/blenkernel/intern/subsurf_ccg.c
M source/blender/gpu/intern/gpu_codegen.c
===================================================================
diff --git a/intern/opensubdiv/opensubdiv_capi.cc b/intern/opensubdiv/opensubdiv_capi.cc
index 0463982..e04b237 100644
--- a/intern/opensubdiv/opensubdiv_capi.cc
+++ b/intern/opensubdiv/opensubdiv_capi.cc
@@ -67,6 +67,7 @@
#include <opensubdiv/osd/glPatchTable.h>
#include <opensubdiv/far/stencilTable.h>
+#include <opensubdiv/far/primvarRefiner.h>
#include "opensubdiv_intern.h"
#include "opensubdiv_topology_refiner.h"
@@ -143,11 +144,69 @@ typedef Mesh<GLVertexBuffer,
GLPatchTable> OsdGLSLComputeMesh;
#endif
+namespace {
+
+struct FVarVertex {
+ float u, v;
+ void Clear() {
+ u = v = 0.0f;
+ }
+ void AddWithWeight(FVarVertex const & src, float weight) {
+ u += weight * src.u;
+ v += weight * src.v;
+ }
+};
+
+static void interpolate_fvar_data(OpenSubdiv::Far::TopologyRefiner& refiner,
+ const std::vector<float> uvs,
+ std::vector<float> &fvar_data) {
+ /* TODO(sergey): Support all FVar channels. */
+ const int channel = 0;
+ /* TODO(sergey): Make it somehow more generic way. */
+ const int fvar_width = 2;
+
+ int max_level = refiner.GetMaxLevel(),
+ num_values_max = refiner.GetLevel(max_level).GetNumFVarValues(channel),
+ num_values_total = refiner.GetNumFVarValuesTotal(channel);
+ if (num_values_total <= 0) {
+ return;
+ }
+ OpenSubdiv::Far::PrimvarRefiner primvarRefiner(refiner);
+ if (refiner.IsUniform()) {
+ /* For uniform we only keep the highest level of refinement. */
+ fvar_data.resize(num_values_max * fvar_width);
+ std::vector<FVarVertex> buffer(num_values_total - num_values_max);
+ FVarVertex *src = &buffer[0];
+ memcpy(src, &uvs[0], uvs.size() * sizeof(float));
+ /* Defer the last level to treat separately with its alternate
+ * destination.
+ */
+ for (int level = 1; level < max_level; ++level) {
+ FVarVertex *dst = src + refiner.GetLevel(level-1).GetNumFVarValues(channel);
+ primvarRefiner.InterpolateFaceVarying(level, src, dst, channel);
+ src = dst;
+ }
+ FVarVertex *dst = reinterpret_cast<FVarVertex *>(&fvar_data[0]);
+ primvarRefiner.InterpolateFaceVarying(max_level, src, dst, channel);
+ } else {
+ /* For adaptive we keep all levels. */
+ fvar_data.resize(num_values_total * fvar_width);
+ FVarVertex *src = reinterpret_cast<FVarVertex *>(&fvar_data[0]);
+ memcpy(src, &uvs[0], uvs.size() * sizeof(float));
+ for (int level = 1; level <= max_level; ++level) {
+ FVarVertex *dst = src + refiner.GetLevel(level-1).GetNumFVarValues(channel);
+ primvarRefiner.InterpolateFaceVarying(level, src, dst, channel);
+ src = dst;
+ }
+ }
+}
+
+} // namespace
+
struct OpenSubdiv_GLMesh *openSubdiv_createOsdGLMeshFromTopologyRefiner(
OpenSubdiv_TopologyRefinerDescr *topology_refiner,
int evaluator_type,
- int level,
- int /*subdivide_uvs*/)
+ int level)
{
using OpenSubdiv::Far::TopologyRefiner;
@@ -213,11 +272,21 @@ struct OpenSubdiv_GLMesh *openSubdiv_createOsdGLMeshFromTopologyRefiner(
gl_mesh->descriptor = (OpenSubdiv_GLMeshDescr *) mesh;
gl_mesh->topology_refiner = topology_refiner;
+ if (refiner->GetNumFVarChannels() > 0) {
+ std::vector<float> fvar_data;
+ interpolate_fvar_data(*refiner, topology_refiner->uvs, fvar_data);
+ openSubdiv_osdGLAllocFVar(gl_mesh, &fvar_data[0]);
+ }
+ else {
+ gl_mesh->fvar_data = NULL;
+ }
+
return gl_mesh;
}
void openSubdiv_deleteOsdGLMesh(struct OpenSubdiv_GLMesh *gl_mesh)
{
+ openSubdiv_osdGLDestroyFVar(gl_mesh);
switch (gl_mesh->evaluator_type) {
#define CHECK_EVALUATOR_TYPE(type, class) \
case OPENSUBDIV_EVALUATOR_ ## type: \
diff --git a/intern/opensubdiv/opensubdiv_capi.h b/intern/opensubdiv/opensubdiv_capi.h
index b40505b..0410083 100644
--- a/intern/opensubdiv/opensubdiv_capi.h
+++ b/intern/opensubdiv/opensubdiv_capi.h
@@ -32,16 +32,19 @@ extern "C" {
// Types declaration.
struct OpenSubdiv_GLMesh;
+struct OpenSubdiv_GLMeshFVarData;
struct OpenSubdiv_TopologyRefinerDescr;
typedef struct OpenSubdiv_GLMesh OpenSubdiv_GLMesh;
#ifdef __cplusplus
struct OpenSubdiv_GLMeshDescr;
+
typedef struct OpenSubdiv_GLMesh {
int evaluator_type;
OpenSubdiv_GLMeshDescr *descriptor;
OpenSubdiv_TopologyRefinerDescr *topology_refiner;
+ OpenSubdiv_GLMeshFVarData *fvar_data;
} OpenSubdiv_GLMesh;
#endif
@@ -66,8 +69,7 @@ enum {
OpenSubdiv_GLMesh *openSubdiv_createOsdGLMeshFromTopologyRefiner(
struct OpenSubdiv_TopologyRefinerDescr *topology_refiner,
int evaluator_type,
- int level,
- int subdivide_uvs);
+ int level);
void openSubdiv_deleteOsdGLMesh(OpenSubdiv_GLMesh *gl_mesh);
unsigned int openSubdiv_getOsdGLMeshPatchIndexBuffer(
@@ -129,8 +131,7 @@ void openSubdiv_evaluateVarying(OpenSubdiv_EvaluatorDescr *evaluator_descr,
*
* TODO(sergey): Some of the stuff could be initialized once for all meshes.
*/
-void openSubdiv_osdGLMeshDisplayPrepare(int use_osd_glsl,
- int active_uv_index);
+void openSubdiv_osdGLMeshDisplayPrepare(int use_osd_glsl);
/* Draw specified patches. */
void openSubdiv_osdGLMeshDisplay(OpenSubdiv_GLMesh *gl_mesh,
@@ -138,6 +139,10 @@ void openSubdiv_osdGLMeshDisplay(OpenSubdiv_GLMesh *gl_mesh,
int start_patch,
int num_patches);
+void openSubdiv_osdGLAllocFVar(OpenSubdiv_GLMesh *gl_mesh,
+ const float *fvar_data);
+void openSubdiv_osdGLDestroyFVar(OpenSubdiv_GLMesh *gl_mesh);
+
/* ** Utility functions ** */
int openSubdiv_supportGPUDisplay(void);
int openSubdiv_getAvailableEvaluators(void);
diff --git a/intern/opensubdiv/opensubdiv_converter.cc b/intern/opensubdiv/opensubdiv_converter.cc
index e718d6b..e6c8985 100644
--- a/intern/opensubdiv/opensubdiv_converter.cc
+++ b/intern/opensubdiv/opensubdiv_converter.cc
@@ -488,6 +488,39 @@ inline void TopologyRefinerFactory<OpenSubdiv_Converter>::reportInvalidTopology(
printf("OpenSubdiv Error: %s\n", msg);
}
+template <>
+inline bool TopologyRefinerFactory<OpenSubdiv_Converter>::assignFaceVaryingTopology(
+ TopologyRefiner& refiner,
+ const OpenSubdiv_Converter& conv)
+{
+ if (conv.get_num_uv_layers(&conv) <= 0) {
+ /* No UV maps, we can skip any face-varying data. */
+ return true;
+ }
+ /* Count overall number of UV data.
+ * NOTE: We only do single UV layer here, and we don't "merge" loops
+ * together as it is done in OpenSubdiv examples.x
+ */
+ const int num_faces = getNumBaseFaces(refiner);
+ int num_uvs = 0;
+ for (int face = 0; face < num_faces; ++face) {
+ IndexArray face_verts = getBaseFaceVertices(refiner, face);
+ num_uvs += face_verts.size();
+ }
+ /* Fill in actual UV offsets. */
+ const int channel = createBaseFVarChannel(refiner, num_uvs);
+ for (int face = 0, offset = 0; face < num_faces; ++face) {
+ Far::IndexArray dst_face_uvs = getBaseFaceFVarValues(refiner,
+ face,
+ channel);
+ for (int corner = 0; corner < dst_face_uvs.size(); ++corner) {
+ dst_face_uvs[corner] = offset;
+ ++offset;
+ }
+ }
+ return true;
+}
+
} /* namespace Far */
} /* namespace OPENSUBDIV_VERSION */
} /* namespace OpenSubdiv */
@@ -508,6 +541,33 @@ OpenSubdiv::Sdc::SchemeType get_capi_scheme_type(OpenSubdiv_SchemeType type)
return OpenSubdiv::Sdc::SCHEME_CATMARK;
}
+static void import_fvar_data(OpenSubdiv_TopologyRefinerDescr *result,
+ const OpenSubdiv_Converter& conv)
+{
+ const int num_layers = conv.get_num_uv_layers(&conv),
+ num_faces = conv.get_num_faces(&conv);
+ /* Pre-allocate values in one go. */
+ int num_fvar_values = 0;
+ for (int layer = 0; layer < num_layers; ++layer) {
+ num_fvar_values = result->osd_refiner->GetNumFVarValuesTotal();
+ }
+ result->uvs.resize(num_fvar_values * 2);
+ /* Fill in all channels. */
+ for (int layer = 0, offset = 0; layer < num_layers; ++layer) {
+ for (int face = 0; face < num_faces; ++face) {
+ const int num_verts = conv.get_num_face_verts(&conv, face);
+ for (int vert = 0; vert < num_verts; ++vert) {
+ float uv[2];
+ conv.get_face_corner_uv(&conv, face, vert, uv);
+ result->uvs[offset++] = uv[0];
+ result->uvs[offset++] = uv[1];
+ }
+ }
+ /* TODO(sergey): Currently we only support first layer only. */
+ break;
+ }
+}
+
} /* namespace */
struct OpenSubdiv_TopologyRefinerDescr *openSubdiv_createTopologyRefinerDescr(
@@ -536,6 +596,18 @@ struct OpenSubdiv_TopologyRefinerDescr *openSubdiv_createTopologyRefinerDescr(
TopologyRefinerFactory<OpenSubdiv_Converter>::Create(
*converter,
topology_options);
+
+ if (result->osd_refiner->GetNumFVarChannels() > 0) {
+ /* Import face varrying data now since later we wouldn't have
+ * access to the converter.
+ *
+ * TODO(sergey): This is so-called "for now", for until we'll
+ * find better way to plug OSD to Blender or for until something
+ * happens inside of OSD API.
+ */
+ import_fvar_data(result, *converter);
+ }
+
return result;
}
diff --git a/intern/opensubdiv/opensubdiv_converter_capi.h b/intern/opensubdiv/opensubdiv_converter_capi.h
index 1f09fa0..47c8dab 100644
--- a/intern/opensubdiv/opensubdiv_converter_capi.h
+++ b/intern/opensubdiv/opensubdiv_converter_capi.h
@@ -83,6 +83,14 @@ typedef struct OpenSubdiv_Converter {
int vert,
int *vert_faces);
+ /* Face-varying data. */
+
+ int (*get_num_uv_layers)(const OpenSubdiv_Converter *converter);
+ void (*get_face_corner_uv)(const OpenSubdiv_Converter *converter,
+ int face,
+ int corner,
+ float r_uv[2]);
+
void (*free_user_data)(const OpenSubdiv_Converter *converter);
void *user_data;
} OpenSubdiv_Converter;
diff --git a/intern/opensubdiv/opensubdiv_gpu_capi.cc b/intern/opensubdiv/opensubdiv_gpu_capi.cc
index 63cf390..84984e8 100644
--- a/intern/opensubdiv/opensubdiv_gpu_capi.cc
+++ b/intern/opensubdiv/opensubdiv_gpu_capi.cc
@@ -42,6 +42,10 @@
#include <opensubdiv/osd/cpuGLVertexBuffer.h>
#include <o
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list