Dyntopo: code cleanup

This commit is contained in:
Joseph Eagar 2021-05-19 12:21:46 -07:00
parent 71959181ad
commit 3d6ac0bd7b
10 changed files with 24 additions and 751 deletions

Binary file not shown.

View File

@ -282,8 +282,7 @@ set(SRC
intern/workspace.c
intern/world.c
intern/writeavi.c
intern/closest_point_tri_sse.cc
BKE_DerivedMesh.h
BKE_action.h
BKE_addon.h

View File

@ -1,398 +0,0 @@
// see Fast Distance Queries for Triangles, Lines, and
// Points using SSE Instructions
// http://jcgt.org/published/0003/04/05/paper.pdf
typedef struct DistRet {
float dist[4];
} DistRet;
#if defined(__SSE2__) || defined(__SSE4__)
# include <cstdint>
# include <immintrin.h>
# include <smmintrin.h>
# include <xmmintrin.h>
struct sseb {
// data
union {
__m128 m128;
uint32_t v[4];
};
sseb()
{
}
sseb(__m128 m)
{
m128 = m;
}
};
struct ssef {
// data
union {
__m128 m128;
float v[4];
int i[4];
};
ssef(float a, float b, float c, float d)
{
v[0] = a;
v[1] = b;
v[2] = c;
v[3] = d;
}
ssef()
{
}
ssef(__m128 f)
{
m128 = f;
}
ssef(float f)
{
v[0] = v[1] = v[2] = v[3] = f;
}
};
#endif
#if defined(__SSE2__) && !defined(__SSE4__)
__m128 my_mm_blendv_ps(__m128 a, __m128 b, __m128 mask)
{
ssef fa(a);
ssef fb(b);
sseb fm(mask);
ssef ret;
for (int i = 0; i < 4; i++) {
if (fm.v[i] & (1 << 31)) {
ret.v[i] = fb.v[i];
}
else {
ret.v[i] = fa.v[i];
}
}
return ret.m128;
}
# define _mm_blendv_ps my_mm_blendv_ps
#endif
#ifdef __SSE2__
# include <array>
# include <vector>
static inline struct sseb makeSSSEB(__m128 val)
{
sseb r;
r.m128 = val;
return r;
}
// operations
const sseb operator&(const sseb &a, const sseb &b)
{
return makeSSSEB(_mm_and_ps(a.m128, b.m128));
}
const sseb operator|(const sseb &a, const sseb &b)
{
return makeSSSEB(_mm_or_ps(a.m128, b.m128));
}
const sseb operator|=(const sseb &a, const sseb &b)
{
return a | b;
}
const sseb operator^(const sseb &a, const sseb &b)
{
return makeSSSEB(_mm_xor_ps(a.m128, b.m128));
}
bool all(const sseb &b)
{
return _mm_movemask_ps(b.m128) == 0xf;
}
bool any(const sseb &b)
{
return _mm_movemask_ps(b.m128) != 0x0;
}
bool none(const sseb &b)
{
return _mm_movemask_ps(b.m128) == 0x0;
}
static inline struct ssef makeSSSEF(__m128 val)
{
ssef r;
r.m128 = val;
return r;
}
// operations
const ssef operator+(const ssef &a, const ssef &b)
{
return makeSSSEF(_mm_add_ps(a.m128, b.m128));
}
const ssef operator-(const ssef &a, const ssef &b)
{
return makeSSSEF(_mm_sub_ps(a.m128, b.m128));
}
const ssef operator*(const ssef &a, const ssef &b)
{
return makeSSSEF(_mm_mul_ps(a.m128, b.m128));
}
const ssef operator/(const ssef &a, const ssef &b)
{
return makeSSSEF(_mm_div_ps(a.m128, b.m128));
}
const sseb operator>=(const ssef &a, const ssef &b)
{
__m128 r1 = _mm_cmpgt_ss(a.m128, b.m128);
__m128 r2 = _mm_cmpeq_ss(a.m128, b.m128);
return makeSSSEB(_mm_or_ps(r1, r2));
}
const sseb operator<=(const ssef &a, const ssef &b)
{
__m128 r1 = _mm_cmplt_ss(a.m128, b.m128);
__m128 r2 = _mm_cmpeq_ss(a.m128, b.m128);
return makeSSSEB(_mm_or_ps(r1, r2));
}
const sseb operator>(const ssef &a, const ssef &b)
{
return makeSSSEB(_mm_cmpgt_ss(a.m128, b.m128));
}
const sseb operator<(const ssef &a, const ssef &b)
{
return makeSSSEB(_mm_cmplt_ss(a.m128, b.m128));
}
const ssef min(const ssef &a, const ssef &b)
{
return makeSSSEF(_mm_min_ps(a.m128, b.m128));
}
const ssef sqr(const ssef &a)
{
return makeSSSEF(_mm_mul_ps(a.m128, a.m128));
}
const ssef sqrt(const ssef &a)
{
return makeSSSEF(_mm_sqrt_ps(a.m128));
}
const ssef select(const sseb &mask, const ssef &t, const ssef &f)
{
return makeSSSEF(_mm_blendv_ps(f.m128, t.m128, mask.m128));
}
template<typename T> struct Vec3 {
// data
T x, y, z;
Vec3(T x, T y, T z) : x(x), y(y), z(z)
{
}
Vec3(T v) : x(v), y(v), z(v)
{
}
};
// operations
template<typename T> Vec3<T> operator+(const Vec3<T> &a, const Vec3<T> &b)
{
return Vec3<T>(a.x + b.x, a.y + b.y, a.z + b.z);
}
template<typename T> Vec3<T> operator-(const Vec3<T> &a, const Vec3<T> &b)
{
return Vec3<T>(a.x - b.x, a.y - b.y, a.z - b.z);
}
template<typename T> Vec3<T> operator*(const Vec3<T> &a, const Vec3<T> &b)
{
return Vec3<T>(a.x * b.x, a.y * b.y, a.z * b.z);
}
template<typename T> Vec3<T> operator*(const T &a, const Vec3<T> &b)
{
return Vec3<T>(b.x * a, b.y * a, b.z * a);
}
template<typename T> Vec3<T> operator*(const Vec3<T> &b, const T &a)
{
return Vec3<T>(b.x * a, b.y * a, b.z * a);
}
template<typename T> inline Vec3<T> rcp(const Vec3<T> &a)
{
return Vec3<T>(rcp(a.x), rcp(a.y), rcp(a.z));
}
template<typename T> inline Vec3<T> rsqrt(const Vec3<T> &a)
{
return Vec3<T>(rsqrt(a.x), rsqrt(a.y), rsqrt(a.z));
}
template<typename T> T dot(const Vec3<T> &a, const Vec3<T> &b)
{
return a.x * b.x + a.y * b.y + a.z * b.z;
}
template<typename T> T length2b(const Vec3<T> &a)
{
return dot(a, a);
}
typedef sseb simdBool;
typedef ssef simdFloat;
typedef Vec3<ssef> simdFloatVec;
typedef std::array<simdFloatVec, 3> simdTriangle_type;
typedef std::array<simdFloatVec, 2> simdLine_type;
typedef simdFloatVec simdPoint_type;
static inline simdFloat length2(const simdFloatVec &a)
{
return a.x * a.x + a.y * a.y + a.z * a.z;
}
static simdFloat zero = {0};
static simdFloat one = {1.0f, 1.0f, 1.0f, 1.0f};
const simdFloatVec select(const sseb &mask, const simdFloatVec &t, const simdFloatVec &f)
{
simdFloatVec r2(select(mask, t.x, f.x), select(mask, t.y, f.y), select(mask, t.z, f.z));
return r2;
}
template<typename T> T clamp(const T &x, const T &lower, const T &upper)
{
return max(lower, min(x, upper));
}
const simdFloat simdTriPoint2(simdFloatVec &oTriPoint,
const simdTriangle_type &iTri,
const simdPoint_type &iPoint)
{
const simdFloatVec ab = iTri[1] - iTri[0];
const simdFloatVec ac = iTri[2] - iTri[0];
const simdFloatVec ap = iPoint - iTri[0];
const simdFloat d1 = dot(ab, ap);
const simdFloat d2 = dot(ac, ap);
const simdBool mask1 = (d1 <= simdFloat(zero)) & (d2 <= simdFloat(zero));
oTriPoint = iTri[0];
simdBool exit(mask1);
if (all(exit))
return length2(oTriPoint - iPoint);
const simdFloatVec bp = iPoint - iTri[1];
const simdFloat d3 = dot(ab, bp);
const simdFloat d4 = dot(ac, bp);
const simdBool mask2 = (d3 >= simdFloat(zero)) & (d4 <= d3);
// Closest point is the point iTri[1]. Update if necessary.
oTriPoint = select(exit, oTriPoint, select(mask2, iTri[1], oTriPoint));
exit = exit | mask2;
if (all(exit))
return length2(oTriPoint - iPoint);
const simdFloatVec cp = iPoint - iTri[2];
const simdFloat d5 = dot(ab, cp);
const simdFloat d6 = dot(ac, cp);
const simdBool mask3 = (d6 >= simdFloat(zero)) & (d5 <= d6);
// Closest point is the point iTri[2]. Update if necessary.
oTriPoint = select(exit, oTriPoint, select(mask3, iTri[2], oTriPoint));
exit |= mask3;
if (all(exit))
return length2(oTriPoint - iPoint);
const simdFloat vc = d1 * d4 - d3 * d2;
const simdBool mask4 = (vc <= simdFloat(zero)) & (d1 >= simdFloat(zero)) &
(d3 <= simdFloat(zero));
const simdFloat v1 = d1 / (d1 - d3);
const simdFloatVec answer1 = iTri[0] + v1 * ab;
// Closest point is on the line ab. Update if necessary.
oTriPoint = select(exit, oTriPoint, select(mask4, answer1, oTriPoint));
exit |= mask4;
if (all(exit))
return length2(oTriPoint - iPoint);
const simdFloat vb = d5 * d2 - d1 * d6;
const simdBool mask5 = (vb <= simdFloat(zero)) & (d2 >= simdFloat(zero)) &
(d6 <= simdFloat(zero));
const simdFloat w1 = d2 / (d2 - d6);
const simdFloatVec answer2 = iTri[0] + w1 * ac;
// Closest point is on the line ac. Update if necessary.
oTriPoint = select(exit, oTriPoint, select(mask5, answer2, oTriPoint));
exit |= mask5;
if (all(exit))
return length2(oTriPoint - iPoint);
const simdFloat va = d3 * d6 - d5 * d4;
const simdBool mask6 = (va <= simdFloat(zero)) & ((d4 - d3) >= simdFloat(zero)) &
((d5 - d6) >= simdFloat(zero));
simdFloat w2 = (d4 - d3) / ((d4 - d3) + (d5 - d6));
const simdFloatVec answer3 = iTri[1] + w2 * (iTri[2] - iTri[1]);
// Closest point is on the line bc. Update if necessary.
oTriPoint = select(exit, oTriPoint, select(mask6, answer3, oTriPoint));
exit |= mask6;
if (all(exit))
return length2(oTriPoint - iPoint);
const simdFloat denom = simdFloat(one) / (va + vb + vc);
const simdFloat v2 = vb * denom;
const simdFloat w3 = vc * denom;
const simdFloatVec answer4 = iTri[0] + ab * v2 + ac * w3;
const simdBool mask7 = length2(answer4 - iPoint) < length2(oTriPoint - iPoint);
// Closest point is inside triangle. Update if necessary.
oTriPoint = select(exit, oTriPoint, select(mask7, answer4, oTriPoint));
return length2(oTriPoint - iPoint);
}
extern "C" struct DistRet dist_to_tri_sphere_fast_4(
float p[3], float v1[4][3], float v2[4][3], float v3[4][3], float n[4][3])
{
simdFloatVec mp((simdFloat(p[0]), simdFloat(p[1]), simdFloat(p[2])));
simdFloatVec t1(simdFloat(v1[0][0], v1[1][0], v1[2][0], v1[3][0]),
simdFloat(v1[0][1], v1[1][1], v1[2][1], v1[3][1]),
simdFloat(v1[0][2], v1[1][2], v1[2][2], v1[3][2]));
simdFloatVec t2(simdFloat(v2[0][0], v2[1][0], v2[2][0], v2[3][0]),
simdFloat(v2[0][1], v2[1][1], v2[2][1], v2[3][1]),
simdFloat(v2[0][2], v2[1][2], v2[2][2], v2[3][2]));
simdFloatVec t3(simdFloat(v3[0][0], v3[1][0], v3[2][0], v3[3][0]),
simdFloat(v3[0][1], v3[1][1], v3[2][1], v3[3][1]),
simdFloat(v3[0][2], v3[1][2], v3[2][2], v3[3][2]));
simdTriangle_type tri = {t1, t2, t3};
struct DistRet ret;
ssef f = simdTriPoint2(mp, tri, mp);
ret.dist[0] = f.v[0];
ret.dist[1] = f.v[1];
ret.dist[2] = f.v[2];
ret.dist[3] = f.v[3];
return ret;
}
#else
#include "BLI_math.h"
extern "C" struct DistRet dist_to_tri_sphere_fast_4(
float p[3], float v1[4][3], float v2[4][3], float v3[4][3], float n[4][3])
{
DistRet ret;
float r[3];
for (int i=0; i<4; i++) {
closest_on_tri_to_point_v3(r, p, v1[i], v2[i], v3[i]);
ret.dist[i] = len_squared_v3v3(r, p);
}
return ret;
}
#endif

View File

@ -1445,95 +1445,10 @@ static bool edge_queue_vert_in_sphere(const EdgeQueue *q, BMVert *v)
return len_squared_v3v3(q->center, v->co) <= q->radius_squared;
}
/* reduce script
on factor;
ax := 0;
ay := 0;
e1x := bx - ax;
e1y := by - ay;
e2x := cx - bx;
e2y := cy - by;
e3x := ax - cx;
e3y := ay - cy;
l1 := (e1x**2 + e1y**2)**0.5;
l2 := (e2x**2 + e2y**2)**0.5;
l3 := (e3x**2 + e3y**2)**0.5;
load_package "avector";
e1 := avec(e1x / l1, e1y / l1, 0.0);
e2 := avec(e2x / l2, e2y / l2, 0.0);
e3 := avec(e3x / l3, e3y / l3, 0.0);
ax := 0;
ay := 0;
d1 := x1*e1[1] - y1*e1[0];
d2 := x1*e2[1] - y1*e2[0];
d3 := x1*e3[1] - y1*e3[0];
d1 := d1**2;
d2 := d2**2;
d3 := d3**2;
on fort;
d1;
d2;
d3;
off fort;
fdis := (sqrt(dis)/nz)**2 + planedis**2;
*/
/*
static inline float dot_v3v3(const float a[3], const float b[3])
{
return a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
}
static inline void sub_v3_v3v3(float r[3], const float a[3], const float b[3])
{
r[0] = a[0] - b[0];
r[1] = a[1] - b[1];
r[2] = a[2] - b[2];
}
static inline void add_v3_v3v3(float r[3], const float a[3], const float b[3])
{
r[0] = a[0] + b[0];
r[1] = a[1] + b[1];
r[2] = a[2] + b[2];
}
static inline void add_v3_v3(float r[3], const float a[3])
{
r[0] += a[0];
r[1] += a[1];
r[2] += a[2];
}
static inline void mul_v3_fl(float r[3], float f)
{
r[0] *= f;
r[1] *= f;
r[2] *= f;
}
static inline float len_squared_v3v3(const float a[3], const float b[3])
{
float d[3];
sub_v3_v3v3(d, b, a);
return dot_v3v3(d, d);
}
*/
Profiling revealed the accurate distance to tri in blenlib was too slow,
so we use a simpler version here
*/
static float dist_to_tri_sphere_simple(
float p[3], float v1[3], float v2[3], float v3[3], float n[3])
{
@ -1563,205 +1478,6 @@ static float dist_to_tri_sphere_simple(
return dis;
}
//#include <cmath>
// int mask = (nx < ny) | ((nx < nz) << 1) | ((ny < nz) << 2) | ((nx < nz) << 3);
/*
let axis1, axis2, axis3;
let tabx = new Array(8);
let taby = new Array(8);
let tabz = new Array(8);
let b1 = 1;//nx > ny;
let b2 = 2;//nx > nz;
let b3 = 4;//ny > nz;
m1 = 1 | 2;
m2 = 4;
tabx[m1] = 1;
taby[m1] = 2;
tabz[m1] = 0;
tabx[m2] = 0;
taby[m2] = 2;
tabz[m2] = 1;
for (let i=0; i<tabx.length; i++) {
if (tabx[i] === undefined) {
tabx[i] = 0;
taby[i] = 1;
tabz[i] = 2;
}
}
function format(tab) {
let s = '';
for (let i=0; i<tab.length; i++) {
if (i > 0) {
s += ', '
}
s += tab[i];
}
return s;
}
let buf = `
static int tritablex[${tabx.length}] = {${format(tabx)}};
static int tritabley[${taby.length}] = {${format(taby)}};
static int tritablez[${tabz.length}] = {${format(tabz)}};
`;
console.log(buf);
*/
static int tritablex[8] = {0, 0, 0, 1, 0, 0, 0, 0};
static int tritabley[8] = {1, 1, 1, 2, 2, 1, 1, 1};
static int tritablez[8] = {2, 2, 2, 0, 1, 2, 2, 2};
float dist_to_tri_sphere(float p[3], float v1[3], float v2[3], float v3[3], float n[3])
{
// find projection axis;
int axis1, axis2, axis3;
// clang optimizes fabsf better
double nx = fabsf(n[0]); // n[0] < 0.0 ? -n[0] : n[0];
double ny = fabsf(n[1]); // n[1] < 0.0 ? -n[1] : n[1];
double nz = fabsf(n[2]); // n[2] < 0.0 ? -n[2] : n[2];
const double feps = 0.000001;
#if 0
if (nx > ny && nx > nz) {
axis1 = 1;
axis2 = 2;
axis3 = 0;
}
else if (ny > nx && ny > nz) {
axis1 = 0;
axis2 = 2;
axis3 = 1;
}
else {
axis1 = 0;
axis2 = 1;
axis3 = 2;
}
#else
int mask = 0;
//
// let b1 = 1; // nx > ny;
// let b2 = 2; // nx > nz;
// let b3 = 4; // ny > nz;
mask = mask | (nx > ny);
mask = mask | ((nx > nz) << 1);
mask = mask | ((ny > nz) << 2);
axis1 = tritablex[mask];
axis2 = tritabley[mask];
axis3 = tritablez[mask];
#endif
#if 1
double planedis = (p[0] - v1[0]) * n[0] + (p[1] - v1[1]) * n[1] + (p[2] - v1[2]) * n[2];
planedis = planedis < 0.0 ? -planedis : planedis;
double ax = v1[axis1], ay = v1[axis2];
double bx = v2[axis1] - ax, by = v2[axis2] - ay;
double cx = v3[axis1] - ax, cy = v3[axis2] - ay;
double bx2 = bx * bx, by2 = by * by, cx2 = cx * cx, cy2 = cy * cy;
double x1 = p[axis1] - ax;
double y1 = p[axis2] - ay;
bool s1 = x1 * by - y1 * bx < 0.0;
bool s2 = x1 * (cy - by) - y1 * (cx - bx) < 0.0;
bool s3 = x1 * -cy - y1 * -cx < 0.0;
int side = 0;
mask = s1 | (s2 << 1) | (s3 << 2);
if (mask == 0.0) {
return planedis * planedis;
}
double d1, d2, d3, div;
/*
//\ 3|
// \ |
// b
// | \
// 1 | \ 2
// | 0 \
// ___a_______c___
// 5 | 4 \ 6
*/
double dis = 0.0;
switch (mask) {
case 1:
div = (bx2 + by2);
if (div > feps) {
d1 = (bx * y1 - by * x1);
d1 = (d1 * d1) / div;
}
else {
d1 = x1 * x1 + y1 * y1;
}
dis = d1;
break;
case 3:
dis = ((x1 - bx) * (x1 - bx) + (y1 - by) * (y1 - by));
break;
case 2:
div = ((bx - cx) * (bx - cx) + (by - cy) * (by - cy));
if (div > feps) {
d2 = ((bx - cx) * y1 - (by - cy) * x1);
d2 = (d2 * d2) / div;
}
else {
d2 = (x1 - bx) * (x1 - bx) + (y1 - by) * (y1 - by);
}
dis = d2;
break;
case 6:
dis = (x1 - cx) * (x1 - cx) + (y1 - cy) * (y1 - cy);
break;
case 4:
div = (cx2 + cy2);
if (div > feps) {
d3 = (cx * y1 - cy * x1);
d3 = (d3 * d3) / div;
}
else {
d3 = (x1 - cx) * (x1 - cx) + (y1 - cy) * (y1 - cy);
}
dis = d3;
break;
case 5:
dis = x1 * x1 + y1 * y1;
break;
}
nz = n[axis3] < 0.0 ? -n[axis3] : n[axis3];
return (float)(dis + nz * nz * planedis * planedis) / (nz * nz);
#else
return (float)axis1 + (float)axis2 + (float)axis3;
#endif
}
static bool edge_queue_tri_in_sphere(const EdgeQueue *q, BMFace *f)
{
float c[3];
@ -1777,37 +1493,7 @@ static bool edge_queue_tri_in_sphere(const EdgeQueue *q, BMFace *f)
(float *)l->prev->v->co,
(float *)f->no);
// closest_on_tri_to_point_v3(c, co, v1, v2, v3);
// float dis2 = len_squared_v3v3(q->center, c);
// float dis3 = sqrtf(dis2);
return dis <= q->radius_squared;
/* Get closest point in triangle to sphere center */
#if 0
/*
closest_on_tri_to_point_v3 is being slow
*/
float mindis = 1e17;
float dis;
copy_v3_v3(c, q->center);
for (int i=0; i<3; i++) {
dis = len_squared_v3v3(v_tri[i]->co, c);
mindis = MIN2(mindis, dis);
dis = dist_squared_to_line_segment_v3(c, v_tri[i]->co, v_tri[(i+1)%3]->co);
mindis = MIN2(mindis, dis);
}
return mindis <= q->radius_squared;
#else
closest_on_tri_to_point_v3(c, q->center, l->v->co, l->next->v->co, l->prev->v->co);
/* Check if triangle intersects the sphere */
return len_squared_v3v3(q->center, c) <= q->radius_squared;
#endif
}
static bool edge_queue_tri_in_circle(const EdgeQueue *q, BMFace *f)

