[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [24882] branches/sculpt25/source/blender/ blenkernel/intern: Sculpt: CCGSubsurf new functions to update normals, update subdivision

Brecht Van Lommel brecht at blender.org
Wed Nov 25 13:27:21 CET 2009


Revision: 24882
          http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=24882
Author:   blendix
Date:     2009-11-25 13:27:21 +0100 (Wed, 25 Nov 2009)

Log Message:
-----------
Sculpt: CCGSubsurf new functions to update normals, update subdivision
levels, copy coordinates from face grids, and stitch together face grids.

Modified Paths:
--------------
    branches/sculpt25/source/blender/blenkernel/intern/CCGSubSurf.c
    branches/sculpt25/source/blender/blenkernel/intern/CCGSubSurf.h

Modified: branches/sculpt25/source/blender/blenkernel/intern/CCGSubSurf.c
===================================================================
--- branches/sculpt25/source/blender/blenkernel/intern/CCGSubSurf.c	2009-11-25 12:04:11 UTC (rev 24881)
+++ branches/sculpt25/source/blender/blenkernel/intern/CCGSubSurf.c	2009-11-25 12:27:21 UTC (rev 24882)
@@ -1130,6 +1130,643 @@
 	return eCCGError_None;
 }
 
+#define FACE_getIFNo(f, lvl, S, x, y)		_face_getIFNo(f, lvl, S, x, y, subdivLevels, vertDataSize, normalDataOffset)
+#define FACE_calcIFNo(f, lvl, S, x, y, no)	_face_calcIFNo(f, lvl, S, x, y, no, subdivLevels, vertDataSize)
+static void ccgSubSurf__calcVertNormals(CCGSubSurf *ss,
+	CCGVert **effectedV, CCGEdge **effectedE, CCGFace **effectedF,
+	int numEffectedV, int numEffectedE, int numEffectedF) {
+	int i,ptrIdx;
+	int subdivLevels = ss->subdivLevels;
+	int lvl = ss->subdivLevels;
+	int edgeSize = 1 + (1<<lvl);
+	int gridSize = 1 + (1<<(lvl-1));
+	int normalDataOffset = ss->normalDataOffset;
+	int vertDataSize = ss->meshIFC.vertDataSize;
+
+	for (ptrIdx=0; ptrIdx<numEffectedF; ptrIdx++) {
+		CCGFace *f = (CCGFace*) effectedF[ptrIdx];
+		int S, x, y;
+
+		for (S=0; S<f->numVerts; S++) {
+			for (y=0; y<gridSize-1; y++)
+				for (x=0; x<gridSize-1; x++)
+					NormZero(FACE_getIFNo(f, lvl, S, x, y));
+
+			if (FACE_getEdges(f)[(S-1+f->numVerts)%f->numVerts]->flags&Edge_eEffected)
+				for (x=0; x<gridSize-1; x++)
+					NormZero(FACE_getIFNo(f, lvl, S, x, gridSize-1));
+			if (FACE_getEdges(f)[S]->flags&Edge_eEffected)
+				for (y=0; y<gridSize-1; y++)
+					NormZero(FACE_getIFNo(f, lvl, S, gridSize-1, y));
+			if (FACE_getVerts(f)[S]->flags&Vert_eEffected)
+				NormZero(FACE_getIFNo(f, lvl, S, gridSize-1, gridSize-1));
+		}
+	}
+
+	for (ptrIdx=0; ptrIdx<numEffectedF; ptrIdx++) {
+		CCGFace *f = (CCGFace*) effectedF[ptrIdx];
+		int S, x, y;
+		float no[3];
+
+		for (S=0; S<f->numVerts; S++) {
+			int yLimit = !(FACE_getEdges(f)[(S-1+f->numVerts)%f->numVerts]->flags&Edge_eEffected);
+			int xLimit = !(FACE_getEdges(f)[S]->flags&Edge_eEffected);
+			int yLimitNext = xLimit;
+			int xLimitPrev = yLimit;
+			
+			for (y=0; y<gridSize - 1; y++) {
+				for (x=0; x<gridSize - 1; x++) {
+					int xPlusOk = (!xLimit || x<gridSize-2);
+					int yPlusOk = (!yLimit || y<gridSize-2);
+
+					FACE_calcIFNo(f, lvl, S, x, y, no);
+
+					NormAdd(FACE_getIFNo(f, lvl, S, x+0, y+0), no);
+					if (xPlusOk)
+						NormAdd(FACE_getIFNo(f, lvl, S, x+1, y+0), no);
+					if (yPlusOk)
+						NormAdd(FACE_getIFNo(f, lvl, S, x+0, y+1), no);
+					if (xPlusOk && yPlusOk) {
+						if (x<gridSize-2 || y<gridSize-2 || FACE_getVerts(f)[S]->flags&Vert_eEffected) {
+							NormAdd(FACE_getIFNo(f, lvl, S, x+1, y+1), no);
+						}
+					}
+
+					if (x==0 && y==0) {
+						int K;
+
+						if (!yLimitNext || 1<gridSize-1)
+							NormAdd(FACE_getIFNo(f, lvl, (S+1)%f->numVerts, 0, 1), no);
+						if (!xLimitPrev || 1<gridSize-1)
+							NormAdd(FACE_getIFNo(f, lvl, (S-1+f->numVerts)%f->numVerts, 1, 0), no);
+
+						for (K=0; K<f->numVerts; K++) {
+							if (K!=S) {
+								NormAdd(FACE_getIFNo(f, lvl, K, 0, 0), no);
+							}
+						}
+					} else if (y==0) {
+						NormAdd(FACE_getIFNo(f, lvl, (S+1)%f->numVerts, 0, x), no);
+						if (!yLimitNext || x<gridSize-2)
+							NormAdd(FACE_getIFNo(f, lvl, (S+1)%f->numVerts, 0, x+1), no);
+					} else if (x==0) {
+						NormAdd(FACE_getIFNo(f, lvl, (S-1+f->numVerts)%f->numVerts, y, 0), no);
+						if (!xLimitPrev || y<gridSize-2)
+							NormAdd(FACE_getIFNo(f, lvl, (S-1+f->numVerts)%f->numVerts, y+1, 0), no);
+					}
+				}
+			}
+		}
+	}
+		// XXX can I reduce the number of normalisations here?
+	for (ptrIdx=0; ptrIdx<numEffectedV; ptrIdx++) {
+		CCGVert *v = (CCGVert*) effectedV[ptrIdx];
+		float length, *no = _vert_getNo(v, lvl, vertDataSize, normalDataOffset);
+
+		NormZero(no);
+
+		for (i=0; i<v->numFaces; i++) {
+			CCGFace *f = v->faces[i];
+			NormAdd(no, FACE_getIFNo(f, lvl, _face_getVertIndex(f,v), gridSize-1, gridSize-1));
+		}
+
+		length = sqrt(no[0]*no[0] + no[1]*no[1] + no[2]*no[2]);
+
+		if (length>FLT_EPSILON) {
+			float invLength = 1.0f/length;
+			no[0] *= invLength;
+			no[1] *= invLength;
+			no[2] *= invLength;
+		} else {
+			NormZero(no);
+		}
+
+		for (i=0; i<v->numFaces; i++) {
+			CCGFace *f = v->faces[i];
+			NormCopy(FACE_getIFNo(f, lvl, _face_getVertIndex(f,v), gridSize-1, gridSize-1), no);
+		}
+	}
+	for (ptrIdx=0; ptrIdx<numEffectedE; ptrIdx++) {
+		CCGEdge *e = (CCGEdge*) effectedE[ptrIdx];
+
+		if (e->numFaces) {
+			CCGFace *fLast = e->faces[e->numFaces-1];
+			int x;
+
+			for (i=0; i<e->numFaces-1; i++) {
+				CCGFace *f = e->faces[i];
+
+				for (x=1; x<edgeSize-1; x++) {
+					NormAdd(_face_getIFNoEdge(fLast, e, lvl, x, 0, subdivLevels, vertDataSize, normalDataOffset),
+							_face_getIFNoEdge(f, e, lvl, x, 0, subdivLevels, vertDataSize, normalDataOffset));
+				}
+			}
+
+			for (i=0; i<e->numFaces-1; i++) {
+				CCGFace *f = e->faces[i];
+
+				for (x=1; x<edgeSize-1; x++) {
+					NormCopy(_face_getIFNoEdge(f, e, lvl, x, 0, subdivLevels, vertDataSize, normalDataOffset),
+							_face_getIFNoEdge(fLast, e, lvl, x, 0, subdivLevels, vertDataSize, normalDataOffset));
+				}
+			}
+		}
+	}
+	for (ptrIdx=0; ptrIdx<numEffectedF; ptrIdx++) {
+		CCGFace *f = (CCGFace*) effectedF[ptrIdx];
+		int S;
+
+		for (S=0; S<f->numVerts; S++) {
+			NormCopy(FACE_getIFNo(f, lvl, (S+1)%f->numVerts, 0, gridSize-1),
+					 FACE_getIFNo(f, lvl, S, gridSize-1, 0));
+		}
+	}
+	for (ptrIdx=0; ptrIdx<numEffectedF; ptrIdx++) {
+		CCGFace *f = (CCGFace*) effectedF[ptrIdx];
+		int S, x, y;
+
+		for (S=0; S<f->numVerts; S++) {
+			for (y=0; y<gridSize; y++) {
+				for (x=0; x<gridSize; x++) {
+					float *no = FACE_getIFNo(f, lvl, S, x, y);
+					float length = sqrt(no[0]*no[0] + no[1]*no[1] + no[2]*no[2]);
+
+					if (length>FLT_EPSILON) {
+						float invLength = 1.0f/length;
+						no[0] *= invLength;
+						no[1] *= invLength;
+						no[2] *= invLength;
+					} else {
+						NormZero(no);
+					}
+				}
+			}
+		}
+	}
+}
+#undef FACE_getIFNo
+
+#define VERT_getCo(v, lvl)				_vert_getCo(v, lvl, vertDataSize)
+#define EDGE_getCo(e, lvl, x)			_edge_getCo(e, lvl, x, vertDataSize)
+#define FACE_getIECo(f, lvl, S, x)		_face_getIECo(f, lvl, S, x, subdivLevels, vertDataSize)
+#define FACE_getIFCo(f, lvl, S, x, y)	_face_getIFCo(f, lvl, S, x, y, subdivLevels, vertDataSize)
+static void ccgSubSurf__calcSubdivLevel(CCGSubSurf *ss,
+	CCGVert **effectedV, CCGEdge **effectedE, CCGFace **effectedF,
+	int numEffectedV, int numEffectedE, int numEffectedF, int curLvl) {
+	int subdivLevels = ss->subdivLevels;
+	int edgeSize = 1 + (1<<curLvl);
+	int gridSize = 1 + (1<<(curLvl-1));
+	int nextLvl = curLvl+1;
+	int ptrIdx, S, y, x, i, cornerIdx;
+	void *q = ss->q, *r = ss->r;
+	int vertDataSize = ss->meshIFC.vertDataSize;
+
+	for (ptrIdx=0; ptrIdx<numEffectedF; ptrIdx++) {
+		CCGFace *f = (CCGFace*) effectedF[ptrIdx];
+
+			/* interior face midpoints
+			 *  o old interior face points
+			 */
+		for (S=0; S<f->numVerts; S++) {
+			for (y=0; y<gridSize-1; y++) {
+				for (x=0; x<gridSize-1; x++) {
+					int fx = 1 + 2*x;
+					int fy = 1 + 2*y;
+					void *co0 = FACE_getIFCo(f, curLvl, S, x+0, y+0);
+					void *co1 = FACE_getIFCo(f, curLvl, S, x+1, y+0);
+					void *co2 = FACE_getIFCo(f, curLvl, S, x+1, y+1);
+					void *co3 = FACE_getIFCo(f, curLvl, S, x+0, y+1);
+					void *co = FACE_getIFCo(f, nextLvl, S, fx, fy);
+
+					VertDataAvg4(co, co0, co1, co2, co3);
+				}
+			}
+		}
+
+			/* interior edge midpoints
+			 *  o old interior edge points
+			 *  o new interior face midpoints
+			 */
+		for (S=0; S<f->numVerts; S++) {
+			for (x=0; x<gridSize-1; x++) {
+				int fx = x*2 + 1;
+				void *co0 = FACE_getIECo(f, curLvl, S, x+0);
+				void *co1 = FACE_getIECo(f, curLvl, S, x+1);
+				void *co2 = FACE_getIFCo(f, nextLvl, (S+1)%f->numVerts, 1, fx);
+				void *co3 = FACE_getIFCo(f, nextLvl, S, fx, 1);
+				void *co = FACE_getIECo(f, nextLvl, S, fx);
+				
+				VertDataAvg4(co, co0, co1, co2, co3);
+			}
+
+					/* interior face interior edge midpoints
+					 *  o old interior face points
+					 *  o new interior face midpoints
+					 */
+
+				/* vertical */
+			for (x=1; x<gridSize-1; x++) {
+				for (y=0; y<gridSize-1; y++) {
+					int fx = x*2;
+					int fy = y*2+1;
+					void *co0 = FACE_getIFCo(f, curLvl, S, x, y+0);
+					void *co1 = FACE_getIFCo(f, curLvl, S, x, y+1);
+					void *co2 = FACE_getIFCo(f, nextLvl, S, fx-1, fy);
+					void *co3 = FACE_getIFCo(f, nextLvl, S, fx+1, fy);
+					void *co = FACE_getIFCo(f, nextLvl, S, fx, fy);
+
+					VertDataAvg4(co, co0, co1, co2, co3);
+				}
+			}
+
+				/* horizontal */
+			for (y=1; y<gridSize-1; y++) {
+				for (x=0; x<gridSize-1; x++) {
+					int fx = x*2+1;
+					int fy = y*2;
+					void *co0 = FACE_getIFCo(f, curLvl, S, x+0, y);
+					void *co1 = FACE_getIFCo(f, curLvl, S, x+1, y);
+					void *co2 = FACE_getIFCo(f, nextLvl, S, fx, fy-1);
+					void *co3 = FACE_getIFCo(f, nextLvl, S, fx, fy+1);
+					void *co = FACE_getIFCo(f, nextLvl, S, fx, fy);
+
+					VertDataAvg4(co, co0, co1, co2, co3);
+				}
+			}
+		}
+	}
+
+		/* exterior edge midpoints
+		 *  o old exterior edge points
+		 *  o new interior face midpoints
+		 */
+	for (ptrIdx=0; ptrIdx<numEffectedE; ptrIdx++) {
+		CCGEdge *e = (CCGEdge*) effectedE[ptrIdx];
+		float sharpness = EDGE_getSharpness(e, curLvl);
+
+		if (_edge_isBoundary(e) || sharpness>1.0) {
+			for (x=0; x<edgeSize-1; x++) {
+				int fx = x*2 + 1;
+				void *co0 = EDGE_getCo(e, curLvl, x+0);
+				void *co1 = EDGE_getCo(e, curLvl, x+1);
+				void *co = EDGE_getCo(e, nextLvl, fx);
+
+				VertDataCopy(co, co0);
+				VertDataAdd(co, co1);
+				VertDataMulN(co, 0.5);
+			}
+		} else {
+			for (x=0; x<edgeSize-1; x++) {
+				int fx = x*2 + 1;
+				void *co0 = EDGE_getCo(e, curLvl, x+0);
+				void *co1 = EDGE_getCo(e, curLvl, x+1);
+				void *co = EDGE_getCo(e, nextLvl, fx);
+				int numFaces = 0;
+
+				VertDataCopy(q, co0);
+				VertDataAdd(q, co1);
+
+				for (i=0; i<e->numFaces; i++) {
+					CCGFace *f = e->faces[i];
+					VertDataAdd(q, _face_getIFCoEdge(f, e, nextLvl, fx, 1, subdivLevels, vertDataSize));
+					numFaces++;
+				}
+
+				VertDataMulN(q, 1.0f/(2.0f+numFaces));
+
+				VertDataCopy(r, co0);
+				VertDataAdd(r, co1);
+				VertDataMulN(r, 0.5);
+
+				VertDataCopy(co, q);
+				VertDataSub(r, q);
+				VertDataMulN(r, sharpness);
+				VertDataAdd(co, r);
+			}
+		}
+	}
+
+		/* exterior vertex shift
+		 *  o old vertex points (shifting)
+		 *  o old exterior edge points

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list