Compare commits
60 Commits
temp-gpu-p
...
soc-2017-s
Author | SHA1 | Date | |
---|---|---|---|
![]() |
b8a14f04af | ||
![]() |
f428554df4 | ||
![]() |
0c24cb542d | ||
![]() |
c3bd1c8414 | ||
![]() |
c982e62128 | ||
![]() |
f729653f5d | ||
![]() |
5f6c7a9eb6 | ||
![]() |
6d86842dd3 | ||
![]() |
e27bacaa43 | ||
![]() |
5e1d75247d | ||
![]() |
a25577433c | ||
![]() |
664936777b | ||
![]() |
b77d3ecb5c | ||
![]() |
30d32fa602 | ||
![]() |
b0b1101716 | ||
![]() |
d0cb5c8fd9 | ||
![]() |
30aea5e13e | ||
![]() |
4c567c578a | ||
![]() |
fa86bbb054 | ||
![]() |
3ab49cae0e | ||
![]() |
8ac93b5428 | ||
![]() |
72713bddc0 | ||
![]() |
779682537e | ||
![]() |
781a7f0822 | ||
![]() |
cba8a0e1c2 | ||
![]() |
3aca62a444 | ||
![]() |
3566bb561c | ||
![]() |
5465a1ee16 | ||
![]() |
5062205b2a | ||
![]() |
d684bdd139 | ||
![]() |
473cea6f0a | ||
![]() |
8fbe4be8a5 | ||
![]() |
a09c182b34 | ||
![]() |
c416bfa757 | ||
![]() |
7c2213c00a | ||
![]() |
7e1af56fab | ||
![]() |
774de995f3 | ||
![]() |
83bc4f9c9e | ||
![]() |
dfcef67095 | ||
![]() |
16fca86e92 | ||
![]() |
1f63381746 | ||
![]() |
85e280bc43 | ||
![]() |
78a97b79f8 | ||
![]() |
8dea4b3d99 | ||
![]() |
8611880b86 | ||
![]() |
fdefef10a3 | ||
![]() |
e054e3c87e | ||
![]() |
e8f3165282 | ||
![]() |
7239c7d4a1 | ||
![]() |
323e34aa28 | ||
![]() |
637a32a3d9 | ||
![]() |
d213d26e3c | ||
![]() |
82835bcaad | ||
![]() |
e9a6e62d19 | ||
![]() |
e0d8817e05 | ||
![]() |
0a41049893 | ||
![]() |
ce2671b0e2 | ||
![]() |
15d74e7e51 | ||
![]() |
5fa1b47494 | ||
![]() |
109fc7682b |
@@ -1441,16 +1441,13 @@ class VIEW3D_PT_tools_brush_stroke(Panel, View3DPaintPanel):
|
||||
col.separator()
|
||||
col.prop(brush, "rate", text="Rate", slider=True)
|
||||
|
||||
if brush.use_space:
|
||||
if brush.use_space or brush.use_line or brush.use_curve:
|
||||
col.separator()
|
||||
row = col.row(align=True)
|
||||
row.prop(brush, "spacing", text="Spacing")
|
||||
row.prop(brush, "use_pressure_spacing", toggle=True, text="")
|
||||
|
||||
if brush.use_line or brush.use_curve:
|
||||
col.separator()
|
||||
row = col.row(align=True)
|
||||
row.prop(brush, "spacing", text="Spacing")
|
||||
col.prop(brush, "use_adaptive_space", text="Adaptive Spacing")
|
||||
|
||||
if brush.use_curve:
|
||||
col.separator()
|
||||
@@ -1656,6 +1653,33 @@ class VIEW3D_PT_sculpt_symmetry(Panel, View3DPaintPanel):
|
||||
layout.column().prop(sculpt, "tile_offset", text="Tile Offset")
|
||||
|
||||
|
||||
class VIEW3D_PT_sculpt_silhouette(Panel, View3DPaintPanel):
|
||||
bl_category = "Tools"
|
||||
bl_label = "Silhouette"
|
||||
bl_options = {'DEFAULT_CLOSED'}
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
return (context.sculpt_object and context.tool_settings.sculpt)
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
|
||||
sculpt = context.tool_settings.sculpt
|
||||
|
||||
col = layout.column(align=False)
|
||||
col.label(text="Shape:")
|
||||
col.prop(sculpt, "silhouette_smoothness", text="Smoothness", slider=True)
|
||||
col.prop(sculpt, "silhouette_depth", text="Depth")
|
||||
col.prop(sculpt, "silhouette_resolution", text="Resolution")
|
||||
sub = col.column()
|
||||
|
||||
sub.row().prop(sculpt, "silhouette_add", text="Add")
|
||||
sub.row().prop(sculpt, "silhouette_subtract", text="Subtract")
|
||||
|
||||
col.separator()
|
||||
|
||||
|
||||
class VIEW3D_PT_tools_brush_appearance(Panel, View3DPaintPanel):
|
||||
bl_category = "Options"
|
||||
bl_label = "Appearance"
|
||||
@@ -2056,6 +2080,7 @@ classes = (
|
||||
VIEW3D_PT_sculpt_dyntopo,
|
||||
VIEW3D_PT_sculpt_options,
|
||||
VIEW3D_PT_sculpt_symmetry,
|
||||
VIEW3D_PT_sculpt_silhouette,
|
||||
VIEW3D_PT_tools_brush_appearance,
|
||||
VIEW3D_PT_tools_weightpaint,
|
||||
VIEW3D_PT_tools_weightpaint_options,
|
||||
|
@@ -105,6 +105,7 @@ void BKE_brush_weight_set(const struct Scene *scene, struct Brush *brush, float
|
||||
int BKE_brush_use_locked_size(const struct Scene *scene, const struct Brush *brush);
|
||||
int BKE_brush_use_alpha_pressure(const struct Scene *scene, const struct Brush *brush);
|
||||
int BKE_brush_use_size_pressure(const struct Scene *scene, const struct Brush *brush);
|
||||
int BKE_brush_use_adaptive_spacing(const struct Brush *brush);
|
||||
|
||||
/* scale unprojected radius to reflect a change in the brush's 2D size */
|
||||
void BKE_brush_scale_unprojected_radius(
|
||||
|
@@ -29,6 +29,7 @@
|
||||
#include "BLI_bitmap.h"
|
||||
#include "BLI_ghash.h"
|
||||
#include "BLI_utildefines.h"
|
||||
#include "DNA_mesh_types.h"
|
||||
|
||||
struct CCGElem;
|
||||
struct CCGKey;
|
||||
@@ -61,6 +62,8 @@ typedef void (*BKE_pbvh_HitOccludedCallback)(PBVHNode *node, void *data, float *
|
||||
/* Building */
|
||||
|
||||
PBVH *BKE_pbvh_new(void);
|
||||
void BKE_pbvh_attach_mesh(PBVH *pbvh, PBVHNode *node, Mesh *me, int totprim, float *max_bmin, float *max_bmax);
|
||||
void BKE_pbvh_build_mesh_complete(PBVH *pbvh, Mesh *me);
|
||||
void BKE_pbvh_build_mesh(
|
||||
PBVH *bvh,
|
||||
const struct MPoly *mpoly, const struct MLoop *mloop,
|
||||
@@ -71,6 +74,7 @@ void BKE_pbvh_build_grids(PBVH *bvh, struct CCGElem **grid_elems,
|
||||
struct CCGKey *key, void **gridfaces, struct DMFlagMat *flagmats,
|
||||
unsigned int **grid_hidden);
|
||||
void BKE_pbvh_build_bmesh(PBVH *bvh, struct BMesh *bm, bool smooth_shading, struct BMLog *log, const int cd_vert_node_offset, const int cd_face_node_offset);
|
||||
void BKE_pbvh_build_tmp_bmesh(PBVH *bvh, struct BMesh *bm, bool smooth_shading);
|
||||
|
||||
void BKE_pbvh_free(PBVH *bvh);
|
||||
void BKE_pbvh_free_layer_disp(PBVH *bvh);
|
||||
@@ -172,6 +176,8 @@ typedef enum {
|
||||
PBVH_UpdateTopology = 256,
|
||||
} PBVHNodeFlags;
|
||||
|
||||
bool BKE_pbvh_node_is_valid(PBVHNode *node);
|
||||
bool BKE_pbvh_node_is_leaf(PBVHNode *node);
|
||||
void BKE_pbvh_node_mark_update(PBVHNode *node);
|
||||
void BKE_pbvh_node_mark_rebuild_draw(PBVHNode *node);
|
||||
void BKE_pbvh_node_mark_redraw(PBVHNode *node);
|
||||
@@ -190,9 +196,15 @@ void BKE_pbvh_node_get_verts(
|
||||
PBVH *bvh, PBVHNode *node,
|
||||
const int **r_vert_indices, struct MVert **r_verts);
|
||||
|
||||
int BKE_pbvh_recalc_looptri_from_me(PBVH *pbvh, Mesh *me);
|
||||
PBVHNode *BKE_search_closest_pbvh_leaf_node(PBVH *pbvh, PBVHNode *p_node, float *target_bmin, float *target_bmax);
|
||||
|
||||
void BKE_pbvh_node_get_BB(PBVHNode *node, float bb_min[3], float bb_max[3]);
|
||||
void BKE_pbvh_node_get_original_BB(PBVHNode *node, float bb_min[3], float bb_max[3]);
|
||||
|
||||
void BKE_pbvh_node_get_children(PBVH *pbvh, PBVHNode *node, PBVHNode **left, PBVHNode **right);
|
||||
PBVHNode *BKE_pbvh_node_get_root(PBVH *pbvh);
|
||||
|
||||
float BKE_pbvh_node_get_tmin(PBVHNode *node);
|
||||
|
||||
/* test if AABB is at least partially inside the planes' volume */
|
||||
@@ -351,6 +363,8 @@ void BKE_pbvh_node_get_bm_orco_data(
|
||||
|
||||
bool BKE_pbvh_node_vert_update_check_any(PBVH *bvh, PBVHNode *node);
|
||||
|
||||
void BKE_pbvh_get_node_tris_from_verts(PBVH *bvh, PBVHNode *curr_node, GHash *vert_hash, int **tris, int *r_tot_tris);
|
||||
void BKE_pbvh_get_tri(PBVH *bvh, const struct MLoopTri **r_tri);
|
||||
//void BKE_pbvh_node_BB_reset(PBVHNode *node);
|
||||
//void BKE_pbvh_node_BB_expand(PBVHNode *node, float co[3]);
|
||||
|
||||
|
@@ -94,7 +94,7 @@ static void brush_defaults(Brush *brush)
|
||||
zero_v3(brush->secondary_rgb);
|
||||
|
||||
/* BRUSH STROKE SETTINGS */
|
||||
brush->flag |= (BRUSH_SPACE | BRUSH_SPACE_ATTEN);
|
||||
brush->flag |= (BRUSH_SPACE | BRUSH_SPACE_ATTEN | BRUSH_ADAPTIVE_SPACE);
|
||||
brush->spacing = 10; /* how far each brush dot should be spaced as a percentage of brush diameter */
|
||||
|
||||
brush->smooth_stroke_radius = 75;
|
||||
@@ -104,6 +104,8 @@ static void brush_defaults(Brush *brush)
|
||||
|
||||
brush->jitter = 0.0f;
|
||||
|
||||
brush->adaptive_space_factor = 1;
|
||||
|
||||
/* BRUSH TEXTURE SETTINGS */
|
||||
BKE_texture_mtex_default(&brush->mtex);
|
||||
BKE_texture_mtex_default(&brush->mask_mtex);
|
||||
@@ -844,6 +846,12 @@ int BKE_brush_use_alpha_pressure(const Scene *scene, const Brush *brush)
|
||||
(brush->flag & BRUSH_ALPHA_PRESSURE);
|
||||
}
|
||||
|
||||
|
||||
int BKE_brush_use_adaptive_spacing(const Brush *brush)
|
||||
{
|
||||
return (brush->flag & BRUSH_ADAPTIVE_SPACE); //FIXME make sure we are in view3D
|
||||
}
|
||||
|
||||
void BKE_brush_unprojected_radius_set(Scene *scene, Brush *brush, float unprojected_radius)
|
||||
{
|
||||
UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings;
|
||||
|
@@ -38,6 +38,7 @@
|
||||
#include "BKE_global.h"
|
||||
#include "BKE_mesh.h" /* for BKE_mesh_calc_normals */
|
||||
#include "BKE_paint.h"
|
||||
#include "DNA_mesh_types.h"
|
||||
|
||||
#include "GPU_buffers.h"
|
||||
|
||||
@@ -57,6 +58,9 @@
|
||||
|
||||
#define PBVH_THREADED_LIMIT 4
|
||||
|
||||
/*TODO: Usefull?*/
|
||||
#define TRI_ARRAY_GROW 50
|
||||
|
||||
typedef struct PBVHStack {
|
||||
PBVHNode *node;
|
||||
bool revisiting;
|
||||
@@ -514,6 +518,93 @@ static void pbvh_build(PBVH *bvh, BB *cb, BBC *prim_bbc, int totprim)
|
||||
build_sub(bvh, 0, cb, prim_bbc, 0, totprim);
|
||||
}
|
||||
|
||||
/**
|
||||
* Attach a new mesh to a node of the PBVH
|
||||
* vertdata etc needs to be already in the basemesh
|
||||
*/
|
||||
void BKE_pbvh_attach_mesh(PBVH *pbvh, PBVHNode *node, Mesh *me, int totprim, float *max_bmin, float *max_bmax)
|
||||
{
|
||||
BB new_BB;
|
||||
copy_v3_v3(new_BB.bmin, max_bmin);
|
||||
copy_v3_v3(new_BB.bmax, max_bmax);
|
||||
int d_prim = totprim-pbvh->totprim;
|
||||
|
||||
/*for (int i = 0; i < pbvh->totprim; i++) {
|
||||
printf("%i,",pbvh->prim_indices[i]);
|
||||
}*/
|
||||
|
||||
if (me->totvert <= pbvh->leaf_limit) {
|
||||
pbvh->totvert = me->totvert;
|
||||
pbvh->totprim = totprim;
|
||||
MEM_freeN(pbvh->prim_indices);
|
||||
|
||||
pbvh->prim_indices = MEM_mallocN(sizeof(int) * pbvh->totprim, "bvh prim indices");
|
||||
|
||||
//TODO: parent nodes need to be scaled as well
|
||||
node->totprim += d_prim;
|
||||
node->prim_indices = pbvh->prim_indices;
|
||||
|
||||
//Fill with all prim to test
|
||||
for (int i = 0; i < pbvh->totprim; i++) {
|
||||
pbvh->prim_indices[i] = i;
|
||||
}
|
||||
|
||||
BB_expand_with_bb( &node->vb, &new_BB);
|
||||
|
||||
pbvh->verts = me->mvert;
|
||||
pbvh->mloop = me->mloop;
|
||||
pbvh->mpoly = me->mpoly;
|
||||
|
||||
build_mesh_leaf_node(pbvh, node);
|
||||
|
||||
MEM_freeN(node->draw_buffers);
|
||||
node->draw_buffers = NULL;
|
||||
|
||||
BKE_pbvh_node_mark_rebuild_draw(node);
|
||||
printf("Attached new shape to pbvh.\n");
|
||||
} else {
|
||||
//TODO: Attach to multiple nodes.
|
||||
}
|
||||
}
|
||||
|
||||
void BKE_pbvh_build_mesh_complete(PBVH *pbvh, Mesh *me){
|
||||
PBVHNode *root;
|
||||
int looptri_num;
|
||||
|
||||
//BKE_pbvh_free(pbvh);
|
||||
//pbvh = BKE_pbvh_new();
|
||||
|
||||
looptri_num = BKE_pbvh_recalc_looptri_from_me(pbvh, me);
|
||||
|
||||
BKE_pbvh_build_mesh( pbvh, me->mpoly, me->mloop, me->mvert,
|
||||
me->totvert, &me->vdata,
|
||||
pbvh->looptri, looptri_num);
|
||||
|
||||
/*pbvh_show_diffuse_color_set(pbvh, false);*/
|
||||
root = BKE_pbvh_node_get_root(pbvh);
|
||||
|
||||
BKE_pbvh_node_mark_rebuild_draw(root);
|
||||
BKE_pbvh_update( pbvh, root->flag, NULL);
|
||||
|
||||
/*if (root->flag & PBVH_RebuildDrawBuffers) {
|
||||
root->draw_buffers = NULL;
|
||||
} else if (root->draw_buffers){
|
||||
MEM_freeN(root->draw_buffers);
|
||||
root->draw_buffers = NULL;
|
||||
}
|
||||
root->draw_buffers = NULL;*/
|
||||
/*printf("Buffers freed\n");
|
||||
if (root->flag & PBVH_RebuildDrawBuffers) {
|
||||
root->draw_buffers = NULL;
|
||||
} else {
|
||||
GPU_pbvh_buffers_free(root->draw_buffers);
|
||||
root->draw_buffers = NULL;
|
||||
}
|
||||
|
||||
BKE_pbvh_node_mark_rebuild_draw(root);
|
||||
|
||||
BKE_pbvh_update( pbvh, root->flag, NULL);*/
|
||||
}
|
||||
/**
|
||||
* Do a full rebuild with on Mesh data structure.
|
||||
*
|
||||
@@ -1337,6 +1428,16 @@ BMesh *BKE_pbvh_get_bmesh(PBVH *bvh)
|
||||
|
||||
/***************************** Node Access ***********************************/
|
||||
|
||||
bool BKE_pbvh_node_is_valid(PBVHNode *node)
|
||||
{
|
||||
return node->flag; //TODO: check diffrent!
|
||||
}
|
||||
|
||||
bool BKE_pbvh_node_is_leaf(PBVHNode *node)
|
||||
{
|
||||
return node->flag & PBVH_Leaf;
|
||||
}
|
||||
|
||||
void BKE_pbvh_node_mark_update(PBVHNode *node)
|
||||
{
|
||||
node->flag |= PBVH_UpdateNormals | PBVH_UpdateBB | PBVH_UpdateOriginalBB | PBVH_UpdateDrawBuffers | PBVH_UpdateRedraw;
|
||||
@@ -1428,6 +1529,112 @@ void BKE_pbvh_node_get_grids(
|
||||
}
|
||||
}
|
||||
|
||||
static float get_bb_distance_sqr(BB a, BB b)
|
||||
{
|
||||
float dist = 0.0f;
|
||||
for (int i = 0; i < 3; i++) {
|
||||
if (a.bmin[i] >= b.bmax[i]) {
|
||||
dist += (b.bmax[i] - a.bmin[i]) * (b.bmax[i] - a.bmin[i]);
|
||||
} else if (a.bmax[i] < b.bmin[i]) {
|
||||
dist += (b.bmin[i] - a.bmax[i]) * (b.bmin[i] - a.bmax[i]);
|
||||
}
|
||||
}
|
||||
return dist;
|
||||
}
|
||||
|
||||
int BKE_pbvh_recalc_looptri_from_me(PBVH *pbvh, Mesh *me)
|
||||
{
|
||||
if(pbvh->looptri){
|
||||
MEM_freeN((void*)pbvh->looptri);
|
||||
}
|
||||
MLoopTri *looptri = NULL;
|
||||
int looptri_num = poly_to_tri_count(me->totpoly, me->totloop);
|
||||
looptri = MEM_mallocN(sizeof(*looptri) * looptri_num, __func__);
|
||||
|
||||
BKE_mesh_recalc_looptri(
|
||||
me->mloop, me->mpoly,
|
||||
me->mvert,
|
||||
me->totloop, me->totpoly,
|
||||
looptri);
|
||||
/*for (int i = 0; i < looptri_num; i++) {
|
||||
printf("Tri (%i,%i,%i), Poly %i\n", looptri[i].tri[0], looptri[i].tri[1], looptri[i].tri[2], looptri[i].poly);
|
||||
}*/
|
||||
|
||||
pbvh->looptri = looptri;
|
||||
return looptri_num;
|
||||
}
|
||||
|
||||
void BKE_pbvh_get_tri(PBVH *bvh, const struct MLoopTri **r_tri)
|
||||
{
|
||||
*r_tri = bvh->looptri;
|
||||
}
|
||||
|
||||
void BKE_pbvh_get_node_tris_from_verts(PBVH *bvh, PBVHNode *node, GHash *vert_hash, int **r_tris, int *r_tot_tris)
|
||||
{
|
||||
|
||||
const int *faces = node->prim_indices;
|
||||
const MLoop *mloop = bvh->mloop;
|
||||
int totface = node->totprim;
|
||||
int *tris;
|
||||
int r_tris_max;
|
||||
/* Estimated that every vert has roughly two tris in a uniform mesh*/
|
||||
tris = MEM_callocN(sizeof(int) * BLI_ghash_size(vert_hash) * 2, "tris connected to verts");
|
||||
r_tris_max = BLI_ghash_size(vert_hash) * 2;
|
||||
*r_tot_tris = 0;
|
||||
|
||||
for (int i = 0; i < totface; i++) {
|
||||
const MLoopTri lt = bvh->looptri[faces[i]];
|
||||
/* TODO: Original or not etc?
|
||||
const int *face_verts = node->face_vert_indices[i];*/
|
||||
for(int s = 0; s < 3; s++) {
|
||||
if (BLI_ghash_haskey(vert_hash, SET_INT_IN_POINTER(mloop[lt.tri[s]].v))) {
|
||||
if (*r_tot_tris >= r_tris_max) {
|
||||
r_tris_max += TRI_ARRAY_GROW;
|
||||
tris = MEM_reallocN(tris, sizeof(int) * r_tris_max);
|
||||
}
|
||||
tris[*r_tot_tris] = faces[i];
|
||||
*r_tot_tris += 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*r_tris = tris;
|
||||
}
|
||||
|
||||
PBVHNode *BKE_search_closest_pbvh_leaf_node(PBVH *pbvh, PBVHNode *p_node, float *target_bmin, float *target_bmax)
|
||||
{
|
||||
BB new_BB;
|
||||
copy_v3_v3(new_BB.bmin,target_bmin);
|
||||
copy_v3_v3(new_BB.bmax,target_bmax);
|
||||
BB_expand_with_bb(&p_node->vb,&new_BB);
|
||||
if (BKE_pbvh_node_is_leaf(p_node)) {
|
||||
return p_node;
|
||||
}
|
||||
PBVHNode *left = NULL, *right = NULL;
|
||||
BB bb_left, bb_right, bb_target;
|
||||
|
||||
copy_v3_v3(bb_target.bmin,target_bmin);
|
||||
copy_v3_v3(bb_target.bmax,target_bmax);
|
||||
|
||||
BKE_pbvh_node_get_children(pbvh, p_node, &left, &right);
|
||||
if ((!left && !right)) {
|
||||
return p_node;
|
||||
} else if (!left) {
|
||||
return BKE_search_closest_pbvh_leaf_node(pbvh, right, bb_target.bmin, bb_target.bmax);
|
||||
} else if (!right) {
|
||||
return BKE_search_closest_pbvh_leaf_node(pbvh, left, bb_target.bmin, bb_target.bmax);
|
||||
}
|
||||
BKE_pbvh_node_get_BB(left, bb_left.bmin, bb_left.bmax);
|
||||
BKE_pbvh_node_get_BB(right, bb_right.bmin, bb_right.bmax);
|
||||
if (get_bb_distance_sqr(bb_target,bb_left) > get_bb_distance_sqr(bb_target,bb_right)) {
|
||||
return BKE_search_closest_pbvh_leaf_node(pbvh, right, bb_target.bmin, bb_target.bmax);
|
||||
} else {
|
||||
return BKE_search_closest_pbvh_leaf_node(pbvh, left, bb_target.bmin, bb_target.bmax);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void BKE_pbvh_node_get_BB(PBVHNode *node, float bb_min[3], float bb_max[3])
|
||||
{
|
||||
copy_v3_v3(bb_min, node->vb.bmin);
|
||||
@@ -1440,6 +1647,17 @@ void BKE_pbvh_node_get_original_BB(PBVHNode *node, float bb_min[3], float bb_max
|
||||
copy_v3_v3(bb_max, node->orig_vb.bmax);
|
||||
}
|
||||
|
||||
void BKE_pbvh_node_get_children(PBVH *pbvh, PBVHNode *node, PBVHNode **left, PBVHNode **right)
|
||||
{
|
||||
*left = pbvh->nodes+node->children_offset;
|
||||
*right = pbvh->nodes+node->children_offset+1;
|
||||
}
|
||||
|
||||
PBVHNode *BKE_pbvh_node_get_root(PBVH *pbvh)
|
||||
{
|
||||
return pbvh->nodes;
|
||||
}
|
||||
|
||||
void BKE_pbvh_node_get_proxies(PBVHNode *node, PBVHProxyNode **proxies, int *proxy_count)
|
||||
{
|
||||
if (node->proxy_count > 0) {
|
||||
|
@@ -1850,6 +1850,71 @@ void BKE_pbvh_build_bmesh(
|
||||
MEM_freeN(nodeinfo);
|
||||
}
|
||||
|
||||
/* Build a PBVH from a BMesh */
|
||||
void BKE_pbvh_build_tmp_bmesh(
|
||||
PBVH *bvh, BMesh *bm, bool smooth_shading)
|
||||
{
|
||||
bvh->cd_vert_node_offset = 0;
|
||||
bvh->cd_face_node_offset = 0;
|
||||
bvh->bm = bm;
|
||||
|
||||
bvh->type = PBVH_BMESH;
|
||||
|
||||
/* TODO: choose leaf limit better */
|
||||
bvh->leaf_limit = 100;
|
||||
|
||||
if (smooth_shading)
|
||||
bvh->flags |= PBVH_DYNTOPO_SMOOTH_SHADING;
|
||||
|
||||
/* bounding box array of all faces, no need to recalculate every time */
|
||||
BBC *bbc_array = MEM_mallocN(sizeof(BBC) * bm->totface, "BBC");
|
||||
BMFace **nodeinfo = MEM_mallocN(sizeof(*nodeinfo) * bm->totface, "nodeinfo");
|
||||
MemArena *arena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, "fast PBVH node storage");
|
||||
|
||||
BMIter iter;
|
||||
BMFace *f;
|
||||
int i;
|
||||
BM_ITER_MESH_INDEX(f, &iter, bm, BM_FACES_OF_MESH, i) {
|
||||
BBC *bbc = &bbc_array[i];
|
||||
BMLoop *l_first = BM_FACE_FIRST_LOOP(f);
|
||||
BMLoop *l_iter = l_first;
|
||||
|
||||
BB_reset((BB *)bbc);
|
||||
do {
|
||||
BB_expand((BB *)bbc, l_iter->v->co);
|
||||
} while ((l_iter = l_iter->next) != l_first);
|
||||
BBC_update_centroid(bbc);
|
||||
|
||||
/* so we can do direct lookups on 'bbc_array' */
|
||||
BM_elem_index_set(f, i); /* set_dirty! */
|
||||
nodeinfo[i] = f;
|
||||
}
|
||||
|
||||
/* likely this is already dirty */
|
||||
bm->elem_index_dirty |= BM_FACE;
|
||||
|
||||
/* setup root node */
|
||||
struct FastNodeBuildInfo rootnode = {0};
|
||||
rootnode.totface = bm->totface;
|
||||
|
||||
/* start recursion, assign faces to nodes accordingly */
|
||||
pbvh_bmesh_node_limit_ensure_fast(bvh, nodeinfo, bbc_array, &rootnode, arena);
|
||||
|
||||
/* we now have all faces assigned to a node, next we need to assign those to the gsets of the nodes */
|
||||
|
||||
/* Start with all faces in the root node */
|
||||
bvh->nodes = MEM_callocN(sizeof(PBVHNode), "PBVHNode");
|
||||
bvh->totnode = 1;
|
||||
|
||||
/* take root node and visit and populate children recursively */
|
||||
pbvh_bmesh_create_nodes_fast_recursive(bvh, nodeinfo, bbc_array, &rootnode, 0);
|
||||
|
||||
BLI_memarena_free(arena);
|
||||
MEM_freeN(bbc_array);
|
||||
MEM_freeN(nodeinfo);
|
||||
}
|
||||
|
||||
|
||||
/* Collapse short edges, subdivide long edges */
|
||||
bool BKE_pbvh_bmesh_update_topology(
|
||||
PBVH *bvh, PBVHTopologyUpdateMode mode,
|
||||
|
@@ -107,6 +107,10 @@ void BLO_update_defaults_startup_blend(Main *bmain)
|
||||
sculpt->paint.symmetry_flags |= PAINT_SYMM_X;
|
||||
sculpt->flags |= SCULPT_DYNTOPO_COLLAPSE;
|
||||
sculpt->detail_size = 12;
|
||||
|
||||
sculpt->silhouette_smoothness = 50.0f;
|
||||
sculpt->silhouette_depth = 1.0f;
|
||||
sculpt->silhouette_resolution = 3;
|
||||
}
|
||||
|
||||
if (ts->gp_sculpt.brush[0].size == 0) {
|
||||
|
@@ -32,6 +32,7 @@
|
||||
#ifndef __PAINT_INTERN_H__
|
||||
#define __PAINT_INTERN_H__
|
||||
|
||||
|
||||
struct ARegion;
|
||||
struct bContext;
|
||||
struct Brush;
|
||||
@@ -76,6 +77,7 @@ bool paint_supports_smooth_stroke(struct Brush *br, enum PaintMode mode);
|
||||
bool paint_supports_texture(enum PaintMode mode);
|
||||
bool paint_supports_jitter(enum PaintMode mode);
|
||||
|
||||
|
||||
struct wmKeyMap *paint_stroke_modal_keymap(struct wmKeyConfig *keyconf);
|
||||
int paint_stroke_modal(struct bContext *C, struct wmOperator *op, const struct wmEvent *event);
|
||||
int paint_stroke_exec(struct bContext *C, struct wmOperator *op);
|
||||
|
@@ -1564,6 +1564,10 @@ void ED_keymap_paint(wmKeyConfig *keyconf)
|
||||
/* Toggle dynamic topology */
|
||||
WM_keymap_add_item(keymap, "SCULPT_OT_dynamic_topology_toggle", DKEY, KM_PRESS, KM_CTRL, 0);
|
||||
|
||||
/* Draw Silhouette */
|
||||
RNA_enum_set(WM_keymap_add_item(keymap, "SCULPT_OT_silhouette_draw", LEFTMOUSE, KM_PRESS, KM_ALT, 0)->ptr, "mode", BRUSH_STROKE_NORMAL);
|
||||
RNA_enum_set(WM_keymap_add_item(keymap, "SCULPT_OT_silhouette_draw", RIGHTMOUSE, KM_PRESS, KM_ALT, 0)->ptr, "mode", BRUSH_STROKE_INVERT);
|
||||
|
||||
/* Dynamic-topology detail size
|
||||
*
|
||||
* This should be improved further, perhaps by showing a triangle
|
||||
|
@@ -66,16 +66,40 @@
|
||||
#include "IMB_imbuf_types.h"
|
||||
|
||||
#include "paint_intern.h"
|
||||
#include "sculpt_intern.h"
|
||||
|
||||
#include <float.h>
|
||||
#include <math.h>
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
//#define DEBUG_TIME
|
||||
|
||||
#ifdef DEBUG_TIME
|
||||
# include "PIL_time_utildefines.h"
|
||||
#endif
|
||||
|
||||
/*Debug spacing calc define DEBUG_DRAW to get info about sampling etc.*/
|
||||
/*#define DEBUG_DRAW*/
|
||||
|
||||
#ifdef DEBUG_DRAW
|
||||
static void bl_debug_draw(void);
|
||||
/* add these locally when using these functions for testing */
|
||||
extern void bl_debug_draw_quad_clear(void);
|
||||
extern void bl_debug_draw_quad_add(const float v0[3], const float v1[3], const float v2[3], const float v3[3]);
|
||||
extern void bl_debug_draw_edge_add(const float v0[3], const float v1[3]);
|
||||
extern void bl_debug_color_set(const unsigned int col);
|
||||
|
||||
void bl_debug_draw_point(const float pos[3],const float thickness){
|
||||
float h = thickness*0.5;
|
||||
float v1[] = {pos[0]-h,pos[1]-h,pos[2]};
|
||||
float v2[] = {pos[0]-h,pos[1]+h,pos[2]};
|
||||
float v3[] = {pos[0]+h,pos[1]-h,pos[2]};
|
||||
float v4[] = {pos[0]+h,pos[1]+h,pos[2]};
|
||||
bl_debug_draw_quad_add(v1,v2,v3,v4);
|
||||
}
|
||||
#endif
|
||||
|
||||
typedef struct PaintSample {
|
||||
float mouse[2];
|
||||
float pressure;
|
||||
@@ -101,8 +125,10 @@ typedef struct PaintStroke {
|
||||
int cur_sample;
|
||||
|
||||
float last_mouse_position[2];
|
||||
float last_v3_mouse_position[3];
|
||||
/* space distance covered so far */
|
||||
float stroke_distance;
|
||||
float distance_since_last_dab;
|
||||
|
||||
/* Set whether any stroke step has yet occurred
|
||||
* e.g. in sculpt mode, stroke doesn't start until cursor
|
||||
@@ -444,6 +470,7 @@ static void paint_brush_stroke_add_step(bContext *C, wmOperator *op, const float
|
||||
* will create too many dabs */
|
||||
copy_v2_v2(stroke->last_mouse_position, mouse_in);
|
||||
stroke->last_pressure = pressure;
|
||||
stroke->distance_since_last_dab = 0.0f;
|
||||
|
||||
if (paint_stroke_use_jitter(mode, brush, stroke->stroke_mode == BRUSH_STROKE_INVERT)) {
|
||||
float delta[2];
|
||||
@@ -474,6 +501,14 @@ static void paint_brush_stroke_add_step(bContext *C, wmOperator *op, const float
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_DRAW
|
||||
bl_debug_color_set(0x0000FF);
|
||||
bl_debug_draw_point(ups->last_location,0.05f);
|
||||
bl_debug_color_set(0x000000);
|
||||
#endif
|
||||
|
||||
copy_v3_v3(stroke->last_v3_mouse_position, location);
|
||||
|
||||
/* Add to stroke */
|
||||
RNA_collection_add(op->ptr, "stroke", &itemptr);
|
||||
RNA_float_set(&itemptr, "size", ups->pixel_radius);
|
||||
@@ -516,36 +551,56 @@ static bool paint_smooth_stroke(
|
||||
return true;
|
||||
}
|
||||
|
||||
static float paint_space_stroke_spacing(const Scene *scene, PaintStroke *stroke, float size_pressure, float spacing_pressure)
|
||||
static const float MIN_BRUSH_SIZE_PIXELS = 1.0f;
|
||||
static const float MAGIC_50 = 50.0f;
|
||||
static const float MAGIC_1_5 = 1.5f;
|
||||
|
||||
/* Brush spacing ignoring both pressure and brush angle to the geometry */
|
||||
static float paint_space_unadjusted_stroke_spacing(const Scene *scene, PaintStroke *stroke) {
|
||||
|
||||
const float size_clamp = max_ff(MIN_BRUSH_SIZE_PIXELS, BKE_brush_size_get(scene, stroke->brush));
|
||||
|
||||
return max_ff(MIN_BRUSH_SIZE_PIXELS, size_clamp * stroke->brush->spacing / MAGIC_50);
|
||||
}
|
||||
|
||||
static float paint_space_stroke_adaptive_spacing(const Scene *scene, PaintStroke *stroke, float spacing)
|
||||
{
|
||||
spacing = spacing * stroke->brush->adaptive_space_factor;
|
||||
|
||||
return spacing;
|
||||
}
|
||||
|
||||
static float paint_space_stroke_pressure_spacing(const Scene *scene, PaintStroke *stroke, float size_pressure, float spacing_pressure, float spacing)
|
||||
{
|
||||
/* brushes can have a minimum size of 1.0 but with pressure it can be smaller then a pixel
|
||||
* causing very high step sizes, hanging blender [#32381] */
|
||||
const float size_clamp = max_ff(1.0f, BKE_brush_size_get(scene, stroke->brush) * size_pressure);
|
||||
float spacing = stroke->brush->spacing;
|
||||
//TODO size_clamp should probably be calculated at the start and used throughout
|
||||
const float size_clamp = max_ff(MIN_BRUSH_SIZE_PIXELS, BKE_brush_size_get(scene, stroke->brush) * size_pressure);
|
||||
|
||||
/* apply spacing pressure */
|
||||
if (stroke->brush->flag & BRUSH_SPACING_PRESSURE)
|
||||
spacing = spacing * (1.5f - spacing_pressure);
|
||||
|
||||
spacing = spacing * (MAGIC_1_5 - spacing_pressure);
|
||||
|
||||
//TODO zoom_2d should be seperated out
|
||||
/* stroke system is used for 2d paint too, so we need to account for
|
||||
* the fact that brush can be scaled there. */
|
||||
spacing *= stroke->zoom_2d;
|
||||
|
||||
return max_ff(1.0, size_clamp * spacing / 50.0f);
|
||||
return max_ff(MIN_BRUSH_SIZE_PIXELS, size_clamp * spacing / MAGIC_50);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static float paint_stroke_overlapped_curve(Brush *br, float x, float spacing)
|
||||
{
|
||||
int i;
|
||||
const int n = 100 / spacing;
|
||||
const float h = spacing / 50.0f;
|
||||
const float x0 = x - 1;
|
||||
//TODO I think the refactoring and spacing integration elsewhere makes this no longer necessary
|
||||
//const int n = 100 / ((br->flag&BRUSH_ADAPTIVE_SPACE ? br->adaptive_space_factor : 1.0f) * br->spacing);
|
||||
const float h = spacing / MAGIC_50;
|
||||
const float x0 = x - 1.0f;
|
||||
|
||||
float sum;
|
||||
|
||||
sum = 0;
|
||||
sum = 0.0f;
|
||||
for (i = 0; i < n; i++) {
|
||||
float xx;
|
||||
|
||||
@@ -585,32 +640,71 @@ static float paint_stroke_integrate_overlap(Brush *br, float factor)
|
||||
|
||||
static float paint_space_stroke_spacing_variable(const Scene *scene, PaintStroke *stroke, float pressure, float dpressure, float length)
|
||||
{
|
||||
float spacing = paint_space_unadjusted_stroke_spacing(scene, stroke);
|
||||
|
||||
if (BKE_brush_use_adaptive_spacing(stroke->brush)) {
|
||||
/*adapt the stroke spacing to account for geometry that curves away from the viewport*/
|
||||
spacing = paint_space_stroke_adaptive_spacing(scene, stroke, spacing);
|
||||
}
|
||||
|
||||
if (BKE_brush_use_size_pressure(scene, stroke->brush)) {
|
||||
/* use pressure to modify size. set spacing so that at 100%, the circles
|
||||
* are aligned nicely with no overlap. for this the spacing needs to be
|
||||
* the average of the previous and next size. */
|
||||
float s = paint_space_stroke_spacing(scene, stroke, 1.0f, pressure);
|
||||
float q = s * dpressure / (2.0f * length);
|
||||
float q = spacing * dpressure / (2.0f * length);
|
||||
float pressure_fac = (1.0f + q) / (1.0f - q);
|
||||
|
||||
float last_size_pressure = stroke->last_pressure;
|
||||
float new_size_pressure = stroke->last_pressure * pressure_fac;
|
||||
|
||||
/* average spacing */
|
||||
float last_spacing = paint_space_stroke_spacing(scene, stroke, last_size_pressure, pressure);
|
||||
float new_spacing = paint_space_stroke_spacing(scene, stroke, new_size_pressure, pressure);
|
||||
float last_spacing = paint_space_stroke_pressure_spacing(scene, stroke, last_size_pressure, pressure, spacing);
|
||||
float new_spacing = paint_space_stroke_pressure_spacing(scene, stroke, new_size_pressure, pressure, spacing);
|
||||
|
||||
spacing = 0.5f * (last_spacing + new_spacing);
|
||||
|
||||
return 0.5f * (last_spacing + new_spacing);
|
||||
}
|
||||
else {
|
||||
/* no size pressure */
|
||||
return paint_space_stroke_spacing(scene, stroke, 1.0f, pressure);
|
||||
}
|
||||
return spacing;
|
||||
}
|
||||
|
||||
/* For brushes with stroke spacing enabled, moves mouse in steps
|
||||
* towards the final mouse location. */
|
||||
static int paint_space_stroke(bContext *C, wmOperator *op, const float final_mouse[2], float final_pressure)
|
||||
/* Draw a dab in the sample region.
|
||||
* sample_point is the end point.
|
||||
* step_v2 is the vector between first point and the end point.
|
||||
* draw dabs with spacing interpolated on the line between the two points.
|
||||
*/
|
||||
static int draw_spaced_dab(bContext *C, wmOperator *op,const float sample_point[2], float step_v2[2], float dist_last_dab, float spacing, float pressure, float *length_v3){
|
||||
float draw_pos[2];
|
||||
float interpol_fact;
|
||||
float interpol_pos = -dist_last_dab;
|
||||
int cnt = 0;
|
||||
|
||||
while((*length_v3)-interpol_pos >= spacing){
|
||||
interpol_fact = 1.0f-((interpol_pos+spacing)/(*length_v3));
|
||||
if(interpol_fact > 0.0f && interpol_fact <= 1.0f){
|
||||
mul_v2_v2fl(draw_pos,step_v2,-interpol_fact);
|
||||
add_v2_v2(draw_pos,sample_point);
|
||||
paint_brush_stroke_add_step(C, op, draw_pos, pressure);
|
||||
cnt ++;
|
||||
}else{
|
||||
/*Cornercase should not happen. TODO: Delete?*/
|
||||
mul_v2_v2fl(draw_pos,step_v2,-1.0f);
|
||||
add_v2_v2(draw_pos,sample_point);
|
||||
paint_brush_stroke_add_step(C, op, draw_pos, pressure);
|
||||
*length_v3 = 0.0f;
|
||||
return cnt+1;
|
||||
}
|
||||
interpol_pos += spacing;
|
||||
}
|
||||
/* transfer remaining space between end point and last dab to the next region*/
|
||||
*length_v3 -= interpol_pos;
|
||||
|
||||
return cnt;
|
||||
}
|
||||
|
||||
/* Calculate spacing in screen space. (distance between last dab in screen space)
|
||||
* This checks distance to the last dab. Maybe it should be distance drawn on screen?
|
||||
*/
|
||||
static int paint_space_stroke_screen_space(bContext *C, wmOperator *op, const float final_mouse[2], float final_pressure)
|
||||
{
|
||||
const Scene *scene = CTX_data_scene(C);
|
||||
PaintStroke *stroke = op->customdata;
|
||||
@@ -620,7 +714,7 @@ static int paint_space_stroke(bContext *C, wmOperator *op, const float final_mou
|
||||
float pressure, dpressure;
|
||||
float mouse[2], dmouse[2];
|
||||
float length;
|
||||
float no_pressure_spacing = paint_space_stroke_spacing(scene, stroke, 1.0f, 1.0f);
|
||||
float no_pressure_spacing = paint_space_unadjusted_stroke_spacing(scene, stroke);
|
||||
|
||||
sub_v2_v2v2(dmouse, final_mouse, stroke->last_mouse_position);
|
||||
|
||||
@@ -652,6 +746,143 @@ static int paint_space_stroke(bContext *C, wmOperator *op, const float final_mou
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return cnt;
|
||||
}
|
||||
|
||||
/* For brushes with adaptive stroke spacing enabled.
|
||||
* Calculate spacing in object space. Distance drawn on surface rather than distance drawn on screen.
|
||||
*/
|
||||
static int paint_space_stroke_object_space(bContext *C, wmOperator *op, const float final_mouse[2], float final_pressure)
|
||||
{
|
||||
const Scene *scene = CTX_data_scene(C);
|
||||
PaintStroke *stroke = op->customdata;
|
||||
UnifiedPaintSettings *ups = stroke->ups;
|
||||
int cnt = 0;
|
||||
|
||||
float pressure, dpressure;
|
||||
float mouse_v3[3], diff_mouse_v3[3];
|
||||
|
||||
float length, length_v3;
|
||||
float no_pressure_spacing = paint_space_unadjusted_stroke_spacing(scene, stroke);
|
||||
|
||||
int steps;
|
||||
float length_v2,step_size;
|
||||
float diff_path_v2[2], step_pos_v2[2];
|
||||
float start_step_v3[3], end_step_v3[3];
|
||||
|
||||
bool off_mesh = false;
|
||||
float min_res = 0.1f;
|
||||
|
||||
pressure = stroke->last_pressure;
|
||||
dpressure = final_pressure - stroke->last_pressure;
|
||||
|
||||
if(stroke->get_location){
|
||||
if(!stroke->get_location(C, mouse_v3, final_mouse)){
|
||||
off_mesh = true;
|
||||
}
|
||||
}
|
||||
|
||||
sub_v3_v3v3(diff_mouse_v3, mouse_v3, stroke->last_v3_mouse_position);
|
||||
|
||||
/* accumulate path or 3d max distance from last dab?
|
||||
* accumulative version here:
|
||||
*/
|
||||
|
||||
/*length_v3 is the distance between the last samplepoint and the current*/
|
||||
length_v3 = normalize_v3(diff_mouse_v3);
|
||||
|
||||
if(length_v3 > 0.0f){
|
||||
float spacing = paint_space_stroke_spacing_variable(scene, stroke, pressure, dpressure, stroke->distance_since_last_dab);
|
||||
|
||||
/*check if more samplepoints are needed to better approximate the surface.*/
|
||||
if(length_v3 > min_res){
|
||||
steps = ceilf(length_v3/min_res);
|
||||
sub_v2_v2v2(diff_path_v2,final_mouse,stroke->last_mouse_position);
|
||||
length_v2 = normalize_v2(diff_path_v2);
|
||||
if(off_mesh){
|
||||
step_size = 1.0f/min_res;
|
||||
steps = 10000;/*turns "for" into "while", maybe there is a better way?*/
|
||||
}else{
|
||||
step_size = length_v2/steps;
|
||||
}
|
||||
|
||||
length_v3 = 0.0f;
|
||||
|
||||
mul_v2_fl(diff_path_v2,step_size);
|
||||
|
||||
copy_v3_v3(start_step_v3,stroke->last_v3_mouse_position);
|
||||
copy_v2_v2(step_pos_v2,stroke->last_mouse_position);
|
||||
|
||||
#ifdef DEBUG_DRAW
|
||||
bl_debug_color_set(0x000000);
|
||||
#endif
|
||||
/*split up the current section into smaller parts*/
|
||||
for(int i = 0; i < steps; i++){
|
||||
if(i < steps-1){
|
||||
add_v2_v2(step_pos_v2,diff_path_v2);
|
||||
if(stroke->get_location){
|
||||
if(!stroke->get_location(C, end_step_v3, step_pos_v2)){
|
||||
copy_v2_v2(stroke->last_mouse_position,step_pos_v2);
|
||||
copy_v3_v3(stroke->last_v3_mouse_position,end_step_v3);
|
||||
return cnt;
|
||||
}
|
||||
}
|
||||
length_v3 = len_v3v3(end_step_v3,start_step_v3);
|
||||
#ifdef DEBUG_DRAW
|
||||
bl_debug_draw_edge_add(end_step_v3,start_step_v3);
|
||||
#endif
|
||||
copy_v3_v3(start_step_v3,end_step_v3);
|
||||
}else{
|
||||
add_v2_v2(step_pos_v2,diff_path_v2);
|
||||
length_v3 = len_v3v3(end_step_v3,mouse_v3);
|
||||
#ifdef DEBUG_DRAW
|
||||
bl_debug_color_set(0xff0000);
|
||||
bl_debug_draw_edge_add(end_step_v3,mouse_v3);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*Dab*/
|
||||
length = stroke->distance_since_last_dab + length_v3;
|
||||
if(length >= spacing){
|
||||
pressure = stroke->last_pressure + (spacing / length) * dpressure;
|
||||
ups->overlap_factor = paint_stroke_integrate_overlap(stroke->brush, (spacing/stroke->brush->adaptive_space_factor) / no_pressure_spacing);
|
||||
stroke->stroke_distance += spacing;
|
||||
|
||||
cnt += draw_spaced_dab(C, op, step_pos_v2, diff_path_v2, stroke->distance_since_last_dab, spacing, pressure, &length_v3);
|
||||
|
||||
stroke->distance_since_last_dab = length_v3;
|
||||
pressure = stroke->last_pressure;
|
||||
dpressure = final_pressure - stroke->last_pressure;
|
||||
}else{
|
||||
stroke->distance_since_last_dab += length_v3;
|
||||
}
|
||||
/*end Dab*/
|
||||
}
|
||||
}else{
|
||||
/*Dab*/
|
||||
length = stroke->distance_since_last_dab + length_v3;
|
||||
if(length >= spacing){
|
||||
sub_v2_v2v2(diff_path_v2,final_mouse,stroke->last_mouse_position);
|
||||
|
||||
pressure = stroke->last_pressure + (spacing / length) * dpressure;
|
||||
ups->overlap_factor = paint_stroke_integrate_overlap(stroke->brush, (spacing/stroke->brush->adaptive_space_factor) / no_pressure_spacing);//paint_stroke_integrate_overlap(stroke->brush, spacing / no_pressure_spacing);
|
||||
stroke->stroke_distance += length;
|
||||
|
||||
cnt += draw_spaced_dab(C, op, final_mouse, diff_path_v2, stroke->distance_since_last_dab, spacing, pressure, &length_v3);
|
||||
|
||||
stroke->distance_since_last_dab = length_v3;
|
||||
pressure = stroke->last_pressure;
|
||||
dpressure = final_pressure - stroke->last_pressure;
|
||||
}else{
|
||||
stroke->distance_since_last_dab += length_v3;
|
||||
}
|
||||
/*end Dab*/
|
||||
}
|
||||
}
|
||||
|
||||
copy_v2_v2(stroke->last_mouse_position,final_mouse);
|
||||
copy_v3_v3(stroke->last_v3_mouse_position,mouse_v3);
|
||||
|
||||
return cnt;
|
||||
}
|
||||
@@ -960,7 +1191,12 @@ static void paint_stroke_line_end(bContext *C, wmOperator *op, PaintStroke *stro
|
||||
stroke->ups->overlap_factor = paint_stroke_integrate_overlap(br, 1.0);
|
||||
|
||||
paint_brush_stroke_add_step(C, op, stroke->last_mouse_position, 1.0);
|
||||
paint_space_stroke(C, op, mouse, 1.0);
|
||||
|
||||
if(BKE_brush_use_adaptive_spacing(stroke->brush)){
|
||||
paint_space_stroke_object_space(C,op, mouse, 1.0f);
|
||||
}else{
|
||||
paint_space_stroke_screen_space(C,op, mouse, 1.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -971,7 +1207,7 @@ static bool paint_stroke_curve_end(bContext *C, wmOperator *op, PaintStroke *str
|
||||
if (br->flag & BRUSH_CURVE) {
|
||||
UnifiedPaintSettings *ups = &CTX_data_tool_settings(C)->unified_paint_settings;
|
||||
const Scene *scene = CTX_data_scene(C);
|
||||
const float spacing = paint_space_stroke_spacing(scene, stroke, 1.0f, 1.0f);
|
||||
const float spacing = paint_space_unadjusted_stroke_spacing(scene, stroke);
|
||||
PaintCurve *pc = br->paint_curve;
|
||||
PaintCurvePoint *pcp;
|
||||
float length_residue = 0.0f;
|
||||
@@ -1125,6 +1361,7 @@ int paint_stroke_modal(bContext *C, wmOperator *op, const wmEvent *event)
|
||||
if (!stroke->stroke_started) {
|
||||
stroke->last_pressure = sample_average.pressure;
|
||||
copy_v2_v2(stroke->last_mouse_position, sample_average.mouse);
|
||||
stroke->get_location(C,stroke->last_v3_mouse_position,stroke->last_mouse_position);
|
||||
stroke->stroke_started = stroke->test_start(C, op, sample_average.mouse);
|
||||
BLI_assert((stroke->stroke_started & ~1) == 0); /* 0/1 */
|
||||
|
||||
@@ -1191,8 +1428,13 @@ int paint_stroke_modal(bContext *C, wmOperator *op, const wmEvent *event)
|
||||
if (paint_smooth_stroke(stroke, &sample_average, mode, mouse, &pressure)) {
|
||||
if (stroke->stroke_started) {
|
||||
if (paint_space_stroke_enabled(br, mode)) {
|
||||
if (paint_space_stroke(C, op, mouse, pressure))
|
||||
redraw = true;
|
||||
if (BKE_brush_use_adaptive_spacing(stroke->brush)) {
|
||||
if (paint_space_stroke_object_space(C, op, mouse, pressure))
|
||||
redraw = true;
|
||||
}else{
|
||||
if (paint_space_stroke_screen_space(C, op, mouse, pressure))
|
||||
redraw = true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
float dmouse[2];
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -36,12 +36,11 @@
|
||||
#include "DNA_listBase.h"
|
||||
#include "DNA_vec_types.h"
|
||||
#include "DNA_key_types.h"
|
||||
|
||||
#include "DNA_customdata_types.h"
|
||||
#include "BLI_bitmap.h"
|
||||
#include "BKE_pbvh.h"
|
||||
|
||||
struct bContext;
|
||||
struct KeyBlock;
|
||||
struct Object;
|
||||
struct SculptUndoNode;
|
||||
|
||||
@@ -64,19 +63,20 @@ void sculpt_dynamic_topology_disable(struct bContext *C,
|
||||
|
||||
/* Undo */
|
||||
|
||||
typedef enum {
|
||||
typedef enum SculptUndoType {
|
||||
SCULPT_UNDO_COORDS,
|
||||
SCULPT_UNDO_HIDDEN,
|
||||
SCULPT_UNDO_MASK,
|
||||
SCULPT_UNDO_DYNTOPO_BEGIN,
|
||||
SCULPT_UNDO_DYNTOPO_END,
|
||||
SCULPT_UNDO_DYNTOPO_SYMMETRIZE,
|
||||
SCULPT_UNDO_SILHOUETTE
|
||||
} SculptUndoType;
|
||||
|
||||
typedef struct SculptUndoNode {
|
||||
struct SculptUndoNode *next, *prev;
|
||||
|
||||
SculptUndoType type;
|
||||
enum SculptUndoType type;
|
||||
|
||||
char idname[MAX_ID_NAME]; /* name instead of pointer*/
|
||||
void *node; /* only during push, not valid afterwards! */
|
||||
@@ -100,6 +100,7 @@ typedef struct SculptUndoNode {
|
||||
BLI_bitmap **grid_hidden;
|
||||
|
||||
/* bmesh */
|
||||
/* Reused for Silhouette undonode. TODO: Maybe separate?*/
|
||||
struct BMLogEntry *bm_entry;
|
||||
bool applied;
|
||||
CustomData bm_enter_vdata;
|
||||
@@ -117,6 +118,7 @@ typedef struct SculptUndoNode {
|
||||
|
||||
SculptUndoNode *sculpt_undo_push_node(Object *ob, PBVHNode *node, SculptUndoType type);
|
||||
SculptUndoNode *sculpt_undo_get_node(PBVHNode *node);
|
||||
SculptUndoNode *sculpt_undo_silhouette_push(Object *ob, int v_start, int e_start, int l_start, int p_start);
|
||||
void sculpt_undo_push_begin(const char *name);
|
||||
void sculpt_undo_push_end(const struct bContext *C);
|
||||
|
||||
|
@@ -68,6 +68,8 @@
|
||||
#include "bmesh.h"
|
||||
#include "paint_intern.h"
|
||||
#include "sculpt_intern.h"
|
||||
#include "BKE_object.h"
|
||||
#include "ED_mesh.h"
|
||||
|
||||
/************************** Undo *************************/
|
||||
|
||||
@@ -446,6 +448,74 @@ static int sculpt_undo_bmesh_restore(bContext *C,
|
||||
return false;
|
||||
}
|
||||
|
||||
static void sculpt_undo_silhouette_restore(bContext *C, Object *ob, SculptUndoNode *unode)
|
||||
{
|
||||
Mesh *me = ob->data;
|
||||
if(unode->applied){
|
||||
unode->applied = false;
|
||||
|
||||
CustomData_free_elem(&me->vdata, me->totvert - unode->bm_enter_totvert, unode->bm_enter_totvert);
|
||||
CustomData_free_elem(&me->edata, me->totedge - unode->bm_enter_totedge, unode->bm_enter_totedge);
|
||||
CustomData_free_elem(&me->ldata, me->totloop - unode->bm_enter_totloop, unode->bm_enter_totloop);
|
||||
CustomData_free_elem(&me->pdata, me->totpoly - unode->bm_enter_totpoly, unode->bm_enter_totpoly);
|
||||
|
||||
CustomData_realloc(&me->vdata, me->totvert - unode->bm_enter_totvert);
|
||||
CustomData_realloc(&me->edata, me->totedge - unode->bm_enter_totedge);
|
||||
CustomData_realloc(&me->ldata, me->totloop - unode->bm_enter_totloop);
|
||||
CustomData_realloc(&me->pdata, me->totpoly - unode->bm_enter_totpoly);
|
||||
|
||||
BKE_mesh_update_customdata_pointers(me, false);
|
||||
|
||||
me->totvert = me->totvert - unode->bm_enter_totvert;
|
||||
me->totedge = me->totedge - unode->bm_enter_totedge;
|
||||
me->totloop = me->totloop - unode->bm_enter_totloop;
|
||||
me->totpoly = me->totpoly - unode->bm_enter_totpoly;
|
||||
|
||||
BKE_mesh_calc_edges(me, false, true);
|
||||
BKE_mesh_tessface_clear(me);
|
||||
BKE_mesh_calc_normals(me);
|
||||
DAG_id_tag_update(&me->id, 0);
|
||||
WM_event_add_notifier(C, NC_GEOM | ND_DATA, me);
|
||||
|
||||
BKE_object_free_derived_caches(ob);
|
||||
} else {
|
||||
unode->applied = true;
|
||||
|
||||
int v_start_n, e_start_n, l_start_n, p_start_n;
|
||||
|
||||
v_start_n = me->totvert;
|
||||
e_start_n = me->totedge;
|
||||
l_start_n = me->totloop;
|
||||
p_start_n = me->totpoly;
|
||||
|
||||
ED_mesh_vertices_add(me, NULL, unode->bm_enter_totvert);
|
||||
ED_mesh_edges_add(me, NULL, unode->bm_enter_totedge);
|
||||
ED_mesh_loops_add(me, NULL, unode->bm_enter_totloop);
|
||||
ED_mesh_polys_add(me, NULL, unode->bm_enter_totpoly);
|
||||
|
||||
CustomData_copy_data(&unode->bm_enter_vdata, &me->vdata, v_start_n, v_start_n, unode->bm_enter_totvert);
|
||||
CustomData_copy_data(&unode->bm_enter_edata, &me->edata, e_start_n, e_start_n, unode->bm_enter_totedge);
|
||||
CustomData_copy_data(&unode->bm_enter_ldata, &me->ldata, l_start_n, l_start_n, unode->bm_enter_totloop);
|
||||
CustomData_copy_data(&unode->bm_enter_pdata, &me->pdata, p_start_n, p_start_n, unode->bm_enter_totpoly);
|
||||
|
||||
/* TODO: Not a full copy:
|
||||
CustomData_copy_data(&unode->bm_enter_vdata, &me->vdata, 0, v_start_n, unode->bm_enter_totvert);
|
||||
CustomData_copy_data(&unode->bm_enter_edata, &me->edata, 0, e_start_n, unode->bm_enter_totedge);
|
||||
CustomData_copy_data(&unode->bm_enter_ldata, &me->ldata, 0, l_start_n, unode->bm_enter_totloop);
|
||||
CustomData_copy_data(&unode->bm_enter_pdata, &me->pdata, 0, p_start_n, unode->bm_enter_totpoly);*/
|
||||
|
||||
BKE_mesh_update_customdata_pointers(me, true);
|
||||
|
||||
BKE_mesh_calc_edges(me, false, true);
|
||||
BKE_mesh_tessface_clear(me);
|
||||
BKE_mesh_calc_normals(me);
|
||||
DAG_id_tag_update(&me->id, 0);
|
||||
WM_event_add_notifier(C, NC_GEOM | ND_DATA, me);
|
||||
|
||||
BKE_object_free_derived_caches(ob);
|
||||
}
|
||||
}
|
||||
|
||||
static void sculpt_undo_restore(bContext *C, ListBase *lb)
|
||||
{
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
@@ -517,6 +587,12 @@ static void sculpt_undo_restore(bContext *C, ListBase *lb)
|
||||
case SCULPT_UNDO_DYNTOPO_SYMMETRIZE:
|
||||
BLI_assert(!"Dynamic topology should've already been handled");
|
||||
break;
|
||||
case SCULPT_UNDO_SILHOUETTE:
|
||||
sculpt_undo_silhouette_restore(C, ob, unode);
|
||||
rebuild = true;
|
||||
partial_update = false;
|
||||
return;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -711,6 +787,8 @@ static SculptUndoNode *sculpt_undo_alloc_node(Object *ob, PBVHNode *node,
|
||||
case SCULPT_UNDO_DYNTOPO_SYMMETRIZE:
|
||||
BLI_assert(!"Dynamic topology should've already been handled");
|
||||
break;
|
||||
case SCULPT_UNDO_SILHOUETTE:
|
||||
break;
|
||||
}
|
||||
|
||||
BLI_addtail(lb, unode);
|
||||
@@ -868,6 +946,7 @@ static SculptUndoNode *sculpt_undo_bmesh_push(Object *ob,
|
||||
case SCULPT_UNDO_DYNTOPO_BEGIN:
|
||||
case SCULPT_UNDO_DYNTOPO_END:
|
||||
case SCULPT_UNDO_DYNTOPO_SYMMETRIZE:
|
||||
case SCULPT_UNDO_SILHOUETTE:
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -875,6 +954,53 @@ static SculptUndoNode *sculpt_undo_bmesh_push(Object *ob,
|
||||
return unode;
|
||||
}
|
||||
|
||||
SculptUndoNode *sculpt_undo_silhouette_push(Object *ob, int v_start, int e_start, int l_start, int p_start)
|
||||
{
|
||||
/* list is manipulated by multiple threads, so we lock */
|
||||
BLI_lock_thread(LOCK_CUSTOM1);
|
||||
|
||||
ListBase *lb = undo_paint_push_get_list(UNDO_PAINT_MESH);
|
||||
SculptUndoNode *unode = lb->first;
|
||||
|
||||
if (!lb->first) {
|
||||
unode = MEM_callocN(sizeof(*unode), __func__);
|
||||
|
||||
BLI_strncpy(unode->idname, ob->id.name, sizeof(unode->idname));
|
||||
unode->type = SCULPT_UNDO_SILHOUETTE;
|
||||
unode->applied = true;
|
||||
|
||||
Mesh *me = ob->data;
|
||||
|
||||
/* Store a copy of the silhouettes current vertices, loops, and
|
||||
* polys. TODO: Add bridge edges and deleted existing geometry later */
|
||||
CustomData_copy(&me->vdata, &unode->bm_enter_vdata, CD_MASK_MESH,
|
||||
CD_DUPLICATE, me->totvert);
|
||||
CustomData_copy(&me->edata, &unode->bm_enter_edata, CD_MASK_MESH,
|
||||
CD_DUPLICATE, me->totedge);
|
||||
CustomData_copy(&me->ldata, &unode->bm_enter_ldata, CD_MASK_MESH,
|
||||
CD_DUPLICATE, me->totloop);
|
||||
CustomData_copy(&me->pdata, &unode->bm_enter_pdata, CD_MASK_MESH,
|
||||
CD_DUPLICATE, me->totpoly);
|
||||
|
||||
/*TODO: Not a full copy:
|
||||
CustomData_copy_data(&me->vdata, &unode->bm_enter_vdata, me->totvert - unode->bm_enter_totvert, 0, unode->bm_enter_totvert);
|
||||
CustomData_copy_data(&me->edata, &unode->bm_enter_edata, me->totedge - unode->bm_enter_totedge, 0, unode->bm_enter_totedge);
|
||||
CustomData_copy_data(&me->ldata, &unode->bm_enter_ldata, me->totloop - unode->bm_enter_totloop, 0, unode->bm_enter_totloop);
|
||||
CustomData_copy_data(&me->pdata, &unode->bm_enter_pdata, me->totpoly - unode->bm_enter_totpoly, 0, unode->bm_enter_totpoly);*/
|
||||
|
||||
unode->bm_enter_totvert = me->totvert - v_start;
|
||||
unode->bm_enter_totedge = me->totedge - e_start;
|
||||
unode->bm_enter_totloop = me->totloop - l_start;
|
||||
unode->bm_enter_totpoly = me->totpoly - p_start;
|
||||
|
||||
BLI_addtail(lb, unode);
|
||||
}
|
||||
|
||||
BLI_unlock_thread(LOCK_CUSTOM1);
|
||||
return unode;
|
||||
}
|
||||
|
||||
|
||||
SculptUndoNode *sculpt_undo_push_node(Object *ob, PBVHNode *node,
|
||||
SculptUndoType type)
|
||||
{
|
||||
@@ -898,6 +1024,10 @@ SculptUndoNode *sculpt_undo_push_node(Object *ob, PBVHNode *node,
|
||||
else if ((unode = sculpt_undo_get_node(node))) {
|
||||
BLI_unlock_thread(LOCK_CUSTOM1);
|
||||
return unode;
|
||||
} else if (ELEM(type,SCULPT_UNDO_SILHOUETTE)) {
|
||||
/* TODO:Remove? Should not reach. */
|
||||
BLI_unlock_thread(LOCK_CUSTOM1);
|
||||
return unode;
|
||||
}
|
||||
|
||||
unode = sculpt_undo_alloc_node(ob, node, type);
|
||||
@@ -935,6 +1065,8 @@ SculptUndoNode *sculpt_undo_push_node(Object *ob, PBVHNode *node,
|
||||
case SCULPT_UNDO_DYNTOPO_SYMMETRIZE:
|
||||
BLI_assert(!"Dynamic topology should've already been handled");
|
||||
break;
|
||||
case SCULPT_UNDO_SILHOUETTE:/*TODO: Store data?*/
|
||||
break;
|
||||
}
|
||||
|
||||
/* store active shape key */
|
||||
|
@@ -112,7 +112,7 @@ static void view3d_stereo3d_setup_offscreen(Scene *scene, View3D *v3d, ARegion *
|
||||
|
||||
/* handy utility for drawing shapes in the viewport for arbitrary code.
|
||||
* could add lines and points too */
|
||||
// #define DEBUG_DRAW
|
||||
#define DEBUG_DRAW
|
||||
#ifdef DEBUG_DRAW
|
||||
static void bl_debug_draw(void);
|
||||
/* add these locally when using these functions for testing */
|
||||
@@ -4064,8 +4064,8 @@ void view3d_main_region_draw(const bContext *C, ARegion *ar)
|
||||
|
||||
#ifdef DEBUG_DRAW
|
||||
/* debug drawing */
|
||||
#define _DEBUG_DRAW_QUAD_TOT 1024
|
||||
#define _DEBUG_DRAW_EDGE_TOT 1024
|
||||
#define _DEBUG_DRAW_QUAD_TOT 16000
|
||||
#define _DEBUG_DRAW_EDGE_TOT 16000
|
||||
static float _bl_debug_draw_quads[_DEBUG_DRAW_QUAD_TOT][4][3];
|
||||
static int _bl_debug_draw_quads_tot = 0;
|
||||
static float _bl_debug_draw_edges[_DEBUG_DRAW_QUAD_TOT][2][3];
|
||||
|
@@ -119,6 +119,8 @@ typedef struct Brush {
|
||||
|
||||
float unprojected_radius;
|
||||
|
||||
float adaptive_space_factor;
|
||||
|
||||
/* soften/sharpen */
|
||||
float sharp_threshold;
|
||||
int blur_kernel_radius;
|
||||
@@ -135,6 +137,8 @@ typedef struct Brush {
|
||||
|
||||
float mask_stencil_pos[2];
|
||||
float mask_stencil_dimension[2];
|
||||
|
||||
float pad;
|
||||
} Brush;
|
||||
|
||||
typedef struct PaletteColor {
|
||||
|
@@ -1141,7 +1141,14 @@ typedef struct Sculpt {
|
||||
/* scale for constant detail size */
|
||||
float constant_detail; /* Constant detail resolution (Blender unit / constant_detail) */
|
||||
float detail_percent;
|
||||
float pad;
|
||||
|
||||
/* silhouette settings */
|
||||
float silhouette_smoothness;
|
||||
float silhouette_depth;
|
||||
int silhouette_resolution;
|
||||
int silhouette_flags;
|
||||
|
||||
int pad;
|
||||
|
||||
struct Object *gravity_object;
|
||||
} Sculpt;
|
||||
|
@@ -1224,7 +1224,6 @@ static void rna_def_brush(BlenderRNA *brna)
|
||||
"Automatically adjust strength to give consistent results for different spacings");
|
||||
RNA_def_property_update(prop, 0, "rna_Brush_update");
|
||||
|
||||
/* adaptive space is not implemented yet */
|
||||
prop = RNA_def_property(srna, "use_adaptive_space", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flag", BRUSH_ADAPTIVE_SPACE);
|
||||
RNA_def_property_ui_text(prop, "Adaptive Spacing",
|
||||
|
@@ -647,6 +647,24 @@ static void rna_def_sculpt(BlenderRNA *brna)
|
||||
RNA_def_property_flag(prop, PROP_EDITABLE);
|
||||
RNA_def_property_ui_text(prop, "Orientation", "Object whose Z axis defines orientation of gravity");
|
||||
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL);
|
||||
|
||||
prop = RNA_def_property(srna, "silhouette_smoothness", PROP_FLOAT, PROP_PERCENTAGE);
|
||||
RNA_def_property_ui_range(prop, 0.0, 100.0, 1.0, 0.1);
|
||||
RNA_def_property_ui_text(prop, "Smoothness Factor", "Smoothness of generated silhouette");
|
||||
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL);
|
||||
|
||||
prop = RNA_def_property(srna, "silhouette_depth", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_float_default(prop, 1.0f);
|
||||
RNA_def_property_range(prop, 0.0001, FLT_MAX);
|
||||
RNA_def_property_ui_range(prop, 0.001, 1000.0, 10, 2);
|
||||
RNA_def_property_ui_text(prop, "Depth", "Depth or thickness of the generated silhouette");
|
||||
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL);
|
||||
|
||||
prop = RNA_def_property(srna, "silhouette_resolution", PROP_INT, PROP_UNSIGNED);
|
||||
RNA_def_property_int_default(prop, 3);
|
||||
RNA_def_property_ui_range(prop, 1, 8, 0, -1);
|
||||
RNA_def_property_ui_text(prop, "Subsurf resolution", "Subdivision of the generated geometry");
|
||||
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL);
|
||||
}
|
||||
|
||||
|
||||
|
Reference in New Issue
Block a user