1
1

Compare commits

...

37 Commits

Author SHA1 Message Date
a2ed635a73 Fix typo and change .enabled to .active 2017-02-18 04:12:29 -02:00
b3aead8fd7 Use parenthesis for bit shifts 2017-02-14 18:13:08 -02:00
733b5b8c66 Remove unused weight_components 2017-02-14 18:13:08 -02:00
5a17cb4c08 Use poll callback to disable bind operator instead of Python 2017-02-14 18:13:08 -02:00
e5e44c01f2 icon 2017-02-06 01:23:18 -02:00
a3e32e2ab5 Review: Multithread deform code 2017-01-25 04:05:53 -02:00
e843f42e66 Review: Cleanup 2017-01-25 04:05:52 -02:00
96f6ec07fb Review: Add infinite weight flags enum 2017-01-25 04:05:52 -02:00
c38e19ca67 Review: Move stuff to helper func and more cleanup 2017-01-25 04:05:52 -02:00
96d66c7e4d Review: Optimize numpoly calculation 2017-01-25 04:05:52 -02:00
46821f072d Review: Join allocations and some bpoly refactor 2017-01-25 04:05:52 -02:00
f870343208 Review: Combine allocations and minor cleanup 2017-01-25 04:05:52 -02:00
cf1a7e3944 Review: Report errors in UI and some more cleanup 2017-01-25 04:05:52 -02:00
cf660b2a02 Review: Fix depsgraph relation 2017-01-25 04:05:52 -02:00
6f3957770d Review: Fix indentations and use MEM_SAFE_FREE 2017-01-25 04:05:52 -02:00
7608f366c7 Review: Replace weight_components with individual variables 2017-01-25 04:05:52 -02:00
8c220c57f9 Review: More cleanup... 2017-01-25 04:05:52 -02:00
a300f80043 Review: Inline loop indices
Also fixed endian switch sign, and UI Python thingy...
2017-01-25 04:05:52 -02:00
22ce298d73 General cleanup (unsigned stuff and loop counter inlining) 2017-01-15 16:54:46 -02:00
3469aa47c1 Remove warnings 2017-01-15 16:54:46 -02:00
097a560bc9 Fix silly mistake in nearestVert 2017-01-15 16:54:45 -02:00
1b7623fc06 Change angle function calls in sdef 2017-01-14 01:51:55 -02:00
c546256563 Change angle function call in 3d to 2d mapping function 2017-01-14 01:51:55 -02:00
5c263a9050 Split interp_weights_face_v3 into specific functions for tris and quads 2017-01-11 15:52:52 -02:00
8745cd825a Remove custom weight interp func in favor of Blender's built-in implementation 2017-01-11 15:52:32 -02:00
28622ae81e Fix VS 2015 issue (change isnanf to isnan) 2017-01-11 13:05:53 -02:00
d6c7163c06 Fix 2d mapping function's name 2017-01-11 03:59:30 -02:00
0bb57759ec Replace "cent" functions from math_geom with "mid" ones from math_vector 2017-01-10 20:29:22 -02:00
5e1d438d5e Constify some stuff (for clarity and correctness) 2017-01-10 16:42:34 -02:00
0721bc0ac4 Silly const mistake (missed in refactor...) 2017-01-03 20:02:49 -02:00
7ca0894a17 Implement target poly influence interpolation 2017-01-03 19:27:08 -02:00
751496437b Add 3d to 2d plane mapping functions to math lib 2017-01-03 19:26:03 -02:00
3014601f3b Fix out of bounds memory access in interp_weights_face_v3
interp_weights_face_v3 required a length four array for weights even when
calculating weights for a tri, otherwise, it would access unkown memory.
This fix allows a weight array of size three to be passed when only
calculating tri weights.
2017-01-03 19:22:08 -02:00
b80971ce10 Initial Surface Deform Modifier implementation 2016-11-29 23:04:40 -02:00
68f5ce194b Add cent_poly_v3 function 2016-11-27 00:44:48 -02:00
1e9003aea5 Add is_poly_convex_v3 function 2016-11-25 14:56:09 -02:00
95701b0b04 Fix (unreported) looptri array not being recalculated in ccgDM and emDM
In ccgDM and emDM, looptri array recalculation was being handled
directly by `*DM_getLoopTriArray` (`getLoopTriArray` callback), while
`*DM_recalcLoopTri` (`recalcLoopTri` callback) was doing nothing.

This results in the array not being recalculated when other functions
that depend on the array data are called. These functions, such as
`getNumLoopTris`, call `recalcLoopTri` to ensure the data is up to date,
but in the case of CCGDerivedMesh that was doing nothing.

This moves all the recalculation code to `ccgDM_recalcLoopTri` and makes
`ccgDM_getLoopTriArray` call that.

Reviewed By: mont29

Differential Revision: https://developer.blender.org/D2375
2016-11-25 14:49:58 -02:00
28 changed files with 1599 additions and 171 deletions

View File

@@ -947,6 +947,20 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel):
def SURFACE(self, layout, ob, md):
layout.label(text="Settings are inside the Physics tab")
def SURFACE_DEFORM(self, layout, ob, md):
col = layout.column()
col.active = not md.is_bound
col.prop(md, "target")
col.prop(md, "falloff")
layout.separator()
if md.is_bound:
layout.operator("object.surfacedeform_bind", text="Unbind")
else:
layout.operator("object.surfacedeform_bind", text="Bind")
def UV_PROJECT(self, layout, ob, md):
split = layout.split()

View File

@@ -230,6 +230,7 @@ static MPoly *dm_dupPolyArray(DerivedMesh *dm)
static int dm_getNumLoopTri(DerivedMesh *dm)
{
DM_ensure_looptri(dm);
return dm->looptris.num;
}

View File

