Blender V4.5
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_bounds.hh"
6#include "BLI_color.hh"
7#include "BLI_listbase.h"
8#include "BLI_math_matrix.hh"
9#include "BLI_math_vector.h"
10#include "BLI_math_vector.hh"
11
12#include "BKE_attribute.hh"
13#include "BKE_camera.h"
14#include "BKE_context.hh"
15#include "BKE_crazyspace.hh"
16#include "BKE_curves.hh"
17#include "BKE_grease_pencil.hh"
18#include "BKE_layer.hh"
19#include "BKE_material.hh"
20#include "BKE_scene.hh"
21
23#include "DNA_material_types.h"
24#include "DNA_object_types.h"
25#include "DNA_scene_types.h"
26#include "DNA_view3d_types.h"
27
29
31
32#include "ED_grease_pencil.hh"
33#include "ED_object.hh"
34#include "ED_view3d.hh"
35
36#include "UI_view2d.hh"
37
39
40#include <numeric>
41#include <optional>
46
48
49static float get_average(const Span<float> values)
50{
51 return values.is_empty() ? 0.0f :
52 std::accumulate(values.begin(), values.end(), 0.0f) / values.size();
53}
54
56{
57 if (values.is_empty()) {
58 return ColorGeometry4f(nullptr);
59 }
60 /* ColorGeometry4f does not support arithmetic directly. */
61 Span<float4> rgba_values = values.cast<float4>();
62 float4 avg_rgba = std::accumulate(rgba_values.begin(), rgba_values.end(), float4(0)) /
63 values.size();
64 return ColorGeometry4f(avg_rgba);
65}
81
86
88{
89 const float3 cur_loc = context_.scene->cursor.location;
90 const float3 rot = float3(0.0f);
91 const ushort local_view_bits = (context_.v3d && context_.v3d->localvd) ?
92 context_.v3d->local_view_uid :
93 ushort(0);
94
96 &context_.C, OB_GREASE_PENCIL, name.c_str(), cur_loc, rot, false, local_view_bits);
97
98 return ob_gpencil;
99}
100
102 const bool stroke,
103 const bool fill)
104{
105 const ColorGeometry4f default_stroke_color = {0.0f, 0.0f, 0.0f, 1.0f};
106 const ColorGeometry4f default_fill_color = {0.5f, 0.5f, 0.5f, 1.0f};
108 /* Stroke and Fill material. */
109 if (mat_index == -1) {
110 Main *bmain = CTX_data_main(&context_.C);
111 int new_idx;
113 bmain, object_, name.c_str(), &new_idx);
114 MaterialGPencilStyle *gp_style = mat_gp->gp_style;
115 gp_style->flag &= ~GP_MATERIAL_STROKE_SHOW;
116 gp_style->flag &= ~GP_MATERIAL_FILL_SHOW;
117
118 copy_v4_v4(gp_style->stroke_rgba, default_stroke_color);
119 copy_v4_v4(gp_style->fill_rgba, default_fill_color);
120 if (stroke) {
121 gp_style->flag |= GP_MATERIAL_STROKE_SHOW;
122 }
123 if (fill) {
124 gp_style->flag |= GP_MATERIAL_FILL_SHOW;
125 }
126 mat_index = object_->totcol - 1;
127 }
128
129 return mat_index;
130}
131
136
137std::optional<Bounds<float2>> GreasePencilExporter::compute_screen_space_drawing_bounds(
138 const RegionView3D &rv3d,
139 Object &object,
140 const int layer_index,
141 const bke::greasepencil::Drawing &drawing)
142{
145
146 std::optional<Bounds<float2>> drawing_bounds = std::nullopt;
147
148 BLI_assert(object.type == OB_GREASE_PENCIL);
149 GreasePencil &grease_pencil = *static_cast<GreasePencil *>(object.data);
150
151 const Layer &layer = *grease_pencil.layers()[layer_index];
152 const float4x4 layer_to_world = layer.to_world_space(object);
153 const VArray<float> radii = drawing.radii();
154 const bke::CurvesGeometry &strokes = drawing.strokes();
155 const Span<float3> positions = strokes.positions();
156
157 IndexMaskMemory memory;
159 object, drawing, memory);
160
161 visible_strokes.foreach_index(GrainSize(512), [&](const int curve_i) {
162 const IndexRange points = strokes.points_by_curve()[curve_i];
163
164 for (const int point_i : points) {
165 const float2 screen_co = this->project_to_screen(layer_to_world, positions[point_i]);
166
167 if (screen_co.x != V2D_IS_CLIPPED) {
168 const float3 world_pos = math::transform_point(layer_to_world, positions[point_i]);
169 const float pixels = radii[point_i] / ED_view3d_pixel_size(&rv3d, world_pos);
170
171 std::optional<Bounds<float2>> point_bounds = Bounds<float2>(screen_co);
172 point_bounds->pad(pixels);
173 drawing_bounds = bounds::merge(drawing_bounds, point_bounds);
174 }
175 }
176 });
177
178 return drawing_bounds;
179}
180
181std::optional<Bounds<float2>> GreasePencilExporter::compute_objects_bounds(
182 const RegionView3D &rv3d,
183 const Depsgraph &depsgraph,
184 const Span<GreasePencilExporter::ObjectInfo> objects,
185 const int frame_number)
186{
187 using bke::greasepencil::Drawing;
188 using bke::greasepencil::Layer;
189 using ObjectInfo = GreasePencilExporter::ObjectInfo;
190
191 constexpr float gap = 10.0f;
192
193 std::optional<Bounds<float2>> full_bounds = std::nullopt;
194
195 for (const ObjectInfo &info : objects) {
196 Object *object_eval = DEG_get_evaluated(&depsgraph, info.object);
197 const GreasePencil &grease_pencil_eval = *static_cast<GreasePencil *>(object_eval->data);
198
199 for (const int layer_index : grease_pencil_eval.layers().index_range()) {
200 const Layer &layer = *grease_pencil_eval.layers()[layer_index];
201 const Drawing *drawing = grease_pencil_eval.get_drawing_at(layer, frame_number);
202 if (drawing == nullptr) {
203 continue;
204 }
205
206 std::optional<Bounds<float2>> layer_bounds = this->compute_screen_space_drawing_bounds(
207 rv3d, *object_eval, layer_index, *drawing);
208
209 full_bounds = bounds::merge(full_bounds, layer_bounds);
210 }
211 }
212
213 /* Add small gap. */
214 full_bounds->pad(gap);
215
216 return full_bounds;
217}
218
220{
221 /* Ensure camera switch is applied. */
223
224 /* Calculate camera matrix. */
225 Object *cam_ob = scene.camera;
226 if (cam_ob == nullptr) {
227 /* XXX not sure when this could ever happen if v3d camera is not null,
228 * conditions are from GPv2 and not explained anywhere. */
229 return float4x4::identity();
230 }
231
232 /* Set up parameters. */
236
237 /* Compute matrix, view-plane, etc. */
239 &params, scene.r.xsch, scene.r.ysch, scene.r.xasp, scene.r.yasp);
241
242 float4x4 viewmat = math::invert(cam_ob->object_to_world());
243 return float4x4(params.winmat) * viewmat;
244}
245
246void GreasePencilExporter::prepare_render_params(Scene &scene, const int frame_number)
247{
248 const bool use_camera_view = (context_.rv3d->persp == RV3D_CAMOB) &&
249 (context_.v3d->camera != nullptr);
250
251 if (use_camera_view) {
252 /* Camera rectangle (in screen space). */
253 rctf camera_rect;
255 context_.depsgraph,
256 context_.region,
257 context_.v3d,
258 context_.rv3d,
259 true,
260 &camera_rect);
261 screen_rect_ = {{camera_rect.xmin, camera_rect.ymin}, {camera_rect.xmax, camera_rect.ymax}};
263
264 /* Output resolution (when in camera view). */
265 int width, height;
266 BKE_render_resolution(&scene.r, false, &width, &height);
267 camera_rect_ = {{0.0f, 0.0f}, {float(width), float(height)}};
268 /* Compute factor that remaps screen_rect to final output resolution. */
269 BLI_assert(screen_rect_.size() != float2(0.0f));
271 }
272 else {
273 Vector<ObjectInfo> objects = this->retrieve_objects();
274 std::optional<Bounds<float2>> full_bounds = this->compute_objects_bounds(
275 *context_.rv3d, *context_.depsgraph, objects, frame_number);
276 screen_rect_ = full_bounds ? *full_bounds : Bounds<float2>(float2(0.0f));
277 camera_persmat_ = std::nullopt;
278 }
279}
280
282 const Material &material, const Span<ColorGeometry4f> vertex_colors)
283{
284 const MaterialGPencilStyle &gp_style = *material.gp_style;
285
286 const ColorGeometry4f material_color = ColorGeometry4f(gp_style.stroke_rgba);
287 const ColorGeometry4f avg_vertex_color = get_average(vertex_colors);
288 return math::interpolate(material_color, avg_vertex_color, avg_vertex_color.a);
289}
290
292{
293 return get_average(opacities);
294}
295
297 const RegionView3D &rv3d, const Span<float3> world_positions, const Span<float> radii)
298{
299 if (world_positions.is_empty()) {
300 return std::nullopt;
301 }
302 BLI_assert(world_positions.size() == radii.size());
303 Array<float> widths(world_positions.size());
304 threading::parallel_for(widths.index_range(), 4096, [&](const IndexRange range) {
305 for (const int index : range) {
306 const float3 &pos = world_positions[index];
307 const float radius = radii[index];
308 /* Compute the width in screen space by dividing by the pixel size at the point position. */
309 widths[index] = 2.0f * radius / ED_view3d_pixel_size(&rv3d, pos);
310 }
311 });
312 return get_average(widths);
313}
314
316{
317 using SelectMode = ExportParams::SelectMode;
318
319 Scene &scene = *CTX_data_scene(&context_.C);
320 ViewLayer *view_layer = CTX_data_view_layer(&context_.C);
321 const float3 camera_z_axis = float3(context_.rv3d->viewinv[2]);
322
323 BKE_view_layer_synced_ensure(&scene, view_layer);
324
325 Vector<ObjectInfo> objects;
326 auto add_object = [&](Object *object) {
327 if (object == nullptr || object->type != OB_GREASE_PENCIL) {
328 return;
329 }
330
331 const float3 position = object->object_to_world().location();
332
333 /* Save z-depth from view to sort from back to front. */
334 const bool use_ortho_depth = camera_persmat_ || !context_.rv3d->is_persp;
335 const float depth = use_ortho_depth ? math::dot(camera_z_axis, position) :
336 -ED_view3d_calc_zfac(context_.rv3d, position);
337 objects.append({object, depth});
338 };
339
340 switch (params_.select_mode) {
341 case SelectMode::Active:
342 add_object(params_.object);
343 break;
344 case SelectMode::Selected:
346 if (base->flag & BASE_SELECTED) {
347 add_object(base->object);
348 }
349 }
350 break;
351 case SelectMode::Visible:
353 add_object(base->object);
354 }
355 break;
356 }
357
358 /* Sort list of objects from point of view. */
359 std::sort(objects.begin(), objects.end(), [](const ObjectInfo &info1, const ObjectInfo &info2) {
360 return info1.depth < info2.depth;
361 });
362
363 return objects;
364}
365
367 const bke::greasepencil::Layer &layer,
368 const bke::greasepencil::Drawing &drawing,
369 WriteStrokeFn stroke_fn)
370{
372
373 const float4x4 layer_to_world = layer.to_world_space(object);
374 const float4x4 viewmat = float4x4(context_.rv3d->viewmat);
375 const float4x4 layer_to_view = viewmat * layer_to_world;
376
377 const bke::CurvesGeometry &curves = drawing.strokes();
378 const bke::AttributeAccessor attributes = curves.attributes();
379 /* Curve attributes. */
380 const OffsetIndices points_by_curve = curves.points_by_curve();
381 const VArray<bool> cyclic = curves.cyclic();
382 const VArraySpan<int> material_indices = *attributes.lookup_or_default<int>(
383 "material_index", bke::AttrDomain::Curve, 0);
384 const VArraySpan<ColorGeometry4f> fill_colors = drawing.fill_colors();
385 const VArray<int8_t> start_caps = *attributes.lookup_or_default<int8_t>(
387 const VArray<int8_t> end_caps = *attributes.lookup_or_default<int8_t>(
388 "end_cap", bke::AttrDomain::Curve, 0);
389 /* Point attributes. */
390 const Span<float3> positions = curves.positions();
391 const VArraySpan<float> radii = drawing.radii();
392 const VArraySpan<float> opacities = drawing.opacities();
393 const VArraySpan<ColorGeometry4f> vertex_colors = drawing.vertex_colors();
394
395 Array<float3> world_positions(positions.size());
396 threading::parallel_for(positions.index_range(), 4096, [&](const IndexRange range) {
397 for (const int i : range) {
398 world_positions[i] = math::transform_point(layer_to_world, positions[i]);
399 }
400 });
401
402 for (const int i_curve : curves.curves_range()) {
403 const IndexRange points = points_by_curve[i_curve];
404 if (points.size() < 2) {
405 continue;
406 }
407
408 const bool is_cyclic = cyclic[i_curve];
409 const int material_index = material_indices[i_curve];
410 const Material *material = [&]() {
411 const Material *material = BKE_object_material_get(const_cast<Object *>(&object),
412 material_index + 1);
413 if (!material) {
414 const Material *material_default = BKE_material_default_gpencil();
415 return material_default;
416 }
417 return material;
418 }();
419
420 BLI_assert(material->gp_style != nullptr);
421 if (material->gp_style->flag & GP_MATERIAL_HIDE) {
422 continue;
423 }
424 const bool is_stroke_material = (material->gp_style->flag & GP_MATERIAL_STROKE_SHOW);
425 const bool is_fill_material = (material->gp_style->flag & GP_MATERIAL_FILL_SHOW);
426
427 /* Fill. */
428 if (is_fill_material && params_.export_fill_materials) {
429 const ColorGeometry4f material_fill_color = ColorGeometry4f(material->gp_style->fill_rgba);
430 const ColorGeometry4f fill_color = math::interpolate(
431 material_fill_color, fill_colors[i_curve], fill_colors[i_curve].a);
432 stroke_fn(positions.slice(points),
433 is_cyclic,
434 fill_color,
435 layer.opacity,
436 std::nullopt,
437 false,
438 false);
439 }
440
441 /* Stroke. */
442 if (is_stroke_material && params_.export_stroke_materials) {
443 const ColorGeometry4f stroke_color = compute_average_stroke_color(
444 *material, vertex_colors.slice(points));
445 const float stroke_opacity = compute_average_stroke_opacity(opacities.slice(points)) *
446 layer.opacity;
447 const std::optional<float> uniform_width = params_.use_uniform_width ?
448 try_get_uniform_point_width(
449 *context_.rv3d,
450 world_positions.as_span().slice(points),
451 radii.slice(points)) :
452 std::nullopt;
453 if (uniform_width) {
454 const GreasePencilStrokeCapType start_cap = GreasePencilStrokeCapType(start_caps[i_curve]);
455 const GreasePencilStrokeCapType end_cap = GreasePencilStrokeCapType(end_caps[i_curve]);
456 const bool round_cap = start_cap == GP_STROKE_CAP_TYPE_ROUND ||
457 end_cap == GP_STROKE_CAP_TYPE_ROUND;
458
459 stroke_fn(positions.slice(points),
460 is_cyclic,
461 stroke_color,
462 stroke_opacity,
463 uniform_width,
464 round_cap,
465 false);
466 }
467 else {
468 const IndexMask single_curve_mask = IndexRange::from_single(i_curve);
469
470 constexpr int corner_subdivisions = 3;
471 constexpr float outline_radius = 0.0f;
472 constexpr float outline_offset = 0.0f;
473 bke::CurvesGeometry outline = ed::greasepencil::create_curves_outline(drawing,
474 single_curve_mask,
475 layer_to_view,
476 corner_subdivisions,
477 outline_radius,
478 outline_offset,
479 material_index);
480
481 /* Sample the outline stroke. */
482 if (params_.outline_resample_length > 0.0f) {
483 VArray<float> resample_lengths = VArray<float>::ForSingle(
484 params_.outline_resample_length, outline.curves_num());
486 outline, outline.curves_range(), resample_lengths);
487 }
488
489 const OffsetIndices outline_points_by_curve = outline.points_by_curve();
490 const Span<float3> outline_positions = outline.positions();
491
492 for (const int i_outline_curve : outline.curves_range()) {
493 const IndexRange outline_points = outline_points_by_curve[i_outline_curve];
494 /* Use stroke color to fill the outline. */
495 stroke_fn(outline_positions.slice(outline_points),
496 true,
497 stroke_color,
498 stroke_opacity,
499 std::nullopt,
500 false,
501 true);
502 }
503 }
504 }
505 }
506}
507
509 const float3 &position) const
510{
511 const float3 world_pos = math::transform_point(transform, position);
512
513 if (camera_persmat_) {
514 /* Use camera render space. */
515 const float2 cam_space = (float2(math::project_point(*camera_persmat_, world_pos)) + 1.0f) /
516 2.0f * float2(screen_rect_.size());
517 return cam_space * camera_fac_;
518 }
519
520 /* Use 3D view screen space. */
521 float2 screen_co;
522 if (ED_view3d_project_float_global(context_.region, world_pos, screen_co, V3D_PROJ_TEST_NOP) ==
524 {
525 if (!ELEM(V2D_IS_CLIPPED, screen_co.x, screen_co.y)) {
526 /* Apply offset and scale. */
527 return screen_co - screen_rect_.min;
528 }
529 }
530
531 return float2(V2D_IS_CLIPPED);
532}
533
535 const int frame_number) const
536{
537 for (const bke::greasepencil::Layer *layer : grease_pencil.layers()) {
538 if (layer->is_visible()) {
539 const GreasePencilFrame *frame = layer->frame_at(frame_number);
540 if ((frame != nullptr) && frame->is_selected()) {
541 return true;
542 }
543 }
544 }
545 return false;
546}
547
548} // 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.
Material * BKE_material_default_gpencil()
Material * BKE_object_material_get(Object *ob, short act)
void BKE_render_resolution(const RenderData *r, const bool use_crop, int *r_width, int *r_height)
Definition scene.cc:2927
bool BKE_scene_camera_switch_update(Scene *scene)
Definition scene.cc:2267
#define BLI_assert(a)
Definition BLI_assert.h:46
#define LISTBASE_FOREACH(type, var, list)
MINLINE void copy_v4_v4(float r[4], const float a[4])
unsigned short ushort
#define ELEM(...)
T * DEG_get_evaluated(const Depsgraph *depsgraph, T *id)
GreasePencilStrokeCapType
@ GP_STROKE_CAP_TYPE_ROUND
struct GreasePencil GreasePencil
@ GP_MATERIAL_HIDE
@ GP_MATERIAL_STROKE_SHOW
@ GP_MATERIAL_FILL_SHOW
Object is a sort of wrapper for general info.
@ OB_GREASE_PENCIL
struct Object Object
#define BASE_SELECTED(v3d, base)
@ RV3D_CAMOB
struct RegionView3D RegionView3D
@ V3D_PROJ_TEST_NOP
Definition ED_view3d.hh:279
float ED_view3d_pixel_size(const RegionView3D *rv3d, const float co[3])
@ V3D_PROJ_RET_OK
Definition ED_view3d.hh:256
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
BPy_StructRNA * depsgraph
SIMD_FORCE_INLINE btVector3 transform(const btVector3 &point) const
const GreasePencilFrame * frame_at(const int frame_number) const
constexpr Span slice(int64_t start, int64_t size) const
Definition BLI_span.hh:137
IndexRange index_range() const
Definition BLI_array.hh:349
ChannelStorageType a
Definition BLI_color.hh:93
constexpr int64_t size() const
static constexpr IndexRange from_single(const int64_t index)
Span< NewT > constexpr cast() const
Definition BLI_span.hh:418
constexpr Span slice(int64_t start, int64_t size) const
Definition BLI_span.hh:137
constexpr int64_t size() const
Definition BLI_span.hh:252
constexpr const T * end() const
Definition BLI_span.hh:224
constexpr const T * begin() const
Definition BLI_span.hh:220
constexpr bool is_empty() const
Definition BLI_span.hh:260
constexpr const char * c_str() const
static VArray ForSingle(T value, const int64_t size)
void append(const T &value)
GAttributeReader lookup_or_default(StringRef attribute_id, AttrDomain domain, eCustomDataType data_type, const void *default_value=nullptr) const
OffsetIndices< int > points_by_curve() const
Span< float3 > positions() const
AttributeAccessor attributes() const
VArray< bool > cyclic() const
VArray< ColorGeometry4f > vertex_colors() const
const bke::CurvesGeometry & strokes() const
VArray< ColorGeometry4f > fill_colors() const
VArray< float > opacities() const
float4x4 to_world_space(const Object &object) const
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)
bool is_selected_frame(const GreasePencil &grease_pencil, int frame_number) const
FunctionRef< void(const Span< float3 > positions, bool cyclic, const ColorGeometry4f &color, float opacity, std::optional< float > width, bool round_cap, bool is_outline)> WriteStrokeFn
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)
static bool is_cyclic(const Nurb *nu)
#define rot(x, k)
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
Bounds< T > merge(const Bounds< T > &a, const Bounds< T > &b)
Definition BLI_bounds.hh:26
IndexMask retrieve_visible_strokes(Object &object, const bke::greasepencil::Drawing &drawing, IndexMaskMemory &memory)
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={}, bool keep_last_segment=false)
static float4x4 persmat_from_camera_object(Scene &scene)
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:93
MatBase< float, 4, 4 > float4x4
VecBase< float, 4 > float4
VecBase< float, 2 > float2
ColorSceneLinear4f< eAlpha::Premultiplied > ColorGeometry4f
Definition BLI_color.hh:342
VecBase< float, 3 > float3
struct MaterialGPencilStyle * gp_style
struct RenderData r
struct Object * camera
IOContext(bContext &C, const ARegion *region, const View3D *v3d, const RegionView3D *rv3d, ReportList *reports)
float xmax
float xmin
float ymax
float ymin