View File

@ -360,9 +360,9 @@ static void eval_displacement(SubdivDisplacement *displacement,
BKE_multires_construct_tangent_matrix(tangent_matrix, dPdu, dPdv, corner_of_quad);
mul_v3_m3v3(r_D, tangent_matrix, tangent_D);
/* For the boundary points of grid average two (or all) neighbor grids. */
//XXX
//const int corner = displacement_get_face_corner(data, ptex_face_index, u, v);
//average_displacement(displacement, average_with, ptex_face_index, corner, grid_u, grid_v, r_D);
const int corner = displacement_get_face_corner(data, ptex_face_index, u, v);
average_displacement(displacement, average_with, ptex_face_index, corner, grid_u, grid_v, r_D);
}
static void free_displacement(SubdivDisplacement *displacement)

View File

@ -755,15 +755,18 @@ set_property(GLOBAL PROPERTY ICON_GEOM_NAMES
brush.sculpt.mask
brush.sculpt.multiplane_scrape
brush.sculpt.nudge
brush.sculpt.paint
brush.sculpt.pinch
brush.sculpt.pose
brush.sculpt.rotate
brush.sculpt.scrape
brush.sculpt.simplify
brush.sculpt.smear
brush.sculpt.smooth
brush.sculpt.snake_hook
brush.sculpt.thumb
brush.sculpt.topology
brush.sculpt.vcol_boundary
brush.uv_sculpt.grab
brush.uv_sculpt.pinch
brush.uv_sculpt.relax

View File

@ -921,6 +921,7 @@ DEF_ICON_COLOR(BRUSH_THUMB)
DEF_ICON_COLOR(BRUSH_ROTATE)
DEF_ICON_COLOR(BRUSH_VCOL_BOUNDARY)
DEF_ICON_COLOR(BRUSH_PAINT)
DEF_ICON_COLOR(BRUSH_SCULPT_SMEAR)
/* grease pencil sculpt */
DEF_ICON_COLOR(GPBRUSH_SMOOTH)

View File

@ -161,10 +161,10 @@ static SculptVertRef sculpt_boundary_get_closest_boundary_vertex(
static int BOUNDARY_INDICES_BLOCK_SIZE = 300;
static void sculpt_boundary_index_add(SculptSession *ss,
SculptBoundary *boundary,
const SculptVertRef new_index,
const float distance,
GSet *included_vertices)
SculptBoundary *boundary,
const SculptVertRef new_index,
const float distance,
GSet *included_vertices)
{
boundary->vertices[boundary->num_vertices] = new_index;
@ -346,9 +346,9 @@ static void sculpt_boundary_indices_init(SculptSession *ss,
* the closest one.
*/
static void sculpt_boundary_edit_data_init(SculptSession *ss,
SculptBoundary *boundary,
const SculptVertRef initial_vertex,
const float radius)
SculptBoundary *boundary,
const SculptVertRef initial_vertex,
const float radius)
{
const int totvert = SCULPT_vertex_count_get(ss);
@ -559,7 +559,7 @@ SculptBoundary *SCULPT_boundary_data_init(Object *object,
return NULL;
}
// XXX
// XXX force update of BMVert->head.index
if (ss->bm) {
ss->bm->elem_index_dirty |= BM_VERT;
}
@ -648,24 +648,6 @@ static void sculpt_boundary_bend_data_init(SculptSession *ss, SculptBoundary *bo
SCULPT_vertex_co_get(ss, boundary->edit_info[i].original_vertex),
SCULPT_vertex_co_get(ss, vertex));
#if 0
/*strategy to increase accuracy for non-quad topologies:
use principle curvature direction. Since SCULPT_curvature_dir_get
can also be somewhat noisy we average it with dir.
*/
float cdir[3];
SCULPT_curvature_dir_get(ss, vertex, cdir);
normalize_v3(dir);
normalize_v3(cdir);
if (dot_v3v3(dir, cdir) < 0.0f) {
negate_v3(cdir);
}
add_v3_v3(dir, cdir);
#endif
cross_v3_v3v3(boundary->bend.pivot_rotation_axis[boundary->edit_info[i].original_vertex_i],
dir,
normal);
@ -772,10 +754,10 @@ static void sculpt_boundary_bend_data_init(SculptSession *ss, SculptBoundary *bo
SculptVertRef vertex = BKE_pbvh_table_index_to_vertex(ss->pbvh, i);
const float *co = SCULPT_vertex_co_get(ss, vertex);
//boundary->bend.pivot_positions[i][0] = co[0];
//boundary->bend.pivot_positions[i][1] = co[1];
//boundary->bend.pivot_positions[i][2] = co[2];
//boundary->bend.pivot_positions[i][3] = 0.0f;
// boundary->bend.pivot_positions[i][0] = co[0];
// boundary->bend.pivot_positions[i][1] = co[1];
// boundary->bend.pivot_positions[i][2] = co[2];
// boundary->bend.pivot_positions[i][3] = 0.0f;
}
}

View File

@ -136,7 +136,7 @@ const EnumPropertyItem rna_enum_brush_sculpt_tool_items[] = {
{SCULPT_TOOL_DISPLACEMENT_ERASER, "DISPLACEMENT_ERASER", ICON_BRUSH_SCULPT_DRAW, "Multires Displacement Eraser", ""},
{SCULPT_TOOL_DISPLACEMENT_SMEAR, "DISPLACEMENT_SMEAR", ICON_BRUSH_SCULPT_DRAW, "Multires Displacement Smear", ""},
{SCULPT_TOOL_PAINT, "PAINT", ICON_BRUSH_PAINT, "Paint", ""},
{SCULPT_TOOL_SMEAR, "SMEAR", ICON_BRUSH_SCULPT_DRAW, "Smear", ""},
{SCULPT_TOOL_SMEAR, "SMEAR", ICON_BRUSH_SCULPT_SMEAR, "Smear", ""},
{SCULPT_TOOL_DRAW_FACE_SETS, "DRAW_FACE_SETS", ICON_BRUSH_MASK, "Draw Face Sets", ""},
{SCULPT_TOOL_VCOL_BOUNDARY, "VCOL_BOUNDARY", ICON_BRUSH_VCOL_BOUNDARY, "Sharpen Color Boundary", ""},
{0, NULL, 0, NULL, NULL},