LineArt: Clean up LineartRenderBuffer.
This patch does code clean ups in `LineartRenderBuffer` because it's grown kinda big and we need better way to organize those variables inside. Reviewed By: Sebastian Parborg (zeddb) Differential Revision: https://developer.blender.org/D15172
This commit is contained in:
@@ -210,128 +210,126 @@ typedef struct LineartPendingEdges {
|
||||
int next;
|
||||
} LineartPendingEdges;
|
||||
|
||||
typedef struct LineartRenderBuffer {
|
||||
struct LineartRenderBuffer *prev, *next;
|
||||
|
||||
int thread_count;
|
||||
typedef struct LineartData {
|
||||
|
||||
int w, h;
|
||||
int tile_size_w, tile_size_h;
|
||||
int tile_count_x, tile_count_y;
|
||||
double width_per_tile, height_per_tile;
|
||||
double view_projection[4][4];
|
||||
double view[4][4];
|
||||
int thread_count;
|
||||
int sizeof_triangle;
|
||||
|
||||
float overscan;
|
||||
LineartStaticMemPool render_data_pool;
|
||||
/* A pointer to LineartCache::chain_data_pool, which acts as a cache for edge chains. */
|
||||
LineartStaticMemPool *chain_data_pool;
|
||||
|
||||
struct LineartBoundingArea *initial_bounding_areas;
|
||||
unsigned int bounding_area_count;
|
||||
struct _qtree {
|
||||
|
||||
/* When splitting bounding areas, if there's an ortho camera placed at a straight angle, there
|
||||
* will be a lot of triangles aligned in line which can not be separated by continue subdividing
|
||||
* the tile. So we set a strict limit when using ortho camera. See eLineArtTileRecursiveLimit. */
|
||||
int tile_recursive_level;
|
||||
int count_x, count_y;
|
||||
double tile_width, tile_height;
|
||||
|
||||
ListBase vertex_buffer_pointers;
|
||||
ListBase line_buffer_pointers;
|
||||
ListBase triangle_buffer_pointers;
|
||||
/* When splitting bounding areas, if there's an ortho camera placed at a straight angle, there
|
||||
* will be a lot of triangles aligned in line which can not be separated by continue
|
||||
* subdividing the tile. So we set a strict limit when using ortho camera. See
|
||||
* eLineArtTileRecursiveLimit. */
|
||||
int recursive_level;
|
||||
|
||||
struct LineartBoundingArea *initials;
|
||||
|
||||
unsigned int tile_count;
|
||||
|
||||
} qtree;
|
||||
|
||||
struct _geom {
|
||||
|
||||
ListBase vertex_buffer_pointers;
|
||||
ListBase line_buffer_pointers;
|
||||
ListBase triangle_buffer_pointers;
|
||||
|
||||
/** This one's memory is not from main pool and is free()ed after culling stage. */
|
||||
ListBase triangle_adjacent_pointers;
|
||||
|
||||
ListBase intersecting_vertex_buffer;
|
||||
|
||||
} geom;
|
||||
|
||||
struct _conf {
|
||||
|
||||
double view_projection[4][4];
|
||||
double view[4][4];
|
||||
|
||||
float overscan;
|
||||
|
||||
int max_occlusion_level;
|
||||
double crease_angle;
|
||||
double crease_cos;
|
||||
|
||||
int draw_material_preview;
|
||||
double material_transparency;
|
||||
|
||||
bool use_contour;
|
||||
bool use_crease;
|
||||
bool use_material;
|
||||
bool use_edge_marks;
|
||||
bool use_intersections;
|
||||
bool use_loose;
|
||||
bool fuzzy_intersections;
|
||||
bool fuzzy_everything;
|
||||
bool allow_boundaries;
|
||||
bool allow_overlapping_edges;
|
||||
bool allow_duplicated_types;
|
||||
bool remove_doubles;
|
||||
bool use_loose_as_contour;
|
||||
bool use_loose_edge_chain;
|
||||
bool use_geometry_space_chain;
|
||||
bool use_image_boundary_trimming;
|
||||
bool use_back_face_culling;
|
||||
|
||||
bool filter_face_mark;
|
||||
bool filter_face_mark_invert;
|
||||
bool filter_face_mark_boundaries;
|
||||
bool filter_face_mark_keep_contour;
|
||||
|
||||
bool force_crease;
|
||||
bool sharp_as_crease;
|
||||
|
||||
bool chain_preserve_details;
|
||||
|
||||
/* Keep an copy of these data so when line art is running it's self-contained. */
|
||||
bool cam_is_persp;
|
||||
float cam_obmat[4][4];
|
||||
double camera_pos[3];
|
||||
double active_camera_pos[3]; /* Stroke offset calculation may use active or selected camera. */
|
||||
double near_clip, far_clip;
|
||||
float shift_x, shift_y;
|
||||
float crease_threshold;
|
||||
float chaining_image_threshold;
|
||||
float angle_splitting_threshold;
|
||||
|
||||
float chain_smooth_tolerance;
|
||||
|
||||
double view_vector[3];
|
||||
|
||||
} conf;
|
||||
|
||||
LineartElementLinkNode *isect_scheduled_up_to;
|
||||
int isect_scheduled_up_to_index;
|
||||
|
||||
/** This one's memory is not from main pool and is free()ed after culling stage. */
|
||||
ListBase triangle_adjacent_pointers;
|
||||
|
||||
ListBase intersecting_vertex_buffer;
|
||||
/** Use the one comes with Line Art. */
|
||||
LineartStaticMemPool render_data_pool;
|
||||
ListBase wasted_cuts;
|
||||
SpinLock lock_cuts;
|
||||
|
||||
/* This is just a pointer to LineartCache::chain_data_pool, which acts as a cache for line
|
||||
* chains. */
|
||||
LineartStaticMemPool *chain_data_pool;
|
||||
|
||||
/* Render status */
|
||||
double view_vector[3];
|
||||
|
||||
int triangle_size;
|
||||
|
||||
/* Note: Data inside #pending_edges are allocated with MEM_xxx call instead of in pool. */
|
||||
struct LineartPendingEdges pending_edges;
|
||||
int scheduled_count;
|
||||
|
||||
ListBase chains;
|
||||
|
||||
/* For managing calculation tasks for multiple threads. */
|
||||
ListBase wasted_cuts;
|
||||
SpinLock lock_cuts;
|
||||
SpinLock lock_task;
|
||||
|
||||
/* settings */
|
||||
|
||||
int max_occlusion_level;
|
||||
double crease_angle;
|
||||
double crease_cos;
|
||||
|
||||
int draw_material_preview;
|
||||
double material_transparency;
|
||||
|
||||
bool use_contour;
|
||||
bool use_crease;
|
||||
bool use_material;
|
||||
bool use_edge_marks;
|
||||
bool use_intersections;
|
||||
bool use_loose;
|
||||
bool fuzzy_intersections;
|
||||
bool fuzzy_everything;
|
||||
bool allow_boundaries;
|
||||
bool allow_overlapping_edges;
|
||||
bool allow_duplicated_types;
|
||||
bool remove_doubles;
|
||||
bool use_loose_as_contour;
|
||||
bool use_loose_edge_chain;
|
||||
bool use_geometry_space_chain;
|
||||
bool use_image_boundary_trimming;
|
||||
bool use_back_face_culling;
|
||||
|
||||
bool filter_face_mark;
|
||||
bool filter_face_mark_invert;
|
||||
bool filter_face_mark_boundaries;
|
||||
bool filter_face_mark_keep_contour;
|
||||
|
||||
bool force_crease;
|
||||
bool sharp_as_crease;
|
||||
|
||||
bool chain_preserve_details;
|
||||
|
||||
/* Keep an copy of these data so when line art is running it's self-contained. */
|
||||
bool cam_is_persp;
|
||||
float cam_obmat[4][4];
|
||||
double camera_pos[3];
|
||||
double active_camera_pos[3]; /* Stroke offset calculation may use active or selected camera. */
|
||||
double near_clip, far_clip;
|
||||
float shift_x, shift_y;
|
||||
float crease_threshold;
|
||||
float chaining_image_threshold;
|
||||
float angle_splitting_threshold;
|
||||
|
||||
float chain_smooth_tolerance;
|
||||
|
||||
/* FIXME(Yiming): Temporary solution for speeding up calculation by not including lines that
|
||||
* are not in the selected source. This will not be needed after we have a proper scene-wise
|
||||
* cache running because multiple modifiers can then select results from that without further
|
||||
* calculation. */
|
||||
int _source_type;
|
||||
struct Collection *_source_collection;
|
||||
struct Object *_source_object;
|
||||
|
||||
} LineartRenderBuffer;
|
||||
} LineartData;
|
||||
|
||||
typedef struct LineartCache {
|
||||
/** Separate memory pool for chain data, this goes to the cache, so when we free the main pool,
|
||||
* chains will still be available. */
|
||||
LineartStaticMemPool chain_data_pool;
|
||||
|
||||
/** A copy of rb->chains so we have that data available after rb has been destroyed. */
|
||||
/** A copy of ld->chains so we have that data available after ld has been destroyed. */
|
||||
ListBase chains;
|
||||
|
||||
/** Cache only contains edge types specified in this variable. */
|
||||
@@ -361,13 +359,13 @@ typedef enum eLineartTriangleFlags {
|
||||
#define LRT_THREAD_EDGE_COUNT 1000
|
||||
|
||||
typedef struct LineartRenderTaskInfo {
|
||||
struct LineartRenderBuffer *rb;
|
||||
struct LineartData *ld;
|
||||
|
||||
int thread_id;
|
||||
|
||||
/**
|
||||
* #pending_edges here only stores a reference to a portion in
|
||||
* LineartRenderbuffer::pending_edges, assigned by the occlusion scheduler.
|
||||
* LineartData::pending_edges, assigned by the occlusion scheduler.
|
||||
*/
|
||||
struct LineartPendingEdges pending_edges;
|
||||
|
||||
@@ -393,7 +391,7 @@ typedef struct LineartObjectInfo {
|
||||
} LineartObjectInfo;
|
||||
|
||||
typedef struct LineartObjectLoadTaskInfo {
|
||||
struct LineartRenderBuffer *rb;
|
||||
struct LineartData *ld;
|
||||
int thread_id;
|
||||
/* LinkNode styled list */
|
||||
LineartObjectInfo *pending;
|
||||
@@ -632,30 +630,28 @@ BLI_INLINE int lineart_intersect_seg_seg(const double *a1,
|
||||
|
||||
struct Depsgraph;
|
||||
struct LineartGpencilModifierData;
|
||||
struct LineartRenderBuffer;
|
||||
struct LineartData;
|
||||
struct Scene;
|
||||
|
||||
void MOD_lineart_destroy_render_data(struct LineartGpencilModifierData *lmd);
|
||||
|
||||
void MOD_lineart_chain_feature_lines(LineartRenderBuffer *rb);
|
||||
void MOD_lineart_chain_split_for_fixed_occlusion(LineartRenderBuffer *rb);
|
||||
void MOD_lineart_chain_feature_lines(LineartData *ld);
|
||||
void MOD_lineart_chain_split_for_fixed_occlusion(LineartData *ld);
|
||||
/**
|
||||
* This function only connects two different chains. It will not do any clean up or smart chaining.
|
||||
* So no: removing overlapping chains, removal of short isolated segments, and no loop reduction is
|
||||
* implemented yet.
|
||||
*/
|
||||
void MOD_lineart_chain_connect(LineartRenderBuffer *rb);
|
||||
void MOD_lineart_chain_discard_short(LineartRenderBuffer *rb, float threshold);
|
||||
void MOD_lineart_chain_clip_at_border(LineartRenderBuffer *rb);
|
||||
void MOD_lineart_chain_connect(LineartData *ld);
|
||||
void MOD_lineart_chain_discard_short(LineartData *ld, float threshold);
|
||||
void MOD_lineart_chain_clip_at_border(LineartData *ld);
|
||||
/**
|
||||
* This should always be the last stage!, see the end of
|
||||
* #MOD_lineart_chain_split_for_fixed_occlusion().
|
||||
*/
|
||||
void MOD_lineart_chain_split_angle(LineartRenderBuffer *rb, float angle_threshold_rad);
|
||||
void MOD_lineart_smooth_chains(LineartRenderBuffer *rb, float tolerance);
|
||||
void MOD_lineart_chain_offset_towards_camera(LineartRenderBuffer *rb,
|
||||
float dist,
|
||||
bool use_custom_camera);
|
||||
void MOD_lineart_chain_split_angle(LineartData *ld, float angle_threshold_rad);
|
||||
void MOD_lineart_smooth_chains(LineartData *ld, float tolerance);
|
||||
void MOD_lineart_chain_offset_towards_camera(LineartData *ld, float dist, bool use_custom_camera);
|
||||
|
||||
int MOD_lineart_chain_count(const LineartEdgeChain *ec);
|
||||
void MOD_lineart_chain_clear_picked_flag(LineartCache *lc);
|
||||
@@ -675,14 +671,12 @@ struct Scene;
|
||||
/**
|
||||
* This only gets initial "biggest" tile.
|
||||
*/
|
||||
LineartBoundingArea *MOD_lineart_get_parent_bounding_area(LineartRenderBuffer *rb,
|
||||
double x,
|
||||
double y);
|
||||
LineartBoundingArea *MOD_lineart_get_parent_bounding_area(LineartData *ld, double x, double y);
|
||||
|
||||
/**
|
||||
* Wrapper for more convenience.
|
||||
*/
|
||||
LineartBoundingArea *MOD_lineart_get_bounding_area(LineartRenderBuffer *rb, double x, double y);
|
||||
LineartBoundingArea *MOD_lineart_get_bounding_area(LineartData *ld, double x, double y);
|
||||
|
||||
struct bGPDframe;
|
||||
struct bGPDlayer;
|
||||
|
||||
@@ -60,12 +60,12 @@ static LineartEdge *lineart_line_get_connected(LineartBoundingArea *ba,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static LineartEdgeChain *lineart_chain_create(LineartRenderBuffer *rb)
|
||||
static LineartEdgeChain *lineart_chain_create(LineartData *ld)
|
||||
{
|
||||
LineartEdgeChain *ec;
|
||||
ec = lineart_mem_acquire(rb->chain_data_pool, sizeof(LineartEdgeChain));
|
||||
ec = lineart_mem_acquire(ld->chain_data_pool, sizeof(LineartEdgeChain));
|
||||
|
||||
BLI_addtail(&rb->chains, ec);
|
||||
BLI_addtail(&ld->chains, ec);
|
||||
|
||||
return ec;
|
||||
}
|
||||
@@ -85,7 +85,7 @@ static bool lineart_point_overlapping(LineartEdgeChainItem *eci,
|
||||
return false;
|
||||
}
|
||||
|
||||
static LineartEdgeChainItem *lineart_chain_append_point(LineartRenderBuffer *rb,
|
||||
static LineartEdgeChainItem *lineart_chain_append_point(LineartData *ld,
|
||||
LineartEdgeChain *ec,
|
||||
float *fbcoord,
|
||||
float *gpos,
|
||||
@@ -108,7 +108,7 @@ static LineartEdgeChainItem *lineart_chain_append_point(LineartRenderBuffer *rb,
|
||||
return old_eci;
|
||||
}
|
||||
|
||||
eci = lineart_mem_acquire(rb->chain_data_pool, sizeof(LineartEdgeChainItem));
|
||||
eci = lineart_mem_acquire(ld->chain_data_pool, sizeof(LineartEdgeChainItem));
|
||||
|
||||
copy_v4_v4(eci->pos, fbcoord);
|
||||
copy_v3_v3(eci->gpos, gpos);
|
||||
@@ -122,7 +122,7 @@ static LineartEdgeChainItem *lineart_chain_append_point(LineartRenderBuffer *rb,
|
||||
return eci;
|
||||
}
|
||||
|
||||
static LineartEdgeChainItem *lineart_chain_prepend_point(LineartRenderBuffer *rb,
|
||||
static LineartEdgeChainItem *lineart_chain_prepend_point(LineartData *ld,
|
||||
LineartEdgeChain *ec,
|
||||
float *fbcoord,
|
||||
float *gpos,
|
||||
@@ -138,7 +138,7 @@ static LineartEdgeChainItem *lineart_chain_prepend_point(LineartRenderBuffer *rb
|
||||
return ec->chain.first;
|
||||
}
|
||||
|
||||
eci = lineart_mem_acquire(rb->chain_data_pool, sizeof(LineartEdgeChainItem));
|
||||
eci = lineart_mem_acquire(ld->chain_data_pool, sizeof(LineartEdgeChainItem));
|
||||
|
||||
copy_v4_v4(eci->pos, fbcoord);
|
||||
copy_v3_v3(eci->gpos, gpos);
|
||||
@@ -152,7 +152,7 @@ static LineartEdgeChainItem *lineart_chain_prepend_point(LineartRenderBuffer *rb
|
||||
return eci;
|
||||
}
|
||||
|
||||
void MOD_lineart_chain_feature_lines(LineartRenderBuffer *rb)
|
||||
void MOD_lineart_chain_feature_lines(LineartData *ld)
|
||||
{
|
||||
LineartEdgeChain *ec;
|
||||
LineartEdgeChainItem *eci;
|
||||
@@ -181,7 +181,7 @@ void MOD_lineart_chain_feature_lines(LineartRenderBuffer *rb)
|
||||
|
||||
e->flags |= LRT_EDGE_FLAG_CHAIN_PICKED;
|
||||
|
||||
ec = lineart_chain_create(rb);
|
||||
ec = lineart_chain_create(ld);
|
||||
|
||||
/* One chain can only have one object_ref and intersection_mask,
|
||||
* so we assign them based on the first segment we found. */
|
||||
@@ -207,11 +207,11 @@ void MOD_lineart_chain_feature_lines(LineartRenderBuffer *rb)
|
||||
}
|
||||
|
||||
/* Step 1: grow left. */
|
||||
ba = MOD_lineart_get_bounding_area(rb, e->v1->fbcoord[0], e->v1->fbcoord[1]);
|
||||
ba = MOD_lineart_get_bounding_area(ld, e->v1->fbcoord[0], e->v1->fbcoord[1]);
|
||||
new_vt = e->v1;
|
||||
es = e->segments.first;
|
||||
VERT_COORD_TO_FLOAT(new_vt);
|
||||
lineart_chain_prepend_point(rb,
|
||||
lineart_chain_prepend_point(ld,
|
||||
ec,
|
||||
use_fbcoord,
|
||||
use_gpos,
|
||||
@@ -248,7 +248,7 @@ void MOD_lineart_chain_feature_lines(LineartRenderBuffer *rb)
|
||||
interp_v3_v3v3_db(gpos, new_e->v1->gloc, new_e->v2->gloc, global_at);
|
||||
use_fbcoord[3] = interpf(new_e->v2->fbcoord[3], new_e->v1->fbcoord[3], global_at);
|
||||
POS_TO_FLOAT(lpos, gpos)
|
||||
lineart_chain_prepend_point(rb,
|
||||
lineart_chain_prepend_point(ld,
|
||||
ec,
|
||||
use_fbcoord,
|
||||
use_gpos,
|
||||
@@ -274,7 +274,7 @@ void MOD_lineart_chain_feature_lines(LineartRenderBuffer *rb)
|
||||
interp_v3_v3v3_db(gpos, new_e->v1->gloc, new_e->v2->gloc, global_at);
|
||||
use_fbcoord[3] = interpf(new_e->v2->fbcoord[3], new_e->v1->fbcoord[3], global_at);
|
||||
POS_TO_FLOAT(lpos, gpos)
|
||||
lineart_chain_prepend_point(rb,
|
||||
lineart_chain_prepend_point(ld,
|
||||
ec,
|
||||
use_fbcoord,
|
||||
use_gpos,
|
||||
@@ -287,7 +287,7 @@ void MOD_lineart_chain_feature_lines(LineartRenderBuffer *rb)
|
||||
last_transparency = es->material_mask_bits;
|
||||
}
|
||||
VERT_COORD_TO_FLOAT(new_e->v2);
|
||||
lineart_chain_prepend_point(rb,
|
||||
lineart_chain_prepend_point(ld,
|
||||
ec,
|
||||
use_fbcoord,
|
||||
use_gpos,
|
||||
@@ -297,7 +297,7 @@ void MOD_lineart_chain_feature_lines(LineartRenderBuffer *rb)
|
||||
last_transparency,
|
||||
new_e->v2->index);
|
||||
}
|
||||
ba = MOD_lineart_get_bounding_area(rb, new_vt->fbcoord[0], new_vt->fbcoord[1]);
|
||||
ba = MOD_lineart_get_bounding_area(ld, new_vt->fbcoord[0], new_vt->fbcoord[1]);
|
||||
}
|
||||
|
||||
/* Restore normal value. */
|
||||
@@ -328,7 +328,7 @@ void MOD_lineart_chain_feature_lines(LineartRenderBuffer *rb)
|
||||
interp_v3_v3v3_db(gpos, e->v1->gloc, e->v2->gloc, global_at);
|
||||
use_fbcoord[3] = interpf(e->v2->fbcoord[3], e->v1->fbcoord[3], global_at);
|
||||
POS_TO_FLOAT(lpos, gpos)
|
||||
lineart_chain_append_point(rb,
|
||||
lineart_chain_append_point(ld,
|
||||
ec,
|
||||
use_fbcoord,
|
||||
use_gpos,
|
||||
@@ -341,7 +341,7 @@ void MOD_lineart_chain_feature_lines(LineartRenderBuffer *rb)
|
||||
last_transparency = es->material_mask_bits;
|
||||
}
|
||||
VERT_COORD_TO_FLOAT(e->v2)
|
||||
lineart_chain_append_point(rb,
|
||||
lineart_chain_append_point(ld,
|
||||
ec,
|
||||
use_fbcoord,
|
||||
use_gpos,
|
||||
@@ -352,7 +352,7 @@ void MOD_lineart_chain_feature_lines(LineartRenderBuffer *rb)
|
||||
e->v2->index);
|
||||
|
||||
/* Step 3: grow right. */
|
||||
ba = MOD_lineart_get_bounding_area(rb, e->v2->fbcoord[0], e->v2->fbcoord[1]);
|
||||
ba = MOD_lineart_get_bounding_area(ld, e->v2->fbcoord[0], e->v2->fbcoord[1]);
|
||||
new_vt = e->v2;
|
||||
while (ba && (new_e = lineart_line_get_connected(
|
||||
ba, new_vt, &new_vt, e->flags, e->intersection_mask))) {
|
||||
@@ -394,7 +394,7 @@ void MOD_lineart_chain_feature_lines(LineartRenderBuffer *rb)
|
||||
last_occlusion = es->prev ? es->prev->occlusion : last_occlusion;
|
||||
last_transparency = es->prev ? es->prev->material_mask_bits : last_transparency;
|
||||
POS_TO_FLOAT(lpos, gpos)
|
||||
lineart_chain_append_point(rb,
|
||||
lineart_chain_append_point(ld,
|
||||
ec,
|
||||
use_fbcoord,
|
||||
use_gpos,
|
||||
@@ -420,7 +420,7 @@ void MOD_lineart_chain_feature_lines(LineartRenderBuffer *rb)
|
||||
interp_v3_v3v3_db(gpos, new_e->v1->gloc, new_e->v2->gloc, global_at);
|
||||
use_fbcoord[3] = interpf(new_e->v2->fbcoord[3], new_e->v1->fbcoord[3], global_at);
|
||||
POS_TO_FLOAT(lpos, gpos)
|
||||
lineart_chain_append_point(rb,
|
||||
lineart_chain_append_point(ld,
|
||||
ec,
|
||||
use_fbcoord,
|
||||
use_gpos,
|
||||
@@ -433,7 +433,7 @@ void MOD_lineart_chain_feature_lines(LineartRenderBuffer *rb)
|
||||
last_transparency = es->material_mask_bits;
|
||||
}
|
||||
VERT_COORD_TO_FLOAT(new_e->v2)
|
||||
lineart_chain_append_point(rb,
|
||||
lineart_chain_append_point(ld,
|
||||
ec,
|
||||
use_fbcoord,
|
||||
use_gpos,
|
||||
@@ -443,9 +443,9 @@ void MOD_lineart_chain_feature_lines(LineartRenderBuffer *rb)
|
||||
last_transparency,
|
||||
new_e->v2->index);
|
||||
}
|
||||
ba = MOD_lineart_get_bounding_area(rb, new_vt->fbcoord[0], new_vt->fbcoord[1]);
|
||||
ba = MOD_lineart_get_bounding_area(ld, new_vt->fbcoord[0], new_vt->fbcoord[1]);
|
||||
}
|
||||
if (rb->fuzzy_everything) {
|
||||
if (ld->conf.fuzzy_everything) {
|
||||
ec->type = LRT_EDGE_FLAG_CONTOUR;
|
||||
}
|
||||
else {
|
||||
@@ -455,7 +455,7 @@ void MOD_lineart_chain_feature_lines(LineartRenderBuffer *rb)
|
||||
LRT_ITER_ALL_LINES_END
|
||||
}
|
||||
|
||||
static LineartBoundingArea *lineart_bounding_area_get_eci_recursive(LineartRenderBuffer *rb,
|
||||
static LineartBoundingArea *lineart_bounding_area_get_eci_recursive(LineartData *ld,
|
||||
LineartBoundingArea *root,
|
||||
LineartEdgeChainItem *eci)
|
||||
{
|
||||
@@ -468,32 +468,32 @@ static LineartBoundingArea *lineart_bounding_area_get_eci_recursive(LineartRende
|
||||
ba.l <= eci->pos[0] && ba.r >= eci->pos[0] && ba.b <= eci->pos[1] && ba.u >= eci->pos[1]
|
||||
|
||||
if (IN_BOUND(ch[0], eci)) {
|
||||
return lineart_bounding_area_get_eci_recursive(rb, &ch[0], eci);
|
||||
return lineart_bounding_area_get_eci_recursive(ld, &ch[0], eci);
|
||||
}
|
||||
if (IN_BOUND(ch[1], eci)) {
|
||||
return lineart_bounding_area_get_eci_recursive(rb, &ch[1], eci);
|
||||
return lineart_bounding_area_get_eci_recursive(ld, &ch[1], eci);
|
||||
}
|
||||
if (IN_BOUND(ch[2], eci)) {
|
||||
return lineart_bounding_area_get_eci_recursive(rb, &ch[2], eci);
|
||||
return lineart_bounding_area_get_eci_recursive(ld, &ch[2], eci);
|
||||
}
|
||||
if (IN_BOUND(ch[3], eci)) {
|
||||
return lineart_bounding_area_get_eci_recursive(rb, &ch[3], eci);
|
||||
return lineart_bounding_area_get_eci_recursive(ld, &ch[3], eci);
|
||||
}
|
||||
#undef IN_BOUND
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static LineartBoundingArea *lineart_bounding_area_get_end_point(LineartRenderBuffer *rb,
|
||||
static LineartBoundingArea *lineart_bounding_area_get_end_point(LineartData *ld,
|
||||
LineartEdgeChainItem *eci)
|
||||
{
|
||||
if (!eci) {
|
||||
return NULL;
|
||||
}
|
||||
LineartBoundingArea *root = MOD_lineart_get_parent_bounding_area(rb, eci->pos[0], eci->pos[1]);
|
||||
LineartBoundingArea *root = MOD_lineart_get_parent_bounding_area(ld, eci->pos[0], eci->pos[1]);
|
||||
if (root == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
return lineart_bounding_area_get_eci_recursive(rb, root, eci);
|
||||
return lineart_bounding_area_get_eci_recursive(ld, root, eci);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -502,14 +502,14 @@ static LineartBoundingArea *lineart_bounding_area_get_end_point(LineartRenderBuf
|
||||
* areas, this happens either when 1) the geometry is way too dense, or 2) the chaining threshold
|
||||
* is too big that it covers multiple small bounding areas.
|
||||
*/
|
||||
static void lineart_bounding_area_link_point_recursive(LineartRenderBuffer *rb,
|
||||
static void lineart_bounding_area_link_point_recursive(LineartData *ld,
|
||||
LineartBoundingArea *root,
|
||||
LineartEdgeChain *ec,
|
||||
LineartEdgeChainItem *eci)
|
||||
{
|
||||
if (root->child == NULL) {
|
||||
LineartChainRegisterEntry *cre = lineart_list_append_pointer_pool_sized(
|
||||
&root->linked_chains, &rb->render_data_pool, ec, sizeof(LineartChainRegisterEntry));
|
||||
&root->linked_chains, &ld->render_data_pool, ec, sizeof(LineartChainRegisterEntry));
|
||||
|
||||
cre->eci = eci;
|
||||
|
||||
@@ -524,34 +524,34 @@ static void lineart_bounding_area_link_point_recursive(LineartRenderBuffer *rb,
|
||||
ba.l <= eci->pos[0] && ba.r >= eci->pos[0] && ba.b <= eci->pos[1] && ba.u >= eci->pos[1]
|
||||
|
||||
if (IN_BOUND(ch[0], eci)) {
|
||||
lineart_bounding_area_link_point_recursive(rb, &ch[0], ec, eci);
|
||||
lineart_bounding_area_link_point_recursive(ld, &ch[0], ec, eci);
|
||||
}
|
||||
else if (IN_BOUND(ch[1], eci)) {
|
||||
lineart_bounding_area_link_point_recursive(rb, &ch[1], ec, eci);
|
||||
lineart_bounding_area_link_point_recursive(ld, &ch[1], ec, eci);
|
||||
}
|
||||
else if (IN_BOUND(ch[2], eci)) {
|
||||
lineart_bounding_area_link_point_recursive(rb, &ch[2], ec, eci);
|
||||
lineart_bounding_area_link_point_recursive(ld, &ch[2], ec, eci);
|
||||
}
|
||||
else if (IN_BOUND(ch[3], eci)) {
|
||||
lineart_bounding_area_link_point_recursive(rb, &ch[3], ec, eci);
|
||||
lineart_bounding_area_link_point_recursive(ld, &ch[3], ec, eci);
|
||||
}
|
||||
|
||||
#undef IN_BOUND
|
||||
}
|
||||
}
|
||||
|
||||
static void lineart_bounding_area_link_chain(LineartRenderBuffer *rb, LineartEdgeChain *ec)
|
||||
static void lineart_bounding_area_link_chain(LineartData *ld, LineartEdgeChain *ec)
|
||||
{
|
||||
LineartEdgeChainItem *pl = ec->chain.first;
|
||||
LineartEdgeChainItem *pr = ec->chain.last;
|
||||
LineartBoundingArea *ba1 = MOD_lineart_get_parent_bounding_area(rb, pl->pos[0], pl->pos[1]);
|
||||
LineartBoundingArea *ba2 = MOD_lineart_get_parent_bounding_area(rb, pr->pos[0], pr->pos[1]);
|
||||
LineartBoundingArea *ba1 = MOD_lineart_get_parent_bounding_area(ld, pl->pos[0], pl->pos[1]);
|
||||
LineartBoundingArea *ba2 = MOD_lineart_get_parent_bounding_area(ld, pr->pos[0], pr->pos[1]);
|
||||
|
||||
if (ba1) {
|
||||
lineart_bounding_area_link_point_recursive(rb, ba1, ec, pl);
|
||||
lineart_bounding_area_link_point_recursive(ld, ba1, ec, pl);
|
||||
}
|
||||
if (ba2) {
|
||||
lineart_bounding_area_link_point_recursive(rb, ba2, ec, pr);
|
||||
lineart_bounding_area_link_point_recursive(ld, ba2, ec, pr);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -606,21 +606,21 @@ static bool lineart_chain_fix_ambiguous_segments(LineartEdgeChain *ec,
|
||||
return false;
|
||||
}
|
||||
|
||||
void MOD_lineart_chain_split_for_fixed_occlusion(LineartRenderBuffer *rb)
|
||||
void MOD_lineart_chain_split_for_fixed_occlusion(LineartData *ld)
|
||||
{
|
||||
LineartEdgeChain *ec, *new_ec;
|
||||
LineartEdgeChainItem *eci, *next_eci;
|
||||
ListBase swap = {0};
|
||||
|
||||
swap.first = rb->chains.first;
|
||||
swap.last = rb->chains.last;
|
||||
swap.first = ld->chains.first;
|
||||
swap.last = ld->chains.last;
|
||||
|
||||
rb->chains.last = rb->chains.first = NULL;
|
||||
ld->chains.last = ld->chains.first = NULL;
|
||||
|
||||
int loop_id = 0;
|
||||
while ((ec = BLI_pophead(&swap)) != NULL) {
|
||||
ec->next = ec->prev = NULL;
|
||||
BLI_addtail(&rb->chains, ec);
|
||||
BLI_addtail(&ld->chains, ec);
|
||||
|
||||
ec->loop_id = loop_id;
|
||||
loop_id++;
|
||||
@@ -639,8 +639,8 @@ void MOD_lineart_chain_split_for_fixed_occlusion(LineartRenderBuffer *rb)
|
||||
}
|
||||
if (lineart_chain_fix_ambiguous_segments(ec,
|
||||
eci->prev,
|
||||
rb->chaining_image_threshold,
|
||||
rb->chain_preserve_details,
|
||||
ld->conf.chaining_image_threshold,
|
||||
ld->conf.chain_preserve_details,
|
||||
&next_eci)) {
|
||||
continue;
|
||||
}
|
||||
@@ -653,7 +653,7 @@ void MOD_lineart_chain_split_for_fixed_occlusion(LineartRenderBuffer *rb)
|
||||
/* No need to split at the last point anyway. */
|
||||
break;
|
||||
}
|
||||
new_ec = lineart_chain_create(rb);
|
||||
new_ec = lineart_chain_create(ld);
|
||||
new_ec->chain.first = eci;
|
||||
new_ec->chain.last = ec->chain.last;
|
||||
new_ec->loop_id = loop_id;
|
||||
@@ -662,7 +662,7 @@ void MOD_lineart_chain_split_for_fixed_occlusion(LineartRenderBuffer *rb)
|
||||
eci->prev = 0;
|
||||
|
||||
/* End the previous one. */
|
||||
lineart_chain_append_point(rb,
|
||||
lineart_chain_append_point(ld,
|
||||
ec,
|
||||
eci->pos,
|
||||
eci->gpos,
|
||||
@@ -683,16 +683,16 @@ void MOD_lineart_chain_split_for_fixed_occlusion(LineartRenderBuffer *rb)
|
||||
}
|
||||
}
|
||||
/* Get rid of those very short "zig-zag" lines that jumps around visibility. */
|
||||
MOD_lineart_chain_discard_short(rb, DBL_EDGE_LIM);
|
||||
LISTBASE_FOREACH (LineartEdgeChain *, iec, &rb->chains) {
|
||||
lineart_bounding_area_link_chain(rb, iec);
|
||||
MOD_lineart_chain_discard_short(ld, DBL_EDGE_LIM);
|
||||
LISTBASE_FOREACH (LineartEdgeChain *, iec, &ld->chains) {
|
||||
lineart_bounding_area_link_chain(ld, iec);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* NOTE: segment type (crease/material/contour...) is ambiguous after this.
|
||||
*/
|
||||
static void lineart_chain_connect(LineartRenderBuffer *UNUSED(rb),
|
||||
static void lineart_chain_connect(LineartData *UNUSED(ld),
|
||||
LineartEdgeChain *onto,
|
||||
LineartEdgeChain *sub,
|
||||
int reverse_1,
|
||||
@@ -742,7 +742,7 @@ static void lineart_chain_connect(LineartRenderBuffer *UNUSED(rb),
|
||||
}
|
||||
}
|
||||
|
||||
static LineartChainRegisterEntry *lineart_chain_get_closest_cre(LineartRenderBuffer *rb,
|
||||
static LineartChainRegisterEntry *lineart_chain_get_closest_cre(LineartData *ld,
|
||||
LineartBoundingArea *ba,
|
||||
LineartEdgeChain *ec,
|
||||
LineartEdgeChainItem *eci,
|
||||
@@ -761,8 +761,8 @@ static LineartChainRegisterEntry *lineart_chain_get_closest_cre(LineartRenderBuf
|
||||
* next one. */
|
||||
LISTBASE_FOREACH_MUTABLE (LineartChainRegisterEntry *, cre, &ba->linked_chains) {
|
||||
if (cre->ec->object_ref != ec->object_ref) {
|
||||
if (!rb->fuzzy_everything) {
|
||||
if (rb->fuzzy_intersections) {
|
||||
if (!ld->conf.fuzzy_everything) {
|
||||
if (ld->conf.fuzzy_intersections) {
|
||||
/* If none of those are intersection lines... */
|
||||
if ((!(cre->ec->type & LRT_EDGE_FLAG_INTERSECTION)) &&
|
||||
(!(ec->type & LRT_EDGE_FLAG_INTERSECTION))) {
|
||||
@@ -782,9 +782,9 @@ static LineartChainRegisterEntry *lineart_chain_get_closest_cre(LineartRenderBuf
|
||||
(cre->ec->intersection_mask != isec_mask)) {
|
||||
continue;
|
||||
}
|
||||
if (!rb->fuzzy_everything) {
|
||||
if (!ld->conf.fuzzy_everything) {
|
||||
if (cre->ec->type != ec->type) {
|
||||
if (rb->fuzzy_intersections) {
|
||||
if (ld->conf.fuzzy_intersections) {
|
||||
if (!(cre->ec->type == LRT_EDGE_FLAG_INTERSECTION ||
|
||||
ec->type == LRT_EDGE_FLAG_INTERSECTION)) {
|
||||
continue; /* Fuzzy intersections but no intersection line found. */
|
||||
@@ -796,8 +796,8 @@ static LineartChainRegisterEntry *lineart_chain_get_closest_cre(LineartRenderBuf
|
||||
}
|
||||
}
|
||||
|
||||
float new_len = rb->use_geometry_space_chain ? len_v3v3(cre->eci->gpos, eci->gpos) :
|
||||
len_v2v2(cre->eci->pos, eci->pos);
|
||||
float new_len = ld->conf.use_geometry_space_chain ? len_v3v3(cre->eci->gpos, eci->gpos) :
|
||||
len_v2v2(cre->eci->pos, eci->pos);
|
||||
/* Even if the vertex is not from the same contour loop, we try to chain it still if the
|
||||
* distance is small enough. This way we can better chain smaller loops and smooth them out
|
||||
* later. */
|
||||
@@ -817,9 +817,9 @@ static LineartChainRegisterEntry *lineart_chain_get_closest_cre(LineartRenderBuf
|
||||
|
||||
#define LRT_TEST_ADJACENT_AREAS(dist_to, list) \
|
||||
if (dist_to < dist && dist_to > 0) { \
|
||||
LISTBASE_FOREACH (LinkData *, ld, list) { \
|
||||
LineartBoundingArea *sba = (LineartBoundingArea *)ld->data; \
|
||||
adjacent_closest = lineart_chain_get_closest_cre(rb, \
|
||||
LISTBASE_FOREACH (LinkData *, link, list) { \
|
||||
LineartBoundingArea *sba = (LineartBoundingArea *)link->data; \
|
||||
adjacent_closest = lineart_chain_get_closest_cre(ld, \
|
||||
sba, \
|
||||
ec, \
|
||||
eci, \
|
||||
@@ -848,36 +848,36 @@ static LineartChainRegisterEntry *lineart_chain_get_closest_cre(LineartRenderBuf
|
||||
return closest_cre;
|
||||
}
|
||||
|
||||
void MOD_lineart_chain_connect(LineartRenderBuffer *rb)
|
||||
void MOD_lineart_chain_connect(LineartData *ld)
|
||||
{
|
||||
LineartEdgeChain *ec;
|
||||
LineartEdgeChainItem *eci_l, *eci_r;
|
||||
LineartBoundingArea *ba_l, *ba_r;
|
||||
LineartChainRegisterEntry *closest_cre_l, *closest_cre_r, *closest_cre;
|
||||
float dist = rb->chaining_image_threshold;
|
||||
float dist = ld->conf.chaining_image_threshold;
|
||||
float dist_l, dist_r;
|
||||
int occlusion, reverse_main, loop_id;
|
||||
unsigned char material_mask_bits, isec_mask;
|
||||
ListBase swap = {0};
|
||||
|
||||
if (rb->chaining_image_threshold < 0.0001) {
|
||||
if (ld->conf.chaining_image_threshold < 0.0001) {
|
||||
return;
|
||||
}
|
||||
|
||||
swap.first = rb->chains.first;
|
||||
swap.last = rb->chains.last;
|
||||
swap.first = ld->chains.first;
|
||||
swap.last = ld->chains.last;
|
||||
|
||||
rb->chains.last = rb->chains.first = NULL;
|
||||
ld->chains.last = ld->chains.first = NULL;
|
||||
|
||||
while ((ec = BLI_pophead(&swap)) != NULL) {
|
||||
ec->next = ec->prev = NULL;
|
||||
if (ec->picked) {
|
||||
continue;
|
||||
}
|
||||
BLI_addtail(&rb->chains, ec);
|
||||
BLI_addtail(&ld->chains, ec);
|
||||
loop_id = ec->loop_id;
|
||||
|
||||
if (ec->type == LRT_EDGE_FLAG_LOOSE && (!rb->use_loose_edge_chain)) {
|
||||
if (ec->type == LRT_EDGE_FLAG_LOOSE && (!ld->conf.use_loose_edge_chain)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -887,9 +887,9 @@ void MOD_lineart_chain_connect(LineartRenderBuffer *rb)
|
||||
|
||||
eci_l = ec->chain.first;
|
||||
eci_r = ec->chain.last;
|
||||
while ((ba_l = lineart_bounding_area_get_end_point(rb, eci_l)) &&
|
||||
(ba_r = lineart_bounding_area_get_end_point(rb, eci_r))) {
|
||||
closest_cre_l = lineart_chain_get_closest_cre(rb,
|
||||
while ((ba_l = lineart_bounding_area_get_end_point(ld, eci_l)) &&
|
||||
(ba_r = lineart_bounding_area_get_end_point(ld, eci_r))) {
|
||||
closest_cre_l = lineart_chain_get_closest_cre(ld,
|
||||
ba_l,
|
||||
ec,
|
||||
eci_l,
|
||||
@@ -900,7 +900,7 @@ void MOD_lineart_chain_connect(LineartRenderBuffer *rb)
|
||||
dist,
|
||||
&dist_l,
|
||||
NULL);
|
||||
closest_cre_r = lineart_chain_get_closest_cre(rb,
|
||||
closest_cre_r = lineart_chain_get_closest_cre(ld,
|
||||
ba_r,
|
||||
ec,
|
||||
eci_r,
|
||||
@@ -936,10 +936,10 @@ void MOD_lineart_chain_connect(LineartRenderBuffer *rb)
|
||||
closest_cre->picked = 1;
|
||||
closest_cre->ec->picked = 1;
|
||||
if (closest_cre->is_left) {
|
||||
lineart_chain_connect(rb, ec, closest_cre->ec, reverse_main, 0);
|
||||
lineart_chain_connect(ld, ec, closest_cre->ec, reverse_main, 0);
|
||||
}
|
||||
else {
|
||||
lineart_chain_connect(rb, ec, closest_cre->ec, reverse_main, 1);
|
||||
lineart_chain_connect(ld, ec, closest_cre->ec, reverse_main, 1);
|
||||
}
|
||||
BLI_remlink(&swap, closest_cre->ec);
|
||||
eci_l = ec->chain.first;
|
||||
@@ -969,13 +969,13 @@ float MOD_lineart_chain_compute_length(LineartEdgeChain *ec)
|
||||
return offset_accum;
|
||||
}
|
||||
|
||||
void MOD_lineart_chain_discard_short(LineartRenderBuffer *rb, const float threshold)
|
||||
void MOD_lineart_chain_discard_short(LineartData *ld, const float threshold)
|
||||
{
|
||||
LineartEdgeChain *ec, *next_ec;
|
||||
for (ec = rb->chains.first; ec; ec = next_ec) {
|
||||
for (ec = ld->chains.first; ec; ec = next_ec) {
|
||||
next_ec = ec->next;
|
||||
if (MOD_lineart_chain_compute_length(ec) < threshold) {
|
||||
BLI_remlink(&rb->chains, ec);
|
||||
BLI_remlink(&ld->chains, ec);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -999,9 +999,9 @@ void MOD_lineart_chain_clear_picked_flag(LineartCache *lc)
|
||||
}
|
||||
}
|
||||
|
||||
void MOD_lineart_smooth_chains(LineartRenderBuffer *rb, float tolerance)
|
||||
void MOD_lineart_smooth_chains(LineartData *ld, float tolerance)
|
||||
{
|
||||
LISTBASE_FOREACH (LineartEdgeChain *, ec, &rb->chains) {
|
||||
LISTBASE_FOREACH (LineartEdgeChain *, ec, &ld->chains) {
|
||||
/* Go through the chain two times, once from each direction. */
|
||||
for (int times = 0; times < 2; times++) {
|
||||
for (LineartEdgeChainItem *eci = ec->chain.first, *next_eci = eci->next; eci;
|
||||
@@ -1067,7 +1067,7 @@ void MOD_lineart_smooth_chains(LineartRenderBuffer *rb, float tolerance)
|
||||
}
|
||||
}
|
||||
|
||||
static LineartEdgeChainItem *lineart_chain_create_crossing_point(LineartRenderBuffer *rb,
|
||||
static LineartEdgeChainItem *lineart_chain_create_crossing_point(LineartData *ld,
|
||||
LineartEdgeChainItem *eci_inside,
|
||||
LineartEdgeChainItem *eci_outside)
|
||||
{
|
||||
@@ -1097,7 +1097,7 @@ static LineartEdgeChainItem *lineart_chain_create_crossing_point(LineartRenderBu
|
||||
ratiof(eci1->pos[1], eci2->pos[1], isec[1]);
|
||||
float gratio = eci1->pos[3] * ratio / (ratio * eci1->pos[3] + (1 - ratio) * eci2->pos[3]);
|
||||
|
||||
LineartEdgeChainItem *eci = lineart_mem_acquire(rb->chain_data_pool,
|
||||
LineartEdgeChainItem *eci = lineart_mem_acquire(ld->chain_data_pool,
|
||||
sizeof(LineartEdgeChainItem));
|
||||
memcpy(eci, eci1, sizeof(LineartEdgeChainItem));
|
||||
interp_v3_v3v3(eci->gpos, eci1->gpos, eci2->gpos, gratio);
|
||||
@@ -1111,16 +1111,16 @@ static LineartEdgeChainItem *lineart_chain_create_crossing_point(LineartRenderBu
|
||||
((eci)->pos[0] >= -1.0f && (eci)->pos[0] <= 1.0f && (eci)->pos[1] >= -1.0f && \
|
||||
(eci)->pos[1] <= 1.0f)
|
||||
|
||||
void MOD_lineart_chain_clip_at_border(LineartRenderBuffer *rb)
|
||||
void MOD_lineart_chain_clip_at_border(LineartData *ld)
|
||||
{
|
||||
LineartEdgeChain *ec;
|
||||
LineartEdgeChainItem *eci, *next_eci, *prev_eci, *new_eci;
|
||||
bool is_inside, new_inside;
|
||||
ListBase swap = {0};
|
||||
swap.first = rb->chains.first;
|
||||
swap.last = rb->chains.last;
|
||||
swap.first = ld->chains.first;
|
||||
swap.last = ld->chains.last;
|
||||
|
||||
rb->chains.last = rb->chains.first = NULL;
|
||||
ld->chains.last = ld->chains.first = NULL;
|
||||
while ((ec = BLI_pophead(&swap)) != NULL) {
|
||||
bool ec_added = false;
|
||||
LineartEdgeChainItem *first_eci = (LineartEdgeChainItem *)ec->chain.first;
|
||||
@@ -1137,9 +1137,9 @@ void MOD_lineart_chain_clip_at_border(LineartRenderBuffer *rb)
|
||||
if ((new_inside = LRT_ECI_INSIDE(eci)) != is_inside) {
|
||||
if (new_inside == false) {
|
||||
/* Stroke goes out. */
|
||||
new_eci = lineart_chain_create_crossing_point(rb, prev_eci, eci);
|
||||
new_eci = lineart_chain_create_crossing_point(ld, prev_eci, eci);
|
||||
|
||||
LineartEdgeChain *new_ec = lineart_mem_acquire(rb->chain_data_pool,
|
||||
LineartEdgeChain *new_ec = lineart_mem_acquire(ld->chain_data_pool,
|
||||
sizeof(LineartEdgeChain));
|
||||
memcpy(new_ec, ec, sizeof(LineartEdgeChain));
|
||||
new_ec->chain.first = next_eci;
|
||||
@@ -1147,7 +1147,7 @@ void MOD_lineart_chain_clip_at_border(LineartRenderBuffer *rb)
|
||||
prev_eci->next = NULL;
|
||||
ec->chain.last = prev_eci;
|
||||
BLI_addtail(&ec->chain, new_eci);
|
||||
BLI_addtail(&rb->chains, ec);
|
||||
BLI_addtail(&ld->chains, ec);
|
||||
ec_added = true;
|
||||
ec = new_ec;
|
||||
|
||||
@@ -1156,7 +1156,7 @@ void MOD_lineart_chain_clip_at_border(LineartRenderBuffer *rb)
|
||||
continue;
|
||||
}
|
||||
/* Stroke comes in. */
|
||||
new_eci = lineart_chain_create_crossing_point(rb, eci, prev_eci);
|
||||
new_eci = lineart_chain_create_crossing_point(ld, eci, prev_eci);
|
||||
|
||||
ec->chain.first = eci;
|
||||
eci->prev = NULL;
|
||||
@@ -1172,25 +1172,25 @@ void MOD_lineart_chain_clip_at_border(LineartRenderBuffer *rb)
|
||||
}
|
||||
|
||||
if ((!ec_added) && is_inside) {
|
||||
BLI_addtail(&rb->chains, ec);
|
||||
BLI_addtail(&ld->chains, ec);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MOD_lineart_chain_split_angle(LineartRenderBuffer *rb, float angle_threshold_rad)
|
||||
void MOD_lineart_chain_split_angle(LineartData *ld, float angle_threshold_rad)
|
||||
{
|
||||
LineartEdgeChain *ec, *new_ec;
|
||||
LineartEdgeChainItem *eci, *next_eci, *prev_eci;
|
||||
ListBase swap = {0};
|
||||
|
||||
swap.first = rb->chains.first;
|
||||
swap.last = rb->chains.last;
|
||||
swap.first = ld->chains.first;
|
||||
swap.last = ld->chains.last;
|
||||
|
||||
rb->chains.last = rb->chains.first = NULL;
|
||||
ld->chains.last = ld->chains.first = NULL;
|
||||
|
||||
while ((ec = BLI_pophead(&swap)) != NULL) {
|
||||
ec->next = ec->prev = NULL;
|
||||
BLI_addtail(&rb->chains, ec);
|
||||
BLI_addtail(&ld->chains, ec);
|
||||
LineartEdgeChainItem *first_eci = (LineartEdgeChainItem *)ec->chain.first;
|
||||
for (eci = first_eci->next; eci; eci = next_eci) {
|
||||
next_eci = eci->next;
|
||||
@@ -1203,7 +1203,7 @@ void MOD_lineart_chain_split_angle(LineartRenderBuffer *rb, float angle_threshol
|
||||
break; /* No need to split at the last point anyway. */
|
||||
}
|
||||
if (angle < angle_threshold_rad) {
|
||||
new_ec = lineart_chain_create(rb);
|
||||
new_ec = lineart_chain_create(ld);
|
||||
new_ec->chain.first = eci;
|
||||
new_ec->chain.last = ec->chain.last;
|
||||
ec->chain.last = eci->prev;
|
||||
@@ -1211,7 +1211,7 @@ void MOD_lineart_chain_split_angle(LineartRenderBuffer *rb, float angle_threshol
|
||||
eci->prev = 0;
|
||||
|
||||
/* End the previous one. */
|
||||
lineart_chain_append_point(rb,
|
||||
lineart_chain_append_point(ld,
|
||||
ec,
|
||||
eci->pos,
|
||||
eci->gpos,
|
||||
@@ -1232,40 +1232,38 @@ void MOD_lineart_chain_split_angle(LineartRenderBuffer *rb, float angle_threshol
|
||||
}
|
||||
}
|
||||
|
||||
void MOD_lineart_chain_offset_towards_camera(LineartRenderBuffer *rb,
|
||||
float dist,
|
||||
bool use_custom_camera)
|
||||
void MOD_lineart_chain_offset_towards_camera(LineartData *ld, float dist, bool use_custom_camera)
|
||||
{
|
||||
float dir[3];
|
||||
float cam[3];
|
||||
float view[3];
|
||||
float view_clamp[3];
|
||||
copy_v3fl_v3db(cam, rb->camera_pos);
|
||||
copy_v3fl_v3db(view, rb->view_vector);
|
||||
copy_v3fl_v3db(cam, ld->conf.camera_pos);
|
||||
copy_v3fl_v3db(view, ld->conf.view_vector);
|
||||
|
||||
if (use_custom_camera) {
|
||||
copy_v3fl_v3db(cam, rb->camera_pos);
|
||||
copy_v3fl_v3db(cam, ld->conf.camera_pos);
|
||||
}
|
||||
else {
|
||||
copy_v3fl_v3db(cam, rb->active_camera_pos);
|
||||
copy_v3fl_v3db(cam, ld->conf.active_camera_pos);
|
||||
}
|
||||
|
||||
if (rb->cam_is_persp) {
|
||||
LISTBASE_FOREACH (LineartEdgeChain *, ec, &rb->chains) {
|
||||
if (ld->conf.cam_is_persp) {
|
||||
LISTBASE_FOREACH (LineartEdgeChain *, ec, &ld->chains) {
|
||||
LISTBASE_FOREACH (LineartEdgeChainItem *, eci, &ec->chain) {
|
||||
sub_v3_v3v3(dir, cam, eci->gpos);
|
||||
float orig_len = len_v3(dir);
|
||||
normalize_v3(dir);
|
||||
mul_v3_fl(dir, MIN2(dist, orig_len - rb->near_clip));
|
||||
mul_v3_fl(dir, MIN2(dist, orig_len - ld->conf.near_clip));
|
||||
add_v3_v3(eci->gpos, dir);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
LISTBASE_FOREACH (LineartEdgeChain *, ec, &rb->chains) {
|
||||
LISTBASE_FOREACH (LineartEdgeChain *, ec, &ld->chains) {
|
||||
LISTBASE_FOREACH (LineartEdgeChainItem *, eci, &ec->chain) {
|
||||
sub_v3_v3v3(dir, cam, eci->gpos);
|
||||
float len_lim = dot_v3v3(view, dir) - rb->near_clip;
|
||||
float len_lim = dot_v3v3(view, dir) - ld->conf.near_clip;
|
||||
normalize_v3_v3(view_clamp, view);
|
||||
mul_v3_fl(view_clamp, MIN2(dist, len_lim));
|
||||
add_v3_v3(eci->gpos, view_clamp);
|
||||
|
||||
@@ -73,19 +73,18 @@ typedef struct LineartIsecThread {
|
||||
int count_test;
|
||||
|
||||
/* For individual thread reference.*/
|
||||
LineartRenderBuffer *rb;
|
||||
LineartData *ld;
|
||||
} LineartIsecThread;
|
||||
|
||||
typedef struct LineartIsecData {
|
||||
LineartRenderBuffer *rb;
|
||||
LineartData *ld;
|
||||
LineartIsecThread *threads;
|
||||
int thread_count;
|
||||
} LineartIsecData;
|
||||
|
||||
static LineartBoundingArea *lineart_edge_first_bounding_area(LineartRenderBuffer *rb,
|
||||
LineartEdge *e);
|
||||
static LineartBoundingArea *lineart_edge_first_bounding_area(LineartData *ld, LineartEdge *e);
|
||||
|
||||
static void lineart_bounding_area_link_edge(LineartRenderBuffer *rb,
|
||||
static void lineart_bounding_area_link_edge(LineartData *ld,
|
||||
LineartBoundingArea *root_ba,
|
||||
LineartEdge *e);
|
||||
|
||||
@@ -99,12 +98,8 @@ static LineartBoundingArea *lineart_bounding_area_next(LineartBoundingArea *this
|
||||
double *next_x,
|
||||
double *next_y);
|
||||
|
||||
static bool lineart_get_edge_bounding_areas(LineartRenderBuffer *rb,
|
||||
LineartEdge *e,
|
||||
int *rowbegin,
|
||||
int *rowend,
|
||||
int *colbegin,
|
||||
int *colend);
|
||||
static bool lineart_get_edge_bounding_areas(
|
||||
LineartData *ld, LineartEdge *e, int *rowbegin, int *rowend, int *colbegin, int *colend);
|
||||
|
||||
static bool lineart_triangle_edge_image_space_occlusion(SpinLock *spl,
|
||||
const LineartTriangle *tri,
|
||||
@@ -121,7 +116,7 @@ static bool lineart_triangle_edge_image_space_occlusion(SpinLock *spl,
|
||||
|
||||
static void lineart_add_edge_to_array(LineartPendingEdges *pe, LineartEdge *e);
|
||||
|
||||
static void lineart_bounding_area_link_triangle(LineartRenderBuffer *rb,
|
||||
static void lineart_bounding_area_link_triangle(LineartData *ld,
|
||||
LineartBoundingArea *root_ba,
|
||||
LineartTriangle *tri,
|
||||
double *LRUB,
|
||||
@@ -132,45 +127,45 @@ static void lineart_bounding_area_link_triangle(LineartRenderBuffer *rb,
|
||||
|
||||
static void lineart_free_bounding_area_memory(LineartBoundingArea *ba, bool recursive);
|
||||
|
||||
static void lineart_free_bounding_area_memories(LineartRenderBuffer *rb);
|
||||
static void lineart_free_bounding_area_memories(LineartData *ld);
|
||||
|
||||
static LineartCache *lineart_init_cache(void);
|
||||
|
||||
static void lineart_discard_segment(LineartRenderBuffer *rb, LineartEdgeSegment *es)
|
||||
static void lineart_discard_segment(LineartData *ld, LineartEdgeSegment *es)
|
||||
{
|
||||
BLI_spin_lock(&rb->lock_cuts);
|
||||
BLI_spin_lock(&ld->lock_cuts);
|
||||
|
||||
memset(es, 0, sizeof(LineartEdgeSegment));
|
||||
|
||||
/* Storing the node for potentially reuse the memory for new segment data.
|
||||
* Line Art data is not freed after all calculations are done. */
|
||||
BLI_addtail(&rb->wasted_cuts, es);
|
||||
BLI_addtail(&ld->wasted_cuts, es);
|
||||
|
||||
BLI_spin_unlock(&rb->lock_cuts);
|
||||
BLI_spin_unlock(&ld->lock_cuts);
|
||||
}
|
||||
|
||||
static LineartEdgeSegment *lineart_give_segment(LineartRenderBuffer *rb)
|
||||
static LineartEdgeSegment *lineart_give_segment(LineartData *ld)
|
||||
{
|
||||
BLI_spin_lock(&rb->lock_cuts);
|
||||
BLI_spin_lock(&ld->lock_cuts);
|
||||
|
||||
/* See if there is any already allocated memory we can reuse. */
|
||||
if (rb->wasted_cuts.first) {
|
||||
LineartEdgeSegment *es = (LineartEdgeSegment *)BLI_pophead(&rb->wasted_cuts);
|
||||
BLI_spin_unlock(&rb->lock_cuts);
|
||||
if (ld->wasted_cuts.first) {
|
||||
LineartEdgeSegment *es = (LineartEdgeSegment *)BLI_pophead(&ld->wasted_cuts);
|
||||
BLI_spin_unlock(&ld->lock_cuts);
|
||||
memset(es, 0, sizeof(LineartEdgeSegment));
|
||||
return es;
|
||||
}
|
||||
BLI_spin_unlock(&rb->lock_cuts);
|
||||
BLI_spin_unlock(&ld->lock_cuts);
|
||||
|
||||
/* Otherwise allocate some new memory. */
|
||||
return (LineartEdgeSegment *)lineart_mem_acquire_thread(&rb->render_data_pool,
|
||||
return (LineartEdgeSegment *)lineart_mem_acquire_thread(&ld->render_data_pool,
|
||||
sizeof(LineartEdgeSegment));
|
||||
}
|
||||
|
||||
/**
|
||||
* Cuts the edge in image space and mark occlusion level for each segment.
|
||||
*/
|
||||
static void lineart_edge_cut(LineartRenderBuffer *rb,
|
||||
static void lineart_edge_cut(LineartData *ld,
|
||||
LineartEdge *e,
|
||||
double start,
|
||||
double end,
|
||||
@@ -218,7 +213,7 @@ static void lineart_edge_cut(LineartRenderBuffer *rb,
|
||||
ies = es->next;
|
||||
if (ies->at > start + 1e-09 && start > es->at) {
|
||||
cut_start_before = ies;
|
||||
ns = lineart_give_segment(rb);
|
||||
ns = lineart_give_segment(ld);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -244,14 +239,14 @@ static void lineart_edge_cut(LineartRenderBuffer *rb,
|
||||
/* When an actual cut is needed in the line. */
|
||||
if (es->at > end) {
|
||||
cut_end_before = es;
|
||||
ns2 = lineart_give_segment(rb);
|
||||
ns2 = lineart_give_segment(ld);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* When we still can't find any existing cut in the line, we allocate new ones. */
|
||||
if (ns == NULL) {
|
||||
ns = lineart_give_segment(rb);
|
||||
ns = lineart_give_segment(ld);
|
||||
}
|
||||
if (ns2 == NULL) {
|
||||
if (untouched) {
|
||||
@@ -259,7 +254,7 @@ static void lineart_edge_cut(LineartRenderBuffer *rb,
|
||||
cut_end_before = ns2;
|
||||
}
|
||||
else {
|
||||
ns2 = lineart_give_segment(rb);
|
||||
ns2 = lineart_give_segment(ld);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -325,7 +320,7 @@ static void lineart_edge_cut(LineartRenderBuffer *rb,
|
||||
BLI_remlink(&e->segments, es);
|
||||
/* This puts the node back to the render buffer, if more cut happens, these unused nodes get
|
||||
* picked first. */
|
||||
lineart_discard_segment(rb, es);
|
||||
lineart_discard_segment(ld, es);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -374,10 +369,10 @@ static void lineart_bounding_area_line_add(LineartBoundingArea *ba, LineartEdge
|
||||
ba->line_count++;
|
||||
}
|
||||
|
||||
static void lineart_occlusion_single_line(LineartRenderBuffer *rb, LineartEdge *e, int thread_id)
|
||||
static void lineart_occlusion_single_line(LineartData *ld, LineartEdge *e, int thread_id)
|
||||
{
|
||||
double x = e->v1->fbcoord[0], y = e->v1->fbcoord[1];
|
||||
LineartBoundingArea *ba = lineart_edge_first_bounding_area(rb, e);
|
||||
LineartBoundingArea *ba = lineart_edge_first_bounding_area(ld, e);
|
||||
LineartBoundingArea *nba = ba;
|
||||
LineartTriangleThread *tri;
|
||||
|
||||
@@ -406,20 +401,20 @@ static void lineart_occlusion_single_line(LineartRenderBuffer *rb, LineartEdge *
|
||||
continue;
|
||||
}
|
||||
tri->testing_e[thread_id] = e;
|
||||
if (lineart_triangle_edge_image_space_occlusion(&rb->lock_task,
|
||||
if (lineart_triangle_edge_image_space_occlusion(&ld->lock_task,
|
||||
(const LineartTriangle *)tri,
|
||||
e,
|
||||
rb->camera_pos,
|
||||
rb->cam_is_persp,
|
||||
rb->allow_overlapping_edges,
|
||||
rb->view_projection,
|
||||
rb->view_vector,
|
||||
rb->shift_x,
|
||||
rb->shift_y,
|
||||
ld->conf.camera_pos,
|
||||
ld->conf.cam_is_persp,
|
||||
ld->conf.allow_overlapping_edges,
|
||||
ld->conf.view_projection,
|
||||
ld->conf.view_vector,
|
||||
ld->conf.shift_x,
|
||||
ld->conf.shift_y,
|
||||
&l,
|
||||
&r)) {
|
||||
lineart_edge_cut(rb, e, l, r, tri->base.material_mask_bits, tri->base.mat_occlusion);
|
||||
if (e->min_occ > rb->max_occlusion_level) {
|
||||
lineart_edge_cut(ld, e, l, r, tri->base.material_mask_bits, tri->base.mat_occlusion);
|
||||
if (e->min_occ > ld->conf.max_occlusion_level) {
|
||||
/* No need to calculate any longer on this line because no level more than set value is
|
||||
* going to show up in the rendered result. */
|
||||
return;
|
||||
@@ -431,24 +426,24 @@ static void lineart_occlusion_single_line(LineartRenderBuffer *rb, LineartEdge *
|
||||
}
|
||||
}
|
||||
|
||||
static int lineart_occlusion_make_task_info(LineartRenderBuffer *rb, LineartRenderTaskInfo *rti)
|
||||
static int lineart_occlusion_make_task_info(LineartData *ld, LineartRenderTaskInfo *rti)
|
||||
{
|
||||
int res = 0;
|
||||
int starting_index;
|
||||
|
||||
BLI_spin_lock(&rb->lock_task);
|
||||
BLI_spin_lock(&ld->lock_task);
|
||||
|
||||
starting_index = rb->scheduled_count;
|
||||
rb->scheduled_count += LRT_THREAD_EDGE_COUNT;
|
||||
starting_index = ld->scheduled_count;
|
||||
ld->scheduled_count += LRT_THREAD_EDGE_COUNT;
|
||||
|
||||
BLI_spin_unlock(&rb->lock_task);
|
||||
BLI_spin_unlock(&ld->lock_task);
|
||||
|
||||
if (starting_index >= rb->pending_edges.next) {
|
||||
if (starting_index >= ld->pending_edges.next) {
|
||||
res = 0;
|
||||
}
|
||||
else {
|
||||
rti->pending_edges.array = &rb->pending_edges.array[starting_index];
|
||||
int remaining = rb->pending_edges.next - starting_index;
|
||||
rti->pending_edges.array = &ld->pending_edges.array[starting_index];
|
||||
int remaining = ld->pending_edges.next - starting_index;
|
||||
rti->pending_edges.max = MIN2(remaining, LRT_THREAD_EDGE_COUNT);
|
||||
res = 1;
|
||||
}
|
||||
@@ -458,13 +453,13 @@ static int lineart_occlusion_make_task_info(LineartRenderBuffer *rb, LineartRend
|
||||
|
||||
static void lineart_occlusion_worker(TaskPool *__restrict UNUSED(pool), LineartRenderTaskInfo *rti)
|
||||
{
|
||||
LineartRenderBuffer *rb = rti->rb;
|
||||
LineartData *ld = rti->ld;
|
||||
LineartEdge *eip;
|
||||
|
||||
while (lineart_occlusion_make_task_info(rb, rti)) {
|
||||
while (lineart_occlusion_make_task_info(ld, rti)) {
|
||||
for (int i = 0; i < rti->pending_edges.max; i++) {
|
||||
eip = rti->pending_edges.array[i];
|
||||
lineart_occlusion_single_line(rb, eip, rti->thread_id);
|
||||
lineart_occlusion_single_line(ld, eip, rti->thread_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -474,9 +469,9 @@ static void lineart_occlusion_worker(TaskPool *__restrict UNUSED(pool), LineartR
|
||||
* #MOD_lineart_compute_feature_lines function.
|
||||
* This function handles all occlusion calculation.
|
||||
*/
|
||||
static void lineart_main_occlusion_begin(LineartRenderBuffer *rb)
|
||||
static void lineart_main_occlusion_begin(LineartData *ld)
|
||||
{
|
||||
int thread_count = rb->thread_count;
|
||||
int thread_count = ld->thread_count;
|
||||
LineartRenderTaskInfo *rti = MEM_callocN(sizeof(LineartRenderTaskInfo) * thread_count,
|
||||
"Task Pool");
|
||||
int i;
|
||||
@@ -485,7 +480,7 @@ static void lineart_main_occlusion_begin(LineartRenderBuffer *rb)
|
||||
|
||||
for (i = 0; i < thread_count; i++) {
|
||||
rti[i].thread_id = i;
|
||||
rti[i].rb = rb;
|
||||
rti[i].ld = ld;
|
||||
BLI_task_pool_push(tp, (TaskRunFunction)lineart_occlusion_worker, &rti[i], 0, NULL);
|
||||
}
|
||||
BLI_task_pool_work_and_wait(tp);
|
||||
@@ -662,17 +657,17 @@ static bool lineart_point_inside_triangle3d(double v[3], double v0[3], double v1
|
||||
* The following `lineart_memory_get_XXX_space` functions are for allocating new memory for some
|
||||
* modified geometries in the culling stage.
|
||||
*/
|
||||
static LineartElementLinkNode *lineart_memory_get_triangle_space(LineartRenderBuffer *rb)
|
||||
static LineartElementLinkNode *lineart_memory_get_triangle_space(LineartData *ld)
|
||||
{
|
||||
LineartElementLinkNode *eln;
|
||||
|
||||
/* We don't need to allocate a whole bunch of triangles because the amount of clipped triangles
|
||||
* are relatively small. */
|
||||
LineartTriangle *render_triangles = lineart_mem_acquire(&rb->render_data_pool,
|
||||
64 * rb->triangle_size);
|
||||
LineartTriangle *render_triangles = lineart_mem_acquire(&ld->render_data_pool,
|
||||
64 * ld->sizeof_triangle);
|
||||
|
||||
eln = lineart_list_append_pointer_pool_sized(&rb->triangle_buffer_pointers,
|
||||
&rb->render_data_pool,
|
||||
eln = lineart_list_append_pointer_pool_sized(&ld->geom.triangle_buffer_pointers,
|
||||
&ld->render_data_pool,
|
||||
render_triangles,
|
||||
sizeof(LineartElementLinkNode));
|
||||
eln->element_count = 64;
|
||||
@@ -681,15 +676,15 @@ static LineartElementLinkNode *lineart_memory_get_triangle_space(LineartRenderBu
|
||||
return eln;
|
||||
}
|
||||
|
||||
static LineartElementLinkNode *lineart_memory_get_vert_space(LineartRenderBuffer *rb)
|
||||
static LineartElementLinkNode *lineart_memory_get_vert_space(LineartData *ld)
|
||||
{
|
||||
LineartElementLinkNode *eln;
|
||||
|
||||
LineartVert *render_vertices = lineart_mem_acquire(&rb->render_data_pool,
|
||||
LineartVert *render_vertices = lineart_mem_acquire(&ld->render_data_pool,
|
||||
sizeof(LineartVert) * 64);
|
||||
|
||||
eln = lineart_list_append_pointer_pool_sized(&rb->vertex_buffer_pointers,
|
||||
&rb->render_data_pool,
|
||||
eln = lineart_list_append_pointer_pool_sized(&ld->geom.vertex_buffer_pointers,
|
||||
&ld->render_data_pool,
|
||||
render_vertices,
|
||||
sizeof(LineartElementLinkNode));
|
||||
eln->element_count = 64;
|
||||
@@ -698,18 +693,18 @@ static LineartElementLinkNode *lineart_memory_get_vert_space(LineartRenderBuffer
|
||||
return eln;
|
||||
}
|
||||
|
||||
static LineartElementLinkNode *lineart_memory_get_edge_space(LineartRenderBuffer *rb)
|
||||
static LineartElementLinkNode *lineart_memory_get_edge_space(LineartData *ld)
|
||||
{
|
||||
LineartElementLinkNode *eln;
|
||||
|
||||
LineartEdge *render_edges = lineart_mem_acquire(&rb->render_data_pool, sizeof(LineartEdge) * 64);
|
||||
LineartEdge *render_edges = lineart_mem_acquire(&ld->render_data_pool, sizeof(LineartEdge) * 64);
|
||||
|
||||
eln = lineart_list_append_pointer_pool_sized(&rb->line_buffer_pointers,
|
||||
&rb->render_data_pool,
|
||||
eln = lineart_list_append_pointer_pool_sized(&ld->geom.line_buffer_pointers,
|
||||
&ld->render_data_pool,
|
||||
render_edges,
|
||||
sizeof(LineartElementLinkNode));
|
||||
eln->element_count = 64;
|
||||
eln->crease_threshold = rb->crease_threshold;
|
||||
eln->crease_threshold = ld->conf.crease_threshold;
|
||||
eln->flags |= LRT_ELEMENT_IS_ADDITIONAL;
|
||||
|
||||
return eln;
|
||||
@@ -751,7 +746,7 @@ static void lineart_discard_duplicated_edges(LineartEdge *old_e)
|
||||
* Does near-plane cut on 1 triangle only. When cutting with far-plane, the camera vectors gets
|
||||
* reversed by the caller so don't need to implement one in a different direction.
|
||||
*/
|
||||
static void lineart_triangle_cull_single(LineartRenderBuffer *rb,
|
||||
static void lineart_triangle_cull_single(LineartData *ld,
|
||||
LineartTriangle *tri,
|
||||
int in0,
|
||||
int in1,
|
||||
@@ -788,8 +783,9 @@ static void lineart_triangle_cull_single(LineartRenderBuffer *rb,
|
||||
ta = (void *)tri->intersecting_verts;
|
||||
|
||||
LineartVert *vt = &((LineartVert *)v_eln->pointer)[v_count];
|
||||
LineartTriangle *tri1 = (void *)(((uchar *)t_eln->pointer) + rb->triangle_size * t_count);
|
||||
LineartTriangle *tri2 = (void *)(((uchar *)t_eln->pointer) + rb->triangle_size * (t_count + 1));
|
||||
LineartTriangle *tri1 = (void *)(((uchar *)t_eln->pointer) + ld->sizeof_triangle * t_count);
|
||||
LineartTriangle *tri2 = (void *)(((uchar *)t_eln->pointer) +
|
||||
ld->sizeof_triangle * (t_count + 1));
|
||||
|
||||
new_e = &((LineartEdge *)e_eln->pointer)[e_count];
|
||||
/* Init `edge` to the last `edge` entry. */
|
||||
@@ -799,7 +795,7 @@ static void lineart_triangle_cull_single(LineartRenderBuffer *rb,
|
||||
new_e = &((LineartEdge *)e_eln->pointer)[e_count]; \
|
||||
e_count++; \
|
||||
e = new_e; \
|
||||
es = lineart_mem_acquire(&rb->render_data_pool, sizeof(LineartEdgeSegment)); \
|
||||
es = lineart_mem_acquire(&ld->render_data_pool, sizeof(LineartEdgeSegment)); \
|
||||
BLI_addtail(&e->segments, es);
|
||||
|
||||
#define SELECT_EDGE(e_num, v1_link, v2_link, new_tri) \
|
||||
@@ -817,7 +813,7 @@ static void lineart_triangle_cull_single(LineartRenderBuffer *rb,
|
||||
e->object_ref = ob; \
|
||||
e->t1 = ((old_e->t1 == tri) ? (new_tri) : (old_e->t1)); \
|
||||
e->t2 = ((old_e->t2 == tri) ? (new_tri) : (old_e->t2)); \
|
||||
lineart_add_edge_to_array(&rb->pending_edges, e); \
|
||||
lineart_add_edge_to_array(&ld->pending_edges, e); \
|
||||
}
|
||||
|
||||
#define RELINK_EDGE(e_num, new_tri) \
|
||||
@@ -903,7 +899,7 @@ static void lineart_triangle_cull_single(LineartRenderBuffer *rb,
|
||||
INCREASE_EDGE
|
||||
if (allow_boundaries) {
|
||||
e->flags = LRT_EDGE_FLAG_CONTOUR;
|
||||
lineart_add_edge_to_array(&rb->pending_edges, e);
|
||||
lineart_add_edge_to_array(&ld->pending_edges, e);
|
||||
}
|
||||
/* NOTE: inverting `e->v1/v2` (left/right point) doesn't matter as long as
|
||||
* `tri->edge` and `tri->v` has the same sequence. and the winding direction
|
||||
@@ -952,7 +948,7 @@ static void lineart_triangle_cull_single(LineartRenderBuffer *rb,
|
||||
INCREASE_EDGE
|
||||
if (allow_boundaries) {
|
||||
e->flags = LRT_EDGE_FLAG_CONTOUR;
|
||||
lineart_add_edge_to_array(&rb->pending_edges, e);
|
||||
lineart_add_edge_to_array(&ld->pending_edges, e);
|
||||
}
|
||||
e->v1 = &vt[0];
|
||||
e->v2 = &vt[1];
|
||||
@@ -993,7 +989,7 @@ static void lineart_triangle_cull_single(LineartRenderBuffer *rb,
|
||||
INCREASE_EDGE
|
||||
if (allow_boundaries) {
|
||||
e->flags = LRT_EDGE_FLAG_CONTOUR;
|
||||
lineart_add_edge_to_array(&rb->pending_edges, e);
|
||||
lineart_add_edge_to_array(&ld->pending_edges, e);
|
||||
}
|
||||
e->v1 = &vt[1];
|
||||
e->v2 = &vt[0];
|
||||
@@ -1068,7 +1064,7 @@ static void lineart_triangle_cull_single(LineartRenderBuffer *rb,
|
||||
INCREASE_EDGE
|
||||
if (allow_boundaries) {
|
||||
e->flags = LRT_EDGE_FLAG_CONTOUR;
|
||||
lineart_add_edge_to_array(&rb->pending_edges, e);
|
||||
lineart_add_edge_to_array(&ld->pending_edges, e);
|
||||
}
|
||||
e->v1 = &vt[1];
|
||||
e->v2 = &vt[0];
|
||||
@@ -1120,7 +1116,7 @@ static void lineart_triangle_cull_single(LineartRenderBuffer *rb,
|
||||
INCREASE_EDGE
|
||||
if (allow_boundaries) {
|
||||
e->flags = LRT_EDGE_FLAG_CONTOUR;
|
||||
lineart_add_edge_to_array(&rb->pending_edges, e);
|
||||
lineart_add_edge_to_array(&ld->pending_edges, e);
|
||||
}
|
||||
e->v1 = &vt[1];
|
||||
e->v2 = &vt[0];
|
||||
@@ -1169,7 +1165,7 @@ static void lineart_triangle_cull_single(LineartRenderBuffer *rb,
|
||||
INCREASE_EDGE
|
||||
if (allow_boundaries) {
|
||||
e->flags = LRT_EDGE_FLAG_CONTOUR;
|
||||
lineart_add_edge_to_array(&rb->pending_edges, e);
|
||||
lineart_add_edge_to_array(&ld->pending_edges, e);
|
||||
}
|
||||
e->v1 = &vt[1];
|
||||
e->v2 = &vt[0];
|
||||
@@ -1213,22 +1209,22 @@ static void lineart_triangle_cull_single(LineartRenderBuffer *rb,
|
||||
* new topology that represents the trimmed triangle. (which then became a triangle or a square
|
||||
* formed by two triangles)
|
||||
*/
|
||||
static void lineart_main_cull_triangles(LineartRenderBuffer *rb, bool clip_far)
|
||||
static void lineart_main_cull_triangles(LineartData *ld, bool clip_far)
|
||||
{
|
||||
LineartTriangle *tri;
|
||||
LineartElementLinkNode *v_eln, *t_eln, *e_eln;
|
||||
double(*vp)[4] = rb->view_projection;
|
||||
double(*vp)[4] = ld->conf.view_projection;
|
||||
int i;
|
||||
int v_count = 0, t_count = 0, e_count = 0;
|
||||
Object *ob;
|
||||
bool allow_boundaries = rb->allow_boundaries;
|
||||
bool allow_boundaries = ld->conf.allow_boundaries;
|
||||
double cam_pos[3];
|
||||
double clip_start = rb->near_clip, clip_end = rb->far_clip;
|
||||
double clip_start = ld->conf.near_clip, clip_end = ld->conf.far_clip;
|
||||
double view_dir[3], clip_advance[3];
|
||||
|
||||
copy_v3_v3_db(view_dir, rb->view_vector);
|
||||
copy_v3_v3_db(clip_advance, rb->view_vector);
|
||||
copy_v3_v3_db(cam_pos, rb->camera_pos);
|
||||
copy_v3_v3_db(view_dir, ld->conf.view_vector);
|
||||
copy_v3_v3_db(clip_advance, ld->conf.view_vector);
|
||||
copy_v3_v3_db(cam_pos, ld->conf.camera_pos);
|
||||
|
||||
if (clip_far) {
|
||||
/* Move starting point to end plane. */
|
||||
@@ -1244,25 +1240,25 @@ static void lineart_main_cull_triangles(LineartRenderBuffer *rb, bool clip_far)
|
||||
add_v3_v3_db(cam_pos, clip_advance);
|
||||
}
|
||||
|
||||
v_eln = lineart_memory_get_vert_space(rb);
|
||||
t_eln = lineart_memory_get_triangle_space(rb);
|
||||
e_eln = lineart_memory_get_edge_space(rb);
|
||||
v_eln = lineart_memory_get_vert_space(ld);
|
||||
t_eln = lineart_memory_get_triangle_space(ld);
|
||||
e_eln = lineart_memory_get_edge_space(ld);
|
||||
|
||||
/* Additional memory space for storing generated points and triangles. */
|
||||
#define LRT_CULL_ENSURE_MEMORY \
|
||||
if (v_count > 60) { \
|
||||
v_eln->element_count = v_count; \
|
||||
v_eln = lineart_memory_get_vert_space(rb); \
|
||||
v_eln = lineart_memory_get_vert_space(ld); \
|
||||
v_count = 0; \
|
||||
} \
|
||||
if (t_count > 60) { \
|
||||
t_eln->element_count = t_count; \
|
||||
t_eln = lineart_memory_get_triangle_space(rb); \
|
||||
t_eln = lineart_memory_get_triangle_space(ld); \
|
||||
t_count = 0; \
|
||||
} \
|
||||
if (e_count > 60) { \
|
||||
e_eln->element_count = e_count; \
|
||||
e_eln = lineart_memory_get_edge_space(rb); \
|
||||
e_eln = lineart_memory_get_edge_space(ld); \
|
||||
e_count = 0; \
|
||||
}
|
||||
|
||||
@@ -1297,21 +1293,21 @@ static void lineart_main_cull_triangles(LineartRenderBuffer *rb, bool clip_far)
|
||||
int use_w = 3;
|
||||
int in0 = 0, in1 = 0, in2 = 0;
|
||||
|
||||
if (!rb->cam_is_persp) {
|
||||
if (!ld->conf.cam_is_persp) {
|
||||
clip_start = -1;
|
||||
clip_end = 1;
|
||||
use_w = 2;
|
||||
}
|
||||
|
||||
/* Then go through all the other triangles. */
|
||||
LISTBASE_FOREACH (LineartElementLinkNode *, eln, &rb->triangle_buffer_pointers) {
|
||||
LISTBASE_FOREACH (LineartElementLinkNode *, eln, &ld->geom.triangle_buffer_pointers) {
|
||||
if (eln->flags & LRT_ELEMENT_IS_ADDITIONAL) {
|
||||
continue;
|
||||
}
|
||||
ob = eln->object_ref;
|
||||
for (i = 0; i < eln->element_count; i++) {
|
||||
/* Select the triangle in the array. */
|
||||
tri = (void *)(((uchar *)eln->pointer) + rb->triangle_size * i);
|
||||
tri = (void *)(((uchar *)eln->pointer) + ld->sizeof_triangle * i);
|
||||
|
||||
if (tri->flags & LRT_CULL_DISCARD) {
|
||||
continue;
|
||||
@@ -1319,7 +1315,7 @@ static void lineart_main_cull_triangles(LineartRenderBuffer *rb, bool clip_far)
|
||||
|
||||
LRT_CULL_DECIDE_INSIDE
|
||||
LRT_CULL_ENSURE_MEMORY
|
||||
lineart_triangle_cull_single(rb,
|
||||
lineart_triangle_cull_single(ld,
|
||||
tri,
|
||||
in0,
|
||||
in1,
|
||||
@@ -1348,33 +1344,33 @@ static void lineart_main_cull_triangles(LineartRenderBuffer *rb, bool clip_far)
|
||||
* Adjacent data is only used during the initial stages of computing.
|
||||
* So we can free it using this function when it is not needed anymore.
|
||||
*/
|
||||
static void lineart_main_free_adjacent_data(LineartRenderBuffer *rb)
|
||||
static void lineart_main_free_adjacent_data(LineartData *ld)
|
||||
{
|
||||
LinkData *ld;
|
||||
while ((ld = BLI_pophead(&rb->triangle_adjacent_pointers)) != NULL) {
|
||||
MEM_freeN(ld->data);
|
||||
LinkData *link;
|
||||
while ((link = BLI_pophead(&ld->geom.triangle_adjacent_pointers)) != NULL) {
|
||||
MEM_freeN(link->data);
|
||||
}
|
||||
LISTBASE_FOREACH (LineartElementLinkNode *, eln, &rb->triangle_buffer_pointers) {
|
||||
LISTBASE_FOREACH (LineartElementLinkNode *, eln, &ld->geom.triangle_buffer_pointers) {
|
||||
LineartTriangle *tri = eln->pointer;
|
||||
int i;
|
||||
for (i = 0; i < eln->element_count; i++) {
|
||||
/* See definition of tri->intersecting_verts and the usage in
|
||||
* lineart_geometry_object_load() for detailed. */
|
||||
tri->intersecting_verts = NULL;
|
||||
tri = (LineartTriangle *)(((uchar *)tri) + rb->triangle_size);
|
||||
tri = (LineartTriangle *)(((uchar *)tri) + ld->sizeof_triangle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void lineart_main_perspective_division(LineartRenderBuffer *rb)
|
||||
static void lineart_main_perspective_division(LineartData *ld)
|
||||
{
|
||||
LineartVert *vt;
|
||||
int i;
|
||||
|
||||
LISTBASE_FOREACH (LineartElementLinkNode *, eln, &rb->vertex_buffer_pointers) {
|
||||
LISTBASE_FOREACH (LineartElementLinkNode *, eln, &ld->geom.vertex_buffer_pointers) {
|
||||
vt = eln->pointer;
|
||||
for (i = 0; i < eln->element_count; i++) {
|
||||
if (rb->cam_is_persp) {
|
||||
if (ld->conf.cam_is_persp) {
|
||||
/* Do not divide Z, we use Z to back transform cut points in later chaining process. */
|
||||
vt[i].fbcoord[0] /= vt[i].fbcoord[3];
|
||||
vt[i].fbcoord[1] /= vt[i].fbcoord[3];
|
||||
@@ -1385,13 +1381,13 @@ static void lineart_main_perspective_division(LineartRenderBuffer *rb)
|
||||
// `vt[i].fbcoord[2] = -2 * vt[i].fbcoord[2] / (far - near) - (far + near) / (far - near);
|
||||
}
|
||||
/* Shifting is always needed. */
|
||||
vt[i].fbcoord[0] -= rb->shift_x * 2;
|
||||
vt[i].fbcoord[1] -= rb->shift_y * 2;
|
||||
vt[i].fbcoord[0] -= ld->conf.shift_x * 2;
|
||||
vt[i].fbcoord[1] -= ld->conf.shift_y * 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void lineart_main_discard_out_of_frame_edges(LineartRenderBuffer *rb)
|
||||
static void lineart_main_discard_out_of_frame_edges(LineartData *ld)
|
||||
{
|
||||
LineartEdge *e;
|
||||
int i;
|
||||
@@ -1399,7 +1395,7 @@ static void lineart_main_discard_out_of_frame_edges(LineartRenderBuffer *rb)
|
||||
#define LRT_VERT_OUT_OF_BOUND(v) \
|
||||
(v && (v->fbcoord[0] < -1 || v->fbcoord[0] > 1 || v->fbcoord[1] < -1 || v->fbcoord[1] > 1))
|
||||
|
||||
LISTBASE_FOREACH (LineartElementLinkNode *, eln, &rb->line_buffer_pointers) {
|
||||
LISTBASE_FOREACH (LineartElementLinkNode *, eln, &ld->geom.line_buffer_pointers) {
|
||||
e = (LineartEdge *)eln->pointer;
|
||||
for (i = 0; i < eln->element_count; i++) {
|
||||
if ((LRT_VERT_OUT_OF_BOUND(e[i].v1) && LRT_VERT_OUT_OF_BOUND(e[i].v2))) {
|
||||
@@ -1454,17 +1450,17 @@ static int lineart_edge_type_duplication_count(char eflag)
|
||||
* Because we have a variable size for #LineartTriangle, we need an access helper.
|
||||
* See #LineartTriangleThread for more info.
|
||||
*/
|
||||
static LineartTriangle *lineart_triangle_from_index(LineartRenderBuffer *rb,
|
||||
static LineartTriangle *lineart_triangle_from_index(LineartData *ld,
|
||||
LineartTriangle *rt_array,
|
||||
int index)
|
||||
{
|
||||
char *b = (char *)rt_array;
|
||||
b += (index * rb->triangle_size);
|
||||
b += (index * ld->sizeof_triangle);
|
||||
return (LineartTriangle *)b;
|
||||
}
|
||||
|
||||
typedef struct EdgeFeatData {
|
||||
LineartRenderBuffer *rb;
|
||||
LineartData *ld;
|
||||
Mesh *me;
|
||||
const MLoopTri *mlooptri;
|
||||
LineartTriangle *tri_array;
|
||||
@@ -1510,7 +1506,8 @@ static void lineart_identify_mlooptri_feature_edges(void *__restrict userdata,
|
||||
}
|
||||
|
||||
bool face_mark_filtered = false;
|
||||
bool enable_face_mark = (e_feat_data->use_freestyle_face && e_feat_data->rb->filter_face_mark);
|
||||
bool enable_face_mark = (e_feat_data->use_freestyle_face &&
|
||||
e_feat_data->ld->conf.filter_face_mark);
|
||||
bool only_contour = false;
|
||||
if (enable_face_mark) {
|
||||
FreestyleFace *ff1, *ff2;
|
||||
@@ -1527,7 +1524,8 @@ static void lineart_identify_mlooptri_feature_edges(void *__restrict userdata,
|
||||
* path is simper when it's assuming both ff1 and ff2 not NULL. */
|
||||
ff2 = ff1;
|
||||
}
|
||||
if (e_feat_data->rb->filter_face_mark_boundaries ^ e_feat_data->rb->filter_face_mark_invert) {
|
||||
if (e_feat_data->ld->conf.filter_face_mark_boundaries ^
|
||||
e_feat_data->ld->conf.filter_face_mark_invert) {
|
||||
if ((ff1->flag & FREESTYLE_FACE_MARK) || (ff2->flag & FREESTYLE_FACE_MARK)) {
|
||||
face_mark_filtered = true;
|
||||
}
|
||||
@@ -1537,12 +1535,12 @@ static void lineart_identify_mlooptri_feature_edges(void *__restrict userdata,
|
||||
face_mark_filtered = true;
|
||||
}
|
||||
}
|
||||
if (e_feat_data->rb->filter_face_mark_invert) {
|
||||
if (e_feat_data->ld->conf.filter_face_mark_invert) {
|
||||
face_mark_filtered = !face_mark_filtered;
|
||||
}
|
||||
if (!face_mark_filtered) {
|
||||
edge_nabr[i].flags = LRT_EDGE_FLAG_INHIBIT;
|
||||
if (e_feat_data->rb->filter_face_mark_keep_contour) {
|
||||
if (e_feat_data->ld->conf.filter_face_mark_keep_contour) {
|
||||
only_contour = true;
|
||||
}
|
||||
}
|
||||
@@ -1561,13 +1559,13 @@ static void lineart_identify_mlooptri_feature_edges(void *__restrict userdata,
|
||||
|
||||
LineartTriangle *tri1, *tri2;
|
||||
LineartVert *vert;
|
||||
LineartRenderBuffer *rb = e_feat_data->rb;
|
||||
LineartData *ld = e_feat_data->ld;
|
||||
|
||||
int f1 = i / 3, f2 = edge_nabr[i].e / 3;
|
||||
|
||||
/* The mesh should already be triangulated now, so we can assume each face is a triangle. */
|
||||
tri1 = lineart_triangle_from_index(rb, e_feat_data->tri_array, f1);
|
||||
tri2 = lineart_triangle_from_index(rb, e_feat_data->tri_array, f2);
|
||||
tri1 = lineart_triangle_from_index(ld, e_feat_data->tri_array, f1);
|
||||
tri2 = lineart_triangle_from_index(ld, e_feat_data->tri_array, f2);
|
||||
|
||||
vert = &e_feat_data->v_array[edge_nabr[i].v1];
|
||||
|
||||
@@ -1577,12 +1575,12 @@ static void lineart_identify_mlooptri_feature_edges(void *__restrict userdata,
|
||||
double result;
|
||||
bool material_back_face = ((tri1->flags | tri2->flags) & LRT_TRIANGLE_MAT_BACK_FACE_CULLING);
|
||||
|
||||
if (rb->use_contour || rb->use_back_face_culling || material_back_face) {
|
||||
if (rb->cam_is_persp) {
|
||||
sub_v3_v3v3_db(view_vector, rb->camera_pos, vert->gloc);
|
||||
if (ld->conf.use_contour || ld->conf.use_back_face_culling || material_back_face) {
|
||||
if (ld->conf.cam_is_persp) {
|
||||
sub_v3_v3v3_db(view_vector, ld->conf.camera_pos, vert->gloc);
|
||||
}
|
||||
else {
|
||||
view_vector = rb->view_vector;
|
||||
view_vector = ld->conf.view_vector;
|
||||
}
|
||||
|
||||
dot_1 = dot_v3v3_db(view_vector, tri1->gn);
|
||||
@@ -1592,7 +1590,7 @@ static void lineart_identify_mlooptri_feature_edges(void *__restrict userdata,
|
||||
edge_flag_result |= LRT_EDGE_FLAG_CONTOUR;
|
||||
}
|
||||
|
||||
if (rb->use_back_face_culling) {
|
||||
if (ld->conf.use_back_face_culling) {
|
||||
if (dot_1 < 0) {
|
||||
tri1->flags |= LRT_CULL_DISCARD;
|
||||
}
|
||||
@@ -1612,9 +1610,9 @@ static void lineart_identify_mlooptri_feature_edges(void *__restrict userdata,
|
||||
|
||||
if (!only_contour) {
|
||||
|
||||
if (rb->use_crease) {
|
||||
if (ld->conf.use_crease) {
|
||||
bool do_crease = true;
|
||||
if (!rb->force_crease && !e_feat_data->use_auto_smooth &&
|
||||
if (!ld->conf.force_crease && !e_feat_data->use_auto_smooth &&
|
||||
(me->mpoly[mlooptri[f1].poly].flag & ME_SMOOTH) &&
|
||||
(me->mpoly[mlooptri[f2].poly].flag & ME_SMOOTH)) {
|
||||
do_crease = false;
|
||||
@@ -1627,7 +1625,7 @@ static void lineart_identify_mlooptri_feature_edges(void *__restrict userdata,
|
||||
int mat1 = me->mpoly[mlooptri[f1].poly].mat_nr;
|
||||
int mat2 = me->mpoly[mlooptri[f2].poly].mat_nr;
|
||||
|
||||
if (rb->use_material && mat1 != mat2) {
|
||||
if (ld->conf.use_material && mat1 != mat2) {
|
||||
edge_flag_result |= LRT_EDGE_FLAG_MATERIAL;
|
||||
}
|
||||
}
|
||||
@@ -1643,11 +1641,11 @@ static void lineart_identify_mlooptri_feature_edges(void *__restrict userdata,
|
||||
if (real_edges[i % 3] >= 0) {
|
||||
MEdge *medge = &me->medge[real_edges[i % 3]];
|
||||
|
||||
if (rb->use_crease && rb->sharp_as_crease && (medge->flag & ME_SHARP)) {
|
||||
if (ld->conf.use_crease && ld->conf.sharp_as_crease && (medge->flag & ME_SHARP)) {
|
||||
edge_flag_result |= LRT_EDGE_FLAG_CREASE;
|
||||
}
|
||||
|
||||
if (rb->use_edge_marks && e_feat_data->use_freestyle_edge) {
|
||||
if (ld->conf.use_edge_marks && e_feat_data->use_freestyle_edge) {
|
||||
FreestyleEdge *fe;
|
||||
int index = e_feat_data->freestyle_edge_index;
|
||||
fe = &((FreestyleEdge *)me->edata.layers[index].data)[real_edges[i % 3]];
|
||||
@@ -1663,7 +1661,7 @@ static void lineart_identify_mlooptri_feature_edges(void *__restrict userdata,
|
||||
/* Only allocate for feature edge (instead of all edges) to save memory.
|
||||
* If allow duplicated edges, one edge gets added multiple times if it has multiple types.
|
||||
*/
|
||||
reduce_data->feat_edges += e_feat_data->rb->allow_duplicated_types ?
|
||||
reduce_data->feat_edges += e_feat_data->ld->conf.allow_duplicated_types ?
|
||||
lineart_edge_type_duplication_count(edge_flag_result) :
|
||||
1;
|
||||
}
|
||||
@@ -1931,7 +1929,7 @@ static LineartEdgeNeighbor *lineart_build_edge_neighbor(Mesh *me, int total_edge
|
||||
return edge_nabr;
|
||||
}
|
||||
|
||||
static void lineart_geometry_object_load(LineartObjectInfo *ob_info, LineartRenderBuffer *re_buf)
|
||||
static void lineart_geometry_object_load(LineartObjectInfo *ob_info, LineartData *la_data)
|
||||
{
|
||||
LineartElementLinkNode *elem_link_node;
|
||||
LineartVert *la_v_arr;
|
||||
@@ -1965,19 +1963,20 @@ static void lineart_geometry_object_load(LineartObjectInfo *ob_info, LineartRend
|
||||
/* If we allow duplicated edges, one edge should get added multiple times if is has been
|
||||
* classified as more than one edge type. This is so we can create multiple different line type
|
||||
* chains containing the same edge. */
|
||||
la_v_arr = lineart_mem_acquire_thread(&re_buf->render_data_pool,
|
||||
la_v_arr = lineart_mem_acquire_thread(&la_data->render_data_pool,
|
||||
sizeof(LineartVert) * me->totvert);
|
||||
la_tri_arr = lineart_mem_acquire_thread(&re_buf->render_data_pool,
|
||||
tot_tri * re_buf->triangle_size);
|
||||
la_tri_arr = lineart_mem_acquire_thread(&la_data->render_data_pool,
|
||||
tot_tri * la_data->sizeof_triangle);
|
||||
|
||||
Object *orig_ob = ob_info->original_ob;
|
||||
|
||||
BLI_spin_lock(&re_buf->lock_task);
|
||||
elem_link_node = lineart_list_append_pointer_pool_sized_thread(&re_buf->vertex_buffer_pointers,
|
||||
&re_buf->render_data_pool,
|
||||
la_v_arr,
|
||||
sizeof(LineartElementLinkNode));
|
||||
BLI_spin_unlock(&re_buf->lock_task);
|
||||
BLI_spin_lock(&la_data->lock_task);
|
||||
elem_link_node = lineart_list_append_pointer_pool_sized_thread(
|
||||
&la_data->geom.vertex_buffer_pointers,
|
||||
&la_data->render_data_pool,
|
||||
la_v_arr,
|
||||
sizeof(LineartElementLinkNode));
|
||||
BLI_spin_unlock(&la_data->lock_task);
|
||||
|
||||
elem_link_node->element_count = me->totvert;
|
||||
elem_link_node->object_ref = orig_ob;
|
||||
@@ -1993,7 +1992,7 @@ static void lineart_geometry_object_load(LineartObjectInfo *ob_info, LineartRend
|
||||
use_auto_smooth = true;
|
||||
}
|
||||
else {
|
||||
crease_angle = re_buf->crease_threshold;
|
||||
crease_angle = la_data->conf.crease_threshold;
|
||||
}
|
||||
|
||||
/* FIXME(Yiming): Hack for getting clean 3D text, the seam that extruded text object creates
|
||||
@@ -2002,12 +2001,13 @@ static void lineart_geometry_object_load(LineartObjectInfo *ob_info, LineartRend
|
||||
elem_link_node->flags |= LRT_ELEMENT_BORDER_ONLY;
|
||||
}
|
||||
|
||||
BLI_spin_lock(&re_buf->lock_task);
|
||||
elem_link_node = lineart_list_append_pointer_pool_sized_thread(&re_buf->triangle_buffer_pointers,
|
||||
&re_buf->render_data_pool,
|
||||
la_tri_arr,
|
||||
sizeof(LineartElementLinkNode));
|
||||
BLI_spin_unlock(&re_buf->lock_task);
|
||||
BLI_spin_lock(&la_data->lock_task);
|
||||
elem_link_node = lineart_list_append_pointer_pool_sized_thread(
|
||||
&la_data->geom.triangle_buffer_pointers,
|
||||
&la_data->render_data_pool,
|
||||
la_tri_arr,
|
||||
sizeof(LineartElementLinkNode));
|
||||
BLI_spin_unlock(&la_data->lock_task);
|
||||
|
||||
int usage = ob_info->usage;
|
||||
|
||||
@@ -2019,10 +2019,10 @@ static void lineart_geometry_object_load(LineartObjectInfo *ob_info, LineartRend
|
||||
LineartTriangleAdjacent *tri_adj = MEM_callocN(sizeof(LineartTriangleAdjacent) * tot_tri,
|
||||
"LineartTriangleAdjacent");
|
||||
/* Link is minimal so we use pool anyway. */
|
||||
BLI_spin_lock(&re_buf->lock_task);
|
||||
BLI_spin_lock(&la_data->lock_task);
|
||||
lineart_list_append_pointer_pool_thread(
|
||||
&re_buf->triangle_adjacent_pointers, &re_buf->render_data_pool, tri_adj);
|
||||
BLI_spin_unlock(&re_buf->lock_task);
|
||||
&la_data->geom.triangle_adjacent_pointers, &la_data->render_data_pool, tri_adj);
|
||||
BLI_spin_unlock(&la_data->lock_task);
|
||||
|
||||
/* Convert all vertices to lineart verts. */
|
||||
TaskParallelSettings vert_settings;
|
||||
@@ -2051,7 +2051,7 @@ static void lineart_geometry_object_load(LineartObjectInfo *ob_info, LineartRend
|
||||
tri_data.mlooptri = mlooptri;
|
||||
tri_data.vert_arr = la_v_arr;
|
||||
tri_data.tri_arr = la_tri_arr;
|
||||
tri_data.lineart_triangle_size = re_buf->triangle_size;
|
||||
tri_data.lineart_triangle_size = la_data->sizeof_triangle;
|
||||
tri_data.tri_adj = tri_adj;
|
||||
|
||||
unsigned int total_edges = tot_tri * 3;
|
||||
@@ -2072,7 +2072,7 @@ static void lineart_geometry_object_load(LineartObjectInfo *ob_info, LineartRend
|
||||
edge_feat_settings.func_reduce = feat_data_sum_reduce;
|
||||
|
||||
EdgeFeatData edge_feat_data = {0};
|
||||
edge_feat_data.rb = re_buf;
|
||||
edge_feat_data.ld = la_data;
|
||||
edge_feat_data.me = me;
|
||||
edge_feat_data.mlooptri = mlooptri;
|
||||
edge_feat_data.edge_nabr = lineart_build_edge_neighbor(me, total_edges);
|
||||
@@ -2098,7 +2098,7 @@ static void lineart_geometry_object_load(LineartObjectInfo *ob_info, LineartRend
|
||||
&edge_feat_settings);
|
||||
|
||||
LooseEdgeData loose_data = {0};
|
||||
if (re_buf->use_loose) {
|
||||
if (la_data->conf.use_loose) {
|
||||
/* Only identifying floating edges at this point because other edges has been taken care of
|
||||
* inside #lineart_identify_mlooptri_feature_edges function. */
|
||||
TaskParallelSettings edge_loose_settings;
|
||||
@@ -2114,16 +2114,17 @@ static void lineart_geometry_object_load(LineartObjectInfo *ob_info, LineartRend
|
||||
|
||||
int allocate_la_e = edge_reduce.feat_edges + loose_data.loose_count;
|
||||
|
||||
la_edge_arr = lineart_mem_acquire_thread(&re_buf->render_data_pool,
|
||||
la_edge_arr = lineart_mem_acquire_thread(&la_data->render_data_pool,
|
||||
sizeof(LineartEdge) * allocate_la_e);
|
||||
la_seg_arr = lineart_mem_acquire_thread(&re_buf->render_data_pool,
|
||||
la_seg_arr = lineart_mem_acquire_thread(&la_data->render_data_pool,
|
||||
sizeof(LineartEdgeSegment) * allocate_la_e);
|
||||
BLI_spin_lock(&re_buf->lock_task);
|
||||
elem_link_node = lineart_list_append_pointer_pool_sized_thread(&re_buf->line_buffer_pointers,
|
||||
&re_buf->render_data_pool,
|
||||
la_edge_arr,
|
||||
sizeof(LineartElementLinkNode));
|
||||
BLI_spin_unlock(&re_buf->lock_task);
|
||||
BLI_spin_lock(&la_data->lock_task);
|
||||
elem_link_node = lineart_list_append_pointer_pool_sized_thread(
|
||||
&la_data->geom.line_buffer_pointers,
|
||||
&la_data->render_data_pool,
|
||||
la_edge_arr,
|
||||
sizeof(LineartElementLinkNode));
|
||||
BLI_spin_unlock(&la_data->lock_task);
|
||||
elem_link_node->element_count = allocate_la_e;
|
||||
elem_link_node->object_ref = orig_ob;
|
||||
|
||||
@@ -2157,13 +2158,13 @@ static void lineart_geometry_object_load(LineartObjectInfo *ob_info, LineartRend
|
||||
la_edge->v1 = &la_v_arr[edge_nabr->v1];
|
||||
la_edge->v2 = &la_v_arr[edge_nabr->v2];
|
||||
int findex = i / 3;
|
||||
la_edge->t1 = lineart_triangle_from_index(re_buf, la_tri_arr, findex);
|
||||
la_edge->t1 = lineart_triangle_from_index(la_data, la_tri_arr, findex);
|
||||
if (!edge_added) {
|
||||
lineart_triangle_adjacent_assign(la_edge->t1, &tri_adj[findex], la_edge);
|
||||
}
|
||||
if (edge_nabr->e != -1) {
|
||||
findex = edge_nabr->e / 3;
|
||||
la_edge->t2 = lineart_triangle_from_index(re_buf, la_tri_arr, findex);
|
||||
la_edge->t2 = lineart_triangle_from_index(la_data, la_tri_arr, findex);
|
||||
if (!edge_added) {
|
||||
lineart_triangle_adjacent_assign(la_edge->t2, &tri_adj[findex], la_edge);
|
||||
}
|
||||
@@ -2185,7 +2186,7 @@ static void lineart_geometry_object_load(LineartObjectInfo *ob_info, LineartRend
|
||||
la_edge++;
|
||||
la_seg++;
|
||||
|
||||
if (!re_buf->allow_duplicated_types) {
|
||||
if (!la_data->conf.allow_duplicated_types) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -2219,7 +2220,7 @@ static void lineart_object_load_worker(TaskPool *__restrict UNUSED(pool),
|
||||
LineartObjectLoadTaskInfo *olti)
|
||||
{
|
||||
for (LineartObjectInfo *obi = olti->pending; obi; obi = obi->next) {
|
||||
lineart_geometry_object_load(obi, olti->rb);
|
||||
lineart_geometry_object_load(obi, olti->ld);
|
||||
if (G.debug_value == 4000) {
|
||||
printf("thread id: %d processed: %d\n", olti->thread_id, obi->original_me->totpoly);
|
||||
}
|
||||
@@ -2356,7 +2357,7 @@ static bool lineart_geometry_check_visible(double (*model_view_proj)[4],
|
||||
return true;
|
||||
}
|
||||
|
||||
static void lineart_object_load_single_instance(LineartRenderBuffer *rb,
|
||||
static void lineart_object_load_single_instance(LineartData *ld,
|
||||
Depsgraph *depsgraph,
|
||||
Scene *scene,
|
||||
Object *ob,
|
||||
@@ -2366,7 +2367,7 @@ static void lineart_object_load_single_instance(LineartRenderBuffer *rb,
|
||||
LineartObjectLoadTaskInfo *olti,
|
||||
int thread_count)
|
||||
{
|
||||
LineartObjectInfo *obi = lineart_mem_acquire(&rb->render_data_pool, sizeof(LineartObjectInfo));
|
||||
LineartObjectInfo *obi = lineart_mem_acquire(&ld->render_data_pool, sizeof(LineartObjectInfo));
|
||||
obi->usage = lineart_usage_check(scene->master_collection, ob, is_render);
|
||||
obi->override_intersection_mask = lineart_intersection_mask_check(scene->master_collection, ob);
|
||||
Mesh *use_mesh;
|
||||
@@ -2377,8 +2378,8 @@ static void lineart_object_load_single_instance(LineartRenderBuffer *rb,
|
||||
|
||||
/* Prepare the matrix used for transforming this specific object (instance). This has to be
|
||||
* done before mesh boundbox check because the function needs that. */
|
||||
mul_m4db_m4db_m4fl_uniq(obi->model_view_proj, rb->view_projection, use_mat);
|
||||
mul_m4db_m4db_m4fl_uniq(obi->model_view, rb->view, use_mat);
|
||||
mul_m4db_m4db_m4fl_uniq(obi->model_view_proj, ld->conf.view_projection, use_mat);
|
||||
mul_m4db_m4db_m4fl_uniq(obi->model_view, ld->conf.view, use_mat);
|
||||
|
||||
if (!ELEM(ob->type, OB_MESH, OB_MBALL, OB_CURVES_LEGACY, OB_SURF, OB_FONT)) {
|
||||
return;
|
||||
@@ -2400,7 +2401,8 @@ static void lineart_object_load_single_instance(LineartRenderBuffer *rb,
|
||||
return;
|
||||
}
|
||||
|
||||
if (!lineart_geometry_check_visible(obi->model_view_proj, rb->shift_x, rb->shift_y, use_mesh)) {
|
||||
if (!lineart_geometry_check_visible(
|
||||
obi->model_view_proj, ld->conf.shift_x, ld->conf.shift_y, use_mesh)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -2423,15 +2425,15 @@ static void lineart_main_load_geometries(
|
||||
Depsgraph *depsgraph,
|
||||
Scene *scene,
|
||||
Object *camera /* Still use camera arg for convenience. */,
|
||||
LineartRenderBuffer *rb,
|
||||
LineartData *ld,
|
||||
bool allow_duplicates)
|
||||
{
|
||||
double proj[4][4], view[4][4], result[4][4];
|
||||
float inv[4][4];
|
||||
Camera *cam = camera->data;
|
||||
float sensor = BKE_camera_sensor_size(cam->sensor_fit, cam->sensor_x, cam->sensor_y);
|
||||
int fit = BKE_camera_sensor_fit(cam->sensor_fit, rb->w, rb->h);
|
||||
double asp = ((double)rb->w / (double)rb->h);
|
||||
int fit = BKE_camera_sensor_fit(cam->sensor_fit, ld->w, ld->h);
|
||||
double asp = ((double)ld->w / (double)ld->h);
|
||||
|
||||
int bound_box_discard_count = 0;
|
||||
|
||||
@@ -2442,7 +2444,7 @@ static void lineart_main_load_geometries(
|
||||
if (fit == CAMERA_SENSOR_FIT_HOR && asp < 1) {
|
||||
sensor /= asp;
|
||||
}
|
||||
const double fov = focallength_to_fov(cam->lens / (1 + rb->overscan), sensor);
|
||||
const double fov = focallength_to_fov(cam->lens / (1 + ld->conf.overscan), sensor);
|
||||
lineart_matrix_perspective_44d(proj, fov, asp, cam->clip_start, cam->clip_end);
|
||||
}
|
||||
else if (cam->type == CAM_ORTHO) {
|
||||
@@ -2456,23 +2458,23 @@ static void lineart_main_load_geometries(
|
||||
t_start = PIL_check_seconds_timer();
|
||||
}
|
||||
|
||||
invert_m4_m4(inv, rb->cam_obmat);
|
||||
invert_m4_m4(inv, ld->conf.cam_obmat);
|
||||
mul_m4db_m4db_m4fl_uniq(result, proj, inv);
|
||||
copy_m4_m4_db(proj, result);
|
||||
copy_m4_m4_db(rb->view_projection, proj);
|
||||
copy_m4_m4_db(ld->conf.view_projection, proj);
|
||||
|
||||
unit_m4_db(view);
|
||||
copy_m4_m4_db(rb->view, view);
|
||||
copy_m4_m4_db(ld->conf.view, view);
|
||||
|
||||
BLI_listbase_clear(&rb->triangle_buffer_pointers);
|
||||
BLI_listbase_clear(&rb->vertex_buffer_pointers);
|
||||
BLI_listbase_clear(&ld->geom.triangle_buffer_pointers);
|
||||
BLI_listbase_clear(&ld->geom.vertex_buffer_pointers);
|
||||
|
||||
int thread_count = rb->thread_count;
|
||||
int thread_count = ld->thread_count;
|
||||
|
||||
/* This memory is in render buffer memory pool. so we don't need to free those after loading.
|
||||
*/
|
||||
LineartObjectLoadTaskInfo *olti = lineart_mem_acquire(
|
||||
&rb->render_data_pool, sizeof(LineartObjectLoadTaskInfo) * thread_count);
|
||||
&ld->render_data_pool, sizeof(LineartObjectLoadTaskInfo) * thread_count);
|
||||
|
||||
eEvaluationMode eval_mode = DEG_get_mode(depsgraph);
|
||||
bool is_render = eval_mode == DAG_EVAL_RENDER;
|
||||
@@ -2502,7 +2504,7 @@ static void lineart_main_load_geometries(
|
||||
|
||||
if (BKE_object_visibility(eval_ob, eval_mode) & OB_VISIBLE_SELF) {
|
||||
lineart_object_load_single_instance(
|
||||
rb, depsgraph, scene, eval_ob, eval_ob, eval_ob->obmat, is_render, olti, thread_count);
|
||||
ld, depsgraph, scene, eval_ob, eval_ob, eval_ob->obmat, is_render, olti, thread_count);
|
||||
}
|
||||
}
|
||||
DEG_OBJECT_ITER_END;
|
||||
@@ -2513,7 +2515,7 @@ static void lineart_main_load_geometries(
|
||||
printf("thread count: %d\n", thread_count);
|
||||
}
|
||||
for (int i = 0; i < thread_count; i++) {
|
||||
olti[i].rb = rb;
|
||||
olti[i].ld = ld;
|
||||
olti[i].thread_id = i;
|
||||
BLI_task_pool_push(tp, (TaskRunFunction)lineart_object_load_worker, &olti[i], 0, NULL);
|
||||
}
|
||||
@@ -2533,7 +2535,7 @@ static void lineart_main_load_geometries(
|
||||
edge_count += obi->pending_edges.next;
|
||||
}
|
||||
}
|
||||
lineart_finalize_object_edge_array_reserve(&rb->pending_edges, edge_count);
|
||||
lineart_finalize_object_edge_array_reserve(&ld->pending_edges, edge_count);
|
||||
|
||||
for (int i = 0; i < thread_count; i++) {
|
||||
for (LineartObjectInfo *obi = olti[i].pending; obi; obi = obi->next) {
|
||||
@@ -2551,7 +2553,7 @@ static void lineart_main_load_geometries(
|
||||
* same numeric index to come close together. */
|
||||
obi->global_i_offset = global_i;
|
||||
global_i += v_count;
|
||||
lineart_finalize_object_edge_array(&rb->pending_edges, obi);
|
||||
lineart_finalize_object_edge_array(&ld->pending_edges, obi);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3164,38 +3166,38 @@ static void lineart_add_isec_thread(LineartIsecThread *th,
|
||||
|
||||
static bool lineart_schedule_new_triangle_task(LineartIsecThread *th)
|
||||
{
|
||||
LineartRenderBuffer *rb = th->rb;
|
||||
LineartData *ld = th->ld;
|
||||
int remaining = LRT_ISECT_TRIANGLE_PER_THREAD;
|
||||
|
||||
BLI_spin_lock(&rb->lock_task);
|
||||
LineartElementLinkNode *eln = rb->isect_scheduled_up_to;
|
||||
BLI_spin_lock(&ld->lock_task);
|
||||
LineartElementLinkNode *eln = ld->isect_scheduled_up_to;
|
||||
|
||||
if (!eln) {
|
||||
BLI_spin_unlock(&rb->lock_task);
|
||||
BLI_spin_unlock(&ld->lock_task);
|
||||
return false;
|
||||
}
|
||||
|
||||
th->pending_from = eln;
|
||||
th->index_from = rb->isect_scheduled_up_to_index;
|
||||
th->index_from = ld->isect_scheduled_up_to_index;
|
||||
|
||||
while (remaining > 0 && eln) {
|
||||
int remaining_this_eln = eln->element_count - rb->isect_scheduled_up_to_index;
|
||||
int remaining_this_eln = eln->element_count - ld->isect_scheduled_up_to_index;
|
||||
int added_count = MIN2(remaining, remaining_this_eln);
|
||||
remaining -= added_count;
|
||||
if (remaining || added_count == remaining_this_eln) {
|
||||
eln = eln->next;
|
||||
rb->isect_scheduled_up_to = eln;
|
||||
rb->isect_scheduled_up_to_index = 0;
|
||||
ld->isect_scheduled_up_to = eln;
|
||||
ld->isect_scheduled_up_to_index = 0;
|
||||
}
|
||||
else {
|
||||
rb->isect_scheduled_up_to_index += added_count;
|
||||
ld->isect_scheduled_up_to_index += added_count;
|
||||
}
|
||||
}
|
||||
|
||||
th->pending_to = eln ? eln : rb->triangle_buffer_pointers.last;
|
||||
th->index_to = rb->isect_scheduled_up_to_index;
|
||||
th->pending_to = eln ? eln : ld->geom.triangle_buffer_pointers.last;
|
||||
th->index_to = ld->isect_scheduled_up_to_index;
|
||||
|
||||
BLI_spin_unlock(&rb->lock_task);
|
||||
BLI_spin_unlock(&ld->lock_task);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -3205,14 +3207,14 @@ static bool lineart_schedule_new_triangle_task(LineartIsecThread *th)
|
||||
* 2) Per-thread intersection result array. Does not store actual #LineartEdge, these results will
|
||||
* be finalized by #lineart_create_edges_from_isec_data
|
||||
*/
|
||||
static void lineart_init_isec_thread(LineartIsecData *d, LineartRenderBuffer *rb, int thread_count)
|
||||
static void lineart_init_isec_thread(LineartIsecData *d, LineartData *ld, int thread_count)
|
||||
{
|
||||
d->threads = MEM_callocN(sizeof(LineartIsecThread) * thread_count, "LineartIsecThread arr");
|
||||
d->rb = rb;
|
||||
d->ld = ld;
|
||||
d->thread_count = thread_count;
|
||||
|
||||
rb->isect_scheduled_up_to = rb->triangle_buffer_pointers.first;
|
||||
rb->isect_scheduled_up_to_index = 0;
|
||||
ld->isect_scheduled_up_to = ld->geom.triangle_buffer_pointers.first;
|
||||
ld->isect_scheduled_up_to_index = 0;
|
||||
|
||||
for (int i = 0; i < thread_count; i++) {
|
||||
LineartIsecThread *it = &d->threads[i];
|
||||
@@ -3220,7 +3222,7 @@ static void lineart_init_isec_thread(LineartIsecData *d, LineartRenderBuffer *rb
|
||||
it->max = 100;
|
||||
it->current = 0;
|
||||
it->thread_id = i;
|
||||
it->rb = rb;
|
||||
it->ld = ld;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3290,14 +3292,14 @@ static void lineart_triangle_intersect_in_bounding_area(LineartTriangle *tri,
|
||||
/**
|
||||
* The calculated view vector will point towards the far-plane from the camera position.
|
||||
*/
|
||||
static void lineart_main_get_view_vector(LineartRenderBuffer *rb)
|
||||
static void lineart_main_get_view_vector(LineartData *ld)
|
||||
{
|
||||
float direction[3] = {0, 0, 1};
|
||||
float trans[3];
|
||||
float inv[4][4];
|
||||
float obmat_no_scale[4][4];
|
||||
|
||||
copy_m4_m4(obmat_no_scale, rb->cam_obmat);
|
||||
copy_m4_m4(obmat_no_scale, ld->conf.cam_obmat);
|
||||
|
||||
normalize_v3(obmat_no_scale[0]);
|
||||
normalize_v3(obmat_no_scale[1]);
|
||||
@@ -3305,45 +3307,45 @@ static void lineart_main_get_view_vector(LineartRenderBuffer *rb)
|
||||
invert_m4_m4(inv, obmat_no_scale);
|
||||
transpose_m4(inv);
|
||||
mul_v3_mat3_m4v3(trans, inv, direction);
|
||||
copy_m4_m4(rb->cam_obmat, obmat_no_scale);
|
||||
copy_v3db_v3fl(rb->view_vector, trans);
|
||||
copy_m4_m4(ld->conf.cam_obmat, obmat_no_scale);
|
||||
copy_v3db_v3fl(ld->conf.view_vector, trans);
|
||||
}
|
||||
|
||||
static void lineart_destroy_render_data(LineartRenderBuffer *rb)
|
||||
static void lineart_destroy_render_data(LineartData *ld)
|
||||
{
|
||||
if (rb == NULL) {
|
||||
if (ld == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
BLI_listbase_clear(&rb->chains);
|
||||
BLI_listbase_clear(&rb->wasted_cuts);
|
||||
BLI_listbase_clear(&ld->chains);
|
||||
BLI_listbase_clear(&ld->wasted_cuts);
|
||||
|
||||
BLI_listbase_clear(&rb->vertex_buffer_pointers);
|
||||
BLI_listbase_clear(&rb->line_buffer_pointers);
|
||||
BLI_listbase_clear(&rb->triangle_buffer_pointers);
|
||||
BLI_listbase_clear(&ld->geom.vertex_buffer_pointers);
|
||||
BLI_listbase_clear(&ld->geom.line_buffer_pointers);
|
||||
BLI_listbase_clear(&ld->geom.triangle_buffer_pointers);
|
||||
|
||||
BLI_spin_end(&rb->lock_task);
|
||||
BLI_spin_end(&rb->lock_cuts);
|
||||
BLI_spin_end(&rb->render_data_pool.lock_mem);
|
||||
BLI_spin_end(&ld->lock_task);
|
||||
BLI_spin_end(&ld->lock_cuts);
|
||||
BLI_spin_end(&ld->render_data_pool.lock_mem);
|
||||
|
||||
if (rb->pending_edges.array) {
|
||||
MEM_freeN(rb->pending_edges.array);
|
||||
if (ld->pending_edges.array) {
|
||||
MEM_freeN(ld->pending_edges.array);
|
||||
}
|
||||
|
||||
lineart_free_bounding_area_memories(rb);
|
||||
lineart_free_bounding_area_memories(ld);
|
||||
|
||||
lineart_mem_destroy(&rb->render_data_pool);
|
||||
lineart_mem_destroy(&ld->render_data_pool);
|
||||
}
|
||||
|
||||
void MOD_lineart_destroy_render_data(LineartGpencilModifierData *lmd)
|
||||
{
|
||||
LineartRenderBuffer *rb = lmd->render_buffer_ptr;
|
||||
LineartData *ld = lmd->la_data_ptr;
|
||||
|
||||
lineart_destroy_render_data(rb);
|
||||
lineart_destroy_render_data(ld);
|
||||
|
||||
if (rb) {
|
||||
MEM_freeN(rb);
|
||||
lmd->render_buffer_ptr = NULL;
|
||||
if (ld) {
|
||||
MEM_freeN(ld);
|
||||
lmd->la_data_ptr = NULL;
|
||||
}
|
||||
|
||||
if (G.debug_value == 4000) {
|
||||
@@ -3367,16 +3369,16 @@ void MOD_lineart_clear_cache(struct LineartCache **lc)
|
||||
(*lc) = NULL;
|
||||
}
|
||||
|
||||
static LineartRenderBuffer *lineart_create_render_buffer(Scene *scene,
|
||||
LineartGpencilModifierData *lmd,
|
||||
Object *camera,
|
||||
Object *active_camera,
|
||||
LineartCache *lc)
|
||||
static LineartData *lineart_create_render_buffer(Scene *scene,
|
||||
LineartGpencilModifierData *lmd,
|
||||
Object *camera,
|
||||
Object *active_camera,
|
||||
LineartCache *lc)
|
||||
{
|
||||
LineartRenderBuffer *rb = MEM_callocN(sizeof(LineartRenderBuffer), "Line Art render buffer");
|
||||
LineartData *ld = MEM_callocN(sizeof(LineartData), "Line Art render buffer");
|
||||
|
||||
lmd->cache = lc;
|
||||
lmd->render_buffer_ptr = rb;
|
||||
lmd->la_data_ptr = ld;
|
||||
lc->rb_edge_types = lmd->edge_types_override;
|
||||
|
||||
if (!scene || !camera || !lc) {
|
||||
@@ -3390,97 +3392,97 @@ static LineartRenderBuffer *lineart_create_render_buffer(Scene *scene,
|
||||
clipping_offset = 0.0001;
|
||||
}
|
||||
|
||||
copy_v3db_v3fl(rb->camera_pos, camera->obmat[3]);
|
||||
copy_v3db_v3fl(ld->conf.camera_pos, camera->obmat[3]);
|
||||
if (active_camera) {
|
||||
copy_v3db_v3fl(rb->active_camera_pos, active_camera->obmat[3]);
|
||||
copy_v3db_v3fl(ld->conf.active_camera_pos, active_camera->obmat[3]);
|
||||
}
|
||||
copy_m4_m4(rb->cam_obmat, camera->obmat);
|
||||
rb->cam_is_persp = (c->type == CAM_PERSP);
|
||||
rb->near_clip = c->clip_start + clipping_offset;
|
||||
rb->far_clip = c->clip_end - clipping_offset;
|
||||
rb->w = scene->r.xsch;
|
||||
rb->h = scene->r.ysch;
|
||||
copy_m4_m4(ld->conf.cam_obmat, camera->obmat);
|
||||
ld->conf.cam_is_persp = (c->type == CAM_PERSP);
|
||||
ld->conf.near_clip = c->clip_start + clipping_offset;
|
||||
ld->conf.far_clip = c->clip_end - clipping_offset;
|
||||
ld->w = scene->r.xsch;
|
||||
ld->h = scene->r.ysch;
|
||||
|
||||
if (rb->cam_is_persp) {
|
||||
rb->tile_recursive_level = LRT_TILE_RECURSIVE_PERSPECTIVE;
|
||||
if (ld->conf.cam_is_persp) {
|
||||
ld->qtree.recursive_level = LRT_TILE_RECURSIVE_PERSPECTIVE;
|
||||
}
|
||||
else {
|
||||
rb->tile_recursive_level = LRT_TILE_RECURSIVE_ORTHO;
|
||||
ld->qtree.recursive_level = LRT_TILE_RECURSIVE_ORTHO;
|
||||
}
|
||||
|
||||
double asp = ((double)rb->w / (double)rb->h);
|
||||
int fit = BKE_camera_sensor_fit(c->sensor_fit, rb->w, rb->h);
|
||||
rb->shift_x = fit == CAMERA_SENSOR_FIT_HOR ? c->shiftx : c->shiftx / asp;
|
||||
rb->shift_y = fit == CAMERA_SENSOR_FIT_VERT ? c->shifty : c->shifty * asp;
|
||||
double asp = ((double)ld->w / (double)ld->h);
|
||||
int fit = BKE_camera_sensor_fit(c->sensor_fit, ld->w, ld->h);
|
||||
ld->conf.shift_x = fit == CAMERA_SENSOR_FIT_HOR ? c->shiftx : c->shiftx / asp;
|
||||
ld->conf.shift_y = fit == CAMERA_SENSOR_FIT_VERT ? c->shifty : c->shifty * asp;
|
||||
|
||||
rb->overscan = lmd->overscan;
|
||||
ld->conf.overscan = lmd->overscan;
|
||||
|
||||
rb->shift_x /= (1 + rb->overscan);
|
||||
rb->shift_y /= (1 + rb->overscan);
|
||||
ld->conf.shift_x /= (1 + ld->conf.overscan);
|
||||
ld->conf.shift_y /= (1 + ld->conf.overscan);
|
||||
|
||||
rb->crease_threshold = cos(M_PI - lmd->crease_threshold);
|
||||
rb->chaining_image_threshold = lmd->chaining_image_threshold;
|
||||
rb->angle_splitting_threshold = lmd->angle_splitting_threshold;
|
||||
rb->chain_smooth_tolerance = lmd->chain_smooth_tolerance;
|
||||
ld->conf.crease_threshold = cos(M_PI - lmd->crease_threshold);
|
||||
ld->conf.chaining_image_threshold = lmd->chaining_image_threshold;
|
||||
ld->conf.angle_splitting_threshold = lmd->angle_splitting_threshold;
|
||||
ld->conf.chain_smooth_tolerance = lmd->chain_smooth_tolerance;
|
||||
|
||||
rb->fuzzy_intersections = (lmd->calculation_flags & LRT_INTERSECTION_AS_CONTOUR) != 0;
|
||||
rb->fuzzy_everything = (lmd->calculation_flags & LRT_EVERYTHING_AS_CONTOUR) != 0;
|
||||
rb->allow_boundaries = (lmd->calculation_flags & LRT_ALLOW_CLIPPING_BOUNDARIES) != 0;
|
||||
rb->use_loose_as_contour = (lmd->calculation_flags & LRT_LOOSE_AS_CONTOUR) != 0;
|
||||
rb->use_loose_edge_chain = (lmd->calculation_flags & LRT_CHAIN_LOOSE_EDGES) != 0;
|
||||
rb->use_geometry_space_chain = (lmd->calculation_flags & LRT_CHAIN_GEOMETRY_SPACE) != 0;
|
||||
rb->use_image_boundary_trimming = (lmd->calculation_flags & LRT_USE_IMAGE_BOUNDARY_TRIMMING) !=
|
||||
0;
|
||||
ld->conf.fuzzy_intersections = (lmd->calculation_flags & LRT_INTERSECTION_AS_CONTOUR) != 0;
|
||||
ld->conf.fuzzy_everything = (lmd->calculation_flags & LRT_EVERYTHING_AS_CONTOUR) != 0;
|
||||
ld->conf.allow_boundaries = (lmd->calculation_flags & LRT_ALLOW_CLIPPING_BOUNDARIES) != 0;
|
||||
ld->conf.use_loose_as_contour = (lmd->calculation_flags & LRT_LOOSE_AS_CONTOUR) != 0;
|
||||
ld->conf.use_loose_edge_chain = (lmd->calculation_flags & LRT_CHAIN_LOOSE_EDGES) != 0;
|
||||
ld->conf.use_geometry_space_chain = (lmd->calculation_flags & LRT_CHAIN_GEOMETRY_SPACE) != 0;
|
||||
ld->conf.use_image_boundary_trimming = (lmd->calculation_flags &
|
||||
LRT_USE_IMAGE_BOUNDARY_TRIMMING) != 0;
|
||||
|
||||
/* See lineart_edge_from_triangle() for how this option may impact performance. */
|
||||
rb->allow_overlapping_edges = (lmd->calculation_flags & LRT_ALLOW_OVERLAPPING_EDGES) != 0;
|
||||
ld->conf.allow_overlapping_edges = (lmd->calculation_flags & LRT_ALLOW_OVERLAPPING_EDGES) != 0;
|
||||
|
||||
rb->allow_duplicated_types = (lmd->calculation_flags & LRT_ALLOW_OVERLAP_EDGE_TYPES) != 0;
|
||||
ld->conf.allow_duplicated_types = (lmd->calculation_flags & LRT_ALLOW_OVERLAP_EDGE_TYPES) != 0;
|
||||
|
||||
rb->force_crease = (lmd->calculation_flags & LRT_USE_CREASE_ON_SMOOTH_SURFACES) != 0;
|
||||
rb->sharp_as_crease = (lmd->calculation_flags & LRT_USE_CREASE_ON_SHARP_EDGES) != 0;
|
||||
ld->conf.force_crease = (lmd->calculation_flags & LRT_USE_CREASE_ON_SMOOTH_SURFACES) != 0;
|
||||
ld->conf.sharp_as_crease = (lmd->calculation_flags & LRT_USE_CREASE_ON_SHARP_EDGES) != 0;
|
||||
|
||||
rb->chain_preserve_details = (lmd->calculation_flags & LRT_CHAIN_PRESERVE_DETAILS) != 0;
|
||||
ld->conf.chain_preserve_details = (lmd->calculation_flags & LRT_CHAIN_PRESERVE_DETAILS) != 0;
|
||||
|
||||
/* This is used to limit calculation to a certain level to save time, lines who have higher
|
||||
* occlusion levels will get ignored. */
|
||||
rb->max_occlusion_level = lmd->level_end_override;
|
||||
ld->conf.max_occlusion_level = lmd->level_end_override;
|
||||
|
||||
rb->use_back_face_culling = (lmd->calculation_flags & LRT_USE_BACK_FACE_CULLING) != 0;
|
||||
ld->conf.use_back_face_culling = (lmd->calculation_flags & LRT_USE_BACK_FACE_CULLING) != 0;
|
||||
|
||||
int16_t edge_types = lmd->edge_types_override;
|
||||
|
||||
rb->use_contour = (edge_types & LRT_EDGE_FLAG_CONTOUR) != 0;
|
||||
rb->use_crease = (edge_types & LRT_EDGE_FLAG_CREASE) != 0;
|
||||
rb->use_material = (edge_types & LRT_EDGE_FLAG_MATERIAL) != 0;
|
||||
rb->use_edge_marks = (edge_types & LRT_EDGE_FLAG_EDGE_MARK) != 0;
|
||||
rb->use_intersections = (edge_types & LRT_EDGE_FLAG_INTERSECTION) != 0;
|
||||
rb->use_loose = (edge_types & LRT_EDGE_FLAG_LOOSE) != 0;
|
||||
ld->conf.use_contour = (edge_types & LRT_EDGE_FLAG_CONTOUR) != 0;
|
||||
ld->conf.use_crease = (edge_types & LRT_EDGE_FLAG_CREASE) != 0;
|
||||
ld->conf.use_material = (edge_types & LRT_EDGE_FLAG_MATERIAL) != 0;
|
||||
ld->conf.use_edge_marks = (edge_types & LRT_EDGE_FLAG_EDGE_MARK) != 0;
|
||||
ld->conf.use_intersections = (edge_types & LRT_EDGE_FLAG_INTERSECTION) != 0;
|
||||
ld->conf.use_loose = (edge_types & LRT_EDGE_FLAG_LOOSE) != 0;
|
||||
|
||||
rb->filter_face_mark_invert = (lmd->calculation_flags & LRT_FILTER_FACE_MARK_INVERT) != 0;
|
||||
rb->filter_face_mark = (lmd->calculation_flags & LRT_FILTER_FACE_MARK) != 0;
|
||||
rb->filter_face_mark_boundaries = (lmd->calculation_flags & LRT_FILTER_FACE_MARK_BOUNDARIES) !=
|
||||
0;
|
||||
rb->filter_face_mark_keep_contour = (lmd->calculation_flags &
|
||||
LRT_FILTER_FACE_MARK_KEEP_CONTOUR) != 0;
|
||||
ld->conf.filter_face_mark_invert = (lmd->calculation_flags & LRT_FILTER_FACE_MARK_INVERT) != 0;
|
||||
ld->conf.filter_face_mark = (lmd->calculation_flags & LRT_FILTER_FACE_MARK) != 0;
|
||||
ld->conf.filter_face_mark_boundaries = (lmd->calculation_flags &
|
||||
LRT_FILTER_FACE_MARK_BOUNDARIES) != 0;
|
||||
ld->conf.filter_face_mark_keep_contour = (lmd->calculation_flags &
|
||||
LRT_FILTER_FACE_MARK_KEEP_CONTOUR) != 0;
|
||||
|
||||
rb->chain_data_pool = &lc->chain_data_pool;
|
||||
ld->chain_data_pool = &lc->chain_data_pool;
|
||||
|
||||
BLI_spin_init(&rb->lock_task);
|
||||
BLI_spin_init(&rb->lock_cuts);
|
||||
BLI_spin_init(&rb->render_data_pool.lock_mem);
|
||||
BLI_spin_init(&ld->lock_task);
|
||||
BLI_spin_init(&ld->lock_cuts);
|
||||
BLI_spin_init(&ld->render_data_pool.lock_mem);
|
||||
|
||||
rb->thread_count = BKE_render_num_threads(&scene->r);
|
||||
ld->thread_count = BKE_render_num_threads(&scene->r);
|
||||
|
||||
return rb;
|
||||
return ld;
|
||||
}
|
||||
|
||||
static int lineart_triangle_size_get(LineartRenderBuffer *rb)
|
||||
static int lineart_triangle_size_get(LineartData *ld)
|
||||
{
|
||||
return sizeof(LineartTriangle) + (sizeof(LineartEdge *) * (rb->thread_count));
|
||||
return sizeof(LineartTriangle) + (sizeof(LineartEdge *) * (ld->thread_count));
|
||||
}
|
||||
|
||||
static void lineart_main_bounding_area_make_initial(LineartRenderBuffer *rb)
|
||||
static void lineart_main_bounding_area_make_initial(LineartData *ld)
|
||||
{
|
||||
/* Initial tile split is defined as 4 (subdivided as 4*4), increasing the value allows the
|
||||
* algorithm to build the acceleration structure for bigger scenes a little faster but not as
|
||||
@@ -3491,11 +3493,11 @@ static void lineart_main_bounding_area_make_initial(LineartRenderBuffer *rb)
|
||||
LineartBoundingArea *ba;
|
||||
|
||||
/* Always make sure the shortest side has at least LRT_BA_ROWS tiles. */
|
||||
if (rb->w > rb->h) {
|
||||
sp_w = sp_h * rb->w / rb->h;
|
||||
if (ld->w > ld->h) {
|
||||
sp_w = sp_h * ld->w / ld->h;
|
||||
}
|
||||
else {
|
||||
sp_h = sp_w * rb->h / rb->w;
|
||||
sp_h = sp_w * ld->h / ld->w;
|
||||
}
|
||||
|
||||
/* Because NDC (Normalized Device Coordinates) range is (-1,1),
|
||||
@@ -3503,19 +3505,19 @@ static void lineart_main_bounding_area_make_initial(LineartRenderBuffer *rb)
|
||||
double span_w = (double)1 / sp_w * 2.0;
|
||||
double span_h = (double)1 / sp_h * 2.0;
|
||||
|
||||
rb->tile_count_x = sp_w;
|
||||
rb->tile_count_y = sp_h;
|
||||
rb->width_per_tile = span_w;
|
||||
rb->height_per_tile = span_h;
|
||||
ld->qtree.count_x = sp_w;
|
||||
ld->qtree.count_y = sp_h;
|
||||
ld->qtree.tile_width = span_w;
|
||||
ld->qtree.tile_height = span_h;
|
||||
|
||||
rb->bounding_area_count = sp_w * sp_h;
|
||||
rb->initial_bounding_areas = lineart_mem_acquire(
|
||||
&rb->render_data_pool, sizeof(LineartBoundingArea) * rb->bounding_area_count);
|
||||
ld->qtree.tile_count = sp_w * sp_h;
|
||||
ld->qtree.initials = lineart_mem_acquire(&ld->render_data_pool,
|
||||
sizeof(LineartBoundingArea) * ld->qtree.tile_count);
|
||||
|
||||
/* Initialize tiles. */
|
||||
for (row = 0; row < sp_h; row++) {
|
||||
for (col = 0; col < sp_w; col++) {
|
||||
ba = &rb->initial_bounding_areas[row * rb->tile_count_x + col];
|
||||
ba = &ld->qtree.initials[row * ld->qtree.count_x + col];
|
||||
|
||||
/* Set the four direction limits. */
|
||||
ba->l = span_w * col - 1.0;
|
||||
@@ -3542,11 +3544,11 @@ static void lineart_main_bounding_area_make_initial(LineartRenderBuffer *rb)
|
||||
/**
|
||||
* Re-link adjacent tiles after one gets subdivided.
|
||||
*/
|
||||
static void lineart_bounding_areas_connect_new(LineartRenderBuffer *rb, LineartBoundingArea *root)
|
||||
static void lineart_bounding_areas_connect_new(LineartData *ld, LineartBoundingArea *root)
|
||||
{
|
||||
LineartBoundingArea *ba = root->child, *tba;
|
||||
LinkData *lip2, *next_lip;
|
||||
LineartStaticMemPool *mph = &rb->render_data_pool;
|
||||
LineartStaticMemPool *mph = &ld->render_data_pool;
|
||||
|
||||
/* Inter-connection with newly created 4 child bounding areas. */
|
||||
lineart_list_append_pointer_pool(&ba[1].rp, mph, &ba[0]);
|
||||
@@ -3682,54 +3684,45 @@ static void lineart_bounding_areas_connect_new(LineartRenderBuffer *rb, LineartB
|
||||
BLI_listbase_clear(&root->bp);
|
||||
}
|
||||
|
||||
static void lineart_bounding_areas_connect_recursive(LineartRenderBuffer *rb,
|
||||
LineartBoundingArea *root)
|
||||
static void lineart_bounding_areas_connect_recursive(LineartData *ld, LineartBoundingArea *root)
|
||||
{
|
||||
if (root->child) {
|
||||
lineart_bounding_areas_connect_new(rb, root);
|
||||
lineart_bounding_areas_connect_new(ld, root);
|
||||
for (int i = 0; i < 4; i++) {
|
||||
lineart_bounding_areas_connect_recursive(rb, &root->child[i]);
|
||||
lineart_bounding_areas_connect_recursive(ld, &root->child[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void lineart_main_bounding_areas_connect_post(LineartRenderBuffer *rb)
|
||||
static void lineart_main_bounding_areas_connect_post(LineartData *ld)
|
||||
{
|
||||
int total_tile_initial = rb->tile_count_x * rb->tile_count_y;
|
||||
int tiles_per_row = rb->tile_count_x;
|
||||
int total_tile_initial = ld->qtree.count_x * ld->qtree.count_y;
|
||||
int tiles_per_row = ld->qtree.count_x;
|
||||
|
||||
for (int row = 0; row < rb->tile_count_y; row++) {
|
||||
for (int col = 0; col < rb->tile_count_x; col++) {
|
||||
LineartBoundingArea *ba = &rb->initial_bounding_areas[row * tiles_per_row + col];
|
||||
for (int row = 0; row < ld->qtree.count_y; row++) {
|
||||
for (int col = 0; col < ld->qtree.count_x; col++) {
|
||||
LineartBoundingArea *ba = &ld->qtree.initials[row * tiles_per_row + col];
|
||||
/* Link adjacent ones. */
|
||||
if (row) {
|
||||
lineart_list_append_pointer_pool(
|
||||
&ba->up,
|
||||
&rb->render_data_pool,
|
||||
&rb->initial_bounding_areas[(row - 1) * tiles_per_row + col]);
|
||||
&ba->up, &ld->render_data_pool, &ld->qtree.initials[(row - 1) * tiles_per_row + col]);
|
||||
}
|
||||
if (col) {
|
||||
lineart_list_append_pointer_pool(
|
||||
&ba->lp,
|
||||
&rb->render_data_pool,
|
||||
&rb->initial_bounding_areas[row * tiles_per_row + col - 1]);
|
||||
&ba->lp, &ld->render_data_pool, &ld->qtree.initials[row * tiles_per_row + col - 1]);
|
||||
}
|
||||
if (row != rb->tile_count_y - 1) {
|
||||
if (row != ld->qtree.count_y - 1) {
|
||||
lineart_list_append_pointer_pool(
|
||||
&ba->bp,
|
||||
&rb->render_data_pool,
|
||||
&rb->initial_bounding_areas[(row + 1) * tiles_per_row + col]);
|
||||
&ba->bp, &ld->render_data_pool, &ld->qtree.initials[(row + 1) * tiles_per_row + col]);
|
||||
}
|
||||
if (col != rb->tile_count_x - 1) {
|
||||
if (col != ld->qtree.count_x - 1) {
|
||||
lineart_list_append_pointer_pool(
|
||||
&ba->rp,
|
||||
&rb->render_data_pool,
|
||||
&rb->initial_bounding_areas[row * tiles_per_row + col + 1]);
|
||||
&ba->rp, &ld->render_data_pool, &ld->qtree.initials[row * tiles_per_row + col + 1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < total_tile_initial; i++) {
|
||||
lineart_bounding_areas_connect_recursive(rb, &rb->initial_bounding_areas[i]);
|
||||
lineart_bounding_areas_connect_recursive(ld, &ld->qtree.initials[i]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3737,12 +3730,12 @@ static void lineart_main_bounding_areas_connect_post(LineartRenderBuffer *rb)
|
||||
* Subdivide a tile after one tile contains too many triangles, then re-link triangles into all the
|
||||
* child tiles.
|
||||
*/
|
||||
static void lineart_bounding_area_split(LineartRenderBuffer *rb,
|
||||
static void lineart_bounding_area_split(LineartData *ld,
|
||||
LineartBoundingArea *root,
|
||||
int recursive_level)
|
||||
{
|
||||
|
||||
LineartBoundingArea *ba = lineart_mem_acquire_thread(&rb->render_data_pool,
|
||||
LineartBoundingArea *ba = lineart_mem_acquire_thread(&ld->render_data_pool,
|
||||
sizeof(LineartBoundingArea) * 4);
|
||||
ba[0].l = root->cx;
|
||||
ba[0].r = root->r;
|
||||
@@ -3795,16 +3788,16 @@ static void lineart_bounding_area_split(LineartRenderBuffer *rb,
|
||||
/* Re-link triangles into child tiles, not doing intersection lines during this because this
|
||||
* batch of triangles are all tested with each other for intersections. */
|
||||
if (LRT_BOUND_AREA_CROSSES(b, &ba[0].l)) {
|
||||
lineart_bounding_area_link_triangle(rb, &ba[0], tri, b, 0, recursive_level + 1, false, NULL);
|
||||
lineart_bounding_area_link_triangle(ld, &ba[0], tri, b, 0, recursive_level + 1, false, NULL);
|
||||
}
|
||||
if (LRT_BOUND_AREA_CROSSES(b, &ba[1].l)) {
|
||||
lineart_bounding_area_link_triangle(rb, &ba[1], tri, b, 0, recursive_level + 1, false, NULL);
|
||||
lineart_bounding_area_link_triangle(ld, &ba[1], tri, b, 0, recursive_level + 1, false, NULL);
|
||||
}
|
||||
if (LRT_BOUND_AREA_CROSSES(b, &ba[2].l)) {
|
||||
lineart_bounding_area_link_triangle(rb, &ba[2], tri, b, 0, recursive_level + 1, false, NULL);
|
||||
lineart_bounding_area_link_triangle(ld, &ba[2], tri, b, 0, recursive_level + 1, false, NULL);
|
||||
}
|
||||
if (LRT_BOUND_AREA_CROSSES(b, &ba[3].l)) {
|
||||
lineart_bounding_area_link_triangle(rb, &ba[3], tri, b, 0, recursive_level + 1, false, NULL);
|
||||
lineart_bounding_area_link_triangle(ld, &ba[3], tri, b, 0, recursive_level + 1, false, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3812,10 +3805,10 @@ static void lineart_bounding_area_split(LineartRenderBuffer *rb,
|
||||
* inserted, so assign root->child for #lineart_bounding_area_link_triangle to use. */
|
||||
root->child = ba;
|
||||
|
||||
rb->bounding_area_count += 3;
|
||||
ld->qtree.tile_count += 3;
|
||||
}
|
||||
|
||||
static bool lineart_bounding_area_edge_intersect(LineartRenderBuffer *UNUSED(fb),
|
||||
static bool lineart_bounding_area_edge_intersect(LineartData *UNUSED(fb),
|
||||
const double l[2],
|
||||
const double r[2],
|
||||
LineartBoundingArea *ba)
|
||||
@@ -3858,7 +3851,7 @@ static bool lineart_bounding_area_edge_intersect(LineartRenderBuffer *UNUSED(fb)
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool lineart_bounding_area_triangle_intersect(LineartRenderBuffer *fb,
|
||||
static bool lineart_bounding_area_triangle_intersect(LineartData *fb,
|
||||
LineartTriangle *tri,
|
||||
LineartBoundingArea *ba)
|
||||
{
|
||||
@@ -3895,7 +3888,7 @@ static bool lineart_bounding_area_triangle_intersect(LineartRenderBuffer *fb,
|
||||
/**
|
||||
* This function does two things:
|
||||
*
|
||||
* 1) Builds a quad-tree under rb->InitialBoundingAreas to achieve good geometry separation for
|
||||
* 1) Builds a quad-tree under ld->InitialBoundingAreas to achieve good geometry separation for
|
||||
* fast overlapping test between triangles and lines. This acceleration structure makes the
|
||||
* occlusion stage much faster.
|
||||
*
|
||||
@@ -3905,7 +3898,7 @@ static bool lineart_bounding_area_triangle_intersect(LineartRenderBuffer *fb,
|
||||
* duplicated intersection lines.
|
||||
*
|
||||
*/
|
||||
static void lineart_bounding_area_link_triangle(LineartRenderBuffer *rb,
|
||||
static void lineart_bounding_area_link_triangle(LineartData *ld,
|
||||
LineartBoundingArea *root_ba,
|
||||
LineartTriangle *tri,
|
||||
double *LRUB,
|
||||
@@ -3914,7 +3907,7 @@ static void lineart_bounding_area_link_triangle(LineartRenderBuffer *rb,
|
||||
bool do_intersection,
|
||||
struct LineartIsecThread *th)
|
||||
{
|
||||
if (!lineart_bounding_area_triangle_intersect(rb, tri, root_ba)) {
|
||||
if (!lineart_bounding_area_triangle_intersect(ld, tri, root_ba)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -3935,7 +3928,7 @@ static void lineart_bounding_area_link_triangle(LineartRenderBuffer *rb,
|
||||
for (int iba = 0; iba < 4; iba++) {
|
||||
if (LRT_BOUND_AREA_CROSSES(B1, &old_ba->child[iba].l)) {
|
||||
lineart_bounding_area_link_triangle(
|
||||
rb, &old_ba->child[iba], tri, B1, recursive, recursive_level + 1, do_intersection, th);
|
||||
ld, &old_ba->child[iba], tri, B1, recursive, recursive_level + 1, do_intersection, th);
|
||||
}
|
||||
}
|
||||
return;
|
||||
@@ -3954,7 +3947,7 @@ static void lineart_bounding_area_link_triangle(LineartRenderBuffer *rb,
|
||||
old_ba->linked_triangles[old_ba->triangle_count++] = tri;
|
||||
|
||||
/* Do intersections in place. */
|
||||
if (do_intersection && rb->use_intersections) {
|
||||
if (do_intersection && ld->conf.use_intersections) {
|
||||
lineart_triangle_intersect_in_bounding_area(tri, old_ba, th, old_tri_count);
|
||||
}
|
||||
|
||||
@@ -3964,10 +3957,10 @@ static void lineart_bounding_area_link_triangle(LineartRenderBuffer *rb,
|
||||
}
|
||||
else { /* We need to wait for either splitting or array extension to be done. */
|
||||
|
||||
if (recursive_level < rb->tile_recursive_level) {
|
||||
if (recursive_level < ld->qtree.recursive_level) {
|
||||
if (!old_ba->child) {
|
||||
/* old_ba->child==NULL, means we are the thread that's doing the splitting. */
|
||||
lineart_bounding_area_split(rb, old_ba, recursive_level);
|
||||
lineart_bounding_area_split(ld, old_ba, recursive_level);
|
||||
} /* Otherwise other thread has completed the splitting process. */
|
||||
}
|
||||
else {
|
||||
@@ -3984,7 +3977,7 @@ static void lineart_bounding_area_link_triangle(LineartRenderBuffer *rb,
|
||||
|
||||
/* Of course we still have our own triangle needs to be added. */
|
||||
lineart_bounding_area_link_triangle(
|
||||
rb, root_ba, tri, LRUB, recursive, recursive_level, do_intersection, th);
|
||||
ld, root_ba, tri, LRUB, recursive, recursive_level, do_intersection, th);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4003,17 +3996,16 @@ static void lineart_free_bounding_area_memory(LineartBoundingArea *ba, bool recu
|
||||
}
|
||||
}
|
||||
}
|
||||
static void lineart_free_bounding_area_memories(LineartRenderBuffer *rb)
|
||||
static void lineart_free_bounding_area_memories(LineartData *ld)
|
||||
{
|
||||
for (int i = 0; i < rb->tile_count_y; i++) {
|
||||
for (int j = 0; j < rb->tile_count_x; j++) {
|
||||
lineart_free_bounding_area_memory(&rb->initial_bounding_areas[i * rb->tile_count_x + j],
|
||||
true);
|
||||
for (int i = 0; i < ld->qtree.count_y; i++) {
|
||||
for (int j = 0; j < ld->qtree.count_x; j++) {
|
||||
lineart_free_bounding_area_memory(&ld->qtree.initials[i * ld->qtree.count_x + j], true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void lineart_bounding_area_link_edge(LineartRenderBuffer *rb,
|
||||
static void lineart_bounding_area_link_edge(LineartData *ld,
|
||||
LineartBoundingArea *root_ba,
|
||||
LineartEdge *e)
|
||||
{
|
||||
@@ -4022,20 +4014,20 @@ static void lineart_bounding_area_link_edge(LineartRenderBuffer *rb,
|
||||
}
|
||||
else {
|
||||
if (lineart_bounding_area_edge_intersect(
|
||||
rb, e->v1->fbcoord, e->v2->fbcoord, &root_ba->child[0])) {
|
||||
lineart_bounding_area_link_edge(rb, &root_ba->child[0], e);
|
||||
ld, e->v1->fbcoord, e->v2->fbcoord, &root_ba->child[0])) {
|
||||
lineart_bounding_area_link_edge(ld, &root_ba->child[0], e);
|
||||
}
|
||||
if (lineart_bounding_area_edge_intersect(
|
||||
rb, e->v1->fbcoord, e->v2->fbcoord, &root_ba->child[1])) {
|
||||
lineart_bounding_area_link_edge(rb, &root_ba->child[1], e);
|
||||
ld, e->v1->fbcoord, e->v2->fbcoord, &root_ba->child[1])) {
|
||||
lineart_bounding_area_link_edge(ld, &root_ba->child[1], e);
|
||||
}
|
||||
if (lineart_bounding_area_edge_intersect(
|
||||
rb, e->v1->fbcoord, e->v2->fbcoord, &root_ba->child[2])) {
|
||||
lineart_bounding_area_link_edge(rb, &root_ba->child[2], e);
|
||||
ld, e->v1->fbcoord, e->v2->fbcoord, &root_ba->child[2])) {
|
||||
lineart_bounding_area_link_edge(ld, &root_ba->child[2], e);
|
||||
}
|
||||
if (lineart_bounding_area_edge_intersect(
|
||||
rb, e->v1->fbcoord, e->v2->fbcoord, &root_ba->child[3])) {
|
||||
lineart_bounding_area_link_edge(rb, &root_ba->child[3], e);
|
||||
ld, e->v1->fbcoord, e->v2->fbcoord, &root_ba->child[3])) {
|
||||
lineart_bounding_area_link_edge(ld, &root_ba->child[3], e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4043,16 +4035,16 @@ static void lineart_bounding_area_link_edge(LineartRenderBuffer *rb,
|
||||
/**
|
||||
* Link lines to their respective bounding areas.
|
||||
*/
|
||||
static void lineart_main_link_lines(LineartRenderBuffer *rb)
|
||||
static void lineart_main_link_lines(LineartData *ld)
|
||||
{
|
||||
LRT_ITER_ALL_LINES_BEGIN
|
||||
{
|
||||
int r1, r2, c1, c2, row, col;
|
||||
if (lineart_get_edge_bounding_areas(rb, e, &r1, &r2, &c1, &c2)) {
|
||||
if (lineart_get_edge_bounding_areas(ld, e, &r1, &r2, &c1, &c2)) {
|
||||
for (row = r1; row != r2 + 1; row++) {
|
||||
for (col = c1; col != c2 + 1; col++) {
|
||||
lineart_bounding_area_link_edge(
|
||||
rb, &rb->initial_bounding_areas[row * rb->tile_count_x + col], e);
|
||||
ld, &ld->qtree.initials[row * ld->qtree.count_x + col], e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4060,14 +4052,10 @@ static void lineart_main_link_lines(LineartRenderBuffer *rb)
|
||||
LRT_ITER_ALL_LINES_END
|
||||
}
|
||||
|
||||
static bool lineart_get_triangle_bounding_areas(LineartRenderBuffer *rb,
|
||||
LineartTriangle *tri,
|
||||
int *rowbegin,
|
||||
int *rowend,
|
||||
int *colbegin,
|
||||
int *colend)
|
||||
static bool lineart_get_triangle_bounding_areas(
|
||||
LineartData *ld, LineartTriangle *tri, int *rowbegin, int *rowend, int *colbegin, int *colend)
|
||||
{
|
||||
double sp_w = rb->width_per_tile, sp_h = rb->height_per_tile;
|
||||
double sp_w = ld->qtree.tile_width, sp_h = ld->qtree.tile_height;
|
||||
double b[4];
|
||||
|
||||
if (!tri->v[0] || !tri->v[1] || !tri->v[2]) {
|
||||
@@ -4085,14 +4073,14 @@ static bool lineart_get_triangle_bounding_areas(LineartRenderBuffer *rb,
|
||||
|
||||
(*colbegin) = (int)((b[0] + 1.0) / sp_w);
|
||||
(*colend) = (int)((b[1] + 1.0) / sp_w);
|
||||
(*rowend) = rb->tile_count_y - (int)((b[2] + 1.0) / sp_h) - 1;
|
||||
(*rowbegin) = rb->tile_count_y - (int)((b[3] + 1.0) / sp_h) - 1;
|
||||
(*rowend) = ld->qtree.count_y - (int)((b[2] + 1.0) / sp_h) - 1;
|
||||
(*rowbegin) = ld->qtree.count_y - (int)((b[3] + 1.0) / sp_h) - 1;
|
||||
|
||||
if ((*colend) >= rb->tile_count_x) {
|
||||
(*colend) = rb->tile_count_x - 1;
|
||||
if ((*colend) >= ld->qtree.count_x) {
|
||||
(*colend) = ld->qtree.count_x - 1;
|
||||
}
|
||||
if ((*rowend) >= rb->tile_count_y) {
|
||||
(*rowend) = rb->tile_count_y - 1;
|
||||
if ((*rowend) >= ld->qtree.count_y) {
|
||||
(*rowend) = ld->qtree.count_y - 1;
|
||||
}
|
||||
if ((*colbegin) < 0) {
|
||||
(*colbegin) = 0;
|
||||
@@ -4104,14 +4092,10 @@ static bool lineart_get_triangle_bounding_areas(LineartRenderBuffer *rb,
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool lineart_get_edge_bounding_areas(LineartRenderBuffer *rb,
|
||||
LineartEdge *e,
|
||||
int *rowbegin,
|
||||
int *rowend,
|
||||
int *colbegin,
|
||||
int *colend)
|
||||
static bool lineart_get_edge_bounding_areas(
|
||||
LineartData *ld, LineartEdge *e, int *rowbegin, int *rowend, int *colbegin, int *colend)
|
||||
{
|
||||
double sp_w = rb->width_per_tile, sp_h = rb->height_per_tile;
|
||||
double sp_w = ld->qtree.tile_width, sp_h = ld->qtree.tile_height;
|
||||
double b[4];
|
||||
|
||||
if (!e->v1 || !e->v2) {
|
||||
@@ -4133,31 +4117,29 @@ static bool lineart_get_edge_bounding_areas(LineartRenderBuffer *rb,
|
||||
|
||||
(*colbegin) = (int)((b[0] + 1.0) / sp_w);
|
||||
(*colend) = (int)((b[1] + 1.0) / sp_w);
|
||||
(*rowend) = rb->tile_count_y - (int)((b[2] + 1.0) / sp_h) - 1;
|
||||
(*rowbegin) = rb->tile_count_y - (int)((b[3] + 1.0) / sp_h) - 1;
|
||||
(*rowend) = ld->qtree.count_y - (int)((b[2] + 1.0) / sp_h) - 1;
|
||||
(*rowbegin) = ld->qtree.count_y - (int)((b[3] + 1.0) / sp_h) - 1;
|
||||
|
||||
/* It's possible that the line stretches too much out to the side, resulting negative value. */
|
||||
if ((*rowend) < (*rowbegin)) {
|
||||
(*rowend) = rb->tile_count_y - 1;
|
||||
(*rowend) = ld->qtree.count_y - 1;
|
||||
}
|
||||
|
||||
if ((*colend) < (*colbegin)) {
|
||||
(*colend) = rb->tile_count_x - 1;
|
||||
(*colend) = ld->qtree.count_x - 1;
|
||||
}
|
||||
|
||||
CLAMP((*colbegin), 0, rb->tile_count_x - 1);
|
||||
CLAMP((*rowbegin), 0, rb->tile_count_y - 1);
|
||||
CLAMP((*colend), 0, rb->tile_count_x - 1);
|
||||
CLAMP((*rowend), 0, rb->tile_count_y - 1);
|
||||
CLAMP((*colbegin), 0, ld->qtree.count_x - 1);
|
||||
CLAMP((*rowbegin), 0, ld->qtree.count_y - 1);
|
||||
CLAMP((*colend), 0, ld->qtree.count_x - 1);
|
||||
CLAMP((*rowend), 0, ld->qtree.count_y - 1);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
LineartBoundingArea *MOD_lineart_get_parent_bounding_area(LineartRenderBuffer *rb,
|
||||
double x,
|
||||
double y)
|
||||
LineartBoundingArea *MOD_lineart_get_parent_bounding_area(LineartData *ld, double x, double y)
|
||||
{
|
||||
double sp_w = rb->width_per_tile, sp_h = rb->height_per_tile;
|
||||
double sp_w = ld->qtree.tile_width, sp_h = ld->qtree.tile_height;
|
||||
int col, row;
|
||||
|
||||
if (x > 1 || x < -1 || y > 1 || y < -1) {
|
||||
@@ -4165,13 +4147,13 @@ LineartBoundingArea *MOD_lineart_get_parent_bounding_area(LineartRenderBuffer *r
|
||||
}
|
||||
|
||||
col = (int)((x + 1.0) / sp_w);
|
||||
row = rb->tile_count_y - (int)((y + 1.0) / sp_h) - 1;
|
||||
row = ld->qtree.count_y - (int)((y + 1.0) / sp_h) - 1;
|
||||
|
||||
if (col >= rb->tile_count_x) {
|
||||
col = rb->tile_count_x - 1;
|
||||
if (col >= ld->qtree.count_x) {
|
||||
col = ld->qtree.count_x - 1;
|
||||
}
|
||||
if (row >= rb->tile_count_y) {
|
||||
row = rb->tile_count_y - 1;
|
||||
if (row >= ld->qtree.count_y) {
|
||||
row = ld->qtree.count_y - 1;
|
||||
}
|
||||
if (col < 0) {
|
||||
col = 0;
|
||||
@@ -4180,29 +4162,29 @@ LineartBoundingArea *MOD_lineart_get_parent_bounding_area(LineartRenderBuffer *r
|
||||
row = 0;
|
||||
}
|
||||
|
||||
return &rb->initial_bounding_areas[row * rb->tile_count_x + col];
|
||||
return &ld->qtree.initials[row * ld->qtree.count_x + col];
|
||||
}
|
||||
|
||||
static LineartBoundingArea *lineart_get_bounding_area(LineartRenderBuffer *rb, double x, double y)
|
||||
static LineartBoundingArea *lineart_get_bounding_area(LineartData *ld, double x, double y)
|
||||
{
|
||||
LineartBoundingArea *iba;
|
||||
double sp_w = rb->width_per_tile, sp_h = rb->height_per_tile;
|
||||
double sp_w = ld->qtree.tile_width, sp_h = ld->qtree.tile_height;
|
||||
int c = (int)((x + 1.0) / sp_w);
|
||||
int r = rb->tile_count_y - (int)((y + 1.0) / sp_h) - 1;
|
||||
int r = ld->qtree.count_y - (int)((y + 1.0) / sp_h) - 1;
|
||||
if (r < 0) {
|
||||
r = 0;
|
||||
}
|
||||
if (c < 0) {
|
||||
c = 0;
|
||||
}
|
||||
if (r >= rb->tile_count_y) {
|
||||
r = rb->tile_count_y - 1;
|
||||
if (r >= ld->qtree.count_y) {
|
||||
r = ld->qtree.count_y - 1;
|
||||
}
|
||||
if (c >= rb->tile_count_x) {
|
||||
c = rb->tile_count_x - 1;
|
||||
if (c >= ld->qtree.count_x) {
|
||||
c = ld->qtree.count_x - 1;
|
||||
}
|
||||
|
||||
iba = &rb->initial_bounding_areas[r * rb->tile_count_x + c];
|
||||
iba = &ld->qtree.initials[r * ld->qtree.count_x + c];
|
||||
while (iba->child) {
|
||||
if (x > iba->cx) {
|
||||
if (y > iba->cy) {
|
||||
@@ -4224,49 +4206,48 @@ static LineartBoundingArea *lineart_get_bounding_area(LineartRenderBuffer *rb, d
|
||||
return iba;
|
||||
}
|
||||
|
||||
LineartBoundingArea *MOD_lineart_get_bounding_area(LineartRenderBuffer *rb, double x, double y)
|
||||
LineartBoundingArea *MOD_lineart_get_bounding_area(LineartData *ld, double x, double y)
|
||||
{
|
||||
LineartBoundingArea *ba;
|
||||
if ((ba = MOD_lineart_get_parent_bounding_area(rb, x, y)) != NULL) {
|
||||
return lineart_get_bounding_area(rb, x, y);
|
||||
if ((ba = MOD_lineart_get_parent_bounding_area(ld, x, y)) != NULL) {
|
||||
return lineart_get_bounding_area(ld, x, y);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void lineart_add_triangles_worker(TaskPool *__restrict UNUSED(pool), LineartIsecThread *th)
|
||||
{
|
||||
LineartRenderBuffer *rb = th->rb;
|
||||
LineartData *ld = th->ld;
|
||||
int _dir_control = 0;
|
||||
while (lineart_schedule_new_triangle_task(th)) {
|
||||
for (LineartElementLinkNode *eln = th->pending_from; eln != th->pending_to->next;
|
||||
eln = eln->next) {
|
||||
int index_start = eln == th->pending_from ? th->index_from : 0;
|
||||
int index_end = eln == th->pending_to ? th->index_to : eln->element_count;
|
||||
LineartTriangle *tri = (void *)(((uchar *)eln->pointer) + rb->triangle_size * index_start);
|
||||
LineartTriangle *tri = (void *)(((uchar *)eln->pointer) + ld->sizeof_triangle * index_start);
|
||||
for (int ei = index_start; ei < index_end; ei++) {
|
||||
int x1, x2, y1, y2;
|
||||
int r, co;
|
||||
if ((tri->flags & LRT_CULL_USED) || (tri->flags & LRT_CULL_DISCARD)) {
|
||||
tri = (void *)(((uchar *)tri) + rb->triangle_size);
|
||||
tri = (void *)(((uchar *)tri) + ld->sizeof_triangle);
|
||||
continue;
|
||||
}
|
||||
if (lineart_get_triangle_bounding_areas(rb, tri, &y1, &y2, &x1, &x2)) {
|
||||
if (lineart_get_triangle_bounding_areas(ld, tri, &y1, &y2, &x1, &x2)) {
|
||||
_dir_control++;
|
||||
for (co = x1; co <= x2; co++) {
|
||||
for (r = y1; r <= y2; r++) {
|
||||
lineart_bounding_area_link_triangle(
|
||||
rb,
|
||||
&rb->initial_bounding_areas[r * rb->tile_count_x + co],
|
||||
tri,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
(!(tri->flags & LRT_TRIANGLE_NO_INTERSECTION)),
|
||||
th);
|
||||
lineart_bounding_area_link_triangle(ld,
|
||||
&ld->qtree.initials[r * ld->qtree.count_x + co],
|
||||
tri,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
(!(tri->flags & LRT_TRIANGLE_NO_INTERSECTION)),
|
||||
th);
|
||||
}
|
||||
}
|
||||
} /* Else throw away. */
|
||||
tri = (void *)(((uchar *)tri) + rb->triangle_size);
|
||||
tri = (void *)(((uchar *)tri) + ld->sizeof_triangle);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4274,9 +4255,9 @@ static void lineart_add_triangles_worker(TaskPool *__restrict UNUSED(pool), Line
|
||||
|
||||
static void lineart_create_edges_from_isec_data(LineartIsecData *d)
|
||||
{
|
||||
LineartRenderBuffer *rb = d->rb;
|
||||
double ZMax = rb->far_clip;
|
||||
double ZMin = rb->near_clip;
|
||||
LineartData *ld = d->ld;
|
||||
double ZMax = ld->conf.far_clip;
|
||||
double ZMin = ld->conf.near_clip;
|
||||
|
||||
for (int i = 0; i < d->thread_count; i++) {
|
||||
LineartIsecThread *th = &d->threads[i];
|
||||
@@ -4289,9 +4270,9 @@ static void lineart_create_edges_from_isec_data(LineartIsecData *d)
|
||||
/* We don't care about removing duplicated vert in this method, chaining can handle that,
|
||||
* and it saves us from using locks and look up tables. */
|
||||
LineartVertIntersection *v = lineart_mem_acquire(
|
||||
&rb->render_data_pool, sizeof(LineartVertIntersection) * th->current * 2);
|
||||
LineartEdge *e = lineart_mem_acquire(&rb->render_data_pool, sizeof(LineartEdge) * th->current);
|
||||
LineartEdgeSegment *es = lineart_mem_acquire(&rb->render_data_pool,
|
||||
&ld->render_data_pool, sizeof(LineartVertIntersection) * th->current * 2);
|
||||
LineartEdge *e = lineart_mem_acquire(&ld->render_data_pool, sizeof(LineartEdge) * th->current);
|
||||
LineartEdgeSegment *es = lineart_mem_acquire(&ld->render_data_pool,
|
||||
sizeof(LineartEdgeSegment) * th->current);
|
||||
for (int j = 0; j < th->current; j++) {
|
||||
LineartVertIntersection *v1i = v;
|
||||
@@ -4307,15 +4288,15 @@ static void lineart_create_edges_from_isec_data(LineartIsecData *d)
|
||||
copy_v3db_v3fl(v2->gloc, is->v2);
|
||||
/* The intersection line has been generated only in geometry space, so we need to transform
|
||||
* them as well. */
|
||||
mul_v4_m4v3_db(v1->fbcoord, rb->view_projection, v1->gloc);
|
||||
mul_v4_m4v3_db(v2->fbcoord, rb->view_projection, v2->gloc);
|
||||
mul_v4_m4v3_db(v1->fbcoord, ld->conf.view_projection, v1->gloc);
|
||||
mul_v4_m4v3_db(v2->fbcoord, ld->conf.view_projection, v2->gloc);
|
||||
mul_v3db_db(v1->fbcoord, (1 / v1->fbcoord[3]));
|
||||
mul_v3db_db(v2->fbcoord, (1 / v2->fbcoord[3]));
|
||||
|
||||
v1->fbcoord[0] -= rb->shift_x * 2;
|
||||
v1->fbcoord[1] -= rb->shift_y * 2;
|
||||
v2->fbcoord[0] -= rb->shift_x * 2;
|
||||
v2->fbcoord[1] -= rb->shift_y * 2;
|
||||
v1->fbcoord[0] -= ld->conf.shift_x * 2;
|
||||
v1->fbcoord[1] -= ld->conf.shift_y * 2;
|
||||
v2->fbcoord[0] -= ld->conf.shift_x * 2;
|
||||
v2->fbcoord[1] -= ld->conf.shift_y * 2;
|
||||
|
||||
/* This z transformation is not the same as the rest of the part, because the data don't go
|
||||
* through normal perspective division calls in the pipeline, but this way the 3D result and
|
||||
@@ -4331,7 +4312,7 @@ static void lineart_create_edges_from_isec_data(LineartIsecData *d)
|
||||
e->intersection_mask = (is->tri1->intersection_mask | is->tri2->intersection_mask);
|
||||
BLI_addtail(&e->segments, es);
|
||||
|
||||
lineart_add_edge_to_array(&rb->pending_edges, e);
|
||||
lineart_add_edge_to_array(&ld->pending_edges, e);
|
||||
|
||||
v += 2;
|
||||
e++;
|
||||
@@ -4344,7 +4325,7 @@ static void lineart_create_edges_from_isec_data(LineartIsecData *d)
|
||||
* Sequentially add triangles into render buffer, intersection lines between those triangles will
|
||||
* also be computed at the same time.
|
||||
*/
|
||||
static void lineart_main_add_triangles(LineartRenderBuffer *rb)
|
||||
static void lineart_main_add_triangles(LineartData *ld)
|
||||
{
|
||||
double t_start;
|
||||
if (G.debug_value == 4000) {
|
||||
@@ -4354,10 +4335,10 @@ static void lineart_main_add_triangles(LineartRenderBuffer *rb)
|
||||
/* Initialize per-thread data for thread task scheduling information and storing intersection
|
||||
* results. */
|
||||
LineartIsecData d = {0};
|
||||
lineart_init_isec_thread(&d, rb, rb->thread_count);
|
||||
lineart_init_isec_thread(&d, ld, ld->thread_count);
|
||||
|
||||
TaskPool *tp = BLI_task_pool_create(NULL, TASK_PRIORITY_HIGH);
|
||||
for (int i = 0; i < rb->thread_count; i++) {
|
||||
for (int i = 0; i < ld->thread_count; i++) {
|
||||
BLI_task_pool_push(tp, (TaskRunFunction)lineart_add_triangles_worker, &d.threads[i], 0, NULL);
|
||||
}
|
||||
BLI_task_pool_work_and_wait(tp);
|
||||
@@ -4378,8 +4359,7 @@ static void lineart_main_add_triangles(LineartRenderBuffer *rb)
|
||||
* This function gets the tile for the point `e->v1`, and later use #lineart_bounding_area_next()
|
||||
* to get next along the way.
|
||||
*/
|
||||
static LineartBoundingArea *lineart_edge_first_bounding_area(LineartRenderBuffer *rb,
|
||||
LineartEdge *e)
|
||||
static LineartBoundingArea *lineart_edge_first_bounding_area(LineartData *ld, LineartEdge *e)
|
||||
{
|
||||
double data[2] = {e->v1->fbcoord[0], e->v1->fbcoord[1]};
|
||||
double LU[2] = {-1, 1}, RU[2] = {1, 1}, LB[2] = {-1, -1}, RB[2] = {1, -1};
|
||||
@@ -4387,7 +4367,7 @@ static LineartBoundingArea *lineart_edge_first_bounding_area(LineartRenderBuffer
|
||||
bool p_unused;
|
||||
|
||||
if (data[0] > -1 && data[0] < 1 && data[1] > -1 && data[1] < 1) {
|
||||
return lineart_get_bounding_area(rb, data[0], data[1]);
|
||||
return lineart_get_bounding_area(ld, data[0], data[1]);
|
||||
}
|
||||
|
||||
if (lineart_intersect_seg_seg(e->v1->fbcoord, e->v2->fbcoord, LU, RU, &sr, &p_unused) &&
|
||||
@@ -4408,7 +4388,7 @@ static LineartBoundingArea *lineart_edge_first_bounding_area(LineartRenderBuffer
|
||||
}
|
||||
interp_v2_v2v2_db(data, e->v1->fbcoord, e->v2->fbcoord, r);
|
||||
|
||||
return lineart_get_bounding_area(rb, data[0], data[1]);
|
||||
return lineart_get_bounding_area(ld, data[0], data[1]);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -4639,7 +4619,7 @@ bool MOD_lineart_compute_feature_lines(Depsgraph *depsgraph,
|
||||
LineartCache **cached_result,
|
||||
bool enable_stroke_depth_offset)
|
||||
{
|
||||
LineartRenderBuffer *rb;
|
||||
LineartData *ld;
|
||||
Scene *scene = DEG_get_evaluated_scene(depsgraph);
|
||||
int intersections_only = 0; /* Not used right now, but preserve for future. */
|
||||
Object *use_camera;
|
||||
@@ -4669,58 +4649,53 @@ bool MOD_lineart_compute_feature_lines(Depsgraph *depsgraph,
|
||||
LineartCache *lc = lineart_init_cache();
|
||||
*cached_result = lc;
|
||||
|
||||
rb = lineart_create_render_buffer(scene, lmd, use_camera, scene->camera, lc);
|
||||
ld = lineart_create_render_buffer(scene, lmd, use_camera, scene->camera, lc);
|
||||
|
||||
/* Triangle thread testing data size varies depending on the thread count.
|
||||
* See definition of LineartTriangleThread for details. */
|
||||
rb->triangle_size = lineart_triangle_size_get(rb);
|
||||
|
||||
/* FIXME(Yiming): See definition of int #LineartRenderBuffer::_source_type for detailed. */
|
||||
rb->_source_type = lmd->source_type;
|
||||
rb->_source_collection = lmd->source_collection;
|
||||
rb->_source_object = lmd->source_object;
|
||||
ld->sizeof_triangle = lineart_triangle_size_get(ld);
|
||||
|
||||
/* Get view vector before loading geometries, because we detect feature lines there. */
|
||||
lineart_main_get_view_vector(rb);
|
||||
lineart_main_get_view_vector(ld);
|
||||
lineart_main_load_geometries(
|
||||
depsgraph, scene, use_camera, rb, lmd->calculation_flags & LRT_ALLOW_DUPLI_OBJECTS);
|
||||
depsgraph, scene, use_camera, ld, lmd->calculation_flags & LRT_ALLOW_DUPLI_OBJECTS);
|
||||
|
||||
if (!rb->vertex_buffer_pointers.first) {
|
||||
if (!ld->geom.vertex_buffer_pointers.first) {
|
||||
/* No geometry loaded, return early. */
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Initialize the bounding box acceleration structure, it's a lot like BVH in 3D. */
|
||||
lineart_main_bounding_area_make_initial(rb);
|
||||
lineart_main_bounding_area_make_initial(ld);
|
||||
|
||||
/* We need to get cut into triangles that are crossing near/far plans, only this way can we get
|
||||
* correct coordinates of those clipped lines. Done in two steps,
|
||||
* setting clip_far==false for near plane. */
|
||||
lineart_main_cull_triangles(rb, false);
|
||||
lineart_main_cull_triangles(ld, false);
|
||||
/* `clip_far == true` for far plane. */
|
||||
lineart_main_cull_triangles(rb, true);
|
||||
lineart_main_cull_triangles(ld, true);
|
||||
|
||||
/* At this point triangle adjacent info pointers is no longer needed, free them. */
|
||||
lineart_main_free_adjacent_data(rb);
|
||||
lineart_main_free_adjacent_data(ld);
|
||||
|
||||
/* Do the perspective division after clipping is done. */
|
||||
lineart_main_perspective_division(rb);
|
||||
lineart_main_perspective_division(ld);
|
||||
|
||||
lineart_main_discard_out_of_frame_edges(rb);
|
||||
lineart_main_discard_out_of_frame_edges(ld);
|
||||
|
||||
/* Triangle intersections are done here during sequential adding of them. Only after this,
|
||||
* triangles and lines are all linked with acceleration structure, and the 2D occlusion stage
|
||||
* can do its job. */
|
||||
lineart_main_add_triangles(rb);
|
||||
lineart_main_add_triangles(ld);
|
||||
|
||||
/* Re-link bounding areas because they have been subdivided by worker threads and we need
|
||||
* adjacent info. */
|
||||
lineart_main_bounding_areas_connect_post(rb);
|
||||
lineart_main_bounding_areas_connect_post(ld);
|
||||
|
||||
/* Link lines to acceleration structure, this can only be done after perspective division, if
|
||||
* we do it after triangles being added, the acceleration structure has already been
|
||||
* subdivided, this way we do less list manipulations. */
|
||||
lineart_main_link_lines(rb);
|
||||
lineart_main_link_lines(ld);
|
||||
|
||||
/* "intersection_only" is preserved for being called in a standalone fashion.
|
||||
* If so the data will already be available at the stage. Otherwise we do the occlusion and
|
||||
@@ -4729,54 +4704,54 @@ bool MOD_lineart_compute_feature_lines(Depsgraph *depsgraph,
|
||||
if (!intersections_only) {
|
||||
|
||||
/* Occlusion is work-and-wait. This call will not return before work is completed. */
|
||||
lineart_main_occlusion_begin(rb);
|
||||
lineart_main_occlusion_begin(ld);
|
||||
|
||||
/* Chaining is all single threaded. See lineart_chain.c
|
||||
* In this particular call, only lines that are geometrically connected (share the _exact_
|
||||
* same end point) will be chained together. */
|
||||
MOD_lineart_chain_feature_lines(rb);
|
||||
MOD_lineart_chain_feature_lines(ld);
|
||||
|
||||
/* We are unable to take care of occlusion if we only connect end points, so here we do a
|
||||
* spit, where the splitting point could be any cut in e->segments. */
|
||||
MOD_lineart_chain_split_for_fixed_occlusion(rb);
|
||||
MOD_lineart_chain_split_for_fixed_occlusion(ld);
|
||||
|
||||
/* Then we connect chains based on the _proximity_ of their end points in image space, here's
|
||||
* the place threshold value gets involved. */
|
||||
MOD_lineart_chain_connect(rb);
|
||||
MOD_lineart_chain_connect(ld);
|
||||
|
||||
float *t_image = &lmd->chaining_image_threshold;
|
||||
/* This configuration ensures there won't be accidental lost of short unchained segments. */
|
||||
MOD_lineart_chain_discard_short(rb, MIN2(*t_image, 0.001f) - FLT_EPSILON);
|
||||
MOD_lineart_chain_discard_short(ld, MIN2(*t_image, 0.001f) - FLT_EPSILON);
|
||||
|
||||
if (rb->chain_smooth_tolerance > FLT_EPSILON) {
|
||||
if (ld->conf.chain_smooth_tolerance > FLT_EPSILON) {
|
||||
/* Keeping UI range of 0-1 for ease of read while scaling down the actual value for best
|
||||
* effective range in image-space (Coordinate only goes from -1 to 1). This value is
|
||||
* somewhat arbitrary, but works best for the moment. */
|
||||
MOD_lineart_smooth_chains(rb, rb->chain_smooth_tolerance / 50);
|
||||
MOD_lineart_smooth_chains(ld, ld->conf.chain_smooth_tolerance / 50);
|
||||
}
|
||||
|
||||
if (rb->use_image_boundary_trimming) {
|
||||
MOD_lineart_chain_clip_at_border(rb);
|
||||
if (ld->conf.use_image_boundary_trimming) {
|
||||
MOD_lineart_chain_clip_at_border(ld);
|
||||
}
|
||||
|
||||
if (rb->angle_splitting_threshold > FLT_EPSILON) {
|
||||
MOD_lineart_chain_split_angle(rb, rb->angle_splitting_threshold);
|
||||
if (ld->conf.angle_splitting_threshold > FLT_EPSILON) {
|
||||
MOD_lineart_chain_split_angle(ld, ld->conf.angle_splitting_threshold);
|
||||
}
|
||||
|
||||
if (enable_stroke_depth_offset && lmd->stroke_depth_offset > FLT_EPSILON) {
|
||||
MOD_lineart_chain_offset_towards_camera(
|
||||
rb, lmd->stroke_depth_offset, lmd->flags & LRT_GPENCIL_OFFSET_TOWARDS_CUSTOM_CAMERA);
|
||||
ld, lmd->stroke_depth_offset, lmd->flags & LRT_GPENCIL_OFFSET_TOWARDS_CUSTOM_CAMERA);
|
||||
}
|
||||
|
||||
/* Finally transfer the result list into cache. */
|
||||
memcpy(&lc->chains, &rb->chains, sizeof(ListBase));
|
||||
memcpy(&lc->chains, &ld->chains, sizeof(ListBase));
|
||||
|
||||
/* At last, we need to clear flags so we don't confuse GPencil generation calls. */
|
||||
MOD_lineart_chain_clear_picked_flag(lc);
|
||||
}
|
||||
|
||||
if (G.debug_value == 4000) {
|
||||
lineart_count_and_print_render_buffer_memory(rb);
|
||||
lineart_count_and_print_render_buffer_memory(ld);
|
||||
|
||||
double t_elapsed = PIL_check_seconds_timer() - t_start;
|
||||
printf("Line art total time: %lf\n", t_elapsed);
|
||||
@@ -4785,15 +4760,15 @@ bool MOD_lineart_compute_feature_lines(Depsgraph *depsgraph,
|
||||
return true;
|
||||
}
|
||||
|
||||
static int UNUSED_FUNCTION(lineart_rb_edge_types)(LineartRenderBuffer *rb)
|
||||
static int UNUSED_FUNCTION(lineart_rb_edge_types)(LineartData *ld)
|
||||
{
|
||||
int types = 0;
|
||||
types |= rb->use_contour ? LRT_EDGE_FLAG_CONTOUR : 0;
|
||||
types |= rb->use_crease ? LRT_EDGE_FLAG_CREASE : 0;
|
||||
types |= rb->use_material ? LRT_EDGE_FLAG_MATERIAL : 0;
|
||||
types |= rb->use_edge_marks ? LRT_EDGE_FLAG_EDGE_MARK : 0;
|
||||
types |= rb->use_intersections ? LRT_EDGE_FLAG_INTERSECTION : 0;
|
||||
types |= rb->use_loose ? LRT_EDGE_FLAG_LOOSE : 0;
|
||||
types |= ld->conf.use_contour ? LRT_EDGE_FLAG_CONTOUR : 0;
|
||||
types |= ld->conf.use_crease ? LRT_EDGE_FLAG_CREASE : 0;
|
||||
types |= ld->conf.use_material ? LRT_EDGE_FLAG_MATERIAL : 0;
|
||||
types |= ld->conf.use_edge_marks ? LRT_EDGE_FLAG_EDGE_MARK : 0;
|
||||
types |= ld->conf.use_intersections ? LRT_EDGE_FLAG_INTERSECTION : 0;
|
||||
types |= ld->conf.use_loose ? LRT_EDGE_FLAG_LOOSE : 0;
|
||||
return types;
|
||||
}
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
#include <string.h>
|
||||
|
||||
struct LineartEdge;
|
||||
struct LineartRenderBuffer;
|
||||
struct LineartData;
|
||||
struct LineartStaticMemPool;
|
||||
struct LineartStaticMemPoolNode;
|
||||
|
||||
@@ -62,14 +62,14 @@ void lineart_matrix_ortho_44d(double (*mProjection)[4],
|
||||
void lineart_matrix_perspective_44d(
|
||||
double (*mProjection)[4], double fFov_rad, double fAspect, double zMin, double zMax);
|
||||
|
||||
int lineart_count_intersection_segment_count(struct LineartRenderBuffer *rb);
|
||||
int lineart_count_intersection_segment_count(struct LineartData *ld);
|
||||
|
||||
void lineart_count_and_print_render_buffer_memory(struct LineartRenderBuffer *rb);
|
||||
void lineart_count_and_print_render_buffer_memory(struct LineartData *ld);
|
||||
|
||||
#define LRT_ITER_ALL_LINES_BEGIN \
|
||||
LineartEdge *e; \
|
||||
for (int i = 0; i < rb->pending_edges.next; i++) { \
|
||||
e = rb->pending_edges.array[i];
|
||||
for (int i = 0; i < ld->pending_edges.next; i++) { \
|
||||
e = ld->pending_edges.array[i];
|
||||
|
||||
#define LRT_ITER_ALL_LINES_NEXT ; /* Doesn't do anything now with new array setup. */
|
||||
|
||||
|
||||
@@ -212,13 +212,13 @@ void lineart_matrix_ortho_44d(double (*mProjection)[4],
|
||||
mProjection[3][3] = 1.0f;
|
||||
}
|
||||
|
||||
void lineart_count_and_print_render_buffer_memory(LineartRenderBuffer *rb)
|
||||
void lineart_count_and_print_render_buffer_memory(LineartData *ld)
|
||||
{
|
||||
size_t total = 0;
|
||||
size_t sum_this = 0;
|
||||
size_t count_this = 0;
|
||||
|
||||
LISTBASE_FOREACH (LineartStaticMemPoolNode *, smpn, &rb->render_data_pool.pools) {
|
||||
LISTBASE_FOREACH (LineartStaticMemPoolNode *, smpn, &ld->render_data_pool.pools) {
|
||||
count_this++;
|
||||
sum_this += LRT_MEMORY_POOL_1MB;
|
||||
}
|
||||
@@ -227,7 +227,7 @@ void lineart_count_and_print_render_buffer_memory(LineartRenderBuffer *rb)
|
||||
sum_this = 0;
|
||||
count_this = 0;
|
||||
|
||||
LISTBASE_FOREACH (LineartElementLinkNode *, reln, &rb->line_buffer_pointers) {
|
||||
LISTBASE_FOREACH (LineartElementLinkNode *, reln, &ld->geom.line_buffer_pointers) {
|
||||
count_this++;
|
||||
sum_this += reln->element_count * sizeof(LineartEdge);
|
||||
}
|
||||
@@ -236,9 +236,9 @@ void lineart_count_and_print_render_buffer_memory(LineartRenderBuffer *rb)
|
||||
sum_this = 0;
|
||||
count_this = 0;
|
||||
|
||||
LISTBASE_FOREACH (LineartElementLinkNode *, reln, &rb->triangle_buffer_pointers) {
|
||||
LISTBASE_FOREACH (LineartElementLinkNode *, reln, &ld->geom.triangle_buffer_pointers) {
|
||||
count_this++;
|
||||
sum_this += reln->element_count * rb->triangle_size;
|
||||
sum_this += reln->element_count * ld->sizeof_triangle;
|
||||
}
|
||||
printf(" allocated %zu triangle blocks, total %zu Bytes.\n", count_this, sum_this);
|
||||
total += sum_this;
|
||||
|
||||
@@ -1098,7 +1098,7 @@ typedef struct LineartGpencilModifierData {
|
||||
|
||||
struct LineartCache *cache;
|
||||
/* Keep a pointer to the render buffer so we can call destroy from ModifierData. */
|
||||
struct LineartRenderBuffer *render_buffer_ptr;
|
||||
struct LineartData *la_data_ptr;
|
||||
|
||||
} LineartGpencilModifierData;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user