BMesh: avoid incorrect/invalid matrix calculation
- `BKE_object_scale_to_mat3` was used to get the worldspace scale, without taking constraints, parenting etc into account. - Don't pass object's into BMesh API, (prefer matrices instead). - Avoid matrix invert for each edge-angle calculation. - Avoid 2x matrix multiplies when looping over edge pairs.
This commit is contained in:
parent
dc21ef7b86
commit
0feeea1bd5
|
@ -30,7 +30,6 @@
|
|||
|
||||
#include "DNA_listBase.h"
|
||||
#include "DNA_modifier_types.h"
|
||||
#include "DNA_object_types.h"
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
|
@ -243,23 +242,21 @@ float BM_face_calc_area(const BMFace *f)
|
|||
/**
|
||||
* Get the area of the face in world space.
|
||||
*/
|
||||
float BM_face_calc_area_worldspace(Object *ob, const BMFace *f)
|
||||
float BM_face_calc_area_with_mat3(const BMFace *f, const float mat3[3][3])
|
||||
{
|
||||
/* inline 'area_poly_v3' logic, avoid creating a temp array */
|
||||
const BMLoop *l_iter, *l_first;
|
||||
float co[3];
|
||||
float n[3];
|
||||
|
||||
zero_v3(n);
|
||||
l_iter = l_first = BM_FACE_FIRST_LOOP(f);
|
||||
float rsmat[3][3];
|
||||
copy_m3_m4(rsmat, ob->obmat);
|
||||
mul_v3_m3v3(co, mat3, l_iter->v->co);
|
||||
do {
|
||||
float co[3], co_next[3];
|
||||
copy_v3_v3(co, l_iter->v->co);
|
||||
copy_v3_v3(co_next, l_iter->next->v->co);
|
||||
mul_m3_v3(rsmat, co);
|
||||
mul_m3_v3(rsmat, co_next);
|
||||
float co_next[3];
|
||||
mul_v3_m3v3(co_next, mat3, l_iter->next->v->co);
|
||||
add_newell_cross_v3_v3v3(n, co, co_next);
|
||||
copy_v3_v3(co, co_next);
|
||||
} while ((l_iter = l_iter->next) != l_first);
|
||||
return len_v3(n) * 0.5f;
|
||||
}
|
||||
|
@ -283,21 +280,19 @@ float BM_face_calc_perimeter(const BMFace *f)
|
|||
/**
|
||||
* Calculate the perimeter of a ngon in world space.
|
||||
*/
|
||||
float BM_face_calc_perimeter_worldspace(Object *ob, const BMFace *f)
|
||||
float BM_face_calc_perimeter_with_mat3(const BMFace *f, const float mat3[3][3])
|
||||
{
|
||||
const BMLoop *l_iter, *l_first;
|
||||
float co[3];
|
||||
float perimeter = 0.0f;
|
||||
|
||||
l_iter = l_first = BM_FACE_FIRST_LOOP(f);
|
||||
float rsmat[3][3];
|
||||
copy_m3_m4(rsmat, ob->obmat);
|
||||
mul_v3_m3v3(co, mat3, l_iter->v->co);
|
||||
do {
|
||||
float co[3], co_next[3];
|
||||
copy_v3_v3(co, l_iter->v->co);
|
||||
copy_v3_v3(co_next, l_iter->next->v->co);
|
||||
mul_m3_v3(rsmat, co);
|
||||
mul_m3_v3(rsmat, co_next);
|
||||
float co_next[3];
|
||||
mul_v3_m3v3(co_next, mat3, l_iter->next->v->co);
|
||||
perimeter += len_v3v3(co, co_next);
|
||||
copy_v3_v3(co, co_next);
|
||||
} while ((l_iter = l_iter->next) != l_first);
|
||||
|
||||
return perimeter;
|
||||
|
|
|
@ -28,7 +28,6 @@
|
|||
*/
|
||||
|
||||
struct Heap;
|
||||
struct Object;
|
||||
|
||||
#include "BLI_compiler_attrs.h"
|
||||
|
||||
|
@ -45,9 +44,9 @@ float BM_face_calc_normal_vcos(
|
|||
float const (*vertexCos)[3]) ATTR_NONNULL();
|
||||
float BM_face_calc_normal_subset(const BMLoop *l_first, const BMLoop *l_last, float r_no[3]) ATTR_NONNULL();
|
||||
float BM_face_calc_area(const BMFace *f) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
|
||||
float BM_face_calc_area_worldspace(struct Object *ob, const BMFace *f) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
|
||||
float BM_face_calc_area_with_mat3(const BMFace *f, const float mat3[3][3]) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
|
||||
float BM_face_calc_perimeter(const BMFace *f) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
|
||||
float BM_face_calc_perimeter_worldspace(struct Object *ob, const BMFace *f) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
|
||||
float BM_face_calc_perimeter_with_mat3(const BMFace *f, const float mat3[3][3]) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
|
||||
void BM_face_calc_tangent_edge(const BMFace *f, float r_plane[3]) ATTR_NONNULL();
|
||||
void BM_face_calc_tangent_edge_pair(const BMFace *f, float r_plane[3]) ATTR_NONNULL();
|
||||
void BM_face_calc_tangent_edge_diagonal(const BMFace *f, float r_plane[3]) ATTR_NONNULL();
|
||||
|
|
|
@ -31,8 +31,6 @@
|
|||
* of inspecting the mesh structure directly.
|
||||
*/
|
||||
|
||||
#include "DNA_object_types.h"
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "BLI_math.h"
|
||||
|
@ -41,7 +39,6 @@
|
|||
#include "BLI_utildefines_stack.h"
|
||||
|
||||
#include "BKE_customdata.h"
|
||||
#include "BKE_object.h"
|
||||
|
||||
#include "bmesh.h"
|
||||
#include "intern/bmesh_private.h"
|
||||
|
@ -1688,7 +1685,7 @@ float BM_edge_calc_face_angle(const BMEdge *e)
|
|||
*
|
||||
* \return angle in radians
|
||||
*/
|
||||
float BM_edge_calc_face_angle_worldspace_ex(Object *ob, const BMEdge *e, const float fallback)
|
||||
float BM_edge_calc_face_angle_with_imat3_ex(const BMEdge *e, const float imat3[3][3], const float fallback)
|
||||
{
|
||||
if (BM_edge_is_manifold(e)) {
|
||||
const BMLoop *l1 = e->l;
|
||||
|
@ -1697,12 +1694,9 @@ float BM_edge_calc_face_angle_worldspace_ex(Object *ob, const BMEdge *e, const f
|
|||
copy_v3_v3(no1, l1->f->no);
|
||||
copy_v3_v3(no2, l2->f->no);
|
||||
|
||||
float smat[3][3];
|
||||
BKE_object_scale_to_mat3(ob, smat);
|
||||
invert_m3(smat);
|
||||
mul_transposed_m3_v3(imat3, no1);
|
||||
mul_transposed_m3_v3(imat3, no2);
|
||||
|
||||
mul_m3_v3(smat, no1);
|
||||
mul_m3_v3(smat, no2);
|
||||
normalize_v3(no1);
|
||||
normalize_v3(no2);
|
||||
|
||||
|
@ -1712,9 +1706,9 @@ float BM_edge_calc_face_angle_worldspace_ex(Object *ob, const BMEdge *e, const f
|
|||
return fallback;
|
||||
}
|
||||
}
|
||||
float BM_edge_calc_face_angle_worldspace(Object *ob, const BMEdge *e)
|
||||
float BM_edge_calc_face_angle_with_imat3(const BMEdge *e, const float imat3[3][3])
|
||||
{
|
||||
return BM_edge_calc_face_angle_worldspace_ex(ob, e, DEG2RADF(90.0f));
|
||||
return BM_edge_calc_face_angle_with_imat3_ex(e, imat3, DEG2RADF(90.0f));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -27,8 +27,6 @@
|
|||
* \ingroup bmesh
|
||||
*/
|
||||
|
||||
struct Object;
|
||||
|
||||
bool BM_vert_in_face(BMVert *v, BMFace *f) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
|
||||
int BM_verts_in_face_count(BMVert **varr, int len, BMFace *f) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
|
||||
bool BM_verts_in_face(BMVert **varr, int len, BMFace *f) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
|
||||
|
@ -125,8 +123,8 @@ void BM_loop_calc_face_tangent(const BMLoop *l, float r_tangent[3]);
|
|||
float BM_edge_calc_face_angle_ex(const BMEdge *e, const float fallback) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
|
||||
float BM_edge_calc_face_angle(const BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
|
||||
float BM_edge_calc_face_angle_signed_ex(const BMEdge *e, const float fallback) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
|
||||
float BM_edge_calc_face_angle_worldspace_ex(struct Object *ob, const BMEdge *e, const float fallback) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
|
||||
float BM_edge_calc_face_angle_worldspace(struct Object *ob, const BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
|
||||
float BM_edge_calc_face_angle_with_imat3_ex(const BMEdge *e, const float imat3[3][3], const float fallback) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
|
||||
float BM_edge_calc_face_angle_with_imat3(const BMEdge *e, const float imat3[3][3]) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
|
||||
float BM_edge_calc_face_angle_signed(const BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
|
||||
void BM_edge_calc_face_tangent(const BMEdge *e, const BMLoop *e_loop, float r_tangent[3]) ATTR_NONNULL();
|
||||
|
||||
|
|
|
@ -245,6 +245,9 @@ static int similar_face_select_exec(bContext *C, wmOperator *op)
|
|||
continue;
|
||||
}
|
||||
|
||||
float ob_m3[3][3];
|
||||
copy_m3_m4(ob_m3, ob->obmat);
|
||||
|
||||
switch (type) {
|
||||
case SIMFACE_MATERIAL:
|
||||
{
|
||||
|
@ -293,14 +296,14 @@ static int similar_face_select_exec(bContext *C, wmOperator *op)
|
|||
}
|
||||
case SIMFACE_AREA:
|
||||
{
|
||||
float area = BM_face_calc_area_worldspace(ob, face);
|
||||
float area = BM_face_calc_area_with_mat3(face, ob_m3);
|
||||
float dummy[3] = {area, 0.0f, 0.0f};
|
||||
BLI_kdtree_insert(tree, tree_index++, dummy);
|
||||
break;
|
||||
}
|
||||
case SIMFACE_PERIMETER:
|
||||
{
|
||||
float perimeter = BM_face_calc_perimeter_worldspace(ob, face);
|
||||
float perimeter = BM_face_calc_perimeter_with_mat3(face, ob_m3);
|
||||
float dummy[3] = {perimeter, 0.0f, 0.0f};
|
||||
BLI_kdtree_insert(tree, tree_index++, dummy);
|
||||
break;
|
||||
|
@ -371,6 +374,9 @@ static int similar_face_select_exec(bContext *C, wmOperator *op)
|
|||
Material ***material_array = NULL;
|
||||
int custom_data_offset;
|
||||
|
||||
float ob_m3[3][3];
|
||||
copy_m3_m4(ob_m3, ob->obmat);
|
||||
|
||||
bool has_custom_data_layer = false;
|
||||
switch (type) {
|
||||
case SIMFACE_MATERIAL:
|
||||
|
@ -440,7 +446,7 @@ static int similar_face_select_exec(bContext *C, wmOperator *op)
|
|||
}
|
||||
case SIMFACE_AREA:
|
||||
{
|
||||
float area = BM_face_calc_area_worldspace(ob, face);
|
||||
float area = BM_face_calc_area_with_mat3(face, ob_m3);
|
||||
if (ED_select_similar_compare_float_tree(tree, area, thresh, compare)) {
|
||||
select = true;
|
||||
}
|
||||
|
@ -448,7 +454,7 @@ static int similar_face_select_exec(bContext *C, wmOperator *op)
|
|||
}
|
||||
case SIMFACE_PERIMETER:
|
||||
{
|
||||
float perimeter = BM_face_calc_perimeter_worldspace(ob, face);
|
||||
float perimeter = BM_face_calc_perimeter_with_mat3(face, ob_m3);
|
||||
if (ED_select_similar_compare_float_tree(tree, perimeter, thresh, compare)) {
|
||||
select = true;
|
||||
}
|
||||
|
@ -748,6 +754,10 @@ static int similar_edge_select_exec(bContext *C, wmOperator *op)
|
|||
}
|
||||
}
|
||||
|
||||
float ob_m3[3][3], ob_m3_inv[3][3];
|
||||
copy_m3_m4(ob_m3, ob->obmat);
|
||||
invert_m3_m3(ob_m3_inv, ob_m3);
|
||||
|
||||
BMEdge *edge; /* Mesh edge. */
|
||||
BMIter iter; /* Selected edges iterator. */
|
||||
|
||||
|
@ -774,7 +784,7 @@ static int similar_edge_select_exec(bContext *C, wmOperator *op)
|
|||
case SIMEDGE_FACE_ANGLE:
|
||||
{
|
||||
if (BM_edge_face_count_at_most(edge, 2) == 2) {
|
||||
float angle = BM_edge_calc_face_angle_worldspace(ob, edge);
|
||||
float angle = BM_edge_calc_face_angle_with_imat3(edge, ob_m3_inv);
|
||||
float dummy[3] = {angle, 0.0f, 0.0f};
|
||||
BLI_kdtree_insert(tree, tree_index++, dummy);
|
||||
}
|
||||
|
@ -855,6 +865,10 @@ static int similar_edge_select_exec(bContext *C, wmOperator *op)
|
|||
}
|
||||
}
|
||||
|
||||
float ob_m3[3][3], ob_m3_inv[3][3];
|
||||
copy_m3_m4(ob_m3, ob->obmat);
|
||||
invert_m3_m3(ob_m3_inv, ob_m3);
|
||||
|
||||
BMEdge *edge; /* Mesh edge. */
|
||||
BMIter iter; /* Selected edges iterator. */
|
||||
|
||||
|
@ -904,7 +918,7 @@ static int similar_edge_select_exec(bContext *C, wmOperator *op)
|
|||
case SIMEDGE_FACE_ANGLE:
|
||||
{
|
||||
if (BM_edge_face_count_at_most(edge, 2) == 2) {
|
||||
float angle = BM_edge_calc_face_angle_worldspace(ob, edge);
|
||||
float angle = BM_edge_calc_face_angle_with_imat3(edge, ob_m3_inv);
|
||||
if (ED_select_similar_compare_float_tree(tree, angle, thresh, SIM_CMP_EQ)) {
|
||||
select = true;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue