Geometry Node: Make Capture Attributes more lazy #105264

Closed
Iliya Katushenock wants to merge 4 commits from mod_moder/blender:more_lazynes_capture_attribute_node into main

When changing the target branch, be careful to rebase the branch in your fork to match. See documentation.
156 changed files with 2245 additions and 1835 deletions
Showing only changes of commit 06e456c64f - Show all commits

View File

@ -216,7 +216,7 @@ def use_upstream_workflow(args: argparse.Namespace) -> bool:
return make_utils.git_remote_exist(args.git_command, "upstream")
def work_tree_update_upstream_workflow(args: argparse.Namespace, use_fetch=True) -> str:
def work_tree_update_upstream_workflow(args: argparse.Namespace, use_fetch: bool = True) -> str:
"""
Update the Blender repository using the Github style of fork organization
@ -240,7 +240,7 @@ def work_tree_update_upstream_workflow(args: argparse.Namespace, use_fetch=True)
return ""
def work_tree_update(args: argparse.Namespace, use_fetch=True) -> str:
def work_tree_update(args: argparse.Namespace, use_fetch: bool = True) -> str:
"""
Update the Git working tree using the best strategy
@ -295,7 +295,7 @@ def external_script_copy_old_submodule_over(args: argparse.Namespace, directory_
shutil.copytree(bare_repo_dir, external_dir / ".git")
git_config = external_dir / ".git" / "config"
call((args.git_command, "config", "--file", git_config, "--unset", "core.worktree"))
call((args.git_command, "config", "--file", str(git_config), "--unset", "core.worktree"))
def external_script_initialize_if_needed(args: argparse.Namespace,
@ -322,12 +322,12 @@ def external_script_initialize_if_needed(args: argparse.Namespace,
blender_url = make_utils.git_get_remote_url(args.git_command, origin_name)
external_url = resolve_external_url(blender_url, repo_name)
call((args.git_command, "clone", "--origin", origin_name, external_url, external_dir))
call((args.git_command, "clone", "--origin", origin_name, external_url, str(external_dir)))
def external_script_add_origin_if_needed(args: argparse.Namespace,
repo_name: str,
directory_name: str) -> str:
directory_name: str) -> None:
"""
Add remote called 'origin' if there is a fork of the external repository available
@ -335,7 +335,7 @@ def external_script_add_origin_if_needed(args: argparse.Namespace,
"""
if not use_upstream_workflow(args):
return ""
return
cwd = os.getcwd()
@ -382,7 +382,7 @@ def external_script_add_origin_if_needed(args: argparse.Namespace,
finally:
os.chdir(cwd)
return ""
return
def external_scripts_update(args: argparse.Namespace,

View File

@ -68,7 +68,7 @@ def git_branch_exists(git_command: str, branch: str) -> bool:
)
def git_get_remote_url(git_command: str, remote_name: str) -> bool:
def git_get_remote_url(git_command: str, remote_name: str) -> str:
return check_output((git_command, "ls-remote", "--get-url", remote_name))

View File

@ -1228,4 +1228,4 @@ void GHOST_GetVulkanBackbuffer(GHOST_WindowHandle windowhandle,
window->getVulkanBackbuffer(image, framebuffer, render_pass, extent, fb_id);
}
#endif /* WITH_VULKAN */
#endif /* WITH_VULKAN_BACKEND */

View File

@ -1226,7 +1226,7 @@ static GHOST_Context *create_glx_context(Window window,
GHOST_Context *GHOST_WindowX11::newDrawingContext(GHOST_TDrawingContextType type)
{
#if defined(WITH_VULKAN)
#if defined(WITH_VULKAN_BACKEND)
if (type == GHOST_kDrawingContextTypeVulkan) {
GHOST_Context *context = new GHOST_ContextVK(m_wantStereoVisual,
GHOST_kVulkanPlatformX11,

View File

@ -363,6 +363,7 @@ const bTheme U_theme_default = {
.handle_sel_vect = RGBA(0x40c030ff),
.handle_sel_align = RGBA(0xf090a0ff),
.vertex_size = 3,
.edge_width = 1,
.outline_width = 1,
.obcenter_dia = 6,
.facedot_size = 3,
@ -717,6 +718,7 @@ const bTheme U_theme_default = {
.handle_sel_auto = RGBA(0xf0ff40ff),
.handle_sel_align = RGBA(0xf090a0ff),
.vertex_size = 3,
.edge_width = 1,
.outline_width = 1,
.facedot_size = 3,
.editmesh_active = RGBA(0xffffff40),

View File

@ -60,12 +60,12 @@ extern "C" {
/**
* Call after changing vertex positions to tag lazily calculated caches for recomputation.
*/
void BKE_mesh_tag_coords_changed(struct Mesh *mesh);
void BKE_mesh_tag_positions_changed(struct Mesh *mesh);
/**
* Call after moving every mesh vertex by the same translation.
*/
void BKE_mesh_tag_coords_changed_uniformly(struct Mesh *mesh);
void BKE_mesh_tag_positions_changed_uniformly(struct Mesh *mesh);
void BKE_mesh_tag_topology_changed(struct Mesh *mesh);
@ -164,6 +164,7 @@ struct Mesh *BKE_mesh_new_nomain_from_template(
struct Mesh *BKE_mesh_new_nomain_from_template_ex(const struct Mesh *me_src,
int verts_len,
int edges_len,
int tessface_len,
int loops_len,
int polys_len,
struct CustomData_MeshMasks mask);
@ -341,7 +342,7 @@ void BKE_mesh_recalc_looptri_with_normals(const struct MLoop *mloop,
* from a vertices surrounding faces, or the normalized position of vertices connected to no faces.
* \warning May still return null if the mesh is empty.
*/
const float (*BKE_mesh_vertex_normals_ensure(const struct Mesh *mesh))[3];
const float (*BKE_mesh_vert_normals_ensure(const struct Mesh *mesh))[3];
/**
* Return the normal direction of every polygon, which is defined by the winding direction of its
@ -364,13 +365,13 @@ void BKE_mesh_normals_tag_dirty(struct Mesh *mesh);
* calculated automatically.
*
* \note In order to clear the dirty flag, this function should be followed by a call to
* #BKE_mesh_vertex_normals_clear_dirty. This is separate so that normals are still tagged dirty
* #BKE_mesh_vert_normals_clear_dirty. This is separate so that normals are still tagged dirty
* while they are being assigned.
*
* \warning The memory returned by this function is not initialized if it was not previously
* allocated.
*/
float (*BKE_mesh_vertex_normals_for_write(struct Mesh *mesh))[3];
float (*BKE_mesh_vert_normals_for_write(struct Mesh *mesh))[3];
/**
* Retrieve write access to the cached polygon normals, ensuring that they are allocated but *not*
@ -389,7 +390,7 @@ float (*BKE_mesh_poly_normals_for_write(struct Mesh *mesh))[3];
/**
* Mark the mesh's vertex normals non-dirty, for when they are calculated or assigned manually.
*/
void BKE_mesh_vertex_normals_clear_dirty(struct Mesh *mesh);
void BKE_mesh_vert_normals_clear_dirty(struct Mesh *mesh);
/**
* Mark the mesh's poly normals non-dirty, for when they are calculated or assigned manually.
@ -400,7 +401,7 @@ void BKE_mesh_poly_normals_clear_dirty(struct Mesh *mesh);
* Return true if the mesh vertex normals either are not stored or are dirty.
* This can be used to help decide whether to transfer them when copying a mesh.
*/
bool BKE_mesh_vertex_normals_are_dirty(const struct Mesh *mesh);
bool BKE_mesh_vert_normals_are_dirty(const struct Mesh *mesh);
/**
* Return true if the mesh polygon normals either are not stored or are dirty.
@ -430,7 +431,7 @@ void BKE_mesh_calc_normals_poly(const float (*vert_positions)[3],
/**
* Calculate face and vertex normals directly into result arrays.
*
* \note Usually #BKE_mesh_vertex_normals_ensure is the preferred way to access vertex normals,
* \note Usually #BKE_mesh_vert_normals_ensure is the preferred way to access vertex normals,
* since they may already be calculated and cached on the mesh.
*/
void BKE_mesh_calc_normals_poly_and_vertex(const float (*vert_positions)[3],
@ -446,7 +447,7 @@ void BKE_mesh_calc_normals_poly_and_vertex(const float (*vert_positions)[3],
* Calculate vertex and face normals, storing the result in custom data layers on the mesh.
*
* \note It is usually preferable to calculate normals lazily with
* #BKE_mesh_vertex_normals_ensure, but some areas (perhaps unnecessarily)
* #BKE_mesh_vert_normals_ensure, but some areas (perhaps unnecessarily)
* can also calculate them eagerly.
*/
void BKE_mesh_calc_normals(struct Mesh *me);
@ -1059,9 +1060,9 @@ inline blender::Span<blender::float3> Mesh::poly_normals() const
this->totpoly};
}
inline blender::Span<blender::float3> Mesh::vertex_normals() const
inline blender::Span<blender::float3> Mesh::vert_normals() const
{
return {reinterpret_cast<const blender::float3 *>(BKE_mesh_vertex_normals_ensure(this)),
return {reinterpret_cast<const blender::float3 *>(BKE_mesh_vert_normals_ensure(this)),
this->totvert};
}

View File

@ -44,7 +44,7 @@ void BKE_mesh_runtime_reset_edit_data(struct Mesh *mesh);
* directly or making other large changes to topology. It does not need to be called on new meshes.
*
* For "smaller" changes to meshes like updating positions, consider calling a more specific update
* function like #BKE_mesh_tag_coords_changed.
* function like #BKE_mesh_tag_positions_changed.
*
* Also note that some derived caches like #CD_NORMAL and #CD_TANGENT are stored directly in
* #CustomData.

View File

@ -21,9 +21,9 @@ struct MovieDistortion;
/**
* Checks if image was already loaded, then returns same image otherwise creates new.
* does not load ibuf itself pass on optional frame for #name images.
* does not load ibuf itself pass on optional frame for `filepath` images.
*/
struct MovieClip *BKE_movieclip_file_add(struct Main *bmain, const char *name);
struct MovieClip *BKE_movieclip_file_add(struct Main *bmain, const char *filepath);
struct MovieClip *BKE_movieclip_file_add_exists_ex(struct Main *bmain,
const char *filepath,
bool *r_exists);
@ -106,9 +106,9 @@ bool BKE_movieclip_proxy_enabled(struct MovieClip *clip);
float BKE_movieclip_remap_scene_to_clip_frame(const struct MovieClip *clip, float framenr);
float BKE_movieclip_remap_clip_to_scene_frame(const struct MovieClip *clip, float framenr);
void BKE_movieclip_filename_for_frame(struct MovieClip *clip,
void BKE_movieclip_filepath_for_frame(struct MovieClip *clip,
const struct MovieClipUser *user,
char *name);
char *filepath);
/**
* Read image buffer from the given movie clip without acquiring the #LOCK_MOVIECLIP lock.

View File

@ -103,9 +103,9 @@ bool txt_add_char(struct Text *text, unsigned int add);
bool txt_add_raw_char(struct Text *text, unsigned int add);
bool txt_replace_char(struct Text *text, unsigned int add);
bool txt_unindent(struct Text *text);
void txt_comment(struct Text *text);
void txt_indent(struct Text *text);
bool txt_uncomment(struct Text *text);
void txt_comment(struct Text *text, const char *prefix);
bool txt_uncomment(struct Text *text, const char *prefix);
void txt_move_lines(struct Text *text, int direction);
void txt_duplicate_line(struct Text *text);
int txt_setcurr_tab_spaces(struct Text *text, int space);

View File

@ -54,6 +54,10 @@ bool BKE_vfont_is_builtin(const struct VFont *vfont);
void BKE_vfont_builtin_register(const void *mem, int size);
void BKE_vfont_free_data(struct VFont *vfont);
/**
* Return the built-in #VFont, without adding a user (the user-count may be zero).
* The caller is responsible for adding a user.
*/
struct VFont *BKE_vfont_builtin_get(void);
struct VFont *BKE_vfont_load(struct Main *bmain, const char *filepath);
struct VFont *BKE_vfont_load_exists_ex(struct Main *bmain, const char *filepath, bool *r_exists);

View File

@ -580,7 +580,7 @@ static void bvhtree_from_mesh_setup_data(BVHTree *tree,
const MEdge *edge,
const MFace *face,
const MLoop *loop,
const MLoopTri *looptri,
const Span<MLoopTri> looptris,
BVHTreeFromMesh *r_data)
{
memset(r_data, 0, sizeof(*r_data));
@ -591,7 +591,7 @@ static void bvhtree_from_mesh_setup_data(BVHTree *tree,
r_data->edge = edge;
r_data->face = face;
r_data->loop = loop;
r_data->looptri = looptri;
r_data->looptri = looptris.data();
switch (bvh_cache_type) {
case BVHTREE_FROM_VERTS:
@ -779,7 +779,7 @@ BVHTree *bvhtree_from_mesh_verts_ex(BVHTreeFromMesh *data,
if (data) {
/* Setup BVHTreeFromMesh */
bvhtree_from_mesh_setup_data(
tree, BVHTREE_FROM_VERTS, vert_positions, nullptr, nullptr, nullptr, nullptr, data);
tree, BVHTREE_FROM_VERTS, vert_positions, nullptr, nullptr, nullptr, {}, data);
}
return tree;
@ -914,7 +914,7 @@ BVHTree *bvhtree_from_mesh_edges_ex(BVHTreeFromMesh *data,
if (data) {
/* Setup BVHTreeFromMesh */
bvhtree_from_mesh_setup_data(
tree, BVHTREE_FROM_EDGES, vert_positions, edge, nullptr, nullptr, nullptr, data);
tree, BVHTREE_FROM_EDGES, vert_positions, edge, nullptr, nullptr, {}, data);
}
return tree;
@ -1037,16 +1037,15 @@ static BVHTree *bvhtree_from_mesh_looptri_create_tree(float epsilon,
int axis,
const float (*positions)[3],
const MLoop *mloop,
const MLoopTri *looptri,
const int looptri_num,
const Span<MLoopTri> looptris,
const BitSpan looptri_mask,
int looptri_num_active)
{
if (!looptri_mask.is_empty()) {
BLI_assert(IN_RANGE_INCL(looptri_num_active, 0, looptri_num));
BLI_assert(IN_RANGE_INCL(looptri_num_active, 0, looptris.size()));
}
else {
looptri_num_active = looptri_num;
looptri_num_active = looptris.size();
}
if (looptri_num_active == 0) {
return nullptr;
@ -1059,16 +1058,16 @@ static BVHTree *bvhtree_from_mesh_looptri_create_tree(float epsilon,
return nullptr;
}
if (positions && looptri) {
for (int i = 0; i < looptri_num; i++) {
if (positions && !looptris.is_empty()) {
for (const int i : looptris.index_range()) {
float co[3][3];
if (!looptri_mask.is_empty() && !looptri_mask[i]) {
continue;
}
copy_v3_v3(co[0], positions[mloop[looptri[i].tri[0]].v]);
copy_v3_v3(co[1], positions[mloop[looptri[i].tri[1]].v]);
copy_v3_v3(co[2], positions[mloop[looptri[i].tri[2]].v]);
copy_v3_v3(co[0], positions[mloop[looptris[i].tri[0]].v]);
copy_v3_v3(co[1], positions[mloop[looptris[i].tri[1]].v]);
copy_v3_v3(co[2], positions[mloop[looptris[i].tri[2]].v]);
BLI_bvhtree_insert(tree, i, co[0], 3);
}
@ -1121,8 +1120,7 @@ BVHTree *bvhtree_from_mesh_looptri_ex(BVHTreeFromMesh *data,
axis,
vert_positions,
mloop,
looptri,
looptri_num,
{looptri, looptri_num},
looptri_mask,
looptri_num_active);
@ -1130,8 +1128,14 @@ BVHTree *bvhtree_from_mesh_looptri_ex(BVHTreeFromMesh *data,
if (data) {
/* Setup BVHTreeFromMesh */
bvhtree_from_mesh_setup_data(
tree, BVHTREE_FROM_LOOPTRI, vert_positions, nullptr, nullptr, mloop, looptri, data);
bvhtree_from_mesh_setup_data(tree,
BVHTREE_FROM_LOOPTRI,
vert_positions,
nullptr,
nullptr,
mloop,
{looptri, looptri_num},
data);
}
return tree;
@ -1208,11 +1212,9 @@ BVHTree *BKE_bvhtree_from_mesh_get(struct BVHTreeFromMesh *data,
{
BVHCache **bvh_cache_p = (BVHCache **)&mesh->runtime->bvh_cache;
const MLoopTri *looptri = nullptr;
int looptri_len = 0;
Span<MLoopTri> looptris;
if (ELEM(bvh_cache_type, BVHTREE_FROM_LOOPTRI, BVHTREE_FROM_LOOPTRI_NO_HIDDEN)) {
looptri = BKE_mesh_runtime_looptri_ensure(mesh);
looptri_len = BKE_mesh_runtime_looptri_len(mesh);
looptris = mesh->looptris();
}
const float(*positions)[3] = reinterpret_cast<const float(*)[3]>(mesh->vert_positions().data());
const Span<MEdge> edges = mesh->edges();
@ -1225,7 +1227,7 @@ BVHTree *BKE_bvhtree_from_mesh_get(struct BVHTreeFromMesh *data,
edges.data(),
(const MFace *)CustomData_get_layer(&mesh->fdata, CD_MFACE),
loops.data(),
looptri,
looptris,
data);
bool lock_started = false;
@ -1278,20 +1280,13 @@ BVHTree *BKE_bvhtree_from_mesh_get(struct BVHTreeFromMesh *data,
mask = looptri_no_hidden_map_get(
mesh->polys(),
attributes.lookup_or_default(".hide_poly", ATTR_DOMAIN_FACE, false),
looptri_len,
looptris.size(),
&mask_bits_act_len);
ATTR_FALLTHROUGH;
}
case BVHTREE_FROM_LOOPTRI:
data->tree = bvhtree_from_mesh_looptri_create_tree(0.0f,
tree_type,
6,
positions,
loops.data(),
looptri,
looptri_len,
mask,
mask_bits_act_len);
data->tree = bvhtree_from_mesh_looptri_create_tree(
0.0f, tree_type, 6, positions, loops.data(), looptris, mask, mask_bits_act_len);
break;
case BVHTREE_FROM_EM_VERTS:
case BVHTREE_FROM_EM_EDGES:

View File

@ -222,7 +222,7 @@ static DerivedMesh *cdDM_from_mesh_ex(Mesh *mesh,
&dm->vertData, CD_PROP_FLOAT3, "position", mesh->totvert));
/* Though this may be an unnecessary calculation, simply retrieving the layer may return nothing
* or dirty normals. */
cddm->vert_normals = BKE_mesh_vertex_normals_ensure(mesh);
cddm->vert_normals = BKE_mesh_vert_normals_ensure(mesh);
cddm->medge = static_cast<MEdge *>(
CustomData_get_layer_for_write(&dm->edgeData, CD_MEDGE, mesh->totedge));
cddm->mloop = static_cast<MLoop *>(

View File

@ -836,9 +836,8 @@ static bool cloth_from_object(
static void cloth_from_mesh(ClothModifierData *clmd, const Object *ob, Mesh *mesh)
{
const blender::Span<MLoop> loops = mesh->loops();
const MLoopTri *looptri = BKE_mesh_runtime_looptri_ensure(mesh);
const blender::Span<MLoopTri> looptris = mesh->looptris();
const uint mvert_num = mesh->totvert;
const uint looptri_num = BKE_mesh_runtime_looptri_len(mesh);
/* Allocate our vertices. */
clmd->clothObject->mvert_num = mvert_num;
@ -853,14 +852,14 @@ static void cloth_from_mesh(ClothModifierData *clmd, const Object *ob, Mesh *mes
/* save face information */
if (clmd->hairdata == nullptr) {
clmd->clothObject->primitive_num = looptri_num;
clmd->clothObject->primitive_num = looptris.size();
}
else {
clmd->clothObject->primitive_num = mesh->totedge;
}
clmd->clothObject->tri = static_cast<MVertTri *>(
MEM_malloc_arrayN(looptri_num, sizeof(MVertTri), __func__));
MEM_malloc_arrayN(looptris.size(), sizeof(MVertTri), __func__));
if (clmd->clothObject->tri == nullptr) {
cloth_free_modifier(clmd);
BKE_modifier_set_error(
@ -869,7 +868,7 @@ static void cloth_from_mesh(ClothModifierData *clmd, const Object *ob, Mesh *mes
return;
}
BKE_mesh_runtime_verttri_from_looptri(
clmd->clothObject->tri, loops.data(), looptri, looptri_num);
clmd->clothObject->tri, loops.data(), looptris.data(), looptris.size());
clmd->clothObject->edges = mesh->edges().data();
@ -1185,7 +1184,7 @@ static Mesh *cloth_make_rest_mesh(ClothModifierData *clmd, Mesh *mesh)
for (const int i : positions.index_range()) {
positions[i] = verts[i].xrest;
}
BKE_mesh_tag_coords_changed(new_mesh);
BKE_mesh_tag_positions_changed(new_mesh);
return new_mesh;
}
@ -1531,7 +1530,7 @@ static bool cloth_build_springs(ClothModifierData *clmd, Mesh *mesh)
BKE_bvhtree_from_mesh_get(&treedata, tmp_mesh ? tmp_mesh : mesh, BVHTREE_FROM_LOOPTRI, 2);
rng = BLI_rng_new_srandom(0);
const float(*vert_normals)[3] = BKE_mesh_vertex_normals_ensure(tmp_mesh ? tmp_mesh : mesh);
const float(*vert_normals)[3] = BKE_mesh_vert_normals_ensure(tmp_mesh ? tmp_mesh : mesh);
for (int i = 0; i < mvert_num; i++) {
if (find_internal_spring_target_vertex(

View File

@ -546,7 +546,7 @@ static void contarget_get_mesh_mat(Object *ob, const char *substring, float mat[
}
}
else if (me_eval) {
const float(*vert_normals)[3] = BKE_mesh_vertex_normals_ensure(me_eval);
const float(*vert_normals)[3] = BKE_mesh_vert_normals_ensure(me_eval);
const MDeformVert *dvert = CustomData_get_layer(&me_eval->vdata, CD_MDEFORMVERT);
const float(*positions)[3] = BKE_mesh_vert_positions(me_eval);
int numVerts = me_eval->totvert;

View File

@ -383,7 +383,7 @@ static void data_transfer_dtdata_type_preprocess(Mesh *me_src,
const bool *sharp_edges = static_cast<const bool *>(
CustomData_get_layer_named(&me_dst->edata, CD_PROP_BOOL, "sharp_edge"));
BKE_mesh_normals_loop_split(positions_dst,
BKE_mesh_vertex_normals_ensure(me_dst),
BKE_mesh_vert_normals_ensure(me_dst),
num_verts_dst,
edges_dst.data(),
edges_dst.size(),
@ -442,7 +442,7 @@ static void data_transfer_dtdata_type_postprocess(Object * /*ob_src*/,
/* Note loop_nors_dst contains our custom normals as transferred from source... */
BKE_mesh_normals_loop_custom_set(positions_dst,
BKE_mesh_vertex_normals_ensure(me_dst),
BKE_mesh_vert_normals_ensure(me_dst),
num_verts_dst,
edges_dst.data(),
edges_dst.size(),
@ -1344,7 +1344,7 @@ bool BKE_object_data_transfer_ex(struct Depsgraph *depsgraph,
BLI_assert((ob_src != ob_dst) && (ob_src->type == OB_MESH) && (ob_dst->type == OB_MESH));
if (me_dst) {
dirty_nors_dst = BKE_mesh_vertex_normals_are_dirty(me_dst);
dirty_nors_dst = BKE_mesh_vert_normals_are_dirty(me_dst);
/* Never create needed custom layers on passed destination mesh
* (assumed to *not* be ob_dst->data, aka modifier case). */
use_create = false;

View File

@ -1481,7 +1481,7 @@ struct DynamicPaintSetInitColorData {
blender::Span<MLoop> loops;
const float (*mloopuv)[2];
const MLoopTri *mlooptri;
blender::Span<MLoopTri> looptris;
const MLoopCol *mloopcol;
ImagePool *pool;
@ -1498,7 +1498,7 @@ static void dynamic_paint_set_init_color_tex_to_vcol_cb(void *__restrict userdat
PaintPoint *pPoint = (PaintPoint *)sData->type_data;
const blender::Span<MLoop> loops = data->loops;
const MLoopTri *mlooptri = data->mlooptri;
const blender::Span<MLoopTri> looptris = data->looptris;
const float(*mloopuv)[2] = data->mloopuv;
ImagePool *pool = data->pool;
Tex *tex = data->surface->init_texture;
@ -1509,11 +1509,11 @@ static void dynamic_paint_set_init_color_tex_to_vcol_cb(void *__restrict userdat
for (int j = 3; j--;) {
TexResult texres = {0};
const uint vert = loops[mlooptri[i].tri[j]].v;
const uint vert = loops[looptris[i].tri[j]].v;
/* remap to [-1.0, 1.0] */
uv[0] = mloopuv[mlooptri[i].tri[j]][0] * 2.0f - 1.0f;
uv[1] = mloopuv[mlooptri[i].tri[j]][1] * 2.0f - 1.0f;
uv[0] = mloopuv[looptris[i].tri[j]][0] * 2.0f - 1.0f;
uv[1] = mloopuv[looptris[i].tri[j]][1] * 2.0f - 1.0f;
multitex_ext_safe(tex, uv, &texres, pool, scene_color_manage, false);
@ -1533,7 +1533,7 @@ static void dynamic_paint_set_init_color_tex_to_imseq_cb(void *__restrict userda
const PaintSurfaceData *sData = data->surface->data;
PaintPoint *pPoint = (PaintPoint *)sData->type_data;
const MLoopTri *mlooptri = data->mlooptri;
const blender::Span<MLoopTri> looptris = data->looptris;
const float(*mloopuv)[2] = data->mloopuv;
Tex *tex = data->surface->init_texture;
ImgSeqFormatData *f_data = (ImgSeqFormatData *)sData->format_data;
@ -1548,7 +1548,7 @@ static void dynamic_paint_set_init_color_tex_to_imseq_cb(void *__restrict userda
/* collect all uvs */
for (int j = 3; j--;) {
copy_v2_v2(&uv[j * 3], mloopuv[mlooptri[f_data->uv_p[i].tri_index].tri[j]]);
copy_v2_v2(&uv[j * 3], mloopuv[looptris[f_data->uv_p[i].tri_index].tri[j]]);
}
/* interpolate final uv pos */
@ -1572,7 +1572,7 @@ static void dynamic_paint_set_init_color_vcol_to_imseq_cb(
const PaintSurfaceData *sData = data->surface->data;
PaintPoint *pPoint = (PaintPoint *)sData->type_data;
const MLoopTri *mlooptri = data->mlooptri;
const blender::Span<MLoopTri> looptris = data->looptris;
const MLoopCol *mloopcol = data->mloopcol;
ImgSeqFormatData *f_data = (ImgSeqFormatData *)sData->format_data;
const int samples = (data->surface->flags & MOD_DPAINT_ANTIALIAS) ? 5 : 1;
@ -1583,7 +1583,7 @@ static void dynamic_paint_set_init_color_vcol_to_imseq_cb(
/* collect color values */
for (int j = 3; j--;) {
rgba_uchar_to_float(colors[j], (const uchar *)&mloopcol[mlooptri[tri_idx].tri[j]].r);
rgba_uchar_to_float(colors[j], (const uchar *)&mloopcol[looptris[tri_idx].tri[j]].r);
}
/* interpolate final color */
@ -1619,8 +1619,7 @@ static void dynamicPaint_setInitialColor(const Scene *scene, DynamicPaintSurface
Tex *tex = surface->init_texture;
const blender::Span<MLoop> loops = mesh->loops();
const MLoopTri *mlooptri = BKE_mesh_runtime_looptri_ensure(mesh);
const int tottri = BKE_mesh_runtime_looptri_len(mesh);
const blender::Span<MLoopTri> looptris = mesh->looptris();
char uvname[MAX_CUSTOMDATA_LAYER_NAME];
@ -1645,22 +1644,22 @@ static void dynamicPaint_setInitialColor(const Scene *scene, DynamicPaintSurface
DynamicPaintSetInitColorData data{};
data.surface = surface;
data.loops = loops;
data.mlooptri = mlooptri;
data.looptris = looptris;
data.mloopuv = mloopuv;
data.pool = pool;
data.scene_color_manage = scene_color_manage;
TaskParallelSettings settings;
BLI_parallel_range_settings_defaults(&settings);
settings.use_threading = (tottri > 1000);
settings.use_threading = (looptris.size() > 1000);
BLI_task_parallel_range(
0, tottri, &data, dynamic_paint_set_init_color_tex_to_vcol_cb, &settings);
0, looptris.size(), &data, dynamic_paint_set_init_color_tex_to_vcol_cb, &settings);
BKE_image_pool_free(pool);
}
else if (surface->format == MOD_DPAINT_SURFACE_F_IMAGESEQ) {
DynamicPaintSetInitColorData data{};
data.surface = surface;
data.mlooptri = mlooptri;
data.looptris = looptris;
data.mloopuv = mloopuv;
data.scene_color_manage = scene_color_manage;
@ -1688,7 +1687,7 @@ static void dynamicPaint_setInitialColor(const Scene *scene, DynamicPaintSurface
}
}
else if (surface->format == MOD_DPAINT_SURFACE_F_IMAGESEQ) {
const MLoopTri *mlooptri = BKE_mesh_runtime_looptri_ensure(mesh);
const blender::Span<MLoopTri> looptris = mesh->looptris();
const MLoopCol *col = static_cast<const MLoopCol *>(
CustomData_get_layer_named(&mesh->ldata, CD_PROP_BYTE_COLOR, surface->init_layername));
if (!col) {
@ -1697,7 +1696,7 @@ static void dynamicPaint_setInitialColor(const Scene *scene, DynamicPaintSurface
DynamicPaintSetInitColorData data{};
data.surface = surface;
data.mlooptri = mlooptri;
data.looptris = looptris;
data.mloopcol = col;
TaskParallelSettings settings;
@ -1828,7 +1827,7 @@ static void dynamicPaint_applySurfaceDisplace(DynamicPaintSurface *surface, Mesh
DynamicPaintModifierApplyData data{};
data.surface = surface;
data.vert_positions = BKE_mesh_vert_positions_for_write(result);
data.vert_normals = BKE_mesh_vertex_normals_ensure(result);
data.vert_normals = BKE_mesh_vert_normals_ensure(result);
TaskParallelSettings settings;
BLI_parallel_range_settings_defaults(&settings);
@ -2029,20 +2028,20 @@ static Mesh *dynamicPaint_Modifier_apply(DynamicPaintModifierData *pmd, Object *
DynamicPaintModifierApplyData data{};
data.surface = surface;
data.vert_positions = BKE_mesh_vert_positions_for_write(result);
data.vert_normals = BKE_mesh_vertex_normals_ensure(result);
data.vert_normals = BKE_mesh_vert_normals_ensure(result);
TaskParallelSettings settings;
BLI_parallel_range_settings_defaults(&settings);
settings.use_threading = (sData->total_points > 1000);
BLI_task_parallel_range(
0, sData->total_points, &data, dynamic_paint_apply_surface_wave_cb, &settings);
BKE_mesh_tag_coords_changed(result);
BKE_mesh_tag_positions_changed(result);
}
/* displace */
if (surface->type == MOD_DPAINT_SURFACE_T_DISPLACE) {
dynamicPaint_applySurfaceDisplace(surface, result);
BKE_mesh_tag_coords_changed(result);
BKE_mesh_tag_positions_changed(result);
}
}
}
@ -2192,10 +2191,9 @@ struct DynamicPaintCreateUVSurfaceData {
PaintUVPoint *tempPoints;
Vec3f *tempWeights;
const MLoopTri *mlooptri;
blender::Span<MLoopTri> looptris;
const float (*mloopuv)[2];
blender::Span<MLoop> loops;
int tottri;
const Bounds2D *faceBB;
uint32_t *active_points;
@ -2212,10 +2210,9 @@ static void dynamic_paint_create_uv_surface_direct_cb(void *__restrict userdata,
PaintUVPoint *tempPoints = data->tempPoints;
Vec3f *tempWeights = data->tempWeights;
const MLoopTri *mlooptri = data->mlooptri;
const blender::Span<MLoopTri> looptris = data->looptris;
const float(*mloopuv)[2] = data->mloopuv;
const blender::Span<MLoop> loops = data->loops;
const int tottri = data->tottri;
const Bounds2D *faceBB = data->faceBB;
@ -2259,16 +2256,16 @@ static void dynamic_paint_create_uv_surface_direct_cb(void *__restrict userdata,
/* Loop through every face in the mesh */
/* XXX TODO: This is *horrible* with big meshes, should use a 2D BVHTree over UV tris here!
*/
for (int i = 0; i < tottri; i++) {
for (const int i : looptris.index_range()) {
/* Check uv bb */
if ((faceBB[i].min[0] > point[sample][0]) || (faceBB[i].min[1] > point[sample][1]) ||
(faceBB[i].max[0] < point[sample][0]) || (faceBB[i].max[1] < point[sample][1])) {
continue;
}
const float *uv1 = mloopuv[mlooptri[i].tri[0]];
const float *uv2 = mloopuv[mlooptri[i].tri[1]];
const float *uv3 = mloopuv[mlooptri[i].tri[2]];
const float *uv1 = mloopuv[looptris[i].tri[0]];
const float *uv2 = mloopuv[looptris[i].tri[1]];
const float *uv3 = mloopuv[looptris[i].tri[2]];
/* If point is inside the face */
if (isect_point_tri_v2(point[sample], uv1, uv2, uv3) != 0) {
@ -2286,9 +2283,9 @@ static void dynamic_paint_create_uv_surface_direct_cb(void *__restrict userdata,
tPoint->tri_index = i;
/* save vertex indexes */
tPoint->v1 = loops[mlooptri[i].tri[0]].v;
tPoint->v2 = loops[mlooptri[i].tri[1]].v;
tPoint->v3 = loops[mlooptri[i].tri[2]].v;
tPoint->v1 = loops[looptris[i].tri[0]].v;
tPoint->v2 = loops[looptris[i].tri[1]].v;
tPoint->v3 = loops[looptris[i].tri[2]].v;
sample = 5; /* make sure we exit sample loop as well */
break;
@ -2309,7 +2306,7 @@ static void dynamic_paint_create_uv_surface_neighbor_cb(void *__restrict userdat
PaintUVPoint *tempPoints = data->tempPoints;
Vec3f *tempWeights = data->tempWeights;
const MLoopTri *mlooptri = data->mlooptri;
const blender::Span<MLoopTri> looptris = data->looptris;
const float(*mloopuv)[2] = data->mloopuv;
const blender::Span<MLoop> loops = data->loops;
@ -2351,9 +2348,9 @@ static void dynamic_paint_create_uv_surface_neighbor_cb(void *__restrict userdat
if (tempPoints[ind].neighbor_pixel == -1 && tempPoints[ind].tri_index != -1) {
float uv[2];
const int i = tempPoints[ind].tri_index;
const float *uv1 = mloopuv[mlooptri[i].tri[0]];
const float *uv2 = mloopuv[mlooptri[i].tri[1]];
const float *uv3 = mloopuv[mlooptri[i].tri[2]];
const float *uv1 = mloopuv[looptris[i].tri[0]];
const float *uv2 = mloopuv[looptris[i].tri[1]];
const float *uv3 = mloopuv[looptris[i].tri[2]];
/* tri index */
/* There is a low possibility of actually having a neighbor point which tri is
@ -2376,9 +2373,9 @@ static void dynamic_paint_create_uv_surface_neighbor_cb(void *__restrict userdat
}
/* save vertex indexes */
tPoint->v1 = loops[mlooptri[i].tri[0]].v;
tPoint->v2 = loops[mlooptri[i].tri[1]].v;
tPoint->v3 = loops[mlooptri[i].tri[2]].v;
tPoint->v1 = loops[looptris[i].tri[0]].v;
tPoint->v2 = loops[looptris[i].tri[1]].v;
tPoint->v3 = loops[looptris[i].tri[2]].v;
break;
}
@ -2396,7 +2393,7 @@ static void dynamic_paint_create_uv_surface_neighbor_cb(void *__restrict userdat
#undef JITTER_SAMPLES
static float dist_squared_to_looptri_uv_edges(const MLoopTri *mlooptri,
static float dist_squared_to_looptri_uv_edges(const blender::Span<MLoopTri> looptris,
const float (*mloopuv)[2],
int tri_index,
const float point[2])
@ -2408,8 +2405,8 @@ static float dist_squared_to_looptri_uv_edges(const MLoopTri *mlooptri,
for (int i = 0; i < 3; i++) {
const float dist_squared = dist_squared_to_line_segment_v2(
point,
mloopuv[mlooptri[tri_index].tri[(i + 0)]],
mloopuv[mlooptri[tri_index].tri[(i + 1) % 3]]);
mloopuv[looptris[tri_index].tri[(i + 0)]],
mloopuv[looptris[tri_index].tri[(i + 1) % 3]]);
if (dist_squared < min_distance) {
min_distance = dist_squared;
@ -2520,10 +2517,10 @@ static void dynamic_paint_find_island_border(const DynamicPaintCreateUVSurfaceDa
int depth)
{
const blender::Span<MLoop> loops = data->loops;
const MLoopTri *mlooptri = data->mlooptri;
const blender::Span<MLoopTri> looptris = data->looptris;
const float(*mloopuv)[2] = data->mloopuv;
const uint *loop_idx = mlooptri[tri_index].tri;
const uint *loop_idx = looptris[tri_index].tri;
/* Enumerate all edges of the triangle, rotating the vertex list accordingly. */
for (int edge_idx = 0; edge_idx < 3; edge_idx++) {
@ -2577,7 +2574,7 @@ static void dynamic_paint_find_island_border(const DynamicPaintCreateUVSurfaceDa
continue;
}
const uint *other_loop_idx = mlooptri[lt_index].tri;
const uint *other_loop_idx = looptris[lt_index].tri;
/* Check edges for match, looping in the same order as the outer loop. */
for (int j = 0; j < 3; j++) {
@ -2680,7 +2677,7 @@ static void dynamic_paint_find_island_border(const DynamicPaintCreateUVSurfaceDa
const float final_pt[2] = {((final_index % w) + 0.5f) / w, ((final_index / w) + 0.5f) / h};
const float threshold = square_f(0.7f) / (w * h);
if (dist_squared_to_looptri_uv_edges(mlooptri, mloopuv, final_tri_index, final_pt) >
if (dist_squared_to_looptri_uv_edges(looptris, mloopuv, final_tri_index, final_pt) >
threshold) {
continue;
}
@ -2818,7 +2815,6 @@ int dynamicPaint_createUVSurface(Scene *scene,
PaintUVPoint *tempPoints = nullptr;
Vec3f *tempWeights = nullptr;
const MLoopTri *mlooptri = nullptr;
const float(*mloopuv)[2] = nullptr;
Bounds2D *faceBB = nullptr;
@ -2835,8 +2831,7 @@ int dynamicPaint_createUVSurface(Scene *scene,
}
const blender::Span<MLoop> loops = mesh->loops();
mlooptri = BKE_mesh_runtime_looptri_ensure(mesh);
const int tottri = BKE_mesh_runtime_looptri_len(mesh);
const blender::Span<MLoopTri> looptris = mesh->looptris();
/* get uv map */
if (CustomData_has_layer(&mesh->ldata, CD_PROP_FLOAT2)) {
@ -2859,7 +2854,8 @@ int dynamicPaint_createUVSurface(Scene *scene,
/*
* Start generating the surface
*/
CLOG_INFO(&LOG, 1, "Preparing UV surface of %ix%i pixels and %i tris.", w, h, tottri);
CLOG_INFO(
&LOG, 1, "Preparing UV surface of %ix%i pixels and %i tris.", w, h, int(looptris.size()));
/* Init data struct */
if (surface->data) {
@ -2893,7 +2889,8 @@ int dynamicPaint_createUVSurface(Scene *scene,
* the pixel-inside-a-face search.
*/
if (!error) {
faceBB = static_cast<Bounds2D *>(MEM_mallocN(tottri * sizeof(*faceBB), "MPCanvasFaceBB"));
faceBB = static_cast<Bounds2D *>(
MEM_malloc_arrayN(looptris.size(), sizeof(*faceBB), "MPCanvasFaceBB"));
if (!faceBB) {
error = true;
}
@ -2903,12 +2900,12 @@ int dynamicPaint_createUVSurface(Scene *scene,
*do_update = true;
if (!error) {
for (int i = 0; i < tottri; i++) {
copy_v2_v2(faceBB[i].min, mloopuv[mlooptri[i].tri[0]]);
copy_v2_v2(faceBB[i].max, mloopuv[mlooptri[i].tri[0]]);
for (const int i : looptris.index_range()) {
copy_v2_v2(faceBB[i].min, mloopuv[looptris[i].tri[0]]);
copy_v2_v2(faceBB[i].max, mloopuv[looptris[i].tri[0]]);
for (int j = 1; j < 3; j++) {
minmax_v2v2_v2(faceBB[i].min, faceBB[i].max, mloopuv[mlooptri[i].tri[j]]);
minmax_v2v2_v2(faceBB[i].min, faceBB[i].max, mloopuv[looptris[i].tri[j]]);
}
}
@ -2920,16 +2917,15 @@ int dynamicPaint_createUVSurface(Scene *scene,
data.surface = surface;
data.tempPoints = tempPoints;
data.tempWeights = tempWeights;
data.mlooptri = mlooptri;
data.looptris = looptris;
data.mloopuv = mloopuv;
data.loops = loops;
data.tottri = tottri;
data.faceBB = faceBB;
{
TaskParallelSettings settings;
BLI_parallel_range_settings_defaults(&settings);
settings.use_threading = (h > 64 || tottri > 1000);
settings.use_threading = (h > 64 || looptris.size() > 1000);
BLI_task_parallel_range(0, h, &data, dynamic_paint_create_uv_surface_direct_cb, &settings);
}
@ -2979,8 +2975,8 @@ int dynamicPaint_createUVSurface(Scene *scene,
BKE_mesh_vert_looptri_map_create(&vert_to_looptri_map,
&vert_to_looptri_map_mem,
mesh->totvert,
mlooptri,
tottri,
looptris.data(),
looptris.size(),
loops.data(),
mesh->totloop);
@ -3439,15 +3435,15 @@ static void mesh_tris_spherecast_dp(void *userdata,
{
const BVHTreeFromMesh *data = (BVHTreeFromMesh *)userdata;
const float(*positions)[3] = data->vert_positions;
const MLoopTri *mlooptri = data->looptri;
const MLoopTri *looptris = data->looptri;
const MLoop *loops = data->loop;
const float *t0, *t1, *t2;
float dist;
t0 = positions[loops[mlooptri[index].tri[0]].v];
t1 = positions[loops[mlooptri[index].tri[1]].v];
t2 = positions[loops[mlooptri[index].tri[2]].v];
t0 = positions[loops[looptris[index].tri[0]].v];
t1 = positions[loops[looptris[index].tri[1]].v];
t2 = positions[loops[looptris[index].tri[2]].v];
dist = bvhtree_ray_tri_intersection(ray, hit->dist, t0, t1, t2);
@ -3471,14 +3467,14 @@ static void mesh_tris_nearest_point_dp(void *userdata,
{
const BVHTreeFromMesh *data = (BVHTreeFromMesh *)userdata;
const float(*positions)[3] = data->vert_positions;
const MLoopTri *mlooptri = data->looptri;
const MLoopTri *looptris = data->looptri;
const MLoop *loops = data->loop;
float nearest_tmp[3], dist_sq;
const float *t0, *t1, *t2;
t0 = positions[loops[mlooptri[index].tri[0]].v];
t1 = positions[loops[mlooptri[index].tri[1]].v];
t2 = positions[loops[mlooptri[index].tri[2]].v];
t0 = positions[loops[looptris[index].tri[0]].v];
t1 = positions[loops[looptris[index].tri[1]].v];
t2 = positions[loops[looptris[index].tri[2]].v];
closest_on_tri_to_point_v3(nearest_tmp, co, t0, t1, t2);
dist_sq = len_squared_v3v3(co, nearest_tmp);
@ -3912,7 +3908,7 @@ struct DynamicPaintPaintData {
Mesh *mesh;
const float (*positions)[3];
blender::Span<MLoop> loops;
const MLoopTri *mlooptri;
blender::Span<MLoopTri> looptris;
float brush_radius;
const float *avg_brushNor;
const Vec3f *brushVelocity;
@ -3946,7 +3942,7 @@ static void dynamic_paint_paint_mesh_cell_point_cb_ex(void *__restrict userdata,
const float(*positions)[3] = data->positions;
const blender::Span<MLoop> loops = data->loops;
const MLoopTri *mlooptri = data->mlooptri;
const blender::Span<MLoopTri> looptris = data->looptris;
const float brush_radius = data->brush_radius;
const float *avg_brushNor = data->avg_brushNor;
const Vec3f *brushVelocity = data->brushVelocity;
@ -4019,9 +4015,9 @@ static void dynamic_paint_paint_mesh_cell_point_cb_ex(void *__restrict userdata,
/* For optimization sake, hit point normal isn't calculated in ray cast loop */
const int vtri[3] = {
int(loops[mlooptri[hit.index].tri[0]].v),
int(loops[mlooptri[hit.index].tri[1]].v),
int(loops[mlooptri[hit.index].tri[2]].v),
int(loops[looptris[hit.index].tri[0]].v),
int(loops[looptris[hit.index].tri[1]].v),
int(loops[looptris[hit.index].tri[2]].v),
};
float dot;
@ -4169,9 +4165,9 @@ static void dynamic_paint_paint_mesh_cell_point_cb_ex(void *__restrict userdata,
float brushPointVelocity[3];
float velocity[3];
const int v1 = loops[mlooptri[hitTri].tri[0]].v;
const int v2 = loops[mlooptri[hitTri].tri[1]].v;
const int v3 = loops[mlooptri[hitTri].tri[2]].v;
const int v1 = loops[looptris[hitTri].tri[0]].v;
const int v2 = loops[looptris[hitTri].tri[1]].v;
const int v3 = loops[looptris[hitTri].tri[2]].v;
/* calculate barycentric weights for hit point */
interp_weights_tri_v3(weights, positions[v1], positions[v2], positions[v3], hitCoord);
@ -4270,7 +4266,6 @@ static bool dynamicPaint_paintMesh(Depsgraph *depsgraph,
PaintBakeData *bData = sData->bData;
Mesh *mesh = nullptr;
Vec3f *brushVelocity = nullptr;
const MLoopTri *mlooptri = nullptr;
if (brush->flags & MOD_DPAINT_USES_VELOCITY) {
dynamicPaint_brushMeshCalculateVelocity(
@ -4293,8 +4288,8 @@ static bool dynamicPaint_paintMesh(Depsgraph *depsgraph,
mesh = BKE_mesh_copy_for_eval(brush_mesh, false);
float(*positions)[3] = BKE_mesh_vert_positions_for_write(mesh);
const float(*vert_normals)[3] = BKE_mesh_vertex_normals_ensure(mesh);
mlooptri = BKE_mesh_runtime_looptri_ensure(mesh);
const float(*vert_normals)[3] = BKE_mesh_vert_normals_ensure(mesh);
const blender::Span<MLoopTri> looptris = mesh->looptris();
const blender::Span<MLoop> loops = mesh->loops();
numOfVerts = mesh->totvert;
@ -4350,7 +4345,7 @@ static bool dynamicPaint_paintMesh(Depsgraph *depsgraph,
data.mesh = mesh;
data.positions = positions;
data.loops = loops;
data.mlooptri = mlooptri;
data.looptris = looptris;
data.brush_radius = brush_radius;
data.avg_brushNor = avg_brushNor;
data.brushVelocity = brushVelocity;
@ -6154,7 +6149,7 @@ static bool dynamicPaint_generateBakeData(DynamicPaintSurface *surface,
data.surface = surface;
data.ob = ob;
data.positions = positions;
data.vert_normals = BKE_mesh_vertex_normals_ensure(mesh);
data.vert_normals = BKE_mesh_vert_normals_ensure(mesh);
data.canvas_verts = canvas_verts;
data.do_velocity_data = do_velocity_data;
data.new_bdata = new_bdata;

View File

@ -703,7 +703,7 @@ bool get_effector_data(EffectorCache *eff,
/* TODO: hair and points object support */
const Mesh *me_eval = BKE_object_get_evaluated_mesh(eff->ob);
const float(*positions)[3] = BKE_mesh_vert_positions(me_eval);
const float(*vert_normals)[3] = BKE_mesh_vertex_normals_ensure(me_eval);
const float(*vert_normals)[3] = BKE_mesh_vert_normals_ensure(me_eval);
if (me_eval != NULL) {
copy_v3_v3(efd->loc, positions[*efd->index]);
copy_v3_v3(efd->nor, vert_normals[*efd->index]);

View File

@ -939,7 +939,7 @@ struct ObstaclesFromDMData {
const float (*vert_positions)[3];
const MLoop *mloop;
const MLoopTri *mlooptri;
blender::Span<MLoopTri> looptris;
BVHTreeFromMesh *tree;
FluidObjectBB *bb;
@ -974,7 +974,7 @@ static void obstacles_from_mesh_task_cb(void *__restrict userdata,
update_velocities(data->fes,
data->vert_positions,
data->mloop,
data->mlooptri,
data->looptris.data(),
bb->velocity,
index,
data->tree,
@ -997,7 +997,6 @@ static void obstacles_from_mesh(Object *coll_ob,
float dt)
{
if (fes->mesh) {
const MLoopTri *looptri;
BVHTreeFromMesh tree_data = {nullptr};
int numverts, i;
@ -1010,7 +1009,7 @@ static void obstacles_from_mesh(Object *coll_ob,
int min[3], max[3], res[3];
const MLoop *mloop = BKE_mesh_loops(me);
looptri = BKE_mesh_runtime_looptri_ensure(me);
const blender::Span<MLoopTri> looptris = me->looptris();
numverts = me->totvert;
/* TODO(sebbas): Make initialization of vertex velocities optional? */
@ -1074,7 +1073,7 @@ static void obstacles_from_mesh(Object *coll_ob,
data.fes = fes;
data.vert_positions = positions;
data.mloop = mloop;
data.mlooptri = looptri;
data.looptris = looptris;
data.tree = &tree_data;
data.bb = bb;
data.has_velocity = has_velocity;
@ -1983,7 +1982,7 @@ struct EmitFromDMData {
const float (*vert_positions)[3];
const float (*vert_normals)[3];
const MLoop *mloop;
const MLoopTri *mlooptri;
blender::Span<MLoopTri> looptris;
const float (*mloopuv)[2];
const MDeformVert *dvert;
int defgrp_index;
@ -2017,7 +2016,7 @@ static void emit_from_mesh_task_cb(void *__restrict userdata,
data->vert_positions,
data->vert_normals,
data->mloop,
data->mlooptri,
data->looptris.data(),
data->mloopuv,
bb->influence,
bb->velocity,
@ -2067,7 +2066,7 @@ static void emit_from_mesh(
float(*positions)[3] = BKE_mesh_vert_positions_for_write(me);
const MLoop *mloop = BKE_mesh_loops(me);
const MLoopTri *mlooptri = BKE_mesh_runtime_looptri_ensure(me);
const blender::Span<MLoopTri> looptris = me->looptris();
const int numverts = me->totvert;
const MDeformVert *dvert = BKE_mesh_deform_verts(me);
const float(*mloopuv)[2] = static_cast<const float(*)[2]>(
@ -2092,8 +2091,8 @@ static void emit_from_mesh(
/* Transform mesh vertices to domain grid space for fast lookups.
* This is valid because the mesh is copied above. */
BKE_mesh_vertex_normals_ensure(me);
float(*vert_normals)[3] = BKE_mesh_vertex_normals_for_write(me);
BKE_mesh_vert_normals_ensure(me);
float(*vert_normals)[3] = BKE_mesh_vert_normals_for_write(me);
for (i = 0; i < numverts; i++) {
/* Vertex position. */
mul_m4_v3(flow_ob->object_to_world, positions[i]);
@ -2144,7 +2143,7 @@ static void emit_from_mesh(
data.vert_positions = positions;
data.vert_normals = vert_normals;
data.mloop = mloop;
data.mlooptri = mlooptri;
data.looptris = looptris;
data.mloopuv = mloopuv;
data.dvert = dvert;
data.defgrp_index = defgrp_index;

View File

@ -127,14 +127,14 @@ VArray<float3> mesh_normals_varray(const Mesh &mesh,
return VArray<float3>::ForSpan(mesh.poly_normals());
}
case ATTR_DOMAIN_POINT: {
return VArray<float3>::ForSpan(mesh.vertex_normals());
return VArray<float3>::ForSpan(mesh.vert_normals());
}
case ATTR_DOMAIN_EDGE: {
/* In this case, start with vertex normals and convert to the edge domain, since the
* conversion from edges to vertices is very simple. Use "manual" domain interpolation
* instead of the GeometryComponent API to avoid calculating unnecessary values and to
* allow normalizing the result more simply. */
Span<float3> vert_normals = mesh.vertex_normals();
Span<float3> vert_normals = mesh.vert_normals();
const Span<MEdge> edges = mesh.edges();
Array<float3> edge_normals(mask.min_array_size());
for (const int i : mask) {
@ -909,7 +909,7 @@ static void tag_component_positions_changed(void *owner)
{
Mesh *mesh = static_cast<Mesh *>(owner);
if (mesh != nullptr) {
BKE_mesh_tag_coords_changed(mesh);
BKE_mesh_tag_positions_changed(mesh);
}
}

View File

@ -2497,7 +2497,7 @@ static void gpencil_generate_edgeloops(Object *ob,
const Span<float3> vert_positions = me->vert_positions();
const Span<MEdge> edges = me->edges();
const Span<MDeformVert> dverts = me->deform_verts();
const float(*vert_normals)[3] = BKE_mesh_vertex_normals_ensure(me);
const float(*vert_normals)[3] = BKE_mesh_vert_normals_ensure(me);
/* Arrays for all edge vertices (forward and backward) that form a edge loop.
* This is reused for each edge-loop to create gpencil stroke. */

View File

@ -1496,11 +1496,10 @@ Mesh *BKE_mball_polygonize(Depsgraph *depsgraph, Scene *scene, Object *ob)
for (int i = 0; i < mesh->totvert; i++) {
normalize_v3(process.no[i]);
}
memcpy(BKE_mesh_vertex_normals_for_write(mesh),
process.no,
sizeof(float[3]) * size_t(mesh->totvert));
memcpy(
BKE_mesh_vert_normals_for_write(mesh), process.no, sizeof(float[3]) * size_t(mesh->totvert));
MEM_freeN(process.no);
BKE_mesh_vertex_normals_clear_dirty(mesh);
BKE_mesh_vert_normals_clear_dirty(mesh);
mesh->totloop = loop_offset;

View File

@ -1054,17 +1054,21 @@ void BKE_mesh_copy_parameters_for_eval(Mesh *me_dst, const Mesh *me_src)
Mesh *BKE_mesh_new_nomain_from_template_ex(const Mesh *me_src,
int verts_len,
int edges_len,
int tessface_len,
int loops_len,
int polys_len,
CustomData_MeshMasks mask)
{
/* Only do tessface if we are creating tessfaces or copying from mesh with only tessfaces. */
const bool do_tessface = (tessface_len || ((me_src->totface != 0) && (me_src->totpoly == 0)));
Mesh *me_dst = (Mesh *)BKE_id_new_nomain(ID_ME, nullptr);
me_dst->mselect = (MSelect *)MEM_dupallocN(me_src->mselect);
me_dst->totvert = verts_len;
me_dst->totedge = edges_len;
me_dst->totface = 0;
me_dst->totface = tessface_len;
me_dst->totloop = loops_len;
me_dst->totpoly = polys_len;
@ -1074,14 +1078,22 @@ Mesh *BKE_mesh_new_nomain_from_template_ex(const Mesh *me_src,
CustomData_copy(&me_src->edata, &me_dst->edata, mask.emask, CD_SET_DEFAULT, edges_len);
CustomData_copy(&me_src->ldata, &me_dst->ldata, mask.lmask, CD_SET_DEFAULT, loops_len);
CustomData_copy(&me_src->pdata, &me_dst->pdata, mask.pmask, CD_SET_DEFAULT, polys_len);
mesh_tessface_clear_intern(me_dst, false);
if (do_tessface) {
CustomData_copy(&me_src->fdata, &me_dst->fdata, mask.fmask, CD_SET_DEFAULT, tessface_len);
}
else {
mesh_tessface_clear_intern(me_dst, false);
}
/* The destination mesh should at least have valid primary CD layers,
* even in cases where the source mesh does not. */
mesh_ensure_cdlayers_primary(me_dst);
if (do_tessface && !CustomData_get_layer(&me_dst->fdata, CD_MFACE)) {
CustomData_add_layer(&me_dst->fdata, CD_MFACE, CD_SET_DEFAULT, nullptr, me_dst->totface);
}
/* Expect that normals aren't copied at all, since the destination mesh is new. */
BLI_assert(BKE_mesh_vertex_normals_are_dirty(me_dst));
BLI_assert(BKE_mesh_vert_normals_are_dirty(me_dst));
return me_dst;
}
@ -1090,7 +1102,7 @@ Mesh *BKE_mesh_new_nomain_from_template(
const Mesh *me_src, int verts_len, int edges_len, int loops_len, int polys_len)
{
return BKE_mesh_new_nomain_from_template_ex(
me_src, verts_len, edges_len, loops_len, polys_len, CD_MASK_EVERYTHING);
me_src, verts_len, edges_len, 0, loops_len, polys_len, CD_MASK_EVERYTHING);
}
void BKE_mesh_eval_delete(struct Mesh *mesh_eval)
@ -1597,7 +1609,7 @@ void BKE_mesh_transform(Mesh *me, const float mat[4][4], bool do_keys)
mul_m3_v3(m3, *lnors);
}
}
BKE_mesh_tag_coords_changed(me);
BKE_mesh_tag_positions_changed(me);
}
void BKE_mesh_translate(Mesh *me, const float offset[3], const bool do_keys)
@ -1616,7 +1628,7 @@ void BKE_mesh_translate(Mesh *me, const float offset[3], const bool do_keys)
}
}
}
BKE_mesh_tag_coords_changed_uniformly(me);
BKE_mesh_tag_positions_changed_uniformly(me);
}
void BKE_mesh_tessface_clear(Mesh *mesh)
@ -1782,7 +1794,7 @@ void BKE_mesh_vert_coords_apply(Mesh *mesh, const float (*vert_coords)[3])
for (const int i : positions.index_range()) {
copy_v3_v3(positions[i], vert_coords[i]);
}
BKE_mesh_tag_coords_changed(mesh);
BKE_mesh_tag_positions_changed(mesh);
}
void BKE_mesh_vert_coords_apply_with_mat4(Mesh *mesh,
@ -1793,7 +1805,7 @@ void BKE_mesh_vert_coords_apply_with_mat4(Mesh *mesh,
for (const int i : positions.index_range()) {
mul_v3_m4v3(positions[i], mat, vert_coords[i]);
}
BKE_mesh_tag_coords_changed(mesh);
BKE_mesh_tag_positions_changed(mesh);
}
static float (*ensure_corner_normal_layer(Mesh &mesh))[3]
@ -1835,7 +1847,7 @@ void BKE_mesh_calc_normals_split_ex(Mesh *mesh,
const Span<MLoop> loops = mesh->loops();
BKE_mesh_normals_loop_split(reinterpret_cast<const float(*)[3]>(positions.data()),
BKE_mesh_vertex_normals_ensure(mesh),
BKE_mesh_vert_normals_ensure(mesh),
positions.size(),
edges.data(),
edges.size(),

View File

@ -68,7 +68,7 @@ void BKE_mesh_foreach_mapped_vert(
const float(*positions)[3] = BKE_mesh_vert_positions(mesh);
const int *index = static_cast<const int *>(CustomData_get_layer(&mesh->vdata, CD_ORIGINDEX));
const float(*vert_normals)[3] = (flag & MESH_FOREACH_USE_NORMAL) ?
BKE_mesh_vertex_normals_ensure(mesh) :
BKE_mesh_vert_normals_ensure(mesh) :
nullptr;
if (index) {
@ -311,7 +311,7 @@ void BKE_mesh_foreach_mapped_subdiv_face_center(
const blender::Span<MPoly> polys = mesh->polys();
const blender::Span<MLoop> loops = mesh->loops();
const float(*vert_normals)[3] = (flag & MESH_FOREACH_USE_NORMAL) ?
BKE_mesh_vertex_normals_ensure(mesh) :
BKE_mesh_vert_normals_ensure(mesh) :
nullptr;
const int *index = static_cast<const int *>(CustomData_get_layer(&mesh->pdata, CD_ORIGINDEX));
const blender::BitSpan facedot_tags = mesh->runtime->subsurf_face_dot_tags;

View File

@ -400,7 +400,7 @@ Mesh *BKE_mesh_mirror_apply_mirror_on_axis_for_modifier(MirrorModifierData *mmd,
const bool *sharp_edges = static_cast<const bool *>(
CustomData_get_layer_named(&mesh->edata, CD_PROP_BOOL, "sharp_edge"));
BKE_mesh_normals_loop_split(BKE_mesh_vert_positions(result),
BKE_mesh_vertex_normals_ensure(result),
BKE_mesh_vert_normals_ensure(result),
result->totvert,
result->edges().data(),
result->totedge,

View File

@ -106,7 +106,7 @@ void BKE_mesh_normals_tag_dirty(Mesh *mesh)
mesh->runtime->poly_normals_dirty = true;
}
float (*BKE_mesh_vertex_normals_for_write(Mesh *mesh))[3]
float (*BKE_mesh_vert_normals_for_write(Mesh *mesh))[3]
{
if (mesh->runtime->vert_normals == nullptr) {
mesh->runtime->vert_normals = (float(*)[3])MEM_malloc_arrayN(
@ -130,7 +130,7 @@ float (*BKE_mesh_poly_normals_for_write(Mesh *mesh))[3]
return mesh->runtime->poly_normals;
}
void BKE_mesh_vertex_normals_clear_dirty(Mesh *mesh)
void BKE_mesh_vert_normals_clear_dirty(Mesh *mesh)
{
mesh->runtime->vert_normals_dirty = false;
BLI_assert(mesh->runtime->vert_normals || mesh->totvert == 0);
@ -142,7 +142,7 @@ void BKE_mesh_poly_normals_clear_dirty(Mesh *mesh)
BLI_assert(mesh->runtime->poly_normals || mesh->totpoly == 0);
}
bool BKE_mesh_vertex_normals_are_dirty(const Mesh *mesh)
bool BKE_mesh_vert_normals_are_dirty(const Mesh *mesh)
{
return mesh->runtime->vert_normals_dirty;
}
@ -368,9 +368,9 @@ void BKE_mesh_calc_normals_poly_and_vertex(const float (*vert_positions)[3],
/** \name Mesh Normal Calculation
* \{ */
const float (*BKE_mesh_vertex_normals_ensure(const Mesh *mesh))[3]
const float (*BKE_mesh_vert_normals_ensure(const Mesh *mesh))[3]
{
if (!BKE_mesh_vertex_normals_are_dirty(mesh)) {
if (!BKE_mesh_vert_normals_are_dirty(mesh)) {
BLI_assert(mesh->runtime->vert_normals != nullptr || mesh->totvert == 0);
return mesh->runtime->vert_normals;
}
@ -380,7 +380,7 @@ const float (*BKE_mesh_vertex_normals_ensure(const Mesh *mesh))[3]
}
std::lock_guard lock{mesh->runtime->normals_mutex};
if (!BKE_mesh_vertex_normals_are_dirty(mesh)) {
if (!BKE_mesh_vert_normals_are_dirty(mesh)) {
BLI_assert(mesh->runtime->vert_normals != nullptr);
return mesh->runtime->vert_normals;
}
@ -395,7 +395,7 @@ const float (*BKE_mesh_vertex_normals_ensure(const Mesh *mesh))[3]
const Span<MPoly> polys = mesh_mutable.polys();
const Span<MLoop> loops = mesh_mutable.loops();
vert_normals = BKE_mesh_vertex_normals_for_write(&mesh_mutable);
vert_normals = BKE_mesh_vert_normals_for_write(&mesh_mutable);
poly_normals = BKE_mesh_poly_normals_for_write(&mesh_mutable);
BKE_mesh_calc_normals_poly_and_vertex(reinterpret_cast<const float(*)[3]>(positions.data()),
@ -407,7 +407,7 @@ const float (*BKE_mesh_vertex_normals_ensure(const Mesh *mesh))[3]
poly_normals,
vert_normals);
BKE_mesh_vertex_normals_clear_dirty(&mesh_mutable);
BKE_mesh_vert_normals_clear_dirty(&mesh_mutable);
BKE_mesh_poly_normals_clear_dirty(&mesh_mutable);
});
@ -461,7 +461,7 @@ void BKE_mesh_ensure_normals_for_display(Mesh *mesh)
switch (mesh->runtime->wrapper_type) {
case ME_WRAPPER_TYPE_SUBD:
case ME_WRAPPER_TYPE_MDATA:
BKE_mesh_vertex_normals_ensure(mesh);
BKE_mesh_vert_normals_ensure(mesh);
BKE_mesh_poly_normals_ensure(mesh);
break;
case ME_WRAPPER_TYPE_BMESH: {
@ -481,7 +481,7 @@ void BKE_mesh_calc_normals(Mesh *mesh)
#ifdef DEBUG_TIME
SCOPED_TIMER_AVERAGED(__func__);
#endif
BKE_mesh_vertex_normals_ensure(mesh);
BKE_mesh_vert_normals_ensure(mesh);
}
void BKE_lnor_spacearr_init(MLoopNorSpaceArray *lnors_spacearr,
@ -1932,7 +1932,7 @@ static void mesh_set_custom_normals(Mesh *mesh, float (*r_custom_nors)[3], const
"sharp_edge", ATTR_DOMAIN_EDGE);
mesh_normals_loop_custom_set(reinterpret_cast<const float(*)[3]>(positions.data()),
BKE_mesh_vertex_normals_ensure(mesh),
BKE_mesh_vert_normals_ensure(mesh),
positions.size(),
edges.data(),
edges.size(),

View File

@ -571,7 +571,7 @@ void BKE_mesh_remap_calc_verts_from_mesh(const int mode,
const blender::Span<MPoly> polys_src = me_src->polys();
const blender::Span<MLoop> loops_src = me_src->loops();
float(*vcos_src)[3] = BKE_mesh_vert_coords_alloc(me_src, nullptr);
const float(*vert_normals_dst)[3] = BKE_mesh_vertex_normals_ensure(me_dst);
const float(*vert_normals_dst)[3] = BKE_mesh_vert_normals_ensure(me_dst);
size_t tmp_buff_size = MREMAP_DEFAULT_BUFSIZE;
float(*vcos)[3] = static_cast<float(*)[3]>(
@ -937,7 +937,7 @@ void BKE_mesh_remap_calc_edges_from_mesh(const int mode,
BKE_bvhtree_from_mesh_get(&treedata, me_src, BVHTREE_FROM_EDGES, 2);
const float(*vert_normals_dst)[3] = BKE_mesh_vertex_normals_ensure(me_dst);
const float(*vert_normals_dst)[3] = BKE_mesh_vert_normals_ensure(me_dst);
for (i = 0; i < numedges_dst; i++) {
/* For each dst edge, we sample some rays from it (interpolated from its vertices)
@ -1252,8 +1252,6 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode,
const float full_weight = 1.0f;
const float max_dist_sq = max_dist * max_dist;
int i;
BLI_assert(mode & MREMAP_MODE_LOOP);
BLI_assert((islands_precision_src >= 0.0f) && (islands_precision_src <= 1.0f));
@ -1262,7 +1260,7 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode,
if (mode == MREMAP_MODE_TOPOLOGY) {
/* In topology mapping, we assume meshes are identical, islands included! */
BLI_assert(numloops_dst == me_src->totloop);
for (i = 0; i < numloops_dst; i++) {
for (int i = 0; i < numloops_dst; i++) {
mesh_remap_item_define(r_map, i, FLT_MAX, 0, 1, &i, &full_weight);
}
}
@ -1311,8 +1309,7 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode,
const blender::Span<MEdge> edges_src = me_src->edges();
const blender::Span<MPoly> polys_src = me_src->polys();
const blender::Span<MLoop> loops_src = me_src->loops();
const MLoopTri *looptri_src = nullptr;
int num_looptri_src = 0;
blender::Span<MLoopTri> looptris_src;
size_t buff_size_interp = MREMAP_DEFAULT_BUFSIZE;
float(*vcos_interp)[3] = nullptr;
@ -1365,7 +1362,7 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode,
const bool *sharp_edges = static_cast<const bool *>(
CustomData_get_layer_named(&mesh_dst->edata, CD_PROP_BOOL, "sharp_edge"));
BKE_mesh_normals_loop_split(vert_positions_dst,
BKE_mesh_vertex_normals_ensure(mesh_dst),
BKE_mesh_vert_normals_ensure(mesh_dst),
numverts_dst,
edges_dst,
numedges_dst,
@ -1506,7 +1503,7 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode,
MeshElemMap *isld = island_store.islands[tindex];
int num_verts_active = 0;
verts_active.fill(false);
for (i = 0; i < isld->count; i++) {
for (int i = 0; i < isld->count; i++) {
const MPoly &poly = polys_src[isld->indices[i]];
for (lidx_src = poly.loopstart; lidx_src < poly.loopstart + poly.totloop; lidx_src++) {
const uint vidx_src = loops_src[lidx_src].v;
@ -1533,16 +1530,14 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode,
}
else { /* We use polygons. */
if (use_islands) {
/* bvhtree here uses looptri faces... */
looptri_src = BKE_mesh_runtime_looptri_ensure(me_src);
num_looptri_src = BKE_mesh_runtime_looptri_len(me_src);
blender::BitVector<> looptri_active(num_looptri_src);
looptris_src = me_src->looptris();
blender::BitVector<> looptri_active(looptris_src.size());
for (tindex = 0; tindex < num_trees; tindex++) {
int num_looptri_active = 0;
looptri_active.fill(false);
for (i = 0; i < num_looptri_src; i++) {
const MPoly &poly = polys_src[looptri_src[i].poly];
for (const int64_t i : looptris_src.index_range()) {
const MPoly &poly = polys_src[looptris_src[i].poly];
if (island_store.items_to_islands[poly.loopstart] == tindex) {
looptri_active[i].set();
num_looptri_active++;
@ -1551,8 +1546,8 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode,
bvhtree_from_mesh_looptri_ex(&treedata[tindex],
positions_src,
loops_src.data(),
looptri_src,
num_looptri_src,
looptris_src.data(),
int(looptris_src.size()),
looptri_active,
num_looptri_active,
0.0,
@ -1636,7 +1631,7 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode,
vert_to_refelem_map_src = vert_to_poly_map_src;
}
for (i = vert_to_refelem_map_src[nearest.index].count; i--;) {
for (int i = vert_to_refelem_map_src[nearest.index].count; i--;) {
const int index_src = vert_to_refelem_map_src[nearest.index].indices[i];
BLI_assert(index_src != -1);
const float dot = dot_v3v3(nors_src[index_src], *nor_dst);
@ -1881,7 +1876,7 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode,
*/
int last_valid_pidx_isld_src = -1;
/* Note we go backward here, from dest to src poly. */
for (i = as_solution.steps - 1; i--;) {
for (int i = as_solution.steps - 1; i--;) {
BLI_AStarGNLink *as_link = as_solution.prev_links[pidx_isld_src];
const int eidx = POINTER_AS_INT(as_link->custom_data);
pidx_isld_src = as_solution.prev_nodes[pidx_isld_src];
@ -1973,7 +1968,7 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode,
*/
int last_valid_pidx_isld_src = -1;
/* Note we go backward here, from dest to src poly. */
for (i = as_solution.steps - 1; i--;) {
for (int i = as_solution.steps - 1; i--;) {
BLI_AStarGNLink *as_link = as_solution.prev_links[pidx_isld_src];
int eidx = POINTER_AS_INT(as_link->custom_data);
@ -2008,14 +2003,14 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode,
&poly_to_looptri_map_src_buff,
polys_src.data(),
int(polys_src.size()),
looptri_src,
num_looptri_src);
looptris_src.data(),
int(looptris_src.size()));
}
for (j = poly_to_looptri_map_src[pidx_src].count; j--;) {
float h[3];
const MLoopTri *lt =
&looptri_src[poly_to_looptri_map_src[pidx_src].indices[j]];
&looptris_src[poly_to_looptri_map_src[pidx_src].indices[j]];
float dist_sq;
closest_on_tri_to_point_v3(h,

View File

@ -65,15 +65,14 @@ static Mesh *remesh_quadriflow(const Mesh *input_mesh,
{
const Span<float3> input_positions = input_mesh->vert_positions();
const Span<MLoop> input_loops = input_mesh->loops();
const MLoopTri *looptri = BKE_mesh_runtime_looptri_ensure(input_mesh);
const Span<MLoopTri> looptris = input_mesh->looptris();
/* Gather the required data for export to the internal quadriflow mesh format. */
MVertTri *verttri = (MVertTri *)MEM_callocN(
sizeof(*verttri) * BKE_mesh_runtime_looptri_len(input_mesh), "remesh_looptri");
Array<MVertTri> verttri(looptris.size());
BKE_mesh_runtime_verttri_from_looptri(
verttri, input_loops.data(), looptri, BKE_mesh_runtime_looptri_len(input_mesh));
verttri.data(), input_loops.data(), looptris.data(), looptris.size());
const int totfaces = BKE_mesh_runtime_looptri_len(input_mesh);
const int totfaces = looptris.size();
const int totverts = input_mesh->totvert;
Array<int> faces(totfaces * 3);
@ -105,8 +104,6 @@ static Mesh *remesh_quadriflow(const Mesh *input_mesh,
/* Run the remesher */
QFLOW_quadriflow_remesh(&qrd, update_cb, update_cb_data);
MEM_freeN(verttri);
if (qrd.out_faces == nullptr) {
/* The remeshing was canceled */
return nullptr;
@ -335,7 +332,7 @@ void BKE_remesh_reproject_sculpt_face_sets(Mesh *target, const Mesh *source)
const VArraySpan<int> src(src_face_sets);
MutableSpan<int> dst = dst_face_sets.span;
const MLoopTri *looptri = BKE_mesh_runtime_looptri_ensure(source);
const blender::Span<MLoopTri> looptris = source->looptris();
BVHTreeFromMesh bvhtree = {nullptr};
BKE_bvhtree_from_mesh_get(&bvhtree, source, BVHTREE_FROM_LOOPTRI, 2);
@ -353,7 +350,7 @@ void BKE_remesh_reproject_sculpt_face_sets(Mesh *target, const Mesh *source)
BLI_bvhtree_find_nearest(
bvhtree.tree, from_co, &nearest, bvhtree.nearest_callback, &bvhtree);
if (nearest.index != -1) {
dst[i] = src[looptri[nearest.index].poly];
dst[i] = src[looptris[nearest.index].poly];
}
else {
dst[i] = 1;

View File

@ -254,7 +254,7 @@ void BKE_mesh_tag_edges_split(struct Mesh *mesh)
}
}
void BKE_mesh_tag_coords_changed(Mesh *mesh)
void BKE_mesh_tag_positions_changed(Mesh *mesh)
{
BKE_mesh_normals_tag_dirty(mesh);
free_bvh_cache(*mesh->runtime);
@ -262,7 +262,7 @@ void BKE_mesh_tag_coords_changed(Mesh *mesh)
mesh->runtime->bounds_cache.tag_dirty();
}
void BKE_mesh_tag_coords_changed_uniformly(Mesh *mesh)
void BKE_mesh_tag_positions_changed_uniformly(Mesh *mesh)
{
/* The normals and triangulation didn't change, since all verts moved by the same amount. */
free_bvh_cache(*mesh->runtime);

View File

@ -574,19 +574,20 @@ void BKE_mesh_calc_loop_tangents(Mesh *me_eval,
int tangent_names_len)
{
/* TODO(@ideasman42): store in Mesh.runtime to avoid recalculation. */
const blender::Span<MLoopTri> looptris = me_eval->looptris();
short tangent_mask = 0;
BKE_mesh_calc_loop_tangent_ex(
BKE_mesh_vert_positions(me_eval),
me_eval->polys().data(),
uint(me_eval->totpoly),
me_eval->loops().data(),
BKE_mesh_runtime_looptri_ensure(me_eval),
uint(BKE_mesh_runtime_looptri_len(me_eval)),
looptris.data(),
uint(looptris.size()),
&me_eval->ldata,
calc_active_tangent,
tangent_names,
tangent_names_len,
BKE_mesh_vertex_normals_ensure(me_eval),
BKE_mesh_vert_normals_ensure(me_eval),
BKE_mesh_poly_normals_ensure(me_eval),
static_cast<const float(*)[3]>(CustomData_get_layer(&me_eval->ldata, CD_NORMAL)),
/* may be nullptr */

View File

@ -298,8 +298,8 @@ bool BKE_mesh_validate_arrays(Mesh *mesh,
}
const float(*vert_normals)[3] = nullptr;
if (!BKE_mesh_vertex_normals_are_dirty(mesh)) {
vert_normals = BKE_mesh_vertex_normals_ensure(mesh);
if (!BKE_mesh_vert_normals_are_dirty(mesh)) {
vert_normals = BKE_mesh_vert_normals_ensure(mesh);
}
for (i = 0; i < totvert; i++) {

View File

@ -1018,7 +1018,7 @@ void BKE_modifier_deform_verts(ModifierData *md,
}
mti->deformVerts(md, ctx, me, vertexCos, numVerts);
if (me) {
BKE_mesh_tag_coords_changed(me);
BKE_mesh_tag_positions_changed(me);
}
}

View File

@ -474,14 +474,14 @@ static int get_timecode(MovieClip *clip, int flag)
return clip->proxy.tc;
}
static void get_sequence_fname(const MovieClip *clip, const int framenr, char *name)
static void get_sequence_filepath(const MovieClip *clip, const int framenr, char *filepath)
{
ushort numlen;
char head[FILE_MAX], tail[FILE_MAX];
int offset;
BLI_strncpy(name, clip->filepath, sizeof(clip->filepath));
BLI_path_sequence_decode(name, head, tail, &numlen);
BLI_strncpy(filepath, clip->filepath, sizeof(clip->filepath));
BLI_path_sequence_decode(filepath, head, tail, &numlen);
/* Movie-clips always points to first image from sequence, auto-guess offset for now.
* Could be something smarter in the future. */
@ -489,18 +489,18 @@ static void get_sequence_fname(const MovieClip *clip, const int framenr, char *n
if (numlen) {
BLI_path_sequence_encode(
name, head, tail, numlen, offset + framenr - clip->start_frame + clip->frame_offset);
filepath, head, tail, numlen, offset + framenr - clip->start_frame + clip->frame_offset);
}
else {
BLI_strncpy(name, clip->filepath, sizeof(clip->filepath));
BLI_strncpy(filepath, clip->filepath, sizeof(clip->filepath));
}
BLI_path_abs(name, ID_BLEND_PATH_FROM_GLOBAL(&clip->id));
BLI_path_abs(filepath, ID_BLEND_PATH_FROM_GLOBAL(&clip->id));
}
/* supposed to work with sequences only */
static void get_proxy_fname(
const MovieClip *clip, int proxy_render_size, bool undistorted, int framenr, char *name)
static void get_proxy_filepath(
const MovieClip *clip, int proxy_render_size, bool undistorted, int framenr, char *filepath)
{
int size = rendersize_to_number(proxy_render_size);
char dir[FILE_MAX], clipdir[FILE_MAX], clipfile[FILE_MAX];
@ -516,16 +516,17 @@ static void get_proxy_fname(
}
if (undistorted) {
BLI_snprintf(name, FILE_MAX, "%s/%s/proxy_%d_undistorted/%08d", dir, clipfile, size, proxynr);
BLI_snprintf(
filepath, FILE_MAX, "%s/%s/proxy_%d_undistorted/%08d", dir, clipfile, size, proxynr);
}
else {
BLI_snprintf(name, FILE_MAX, "%s/%s/proxy_%d/%08d", dir, clipfile, size, proxynr);
BLI_snprintf(filepath, FILE_MAX, "%s/%s/proxy_%d/%08d", dir, clipfile, size, proxynr);
}
BLI_path_abs(name, BKE_main_blendfile_path_from_global());
BLI_path_frame(name, 1, 0);
BLI_path_abs(filepath, BKE_main_blendfile_path_from_global());
BLI_path_frame(filepath, 1, 0);
strcat(name, ".jpg");
strcat(filepath, ".jpg");
}
#ifdef WITH_OPENEXR
@ -610,7 +611,7 @@ static ImBuf *movieclip_load_sequence_file(MovieClip *clip,
int flag)
{
struct ImBuf *ibuf;
char name[FILE_MAX];
char filepath[FILE_MAX];
int loadflag;
bool use_proxy = false;
char *colorspace;
@ -618,7 +619,7 @@ static ImBuf *movieclip_load_sequence_file(MovieClip *clip,
use_proxy = (flag & MCLIP_USE_PROXY) && user->render_size != MCLIP_PROXY_RENDER_SIZE_FULL;
if (use_proxy) {
int undistort = user->render_flag & MCLIP_PROXY_RENDER_UNDISTORT;
get_proxy_fname(clip, user->render_size, undistort, framenr, name);
get_proxy_filepath(clip, user->render_size, undistort, framenr, filepath);
/* Well, this is a bit weird, but proxies for movie sources
* are built in the same exact color space as the input,
@ -633,14 +634,14 @@ static ImBuf *movieclip_load_sequence_file(MovieClip *clip,
}
}
else {
get_sequence_fname(clip, framenr, name);
get_sequence_filepath(clip, framenr, filepath);
colorspace = clip->colorspace_settings.name;
}
loadflag = IB_rect | IB_multilayer | IB_alphamode_detect | IB_metadata;
/* read ibuf */
ibuf = IMB_loadiffname(name, loadflag, colorspace);
ibuf = IMB_loadiffname(filepath, loadflag, colorspace);
BKE_movieclip_convert_multilayer_ibuf(ibuf);
return ibuf;
@ -699,7 +700,7 @@ static void movieclip_calc_length(MovieClip *clip)
}
else if (clip->source == MCLIP_SRC_SEQUENCE) {
ushort numlen;
char name[FILE_MAX], head[FILE_MAX], tail[FILE_MAX];
char filepath[FILE_MAX], head[FILE_MAX], tail[FILE_MAX];
BLI_path_sequence_decode(clip->filepath, head, tail, &numlen);
@ -710,9 +711,9 @@ static void movieclip_calc_length(MovieClip *clip)
else {
clip->len = 0;
for (;;) {
get_sequence_fname(clip, clip->len + clip->start_frame, name);
get_sequence_filepath(clip, clip->len + clip->start_frame, filepath);
if (BLI_exists(name)) {
if (BLI_exists(filepath)) {
clip->len++;
}
else {
@ -791,7 +792,7 @@ static int user_frame_to_cache_frame(MovieClip *clip, int framenr)
BLI_path_sequence_decode(clip->filepath, head, tail, &numlen);
/* see comment in get_sequence_fname */
/* see comment in get_sequence_filepath */
clip->cache->sequence_offset = sequence_guess_offset(clip->filepath, strlen(head), numlen);
}
@ -996,12 +997,12 @@ static void movieclip_load_get_size(MovieClip *clip)
static void detect_clip_source(Main *bmain, MovieClip *clip)
{
ImBuf *ibuf;
char name[FILE_MAX];
char filepath[FILE_MAX];
BLI_strncpy(name, clip->filepath, sizeof(name));
BLI_path_abs(name, BKE_main_blendfile_path(bmain));
BLI_strncpy(filepath, clip->filepath, sizeof(filepath));
BLI_path_abs(filepath, BKE_main_blendfile_path(bmain));
ibuf = IMB_testiffname(name, IB_rect | IB_multilayer);
ibuf = IMB_testiffname(filepath, IB_rect | IB_multilayer);
if (ibuf) {
clip->source = MCLIP_SRC_SEQUENCE;
IMB_freeImBuf(ibuf);
@ -1011,13 +1012,13 @@ static void detect_clip_source(Main *bmain, MovieClip *clip)
}
}
MovieClip *BKE_movieclip_file_add(Main *bmain, const char *name)
MovieClip *BKE_movieclip_file_add(Main *bmain, const char *filepath)
{
MovieClip *clip;
int file;
char str[FILE_MAX];
BLI_strncpy(str, name, sizeof(str));
BLI_strncpy(str, filepath, sizeof(str));
BLI_path_abs(str, BKE_main_blendfile_path(bmain));
/* exists? */
@ -1030,8 +1031,8 @@ MovieClip *BKE_movieclip_file_add(Main *bmain, const char *name)
/* ** add new movieclip ** */
/* create a short library name */
clip = movieclip_alloc(bmain, BLI_path_basename(name));
BLI_strncpy(clip->filepath, name, sizeof(clip->filepath));
clip = movieclip_alloc(bmain, BLI_path_basename(filepath));
BLI_strncpy(clip->filepath, filepath, sizeof(clip->filepath));
detect_clip_source(bmain, clip);
@ -1826,12 +1827,12 @@ void BKE_movieclip_update_scopes(MovieClip *clip,
static void movieclip_build_proxy_ibuf(
MovieClip *clip, ImBuf *ibuf, int cfra, int proxy_render_size, bool undistorted, bool threaded)
{
char name[FILE_MAX];
char filepath[FILE_MAX];
int quality, rectx, recty;
int size = rendersize_to_number(proxy_render_size);
ImBuf *scaleibuf;
get_proxy_fname(clip, proxy_render_size, undistorted, cfra, name);
get_proxy_filepath(clip, proxy_render_size, undistorted, cfra, filepath);
rectx = ibuf->x * size / 100.0f;
recty = ibuf->y * size / 100.0f;
@ -1859,9 +1860,9 @@ static void movieclip_build_proxy_ibuf(
*/
BLI_thread_lock(LOCK_MOVIECLIP);
BLI_make_existing_file(name);
if (IMB_saveiff(scaleibuf, name, IB_rect) == 0) {
perror(name);
BLI_make_existing_file(filepath);
if (IMB_saveiff(scaleibuf, filepath, IB_rect) == 0) {
perror(filepath);
}
BLI_thread_unlock(LOCK_MOVIECLIP);
@ -1955,7 +1956,7 @@ float BKE_movieclip_remap_clip_to_scene_frame(const MovieClip *clip, const float
return framenr + (float)clip->start_frame - 1.0f;
}
void BKE_movieclip_filename_for_frame(MovieClip *clip, const MovieClipUser *user, char *name)
void BKE_movieclip_filepath_for_frame(MovieClip *clip, const MovieClipUser *user, char *filepath)
{
if (clip->source == MCLIP_SRC_SEQUENCE) {
int use_proxy;
@ -1965,15 +1966,15 @@ void BKE_movieclip_filename_for_frame(MovieClip *clip, const MovieClipUser *user
if (use_proxy) {
int undistort = user->render_flag & MCLIP_PROXY_RENDER_UNDISTORT;
get_proxy_fname(clip, user->render_size, undistort, user->framenr, name);
get_proxy_filepath(clip, user->render_size, undistort, user->framenr, filepath);
}
else {
get_sequence_fname(clip, user->framenr, name);
get_sequence_filepath(clip, user->framenr, filepath);
}
}
else {
BLI_strncpy(name, clip->filepath, FILE_MAX);
BLI_path_abs(name, ID_BLEND_PATH_FROM_GLOBAL(&clip->id));
BLI_strncpy(filepath, clip->filepath, FILE_MAX);
BLI_path_abs(filepath, ID_BLEND_PATH_FROM_GLOBAL(&clip->id));
}
}

View File

@ -160,7 +160,7 @@ void multires_reshape_apply_base_refit_base_mesh(MultiresReshapeContext *reshape
/* Vertices were moved around, need to update normals after all the vertices are updated
* Probably this is possible to do in the loop above, but this is rather tricky because
* we don't know all needed vertices' coordinates there yet. */
BKE_mesh_tag_coords_changed(base_mesh);
BKE_mesh_tag_positions_changed(base_mesh);
}
void multires_reshape_apply_base_refine_from_base(MultiresReshapeContext *reshape_context)

View File

@ -735,7 +735,7 @@ static void make_duplis_verts(const DupliContext *ctx)
vdd.params = vdd_params;
vdd.totvert = me_eval->totvert;
vdd.vert_positions = me_eval->vert_positions();
vdd.vert_normals = BKE_mesh_vertex_normals_ensure(me_eval);
vdd.vert_normals = BKE_mesh_vert_normals_ensure(me_eval);
vdd.orco = (const float(*)[3])CustomData_get_layer(&me_eval->vdata, CD_ORCO);
make_child_duplis(ctx, &vdd, make_child_duplis_verts_from_mesh);

View File

@ -2160,7 +2160,7 @@ void psys_particle_on_dm(Mesh *mesh_final,
}
orcodata = static_cast<const float(*)[3]>(CustomData_get_layer(&mesh_final->vdata, CD_ORCO));
const float(*vert_normals)[3] = BKE_mesh_vertex_normals_ensure(mesh_final);
const float(*vert_normals)[3] = BKE_mesh_vert_normals_ensure(mesh_final);
if (from == PART_FROM_VERT) {
const float(*vert_positions)[3] = BKE_mesh_vert_positions(mesh_final);

View File

@ -613,18 +613,8 @@ static void distribute_from_volume_exec(ParticleTask *thread, ParticleData *pa,
/* experimental */
tot = mesh->totface;
psys_interpolate_face(mesh,
positions,
BKE_mesh_vertex_normals_ensure(mesh),
mface,
0,
0,
pa->fuv,
co,
nor,
0,
0,
0);
psys_interpolate_face(
mesh, positions, BKE_mesh_vert_normals_ensure(mesh), mface, 0, 0, pa->fuv, co, nor, 0, 0, 0);
normalize_v3(nor);
negate_v3(nor);

View File

@ -834,8 +834,8 @@ void BKE_pbvh_build_mesh(PBVH *pbvh,
pbvh->mloop = mloop;
pbvh->looptri = looptri;
pbvh->vert_positions = vert_positions;
BKE_mesh_vertex_normals_ensure(mesh);
pbvh->vert_normals = BKE_mesh_vertex_normals_for_write(mesh);
BKE_mesh_vert_normals_ensure(mesh);
pbvh->vert_normals = BKE_mesh_vert_normals_for_write(mesh);
pbvh->hide_vert = static_cast<bool *>(CustomData_get_layer_named_for_write(
&mesh->vdata, CD_PROP_BOOL, ".hide_vert", mesh->totvert));
pbvh->vert_bitmap = static_cast<bool *>(

View File

@ -672,7 +672,6 @@ static bool update_pixels(PBVH *pbvh, Mesh *mesh, Image *image, ImageUser *image
uv_islands::MeshData mesh_data(
{pbvh->looptri, pbvh->totprim},
{pbvh->mloop, mesh->totloop},
pbvh->totvert,
uv_map,
{static_cast<blender::float3 *>(static_cast<void *>(pbvh->vert_positions)), pbvh->totvert});
uv_islands::UVIslands islands(mesh_data);

View File

@ -200,15 +200,13 @@ static void mesh_data_init(MeshData &mesh_data)
MeshData::MeshData(const Span<MLoopTri> looptris,
const Span<MLoop> loops,
const int verts_num,
const Span<float2> uv_map,
const Span<float3> vertex_positions)
const Span<float3> vert_positions)
: looptris(looptris),
verts_num(verts_num),
loops(loops),
uv_map(uv_map),
vertex_positions(vertex_positions),
vert_to_edge_map(verts_num),
vert_positions(vert_positions),
vert_to_edge_map(vert_positions.size()),
edge_to_primitive_map(0),
primitive_to_edge_map(looptris.size())
{
@ -1085,7 +1083,7 @@ void UVIsland::print_debug(const MeshData &mesh_data) const
ss << "import mathutils\n";
ss << "uvisland_vertices = [\n";
for (const float3 &vertex_position : mesh_data.vertex_positions) {
for (const float3 &vertex_position : mesh_data.vert_positions) {
ss << " mathutils.Vector((" << vertex_position.x << ", " << vertex_position.y << ", "
<< vertex_position.z << ")),\n";
}

View File

@ -119,10 +119,9 @@ class TriangleToEdgeMap {
struct MeshData {
public:
const Span<MLoopTri> looptris;
const int64_t verts_num;
const Span<MLoop> loops;
const Span<float2> uv_map;
const Span<float3> vertex_positions;
const Span<float3> vert_positions;
VertToEdgeMap vert_to_edge_map;
@ -142,9 +141,8 @@ struct MeshData {
public:
explicit MeshData(Span<MLoopTri> looptris,
Span<MLoop> loops,
const int verts_num,
const Span<float2> uv_map,
const Span<float3> vertex_positions);
const Span<float3> vert_positions);
};
struct UVVertex {

View File

@ -115,7 +115,7 @@ bool BKE_shrinkwrap_init_tree(
data->mesh = mesh;
data->polys = mesh->polys().data();
data->vert_normals = BKE_mesh_vertex_normals_ensure(mesh);
data->vert_normals = BKE_mesh_vert_normals_ensure(mesh);
if (shrinkType == MOD_SHRINKWRAP_NEAREST_VERTEX) {
data->bvh = BKE_bvhtree_from_mesh_get(&data->treeData, mesh, BVHTREE_FROM_VERTS, 2);
@ -231,15 +231,14 @@ static ShrinkwrapBoundaryData *shrinkwrap_build_boundary_data(Mesh *mesh)
data->edge_is_boundary = edge_is_boundary;
/* Build the boundary looptri bitmask. */
const MLoopTri *mlooptri = BKE_mesh_runtime_looptri_ensure(mesh);
int totlooptri = BKE_mesh_runtime_looptri_len(mesh);
const blender::Span<MLoopTri> looptris = mesh->looptris();
BLI_bitmap *looptri_has_boundary = BLI_BITMAP_NEW(totlooptri,
BLI_bitmap *looptri_has_boundary = BLI_BITMAP_NEW(looptris.size(),
"ShrinkwrapBoundaryData::looptri_is_boundary");
for (int i = 0; i < totlooptri; i++) {
for (const int64_t i : looptris.index_range()) {
int real_edges[3];
BKE_mesh_looptri_get_real_edges(edges.data(), loops.data(), &mlooptri[i], real_edges);
BKE_mesh_looptri_get_real_edges(edges.data(), loops.data(), &looptris[i], real_edges);
for (int j = 0; j < 3; j++) {
if (real_edges[j] >= 0 && edge_mode[real_edges[j]]) {
@ -296,7 +295,7 @@ static ShrinkwrapBoundaryData *shrinkwrap_build_boundary_data(Mesh *mesh)
MEM_freeN(vert_status);
/* Finalize average direction and compute normal. */
const float(*vert_normals)[3] = BKE_mesh_vertex_normals_ensure(mesh);
const float(*vert_normals)[3] = BKE_mesh_vert_normals_ensure(mesh);
for (int i = 0; i < mesh->totvert; i++) {
int bidx = vert_boundary_id[i];
@ -1408,7 +1407,7 @@ void shrinkwrapModifier_deform(ShrinkwrapModifierData *smd,
if (mesh != nullptr && smd->shrinkType == MOD_SHRINKWRAP_PROJECT) {
/* Setup arrays to get vertex positions, normals and deform weights */
calc.vert_positions = BKE_mesh_vert_positions_for_write(mesh);
calc.vert_normals = BKE_mesh_vertex_normals_ensure(mesh);
calc.vert_normals = BKE_mesh_vert_normals_ensure(mesh);
/* Using vertices positions/normals as if a subsurface was applied */
if (smd->subsurfLevels) {
@ -1569,7 +1568,7 @@ void BKE_shrinkwrap_remesh_target_project(Mesh *src_me, Mesh *target_me, Object
calc.smd = &ssmd;
calc.numVerts = src_me->totvert;
calc.vertexCos = vertexCos;
calc.vert_normals = BKE_mesh_vertex_normals_ensure(src_me);
calc.vert_normals = BKE_mesh_vert_normals_ensure(src_me);
calc.vgroup = -1;
calc.target = target_me;
calc.keepDist = ssmd.keepDist;

View File

@ -535,7 +535,7 @@ static bool subdiv_mesh_topology_info(const SubdivForeachContext *foreach_contex
SubdivMeshContext *subdiv_context = static_cast<SubdivMeshContext *>(foreach_context->user_data);
subdiv_context->subdiv_mesh = BKE_mesh_new_nomain_from_template_ex(
subdiv_context->coarse_mesh, num_vertices, num_edges, num_loops, num_polygons, mask);
subdiv_context->coarse_mesh, num_vertices, num_edges, 0, num_loops, num_polygons, mask);
subdiv_mesh_ctx_cache_custom_data_layers(subdiv_context);
subdiv_mesh_prepare_accumulator(subdiv_context, num_vertices);
subdiv_context->subdiv_mesh->runtime->subsurf_face_dot_tags.clear();
@ -1226,7 +1226,7 @@ Mesh *BKE_subdiv_to_mesh(Subdiv *subdiv,
* calculation. Since vertex normals are supposed to be a consistent cache, don't bother
* calculating them here. The work may have been pointless anyway if the mesh is deformed or
* changed afterwards. */
BLI_assert(BKE_mesh_vertex_normals_are_dirty(result) || BKE_mesh_poly_normals_are_dirty(result));
BLI_assert(BKE_mesh_vert_normals_are_dirty(result) || BKE_mesh_poly_normals_are_dirty(result));
/* Free used memory. */
subdiv_mesh_context_free(&subdiv_context);
return result;

View File

@ -2124,10 +2124,8 @@ static bool txt_select_unprefix(Text *text, const char *remove, const bool requi
return changed_any;
}
void txt_comment(Text *text)
void txt_comment(Text *text, const char *prefix)
{
const char *prefix = "#";
if (ELEM(NULL, text->curl, text->sell)) {
return;
}
@ -2136,10 +2134,8 @@ void txt_comment(Text *text)
txt_select_prefix(text, prefix, skip_blank_lines);
}
bool txt_uncomment(Text *text)
bool txt_uncomment(Text *text, const char *prefix)
{
const char *prefix = "#";
if (ELEM(NULL, text->curl, text->sell)) {
return false;
}

View File

@ -420,7 +420,12 @@ VFont *BKE_vfont_builtin_get(void)
}
}
return BKE_vfont_load(G_MAIN, FO_BUILTIN_NAME);
/* Newly loaded ID's have a user by default, in this case the caller is responsible
* for assigning a user, otherwise an additional user would be added, see: #100819. */
vfont = BKE_vfont_load(G_MAIN, FO_BUILTIN_NAME);
id_us_min(&vfont->id);
BLI_assert(vfont->id.us == 0);
return vfont;
}
static VChar *find_vfont_char(VFontData *vfd, uint character)

View File

@ -302,7 +302,7 @@ void BM_mesh_bm_from_me(BMesh *bm, const Mesh *me, const struct BMeshFromMeshPar
const float(*vert_normals)[3] = nullptr;
if (params->calc_vert_normal) {
vert_normals = BKE_mesh_vertex_normals_ensure(me);
vert_normals = BKE_mesh_vert_normals_ensure(me);
}
if (is_new) {

View File

@ -387,7 +387,7 @@ BLI_INLINE void extract_task_range_run_iter(const MeshRenderData *mr,
int stop;
switch (iter_type) {
case MR_ITER_LOOPTRI:
range_data.elems = is_mesh ? mr->mlooptri : (void *)mr->edit_bmesh->looptris;
range_data.elems = is_mesh ? mr->looptris.data() : (void *)mr->edit_bmesh->looptris;
func = is_mesh ? extract_range_iter_looptri_mesh : extract_range_iter_looptri_bm;
stop = mr->tri_len;
break;

View File

@ -339,7 +339,7 @@ void mesh_render_data_update_looptris(MeshRenderData *mr,
if (mr->extract_type != MR_EXTRACT_BMESH) {
/* Mesh */
if ((iter_type & MR_ITER_LOOPTRI) || (data_flag & MR_DATA_LOOPTRI)) {
mr->mlooptri = BKE_mesh_runtime_looptri_ensure(mr->me);
mr->looptris = mr->me->looptris();
}
}
else {
@ -359,7 +359,7 @@ void mesh_render_data_update_normals(MeshRenderData *mr, const eMRDataType data_
if (mr->extract_type != MR_EXTRACT_BMESH) {
/* Mesh */
mr->vert_normals = BKE_mesh_vertex_normals_ensure(mr->me);
mr->vert_normals = BKE_mesh_vert_normals_ensure(mr->me);
if (data_flag & (MR_DATA_POLY_NOR | MR_DATA_LOOP_NOR | MR_DATA_TAN_LOOP_NOR)) {
mr->poly_normals = BKE_mesh_poly_normals_ensure(mr->me);
}

View File

@ -1625,7 +1625,7 @@ void draw_subdiv_accumulate_normals(const DRWSubdivCache *cache,
GPUVertBuf *face_adjacency_offsets,
GPUVertBuf *face_adjacency_lists,
GPUVertBuf *vertex_loop_map,
GPUVertBuf *vertex_normals)
GPUVertBuf *vert_normals)
{
GPUShader *shader = get_subdiv_shader(SHADER_BUFFER_NORMALS_ACCUMULATE);
GPU_shader_bind(shader);
@ -1636,7 +1636,7 @@ void draw_subdiv_accumulate_normals(const DRWSubdivCache *cache,
GPU_vertbuf_bind_as_ssbo(face_adjacency_offsets, binding_point++);
GPU_vertbuf_bind_as_ssbo(face_adjacency_lists, binding_point++);
GPU_vertbuf_bind_as_ssbo(vertex_loop_map, binding_point++);
GPU_vertbuf_bind_as_ssbo(vertex_normals, binding_point++);
GPU_vertbuf_bind_as_ssbo(vert_normals, binding_point++);
BLI_assert(binding_point <= MAX_GPU_SUBDIV_SSBOS);
drw_subdiv_compute_dispatch(cache, shader, 0, 0, cache->num_subdiv_verts);
@ -1651,7 +1651,7 @@ void draw_subdiv_accumulate_normals(const DRWSubdivCache *cache,
}
void draw_subdiv_finalize_normals(const DRWSubdivCache *cache,
GPUVertBuf *vertex_normals,
GPUVertBuf *vert_normals,
GPUVertBuf *subdiv_loop_subdiv_vert_index,
GPUVertBuf *pos_nor)
{
@ -1659,7 +1659,7 @@ void draw_subdiv_finalize_normals(const DRWSubdivCache *cache,
GPU_shader_bind(shader);
int binding_point = 0;
GPU_vertbuf_bind_as_ssbo(vertex_normals, binding_point++);
GPU_vertbuf_bind_as_ssbo(vert_normals, binding_point++);
GPU_vertbuf_bind_as_ssbo(subdiv_loop_subdiv_vert_index, binding_point++);
GPU_vertbuf_bind_as_ssbo(pos_nor, binding_point++);
BLI_assert(binding_point <= MAX_GPU_SUBDIV_SSBOS);

View File

@ -175,8 +175,8 @@ void DRW_globals_update(void)
max_ff(1.0f, UI_GetThemeValuef(TH_VERTEX_SIZE) * (float)M_SQRT2 / 2.0f);
gb->size_vertex_gpencil = U.pixelsize * UI_GetThemeValuef(TH_GP_VERTEX_SIZE);
gb->size_face_dot = U.pixelsize * UI_GetThemeValuef(TH_FACEDOT_SIZE);
gb->size_edge = U.pixelsize * (1.0f / 2.0f); /* TODO: Theme. */
gb->size_edge_fix = U.pixelsize * (0.5f + 2.0f * (2.0f * (gb->size_edge * (float)M_SQRT1_2)));
gb->size_edge = U.pixelsize * max_ff(1.0f, UI_GetThemeValuef(TH_EDGE_WIDTH)) / 2.0f;
gb->size_edge_fix = U.pixelsize * (0.5f + 2.0f * (1.0f * (gb->size_edge * (float)M_SQRT1_2)));
gb->pixel_fac = *DRW_viewport_pixelsize_get();

View File

@ -229,10 +229,10 @@ void draw_subdiv_accumulate_normals(const DRWSubdivCache *cache,
struct GPUVertBuf *face_adjacency_offsets,
struct GPUVertBuf *face_adjacency_lists,
struct GPUVertBuf *vertex_loop_map,
struct GPUVertBuf *vertex_normals);
struct GPUVertBuf *vert_normals);
void draw_subdiv_finalize_normals(const DRWSubdivCache *cache,
struct GPUVertBuf *vertex_normals,
struct GPUVertBuf *vert_normals,
struct GPUVertBuf *subdiv_loop_subdiv_vert_index,
struct GPUVertBuf *pos_nor);

View File

@ -83,7 +83,7 @@ struct MeshRenderData {
BMFace *efa_act;
BMFace *efa_act_uv;
/* The triangulation of #Mesh polygons, owned by the mesh. */
const MLoopTri *mlooptri;
blender::Span<MLoopTri> looptris;
const int *material_indices;
const float (*vert_normals)[3];
const float (*poly_normals)[3];

View File

@ -74,7 +74,7 @@ static void extract_tris_iter_poly_mesh(const MeshRenderData *mr,
int tri_len = mp->totloop - 2;
for (int offs = 0; offs < tri_len; offs++) {
const MLoopTri *mlt = &mr->mlooptri[tri_first_index_real + offs];
const MLoopTri *mlt = &mr->looptris[tri_first_index_real + offs];
int tri_index = tri_first_index + offs;
GPU_indexbuf_set_tri_verts(elb, tri_index, mlt->tri[0], mlt->tri[1], mlt->tri[2]);
}

View File

@ -214,12 +214,12 @@ static void statvis_calc_thickness(const MeshRenderData *mr, float *r_thickness)
BVHTreeFromMesh treeData = {nullptr};
BVHTree *tree = BKE_bvhtree_from_mesh_get(&treeData, mr->me, BVHTREE_FROM_LOOPTRI, 4);
const MLoopTri *mlooptri = mr->mlooptri;
for (int i = 0; i < mr->tri_len; i++, mlooptri++) {
const int index = mlooptri->poly;
const float *cos[3] = {mr->vert_positions[mr->mloop[mlooptri->tri[0]].v],
mr->vert_positions[mr->mloop[mlooptri->tri[1]].v],
mr->vert_positions[mr->mloop[mlooptri->tri[2]].v]};
const Span<MLoopTri> looptris = mr->looptris;
for (const int i : looptris.index_range()) {
const int index = looptris[i].poly;
const float *cos[3] = {mr->vert_positions[mr->mloop[looptris[i].tri[0]].v],
mr->vert_positions[mr->mloop[looptris[i].tri[1]].v],
mr->vert_positions[mr->mloop[looptris[i].tri[2]].v]};
float ray_co[3];
float ray_no[3];
@ -261,7 +261,7 @@ static void statvis_calc_thickness(const MeshRenderData *mr, float *r_thickness)
struct BVHTree_OverlapData {
const float3 *positions;
const MLoop *loops;
const MLoopTri *mlooptri;
Span<MLoopTri> looptris;
float epsilon;
};
@ -269,8 +269,8 @@ static bool bvh_overlap_cb(void *userdata, int index_a, int index_b, int /*threa
{
struct BVHTree_OverlapData *data = static_cast<struct BVHTree_OverlapData *>(userdata);
const MLoopTri *tri_a = &data->mlooptri[index_a];
const MLoopTri *tri_b = &data->mlooptri[index_b];
const MLoopTri *tri_a = &data->looptris[index_a];
const MLoopTri *tri_b = &data->looptris[index_b];
if (UNLIKELY(tri_a->poly == tri_b->poly)) {
return false;
@ -344,15 +344,15 @@ static void statvis_calc_intersect(const MeshRenderData *mr, float *r_intersect)
struct BVHTree_OverlapData data = {nullptr};
data.positions = mr->vert_positions;
data.loops = mr->mloop;
data.mlooptri = mr->mlooptri;
data.looptris = mr->looptris;
data.epsilon = BLI_bvhtree_get_epsilon(tree);
BVHTreeOverlap *overlap = BLI_bvhtree_overlap_self(tree, &overlap_len, bvh_overlap_cb, &data);
if (overlap) {
for (int i = 0; i < overlap_len; i++) {
const MPoly *f_hit_pair[2] = {
&mr->mpoly[mr->mlooptri[overlap[i].indexA].poly],
&mr->mpoly[mr->mlooptri[overlap[i].indexB].poly],
&mr->mpoly[mr->looptris[overlap[i].indexA].poly],
&mr->mpoly[mr->looptris[overlap[i].indexB].poly],
};
for (int j = 0; j < 2; j++) {
const MPoly *f_hit = f_hit_pair[j];

View File

@ -291,20 +291,20 @@ static void extract_pos_nor_init_subdiv(const DRWSubdivCache *subdiv_cache,
GPUVertBuf *subdiv_loop_subdiv_vert_index = draw_subdiv_build_origindex_buffer(
subdiv_cache->subdiv_loop_subdiv_vert_index, subdiv_cache->num_subdiv_loops);
GPUVertBuf *vertex_normals = GPU_vertbuf_calloc();
GPUVertBuf *vert_normals = GPU_vertbuf_calloc();
GPU_vertbuf_init_build_on_device(
vertex_normals, get_normals_format(), subdiv_cache->num_subdiv_verts);
vert_normals, get_normals_format(), subdiv_cache->num_subdiv_verts);
draw_subdiv_accumulate_normals(subdiv_cache,
vbo,
subdiv_cache->subdiv_vertex_face_adjacency_offsets,
subdiv_cache->subdiv_vertex_face_adjacency,
subdiv_loop_subdiv_vert_index,
vertex_normals);
vert_normals);
draw_subdiv_finalize_normals(subdiv_cache, vertex_normals, subdiv_loop_subdiv_vert_index, vbo);
draw_subdiv_finalize_normals(subdiv_cache, vert_normals, subdiv_loop_subdiv_vert_index, vbo);
GPU_vertbuf_discard(vertex_normals);
GPU_vertbuf_discard(vert_normals);
GPU_vertbuf_discard(subdiv_loop_subdiv_vert_index);
}

View File

@ -118,7 +118,7 @@ static void extract_tan_init_common(const MeshRenderData *mr,
mr->mpoly,
mr->poly_len,
mr->mloop,
mr->mlooptri,
mr->looptris.data(),
mr->tri_len,
cd_ldata,
calc_active_tangent,

View File

@ -198,23 +198,23 @@ static short ob_keyframes_loop(KeyframeEditData *ked,
int filter;
int ret = 0;
bAnimListElem dummychan = {NULL};
Base dummybase = {NULL};
bAnimListElem dummy_chan = {NULL};
Base dummy_base = {NULL};
if (ob == NULL) {
return 0;
}
/* create a dummy wrapper data to work with */
dummybase.object = ob;
dummy_base.object = ob;
dummychan.type = ANIMTYPE_OBJECT;
dummychan.data = &dummybase;
dummychan.id = &ob->id;
dummychan.adt = ob->adt;
dummy_chan.type = ANIMTYPE_OBJECT;
dummy_chan.data = &dummy_base;
dummy_chan.id = &ob->id;
dummy_chan.adt = ob->adt;
ac.ads = ads;
ac.data = &dummychan;
ac.data = &dummy_chan;
ac.datatype = ANIMCONT_CHANNEL;
/* get F-Curves to take keyframes from */
@ -250,20 +250,20 @@ static short scene_keyframes_loop(KeyframeEditData *ked,
int filter;
int ret = 0;
bAnimListElem dummychan = {NULL};
bAnimListElem dummy_chan = {NULL};
if (sce == NULL) {
return 0;
}
/* create a dummy wrapper data to work with */
dummychan.type = ANIMTYPE_SCENE;
dummychan.data = sce;
dummychan.id = &sce->id;
dummychan.adt = sce->adt;
dummy_chan.type = ANIMTYPE_SCENE;
dummy_chan.data = sce;
dummy_chan.id = &sce->id;
dummy_chan.adt = sce->adt;
ac.ads = ads;
ac.data = &dummychan;
ac.data = &dummy_chan;
ac.datatype = ANIMCONT_CHANNEL;
/* get F-Curves to take keyframes from */

View File

@ -926,20 +926,20 @@ void scene_to_keylist(bDopeSheet *ads, Scene *sce, AnimKeylist *keylist, const i
bAnimContext ac = {nullptr};
ListBase anim_data = {nullptr, nullptr};
bAnimListElem dummychan = {nullptr};
bAnimListElem dummy_chan = {nullptr};
if (sce == nullptr) {
return;
}
/* create a dummy wrapper data to work with */
dummychan.type = ANIMTYPE_SCENE;
dummychan.data = sce;
dummychan.id = &sce->id;
dummychan.adt = sce->adt;
dummy_chan.type = ANIMTYPE_SCENE;
dummy_chan.data = sce;
dummy_chan.id = &sce->id;
dummy_chan.adt = sce->adt;
ac.ads = ads;
ac.data = &dummychan;
ac.data = &dummy_chan;
ac.datatype = ANIMCONT_CHANNEL;
/* get F-Curves to take keyframes from */
@ -961,23 +961,23 @@ void ob_to_keylist(bDopeSheet *ads, Object *ob, AnimKeylist *keylist, const int
bAnimContext ac = {nullptr};
ListBase anim_data = {nullptr, nullptr};
bAnimListElem dummychan = {nullptr};
Base dummybase = {nullptr};
bAnimListElem dummy_chan = {nullptr};
Base dummy_base = {nullptr};
if (ob == nullptr) {
return;
}
/* create a dummy wrapper data to work with */
dummybase.object = ob;
dummy_base.object = ob;
dummychan.type = ANIMTYPE_OBJECT;
dummychan.data = &dummybase;
dummychan.id = &ob->id;
dummychan.adt = ob->adt;
dummy_chan.type = ANIMTYPE_OBJECT;
dummy_chan.data = &dummy_base;
dummy_chan.id = &ob->id;
dummy_chan.adt = ob->adt;
ac.ads = ads;
ac.data = &dummychan;
ac.data = &dummy_chan;
ac.datatype = ANIMCONT_CHANNEL;
/* get F-Curves to take keyframes from */
@ -1003,15 +1003,15 @@ void cachefile_to_keylist(bDopeSheet *ads,
}
/* create a dummy wrapper data to work with */
bAnimListElem dummychan = {nullptr};
dummychan.type = ANIMTYPE_DSCACHEFILE;
dummychan.data = cache_file;
dummychan.id = &cache_file->id;
dummychan.adt = cache_file->adt;
bAnimListElem dummy_chan = {nullptr};
dummy_chan.type = ANIMTYPE_DSCACHEFILE;
dummy_chan.data = cache_file;
dummy_chan.id = &cache_file->id;
dummy_chan.adt = cache_file->adt;
bAnimContext ac = {nullptr};
ac.ads = ads;
ac.data = &dummychan;
ac.data = &dummy_chan;
ac.datatype = ANIMCONT_CHANNEL;
/* get F-Curves to take keyframes from */

View File

@ -928,7 +928,7 @@ typedef struct MeshDeformBind {
struct {
blender::Span<MPoly> polys;
blender::Span<MLoop> loops;
const MLoopTri *looptri;
blender::Span<MLoopTri> looptris;
const float (*poly_nors)[3];
} cagemesh_cache;
} MeshDeformBind;
@ -959,13 +959,12 @@ static void harmonic_ray_callback(void *userdata,
MeshRayCallbackData *data = static_cast<MeshRayCallbackData *>(userdata);
MeshDeformBind *mdb = data->mdb;
const blender::Span<MLoop> loops = mdb->cagemesh_cache.loops;
const MLoopTri *looptri = mdb->cagemesh_cache.looptri, *lt;
const float(*poly_nors)[3] = mdb->cagemesh_cache.poly_nors;
MeshDeformIsect *isec = data->isec;
float no[3], co[3], dist;
float *face[3];
lt = &looptri[index];
const MLoopTri *lt = &mdb->cagemesh_cache.looptris[index];
face[0] = mdb->cagecos[loops[lt->tri[0]].v];
face[1] = mdb->cagecos[loops[lt->tri[1]].v];
@ -1034,7 +1033,7 @@ static MDefBoundIsect *meshdeform_ray_tree_intersect(MeshDeformBind *mdb,
&data,
BVH_RAYCAST_WATERTIGHT) != -1) {
const blender::Span<MLoop> loops = mdb->cagemesh_cache.loops;
const MLoopTri *lt = &mdb->cagemesh_cache.looptri[hit.index];
const MLoopTri *lt = &mdb->cagemesh_cache.looptris[hit.index];
const MPoly *mp = &mdb->cagemesh_cache.polys[lt->poly];
const float(*cagecos)[3] = mdb->cagecos;
const float len = isect_mdef.lambda;
@ -1632,7 +1631,7 @@ static void harmonic_coordinates_bind(MeshDeformModifierData *mmd, MeshDeformBin
Mesh *me = mdb->cagemesh;
mdb->cagemesh_cache.polys = me->polys();
mdb->cagemesh_cache.loops = me->loops();
mdb->cagemesh_cache.looptri = BKE_mesh_runtime_looptri_ensure(me);
mdb->cagemesh_cache.looptris = me->looptris();
mdb->cagemesh_cache.poly_nors = BKE_mesh_poly_normals_ensure(me);
}

View File

@ -1174,21 +1174,30 @@ static int gizmo_cage2d_modal(bContext *C,
}
}
float scale[2] = {1.0f, 1.0f};
for (int i = 0; i < 2; i++) {
if (size_orig[i] == 0) {
size_orig[i] = 1.0f;
gz->matrix_offset[i][i] = 1.0f;
}
scale[i] = size_new[i] / size_orig[i];
}
if (transform_flag & ED_GIZMO_CAGE_XFORM_FLAG_SCALE_UNIFORM) {
if (constrain_axis[0] == false && constrain_axis[1] == false) {
if (draw_style == ED_GIZMO_CAGE2D_STYLE_CIRCLE) {
/* So that the cursor lies on the circle. */
size_new[1] = size_new[0] = len_v2(size_new);
scale[1] = scale[0] = len_v2(scale);
}
else {
size_new[1] = size_new[0] = (size_new[1] + size_new[0]) / 2.0f;
scale[1] = scale[0] = (scale[1] + scale[0]) / 2.0f;
}
}
else if (constrain_axis[0] == false) {
size_new[1] = size_new[0];
scale[1] = scale[0];
}
else if (constrain_axis[1] == false) {
size_new[0] = size_new[1];
scale[0] = scale[1];
}
else {
BLI_assert(0);
@ -1196,18 +1205,11 @@ static int gizmo_cage2d_modal(bContext *C,
}
/* Scale around pivot. */
float scale[2];
float matrix_scale[4][4];
unit_m4(matrix_scale);
for (int i = 0; i < 2; i++) {
if (size_orig[i] == 0) {
size_orig[i] = 1.0f;
gz->matrix_offset[i][i] = 1.0f;
}
scale[i] = size_new[i] / size_orig[i];
mul_v3_fl(matrix_scale[i], scale[i]);
}
mul_v3_fl(matrix_scale[0], scale[0]);
mul_v3_fl(matrix_scale[1], scale[1]);
transform_pivot_set_m4(matrix_scale, (const float[3]){UNPACK2(pivot), 0.0f});
mul_m4_m4_post(gz->matrix_offset, matrix_scale);

View File

@ -223,7 +223,7 @@ typedef struct KeyingSetInfo {
/* identifier so that user can hook this up to a KeyingSet (used as label). */
char name[64];
/* short help/description. */
char description[240]; /* RNA_DYN_DESCR_MAX */
char description[1024]; /* #RNA_DYN_DESCR_MAX */
/* keying settings */
short keyingflag;

View File

@ -43,6 +43,8 @@ struct UndoStep *ED_text_undo_push_init(struct bContext *C);
/* text_format.c */
const char *ED_text_format_comment_line_prefix(struct Text *text);
bool ED_text_is_syntax_highlight_supported(struct Text *text);
#ifdef __cplusplus

View File

@ -26,6 +26,7 @@ struct Object;
struct Scene;
struct SpaceImage;
struct ToolSettings;
struct UVPackIsland_Params;
struct View2D;
struct ViewLayer;
struct bContext;
@ -348,26 +349,6 @@ struct UVMapUDIM_Params {
int grid_shape[2];
};
typedef enum {
ED_UVPACK_MARGIN_SCALED = 0, /* Use scale of existing UVs to multiply margin. */
ED_UVPACK_MARGIN_ADD, /* Just add the margin, ignoring any UV scale. */
ED_UVPACK_MARGIN_FRACTION, /* Specify a precise fraction of final UV output. */
} eUVPackIsland_MarginMethod;
/** See also #UnwrapOptions. */
struct UVPackIsland_Params {
uint rotate : 1;
uint only_selected_uvs : 1;
uint only_selected_faces : 1;
uint use_seams : 1;
uint correct_aspect : 1;
bool ignore_pinned; /* Ignore islands which have any pinned UVs. */
bool pin_unselected; /* Treat unselected UVs as if they were pinned. */
eUVPackIsland_MarginMethod margin_method; /* Which formula to use when scaling island margin. */
float margin; /* Additional space to add around each island. */
float udim_base_offset[2]; /* Additional translation for bottom left corner. */
};
/**
* Returns true if UV coordinates lie on a valid tile in UDIM grid or tiled image.
*/

View File

@ -79,6 +79,7 @@ typedef enum ThemeColorID {
TH_VERTEX_ACTIVE,
TH_VERTEX_UNREFERENCED,
TH_VERTEX_SIZE,
TH_EDGE_WIDTH,
TH_OUTLINE_WIDTH,
TH_OBCENTER_DIA,
TH_EDGE,

View File

@ -366,6 +366,9 @@ const uchar *UI_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colorid)
case TH_EDGE:
cp = ts->edge;
break;
case TH_EDGE_WIDTH:
cp = &ts->edge_width;
break;
case TH_EDGE_SELECT:
cp = ts->edge_select;
break;

View File

@ -685,7 +685,7 @@ static void undomesh_to_editmesh(UndoMesh *um, Object *ob, BMEditMesh *em)
/* Normals should not be stored in the undo mesh, so recalculate them. The edit
* mesh is expected to have valid normals and there is no tracked dirty state. */
BLI_assert(BKE_mesh_vertex_normals_are_dirty(&um->me));
BLI_assert(BKE_mesh_vert_normals_are_dirty(&um->me));
/* Calculate face normals and tessellation at once since it's multi-threaded. */
BKE_editmesh_looptri_and_normals_calc(em);

View File

@ -1453,7 +1453,7 @@ void recalc_emitter_field(Depsgraph *UNUSED(depsgraph), Object *UNUSED(ob), Part
nor = vec + 3;
const float(*positions)[3] = BKE_mesh_vert_positions(mesh);
const float(*vert_normals)[3] = BKE_mesh_vertex_normals_ensure(mesh);
const float(*vert_normals)[3] = BKE_mesh_vert_normals_ensure(mesh);
const MFace *mfaces = (const MFace *)CustomData_get_layer(&mesh->fdata, CD_MFACE);
for (i = 0; i < totface; i++, vec += 6, nor += 6) {
const MFace *mface = &mfaces[i];

View File

@ -784,8 +784,8 @@ static Object *object_preview_camera_create(Main *preview_main,
Object *camera = BKE_object_add(preview_main, scene, view_layer, OB_CAMERA, "Preview Camera");
float rotmat[3][3];
float dummyscale[3];
mat4_to_loc_rot_size(camera->loc, rotmat, dummyscale, preview_object->object_to_world);
float dummy_scale[3];
mat4_to_loc_rot_size(camera->loc, rotmat, dummy_scale, preview_object->object_to_world);
/* Camera is Y up, so needs additional rotations to obliquely face the front. */
float drotmat[3][3];

View File

@ -419,7 +419,7 @@ struct ProjPaintState {
blender::Span<MLoop> loops_eval;
const bool *select_poly_eval;
const int *material_indices;
const MLoopTri *mlooptri_eval;
blender::Span<MLoopTri> looptris_eval;
const float (*mloopuv_stencil_eval)[2];
@ -551,7 +551,7 @@ static Material *tex_get_material(const ProjPaintState *ps, int poly_i)
static TexPaintSlot *project_paint_face_paint_slot(const ProjPaintState *ps, int tri_index)
{
const int poly_i = ps->mlooptri_eval[tri_index].poly;
const int poly_i = ps->looptris_eval[tri_index].poly;
Material *ma = tex_get_material(ps, poly_i);
return ma ? ma->texpaintslot + ma->paint_active_slot : nullptr;
}
@ -562,7 +562,7 @@ static Image *project_paint_face_paint_image(const ProjPaintState *ps, int tri_i
return ps->stencil_ima;
}
const int poly_i = ps->mlooptri_eval[tri_index].poly;
const int poly_i = ps->looptris_eval[tri_index].poly;
Material *ma = tex_get_material(ps, poly_i);
TexPaintSlot *slot = ma ? ma->texpaintslot + ma->paint_active_slot : nullptr;
return slot ? slot->ima : ps->canvas_ima;
@ -570,14 +570,14 @@ static Image *project_paint_face_paint_image(const ProjPaintState *ps, int tri_i
static TexPaintSlot *project_paint_face_clone_slot(const ProjPaintState *ps, int tri_index)
{
const int poly_i = ps->mlooptri_eval[tri_index].poly;
const int poly_i = ps->looptris_eval[tri_index].poly;
Material *ma = tex_get_material(ps, poly_i);
return ma ? ma->texpaintslot + ma->paint_clone_slot : nullptr;
}
static Image *project_paint_face_clone_image(const ProjPaintState *ps, int tri_index)
{
const int poly_i = ps->mlooptri_eval[tri_index].poly;
const int poly_i = ps->looptris_eval[tri_index].poly;
Material *ma = tex_get_material(ps, poly_i);
TexPaintSlot *slot = ma ? ma->texpaintslot + ma->paint_clone_slot : nullptr;
return slot ? slot->ima : ps->clone_ima;
@ -673,7 +673,7 @@ static int project_paint_PickFace(const ProjPaintState *ps, const float pt[2], f
for (node = ps->bucketFaces[bucket_index]; node; node = node->next) {
const int tri_index = POINTER_AS_INT(node->link);
const MLoopTri *lt = &ps->mlooptri_eval[tri_index];
const MLoopTri *lt = &ps->looptris_eval[tri_index];
const float *vtri_ss[3] = {
ps->screenCoords[ps->loops_eval[lt->tri[0]].v],
ps->screenCoords[ps->loops_eval[lt->tri[1]].v],
@ -737,7 +737,7 @@ static bool project_paint_PickColor(
return false;
}
lt = &ps->mlooptri_eval[tri_index];
lt = &ps->looptris_eval[tri_index];
PS_LOOPTRI_ASSIGN_UV_3(lt_tri_uv, ps->poly_to_loop_uv, lt);
interp_v2_v2v2v2(uv, UNPACK3(lt_tri_uv), w);
@ -915,7 +915,7 @@ static bool project_bucket_point_occluded(const ProjPaintState *ps,
const int tri_index = POINTER_AS_INT(bucketFace->link);
if (orig_face != tri_index) {
const MLoopTri *lt = &ps->mlooptri_eval[tri_index];
const MLoopTri *lt = &ps->looptris_eval[tri_index];
const float *vtri_ss[3] = {
ps->screenCoords[ps->loops_eval[lt->tri[0]].v],
ps->screenCoords[ps->loops_eval[lt->tri[1]].v],
@ -1121,7 +1121,7 @@ static bool pixel_bounds_array(
static void project_face_winding_init(const ProjPaintState *ps, const int tri_index)
{
/* detect the winding of faces in uv space */
const MLoopTri *lt = &ps->mlooptri_eval[tri_index];
const MLoopTri *lt = &ps->looptris_eval[tri_index];
const float *lt_tri_uv[3] = {PS_LOOPTRI_AS_UV_3(ps->poly_to_loop_uv, lt)};
float winding = cross_tri_v2(lt_tri_uv[0], lt_tri_uv[1], lt_tri_uv[2]);
@ -1141,7 +1141,7 @@ static bool check_seam(const ProjPaintState *ps,
int *other_face,
int *orig_fidx)
{
const MLoopTri *orig_lt = &ps->mlooptri_eval[orig_face];
const MLoopTri *orig_lt = &ps->looptris_eval[orig_face];
const float *orig_lt_tri_uv[3] = {PS_LOOPTRI_AS_UV_3(ps->poly_to_loop_uv, orig_lt)};
/* vert indices from face vert order indices */
const uint i1 = ps->loops_eval[orig_lt->tri[orig_i1_fidx]].v;
@ -1154,7 +1154,7 @@ static bool check_seam(const ProjPaintState *ps,
const int tri_index = POINTER_AS_INT(node->link);
if (tri_index != orig_face) {
const MLoopTri *lt = &ps->mlooptri_eval[tri_index];
const MLoopTri *lt = &ps->looptris_eval[tri_index];
const int lt_vtri[3] = {PS_LOOPTRI_AS_VERT_INDEX_3(ps, lt)};
/* could check if the 2 faces images match here,
* but then there wouldn't be a way to return the opposite face's info */
@ -1303,7 +1303,7 @@ static void uv_image_outset(const ProjPaintState *ps,
int fidx[2];
uint loop_index;
uint vert[2];
const MLoopTri *ltri = &ps->mlooptri_eval[tri_index];
const MLoopTri *ltri = &ps->looptris_eval[tri_index];
float ibuf_inv[2];
@ -1386,7 +1386,7 @@ static void insert_seam_vert_array(const ProjPaintState *ps,
const int ibuf_x,
const int ibuf_y)
{
const MLoopTri *lt = &ps->mlooptri_eval[tri_index];
const MLoopTri *lt = &ps->looptris_eval[tri_index];
const float *lt_tri_uv[3] = {PS_LOOPTRI_AS_UV_3(ps->poly_to_loop_uv, lt)};
const int fidx[2] = {fidx1, ((fidx1 + 1) % 3)};
float vec[2];
@ -1446,7 +1446,7 @@ static void project_face_seams_init(const ProjPaintState *ps,
int other_face, other_fidx;
/* next fidx in the face (0,1,2,3) -> (1,2,3,0) or (0,1,2) -> (1,2,0) for a tri */
int fidx[2] = {2, 0};
const MLoopTri *lt = &ps->mlooptri_eval[tri_index];
const MLoopTri *lt = &ps->looptris_eval[tri_index];
LinkNode *node;
/* initialize face winding if needed */
@ -1665,7 +1665,7 @@ static float project_paint_uvpixel_mask(const ProjPaintState *ps,
Image *other_tpage = ps->stencil_ima;
if (other_tpage && (ibuf_other = BKE_image_acquire_ibuf(other_tpage, nullptr, nullptr))) {
const MLoopTri *lt_other = &ps->mlooptri_eval[tri_index];
const MLoopTri *lt_other = &ps->looptris_eval[tri_index];
const float *lt_other_tri_uv[3] = {ps->mloopuv_stencil_eval[lt_other->tri[0]],
ps->mloopuv_stencil_eval[lt_other->tri[1]],
ps->mloopuv_stencil_eval[lt_other->tri[2]]};
@ -1704,7 +1704,7 @@ static float project_paint_uvpixel_mask(const ProjPaintState *ps,
}
if (ps->do_mask_cavity) {
const MLoopTri *lt = &ps->mlooptri_eval[tri_index];
const MLoopTri *lt = &ps->looptris_eval[tri_index];
const int lt_vtri[3] = {PS_LOOPTRI_AS_VERT_INDEX_3(ps, lt)};
float ca1, ca2, ca3, ca_mask;
ca1 = ps->cavities[lt_vtri[0]];
@ -1719,7 +1719,7 @@ static float project_paint_uvpixel_mask(const ProjPaintState *ps,
/* calculate mask */
if (ps->do_mask_normal) {
const MLoopTri *lt = &ps->mlooptri_eval[tri_index];
const MLoopTri *lt = &ps->looptris_eval[tri_index];
const int lt_vtri[3] = {PS_LOOPTRI_AS_VERT_INDEX_3(ps, lt)};
const MPoly *mp = &ps->polys_eval[lt->poly];
float no[3], angle_cos;
@ -1959,7 +1959,7 @@ static ProjPixel *project_paint_uvpixel_init(const ProjPaintState *ps,
Image *other_tpage = project_paint_face_clone_image(ps, tri_index);
if (other_tpage && (ibuf_other = BKE_image_acquire_ibuf(other_tpage, nullptr, nullptr))) {
const MLoopTri *lt_other = &ps->mlooptri_eval[tri_index];
const MLoopTri *lt_other = &ps->looptris_eval[tri_index];
const float *lt_other_tri_uv[3] = {
PS_LOOPTRI_AS_UV_3(ps->poly_to_loop_uv_clone, lt_other)};
@ -2996,7 +2996,7 @@ static void project_paint_face_init(const ProjPaintState *ps,
ps->projImages + image_index,
};
const MLoopTri *lt = &ps->mlooptri_eval[tri_index];
const MLoopTri *lt = &ps->looptris_eval[tri_index];
const int lt_vtri[3] = {PS_LOOPTRI_AS_VERT_INDEX_3(ps, lt)};
const float *lt_tri_uv[3] = {PS_LOOPTRI_AS_UV_3(ps->poly_to_loop_uv, lt)};
@ -3287,7 +3287,7 @@ static void project_paint_face_init(const ProjPaintState *ps,
bucket_clip_edges[1])) {
/* Avoid div by zero. */
if (len_squared_v2v2(vCoSS[fidx1], vCoSS[fidx2]) > FLT_EPSILON) {
uint loop_idx = ps->mlooptri_eval[tri_index].tri[fidx1];
uint loop_idx = ps->looptris_eval[tri_index].tri[fidx1];
LoopSeamData *seam_data = &ps->loopSeamData[loop_idx];
float(*seam_uvs)[2] = seam_data->seam_uvs;
@ -3525,7 +3525,7 @@ static void project_bucket_init(const ProjPaintState *ps,
for (node = ps->bucketFaces[bucket_index]; node; node = node->next) {
tri_index = POINTER_AS_INT(node->link);
const MLoopTri *lt = &ps->mlooptri_eval[tri_index];
const MLoopTri *lt = &ps->looptris_eval[tri_index];
const float *lt_tri_uv[3] = {PS_LOOPTRI_AS_UV_3(ps->poly_to_loop_uv, lt)};
/* Image context switching */
@ -4071,7 +4071,7 @@ static bool proj_paint_state_mesh_eval_init(const bContext *C, ProjPaintState *p
ps->mat_array[totmat - 1] = nullptr;
ps->vert_positions_eval = BKE_mesh_vert_positions(ps->me_eval);
ps->vert_normals = BKE_mesh_vertex_normals_ensure(ps->me_eval);
ps->vert_normals = BKE_mesh_vert_normals_ensure(ps->me_eval);
ps->edges_eval = ps->me_eval->edges();
ps->polys_eval = ps->me_eval->polys();
ps->loops_eval = ps->me_eval->loops();
@ -4085,8 +4085,7 @@ static bool proj_paint_state_mesh_eval_init(const bContext *C, ProjPaintState *p
ps->totpoly_eval = ps->me_eval->totpoly;
ps->totloop_eval = ps->me_eval->totloop;
ps->mlooptri_eval = BKE_mesh_runtime_looptri_ensure(ps->me_eval);
ps->totlooptri_eval = BKE_mesh_runtime_looptri_len(ps->me_eval);
ps->looptris_eval = ps->me_eval->looptris();
ps->poly_to_loop_uv = static_cast<const float(**)[2]>(
MEM_mallocN(ps->totpoly_eval * sizeof(float(*)[2]), "proj_paint_mtfaces"));
@ -4159,7 +4158,7 @@ static bool project_paint_clone_face_skip(ProjPaintState *ps,
}
/* will set multiple times for 4+ sided poly */
ps->poly_to_loop_uv_clone[ps->mlooptri_eval[tri_index].poly] = lc->mloopuv_clone_base;
ps->poly_to_loop_uv_clone[ps->looptris_eval[tri_index].poly] = lc->mloopuv_clone_base;
}
return false;
}
@ -4304,17 +4303,17 @@ static void project_paint_prepare_all_faces(ProjPaintState *ps,
TexPaintSlot *slot_last = nullptr;
TexPaintSlot *slot = nullptr;
int tile_last = -1, tile;
const MLoopTri *lt;
int image_index = -1, tri_index;
int prev_poly = -1;
const blender::Span<MLoopTri> looptris = ps->looptris_eval;
BLI_assert(ps->image_tot == 0);
for (tri_index = 0, lt = ps->mlooptri_eval; tri_index < ps->totlooptri_eval; tri_index++, lt++) {
for (tri_index = 0; tri_index < ps->totlooptri_eval; tri_index++) {
bool is_face_sel;
bool skip_tri = false;
is_face_sel = project_paint_check_face_sel(ps, face_lookup, lt);
is_face_sel = project_paint_check_face_sel(ps, face_lookup, &looptris[tri_index]);
if (!ps->do_stencil_brush) {
slot = project_paint_face_paint_slot(ps, tri_index);
@ -4353,12 +4352,12 @@ static void project_paint_prepare_all_faces(ProjPaintState *ps,
tpage = ps->stencil_ima;
}
ps->poly_to_loop_uv[lt->poly] = mloopuv_base;
ps->poly_to_loop_uv[looptris[tri_index].poly] = mloopuv_base;
tile = project_paint_face_paint_tile(tpage, mloopuv_base[lt->tri[0]]);
tile = project_paint_face_paint_tile(tpage, mloopuv_base[looptris[tri_index].tri[0]]);
#ifndef PROJ_DEBUG_NOSEAMBLEED
project_paint_bleed_add_face_user(ps, arena, lt, tri_index);
project_paint_bleed_add_face_user(ps, arena, &looptris[tri_index], tri_index);
#endif
if (skip_tri || project_paint_clone_face_skip(ps, layer_clone, slot, tri_index)) {
@ -4369,7 +4368,7 @@ static void project_paint_prepare_all_faces(ProjPaintState *ps,
if (is_face_sel && tpage) {
ProjPaintFaceCoSS coSS;
proj_paint_face_coSS_init(ps, lt, &coSS);
proj_paint_face_coSS_init(ps, &looptris[tri_index], &coSS);
if (is_multi_view == false) {
if (project_paint_flt_max_cull(ps, &coSS)) {
@ -4386,12 +4385,12 @@ static void project_paint_prepare_all_faces(ProjPaintState *ps,
/* Back-face culls individual triangles but mask normal will use polygon. */
if (ps->do_backfacecull) {
if (ps->do_mask_normal) {
if (prev_poly != lt->poly) {
if (prev_poly != looptris[tri_index].poly) {
int iloop;
bool culled = true;
const MPoly *poly = &ps->polys_eval[lt->poly];
const MPoly *poly = &ps->polys_eval[looptris[tri_index].poly];
int poly_loops = poly->totloop;
prev_poly = lt->poly;
prev_poly = looptris[tri_index].poly;
for (iloop = 0; iloop < poly_loops; iloop++) {
if (!(ps->vertFlags[ps->loops_eval[poly->loopstart + iloop].v] & PROJ_VERT_CULL)) {
culled = false;
@ -4404,7 +4403,6 @@ static void project_paint_prepare_all_faces(ProjPaintState *ps,
* but counter gets incremented when continuing, so decrease by 3 */
int poly_tri = poly_loops - 3;
tri_index += poly_tri;
lt += poly_tri;
continue;
}
}
@ -4451,7 +4449,7 @@ static void project_paint_prepare_all_faces(ProjPaintState *ps,
if (image_index != -1) {
/* Initialize the faces screen pixels */
/* Add this to a list to initialize later */
project_paint_delayed_face_init(ps, lt, tri_index);
project_paint_delayed_face_init(ps, &looptris[tri_index], tri_index);
}
}
}
@ -5703,7 +5701,7 @@ static bool project_paint_op(void *state, const float lastpos[2], const float po
tri_index = project_paint_PickFace(ps, pos, w);
if (tri_index != -1) {
const MLoopTri *lt = &ps->mlooptri_eval[tri_index];
const MLoopTri *lt = &ps->looptris_eval[tri_index];
const int lt_vtri[3] = {PS_LOOPTRI_AS_VERT_INDEX_3(ps, lt)};
float world[3];
UnifiedPaintSettings *ups = &ps->scene->toolsettings->unified_paint_settings;

View File

@ -5547,7 +5547,7 @@ void SCULPT_flush_update_step(bContext *C, SculptUpdateType update_flags)
if (update_flags & SCULPT_UPDATE_COORDS && !ss->shapekey_active) {
if (BKE_pbvh_type(ss->pbvh) == PBVH_FACES) {
/* When sculpting and changing the positions of a mesh, tag them as changed and update. */
BKE_mesh_tag_coords_changed(mesh);
BKE_mesh_tag_positions_changed(mesh);
/* Update the mesh's bounds eagerly since the PBVH already has that information. */
mesh->runtime->bounds_cache.ensure([&](Bounds<float3> &r_bounds) {
BKE_pbvh_bounding_box(ob->sculpt->pbvh, r_bounds.min, r_bounds.max);

View File

@ -1092,7 +1092,7 @@ static void sculpt_undo_restore_list(bContext *C, Depsgraph *depsgraph, ListBase
if (tag_update) {
Mesh *mesh = static_cast<Mesh *>(ob->data);
BKE_mesh_tag_coords_changed(mesh);
BKE_mesh_tag_positions_changed(mesh);
BKE_sculptsession_free_deformMats(ss);
}

View File

@ -853,7 +853,7 @@ void uiTemplateMovieclipInformation(uiLayout *layout,
const char *file;
if (framenr <= clip->len) {
BKE_movieclip_filename_for_frame(clip, user, filepath);
BKE_movieclip_filepath_for_frame(clip, user, filepath);
file = BLI_path_slash_rfind(filepath);
}
else {

View File

@ -703,10 +703,10 @@ static uchar *prefetch_read_file_to_memory(
user.render_size = render_size;
user.render_flag = render_flag;
char name[FILE_MAX];
BKE_movieclip_filename_for_frame(clip, &user, name);
char filepath[FILE_MAX];
BKE_movieclip_filepath_for_frame(clip, &user, filepath);
int file = BLI_open(name, O_BINARY | O_RDONLY, 0);
int file = BLI_open(filepath, O_BINARY | O_RDONLY, 0);
if (file == -1) {
return NULL;
}

View File

@ -1307,15 +1307,15 @@ static uchar *proxy_thread_next_frame(ProxyQueue *queue,
BLI_spin_lock(&queue->spin);
if (!*queue->stop && queue->cfra <= queue->efra) {
MovieClipUser user = *DNA_struct_default_get(MovieClipUser);
char name[FILE_MAX];
char filepath[FILE_MAX];
size_t size;
int file;
user.framenr = queue->cfra;
BKE_movieclip_filename_for_frame(clip, &user, name);
BKE_movieclip_filepath_for_frame(clip, &user, filepath);
file = BLI_open(name, O_BINARY | O_RDONLY, 0);
file = BLI_open(filepath, O_BINARY | O_RDONLY, 0);
if (file < 0) {
BLI_spin_unlock(&queue->spin);
return NULL;

View File

@ -902,7 +902,7 @@ void file_draw_list(const bContext *C, ARegion *region)
int numfiles;
int numfiles_layout;
int offset;
int textwidth, textheight;
int column_width, textheight;
int i;
bool is_icon;
eFontStyle_Align align;
@ -936,9 +936,9 @@ void file_draw_list(const bContext *C, ARegion *region)
filelist_file_cache_slidingwindow_set(files, numfiles_layout);
textwidth = (FILE_IMGDISPLAY == params->display) ?
layout->tile_w :
round_fl_to_int(layout->attribute_columns[COLUMN_NAME].width);
column_width = (FILE_IMGDISPLAY == params->display) ?
layout->tile_w :
round_fl_to_int(layout->attribute_columns[COLUMN_NAME].width);
textheight = (int)(layout->textheight * 3.0 / 2.0 + 0.5);
align = (FILE_IMGDISPLAY == params->display) ? UI_STYLE_TEXT_CENTER : UI_STYLE_TEXT_LEFT;
@ -1053,7 +1053,7 @@ void file_draw_list(const bContext *C, ARegion *region)
if (file_selflag & FILE_SEL_EDITING) {
const short width = (params->display == FILE_IMGDISPLAY) ?
textwidth :
column_width :
layout->attribute_columns[COLUMN_NAME].width -
ATTRIBUTE_COLUMN_PADDING;
@ -1099,8 +1099,8 @@ void file_draw_list(const bContext *C, ARegion *region)
tile_draw_rect.ymin + layout->tile_border_y + layout->textheight :
tile_draw_rect.ymax - layout->tile_border_y;
const int twidth = (params->display == FILE_IMGDISPLAY) ?
textwidth :
textwidth - 1 - icon_ofs - padx - layout->tile_border_x;
column_width :
column_width - 1 - icon_ofs - padx - layout->tile_border_x;
file_draw_string(txpos, typos, file->name, (float)twidth, textheight, align, text_col);
}

View File

@ -199,6 +199,12 @@ TextFormatType *ED_text_format_get(Text *text)
return tft_lb.first;
}
const char *ED_text_format_comment_line_prefix(Text *text)
{
const struct TextFormatType *format = ED_text_format_get(text);
return format->comment_line;
}
bool ED_text_is_syntax_highlight_supported(Text *text)
{
if (text == NULL) {

View File

@ -75,6 +75,9 @@ typedef struct TextFormatType {
void (*format_line)(SpaceText *st, TextLine *line, bool do_next);
const char **ext; /* NULL terminated extensions */
/** The prefix of a single-line line comment (without trailing space). */
const char *comment_line;
} TextFormatType;
enum {

View File

@ -341,6 +341,7 @@ void ED_text_format_register_lua(void)
tft.format_identifier = txtfmt_lua_format_identifier;
tft.format_line = txtfmt_lua_format_line;
tft.ext = ext;
tft.comment_line = "--";
ED_text_format_register(&tft);
}

View File

@ -359,6 +359,7 @@ void ED_text_format_register_osl(void)
tft.format_identifier = txtfmt_osl_format_identifier;
tft.format_line = txtfmt_osl_format_line;
tft.ext = ext;
tft.comment_line = "//";
ED_text_format_register(&tft);
}

View File

@ -936,6 +936,7 @@ void ED_text_format_register_pov(void)
tft.format_identifier = txtfmt_pov_format_identifier;
tft.format_line = txtfmt_pov_format_line;
tft.ext = ext;
tft.comment_line = "//";
ED_text_format_register(&tft);
}

View File

@ -512,6 +512,7 @@ void ED_text_format_register_pov_ini(void)
tft.format_identifier = txtfmt_pov_ini_format_identifier;
tft.format_line = txtfmt_pov_ini_format_line;
tft.ext = ext;
tft.comment_line = "//";
ED_text_format_register(&tft);
}

View File

@ -507,6 +507,7 @@ void ED_text_format_register_py(void)
tft.format_identifier = txtfmt_py_format_identifier;
tft.format_line = txtfmt_py_format_line;
tft.ext = ext;
tft.comment_line = "#";
ED_text_format_register(&tft);
}

View File

@ -1273,6 +1273,7 @@ static int text_comment_exec(bContext *C, wmOperator *op)
{
Text *text = CTX_data_edit_text(C);
int type = RNA_enum_get(op->ptr, "type");
const char *prefix = ED_text_format_comment_line_prefix(text);
text_drawcache_tag_update(CTX_wm_space_text(C), 0);
@ -1284,14 +1285,14 @@ static int text_comment_exec(bContext *C, wmOperator *op)
switch (type) {
case 1:
txt_comment(text);
txt_comment(text, prefix);
break;
case -1:
txt_uncomment(text);
txt_uncomment(text, prefix);
break;
default:
if (txt_uncomment(text) == false) {
txt_comment(text);
if (txt_uncomment(text, prefix) == false) {
txt_comment(text, prefix);
}
break;
}

View File

@ -72,6 +72,7 @@ void ED_draw_object_facemap(Depsgraph *depsgraph,
const float(*positions)[3] = BKE_mesh_vert_positions(me);
const blender::Span<MPoly> polys = me->polys();
const blender::Span<MLoop> loops = me->loops();
const blender::Span<MLoopTri> looptris = me->looptris();
facemap_data = static_cast<const int *>(CustomData_get_layer(&me->pdata, CD_FACEMAP));
@ -90,46 +91,23 @@ void ED_draw_object_facemap(Depsgraph *depsgraph,
GPUVertBufRaw pos_step;
GPU_vertbuf_attr_get_raw_data(vbo_pos, pos_id, &pos_step);
if (BKE_mesh_runtime_looptri_ensure(me)) {
const MLoopTri *mlt = BKE_mesh_runtime_looptri_ensure(me);
for (const int i : polys.index_range()) {
const MPoly &poly = polys[i];
if (facemap_data[i] == facemap) {
for (int j = 2; j < poly.totloop; j++) {
copy_v3_v3(static_cast<float *>(GPU_vertbuf_raw_step(&pos_step)),
positions[loops[mlt->tri[0]].v]);
copy_v3_v3(static_cast<float *>(GPU_vertbuf_raw_step(&pos_step)),
positions[loops[mlt->tri[1]].v]);
copy_v3_v3(static_cast<float *>(GPU_vertbuf_raw_step(&pos_step)),
positions[loops[mlt->tri[2]].v]);
vbo_len_used += 3;
mlt++;
}
}
else {
mlt += poly.totloop - 2;
int tri_index = 0;
for (const int i : polys.index_range()) {
const MPoly &poly = polys[i];
if (facemap_data[i] == facemap) {
for (int j = 2; j < poly.totloop; j++) {
copy_v3_v3(static_cast<float *>(GPU_vertbuf_raw_step(&pos_step)),
positions[loops[looptris[tri_index].tri[0]].v]);
copy_v3_v3(static_cast<float *>(GPU_vertbuf_raw_step(&pos_step)),
positions[loops[looptris[tri_index].tri[1]].v]);
copy_v3_v3(static_cast<float *>(GPU_vertbuf_raw_step(&pos_step)),
positions[loops[looptris[tri_index].tri[2]].v]);
vbo_len_used += 3;
tri_index++;
}
}
}
else {
/* No tessellation data, fan-fill. */
for (const int i : polys.index_range()) {
const MPoly &poly = polys[i];
if (facemap_data[i] == facemap) {
const MLoop *ml_start = &loops[poly.loopstart];
const MLoop *ml_a = ml_start + 1;
const MLoop *ml_b = ml_start + 2;
for (int j = 2; j < poly.totloop; j++) {
copy_v3_v3(static_cast<float *>(GPU_vertbuf_raw_step(&pos_step)),
positions[ml_start->v]);
copy_v3_v3(static_cast<float *>(GPU_vertbuf_raw_step(&pos_step)), positions[ml_a->v]);
copy_v3_v3(static_cast<float *>(GPU_vertbuf_raw_step(&pos_step)), positions[ml_b->v]);
vbo_len_used += 3;
ml_a++;
ml_b++;
}
}
else {
tri_index += poly.totloop - 2;
}
}

View File

@ -55,6 +55,8 @@ set(SRC
transform_generics.c
transform_gizmo_2d.c
transform_gizmo_3d.cc
transform_gizmo_3d_cage.cc
transform_gizmo_3d_shear.cc
transform_gizmo_extrude_3d.c
transform_input.c
transform_mode.c
@ -99,6 +101,7 @@ set(SRC
transform_convert.h
transform_data.h
transform_draw_cursors.h
transform_gizmo.h
transform_mode.h
transform_orientations.h
transform_snap.h

View File

@ -52,6 +52,7 @@
#include "transform_constraints.h"
#include "transform_convert.h"
#include "transform_draw_cursors.h"
#include "transform_gizmo.h"
#include "transform_mode.h"
#include "transform_orientations.h"
#include "transform_snap.h"

View File

@ -728,40 +728,6 @@ void transform_final_value_get(const TransInfo *t, float *value, int value_num);
/** \} */
/* -------------------------------------------------------------------- */
/** \name Gizmo
* \{ */
/* transform_gizmo.c */
#define GIZMO_AXIS_LINE_WIDTH 2.0f
bool gimbal_axis_pose(struct Object *ob, const struct bPoseChannel *pchan, float gmat[3][3]);
bool gimbal_axis_object(struct Object *ob, float gmat[3][3]);
/**
* Set the #T_NO_GIZMO flag.
*
* \note This maintains the conventional behavior of not displaying the gizmo if the operator has
* been triggered by shortcuts.
*/
void transform_gizmo_3d_model_from_constraint_and_mode_init(TransInfo *t);
/**
* Change the gizmo and its orientation to match the transform state.
*
* \note This used while the modal operator is running so changes to the constraint or mode show
* the gizmo associated with that state, as if it had been the initial gizmo dragged.
*/
void transform_gizmo_3d_model_from_constraint_and_mode_set(TransInfo *t);
/**
* Restores the non-modal state of the gizmo.
*/
void transform_gizmo_3d_model_from_constraint_and_mode_restore(TransInfo *t);
/** \} */
/* -------------------------------------------------------------------- */
/** \name TransData Creation and General Handling
* \{ */

View File

@ -34,6 +34,7 @@
#include "UI_resources.h"
#include "transform.h"
#include "transform_gizmo.h"
#include "transform_orientations.h"
#include "transform_snap.h"

View File

@ -35,6 +35,7 @@
#include "RNA_prototypes.h"
#include "transform.h"
#include "transform_orientations.h"
#include "transform_snap.h"
/* Own include. */

View File

@ -49,6 +49,7 @@
#include "transform.h"
#include "transform_convert.h"
#include "transform_gizmo.h"
#include "transform_mode.h"
#include "transform_orientations.h"
#include "transform_snap.h"

View File

@ -0,0 +1,78 @@
/* SPDX-License-Identifier: GPL-2.0-or-later
* Copyright 2001-2002 NaN Holding BV. All rights reserved. */
/** \file
* \ingroup edtransform
*/
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
/** \} */
/* -------------------------------------------------------------------- */
/** \name Types/
* \{ */
struct ARegion;
struct bContext;
struct bScreen;
struct RegionView3D;
struct Scene;
struct ScrArea;
struct TransformBounds;
struct TransInfo;
struct wmGizmoGroup;
struct wmGizmoGroupType;
struct wmMsgBus;
/** \} */
/* -------------------------------------------------------------------- */
/** \name Gizmo
* \{ */
/* transform_gizmo_3d.c */
#define GIZMO_AXIS_LINE_WIDTH 2.0f
void gizmo_prepare_mat(const struct bContext *C,
struct RegionView3D *rv3d,
const struct TransformBounds *tbounds);
void gizmo_xform_message_subscribe(struct wmGizmoGroup *gzgroup,
struct wmMsgBus *mbus,
struct Scene *scene,
struct bScreen *screen,
struct ScrArea *area,
struct ARegion *region,
void (*type_fn)(struct wmGizmoGroupType *));
/**
* Set the #T_NO_GIZMO flag.
*
* \note This maintains the conventional behavior of not displaying the gizmo if the operator has
* been triggered by shortcuts.
*/
void transform_gizmo_3d_model_from_constraint_and_mode_init(TransInfo *t);
/**
* Change the gizmo and its orientation to match the transform state.
*
* \note This used while the modal operator is running so changes to the constraint or mode show
* the gizmo associated with that state, as if it had been the initial gizmo dragged.
*/
void transform_gizmo_3d_model_from_constraint_and_mode_set(TransInfo *t);
/**
* Restores the non-modal state of the gizmo.
*/
void transform_gizmo_3d_model_from_constraint_and_mode_restore(TransInfo *t);
/** \} */
#ifdef __cplusplus
}
#endif

View File

@ -42,7 +42,8 @@
#include "SEQ_time.h"
#include "SEQ_transform.h"
#include "transform.h" /* own include */
#include "transform.h"
#include "transform_gizmo.h"
/* -------------------------------------------------------------------- */
/** \name Shared Callback's

View File

@ -8,31 +8,15 @@
* Used for 3D View
*/
#include <cfloat>
#include <cmath>
#include <cstdlib>
#include <cstring>
#include "DNA_armature_types.h"
#include "DNA_curve_types.h"
#include "DNA_gpencil_types.h"
#include "DNA_lattice_types.h"
#include "DNA_meta_types.h"
#include "DNA_scene_types.h"
#include "DNA_screen_types.h"
#include "DNA_view3d_types.h"
#include "BLI_array_utils.h"
#include "BLI_listbase.h"
#include "BLI_math.h"
#include "BLI_utildefines.h"
#include "BKE_action.h"
#include "BKE_armature.h"
#include "BKE_context.h"
#include "BKE_crazyspace.hh"
#include "BKE_curve.h"
#include "BKE_curves.hh"
#include "BKE_editmesh.h"
#include "BKE_global.h"
#include "BKE_gpencil.h"
@ -41,12 +25,10 @@
#include "BKE_paint.h"
#include "BKE_pointcache.h"
#include "BKE_scene.h"
#include "DEG_depsgraph.h"
#include "BLI_array_utils.h"
#include "WM_api.h"
#include "WM_message.h"
#include "WM_types.h"
#include "ED_armature.h"
#include "ED_curves.h"
@ -56,9 +38,7 @@
#include "ED_object.h"
#include "ED_particle.h"
#include "ED_screen.h"
#include "ED_view3d.h"
#include "UI_interface.h"
#include "UI_resources.h"
#include "RNA_access.h"
@ -67,12 +47,9 @@
/* local module include */
#include "transform.h"
#include "transform_convert.h"
#include "transform_gizmo.h"
#include "transform_snap.h"
#include "MEM_guardedalloc.h"
#include "GPU_state.h"
static wmGizmoGroupType *g_GGT_xform_gizmo = nullptr;
static wmGizmoGroupType *g_GGT_xform_gizmo_context = nullptr;
@ -527,101 +504,6 @@ static void protectflag_to_drawflags_ebone(RegionView3D *rv3d, const EditBone *e
}
}
/* could move into BLI_math however this is only useful for display/editing purposes */
static void axis_angle_to_gimbal_axis(float gmat[3][3], const float axis[3], const float angle)
{
/* X/Y are arbitrary axes, most importantly Z is the axis of rotation. */
float cross_vec[3];
float quat[4];
/* this is an un-scientific method to get a vector to cross with
* XYZ intentionally YZX */
cross_vec[0] = axis[1];
cross_vec[1] = axis[2];
cross_vec[2] = axis[0];
/* X-axis */
cross_v3_v3v3(gmat[0], cross_vec, axis);
normalize_v3(gmat[0]);
axis_angle_to_quat(quat, axis, angle);
mul_qt_v3(quat, gmat[0]);
/* Y-axis */
axis_angle_to_quat(quat, axis, M_PI_2);
copy_v3_v3(gmat[1], gmat[0]);
mul_qt_v3(quat, gmat[1]);
/* Z-axis */
copy_v3_v3(gmat[2], axis);
normalize_m3(gmat);
}
static bool test_rotmode_euler(short rotmode)
{
return ELEM(rotmode, ROT_MODE_AXISANGLE, ROT_MODE_QUAT) ? 0 : 1;
}
bool gimbal_axis_pose(Object *ob, const bPoseChannel *pchan, float gmat[3][3])
{
float mat[3][3], tmat[3][3], obmat[3][3];
if (test_rotmode_euler(pchan->rotmode)) {
eulO_to_gimbal_axis(mat, pchan->eul, pchan->rotmode);
}
else if (pchan->rotmode == ROT_MODE_AXISANGLE) {
axis_angle_to_gimbal_axis(mat, pchan->rotAxis, pchan->rotAngle);
}
else { /* quat */
return 0;
}
/* apply bone transformation */
mul_m3_m3m3(tmat, pchan->bone->bone_mat, mat);
if (pchan->parent) {
float parent_mat[3][3];
copy_m3_m4(parent_mat,
(pchan->bone->flag & BONE_HINGE) ? pchan->parent->bone->arm_mat :
pchan->parent->pose_mat);
mul_m3_m3m3(mat, parent_mat, tmat);
/* needed if object transformation isn't identity */
copy_m3_m4(obmat, ob->object_to_world);
mul_m3_m3m3(gmat, obmat, mat);
}
else {
/* needed if object transformation isn't identity */
copy_m3_m4(obmat, ob->object_to_world);
mul_m3_m3m3(gmat, obmat, tmat);
}
normalize_m3(gmat);
return true;
}
bool gimbal_axis_object(Object *ob, float gmat[3][3])
{
if (test_rotmode_euler(ob->rotmode)) {
eulO_to_gimbal_axis(gmat, ob->rot, ob->rotmode);
}
else if (ob->rotmode == ROT_MODE_AXISANGLE) {
axis_angle_to_gimbal_axis(gmat, ob->rotAxis, ob->rotAngle);
}
else { /* quat */
return 0;
}
if (ob->parent) {
float parent_mat[3][3];
copy_m3_m4(parent_mat, ob->parent->object_to_world);
normalize_m3(parent_mat);
mul_m3_m3m3(gmat, parent_mat, gmat);
}
return 1;
}
int ED_transform_calc_gizmo_stats(const bContext *C,
const TransformCalcParams *params,
TransformBounds *tbounds)
@ -1117,9 +999,7 @@ static void gizmo_get_idot(const RegionView3D *rv3d, float r_idot[3])
}
}
static void gizmo_prepare_mat(const bContext *C,
RegionView3D *rv3d,
const TransformBounds *tbounds)
void gizmo_prepare_mat(const bContext *C, RegionView3D *rv3d, const TransformBounds *tbounds)
{
Scene *scene = CTX_data_scene(C);
ViewLayer *view_layer = CTX_data_view_layer(C);
@ -1197,13 +1077,13 @@ static void gizmo_line_range(const int twtype, const short axis_type, float *r_s
}
}
static void gizmo_xform_message_subscribe(wmGizmoGroup *gzgroup,
wmMsgBus *mbus,
Scene *scene,
bScreen *screen,
ScrArea *area,
ARegion *region,
void (*type_fn)(wmGizmoGroupType *))
void gizmo_xform_message_subscribe(wmGizmoGroup *gzgroup,
wmMsgBus *mbus,
Scene *scene,
bScreen *screen,
ScrArea *area,
ARegion *region,
void (*type_fn)(wmGizmoGroupType *))
{
/* Subscribe to view properties */
wmMsgSubscribeValue msg_sub_value_gz_tag_refresh{};
@ -2337,437 +2217,6 @@ void VIEW3D_GGT_xform_gizmo_context(wmGizmoGroupType *gzgt)
/** \} */
/* -------------------------------------------------------------------- */
/** \name Scale Cage Gizmo
* \{ */
struct XFormCageWidgetGroup {
wmGizmo *gizmo;
/* Only for view orientation. */
struct {
float viewinv_m3[3][3];
} prev;
};
static bool WIDGETGROUP_xform_cage_poll(const bContext *C, wmGizmoGroupType *gzgt)
{
if (!ED_gizmo_poll_or_unlink_delayed_from_tool(C, gzgt)) {
return false;
}
View3D *v3d = CTX_wm_view3d(C);
if (v3d->gizmo_flag & (V3D_GIZMO_HIDE | V3D_GIZMO_HIDE_TOOL)) {
return false;
}
if (G.moving & (G_TRANSFORM_OBJ | G_TRANSFORM_EDIT)) {
return false;
}
return true;
}
static void WIDGETGROUP_xform_cage_setup(const bContext * /*C*/, wmGizmoGroup *gzgroup)
{
XFormCageWidgetGroup *xgzgroup = static_cast<XFormCageWidgetGroup *>(
MEM_mallocN(sizeof(XFormCageWidgetGroup), __func__));
const wmGizmoType *gzt_cage = WM_gizmotype_find("GIZMO_GT_cage_3d", true);
xgzgroup->gizmo = WM_gizmo_new_ptr(gzt_cage, gzgroup, nullptr);
wmGizmo *gz = xgzgroup->gizmo;
RNA_enum_set(
gz->ptr, "transform", ED_GIZMO_CAGE_XFORM_FLAG_SCALE | ED_GIZMO_CAGE_XFORM_FLAG_TRANSLATE);
gz->color[0] = 1;
gz->color_hi[0] = 1;
gzgroup->customdata = xgzgroup;
{
wmOperatorType *ot_resize = WM_operatortype_find("TRANSFORM_OT_resize", true);
PointerRNA *ptr;
/* assign operator */
PropertyRNA *prop_release_confirm = nullptr;
PropertyRNA *prop_constraint_axis = nullptr;
int i = ED_GIZMO_CAGE3D_PART_SCALE_MIN_X_MIN_Y_MIN_Z;
for (int x = 0; x < 3; x++) {
for (int y = 0; y < 3; y++) {
for (int z = 0; z < 3; z++) {
const bool constraint[3] = {x != 1, y != 1, z != 1};
ptr = WM_gizmo_operator_set(gz, i, ot_resize, nullptr);
if (prop_release_confirm == nullptr) {
prop_release_confirm = RNA_struct_find_property(ptr, "release_confirm");
prop_constraint_axis = RNA_struct_find_property(ptr, "constraint_axis");
}
RNA_property_boolean_set(ptr, prop_release_confirm, true);
RNA_property_boolean_set_array(ptr, prop_constraint_axis, constraint);
i++;
}
}
}
}
}
static void WIDGETGROUP_xform_cage_refresh(const bContext *C, wmGizmoGroup *gzgroup)
{
ARegion *region = CTX_wm_region(C);
RegionView3D *rv3d = static_cast<RegionView3D *>(region->regiondata);
Scene *scene = CTX_data_scene(C);
XFormCageWidgetGroup *xgzgroup = static_cast<XFormCageWidgetGroup *>(gzgroup->customdata);
wmGizmo *gz = xgzgroup->gizmo;
TransformBounds tbounds;
const int orient_index = BKE_scene_orientation_get_index_from_flag(scene, SCE_ORIENT_SCALE);
TransformCalcParams calc_params{};
calc_params.use_local_axis = true;
calc_params.orientation_index = orient_index + 1;
if ((ED_transform_calc_gizmo_stats(C, &calc_params, &tbounds) == 0) ||
equals_v3v3(rv3d->tw_axis_min, rv3d->tw_axis_max)) {
WM_gizmo_set_flag(gz, WM_GIZMO_HIDDEN, true);
}
else {
if (tbounds.use_matrix_space) {
copy_m4_m4(gz->matrix_space, tbounds.matrix_space);
}
else {
unit_m4(gz->matrix_space);
}
gizmo_prepare_mat(C, rv3d, &tbounds);
WM_gizmo_set_flag(gz, WM_GIZMO_HIDDEN, false);
WM_gizmo_set_flag(gz, WM_GIZMO_MOVE_CURSOR, true);
float dims[3];
sub_v3_v3v3(dims, rv3d->tw_axis_max, rv3d->tw_axis_min);
RNA_float_set_array(gz->ptr, "dimensions", dims);
mul_v3_fl(dims, 0.5f);
copy_m4_m3(gz->matrix_offset, rv3d->tw_axis_matrix);
mid_v3_v3v3(gz->matrix_offset[3], rv3d->tw_axis_max, rv3d->tw_axis_min);
mul_m3_v3(rv3d->tw_axis_matrix, gz->matrix_offset[3]);
float matrix_offset_global[4][4];
mul_m4_m4m4(matrix_offset_global, gz->matrix_space, gz->matrix_offset);
PropertyRNA *prop_center_override = nullptr;
float center[3];
float center_global[3];
int i = ED_GIZMO_CAGE3D_PART_SCALE_MIN_X_MIN_Y_MIN_Z;
for (int x = 0; x < 3; x++) {
center[0] = float(1 - x) * dims[0];
for (int y = 0; y < 3; y++) {
center[1] = float(1 - y) * dims[1];
for (int z = 0; z < 3; z++) {
center[2] = float(1 - z) * dims[2];
wmGizmoOpElem *gzop = WM_gizmo_operator_get(gz, i);
if (prop_center_override == nullptr) {
prop_center_override = RNA_struct_find_property(&gzop->ptr, "center_override");
}
mul_v3_m4v3(center_global, matrix_offset_global, center);
RNA_property_float_set_array(&gzop->ptr, prop_center_override, center_global);
i++;
}
}
}
}
/* Needed to test view orientation changes. */
copy_m3_m4(xgzgroup->prev.viewinv_m3, rv3d->viewinv);
}
static void WIDGETGROUP_xform_cage_message_subscribe(const bContext *C,
wmGizmoGroup *gzgroup,
wmMsgBus *mbus)
{
Scene *scene = CTX_data_scene(C);
bScreen *screen = CTX_wm_screen(C);
ScrArea *area = CTX_wm_area(C);
ARegion *region = CTX_wm_region(C);
gizmo_xform_message_subscribe(gzgroup, mbus, scene, screen, area, region, VIEW3D_GGT_xform_cage);
}
static void WIDGETGROUP_xform_cage_draw_prepare(const bContext *C, wmGizmoGroup *gzgroup)
{
XFormCageWidgetGroup *xgzgroup = static_cast<XFormCageWidgetGroup *>(gzgroup->customdata);
RegionView3D *rv3d = CTX_wm_region_view3d(C);
{
Scene *scene = CTX_data_scene(C);
const TransformOrientationSlot *orient_slot = BKE_scene_orientation_slot_get(scene,
SCE_ORIENT_SCALE);
switch (orient_slot->type) {
case V3D_ORIENT_VIEW: {
float viewinv_m3[3][3];
copy_m3_m4(viewinv_m3, rv3d->viewinv);
if (!equals_m3m3(viewinv_m3, xgzgroup->prev.viewinv_m3)) {
/* Take care calling refresh from draw_prepare,
* this should be OK because it's only adjusting the cage orientation. */
WIDGETGROUP_xform_cage_refresh(C, gzgroup);
}
break;
}
}
}
}
void VIEW3D_GGT_xform_cage(wmGizmoGroupType *gzgt)
{
gzgt->name = "Transform Cage";
gzgt->idname = "VIEW3D_GGT_xform_cage";
gzgt->flag |= WM_GIZMOGROUPTYPE_3D | WM_GIZMOGROUPTYPE_DRAW_MODAL_EXCLUDE |
WM_GIZMOGROUPTYPE_TOOL_FALLBACK_KEYMAP | WM_GIZMOGROUPTYPE_DELAY_REFRESH_FOR_TWEAK;
gzgt->gzmap_params.spaceid = SPACE_VIEW3D;
gzgt->gzmap_params.regionid = RGN_TYPE_WINDOW;
gzgt->poll = WIDGETGROUP_xform_cage_poll;
gzgt->setup = WIDGETGROUP_xform_cage_setup;
gzgt->setup_keymap = WM_gizmogroup_setup_keymap_generic_maybe_drag;
gzgt->refresh = WIDGETGROUP_xform_cage_refresh;
gzgt->message_subscribe = WIDGETGROUP_xform_cage_message_subscribe;
gzgt->draw_prepare = WIDGETGROUP_xform_cage_draw_prepare;
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Transform Shear Gizmo
* \{ */
struct XFormShearWidgetGroup {
wmGizmo *gizmo[3][2];
/** View aligned gizmos. */
wmGizmo *gizmo_view[4];
/* Only for view orientation. */
struct {
float viewinv_m3[3][3];
} prev;
};
static bool WIDGETGROUP_xform_shear_poll(const bContext *C, wmGizmoGroupType *gzgt)
{
if (!ED_gizmo_poll_or_unlink_delayed_from_tool(C, gzgt)) {
return false;
}
View3D *v3d = CTX_wm_view3d(C);
if (v3d->gizmo_flag & (V3D_GIZMO_HIDE | V3D_GIZMO_HIDE_TOOL)) {
return false;
}
return true;
}
static void WIDGETGROUP_xform_shear_setup(const bContext * /*C*/, wmGizmoGroup *gzgroup)
{
XFormShearWidgetGroup *xgzgroup = static_cast<XFormShearWidgetGroup *>(
MEM_mallocN(sizeof(XFormShearWidgetGroup), __func__));
const wmGizmoType *gzt_arrow = WM_gizmotype_find("GIZMO_GT_arrow_3d", true);
wmOperatorType *ot_shear = WM_operatortype_find("TRANSFORM_OT_shear", true);
float axis_color[3][3];
for (int i = 0; i < 3; i++) {
UI_GetThemeColor3fv(TH_AXIS_X + i, axis_color[i]);
}
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 2; j++) {
wmGizmo *gz = WM_gizmo_new_ptr(gzt_arrow, gzgroup, nullptr);
RNA_enum_set(gz->ptr, "draw_style", ED_GIZMO_ARROW_STYLE_BOX);
const int i_ortho_a = (i + j + 1) % 3;
const int i_ortho_b = (i + (1 - j) + 1) % 3;
interp_v3_v3v3(gz->color, axis_color[i_ortho_a], axis_color[i_ortho_b], 0.75f);
gz->color[3] = 0.5f;
PointerRNA *ptr = WM_gizmo_operator_set(gz, 0, ot_shear, nullptr);
RNA_boolean_set(ptr, "release_confirm", 1);
xgzgroup->gizmo[i][j] = gz;
}
}
for (int i = 0; i < 4; i++) {
wmGizmo *gz = WM_gizmo_new_ptr(gzt_arrow, gzgroup, nullptr);
RNA_enum_set(gz->ptr, "draw_style", ED_GIZMO_ARROW_STYLE_BOX);
RNA_enum_set(gz->ptr, "draw_options", 0); /* No stem. */
copy_v3_fl(gz->color, 1.0f);
gz->color[3] = 0.5f;
WM_gizmo_set_flag(gz, WM_GIZMO_DRAW_OFFSET_SCALE, true);
PointerRNA *ptr = WM_gizmo_operator_set(gz, 0, ot_shear, nullptr);
RNA_boolean_set(ptr, "release_confirm", 1);
xgzgroup->gizmo_view[i] = gz;
/* Unlike the other gizmos, this never changes so can be set on setup. */
wmGizmoOpElem *gzop = WM_gizmo_operator_get(gz, 0);
RNA_enum_set(&gzop->ptr, "orient_type", V3D_ORIENT_VIEW);
RNA_enum_set(&gzop->ptr, "orient_axis", 2);
RNA_enum_set(&gzop->ptr, "orient_axis_ortho", ((i % 2) ? 0 : 1));
}
gzgroup->customdata = xgzgroup;
}
static void WIDGETGROUP_xform_shear_refresh(const bContext *C, wmGizmoGroup *gzgroup)
{
Scene *scene = CTX_data_scene(C);
ARegion *region = CTX_wm_region(C);
RegionView3D *rv3d = static_cast<RegionView3D *>(region->regiondata);
XFormShearWidgetGroup *xgzgroup = static_cast<XFormShearWidgetGroup *>(gzgroup->customdata);
TransformBounds tbounds;
/* Needed to test view orientation changes. */
copy_m3_m4(xgzgroup->prev.viewinv_m3, rv3d->viewinv);
TransformOrientationSlot *orient_slot = BKE_scene_orientation_slot_get_from_flag(
scene, SCE_ORIENT_ROTATE);
const int orient_index = BKE_scene_orientation_slot_get_index(orient_slot);
TransformCalcParams calc_params{};
calc_params.use_local_axis = false;
calc_params.orientation_index = orient_index + 1;
if (ED_transform_calc_gizmo_stats(C, &calc_params, &tbounds) == 0) {
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 2; j++) {
wmGizmo *gz = xgzgroup->gizmo[i][j];
WM_gizmo_set_flag(gz, WM_GIZMO_HIDDEN, true);
}
}
for (int i = 0; i < 4; i++) {
wmGizmo *gz = xgzgroup->gizmo_view[i];
WM_gizmo_set_flag(gz, WM_GIZMO_HIDDEN, true);
}
}
else {
gizmo_prepare_mat(C, rv3d, &tbounds);
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 2; j++) {
wmGizmo *gz = xgzgroup->gizmo[i][j];
WM_gizmo_set_flag(gz, WM_GIZMO_HIDDEN, false);
WM_gizmo_set_flag(gz, WM_GIZMO_MOVE_CURSOR, true);
wmGizmoOpElem *gzop = WM_gizmo_operator_get(gz, 0);
const int i_ortho_a = (i + j + 1) % 3;
const int i_ortho_b = (i + (1 - j) + 1) % 3;
WM_gizmo_set_matrix_rotation_from_yz_axis(gz, rv3d->twmat[i_ortho_a], rv3d->twmat[i]);
WM_gizmo_set_matrix_location(gz, rv3d->twmat[3]);
RNA_float_set_array(&gzop->ptr, "orient_matrix", &tbounds.axis[0][0]);
RNA_enum_set(&gzop->ptr, "orient_type", orient_slot->type);
RNA_enum_set(&gzop->ptr, "orient_axis", i_ortho_b);
RNA_enum_set(&gzop->ptr, "orient_axis_ortho", i_ortho_a);
mul_v3_fl(gz->matrix_basis[0], 0.5f);
mul_v3_fl(gz->matrix_basis[1], 6.0f);
}
}
for (int i = 0; i < 4; i++) {
wmGizmo *gz = xgzgroup->gizmo_view[i];
WM_gizmo_set_flag(gz, WM_GIZMO_HIDDEN, false);
}
}
}
static void WIDGETGROUP_xform_shear_message_subscribe(const bContext *C,
wmGizmoGroup *gzgroup,
wmMsgBus *mbus)
{
Scene *scene = CTX_data_scene(C);
bScreen *screen = CTX_wm_screen(C);
ScrArea *area = CTX_wm_area(C);
ARegion *region = CTX_wm_region(C);
gizmo_xform_message_subscribe(
gzgroup, mbus, scene, screen, area, region, VIEW3D_GGT_xform_shear);
}
static void WIDGETGROUP_xform_shear_draw_prepare(const bContext *C, wmGizmoGroup *gzgroup)
{
XFormShearWidgetGroup *xgzgroup = static_cast<XFormShearWidgetGroup *>(gzgroup->customdata);
RegionView3D *rv3d = CTX_wm_region_view3d(C);
{
Scene *scene = CTX_data_scene(C);
/* Shear is like rotate, use the rotate setting. */
const TransformOrientationSlot *orient_slot = BKE_scene_orientation_slot_get(
scene, SCE_ORIENT_ROTATE);
switch (orient_slot->type) {
case V3D_ORIENT_VIEW: {
float viewinv_m3[3][3];
copy_m3_m4(viewinv_m3, rv3d->viewinv);
if (!equals_m3m3(viewinv_m3, xgzgroup->prev.viewinv_m3)) {
/* Take care calling refresh from draw_prepare,
* this should be OK because it's only adjusting the cage orientation. */
WIDGETGROUP_xform_shear_refresh(C, gzgroup);
}
break;
}
}
}
for (int i = 0; i < 4; i++) {
const float outer_thin = 0.3f;
const float outer_offset = 1.0f / 0.3f;
wmGizmo *gz = xgzgroup->gizmo_view[i];
WM_gizmo_set_matrix_rotation_from_yz_axis(
gz, rv3d->viewinv[(i + 1) % 2], rv3d->viewinv[i % 2]);
if (i >= 2) {
negate_v3(gz->matrix_basis[1]);
negate_v3(gz->matrix_basis[2]);
}
/* No need for depth with view aligned gizmos. */
mul_v3_fl(gz->matrix_basis[0], 0.0f);
mul_v3_fl(gz->matrix_basis[1], 20.0f + ((1.0f / outer_thin) * 1.8f));
mul_v3_fl(gz->matrix_basis[2], outer_thin);
WM_gizmo_set_matrix_location(gz, rv3d->twmat[3]);
gz->matrix_offset[3][2] = outer_offset;
}
/* Basic ordering for drawing only. */
{
LISTBASE_FOREACH (wmGizmo *, gz, &gzgroup->gizmos) {
/* Since we have two pairs of each axis,
* bias the values so gizmos that are orthogonal to the view get priority.
* This means we never default to shearing along
* the view axis in the case of an overlap. */
float axis_order[3], axis_bias[3];
copy_v3_v3(axis_order, gz->matrix_basis[2]);
copy_v3_v3(axis_bias, gz->matrix_basis[1]);
if (dot_v3v3(axis_bias, rv3d->viewinv[2]) < 0.0f) {
negate_v3(axis_bias);
}
madd_v3_v3fl(axis_order, axis_bias, 0.01f);
gz->temp.f = dot_v3v3(rv3d->viewinv[2], axis_order);
}
BLI_listbase_sort(&gzgroup->gizmos, WM_gizmo_cmp_temp_fl_reverse);
}
}
void VIEW3D_GGT_xform_shear(wmGizmoGroupType *gzgt)
{
gzgt->name = "Transform Shear";
gzgt->idname = "VIEW3D_GGT_xform_shear";
gzgt->flag |= WM_GIZMOGROUPTYPE_3D | WM_GIZMOGROUPTYPE_DRAW_MODAL_EXCLUDE |
WM_GIZMOGROUPTYPE_TOOL_FALLBACK_KEYMAP | WM_GIZMOGROUPTYPE_DELAY_REFRESH_FOR_TWEAK;
gzgt->gzmap_params.spaceid = SPACE_VIEW3D;
gzgt->gzmap_params.regionid = RGN_TYPE_WINDOW;
gzgt->poll = WIDGETGROUP_xform_shear_poll;
gzgt->setup = WIDGETGROUP_xform_shear_setup;
gzgt->setup_keymap = WM_gizmogroup_setup_keymap_generic_maybe_drag;
gzgt->refresh = WIDGETGROUP_xform_shear_refresh;
gzgt->message_subscribe = WIDGETGROUP_xform_shear_message_subscribe;
gzgt->draw_prepare = WIDGETGROUP_xform_shear_draw_prepare;
}
/** \} */
static wmGizmoGroup *gizmogroup_xform_find(TransInfo *t)
{
wmGizmo *gizmo_modal_current = WM_gizmomap_get_modal(t->region->gizmo_map);

View File

@ -0,0 +1,223 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup edtransform
*
* \name 3D Transform Gizmo
*
* Used for 3D View
*/
#include "BLI_math.h"
#include "BKE_context.h"
#include "BKE_global.h"
#include "BKE_scene.h"
#include "ED_gizmo_library.h"
#include "ED_gizmo_utils.h"
#include "ED_screen.h"
#include "WM_api.h"
#include "RNA_access.h"
/* local module include */
#include "transform.h"
#include "transform_gizmo.h"
/* -------------------------------------------------------------------- */
/** \name Scale Cage Gizmo
* \{ */
struct XFormCageWidgetGroup {
wmGizmo *gizmo;
/* Only for view orientation. */
struct {
float viewinv_m3[3][3];
} prev;
};
static bool WIDGETGROUP_xform_cage_poll(const bContext *C, wmGizmoGroupType *gzgt)
{
if (!ED_gizmo_poll_or_unlink_delayed_from_tool(C, gzgt)) {
return false;
}
View3D *v3d = CTX_wm_view3d(C);
if (v3d->gizmo_flag & (V3D_GIZMO_HIDE | V3D_GIZMO_HIDE_TOOL)) {
return false;
}
if (G.moving & (G_TRANSFORM_OBJ | G_TRANSFORM_EDIT)) {
return false;
}
return true;
}
static void WIDGETGROUP_xform_cage_setup(const bContext * /*C*/, wmGizmoGroup *gzgroup)
{
XFormCageWidgetGroup *xgzgroup = static_cast<XFormCageWidgetGroup *>(
MEM_mallocN(sizeof(XFormCageWidgetGroup), __func__));
const wmGizmoType *gzt_cage = WM_gizmotype_find("GIZMO_GT_cage_3d", true);
xgzgroup->gizmo = WM_gizmo_new_ptr(gzt_cage, gzgroup, nullptr);
wmGizmo *gz = xgzgroup->gizmo;
RNA_enum_set(
gz->ptr, "transform", ED_GIZMO_CAGE_XFORM_FLAG_SCALE | ED_GIZMO_CAGE_XFORM_FLAG_TRANSLATE);
gz->color[0] = 1;
gz->color_hi[0] = 1;
gzgroup->customdata = xgzgroup;
{
wmOperatorType *ot_resize = WM_operatortype_find("TRANSFORM_OT_resize", true);
PointerRNA *ptr;
/* assign operator */
PropertyRNA *prop_release_confirm = nullptr;
PropertyRNA *prop_constraint_axis = nullptr;
int i = ED_GIZMO_CAGE3D_PART_SCALE_MIN_X_MIN_Y_MIN_Z;
for (int x = 0; x < 3; x++) {
for (int y = 0; y < 3; y++) {
for (int z = 0; z < 3; z++) {
const bool constraint[3] = {x != 1, y != 1, z != 1};
ptr = WM_gizmo_operator_set(gz, i, ot_resize, nullptr);
if (prop_release_confirm == nullptr) {
prop_release_confirm = RNA_struct_find_property(ptr, "release_confirm");
prop_constraint_axis = RNA_struct_find_property(ptr, "constraint_axis");
}
RNA_property_boolean_set(ptr, prop_release_confirm, true);
RNA_property_boolean_set_array(ptr, prop_constraint_axis, constraint);
i++;
}
}
}
}
}
static void WIDGETGROUP_xform_cage_refresh(const bContext *C, wmGizmoGroup *gzgroup)
{
ARegion *region = CTX_wm_region(C);
RegionView3D *rv3d = static_cast<RegionView3D *>(region->regiondata);
Scene *scene = CTX_data_scene(C);
XFormCageWidgetGroup *xgzgroup = static_cast<XFormCageWidgetGroup *>(gzgroup->customdata);
wmGizmo *gz = xgzgroup->gizmo;
TransformBounds tbounds;
const int orient_index = BKE_scene_orientation_get_index_from_flag(scene, SCE_ORIENT_SCALE);
TransformCalcParams calc_params{};
calc_params.use_local_axis = true;
calc_params.orientation_index = orient_index + 1;
if ((ED_transform_calc_gizmo_stats(C, &calc_params, &tbounds) == 0) ||
equals_v3v3(rv3d->tw_axis_min, rv3d->tw_axis_max)) {
WM_gizmo_set_flag(gz, WM_GIZMO_HIDDEN, true);
}
else {
if (tbounds.use_matrix_space) {
copy_m4_m4(gz->matrix_space, tbounds.matrix_space);
}
else {
unit_m4(gz->matrix_space);
}
gizmo_prepare_mat(C, rv3d, &tbounds);
WM_gizmo_set_flag(gz, WM_GIZMO_HIDDEN, false);
WM_gizmo_set_flag(gz, WM_GIZMO_MOVE_CURSOR, true);
float dims[3];
sub_v3_v3v3(dims, rv3d->tw_axis_max, rv3d->tw_axis_min);
RNA_float_set_array(gz->ptr, "dimensions", dims);
mul_v3_fl(dims, 0.5f);
copy_m4_m3(gz->matrix_offset, rv3d->tw_axis_matrix);
mid_v3_v3v3(gz->matrix_offset[3], rv3d->tw_axis_max, rv3d->tw_axis_min);
mul_m3_v3(rv3d->tw_axis_matrix, gz->matrix_offset[3]);
float matrix_offset_global[4][4];
mul_m4_m4m4(matrix_offset_global, gz->matrix_space, gz->matrix_offset);
PropertyRNA *prop_center_override = nullptr;
float center[3];
float center_global[3];
int i = ED_GIZMO_CAGE3D_PART_SCALE_MIN_X_MIN_Y_MIN_Z;
for (int x = 0; x < 3; x++) {
center[0] = float(1 - x) * dims[0];
for (int y = 0; y < 3; y++) {
center[1] = float(1 - y) * dims[1];
for (int z = 0; z < 3; z++) {
center[2] = float(1 - z) * dims[2];
wmGizmoOpElem *gzop = WM_gizmo_operator_get(gz, i);
if (prop_center_override == nullptr) {
prop_center_override = RNA_struct_find_property(&gzop->ptr, "center_override");
}
mul_v3_m4v3(center_global, matrix_offset_global, center);
RNA_property_float_set_array(&gzop->ptr, prop_center_override, center_global);
i++;
}
}
}
}
/* Needed to test view orientation changes. */
copy_m3_m4(xgzgroup->prev.viewinv_m3, rv3d->viewinv);
}
static void WIDGETGROUP_xform_cage_message_subscribe(const bContext *C,
wmGizmoGroup *gzgroup,
wmMsgBus *mbus)
{
Scene *scene = CTX_data_scene(C);
bScreen *screen = CTX_wm_screen(C);
ScrArea *area = CTX_wm_area(C);
ARegion *region = CTX_wm_region(C);
gizmo_xform_message_subscribe(gzgroup, mbus, scene, screen, area, region, VIEW3D_GGT_xform_cage);
}
static void WIDGETGROUP_xform_cage_draw_prepare(const bContext *C, wmGizmoGroup *gzgroup)
{
XFormCageWidgetGroup *xgzgroup = static_cast<XFormCageWidgetGroup *>(gzgroup->customdata);
RegionView3D *rv3d = CTX_wm_region_view3d(C);
{
Scene *scene = CTX_data_scene(C);
const TransformOrientationSlot *orient_slot = BKE_scene_orientation_slot_get(scene,
SCE_ORIENT_SCALE);
switch (orient_slot->type) {
case V3D_ORIENT_VIEW: {
float viewinv_m3[3][3];
copy_m3_m4(viewinv_m3, rv3d->viewinv);
if (!equals_m3m3(viewinv_m3, xgzgroup->prev.viewinv_m3)) {
/* Take care calling refresh from draw_prepare,
* this should be OK because it's only adjusting the cage orientation. */
WIDGETGROUP_xform_cage_refresh(C, gzgroup);
}
break;
}
}
}
}
void VIEW3D_GGT_xform_cage(wmGizmoGroupType *gzgt)
{
gzgt->name = "Transform Cage";
gzgt->idname = "VIEW3D_GGT_xform_cage";
gzgt->flag |= WM_GIZMOGROUPTYPE_3D | WM_GIZMOGROUPTYPE_DRAW_MODAL_EXCLUDE |
WM_GIZMOGROUPTYPE_TOOL_FALLBACK_KEYMAP | WM_GIZMOGROUPTYPE_DELAY_REFRESH_FOR_TWEAK;
gzgt->gzmap_params.spaceid = SPACE_VIEW3D;
gzgt->gzmap_params.regionid = RGN_TYPE_WINDOW;
gzgt->poll = WIDGETGROUP_xform_cage_poll;
gzgt->setup = WIDGETGROUP_xform_cage_setup;
gzgt->setup_keymap = WM_gizmogroup_setup_keymap_generic_maybe_drag;
gzgt->refresh = WIDGETGROUP_xform_cage_refresh;
gzgt->message_subscribe = WIDGETGROUP_xform_cage_message_subscribe;
gzgt->draw_prepare = WIDGETGROUP_xform_cage_draw_prepare;
}
/** \} */

View File

@ -0,0 +1,261 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup edtransform
*
* \name 3D Transform Gizmo
*
* Used for 3D View
*/
#include "BLI_math.h"
#include "BKE_context.h"
#include "BKE_scene.h"
#include "ED_gizmo_library.h"
#include "ED_gizmo_utils.h"
#include "ED_screen.h"
#include "WM_api.h"
#include "UI_resources.h"
#include "RNA_access.h"
/* local module include */
#include "transform.h"
#include "transform_gizmo.h"
/* -------------------------------------------------------------------- */
/** \name Transform Shear Gizmo
* \{ */
struct XFormShearWidgetGroup {
wmGizmo *gizmo[3][2];
/** View aligned gizmos. */
wmGizmo *gizmo_view[4];
/* Only for view orientation. */
struct {
float viewinv_m3[3][3];
} prev;
};
static bool WIDGETGROUP_xform_shear_poll(const bContext *C, wmGizmoGroupType *gzgt)
{
if (!ED_gizmo_poll_or_unlink_delayed_from_tool(C, gzgt)) {
return false;
}
View3D *v3d = CTX_wm_view3d(C);
if (v3d->gizmo_flag & (V3D_GIZMO_HIDE | V3D_GIZMO_HIDE_TOOL)) {
return false;
}
return true;
}
static void WIDGETGROUP_xform_shear_setup(const bContext * /*C*/, wmGizmoGroup *gzgroup)
{
XFormShearWidgetGroup *xgzgroup = static_cast<XFormShearWidgetGroup *>(
MEM_mallocN(sizeof(XFormShearWidgetGroup), __func__));
const wmGizmoType *gzt_arrow = WM_gizmotype_find("GIZMO_GT_arrow_3d", true);
wmOperatorType *ot_shear = WM_operatortype_find("TRANSFORM_OT_shear", true);
float axis_color[3][3];
for (int i = 0; i < 3; i++) {
UI_GetThemeColor3fv(TH_AXIS_X + i, axis_color[i]);
}
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 2; j++) {
wmGizmo *gz = WM_gizmo_new_ptr(gzt_arrow, gzgroup, nullptr);
RNA_enum_set(gz->ptr, "draw_style", ED_GIZMO_ARROW_STYLE_BOX);
const int i_ortho_a = (i + j + 1) % 3;
const int i_ortho_b = (i + (1 - j) + 1) % 3;
interp_v3_v3v3(gz->color, axis_color[i_ortho_a], axis_color[i_ortho_b], 0.75f);
gz->color[3] = 0.5f;
PointerRNA *ptr = WM_gizmo_operator_set(gz, 0, ot_shear, nullptr);
RNA_boolean_set(ptr, "release_confirm", 1);
xgzgroup->gizmo[i][j] = gz;
}
}
for (int i = 0; i < 4; i++) {
wmGizmo *gz = WM_gizmo_new_ptr(gzt_arrow, gzgroup, nullptr);
RNA_enum_set(gz->ptr, "draw_style", ED_GIZMO_ARROW_STYLE_BOX);
RNA_enum_set(gz->ptr, "draw_options", 0); /* No stem. */
copy_v3_fl(gz->color, 1.0f);
gz->color[3] = 0.5f;
WM_gizmo_set_flag(gz, WM_GIZMO_DRAW_OFFSET_SCALE, true);
PointerRNA *ptr = WM_gizmo_operator_set(gz, 0, ot_shear, nullptr);
RNA_boolean_set(ptr, "release_confirm", 1);
xgzgroup->gizmo_view[i] = gz;
/* Unlike the other gizmos, this never changes so can be set on setup. */
wmGizmoOpElem *gzop = WM_gizmo_operator_get(gz, 0);
RNA_enum_set(&gzop->ptr, "orient_type", V3D_ORIENT_VIEW);
RNA_enum_set(&gzop->ptr, "orient_axis", 2);
RNA_enum_set(&gzop->ptr, "orient_axis_ortho", ((i % 2) ? 0 : 1));
}
gzgroup->customdata = xgzgroup;
}
static void WIDGETGROUP_xform_shear_refresh(const bContext *C, wmGizmoGroup *gzgroup)
{
Scene *scene = CTX_data_scene(C);
ARegion *region = CTX_wm_region(C);
RegionView3D *rv3d = static_cast<RegionView3D *>(region->regiondata);
XFormShearWidgetGroup *xgzgroup = static_cast<XFormShearWidgetGroup *>(gzgroup->customdata);
TransformBounds tbounds;
/* Needed to test view orientation changes. */
copy_m3_m4(xgzgroup->prev.viewinv_m3, rv3d->viewinv);
TransformOrientationSlot *orient_slot = BKE_scene_orientation_slot_get_from_flag(
scene, SCE_ORIENT_ROTATE);
const int orient_index = BKE_scene_orientation_slot_get_index(orient_slot);
TransformCalcParams calc_params{};
calc_params.use_local_axis = false;
calc_params.orientation_index = orient_index + 1;
if (ED_transform_calc_gizmo_stats(C, &calc_params, &tbounds) == 0) {
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 2; j++) {
wmGizmo *gz = xgzgroup->gizmo[i][j];
WM_gizmo_set_flag(gz, WM_GIZMO_HIDDEN, true);
}
}
for (int i = 0; i < 4; i++) {
wmGizmo *gz = xgzgroup->gizmo_view[i];
WM_gizmo_set_flag(gz, WM_GIZMO_HIDDEN, true);
}
}
else {
gizmo_prepare_mat(C, rv3d, &tbounds);
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 2; j++) {
wmGizmo *gz = xgzgroup->gizmo[i][j];
WM_gizmo_set_flag(gz, WM_GIZMO_HIDDEN, false);
WM_gizmo_set_flag(gz, WM_GIZMO_MOVE_CURSOR, true);
wmGizmoOpElem *gzop = WM_gizmo_operator_get(gz, 0);
const int i_ortho_a = (i + j + 1) % 3;
const int i_ortho_b = (i + (1 - j) + 1) % 3;
WM_gizmo_set_matrix_rotation_from_yz_axis(gz, rv3d->twmat[i_ortho_a], rv3d->twmat[i]);
WM_gizmo_set_matrix_location(gz, rv3d->twmat[3]);
RNA_float_set_array(&gzop->ptr, "orient_matrix", &tbounds.axis[0][0]);
RNA_enum_set(&gzop->ptr, "orient_type", orient_slot->type);
RNA_enum_set(&gzop->ptr, "orient_axis", i_ortho_b);
RNA_enum_set(&gzop->ptr, "orient_axis_ortho", i_ortho_a);
mul_v3_fl(gz->matrix_basis[0], 0.5f);
mul_v3_fl(gz->matrix_basis[1], 6.0f);
}
}
for (int i = 0; i < 4; i++) {
wmGizmo *gz = xgzgroup->gizmo_view[i];
WM_gizmo_set_flag(gz, WM_GIZMO_HIDDEN, false);
}
}
}
static void WIDGETGROUP_xform_shear_message_subscribe(const bContext *C,
wmGizmoGroup *gzgroup,
wmMsgBus *mbus)
{
Scene *scene = CTX_data_scene(C);
bScreen *screen = CTX_wm_screen(C);
ScrArea *area = CTX_wm_area(C);
ARegion *region = CTX_wm_region(C);
gizmo_xform_message_subscribe(
gzgroup, mbus, scene, screen, area, region, VIEW3D_GGT_xform_shear);
}
static void WIDGETGROUP_xform_shear_draw_prepare(const bContext *C, wmGizmoGroup *gzgroup)
{
XFormShearWidgetGroup *xgzgroup = static_cast<XFormShearWidgetGroup *>(gzgroup->customdata);
RegionView3D *rv3d = CTX_wm_region_view3d(C);
{
Scene *scene = CTX_data_scene(C);
/* Shear is like rotate, use the rotate setting. */
const TransformOrientationSlot *orient_slot = BKE_scene_orientation_slot_get(
scene, SCE_ORIENT_ROTATE);
switch (orient_slot->type) {
case V3D_ORIENT_VIEW: {
float viewinv_m3[3][3];
copy_m3_m4(viewinv_m3, rv3d->viewinv);
if (!equals_m3m3(viewinv_m3, xgzgroup->prev.viewinv_m3)) {
/* Take care calling refresh from draw_prepare,
* this should be OK because it's only adjusting the cage orientation. */
WIDGETGROUP_xform_shear_refresh(C, gzgroup);
}
break;
}
}
}
for (int i = 0; i < 4; i++) {
const float outer_thin = 0.3f;
const float outer_offset = 1.0f / 0.3f;
wmGizmo *gz = xgzgroup->gizmo_view[i];
WM_gizmo_set_matrix_rotation_from_yz_axis(
gz, rv3d->viewinv[(i + 1) % 2], rv3d->viewinv[i % 2]);
if (i >= 2) {
negate_v3(gz->matrix_basis[1]);
negate_v3(gz->matrix_basis[2]);
}
/* No need for depth with view aligned gizmos. */
mul_v3_fl(gz->matrix_basis[0], 0.0f);
mul_v3_fl(gz->matrix_basis[1], 20.0f + ((1.0f / outer_thin) * 1.8f));
mul_v3_fl(gz->matrix_basis[2], outer_thin);
WM_gizmo_set_matrix_location(gz, rv3d->twmat[3]);
gz->matrix_offset[3][2] = outer_offset;
}
/* Basic ordering for drawing only. */
{
LISTBASE_FOREACH (wmGizmo *, gz, &gzgroup->gizmos) {
/* Since we have two pairs of each axis,
* bias the values so gizmos that are orthogonal to the view get priority.
* This means we never default to shearing along
* the view axis in the case of an overlap. */
float axis_order[3], axis_bias[3];
copy_v3_v3(axis_order, gz->matrix_basis[2]);
copy_v3_v3(axis_bias, gz->matrix_basis[1]);
if (dot_v3v3(axis_bias, rv3d->viewinv[2]) < 0.0f) {
negate_v3(axis_bias);
}
madd_v3_v3fl(axis_order, axis_bias, 0.01f);
gz->temp.f = dot_v3v3(rv3d->viewinv[2], axis_order);
}
BLI_listbase_sort(&gzgroup->gizmos, WM_gizmo_cmp_temp_fl_reverse);
}
}
void VIEW3D_GGT_xform_shear(wmGizmoGroupType *gzgt)
{
gzgt->name = "Transform Shear";
gzgt->idname = "VIEW3D_GGT_xform_shear";
gzgt->flag |= WM_GIZMOGROUPTYPE_3D | WM_GIZMOGROUPTYPE_DRAW_MODAL_EXCLUDE |
WM_GIZMOGROUPTYPE_TOOL_FALLBACK_KEYMAP | WM_GIZMOGROUPTYPE_DELAY_REFRESH_FOR_TWEAK;
gzgt->gzmap_params.spaceid = SPACE_VIEW3D;
gzgt->gzmap_params.regionid = RGN_TYPE_WINDOW;
gzgt->poll = WIDGETGROUP_xform_shear_poll;
gzgt->setup = WIDGETGROUP_xform_shear_setup;
gzgt->setup_keymap = WM_gizmogroup_setup_keymap_generic_maybe_drag;
gzgt->refresh = WIDGETGROUP_xform_shear_refresh;
gzgt->message_subscribe = WIDGETGROUP_xform_shear_message_subscribe;
gzgt->draw_prepare = WIDGETGROUP_xform_shear_draw_prepare;
}
/** \} */

View File

@ -29,6 +29,7 @@
#include "transform.h"
#include "transform_convert.h"
#include "transform_gizmo.h"
#include "transform_orientations.h"
#include "transform_snap.h"

View File

@ -230,6 +230,101 @@ static TransformOrientation *createMeshSpace(bContext *C,
return addMatrixSpace(C, mat, name, overwrite);
}
static bool test_rotmode_euler(short rotmode)
{
return ELEM(rotmode, ROT_MODE_AXISANGLE, ROT_MODE_QUAT) ? 0 : 1;
}
/* could move into BLI_math however this is only useful for display/editing purposes */
static void axis_angle_to_gimbal_axis(float gmat[3][3], const float axis[3], const float angle)
{
/* X/Y are arbitrary axes, most importantly Z is the axis of rotation. */
float cross_vec[3];
float quat[4];
/* this is an un-scientific method to get a vector to cross with
* XYZ intentionally YZX */
cross_vec[0] = axis[1];
cross_vec[1] = axis[2];
cross_vec[2] = axis[0];
/* X-axis */
cross_v3_v3v3(gmat[0], cross_vec, axis);
normalize_v3(gmat[0]);
axis_angle_to_quat(quat, axis, angle);
mul_qt_v3(quat, gmat[0]);
/* Y-axis */
axis_angle_to_quat(quat, axis, M_PI_2);
copy_v3_v3(gmat[1], gmat[0]);
mul_qt_v3(quat, gmat[1]);
/* Z-axis */
copy_v3_v3(gmat[2], axis);
normalize_m3(gmat);
}
bool gimbal_axis_pose(Object *ob, const bPoseChannel *pchan, float gmat[3][3])
{
float mat[3][3], tmat[3][3], obmat[3][3];
if (test_rotmode_euler(pchan->rotmode)) {
eulO_to_gimbal_axis(mat, pchan->eul, pchan->rotmode);
}
else if (pchan->rotmode == ROT_MODE_AXISANGLE) {
axis_angle_to_gimbal_axis(mat, pchan->rotAxis, pchan->rotAngle);
}
else { /* quat */
return 0;
}
/* apply bone transformation */
mul_m3_m3m3(tmat, pchan->bone->bone_mat, mat);
if (pchan->parent) {
float parent_mat[3][3];
copy_m3_m4(parent_mat,
(pchan->bone->flag & BONE_HINGE) ? pchan->parent->bone->arm_mat :
pchan->parent->pose_mat);
mul_m3_m3m3(mat, parent_mat, tmat);
/* needed if object transformation isn't identity */
copy_m3_m4(obmat, ob->object_to_world);
mul_m3_m3m3(gmat, obmat, mat);
}
else {
/* needed if object transformation isn't identity */
copy_m3_m4(obmat, ob->object_to_world);
mul_m3_m3m3(gmat, obmat, tmat);
}
normalize_m3(gmat);
return true;
}
bool gimbal_axis_object(Object *ob, float gmat[3][3])
{
if (test_rotmode_euler(ob->rotmode)) {
eulO_to_gimbal_axis(gmat, ob->rot, ob->rotmode);
}
else if (ob->rotmode == ROT_MODE_AXISANGLE) {
axis_angle_to_gimbal_axis(gmat, ob->rotAxis, ob->rotAngle);
}
else { /* quat */
return 0;
}
if (ob->parent) {
float parent_mat[3][3];
copy_m3_m4(parent_mat, ob->parent->object_to_world);
normalize_m3(parent_mat);
mul_m3_m3m3(gmat, parent_mat, gmat);
}
return 1;
}
bool transform_orientations_create_from_axis(float mat[3][3],
const float x[3],
const float y[3],

View File

@ -9,8 +9,13 @@
#include "RE_engine.h"
struct bPoseChannel;
struct Object;
struct TransInfo;
bool gimbal_axis_pose(struct Object *ob, const struct bPoseChannel *pchan, float gmat[3][3]);
bool gimbal_axis_object(struct Object *ob, float gmat[3][3]);
/**
* Sets the matrix of the specified space orientation.
* If the matrix cannot be obtained, an orientation different from the one informed is returned.

View File

@ -1430,7 +1430,7 @@ struct Nearest2dUserData {
const float (*vert_normals)[3];
const MEdge *edge; /* only used for #BVHTreeFromMeshEdges */
const MLoop *loop;
const MLoopTri *looptri;
const MLoopTri *looptris;
};
};
@ -1481,7 +1481,7 @@ static void cb_mlooptri_edges_get(const int index, const Nearest2dUserData *data
{
const MEdge *medge = data->edge;
const MLoop *mloop = data->loop;
const MLoopTri *lt = &data->looptri[index];
const MLoopTri *lt = &data->looptris[index];
for (int j = 2, j_next = 0; j_next < 3; j = j_next++) {
const MEdge *ed = &medge[mloop[lt->tri[j]].e];
const uint tri_edge[2] = {mloop[lt->tri[j]].v, mloop[lt->tri[j_next]].v};
@ -1498,7 +1498,7 @@ static void cb_mlooptri_edges_get(const int index, const Nearest2dUserData *data
static void cb_mlooptri_verts_get(const int index, const Nearest2dUserData *data, int r_v_index[3])
{
const MLoop *loop = data->loop;
const MLoopTri *looptri = &data->looptri[index];
const MLoopTri *looptri = &data->looptris[index];
r_v_index[0] = loop[looptri->tri[0]].v;
r_v_index[1] = loop[looptri->tri[1]].v;
@ -1716,10 +1716,10 @@ static void nearest2d_data_init_mesh(const Mesh *mesh,
r_nearest2d->get_tri_edges_index = cb_mlooptri_edges_get;
r_nearest2d->vert_positions = BKE_mesh_vert_positions(mesh);
r_nearest2d->vert_normals = BKE_mesh_vertex_normals_ensure(mesh);
r_nearest2d->vert_normals = BKE_mesh_vert_normals_ensure(mesh);
r_nearest2d->edge = mesh->edges().data();
r_nearest2d->loop = mesh->loops().data();
r_nearest2d->looptri = BKE_mesh_runtime_looptri_ensure(mesh);
r_nearest2d->looptris = mesh->looptris().data();
r_nearest2d->is_persp = is_persp;
r_nearest2d->use_backface_culling = use_backface_culling;

View File

@ -31,6 +31,8 @@
#include "ED_uvedit.h" /* Own include. */
#include "GEO_uv_pack.hh"
#include "WM_api.h"
#include "WM_types.h"
@ -435,199 +437,6 @@ int bm_mesh_calc_uv_islands(const Scene *scene,
/** \} */
static float pack_islands_scale_margin(const blender::Vector<FaceIsland *> &island_vector,
BoxPack *box_array,
const float scale,
const float margin)
{
for (const int index : island_vector.index_range()) {
FaceIsland *island = island_vector[index];
BoxPack *box = &box_array[index];
box->index = index;
box->w = BLI_rctf_size_x(&island->bounds_rect) * scale + 2 * margin;
box->h = BLI_rctf_size_y(&island->bounds_rect) * scale + 2 * margin;
}
float max_u, max_v;
BLI_box_pack_2d(box_array, island_vector.size(), &max_u, &max_v);
return max_ff(max_u, max_v);
}
static float pack_islands_margin_fraction(const blender::Vector<FaceIsland *> &island_vector,
BoxPack *box_array,
const float margin_fraction)
{
/*
* Root finding using a combined search / modified-secant method.
* First, use a robust search procedure to bracket the root within a factor of 10.
* Then, use a modified-secant method to converge.
*
* This is a specialized solver using domain knowledge to accelerate convergence. */
float scale_low = 0.0f;
float value_low = 0.0f;
float scale_high = 0.0f;
float value_high = 0.0f;
float scale_last = 0.0f;
/* Scaling smaller than `min_scale_roundoff` is unlikely to fit and
* will destroy information in existing UVs. */
float min_scale_roundoff = 1e-5f;
/* Certain inputs might have poor convergence properties.
* Use `max_iteration` to prevent an infinite loop. */
int max_iteration = 25;
for (int iteration = 0; iteration < max_iteration; iteration++) {
float scale = 1.0f;
if (iteration == 0) {
BLI_assert(iteration == 0);
BLI_assert(scale == 1.0f);
BLI_assert(scale_low == 0.0f);
BLI_assert(scale_high == 0.0f);
}
else if (scale_low == 0.0f) {
BLI_assert(scale_high > 0.0f);
/* Search mode, shrink layout until we can find a scale that fits. */
scale = scale_high * 0.1f;
}
else if (scale_high == 0.0f) {
BLI_assert(scale_low > 0.0f);
/* Search mode, grow layout until we can find a scale that doesn't fit. */
scale = scale_low * 10.0f;
}
else {
/* Bracket mode, use modified secant method to find root. */
BLI_assert(scale_low > 0.0f);
BLI_assert(scale_high > 0.0f);
BLI_assert(value_low <= 0.0f);
BLI_assert(value_high >= 0.0f);
if (scale_high < scale_low * 1.0001f) {
/* Convergence. */
break;
}
/* Secant method for area. */
scale = (sqrtf(scale_low) * value_high - sqrtf(scale_high) * value_low) /
(value_high - value_low);
scale = scale * scale;
if (iteration & 1) {
/* Modified binary-search to improve robustness. */
scale = sqrtf(scale * sqrtf(scale_low * scale_high));
}
}
scale = max_ff(scale, min_scale_roundoff);
/* Evaluate our `f`. */
scale_last = scale;
float max_uv = pack_islands_scale_margin(
island_vector, box_array, scale_last, margin_fraction);
float value = sqrtf(max_uv) - 1.0f;
if (value <= 0.0f) {
scale_low = scale;
value_low = value;
}
else {
scale_high = scale;
value_high = value;
if (scale == min_scale_roundoff) {
/* Unable to pack without damaging UVs. */
scale_low = scale;
break;
}
}
}
const bool flush = true;
if (flush) {
/* Write back best pack as a side-effect. First get best pack. */
if (scale_last != scale_low) {
scale_last = scale_low;
float max_uv = pack_islands_scale_margin(
island_vector, box_array, scale_last, margin_fraction);
UNUSED_VARS(max_uv);
/* TODO (?): `if (max_uv < 1.0f) { scale_last /= max_uv; }` */
}
/* Then expand FaceIslands by the correct amount. */
for (const int index : island_vector.index_range()) {
BoxPack *box = &box_array[index];
box->x /= scale_last;
box->y /= scale_last;
FaceIsland *island = island_vector[index];
BLI_rctf_pad(
&island->bounds_rect, margin_fraction / scale_last, margin_fraction / scale_last);
}
}
return scale_last;
}
static float calc_margin_from_aabb_length_sum(const blender::Vector<FaceIsland *> &island_vector,
const struct UVPackIsland_Params &params)
{
/* Logic matches behavior from #GEO_uv_parametrizer_pack.
* Attempt to give predictable results not dependent on current UV scale by using
* `aabb_length_sum` (was "`area`") to multiply the margin by the length (was "area"). */
double aabb_length_sum = 0.0f;
for (FaceIsland *island : island_vector) {
float w = BLI_rctf_size_x(&island->bounds_rect);
float h = BLI_rctf_size_y(&island->bounds_rect);
aabb_length_sum += sqrtf(w * h);
}
return params.margin * aabb_length_sum * 0.1f;
}
static BoxPack *pack_islands_params(const blender::Vector<FaceIsland *> &island_vector,
const struct UVPackIsland_Params &params,
float r_scale[2])
{
BoxPack *box_array = static_cast<BoxPack *>(
MEM_mallocN(sizeof(*box_array) * island_vector.size(), __func__));
if (params.margin == 0.0f) {
/* Special case for zero margin. Margin_method is ignored as all formulas give same result. */
const float max_uv = pack_islands_scale_margin(island_vector, box_array, 1.0f, 0.0f);
r_scale[0] = 1.0f / max_uv;
r_scale[1] = r_scale[0];
return box_array;
}
if (params.margin_method == ED_UVPACK_MARGIN_FRACTION) {
/* Uses a line search on scale. ~10x slower than other method. */
const float scale = pack_islands_margin_fraction(island_vector, box_array, params.margin);
r_scale[0] = scale;
r_scale[1] = scale;
/* pack_islands_margin_fraction will pad FaceIslands, return early. */
return box_array;
}
float margin = params.margin;
switch (params.margin_method) {
case ED_UVPACK_MARGIN_ADD: /* Default for Blender 2.8 and earlier. */
break; /* Nothing to do. */
case ED_UVPACK_MARGIN_SCALED: /* Default for Blender 3.3 and later. */
margin = calc_margin_from_aabb_length_sum(island_vector, params);
break;
case ED_UVPACK_MARGIN_FRACTION: /* Added as an option in Blender 3.4. */
BLI_assert_unreachable(); /* Handled above. */
break;
default:
BLI_assert_unreachable();
}
const float max_uv = pack_islands_scale_margin(island_vector, box_array, 1.0f, margin);
r_scale[0] = 1.0f / max_uv;
r_scale[1] = r_scale[0];
for (int index = 0; index < island_vector.size(); index++) {
FaceIsland *island = island_vector[index];
BLI_rctf_pad(&island->bounds_rect, margin, margin);
}
return box_array;
}
static bool island_has_pins(const Scene *scene,
FaceIsland *island,
const UVPackIsland_Params *params)
@ -664,8 +473,8 @@ void ED_uvedit_pack_islands_multi(const Scene *scene,
Object **objects,
const uint objects_len,
BMesh **bmesh_override,
const struct UVMapUDIM_Params *closest_udim,
const struct UVPackIsland_Params *params)
const UVMapUDIM_Params *closest_udim,
const UVPackIsland_Params *params)
{
blender::Vector<FaceIsland *> island_vector;
@ -751,7 +560,14 @@ void ED_uvedit_pack_islands_multi(const Scene *scene,
}
float scale[2] = {1.0f, 1.0f};
BoxPack *box_array = pack_islands_params(island_vector, *params, scale);
blender::Vector<blender::geometry::PackIsland *> pack_island_vector;
for (int i = 0; i < island_vector.size(); i++) {
FaceIsland *face_island = island_vector[i];
blender::geometry::PackIsland *pack_island = new blender::geometry::PackIsland();
pack_island->bounds_rect = face_island->bounds_rect;
pack_island_vector.append(pack_island);
}
BoxPack *box_array = pack_islands(pack_island_vector, *params, scale);
float base_offset[2] = {0.0f, 0.0f};
copy_v2_v2(base_offset, params->udim_base_offset);
@ -818,6 +634,12 @@ void ED_uvedit_pack_islands_multi(const Scene *scene,
MEM_freeN(island);
}
for (int i = 0; i < pack_island_vector.size(); i++) {
blender::geometry::PackIsland *pack_island = pack_island_vector[i];
pack_island_vector[i] = nullptr;
delete pack_island;
}
MEM_freeN(box_array);
}

View File

@ -47,6 +47,7 @@
#include "DEG_depsgraph.h"
#include "GEO_uv_pack.hh"
#include "GEO_uv_parametrizer.h"
#include "PIL_time.h"

Some files were not shown because too many files have changed in this diff Show More