@@ -1014,7 +1014,7 @@ static bool cloth_points_collision_response_static(ClothModifierData *clmd, Coll
}
BLI_INLINE bool cloth_point_face_collision_params(const float p1[3], const float p2[3], const float v0[3], const float v1[3], const float v2[3],
float r_nor[3], float *r_lambda, float r_w[4])
float r_nor[3], float *r_lambda, float r_w[3])
{
float edge1[3], edge2[3], p2face[3], p1p2[3], v0p2[3];
float nor_v0p2, nor_p1p2;
@@ -1026,7 +1026,7 @@ BLI_INLINE bool cloth_point_face_collision_params(const float p1[3], const float
nor_v0p2 = dot_v3v3(v0p2, r_nor);
madd_v3_v3v3fl(p2face, p2, r_nor, -nor_v0p2);
interp_weights_face_v3(r_w, v0, v1, v2, NULL, p2face);
interp_weights_tri_v3(r_w, v0, v1, v2, p2face);
sub_v3_v3v3(p1p2, p2, p1);
sub_v3_v3v3(v0p2, p2, v0);
@@ -1085,7 +1085,7 @@ static CollPair *cloth_point_collpair(
const float *co1 = mverts[bp1].co, *co2 = mverts[bp2].co, *co3 = mverts[bp3].co;
float lambda /*, distance1 */, distance2;
float facenor[3], v1p1[3], v1p2[3];
float w[4];
float w[3];
if (!cloth_point_face_collision_params(p1, p2, co1, co2, co3, facenor, &lambda, w))
return collpair;

View File

@@ -3739,7 +3739,7 @@ static void dynamic_paint_paint_mesh_cell_point_cb_ex(
/* velocity brush, only do on main sample */
if (brush->flags & MOD_DPAINT_USES_VELOCITY && ss == 0 && brushVelocity) {
float weights[4];
float weights[3];
float brushPointVelocity[3];
float velocity[3];
@@ -3748,7 +3748,7 @@ static void dynamic_paint_paint_mesh_cell_point_cb_ex(
const int v3 = mloop[mlooptri[hitTri].tri[2]].v;
/* calculate barycentric weights for hit point */
interp_weights_face_v3(weights, mvert[v1].co, mvert[v2].co, mvert[v3].co, NULL, hitCoord);
interp_weights_tri_v3(weights, mvert[v1].co, mvert[v2].co, mvert[v3].co, hitCoord);
/* simple check based on brush surface velocity,
* todo: perhaps implement something that handles volume movement as well */

View File

@@ -621,10 +621,33 @@ static void emDM_recalcTessellation(DerivedMesh *UNUSED(dm))
/* do nothing */
}
static void emDM_recalcLoopTri(DerivedMesh *UNUSED(dm))
static void emDM_recalcLoopTri(DerivedMesh *dm)
{
/* Nothing to do: emDM tessellation is known,
* allocate and fill in with emDM_getLoopTriArray */
EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
BMLoop *(*looptris)[3] = bmdm->em->looptris;
MLoopTri *mlooptri;
const int tottri = bmdm->em->tottri;
int i;
DM_ensure_looptri_data(dm);
mlooptri = dm->looptris.array;
BLI_assert(poly_to_tri_count(dm->numPolyData, dm->numLoopData) == dm->looptris.num);
BLI_assert(tottri == dm->looptris.num);
BM_mesh_elem_index_ensure(bmdm->em->bm, BM_FACE | BM_LOOP);
for (i = 0; i < tottri; i++) {
BMLoop **ltri = looptris[i];
MLoopTri *lt = &mlooptri[i];
ARRAY_SET_ITEMS(
lt->tri,
BM_elem_index_get(ltri[0]),
BM_elem_index_get(ltri[1]),
BM_elem_index_get(ltri[2]));
lt->poly = BM_elem_index_get(ltri[0]->f);
}
}
static const MLoopTri *emDM_getLoopTriArray(DerivedMesh *dm)
@@ -633,32 +656,9 @@ static const MLoopTri *emDM_getLoopTriArray(DerivedMesh *dm)
BLI_assert(poly_to_tri_count(dm->numPolyData, dm->numLoopData) == dm->looptris.num);
}
else {
EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
BMLoop *(*looptris)[3] = bmdm->em->looptris;
MLoopTri *mlooptri;
const int tottri = bmdm->em->tottri;
int i;
DM_ensure_looptri_data(dm);
mlooptri = dm->looptris.array;
BLI_assert(poly_to_tri_count(dm->numPolyData, dm->numLoopData) == dm->looptris.num);
BLI_assert(tottri == dm->looptris.num);
BM_mesh_elem_index_ensure(bmdm->em->bm, BM_FACE | BM_LOOP);
for (i = 0; i < tottri; i++) {
BMLoop **ltri = looptris[i];
MLoopTri *lt = &mlooptri[i];
ARRAY_SET_ITEMS(
lt->tri,
BM_elem_index_get(ltri[0]),
BM_elem_index_get(ltri[1]),
BM_elem_index_get(ltri[2]));
lt->poly = BM_elem_index_get(ltri[0]->f);
}
dm->recalcLoopTri(dm);
}
return dm->looptris.array;
}

View File

@@ -1909,19 +1909,19 @@ void BKE_mesh_calc_poly_center(
const MVert *mvarray, float r_cent[3])
{
if (mpoly->totloop == 3) {
cent_tri_v3(r_cent,
mvarray[loopstart[0].v].co,
mvarray[loopstart[1].v].co,
mvarray[loopstart[2].v].co
);
mid_v3_v3v3v3(r_cent,
mvarray[loopstart[0].v].co,
mvarray[loopstart[1].v].co,
mvarray[loopstart[2].v].co
);
}
else if (mpoly->totloop == 4) {
cent_quad_v3(r_cent,
mvarray[loopstart[0].v].co,
mvarray[loopstart[1].v].co,
mvarray[loopstart[2].v].co,
mvarray[loopstart[3].v].co
);
mid_v3_v3v3v3v3(r_cent,
mvarray[loopstart[0].v].co,
mvarray[loopstart[1].v].co,
mvarray[loopstart[2].v].co,
mvarray[loopstart[3].v].co
);
}
else {
mesh_calc_ngon_center(mpoly, loopstart, mvarray, r_cent);
@@ -1978,7 +1978,7 @@ static float mesh_calc_poly_planar_area_centroid(
tri_area = area_tri_signed_v3(v1, v2, v3, normal);
total_area += tri_area;
cent_tri_v3(tri_cent, v1, v2, v3);
mid_v3_v3v3v3(tri_cent, v1, v2, v3);
madd_v3_v3fl(r_cent, tri_cent, tri_area);
copy_v3_v3(v2, v3);

View File

@@ -758,15 +758,14 @@ static void obstacles_from_derivedmesh_task_cb(void *userdata, const int z)
/* find the nearest point on the mesh */
if (BLI_bvhtree_find_nearest(data->tree->tree, ray_start, &nearest, data->tree->nearest_callback, data->tree) != -1) {
const MLoopTri *lt = &data->looptri[nearest.index];
float weights[4];
float weights[3];
int v1, v2, v3;
/* calculate barycentric weights for nearest point */
v1 = data->mloop[lt->tri[0]].v;
v2 = data->mloop[lt->tri[1]].v;
v3 = data->mloop[lt->tri[2]].v;
interp_weights_face_v3(
weights, data->mvert[v1].co, data->mvert[v2].co, data->mvert[v3].co, NULL, nearest.co);
interp_weights_tri_v3(weights, data->mvert[v1].co, data->mvert[v2].co, data->mvert[v3].co, nearest.co);
// DG TODO
if (data->has_velocity)
@@ -1454,7 +1453,7 @@ static void sample_derivedmesh(
/* find the nearest point on the mesh */
if (BLI_bvhtree_find_nearest(treeData->tree, ray_start, &nearest, treeData->nearest_callback, treeData) != -1) {
float weights[4];
float weights[3];
int v1, v2, v3, f_index = nearest.index;
float n1[3], n2[3], n3[3], hit_normal[3];
@@ -1471,7 +1470,7 @@ static void sample_derivedmesh(
v1 = mloop[mlooptri[f_index].tri[0]].v;
v2 = mloop[mlooptri[f_index].tri[1]].v;
v3 = mloop[mlooptri[f_index].tri[2]].v;
interp_weights_face_v3(weights, mvert[v1].co, mvert[v2].co, mvert[v3].co, NULL, nearest.co);
interp_weights_tri_v3(weights, mvert[v1].co, mvert[v2].co, mvert[v3].co, nearest.co);
if (sfs->flags & MOD_SMOKE_FLOW_INITVELOCITY && velocity_map) {
/* apply normal directional velocity */

View File

@@ -4474,46 +4474,46 @@ static void ccgDM_recalcTessellation(DerivedMesh *UNUSED(dm))
/* Nothing to do: CCG handles creating its own tessfaces */
}
static void ccgDM_recalcLoopTri(DerivedMesh *UNUSED(dm))
static void ccgDM_recalcLoopTri(DerivedMesh *dm)
{
/* Nothing to do: CCG tessellation is known,
* allocate and fill in with ccgDM_getLoopTriArray */
BLI_rw_mutex_lock(&loops_cache_rwlock, THREAD_LOCK_WRITE);
MLoopTri *mlooptri;
const int tottri = dm->numPolyData * 2;
int i, poly_index;
DM_ensure_looptri_data(dm);
mlooptri = dm->looptris.array;
BLI_assert(poly_to_tri_count(dm->numPolyData, dm->numLoopData) == dm->looptris.num);
BLI_assert(tottri == dm->looptris.num);
for (i = 0, poly_index = 0; i < tottri; i += 2, poly_index += 1) {
MLoopTri *lt;
lt = &mlooptri[i];
/* quad is (0, 3, 2, 1) */
lt->tri[0] = (poly_index * 4) + 0;
lt->tri[1] = (poly_index * 4) + 2;
lt->tri[2] = (poly_index * 4) + 3;
lt->poly = poly_index;
lt = &mlooptri[i + 1];
lt->tri[0] = (poly_index * 4) + 0;
lt->tri[1] = (poly_index * 4) + 1;
lt->tri[2] = (poly_index * 4) + 2;
lt->poly = poly_index;
}
BLI_rw_mutex_unlock(&loops_cache_rwlock);
}
static const MLoopTri *ccgDM_getLoopTriArray(DerivedMesh *dm)
{
BLI_rw_mutex_lock(&loops_cache_rwlock, THREAD_LOCK_WRITE);
if (dm->looptris.array) {
BLI_assert(poly_to_tri_count(dm->numPolyData, dm->numLoopData) == dm->looptris.num);
}
else {
MLoopTri *mlooptri;
const int tottri = dm->numPolyData * 2;
int i, poly_index;
DM_ensure_looptri_data(dm);
mlooptri = dm->looptris.array;
BLI_assert(poly_to_tri_count(dm->numPolyData, dm->numLoopData) == dm->looptris.num);
BLI_assert(tottri == dm->looptris.num);
for (i = 0, poly_index = 0; i < tottri; i += 2, poly_index += 1) {
MLoopTri *lt;
lt = &mlooptri[i];
/* quad is (0, 3, 2, 1) */
lt->tri[0] = (poly_index * 4) + 0;
lt->tri[1] = (poly_index * 4) + 2;
lt->tri[2] = (poly_index * 4) + 3;
lt->poly = poly_index;
lt = &mlooptri[i + 1];
lt->tri[0] = (poly_index * 4) + 0;
lt->tri[1] = (poly_index * 4) + 1;
lt->tri[2] = (poly_index * 4) + 2;
lt->poly = poly_index;
}
dm->recalcLoopTri(dm);
}
BLI_rw_mutex_unlock(&loops_cache_rwlock);
return dm->looptris.array;
}

View File

@@ -44,9 +44,6 @@ extern "C" {
/********************************** Polygons *********************************/
void cent_tri_v3(float r[3], const float a[3], const float b[3], const float c[3]);
void cent_quad_v3(float r[3], const float a[3], const float b[3], const float c[3], const float d[3]);
float normal_tri_v3(float r[3], const float a[3], const float b[3], const float c[3]);
float normal_quad_v3(float r[3], const float a[3], const float b[3], const float c[3], const float d[3]);
float normal_poly_v3(float r[3], const float verts[][3], unsigned int nr);
@@ -85,6 +82,7 @@ float volume_tetrahedron_v3(const float v1[3], const float v2[3], const float v3
float volume_tetrahedron_signed_v3(const float v1[3], const float v2[3], const float v3[3], const float v4[3]);
bool is_quad_convex_v3(const float v1[3], const float v2[3], const float v3[3], const float v4[3]);
bool is_poly_convex_v3(const float verts[][3], unsigned int nr);
bool is_quad_convex_v2(const float v1[2], const float v2[2], const float v3[2], const float v4[2]);
bool is_poly_convex_v2(const float verts[][2], unsigned int nr);
int is_quad_flip_v3(const float v1[3], const float v2[3], const float v3[3], const float v4[3]);
@@ -326,10 +324,8 @@ bool clip_segment_v3_plane_n(
float r_p1[3], float r_p2[3]);
/****************************** Interpolation ********************************/
/* tri or quad, d can be NULL */
void interp_weights_face_v3(float w[4],
const float a[3], const float b[3], const float c[3], const float d[3], const float p[3]);
void interp_weights_tri_v3(float w[3], const float a[3], const float b[3], const float c[3], const float p[3]);
void interp_weights_quad_v3(float w[4], const float a[3], const float b[3], const float c[3], const float d[3], const float p[3]);
void interp_weights_poly_v3(float w[], float v[][3], const int n, const float co[3]);
void interp_weights_poly_v2(float w[], float v[][2], const int n, const float co[2]);
@@ -394,6 +390,8 @@ void box_minmax_bounds_m4(float min[3], float max[3],
void map_to_tube(float *r_u, float *r_v, const float x, const float y, const float z);
void map_to_sphere(float *r_u, float *r_v, const float x, const float y, const float z);
void map_to_plane_v2_v3v3(float r_co[2], const float co[3], const float no[3]);
void map_to_plane_axis_angle_v2_v3v3fl(float r_co[2], const float co[3], const float axis[3], const float angle);
/********************************** Normals **********************************/

View File

@@ -234,6 +234,7 @@ void mid_v3_v3v3(float r[3], const float a[3], const float b[3]);
void mid_v2_v2v2(float r[2], const float a[2], const float b[2]);
void mid_v3_v3v3v3(float v[3], const float v1[3], const float v2[3], const float v3[3]);
void mid_v3_v3v3v3v3(float v[3], const float v1[3], const float v2[3], const float v3[3], const float v4[3]);
void mid_v3_v3_array(float r[3], const float (*vec_arr)[3], const unsigned int nbr);
void mid_v3_v3v3_angle_weighted(float r[3], const float a[3], const float b[3]);
void mid_v3_angle_weighted(float r[3]);

View File

@@ -37,20 +37,6 @@
/********************************** Polygons *********************************/
void cent_tri_v3(float cent[3], const float v1[3], const float v2[3], const float v3[3])
{
cent[0] = (v1[0] + v2[0] + v3[0]) / 3.0f;
cent[1] = (v1[1] + v2[1] + v3[1]) / 3.0f;
cent[2] = (v1[2] + v2[2] + v3[2]) / 3.0f;
}
void cent_quad_v3(float cent[3], const float v1[3], const float v2[3], const float v3[3], const float v4[3])
{
cent[0] = 0.25f * (v1[0] + v2[0] + v3[0] + v4[0]);
cent[1] = 0.25f * (v1[1] + v2[1] + v3[1] + v4[1]);
cent[2] = 0.25f * (v1[2] + v2[2] + v3[2] + v4[2]);
}
void cross_tri_v3(float n[3], const float v1[3], const float v2[3], const float v3[3])
{
float n1[3], n2[3];
@@ -2964,7 +2950,15 @@ static bool barycentric_weights(const float v1[3], const float v2[3], const floa
}
}
void interp_weights_face_v3(float w[4], const float v1[3], const float v2[3], const float v3[3], const float v4[3], const float co[3])
void interp_weights_tri_v3(float w[3], const float v1[3], const float v2[3], const float v3[3], const float co[3])
{
float n[3];
normal_tri_v3(n, v1, v2, v3);
barycentric_weights(v1, v2, v3, co, n, w);
}
void interp_weights_quad_v3(float w[4], const float v1[3], const float v2[3], const float v3[3], const float v4[3], const float co[3])
{
float w2[3];
@@ -2977,7 +2971,7 @@ void interp_weights_face_v3(float w[4], const float v1[3], const float v2[3], co
w[1] = 1.0f;
else if (equals_v3v3(co, v3))
w[2] = 1.0f;
else if (v4 && equals_v3v3(co, v4))
else if (equals_v3v3(co, v4))
w[3] = 1.0f;
else {
/* otherwise compute barycentric interpolation weights */
@@ -2985,35 +2979,24 @@ void interp_weights_face_v3(float w[4], const float v1[3], const float v2[3], co
bool degenerate;
sub_v3_v3v3(n1, v1, v3);
if (v4) {
sub_v3_v3v3(n2, v2, v4);
}
else {
sub_v3_v3v3(n2, v2, v3);
}
sub_v3_v3v3(n2, v2, v4);
cross_v3_v3v3(n, n1, n2);
/* OpenGL seems to split this way, so we do too */
if (v4) {
degenerate = barycentric_weights(v1, v2, v4, co, n, w);
SWAP(float, w[2], w[3]);
degenerate = barycentric_weights(v1, v2, v4, co, n, w);
SWAP(float, w[2], w[3]);
if (degenerate || (w[0] < 0.0f)) {
/* if w[1] is negative, co is on the other side of the v1-v3 edge,
* so we interpolate using the other triangle */
degenerate = barycentric_weights(v2, v3, v4, co, n, w2);
if (degenerate || (w[0] < 0.0f)) {
/* if w[1] is negative, co is on the other side of the v1-v3 edge,
* so we interpolate using the other triangle */
degenerate = barycentric_weights(v2, v3, v4, co, n, w2);
if (!degenerate) {
w[0] = 0.0f;
w[1] = w2[0];
w[2] = w2[1];
w[3] = w2[2];
}
if (!degenerate) {
w[0] = 0.0f;
w[1] = w2[0];
w[2] = w2[1];
w[3] = w2[2];
}
}
else {
barycentric_weights(v1, v2, v3, co, n, w);
}
}
}
@@ -4060,6 +4043,26 @@ void map_to_sphere(float *r_u, float *r_v, const float x, const float y, const f
}
}
void map_to_plane_v2_v3v3(float r_co[2], const float co[3], const float no[3])
{
float target[3] = {0.0f, 0.0f, 1.0f};
float axis[3];
cross_v3_v3v3(axis, no, target);
normalize_v3(axis);
map_to_plane_axis_angle_v2_v3v3fl(r_co, co, axis, angle_normalized_v3v3(no, target));
}
void map_to_plane_axis_angle_v2_v3v3fl(float r_co[2], const float co[3], const float axis[3], const float angle)
{
float tmp[3];
rotate_normalized_v3_v3v3fl(tmp, co, axis, angle);
copy_v2_v2(r_co, tmp);
}
/********************************* Normals **********************************/
void accumulate_vertex_normals_tri(
@@ -4791,54 +4794,56 @@ float form_factor_hemi_poly(float p[3], float n[3], float v1[3], float v2[3], fl
*/
bool is_quad_convex_v3(const float v1[3], const float v2[3], const float v3[3], const float v4[3])
{
const float verts[4][3] = {{UNPACK3(v1)}, {UNPACK3(v2)}, {UNPACK3(v3)}, {UNPACK3(v4)}};
return is_poly_convex_v3(verts, 4);
}
/**
* Check if polygon is convex
*/
bool is_poly_convex_v3(const float verts[][3], unsigned int nr)
{
const float *co_curr, *co_prev;
float vec_curr[3], vec_prev[3];
float normal[3];
unsigned int i;
if (nr == 3)
return true;
co_prev = verts[nr - 1];
co_curr = verts[0];
/* Non-unit length normal, just to check angle directions */
cross_poly_v3(normal, verts, nr);
sub_v3_v3v3(vec_prev, co_prev, verts[nr - 2]);
/**
* Method projects points onto a plane and checks its convex using following method:
*
* - Create a plane from the cross-product of both diagonal vectors.
* - Project all points onto the plane.
* - Subtract for direction vectors.
* - Return true if all corners cross-products point the direction of the plane.
* Implementation note: there is no need to project the vertices onto the normal plane,
* because even if the polygon is highly non-planar, the cross product between
* adjacent edges will always point to the same side as the normal when convex,
* and to the opposite side when concave.
*/
/* non-unit length normal, used as a projection plane */
float plane[3];
for (i = 0; i < nr; i++) {
float cross[3];
{
float v13[3], v24[3];
sub_v3_v3v3(vec_curr, co_curr, co_prev);
sub_v3_v3v3(v13, v1, v3);
sub_v3_v3v3(v24, v2, v4);
cross_v3_v3v3(cross, vec_prev, vec_curr);
cross_v3_v3v3(plane, v13, v24);
if (len_squared_v3(plane) < FLT_EPSILON) {
if (dot_v3v3(cross, normal) < 0.0f) {
return false;
}
copy_v3_v3(vec_prev, vec_curr);
co_prev = co_curr;
co_curr += 3;
}
const float *quad_coords[4] = {v1, v2, v3, v4};
float quad_proj[4][3];
for (int i = 0; i < 4; i++) {
project_plane_v3_v3v3(quad_proj[i], quad_coords[i], plane);
}
float quad_dirs[4][3];
for (int i = 0, j = 3; i < 4; j = i++) {
sub_v3_v3v3(quad_dirs[i], quad_proj[i], quad_proj[j]);
}
float test_dir[3];
#define CROSS_SIGN(dir_a, dir_b) \
((void)cross_v3_v3v3(test_dir, dir_a, dir_b), (dot_v3v3(plane, test_dir) > 0.0f))
return (CROSS_SIGN(quad_dirs[0], quad_dirs[1]) &&
CROSS_SIGN(quad_dirs[1], quad_dirs[2]) &&
CROSS_SIGN(quad_dirs[2], quad_dirs[3]) &&
CROSS_SIGN(quad_dirs[3], quad_dirs[0]));
#undef CROSS_SIGN
return true;
}
bool is_quad_convex_v2(const float v1[2], const float v2[2], const float v3[2], const float v4[2])

View File

@@ -280,6 +280,16 @@ void mid_v3_v3v3v3v3(float v[3], const float v1[3], const float v2[3], const flo
v[2] = (v1[2] + v2[2] + v3[2] + v4[2]) / 4.0f;
}
void mid_v3_v3_array(float r[3], const float (*vec_arr)[3], const unsigned int nbr)
{
const float factor = 1.0f / (float)nbr;
zero_v3(r);
for (unsigned int i = 0; i < nbr; i++) {
madd_v3_v3fl(r, vec_arr[i], factor);
}
}
/**
* Specialized function for calculating normals.
* fastpath for:

View File

@@ -5302,6 +5302,37 @@ static void direct_link_modifiers(FileData *fd, ListBase *lb)
csmd->delta_cache = NULL;
csmd->delta_cache_num = 0;
}
else if (md->type == eModifierType_SurfaceDeform) {
SurfaceDeformModifierData *smd = (SurfaceDeformModifierData *)md;
smd->verts = newdataadr(fd, smd->verts);
if (smd->verts) {
for (int i = 0; i < smd->numverts; i++) {
smd->verts[i].binds = newdataadr(fd, smd->verts[i].binds);
if (smd->verts[i].binds) {
for (int j = 0; j < smd->verts[i].numbinds; j++) {
smd->verts[i].binds[j].vert_inds = newdataadr(fd, smd->verts[i].binds[j].vert_inds);
smd->verts[i].binds[j].vert_weights = newdataadr(fd, smd->verts[i].binds[j].vert_weights);
if (fd->flags & FD_FLAGS_SWITCH_ENDIAN) {
if (smd->verts[i].binds[j].vert_inds)
BLI_endian_switch_uint32_array(smd->verts[i].binds[j].vert_inds, smd->verts[i].binds[j].numverts);
if (smd->verts[i].binds[j].vert_weights) {
if (smd->verts[i].binds[j].mode == MOD_SDEF_MODE_CENTROID ||
smd->verts[i].binds[j].mode == MOD_SDEF_MODE_LOOPTRI)
BLI_endian_switch_float_array(smd->verts[i].binds[j].vert_weights, 3);
else
BLI_endian_switch_float_array(smd->verts[i].binds[j].vert_weights, smd->verts[i].binds[j].numverts);
}
}
}
}
}
}
}
}
}

View File

@@ -1830,6 +1830,32 @@ static void write_modifiers(WriteData *wd, ListBase *modbase)
writedata(wd, DATA, sizeof(float[3]) * csmd->bind_coords_num, csmd->bind_coords);
}
}
else if (md->type == eModifierType_SurfaceDeform) {
SurfaceDeformModifierData *smd = (SurfaceDeformModifierData *)md;
writestruct(wd, DATA, SDefVert, smd->numverts, smd->verts);
if (smd->verts) {
for (int i = 0; i < smd->numverts; i++) {
writestruct(wd, DATA, SDefBind, smd->verts[i].numbinds, smd->verts[i].binds);
if (smd->verts[i].binds) {
for (int j = 0; j < smd->verts[i].numbinds; j++) {
writedata(wd, DATA, sizeof(int) * smd->verts[i].binds[j].numverts, smd->verts[i].binds[j].vert_inds);
if (smd->verts[i].binds[j].mode == MOD_SDEF_MODE_CENTROID ||
smd->verts[i].binds[j].mode == MOD_SDEF_MODE_LOOPTRI)
{
writedata(wd, DATA, sizeof(float) * 3, smd->verts[i].binds[j].vert_weights);
}
else {
writedata(wd, DATA, sizeof(float) * smd->verts[i].binds[j].numverts, smd->verts[i].binds[j].vert_weights);
}
}
}
}
}
}
}
}

View File

@@ -339,7 +339,7 @@ static bool mdisp_in_mdispquad(
compute_mdisp_quad(l_dst, l_dst_f_center, v1, v2, v3, v4, e1, e2);
/* expand quad a bit */
cent_quad_v3(c, v1, v2, v3, v4);
mid_v3_v3v3v3v3(c, v1, v2, v3, v4);
sub_v3_v3(v1, c); sub_v3_v3(v2, c);
sub_v3_v3(v3, c); sub_v3_v3(v4, c);

View File

@@ -186,6 +186,7 @@ void OBJECT_OT_skin_loose_mark_clear(struct wmOperatorType *ot);
void OBJECT_OT_skin_radii_equalize(struct wmOperatorType *ot);
void OBJECT_OT_skin_armature_create(struct wmOperatorType *ot);
void OBJECT_OT_laplaciandeform_bind(struct wmOperatorType *ot);
void OBJECT_OT_surfacedeform_bind(struct wmOperatorType *ot);
/* object_constraint.c */
void OBJECT_OT_constraint_add(struct wmOperatorType *ot);

View File

@@ -2294,3 +2294,63 @@ void OBJECT_OT_laplaciandeform_bind(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
edit_modifier_properties(ot);
}
/************************ sdef bind operator *********************/
static int surfacedeform_bind_poll(bContext *C)
{
if (edit_modifier_poll_generic(C, &RNA_SurfaceDeformModifier, 0)) {
PointerRNA ptr = CTX_data_pointer_get_type(C, "modifier", &RNA_SurfaceDeformModifier);
SurfaceDeformModifierData *smd = (SurfaceDeformModifierData *)ptr.data;
return ((smd != NULL) && (smd->target != NULL));
}
return 0;
}
static int surfacedeform_bind_exec(bContext *C, wmOperator *op)
{
Object *ob = ED_object_active_context(C);
SurfaceDeformModifierData *smd = (SurfaceDeformModifierData *)edit_modifier_property_get(op, ob, eModifierType_SurfaceDeform);
if (!smd)
return OPERATOR_CANCELLED;
if (smd->flags & MOD_SDEF_BIND) {
smd->flags &= ~MOD_SDEF_BIND;
}
else if (smd->target) {
smd->flags |= MOD_SDEF_BIND;
}
DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
return OPERATOR_FINISHED;
}
static int surfacedeform_bind_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
if (edit_modifier_invoke_properties(C, op))
return surfacedeform_bind_exec(C, op);
else
return OPERATOR_CANCELLED;
}
void OBJECT_OT_surfacedeform_bind(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Surface Deform Bind";
ot->description = "Bind mesh to target in surface deform modifier";
ot->idname = "OBJECT_OT_surfacedeform_bind";
/* api callbacks */
ot->poll = surfacedeform_bind_poll;
ot->invoke = surfacedeform_bind_invoke;
ot->exec = surfacedeform_bind_exec;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
edit_modifier_properties(ot);
}

View File

@@ -255,6 +255,7 @@ void ED_operatortypes_object(void)
WM_operatortype_append(OBJECT_OT_data_transfer);
WM_operatortype_append(OBJECT_OT_datalayout_transfer);
WM_operatortype_append(OBJECT_OT_surfacedeform_bind);
}
void ED_operatormacros_object(void)

View File

@@ -1125,6 +1125,7 @@ static void tselem_draw_icon(uiBlock *block, int xmax, float x, float y, TreeSto
case eModifierType_Cast:
UI_icon_draw(x, y, ICON_MOD_CAST); break;
case eModifierType_MeshDeform:
case eModifierType_SurfaceDeform:
UI_icon_draw(x, y, ICON_MOD_MESHDEFORM); break;
case eModifierType_Bevel:
UI_icon_draw(x, y, ICON_MOD_BEVEL); break;

View File

@@ -86,6 +86,7 @@ typedef enum ModifierType {
eModifierType_NormalEdit = 50,
eModifierType_CorrectiveSmooth = 51,
eModifierType_MeshSequenceCache = 52,
eModifierType_SurfaceDeform = 53,
NUM_MODIFIER_TYPES
} ModifierType;
@@ -1570,6 +1571,45 @@ enum {
MOD_MESHSEQ_READ_COLOR = (1 << 3),
};
typedef struct SDefBind {
unsigned int *vert_inds;
unsigned int numverts;
int mode;
float *vert_weights;
float normal_dist;
float influence;
} SDefBind;
typedef struct SDefVert {
SDefBind *binds;
unsigned int numbinds;
char pad[4];
} SDefVert;
typedef struct SurfaceDeformModifierData {
ModifierData modifier;
struct Object *target; /* bind target object */
SDefVert *verts; /* vertex bind data */
float falloff;
unsigned int numverts, numpoly;
int flags;
} SurfaceDeformModifierData;
/* Surface Deform modifier flags */
enum {
MOD_SDEF_BIND = (1 << 0),
MOD_SDEF_USES_LOOPTRI = (1 << 1),
MOD_SDEF_HAS_CONCAVE = (1 << 2),
};
/* Surface Deform vertex bind modes */
enum {
MOD_SDEF_MODE_LOOPTRI = 0,
MOD_SDEF_MODE_NGON = 1,
MOD_SDEF_MODE_CENTROID = 2,
};
#define MOD_MESHSEQ_READ_ALL \
(MOD_MESHSEQ_READ_VERT | MOD_MESHSEQ_READ_POLY | MOD_MESHSEQ_READ_UV | MOD_MESHSEQ_READ_COLOR)

View File

@@ -597,6 +597,7 @@ extern StructRNA RNA_StucciTexture;
extern StructRNA RNA_SubsurfModifier;
extern StructRNA RNA_SunLamp;
extern StructRNA RNA_SurfaceCurve;
extern StructRNA RNA_SurfaceDeformModifier;
extern StructRNA RNA_SurfaceModifier;
extern StructRNA RNA_TexMapping;
extern StructRNA RNA_Text;

View File

@@ -105,6 +105,7 @@ EnumPropertyItem rna_enum_object_modifier_type_items[] = {
{eModifierType_Shrinkwrap, "SHRINKWRAP", ICON_MOD_SHRINKWRAP, "Shrinkwrap", ""},
{eModifierType_SimpleDeform, "SIMPLE_DEFORM", ICON_MOD_SIMPLEDEFORM, "Simple Deform", ""},
{eModifierType_Smooth, "SMOOTH", ICON_MOD_SMOOTH, "Smooth", ""},
{eModifierType_SurfaceDeform, "SURFACE_DEFORM", ICON_MOD_MESHDEFORM, "Surface Deform", ""},
{eModifierType_Warp, "WARP", ICON_MOD_WARP, "Warp", ""},
{eModifierType_Wave, "WAVE", ICON_MOD_WAVE, "Wave", ""},
{0, "", 0, N_("Simulate"), ""},
@@ -408,6 +409,8 @@ static StructRNA *rna_Modifier_refine(struct PointerRNA *ptr)
return &RNA_CorrectiveSmoothModifier;
case eModifierType_MeshSequenceCache:
return &RNA_MeshSequenceCacheModifier;
case eModifierType_SurfaceDeform:
return &RNA_SurfaceDeformModifier;
/* Default */
case eModifierType_None:
case eModifierType_ShapeKey:
@@ -573,6 +576,7 @@ RNA_MOD_OBJECT_SET(MeshDeform, object, OB_MESH);
RNA_MOD_OBJECT_SET(NormalEdit, target, OB_EMPTY);
RNA_MOD_OBJECT_SET(Shrinkwrap, target, OB_MESH);
RNA_MOD_OBJECT_SET(Shrinkwrap, auxTarget, OB_MESH);
RNA_MOD_OBJECT_SET(SurfaceDeform, target, OB_MESH);
static void rna_HookModifier_object_set(PointerRNA *ptr, PointerRNA value)
{
@@ -1131,6 +1135,11 @@ static int rna_CorrectiveSmoothModifier_is_bind_get(PointerRNA *ptr)
return (csmd->bind_coords != NULL);
}
static int rna_SurfaceDeformModifier_is_bound_get(PointerRNA *ptr)
{
return (((SurfaceDeformModifierData *)ptr->data)->verts != NULL);
}
static void rna_MeshSequenceCache_object_path_update(Main *bmain, Scene *scene, PointerRNA *ptr)
{
#ifdef WITH_ALEMBIC
@@ -4702,6 +4711,33 @@ static void rna_def_modifier_normaledit(BlenderRNA *brna)
RNA_def_property_update(prop, 0, "rna_Modifier_update");
}
static void rna_def_modifier_surfacedeform(BlenderRNA *brna)
{
StructRNA *srna;
PropertyRNA *prop;
srna = RNA_def_struct(brna, "SurfaceDeformModifier", "Modifier");
RNA_def_struct_ui_text(srna, "SurfaceDeform Modifier", "blablabla");
RNA_def_struct_sdna(srna, "SurfaceDeformModifierData");
RNA_def_struct_ui_icon(srna, ICON_MOD_MESHDEFORM);
prop = RNA_def_property(srna, "target", PROP_POINTER, PROP_NONE);
RNA_def_property_ui_text(prop, "Target", "Mesh object to deform with");
RNA_def_property_pointer_funcs(prop, NULL, "rna_SurfaceDeformModifier_target_set", NULL, "rna_Mesh_object_poll");
RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK);
RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update");
prop = RNA_def_property(srna, "falloff", PROP_FLOAT, PROP_NONE);
RNA_def_property_range(prop, 2.0f, 16.0f);
RNA_def_property_ui_text(prop, "Interpolation falloff", "Controls how much nearby polygons influence deformation");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
prop = RNA_def_property(srna, "is_bound", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_funcs(prop, "rna_SurfaceDeformModifier_is_bound_get", NULL);
RNA_def_property_ui_text(prop, "Bound", "Whether geometry has been bound to target mesh");
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
}
void RNA_def_modifier(BlenderRNA *brna)
{
StructRNA *srna;
@@ -4819,6 +4855,7 @@ void RNA_def_modifier(BlenderRNA *brna)
rna_def_modifier_datatransfer(brna);
rna_def_modifier_normaledit(brna);
rna_def_modifier_meshseqcache(brna);
rna_def_modifier_surfacedeform(brna);
}
#endif

View File

@@ -93,6 +93,7 @@ set(SRC
intern/MOD_solidify.c
intern/MOD_subsurf.c
intern/MOD_surface.c
intern/MOD_surfacedeform.c
intern/MOD_triangulate.c
intern/MOD_util.c
intern/MOD_uvwarp.c

View File

@@ -85,6 +85,7 @@ extern ModifierTypeInfo modifierType_DataTransfer;
extern ModifierTypeInfo modifierType_NormalEdit;
extern ModifierTypeInfo modifierType_CorrectiveSmooth;
extern ModifierTypeInfo modifierType_MeshSequenceCache;
extern ModifierTypeInfo modifierType_SurfaceDeform;
/* MOD_util.c */
void modifier_type_init(ModifierTypeInfo *types[]);

File diff suppressed because it is too large Load Diff

View File

@@ -287,5 +287,6 @@ void modifier_type_init(ModifierTypeInfo *types[])
INIT_TYPE(NormalEdit);
INIT_TYPE(CorrectiveSmooth);
INIT_TYPE(MeshSequenceCache);
INIT_TYPE(SurfaceDeform);
#undef INIT_TYPE
}

View File

@@ -5572,9 +5572,14 @@ static void calculate_speedvectors(Render *re, ObjectInstanceRen *obi, float *ve
co1= mesh->co[face[0]];
co2= mesh->co[face[1]];
co3= mesh->co[face[2]];
co4= (face[3])? mesh->co[face[3]]: NULL;
interp_weights_face_v3(w, co1, co2, co3, co4, strand->vert->co);
if (face[3]) {
co4= mesh->co[face[3]];
interp_weights_quad_v3(w, co1, co2, co3, co4, strand->vert->co);
}
else {
interp_weights_tri_v3(w, co1, co2, co3, strand->vert->co);
}
zero_v4(speed);
madd_v4_v4fl(speed, winspeed[face[0]], w[0]);

View File

@@ -329,7 +329,7 @@ static void occ_face(const OccFace *face, float co[3], float normal[3], float *a
if (vlr->v4)
mid_v3_v3v3(co, vlr->v1->co, vlr->v3->co);
else
cent_tri_v3(co, vlr->v1->co, vlr->v2->co, vlr->v3->co);
mid_v3_v3v3v3(co, vlr->v1->co, vlr->v2->co, vlr->v3->co);
if (obi->flag & R_TRANSFORMED)
mul_m4_v3(obi->mat, co);
@@ -1190,9 +1190,14 @@ static void sample_occ_surface(ShadeInput *shi)
co1 = mesh->co[face[0]];
co2 = mesh->co[face[1]];
co3 = mesh->co[face[2]];
co4 = (face[3]) ? mesh->co[face[3]] : NULL;
interp_weights_face_v3(w, co1, co2, co3, co4, strand->vert->co);
if (face[3]) {
co4 = mesh->co[face[3]];
interp_weights_quad_v3(w, co1, co2, co3, co4, strand->vert->co);
}
else {
interp_weights_tri_v3(w, co1, co2, co3, strand->vert->co);
}
zero_v3(shi->ao);
zero_v3(shi->env);
@@ -1245,7 +1250,7 @@ static void *exec_strandsurface_sample(void *data)
normal_quad_v3(n, co1, co2, co3, co4);
}
else {
cent_tri_v3(co, co1, co2, co3);
mid_v3_v3v3v3(co, co1, co2, co3);
normal_tri_v3(n, co1, co2, co3);
}
negate_v3(n);