Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/editors/object')
-rw-r--r--source/blender/editors/object/SConscript28
-rw-r--r--source/blender/editors/object/object_add.c24
-rw-r--r--source/blender/editors/object/object_bake.c876
-rw-r--r--source/blender/editors/object/object_edit.c4
-rw-r--r--source/blender/editors/object/object_transform.c2
-rw-r--r--source/blender/editors/object/object_vgroup.c182
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", "");