/WX enabled for MSVC in CMake too.
[blender.git] / source / blender / blenkernel / intern / multires.c
index d8c39ab..91f15d1 100644 (file)
@@ -60,35 +60,33 @@ static const int multires_side_tot[] = {0, 2, 3, 5,  9,  17,  33,   65,   129,
 static void multires_mvert_to_ss(DerivedMesh *dm, MVert *mvert);
 static void multiresModifier_disp_run(DerivedMesh *dm, Mesh *me, int invert, int add, DMGridData **oldGridData, int totlvl);
 
-DerivedMesh *get_multires_dm(Object *ob)
+DerivedMesh *get_multires_dm(Scene *scene, MultiresModifierData *mmd, Object *ob)
 {
-       Mesh *me= ob->data;
-       ModifierData *md= (ModifierData *)find_multires_modifier(ob);
+       ModifierData *md= (ModifierData *)mmd;
        ModifierTypeInfo *mti = modifierType_getInfo(md->type);
-       DerivedMesh *tdm = CDDM_from_mesh(me, ob);
+       DerivedMesh *tdm = mesh_get_derived_deform(scene, ob, CD_MASK_BAREMESH);
        DerivedMesh *dm;
 
-       CDDM_calc_normals(tdm);
        dm = mti->applyModifier(md, ob, tdm, 0, 1);
-
-       if(tdm != dm) tdm->release(tdm);
+       if (dm == tdm) {
+               dm = CDDM_copy(tdm);
+       }
 
        return dm;
 }
 
-MultiresModifierData *find_multires_modifier(Object *ob)
+MultiresModifierData *find_multires_modifier_before(Scene *scene, ModifierData *lastmd)
 {
        ModifierData *md;
-       MultiresModifierData *mmd = NULL;
 
-       for(md = ob->modifiers.first; md; md = md->next) {
+       for(md = lastmd; md; md = md->prev) {
                if(md->type == eModifierType_Multires) {
-                       mmd = (MultiresModifierData*)md;
-                       break;
+                       if (modifier_isEnabled(scene, md, eModifierMode_Realtime))
+                               return (MultiresModifierData*)md;
                }
        }
 
-       return mmd;
+       return NULL;
 }
 
 static int multires_get_level(Object *ob, MultiresModifierData *mmd, int render)
@@ -139,6 +137,14 @@ void multires_force_update(Object *ob)
        }
 }
 
+void multires_force_external_reload(Object *ob)
+{
+       Mesh *me = get_mesh(ob);
+
+       CustomData_external_reload(&me->fdata, &me->id, CD_MASK_MDISPS, me->totface);
+       multires_force_update(ob);
+}
+
 void multires_force_render_update(Object *ob)
 {
        if(ob && (ob->mode & OB_MODE_SCULPT) && modifiers_findByType(ob, eModifierType_Multires))
@@ -207,9 +213,10 @@ void multiresModifier_join(Object *ob)
 }
 #endif
 
