Curve Batch Cache: Add support for loose edges and curve/surf modifier

Fixes T58298 Nurbs circle and curve dont draw in objectmode
Fixes T58107 Modified curves/surfaces/fonts do not show their eval mesh
This commit is contained in:
Clément Foucault 2018-12-14 15:23:13 +01:00
parent e4b3fe4b69
commit f371e633f9
Notes: blender-bot 2023-02-14 05:50:03 +01:00
Referenced by issue #58298, Nurbs circle and curve dont draw in objectmode
Referenced by issue #58107, Modified curves/surfaces/fonts do not show their evaluated mesh, only the displist.
6 changed files with 192 additions and 36 deletions

View File

@ -718,8 +718,14 @@ GPUBatch *DRW_cache_object_loose_edges_get(struct Object *ob)
switch (ob->type) {
case OB_MESH:
return DRW_cache_mesh_loose_edges_get(ob);
/* TODO, should match 'DRW_cache_object_surface_get' */
case OB_CURVE:
return DRW_cache_curve_loose_edges_get(ob);
case OB_SURF:
return DRW_cache_surf_loose_edges_get(ob);
case OB_FONT:
return DRW_cache_text_loose_edges_get(ob);
case OB_MBALL:
/* Cannot have any loose edge */
default:
return NULL;
}
@ -3227,7 +3233,29 @@ GPUBatch *DRW_cache_curve_surface_get(Object *ob)
BLI_assert(ob->type == OB_CURVE);
struct Curve *cu = ob->data;
return DRW_curve_batch_cache_get_triangles_with_normals(cu);
struct Mesh *mesh_eval = ob->runtime.mesh_eval;
if (mesh_eval != NULL) {
return DRW_mesh_batch_cache_get_triangles_with_normals(mesh_eval, true);
}
else {
return DRW_curve_batch_cache_get_triangles_with_normals(cu);
}
}
GPUBatch *DRW_cache_curve_loose_edges_get(Object *ob)
{
BLI_assert(ob->type == OB_CURVE);
struct Curve *cu = ob->data;
struct Mesh *mesh_eval = ob->runtime.mesh_eval;
if (mesh_eval != NULL) {
return DRW_mesh_batch_cache_get_loose_edges_with_normals(mesh_eval);
}
else {
/* TODO */
UNUSED_VARS(cu);
return NULL;
}
}
GPUBatch *DRW_cache_curve_face_wireframe_get(Object *ob)
@ -3235,7 +3263,13 @@ GPUBatch *DRW_cache_curve_face_wireframe_get(Object *ob)
BLI_assert(ob->type == OB_CURVE);
struct Curve *cu = ob->data;
return DRW_curve_batch_cache_get_wireframes_face(cu);
struct Mesh *mesh_eval = ob->runtime.mesh_eval;
if (mesh_eval != NULL) {
return DRW_mesh_batch_cache_get_wireframes_face(mesh_eval);
}
else {
return DRW_curve_batch_cache_get_wireframes_face(cu);
}
}
/* Return list of batches */
@ -3245,7 +3279,13 @@ GPUBatch **DRW_cache_curve_surface_shaded_get(
BLI_assert(ob->type == OB_CURVE);
struct Curve *cu = ob->data;
return DRW_curve_batch_cache_get_surface_shaded(cu, gpumat_array, gpumat_array_len);
struct Mesh *mesh_eval = ob->runtime.mesh_eval;
if (mesh_eval != NULL) {
return DRW_mesh_batch_cache_get_surface_shaded(mesh_eval, gpumat_array, gpumat_array_len, true, NULL, NULL, NULL);
}
else {
return DRW_curve_batch_cache_get_surface_shaded(cu, gpumat_array, gpumat_array_len);
}
}
/** \} */
@ -3294,20 +3334,49 @@ GPUBatch *DRW_cache_text_surface_get(Object *ob)
{
BLI_assert(ob->type == OB_FONT);
struct Curve *cu = ob->data;
struct Mesh *mesh_eval = ob->runtime.mesh_eval;
if (cu->editfont && (cu->flag & CU_FAST)) {
return NULL;
}
return DRW_curve_batch_cache_get_triangles_with_normals(cu);
if (mesh_eval != NULL) {
return DRW_mesh_batch_cache_get_triangles_with_normals(mesh_eval, true);
}
else {
return DRW_curve_batch_cache_get_triangles_with_normals(cu);
}
}
GPUBatch *DRW_cache_text_loose_edges_get(Object *ob)
{
BLI_assert(ob->type == OB_FONT);
struct Curve *cu = ob->data;
struct Mesh *mesh_eval = ob->runtime.mesh_eval;
if (cu->editfont && (cu->flag & CU_FAST)) {
return NULL;
}
if (mesh_eval != NULL) {
return DRW_mesh_batch_cache_get_loose_edges_with_normals(mesh_eval);
}
else {
/* TODO */
return NULL;
}
}
GPUBatch *DRW_cache_text_face_wireframe_get(Object *ob)
{
BLI_assert(ob->type == OB_FONT);
struct Curve *cu = ob->data;
struct Mesh *mesh_eval = ob->runtime.mesh_eval;
if (cu->editfont && (cu->flag & CU_FAST)) {
return NULL;
}
return DRW_curve_batch_cache_get_wireframes_face(cu);
if (mesh_eval != NULL) {
return DRW_mesh_batch_cache_get_wireframes_face(mesh_eval);
}
else {
return DRW_curve_batch_cache_get_wireframes_face(cu);
}
}
GPUBatch **DRW_cache_text_surface_shaded_get(
@ -3315,10 +3384,16 @@ GPUBatch **DRW_cache_text_surface_shaded_get(
{
BLI_assert(ob->type == OB_FONT);
struct Curve *cu = ob->data;
struct Mesh *mesh_eval = ob->runtime.mesh_eval;
if (cu->editfont && (cu->flag & CU_FAST)) {
return NULL;
}
return DRW_curve_batch_cache_get_surface_shaded(cu, gpumat_array, gpumat_array_len);
if (mesh_eval != NULL) {
return DRW_mesh_batch_cache_get_surface_shaded(mesh_eval, gpumat_array, gpumat_array_len, true, NULL, NULL, NULL);
}
else {
return DRW_curve_batch_cache_get_surface_shaded(cu, gpumat_array, gpumat_array_len);
}
}
/** \} */
@ -3333,7 +3408,21 @@ GPUBatch *DRW_cache_surf_surface_get(Object *ob)
BLI_assert(ob->type == OB_SURF);
struct Curve *cu = ob->data;
return DRW_curve_batch_cache_get_triangles_with_normals(cu);
struct Mesh *mesh_eval = ob->runtime.mesh_eval;
if (mesh_eval != NULL) {
return DRW_mesh_batch_cache_get_triangles_with_normals(mesh_eval, true);
}
else {
return DRW_curve_batch_cache_get_triangles_with_normals(cu);
}
}
GPUBatch *DRW_cache_surf_edge_wire_get(Object *ob)
{
BLI_assert(ob->type == OB_SURF);
struct Curve *cu = ob->data;
return DRW_curve_batch_cache_get_wire_edge(cu);
}
GPUBatch *DRW_cache_surf_face_wireframe_get(Object *ob)
@ -3341,7 +3430,29 @@ GPUBatch *DRW_cache_surf_face_wireframe_get(Object *ob)
BLI_assert(ob->type == OB_SURF);
struct Curve *cu = ob->data;
return DRW_curve_batch_cache_get_wireframes_face(cu);
struct Mesh *mesh_eval = ob->runtime.mesh_eval;
if (mesh_eval != NULL) {
return DRW_mesh_batch_cache_get_wireframes_face(mesh_eval);
}
else {
return DRW_curve_batch_cache_get_wireframes_face(cu);
}
}
GPUBatch *DRW_cache_surf_loose_edges_get(Object *ob)
{
BLI_assert(ob->type == OB_SURF);
struct Curve *cu = ob->data;
struct Mesh *mesh_eval = ob->runtime.mesh_eval;
if (mesh_eval != NULL) {
return DRW_mesh_batch_cache_get_loose_edges_with_normals(mesh_eval);
}
else {
/* TODO */
UNUSED_VARS(cu);
return NULL;
}
}
/* Return list of batches */
@ -3351,7 +3462,13 @@ GPUBatch **DRW_cache_surf_surface_shaded_get(
BLI_assert(ob->type == OB_SURF);
struct Curve *cu = ob->data;
return DRW_curve_batch_cache_get_surface_shaded(cu, gpumat_array, gpumat_array_len);
struct Mesh *mesh_eval = ob->runtime.mesh_eval;
if (mesh_eval != NULL) {
return DRW_mesh_batch_cache_get_surface_shaded(mesh_eval, gpumat_array, gpumat_array_len, true, NULL, NULL, NULL);
}
else {
return DRW_curve_batch_cache_get_surface_shaded(cu, gpumat_array, gpumat_array_len);
}
}
/** \} */
@ -3732,13 +3849,17 @@ bool DRW_vbo_requested(GPUVertBuf *vbo)
void drw_batch_cache_generate_requested(Object *ob)
{
struct Mesh *mesh_eval = ob->runtime.mesh_eval;
switch (ob->type) {
case OB_MESH:
DRW_mesh_batch_cache_create_requested(ob);
DRW_mesh_batch_cache_create_requested(ob, (Mesh *)ob->data);
break;
case OB_CURVE:
case OB_FONT:
case OB_SURF:
if (mesh_eval) {
DRW_mesh_batch_cache_create_requested(ob, mesh_eval);
}
DRW_curve_batch_cache_create_requested(ob);
break;
/* TODO all cases */

View File

@ -153,6 +153,7 @@ struct GPUBatch *DRW_cache_curve_surface_get(struct Object *ob);
struct GPUBatch **DRW_cache_curve_surface_shaded_get(
struct Object *ob, struct GPUMaterial **gpumat_array, uint gpumat_array_len);
struct GPUBatch *DRW_cache_curve_surface_verts_get(struct Object *ob);
struct GPUBatch *DRW_cache_curve_loose_edges_get(struct Object *ob);
struct GPUBatch *DRW_cache_curve_edge_wire_get(struct Object *ob);
struct GPUBatch *DRW_cache_curve_face_wireframe_get(Object *ob);
/* edit-mode */
@ -161,8 +162,9 @@ struct GPUBatch *DRW_cache_curve_edge_overlay_get(struct Object *ob);
struct GPUBatch *DRW_cache_curve_vert_overlay_get(struct Object *ob, bool handles);
/* Font */
struct GPUBatch *DRW_cache_text_edge_wire_get(struct Object *ob);
struct GPUBatch *DRW_cache_text_surface_get(struct Object *ob);
struct GPUBatch *DRW_cache_text_loose_edges_get(struct Object *ob);
struct GPUBatch *DRW_cache_text_edge_wire_get(struct Object *ob);
struct GPUBatch **DRW_cache_text_surface_shaded_get(
struct Object *ob, struct GPUMaterial **gpumat_array, uint gpumat_array_len);
struct GPUBatch *DRW_cache_text_face_wireframe_get(Object *ob);
@ -172,6 +174,8 @@ struct GPUBatch *DRW_cache_text_select_overlay_get(struct Object *ob);
/* Surface */
struct GPUBatch *DRW_cache_surf_surface_get(struct Object *ob);
struct GPUBatch *DRW_cache_surf_edge_wire_get(struct Object *ob);
struct GPUBatch *DRW_cache_surf_loose_edges_get(struct Object *ob);
struct GPUBatch **DRW_cache_surf_surface_shaded_get(
struct Object *ob, struct GPUMaterial **gpumat_array, uint gpumat_array_len);
struct GPUBatch *DRW_cache_surf_face_wireframe_get(Object *ob);

View File

@ -119,7 +119,7 @@ void DRW_mesh_weight_state_copy(struct DRW_MeshWeightState *wstate_dst, const st
bool DRW_mesh_weight_state_compare(const struct DRW_MeshWeightState *a, const struct DRW_MeshWeightState *b);
/* Mesh */
void DRW_mesh_batch_cache_create_requested(struct Object *ob);
void DRW_mesh_batch_cache_create_requested(struct Object *ob, struct Mesh *me);
struct GPUBatch **DRW_mesh_batch_cache_get_surface_shaded(
struct Mesh *me, struct GPUMaterial **gpumat_array, uint gpumat_array_len, bool use_hide,

View File

@ -35,7 +35,7 @@
#include "DNA_curve_types.h"
#include "BKE_curve.h"
#include "BKE_displist.h"
#include "BKE_font.h"
#include "GPU_batch.h"
@ -105,21 +105,22 @@ static void curve_render_wire_verts_edges_len_get(
BLI_assert(r_vert_len || r_edge_len);
int vert_len = 0;
int edge_len = 0;
*r_curve_len = 0;
int curve_len = 0;
for (const BevList *bl = ob_curve_cache->bev.first; bl; bl = bl->next) {
if (bl->nr > 0) {
const bool is_cyclic = bl->poly != -1;
/* Curve */
*r_curve_len += 1;
/* verts */
edge_len += (is_cyclic) ? bl->nr : bl->nr - 1;
vert_len += bl->nr;
/* edges */
edge_len += bl->nr;
if (!is_cyclic) {
edge_len -= 1;
}
curve_len += 1;
}
}
for (const DispList *dl = ob_curve_cache->disp.first; dl; dl = dl->next) {
if (ELEM(dl->type, DL_SEGM, DL_POLY)) {
BLI_assert(dl->parts == 1);
const bool is_cyclic = dl->type == DL_POLY;
edge_len += (is_cyclic) ? dl->nr : dl->nr - 1;
vert_len += dl->nr;
curve_len += 1;
}
}
if (r_vert_len) {
@ -128,6 +129,9 @@ static void curve_render_wire_verts_edges_len_get(
if (r_edge_len) {
*r_edge_len = edge_len;
}
if (r_curve_len) {
*r_curve_len = curve_len;
}
}
static int curve_render_normal_len_get(const ListBase *lb, const CurveCache *ob_curve_cache)
@ -345,7 +349,6 @@ static void curve_cd_calc_used_gpu_layers(int *cd_layers, struct GPUMaterial **g
typedef struct CurveBatchCache {
struct {
/* Split by normals if necessary. */
GPUVertBuf *pos_nor;
GPUVertBuf *curves_pos;
} ordered;
@ -570,6 +573,13 @@ static void curve_create_curves_pos(CurveRenderData *rdata, GPUVertBuf *vbo_curv
GPU_vertbuf_attr_set(vbo_curves_pos, attr_id.pos, v_idx, bevp->vec);
}
}
for (const DispList *dl = rdata->ob_curve_cache->disp.first; dl; dl = dl->next) {
if (ELEM(dl->type, DL_SEGM, DL_POLY)) {
for (int i = 0; i < dl->nr; v_idx++, i++) {
GPU_vertbuf_attr_set(vbo_curves_pos, attr_id.pos, v_idx, &((float(*)[3])dl->verts)[i]);
}
}
}
BLI_assert(v_idx == vert_len);
}
@ -601,7 +611,19 @@ static void curve_create_curves_lines(CurveRenderData *rdata, GPUIndexBuf *ibo_c
GPU_indexbuf_add_primitive_restart(&elb);
v_idx += bl->nr;
}
for (const DispList *dl = rdata->ob_curve_cache->disp.first; dl; dl = dl->next) {
if (ELEM(dl->type, DL_SEGM, DL_POLY)) {
const bool is_cyclic = dl->type == DL_POLY;
if (is_cyclic) {
GPU_indexbuf_add_generic_vert(&elb, v_idx + (dl->nr - 1));
}
for (int i = 0; i < dl->nr; i++) {
GPU_indexbuf_add_generic_vert(&elb, v_idx + i);
}
GPU_indexbuf_add_primitive_restart(&elb);
v_idx += dl->nr;
}
}
GPU_indexbuf_build_in_place(&elb, ibo_curve_lines);
}
@ -1002,10 +1024,7 @@ void DRW_curve_batch_cache_create_requested(Object *ob)
#ifdef DEBUG
/* Make sure all requested batches have been setup. */
for (int i = 0; i < sizeof(cache->batch) / sizeof(void *); ++i) {
GPUBatch **batch = (GPUBatch **)&cache->batch;
if (batch[i] != NULL) {
BLI_assert(batch[i]->verts[0] != NULL);
}
BLI_assert(!DRW_batch_requested(((GPUBatch **)&cache->batch)[i], 0));
}
#endif

View File

@ -5761,13 +5761,11 @@ void DRW_mesh_cache_uvedit(
/** \name Grouped batch generation
* \{ */
void DRW_mesh_batch_cache_create_requested(Object *ob)
/* Can be called for any surface type. Mesh *me is the final mesh. */
void DRW_mesh_batch_cache_create_requested(Object *UNUSED(ob), Mesh *me)
{
BLI_assert(ob->type == OB_MESH);
const bool use_hide = false; /* TODO */
Mesh *me = (Mesh *)ob->data;
MeshBatchCache *cache = mesh_batch_cache_get(me);
/* Init batches and request VBOs & IBOs */

View File

@ -2682,7 +2682,21 @@ static void OBJECT_cache_populate(void *vedata, Object *ob)
break;
}
case OB_SURF:
{
if (hide_object_extra) {
break;
}
struct GPUBatch *geom = DRW_cache_surf_edge_wire_get(ob);
if (geom == NULL) {
break;
}
if (theme_id == TH_UNDEFINED) {
theme_id = DRW_object_wire_theme_get(ob, view_layer, NULL);
}
DRWShadingGroup *shgroup = shgroup_theme_id_to_wire_or(sgl, theme_id, sgl->wire);
DRW_shgroup_call_object_add(shgroup, geom, ob);
break;
}
case OB_LATTICE:
{
if (ob != draw_ctx->object_edit && !BKE_object_is_in_editmode(ob)) {