Sculpt Branch:
authorBrecht Van Lommel <brechtvanlommel@pandora.be>
Thu, 3 Dec 2009 18:35:37 +0000 (18:35 +0000)
committerBrecht Van Lommel <brechtvanlommel@pandora.be>
Thu, 3 Dec 2009 18:35:37 +0000 (18:35 +0000)
* Multithread parts of multires and subsurf. Only loops working on
  face grid data and do no memory allocation have been multithreaded,
  others would be more complicated.
* Force some CCGSubsurf functions to be inlined, gives a small overall
  speedup in subsurf code.

* Fix sculpting not working correct with transformed objects.
* Fix a few cases of "spikes" on lower level multires levels. There's
  still cases where it happens, usually on boundary cornders. The
  problem is that in such cases the limit surfaces can be very different
  from the low res surface, so the tangent space is very different too..
* Fix crash deleting multires higher levels with level set to 0.
* Fix crashes that happened sometimes when adding faces in editmode.

source/blender/blenkernel/BKE_DerivedMesh.h
source/blender/blenkernel/BKE_subsurf.h
source/blender/blenkernel/intern/CCGSubSurf.c
source/blender/blenkernel/intern/multires.c
source/blender/blenkernel/intern/subsurf_ccg.c
source/blender/editors/sculpt_paint/sculpt.c
source/blender/gpu/intern/gpu_buffers.c