-int multiresModifier_reshapeFromDM(Object *ob, DerivedMesh *srcdm)
+int multiresModifier_reshapeFromDM(Scene *scene, MultiresModifierData *mmd,
+                               Object *ob, DerivedMesh *srcdm)
 {
-       DerivedMesh *mrdm = get_multires_dm (ob);
+       DerivedMesh *mrdm = get_multires_dm (scene, mmd, ob);
 
        if(mrdm && srcdm && mrdm->getNumVerts(mrdm) == srcdm->getNumVerts(srcdm)) {
                multires_mvert_to_ss(mrdm, srcdm->getVertArray(srcdm));
@@ -228,21 +235,25 @@ int multiresModifier_reshapeFromDM(Object *ob, DerivedMesh *srcdm)
 }
 
 /* Returns 1 on success, 0 if the src's totvert doesn't match */
-int multiresModifier_reshape(Object *dst, Object *src)
+int multiresModifier_reshape(Scene *scene, MultiresModifierData *mmd, Object *dst, Object *src)
 {
-       DerivedMesh *srcdm = src->derivedFinal;
-       return multiresModifier_reshapeFromDM(dst, srcdm);
+       DerivedMesh *srcdm = mesh_get_derived_final(scene, src, CD_MASK_BAREMESH);
+       return multiresModifier_reshapeFromDM(scene, mmd, dst, srcdm);
 }
 
-int multiresModifier_reshapeFromDeformMod(Object *ob, ModifierData *md)
+int multiresModifier_reshapeFromDeformMod(Scene *scene, MultiresModifierData *mmd,
+                               Object *ob, ModifierData *md)
 {
        ModifierTypeInfo *mti = modifierType_getInfo(md->type);
        DerivedMesh *dm, *ndm;
        int numVerts, result;
        float (*deformedVerts)[3];
 
+       if(multires_get_level(ob, mmd, 0) == 0)
+               return 0;
+
        /* Create DerivedMesh for deformation modifier */
-       dm = get_multires_dm(ob);
+       dm = get_multires_dm(scene, mmd, ob);
        numVerts= dm->getNumVerts(dm);
        deformedVerts= MEM_callocN(sizeof(float)*numVerts*3, "multiresReshape_deformVerts");
 
@@ -256,7 +267,7 @@ int multiresModifier_reshapeFromDeformMod(Object *ob, ModifierData *md)
        dm->release(dm);
 
        /* Reshaping */
-       result= multiresModifier_reshapeFromDM(ob, ndm);
+       result= multiresModifier_reshapeFromDM(scene, mmd, ob, ndm);
 
        /* Cleanup */
        ndm->release(ndm);
@@ -264,6 +275,40 @@ int multiresModifier_reshapeFromDeformMod(Object *ob, ModifierData *md)
        return result;
 }
 
+/* reset the multires levels to match the number of mdisps */
+void multiresModifier_set_levels_from_disps(MultiresModifierData *mmd, Object *ob)
+{
+       Mesh *me = ob->data;
+       MDisps *mdisp;
+       int i;
+
+       mdisp = CustomData_get_layer(&me->fdata, CD_MDISPS);
+
+       if(mdisp) {
+               for(i = 0; i < me->totface; ++i, ++mdisp) {
+                       int S = me->mface[i].v4 ? 4 : 3;
+
+                       if(mdisp->totdisp == 0) continue;
+
+                       while(1) {
+                               int side = (1 << (mmd->totlvl-1)) + 1;
+                               int lvl_totdisp = side*side*S;
+                               if(mdisp->totdisp == lvl_totdisp)
+                                       break;
+                               else if(mdisp->totdisp < lvl_totdisp)
+                                       --mmd->totlvl;
+                               else
+                                       ++mmd->totlvl;
+                                       
+                       }
+               }
+
+               mmd->lvl = MIN2(mmd->sculptlvl, mmd->totlvl);
+               mmd->sculptlvl = MIN2(mmd->sculptlvl, mmd->totlvl);
+               mmd->renderlvl = MIN2(mmd->renderlvl, mmd->totlvl);
+       }
+}
+
 static void multires_set_tot_mdisps(Mesh *me, int lvl)
 {
        MDisps *mdisps= CustomData_get_layer(&me->fdata, CD_MDISPS);
@@ -411,7 +456,7 @@ static DerivedMesh *multires_dm_create_local(Object *ob, DerivedMesh *dm, int lv
        return multires_dm_create_from_derived(&mmd, 1, dm, ob, 0, 0);
 }
 
-static DerivedMesh *subsurf_dm_create_local(Object *ob, DerivedMesh *dm, int lvl, int simple, int optimal)
+static DerivedMesh *subsurf_dm_create_local(Object *UNUSED(ob), DerivedMesh *dm, int lvl, int simple, int optimal)
 {
        SubsurfModifierData smd;
 
@@ -451,6 +496,7 @@ void multiresModifier_subdivide(MultiresModifierData *mmd, Object *ob, int updat
 
                /* create subsurf DM from original mesh at high level */
                cddm = CDDM_from_mesh(me, NULL);
+               DM_set_only_copy(cddm, CD_MASK_BAREMESH);
                highdm = subsurf_dm_create_local(ob, cddm, totlvl, simple, 0);
 
                /* create multires DM from original mesh at low level */
@@ -552,7 +598,7 @@ static void multiresModifier_disp_run(DerivedMesh *dm, Mesh *me, int invert, int
        dGridSize = multires_side_tot[totlvl];
        dSkip = (dGridSize-1)/(gridSize-1);
 
-       #pragma omp parallel for private(i) schedule(static)
+       #pragma omp parallel for private(i) if(me->totface*gridSize*gridSize*4 >= CCG_OMP_LIMIT)
        for(i = 0; i < me->totface; ++i) {
                const int numVerts = mface[i].v4 ? 4 : 3;
                MDisps *mdisp = &mdisps[i];
@@ -646,7 +692,10 @@ static void multiresModifier_update(DerivedMesh *dm)
                        int i, j, numGrids, highGridSize, lowGridSize;
 
                        /* create subsurf DM from original mesh at high level */
-                       cddm = CDDM_from_mesh(me, NULL);
+                       if (ob->derivedDeform) cddm = CDDM_copy(ob->derivedDeform);
+                       else cddm = CDDM_from_mesh(me, NULL);
+                       DM_set_only_copy(cddm, CD_MASK_BAREMESH);
+
                        highdm = subsurf_dm_create_local(ob, cddm, totlvl, mmd->simple, 0);
 
                        /* create multires DM from original mesh and displacements */
@@ -697,7 +746,10 @@ static void multiresModifier_update(DerivedMesh *dm)
                else {
                        DerivedMesh *cddm, *subdm;
 
-                       cddm = CDDM_from_mesh(me, NULL);
+                       if (ob->derivedDeform) cddm = CDDM_copy(ob->derivedDeform);
+                       else cddm = CDDM_from_mesh(me, NULL);
+                       DM_set_only_copy(cddm, CD_MASK_BAREMESH);
+
                        subdm = subsurf_dm_create_local(ob, cddm, mmd->totlvl, mmd->simple, 0);
                        cddm->release(cddm);
 
@@ -728,7 +780,7 @@ void multires_stitch_grids(Object *ob)
 }
 
 DerivedMesh *multires_dm_create_from_derived(MultiresModifierData *mmd, int local_mmd, DerivedMesh *dm, Object *ob,
-                                                       int useRenderParams, int isFinalCalc)
+                                                       int useRenderParams, int UNUSED(isFinalCalc))
 {
        Mesh *me= ob->data;
        DerivedMesh *result;
@@ -822,7 +874,7 @@ static void old_mdisps_bilinear(float out[3], float (*disps)[3], int st, float u
        add_v3_v3v3(out, d2[0], d2[1]);
 }
 
-static void old_mdisps_rotate(int S, int newside, int oldside, int x, int y, float *u, float *v)
+static void old_mdisps_rotate(int S, int UNUSED(newside), int oldside, int x, int y, float *u, float *v)
 {
        float offset = oldside*0.5f - 0.5f;
 
@@ -1106,18 +1158,19 @@ static void multires_load_old_dm(DerivedMesh *dm, Mesh *me, int totlvl)
        MultiresLevel *lvl, *lvl1;
        Multires *mr= me->mr;
        MVert *vsrc, *vdst;
-       int src, dst;
+       unsigned int src, dst;
        int st = multires_side_tot[totlvl - 1] - 1;
        int extedgelen = multires_side_tot[totlvl] - 2;
        int *vvmap; // inorder for dst, map to src
        int crossedgelen;
-       int i, j, s, x, totvert, tottri, totquad;
+       int s, x, tottri, totquad;
+       unsigned int i, j, totvert;
 
        src = 0;
        dst = 0;
        vsrc = mr->verts;
        vdst = dm->getVertArray(dm);
-       totvert = dm->getNumVerts(dm);
+       totvert = (unsigned int)dm->getNumVerts(dm);
        vvmap = MEM_callocN(sizeof(int) * totvert, "multires vvmap");
 
        lvl1 = mr->levels.first;
@@ -1208,7 +1261,7 @@ static void multires_load_old_dm(DerivedMesh *dm, Mesh *me, int totlvl)
                fmem = MEM_callocN(sizeof(IndexNode*) * (mr->level_count-1), "multires fmem");
                emem = MEM_callocN(sizeof(IndexNode*) * (mr->level_count-1), "multires emem");
                lvl = lvl1;
-               for(i = 0; i < mr->level_count - 1; ++i) {
+               for(i = 0; i < (unsigned int)mr->level_count - 1; ++i) {
                        create_old_vert_face_map(fmap + i, fmem + i, lvl->faces, lvl->totvert, lvl->totface);
                        create_old_vert_edge_map(emap + i, emem + i, lvl->edges, lvl->totvert, lvl->totedge);
                        lvl = lvl->next;
@@ -1245,7 +1298,7 @@ static void multires_load_old_dm(DerivedMesh *dm, Mesh *me, int totlvl)
 
                lvl = lvl->next;
 
-               for(i = 0; i < mr->level_count - 1; ++i) {
+               for(i = 0; i < (unsigned int)(mr->level_count - 1); ++i) {
                        MEM_freeN(fmap[i]);
                        MEM_freeN(fmem[i]);
                        MEM_freeN(emap[i]);
@@ -1274,6 +1327,7 @@ void multires_load_old(Object *ob, Mesh *me)
        ModifierData *md;
        MultiresModifierData *mmd;
        DerivedMesh *dm, *orig;
+       CustomDataLayer *l;
        int i;
 
        /* Load original level into the mesh */
@@ -1319,6 +1373,14 @@ void multires_load_old(Object *ob, Mesh *me)
        dm->release(dm);
        orig->release(orig);
 
+       /* Copy the first-level data to the mesh */
+       for(i = 0, l = me->mr->vdata.layers; i < me->mr->vdata.totlayer; ++i, ++l)
+               CustomData_add_layer(&me->vdata, l->type, CD_REFERENCE, l->data, me->totvert);
+       for(i = 0, l = me->mr->fdata.layers; i < me->mr->fdata.totlayer; ++i, ++l)
+               CustomData_add_layer(&me->fdata, l->type, CD_REFERENCE, l->data, me->totface);
+       memset(&me->mr->vdata, 0, sizeof(CustomData));
+       memset(&me->mr->fdata, 0, sizeof(CustomData));
+
        /* Remove the old multires */
        multires_free(me->mr);
        me->mr= NULL;