Fix T62941 Subdivision Modifier Showing all face dots

Previously in 2.79 we were using a specialized drawing using derivedMesh.

Now the subsurf modifier tag each center vertex as facedot and let the
DRWManager pick it up.

Some modifiers (deforming ones) do not clear the tag so we can use this
technique even if there is deforming modifiers after subsurf modifiers.
This commit is contained in:
Clément Foucault 2019-07-07 18:58:11 +02:00
parent 0a16519f5d
commit 226c6f086a
Notes: blender-bot 2023-02-14 08:24:03 +01:00
Referenced by commit 7bf820fb96, Fix uninitialized loop variable
Referenced by issue #66630, X-Ray + Subdivision surface Face select problem
Referenced by issue #62941, Subdivision Modifier Showing all face dots instead of just the nonsubdivided dot.
8 changed files with 227 additions and 29 deletions

View File

@ -59,6 +59,11 @@ void BKE_mesh_foreach_mapped_face_center(
void (*func)(void *userData, int index, const float cent[3], const float no[3]),
void *userData,
MeshForeachFlag flag);
void BKE_mesh_foreach_mapped_subdiv_face_center(
struct Mesh *mesh,
void (*func)(void *userData, int index, const float cent[3], const float no[3]),
void *userData,
MeshForeachFlag flag);
void BKE_mesh_foreach_mapped_vert_coords_get(struct Mesh *me_eval,
float (*r_cos)[3],

View File

@ -382,6 +382,7 @@ struct Object *modifiers_isDeformedByMeshDeform(struct Object *ob);
struct Object *modifiers_isDeformedByLattice(struct Object *ob);
struct Object *modifiers_isDeformedByCurve(struct Object *ob);
bool modifiers_usesArmature(struct Object *ob, struct bArmature *arm);
bool modifiers_usesSubsurfFacedots(struct Scene *scene, struct Object *ob);
bool modifiers_isCorrectableDeformed(struct Scene *scene, struct Object *ob);
void modifier_freeTemporaryData(struct ModifierData *md);
bool modifiers_isPreview(struct Object *ob);

View File

@ -180,6 +180,54 @@ void BKE_mesh_foreach_mapped_face_center(
}
}
/* Copied from cdDM_foreachMappedFaceCenter */
void BKE_mesh_foreach_mapped_subdiv_face_center(
Mesh *mesh,
void (*func)(void *userData, int index, const float cent[3], const float no[3]),
void *userData,
MeshForeachFlag flag)
{
const MPoly *mp = mesh->mpoly;
const MLoop *ml;
const MVert *mv;
float _no_buf[3];
float *no = (flag & MESH_FOREACH_USE_NORMAL) ? _no_buf : NULL;
const int *index = CustomData_get_layer(&mesh->pdata, CD_ORIGINDEX);
if (index) {
for (int i = 0; i < mesh->totpoly; i++, mp++) {
const int orig = *index++;
if (orig == ORIGINDEX_NONE) {
continue;
}
ml = &mesh->mloop[mp->loopstart];
for (int j = 0; j < mp->totloop; j++, ml++) {
mv = &mesh->mvert[ml->v];
if (mv->flag & ME_VERT_FACEDOT) {
if (flag & MESH_FOREACH_USE_NORMAL) {
normal_short_to_float_v3(no, mv->no);
}
func(userData, orig, mv->co, no);
}
}
}
}
else {
for (int i = 0; i < mesh->totpoly; i++, mp++) {
ml = &mesh->mloop[mp->loopstart];
for (int j = 0; j < mp->totloop; j++, ml++) {
mv = &mesh->mvert[ml->v];
if (mv->flag & ME_VERT_FACEDOT) {
if (flag & MESH_FOREACH_USE_NORMAL) {
normal_short_to_float_v3(no, mv->no);
}
func(userData, i, mv->co, no);
}
}
}
}
}
/* Helpers based on above foreach loopers> */
typedef struct MappedVCosData {

View File

@ -778,6 +778,38 @@ bool modifiers_usesArmature(Object *ob, bArmature *arm)
return false;
}
bool modifiers_usesSubsurfFacedots(struct Scene *scene, Object *ob)
{
/* Search (backward) in the modifier stack to find if we have a subsurf modifier (enabled) before
* the last modifier displayed on cage (or if the subsurf is the last). */
VirtualModifierData virtualModifierData;
ModifierData *md = modifiers_getVirtualModifierList(ob, &virtualModifierData);
int cage_index = modifiers_getCageIndex(scene, ob, NULL, 1);
/* Find first modifier enabled on cage. */
for (int i; md && i < cage_index; i++) {
md = md->next;
}
/* Now from this point, search for subsurf modifier. */
for (; md; md = md->prev) {
const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
if (md->type == eModifierType_Subsurf) {
ModifierMode mode = eModifierMode_Realtime | eModifierMode_Editmode;
if (modifier_isEnabled(scene, md, mode)) {
return true;
}
}
else if (mti->type == eModifierTypeType_OnlyDeform) {
/* Theses modifiers do not reset the subdiv flag nor change the topology.
* We can still search for a subsurf modifier. */
}
else {
/* Other modifiers may reset the subdiv facedot flag or create. */
return false;
}
}
return false;
}
bool modifier_isCorrectableDeformed(ModifierData *md)
{
const ModifierTypeInfo *mti = modifierType_getInfo(md->type);

View File

@ -570,6 +570,8 @@ static void evaluate_vertex_and_apply_displacement_copy(const SubdivMeshContext
normalize_v3(N);
normal_float_to_short_v3(subdiv_vert->no, N);
}
/* Remove facedot flag. This can happen if there is more than one subsurf modifier. */
subdiv_vert->flag &= ~ME_VERT_FACEDOT;
}
static void evaluate_vertex_and_apply_displacement_interpolate(
@ -719,6 +721,31 @@ static void subdiv_mesh_vertex_edge(const SubdivForeachContext *foreach_context,
ctx, ptex_face_index, u, v, &tls->vertex_interpolation, subdiv_vert);
}
static bool subdiv_mesh_is_center_vertex(const MPoly *coarse_poly, const float u, const float v)
{
if (coarse_poly->totloop == 4) {
if (u == 0.5f && v == 0.5f) {
return true;
}
}
else {
if (u == 1.0f && v == 1.0f) {
return true;
}
}
return false;
}
static void subdiv_mesh_tag_center_vertex(const MPoly *coarse_poly,
MVert *subdiv_vert,
const float u,
const float v)
{
if (subdiv_mesh_is_center_vertex(coarse_poly, u, v)) {
subdiv_vert->flag |= ME_VERT_FACEDOT;
}
}
static void subdiv_mesh_vertex_inner(const SubdivForeachContext *foreach_context,
void *tls_v,
const int ptex_face_index,
@ -741,6 +768,7 @@ static void subdiv_mesh_vertex_inner(const SubdivForeachContext *foreach_context
subdiv_vertex_data_interpolate(ctx, subdiv_vert, &tls->vertex_interpolation, u, v);
eval_final_point_and_vertex_normal(
subdiv, ptex_face_index, u, v, subdiv_vert->co, subdiv_vert->no);
subdiv_mesh_tag_center_vertex(coarse_poly, subdiv_vert, u, v);
}
/* =============================================================================
@ -1098,8 +1126,8 @@ static void setup_foreach_callbacks(const SubdivMeshContext *subdiv_context,
foreach_context->vertex_every_edge = subdiv_mesh_vertex_every_edge;
}
else {
foreach_context->vertex_every_corner = NULL;
foreach_context->vertex_every_edge = NULL;
foreach_context->vertex_every_corner = subdiv_mesh_vertex_every_corner;
foreach_context->vertex_every_edge = subdiv_mesh_vertex_every_edge;
}
foreach_context->vertex_corner = subdiv_mesh_vertex_corner;
foreach_context->vertex_edge = subdiv_mesh_vertex_edge;

View File

@ -47,6 +47,7 @@
#include "BKE_mesh.h"
#include "BKE_mesh_tangent.h"
#include "BKE_mesh_runtime.h"
#include "BKE_modifier.h"
#include "BKE_object_deform.h"
#include "atomic_ops.h"
@ -1813,6 +1814,36 @@ static bool add_edit_facedot_mapped(MeshRenderData *rdata,
return true;
}
static bool add_edit_facedot_subdiv(MeshRenderData *rdata,
GPUVertBuf *vbo,
const uint fdot_pos_id,
const uint fdot_nor_flag_id,
const int vert,
const int poly,
const int base_vert_idx)
{
BLI_assert(rdata->types & (MR_DATATYPE_VERT | MR_DATATYPE_LOOP | MR_DATATYPE_POLY));
const int *p_origindex = rdata->mapped.p_origindex;
const int p_orig = p_origindex[poly];
if (p_orig == ORIGINDEX_NONE) {
return false;
}
BMEditMesh *em = rdata->edit_bmesh;
const BMFace *efa = BM_face_at_index(em->bm, p_orig);
if (BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) {
return false;
}
Mesh *me_cage = em->mesh_eval_cage;
const MVert *mvert = &me_cage->mvert[vert];
GPUPackedNormal nor = GPU_normal_convert_i10_s3(mvert->no);
nor.w = BM_elem_flag_test(efa, BM_ELEM_SELECT) ? ((efa == em->bm->act_face) ? -1 : 1) : 0;
GPU_vertbuf_attr_set(vbo, fdot_nor_flag_id, base_vert_idx, &nor);
GPU_vertbuf_attr_set(vbo, fdot_pos_id, base_vert_idx, mvert->co);
return true;
}
/** \} */
@ -2722,7 +2753,10 @@ static void mesh_create_edit_vertex_loops(MeshRenderData *rdata,
}
/* TODO: We could use gl_PrimitiveID as index instead of using another VBO. */
static void mesh_create_edit_facedots_select_id(MeshRenderData *rdata, GPUVertBuf *vbo)
static void mesh_create_edit_facedots_select_id(MeshRenderData *rdata,
GPUVertBuf *vbo,
Scene *scene,
Object *ob)
{
const int poly_len = mesh_render_data_polys_len_get_maybe_mapped(rdata);
@ -2757,12 +2791,32 @@ static void mesh_create_edit_facedots_select_id(MeshRenderData *rdata, GPUVertBu
}
else {
const int *p_origindex = rdata->mapped.p_origindex;
for (int poly = 0; poly < poly_len; poly++) {
const int p_orig = p_origindex[poly];
if (p_orig != ORIGINDEX_NONE) {
const BMFace *efa = BM_face_at_index(rdata->edit_bmesh->bm, p_orig);
if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) {
*((uint *)GPU_vertbuf_raw_step(&idx_step)) = p_orig;
if (modifiers_usesSubsurfFacedots(scene, ob)) {
Mesh *me_cage = rdata->mapped.me_cage;
const MPoly *mpoly = me_cage->mpoly;
for (int p = 0; p < poly_len; p++, mpoly++) {
const int p_orig = p_origindex[p];
if (p_orig != ORIGINDEX_NONE) {
const MLoop *mloop = me_cage->mloop + mpoly->loopstart;
for (int l = 0; l < mpoly->totloop; l++, mloop++) {
if (me_cage->mvert[mloop->v].flag & ME_VERT_FACEDOT) {
const BMFace *efa = BM_face_at_index(rdata->edit_bmesh->bm, p_orig);
if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) {
*((uint *)GPU_vertbuf_raw_step(&idx_step)) = p_orig;
}
}
}
}
}
}
else {
for (int poly = 0; poly < poly_len; poly++) {
const int p_orig = p_origindex[poly];
if (p_orig != ORIGINDEX_NONE) {
const BMFace *efa = BM_face_at_index(rdata->edit_bmesh->bm, p_orig);
if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) {
*((uint *)GPU_vertbuf_raw_step(&idx_step)) = p_orig;
}
}
}
}
@ -3372,7 +3426,10 @@ static void mesh_create_loop_vcol(MeshRenderData *rdata, GPUVertBuf *vbo)
#undef USE_COMP_MESH_DATA
}
static void mesh_create_edit_facedots(MeshRenderData *rdata, GPUVertBuf *vbo_facedots_pos_nor_data)
static void mesh_create_edit_facedots(MeshRenderData *rdata,
GPUVertBuf *vbo_facedots_pos_nor_data,
Scene *scene,
Object *ob)
{
const int poly_len = mesh_render_data_polys_len_get_maybe_mapped(rdata);
const int verts_facedot_len = poly_len;
@ -3414,21 +3471,37 @@ static void mesh_create_edit_facedots(MeshRenderData *rdata, GPUVertBuf *vbo_fac
}
}
else {
#if 0 /* TODO(fclem): Mapped facedots are not following the original face. */
Mesh *me_cage = rdata->mapped.me_cage;
const MVert *mvert = me_cage->mvert;
const MEdge *medge = me_cage->medge;
const int *e_origindex = rdata->mapped.e_origindex;
const int *v_origindex = rdata->mapped.v_origindex;
#endif
for (int i = 0; i < poly_len; i++) {
if (add_edit_facedot_mapped(rdata,
vbo_facedots_pos_nor_data,
attr_id.fdot_pos,
attr_id.fdot_nor_flag,
i,
facedot_len_used)) {
facedot_len_used += 1;
if (modifiers_usesSubsurfFacedots(scene, ob)) {
/* Facedots that follow surbsurf face center. */
Mesh *me_cage = rdata->mapped.me_cage;
const MPoly *mpoly = me_cage->mpoly;
for (int p = 0; p < poly_len; p++, mpoly++) {
const MLoop *mloop = me_cage->mloop + mpoly->loopstart;
for (int l = 0; l < mpoly->totloop; l++, mloop++) {
if (me_cage->mvert[mloop->v].flag & ME_VERT_FACEDOT) {
if (add_edit_facedot_subdiv(rdata,
vbo_facedots_pos_nor_data,
attr_id.fdot_pos,
attr_id.fdot_nor_flag,
mloop->v,
p,
facedot_len_used)) {
facedot_len_used += 1;
}
}
}
}
}
else {
for (int i = 0; i < poly_len; i++) {
if (add_edit_facedot_mapped(rdata,
vbo_facedots_pos_nor_data,
attr_id.fdot_pos,
attr_id.fdot_nor_flag,
i,
facedot_len_used)) {
facedot_len_used += 1;
}
}
}
}
@ -5447,10 +5520,12 @@ void DRW_mesh_batch_cache_create_requested(
cache->edit.loop_face_idx);
}
if (DRW_vbo_requested(cache->edit.facedots_pos_nor_data)) {
mesh_create_edit_facedots(rdata, cache->edit.facedots_pos_nor_data);
Scene *scene = DRW_context_state_get()->scene;
mesh_create_edit_facedots(rdata, cache->edit.facedots_pos_nor_data, scene, ob);
}
if (DRW_vbo_requested(cache->edit.facedots_idx)) {
mesh_create_edit_facedots_select_id(rdata, cache->edit.facedots_idx);
Scene *scene = DRW_context_state_get()->scene;
mesh_create_edit_facedots_select_id(rdata, cache->edit.facedots_idx, scene, ob);
}
if (DRW_ibo_requested(cache->ibo.edit_loops_points) ||
DRW_ibo_requested(cache->ibo.edit_loops_lines)) {

View File

@ -38,6 +38,7 @@
#include "BKE_editmesh.h"
#include "BKE_mesh_runtime.h"
#include "BKE_mesh_iterators.h"
#include "BKE_modifier.h"
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_query.h"
@ -293,8 +294,15 @@ void mesh_foreachScreenFace(
data.clip_flag = clip_flag;
BM_mesh_elem_table_ensure(vc->em->bm, BM_FACE);
BKE_mesh_foreach_mapped_face_center(
me, mesh_foreachScreenFace__mapFunc, &data, MESH_FOREACH_NOP);
if (modifiers_usesSubsurfFacedots(vc->scene, vc->obedit)) {
BKE_mesh_foreach_mapped_subdiv_face_center(
me, mesh_foreachScreenFace__mapFunc, &data, MESH_FOREACH_NOP);
}
else {
BKE_mesh_foreach_mapped_face_center(
me, mesh_foreachScreenFace__mapFunc, &data, MESH_FOREACH_NOP);
}
}
/* ------------------------------------------------------------------------ */

View File

@ -394,6 +394,7 @@ enum {
/* SELECT = (1 << 0), */
ME_VERT_TMP_TAG = (1 << 2),
ME_HIDE = (1 << 4),
ME_VERT_FACEDOT = (1 << 5),
/* ME_VERT_MERGED = (1 << 6), */
ME_VERT_PBVH_UPDATE = (1 << 7),
};