forked from blender/blender
GPv3: Add Compound Shapes Rendering (i.e. Hole rendering) #12
@ -87,10 +87,11 @@ class Drawing : public ::GreasePencilDrawing {
|
|||||||
const bke::CurvesGeometry &strokes() const;
|
const bke::CurvesGeometry &strokes() const;
|
||||||
bke::CurvesGeometry &strokes_for_write();
|
bke::CurvesGeometry &strokes_for_write();
|
||||||
|
|
||||||
Vector<IndexMask> get_shapes_index_masks(IndexMaskMemory &memory) const;
|
Vector<IndexMask> shapes(IndexMaskMemory &memory) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The triangles for all the fills in the geometry.
|
* The triangles for all the fills in the geometry.
|
||||||
|
* Stored per shape and indexing into points.
|
||||||
*/
|
*/
|
||||||
Span<Vector<uint3>> triangles() const;
|
Span<Vector<uint3>> triangles() const;
|
||||||
/**
|
/**
|
||||||
|
@ -367,7 +367,7 @@ Drawing::~Drawing()
|
|||||||
this->runtime = nullptr;
|
this->runtime = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector<IndexMask> Drawing::get_shapes_index_masks(IndexMaskMemory &memory) const
|
Vector<IndexMask> Drawing::shapes(IndexMaskMemory &memory) const
|
||||||
{
|
{
|
||||||
const CurvesGeometry &curves = this->strokes();
|
const CurvesGeometry &curves = this->strokes();
|
||||||
const bke::AttributeAccessor attributes = curves.attributes();
|
const bke::AttributeAccessor attributes = curves.attributes();
|
||||||
@ -525,23 +525,23 @@ Span<Vector<uint3>> Drawing::triangles() const
|
|||||||
const Array<int> point_to_curve_map = curves.point_to_curve_map();
|
const Array<int> point_to_curve_map = curves.point_to_curve_map();
|
||||||
|
|
||||||
IndexMaskMemory memory;
|
IndexMaskMemory memory;
|
||||||
const Vector<IndexMask> groups = this->get_shapes_index_masks(memory);
|
const Vector<IndexMask> shapes = this->shapes(memory);
|
||||||
|
|
||||||
r_data.resize(groups.size() + 1);
|
r_data.resize(shapes.size() + 1);
|
||||||
MutableSpan<Vector<uint3>> strokes_triangles = r_data.as_mutable_span();
|
MutableSpan<Vector<uint3>> strokes_triangles = r_data.as_mutable_span();
|
||||||
|
|
||||||
threading::EnumerableThreadSpecific<LocalMemArena> all_local_mem_arenas;
|
threading::EnumerableThreadSpecific<LocalMemArena> all_local_mem_arenas;
|
||||||
threading::parallel_for(groups.index_range(), 32, [&](const IndexRange group_range) {
|
threading::parallel_for(shapes.index_range(), 32, [&](const IndexRange shape_range) {
|
||||||
MemArena *pf_arena = all_local_mem_arenas.local().pf_arena;
|
MemArena *pf_arena = all_local_mem_arenas.local().pf_arena;
|
||||||
for (const int group_id : group_range) {
|
for (const int shape_index : shape_range) {
|
||||||
const IndexMask &group = groups[group_id];
|
const IndexMask &shape = shapes[shape_index];
|
||||||
|
|
||||||
float3x3 axis_mat;
|
float3x3 axis_mat;
|
||||||
axis_dominant_v3_to_m3(axis_mat.ptr(), normals[group.first()]);
|
axis_dominant_v3_to_m3(axis_mat.ptr(), normals[shape.first()]);
|
||||||
|
|
||||||
Array<int> offsets_data(group.size() + 1);
|
Array<int> offsets_data(shape.size() + 1);
|
||||||
offset_indices::gather_group_sizes(
|
offset_indices::gather_group_sizes(
|
||||||
points_by_curve, group, offsets_data.as_mutable_span().drop_back(1));
|
points_by_curve, shape, offsets_data.as_mutable_span().drop_back(1));
|
||||||
offset_indices::accumulate_counts_to_offsets(offsets_data);
|
offset_indices::accumulate_counts_to_offsets(offsets_data);
|
||||||
const OffsetIndices<int> points_by_group = OffsetIndices<int>(offsets_data);
|
const OffsetIndices<int> points_by_group = OffsetIndices<int>(offsets_data);
|
||||||
|
|
||||||
@ -550,7 +550,7 @@ Span<Vector<uint3>> Drawing::triangles() const
|
|||||||
float(*projverts)[2] = static_cast<float(*)[2]>(
|
float(*projverts)[2] = static_cast<float(*)[2]>(
|
||||||
BLI_memarena_alloc(pf_arena, sizeof(*projverts) * size_t(num_points)));
|
BLI_memarena_alloc(pf_arena, sizeof(*projverts) * size_t(num_points)));
|
||||||
|
|
||||||
group.foreach_index(GrainSize(256), [&](const int64_t curve_i, const int64_t pos) {
|
shape.foreach_index(GrainSize(256), [&](const int64_t curve_i, const int64_t pos) {
|
||||||
const IndexRange point_group = points_by_group[pos];
|
const IndexRange point_group = points_by_group[pos];
|
||||||
const IndexRange points = points_by_curve[curve_i];
|
const IndexRange points = points_by_curve[curve_i];
|
||||||
threading::parallel_for(points.index_range(), 512, [&](const IndexRange range) {
|
threading::parallel_for(points.index_range(), 512, [&](const IndexRange range) {
|
||||||
@ -562,14 +562,14 @@ Span<Vector<uint3>> Drawing::triangles() const
|
|||||||
|
|
||||||
/* If there is only on stroke or the geometry can not meshed then use simple poly fill
|
/* If there is only on stroke or the geometry can not meshed then use simple poly fill
|
||||||
* using the first curve in the group. */
|
* using the first curve in the group. */
|
||||||
if (group.size() == 1 ||
|
if (shape.size() == 1 ||
|
||||||
!check_valid_curves({reinterpret_cast<float2 *>(projverts), num_points},
|
!check_valid_curves({reinterpret_cast<float2 *>(projverts), num_points},
|
||||||
points_by_group))
|
points_by_group))
|
||||||
{
|
{
|
||||||
const IndexRange points = points_by_curve[group.first()];
|
const IndexRange points = points_by_curve[shape.first()];
|
||||||
|
|
||||||
strokes_triangles[group_id].resize(points.size() - 2);
|
strokes_triangles[shape_index].resize(points.size() - 2);
|
||||||
MutableSpan<uint3> r_tris = strokes_triangles[group_id];
|
MutableSpan<uint3> r_tris = strokes_triangles[shape_index];
|
||||||
BLI_polyfill_calc_arena(projverts,
|
BLI_polyfill_calc_arena(projverts,
|
||||||
points.size(),
|
points.size(),
|
||||||
0,
|
0,
|
||||||
@ -584,11 +584,11 @@ Span<Vector<uint3>> Drawing::triangles() const
|
|||||||
|
|
||||||
Array<double2> verts(num_points);
|
Array<double2> verts(num_points);
|
||||||
Array<std::pair<int, int>> edges(num_points);
|
Array<std::pair<int, int>> edges(num_points);
|
||||||
Array<Vector<int>> faces(group.size());
|
Array<Vector<int>> faces(shape.size());
|
||||||
|
|
||||||
Array<int> vert_to_point_map(num_points);
|
Array<int> vert_to_point_map(num_points);
|
||||||
|
|
||||||
group.foreach_index(GrainSize(256), [&](const int64_t curve_i, const int64_t pos) {
|
shape.foreach_index(GrainSize(256), [&](const int64_t curve_i, const int64_t pos) {
|
||||||
const IndexRange point_group = points_by_group[pos];
|
const IndexRange point_group = points_by_group[pos];
|
||||||
const IndexRange points = points_by_curve[curve_i];
|
const IndexRange points = points_by_curve[curve_i];
|
||||||
faces[pos].resize(points.size());
|
faces[pos].resize(points.size());
|
||||||
@ -611,8 +611,8 @@ Span<Vector<uint3>> Drawing::triangles() const
|
|||||||
|
|
||||||
meshintersect::CDT_result<double> result = delaunay_2d_calc(input, CDT_INSIDE_WITH_HOLES);
|
meshintersect::CDT_result<double> result = delaunay_2d_calc(input, CDT_INSIDE_WITH_HOLES);
|
||||||
|
|
||||||
strokes_triangles[group_id].resize(result.face.size());
|
strokes_triangles[shape_index].resize(result.face.size());
|
||||||
MutableSpan<uint3> r_tris = strokes_triangles[group_id];
|
MutableSpan<uint3> r_tris = strokes_triangles[shape_index];
|
||||||
|
|
||||||
threading::parallel_for(result.face.index_range(), 512, [&](const IndexRange range) {
|
threading::parallel_for(result.face.index_range(), 512, [&](const IndexRange range) {
|
||||||
for (const int i : range) {
|
for (const int i : range) {
|
||||||
|
@ -725,24 +725,24 @@ static GPENCIL_tObject *grease_pencil_object_cache_populate(GPENCIL_PrivateData
|
|||||||
IndexMaskMemory memory;
|
IndexMaskMemory memory;
|
||||||
const IndexMask visible_strokes = ed::greasepencil::retrieve_visible_strokes(
|
const IndexMask visible_strokes = ed::greasepencil::retrieve_visible_strokes(
|
||||||
*ob, info.drawing, memory);
|
*ob, info.drawing, memory);
|
||||||
const Vector<IndexMask> groups = info.drawing.get_shapes_index_masks(memory);
|
const Vector<IndexMask> shapes = info.drawing.shapes(memory);
|
||||||
|
|
||||||
/* Precompute all the triangle and vertex counts.
|
/* Precompute all the triangle and vertex counts.
|
||||||
* In case the drawing should not be rendered, we need to compute the offset where the next
|
* In case the drawing should not be rendered, we need to compute the offset where the next
|
||||||
* drawing begins. */
|
* drawing begins. */
|
||||||
Array<int> num_triangles_per_stroke(groups.size());
|
Array<int> num_triangles_per_stroke(shapes.size());
|
||||||
Array<int> num_vertices_per_stroke(visible_strokes.size());
|
Array<int> num_vertices_per_stroke(visible_strokes.size());
|
||||||
int total_num_triangles = 0;
|
int total_num_triangles = 0;
|
||||||
int total_num_vertices = 0;
|
int total_num_vertices = 0;
|
||||||
int current_curve = 0;
|
int current_curve = 0;
|
||||||
for (const int group_id : groups.index_range()) {
|
for (const int shape_index : shapes.index_range()) {
|
||||||
const IndexMask &group = groups[group_id];
|
const IndexMask &shape = shapes[shape_index];
|
||||||
|
|
||||||
const int num_stroke_triangles = triangles[group_id].size();
|
const int num_stroke_triangles = triangles[shape_index].size();
|
||||||
num_triangles_per_stroke[group_id] = num_stroke_triangles;
|
num_triangles_per_stroke[shape_index] = num_stroke_triangles;
|
||||||
total_num_triangles += num_stroke_triangles;
|
total_num_triangles += num_stroke_triangles;
|
||||||
|
|
||||||
group.foreach_index([&](const int curve_i) {
|
shape.foreach_index([&](const int curve_i) {
|
||||||
const IndexRange points = points_by_curve[curve_i];
|
const IndexRange points = points_by_curve[curve_i];
|
||||||
const int num_stroke_vertices = (points.size() +
|
const int num_stroke_vertices = (points.size() +
|
||||||
int(cyclic[curve_i] && (points.size() >= 3)));
|
int(cyclic[curve_i] && (points.size() >= 3)));
|
||||||
@ -798,10 +798,10 @@ static GPENCIL_tObject *grease_pencil_object_cache_populate(GPENCIL_PrivateData
|
|||||||
const bool is_onion = info.onion_id != 0;
|
const bool is_onion = info.onion_id != 0;
|
||||||
|
|
||||||
current_curve = 0;
|
current_curve = 0;
|
||||||
for (const int group_id : groups.index_range()) {
|
for (const int shape_index : shapes.index_range()) {
|
||||||
const IndexMask &group = groups[group_id];
|
const IndexMask &shape = shapes[shape_index];
|
||||||
|
|
||||||
const int curve_i = group.first();
|
const int curve_i = shape.first();
|
||||||
|
|
||||||
/* The material index is allowed to be negative as it's stored as a generic attribute. We
|
/* The material index is allowed to be negative as it's stored as a generic attribute. We
|
||||||
* clamp it here to avoid crashing in the rendering code. Any stroke with a material < 0
|
* clamp it here to avoid crashing in the rendering code. Any stroke with a material < 0
|
||||||
@ -811,7 +811,7 @@ static GPENCIL_tObject *grease_pencil_object_cache_populate(GPENCIL_PrivateData
|
|||||||
|
|
||||||
const bool hide_material = (gp_style->flag & GP_MATERIAL_HIDE) != 0;
|
const bool hide_material = (gp_style->flag & GP_MATERIAL_HIDE) != 0;
|
||||||
const bool show_stroke = ((gp_style->flag & GP_MATERIAL_STROKE_SHOW) != 0);
|
const bool show_stroke = ((gp_style->flag & GP_MATERIAL_STROKE_SHOW) != 0);
|
||||||
const bool show_fill = (!triangles[group_id].is_empty()) &&
|
const bool show_fill = (!triangles[shape_index].is_empty()) &&
|
||||||
((gp_style->flag & GP_MATERIAL_FILL_SHOW) != 0) &&
|
((gp_style->flag & GP_MATERIAL_FILL_SHOW) != 0) &&
|
||||||
(!pd->simplify_fill);
|
(!pd->simplify_fill);
|
||||||
const bool hide_onion = is_onion && ((gp_style->flag & GP_MATERIAL_HIDE_ONIONSKIN) != 0 ||
|
const bool hide_onion = is_onion && ((gp_style->flag & GP_MATERIAL_HIDE_ONIONSKIN) != 0 ||
|
||||||
@ -820,11 +820,11 @@ static GPENCIL_tObject *grease_pencil_object_cache_populate(GPENCIL_PrivateData
|
|||||||
(only_lines && !is_onion) || hide_onion;
|
(only_lines && !is_onion) || hide_onion;
|
||||||
|
|
||||||
if (skip_stroke) {
|
if (skip_stroke) {
|
||||||
t_offset += num_triangles_per_stroke[group_id];
|
t_offset += num_triangles_per_stroke[shape_index];
|
||||||
for (const int i : group.index_range()) {
|
for (const int i : shape.index_range()) {
|
||||||
t_offset += num_vertices_per_stroke[current_curve + i] * 2;
|
t_offset += num_vertices_per_stroke[current_curve + i] * 2;
|
||||||
};
|
};
|
||||||
current_curve += group.size();
|
current_curve += shape.size();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -870,13 +870,13 @@ static GPENCIL_tObject *grease_pencil_object_cache_populate(GPENCIL_PrivateData
|
|||||||
|
|
||||||
if (show_fill) {
|
if (show_fill) {
|
||||||
const int v_first = t_offset * 3;
|
const int v_first = t_offset * 3;
|
||||||
const int v_count = num_triangles_per_stroke[group_id] * 3;
|
const int v_count = num_triangles_per_stroke[shape_index] * 3;
|
||||||
drawcall_add(geom, v_first, v_count);
|
drawcall_add(geom, v_first, v_count);
|
||||||
}
|
}
|
||||||
|
|
||||||
t_offset += num_triangles_per_stroke[group_id];
|
t_offset += num_triangles_per_stroke[shape_index];
|
||||||
|
|
||||||
group.foreach_index([&](const int curve_i) {
|
shape.foreach_index([&](const int curve_i) {
|
||||||
const IndexRange points = points_by_curve[curve_i];
|
const IndexRange points = points_by_curve[curve_i];
|
||||||
|
|
||||||
if (show_stroke) {
|
if (show_stroke) {
|
||||||
|
@ -89,21 +89,21 @@ class GreasePencil {
|
|||||||
IndexMaskMemory memory;
|
IndexMaskMemory memory;
|
||||||
const IndexMask visible_strokes = ed::greasepencil::retrieve_visible_strokes(
|
const IndexMask visible_strokes = ed::greasepencil::retrieve_visible_strokes(
|
||||||
*ob, info.drawing, memory);
|
*ob, info.drawing, memory);
|
||||||
const Vector<IndexMask> groups = info.drawing.get_shapes_index_masks(memory);
|
const Vector<IndexMask> shapes = info.drawing.shapes(memory);
|
||||||
|
|
||||||
const Span<Vector<uint3>> triangles = info.drawing.triangles();
|
const Span<Vector<uint3>> triangles = info.drawing.triangles();
|
||||||
|
|
||||||
const bool hide_onion = info.onion_id != 0;
|
const bool hide_onion = info.onion_id != 0;
|
||||||
|
|
||||||
for (const int group_id : groups.index_range()) {
|
for (const int shape_index : shapes.index_range()) {
|
||||||
const IndexMask &group = groups[group_id];
|
const IndexMask &shape = shapes[shape_index];
|
||||||
|
|
||||||
const int material_index = stroke_materials[group.first()];
|
const int material_index = stroke_materials[shape.first()];
|
||||||
MaterialGPencilStyle *gp_style = BKE_gpencil_material_settings(ob, material_index + 1);
|
MaterialGPencilStyle *gp_style = BKE_gpencil_material_settings(ob, material_index + 1);
|
||||||
|
|
||||||
const bool hide_material = (gp_style->flag & GP_MATERIAL_HIDE) != 0;
|
const bool hide_material = (gp_style->flag & GP_MATERIAL_HIDE) != 0;
|
||||||
|
|
||||||
const int num_stroke_triangles = triangles[group_id].size();
|
const int num_stroke_triangles = triangles[shape_index].size();
|
||||||
|
|
||||||
if (hide_material || hide_onion) {
|
if (hide_material || hide_onion) {
|
||||||
t_offset += num_stroke_triangles;
|
t_offset += num_stroke_triangles;
|
||||||
@ -123,7 +123,7 @@ class GreasePencil {
|
|||||||
|
|
||||||
t_offset += num_stroke_triangles;
|
t_offset += num_stroke_triangles;
|
||||||
|
|
||||||
group.foreach_index([&](const int curve_i) {
|
shape.foreach_index([&](const int curve_i) {
|
||||||
const IndexRange points = points_by_curve[curve_i];
|
const IndexRange points = points_by_curve[curve_i];
|
||||||
|
|
||||||
const int num_stroke_vertices = (points.size() +
|
const int num_stroke_vertices = (points.size() +
|
||||||
|
@ -323,20 +323,20 @@ static void OVERLAY_outline_grease_pencil(OVERLAY_PrivateData *pd, Scene *scene,
|
|||||||
IndexMaskMemory memory;
|
IndexMaskMemory memory;
|
||||||
const IndexMask visible_strokes = ed::greasepencil::retrieve_visible_strokes(
|
const IndexMask visible_strokes = ed::greasepencil::retrieve_visible_strokes(
|
||||||
*ob, info.drawing, memory);
|
*ob, info.drawing, memory);
|
||||||
const Vector<IndexMask> groups = info.drawing.get_shapes_index_masks(memory);
|
const Vector<IndexMask> shapes = info.drawing.shapes(memory);
|
||||||
|
|
||||||
const Span<Vector<uint3>> triangles = info.drawing.triangles();
|
const Span<Vector<uint3>> triangles = info.drawing.triangles();
|
||||||
|
|
||||||
for (const int group_id : groups.index_range()) {
|
for (const int shape_index : shapes.index_range()) {
|
||||||
const IndexMask &group = groups[group_id];
|
const IndexMask &shape = shapes[shape_index];
|
||||||
|
|
||||||
const int material_index = stroke_materials[group.first()];
|
const int material_index = stroke_materials[shape.first()];
|
||||||
MaterialGPencilStyle *gp_style = BKE_gpencil_material_settings(ob, material_index + 1);
|
MaterialGPencilStyle *gp_style = BKE_gpencil_material_settings(ob, material_index + 1);
|
||||||
|
|
||||||
const bool hide_onion = info.onion_id != 0;
|
const bool hide_onion = info.onion_id != 0;
|
||||||
const bool hide_material = (gp_style->flag & GP_MATERIAL_HIDE) != 0;
|
const bool hide_material = (gp_style->flag & GP_MATERIAL_HIDE) != 0;
|
||||||
|
|
||||||
const int num_stroke_triangles = triangles[group_id].size();
|
const int num_stroke_triangles = triangles[shape_index].size();
|
||||||
|
|
||||||
const bool show_stroke = (gp_style->flag & GP_MATERIAL_STROKE_SHOW) != 0;
|
const bool show_stroke = (gp_style->flag & GP_MATERIAL_STROKE_SHOW) != 0;
|
||||||
const bool show_fill = (num_stroke_triangles != 0) &&
|
const bool show_fill = (num_stroke_triangles != 0) &&
|
||||||
@ -352,7 +352,7 @@ static void OVERLAY_outline_grease_pencil(OVERLAY_PrivateData *pd, Scene *scene,
|
|||||||
|
|
||||||
t_offset += num_stroke_triangles;
|
t_offset += num_stroke_triangles;
|
||||||
|
|
||||||
group.foreach_index([&](const int curve_i) {
|
shape.foreach_index([&](const int curve_i) {
|
||||||
const IndexRange points = points_by_curve[curve_i];
|
const IndexRange points = points_by_curve[curve_i];
|
||||||
const int num_stroke_vertices = (points.size() +
|
const int num_stroke_vertices = (points.size() +
|
||||||
int(cyclic[curve_i] && (points.size() >= 3)));
|
int(cyclic[curve_i] && (points.size() >= 3)));
|
||||||
|
@ -1194,7 +1194,7 @@ static void grease_pencil_geom_batch_ensure(Object &object,
|
|||||||
GPU_indexbuf_add_tri_verts(&ibo, v_mat + 2, v_mat + 1, v_mat + 3);
|
GPU_indexbuf_add_tri_verts(&ibo, v_mat + 2, v_mat + 1, v_mat + 3);
|
||||||
};
|
};
|
||||||
|
|
||||||
const Vector<IndexMask> groups = info.drawing.get_shapes_index_masks(memory);
|
const Vector<IndexMask> shapes = info.drawing.shapes(memory);
|
||||||
const Array<int> point_to_curve_map = curves.point_to_curve_map();
|
const Array<int> point_to_curve_map = curves.point_to_curve_map();
|
||||||
|
|
||||||
auto point_to_id = [&](uint32_t p) {
|
auto point_to_id = [&](uint32_t p) {
|
||||||
@ -1203,9 +1203,9 @@ static void grease_pencil_geom_batch_ensure(Object &object,
|
|||||||
return (1 + (p - points_.first()) + verts_start_offsets[curve_]) << GP_VERTEX_ID_SHIFT;
|
return (1 + (p - points_.first()) + verts_start_offsets[curve_]) << GP_VERTEX_ID_SHIFT;
|
||||||
};
|
};
|
||||||
|
|
||||||
for (const int group_id : groups.index_range()) {
|
for (const int shape_index : shapes.index_range()) {
|
||||||
const IndexMask &group = groups[group_id];
|
const IndexMask &shape = shapes[shape_index];
|
||||||
const Span<uint3> tris_slice = triangles[group_id];
|
const Span<uint3> tris_slice = triangles[shape_index];
|
||||||
|
|
||||||
/* Add the triangle indices to the index buffer. */
|
/* Add the triangle indices to the index buffer. */
|
||||||
for (const uint3 tri : tris_slice) {
|
for (const uint3 tri : tris_slice) {
|
||||||
@ -1213,10 +1213,10 @@ static void grease_pencil_geom_batch_ensure(Object &object,
|
|||||||
GPU_indexbuf_add_tri_verts(&ibo, tri_verts.x, tri_verts.y, tri_verts.z);
|
GPU_indexbuf_add_tri_verts(&ibo, tri_verts.x, tri_verts.y, tri_verts.z);
|
||||||
}
|
}
|
||||||
|
|
||||||
const float4x2 texture_matrix = texture_matrices[group.first()] *
|
const float4x2 texture_matrix = texture_matrices[shape.first()] *
|
||||||
object_space_to_layer_space;
|
object_space_to_layer_space;
|
||||||
|
|
||||||
group.foreach_index([&](const int curve_i) {
|
shape.foreach_index([&](const int curve_i) {
|
||||||
const IndexRange points = points_by_curve[curve_i];
|
const IndexRange points = points_by_curve[curve_i];
|
||||||
const bool is_cyclic = cyclic[curve_i] && (points.size() > 2);
|
const bool is_cyclic = cyclic[curve_i] && (points.size() > 2);
|
||||||
const int verts_start_offset = verts_start_offsets[curve_i];
|
const int verts_start_offset = verts_start_offsets[curve_i];
|
||||||
|
Loading…
Reference in New Issue
Block a user