Merge branch 'master' into blender2.8

This commit is contained in:
Bastien Montagne 2017-02-02 21:50:12 +01:00
commit d85295534b
19 changed files with 363 additions and 298 deletions

@ -62,7 +62,7 @@ def _parse_command_line():
num_resumable_chunks = None
current_resumable_chunk = None
# TODO(sergey): Add some nice error ptins if argument is not used properly.
# TODO(sergey): Add some nice error prints if argument is not used properly.
idx = 0
while idx < len(argv) - 1:
arg = argv[idx]

@ -1352,6 +1352,9 @@ void BlenderSession::update_resumable_tile_manager(int num_samples)
VLOG(1) << "Samples range start is " << range_start_sample << ", "
<< "number of samples to render is " << range_num_samples;
scene->integrator->start_sample = range_start_sample;
scene->integrator->tag_update(scene);
session->tile_manager.range_start_sample = range_start_sample;
session->tile_manager.range_num_samples = range_num_samples;
}

@ -30,7 +30,7 @@ ccl_device_inline void kernel_path_trace_setup(KernelGlobals *kg,
int num_samples = kernel_data.integrator.aa_samples;
if(sample == 0) {
if(sample == kernel_data.integrator.start_sample) {
*rng_state = hash_int_2d(x, y);
}

@ -1187,6 +1187,9 @@ typedef struct KernelIntegrator {
int volume_samples;
float light_inv_rr_threshold;
int start_sample;
int pad1, pad2, pad3;
} KernelIntegrator;
static_assert_align(KernelIntegrator, 16);

@ -64,6 +64,7 @@ NODE_DEFINE(Integrator)
SOCKET_INT(mesh_light_samples, "Mesh Light Samples", 1);
SOCKET_INT(subsurface_samples, "Subsurface Samples", 1);
SOCKET_INT(volume_samples, "Volume Samples", 1);
SOCKET_INT(start_sample, "Start Sample", 0);
SOCKET_BOOLEAN(sample_all_lights_direct, "Sample All Lights Direct", true);
SOCKET_BOOLEAN(sample_all_lights_indirect, "Sample All Lights Indirect", true);
@ -161,6 +162,7 @@ void Integrator::device_update(Device *device, DeviceScene *dscene, Scene *scene
kintegrator->mesh_light_samples = mesh_light_samples;
kintegrator->subsurface_samples = subsurface_samples;
kintegrator->volume_samples = volume_samples;
kintegrator->start_sample = start_sample;
if(method == BRANCHED_PATH) {
kintegrator->sample_all_lights_direct = sample_all_lights_direct;

@ -66,6 +66,7 @@ public:
int mesh_light_samples;
int subsurface_samples;
int volume_samples;
int start_sample;
bool sample_all_lights_direct;
bool sample_all_lights_indirect;

@ -377,7 +377,7 @@ class RENDER_PT_stamp(RenderButtonsPanel, Panel):
sub.active = rd.use_stamp_note
sub.prop(rd, "stamp_note_text", text="")
if rd.use_sequencer:
layout.label("Sequencer")
layout.label("Sequencer:")
layout.prop(rd, "use_stamp_strip_meta")

@ -2408,36 +2408,46 @@ static DerivedMesh *cddm_copy_ex(DerivedMesh *source, int faces_from_tessfaces)
int numLoops = source->numLoopData;
int numPolys = source->numPolyData;
/* NOTE: Don't copy tessellation faces if not requested explicitly. */
/* ensure these are created if they are made on demand */
source->getVertDataArray(source, CD_ORIGINDEX);
source->getEdgeDataArray(source, CD_ORIGINDEX);
source->getTessFaceDataArray(source, CD_ORIGINDEX);
source->getPolyDataArray(source, CD_ORIGINDEX);
/* this initializes dm, and copies all non mvert/medge/mface layers */
DM_from_template(dm, source, DM_TYPE_CDDM, numVerts, numEdges, numTessFaces,
DM_from_template(dm, source, DM_TYPE_CDDM, numVerts, numEdges,
faces_from_tessfaces ? numTessFaces : 0,
numLoops, numPolys);
dm->deformedOnly = source->deformedOnly;
dm->cd_flag = source->cd_flag;
dm->dirty = source->dirty;
/* Tessellation data is never copied, so tag it here. */
dm->dirty |= DM_DIRTY_TESS_CDLAYERS;
CustomData_copy_data(&source->vertData, &dm->vertData, 0, 0, numVerts);
CustomData_copy_data(&source->edgeData, &dm->edgeData, 0, 0, numEdges);
CustomData_copy_data(&source->faceData, &dm->faceData, 0, 0, numTessFaces);
/* now add mvert/medge/mface layers */
cddm->mvert = source->dupVertArray(source);
cddm->medge = source->dupEdgeArray(source);
cddm->mface = source->dupTessFaceArray(source);
CustomData_add_layer(&dm->vertData, CD_MVERT, CD_ASSIGN, cddm->mvert, numVerts);
CustomData_add_layer(&dm->edgeData, CD_MEDGE, CD_ASSIGN, cddm->medge, numEdges);
CustomData_add_layer(&dm->faceData, CD_MFACE, CD_ASSIGN, cddm->mface, numTessFaces);
if (!faces_from_tessfaces)
if (!faces_from_tessfaces) {
DM_DupPolys(source, dm);
else
}
else {
source->getTessFaceDataArray(source, CD_ORIGINDEX);
CustomData_copy_data(&source->faceData, &dm->faceData, 0, 0, numTessFaces);
cddm->mface = source->dupTessFaceArray(source);
CustomData_add_layer(&dm->faceData, CD_MFACE, CD_ASSIGN, cddm->mface, numTessFaces);
CDDM_tessfaces_to_faces(dm);
}
cddm->mloop = CustomData_get_layer(&dm->loopData, CD_MLOOP);
cddm->mpoly = CustomData_get_layer(&dm->polyData, CD_MPOLY);

@ -945,6 +945,10 @@ void BM_mesh_bm_to_me(
/* propagate edited basis offsets to other shapes */
if (apply_offset) {
add_v3_v3(fp, *ofs_pt++);
/* Apply back new coordinates of offsetted shapekeys into BMesh.
* Otherwise, in case we call again BM_mesh_bm_to_me on same BMesh, we'll apply diff from previous
* call to BM_mesh_bm_to_me, to shapekey values from *original creation of the BMesh*. See T50524. */
copy_v3_v3(BM_ELEM_CD_GET_VOID_P(eve, cd_shape_offset), fp);
}
fp += 3;

@ -43,8 +43,6 @@ void HueSaturationValueNode::convertToOperations(NodeConverter &converter, const
NodeInput *valueSocket = this->getInputSocket(3);
NodeInput *facSocket = this->getInputSocket(4);
NodeOutput *outputSocket = this->getOutputSocket(0);
bNode *editorsnode = getbNode();
NodeHueSat *storage = (NodeHueSat *)editorsnode->storage;
ConvertRGBToHSVOperation *rgbToHSV = new ConvertRGBToHSVOperation();
converter.addOperation(rgbToHSV);

@ -129,8 +129,8 @@ static bool python_driver_depends_on_time(ChannelDriver *driver)
/* Function calls are considered dependent on a time. */
return true;
}
if (strstr(driver->expression, "time") != NULL) {
/* Variable `time` depends on time. */
if (strstr(driver->expression, "frame") != NULL) {
/* Variable `frame` depends on time. */
/* TODO(sergey): This is a bit weak, but not sure about better way of
* handling this.
*/

@ -2078,15 +2078,7 @@ static void ui_litem_estimate_row(uiLayout *litem)
for (item = litem->items.first; item; item = item->next) {
ui_item_size(item, &itemw, &itemh);
if (item->type == ITEM_BUTTON) {
const uiBut *but = ((uiButtonItem *)item)->but;
const bool icon_only = (but->flag & UI_HAS_ICON) && (but->str == NULL || but->str[0] == '\0');
min_size_flag = min_size_flag && icon_only;
}
else {
min_size_flag = min_size_flag && (item->flag & UI_ITEM_MIN);
}
min_size_flag = min_size_flag && (item->flag & UI_ITEM_MIN);
litem->w += itemw;
litem->h = MAX2(itemh, litem->h);
@ -2232,15 +2224,7 @@ static void ui_litem_estimate_column(uiLayout *litem)
for (item = litem->items.first; item; item = item->next) {
ui_item_size(item, &itemw, &itemh);
if (item->type == ITEM_BUTTON) {
const uiBut *but = ((uiButtonItem *)item)->but;
const bool icon_only = (but->flag & UI_HAS_ICON) && (but->str == NULL || but->str[0] == '\0');
min_size_flag = min_size_flag && icon_only;
}
else {
min_size_flag = min_size_flag && (item->flag & UI_ITEM_MIN);
}
min_size_flag = min_size_flag && (item->flag & UI_ITEM_MIN);
litem->w = MAX2(litem->w, itemw);
litem->h += itemh;
@ -3336,6 +3320,14 @@ void ui_layout_add_but(uiLayout *layout, uiBut *but)
bitem = MEM_callocN(sizeof(uiButtonItem), "uiButtonItem");
bitem->item.type = ITEM_BUTTON;
bitem->but = but;
int w, h;
ui_item_size((uiItem *)bitem, &w, &h);
/* XXX uiBut hasn't scaled yet
* we can flag the button as not expandable, depending on its size */
if (w <= 2 * UI_UNIT_X)
bitem->item.flag |= UI_ITEM_MIN;
BLI_addtail(&layout->items, bitem);
if (layout->context) {

@ -447,7 +447,8 @@ static int view_scrolldown_exec(bContext *C, wmOperator *op)
RNA_int_set(op->ptr, "deltax", 0);
RNA_int_set(op->ptr, "deltay", -40);
if (RNA_boolean_get(op->ptr, "page")) {
PropertyRNA *prop = RNA_struct_find_property(op->ptr, "page");
if (RNA_property_is_set(op->ptr, prop) && RNA_property_boolean_get(op->ptr, prop)) {
ARegion *ar = CTX_wm_region(C);
RNA_int_set(op->ptr, "deltay", ar->v2d.mask.ymin - ar->v2d.mask.ymax);
}
@ -497,7 +498,8 @@ static int view_scrollup_exec(bContext *C, wmOperator *op)
RNA_int_set(op->ptr, "deltax", 0);
RNA_int_set(op->ptr, "deltay", 40);
if (RNA_boolean_get(op->ptr, "page")) {
PropertyRNA *prop = RNA_struct_find_property(op->ptr, "page");
if (RNA_property_is_set(op->ptr, prop) && RNA_property_boolean_get(op->ptr, prop)) {
ARegion *ar = CTX_wm_region(C);
RNA_int_set(op->ptr, "deltay", BLI_rcti_size_y(&ar->v2d.mask));
}

@ -75,26 +75,213 @@
/* join selected meshes into the active mesh, context sensitive
* return 0 if no join is made (error) and 1 if the join is done */
static void join_mesh_single(
Main *bmain, Scene *scene,
Object *ob_dst, Base *base_src, float imat[4][4],
MVert **mvert_pp, MEdge **medge_pp, MLoop **mloop_pp, MPoly **mpoly_pp,
CustomData *vdata, CustomData *edata, CustomData *ldata, CustomData *pdata,
int totvert, int totedge, int totloop, int totpoly,
Key *key, Key *nkey,
Material **matar, int *matmap, int totcol,
int *vertofs, int *edgeofs, int *loopofs, int *polyofs)
{
int a, b;
Mesh *me = base_src->object->data;
MVert *mvert = *mvert_pp;
MEdge *medge = *medge_pp;
MLoop *mloop = *mloop_pp;
MPoly *mpoly = *mpoly_pp;
if (me->totvert) {
/* merge customdata flag */
((Mesh *)ob_dst->data)->cd_flag |= me->cd_flag;
/* standard data */
CustomData_merge(&me->vdata, vdata, CD_MASK_MESH, CD_DEFAULT, totvert);
CustomData_copy_data_named(&me->vdata, vdata, 0, *vertofs, me->totvert);
/* vertex groups */
MDeformVert *dvert = CustomData_get(vdata, *vertofs, CD_MDEFORMVERT);
/* NB: vertex groups here are new version */
if (dvert) {
for (a = 0; a < me->totvert; a++) {
for (b = 0; b < dvert[a].totweight; b++) {
/* Find the old vertex group */
bDeformGroup *dg, *odg = BLI_findlink(&base_src->object->defbase, dvert[a].dw[b].def_nr);
int index;
if (odg) {
/* Search for a match in the new object, and set new index */
for (dg = ob_dst->defbase.first, index = 0; dg; dg = dg->next, index++) {
if (STREQ(dg->name, odg->name)) {
dvert[a].dw[b].def_nr = index;
break;
}
}
}
}
}
}
/* if this is the object we're merging into, no need to do anything */
if (base_src->object != ob_dst) {
float cmat[4][4];
/* watch this: switch matmul order really goes wrong */
mul_m4_m4m4(cmat, imat, base_src->object->obmat);
/* transform vertex coordinates into new space */
for (a = 0, mvert = *mvert_pp; a < me->totvert; a++, mvert++) {
mul_m4_v3(cmat, mvert->co);
}
/* for each shapekey in destination mesh:
* - if there's a matching one, copy it across (will need to transform vertices into new space...)
* - otherwise, just copy own coordinates of mesh (no need to transform vertex coordinates into new space)
*/
if (key) {
/* if this mesh has any shapekeys, check first, otherwise just copy coordinates */
for (KeyBlock *kb = key->block.first; kb; kb = kb->next) {
/* get pointer to where to write data for this mesh in shapekey's data array */
float (*cos)[3] = ((float (*)[3])kb->data) + *vertofs;
/* check if this mesh has such a shapekey */
KeyBlock *okb = me->key ? BKE_keyblock_find_name(me->key, kb->name) : NULL;
if (okb) {
/* copy this mesh's shapekey to the destination shapekey (need to transform first) */
float (*ocos)[3] = okb->data;
for (a = 0; a < me->totvert; a++, cos++, ocos++) {
copy_v3_v3(*cos, *ocos);
mul_m4_v3(cmat, *cos);
}
}
else {
/* copy this mesh's vertex coordinates to the destination shapekey */
for (a = 0, mvert = *mvert_pp; a < me->totvert; a++, cos++, mvert++) {
copy_v3_v3(*cos, mvert->co);
}
}
}
}
}
else {
/* for each shapekey in destination mesh:
* - if it was an 'original', copy the appropriate data from nkey
* - otherwise, copy across plain coordinates (no need to transform coordinates)
*/
if (key) {
for (KeyBlock *kb = key->block.first; kb; kb = kb->next) {
/* get pointer to where to write data for this mesh in shapekey's data array */
float (*cos)[3] = ((float (*)[3])kb->data) + *vertofs;
/* check if this was one of the original shapekeys */
KeyBlock *okb = nkey ? BKE_keyblock_find_name(nkey, kb->name) : NULL;
if (okb) {
/* copy this mesh's shapekey to the destination shapekey */
float (*ocos)[3] = okb->data;
for (a = 0; a < me->totvert; a++, cos++, ocos++) {
copy_v3_v3(*cos, *ocos);
}
}
else {
/* copy base-coordinates to the destination shapekey */
for (a = 0, mvert = *mvert_pp; a < me->totvert; a++, cos++, mvert++) {
copy_v3_v3(*cos, mvert->co);
}
}
}
}
}
}
if (me->totedge) {
CustomData_merge(&me->edata, edata, CD_MASK_MESH, CD_DEFAULT, totedge);
CustomData_copy_data_named(&me->edata, edata, 0, *edgeofs, me->totedge);
for (a = 0; a < me->totedge; a++, medge++) {
medge->v1 += *vertofs;
medge->v2 += *vertofs;
}
}
if (me->totloop) {
if (base_src->object != ob_dst) {
MultiresModifierData *mmd;
multiresModifier_prepare_join(scene, base_src->object, ob_dst);
if ((mmd = get_multires_modifier(scene, base_src->object, true))) {
ED_object_iter_other(bmain, base_src->object, true,
ED_object_multires_update_totlevels_cb,
&mmd->totlvl);
}
}
CustomData_merge(&me->ldata, ldata, CD_MASK_MESH, CD_DEFAULT, totloop);
CustomData_copy_data_named(&me->ldata, ldata, 0, *loopofs, me->totloop);
for (a = 0; a < me->totloop; a++, mloop++) {
mloop->v += *vertofs;
mloop->e += *edgeofs;
}
}
if (me->totpoly) {
if (matmap) {
/* make mapping for materials */
for (a = 1; a <= base_src->object->totcol; a++) {
Material *ma = give_current_material(base_src->object, a);
for (b = 0; b < totcol; b++) {
if (ma == matar[b]) {
matmap[a - 1] = b;
break;
}
}
}
}
CustomData_merge(&me->pdata, pdata, CD_MASK_MESH, CD_DEFAULT, totpoly);
CustomData_copy_data_named(&me->pdata, pdata, 0, *polyofs, me->totpoly);
for (a = 0; a < me->totpoly; a++, mpoly++) {
mpoly->loopstart += *loopofs;
mpoly->mat_nr = matmap ? matmap[mpoly->mat_nr] : 0;
}
}
/* these are used for relinking (cannot be set earlier, or else reattaching goes wrong) */
*vertofs += me->totvert;
*mvert_pp += me->totvert;
*edgeofs += me->totedge;
*medge_pp += me->totedge;
*loopofs += me->totloop;
*mloop_pp += me->totloop;
*polyofs += me->totpoly;
*mpoly_pp += me->totpoly;
}
int join_mesh_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
Object *ob = CTX_data_active_object(C);
Material **matar, *ma;
Base *ob_base = CTX_data_active_base(C);
Object *ob = ob_base->object;
Material **matar = NULL, *ma;
Mesh *me;
MVert *mvert, *mv;
MVert *mvert = NULL;
MEdge *medge = NULL;
MPoly *mpoly = NULL;
MLoop *mloop = NULL;
Key *key, *nkey = NULL;
KeyBlock *kb, *okb, *kbn;
float imat[4][4], cmat[4][4], *fp1, *fp2;
KeyBlock *kb, *kbn;
float imat[4][4];
int a, b, totcol, totmat = 0, totedge = 0, totvert = 0;
int totloop = 0, totpoly = 0, vertofs, *matmap = NULL;
int i, j, index, haskey = 0, edgeofs, loopofs, polyofs;
int i, haskey = 0, edgeofs, loopofs, polyofs;
bool ok = false;
bDeformGroup *dg, *odg;
MDeformVert *dvert;
CustomData vdata, edata, fdata, ldata, pdata;
if (scene->obedit) {
@ -154,8 +341,10 @@ int join_mesh_exec(bContext *C, wmOperator *op)
BKE_mesh_tessface_clear(me);
/* new material indices and material array */
matar = MEM_callocN(sizeof(void *) * totmat, "join_mesh matar");
if (totmat) matmap = MEM_callocN(sizeof(int) * totmat, "join_mesh matmap");
if (totmat) {
matar = MEM_callocN(sizeof(*matar) * totmat, "join_mesh matar");
matmap = MEM_callocN(sizeof(*matmap) * totmat, "join_mesh matmap");
}
totcol = ob->totcol;
/* obact materials in new main array, is nicer start! */
@ -214,7 +403,9 @@ int join_mesh_exec(bContext *C, wmOperator *op)
ma = give_current_material(base->object, a);
for (b = 0; b < totcol; b++) {
if (ma == matar[b]) break;
if (ma == matar[b]) {
break;
}
}
if (b == totcol) {
matar[b] = ma;
@ -223,8 +414,9 @@ int join_mesh_exec(bContext *C, wmOperator *op)
}
totcol++;
}
if (totcol >= MAXMAT)
if (totcol >= MAXMAT) {
break;
}
}
}
@ -301,187 +493,41 @@ int join_mesh_exec(bContext *C, wmOperator *op)
/* inverse transform for all selected meshes in this object */
invert_m4_m4(imat, ob->obmat);
/* Add back active mesh first. This allows to keep things similar as they were, as much as possible (i.e. data from
* active mesh will remain first ones in new result of the merge, in same order for CD layers, etc. See also T50084.
*/
join_mesh_single(
bmain, scene,
ob, ob_base, imat,
&mvert, &medge, &mloop, &mpoly,
&vdata, &edata, &ldata, &pdata,
totvert, totedge, totloop, totpoly,
key, nkey,
matar, matmap, totcol,
&vertofs, &edgeofs, &loopofs, &polyofs);
CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases)
{
if (base->object == ob) {
continue;
}
/* only join if this is a mesh */
if (base->object->type == OB_MESH) {
me = base->object->data;
if (me->totvert) {
join_mesh_single(
bmain, scene,
ob, base, imat,
&mvert, &medge, &mloop, &mpoly,
&vdata, &edata, &ldata, &pdata,
totvert, totedge, totloop, totpoly,
key, nkey,
matar, matmap, totcol,
&vertofs, &edgeofs, &loopofs, &polyofs);
/* merge customdata flag */
((Mesh *)ob->data)->cd_flag |= me->cd_flag;
/* standard data */
CustomData_merge(&me->vdata, &vdata, CD_MASK_MESH, CD_DEFAULT, totvert);
CustomData_copy_data_named(&me->vdata, &vdata, 0, vertofs, me->totvert);
/* vertex groups */
dvert = CustomData_get(&vdata, vertofs, CD_MDEFORMVERT);
/* NB: vertex groups here are new version */
if (dvert) {
for (i = 0; i < me->totvert; i++) {
for (j = 0; j < dvert[i].totweight; j++) {
/* Find the old vertex group */
odg = BLI_findlink(&base->object->defbase, dvert[i].dw[j].def_nr);
if (odg) {
/* Search for a match in the new object, and set new index */
for (dg = ob->defbase.first, index = 0; dg; dg = dg->next, index++) {
if (STREQ(dg->name, odg->name)) {
dvert[i].dw[j].def_nr = index;
break;
}
}
}
}
}
}
/* if this is the object we're merging into, no need to do anything */
if (base->object != ob) {
/* watch this: switch matmul order really goes wrong */
mul_m4_m4m4(cmat, imat, base->object->obmat);
/* transform vertex coordinates into new space */
for (a = 0, mv = mvert; a < me->totvert; a++, mv++) {
mul_m4_v3(cmat, mv->co);
}
/* for each shapekey in destination mesh:
* - if there's a matching one, copy it across (will need to transform vertices into new space...)
* - otherwise, just copy own coordinates of mesh (no need to transform vertex coordinates into new space)
*/
if (key) {
/* if this mesh has any shapekeys, check first, otherwise just copy coordinates */
for (kb = key->block.first; kb; kb = kb->next) {
/* get pointer to where to write data for this mesh in shapekey's data array */
fp1 = ((float *)kb->data) + (vertofs * 3);
/* check if this mesh has such a shapekey */
okb = me->key ? BKE_keyblock_find_name(me->key, kb->name) : NULL;
if (okb) {
/* copy this mesh's shapekey to the destination shapekey (need to transform first) */
fp2 = ((float *)(okb->data));
for (a = 0; a < me->totvert; a++, fp1 += 3, fp2 += 3) {
copy_v3_v3(fp1, fp2);
mul_m4_v3(cmat, fp1);
}
}
else {
/* copy this mesh's vertex coordinates to the destination shapekey */
mv = mvert;
for (a = 0; a < me->totvert; a++, fp1 += 3, mv++) {
copy_v3_v3(fp1, mv->co);
}
}
}
}
}
else {
/* for each shapekey in destination mesh:
* - if it was an 'original', copy the appropriate data from nkey
* - otherwise, copy across plain coordinates (no need to transform coordinates)
*/
if (key) {
for (kb = key->block.first; kb; kb = kb->next) {
/* get pointer to where to write data for this mesh in shapekey's data array */
fp1 = ((float *)kb->data) + (vertofs * 3);
/* check if this was one of the original shapekeys */
okb = nkey ? BKE_keyblock_find_name(nkey, kb->name) : NULL;
if (okb) {
/* copy this mesh's shapekey to the destination shapekey */
fp2 = ((float *)(okb->data));
for (a = 0; a < me->totvert; a++, fp1 += 3, fp2 += 3) {
copy_v3_v3(fp1, fp2);
}
}
else {
/* copy base-coordinates to the destination shapekey */
mv = mvert;
for (a = 0; a < me->totvert; a++, fp1 += 3, mv++) {
copy_v3_v3(fp1, mv->co);
}
}
}
}
}
/* advance mvert pointer to end of base mesh's data */
mvert += me->totvert;
}
if (me->totedge) {
CustomData_merge(&me->edata, &edata, CD_MASK_MESH, CD_DEFAULT, totedge);
CustomData_copy_data_named(&me->edata, &edata, 0, edgeofs, me->totedge);
for (a = 0; a < me->totedge; a++, medge++) {
medge->v1 += vertofs;
medge->v2 += vertofs;
}
}
if (me->totloop) {
if (base->object != ob) {
MultiresModifierData *mmd;
multiresModifier_prepare_join(scene, base->object, ob);
if ((mmd = get_multires_modifier(scene, base->object, true))) {
ED_object_iter_other(bmain, base->object, true,
ED_object_multires_update_totlevels_cb,
&mmd->totlvl);
}
}
CustomData_merge(&me->ldata, &ldata, CD_MASK_MESH, CD_DEFAULT, totloop);
CustomData_copy_data_named(&me->ldata, &ldata, 0, loopofs, me->totloop);
for (a = 0; a < me->totloop; a++, mloop++) {
mloop->v += vertofs;
mloop->e += edgeofs;
}
}
if (me->totpoly) {
if (totmat) {
/* make mapping for materials */
for (a = 1; a <= base->object->totcol; a++) {
ma = give_current_material(base->object, a);
for (b = 0; b < totcol; b++) {
if (ma == matar[b]) {
matmap[a - 1] = b;
break;
}
}
}
}
CustomData_merge(&me->pdata, &pdata, CD_MASK_MESH, CD_DEFAULT, totpoly);
CustomData_copy_data_named(&me->pdata, &pdata, 0, polyofs, me->totpoly);
for (a = 0; a < me->totpoly; a++, mpoly++) {
mpoly->loopstart += loopofs;
mpoly->mat_nr = matmap ? matmap[(int)mpoly->mat_nr] : 0;
}
polyofs += me->totpoly;
}
/* these are used for relinking (cannot be set earlier,
* or else reattaching goes wrong)
*/
vertofs += me->totvert;
edgeofs += me->totedge;
loopofs += me->totloop;
/* free base, now that data is merged */
if (base->object != ob)
if (base->object != ob) {
ED_base_object_free_and_unlink(bmain, scene, base);
}
}
}
CTX_DATA_END;
@ -529,34 +575,20 @@ int join_mesh_exec(bContext *C, wmOperator *op)
if (totcol) {
me->mat = matar;
ob->mat = MEM_callocN(sizeof(void *) * totcol, "join obmatar");
ob->matbits = MEM_callocN(sizeof(char) * totcol, "join obmatbits");
ob->mat = MEM_callocN(sizeof(*ob->mat) * totcol, "join obmatar");
ob->matbits = MEM_callocN(sizeof(*ob->matbits) * totcol, "join obmatbits");
MEM_freeN(matmap);
}
else
MEM_freeN(matar);
ob->totcol = me->totcol = totcol;
if (matmap) MEM_freeN(matmap);
/* other mesh users */
test_all_objects_materials(bmain, (ID *)me);
/* free temp copy of destination shapekeys (if applicable) */
if (nkey) {
/* XXX 2.5 Animato */
#if 0
/* free it's ipo too - both are not actually freed from memory yet as ID-blocks */
if (nkey->ipo) {
BKE_ipo_free(nkey->ipo);
BLI_remlink(&bmain->ipo, nkey->ipo);
MEM_freeN(nkey->ipo);
}
#endif
BKE_key_free(nkey);
BLI_remlink(&bmain->key, nkey);
MEM_freeN(nkey);
/* We can assume nobody is using that ID currently. */
BKE_libblock_free_ex(bmain, nkey, false, false);
}
/* ensure newly inserted keys are time sorted */
@ -564,7 +596,7 @@ int join_mesh_exec(bContext *C, wmOperator *op)
BKE_key_sort(key);
}
DAG_relations_tag_update(bmain); // removed objects, need to rebuild dag
DAG_relations_tag_update(bmain); /* removed objects, need to rebuild dag */
DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA);

@ -387,8 +387,9 @@ typedef struct Nearest2dPrecalc {
float ray_direction_local[3];
float ray_inv_dir[3];
float depth_range[2];
float ray_min_dist;
float pmat[4][4]; /* perspective matrix multiplied by object matrix */
bool is_persp;
float win_half[2];
float mval[2];
@ -400,13 +401,14 @@ typedef struct Nearest2dPrecalc {
*/
static void dist_squared_to_projected_aabb_precalc(
struct Nearest2dPrecalc *neasrest_precalc,
float lpmat[4][4], const float win_half[2],
const float depth_range[2], const float mval[2],
float lpmat[4][4], bool is_persp, const float win_half[2],
const float ray_min_dist, const float mval[2],
const float ray_origin_local[3], const float ray_direction_local[3])
{
copy_m4_m4(neasrest_precalc->pmat, lpmat);
neasrest_precalc->is_persp = is_persp;
copy_v2_v2(neasrest_precalc->win_half, win_half);
copy_v2_v2(neasrest_precalc->depth_range, depth_range);
neasrest_precalc->ray_min_dist = ray_min_dist;
copy_v3_v3(neasrest_precalc->ray_origin_local, ray_origin_local);
copy_v3_v3(neasrest_precalc->ray_direction_local, ray_direction_local);
@ -513,11 +515,11 @@ static float dist_squared_to_projected_aabb(
#define IGNORE_BEHIND_RAY
#ifdef IGNORE_BEHIND_RAY
/* `if rtmax < depth_min`, the hit is behind us */
if (rtmax < data->depth_range[0]) {
if (rtmax < data->ray_min_dist) {
/* Test if the entire AABB is behind us */
float depth = depth_get(
local_bvmax, data->ray_origin_local, data->ray_direction_local);
if (depth < (data->depth_range[0])) {
if (depth < (data->ray_min_dist)) {
return FLT_MAX;
}
}
@ -528,11 +530,11 @@ static float dist_squared_to_projected_aabb(
}
#ifdef IGNORE_BEHIND_RAY
/* `if rtmin < depth_min`, the hit is behing us */
else if (rtmin < data->depth_range[0]) {
else if (rtmin < data->ray_min_dist) {
/* Test if the entire AABB is behind us */
float depth = depth_get(
local_bvmax, data->ray_origin_local, data->ray_direction_local);
if (depth < (data->depth_range[0])) {
if (depth < (data->ray_min_dist)) {
return FLT_MAX;
}
}
@ -549,20 +551,24 @@ static float dist_squared_to_projected_aabb(
float scale = fabsf(local_bvmax[main_axis] - local_bvmin[main_axis]);
float (*pmat)[4] = data->pmat;
float depth_a = mul_project_m4_v3_zfac(pmat, va);
float depth_b = depth_a + pmat[main_axis][3] * scale;
float va2d[2] = {
(dot_m4_v3_row_x(pmat, va) + pmat[3][0]),
(dot_m4_v3_row_y(pmat, va) + pmat[3][1]),
};
float vb2d[2] = {
(va2d[0] + pmat[main_axis][0] * scale) / depth_b,
(va2d[1] + pmat[main_axis][1] * scale) / depth_b,
(va2d[0] + pmat[main_axis][0] * scale),
(va2d[1] + pmat[main_axis][1] * scale),
};
va2d[0] /= depth_a;
va2d[1] /= depth_a;
if (data->is_persp) {
float depth_a = mul_project_m4_v3_zfac(pmat, va);
float depth_b = depth_a + pmat[main_axis][3] * scale;
va2d[0] /= depth_a;
va2d[1] /= depth_a;
vb2d[0] /= depth_b;
vb2d[1] /= depth_b;
}
va2d[0] += 1.0f;
va2d[1] += 1.0f;
@ -606,13 +612,13 @@ static float dist_squared_to_projected_aabb(
static float dist_squared_to_projected_aabb_simple(
float lpmat[4][4], const float win_half[2],
const float depth_range[2], const float mval[2],
const float ray_min_dist, const float mval[2],
const float ray_origin_local[3], const float ray_direction_local[3],
const float bbmin[3], const float bbmax[3])
{
struct Nearest2dPrecalc data;
dist_squared_to_projected_aabb_precalc(
&data, lpmat, win_half, depth_range,
&data, lpmat, true, win_half, ray_min_dist,
mval, ray_origin_local, ray_direction_local);
bool dummy[3] = {true, true, true};
@ -641,11 +647,11 @@ static float dist_aabb_to_plane(
typedef struct Nearest2dUserData {
struct Nearest2dPrecalc data_precalc;
bool is_persp;
float dist_px_sq;
bool r_axis_closest[3];
float depth_range[2];
void *userdata;
int index;
float co[3];
@ -674,11 +680,11 @@ static bool cb_walk_leaf_snap_vert(const BVHTreeAxisRange *bounds, int index, vo
};
if (test_projected_vert_dist(
neasrest_precalc->depth_range,
data->depth_range,
neasrest_precalc->mval, co,
neasrest_precalc->pmat,
neasrest_precalc->win_half,
data->is_persp,
neasrest_precalc->is_persp,
&data->dist_px_sq,
data->co))
{
@ -697,11 +703,11 @@ static bool cb_walk_leaf_snap_edge(const BVHTreeAxisRange *UNUSED(bounds), int i
get_edge_verts(data->userdata, index, v_pair);
if (test_projected_edge_dist(
neasrest_precalc->depth_range,
data->depth_range,
neasrest_precalc->mval,
neasrest_precalc->pmat,
neasrest_precalc->win_half,
data->is_persp,
neasrest_precalc->is_persp,
neasrest_precalc->ray_origin_local,
neasrest_precalc->ray_direction_local,
v_pair[0], v_pair[1],
@ -1114,15 +1120,15 @@ static bool snapDerivedMesh(
float lpmat[4][4];
float ray_org_local[3];
float depth_range_local[2];
float ray_min_dist;
if (ELEM(snapdata->snap_to, SCE_SNAP_MODE_VERTEX, SCE_SNAP_MODE_EDGE)) {
mul_m4_m4m4(lpmat, snapdata->pmat, obmat);
copy_v3_v3(ray_org_local, snapdata->ray_origin);
mul_m4_v3(imat, ray_org_local);
depth_range_local[0] = snapdata->depth_range[0] * local_scale;
depth_range_local[1] = local_depth + depth_range_local[0];
ray_min_dist = snapdata->depth_range[0] * local_scale;
}
copy_v3_v3(ray_org_local, snapdata->ray_origin);
mul_m4_v3(imat, ray_org_local);
if (do_bb) {
BoundBox *bb = BKE_object_boundbox_get(ob);
@ -1136,7 +1142,7 @@ static bool snapDerivedMesh(
/* In vertex and edges you need to get the pixel distance from ray to BoundBox, see T46816. */
if (ELEM(snapdata->snap_to, SCE_SNAP_MODE_VERTEX, SCE_SNAP_MODE_EDGE)) {
float dist_px_sq = dist_squared_to_projected_aabb_simple(
lpmat, snapdata->win_half, snapdata->depth_range, snapdata->mval,
lpmat, snapdata->win_half, ray_min_dist, snapdata->mval,
ray_org_local, ray_normal_local, bb->vec[0], bb->vec[6]);
if (dist_px_sq > SQUARE(*dist_px))
{
@ -1246,11 +1252,6 @@ static bool snapDerivedMesh(
* because even in the Orthografic view, in some cases,
* the ray can start inside the object (see T50486) */
if (len_diff > 400.0f) {
float ray_org_local[3];
copy_v3_v3(ray_org_local, snapdata->ray_origin);
mul_m4_v3(imat, ray_org_local);
/* We pass a temp ray_start, set from object's boundbox, to avoid precision issues with
* very far away ray_start values (as returned in case of ortho view3d), see T38358.
*/
@ -1321,15 +1322,16 @@ static bool snapDerivedMesh(
BVHTreeFromMeshType treedata_type = {.userdata = treedata, .type = SNAP_MESH};
Nearest2dUserData neasrest2d = {
.is_persp = snapdata->view_proj == VIEW_PROJ_PERSP,
.dist_px_sq = SQUARE(*dist_px),
.r_axis_closest = {1.0f, 1.0f, 1.0f},
.depth_range = {snapdata->depth_range[0], *ray_depth + snapdata->depth_range[0]},
.userdata = &treedata_type,
.index = -1};
dist_squared_to_projected_aabb_precalc(
&neasrest2d.data_precalc, lpmat, snapdata->win_half,
depth_range_local, snapdata->mval, ray_org_local, ray_normal_local);
&neasrest2d.data_precalc, lpmat,
snapdata->view_proj == VIEW_PROJ_PERSP, snapdata->win_half,
ray_min_dist, snapdata->mval, ray_org_local, ray_normal_local);
BVHTree_WalkLeafCallback cb_walk_leaf =
(snapdata->snap_to == SCE_SNAP_MODE_VERTEX) ?
@ -1612,19 +1614,19 @@ static bool snapEditMesh(
BVHTreeFromMeshType treedata_type = {.userdata = treedata, .type = SNAP_EDIT_MESH};
Nearest2dUserData neasrest2d = {
.is_persp = snapdata->view_proj == VIEW_PROJ_PERSP,
.dist_px_sq = SQUARE(*dist_px),
.r_axis_closest = {1.0f, 1.0f, 1.0f},
.depth_range = {snapdata->depth_range[0], *ray_depth + snapdata->depth_range[0]},
.userdata = &treedata_type,
.index = -1};
float lpmat[4][4], depth_range_local[2];
float lpmat[4][4];
mul_m4_m4m4(lpmat, snapdata->pmat, obmat);
depth_range_local[0] = snapdata->depth_range[0] * local_scale;
depth_range_local[1] = local_depth + depth_range_local[0];
dist_squared_to_projected_aabb_precalc(
&neasrest2d.data_precalc, lpmat, snapdata->win_half,
snapdata->depth_range, snapdata->mval, ray_org_local, ray_normal_local);
&neasrest2d.data_precalc, lpmat,
snapdata->view_proj == VIEW_PROJ_PERSP, snapdata->win_half,
(snapdata->depth_range[0] * local_scale), snapdata->mval,
ray_org_local, ray_normal_local);
BVHTree_WalkLeafCallback cb_walk_leaf =
(snapdata->snap_to == SCE_SNAP_MODE_VERTEX) ?
@ -2080,23 +2082,37 @@ static bool transform_snap_context_project_view3d_mixed_impl(
BLI_assert(snap_to_flag != 0);
BLI_assert((snap_to_flag & ~(1 | 2 | 4)) == 0);
for (int i = 0; i < 3; i++) {
if ((snap_to_flag & (1 << i)) && (is_hit == false || use_depth)) {
if (ED_transform_snap_object_project_view3d(
sctx,
elem_type[i], params,
mval, dist_px, &ray_depth,
r_co, r_no))
{
is_hit = true;
if (use_depth == false) {
ray_depth = BVH_RAYCAST_DIST_MAX;
}
else {
if (use_depth) {
const float dist_px_orig = *dist_px;
for (int i = 2; i >= 0; i--) {
if (snap_to_flag & (1 << i)) {
if (i == 0)
*dist_px = dist_px_orig;
if (ED_transform_snap_object_project_view3d(
sctx,
elem_type[i], params,
mval, dist_px, &ray_depth,
r_co, r_no))
{
/* 0.01 is a random but small value to prioritizing
* the first elements of the loop */
ray_depth -= 0.01f;
ray_depth += 0.01f;
is_hit = true;
}
}
}
}
else {
for (int i = 0; i < 3; i++) {
if (snap_to_flag & (1 << i)) {
if (ED_transform_snap_object_project_view3d(
sctx,
elem_type[i], params,
mval, dist_px, &ray_depth,
r_co, r_no))
{
is_hit = true;
break;
}
}
}

@ -609,7 +609,7 @@ static GPUNodeLink *lamp_get_visibility(GPUMaterial *mat, GPULamp *lamp, GPUNode
GPU_link(mat, "lamp_visibility_spot",
GPU_dynamic_uniform(&lamp->spotsi, GPU_DYNAMIC_LAMP_SPOTSIZE, lamp->ob),
GPU_dynamic_uniform(&lamp->spotbl, GPU_DYNAMIC_LAMP_SPOTSIZE, lamp->ob),
GPU_dynamic_uniform(&lamp->spotbl, GPU_DYNAMIC_LAMP_SPOTBLEND, lamp->ob),
inpr, visifac, &visifac);
}

@ -3937,7 +3937,7 @@ static void rna_def_userdef_system(BlenderRNA *brna)
prop = RNA_def_property(srna, "dpi", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "dpi");
RNA_def_property_range(prop, 16, 256);
RNA_def_property_range(prop, 48, 144);
RNA_def_property_ui_text(prop, "DPI", "Font size and resolution for display");
RNA_def_property_update(prop, 0, "rna_userdef_dpi_update");

@ -138,6 +138,7 @@ static PyObject *PyInit_gpu(void)
PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_MAT_EMIT);
PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_MAT_AMB);
PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_MAT_ALPHA);
PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_MAT_MIR);
/* -------------------------------------------------------------------- */

@ -52,6 +52,7 @@ def render_file(filepath):
"--background",
"-noaudio",
"--factory-startup",
"--enable-autoexec",
filepath,
"-E", "CYCLES",
# Run with OSL enabled