[Bf-blender-cvs] [963f2ea] opensubdiv-modifier: OpenSubdiv: Ensure proper component orientation

Sergey Sharybin noreply at git.blender.org
Sat Jul 11 20:01:57 CEST 2015


Commit: 963f2ea6fe95e56dafdd11a2cbb9644a8d1e451f
Author: Sergey Sharybin
Date:   Fri Jul 10 10:39:34 2015 +0200
Branches: opensubdiv-modifier
https://developer.blender.org/rB963f2ea6fe95e56dafdd11a2cbb9644a8d1e451f

OpenSubdiv: Ensure proper component orientation

This is crucial for CPU evaluator, otherwise some unpredictable results
are coming out of evaluator. It's based on the validation code from OSD
and not optimal at all.

Need to replace with some smarter approach, which at least wouldn't
re-collect all the connectivity information for each vertex.

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

M	intern/opensubdiv/opensubdiv_converter.h
M	intern/opensubdiv/opensubdiv_evaluator_capi.cc
M	source/blender/blenkernel/intern/CCGSubSurf.c

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

diff --git a/intern/opensubdiv/opensubdiv_converter.h b/intern/opensubdiv/opensubdiv_converter.h
index 208084e..dea1e97 100644
--- a/intern/opensubdiv/opensubdiv_converter.h
+++ b/intern/opensubdiv/opensubdiv_converter.h
@@ -68,8 +68,131 @@ private:
 
 namespace OpenSubdiv {
 namespace OPENSUBDIV_VERSION {
+
+namespace Vtr {
+
+class ConstIndexArrayOwn : public ConstIndexArray
+{
+public:
+	ConstIndexArrayOwn(Index *ptr, size_type size)
+	    : ConstIndexArray(ptr, size) { }
+
+	~ConstIndexArrayOwn() {
+		delete [] this->_begin;
+	}
+};
+
+}  /* namespace Vtr */
+
 namespace Far {
 
+/* Hackish approach to ensure proper component orientation.
+ *
+ * TODO(sergey): Get rid of this, it's far too slow.
+ */
+namespace {
+
+using OpenSubdiv::Vtr::ConstIndexArrayOwn;
+
+inline int findInArray(ConstIndexArrayOwn array, Index value)
+{
+	return (int)(std::find(array.begin(), array.end(), value) - array.begin());
+}
+
+inline ConstIndexArrayOwn getVertexEdges(const OsdBlenderConverter& conv, Index vIndex)
+{
+	int num_vert_edges = conv.get_num_vert_edges(vIndex);
+	int *vert_edges = new int[num_vert_edges];
+	conv.get_vert_edges(vIndex, vert_edges);
+	return ConstIndexArrayOwn(vert_edges, num_vert_edges);
+}
+
+inline ConstIndexArrayOwn getVertexFaces(const OsdBlenderConverter& conv, Index vIndex)
+{
+	int num_vert_faces = conv.get_num_vert_faces(vIndex);
+	int *vert_faces = new int[num_vert_faces];
+	conv.get_vert_faces(vIndex, vert_faces);
+	return ConstIndexArrayOwn(vert_faces, num_vert_faces);
+}
+
+inline ConstIndexArrayOwn getFaceVertices(const OsdBlenderConverter& conv, Index fIndex)
+{
+	int num_face_verts = conv.get_num_face_verts(fIndex);
+	int *face_verts = new int[num_face_verts];
+	conv.get_face_verts(fIndex, face_verts);
+	return ConstIndexArrayOwn(face_verts, num_face_verts);
+}
+
+inline ConstIndexArrayOwn getFaceEdges(const OsdBlenderConverter& conv, Index fIndex)
+{
+	int num_face_edges = conv.get_num_face_verts(fIndex);
+	int *face_edges = new int[num_face_edges];
+	conv.get_face_edges(fIndex, face_edges);
+	return ConstIndexArrayOwn(face_edges, num_face_edges);
+}
+
+inline ConstIndexArrayOwn getEdgeFaces(const OsdBlenderConverter& conv, Index eIndex)
+{
+	int num_edge_faces = conv.get_num_edge_faces(eIndex);
+	int *edge_faces = new int[num_edge_faces];
+	conv.get_edge_faces(eIndex, edge_faces);
+	return ConstIndexArrayOwn(edge_faces, num_edge_faces);
+}
+
+void orderVertexFacesAndEdges(const OsdBlenderConverter& conv,
+                              Index vIndex,
+                              Index *vFacesOrdered,
+                              Index *vEdgesOrdered)
+{
+	ConstIndexArrayOwn vEdges = getVertexEdges(conv, vIndex);
+	ConstIndexArrayOwn vFaces = getVertexFaces(conv, vIndex);
+	int fCount = vFaces.size();
+	int eCount = vEdges.size();
+	Index fStart = INDEX_INVALID;
+	Index eStart = INDEX_INVALID;
+	int fvStart = 0;
+	if (eCount == fCount) {
+		fStart  = vFaces[0];
+		fvStart = findInArray(getFaceVertices(conv, fStart), vIndex);
+		eStart = getFaceEdges(conv, fStart)[fvStart];
+	} else {
+		for (int i = 0; i < eCount; ++i) {
+			ConstIndexArrayOwn eFaces = getEdgeFaces(conv, vEdges[i]);
+			if (eFaces.size() == 1) {
+				eStart = vEdges[i];
+				fStart = eFaces[0];
+				fvStart = findInArray(getFaceVertices(conv, fStart), vIndex);
+				if (eStart == (getFaceEdges(conv, fStart)[fvStart])) {
+					break;
+				}
+			}
+		}
+	}
+	int eCountOrdered = 1;
+	int fCountOrdered = 1;
+	vFacesOrdered[0] = fStart;
+	vEdgesOrdered[0] = eStart;
+	while (eCountOrdered < eCount) {
+		ConstIndexArrayOwn fVerts = getFaceVertices(conv, fStart);
+		ConstIndexArrayOwn fEdges = getFaceEdges(conv, fStart);
+		int feStart = fvStart;
+		int feNext  = feStart ? (feStart - 1) : (fVerts.size() - 1);
+		Index eNext = fEdges[feNext];
+		vEdgesOrdered[eCountOrdered++] = eNext;
+		if (fCountOrdered < fCount) {
+			ConstIndexArrayOwn eFaces = getEdgeFaces(conv, eNext);
+			fStart = eFaces[eFaces[0] == fStart];
+			fvStart = findInArray(getFaceEdges(conv, fStart), eNext);
+			vFacesOrdered[fCountOrdered++] = fStart;
+		}
+		eStart = eNext;
+	}
+	assert(eCountOrdered == eCount);
+	assert(fCountOrdered == fCount);
+}
+
+}  /* namespace */
+
 template <>
 inline bool TopologyRefinerFactory<OsdBlenderConverter>::resizeComponentTopology(
         TopologyRefiner& refiner,
@@ -131,10 +254,11 @@ inline bool TopologyRefinerFactory<OsdBlenderConverter>::assignComponentTopology
 	for (int vert = 0; vert < num_verts; ++vert) {
 		/* Vert-Faces */
 		IndexArray dst_vert_faces = getBaseVertexFaces(refiner, vert);
-		conv.get_vert_faces(vert, &dst_vert_faces[0]);
+		//conv.get_vert_faces(vert, &dst_vert_faces[0]);
 		/* Vert-Edges */
 		IndexArray dst_vert_edges = getBaseVertexEdges(refiner, vert);
-		conv.get_vert_edges(vert, &dst_vert_edges[0]);
+		//conv.get_vert_edges(vert, &dst_vert_edges[0]);
+		orderVertexFacesAndEdges(conv, vert, &dst_vert_faces[0], &dst_vert_edges[0]);
 	}
 	populateBaseLocalIndices(refiner);
 	return true;
diff --git a/intern/opensubdiv/opensubdiv_evaluator_capi.cc b/intern/opensubdiv/opensubdiv_evaluator_capi.cc
index 788e4e5..05973f4 100644
--- a/intern/opensubdiv/opensubdiv_evaluator_capi.cc
+++ b/intern/opensubdiv/opensubdiv_evaluator_capi.cc
@@ -364,7 +364,7 @@ OpenSubdiv_EvaluatorDescr *openSubdiv_createEvaluatorDescr(DerivedMesh *dm,
 	float *g_positions = new float[3 * num_coarse_verts];
 	conv.get_coarse_verts(g_positions);
 	eval_output->UpdateData(&g_positions[0], 0, num_coarse_verts);
-	delete g_positions;
+	delete [] g_positions;
 	eval_output->Refine();
 
 	OpenSubdiv::Far::PatchMap *patch_map = new PatchMap(*patch_table);
@@ -375,11 +375,9 @@ OpenSubdiv_EvaluatorDescr *openSubdiv_createEvaluatorDescr(DerivedMesh *dm,
 	evaluator_descr->patch_map = patch_map;
 
 	/* TOOD(sergey): Look into whether w've got duplicated stencils arrays. */
-	/*
 	delete varying_stencils;
-	delete patch_table;
+	// delete patch_table;
 	delete vertex_stencils;
-	*/
 
 	delete refiner;
 
diff --git a/source/blender/blenkernel/intern/CCGSubSurf.c b/source/blender/blenkernel/intern/CCGSubSurf.c
index a537978..32a90bd 100644
--- a/source/blender/blenkernel/intern/CCGSubSurf.c
+++ b/source/blender/blenkernel/intern/CCGSubSurf.c
@@ -1527,7 +1527,7 @@ static void ccgSubSurf__calcVertNormals(CCGSubSurf *ss,
 	int normalDataOffset = ss->normalDataOffset;
 	int vertDataSize = ss->meshIFC.vertDataSize;
 
-//#pragma omp parallel for private(ptrIdx) if (numEffectedF * edgeSize * edgeSize * 4 >= CCG_OMP_LIMIT)
+#pragma omp parallel for private(ptrIdx) if (numEffectedF * edgeSize * edgeSize * 4 >= CCG_OMP_LIMIT)
 	for (ptrIdx = 0; ptrIdx < numEffectedF; ptrIdx++) {
 		CCGFace *f = (CCGFace *) effectedF[ptrIdx];
 		int S, x, y;
@@ -1661,7 +1661,7 @@ static void ccgSubSurf__calcVertNormals(CCGSubSurf *ss,
 		}
 	}
 
-//#pragma omp parallel for private(ptrIdx) if (numEffectedF * edgeSize * edgeSize * 4 >= CCG_OMP_LIMIT)
+#pragma omp parallel for private(ptrIdx) if (numEffectedF * edgeSize * edgeSize * 4 >= CCG_OMP_LIMIT)
 	for (ptrIdx = 0; ptrIdx < numEffectedF; ptrIdx++) {
 		CCGFace *f = (CCGFace *) effectedF[ptrIdx];
 		int S, x, y;
@@ -1728,7 +1728,7 @@ static void ccgSubSurf__calcSubdivLevel(CCGSubSurf *ss,
 	int vertDataSize = ss->meshIFC.vertDataSize;
 	float *q = ss->q, *r = ss->r;
 
-//#pragma omp parallel for private(ptrIdx) if (numEffectedF * edgeSize * edgeSize * 4 >= CCG_OMP_LIMIT)
+#pragma omp parallel for private(ptrIdx) if (numEffectedF * edgeSize * edgeSize * 4 >= CCG_OMP_LIMIT)
 	for (ptrIdx = 0; ptrIdx < numEffectedF; ptrIdx++) {
 		CCGFace *f = (CCGFace *) effectedF[ptrIdx];
 		int S, x, y;
@@ -2075,17 +2075,17 @@ static void ccgSubSurf__calcSubdivLevel(CCGSubSurf *ss,
 		}
 	}
 
-//#pragma omp parallel private(ptrIdx) if (numEffectedF * edgeSize * edgeSize * 4 >= CCG_OMP_LIMIT)
+#pragma omp parallel private(ptrIdx) if (numEffectedF * edgeSize * edgeSize * 4 >= CCG_OMP_LIMIT)
 	{
 		float *q, *r;
 
-//#pragma omp critical
+#pragma omp critical
 		{
 			q = MEM_mallocN(ss->meshIFC.vertDataSize, "CCGSubsurf q");
 			r = MEM_mallocN(ss->meshIFC.vertDataSize, "CCGSubsurf r");
 		}
 
-//#pragma omp for schedule(static)
+#pragma omp for schedule(static)
 		for (ptrIdx = 0; ptrIdx < numEffectedF; ptrIdx++) {
 			CCGFace *f = (CCGFace *) effectedF[ptrIdx];
 			int S, x, y;
@@ -2176,7 +2176,7 @@ static void ccgSubSurf__calcSubdivLevel(CCGSubSurf *ss,
 			}
 		}
 
-//#pragma omp critical
+#pragma omp critical
 		{
 			MEM_freeN(q);
 			MEM_freeN(r);
@@ -2188,14 +2188,14 @@ static void ccgSubSurf__calcSubdivLevel(CCGSubSurf *ss,
 	gridSize = ccg_gridsize(nextLvl);
 	cornerIdx = gridSize - 1;
 
-//#pragma omp parallel for private(i) if (numEffectedF * edgeSize * edgeSize * 4 >= CCG_OMP_LIMIT)
+#pragma omp parallel for private(i) if (numEffectedF * edgeSize * edgeSize * 4 >= CCG_OMP_LIMIT)
 	for (i = 0; i < numEffectedE; i++) {
 		CCGEdge *e = effectedE[i];
 		VertDataCopy(EDGE_getCo(e, nextLvl, 0), VERT_getCo(e->v0, nextLvl), ss);
 		VertDataCopy(EDGE_getCo(e, nextLvl, edgeSize - 1), VERT_getCo(e->v1, nextLvl), ss);
 	}
 
-//#pragma omp parallel for private(i) if (numEffectedF * edgeSize * edgeSize * 4 >= CCG_OMP_LIMIT)
+#pragma omp parallel for private(i) if (numEffectedF * edgeSize * edgeSize * 4 >= CCG_OMP_LIMIT)
 	for (i = 0; i < numEffectedF; i++) {
 		CCGFace *f = effectedF[i];
 		int S, x;
@@ -2336,7 +2336,7 @@ static void ccgSubSurf__updateGLMeshCoords(CCGSubSurf *ss)
 
 	positions = MEM_callocN(2 * sizeof(*positions) * num_basis_verts,
 	                        "OpenSubdiv coarse points");
-//#pragma omp parallel for
+#pragma omp parallel for
 	for (i = 0; i < ss->vMap->curSize; i++) {
 		CCGVert *v = (CCGVert *) ss->vMap->buckets[i];
 		for (; v; v = v->next) {
@@ -2714,7 +2714,7 @@ static void opensubdiv_updateCoarsePositions(CCGSubSurf *ss)
 		positions = MEM_callocN(3 * sizeof(float) * num_basis_verts,
 		                        "OpenSubdiv coarse points");
 	}
-//#pragma omp parallel for
+#pragma omp parallel for
 	for (i = 0; i < ss->vMap->curSize; i++) {
 		CCGVert *v = (CCGVert *) ss->vMap->buckets[i];
 		for (; v; v = v->next) {
@@ -2747,7 +2747,7 @@ static void opensubdiv_updateCoarseNormals(CCGSubSurf *ss)
 		return;
 	}
 
-//#pragma omp p

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list