[Bf-blender-cvs] [bb22c6f] opensubdiv-modifier: OpenSubdiv: Implement topology refiner converter from Blender side

Sergey Sharybin noreply at git.blender.org
Tue Jul 14 18:54:28 CEST 2015


Commit: bb22c6f3cf7e16e0be753e9b54299e7b6b05127a
Author: Sergey Sharybin
Date:   Tue Jul 14 18:44:08 2015 +0200
Branches: opensubdiv-modifier
https://developer.blender.org/rBbb22c6f3cf7e16e0be753e9b54299e7b6b05127a

OpenSubdiv: Implement topology refiner converter from Blender side

This way it's possible to avoid having bad level calls to DM code from
intern/opensubdiv and also makes it possible to create topology refiner
from CCGSubSurf structure in the future.

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

M	intern/opensubdiv/opensubdiv_capi.cc
M	intern/opensubdiv/opensubdiv_capi.h
M	intern/opensubdiv/opensubdiv_converter.cc
A	intern/opensubdiv/opensubdiv_converter_capi.h
M	intern/opensubdiv/opensubdiv_evaluator_capi.cc
M	source/blender/blenkernel/intern/CCGSubSurf_opensubdiv.c

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

diff --git a/intern/opensubdiv/opensubdiv_capi.cc b/intern/opensubdiv/opensubdiv_capi.cc
index 683dde4..0ecac20 100644
--- a/intern/opensubdiv/opensubdiv_capi.cc
+++ b/intern/opensubdiv/opensubdiv_capi.cc
@@ -210,14 +210,15 @@ static void get_partition_per_face(OsdHbrMesh &hmesh,
 }
 #endif
 
-struct OpenSubdiv_GLMesh *openSubdiv_createOsdGLMeshFromEvaluator(
-        //OpenSubdiv_EvaluatorDescr * /*evaluator_descr*/,
-        DerivedMesh *dm,
+struct OpenSubdiv_GLMesh *openSubdiv_createOsdGLMeshFromTopologyRefiner(
+        OpenSubdiv_TopologyRefinerDescr *topology_refiner,
         int evaluator_type,
         int level,
         int /*scheme*/,
         int /*subdivide_uvs*/)
 {
+	using OpenSubdiv::Far::TopologyRefiner;
+
 	MeshBitset bits;
 	/* TODO(sergey): Adaptive subdivisions are not currently
 	 * possible because of the lack of tessellation shader.
@@ -234,7 +235,7 @@ struct OpenSubdiv_GLMesh *openSubdiv_createOsdGLMeshFromEvaluator(
 	const int num_varying_elements = 0;
 
 	GLMeshInterface *mesh = NULL;
-	OpenSubdiv::Far::TopologyRefiner *refiner = openSubdiv_topologyRefinerFromDM(dm);
+	TopologyRefiner *refiner = (TopologyRefiner*)topology_refiner;
 
 	switch(evaluator_type) {
 #define CHECK_EVALUATOR_TYPE(type, class) \
diff --git a/intern/opensubdiv/opensubdiv_capi.h b/intern/opensubdiv/opensubdiv_capi.h
index eb273c1..184c9d7 100644
--- a/intern/opensubdiv/opensubdiv_capi.h
+++ b/intern/opensubdiv/opensubdiv_capi.h
@@ -32,6 +32,7 @@ extern "C" {
 
 // Types declaration.
 struct OpenSubdiv_GLMesh;
+struct OpenSubdiv_TopologyRefinerDescr;
 
 typedef struct OpenSubdiv_GLMesh OpenSubdiv_GLMesh;
 
@@ -62,9 +63,8 @@ enum {
 };
 
 /* TODO(sergey): Re-name and avoid bad level data access. */
-struct DerivedMesh;
-OpenSubdiv_GLMesh *openSubdiv_createOsdGLMeshFromEvaluator(
-    DerivedMesh *dm,
+OpenSubdiv_GLMesh *openSubdiv_createOsdGLMeshFromTopologyRefiner(
+    struct OpenSubdiv_TopologyRefinerDescr *topology_refiner,
     int evaluator_type,
     int level,
     int scheme,
@@ -92,8 +92,9 @@ struct OpenSubdiv_EvaluatorDescr;
 typedef struct OpenSubdiv_EvaluatorDescr OpenSubdiv_EvaluatorDescr;
 
 /* TODO(sergey): Avoid bad-level data access, */
-OpenSubdiv_EvaluatorDescr *openSubdiv_createEvaluatorDescr(DerivedMesh *dm,
-                                                           int subsurf_level);
+OpenSubdiv_EvaluatorDescr *openSubdiv_createEvaluatorDescr(
+        struct OpenSubdiv_TopologyRefinerDescr *topology_refiner,
+        int subsurf_level);
 
 void openSubdiv_deleteEvaluatorDescr(OpenSubdiv_EvaluatorDescr *evaluator_descr);
 
diff --git a/intern/opensubdiv/opensubdiv_converter.cc b/intern/opensubdiv/opensubdiv_converter.cc
index b9d6760..6b60e2a 100644
--- a/intern/opensubdiv/opensubdiv_converter.cc
+++ b/intern/opensubdiv/opensubdiv_converter.cc
@@ -27,6 +27,7 @@
 
 #include <opensubdiv/far/topologyRefinerFactory.h>
 
+#include "opensubdiv_converter_capi.h"
 #include "opensubdiv_intern.h"
 
 extern "C" {
@@ -219,7 +220,176 @@ OpenSubdiv::Far::TopologyRefiner *openSubdiv_topologyRefinerFromDM(DerivedMesh *
 	TopologyRefinerFactory<OsdBlenderConverter>::Options
 	        topology_options(conv.get_type(), conv.get_options());
 #ifdef OPENSUBDIV_VALIDATE_TOPOLOGY
-       topology_options.validateFullTopology = true;
+	topology_options.validateFullTopology = true;
 #endif
 	return TopologyRefinerFactory<OsdBlenderConverter>::Create(conv, topology_options);
 }
+
+/* *********************************************************** */
+
+namespace OpenSubdiv {
+namespace OPENSUBDIV_VERSION {
+namespace Far {
+
+template <>
+inline bool TopologyRefinerFactory<OpenSubdiv_Converter>::resizeComponentTopology(
+        TopologyRefiner& refiner,
+        const OpenSubdiv_Converter& conv)
+{
+	/* Faces and face-verts */
+	const int num_faces = conv.get_num_faces(&conv);
+	setNumBaseFaces(refiner, num_faces);
+	for (int face = 0; face < num_faces; ++face) {
+		const int num_verts = conv.get_num_face_verts(&conv, face);
+		setNumBaseFaceVertices(refiner, face, num_verts);
+	}
+	/* Edges and edge-faces. */
+	const int num_edges = conv.get_num_edges(&conv);
+	setNumBaseEdges(refiner, num_edges);
+	for (int edge = 0; edge < num_edges; ++edge) {
+		const int num_edge_faces = conv.get_num_edge_faces(&conv, edge);
+		setNumBaseEdgeFaces(refiner, edge, num_edge_faces);
+	}
+	/* Vertices and vert-faces and vert-edges/ */
+	const int num_verts = conv.get_num_verts(&conv);
+	setNumBaseVertices(refiner, num_verts);
+	for (int vert = 0; vert < num_verts; ++vert) {
+		const int num_vert_edges = conv.get_num_vert_edges(&conv, vert),
+		          num_vert_faces = conv.get_num_vert_faces(&conv, vert);
+		setNumBaseVertexEdges(refiner, vert, num_vert_edges);
+		setNumBaseVertexFaces(refiner, vert, num_vert_faces);
+	}
+	return true;
+}
+
+template <>
+inline bool TopologyRefinerFactory<OpenSubdiv_Converter>::assignComponentTopology(
+	  TopologyRefiner& refiner,
+        const OpenSubdiv_Converter& conv)
+{
+	using Far::IndexArray;
+	/* Face relations. */
+	const int num_faces = conv.get_num_faces(&conv);
+	for (int face = 0; face < num_faces; ++face) {
+		IndexArray dst_face_verts = getBaseFaceVertices(refiner, face);
+		conv.get_face_verts(&conv, face, &dst_face_verts[0]);
+		IndexArray dst_face_edges = getBaseFaceEdges(refiner, face);
+		conv.get_face_edges(&conv, face, &dst_face_edges[0]);
+	}
+	/* Edge relations. */
+	const int num_edges = conv.get_num_edges(&conv);
+	for (int edge = 0; edge < num_edges; ++edge) {
+		/* Edge-vertices */
+		IndexArray dst_edge_verts = getBaseEdgeVertices(refiner, edge);
+		conv.get_edge_verts(&conv, edge, &dst_edge_verts[0]);
+		/* Edge-faces */
+		IndexArray dst_edge_faces = getBaseEdgeFaces(refiner, edge);
+		conv.get_edge_faces(&conv, edge, &dst_edge_faces[0]);
+	}
+	/* Vertex relations */
+	const int num_verts = conv.get_num_verts(&conv);
+	for (int vert = 0; vert < num_verts; ++vert) {
+		/* Vert-Faces */
+		IndexArray dst_vert_faces = getBaseVertexFaces(refiner, vert);
+		int num_vert_edges = conv.get_num_vert_edges(&conv, vert);
+		int *vert_edges = new int[num_vert_edges];
+		conv.get_vert_edges(&conv, vert, vert_edges);
+		/* Vert-Edges */
+		IndexArray dst_vert_edges = getBaseVertexEdges(refiner, vert);
+		int num_vert_faces = conv.get_num_vert_faces(&conv, vert);
+		int *vert_faces = new int[num_vert_faces];
+		conv.get_vert_faces(&conv, vert, vert_faces);
+		/* Order vertex edges and faces in a CCW order. */
+		Index face_start = INDEX_INVALID;
+		Index edge_start = INDEX_INVALID;
+		int face_vert_start = 0;
+		if (num_vert_edges == num_vert_faces) {
+			face_start  = vert_faces[0];
+			face_vert_start = findInArray(getBaseFaceVertices(refiner, face_start), vert);
+			edge_start = getBaseFaceEdges(refiner, face_start)[face_vert_start];
+		} else {
+			for (int i = 0; i < num_vert_edges; ++i) {
+				IndexArray edge_faces = getBaseEdgeFaces(refiner, vert_edges[i]);
+				if (edge_faces.size() == 1) {
+					edge_start = vert_edges[i];
+					face_start = edge_faces[0];
+					face_vert_start = findInArray(getBaseFaceVertices(refiner, face_start), vert);
+					if (edge_start == (getBaseFaceEdges(refiner, face_start)[face_vert_start])) {
+						break;
+					}
+				}
+			}
+		}
+		int edge_count_ordered = 1;
+		int face_count_ordered = 1;
+		dst_vert_faces[0] = face_start;
+		dst_vert_edges[0] = edge_start;
+		while (edge_count_ordered < num_vert_edges) {
+			IndexArray fVerts = getBaseFaceVertices(refiner, face_start);
+			IndexArray fEdges = getBaseFaceEdges(refiner, face_start);
+			int feStart = face_vert_start;
+			int feNext = feStart ? (feStart - 1) : (fVerts.size() - 1);
+			Index eNext = fEdges[feNext];
+			dst_vert_edges[edge_count_ordered++] = eNext;
+			if (face_count_ordered < num_vert_faces) {
+				IndexArray edge_faces = getBaseEdgeFaces(refiner, eNext);
+				face_start = edge_faces[edge_faces[0] == face_start];
+				face_vert_start = findInArray(getBaseFaceEdges(refiner, face_start), eNext);
+				dst_vert_faces[face_count_ordered++] = face_start;
+			}
+			edge_start = eNext;
+		}
+
+		delete [] vert_edges;
+		delete [] vert_faces;
+	}
+	populateBaseLocalIndices(refiner);
+	return true;
+};
+
+template <>
+inline bool TopologyRefinerFactory<OpenSubdiv_Converter>::assignComponentTags(
+        TopologyRefiner& refiner,
+        const OpenSubdiv_Converter& conv)
+{
+	/* TODO(sergey): Use real sharpness. */
+	int num_edges = conv.get_num_edges(&conv);
+	for (int edge = 0; edge < num_edges; ++edge) {
+		setBaseEdgeSharpness(refiner, edge, 0.0f);
+	}
+	return true;
+}
+
+template <>
+inline void TopologyRefinerFactory<OpenSubdiv_Converter>::reportInvalidTopology(
+        TopologyError /*errCode*/,
+        const char *msg,
+        const OpenSubdiv_Converter& /*mesh*/)
+{
+	printf("OpenSubdiv Error: %s\n", msg);
+}
+
+}  /* namespace Far */
+}  /* namespace OPENSUBDIV_VERSION */
+}  /* namespace OpenSubdiv */
+
+
+struct OpenSubdiv_TopologyRefinerDescr *openSubdiv_createTopologyRefinerDescr(
+        OpenSubdiv_Converter *converter)
+{
+	using OpenSubdiv::Far::TopologyRefinerFactory;
+	OpenSubdiv::Sdc::SchemeType scheme_type = OpenSubdiv::Sdc::SCHEME_CATMARK;
+	OpenSubdiv::Sdc::Options options;
+	options.SetVtxBoundaryInterpolation(OpenSubdiv::Sdc::Options::VTX_BOUNDARY_EDGE_ONLY);
+	options.SetFVarLinearInterpolation(OpenSubdiv::Sdc::Options::FVAR_LINEAR_ALL);
+
+	TopologyRefinerFactory<OpenSubdiv_Converter>::Options
+	        topology_options(scheme_type, options);
+#ifdef OPENSUBDIV_VALIDATE_TOPOLOGY
+	topology_options.validateFullTopology = true;
+#endif
+	return (struct OpenSubdiv_TopologyRefinerDescr*)
+	        TopologyRefinerFactory<OpenSubdiv_Converter>::Create(
+	                *converter,
+	                topology_options);
+}
diff --git a/intern/opensubdiv/opensubdiv_converter_capi.h b/intern/opensubdiv/opensubdiv_converter_capi.h
new file mode 100644
index 0000000..cff1fff
--- /dev/null
+++ b/intern/opensubdiv/opensubdiv_converter_capi.h
@@ -0,0 +1,87 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list