diff options
Diffstat (limited to 'source/blender/draw/intern/draw_cache_impl_curve.cc')
-rw-r--r-- | source/blender/draw/intern/draw_cache_impl_curve.cc | 288 |
1 files changed, 28 insertions, 260 deletions
diff --git a/source/blender/draw/intern/draw_cache_impl_curve.cc b/source/blender/draw/intern/draw_cache_impl_curve.cc index 6a3d3fa5e9e..7b8f34b999c 100644 --- a/source/blender/draw/intern/draw_cache_impl_curve.cc +++ b/source/blender/draw/intern/draw_cache_impl_curve.cc @@ -19,9 +19,9 @@ #include "DNA_curve_types.h" #include "BKE_curve.h" +#include "BKE_curves.hh" #include "BKE_displist.h" #include "BKE_geometry_set.hh" -#include "BKE_spline.hh" #include "BKE_vfont.h" #include "GPU_batch.h" @@ -96,18 +96,19 @@ static void curve_render_overlay_verts_edges_len_get(ListBase *lb, } } -static void curve_eval_render_wire_verts_edges_len_get(const CurveEval &curve_eval, +static void curve_eval_render_wire_verts_edges_len_get(const blender::bke::CurvesGeometry &curves, int *r_curve_len, int *r_vert_len, int *r_edge_len) { - Span<SplinePtr> splines = curve_eval.splines(); - *r_curve_len = splines.size(); - *r_vert_len = 0; + *r_curve_len = curves.curves_num(); + *r_vert_len = curves.evaluated_points_num(); + *r_edge_len = 0; - for (const SplinePtr &spline : splines) { - *r_vert_len += spline->evaluated_points_size(); - *r_edge_len += spline->evaluated_edges_size(); + const blender::VArray<bool> cyclic = curves.cyclic(); + for (const int i : curves.curves_range()) { + const IndexRange points = curves.evaluated_points_for_curve(i); + *r_edge_len += blender::bke::curves::curve_segment_size(points.size(), cyclic[i]); } } @@ -165,7 +166,7 @@ struct CurveRenderData { CurveCache *ob_curve_cache; /* Owned by the evaluated object's geometry set (#geometry_set_eval). */ - const CurveEval *curve_eval; + const Curves *curve_eval; /* borrow from 'Curve' */ ListBase *nurbs; @@ -209,10 +210,11 @@ static CurveRenderData *curve_render_data_create(Curve *cu, if (types & CU_DATATYPE_WIRE) { if (rdata->curve_eval != nullptr) { - curve_eval_render_wire_verts_edges_len_get(*rdata->curve_eval, - &rdata->wire.curve_len, - &rdata->wire.vert_len, - &rdata->wire.edge_len); + curve_eval_render_wire_verts_edges_len_get( + blender::bke::CurvesGeometry::wrap(rdata->curve_eval->geometry), + &rdata->wire.curve_len, + &rdata->wire.vert_len, + &rdata->wire.edge_len); } } @@ -288,107 +290,39 @@ static int curve_render_data_normal_len_get(const CurveRenderData *rdata) return rdata->normal.len; } -static void curve_cd_calc_used_gpu_layers(CustomDataMask *cd_layers, - struct GPUMaterial **gpumat_array, - int gpumat_array_len) -{ - for (int i = 0; i < gpumat_array_len; i++) { - struct GPUMaterial *gpumat = gpumat_array[i]; - if (gpumat == nullptr) { - continue; - } - - ListBase gpu_attrs = GPU_material_attributes(gpumat); - LISTBASE_FOREACH (GPUMaterialAttribute *, gpu_attr, &gpu_attrs) { - const char *name = gpu_attr->name; - int type = gpu_attr->type; - - /* Curves cannot have named layers. - * NOTE: We could relax this assumption later. */ - if (name[0] != '\0') { - continue; - } - - if (type == CD_AUTO_FROM_NAME) { - type = CD_MTFACE; - } - - switch (type) { - case CD_MTFACE: - *cd_layers |= CD_MASK_MLOOPUV; - break; - case CD_TANGENT: - *cd_layers |= CD_MASK_TANGENT; - break; - case CD_MCOL: - /* Curve object don't have Color data. */ - break; - case CD_ORCO: - *cd_layers |= CD_MASK_ORCO; - break; - case CD_HAIRLENGTH: - *cd_layers |= CD_MASK_HAIRLENGTH; - break; - } - } - } -} - /* ---------------------------------------------------------------------- */ /* Curve GPUBatch Cache */ struct CurveBatchCache { struct { - GPUVertBuf *pos_nor; - GPUVertBuf *edge_fac; GPUVertBuf *curves_pos; - - GPUVertBuf *loop_pos_nor; - GPUVertBuf *loop_uv; - GPUVertBuf *loop_tan; } ordered; struct { - /* Curve points. Aligned with ordered.pos_nor */ GPUVertBuf *curves_nor; - GPUVertBuf *curves_weight; /* TODO. */ /* Edit points (beztriples and bpoints) */ GPUVertBuf *pos; GPUVertBuf *data; } edit; struct { - GPUIndexBuf *surfaces_tris; - GPUIndexBuf *surfaces_lines; GPUIndexBuf *curves_lines; - GPUIndexBuf *edges_adj_lines; /* Edit mode */ GPUIndexBuf *edit_verts; GPUIndexBuf *edit_lines; } ibo; struct { - GPUBatch *surfaces; - GPUBatch *surfaces_edges; GPUBatch *curves; /* control handles and vertices */ GPUBatch *edit_edges; GPUBatch *edit_verts; GPUBatch *edit_normals; - GPUBatch *edge_detection; } batch; - GPUIndexBuf **surf_per_mat_tris; - GPUBatch **surf_per_mat; - int mat_len; - CustomDataMask cd_used, cd_needed; - /* settings to determine if cache is invalid */ bool is_dirty; bool is_editmode; - - /* Valid only if edge_detection is up to date. */ - bool is_manifold; }; /* GPUBatch cache management. */ @@ -401,10 +335,6 @@ static bool curve_batch_cache_valid(Curve *cu) return false; } - if (cache->mat_len != DRW_curve_material_count_get(cu)) { - return false; - } - if (cache->is_dirty) { return false; } @@ -445,13 +375,6 @@ static void curve_batch_cache_init(Curve *cu) } #endif - cache->cd_used = 0; - cache->mat_len = DRW_curve_material_count_get(cu); - cache->surf_per_mat_tris = (GPUIndexBuf **)MEM_callocN( - sizeof(*cache->surf_per_mat_tris) * cache->mat_len, __func__); - cache->surf_per_mat = (GPUBatch **)MEM_callocN(sizeof(*cache->surf_per_mat) * cache->mat_len, - __func__); - cache->is_editmode = (cu->editnurb != nullptr) || (cu->editfont != nullptr); cache->is_dirty = false; @@ -514,15 +437,6 @@ static void curve_batch_cache_clear(Curve *cu) GPUBatch **batch = (GPUBatch **)&cache->batch; GPU_BATCH_DISCARD_SAFE(batch[i]); } - - for (int i = 0; i < cache->mat_len; i++) { - GPU_INDEXBUF_DISCARD_SAFE(cache->surf_per_mat_tris[i]); - GPU_BATCH_DISCARD_SAFE(cache->surf_per_mat[i]); - } - MEM_SAFE_FREE(cache->surf_per_mat_tris); - MEM_SAFE_FREE(cache->surf_per_mat); - cache->mat_len = 0; - cache->cd_used = 0; } void DRW_curve_batch_cache_free(Curve *cu) @@ -554,18 +468,10 @@ static void curve_create_curves_pos(CurveRenderData *rdata, GPUVertBuf *vbo_curv GPU_vertbuf_init_with_format(vbo_curves_pos, &format); GPU_vertbuf_data_alloc(vbo_curves_pos, vert_len); - const CurveEval &curve_eval = *rdata->curve_eval; - Span<SplinePtr> splines = curve_eval.splines(); - Array<int> offsets = curve_eval.evaluated_point_offsets(); - BLI_assert(offsets.last() == vert_len); - - for (const int i_spline : splines.index_range()) { - Span<float3> positions = splines[i_spline]->evaluated_positions(); - for (const int i_point : positions.index_range()) { - GPU_vertbuf_attr_set( - vbo_curves_pos, attr_id.pos, offsets[i_spline] + i_point, positions[i_point]); - } - } + const blender::bke::CurvesGeometry &curves = blender::bke::CurvesGeometry::wrap( + rdata->curve_eval->geometry); + const Span<float3> positions = curves.evaluated_positions(); + GPU_vertbuf_attr_fill(vbo_curves_pos, attr_id.pos, positions.data()); } static void curve_create_curves_lines(CurveRenderData *rdata, GPUIndexBuf *ibo_curve_lines) @@ -583,18 +489,16 @@ static void curve_create_curves_lines(CurveRenderData *rdata, GPUIndexBuf *ibo_c GPUIndexBufBuilder elb; GPU_indexbuf_init_ex(&elb, GPU_PRIM_LINE_STRIP, index_len, vert_len); - const CurveEval &curve_eval = *rdata->curve_eval; - Span<SplinePtr> splines = curve_eval.splines(); - Array<int> offsets = curve_eval.evaluated_point_offsets(); - BLI_assert(offsets.last() == vert_len); - - for (const int i_spline : splines.index_range()) { - const int eval_size = splines[i_spline]->evaluated_points_size(); - if (splines[i_spline]->is_cyclic() && splines[i_spline]->evaluated_edges_size() > 1) { - GPU_indexbuf_add_generic_vert(&elb, offsets[i_spline] + eval_size - 1); + const blender::bke::CurvesGeometry &curves = blender::bke::CurvesGeometry::wrap( + rdata->curve_eval->geometry); + const blender::VArray<bool> cyclic = curves.cyclic(); + for (const int i : curves.curves_range()) { + const IndexRange points = curves.evaluated_points_for_curve(i); + if (cyclic[i] && points.size() > 1) { + GPU_indexbuf_add_generic_vert(&elb, points.last()); } - for (const int i_point : IndexRange(eval_size)) { - GPU_indexbuf_add_generic_vert(&elb, offsets[i_spline] + i_point); + for (const int i_point : points) { + GPU_indexbuf_add_generic_vert(&elb, i_point); } GPU_indexbuf_add_primitive_restart(&elb); } @@ -883,55 +787,6 @@ GPUBatch *DRW_curve_batch_cache_get_edit_verts(Curve *cu) return DRW_batch_request(&cache->batch.edit_verts); } -GPUBatch *DRW_curve_batch_cache_get_triangles_with_normals(struct Curve *cu) -{ - CurveBatchCache *cache = curve_batch_cache_get(cu); - return DRW_batch_request(&cache->batch.surfaces); -} - -GPUBatch **DRW_curve_batch_cache_get_surface_shaded(struct Curve *cu, - struct GPUMaterial **gpumat_array, - uint gpumat_array_len) -{ - CurveBatchCache *cache = curve_batch_cache_get(cu); - - BLI_assert(gpumat_array_len == cache->mat_len); - - curve_cd_calc_used_gpu_layers(&cache->cd_needed, gpumat_array, gpumat_array_len); - - for (int i = 0; i < cache->mat_len; i++) { - DRW_batch_request(&cache->surf_per_mat[i]); - } - return cache->surf_per_mat; -} - -GPUVertBuf *DRW_curve_batch_cache_pos_vertbuf_get(struct Curve *cu) -{ - CurveBatchCache *cache = curve_batch_cache_get(cu); - /* Request surface to trigger the vbo filling. Otherwise it may do nothing. */ - DRW_batch_request(&cache->batch.surfaces); - - DRW_vbo_request(nullptr, &cache->ordered.loop_pos_nor); - return cache->ordered.loop_pos_nor; -} - -GPUBatch *DRW_curve_batch_cache_get_wireframes_face(Curve *cu) -{ - CurveBatchCache *cache = curve_batch_cache_get(cu); - return DRW_batch_request(&cache->batch.surfaces_edges); -} - -GPUBatch *DRW_curve_batch_cache_get_edge_detection(Curve *cu, bool *r_is_manifold) -{ - CurveBatchCache *cache = curve_batch_cache_get(cu); - /* Even if is_manifold is not correct (not updated), - * the default (not manifold) is just the worst case. */ - if (r_is_manifold) { - *r_is_manifold = cache->is_manifold; - } - return DRW_batch_request(&cache->batch.edge_detection); -} - int DRW_curve_material_count_get(Curve *cu) { return max_ii(1, cu->totcol); @@ -950,36 +805,11 @@ void DRW_curve_batch_cache_create_requested(Object *ob, const struct Scene *scen Curve *cu = (Curve *)ob->data; CurveBatchCache *cache = curve_batch_cache_get(cu); - /* Verify that all surface batches have needed attribute layers. */ - /* TODO(fclem): We could be a bit smarter here and only do it per material. */ - if ((cache->cd_used & cache->cd_needed) != cache->cd_needed) { - for (int i = 0; i < cache->mat_len; i++) { - /* We can't discard batches at this point as they have been - * referenced for drawing. Just clear them in place. */ - GPU_BATCH_CLEAR_SAFE(cache->surf_per_mat[i]); - } - - cache->cd_used |= cache->cd_needed; - cache->cd_needed = 0; - } - /* Init batches and request VBOs & IBOs */ - if (DRW_batch_requested(cache->batch.surfaces, GPU_PRIM_TRIS)) { - DRW_vbo_request(cache->batch.surfaces, &cache->ordered.loop_pos_nor); - } - if (DRW_batch_requested(cache->batch.surfaces_edges, GPU_PRIM_LINES)) { - DRW_ibo_request(cache->batch.surfaces_edges, &cache->ibo.surfaces_lines); - DRW_vbo_request(cache->batch.surfaces_edges, &cache->ordered.pos_nor); - DRW_vbo_request(cache->batch.surfaces_edges, &cache->ordered.edge_fac); - } if (DRW_batch_requested(cache->batch.curves, GPU_PRIM_LINE_STRIP)) { DRW_ibo_request(cache->batch.curves, &cache->ibo.curves_lines); DRW_vbo_request(cache->batch.curves, &cache->ordered.curves_pos); } - if (DRW_batch_requested(cache->batch.edge_detection, GPU_PRIM_LINES_ADJ)) { - DRW_ibo_request(cache->batch.edge_detection, &cache->ibo.edges_adj_lines); - DRW_vbo_request(cache->batch.edge_detection, &cache->ordered.pos_nor); - } /* Edit mode */ if (DRW_batch_requested(cache->batch.edit_edges, GPU_PRIM_LINES)) { @@ -995,20 +825,6 @@ void DRW_curve_batch_cache_create_requested(Object *ob, const struct Scene *scen if (DRW_batch_requested(cache->batch.edit_normals, GPU_PRIM_LINES)) { DRW_vbo_request(cache->batch.edit_normals, &cache->edit.curves_nor); } - for (int i = 0; i < cache->mat_len; i++) { - if (DRW_batch_requested(cache->surf_per_mat[i], GPU_PRIM_TRIS)) { - if (cache->mat_len > 1) { - DRW_ibo_request(cache->surf_per_mat[i], &cache->surf_per_mat_tris[i]); - } - if (cache->cd_used & CD_MASK_MLOOPUV) { - DRW_vbo_request(cache->surf_per_mat[i], &cache->ordered.loop_uv); - } - if (cache->cd_used & CD_MASK_TANGENT) { - DRW_vbo_request(cache->surf_per_mat[i], &cache->ordered.loop_tan); - } - DRW_vbo_request(cache->surf_per_mat[i], &cache->ordered.loop_pos_nor); - } - } #ifdef DRW_DEBUG_MESH_CACHE_REQUEST printf("-- %s %s --\n", __func__, ob->id.name + 2); @@ -1016,76 +832,28 @@ void DRW_curve_batch_cache_create_requested(Object *ob, const struct Scene *scen /* Generate MeshRenderData flags */ int mr_flag = 0; - DRW_ADD_FLAG_FROM_VBO_REQUEST(mr_flag, cache->ordered.pos_nor, CU_DATATYPE_SURFACE); - DRW_ADD_FLAG_FROM_VBO_REQUEST(mr_flag, cache->ordered.edge_fac, CU_DATATYPE_SURFACE); DRW_ADD_FLAG_FROM_VBO_REQUEST(mr_flag, cache->ordered.curves_pos, CU_DATATYPE_WIRE); - DRW_ADD_FLAG_FROM_VBO_REQUEST(mr_flag, cache->ordered.loop_pos_nor, CU_DATATYPE_SURFACE); - DRW_ADD_FLAG_FROM_VBO_REQUEST(mr_flag, cache->ordered.loop_uv, CU_DATATYPE_SURFACE); - DRW_ADD_FLAG_FROM_VBO_REQUEST(mr_flag, cache->ordered.loop_tan, CU_DATATYPE_SURFACE); - DRW_ADD_FLAG_FROM_IBO_REQUEST(mr_flag, cache->ibo.surfaces_tris, CU_DATATYPE_SURFACE); - DRW_ADD_FLAG_FROM_IBO_REQUEST(mr_flag, cache->ibo.surfaces_lines, CU_DATATYPE_SURFACE); DRW_ADD_FLAG_FROM_IBO_REQUEST(mr_flag, cache->ibo.curves_lines, CU_DATATYPE_WIRE); - DRW_ADD_FLAG_FROM_IBO_REQUEST(mr_flag, cache->ibo.edges_adj_lines, CU_DATATYPE_SURFACE); DRW_ADD_FLAG_FROM_VBO_REQUEST(mr_flag, cache->edit.pos, CU_DATATYPE_OVERLAY); DRW_ADD_FLAG_FROM_VBO_REQUEST(mr_flag, cache->edit.data, CU_DATATYPE_OVERLAY); DRW_ADD_FLAG_FROM_VBO_REQUEST(mr_flag, cache->edit.curves_nor, CU_DATATYPE_NORMAL); - DRW_ADD_FLAG_FROM_VBO_REQUEST(mr_flag, cache->edit.curves_weight, CU_DATATYPE_OVERLAY); DRW_ADD_FLAG_FROM_IBO_REQUEST(mr_flag, cache->ibo.edit_verts, CU_DATATYPE_OVERLAY); DRW_ADD_FLAG_FROM_IBO_REQUEST(mr_flag, cache->ibo.edit_lines, CU_DATATYPE_OVERLAY); - for (int i = 0; i < cache->mat_len; i++) { - DRW_ADD_FLAG_FROM_IBO_REQUEST(mr_flag, cache->surf_per_mat_tris[i], CU_DATATYPE_SURFACE); - } - #ifdef DRW_DEBUG_MESH_CACHE_REQUEST printf(" mr_flag %d\n\n", mr_flag); #endif CurveRenderData *rdata = curve_render_data_create(cu, ob->runtime.curve_cache, mr_flag); - /* The object's curve cache can be empty (in one case because we use #CurveEval's cache instead), - * If so, point to an empty DispList list to avoid the need to check for null in the following - * functions. */ - ListBase empty_lb = {nullptr, nullptr}; - ListBase *lb = rdata->ob_curve_cache == nullptr ? &empty_lb : &rdata->ob_curve_cache->disp; - /* Generate VBOs */ - if (DRW_vbo_requested(cache->ordered.pos_nor)) { - DRW_displist_vertbuf_create_pos_and_nor(lb, cache->ordered.pos_nor, scene); - } - if (DRW_vbo_requested(cache->ordered.edge_fac)) { - DRW_displist_vertbuf_create_wiredata(lb, cache->ordered.edge_fac); - } if (DRW_vbo_requested(cache->ordered.curves_pos)) { curve_create_curves_pos(rdata, cache->ordered.curves_pos); } - - if (DRW_vbo_requested(cache->ordered.loop_pos_nor) || - DRW_vbo_requested(cache->ordered.loop_uv) || DRW_vbo_requested(cache->ordered.loop_tan)) { - DRW_displist_vertbuf_create_loop_pos_and_nor_and_uv_and_tan( - lb, cache->ordered.loop_pos_nor, cache->ordered.loop_uv, cache->ordered.loop_tan, scene); - } - - if (DRW_ibo_requested(cache->surf_per_mat_tris[0])) { - DRW_displist_indexbuf_create_triangles_loop_split_by_material( - lb, cache->surf_per_mat_tris, cache->mat_len); - } - if (DRW_ibo_requested(cache->ibo.curves_lines)) { curve_create_curves_lines(rdata, cache->ibo.curves_lines); } - if (DRW_ibo_requested(cache->ibo.surfaces_tris)) { - DRW_displist_indexbuf_create_triangles_in_order(lb, cache->ibo.surfaces_tris); - } - if (DRW_ibo_requested(cache->ibo.surfaces_lines)) { - DRW_displist_indexbuf_create_lines_in_order(lb, cache->ibo.surfaces_lines); - } - if (DRW_ibo_requested(cache->ibo.edges_adj_lines)) { - DRW_displist_indexbuf_create_edges_adjacency_lines( - lb, cache->ibo.edges_adj_lines, &cache->is_manifold); - } - if (DRW_vbo_requested(cache->edit.pos) || DRW_vbo_requested(cache->edit.data) || DRW_ibo_requested(cache->ibo.edit_verts) || DRW_ibo_requested(cache->ibo.edit_lines)) { curve_create_edit_data_and_handles( |