Math Lib: optimize axis_dominant_v3_to_m3, approx 6x speedup
build the matrix directly rather then calculating with axis/angle also remove unused function calc_poly_plane
This commit is contained in:
parent
233dac1494
commit
b3972aeea0
Notes:
blender-bot
2023-05-03 10:14:48 +02:00
Referenced by issue #40434, Crash when trying to add mirror to a curve
|
@ -49,84 +49,53 @@ namespace {
|
|||
|
||||
// Functions adopted from BLI_math.h to use Carve Vector and Matrix.
|
||||
|
||||
void axis_angle_normalized_to_mat3(const Vector &normal,
|
||||
const double angle,
|
||||
Matrix3 *matrix)
|
||||
void transpose_m3__bli(double mat[3][3])
|
||||
{
|
||||
double nsi[3], co, si, ico;
|
||||
double t;
|
||||
|
||||
/* now convert this to a 3x3 matrix */
|
||||
co = cos(angle);
|
||||
si = sin(angle);
|
||||
|
||||
ico = (1.0 - co);
|
||||
nsi[0] = normal[0] * si;
|
||||
nsi[1] = normal[1] * si;
|
||||
nsi[2] = normal[2] * si;
|
||||
|
||||
matrix->m[0][0] = ((normal[0] * normal[0]) * ico) + co;
|
||||
matrix->m[0][1] = ((normal[0] * normal[1]) * ico) + nsi[2];
|
||||
matrix->m[0][2] = ((normal[0] * normal[2]) * ico) - nsi[1];
|
||||
matrix->m[1][0] = ((normal[0] * normal[1]) * ico) - nsi[2];
|
||||
matrix->m[1][1] = ((normal[1] * normal[1]) * ico) + co;
|
||||
matrix->m[1][2] = ((normal[1] * normal[2]) * ico) + nsi[0];
|
||||
matrix->m[2][0] = ((normal[0] * normal[2]) * ico) + nsi[1];
|
||||
matrix->m[2][1] = ((normal[1] * normal[2]) * ico) - nsi[0];
|
||||
matrix->m[2][2] = ((normal[2] * normal[2]) * ico) + co;
|
||||
t = mat[0][1];
|
||||
mat[0][1] = mat[1][0];
|
||||
mat[1][0] = t;
|
||||
t = mat[0][2];
|
||||
mat[0][2] = mat[2][0];
|
||||
mat[2][0] = t;
|
||||
t = mat[1][2];
|
||||
mat[1][2] = mat[2][1];
|
||||
mat[2][1] = t;
|
||||
}
|
||||
|
||||
void axis_angle_to_mat3(const Vector &axis,
|
||||
const double angle,
|
||||
Matrix3 *matrix)
|
||||
void ortho_basis_v3v3_v3__bli(double r_n1[3], double r_n2[3], const double n[3])
|
||||
{
|
||||
if (axis.length2() < FLT_EPSILON) {
|
||||
*matrix = Matrix3();
|
||||
return;
|
||||
}
|
||||
const double eps = FLT_EPSILON;
|
||||
const double f = (n[0] * n[0]) + (n[1] * n[1]);
|
||||
|
||||
Vector nor = axis;
|
||||
nor.normalize();
|
||||
if (f > eps) {
|
||||
const double d = 1.0f / sqrt(f);
|
||||
|
||||
axis_angle_normalized_to_mat3(nor, angle, matrix);
|
||||
}
|
||||
|
||||
inline double saacos(double fac)
|
||||
{
|
||||
if (fac <= -1.0) return M_PI;
|
||||
else if (fac >= 1.0) return 0.0;
|
||||
else return acos(fac);
|
||||
}
|
||||
|
||||
bool axis_dominant_v3_to_m3(const Vector &normal,
|
||||
Matrix3 *matrix)
|
||||
{
|
||||
Vector up;
|
||||
Vector axis;
|
||||
double angle;
|
||||
|
||||
up.x = 0.0;
|
||||
up.y = 0.0;
|
||||
up.z = 1.0;
|
||||
|
||||
axis = carve::geom::cross(normal, up);
|
||||
angle = saacos(carve::geom::dot(normal, up));
|
||||
|
||||
if (angle >= FLT_EPSILON) {
|
||||
if (axis.length2() < FLT_EPSILON) {
|
||||
axis[0] = 0.0;
|
||||
axis[1] = 1.0;
|
||||
axis[2] = 0.0;
|
||||
}
|
||||
|
||||
axis_angle_to_mat3(axis, angle, matrix);
|
||||
return true;
|
||||
r_n1[0] = n[1] * d;
|
||||
r_n1[1] = -n[0] * d;
|
||||
r_n1[2] = 0.0f;
|
||||
r_n2[0] = -n[2] * r_n1[1];
|
||||
r_n2[1] = n[2] * r_n1[0];
|
||||
r_n2[2] = n[0] * r_n1[1] - n[1] * r_n1[0];
|
||||
}
|
||||
else {
|
||||
*matrix = Matrix3();
|
||||
return false;
|
||||
/* degenerate case */
|
||||
r_n1[0] = (n[2] < 0.0f) ? -1.0f : 1.0f;
|
||||
r_n1[1] = r_n1[2] = r_n2[0] = r_n2[2] = 0.0f;
|
||||
r_n2[1] = 1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
void axis_dominant_v3_to_m3__bli(Matrix3 *r_mat, const Vector &normal)
|
||||
{
|
||||
memcpy(r_mat->m[2], normal.v, sizeof(double[3]));
|
||||
ortho_basis_v3v3_v3__bli(r_mat->m[0], r_mat->m[1], r_mat->m[2]);
|
||||
|
||||
transpose_m3__bli(r_mat->m);
|
||||
}
|
||||
|
||||
|
||||
void meshset_minmax(const MeshSet<3> *mesh,
|
||||
Vector *min,
|
||||
Vector *max)
|
||||
|
@ -581,7 +550,7 @@ bool carve_checkPolyPlanarAndGetNormal(const std::vector<Vector> &vertices,
|
|||
double magnitude = normal.length2();
|
||||
|
||||
normal.normalize();
|
||||
axis_dominant_v3_to_m3(normal, axis_matrix_r);
|
||||
axis_dominant_v3_to_m3__bli(axis_matrix_r, normal);
|
||||
|
||||
Vector first_projected = *axis_matrix_r * vertices[verts_of_poly[0]];
|
||||
double min_z = first_projected[2], max_z = first_projected[2];
|
||||
|
|
|
@ -303,7 +303,7 @@ bool form_factor_visible_quad(const float p[3], const float n[3],
|
|||
float form_factor_hemi_poly(float p[3], float n[3],
|
||||
float v1[3], float v2[3], float v3[3], float v4[3]);
|
||||
|
||||
bool axis_dominant_v3_to_m3(float r_mat[3][3], const float normal[3]);
|
||||
void axis_dominant_v3_to_m3(float r_mat[3][3], const float normal[3]);
|
||||
|
||||
MINLINE void axis_dominant_v3(int *r_axis_a, int *r_axis_b, const float axis[3]);
|
||||
MINLINE float axis_dominant_v3_max(int *r_axis_a, int *r_axis_b, const float axis[3]) ATTR_WARN_UNUSED_RESULT;
|
||||
|
|
|
@ -2133,32 +2133,20 @@ void fill_poly_v2i_n(
|
|||
* \param r_mat The matrix to return.
|
||||
* \param normal A unit length vector.
|
||||
*/
|
||||
bool axis_dominant_v3_to_m3(float r_mat[3][3], const float normal[3])
|
||||
void axis_dominant_v3_to_m3(float r_mat[3][3], const float normal[3])
|
||||
{
|
||||
float up[3] = {0.0f, 0.0f, 1.0f};
|
||||
float axis[3];
|
||||
float angle;
|
||||
|
||||
/* double check they are normalized */
|
||||
BLI_ASSERT_UNIT_V3(normal);
|
||||
|
||||
cross_v3_v3v3(axis, normal, up);
|
||||
angle = saacos(dot_v3v3(normal, up));
|
||||
copy_v3_v3(r_mat[2], normal);
|
||||
ortho_basis_v3v3_v3(r_mat[0], r_mat[1], r_mat[2]);
|
||||
|
||||
if (angle >= FLT_EPSILON) {
|
||||
if (len_squared_v3(axis) < FLT_EPSILON) {
|
||||
axis[0] = 0.0f;
|
||||
axis[1] = 1.0f;
|
||||
axis[2] = 0.0f;
|
||||
}
|
||||
BLI_ASSERT_UNIT_V3(r_mat[0]);
|
||||
BLI_ASSERT_UNIT_V3(r_mat[1]);
|
||||
|
||||
axis_angle_to_mat3(r_mat, axis, angle);
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
unit_m3(r_mat);
|
||||
return false;
|
||||
}
|
||||
transpose_m3(r_mat);
|
||||
|
||||
BLI_assert(!is_negative_m3(r_mat));
|
||||
BLI_assert(fabsf(dot_m3_v3_row_z(r_mat, normal) - 1.0f) < BLI_ASSERT_UNIT_EPSILON);
|
||||
}
|
||||
|
||||
/****************************** Interpolation ********************************/
|
||||
|
|
|
@ -317,12 +317,7 @@ static int quad_co(float *x, float *y, float v1[3], float v2[3], float v3[3], fl
|
|||
|
||||
/* rotate */
|
||||
poly_rotate_plane(n, projverts, 5);
|
||||
|
||||
/* flatten */
|
||||
for (i = 0; i < 5; i++) {
|
||||
projverts[i][2] = 0.0f;
|
||||
}
|
||||
|
||||
|
||||
/* subtract origin */
|
||||
for (i = 0; i < 4; i++) {
|
||||
sub_v3_v3(projverts[i], projverts[4]);
|
||||
|
|
|
@ -361,46 +361,6 @@ void BM_face_calc_center_mean_weighted(BMFace *f, float r_cent[3])
|
|||
mul_v3_fl(r_cent, 1.0f / (float) totw);
|
||||
}
|
||||
|
||||
/**
|
||||
* COMPUTE POLY PLANE
|
||||
*
|
||||
* Projects a set polygon's vertices to
|
||||
* a plane defined by the average
|
||||
* of its edges cross products
|
||||
*/
|
||||
void calc_poly_plane(float (*verts)[3], const int nverts)
|
||||
{
|
||||
|
||||
float avgc[3], norm[3], mag, avgn[3];
|
||||
float *v1, *v2, *v3;
|
||||
int i;
|
||||
|
||||
if (nverts < 3)
|
||||
return;
|
||||
|
||||
zero_v3(avgn);
|
||||
zero_v3(avgc);
|
||||
|
||||
for (i = 0; i < nverts; i++) {
|
||||
v1 = verts[i];
|
||||
v2 = verts[(i + 1) % nverts];
|
||||
v3 = verts[(i + 2) % nverts];
|
||||
normal_tri_v3(norm, v1, v2, v3);
|
||||
|
||||
add_v3_v3(avgn, norm);
|
||||
}
|
||||
|
||||
if (UNLIKELY(normalize_v3(avgn) == 0.0f)) {
|
||||
avgn[2] = 1.0f;
|
||||
}
|
||||
|
||||
for (i = 0; i < nverts; i++) {
|
||||
v1 = verts[i];
|
||||
mag = dot_v3v3(v1, avgn);
|
||||
madd_v3_v3fl(v1, avgn, -mag);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief BM LEGAL EDGES
|
||||
*
|
||||
|
@ -430,15 +390,18 @@ static void scale_edge_v2f(float v1[2], float v2[2], const float fac)
|
|||
* Rotates a polygon so that it's
|
||||
* normal is pointing towards the mesh Z axis
|
||||
*/
|
||||
void poly_rotate_plane(const float normal[3], float (*verts)[3], const int nverts)
|
||||
void poly_rotate_plane(const float normal[3], float (*verts)[3], const unsigned int nverts)
|
||||
{
|
||||
float mat[3][3];
|
||||
float co[3];
|
||||
unsigned int i;
|
||||
|
||||
if (axis_dominant_v3_to_m3(mat, normal)) {
|
||||
int i;
|
||||
for (i = 0; i < nverts; i++) {
|
||||
mul_m3_v3(mat, verts[i]);
|
||||
}
|
||||
co[2] = 0.0f;
|
||||
|
||||
axis_dominant_v3_to_m3(mat, normal);
|
||||
for (i = 0; i < nverts; i++) {
|
||||
mul_v2_m3v3(co, mat, verts[i]);
|
||||
copy_v3_v3(verts[i], co);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -72,8 +72,7 @@ enum {
|
|||
#define BM_ELEM_API_FLAG_TEST(element, f) ((element)->head.api_flag & (f))
|
||||
#define BM_ELEM_API_FLAG_CLEAR(element) ((element)->head.api_flag = 0)
|
||||
|
||||
void calc_poly_plane(float (*verts)[3], const int nverts);
|
||||
void poly_rotate_plane(const float normal[3], float (*verts)[3], const int nverts);
|
||||
void poly_rotate_plane(const float normal[3], float (*verts)[3], unsigned const int nverts);
|
||||
|
||||
/* include the rest of our private declarations */
|
||||
#include "bmesh_structure.h"
|
||||
|
|
Loading…
Reference in New Issue