diff options
author | Lukas Tönne <lukas.toenne@gmail.com> | 2016-06-08 10:41:04 +0300 |
---|---|---|
committer | Lukas Tönne <lukas.toenne@gmail.com> | 2016-06-08 10:41:04 +0300 |
commit | a6fdd7d8765ca5b87db4f2a7e562e9f4525dcc5a (patch) | |
tree | 4ebcf5e4a137ccf96f227093ab52ed0c197b810a /source/blender/blenkernel | |
parent | 95a603c607b88f4527c7b8edf4eeacd1ba380867 (diff) | |
parent | fc60689a258a4a9c7c73c0a91cdfeeb57ecc3ccb (diff) |
Merge branch 'master' into object_nodes
Diffstat (limited to 'source/blender/blenkernel')
30 files changed, 623 insertions, 269 deletions
diff --git a/source/blender/blenkernel/BKE_DerivedMesh.h b/source/blender/blenkernel/BKE_DerivedMesh.h index 2b13a847e14..8ccc4a6eb0e 100644 --- a/source/blender/blenkernel/BKE_DerivedMesh.h +++ b/source/blender/blenkernel/BKE_DerivedMesh.h @@ -757,22 +757,22 @@ void DM_update_weight_mcol( typedef struct DMVertexAttribs { struct { struct MLoopUV *array; - int em_offset, gl_index, gl_texco; + int em_offset, gl_index, gl_texco, gl_info_index; } tface[MAX_MTFACE]; struct { struct MLoopCol *array; - int em_offset, gl_index; + int em_offset, gl_index, gl_info_index; } mcol[MAX_MCOL]; struct { float (*array)[4]; - int em_offset, gl_index; + int em_offset, gl_index, gl_info_index; } tang[MAX_MTFACE]; struct { float (*array)[3]; - int em_offset, gl_index, gl_texco; + int em_offset, gl_index, gl_texco, gl_info_index; } orco; int tottface, totmcol, tottang, totorco; diff --git a/source/blender/blenkernel/BKE_animsys.h b/source/blender/blenkernel/BKE_animsys.h index dc751747f32..6524afff051 100644 --- a/source/blender/blenkernel/BKE_animsys.h +++ b/source/blender/blenkernel/BKE_animsys.h @@ -177,7 +177,7 @@ void BKE_animsys_evaluate_all_animation(struct Main *main, struct Scene *scene, /* TODO(sergey): This is mainly a temp public function. */ struct FCurve; -bool BKE_animsys_execute_fcurve(struct PointerRNA *ptr, struct AnimMapper *remap, struct FCurve *fcu); +bool BKE_animsys_execute_fcurve(struct PointerRNA *ptr, struct AnimMapper *remap, struct FCurve *fcu, float curval); /* ------------ Specialized API --------------- */ /* There are a few special tools which require these following functions. They are NOT to be used diff --git a/source/blender/blenkernel/BKE_fcurve.h b/source/blender/blenkernel/BKE_fcurve.h index 2022d11d508..bb4eb652ae2 100644 --- a/source/blender/blenkernel/BKE_fcurve.h +++ b/source/blender/blenkernel/BKE_fcurve.h @@ -279,7 +279,7 @@ void correct_bezpart(float v1[2], float v2[2], float v3[2], float v4[2]); /* evaluate fcurve */ float evaluate_fcurve(struct FCurve *fcu, float evaltime); /* evaluate fcurve and store value */ -void calculate_fcurve(struct FCurve *fcu, float ctime); +float calculate_fcurve(struct FCurve *fcu, float evaltime); /* ************* F-Curve Samples API ******************** */ diff --git a/source/blender/blenkernel/BKE_library_idmap.h b/source/blender/blenkernel/BKE_library_idmap.h new file mode 100644 index 00000000000..971586ea8b7 --- /dev/null +++ b/source/blender/blenkernel/BKE_library_idmap.h @@ -0,0 +1,50 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * ***** END GPL LICENSE BLOCK ***** + */ +#ifndef __BKE_LIBRARY_IDMAP_H__ +#define __BKE_LIBRARY_IDMAP_H__ + +/** \file BKE_library_idmap.h + * \ingroup bke + */ + +#include "BLI_compiler_attrs.h" + +struct ID; +struct Main; +struct IDNameLib_Map; + +struct IDNameLib_Map *BKE_main_idmap_create( + struct Main *bmain) + ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); +void BKE_main_idmap_destroy( + struct IDNameLib_Map *id_typemap) + ATTR_NONNULL(); +struct Main *BKE_main_idmap_main_get( + struct IDNameLib_Map *id_typemap) + ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); +struct ID *BKE_main_idmap_lookup( + struct IDNameLib_Map *id_typemap, + short id_type, const char *name, const struct Library *lib) + ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 3); +struct ID *BKE_main_idmap_lookup_id( + struct IDNameLib_Map *id_typemap, const struct ID *id) + ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2); + +#endif /* __BKE_LIBRARY_IDMAP_H__ */ diff --git a/source/blender/blenkernel/BKE_mesh.h b/source/blender/blenkernel/BKE_mesh.h index c7d5857b873..d8d869015a3 100644 --- a/source/blender/blenkernel/BKE_mesh.h +++ b/source/blender/blenkernel/BKE_mesh.h @@ -323,7 +323,7 @@ void BKE_mesh_mdisp_flip(struct MDisps *md, const bool use_loop_mdisp_flip); void BKE_mesh_polygon_flip_ex( struct MPoly *mpoly, struct MLoop *mloop, struct CustomData *ldata, - struct MDisps *mdisp, const bool use_loop_mdisp_flip); + float (*lnors)[3], struct MDisps *mdisp, const bool use_loop_mdisp_flip); void BKE_mesh_polygon_flip(struct MPoly *mpoly, struct MLoop *mloop, struct CustomData *ldata); void BKE_mesh_polygons_flip(struct MPoly *mpoly, struct MLoop *mloop, struct CustomData *ldata, int totpoly); diff --git a/source/blender/blenkernel/BKE_object.h b/source/blender/blenkernel/BKE_object.h index 7d6096407ff..c591ec2a0aa 100644 --- a/source/blender/blenkernel/BKE_object.h +++ b/source/blender/blenkernel/BKE_object.h @@ -208,6 +208,8 @@ void BKE_object_eval_uber_data(struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob); +void BKE_object_eval_proxy_backlink(struct EvaluationContext *eval_ctx, struct Object *ob); + void BKE_object_handle_data_update(struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob); diff --git a/source/blender/blenkernel/BKE_scene.h b/source/blender/blenkernel/BKE_scene.h index a4c44b9934e..12bfc07e958 100644 --- a/source/blender/blenkernel/BKE_scene.h +++ b/source/blender/blenkernel/BKE_scene.h @@ -135,6 +135,7 @@ float get_render_aosss_error(const struct RenderData *r, float error); bool BKE_scene_use_new_shading_nodes(const struct Scene *scene); bool BKE_scene_use_shading_nodes_custom(struct Scene *scene); +bool BKE_scene_use_world_space_shading(struct Scene *scene); bool BKE_scene_use_spherical_stereo(struct Scene *scene); bool BKE_scene_uses_blender_internal(const struct Scene *scene); diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt index 1f0a93bdc30..f32172c2806 100644 --- a/source/blender/blenkernel/CMakeLists.txt +++ b/source/blender/blenkernel/CMakeLists.txt @@ -122,6 +122,7 @@ set(SRC intern/lamp.c intern/lattice.c intern/library.c + intern/library_idmap.c intern/library_query.c intern/linestyle.c intern/mask.c @@ -245,6 +246,7 @@ set(SRC BKE_lamp.h BKE_lattice.h BKE_library.h + BKE_library_idmap.h BKE_library_query.h BKE_linestyle.h BKE_main.h diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c index 195b5e75352..09f4c286f48 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.c +++ b/source/blender/blenkernel/intern/DerivedMesh.c @@ -2067,15 +2067,10 @@ static void mesh_calc_modifiers( DM_add_edge_layer(dm, CD_ORIGINDEX, CD_CALLOC, NULL); DM_add_poly_layer(dm, CD_ORIGINDEX, CD_CALLOC, NULL); -#pragma omp parallel sections if (dm->numVertData + dm->numEdgeData + dm->numPolyData >= BKE_MESH_OMP_LIMIT) - { -#pragma omp section - { range_vn_i(DM_get_vert_data_layer(dm, CD_ORIGINDEX), dm->numVertData, 0); } -#pragma omp section - { range_vn_i(DM_get_edge_data_layer(dm, CD_ORIGINDEX), dm->numEdgeData, 0); } -#pragma omp section - { range_vn_i(DM_get_poly_data_layer(dm, CD_ORIGINDEX), dm->numPolyData, 0); } - } + /* Not worth parallelizing this, gives less than 0.1% overall speedup in best of best cases... */ + range_vn_i(DM_get_vert_data_layer(dm, CD_ORIGINDEX), dm->numVertData, 0); + range_vn_i(DM_get_edge_data_layer(dm, CD_ORIGINDEX), dm->numEdgeData, 0); + range_vn_i(DM_get_poly_data_layer(dm, CD_ORIGINDEX), dm->numPolyData, 0); } } @@ -3742,6 +3737,7 @@ void DM_vertex_attributes_from_gpu(DerivedMesh *dm, GPUVertexAttribs *gattribs, } attribs->tface[a].gl_index = gattribs->layer[b].glindex; + attribs->tface[a].gl_info_index = gattribs->layer[b].glinfoindoex; attribs->tface[a].gl_texco = gattribs->layer[b].gltexco; } else if (type == CD_MCOL) { @@ -3765,6 +3761,7 @@ void DM_vertex_attributes_from_gpu(DerivedMesh *dm, GPUVertexAttribs *gattribs, } attribs->mcol[a].gl_index = gattribs->layer[b].glindex; + attribs->mcol[a].gl_info_index = gattribs->layer[b].glinfoindoex; } else if (type == CD_TANGENT) { /* note, even with 'is_editmesh' this uses the derived-meshes loop data */ @@ -3787,6 +3784,7 @@ void DM_vertex_attributes_from_gpu(DerivedMesh *dm, GPUVertexAttribs *gattribs, } attribs->tang[a].gl_index = gattribs->layer[b].glindex; + attribs->tang[a].gl_info_index = gattribs->layer[b].glinfoindoex; } else if (type == CD_ORCO) { /* original coordinates */ @@ -3806,6 +3804,7 @@ void DM_vertex_attributes_from_gpu(DerivedMesh *dm, GPUVertexAttribs *gattribs, attribs->orco.gl_index = gattribs->layer[b].glindex; attribs->orco.gl_texco = gattribs->layer[b].gltexco; + attribs->orco.gl_info_index = gattribs->layer[b].glinfoindoex; } } } @@ -3834,6 +3833,7 @@ void DM_draw_attrib_vertex(DMVertexAttribs *attribs, int a, int index, int vert, glTexCoord3fv(orco); else glVertexAttrib3fv(attribs->orco.gl_index, orco); + glUniform1i(attribs->orco.gl_info_index, 0); } /* uv texture coordinates */ @@ -3852,6 +3852,7 @@ void DM_draw_attrib_vertex(DMVertexAttribs *attribs, int a, int index, int vert, glTexCoord2fv(uv); else glVertexAttrib2fv(attribs->tface[b].gl_index, uv); + glUniform1i(attribs->tface[b].gl_info_index, 0); } /* vertex colors */ @@ -3867,6 +3868,7 @@ void DM_draw_attrib_vertex(DMVertexAttribs *attribs, int a, int index, int vert, } glVertexAttrib4fv(attribs->mcol[b].gl_index, col); + glUniform1i(attribs->mcol[b].gl_info_index, GPU_ATTR_INFO_SRGB); } /* tangent for normal mapping */ @@ -3876,6 +3878,7 @@ void DM_draw_attrib_vertex(DMVertexAttribs *attribs, int a, int index, int vert, const float *tang = (array) ? array[a * 4 + vert] : zero; glVertexAttrib4fv(attribs->tang[b].gl_index, tang); } + glUniform1i(attribs->tang[b].gl_info_index, 0); } } diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c index 41950c59a22..99aae6239e8 100644 --- a/source/blender/blenkernel/intern/anim_sys.c +++ b/source/blender/blenkernel/intern/anim_sys.c @@ -730,14 +730,10 @@ static char *rna_path_rename_fix(ID *owner_id, const char *prefix, const char *o DynStr *ds = BLI_dynstr_new(); const char *postfixPtr = oldNamePtr + oldNameLen; char *newPath = NULL; - char oldChar; - + /* add the part of the string that goes up to the start of the prefix */ if (prefixPtr > oldpath) { - oldChar = prefixPtr[0]; - prefixPtr[0] = 0; - BLI_dynstr_append(ds, oldpath); - prefixPtr[0] = oldChar; + BLI_dynstr_nappend(ds, oldpath, prefixPtr - oldpath); } /* add the prefix */ @@ -1620,7 +1616,7 @@ static bool animsys_write_rna_setting(PointerRNA *ptr, char *path, int array_ind } /* Simple replacement based data-setting of the FCurve using RNA */ -bool BKE_animsys_execute_fcurve(PointerRNA *ptr, AnimMapper *remap, FCurve *fcu) +bool BKE_animsys_execute_fcurve(PointerRNA *ptr, AnimMapper *remap, FCurve *fcu, float curval) { char *path = NULL; bool free_path = false; @@ -1631,7 +1627,7 @@ bool BKE_animsys_execute_fcurve(PointerRNA *ptr, AnimMapper *remap, FCurve *fcu) /* write value to setting */ if (path) - ok = animsys_write_rna_setting(ptr, path, fcu->array_index, fcu->curval); + ok = animsys_write_rna_setting(ptr, path, fcu->array_index, curval); /* free temp path-info */ if (free_path) @@ -1654,8 +1650,8 @@ static void animsys_evaluate_fcurves(PointerRNA *ptr, ListBase *list, AnimMapper if ((fcu->grp == NULL) || (fcu->grp->flag & AGRP_MUTED) == 0) { /* check if this curve should be skipped */ if ((fcu->flag & (FCURVE_MUTED | FCURVE_DISABLED)) == 0) { - calculate_fcurve(fcu, ctime); - BKE_animsys_execute_fcurve(ptr, remap, fcu); + const float curval = calculate_fcurve(fcu, ctime); + BKE_animsys_execute_fcurve(ptr, remap, fcu, curval); } } } @@ -1684,8 +1680,8 @@ static void animsys_evaluate_drivers(PointerRNA *ptr, AnimData *adt, float ctime /* evaluate this using values set already in other places * NOTE: for 'layering' option later on, we should check if we should remove old value before adding * new to only be done when drivers only changed */ - calculate_fcurve(fcu, ctime); - ok = BKE_animsys_execute_fcurve(ptr, NULL, fcu); + const float curval = calculate_fcurve(fcu, ctime); + ok = BKE_animsys_execute_fcurve(ptr, NULL, fcu, curval); /* clear recalc flag */ driver->flag &= ~DRIVER_FLAG_RECALC; @@ -1753,8 +1749,8 @@ void animsys_evaluate_action_group(PointerRNA *ptr, bAction *act, bActionGroup * for (fcu = agrp->channels.first; (fcu) && (fcu->grp == agrp); fcu = fcu->next) { /* check if this curve should be skipped */ if ((fcu->flag & (FCURVE_MUTED | FCURVE_DISABLED)) == 0) { - calculate_fcurve(fcu, ctime); - BKE_animsys_execute_fcurve(ptr, remap, fcu); + const float curval = calculate_fcurve(fcu, ctime); + BKE_animsys_execute_fcurve(ptr, remap, fcu, curval); } } } @@ -2888,8 +2884,8 @@ void BKE_animsys_eval_driver(EvaluationContext *eval_ctx, * NOTE: for 'layering' option later on, we should check if we should remove old value before adding * new to only be done when drivers only changed */ //printf("\told val = %f\n", fcu->curval); - calculate_fcurve(fcu, eval_ctx->ctime); - ok = BKE_animsys_execute_fcurve(&id_ptr, NULL, fcu); + const float curval = calculate_fcurve(fcu, eval_ctx->ctime); + ok = BKE_animsys_execute_fcurve(&id_ptr, NULL, fcu, curval); //printf("\tnew val = %f\n", fcu->curval); /* clear recalc flag */ diff --git a/source/blender/blenkernel/intern/autoexec.c b/source/blender/blenkernel/intern/autoexec.c index d9462cd0262..bde06b02ae8 100644 --- a/source/blender/blenkernel/intern/autoexec.c +++ b/source/blender/blenkernel/intern/autoexec.c @@ -59,7 +59,10 @@ bool BKE_autoexec_match(const char *path) BLI_assert((U.flag & USER_SCRIPT_AUTOEXEC_DISABLE) == 0); for (path_cmp = U.autoexec_paths.first; path_cmp; path_cmp = path_cmp->next) { - if ((path_cmp->flag & USER_PATHCMP_GLOB)) { + if (path_cmp->path[0] == '\0') { + /* pass */ + } + else if ((path_cmp->flag & USER_PATHCMP_GLOB)) { if (fnmatch(path_cmp->path, path, fnmatch_flags) == 0) { return true; } diff --git a/source/blender/blenkernel/intern/brush.c b/source/blender/blenkernel/intern/brush.c index 31dac038e43..da7863096e3 100644 --- a/source/blender/blenkernel/intern/brush.c +++ b/source/blender/blenkernel/intern/brush.c @@ -852,7 +852,7 @@ int BKE_brush_size_get(const Scene *scene, const Brush *brush) UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings; int size = (ups->flag & UNIFIED_PAINT_SIZE) ? ups->size : brush->size; - return (int)((float)size * U.pixelsize); + return size; } int BKE_brush_use_locked_size(const Scene *scene, const Brush *brush) diff --git a/source/blender/blenkernel/intern/cdderivedmesh.c b/source/blender/blenkernel/intern/cdderivedmesh.c index af1ad4900b3..392a38773e7 100644 --- a/source/blender/blenkernel/intern/cdderivedmesh.c +++ b/source/blender/blenkernel/intern/cdderivedmesh.c @@ -1032,6 +1032,7 @@ static void cdDM_drawMappedFacesGLSL( if (matconv[a].attribs.totorco && matconv[a].attribs.orco.array) { matconv[a].datatypes[numdata].index = matconv[a].attribs.orco.gl_index; + matconv[a].datatypes[numdata].info_index = matconv[a].attribs.orco.gl_info_index; matconv[a].datatypes[numdata].size = 3; matconv[a].datatypes[numdata].type = GL_FLOAT; numdata++; @@ -1039,6 +1040,7 @@ static void cdDM_drawMappedFacesGLSL( for (b = 0; b < matconv[a].attribs.tottface; b++) { if (matconv[a].attribs.tface[b].array) { matconv[a].datatypes[numdata].index = matconv[a].attribs.tface[b].gl_index; + matconv[a].datatypes[numdata].info_index = matconv[a].attribs.tface[b].gl_info_index; matconv[a].datatypes[numdata].size = 2; matconv[a].datatypes[numdata].type = GL_FLOAT; numdata++; @@ -1047,6 +1049,7 @@ static void cdDM_drawMappedFacesGLSL( for (b = 0; b < matconv[a].attribs.totmcol; b++) { if (matconv[a].attribs.mcol[b].array) { matconv[a].datatypes[numdata].index = matconv[a].attribs.mcol[b].gl_index; + matconv[a].datatypes[numdata].info_index = matconv[a].attribs.mcol[b].gl_info_index; matconv[a].datatypes[numdata].size = 4; matconv[a].datatypes[numdata].type = GL_UNSIGNED_BYTE; numdata++; @@ -1055,6 +1058,7 @@ static void cdDM_drawMappedFacesGLSL( for (b = 0; b < matconv[a].attribs.tottang; b++) { if (matconv[a].attribs.tang[b].array) { matconv[a].datatypes[numdata].index = matconv[a].attribs.tang[b].gl_index; + matconv[a].datatypes[numdata].info_index = matconv[a].attribs.tang[b].gl_info_index; matconv[a].datatypes[numdata].size = 4; matconv[a].datatypes[numdata].type = GL_FLOAT; numdata++; @@ -2656,6 +2660,9 @@ void CDDM_calc_loop_normals(DerivedMesh *dm, const bool use_split_normals, const } /* #define DEBUG_CLNORS */ +#ifdef DEBUG_CLNORS +# include "BLI_linklist.h" +#endif void CDDM_calc_loop_normals_spacearr( DerivedMesh *dm, const bool use_split_normals, const float split_angle, MLoopNorSpaceArray *r_lnors_spacearr) diff --git a/source/blender/blenkernel/intern/customdata.c b/source/blender/blenkernel/intern/customdata.c index de79a30bd60..612f1f477e1 100644 --- a/source/blender/blenkernel/intern/customdata.c +++ b/source/blender/blenkernel/intern/customdata.c @@ -1853,8 +1853,6 @@ static CustomDataLayer *customData_add_layer__internal(CustomData *data, int typ (alloctype == CD_DUPLICATE) || (alloctype == CD_REFERENCE)); - BLI_assert(size >= 0); - if (!typeInfo->defaultname && CustomData_has_layer(data, type)) return &data->layers[CustomData_get_layer_index(data, type)]; diff --git a/source/blender/blenkernel/intern/editderivedmesh.c b/source/blender/blenkernel/intern/editderivedmesh.c index 6c117447664..ffd000eed88 100644 --- a/source/blender/blenkernel/intern/editderivedmesh.c +++ b/source/blender/blenkernel/intern/editderivedmesh.c @@ -57,6 +57,7 @@ #include "MEM_guardedalloc.h" #include "GPU_glew.h" +#include "GPU_buffers.h" #include "GPU_shader.h" #include "GPU_basic_shader.h" @@ -1405,6 +1406,24 @@ static void emDM_drawMappedFacesTex( emDM_drawFacesTex_common(dm, NULL, setDrawOptions, compareDrawOptions, userData); } +static void emdm_pass_attrib_update_uniforms(const DMVertexAttribs *attribs) +{ + int i; + if (attribs->totorco) { + glUniform1i(attribs->orco.gl_info_index, 0); + } + for (i = 0; i < attribs->tottface; i++) { + glUniform1i(attribs->tface[i].gl_info_index, 0); + } + for (i = 0; i < attribs->totmcol; i++) { + glUniform1i(attribs->mcol[i].gl_info_index, GPU_ATTR_INFO_SRGB); + } + + for (i = 0; i < attribs->tottang; i++) { + glUniform1i(attribs->tang[i].gl_info_index, 0); + } +} + /** * \note * @@ -1449,15 +1468,15 @@ static void emdm_pass_attrib_vertex_glsl(const DMVertexAttribs *attribs, const B glVertexAttrib2fv(attribs->tface[i].gl_index, uv); } for (i = 0; i < attribs->totmcol; i++) { - GLubyte col[4]; + float col[4]; if (attribs->mcol[i].em_offset != -1) { const MLoopCol *cp = BM_ELEM_CD_GET_VOID_P(loop, attribs->mcol[i].em_offset); - copy_v4_v4_uchar(col, &cp->r); + rgba_uchar_to_float(col, &cp->r); } else { - col[0] = 0; col[1] = 0; col[2] = 0; col[3] = 0; + col[0] = 0.0f; col[1] = 0.0f; col[2] = 0.0f; col[3] = 0.0f; } - glVertexAttrib4ubv(attribs->mcol[i].gl_index, col); + glVertexAttrib4fv(attribs->mcol[i].gl_index, col); } for (i = 0; i < attribs->tottang; i++) { @@ -1527,6 +1546,7 @@ static void emDM_drawMappedFacesGLSL( do_draw = setMaterial(matnr = new_matnr, &gattribs); if (do_draw) { DM_vertex_attributes_from_gpu(dm, &gattribs, &attribs); + emdm_pass_attrib_update_uniforms(&attribs); if (UNLIKELY(attribs.tottang && bm->elem_index_dirty & BM_LOOP)) { BM_mesh_elem_index_ensure(bm, BM_LOOP); } diff --git a/source/blender/blenkernel/intern/effect.c b/source/blender/blenkernel/intern/effect.c index e00d19b2b01..a5c4be364d2 100644 --- a/source/blender/blenkernel/intern/effect.c +++ b/source/blender/blenkernel/intern/effect.c @@ -596,7 +596,9 @@ int get_effector_data(EffectorCache *eff, EffectorData *efd, EffectedPoint *poin float cfra = eff->scene->r.cfra; int ret = 0; - if (eff->pd && eff->pd->shape==PFIELD_SHAPE_SURFACE && eff->surmd) { + /* In case surface object is in Edit mode when loading the .blend, surface modifier is never executed + * and bvhtree never built, see T48415. */ + if (eff->pd && eff->pd->shape==PFIELD_SHAPE_SURFACE && eff->surmd && eff->surmd->bvhtree) { /* closest point in the object surface is an effector */ float vec[3]; diff --git a/source/blender/blenkernel/intern/fcurve.c b/source/blender/blenkernel/intern/fcurve.c index a2b5a05feac..395161aa6ed 100644 --- a/source/blender/blenkernel/intern/fcurve.c +++ b/source/blender/blenkernel/intern/fcurve.c @@ -2671,7 +2671,7 @@ float evaluate_fcurve(FCurve *fcu, float evaltime) } /* Calculate the value of the given F-Curve at the given frame, and set its curval */ -void calculate_fcurve(FCurve *fcu, float ctime) +float calculate_fcurve(FCurve *fcu, float evaltime) { /* only calculate + set curval (overriding the existing value) if curve has * any data which warrants this... @@ -2680,7 +2680,12 @@ void calculate_fcurve(FCurve *fcu, float ctime) list_has_suitable_fmodifier(&fcu->modifiers, 0, FMI_TYPE_GENERATE_CURVE)) { /* calculate and set curval (evaluates driver too if necessary) */ - fcu->curval = evaluate_fcurve(fcu, ctime); + float curval = evaluate_fcurve(fcu, evaltime); + fcu->curval = curval; /* debug display only, not thread safe! */ + return curval; + } + else { + return 0.0f; } } diff --git a/source/blender/blenkernel/intern/font.c b/source/blender/blenkernel/intern/font.c index aed33d2c64d..98757407e89 100644 --- a/source/blender/blenkernel/intern/font.c +++ b/source/blender/blenkernel/intern/font.c @@ -541,7 +541,7 @@ int BKE_vfont_select_get(Object *ob, int *r_start, int *r_end) BLI_assert(ef->len >= 0); BLI_assert(ef->selstart >= 0 && ef->selstart <= ef->len + 1); - BLI_assert(ef->selend >= 0 && ef->selend <= ef->len); + BLI_assert(ef->selend >= 0 && ef->selend <= ef->len + 1); BLI_assert(ef->pos >= 0 && ef->pos <= ef->len); if (ef->selstart == 0) { diff --git a/source/blender/blenkernel/intern/idcode.c b/source/blender/blenkernel/intern/idcode.c index 68a741bc3fc..899ed548783 100644 --- a/source/blender/blenkernel/intern/idcode.c +++ b/source/blender/blenkernel/intern/idcode.c @@ -39,6 +39,7 @@ #include "BLT_translation.h" +#include "BKE_library.h" #include "BKE_idcode.h" typedef struct { @@ -54,6 +55,7 @@ typedef struct { /* plural need to match rna_main.c's MainCollectionDef */ /* WARNING! Keep it in sync with i18n contexts in BLT_translation.h */ static IDType idtypes[] = { + /** ID's directly below must all be in #Main, and be kept in sync with #MAX_LIBARRAY (membership, not order) */ { ID_AC, "Action", "actions", BLT_I18NCONTEXT_ID_ACTION, IDTYPE_FLAGS_ISLINKABLE }, { ID_AR, "Armature", "armatures", BLT_I18NCONTEXT_ID_ARMATURE, IDTYPE_FLAGS_ISLINKABLE }, { ID_BR, "Brush", "brushes", BLT_I18NCONTEXT_ID_BRUSH, IDTYPE_FLAGS_ISLINKABLE }, @@ -61,7 +63,6 @@ static IDType idtypes[] = { { ID_CU, "Curve", "curves", BLT_I18NCONTEXT_ID_CURVE, IDTYPE_FLAGS_ISLINKABLE }, { ID_GD, "GPencil", "grease_pencil", BLT_I18NCONTEXT_ID_GPENCIL, IDTYPE_FLAGS_ISLINKABLE }, /* rename gpencil */ { ID_GR, "Group", "groups", BLT_I18NCONTEXT_ID_GROUP, IDTYPE_FLAGS_ISLINKABLE }, - { ID_ID, "ID", "ids", BLT_I18NCONTEXT_ID_ID, 0 }, /* plural is fake */ { ID_IM, "Image", "images", BLT_I18NCONTEXT_ID_IMAGE, IDTYPE_FLAGS_ISLINKABLE }, { ID_IP, "Ipo", "ipos", "", IDTYPE_FLAGS_ISLINKABLE }, /* deprecated */ { ID_KE, "Key", "shape_keys", BLT_I18NCONTEXT_ID_SHAPEKEY, 0 }, @@ -89,8 +90,14 @@ static IDType idtypes[] = { { ID_VF, "VFont", "fonts", BLT_I18NCONTEXT_ID_VFONT, IDTYPE_FLAGS_ISLINKABLE }, { ID_WO, "World", "worlds", BLT_I18NCONTEXT_ID_WORLD, IDTYPE_FLAGS_ISLINKABLE }, { ID_WM, "WindowManager", "window_managers", BLT_I18NCONTEXT_ID_WINDOWMANAGER, 0 }, + + /** Keep last, not an ID exactly, only include for completeness */ + { ID_ID, "ID", "ids", BLT_I18NCONTEXT_ID_ID, 0 }, /* plural is fake */ }; +/* -1 for ID_ID */ +BLI_STATIC_ASSERT((ARRAY_SIZE(idtypes) - 1 == MAX_LIBARRAY), "Missing IDType"); + static IDType *idtype_from_name(const char *str) { int i = ARRAY_SIZE(idtypes); diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c index 911bf21b731..ecebc7336a2 100644 --- a/source/blender/blenkernel/intern/image.c +++ b/source/blender/blenkernel/intern/image.c @@ -109,8 +109,8 @@ static void image_add_view(Image *ima, const char *viewname, const char *filepat #define IMA_NO_INDEX 0x7FEFEFEF /* quick lookup: supports 1 million frames, thousand passes */ -#define IMA_MAKE_INDEX(frame, index) ((frame) << 10) + index -#define IMA_INDEX_FRAME(index) (index >> 10) +#define IMA_MAKE_INDEX(frame, index) (((frame) << 10) + (index)) +#define IMA_INDEX_FRAME(index) ((index) >> 10) /* #define IMA_INDEX_PASS(index) (index & ~1023) */ diff --git a/source/blender/blenkernel/intern/library_idmap.c b/source/blender/blenkernel/intern/library_idmap.c new file mode 100644 index 00000000000..fd78d9b23ce --- /dev/null +++ b/source/blender/blenkernel/intern/library_idmap.c @@ -0,0 +1,174 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include <string.h> +#include <stdlib.h> + +#include "MEM_guardedalloc.h" + +#include "BLI_utildefines.h" +#include "BLI_ghash.h" +#include "BLI_listbase.h" + +#include "DNA_ID.h" + +#include "BKE_idcode.h" +#include "BKE_library.h" +#include "BKE_library_idmap.h" /* own include */ + +/** \file blender/blenkernel/intern/library_map.c + * \ingroup bke + * + * Utility functions for faster ID lookups. + */ + +/** \name BKE_main_idmap API + * + * Cache ID (name, library lookups). + * This doesn't account for adding/removing data-blocks, + * and should only be used when performing many lookups. + * + * \note GHash's are initialized on demand, + * since its likely some types will never have lookups run on them, + * so its a waste to create and never use. + * \{ */ + +struct IDNameLib_Key { + /** ``ID.name + 2``: without the ID type prefix, since each id type gets it's own 'map' */ + const char *name; + /** ``ID.lib``: */ + const Library *lib; +}; + +struct IDNameLib_TypeMap { + GHash *map; + short id_type; + /* only for storage of keys in the ghash, avoid many single allocs */ + struct IDNameLib_Key *keys; +}; + +/** + * Opaque structure, external API users only see this. + */ +struct IDNameLib_Map { + struct IDNameLib_TypeMap type_maps[MAX_LIBARRAY]; + struct Main *bmain; +}; + +static struct IDNameLib_TypeMap *main_idmap_from_idcode(struct IDNameLib_Map *id_map, short id_type) +{ + for (int i = 0; i < MAX_LIBARRAY; i++) { + if (id_map->type_maps[i].id_type == id_type) { + return &id_map->type_maps[i]; + } + } + return NULL; +} + +struct IDNameLib_Map *BKE_main_idmap_create(struct Main *bmain) +{ + struct IDNameLib_Map *id_map = MEM_mallocN(sizeof(*id_map), __func__); + + int index = 0; + while (index < MAX_LIBARRAY) { + id_map->type_maps[index].map = NULL; + id_map->type_maps[index].id_type = BKE_idcode_iter_step(&index); + } + BLI_assert(index == MAX_LIBARRAY); + + id_map->bmain = bmain; + + return id_map; +} + +struct Main *BKE_main_idmap_main_get(struct IDNameLib_Map *id_map) +{ + return id_map->bmain; +} + +static unsigned int idkey_hash(const void *ptr) +{ + const struct IDNameLib_Key *idkey = ptr; + unsigned int key = BLI_ghashutil_strhash(idkey->name); + if (idkey->lib) { + key ^= BLI_ghashutil_ptrhash(idkey->lib); + } + return key; +} + +static bool idkey_cmp(const void *a, const void *b) +{ + const struct IDNameLib_Key *idkey_a = a; + const struct IDNameLib_Key *idkey_b = b; + return strcmp(idkey_a->name, idkey_b->name) || (idkey_a->lib != idkey_b->lib); +} + +ID *BKE_main_idmap_lookup(struct IDNameLib_Map *id_map, short id_type, const char *name, const Library *lib) +{ + struct IDNameLib_TypeMap *type_map = main_idmap_from_idcode(id_map, id_type); + + if (UNLIKELY(type_map == NULL)) { + return NULL; + } + + /* lazy init */ + if (type_map->map == NULL) { + ListBase *lb = which_libbase(id_map->bmain, id_type); + const int lb_len = BLI_listbase_count(lb); + if (lb_len == 0) { + return NULL; + } + type_map->map = BLI_ghash_new_ex(idkey_hash, idkey_cmp, __func__, lb_len); + type_map->keys = MEM_mallocN(sizeof(struct IDNameLib_Key) * lb_len, __func__); + + GHash *map = type_map->map; + struct IDNameLib_Key *key = type_map->keys; + + for (ID *id = lb->first; id; id = id->next, key++) { + key->name = id->name + 2; + key->lib = id->lib; + BLI_ghash_insert(map, key, id); + } + } + + const struct IDNameLib_Key key_lookup = {name, lib}; + return BLI_ghash_lookup(type_map->map, &key_lookup); +} + +ID *BKE_main_idmap_lookup_id(struct IDNameLib_Map *id_map, const ID *id) +{ + return BKE_main_idmap_lookup(id_map, GS(id->name), id->name + 2, id->lib); +} + +void BKE_main_idmap_destroy(struct IDNameLib_Map *id_map) +{ + struct IDNameLib_TypeMap *type_map = id_map->type_maps; + for (int i = 0; i < MAX_LIBARRAY; i++, type_map++) { + if (type_map->map) { + BLI_ghash_free(type_map->map, NULL, NULL); + type_map->map = NULL; + MEM_freeN(type_map->keys); + } + } + + MEM_freeN(id_map); +} + +/** \} */ diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c index 1fec725dbb7..30f82a50ed9 100644 --- a/source/blender/blenkernel/intern/material.c +++ b/source/blender/blenkernel/intern/material.c @@ -1148,7 +1148,6 @@ static void init_render_nodetree(bNodeTree *ntree, Material *basemat, int r_mode /* parses the geom+tex nodes */ ntreeShaderGetTexcoMode(ntree, r_mode, &basemat->texco, &basemat->mode_l); - basemat->nmap_tangent_names_count = 0; for (node = ntree->nodes.first; node; node = node->next) { if (node->id) { if (GS(node->id->name) == ID_MA) { @@ -1199,7 +1198,7 @@ void init_render_material(Material *mat, int r_mode, float *amb) * mode_l will have it set when all node materials are shadeless. */ mat->mode_l = (mat->mode & MA_MODE_PIPELINE) | MA_SHLESS; mat->mode2_l = mat->mode2 & MA_MODE2_PIPELINE; - + mat->nmap_tangent_names_count = 0; init_render_nodetree(mat->nodetree, mat, r_mode, amb); if (!mat->nodetree->execdata) diff --git a/source/blender/blenkernel/intern/mesh_evaluate.c b/source/blender/blenkernel/intern/mesh_evaluate.c index 577a21285f8..1c86fbcfe8e 100644 --- a/source/blender/blenkernel/intern/mesh_evaluate.c +++ b/source/blender/blenkernel/intern/mesh_evaluate.c @@ -677,7 +677,7 @@ static void split_loop_nor_single_do(LoopSplitTaskDataCommon *common_data, LoopS */ copy_v3_v3(*lnor, polynors[mp_index]); - /* printf("BASIC: handling loop %d / edge %d / vert %d\n", ml_curr_index, ml_curr->e, ml_curr->v); */ + /* printf("BASIC: handling loop %d / edge %d / vert %d / poly %d\n", ml_curr_index, ml_curr->e, ml_curr->v, mp_index); */ /* If needed, generate this (simple!) lnor space. */ if (lnors_spacearr) { @@ -3262,14 +3262,14 @@ void BKE_mesh_mdisp_flip(MDisps *md, const bool use_loop_mdisp_flip) */ void BKE_mesh_polygon_flip_ex( MPoly *mpoly, MLoop *mloop, CustomData *ldata, - MDisps *mdisp, const bool use_loop_mdisp_flip) + float (*lnors)[3], MDisps *mdisp, const bool use_loop_mdisp_flip) { int loopstart = mpoly->loopstart; int loopend = loopstart + mpoly->totloop - 1; const bool loops_in_ldata = (CustomData_get_layer(ldata, CD_MLOOP) == mloop); if (mdisp) { - for (int i = mpoly->loopstart; i <= loopend; i++) { + for (int i = loopstart; i <= loopend; i++) { BKE_mesh_mdisp_flip(&mdisp[i], use_loop_mdisp_flip); } } @@ -3288,6 +3288,9 @@ void BKE_mesh_polygon_flip_ex( if (!loops_in_ldata) { SWAP(MLoop, mloop[loopstart], mloop[loopend]); } + if (lnors) { + swap_v3_v3(lnors[loopstart], lnors[loopend]); + } CustomData_swap(ldata, loopstart, loopend); } /* Even if we did not swap the other 'pivot' loop, we need to set its swapped edge. */ @@ -3299,7 +3302,7 @@ void BKE_mesh_polygon_flip_ex( void BKE_mesh_polygon_flip(MPoly *mpoly, MLoop *mloop, CustomData *ldata) { MDisps *mdisp = CustomData_get_layer(ldata, CD_MDISPS); - BKE_mesh_polygon_flip_ex(mpoly, mloop, ldata, mdisp, true); + BKE_mesh_polygon_flip_ex(mpoly, mloop, ldata, NULL, mdisp, true); } /** @@ -3315,7 +3318,7 @@ void BKE_mesh_polygons_flip( int i; for (mp = mpoly, i = 0; i < totpoly; mp++, i++) { - BKE_mesh_polygon_flip_ex(mp, mloop, ldata, mdisp, true); + BKE_mesh_polygon_flip_ex(mp, mloop, ldata, NULL, mdisp, true); } } diff --git a/source/blender/blenkernel/intern/object_update.c b/source/blender/blenkernel/intern/object_update.c index 03348adeabc..2468cb8b697 100644 --- a/source/blender/blenkernel/intern/object_update.c +++ b/source/blender/blenkernel/intern/object_update.c @@ -347,3 +347,10 @@ void BKE_object_eval_uber_data(EvaluationContext *eval_ctx, ob->recalc &= ~(OB_RECALC_DATA | OB_RECALC_TIME); } + +void BKE_object_eval_proxy_backlink(EvaluationContext *UNUSED(eval_ctx), Object *ob) +{ + if (ob->proxy) { + ob->proxy->proxy_from = ob; + } +} diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c index af30c1af66b..106720c4f1f 100644 --- a/source/blender/blenkernel/intern/particle.c +++ b/source/blender/blenkernel/intern/particle.c @@ -141,6 +141,11 @@ int count_particles_mod(ParticleSystem *psys, int totgr, int cur) #define PATH_CACHE_BUF_SIZE 1024 +static ParticleCacheKey *pcache_key_segment_endpoint_safe(ParticleCacheKey *key) +{ + return (key->segments > 0) ? (key + (key->segments - 1)) : key; +} + static ParticleCacheKey **psys_alloc_path_cache_buffers(ListBase *bufs, int tot, int totkeys) { LinkData *buf; @@ -2205,20 +2210,22 @@ static void psys_thread_create_path(ParticleTask *task, struct ChildParticle *cp /* modify weights to create parting */ if (p_fac > 0.f) { + const ParticleCacheKey *key_0_last = pcache_key_segment_endpoint_safe(key[0]); for (w = 0; w < 4; w++) { - if (w && weight[w] > 0.f) { + if (w && (weight[w] > 0.f)) { + const ParticleCacheKey *key_w_last = pcache_key_segment_endpoint_safe(key[w]); float d; if (part->flag & PART_CHILD_LONG_HAIR) { /* For long hair use tip distance/root distance as parting factor instead of root to tip angle. */ float d1 = len_v3v3(key[0]->co, key[w]->co); - float d2 = len_v3v3((key[0] + key[0]->segments - 1)->co, (key[w] + key[w]->segments - 1)->co); + float d2 = len_v3v3(key_0_last->co, key_w_last->co); d = d1 > 0.f ? d2 / d1 - 1.f : 10000.f; } else { float v1[3], v2[3]; - sub_v3_v3v3(v1, (key[0] + key[0]->segments - 1)->co, key[0]->co); - sub_v3_v3v3(v2, (key[w] + key[w]->segments - 1)->co, key[w]->co); + sub_v3_v3v3(v1, key_0_last->co, key[0]->co); + sub_v3_v3v3(v2, key_w_last->co, key[w]->co); normalize_v3(v1); normalize_v3(v2); diff --git a/source/blender/blenkernel/intern/pbvh.c b/source/blender/blenkernel/intern/pbvh.c index d73f087a3fe..58ec75dc706 100644 --- a/source/blender/blenkernel/intern/pbvh.c +++ b/source/blender/blenkernel/intern/pbvh.c @@ -637,6 +637,7 @@ void BKE_pbvh_free(PBVH *bvh) BLI_gset_free(node->bm_other_verts, NULL); } } + GPU_free_pbvh_buffer_multires(&bvh->grid_common_gpu_buffer); if (bvh->deformed) { if (bvh->verts) { @@ -1100,7 +1101,7 @@ static void pbvh_update_draw_buffers(PBVH *bvh, PBVHNode **nodes, int totnode) node->totprim, bvh->grid_hidden, bvh->gridkey.grid_size, - &bvh->gridkey); + &bvh->gridkey, &bvh->grid_common_gpu_buffer); break; case PBVH_FACES: node->draw_buffers = diff --git a/source/blender/blenkernel/intern/pbvh_intern.h b/source/blender/blenkernel/intern/pbvh_intern.h index bae323dedef..4d2307c3e12 100644 --- a/source/blender/blenkernel/intern/pbvh_intern.h +++ b/source/blender/blenkernel/intern/pbvh_intern.h @@ -145,6 +145,11 @@ struct PBVH { const DMFlagMat *grid_flag_mats; int totgrid; BLI_bitmap **grid_hidden; + /* index_buf of GPU_PBVH_Buffers can be the same for all 'fully drawn' nodes (same size). + * Previously was stored in a static var in gpu_buffer.c, but this breaks in case we handle several different + * objects in sculpt mode with different sizes at the same time, so now storing that common gpu buffer + * in an opaque pointer per pbvh. See T47637. */ + struct GridCommonGPUBuffer *grid_common_gpu_buffer; /* Only used during BVH build and update, * don't need to remain valid after */ diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index d307ba1811b..a3393b6b9c0 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -2193,6 +2193,13 @@ bool BKE_scene_use_shading_nodes_custom(Scene *scene) return (type && type->flag & RE_USE_SHADING_NODES_CUSTOM); } +bool BKE_scene_use_world_space_shading(Scene *scene) +{ + const RenderEngineType *type = RE_engines_find(scene->r.engine); + return ((scene->r.mode & R_USE_WS_SHADING) || + (type && (type->flag & RE_USE_SHADING_NODES))); +} + bool BKE_scene_use_spherical_stereo(Scene *scene) { RenderEngineType *type = RE_engines_find(scene->r.engine); diff --git a/source/blender/blenkernel/intern/shrinkwrap.c b/source/blender/blenkernel/intern/shrinkwrap.c index e855f6faa22..518d8d68919 100644 --- a/source/blender/blenkernel/intern/shrinkwrap.c +++ b/source/blender/blenkernel/intern/shrinkwrap.c @@ -44,6 +44,7 @@ #include "BLI_math.h" #include "BLI_utildefines.h" +#include "BLI_task.h" #include "BKE_shrinkwrap.h" #include "BKE_DerivedMesh.h" @@ -58,7 +59,7 @@ /* for timing... */ #if 0 -# include "PIL_time.h" +# include "PIL_time_utildefines.h" #else # define TIMEIT_BENCH(expr, id) (expr) #endif @@ -66,16 +67,88 @@ /* Util macros */ #define OUT_OF_MEMORY() ((void)printf("Shrinkwrap: Out of memory\n")) +typedef struct ShrinkwrapCalcCBData { + ShrinkwrapCalcData *calc; + + void *treeData; + void *auxData; + BVHTree *targ_tree; + BVHTree *aux_tree; + void *targ_callback; + void *aux_callback; + + float *proj_axis; + SpaceTransform *local2aux; +} ShrinkwrapCalcCBData; + /* * Shrinkwrap to the nearest vertex * * it builds a kdtree of vertexs we can attach to and then * for each vertex performs a nearest vertex search on the tree */ -static void shrinkwrap_calc_nearest_vertex(ShrinkwrapCalcData *calc) +static void shrinkwrap_calc_nearest_vertex_cb_ex( + void *userdata, void *userdata_chunk, const int i, const int UNUSED(threadid)) { - int i; + ShrinkwrapCalcCBData *data = userdata; + + ShrinkwrapCalcData *calc = data->calc; + BVHTreeFromMesh *treeData = data->treeData; + BVHTreeNearest *nearest = userdata_chunk; + + float *co = calc->vertexCos[i]; + float tmp_co[3]; + float weight = defvert_array_find_weight_safe(calc->dvert, i, calc->vgroup); + + if (calc->invert_vgroup) { + weight = 1.0f - weight; + } + + if (weight == 0.0f) { + return; + } + + /* Convert the vertex to tree coordinates */ + if (calc->vert) { + copy_v3_v3(tmp_co, calc->vert[i].co); + } + else { + copy_v3_v3(tmp_co, co); + } + BLI_space_transform_apply(&calc->local2target, tmp_co); + + /* Use local proximity heuristics (to reduce the nearest search) + * + * If we already had an hit before.. we assume this vertex is going to have a close hit to that other vertex + * so we can initiate the "nearest.dist" with the expected value to that last hit. + * This will lead in pruning of the search tree. */ + if (nearest->index != -1) + nearest->dist_sq = len_squared_v3v3(tmp_co, nearest->co); + else + nearest->dist_sq = FLT_MAX; + + BLI_bvhtree_find_nearest(treeData->tree, tmp_co, nearest, treeData->nearest_callback, treeData); + + + /* Found the nearest vertex */ + if (nearest->index != -1) { + /* Adjusting the vertex weight, + * so that after interpolating it keeps a certain distance from the nearest position */ + if (nearest->dist_sq > FLT_EPSILON) { + const float dist = sqrtf(nearest->dist_sq); + weight *= (dist - calc->keepDist) / dist; + } + + /* Convert the coordinates back to mesh coordinates */ + copy_v3_v3(tmp_co, nearest->co); + BLI_space_transform_invert(&calc->local2target, tmp_co); + + interp_v3_v3v3(co, co, tmp_co, weight); /* linear interpolation */ + } +} +static void shrinkwrap_calc_nearest_vertex(ShrinkwrapCalcData *calc) +{ BVHTreeFromMesh treeData = NULL_BVHTreeFromMesh; BVHTreeNearest nearest = NULL_BVHTreeNearest; @@ -89,61 +162,11 @@ static void shrinkwrap_calc_nearest_vertex(ShrinkwrapCalcData *calc) /* 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) if (calc->numVerts > BKE_MESH_OMP_LIMIT) -#endif - for (i = 0; i < calc->numVerts; ++i) { - float *co = calc->vertexCos[i]; - float tmp_co[3]; - float weight = defvert_array_find_weight_safe(calc->dvert, i, calc->vgroup); - - if (calc->invert_vgroup) { - weight = 1.0f - weight; - } - - if (weight == 0.0f) { - continue; - } - - - /* Convert the vertex to tree coordinates */ - if (calc->vert) { - copy_v3_v3(tmp_co, calc->vert[i].co); - } - else { - copy_v3_v3(tmp_co, co); - } - BLI_space_transform_apply(&calc->local2target, tmp_co); - - /* Use local proximity heuristics (to reduce the nearest search) - * - * If we already had an hit before.. we assume this vertex is going to have a close hit to that other vertex - * so we can initiate the "nearest.dist" with the expected value to that last hit. - * This will lead in pruning of the search tree. */ - if (nearest.index != -1) - nearest.dist_sq = len_squared_v3v3(tmp_co, nearest.co); - else - nearest.dist_sq = FLT_MAX; - - BLI_bvhtree_find_nearest(treeData.tree, tmp_co, &nearest, treeData.nearest_callback, &treeData); - - - /* Found the nearest vertex */ - if (nearest.index != -1) { - /* Adjusting the vertex weight, - * so that after interpolating it keeps a certain distance from the nearest position */ - if (nearest.dist_sq > FLT_EPSILON) { - const float dist = sqrtf(nearest.dist_sq); - weight *= (dist - calc->keepDist) / dist; - } - /* Convert the coordinates back to mesh coordinates */ - copy_v3_v3(tmp_co, nearest.co); - BLI_space_transform_invert(&calc->local2target, tmp_co); - - interp_v3_v3v3(co, co, tmp_co, weight); /* linear interpolation */ - } - } + ShrinkwrapCalcCBData data = {.calc = calc, .treeData = &treeData}; + BLI_task_parallel_range_ex( + 0, calc->numVerts, &data, &nearest, sizeof(nearest), shrinkwrap_calc_nearest_vertex_cb_ex, + calc->numVerts > BKE_MESH_OMP_LIMIT, false); free_bvhtree_from_mesh(&treeData); } @@ -230,13 +253,109 @@ bool BKE_shrinkwrap_project_normal( return false; } +static void shrinkwrap_calc_normal_projection_cb_ex( + void *userdata, void *userdata_chunk, const int i, const int UNUSED(threadid)) +{ + ShrinkwrapCalcCBData *data = userdata; + + ShrinkwrapCalcData *calc = data->calc; + void *treeData = data->treeData; + void *auxData = data->auxData; + BVHTree *targ_tree = data->targ_tree; + BVHTree *aux_tree = data->aux_tree; + void *targ_callback = data->targ_callback; + void *aux_callback = data->aux_callback; + + float *proj_axis = data->proj_axis; + SpaceTransform *local2aux = data->local2aux; + + BVHTreeRayHit *hit = userdata_chunk; + + const float proj_limit_squared = calc->smd->projLimit * calc->smd->projLimit; + float *co = calc->vertexCos[i]; + float tmp_co[3], tmp_no[3]; + float weight = defvert_array_find_weight_safe(calc->dvert, i, calc->vgroup); + + if (calc->invert_vgroup) { + weight = 1.0f - weight; + } + + if (weight == 0.0f) { + return; + } + + if (calc->vert) { + /* calc->vert contains verts from derivedMesh */ + /* this coordinated are deformed by vertexCos only for normal projection (to get correct normals) */ + /* for other cases calc->varts contains undeformed coordinates and vertexCos should be used */ + if (calc->smd->projAxis == MOD_SHRINKWRAP_PROJECT_OVER_NORMAL) { + copy_v3_v3(tmp_co, calc->vert[i].co); + normal_short_to_float_v3(tmp_no, calc->vert[i].no); + } + else { + copy_v3_v3(tmp_co, co); + copy_v3_v3(tmp_no, proj_axis); + } + } + else { + copy_v3_v3(tmp_co, co); + copy_v3_v3(tmp_no, proj_axis); + } + + + hit->index = -1; + hit->dist = BVH_RAYCAST_DIST_MAX; /* TODO: we should use FLT_MAX here, but sweepsphere code isn't prepared for that */ + + /* Project over positive direction of axis */ + if (calc->smd->shrinkOpts & MOD_SHRINKWRAP_PROJECT_ALLOW_POS_DIR) { + if (aux_tree) { + BKE_shrinkwrap_project_normal( + 0, tmp_co, tmp_no, + local2aux, aux_tree, hit, + aux_callback, auxData); + } + + BKE_shrinkwrap_project_normal( + calc->smd->shrinkOpts, tmp_co, tmp_no, + &calc->local2target, targ_tree, hit, + targ_callback, treeData); + } + + /* Project over negative direction of axis */ + if (calc->smd->shrinkOpts & MOD_SHRINKWRAP_PROJECT_ALLOW_NEG_DIR) { + float inv_no[3]; + negate_v3_v3(inv_no, tmp_no); + + if (aux_tree) { + BKE_shrinkwrap_project_normal( + 0, tmp_co, inv_no, + local2aux, aux_tree, hit, + aux_callback, auxData); + } + + BKE_shrinkwrap_project_normal( + calc->smd->shrinkOpts, tmp_co, inv_no, + &calc->local2target, targ_tree, hit, + targ_callback, treeData); + } + + /* don't set the initial dist (which is more efficient), + * because its calculated in the targets space, we want the dist in our own space */ + if (proj_limit_squared != 0.0f) { + if (len_squared_v3v3(hit->co, co) > proj_limit_squared) { + hit->index = -1; + } + } + + if (hit->index != -1) { + madd_v3_v3v3fl(hit->co, hit->co, tmp_no, calc->keepDist); + interp_v3_v3v3(co, co, hit->co, weight); + } +} static void shrinkwrap_calc_normal_projection(ShrinkwrapCalcData *calc, bool for_render) { - int i; - /* Options about projection direction */ - const float proj_limit_squared = calc->smd->projLimit * calc->smd->projLimit; float proj_axis[3] = {0.0f, 0.0f, 0.0f}; /* Raycast and tree stuff */ @@ -305,7 +424,7 @@ static void shrinkwrap_calc_normal_projection(ShrinkwrapCalcData *calc, bool for } if (targ_tree) { BVHTree *aux_tree = NULL; - void *aux_callback; + void *aux_callback = NULL; if (auxMesh != NULL) { /* use editmesh to avoid array allocation */ if (calc->smd->auxTarget && auxMesh->type == DM_TYPE_EDITBMESH) { @@ -316,99 +435,22 @@ static void shrinkwrap_calc_normal_projection(ShrinkwrapCalcData *calc, bool for } } else { - if ((aux_tree = bvhtree_from_mesh_looptri(&dmauxdata_stack, calc->target, 0.0, 4, 6)) != NULL) { + if ((aux_tree = bvhtree_from_mesh_looptri(&dmauxdata_stack, auxMesh, 0.0, 4, 6)) != NULL) { aux_callback = dmauxdata_stack.raycast_callback; auxData = &dmauxdata_stack; } } } /* After sucessufuly build the trees, start projection vertexs */ - -#ifndef __APPLE__ -#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]; - float tmp_co[3], tmp_no[3]; - float weight = defvert_array_find_weight_safe(calc->dvert, i, calc->vgroup); - - if (calc->invert_vgroup) { - weight = 1.0f - weight; - } - - if (weight == 0.0f) { - continue; - } - - if (calc->vert) { - /* calc->vert contains verts from derivedMesh */ - /* this coordinated are deformed by vertexCos only for normal projection (to get correct normals) */ - /* for other cases calc->varts contains undeformed coordinates and vertexCos should be used */ - if (calc->smd->projAxis == MOD_SHRINKWRAP_PROJECT_OVER_NORMAL) { - copy_v3_v3(tmp_co, calc->vert[i].co); - normal_short_to_float_v3(tmp_no, calc->vert[i].no); - } - else { - copy_v3_v3(tmp_co, co); - copy_v3_v3(tmp_no, proj_axis); - } - } - else { - copy_v3_v3(tmp_co, co); - copy_v3_v3(tmp_no, proj_axis); - } - - - hit.index = -1; - hit.dist = BVH_RAYCAST_DIST_MAX; /* TODO: we should use FLT_MAX here, but sweepsphere code isn't prepared for that */ - - /* Project over positive direction of axis */ - if (calc->smd->shrinkOpts & MOD_SHRINKWRAP_PROJECT_ALLOW_POS_DIR) { - - if (aux_tree) { - BKE_shrinkwrap_project_normal( - 0, tmp_co, tmp_no, - &local2aux, aux_tree, &hit, - aux_callback, auxData); - } - - BKE_shrinkwrap_project_normal( - calc->smd->shrinkOpts, tmp_co, tmp_no, - &calc->local2target, targ_tree, &hit, - targ_callback, treeData); - } - - /* Project over negative direction of axis */ - if (calc->smd->shrinkOpts & MOD_SHRINKWRAP_PROJECT_ALLOW_NEG_DIR) { - float inv_no[3]; - negate_v3_v3(inv_no, tmp_no); - - if (aux_tree) { - BKE_shrinkwrap_project_normal( - 0, tmp_co, inv_no, - &local2aux, aux_tree, &hit, - aux_callback, auxData); - } - - BKE_shrinkwrap_project_normal( - calc->smd->shrinkOpts, tmp_co, inv_no, - &calc->local2target, targ_tree, &hit, - targ_callback, treeData); - } - - /* don't set the initial dist (which is more efficient), - * because its calculated in the targets space, we want the dist in our own space */ - if (proj_limit_squared != 0.0f) { - if (len_squared_v3v3(hit.co, co) > proj_limit_squared) { - hit.index = -1; - } - } - - if (hit.index != -1) { - madd_v3_v3v3fl(hit.co, hit.co, tmp_no, calc->keepDist); - interp_v3_v3v3(co, co, hit.co, weight); - } - } + ShrinkwrapCalcCBData data = { + .calc = calc, + .treeData = treeData, .targ_tree = targ_tree, .targ_callback = targ_callback, + .auxData = auxData, .aux_tree = aux_tree, .aux_callback = aux_callback, + .proj_axis = proj_axis, .local2aux = &local2aux, + }; + BLI_task_parallel_range_ex( + 0, calc->numVerts, &data, &hit, sizeof(hit), shrinkwrap_calc_normal_projection_cb_ex, + calc->numVerts > BKE_MESH_OMP_LIMIT, false); } /* free data structures */ @@ -428,10 +470,75 @@ static void shrinkwrap_calc_normal_projection(ShrinkwrapCalcData *calc, bool for * it builds a BVHTree from the target mesh and then performs a * NN matches for each vertex */ -static void shrinkwrap_calc_nearest_surface_point(ShrinkwrapCalcData *calc) +static void shrinkwrap_calc_nearest_surface_point_cb_ex( + void *userdata, void *userdata_chunk, const int i, const int UNUSED(threadid)) { - int i; + ShrinkwrapCalcCBData *data = userdata; + + ShrinkwrapCalcData *calc = data->calc; + BVHTreeFromMesh *treeData = data->treeData; + BVHTreeNearest *nearest = userdata_chunk; + + float *co = calc->vertexCos[i]; + float tmp_co[3]; + float weight = defvert_array_find_weight_safe(calc->dvert, i, calc->vgroup); + + if (calc->invert_vgroup) { + weight = 1.0f - weight; + } + + if (weight == 0.0f) { + return; + } + + /* Convert the vertex to tree coordinates */ + if (calc->vert) { + copy_v3_v3(tmp_co, calc->vert[i].co); + } + else { + copy_v3_v3(tmp_co, co); + } + BLI_space_transform_apply(&calc->local2target, tmp_co); + + /* Use local proximity heuristics (to reduce the nearest search) + * + * If we already had an hit before.. we assume this vertex is going to have a close hit to that other vertex + * so we can initiate the "nearest.dist" with the expected value to that last hit. + * This will lead in pruning of the search tree. */ + if (nearest->index != -1) + nearest->dist_sq = len_squared_v3v3(tmp_co, nearest->co); + else + nearest->dist_sq = FLT_MAX; + + BLI_bvhtree_find_nearest(treeData->tree, tmp_co, nearest, treeData->nearest_callback, treeData); + + /* Found the nearest vertex */ + if (nearest->index != -1) { + if (calc->smd->shrinkOpts & MOD_SHRINKWRAP_KEEP_ABOVE_SURFACE) { + /* Make the vertex stay on the front side of the face */ + madd_v3_v3v3fl(tmp_co, nearest->co, nearest->no, calc->keepDist); + } + else { + /* Adjusting the vertex weight, + * so that after interpolating it keeps a certain distance from the nearest position */ + const float dist = sasqrt(nearest->dist_sq); + if (dist > FLT_EPSILON) { + /* linear interpolation */ + interp_v3_v3v3(tmp_co, tmp_co, nearest->co, (dist - calc->keepDist) / dist); + } + else { + copy_v3_v3(tmp_co, nearest->co); + } + } + /* Convert the coordinates back to mesh coordinates */ + BLI_space_transform_invert(&calc->local2target, tmp_co); + interp_v3_v3v3(co, co, tmp_co, weight); /* linear interpolation */ + } +} + +static void shrinkwrap_calc_nearest_surface_point(ShrinkwrapCalcData *calc) +{ BVHTreeFromMesh treeData = NULL_BVHTreeFromMesh; BVHTreeNearest nearest = NULL_BVHTreeNearest; @@ -446,67 +553,11 @@ static void shrinkwrap_calc_nearest_surface_point(ShrinkwrapCalcData *calc) nearest.index = -1; nearest.dist_sq = FLT_MAX; - /* Find the nearest vertex */ -#ifndef __APPLE__ -#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]; - float tmp_co[3]; - float weight = defvert_array_find_weight_safe(calc->dvert, i, calc->vgroup); - - if (calc->invert_vgroup) { - weight = 1.0f - weight; - } - - if (weight == 0.0f) continue; - - /* Convert the vertex to tree coordinates */ - if (calc->vert) { - copy_v3_v3(tmp_co, calc->vert[i].co); - } - else { - copy_v3_v3(tmp_co, co); - } - BLI_space_transform_apply(&calc->local2target, tmp_co); - - /* Use local proximity heuristics (to reduce the nearest search) - * - * If we already had an hit before.. we assume this vertex is going to have a close hit to that other vertex - * so we can initiate the "nearest.dist" with the expected value to that last hit. - * This will lead in pruning of the search tree. */ - if (nearest.index != -1) - nearest.dist_sq = len_squared_v3v3(tmp_co, nearest.co); - else - nearest.dist_sq = FLT_MAX; - - BLI_bvhtree_find_nearest(treeData.tree, tmp_co, &nearest, treeData.nearest_callback, &treeData); - - /* Found the nearest vertex */ - if (nearest.index != -1) { - if (calc->smd->shrinkOpts & MOD_SHRINKWRAP_KEEP_ABOVE_SURFACE) { - /* Make the vertex stay on the front side of the face */ - madd_v3_v3v3fl(tmp_co, nearest.co, nearest.no, calc->keepDist); - } - else { - /* Adjusting the vertex weight, - * so that after interpolating it keeps a certain distance from the nearest position */ - const float dist = sasqrt(nearest.dist_sq); - if (dist > FLT_EPSILON) { - /* linear interpolation */ - interp_v3_v3v3(tmp_co, tmp_co, nearest.co, (dist - calc->keepDist) / dist); - } - else { - copy_v3_v3(tmp_co, nearest.co); - } - } - - /* Convert the coordinates back to mesh coordinates */ - BLI_space_transform_invert(&calc->local2target, tmp_co); - interp_v3_v3v3(co, co, tmp_co, weight); /* linear interpolation */ - } - } + ShrinkwrapCalcCBData data = {.calc = calc, .treeData = &treeData}; + BLI_task_parallel_range_ex( + 0, calc->numVerts, &data, &nearest, sizeof(nearest), shrinkwrap_calc_nearest_surface_point_cb_ex, + calc->numVerts > BKE_MESH_OMP_LIMIT, false); free_bvhtree_from_mesh(&treeData); } diff --git a/source/blender/blenkernel/intern/subsurf_ccg.c b/source/blender/blenkernel/intern/subsurf_ccg.c index 5fd418fadfc..88bc3fb9854 100644 --- a/source/blender/blenkernel/intern/subsurf_ccg.c +++ b/source/blender/blenkernel/intern/subsurf_ccg.c @@ -2996,6 +2996,7 @@ static void ccgDM_drawMappedFacesGLSL(DerivedMesh *dm, if (matconv[a].attribs.totorco && matconv[a].attribs.orco.array) { matconv[a].datatypes[numdata].index = matconv[a].attribs.orco.gl_index; + matconv[a].datatypes[numdata].info_index = matconv[a].attribs.orco.gl_info_index; matconv[a].datatypes[numdata].size = 3; matconv[a].datatypes[numdata].type = GL_FLOAT; numdata++; @@ -3003,6 +3004,7 @@ static void ccgDM_drawMappedFacesGLSL(DerivedMesh *dm, for (b = 0; b < matconv[a].attribs.tottface; b++) { if (matconv[a].attribs.tface[b].array) { matconv[a].datatypes[numdata].index = matconv[a].attribs.tface[b].gl_index; + matconv[a].datatypes[numdata].info_index = matconv[a].attribs.tface[b].gl_info_index; matconv[a].datatypes[numdata].size = 2; matconv[a].datatypes[numdata].type = GL_FLOAT; numdata++; @@ -3011,6 +3013,7 @@ static void ccgDM_drawMappedFacesGLSL(DerivedMesh *dm, for (b = 0; b < matconv[a].attribs.totmcol; b++) { if (matconv[a].attribs.mcol[b].array) { matconv[a].datatypes[numdata].index = matconv[a].attribs.mcol[b].gl_index; + matconv[a].datatypes[numdata].info_index = matconv[a].attribs.mcol[b].gl_info_index; matconv[a].datatypes[numdata].size = 4; matconv[a].datatypes[numdata].type = GL_UNSIGNED_BYTE; numdata++; @@ -3019,6 +3022,7 @@ static void ccgDM_drawMappedFacesGLSL(DerivedMesh *dm, for (b = 0; b < matconv[a].attribs.tottang; b++) { if (matconv[a].attribs.tottang && matconv[a].attribs.tang[b].array) { matconv[a].datatypes[numdata].index = matconv[a].attribs.tang[b].gl_index; + matconv[a].datatypes[numdata].info_index = matconv[a].attribs.tang[b].gl_info_index; matconv[a].datatypes[numdata].size = 4; matconv[a].datatypes[numdata].type = GL_FLOAT; numdata++; |