diff options
Diffstat (limited to 'source/blender/editors/object')
-rw-r--r-- | source/blender/editors/object/SConscript | 28 | ||||
-rw-r--r-- | source/blender/editors/object/object_add.c | 24 | ||||
-rw-r--r-- | source/blender/editors/object/object_bake.c | 876 | ||||
-rw-r--r-- | source/blender/editors/object/object_edit.c | 4 | ||||
-rw-r--r-- | source/blender/editors/object/object_transform.c | 2 | ||||
-rw-r--r-- | source/blender/editors/object/object_vgroup.c | 182 |
6 files changed, 194 insertions, 922 deletions
diff --git a/source/blender/editors/object/SConscript b/source/blender/editors/object/SConscript index b53ea549853..df51198df92 100644 --- a/source/blender/editors/object/SConscript +++ b/source/blender/editors/object/SConscript @@ -1,4 +1,30 @@ -#!/usr/bin/python +#!/usr/bin/env python +# +# ***** 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 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# The Original Code is Copyright (C) 2006, Blender Foundation +# All rights reserved. +# +# The Original Code is: all of this file. +# +# Contributor(s): Nathan Letwory. +# +# ***** END GPL LICENSE BLOCK ***** + Import ('env') sources = env.Glob('*.c') diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c index 7c4a547debc..b21b77e4e34 100644 --- a/source/blender/editors/object/object_add.c +++ b/source/blender/editors/object/object_add.c @@ -146,7 +146,7 @@ void ED_object_location_from_view(bContext *C, float loc[3]) { View3D *v3d = CTX_wm_view3d(C); Scene *scene = CTX_data_scene(C); - float *cursor; + const float *cursor; cursor = give_cursor(scene, v3d); @@ -186,7 +186,7 @@ void ED_object_base_init_transform(bContext *C, Base *base, const float loc[3], /* Uses context to figure out transform for primitive. * Returns standard diameter. */ float ED_object_new_primitive_matrix(bContext *C, Object *obedit, - const float loc[3], const float rot[3], float primmat[][4], + const float loc[3], const float rot[3], float primmat[4][4], int apply_diameter) { Scene *scene = CTX_data_scene(C); @@ -936,6 +936,8 @@ static int object_delete_exec(bContext *C, wmOperator *op) { Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); + wmWindowManager *wm = CTX_wm_manager(C); + wmWindow *win; const short use_global = RNA_boolean_get(op->ptr, "use_global"); if (CTX_data_edit_object(C)) @@ -967,12 +969,22 @@ static int object_delete_exec(bContext *C, wmOperator *op) } CTX_DATA_END; - DAG_scene_sort(bmain, scene); + /* delete has to handle all open scenes */ + flag_listbase_ids(&bmain->scene, LIB_DOIT, 1); + for (win = wm->windows.first; win; win = win->next) { + scene = win->screen->scene; + + if (scene->id.flag & LIB_DOIT) { + scene->id.flag &= ~LIB_DOIT; + + DAG_scene_sort(bmain, scene); + + WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene); + WM_event_add_notifier(C, NC_SCENE | ND_LAYER_CONTENT, scene); + } + } DAG_ids_flush_update(bmain, 0); - WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene); - WM_event_add_notifier(C, NC_SCENE | ND_LAYER_CONTENT, scene); - return OPERATOR_FINISHED; } diff --git a/source/blender/editors/object/object_bake.c b/source/blender/editors/object/object_bake.c index e144c38a350..8b40379f88d 100644 --- a/source/blender/editors/object/object_bake.c +++ b/source/blender/editors/object/object_bake.c @@ -64,6 +64,7 @@ #include "RE_pipeline.h" #include "RE_shader_ext.h" +#include "RE_multires_bake.h" #include "PIL_time.h" @@ -95,829 +96,12 @@ typedef struct { ListBase data; int bake_clear, bake_filter; short mode, use_lores_mesh; + int number_of_rays; + float bias; + int raytrace_structure; + int octree_resolution; } MultiresBakeJob; -/* data passing to multires baker */ -typedef struct { - DerivedMesh *lores_dm, *hires_dm; - int simple, lvl, tot_lvl, bake_filter; - short mode, use_lores_mesh; - - int tot_obj, tot_image; - ListBase image; - - int baked_objects, baked_faces; - - short *stop; - short *do_update; - float *progress; -} MultiresBakeRender; - -typedef void (*MPassKnownData)(DerivedMesh *lores_dm, DerivedMesh *hires_dm, const void *bake_data, - ImBuf *ibuf, const int face_index, const int lvl, const float st[2], - float tangmat[3][3], const int x, const int y); - -typedef void * (*MInitBakeData)(MultiresBakeRender *bkr, Image *ima); -typedef void (*MApplyBakeData)(void *bake_data); -typedef void (*MFreeBakeData)(void *bake_data); - -typedef struct { - MVert *mvert; - MFace *mface; - MTFace *mtface; - float *pvtangent; - float *precomputed_normals; - int w, h; - int face_index; - int i0, i1, i2; - DerivedMesh *lores_dm, *hires_dm; - int lvl; - void *bake_data; - ImBuf *ibuf; - MPassKnownData pass_data; -} MResolvePixelData; - -typedef void (*MFlushPixel)(const MResolvePixelData *data, const int x, const int y); - -typedef struct { - int w, h; - char *texels; - const MResolvePixelData *data; - MFlushPixel flush_pixel; -} MBakeRast; - -typedef struct { - float *heights; - float height_min, height_max; - Image *ima; - DerivedMesh *ssdm; - const int *orig_index_mf_to_mpoly; - const int *orig_index_mp_to_orig; -} MHeightBakeData; - -typedef struct { - const int *orig_index_mf_to_mpoly; - const int *orig_index_mp_to_orig; -} MNormalBakeData; - -static void multiresbake_get_normal(const MResolvePixelData *data, float norm[], const int face_num, const int vert_index) -{ - unsigned int indices[] = {data->mface[face_num].v1, data->mface[face_num].v2, - data->mface[face_num].v3, data->mface[face_num].v4}; - const int smoothnormal = (data->mface[face_num].flag & ME_SMOOTH); - - if (!smoothnormal) { /* flat */ - if (data->precomputed_normals) { - copy_v3_v3(norm, &data->precomputed_normals[3 * face_num]); - } - else { - float nor[3]; - float *p0, *p1, *p2; - const int iGetNrVerts = data->mface[face_num].v4 != 0 ? 4 : 3; - - p0 = data->mvert[indices[0]].co; - p1 = data->mvert[indices[1]].co; - p2 = data->mvert[indices[2]].co; - - if (iGetNrVerts == 4) { - float *p3 = data->mvert[indices[3]].co; - normal_quad_v3(nor, p0, p1, p2, p3); - } - else { - normal_tri_v3(nor, p0, p1, p2); - } - - copy_v3_v3(norm, nor); - } - } - else { - short *no = data->mvert[indices[vert_index]].no; - - normal_short_to_float_v3(norm, no); - normalize_v3(norm); - } -} - -static void init_bake_rast(MBakeRast *bake_rast, const ImBuf *ibuf, const MResolvePixelData *data, MFlushPixel flush_pixel) -{ - memset(bake_rast, 0, sizeof(MBakeRast)); - - bake_rast->texels = ibuf->userdata; - bake_rast->w = ibuf->x; - bake_rast->h = ibuf->y; - bake_rast->data = data; - bake_rast->flush_pixel = flush_pixel; -} - -static void flush_pixel(const MResolvePixelData *data, const int x, const int y) -{ - float st[2] = {(x + 0.5f) / data->w, (y + 0.5f) / data->h}; - float *st0, *st1, *st2; - float *tang0, *tang1, *tang2; - float no0[3], no1[3], no2[3]; - float fUV[2], from_tang[3][3], to_tang[3][3]; - float u, v, w, sign; - int r; - - const int i0 = data->i0; - const int i1 = data->i1; - const int i2 = data->i2; - - st0 = data->mtface[data->face_index].uv[i0]; - st1 = data->mtface[data->face_index].uv[i1]; - st2 = data->mtface[data->face_index].uv[i2]; - - tang0 = data->pvtangent + data->face_index * 16 + i0 * 4; - tang1 = data->pvtangent + data->face_index * 16 + i1 * 4; - tang2 = data->pvtangent + data->face_index * 16 + i2 * 4; - - multiresbake_get_normal(data, no0, data->face_index, i0); /* can optimize these 3 into one call */ - multiresbake_get_normal(data, no1, data->face_index, i1); - multiresbake_get_normal(data, no2, data->face_index, i2); - - resolve_tri_uv(fUV, st, st0, st1, st2); - - u = fUV[0]; - v = fUV[1]; - w = 1 - u - v; - - /* the sign is the same at all face vertices for any non degenerate face. - * Just in case we clamp the interpolated value though. */ - sign = (tang0[3] * u + tang1[3] * v + tang2[3] * w) < 0 ? (-1.0f) : 1.0f; - - /* this sequence of math is designed specifically as is with great care - * to be compatible with our shader. Please don't change without good reason. */ - for (r = 0; r < 3; r++) { - from_tang[0][r] = tang0[r] * u + tang1[r] * v + tang2[r] * w; - from_tang[2][r] = no0[r] * u + no1[r] * v + no2[r] * w; - } - - cross_v3_v3v3(from_tang[1], from_tang[2], from_tang[0]); /* B = sign * cross(N, T) */ - mul_v3_fl(from_tang[1], sign); - invert_m3_m3(to_tang, from_tang); - /* sequence end */ - - data->pass_data(data->lores_dm, data->hires_dm, data->bake_data, - data->ibuf, data->face_index, data->lvl, st, to_tang, x, y); -} - -static void set_rast_triangle(const MBakeRast *bake_rast, const int x, const int y) -{ - const int w = bake_rast->w; - const int h = bake_rast->h; - - if (x >= 0 && x < w && y >= 0 && y < h) { - if ((bake_rast->texels[y * w + x]) == 0) { - flush_pixel(bake_rast->data, x, y); - bake_rast->texels[y * w + x] = FILTER_MASK_USED; - } - } -} - -static void rasterize_half(const MBakeRast *bake_rast, - const float s0_s, const float t0_s, const float s1_s, const float t1_s, - const float s0_l, const float t0_l, const float s1_l, const float t1_l, - const int y0_in, const int y1_in, const int is_mid_right) -{ - const int s_stable = fabsf(t1_s - t0_s) > FLT_EPSILON ? 1 : 0; - const int l_stable = fabsf(t1_l - t0_l) > FLT_EPSILON ? 1 : 0; - const int w = bake_rast->w; - const int h = bake_rast->h; - int y, y0, y1; - - if (y1_in <= 0 || y0_in >= h) - return; - - y0 = y0_in < 0 ? 0 : y0_in; - y1 = y1_in >= h ? h : y1_in; - - for (y = y0; y < y1; y++) { - /*-b(x-x0) + a(y-y0) = 0 */ - int iXl, iXr, x; - float x_l = s_stable != 0 ? (s0_s + (((s1_s - s0_s) * (y - t0_s)) / (t1_s - t0_s))) : s0_s; - float x_r = l_stable != 0 ? (s0_l + (((s1_l - s0_l) * (y - t0_l)) / (t1_l - t0_l))) : s0_l; - - if (is_mid_right != 0) - SWAP(float, x_l, x_r); - - iXl = (int)ceilf(x_l); - iXr = (int)ceilf(x_r); - - if (iXr > 0 && iXl < w) { - iXl = iXl < 0 ? 0 : iXl; - iXr = iXr >= w ? w : iXr; - - for (x = iXl; x < iXr; x++) - set_rast_triangle(bake_rast, x, y); - } - } -} - -static void bake_rasterize(const MBakeRast *bake_rast, const float st0_in[2], const float st1_in[2], const float st2_in[2]) -{ - const int w = bake_rast->w; - const int h = bake_rast->h; - float slo = st0_in[0] * w - 0.5f; - float tlo = st0_in[1] * h - 0.5f; - float smi = st1_in[0] * w - 0.5f; - float tmi = st1_in[1] * h - 0.5f; - float shi = st2_in[0] * w - 0.5f; - float thi = st2_in[1] * h - 0.5f; - int is_mid_right = 0, ylo, yhi, yhi_beg; - - /* skip degenerates */ - if ((slo == smi && tlo == tmi) || (slo == shi && tlo == thi) || (smi == shi && tmi == thi)) - return; - - /* sort by T */ - if (tlo > tmi && tlo > thi) { - SWAP(float, shi, slo); - SWAP(float, thi, tlo); - } - else if (tmi > thi) { - SWAP(float, shi, smi); - SWAP(float, thi, tmi); - } - - if (tlo > tmi) { - SWAP(float, slo, smi); - SWAP(float, tlo, tmi); - } - - /* check if mid point is to the left or to the right of the lo-hi edge */ - is_mid_right = (-(shi - slo) * (tmi - thi) + (thi - tlo) * (smi - shi)) > 0 ? 1 : 0; - ylo = (int) ceilf(tlo); - yhi_beg = (int) ceilf(tmi); - yhi = (int) ceilf(thi); - - /*if (fTmi>ceilf(fTlo))*/ - rasterize_half(bake_rast, slo, tlo, smi, tmi, slo, tlo, shi, thi, ylo, yhi_beg, is_mid_right); - rasterize_half(bake_rast, smi, tmi, shi, thi, slo, tlo, shi, thi, yhi_beg, yhi, is_mid_right); -} - -static int multiresbake_test_break(MultiresBakeRender *bkr) -{ - if (!bkr->stop) { - /* this means baker is executed outside from job system */ - return 0; - } - - return G.is_break; -} - -static void do_multires_bake(MultiresBakeRender *bkr, Image *ima, MPassKnownData passKnownData, - MInitBakeData initBakeData, MApplyBakeData applyBakeData, MFreeBakeData freeBakeData) -{ - DerivedMesh *dm = bkr->lores_dm; - ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL); - const int lvl = bkr->lvl; - const int tot_face = dm->getNumTessFaces(dm); - MVert *mvert = dm->getVertArray(dm); - MFace *mface = dm->getTessFaceArray(dm); - MTFace *mtface = dm->getTessFaceDataArray(dm, CD_MTFACE); - float *pvtangent = NULL; - - if (CustomData_get_layer_index(&dm->faceData, CD_TANGENT) == -1) - DM_add_tangent_layer(dm); - - pvtangent = DM_get_tessface_data_layer(dm, CD_TANGENT); - - if (tot_face > 0) { /* sanity check */ - int f = 0; - MBakeRast bake_rast; - MResolvePixelData data = {NULL}; - - data.mface = mface; - data.mvert = mvert; - data.mtface = mtface; - data.pvtangent = pvtangent; - data.precomputed_normals = dm->getTessFaceDataArray(dm, CD_NORMAL); /* don't strictly need this */ - data.w = ibuf->x; - data.h = ibuf->y; - data.lores_dm = dm; - data.hires_dm = bkr->hires_dm; - data.lvl = lvl; - data.pass_data = passKnownData; - - if (initBakeData) - data.bake_data = initBakeData(bkr, ima); - - init_bake_rast(&bake_rast, ibuf, &data, flush_pixel); - - for (f = 0; f < tot_face; f++) { - MTFace *mtfate = &mtface[f]; - int verts[3][2], nr_tris, t; - - if (multiresbake_test_break(bkr)) - break; - - if (mtfate->tpage != ima) - continue; - - data.face_index = f; - data.ibuf = ibuf; - - /* might support other forms of diagonal splits later on such as - * split by shortest diagonal.*/ - verts[0][0] = 0; - verts[1][0] = 1; - verts[2][0] = 2; - - verts[0][1] = 0; - verts[1][1] = 2; - verts[2][1] = 3; - - nr_tris = mface[f].v4 != 0 ? 2 : 1; - for (t = 0; t < nr_tris; t++) { - data.i0 = verts[0][t]; - data.i1 = verts[1][t]; - data.i2 = verts[2][t]; - - bake_rasterize(&bake_rast, mtfate->uv[data.i0], mtfate->uv[data.i1], mtfate->uv[data.i2]); - } - - bkr->baked_faces++; - - if (bkr->do_update) - *bkr->do_update = TRUE; - - if (bkr->progress) - *bkr->progress = ((float)bkr->baked_objects + (float)bkr->baked_faces / tot_face) / bkr->tot_obj; - } - - if (applyBakeData) - applyBakeData(data.bake_data); - - if (freeBakeData) - freeBakeData(data.bake_data); - } - - BKE_image_release_ibuf(ima, ibuf, NULL); -} - -/* mode = 0: interpolate normals, - * mode = 1: interpolate coord */ -static void interp_bilinear_grid(CCGKey *key, CCGElem *grid, float crn_x, float crn_y, int mode, float res[3]) -{ - int x0, x1, y0, y1; - float u, v; - float data[4][3]; - - x0 = (int) crn_x; - x1 = x0 >= (key->grid_size - 1) ? (key->grid_size - 1) : (x0 + 1); - - y0 = (int) crn_y; - y1 = y0 >= (key->grid_size - 1) ? (key->grid_size - 1) : (y0 + 1); - - u = crn_x - x0; - v = crn_y - y0; - - if (mode == 0) { - copy_v3_v3(data[0], CCG_grid_elem_no(key, grid, x0, y0)); - copy_v3_v3(data[1], CCG_grid_elem_no(key, grid, x1, y0)); - copy_v3_v3(data[2], CCG_grid_elem_no(key, grid, x1, y1)); - copy_v3_v3(data[3], CCG_grid_elem_no(key, grid, x0, y1)); - } - else { - copy_v3_v3(data[0], CCG_grid_elem_co(key, grid, x0, y0)); - copy_v3_v3(data[1], CCG_grid_elem_co(key, grid, x1, y0)); - copy_v3_v3(data[2], CCG_grid_elem_co(key, grid, x1, y1)); - copy_v3_v3(data[3], CCG_grid_elem_co(key, grid, x0, y1)); - } - - interp_bilinear_quad_v3(data, u, v, res); -} - -static void get_ccgdm_data(DerivedMesh *lodm, DerivedMesh *hidm, - const int *index_mf_to_mpoly, const int *index_mp_to_orig, - const int lvl, const int face_index, const float u, const float v, float co[3], float n[3]) -{ - MFace mface; - CCGElem **grid_data; - CCGKey key; - float crn_x, crn_y; - int grid_size, S, face_side; - int *grid_offset, g_index; - - lodm->getTessFace(lodm, face_index, &mface); - - grid_size = hidm->getGridSize(hidm); - grid_data = hidm->getGridData(hidm); - grid_offset = hidm->getGridOffset(hidm); - hidm->getGridKey(hidm, &key); - - face_side = (grid_size << 1) - 1; - - if (lvl == 0) { - g_index = grid_offset[face_index]; - S = mdisp_rot_face_to_crn(mface.v4 ? 4 : 3, face_side, u * (face_side - 1), v * (face_side - 1), &crn_x, &crn_y); - } - else { - int side = (1 << (lvl - 1)) + 1; - int grid_index = DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, face_index); - int loc_offs = face_index % (1 << (2 * lvl)); - int cell_index = loc_offs % ((side - 1) * (side - 1)); - int cell_side = (grid_size - 1) / (side - 1); - int row = cell_index / (side - 1); - int col = cell_index % (side - 1); - - S = face_index / (1 << (2 * (lvl - 1))) - grid_offset[grid_index]; - g_index = grid_offset[grid_index]; - - crn_y = (row * cell_side) + u * cell_side; - crn_x = (col * cell_side) + v * cell_side; - } - - CLAMP(crn_x, 0.0f, grid_size); - CLAMP(crn_y, 0.0f, grid_size); - - if (n != NULL) - interp_bilinear_grid(&key, grid_data[g_index + S], crn_x, crn_y, 0, n); - - if (co != NULL) - interp_bilinear_grid(&key, grid_data[g_index + S], crn_x, crn_y, 1, co); -} - -/* mode = 0: interpolate normals, - * mode = 1: interpolate coord */ -static void interp_bilinear_mface(DerivedMesh *dm, MFace *mface, const float u, const float v, const int mode, float res[3]) -{ - float data[4][3]; - - if (mode == 0) { - dm->getVertNo(dm, mface->v1, data[0]); - dm->getVertNo(dm, mface->v2, data[1]); - dm->getVertNo(dm, mface->v3, data[2]); - dm->getVertNo(dm, mface->v4, data[3]); - } - else { - dm->getVertCo(dm, mface->v1, data[0]); - dm->getVertCo(dm, mface->v2, data[1]); - dm->getVertCo(dm, mface->v3, data[2]); - dm->getVertCo(dm, mface->v4, data[3]); - } - - interp_bilinear_quad_v3(data, u, v, res); -} - -/* mode = 0: interpolate normals, - * mode = 1: interpolate coord */ -static void interp_barycentric_mface(DerivedMesh *dm, MFace *mface, const float u, const float v, const int mode, float res[3]) -{ - float data[3][3]; - - if (mode == 0) { - dm->getVertNo(dm, mface->v1, data[0]); - dm->getVertNo(dm, mface->v2, data[1]); - dm->getVertNo(dm, mface->v3, data[2]); - } - else { - dm->getVertCo(dm, mface->v1, data[0]); - dm->getVertCo(dm, mface->v2, data[1]); - dm->getVertCo(dm, mface->v3, data[2]); - } - - interp_barycentric_tri_v3(data, u, v, res); -} - -static void *init_heights_data(MultiresBakeRender *bkr, Image *ima) -{ - MHeightBakeData *height_data; - ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL); - DerivedMesh *lodm = bkr->lores_dm; - - height_data = MEM_callocN(sizeof(MHeightBakeData), "MultiresBake heightData"); - - height_data->ima = ima; - height_data->heights = MEM_callocN(sizeof(float) * ibuf->x * ibuf->y, "MultiresBake heights"); - height_data->height_max = -FLT_MAX; - height_data->height_min = FLT_MAX; - - if (!bkr->use_lores_mesh) { - SubsurfModifierData smd = {{NULL}}; - int ss_lvl = bkr->tot_lvl - bkr->lvl; - - CLAMP(ss_lvl, 0, 6); - - if (ss_lvl > 0) { - smd.levels = smd.renderLevels = ss_lvl; - smd.flags |= eSubsurfModifierFlag_SubsurfUv; - - if (bkr->simple) - smd.subdivType = ME_SIMPLE_SUBSURF; - - height_data->ssdm = subsurf_make_derived_from_derived(bkr->lores_dm, &smd, NULL, 0); - } - } - - height_data->orig_index_mf_to_mpoly = lodm->getTessFaceDataArray(lodm, CD_ORIGINDEX); - height_data->orig_index_mp_to_orig = lodm->getPolyDataArray(lodm, CD_ORIGINDEX); - - BKE_image_release_ibuf(ima, ibuf, NULL); - - return (void *)height_data; -} - -static void *init_normal_data(MultiresBakeRender *bkr, Image *UNUSED(ima)) -{ - MNormalBakeData *normal_data; - DerivedMesh *lodm = bkr->lores_dm; - - normal_data = MEM_callocN(sizeof(MNormalBakeData), "MultiresBake normalData"); - - normal_data->orig_index_mf_to_mpoly = lodm->getTessFaceDataArray(lodm, CD_ORIGINDEX); - normal_data->orig_index_mp_to_orig = lodm->getPolyDataArray(lodm, CD_ORIGINDEX); - - return (void *)normal_data; -} - -static void free_normal_data(void *bake_data) -{ - MNormalBakeData *normal_data = (MNormalBakeData *)bake_data; - - MEM_freeN(normal_data); -} - -static void apply_heights_data(void *bake_data) -{ - MHeightBakeData *height_data = (MHeightBakeData *)bake_data; - ImBuf *ibuf = BKE_image_acquire_ibuf(height_data->ima, NULL, NULL); - int x, y, i; - float height, *heights = height_data->heights; - float min = height_data->height_min, max = height_data->height_max; - - for (x = 0; x < ibuf->x; x++) { - for (y = 0; y < ibuf->y; y++) { - i = ibuf->x * y + x; - - if (((char *)ibuf->userdata)[i] != FILTER_MASK_USED) - continue; - - if (ibuf->rect_float) { - float *rrgbf = ibuf->rect_float + i * 4; - - if (max - min > 1e-5f) height = (heights[i] - min) / (max - min); - else height = 0; - - rrgbf[0] = rrgbf[1] = rrgbf[2] = height; - } - else { - char *rrgb = (char *)ibuf->rect + i * 4; - - if (max - min > 1e-5f) height = (heights[i] - min) / (max - min); - else height = 0; - - rrgb[0] = rrgb[1] = rrgb[2] = FTOCHAR(height); - } - } - } - - ibuf->userflags = IB_RECT_INVALID | IB_DISPLAY_BUFFER_INVALID; - - BKE_image_release_ibuf(height_data->ima, ibuf, NULL); -} - -static void free_heights_data(void *bake_data) -{ - MHeightBakeData *height_data = (MHeightBakeData *)bake_data; - - if (height_data->ssdm) - height_data->ssdm->release(height_data->ssdm); - - MEM_freeN(height_data->heights); - MEM_freeN(height_data); -} - -/* MultiresBake callback for heights baking - * general idea: - * - find coord of point with specified UV in hi-res mesh (let's call it p1) - * - find coord of point and normal with specified UV in lo-res mesh (or subdivided lo-res - * mesh to make texture smoother) let's call this point p0 and n. - * - height wound be dot(n, p1-p0) */ -static void apply_heights_callback(DerivedMesh *lores_dm, DerivedMesh *hires_dm, const void *bake_data, - ImBuf *ibuf, const int face_index, const int lvl, const float st[2], - float UNUSED(tangmat[3][3]), const int x, const int y) -{ - MTFace *mtface = CustomData_get_layer(&lores_dm->faceData, CD_MTFACE); - MFace mface; - MHeightBakeData *height_data = (MHeightBakeData *)bake_data; - float uv[2], *st0, *st1, *st2, *st3; - int pixel = ibuf->x * y + x; - float vec[3], p0[3], p1[3], n[3], len; - - lores_dm->getTessFace(lores_dm, face_index, &mface); - - st0 = mtface[face_index].uv[0]; - st1 = mtface[face_index].uv[1]; - st2 = mtface[face_index].uv[2]; - - if (mface.v4) { - st3 = mtface[face_index].uv[3]; - resolve_quad_uv(uv, st, st0, st1, st2, st3); - } - else - resolve_tri_uv(uv, st, st0, st1, st2); - - CLAMP(uv[0], 0.0f, 1.0f); - CLAMP(uv[1], 0.0f, 1.0f); - - get_ccgdm_data(lores_dm, hires_dm, - height_data->orig_index_mf_to_mpoly, height_data->orig_index_mf_to_mpoly, - lvl, face_index, uv[0], uv[1], p1, 0); - - if (height_data->ssdm) { - get_ccgdm_data(lores_dm, height_data->ssdm, - height_data->orig_index_mf_to_mpoly, height_data->orig_index_mf_to_mpoly, - 0, face_index, uv[0], uv[1], p0, n); - } - else { - lores_dm->getTessFace(lores_dm, face_index, &mface); - - if (mface.v4) { - interp_bilinear_mface(lores_dm, &mface, uv[0], uv[1], 1, p0); - interp_bilinear_mface(lores_dm, &mface, uv[0], uv[1], 0, n); - } - else { - interp_barycentric_mface(lores_dm, &mface, uv[0], uv[1], 1, p0); - interp_barycentric_mface(lores_dm, &mface, uv[0], uv[1], 0, n); - } - } - - sub_v3_v3v3(vec, p1, p0); - len = dot_v3v3(n, vec); - - height_data->heights[pixel] = len; - if (len < height_data->height_min) height_data->height_min = len; - if (len > height_data->height_max) height_data->height_max = len; - - if (ibuf->rect_float) { - float *rrgbf = ibuf->rect_float + pixel * 4; - rrgbf[3] = 1.0f; - - ibuf->userflags = IB_RECT_INVALID; - } - else { - char *rrgb = (char *)ibuf->rect + pixel * 4; - rrgb[3] = 255; - } - - ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID; -} - -/* MultiresBake callback for normals' baking - * general idea: - * - find coord and normal of point with specified UV in hi-res mesh - * - multiply it by tangmat - * - vector in color space would be norm(vec) /2 + (0.5, 0.5, 0.5) */ -static void apply_tangmat_callback(DerivedMesh *lores_dm, DerivedMesh *hires_dm, const void *bake_data, - ImBuf *ibuf, const int face_index, const int lvl, const float st[2], - float tangmat[3][3], const int x, const int y) -{ - MTFace *mtface = CustomData_get_layer(&lores_dm->faceData, CD_MTFACE); - MFace mface; - MNormalBakeData *normal_data = (MNormalBakeData *)bake_data; - float uv[2], *st0, *st1, *st2, *st3; - int pixel = ibuf->x * y + x; - float n[3], vec[3], tmp[3] = {0.5, 0.5, 0.5}; - - lores_dm->getTessFace(lores_dm, face_index, &mface); - - st0 = mtface[face_index].uv[0]; - st1 = mtface[face_index].uv[1]; - st2 = mtface[face_index].uv[2]; - - if (mface.v4) { - st3 = mtface[face_index].uv[3]; - resolve_quad_uv(uv, st, st0, st1, st2, st3); - } - else - resolve_tri_uv(uv, st, st0, st1, st2); - - CLAMP(uv[0], 0.0f, 1.0f); - CLAMP(uv[1], 0.0f, 1.0f); - - get_ccgdm_data(lores_dm, hires_dm, - normal_data->orig_index_mf_to_mpoly, normal_data->orig_index_mp_to_orig, - lvl, face_index, uv[0], uv[1], NULL, n); - - mul_v3_m3v3(vec, tangmat, n); - normalize_v3(vec); - mul_v3_fl(vec, 0.5); - add_v3_v3(vec, tmp); - - if (ibuf->rect_float) { - float *rrgbf = ibuf->rect_float + pixel * 4; - rrgbf[0] = vec[0]; - rrgbf[1] = vec[1]; - rrgbf[2] = vec[2]; - rrgbf[3] = 1.0f; - - ibuf->userflags = IB_RECT_INVALID; - } - else { - unsigned char *rrgb = (unsigned char *)ibuf->rect + pixel * 4; - rgb_float_to_uchar(rrgb, vec); - rrgb[3] = 255; - } - - ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID; -} - -static void count_images(MultiresBakeRender *bkr) -{ - int a, totface; - DerivedMesh *dm = bkr->lores_dm; - MTFace *mtface = CustomData_get_layer(&dm->faceData, CD_MTFACE); - - bkr->image.first = bkr->image.last = NULL; - bkr->tot_image = 0; - - totface = dm->getNumTessFaces(dm); - - for (a = 0; a < totface; a++) - mtface[a].tpage->id.flag &= ~LIB_DOIT; - - for (a = 0; a < totface; a++) { - Image *ima = mtface[a].tpage; - if ((ima->id.flag & LIB_DOIT) == 0) { - LinkData *data = BLI_genericNodeN(ima); - BLI_addtail(&bkr->image, data); - bkr->tot_image++; - ima->id.flag |= LIB_DOIT; - } - } - - for (a = 0; a < totface; a++) - mtface[a].tpage->id.flag &= ~LIB_DOIT; -} - -static void bake_images(MultiresBakeRender *bkr) -{ - LinkData *link; - - for (link = bkr->image.first; link; link = link->next) { - Image *ima = (Image *)link->data; - ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL); - - if (ibuf->x > 0 && ibuf->y > 0) { - ibuf->userdata = MEM_callocN(ibuf->y * ibuf->x, "MultiresBake imbuf mask"); - - switch (bkr->mode) { - case RE_BAKE_NORMALS: - do_multires_bake(bkr, ima, apply_tangmat_callback, init_normal_data, NULL, free_normal_data); - break; - case RE_BAKE_DISPLACEMENT: - do_multires_bake(bkr, ima, apply_heights_callback, init_heights_data, - apply_heights_data, free_heights_data); - break; - } - } - - BKE_image_release_ibuf(ima, ibuf, NULL); - - ima->id.flag |= LIB_DOIT; - } -} - -static void finish_images(MultiresBakeRender *bkr) -{ - LinkData *link; - - for (link = bkr->image.first; link; link = link->next) { - Image *ima = (Image *)link->data; - ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL); - - if (ibuf->x <= 0 || ibuf->y <= 0) - continue; - - RE_bake_ibuf_filter(ibuf, (char *)ibuf->userdata, bkr->bake_filter); - - ibuf->userflags |= IB_BITMAPDIRTY | IB_DISPLAY_BUFFER_INVALID; - - if (ibuf->rect_float) - ibuf->userflags |= IB_RECT_INVALID; - - if (ibuf->mipmap[0]) { - ibuf->userflags |= IB_MIPMAP_INVALID; - imb_freemipmapImBuf(ibuf); - } - - if (ibuf->userdata) { - MEM_freeN(ibuf->userdata); - ibuf->userdata = NULL; - } - - BKE_image_release_ibuf(ima, ibuf, NULL); - } -} - -static void multiresbake_start(MultiresBakeRender *bkr) -{ - count_images(bkr); - bake_images(bkr); - finish_images(bkr); -} - static int multiresbake_check(bContext *C, wmOperator *op) { Scene *scene = CTX_data_scene(C); @@ -1023,6 +207,9 @@ static DerivedMesh *multiresbake_create_loresdm(Scene *scene, Object *ob, int *l if (*lvl == 0) { DerivedMesh *tmp_dm = CDDM_from_mesh(me, ob); + + DM_set_only_copy(tmp_dm, CD_MASK_BAREMESH | CD_MASK_MTFACE); + dm = CDDM_copy(tmp_dm); tmp_dm->release(tmp_dm); } @@ -1030,6 +217,8 @@ static DerivedMesh *multiresbake_create_loresdm(Scene *scene, Object *ob, int *l MultiresModifierData tmp_mmd = *mmd; DerivedMesh *cddm = CDDM_from_mesh(me, ob); + DM_set_only_copy(cddm, CD_MASK_BAREMESH | CD_MASK_MTFACE); + tmp_mmd.lvl = *lvl; tmp_mmd.sculptlvl = *lvl; dm = multires_make_derived_from_derived(cddm, &tmp_mmd, ob, 0); @@ -1047,6 +236,14 @@ static DerivedMesh *multiresbake_create_hiresdm(Scene *scene, Object *ob, int *l DerivedMesh *cddm = CDDM_from_mesh(me, ob); DerivedMesh *dm; + DM_set_only_copy(cddm, CD_MASK_BAREMESH); + + /* TODO: DM_set_only_copy wouldn't set mask for loop and poly data, + * but we really need BAREMESH only to save lots of memory + */ + CustomData_set_only_copy(&cddm->loopData, CD_MASK_BAREMESH); + CustomData_set_only_copy(&cddm->polyData, CD_MASK_BAREMESH); + *lvl = mmd->totlvl; *simple = mmd->simple; @@ -1118,16 +315,16 @@ static int multiresbake_image_exec_locked(bContext *C, wmOperator *op) bkr.bake_filter = scene->r.bake_filter; bkr.mode = scene->r.bake_mode; bkr.use_lores_mesh = scene->r.bake_flag & R_BAKE_LORES_MESH; + bkr.bias = scene->r.bake_biasdist; + bkr.number_of_rays = scene->r.bake_rays_number; + bkr.raytrace_structure = scene->r.raytrace_structure; + bkr.octree_resolution = scene->r.ocres; /* create low-resolution DM (to bake to) and hi-resolution DM (to bake from) */ - bkr.lores_dm = multiresbake_create_loresdm(scene, ob, &bkr.lvl); - - if (!bkr.lores_dm) - continue; - bkr.hires_dm = multiresbake_create_hiresdm(scene, ob, &bkr.tot_lvl, &bkr.simple); + bkr.lores_dm = multiresbake_create_loresdm(scene, ob, &bkr.lvl); - multiresbake_start(&bkr); + RE_multires_bake_images(&bkr); BLI_freelistN(&bkr.image); @@ -1155,24 +352,26 @@ static void init_multiresbake_job(bContext *C, MultiresBakeJob *bkj) bkj->mode = scene->r.bake_mode; bkj->use_lores_mesh = scene->r.bake_flag & R_BAKE_LORES_MESH; bkj->bake_clear = scene->r.bake_flag & R_BAKE_CLEAR; + bkj->bias = scene->r.bake_biasdist; + bkj->number_of_rays = scene->r.bake_rays_number; + bkj->raytrace_structure = scene->r.raytrace_structure; + bkj->octree_resolution = scene->r.ocres; CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases) { MultiresBakerJobData *data; - DerivedMesh *lores_dm; int lvl; + ob = base->object; multires_force_update(ob); - lores_dm = multiresbake_create_loresdm(scene, ob, &lvl); - if (!lores_dm) - continue; - data = MEM_callocN(sizeof(MultiresBakerJobData), "multiresBaker derivedMesh_data"); - data->lores_dm = lores_dm; - data->lvl = lvl; + + /* create low-resolution DM (to bake to) and hi-resolution DM (to bake from) */ data->hires_dm = multiresbake_create_hiresdm(scene, ob, &data->tot_lvl, &data->simple); + data->lores_dm = multiresbake_create_loresdm(scene, ob, &lvl); + data->lvl = lvl; BLI_addtail(&bkj->data, data); } @@ -1219,7 +418,12 @@ static void multiresbake_startjob(void *bkv, short *stop, short *do_update, floa bkr.do_update = do_update; bkr.progress = progress; - multiresbake_start(&bkr); + bkr.bias = bkj->bias; + bkr.number_of_rays = bkj->number_of_rays; + bkr.raytrace_structure = bkj->raytrace_structure; + bkr.octree_resolution = bkj->octree_resolution; + + RE_multires_bake_images(&bkr); BLI_freelistN(&bkr.image); @@ -1472,7 +676,7 @@ static int objects_bake_render_modal(bContext *C, wmOperator *UNUSED(op), wmEven static int is_multires_bake(Scene *scene) { - if (ELEM(scene->r.bake_mode, RE_BAKE_NORMALS, RE_BAKE_DISPLACEMENT)) + if (ELEM3(scene->r.bake_mode, RE_BAKE_NORMALS, RE_BAKE_DISPLACEMENT, RE_BAKE_AO)) return scene->r.bake_flag & R_BAKE_MULTIRES; return 0; diff --git a/source/blender/editors/object/object_edit.c b/source/blender/editors/object/object_edit.c index d39e34824b9..12edb3e8edb 100644 --- a/source/blender/editors/object/object_edit.c +++ b/source/blender/editors/object/object_edit.c @@ -429,6 +429,10 @@ void ED_object_enter_editmode(bContext *C, int flag) ob = base->object; + /* this checks actual object->data, for cases when other scenes have it in editmode context */ + if ( BKE_object_is_in_editmode(ob) ) + return; + if (BKE_object_obdata_is_libdata(ob)) { error_libdata(); return; diff --git a/source/blender/editors/object/object_transform.c b/source/blender/editors/object/object_transform.c index 900bf57b509..7a2eb5667a2 100644 --- a/source/blender/editors/object/object_transform.c +++ b/source/blender/editors/object/object_transform.c @@ -447,7 +447,7 @@ static int apply_objects_internal(bContext *C, ReportList *reports, int apply_lo float tmat[3][3], timat[3][3]; /* simple rotation matrix */ - BKE_object_rot_to_mat3(ob, rsmat); + BKE_object_rot_to_mat3(ob, rsmat, TRUE); /* correct for scale, note mul_m3_m3m3 has swapped args! */ BKE_object_scale_to_mat3(ob, tmat); diff --git a/source/blender/editors/object/object_vgroup.c b/source/blender/editors/object/object_vgroup.c index 1b135c0686e..f3e792def17 100644 --- a/source/blender/editors/object/object_vgroup.c +++ b/source/blender/editors/object/object_vgroup.c @@ -400,26 +400,34 @@ typedef enum WT_ReplaceMode { } WT_ReplaceMode; static EnumPropertyItem WT_vertex_group_mode_item[] = { - {WT_REPLACE_ACTIVE_VERTEX_GROUP, "WT_REPLACE_ACTIVE_VERTEX_GROUP", 0, "Active", "Transfer active vertex group from selected to active mesh"}, - {WT_REPLACE_ALL_VERTEX_GROUPS, "WT_REPLACE_ALL_VERTEX_GROUPS", 0, "All", "Transfer all vertex groups from selected to active mesh"}, + {WT_REPLACE_ACTIVE_VERTEX_GROUP, + "WT_REPLACE_ACTIVE_VERTEX_GROUP", 0, "Active", "Transfer active vertex group from selected to active mesh"}, + {WT_REPLACE_ALL_VERTEX_GROUPS, + "WT_REPLACE_ALL_VERTEX_GROUPS", 0, "All", "Transfer all vertex groups from selected to active mesh"}, {0, NULL, 0, NULL, NULL} }; static EnumPropertyItem WT_method_item[] = { - {WT_BY_INDEX, "WT_BY_INDEX", 0, "Vertex index", "Copy for identical meshes"}, - {WT_BY_NEAREST_VERTEX, "WT_BY_NEAREST_VERTEX", 0, "Nearest vertex", "Copy weight from closest vertex"}, - {WT_BY_NEAREST_FACE, "WT_BY_NEAREST_FACE", 0, "Nearest face", "Barycentric interpolation from nearest face"}, - {WT_BY_NEAREST_VERTEX_IN_FACE, "WT_BY_NEAREST_VERTEX_IN_FACE", 0, "Nearest vertex in face", "Copy weight from closest vertex in nearest face"}, + {WT_BY_INDEX, + "WT_BY_INDEX", 0, "Vertex index", "Copy for identical meshes"}, + {WT_BY_NEAREST_VERTEX, + "WT_BY_NEAREST_VERTEX", 0, "Nearest vertex", "Copy weight from closest vertex"}, + {WT_BY_NEAREST_FACE, + "WT_BY_NEAREST_FACE", 0, "Nearest face", "Barycentric interpolation from nearest face"}, + {WT_BY_NEAREST_VERTEX_IN_FACE, + "WT_BY_NEAREST_VERTEX_IN_FACE", 0, "Nearest vertex in face", "Copy weight from closest vertex in nearest face"}, {0, NULL, 0, NULL, NULL} }; static EnumPropertyItem WT_replace_mode_item[] = { - {WT_REPLACE_ALL_WEIGHTS, "WT_REPLACE_ALL_WEIGHTS", 0, "All", "Overwrite all weights"}, - {WT_REPLACE_EMPTY_WEIGHTS, "WT_REPLACE_EMPTY_WEIGHTS", 0, "Empty", "Add weights to vertices with no weight"}, + {WT_REPLACE_ALL_WEIGHTS, + "WT_REPLACE_ALL_WEIGHTS", 0, "All", "Overwrite all weights"}, + {WT_REPLACE_EMPTY_WEIGHTS, + "WT_REPLACE_EMPTY_WEIGHTS", 0, "Empty", "Add weights to vertices with no weight"}, {0, NULL, 0, NULL, NULL} }; -/*copy weight*/ +/* Copy weight.*/ static void vgroup_transfer_weight(float *r_weight_dst, const float weight_src, const WT_ReplaceMode replace_mode) { switch (replace_mode) { @@ -439,7 +447,9 @@ static void vgroup_transfer_weight(float *r_weight_dst, const float weight_src, } } -/* could be exposed externally */ +/* Could be exposed externally by implementing it in header with the rest. + * Simple refactoring will break something. + * For now, naming is ed_ instead of ED_*/ static int ed_vgroup_transfer_weight(Object *ob_dst, Object *ob_src, bDeformGroup *dg_src, Scene *scene, WT_Method method, WT_ReplaceMode replace_mode, wmOperator *op) { @@ -457,53 +467,52 @@ static int ed_vgroup_transfer_weight(Object *ob_dst, Object *ob_src, bDeformGrou float weight, tmp_weight[4], tmp_co[3], normal[3], tmp_mat[4][4], dist_v1, dist_v2, dist_v3, dist_v4; const int use_vert_sel = vertex_group_use_vert_sel(ob_dst); - /* create new and overwrite vertex group on destination without data */ + /* Ensure vertex group on target.*/ if (!defgroup_find_name(ob_dst, dg_src->name)) { - ED_vgroup_delete(ob_dst, defgroup_find_name(ob_dst, dg_src->name)); ED_vgroup_add_name(ob_dst, dg_src->name); } - /* get destination deformgroup */ + /* Get destination deformgroup.*/ dg_dst = defgroup_find_name(ob_dst, dg_src->name); - /* get meshes */ + /* Get meshes.*/ dmesh_src = mesh_get_derived_deform(scene, ob_src, CD_MASK_BAREMESH); me_dst = ob_dst->data; me_src = ob_src->data; - /* sanity check */ + /* Sanity check.*/ if (!me_src->dvert) { BKE_report(op->reports, RPT_ERROR, "Transfer failed (source mesh does not have any vertex groups)"); return 0; } - /* create data in memory when nothing there */ + /* Create data in memory when nothing there.*/ if (!me_dst->dvert) ED_vgroup_data_create(ob_dst->data); - /* get vertex group arrays */ + /* Get vertex group arrays.*/ ED_vgroup_give_parray(ob_src->data, &dv_array_src, &dv_tot_src, FALSE); ED_vgroup_give_parray(ob_dst->data, &dv_array_dst, &dv_tot_dst, use_vert_sel); - /* get indexes of vertex groups */ + /* Get indexes of vertex groups.*/ index_src = BLI_findindex(&ob_src->defbase, dg_src); index_dst = BLI_findindex(&ob_dst->defbase, dg_dst); - /* get vertices */ + /* Get vertices.*/ mv_dst = me_dst->mvert; mv_src = dmesh_src->getVertArray(dmesh_src); - /* prepare transformation matrix */ + /* Prepare transformation matrix.*/ invert_m4_m4(ob_src->imat, ob_src->obmat); mult_m4_m4m4(tmp_mat, ob_src->imat, ob_dst->obmat); - /* clear weights */ + /* Clear weights.*/ if (replace_mode == WT_REPLACE_ALL_WEIGHTS) { for (i = 0, dv_dst = dv_array_dst; i < me_dst->totvert; i++, dv_dst++) { if (*dv_dst == NULL) continue; dw_dst = defvert_find_index(*dv_dst, index_dst); - /* remove vertex from group */ + /* Remove vertex from group.*/ if (dw_dst) defvert_remove_group(*dv_dst, dw_dst); } } @@ -511,7 +520,7 @@ static int ed_vgroup_transfer_weight(Object *ob_dst, Object *ob_src, bDeformGrou switch (method) { case WT_BY_INDEX: - /* check if indices are matching, delete and return if not */ + /* Check if indices are matching, delete and return if not.*/ if (ob_dst == ob_src || dv_tot_dst == 0 || dv_tot_dst != dv_tot_src || dv_array_src == NULL || dv_array_dst == NULL) { @@ -523,14 +532,15 @@ static int ed_vgroup_transfer_weight(Object *ob_dst, Object *ob_src, bDeformGrou return 0; } - /* loop through the vertices*/ - for (i = 0, dv_src = dv_array_src, dv_dst = dv_array_dst; i < me_dst->totvert; i++, dv_dst++, dv_src++, mv_src++, mv_dst++) { + /* Loop through the vertices.*/ + for (i = 0, dv_src = dv_array_src, dv_dst = dv_array_dst; i < me_dst->totvert; + i++, dv_dst++, dv_src++, mv_src++, mv_dst++) { if (*dv_dst == NULL) { continue; } - /* copy weight */ + /* Copy weight.*/ dw_src = defvert_find_index(*dv_src, index_src); if (dw_src && dw_src->weight) { dw_dst = defvert_verify_index(*dv_dst, index_dst); @@ -540,29 +550,30 @@ static int ed_vgroup_transfer_weight(Object *ob_dst, Object *ob_src, bDeformGrou break; case WT_BY_NEAREST_VERTEX: - /* make node tree */ + /* Make node tree.*/ bvhtree_from_mesh_verts(&tree_mesh_vertices_src, dmesh_src, FLT_EPSILON, 2, 6); - /* loop trough vertices */ + /* Loop trough vertices.*/ for (i = 0, dv_dst = dv_array_dst; i < me_dst->totvert; i++, dv_dst++, mv_dst++) { if (*dv_dst == NULL) { continue; } - /* reset nearest */ + /* Reset nearest.*/ nearest.dist = FLT_MAX; - /* with current binary tree its marginally faster to start searching at the top, as opposed to previous search. */ + /* It is faster to start searching at the top of the tree instead of previous search result.*/ nearest.index = -1; - /* transform into target space */ + /* Transform into target space.*/ mul_v3_m4v3(tmp_co, tmp_mat, mv_dst->co); - /* node tree accelerated search for closest vetex */ + /* Node tree accelerated search for closest vetex.*/ BLI_bvhtree_find_nearest(tree_mesh_vertices_src.tree, tmp_co, &nearest, tree_mesh_vertices_src.nearest_callback, &tree_mesh_vertices_src); - /* copy weight that are not NULL including weight value 0. Existing target weights are overwritten prior to this in relevant cases. */ + /* Copy weight that are not NULL including weight value 0. In relevant cases, existing weights are + * overwritten prior to this. See the "Clear weights." step above.*/ dw_src = defvert_find_index(dv_array_src[nearest.index], index_src); if (dw_src && dw_src->weight) { dw_dst = defvert_verify_index(*dv_dst, index_dst); @@ -570,105 +581,108 @@ static int ed_vgroup_transfer_weight(Object *ob_dst, Object *ob_src, bDeformGrou } } - /* free memory */ + /* Free memory.*/ free_bvhtree_from_mesh(&tree_mesh_vertices_src); break; case WT_BY_NEAREST_FACE: - /* get faces */ + /* Get faces.*/ DM_ensure_tessface(dmesh_src); mface_src = dmesh_src->getTessFaceArray(dmesh_src); - /* make node tree */ + /* Make node tree.*/ bvhtree_from_mesh_faces(&tree_mesh_faces_src, dmesh_src, FLT_EPSILON, 2, 6); - /* loop through the vertices */ + /* Loop through the vertices.*/ for (i = 0, dv_dst = dv_array_dst; i < me_dst->totvert; i++, dv_dst++, mv_dst++) { if (*dv_dst == NULL) { continue; } - /* reset nearest */ + /* Reset nearest.*/ nearest.dist = FLT_MAX; - /* with current binary tree its marginally faster to start searching at the top, as opposed to previous search. */ + /* It is faster to start searching at the top of the tree instead of previous search result.*/ nearest.index = -1; - /* transform into target space */ + /* Transform into target space.*/ mul_v3_m4v3(tmp_co, tmp_mat, mv_dst->co); - /* node tree accelerated search for closest face */ + /* Node tree accelerated search for closest face.*/ BLI_bvhtree_find_nearest(tree_mesh_faces_src.tree, tmp_co, &nearest, tree_mesh_faces_src.nearest_callback, &tree_mesh_faces_src); index_nearest = nearest.index; - /* project onto face */ + /* Project onto face.*/ mf = &mface_src[index_nearest]; normal_tri_v3(normal, mv_src[mf->v1].co, mv_src[mf->v2].co, mv_src[mf->v3].co); project_v3_plane(tmp_co, normal, mv_src[mf->v1].co); - /* interpolate weights over face*/ + /* Interpolate weights over face.*/ f_index = mf->v4 ? 3 : 2; if (f_index == 3) { - interp_weights_face_v3(tmp_weight, mv_src[mf->v1].co, mv_src[mf->v2].co, mv_src[mf->v3].co, mv_src[mf->v4].co, tmp_co); + interp_weights_face_v3(tmp_weight, mv_src[mf->v1].co, mv_src[mf->v2].co, + mv_src[mf->v3].co, mv_src[mf->v4].co, tmp_co); } else { - interp_weights_face_v3(tmp_weight, mv_src[mf->v1].co, mv_src[mf->v2].co, mv_src[mf->v3].co, NULL, tmp_co); + interp_weights_face_v3(tmp_weight, mv_src[mf->v1].co, mv_src[mf->v2].co, + mv_src[mf->v3].co, NULL, tmp_co); } - /* get weights from face*/ + /* Get weights from face.*/ weight = 0; do { v_index = (&mf->v1)[f_index]; weight += tmp_weight[f_index] * defvert_find_weight(dv_array_src[v_index], index_src); } while (f_index--); - /* copy weight that are not NULL including weight value 0. Existing target weights are overwritten prior to this in relevant cases. */ + /* Copy weight that are not NULL including weight value 0. In relevant cases, existing weights are + * overwritten prior to this. See the "Clear weights." step above.*/ if (weight > 0) { dw_dst = defvert_verify_index(*dv_dst, index_dst); vgroup_transfer_weight(&dw_dst->weight, weight, replace_mode); } } - /* free memory */ + /* Free memory.*/ free_bvhtree_from_mesh(&tree_mesh_faces_src); break; case WT_BY_NEAREST_VERTEX_IN_FACE: - /* get faces */ + /* Get faces.*/ DM_ensure_tessface(dmesh_src); mface_src = dmesh_src->getTessFaceArray(dmesh_src); - /* make node tree */ + /* Make node tree.*/ bvhtree_from_mesh_faces(&tree_mesh_faces_src, dmesh_src, FLT_EPSILON, 2, 6); - /* loop through the vertices */ + /* Loop through the vertices.*/ for (i = 0, dv_dst = dv_array_dst; i < me_dst->totvert; i++, dv_dst++, mv_dst++) { if (*dv_dst == NULL) { continue; } - /* reset nearest */ + /* Reset nearest.*/ nearest.dist = FLT_MAX; - /* With current binary tree its marginally faster to start searching at the top, as opposed to previous search. */ + /* It is faster to start searching at the top of the tree instead of previous search result.*/ nearest.index = -1; - /* transform into target space */ + /* Transform into target space.*/ mul_v3_m4v3(tmp_co, tmp_mat, mv_dst->co); - /* node tree accelerated search for closest face */ + /* Node tree accelerated search for closest face.*/ BLI_bvhtree_find_nearest(tree_mesh_faces_src.tree, tmp_co, &nearest, tree_mesh_faces_src.nearest_callback, &tree_mesh_faces_src); index_nearest = nearest.index; - /* get distances */ + /* Get distances.*/ mf = &mface_src[index_nearest]; dist_v1 = len_squared_v3v3(tmp_co, mv_src[mf->v1].co); dist_v2 = len_squared_v3v3(tmp_co, mv_src[mf->v2].co); dist_v3 = len_squared_v3v3(tmp_co, mv_src[mf->v3].co); - /* get closest vertex */ + /* Get closest vertex.*/ f_index = mf->v4 ? 3 : 2; if (dist_v1 < dist_v2 && dist_v1 < dist_v3) index_nearest_vertex = mf->v1; else if (dist_v2 < dist_v3) index_nearest_vertex = mf->v2; @@ -680,7 +694,8 @@ static int ed_vgroup_transfer_weight(Object *ob_dst, Object *ob_src, bDeformGrou } } - /* copy weight that are not NULL including weight value 0. Existing target weights are overwritten prior to this in relevant cases. */ + /* Copy weight that are not NULL including weight value 0. In relevant cases, existing weights are + * overwritten prior to this. See the "Clear weights." step above.*/ dw_src = defvert_find_index(dv_array_src[index_nearest_vertex], index_src); if (dw_src && dw_src->weight) { dw_dst = defvert_verify_index(*dv_dst, index_dst); @@ -688,7 +703,7 @@ static int ed_vgroup_transfer_weight(Object *ob_dst, Object *ob_src, bDeformGrou } } - /* free memory */ + /* Free memory.*/ free_bvhtree_from_mesh(&tree_mesh_faces_src); break; @@ -697,7 +712,7 @@ static int ed_vgroup_transfer_weight(Object *ob_dst, Object *ob_src, bDeformGrou break; } - /*free memory*/ + /* Free memory.*/ if (dv_array_src) MEM_freeN(dv_array_src); if (dv_array_dst) MEM_freeN(dv_array_dst); dmesh_src->release(dmesh_src); @@ -1516,16 +1531,30 @@ static void vgroup_normalize_all(Object *ob, int lock_active) } } +enum { + VGROUP_TOGGLE, + VGROUP_LOCK, + VGROUP_UNLOCK, + VGROUP_INVERT +}; + +static EnumPropertyItem vgroup_lock_actions[] = { + {VGROUP_TOGGLE, "TOGGLE", 0, "Toggle", "Unlock all vertex groups if there is at least one locked group, lock all in other case"}, + {VGROUP_LOCK, "LOCK", 0, "Lock", "Lock all vertex groups"}, + {VGROUP_UNLOCK, "UNLOCK", 0, "Unlock", "Unlock all vertex groups"}, + {VGROUP_INVERT, "INVERT", 0, "Invert", "Invert the lock state of all vertex groups"}, + {0, NULL, 0, NULL, NULL} +}; static void vgroup_lock_all(Object *ob, int action) { bDeformGroup *dg; - if (action == SEL_TOGGLE) { - action = SEL_SELECT; + if (action == VGROUP_TOGGLE) { + action = VGROUP_LOCK; for (dg = ob->defbase.first; dg; dg = dg->next) { if (dg->flag & DG_LOCK_WEIGHT) { - action = SEL_DESELECT; + action = VGROUP_UNLOCK; break; } } @@ -1533,13 +1562,13 @@ static void vgroup_lock_all(Object *ob, int action) for (dg = ob->defbase.first; dg; dg = dg->next) { switch (action) { - case SEL_SELECT: + case VGROUP_LOCK: dg->flag |= DG_LOCK_WEIGHT; break; - case SEL_DESELECT: + case VGROUP_UNLOCK: dg->flag &= ~DG_LOCK_WEIGHT; break; - case SEL_INVERT: + case VGROUP_INVERT: dg->flag ^= DG_LOCK_WEIGHT; break; } @@ -2963,7 +2992,7 @@ void OBJECT_OT_vertex_group_lock(wmOperatorType *ot) /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - WM_operator_properties_select_all(ot); + RNA_def_enum(ot->srna, "action", vgroup_lock_actions, VGROUP_TOGGLE, "Action", "Lock action to execute on vertex groups"); } static int vertex_group_invert_exec(bContext *C, wmOperator *op) @@ -3274,7 +3303,7 @@ static int vertex_group_transfer_weight_exec(bContext *C, wmOperator *op) WT_Method method = RNA_enum_get(op->ptr, "WT_method"); WT_ReplaceMode replace_mode = RNA_enum_get(op->ptr, "WT_replace_mode"); - /* Macro to loop through selected objects and perform operation depending on function, option and method */ + /* Macro to loop through selected objects and perform operation depending on function, option and method.*/ CTX_DATA_BEGIN (C, Object *, ob_slc, selected_editable_objects) { @@ -3282,8 +3311,7 @@ static int vertex_group_transfer_weight_exec(bContext *C, wmOperator *op) switch (vertex_group_mode) { case WT_REPLACE_ACTIVE_VERTEX_GROUP: - if (!ed_vgroup_transfer_weight(ob_act, ob_slc, - BLI_findlink(&ob_slc->defbase, ob_slc->actdef - 1), + if (!ed_vgroup_transfer_weight(ob_act, ob_slc, BLI_findlink(&ob_slc->defbase, ob_slc->actdef - 1), scene, method, replace_mode, op)) { fail++; @@ -3292,9 +3320,7 @@ static int vertex_group_transfer_weight_exec(bContext *C, wmOperator *op) case WT_REPLACE_ALL_VERTEX_GROUPS: for (dg_src = ob_slc->defbase.first; dg_src; dg_src = dg_src->next) { - if (!ed_vgroup_transfer_weight(ob_act, ob_slc, - dg_src, scene, method, replace_mode, op)) - { + if (!ed_vgroup_transfer_weight(ob_act, ob_slc, dg_src, scene, method, replace_mode, op)) { fail++; } } @@ -3307,7 +3333,7 @@ static int vertex_group_transfer_weight_exec(bContext *C, wmOperator *op) } } - /* Event notifiers for correct display of data */ + /* Event notifiers for correct display of data.*/ DAG_id_tag_update(&ob_slc->id, OB_RECALC_DATA); WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob_slc); WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob_slc->data); @@ -3325,19 +3351,19 @@ static int vertex_group_transfer_weight_exec(bContext *C, wmOperator *op) /* transfers weight from active to selected */ void OBJECT_OT_vertex_group_transfer_weight(wmOperatorType *ot) { - /* identifiers */ + /* Identifiers.*/ ot->name = "Transfer Weights"; ot->idname = "OBJECT_OT_vertex_group_transfer_weight"; ot->description = "Transfer weight paint to active from selected mesh"; - /* api callbacks */ + /* API callbacks.*/ ot->poll = vertex_group_poll; ot->exec = vertex_group_transfer_weight_exec; - /* flags */ + /* Flags.*/ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - /* properties */ + /* Properties.*/ ot->prop = RNA_def_enum(ot->srna, "WT_vertex_group_mode", WT_vertex_group_mode_item, 1, "Group", ""); ot->prop = RNA_def_enum(ot->srna, "WT_method", WT_method_item, 3, "Method", ""); ot->prop = RNA_def_enum(ot->srna, "WT_replace_mode", WT_replace_mode_item, 1, "Replace", ""); |