Commit: 48c4b700dce0b326e1b905e133c0db1217a5cae0
Author: Sergey Sharybin
Date:   Fri Jul 22 14:46:13 2016 +0200
Branches: master
https://developer.blender.org/rB48c4b700dce0b326e1b905e133c0db1217a5cae0

OpenSubdiv: Lay down fundamentals to support multiple UV maps

===================================================================

M       intern/opensubdiv/opensubdiv_capi.cc
M       intern/opensubdiv/opensubdiv_capi.h
M       intern/opensubdiv/opensubdiv_converter.cc
M       intern/opensubdiv/opensubdiv_gpu_capi.cc
M       source/blender/blenkernel/intern/CCGSubSurf.h
M       source/blender/blenkernel/intern/CCGSubSurf_opensubdiv.c
M       source/blender/blenkernel/intern/subsurf_ccg.c

===================================================================

diff --git a/intern/opensubdiv/opensubdiv_capi.cc 
b/intern/opensubdiv/opensubdiv_capi.cc
index 9093fd8..ab90495 100644
--- a/intern/opensubdiv/opensubdiv_capi.cc
+++ b/intern/opensubdiv/opensubdiv_capi.cc
@@ -160,45 +160,49 @@ struct FVarVertex {
 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;
-       const int num_uvs = refiner.GetLevel(0).GetNumFVarValues(0) * 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 primvar_refiner(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], num_uvs * 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);
-                       primvar_refiner.InterpolateFaceVarying(level, src, dst, 
channel);
-                       src = dst;
+       const int max_level = refiner.GetMaxLevel();
+       size_t fvar_data_offset = 0, values_offset = 0;
+       for (int channel = 0; channel < refiner.GetNumFVarChannels(); 
++channel) {
+               const int num_values = refiner.GetLevel(0).GetNumFVarValues(0) 
* 2,
+                         num_values_max = 
refiner.GetLevel(max_level).GetNumFVarValues(channel),
+                         num_values_total = 
refiner.GetNumFVarValuesTotal(channel);
+               if (num_values_total <= 0) {
+                       continue;
+               }
+               OpenSubdiv::Far::PrimvarRefiner primvar_refiner(refiner);
+               if (refiner.IsUniform()) {
+                       /* For uniform we only keep the highest level of 
refinement. */
+                       fvar_data.resize(fvar_data.size() + num_values_max * 
fvar_width);
+                       std::vector<FVarVertex> buffer(num_values_total - 
num_values_max);
+                       FVarVertex *src = &buffer[0];
+                       memcpy(src, &uvs[values_offset], num_values * 
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);
+                               primvar_refiner.InterpolateFaceVarying(level, 
src, dst, channel);
+                               src = dst;
+                       }
+                       FVarVertex *dst = reinterpret_cast<FVarVertex 
*>(&fvar_data[fvar_data_offset]);
+                       primvar_refiner.InterpolateFaceVarying(max_level, src, 
dst, channel);
+                       fvar_data_offset += num_values_max * fvar_width;
+               } else {
+                       /* For adaptive we keep all levels. */
+                       fvar_data.resize(fvar_data.size() + num_values_total * 
fvar_width);
+                       FVarVertex *src = reinterpret_cast<FVarVertex 
*>(&fvar_data[fvar_data_offset]);
+                       memcpy(src, &uvs[values_offset], num_values * 
sizeof(float));
+                       for (int level = 1; level <= max_level; ++level) {
+                               FVarVertex *dst = src + 
refiner.GetLevel(level-1).GetNumFVarValues(channel);
+                               primvar_refiner.InterpolateFaceVarying(level, 
src, dst, channel);
+                               src = dst;
+                       }
+                       fvar_data_offset += num_values_total * fvar_width;
                }
