[Bf-blender-cvs] [f1e6847] master: OpenSubdiv: Support for multiple materials in solid shading mode

Sergey Sharybin noreply at git.blender.org
Tue Aug 25 15:14:56 CEST 2015


Commit: f1e68474e051667b85ac804bded8fa2c8e0ff374
Author: Sergey Sharybin
Date:   Tue Aug 25 15:05:28 2015 +0200
Branches: master
https://developer.blender.org/rBf1e68474e051667b85ac804bded8fa2c8e0ff374

OpenSubdiv: Support for multiple materials in solid shading mode

Implementation is less optimal compared to non-opensubdiv drawing but
it is now as good as we can do it without affecting on how patches are
being created by OpenSubdiv.

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

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	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.h b/intern/opensubdiv/opensubdiv_capi.h
index c86e739..c09d032 100644
--- a/intern/opensubdiv/opensubdiv_capi.h
+++ b/intern/opensubdiv/opensubdiv_capi.h
@@ -135,8 +135,8 @@ void openSubdiv_osdGLMeshDisplayPrepare(int use_osd_glsl,
 /* Draw patches which corresponds to a given partition. */
 void openSubdiv_osdGLMeshDisplay(OpenSubdiv_GLMesh *gl_mesh,
                                  int fill_quads,
-                                 int start_partition,
-                                 int num_partitions);
+                                 int start_patch,
+                                 int num_patches);
 
 /* ** Utility functions ** */
 int openSubdiv_supportGPUDisplay(void);
diff --git a/intern/opensubdiv/opensubdiv_converter.cc b/intern/opensubdiv/opensubdiv_converter.cc
index 0988074..5d43caf 100644
--- a/intern/opensubdiv/opensubdiv_converter.cc
+++ b/intern/opensubdiv/opensubdiv_converter.cc
@@ -574,6 +574,17 @@ int openSubdiv_topologyRefinerGetNumFaces(
 	return base_level.GetNumFaces();
 }
 
+int openSubdiv_topologyRefinerGetNumFaceVerts(
+        const OpenSubdiv_TopologyRefinerDescr *topology_refiner,
+        int face)
+{
+	using OpenSubdiv::Far::TopologyLevel;
+	using OpenSubdiv::Far::TopologyRefiner;
+	const TopologyRefiner *refiner = (const TopologyRefiner *)topology_refiner;
+	const TopologyLevel &base_level = refiner->GetLevel(0);
+	return base_level.GetFaceVertices(face).size();
+}
+
 int openSubdiv_topologyRefnerCompareConverter(
         const OpenSubdiv_TopologyRefinerDescr *topology_refiner,
         OpenSubdiv_Converter *converter)
diff --git a/intern/opensubdiv/opensubdiv_converter_capi.h b/intern/opensubdiv/opensubdiv_converter_capi.h
index 7c96d3d..ac1e830 100644
--- a/intern/opensubdiv/opensubdiv_converter_capi.h
+++ b/intern/opensubdiv/opensubdiv_converter_capi.h
@@ -94,7 +94,7 @@ void openSubdiv_deleteTopologyRefinerDescr(
         OpenSubdiv_TopologyRefinerDescr *topology_refiner);
 
 /* TODO(sergey): Those calls are not strictly related on conversion.
- * needs some dedicated fiel perhaps.
+ * needs some dedicated file perhaps.
  */
 
 int openSubdiv_topologyRefinerGetSubdivLevel(
@@ -109,6 +109,10 @@ int openSubdiv_topologyRefinerGetNumEdges(
 int openSubdiv_topologyRefinerGetNumFaces(
         const OpenSubdiv_TopologyRefinerDescr *topology_refiner);
 
+int openSubdiv_topologyRefinerGetNumFaceVerts(
+        const OpenSubdiv_TopologyRefinerDescr *topology_refiner,
+        int face);
+
 int openSubdiv_topologyRefnerCompareConverter(
         const OpenSubdiv_TopologyRefinerDescr *topology_refiner,
         OpenSubdiv_Converter *converter);
diff --git a/intern/opensubdiv/opensubdiv_gpu_capi.cc b/intern/opensubdiv/opensubdiv_gpu_capi.cc
index 9498f93..803265d 100644
--- a/intern/opensubdiv/opensubdiv_gpu_capi.cc
+++ b/intern/opensubdiv/opensubdiv_gpu_capi.cc
@@ -575,46 +575,41 @@ static void finish_patchDraw(bool fill_quads)
 	}
 }
 
