diff options
Diffstat (limited to 'source/blender/blenkernel/intern')
69 files changed, 3036 insertions, 1203 deletions
diff --git a/source/blender/blenkernel/intern/CCGSubSurf.c b/source/blender/blenkernel/intern/CCGSubSurf.c index 6cda0a1bc33..623fb50b62c 100644 --- a/source/blender/blenkernel/intern/CCGSubSurf.c +++ b/source/blender/blenkernel/intern/CCGSubSurf.c @@ -119,7 +119,7 @@ static void _ehash_insert(EHash *eh, EHEntry *entry) eh->buckets[hash] = entry; eh->numEntries++; - if (eh->numEntries > (numBuckets * 3)) { + if (UNLIKELY(eh->numEntries > (numBuckets * 3))) { EHEntry **oldBuckets = eh->buckets; eh->curSize = kHashSizes[++eh->curSizeIdx]; @@ -1274,7 +1274,7 @@ CCGError ccgSubSurf_syncFace(CCGSubSurf *ss, CCGFaceHDL fHDL, int numVerts, CCGV CCGFace *f = NULL, *fNew; int j, k, topologyChanged = 0; - if (numVerts > ss->lenTempArrays) { + if (UNLIKELY(numVerts > ss->lenTempArrays)) { ss->lenTempArrays = (numVerts < ss->lenTempArrays * 2) ? ss->lenTempArrays * 2 : numVerts; ss->tempVerts = MEM_reallocN(ss->tempVerts, sizeof(*ss->tempVerts) * ss->lenTempArrays); ss->tempEdges = MEM_reallocN(ss->tempEdges, sizeof(*ss->tempEdges) * ss->lenTempArrays); diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c index a70238da34e..52ded77b117 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.c +++ b/source/blender/blenkernel/intern/DerivedMesh.c @@ -37,12 +37,14 @@ #include "DNA_cloth_types.h" #include "DNA_key_types.h" +#include "DNA_material_types.h" #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" #include "DNA_object_types.h" #include "DNA_scene_types.h" #include "BLI_blenlib.h" +#include "BLI_bitmap.h" #include "BLI_math.h" #include "BLI_utildefines.h" #include "BLI_linklist.h" @@ -500,11 +502,36 @@ void DM_update_materials(DerivedMesh *dm, Object *ob) dm->mat = MEM_callocN(totmat * sizeof(*dm->mat), "DerivedMesh.mat"); - for (i = 1; i < totmat; i++) { - dm->mat[i] = give_current_material(ob, i); + /* we leave last material as empty - rationale here is being able to index + * the materials by using the mf->mat_nr directly and leaving the last + * material as NULL in case no materials exist on mesh, so indexing will not fail */ + for (i = 0; i < totmat - 1; i++) { + dm->mat[i] = give_current_material(ob, i + 1); } } +MTFace *DM_paint_uvlayer_active_get(DerivedMesh *dm, int mat_nr) +{ + MTFace *tf_base; + + BLI_assert(mat_nr < dm->totmat); + + if (dm->mat[mat_nr] && dm->mat[mat_nr]->texpaintslot && + dm->mat[mat_nr]->texpaintslot[dm->mat[mat_nr]->paint_active_slot].uvname) + { + tf_base = CustomData_get_layer_named(&dm->faceData, CD_MTFACE, + dm->mat[mat_nr]->texpaintslot[dm->mat[mat_nr]->paint_active_slot].uvname); + /* This can fail if we have changed the name in the UV layer list and have assigned the old name in the material + * texture slot.*/ + if (!tf_base) + tf_base = CustomData_get_layer(&dm->faceData, CD_MTFACE); + } + else { + tf_base = CustomData_get_layer(&dm->faceData, CD_MTFACE); + } + + return tf_base; +} void DM_to_mesh(DerivedMesh *dm, Mesh *me, Object *ob, CustomDataMask mask) { @@ -1107,7 +1134,7 @@ static void weightpaint_color(unsigned char r_col[4], DMWeightColorInfo *dm_wcin static void calc_weightpaint_vert_color( unsigned char r_col[4], - MDeformVert *dv, + const MDeformVert *dv, DMWeightColorInfo *dm_wcinfo, const int defbase_tot, const int defbase_act, const bool *defbase_sel, const int defbase_sel_tot, @@ -1122,7 +1149,7 @@ static void calc_weightpaint_vert_color( bool was_a_nonzero = false; unsigned int i; - MDeformWeight *dw = dv->dw; + const MDeformWeight *dw = dv->dw; for (i = dv->totweight; i != 0; i--, dw++) { /* in multipaint, get the average if auto normalize is inactive * get the sum if it is active */ @@ -1995,9 +2022,7 @@ static void editbmesh_calc_modifiers(Scene *scene, Object *ob, BMEditMesh *em, D previewmd = modifiers_getLastPreview(scene, md, required_mode); /* even if the modifier doesn't need the data, to make a preview it may */ if (previewmd) { - if (do_mod_wmcol) { - previewmask = CD_MASK_MDEFORMVERT; - } + previewmask = CD_MASK_MDEFORMVERT; } } @@ -2473,6 +2498,28 @@ DerivedMesh *editbmesh_get_derived_base(Object *obedit, BMEditMesh *em) return getEditDerivedBMesh(em, obedit, NULL); } +/***/ + +/* get derived mesh from an object, using editbmesh if available. */ +DerivedMesh *object_get_derived_final(Object *ob, const bool for_render) +{ + Mesh *me = ob->data; + BMEditMesh *em = me->edit_btmesh; + + if (for_render) { + /* TODO(sergey): use proper derived render here in the future. */ + return ob->derivedFinal; + } + + if (em) { + DerivedMesh *dm = em->derivedFinal; + return dm; + } + + return ob->derivedFinal; +} + + /* UNUSED */ #if 0 @@ -2533,6 +2580,46 @@ DMCoNo *mesh_get_mapped_verts_nors(Scene *scene, Object *ob) #endif +/* same as above but for vert coords */ +typedef struct { + float (*vertexcos)[3]; + BLI_bitmap *vertex_visit; +} MappedUserData; + +static void make_vertexcos__mapFunc(void *userData, int index, const float co[3], + const float UNUSED(no_f[3]), const short UNUSED(no_s[3])) +{ + MappedUserData *mappedData = (MappedUserData *)userData; + + if (BLI_BITMAP_TEST(mappedData->vertex_visit, index) == 0) { + /* we need coord from prototype vertex, not from copies, + * assume they stored in the beginning of vertex array stored in DM + * (mirror modifier for eg does this) */ + copy_v3_v3(mappedData->vertexcos[index], co); + BLI_BITMAP_ENABLE(mappedData->vertex_visit, index); + } +} + +void mesh_get_mapped_verts_coords(DerivedMesh *dm, float (*r_cos)[3], const int totcos) +{ + float (*vertexcos)[3]; + + if (dm->foreachMappedVert) { + MappedUserData userData; + memset(r_cos, 0, sizeof(r_cos) * totcos); + userData.vertexcos = r_cos; + userData.vertex_visit = BLI_BITMAP_NEW(totcos, "vertexcos flags"); + dm->foreachMappedVert(dm, make_vertexcos__mapFunc, &userData, DM_FOREACH_NOP); + MEM_freeN(userData.vertex_visit); + } + else { + int i; + for (i = 0; i < totcos; i++) { + dm->getVertCo(dm, i, vertexcos[i]); + } + } +} + /* ******************* GLSL ******************** */ typedef struct { @@ -3090,7 +3177,7 @@ static void navmesh_drawColored(DerivedMesh *dm) static void navmesh_DM_drawFacesTex(DerivedMesh *dm, DMSetDrawOptionsTex setDrawOptions, DMCompareDrawOptions compareDrawOptions, - void *userData) + void *userData, DMDrawFlag UNUSED(flag)) { (void) setDrawOptions; (void) compareDrawOptions; diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c index 8f1382dacc3..c6dcca576fb 100644 --- a/source/blender/blenkernel/intern/action.c +++ b/source/blender/blenkernel/intern/action.c @@ -315,7 +315,7 @@ bActionGroup *action_groups_add_new(bAction *act, const char name[]) void action_groups_add_channel(bAction *act, bActionGroup *agrp, FCurve *fcurve) { /* sanity checks */ - if (ELEM3(NULL, act, agrp, fcurve)) + if (ELEM(NULL, act, agrp, fcurve)) return; /* if no channels anywhere, just add to two lists at the same time */ @@ -417,7 +417,7 @@ void action_groups_remove_channel(bAction *act, FCurve *fcu) bActionGroup *BKE_action_group_find_name(bAction *act, const char name[]) { /* sanity checks */ - if (ELEM3(NULL, act, act->groups.first, name) || (name[0] == 0)) + if (ELEM(NULL, act, act->groups.first, name) || (name[0] == 0)) return NULL; /* do string comparisons */ @@ -526,7 +526,7 @@ bPoseChannel *BKE_pose_channel_active(Object *ob) bArmature *arm = (ob) ? ob->data : NULL; bPoseChannel *pchan; - if (ELEM3(NULL, ob, ob->pose, arm)) { + if (ELEM(NULL, ob, ob->pose, arm)) { return NULL; } diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c index 995b2ac5321..5ee82bb5842 100644 --- a/source/blender/blenkernel/intern/anim_sys.c +++ b/source/blender/blenkernel/intern/anim_sys.c @@ -405,7 +405,7 @@ void action_move_fcurves_by_basepath(bAction *srcAct, bAction *dstAct, const cha FCurve *fcu, *fcn = NULL; /* sanity checks */ - if (ELEM3(NULL, srcAct, dstAct, basepath)) { + if (ELEM(NULL, srcAct, dstAct, basepath)) { if (G.debug & G_DEBUG) { printf("ERROR: action_partition_fcurves_by_basepath(%p, %p, %p) has insufficient info to work with\n", (void *)srcAct, (void *)dstAct, (void *)basepath); @@ -1062,7 +1062,7 @@ KS_Path *BKE_keyingset_find_path(KeyingSet *ks, ID *id, const char group_name[], KS_Path *ksp; /* sanity checks */ - if (ELEM3(NULL, ks, rna_path, id)) + if (ELEM(NULL, ks, rna_path, id)) return NULL; /* loop over paths in the current KeyingSet, finding the first one where all settings match @@ -2338,6 +2338,17 @@ static void animsys_evaluate_nla(ListBase *echannels, PointerRNA *ptr, AnimData /* 3. free temporary evaluation data that's not used elsewhere */ BLI_freelistN(&estrips); + + /* Tag ID as updated so render engines will recognize changes in data + * which is animated but doesn't have actions. + */ + if (ptr->id.data != NULL) { + ID *id = ptr->id.data; + if (!(id->flag & LIB_ANIM_NO_RECALC)) { + id->flag |= LIB_ID_RECALC; + DAG_id_type_tag(G.main, GS(id->name)); + } + } } /* NLA Evaluation function (mostly for use through do_animdata) @@ -2392,7 +2403,7 @@ static void animsys_evaluate_overrides(PointerRNA *ptr, AnimData *adt) /* Overview of how this system works: * 1) Depsgraph sorts data as necessary, so that data is in an order that means - * that all dependencies are resolved before dependants. + * that all dependencies are resolved before dependents. * 2) All normal animation is evaluated, so that drivers have some basis values to * work with * a. NLA stacks are done first, as the Active Actions act as 'tweaking' tracks diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c index 95f8426872d..16b5574709e 100644 --- a/source/blender/blenkernel/intern/armature.c +++ b/source/blender/blenkernel/intern/armature.c @@ -574,7 +574,7 @@ void b_bone_spline_setup(bPoseChannel *pchan, int rest, Mat4 result_array[MAX_BB if (do_scale) { /* correct for scaling when this matrix is used in scaled space */ - mul_serie_m4(result_array[a].mat, iscalemat, result_array[a].mat, scalemat, NULL, NULL, NULL, NULL, NULL); + mul_m4_series(result_array[a].mat, iscalemat, result_array[a].mat, scalemat); } } } @@ -622,8 +622,7 @@ static void pchan_b_bone_defmats(bPoseChannel *pchan, bPoseChanDeform *pdef_info invert_m4_m4(tmat, b_bone_rest[a].mat); - mul_serie_m4(b_bone_mats[a + 1].mat, pchan->chan_mat, bone->arm_mat, b_bone[a].mat, tmat, b_bone_mats[0].mat, - NULL, NULL, NULL); + mul_m4_series(b_bone_mats[a + 1].mat, pchan->chan_mat, bone->arm_mat, b_bone[a].mat, tmat, b_bone_mats[0].mat); if (use_quaternion) mat4_to_dquat(&b_bone_dual_quats[a], bone->arm_mat, b_bone_mats[a + 1].mat); @@ -1042,7 +1041,7 @@ void armature_deform_verts(Object *armOb, Object *target, DerivedMesh *dm, float if (!use_quaternion) /* quaternion already is scale corrected */ mul_m3_fl(smat, armature_weight / contrib); - mul_serie_m3(defMats[i], tmpmat, pre, smat, post, NULL, NULL, NULL, NULL); + mul_m3_series(defMats[i], post, smat, pre, tmpmat); } } @@ -1881,7 +1880,7 @@ static void splineik_init_tree_from_pchan(Scene *scene, Object *UNUSED(ob), bPos */ /* only happens on reload file, but violates depsgraph still... fix! */ - if (ELEM3(NULL, ikData->tar->curve_cache, ikData->tar->curve_cache->path, ikData->tar->curve_cache->path->data)) { + if (ELEM(NULL, ikData->tar->curve_cache, ikData->tar->curve_cache->path, ikData->tar->curve_cache->path->data)) { BKE_displist_make_curveTypes(scene, ikData->tar, 0); /* path building may fail in EditMode after removing verts [#33268]*/ diff --git a/source/blender/blenkernel/intern/blender.c b/source/blender/blenkernel/intern/blender.c index 9be9db77d39..fff8265a158 100644 --- a/source/blender/blenkernel/intern/blender.c +++ b/source/blender/blenkernel/intern/blender.c @@ -170,7 +170,7 @@ static void clear_global(void) static bool clean_paths_visit_cb(void *UNUSED(userdata), char *path_dst, const char *path_src) { strcpy(path_dst, path_src); - BLI_clean(path_dst); + BLI_path_native_slash(path_dst); return !STREQ(path_dst, path_src); } @@ -182,7 +182,7 @@ static void clean_paths(Main *main) BKE_bpath_traverse_main(main, clean_paths_visit_cb, BKE_BPATH_TRAVERSE_SKIP_MULTIFILE, NULL); for (scene = main->scene.first; scene; scene = scene->id.next) { - BLI_clean(scene->r.pic); + BLI_path_native_slash(scene->r.pic); } } @@ -479,7 +479,9 @@ int BKE_read_file(bContext *C, const char *filepath, ReportList *reports) return (bfd ? retval : BKE_READ_FILE_FAIL); } -int BKE_read_file_from_memory(bContext *C, const void *filebuf, int filelength, ReportList *reports, int update_defaults) +bool BKE_read_file_from_memory( + bContext *C, const void *filebuf, int filelength, + ReportList *reports, bool update_defaults) { BlendFileData *bfd; @@ -496,7 +498,9 @@ int BKE_read_file_from_memory(bContext *C, const void *filebuf, int filelength, } /* memfile is the undo buffer */ -int BKE_read_file_from_memfile(bContext *C, MemFile *memfile, ReportList *reports) +bool BKE_read_file_from_memfile( + bContext *C, MemFile *memfile, + ReportList *reports) { BlendFileData *bfd; diff --git a/source/blender/blenkernel/intern/bpath.c b/source/blender/blenkernel/intern/bpath.c index dc2d0924bba..3cd26dacebd 100644 --- a/source/blender/blenkernel/intern/bpath.c +++ b/source/blender/blenkernel/intern/bpath.c @@ -107,7 +107,7 @@ typedef struct BPathRemap_Data { int count_failed; } BPathRemap_Data; -static bool makeFilesRelative_visit_cb(void *userdata, char *path_dst, const char *path_src) +static bool bpath_relative_convert_visit_cb(void *userdata, char *path_dst, const char *path_src) { BPathRemap_Data *data = (BPathRemap_Data *)userdata; @@ -133,6 +133,7 @@ static bool makeFilesRelative_visit_cb(void *userdata, char *path_dst, const cha void BKE_bpath_relative_convert(Main *bmain, const char *basedir, ReportList *reports) { BPathRemap_Data data = {NULL}; + const int flag = BKE_BPATH_TRAVERSE_SKIP_LIBRARY; if (basedir[0] == '\0') { printf("%s: basedir='', this is a bug\n", __func__); @@ -142,14 +143,14 @@ void BKE_bpath_relative_convert(Main *bmain, const char *basedir, ReportList *re data.basedir = basedir; data.reports = reports; - BKE_bpath_traverse_main(bmain, makeFilesRelative_visit_cb, 0, (void *)&data); + BKE_bpath_traverse_main(bmain, bpath_relative_convert_visit_cb, flag, (void *)&data); BKE_reportf(reports, data.count_failed ? RPT_WARNING : RPT_INFO, "Total files %d | Changed %d | Failed %d", data.count_tot, data.count_changed, data.count_failed); } -static bool makeFilesAbsolute_visit_cb(void *userdata, char *path_dst, const char *path_src) +static bool bpath_absolute_convert_visit_cb(void *userdata, char *path_dst, const char *path_src) { BPathRemap_Data *data = (BPathRemap_Data *)userdata; @@ -176,6 +177,7 @@ static bool makeFilesAbsolute_visit_cb(void *userdata, char *path_dst, const cha void BKE_bpath_absolute_convert(Main *bmain, const char *basedir, ReportList *reports) { BPathRemap_Data data = {NULL}; + const int flag = BKE_BPATH_TRAVERSE_SKIP_LIBRARY; if (basedir[0] == '\0') { printf("%s: basedir='', this is a bug\n", __func__); @@ -185,7 +187,7 @@ void BKE_bpath_absolute_convert(Main *bmain, const char *basedir, ReportList *re data.basedir = basedir; data.reports = reports; - BKE_bpath_traverse_main(bmain, makeFilesAbsolute_visit_cb, 0, (void *)&data); + BKE_bpath_traverse_main(bmain, bpath_absolute_convert_visit_cb, flag, (void *)&data); BKE_reportf(reports, data.count_failed ? RPT_WARNING : RPT_INFO, "Total files %d | Changed %d | Failed %d", @@ -422,7 +424,7 @@ void BKE_bpath_traverse_id(Main *bmain, ID *id, BPathVisitor visit_cb, const int Image *ima; ima = (Image *)id; if (ima->packedfile == NULL || (flag & BKE_BPATH_TRAVERSE_SKIP_PACKED) == 0) { - if (ELEM3(ima->source, IMA_SRC_FILE, IMA_SRC_MOVIE, IMA_SRC_SEQUENCE)) { + if (ELEM(ima->source, IMA_SRC_FILE, IMA_SRC_MOVIE, IMA_SRC_SEQUENCE)) { if (rewrite_path_fixed(ima->name, visit_cb, absbase, bpath_user_data)) { if (!ima->packedfile) { BKE_image_signal(ima, NULL, IMA_SIGNAL_RELOAD); diff --git a/source/blender/blenkernel/intern/brush.c b/source/blender/blenkernel/intern/brush.c index 967e89e0dd1..76b0cad337f 100644 --- a/source/blender/blenkernel/intern/brush.c +++ b/source/blender/blenkernel/intern/brush.c @@ -83,6 +83,7 @@ static void brush_defaults(Brush *brush) brush->plane_trim = 0.5f; brush->clone.alpha = 0.5f; brush->normal_weight = 0.0f; + brush->fill_threshold = 0.2f; brush->flag |= BRUSH_ALPHA_PRESSURE; /* BRUSH PAINT TOOL SETTINGS */ @@ -90,6 +91,8 @@ static void brush_defaults(Brush *brush) brush->rgb[1] = 1.0f; brush->rgb[2] = 1.0f; + zero_v3(brush->secondary_rgb); + /* BRUSH STROKE SETTINGS */ brush->flag |= (BRUSH_SPACE | BRUSH_SPACE_ATTEN); brush->spacing = 10; /* how far each brush dot should be spaced as a percentage of brush diameter */ @@ -161,6 +164,9 @@ Brush *BKE_brush_copy(Brush *brush) if (brush->mask_mtex.tex) id_us_plus((ID *)brush->mask_mtex.tex); + if (brush->paint_curve) + id_us_plus((ID *)brush->paint_curve); + if (brush->icon_imbuf) brushn->icon_imbuf = IMB_dupImBuf(brush->icon_imbuf); @@ -180,11 +186,9 @@ Brush *BKE_brush_copy(Brush *brush) /* not brush itself */ void BKE_brush_free(Brush *brush) { - if (brush->mtex.tex) - brush->mtex.tex->id.us--; - - if (brush->mask_mtex.tex) - brush->mask_mtex.tex->id.us--; + id_us_min((ID *)brush->mtex.tex); + id_us_min((ID *)brush->mask_mtex.tex); + id_us_min((ID *)brush->paint_curve); if (brush->icon_imbuf) IMB_freeImBuf(brush->icon_imbuf); @@ -192,6 +196,9 @@ void BKE_brush_free(Brush *brush) BKE_previewimg_free(&(brush->preview)); curvemapping_free(brush->curve); + + if (brush->gradient) + MEM_freeN(brush->gradient); } static void extern_local_brush(Brush *brush) @@ -199,6 +206,7 @@ static void extern_local_brush(Brush *brush) id_lib_extern((ID *)brush->mtex.tex); id_lib_extern((ID *)brush->mask_mtex.tex); id_lib_extern((ID *)brush->clone.image); + id_lib_extern((ID *)brush->paint_curve); } void BKE_brush_make_local(Brush *brush) @@ -742,10 +750,23 @@ float BKE_brush_sample_masktex(const Scene *scene, Brush *br, rgba, rgba + 1, rgba + 2, rgba + 3, thread, pool); } + CLAMP(intensity, 0.0f, 1.0f); + + switch (br->mask_pressure) { + case BRUSH_MASK_PRESSURE_CUTOFF: + intensity = ((1.0f - intensity) < ups->size_pressure_value) ? 1.0f : 0.0f; + break; + case BRUSH_MASK_PRESSURE_RAMP: + intensity = ups->size_pressure_value + intensity * (1.0f - ups->size_pressure_value); + break; + default: + break; + } + return intensity; } -/* Unified Size and Strength */ +/* Unified Size / Strength / Color */ /* XXX: be careful about setting size and unprojected radius * because they depend on one another @@ -760,6 +781,29 @@ float BKE_brush_sample_masktex(const Scene *scene, Brush *br, * In any case, a better solution is needed to prevent * inconsistency. */ + +float *BKE_brush_color_get(const struct Scene *scene, struct Brush *brush) +{ + UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings; + return (ups->flag & UNIFIED_PAINT_COLOR) ? ups->rgb : brush->rgb; +} + +float *BKE_brush_secondary_color_get(const struct Scene *scene, struct Brush *brush) +{ + UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings; + return (ups->flag & UNIFIED_PAINT_COLOR) ? ups->secondary_rgb : brush->secondary_rgb; +} + +void BKE_brush_color_set(struct Scene *scene, struct Brush *brush, const float color[3]) +{ + UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings; + + if (ups->flag & UNIFIED_PAINT_COLOR) + copy_v3_v3(ups->rgb, color); + else + copy_v3_v3(brush->rgb, color); +} + void BKE_brush_size_set(Scene *scene, Brush *brush, int size) { UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings; @@ -886,39 +930,27 @@ void BKE_brush_scale_size(int *r_brush_size, void BKE_brush_jitter_pos(const Scene *scene, Brush *brush, const float pos[2], float jitterpos[2]) { - int use_jitter = (brush->flag & BRUSH_ABSOLUTE_JITTER) ? - (brush->jitter_absolute != 0) : (brush->jitter != 0); + float rand_pos[2]; + float spread; + int diameter; - /* jitter-ed brush gives weird and unpredictable result for this - * kinds of stroke, so manually disable jitter usage (sergey) */ - use_jitter &= (brush->flag & (BRUSH_DRAG_DOT | BRUSH_ANCHORED)) == 0; + do { + rand_pos[0] = BLI_rng_get_float(brush_rng) - 0.5f; + rand_pos[1] = BLI_rng_get_float(brush_rng) - 0.5f; + } while (len_squared_v2(rand_pos) > (0.5f * 0.5f)); - if (use_jitter) { - float rand_pos[2]; - float spread; - int diameter; - do { - rand_pos[0] = BLI_rng_get_float(brush_rng) - 0.5f; - rand_pos[1] = BLI_rng_get_float(brush_rng) - 0.5f; - } while (len_squared_v2(rand_pos) > (0.5f * 0.5f)); - - - if (brush->flag & BRUSH_ABSOLUTE_JITTER) { - diameter = 2 * brush->jitter_absolute; - spread = 1.0; - } - else { - diameter = 2 * BKE_brush_size_get(scene, brush); - spread = brush->jitter; - } - /* find random position within a circle of diameter 1 */ - jitterpos[0] = pos[0] + 2 * rand_pos[0] * diameter * spread; - jitterpos[1] = pos[1] + 2 * rand_pos[1] * diameter * spread; + if (brush->flag & BRUSH_ABSOLUTE_JITTER) { + diameter = 2 * brush->jitter_absolute; + spread = 1.0; } else { - copy_v2_v2(jitterpos, pos); + diameter = 2 * BKE_brush_size_get(scene, brush); + spread = brush->jitter; } + /* find random position within a circle of diameter 1 */ + jitterpos[0] = pos[0] + 2 * rand_pos[0] * diameter * spread; + jitterpos[1] = pos[1] + 2 * rand_pos[1] * diameter * spread; } void BKE_brush_randomize_texture_coordinates(UnifiedPaintSettings *ups, bool mask) diff --git a/source/blender/blenkernel/intern/bvhutils.c b/source/blender/blenkernel/intern/bvhutils.c index f85a91b66cb..4ad577a7bda 100644 --- a/source/blender/blenkernel/intern/bvhutils.c +++ b/source/blender/blenkernel/intern/bvhutils.c @@ -77,288 +77,6 @@ static float sphereray_tri_intersection(const BVHTreeRay *ray, float radius, con return FLT_MAX; } - -/* - * Function adapted from David Eberly's distance tools (LGPL) - * http://www.geometrictools.com/LibFoundation/Distance/Distance.html - */ -float nearest_point_in_tri_surface_squared( - const float v0[3], const float v1[3], const float v2[3], - const float p[3], int *v, int *e, float nearest[3]) -{ - float diff[3]; - float e0[3]; - float e1[3]; - float A00; - float A01; - float A11; - float B0; - float B1; - float C; - float Det; - float S; - float T; - float sqrDist; - int lv = -1, le = -1; - - sub_v3_v3v3(diff, v0, p); - sub_v3_v3v3(e0, v1, v0); - sub_v3_v3v3(e1, v2, v0); - - A00 = dot_v3v3(e0, e0); - A01 = dot_v3v3(e0, e1); - A11 = dot_v3v3(e1, e1); - B0 = dot_v3v3(diff, e0); - B1 = dot_v3v3(diff, e1); - C = dot_v3v3(diff, diff); - Det = fabsf(A00 * A11 - A01 * A01); - S = A01 * B1 - A11 * B0; - T = A01 * B0 - A00 * B1; - - if (S + T <= Det) { - if (S < 0.0f) { - if (T < 0.0f) { /* Region 4 */ - if (B0 < 0.0f) { - T = 0.0f; - if (-B0 >= A00) { - S = 1.0f; - sqrDist = A00 + 2.0f * B0 + C; - lv = 1; - } - else { - if (fabsf(A00) > FLT_EPSILON) - S = -B0 / A00; - else - S = 0.0f; - sqrDist = B0 * S + C; - le = 0; - } - } - else { - S = 0.0f; - if (B1 >= 0.0f) { - T = 0.0f; - sqrDist = C; - lv = 0; - } - else if (-B1 >= A11) { - T = 1.0f; - sqrDist = A11 + 2.0f * B1 + C; - lv = 2; - } - else { - if (fabsf(A11) > FLT_EPSILON) - T = -B1 / A11; - else - T = 0.0f; - sqrDist = B1 * T + C; - le = 1; - } - } - } - else { /* Region 3 */ - S = 0.0f; - if (B1 >= 0.0f) { - T = 0.0f; - sqrDist = C; - lv = 0; - } - else if (-B1 >= A11) { - T = 1.0f; - sqrDist = A11 + 2.0f * B1 + C; - lv = 2; - } - else { - if (fabsf(A11) > FLT_EPSILON) - T = -B1 / A11; - else - T = 0.0; - sqrDist = B1 * T + C; - le = 1; - } - } - } - else if (T < 0.0f) { /* Region 5 */ - T = 0.0f; - if (B0 >= 0.0f) { - S = 0.0f; - sqrDist = C; - lv = 0; - } - else if (-B0 >= A00) { - S = 1.0f; - sqrDist = A00 + 2.0f * B0 + C; - lv = 1; - } - else { - if (fabsf(A00) > FLT_EPSILON) - S = -B0 / A00; - else - S = 0.0f; - sqrDist = B0 * S + C; - le = 0; - } - } - else { /* Region 0 */ - /* Minimum at interior lv */ - float invDet; - if (fabsf(Det) > FLT_EPSILON) - invDet = 1.0f / Det; - else - invDet = 0.0f; - S *= invDet; - T *= invDet; - sqrDist = S * (A00 * S + A01 * T + 2.0f * B0) + - T * (A01 * S + A11 * T + 2.0f * B1) + C; - } - } - else { - float tmp0, tmp1, numer, denom; - - if (S < 0.0f) { /* Region 2 */ - tmp0 = A01 + B0; - tmp1 = A11 + B1; - if (tmp1 > tmp0) { - numer = tmp1 - tmp0; - denom = A00 - 2.0f * A01 + A11; - if (numer >= denom) { - S = 1.0f; - T = 0.0f; - sqrDist = A00 + 2.0f * B0 + C; - lv = 1; - } - else { - if (fabsf(denom) > FLT_EPSILON) - S = numer / denom; - else - S = 0.0f; - T = 1.0f - S; - sqrDist = S * (A00 * S + A01 * T + 2.0f * B0) + - T * (A01 * S + A11 * T + 2.0f * B1) + C; - le = 2; - } - } - else { - S = 0.0f; - if (tmp1 <= 0.0f) { - T = 1.0f; - sqrDist = A11 + 2.0f * B1 + C; - lv = 2; - } - else if (B1 >= 0.0f) { - T = 0.0f; - sqrDist = C; - lv = 0; - } - else { - if (fabsf(A11) > FLT_EPSILON) - T = -B1 / A11; - else - T = 0.0f; - sqrDist = B1 * T + C; - le = 1; - } - } - } - else if (T < 0.0f) { /* Region 6 */ - tmp0 = A01 + B1; - tmp1 = A00 + B0; - if (tmp1 > tmp0) { - numer = tmp1 - tmp0; - denom = A00 - 2.0f * A01 + A11; - if (numer >= denom) { - T = 1.0f; - S = 0.0f; - sqrDist = A11 + 2.0f * B1 + C; - lv = 2; - } - else { - if (fabsf(denom) > FLT_EPSILON) - T = numer / denom; - else - T = 0.0f; - S = 1.0f - T; - sqrDist = S * (A00 * S + A01 * T + 2.0f * B0) + - T * (A01 * S + A11 * T + 2.0f * B1) + C; - le = 2; - } - } - else { - T = 0.0f; - if (tmp1 <= 0.0f) { - S = 1.0f; - sqrDist = A00 + 2.0f * B0 + C; - lv = 1; - } - else if (B0 >= 0.0f) { - S = 0.0f; - sqrDist = C; - lv = 0; - } - else { - if (fabsf(A00) > FLT_EPSILON) - S = -B0 / A00; - else - S = 0.0f; - sqrDist = B0 * S + C; - le = 0; - } - } - } - else { /* Region 1 */ - numer = A11 + B1 - A01 - B0; - if (numer <= 0.0f) { - S = 0.0f; - T = 1.0f; - sqrDist = A11 + 2.0f * B1 + C; - lv = 2; - } - else { - denom = A00 - 2.0f * A01 + A11; - if (numer >= denom) { - S = 1.0f; - T = 0.0f; - sqrDist = A00 + 2.0f * B0 + C; - lv = 1; - } - else { - if (fabsf(denom) > FLT_EPSILON) - S = numer / denom; - else - S = 0.0f; - T = 1.0f - S; - sqrDist = S * (A00 * S + A01 * T + 2.0f * B0) + - T * (A01 * S + A11 * T + 2.0f * B1) + C; - le = 2; - } - } - } - } - - /* Account for numerical round-off error */ - if (sqrDist < FLT_EPSILON) - sqrDist = 0.0f; - - { - float w[3], x[3], y[3], z[3]; - copy_v3_v3(w, v0); - copy_v3_v3(x, e0); - mul_v3_fl(x, S); - copy_v3_v3(y, e1); - mul_v3_fl(y, T); - add_v3_v3v3(z, w, x); - add_v3_v3v3(z, z, y); - //sub_v3_v3v3(d, p, z); - copy_v3_v3(nearest, z); - //d = p - ( v0 + S * e0 + T * e1 ); - } - *v = lv; - *e = le; - - return sqrDist; -} - - /* * BVH from meshes callbacks */ @@ -380,9 +98,10 @@ static void mesh_faces_nearest_point(void *userdata, int index, const float co[3 do { float nearest_tmp[3], dist_sq; - int vertex, edge; - - dist_sq = nearest_point_in_tri_surface_squared(t0, t1, t2, co, &vertex, &edge, nearest_tmp); + + closest_on_tri_to_point_v3(nearest_tmp, co, t0, t1, t2); + dist_sq = len_squared_v3v3(co, nearest_tmp); + if (dist_sq < nearest->dist_sq) { nearest->index = index; nearest->dist_sq = dist_sq; @@ -413,9 +132,10 @@ static void editmesh_faces_nearest_point(void *userdata, int index, const float { float nearest_tmp[3], dist_sq; - int vertex, edge; - dist_sq = nearest_point_in_tri_surface_squared(t0, t1, t2, co, &vertex, &edge, nearest_tmp); + closest_on_tri_to_point_v3(nearest_tmp, co, t0, t1, t2); + dist_sq = len_squared_v3v3(co, nearest_tmp); + if (dist_sq < nearest->dist_sq) { nearest->index = index; nearest->dist_sq = dist_sq; diff --git a/source/blender/blenkernel/intern/camera.c b/source/blender/blenkernel/intern/camera.c index b20ba40c0dd..6ce3abe7a32 100644 --- a/source/blender/blenkernel/intern/camera.c +++ b/source/blender/blenkernel/intern/camera.c @@ -201,7 +201,7 @@ void BKE_camera_params_init(CameraParams *params) /* fallback for non camera objects */ params->clipsta = 0.1f; - params->clipsta = 100.0f; + params->clipend = 100.0f; } void BKE_camera_params_from_object(CameraParams *params, Object *ob) @@ -473,7 +473,7 @@ static void camera_to_frame_view_cb(const float co[3], void *user_data) unsigned int i; for (i = 0; i < 4; i++) { - float nd = dist_squared_to_plane_v3(co, data->plane_tx[i]); + float nd = dist_signed_squared_to_plane_v3(co, data->plane_tx[i]); if (nd < data->dist_vals_sq[i]) { data->dist_vals_sq[i] = nd; } diff --git a/source/blender/blenkernel/intern/cdderivedmesh.c b/source/blender/blenkernel/intern/cdderivedmesh.c index f39b4e20b70..08052127fbf 100644 --- a/source/blender/blenkernel/intern/cdderivedmesh.c +++ b/source/blender/blenkernel/intern/cdderivedmesh.c @@ -49,6 +49,7 @@ #include "BKE_editmesh.h" #include "BKE_curve.h" +#include "DNA_material_types.h" #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" #include "DNA_object_types.h" @@ -668,7 +669,7 @@ static void cdDM_drawFacesTex_common(DerivedMesh *dm, DMSetDrawOptionsTex drawParams, DMSetDrawOptions drawParamsMapped, DMCompareDrawOptions compareDrawOptions, - void *userData) + void *userData, DMDrawFlag uvflag) { CDDerivedMesh *cddm = (CDDerivedMesh *) dm; MVert *mv = cddm->mvert; @@ -679,6 +680,7 @@ static void cdDM_drawFacesTex_common(DerivedMesh *dm, MCol *mcol; int i, orig; int colType, startFace = 0; + bool use_tface = (uvflag & DM_DRAW_USE_ACTIVE_UV) != 0; /* double lookup */ const int *index_mf_to_mpoly = dm->getTessFaceDataArray(dm, CD_ORIGINDEX); @@ -717,14 +719,35 @@ static void cdDM_drawFacesTex_common(DerivedMesh *dm, cdDM_update_normals_from_pbvh(dm); if (GPU_buffer_legacy(dm)) { + int mat_nr_cache = -1; + MTFace *tf_base = DM_get_tessface_data_layer(dm, CD_MTFACE); + MTFace *tf_stencil_base = NULL; + MTFace *tf_stencil = NULL; + + if (uvflag & DM_DRAW_USE_TEXPAINT_UV) { + int stencil = CustomData_get_stencil_layer(&dm->faceData, CD_MTFACE); + tf_stencil_base = CustomData_get_layer_n(&dm->faceData, CD_MTFACE, stencil); + } + DEBUG_VBO("Using legacy code. cdDM_drawFacesTex_common\n"); for (i = 0; i < dm->numTessFaceData; i++, mf++) { MVert *mvert; DMDrawOption draw_option; unsigned char *cp = NULL; + if (uvflag & DM_DRAW_USE_TEXPAINT_UV) { + if (mf->mat_nr != mat_nr_cache) { + tf_base = DM_paint_uvlayer_active_get(dm, mf->mat_nr); + + mat_nr_cache = mf->mat_nr; + } + } + + tf = tf_base ? tf_base + i : NULL; + tf_stencil = tf_stencil_base ? tf_stencil_base + i : NULL; + if (drawParams) { - draw_option = drawParams(tf ? &tf[i] : NULL, (mcol != NULL), mf->mat_nr); + draw_option = drawParams(use_tface ? tf : NULL, (mcol != NULL), mf->mat_nr); } else { if (index_mf_to_mpoly) { @@ -777,21 +800,24 @@ static void cdDM_drawFacesTex_common(DerivedMesh *dm, } glBegin(mf->v4 ? GL_QUADS : GL_TRIANGLES); - if (tf) glTexCoord2fv(tf[i].uv[0]); + if (tf) glTexCoord2fv(tf->uv[0]); + if (tf_stencil) glMultiTexCoord2fv(GL_TEXTURE2, tf->uv[0]); if (cp) glColor3ub(cp[3], cp[2], cp[1]); mvert = &mv[mf->v1]; if (lnors) glNormal3sv((const GLshort *)lnors[0][0]); else if (mf->flag & ME_SMOOTH) glNormal3sv(mvert->no); glVertex3fv(mvert->co); - if (tf) glTexCoord2fv(tf[i].uv[1]); + if (tf) glTexCoord2fv(tf->uv[1]); + if (tf_stencil) glMultiTexCoord2fv(GL_TEXTURE2, tf->uv[1]); if (cp) glColor3ub(cp[7], cp[6], cp[5]); mvert = &mv[mf->v2]; if (lnors) glNormal3sv((const GLshort *)lnors[0][1]); else if (mf->flag & ME_SMOOTH) glNormal3sv(mvert->no); glVertex3fv(mvert->co); - if (tf) glTexCoord2fv(tf[i].uv[2]); + if (tf) glTexCoord2fv(tf->uv[2]); + if (tf_stencil) glMultiTexCoord2fv(GL_TEXTURE2, tf->uv[2]); if (cp) glColor3ub(cp[11], cp[10], cp[9]); mvert = &mv[mf->v3]; if (lnors) glNormal3sv((const GLshort *)lnors[0][2]); @@ -799,7 +825,8 @@ static void cdDM_drawFacesTex_common(DerivedMesh *dm, glVertex3fv(mvert->co); if (mf->v4) { - if (tf) glTexCoord2fv(tf[i].uv[3]); + if (tf) glTexCoord2fv(tf->uv[3]); + if (tf_stencil) glMultiTexCoord2fv(GL_TEXTURE2, tf->uv[3]); if (cp) glColor3ub(cp[15], cp[14], cp[13]); mvert = &mv[mf->v4]; if (lnors) glNormal3sv((const GLshort *)lnors[0][3]); @@ -818,7 +845,10 @@ static void cdDM_drawFacesTex_common(DerivedMesh *dm, else { /* use OpenGL VBOs or Vertex Arrays instead for better, faster rendering */ GPU_vertex_setup(dm); GPU_normal_setup(dm); - GPU_uv_setup(dm); + if (uvflag & DM_DRAW_USE_TEXPAINT_UV) + GPU_texpaint_uv_setup(dm); + else + GPU_uv_setup(dm); if (mcol) { GPU_color_setup(dm, colType); } @@ -838,7 +868,7 @@ static void cdDM_drawFacesTex_common(DerivedMesh *dm, next_actualFace = dm->drawObject->triangle_to_mface[i + 1]; if (drawParams) { - draw_option = drawParams(tf ? &tf[actualFace] : NULL, (mcol != NULL), mf[actualFace].mat_nr); + draw_option = drawParams(use_tface && tf ? &tf[actualFace] : NULL, (mcol != NULL), mf[actualFace].mat_nr); } else { if (index_mf_to_mpoly) { @@ -894,9 +924,9 @@ static void cdDM_drawFacesTex_common(DerivedMesh *dm, static void cdDM_drawFacesTex(DerivedMesh *dm, DMSetDrawOptionsTex setDrawOptions, DMCompareDrawOptions compareDrawOptions, - void *userData) + void *userData, DMDrawFlag uvflag) { - cdDM_drawFacesTex_common(dm, setDrawOptions, NULL, compareDrawOptions, userData); + cdDM_drawFacesTex_common(dm, setDrawOptions, NULL, compareDrawOptions, userData, uvflag); } static void cdDM_drawMappedFaces(DerivedMesh *dm, @@ -1122,9 +1152,9 @@ static void cdDM_drawMappedFaces(DerivedMesh *dm, static void cdDM_drawMappedFacesTex(DerivedMesh *dm, DMSetDrawOptions setDrawOptions, DMCompareDrawOptions compareDrawOptions, - void *userData) + void *userData, DMDrawFlag flag) { - cdDM_drawFacesTex_common(dm, NULL, setDrawOptions, compareDrawOptions, userData); + cdDM_drawFacesTex_common(dm, NULL, setDrawOptions, compareDrawOptions, userData, flag); } static void cddm_draw_attrib_vertex(DMVertexAttribs *attribs, MVert *mvert, int a, int index, int vert, @@ -2541,25 +2571,200 @@ void CDDM_calc_normals_tessface(DerivedMesh *dm) #if 1 /** + * Poly compare with vtargetmap + * Function used by #CDDM_merge_verts. + * The function compares poly_source after applying vtargetmap, with poly_target. + * The two polys are identical if they share the same vertices in the same order, or in reverse order, + * but starting position loopstart may be different. + * The function is called with direct_reverse=1 for same order (i.e. same normal), + * and may be called again with direct_reverse=-1 for reverse order. + * \return 1 if polys are identical, 0 if polys are different. + */ +static int cddm_poly_compare(MLoop *mloop_array, MPoly *mpoly_source, MPoly *mpoly_target, const int *vtargetmap, const int direct_reverse) +{ + int vert_source, first_vert_source, vert_target; + int i_loop_source; + int i_loop_target, i_loop_target_start, i_loop_target_offset, i_loop_target_adjusted; + bool compare_completed = false; + bool same_loops = false; + + MLoop *mloop_source, *mloop_target; + + BLI_assert(direct_reverse == 1 || direct_reverse == -1); + + i_loop_source = 0; + mloop_source = mloop_array + mpoly_source->loopstart; + vert_source = mloop_source->v; + + if (vtargetmap[vert_source] != -1) { + vert_source = vtargetmap[vert_source]; + } + else { + /* All source loop vertices should be mapped */ + BLI_assert(false); + } + + /* Find same vertex within mpoly_target's loops */ + mloop_target = mloop_array + mpoly_target->loopstart; + for (i_loop_target = 0; i_loop_target < mpoly_target->totloop; i_loop_target++, mloop_target++) { + if (mloop_target->v == vert_source) { + break; + } + } + + /* If same vertex not found, then polys cannot be equal */ + if (i_loop_target >= mpoly_target->totloop) { + return false; + } + + /* Now mloop_source and m_loop_target have one identical vertex */ + /* mloop_source is at position 0, while m_loop_target has advanced to find identical vertex */ + /* Go around the loop and check that all vertices match in same order */ + /* Skipping source loops when consecutive source vertices are mapped to same target vertex */ + + i_loop_target_start = i_loop_target; + i_loop_target_offset = 0; + first_vert_source = vert_source; + + compare_completed = false; + same_loops = false; + + while (!compare_completed) { + + vert_target = mloop_target->v; + + /* First advance i_loop_source, until it points to different vertex, after mapping applied */ + do { + i_loop_source++; + + if (i_loop_source == mpoly_source->totloop) { + /* End of loops for source, must match end of loop for target. */ + if (i_loop_target_offset == mpoly_target->totloop - 1) { + compare_completed = true; + same_loops = true; + break; /* Polys are identical */ + } + else { + compare_completed = true; + same_loops = false; + break; /* Polys are different */ + } + } + + mloop_source++; + vert_source = mloop_source->v; + + if (vtargetmap[vert_source] != -1) { + vert_source = vtargetmap[vert_source]; + } + else { + /* All source loop vertices should be mapped */ + BLI_assert(false); + } + + } while (vert_source == vert_target); + + if (compare_completed) { + break; + } + + /* Now advance i_loop_target as well */ + i_loop_target_offset++; + + if (i_loop_target_offset == mpoly_target->totloop) { + /* End of loops for target only, that means no match */ + /* except if all remaining source vertices are mapped to first target */ + for (; i_loop_source < mpoly_source->totloop; i_loop_source++, mloop_source++) { + vert_source = vtargetmap[mloop_source->v]; + if (vert_source != first_vert_source) { + compare_completed = true; + same_loops = false; + break; + } + } + if (!compare_completed) { + same_loops = true; + } + break; + } + + /* Adjust i_loop_target for cycling around and for direct/reverse order defined by delta = +1 or -1 */ + i_loop_target_adjusted = (i_loop_target_start + direct_reverse * i_loop_target_offset) % mpoly_target->totloop; + if (i_loop_target_adjusted < 0) { + i_loop_target_adjusted += mpoly_target->totloop; + } + mloop_target = mloop_array + mpoly_target->loopstart + i_loop_target_adjusted; + vert_target = mloop_target->v; + + if (vert_target != vert_source) { + same_loops = false; /* Polys are different */ + break; + } + } + return same_loops; +} + +/* Utility stuff for using GHash with polys */ + +typedef struct PolyKey { + int poly_index; /* index of the MPoly within the derived mesh */ + int totloops; /* number of loops in the poly */ + unsigned int hash_sum; /* Sum of all vertices indices */ + unsigned int hash_xor; /* Xor of all vertices indices */ +} PolyKey; + + +static unsigned int poly_gset_hash_fn(const void *key) +{ + const PolyKey *pk = key; + return pk->hash_sum; +} + +static int poly_gset_compare_fn(const void *k1, const void *k2) +{ + const PolyKey *pk1 = k1; + const PolyKey *pk2 = k2; + if ((pk1->hash_sum == pk2->hash_sum) && + (pk1->hash_xor == pk2->hash_xor) && + (pk1->totloops == pk2->totloops)) + { + /* Equality - note that this does not mean equality of polys */ + return 0; + } + else { + return 1; + } +} + +/** * Merge Verts * + * This frees dm, and returns a new one. + * * \param vtargetmap The table that maps vertices to target vertices. a value of -1 * indicates a vertex is a target, and is to be kept. * This array is aligned with 'dm->numVertData' * - * \param tot_vtargetmap The number of non '-1' values in vtargetmap. - * (not the size ) - * - * this frees dm, and returns a new one. + * \param tot_vtargetmap The number of non '-1' values in vtargetmap. (not the size) * - * note, CDDM_recalc_tessellation has to run on the returned DM if you want to access tessfaces. + * \param merge_mode enum with two modes. + * - #CDDM_MERGE_VERTS_DUMP_IF_MAPPED + * When called by the Mirror Modifier, + * In this mode it skips any faces that have all vertices merged (to avoid creating pairs + * of faces sharing the same set of vertices) + * - #CDDM_MERGE_VERTS_DUMP_IF_EQUAL + * When called by the Array Modifier, + * In this mode, faces where all vertices are merged are double-checked, + * to see whether all target vertices actually make up a poly already. + * Indeed it could be that all of a poly's vertices are merged, + * but merged to vertices that do not make up a single poly, + * in which case the original poly should not be dumped. + * Actually this later behavior could apply to the Mirror Modifier as well, but the additional checks are + * costly and not necessary in the case of mirror, because each vertex is only merged to its own mirror. * - * Note: This function is currently only used by the Mirror modifier, so it - * skips any faces that have all vertices merged (to avoid creating pairs - * of faces sharing the same set of vertices). If used elsewhere, it may - * be necessary to make this functionality optional. + * \note #CDDM_recalc_tessellation has to run on the returned DM if you want to access tessfaces. */ -DerivedMesh *CDDM_merge_verts(DerivedMesh *dm, const int *vtargetmap, const int tot_vtargetmap) +DerivedMesh *CDDM_merge_verts(DerivedMesh *dm, const int *vtargetmap, const int tot_vtargetmap, const int merge_mode) { // #define USE_LOOPS CDDerivedMesh *cddm = (CDDerivedMesh *)dm; @@ -2600,7 +2805,10 @@ DerivedMesh *CDDM_merge_verts(DerivedMesh *dm, const int *vtargetmap, const int EdgeHash *ehash = BLI_edgehash_new_ex(__func__, totedge); int i, j, c; - + + PolyKey *poly_keys; + GSet *poly_gset = NULL; + STACK_INIT(oldv, totvert_final); STACK_INIT(olde, totedge); STACK_INIT(oldl, totloop); @@ -2642,10 +2850,9 @@ DerivedMesh *CDDM_merge_verts(DerivedMesh *dm, const int *vtargetmap, const int med = cddm->medge; c = 0; for (i = 0; i < totedge; i++, med++) { - - if (LIKELY(med->v1 != med->v2)) { - const unsigned int v1 = (vtargetmap[med->v1] != -1) ? vtargetmap[med->v1] : med->v1; - const unsigned int v2 = (vtargetmap[med->v2] != -1) ? vtargetmap[med->v2] : med->v2; + const unsigned int v1 = (vtargetmap[med->v1] != -1) ? vtargetmap[med->v1] : med->v1; + const unsigned int v2 = (vtargetmap[med->v2] != -1) ? vtargetmap[med->v2] : med->v2; + if (LIKELY(v1 != v2)) { void **eh_p = BLI_edgehash_lookup_p(ehash, v1, v2); if (eh_p) { @@ -2664,13 +2871,49 @@ DerivedMesh *CDDM_merge_verts(DerivedMesh *dm, const int *vtargetmap, const int } } + if (merge_mode == CDDM_MERGE_VERTS_DUMP_IF_EQUAL) { + /* In this mode, we need to determine, whenever a poly' vertices are all mapped */ + /* if the targets already make up a poly, in which case the new poly is dropped */ + /* This poly equality check is rather complex. We use a BLI_ghash to speed it up with a first level check */ + PolyKey *mpgh; + poly_keys = MEM_mallocN(sizeof(PolyKey) * totpoly, __func__); + poly_gset = BLI_gset_new_ex(poly_gset_hash_fn, poly_gset_compare_fn, __func__, totpoly); + /* Duplicates allowed because our compare function is not pure equality */ + BLI_gset_flag_set(poly_gset, GHASH_FLAG_ALLOW_DUPES); + + mp = cddm->mpoly; + mpgh = poly_keys; + for (i = 0; i < totpoly; i++, mp++, mpgh++) { + mpgh->poly_index = i; + mpgh->totloops = mp->totloop; + ml = cddm->mloop + mp->loopstart; + mpgh->hash_sum = mpgh->hash_xor = 0; + for (j = 0; j < mp->totloop; j++, ml++) { + mpgh->hash_sum += ml->v; + mpgh->hash_xor ^= ml->v; + } + BLI_gset_insert(poly_gset, mpgh); + } + + if (cddm->pmap) { + MEM_freeN(cddm->pmap); + MEM_freeN(cddm->pmap_mem); + } + /* Can we optimise by reusing an old pmap ? How do we know an old pmap is stale ? */ + /* When called by MOD_array.c, the cddm has just been created, so it has no valid pmap. */ + BKE_mesh_vert_poly_map_create(&cddm->pmap, &cddm->pmap_mem, + cddm->mpoly, cddm->mloop, + totvert, totpoly, totloop); + } /* done preparing for fast poly compare */ + + mp = cddm->mpoly; for (i = 0; i < totpoly; i++, mp++) { MPoly *mp_new; ml = cddm->mloop + mp->loopstart; - /* skip faces with all vertices merged */ + /* check faces with all vertices merged */ { bool all_vertices_merged = true; @@ -2682,16 +2925,86 @@ DerivedMesh *CDDM_merge_verts(DerivedMesh *dm, const int *vtargetmap, const int } if (UNLIKELY(all_vertices_merged)) { - continue; + if (merge_mode == CDDM_MERGE_VERTS_DUMP_IF_MAPPED) { + /* In this mode, all vertices merged is enough to dump face */ + continue; + } + else if (merge_mode == CDDM_MERGE_VERTS_DUMP_IF_EQUAL) { + /* Additional condition for face dump: target vertices must make up an identical face */ + /* The test has 2 steps: (1) first step is fast ghash lookup, but not failproof */ + /* (2) second step is thorough but more costly poly compare */ + int i_poly, v_target, v_prev; + bool found = false; + PolyKey pkey; + + /* Use poly_gset for fast (although not 100% certain) identification of same poly */ + /* First, make up a poly_summary structure */ + ml = cddm->mloop + mp->loopstart; + pkey.hash_sum = pkey.hash_xor = 0; + pkey.totloops = 0; + v_prev = vtargetmap[(ml + mp->totloop -1)->v]; /* since it loops around, the prev of first is the last */ + for (j = 0; j < mp->totloop; j++, ml++) { + v_target = vtargetmap[ml->v]; /* Cannot be -1, they are all mapped */ + if (v_target == v_prev) { + /* consecutive vertices in loop map to the same target: discard */ + /* but what about last to first ? */ + continue; + } + pkey.hash_sum += v_target; + pkey.hash_xor ^= v_target; + pkey.totloops++; + v_prev = v_target; + } + if (BLI_gset_haskey(poly_gset, &pkey)) { + + /* There might be a poly that matches this one. + * We could just leave it there and say there is, and do a "continue". + * ... but we are checking whether there is an exact poly match. + * It's not so costly in terms of CPU since it's very rare, just a lot of complex code. + */ + + /* Consider current loop again */ + ml = cddm->mloop + mp->loopstart; + /* Consider the target of the loop's first vert */ + v_target = vtargetmap[ml->v]; + /* Now see if v_target belongs to a poly that shares all vertices with source poly, + * in same order, or reverse order */ + + for (i_poly = 0; i_poly < cddm->pmap[v_target].count; i_poly++) { + MPoly *target_poly = cddm->mpoly + *(cddm->pmap[v_target].indices + i_poly); + + if (cddm_poly_compare(cddm->mloop, mp, target_poly, vtargetmap, +1) || + cddm_poly_compare(cddm->mloop, mp, target_poly, vtargetmap, -1)) + { + found = true; + break; + } + } + if (found) { + /* Current poly's vertices are mapped to a poly that is strictly identical */ + /* Current poly is dumped */ + continue; + } + } + } } } + + /* Here either the poly's vertices were not all merged + * or they were all merged, but targets do not make up an identical poly, + * the poly is retained. + */ ml = cddm->mloop + mp->loopstart; c = 0; for (j = 0; j < mp->totloop; j++, ml++) { + unsigned int v1, v2; + med = cddm->medge + ml->e; - if (LIKELY(med->v1 != med->v2)) { + v1 = (vtargetmap[med->v1] != -1) ? vtargetmap[med->v1] : med->v1; + v2 = (vtargetmap[med->v2] != -1) ? vtargetmap[med->v2] : med->v2; + if (LIKELY(v1 != v2)) { #ifdef USE_LOOPS newl[j + mp->loopstart] = STACK_SIZE(mloop); #endif @@ -2711,6 +3024,14 @@ DerivedMesh *CDDM_merge_verts(DerivedMesh *dm, const int *vtargetmap, const int mp_new->loopstart = STACK_SIZE(mloop) - c; STACK_PUSH(oldp, i); + } /* end of the loop that tests polys */ + + + if (poly_gset) { + // printf("hash quality %.6f\n", BLI_gset_calc_quality(poly_gset)); + + BLI_gset_free(poly_gset, NULL); + MEM_freeN(poly_keys); } /*create new cddm*/ diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c index b27655c8c19..d80529ee780 100644 --- a/source/blender/blenkernel/intern/constraint.c +++ b/source/blender/blenkernel/intern/constraint.c @@ -3375,7 +3375,7 @@ static void shrinkwrap_get_tarmat(bConstraint *con, bConstraintOb *cob, bConstra unit_m4(ct->matrix); if (target != NULL) { - space_transform_from_matrixs(&transform, cob->matrix, ct->tar->obmat); + BLI_space_transform_from_matrices(&transform, cob->matrix, ct->tar->obmat); switch (scon->shrinkType) { case MOD_SHRINKWRAP_NEAREST_SURFACE: @@ -3397,7 +3397,7 @@ static void shrinkwrap_get_tarmat(bConstraint *con, bConstraintOb *cob, bConstra break; } - space_transform_apply(&transform, co); + BLI_space_transform_apply(&transform, co); BLI_bvhtree_find_nearest(treeData.tree, co, &nearest, treeData.nearest_callback, &treeData); @@ -3405,7 +3405,7 @@ static void shrinkwrap_get_tarmat(bConstraint *con, bConstraintOb *cob, bConstra if (dist != 0.0f) { interp_v3_v3v3(co, co, nearest.co, (dist - scon->dist) / dist); /* linear interpolation */ } - space_transform_invert(&transform, co); + BLI_space_transform_invert(&transform, co); break; } case MOD_SHRINKWRAP_PROJECT: @@ -3909,7 +3909,7 @@ static void followtrack_evaluate(bConstraint *con, bConstraintOb *cob, ListBase BKE_tracking_camera_get_reconstructed_interpolate(tracking, tracking_object, framenr, imat); invert_m4(imat); - mul_serie_m4(cob->matrix, obmat, mat, imat, NULL, NULL, NULL, NULL, NULL); + mul_m4_series(cob->matrix, obmat, mat, imat); translate_m4(cob->matrix, track->bundle_pos[0], track->bundle_pos[1], track->bundle_pos[2]); } else { @@ -3943,19 +3943,31 @@ static void followtrack_evaluate(bConstraint *con, bConstraintOb *cob, ListBase if (len > FLT_EPSILON) { CameraParams params; + int width, height; float pos[2], rmat[4][4]; + BKE_movieclip_get_size(clip, NULL, &width, &height); + marker = BKE_tracking_marker_get(track, framenr); add_v2_v2v2(pos, marker->pos, track->offset); + if (data->flag & FOLLOWTRACK_USE_UNDISTORTION) { + /* Undistortion need to happen in pixel space. */ + pos[0] *= width; + pos[1] *= height; + + BKE_tracking_undistort_v2(tracking, pos, pos); + + /* Normalize pixel coordinates back. */ + pos[0] /= width; + pos[1] /= height; + } + /* aspect correction */ if (data->frame_method != FOLLOWTRACK_FRAME_STRETCH) { - int width, height; float w_src, h_src, w_dst, h_dst, asp_src, asp_dst; - BKE_movieclip_get_size(clip, NULL, &width, &height); - /* apply clip display aspect */ w_src = width * clip->aspx; h_src = height * clip->aspy; @@ -4187,7 +4199,7 @@ static void objectsolver_evaluate(bConstraint *con, bConstraintOb *cob, ListBase invert_m4_m4(imat, mat); - mul_serie_m4(cob->matrix, cammat, imat, camimat, parmat, obmat, NULL, NULL, NULL); + mul_m4_series(cob->matrix, cammat, imat, camimat, parmat, obmat); } } } diff --git a/source/blender/blenkernel/intern/context.c b/source/blender/blenkernel/intern/context.c index 47b29b49689..de285f87444 100644 --- a/source/blender/blenkernel/intern/context.c +++ b/source/blender/blenkernel/intern/context.c @@ -48,7 +48,6 @@ #include "BKE_context.h" #include "BKE_main.h" #include "BKE_screen.h" -#include "BKE_freestyle.h" #include "RNA_access.h" @@ -1091,16 +1090,3 @@ int CTX_data_visible_pose_bones(const bContext *C, ListBase *list) { return ctx_data_collection_get(C, "visible_pose_bones", list); } - -FreestyleLineStyle *CTX_data_linestyle_from_scene(Scene *scene) -{ - SceneRenderLayer *actsrl = BLI_findlink(&scene->r.layers, scene->r.actlay); - FreestyleConfig *config = &actsrl->freestyleConfig; - FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(config); - - if (lineset) { - return lineset->linestyle; - } - - return NULL; -} diff --git a/source/blender/blenkernel/intern/crazyspace.c b/source/blender/blenkernel/intern/crazyspace.c index 7ca5d6b4f28..911bb19a594 100644 --- a/source/blender/blenkernel/intern/crazyspace.c +++ b/source/blender/blenkernel/intern/crazyspace.c @@ -40,7 +40,6 @@ #include "BLI_utildefines.h" #include "BLI_math.h" -#include "BLI_bitmap.h" #include "BKE_crazyspace.h" #include "BKE_DerivedMesh.h" @@ -49,11 +48,6 @@ #include "BKE_mesh.h" #include "BKE_editmesh.h" -typedef struct { - float (*vertexcos)[3]; - BLI_bitmap *vertex_visit; -} MappedUserData; - BLI_INLINE void tan_calc_quat_v3( float r_quat[4], const float co_1[3], const float co_2[3], const float co_3[3]) @@ -88,20 +82,6 @@ static void set_crazy_vertex_quat( sub_qt_qtqt(r_quat, q2, q1); } -static void make_vertexcos__mapFunc(void *userData, int index, const float co[3], - const float UNUSED(no_f[3]), const short UNUSED(no_s[3])) -{ - MappedUserData *mappedData = (MappedUserData *)userData; - - if (BLI_BITMAP_TEST(mappedData->vertex_visit, index) == 0) { - /* we need coord from prototype vertex, not from copies, - * assume they stored in the beginning of vertex array stored in DM - * (mirror modifier for eg does this) */ - copy_v3_v3(mappedData->vertexcos[index], co); - BLI_BITMAP_ENABLE(mappedData->vertex_visit, index); - } -} - static int modifiers_disable_subsurf_temporary(Object *ob) { ModifierData *md; @@ -124,8 +104,6 @@ float (*BKE_crazyspace_get_mapped_editverts(Scene *scene, Object *obedit))[3] DerivedMesh *dm; float (*vertexcos)[3]; int nverts = me->edit_btmesh->bm->totvert; - BLI_bitmap *vertex_visit; - MappedUserData userData; /* disable subsurf temporal, get mapped cos, and enable it */ if (modifiers_disable_subsurf_temporary(obedit)) { @@ -134,22 +112,17 @@ float (*BKE_crazyspace_get_mapped_editverts(Scene *scene, Object *obedit))[3] } /* now get the cage */ - dm = editbmesh_get_derived_cage(scene, obedit, me->edit_btmesh, CD_MASK_BAREMESH); + vertexcos = MEM_mallocN(sizeof(*vertexcos) * nverts, "vertexcos map"); - vertexcos = MEM_callocN(sizeof(*vertexcos) * nverts, "vertexcos map"); - vertex_visit = BLI_BITMAP_NEW(nverts, "vertexcos flags"); + dm = editbmesh_get_derived_cage(scene, obedit, me->edit_btmesh, CD_MASK_BAREMESH); - userData.vertexcos = vertexcos; - userData.vertex_visit = vertex_visit; - dm->foreachMappedVert(dm, make_vertexcos__mapFunc, &userData, DM_FOREACH_NOP); + mesh_get_mapped_verts_coords(dm, vertexcos, nverts); dm->release(dm); /* set back the flag, no new cage needs to be built, transform does it */ modifiers_disable_subsurf_temporary(obedit); - MEM_freeN(vertex_visit); - return vertexcos; } diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c index 0abe956b599..9275b626b49 100644 --- a/source/blender/blenkernel/intern/curve.c +++ b/source/blender/blenkernel/intern/curve.c @@ -52,6 +52,7 @@ #include "BKE_animsys.h" #include "BKE_curve.h" +#include "BKE_depsgraph.h" #include "BKE_displist.h" #include "BKE_font.h" #include "BKE_global.h" @@ -642,8 +643,9 @@ void BKE_nurb_test2D(Nurb *nu) } } -/* if use_radius is truth, minmax will take points' radius into account, - * which will make boundbox closer to bevelled curve. +/** + * if use_radius is truth, minmax will take points' radius into account, + * which will make boundbox closer to beveled curve. */ void BKE_nurb_minmax(Nurb *nu, bool use_radius, float min[3], float max[3]) { @@ -2498,6 +2500,22 @@ static void bevlist_firstlast_direction_calc_from_bpoint(Nurb *nu, BevList *bl) } } +void BKE_curve_bevelList_free(ListBase *bev) +{ + BevList *bl, *blnext; + for (bl = bev->first; bl != NULL; bl = blnext) { + blnext = bl->next; + if (bl->seglen != NULL) { + MEM_freeN(bl->seglen); + } + if (bl->segbevcount != NULL) { + MEM_freeN(bl->segbevcount); + } + MEM_freeN(bl); + } + bev->first = bev->last = NULL; +} + void BKE_curve_bevelList_make(Object *ob, ListBase *nurbs, bool for_render) { /* @@ -2506,21 +2524,29 @@ void BKE_curve_bevelList_make(Object *ob, ListBase *nurbs, bool for_render) * - separate in individual blocks with BoundBox * - AutoHole detection */ - Curve *cu; + + /* this function needs an object, because of tflag and upflag */ + Curve *cu = ob->data; Nurb *nu; BezTriple *bezt, *prevbezt; BPoint *bp; BevList *bl, *blnew, *blnext; BevPoint *bevp, *bevp2, *bevp1 = NULL, *bevp0; + const float treshold = 0.00001f; float min, inp; + float *seglen; struct BevelSort *sortdata, *sd, *sd1; - int a, b, nr, poly, resolu = 0, len = 0; + int a, b, nr, poly, resolu = 0, len = 0, segcount; + int *segbevcount; bool do_tilt, do_radius, do_weight; bool is_editmode = false; ListBase *bev; - /* this function needs an object, because of tflag and upflag */ - cu = ob->data; + /* segbevcount alsp requires seglen. */ + const bool need_seglen = + ELEM(cu->bevfac1_mapping, CU_BEVFAC_MAP_SEGMENT, CU_BEVFAC_MAP_SPLINE) || + ELEM(cu->bevfac2_mapping, CU_BEVFAC_MAP_SEGMENT, CU_BEVFAC_MAP_SPLINE); + bev = &ob->curve_cache->bev; @@ -2529,7 +2555,7 @@ void BKE_curve_bevelList_make(Object *ob, ListBase *nurbs, bool for_render) /* STEP 1: MAKE POLYS */ - BLI_freelistN(&(ob->curve_cache->bev)); + BKE_curve_bevelList_free(&ob->curve_cache->bev); nu = nurbs->first; if (cu->editnurb && ob->type != OB_FONT) { is_editmode = 1; @@ -2559,9 +2585,15 @@ void BKE_curve_bevelList_make(Object *ob, ListBase *nurbs, bool for_render) else resolu = nu->resolu; + segcount = SEGMENTSU(nu); + if (nu->type == CU_POLY) { len = nu->pntsu; bl = MEM_callocN(sizeof(BevList) + len * sizeof(BevPoint), "makeBevelList2"); + if (need_seglen) { + bl->seglen = MEM_mallocN(segcount * sizeof(float), "makeBevelList2_seglen"); + bl->segbevcount = MEM_mallocN(segcount * sizeof(int), "makeBevelList2_segbevcount"); + } BLI_addtail(bev, bl); bl->poly = (nu->flagu & CU_NURB_CYCLIC) ? 0 : -1; @@ -2569,7 +2601,11 @@ void BKE_curve_bevelList_make(Object *ob, ListBase *nurbs, bool for_render) bl->dupe_nr = 0; bl->charidx = nu->charidx; bevp = bl->bevpoints; + bevp->offset = 0; bp = nu->bp; + seglen = bl->seglen; + segbevcount = bl->segbevcount; + BLI_assert(segcount >= len); while (len--) { copy_v3_v3(bevp->vec, bp->vec); @@ -2577,23 +2613,53 @@ void BKE_curve_bevelList_make(Object *ob, ListBase *nurbs, bool for_render) bevp->radius = bp->radius; bevp->weight = bp->weight; bevp->split_tag = true; - bevp++; bp++; + if (seglen != NULL) { + *seglen = len_v3v3(bevp->vec, bp->vec); + bevp++; + bevp->offset = *seglen; + if (*seglen > treshold) *segbevcount = 1; + else *segbevcount = 0; + seglen++; + segbevcount++; + } + else { + bevp++; + } } if ((nu->flagu & CU_NURB_CYCLIC) == 0) { bevlist_firstlast_direction_calc_from_bpoint(nu, bl); + if (seglen != NULL) { + *seglen = len_v3v3(bevp->vec, nu->bp->vec); + bl->bevpoints->offset = *seglen; + *segbevcount = 1; + } } } else if (nu->type == CU_BEZIER) { /* in case last point is not cyclic */ - len = resolu * (nu->pntsu + (nu->flagu & CU_NURB_CYCLIC) - 1) + 1; + len = segcount * resolu + 1; + bl = MEM_callocN(sizeof(BevList) + len * sizeof(BevPoint), "makeBevelBPoints"); + if (need_seglen) { + bl->seglen = MEM_mallocN(segcount * sizeof(float), "makeBevelBPoints_seglen"); + bl->segbevcount = MEM_mallocN(segcount * sizeof(int), "makeBevelBPoints_segbevcount"); + } BLI_addtail(bev, bl); bl->poly = (nu->flagu & CU_NURB_CYCLIC) ? 0 : -1; bl->charidx = nu->charidx; + bevp = bl->bevpoints; + seglen = bl->seglen; + segbevcount = bl->segbevcount; + + bevp->offset = 0; + if (seglen != NULL) { + *seglen = 0; + *segbevcount = 0; + } a = nu->pntsu - 1; bezt = nu->bezt; @@ -2609,6 +2675,8 @@ void BKE_curve_bevelList_make(Object *ob, ListBase *nurbs, bool for_render) sub_v3_v3v3(bevp->dir, prevbezt->vec[2], prevbezt->vec[1]); normalize_v3(bevp->dir); + BLI_assert(segcount >= a); + while (a--) { if (prevbezt->h2 == HD_VECT && bezt->h1 == HD_VECT) { @@ -2621,6 +2689,14 @@ void BKE_curve_bevelList_make(Object *ob, ListBase *nurbs, bool for_render) bevp++; bl->nr++; bl->dupe_nr = 1; + if (seglen != NULL) { + *seglen = len_v3v3(prevbezt->vec[1], bezt->vec[1]); + bevp->offset = *seglen; + seglen++; + /* match segbevcount to the cleaned up bevel lists (see STEP 2) */ + if (bevp->offset > treshold) *segbevcount = 1; + segbevcount++; + } } else { /* always do all three, to prevent data hanging around */ @@ -2658,8 +2734,28 @@ void BKE_curve_bevelList_make(Object *ob, ListBase *nurbs, bool for_render) else if (prevbezt->h2 == 0 || prevbezt->h2 == HD_VECT) bevp->split_tag = true; } + + /* seglen */ + if (seglen != NULL) { + *seglen = 0; + *segbevcount = 0; + for (j = 0; j < resolu; j++) { + bevp0 = bevp; + bevp++; + bevp->offset = len_v3v3(bevp0->vec, bevp->vec); + /* match seglen and segbevcount to the cleaned up bevel lists (see STEP 2) */ + if (bevp->offset > treshold) { + *seglen += bevp->offset; + *segbevcount += 1; + } + } + seglen++; + segbevcount++; + } + else { + bevp += resolu; + } bl->nr += resolu; - bevp += resolu; } prevbezt = bezt; bezt++; @@ -2679,15 +2775,22 @@ void BKE_curve_bevelList_make(Object *ob, ListBase *nurbs, bool for_render) } else if (nu->type == CU_NURBS) { if (nu->pntsv == 1) { - len = (resolu * SEGMENTSU(nu)); + len = (resolu * segcount); bl = MEM_callocN(sizeof(BevList) + len * sizeof(BevPoint), "makeBevelList3"); + if (need_seglen) { + bl->seglen = MEM_mallocN(segcount * sizeof(float), "makeBevelList3_seglen"); + bl->segbevcount = MEM_mallocN(segcount * sizeof(int), "makeBevelList3_segbevcount"); + } BLI_addtail(bev, bl); bl->nr = len; bl->dupe_nr = 0; bl->poly = (nu->flagu & CU_NURB_CYCLIC) ? 0 : -1; bl->charidx = nu->charidx; + bevp = bl->bevpoints; + seglen = bl->seglen; + segbevcount = bl->segbevcount; BKE_nurb_makeCurve(nu, &bevp->vec[0], do_tilt ? &bevp->alfa : NULL, @@ -2695,6 +2798,31 @@ void BKE_curve_bevelList_make(Object *ob, ListBase *nurbs, bool for_render) do_weight ? &bevp->weight : NULL, resolu, sizeof(BevPoint)); + /* match seglen and segbevcount to the cleaned up bevel lists (see STEP 2) */ + if (seglen != NULL) { + nr = segcount; + bevp0 = bevp; + bevp++; + while (nr) { + int j; + *seglen = 0; + *segbevcount = 0; + /* We keep last bevel segment zero-length. */ + for (j = 0; j < ((nr == 1) ? (resolu - 1) : resolu); j++) { + bevp->offset = len_v3v3(bevp0->vec, bevp->vec); + if (bevp->offset > treshold) { + *seglen += bevp->offset; + *segbevcount += 1; + } + bevp0 = bevp; + bevp++; + } + seglen++; + segbevcount++; + nr--; + } + } + if ((nu->flagu & CU_NURB_CYCLIC) == 0) { bevlist_firstlast_direction_calc_from_bpoint(nu, bl); } @@ -2715,15 +2843,24 @@ void BKE_curve_bevelList_make(Object *ob, ListBase *nurbs, bool for_render) } else { bevp0 = bl->bevpoints; + bevp0->offset = 0; bevp1 = bevp0 + 1; } nr--; while (nr--) { - if (fabsf(bevp0->vec[0] - bevp1->vec[0]) < 0.00001f) { - if (fabsf(bevp0->vec[1] - bevp1->vec[1]) < 0.00001f) { - if (fabsf(bevp0->vec[2] - bevp1->vec[2]) < 0.00001f) { - bevp0->dupe_tag = true; - bl->dupe_nr++; + if (seglen != NULL) { + if (fabsf(bevp1->offset) < treshold) { + bevp0->dupe_tag = true; + bl->dupe_nr++; + } + } + else { + if (fabsf(bevp0->vec[0] - bevp1->vec[0]) < 0.00001f) { + if (fabsf(bevp0->vec[1] - bevp1->vec[1]) < 0.00001f) { + if (fabsf(bevp0->vec[2] - bevp1->vec[2]) < 0.00001f) { + bevp0->dupe_tag = true; + bl->dupe_nr++; + } } } } @@ -2740,6 +2877,8 @@ void BKE_curve_bevelList_make(Object *ob, ListBase *nurbs, bool for_render) nr = bl->nr - bl->dupe_nr + 1; /* +1 because vectorbezier sets flag too */ blnew = MEM_mallocN(sizeof(BevList) + nr * sizeof(BevPoint), "makeBevelList4"); memcpy(blnew, bl, sizeof(BevList)); + blnew->segbevcount = bl->segbevcount; + blnew->seglen = bl->seglen; blnew->nr = 0; BLI_remlink(bev, bl); BLI_insertlinkbefore(bev, blnext, blnew); /* to make sure bevlijst is tuned with nurblist */ @@ -3070,7 +3209,13 @@ static void calchandleNurb_intern(BezTriple *bezt, BezTriple *prev, BezTriple *n madd_v3_v3v3fl(p2_h2, p2, dvec_b, 1.0f / 3.0f); } - if (skip_align || (!ELEM(HD_ALIGN, bezt->h1, bezt->h2) && !ELEM(HD_ALIGN_DOUBLESIDE, bezt->h1, bezt->h2))) { + if (skip_align || + /* when one handle is free, alignming makes no sense, see: T35952 */ + (ELEM(HD_FREE, bezt->h1, bezt->h2)) || + /* also when no handles are aligned, skip this step */ + (!ELEM(HD_ALIGN, bezt->h1, bezt->h2) && + !ELEM(HD_ALIGN_DOUBLESIDE, bezt->h1, bezt->h2))) + { /* handles need to be updated during animation and applying stuff like hooks, * but in such situations it's quite difficult to distinguish in which order * align handles should be aligned so skip them for now */ @@ -3168,6 +3313,31 @@ void BKE_nurb_handles_calc(Nurb *nu) /* first, if needed, set handle flags */ calchandlesNurb_intern(nu, false); } +/** + * Workaround #BKE_nurb_handles_calc logic + * that makes unselected align to the selected handle. + */ +static void nurbList_handles_swap_select(Nurb *nu) +{ + BezTriple *bezt; + int i; + + for (i = nu->pntsu, bezt = nu->bezt; i--; bezt++) { + if ((bezt->f1 & SELECT) != (bezt->f3 & SELECT)) { + bezt->f1 ^= SELECT; + bezt->f3 ^= SELECT; + } + } +} + +/* internal use only (weak) */ +static void nurb_handles_calc__align_selected(Nurb *nu) +{ + nurbList_handles_swap_select(nu); + BKE_nurb_handles_calc(nu); + nurbList_handles_swap_select(nu); +} + /* similar to BKE_nurb_handle_calc but for curves and * figures out the previous and next for us */ void BKE_nurb_handle_calc_simple(Nurb *nu, BezTriple *bezt) @@ -3365,7 +3535,9 @@ void BKE_nurbList_handles_set(ListBase *editnurb, const char code) } bezt++; } - BKE_nurb_handles_calc(nu); + + /* like BKE_nurb_handles_calc but moves selected */ + nurb_handles_calc__align_selected(nu); } nu = nu->next; } @@ -3409,7 +3581,9 @@ void BKE_nurbList_handles_set(ListBase *editnurb, const char code) bezt++; } - BKE_nurb_handles_calc(nu); + + /* like BKE_nurb_handles_calc but moves selected */ + nurb_handles_calc__align_selected(nu); } } } @@ -4143,7 +4317,50 @@ bool BKE_curve_center_bounds(Curve *cu, float cent[3]) return false; } -void BKE_curve_translate(Curve *cu, float offset[3], const bool do_keys) + +void BKE_curve_transform_ex(Curve *cu, float mat[4][4], bool do_keys, float unit_scale) +{ + Nurb *nu; + BPoint *bp; + BezTriple *bezt; + int i; + + for (nu = cu->nurb.first; nu; nu = nu->next) { + if (nu->type == CU_BEZIER) { + i = nu->pntsu; + for (bezt = nu->bezt; i--; bezt++) { + mul_m4_v3(mat, bezt->vec[0]); + mul_m4_v3(mat, bezt->vec[1]); + mul_m4_v3(mat, bezt->vec[2]); + bezt->radius *= unit_scale; + } + BKE_nurb_handles_calc(nu); + } + else { + i = nu->pntsu * nu->pntsv; + for (bp = nu->bp; i--; bp++) + mul_m4_v3(mat, bp->vec); + } + } + + if (do_keys && cu->key) { + KeyBlock *kb; + for (kb = cu->key->block.first; kb; kb = kb->next) { + float *fp = kb->data; + for (i = kb->totelem; i--; fp += 3) { + mul_m4_v3(mat, fp); + } + } + } +} + +void BKE_curve_transform(Curve *cu, float mat[4][4], bool do_keys) +{ + float unit_scale = mat4_to_scale(mat); + BKE_curve_transform_ex(cu, mat, do_keys, unit_scale); +} + +void BKE_curve_translate(Curve *cu, float offset[3], bool do_keys) { ListBase *nurb_lb = BKE_curve_nurbs_get(cu); Nurb *nu; @@ -4230,6 +4447,45 @@ void BKE_curve_material_index_clear(Curve *cu) } } +int BKE_curve_material_index_validate(Curve *cu) +{ + const int curvetype = BKE_curve_type_get(cu); + bool is_valid = true; + + if (curvetype == OB_FONT) { + CharInfo *info = cu->strinfo; + const int max_idx = max_ii(0, cu->totcol); /* OB_FONT use 1 as first mat index, not 0!!! */ + int i; + for (i = cu->len_wchar - 1; i >= 0; i--, info++) { + if (info->mat_nr > max_idx) { + info->mat_nr = 0; + is_valid = false; + } + } + } + else { + Nurb *nu; + const int max_idx = max_ii(0, cu->totcol - 1); + for (nu = cu->nurb.first; nu; nu = nu->next) { + if (nu->mat_nr > max_idx) { + nu->mat_nr = 0; + if (curvetype == OB_CURVE) { + nu->charidx = 0; + } + is_valid = false; + } + } + } + + if (!is_valid) { + DAG_id_tag_update(&cu->id, OB_RECALC_DATA); + return true; + } + else { + return false; + } +} + void BKE_curve_rect_from_textbox(const struct Curve *cu, const struct TextBox *tb, struct rctf *r_rect) { r_rect->xmin = cu->xof + tb->x; diff --git a/source/blender/blenkernel/intern/deform.c b/source/blender/blenkernel/intern/deform.c index d072088ac8e..528ff2d7b19 100644 --- a/source/blender/blenkernel/intern/deform.c +++ b/source/blender/blenkernel/intern/deform.c @@ -559,7 +559,7 @@ void defgroup_unique_name(bDeformGroup *dg, Object *ob) static bool is_char_sep(const char c) { - return ELEM4(c, '.', ' ', '-', '_'); + return ELEM(c, '.', ' ', '-', '_'); } /* based on BLI_split_dirfile() / os.path.splitext(), "a.b.c" -> ("a.b", ".c") */ @@ -614,6 +614,7 @@ void BKE_deform_flip_side_name(char name[MAX_VGROUP_NAME], const char from_name[ char replace[MAX_VGROUP_NAME] = ""; /* The replacement string */ char number[MAX_VGROUP_NAME] = ""; /* The number extension string */ char *index = NULL; + bool is_set = false; /* always copy the name, since this can be called with an uninitialized string */ BLI_strncpy(name, from_name, MAX_VGROUP_NAME); @@ -640,6 +641,7 @@ void BKE_deform_flip_side_name(char name[MAX_VGROUP_NAME], const char from_name[ /* first case; separator . - _ with extensions r R l L */ if (is_char_sep(name[len - 2])) { + is_set = true; switch (name[len - 1]) { case 'l': prefix[len - 1] = 0; @@ -657,10 +659,14 @@ void BKE_deform_flip_side_name(char name[MAX_VGROUP_NAME], const char from_name[ prefix[len - 1] = 0; strcpy(replace, "L"); break; + default: + is_set = false; } } + /* case; beginning with r R l L, with separator after it */ - else if (is_char_sep(name[1])) { + if (!is_set && is_char_sep(name[1])) { + is_set = true; switch (name[0]) { case 'l': strcpy(replace, "r"); @@ -682,40 +688,43 @@ void BKE_deform_flip_side_name(char name[MAX_VGROUP_NAME], const char from_name[ BLI_strncpy(suffix, name + 1, sizeof(suffix)); prefix[0] = 0; break; + default: + is_set = false; } } - else if (len > 5) { + + if (!is_set && len > 5) { /* hrms, why test for a separator? lets do the rule 'ultimate left or right' */ - index = BLI_strcasestr(prefix, "right"); - if (index == prefix || index == prefix + len - 5) { - if (index[0] == 'r') + if (((index = BLI_strcasestr(prefix, "right")) == prefix) || + (index == prefix + len - 5)) + { + is_set = true; + if (index[0] == 'r') { strcpy(replace, "left"); + } else { - if (index[1] == 'I') - strcpy(replace, "LEFT"); - else - strcpy(replace, "Left"); + strcpy(replace, (index[1] == 'I') ? "LEFT" : "Left"); } *index = 0; BLI_strncpy(suffix, index + 5, sizeof(suffix)); } - else { - index = BLI_strcasestr(prefix, "left"); - if (index == prefix || index == prefix + len - 4) { - if (index[0] == 'l') - strcpy(replace, "right"); - else { - if (index[1] == 'E') - strcpy(replace, "RIGHT"); - else - strcpy(replace, "Right"); - } - *index = 0; - BLI_strncpy(suffix, index + 4, sizeof(suffix)); + else if (((index = BLI_strcasestr(prefix, "left")) == prefix) || + (index == prefix + len - 4)) + { + is_set = true; + if (index[0] == 'l') { + strcpy(replace, "right"); + } + else { + strcpy(replace, (index[1] == 'E') ? "RIGHT" : "Right"); } + *index = 0; + BLI_strncpy(suffix, index + 4, sizeof(suffix)); } } + (void)is_set; /* quiet warning */ + BLI_snprintf(name, MAX_VGROUP_NAME, "%s%s%s%s", prefix, replace, suffix, number); } diff --git a/source/blender/blenkernel/intern/depsgraph.c b/source/blender/blenkernel/intern/depsgraph.c index 24b580672d1..93bb4849718 100644 --- a/source/blender/blenkernel/intern/depsgraph.c +++ b/source/blender/blenkernel/intern/depsgraph.c @@ -59,8 +59,10 @@ #include "DNA_movieclip_types.h" #include "DNA_mask_types.h" +#include "BKE_anim.h" #include "BKE_animsys.h" #include "BKE_action.h" +#include "BKE_DerivedMesh.h" #include "BKE_effect.h" #include "BKE_fcurve.h" #include "BKE_global.h" @@ -79,6 +81,8 @@ #include "BKE_screen.h" #include "BKE_tracking.h" +#include "GPU_buffers.h" + #include "atomic_ops.h" #include "depsgraph_private.h" @@ -524,7 +528,7 @@ static void build_dag_object(DagForest *dag, DagNode *scenenode, Scene *scene, O if (ct->tar->type == OB_MESH) node3->customdata_mask |= CD_MASK_MDEFORMVERT; } - else if (ELEM3(con->type, CONSTRAINT_TYPE_FOLLOWPATH, CONSTRAINT_TYPE_CLAMPTO, CONSTRAINT_TYPE_SPLINEIK)) + else if (ELEM(con->type, CONSTRAINT_TYPE_FOLLOWPATH, CONSTRAINT_TYPE_CLAMPTO, CONSTRAINT_TYPE_SPLINEIK)) dag_add_relation(dag, node3, node, DAG_RL_DATA_DATA | DAG_RL_OB_DATA, cti->name); else dag_add_relation(dag, node3, node, DAG_RL_OB_DATA, cti->name); @@ -688,6 +692,29 @@ static void build_dag_object(DagForest *dag, DagNode *scenenode, Scene *scene, O dag_add_relation(dag, node2, node, DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Curve Taper"); } if (ob->type == OB_FONT) { + /* Really rather dirty hack. needs to support font family to work + * reliably on render export. + * + * This totally mimics behavior of regular verts duplication with + * parenting. The only tricky thing here is to get list of objects + * used for the custom "font". + * + * This shouldn't harm so much because this code only runs on DAG + * rebuild and this feature is not that commonly used. + * + * - sergey - + */ + if (cu->family[0] != '\n') { + ListBase *duplilist; + DupliObject *dob; + duplilist = object_duplilist(G.main->eval_ctx, scene, ob); + for (dob = duplilist->first; dob; dob = dob->next) { + node2 = dag_get_node(dag, dob->ob); + dag_add_relation(dag, node, node2, DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Object Font"); + } + free_object_duplilist(duplilist); + } + if (cu->textoncurve) { node2 = dag_get_node(dag, cu->textoncurve); /* Text on curve requires path to be evaluated for the target curve. */ @@ -803,7 +830,7 @@ static void build_dag_object(DagForest *dag, DagNode *scenenode, Scene *scene, O continue; /* special case for camera tracking -- it doesn't use targets to define relations */ - if (ELEM3(cti->type, CONSTRAINT_TYPE_FOLLOWTRACK, CONSTRAINT_TYPE_CAMERASOLVER, CONSTRAINT_TYPE_OBJECTSOLVER)) { + if (ELEM(cti->type, CONSTRAINT_TYPE_FOLLOWTRACK, CONSTRAINT_TYPE_CAMERASOLVER, CONSTRAINT_TYPE_OBJECTSOLVER)) { int depends_on_camera = 0; if (cti->type == CONSTRAINT_TYPE_FOLLOWTRACK) { @@ -843,7 +870,7 @@ static void build_dag_object(DagForest *dag, DagNode *scenenode, Scene *scene, O if (ELEM(con->type, CONSTRAINT_TYPE_FOLLOWPATH, CONSTRAINT_TYPE_CLAMPTO)) dag_add_relation(dag, node2, node, DAG_RL_DATA_OB | DAG_RL_OB_OB, cti->name); else { - if (ELEM3(obt->type, OB_ARMATURE, OB_MESH, OB_LATTICE) && (ct->subtarget[0])) { + if (ELEM(obt->type, OB_ARMATURE, OB_MESH, OB_LATTICE) && (ct->subtarget[0])) { dag_add_relation(dag, node2, node, DAG_RL_DATA_OB | DAG_RL_OB_OB, cti->name); if (obt->type == OB_MESH) node2->customdata_mask |= CD_MASK_MDEFORMVERT; @@ -1386,7 +1413,7 @@ static bool check_object_needs_evaluation(Object *object) if (object->type == OB_MESH) { return object->derivedFinal == NULL; } - else if (ELEM5(object->type, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL, OB_LATTICE)) { + else if (ELEM(object->type, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL, OB_LATTICE)) { return object->curve_cache == NULL; } @@ -1400,7 +1427,7 @@ static bool check_object_tagged_for_update(Object *object) return true; } - if (ELEM6(object->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL, OB_LATTICE)) { + if (ELEM(object->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL, OB_LATTICE)) { ID *data_id = object->data; return (data_id->flag & (LIB_ID_RECALC_DATA | LIB_ID_RECALC)) != 0; } @@ -1747,7 +1774,8 @@ static unsigned int flush_layer_node(Scene *sce, DagNode *node, int curtime) } /* node was checked to have lasttime != curtime, and is of type ID_OB */ -static void flush_pointcache_reset(Main *bmain, Scene *scene, DagNode *node, int curtime, int reset) +static void flush_pointcache_reset(Main *bmain, Scene *scene, DagNode *node, + int curtime, unsigned int lay, bool reset) { DagAdjList *itA; Object *ob; @@ -1761,14 +1789,17 @@ static void flush_pointcache_reset(Main *bmain, Scene *scene, DagNode *node, int if (reset || (ob->recalc & OB_RECALC_ALL)) { if (BKE_ptcache_object_reset(scene, ob, PTCACHE_RESET_DEPSGRAPH)) { - ob->recalc |= OB_RECALC_DATA; - lib_id_recalc_data_tag(bmain, &ob->id); + /* Don't tag nodes which are on invisible layer. */ + if (itA->node->lay & lay) { + ob->recalc |= OB_RECALC_DATA; + lib_id_recalc_data_tag(bmain, &ob->id); + } } - flush_pointcache_reset(bmain, scene, itA->node, curtime, 1); + flush_pointcache_reset(bmain, scene, itA->node, curtime, lay, true); } else - flush_pointcache_reset(bmain, scene, itA->node, curtime, 0); + flush_pointcache_reset(bmain, scene, itA->node, curtime, lay, false); } } } @@ -1885,10 +1916,12 @@ void DAG_scene_flush_update(Main *bmain, Scene *sce, unsigned int lay, const sho lib_id_recalc_data_tag(bmain, &ob->id); } - flush_pointcache_reset(bmain, sce, itA->node, lasttime, 1); + flush_pointcache_reset(bmain, sce, itA->node, lasttime, + lay, true); } else - flush_pointcache_reset(bmain, sce, itA->node, lasttime, 0); + flush_pointcache_reset(bmain, sce, itA->node, lasttime, + lay, false); } } } @@ -1983,7 +2016,7 @@ static void dag_object_time_update_flags(Main *bmain, Scene *scene, Object *ob) if (cti) { /* special case for camera tracking -- it doesn't use targets to define relations */ - if (ELEM3(cti->type, CONSTRAINT_TYPE_FOLLOWTRACK, CONSTRAINT_TYPE_CAMERASOLVER, CONSTRAINT_TYPE_OBJECTSOLVER)) { + if (ELEM(cti->type, CONSTRAINT_TYPE_FOLLOWTRACK, CONSTRAINT_TYPE_CAMERASOLVER, CONSTRAINT_TYPE_OBJECTSOLVER)) { ob->recalc |= OB_RECALC_OB; } else if (cti->get_constraint_targets) { @@ -2272,7 +2305,7 @@ static void dag_group_on_visible_update(Group *group) group->id.flag |= LIB_DOIT; for (go = group->gobject.first; go; go = go->next) { - if (ELEM6(go->ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL, OB_LATTICE)) { + if (ELEM(go->ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL, OB_LATTICE)) { go->ob->recalc |= OB_RECALC_DATA; go->ob->id.flag |= LIB_DOIT; lib_id_recalc_tag(G.main, &go->ob->id); @@ -2319,7 +2352,7 @@ void DAG_on_visible_update(Main *bmain, const bool do_time) oblay = (node) ? node->lay : ob->lay; if ((oblay & lay) & ~scene->lay_updated) { - if (ELEM6(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL, OB_LATTICE)) { + if (ELEM(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL, OB_LATTICE)) { ob->recalc |= OB_RECALC_DATA; lib_id_recalc_tag(bmain, &ob->id); } @@ -2472,6 +2505,14 @@ static void dag_id_flush_update(Main *bmain, Scene *sce, ID *id) BKE_ptcache_object_reset(sce, obt, PTCACHE_RESET_DEPSGRAPH); } + if (ELEM(idtype, ID_MA, ID_TE)) { + obt = sce->basact ? sce->basact->object : NULL; + if (obt && obt->mode & OB_MODE_TEXTURE_PAINT) { + BKE_texpaint_slots_refresh_object(sce, obt); + GPU_drawobject_free(obt->derivedFinal); + } + } + if (idtype == ID_MC) { MovieClip *clip = (MovieClip *) id; @@ -2481,7 +2522,7 @@ static void dag_id_flush_update(Main *bmain, Scene *sce, ID *id) bConstraint *con; for (con = obt->constraints.first; con; con = con->next) { bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con); - if (ELEM3(cti->type, CONSTRAINT_TYPE_FOLLOWTRACK, CONSTRAINT_TYPE_CAMERASOLVER, + if (ELEM(cti->type, CONSTRAINT_TYPE_FOLLOWTRACK, CONSTRAINT_TYPE_CAMERASOLVER, CONSTRAINT_TYPE_OBJECTSOLVER)) { obt->recalc |= OB_RECALC_OB; @@ -2502,6 +2543,23 @@ static void dag_id_flush_update(Main *bmain, Scene *sce, ID *id) } } + /* Not pretty to iterate all the nodes here, but it's as good as it + * could be with the current depsgraph design/ + */ + if (idtype == ID_IM) { + FOREACH_NODETREE(bmain, ntree, parent_id) { + if (ntree->type == NTREE_SHADER) { + bNode *node; + for (node = ntree->nodes.first; node; node = node->next) { + if (node->id == id) { + lib_id_recalc_tag(bmain, &ntree->id); + break; + } + } + } + } FOREACH_NODETREE_END + } + if (idtype == ID_MSK) { if (sce->nodetree) { bNode *node; @@ -2742,7 +2800,7 @@ void DAG_id_tag_update_ex(Main *bmain, ID *id, short flag) if (ob->type == OB_FONT) { Curve *cu = ob->data; - if (ELEM4((struct VFont *)id, cu->vfont, cu->vfontb, cu->vfonti, cu->vfontbi)) { + if (ELEM((struct VFont *)id, cu->vfont, cu->vfontb, cu->vfonti, cu->vfontbi)) { ob->recalc |= (flag & OB_RECALC_ALL); } } diff --git a/source/blender/blenkernel/intern/displist.c b/source/blender/blenkernel/intern/displist.c index cf894e72324..98f0025921d 100644 --- a/source/blender/blenkernel/intern/displist.c +++ b/source/blender/blenkernel/intern/displist.c @@ -122,7 +122,7 @@ bool BKE_displist_has_faces(ListBase *lb) DispList *dl; for (dl = lb->first; dl; dl = dl->next) { - if (ELEM3(dl->type, DL_INDEX3, DL_INDEX4, DL_SURF)) { + if (ELEM(dl->type, DL_INDEX3, DL_INDEX4, DL_SURF)) { return true; } } @@ -653,8 +653,8 @@ static void curve_to_filledpoly(Curve *cu, ListBase *UNUSED(nurb), ListBase *dis bevels_to_filledpoly(cu, dispbase); } else { - /* TODO, investigate passing zup instead of NULL */ - BKE_displist_fill(dispbase, dispbase, NULL, false); + const float z_up[3] = {0.0f, 0.0f, 1.0f}; + BKE_displist_fill(dispbase, dispbase, z_up, false); } } @@ -715,21 +715,20 @@ void BKE_displist_make_mball(EvaluationContext *eval_ctx, Scene *scene, Object * if (!ob || ob->type != OB_MBALL) return; - if (ob->curve_cache) { - BKE_displist_free(&(ob->curve_cache->disp)); - } - else { - ob->curve_cache = MEM_callocN(sizeof(CurveCache), "CurveCache for MBall"); - } + if (ob == BKE_mball_basis_find(scene, ob)) { + if (ob->curve_cache) { + BKE_displist_free(&(ob->curve_cache->disp)); + } + else { + ob->curve_cache = MEM_callocN(sizeof(CurveCache), "CurveCache for MBall"); + } - if (ob->type == OB_MBALL) { - if (ob == BKE_mball_basis_find(scene, ob)) { - BKE_mball_polygonize(eval_ctx, scene, ob, &ob->curve_cache->disp); - BKE_mball_texspace_calc(ob); + BKE_mball_polygonize(eval_ctx, scene, ob, &ob->curve_cache->disp); + BKE_mball_texspace_calc(ob); - object_deform_mball(ob, &ob->curve_cache->disp); - } + object_deform_mball(ob, &ob->curve_cache->disp); + /* NOP for MBALLs anyway... */ boundbox_displist_object(ob); } } @@ -767,7 +766,7 @@ static ModifierData *curve_get_tessellate_point(Scene *scene, Object *ob, if (mti->type == eModifierTypeType_Constructive) return pretessellatePoint; - if (ELEM3(md->type, eModifierType_Hook, eModifierType_Softbody, eModifierType_MeshDeform)) { + if (ELEM(md->type, eModifierType_Hook, eModifierType_Softbody, eModifierType_MeshDeform)) { pretessellatePoint = md; /* this modifiers are moving point of tessellation automatically @@ -1357,31 +1356,57 @@ static void fillBevelCap(Nurb *nu, DispList *dlb, float *prev_fp, ListBase *disp BLI_addtail(dispbase, dl); } +static void calc_bevfac_segment_mapping(BevList *bl, float bevfac, float spline_length, int *r_bev, float *r_blend) +{ + float normlen, normsum = 0.0f; + float *seglen = bl->seglen; + int *segbevcount = bl->segbevcount; + int bevcount = 0, nr = bl->nr; + + float bev_fl = bevfac * (bl->nr - 1); + *r_bev = (int)bev_fl; + + while (bevcount < nr - 1) { + normlen = *seglen / spline_length; + if (normsum + normlen > bevfac) { + bev_fl = bevcount + (bevfac - normsum) / normlen * *segbevcount; + *r_bev = (int) bev_fl; + *r_blend = bev_fl - *r_bev; + break; + } + normsum += normlen; + bevcount += *segbevcount; + segbevcount++; + seglen++; + } +} -static void calc_bevfac_spline_mapping(BevList *bl, float bevfac, float spline_length, const float *bevp_array, +static void calc_bevfac_spline_mapping(BevList *bl, float bevfac, + float spline_length, int *r_bev, float *r_blend) { const float len_target = bevfac * spline_length; - float len = 0.0f; - float len_step = 0.0f; - int i; - for (i = 0; i < bl->nr - 1; i++) { - float len_next; - len_step = bevp_array[i]; - len_next = len + len_step; + BevPoint *bevp = bl->bevpoints; + float len_next = 0.0f, len = 0.0f; + int i = 0, nr = bl->nr; + + while (nr--) { + bevp++; + len_next = len + bevp->offset; if (len_next > len_target) { break; } len = len_next; + i++; } *r_bev = i; - *r_blend = (len_target - len) / len_step; + *r_blend = (len_target - len) / bevp->offset; } -static void calc_bevfac_mapping_default( - BevList *bl, - int *r_start, float *r_firstblend, int *r_steps, float *r_lastblend) +static void calc_bevfac_mapping_default(BevList *bl, + int *r_start, float *r_firstblend, + int *r_steps, float *r_lastblend) { *r_start = 0; *r_steps = bl->nr; @@ -1389,19 +1414,11 @@ static void calc_bevfac_mapping_default( *r_lastblend = 1.0f; } -static void calc_bevfac_mapping( - Curve *cu, BevList *bl, Nurb *nu, const bool use_render_resolution, +static void calc_bevfac_mapping(Curve *cu, BevList *bl, Nurb *nu, int *r_start, float *r_firstblend, int *r_steps, float *r_lastblend) { - const int resolu = (nu->type == CU_POLY) ? - 1 : (use_render_resolution && (cu->resolu_ren != 0)) ? - cu->resolu_ren : cu->resolu; - const int segcount = ((nu->type == CU_POLY) ? bl->nr : nu->pntsu) - 1; - - float l, startf, endf, tmpf, total_length = 0.0f; - float *bevp_array = NULL; - float *segments = NULL; - int end = 0, i, j; + float tmpf, total_length = 0.0f; + int end = 0, i; if ((BKE_nurb_check_valid_u(nu) == false) || /* not essential, but skips unnecessary calculation */ @@ -1412,57 +1429,12 @@ static void calc_bevfac_mapping( return; } - if ((cu->bevfac1_mapping != CU_BEVFAC_MAP_RESOLU) || - (cu->bevfac2_mapping != CU_BEVFAC_MAP_RESOLU)) + if (ELEM(cu->bevfac1_mapping, + CU_BEVFAC_MAP_SEGMENT, + CU_BEVFAC_MAP_SPLINE)) { - BezTriple *bezt, *bezt_prev; - BevPoint *bevp, *bevp_prev; - int bevp_i; - - bevp_array = MEM_mallocN(sizeof(*bevp_array) * (bl->nr - 1), "bevp_dists"); - segments = MEM_callocN(sizeof(*segments) * segcount, "bevp_segmentlengths"); - bevp_prev = bl->bevpoints; - bevp = bevp_prev + 1; - - if (nu->type == CU_BEZIER) { - bezt_prev = nu->bezt; - bezt = bezt_prev + 1; - for (i = 0, bevp_i = 0; i < segcount; i++, bezt_prev++, bezt++) { - float seglen = 0.0f; - if (bezt_prev->h2 == HD_VECT && bezt->h1 == HD_VECT) { - seglen = len_v3v3(bevp->vec, bevp_prev->vec); - BLI_assert(bevp_i < bl->nr - 1); - bevp_array[bevp_i++] = seglen; - - bevp_prev = bevp++; - } - else { - for (j = 0; j < resolu; j++, bevp_prev = bevp++) { - l = len_v3v3(bevp->vec, bevp_prev->vec); - seglen += l; - BLI_assert(bevp_i < bl->nr - 1); - bevp_array[bevp_i++] = l; - } - } - BLI_assert(i < segcount); - segments[i] = seglen; - total_length += seglen; - seglen = 0.0f; - } - } - else { - float seglen = 0.0f; - for (i = 1, j = 0; i < bl->nr; i++, bevp_prev = bevp++) { - BLI_assert(i - 1 < bl->nr); - bevp_array[i - 1] = len_v3v3(bevp->vec, bevp_prev->vec); - total_length += bevp_array[i - 1]; - seglen += bevp_array[i - 1]; - if ((i % resolu) == 0 || (bl->nr - 1) == i) { - BLI_assert(j < segcount); - segments[j++] = seglen; - seglen = 0.0f; - } - } + for (i = 0; i < SEGMENTSU(nu); i++) { + total_length += bl->seglen[i]; } } @@ -1471,31 +1443,18 @@ static void calc_bevfac_mapping( { const float start_fl = cu->bevfac1 * (bl->nr - 1); *r_start = (int)start_fl; - *r_firstblend = 1.0f - (start_fl - (*r_start)); break; } case CU_BEVFAC_MAP_SEGMENT: { - float sum = 0.0f; - const float start_fl = cu->bevfac1 * (bl->nr - 1); - *r_start = (int)start_fl; - - for (i = 0; i < segcount; i++) { - l = segments[i] / total_length; - if (sum + l > cu->bevfac1) { - startf = i * resolu + (cu->bevfac1 - sum) / l * resolu; - *r_start = (int) startf; - *r_firstblend = 1.0f - (startf - *r_start); - break; - } - sum += l; - } + calc_bevfac_segment_mapping(bl, cu->bevfac1, total_length, r_start, r_firstblend); + *r_firstblend = 1.0f - *r_firstblend; break; } case CU_BEVFAC_MAP_SPLINE: { - calc_bevfac_spline_mapping(bl, cu->bevfac1, total_length, bevp_array, r_start, r_firstblend); + calc_bevfac_spline_mapping(bl, cu->bevfac1, total_length, r_start, r_firstblend); *r_firstblend = 1.0f - *r_firstblend; break; } @@ -1513,27 +1472,13 @@ static void calc_bevfac_mapping( } case CU_BEVFAC_MAP_SEGMENT: { - float sum = 0.0f; - const float end_fl = cu->bevfac2 * (bl->nr - 1); - end = (int)end_fl; - + calc_bevfac_segment_mapping(bl, cu->bevfac2, total_length, &end, r_lastblend); *r_steps = end - *r_start + 2; - for (i = 0; i < segcount; i++) { - l = segments[i] / total_length; - if (sum + l > cu->bevfac2) { - endf = i * resolu + (cu->bevfac2 - sum) / l * resolu; - end = (int)endf; - *r_lastblend = (endf - end); - *r_steps = end - *r_start + 2; - break; - } - sum += l; - } break; } case CU_BEVFAC_MAP_SPLINE: { - calc_bevfac_spline_mapping(bl, cu->bevfac2, total_length, bevp_array, &end, r_lastblend); + calc_bevfac_spline_mapping(bl, cu->bevfac2, total_length, &end, r_lastblend); *r_steps = end - *r_start + 2; break; } @@ -1551,13 +1496,6 @@ static void calc_bevfac_mapping( *r_steps = bl->nr - *r_start; *r_lastblend = 1.0f; } - - if (bevp_array) { - MEM_freeN(bevp_array); - } - if (segments) { - MEM_freeN(segments); - } } static void do_makeDispListCurveTypes(Scene *scene, Object *ob, ListBase *dispbase, @@ -1567,7 +1505,7 @@ static void do_makeDispListCurveTypes(Scene *scene, Object *ob, ListBase *dispba Curve *cu = ob->data; /* we do allow duplis... this is only displist on curve level */ - if (!ELEM3(ob->type, OB_SURF, OB_CURVE, OB_FONT)) return; + if (!ELEM(ob->type, OB_SURF, OB_CURVE, OB_FONT)) return; if (ob->type == OB_SURF) { BKE_displist_make_surf(scene, ob, dispbase, r_dm_final, for_render, for_orco, use_render_resolution); @@ -1576,7 +1514,7 @@ static void do_makeDispListCurveTypes(Scene *scene, Object *ob, ListBase *dispba ListBase dlbev; ListBase nubase = {NULL, NULL}; - BLI_freelistN(&(ob->curve_cache->bev)); + BKE_curve_bevelList_free(&ob->curve_cache->bev); /* We only re-evlauate path if evaluation is not happening for orco. * If the calculation happens for orco, we should never free data which @@ -1668,8 +1606,7 @@ static void do_makeDispListCurveTypes(Scene *scene, Object *ob, ListBase *dispba continue; } - calc_bevfac_mapping(cu, bl, nu, use_render_resolution, - &start, &firstblend, &steps, &lastblend); + calc_bevfac_mapping(cu, bl, nu, &start, &firstblend, &steps, &lastblend); } for (dlb = dlbev.first; dlb; dlb = dlb->next) { @@ -1810,7 +1747,7 @@ void BKE_displist_make_curveTypes(Scene *scene, Object *ob, const bool for_orco) /* The same check for duplis as in do_makeDispListCurveTypes. * Happens when curve used for constraint/bevel was converted to mesh. * check there is still needed for render displist and orco displists. */ - if (!ELEM3(ob->type, OB_SURF, OB_CURVE, OB_FONT)) + if (!ELEM(ob->type, OB_SURF, OB_CURVE, OB_FONT)) return; BKE_object_free_derived_caches(ob); @@ -1831,7 +1768,7 @@ void BKE_displist_make_curveTypes_forRender(Scene *scene, Object *ob, ListBase * const bool use_render_resolution) { if (ob->curve_cache == NULL) { - ob->curve_cache = MEM_callocN(sizeof(CurveCache), "CurveCache for MBall"); + ob->curve_cache = MEM_callocN(sizeof(CurveCache), "CurveCache for Curve"); } do_makeDispListCurveTypes(scene, ob, dispbase, r_dm_final, true, for_orco, use_render_resolution); @@ -1840,7 +1777,7 @@ void BKE_displist_make_curveTypes_forRender(Scene *scene, Object *ob, ListBase * void BKE_displist_make_curveTypes_forOrco(struct Scene *scene, struct Object *ob, struct ListBase *dispbase) { if (ob->curve_cache == NULL) { - ob->curve_cache = MEM_callocN(sizeof(CurveCache), "CurveCache for MBall"); + ob->curve_cache = MEM_callocN(sizeof(CurveCache), "CurveCache for Curve"); } do_makeDispListCurveTypes(scene, ob, dispbase, NULL, 1, 1, 1); @@ -1895,8 +1832,8 @@ void BKE_displist_minmax(ListBase *dispbase, float min[3], float max[3]) /* this is confusing, there's also min_max_object, appplying the obmat... */ static void boundbox_displist_object(Object *ob) { - if (ELEM3(ob->type, OB_CURVE, OB_SURF, OB_FONT)) { - /* Curver's BB is already calculated as a part of modifier stack, + if (ELEM(ob->type, OB_CURVE, OB_SURF, OB_FONT)) { + /* Curve's BB is already calculated as a part of modifier stack, * here we only calculate object BB based on final display list. */ diff --git a/source/blender/blenkernel/intern/dynamicpaint.c b/source/blender/blenkernel/intern/dynamicpaint.c index 11737bccef2..4719013e2f8 100644 --- a/source/blender/blenkernel/intern/dynamicpaint.c +++ b/source/blender/blenkernel/intern/dynamicpaint.c @@ -2942,9 +2942,10 @@ static void mesh_faces_nearest_point_dp(void *userdata, int index, const float c do { float nearest_tmp[3], dist_sq; - int vertex, edge; - - dist_sq = nearest_point_in_tri_surface_squared(t0, t1, t2, co, &vertex, &edge, nearest_tmp); + + closest_on_tri_to_point_v3(nearest_tmp, co, t0, t1, t2); + dist_sq = len_squared_v3v3(co, nearest_tmp); + if (dist_sq < nearest->dist_sq) { nearest->index = index; nearest->dist_sq = dist_sq; diff --git a/source/blender/blenkernel/intern/editderivedmesh.c b/source/blender/blenkernel/intern/editderivedmesh.c index e74adea529b..ce7804d9878 100644 --- a/source/blender/blenkernel/intern/editderivedmesh.c +++ b/source/blender/blenkernel/intern/editderivedmesh.c @@ -910,7 +910,7 @@ static void emDM_drawFacesTex_common(DerivedMesh *dm, static void emDM_drawFacesTex(DerivedMesh *dm, DMSetDrawOptionsTex setDrawOptions, DMCompareDrawOptions compareDrawOptions, - void *userData) + void *userData, DMDrawFlag UNUSED(flag)) { emDM_drawFacesTex_common(dm, setDrawOptions, NULL, compareDrawOptions, userData); } @@ -918,7 +918,7 @@ static void emDM_drawFacesTex(DerivedMesh *dm, static void emDM_drawMappedFacesTex(DerivedMesh *dm, DMSetDrawOptions setDrawOptions, DMCompareDrawOptions compareDrawOptions, - void *userData) + void *userData, DMDrawFlag UNUSED(flag)) { emDM_drawFacesTex_common(dm, NULL, setDrawOptions, compareDrawOptions, userData); } diff --git a/source/blender/blenkernel/intern/editmesh_bvh.c b/source/blender/blenkernel/intern/editmesh_bvh.c index 76ea340ecbd..442ab26ffc8 100644 --- a/source/blender/blenkernel/intern/editmesh_bvh.c +++ b/source/blender/blenkernel/intern/editmesh_bvh.c @@ -53,13 +53,17 @@ struct BMBVHTree { int flag; }; -BMBVHTree *BKE_bmbvh_new_from_editmesh(BMEditMesh *em, int flag, const float (*cos_cage)[3], const bool cos_cage_free) +BMBVHTree *BKE_bmbvh_new_from_editmesh( + BMEditMesh *em, int flag, + const float (*cos_cage)[3], const bool cos_cage_free) { return BKE_bmbvh_new(em->bm, em->looptris, em->tottri, flag, cos_cage, cos_cage_free); } -BMBVHTree *BKE_bmbvh_new(BMesh *bm, BMLoop *(*looptris)[3], int looptris_tot, int flag, const float (*cos_cage)[3], -const bool cos_cage_free) +BMBVHTree *BKE_bmbvh_new_ex( + BMesh *bm, BMLoop *(*looptris)[3], int looptris_tot, int flag, + const float (*cos_cage)[3], const bool cos_cage_free, + bool (*test_fn)(BMFace *, void *user_data), void *user_data) { /* could become argument */ const float epsilon = FLT_EPSILON * 2.0f; @@ -69,6 +73,10 @@ const bool cos_cage_free) int i; int tottri; + /* avoid testing every tri */ + BMFace *f_test, *f_test_prev; + bool test_fn_ret; + /* BKE_editmesh_tessface_calc() must be called already */ BLI_assert(looptris_tot != 0 || bm->totface == 0); @@ -83,18 +91,22 @@ const bool cos_cage_free) bmtree->cos_cage_free = cos_cage_free; bmtree->flag = flag; - if (flag & (BMBVH_RESPECT_SELECT)) { + if (test_fn) { + /* callback must do... */ + BLI_assert(!(flag & (BMBVH_RESPECT_SELECT | BMBVH_RESPECT_HIDDEN))); + + f_test_prev = NULL; + test_fn_ret = false; + tottri = 0; for (i = 0; i < looptris_tot; i++) { - if (BM_elem_flag_test(looptris[i][0]->f, BM_ELEM_SELECT)) { - tottri++; + f_test = looptris[i][0]->f; + if (f_test != f_test_prev) { + test_fn_ret = test_fn(f_test, user_data); + f_test_prev = f_test; } - } - } - else if (flag & (BMBVH_RESPECT_HIDDEN)) { - tottri = 0; - for (i = 0; i < looptris_tot; i++) { - if (!BM_elem_flag_test(looptris[i][0]->f, BM_ELEM_HIDDEN)) { + + if (test_fn_ret) { tottri++; } } @@ -105,17 +117,19 @@ const bool cos_cage_free) bmtree->tree = BLI_bvhtree_new(tottri, epsilon, 8, 8); - for (i = 0; i < looptris_tot; i++) { + f_test_prev = NULL; + test_fn_ret = false; - if (flag & BMBVH_RESPECT_SELECT) { + for (i = 0; i < looptris_tot; i++) { + if (test_fn) { /* note, the arrays wont align now! take care */ - if (!BM_elem_flag_test(looptris[i][0]->f, BM_ELEM_SELECT)) { - continue; + f_test = looptris[i][0]->f; + if (f_test != f_test_prev) { + test_fn_ret = test_fn(f_test, user_data); + f_test_prev = f_test; } - } - else if (flag & BMBVH_RESPECT_HIDDEN) { - /* note, the arrays wont align now! take care */ - if (BM_elem_flag_test(looptris[i][0]->f, BM_ELEM_HIDDEN)) { + + if (!test_fn_ret) { continue; } } @@ -139,6 +153,38 @@ const bool cos_cage_free) return bmtree; } +static bool bm_face_is_select(BMFace *f, void *UNUSED(user_data)) +{ + return (BM_elem_flag_test(f, BM_ELEM_SELECT) != 0); +} + +static bool bm_face_is_not_hidden(BMFace *f, void *UNUSED(user_data)) +{ + return (BM_elem_flag_test(f, BM_ELEM_HIDDEN) == 0); +} + +BMBVHTree *BKE_bmbvh_new( + BMesh *bm, BMLoop *(*looptris)[3], int looptris_tot, int flag, + const float (*cos_cage)[3], const bool cos_cage_free) +{ + bool (*test_fn)(BMFace *, void *user_data); + + if (flag & BMBVH_RESPECT_SELECT) { + test_fn = bm_face_is_select; + } + else if (flag & BMBVH_RESPECT_HIDDEN) { + test_fn = bm_face_is_not_hidden; + } + else { + test_fn = NULL; + } + + flag &= ~(BMBVH_RESPECT_SELECT | BMBVH_RESPECT_HIDDEN); + + return BKE_bmbvh_new_ex(bm, looptris, looptris_tot, flag, cos_cage, cos_cage_free, test_fn, NULL); +} + + void BKE_bmbvh_free(BMBVHTree *bmtree) { BLI_bvhtree_free(bmtree->tree); diff --git a/source/blender/blenkernel/intern/effect.c b/source/blender/blenkernel/intern/effect.c index e28152dbc1a..4859aa8f791 100644 --- a/source/blender/blenkernel/intern/effect.c +++ b/source/blender/blenkernel/intern/effect.c @@ -935,7 +935,7 @@ static void do_physical_effector(EffectorCache *eff, EffectorData *efd, Effected if (pd->flag & PFIELD_DO_LOCATION) { madd_v3_v3fl(total_force, force, 1.0f/point->vel_to_sec); - if (ELEM3(pd->forcefield, PFIELD_HARMONIC, PFIELD_DRAG, PFIELD_SMOKEFLOW)==0 && pd->f_flow != 0.0f) { + if (ELEM(pd->forcefield, PFIELD_HARMONIC, PFIELD_DRAG, PFIELD_SMOKEFLOW)==0 && pd->f_flow != 0.0f) { madd_v3_v3fl(total_force, point->vel, -pd->f_flow * efd->falloff); } } diff --git a/source/blender/blenkernel/intern/fcurve.c b/source/blender/blenkernel/intern/fcurve.c index a8de9b69fbe..09c1dcf701d 100644 --- a/source/blender/blenkernel/intern/fcurve.c +++ b/source/blender/blenkernel/intern/fcurve.c @@ -276,7 +276,7 @@ int list_find_data_fcurves(ListBase *dst, ListBase *src, const char *dataPrefix, int matches = 0; /* sanity checks */ - if (ELEM4(NULL, dst, src, dataPrefix, dataName)) + if (ELEM(NULL, dst, src, dataPrefix, dataName)) return 0; else if ((dataPrefix[0] == 0) || (dataName[0] == 0)) return 0; @@ -522,17 +522,28 @@ bool calc_fcurve_bounds(FCurve *fcu, float *xmin, float *xmax, float *ymin, floa /* only loop over keyframes to find extents for values if needed */ if (ymin || ymax) { - BezTriple *bezt; + BezTriple *bezt, *prevbezt = NULL; - for (bezt = fcu->bezt, i = 0; i < fcu->totvert; bezt++, i++) { - if ((do_sel_only == false) || BEZSELECTED(bezt)) { + for (bezt = fcu->bezt, i = 0; i < fcu->totvert; prevbezt = bezt, bezt++, i++) { + if ((do_sel_only == false) || BEZSELECTED(bezt)) { + /* keyframe itself */ + yminv = min_ff(yminv, bezt->vec[1][1]); + ymaxv = max_ff(ymaxv, bezt->vec[1][1]); + if (include_handles) { - yminv = min_ffff(yminv, bezt->vec[1][1], bezt->vec[0][1], bezt->vec[2][1]); - ymaxv = max_ffff(ymaxv, bezt->vec[1][1], bezt->vec[0][1], bezt->vec[2][1]); - } - else { - yminv = min_ff(yminv, bezt->vec[1][1]); - ymaxv = max_ff(ymaxv, bezt->vec[1][1]); + /* left handle - only if applicable + * NOTE: for the very first keyframe, the left handle actually has no bearings on anything + */ + if (prevbezt && (prevbezt->ipo == BEZT_IPO_BEZ)) { + yminv = min_ff(yminv, bezt->vec[0][1]); + ymaxv = max_ff(ymaxv, bezt->vec[0][1]); + } + + /* right handle - only if applicable */ + if (bezt->ipo == BEZT_IPO_BEZ) { + yminv = min_ff(yminv, bezt->vec[2][1]); + ymaxv = max_ff(ymaxv, bezt->vec[2][1]); + } } foundvert = true; diff --git a/source/blender/blenkernel/intern/freestyle.c b/source/blender/blenkernel/intern/freestyle.c index 445acc850e6..4aa1b49ea13 100644 --- a/source/blender/blenkernel/intern/freestyle.c +++ b/source/blender/blenkernel/intern/freestyle.c @@ -187,7 +187,7 @@ FreestyleLineSet *BKE_freestyle_lineset_add(FreestyleConfig *config, const char BLI_addtail(&config->linesets, (void *)lineset); BKE_freestyle_lineset_set_active_index(config, lineset_index); - lineset->linestyle = BKE_new_linestyle("LineStyle", NULL); + lineset->linestyle = BKE_linestyle_new("LineStyle", NULL); lineset->flags |= FREESTYLE_LINESET_ENABLED; lineset->selection = FREESTYLE_SEL_VISIBILITY | FREESTYLE_SEL_EDGE_TYPES | FREESTYLE_SEL_IMAGE_BORDER; lineset->qi = FREESTYLE_QI_VISIBLE; diff --git a/source/blender/blenkernel/intern/gpencil.c b/source/blender/blenkernel/intern/gpencil.c index c381084cfd2..e226e9d9797 100644 --- a/source/blender/blenkernel/intern/gpencil.c +++ b/source/blender/blenkernel/intern/gpencil.c @@ -506,7 +506,7 @@ void gpencil_layer_setactive(bGPdata *gpd, bGPDlayer *active) bGPDlayer *gpl; /* error checking */ - if (ELEM3(NULL, gpd, gpd->layers.first, active)) + if (ELEM(NULL, gpd, gpd->layers.first, active)) return; /* loop over layers deactivating all */ diff --git a/source/blender/blenkernel/intern/idcode.c b/source/blender/blenkernel/intern/idcode.c index 2e201a0b8e8..1b7a03ec80e 100644 --- a/source/blender/blenkernel/intern/idcode.c +++ b/source/blender/blenkernel/intern/idcode.c @@ -73,6 +73,8 @@ static IDType idtypes[] = { { ID_NT, "NodeTree", "node_groups", IDTYPE_FLAGS_ISLINKABLE }, { ID_OB, "Object", "objects", IDTYPE_FLAGS_ISLINKABLE }, { ID_PA, "ParticleSettings", "particles", 0 }, + { ID_PAL, "Palettes", "palettes", IDTYPE_FLAGS_ISLINKABLE }, + { ID_PC, "PaintCurve", "paint_curves", IDTYPE_FLAGS_ISLINKABLE }, { ID_SCE, "Scene", "scenes", IDTYPE_FLAGS_ISLINKABLE }, { ID_SCR, "Screen", "screens", 0 }, { ID_SEQ, "Sequence", "sequences", 0 }, /* not actually ID data */ diff --git a/source/blender/blenkernel/intern/idprop.c b/source/blender/blenkernel/intern/idprop.c index 3188676fb6c..4dbd15a3774 100644 --- a/source/blender/blenkernel/intern/idprop.c +++ b/source/blender/blenkernel/intern/idprop.c @@ -64,7 +64,7 @@ static char idp_size_table[] = { /** \name IDP Array API * \{ */ -#define GETPROP(prop, i) (((IDProperty *)(prop)->data.pointer) + (i)) +#define GETPROP(prop, i) &(IDP_IDPArray(prop)[i]) /* --------- property array type -------------*/ @@ -251,7 +251,7 @@ void IDP_ResizeArray(IDProperty *prop, int newlen) * The growth pattern is: 0, 4, 8, 16, 25, 35, 46, 58, 72, 88, ... */ newsize = newlen; - newsize = (newsize >> 3) + (newsize < 9 ? 3 : 6) + newsize;\ + newsize = (newsize >> 3) + (newsize < 9 ? 3 : 6) + newsize; if (is_grow == false) idp_resize_group_array(prop, newlen, prop->data.pointer); @@ -821,7 +821,7 @@ bool IDP_EqualsProperties_ex(IDProperty *prop1, IDProperty *prop2, const bool is case IDP_INT: return (IDP_Int(prop1) == IDP_Int(prop2)); case IDP_FLOAT: -#if defined(DEBUG) && defined(WITH_PYTHON) +#if !defined(NDEBUG) && defined(WITH_PYTHON) { float p1 = IDP_Float(prop1); float p2 = IDP_Float(prop2); diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c index db5c212d1db..805c1250c5d 100644 --- a/source/blender/blenkernel/intern/image.c +++ b/source/blender/blenkernel/intern/image.c @@ -1257,7 +1257,7 @@ static bool do_add_image_extension(char *string, const char imtype, const ImageF extension = extension_test; } #endif - else if (ELEM5(imtype, R_IMF_IMTYPE_PNG, R_IMF_IMTYPE_FFMPEG, R_IMF_IMTYPE_H264, R_IMF_IMTYPE_THEORA, R_IMF_IMTYPE_XVID)) { + else if (ELEM(imtype, R_IMF_IMTYPE_PNG, R_IMF_IMTYPE_FFMPEG, R_IMF_IMTYPE_H264, R_IMF_IMTYPE_THEORA, R_IMF_IMTYPE_XVID)) { if (!BLI_testextensie(string, extension_test = ".png")) extension = extension_test; } @@ -1900,7 +1900,7 @@ int BKE_imbuf_write(ImBuf *ibuf, const char *name, ImageFormatData *imf) ibuf->ftype = RADHDR; } #endif - else if (ELEM5(imtype, R_IMF_IMTYPE_PNG, R_IMF_IMTYPE_FFMPEG, R_IMF_IMTYPE_H264, R_IMF_IMTYPE_THEORA, R_IMF_IMTYPE_XVID)) { + else if (ELEM(imtype, R_IMF_IMTYPE_PNG, R_IMF_IMTYPE_FFMPEG, R_IMF_IMTYPE_H264, R_IMF_IMTYPE_THEORA, R_IMF_IMTYPE_XVID)) { ibuf->ftype = PNG; if (imtype == R_IMF_IMTYPE_PNG) { diff --git a/source/blender/blenkernel/intern/implicit.c b/source/blender/blenkernel/intern/implicit.c index 6682b1a9b2d..4d80256426d 100644 --- a/source/blender/blenkernel/intern/implicit.c +++ b/source/blender/blenkernel/intern/implicit.c @@ -1804,6 +1804,7 @@ static int UNUSED_FUNCTION(cloth_calc_helper_forces)(Object *UNUSED(ob), ClothMo return 1; } + int implicit_solver(Object *ob, float frame, ClothModifierData *clmd, ListBase *effectors) { unsigned int i=0; @@ -1888,10 +1889,8 @@ int implicit_solver(Object *ob, float frame, ClothModifierData *clmd, ListBase * //if (do_extra_solve) // cloth_calc_helper_forces(ob, clmd, initial_cos, step/clmd->sim_parms->timescale, dt/clmd->sim_parms->timescale); - for (i = 0; i < numverts; i++) { - - if (do_extra_solve) { - + if (do_extra_solve) { + for (i = 0; i < numverts; i++) { if ((clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL) && (verts [i].flags & CLOTH_VERT_FLAG_PINNED)) continue; diff --git a/source/blender/blenkernel/intern/ipo.c b/source/blender/blenkernel/intern/ipo.c index 7385322ddeb..51cf26063c7 100644 --- a/source/blender/blenkernel/intern/ipo.c +++ b/source/blender/blenkernel/intern/ipo.c @@ -1308,8 +1308,8 @@ static void icu_to_fcurves(ID *id, ListBase *groups, ListBase *list, IpoCurve *i * - they were degrees/10 * - we need radians for RNA to do the right thing */ - if ( ((icu->blocktype == ID_OB) && ELEM3(icu->adrcode, OB_ROT_X, OB_ROT_Y, OB_ROT_Z)) || - ((icu->blocktype == ID_PO) && ELEM3(icu->adrcode, AC_EUL_X, AC_EUL_Y, AC_EUL_Z)) ) + if ( ((icu->blocktype == ID_OB) && ELEM(icu->adrcode, OB_ROT_X, OB_ROT_Y, OB_ROT_Z)) || + ((icu->blocktype == ID_PO) && ELEM(icu->adrcode, AC_EUL_X, AC_EUL_Y, AC_EUL_Z)) ) { const float fac = (float)M_PI / 18.0f; //10.0f * M_PI/180.0f; @@ -1341,7 +1341,7 @@ static void icu_to_fcurves(ID *id, ListBase *groups, ListBase *list, IpoCurve *i DriverVar *dvar = fcu->driver->variables.first; DriverTarget *dtar = &dvar->targets[0]; - if (ELEM3(dtar->transChan, DTAR_TRANSCHAN_ROTX, DTAR_TRANSCHAN_ROTY, DTAR_TRANSCHAN_ROTZ)) { + if (ELEM(dtar->transChan, DTAR_TRANSCHAN_ROTX, DTAR_TRANSCHAN_ROTY, DTAR_TRANSCHAN_ROTZ)) { const float fac = (float)M_PI / 18.0f; dst->vec[0][0] *= fac; @@ -1388,7 +1388,7 @@ static void ipo_to_animato(ID *id, Ipo *ipo, char actname[], char constname[], S IpoCurve *icu; /* sanity check */ - if (ELEM3(NULL, ipo, anim, drivers)) + if (ELEM(NULL, ipo, anim, drivers)) return; if (G.debug & G_DEBUG) printf("ipo_to_animato\n"); diff --git a/source/blender/blenkernel/intern/lattice.c b/source/blender/blenkernel/intern/lattice.c index ea55f32ea05..3f12e3efcc7 100644 --- a/source/blender/blenkernel/intern/lattice.c +++ b/source/blender/blenkernel/intern/lattice.c @@ -729,7 +729,8 @@ void curve_deform_verts(Scene *scene, Object *cuOb, Object *target, DerivedMesh Curve *cu; int a; CurveDeform cd; - int use_vgroups; + MDeformVert *dvert = NULL; + int defgrp_index = -1; const bool is_neg_axis = (defaxis > 2); if (cuOb->type != OB_CURVE) @@ -750,75 +751,63 @@ void curve_deform_verts(Scene *scene, Object *cuOb, Object *target, DerivedMesh cd.dmax[0] = cd.dmax[1] = cd.dmax[2] = 0.0f; } - /* check whether to use vertex groups (only possible if target is a Mesh) - * we want either a Mesh with no derived data, or derived data with - * deformverts + /* Check whether to use vertex groups (only possible if target is a Mesh or Lattice). + * We want either a Mesh/Lattice with no derived data, or derived data with deformverts. */ - if (target->type == OB_MESH) { - /* if there's derived data without deformverts, don't use vgroups */ - if (dm) { - use_vgroups = (dm->getVertData(dm, 0, CD_MDEFORMVERT) != NULL); - } - else { - Mesh *me = target->data; - use_vgroups = (me->dvert != NULL); + if (vgroup && vgroup[0] && ELEM(target->type, OB_MESH, OB_LATTICE)) { + defgrp_index = defgroup_name_index(target, vgroup); + + if (defgrp_index != -1) { + /* if there's derived data without deformverts, don't use vgroups */ + if (dm) { + dvert = dm->getVertDataArray(dm, CD_MDEFORMVERT); + } + else if (target->type == OB_LATTICE) { + dvert = ((Lattice *)target->data)->dvert; + } + else { + dvert = ((Mesh *)target->data)->dvert; + } } } - else { - use_vgroups = false; - } - - if (vgroup && vgroup[0] && use_vgroups) { - Mesh *me = target->data; - const int defgrp_index = defgroup_name_index(target, vgroup); - if (defgrp_index != -1 && (me->dvert || dm)) { - MDeformVert *dvert = me->dvert; - float vec[3]; - float weight; - + if (dvert) { + MDeformVert *dvert_iter; + float vec[3]; - if (cu->flag & CU_DEFORM_BOUNDS_OFF) { - dvert = me->dvert; - for (a = 0; a < numVerts; a++, dvert++) { - if (dm) dvert = dm->getVertData(dm, a, CD_MDEFORMVERT); - weight = defvert_find_weight(dvert, defgrp_index); - - if (weight > 0.0f) { - mul_m4_v3(cd.curvespace, vertexCos[a]); - copy_v3_v3(vec, vertexCos[a]); - calc_curve_deform(scene, cuOb, vec, defaxis, &cd, NULL); - interp_v3_v3v3(vertexCos[a], vertexCos[a], vec, weight); - mul_m4_v3(cd.objectspace, vertexCos[a]); - } + if (cu->flag & CU_DEFORM_BOUNDS_OFF) { + for (a = 0, dvert_iter = dvert; a < numVerts; a++, dvert_iter++) { + const float weight = defvert_find_weight(dvert_iter, defgrp_index); + + if (weight > 0.0f) { + mul_m4_v3(cd.curvespace, vertexCos[a]); + copy_v3_v3(vec, vertexCos[a]); + calc_curve_deform(scene, cuOb, vec, defaxis, &cd, NULL); + interp_v3_v3v3(vertexCos[a], vertexCos[a], vec, weight); + mul_m4_v3(cd.objectspace, vertexCos[a]); } } - else { - /* set mesh min/max bounds */ - INIT_MINMAX(cd.dmin, cd.dmax); - - for (a = 0; a < numVerts; a++, dvert++) { - if (dm) dvert = dm->getVertData(dm, a, CD_MDEFORMVERT); - - if (defvert_find_weight(dvert, defgrp_index) > 0.0f) { - mul_m4_v3(cd.curvespace, vertexCos[a]); - minmax_v3v3_v3(cd.dmin, cd.dmax, vertexCos[a]); - } + } + else { + /* set mesh min/max bounds */ + INIT_MINMAX(cd.dmin, cd.dmax); + + for (a = 0, dvert_iter = dvert; a < numVerts; a++, dvert_iter++) { + if (defvert_find_weight(dvert_iter, defgrp_index) > 0.0f) { + mul_m4_v3(cd.curvespace, vertexCos[a]); + minmax_v3v3_v3(cd.dmin, cd.dmax, vertexCos[a]); } - - dvert = me->dvert; - for (a = 0; a < numVerts; a++, dvert++) { - if (dm) dvert = dm->getVertData(dm, a, CD_MDEFORMVERT); - - weight = defvert_find_weight(dvert, defgrp_index); - - if (weight > 0.0f) { - /* already in 'cd.curvespace', prev for loop */ - copy_v3_v3(vec, vertexCos[a]); - calc_curve_deform(scene, cuOb, vec, defaxis, &cd, NULL); - interp_v3_v3v3(vertexCos[a], vertexCos[a], vec, weight); - mul_m4_v3(cd.objectspace, vertexCos[a]); - } + } + + for (a = 0, dvert_iter = dvert; a < numVerts; a++, dvert_iter++) { + const float weight = defvert_find_weight(dvert_iter, defgrp_index); + + if (weight > 0.0f) { + /* already in 'cd.curvespace', prev for loop */ + copy_v3_v3(vec, vertexCos[a]); + calc_curve_deform(scene, cuOb, vec, defaxis, &cd, NULL); + interp_v3_v3v3(vertexCos[a], vertexCos[a], vec, weight); + mul_m4_v3(cd.objectspace, vertexCos[a]); } } } @@ -1166,6 +1155,28 @@ void BKE_lattice_center_bounds(Lattice *lt, float cent[3]) mid_v3_v3v3(cent, min, max); } +void BKE_lattice_transform(Lattice *lt, float mat[4][4], bool do_keys) +{ + BPoint *bp = lt->def; + int i = lt->pntsu * lt->pntsv * lt->pntsw; + + while (i--) { + mul_m4_v3(mat, bp->vec); + bp++; + } + + if (do_keys && lt->key) { + KeyBlock *kb; + + for (kb = lt->key->block.first; kb; kb = kb->next) { + float *fp = kb->data; + for (i = kb->totelem; i--; fp += 3) { + mul_m4_v3(mat, fp); + } + } + } +} + void BKE_lattice_translate(Lattice *lt, float offset[3], bool do_keys) { int i, numVerts; diff --git a/source/blender/blenkernel/intern/library.c b/source/blender/blenkernel/intern/library.c index 1f3327b0dc4..515287de336 100644 --- a/source/blender/blenkernel/intern/library.c +++ b/source/blender/blenkernel/intern/library.c @@ -104,6 +104,7 @@ #include "BKE_mask.h" #include "BKE_node.h" #include "BKE_object.h" +#include "BKE_paint.h" #include "BKE_particle.h" #include "BKE_packedFile.h" #include "BKE_speaker.h" @@ -382,7 +383,7 @@ bool id_copy(ID *id, ID **newid, bool test) if (!test) *newid = (ID *)BKE_mask_copy((Mask *)id); return true; case ID_LS: - if (!test) *newid = (ID *)BKE_copy_linestyle((FreestyleLineStyle *)id); + if (!test) *newid = (ID *)BKE_linestyle_copy((FreestyleLineStyle *)id); return true; } @@ -515,6 +516,10 @@ ListBase *which_libbase(Main *mainlib, short type) return &(mainlib->mask); case ID_LS: return &(mainlib->linestyle); + case ID_PAL: + return &(mainlib->palettes); + case ID_PC: + return &(mainlib->paintcurves); } return NULL; } @@ -596,6 +601,8 @@ int set_listbasepointers(Main *main, ListBase **lb) lb[a++] = &(main->text); lb[a++] = &(main->sound); lb[a++] = &(main->group); + lb[a++] = &(main->palettes); + lb[a++] = &(main->paintcurves); lb[a++] = &(main->brush); lb[a++] = &(main->script); lb[a++] = &(main->particle); @@ -731,6 +738,12 @@ static ID *alloc_libblock_notest(short type) case ID_LS: id = MEM_callocN(sizeof(FreestyleLineStyle), "Freestyle Line Style"); break; + case ID_PAL: + id = MEM_callocN(sizeof(Palette), "Palette"); + break; + case ID_PC: + id = MEM_callocN(sizeof(PaintCurve), "Paint Curve"); + break; } return id; } @@ -1005,7 +1018,13 @@ void BKE_libblock_free_ex(Main *bmain, void *idv, bool do_id_user) BKE_mask_free(bmain, (Mask *)id); break; case ID_LS: - BKE_free_linestyle((FreestyleLineStyle *)id); + BKE_linestyle_free((FreestyleLineStyle *)id); + break; + case ID_PAL: + BKE_palette_free((Palette *)id); + break; + case ID_PC: + BKE_paint_curve_free((PaintCurve *)id); break; } @@ -1131,14 +1150,17 @@ void BKE_main_unlock(struct Main *bmain) } /* ***************** ID ************************ */ - - -ID *BKE_libblock_find_name(const short type, const char *name) /* type: "OB" or "MA" etc */ +ID *BKE_libblock_find_name_ex(struct Main *bmain, const short type, const char *name) { - ListBase *lb = which_libbase(G.main, type); + ListBase *lb = which_libbase(bmain, type); BLI_assert(lb != NULL); return BLI_findstring(lb, name, offsetof(ID, name) + 2); } +ID *BKE_libblock_find_name(const short type, const char *name) +{ + return BKE_libblock_find_name_ex(G.main, type, name); +} + void id_sort_by_name(ListBase *lb, ID *id) { diff --git a/source/blender/blenkernel/intern/linestyle.c b/source/blender/blenkernel/intern/linestyle.c index d92fa328e87..45695844101 100644 --- a/source/blender/blenkernel/intern/linestyle.c +++ b/source/blender/blenkernel/intern/linestyle.c @@ -43,6 +43,8 @@ #include "BLI_math.h" #include "BLI_utildefines.h" +#include "BKE_context.h" +#include "BKE_freestyle.h" #include "BKE_global.h" #include "BKE_library.h" #include "BKE_linestyle.h" @@ -51,6 +53,8 @@ #include "BKE_colortools.h" #include "BKE_animsys.h" +#include "RNA_access.h" + static const char *modifier_name[LS_MODIFIER_NUM] = { NULL, "Along Stroke", @@ -99,12 +103,12 @@ static void default_linestyle_settings(FreestyleLineStyle *linestyle) BLI_listbase_clear(&linestyle->thickness_modifiers); BLI_listbase_clear(&linestyle->geometry_modifiers); - BKE_add_linestyle_geometry_modifier(linestyle, NULL, LS_MODIFIER_SAMPLING); + BKE_linestyle_geometry_modifier_add(linestyle, NULL, LS_MODIFIER_SAMPLING); linestyle->caps = LS_CAPS_BUTT; } -FreestyleLineStyle *BKE_new_linestyle(const char *name, struct Main *main) +FreestyleLineStyle *BKE_linestyle_new(const char *name, struct Main *main) { FreestyleLineStyle *linestyle; @@ -118,7 +122,7 @@ FreestyleLineStyle *BKE_new_linestyle(const char *name, struct Main *main) return linestyle; } -void BKE_free_linestyle(FreestyleLineStyle *linestyle) +void BKE_linestyle_free(FreestyleLineStyle *linestyle) { LineStyleModifier *m; @@ -137,33 +141,33 @@ void BKE_free_linestyle(FreestyleLineStyle *linestyle) BKE_free_animdata(&linestyle->id); while ((m = (LineStyleModifier *)linestyle->color_modifiers.first)) - BKE_remove_linestyle_color_modifier(linestyle, m); + BKE_linestyle_color_modifier_remove(linestyle, m); while ((m = (LineStyleModifier *)linestyle->alpha_modifiers.first)) - BKE_remove_linestyle_alpha_modifier(linestyle, m); + BKE_linestyle_alpha_modifier_remove(linestyle, m); while ((m = (LineStyleModifier *)linestyle->thickness_modifiers.first)) - BKE_remove_linestyle_thickness_modifier(linestyle, m); + BKE_linestyle_thickness_modifier_remove(linestyle, m); while ((m = (LineStyleModifier *)linestyle->geometry_modifiers.first)) - BKE_remove_linestyle_geometry_modifier(linestyle, m); + BKE_linestyle_geometry_modifier_remove(linestyle, m); } -FreestyleLineStyle *BKE_copy_linestyle(FreestyleLineStyle *linestyle) +FreestyleLineStyle *BKE_linestyle_copy(FreestyleLineStyle *linestyle) { FreestyleLineStyle *new_linestyle; LineStyleModifier *m; int a; - new_linestyle = BKE_new_linestyle(linestyle->id.name + 2, NULL); - BKE_free_linestyle(new_linestyle); + new_linestyle = BKE_linestyle_new(linestyle->id.name + 2, NULL); + BKE_linestyle_free(new_linestyle); for (a = 0; a < MAX_MTEX; a++) { if (linestyle->mtex[a]) { - new_linestyle->mtex[a] = MEM_mallocN(sizeof(MTex), "BKE_copy_linestyle"); + new_linestyle->mtex[a] = MEM_mallocN(sizeof(MTex), "BKE_linestyle_copy"); memcpy(new_linestyle->mtex[a], linestyle->mtex[a], sizeof(MTex)); id_us_plus((ID *)new_linestyle->mtex[a]->tex); } } if (linestyle->nodetree) { - linestyle->nodetree = ntreeCopyTree(linestyle->nodetree); + new_linestyle->nodetree = ntreeCopyTree(linestyle->nodetree); } new_linestyle->r = linestyle->r; @@ -198,17 +202,29 @@ FreestyleLineStyle *BKE_copy_linestyle(FreestyleLineStyle *linestyle) new_linestyle->texstep = linestyle->texstep; new_linestyle->pr_texture = linestyle->pr_texture; for (m = (LineStyleModifier *)linestyle->color_modifiers.first; m; m = m->next) - BKE_copy_linestyle_color_modifier(new_linestyle, m); + BKE_linestyle_color_modifier_copy(new_linestyle, m); for (m = (LineStyleModifier *)linestyle->alpha_modifiers.first; m; m = m->next) - BKE_copy_linestyle_alpha_modifier(new_linestyle, m); + BKE_linestyle_alpha_modifier_copy(new_linestyle, m); for (m = (LineStyleModifier *)linestyle->thickness_modifiers.first; m; m = m->next) - BKE_copy_linestyle_thickness_modifier(new_linestyle, m); + BKE_linestyle_thickness_modifier_copy(new_linestyle, m); for (m = (LineStyleModifier *)linestyle->geometry_modifiers.first; m; m = m->next) - BKE_copy_linestyle_geometry_modifier(new_linestyle, m); + BKE_linestyle_geometry_modifier_copy(new_linestyle, m); return new_linestyle; } +FreestyleLineStyle *BKE_linestyle_active_from_scene(Scene *scene) +{ + SceneRenderLayer *actsrl = BLI_findlink(&scene->r.layers, scene->r.actlay); + FreestyleConfig *config = &actsrl->freestyleConfig; + FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(config); + + if (lineset) { + return lineset->linestyle; + } + return NULL; +} + static LineStyleModifier *new_modifier(const char *name, int type, size_t size) { LineStyleModifier *m; @@ -255,7 +271,7 @@ static LineStyleModifier *alloc_color_modifier(const char *name, int type) return new_modifier(name, type, size); } -LineStyleModifier *BKE_add_linestyle_color_modifier(FreestyleLineStyle *linestyle, const char *name, int type) +LineStyleModifier *BKE_linestyle_color_modifier_add(FreestyleLineStyle *linestyle, const char *name, int type) { LineStyleModifier *m; @@ -289,7 +305,7 @@ LineStyleModifier *BKE_add_linestyle_color_modifier(FreestyleLineStyle *linestyl return m; } -LineStyleModifier *BKE_copy_linestyle_color_modifier(FreestyleLineStyle *linestyle, LineStyleModifier *m) +LineStyleModifier *BKE_linestyle_color_modifier_copy(FreestyleLineStyle *linestyle, LineStyleModifier *m) { LineStyleModifier *new_m; @@ -344,7 +360,7 @@ LineStyleModifier *BKE_copy_linestyle_color_modifier(FreestyleLineStyle *linesty return new_m; } -int BKE_remove_linestyle_color_modifier(FreestyleLineStyle *linestyle, LineStyleModifier *m) +int BKE_linestyle_color_modifier_remove(FreestyleLineStyle *linestyle, LineStyleModifier *m) { if (BLI_findindex(&linestyle->color_modifiers, m) == -1) return -1; @@ -389,7 +405,7 @@ static LineStyleModifier *alloc_alpha_modifier(const char *name, int type) return new_modifier(name, type, size); } -LineStyleModifier *BKE_add_linestyle_alpha_modifier(FreestyleLineStyle *linestyle, const char *name, int type) +LineStyleModifier *BKE_linestyle_alpha_modifier_add(FreestyleLineStyle *linestyle, const char *name, int type) { LineStyleModifier *m; @@ -435,7 +451,7 @@ LineStyleModifier *BKE_add_linestyle_alpha_modifier(FreestyleLineStyle *linestyl return m; } -LineStyleModifier *BKE_copy_linestyle_alpha_modifier(FreestyleLineStyle *linestyle, LineStyleModifier *m) +LineStyleModifier *BKE_linestyle_alpha_modifier_copy(FreestyleLineStyle *linestyle, LineStyleModifier *m) { LineStyleModifier *new_m; @@ -493,7 +509,7 @@ LineStyleModifier *BKE_copy_linestyle_alpha_modifier(FreestyleLineStyle *linesty return new_m; } -int BKE_remove_linestyle_alpha_modifier(FreestyleLineStyle *linestyle, LineStyleModifier *m) +int BKE_linestyle_alpha_modifier_remove(FreestyleLineStyle *linestyle, LineStyleModifier *m) { if (BLI_findindex(&linestyle->alpha_modifiers, m) == -1) return -1; @@ -542,7 +558,7 @@ static LineStyleModifier *alloc_thickness_modifier(const char *name, int type) return new_modifier(name, type, size); } -LineStyleModifier *BKE_add_linestyle_thickness_modifier(FreestyleLineStyle *linestyle, const char *name, int type) +LineStyleModifier *BKE_linestyle_thickness_modifier_add(FreestyleLineStyle *linestyle, const char *name, int type) { LineStyleModifier *m; @@ -604,7 +620,7 @@ LineStyleModifier *BKE_add_linestyle_thickness_modifier(FreestyleLineStyle *line return m; } -LineStyleModifier *BKE_copy_linestyle_thickness_modifier(FreestyleLineStyle *linestyle, LineStyleModifier *m) +LineStyleModifier *BKE_linestyle_thickness_modifier_copy(FreestyleLineStyle *linestyle, LineStyleModifier *m) { LineStyleModifier *new_m; @@ -681,7 +697,7 @@ LineStyleModifier *BKE_copy_linestyle_thickness_modifier(FreestyleLineStyle *lin return new_m; } -int BKE_remove_linestyle_thickness_modifier(FreestyleLineStyle *linestyle, LineStyleModifier *m) +int BKE_linestyle_thickness_modifier_remove(FreestyleLineStyle *linestyle, LineStyleModifier *m) { if (BLI_findindex(&linestyle->thickness_modifiers, m) == -1) return -1; @@ -756,7 +772,7 @@ static LineStyleModifier *alloc_geometry_modifier(const char *name, int type) return new_modifier(name, type, size); } -LineStyleModifier *BKE_add_linestyle_geometry_modifier(FreestyleLineStyle *linestyle, const char *name, int type) +LineStyleModifier *BKE_linestyle_geometry_modifier_add(FreestyleLineStyle *linestyle, const char *name, int type) { LineStyleModifier *m; @@ -874,7 +890,7 @@ LineStyleModifier *BKE_add_linestyle_geometry_modifier(FreestyleLineStyle *lines return m; } -LineStyleModifier *BKE_copy_linestyle_geometry_modifier(FreestyleLineStyle *linestyle, LineStyleModifier *m) +LineStyleModifier *BKE_linestyle_geometry_modifier_copy(FreestyleLineStyle *linestyle, LineStyleModifier *m) { LineStyleModifier *new_m; @@ -1008,7 +1024,7 @@ LineStyleModifier *BKE_copy_linestyle_geometry_modifier(FreestyleLineStyle *line return new_m; } -int BKE_remove_linestyle_geometry_modifier(FreestyleLineStyle *linestyle, LineStyleModifier *m) +int BKE_linestyle_geometry_modifier_remove(FreestyleLineStyle *linestyle, LineStyleModifier *m) { if (BLI_findindex(&linestyle->geometry_modifiers, m) == -1) return -1; @@ -1025,27 +1041,27 @@ static void move_modifier(ListBase *lb, LineStyleModifier *modifier, int directi BLI_insertlinkafter(lb, modifier->next, modifier); } -void BKE_move_linestyle_color_modifier(FreestyleLineStyle *linestyle, LineStyleModifier *modifier, int direction) +void BKE_linestyle_color_modifier_move(FreestyleLineStyle *linestyle, LineStyleModifier *modifier, int direction) { move_modifier(&linestyle->color_modifiers, modifier, direction); } -void BKE_move_linestyle_alpha_modifier(FreestyleLineStyle *linestyle, LineStyleModifier *modifier, int direction) +void BKE_linestyle_alpha_modifier_move(FreestyleLineStyle *linestyle, LineStyleModifier *modifier, int direction) { move_modifier(&linestyle->alpha_modifiers, modifier, direction); } -void BKE_move_linestyle_thickness_modifier(FreestyleLineStyle *linestyle, LineStyleModifier *modifier, int direction) +void BKE_linestyle_thickness_modifier_move(FreestyleLineStyle *linestyle, LineStyleModifier *modifier, int direction) { move_modifier(&linestyle->thickness_modifiers, modifier, direction); } -void BKE_move_linestyle_geometry_modifier(FreestyleLineStyle *linestyle, LineStyleModifier *modifier, int direction) +void BKE_linestyle_geometry_modifier_move(FreestyleLineStyle *linestyle, LineStyleModifier *modifier, int direction) { move_modifier(&linestyle->geometry_modifiers, modifier, direction); } -void BKE_list_modifier_color_ramps(FreestyleLineStyle *linestyle, ListBase *listbase) +void BKE_linestyle_modifier_list_color_ramps(FreestyleLineStyle *linestyle, ListBase *listbase) { LineStyleModifier *m; ColorBand *color_ramp; @@ -1076,7 +1092,7 @@ void BKE_list_modifier_color_ramps(FreestyleLineStyle *linestyle, ListBase *list } } -char *BKE_path_from_ID_to_color_ramp(FreestyleLineStyle *linestyle, ColorBand *color_ramp) +char *BKE_linestyle_path_to_color_ramp(FreestyleLineStyle *linestyle, ColorBand *color_ramp) { LineStyleModifier *m; bool found = false; @@ -1107,11 +1123,11 @@ char *BKE_path_from_ID_to_color_ramp(FreestyleLineStyle *linestyle, ColorBand *c return BLI_sprintfN("color_modifiers[\"%s\"].color_ramp", name_esc); } } - printf("BKE_path_from_ID_to_color_ramp: No color ramps correspond to the given pointer.\n"); + printf("BKE_linestyle_path_to_color_ramp: No color ramps correspond to the given pointer.\n"); return NULL; } -void BKE_unlink_linestyle_target_object(FreestyleLineStyle *linestyle, struct Object *ob) +void BKE_linestyle_target_object_unlink(FreestyleLineStyle *linestyle, struct Object *ob) { LineStyleModifier *m; @@ -1137,3 +1153,64 @@ void BKE_unlink_linestyle_target_object(FreestyleLineStyle *linestyle, struct Ob } } } + +bool BKE_linestyle_use_textures(FreestyleLineStyle *linestyle, const bool use_shading_nodes) +{ + if (use_shading_nodes) { + if (linestyle && linestyle->use_nodes && linestyle->nodetree) { + bNode *node; + + for (node = linestyle->nodetree->nodes.first; node; node = node->next) { + if (node->typeinfo->nclass == NODE_CLASS_TEXTURE) { + return true; + } + } + } + } + else { + if (linestyle && (linestyle->flag & LS_TEXTURE)) { + return (linestyle->mtex[0] != NULL); + } + } + return false; +} + +void BKE_linestyle_default_shader(const bContext *C, FreestyleLineStyle *linestyle) +{ + bNode *uv_along_stroke, *input_texure, *output_linestyle; + bNodeSocket *fromsock, *tosock; + bNodeTree *ntree; + + BLI_assert(linestyle->nodetree == NULL); + + ntree = ntreeAddTree(NULL, "stroke_shader", "ShaderNodeTree"); + + linestyle->nodetree = ntree; + + uv_along_stroke = nodeAddStaticNode(C, ntree, SH_NODE_UVALONGSTROKE); + uv_along_stroke->locx = 0.0f; + uv_along_stroke->locy = 300.0f; + uv_along_stroke->custom1 = 0; // use_tips + + input_texure = nodeAddStaticNode(C, ntree, SH_NODE_TEX_IMAGE); + input_texure->locx = 200.0f; + input_texure->locy = 300.0f; + + output_linestyle = nodeAddStaticNode(C, ntree, SH_NODE_OUTPUT_LINESTYLE); + output_linestyle->locx = 400.0f; + output_linestyle->locy = 300.0f; + output_linestyle->custom1 = MA_RAMP_BLEND; + output_linestyle->custom2 = 0; // use_clamp + + nodeSetActive(ntree, input_texure); + + fromsock = BLI_findlink(&uv_along_stroke->outputs, 0); // UV + tosock = BLI_findlink(&input_texure->inputs, 0); // UV + nodeAddLink(ntree, uv_along_stroke, fromsock, input_texure, tosock); + + fromsock = BLI_findlink(&input_texure->outputs, 0); // Color + tosock = BLI_findlink(&output_linestyle->inputs, 0); // Color + nodeAddLink(ntree, input_texure, fromsock, output_linestyle, tosock); + + ntreeUpdateTree(CTX_data_main(C), ntree); +} diff --git a/source/blender/blenkernel/intern/mask.c b/source/blender/blenkernel/intern/mask.c index 4147750c356..1c40446c217 100644 --- a/source/blender/blenkernel/intern/mask.c +++ b/source/blender/blenkernel/intern/mask.c @@ -1212,7 +1212,7 @@ void BKE_mask_point_parent_matrix_get(MaskSplinePoint *point, float ctime, float } invert_m3_m3(mask_to_clip_matrix, mask_from_clip_matrix); - mul_serie_m3(parent_matrix, mask_to_clip_matrix, H, mask_from_clip_matrix, NULL, NULL, NULL, NULL, NULL); + mul_m3_series(parent_matrix, mask_from_clip_matrix, H, mask_to_clip_matrix); } } } diff --git a/source/blender/blenkernel/intern/mask_rasterize.c b/source/blender/blenkernel/intern/mask_rasterize.c index 35207595103..4dc8ed21463 100644 --- a/source/blender/blenkernel/intern/mask_rasterize.c +++ b/source/blender/blenkernel/intern/mask_rasterize.c @@ -326,7 +326,7 @@ static void maskrasterize_spline_differentiate_point_outset(float (*diff_feather * are to any of the triangle edges. */ static bool layer_bucket_isect_test( - MaskRasterLayer *layer, unsigned int face_index, + const MaskRasterLayer *layer, unsigned int face_index, const unsigned int bucket_x, const unsigned int bucket_y, const float bucket_size_x, const float bucket_size_y, const float bucket_max_rad_squared) diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c index 971db1997de..eeca60f7ef4 100644 --- a/source/blender/blenkernel/intern/material.c +++ b/source/blender/blenkernel/intern/material.c @@ -63,6 +63,7 @@ #include "BKE_main.h" #include "BKE_material.h" #include "BKE_mesh.h" +#include "BKE_scene.h" #include "BKE_node.h" #include "BKE_curve.h" @@ -111,6 +112,9 @@ void BKE_material_free_ex(Material *ma, bool do_id_user) MEM_freeN(ma->nodetree); } + if (ma->texpaintslot) + MEM_freeN(ma->texpaintslot); + if (ma->gpumaterial.first) GPU_material_free(ma); } @@ -269,7 +273,8 @@ Material *localize_material(Material *ma) if (ma->ramp_col) man->ramp_col = MEM_dupallocN(ma->ramp_col); if (ma->ramp_spec) man->ramp_spec = MEM_dupallocN(ma->ramp_spec); - + + man->texpaintslot = NULL; man->preview = NULL; if (ma->nodetree) @@ -467,7 +472,7 @@ Material ***give_matarar(Object *ob) me = ob->data; return &(me->mat); } - else if (ELEM3(ob->type, OB_CURVE, OB_FONT, OB_SURF)) { + else if (ELEM(ob->type, OB_CURVE, OB_FONT, OB_SURF)) { cu = ob->data; return &(cu->mat); } @@ -488,7 +493,7 @@ short *give_totcolp(Object *ob) me = ob->data; return &(me->totcol); } - else if (ELEM3(ob->type, OB_CURVE, OB_FONT, OB_SURF)) { + else if (ELEM(ob->type, OB_CURVE, OB_FONT, OB_SURF)) { cu = ob->data; return &(cu->totcol); } @@ -1291,7 +1296,7 @@ bool object_remove_material_slot(Object *ob) } /* check indices from mesh */ - if (ELEM4(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT)) { + if (ELEM(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT)) { material_data_index_remove_id((ID *)ob->data, actcol - 1); if (ob->curve_cache) { BKE_displist_free(&ob->curve_cache->disp); @@ -1301,6 +1306,124 @@ bool object_remove_material_slot(Object *ob) return true; } +static bool get_mtex_slot_valid_texpaint(struct MTex *mtex) +{ + return (mtex && (mtex->texco == TEXCO_UV) && + mtex->tex && (mtex->tex->type == TEX_IMAGE) && + mtex->tex->ima); +} + +void BKE_texpaint_slot_refresh_cache(Scene *scene, Material *ma) +{ + MTex **mtex; + short count = 0; + short index = 0, i; + + bool use_nodes = BKE_scene_use_new_shading_nodes(scene); + bool is_bi = BKE_scene_uses_blender_internal(scene); + + if (!ma) + return; + + if (ma->texpaintslot) { + MEM_freeN(ma->texpaintslot); + ma->tot_slots = 0; + ma->texpaintslot = NULL; + } + + if (scene->toolsettings->imapaint.mode == IMAGEPAINT_MODE_IMAGE) { + ma->paint_active_slot = 0; + ma->paint_clone_slot = 0; + return; + } + + if (use_nodes || ma->use_nodes) { + bNode *node, *active_node; + + if (!(ma->nodetree)) { + ma->paint_active_slot = 0; + ma->paint_clone_slot = 0; + return; + } + + for (node = ma->nodetree->nodes.first; node; node = node->next) { + if (node->typeinfo->nclass == NODE_CLASS_TEXTURE && node->typeinfo->type == SH_NODE_TEX_IMAGE && node->id) + count++; + } + + if (count == 0) { + ma->paint_active_slot = 0; + ma->paint_clone_slot = 0; + return; + } + ma->texpaintslot = MEM_callocN(sizeof(*ma->texpaintslot) * count, "texpaint_slots"); + + active_node = nodeGetActiveTexture(ma->nodetree); + + for (node = ma->nodetree->nodes.first; node; node = node->next) { + if (node->typeinfo->nclass == NODE_CLASS_TEXTURE && node->typeinfo->type == SH_NODE_TEX_IMAGE && node->id) { + if (active_node == node) + ma->paint_active_slot = index; + ma->texpaintslot[index++].ima = (Image *)node->id; + } + } + } + else if (is_bi) { + for (mtex = ma->mtex, i = 0; i < MAX_MTEX; i++, mtex++) { + if (get_mtex_slot_valid_texpaint(*mtex)) { + count++; + } + } + + if (count == 0) { + ma->paint_active_slot = 0; + ma->paint_clone_slot = 0; + return; + } + + ma->texpaintslot = MEM_callocN(sizeof(*ma->texpaintslot) * count, "texpaint_slots"); + + for (mtex = ma->mtex, i = 0; i < MAX_MTEX; i++, mtex++) { + if (get_mtex_slot_valid_texpaint(*mtex)) { + ma->texpaintslot[index].ima = (*mtex)->tex->ima; + ma->texpaintslot[index].uvname = (*mtex)->uvname; + ma->texpaintslot[index].index = i; + + index++; + } + } + } + else { + ma->paint_active_slot = 0; + ma->paint_clone_slot = 0; + return; + } + + + ma->tot_slots = count; + + + if (ma->paint_active_slot >= count) { + ma->paint_active_slot = count - 1; + } + + if (ma->paint_clone_slot >= count) { + ma->paint_clone_slot = count - 1; + } + + return; +} + +void BKE_texpaint_slots_refresh_object(Scene *scene, struct Object *ob) +{ + int i; + + for (i = 1; i < ob->totcol + 1; i++) { + Material *ma = give_current_material(ob, i); + BKE_texpaint_slot_refresh_cache(scene, ma); + } +} + /* r_col = current value, col = new value, (fac == 0) is no change */ void ramp_blend(int type, float r_col[3], const float fac, const float col[3]) @@ -1573,7 +1696,7 @@ void copy_matcopybuf(Material *ma) matcopybuf.mtex[a] = MEM_dupallocN(mtex); } } - matcopybuf.nodetree = ntreeCopyTree_ex(ma->nodetree, false); + matcopybuf.nodetree = ntreeCopyTree_ex(ma->nodetree, G.main, false); matcopybuf.preview = NULL; BLI_listbase_clear(&matcopybuf.gpumaterial); matcopied = 1; @@ -1626,7 +1749,7 @@ void paste_matcopybuf(Material *ma) } } - ma->nodetree = ntreeCopyTree_ex(matcopybuf.nodetree, false); + ma->nodetree = ntreeCopyTree_ex(matcopybuf.nodetree, G.main, false); } diff --git a/source/blender/blenkernel/intern/mball.c b/source/blender/blenkernel/intern/mball.c index 43b19f0c869..453c6df6e3b 100644 --- a/source/blender/blenkernel/intern/mball.c +++ b/source/blender/blenkernel/intern/mball.c @@ -491,10 +491,7 @@ void BKE_mball_properties_copy(Scene *scene, Object *active_object) BLI_split_name_num(basisname, &basisnr, active_object->id.name + 2, '.'); - /* XXX recursion check, see scene.c, just too simple code this BKE_scene_base_iter_next() */ - if (F_ERROR == BKE_scene_base_iter_next(eval_ctx, &iter, &sce_iter, 0, NULL, NULL)) - return; - + BKE_scene_base_iter_next(eval_ctx, &iter, &sce_iter, 0, NULL, NULL); while (BKE_scene_base_iter_next(eval_ctx, &iter, &sce_iter, 1, &base, &ob)) { if (ob->type == OB_MBALL) { if (ob != active_object) { @@ -537,23 +534,17 @@ Object *BKE_mball_basis_find(Scene *scene, Object *basis) BLI_split_name_num(basisname, &basisnr, basis->id.name + 2, '.'); - /* XXX recursion check, see scene.c, just too simple code this BKE_scene_base_iter_next() */ - if (F_ERROR == BKE_scene_base_iter_next(eval_ctx, &iter, &sce_iter, 0, NULL, NULL)) - return NULL; - + BKE_scene_base_iter_next(eval_ctx, &iter, &sce_iter, 0, NULL, NULL); while (BKE_scene_base_iter_next(eval_ctx, &iter, &sce_iter, 1, &base, &ob)) { - if (ob->type == OB_MBALL) { + if ((ob->type == OB_MBALL) && !(base->flag & OB_FROMDUPLI)) { if (ob != bob) { BLI_split_name_num(obname, &obnr, ob->id.name + 2, '.'); - /* object ob has to be in same "group" ... it means, that it has to have - * same base of its name */ + /* object ob has to be in same "group" ... it means, that it has to have same base of its name */ if (strcmp(obname, basisname) == 0) { if (obnr < basisnr) { - if (!(ob->flag & OB_FROMDUPLI)) { - basis = ob; - basisnr = obnr; - } + basis = ob; + basisnr = obnr; } } } @@ -2227,10 +2218,7 @@ static void mball_count(EvaluationContext *eval_ctx, PROCESS *process, Scene *sc BLI_split_name_num(basisname, &basisnr, basis->id.name + 2, '.'); process->totelem = 0; - /* XXX recursion check, see scene.c, just too simple code this BKE_scene_base_iter_next() */ - if (F_ERROR == BKE_scene_base_iter_next(eval_ctx, &iter, &sce_iter, 0, NULL, NULL)) - return; - + BKE_scene_base_iter_next(eval_ctx, &iter, &sce_iter, 0, NULL, NULL); while (BKE_scene_base_iter_next(eval_ctx, &iter, &sce_iter, 1, &base, &ob)) { if (ob->type == OB_MBALL) { if (ob == bob) { @@ -2454,6 +2442,30 @@ bool BKE_mball_center_bounds(MetaBall *mb, float r_cent[3]) return 0; } +void BKE_mball_transform(MetaBall *mb, float mat[4][4]) +{ + MetaElem *me; + float quat[4]; + const float scale = mat4_to_scale(mat); + const float scale_sqrt = sqrtf(scale); + + mat4_to_quat(quat, mat); + + for (me = mb->elems.first; me; me = me->next) { + mul_m4_v3(mat, &me->x); + mul_qt_qtqt(me->quat, quat, me->quat); + me->rad *= scale; + /* hrmf, probably elems shouldn't be + * treating scale differently - campbell */ + if (!MB_TYPE_SIZE_SQUARED(me->type)) { + mul_v3_fl(&me->expx, scale); + } + else { + mul_v3_fl(&me->expx, scale_sqrt); + } + } +} + void BKE_mball_translate(MetaBall *mb, const float offset[3]) { MetaElem *ml; diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c index 2bf33b97a70..2e80379522c 100644 --- a/source/blender/blenkernel/intern/mesh.c +++ b/source/blender/blenkernel/intern/mesh.c @@ -115,16 +115,16 @@ static int customdata_compare(CustomData *c1, CustomData *c2, Mesh *m1, Mesh *m2 int i, i1 = 0, i2 = 0, tot, j; for (i = 0; i < c1->totlayer; i++) { - if (ELEM7(c1->layers[i].type, CD_MVERT, CD_MEDGE, CD_MPOLY, - CD_MLOOPUV, CD_MLOOPCOL, CD_MTEXPOLY, CD_MDEFORMVERT)) + if (ELEM(c1->layers[i].type, CD_MVERT, CD_MEDGE, CD_MPOLY, + CD_MLOOPUV, CD_MLOOPCOL, CD_MTEXPOLY, CD_MDEFORMVERT)) { i1++; } } for (i = 0; i < c2->totlayer; i++) { - if (ELEM7(c2->layers[i].type, CD_MVERT, CD_MEDGE, CD_MPOLY, - CD_MLOOPUV, CD_MLOOPCOL, CD_MTEXPOLY, CD_MDEFORMVERT)) + if (ELEM(c2->layers[i].type, CD_MVERT, CD_MEDGE, CD_MPOLY, + CD_MLOOPUV, CD_MLOOPCOL, CD_MTEXPOLY, CD_MDEFORMVERT)) { i2++; } @@ -135,16 +135,16 @@ static int customdata_compare(CustomData *c1, CustomData *c2, Mesh *m1, Mesh *m2 l1 = c1->layers; l2 = c2->layers; tot = i1; - i1 = 0; i2 = 0; + i1 = 0; i2 = 0; for (i = 0; i < tot; i++) { - while (i1 < c1->totlayer && !ELEM7(l1->type, CD_MVERT, CD_MEDGE, CD_MPOLY, - CD_MLOOPUV, CD_MLOOPCOL, CD_MTEXPOLY, CD_MDEFORMVERT)) + while (i1 < c1->totlayer && !ELEM(l1->type, CD_MVERT, CD_MEDGE, CD_MPOLY, + CD_MLOOPUV, CD_MLOOPCOL, CD_MTEXPOLY, CD_MDEFORMVERT)) { i1++, l1++; } - while (i2 < c2->totlayer && !ELEM7(l2->type, CD_MVERT, CD_MEDGE, CD_MPOLY, - CD_MLOOPUV, CD_MLOOPCOL, CD_MTEXPOLY, CD_MDEFORMVERT)) + while (i2 < c2->totlayer && !ELEM(l2->type, CD_MVERT, CD_MEDGE, CD_MPOLY, + CD_MLOOPUV, CD_MLOOPCOL, CD_MTEXPOLY, CD_MDEFORMVERT)) { i2++, l2++; } @@ -1869,6 +1869,27 @@ bool BKE_mesh_minmax(Mesh *me, float r_min[3], float r_max[3]) return (me->totvert != 0); } +void BKE_mesh_transform(Mesh *me, float mat[4][4], bool do_keys) +{ + int i; + MVert *mvert = me->mvert; + + for (i = 0; i < me->totvert; i++, mvert++) + mul_m4_v3(mat, mvert->co); + + if (do_keys && me->key) { + KeyBlock *kb; + for (kb = me->key->block.first; kb; kb = kb->next) { + float *fp = kb->data; + for (i = kb->totelem; i--; fp += 3) { + mul_m4_v3(mat, fp); + } + } + } + + /* don't update normals, caller can do this explicitly */ +} + void BKE_mesh_translate(Mesh *me, const float offset[3], const bool do_keys) { int i = me->totvert; @@ -2041,7 +2062,7 @@ int BKE_mesh_mselect_find(Mesh *me, int index, int type) { int i; - BLI_assert(ELEM3(type, ME_VSEL, ME_ESEL, ME_FSEL)); + BLI_assert(ELEM(type, ME_VSEL, ME_ESEL, ME_FSEL)); for (i = 0; i < me->totselect; i++) { if ((me->mselect[i].index == index) && @@ -2059,7 +2080,7 @@ int BKE_mesh_mselect_find(Mesh *me, int index, int type) */ int BKE_mesh_mselect_active_get(Mesh *me, int type) { - BLI_assert(ELEM3(type, ME_VSEL, ME_ESEL, ME_FSEL)); + BLI_assert(ELEM(type, ME_VSEL, ME_ESEL, ME_FSEL)); if (me->totselect) { if (me->mselect[me->totselect - 1].type == type) { diff --git a/source/blender/blenkernel/intern/mesh_evaluate.c b/source/blender/blenkernel/intern/mesh_evaluate.c index cb0386b1203..4c9e44682c3 100644 --- a/source/blender/blenkernel/intern/mesh_evaluate.c +++ b/source/blender/blenkernel/intern/mesh_evaluate.c @@ -567,6 +567,10 @@ void BKE_mesh_normals_loop_split(MVert *mverts, const int UNUSED(numVerts), MEdg copy_v3_v3(nor, lnor); } } + else { + /* We still have to clear the stack! */ + while (BLI_SMALLSTACK_POP(normal)); + } } ml_prev = ml_curr; @@ -574,8 +578,6 @@ void BKE_mesh_normals_loop_split(MVert *mverts, const int UNUSED(numVerts), MEdg } } - BLI_SMALLSTACK_FREE(normal); - MEM_freeN(edge_to_loops); MEM_freeN(loop_to_poly); @@ -729,7 +731,7 @@ void BKE_mesh_loop_tangents(Mesh *mesh, const char *uvmap, float (*r_looptangent } BKE_mesh_loop_tangents_ex(mesh->mvert, mesh->totvert, mesh->mloop, r_looptangents, - loopnors, loopuvs, mesh->totloop, mesh->mpoly, mesh->totpoly, reports); + loopnors, loopuvs, mesh->totloop, mesh->mpoly, mesh->totpoly, reports); } /** \} */ @@ -1096,6 +1098,125 @@ bool BKE_mesh_center_centroid(Mesh *me, float cent[3]) /* -------------------------------------------------------------------- */ +/** \name Mesh Volume Calculation + * \{ */ + +static bool mesh_calc_center_centroid_ex(MVert *mverts, int UNUSED(numVerts), + MFace *mfaces, int numFaces, + float center[3]) +{ + float totweight; + int f; + + zero_v3(center); + + if (numFaces == 0) + return false; + + totweight = 0.0f; + for (f = 0; f < numFaces; ++f) { + MFace *face = &mfaces[f]; + MVert *v1 = &mverts[face->v1]; + MVert *v2 = &mverts[face->v2]; + MVert *v3 = &mverts[face->v3]; + MVert *v4 = &mverts[face->v4]; + float area; + + area = area_tri_v3(v1->co, v2->co, v3->co); + madd_v3_v3fl(center, v1->co, area); + madd_v3_v3fl(center, v2->co, area); + madd_v3_v3fl(center, v3->co, area); + totweight += area; + + if (face->v4) { + area = area_tri_v3(v3->co, v4->co, v1->co); + madd_v3_v3fl(center, v3->co, area); + madd_v3_v3fl(center, v4->co, area); + madd_v3_v3fl(center, v1->co, area); + totweight += area; + } + } + if (totweight == 0.0f) + return false; + + mul_v3_fl(center, 1.0f / (3.0f * totweight)); + + return true; +} + +void BKE_mesh_calc_volume(MVert *mverts, int numVerts, + MFace *mfaces, int numFaces, + float *r_vol, float *r_com) +{ + float center[3]; + float totvol; + int f; + + if (r_vol) *r_vol = 0.0f; + if (r_com) zero_v3(r_com); + + if (numFaces == 0) + return; + + if (!mesh_calc_center_centroid_ex(mverts, numVerts, mfaces, numFaces, center)) + return; + + totvol = 0.0f; + for (f = 0; f < numFaces; ++f) { + MFace *face = &mfaces[f]; + MVert *v1 = &mverts[face->v1]; + MVert *v2 = &mverts[face->v2]; + MVert *v3 = &mverts[face->v3]; + MVert *v4 = &mverts[face->v4]; + float vol; + + vol = volume_tetrahedron_signed_v3(center, v1->co, v2->co, v3->co); + if (r_vol) { + totvol += vol; + } + if (r_com) { + /* averaging factor 1/4 is applied in the end */ + madd_v3_v3fl(r_com, center, vol); // XXX could extract this + madd_v3_v3fl(r_com, v1->co, vol); + madd_v3_v3fl(r_com, v2->co, vol); + madd_v3_v3fl(r_com, v3->co, vol); + } + + if (face->v4) { + vol = volume_tetrahedron_signed_v3(center, v3->co, v4->co, v1->co); + + if (r_vol) { + totvol += vol; + } + if (r_com) { + /* averaging factor 1/4 is applied in the end */ + madd_v3_v3fl(r_com, center, vol); // XXX could extract this + madd_v3_v3fl(r_com, v3->co, vol); + madd_v3_v3fl(r_com, v4->co, vol); + madd_v3_v3fl(r_com, v1->co, vol); + } + } + } + + /* Note: Depending on arbitrary centroid position, + * totvol can become negative even for a valid mesh. + * The true value is always the positive value. + */ + if (r_vol) { + *r_vol = fabsf(totvol); + } + if (r_com) { + /* Note: Factor 1/4 is applied once for all vertices here. + * This also automatically negates the vector if totvol is negative. + */ + if (totvol != 0.0f) + mul_v3_fl(r_com, 0.25f / totvol); + } +} + + +/* -------------------------------------------------------------------- */ + /** \name NGon Tessellation (NGon/Tessface Conversion) * \{ */ @@ -2110,11 +2231,10 @@ void BKE_mesh_calc_relative_deform( float tvec[3]; - barycentric_transform( - tvec, vert_cos_dst[v_curr], - vert_cos_org[v_prev], vert_cos_org[v_curr], vert_cos_org[v_next], - vert_cos_src[v_prev], vert_cos_src[v_curr], vert_cos_src[v_next] - ); + transform_point_by_tri_v3( + tvec, vert_cos_dst[v_curr], + vert_cos_org[v_prev], vert_cos_org[v_curr], vert_cos_org[v_next], + vert_cos_src[v_prev], vert_cos_src[v_curr], vert_cos_src[v_next]); add_v3_v3(vert_cos_new[v_curr], tvec); vert_accum[v_curr] += 1; diff --git a/source/blender/blenkernel/intern/mesh_mapping.c b/source/blender/blenkernel/intern/mesh_mapping.c index 65c576dd6a0..82065750791 100644 --- a/source/blender/blenkernel/intern/mesh_mapping.c +++ b/source/blender/blenkernel/intern/mesh_mapping.c @@ -442,7 +442,7 @@ int *BKE_mesh_calc_smoothgroups(const MEdge *medge, const int totedge, /* Find contiguous smooth groups already assigned, these are the values we can't reuse! */ for (; i--; p++) { int bit = poly_groups[*p]; - if (!ELEM3(bit, 0, poly_group_id, poly_group_id_overflowed) && + if (!ELEM(bit, 0, poly_group_id, poly_group_id_overflowed) && !(bit_poly_group_mask & bit)) { bit_poly_group_mask |= bit; diff --git a/source/blender/blenkernel/intern/mesh_validate.c b/source/blender/blenkernel/intern/mesh_validate.c index 858fe83b43f..f3a9e894eb3 100644 --- a/source/blender/blenkernel/intern/mesh_validate.c +++ b/source/blender/blenkernel/intern/mesh_validate.c @@ -164,16 +164,20 @@ static int search_poly_cmp(const void *v1, const void *v2) { const SortPoly *sp1 = v1, *sp2 = v2; const int max_idx = sp1->numverts > sp2->numverts ? sp2->numverts : sp1->numverts; - int idx = 0; + int idx; /* Reject all invalid polys at end of list! */ if (sp1->invalid || sp2->invalid) - return sp1->invalid && sp2->invalid ? 0 : sp1->invalid ? 1 : -1; - /* Else, sort on first non-egal verts (remember verts of valid polys are sorted). */ - while (idx < max_idx && sp1->verts[idx] == sp2->verts[idx]) - idx++; - return sp1->verts[idx] > sp2->verts[idx] ? 1 : sp1->verts[idx] < sp2->verts[idx] ? -1 : - sp1->numverts > sp2->numverts ? 1 : sp1->numverts < sp2->numverts ? -1 : 0; + return sp1->invalid ? (sp2->invalid ? 0 : 1) : -1; + /* Else, sort on first non-equal verts (remember verts of valid polys are sorted). */ + for (idx = 0; idx < max_idx; idx++) { + const int v1 = sp1->verts[idx]; + const int v2 = sp2->verts[idx]; + if (v1 != v2) { + return (v1 > v2) ? 1 : -1; + } + } + return sp1->numverts > sp2->numverts ? 1 : sp1->numverts < sp2->numverts ? -1 : 0; } static int search_polyloop_cmp(const void *v1, const void *v2) @@ -255,7 +259,7 @@ bool BKE_mesh_validate_arrays(Mesh *mesh, do_edge_recalc = do_fixes; } - for (i = 1; i < totvert; i++, mv++) { + for (i = 0; i < totvert; i++, mv++) { bool fix_normal = true; for (j = 0; j < 3; j++) { @@ -498,8 +502,9 @@ bool BKE_mesh_validate_arrays(Mesh *mesh, PRINT_ERR("\tLoop %u has invalid vert reference (%u)\n", sp->loopstart + j, ml->v); sp->invalid = true; } - - mverts[ml->v].flag |= ME_VERT_TMP_TAG; + else { + mverts[ml->v].flag |= ME_VERT_TMP_TAG; + } *v = ml->v; } @@ -909,8 +914,6 @@ static bool mesh_validate_customdata(CustomData *data, CustomDataMask mask, return is_valid; } -#undef PRINT - /** * \returns is_valid. */ @@ -1052,8 +1055,36 @@ void BKE_mesh_cd_validate(Mesh *me) } } } -/** \} */ +/** + * Check all material indices of polygons are valid, invalid ones are set to 0. + * \returns is_valid. + */ +int BKE_mesh_validate_material_indices(Mesh *me) +{ + MPoly *mp; + const int max_idx = max_ii(0, me->totcol - 1); + const int totpoly = me->totpoly; + int i; + bool is_valid = true; + + for (mp = me->mpoly, i = 0; i < totpoly; i++, mp++) { + if (mp->mat_nr > max_idx) { + mp->mat_nr = 0; + is_valid = false; + } + } + + if (!is_valid) { + DAG_id_tag_update(&me->id, OB_RECALC_DATA); + return true; + } + else { + return false; + } +} + +/** \} */ /* -------------------------------------------------------------------- */ diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index 1c42603cf4a..a9e853c873e 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -171,11 +171,14 @@ bool modifier_isPreview(ModifierData *md) { ModifierTypeInfo *mti = modifierType_getInfo(md->type); - if (!(mti->flags & eModifierTypeFlag_UsesPreview)) + /* Constructive modifiers are highly likely to also modify data like vgroups or vcol! */ + if (!((mti->flags & eModifierTypeFlag_UsesPreview) || (mti->type == eModifierTypeType_Constructive))) { return false; + } - if (md->mode & eModifierMode_Realtime) + if (md->mode & eModifierMode_Realtime) { return true; + } return false; } @@ -350,6 +353,7 @@ int modifiers_getCageIndex(struct Scene *scene, Object *ob, int *r_lastPossibleC /* Find the last modifier acting on the cage. */ for (i = 0; md; i++, md = md->next) { ModifierTypeInfo *mti = modifierType_getInfo(md->type); + bool supports_mapping; md->scene = scene; @@ -357,16 +361,17 @@ int modifiers_getCageIndex(struct Scene *scene, Object *ob, int *r_lastPossibleC if (!(mti->flags & eModifierTypeFlag_SupportsEditmode)) continue; if (md->mode & eModifierMode_DisableTemporary) continue; + supports_mapping = modifier_supportsMapping(md); + if (r_lastPossibleCageIndex && supports_mapping) { + *r_lastPossibleCageIndex = i; + } + if (!(md->mode & eModifierMode_Realtime)) continue; if (!(md->mode & eModifierMode_Editmode)) continue; - if (!modifier_supportsMapping(md)) + if (!supports_mapping) break; - if (r_lastPossibleCageIndex) { - *r_lastPossibleCageIndex = i; - } - if (md->mode & eModifierMode_OnCage) cageIndex = i; } @@ -409,13 +414,12 @@ bool modifier_isEnabled(struct Scene *scene, ModifierData *md, int required_mode md->scene = scene; - if ((md->mode & required_mode) != required_mode) return 0; - if (mti->isDisabled && mti->isDisabled(md, required_mode == eModifierMode_Render)) return 0; - if (md->mode & eModifierMode_DisableTemporary) return 0; - if (required_mode & eModifierMode_Editmode) - if (!(mti->flags & eModifierTypeFlag_SupportsEditmode)) return 0; + if ((md->mode & required_mode) != required_mode) return false; + if (mti->isDisabled && mti->isDisabled(md, required_mode == eModifierMode_Render)) return false; + if (md->mode & eModifierMode_DisableTemporary) return false; + if ((required_mode & eModifierMode_Editmode) && !(mti->flags & eModifierTypeFlag_SupportsEditmode)) return false; - return 1; + return true; } CDMaskLink *modifiers_calcDataMasks(struct Scene *scene, Object *ob, ModifierData *md, diff --git a/source/blender/blenkernel/intern/multires.c b/source/blender/blenkernel/intern/multires.c index 1d5bbbe1aeb..246ef8a33f5 100644 --- a/source/blender/blenkernel/intern/multires.c +++ b/source/blender/blenkernel/intern/multires.c @@ -112,7 +112,7 @@ static BLI_bitmap *multires_mdisps_upsample_hidden(BLI_bitmap *lo_hidden, /* assumed to be at hi_level (or * null) */ - BLI_bitmap *prev_hidden) + const BLI_bitmap *prev_hidden) { BLI_bitmap *subd; int hi_gridsize = BKE_ccg_gridsize(hi_level); diff --git a/source/blender/blenkernel/intern/nla.c b/source/blender/blenkernel/intern/nla.c index d0114d52a06..19e45142960 100644 --- a/source/blender/blenkernel/intern/nla.c +++ b/source/blender/blenkernel/intern/nla.c @@ -430,7 +430,7 @@ static float nlastrip_get_frame_actionclip(NlaStrip *strip, float cframe, short return (strip->end + (strip->actstart * scale - cframe)) / scale; } else { /* if (mode == NLATIME_CONVERT_EVAL) */ - if (IS_EQF(cframe, strip->end) && IS_EQF(strip->repeat, ((int)strip->repeat))) { + if (IS_EQF((float)cframe, strip->end) && IS_EQF(strip->repeat, floorf(strip->repeat))) { /* this case prevents the motion snapping back to the first frame at the end of the strip * by catching the case where repeats is a whole number, which means that the end of the strip * could also be interpreted as the end of the start of a repeat @@ -453,7 +453,7 @@ static float nlastrip_get_frame_actionclip(NlaStrip *strip, float cframe, short return strip->actstart + (cframe - strip->start) / scale; } else { /* if (mode == NLATIME_CONVERT_EVAL) */ - if (IS_EQF(cframe, strip->end) && IS_EQF(strip->repeat, ((int)strip->repeat))) { + if (IS_EQF(cframe, strip->end) && IS_EQF(strip->repeat, floorf(strip->repeat))) { /* this case prevents the motion snapping back to the first frame at the end of the strip * by catching the case where repeats is a whole number, which means that the end of the strip * could also be interpreted as the end of the start of a repeat @@ -1637,7 +1637,7 @@ bool BKE_nla_tweakmode_enter(AnimData *adt) } } - if (ELEM3(NULL, activeTrack, activeStrip, activeStrip->act)) { + if (ELEM(NULL, activeTrack, activeStrip, activeStrip->act)) { if (G.debug & G_DEBUG) { printf("NLA tweakmode enter - neither active requirement found\n"); printf("\tactiveTrack = %p, activeStrip = %p\n", (void *)activeTrack, (void *)activeStrip); @@ -1744,7 +1744,7 @@ static void UNUSED_FUNCTION(BKE_nla_bake) (Scene *scene, ID *UNUSED(id), AnimDat * 1) Scene and AnimData must be provided * 2) there must be tracks to merge... */ - if (ELEM3(NULL, scene, adt, adt->nla_tracks.first)) + if (ELEM(NULL, scene, adt, adt->nla_tracks.first)) return; /* if animdata currently has an action, 'push down' this onto the stack first */ diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c index 56a76a54955..0f86b551092 100644 --- a/source/blender/blenkernel/intern/node.c +++ b/source/blender/blenkernel/intern/node.c @@ -1205,13 +1205,13 @@ static bNodeTree *ntreeCopyTree_internal(bNodeTree *ntree, Main *bmain, bool do_ return newtree; } -bNodeTree *ntreeCopyTree_ex(bNodeTree *ntree, const bool do_id_user) +bNodeTree *ntreeCopyTree_ex(bNodeTree *ntree, Main *bmain, const bool do_id_user) { - return ntreeCopyTree_internal(ntree, G.main, do_id_user, true, true); + return ntreeCopyTree_internal(ntree, bmain, do_id_user, true, true); } bNodeTree *ntreeCopyTree(bNodeTree *ntree) { - return ntreeCopyTree_ex(ntree, true); + return ntreeCopyTree_ex(ntree, G.main, true); } /* use when duplicating scenes */ @@ -3406,6 +3406,7 @@ static void registerCompositNodes(void) register_node_type_cmp_inpaint(); register_node_type_cmp_despeckle(); register_node_type_cmp_defocus(); + register_node_type_cmp_sunbeams(); register_node_type_cmp_valtorgb(); register_node_type_cmp_rgbtobw(); @@ -3528,10 +3529,12 @@ static void registerShaderNodes(void) register_node_type_sh_mix_shader(); register_node_type_sh_add_shader(); register_node_type_sh_uvmap(); + register_node_type_sh_uvalongstroke(); register_node_type_sh_output_lamp(); register_node_type_sh_output_material(); register_node_type_sh_output_world(); + register_node_type_sh_output_linestyle(); register_node_type_sh_tex_image(); register_node_type_sh_tex_environment(); diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index 3490bb9ffbd..b09016506e3 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -42,6 +42,7 @@ #include "DNA_constraint_types.h" #include "DNA_group_types.h" #include "DNA_key_types.h" +#include "DNA_lamp_types.h" #include "DNA_lattice_types.h" #include "DNA_material_types.h" #include "DNA_meta_types.h" @@ -180,7 +181,7 @@ void BKE_object_free_curve_cache(Object *ob) { if (ob->curve_cache) { BKE_displist_free(&ob->curve_cache->disp); - BLI_freelistN(&ob->curve_cache->bev); + BKE_curve_bevelList_free(&ob->curve_cache->bev); if (ob->curve_cache->path) { free_path(ob->curve_cache->path); } @@ -246,7 +247,7 @@ void BKE_object_link_modifiers(struct Object *ob_dst, struct Object *ob_src) ModifierData *md; BKE_object_free_modifiers(ob_dst); - if (!ELEM5(ob_dst->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_LATTICE)) { + if (!ELEM(ob_dst->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_LATTICE)) { /* only objects listed above can have modifiers and linking them to objects * which doesn't have modifiers stack is quite silly */ return; @@ -255,11 +256,11 @@ void BKE_object_link_modifiers(struct Object *ob_dst, struct Object *ob_src) for (md = ob_src->modifiers.first; md; md = md->next) { ModifierData *nmd = NULL; - if (ELEM4(md->type, - eModifierType_Hook, - eModifierType_Softbody, - eModifierType_ParticleInstance, - eModifierType_Collision)) + if (ELEM(md->type, + eModifierType_Hook, + eModifierType_Softbody, + eModifierType_ParticleInstance, + eModifierType_Collision)) { continue; } @@ -296,7 +297,7 @@ void BKE_object_free_derived_caches(Object *ob) me->bb->flag |= BOUNDBOX_DIRTY; } } - else if (ELEM3(ob->type, OB_SURF, OB_CURVE, OB_FONT)) { + else if (ELEM(ob->type, OB_SURF, OB_CURVE, OB_FONT)) { Curve *cu = ob->data; if (cu->bb) { @@ -322,7 +323,7 @@ void BKE_object_free_derived_caches(Object *ob) if (ob->curve_cache) { BKE_displist_free(&ob->curve_cache->disp); - BLI_freelistN(&ob->curve_cache->bev); + BKE_curve_bevelList_free(&ob->curve_cache->bev); if (ob->curve_cache->path) { free_path(ob->curve_cache->path); ob->curve_cache->path = NULL; @@ -408,7 +409,7 @@ void BKE_object_free_ex(Object *ob, bool do_id_user) /* Free runtime curves data. */ if (ob->curve_cache) { - BLI_freelistN(&ob->curve_cache->bev); + BKE_curve_bevelList_free(&ob->curve_cache->bev); if (ob->curve_cache->path) free_path(ob->curve_cache->path); MEM_freeN(ob->curve_cache); @@ -709,7 +710,7 @@ void BKE_object_unlink(Object *ob) lineset; lineset = lineset->next) { if (lineset->linestyle) { - BKE_unlink_linestyle_target_object(lineset->linestyle, ob); + BKE_linestyle_target_object_unlink(lineset->linestyle, ob); } } } @@ -873,9 +874,9 @@ bool BKE_object_is_in_wpaint_select_vert(Object *ob) { if (ob->type == OB_MESH) { Mesh *me = ob->data; - return ( (ob->mode & OB_MODE_WEIGHT_PAINT) && - (me->edit_btmesh == NULL) && - (ME_EDIT_PAINT_SEL_MODE(me) == SCE_SELECT_VERTEX) ); + return ((ob->mode & OB_MODE_WEIGHT_PAINT) && + (me->edit_btmesh == NULL) && + (ME_EDIT_PAINT_SEL_MODE(me) == SCE_SELECT_VERTEX)); } return false; @@ -977,7 +978,7 @@ Object *BKE_object_add_only_object(Main *bmain, int type, const char *name) ob->empty_drawtype = OB_PLAINAXES; ob->empty_drawsize = 1.0; - if (ELEM3(type, OB_LAMP, OB_CAMERA, OB_SPEAKER)) { + if (ELEM(type, OB_LAMP, OB_CAMERA, OB_SPEAKER)) { ob->trackflag = OB_NEGZ; ob->upflag = OB_POSY; } @@ -1526,6 +1527,18 @@ Object *BKE_object_copy(Object *ob) return BKE_object_copy_ex(G.main, ob, false); } +static void extern_local_object__modifiersForeachIDLink( + void *UNUSED(userData), Object *UNUSED(ob), + ID **idpoin) +{ + if (*idpoin) { + /* intentionally omit ID_OB */ + if (ELEM(GS((*idpoin)->name), ID_IM, ID_TE)) { + id_lib_extern(*idpoin); + } + } +} + static void extern_local_object(Object *ob) { ParticleSystem *psys; @@ -1539,6 +1552,8 @@ static void extern_local_object(Object *ob) for (psys = ob->particlesystem.first; psys; psys = psys->next) id_lib_extern((ID *)psys->part); + + modifiers_foreachIDLink(ob, extern_local_object__modifiersForeachIDLink, NULL); } void BKE_object_make_local(Object *ob) @@ -1778,6 +1793,55 @@ void BKE_object_make_proxy(Object *ob, Object *target, Object *gob) ob->dt = target->dt; } +/** + * Use with newly created objects to set their size + * (used to apply scene-scale). + */ +void BKE_object_obdata_size_init(struct Object *ob, const float size) +{ + /* apply radius as a scale to types that support it */ + switch (ob->type) { + case OB_EMPTY: + { + ob->empty_drawsize *= size; + break; + } + case OB_FONT: + { + Curve *cu = ob->data; + cu->fsize *= size; + break; + } + case OB_CAMERA: + { + Camera *cam = ob->data; + cam->drawsize *= size; + break; + } + case OB_LAMP: + { + Lamp *lamp = ob->data; + lamp->dist *= size; + lamp->area_size *= size; + lamp->area_sizey *= size; + lamp->area_sizez *= size; + break; + } + /* Only lattice (not mesh, curve, mball...), + * because its got data when newly added */ + case OB_LATTICE: + { + struct Lattice *lt = ob->data; + float mat[4][4]; + + unit_m4(mat); + scale_m4_fl(mat, size); + + BKE_lattice_transform(lt, (float (*)[4])mat, false); + break; + } + } +} /* *************** CALC ****************** */ @@ -1978,7 +2042,7 @@ static void ob_parcurve(Scene *scene, Object *ob, Object *par, float mat[4][4]) unit_m4(mat); cu = par->data; - if (ELEM3(NULL, par->curve_cache, par->curve_cache->path, par->curve_cache->path->data)) /* only happens on reload file, but violates depsgraph still... fix! */ + if (ELEM(NULL, par->curve_cache, par->curve_cache->path, par->curve_cache->path->data)) /* only happens on reload file, but violates depsgraph still... fix! */ BKE_displist_make_curveTypes(scene, par, 0); if (par->curve_cache->path == NULL) return; @@ -1994,17 +2058,20 @@ static void ob_parcurve(Scene *scene, Object *ob, Object *par, float mat[4][4]) * we divide the curvetime calculated in the previous step by the length of the path, to get a time * factor, which then gets clamped to lie within 0.0 - 1.0 range */ - if (IS_EQF(cu->pathlen, 0.0f) == 0) + if (cu->pathlen) { ctime = cu->ctime / cu->pathlen; - else + } + else { ctime = cu->ctime; + } CLAMP(ctime, 0.0f, 1.0f); } else { ctime = BKE_scene_frame_get(scene); - if (IS_EQF(cu->pathlen, 0.0f) == 0) + if (cu->pathlen) { ctime /= cu->pathlen; + } CLAMP(ctime, 0.0f, 1.0f); } @@ -2289,7 +2356,7 @@ static bool where_is_object_parslow(Object *ob, float obmat[4][4], float slowmat int a; /* include framerate */ - fac1 = (1.0f / (1.0f + fabsf(ob->sf)) ); + fac1 = (1.0f / (1.0f + fabsf(ob->sf))); if (fac1 >= 1.0f) return 0; fac2 = 1.0f - fac1; @@ -2466,6 +2533,20 @@ void BKE_boundbox_init_from_minmax(BoundBox *bb, const float min[3], const float bb->vec[1][2] = bb->vec[2][2] = bb->vec[5][2] = bb->vec[6][2] = max[2]; } +void BKE_boundbox_calc_center_aabb(const BoundBox *bb, float r_cent[3]) +{ + r_cent[0] = 0.5f * (bb->vec[0][0] + bb->vec[4][0]); + r_cent[1] = 0.5f * (bb->vec[0][1] + bb->vec[2][1]); + r_cent[2] = 0.5f * (bb->vec[0][2] + bb->vec[1][2]); +} + +void BKE_boundbox_calc_size_aabb(const BoundBox *bb, float r_size[3]) +{ + r_size[0] = 0.5f * fabsf(bb->vec[0][0] - bb->vec[4][0]); + r_size[1] = 0.5f * fabsf(bb->vec[0][1] - bb->vec[2][1]); + r_size[2] = 0.5f * fabsf(bb->vec[0][2] - bb->vec[1][2]); +} + BoundBox *BKE_object_boundbox_get(Object *ob) { BoundBox *bb = NULL; @@ -2473,7 +2554,7 @@ BoundBox *BKE_object_boundbox_get(Object *ob) if (ob->type == OB_MESH) { bb = BKE_mesh_boundbox_get(ob); } - else if (ELEM3(ob->type, OB_CURVE, OB_SURF, OB_FONT)) { + else if (ELEM(ob->type, OB_CURVE, OB_SURF, OB_FONT)) { bb = BKE_curve_boundbox_get(ob); } else if (ob->type == OB_MBALL) { @@ -2483,7 +2564,7 @@ BoundBox *BKE_object_boundbox_get(Object *ob) } /* used to temporally disable/enable boundbox */ -void BKE_object_boundbox_flag(Object *ob, int flag, int set) +void BKE_object_boundbox_flag(Object *ob, int flag, const bool set) { BoundBox *bb = BKE_object_boundbox_get(ob); if (bb) { @@ -3126,8 +3207,10 @@ int BKE_object_obdata_texspace_get(Object *ob, short **r_texflag, float **r_loc, * Test a bounding box for ray intersection * assumes the ray is already local to the boundbox space */ -bool BKE_boundbox_ray_hit_check(struct BoundBox *bb, const float ray_start[3], const float ray_normal[3], - float *r_lambda) +bool BKE_boundbox_ray_hit_check( + const struct BoundBox *bb, + const float ray_start[3], const float ray_normal[3], + float *r_lambda) { const int triangle_indexes[12][3] = { {0, 1, 2}, {0, 2, 3}, diff --git a/source/blender/blenkernel/intern/object_dupli.c b/source/blender/blenkernel/intern/object_dupli.c index 707438bc673..0d82c6e89a1 100644 --- a/source/blender/blenkernel/intern/object_dupli.c +++ b/source/blender/blenkernel/intern/object_dupli.c @@ -754,14 +754,14 @@ static void make_child_duplis_faces(const DupliContext *ctx, void *userdata, Obj if (orco) { int j; - for (j = 0; j < mpoly->totloop; j++) { + for (j = 0; j < mp->totloop; j++) { madd_v3_v3fl(dob->orco, orco[loopstart[j].v], w); } } if (mloopuv) { int j; - for (j = 0; j < mpoly->totloop; j++) { + for (j = 0; j < mp->totloop; j++) { madd_v2_v2fl(dob->uv, mloopuv[mp->loopstart + j].uv, w); } } diff --git a/source/blender/blenkernel/intern/paint.c b/source/blender/blenkernel/intern/paint.c index 9a144b5461a..4382d74f34e 100644 --- a/source/blender/blenkernel/intern/paint.c +++ b/source/blender/blenkernel/intern/paint.c @@ -45,8 +45,10 @@ #include "BLI_bitmap.h" #include "BLI_utildefines.h" #include "BLI_math_vector.h" +#include "BLI_listbase.h" #include "BKE_brush.h" +#include "BKE_main.h" #include "BKE_context.h" #include "BKE_crazyspace.h" #include "BKE_depsgraph.h" @@ -269,6 +271,105 @@ void BKE_paint_brush_set(Paint *p, Brush *br) } } +void BKE_paint_curve_free(PaintCurve *pc) +{ + if (pc->points) { + MEM_freeN(pc->points); + pc->points = NULL; + pc->tot_points = 0; + } +} + +PaintCurve *BKE_paint_curve_add(Main *bmain, const char *name) +{ + PaintCurve *pc; + + pc = BKE_libblock_alloc(bmain, ID_PC, name); + + return pc; +} + +Palette *BKE_paint_palette(Paint *p) +{ + return p ? p->palette : NULL; +} + +void BKE_paint_palette_set(Paint *p, Palette *palette) +{ + if (p) { + id_us_min((ID *)p->palette); + id_us_plus((ID *)palette); + p->palette = palette; + } +} + +void BKE_paint_curve_set(Brush *br, PaintCurve *pc) +{ + if (br) { + id_us_min((ID *)br->paint_curve); + id_us_plus((ID *)pc); + br->paint_curve = pc; + } +} + +/* remove colour from palette. Must be certain color is inside the palette! */ +void BKE_palette_color_remove(Palette *palette, PaletteColor *color) +{ + BLI_remlink(&palette->colors, color); + BLI_addhead(&palette->deleted, color); +} + +void BKE_palette_cleanup(Palette *palette) +{ + BLI_freelistN(&palette->deleted); +} + + +Palette *BKE_palette_add(Main *bmain, const char *name) +{ + Palette *palette; + + palette = BKE_libblock_alloc(bmain, ID_PAL, name); + + /* enable fake user by default */ + palette->id.flag |= LIB_FAKEUSER; + + return palette; +} + +void BKE_palette_free(Palette *palette) +{ + BLI_freelistN(&palette->colors); +} + +PaletteColor *BKE_palette_color_add(Palette *palette) +{ + PaletteColor *color = MEM_callocN(sizeof(*color), "Pallete Color"); + BLI_addtail(&palette->colors, color); + palette->active_color = BLI_countlist(&palette->colors) - 1; + return color; +} + +void BKE_palette_color_delete(struct Palette *palette) +{ + PaletteColor *color = BLI_findlink(&palette->colors, palette->active_color); + + if (color) { + if ((color == palette->colors.last) && (palette->colors.last != palette->colors.first)) + palette->active_color--; + + BLI_remlink(&palette->colors, color); + BLI_addhead(&palette->deleted, color); + } +} + + +bool BKE_palette_is_empty(const struct Palette *palette) +{ + return BLI_listbase_is_empty(&palette->colors); +} + + /* are we in vertex paint or weight pain face select mode? */ bool BKE_paint_select_face_test(Object *ob) { @@ -318,6 +419,7 @@ void BKE_paint_init(Paint *p, const char col[3]) void BKE_paint_free(Paint *paint) { id_us_min((ID *)paint->brush); + id_us_min((ID *)paint->palette); } /* called when copying scene settings, so even if 'src' and 'tar' are the same @@ -328,6 +430,7 @@ void BKE_paint_copy(Paint *src, Paint *tar) { tar->brush = src->brush; id_us_plus((ID *)tar->brush); + id_us_plus((ID *)tar->palette); } /* returns non-zero if any of the face's vertices @@ -378,7 +481,7 @@ float paint_grid_paint_mask(const GridPaintMask *gpm, unsigned level, return gpm->data[(y * factor) * gridsize + (x * factor)]; } -/* threshhold to move before updating the brush rotation */ +/* threshold to move before updating the brush rotation */ #define RAKE_THRESHHOLD 20 void paint_calculate_rake_rotation(UnifiedPaintSettings *ups, const float mouse_pos[2]) diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c index 8161f9d8875..27d346f65b9 100644 --- a/source/blender/blenkernel/intern/particle.c +++ b/source/blender/blenkernel/intern/particle.c @@ -1657,11 +1657,14 @@ int psys_particle_dm_face_lookup(Object *ob, DerivedMesh *dm, int index, const f index_mp_to_orig = NULL; } + totface = dm->getNumTessFaces(dm); + if (!totface) { + return DMCACHE_NOTFOUND; + } + mpoly = dm->getPolyArray(dm); osface = dm->getTessFaceDataArray(dm, CD_ORIGSPACE); - totface = dm->getNumTessFaces(dm); - if (osface == NULL || index_mf_to_mpoly == NULL) { /* Assume we don't need osface data */ if (index < totface) { diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c index 06ac9db0b16..09e20c02691 100644 --- a/source/blender/blenkernel/intern/particle_system.c +++ b/source/blender/blenkernel/intern/particle_system.c @@ -117,7 +117,7 @@ static int particles_are_dynamic(ParticleSystem *psys) if (psys->part->type == PART_HAIR) return psys->flag & PSYS_HAIR_DYNAMICS; else - return ELEM3(psys->part->phystype, PART_PHYS_NEWTON, PART_PHYS_BOIDS, PART_PHYS_FLUID); + return ELEM(psys->part->phystype, PART_PHYS_NEWTON, PART_PHYS_BOIDS, PART_PHYS_FLUID); } float psys_get_current_display_percentage(ParticleSystem *psys) @@ -399,7 +399,7 @@ void psys_calc_dmcache(Object *ob, DerivedMesh *dm, ParticleSystem *psys) } } - if (origindex_final != ORIGINDEX_NONE) { + if (origindex_final != ORIGINDEX_NONE && origindex_final < totelem) { if (nodearray[origindex_final]) { /* prepend */ node->next = nodearray[origindex_final]; @@ -507,7 +507,7 @@ static void distribute_grid(DerivedMesh *dm, ParticleSystem *psys) sub_v3_v3v3(delta, max, min); /* determine major axis */ - axis = (delta[0]>=delta[1]) ? 0 : ((delta[1]>=delta[2]) ? 1 : 2); + axis = axis_dominant_v3_single(delta); d = delta[axis]/(float)res; @@ -1079,7 +1079,7 @@ static int distribute_threads_init_data(ParticleThread *threads, Scene *scene, D float *element_weight=NULL,*element_sum=NULL,*jitter_offset=NULL, *vweight=NULL; float cur, maxweight=0.0, tweight, totweight, inv_totweight, co[3], nor[3], orco[3]; - if (ELEM3(NULL, ob, psys, psys->part)) + if (ELEM(NULL, ob, psys, psys->part)) return 0; part=psys->part; @@ -2638,7 +2638,7 @@ static void sph_particle_courant(SPHData *sphdata, SPHRangeData *pfr) mul_v3_v3fl(sphdata->flow, flow, 1.0f / pfr->tot_neighbors); } else { - sphdata->element_size = MAXFLOAT; + sphdata->element_size = FLT_MAX; copy_v3_v3(sphdata->flow, flow); } } @@ -3153,7 +3153,7 @@ static void basic_rotate(ParticleSettings *part, ParticleData *pa, float dfra, f extrotfac = 0.0f; } - if ((part->flag & PART_ROT_DYN) && ELEM3(part->avemode, PART_AVE_VELOCITY, PART_AVE_HORIZONTAL, PART_AVE_VERTICAL)) { + if ((part->flag & PART_ROT_DYN) && ELEM(part->avemode, PART_AVE_VELOCITY, PART_AVE_HORIZONTAL, PART_AVE_VERTICAL)) { float angle; float len1 = len_v3(pa->prev_state.vel); float len2 = len_v3(pa->state.vel); @@ -4012,6 +4012,7 @@ static void do_hair_dynamics(ParticleSimulationData *sim) if (!psys->clmd) { psys->clmd = (ClothModifierData*)modifier_new(eModifierType_Cloth); psys->clmd->sim_parms->goalspring = 0.0f; + psys->clmd->sim_parms->vel_damping = 1.0f; psys->clmd->sim_parms->flags |= CLOTH_SIMSETTINGS_FLAG_GOAL|CLOTH_SIMSETTINGS_FLAG_NO_SPRING_COMPRESS; psys->clmd->coll_parms->flags &= ~CLOTH_COLLSETTINGS_FLAG_SELF; } @@ -4846,13 +4847,13 @@ void psys_changed_type(Object *ob, ParticleSystem *psys) psys->flag &= ~PSYS_KEYED; if (part->type == PART_HAIR) { - if (ELEM4(part->ren_as, PART_DRAW_NOT, PART_DRAW_PATH, PART_DRAW_OB, PART_DRAW_GR)==0) + if (ELEM(part->ren_as, PART_DRAW_NOT, PART_DRAW_PATH, PART_DRAW_OB, PART_DRAW_GR)==0) part->ren_as = PART_DRAW_PATH; if (part->distr == PART_DISTR_GRID) part->distr = PART_DISTR_JIT; - if (ELEM3(part->draw_as, PART_DRAW_NOT, PART_DRAW_REND, PART_DRAW_PATH)==0) + if (ELEM(part->draw_as, PART_DRAW_NOT, PART_DRAW_REND, PART_DRAW_PATH)==0) part->draw_as = PART_DRAW_REND; CLAMP(part->path_start, 0.0f, 100.0f); diff --git a/source/blender/blenkernel/intern/pbvh.c b/source/blender/blenkernel/intern/pbvh.c index 1a815cf0dee..3e763016efb 100644 --- a/source/blender/blenkernel/intern/pbvh.c +++ b/source/blender/blenkernel/intern/pbvh.c @@ -50,6 +50,15 @@ #define STACK_FIXED_DEPTH 100 +/* Setting zero so we can catch bugs in OpenMP/PBVH. */ +#ifdef _OPENMP +# ifdef DEBUG +# define PBVH_OMP_LIMIT 0 +# else +# define PBVH_OMP_LIMIT 8 +# endif +#endif + typedef struct PBVHStack { PBVHNode *node; int revisiting; @@ -965,7 +974,7 @@ static void pbvh_update_normals(PBVH *bvh, PBVHNode **nodes, * can only update vertices marked with ME_VERT_PBVH_UPDATE. */ -#pragma omp parallel for private(n) schedule(static) +#pragma omp parallel for private(n) schedule(static) if (totnode > PBVH_OMP_LIMIT) for (n = 0; n < totnode; n++) { PBVHNode *node = nodes[n]; @@ -1009,7 +1018,7 @@ static void pbvh_update_normals(PBVH *bvh, PBVHNode **nodes, } } -#pragma omp parallel for private(n) schedule(static) +#pragma omp parallel for private(n) schedule(static) if (totnode > PBVH_OMP_LIMIT) for (n = 0; n < totnode; n++) { PBVHNode *node = nodes[n]; @@ -1046,7 +1055,7 @@ void pbvh_update_BB_redraw(PBVH *bvh, PBVHNode **nodes, int totnode, int flag) int n; /* update BB, redraw flag */ -#pragma omp parallel for private(n) schedule(static) +#pragma omp parallel for private(n) schedule(static) if (totnode > PBVH_OMP_LIMIT) for (n = 0; n < totnode; n++) { PBVHNode *node = nodes[n]; diff --git a/source/blender/blenkernel/intern/report.c b/source/blender/blenkernel/intern/report.c index 90b5d8cf1a1..b2178fe69b3 100644 --- a/source/blender/blenkernel/intern/report.c +++ b/source/blender/blenkernel/intern/report.c @@ -284,7 +284,7 @@ Report *BKE_reports_last_displayable(ReportList *reports) Report *report; for (report = reports->list.last; report; report = report->prev) { - if (ELEM3(report->type, RPT_ERROR, RPT_WARNING, RPT_INFO)) + if (ELEM(report->type, RPT_ERROR, RPT_WARNING, RPT_INFO)) return report; } diff --git a/source/blender/blenkernel/intern/rigidbody.c b/source/blender/blenkernel/intern/rigidbody.c index 09293503ad5..3d61b0bdefb 100644 --- a/source/blender/blenkernel/intern/rigidbody.c +++ b/source/blender/blenkernel/intern/rigidbody.c @@ -57,6 +57,7 @@ #include "BKE_effect.h" #include "BKE_global.h" #include "BKE_library.h" +#include "BKE_mesh.h" #include "BKE_object.h" #include "BKE_pointcache.h" #include "BKE_rigidbody.h" @@ -287,10 +288,10 @@ static rbCollisionShape *rigidbody_get_shape_trimesh_from_mesh(Object *ob) DM_ensure_tessface(dm); - mvert = (dm) ? dm->getVertArray(dm) : NULL; - totvert = (dm) ? dm->getNumVerts(dm) : 0; - mface = (dm) ? dm->getTessFaceArray(dm) : NULL; - totface = (dm) ? dm->getNumTessFaces(dm) : 0; + mvert = dm->getVertArray(dm); + totvert = dm->getNumVerts(dm); + mface = dm->getTessFaceArray(dm); + totface = dm->getNumTessFaces(dm); /* sanity checking - potential case when no data will be present */ if ((totvert == 0) || (totface == 0)) { @@ -344,7 +345,7 @@ static rbCollisionShape *rigidbody_get_shape_trimesh_from_mesh(Object *ob) } /* cleanup temp data */ - if (dm && ob->rigidbody_object->mesh_source == RBO_MESH_BASE) { + if (ob->rigidbody_object->mesh_source == RBO_MESH_BASE) { dm->release(dm); } } @@ -394,7 +395,7 @@ static void rigidbody_validate_sim_shape(Object *ob, bool rebuild) } mul_v3_fl(size, 0.5f); - if (ELEM3(rbo->shape, RB_SHAPE_CAPSULE, RB_SHAPE_CYLINDER, RB_SHAPE_CONE)) { + if (ELEM(rbo->shape, RB_SHAPE_CAPSULE, RB_SHAPE_CYLINDER, RB_SHAPE_CONE)) { /* take radius as largest x/y dimension, and height as z-dimension */ radius = MAX2(size[0], size[1]); height = size[2]; @@ -455,6 +456,182 @@ static void rigidbody_validate_sim_shape(Object *ob, bool rebuild) /* --------------------- */ +/* helper function to calculate volume of rigidbody object */ +// TODO: allow a parameter to specify method used to calculate this? +void BKE_rigidbody_calc_volume(Object *ob, float *r_vol) +{ + RigidBodyOb *rbo = ob->rigidbody_object; + + float size[3] = {1.0f, 1.0f, 1.0f}; + float radius = 1.0f; + float height = 1.0f; + + float volume = 0.0f; + + /* if automatically determining dimensions, use the Object's boundbox + * - assume that all quadrics are standing upright on local z-axis + * - assume even distribution of mass around the Object's pivot + * (i.e. Object pivot is centralized in boundbox) + * - boundbox gives full width + */ + // XXX: all dimensions are auto-determined now... later can add stored settings for this + BKE_object_dimensions_get(ob, size); + + if (ELEM(rbo->shape, RB_SHAPE_CAPSULE, RB_SHAPE_CYLINDER, RB_SHAPE_CONE)) { + /* take radius as largest x/y dimension, and height as z-dimension */ + radius = MAX2(size[0], size[1]) * 0.5f; + height = size[2]; + } + else if (rbo->shape == RB_SHAPE_SPHERE) { + /* take radius to the the largest dimension to try and encompass everything */ + radius = max_fff(size[0], size[1], size[2]) * 0.5f; + } + + /* calculate volume as appropriate */ + switch (rbo->shape) { + case RB_SHAPE_BOX: + volume = size[0] * size[1] * size[2]; + break; + + case RB_SHAPE_SPHERE: + volume = 4.0f / 3.0f * (float)M_PI * radius * radius * radius; + break; + + /* for now, assume that capsule is close enough to a cylinder... */ + case RB_SHAPE_CAPSULE: + case RB_SHAPE_CYLINDER: + volume = (float)M_PI * radius * radius * height; + break; + + case RB_SHAPE_CONE: + volume = (float)M_PI / 3.0f * radius * radius * height; + break; + + case RB_SHAPE_CONVEXH: + case RB_SHAPE_TRIMESH: + { + if (ob->type == OB_MESH) { + DerivedMesh *dm = rigidbody_get_mesh(ob); + MVert *mvert; + MFace *mface; + int totvert, totface; + + /* ensure mesh validity, then grab data */ + if (dm == NULL) + return; + + DM_ensure_tessface(dm); + + mvert = dm->getVertArray(dm); + totvert = dm->getNumVerts(dm); + mface = dm->getTessFaceArray(dm); + totface = dm->getNumTessFaces(dm); + + if (totvert > 0 && totface > 0) { + BKE_mesh_calc_volume(mvert, totvert, mface, totface, &volume, NULL); + } + + /* cleanup temp data */ + if (ob->rigidbody_object->mesh_source == RBO_MESH_BASE) { + dm->release(dm); + } + } + else { + /* rough estimate from boundbox as fallback */ + /* XXX could implement other types of geometry here (curves, etc.) */ + volume = size[0] * size[1] * size[2]; + } + break; + } + +#if 0 // XXX: not defined yet + case RB_SHAPE_COMPOUND: + volume = 0.0f; + break; +#endif + } + + /* return the volume calculated */ + if (r_vol) *r_vol = volume; +} + +void BKE_rigidbody_calc_center_of_mass(Object *ob, float r_com[3]) +{ + RigidBodyOb *rbo = ob->rigidbody_object; + + float size[3] = {1.0f, 1.0f, 1.0f}; + float height = 1.0f; + + zero_v3(r_com); + + /* if automatically determining dimensions, use the Object's boundbox + * - assume that all quadrics are standing upright on local z-axis + * - assume even distribution of mass around the Object's pivot + * (i.e. Object pivot is centralized in boundbox) + * - boundbox gives full width + */ + // XXX: all dimensions are auto-determined now... later can add stored settings for this + BKE_object_dimensions_get(ob, size); + + /* calculate volume as appropriate */ + switch (rbo->shape) { + case RB_SHAPE_BOX: + case RB_SHAPE_SPHERE: + case RB_SHAPE_CAPSULE: + case RB_SHAPE_CYLINDER: + break; + + case RB_SHAPE_CONE: + /* take radius as largest x/y dimension, and height as z-dimension */ + height = size[2]; + /* cone is geometrically centered on the median, + * center of mass is 1/4 up from the base + */ + r_com[2] = -0.25f * height; + break; + + case RB_SHAPE_CONVEXH: + case RB_SHAPE_TRIMESH: + { + if (ob->type == OB_MESH) { + DerivedMesh *dm = rigidbody_get_mesh(ob); + MVert *mvert; + MFace *mface; + int totvert, totface; + + /* ensure mesh validity, then grab data */ + if (dm == NULL) + return; + + DM_ensure_tessface(dm); + + mvert = dm->getVertArray(dm); + totvert = dm->getNumVerts(dm); + mface = dm->getTessFaceArray(dm); + totface = dm->getNumTessFaces(dm); + + if (totvert > 0 && totface > 0) { + BKE_mesh_calc_volume(mvert, totvert, mface, totface, NULL, r_com); + } + + /* cleanup temp data */ + if (ob->rigidbody_object->mesh_source == RBO_MESH_BASE) { + dm->release(dm); + } + } + break; + } + +#if 0 // XXX: not defined yet + case RB_SHAPE_COMPOUND: + volume = 0.0f; + break; +#endif + } +} + +/* --------------------- */ + /** * Create physics sim representation of object given RigidBody settings * @@ -543,7 +720,7 @@ static void rigidbody_validate_sim_constraint(RigidBodyWorld *rbw, Object *ob, b return; } - if (ELEM4(NULL, rbc->ob1, rbc->ob1->rigidbody_object, rbc->ob2, rbc->ob2->rigidbody_object)) { + if (ELEM(NULL, rbc->ob1, rbc->ob1->rigidbody_object, rbc->ob2, rbc->ob2->rigidbody_object)) { if (rbc->physics_constraint) { RB_dworld_remove_constraint(rbw->physics_world, rbc->physics_constraint); RB_constraint_delete(rbc->physics_constraint); @@ -1414,6 +1591,8 @@ struct RigidBodyOb *BKE_rigidbody_copy_object(Object *ob) { return NULL; } struct RigidBodyCon *BKE_rigidbody_copy_constraint(Object *ob) { return NULL; } void BKE_rigidbody_relink_constraint(RigidBodyCon *rbc) {} void BKE_rigidbody_validate_sim_world(Scene *scene, RigidBodyWorld *rbw, bool rebuild) {} +void BKE_rigidbody_calc_volume(Object *ob, float *r_vol) { if (r_vol) *r_vol = 0.0f; } +void BKE_rigidbody_calc_center_of_mass(Object *ob, float r_com[3]) { zero_v3(r_com); } struct RigidBodyWorld *BKE_rigidbody_create_world(Scene *scene) { return NULL; } struct RigidBodyWorld *BKE_rigidbody_world_copy(RigidBodyWorld *rbw) { return NULL; } void BKE_rigidbody_world_groups_relink(struct RigidBodyWorld *rbw) {} diff --git a/source/blender/blenkernel/intern/sca.c b/source/blender/blenkernel/intern/sca.c index 1310162483e..4be75344133 100644 --- a/source/blender/blenkernel/intern/sca.c +++ b/source/blender/blenkernel/intern/sca.c @@ -392,6 +392,7 @@ void init_actuator(bActuator *act) bSteeringActuator *sta; bArmatureActuator *arma; bMouseActuator *ma; + bEditObjectActuator *eoa; if (act->data) MEM_freeN(act->data); act->data= NULL; @@ -430,6 +431,9 @@ void init_actuator(bActuator *act) break; case ACT_EDIT_OBJECT: act->data= MEM_callocN(sizeof(bEditObjectActuator), "editobact"); + eoa = act->data; + eoa->upflag= ACT_TRACK_UP_Z; + eoa->trackflag= ACT_TRACK_TRAXIS_Y; break; case ACT_CONSTRAINT: act->data= MEM_callocN(sizeof(bConstraintActuator), "cons act"); diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index f8ce31f1b8a..eb98e381222 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -39,6 +39,7 @@ #include "DNA_anim_types.h" #include "DNA_group_types.h" #include "DNA_linestyle_types.h" +#include "DNA_mesh_types.h" #include "DNA_node_types.h" #include "DNA_object_types.h" #include "DNA_rigidbody_types.h" @@ -46,6 +47,8 @@ #include "DNA_screen_types.h" #include "DNA_sequence_types.h" #include "DNA_space_types.h" +#include "DNA_view3d_types.h" +#include "DNA_windowmanager_types.h" #include "BLI_math.h" #include "BLI_blenlib.h" @@ -62,6 +65,7 @@ #include "BKE_action.h" #include "BKE_colortools.h" #include "BKE_depsgraph.h" +#include "BKE_editmesh.h" #include "BKE_fcurve.h" #include "BKE_freestyle.h" #include "BKE_global.h" @@ -78,6 +82,7 @@ #include "BKE_scene.h" #include "BKE_sequencer.h" #include "BKE_sound.h" +#include "BKE_unit.h" #include "BKE_world.h" #include "RE_engine.h" @@ -86,6 +91,8 @@ #include "IMB_colormanagement.h" +#include "bmesh.h" + //XXX #include "BIF_previewrender.h" //XXX #include "BIF_editseq.h" @@ -253,6 +260,7 @@ Scene *BKE_scene_copy(Scene *sce, int type) BKE_paint_copy(&ts->imapaint.paint, &ts->imapaint.paint); ts->imapaint.paintcursor = NULL; + id_us_plus((ID *)ts->imapaint.stencil); ts->particle.paintcursor = NULL; } @@ -510,6 +518,8 @@ Scene *BKE_scene_add(Main *bmain, const char *name) sce->r.border.ymin = 0.0f; sce->r.border.xmax = 1.0f; sce->r.border.ymax = 1.0f; + + sce->r.preview_start_resolution = 64; sce->toolsettings = MEM_callocN(sizeof(struct ToolSettings), "Tool Settings Struct"); sce->toolsettings->doublimit = 0.001; @@ -553,6 +563,8 @@ Scene *BKE_scene_add(Main *bmain, const char *name) sce->toolsettings->proportional_size = 1.0f; sce->toolsettings->imapaint.paint.flags |= PAINT_SHOW_BRUSH; + sce->toolsettings->imapaint.normal_angle = 80; + sce->toolsettings->imapaint.seam_bleed = 2; sce->physics_settings.gravity[0] = 0.0f; sce->physics_settings.gravity[1] = 0.0f; @@ -719,14 +731,14 @@ void BKE_scene_set_background(Main *bmain, Scene *scene) /* called from creator.c */ Scene *BKE_scene_set_name(Main *bmain, const char *name) { - Scene *sce = (Scene *)BKE_libblock_find_name(ID_SCE, name); + Scene *sce = (Scene *)BKE_libblock_find_name_ex(bmain, ID_SCE, name); if (sce) { BKE_scene_set_background(bmain, sce); - printf("Scene switch: '%s' in file: '%s'\n", name, G.main->name); + printf("Scene switch: '%s' in file: '%s'\n", name, bmain->name); return sce; } - printf("Can't find scene: '%s' in file: '%s'\n", name, G.main->name); + printf("Can't find scene: '%s' in file: '%s'\n", name, bmain->name); return NULL; } @@ -804,9 +816,7 @@ void BKE_scene_unlink(Main *bmain, Scene *sce, Scene *newsce) BKE_libblock_free(bmain, sce); } -/* used by metaballs - * doesn't return the original duplicated object, only dupli's - */ +/* Used by metaballs, return *all* objects (including duplis) existing in the scene (including scene's sets) */ int BKE_scene_base_iter_next(EvaluationContext *eval_ctx, SceneBaseIter *iter, Scene **scene, int val, Base **base, Object **ob) { @@ -817,11 +827,12 @@ int BKE_scene_base_iter_next(EvaluationContext *eval_ctx, SceneBaseIter *iter, iter->phase = F_START; iter->dupob = NULL; iter->duplilist = NULL; + iter->dupli_refob = NULL; } else { /* run_again is set when a duplilist has been ended */ while (run_again) { - run_again = 0; + run_again = false; /* the first base */ if (iter->phase == F_START) { @@ -879,34 +890,46 @@ int BKE_scene_base_iter_next(EvaluationContext *eval_ctx, SceneBaseIter *iter, iter->dupob = iter->duplilist->first; - if (!iter->dupob) + if (!iter->dupob) { free_object_duplilist(iter->duplilist); + iter->duplilist = NULL; + } + iter->dupli_refob = NULL; } } } /* handle dupli's */ if (iter->dupob) { - - copy_m4_m4(iter->omat, iter->dupob->ob->obmat); - copy_m4_m4(iter->dupob->ob->obmat, iter->dupob->mat); - (*base)->flag |= OB_FROMDUPLI; *ob = iter->dupob->ob; iter->phase = F_DUPLI; - + + if (iter->dupli_refob != *ob) { + if (iter->dupli_refob) { + /* Restore previous object's real matrix. */ + copy_m4_m4(iter->dupli_refob->obmat, iter->omat); + } + /* Backup new object's real matrix. */ + iter->dupli_refob = *ob; + copy_m4_m4(iter->omat, iter->dupli_refob->obmat); + } + copy_m4_m4((*ob)->obmat, iter->dupob->mat); + iter->dupob = iter->dupob->next; } else if (iter->phase == F_DUPLI) { iter->phase = F_SCENE; (*base)->flag &= ~OB_FROMDUPLI; - for (iter->dupob = iter->duplilist->first; iter->dupob; iter->dupob = iter->dupob->next) { - copy_m4_m4(iter->dupob->ob->obmat, iter->omat); + if (iter->dupli_refob) { + /* Restore last object's real matrix. */ + copy_m4_m4(iter->dupli_refob->obmat, iter->omat); + iter->dupli_refob = NULL; } free_object_duplilist(iter->duplilist); iter->duplilist = NULL; - run_again = 1; + run_again = true; } } } @@ -1118,11 +1141,6 @@ void BKE_scene_frame_set(struct Scene *scene, double cfra) double intpart; scene->r.subframe = modf(cfra, &intpart); scene->r.cfra = (int)intpart; - - if (cfra < 0.0) { - scene->r.cfra -= 1; - scene->r.subframe = 1.0f + scene->r.subframe; - } } /* drivers support/hacks @@ -1541,6 +1559,53 @@ static void scene_update_tagged_recursive(EvaluationContext *eval_ctx, Main *bma } +static bool check_rendered_viewport_visible(Main *bmain) +{ + wmWindowManager *wm = bmain->wm.first; + wmWindow *window; + for (window = wm->windows.first; window != NULL; window = window->next) { + bScreen *screen = window->screen; + ScrArea *area; + for (area = screen->areabase.first; area != NULL; area = area->next) { + View3D *v3d = area->spacedata.first; + if (area->spacetype != SPACE_VIEW3D) { + continue; + } + if (v3d->drawtype == OB_RENDER) { + return true; + } + } + } + return false; +} + +static void prepare_mesh_for_viewport_render(Main *bmain, Scene *scene) +{ + /* This is needed to prepare mesh to be used by the render + * engine from the viewport rendering. We do loading here + * so all the objects which shares the same mesh datablock + * are nicely tagged for update and updated. + * + * This makes it so viewport render engine doesn't need to + * call loading of the edit data for the mesh objects. + */ + + Object *obedit = scene->obedit; + if (obedit) { + Mesh *mesh = obedit->data; + /* TODO(sergey): Check object recalc flags as well? */ + if ((obedit->type == OB_MESH) && + (mesh->id.flag & (LIB_ID_RECALC | LIB_ID_RECALC_DATA))) + { + if (check_rendered_viewport_visible(bmain)) { + BMesh *bm = mesh->edit_btmesh->bm; + BM_mesh_bm_to_me(bm, mesh, false); + DAG_id_tag_update(&mesh->id, 0); + } + } + } +} + void BKE_scene_update_tagged(EvaluationContext *eval_ctx, Main *bmain, Scene *scene) { Scene *sce_iter; @@ -1552,6 +1617,9 @@ void BKE_scene_update_tagged(EvaluationContext *eval_ctx, Main *bmain, Scene *sc for (sce_iter = scene; sce_iter; sce_iter = sce_iter->set) DAG_scene_relations_update(bmain, sce_iter); + /* flush editing data if needed */ + prepare_mesh_for_viewport_render(bmain, scene); + /* flush recalc flags to dependencies */ DAG_ids_flush_tagged(bmain); @@ -1832,6 +1900,12 @@ bool BKE_scene_use_new_shading_nodes(Scene *scene) return (type && type->flag & RE_USE_SHADING_NODES); } +bool BKE_scene_uses_blender_internal(struct Scene *scene) +{ + return strcmp("BLENDER_RENDER", scene->r.engine) == 0; +} + + void BKE_scene_base_flag_to_objects(struct Scene *scene) { Base *base = scene->base.first; @@ -1903,3 +1977,29 @@ int BKE_scene_num_threads(const Scene *scene) { return BKE_render_num_threads(&scene->r); } + +/* Apply the needed correction factor to value, based on unit_type (only length-related are affected currently) + * and unit->scale_length. + */ +double BKE_scene_unit_scale(const UnitSettings *unit, const int unit_type, double value) +{ + if (unit->system == USER_UNIT_NONE) { + /* Never apply scale_length when not using a unit setting! */ + return value; + } + + switch (unit_type) { + case B_UNIT_LENGTH: + return value * (double)unit->scale_length; + case B_UNIT_CAMERA: + return value * (double)unit->scale_length; + case B_UNIT_AREA: + return value * pow(unit->scale_length, 2); + case B_UNIT_VOLUME: + return value * pow(unit->scale_length, 3); + case B_UNIT_MASS: + return value * pow(unit->scale_length, 3); + default: + return value; + } +} diff --git a/source/blender/blenkernel/intern/screen.c b/source/blender/blenkernel/intern/screen.c index 9d40ee6e667..b2296151cf7 100644 --- a/source/blender/blenkernel/intern/screen.c +++ b/source/blender/blenkernel/intern/screen.c @@ -425,6 +425,32 @@ ScrArea *BKE_screen_find_big_area(bScreen *sc, const int spacetype, const short return big; } +/** + * Utility function to get the active layer to use when adding new objects. + */ +unsigned int BKE_screen_view3d_layer_active_ex(const View3D *v3d, const Scene *scene, bool use_localvd) +{ + unsigned int lay; + if ((v3d == NULL) || (v3d->scenelock && !v3d->localvd)) { + lay = scene->layact; + } + else { + lay = v3d->layact; + } + + if (use_localvd) { + if (v3d && v3d->localvd) { + lay |= v3d->lay; + } + } + + return lay; +} +unsigned int BKE_screen_view3d_layer_active(const struct View3D *v3d, const struct Scene *scene) +{ + return BKE_screen_view3d_layer_active_ex(v3d, scene, true); +} + void BKE_screen_view3d_sync(View3D *v3d, struct Scene *scene) { int bit; diff --git a/source/blender/blenkernel/intern/seqeffects.c b/source/blender/blenkernel/intern/seqeffects.c index 2b14b92217b..d2dc9da47f9 100644 --- a/source/blender/blenkernel/intern/seqeffects.c +++ b/source/blender/blenkernel/intern/seqeffects.c @@ -52,6 +52,11 @@ #include "RNA_access.h" +/* TODO(sergey): Could be considered a bad level call, but + * need this for gaussian table. + */ +#include "RE_pipeline.h" + static void slice_get_byte_buffers(const SeqRenderData *context, const ImBuf *ibuf1, const ImBuf *ibuf2, const ImBuf *ibuf3, const ImBuf *out, int start_line, unsigned char **rect1, unsigned char **rect2, unsigned char **rect3, unsigned char **rect_out) @@ -2579,6 +2584,295 @@ static void do_overdrop_effect(const SeqRenderData *context, Sequence *UNUSED(se } } +/*********************** Gaussian Blur *************************/ + +/* NOTE: This gaussian blur implementation accumulates values in the square + * kernel rather that doing X direction and then Y direction because of the + * lack of using multiple-staged filters. + * + * Once we can we'll implement a way to apply filter as multiple stages we + * can optimize hell of a lot in here. + */ + +static void init_gaussian_blur_effect(Sequence *seq) +{ + if (seq->effectdata) + MEM_freeN(seq->effectdata); + + seq->effectdata = MEM_callocN(sizeof(WipeVars), "wipevars"); +} + +static int num_inputs_gaussian_blur(void) +{ + return 1; +} + +static void free_gaussian_blur_effect(Sequence *seq) +{ + if (seq->effectdata) + MEM_freeN(seq->effectdata); + + seq->effectdata = NULL; +} + +static void copy_gaussian_blur_effect(Sequence *dst, Sequence *src) +{ + dst->effectdata = MEM_dupallocN(src->effectdata); +} + +static int early_out_gaussian_blur(Sequence *seq, float UNUSED(facf0), float UNUSED(facf1)) +{ + GaussianBlurVars *data = seq->effectdata; + if (data->size_x == 0.0f && data->size_y == 0) { + return EARLY_USE_INPUT_1; + } + return EARLY_DO_EFFECT; +} + +/* TODO(sergey): De-duplicate with compositor. */ +static float *make_gaussian_blur_kernel(float rad, int size) +{ + float *gausstab, sum, val; + float fac; + int i, n; + + n = 2 * size + 1; + + gausstab = (float *)MEM_mallocN(sizeof(float) * n, __func__); + + sum = 0.0f; + fac = (rad > 0.0f ? 1.0f / rad : 0.0f); + for (i = -size; i <= size; i++) { + val = RE_filter_value(R_FILTER_GAUSS, (float)i * fac); + sum += val; + gausstab[i + size] = val; + } + + sum = 1.0f / sum; + for (i = 0; i < n; i++) + gausstab[i] *= sum; + + return gausstab; +} + +static void do_gaussian_blur_effect_byte(Sequence *seq, + int start_line, + int x, int y, + int frame_width, int frame_height, + unsigned char *rect, + unsigned char *out) +{ +#define INDEX(_x, _y) (((_y) * (x) + (_x)) * 4) + GaussianBlurVars *data = seq->effectdata; + const int size_x = (int) (data->size_x + 0.5f), + size_y = (int) (data->size_y + 0.5f); + int i, j; + + /* Make gaussian weight tabke. */ + float *gausstab_x, *gausstab_y; + gausstab_x = make_gaussian_blur_kernel(data->size_x, size_x); + if (data->size_x == data->size_y) { + gausstab_y = gausstab_x; + } + else { + gausstab_y = make_gaussian_blur_kernel(data->size_y, size_y); + } + + for (i = 0; i < y; ++i) { + for (j = 0; j < x; ++j) { + int out_index = INDEX(j, i); + int current_x, current_y; + float accum[4] = {0.0f, 0.0f, 0.0f, 0.0f}; + float accum_weight = 0.0f; + for (current_y = i - size_y; + current_y <= i + size_y; + ++current_y) + { + if (current_y < -start_line || + current_y + start_line >= frame_height) + { + /* Out of bounds. */ + continue; + } + + for (current_x = j - size_x; + current_x <= j + size_x; + ++current_x) + { + float weight; + int index = INDEX(current_x, current_y + start_line); + if (current_x < 0 || current_x >= frame_width) { + /* Out of bounds. */ + continue; + } + BLI_assert(index >= 0); + BLI_assert(index < frame_width * frame_height * 4); + + if (size_x != 0 && size_y != 0) { + weight = gausstab_x[current_x - j + size_x] * + gausstab_y[current_y - i + size_y]; + } + else if (size_x == 0) { + weight = gausstab_y[current_y - i + size_y]; + } + else { + weight = gausstab_x[current_x - j + size_x]; + } + accum[0] += rect[index] * weight; + accum[1] += rect[index + 1] * weight; + accum[2] += rect[index + 2] * weight; + accum[3] += rect[index + 3] * weight; + accum_weight += weight; + } + } + out[out_index + 0] = accum[0] / accum_weight; + out[out_index + 1] = accum[1] / accum_weight; + out[out_index + 2] = accum[2] / accum_weight; + out[out_index + 3] = accum[3] / accum_weight; + } + } + + MEM_freeN(gausstab_x); + if (gausstab_x != gausstab_y) { + MEM_freeN(gausstab_y); + } +#undef INDEX +} + +static void do_gaussian_blur_effect_float(Sequence *seq, + int start_line, + int x, int y, + int frame_width, int frame_height, + float *rect, + float *out) +{ +#define INDEX(_x, _y) (((_y) * (x) + (_x)) * 4) + GaussianBlurVars *data = seq->effectdata; + const int size_x = (int) (data->size_x + 0.5f), + size_y = (int) (data->size_y + 0.5f); + int i, j; + + /* Make gaussian weight tabke. */ + float *gausstab_x, *gausstab_y; + gausstab_x = make_gaussian_blur_kernel(data->size_x, size_x); + if (data->size_x == data->size_y) { + gausstab_y = gausstab_x; + } + else { + gausstab_y = make_gaussian_blur_kernel(data->size_y, size_y); + } + + for (i = 0; i < y; ++i) { + for (j = 0; j < x; ++j) { + int out_index = INDEX(j, i); + int current_x, current_y; + float accum[4] = {0.0f, 0.0f, 0.0f, 0.0f}; + float accum_weight = 0.0f; + for (current_y = i - size_y; + current_y <= i + size_y; + ++current_y) + { + float weight; + if (current_y < -start_line || + current_y + start_line >= frame_height) + { + /* Out of bounds. */ + continue; + } + + for (current_x = j - size_x; + current_x <= j + size_x; + ++current_x) + { + int index = INDEX(current_x, current_y + start_line); + if (current_x < 0 || current_x >= frame_width) { + /* Out of bounds. */ + continue; + } + + if (size_x != 0 && size_y != 0) { + weight = gausstab_x[current_x - j + size_x] * + gausstab_y[current_y - i + size_y]; + } + else if (size_x == 0) { + weight = gausstab_y[current_y - i + size_y]; + } + else { + weight = gausstab_x[current_x - j + size_x]; + } + madd_v4_v4fl(accum, &rect[index], weight); + accum_weight += weight; + } + } + mul_v4_v4fl(&out[out_index], accum, 1.0f / accum_weight); + } + } + + MEM_freeN(gausstab_x); + if (gausstab_x != gausstab_y) { + MEM_freeN(gausstab_y); + } +#undef INDEX +} + +static void do_gaussian_blur_effect(const SeqRenderData *context, + Sequence *seq, + float UNUSED(cfra), + float UNUSED(facf0), + float UNUSED(facf1), + ImBuf *ibuf1, + ImBuf *ibuf2, + ImBuf *UNUSED(ibuf3), + int start_line, + int total_lines, + ImBuf *out) +{ + if (out->rect_float) { + float *rect1 = NULL, *rect2 = NULL, *rect_out = NULL; + + slice_get_float_buffers(context, + ibuf1, ibuf2, + NULL, + out, + start_line, + &rect1, + &rect2, + NULL, + &rect_out); + + do_gaussian_blur_effect_float(seq, + start_line, + context->rectx, + total_lines, + context->rectx, + context->recty, + ibuf1->rect_float, + rect_out); + } + else { + unsigned char *rect1 = NULL, *rect2 = NULL, *rect_out = NULL; + + slice_get_byte_buffers(context, + ibuf1, ibuf2, + NULL, + out, + start_line, + &rect1, + &rect2, + NULL, + &rect_out); + + do_gaussian_blur_effect_byte(seq, + start_line, + context->rectx, + total_lines, + context->rectx, + context->recty, + (unsigned char *) ibuf1->rect, + rect_out); + } +} + /*********************** sequence effect factory *************************/ static void init_noop(Sequence *UNUSED(seq)) @@ -2767,6 +3061,15 @@ static struct SeqEffectHandle get_sequence_effect_impl(int seq_type) rval.early_out = early_out_adjustment; rval.execute = do_adjustment; break; + case SEQ_TYPE_GAUSSIAN_BLUR: + rval.multithreaded = true; + rval.init = init_gaussian_blur_effect; + rval.num_inputs = num_inputs_gaussian_blur; + rval.free = free_gaussian_blur_effect; + rval.copy = copy_gaussian_blur_effect; + rval.early_out = early_out_gaussian_blur; + rval.execute_slice = do_gaussian_blur_effect; + break; } return rval; diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c index f5efe04951f..c9647b05ce7 100644 --- a/source/blender/blenkernel/intern/sequencer.c +++ b/source/blender/blenkernel/intern/sequencer.c @@ -758,7 +758,7 @@ void BKE_sequence_reload_new_file(Scene *scene, Sequence *seq, const bool lock_r int prev_startdisp = 0, prev_enddisp = 0; /* note: don't rename the strip, will break animation curves */ - if (ELEM7(seq->type, + if (ELEM(seq->type, SEQ_TYPE_MOVIE, SEQ_TYPE_IMAGE, SEQ_TYPE_SOUND_RAM, SEQ_TYPE_SCENE, SEQ_TYPE_META, SEQ_TYPE_MOVIECLIP, SEQ_TYPE_MASK) == 0) { @@ -994,28 +994,29 @@ void BKE_sequence_base_unique_name_recursive(ListBase *seqbasep, Sequence *seq) static const char *give_seqname_by_type(int type) { switch (type) { - case SEQ_TYPE_META: return "Meta"; - case SEQ_TYPE_IMAGE: return "Image"; - case SEQ_TYPE_SCENE: return "Scene"; - case SEQ_TYPE_MOVIE: return "Movie"; - case SEQ_TYPE_MOVIECLIP: return "Clip"; - case SEQ_TYPE_MASK: return "Mask"; - case SEQ_TYPE_SOUND_RAM: return "Audio"; - case SEQ_TYPE_CROSS: return "Cross"; - case SEQ_TYPE_GAMCROSS: return "Gamma Cross"; - case SEQ_TYPE_ADD: return "Add"; - case SEQ_TYPE_SUB: return "Sub"; - case SEQ_TYPE_MUL: return "Mul"; - case SEQ_TYPE_ALPHAOVER: return "Alpha Over"; - case SEQ_TYPE_ALPHAUNDER: return "Alpha Under"; - case SEQ_TYPE_OVERDROP: return "Over Drop"; - case SEQ_TYPE_WIPE: return "Wipe"; - case SEQ_TYPE_GLOW: return "Glow"; - case SEQ_TYPE_TRANSFORM: return "Transform"; - case SEQ_TYPE_COLOR: return "Color"; - case SEQ_TYPE_MULTICAM: return "Multicam"; - case SEQ_TYPE_ADJUSTMENT: return "Adjustment"; - case SEQ_TYPE_SPEED: return "Speed"; + case SEQ_TYPE_META: return "Meta"; + case SEQ_TYPE_IMAGE: return "Image"; + case SEQ_TYPE_SCENE: return "Scene"; + case SEQ_TYPE_MOVIE: return "Movie"; + case SEQ_TYPE_MOVIECLIP: return "Clip"; + case SEQ_TYPE_MASK: return "Mask"; + case SEQ_TYPE_SOUND_RAM: return "Audio"; + case SEQ_TYPE_CROSS: return "Cross"; + case SEQ_TYPE_GAMCROSS: return "Gamma Cross"; + case SEQ_TYPE_ADD: return "Add"; + case SEQ_TYPE_SUB: return "Sub"; + case SEQ_TYPE_MUL: return "Mul"; + case SEQ_TYPE_ALPHAOVER: return "Alpha Over"; + case SEQ_TYPE_ALPHAUNDER: return "Alpha Under"; + case SEQ_TYPE_OVERDROP: return "Over Drop"; + case SEQ_TYPE_WIPE: return "Wipe"; + case SEQ_TYPE_GLOW: return "Glow"; + case SEQ_TYPE_TRANSFORM: return "Transform"; + case SEQ_TYPE_COLOR: return "Color"; + case SEQ_TYPE_MULTICAM: return "Multicam"; + case SEQ_TYPE_ADJUSTMENT: return "Adjustment"; + case SEQ_TYPE_SPEED: return "Speed"; + case SEQ_TYPE_GAUSSIAN_BLUR: return "Gaussian Blur"; default: return NULL; } @@ -2224,7 +2225,7 @@ static ImBuf *seq_render_effect_execute_threaded(struct SeqEffectHandle *sh, con init_data.out = out; IMB_processor_apply_threaded(out->y, sizeof(RenderEffectThread), &init_data, - render_effect_execute_init_handle, render_effect_execute_do_thread); + render_effect_execute_init_handle, render_effect_execute_do_thread); return out; } @@ -2808,7 +2809,7 @@ static ImBuf *seq_render_strip(const SeqRenderData *context, Sequence *seq, floa float nr = give_stripelem_index(seq, cfra); /* all effects are handled similarly with the exception of speed effect */ int type = (seq->type & SEQ_TYPE_EFFECT && seq->type != SEQ_TYPE_SPEED) ? SEQ_TYPE_EFFECT : seq->type; - bool is_preprocessed = !ELEM3(type, SEQ_TYPE_IMAGE, SEQ_TYPE_MOVIE, SEQ_TYPE_SCENE); + bool is_preprocessed = !ELEM(type, SEQ_TYPE_IMAGE, SEQ_TYPE_MOVIE, SEQ_TYPE_SCENE); ibuf = BKE_sequencer_cache_get(context, seq, cfra, SEQ_STRIPELEM_IBUF); @@ -2875,7 +2876,7 @@ static bool seq_must_swap_input_in_blend_mode(Sequence *seq) /* bad hack, to fix crazy input ordering of * those two effects */ - if (ELEM3(seq->blend_mode, SEQ_TYPE_ALPHAOVER, SEQ_TYPE_ALPHAUNDER, SEQ_TYPE_OVERDROP)) { + if (ELEM(seq->blend_mode, SEQ_TYPE_ALPHAOVER, SEQ_TYPE_ALPHAUNDER, SEQ_TYPE_OVERDROP)) { swap_input = true; } @@ -2960,7 +2961,7 @@ static ImBuf *seq_render_strip_stack(const SeqRenderData *context, ListBase *seq /* Some of the blend modes are unclear how to apply with only single input, * or some of them will just produce an empty result.. */ - if (ELEM3(seq->blend_mode, SEQ_BLEND_REPLACE, SEQ_TYPE_CROSS, SEQ_TYPE_ALPHAOVER)) { + if (ELEM(seq->blend_mode, SEQ_BLEND_REPLACE, SEQ_TYPE_CROSS, SEQ_TYPE_ALPHAOVER)) { int early_out; if (seq->blend_mode == SEQ_BLEND_REPLACE) { early_out = EARLY_NO_INPUT; @@ -3512,16 +3513,28 @@ bool BKE_sequence_single_check(Sequence *seq) } /* check if the selected seq's reference unselected seq's */ -bool BKE_sequence_base_isolated_sel_check(ListBase *seqbase) +bool BKE_sequence_base_isolated_sel_check(ListBase *seqbase, bool one_only) { Sequence *seq; - /* is there more than 1 select */ + /* is there a valid selection select */ bool ok = false; + /* is there one selected already? */ + bool first = false; for (seq = seqbase->first; seq; seq = seq->next) { if (seq->flag & SELECT) { - ok = true; - break; + if (one_only) { + ok = true; + break; + } + else { + if (first) { + ok = true; + break; + } + else + first = true; + } } } @@ -3688,7 +3701,7 @@ Sequence *BKE_sequencer_foreground_frame_get(Scene *scene, int frame) if (seq->flag & SEQ_MUTE || seq->startdisp > frame || seq->enddisp <= frame) continue; /* only use elements you can see - not */ - if (ELEM5(seq->type, SEQ_TYPE_IMAGE, SEQ_TYPE_META, SEQ_TYPE_SCENE, SEQ_TYPE_MOVIE, SEQ_TYPE_COLOR)) { + if (ELEM(seq->type, SEQ_TYPE_IMAGE, SEQ_TYPE_META, SEQ_TYPE_SCENE, SEQ_TYPE_MOVIE, SEQ_TYPE_COLOR)) { if (seq->machine > best_machine) { best_seq = seq; best_machine = seq->machine; diff --git a/source/blender/blenkernel/intern/shrinkwrap.c b/source/blender/blenkernel/intern/shrinkwrap.c index e2cc7b84f95..d2a4d15a2c6 100644 --- a/source/blender/blenkernel/intern/shrinkwrap.c +++ b/source/blender/blenkernel/intern/shrinkwrap.c @@ -50,6 +50,7 @@ #include "BKE_lattice.h" #include "BKE_deform.h" +#include "BKE_mesh.h" /* for OMP limits. */ #include "BKE_subsurf.h" #include "BKE_editmesh.h" @@ -65,57 +66,6 @@ /* Util macros */ #define OUT_OF_MEMORY() ((void)printf("Shrinkwrap: Out of memory\n")) -/* get derived mesh */ -/* TODO is anyfunction that does this? returning the derivedFinal without we caring if its in edit mode or not? */ -DerivedMesh *object_get_derived_final(Object *ob, bool for_render) -{ - Mesh *me = ob->data; - BMEditMesh *em = me->edit_btmesh; - - if (for_render) { - /* TODO(sergey): use proper derived render here in the future. */ - return ob->derivedFinal; - } - - if (em) { - DerivedMesh *dm = em->derivedFinal; - return dm; - } - - return ob->derivedFinal; -} - -/* Space transform */ -void space_transform_from_matrixs(SpaceTransform *data, float local[4][4], float target[4][4]) -{ - float itarget[4][4]; - invert_m4_m4(itarget, target); - mul_m4_m4m4(data->local2target, itarget, local); - invert_m4_m4(data->target2local, data->local2target); -} - -void space_transform_apply(const SpaceTransform *data, float co[3]) -{ - mul_v3_m4v3(co, ((SpaceTransform *)data)->local2target, co); -} - -void space_transform_invert(const SpaceTransform *data, float co[3]) -{ - mul_v3_m4v3(co, ((SpaceTransform *)data)->target2local, co); -} - -static void space_transform_apply_normal(const SpaceTransform *data, float no[3]) -{ - mul_mat3_m4_v3(((SpaceTransform *)data)->local2target, no); - normalize_v3(no); /* TODO: could we just determine de scale value from the matrix? */ -} - -static void space_transform_invert_normal(const SpaceTransform *data, float no[3]) -{ - mul_mat3_m4_v3(((SpaceTransform *)data)->target2local, no); - normalize_v3(no); /* TODO: could we just determine de scale value from the matrix? */ -} - /* * Shrinkwrap to the nearest vertex * @@ -135,12 +85,12 @@ static void shrinkwrap_calc_nearest_vertex(ShrinkwrapCalcData *calc) OUT_OF_MEMORY(); return; } - + /* Setup nearest */ nearest.index = -1; nearest.dist_sq = FLT_MAX; #ifndef __APPLE__ -#pragma omp parallel for default(none) private(i) firstprivate(nearest) shared(treeData, calc) schedule(static) +#pragma omp parallel for default(none) private(i) firstprivate(nearest) shared(treeData, calc) schedule(static) if(calc->numVerts > BKE_MESH_OMP_LIMIT) #endif for (i = 0; i < calc->numVerts; ++i) { float *co = calc->vertexCos[i]; @@ -158,7 +108,7 @@ static void shrinkwrap_calc_nearest_vertex(ShrinkwrapCalcData *calc) else { copy_v3_v3(tmp_co, co); } - space_transform_apply(&calc->local2target, tmp_co); + BLI_space_transform_apply(&calc->local2target, tmp_co); /* Use local proximity heuristics (to reduce the nearest search) * @@ -184,7 +134,7 @@ static void shrinkwrap_calc_nearest_vertex(ShrinkwrapCalcData *calc) /* Convert the coordinates back to mesh coordinates */ copy_v3_v3(tmp_co, nearest.co); - space_transform_invert(&calc->local2target, tmp_co); + BLI_space_transform_invert(&calc->local2target, tmp_co); interp_v3_v3v3(co, co, tmp_co, weight); /* linear interpolation */ } @@ -223,11 +173,11 @@ bool BKE_shrinkwrap_project_normal( /* Apply space transform (TODO readjust dist) */ if (transf) { copy_v3_v3(tmp_co, vert); - space_transform_apply(transf, tmp_co); + BLI_space_transform_apply(transf, tmp_co); co = tmp_co; copy_v3_v3(tmp_no, dir); - space_transform_apply_normal(transf, tmp_no); + BLI_space_transform_apply_normal(transf, tmp_no); no = tmp_no; #ifdef USE_DIST_CORRECT @@ -246,7 +196,7 @@ bool BKE_shrinkwrap_project_normal( if (hit_tmp.index != -1) { /* invert the normal first so face culling works on rotated objects */ if (transf) { - space_transform_invert_normal(transf, hit_tmp.no); + BLI_space_transform_invert_normal(transf, hit_tmp.no); } if (options & (MOD_SHRINKWRAP_CULL_TARGET_FRONTFACE | MOD_SHRINKWRAP_CULL_TARGET_BACKFACE)) { @@ -261,7 +211,7 @@ bool BKE_shrinkwrap_project_normal( if (transf) { /* Inverting space transform (TODO make coeherent with the initial dist readjust) */ - space_transform_invert(transf, hit_tmp.co); + BLI_space_transform_invert(transf, hit_tmp.co); #ifdef USE_DIST_CORRECT hit_tmp.dist = len_v3v3(vert, hit_tmp.co); #endif @@ -326,7 +276,7 @@ static void shrinkwrap_calc_normal_projection(ShrinkwrapCalcData *calc, bool for auxMesh = object_get_derived_final(calc->smd->auxTarget, for_render); if (!auxMesh) return; - SPACE_TRANSFORM_SETUP(&local2aux, calc->ob, calc->smd->auxTarget); + BLI_SPACE_TRANSFORM_SETUP(&local2aux, calc->ob, calc->smd->auxTarget); } /* After sucessufuly build the trees, start projection vertexs */ @@ -335,7 +285,7 @@ static void shrinkwrap_calc_normal_projection(ShrinkwrapCalcData *calc, bool for { #ifndef __APPLE__ -#pragma omp parallel for private(i, hit) schedule(static) +#pragma omp parallel for private(i, hit) schedule(static) if (calc->numVerts > BKE_MESH_OMP_LIMIT) #endif for (i = 0; i < calc->numVerts; ++i) { float *co = calc->vertexCos[i]; @@ -445,7 +395,7 @@ static void shrinkwrap_calc_nearest_surface_point(ShrinkwrapCalcData *calc) /* Find the nearest vertex */ #ifndef __APPLE__ -#pragma omp parallel for default(none) private(i) firstprivate(nearest) shared(calc, treeData) schedule(static) +#pragma omp parallel for default(none) private(i) firstprivate(nearest) shared(calc, treeData) schedule(static) if(calc->numVerts > BKE_MESH_OMP_LIMIT) #endif for (i = 0; i < calc->numVerts; ++i) { float *co = calc->vertexCos[i]; @@ -460,7 +410,7 @@ static void shrinkwrap_calc_nearest_surface_point(ShrinkwrapCalcData *calc) else { copy_v3_v3(tmp_co, co); } - space_transform_apply(&calc->local2target, tmp_co); + BLI_space_transform_apply(&calc->local2target, tmp_co); /* Use local proximity heuristics (to reduce the nearest search) * @@ -494,7 +444,7 @@ static void shrinkwrap_calc_nearest_surface_point(ShrinkwrapCalcData *calc) } /* Convert the coordinates back to mesh coordinates */ - space_transform_invert(&calc->local2target, tmp_co); + BLI_space_transform_invert(&calc->local2target, tmp_co); interp_v3_v3v3(co, co, tmp_co, weight); /* linear interpolation */ } } @@ -537,7 +487,7 @@ void shrinkwrapModifier_deform(ShrinkwrapModifierData *smd, Object *ob, DerivedM /* TODO there might be several "bugs" on non-uniform scales matrixs * because it will no longer be nearest surface, not sphere projection * because space has been deformed */ - SPACE_TRANSFORM_SETUP(&calc.local2target, ob, smd->target); + BLI_SPACE_TRANSFORM_SETUP(&calc.local2target, ob, smd->target); /* TODO: smd->keepDist is in global units.. must change to local */ calc.keepDist = smd->keepDist; diff --git a/source/blender/blenkernel/intern/subsurf_ccg.c b/source/blender/blenkernel/intern/subsurf_ccg.c index 12a19381e9d..0bd9517dcfd 100644 --- a/source/blender/blenkernel/intern/subsurf_ccg.c +++ b/source/blender/blenkernel/intern/subsurf_ccg.c @@ -41,6 +41,7 @@ #include "MEM_guardedalloc.h" +#include "DNA_material_types.h" #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" #include "DNA_modifier_types.h" @@ -2290,18 +2291,23 @@ static void ccgDM_drawFacesTex_common(DerivedMesh *dm, DMSetDrawOptionsTex drawParams, DMSetDrawOptions drawParamsMapped, DMCompareDrawOptions compareDrawOptions, - void *userData) + void *userData, DMDrawFlag flag) { CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm; CCGSubSurf *ss = ccgdm->ss; CCGKey key; MCol *mcol = dm->getTessFaceDataArray(dm, CD_PREVIEW_MCOL); MTFace *tf = DM_get_tessface_data_layer(dm, CD_MTFACE); + MTFace *tf_stencil_base = NULL; + MTFace *tf_stencil = NULL; + MTFace *tf_base; short (*lnors)[4][3] = dm->getTessFaceDataArray(dm, CD_TESSLOOPNORMAL); DMFlagMat *faceFlags = ccgdm->faceFlags; DMDrawOption draw_option; int i, totface, gridSize = ccgSubSurf_getGridSize(ss); int gridFaces = gridSize - 1; + int gridOffset = 0; + int mat_nr_cache = -1; (void) compareDrawOptions; @@ -2315,6 +2321,12 @@ static void ccgDM_drawFacesTex_common(DerivedMesh *dm, mcol = dm->getTessFaceDataArray(dm, CD_TEXTURE_MCOL); totface = ccgSubSurf_getNumFaces(ss); + + if (flag & DM_DRAW_USE_TEXPAINT_UV) { + int stencil = CustomData_get_stencil_layer(&dm->faceData, CD_MTFACE); + tf_stencil_base = CustomData_get_layer_n(&dm->faceData, CD_MTFACE, stencil); + } + for (i = 0; i < totface; i++) { CCGFace *f = ccgdm->faceMap[i].face; int S, x, y, numVerts = ccgSubSurf_getFaceNumVerts(f); @@ -2333,6 +2345,18 @@ static void ccgDM_drawFacesTex_common(DerivedMesh *dm, mat_nr = 0; } + /* texture painting, handle the correct uv layer here */ + if (flag & DM_DRAW_USE_TEXPAINT_UV) { + if (mat_nr != mat_nr_cache) { + tf_base = DM_paint_uvlayer_active_get(dm, mat_nr); + + mat_nr_cache = mat_nr; + } + tf = tf_base + gridOffset; + tf_stencil = tf_stencil_base + gridOffset; + gridOffset += gridFaces * gridFaces * numVerts; + } + if (drawParams) draw_option = drawParams(tf, (mcol != NULL), mat_nr); else if (index != ORIGINDEX_NONE) @@ -2373,26 +2397,31 @@ static void ccgDM_drawFacesTex_common(DerivedMesh *dm, float *d_co = CCG_grid_elem_co(&key, faceGridData, x, y + 1); if (tf) glTexCoord2fv(tf->uv[1]); + if (tf_stencil) glMultiTexCoord2fv(GL_TEXTURE2, tf_stencil->uv[1]); if (cp) glColor3ub(cp[7], cp[6], cp[5]); glNormal3sv(ln[0][1]); glVertex3fv(d_co); if (tf) glTexCoord2fv(tf->uv[2]); + if (tf_stencil) glMultiTexCoord2fv(GL_TEXTURE2, tf_stencil->uv[2]); if (cp) glColor3ub(cp[11], cp[10], cp[9]); glNormal3sv(ln[0][2]); glVertex3fv(c_co); if (tf) glTexCoord2fv(tf->uv[3]); + if (tf_stencil) glMultiTexCoord2fv(GL_TEXTURE2, tf_stencil->uv[3]); if (cp) glColor3ub(cp[15], cp[14], cp[13]); glNormal3sv(ln[0][3]); glVertex3fv(b_co); if (tf) glTexCoord2fv(tf->uv[0]); + if (tf_stencil) glMultiTexCoord2fv(GL_TEXTURE2, tf_stencil->uv[0]); if (cp) glColor3ub(cp[3], cp[2], cp[1]); glNormal3sv(ln[0][0]); glVertex3fv(a_co); if (tf) tf++; + if (tf_stencil) tf_stencil++; if (cp) cp += 16; ln++; } @@ -2408,17 +2437,20 @@ static void ccgDM_drawFacesTex_common(DerivedMesh *dm, b = CCG_grid_elem(&key, faceGridData, x, y + 1); if (tf) glTexCoord2fv(tf->uv[0]); + if (tf_stencil) glMultiTexCoord2fv(GL_TEXTURE2, tf_stencil->uv[0]); if (cp) glColor3ub(cp[3], cp[2], cp[1]); glNormal3fv(CCG_elem_no(&key, a)); glVertex3fv(CCG_elem_co(&key, a)); if (tf) glTexCoord2fv(tf->uv[1]); + if (tf_stencil) glMultiTexCoord2fv(GL_TEXTURE2, tf_stencil->uv[1]); if (cp) glColor3ub(cp[7], cp[6], cp[5]); glNormal3fv(CCG_elem_no(&key, b)); glVertex3fv(CCG_elem_co(&key, b)); if (x != gridFaces - 1) { if (tf) tf++; + if (tf_stencil) tf_stencil++; if (cp) cp += 16; } } @@ -2427,16 +2459,19 @@ static void ccgDM_drawFacesTex_common(DerivedMesh *dm, b = CCG_grid_elem(&key, faceGridData, x, y + 1); if (tf) glTexCoord2fv(tf->uv[3]); + if (tf_stencil) glMultiTexCoord2fv(GL_TEXTURE2, tf_stencil->uv[3]); if (cp) glColor3ub(cp[15], cp[14], cp[13]); glNormal3fv(CCG_elem_no(&key, a)); glVertex3fv(CCG_elem_co(&key, a)); if (tf) glTexCoord2fv(tf->uv[2]); + if (tf_stencil) glMultiTexCoord2fv(GL_TEXTURE2, tf_stencil->uv[2]); if (cp) glColor3ub(cp[11], cp[10], cp[9]); glNormal3fv(CCG_elem_no(&key, b)); glVertex3fv(CCG_elem_co(&key, b)); if (tf) tf++; + if (tf_stencil) tf_stencil++; if (cp) cp += 16; glEnd(); @@ -2455,22 +2490,27 @@ static void ccgDM_drawFacesTex_common(DerivedMesh *dm, ccgDM_glNormalFast(a_co, b_co, c_co, d_co); if (tf) glTexCoord2fv(tf->uv[1]); + if (tf_stencil) glMultiTexCoord2fv(GL_TEXTURE2, tf_stencil->uv[1]); if (cp) glColor3ub(cp[7], cp[6], cp[5]); glVertex3fv(d_co); if (tf) glTexCoord2fv(tf->uv[2]); + if (tf_stencil) glMultiTexCoord2fv(GL_TEXTURE2, tf_stencil->uv[2]); if (cp) glColor3ub(cp[11], cp[10], cp[9]); glVertex3fv(c_co); if (tf) glTexCoord2fv(tf->uv[3]); + if (tf_stencil) glMultiTexCoord2fv(GL_TEXTURE2, tf_stencil->uv[3]); if (cp) glColor3ub(cp[15], cp[14], cp[13]); glVertex3fv(b_co); if (tf) glTexCoord2fv(tf->uv[0]); + if (tf_stencil) glMultiTexCoord2fv(GL_TEXTURE2, tf_stencil->uv[0]); if (cp) glColor3ub(cp[3], cp[2], cp[1]); glVertex3fv(a_co); if (tf) tf++; + if (tf_stencil) tf_stencil++; if (cp) cp += 16; } } @@ -2483,17 +2523,17 @@ static void ccgDM_drawFacesTex_common(DerivedMesh *dm, static void ccgDM_drawFacesTex(DerivedMesh *dm, DMSetDrawOptionsTex setDrawOptions, DMCompareDrawOptions compareDrawOptions, - void *userData) + void *userData, DMDrawFlag flag) { - ccgDM_drawFacesTex_common(dm, setDrawOptions, NULL, compareDrawOptions, userData); + ccgDM_drawFacesTex_common(dm, setDrawOptions, NULL, compareDrawOptions, userData, flag); } static void ccgDM_drawMappedFacesTex(DerivedMesh *dm, DMSetDrawOptions setDrawOptions, DMCompareDrawOptions compareDrawOptions, - void *userData) + void *userData, DMDrawFlag flag) { - ccgDM_drawFacesTex_common(dm, NULL, setDrawOptions, compareDrawOptions, userData); + ccgDM_drawFacesTex_common(dm, NULL, setDrawOptions, compareDrawOptions, userData, flag); } static void ccgDM_drawUVEdges(DerivedMesh *dm) diff --git a/source/blender/blenkernel/intern/text.c b/source/blender/blenkernel/intern/text.c index 90687ef9916..4cd85fb342e 100644 --- a/source/blender/blenkernel/intern/text.c +++ b/source/blender/blenkernel/intern/text.c @@ -1286,6 +1286,19 @@ void txt_sel_all(Text *text) text->selc = text->sell->len; } +/** + * Reverse of #txt_pop_sel + * Clears the selection and ensures the cursor is located + * at the selection (where the cursor is visually while editing). + */ +void txt_sel_clear(Text *text) +{ + if (text->sell) { + text->curl = text->sell; + text->curc = text->selc; + } +} + void txt_sel_line(Text *text) { if (!text) return; @@ -2697,7 +2710,7 @@ void txt_indent(Text *text) /* hardcoded: TXT_TABSIZE = 4 spaces: */ int spaceslen = TXT_TABSIZE; - if (ELEM3(NULL, text, text->curl, text->sell)) { + if (ELEM(NULL, text, text->curl, text->sell)) { return; } @@ -2764,7 +2777,7 @@ void txt_unindent(Text *text) /* hardcoded: TXT_TABSIZE = 4 spaces: */ int spaceslen = TXT_TABSIZE; - if (ELEM3(NULL, text, text->curl, text->sell)) { + if (ELEM(NULL, text, text->curl, text->sell)) { return; } diff --git a/source/blender/blenkernel/intern/texture.c b/source/blender/blenkernel/intern/texture.c index bb956cb085c..b1981a3a804 100644 --- a/source/blender/blenkernel/intern/texture.c +++ b/source/blender/blenkernel/intern/texture.c @@ -41,6 +41,7 @@ #include "BLI_math.h" #include "BLI_kdopbvh.h" #include "BLI_utildefines.h" +#include "BLI_math_color.h" #include "DNA_key_types.h" #include "DNA_object_types.h" @@ -145,12 +146,12 @@ void init_tex_mapping(TexMapping *texmap) if (texmap->type == TEXMAP_TYPE_TEXTURE) { /* to transform a texture, the inverse transform needs * to be applied to the texture coordinate */ - mul_serie_m4(texmap->mat, tmat, rmat, smat, 0, 0, 0, 0, 0); + mul_m4_series(texmap->mat, tmat, rmat, smat); invert_m4(texmap->mat); } else if (texmap->type == TEXMAP_TYPE_POINT) { /* forward transform */ - mul_serie_m4(texmap->mat, tmat, rmat, smat, 0, 0, 0, 0, 0); + mul_m4_series(texmap->mat, tmat, rmat, smat); } else if (texmap->type == TEXMAP_TYPE_VECTOR) { /* no translation for vectors */ @@ -237,7 +238,7 @@ void init_colorband(ColorBand *coba, bool rangetype) } coba->tot = 2; - + coba->color_mode = COLBAND_BLEND_RGB; } ColorBand *add_colorband(bool rangetype) @@ -252,106 +253,209 @@ ColorBand *add_colorband(bool rangetype) /* ------------------------------------------------------------------------- */ +static float colorband_hue_interp( + const int ipotype_hue, + const float mfac, const float fac, + float h1, float h2) +{ + float h_interp; + int mode = 0; + +#define HUE_INTERP(h_a, h_b) ((mfac * (h_a)) + (fac * (h_b))) +#define HUE_MOD(h) (((h) < 1.0f) ? (h) : (h) - 1.0f) + + h1 = HUE_MOD(h1); + h2 = HUE_MOD(h2); + + BLI_assert(h1 >= 0.0f && h1 < 1.0f); + BLI_assert(h2 >= 0.0f && h2 < 1.0f); + + switch (ipotype_hue) { + case COLBAND_HUE_NEAR: + { + if ((h1 < h2) && (h2 - h1) > +0.5f) mode = 1; + else if ((h1 > h2) && (h2 - h1) < -0.5f) mode = 2; + else mode = 0; + break; + } + case COLBAND_HUE_FAR: + { + if ((h1 < h2) && (h2 - h1) < +0.5f) mode = 1; + else if ((h1 > h2) && (h2 - h1) > -0.5f) mode = 2; + else mode = 0; + break; + } + case COLBAND_HUE_CCW: + { + if (h1 > h2) mode = 2; + else mode = 0; + break; + } + case COLBAND_HUE_CW: + { + if (h1 < h2) mode = 1; + else mode = 0; + break; + } + } + + switch (mode) { + case 0: + h_interp = HUE_INTERP(h1, h2); + break; + case 1: + h_interp = HUE_INTERP(h1 + 1.0f, h2); + h_interp = HUE_MOD(h_interp); + break; + case 2: + h_interp = HUE_INTERP(h1, h2 + 1.0f); + h_interp = HUE_MOD(h_interp); + break; + } + + BLI_assert(h_interp >= 0.0f && h_interp < 1.0f); + +#undef HUE_INTERP +#undef HUE_MOD + + return h_interp; +} + bool do_colorband(const ColorBand *coba, float in, float out[4]) { const CBData *cbd1, *cbd2, *cbd0, *cbd3; - float fac, mfac, t[4]; + float fac; + int ipotype; int a; if (coba == NULL || coba->tot == 0) return 0; cbd1 = coba->data; + + ipotype = (coba->color_mode == COLBAND_BLEND_RGB) ? coba->ipotype : COLBAND_INTERP_LINEAR; + if (coba->tot == 1) { out[0] = cbd1->r; out[1] = cbd1->g; out[2] = cbd1->b; out[3] = cbd1->a; } + else if ((in <= cbd1->pos) && ELEM(ipotype, COLBAND_INTERP_LINEAR, COLBAND_INTERP_EASE)) { + out[0] = cbd1->r; + out[1] = cbd1->g; + out[2] = cbd1->b; + out[3] = cbd1->a; + } else { - if (in <= cbd1->pos && coba->ipotype < 2) { + CBData left, right; + + /* we're looking for first pos > in */ + for (a = 0; a < coba->tot; a++, cbd1++) if (cbd1->pos > in) break; + + if (a == coba->tot) { + cbd2 = cbd1 - 1; + right = *cbd2; + right.pos = 1.0f; + cbd1 = &right; + } + else if (a == 0) { + left = *cbd1; + left.pos = 0.0f; + cbd2 = &left; + } + else { + cbd2 = cbd1 - 1; + } + + if ((in >= cbd1->pos) && ELEM(ipotype, COLBAND_INTERP_LINEAR, COLBAND_INTERP_EASE)) { out[0] = cbd1->r; out[1] = cbd1->g; out[2] = cbd1->b; out[3] = cbd1->a; } else { - CBData left, right; - - /* we're looking for first pos > in */ - for (a = 0; a < coba->tot; a++, cbd1++) if (cbd1->pos > in) break; - - if (a == coba->tot) { - cbd2 = cbd1 - 1; - right = *cbd2; - right.pos = 1.0f; - cbd1 = &right; - } - else if (a == 0) { - left = *cbd1; - left.pos = 0.0f; - cbd2 = &left; + + if (cbd2->pos != cbd1->pos) { + fac = (in - cbd1->pos) / (cbd2->pos - cbd1->pos); } else { - cbd2 = cbd1 - 1; + /* was setting to 0.0 in 2.56 & previous, but this + * is incorrect for the last element, see [#26732] */ + fac = (a != coba->tot) ? 0.0f : 1.0f; } - - if (in >= cbd1->pos && coba->ipotype < 2) { - out[0] = cbd1->r; - out[1] = cbd1->g; - out[2] = cbd1->b; - out[3] = cbd1->a; + + if (ipotype == COLBAND_INTERP_CONSTANT) { + /* constant */ + out[0] = cbd2->r; + out[1] = cbd2->g; + out[2] = cbd2->b; + out[3] = cbd2->a; } - else { - - if (cbd2->pos != cbd1->pos) - fac = (in - cbd1->pos) / (cbd2->pos - cbd1->pos); + else if (ipotype >= COLBAND_INTERP_B_SPLINE) { + /* ipo from right to left: 3 2 1 0 */ + float t[4]; + + if (a >= coba->tot - 1) cbd0 = cbd1; + else cbd0 = cbd1 + 1; + if (a < 2) cbd3 = cbd2; + else cbd3 = cbd2 - 1; + + CLAMP(fac, 0.0f, 1.0f); + + if (ipotype == COLBAND_INTERP_CARDINAL) { + key_curve_position_weights(fac, t, KEY_CARDINAL); + } else { - /* was setting to 0.0 in 2.56 & previous, but this - * is incorrect for the last element, see [#26732] */ - fac = (a != coba->tot) ? 0.0f : 1.0f; + key_curve_position_weights(fac, t, KEY_BSPLINE); + } + + out[0] = t[3] * cbd3->r + t[2] * cbd2->r + t[1] * cbd1->r + t[0] * cbd0->r; + out[1] = t[3] * cbd3->g + t[2] * cbd2->g + t[1] * cbd1->g + t[0] * cbd0->g; + out[2] = t[3] * cbd3->b + t[2] * cbd2->b + t[1] * cbd1->b + t[0] * cbd0->b; + out[3] = t[3] * cbd3->a + t[2] * cbd2->a + t[1] * cbd1->a + t[0] * cbd0->a; + CLAMP(out[0], 0.0f, 1.0f); + CLAMP(out[1], 0.0f, 1.0f); + CLAMP(out[2], 0.0f, 1.0f); + CLAMP(out[3], 0.0f, 1.0f); + } + else { + float mfac; + + if (ipotype == COLBAND_INTERP_EASE) { + mfac = fac * fac; + fac = 3.0f * mfac - 2.0f * mfac * fac; } - - if (coba->ipotype == 4) { - /* constant */ - out[0] = cbd2->r; - out[1] = cbd2->g; - out[2] = cbd2->b; - out[3] = cbd2->a; - return 1; + + mfac = 1.0f - fac; + + if (UNLIKELY(coba->color_mode == COLBAND_BLEND_HSV)) { + float col1[3], col2[3]; + + rgb_to_hsv_v(&cbd1->r, col1); + rgb_to_hsv_v(&cbd2->r, col2); + + out[0] = colorband_hue_interp(coba->ipotype_hue, mfac, fac, col1[0], col2[0]); + out[1] = mfac * col1[1] + fac * col2[1]; + out[2] = mfac * col1[2] + fac * col2[2]; + out[3] = mfac * cbd1->a + fac * cbd2->a; + + hsv_to_rgb_v(out, out); } - - if (coba->ipotype >= 2) { - /* ipo from right to left: 3 2 1 0 */ - - if (a >= coba->tot - 1) cbd0 = cbd1; - else cbd0 = cbd1 + 1; - if (a < 2) cbd3 = cbd2; - else cbd3 = cbd2 - 1; - - CLAMP(fac, 0.0f, 1.0f); - - if (coba->ipotype == 3) - key_curve_position_weights(fac, t, KEY_CARDINAL); - else - key_curve_position_weights(fac, t, KEY_BSPLINE); - - out[0] = t[3] * cbd3->r + t[2] * cbd2->r + t[1] * cbd1->r + t[0] * cbd0->r; - out[1] = t[3] * cbd3->g + t[2] * cbd2->g + t[1] * cbd1->g + t[0] * cbd0->g; - out[2] = t[3] * cbd3->b + t[2] * cbd2->b + t[1] * cbd1->b + t[0] * cbd0->b; - out[3] = t[3] * cbd3->a + t[2] * cbd2->a + t[1] * cbd1->a + t[0] * cbd0->a; - CLAMP(out[0], 0.0f, 1.0f); - CLAMP(out[1], 0.0f, 1.0f); - CLAMP(out[2], 0.0f, 1.0f); - CLAMP(out[3], 0.0f, 1.0f); + else if (UNLIKELY(coba->color_mode == COLBAND_BLEND_HSL)) { + float col1[3], col2[3]; + + rgb_to_hsl_v(&cbd1->r, col1); + rgb_to_hsl_v(&cbd2->r, col2); + + out[0] = colorband_hue_interp(coba->ipotype_hue, mfac, fac, col1[0], col2[0]); + out[1] = mfac * col1[1] + fac * col2[1]; + out[2] = mfac * col1[2] + fac * col2[2]; + out[3] = mfac * cbd1->a + fac * cbd2->a; + + hsl_to_rgb_v(out, out); } else { - - if (coba->ipotype == 1) { /* EASE */ - mfac = fac * fac; - fac = 3.0f * mfac - 2.0f * mfac * fac; - } - mfac = 1.0f - fac; - + /* COLBAND_BLEND_RGB */ out[0] = mfac * cbd1->r + fac * cbd2->r; out[1] = mfac * cbd1->g + fac * cbd2->g; out[2] = mfac * cbd1->b + fac * cbd2->b; @@ -408,19 +512,18 @@ CBData *colorband_element_add(struct ColorBand *coba, float position) if (coba->tot == MAXCOLORBAND) { return NULL; } - else if (coba->tot > 0) { + else { CBData *xnew; - float col[4]; - - do_colorband(coba, position, col); xnew = &coba->data[coba->tot]; xnew->pos = position; - xnew->r = col[0]; - xnew->g = col[1]; - xnew->b = col[2]; - xnew->a = col[3]; + if (coba->tot != 0) { + do_colorband(coba, position, &xnew->r); + } + else { + zero_v4(&xnew->r); + } } coba->tot++; @@ -474,7 +577,8 @@ void BKE_texture_free(Tex *tex) void default_tex(Tex *tex) { - tex->type = TEX_CLOUDS; + tex->type = TEX_IMAGE; + tex->ima = NULL; tex->stype = 0; tex->flag = TEX_CHECKER_ODD; tex->imaflag = TEX_INTERPOL | TEX_MIPMAP | TEX_USEALPHA; @@ -592,7 +696,7 @@ Tex *add_texture(Main *bmain, const char *name) void default_mtex(MTex *mtex) { - mtex->texco = TEXCO_ORCO; + mtex->texco = TEXCO_UV; mtex->mapto = MAP_COL; mtex->object = NULL; mtex->projx = PROJ_X; @@ -747,8 +851,7 @@ Tex *localize_texture(Tex *tex) { Tex *texn; - texn = BKE_libblock_copy(&tex->id); - BLI_remlink(&G.main->tex, texn); + texn = BKE_libblock_copy_nolib(&tex->id, false); /* image texture: BKE_texture_free also doesn't decrease */ diff --git a/source/blender/blenkernel/intern/tracking_region_tracker.c b/source/blender/blenkernel/intern/tracking_region_tracker.c index 76b7ad5d982..6300e29f516 100644 --- a/source/blender/blenkernel/intern/tracking_region_tracker.c +++ b/source/blender/blenkernel/intern/tracking_region_tracker.c @@ -501,7 +501,7 @@ static void tracking_scale_marker_search(const MovieTrackingMarker *old_marker, static void tracking_insert_new_marker(MovieTrackingContext *context, MovieTrackingTrack *track, const MovieTrackingMarker *old_marker, int curfra, bool tracked, int frame_width, int frame_height, - double dst_pixel_x[5], double dst_pixel_y[5]) + const double dst_pixel_x[5], const double dst_pixel_y[5]) { MovieTrackingMarker new_marker; int frame_delta = context->backwards ? -1 : 1; diff --git a/source/blender/blenkernel/intern/tracking_stabilize.c b/source/blender/blenkernel/intern/tracking_stabilize.c index ffbdf5cb486..eb224020977 100644 --- a/source/blender/blenkernel/intern/tracking_stabilize.c +++ b/source/blender/blenkernel/intern/tracking_stabilize.c @@ -82,7 +82,7 @@ static bool stabilization_median_point_get(MovieTracking *tracking, int framenr, * NOTE: frame number should be in clip space, not scene space */ static void stabilization_calculate_data(MovieTracking *tracking, int framenr, int width, int height, - float firstmedian[2], float median[2], + const float firstmedian[2], const float median[2], float translation[2], float *scale, float *angle) { MovieTrackingStabilization *stab = &tracking->stabilization; @@ -439,6 +439,6 @@ void BKE_tracking_stabilization_data_to_mat4(int width, int height, float aspect rotate_m4(rotation_mat, 'Z', angle); /* rotation matrix */ /* compose transformation matrix */ - mul_serie_m4(mat, translation_mat, center_mat, aspect_mat, rotation_mat, inv_aspect_mat, - scale_mat, inv_center_mat, NULL); + mul_m4_series(mat, translation_mat, center_mat, aspect_mat, rotation_mat, inv_aspect_mat, + scale_mat, inv_center_mat); } diff --git a/source/blender/blenkernel/intern/treehash.c b/source/blender/blenkernel/intern/treehash.c index fb55e3d2137..a65bd28da97 100644 --- a/source/blender/blenkernel/intern/treehash.c +++ b/source/blender/blenkernel/intern/treehash.c @@ -59,7 +59,7 @@ static TseGroup *tse_group_create(void) static void tse_group_add(TseGroup *tse_group, TreeStoreElem *elem) { - if (tse_group->size == tse_group->allocated) { + if (UNLIKELY(tse_group->size == tse_group->allocated)) { tse_group->allocated *= 2; tse_group->elems = MEM_reallocN(tse_group->elems, sizeof(TreeStoreElem *) * tse_group->allocated); } diff --git a/source/blender/blenkernel/intern/unit.c b/source/blender/blenkernel/intern/unit.c index 8aca9f78702..5a2c77b5619 100644 --- a/source/blender/blenkernel/intern/unit.c +++ b/source/blender/blenkernel/intern/unit.c @@ -41,6 +41,8 @@ # include "BLI_winstuff.h" #endif +/* no BKE or DNA includes! */ + #define TEMP_STR_SIZE 256 #define SEP_CHR '#' @@ -349,7 +351,7 @@ static void unit_dual_convert(double value, bUnitCollection *usys, bUnitDef **un static size_t unit_as_string(char *str, int len_max, double value, int prec, bUnitCollection *usys, /* non exposed options */ - bUnitDef *unit, char pad) + const bUnitDef *unit, char pad) { double value_conv; size_t len, i; @@ -456,7 +458,7 @@ size_t bUnit_AsString(char *str, int len_max, double value, int prec, int system return unit_as_string(str, len_max, value, prec, usys, NULL, pad ? ' ' : '\0'); } -BLI_INLINE int isalpha_or_utf8(const int ch) +BLI_INLINE bool isalpha_or_utf8(const int ch) { return (ch >= 128 || isalpha(ch)); } @@ -493,11 +495,11 @@ static const char *unit_find_str(const char *str, const char *substr) * * "1m1cm+2mm" - Original value * "1*1#1*0.01#+2*0.001#" - Replace numbers - * "1*1,1*0.01 +2*0.001 " - Add comma's if ( - + * / % ^ < > ) not found in between + * "1*1+1*0.01 +2*0.001 " - Add add signs if ( + - * / | & ~ < > ^ ! = % ) not found in between * */ -/* not too strict, (- = * /) are most common */ +/* not too strict, (+ - * /) are most common */ static bool ch_is_op(char op) { switch (op) { @@ -514,9 +516,11 @@ static bool ch_is_op(char op) case '!': case '=': case '%': - return 1; + return true; + break; default: - return 0; + return false; + break; } } @@ -579,14 +583,42 @@ static int unit_replace(char *str, int len_max, char *str_tmp, double scale_pref return ofs; } -static int unit_find(const char *str, bUnitDef *unit) +static bool unit_find(const char *str, bUnitDef *unit) { - if (unit_find_str(str, unit->name_short)) return 1; - if (unit_find_str(str, unit->name_plural)) return 1; - if (unit_find_str(str, unit->name_alt)) return 1; - if (unit_find_str(str, unit->name)) return 1; + if (unit_find_str(str, unit->name_short)) return true; + if (unit_find_str(str, unit->name_plural)) return true; + if (unit_find_str(str, unit->name_alt)) return true; + if (unit_find_str(str, unit->name)) return true; - return 0; + return false; +} + +static bUnitDef *unit_detect_from_str(bUnitCollection *usys, const char *str, const char *str_prev) +{ + /* Try to find a default unit from current or previous string. + * This allows us to handle cases like 2 + 2mm, people would expect to get 4mm, not 2.002m! + * Note this does not handle corner cases like 2 + 2cm + 1 + 2.5mm... We can't support everything. */ + bUnitDef *unit = NULL; + + /* see which units the new value has */ + for (unit = usys->units; unit->name; unit++) { + if (unit_find(str, unit)) + break; + } + /* Else, try to infer the default unit from the previous string. */ + if (str_prev && (unit == NULL || unit->name == NULL)) { + /* see which units the original value had */ + for (unit = usys->units; unit->name; unit++) { + if (unit_find(str_prev, unit)) + break; + } + } + /* Else, fall back to default unit. */ + if (unit == NULL || unit->name == NULL) { + unit = unit_default(usys); + } + + return unit; } /* make a copy of the string that replaces the units with numbers @@ -597,37 +629,58 @@ static int unit_find(const char *str, bUnitDef *unit) * 10.1km -> 10.1*1000.0 * ...will be resolved by python. * - * values will be split by a comma's - * 5'2" -> 5*0.3048, 2*0.0254 + * values will be split by an add sign + * 5'2" -> 5*0.3048 + 2*0.0254 * * str_prev is optional, when valid it is used to get a base unit when none is set. * * return true of a change was made. */ -int bUnit_ReplaceString(char *str, int len_max, const char *str_prev, double scale_pref, int system, int type) +bool bUnit_ReplaceString(char *str, int len_max, const char *str_prev, double scale_pref, int system, int type) { bUnitCollection *usys = unit_get_system(system, type); - bUnitDef *unit; + bUnitDef *unit = NULL, *default_unit; + double scale_pref_base = scale_pref; char str_tmp[TEMP_STR_SIZE]; - int changed = 0; + bool changed = false; if (usys == NULL || usys->units[0].name == NULL) { - return 0; + return changed; } /* make lowercase */ BLI_ascii_strtolower(str, len_max); + /* Try to find a default unit from current or previous string. */ + default_unit = unit_detect_from_str(usys, str, str_prev); + + /* We apply the default unit to the whole expression (default unit is now the reference '1.0' one). */ + scale_pref_base *= default_unit->scalar; + + /* Apply the default unit on the whole expression, this allows to handle nasty cases like '2+2in'. */ + if (BLI_snprintf(str_tmp, sizeof(str_tmp), "(%s)*%.9g", str, default_unit->scalar) < sizeof(str_tmp)) { + strncpy(str, str_tmp, len_max); + } + else { + /* BLI_snprintf would not fit into str_tmp, cant do much in this case + * check for this because otherwise bUnit_ReplaceString could call its self forever */ + return changed; + } + for (unit = usys->units; unit->name; unit++) { /* in case there are multiple instances */ - while (unit_replace(str, len_max, str_tmp, scale_pref, unit)) + while (unit_replace(str, len_max, str_tmp, scale_pref_base, unit)) changed = true; } unit = NULL; { /* try other unit systems now, so we can evaluate imperial when metric is set for eg. */ + /* Note that checking other systems at that point means we do not support their units as 'default' one. + * In other words, when in metrics, typing '2+2in' will give 2 meters 2 inches, not 4 inches. + * I do think this is the desired behavior! + */ bUnitCollection *usys_iter; int system_iter; @@ -638,7 +691,7 @@ int bUnit_ReplaceString(char *str, int len_max, const char *str_prev, double sca for (unit = usys_iter->units; unit->name; unit++) { int ofs = 0; /* in case there are multiple instances */ - while ((ofs = unit_replace(str + ofs, len_max - ofs, str_tmp, scale_pref, unit))) + while ((ofs = unit_replace(str + ofs, len_max - ofs, str_tmp, scale_pref_base, unit))) changed = true; } } @@ -647,35 +700,9 @@ int bUnit_ReplaceString(char *str, int len_max, const char *str_prev, double sca } unit = NULL; - if (changed == 0) { - /* no units given so infer a unit from the previous string or default */ - if (str_prev) { - /* see which units the original value had */ - for (unit = usys->units; unit->name; unit++) { - if (unit_find(str_prev, unit)) - break; - } - } - - if (unit == NULL || unit->name == NULL) - unit = unit_default(usys); - - /* add the unit prefix and re-run, use brackets in case there was an expression given */ - if (BLI_snprintf(str_tmp, sizeof(str_tmp), "(%s)%s", str, unit->name) < sizeof(str_tmp)) { - strncpy(str, str_tmp, len_max); - return bUnit_ReplaceString(str, len_max, NULL, scale_pref, system, type); - } - else { - /* BLI_snprintf would not fit into str_tmp, cant do much in this case - * check for this because otherwise bUnit_ReplaceString could call its self forever */ - return 0; - } - - } - - /* replace # with commas when there is no operator between it and the next number + /* replace # with add sign when there is no operator between it and the next number * - * "1*1# 3*100# * 3" -> "1 *1, 3 *100 * 3" + * "1*1# 3*100# * 3" -> "1*1+ 3*100 * 3" * * */ { @@ -683,25 +710,19 @@ int bUnit_ReplaceString(char *str, int len_max, const char *str_prev, double sca const char *ch = str; while ((str_found = strchr(str_found, SEP_CHR))) { + bool op_found = false; - int op_found = 0; - /* any operators after this?*/ + /* any operators after this? */ for (ch = str_found + 1; *ch != '\0'; ch++) { - if (*ch == ' ' || *ch == '\t') { - /* do nothing */ - } - else if (ch_is_op(*ch) || *ch == ',') { /* found an op, no need to insert a ',' */ - op_found = 1; - break; - } - else { /* found a non-op character */ - op_found = 0; - break; + continue; } + op_found = (ch_is_op(*ch) || ELEM(*ch, ',', ')')); + break; } - *str_found++ = op_found ? ' ' : ','; + /* If found an op, comma or closing parenthesis, no need to insert a '+', else we need it. */ + *str_found++ = op_found ? ' ' : '+'; } } @@ -771,7 +792,7 @@ double bUnit_BaseScalar(int system, int type) } /* external access */ -int bUnit_IsValid(int system, int type) +bool bUnit_IsValid(int system, int type) { return !(system < 0 || system > UNIT_SYSTEM_TOT || type < 0 || type > B_UNIT_TYPE_TOT); } diff --git a/source/blender/blenkernel/intern/world.c b/source/blender/blenkernel/intern/world.c index 5065c3ae04f..8e3c92314e6 100644 --- a/source/blender/blenkernel/intern/world.c +++ b/source/blender/blenkernel/intern/world.c @@ -142,8 +142,7 @@ World *localize_world(World *wrld) World *wrldn; int a; - wrldn = BKE_libblock_copy(&wrld->id); - BLI_remlink(&G.main->world, wrldn); + wrldn = BKE_libblock_copy_nolib(&wrld->id, false); for (a = 0; a < MAX_MTEX; a++) { if (wrld->mtex[a]) { diff --git a/source/blender/blenkernel/intern/writeavi.c b/source/blender/blenkernel/intern/writeavi.c index a9f040b8650..aef44993912 100644 --- a/source/blender/blenkernel/intern/writeavi.c +++ b/source/blender/blenkernel/intern/writeavi.c @@ -110,7 +110,7 @@ bMovieHandle *BKE_movie_handle_get(const char imtype) } #endif #ifdef WITH_FFMPEG - if (ELEM4(imtype, R_IMF_IMTYPE_FFMPEG, R_IMF_IMTYPE_H264, R_IMF_IMTYPE_XVID, R_IMF_IMTYPE_THEORA)) { + if (ELEM(imtype, R_IMF_IMTYPE_FFMPEG, R_IMF_IMTYPE_H264, R_IMF_IMTYPE_XVID, R_IMF_IMTYPE_THEORA)) { mh.start_movie = BKE_ffmpeg_start; mh.append_movie = BKE_ffmpeg_append; mh.end_movie = BKE_ffmpeg_end; diff --git a/source/blender/blenkernel/intern/writeffmpeg.c b/source/blender/blenkernel/intern/writeffmpeg.c index 00dfae9e72a..ca21180000d 100644 --- a/source/blender/blenkernel/intern/writeffmpeg.c +++ b/source/blender/blenkernel/intern/writeffmpeg.c @@ -30,13 +30,6 @@ #include <string.h> #include <stdio.h> -#if defined(_WIN32) && defined(DEBUG) && !defined(__MINGW32__) && !defined(__CYGWIN__) -/* This does not seem necessary or present on MSVC 8, but may be needed in earlier versions? */ -# if _MSC_VER < 1400 -# include <stdint.h> -# endif -#endif - #include <stdlib.h> #include <libavformat/avformat.h> @@ -708,7 +701,7 @@ static AVStream *alloc_audio_stream(RenderData *rd, int codec_id, AVFormatContex * you have various implementations around. float samples in particular are not always supported. */ const enum AVSampleFormat *p = codec->sample_fmts; - for (; *p!=-1; p++) { + for (; *p != -1; p++) { if (*p == st->codec->sample_fmt) break; } |