-               FVarVertex *dst = reinterpret_cast<FVarVertex *>(&fvar_data[0]);
-               primvar_refiner.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], num_uvs * sizeof(float));
-               for (int level = 1; level <= max_level; ++level) {
-                       FVarVertex *dst = src + 
refiner.GetLevel(level-1).GetNumFVarValues(channel);
-                       primvar_refiner.InterpolateFaceVarying(level, src, dst, 
channel);
-                       src = dst;
-        }
-    }
+               values_offset += num_values;
+       }
 }
 
 }  // namespace
@@ -275,7 +279,7 @@ struct OpenSubdiv_GLMesh 
*openSubdiv_createOsdGLMeshFromTopologyRefiner(
        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]);
+               openSubdiv_osdGLAllocFVar(topology_refiner, gl_mesh, 
&fvar_data[0]);
        }
        else {
                gl_mesh->fvar_data = NULL;
diff --git a/intern/opensubdiv/opensubdiv_capi.h 
b/intern/opensubdiv/opensubdiv_capi.h
index 0410083..c3a1948 100644
--- a/intern/opensubdiv/opensubdiv_capi.h
+++ b/intern/opensubdiv/opensubdiv_capi.h
@@ -131,7 +131,8 @@ 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);
+void openSubdiv_osdGLMeshDisplayPrepare(int use_osd_glsl,
+                                        int active_uv_index);
 
 /* Draw specified patches. */
 void openSubdiv_osdGLMeshDisplay(OpenSubdiv_GLMesh *gl_mesh,
@@ -139,7 +140,8 @@ void openSubdiv_osdGLMeshDisplay(OpenSubdiv_GLMesh *gl_mesh,
                                  int start_patch,
                                  int num_patches);
 
-void openSubdiv_osdGLAllocFVar(OpenSubdiv_GLMesh *gl_mesh,
+void openSubdiv_osdGLAllocFVar(struct OpenSubdiv_TopologyRefinerDescr 
*topology_refiner,
+                               OpenSubdiv_GLMesh *gl_mesh,
                                const float *fvar_data);
 void openSubdiv_osdGLDestroyFVar(OpenSubdiv_GLMesh *gl_mesh);
 
diff --git a/intern/opensubdiv/opensubdiv_converter.cc 
b/intern/opensubdiv/opensubdiv_converter.cc
index f637f51..9b2fb19 100644
--- a/intern/opensubdiv/opensubdiv_converter.cc
+++ b/intern/opensubdiv/opensubdiv_converter.cc
@@ -508,12 +508,14 @@ inline bool 
TopologyRefinerFactory<TopologyRefinerData>::assignFaceVaryingTopolo
                return true;
        }
        const int num_faces = getNumBaseFaces(refiner);
+       size_t uvs_offset = 0;
        for (int layer = 0; layer < num_layers; ++layer) {
                conv.precalc_uv_layer(&conv, layer);
                const int num_uvs = conv.get_num_uvs(&conv);
                /* Fill in UV coordinates. */
-               cb_data.uvs->resize(num_uvs * 2);
-               conv.get_uvs(&conv, &cb_data.uvs->at(0));
+               cb_data.uvs->resize(cb_data.uvs->size() + num_uvs * 2);
+               conv.get_uvs(&conv, &cb_data.uvs->at(uvs_offset));
+               uvs_offset += num_uvs * 2;
                /* Fill in per-corner index of the UV. */
                const int channel = createBaseFVarChannel(refiner, num_uvs);
                for (int face = 0; face < num_faces; ++face) {
@@ -528,8 +530,6 @@ inline bool 
TopologyRefinerFactory<TopologyRefinerData>::assignFaceVaryingTopolo
                        }
                }
                conv.finish_uv_layer(&conv);
-               /* TODO(sergey): Single layer only for now. */
-               break;
        }
        return true;
 }
diff --git a/intern/opensubdiv/opensubdiv_gpu_capi.cc 
b/intern/opensubdiv/opensubdiv_gpu_capi.cc
index 8329062..a7c42ae 100644
--- a/intern/opensubdiv/opensubdiv_gpu_capi.cc
+++ b/intern/opensubdiv/opensubdiv_gpu_capi.cc
@@ -45,6 +45,7 @@
 #include "MEM_guardedalloc.h"
 
 #include "opensubdiv_capi.h"
