Blender  V2.93
lineart_cpu.c
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * The Original Code is Copyright (C) 2019 Blender Foundation.
17  * All rights reserved.
18  */
19 
20 /* \file
21  * \ingroup editors
22  */
23 
24 #include "MOD_lineart.h"
25 
26 #include "BLI_linklist.h"
27 #include "BLI_listbase.h"
28 #include "BLI_math.h"
29 #include "BLI_task.h"
30 #include "BLI_utildefines.h"
31 
32 #include "PIL_time.h"
33 
34 #include "BKE_camera.h"
35 #include "BKE_collection.h"
36 #include "BKE_customdata.h"
37 #include "BKE_deform.h"
38 #include "BKE_editmesh.h"
39 #include "BKE_global.h"
40 #include "BKE_gpencil.h"
41 #include "BKE_gpencil_geom.h"
42 #include "BKE_gpencil_modifier.h"
43 #include "BKE_material.h"
44 #include "BKE_mesh.h"
45 #include "BKE_scene.h"
46 #include "DEG_depsgraph_query.h"
47 #include "DNA_camera_types.h"
48 #include "DNA_collection_types.h"
49 #include "DNA_gpencil_types.h"
50 #include "DNA_material_types.h"
51 #include "DNA_mesh_types.h"
52 #include "DNA_meshdata_types.h"
53 #include "DNA_modifier_types.h"
54 #include "DNA_scene_types.h"
55 #include "MEM_guardedalloc.h"
56 
57 #include "BLI_math.h"
58 
59 #include "bmesh.h"
60 #include "bmesh_class.h"
61 #include "bmesh_tools.h"
62 
63 #include "lineart_intern.h"
64 
66  LineartEdge *e);
67 
69  LineartBoundingArea *root_ba,
70  LineartEdge *e);
71 
73  LineartEdge *e,
74  double x,
75  double y,
76  double k,
77  int positive_x,
78  int positive_y,
79  double *next_x,
80  double *next_y);
81 
83  LineartEdge *e,
84  int *rowbegin,
85  int *rowend,
86  int *colbegin,
87  int *colend);
88 
90  LineartBoundingArea *root_ba,
91  LineartTriangle *rt,
92  double *LRUB,
93  int recursive,
94  int recursive_level,
95  bool do_intersection);
96 
98  const LineartTriangle *rt,
99  const LineartEdge *e,
100  const double *override_camera_loc,
101  const bool override_cam_is_persp,
102  const bool allow_overlapping_edges,
103  const double vp[4][4],
104  const double *camera_dir,
105  const float cam_shift_x,
106  const float cam_shift_y,
107  double *from,
108  double *to);
109 
111 
113 {
114  BLI_spin_lock(&rb->lock_cuts);
115 
116  memset(rls, 0, sizeof(LineartLineSegment));
117 
118  /* Storing the node for potentially reuse the memory for new segment data.
119  * Line Art data is not freed after all calculations are done. */
120  BLI_addtail(&rb->wasted_cuts, rls);
121 
123 }
124 
126 {
127  BLI_spin_lock(&rb->lock_cuts);
128 
129  /* See if there is any already allocated memory we can reuse. */
130  if (rb->wasted_cuts.first) {
133  memset(rls, 0, sizeof(LineartLineSegment));
134  return rls;
135  }
137 
138  /* Otherwise allocate some new memory. */
140  sizeof(LineartLineSegment));
141 }
142 
146 static void lineart_edge_cut(
147  LineartRenderBuffer *rb, LineartEdge *e, double start, double end, uchar transparency_mask)
148 {
149  LineartLineSegment *rls, *irls, *next_rls, *prev_rls;
150  LineartLineSegment *cut_start_before = 0, *cut_end_before = 0;
151  LineartLineSegment *ns = 0, *ns2 = 0;
152  int untouched = 0;
153 
154  /* If for some reason the occlusion function may give a result that has zero length, or reversed
155  * in direction, or NAN, we take care of them here. */
156  if (LRT_DOUBLE_CLOSE_ENOUGH(start, end)) {
157  return;
158  }
159  if (LRT_DOUBLE_CLOSE_ENOUGH(start, 1) || LRT_DOUBLE_CLOSE_ENOUGH(end, 0)) {
160  return;
161  }
162  if (UNLIKELY(start != start)) {
163  start = 0;
164  }
165  if (UNLIKELY(end != end)) {
166  end = 0;
167  }
168 
169  if (start > end) {
170  double t = start;
171  start = end;
172  end = t;
173  }
174 
175  /* Begin looking for starting position of the segment. */
176  /* Not using a list iteration macro because of it more clear when using for loops to iterate
177  * through the segments. */
178  for (rls = e->segments.first; rls; rls = rls->next) {
179  if (LRT_DOUBLE_CLOSE_ENOUGH(rls->at, start)) {
180  cut_start_before = rls;
181  ns = cut_start_before;
182  break;
183  }
184  if (rls->next == NULL) {
185  break;
186  }
187  irls = rls->next;
188  if (irls->at > start + 1e-09 && start > rls->at) {
189  cut_start_before = irls;
190  ns = lineart_give_segment(rb);
191  break;
192  }
193  }
194  if (!cut_start_before && LRT_DOUBLE_CLOSE_ENOUGH(1, end)) {
195  untouched = 1;
196  }
197  for (rls = cut_start_before; rls; rls = rls->next) {
198  /* We tried to cut at existing cutting point (e.g. where the line's occluded by a triangle
199  * strip). */
200  if (LRT_DOUBLE_CLOSE_ENOUGH(rls->at, end)) {
201  cut_end_before = rls;
202  ns2 = cut_end_before;
203  break;
204  }
205  /* This check is to prevent `rls->at == 1.0` (where we don't need to cut because we are at the
206  * end point). */
207  if (!rls->next && LRT_DOUBLE_CLOSE_ENOUGH(1, end)) {
208  cut_end_before = rls;
209  ns2 = cut_end_before;
210  untouched = 1;
211  break;
212  }
213  /* When an actual cut is needed in the line. */
214  if (rls->at > end) {
215  cut_end_before = rls;
216  ns2 = lineart_give_segment(rb);
217  break;
218  }
219  }
220 
221  /* When we still can't find any existing cut in the line, we allocate new ones. */
222  if (ns == NULL) {
223  ns = lineart_give_segment(rb);
224  }
225  if (ns2 == NULL) {
226  if (untouched) {
227  ns2 = ns;
228  cut_end_before = ns2;
229  }
230  else {
231  ns2 = lineart_give_segment(rb);
232  }
233  }
234 
235  if (cut_start_before) {
236  if (cut_start_before != ns) {
237  /* Insert cutting points for when a new cut is needed. */
238  irls = cut_start_before->prev ? cut_start_before->prev : NULL;
239  ns->occlusion = irls ? irls->occlusion : 0;
241  BLI_insertlinkbefore(&e->segments, cut_start_before, ns);
242  }
243  /* Otherwise we already found a existing cutting point, no need to insert a new one. */
244  }
245  else {
246  /* We have yet to reach a existing cutting point even after we searched the whole line, so we
247  * append the new cut to the end. */
248  irls = e->segments.last;
249  ns->occlusion = irls->occlusion;
251  BLI_addtail(&e->segments, ns);
252  }
253  if (cut_end_before) {
254  /* The same manipulation as on "cut_start_before". */
255  if (cut_end_before != ns2) {
256  irls = cut_end_before->prev ? cut_end_before->prev : NULL;
257  ns2->occlusion = irls ? irls->occlusion : 0;
258  ns2->transparency_mask = irls ? irls->transparency_mask : 0;
259  BLI_insertlinkbefore(&e->segments, cut_end_before, ns2);
260  }
261  }
262  else {
263  irls = e->segments.last;
264  ns2->occlusion = irls->occlusion;
265  ns2->transparency_mask = irls->transparency_mask;
266  BLI_addtail(&e->segments, ns2);
267  }
268 
269  /* If we touched the cut list, we assign the new cut position based on new cut position,
270  * this way we accommodate precision lost due to multiple cut inserts. */
271  ns->at = start;
272  if (!untouched) {
273  ns2->at = end;
274  }
275  else {
276  /* For the convenience of the loop below. */
277  ns2 = ns2->next;
278  }
279 
280  /* Register 1 level of occlusion for all touched segments. */
281  for (rls = ns; rls && rls != ns2; rls = rls->next) {
282  rls->occlusion++;
283  rls->transparency_mask |= transparency_mask;
284  }
285 
286  /* Reduce adjacent cutting points of the same level, which saves memory. */
287  char min_occ = 127;
288  prev_rls = NULL;
289  for (rls = e->segments.first; rls; rls = next_rls) {
290  next_rls = rls->next;
291 
292  if (prev_rls && prev_rls->occlusion == rls->occlusion &&
293  prev_rls->transparency_mask == rls->transparency_mask) {
294  BLI_remlink(&e->segments, rls);
295  /* This puts the node back to the render buffer, if more cut happens, these unused nodes get
296  * picked first. */
297  lineart_discard_segment(rb, rls);
298  continue;
299  }
300 
301  min_occ = MIN2(min_occ, rls->occlusion);
302 
303  prev_rls = rls;
304  }
305  e->min_occ = min_occ;
306 }
307 
312 {
313  LineartVertIntersection *v1 = (void *)e->v1;
314  LineartVertIntersection *v2 = (void *)e->v2;
315  return ((v1->base.flag && v1->intersecting_with == rt) ||
316  (v2->base.flag && v2->intersecting_with == rt));
317 }
318 
320 {
321  double x = e->v1->fbcoord[0], y = e->v1->fbcoord[1];
323  LineartBoundingArea *nba = ba;
325 
326  /* These values are used for marching along the line. */
327  double l, r;
328  double k = (e->v2->fbcoord[1] - e->v1->fbcoord[1]) /
329  (e->v2->fbcoord[0] - e->v1->fbcoord[0] + 1e-30);
330  int positive_x = (e->v2->fbcoord[0] - e->v1->fbcoord[0]) > 0 ?
331  1 :
332  (e->v2->fbcoord[0] == e->v1->fbcoord[0] ? 0 : -1);
333  int positive_y = (e->v2->fbcoord[1] - e->v1->fbcoord[1]) > 0 ?
334  1 :
335  (e->v2->fbcoord[1] == e->v1->fbcoord[1] ? 0 : -1);
336 
337  while (nba) {
338 
339  LISTBASE_FOREACH (LinkData *, lip, &nba->linked_triangles) {
340  rt = lip->data;
341  /* If we are already testing the line in this thread, then don't do it. */
342  if (rt->testing_e[thread_id] == e || (rt->base.flags & LRT_TRIANGLE_INTERSECTION_ONLY) ||
344  continue;
345  }
346  rt->testing_e[thread_id] = e;
348  (const LineartTriangle *)rt,
349  e,
350  rb->camera_pos,
351  rb->cam_is_persp,
353  rb->view_projection,
354  rb->view_vector,
355  rb->shift_x,
356  rb->shift_y,
357  &l,
358  &r)) {
359  lineart_edge_cut(rb, e, l, r, rt->base.transparency_mask);
360  if (e->min_occ > rb->max_occlusion_level) {
361  /* No need to calculate any longer on this line because no level more than set value is
362  * going to show up in the rendered result. */
363  return;
364  }
365  }
366  }
367  /* Marching along `e->v1` to `e->v2`, searching each possible bounding areas it may touch. */
368  nba = lineart_bounding_area_next(nba, e, x, y, k, positive_x, positive_y, &x, &y);
369  }
370 }
371 
373 {
374  LineartEdge *data;
375  int i;
376  int res = 0;
377 
378  BLI_spin_lock(&rb->lock_task);
379 
380 #define LRT_ASSIGN_OCCLUSION_TASK(name) \
381  if (rb->name##_managed) { \
382  data = rb->name##_managed; \
383  rti->name = (void *)data; \
384  for (i = 0; i < LRT_THREAD_EDGE_COUNT && data; i++) { \
385  data = data->next; \
386  } \
387  rti->name##_end = data; \
388  rb->name##_managed = data; \
389  res = 1; \
390  } \
391  else { \
392  rti->name = NULL; \
393  }
394 
395  LRT_ASSIGN_OCCLUSION_TASK(contour);
399  LRT_ASSIGN_OCCLUSION_TASK(edge_mark);
400 
401 #undef LRT_ASSIGN_OCCLUSION_TASK
402 
404 
405  return res;
406 }
407 
409 {
410  LineartRenderBuffer *rb = rti->rb;
411  LineartEdge *eip;
412 
413  while (lineart_occlusion_make_task_info(rb, rti)) {
414 
415  for (eip = rti->contour; eip && eip != rti->contour_end; eip = eip->next) {
417  }
418 
419  for (eip = rti->crease; eip && eip != rti->crease_end; eip = eip->next) {
421  }
422 
423  for (eip = rti->intersection; eip && eip != rti->intersection_end; eip = eip->next) {
425  }
426 
427  for (eip = rti->material; eip && eip != rti->material_end; eip = eip->next) {
429  }
430 
431  for (eip = rti->edge_mark; eip && eip != rti->edge_mark_end; eip = eip->next) {
433  }
434  }
435 }
436 
443 {
444  int thread_count = rb->thread_count;
445  LineartRenderTaskInfo *rti = MEM_callocN(sizeof(LineartRenderTaskInfo) * thread_count,
446  "Task Pool");
447  int i;
448 
449  rb->contour_managed = rb->contours;
450  rb->crease_managed = rb->crease_lines;
453  rb->edge_mark_managed = rb->edge_marks;
454 
456 
457  for (i = 0; i < thread_count; i++) {
458  rti[i].thread_id = i;
459  rti[i].rb = rb;
461  }
463  BLI_task_pool_free(tp);
464 
465  MEM_freeN(rti);
466 }
467 
475 static bool lineart_point_inside_triangle(const double v[2],
476  const double v0[2],
477  const double v1[2],
478  const double v2[2])
479 {
480  double cl, c;
481 
482  cl = (v0[0] - v[0]) * (v1[1] - v[1]) - (v0[1] - v[1]) * (v1[0] - v[0]);
483  c = cl;
484 
485  cl = (v1[0] - v[0]) * (v2[1] - v[1]) - (v1[1] - v[1]) * (v2[0] - v[0]);
486  if (c * cl <= 0) {
487  return false;
488  }
489 
490  c = cl;
491 
492  cl = (v2[0] - v[0]) * (v0[1] - v[1]) - (v2[1] - v[1]) * (v0[0] - v[0]);
493  if (c * cl <= 0) {
494  return false;
495  }
496 
497  c = cl;
498 
499  cl = (v0[0] - v[0]) * (v1[1] - v[1]) - (v0[1] - v[1]) * (v1[0] - v[0]);
500  if (c * cl <= 0) {
501  return false;
502  }
503 
504  return true;
505 }
506 
507 static int lineart_point_on_line_segment(double v[2], double v0[2], double v1[2])
508 {
509  /* `c1 != c2` by default. */
510  double c1 = 1, c2 = 0;
511  double l0[2], l1[2];
512 
513  sub_v2_v2v2_db(l0, v, v0);
514  sub_v2_v2v2_db(l1, v, v1);
515 
516  if (v1[0] == v0[0] && v1[1] == v0[1]) {
517  return 0;
518  }
519 
520  if (v1[0] - v0[0]) {
521  c1 = ratiod(v0[0], v1[0], v[0]);
522  }
523  else if (v[0] == v1[0]) {
524  c2 = ratiod(v0[1], v1[1], v[1]);
525  return (c2 >= 0 && c2 <= 1);
526  }
527 
528  if (v1[1] - v0[1]) {
529  c2 = ratiod(v0[1], v1[1], v[1]);
530  }
531  else if (v[1] == v1[1]) {
532  c1 = ratiod(v0[0], v1[0], v[0]);
533  return (c1 >= 0 && c1 <= 1);
534  }
535 
536  if (LRT_DOUBLE_CLOSE_ENOUGH(c1, c2) && c1 >= 0 && c1 <= 1) {
537  return 1;
538  }
539 
540  return 0;
541 }
542 
547 static int lineart_point_triangle_relation(double v[2], double v0[2], double v1[2], double v2[2])
548 {
549  double cl, c;
550  double r;
553  return 1;
554  }
555 
556  cl = (v0[0] - v[0]) * (v1[1] - v[1]) - (v0[1] - v[1]) * (v1[0] - v[0]);
557  c = cl;
558 
559  cl = (v1[0] - v[0]) * (v2[1] - v[1]) - (v1[1] - v[1]) * (v2[0] - v[0]);
560  if ((r = c * cl) < 0) {
561  return 0;
562  }
563 
564  c = cl;
565 
566  cl = (v2[0] - v[0]) * (v0[1] - v[1]) - (v2[1] - v[1]) * (v0[0] - v[0]);
567  if ((r = c * cl) < 0) {
568  return 0;
569  }
570 
571  c = cl;
572 
573  cl = (v0[0] - v[0]) * (v1[1] - v[1]) - (v0[1] - v[1]) * (v1[0] - v[0]);
574  if ((r = c * cl) < 0) {
575  return 0;
576  }
577 
578  if (r == 0) {
579  return 1;
580  }
581 
582  return 2;
583 }
584 
589 static bool lineart_point_inside_triangle3d(double v[3], double v0[3], double v1[3], double v2[3])
590 {
591  double l[3], r[3];
592  double N1[3], N2[3];
593  double d;
594 
595  sub_v3_v3v3_db(l, v1, v0);
596  sub_v3_v3v3_db(r, v, v1);
597  cross_v3_v3v3_db(N1, l, r);
598 
599  sub_v3_v3v3_db(l, v2, v1);
600  sub_v3_v3v3_db(r, v, v2);
601  cross_v3_v3v3_db(N2, l, r);
602 
603  if ((d = dot_v3v3_db(N1, N2)) < 0) {
604  return false;
605  }
606 
607  sub_v3_v3v3_db(l, v0, v2);
608  sub_v3_v3v3_db(r, v, v0);
609  cross_v3_v3v3_db(N1, l, r);
610 
611  if ((d = dot_v3v3_db(N1, N2)) < 0) {
612  return false;
613  }
614 
615  sub_v3_v3v3_db(l, v1, v0);
616  sub_v3_v3v3_db(r, v, v1);
617  cross_v3_v3v3_db(N2, l, r);
618 
619  if ((d = dot_v3v3_db(N1, N2)) < 0) {
620  return false;
621  }
622 
623  return true;
624 }
625 
631 {
633 
634  /* We don't need to allocate a whole bunch of triangles because the amount of clipped triangles
635  * are relatively small. */
636  LineartTriangle *render_triangles = lineart_mem_aquire(&rb->render_data_pool,
637  64 * rb->triangle_size);
638 
640  &rb->render_data_pool,
641  render_triangles,
642  sizeof(LineartElementLinkNode));
643  reln->element_count = 64;
645 
646  return reln;
647 }
648 
650 {
652 
653  LineartVert *render_vertices = lineart_mem_aquire(&rb->render_data_pool,
654  sizeof(LineartVert) * 64);
655 
657  &rb->render_data_pool,
658  render_vertices,
659  sizeof(LineartElementLinkNode));
660  reln->element_count = 64;
662 
663  return reln;
664 }
665 
667 {
669 
670  LineartEdge *render_edges = lineart_mem_aquire(&rb->render_data_pool, sizeof(LineartEdge) * 64);
671 
673  &rb->render_data_pool,
674  render_edges,
675  sizeof(LineartElementLinkNode));
676  reln->element_count = 64;
679 
680  return reln;
681 }
682 
684 {
685  /* Just re-assign normal and set cull flag. */
686  copy_v3_v3_db(rt->gn, orig->gn);
688 }
689 
691 {
692  uchar intersection_only = (rt->flags & LRT_TRIANGLE_INTERSECTION_ONLY);
693  rt->flags = flag;
694  rt->flags |= intersection_only;
695 }
696 
697 static bool lineart_edge_match(LineartTriangle *rt, LineartEdge *e, int v1, int v2)
698 {
699  return ((rt->v[v1] == e->v1 && rt->v[v2] == e->v2) ||
700  (rt->v[v2] == e->v1 && rt->v[v1] == e->v2));
701 }
702 
708  LineartTriangle *rt,
709  int in0,
710  int in1,
711  int in2,
712  double *cam_pos,
713  double *view_dir,
714  bool allow_boundaries,
715  double (*vp)[4],
716  Object *ob,
717  int *r_v_count,
718  int *r_e_count,
719  int *r_t_count,
720  LineartElementLinkNode *v_eln,
721  LineartElementLinkNode *e_eln,
722  LineartElementLinkNode *t_eln)
723 {
724  double vv1[3], vv2[3], dot1, dot2;
725  double a;
726  int v_count = *r_v_count;
727  int e_count = *r_e_count;
728  int t_count = *r_t_count;
729  int v1_obi, v2_obi;
730  char new_flag = 0;
731 
732  LineartEdge *new_e, *e, *old_e;
733  LineartLineSegment *rls;
735 
737  return;
738  }
739 
740  /* See definition of rt->intersecting_verts and the usage in
741  * lineart_geometry_object_load() for details. */
742  rta = (void *)rt->intersecting_verts;
743 
744  LineartVert *rv = &((LineartVert *)v_eln->pointer)[v_count];
745  LineartTriangle *rt1 = (void *)(((uchar *)t_eln->pointer) + rb->triangle_size * t_count);
746  LineartTriangle *rt2 = (void *)(((uchar *)t_eln->pointer) + rb->triangle_size * (t_count + 1));
747 
748  new_e = &((LineartEdge *)e_eln->pointer)[e_count];
749  /* Init `rl` to the last `rl` entry. */
750  e = new_e;
751 
752 #define INCREASE_RL \
753  v1_obi = e->v1_obindex; \
754  v2_obi = e->v2_obindex; \
755  new_e = &((LineartEdge *)e_eln->pointer)[e_count]; \
756  e_count++; \
757  e = new_e; \
758  e->v1_obindex = v1_obi; \
759  e->v2_obindex = v2_obi; \
760  rls = lineart_mem_aquire(&rb->render_data_pool, sizeof(LineartLineSegment)); \
761  BLI_addtail(&e->segments, rls);
762 
763 #define SELECT_RL(e_num, v1_link, v2_link, newrt) \
764  if (rta->e[e_num]) { \
765  old_e = rta->e[e_num]; \
766  new_flag = old_e->flags; \
767  old_e->flags = LRT_EDGE_FLAG_CHAIN_PICKED; \
768  INCREASE_RL \
769  e->v1 = (v1_link); \
770  e->v2 = (v2_link); \
771  e->flags = new_flag; \
772  e->object_ref = ob; \
773  e->t1 = ((old_e->t1 == rt) ? (newrt) : (old_e->t1)); \
774  e->t2 = ((old_e->t2 == rt) ? (newrt) : (old_e->t2)); \
775  lineart_add_edge_to_list(rb, e); \
776  }
777 
778 #define RELINK_RL(e_num, newrt) \
779  if (rta->e[e_num]) { \
780  old_e = rta->e[e_num]; \
781  old_e->t1 = ((old_e->t1 == rt) ? (newrt) : (old_e->t1)); \
782  old_e->t2 = ((old_e->t2 == rt) ? (newrt) : (old_e->t2)); \
783  }
784 
785 #define REMOVE_TRIANGLE_RL \
786  if (rta->e[0]) { \
787  rta->e[0]->flags = LRT_EDGE_FLAG_CHAIN_PICKED; \
788  } \
789  if (rta->e[1]) { \
790  rta->e[1]->flags = LRT_EDGE_FLAG_CHAIN_PICKED; \
791  } \
792  if (rta->e[2]) { \
793  rta->e[2]->flags = LRT_EDGE_FLAG_CHAIN_PICKED; \
794  }
795 
796  switch (in0 + in1 + in2) {
797  case 0: /* Triangle is visible. Ignore this triangle. */
798  return;
799  case 3:
800  /* Triangle completely behind near plane, throw it away
801  * also remove render lines form being computed. */
804  return;
805  case 2:
806  /* Two points behind near plane, cut those and
807  * generate 2 new points, 3 lines and 1 triangle. */
809 
830  if (!in0) {
831 
832  /* Cut point for line 2---|-----0. */
833  sub_v3_v3v3_db(vv1, rt->v[0]->gloc, cam_pos);
834  sub_v3_v3v3_db(vv2, cam_pos, rt->v[2]->gloc);
835  dot1 = dot_v3v3_db(vv1, view_dir);
836  dot2 = dot_v3v3_db(vv2, view_dir);
837  a = dot1 / (dot1 + dot2);
838  /* Assign it to a new point. */
839  interp_v3_v3v3_db(rv[0].gloc, rt->v[0]->gloc, rt->v[2]->gloc, a);
840  mul_v4_m4v3_db(rv[0].fbcoord, vp, rv[0].gloc);
841  rv[0].index = rt->v[2]->index;
842 
843  /* Cut point for line 1---|-----0. */
844  sub_v3_v3v3_db(vv1, rt->v[0]->gloc, cam_pos);
845  sub_v3_v3v3_db(vv2, cam_pos, rt->v[1]->gloc);
846  dot1 = dot_v3v3_db(vv1, view_dir);
847  dot2 = dot_v3v3_db(vv2, view_dir);
848  a = dot1 / (dot1 + dot2);
849  /* Assign it to another new point. */
850  interp_v3_v3v3_db(rv[1].gloc, rt->v[0]->gloc, rt->v[1]->gloc, a);
851  mul_v4_m4v3_db(rv[1].fbcoord, vp, rv[1].gloc);
852  rv[1].index = rt->v[1]->index;
853 
854  /* New line connecting two new points. */
856  if (allow_boundaries) {
857  e->flags = LRT_EDGE_FLAG_CONTOUR;
859  }
860  /* NOTE: inverting `e->v1/v2` (left/right point) doesn't matter as long as
861  * `rt->rl` and `rt->v` has the same sequence. and the winding direction
862  * can be either CW or CCW but needs to be consistent throughout the calculation. */
863  e->v1 = &rv[1];
864  e->v2 = &rv[0];
865  /* Only one adjacent triangle, because the other side is the near plane. */
866  /* Use `tl` or `tr` doesn't matter. */
867  e->t1 = rt1;
868  e->object_ref = ob;
869 
870  /* New line connecting original point 0 and a new point, only when it's a selected line. */
871  SELECT_RL(2, rt->v[0], &rv[0], rt1)
872  /* New line connecting original point 0 and another new point. */
873  SELECT_RL(0, rt->v[0], &rv[1], rt1)
874 
875  /* Re-assign triangle point array to two new points. */
876  rt1->v[0] = rt->v[0];
877  rt1->v[1] = &rv[1];
878  rt1->v[2] = &rv[0];
879 
880  lineart_triangle_post(rt1, rt);
881 
882  v_count += 2;
883  t_count += 1;
884  }
885  else if (!in2) {
886  sub_v3_v3v3_db(vv1, rt->v[2]->gloc, cam_pos);
887  sub_v3_v3v3_db(vv2, cam_pos, rt->v[0]->gloc);
888  dot1 = dot_v3v3_db(vv1, view_dir);
889  dot2 = dot_v3v3_db(vv2, view_dir);
890  a = dot1 / (dot1 + dot2);
891  interp_v3_v3v3_db(rv[0].gloc, rt->v[2]->gloc, rt->v[0]->gloc, a);
892  mul_v4_m4v3_db(rv[0].fbcoord, vp, rv[0].gloc);
893  rv[0].index = rt->v[0]->index;
894 
895  sub_v3_v3v3_db(vv1, rt->v[2]->gloc, cam_pos);
896  sub_v3_v3v3_db(vv2, cam_pos, rt->v[1]->gloc);
897  dot1 = dot_v3v3_db(vv1, view_dir);
898  dot2 = dot_v3v3_db(vv2, view_dir);
899  a = dot1 / (dot1 + dot2);
900  interp_v3_v3v3_db(rv[1].gloc, rt->v[2]->gloc, rt->v[1]->gloc, a);
901  mul_v4_m4v3_db(rv[1].fbcoord, vp, rv[1].gloc);
902  rv[1].index = rt->v[1]->index;
903 
905  if (allow_boundaries) {
906  e->flags = LRT_EDGE_FLAG_CONTOUR;
908  }
909  e->v1 = &rv[0];
910  e->v2 = &rv[1];
911  e->t1 = rt1;
912  e->object_ref = ob;
913 
914  SELECT_RL(2, rt->v[2], &rv[0], rt1)
915  SELECT_RL(1, rt->v[2], &rv[1], rt1)
916 
917  rt1->v[0] = &rv[0];
918  rt1->v[1] = &rv[1];
919  rt1->v[2] = rt->v[2];
920 
921  lineart_triangle_post(rt1, rt);
922 
923  v_count += 2;
924  t_count += 1;
925  }
926  else if (!in1) {
927  sub_v3_v3v3_db(vv1, rt->v[1]->gloc, cam_pos);
928  sub_v3_v3v3_db(vv2, cam_pos, rt->v[2]->gloc);
929  dot1 = dot_v3v3_db(vv1, view_dir);
930  dot2 = dot_v3v3_db(vv2, view_dir);
931  a = dot1 / (dot1 + dot2);
932  interp_v3_v3v3_db(rv[0].gloc, rt->v[1]->gloc, rt->v[2]->gloc, a);
933  mul_v4_m4v3_db(rv[0].fbcoord, vp, rv[0].gloc);
934  rv[0].index = rt->v[2]->index;
935 
936  sub_v3_v3v3_db(vv1, rt->v[1]->gloc, cam_pos);
937  sub_v3_v3v3_db(vv2, cam_pos, rt->v[0]->gloc);
938  dot1 = dot_v3v3_db(vv1, view_dir);
939  dot2 = dot_v3v3_db(vv2, view_dir);
940  a = dot1 / (dot1 + dot2);
941  interp_v3_v3v3_db(rv[1].gloc, rt->v[1]->gloc, rt->v[0]->gloc, a);
942  mul_v4_m4v3_db(rv[1].fbcoord, vp, rv[1].gloc);
943  rv[1].index = rt->v[0]->index;
944 
946  if (allow_boundaries) {
947  e->flags = LRT_EDGE_FLAG_CONTOUR;
949  }
950  e->v1 = &rv[1];
951  e->v2 = &rv[0];
952  e->t1 = rt1;
953  e->object_ref = ob;
954 
955  SELECT_RL(1, rt->v[1], &rv[0], rt1)
956  SELECT_RL(0, rt->v[1], &rv[1], rt1)
957 
958  rt1->v[0] = &rv[0];
959  rt1->v[1] = rt->v[1];
960  rt1->v[2] = &rv[1];
961 
962  lineart_triangle_post(rt1, rt);
963 
964  v_count += 2;
965  t_count += 1;
966  }
967  break;
968  case 1:
969  /* One point behind near plane, cut those and
970  * generate 2 new points, 4 lines and 2 triangles. */
972 
996  if (in0) {
997  /* Cut point for line 0---|------1. */
998  sub_v3_v3v3_db(vv1, rt->v[1]->gloc, cam_pos);
999  sub_v3_v3v3_db(vv2, cam_pos, rt->v[0]->gloc);
1000  dot1 = dot_v3v3_db(vv1, view_dir);
1001  dot2 = dot_v3v3_db(vv2, view_dir);
1002  a = dot2 / (dot1 + dot2);
1003  /* Assign to a new point. */
1004  interp_v3_v3v3_db(rv[0].gloc, rt->v[0]->gloc, rt->v[1]->gloc, a);
1005  mul_v4_m4v3_db(rv[0].fbcoord, vp, rv[0].gloc);
1006  rv[0].index = rt->v[0]->index;
1007 
1008  /* Cut point for line 0---|------2. */
1009  sub_v3_v3v3_db(vv1, rt->v[2]->gloc, cam_pos);
1010  sub_v3_v3v3_db(vv2, cam_pos, rt->v[0]->gloc);
1011  dot1 = dot_v3v3_db(vv1, view_dir);
1012  dot2 = dot_v3v3_db(vv2, view_dir);
1013  a = dot2 / (dot1 + dot2);
1014  /* Assign to other new point. */
1015  interp_v3_v3v3_db(rv[1].gloc, rt->v[0]->gloc, rt->v[2]->gloc, a);
1016  mul_v4_m4v3_db(rv[1].fbcoord, vp, rv[1].gloc);
1017  rv[1].index = rt->v[0]->index;
1018 
1019  /* New line connects two new points. */
1020  INCREASE_RL
1021  if (allow_boundaries) {
1022  e->flags = LRT_EDGE_FLAG_CONTOUR;
1024  }
1025  e->v1 = &rv[1];
1026  e->v2 = &rv[0];
1027  e->t1 = rt1;
1028  e->object_ref = ob;
1029 
1030  /* New line connects new point 0 and old point 1,
1031  * this is a border line. */
1032 
1033  SELECT_RL(0, rt->v[1], &rv[0], rt1)
1034  SELECT_RL(2, rt->v[2], &rv[1], rt2)
1035  RELINK_RL(1, rt2)
1036 
1037  /* We now have one triangle closed. */
1038  rt1->v[0] = rt->v[1];
1039  rt1->v[1] = &rv[1];
1040  rt1->v[2] = &rv[0];
1041  /* Close the second triangle. */
1042  rt2->v[0] = &rv[1];
1043  rt2->v[1] = rt->v[1];
1044  rt2->v[2] = rt->v[2];
1045 
1046  lineart_triangle_post(rt1, rt);
1047  lineart_triangle_post(rt2, rt);
1048 
1049  v_count += 2;
1050  t_count += 2;
1051  }
1052  else if (in1) {
1053 
1054  sub_v3_v3v3_db(vv1, rt->v[1]->gloc, cam_pos);
1055  sub_v3_v3v3_db(vv2, cam_pos, rt->v[2]->gloc);
1056  dot1 = dot_v3v3_db(vv1, view_dir);
1057  dot2 = dot_v3v3_db(vv2, view_dir);
1058  a = dot1 / (dot1 + dot2);
1059  interp_v3_v3v3_db(rv[0].gloc, rt->v[1]->gloc, rt->v[2]->gloc, a);
1060  mul_v4_m4v3_db(rv[0].fbcoord, vp, rv[0].gloc);
1061  rv[0].index = rt->v[1]->index;
1062 
1063  sub_v3_v3v3_db(vv1, rt->v[1]->gloc, cam_pos);
1064  sub_v3_v3v3_db(vv2, cam_pos, rt->v[0]->gloc);
1065  dot1 = dot_v3v3_db(vv1, view_dir);
1066  dot2 = dot_v3v3_db(vv2, view_dir);
1067  a = dot1 / (dot1 + dot2);
1068  interp_v3_v3v3_db(rv[1].gloc, rt->v[1]->gloc, rt->v[0]->gloc, a);
1069  mul_v4_m4v3_db(rv[1].fbcoord, vp, rv[1].gloc);
1070  rv[1].index = rt->v[1]->index;
1071 
1072  INCREASE_RL
1073  if (allow_boundaries) {
1074  e->flags = LRT_EDGE_FLAG_CONTOUR;
1076  }
1077  e->v1 = &rv[1];
1078  e->v2 = &rv[0];
1079  e->t1 = rt1;
1080  e->object_ref = ob;
1081 
1082  SELECT_RL(1, rt->v[2], &rv[0], rt1)
1083  SELECT_RL(0, rt->v[0], &rv[1], rt2)
1084  RELINK_RL(2, rt2)
1085 
1086  rt1->v[0] = rt->v[2];
1087  rt1->v[1] = &rv[1];
1088  rt1->v[2] = &rv[0];
1089 
1090  rt2->v[0] = &rv[1];
1091  rt2->v[1] = rt->v[2];
1092  rt2->v[2] = rt->v[0];
1093 
1094  lineart_triangle_post(rt1, rt);
1095  lineart_triangle_post(rt2, rt);
1096 
1097  v_count += 2;
1098  t_count += 2;
1099  }
1100  else if (in2) {
1101 
1102  sub_v3_v3v3_db(vv1, rt->v[2]->gloc, cam_pos);
1103  sub_v3_v3v3_db(vv2, cam_pos, rt->v[0]->gloc);
1104  dot1 = dot_v3v3_db(vv1, view_dir);
1105  dot2 = dot_v3v3_db(vv2, view_dir);
1106  a = dot1 / (dot1 + dot2);
1107  interp_v3_v3v3_db(rv[0].gloc, rt->v[2]->gloc, rt->v[0]->gloc, a);
1108  mul_v4_m4v3_db(rv[0].fbcoord, vp, rv[0].gloc);
1109  rv[0].index = rt->v[2]->index;
1110 
1111  sub_v3_v3v3_db(vv1, rt->v[2]->gloc, cam_pos);
1112  sub_v3_v3v3_db(vv2, cam_pos, rt->v[1]->gloc);
1113  dot1 = dot_v3v3_db(vv1, view_dir);
1114  dot2 = dot_v3v3_db(vv2, view_dir);
1115  a = dot1 / (dot1 + dot2);
1116  interp_v3_v3v3_db(rv[1].gloc, rt->v[2]->gloc, rt->v[1]->gloc, a);
1117  mul_v4_m4v3_db(rv[1].fbcoord, vp, rv[1].gloc);
1118  rv[1].index = rt->v[2]->index;
1119 
1120  INCREASE_RL
1121  if (allow_boundaries) {
1122  e->flags = LRT_EDGE_FLAG_CONTOUR;
1124  }
1125  e->v1 = &rv[1];
1126  e->v2 = &rv[0];
1127  e->t1 = rt1;
1128  e->object_ref = ob;
1129 
1130  SELECT_RL(2, rt->v[0], &rv[0], rt1)
1131  SELECT_RL(1, rt->v[1], &rv[1], rt2)
1132  RELINK_RL(0, rt2)
1133 
1134  rt1->v[0] = rt->v[0];
1135  rt1->v[1] = &rv[1];
1136  rt1->v[2] = &rv[0];
1137 
1138  rt2->v[0] = &rv[1];
1139  rt2->v[1] = rt->v[0];
1140  rt2->v[2] = rt->v[1];
1141 
1142  lineart_triangle_post(rt1, rt);
1143  lineart_triangle_post(rt2, rt);
1144 
1145  v_count += 2;
1146  t_count += 2;
1147  }
1148  break;
1149  }
1150  *r_v_count = v_count;
1151  *r_e_count = e_count;
1152  *r_t_count = t_count;
1153 
1154 #undef INCREASE_RL
1155 #undef SELECT_RL
1156 #undef RELINK_RL
1157 #undef REMOVE_TRIANGLE_RL
1158 }
1159 
1166 static void lineart_main_cull_triangles(LineartRenderBuffer *rb, bool clip_far)
1167 {
1168  LineartTriangle *rt;
1169  LineartElementLinkNode *v_eln, *t_eln, *e_eln;
1170  double(*vp)[4] = rb->view_projection;
1171  int i;
1172  int v_count = 0, t_count = 0, e_count = 0;
1173  Object *ob;
1174  bool allow_boundaries = rb->allow_boundaries;
1175  double cam_pos[3];
1176  double clip_start = rb->near_clip, clip_end = rb->far_clip;
1177  double view_dir[3], clip_advance[3];
1178 
1179  copy_v3_v3_db(view_dir, rb->view_vector);
1180  copy_v3_v3_db(clip_advance, rb->view_vector);
1181  copy_v3_v3_db(cam_pos, rb->camera_pos);
1182 
1183  if (clip_far) {
1184  /* Move starting point to end plane. */
1185  mul_v3db_db(clip_advance, -clip_end);
1186  add_v3_v3_db(cam_pos, clip_advance);
1187 
1188  /* "reverse looking". */
1189  mul_v3db_db(view_dir, -1.0f);
1190  }
1191  else {
1192  /* Clip Near. */
1193  mul_v3db_db(clip_advance, -clip_start);
1194  add_v3_v3_db(cam_pos, clip_advance);
1195  }
1196 
1197  v_eln = lineart_memory_get_vert_space(rb);
1199  e_eln = lineart_memory_get_edge_space(rb);
1200 
1201  /* Additional memory space for storing generated points and triangles. */
1202 #define LRT_CULL_ENSURE_MEMORY \
1203  if (v_count > 60) { \
1204  v_eln->element_count = v_count; \
1205  v_eln = lineart_memory_get_vert_space(rb); \
1206  v_count = 0; \
1207  } \
1208  if (t_count > 60) { \
1209  t_eln->element_count = t_count; \
1210  t_eln = lineart_memory_get_triangle_space(rb); \
1211  t_count = 0; \
1212  } \
1213  if (e_count > 60) { \
1214  e_eln->element_count = e_count; \
1215  e_eln = lineart_memory_get_edge_space(rb); \
1216  e_count = 0; \
1217  }
1218 
1219 #define LRT_CULL_DECIDE_INSIDE \
1220  /* These three represents points that are in the clipping range or not*/ \
1221  in0 = 0, in1 = 0, in2 = 0; \
1222  if (clip_far) { \
1223  /* Point outside far plane. */ \
1224  if (rt->v[0]->fbcoord[use_w] > clip_end) { \
1225  in0 = 1; \
1226  } \
1227  if (rt->v[1]->fbcoord[use_w] > clip_end) { \
1228  in1 = 1; \
1229  } \
1230  if (rt->v[2]->fbcoord[use_w] > clip_end) { \
1231  in2 = 1; \
1232  } \
1233  } \
1234  else { \
1235  /* Point inside near plane. */ \
1236  if (rt->v[0]->fbcoord[use_w] < clip_start) { \
1237  in0 = 1; \
1238  } \
1239  if (rt->v[1]->fbcoord[use_w] < clip_start) { \
1240  in1 = 1; \
1241  } \
1242  if (rt->v[2]->fbcoord[use_w] < clip_start) { \
1243  in2 = 1; \
1244  } \
1245  }
1246 
1247  int use_w = 3;
1248  int in0 = 0, in1 = 0, in2 = 0;
1249 
1250  if (!rb->cam_is_persp) {
1251  clip_start = -1;
1252  clip_end = 1;
1253  use_w = 2;
1254  }
1255 
1256  /* Then go through all the other triangles. */
1258  if (reln->flags & LRT_ELEMENT_IS_ADDITIONAL) {
1259  continue;
1260  }
1261  ob = reln->object_ref;
1262  for (i = 0; i < reln->element_count; i++) {
1263  /* Select the triangle in the array. */
1264  rt = (void *)(((uchar *)reln->pointer) + rb->triangle_size * i);
1265 
1269  rt,
1270  in0,
1271  in1,
1272  in2,
1273  cam_pos,
1274  view_dir,
1275  allow_boundaries,
1276  vp,
1277  ob,
1278  &v_count,
1279  &e_count,
1280  &t_count,
1281  v_eln,
1282  e_eln,
1283  t_eln);
1284  }
1285  t_eln->element_count = t_count;
1286  v_eln->element_count = v_count;
1287  }
1288 
1289 #undef LRT_CULL_ENSURE_MEMORY
1290 #undef LRT_CULL_DECIDE_INSIDE
1291 }
1292 
1298 {
1299  LinkData *ld;
1300  while ((ld = BLI_pophead(&rb->triangle_adjacent_pointers)) != NULL) {
1301  MEM_freeN(ld->data);
1302  }
1304  LineartTriangle *rt = reln->pointer;
1305  int i;
1306  for (i = 0; i < reln->element_count; i++) {
1307  /* See definition of rt->intersecting_verts and the usage in
1308  * lineart_geometry_object_load() for detailed. */
1309  rt->intersecting_verts = NULL;
1310  rt = (LineartTriangle *)(((uchar *)rt) + rb->triangle_size);
1311  }
1312  }
1313 }
1314 
1316 {
1317  LineartVert *rv;
1318  int i;
1319 
1320  if (!rb->cam_is_persp) {
1321  return;
1322  }
1323 
1325  rv = reln->pointer;
1326  for (i = 0; i < reln->element_count; i++) {
1327  /* Do not divide Z, we use Z to back transform cut points in later chaining process. */
1328  rv[i].fbcoord[0] /= rv[i].fbcoord[3];
1329  rv[i].fbcoord[1] /= rv[i].fbcoord[3];
1330  /* Re-map z into (0-1) range, because we no longer need NDC (Normalized Device Coordinates)
1331  * at the moment.
1332  * The algorithm currently doesn't need Z for operation, we use W instead. If Z is needed in
1333  * the future, the line below correctly transforms it to view space coordinates. */
1334  // `rv[i].fbcoord[2] = -2 * rv[i].fbcoord[2] / (far - near) - (far + near) / (far - near);
1335  rv[i].fbcoord[0] -= rb->shift_x * 2;
1336  rv[i].fbcoord[1] -= rb->shift_y * 2;
1337  }
1338  }
1339 }
1340 
1345  BMVert *v, int index, LineartVert *RvBuf, double (*mv_mat)[4], double (*mvp_mat)[4])
1346 {
1347  double co[4];
1348  LineartVert *rv = &RvBuf[index];
1349  copy_v3db_v3fl(co, v->co);
1350  mul_v3_m4v3_db(rv->gloc, mv_mat, co);
1351  mul_v4_m4v3_db(rv->fbcoord, mvp_mat, co);
1352 }
1353 
1359  LineartTriangle *rt_array,
1360  int index)
1361 {
1362  char *b = (char *)rt_array;
1363  b += (index * rb->triangle_size);
1364  return (LineartTriangle *)b;
1365 }
1366 
1368  BMEdge *e,
1369  LineartTriangle *rt_array,
1370  LineartVert *rv_array,
1371  float crease_threshold,
1372  bool no_crease,
1373  bool count_freestyle,
1374  BMesh *bm_if_freestyle)
1375 {
1376  BMLoop *ll, *lr = NULL;
1377  ll = e->l;
1378  if (ll) {
1379  lr = e->l->radial_next;
1380  }
1381 
1382  if (ll == lr || !lr) {
1383  return LRT_EDGE_FLAG_CONTOUR;
1384  }
1385 
1386  LineartTriangle *rt1, *rt2;
1387  LineartVert *l;
1388 
1389  /* The mesh should already be triangulated now, so we can assume each face is a triangle. */
1390  rt1 = lineart_triangle_from_index(rb, rt_array, BM_elem_index_get(ll->f));
1391  rt2 = lineart_triangle_from_index(rb, rt_array, BM_elem_index_get(lr->f));
1392 
1393  l = &rv_array[BM_elem_index_get(e->v1)];
1394 
1395  double vv[3];
1396  double *view_vector = vv;
1397  double dot_1 = 0, dot_2 = 0;
1398  double result;
1399  FreestyleEdge *fe;
1400 
1401  if (rb->cam_is_persp) {
1402  sub_v3_v3v3_db(view_vector, l->gloc, rb->camera_pos);
1403  }
1404  else {
1405  view_vector = rb->view_vector;
1406  }
1407 
1408  dot_1 = dot_v3v3_db(view_vector, rt1->gn);
1409  dot_2 = dot_v3v3_db(view_vector, rt2->gn);
1410 
1411  if ((result = dot_1 * dot_2) <= 0 && (dot_1 + dot_2)) {
1412  return LRT_EDGE_FLAG_CONTOUR;
1413  }
1414 
1415  if (rb->use_crease && (dot_v3v3_db(rt1->gn, rt2->gn) < crease_threshold)) {
1416  if (!no_crease) {
1417  return LRT_EDGE_FLAG_CREASE;
1418  }
1419  }
1420  else if (rb->use_material && (ll->f->mat_nr != lr->f->mat_nr)) {
1421  return LRT_EDGE_FLAG_MATERIAL;
1422  }
1423  else if (count_freestyle && rb->use_edge_marks) {
1424  fe = CustomData_bmesh_get(&bm_if_freestyle->edata, e->head.data, CD_FREESTYLE_EDGE);
1425  if (fe->flag & FREESTYLE_EDGE_MARK) {
1426  return LRT_EDGE_FLAG_EDGE_MARK;
1427  }
1428  }
1429  return 0;
1430 }
1431 
1433 {
1434  switch (e->flags) {
1435  case LRT_EDGE_FLAG_CONTOUR:
1437  break;
1438  case LRT_EDGE_FLAG_CREASE:
1440  break;
1443  break;
1446  break;
1449  break;
1450  }
1451 }
1452 
1455  LineartEdge *e)
1456 {
1457  if (lineart_edge_match(rt, e, 0, 1)) {
1458  rta->e[0] = e;
1459  }
1460  else if (lineart_edge_match(rt, e, 1, 2)) {
1461  rta->e[1] = e;
1462  }
1463  else if (lineart_edge_match(rt, e, 2, 0)) {
1464  rta->e[2] = e;
1465  }
1466 }
1467 
1469  Object *ob,
1470  double (*mv_mat)[4],
1471  double (*mvp_mat)[4],
1472  LineartRenderBuffer *rb,
1473  int override_usage,
1474  int *global_vindex)
1475 {
1476  BMesh *bm;
1477  BMVert *v;
1478  BMFace *f;
1479  BMEdge *e;
1480  BMLoop *loop;
1481  LineartEdge *la_e;
1482  LineartTriangle *rt;
1484  double new_mvp[4][4], new_mv[4][4], normal[4][4];
1485  float imat[4][4];
1486  LineartElementLinkNode *reln;
1487  LineartVert *orv;
1488  LineartEdge *o_la_e;
1489  LineartTriangle *ort;
1490  Object *orig_ob;
1491  int CanFindFreestyle = 0;
1492  int i, global_i = (*global_vindex);
1493  Mesh *use_mesh;
1494  float use_crease = 0;
1495 
1496  int usage = override_usage ? override_usage : ob->lineart.usage;
1497 
1498 #define LRT_MESH_FINISH \
1499  BM_mesh_free(bm); \
1500  if (ob->type != OB_MESH) { \
1501  BKE_mesh_free_data(use_mesh); \
1502  MEM_freeN(use_mesh); \
1503  }
1504 
1505  if (usage == OBJECT_LRT_EXCLUDE) {
1506  return;
1507  }
1508 
1509  if (ELEM(ob->type, OB_MESH, OB_MBALL, OB_CURVE, OB_SURF, OB_FONT)) {
1510 
1511  if (ob->type == OB_MESH) {
1512  use_mesh = DEG_get_evaluated_object(dg, ob)->data;
1513  }
1514  else {
1515  use_mesh = BKE_mesh_new_from_object(NULL, ob, false, false);
1516  }
1517 
1518  /* In case we can not get any mesh geometry data from the object */
1519  if (!use_mesh) {
1520  return;
1521  }
1522 
1523  /* First we need to prepare the matrix used for transforming this specific object. */
1524  mul_m4db_m4db_m4fl_uniq(new_mvp, mvp_mat, ob->obmat);
1525  mul_m4db_m4db_m4fl_uniq(new_mv, mv_mat, ob->obmat);
1526 
1527  invert_m4_m4(imat, ob->obmat);
1528  transpose_m4(imat);
1529  copy_m4d_m4(normal, imat);
1530 
1531  if (use_mesh->edit_mesh) {
1532  /* Do not use edit_mesh directly because we will modify it, so create a copy. */
1533  bm = BM_mesh_copy(use_mesh->edit_mesh->bm);
1534  }
1535  else {
1536  const BMAllocTemplate allocsize = BMALLOC_TEMPLATE_FROM_ME(((Mesh *)(use_mesh)));
1537  bm = BM_mesh_create(&allocsize,
1538  &((struct BMeshCreateParams){
1539  .use_toolflags = true,
1540  }));
1542  use_mesh,
1543  &((struct BMeshFromMeshParams){
1544  .calc_face_normal = true,
1545  }));
1546  }
1547 
1548  if (rb->remove_doubles) {
1549  BMEditMesh *em = BKE_editmesh_create(bm, false);
1550  BMOperator findop, weldop;
1551 
1552  /* See bmesh_opdefines.c and bmesh_operators.c for op names and argument formatting. */
1553  BMO_op_initf(bm, &findop, BMO_FLAG_DEFAULTS, "find_doubles verts=%av dist=%f", 0.0001);
1554 
1555  BMO_op_exec(bm, &findop);
1556 
1557  /* Weld the vertices. */
1558  BMO_op_init(bm, &weldop, BMO_FLAG_DEFAULTS, "weld_verts");
1559  BMO_slot_copy(&findop, slots_out, "targetmap.out", &weldop, slots_in, "targetmap");
1560  BMO_op_exec(bm, &weldop);
1561 
1562  BMO_op_finish(bm, &findop);
1563  BMO_op_finish(bm, &weldop);
1564 
1565  MEM_freeN(em);
1566  }
1567 
1574 
1576  CanFindFreestyle = 1;
1577  }
1578 
1579  /* Only allocate memory for verts and tris as we don't know how many lines we will generate
1580  * yet. */
1581  orv = lineart_mem_aquire(&rb->render_data_pool, sizeof(LineartVert) * bm->totvert);
1583 
1584  orig_ob = ob->id.orig_id ? (Object *)ob->id.orig_id : ob;
1585 
1588  reln->element_count = bm->totvert;
1589  reln->object_ref = orig_ob;
1590 
1591  if (ob->lineart.flags & OBJECT_LRT_OWN_CREASE) {
1592  use_crease = cosf(M_PI - ob->lineart.crease_threshold);
1593  }
1594  else {
1595  use_crease = rb->crease_threshold;
1596  }
1597 
1598  /* FIXME(Yiming): Hack for getting clean 3D text, the seam that extruded text object creates
1599  * erroneous detection on creases. Future configuration should allow options. */
1600  if (ob->type == OB_FONT) {
1601  reln->flags |= LRT_ELEMENT_BORDER_ONLY;
1602  }
1603 
1606  reln->element_count = bm->totface;
1607  reln->object_ref = orig_ob;
1609 
1610  /* Note this memory is not from pool, will be deleted after culling. */
1611  orta = MEM_callocN(sizeof(LineartTriangleAdjacent) * bm->totface, "LineartTriangleAdjacent");
1612  /* Link is minimal so we use pool anyway. */
1614 
1615  for (i = 0; i < bm->totvert; i++) {
1616  v = BM_vert_at_index(bm, i);
1617  lineart_vert_transform(v, i, orv, new_mv, new_mvp);
1618  orv[i].index = i + global_i;
1619  }
1620  /* Register a global index increment. See #lineart_triangle_share_edge() and
1621  * #lineart_main_load_geometries() for detailed. It's okay that global_vindex might eventually
1622  * overflow, in such large scene it's virtually impossible for two vertex of the same numeric
1623  * index to come close together. */
1624  (*global_vindex) += bm->totvert;
1625 
1626  rt = ort;
1627  for (i = 0; i < bm->totface; i++) {
1628  f = BM_face_at_index(bm, i);
1629 
1630  loop = f->l_first;
1631  rt->v[0] = &orv[BM_elem_index_get(loop->v)];
1632  loop = loop->next;
1633  rt->v[1] = &orv[BM_elem_index_get(loop->v)];
1634  loop = loop->next;
1635  rt->v[2] = &orv[BM_elem_index_get(loop->v)];
1636 
1637  /* Transparency bit assignment. */
1638  Material *mat = BKE_object_material_get(ob, f->mat_nr + 1);
1640  mat->lineart.transparency_mask :
1641  0);
1642 
1643  double gn[3];
1644  copy_v3db_v3fl(gn, f->no);
1645  mul_v3_mat3_m4v3_db(rt->gn, normal, gn);
1646  normalize_v3_db(rt->gn);
1647 
1648  if (usage == OBJECT_LRT_INTERSECTION_ONLY) {
1650  }
1653  }
1654 
1655  /* Re-use this field to refer to adjacent info, will be cleared after culling stage. */
1656  rt->intersecting_verts = (void *)&orta[i];
1657 
1658  rt = (LineartTriangle *)(((uchar *)rt) + rb->triangle_size);
1659  }
1660 
1661  /* Use BM_ELEM_TAG in f->head.hflag to store needed faces in the first iteration. */
1662 
1663  int allocate_la_e = 0;
1664  for (i = 0; i < bm->totedge; i++) {
1665  e = BM_edge_at_index(bm, i);
1666 
1667  /* Because e->head.hflag is char, so line type flags should not exceed positive 7 bits. */
1668  char eflag = lineart_identify_feature_line(
1669  rb, e, ort, orv, use_crease, ob->type == OB_FONT, CanFindFreestyle, bm);
1670  if (eflag) {
1671  /* Only allocate for feature lines (instead of all lines) to save memory. */
1672  allocate_la_e++;
1673  }
1674  /* Here we just use bm's flag for when loading actual lines, then we don't need to call
1675  * lineart_identify_feature_line() again, e->head.hflag deleted after loading anyway. Always
1676  * set the flag, so hflag stays 0 for lines that are not feature lines. */
1677  e->head.hflag = eflag;
1678  }
1679 
1680  o_la_e = lineart_mem_aquire(&rb->render_data_pool, sizeof(LineartEdge) * allocate_la_e);
1682  &rb->line_buffer_pointers, &rb->render_data_pool, o_la_e, sizeof(LineartElementLinkNode));
1683  reln->element_count = allocate_la_e;
1684  reln->object_ref = orig_ob;
1685 
1686  la_e = o_la_e;
1687  for (i = 0; i < bm->totedge; i++) {
1688  e = BM_edge_at_index(bm, i);
1689 
1690  /* Not a feature line, so we skip. */
1691  if (!e->head.hflag) {
1692  continue;
1693  }
1694 
1695  la_e->v1 = &orv[BM_elem_index_get(e->v1)];
1696  la_e->v2 = &orv[BM_elem_index_get(e->v2)];
1697  la_e->v1_obindex = la_e->v1->index - global_i;
1698  la_e->v2_obindex = la_e->v2->index - global_i;
1699  if (e->l) {
1700  int findex = BM_elem_index_get(e->l->f);
1701  la_e->t1 = lineart_triangle_from_index(rb, ort, findex);
1702  lineart_triangle_adjacent_assign(la_e->t1, &orta[findex], la_e);
1703  if (e->l->radial_next && e->l->radial_next != e->l) {
1704  findex = BM_elem_index_get(e->l->radial_next->f);
1705  la_e->t2 = lineart_triangle_from_index(rb, ort, findex);
1706  lineart_triangle_adjacent_assign(la_e->t2, &orta[findex], la_e);
1707  }
1708  }
1709  la_e->flags = e->head.hflag;
1710  la_e->object_ref = orig_ob;
1711 
1713  sizeof(LineartLineSegment));
1714  BLI_addtail(&la_e->segments, rls);
1716  lineart_add_edge_to_list(rb, la_e);
1717  }
1718 
1719  la_e++;
1720  }
1721 
1723  }
1724 
1725 #undef LRT_MESH_FINISH
1726 }
1727 
1729 {
1730  CollectionChild *cc;
1731  Collection *c = source->id.orig_id ? (Collection *)source->id.orig_id : source;
1733  return false;
1734  }
1735  for (cc = source->children.first; cc; cc = cc->next) {
1737  return false;
1738  }
1739  }
1740  return true;
1741 }
1742 
1750 {
1751 
1752  if (!c) {
1753  return OBJECT_LRT_INHERIT;
1754  }
1755 
1756  int object_has_special_usage = (ob->lineart.usage != OBJECT_LRT_INHERIT);
1757 
1758  if (object_has_special_usage) {
1759  return ob->lineart.usage;
1760  }
1761 
1762  if (c->children.first == NULL) {
1763  if (BKE_collection_has_object(c, (Object *)(ob->id.orig_id))) {
1764  if (ob->lineart.usage == OBJECT_LRT_INHERIT) {
1765  switch (c->lineart_usage) {
1769  return OBJECT_LRT_EXCLUDE;
1774  }
1775  return OBJECT_LRT_INHERIT;
1776  }
1777  return ob->lineart.usage;
1778  }
1779  return OBJECT_LRT_INHERIT;
1780  }
1781 
1782  LISTBASE_FOREACH (CollectionChild *, cc, &c->children) {
1783  int result = lineart_usage_check(cc->collection, ob, _rb);
1784  if (result > OBJECT_LRT_INHERIT) {
1785  return result;
1786  }
1787  }
1788 
1789  /* Temp solution to speed up calculation in the modifier without cache. See the definition of
1790  * rb->_source_type for details. */
1791  if (_rb->_source_type == LRT_SOURCE_OBJECT) {
1792  if (ob != _rb->_source_object && ob->id.orig_id != (ID *)_rb->_source_object) {
1794  }
1795  }
1796  else if (_rb->_source_type == LRT_SOURCE_COLLECTION) {
1799  }
1800  }
1801 
1802  return OBJECT_LRT_INHERIT;
1803 }
1804 
1807  Scene *scene,
1808  Object *camera /* Still use camera arg for convenience. */,
1809  LineartRenderBuffer *rb,
1810  bool allow_duplicates)
1811 {
1812  double proj[4][4], view[4][4], result[4][4];
1813  float inv[4][4];
1814 
1815  Camera *cam = camera->data;
1816  float sensor = BKE_camera_sensor_size(cam->sensor_fit, cam->sensor_x, cam->sensor_y);
1817  int fit = BKE_camera_sensor_fit(cam->sensor_fit, rb->w, rb->h);
1818  double asp = ((double)rb->w / (double)rb->h);
1819 
1820  if (cam->type == CAM_PERSP) {
1821  if (fit == CAMERA_SENSOR_FIT_VERT && asp > 1) {
1822  sensor *= asp;
1823  }
1824  if (fit == CAMERA_SENSOR_FIT_HOR && asp < 1) {
1825  sensor /= asp;
1826  }
1827  double fov = focallength_to_fov(cam->lens, sensor);
1828  lineart_matrix_perspective_44d(proj, fov, asp, cam->clip_start, cam->clip_end);
1829  }
1830  else if (cam->type == CAM_ORTHO) {
1831  double w = cam->ortho_scale / 2;
1832  lineart_matrix_ortho_44d(proj, -w, w, -w / asp, w / asp, cam->clip_start, cam->clip_end);
1833  }
1834 
1835  double t_start;
1836 
1837  if (G.debug_value == 4000) {
1838  t_start = PIL_check_seconds_timer();
1839  }
1840 
1841  invert_m4_m4(inv, rb->cam_obmat);
1842  mul_m4db_m4db_m4fl_uniq(result, proj, inv);
1843  copy_m4_m4_db(proj, result);
1844  copy_m4_m4_db(rb->view_projection, proj);
1845 
1846  unit_m4_db(view);
1847 
1850 
1853 
1854  /* Instance duplicated & particles. */
1855  if (allow_duplicates) {
1856  flags |= DEG_ITER_OBJECT_FLAG_DUPLI;
1857  }
1858 
1859  /* This is to serialize vertex index in the whole scene, so lineart_triangle_share_edge() can
1860  * work properly from the lack of triangle adjacent info. */
1861  int global_i = 0;
1862 
1863  DEG_OBJECT_ITER_BEGIN (depsgraph, ob, flags) {
1864  int usage = lineart_usage_check(scene->master_collection, ob, rb);
1865 
1866  lineart_geometry_object_load(depsgraph, ob, view, proj, rb, usage, &global_i);
1867  }
1869 }
1870 
1876  const LineartVert *rv,
1877  LineartVert **l,
1878  LineartVert **r)
1879 {
1880  if (rt->v[0] == rv) {
1881  *l = rt->v[1];
1882  *r = rt->v[2];
1883  return true;
1884  }
1885  if (rt->v[1] == rv) {
1886  *l = rt->v[2];
1887  *r = rt->v[0];
1888  return true;
1889  }
1890  if (rt->v[2] == rv) {
1891  *l = rt->v[0];
1892  *r = rt->v[1];
1893  return true;
1894  }
1895  return false;
1896 }
1897 
1899  const LineartEdge *e,
1900  bool allow_overlapping_edges)
1901 {
1902  /* Normally we just determine from the pointer address. */
1903  if (e->t1 == rt || e->t2 == rt) {
1904  return true;
1905  }
1906  /* If allows overlapping, then we compare the vertex coordinates one by one to determine if one
1907  * edge is from specific triangle. This is slower but can handle edge split cases very well. */
1908  if (allow_overlapping_edges) {
1909 #define LRT_TRI_SAME_POINT(rt, i, pt) \
1910  ((LRT_DOUBLE_CLOSE_ENOUGH(rt->v[i]->gloc[0], pt->gloc[0]) && \
1911  LRT_DOUBLE_CLOSE_ENOUGH(rt->v[i]->gloc[1], pt->gloc[1]) && \
1912  LRT_DOUBLE_CLOSE_ENOUGH(rt->v[i]->gloc[2], pt->gloc[2])) || \
1913  (LRT_DOUBLE_CLOSE_ENOUGH(rt->v[i]->gloc[0], pt->gloc[0]) && \
1914  LRT_DOUBLE_CLOSE_ENOUGH(rt->v[i]->gloc[1], pt->gloc[1]) && \
1915  LRT_DOUBLE_CLOSE_ENOUGH(rt->v[i]->gloc[2], pt->gloc[2])))
1916  if ((LRT_TRI_SAME_POINT(rt, 0, e->v1) || LRT_TRI_SAME_POINT(rt, 1, e->v1) ||
1917  LRT_TRI_SAME_POINT(rt, 2, e->v1)) &&
1918  (LRT_TRI_SAME_POINT(rt, 0, e->v2) || LRT_TRI_SAME_POINT(rt, 1, e->v2) ||
1919  LRT_TRI_SAME_POINT(rt, 2, e->v2))) {
1920  return true;
1921  }
1922 #undef LRT_TRI_SAME_POINT
1923  }
1924  return false;
1925 }
1926 
1927 /* Sorting three intersection points from min to max,
1928  * the order for each intersection is set in lst[0] to lst[2].*/
1929 #define INTERSECT_SORT_MIN_TO_MAX_3(ia, ib, ic, lst) \
1930  { \
1931  lst[0] = LRT_MIN3_INDEX(ia, ib, ic); \
1932  lst[1] = (((ia <= ib && ib <= ic) || (ic <= ib && ib <= ia)) ? \
1933  1 : \
1934  (((ic <= ia && ia <= ib) || (ib < ia && ia <= ic)) ? 0 : 2)); \
1935  lst[2] = LRT_MAX3_INDEX(ia, ib, ic); \
1936  }
1937 
1938 /* `ia ib ic` are ordered. */
1939 #define INTERSECT_JUST_GREATER(is, order, num, index) \
1940  { \
1941  index = (num < is[order[0]] ? \
1942  order[0] : \
1943  (num < is[order[1]] ? order[1] : (num < is[order[2]] ? order[2] : order[2]))); \
1944  }
1945 
1946 /* `ia ib ic` are ordered. */
1947 #define INTERSECT_JUST_SMALLER(is, order, num, index) \
1948  { \
1949  index = (num > is[order[2]] ? \
1950  order[2] : \
1951  (num > is[order[1]] ? order[1] : (num > is[order[0]] ? order[0] : order[0]))); \
1952  }
1953 
1961  const LineartTriangle *rt,
1962  const LineartEdge *e,
1963  const double *override_camera_loc,
1964  const bool override_cam_is_persp,
1965  const bool allow_overlapping_edges,
1966  const double vp[4][4],
1967  const double *camera_dir,
1968  const float cam_shift_x,
1969  const float cam_shift_y,
1970  double *from,
1971  double *to)
1972 {
1973  double is[3] = {0};
1974  int order[3];
1975  int LCross = -1, RCross = -1;
1976  int a, b, c;
1977  int st_l = 0, st_r = 0;
1978 
1979  double Lv[3];
1980  double Rv[3];
1981  double vd4[4];
1982  double Cv[3];
1983  double dot_l, dot_r, dot_la, dot_ra;
1984  double dot_f;
1985  double gloc[4], trans[4];
1986  double cut = -1;
1987 
1988  double *LFBC = e->v1->fbcoord, *RFBC = e->v2->fbcoord, *FBC0 = rt->v[0]->fbcoord,
1989  *FBC1 = rt->v[1]->fbcoord, *FBC2 = rt->v[2]->fbcoord;
1990 
1991  /* Overlapping not possible, return early. */
1992  if ((MAX3(FBC0[0], FBC1[0], FBC2[0]) < MIN2(LFBC[0], RFBC[0])) ||
1993  (MIN3(FBC0[0], FBC1[0], FBC2[0]) > MAX2(LFBC[0], RFBC[0])) ||
1994  (MAX3(FBC0[1], FBC1[1], FBC2[1]) < MIN2(LFBC[1], RFBC[1])) ||
1995  (MIN3(FBC0[1], FBC1[1], FBC2[1]) > MAX2(LFBC[1], RFBC[1])) ||
1996  (MIN3(FBC0[3], FBC1[3], FBC2[3]) > MAX2(LFBC[3], RFBC[3]))) {
1997  return false;
1998  }
1999 
2000  /* If the the line is one of the edge in the triangle, then it's not occluded. */
2001  if (lineart_edge_from_triangle(rt, e, allow_overlapping_edges)) {
2002  return false;
2003  }
2004 
2005  /* Check if the line visually crosses one of the edge in the triangle. */
2006  a = lineart_LineIntersectTest2d(LFBC, RFBC, FBC0, FBC1, &is[0]);
2007  b = lineart_LineIntersectTest2d(LFBC, RFBC, FBC1, FBC2, &is[1]);
2008  c = lineart_LineIntersectTest2d(LFBC, RFBC, FBC2, FBC0, &is[2]);
2009 
2010  /* Sort the intersection distance. */
2011  INTERSECT_SORT_MIN_TO_MAX_3(is[0], is[1], is[2], order);
2012 
2013  sub_v3_v3v3_db(Lv, e->v1->gloc, rt->v[0]->gloc);
2014  sub_v3_v3v3_db(Rv, e->v2->gloc, rt->v[0]->gloc);
2015 
2016  copy_v3_v3_db(Cv, camera_dir);
2017 
2018  if (override_cam_is_persp) {
2019  copy_v3_v3_db(vd4, override_camera_loc);
2020  }
2021  else {
2022  copy_v4_v4_db(vd4, override_camera_loc);
2023  }
2024  if (override_cam_is_persp) {
2025  sub_v3_v3v3_db(Cv, vd4, rt->v[0]->gloc);
2026  }
2027 
2028  dot_l = dot_v3v3_db(Lv, rt->gn);
2029  dot_r = dot_v3v3_db(Rv, rt->gn);
2030  dot_f = dot_v3v3_db(Cv, rt->gn);
2031 
2032  if (!dot_f) {
2033  return false;
2034  }
2035 
2036  if (!a && !b && !c) {
2037  if (!(st_l = lineart_point_triangle_relation(LFBC, FBC0, FBC1, FBC2)) &&
2038  !(st_r = lineart_point_triangle_relation(RFBC, FBC0, FBC1, FBC2))) {
2039  return 0; /* Intersection point is not inside triangle. */
2040  }
2041  }
2042 
2043  st_l = lineart_point_triangle_relation(LFBC, FBC0, FBC1, FBC2);
2044  st_r = lineart_point_triangle_relation(RFBC, FBC0, FBC1, FBC2);
2045 
2046  /* Determine the cut position. */
2047 
2048  dot_la = fabs(dot_l);
2049  if (dot_la < DBL_EPSILON) {
2050  dot_la = 0;
2051  dot_l = 0;
2052  }
2053  dot_ra = fabs(dot_r);
2054  if (dot_ra < DBL_EPSILON) {
2055  dot_ra = 0;
2056  dot_r = 0;
2057  }
2058  if (dot_l - dot_r == 0) {
2059  cut = 100000;
2060  }
2061  else if (dot_l * dot_r <= 0) {
2062  cut = dot_la / fabs(dot_l - dot_r);
2063  }
2064  else {
2065  cut = fabs(dot_r + dot_l) / fabs(dot_l - dot_r);
2066  cut = dot_ra > dot_la ? 1 - cut : cut;
2067  }
2068 
2069  /* Transform the cut from geometry space to image space. */
2070  if (override_cam_is_persp) {
2071  interp_v3_v3v3_db(gloc, e->v1->gloc, e->v2->gloc, cut);
2072  mul_v4_m4v3_db(trans, vp, gloc);
2073  mul_v3db_db(trans, (1 / trans[3]));
2074  }
2075  else {
2076  interp_v3_v3v3_db(trans, e->v1->fbcoord, e->v2->fbcoord, cut);
2077  }
2078  trans[0] -= cam_shift_x * 2;
2079  trans[1] -= cam_shift_y * 2;
2080 
2081  /* To accommodate `k=0` and `k=inf` (vertical) lines. here the cut is in image space. */
2082  if (fabs(e->v1->fbcoord[0] - e->v2->fbcoord[0]) > fabs(e->v1->fbcoord[1] - e->v2->fbcoord[1])) {
2083  cut = ratiod(e->v1->fbcoord[0], e->v2->fbcoord[0], trans[0]);
2084  }
2085  else {
2086  cut = ratiod(e->v1->fbcoord[1], e->v2->fbcoord[1], trans[1]);
2087  }
2088 
2089  /* Determine the pair of edges that the line has crossed. */
2090 
2091  if (st_l == 2) {
2092  if (st_r == 2) {
2094  INTERSECT_JUST_GREATER(is, order, 1 - DBL_TRIANGLE_LIM, RCross);
2095  }
2096  else if (st_r == 1) {
2098  INTERSECT_JUST_GREATER(is, order, 1 - DBL_TRIANGLE_LIM, RCross);
2099  }
2100  else if (st_r == 0) {
2102  INTERSECT_JUST_GREATER(is, order, 0, RCross);
2103  }
2104  }
2105  else if (st_l == 1) {
2106  if (st_r == 2) {
2108  INTERSECT_JUST_GREATER(is, order, 1 - DBL_TRIANGLE_LIM, RCross);
2109  }
2110  else if (st_r == 1) {
2112  INTERSECT_JUST_GREATER(is, order, 1 - DBL_TRIANGLE_LIM, RCross);
2113  }
2114  else if (st_r == 0) {
2116  if (LRT_ABC(RCross) && is[RCross] > (DBL_TRIANGLE_LIM)) {
2118  }
2119  else {
2122  }
2123  }
2124  }
2125  else if (st_l == 0) {
2126  if (st_r == 2) {
2127  INTERSECT_JUST_SMALLER(is, order, 1 - DBL_TRIANGLE_LIM, LCross);
2128  INTERSECT_JUST_GREATER(is, order, 1 - DBL_TRIANGLE_LIM, RCross);
2129  }
2130  else if (st_r == 1) {
2131  INTERSECT_JUST_SMALLER(is, order, 1 - DBL_TRIANGLE_LIM, LCross);
2132  if (LRT_ABC(LCross) && is[LCross] < (1 - DBL_TRIANGLE_LIM)) {
2133  INTERSECT_JUST_GREATER(is, order, 1 - DBL_TRIANGLE_LIM, RCross);
2134  }
2135  else {
2136  INTERSECT_JUST_SMALLER(is, order, 1 + DBL_TRIANGLE_LIM, LCross);
2137  INTERSECT_JUST_GREATER(is, order, 1 + DBL_TRIANGLE_LIM, RCross);
2138  }
2139  }
2140  else if (st_r == 0) {
2142  if (LRT_ABC(LCross) && is[LCross] > DBL_TRIANGLE_LIM) {
2143  INTERSECT_JUST_GREATER(is, order, is[LCross], RCross);
2144  }
2145  else {
2146  INTERSECT_JUST_GREATER(is, order, is[LCross], LCross);
2147  INTERSECT_JUST_GREATER(is, order, is[LCross], RCross);
2148  }
2149  }
2150  }
2151 
2152  double LF = dot_l * dot_f, RF = dot_r * dot_f;
2153 
2154  /* Determine the start and end point of image space cut on a line. */
2155  if (LF <= 0 && RF <= 0 && (dot_l || dot_r)) {
2156  *from = MAX2(0, is[LCross]);
2157  *to = MIN2(1, is[RCross]);
2158  if (*from >= *to) {
2159  return false;
2160  }
2161  return true;
2162  }
2163  if (LF >= 0 && RF <= 0 && (dot_l || dot_r)) {
2164  *from = MAX2(cut, is[LCross]);
2165  *to = MIN2(1, is[RCross]);
2166  if (*from >= *to) {
2167  return false;
2168  }
2169  return true;
2170  }
2171  if (LF <= 0 && RF >= 0 && (dot_l || dot_r)) {
2172  *from = MAX2(0, is[LCross]);
2173  *to = MIN2(cut, is[RCross]);
2174  if (*from >= *to) {
2175  return false;
2176  }
2177  return true;
2178  }
2179 
2180  /* Unlikely, but here's the default failed value if anything fall through. */
2181  return false;
2182 }
2183 
2184 #undef INTERSECT_SORT_MIN_TO_MAX_3
2185 #undef INTERSECT_JUST_GREATER
2186 #undef INTERSECT_JUST_SMALLER
2187 
2193 {
2194  if (l->v[0]->index == r->v[0]->index) {
2195  if (l->v[1]->index == r->v[1]->index || l->v[1]->index == r->v[2]->index ||
2196  l->v[2]->index == r->v[2]->index || l->v[2]->index == r->v[1]->index) {
2197  return true;
2198  }
2199  }
2200  if (l->v[0]->index == r->v[1]->index) {
2201  if (l->v[1]->index == r->v[0]->index || l->v[1]->index == r->v[2]->index ||
2202  l->v[2]->index == r->v[2]->index || l->v[2]->index == r->v[0]->index) {
2203  return true;
2204  }
2205  }
2206  if (l->v[0]->index == r->v[2]->index) {
2207  if (l->v[1]->index == r->v[1]->index || l->v[1]->index == r->v[0]->index ||
2208  l->v[2]->index == r->v[0]->index || l->v[2]->index == r->v[1]->index) {
2209  return true;
2210  }
2211  }
2212  if (l->v[1]->index == r->v[0]->index) {
2213  if (l->v[2]->index == r->v[1]->index || l->v[2]->index == r->v[2]->index ||
2214  l->v[0]->index == r->v[2]->index || l->v[0]->index == r->v[1]->index) {
2215  return true;
2216  }
2217  }
2218  if (l->v[1]->index == r->v[1]->index) {
2219  if (l->v[2]->index == r->v[0]->index || l->v[2]->index == r->v[2]->index ||
2220  l->v[0]->index == r->v[2]->index || l->v[0]->index == r->v[0]->index) {
2221  return true;
2222  }
2223  }
2224  if (l->v[1]->index == r->v[2]->index) {
2225  if (l->v[2]->index == r->v[1]->index || l->v[2]->index == r->v[0]->index ||
2226  l->v[0]->index == r->v[0]->index || l->v[0]->index == r->v[1]->index) {
2227  return true;
2228  }
2229  }
2230 
2231  /* Otherwise not possible. */
2232  return false;
2233 }
2234 
2236  const LineartTriangle *r)
2237 {
2238  if (l->v[0] == r->v[0]) {
2239  return r->v[0];
2240  }
2241  if (l->v[0] == r->v[1]) {
2242  return r->v[1];
2243  }
2244  if (l->v[0] == r->v[2]) {
2245  return r->v[2];
2246  }
2247  if (l->v[1] == r->v[0]) {
2248  return r->v[0];
2249  }
2250  if (l->v[1] == r->v[1]) {
2251  return r->v[1];
2252  }
2253  if (l->v[1] == r->v[2]) {
2254  return r->v[2];
2255  }
2256  if (l->v[2] == r->v[0]) {
2257  return r->v[0];
2258  }
2259  if (l->v[2] == r->v[1]) {
2260  return r->v[1];
2261  }
2262  if (l->v[2] == r->v[2]) {
2263  return r->v[2];
2264  }
2265  return NULL;
2266 }
2267 
2274 {
2275  return ((rv->isec1 == v1->base.index && rv->isec2 == v2->base.index) ||
2276  (rv->isec2 == v2->base.index && rv->isec1 == v1->base.index));
2277 }
2278 
2280 {
2282  irv->isec1 = v1->index;
2283  irv->isec2 = v2->index;
2284 }
2285 
2292  LineartVert *v1,
2293  LineartVert *v2,
2294  LineartTriangle *rt,
2295  LineartTriangle *testing,
2296  LineartVert *last)
2297 {
2298  double Lv[3];
2299  double Rv[3];
2300  double dot_l, dot_r;
2302  double gloc[3];
2303  LineartVert *l = v1, *r = v2;
2304 
2305  for (LinkNode *ln = (void *)testing->intersecting_verts; ln; ln = ln->next) {
2306  LineartVertIntersection *rv = ln->link;
2307  if (rv->intersecting_with == rt &&
2310  return (LineartVert *)rv;
2311  }
2312  }
2313 
2314  sub_v3_v3v3_db(Lv, l->gloc, testing->v[0]->gloc);
2315  sub_v3_v3v3_db(Rv, r->gloc, testing->v[0]->gloc);
2316 
2317  dot_l = dot_v3v3_db(Lv, testing->gn);
2318  dot_r = dot_v3v3_db(Rv, testing->gn);
2319 
2320  if (dot_l * dot_r > 0 || (!dot_l && !dot_r)) {
2321  return 0;
2322  }
2323 
2324  dot_l = fabs(dot_l);
2325  dot_r = fabs(dot_r);
2326 
2327  interp_v3_v3v3_db(gloc, l->gloc, r->gloc, dot_l / (dot_l + dot_r));
2328 
2329  /* Due to precision issue, we might end up with the same point as the one we already detected.
2330  */
2331  if (last && LRT_DOUBLE_CLOSE_ENOUGH(last->gloc[0], gloc[0]) &&
2332  LRT_DOUBLE_CLOSE_ENOUGH(last->gloc[1], gloc[1]) &&
2333  LRT_DOUBLE_CLOSE_ENOUGH(last->gloc[2], gloc[2])) {
2334  return NULL;
2335  }
2336 
2338  gloc, testing->v[0]->gloc, testing->v[1]->gloc, testing->v[2]->gloc))) {
2339  return NULL;
2340  }
2341 
2342  /* This is an intersection vert, the size is bigger than LineartVert,
2343  * allocated separately. */
2345 
2346  /* Indicate the data structure difference. */
2348 
2349  copy_v3_v3_db(result->gloc, gloc);
2350 
2352 
2353  return result;
2354 }
2355 
2360  LineartTriangle *rt,
2361  LineartTriangle *testing)
2362 {
2363  LineartVert *v1 = 0, *v2 = 0;
2364  LineartVert **next = &v1;
2366  LineartVert *E0T = 0;
2367  LineartVert *E1T = 0;
2368  LineartVert *E2T = 0;
2369  LineartVert *TE0 = 0;
2370  LineartVert *TE1 = 0;
2371  LineartVert *TE2 = 0;
2372  LineartVert *sv1, *sv2;
2373  double cl[3];
2374 
2375  double ZMin, ZMax;
2376  ZMax = rb->far_clip;
2377  ZMin = rb->near_clip;
2378  copy_v3_v3_db(cl, rb->camera_pos);
2379  LineartVert *share = lineart_triangle_share_point(testing, rt);
2380 
2381  if (share) {
2382  /* If triangles have sharing points like `abc` and `acd`, then we only need to detect `bc`
2383  * against `acd` or `cd` against `abc`. */
2384 
2385  LineartVert *new_share;
2386  lineart_triangle_get_other_verts(rt, share, &sv1, &sv2);
2387 
2388  v1 = new_share = lineart_mem_aquire(&rb->render_data_pool, (sizeof(LineartVertIntersection)));
2389 
2390  new_share->flag = LRT_VERT_HAS_INTERSECTION_DATA;
2391 
2392  copy_v3_v3_db(new_share->gloc, share->gloc);
2393 
2394  v2 = lineart_triangle_2v_intersection_test(rb, sv1, sv2, rt, testing, 0);
2395 
2396  if (v2 == NULL) {
2397  lineart_triangle_get_other_verts(testing, share, &sv1, &sv2);
2398  v2 = lineart_triangle_2v_intersection_test(rb, sv1, sv2, testing, rt, 0);
2399  if (v2 == NULL) {
2400  return 0;
2401  }
2402  lineart_prepend_pool(&testing->intersecting_verts, &rb->render_data_pool, new_share);
2403  }
2404  else {
2406  }
2407  }
2408  else {
2409  /* If not sharing any points, then we need to try all the possibilities. */
2410 
2411  E0T = lineart_triangle_2v_intersection_test(rb, rt->v[0], rt->v[1], rt, testing, 0);
2412  if (E0T && (!(*next))) {
2413  (*next) = E0T;
2414  lineart_vert_set_intersection_2v((*next), rt->v[0], rt->v[1]);
2415  next = &v2;
2416  }
2417  E1T = lineart_triangle_2v_intersection_test(rb, rt->v[1], rt->v[2], rt, testing, v1);
2418  if (E1T && (!(*next))) {
2419  (*next) = E1T;
2420  lineart_vert_set_intersection_2v((*next), rt->v[1], rt->v[2]);
2421  next = &v2;
2422  }
2423  if (!(*next)) {
2424  E2T = lineart_triangle_2v_intersection_test(rb, rt->v[2], rt->v[0], rt, testing, v1);
2425  }
2426  if (E2T && (!(*next))) {
2427  (*next) = E2T;
2428  lineart_vert_set_intersection_2v((*next), rt->v[2], rt->v[0]);
2429  next = &v2;
2430  }
2431 
2432  if (!(*next)) {
2434  rb, testing->v[0], testing->v[1], testing, rt, v1);
2435  }
2436  if (TE0 && (!(*next))) {
2437  (*next) = TE0;
2438  lineart_vert_set_intersection_2v((*next), testing->v[0], testing->v[1]);
2439  next = &v2;
2440  }
2441  if (!(*next)) {
2443  rb, testing->v[1], testing->v[2], testing, rt, v1);
2444  }
2445  if (TE1 && (!(*next))) {
2446  (*next) = TE1;
2447  lineart_vert_set_intersection_2v((*next), testing->v[1], testing->v[2]);
2448  next = &v2;
2449  }
2450  if (!(*next)) {
2452  rb, testing->v[2], testing->v[0], testing, rt, v1);
2453  }
2454  if (TE2 && (!(*next))) {
2455  (*next) = TE2;
2456  lineart_vert_set_intersection_2v((*next), testing->v[2], testing->v[0]);
2457  next = &v2;
2458  }
2459 
2460  if (!(*next)) {
2461  return 0;
2462  }
2463  }
2464 
2465  /* The intersection line has been generated only in geometry space, so we need to transform
2466  * them as well. */
2467  mul_v4_m4v3_db(v1->fbcoord, rb->view_projection, v1->gloc);
2468  mul_v4_m4v3_db(v2->fbcoord, rb->view_projection, v2->gloc);
2469  mul_v3db_db(v1->fbcoord, (1 / v1->fbcoord[3]));
2470  mul_v3db_db(v2->fbcoord, (1 / v2->fbcoord[3]));
2471 
2472  v1->fbcoord[0] -= rb->shift_x * 2;
2473  v1->fbcoord[1] -= rb->shift_y * 2;
2474  v2->fbcoord[0] -= rb->shift_x * 2;
2475  v2->fbcoord[1] -= rb->shift_y * 2;
2476 
2477  /* This z transformation is not the same as the rest of the part, because the data don't go
2478  * through normal perspective division calls in the pipeline, but this way the 3D result and
2479  * occlusion on the generated line is correct, and we don't really use 2D for viewport stroke
2480  * generation anyway. */
2481  v1->fbcoord[2] = ZMin * ZMax / (ZMax - fabs(v1->fbcoord[2]) * (ZMax - ZMin));
2482  v2->fbcoord[2] = ZMin * ZMax / (ZMax - fabs(v2->fbcoord[2]) * (ZMax - ZMin));
2483 
2484  ((LineartVertIntersection *)v1)->intersecting_with = rt;
2485  ((LineartVertIntersection *)v2)->intersecting_with = testing;
2486 
2488  result->v1 = v1;
2489  result->v2 = v2;
2490  result->t1 = rt;
2491  result->t2 = testing;
2492 
2494  BLI_addtail(&result->segments, rls);
2495  /* Don't need to OR flags right now, just a type mark. */
2498  int r1, r2, c1, c2, row, col;
2499  if (lineart_get_edge_bounding_areas(rb, result, &r1, &r2, &c1, &c2)) {
2500  for (row = r1; row != r2 + 1; row++) {
2501  for (col = c1; col != c2 + 1; col++) {
2503  rb, &rb->initial_bounding_areas[row * LRT_BA_ROWS + col], result);
2504  }
2505  }
2506  }
2507 
2508  rb->intersection_count++;
2509 
2510  return result;
2511 }
2512 
2514  LineartTriangle *rt,
2515  LineartBoundingArea *ba)
2516 {
2517  /* Testing_triangle->testing[0] is used to store pairing triangle reference.
2518  * See definition of LineartTriangleThread for more info. */
2519  LineartTriangle *testing_triangle;
2520  LineartTriangleThread *rtt;
2521  LinkData *lip, *next_lip;
2522 
2523  double *G0 = rt->v[0]->gloc, *G1 = rt->v[1]->gloc, *G2 = rt->v[2]->gloc;
2524 
2525  /* If this is not the smallest subdiv bounding area.*/
2526  if (ba->child) {
2531  return;
2532  }
2533 
2534  /* If this _is_ the smallest subdiv bounding area, then do the intersections there. */
2535  for (lip = ba->linked_triangles.first; lip; lip = next_lip) {
2536  next_lip = lip->next;
2537  testing_triangle = lip->data;
2538  rtt = (LineartTriangleThread *)testing_triangle;
2539 
2540  if (testing_triangle == rt || rtt->testing_e[0] == (LineartEdge *)rt) {
2541  continue;
2542  }
2543  rtt->testing_e[0] = (LineartEdge *)rt;
2544 
2545  if ((testing_triangle->flags & LRT_TRIANGLE_NO_INTERSECTION) ||
2546  ((testing_triangle->flags & LRT_TRIANGLE_INTERSECTION_ONLY) &&
2548  continue;
2549  }
2550 
2551  double *RG0 = testing_triangle->v[0]->gloc, *RG1 = testing_triangle->v[1]->gloc,
2552  *RG2 = testing_triangle->v[2]->gloc;
2553 
2554  /* Bounding box not overlapping or triangles share edges, not potential of intersecting. */
2555  if ((MIN3(G0[2], G1[2], G2[2]) > MAX3(RG0[2], RG1[2], RG2[2])) ||
2556  (MAX3(G0[2], G1[2], G2[2]) < MIN3(RG0[2], RG1[2], RG2[2])) ||
2557  (MIN3(G0[0], G1[0], G2[0]) > MAX3(RG0[0], RG1[0], RG2[0])) ||
2558  (MAX3(G0[0], G1[0], G2[0]) < MIN3(RG0[0], RG1[0], RG2[0])) ||
2559  (MIN3(G0[1], G1[1], G2[1]) > MAX3(RG0[1], RG1[1], RG2[1])) ||
2560  (MAX3(G0[1], G1[1], G2[1]) < MIN3(RG0[1], RG1[1], RG2[1])) ||
2561  lineart_triangle_share_edge(rt, testing_triangle)) {
2562  continue;
2563  }
2564 
2565  /* If we do need to compute intersection, then finally do it. */
2566  lineart_triangle_intersect(rb, rt, testing_triangle);
2567  }
2568 }
2569 
2574 {
2575  float direction[3] = {0, 0, 1};
2576  float trans[3];
2577  float inv[4][4];
2578  float obmat_no_scale[4][4];
2579 
2580  copy_m4_m4(obmat_no_scale, rb->cam_obmat);
2581 
2582  normalize_v3(obmat_no_scale[0]);
2583  normalize_v3(obmat_no_scale[1]);
2584  normalize_v3(obmat_no_scale[2]);
2585  invert_m4_m4(inv, obmat_no_scale);
2586  transpose_m4(inv);
2587  mul_v3_mat3_m4v3(trans, inv, direction);
2588  copy_m4_m4(rb->cam_obmat, obmat_no_scale);
2589  copy_v3db_v3fl(rb->view_vector, trans);
2590 }
2591 
2593 {
2594  if (rb == NULL) {
2595  return;
2596  }
2597 
2598  rb->contour_count = 0;
2599  rb->contour_managed = NULL;
2600  rb->intersection_count = 0;
2601  rb->intersection_managed = NULL;
2602  rb->material_line_count = 0;
2603  rb->material_managed = NULL;
2604  rb->crease_count = 0;
2605  rb->crease_managed = NULL;
2606  rb->edge_mark_count = 0;
2607  rb->edge_mark_managed = NULL;
2608 
2609  rb->contours = NULL;
2610  rb->intersection_lines = NULL;
2611  rb->crease_lines = NULL;
2612  rb->material_lines = NULL;
2613  rb->edge_marks = NULL;
2614 
2615  BLI_listbase_clear(&rb->chains);
2617 
2621 
2622  BLI_spin_end(&rb->lock_task);
2623  BLI_spin_end(&rb->lock_cuts);
2625 
2627 }
2628 
2630 {
2632 
2634 
2635  if (rb) {
2636  MEM_freeN(rb);
2637  lmd->render_buffer = NULL;
2638  }
2639 
2640  if (G.debug_value == 4000) {
2641  printf("LRT: Destroyed render data.\n");
2642  }
2643 }
2644 
2647 {
2648  LineartRenderBuffer *rb = MEM_callocN(sizeof(LineartRenderBuffer), "Line Art render buffer");
2649 
2650  lmd->render_buffer = rb;
2651 
2652  if (!scene || !scene->camera) {
2653  return NULL;
2654  }
2655  Camera *c = scene->camera->data;
2656  double clipping_offset = 0;
2657 
2659  /* This way the clipped lines are "stably visible" by prevents depth buffer artifacts. */
2660  clipping_offset = 0.0001;
2661  }
2662 
2665  rb->cam_is_persp = (c->type == CAM_PERSP);
2666  rb->near_clip = c->clip_start + clipping_offset;
2667  rb->far_clip = c->clip_end - clipping_offset;
2668  rb->w = scene->r.xsch;
2669  rb->h = scene->r.ysch;
2670 
2671  double asp = ((double)rb->w / (double)rb->h);
2672  int fit = BKE_camera_sensor_fit(c->sensor_fit, rb->w, rb->h);
2673  rb->shift_x = fit == CAMERA_SENSOR_FIT_HOR ? c->shiftx : c->shiftx / asp;
2674  rb->shift_y = fit == CAMERA_SENSOR_FIT_VERT ? c->shifty : c->shifty * asp;
2675 
2676  rb->crease_threshold = cos(M_PI - lmd->crease_threshold);
2679 
2684 
2685  /* See lineart_edge_from_triangle() for how this option may impact performance. */
2687 
2688  rb->use_contour = (lmd->edge_types & LRT_EDGE_FLAG_CONTOUR) != 0;
2689  rb->use_crease = (lmd->edge_types & LRT_EDGE_FLAG_CREASE) != 0;
2690  rb->use_material = (lmd->edge_types & LRT_EDGE_FLAG_MATERIAL) != 0;
2693 
2694  BLI_spin_init(&rb->lock_task);
2695  BLI_spin_init(&rb->lock_cuts);
2697 
2698  return rb;
2699 }
2700 
2702 {
2703  if (rb->thread_count == 0) {
2705  }
2706  return sizeof(LineartTriangle) + (sizeof(LineartEdge *) * (rb->thread_count));
2707 }
2708 
2710 {
2711  /* Initial tile split is defined as 4 (subdivided as 4*4), increasing the value allows the
2712  * algorithm to build the acceleration structure for bigger scenes a little faster but not as
2713  * efficient at handling medium to small scenes. */
2714  int sp_w = LRT_BA_ROWS;
2715  int sp_h = LRT_BA_ROWS;
2716  int row, col;
2717  LineartBoundingArea *ba;
2718 
2719  /* Because NDC (Normalized Device Coordinates) range is (-1,1),
2720  * so the span for each initial tile is double of that in the (0,1) range. */
2721  double span_w = (double)1 / sp_w * 2.0;
2722  double span_h = (double)1 / sp_h * 2.0;
2723 
2724  rb->tile_count_x = sp_w;
2725  rb->tile_count_y = sp_h;
2726  rb->width_per_tile = span_w;
2727  rb->height_per_tile = span_h;
2728 
2729  rb->bounding_area_count = sp_w * sp_h;
2732 
2733  /* Initialize tiles. */
2734  for (row = 0; row < sp_h; row++) {
2735  for (col = 0; col < sp_w; col++) {
2736  ba = &rb->initial_bounding_areas[row * LRT_BA_ROWS + col];
2737 
2738  /* Set the four direction limits. */
2739  ba->l = span_w * col - 1.0;
2740  ba->r = (col == sp_w - 1) ? 1.0 : (span_w * (col + 1) - 1.0);
2741  ba->u = 1.0 - span_h * row;
2742  ba->b = (row == sp_h - 1) ? -1.0 : (1.0 - span_h * (row + 1));
2743 
2744  ba->cx = (ba->l + ba->r) / 2;
2745  ba->cy = (ba->u + ba->b) / 2;
2746 
2747  /* Link adjacent ones. */
2748  if (row) {
2750  &ba->up,
2751  &rb->render_data_pool,
2752  &rb->initial_bounding_areas[(row - 1) * LRT_BA_ROWS + col]);
2753  }
2754  if (col) {
2756  &rb->render_data_pool,
2757  &rb->initial_bounding_areas[row * LRT_BA_ROWS + col - 1]);
2758  }
2759  if (row != sp_h - 1) {
2761  &ba->bp,
2762  &rb->render_data_pool,
2763  &rb->initial_bounding_areas[(row + 1) * LRT_BA_ROWS + col]);
2764  }
2765  if (col != sp_w - 1) {
2767  &rb->render_data_pool,
2768  &rb->initial_bounding_areas[row * LRT_BA_ROWS + col + 1]);
2769  }
2770  }
2771  }
2772 }
2773 
2778 {
2779  LineartBoundingArea *ba = root->child, *tba;
2780  LinkData *lip2, *next_lip;
2782 
2783  /* Inter-connection with newly created 4 child bounding areas. */
2784  lineart_list_append_pointer_pool(&ba[1].rp, mph, &ba[0]);
2785  lineart_list_append_pointer_pool(&ba[0].lp, mph, &ba[1]);
2786  lineart_list_append_pointer_pool(&ba[1].bp, mph, &ba[2]);
2787  lineart_list_append_pointer_pool(&ba[2].up, mph, &ba[1]);
2788  lineart_list_append_pointer_pool(&ba[2].rp, mph, &ba[3]);
2789  lineart_list_append_pointer_pool(&ba[3].lp, mph, &ba[2]);
2790  lineart_list_append_pointer_pool(&ba[3].up, mph, &ba[0]);
2791  lineart_list_append_pointer_pool(&ba[0].bp, mph, &ba[3]);
2792 
2793  /* Connect 4 child bounding areas to other areas that are
2794  * adjacent to their original parents. */
2795  LISTBASE_FOREACH (LinkData *, lip, &root->lp) {
2796 
2797  /* For example, we are dealing with parent's left side
2798  * "tba" represents each adjacent neighbor of the parent. */
2799  tba = lip->data;
2800 
2801  /* if this neighbor is adjacent to
2802  * the two new areas on the left side of the parent,
2803  * then add them to the adjacent list as well. */
2804  if (ba[1].u > tba->b && ba[1].b < tba->u) {
2805  lineart_list_append_pointer_pool(&ba[1].lp, mph, tba);
2806  lineart_list_append_pointer_pool(&tba->rp, mph, &ba[1]);
2807  }
2808  if (ba[2].u > tba->b && ba[2].b < tba->u) {
2809  lineart_list_append_pointer_pool(&ba[2].lp, mph, tba);
2810  lineart_list_append_pointer_pool(&tba->rp, mph, &ba[2]);
2811  }
2812  }
2813  LISTBASE_FOREACH (LinkData *, lip, &root->rp) {
2814  tba = lip->data;
2815  if (ba[0].u > tba->b && ba[0].b < tba->u) {
2816  lineart_list_append_pointer_pool(&ba[0].rp, mph, tba);
2817  lineart_list_append_pointer_pool(&tba->lp, mph, &ba[0]);
2818  }
2819  if (ba[3].u > tba->b && ba[3].b < tba->u) {
2820  lineart_list_append_pointer_pool(&ba[3].rp, mph, tba);
2821  lineart_list_append_pointer_pool(&tba->lp, mph, &ba[3]);
2822  }
2823  }
2824  LISTBASE_FOREACH (LinkData *, lip, &root->up) {
2825  tba = lip->data;
2826  if (ba[0].r > tba->l && ba[0].l < tba->r) {
2827  lineart_list_append_pointer_pool(&ba[0].up, mph, tba);
2828  lineart_list_append_pointer_pool(&tba->bp, mph, &ba[0]);
2829  }
2830  if (ba[1].r > tba->l && ba[1].l < tba->r) {
2831  lineart_list_append_pointer_pool(&ba[1].up, mph, tba);
2832  lineart_list_append_pointer_pool(&tba->bp, mph, &ba[1]);
2833  }
2834  }
2835  LISTBASE_FOREACH (LinkData *, lip, &root->bp) {
2836  tba = lip->data;
2837  if (ba[2].r > tba->l && ba[2].l < tba->r) {
2838  lineart_list_append_pointer_pool(&ba[2].bp, mph, tba);
2839  lineart_list_append_pointer_pool(&tba->up, mph, &ba[2]);
2840  }
2841  if (ba[3].r > tba->l && ba[3].l < tba->r) {
2842  lineart_list_append_pointer_pool(&ba[3].bp, mph, tba);
2843  lineart_list_append_pointer_pool(&tba->up, mph, &ba[3]);
2844  }
2845  }
2846 
2847  /* Then remove the parent bounding areas from
2848  * their original adjacent areas. */
2849  LISTBASE_FOREACH (LinkData *, lip, &root->lp) {
2850  for (lip2 = ((LineartBoundingArea *)lip->data)->rp.first; lip2; lip2 = next_lip) {
2851  next_lip = lip2->next;
2852  tba = lip2->data;
2853  if (tba == root) {
2855  if (ba[1].u > tba->b && ba[1].b < tba->u) {
2856  lineart_list_append_pointer_pool(&tba->rp, mph, &ba[1]);
2857  }
2858  if (ba[2].u > tba->b && ba[2].b < tba->u) {
2859  lineart_list_append_pointer_pool(&tba->rp, mph, &ba[2]);
2860  }
2861  }
2862  }
2863  }
2864  LISTBASE_FOREACH (LinkData *, lip, &root->rp) {
2865  for (lip2 = ((LineartBoundingArea *)lip->data)->lp.first; lip2; lip2 = next_lip) {
2866  next_lip = lip2->next;
2867  tba = lip2->data;
2868  if (tba == root) {
2870  if (ba[0].u > tba->b && ba[0].b < tba->u) {
2871  lineart_list_append_pointer_pool(&tba->lp, mph, &ba[0]);
2872  }
2873  if (ba[3].u > tba->b && ba[3].b < tba->u) {
2874  lineart_list_append_pointer_pool(&tba->lp, mph, &ba[3]);
2875  }
2876  }
2877  }
2878  }
2879  LISTBASE_FOREACH (LinkData *, lip, &root->up) {
2880  for (lip2 = ((LineartBoundingArea *)lip->data)->bp.first; lip2; lip2 = next_lip) {
2881  next_lip = lip2->next;
2882  tba = lip2->data;
2883  if (tba == root) {
2885  if (ba[0].r > tba->l && ba[0].l < tba->r) {
2886  lineart_list_append_pointer_pool(&tba->up, mph, &ba[0]);
2887  }
2888  if (ba[1].r > tba->l && ba[1].l < tba->r) {
2889  lineart_list_append_pointer_pool(&tba->up, mph, &ba[1]);
2890  }
2891  }
2892  }
2893  }
2894  LISTBASE_FOREACH (LinkData *, lip, &root->bp) {
2895  for (lip2 = ((LineartBoundingArea *)lip->data)->up.first; lip2; lip2 = next_lip) {
2896  next_lip = lip2->next;
2897  tba = lip2->data;
2898  if (tba == root) {
2900  if (ba[2].r > tba->l && ba[2].l < tba->r) {
2901  lineart_list_append_pointer_pool(&tba->bp, mph, &ba[2]);
2902  }
2903  if (ba[3].r > tba->l && ba[3].l < tba->r) {
2904  lineart_list_append_pointer_pool(&tba->bp, mph, &ba[3]);
2905  }
2906  }
2907  }
2908  }
2909 
2910  /* Finally clear parent's adjacent list. */
2911  BLI_listbase_clear(&root->lp);
2912  BLI_listbase_clear(&root->rp);
2913  BLI_listbase_clear(&root->up);
2914  BLI_listbase_clear(&root->bp);
2915 }
2916 
2921  LineartBoundingArea *root,
2922  int recursive_level)
2923 {
2925  sizeof(LineartBoundingArea) * 4);
2926  LineartTriangle *rt;
2927  LineartEdge *e;
2928 
2929  ba[0].l = root->cx;
2930  ba[0].r = root->r;
2931  ba[0].u = root->u;
2932  ba[0].b = root->cy;
2933  ba[0].cx = (ba[0].l + ba[0].r) / 2;
2934  ba[0].cy = (ba[0].u + ba[0].b) / 2;
2935 
2936  ba[1].l = root->l;
2937  ba[1].r = root->cx;
2938  ba[1].u = root->u;
2939  ba[1].b = root->cy;
2940  ba[1].cx = (ba[1].l + ba[1].r) / 2;
2941  ba[1].cy = (ba[1].u + ba[1].b) / 2;
2942 
2943  ba[2].l = root->l;
2944  ba[2].r = root->cx;
2945  ba[2].u = root->cy;
2946  ba[2].b = root->b;
2947  ba[2].cx = (ba[2].l + ba[2].r) / 2;
2948  ba[2].cy = (ba[2].u + ba[2].b) / 2;
2949 
2950  ba[3].l = root->cx;
2951  ba[3].r = root->r;
2952  ba[3].u = root->cy;
2953  ba[3].b = root->b;
2954  ba[3].cx = (ba[3].l + ba[3].r) / 2;
2955  ba[3].cy = (ba[3].u + ba[3].b) / 2;
2956 
2957  root->child = ba;
2958 
2960 
2961  while ((rt = lineart_list_pop_pointer_no_free(&root->linked_triangles)) != NULL) {
2962  LineartBoundingArea *cba = root->child;
2963  double b[4];
2964  b[0] = MIN3(rt->v[0]->fbcoord[0], rt->v[1]->fbcoord[0], rt->v[2]->fbcoord[0]);
2965  b[1] = MAX3(rt->v[0]->fbcoord[0], rt->v[1]->fbcoord[0], rt->v[2]->fbcoord[0]);
2966  b[2] = MAX3(rt->v[0]->fbcoord[1], rt->v[1]->fbcoord[1], rt->v[2]->fbcoord[1]);
2967  b[3] = MIN3(rt->v[0]->fbcoord[1], rt->v[1]->fbcoord[1], rt->v[2]->fbcoord[1]);
2968  if (LRT_BOUND_AREA_CROSSES(b, &cba[0].l)) {
2969  lineart_bounding_area_link_triangle(rb, &cba[0], rt, b, 0, recursive_level + 1, false);
2970  }
2971  if (LRT_BOUND_AREA_CROSSES(b, &cba[1].l)) {
2972  lineart_bounding_area_link_triangle(rb, &cba[1], rt, b, 0, recursive_level + 1, false);
2973  }
2974  if (LRT_BOUND_AREA_CROSSES(b, &cba[2].l)) {
2975  lineart_bounding_area_link_triangle(rb, &cba[2], rt, b, 0, recursive_level + 1, false);
2976  }
2977  if (LRT_BOUND_AREA_CROSSES(b, &cba[3].l)) {
2978  lineart_bounding_area_link_triangle(rb, &cba[3], rt, b, 0, recursive_level + 1, false);
2979  }
2980  }
2981 
2982  while ((e = lineart_list_pop_pointer_no_free(&root->linked_lines)) != NULL) {
2984  }
2985 
2986  rb->bounding_area_count += 3;
2987 }
2988 
2990  const double l[2],
2991  const double r[2],
2992  LineartBoundingArea *ba)
2993 {
2994  double vx, vy;
2995  double converted[4];
2996  double c1, c;
2997 
2998  if (((converted[0] = (double)ba->l) > MAX2(l[0], r[0])) ||
2999  ((converted[1] = (double)ba->r) < MIN2(l[0], r[0])) ||
3000  ((converted[2] = (double)ba->b) > MAX2(l[1], r[1])) ||
3001  ((converted[3] = (double)ba->u) < MIN2(l[1], r[1]))) {
3002  return false;
3003  }
3004 
3005  vx = l[0] - r[0];
3006  vy = l[1] - r[1];
3007 
3008  c1 = vx * (converted[2] - l[1]) - vy * (converted[0] - l[0]);
3009  c = c1;
3010 
3011  c1 = vx * (converted[2] - l[1]) - vy * (converted[1] - l[0]);
3012  if (c1 * c <= 0) {
3013  return true;
3014  }
3015  c = c1;
3016 
3017  c1 = vx * (converted[3] - l[1]) - vy * (converted[0] - l[0]);
3018  if (c1 * c <= 0) {
3019  return true;
3020  }
3021  c = c1;
3022 
3023  c1 = vx * (converted[3] - l[1]) - vy * (converted[1] - l[0]);
3024  if (c1 * c <= 0) {
3025  return true;
3026  }
3027  c = c1;
3028 
3029  return false;
3030 }
3031 
3033  LineartTriangle *rt,
3034  LineartBoundingArea *ba)
3035 {
3036  double p1[2], p2[2], p3[2], p4[2];
3037  double *FBC1 = rt->v[0]->fbcoord, *FBC2 = rt->v[1]->fbcoord, *FBC3 = rt->v[2]->fbcoord;
3038 
3039  p3[0] = p1[0] = (double)ba->l;
3040  p2[1] = p1[1] = (double)ba->b;
3041  p2[0] = p4[0] = (double)ba->r;
3042  p3[1] = p4[1] = (double)ba->u;
3043 
3044  if ((FBC1[0] >= p1[0] && FBC1[0] <= p2[0] && FBC1[1] >= p1[1] && FBC1[1] <= p3[1]) ||
3045  (FBC2[0] >= p1[0] && FBC2[0] <= p2[0] && FBC2[1] >= p1[1] && FBC2[1] <= p3[1]) ||
3046  (FBC3[0] >= p1[0] && FBC3[0] <= p2[0] && FBC3[1] >= p1[1] && FBC3[1] <= p3[1])) {
3047  return true;
3048  }
3049 
3050  if (lineart_point_inside_triangle(p1, FBC1, FBC2, FBC3) ||
3051  lineart_point_inside_triangle(p2, FBC1, FBC2, FBC3) ||
3052  lineart_point_inside_triangle(p3, FBC1, FBC2, FBC3) ||
3053  lineart_point_inside_triangle(p4, FBC1, FBC2, FBC3)) {
3054  return true;
3055  }
3056 
3057  if ((lineart_bounding_area_line_intersect(fb, FBC1, FBC2, ba)) ||
3058  (lineart_bounding_area_line_intersect(fb, FBC2, FBC3, ba)) ||
3059  (lineart_bounding_area_line_intersect(fb, FBC3, FBC1, ba))) {
3060  return true;
3061  }
3062 
3063  return false;
3064 }
3065 
3071  LineartBoundingArea *root_ba,
3072  LineartTriangle *rt,
3073  double *LRUB,
3074  int recursive,
3075  int recursive_level,
3076  bool do_intersection)
3077 {
3078  if (!lineart_bounding_area_triangle_intersect(rb, rt, root_ba)) {
3079  return;
3080  }
3081  if (root_ba->child == NULL) {
3083  root_ba->triangle_count++;
3084  /* If splitting doesn't improve triangle separation, then shouldn't allow splitting anymore.
3085  * Here we use recursive limit. This is especially useful in orthographic render,
3086  * where a lot of faces could easily line up perfectly in image space,
3087  * which can not be separated by simply slicing the image tile. */
3088  if (root_ba->triangle_count > 200 && recursive && recursive_level < 10) {
3089  lineart_bounding_area_split(rb, root_ba, recursive_level);
3090  }
3091  if (recursive && do_intersection && rb->use_intersections) {
3093  }
3094  }
3095  else {
3096  LineartBoundingArea *ba = root_ba->child;
3097  double *B1 = LRUB;
3098  double b[4];
3099  if (!LRUB) {
3100  b[0] = MIN3(rt->v[0]->fbcoord[0], rt->v[1]->fbcoord[0], rt->v[2]->fbcoord[0]);
3101  b[1] = MAX3(rt->v[0]->fbcoord[0], rt->v[1]->fbcoord[0], rt->v[2]->fbcoord[0]);
3102  b[2] = MAX3(rt->v[0]->fbcoord[1], rt->v[1]->fbcoord[1], rt->v[2]->fbcoord[1]);
3103  b[3] = MIN3(rt->v[0]->fbcoord[1], rt->v[1]->fbcoord[1], rt->v[2]->fbcoord[1]);
3104  B1 = b;
3105  }
3106  if (LRT_BOUND_AREA_CROSSES(B1, &ba[0].l)) {
3108  rb, &ba[0], rt, B1, recursive, recursive_level + 1, do_intersection);
3109  }
3110  if (LRT_BOUND_AREA_CROSSES(B1, &ba[1].l)) {
3112  rb, &ba[1], rt, B1, recursive, recursive_level + 1, do_intersection);
3113  }
3114  if (LRT_BOUND_AREA_CROSSES(B1, &ba[2].l)) {
3116  rb, &ba[2], rt, B1, recursive, recursive_level + 1, do_intersection);
3117  }
3118  if (LRT_BOUND_AREA_CROSSES(B1, &ba[3].l)) {
3120  rb, &ba[3], rt, B1, recursive, recursive_level + 1, do_intersection);
3121  }
3122  }
3123 }
3124 
3126  LineartBoundingArea *root_ba,
3127  LineartEdge *e)
3128 {
3129  if (root_ba->child == NULL) {
3131  }
3132  else {
3134  rb, e->v1->fbcoord, e->v2->fbcoord, &root_ba->child[0])) {
3135  lineart_bounding_area_link_line(rb, &root_ba->child[0], e);
3136  }
3138  rb, e->v1->fbcoord, e->v2->fbcoord, &root_ba->child[1])) {
3139  lineart_bounding_area_link_line(rb, &root_ba->child[1], e);
3140  }
3142  rb, e->v1->fbcoord, e->v2->fbcoord, &root_ba->child[2])) {
3143  lineart_bounding_area_link_line(rb, &root_ba->child[2], e);
3144  }
3146  rb, e->v1->fbcoord, e->v2->fbcoord, &root_ba->child[3])) {
3147  lineart_bounding_area_link_line(rb, &root_ba->child[3], e);
3148  }
3149  }
3150 }
3151 
3156 {
3158  {
3159  int r1, r2, c1, c2, row, col;
3160  if (lineart_get_edge_bounding_areas(rb, e, &r1, &r2, &c1, &c2)) {
3161  for (row = r1; row != r2 + 1; row++) {
3162  for (col = c1; col != c2 + 1; col++) {
3164  rb, &rb->initial_bounding_areas[row * LRT_BA_ROWS + col], e);
3165  }
3166  }
3167  }
3168  }
3170 }
3171 
3173  LineartTriangle *rt,
3174  int *rowbegin,
3175  int *rowend,
3176  int *colbegin,
3177  int *colend)
3178 {
3179  double sp_w = rb->width_per_tile, sp_h = rb->height_per_tile;
3180  double b[4];
3181 
3182  if (!rt->v[0] || !rt->v[1] || !rt->v[2]) {
3183  return false;
3184  }
3185 
3186  b[0] = MIN3(rt->v[0]->fbcoord[0], rt->v[1]->fbcoord[0], rt->v[2]->fbcoord[0]);
3187  b[1] = MAX3(rt->v[0]->fbcoord[0], rt->v[1]->fbcoord[0], rt->v[2]->fbcoord[0]);
3188  b[2] = MIN3(rt->v[0]->fbcoord[1], rt->v[1]->fbcoord[1], rt->v[2]->fbcoord[1]);
3189  b[3] = MAX3(rt->v[0]->fbcoord[1], rt->v[1]->fbcoord[1], rt->v[2]->fbcoord[1]);
3190 
3191  if (b[0] > 1 || b[1] < -1 || b[2] > 1 || b[3] < -1) {
3192  return false;
3193  }
3194 
3195  (*colbegin) = (int)((b[0] + 1.0) / sp_w);
3196  (*colend) = (int)((b[1] + 1.0) / sp_w);
3197  (*rowend) = rb->tile_count_y - (int)((b[2] + 1.0) / sp_h) - 1;
3198  (*rowbegin) = rb->tile_count_y - (int)((b[3] + 1.0) / sp_h) - 1;
3199 
3200  if ((*colend) >= rb->tile_count_x) {
3201  (*colend) = rb->tile_count_x - 1;
3202  }
3203  if ((*rowend) >= rb->tile_count_y) {
3204  (*rowend) = rb->tile_count_y - 1;
3205  }
3206  if ((*colbegin) < 0) {
3207  (*colbegin) = 0;
3208  }
3209  if ((*rowbegin) < 0) {
3210  (*rowbegin) = 0;
3211  }
3212 
3213  return true;
3214 }
3215 
3217  LineartEdge *e,
3218  int *rowbegin,
3219  int *rowend,
3220  int *colbegin,
3221  int *colend)
3222 {
3223  double sp_w = rb->width_per_tile, sp_h = rb->height_per_tile;
3224  double b[4];
3225 
3226  if (!e->v1 || !e->v2) {
3227  return false;
3228  }
3229 
3230  if (e->v1->fbcoord[0] != e->v1->fbcoord[0] || e->v2->fbcoord[0] != e->v2->fbcoord[0]) {
3231  return false;
3232  }
3233 
3234  b[0] = MIN2(e->v1->fbcoord[0], e->v2->fbcoord[0]);
3235  b[1] = MAX2(e->v1->fbcoord[0], e->v2->fbcoord[0]);
3236  b[2] = MIN2(e->v1->fbcoord[1], e->v2->fbcoord[1]);
3237  b[3] = MAX2(e->v1->fbcoord[1], e->v2->fbcoord[1]);
3238 
3239  if (b[0] > 1 || b[1] < -1 || b[2] > 1 || b[3] < -1) {
3240  return false;
3241  }
3242 
3243  (*colbegin) = (int)((b[0] + 1.0) / sp_w);
3244  (*colend) = (int)((b[1] + 1.0) / sp_w);
3245  (*rowend) = rb->tile_count_y - (int)((b[2] + 1.0) / sp_h) - 1;
3246  (*rowbegin) = rb->tile_count_y - (int)((b[3] + 1.0) / sp_h) - 1;
3247 
3248  /* It's possible that the line stretches too much out to the side, resulting negative value. */
3249  if ((*rowend) < (*rowbegin)) {
3250  (*rowend) = rb->tile_count_y - 1;
3251  }
3252 
3253  if ((*colend) < (*colbegin)) {
3254  (*colend) = rb->tile_count_x - 1;
3255  }
3256 
3257  CLAMP((*colbegin), 0, rb->tile_count_x - 1);
3258  CLAMP((*rowbegin), 0, rb->tile_count_y - 1);
3259  CLAMP((*colend), 0, rb->tile_count_x - 1);
3260  CLAMP((*rowend), 0, rb->tile_count_y - 1);
3261 
3262  return true;
3263 }
3264 
3269  double x,
3270  double y)
3271 {
3272  double sp_w = rb->width_per_tile, sp_h = rb->height_per_tile;
3273  int col, row;
3274 
3275  if (x > 1 || x < -1 || y > 1 || y < -1) {
3276  return 0;
3277  }
3278 
3279  col = (int)((x + 1.0) / sp_w);
3280  row = rb->tile_count_y - (int)((y + 1.0) / sp_h) - 1;
3281 
3282  if (col >= rb->tile_count_x) {
3283  col = rb->tile_count_x - 1;
3284  }
3285  if (row >= rb->tile_count_y) {
3286  row = rb->tile_count_y - 1;
3287  }
3288  if (col < 0) {
3289  col = 0;
3290  }
3291  if (row < 0) {
3292  row = 0;
3293  }
3294 
3295  return &rb->initial_bounding_areas[row * LRT_BA_ROWS + col];
3296 }
3297 
3299 {
3300  LineartBoundingArea *iba;
3301  double sp_w = rb->width_per_tile, sp_h = rb->height_per_tile;
3302  int c = (int)((x + 1.0) / sp_w);
3303  int r = rb->tile_count_y - (int)((y + 1.0) / sp_h) - 1;
3304  if (r < 0) {
3305  r = 0;
3306  }
3307  if (c < 0) {
3308  c = 0;
3309  }
3310  if (r >= rb->tile_count_y) {
3311  r = rb->tile_count_y - 1;
3312  }
3313  if (c >= rb->tile_count_x) {
3314  c = rb->tile_count_x - 1;
3315  }
3316 
3317  iba = &rb->initial_bounding_areas[r * LRT_BA_ROWS + c];
3318  while (iba->child) {
3319  if (x > iba->cx) {
3320  if (y > iba->cy) {
3321  iba = &iba->child[0];
3322  }
3323  else {
3324  iba = &iba->child[3];
3325  }
3326  }
3327  else {
3328  if (y > iba->cy) {
3329  iba = &iba->child[1];
3330  }
3331  else {
3332  iba = &iba->child[2];
3333  }
3334  }
3335  }
3336  return iba;
3337 }
3338 
3343 {
3344  LineartBoundingArea *ba;
3345  if ((ba = MOD_lineart_get_parent_bounding_area(rb, x, y)) != NULL) {
3346  return lineart_get_bounding_area(rb, x, y);
3347  }
3348  return NULL;
3349 }
3350 
3355 {
3356  LineartTriangle *rt;
3357  int i, lim;
3358  int x1, x2, y1, y2;
3359  int r, co;
3360 
3362  rt = reln->pointer;
3363  lim = reln->element_count;
3364  for (i = 0; i < lim; i++) {
3365  if ((rt->flags & LRT_CULL_USED) || (rt->flags & LRT_CULL_DISCARD)) {
3366  rt = (void *)(((uchar *)rt) + rb->triangle_size);
3367  continue;
3368  }
3369  if (lineart_get_triangle_bounding_areas(rb, rt, &y1, &y2, &x1, &x2)) {
3370  for (co = x1; co <= x2; co++) {
3371  for (r = y1; r <= y2; r++) {
3373  &rb->initial_bounding_areas[r * LRT_BA_ROWS + co],
3374  rt,
3375  0,
3376  1,
3377  0,
3378  (!(rt->flags & LRT_TRIANGLE_NO_INTERSECTION)));
3379  }
3380  }
3381  } /* Else throw away. */
3382  rt = (void *)(((uchar *)rt) + rb->triangle_size);
3383  }
3384  }
3385 }
3386 
3392  LineartEdge *e)
3393 {
3394  double data[2] = {e->v1->fbcoord[0], e->v1->fbcoord[1]};
3395  double LU[2] = {-1, 1}, RU[2] = {1, 1}, LB[2] = {-1, -1}, RB[2] = {1, -1};
3396  double r = 1, sr = 1;
3397 
3398  if (data[0] > -1 && data[0] < 1 && data[1] > -1 && data[1] < 1) {
3399  return lineart_get_bounding_area(rb, data[0], data[1]);
3400  }
3401 
3402  if (lineart_LineIntersectTest2d(e->v1->fbcoord, e->v2->fbcoord, LU, RU, &sr) && sr < r &&
3403  sr > 0) {
3404  r = sr;
3405  }
3406  if (lineart_LineIntersectTest2d(e->v1->fbcoord, e->v2->fbcoord, LB, RB, &sr) && sr < r &&
3407  sr > 0) {
3408  r = sr;
3409  }
3410  if (lineart_LineIntersectTest2d(e->v1->fbcoord, e->v2->fbcoord, LB, LU, &sr) && sr < r &&
3411  sr > 0) {
3412  r = sr;
3413  }
3414  if (lineart_LineIntersectTest2d(e->v1->fbcoord, e->v2->fbcoord, RB, RU, &sr) && sr < r &&
3415  sr > 0) {
3416  r = sr;
3417  }
3418  interp_v2_v2v2_db(data, e->v1->fbcoord, e->v2->fbcoord, r);
3419 
3420  return lineart_get_bounding_area(rb, data[0], data[1]);
3421 }
3422 
3428  LineartEdge *e,
3429  double x,
3430  double y,
3431  double k,
3432  int positive_x,
3433  int positive_y,
3434  double *next_x,
3435  double *next_y)
3436 {
3437  double rx, ry, ux, uy, lx, ly, bx, by;
3438  double r1, r2;
3439  LineartBoundingArea *ba;
3440 
3441  /* If we are marching towards the right. */
3442  if (positive_x > 0) {
3443  rx = this->r;
3444  ry = y + k * (rx - x);
3445 
3446  /* If we are marching towards the top. */
3447  if (positive_y > 0) {
3448  uy = this->u;
3449  ux = x + (uy - y) / k;
3450  r1 = ratiod(e->v1->fbcoord[0], e->v2->fbcoord[0], rx);
3451  r2 = ratiod(e->v1->fbcoord[0], e->v2->fbcoord[0], ux);
3452  if (MIN2(r1, r2) > 1) {
3453  return 0;
3454  }
3455 
3456  /* We reached the right side before the top side. */
3457  if (r1 <= r2) {
3458  LISTBASE_FOREACH (LinkData *, lip, &this->rp) {
3459  ba = lip->data;
3460  if (ba->u >= ry && ba->b < ry) {
3461  *next_x = rx;
3462  *next_y = ry;
3463  return ba;
3464  }
3465  }
3466  }
3467  /* We reached the top side before the right side. */
3468  else {
3469  LISTBASE_FOREACH (LinkData *, lip, &this->up) {
3470  ba = lip->data;
3471  if (ba->r >= ux && ba->l < ux) {
3472  *next_x = ux;
3473  *next_y = uy;
3474  return ba;
3475  }
3476  }
3477  }
3478  }
3479  /* If we are marching towards the bottom. */
3480  else if (positive_y < 0) {
3481  by = this->b;
3482  bx = x + (by - y) / k;
3483  r1 = ratiod(e->v1->fbcoord[0], e->v2->fbcoord[0], rx);
3484  r2 = ratiod(e->v1->fbcoord[0], e->v2->fbcoord[0], bx);
3485  if (MIN2(r1, r2) > 1) {
3486  return 0;
3487  }
3488  if (r1 <= r2) {
3489  LISTBASE_FOREACH (LinkData *, lip, &this->rp) {
3490  ba = lip->data;
3491  if (ba->u >= ry && ba->b < ry) {
3492  *next_x = rx;
3493  *next_y = ry;
3494  return ba;
3495  }
3496  }
3497  }
3498  else {
3499  LISTBASE_FOREACH (LinkData *, lip, &this->bp) {
3500  ba = lip->data;
3501  if (ba->r >= bx && ba->l < bx) {
3502  *next_x = bx;
3503  *next_y = by;
3504  return ba;
3505  }
3506  }
3507  }
3508  }
3509  /* If the line is completely horizontal, in which Y difference == 0. */
3510  else {
3511  r1 = ratiod(e->v1->fbcoord[0], e->v2->fbcoord[0], this->r);
3512  if (r1 > 1) {
3513  return 0;
3514  }
3515  LISTBASE_FOREACH (LinkData *, lip, &this->rp) {
3516  ba = lip->data;
3517  if (ba->u >= y && ba->b < y) {
3518  *next_x = this->r;
3519  *next_y = y;
3520  return ba;
3521  }
3522  }
3523  }
3524  }
3525 
3526  /* If we are marching towards the left. */
3527  else if (positive_x < 0) {
3528  lx = this->l;
3529  ly = y + k * (lx - x);
3530 
3531  /* If we are marching towards the top. */
3532  if (positive_y > 0) {
3533  uy = this->u;
3534  ux = x + (uy - y) / k;
3535  r1 = ratiod(e->v1->fbcoord[0], e->v2->fbcoord[0], lx);
3536  r2 = ratiod(e->v1->fbcoord[0], e->v2->fbcoord[0], ux);
3537  if (MIN2(r1, r2) > 1) {
3538  return 0;
3539  }
3540  if (r1 <= r2) {
3541  LISTBASE_FOREACH (LinkData *, lip, &this->lp) {
3542  ba = lip->data;
3543  if (ba->u >= ly && ba->b < ly) {
3544  *next_x = lx;
3545  *next_y = ly;
3546  return ba;
3547  }
3548  }
3549  }
3550  else {
3551  LISTBASE_FOREACH (LinkData *, lip, &this->up) {
3552  ba = lip->data;
3553  if (ba->r >= ux && ba->l < ux) {
3554  *next_x = ux;
3555  *next_y = uy;
3556  return ba;
3557  }
3558  }
3559  }
3560  }
3561 
3562  /* If we are marching towards the bottom. */
3563  else if (positive_y < 0) {
3564  by = this->b;
3565  bx = x + (by - y) / k;
3566  r1 = ratiod(e->v1->fbcoord[0], e->v2->fbcoord[0], lx);
3567  r2 = ratiod(e->v1->fbcoord[0], e->v2->fbcoord[0], bx);
3568  if (MIN2(r1, r2) > 1) {
3569  return 0;
3570  }
3571  if (r1 <= r2) {
3572  LISTBASE_FOREACH (LinkData *, lip, &this->lp) {
3573  ba = lip->data;
3574  if (ba->u >= ly && ba->b < ly) {
3575  *next_x = lx;
3576  *next_y = ly;
3577  return ba;
3578  }
3579  }
3580  }
3581  else {
3582  LISTBASE_FOREACH (LinkData *, lip, &this->bp) {
3583  ba = lip->data;
3584  if (ba->r >= bx && ba->l < bx) {
3585  *next_x = bx;
3586  *next_y = by;
3587  return ba;
3588  }
3589  }
3590  }
3591  }
3592  /* Again, horizontal. */
3593  else {
3594  r1 = ratiod(e->v1->fbcoord[0], e->v2->fbcoord[0], this->l);
3595  if (r1 > 1) {
3596  return 0;
3597  }
3598  LISTBASE_FOREACH (LinkData *, lip, &this->lp) {
3599  ba = lip->data;
3600  if (ba->u >= y && ba->b < y) {
3601  *next_x = this->l;
3602  *next_y = y;
3603  return ba;
3604  }
3605  }
3606  }
3607  }
3608  /* If the line is completely vertical, hence X difference == 0. */
3609  else {
3610  if (positive_y > 0) {
3611  r1 = ratiod(e->v1->fbcoord[1], e->v2->fbcoord[1], this->u);
3612  if (r1 > 1) {
3613  return 0;
3614  }
3615  LISTBASE_FOREACH (LinkData *, lip, &this->up) {
3616  ba = lip->data;
3617  if (ba->r > x && ba->l <= x) {
3618  *next_x = x;
3619  *next_y = this->u;
3620  return ba;
3621  }
3622  }
3623  }
3624  else if (positive_y < 0) {
3625  r1 = ratiod(e->v1->fbcoord[1], e->v2->fbcoord[1], this->b);
3626  if (r1 > 1) {
3627  return 0;
3628  }
3629  LISTBASE_FOREACH (LinkData *, lip, &this->bp) {
3630  ba = lip->data;
3631  if (ba->r > x && ba->l <= x) {
3632  *next_x = x;
3633  *next_y = this->b;
3634  return ba;
3635  }
3636  }
3637  }
3638  else {
3639  /* Segment has no length. */
3640  return 0;
3641  }
3642  }
3643  return 0;
3644 }
3645 
3652 {
3653  LineartRenderBuffer *rb;
3655  int intersections_only = 0; /* Not used right now, but preserve for future. */
3656 
3658 
3659  if (!scene->camera) {
3660  return false;
3661  }
3662 
3664 
3665  /* Triangle thread testing data size varies depending on the thread count.
3666  * See definition of LineartTriangleThread for details. */
3668 
3669  /* This is used to limit calculation to a certain level to save time, lines who have higher
3670  * occlusion levels will get ignored. */
3671  rb->max_occlusion_level = MAX2(lmd->level_start, lmd->level_end);
3672 
3673  /* FIXME(Yiming): See definition of int #LineartRenderBuffer::_source_type for detailed. */
3674  rb->_source_type = lmd->source_type;
3676  rb->_source_object = lmd->source_object;
3677 
3678  /* Get view vector before loading geometries, because we detect feature lines there. */
3682 
3683  if (!rb->vertex_buffer_pointers.first) {
3684  /* No geometry loaded, return early. */
3685  return true;
3686  }
3687 
3688  /* Initialize the bounding box acceleration structure, it's a lot like BVH in 3D. */
3690 
3691  /* We need to get cut into triangles that are crossing near/far plans, only this way can we get
3692  * correct coordinates of those clipped lines. Done in two steps,
3693  * setting clip_far==false for near plane. */
3694  lineart_main_cull_triangles(rb, false);
3695  /* `clip_far == true` for far plane. */
3696  lineart_main_cull_triangles(rb, true);
3697 
3698  /* At this point triangle adjacent info pointers is no longer needed, free them. */
3700 
3701  /* Do the perspective division after clipping is done. */
3703 
3704  /* Triangle intersections are done here during sequential adding of them. Only after this,
3705  * triangles and lines are all linked with acceleration structure, and the 2D occlusion stage
3706  * can do its job. */
3708 
3709  /* Link lines to acceleration structure, this can only be done after perspective division, if
3710  * we do it after triangles being added, the acceleration structure has already been
3711  * subdivided, this way we do less list manipulations. */
3713 
3714  /* "intersection_only" is preserved for being called in a standalone fashion.
3715  * If so the data will already be available at the stage. Otherwise we do the occlusion and
3716  * chaining etc.*/
3717 
3718  if (!intersections_only) {
3719 
3720  /* Occlusion is work-and-wait. This call will not return before work is completed. */
3722 
3723  /* Chaining is all single threaded. See lineart_chain.c
3724  * In this particular call, only lines that are geometrically connected (share the _exact_
3725  * same end point) will be chained together. */
3727 
3728  /* We are unable to take care of occlusion if we only connect end points, so here we do a
3729  * spit, where the splitting point could be any cut in e->segments. */
3731 
3732  /* Then we connect chains based on the _proximity_ of their end points in image space, here's
3733  * the place threshold value gets involved. */
3734 
3735  /* do_geometry_space = true. */
3737 
3738  /* After chaining, we need to clear flags so we don't confuse GPencil generation calls. */
3740 
3741  float *t_image = &lmd->chaining_image_threshold;
3742  /* This configuration ensures there won't be accidental lost of short unchained segments. */
3743  MOD_lineart_chain_discard_short(rb, MIN2(*t_image, 0.001f) - FLT_EPSILON);
3744 
3745  if (rb->angle_splitting_threshold > FLT_EPSILON) {
3747  }
3748  }
3749 
3750  if (G.debug_value == 4000) {
3752  }
3753 
3754  return true;
3755 }
3756 
3758 {
3759  int types = 0;
3761  types |= rb->use_crease ? LRT_EDGE_FLAG_CREASE : 0;
3765  return types;
3766 }
3767 
3770  Object *gpencil_object,
3771  float (*gp_obmat_inverse)[4],
3772  bGPDlayer *UNUSED(gpl),
3773  bGPDframe *gpf,
3774  int level_start,
3775  int level_end,
3776  int material_nr,
3777  Object *source_object,
3778  Collection *source_collection,
3779  int types,
3780  uchar transparency_flags,
3781  uchar transparency_mask,
3782  short thickness,
3783  float opacity,
3784  const char *source_vgname,
3785  const char *vgname,
3786  int modifier_flags)
3787 {
3788  if (rb == NULL) {
3789  if (G.debug_value == 4000) {
3790  printf("NULL Lineart rb!\n");
3791  }
3792  return;
3793  }
3794 
3795  int stroke_count = 0;
3796  int color_idx = 0;
3797 
3798  Object *orig_ob = NULL;
3799  if (source_object) {
3800  orig_ob = source_object->id.orig_id ? (Object *)source_object->id.orig_id : source_object;
3801  }
3802 
3803  Collection *orig_col = NULL;
3804  if (source_collection) {
3805  orig_col = source_collection->id.orig_id ? (Collection *)source_collection->id.orig_id :
3806  source_collection;
3807  }
3808 
3809  /* (!orig_col && !orig_ob) means the whole scene is selected. */
3810 
3811  float mat[4][4];
3812  unit_m4(mat);
3813 
3814  int enabled_types = lineart_rb_edge_types(rb);
3815  bool invert_input = modifier_flags & LRT_GPENCIL_INVERT_SOURCE_VGROUP;
3816  bool match_output = modifier_flags & LRT_GPENCIL_MATCH_OUTPUT_VGROUP;
3817 
3818  LISTBASE_FOREACH (LineartLineChain *, rlc, &rb->chains) {
3819 
3820  if (rlc->picked) {
3821  continue;
3822  }
3823  if (!(rlc->type & (types & enabled_types))) {
3824  continue;
3825  }
3826  if (rlc->level > level_end || rlc->level < level_start) {
3827  continue;
3828  }
3829  if (orig_ob && orig_ob != rlc->object_ref) {
3830  continue;
3831  }
3832  if (orig_col && rlc->object_ref) {
3833  if (!BKE_collection_has_object_recursive_instanced(orig_col, (Object *)rlc->object_ref)) {
3834  continue;
3835  }
3836  }
3837  if (transparency_flags & LRT_GPENCIL_TRANSPARENCY_ENABLE) {
3838  if (transparency_flags & LRT_GPENCIL_TRANSPARENCY_MATCH) {
3839  if (rlc->transparency_mask != transparency_mask) {
3840  continue;
3841  }
3842  }
3843  else {
3844  if (!(rlc->transparency_mask & transparency_mask)) {
3845  continue;
3846  }
3847  }
3848  }
3849 
3850  /* Preserved: If we ever do asynchronous generation, this picked flag should be set here. */
3851  // rlc->picked = 1;
3852 
3853  int array_idx = 0;
3854  int count = MOD_lineart_chain_count(rlc);
3855  bGPDstroke *gps = BKE_gpencil_stroke_add(gpf, color_idx, count, thickness, false);
3856 
3857  float *stroke_data = MEM_callocN(sizeof(float) * count * GP_PRIM_DATABUF_SIZE,
3858  "line art add stroke");
3859 
3860  LISTBASE_FOREACH (LineartLineChainItem *, rlci, &rlc->chain) {
3861  stroke_data[array_idx] = rlci->gpos[0];
3862  stroke_data[array_idx + 1] = rlci->gpos[1];
3863  stroke_data[array_idx + 2] = rlci->gpos[2];
3864  mul_m4_v3(gp_obmat_inverse, &stroke_data[array_idx]);
3865  stroke_data[array_idx + 3] = 1; /* thickness. */
3866  stroke_data[array_idx + 4] = opacity; /* hardness?. */
3867  array_idx += 5;
3868  }
3869 
3870  BKE_gpencil_stroke_add_points(gps, stroke_data, count, mat);
3872  gps->mat_nr = max_ii(material_nr, 0);
3873 
3874  MEM_freeN(stroke_data);
3875 
3876  if (source_vgname && vgname) {
3877  Object *eval_ob = DEG_get_evaluated_object(depsgraph, rlc->object_ref);
3878  int gpdg = -1;
3879  if ((match_output || (gpdg = BKE_object_defgroup_name_index(gpencil_object, vgname)) >= 0)) {
3880  if (eval_ob && eval_ob->type == OB_MESH) {
3881  int dindex = 0;
3882  Mesh *me = (Mesh *)eval_ob->data;
3883  if (me->dvert) {
3884  LISTBASE_FOREACH (bDeformGroup *, db, &eval_ob->defbase) {
3885  if ((!source_vgname) || strstr(db->name, source_vgname) == db->name) {
3886  if (match_output) {
3887  gpdg = BKE_object_defgroup_name_index(gpencil_object, db->name);
3888  if (gpdg < 0) {
3889  continue;
3890  }
3891  }
3892  int sindex = 0, vindex;
3893  LISTBASE_FOREACH (LineartLineChainItem *, rlci, &rlc->chain) {
3894  vindex = rlci->index;
3895  if (vindex >= me->totvert) {
3896  break;
3897  }
3898  MDeformWeight *mdw = BKE_defvert_ensure_index(&me->dvert[vindex], dindex);
3899  MDeformWeight *gdw = BKE_defvert_ensure_index(&gps->dvert[sindex], gpdg);
3900 
3901  float use_weight = mdw->weight;
3902  if (invert_input) {
3903  use_weight = 1 - use_weight;
3904  }
3905  gdw->weight = MAX2(use_weight, gdw->weight);
3906 
3907  sindex++;
3908  }
3909  }
3910  dindex++;
3911  }
3912  }
3913  }
3914  }
3915  }
3916 
3917  if (G.debug_value == 4000) {
3919  }
3920  BKE_gpencil_stroke_geometry_update(gpencil_object->data, gps);
3921  stroke_count++;
3922  }
3923 
3924  if (G.debug_value == 4000) {
3925  printf("LRT: Generated %d strokes.\n", stroke_count);
3926  }
3927 }
3928 
3934  Object *ob,
3935  bGPDlayer *gpl,
3936  bGPDframe *gpf,
3937  char source_type,
3938  void *source_reference,
3939  int level_start,
3940  int level_end,
3941  int mat_nr,
3942  short edge_types,
3943  uchar transparency_flags,
3944  uchar transparency_mask,
3945  short thickness,
3946  float opacity,
3947  const char *source_vgname,
3948  const char *vgname,
3949  int modifier_flags)
3950 {
3951 
3952  if (!gpl || !gpf || !ob) {
3953  return;
3954  }
3955 
3956  Object *source_object = NULL;
3957  Collection *source_collection = NULL;
3958  short use_types = 0;
3959  if (source_type == LRT_SOURCE_OBJECT) {
3960  if (!source_reference) {
3961  return;
3962  }
3963  source_object = (Object *)source_reference;
3964  /* Note that intersection lines will only be in collection. */
3965  use_types = edge_types & (~LRT_EDGE_FLAG_INTERSECTION);
3966  }
3967  else if (source_type == LRT_SOURCE_COLLECTION) {
3968  if (!source_reference) {
3969  return;
3970  }
3971  source_collection = (Collection *)source_reference;
3972  use_types = edge_types;
3973  }
3974  else {
3975  /* Whole scene. */
3976  use_types = edge_types;
3977  }
3978  float gp_obmat_inverse[4][4];
3979  invert_m4_m4(gp_obmat_inverse, ob->obmat);
3981  depsgraph,
3982  ob,
3983  gp_obmat_inverse,
3984  gpl,
3985  gpf,
3986  level_start,
3987  level_end,
3988  mat_nr,
3989  source_object,
3990  source_collection,
3991  use_types,
3992  transparency_flags,
3993  transparency_mask,
3994  thickness,
3995  opacity,
3996  source_vgname,
3997  vgname,
3998  modifier_flags);
3999 }
Camera data-block and utility functions.
float BKE_camera_sensor_size(int sensor_fit, float sensor_x, float sensor_y)
Definition: camera.c:242
int BKE_camera_sensor_fit(int sensor_fit, float sizex, float sizey)
Definition: camera.c:252
bool BKE_collection_has_object_recursive_instanced(struct Collection *collection, struct Object *ob)
Definition: collection.c:971
bool BKE_collection_has_object(struct Collection *collection, const struct Object *ob)
CustomData interface, see also DNA_customdata_types.h.
bool CustomData_has_layer(const struct CustomData *data, int type)
void * CustomData_bmesh_get(const struct CustomData *data, void *block, int type)
support for deformation groups and hooks.
int BKE_object_defgroup_name_index(const struct Object *ob, const char *name)
struct MDeformWeight * BKE_defvert_ensure_index(struct MDeformVert *dv, const int defgroup)
Definition: deform.c:688
BMEditMesh * BKE_editmesh_create(BMesh *bm, const bool do_tessellate)
Definition: editmesh.c:42
struct bGPDstroke * BKE_gpencil_stroke_add(struct bGPDframe *gpf, int mat_idx, int totpoints, short thickness, const bool insert_at_head)
Definition: gpencil.c:871
#define GP_PRIM_DATABUF_SIZE
Definition: BKE_gpencil.h:157
void BKE_gpencil_dvert_ensure(struct bGPDstroke *gps)
Definition: gpencil.c:2067
void BKE_gpencil_stroke_add_points(struct bGPDstroke *gps, const float *array, const int totpoints, const float mat[4][4])
Definition: gpencil.c:800
void BKE_gpencil_stroke_geometry_update(struct bGPdata *gpd, struct bGPDstroke *gps)
void BKE_gpencil_stroke_set_random_color(struct bGPDstroke *gps)
General operations, lookup, etc. for materials.
struct Material * BKE_object_material_get(struct Object *ob, short act)
Definition: material.c:697
struct Mesh * BKE_mesh_new_from_object(struct Depsgraph *depsgraph, struct Object *object, const bool preserve_all_data_layers, const bool preserve_origindex)
int BKE_render_num_threads(const struct RenderData *r)
bool BKE_scene_camera_switch_update(struct Scene *scene)
Definition: scene.c:2349
#define BLI_INLINE
void * BLI_pophead(ListBase *listbase) ATTR_NONNULL(1)
Definition: listbase.c:257
#define LISTBASE_FOREACH(type, var, list)
Definition: BLI_listbase.h:172
BLI_INLINE void BLI_listbase_clear(struct ListBase *lb)
Definition: BLI_listbase.h:128
void BLI_addtail(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:110
void BLI_remlink(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:133
void BLI_insertlinkbefore(struct ListBase *listbase, void *vnextlink, void *vnewlink) ATTR_NONNULL(1)
Definition: listbase.c:395
MINLINE double ratiod(double min, double max, double pos)
MINLINE int max_ii(int a, int b)
#define M_PI
Definition: BLI_math_base.h:38
void mul_v4_m4v3_db(double r[4], const double mat[4][4], const double vec[3])
Definition: math_matrix.c:761
void mul_v3_m4v3_db(double r[3], const double mat[4][4], const double vec[3])
Definition: math_matrix.c:752
void unit_m4(float m[4][4])
Definition: rct.c:1140
bool invert_m4_m4(float R[4][4], const float A[4][4])
Definition: math_matrix.c:1278
void unit_m4_db(double m[4][4])
Definition: math_matrix.c:75
void copy_m4d_m4(double m1[4][4], const float m2[4][4])
Definition: math_matrix.c:183
void mul_m4_v3(const float M[4][4], float r[3])
Definition: math_matrix.c:732
void copy_m4_m4(float m1[4][4], const float m2[4][4])
Definition: math_matrix.c:95
void mul_m4db_m4db_m4fl_uniq(double R[4][4], const double A[4][4], const float B[4][4])
Definition: math_matrix.c:347
void mul_v3_mat3_m4v3_db(double r[3], const double M[4][4], const double v[3])
Definition: math_matrix.c:814
void transpose_m4(float R[4][4])
Definition: math_matrix.c:1358
void copy_m4_m4_db(double m1[4][4], const double m2[4][4])
Definition: math_matrix.c:100
void mul_v3_mat3_m4v3(float r[3], const float M[4][4], const float v[3])
Definition: math_matrix.c:804
float focallength_to_fov(float focal_length, float sensor)
MINLINE double normalize_v3_db(double n[3])
MINLINE float normalize_v3(float r[3])
void interp_v3_v3v3_db(double target[3], const double a[3], const double b[3], const double t)
Definition: math_vector.c:1456
MINLINE void mul_v3db_db(double r[3], double f)
MINLINE void add_v3_v3_db(double r[3], const double a[3])
MINLINE double dot_v3v3_db(const double a[3], const double b[3]) ATTR_WARN_UNUSED_RESULT
void interp_v2_v2v2_db(double target[2], const double a[2], const double b[2], const double t)
Definition: math_vector.c:1465
MINLINE void copy_v3db_v3fl(double r[3], const float a[3])
MINLINE void cross_v3_v3v3_db(double r[3], const double a[3], const double b[3])
MINLINE void copy_v3_v3_db(double r[3], const double a[3])
MINLINE void copy_v4_v4_db(double r[4], const double a[4])
MINLINE void sub_v3_v3v3_db(double r[3], const double a[3], const double b[3])
MINLINE void sub_v2_v2v2_db(double r[2], const double a[2], const double b[2])
unsigned char uchar
Definition: BLI_sys_types.h:86
void BLI_task_pool_work_and_wait(TaskPool *pool)
Definition: task_pool.cc:496
TaskPool * BLI_task_pool_create(void *userdata, TaskPriority priority)
Definition: task_pool.cc:406
void BLI_task_pool_free(TaskPool *pool)
Definition: task_pool.cc:456
@ TASK_PRIORITY_HIGH
Definition: BLI_task.h:67
void BLI_task_pool_push(TaskPool *pool, TaskRunFunction run, void *taskdata, bool free_taskdata, TaskFreeFunction freedata)
Definition: task_pool.cc:475
pthread_spinlock_t SpinLock
Definition: BLI_threads.h:111
void BLI_spin_init(SpinLock *spin)
Definition: threads.cc:447
void BLI_spin_unlock(SpinLock *spin)
Definition: threads.cc:480
void BLI_spin_lock(SpinLock *spin)
Definition: threads.cc:461
void BLI_spin_end(SpinLock *spin)
Definition: threads.cc:495
#define MAX3(a, b, c)
#define MIN3(a, b, c)
#define UNUSED(x)
#define MAX2(a, b)
#define UNLIKELY(x)
#define ELEM(...)
#define MIN2(a, b)
typedef double(DMatrix)[4][4]
struct Depsgraph Depsgraph
Definition: DEG_depsgraph.h:51
#define DEG_OBJECT_ITER_END
#define DEG_OBJECT_ITER_BEGIN(graph_, instance_, flag_)
@ DEG_ITER_OBJECT_FLAG_LINKED_DIRECTLY
@ DEG_ITER_OBJECT_FLAG_VISIBLE
@ DEG_ITER_OBJECT_FLAG_DUPLI
@ DEG_ITER_OBJECT_FLAG_LINKED_VIA_SET
struct Object * DEG_get_evaluated_object(const struct Depsgraph *depsgraph, struct Object *object)
struct Scene * DEG_get_evaluated_scene(const struct Depsgraph *graph)
@ CAM_PERSP
@ CAM_ORTHO
@ CAMERA_SENSOR_FIT_HOR
@ CAMERA_SENSOR_FIT_VERT
Object groups, one object can be in many groups at once.
@ COLLECTION_LRT_EXCLUDE
@ COLLECTION_LRT_INTERSECTION_ONLY
@ COLLECTION_LRT_OCCLUSION_ONLY
@ COLLECTION_LRT_NO_INTERSECTION
@ CD_FREESTYLE_EDGE
@ LRT_GPENCIL_TRANSPARENCY_ENABLE
@ LRT_GPENCIL_TRANSPARENCY_MATCH
@ LRT_GPENCIL_INVERT_SOURCE_VGROUP
@ LRT_GPENCIL_MATCH_OUTPUT_VGROUP
@ LRT_EDGE_FLAG_MATERIAL
@ LRT_EDGE_FLAG_CREASE
@ LRT_EDGE_FLAG_INTERSECTION
@ LRT_EDGE_FLAG_CONTOUR
@ LRT_EDGE_FLAG_EDGE_MARK
@ LRT_EVERYTHING_AS_CONTOUR
@ LRT_INTERSECTION_AS_CONTOUR
@ LRT_ALLOW_OVERLAPPING_EDGES
@ LRT_ALLOW_DUPLI_OBJECTS
@ LRT_REMOVE_DOUBLES
@ LRT_ALLOW_CLIPPING_BOUNDARIES
@ LRT_MATERIAL_TRANSPARENCY_ENABLED
@ FREESTYLE_EDGE_MARK
@ MOD_TRIANGULATE_QUAD_FIXED
@ MOD_TRIANGULATE_NGON_BEAUTY
@ OBJECT_LRT_OWN_CREASE
@ OBJECT_LRT_INCLUDE
@ OBJECT_LRT_NO_INTERSECTION
@ OBJECT_LRT_EXCLUDE
@ OBJECT_LRT_INHERIT
@ OBJECT_LRT_OCCLUSION_ONLY
@ OBJECT_LRT_INTERSECTION_ONLY
@ OB_MBALL
@ OB_SURF
@ OB_FONT
@ OB_MESH
@ OB_CURVE
static AppView * view
_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 GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble u2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLdouble GLdouble v2 _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLdouble GLdouble nz _GL_VOID_RET _GL_VOID GLfloat GLfloat nz _GL_VOID_RET _GL_VOID GLint GLint nz _GL_VOID_RET _GL_VOID GLshort GLshort nz _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const GLfloat *values _GL_VOID_RET _GL_VOID GLsizei const GLushort *values _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID const GLuint const GLclampf *priorities _GL_VOID_RET _GL_VOID GLdouble y _GL_VOID_RET _GL_VOID GLfloat y _GL_VOID_RET _GL_VOID GLint y _GL_VOID_RET _GL_VOID GLshort y _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLfloat GLfloat z _GL_VOID_RET _GL_VOID GLint GLint z _GL_VOID_RET _GL_VOID GLshort GLshort z _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble w _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat w _GL_VOID_RET _GL_VOID GLint GLint GLint w _GL_VOID_RET _GL_VOID GLshort GLshort GLshort w _GL_VOID_RET _GL_VOID GLdouble y1
_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 GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble u2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLdouble GLdouble v2 _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLdouble GLdouble nz _GL_VOID_RET _GL_VOID GLfloat GLfloat nz _GL_VOID_RET _GL_VOID GLint GLint nz _GL_VOID_RET _GL_VOID GLshort GLshort nz _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const GLfloat *values _GL_VOID_RET _GL_VOID GLsizei const GLushort *values _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID const GLuint const GLclampf *priorities _GL_VOID_RET _GL_VOID GLdouble y _GL_VOID_RET _GL_VOID GLfloat y _GL_VOID_RET _GL_VOID GLint y _GL_VOID_RET _GL_VOID GLshort y _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLfloat GLfloat z _GL_VOID_RET _GL_VOID GLint GLint z _GL_VOID_RET _GL_VOID GLshort GLshort z _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble w _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat w _GL_VOID_RET _GL_VOID GLint GLint GLint w _GL_VOID_RET _GL_VOID GLshort GLshort GLshort w _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble y2 _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat y2 _GL_VOID_RET _GL_VOID GLint GLint GLint y2 _GL_VOID_RET _GL_VOID GLshort GLshort GLshort y2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLuint *buffer _GL_VOID_RET _GL_VOID GLdouble t _GL_VOID_RET _GL_VOID GLfloat t _GL_VOID_RET _GL_VOID GLint t _GL_VOID_RET _GL_VOID GLshort t _GL_VOID_RET _GL_VOID GLdouble GLdouble r _GL_VOID_RET _GL_VOID GLfloat GLfloat r _GL_VOID_RET _GL_VOID GLint GLint r _GL_VOID_RET _GL_VOID GLshort GLshort r _GL_VOID_RET _GL_VOID GLdouble GLdouble r
_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 GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble u2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLdouble GLdouble v2 _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLdouble GLdouble nz _GL_VOID_RET _GL_VOID GLfloat GLfloat nz _GL_VOID_RET _GL_VOID GLint GLint nz _GL_VOID_RET _GL_VOID GLshort GLshort nz _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const GLfloat *values _GL_VOID_RET _GL_VOID GLsizei const GLushort *values _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID const GLuint const GLclampf *priorities _GL_VOID_RET _GL_VOID GLdouble y _GL_VOID_RET _GL_VOID GLfloat y _GL_VOID_RET _GL_VOID GLint y _GL_VOID_RET _GL_VOID GLshort y _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLfloat GLfloat z _GL_VOID_RET _GL_VOID GLint GLint z _GL_VOID_RET _GL_VOID GLshort GLshort z _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble w _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat w _GL_VOID_RET _GL_VOID GLint GLint GLint w _GL_VOID_RET _GL_VOID GLshort GLshort GLshort w _GL_VOID_RET _GL_VOID GLdouble GLdouble x2
_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 y
_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 GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble u2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLdouble GLdouble v2 _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLdouble GLdouble nz _GL_VOID_RET _GL_VOID GLfloat GLfloat nz _GL_VOID_RET _GL_VOID GLint GLint nz _GL_VOID_RET _GL_VOID GLshort GLshort nz _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const GLfloat *values _GL_VOID_RET _GL_VOID GLsizei const GLushort *values _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID const GLuint const GLclampf *priorities _GL_VOID_RET _GL_VOID GLdouble y _GL_VOID_RET _GL_VOID GLfloat y _GL_VOID_RET _GL_VOID GLint y _GL_VOID_RET _GL_VOID GLshort y _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLfloat GLfloat z _GL_VOID_RET _GL_VOID GLint GLint z _GL_VOID_RET _GL_VOID GLshort GLshort z _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble w _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat w _GL_VOID_RET _GL_VOID GLint GLint GLint w _GL_VOID_RET _GL_VOID GLshort GLshort GLshort w _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble y2 _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat y2 _GL_VOID_RET _GL_VOID GLint GLint GLint y2 _GL_VOID_RET _GL_VOID GLshort GLshort GLshort y2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLuint *buffer _GL_VOID_RET _GL_VOID GLdouble t _GL_VOID_RET _GL_VOID GLfloat t _GL_VOID_RET _GL_VOID GLint t _GL_VOID_RET _GL_VOID GLshort t _GL_VOID_RET _GL_VOID GLdouble t
_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 order
_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
Read Guarded memory(de)allocation.
#define LRT_DOUBLE_CLOSE_ENOUGH(a, b)
Definition: MOD_lineart.h:411
#define LRT_ABC(index)
Definition: MOD_lineart.h:409
#define DBL_TRIANGLE_LIM
Definition: MOD_lineart.h:311
@ LRT_VERT_HAS_INTERSECTION_DATA
Definition: MOD_lineart.h:136
BLI_INLINE int lineart_LineIntersectTest2d(const double *a1, const double *a2, const double *b1, const double *b2, double *aRatio)
Definition: MOD_lineart.h:413
@ LRT_TRIANGLE_NO_INTERSECTION
Definition: MOD_lineart.h:322
@ LRT_CULL_GENERATED
Definition: MOD_lineart.h:320
@ LRT_CULL_DISCARD
Definition: MOD_lineart.h:319
@ LRT_TRIANGLE_INTERSECTION_ONLY
Definition: MOD_lineart.h:321
@ LRT_CULL_USED
Definition: MOD_lineart.h:318
@ LRT_ELEMENT_NO_INTERSECTION
Definition: MOD_lineart.h:82
@ LRT_ELEMENT_BORDER_ONLY
Definition: MOD_lineart.h:81
@ LRT_ELEMENT_IS_ADDITIONAL
Definition: MOD_lineart.h:80
struct LineartTriangle LineartTriangle
Group RGB to Bright Vector Camera CLAMP
Platform independent time functions.
@ BM_FACE
Definition: bmesh_class.h:386
@ BM_VERT
Definition: bmesh_class.h:383
@ BM_EDGE
Definition: bmesh_class.h:384
@ BM_ELEM_TAG
Definition: bmesh_class.h:484
BMesh * BM_mesh_copy(BMesh *bm_old)
#define BM_elem_index_get(ele)
Definition: bmesh_inline.h:124
ATTR_WARN_UNUSED_RESULT BMesh * bm
void BM_mesh_elem_hflag_disable_all(BMesh *bm, const char htype, const char hflag, const bool respecthide)
BMesh * BM_mesh_create(const BMAllocTemplate *allocsize, const struct BMeshCreateParams *params)
BMesh Make Mesh.
Definition: bmesh_mesh.c:157
void BM_mesh_normals_update(BMesh *bm)
BMesh Compute Normals.
Definition: bmesh_mesh.c:500
void BM_mesh_elem_table_ensure(BMesh *bm, const char htype)
Definition: bmesh_mesh.c:2276
void BM_mesh_elem_index_ensure(BMesh *bm, const char htype)
Definition: bmesh_mesh.c:2152
BLI_INLINE BMFace * BM_face_at_index(BMesh *bm, const int index)
Definition: bmesh_mesh.h:110
BLI_INLINE BMEdge * BM_edge_at_index(BMesh *bm, const int index)
Definition: bmesh_mesh.h:104
#define BMALLOC_TEMPLATE_FROM_ME(...)
Definition: bmesh_mesh.h:163
BLI_INLINE BMVert * BM_vert_at_index(BMesh *bm, const int index)
Definition: bmesh_mesh.h:98
void BM_mesh_bm_from_me(BMesh *bm, const Mesh *me, const struct BMeshFromMeshParams *params)
Mesh -> BMesh.
void BMO_op_exec(BMesh *bm, BMOperator *op)
BMESH OPSTACK EXEC OP.
bool BMO_op_initf(BMesh *bm, BMOperator *op, const int flag, const char *fmt,...)
#define BMO_slot_copy(op_src, slots_src, slot_name_src, op_dst, slots_dst, slot_name_dst)
void BMO_op_finish(BMesh *bm, BMOperator *op)
BMESH OPSTACK FINISH OP.
#define BMO_FLAG_DEFAULTS
void BMO_op_init(BMesh *bm, BMOperator *op, const int flag, const char *opname)
BMESH OPSTACK INIT OP.
ATTR_WARN_UNUSED_RESULT const BMVert * v2
ATTR_WARN_UNUSED_RESULT const BMLoop * l
ATTR_WARN_UNUSED_RESULT const BMVert const BMEdge * e
ATTR_WARN_UNUSED_RESULT const BMVert * v
void BM_mesh_triangulate(BMesh *bm, const int quad_method, const int ngon_method, const int min_vertices, const bool tag_only, BMOperator *op, BMOpSlot *slot_facemap_out, BMOpSlot *slot_facemap_double_out)
SIMD_FORCE_INLINE const btScalar & w() const
Return the w value.
Definition: btQuadWord.h:119
StackEntry * from
Scene scene
Material material
const Depsgraph * depsgraph
uint col
BLI_INLINE float fb(float length, float L)
IconTextureDrawCall normal
int count
#define cosf(x)
void MOD_lineart_chain_discard_short(LineartRenderBuffer *rb, const float threshold)
void MOD_lineart_chain_connect(LineartRenderBuffer *rb)
int MOD_lineart_chain_count(const LineartLineChain *rlc)
void MOD_lineart_chain_split_for_fixed_occlusion(LineartRenderBuffer *rb)
void MOD_lineart_chain_feature_lines(LineartRenderBuffer *rb)
void MOD_lineart_chain_clear_picked_flag(LineartRenderBuffer *rb)
void MOD_lineart_chain_split_angle(LineartRenderBuffer *rb, float angle_threshold_rad)
static void lineart_gpencil_generate(LineartRenderBuffer *rb, Depsgraph *depsgraph, Object *gpencil_object, float(*gp_obmat_inverse)[4], bGPDlayer *UNUSED(gpl), bGPDframe *gpf, int level_start, int level_end, int material_nr, Object *source_object, Collection *source_collection, int types, uchar transparency_flags, uchar transparency_mask, short thickness, float opacity, const char *source_vgname, const char *vgname, int modifier_flags)
Definition: lineart_cpu.c:3768
static bool lineart_get_edge_bounding_areas(LineartRenderBuffer *rb, LineartEdge *e, int *rowbegin, int *rowend, int *colbegin, int *colend)
Definition: lineart_cpu.c:3216
static void lineart_triangle_post(LineartTriangle *rt, LineartTriangle *orig)
Definition: lineart_cpu.c:683
static LineartElementLinkNode * lineart_memory_get_triangle_space(LineartRenderBuffer *rb)
Definition: lineart_cpu.c:630
static int lineart_triangle_size_get(const Scene *scene, LineartRenderBuffer *rb)
Definition: lineart_cpu.c:2701
#define INTERSECT_JUST_SMALLER(is, order, num, index)
Definition: lineart_cpu.c:1947
static bool lineart_edge_from_triangle(const LineartTriangle *rt, const LineartEdge *e, bool allow_overlapping_edges)
Definition: lineart_cpu.c:1898
static void lineart_vert_set_intersection_2v(LineartVert *rv, LineartVert *v1, LineartVert *v2)
Definition: lineart_cpu.c:2279
void MOD_lineart_destroy_render_data(LineartGpencilModifierData *lmd)
Definition: lineart_cpu.c:2629
static LineartLineSegment * lineart_give_segment(LineartRenderBuffer *rb)
Definition: lineart_cpu.c:125
#define SELECT_RL(e_num, v1_link, v2_link, newrt)
static LineartRenderBuffer * lineart_create_render_buffer(Scene *scene, LineartGpencilModifierData *lmd)
Definition: lineart_cpu.c:2645
static void lineart_triangle_set_cull_flag(LineartTriangle *rt, uchar flag)
Definition: lineart_cpu.c:690
#define LRT_MESH_FINISH
static void lineart_add_edge_to_list(LineartRenderBuffer *rb, LineartEdge *e)
Definition: lineart_cpu.c:1432
static void lineart_main_link_lines(LineartRenderBuffer *rb)
Definition: lineart_cpu.c:3155
static void lineart_triangle_intersect_in_bounding_area(LineartRenderBuffer *rb, LineartTriangle *rt, LineartBoundingArea *ba)
Definition: lineart_cpu.c:2513
static int lineart_rb_edge_types(LineartRenderBuffer *rb)
Definition: lineart_cpu.c:3757
#define REMOVE_TRIANGLE_RL
static bool lineart_triangle_share_edge(const LineartTriangle *l, const LineartTriangle *r)
Definition: lineart_cpu.c:2192
static void lineart_geometry_object_load(Depsgraph *dg, Object *ob, double(*mv_mat)[4], double(*mvp_mat)[4], LineartRenderBuffer *rb, int override_usage, int *global_vindex)
Definition: lineart_cpu.c:1468
static LineartBoundingArea * lineart_get_bounding_area(LineartRenderBuffer *rb, double x, double y)
Definition: lineart_cpu.c:3298
static bool lineart_point_inside_triangle3d(double v[3], double v0[3], double v1[3], double v2[3])
Definition: lineart_cpu.c:589
static LineartBoundingArea * lineart_edge_first_bounding_area(LineartRenderBuffer *rb, LineartEdge *e)
Definition: lineart_cpu.c:3391
static LineartVert * lineart_triangle_2v_intersection_test(LineartRenderBuffer *rb, LineartVert *v1, LineartVert *v2, LineartTriangle *rt, LineartTriangle *testing, LineartVert *last)
Definition: lineart_cpu.c:2291
static int lineart_occlusion_make_task_info(LineartRenderBuffer *rb, LineartRenderTaskInfo *rti)
Definition: lineart_cpu.c:372
#define LRT_CULL_DECIDE_INSIDE
static bool lineart_vert_already_intersected_2v(LineartVertIntersection *rv, LineartVertIntersection *v1, LineartVertIntersection *v2)
Definition: lineart_cpu.c:2271
static void lineart_main_free_adjacent_data(LineartRenderBuffer *rb)
Definition: lineart_cpu.c:1297
static void lineart_triangle_adjacent_assign(LineartTriangle *rt, LineartTriangleAdjacent *rta, LineartEdge *e)
Definition: lineart_cpu.c:1453
static void lineart_bounding_area_split(LineartRenderBuffer *rb, LineartBoundingArea *root, int recursive_level)
Definition: lineart_cpu.c:2920
static void lineart_main_add_triangles(LineartRenderBuffer *rb)
Definition: lineart_cpu.c:3354
static void lineart_occlusion_worker(TaskPool *__restrict UNUSED(pool), LineartRenderTaskInfo *rti)
Definition: lineart_cpu.c:408
static char lineart_identify_feature_line(LineartRenderBuffer *rb, BMEdge *e, LineartTriangle *rt_array, LineartVert *rv_array, float crease_threshold, bool no_crease, bool count_freestyle, BMesh *bm_if_freestyle)
Definition: lineart_cpu.c:1367
static void lineart_discard_segment(LineartRenderBuffer *rb, LineartLineSegment *rls)
Definition: lineart_cpu.c:112
bool MOD_lineart_compute_feature_lines(Depsgraph *depsgraph, LineartGpencilModifierData *lmd)
Definition: lineart_cpu.c:3651
static bool _lineart_object_not_in_source_collection(Collection *source, Object *ob)
Definition: lineart_cpu.c:1728
static LineartBoundingArea * lineart_bounding_area_next(LineartBoundingArea *this, LineartEdge *e, double x, double y, double k, int positive_x, int positive_y, double *next_x, double *next_y)
Definition: lineart_cpu.c:3427
static LineartElementLinkNode * lineart_memory_get_vert_space(LineartRenderBuffer *rb)
Definition: lineart_cpu.c:649
static LineartTriangle * lineart_triangle_from_index(LineartRenderBuffer *rb, LineartTriangle *rt_array, int index)
Definition: lineart_cpu.c:1358
static bool lineart_triangle_edge_image_space_occlusion(SpinLock *spl, const LineartTriangle *rt, const LineartEdge *e, const double *override_camera_loc, const bool override_cam_is_persp, const bool allow_overlapping_edges, const double vp[4][4], const double *camera_dir, const float cam_shift_x, const float cam_shift_y, double *from, double *to)
BLI_INLINE bool lineart_occlusion_is_adjacent_intersection(LineartEdge *e, LineartTriangle *rt)
Definition: lineart_cpu.c:311
static bool lineart_bounding_area_line_intersect(LineartRenderBuffer *UNUSED(fb), const double l[2], const double r[2], LineartBoundingArea *ba)
Definition: lineart_cpu.c:2989
static void lineart_bounding_areas_connect_new(LineartRenderBuffer *rb, LineartBoundingArea *root)
Definition: lineart_cpu.c:2777
#define RELINK_RL(e_num, newrt)
static void lineart_main_load_geometries(Depsgraph *depsgraph, Scene *scene, Object *camera, LineartRenderBuffer *rb, bool allow_duplicates)
Definition: lineart_cpu.c:1805
static bool lineart_bounding_area_triangle_intersect(LineartRenderBuffer *fb, LineartTriangle *rt, LineartBoundingArea *ba)
Definition: lineart_cpu.c:3032
static void lineart_destroy_render_data(LineartRenderBuffer *rb)
Definition: lineart_cpu.c:2592
static bool lineart_triangle_get_other_verts(const LineartTriangle *rt, const LineartVert *rv, LineartVert **l, LineartVert **r)
Definition: lineart_cpu.c:1875
void MOD_lineart_gpencil_generate(LineartRenderBuffer *rb, Depsgraph *depsgraph, Object *ob, bGPDlayer *gpl, bGPDframe *gpf, char source_type, void *source_reference, int level_start, int level_end, int mat_nr, short edge_types, uchar transparency_flags, uchar transparency_mask, short thickness, float opacity, const char *source_vgname, const char *vgname, int modifier_flags)
Definition: lineart_cpu.c:3932
static bool lineart_point_inside_triangle(const double v[2], const double v0[2], const double v1[2], const double v2[2])
Definition: lineart_cpu.c:475
#define LRT_TRI_SAME_POINT(rt, i, pt)
static void lineart_occlusion_single_line(LineartRenderBuffer *rb, LineartEdge *e, int thread_id)
Definition: lineart_cpu.c:319
static void lineart_bounding_area_link_triangle(LineartRenderBuffer *rb, LineartBoundingArea *root_ba, LineartTriangle *rt, double *LRUB, int recursive, int recursive_level, bool do_intersection)
Definition: lineart_cpu.c:3070
LineartBoundingArea * MOD_lineart_get_parent_bounding_area(LineartRenderBuffer *rb, double x, double y)
Definition: lineart_cpu.c:3268
static LineartElementLinkNode * lineart_memory_get_edge_space(LineartRenderBuffer *rb)
Definition: lineart_cpu.c:666
#define LRT_ASSIGN_OCCLUSION_TASK(name)
static void lineart_main_bounding_area_make_initial(LineartRenderBuffer *rb)
Definition: lineart_cpu.c:2709
static int lineart_point_on_line_segment(double v[2], double v0[2], double v1[2])
Definition: lineart_cpu.c:507
static void lineart_bounding_area_link_line(LineartRenderBuffer *rb, LineartBoundingArea *root_ba, LineartEdge *e)
Definition: lineart_cpu.c:3125
#define INTERSECT_JUST_GREATER(is, order, num, index)
Definition: lineart_cpu.c:1939
static void lineart_edge_cut(LineartRenderBuffer *rb, LineartEdge *e, double start, double end, uchar transparency_mask)
Definition: lineart_cpu.c:146
#define INCREASE_RL
static bool lineart_get_triangle_bounding_areas(LineartRenderBuffer *rb, LineartTriangle *rt, int *rowbegin, int *rowend, int *colbegin, int *colend)
Definition: lineart_cpu.c:3172
static void lineart_triangle_cull_single(LineartRenderBuffer *rb, LineartTriangle *rt, int in0, int in1, int in2, double *cam_pos, double *view_dir, bool allow_boundaries, double(*vp)[4], Object *ob, int *r_v_count, int *r_e_count, int *r_t_count, LineartElementLinkNode *v_eln, LineartElementLinkNode *e_eln, LineartElementLinkNode *t_eln)
Definition: lineart_cpu.c:707
LineartBoundingArea * MOD_lineart_get_bounding_area(LineartRenderBuffer *rb, double x, double y)
Definition: lineart_cpu.c:3342
static LineartVert * lineart_triangle_share_point(const LineartTriangle *l, const LineartTriangle *r)
Definition: lineart_cpu.c:2235
static LineartEdge * lineart_triangle_intersect(LineartRenderBuffer *rb, LineartTriangle *rt, LineartTriangle *testing)
Definition: lineart_cpu.c:2359
static void lineart_main_get_view_vector(LineartRenderBuffer *rb)
Definition: lineart_cpu.c:2573
static void lineart_vert_transform(BMVert *v, int index, LineartVert *RvBuf, double(*mv_mat)[4], double(*mvp_mat)[4])
Definition: lineart_cpu.c:1344
static bool lineart_edge_match(LineartTriangle *rt, LineartEdge *e, int v1, int v2)
Definition: lineart_cpu.c:697
static void lineart_main_cull_triangles(LineartRenderBuffer *rb, bool clip_far)
Definition: lineart_cpu.c:1166
static void lineart_main_occlusion_begin(LineartRenderBuffer *rb)
Definition: lineart_cpu.c:442
#define INTERSECT_SORT_MIN_TO_MAX_3(ia, ib, ic, lst)
Definition: lineart_cpu.c:1929
static int lineart_usage_check(Collection *c, Object *ob, LineartRenderBuffer *_rb)
Definition: lineart_cpu.c:1749
static void lineart_main_perspective_division(LineartRenderBuffer *rb)
Definition: lineart_cpu.c:1315
#define LRT_CULL_ENSURE_MEMORY
static int lineart_point_triangle_relation(double v[2], double v0[2], double v1[2], double v2[2])
Definition: lineart_cpu.c:547
void lineart_prepend_edge_direct(struct LineartEdge **first, void *node)
Definition: lineart_util.c:138
void * lineart_list_pop_pointer_no_free(ListBase *h)
Definition: lineart_util.c:66
void * lineart_list_append_pointer_pool_sized(ListBase *h, struct LineartStaticMemPool *smp, void *data, int size)
Definition: lineart_util.c:51
#define LRT_BOUND_AREA_CROSSES(b1, b2)
void lineart_prepend_pool(LinkNode **first, struct LineartStaticMemPool *smp, void *link)
Definition: lineart_util.c:145
void * lineart_mem_aquire(struct LineartStaticMemPool *smp, size_t size)
Definition: lineart_util.c:95
#define LRT_ITER_ALL_LINES_END
void lineart_matrix_perspective_44d(double(*mProjection)[4], double fFov_rad, double fAspect, double zMin, double zMax)
Definition: lineart_util.c:155
#define LRT_BA_ROWS
void * lineart_mem_aquire_thread(struct LineartStaticMemPool *smp, size_t size)
Definition: lineart_util.c:110
void lineart_count_and_print_render_buffer_memory(struct LineartRenderBuffer *rb)
Definition: lineart_util.c:206
void lineart_list_remove_pointer_item_no_free(ListBase *h, LinkData *lip)
Definition: lineart_util.c:77
#define LRT_ITER_ALL_LINES_BEGIN
void lineart_mem_destroy(struct LineartStaticMemPool *smp)
Definition: lineart_util.c:130
void * lineart_list_append_pointer_pool(ListBase *h, struct LineartStaticMemPool *smp, void *data)
Definition: lineart_util.c:40
void lineart_matrix_ortho_44d(double(*mProjection)[4], double xMin, double xMax, double yMin, double yMax, double zMin, double zMax)
Definition: lineart_util.c:187
static char ** types
Definition: makesdna.c:164
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:41
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:45
static ulong * next
#define RB
#define LF
#define RF
#define LB
static unsigned c
Definition: RandGen.cpp:97
static double B1(double u)
Definition: FitCurve.cpp:318
Intersection< segment > intersection
static unsigned a[3]
Definition: RandGen.cpp:92
INLINE Rall1d< T, V, S > cos(const Rall1d< T, V, S > &arg)
Definition: rall1d.h:319
struct BMesh * bm
Definition: BKE_editmesh.h:52
short mat_nr
Definition: bmesh_class.h:281
float no[3]
Definition: bmesh_class.h:280
BMLoop * l_first
Definition: bmesh_class.h:273
char hflag
Definition: bmesh_class.h:78
void * data
Definition: bmesh_class.h:63
struct BMVert * v
Definition: bmesh_class.h:165
struct BMFace * f
Definition: bmesh_class.h:183
struct BMLoop * next
Definition: bmesh_class.h:245
float co[3]
Definition: bmesh_class.h:99
BMHeader head
Definition: bmesh_class.h:97
int totvert
Definition: bmesh_class.h:297
int totedge
Definition: bmesh_class.h:297
CustomData edata
Definition: bmesh_class.h:337
int totface
Definition: bmesh_class.h:297
float clip_end
char sensor_fit
float sensor_y
float sensor_x
float clip_start
float ortho_scale
struct Collection * collection
struct CollectionChild * next
Definition: DNA_ID.h:273
struct ID * orig_id
Definition: DNA_ID.h:324
struct LineartBoundingArea * child
Definition: MOD_lineart.h:381
ListBase linked_triangles
Definition: MOD_lineart.h:390
struct LineartVert * v2
Definition: MOD_lineart.h:143
ListBase segments
Definition: MOD_lineart.h:150
struct LineartEdge * next
Definition: MOD_lineart.h:142
unsigned char flags
Definition: MOD_lineart.h:154
struct LineartTriangle * t2
Definition: MOD_lineart.h:149
struct LineartTriangle * t1
Definition: MOD_lineart.h:149
struct Object * object_ref
Definition: MOD_lineart.h:163
struct LineartVert * v1
Definition: MOD_lineart.h:143
eLineArtElementNodeFlag flags
Definition: MOD_lineart.h:90
struct LineartLineSegment * prev
Definition: MOD_lineart.h:97
struct LineartLineSegment * next
Definition: MOD_lineart.h:97
unsigned char transparency_mask
Definition: MOD_lineart.h:109
unsigned char occlusion
Definition: MOD_lineart.h:101
ListBase line_buffer_pointers
Definition: MOD_lineart.h:223
LineartEdge * edge_mark_managed
Definition: MOD_lineart.h:263
float cam_obmat[4][4]
Definition: MOD_lineart.h:293
struct LineartBoundingArea * initial_bounding_areas
Definition: MOD_lineart.h:219
unsigned int edge_mark_count
Definition: MOD_lineart.h:261
unsigned int bounding_area_count
Definition: MOD_lineart.h:220
unsigned int intersection_count
Definition: MOD_lineart.h:246
LineartEdge * edge_marks
Definition: MOD_lineart.h:264
unsigned int material_line_count
Definition: MOD_lineart.h:256
ListBase triangle_buffer_pointers
Definition: MOD_lineart.h:224
LineartEdge * material_lines
Definition: MOD_lineart.h:259
LineartEdge * intersection_managed
Definition: MOD_lineart.h:248
LineartStaticMemPool render_data_pool
Definition: MOD_lineart.h:231
double view_projection[4][4]
Definition: MOD_lineart.h:217
unsigned int crease_count
Definition: MOD_lineart.h:251
LineartEdge * material_managed
Definition: MOD_lineart.h:258
double camera_pos[3]
Definition: MOD_lineart.h:294
unsigned int contour_count
Definition: MOD_lineart.h:240
struct Collection * _source_collection
Definition: MOD_lineart.h:306
ListBase triangle_adjacent_pointers
Definition: MOD_lineart.h:227
LineartEdge * intersection_lines
Definition: MOD_lineart.h:249
float chaining_image_threshold
Definition: MOD_lineart.h:298
LineartEdge * crease_lines
Definition: MOD_lineart.h:254
float angle_splitting_threshold
Definition: MOD_lineart.h:299
LineartEdge * contours
Definition: MOD_lineart.h:244
struct Object * _source_object
Definition: MOD_lineart.h:307
ListBase vertex_buffer_pointers
Definition: MOD_lineart.h:222
LineartEdge * crease_managed
Definition: MOD_lineart.h:253
double view_vector[3]
Definition: MOD_lineart.h:236
LineartEdge * contour_managed
Definition: MOD_lineart.h:242
LineartEdge * material
Definition: MOD_lineart.h:344
LineartEdge * edge_mark_end
Definition: MOD_lineart.h:348
LineartEdge * intersection_end
Definition: MOD_lineart.h:339
LineartEdge * crease
Definition: MOD_lineart.h:341
LineartEdge * intersection
Definition: MOD_lineart.h:338
LineartEdge * material_end
Definition: MOD_lineart.h:345
LineartEdge * edge_mark
Definition: MOD_lineart.h:347
LineartEdge * contour_end
Definition: MOD_lineart.h:336
LineartEdge * crease_end
Definition: MOD_lineart.h:342
struct LineartRenderBuffer * rb
Definition: MOD_lineart.h:331
LineartEdge * contour
Definition: MOD_lineart.h:335
struct LineartEdge * e[3]
Definition: MOD_lineart.h:45
struct LineartEdge * testing_e[1]
Definition: MOD_lineart.h:76
struct LineartTriangle base
Definition: MOD_lineart.h:67
unsigned char flags
Definition: MOD_lineart.h:56
struct LinkNode * intersecting_verts
Definition: MOD_lineart.h:63
double gn[3]
Definition: MOD_lineart.h:52
unsigned char transparency_mask
Definition: MOD_lineart.h:55
struct LineartVert * v[3]
Definition: MOD_lineart.h:49
struct LineartTriangle * intersecting_with
Definition: MOD_lineart.h:132
double fbcoord[4]
Definition: MOD_lineart.h:114
double gloc[3]
Definition: MOD_lineart.h:113
void * data
Definition: DNA_listBase.h:42
struct LinkData * next
Definition: DNA_listBase.h:41
struct LinkNode * next
Definition: BLI_linklist.h:39
void * first
Definition: DNA_listBase.h:47
unsigned char transparency_mask
struct MaterialLineArt lineart
struct BMEditMesh * edit_mesh
struct MDeformVert * dvert
int totvert
ustring name
Definition: node.h:174
ListBase defbase
ObjectLineArt lineart
float obmat[4][4]
void * data
struct Collection * master_collection
struct RenderData r
struct Object * camera
struct MDeformVert * dvert
double PIL_check_seconds_timer(void)
Definition: time.c:80
ccl_device_inline float2 fabs(const float2 &a)
#define G(x, y, z)
function< void(void)> TaskRunFunction
Definition: util_task.h:29