-#if 0
 static void draw_partition_patches_range(PartitionedGLMeshInterface *mesh,
                                          GLuint program,
-                                         int start_partition,
-                                         int num_partitions)
+                                         int start_patch,
+                                         int num_patches)
 {
-	/* Glue patches from all partitions in the range together. */
-	int patch_index = -1, start_element = -1, num_elements = 0;
-	for (int partition = start_partition;
-	     partition < start_partition + num_partitions;
-	     ++partition)
-	{
-		OsdDrawContext::PatchArrayVector const &patches =
-		        mesh->GetPatchArrays(partition);
-		for (int i = 0; i < (int)patches.size(); ++i) {
-			OsdDrawContext::PatchArray const &patch = patches[i];
-			OsdDrawContext::PatchDescriptor desc = patch.GetDescriptor();
-			OpenSubdiv::FarPatchTables::Type patchType = desc.GetType();
-			if (patchType == OpenSubdiv::FarPatchTables::QUADS) {
-				if (start_element == -1) {
-					patch_index = patch.GetPatchIndex();
-					start_element = patch.GetVertIndex();
-				}
+	int traversed_patches = 0, num_remained_patches = num_patches;
+	const OpenSubdiv::Osd::PatchArrayVector& patches =
+	        mesh->GetPatchTable()->GetPatchArrays();
+	for (int i = 0; i < (int)patches.size(); ++i) {
+		const OpenSubdiv::Osd::PatchArray& patch = patches[i];
+		OpenSubdiv::Far::PatchDescriptor desc = patch.GetDescriptor();
+		OpenSubdiv::Far::PatchDescriptor::Type patchType = desc.GetType();
 
-				assert(patch.GetVertIndex() == start_element + num_elements);
-				num_elements += patch.GetNumIndices();
+		if (patchType == OpenSubdiv::Far::PatchDescriptor::QUADS) {
+			const int num_block_patches = patch.GetNumPatches();
+			if (start_patch >= traversed_patches &&
+			    start_patch < traversed_patches + num_block_patches)
+			{
+				const int num_control_verts = desc.GetNumControlVertices();
+				const int start_draw_patch = start_patch - traversed_patches;
+				const int num_draw_patches = std::min(num_remained_patches,
+				                                      num_block_patches - start_draw_patch);
+				perform_drawElements(program,
+				                     i,
+				                     num_draw_patches * num_control_verts,
+				                     patch.GetIndexBase() + start_draw_patch * num_control_verts);
+				num_remained_patches -= num_draw_patches;
 			}
-			else {
-				assert(!"Discontinuitied are not supported yet.");
+			if (num_remained_patches == 0) {
+				break;
 			}
+			traversed_patches += num_block_patches;
 		}
-	}
-
-	/* Perform actual draw. */
-	perform_drawElements(program,
-	                     patch_index,
-	                     num_elements,
-	                     start_element);
+    }
 }
-#endif
 
 static void draw_all_patches(PartitionedGLMeshInterface *mesh,
                              GLuint program)
@@ -637,8 +632,8 @@ static void draw_all_patches(PartitionedGLMeshInterface *mesh,
 
 void openSubdiv_osdGLMeshDisplay(OpenSubdiv_GLMesh *gl_mesh,
                                  int fill_quads,
-                                 int start_partition,
-                                 int num_partitions)
+                                 int start_patch,
+                                 int num_patches)
 {
 	PartitionedGLMeshInterface *mesh =
 		(PartitionedGLMeshInterface *)(gl_mesh->descriptor);
@@ -649,18 +644,11 @@ void openSubdiv_osdGLMeshDisplay(OpenSubdiv_GLMesh *gl_mesh,
 	/* Setup GLSL/OpenGL to draw patches in current context. */
 	GLuint program = preapre_patchDraw(mesh, fill_quads != 0);
 
-	if (start_partition != -1) {
-#if 0
+	if (start_patch != -1) {
 		draw_partition_patches_range(mesh,
 		                             program,
-		                             start_partition,
-		                             num_partitions);
-#else
-		(void)num_partitions;
-		if(start_partition == 0) {
-			draw_all_patches(mesh, program);
-		}
-#endif
+		                             start_patch,
+		                             num_patches);
 	}
 	else {
 		draw_all_patches(mesh, program);
diff --git a/source/blender/blenkernel/intern/CCGSubSurf.h b/source/blender/blenkernel/intern/CCGSubSurf.h
index e9ad4c5..a825cff 100644
--- a/source/blender/blenkernel/intern/CCGSubSurf.h
+++ b/source/blender/blenkernel/intern/CCGSubSurf.h
@@ -215,6 +215,12 @@ bool ccgSubSurf_prepareGLMesh(CCGSubSurf *ss, bool use_osd_glsl);
 void ccgSubSurf_drawGLMesh(CCGSubSurf *ss, bool fill_quads,
                            int start_partition, int num_partitions);
 
+/* Get number of base faces in a particular GL mesh. */
+int ccgSubSurf_getNumGLMeshBaseFaces(CCGSubSurf *ss);
+
+/* Get number of vertices in base faces in a particular GL mesh. */
+int ccgSubSurf_getNumGLMeshBaseFaceVerts(CCGSubSurf *ss, int face);
+
 /* Controls whether CCG are needed (Cmeaning CPU evaluation) or fully GPU compute
  * and draw is allowed.
  */
diff --git a/source/blender/blenkernel/intern/CCGSubSurf_opensubdiv.c b/source/blender/blenkernel/intern/CCGSubSurf_opensubdiv.c
index eb7c3bf..fcc4630 100644
--- a/source/blender/blenkernel/intern/CCGSubSurf_opensubdiv.c
+++ b/source/blender/blenkernel/intern/CCGSubSurf_opensubdiv.c
@@ -308,6 +308,31 @@ void ccgSubSurf_drawGLMesh(CCGSubSurf *ss, bool fill_quads,
 	}
 }
 
+int ccgSubSurf_getNumGLMeshBaseFaces(CCGSubSurf *ss)
+{
+	const OpenSubdiv_TopologyRefinerDescr *topology_refiner;
+	if (ss->osd_topology_refiner != NULL) {
+		topology_refiner = ss->osd_topology_refiner;
+	}
+	else {
+		topology_refiner = openSubdiv_getGLMeshTopologyRefiner(ss->osd_mesh);
+	}
+	return openSubdiv_topologyRefinerGetNumFaces(topology_refiner);
+}
+
+/* Get number of vertices in base faces in a particular GL mesh. */
+int ccgSubSurf_getNumGLMeshBaseFaceVerts(CCGSubSurf *ss, int face)
+{
+	const OpenSubdiv_TopologyRefinerDescr *topology_refiner;
+	if (ss->osd_topology_refiner != NULL) {
+		topology_refiner = ss->osd_topology_refiner;
+	}
+	else {
+		topology_refiner = openSubdiv_getGLMeshTopologyRefiner(ss->osd_mesh);
+	}
+	return openSubdiv_topologyRefinerGetNumFaceVerts(topology_refiner, face);
+}
+
 void ccgSubSurf_setSkipGrids(CCGSubSurf *ss, bool skip_grids)
 {
 	ss->skip_grids = skip_grids;
diff --git a/source/blender/blenkernel/intern/subsurf_ccg.c b/source/blender/blenkernel/intern/subsurf_ccg.c
index e38d62c..867065b 100644
--- a/source/blender/blenkernel/intern/subsurf_ccg.c
+++ b/source/blender/blenkernel/intern/subsurf_ccg.c
@@ -2622,24 +2622,72 @@ static void ccgDM_drawFacesSolid(DerivedMesh *dm, float (*partial_redraw_planes)
 #ifdef WITH_OPENSUBDIV
 	if (ccgdm->useGpuBackend) {
 		CCGSubSurf *ss = ccgdm->ss;
-		DMFlagMat *faceFlags = ccgdm->faceFlags;
-		int new_matnr;
-		bool draw_smooth;
+		const DMFlagMat *faceFlags = ccgdm->faceFlags;
+		const int level = ccgSubSurf_getSubdivisionLevels(ss);
+		const int face_side = 1 << level;
+		const int grid_side = 1 << (level - 1);
+		const int face_patches = face_side * face_side;
+		const int grid_patches = grid_side * grid_side;
+		const int num_base_faces = ccgSubSurf_getNumGLMeshBaseFaces(ss);
+		int i, current_patch = 0;
+		int mat_nr = -1;
+		bool draw_smooth = false;
+		int start_draw_patch = -1, num_draw_patches = 

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list