[Bf-blender-cvs] [48c4b70] master: OpenSubdiv: Lay down fundamentals to support multiple UV maps

Sergey Sharybin noreply at git.blender.org
Fri Jul 22 14:56:34 CEST 2016


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. @@




More information about the Bf-blender-cvs mailing list