index bcafc4c..1f6a8f9 100644 (file)
@@ -151,6 +151,7 @@ struct DerivedMesh {
        int (*getGridSize)(DerivedMesh *dm);
        DMGridData **(*getGridData)(DerivedMesh *dm);
        DMGridAdjacency *(*getGridAdjacency)(DerivedMesh *dm);
+       int *(*getGridOffset)(DerivedMesh *dm);
 
        /* Iterate over each mapped vertex in the derived mesh, calling the
         * given function with the original vert and the mapped vert's new
index 7b8adb7..0a18850 100644 (file)
@@ -73,6 +73,7 @@ typedef struct CCGDerivedMesh {
 
        struct DMGridData **gridData;
        struct DMGridAdjacency *gridAdjacency;
+       int *gridOffset;
        struct _CCGFace **gridFaces;
 
        struct {
index 7c2c6d4..cc2bd53 100644 (file)
@@ -8,6 +8,12 @@
 
 #include "BLO_sys_types.h" // for intptr_t support
 
+#ifdef _MSC_VER
+#define CCG_INLINE __inline
+#else
+#define CCG_INLINE inline
+#endif
+
 /* used for normalize_v3 in BLI_math_vector
  * float.h's FLT_EPSILON causes trouble with subsurf normals - campbell */
 #define EPSILON (1.0e-35f)
@@ -523,19 +529,19 @@ static CCGFace *_face_new(CCGFaceHDL fHDL, CCGVert **verts, CCGEdge **edges, int
        return f;
 }
 
-static void *_face_getIECo(CCGFace *f, int lvl, int S, int x, int levels, int dataSize) {
+static CCG_INLINE void *_face_getIECo(CCGFace *f, int lvl, int S, int x, int levels, int dataSize) {
        int maxGridSize = 1 + (1<<(levels-1));
        int spacing = 1<<(levels-lvl);
        byte *gridBase = FACE_getCenterData(f) + dataSize*(1 + S*(maxGridSize + maxGridSize*maxGridSize));
        return &gridBase[dataSize*x*spacing];
 }
-static void *_face_getIFCo(CCGFace *f, int lvl, int S, int x, int y, int levels, int dataSize) {
+static CCG_INLINE void *_face_getIFCo(CCGFace *f, int lvl, int S, int x, int y, int levels, int dataSize) {
        int maxGridSize = 1 + (1<<(levels-1));
        int spacing = 1<<(levels-lvl);
        byte *gridBase = FACE_getCenterData(f) + dataSize*(1 + S*(maxGridSize + maxGridSize*maxGridSize));
        return &gridBase[dataSize*(maxGridSize + (y*maxGridSize + x)*spacing)];
 }
-static float *_face_getIFNo(CCGFace *f, int lvl, int S, int x, int y, int levels, int dataSize, int normalDataOffset) {
+static CCG_INLINE float *_face_getIFNo(CCGFace *f, int lvl, int S, int x, int y, int levels, int dataSize, int normalDataOffset) {
        int maxGridSize = 1 + (1<<(levels-1));
        int spacing = 1<<(levels-lvl);
        byte *gridBase = FACE_getCenterData(f) + dataSize*(1 + S*(maxGridSize + maxGridSize*maxGridSize));
@@ -548,7 +554,7 @@ static int _face_getVertIndex(CCGFace *f, CCGVert *v) {
                        return i;
        return -1;
 }
-static void *_face_getIFCoEdge(CCGFace *f, CCGEdge *e, int lvl, int eX, int eY, int levels, int dataSize) {
+static CCG_INLINE void *_face_getIFCoEdge(CCGFace *f, CCGEdge *e, int lvl, int eX, int eY, int levels, int dataSize) {
        int maxGridSize = 1 + (1<<(levels-1));
        int spacing = 1<<(levels-lvl);
        int S, x, y, cx, cy;
@@ -1146,9 +1152,11 @@ static void ccgSubSurf__calcVertNormals(CCGSubSurf *ss,
        int normalDataOffset = ss->normalDataOffset;
        int vertDataSize = ss->meshIFC.vertDataSize;
 
+       #pragma omp parallel for private(ptrIdx) schedule(static)
        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++) {
                        for (y=0; y<gridSize-1; y++)
@@ -1164,12 +1172,6 @@ static void ccgSubSurf__calcVertNormals(CCGSubSurf *ss,
                        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);
@@ -1275,18 +1277,16 @@ static void ccgSubSurf__calcVertNormals(CCGSubSurf *ss,
                        }
                }
        }
+
+       #pragma omp parallel for private(ptrIdx) schedule(static)
        for (ptrIdx=0; ptrIdx<numEffectedF; ptrIdx++) {
                CCGFace *f = (CCGFace*) effectedF[ptrIdx];
-               int S;
+               int S, x, y;
 
                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++) {
@@ -1320,12 +1320,14 @@ static void ccgSubSurf__calcSubdivLevel(CCGSubSurf *ss,
        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 ptrIdx, cornerIdx, i;
        int vertDataSize = ss->meshIFC.vertDataSize;
+       void *q = ss->q, *r = ss->r;
 
+       #pragma omp parallel for private(ptrIdx) schedule(static)
        for (ptrIdx=0; ptrIdx<numEffectedF; ptrIdx++) {
                CCGFace *f = (CCGFace*) effectedF[ptrIdx];
+               int S, x, y;
 
                        /* interior face midpoints
                         *  o old interior face points
@@ -1406,6 +1408,7 @@ static void ccgSubSurf__calcSubdivLevel(CCGSubSurf *ss,
        for (ptrIdx=0; ptrIdx<numEffectedE; ptrIdx++) {
                CCGEdge *e = (CCGEdge*) effectedE[ptrIdx];
                float sharpness = EDGE_getSharpness(e, curLvl);
+               int x, j;
 
                if (_edge_isBoundary(e) || sharpness>1.0) {
                        for (x=0; x<edgeSize-1; x++) {
@@ -1429,8 +1432,8 @@ static void ccgSubSurf__calcSubdivLevel(CCGSubSurf *ss,
                                VertDataCopy(q, co0);
                                VertDataAdd(q, co1);
 
-                               for (i=0; i<e->numFaces; i++) {
-                                       CCGFace *f = e->faces[i];
+                               for (j=0; j<e->numFaces; j++) {
+                                       CCGFace *f = e->faces[j];
                                        VertDataAdd(q, _face_getIFCoEdge(f, e, nextLvl, fx, 1, subdivLevels, vertDataSize));
                                        numFaces++;
                                }
@@ -1460,10 +1463,10 @@ static void ccgSubSurf__calcSubdivLevel(CCGSubSurf *ss,
                void *nCo = VERT_getCo(v, nextLvl);
                int sharpCount = 0, allSharp = 1;
                float avgSharpness = 0.0;
-               int seam = VERT_seam(v), seamEdges = 0;
+               int j, seam = VERT_seam(v), seamEdges = 0;
 
-               for (i=0; i<v->numEdges; i++) {
-                       CCGEdge *e = v->edges[i];
+               for (j=0; j<v->numEdges; j++) {
+                       CCGEdge *e = v->edges[j];
                        float sharpness = EDGE_getSharpness(e, curLvl);
 
                        if (seam && _edge_isBoundary(e))
@@ -1493,8 +1496,8 @@ static void ccgSubSurf__calcSubdivLevel(CCGSubSurf *ss,
                        int numBoundary = 0;
 
                        VertDataZero(r);
-                       for (i=0; i<v->numEdges; i++) {
-                               CCGEdge *e = v->edges[i];
+                       for (j=0; j<v->numEdges; j++) {
+                               CCGEdge *e = v->edges[j];
                                if (_edge_isBoundary(e)) {
                                        VertDataAdd(r, _edge_getCoVert(e, v, curLvl, 1, vertDataSize));
                                        numBoundary++;
@@ -1510,15 +1513,15 @@ static void ccgSubSurf__calcSubdivLevel(CCGSubSurf *ss,
                        int numEdges = 0, numFaces = 0;
 
                        VertDataZero(q);
-                       for (i=0; i<v->numFaces; i++) {
-                               CCGFace *f = v->faces[i];
+                       for (j=0; j<v->numFaces; j++) {
+                               CCGFace *f = v->faces[j];
                                VertDataAdd(q, FACE_getIFCo(f, nextLvl, _face_getVertIndex(f,v), cornerIdx, cornerIdx));
                                numFaces++;
                        }
                        VertDataMulN(q, 1.0f/numFaces);
                        VertDataZero(r);
-                       for (i=0; i<v->numEdges; i++) {
-                               CCGEdge *e = v->edges[i];
+                       for (j=0; j<v->numEdges; j++) {
+                               CCGEdge *e = v->edges[j];
                                VertDataAdd(r, _edge_getCoVert(e, v, curLvl, 1,vertDataSize));
                                numEdges++;
                        }
@@ -1540,8 +1543,8 @@ static void ccgSubSurf__calcSubdivLevel(CCGSubSurf *ss,
                                allSharp = 1;
                        }
 
-                       for (i=0; i<v->numEdges; i++) {
-                               CCGEdge *e = v->edges[i];
+                       for (j=0; j<v->numEdges; j++) {
+                               CCGEdge *e = v->edges[j];
                                float sharpness = EDGE_getSharpness(e, curLvl);
 
                                if (seam) {
@@ -1585,6 +1588,7 @@ static void ccgSubSurf__calcSubdivLevel(CCGSubSurf *ss,
                float sharpness = EDGE_getSharpness(e, curLvl);
                int sharpCount = 0;
                float avgSharpness = 0.0;
+               int x, j;
 
                if (sharpness!=0.0f) {
                        sharpCount = 2;
@@ -1622,8 +1626,8 @@ static void ccgSubSurf__calcSubdivLevel(CCGSubSurf *ss,
                                VertDataZero(r);
                                VertDataAdd(r, EDGE_getCo(e, curLvl, x-1));
                                VertDataAdd(r, EDGE_getCo(e, curLvl, x+1));
-                               for (i=0; i<e->numFaces; i++) {
-                                       CCGFace *f = e->faces[i];
+                               for (j=0; j<e->numFaces; j++) {
+                                       CCGFace *f = e->faces[j];
                                        VertDataAdd(q, _face_getIFCoEdge(f, e, nextLvl, fx-1, 1, subdivLevels, vertDataSize));
                                        VertDataAdd(q, _face_getIFCoEdge(f, e, nextLvl, fx+1, 1, subdivLevels, vertDataSize));
 
@@ -1654,52 +1658,91 @@ static void ccgSubSurf__calcSubdivLevel(CCGSubSurf *ss,
                }
        }
 
-       for (ptrIdx=0; ptrIdx<numEffectedF; ptrIdx++) {
-               CCGFace *f = (CCGFace*) effectedF[ptrIdx];
+       #pragma omp parallel private(ptrIdx)
+       {
+               void *q, *r;
 
-                       /* interior center point shift
-                        *  o old face center point (shifting)
-                        *  o old interior edge points
-                        *  o new interior face midpoints
-                        */
-               VertDataZero(q);
-               for (S=0; S<f->numVerts; S++) {
-                       VertDataAdd(q, FACE_getIFCo(f, nextLvl, S, 1, 1));
-               }
-               VertDataMulN(q, 1.0f/f->numVerts);
-               VertDataZero(r);
-               for (S=0; S<f->numVerts; S++) {
-                       VertDataAdd(r, FACE_getIECo(f, curLvl, S, 1));
+               #pragma omp critical
+               {
+                       q = CCGSUBSURF_alloc(ss, ss->meshIFC.vertDataSize);
+                       r = CCGSUBSURF_alloc(ss, ss->meshIFC.vertDataSize);
                }
-               VertDataMulN(r, 1.0f/f->numVerts);
 
-               VertDataMulN(FACE_getCenterData(f), f->numVerts-2.0f);
-               VertDataAdd(FACE_getCenterData(f), q);
-               VertDataAdd(FACE_getCenterData(f), r);
-               VertDataMulN(FACE_getCenterData(f), 1.0f/f->numVerts);
+               #pragma omp for schedule(static)
+               for (ptrIdx=0; ptrIdx<numEffectedF; ptrIdx++) {
+                       CCGFace *f = (CCGFace*) effectedF[ptrIdx];
+                       int S, x, y;
 
-               for (S=0; S<f->numVerts; S++) {
-                               /* interior face shift
-                                *  o old interior face point (shifting)
-                                *  o new interior edge midpoints
+                               /* interior center point shift
+                                *  o old face center point (shifting)
+                                *  o old interior edge points
                                 *  o new interior face midpoints
                                 */
-                       for (x=1; x<gridSize-1; x++) {
-                               for (y=1; y<gridSize-1; y++) {
+                       VertDataZero(q);
+                       for (S=0; S<f->numVerts; S++) {
+                               VertDataAdd(q, FACE_getIFCo(f, nextLvl, S, 1, 1));
+                       }
+                       VertDataMulN(q, 1.0f/f->numVerts);
+                       VertDataZero(r);
+                       for (S=0; S<f->numVerts; S++) {
+                               VertDataAdd(r, FACE_getIECo(f, curLvl, S, 1));
+                       }
+                       VertDataMulN(r, 1.0f/f->numVerts);
+
+                       VertDataMulN(FACE_getCenterData(f), f->numVerts-2.0f);
+                       VertDataAdd(FACE_getCenterData(f), q);
+                       VertDataAdd(FACE_getCenterData(f), r);
+                       VertDataMulN(FACE_getCenterData(f), 1.0f/f->numVerts);
+
+                       for (S=0; S<f->numVerts; S++) {
+                                       /* interior face shift
+                                        *  o old interior face point (shifting)
+                                        *  o new interior edge midpoints
+                                        *  o new interior face midpoints
+                                        */
+                               for (x=1; x<gridSize-1; x++) {
+                                       for (y=1; y<gridSize-1; y++) {
+                                               int fx = x*2;
+                                               int fy = y*2;
+                                               void *co = FACE_getIFCo(f, curLvl, S, x, y);
+                                               void *nCo = FACE_getIFCo(f, nextLvl, S, fx, fy);
+                                               
+                                               VertDataAvg4(q, FACE_getIFCo(f, nextLvl, S, fx-1, fy-1),
+                                                       FACE_getIFCo(f, nextLvl, S, fx+1, fy-1),
+                                                       FACE_getIFCo(f, nextLvl, S, fx+1, fy+1),
+                                                       FACE_getIFCo(f, nextLvl, S, fx-1, fy+1));
+
+                                               VertDataAvg4(r, FACE_getIFCo(f, nextLvl, S, fx-1, fy+0),
+                                                       FACE_getIFCo(f, nextLvl, S, fx+1, fy+0),
+                                                       FACE_getIFCo(f, nextLvl, S, fx+0, fy-1),
+                                                       FACE_getIFCo(f, nextLvl, S, fx+0, fy+1));
+
+                                               VertDataCopy(nCo, co);
+                                               VertDataSub(nCo, q);
+                                               VertDataMulN(nCo, 0.25f);
+                                               VertDataAdd(nCo, r);
+                                       }
+                               }
+
+                                       /* interior edge interior shift
+                                        *  o old interior edge point (shifting)
+                                        *  o new interior edge midpoints
+                                        *  o new interior face midpoints
+                                        */
+                               for (x=1; x<gridSize-1; x++) {
                                        int fx = x*2;
-                                       int fy = y*2;
-                                       void *co = FACE_getIFCo(f, curLvl, S, x, y);
-                                       void *nCo = FACE_getIFCo(f, nextLvl, S, fx, fy);
+                                       void *co = FACE_getIECo(f, curLvl, S, x);
+                                       void *nCo = FACE_getIECo(f, nextLvl, S, fx);
                                        
-                                       VertDataAvg4(q, FACE_getIFCo(f, nextLvl, S, fx-1, fy-1),
-                                               FACE_getIFCo(f, nextLvl, S, fx+1, fy-1),
-                                               FACE_getIFCo(f, nextLvl, S, fx+1, fy+1),
-                                               FACE_getIFCo(f, nextLvl, S, fx-1, fy+1));
+                                       VertDataAvg4(q, FACE_getIFCo(f, nextLvl, (S+1)%f->numVerts, 1, fx-1),
+                                               FACE_getIFCo(f, nextLvl, (S+1)%f->numVerts, 1, fx+1),
+                                               FACE_getIFCo(f, nextLvl, S, fx+1, +1),
+                                               FACE_getIFCo(f, nextLvl, S, fx-1, +1));
 
-                                       VertDataAvg4(r, FACE_getIFCo(f, nextLvl, S, fx-1, fy+0),
-                                               FACE_getIFCo(f, nextLvl, S, fx+1, fy+0),
-                                               FACE_getIFCo(f, nextLvl, S, fx+0, fy-1),
-                                               FACE_getIFCo(f, nextLvl, S, fx+0, fy+1));
+                                       VertDataAvg4(r, FACE_getIECo(f, nextLvl, S, fx-1),
+                                               FACE_getIECo(f, nextLvl, S, fx+1),
+                                               FACE_getIFCo(f, nextLvl, (S+1)%f->numVerts, 1, fx),
+                                               FACE_getIFCo(f, nextLvl, S, fx1));
 
                                        VertDataCopy(nCo, co);
                                        VertDataSub(nCo, q);
@@ -1707,32 +1750,12 @@ static void ccgSubSurf__calcSubdivLevel(CCGSubSurf *ss,
                                        VertDataAdd(nCo, r);
                                }
                        }
+               }
 
-                               /* interior edge interior shift
-                                *  o old interior edge point (shifting)
-                                *  o new interior edge midpoints
-                                *  o new interior face midpoints
-                                */
-                       for (x=1; x<gridSize-1; x++) {
-                               int fx = x*2;
-                               void *co = FACE_getIECo(f, curLvl, S, x);
-                               void *nCo = FACE_getIECo(f, nextLvl, S, fx);
-                               
-                               VertDataAvg4(q, FACE_getIFCo(f, nextLvl, (S+1)%f->numVerts, 1, fx-1),
-                                       FACE_getIFCo(f, nextLvl, (S+1)%f->numVerts, 1, fx+1),
-                                       FACE_getIFCo(f, nextLvl, S, fx+1, +1),
-                                       FACE_getIFCo(f, nextLvl, S, fx-1, +1));
-
-                               VertDataAvg4(r, FACE_getIECo(f, nextLvl, S, fx-1),
-                                       FACE_getIECo(f, nextLvl, S, fx+1),
-                                       FACE_getIFCo(f, nextLvl, (S+1)%f->numVerts, 1, fx),
-                                       FACE_getIFCo(f, nextLvl, S, fx, 1));
-
-                               VertDataCopy(nCo, co);
-                               VertDataSub(nCo, q);
-                               VertDataMulN(nCo, 0.25f);
-                               VertDataAdd(nCo, r);
-                       }
+               #pragma omp critical
+               {
+                       CCGSUBSURF_free(ss, q);
+                       CCGSUBSURF_free(ss, r);
                }
        }
 
@@ -1740,13 +1763,19 @@ static void ccgSubSurf__calcSubdivLevel(CCGSubSurf *ss,
        edgeSize = 1 + (1<<(nextLvl));
        gridSize = 1 + (1<<((nextLvl)-1));
        cornerIdx = gridSize-1;
+
+       #pragma omp parallel for private(i) schedule(static)
        for (i=0; i<numEffectedE; i++) {
                CCGEdge *e = effectedE[i];
                VertDataCopy(EDGE_getCo(e, nextLvl, 0), VERT_getCo(e->v0, nextLvl));
                VertDataCopy(EDGE_getCo(e, nextLvl, edgeSize-1), VERT_getCo(e->v1, nextLvl));
        }
+
+       #pragma omp parallel for private(i) schedule(static)
        for (i=0; i<numEffectedF; i++) {
                CCGFace *f = effectedF[i];
+               int S, x;
+
                for (S=0; S<f->numVerts; S++) {
                        CCGEdge *e = FACE_getEdges(f)[S];
                        CCGEdge *prevE = FACE_getEdges(f)[(S+f->numVerts-1)%f->numVerts];
index a709b45..69659db 100644 (file)
@@ -248,39 +248,45 @@ void multiresModifier_del_levels(struct MultiresModifierData *mmd, struct Object
        int lvl = multires_get_level(ob, mmd, 0);
        int levels = mmd->totlvl - lvl;
        MDisps *mdisps;
-       
+
        CustomData_external_read(&me->fdata, CD_MASK_MDISPS, me->totface);
        mdisps= CustomData_get_layer(&me->fdata, CD_MDISPS);
 
        multires_force_update(ob);
 
        if(mdisps && levels > 0 && direction == 1) {
-               int nsize = multires_side_tot[lvl];
-               int hsize = multires_side_tot[mmd->totlvl];
-               int i;
+               if(lvl > 0) {
+                       int nsize = multires_side_tot[lvl];
+                       int hsize = multires_side_tot[mmd->totlvl];
+                       int i;
 
-               for(i = 0; i < me->totface; ++i) {
-                       MDisps *mdisp= &mdisps[i];
-                       float (*disps)[3], (*ndisps)[3], (*hdisps)[3];
-                       int nvert = (me->mface[i].v4)? 4: 3;
-                       int totdisp = multires_grid_tot[lvl]*nvert;
-                       int S;
+                       for(i = 0; i < me->totface; ++i) {
+                               MDisps *mdisp= &mdisps[i];
+                               float (*disps)[3], (*ndisps)[3], (*hdisps)[3];
+                               int nvert = (me->mface[i].v4)? 4: 3;
+                               int totdisp = multires_grid_tot[lvl]*nvert;
+                               int S;
 
-                       disps = MEM_callocN(sizeof(float) * 3 * totdisp, "multires disps");
+                               disps = MEM_callocN(sizeof(float) * 3 * totdisp, "multires disps");
 
-                       ndisps = disps;
-                       hdisps = mdisp->disps;
+                               ndisps = disps;
+                               hdisps = mdisp->disps;
 
-                       for(S = 0; S < nvert; S++) {
-                               multires_copy_grid(ndisps, hdisps, nsize, hsize);
+                               for(S = 0; S < nvert; S++) {
+                                       multires_copy_grid(ndisps, hdisps, nsize, hsize);
 
-                               ndisps += nsize*nsize;
-                               hdisps += hsize*hsize;
-                       }
+                                       ndisps += nsize*nsize;
+                                       hdisps += hsize*hsize;
+                               }
 
-                       MEM_freeN(mdisp->disps);
-                       mdisp->disps = disps;
-                       mdisp->totdisp = totdisp;
+                               MEM_freeN(mdisp->disps);
+                               mdisp->disps = disps;
+                               mdisp->totdisp = totdisp;
+                       }
+               }
+               else {
+                       CustomData_external_remove(&me->fdata, CD_MDISPS, me->totface);
+                       CustomData_free_layer_active(&me->fdata, CD_MDISPS, me->totface);
                }
        }
 
@@ -409,105 +415,27 @@ void multiresModifier_subdivide(MultiresModifierData *mmd, Object *ob, int updat
        multires_set_tot_level(ob, mmd, totlvl);
 }
 
-static void grid_adjacent_rotate(int rotation, int gridSize, int *x, int *y)
-{
-       /* we rotate (rotation * 90°) counterclockwise around center */
-       int nx, ny;
-
-       switch(rotation) {
-               case 0: nx = *x; ny = *y; break;
-               case 1: nx = *y; ny = *x; break;
-               case 2: nx = *x; ny = *y; break; //gridSize - 1 - *x; ny = gridSize - 1 - *y; break;
-               case 3: nx = *y; ny = *x; break;
-       }
-
-       *x = nx;
-       *y = ny;
-}
-
-static void grid_adjacent_jump(DMGridAdjacency *adj, int gridSize, int *index, int *x, int *y)
-{
-       if(*x < 0) {
-               if(adj->index[3] == -1) {
-                       /* no adjacent grid, clamp */
-                       *x = 0;
-               }
-               else {
-                       /* jump to adjacent grid */
-                       *index = adj->index[3];
-                       *x += gridSize;
-                       grid_adjacent_rotate(adj->rotation[3], gridSize, x, y);
-               }
-       }
-       else if(*x >= gridSize) {
-               if(adj->index[1] == -1) {
-                       /* no adjacent grid, take a step back */
-                       *x = gridSize - 1;
-               }
-               else {
-                       /* jump to adjacent grid */
-                       *index = adj->index[1];
-                       *x -= gridSize;
-                       grid_adjacent_rotate(adj->rotation[1], gridSize, x, y);
-               }
-       }
-       else if(*y < 0) {
-               if(adj->index[0] == -1) {
-                       /* no adjacent grid, clamp */
-                       *y = 0;
-               }
-               else {
-                       /* jump to adjacent grid */
-                       *index = adj->index[0];
-                       *y += gridSize;
-                       grid_adjacent_rotate(adj->rotation[0], gridSize, x, y);
-               }
-       }
-       else if(*y >= gridSize) {
-               if(adj->index[2] == -1) {
-                       /* no adjacent grid, take a step back */
-                       *y = gridSize - 1;
-               }
-               else {
-                       /* jump to adjacent grid */
-                       *index = adj->index[2];
-                       *y -= gridSize;
-                       grid_adjacent_rotate(adj->rotation[2], gridSize, x, y);
-               }
-       }
-}
-
-static void grid_tangent(DMGridAdjacency *adj, int gridSize, int index, int x, int y, int axis, DMGridData **gridData, float t[3])
+static void grid_tangent(int gridSize, int index, int x, int y, int axis, DMGridData **gridData, float t[3])
 {
-       int jindex = index, jx = x, jy = y;
-
        if(axis == 0) {
-               if(adj->index[1] == -1 && x == gridSize - 1) {
-                       if(adj->index[2] == -1 && y == gridSize - 1)
+               if(x == gridSize - 1) {
+                       if(y == gridSize - 1)
                                sub_v3_v3v3(t, gridData[index][x + gridSize*(y - 1)].co, gridData[index][x - 1 + gridSize*(y - 1)].co);
                        else
                                sub_v3_v3v3(t, gridData[index][x + gridSize*y].co, gridData[index][x - 1 + gridSize*y].co);
                }
-               else {
-                       jx += 1;
-                       grid_adjacent_jump(adj, gridSize, &jindex, &jx, &jy);
-                       sub_v3_v3v3(t, gridData[jindex][jx + gridSize*jy].co, gridData[index][x + gridSize*y].co);
-               }
+               else
+                       sub_v3_v3v3(t, gridData[index][x + 1 + gridSize*y].co, gridData[index][x + gridSize*y].co);
        }
        else if(axis == 1) {
-               if(adj->index[2] == -1 && y == gridSize - 1) {
-                       if(adj->index[1] == -1 && x == gridSize - 1) {
+               if(y == gridSize - 1) {
+                       if(x == gridSize - 1)
                                sub_v3_v3v3(t, gridData[index][x - 1 + gridSize*y].co, gridData[index][x - 1 + gridSize*(y - 1)].co);
-                       }
-                       else {
+                       else
                                sub_v3_v3v3(t, gridData[index][x + gridSize*y].co, gridData[index][x + gridSize*(y - 1)].co);
-                       }
-               }
-               else {
-                       jy += 1;
-                       grid_adjacent_jump(adj, gridSize, &jindex, &jx, &jy);
-                       sub_v3_v3v3(t, gridData[jindex][jx + gridSize*jy].co, gridData[index][x + gridSize*y].co);
                }
+               else
+                       sub_v3_v3v3(t, gridData[index][x + gridSize*(y + 1)].co, gridData[index][x + gridSize*y].co);
        }
 }
 
@@ -515,28 +443,36 @@ static void multiresModifier_disp_run(DerivedMesh *dm, Mesh *me, int invert, int
 {
        CCGDerivedMesh *ccgdm = (CCGDerivedMesh*)dm;
        DMGridData **gridData, **subGridData;
-       DMGridAdjacency *gridAdjacency;
        MFace *mface = me->mface;
        MDisps *mdisps = CustomData_get_layer(&me->fdata, CD_MDISPS);
-       int i, S, x, y, numGrids, gIndex, gridSize, dGridSize, dSkip;
+       int *gridOffset;
+       int i, numGrids, gridSize, dGridSize, dSkip;
 
        numGrids = dm->getNumGrids(dm);
        gridSize = dm->getGridSize(dm);
        gridData = dm->getGridData(dm);
-       gridAdjacency = dm->getGridAdjacency(dm);
+       gridOffset = dm->getGridOffset(dm);
        subGridData = (oldGridData)? oldGridData: gridData;
 
        dGridSize = multires_side_tot[totlvl];
        dSkip = (dGridSize-1)/(gridSize-1);
 
-       for(gIndex = 0, i = 0; i < me->totface; ++i) {
+       #pragma omp parallel for private(i) schedule(static)
+       for(i = 0; i < me->totface; ++i) {
                const int numVerts = mface[i].v4 ? 4 : 3;
                MDisps *mdisp = &mdisps[i];
+               int S, x, y, gIndex = gridOffset[i];
+
+               /* when adding new faces in edit mode, need to allocate disps */
+               if(!mdisp->disps)
+               #pragma omp critical
+               {
+                       multires_reallocate_mdisps(me, mdisps, totlvl);
+               }
 
                for(S = 0; S < numVerts; ++S, ++gIndex) {
                        DMGridData *grid = gridData[gIndex];
                        DMGridData *subgrid = subGridData[gIndex];
-                       DMGridAdjacency *adj = &gridAdjacency[gIndex];
                        float (*dispgrid)[3] = &mdisp->disps[S*dGridSize*dGridSize];
 
                        for(y = 0; y < gridSize; y++) {
@@ -548,12 +484,16 @@ static void multiresModifier_disp_run(DerivedMesh *dm, Mesh *me, int invert, int
                                        float mat[3][3], tx[3], ty[3], disp[3], d[3];
 
                                        /* construct tangent space matrix */
-                                       grid_tangent(adj, gridSize, gIndex, x, y, 0, subGridData, tx);
+                                       grid_tangent(gridSize, gIndex, x, y, 0, subGridData, tx);
                                        normalize_v3(tx);
 
-                                       grid_tangent(adj, gridSize, gIndex, x, y, 1, subGridData, ty);
+                                       grid_tangent(gridSize, gIndex, x, y, 1, subGridData, ty);
                                        normalize_v3(ty);
 
+                                       //mul_v3_fl(tx, 1.0f/(gridSize-1));
+                                       //mul_v3_fl(ty, 1.0f/(gridSize-1));
+                                       //cross_v3_v3v3(no, tx, ty);
+
                                        column_vectors_to_mat3(mat, tx, ty, no);
 
                                        if(!invert) {
index 716229e..c9d8467 100644 (file)
@@ -1894,6 +1894,7 @@ static void ccgDM_release(DerivedMesh *dm) {
                if(ccgdm->gridFaces) MEM_freeN(ccgdm->gridFaces);
                if(ccgdm->gridData) MEM_freeN(ccgdm->gridData);
                if(ccgdm->gridAdjacency) MEM_freeN(ccgdm->gridAdjacency);
+               if(ccgdm->gridOffset) MEM_freeN(ccgdm->gridOffset);
                if(ccgdm->freeSS) ccgSubSurf_free(ccgdm->ss);
                MEM_freeN(ccgdm->edgeFlags);
                MEM_freeN(ccgdm->faceFlags);
@@ -2112,7 +2113,7 @@ static void ccgdm_create_grids(DerivedMesh *dm)
        ccgdm->gridData = gridData;
        ccgdm->gridFaces = gridFaces;
        ccgdm->gridAdjacency = gridAdjacency;
-       MEM_freeN(gridOffset);
+       ccgdm->gridOffset = gridOffset;
 }
 
 static DMGridData **ccgDM_getGridData(DerivedMesh *dm)
@@ -2131,6 +2132,14 @@ static DMGridAdjacency *ccgDM_getGridAdjacency(DerivedMesh *dm)
        return ccgdm->gridAdjacency;
 }
 
+static int *ccgDM_getGridOffset(DerivedMesh *dm)
+{
+       CCGDerivedMesh *ccgdm= (CCGDerivedMesh*)dm;
+
+       ccgdm_create_grids(dm);
+       return ccgdm->gridOffset;
+}
+
 static struct PBVH *ccgDM_getPBVH(Object *ob, DerivedMesh *dm)
 {
        CCGDerivedMesh *ccgdm= (CCGDerivedMesh*)dm;
@@ -2209,6 +2218,7 @@ static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss,
        ccgdm->dm.getGridSize = ccgDM_getGridSize;
        ccgdm->dm.getGridData = ccgDM_getGridData;
        ccgdm->dm.getGridAdjacency = ccgDM_getGridAdjacency;
+       ccgdm->dm.getGridOffset = ccgDM_getGridOffset;
        ccgdm->dm.getPBVH = ccgDM_getPBVH;
 
        ccgdm->dm.getVertCos = ccgdm_getVertCos;
index 7644751..b39a291 100644 (file)
@@ -1726,12 +1726,17 @@ int sculpt_stroke_get_location(bContext *C, struct PaintStroke *stroke, float ou
        SculptSession *ss= vc->obact->sculpt;
        StrokeCache *cache= ss->cache;
        float ray_start[3], ray_normal[3];
+       float obimat[4][4];
        float mval[2] = {mouse[0] - vc->ar->winrct.xmin,
                         mouse[1] - vc->ar->winrct.ymin};
        SculptRaycastData srd;
 
        viewray(vc->ar, vc->v3d, mval, ray_start, ray_normal);
 
+       invert_m4_m4(obimat, ss->ob->obmat);
+       mul_m4_v3(obimat, ray_start);
+       mul_mat3_m4_v3(obimat, ray_normal);
+
        srd.ss = vc->obact->sculpt;
        srd.ray_start = ray_start;
        srd.ray_normal = ray_normal;
index 9db7f9b..4c55f75 100644 (file)
@@ -379,14 +379,10 @@ void GPU_drawobject_free( DerivedMesh *dm )
        dm->drawObject = 0;
 }
 
-/* Convenience struct for building the VBO.
-   TODO: check that (lack-of) padding is OK,
-   also check performance of short vs float for normals */
+/* Convenience struct for building the VBO. */
 typedef struct {
        float co[3];
        short no[3];
-       
-       char pad[14];
 } VertexBufferFormat;
 
 typedef struct {