Blender  V3.3
gpencil_io_base.cc
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2020 Blender Foundation. All rights reserved. */
3 
8 #include "BLI_float4x4.hh"
9 #include "BLI_math_vec_types.hh"
10 #include "BLI_path_util.h"
11 #include "BLI_span.hh"
12 
13 #include "DNA_gpencil_types.h"
14 #include "DNA_layer_types.h"
15 #include "DNA_material_types.h"
16 #include "DNA_scene_types.h"
17 #include "DNA_screen_types.h"
18 
19 #include "BKE_camera.h"
20 #include "BKE_context.h"
21 #include "BKE_gpencil.h"
22 #include "BKE_gpencil_geom.h"
23 #include "BKE_main.h"
24 #include "BKE_material.h"
25 #include "BKE_scene.h"
26 
27 #include "UI_view2d.h"
28 
29 #include "ED_view3d.h"
30 
31 #include "DEG_depsgraph.h"
32 #include "DEG_depsgraph_query.h"
33 
34 #include "gpencil_io_base.hh"
35 
36 using blender::Span;
37 
39 
40 /* Constructor. */
42 {
43  params_ = *iparams;
44 
45  /* Easy access data. */
50  gpd_ = (params_.ob != nullptr) ? (bGPdata *)params_.ob->data : nullptr;
51  cfra_ = iparams->frame_cur;
52 
53  /* Calculate camera matrix. */
54  prepare_camera_params(scene_, iparams);
55 }
56 
58 {
59  params_ = *iparams;
60  const bool is_pdf = params_.mode == GP_EXPORT_TO_PDF;
61  const bool any_camera = (params_.v3d->camera != nullptr);
62  const bool force_camera_view = is_pdf && any_camera;
63 
64  /* Ensure camera switch is applied. */
66 
67  /* Calculate camera matrix. */
68  Object *cam_ob = scene->camera;
69  if (cam_ob != nullptr) {
70  /* Set up parameters. */
74 
75  /* Compute matrix, view-plane, etc. */
76  RenderData *rd = &scene_->r;
79 
80  float viewmat[4][4];
81  invert_m4_m4(viewmat, cam_ob->obmat);
82 
83  mul_m4_m4m4(persmat_, params.winmat, viewmat);
84  }
85  else {
86  unit_m4(persmat_);
87  }
88 
91 
92  /* Camera rectangle. */
93  if ((rv3d_->persp == RV3D_CAMOB) || (force_camera_view)) {
95 
97  depsgraph_,
99  params_.v3d,
100  rv3d_,
101  &camera_rect_,
102  true);
103  is_camera_ = true;
107  }
108  else {
109  is_camera_ = false;
110  /* Calc selected object boundbox. Need set initial value to some variables. */
111  camera_ratio_ = 1.0f;
112  offset_.x = 0.0f;
113  offset_.y = 0.0f;
114 
116 
118  rctf boundbox;
120 
121  render_x_ = boundbox.xmax - boundbox.xmin;
122  render_y_ = boundbox.ymax - boundbox.ymin;
123  offset_.x = boundbox.xmin;
124  offset_.y = boundbox.ymin;
125  }
126 }
127 
129 {
130  ViewLayer *view_layer = CTX_data_view_layer(params_.C);
131 
132  float3 camera_z_axis;
133  copy_v3_v3(camera_z_axis, rv3d_->viewinv[2]);
134  ob_list_.clear();
135 
136  LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) {
137  Object *object = base->object;
138 
139  if (object->type != OB_GPENCIL) {
140  continue;
141  }
142  if ((params_.select_mode == GP_EXPORT_ACTIVE) && (params_.ob != object)) {
143  continue;
144  }
145 
146  if ((params_.select_mode == GP_EXPORT_SELECTED) && ((base->flag & BASE_SELECTED) == 0)) {
147  continue;
148  }
149 
150  /* Save z-depth from view to sort from back to front. */
151  if (is_camera_) {
152  float camera_z = dot_v3v3(camera_z_axis, object->obmat[3]);
153  ObjectZ obz = {camera_z, object};
154  ob_list_.append(obz);
155  }
156  else {
157  float zdepth = 0;
158  if (rv3d_) {
159  if (rv3d_->is_persp) {
160  zdepth = ED_view3d_calc_zfac(rv3d_, object->obmat[3]);
161  }
162  else {
163  zdepth = -dot_v3v3(rv3d_->viewinv[2], object->obmat[3]);
164  }
165  ObjectZ obz = {zdepth * -1.0f, object};
166  ob_list_.append(obz);
167  }
168  }
169  }
170  /* Sort list of objects from point of view. */
171  std::sort(ob_list_.begin(), ob_list_.end(), [](const ObjectZ &obz1, const ObjectZ &obz2) {
172  return obz1.zdepth < obz2.zdepth;
173  });
174 }
175 
176 void GpencilIO::filepath_set(const char *filepath)
177 {
178  BLI_strncpy(filepath_, filepath, FILE_MAX);
180 }
181 
183 {
184  float3 parent_co = diff_mat_ * co;
185  float2 screen_co;
187  if (ED_view3d_project_float_global(params_.region, parent_co, screen_co, test) ==
188  V3D_PROJ_RET_OK) {
189  if (!ELEM(V2D_IS_CLIPPED, screen_co[0], screen_co[1])) {
190  copy_v2_v2(r_co, screen_co);
191  /* Invert X axis. */
192  if (invert_axis_[0]) {
193  r_co[0] = winx_ - r_co[0];
194  }
195  /* Invert Y axis. */
196  if (invert_axis_[1]) {
197  r_co[1] = winy_ - r_co[1];
198  }
199  /* Apply offset and scale. */
200  sub_v2_v2(r_co, &offset_.x);
201  mul_v2_fl(r_co, camera_ratio_);
202 
203  return true;
204  }
205  }
206  r_co[0] = V2D_IS_CLIPPED;
207  r_co[1] = V2D_IS_CLIPPED;
208 
209  /* Invert X axis. */
210  if (invert_axis_[0]) {
211  r_co[0] = winx_ - r_co[0];
212  }
213  /* Invert Y axis. */
214  if (invert_axis_[1]) {
215  r_co[1] = winy_ - r_co[1];
216  }
217 
218  return false;
219 }
220 
222 {
223  float3 parent_co = diff_mat_ * co;
224 
225  float2 r_co;
226  mul_v2_project_m4_v3(&r_co.x, persmat_, &parent_co.x);
227  r_co.x = (r_co.x + 1.0f) / 2.0f * (float)render_x_;
228  r_co.y = (r_co.y + 1.0f) / 2.0f * (float)render_y_;
229 
230  /* Invert X axis. */
231  if (invert_axis_[0]) {
232  r_co.x = (float)render_x_ - r_co.x;
233  }
234  /* Invert Y axis. */
235  if (invert_axis_[1]) {
236  r_co.y = (float)render_y_ - r_co.y;
237  }
238 
239  return r_co;
240 }
241 
243 {
244  const bool is_camera = (bool)(rv3d_->persp == RV3D_CAMOB);
245  if (is_camera) {
247  }
248  float2 result;
250  return result;
251 }
252 
254 {
255  bGPDspoint *pt = &gps->points[0];
256  const float2 screen_co = gpencil_3D_point_to_2D(&pt->x);
257 
258  /* Radius. */
260  rv3d_, gpd_, gpl, gps, 3, diff_mat_.values);
261 
262  pt = &gps_perimeter->points[0];
263  const float2 screen_ex = gpencil_3D_point_to_2D(&pt->x);
264 
265  const float2 v1 = screen_co - screen_ex;
266  float radius = math::length(v1);
267  BKE_gpencil_free_stroke(gps_perimeter);
268 
269  return MAX2(radius, 1.0f);
270 }
271 
273 {
276 }
277 
279 {
281 
282  /* Stroke color. */
284  avg_opacity_ = 0.0f;
285  /* Get average vertex color and apply. */
286  float avg_color[4] = {0.0f, 0.0f, 0.0f, 0.0f};
287  for (const bGPDspoint &pt : Span(gps->points, gps->totpoints)) {
288  add_v4_v4(avg_color, pt.vert_color);
289  avg_opacity_ += pt.strength;
290  }
291 
292  mul_v4_v4fl(avg_color, avg_color, 1.0f / (float)gps->totpoints);
293  interp_v3_v3v3(stroke_color_, stroke_color_, avg_color, avg_color[3]);
294  avg_opacity_ /= (float)gps->totpoints;
295 
296  /* Fill color. */
297  copy_v4_v4(fill_color_, gp_style->fill_rgba);
298  /* Apply vertex color for fill. */
300 }
301 
303 {
304  return avg_opacity_;
305 }
306 
308 {
309  return is_camera_;
310 }
311 
313 {
314  const float gap = 10.0f;
315 
316  float2 min, max;
317  INIT_MINMAX2(min, max);
318 
319  for (ObjectZ &obz : ob_list_) {
320  Object *ob = obz.ob;
321  /* Use evaluated version to get strokes with modifiers. */
322  Object *ob_eval = (Object *)DEG_get_evaluated_id(depsgraph_, &ob->id);
323  bGPdata *gpd_eval = (bGPdata *)ob_eval->data;
324 
325  LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd_eval->layers) {
326  if (gpl->flag & GP_LAYER_HIDE) {
327  continue;
328  }
330 
331  bGPDframe *gpf = gpl->actframe;
332  if (gpf == nullptr) {
333  continue;
334  }
335 
336  LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
337  if (gps->totpoints == 0) {
338  continue;
339  }
340  for (const bGPDspoint &pt : MutableSpan(gps->points, gps->totpoints)) {
341  const float2 screen_co = gpencil_3D_point_to_2D(&pt.x);
342  minmax_v2v2_v2(min, max, screen_co);
343  }
344  }
345  }
346  }
347  /* Add small gap. */
348  add_v2_fl(min, gap * -1.0f);
349  add_v2_fl(max, gap);
350 
351  select_boundbox_.xmin = min[0];
352  select_boundbox_.ymin = min[1];
353  select_boundbox_.xmax = max[0];
354  select_boundbox_.ymax = max[1];
355 }
356 
358 {
359  boundbox->xmin = select_boundbox_.xmin;
360  boundbox->xmax = select_boundbox_.xmax;
361  boundbox->ymin = select_boundbox_.ymin;
362  boundbox->ymax = select_boundbox_.ymax;
363 }
364 
365 void GpencilIO::frame_number_set(const int value)
366 {
367  cfra_ = value;
368 }
369 
370 } // namespace blender::io::gpencil
typedef float(TangentPoint)[2]
Camera data-block and utility functions.
void BKE_camera_params_init(CameraParams *params)
Definition: camera.c:265
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)
Definition: camera.c:364
void BKE_camera_params_compute_matrix(CameraParams *params)
Definition: camera.c:429
struct Scene * CTX_data_scene(const bContext *C)
Definition: context.c:1090
struct ViewLayer * CTX_data_view_layer(const bContext *C)
Definition: context.c:1100
struct Depsgraph * CTX_data_depsgraph_pointer(const bContext *C)
Definition: context.c:1505
struct Main * CTX_data_main(const bContext *C)
Definition: context.c:1074
void BKE_gpencil_free_stroke(struct bGPDstroke *gps)
Definition: gpencil.c:391
void BKE_gpencil_layer_transform_matrix_get(const struct Depsgraph *depsgraph, struct Object *obact, struct bGPDlayer *gpl, float diff_mat[4][4])
struct bGPDstroke * BKE_gpencil_stroke_perimeter_from_view(struct RegionView3D *rv3d, struct bGPdata *gpd, const struct bGPDlayer *gpl, struct bGPDstroke *gps, int subdivisions, const float diff_mat[4][4])
const char * BKE_main_blendfile_path(const struct Main *bmain) ATTR_NONNULL()
General operations, lookup, etc. for materials.
struct MaterialGPencilStyle * BKE_gpencil_material_settings(struct Object *ob, short act)
Definition: material.c:805
void BKE_render_resolution(const struct RenderData *r, const bool use_crop, int *r_width, int *r_height)
Definition: scene.cc:2960
bool BKE_scene_camera_switch_update(struct Scene *scene)
Definition: scene.cc:2295
#define LISTBASE_FOREACH(type, var, list)
Definition: BLI_listbase.h:336
void mul_m4_m4m4(float R[4][4], const float A[4][4], const float B[4][4])
Definition: math_matrix.c:259
void unit_m4(float m[4][4])
Definition: rct.c:1090
bool invert_m4_m4(float R[4][4], const float A[4][4])
Definition: math_matrix.c:1287
void mul_v2_project_m4_v3(float r[2], const float M[4][4], const float vec[3])
Definition: math_matrix.c:841
MINLINE void add_v4_v4(float r[4], const float a[4])
MINLINE void copy_v4_v4(float r[4], const float a[4])
MINLINE void sub_v2_v2(float r[2], const float a[2])
MINLINE void mul_v2_fl(float r[2], float f)
MINLINE void copy_v2_v2(float r[2], const float a[2])
MINLINE void mul_v4_v4fl(float r[4], const float a[4], float f)
MINLINE void copy_v3_v3(float r[3], const float a[3])
void minmax_v2v2_v2(float min[2], float max[2], const float vec[2])
Definition: math_vector.c:890
MINLINE float dot_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
void interp_v3_v3v3(float r[3], const float a[3], const float b[3], float t)
Definition: math_vector.c:29
MINLINE void add_v2_fl(float r[2], float f)
#define FILE_MAX
bool BLI_path_abs(char *path, const char *basepath) ATTR_NONNULL()
Definition: path_util.c:897
char * BLI_strncpy(char *__restrict dst, const char *__restrict src, size_t maxncpy) ATTR_NONNULL()
Definition: string.c:64
#define INIT_MINMAX2(min, max)
#define MAX2(a, b)
#define ELEM(...)
struct ID * DEG_get_evaluated_id(const struct Depsgraph *depsgraph, struct ID *id)
@ GP_LAYER_HIDE
@ BASE_SELECTED
@ OB_GPENCIL
#define RV3D_CAMOB
eV3DProjTest
Definition: ED_view3d.h:233
eV3DProjStatus ED_view3d_project_float_global(const struct ARegion *region, const float co[3], float r_co[2], eV3DProjTest flag)
@ V3D_PROJ_RET_OK
Definition: ED_view3d.h:217
float ED_view3d_calc_zfac(const struct RegionView3D *rv3d, const float co[3])
void ED_view3d_calc_camera_border(const struct Scene *scene, struct Depsgraph *depsgraph, const struct ARegion *region, const struct View3D *v3d, const struct RegionView3D *rv3d, struct rctf *r_viewborder, bool no_shift)
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble v1
float float4x4[4][4]
#define V2D_IS_CLIPPED
Definition: UI_view2d.h:25
void sort(btMatrix3x3 &U, btVector3 &sigma, btMatrix3x3 &V, int t)
Helper function of 3X3 SVD for sorting singular values.
float2 gpencil_3D_point_to_render_space(const float3 co)
void selected_objects_boundbox_get(rctf *boundbox)
void filepath_set(const char *filepath)
float stroke_point_radius_get(struct bGPDlayer *gpl, struct bGPDstroke *gps)
GpencilIO(const GpencilIOParams *iparams)
blender::Vector< ObjectZ > ob_list_
void prepare_stroke_export_colors(struct Object *ob, struct bGPDstroke *gps)
float2 gpencil_3D_point_to_2D(const float3 co)
bool gpencil_3D_point_to_screen_space(const float3 co, float2 &r_co)
void prepare_layer_export_matrix(struct Object *ob, struct bGPDlayer *gpl)
void prepare_camera_params(Scene *scene, const GpencilIOParams *iparams)
Scene scene
@ GP_EXPORT_SELECTED
Definition: gpencil_io.h:63
@ GP_EXPORT_ACTIVE
Definition: gpencil_io.h:62
@ GP_EXPORT_TO_PDF
Definition: gpencil_io.h:54
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
T length(const vec_base< T, Size > &a)
#define min(a, b)
Definition: sort.c:35
void * regiondata
int32_t frame_cur
Definition: gpencil_io.h:28
uint16_t select_mode
Definition: gpencil_io.h:32
bContext * C
Definition: gpencil_io.h:19
uint16_t mode
Definition: gpencil_io.h:25
View3D * v3d
Definition: gpencil_io.h:21
ARegion * region
Definition: gpencil_io.h:20
Object * ob
Definition: gpencil_io.h:23
float obmat[4][4]
void * data
float viewinv[4][4]
struct RenderData r
struct Object * camera
struct Object * camera
ListBase object_bases
ListBase strokes
float layer_invmat[4][4]
bGPDspoint * points
float vert_color_fill[4]
ListBase layers
float values[4][4]
Definition: BLI_float4x4.hh:13
float xmax
Definition: DNA_vec_types.h:69
float xmin
Definition: DNA_vec_types.h:69
float ymax
Definition: DNA_vec_types.h:70
float ymin
Definition: DNA_vec_types.h:70
float max