+#include "opensubdiv_topology_refiner.h"
 
 using OpenSubdiv::Osd::GLMeshInterface;
 
@@ -82,6 +83,7 @@ typedef struct Transform {
 } Transform;
 
 static bool g_use_osd_glsl = false;
+static int g_active_uv_index = 0;
 
 static GLuint g_flat_fill_solid_program = 0;
 static GLuint g_flat_fill_texture2d_program = 0;
@@ -110,25 +112,44 @@ struct OpenSubdiv_GLMeshFVarData
                        glDeleteTextures(1, &texture_buffer);
                }
                texture_buffer = 0;
+               channel_offsets.clear();
        }
 
-       void Create(const OpenSubdiv::Far::PatchTable *patch_table,
+       void Create(const OpenSubdiv::Far::TopologyRefiner *refiner,
+                   const OpenSubdiv::Far::PatchTable *patch_table,
                    int fvar_width,
                    const float *fvar_src_data)
        {
                Release();
-               OpenSubdiv::Far::ConstIndexArray indices = 
patch_table->GetFVarValues();
 
-               // expand fvardata to per-patch array
+               /* Expand fvar data to per-patch array */
+               const int max_level = refiner->GetMaxLevel();
+               const int num_channels = patch_table->GetNumFVarChannels();
                std::vector<float> data;
-               data.reserve(indices.size() * fvar_width);
-
-               for (int fvert = 0; fvert < (int)indices.size(); ++fvert) {
-                       int index = indices[fvert] * fvar_width;
-                       for (int i = 0; i < fvar_width; ++i) {
-                               data.push_back(fvar_src_data[index++]);
+               size_t fvar_data_offset = 0;
+               channel_offsets.resize(num_channels);
+               for (int channel = 0; channel < num_channels; ++channel) {
+                       OpenSubdiv::Far::ConstIndexArray indices =
+                               patch_table->GetFVarValues(channel);
+
+                       channel_offsets[channel] = data.size();
+                       data.reserve(data.size() + indices.size() * fvar_width);
+
+                       for (int fvert = 0; fvert < (int)indices.size(); 
++fvert) {
+                               int index = indices[fvert] * fvar_width;
+                               for (int i = 0; i < fvar_width; ++i) {
+                                       
data.push_back(fvar_src_data[fvar_data_offset + index++]);
+                               }
+                       }
+                       if (refiner->IsUniform()) {
+                               const int num_values_max = 
refiner->GetLevel(max_level).GetNumFVarValues(channel);
+                               fvar_data_offset += num_values_max * fvar_width;
+                       } else {
+                               const int num_values_total = 
refiner->GetNumFVarValuesTotal(channel);
+                               fvar_data_offset += num_values_total * 
fvar_width;
                        }
                }
+
                GLuint buffer;
                glGenBuffers(1, &buffer);
                glBindBuffer(GL_ARRAY_BUFFER, buffer);
@@ -144,6 +165,7 @@ struct OpenSubdiv_GLMeshFVarData
                glDeleteBuffers(1, &buffer);
        }
        GLuint texture_buffer;
+       std::vector<size_t> channel_offsets;
 };
 
 /* TODO(sergey): This is actually duplicated code from BLI. */
@@ -415,8 +437,14 @@ void bindProgram(OpenSubdiv_GLMesh *gl_mesh, int program)
        }
 
        /* See notes below about why we use such values. */
+       /* TOO(sergey): Get proper value for FVar width. */
        glUniform1i(glGetUniformLocation(program, "osd_fvar_count"), 2);
-       glUniform1i(glGetUniformLocation(program, "osd_active_uv_offset"), 0);
+       if (gl_mesh->fvar_data->channel_offsets.size() > 0 && g_active_uv_index 
>= 0) {
+               glUniform1i

@@ Diff output truncated at 10240 characters. @@

_______________________________________________
Bf-blender-cvs mailing list
[email protected]
https://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to