Blender V4.3
grease_pencil_io.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2024 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
5#include "BLI_color.hh"
6#include "BLI_math_matrix.hh"
7#include "BLI_math_vector.h"
8#include "BLI_math_vector.hh"
9
10#include "BKE_attribute.hh"
11#include "BKE_camera.h"
12#include "BKE_context.hh"
13#include "BKE_crazyspace.hh"
14#include "BKE_curves.hh"
15#include "BKE_grease_pencil.hh"
16#include "BKE_layer.hh"
17#include "BKE_material.h"
18#include "BKE_scene.hh"
19
21#include "DNA_material_types.h"
22#include "DNA_object_types.h"
23#include "DNA_scene_types.h"
24#include "DNA_view3d_types.h"
25
27
29
30#include "ED_grease_pencil.hh"
31#include "ED_object.hh"
32#include "ED_view3d.hh"
33
34#include "UI_view2d.hh"
35
37#include <optional>
38
44
45static float get_average(const Span<float> values)
46{
47 return values.is_empty() ? 0.0f :
48 std::accumulate(values.begin(), values.end(), 0.0f) / values.size();
49}
50
52{
53 if (values.is_empty()) {
54 return ColorGeometry4f(nullptr);
55 }
56 /* ColorGeometry4f does not support arithmetic directly. */
57 Span<float4> rgba_values = values.cast<float4>();
58 float4 avg_rgba = std::accumulate(rgba_values.begin(), rgba_values.end(), float4(0)) /
59 values.size();
60 return ColorGeometry4f(avg_rgba);
61}
62
63static std::optional<float> try_get_constant_value(const VArray<float> values,
64 const float epsilon = 1e-5f)
65{
66 if (values.is_empty()) {
67 return std::nullopt;
68 }
69 const float first_value = values.first();
70 const std::optional<float> first_value_opt = std::make_optional(first_value);
72 values.index_range().drop_front(1),
73 4096,
74 first_value_opt,
75 [&](const IndexRange range, const std::optional<float> /*value*/) -> std::optional<float> {
76 for (const int i : range) {
77 if (math::abs(values[i] - first_value) > epsilon) {
78 return std::nullopt;
79 }
80 }
81 return first_value_opt;
82 },
83 [&](const std::optional<float> a, const std::optional<float> b) {
84 return (a && b) ? first_value_opt : std::nullopt;
85 });
86}
87
88IOContext::IOContext(bContext &C,
89 const ARegion *region,
90 const View3D *v3d,
91 const RegionView3D *rv3d,
92 ReportList *reports)
93 : reports(reports),
94 C(C),
95 region(region),
96 v3d(v3d),
97 rv3d(rv3d),
98 scene(CTX_data_scene(&C)),
100{
101}
102
104 : context_(context), params_(params)
105{
106}
107
109{
110 const float3 cur_loc = context_.scene->cursor.location;
111 const float3 rot = float3(0.0f);
112 const ushort local_view_bits = (context_.v3d && context_.v3d->localvd) ?
114 ushort(0);
115
117 &context_.C, OB_GREASE_PENCIL, name.c_str(), cur_loc, rot, false, local_view_bits);
118
119 return ob_gpencil;
120}
121
123 const bool stroke,
124 const bool fill)
125{
126 const ColorGeometry4f default_stroke_color = {0.0f, 0.0f, 0.0f, 1.0f};
127 const ColorGeometry4f default_fill_color = {0.5f, 0.5f, 0.5f, 1.0f};
129 /* Stroke and Fill material. */
130 if (mat_index == -1) {
131 Main *bmain = CTX_data_main(&context_.C);
132 int new_idx;
134 bmain, object_, name.c_str(), &new_idx);
135 MaterialGPencilStyle *gp_style = mat_gp->gp_style;
136 gp_style->flag &= ~GP_MATERIAL_STROKE_SHOW;
137 gp_style->flag &= ~GP_MATERIAL_FILL_SHOW;
138
139 copy_v4_v4(gp_style->stroke_rgba, default_stroke_color);
140 copy_v4_v4(gp_style->fill_rgba, default_fill_color);
141 if (stroke) {
142 gp_style->flag |= GP_MATERIAL_STROKE_SHOW;
143 }
144 if (fill) {
145 gp_style->flag |= GP_MATERIAL_FILL_SHOW;
146 }
147 mat_index = object_->totcol - 1;
148 }
149
150 return mat_index;
151}
152
154 : context_(context), params_(params)
155{
156}
157
158constexpr const char *attr_material_index = "material_index";
159
161 const bke::greasepencil::Drawing &drawing,
162 IndexMaskMemory &memory)
163{
164 const bke::CurvesGeometry &strokes = drawing.strokes();
165 const bke::AttributeAccessor attributes = strokes.attributes();
166 const VArray<int> materials = *attributes.lookup<int>(attr_material_index,
168
169 auto is_visible_curve = [&](const int curve_i) {
170 /* Check if stroke can be drawn. */
171 const IndexRange points = strokes.points_by_curve()[curve_i];
172 if (points.size() < 2) {
173 return false;
174 }
175
176 /* Check if the material is visible. */
177 const Material *material = BKE_object_material_get(const_cast<Object *>(&object),
178 materials[curve_i] + 1);
179 const MaterialGPencilStyle *gp_style = material ? material->gp_style : nullptr;
180 const bool is_hidden_material = (gp_style->flag & GP_MATERIAL_HIDE);
181 const bool is_stroke_material = (gp_style->flag & GP_MATERIAL_STROKE_SHOW);
182 if (gp_style == nullptr || is_hidden_material || !is_stroke_material) {
183 return false;
184 }
185
186 return true;
187 };
188
190 strokes.curves_range(), GrainSize(512), memory, is_visible_curve);
191}
192
193static std::optional<Bounds<float2>> compute_drawing_bounds(
194 const ARegion &region,
195 const RegionView3D &rv3d,
196 const Object &object,
197 const Object &object_eval,
198 const int layer_index,
199 const int frame_number,
200 const bke::greasepencil::Drawing &drawing)
201{
204
205 std::optional<Bounds<float2>> drawing_bounds = std::nullopt;
206
207 BLI_assert(object.type == OB_GREASE_PENCIL);
208 GreasePencil &grease_pencil = *static_cast<GreasePencil *>(object.data);
209 if (!grease_pencil.has_active_layer()) {
210 return drawing_bounds;
211 }
212
213 const Layer &layer = *grease_pencil.layers()[layer_index];
214 const float4x4 layer_to_world = layer.to_world_space(object);
215 const bke::crazyspace::GeometryDeformation deformation =
217 &object_eval, object, layer_index, frame_number);
218 const VArray<float> radii = drawing.radii();
219 const bke::CurvesGeometry &strokes = drawing.strokes();
220
221 IndexMaskMemory curve_mask_memory;
222 const IndexMask curve_mask = get_visible_strokes(object, drawing, curve_mask_memory);
223
224 curve_mask.foreach_index(GrainSize(512), [&](const int curve_i) {
225 const IndexRange points = strokes.points_by_curve()[curve_i];
226 /* Check if stroke can be drawn. */
227 if (points.size() < 2) {
228 return;
229 }
230
231 for (const int point_i : points) {
232 const float3 pos_world = math::transform_point(layer_to_world,
233 deformation.positions[point_i]);
234 float2 screen_co;
236 &region, pos_world, screen_co, V3D_PROJ_TEST_NOP);
237 if (result == V3D_PROJ_RET_OK) {
238 const float pixels = radii[point_i] / ED_view3d_pixel_size(&rv3d, pos_world);
239
240 std::optional<Bounds<float2>> point_bounds = Bounds<float2>(screen_co);
241 point_bounds->pad(pixels);
242 drawing_bounds = bounds::merge(drawing_bounds, point_bounds);
243 }
244 }
245 });
246
247 return drawing_bounds;
248}
249
250static std::optional<Bounds<float2>> compute_objects_bounds(
251 const ARegion &region,
252 const RegionView3D &rv3d,
253 const Depsgraph &depsgraph,
255 const int frame_number)
256{
259 using ObjectInfo = GreasePencilExporter::ObjectInfo;
260
261 constexpr float gap = 10.0f;
262
263 std::optional<Bounds<float2>> full_bounds = std::nullopt;
264
265 for (const ObjectInfo &info : objects) {
266 const Object *object_eval = DEG_get_evaluated_object(&depsgraph, info.object);
267 const GreasePencil &grease_pencil_eval = *static_cast<GreasePencil *>(object_eval->data);
268
269 for (const int layer_index : grease_pencil_eval.layers().index_range()) {
270 const Layer &layer = *grease_pencil_eval.layers()[layer_index];
271 const Drawing *drawing = grease_pencil_eval.get_drawing_at(layer, frame_number);
272 if (drawing == nullptr) {
273 continue;
274 }
275
276 std::optional<Bounds<float2>> layer_bounds = compute_drawing_bounds(
277 region, rv3d, *info.object, *object_eval, layer_index, frame_number, *drawing);
278
279 full_bounds = bounds::merge(full_bounds, layer_bounds);
280 }
281 }
282
283 /* Add small gap. */
284 full_bounds->pad(gap);
285
286 return full_bounds;
287}
288
290{
291 /* Ensure camera switch is applied. */
293
294 /* Calculate camera matrix. */
295 Object *cam_ob = scene.camera;
296 if (cam_ob == nullptr) {
297 /* XXX not sure when this could ever happen if v3d camera is not null,
298 * conditions are from GPv2 and not explained anywhere. */
299 return float4x4::identity();
300 }
301
302 /* Set up parameters. */
306
307 /* Compute matrix, view-plane, etc. */
309 &params, scene.r.xsch, scene.r.ysch, scene.r.xasp, scene.r.yasp);
311
312 float4x4 viewmat = math::invert(cam_ob->object_to_world());
313 return float4x4(params.winmat) * viewmat;
314}
315
316void GreasePencilExporter::prepare_render_params(Scene &scene, const int frame_number)
317{
318 const bool use_camera_view = (context_.rv3d->persp == RV3D_CAMOB) &&
319 (context_.v3d->camera != nullptr);
320
321 /* Camera rectangle. */
322 if (use_camera_view) {
323 rctf camera_rect;
329 true,
330 &camera_rect);
331 render_rect_ = {{camera_rect.xmin, camera_rect.ymin}, {camera_rect.xmax, camera_rect.ymax}};
333 }
334 else {
335 Vector<ObjectInfo> objects = this->retrieve_objects();
336 std::optional<Bounds<float2>> full_bounds = compute_objects_bounds(
337 *context_.region, *context_.rv3d, *context_.depsgraph, objects, frame_number);
338 render_rect_ = full_bounds ? *full_bounds : Bounds<float2>{float2(0.0f), float2(0.0f)};
339 camera_persmat_ = std::nullopt;
340 }
341}
342
344 const Material &material, const Span<ColorGeometry4f> vertex_colors)
345{
346 const MaterialGPencilStyle &gp_style = *material.gp_style;
347
348 const ColorGeometry4f material_color = ColorGeometry4f(gp_style.stroke_rgba);
349 const ColorGeometry4f avg_vertex_color = get_average(vertex_colors);
350 return math::interpolate(material_color, avg_vertex_color, avg_vertex_color.a);
351}
352
354{
355 return get_average(opacities);
356}
357
359 const RegionView3D &rv3d, const Span<float3> world_positions, const Span<float> radii)
360{
361 VArray<float> widths = VArray<float>::ForFunc(world_positions.size(), [&](const int index) {
362 const float3 &pos = world_positions[index];
363 const float radius = radii[index];
364 return 2.0f * radius * ED_view3d_pixel_size(&rv3d, pos);
365 });
366 return try_get_constant_value(widths);
367}
368
370{
371 using SelectMode = ExportParams::SelectMode;
372
373 Scene &scene = *CTX_data_scene(&context_.C);
374 ViewLayer *view_layer = CTX_data_view_layer(&context_.C);
375 const float3 camera_z_axis = float3(context_.rv3d->viewinv[2]);
376
377 BKE_view_layer_synced_ensure(&scene, view_layer);
378
379 Vector<ObjectInfo> objects;
380 auto add_object = [&](Object *object) {
381 if (object == nullptr || object->type != OB_GREASE_PENCIL) {
382 return;
383 }
384
385 const float3 position = object->object_to_world().location();
386
387 /* Save z-depth from view to sort from back to front. */
388 const bool use_ortho_depth = camera_persmat_ || !context_.rv3d->is_persp;
389 const float depth = use_ortho_depth ? math::dot(camera_z_axis, position) :
391 objects.append({object, depth});
392 };
393
394 switch (params_.select_mode) {
395 case SelectMode::Active:
396 add_object(params_.object);
397 break;
398 case SelectMode::Selected:
400 if (base->flag & BASE_SELECTED) {
401 add_object(base->object);
402 }
403 }
404 break;
405 case SelectMode::Visible:
407 add_object(base->object);
408 }
409 break;
410 }
411
412 /* Sort list of objects from point of view. */
413 std::sort(objects.begin(), objects.end(), [](const ObjectInfo &info1, const ObjectInfo &info2) {
414 return info1.depth < info2.depth;
415 });
416
417 return objects;
418}
419
421 const bke::greasepencil::Layer &layer,
422 const bke::greasepencil::Drawing &drawing,
423 WriteStrokeFn stroke_fn)
424{
426
427 const float4x4 layer_to_world = layer.to_world_space(object);
428 const float4x4 viewmat = float4x4(context_.rv3d->viewmat);
429 const float4x4 layer_to_view = viewmat * layer_to_world;
430
431 const bke::CurvesGeometry &curves = drawing.strokes();
432 const bke::AttributeAccessor attributes = curves.attributes();
433 /* Curve attributes. */
434 const OffsetIndices points_by_curve = curves.points_by_curve();
435 const VArray<bool> cyclic = curves.cyclic();
436 const VArraySpan<int> material_indices = *attributes.lookup_or_default<int>(
437 "material_index", bke::AttrDomain::Curve, 0);
438 const VArraySpan<ColorGeometry4f> fill_colors = drawing.fill_colors();
439 const VArray<int8_t> start_caps = *attributes.lookup_or_default<int8_t>(
441 const VArray<int8_t> end_caps = *attributes.lookup_or_default<int8_t>(
442 "end_cap", bke::AttrDomain::Curve, 0);
443 /* Point attributes. */
444 const Span<float3> positions = curves.positions();
445 const VArraySpan<float> radii = drawing.radii();
446 const VArraySpan<float> opacities = drawing.opacities();
447 const VArraySpan<ColorGeometry4f> vertex_colors = drawing.vertex_colors();
448
449 Array<float3> world_positions(positions.size());
450 threading::parallel_for(positions.index_range(), 4096, [&](const IndexRange range) {
451 for (const int i : range) {
452 world_positions[i] = math::transform_point(layer_to_world, positions[i]);
453 }
454 });
455
456 for (const int i_curve : curves.curves_range()) {
457 const IndexRange points = points_by_curve[i_curve];
458 if (points.size() < 2) {
459 continue;
460 }
461
462 const bool is_cyclic = cyclic[i_curve];
463 const int material_index = material_indices[i_curve];
464 const Material *material = BKE_object_material_get(const_cast<Object *>(&object),
465 material_index + 1);
466 BLI_assert(material->gp_style != nullptr);
467 if (material->gp_style->flag & GP_MATERIAL_HIDE) {
468 continue;
469 }
470 const bool is_stroke_material = material->gp_style->flag & GP_MATERIAL_STROKE_SHOW;
471 const bool is_fill_material = material->gp_style->flag & GP_MATERIAL_FILL_SHOW;
472
473 /* Fill. */
474 if (is_fill_material && params_.export_fill_materials) {
475 const ColorGeometry4f material_fill_color = ColorGeometry4f(material->gp_style->fill_rgba);
476 const ColorGeometry4f fill_color = math::interpolate(
477 material_fill_color, fill_colors[i_curve], fill_colors[i_curve].a);
478 stroke_fn(positions.slice(points),
479 is_cyclic,
480 fill_color,
481 layer.opacity,
482 std::nullopt,
483 false,
484 false);
485 }
486
487 /* Stroke. */
488 if (is_stroke_material && params_.export_stroke_materials) {
489 const ColorGeometry4f stroke_color = compute_average_stroke_color(
490 *material, vertex_colors.slice(points));
491 const float stroke_opacity = compute_average_stroke_opacity(opacities.slice(points)) *
492 layer.opacity;
493 const std::optional<float> uniform_width = params_.use_uniform_width ?
494 try_get_uniform_point_width(
495 *context_.rv3d,
496 world_positions.as_span().slice(points),
497 radii.slice(points)) :
498 std::nullopt;
499 if (uniform_width) {
500 const GreasePencilStrokeCapType start_cap = GreasePencilStrokeCapType(start_caps[i_curve]);
501 const GreasePencilStrokeCapType end_cap = GreasePencilStrokeCapType(end_caps[i_curve]);
502 const bool round_cap = start_cap == GP_STROKE_CAP_TYPE_ROUND ||
503 end_cap == GP_STROKE_CAP_TYPE_ROUND;
504
505 stroke_fn(positions.slice(points),
506 is_cyclic,
507 stroke_color,
508 stroke_opacity,
509 uniform_width,
510 round_cap,
511 false);
512 }
513 else {
514 const IndexMask single_curve_mask = IndexRange::from_single(i_curve);
515
516 constexpr int corner_subdivisions = 3;
517 constexpr float outline_radius = 0.0f;
518 constexpr float outline_offset = 0.0f;
519 bke::CurvesGeometry outline = ed::greasepencil::create_curves_outline(drawing,
520 single_curve_mask,
521 layer_to_view,
522 corner_subdivisions,
523 outline_radius,
524 outline_offset,
525 material_index);
526
527 /* Sample the outline stroke. */
528 if (params_.outline_resample_length > 0.0f) {
529 VArray<float> resample_lengths = VArray<float>::ForSingle(
530 params_.outline_resample_length, curves.curves_num());
531 outline = geometry::resample_to_length(outline, single_curve_mask, resample_lengths);
532 }
533
534 const OffsetIndices outline_points_by_curve = outline.points_by_curve();
535 const Span<float3> outline_positions = outline.positions();
536
537 for (const int i_outline_curve : outline.curves_range()) {
538 const IndexRange outline_points = outline_points_by_curve[i_outline_curve];
539 /* Use stroke color to fill the outline. */
540 stroke_fn(outline_positions.slice(outline_points),
541 true,
542 stroke_color,
543 stroke_opacity,
544 std::nullopt,
545 false,
546 true);
547 }
548 }
549 }
550 }
551}
552
554 const float3 &position) const
555{
556 const float3 world_pos = math::transform_point(transform, position);
557
558 if (camera_persmat_) {
559 /* Use camera render space. */
560 return (float2(math::project_point(*camera_persmat_, world_pos)) + 1.0f) / 2.0f *
561 float2(render_rect_.size());
562 }
563
564 /* Use 3D view screen space. */
565 float2 screen_co;
568 {
569 if (!ELEM(V2D_IS_CLIPPED, screen_co.x, screen_co.y)) {
570 /* Apply offset and scale. */
571 return screen_co - render_rect_.min;
572 }
573 }
574
575 return float2(V2D_IS_CLIPPED);
576}
577
578} // namespace blender::io::grease_pencil
Camera data-block and utility functions.
void BKE_camera_params_init(CameraParams *params)
void BKE_camera_params_from_object(CameraParams *params, const struct Object *cam_ob)
void BKE_camera_params_compute_viewplane(CameraParams *params, int winx, int winy, float aspx, float aspy)
void BKE_camera_params_compute_matrix(CameraParams *params)
Depsgraph * CTX_data_depsgraph_pointer(const bContext *C)
Scene * CTX_data_scene(const bContext *C)
Main * CTX_data_main(const bContext *C)
ViewLayer * CTX_data_view_layer(const bContext *C)
Low-level operations for curves.
Low-level operations for grease pencil.
Material * BKE_grease_pencil_object_material_new(Main *bmain, Object *ob, const char *name, int *r_index)
int BKE_grease_pencil_object_material_index_get_by_name(Object *ob, const char *name)
void BKE_view_layer_synced_ensure(const Scene *scene, ViewLayer *view_layer)
ListBase * BKE_view_layer_object_bases_get(ViewLayer *view_layer)
General operations, lookup, etc. for materials.
struct Material * BKE_object_material_get(struct Object *ob, short act)
bool BKE_scene_camera_switch_update(Scene *scene)
Definition scene.cc:2213
#define BLI_assert(a)
Definition BLI_assert.h:50
#define LISTBASE_FOREACH(type, var, list)
MINLINE void copy_v4_v4(float r[4], const float a[4])
unsigned short ushort
#define ELEM(...)
Object * DEG_get_evaluated_object(const Depsgraph *depsgraph, Object *object)
GreasePencilStrokeCapType
@ GP_STROKE_CAP_TYPE_ROUND
@ GP_MATERIAL_HIDE
@ GP_MATERIAL_STROKE_SHOW
@ GP_MATERIAL_FILL_SHOW
Object is a sort of wrapper for general info.
@ OB_GREASE_PENCIL
#define BASE_SELECTED(v3d, base)
@ RV3D_CAMOB
@ V3D_PROJ_TEST_NOP
Definition ED_view3d.hh:266
float ED_view3d_pixel_size(const RegionView3D *rv3d, const float co[3])
eV3DProjStatus
Definition ED_view3d.hh:242
@ V3D_PROJ_RET_OK
Definition ED_view3d.hh:243
float ED_view3d_calc_zfac(const RegionView3D *rv3d, const float co[3])
void ED_view3d_calc_camera_border(const Scene *scene, const Depsgraph *depsgraph, const ARegion *region, const View3D *v3d, const RegionView3D *rv3d, bool no_shift, rctf *r_viewborder)
eV3DProjStatus ED_view3d_project_float_global(const ARegion *region, const float co[3], float r_co[2], eV3DProjTest flag)
#define V2D_IS_CLIPPED
Definition UI_view2d.hh:21
ChannelStorageType a
Definition BLI_color.hh:88
static constexpr IndexRange from_single(const int64_t index)
Span< NewT > constexpr cast() const
Definition BLI_span.hh:419
constexpr int64_t size() const
Definition BLI_span.hh:253
constexpr const T * end() const
Definition BLI_span.hh:225
constexpr const T * begin() const
Definition BLI_span.hh:221
static VArray ForSingle(T value, const int64_t size)
static VArray ForFunc(const int64_t size, GetFunc get_func)
OffsetIndices< int > points_by_curve() const
IndexRange curves_range() const
VArray< ColorGeometry4f > vertex_colors() const
const bke::CurvesGeometry & strokes() const
VArray< ColorGeometry4f > fill_colors() const
VArray< float > opacities() const
static IndexMask from_predicate(const IndexMask &universe, GrainSize grain_size, IndexMaskMemory &memory, Fn &&predicate)
void foreach_index(Fn &&fn) const
GreasePencilExporter(const IOContext &context, const ExportParams &params)
static std::optional< float > try_get_uniform_point_width(const RegionView3D &rv3d, const Span< float3 > world_positions, const Span< float > radii)
static ColorGeometry4f compute_average_stroke_color(const Material &material, const Span< ColorGeometry4f > vertex_colors)
void prepare_render_params(Scene &scene, int frame_number)
void foreach_stroke_in_layer(const Object &object, const bke::greasepencil::Layer &layer, const bke::greasepencil::Drawing &drawing, WriteStrokeFn stroke_fn)
static float compute_average_stroke_opacity(const Span< float > opacities)
float2 project_to_screen(const float4x4 &transform, const float3 &position) const
GreasePencilImporter(const IOContext &context, const ImportParams &params)
int32_t create_material(StringRefNull name, bool stroke, bool fill)
local_group_size(16, 16) .push_constant(Type b
const Depsgraph * depsgraph
static bool is_cyclic(const Nurb *nu)
#define rot(x, k)
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
GeometryDeformation get_evaluated_grease_pencil_drawing_deformation(const Object *ob_eval, const Object &ob_orig, int layer_index, int frame)
Bounds< T > merge(const Bounds< T > &a, const Bounds< T > &b)
Definition BLI_bounds.hh:24
bke::CurvesGeometry create_curves_outline(const bke::greasepencil::Drawing &drawing, const IndexMask &strokes, const float4x4 &transform, const int corner_subdivisions, const float outline_radius, const float outline_offset, const int material_index)
Object * add_type(bContext *C, int type, const char *name, const float loc[3], const float rot[3], bool enter_editmode, unsigned short local_view_bits) ATTR_NONNULL(1) ATTR_RETURNS_NONNULL
CurvesGeometry resample_to_length(const CurvesGeometry &src_curves, const IndexMask &selection, const VArray< float > &sample_lengths, const ResampleCurvesOutputAttributeIDs &output_ids={})
static std::optional< float > try_get_constant_value(const VArray< float > values, const float epsilon=1e-5f)
static std::optional< Bounds< float2 > > compute_drawing_bounds(const ARegion &region, const RegionView3D &rv3d, const Object &object, const Object &object_eval, const int layer_index, const int frame_number, const bke::greasepencil::Drawing &drawing)
static std::optional< Bounds< float2 > > compute_objects_bounds(const ARegion &region, const RegionView3D &rv3d, const Depsgraph &depsgraph, const Span< GreasePencilExporter::ObjectInfo > objects, const int frame_number)
constexpr const char * attr_material_index
static float4x4 persmat_from_camera_object(Scene &scene)
static IndexMask get_visible_strokes(const Object &object, const bke::greasepencil::Drawing &drawing, IndexMaskMemory &memory)
static float get_average(const Span< float > values)
T dot(const QuaternionBase< T > &a, const QuaternionBase< T > &b)
CartesianBasis invert(const CartesianBasis &basis)
VectorT project_point(const MatT &mat, const VectorT &point)
T interpolate(const T &a, const T &b, const FactorT &t)
VecBase< T, 3 > transform_point(const CartesianBasis &basis, const VecBase< T, 3 > &v)
void parallel_for(const IndexRange range, const int64_t grain_size, const Function &function, const TaskSizeHints &size_hints=detail::TaskSizeHints_Static(1))
Definition BLI_task.hh:95
Value parallel_reduce(IndexRange range, int64_t grain_size, const Value &identity, const Function &function, const Reduction &reduction)
Definition BLI_task.hh:153
MatBase< float, 4, 4 > float4x4
VecBase< float, 2 > float2
ColorSceneLinear4f< eAlpha::Premultiplied > ColorGeometry4f
Definition BLI_color.hh:337
VecBase< float, 3 > float3
signed char int8_t
Definition stdint.h:75
struct MaterialGPencilStyle * gp_style
float viewmat[4][4]
float viewinv[4][4]
View3DCursor cursor
struct Object * camera
struct View3D * localvd
unsigned short local_view_uid
float xmax
float xmin
float ymax
float ymin