diff options
author | YimingWu <xp8110@outlook.com> | 2019-07-31 11:23:32 +0300 |
---|---|---|
committer | YimingWu <xp8110@outlook.com> | 2019-07-31 11:23:32 +0300 |
commit | e5c1b74ec98294071aecd6136283191ccfee8250 (patch) | |
tree | d9dcfdaabafe7573411b19ca1cdb217005b26e4e | |
parent | 4fe067b8541505520363622b26d2dc400a280504 (diff) |
LANPR: use own operator registering function.
-rw-r--r-- | source/blender/editors/include/ED_lanpr.h | 2 | ||||
-rw-r--r-- | source/blender/editors/lanpr/CMakeLists.txt | 1 | ||||
-rw-r--r-- | source/blender/editors/lanpr/lanpr_cpu.c | 4497 | ||||
-rw-r--r-- | source/blender/editors/lanpr/lanpr_ops.c | 4520 | ||||
-rw-r--r-- | source/blender/editors/render/render_intern.h | 14 | ||||
-rw-r--r-- | source/blender/editors/render/render_ops.c | 14 | ||||
-rw-r--r-- | source/blender/editors/space_api/spacetypes.c | 4 |
7 files changed, 4535 insertions, 4517 deletions
diff --git a/source/blender/editors/include/ED_lanpr.h b/source/blender/editors/include/ED_lanpr.h index e583b4bdca5..ff36f24027d 100644 --- a/source/blender/editors/include/ED_lanpr.h +++ b/source/blender/editors/include/ED_lanpr.h @@ -832,4 +832,6 @@ LANPR_BoundingArea *ED_lanpr_get_point_bounding_area_deep(LANPR_RenderBuffer *rb void ED_lanpr_post_frame_update_external(struct Scene *s, struct Depsgraph *dg); +void ED_operatortypes_lanpr(void); + #endif /* __ED_LANPR_H__ */ diff --git a/source/blender/editors/lanpr/CMakeLists.txt b/source/blender/editors/lanpr/CMakeLists.txt index 44a8d294ff7..9319ed94ad0 100644 --- a/source/blender/editors/lanpr/CMakeLists.txt +++ b/source/blender/editors/lanpr/CMakeLists.txt @@ -33,6 +33,7 @@ set(INC_SYS set(SRC lanpr_ops.c + lanpr_cpu.c lanpr_chain.c lanpr_util.c ) diff --git a/source/blender/editors/lanpr/lanpr_cpu.c b/source/blender/editors/lanpr/lanpr_cpu.c new file mode 100644 index 00000000000..33c041144a5 --- /dev/null +++ b/source/blender/editors/lanpr/lanpr_cpu.c @@ -0,0 +1,4497 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** \file + * \ingroup editor/lanpr + */ + +/* Test commit for investigating git problems. */ + +#include "ED_lanpr.h" + +#include "BLI_listbase.h" +#include "BLI_linklist.h" +#include "BLI_math_matrix.h" +#include "BLI_task.h" +#include "BLI_utildefines.h" +#include "BLI_alloca.h" + +#include "BKE_object.h" +#include "DNA_mesh_types.h" +#include "DNA_camera_types.h" +#include "DNA_modifier_types.h" +#include "DNA_text_types.h" +#include "DNA_lanpr_types.h" +#include "DNA_scene_types.h" +#include "DNA_gpencil_types.h" +#include "DNA_meshdata_types.h" +#include "BKE_customdata.h" +#include "DEG_depsgraph_query.h" +#include "BKE_camera.h" +#include "BKE_gpencil.h" +#include "BKE_collection.h" +#include "BKE_report.h" +#include "BKE_screen.h" +#include "BKE_scene.h" +#include "BKE_text.h" +#include "BKE_context.h" +#include "MEM_guardedalloc.h" + +#include "RNA_access.h" +#include "RNA_define.h" + +#include "BLI_math.h" +#include "BLI_callbacks.h" +#include "BLI_string_utils.h" + +#include "bmesh.h" +#include "bmesh_class.h" +#include "bmesh_tools.h" + +#include "WM_types.h" +#include "WM_api.h" + +#include "ED_svg.h" +#include "BKE_text.h" + +extern LANPR_SharedResource lanpr_share; +extern const char *RE_engine_id_BLENDER_LANPR; +struct Object; + +/* External defines */ + +void lanpr_rebuild_all_command(SceneLANPR *lanpr); + +/* Own functions */ + +static LANPR_BoundingArea *lanpr_get_first_possible_bounding_area(LANPR_RenderBuffer *rb, + LANPR_RenderLine *rl); + +static void lanpr_link_line_with_bounding_area(LANPR_RenderBuffer *rb, + LANPR_BoundingArea *RootBoundingArea, + LANPR_RenderLine *rl); + +static LANPR_BoundingArea *lanpr_get_next_bounding_area(LANPR_BoundingArea *This, + LANPR_RenderLine *rl, + real x, + real y, + real k, + int PositiveX, + int PositiveY, + real *NextX, + real *NextY); +static int lanpr_triangle_line_imagespace_intersection_v2(SpinLock *spl, + LANPR_RenderTriangle *rt, + LANPR_RenderLine *rl, + Object *cam, + tnsMatrix44d vp, + real *CameraDir, + double *From, + double *To); +static int lanpr_get_line_bounding_areas(LANPR_RenderBuffer *rb, + LANPR_RenderLine *rl, + int *rowBegin, + int *rowEnd, + int *colBegin, + int *colEnd); + +/* Layer operations */ + +static void lanpr_line_layer_unique_name(ListBase* list, LANPR_LineLayer* ll, const char *defname) +{ + BLI_uniquename(list,ll,defname,'.',offsetof(LANPR_LineLayer, name),sizeof(ll->name)); +} + +int ED_lanpr_max_occlusion_in_line_layers(SceneLANPR *lanpr) +{ + LANPR_LineLayer *lli; + int max_occ = -1, max; + for (lli = lanpr->line_layers.first; lli; lli = lli->next) { + if (lli->use_multiple_levels) { + max = MAX2(lli->qi_begin, lli->qi_end); + } + else { + max = lli->qi_begin; + } + max_occ = MAX2(max, max_occ); + } + return max_occ; +} +LANPR_LineLayer *ED_lanpr_new_line_layer(SceneLANPR *lanpr) +{ + LANPR_LineLayer *ll = MEM_callocN(sizeof(LANPR_LineLayer), "Line Layer"); + + lanpr_line_layer_unique_name(&lanpr->line_layers,ll,"Layer"); + + int max_occ = ED_lanpr_max_occlusion_in_line_layers(lanpr); + + ll->qi_begin = ll->qi_end = max_occ + 1; + ll->use_same_style = 1; + ll->thickness = 1.0f; + copy_v3_fl(ll->color, 0.8); + ll->color[3] = 1.0f; + ll->contour.enabled = 1; + ll->crease.enabled = 1; + ll->material_separate.enabled = 1; + ll->edge_mark.enabled = 1; + ll->intersection.enabled = 1; + + lanpr->active_layer = ll; + BLI_addtail(&lanpr->line_layers, ll); + + return ll; +} +LANPR_LineLayerComponent *ED_lanpr_new_line_component(SceneLANPR *lanpr) +{ + if (!lanpr->active_layer) { + return 0; + } + LANPR_LineLayer *ll = lanpr->active_layer; + + LANPR_LineLayerComponent *llc = MEM_callocN(sizeof(LANPR_LineLayerComponent), "Line Component"); + BLI_addtail(&ll->components, llc); + + return llc; +} +static int lanpr_add_line_layer_exec(struct bContext *C, struct wmOperator *UNUSED(op)) +{ + Scene *scene = CTX_data_scene(C); + SceneLANPR *lanpr = &scene->lanpr; + + ED_lanpr_new_line_layer(lanpr); + + DEG_id_tag_update(&scene->id, ID_RECALC_COPY_ON_WRITE); + + WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, NULL); + + return OPERATOR_FINISHED; +} +static int lanpr_delete_line_layer_exec(struct bContext *C, struct wmOperator *UNUSED(op)) +{ + Scene *scene = CTX_data_scene(C); + SceneLANPR *lanpr = &scene->lanpr; + + LANPR_LineLayer *ll = lanpr->active_layer; + + if (!ll) { + return OPERATOR_FINISHED; + } + + if (ll->prev) { + lanpr->active_layer = ll->prev; + } + else if (ll->next) { + lanpr->active_layer = ll->next; + } + else { + lanpr->active_layer = 0; + } + + BLI_remlink(&scene->lanpr.line_layers, ll); + + /* if (ll->batch) GPU_batch_discard(ll->batch); */ + + MEM_freeN(ll); + + DEG_id_tag_update(&scene->id, ID_RECALC_COPY_ON_WRITE); + + WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, NULL); + + return OPERATOR_FINISHED; +} +static int lanpr_move_line_layer_exec(struct bContext *C, struct wmOperator *op) +{ + Scene *scene = CTX_data_scene(C); + SceneLANPR *lanpr = &scene->lanpr; + + LANPR_LineLayer *ll = lanpr->active_layer; + + if (!ll) { + return OPERATOR_FINISHED; + } + + int dir = RNA_enum_get(op->ptr, "direction"); + + if (dir == 1 && ll->prev) { + BLI_remlink(&lanpr->line_layers, ll); + BLI_insertlinkbefore(&lanpr->line_layers, ll->prev, ll); + } + else if (dir == -1 && ll->next) { + BLI_remlink(&lanpr->line_layers, ll); + BLI_insertlinkafter(&lanpr->line_layers, ll->next, ll); + } + + DEG_id_tag_update(&scene->id, ID_RECALC_COPY_ON_WRITE); + + WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, NULL); + + return OPERATOR_FINISHED; +} +static int lanpr_add_line_component_exec(struct bContext *C, struct wmOperator *UNUSED(op)) +{ + Scene *scene = CTX_data_scene(C); + SceneLANPR *lanpr = &scene->lanpr; + + ED_lanpr_new_line_component(lanpr); + + return OPERATOR_FINISHED; +} +static int lanpr_delete_line_component_exec(struct bContext *C, struct wmOperator *op) +{ + Scene *scene = CTX_data_scene(C); + SceneLANPR *lanpr = &scene->lanpr; + LANPR_LineLayer *ll = lanpr->active_layer; + LANPR_LineLayerComponent *llc; + int i = 0; + + if (!ll) { + return OPERATOR_FINISHED; + } + + int index = RNA_int_get(op->ptr, "index"); + + for (llc = ll->components.first; llc; llc = llc->next) { + if (index == i) { + break; + } + i++; + } + + if (llc) { + BLI_remlink(&ll->components, llc); + MEM_freeN(llc); + } + + return OPERATOR_FINISHED; +} + +static int lanpr_rebuild_all_commands_exec(struct bContext *C, struct wmOperator *UNUSED(op)) +{ + Scene *scene = CTX_data_scene(C); + SceneLANPR *lanpr = &scene->lanpr; + + lanpr_rebuild_all_command(lanpr); + + DEG_id_tag_update(&scene->id, ID_RECALC_COPY_ON_WRITE); + + WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, NULL); + + return OPERATOR_FINISHED; +} +static int lanpr_enable_all_line_types_exec(struct bContext *C, struct wmOperator *UNUSED(op)) +{ + Scene *scene = CTX_data_scene(C); + SceneLANPR *lanpr = &scene->lanpr; + LANPR_LineLayer *ll; + + if (!(ll = lanpr->active_layer)) { + return OPERATOR_FINISHED; + } + + ll->contour.enabled = 1; + ll->crease.enabled = 1; + ll->edge_mark.enabled = 1; + ll->material_separate.enabled = 1; + ll->intersection.enabled = 1; + + copy_v3_v3(ll->contour.color, ll->color); + copy_v3_v3(ll->crease.color, ll->color); + copy_v3_v3(ll->edge_mark.color, ll->color); + copy_v3_v3(ll->material_separate.color, ll->color); + copy_v3_v3(ll->intersection.color, ll->color); + + ll->contour.thickness = 1; + ll->crease.thickness = 1; + ll->material_separate.thickness = 1; + ll->edge_mark.thickness = 1; + ll->intersection.thickness = 1; + + return OPERATOR_FINISHED; +} +static int lanpr_auto_create_line_layer_exec(struct bContext *C, struct wmOperator *op) +{ + Scene *scene = CTX_data_scene(C); + SceneLANPR *lanpr = &scene->lanpr; + + LANPR_LineLayer *ll; + + ll = ED_lanpr_new_line_layer(lanpr); + ll->thickness = 1.7; + + lanpr_enable_all_line_types_exec(C, op); + + ll = ED_lanpr_new_line_layer(lanpr); + ll->thickness = 0.9; + copy_v3_fl(ll->color, 0.6); + + lanpr_enable_all_line_types_exec(C, op); + + ll = ED_lanpr_new_line_layer(lanpr); + ll->thickness = 0.7; + copy_v3_fl(ll->color, 0.5); + + lanpr_enable_all_line_types_exec(C, op); + + lanpr_rebuild_all_command(lanpr); + + return OPERATOR_FINISHED; +} + +void SCENE_OT_lanpr_add_line_layer(struct wmOperatorType *ot) +{ + + ot->name = "Add Line Layer"; + ot->description = "Add a new line layer"; + ot->idname = "SCENE_OT_lanpr_add_line_layer"; + + ot->exec = lanpr_add_line_layer_exec; +} +void SCENE_OT_lanpr_delete_line_layer(struct wmOperatorType *ot) +{ + + ot->name = "Delete Line Layer"; + ot->description = "Delete selected line layer"; + ot->idname = "SCENE_OT_lanpr_delete_line_layer"; + + ot->exec = lanpr_delete_line_layer_exec; +} +void SCENE_OT_lanpr_rebuild_all_commands(struct wmOperatorType *ot) +{ + + ot->name = "Refresh Drawing Commands"; + ot->description = "Refresh LANPR line layer drawing commands"; + ot->idname = "SCENE_OT_lanpr_rebuild_all_commands"; + + ot->exec = lanpr_rebuild_all_commands_exec; +} +void SCENE_OT_lanpr_auto_create_line_layer(struct wmOperatorType *ot) +{ + + ot->name = "Auto Create Line Layer"; + ot->description = "Automatically create defalt line layer config"; + ot->idname = "SCENE_OT_lanpr_auto_create_line_layer"; + + ot->exec = lanpr_auto_create_line_layer_exec; +} +void SCENE_OT_lanpr_move_line_layer(struct wmOperatorType *ot) +{ + static const EnumPropertyItem line_layer_move[] = { + {1, "UP", 0, "Up", ""}, {-1, "DOWN", 0, "Down", ""}, {0, NULL, 0, NULL, NULL}}; + + ot->name = "Move Line Layer"; + ot->description = "Move LANPR line layer up and down"; + ot->idname = "SCENE_OT_lanpr_move_line_layer"; + + /* this need property to assign up/down direction */ + + ot->exec = lanpr_move_line_layer_exec; + + RNA_def_enum(ot->srna, + "direction", + line_layer_move, + 0, + "Direction", + "Direction to move the active line layer towards"); +} +void SCENE_OT_lanpr_enable_all_line_types(struct wmOperatorType *ot) +{ + ot->name = "Enable All Line Types"; + ot->description = "Enable All Line Types In This Line Layer"; + ot->idname = "SCENE_OT_lanpr_enable_all_line_types"; + + ot->exec = lanpr_enable_all_line_types_exec; +} +void SCENE_OT_lanpr_add_line_component(struct wmOperatorType *ot) +{ + + ot->name = "Add Line Component"; + ot->description = "Add a new line Component"; + ot->idname = "SCENE_OT_lanpr_add_line_component"; + + ot->exec = lanpr_add_line_component_exec; +} +void SCENE_OT_lanpr_delete_line_component(struct wmOperatorType *ot) +{ + + ot->name = "Delete Line Component"; + ot->description = "Delete selected line component"; + ot->idname = "SCENE_OT_lanpr_delete_line_component"; + + ot->exec = lanpr_delete_line_component_exec; + + RNA_def_int(ot->srna, "index", 0, 0, 10000, "index", "index of this line component", 0, 10000); +} + +/* Geometry */ + +int use_smooth_contour_modifier_contour = 0; /* debug purpose */ + +static void lanpr_cut_render_line(LANPR_RenderBuffer *rb, + LANPR_RenderLine *rl, + real Begin, + real End) +{ + LANPR_RenderLineSegment *rls = rl->segments.first, *irls; + LANPR_RenderLineSegment *begin_segment = 0, *end_segment = 0; + LANPR_RenderLineSegment *ns = 0, *ns2 = 0; + int untouched = 0; + + if (TNS_DOUBLE_CLOSE_ENOUGH(Begin, End)) { + return; + } + + if (Begin != Begin) { + Begin = 0; + } + if (End != End) { + End = 0; + } + + if (Begin > End) { + real t = Begin; + Begin = End; + End = t; + } + + for (rls = rl->segments.first; rls; rls = rls->next) { + if (TNS_DOUBLE_CLOSE_ENOUGH(rls->at, Begin)) { + begin_segment = rls; + ns = begin_segment; + break; + } + if (!rls->next) { + break; + } + irls = rls->next; + if (irls->at > Begin + 1e-09 && Begin > rls->at) { + begin_segment = irls; + ns = mem_static_aquire_thread(&rb->render_data_pool, sizeof(LANPR_RenderLineSegment)); + break; + } + } + if (!begin_segment && TNS_DOUBLE_CLOSE_ENOUGH(1, End)) { + untouched = 1; + } + for (rls = begin_segment; rls; rls = rls->next) { + if (TNS_DOUBLE_CLOSE_ENOUGH(rls->at, End)) { + end_segment = rls; + ns2 = end_segment; + break; + } + /* irls = rls->next; */ + /* added this to prevent rls->at == 1.0 (we don't need an end point for this) */ + if (!rls->next && TNS_DOUBLE_CLOSE_ENOUGH(1, End)) { + end_segment = rls; + ns2 = end_segment; + untouched = 1; + break; + } + else if (rls->at > End) { + end_segment = rls; + ns2 = mem_static_aquire_thread(&rb->render_data_pool, sizeof(LANPR_RenderLineSegment)); + break; + } + } + + if (!ns) { + ns = mem_static_aquire_thread(&rb->render_data_pool, sizeof(LANPR_RenderLineSegment)); + } + if (!ns2) { + if (untouched) { + ns2 = ns; + end_segment = ns2; + } + else + ns2 = mem_static_aquire_thread(&rb->render_data_pool, sizeof(LANPR_RenderLineSegment)); + } + + if (begin_segment) { + if (begin_segment != ns) { + ns->occlusion = begin_segment->prev ? (irls = begin_segment->prev)->occlusion : 0; + list_insert_item_before(&rl->segments, (void *)ns, (void *)begin_segment); + } + } + else { + ns->occlusion = (irls = rl->segments.last)->occlusion; + BLI_addtail(&rl->segments, ns); + } + if (end_segment) { + if (end_segment != ns2) { + ns2->occlusion = end_segment->prev ? (irls = end_segment->prev)->occlusion : 0; + list_insert_item_before(&rl->segments, (void *)ns2, (void *)end_segment); + } + } + else { + ns2->occlusion = (irls = rl->segments.last)->occlusion; + BLI_addtail(&rl->segments, ns2); + } + + ns->at = Begin; + if (!untouched) { + ns2->at = End; + } + else { + ns2 = ns2->next; + } + + for (rls = ns; rls && rls != ns2; rls = rls->next) { + rls->occlusion++; + } + + char min_occ = 127; + for (rls = rl->segments.first; rls; rls = rls->next) { + min_occ = MIN2(min_occ, rls->occlusion); + } + rl->min_occ = min_occ; +} +static int lanpr_make_next_occlusion_task_info(LANPR_RenderBuffer *rb, LANPR_RenderTaskInfo *rti) +{ + LinkData *data; + int i; + int res = 0; + + BLI_spin_lock(&rb->cs_management); + + if (rb->contour_managed) { + data = rb->contour_managed; + rti->contour = (void *)data; + rti->contour_pointers.first = data; + for (i = 0; i < TNS_THREAD_LINE_COUNT && data; i++) { + data = data->next; + } + rb->contour_managed = data; + rti->contour_pointers.last = data ? data->prev : rb->contours.last; + res = 1; + } + else { + list_handle_empty(&rti->contour_pointers); + rti->contour = 0; + } + + if (rb->intersection_managed) { + data = rb->intersection_managed; + rti->intersection = (void *)data; + rti->intersection_pointers.first = data; + for (i = 0; i < TNS_THREAD_LINE_COUNT && data; i++) { + data = data->next; + } + rb->intersection_managed = data; + rti->intersection_pointers.last = data ? data->prev : rb->intersection_lines.last; + res = 1; + } + else { + list_handle_empty(&rti->intersection_pointers); + rti->intersection = 0; + } + + if (rb->crease_managed) { + data = rb->crease_managed; + rti->crease = (void *)data; + rti->crease_pointers.first = data; + for (i = 0; i < TNS_THREAD_LINE_COUNT && data; i++) { + data = data->next; + } + rb->crease_managed = data; + rti->crease_pointers.last = data ? data->prev : rb->crease_lines.last; + res = 1; + } + else { + list_handle_empty(&rti->crease_pointers); + rti->crease = 0; + } + + if (rb->material_managed) { + data = rb->material_managed; + rti->material = (void *)data; + rti->material_pointers.first = data; + for (i = 0; i < TNS_THREAD_LINE_COUNT && data; i++) { + data = data->next; + } + rb->material_managed = data; + rti->material_pointers.last = data ? data->prev : rb->material_lines.last; + res = 1; + } + else { + list_handle_empty(&rti->material_pointers); + rti->material = 0; + } + + if (rb->edge_mark_managed) { + data = rb->edge_mark_managed; + rti->edge_mark = (void *)data; + rti->edge_mark_pointers.first = data; + for (i = 0; i < TNS_THREAD_LINE_COUNT && data; i++) { + data = data->next; + } + rb->edge_mark_managed = data; + rti->edge_mark_pointers.last = data ? data->prev : rb->edge_marks.last; + res = 1; + } + else { + list_handle_empty(&rti->edge_mark_pointers); + rti->edge_mark = 0; + } + + BLI_spin_unlock(&rb->cs_management); + + return res; +} +static void lanpr_calculate_single_line_occlusion(LANPR_RenderBuffer *rb, + LANPR_RenderLine *rl, + int thread_id) +{ + real x = rl->l->fbcoord[0], y = rl->l->fbcoord[1]; + LANPR_BoundingArea *ba = lanpr_get_first_possible_bounding_area(rb, rl); + LANPR_BoundingArea *nba = ba; + LANPR_RenderTriangleThread *rt; + LinkData *lip; + Object *c = rb->scene->camera; + real l, r; + real k = (rl->r->fbcoord[1] - rl->l->fbcoord[1]) / + (rl->r->fbcoord[0] - rl->l->fbcoord[0] + 1e-30); + int PositiveX = (rl->r->fbcoord[0] - rl->l->fbcoord[0]) > 0 ? + 1 : + (rl->r->fbcoord[0] == rl->l->fbcoord[0] ? 0 : -1); + int PositiveY = (rl->r->fbcoord[1] - rl->l->fbcoord[1]) > 0 ? + 1 : + (rl->r->fbcoord[1] == rl->l->fbcoord[1] ? 0 : -1); + + /* printf("PX %d %lf PY %d %lf\n", PositiveX, rl->r->fbcoord[0] - */ + /* rl->l->fbcoord[0], PositiveY, rl->r->fbcoord[1] - */ + /* rl->l->fbcoord[1]); */ + + while (nba) { + + for (lip = nba->linked_triangles.first; lip; lip = lip->next) { + rt = lip->data; + if (rt->testing[thread_id] == rl || rl->l->intersecting_with == (void *)rt || + rl->r->intersecting_with == (void *)rt) { + continue; + } + rt->testing[thread_id] = rl; + if (lanpr_triangle_line_imagespace_intersection_v2(&rb->cs_management, + (void *)rt, + rl, + c, + rb->view_projection, + rb->view_vector, + &l, + &r)) { + lanpr_cut_render_line(rb, rl, l, r); + if (rl->min_occ > rb->max_occlusion_level) { + return; /* No need to caluclate any longer. */ + } + } + } + + nba = lanpr_get_next_bounding_area(nba, rl, x, y, k, PositiveX, PositiveY, &x, &y); + } +} +static void lanpr_THREAD_calculate_line_occlusion(TaskPool *__restrict pool, + LANPR_RenderTaskInfo *rti, + int UNUSED(threadid)) +{ + LANPR_RenderBuffer *rb = lanpr_share.render_buffer_shared; + LinkData *lip; + + while (lanpr_make_next_occlusion_task_info(rb, rti)) { + + for (lip = (void *)rti->contour; lip && lip->prev != rti->contour_pointers.last; + lip = lip->next) { + lanpr_calculate_single_line_occlusion(rb, lip->data, rti->thread_id); + } + + for (lip = (void *)rti->crease; lip && lip->prev != rti->crease_pointers.last; + lip = lip->next) { + lanpr_calculate_single_line_occlusion(rb, lip->data, rti->thread_id); + } + + for (lip = (void *)rti->intersection; lip && lip->prev != rti->intersection_pointers.last; + lip = lip->next) { + lanpr_calculate_single_line_occlusion(rb, lip->data, rti->thread_id); + } + + for (lip = (void *)rti->material; lip && lip->prev != rti->material_pointers.last; + lip = lip->next) { + lanpr_calculate_single_line_occlusion(rb, lip->data, rti->thread_id); + } + + for (lip = (void *)rti->edge_mark; lip && lip->prev != rti->edge_mark_pointers.last; + lip = lip->next) { + lanpr_calculate_single_line_occlusion(rb, lip->data, rti->thread_id); + } + } +} +static void lanpr_THREAD_calculate_line_occlusion_begin(LANPR_RenderBuffer *rb) +{ + int thread_count = rb->thread_count; + LANPR_RenderTaskInfo *rti = MEM_callocN(sizeof(LANPR_RenderTaskInfo) * thread_count, + "Task Pool"); + TaskScheduler *scheduler = BLI_task_scheduler_get(); + int i; + + rb->contour_managed = rb->contours.first; + rb->crease_managed = rb->crease_lines.first; + rb->intersection_managed = rb->intersection_lines.first; + rb->material_managed = rb->material_lines.first; + rb->edge_mark_managed = rb->edge_marks.first; + + TaskPool *tp = BLI_task_pool_create(scheduler, 0); + + for (i = 0; i < thread_count; i++) { + rti[i].thread_id = i; + BLI_task_pool_push(tp, (TaskRunFunction)lanpr_THREAD_calculate_line_occlusion, &rti[i], 0, TASK_PRIORITY_HIGH); + } + BLI_task_pool_work_and_wait(tp); + BLI_task_pool_free(tp); + + MEM_freeN(rti); +} + +int ED_lanpr_point_inside_triangled(tnsVector2d v, tnsVector2d v0, tnsVector2d v1, tnsVector2d v2) +{ + double cl, c; + + cl = (v0[0] - v[0]) * (v1[1] - v[1]) - (v0[1] - v[1]) * (v1[0] - v[0]); + c = cl; + + cl = (v1[0] - v[0]) * (v2[1] - v[1]) - (v1[1] - v[1]) * (v2[0] - v[0]); + if (c * cl <= 0) { + return 0; + } + else + c = cl; + + cl = (v2[0] - v[0]) * (v0[1] - v[1]) - (v2[1] - v[1]) * (v0[0] - v[0]); + if (c * cl <= 0) { + return 0; + } + else + c = cl; + + cl = (v0[0] - v[0]) * (v1[1] - v[1]) - (v0[1] - v[1]) * (v1[0] - v[0]); + if (c * cl <= 0) { + return 0; + } + + return 1; +} +static int lanpr_point_on_lined(tnsVector2d v, tnsVector2d v0, tnsVector2d v1) +{ + real c1, c2; + + c1 = tMatGetLinearRatio(v0[0], v1[0], v[0]); + c2 = tMatGetLinearRatio(v0[1], v1[1], v[1]); + + if (TNS_DOUBLE_CLOSE_ENOUGH(c1, c2) && c1 >= 0 && c1 <= 1) { + return 1; + } + + return 0; +} +static int lanpr_point_triangle_relation(tnsVector2d v, + tnsVector2d v0, + tnsVector2d v1, + tnsVector2d v2) +{ + double cl, c; + real r; + if (lanpr_point_on_lined(v, v0, v1) || lanpr_point_on_lined(v, v1, v2) || + lanpr_point_on_lined(v, v2, v0)) { + return 1; + } + + cl = (v0[0] - v[0]) * (v1[1] - v[1]) - (v0[1] - v[1]) * (v1[0] - v[0]); + c = cl; + + cl = (v1[0] - v[0]) * (v2[1] - v[1]) - (v1[1] - v[1]) * (v2[0] - v[0]); + if ((r = c * cl) < 0) { + return 0; + } + /* else if(r == 0) return 1; // removed, point could still be on the extention line of some edge + */ + else + c = cl; + + cl = (v2[0] - v[0]) * (v0[1] - v[1]) - (v2[1] - v[1]) * (v0[0] - v[0]); + if ((r = c * cl) < 0) { + return 0; + } + /* else if(r == 0) return 1; */ + else + c = cl; + + cl = (v0[0] - v[0]) * (v1[1] - v[1]) - (v0[1] - v[1]) * (v1[0] - v[0]); + if ((r = c * cl) < 0) { + return 0; + } + else if (r == 0) { + return 1; + } + + return 2; +} +static int lanpr_point_inside_triangle3de(tnsVector3d v, + tnsVector3d v0, + tnsVector3d v1, + tnsVector3d v2) +{ + tnsVector3d l, r; + tnsVector3d N1, N2; + real d; + + tMatVectorMinus3d(l, v1, v0); + tMatVectorMinus3d(r, v, v1); + /* tmat_normalize_self_3d(l); */ + /* tmat_normalize_self_3d(r); */ + tmat_vector_cross_3d(N1, l, r); + + tMatVectorMinus3d(l, v2, v1); + tMatVectorMinus3d(r, v, v2); + /* tmat_normalize_self_3d(l); */ + /* tmat_normalize_self_3d(r); */ + tmat_vector_cross_3d(N2, l, r); + + if ((d = tmat_dot_3d(N1, N2, 0)) < 0) { + return 0; + } + /* if (d<DBL_EPSILON) return -1; */ + + tMatVectorMinus3d(l, v0, v2); + tMatVectorMinus3d(r, v, v0); + /* tmat_normalize_self_3d(l); */ + /* tmat_normalize_self_3d(r); */ + tmat_vector_cross_3d(N1, l, r); + + if ((d = tmat_dot_3d(N1, N2, 0)) < 0) { + return 0; + } + /* if (d<DBL_EPSILON) return -1; */ + + tMatVectorMinus3d(l, v1, v0); + tMatVectorMinus3d(r, v, v1); + /* tmat_normalize_self_3d(l); */ + /* tmat_normalize_self_3d(r); */ + tmat_vector_cross_3d(N2, l, r); + + if ((d = tmat_dot_3d(N1, N2, 0)) < 0) { + return 0; + } + /* if (d<DBL_EPSILON) return -1; */ + + return 1; +} + +static LANPR_RenderElementLinkNode *lanpr_new_cull_triangle_space64(LANPR_RenderBuffer *rb) +{ + LANPR_RenderElementLinkNode *reln; + + LANPR_RenderTriangle *RenderTriangles = mem_static_aquire( + &rb->render_data_pool, + 64 * rb->triangle_size); /* CreateNewBuffer(LANPR_RenderTriangle, 64); */ + + reln = list_append_pointer_static_sized(&rb->triangle_buffer_pointers, + &rb->render_data_pool, + RenderTriangles, + sizeof(LANPR_RenderElementLinkNode)); + reln->element_count = 64; + reln->additional = 1; + + return reln; +} +static LANPR_RenderElementLinkNode *lanpr_new_cull_point_space64(LANPR_RenderBuffer *rb) +{ + LANPR_RenderElementLinkNode *reln; + + LANPR_RenderVert *Rendervertices = mem_static_aquire( + &rb->render_data_pool, + sizeof(LANPR_RenderVert) * 64); /* CreateNewBuffer(LANPR_RenderVert, 64); */ + + reln = list_append_pointer_static_sized(&rb->vertex_buffer_pointers, + &rb->render_data_pool, + Rendervertices, + sizeof(LANPR_RenderElementLinkNode)); + reln->element_count = 64; + reln->additional = 1; + + return reln; +} +static void lanpr_calculate_render_triangle_normal(LANPR_RenderTriangle *rt); +static void lanpr_assign_render_line_with_triangle(LANPR_RenderTriangle *rt) +{ + if (!rt->rl[0]->tl) { + rt->rl[0]->tl = rt; + } + else if (!rt->rl[0]->tr) { + rt->rl[0]->tr = rt; + } + + if (!rt->rl[1]->tl) { + rt->rl[1]->tl = rt; + } + else if (!rt->rl[1]->tr) { + rt->rl[1]->tr = rt; + } + + if (!rt->rl[2]->tl) { + rt->rl[2]->tl = rt; + } + else if (!rt->rl[2]->tr) { + rt->rl[2]->tr = rt; + } +} +static void lanpr_post_triangle(LANPR_RenderTriangle *rt, LANPR_RenderTriangle *orig) +{ + if (rt->v[0]) { + tMatVectorAccum3d(rt->gc, rt->v[0]->fbcoord); + } + if (rt->v[1]) { + tMatVectorAccum3d(rt->gc, rt->v[1]->fbcoord); + } + if (rt->v[2]) { + tMatVectorAccum3d(rt->gc, rt->v[2]->fbcoord); + } + tMatVectorMultiSelf3d(rt->gc, 1.0f / 3.0f); + + tMatVectorCopy3d(orig->gn, rt->gn); +} + +#define RT_AT(head, rb, offset) ((BYTE *)head + offset * rb->triangle_size) + +static void lanpr_cull_triangles(LANPR_RenderBuffer *rb) +{ + LANPR_RenderLine *rl; + LANPR_RenderTriangle *rt, *rt1, *rt2; + LANPR_RenderVert *rv; + LANPR_RenderElementLinkNode *reln, *veln, *teln; + LANPR_RenderLineSegment *rls; + real *vp = rb->view_projection; + int i; + real a; + int v_count = 0, t_count = 0; + Object *o; + + real cam_pos[3]; + Object *cam = ((Object *)rb->scene->camera); + cam_pos[0] = cam->obmat[3][0]; + cam_pos[1] = cam->obmat[3][1]; + cam_pos[2] = cam->obmat[3][2]; + + real view_dir[3], clip_advance[3]; + tMatVectorCopy3d(rb->view_vector, view_dir); + tMatVectorCopy3d(rb->view_vector, clip_advance); + tMatVectorMultiSelf3d(clip_advance, -((Camera *)cam->data)->clip_start); + tMatVectorAccum3d(cam_pos, clip_advance); + + veln = lanpr_new_cull_point_space64(rb); + teln = lanpr_new_cull_triangle_space64(rb); + rv = &((LANPR_RenderVert *)veln->pointer)[v_count]; + rt1 = (void *)(((BYTE *)teln->pointer) + rb->triangle_size * t_count); + + for (reln = rb->triangle_buffer_pointers.first; reln; reln = reln->next) { + if (reln->additional) { + continue; + } + o = reln->object_ref; + for (i = 0; i < reln->element_count; i++) { + int In1 = 0, In2 = 0, In3 = 0; + rt = (void *)(((BYTE *)reln->pointer) + rb->triangle_size * i); + if (rt->v[0]->fbcoord[3] < ((Camera *)cam->data)->clip_start) { + In1 = 1; + } + if (rt->v[1]->fbcoord[3] < ((Camera *)cam->data)->clip_start) { + In2 = 1; + } + if (rt->v[2]->fbcoord[3] < ((Camera *)cam->data)->clip_start) { + In3 = 1; + } + + if (v_count > 60) { + veln->element_count = v_count; + veln = lanpr_new_cull_point_space64(rb); + v_count = 0; + } + + if (t_count > 60) { + teln->element_count = t_count; + teln = lanpr_new_cull_triangle_space64(rb); + t_count = 0; + } + + /* if ((!rt->rl[0]->next && !rt->rl[0]->prev) || */ + /* (!rt->rl[1]->next && !rt->rl[1]->prev) || */ + /* (!rt->rl[2]->next && !rt->rl[2]->prev)) { */ + /* printf("'"); // means this triangle is lonely???? */ + /* } */ + + rv = &((LANPR_RenderVert *)veln->pointer)[v_count]; + rt1 = (void *)(((BYTE *)teln->pointer) + rb->triangle_size * t_count); + rt2 = (void *)(((BYTE *)teln->pointer) + rb->triangle_size * (t_count + 1)); + + real vv1[3], vv2[3], dot1, dot2; + + switch (In1 + In2 + In3) { + case 0: + continue; + case 3: + rt->cull_status = LANPR_CULL_DISCARD; + BLI_remlink(&rb->all_render_lines, (void *)rt->rl[0]); + rt->rl[0]->next = rt->rl[0]->prev = 0; + BLI_remlink(&rb->all_render_lines, (void *)rt->rl[1]); + rt->rl[1]->next = rt->rl[1]->prev = 0; + BLI_remlink(&rb->all_render_lines, (void *)rt->rl[2]); + rt->rl[2]->next = rt->rl[2]->prev = 0; + continue; + case 2: + rt->cull_status = LANPR_CULL_USED; + if (!In1) { + tMatVectorMinus3d(vv1, rt->v[0]->gloc, cam_pos); + tMatVectorMinus3d(vv2, cam_pos, rt->v[2]->gloc); + dot1 = tmat_dot_3d(vv1, view_dir, 0); + dot2 = tmat_dot_3d(vv2, view_dir, 0); + a = dot1 / (dot1 + dot2); + interp_v3_v3v3_db(rv[0].gloc, rt->v[0]->gloc, rt->v[2]->gloc, a); + tmat_apply_transform_44d(rv[0].fbcoord, vp, rv[0].gloc); + + tMatVectorMinus3d(vv1, rt->v[0]->gloc, cam_pos); + tMatVectorMinus3d(vv2, cam_pos, rt->v[1]->gloc); + dot1 = tmat_dot_3d(vv1, view_dir, 0); + dot2 = tmat_dot_3d(vv2, view_dir, 0); + a = dot1 / (dot1 + dot2); + interp_v3_v3v3_db(rv[1].gloc, rt->v[0]->gloc, rt->v[1]->gloc, a); + tmat_apply_transform_44d(rv[1].fbcoord, vp, rv[1].gloc); + + BLI_remlink(&rb->all_render_lines, (void *)rt->rl[0]); + rt->rl[0]->next = rt->rl[0]->prev = 0; + BLI_remlink(&rb->all_render_lines, (void *)rt->rl[1]); + rt->rl[1]->next = rt->rl[1]->prev = 0; + BLI_remlink(&rb->all_render_lines, (void *)rt->rl[2]); + rt->rl[2]->next = rt->rl[2]->prev = 0; + + rl = mem_static_aquire(&rb->render_data_pool, sizeof(LANPR_RenderLine)); + rls = mem_static_aquire(&rb->render_data_pool, sizeof(LANPR_RenderLineSegment)); + BLI_addtail(&rl->segments, rls); + BLI_addtail(&rb->all_render_lines, rl); + rl->l = &rv[1]; + rl->r = &rv[0]; + rl->tl = rt1; + rt1->rl[1] = rl; + rl->object_ref = o; + + rl = mem_static_aquire(&rb->render_data_pool, sizeof(LANPR_RenderLine)); + rls = mem_static_aquire(&rb->render_data_pool, sizeof(LANPR_RenderLineSegment)); + BLI_addtail(&rl->segments, rls); + BLI_addtail(&rb->all_render_lines, rl); + rl->l = &rv[1]; + rl->r = rt->v[0]; + rl->tl = rt->rl[0]->tl == rt ? rt1 : rt->rl[0]->tl; + rl->tr = rt->rl[0]->tr == rt ? rt1 : rt->rl[0]->tr; + rt1->rl[0] = rl; + rl->object_ref = o; + + rl = mem_static_aquire(&rb->render_data_pool, sizeof(LANPR_RenderLine)); + rls = mem_static_aquire(&rb->render_data_pool, sizeof(LANPR_RenderLineSegment)); + BLI_addtail(&rl->segments, rls); + BLI_addtail(&rb->all_render_lines, rl); + rl->l = rt->v[0]; + rl->r = &rv[0]; + rl->tl = rt->rl[2]->tl == rt ? rt1 : rt->rl[2]->tl; + rl->tr = rt->rl[2]->tr == rt ? rt1 : rt->rl[2]->tr; + rt1->rl[2] = rl; + rl->object_ref = o; + + rt1->v[0] = rt->v[0]; + rt1->v[1] = &rv[1]; + rt1->v[2] = &rv[0]; + + lanpr_post_triangle(rt1, rt); + + v_count += 2; + t_count += 1; + continue; + } + else if (!In3) { + tMatVectorMinus3d(vv1, rt->v[2]->gloc, cam_pos); + tMatVectorMinus3d(vv2, cam_pos, rt->v[0]->gloc); + dot1 = tmat_dot_3d(vv1, view_dir, 0); + dot2 = tmat_dot_3d(vv2, view_dir, 0); + a = dot1 / (dot1 + dot2); + interp_v3_v3v3_db(rv[0].gloc, rt->v[2]->gloc, rt->v[0]->gloc, a); + tmat_apply_transform_44d(rv[0].fbcoord, vp, rv[0].gloc); + + tMatVectorMinus3d(vv1, rt->v[2]->gloc, cam_pos); + tMatVectorMinus3d(vv2, cam_pos, rt->v[1]->gloc); + dot1 = tmat_dot_3d(vv1, view_dir, 0); + dot2 = tmat_dot_3d(vv2, view_dir, 0); + a = dot1 / (dot1 + dot2); + interp_v3_v3v3_db(rv[1].gloc, rt->v[2]->gloc, rt->v[1]->gloc, a); + tmat_apply_transform_44d(rv[1].fbcoord, vp, rv[1].gloc); + + BLI_remlink(&rb->all_render_lines, (void *)rt->rl[0]); + rt->rl[0]->next = rt->rl[0]->prev = 0; + BLI_remlink(&rb->all_render_lines, (void *)rt->rl[1]); + rt->rl[1]->next = rt->rl[1]->prev = 0; + BLI_remlink(&rb->all_render_lines, (void *)rt->rl[2]); + rt->rl[2]->next = rt->rl[2]->prev = 0; + + rl = mem_static_aquire(&rb->render_data_pool, sizeof(LANPR_RenderLine)); + rls = mem_static_aquire(&rb->render_data_pool, sizeof(LANPR_RenderLineSegment)); + BLI_addtail(&rl->segments, rls); + BLI_addtail(&rb->all_render_lines, rl); + rl->l = &rv[0]; + rl->r = &rv[1]; + rl->tl = rt1; + rt1->rl[0] = rl; + rl->object_ref = o; + + rl = mem_static_aquire(&rb->render_data_pool, sizeof(LANPR_RenderLine)); + rls = mem_static_aquire(&rb->render_data_pool, sizeof(LANPR_RenderLineSegment)); + BLI_addtail(&rl->segments, rls); + BLI_addtail(&rb->all_render_lines, rl); + rl->l = &rv[1]; + rl->r = rt->v[2]; + rl->tl = rt->rl[1]->tl == rt ? rt1 : rt->rl[1]->tl; + rl->tr = rt->rl[1]->tr == rt ? rt1 : rt->rl[1]->tr; + rt1->rl[1] = rl; + rl->object_ref = o; + + rl = mem_static_aquire(&rb->render_data_pool, sizeof(LANPR_RenderLine)); + rls = mem_static_aquire(&rb->render_data_pool, sizeof(LANPR_RenderLineSegment)); + BLI_addtail(&rl->segments, rls); + BLI_addtail(&rb->all_render_lines, rl); + rl->l = rt->v[2]; + rl->r = &rv[0]; + rl->tl = rt->rl[2]->tl == rt ? rt1 : rt->rl[2]->tl; + rl->tr = rt->rl[2]->tr == rt ? rt1 : rt->rl[2]->tr; + rt1->rl[2] = rl; + rl->object_ref = o; + + rt1->v[0] = &rv[1]; + rt1->v[1] = rt->v[2]; + rt1->v[2] = &rv[0]; + + lanpr_post_triangle(rt1, rt); + + v_count += 2; + t_count += 1; + continue; + } + else if (!In2) { + tMatVectorMinus3d(vv1, rt->v[1]->gloc, cam_pos); + tMatVectorMinus3d(vv2, cam_pos, rt->v[2]->gloc); + dot1 = tmat_dot_3d(vv1, view_dir, 0); + dot2 = tmat_dot_3d(vv2, view_dir, 0); + a = dot1 / (dot1 + dot2); + interp_v3_v3v3_db(rv[0].gloc, rt->v[1]->gloc, rt->v[2]->gloc, a); + tmat_apply_transform_44d(rv[0].fbcoord, vp, rv[0].gloc); + + tMatVectorMinus3d(vv1, rt->v[1]->gloc, cam_pos); + tMatVectorMinus3d(vv2, cam_pos, rt->v[0]->gloc); + dot1 = tmat_dot_3d(vv1, view_dir, 0); + dot2 = tmat_dot_3d(vv2, view_dir, 0); + a = dot1 / (dot1 + dot2); + interp_v3_v3v3_db(rv[1].gloc, rt->v[1]->gloc, rt->v[0]->gloc, a); + tmat_apply_transform_44d(rv[1].fbcoord, vp, rv[1].gloc); + + BLI_remlink(&rb->all_render_lines, (void *)rt->rl[0]); + rt->rl[0]->next = rt->rl[0]->prev = 0; + BLI_remlink(&rb->all_render_lines, (void *)rt->rl[1]); + rt->rl[1]->next = rt->rl[1]->prev = 0; + BLI_remlink(&rb->all_render_lines, (void *)rt->rl[2]); + rt->rl[2]->next = rt->rl[2]->prev = 0; + + rl = mem_static_aquire(&rb->render_data_pool, sizeof(LANPR_RenderLine)); + rls = mem_static_aquire(&rb->render_data_pool, sizeof(LANPR_RenderLineSegment)); + BLI_addtail(&rl->segments, rls); + BLI_addtail(&rb->all_render_lines, rl); + rl->l = &rv[1]; + rl->r = &rv[0]; + rl->tl = rt1; + rt1->rl[2] = rl; + rl->object_ref = o; + + rl = mem_static_aquire(&rb->render_data_pool, sizeof(LANPR_RenderLine)); + rls = mem_static_aquire(&rb->render_data_pool, sizeof(LANPR_RenderLineSegment)); + BLI_addtail(&rl->segments, rls); + BLI_addtail(&rb->all_render_lines, rl); + rl->l = &rv[0]; + rl->r = rt->v[1]; + rl->tl = rt->rl[0]->tl == rt ? rt1 : rt->rl[0]->tl; + rl->tr = rt->rl[0]->tr == rt ? rt1 : rt->rl[0]->tr; + rt1->rl[0] = rl; + rl->object_ref = o; + + rl = mem_static_aquire(&rb->render_data_pool, sizeof(LANPR_RenderLine)); + rls = mem_static_aquire(&rb->render_data_pool, sizeof(LANPR_RenderLineSegment)); + BLI_addtail(&rl->segments, rls); + BLI_addtail(&rb->all_render_lines, rl); + rl->l = rt->v[1]; + rl->r = &rv[1]; + rl->tl = rt->rl[1]->tl == rt ? rt1 : rt->rl[1]->tl; + rl->tr = rt->rl[1]->tr == rt ? rt1 : rt->rl[1]->tr; + rt1->rl[1] = rl; + rl->object_ref = o; + + rt1->v[0] = rt->v[1]; + rt1->v[1] = &rv[1]; + rt1->v[2] = &rv[0]; + + lanpr_post_triangle(rt1, rt); + + v_count += 2; + t_count += 1; + continue; + } + break; + case 1: + rt->cull_status = LANPR_CULL_USED; + if (In1) { + tMatVectorMinus3d(vv1, rt->v[1]->gloc, cam_pos); + tMatVectorMinus3d(vv2, cam_pos, rt->v[0]->gloc); + dot1 = tmat_dot_3d(vv1, view_dir, 0); + dot2 = tmat_dot_3d(vv2, view_dir, 0); + a = dot2 / (dot1 + dot2); + interp_v3_v3v3_db(rv[0].gloc, rt->v[0]->gloc, rt->v[1]->gloc, a); + tmat_apply_transform_44d(rv[0].fbcoord, vp, rv[0].gloc); + + tMatVectorMinus3d(vv1, rt->v[2]->gloc, cam_pos); + tMatVectorMinus3d(vv2, cam_pos, rt->v[0]->gloc); + dot1 = tmat_dot_3d(vv1, view_dir, 0); + dot2 = tmat_dot_3d(vv2, view_dir, 0); + a = dot2 / (dot1 + dot2); + interp_v3_v3v3_db(rv[1].gloc, rt->v[0]->gloc, rt->v[2]->gloc, a); + tmat_apply_transform_44d(rv[1].fbcoord, vp, rv[1].gloc); + + BLI_remlink(&rb->all_render_lines, (void *)rt->rl[0]); + rt->rl[0]->next = rt->rl[0]->prev = 0; + BLI_remlink(&rb->all_render_lines, (void *)rt->rl[2]); + rt->rl[2]->next = rt->rl[2]->prev = 0; + + rl = mem_static_aquire(&rb->render_data_pool, sizeof(LANPR_RenderLine)); + rls = mem_static_aquire(&rb->render_data_pool, sizeof(LANPR_RenderLineSegment)); + BLI_addtail(&rl->segments, rls); + BLI_addtail(&rb->all_render_lines, rl); + rl->l = &rv[1]; + rl->r = &rv[0]; + rl->tl = rt1; + rt1->rl[1] = rl; + rl->object_ref = o; + + rl = mem_static_aquire(&rb->render_data_pool, sizeof(LANPR_RenderLine)); + rls = mem_static_aquire(&rb->render_data_pool, sizeof(LANPR_RenderLineSegment)); + BLI_addtail(&rl->segments, rls); + BLI_addtail(&rb->all_render_lines, rl); + rl->l = &rv[0]; + rl->r = rt->v[1]; + rl->tl = rt1; + rl->tr = rt->rl[0]->tr == rt ? rt->rl[0]->tl : rt->rl[0]->tr; + rt1->rl[2] = rl; + rl->object_ref = o; + + rl = mem_static_aquire(&rb->render_data_pool, sizeof(LANPR_RenderLine)); + rls = mem_static_aquire(&rb->render_data_pool, sizeof(LANPR_RenderLineSegment)); + BLI_addtail(&rl->segments, rls); + BLI_addtail(&rb->all_render_lines, rl); + rl->l = rt->v[1]; + rl->r = &rv[1]; + rl->tl = rt1; + rl->tr = rt2; + rt1->rl[0] = rl; + rt2->rl[0] = rl; + rl->object_ref = o; + + rt1->v[0] = rt->v[1]; + rt1->v[1] = &rv[1]; + rt1->v[2] = &rv[0]; + + rl = mem_static_aquire(&rb->render_data_pool, sizeof(LANPR_RenderLine)); + rls = mem_static_aquire(&rb->render_data_pool, sizeof(LANPR_RenderLineSegment)); + BLI_addtail(&rl->segments, rls); + BLI_addtail(&rb->all_render_lines, rl); + rl->l = rt->v[2]; + rl->r = &rv[1]; + rl->tl = rt2; + rl->tr = rt->rl[2]->tr == rt ? rt->rl[2]->tl : rt->rl[2]->tr; + rt2->rl[2] = rl; + rt2->rl[1] = rt->rl[1]; + rl->object_ref = o; + + rt2->v[0] = &rv[1]; + rt2->v[1] = rt->v[1]; + rt2->v[2] = rt->v[2]; + + lanpr_post_triangle(rt1, rt); + lanpr_post_triangle(rt2, rt); + + v_count += 2; + t_count += 2; + continue; + } + else if (In2) { + + tMatVectorMinus3d(vv1, rt->v[1]->gloc, cam_pos); + tMatVectorMinus3d(vv2, cam_pos, rt->v[2]->gloc); + dot1 = tmat_dot_3d(vv1, view_dir, 0); + dot2 = tmat_dot_3d(vv2, view_dir, 0); + a = dot1 / (dot1 + dot2); + interp_v3_v3v3_db(rv[0].gloc, rt->v[1]->gloc, rt->v[2]->gloc, a); + tmat_apply_transform_44d(rv[0].fbcoord, vp, rv[0].gloc); + + tMatVectorMinus3d(vv1, rt->v[1]->gloc, cam_pos); + tMatVectorMinus3d(vv2, cam_pos, rt->v[0]->gloc); + dot1 = tmat_dot_3d(vv1, view_dir, 0); + dot2 = tmat_dot_3d(vv2, view_dir, 0); + a = dot1 / (dot1 + dot2); + interp_v3_v3v3_db(rv[1].gloc, rt->v[1]->gloc, rt->v[0]->gloc, a); + tmat_apply_transform_44d(rv[1].fbcoord, vp, rv[1].gloc); + + BLI_remlink(&rb->all_render_lines, (void *)rt->rl[0]); + rt->rl[0]->next = rt->rl[0]->prev = 0; + BLI_remlink(&rb->all_render_lines, (void *)rt->rl[1]); + rt->rl[1]->next = rt->rl[1]->prev = 0; + + rl = mem_static_aquire(&rb->render_data_pool, sizeof(LANPR_RenderLine)); + rls = mem_static_aquire(&rb->render_data_pool, sizeof(LANPR_RenderLineSegment)); + BLI_addtail(&rl->segments, rls); + BLI_addtail(&rb->all_render_lines, rl); + rl->l = &rv[1]; + rl->r = &rv[0]; + rl->tl = rt1; + rt1->rl[1] = rl; + rl->object_ref = o; + + rl = mem_static_aquire(&rb->render_data_pool, sizeof(LANPR_RenderLine)); + rls = mem_static_aquire(&rb->render_data_pool, sizeof(LANPR_RenderLineSegment)); + BLI_addtail(&rl->segments, rls); + BLI_addtail(&rb->all_render_lines, rl); + rl->l = &rv[0]; + rl->r = rt->v[2]; + rl->tl = rt1; + rl->tr = rt->rl[1]->tl == rt ? rt->rl[1]->tr : rt->rl[1]->tl; + rt1->rl[2] = rl; + rl->object_ref = o; + + rl = mem_static_aquire(&rb->render_data_pool, sizeof(LANPR_RenderLine)); + rls = mem_static_aquire(&rb->render_data_pool, sizeof(LANPR_RenderLineSegment)); + BLI_addtail(&rl->segments, rls); + BLI_addtail(&rb->all_render_lines, rl); + rl->l = rt->v[2]; + rl->r = &rv[1]; + rl->tl = rt1; + rl->tr = rt2; + rt1->rl[0] = rl; + rt2->rl[0] = rl; + rl->object_ref = o; + + rt1->v[0] = rt->v[2]; + rt1->v[1] = &rv[1]; + rt1->v[2] = &rv[0]; + + rl = mem_static_aquire(&rb->render_data_pool, sizeof(LANPR_RenderLine)); + rls = mem_static_aquire(&rb->render_data_pool, sizeof(LANPR_RenderLineSegment)); + BLI_addtail(&rl->segments, rls); + BLI_addtail(&rb->all_render_lines, rl); + rl->l = rt->v[0]; + rl->r = &rv[1]; + rl->tl = rt2; + rl->tr = rt->rl[0]->tr == rt ? rt->rl[0]->tl : rt->rl[0]->tr; + rt2->rl[2] = rl; + rt2->rl[1] = rt->rl[2]; + rl->object_ref = o; + + rt2->v[0] = &rv[1]; + rt2->v[1] = rt->v[2]; + rt2->v[2] = rt->v[0]; + + lanpr_post_triangle(rt1, rt); + lanpr_post_triangle(rt2, rt); + + v_count += 2; + t_count += 2; + continue; + } + else if (In3) { + + tMatVectorMinus3d(vv1, rt->v[2]->gloc, cam_pos); + tMatVectorMinus3d(vv2, cam_pos, rt->v[0]->gloc); + dot1 = tmat_dot_3d(vv1, view_dir, 0); + dot2 = tmat_dot_3d(vv2, view_dir, 0); + a = dot1 / (dot1 + dot2); + interp_v3_v3v3_db(rv[0].gloc, rt->v[2]->gloc, rt->v[0]->gloc, a); + tmat_apply_transform_44d(rv[0].fbcoord, vp, rv[0].gloc); + + tMatVectorMinus3d(vv1, rt->v[2]->gloc, cam_pos); + tMatVectorMinus3d(vv2, cam_pos, rt->v[1]->gloc); + dot1 = tmat_dot_3d(vv1, view_dir, 0); + dot2 = tmat_dot_3d(vv2, view_dir, 0); + a = dot1 / (dot1 + dot2); + interp_v3_v3v3_db(rv[1].gloc, rt->v[2]->gloc, rt->v[1]->gloc, a); + tmat_apply_transform_44d(rv[1].fbcoord, vp, rv[1].gloc); + + BLI_remlink(&rb->all_render_lines, (void *)rt->rl[1]); + rt->rl[1]->next = rt->rl[1]->prev = 0; + BLI_remlink(&rb->all_render_lines, (void *)rt->rl[2]); + rt->rl[2]->next = rt->rl[2]->prev = 0; + + rl = mem_static_aquire(&rb->render_data_pool, sizeof(LANPR_RenderLine)); + rls = mem_static_aquire(&rb->render_data_pool, sizeof(LANPR_RenderLineSegment)); + BLI_addtail(&rl->segments, rls); + BLI_addtail(&rb->all_render_lines, rl); + rl->l = &rv[1]; + rl->r = &rv[0]; + rl->tl = rt1; + rt1->rl[1] = rl; + rl->object_ref = o; + + rl = mem_static_aquire(&rb->render_data_pool, sizeof(LANPR_RenderLine)); + rls = mem_static_aquire(&rb->render_data_pool, sizeof(LANPR_RenderLineSegment)); + BLI_addtail(&rl->segments, rls); + BLI_addtail(&rb->all_render_lines, rl); + rl->l = &rv[0]; + rl->r = rt->v[0]; + rl->tl = rt1; + rl->tr = rt->rl[2]->tl == rt ? rt->rl[2]->tr : rt->rl[2]->tl; + rt1->rl[2] = rl; + rl->object_ref = o; + + rl = mem_static_aquire(&rb->render_data_pool, sizeof(LANPR_RenderLine)); + rls = mem_static_aquire(&rb->render_data_pool, sizeof(LANPR_RenderLineSegment)); + BLI_addtail(&rl->segments, rls); + BLI_addtail(&rb->all_render_lines, rl); + rl->l = rt->v[0]; + rl->r = &rv[1]; + rl->tl = rt1; + rl->tr = rt2; + rt1->rl[0] = rl; + rt2->rl[0] = rl; + rl->object_ref = o; + + rt1->v[0] = rt->v[0]; + rt1->v[1] = &rv[1]; + rt1->v[2] = &rv[0]; + + rl = mem_static_aquire(&rb->render_data_pool, sizeof(LANPR_RenderLine)); + rls = mem_static_aquire(&rb->render_data_pool, sizeof(LANPR_RenderLineSegment)); + BLI_addtail(&rl->segments, rls); + BLI_addtail(&rb->all_render_lines, rl); + rl->l = rt->v[1]; + rl->r = &rv[1]; + rl->tl = rt2; + rl->tr = rt->rl[1]->tr == rt ? rt->rl[1]->tl : rt->rl[1]->tr; + rt2->rl[2] = rl; + rt2->rl[1] = rt->rl[0]; + rl->object_ref = o; + + rt2->v[0] = &rv[1]; + rt2->v[1] = rt->v[0]; + rt2->v[2] = rt->v[1]; + + lanpr_post_triangle(rt1, rt); + lanpr_post_triangle(rt2, rt); + + v_count += 2; + t_count += 2; + continue; + } + break; + } + } + teln->element_count = t_count; + veln->element_count = v_count; + } +} +static void lanpr_perspective_division(LANPR_RenderBuffer *rb) +{ + LANPR_RenderVert *rv; + LANPR_RenderElementLinkNode *reln; + Camera *cam = rb->scene->camera->data; + int i; + + if (cam->type != CAM_PERSP) { + return; + } + + for (reln = rb->vertex_buffer_pointers.first; reln; reln = reln->next) { + rv = reln->pointer; + for (i = 0; i < reln->element_count; i++) { + /* if (rv->fbcoord[2] < -DBL_EPSILON) continue; */ + tMatVectorMultiSelf3d(rv[i].fbcoord, 1 / rv[i].fbcoord[3]); + /* rv[i].fbcoord[2] = cam->clipsta * cam->clipend / (cam->clipend - */ + /* fabs(rv[i].fbcoord[2]) * (cam->clipend - cam->clipsta)); */ + + rv[i].fbcoord[0] -= cam->shiftx * 2; + rv[i].fbcoord[1] -= cam->shifty * 2; + } + } +} + +static void lanpr_transform_render_vert( + BMVert *v, int index, LANPR_RenderVert *RvBuf, real *MvMat, real *MvPMat, Camera *UNUSED(camera)) +{ /* real HeightMultiply, real clipsta, real clipend) { */ + LANPR_RenderVert *rv = &RvBuf[index]; + /* rv->v = v; */ + /* v->Rv = rv; */ + tmat_apply_transform_43df(rv->gloc, MvMat, v->co); + tmat_apply_transform_43dfND(rv->fbcoord, MvPMat, v->co); + + /* if(rv->fbcoord[2]>0)tMatVectorMultiSelf3d(rv->fbcoord, (1 / */ + /* rv->fbcoord[3])); else tMatVectorMultiSelf3d(rv->fbcoord, */ + /* -rv->fbcoord[3]); */ + /* rv->fbcoord[2] = Camera->clipsta* Camera->clipend / (Camera->clipend - */ + /* fabs(rv->fbcoord[2]) * (Camera->clipend - Camera->clipsta)); */ +} + +static void lanpr_make_render_geometry_buffers_object( + Object *o, real *MvMat, real *MvPMat, LANPR_RenderBuffer *rb, int override_usage) +{ + BMesh *bm; + BMVert *v; + BMFace *f; + BMEdge *e; + BMLoop *loop; + LANPR_RenderLine *rl; + LANPR_RenderTriangle *rt; + tnsMatrix44d new_mvp; + tnsMatrix44d new_mv; + tnsMatrix44d self_transform; + tnsMatrix44d Normal; + LANPR_RenderElementLinkNode *reln; + Object *cam_object = rb->scene->camera; + Camera *c = cam_object->data; + LANPR_RenderVert *orv; + LANPR_RenderLine *orl; + LANPR_RenderTriangle *ort; + FreestyleEdge *fe; + int CanFindFreestyle = 0; + int i; + + int usage = override_usage ? override_usage : o->lanpr.usage; + + if (usage == OBJECT_FEATURE_LINE_EXCLUDE) { + return; + } + + if (o->type == OB_MESH) { + + tmat_obmat_to_16d(o->obmat, self_transform); + + tmat_multiply_44d(new_mvp, MvPMat, self_transform); + tmat_multiply_44d(new_mv, MvMat, self_transform); + + invert_m4_m4(o->imat, o->obmat); + transpose_m4(o->imat); + tmat_obmat_to_16d(o->imat, Normal); + + const BMAllocTemplate allocsize = BMALLOC_TEMPLATE_FROM_ME(((Mesh *)(o->data))); + bm = BM_mesh_create(&allocsize, + &((struct BMeshCreateParams){ + .use_toolflags = true, + })); + BM_mesh_bm_from_me(bm, + o->data, + &((struct BMeshFromMeshParams){ + .calc_face_normal = true, + })); + BM_mesh_elem_hflag_disable_all(bm, BM_FACE | BM_EDGE, BM_ELEM_TAG, false); + BM_mesh_triangulate( + bm, MOD_TRIANGULATE_QUAD_BEAUTY, MOD_TRIANGULATE_NGON_BEAUTY, 4, false, NULL, NULL, NULL); + BM_mesh_normals_update(bm); + BM_mesh_elem_table_ensure(bm, BM_VERT | BM_EDGE | BM_FACE); + BM_mesh_elem_index_ensure(bm, BM_VERT | BM_EDGE | BM_FACE); + + if (CustomData_has_layer(&bm->edata, CD_LANPR_EDGE)) { + CanFindFreestyle = 1; + } + + orv = mem_static_aquire(&rb->render_data_pool, sizeof(LANPR_RenderVert) * bm->totvert); + ort = mem_static_aquire(&rb->render_data_pool, bm->totface * rb->triangle_size); + orl = mem_static_aquire(&rb->render_data_pool, sizeof(LANPR_RenderLine) * bm->totedge); + + reln = list_append_pointer_static_sized(&rb->vertex_buffer_pointers, + &rb->render_data_pool, + orv, + sizeof(LANPR_RenderElementLinkNode)); + reln->element_count = bm->totvert; + reln->object_ref = o; + + reln = list_append_pointer_static_sized(&rb->line_buffer_pointers, + &rb->render_data_pool, + orl, + sizeof(LANPR_RenderElementLinkNode)); + reln->element_count = bm->totedge; + reln->object_ref = o; + + reln = list_append_pointer_static_sized(&rb->triangle_buffer_pointers, + &rb->render_data_pool, + ort, + sizeof(LANPR_RenderElementLinkNode)); + reln->element_count = bm->totface; + reln->object_ref = o; + + for (i = 0; i < bm->totvert; i++) { + v = BM_vert_at_index(bm, i); + lanpr_transform_render_vert(v, i, orv, new_mv, new_mvp, c); + } + + rl = orl; + for (i = 0; i < bm->totedge; i++) { + e = BM_edge_at_index(bm, i); + if (CanFindFreestyle) { + fe = CustomData_bmesh_get(&bm->edata, e->head.data, CD_LANPR_EDGE); + if (fe->flag & FREESTYLE_EDGE_MARK) { + rl->flags |= LANPR_EDGE_FLAG_EDGE_MARK; + } + } + if (use_smooth_contour_modifier_contour) { + rl->edge_idx = i; + if (BM_elem_flag_test(e->v1, BM_ELEM_SELECT) && BM_elem_flag_test(e->v2, BM_ELEM_SELECT)) { + rl->flags |= LANPR_EDGE_FLAG_CONTOUR; + } + } + + rl->l = &orv[BM_elem_index_get(e->v1)]; + rl->r = &orv[BM_elem_index_get(e->v2)]; + + rl->object_ref = o; + + LANPR_RenderLineSegment *rls = mem_static_aquire(&rb->render_data_pool, + sizeof(LANPR_RenderLineSegment)); + BLI_addtail(&rl->segments, rls); + if (usage == OBJECT_FEATURE_LINE_INHERENT) { + BLI_addtail(&rb->all_render_lines, rl); + } + rl++; + } + + rt = ort; + for (i = 0; i < bm->totface; i++) { + f = BM_face_at_index(bm, i); + + loop = f->l_first; + rt->v[0] = &orv[BM_elem_index_get(loop->v)]; + rt->rl[0] = &orl[BM_elem_index_get(loop->e)]; + loop = loop->next; + rt->v[1] = &orv[BM_elem_index_get(loop->v)]; + rt->rl[1] = &orl[BM_elem_index_get(loop->e)]; + loop = loop->next; + rt->v[2] = &orv[BM_elem_index_get(loop->v)]; + rt->rl[2] = &orl[BM_elem_index_get(loop->e)]; + + rt->material_id = f->mat_nr; + rt->gn[0] = f->no[0]; + rt->gn[1] = f->no[1]; + rt->gn[2] = f->no[2]; + + tMatVectorAccum3d(rt->gc, rt->v[0]->fbcoord); + tMatVectorAccum3d(rt->gc, rt->v[1]->fbcoord); + tMatVectorAccum3d(rt->gc, rt->v[2]->fbcoord); + tMatVectorMultiSelf3d(rt->gc, 1.0f / 3.0f); + tmat_apply_normal_transform_43df(rt->gn, Normal, f->no); + tmat_normalize_self_3d(rt->gn); + lanpr_assign_render_line_with_triangle(rt); + /* m = tnsGetIndexedMaterial(rb->scene, f->material_id); */ + /* if(m) m->Previewv_count += (f->triangle_count*3); */ + + if (BM_elem_flag_test(f, BM_ELEM_SELECT)) { + rt->material_id = 1; + } + + rt = (LANPR_RenderTriangle *)(((unsigned char *)rt) + rb->triangle_size); + } + + BM_mesh_free(bm); + } +} + +static int lanpr_object_has_feature_line_modifier(Object *o) +{ + ModifierData *md; + for (md = o->modifiers.first; md; md = md->next) { + if (md->type == eModifierType_FeatureLine) { + return 1; + } + } + return 0; +} + +int ED_lanpr_object_collection_usage_check(Collection *c, Object *o) +{ + CollectionChild *cc; + int object_is_used = (lanpr_object_has_feature_line_modifier(o) && + o->lanpr.usage == OBJECT_FEATURE_LINE_INHERENT); + + if (object_is_used && c->lanpr.force && c->lanpr.usage != COLLECTION_FEATURE_LINE_INCLUDE) { + if (BKE_collection_has_object_recursive(c, o)) { + if (c->lanpr.usage == COLLECTION_FEATURE_LINE_EXCLUDE) { + return OBJECT_FEATURE_LINE_EXCLUDE; + } + else if (c->lanpr.usage == COLLECTION_FEATURE_LINE_OCCLUSION_ONLY) { + return OBJECT_FEATURE_LINE_OCCLUSION_ONLY; + } + } + } + + if (!c->children.first) { + if (BKE_collection_has_object(c, o)) { + if (o->lanpr.usage == OBJECT_FEATURE_LINE_INHERENT) { + if (c->lanpr.usage == COLLECTION_FEATURE_LINE_OCCLUSION_ONLY) { + return OBJECT_FEATURE_LINE_OCCLUSION_ONLY; + } + else if (c->lanpr.usage == COLLECTION_FEATURE_LINE_EXCLUDE) { + return OBJECT_FEATURE_LINE_EXCLUDE; + } + else { + return OBJECT_FEATURE_LINE_INHERENT; + } + } + else { + return o->lanpr.usage; + } + } + else { + return OBJECT_FEATURE_LINE_INHERENT; + } + } + + for (cc = c->children.first; cc; cc = cc->next) { + int result = ED_lanpr_object_collection_usage_check(cc->collection, o); + if (result > OBJECT_FEATURE_LINE_INHERENT) { + return result; + } + } + + return OBJECT_FEATURE_LINE_INHERENT; +} + +static void lanpr_make_render_geometry_buffers(Depsgraph *depsgraph, + Scene *s, + Object *c /*camera*/, + LANPR_RenderBuffer *rb) +{ + tnsMatrix44d obmat16; + tnsMatrix44d proj, view, result, inv; + Camera *cam = c->data; + + float sensor = BKE_camera_sensor_size(cam->sensor_fit, cam->sensor_x, cam->sensor_y); + real fov = focallength_to_fov(cam->lens, sensor); + + memset(rb->material_pointers, 0, sizeof(void *) * 2048); + + real asp = ((real)rb->w / (real)rb->h); + + if (cam->type == CAM_PERSP) { + tmat_make_perspective_matrix_44d(proj, fov, asp, cam->clip_start, cam->clip_end); + } + else if (cam->type == CAM_ORTHO) { + real w = cam->ortho_scale / 2; + tmat_make_ortho_matrix_44d(proj, -w, w, -w / asp, w / asp, cam->clip_start, cam->clip_end); + } + + tmat_load_identity_44d(view); + + /* tObjApplyself_transformMatrix(c, 0); */ + /* tObjApplyGlobalTransformMatrixReverted(c); */ + tmat_obmat_to_16d(c->obmat, obmat16); + tmat_inverse_44d(inv, obmat16); + tmat_multiply_44d(result, proj, inv); + memcpy(proj, result, sizeof(tnsMatrix44d)); + memcpy(rb->view_projection, proj, sizeof(tnsMatrix44d)); + + tmat_inverse_44d(rb->vp_inverse, rb->view_projection); + + list_handle_empty(&rb->triangle_buffer_pointers); + list_handle_empty(&rb->vertex_buffer_pointers); + + DEG_OBJECT_ITER_BEGIN (depsgraph, + o, + DEG_ITER_OBJECT_FLAG_LINKED_DIRECTLY | DEG_ITER_OBJECT_FLAG_VISIBLE | + DEG_ITER_OBJECT_FLAG_DUPLI | DEG_ITER_OBJECT_FLAG_LINKED_VIA_SET) { + int usage = ED_lanpr_object_collection_usage_check(s->master_collection, o); + + lanpr_make_render_geometry_buffers_object(o, view, proj, rb, usage); + } + DEG_OBJECT_ITER_END; + + /* for (collection = s->master_collection.first; collection; collection = collection->ID.next) { + */ + /* for (co = collection->gobject.first; co; co = co->next) { */ + /* //tObjApplyGlobalTransformMatrixRecursive(o); */ + /* lanpr_make_render_geometry_buffers_object(o, view, proj, rb); */ + /* } */ + /* } */ +} + +#define INTERSECT_SORT_MIN_TO_MAX_3(ia, ib, ic, lst) \ + { \ + lst[0] = TNS_MIN3_INDEX(ia, ib, ic); \ + lst[1] = (((ia <= ib && ib <= ic) || (ic <= ib && ib <= ia)) ? \ + 1 : \ + (((ic <= ia && ia <= ib) || (ib < ia && ia <= ic)) ? 0 : 2)); \ + lst[2] = TNS_MAX3_INDEX(ia, ib, ic); \ + } + +/* ia ib ic are ordered */ +#define INTERSECT_JUST_GREATER(is, order, num, index) \ + { \ + index = (num < is[order[0]] ? \ + order[0] : \ + (num < is[order[1]] ? order[1] : (num < is[order[2]] ? order[2] : order[2]))); \ + } + +/* ia ib ic are ordered */ +#define INTERSECT_JUST_SMALLER(is, order, num, index) \ + { \ + index = (num > is[order[2]] ? \ + order[2] : \ + (num > is[order[1]] ? order[1] : (num > is[order[0]] ? order[0] : order[0]))); \ + } + +static void lanpr_get_interpolate_point2d(tnsVector2d l, + tnsVector2d r, + real Ratio, + tnsVector2d Result) +{ + Result[0] = tnsLinearItp(l[0], r[0], Ratio); + Result[1] = tnsLinearItp(l[1], r[1], Ratio); +} + +static LANPR_RenderLine *lanpr_another_edge(LANPR_RenderTriangle *rt, LANPR_RenderVert *rv) +{ + if (rt->v[0] == rv) { + return rt->rl[1]; + } + else if (rt->v[1] == rv) { + return rt->rl[2]; + } + else if (rt->v[2] == rv) { + return rt->rl[0]; + } + return 0; +} +static int lanpr_share_edge(LANPR_RenderTriangle *rt, LANPR_RenderVert *rv, LANPR_RenderLine *rl) +{ + LANPR_RenderVert *another = rv == rl->l ? rl->r : rl->l; + + if (rt->v[0] == rv) { + if (another == rt->v[1] || another == rt->v[2]) { + return 1; + } + return 0; + } + else if (rt->v[1] == rv) { + if (another == rt->v[0] || another == rt->v[2]) { + return 1; + } + return 0; + } + else if (rt->v[2] == rv) { + if (another == rt->v[0] || another == rt->v[1]) { + return 1; + } + return 0; + } + return 0; +} +static int lanpr_share_edge_direct(LANPR_RenderTriangle *rt, LANPR_RenderLine *rl) +{ + if (rt->rl[0] == rl || rt->rl[1] == rl || rt->rl[2] == rl) { + return 1; + } + return 0; +} + +static int lanpr_triangle_line_imagespace_intersection_v2(SpinLock *UNUSED(spl), + LANPR_RenderTriangle *rt, + LANPR_RenderLine *rl, + Object *cam, + tnsMatrix44d vp, + real *CameraDir, + double *From, + double *To) +{ + double is[3] = {0}; + int order[3]; + int LCross = -1, RCross = -1; + int a, b, c; + int StL = 0, StR = 0, In; + + tnsVector3d Lv; + tnsVector3d Rv; + tnsVector4d vd4; + real Cv[3]; + real DotL, DotR, DotLA, DotRA; + real DotF; + tnsVector4d gloc, Trans; + real Cut = -1; + + double *LFBC = rl->l->fbcoord, *RFBC = rl->r->fbcoord, *FBC0 = rt->v[0]->fbcoord, + *FBC1 = rt->v[1]->fbcoord, *FBC2 = rt->v[2]->fbcoord; + + /* printf("(%f %f)(%f %f)(%f %f) (%f %f)(%f %f)\n", FBC0[0], FBC0[1], FBC1[0], FBC1[1], */ + /* FBC2[0], FBC2[1], LFBC[0], LFBC[1], RFBC[0], RFBC[1]); */ + + /* bound box. */ + /* if (MIN3(FBC0[2], FBC1[2], FBC2[2]) > MAX2(LFBC[2], RFBC[2])) */ + /* return 0; */ + if ((MAX3(FBC0[0], FBC1[0], FBC2[0]) < MIN2(LFBC[0], RFBC[0])) || + (MIN3(FBC0[0], FBC1[0], FBC2[0]) > MAX2(LFBC[0], RFBC[0])) || + (MAX3(FBC0[1], FBC1[1], FBC2[1]) < MIN2(LFBC[1], RFBC[1])) || + (MIN3(FBC0[1], FBC1[1], FBC2[1]) > MAX2(LFBC[1], RFBC[1]))) { + return 0; + } + + if (lanpr_share_edge_direct(rt, rl)) { + return 0; + } + + a = lanpr_LineIntersectTest2d(LFBC, RFBC, FBC0, FBC1, &is[0]); + b = lanpr_LineIntersectTest2d(LFBC, RFBC, FBC1, FBC2, &is[1]); + c = lanpr_LineIntersectTest2d(LFBC, RFBC, FBC2, FBC0, &is[2]); + + /* printf("abc: %d %d %d\n", a,b,c); */ + + INTERSECT_SORT_MIN_TO_MAX_3(is[0], is[1], is[2], order); + + tMatVectorMinus3d(Lv, rl->l->gloc, rt->v[0]->gloc); + tMatVectorMinus3d(Rv, rl->r->gloc, rt->v[0]->gloc); + + tMatVectorCopy3d(CameraDir, Cv); + + tMatVectorConvert4fd(cam->obmat[3], vd4); + if (((Camera *)cam->data)->type == CAM_PERSP) { + tMatVectorMinus3d(Cv, vd4, rt->v[0]->gloc); + } + + DotL = tmat_dot_3d(Lv, rt->gn, 0); + DotR = tmat_dot_3d(Rv, rt->gn, 0); + DotF = tmat_dot_3d(Cv, rt->gn, 0); + + if (!DotF) { + return 0; + } + + if (!a && !b && !c) { + if (!(StL = lanpr_point_triangle_relation(LFBC, FBC0, FBC1, FBC2)) && + !(StR = lanpr_point_triangle_relation(RFBC, FBC0, FBC1, FBC2))) { + return 0; /* not occluding */ + } + } + + StL = lanpr_point_triangle_relation(LFBC, FBC0, FBC1, FBC2); + StR = lanpr_point_triangle_relation(RFBC, FBC0, FBC1, FBC2); + + /* for (rv = rt->intersecting_verts.first; rv; rv = rv->next) { */ + /* if (rv->intersecting_with == rt && rv->intersecting_line == rl) { */ + /* Cut = tMatGetLinearRatio(rl->l->fbcoord[0], rl->r->fbcoord[0], */ + /* rv->fbcoord[0]); break; */ + /* } */ + /* } */ + + DotLA = fabs(DotL); + if (DotLA < DBL_EPSILON) { + DotLA = 0; + DotL = 0; + } + DotRA = fabs(DotR); + if (DotRA < DBL_EPSILON) { + DotRA = 0; + DotR = 0; + } + if (DotL - DotR == 0) { + Cut = 100000; + } + else if (DotL * DotR <= 0) { + Cut = DotLA / fabs(DotL - DotR); + } + else { + Cut = fabs(DotR + DotL) / fabs(DotL - DotR); + Cut = DotRA > DotLA ? 1 - Cut : Cut; + } + + if (((Camera *)cam->data)->type == CAM_PERSP) { + interp_v3_v3v3_db(gloc, rl->l->gloc, rl->r->gloc, Cut); + tmat_apply_transform_44d(Trans, vp, gloc); + tMatVectorMultiSelf3d(Trans, (1 / Trans[3]) /**HeightMultiply/2*/); + Camera *camera = cam->data; + Trans[0] -= camera->shiftx * 2; + Trans[1] -= camera->shifty * 2; + } + else { + interp_v3_v3v3_db(Trans, rl->l->fbcoord, rl->r->fbcoord, Cut); + /* tmat_apply_transform_44d(Trans, vp, gloc); */ + } + + /* Trans[2] = tmat_dist_3dv(gloc, cam->Base.gloc); */ + /* Trans[2] = cam->clipsta*cam->clipend / (cam->clipend - fabs(Trans[2]) * (cam->clipend - */ + /* cam->clipsta)); */ + + /* prevent vertical problem ? */ + if (rl->l->fbcoord[0] != rl->r->fbcoord[0]) { + Cut = tMatGetLinearRatio(rl->l->fbcoord[0], rl->r->fbcoord[0], Trans[0]); + } + else { + Cut = tMatGetLinearRatio(rl->l->fbcoord[1], rl->r->fbcoord[1], Trans[1]); + } + + In = ED_lanpr_point_inside_triangled( + Trans, rt->v[0]->fbcoord, rt->v[1]->fbcoord, rt->v[2]->fbcoord); + + if (StL == 2) { + if (StR == 2) { + INTERSECT_JUST_SMALLER(is, order, DBL_TRIANGLE_LIM, LCross); + INTERSECT_JUST_GREATER(is, order, 1 - DBL_TRIANGLE_LIM, RCross); + } + else if (StR == 1) { + INTERSECT_JUST_SMALLER(is, order, DBL_TRIANGLE_LIM, LCross); + INTERSECT_JUST_GREATER(is, order, 1 - DBL_TRIANGLE_LIM, RCross); + } + else if (StR == 0) { + INTERSECT_JUST_SMALLER(is, order, DBL_TRIANGLE_LIM, LCross); + INTERSECT_JUST_GREATER(is, order, 0, RCross); + } + } + else if (StL == 1) { + if (StR == 2) { + INTERSECT_JUST_SMALLER(is, order, DBL_TRIANGLE_LIM, LCross); + INTERSECT_JUST_GREATER(is, order, 1 - DBL_TRIANGLE_LIM, RCross); + } + else if (StR == 1) { + INTERSECT_JUST_SMALLER(is, order, DBL_TRIANGLE_LIM, LCross); + INTERSECT_JUST_GREATER(is, order, 1 - DBL_TRIANGLE_LIM, RCross); + } + else if (StR == 0) { + INTERSECT_JUST_GREATER(is, order, DBL_TRIANGLE_LIM, RCross); + if (TNS_ABC(RCross) && is[RCross] > (DBL_TRIANGLE_LIM)) { + INTERSECT_JUST_SMALLER(is, order, DBL_TRIANGLE_LIM, LCross); + } + else { + INTERSECT_JUST_SMALLER(is, order, -DBL_TRIANGLE_LIM, LCross); + INTERSECT_JUST_GREATER(is, order, -DBL_TRIANGLE_LIM, RCross); + } + } + } + else if (StL == 0) { + if (StR == 2) { + INTERSECT_JUST_SMALLER(is, order, 1 - DBL_TRIANGLE_LIM, LCross); + INTERSECT_JUST_GREATER(is, order, 1 - DBL_TRIANGLE_LIM, RCross); + } + else if (StR == 1) { + INTERSECT_JUST_SMALLER(is, order, 1 - DBL_TRIANGLE_LIM, LCross); + if (TNS_ABC(LCross) && is[LCross] < (1 - DBL_TRIANGLE_LIM)) { + INTERSECT_JUST_GREATER(is, order, 1 - DBL_TRIANGLE_LIM, RCross); + } + else { + INTERSECT_JUST_SMALLER(is, order, 1 + DBL_TRIANGLE_LIM, LCross); + INTERSECT_JUST_GREATER(is, order, 1 + DBL_TRIANGLE_LIM, RCross); + } + } + else if (StR == 0) { + INTERSECT_JUST_GREATER(is, order, 0, LCross); + if (TNS_ABC(LCross) && is[LCross] > 0) { + INTERSECT_JUST_GREATER(is, order, is[LCross], RCross); + } + else { + INTERSECT_JUST_GREATER(is, order, is[LCross], LCross); + INTERSECT_JUST_GREATER(is, order, is[LCross], RCross); + } + } + } + + real LF = DotL * DotF, RF = DotR * DotF; + /* int CrossCount = a + b + c; */ + /* if (CrossCount == 2) { */ + /* INTERSECT_JUST_GREATER(is, order, 0, LCross); */ + /* if (!TNS_ABC(LCross)) INTERSECT_JUST_GREATER(is, order, is[LCross], LCross); */ + /* INTERSECT_JUST_GREATER(is, order, is[LCross], RCross); */ + /* }else if(CrossCount == 1 || StL+StR==1) { */ + /* if (StL) { */ + /* INTERSECT_JUST_GREATER(is, order, DBL_TRIANGLE_LIM, RCross); */ + /* INTERSECT_JUST_SMALLER(is, order, is[RCross], LCross); */ + /* }else if(StR) { */ + /* INTERSECT_JUST_SMALLER(is, order, 1 - DBL_TRIANGLE_LIM, LCross); */ + /* INTERSECT_JUST_GREATER(is, order, is[LCross], RCross); */ + /* } */ + /* }else if(CrossCount == 0) { */ + /* INTERSECT_JUST_SMALLER(is, order, 0, LCross); */ + /* INTERSECT_JUST_GREATER(is, order, 1, RCross); */ + /* } */ + + if (LF <= 0 && RF <= 0 && (DotL || DotR)) { + + *From = MAX2(0, is[LCross]); + *To = MIN2(1, is[RCross]); + if (*From >= *To) { + return 0; + } + /* printf("1 From %f to %f\n",*From, *To); */ + return 1; + } + else if (LF >= 0 && RF <= 0 && (DotL || DotR)) { + *From = MAX2(Cut, is[LCross]); + *To = MIN2(1, is[RCross]); + if (*From >= *To) { + return 0; + } + /* printf("2 From %f to %f\n",*From, *To); */ + return 1; + } + else if (LF <= 0 && RF >= 0 && (DotL || DotR)) { + *From = MAX2(0, is[LCross]); + *To = MIN2(Cut, is[RCross]); + if (*From >= *To) { + return 0; + } + /* printf("3 From %f to %f\n",*From, *To); */ + return 1; + } + else + return 0; + return 1; +} + +static LANPR_RenderLine *lanpr_triangle_share_edge(LANPR_RenderTriangle *l, + LANPR_RenderTriangle *r) +{ + if (l->rl[0] == r->rl[0]) { + return r->rl[0]; + } + if (l->rl[0] == r->rl[1]) { + return r->rl[1]; + } + if (l->rl[0] == r->rl[2]) { + return r->rl[2]; + } + if (l->rl[1] == r->rl[0]) { + return r->rl[0]; + } + if (l->rl[1] == r->rl[1]) { + return r->rl[1]; + } + if (l->rl[1] == r->rl[2]) { + return r->rl[2]; + } + if (l->rl[2] == r->rl[0]) { + return r->rl[0]; + } + if (l->rl[2] == r->rl[1]) { + return r->rl[1]; + } + if (l->rl[2] == r->rl[2]) { + return r->rl[2]; + } + return 0; +} +static LANPR_RenderVert *lanpr_triangle_share_point(LANPR_RenderTriangle *l, + LANPR_RenderTriangle *r) +{ + if (l->v[0] == r->v[0]) { + return r->v[0]; + } + if (l->v[0] == r->v[1]) { + return r->v[1]; + } + if (l->v[0] == r->v[2]) { + return r->v[2]; + } + if (l->v[1] == r->v[0]) { + return r->v[0]; + } + if (l->v[1] == r->v[1]) { + return r->v[1]; + } + if (l->v[1] == r->v[2]) { + return r->v[2]; + } + if (l->v[2] == r->v[0]) { + return r->v[0]; + } + if (l->v[2] == r->v[1]) { + return r->v[1]; + } + if (l->v[2] == r->v[2]) { + return r->v[2]; + } + return 0; +} + +static LANPR_RenderVert *lanpr_triangle_line_intersection_test(LANPR_RenderBuffer *rb, + LANPR_RenderLine *rl, + LANPR_RenderTriangle *rt, + LANPR_RenderTriangle *testing, + LANPR_RenderVert *Last) +{ + tnsVector3d Lv; + tnsVector3d Rv; + real DotL, DotR; + LANPR_RenderVert *Result, *rv; + tnsVector3d gloc; + LANPR_RenderVert *l = rl->l, *r = rl->r; + int result; + + for (rv = testing->intersecting_verts.first; rv; rv = rv->next) { + if (rv->intersecting_with == rt && rv->intersecting_line == rl) { + return rv; + } + } + + tMatVectorMinus3d(Lv, l->gloc, testing->v[0]->gloc); + tMatVectorMinus3d(Rv, r->gloc, testing->v[0]->gloc); + + DotL = tmat_dot_3d(Lv, testing->gn, 0); + DotR = tmat_dot_3d(Rv, testing->gn, 0); + + if (DotL * DotR > 0 || (!DotL && !DotR)) { + return 0; + } + + DotL = fabs(DotL); + DotR = fabs(DotR); + + interp_v3_v3v3_db(gloc, l->gloc, r->gloc, DotL / (DotL + DotR)); + + if (Last && TNS_DOUBLE_CLOSE_ENOUGH(Last->gloc[0], gloc[0]) && + TNS_DOUBLE_CLOSE_ENOUGH(Last->gloc[1], gloc[1]) && + TNS_DOUBLE_CLOSE_ENOUGH(Last->gloc[2], gloc[2])) { + + Last->intersecting_line2 = rl; + return 0; + } + + if (!(result = lanpr_point_inside_triangle3de( + gloc, testing->v[0]->gloc, testing->v[1]->gloc, testing->v[2]->gloc))) { + return 0; + } + /*else if(result < 0) { + return 0; + }*/ + + Result = mem_static_aquire(&rb->render_data_pool, sizeof(LANPR_RenderVert)); + + if (DotL > 0 || DotR < 0) { + Result->positive = 1; + } + else { + Result->positive = 0; + } + + /* Result->IntersectingOnFace = testing; */ + Result->edge_used = 1; + /* Result->IntersectL = l; */ + Result->v = (void *)r; /* Caution! */ + /* Result->intersecting_with = rt; */ + tMatVectorCopy3d(gloc, Result->gloc); + + BLI_addtail(&testing->intersecting_verts, Result); + + return Result; +} +static LANPR_RenderLine *lanpr_triangle_generate_intersection_line_only( + LANPR_RenderBuffer *rb, LANPR_RenderTriangle *rt, LANPR_RenderTriangle *testing) +{ + LANPR_RenderVert *l = 0, *r = 0; + LANPR_RenderVert **Next = &l; + LANPR_RenderLine *Result; + LANPR_RenderVert *E0T = 0; + LANPR_RenderVert *E1T = 0; + LANPR_RenderVert *E2T = 0; + LANPR_RenderVert *TE0 = 0; + LANPR_RenderVert *TE1 = 0; + LANPR_RenderVert *TE2 = 0; + tnsVector3d cl; /* rb->scene->ActiveCamera->gloc; */ + real ZMax = ((Camera *)rb->scene->camera->data)->clip_end; + real ZMin = ((Camera *)rb->scene->camera->data)->clip_start; + LANPR_RenderVert *Share = lanpr_triangle_share_point(testing, rt); + Camera *cam = rb->scene->camera->data; + + tMatVectorConvert3fd(rb->scene->camera->obmat[3], cl); + + if (Share) { + LANPR_RenderVert *NewShare; + LANPR_RenderLine *rl = lanpr_another_edge(rt, Share); + + l = NewShare = mem_static_aquire(&rb->render_data_pool, (sizeof(LANPR_RenderVert))); + + NewShare->positive = 1; + NewShare->edge_used = 1; + /* NewShare->IntersectL = l; */ + NewShare->v = (void *)r; /* Caution! */ + /* Result->intersecting_with = rt; */ + tMatVectorCopy3d(Share->gloc, NewShare->gloc); + + r = lanpr_triangle_line_intersection_test(rb, rl, rt, testing, 0); + + if (!r) { + rl = lanpr_another_edge(testing, Share); + r = lanpr_triangle_line_intersection_test(rb, rl, testing, rt, 0); + if (!r) { + return 0; + } + BLI_addtail(&testing->intersecting_verts, NewShare); + } + else { + BLI_addtail(&rt->intersecting_verts, NewShare); + } + } + else { + if (!rt->rl[0] || !rt->rl[1] || !rt->rl[2]) { + return 0; /* shouldn't need this, there must be problems in culling. */ + } + E0T = lanpr_triangle_line_intersection_test(rb, rt->rl[0], rt, testing, 0); + if (E0T && (!(*Next))) { + (*Next) = E0T; + (*Next)->intersecting_line = rt->rl[0]; + Next = &r; + } + E1T = lanpr_triangle_line_intersection_test(rb, rt->rl[1], rt, testing, l); + if (E1T && (!(*Next))) { + (*Next) = E1T; + (*Next)->intersecting_line = rt->rl[1]; + Next = &r; + } + if (!(*Next)) { + E2T = lanpr_triangle_line_intersection_test(rb, rt->rl[2], rt, testing, l); + } + if (E2T && (!(*Next))) { + (*Next) = E2T; + (*Next)->intersecting_line = rt->rl[2]; + Next = &r; + } + + if (!(*Next)) { + TE0 = lanpr_triangle_line_intersection_test(rb, testing->rl[0], testing, rt, l); + } + if (TE0 && (!(*Next))) { + (*Next) = TE0; + (*Next)->intersecting_line = testing->rl[0]; + Next = &r; + } + if (!(*Next)) { + TE1 = lanpr_triangle_line_intersection_test(rb, testing->rl[1], testing, rt, l); + } + if (TE1 && (!(*Next))) { + (*Next) = TE1; + (*Next)->intersecting_line = testing->rl[1]; + Next = &r; + } + if (!(*Next)) { + TE2 = lanpr_triangle_line_intersection_test(rb, testing->rl[2], testing, rt, l); + } + if (TE2 && (!(*Next))) { + (*Next) = TE2; + (*Next)->intersecting_line = testing->rl[2]; + Next = &r; + } + + if (!(*Next)) { + return 0; + } + } + tmat_apply_transform_44d(l->fbcoord, rb->view_projection, l->gloc); + tmat_apply_transform_44d(r->fbcoord, rb->view_projection, r->gloc); + tMatVectorMultiSelf3d(l->fbcoord, (1 / l->fbcoord[3]) /**HeightMultiply/2*/); + tMatVectorMultiSelf3d(r->fbcoord, (1 / r->fbcoord[3]) /**HeightMultiply/2*/); + + l->fbcoord[0] -= cam->shiftx * 2; + l->fbcoord[1] -= cam->shifty * 2; + r->fbcoord[0] -= cam->shiftx * 2; + r->fbcoord[1] -= cam->shifty * 2; + + l->fbcoord[2] = ZMin * ZMax / (ZMax - fabs(l->fbcoord[2]) * (ZMax - ZMin)); + r->fbcoord[2] = ZMin * ZMax / (ZMax - fabs(r->fbcoord[2]) * (ZMax - ZMin)); + + l->intersecting_with = rt; + r->intersecting_with = testing; + + /* /*((1 / rl->l->fbcoord[3])*rb->FrameBuffer->H / 2) */ + + Result = mem_static_aquire(&rb->render_data_pool, sizeof(LANPR_RenderLine)); + Result->l = l; + Result->r = r; + Result->tl = rt; + Result->tr = testing; + LANPR_RenderLineSegment *rls = mem_static_aquire(&rb->render_data_pool, + sizeof(LANPR_RenderLineSegment)); + BLI_addtail(&Result->segments, rls); + BLI_addtail(&rb->all_render_lines, Result); + Result->flags |= LANPR_EDGE_FLAG_INTERSECTION; + list_append_pointer_static(&rb->intersection_lines, &rb->render_data_pool, Result); + int r1, r2, c1, c2, row, col; + if (lanpr_get_line_bounding_areas(rb, Result, &r1, &r2, &c1, &c2)) { + for (row = r1; row != r2 + 1; row++) { + for (col = c1; col != c2 + 1; col++) { + lanpr_link_line_with_bounding_area(rb, &rb->initial_bounding_areas[row * 4 + col], Result); + } + } + } + + rb->intersection_count++; + + return Result; +} +static void lanpr_triangle_calculate_intersections_in_bounding_area(LANPR_RenderBuffer *rb, + LANPR_RenderTriangle *rt, + LANPR_BoundingArea *ba) +{ + LANPR_RenderTriangle *TestingTriangle; + LinkData *lip, *next_lip; + + real *FBC0 = rt->v[0]->fbcoord, *FBC1 = rt->v[1]->fbcoord, *FBC2 = rt->v[2]->fbcoord; + + if (ba->child) { + lanpr_triangle_calculate_intersections_in_bounding_area(rb, rt, &ba->child[0]); + lanpr_triangle_calculate_intersections_in_bounding_area(rb, rt, &ba->child[1]); + lanpr_triangle_calculate_intersections_in_bounding_area(rb, rt, &ba->child[2]); + lanpr_triangle_calculate_intersections_in_bounding_area(rb, rt, &ba->child[3]); + return; + } + + for (lip = ba->linked_triangles.first; lip; lip = next_lip) { + next_lip = lip->next; + TestingTriangle = lip->data; + if (TestingTriangle == rt || TestingTriangle->testing == rt || + lanpr_triangle_share_edge(rt, TestingTriangle)) { + + continue; + } + + TestingTriangle->testing = rt; + real *RFBC0 = TestingTriangle->v[0]->fbcoord, *RFBC1 = TestingTriangle->v[1]->fbcoord, + *RFBC2 = TestingTriangle->v[2]->fbcoord; + + if ((MIN3(FBC0[2], FBC1[2], FBC2[2]) > MAX3(RFBC0[2], RFBC1[2], RFBC2[2])) || + (MAX3(FBC0[2], FBC1[2], FBC2[2]) < MIN3(RFBC0[2], RFBC1[2], RFBC2[2])) || + (MIN3(FBC0[0], FBC1[0], FBC2[0]) > MAX3(RFBC0[0], RFBC1[0], RFBC2[0])) || + (MAX3(FBC0[0], FBC1[0], FBC2[0]) < MIN3(RFBC0[0], RFBC1[0], RFBC2[0])) || + (MIN3(FBC0[1], FBC1[1], FBC2[1]) > MAX3(RFBC0[1], RFBC1[1], RFBC2[1])) || + (MAX3(FBC0[1], FBC1[1], FBC2[1]) < MIN3(RFBC0[1], RFBC1[1], RFBC2[1]))) { + continue; + } + + lanpr_triangle_generate_intersection_line_only(rb, rt, TestingTriangle); + } +} + +static int lanpr_line_crosses_frame(tnsVector2d l, tnsVector2d r) +{ + real vx, vy; + real c1, c; + + if ((-1 > MAX2(l[0], r[0])) || (1 < MIN2(l[0], r[0])) || (-1 > MAX2(l[1], r[1])) || + (1 < MIN2(l[1], r[1]))) { + return 0; + } + + vx = l[0] - r[0]; + vy = l[1] - r[1]; + + c1 = vx * (-1 - l[1]) - vy * (-1 - l[0]); + c = c1; + + c1 = vx * (-1 - l[1]) - vy * (1 - l[0]); + if (c1 * c <= 0) { + return 1; + } + else { + c = c1; + } + + c1 = vx * (1 - l[1]) - vy * (-1 - l[0]); + if (c1 * c <= 0) { + return 1; + } + else { + c = c1; + } + + c1 = vx * (1 - l[1]) - vy * (1 - l[0]); + if (c1 * c <= 0) { + return 1; + } + else { + c = c1; + } + + return 0; +} + +static void lanpr_compute_view_Vector(LANPR_RenderBuffer *rb) +{ + tnsVector3d Direction = {0, 0, 1}; + tnsVector3d Trans; + tnsMatrix44d inv; + tnsMatrix44d obmat; + + tmat_obmat_to_16d(rb->scene->camera->obmat, obmat); + tmat_inverse_44d(inv, obmat); + tmat_apply_rotation_43d(Trans, inv, Direction); + tMatVectorCopy3d(Trans, rb->view_vector); + /* tMatVectorMultiSelf3d(Trans, -1); */ + /* tMatVectorCopy3d(Trans, ((Camera*)rb->scene->camera)->RenderviewDir); */ +} + +static void lanpr_compute_scene_contours(LANPR_RenderBuffer *rb, float threshold) +{ + real *view_vector = rb->view_vector; + real Dot1 = 0, Dot2 = 0; + real Result; + tnsVector3d cam_location; + int Add = 0; + Object *cam_obj = rb->scene->camera; + Camera *c = cam_obj->data; + LANPR_RenderLine *rl; + int contour_count = 0; + int crease_count = 0; + int MaterialCount = 0; + + if (c->type == CAM_ORTHO) { + lanpr_compute_view_Vector(rb); + } + + for (rl = rb->all_render_lines.first; rl; rl = rl->next) { + /* if(rl->testing) */ + /* if (!lanpr_line_crosses_frame(rl->l->fbcoord, rl->r->fbcoord)) */ + /* continue; */ + + Add = 0; + Dot1 = 0; + Dot2 = 0; + + if (c->type == CAM_PERSP) { + tMatVectorConvert3fd(cam_obj->obmat[3], cam_location); + tMatVectorMinus3d(view_vector, rl->l->gloc, cam_location); + } + + if (use_smooth_contour_modifier_contour) { + if (rl->flags & LANPR_EDGE_FLAG_CONTOUR) { + Add = 1; + } + } + else { + if (rl->tl) { + Dot1 = tmat_dot_3d(view_vector, rl->tl->gn, 0); + } + else { + Add = 1; + } + if (rl->tr) { + Dot2 = tmat_dot_3d(view_vector, rl->tr->gn, 0); + } + else { + Add = 1; + } + } + + if (!Add) { + if ((Result = Dot1 * Dot2) <= 0 && (Dot1 + Dot2)) { + Add = 1; + } + else if (tmat_dot_3d(rl->tl->gn, rl->tr->gn, 0) < threshold) { + Add = 2; + } + else if (rl->tl && rl->tr && rl->tl->material_id != rl->tr->material_id) { + Add = 3; + } + } + + if (Add == 1) { + rl->flags |= LANPR_EDGE_FLAG_CONTOUR; + list_append_pointer_static(&rb->contours, &rb->render_data_pool, rl); + contour_count++; + } + else if (Add == 2) { + rl->flags |= LANPR_EDGE_FLAG_CREASE; + list_append_pointer_static(&rb->crease_lines, &rb->render_data_pool, rl); + crease_count++; + } + else if (Add == 3) { + rl->flags |= LANPR_EDGE_FLAG_MATERIAL; + list_append_pointer_static(&rb->material_lines, &rb->render_data_pool, rl); + MaterialCount++; + } + if (rl->flags & LANPR_EDGE_FLAG_EDGE_MARK) { + /* no need to mark again */ + Add = 4; + list_append_pointer_static(&rb->edge_marks, &rb->render_data_pool, rl); + /* continue; */ + } + if (Add) { + int r1, r2, c1, c2, row, col; + if (lanpr_get_line_bounding_areas(rb, rl, &r1, &r2, &c1, &c2)) { + for (row = r1; row != r2 + 1; row++) { + for (col = c1; col != c2 + 1; col++) { + lanpr_link_line_with_bounding_area(rb, &rb->initial_bounding_areas[row * 4 + col], rl); + } + } + } + } + + /* line count reserved for feature such as progress feedback */ + } +} + +static void lanpr_clear_render_state(LANPR_RenderBuffer *rb) +{ + rb->contour_count = 0; + rb->contour_managed = 0; + rb->intersection_count = 0; + rb->intersection_managed = 0; + rb->material_line_count = 0; + rb->material_managed = 0; + rb->crease_count = 0; + rb->crease_managed = 0; +} + +/* Buffer operations */ + +void ED_lanpr_destroy_render_data(LANPR_RenderBuffer *rb) +{ + if (!rb) { + return; + } + + rb->contour_count = 0; + rb->contour_managed = 0; + rb->intersection_count = 0; + rb->intersection_managed = 0; + rb->material_line_count = 0; + rb->material_managed = 0; + rb->crease_count = 0; + rb->crease_managed = 0; + rb->edge_mark_count = 0; + rb->edge_mark_managed = 0; + + list_handle_empty(&rb->contours); + list_handle_empty(&rb->intersection_lines); + list_handle_empty(&rb->crease_lines); + list_handle_empty(&rb->material_lines); + list_handle_empty(&rb->edge_marks); + list_handle_empty(&rb->all_render_lines); + list_handle_empty(&rb->chains); + + list_handle_empty(&rb->vertex_buffer_pointers); + list_handle_empty(&rb->line_buffer_pointers); + list_handle_empty(&rb->triangle_buffer_pointers); + + BLI_spin_end(&rb->cs_data); + BLI_spin_end(&rb->cs_info); + BLI_spin_end(&rb->cs_management); + BLI_spin_end(&rb->render_data_pool.cs_mem); + + mem_static_destroy(&rb->render_data_pool); +} +LANPR_RenderBuffer *ED_lanpr_create_render_buffer() +{ + if (lanpr_share.render_buffer_shared) { + ED_lanpr_destroy_render_data(lanpr_share.render_buffer_shared); + return lanpr_share.render_buffer_shared; + } + + LANPR_RenderBuffer *rb = MEM_callocN(sizeof(LANPR_RenderBuffer), "LANPR render buffer"); + + lanpr_share.render_buffer_shared = rb; + + rb->cached_for_frame = -1; + + BLI_spin_init(&rb->cs_data); + BLI_spin_init(&rb->cs_info); + BLI_spin_init(&rb->cs_management); + BLI_spin_init(&rb->render_data_pool.cs_mem); + + return rb; +} + +static int lanpr_max_occlusion_in_collections(Collection *c) +{ + CollectionChild *cc; + int max_occ = 0; + int max; + if (c->lanpr.use_multiple_levels) { + max = MAX2(c->lanpr.level_begin, c->lanpr.level_end); + } + else { + max = c->lanpr.level_begin; + } + max_occ = MAX2(max, max_occ); + + for (cc = c->children.first; cc; cc = cc->next) { + max = lanpr_max_occlusion_in_collections(cc->collection); + max_occ = MAX2(max, max_occ); + } + + return max_occ; +} +static int lanpr_max_occlusion_in_targets(Depsgraph *depsgraph) +{ + int max_occ = 0; + int max; + Scene *s = DEG_get_evaluated_scene(depsgraph); + + /* Objects */ + DEG_OBJECT_ITER_BEGIN (depsgraph, + o, + DEG_ITER_OBJECT_FLAG_LINKED_DIRECTLY | DEG_ITER_OBJECT_FLAG_VISIBLE | + DEG_ITER_OBJECT_FLAG_DUPLI | DEG_ITER_OBJECT_FLAG_LINKED_VIA_SET) { + ModifierData *md; + for (md = o->modifiers.first; md; md = md->next) { + if (md->type == eModifierType_FeatureLine) { + FeatureLineModifierData *flmd = (FeatureLineModifierData *)md; + if (flmd->target) { + if (flmd->use_multiple_levels) { + max = MAX2(flmd->level_begin, flmd->level_end); + } + else { + max = flmd->level_begin; + } + max_occ = MAX2(max, max_occ); + } + } + } + } + DEG_OBJECT_ITER_END; + + /* Collections */ + max = lanpr_max_occlusion_in_collections(s->master_collection); + + max_occ = MAX2(max, max_occ); + + return max_occ; +} +static int lanpr_get_max_occlusion_level(Depsgraph *dg) +{ + Scene *s = DEG_get_evaluated_scene(dg); + SceneLANPR *lanpr = &s->lanpr; + if (!strcmp(s->r.engine, RE_engine_id_BLENDER_LANPR)) { + /* Use the line layers in scene LANPR settings */ + return ED_lanpr_max_occlusion_in_line_layers(lanpr); + } + else { + /* Other engines, use GPencil configurations */ + return lanpr_max_occlusion_in_targets(dg); + } +} + +void lanpr_rebuild_render_draw_command(LANPR_RenderBuffer *rb, LANPR_LineLayer *ll); + +static int lanpr_get_render_triangle_size(LANPR_RenderBuffer *rb) +{ + if (rb->thread_count == 0) { + rb->thread_count = BKE_render_num_threads(&rb->scene->r); + } + return sizeof(LANPR_RenderTriangle) + (sizeof(LANPR_RenderLine *) * rb->thread_count); +} + +int lanpr_count_this_line(LANPR_RenderLine *rl, LANPR_LineLayer *ll) +{ + LANPR_LineLayerComponent *llc = ll->components.first; + int AndResult = 1, OrResult = 0; + if (!llc) { + return 1; + } + for (; llc; llc = llc->next) { + if (llc->component_mode == LANPR_COMPONENT_MODE_ALL) { + OrResult = 1; + } + else if (llc->component_mode == LANPR_COMPONENT_MODE_OBJECT && llc->object_select) { + if (rl->object_ref && rl->object_ref->id.orig_id == &llc->object_select->id) { + OrResult = 1; + } + else { + AndResult = 0; + } + } + else if (llc->component_mode == LANPR_COMPONENT_MODE_MATERIAL && llc->material_select) { + if ((rl->tl && rl->tl->material_id == llc->material_select->index) || + (rl->tr && rl->tr->material_id == llc->material_select->index) || + (!(rl->flags & LANPR_EDGE_FLAG_INTERSECTION))) { + OrResult = 1; + } + else { + AndResult = 0; + } + } + else if (llc->component_mode == LANPR_COMPONENT_MODE_COLLECTION && llc->collection_select) { + if (BKE_collection_has_object(llc->collection_select, + (Object *)rl->object_ref->id.orig_id)) { + OrResult = 1; + } + else { + AndResult = 0; + } + } + } + if (ll->logic_mode == LANPR_COMPONENT_LOGIG_OR) { + return OrResult; + } + else { + return AndResult; + } +} +long lanpr_count_leveled_edge_segment_count(ListBase *LineList, LANPR_LineLayer *ll) +{ + LinkData *lip; + LANPR_RenderLine *rl; + LANPR_RenderLineSegment *rls; + long Count = 0; + for (lip = LineList->first; lip; lip = lip->next) { + rl = lip->data; + if (!lanpr_count_this_line(rl, ll)) { + continue; + } + + for (rls = rl->segments.first; rls; rls = rls->next) { + + if (!ll->use_multiple_levels) { + if (rls->occlusion == ll->qi_begin) { + Count++; + } + } + else { + if (rls->occlusion >= ll->qi_begin && rls->occlusion <= ll->qi_end) { + Count++; + } + } + } + } + return Count; +} +long lanpr_count_intersection_segment_count(LANPR_RenderBuffer *rb) +{ + LANPR_RenderLine *rl; + LANPR_RenderLineSegment *rls; + long Count = 0; + for (rl = rb->intersection_lines.first; rl; rl = rl->next) { + Count++; + } + return Count; +} +void *lanpr_make_leveled_edge_vertex_array(LANPR_RenderBuffer *rb, + ListBase *LineList, + float *vertexArray, + float *NormalArray, + float **NextNormal, + LANPR_LineLayer *ll, + float componet_id) +{ + LinkData *lip; + LANPR_RenderLine *rl; + LANPR_RenderLineSegment *rls, *irls; + Object *o; + real W = rb->w / 2, H = rb->h / 2; + long i = 0; + float *v = vertexArray; + float *N = NormalArray; + for (lip = LineList->first; lip; lip = lip->next) { + rl = lip->data; + if (!lanpr_count_this_line(rl, ll)) { + continue; + } + + for (rls = rl->segments.first; rls; rls = rls->next) { + int use = 0; + if (!ll->use_multiple_levels) { + if (rls->occlusion == ll->qi_begin) { + use = 1; + } + } + else { + if (rls->occlusion >= ll->qi_begin && rls->occlusion <= ll->qi_end) { + use = 1; + } + } + + if (!use) + continue; + + if (rl->tl) { + N[0] += rl->tl->gn[0]; + N[1] += rl->tl->gn[1]; + N[2] += rl->tl->gn[2]; + } + if (rl->tr) { + N[0] += rl->tr->gn[0]; + N[1] += rl->tr->gn[1]; + N[2] += rl->tr->gn[2]; + } + if (rl->tl || rl->tr) { + normalize_v3(N); + copy_v3_v3(&N[3], N); + } + N += 6; + + CLAMP(rls->at, 0, 1); + if (irls = rls->next) { + CLAMP(irls->at, 0, 1); + } + + *v = tnsLinearItp(rl->l->fbcoord[0], rl->r->fbcoord[0], rls->at); + v++; + *v = tnsLinearItp(rl->l->fbcoord[1], rl->r->fbcoord[1], rls->at); + v++; + *v = componet_id; + v++; + *v = tnsLinearItp(rl->l->fbcoord[0], rl->r->fbcoord[0], irls ? irls->at : 1); + v++; + *v = tnsLinearItp(rl->l->fbcoord[1], rl->r->fbcoord[1], irls ? irls->at : 1); + v++; + *v = componet_id; + v++; + } + } + *NextNormal = N; + return v; +} + +void lanpr_chain_generate_draw_command(LANPR_RenderBuffer *rb); + +#define TNS_BOUND_AREA_CROSSES(b1, b2) \ + ((b1)[0] < (b2)[1] && (b1)[1] > (b2)[0] && (b1)[3] < (b2)[2] && (b1)[2] > (b2)[3]) + +static void lanpr_make_initial_bounding_areas(LANPR_RenderBuffer *rb) +{ + int sp_w = 4; /* 20; */ + int sp_h = 4; /* rb->H / (rb->W / sp_w); */ + int row, col; + LANPR_BoundingArea *ba; + real W = (real)rb->w; + real H = (real)rb->h; + real span_w = (real)1 / sp_w * 2.0; + real span_h = (real)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; + + rb->bounding_area_count = sp_w * sp_h; + rb->initial_bounding_areas = mem_static_aquire( + &rb->render_data_pool, sizeof(LANPR_BoundingArea) * rb->bounding_area_count); + + for (row = 0; row < sp_h; row++) { + for (col = 0; col < sp_w; col++) { + ba = &rb->initial_bounding_areas[row * 4 + col]; + + ba->l = span_w * col - 1.0; + ba->r = (col == sp_w - 1) ? 1.0 : (span_w * (col + 1) - 1.0); + ba->u = 1.0 - span_h * row; + ba->b = (row == sp_h - 1) ? -1.0 : (1.0 - span_h * (row + 1)); + + ba->cx = (ba->l + ba->r) / 2; + ba->cy = (ba->u + ba->b) / 2; + + if (row) { + list_append_pointer_static( + &ba->up, &rb->render_data_pool, &rb->initial_bounding_areas[(row - 1) * 4 + col]); + } + if (col) { + list_append_pointer_static( + &ba->lp, &rb->render_data_pool, &rb->initial_bounding_areas[row * 4 + col - 1]); + } + if (row != sp_h - 1) { + list_append_pointer_static( + &ba->bp, &rb->render_data_pool, &rb->initial_bounding_areas[(row + 1) * 4 + col]); + } + if (col != sp_w - 1) { + list_append_pointer_static( + &ba->rp, &rb->render_data_pool, &rb->initial_bounding_areas[row * 4 + col + 1]); + } + } + } +} +static void lanpr_connect_new_bounding_areas(LANPR_RenderBuffer *rb, LANPR_BoundingArea *Root) +{ + LANPR_BoundingArea *ba = Root->child, *tba; + LinkData *lip, *lip2, *next_lip; + LANPR_StaticMemPool *mph = &rb->render_data_pool; + + list_append_pointer_static_pool(mph, &ba[1].rp, &ba[0]); + list_append_pointer_static_pool(mph, &ba[0].lp, &ba[1]); + list_append_pointer_static_pool(mph, &ba[1].bp, &ba[2]); + list_append_pointer_static_pool(mph, &ba[2].up, &ba[1]); + list_append_pointer_static_pool(mph, &ba[2].rp, &ba[3]); + list_append_pointer_static_pool(mph, &ba[3].lp, &ba[2]); + list_append_pointer_static_pool(mph, &ba[3].up, &ba[0]); + list_append_pointer_static_pool(mph, &ba[0].bp, &ba[3]); + + for (lip = Root->lp.first; lip; lip = lip->next) { + tba = lip->data; + if (ba[1].u > tba->b && ba[1].b < tba->u) { + list_append_pointer_static_pool(mph, &ba[1].lp, tba); + list_append_pointer_static_pool(mph, &tba->rp, &ba[1]); + } + if (ba[2].u > tba->b && ba[2].b < tba->u) { + list_append_pointer_static_pool(mph, &ba[2].lp, tba); + list_append_pointer_static_pool(mph, &tba->rp, &ba[2]); + } + } + for (lip = Root->rp.first; lip; lip = lip->next) { + tba = lip->data; + if (ba[0].u > tba->b && ba[0].b < tba->u) { + list_append_pointer_static_pool(mph, &ba[0].rp, tba); + list_append_pointer_static_pool(mph, &tba->lp, &ba[0]); + } + if (ba[3].u > tba->b && ba[3].b < tba->u) { + list_append_pointer_static_pool(mph, &ba[3].rp, tba); + list_append_pointer_static_pool(mph, &tba->lp, &ba[3]); + } + } + for (lip = Root->up.first; lip; lip = lip->next) { + tba = lip->data; + if (ba[0].r > tba->l && ba[0].l < tba->r) { + list_append_pointer_static_pool(mph, &ba[0].up, tba); + list_append_pointer_static_pool(mph, &tba->bp, &ba[0]); + } + if (ba[1].r > tba->l && ba[1].l < tba->r) { + list_append_pointer_static_pool(mph, &ba[1].up, tba); + list_append_pointer_static_pool(mph, &tba->bp, &ba[1]); + } + } + for (lip = Root->bp.first; lip; lip = lip->next) { + tba = lip->data; + if (ba[2].r > tba->l && ba[2].l < tba->r) { + list_append_pointer_static_pool(mph, &ba[2].bp, tba); + list_append_pointer_static_pool(mph, &tba->up, &ba[2]); + } + if (ba[3].r > tba->l && ba[3].l < tba->r) { + list_append_pointer_static_pool(mph, &ba[3].bp, tba); + list_append_pointer_static_pool(mph, &tba->up, &ba[3]); + } + } + for (lip = Root->lp.first; lip; lip = lip->next) { + for (lip2 = ((LANPR_BoundingArea *)lip->data)->rp.first; lip2; lip2 = next_lip) { + next_lip = lip2->next; + tba = lip2->data; + if (tba == Root) { + list_remove_pointer_item_no_free(&((LANPR_BoundingArea *)lip->data)->rp, lip2); + if (ba[1].u > tba->b && ba[1].b < tba->u) { + list_append_pointer_static_pool(mph, &tba->rp, &ba[1]); + } + if (ba[2].u > tba->b && ba[2].b < tba->u) { + list_append_pointer_static_pool(mph, &tba->rp, &ba[2]); + } + } + } + } + for (lip = Root->rp.first; lip; lip = lip->next) { + for (lip2 = ((LANPR_BoundingArea *)lip->data)->lp.first; lip2; lip2 = next_lip) { + next_lip = lip2->next; + tba = lip2->data; + if (tba == Root) { + list_remove_pointer_item_no_free(&((LANPR_BoundingArea *)lip->data)->lp, lip2); + if (ba[0].u > tba->b && ba[0].b < tba->u) { + list_append_pointer_static_pool(mph, &tba->lp, &ba[0]); + } + if (ba[3].u > tba->b && ba[3].b < tba->u) { + list_append_pointer_static_pool(mph, &tba->lp, &ba[3]); + } + } + } + } + for (lip = Root->up.first; lip; lip = lip->next) { + for (lip2 = ((LANPR_BoundingArea *)lip->data)->bp.first; lip2; lip2 = next_lip) { + next_lip = lip2->next; + tba = lip2->data; + if (tba == Root) { + list_remove_pointer_item_no_free(&((LANPR_BoundingArea *)lip->data)->bp, lip2); + if (ba[0].r > tba->l && ba[0].l < tba->r) { + list_append_pointer_static_pool(mph, &tba->up, &ba[0]); + } + if (ba[1].r > tba->l && ba[1].l < tba->r) { + list_append_pointer_static_pool(mph, &tba->up, &ba[1]); + } + } + } + } + for (lip = Root->bp.first; lip; lip = lip->next) { + for (lip2 = ((LANPR_BoundingArea *)lip->data)->up.first; lip2; lip2 = next_lip) { + next_lip = lip2->next; + tba = lip2->data; + if (tba == Root) { + list_remove_pointer_item_no_free(&((LANPR_BoundingArea *)lip->data)->up, lip2); + if (ba[2].r > tba->l && ba[2].l < tba->r) { + list_append_pointer_static_pool(mph, &tba->bp, &ba[2]); + } + if (ba[3].r > tba->l && ba[3].l < tba->r) { + list_append_pointer_static_pool(mph, &tba->bp, &ba[3]); + } + } + } + } + while (list_pop_pointer_no_free(&Root->lp)) + ; + while (list_pop_pointer_no_free(&Root->rp)) + ; + while (list_pop_pointer_no_free(&Root->up)) + ; + while (list_pop_pointer_no_free(&Root->bp)) + ; +} +static void lanpr_link_triangle_with_bounding_area(LANPR_RenderBuffer *rb, + LANPR_BoundingArea *RootBoundingArea, + LANPR_RenderTriangle *rt, + real *LRUB, + int Recursive); +static void lanpr_triangle_calculate_intersections_in_bounding_area(LANPR_RenderBuffer *rb, + LANPR_RenderTriangle *rt, + LANPR_BoundingArea *ba); + +static void lanpr_split_bounding_area(LANPR_RenderBuffer *rb, LANPR_BoundingArea *Root) +{ + LANPR_BoundingArea *ba = mem_static_aquire(&rb->render_data_pool, + sizeof(LANPR_BoundingArea) * 4); + LANPR_RenderTriangle *rt; + + ba[0].l = Root->cx; + ba[0].r = Root->r; + ba[0].u = Root->u; + ba[0].b = Root->cy; + ba[0].cx = (ba[0].l + ba[0].r) / 2; + ba[0].cy = (ba[0].u + ba[0].b) / 2; + + ba[1].l = Root->l; + ba[1].r = Root->cx; + ba[1].u = Root->u; + ba[1].b = Root->cy; + ba[1].cx = (ba[1].l + ba[1].r) / 2; + ba[1].cy = (ba[1].u + ba[1].b) / 2; + + ba[2].l = Root->l; + ba[2].r = Root->cx; + ba[2].u = Root->cy; + ba[2].b = Root->b; + ba[2].cx = (ba[2].l + ba[2].r) / 2; + ba[2].cy = (ba[2].u + ba[2].b) / 2; + + ba[3].l = Root->cx; + ba[3].r = Root->r; + ba[3].u = Root->cy; + ba[3].b = Root->b; + ba[3].cx = (ba[3].l + ba[3].r) / 2; + ba[3].cy = (ba[3].u + ba[3].b) / 2; + + Root->child = ba; + + lanpr_connect_new_bounding_areas(rb, Root); + + while (rt = list_pop_pointer_no_free(&Root->linked_triangles)) { + LANPR_BoundingArea *ba = Root->child; + real b[4]; + b[0] = MIN3(rt->v[0]->fbcoord[0], rt->v[1]->fbcoord[0], rt->v[2]->fbcoord[0]); + b[1] = MAX3(rt->v[0]->fbcoord[0], rt->v[1]->fbcoord[0], rt->v[2]->fbcoord[0]); + b[2] = MAX3(rt->v[0]->fbcoord[1], rt->v[1]->fbcoord[1], rt->v[2]->fbcoord[1]); + b[3] = MIN3(rt->v[0]->fbcoord[1], rt->v[1]->fbcoord[1], rt->v[2]->fbcoord[1]); + if (TNS_BOUND_AREA_CROSSES(b, &ba[0].l)) { + lanpr_link_triangle_with_bounding_area(rb, &ba[0], rt, b, 0); + } + if (TNS_BOUND_AREA_CROSSES(b, &ba[1].l)) { + lanpr_link_triangle_with_bounding_area(rb, &ba[1], rt, b, 0); + } + if (TNS_BOUND_AREA_CROSSES(b, &ba[2].l)) { + lanpr_link_triangle_with_bounding_area(rb, &ba[2], rt, b, 0); + } + if (TNS_BOUND_AREA_CROSSES(b, &ba[3].l)) { + lanpr_link_triangle_with_bounding_area(rb, &ba[3], rt, b, 0); + } + } + + rb->bounding_area_count += 3; +} +static int lanpr_line_crosses_bounding_area(LANPR_RenderBuffer *fb, + tnsVector2d l, + tnsVector2d r, + LANPR_BoundingArea *ba) +{ + real vx, vy; + tnsVector4d converted; + real c1, c; + + if (((converted[0] = (real)ba->l) > MAX2(l[0], r[0])) || + ((converted[1] = (real)ba->r) < MIN2(l[0], r[0])) || + ((converted[2] = (real)ba->b) > MAX2(l[1], r[1])) || + ((converted[3] = (real)ba->u) < MIN2(l[1], r[1]))) { + return 0; + } + + vx = l[0] - r[0]; + vy = l[1] - r[1]; + + c1 = vx * (converted[2] - l[1]) - vy * (converted[0] - l[0]); + c = c1; + + c1 = vx * (converted[2] - l[1]) - vy * (converted[1] - l[0]); + if (c1 * c <= 0) { + return 1; + } + else { + c = c1; + } + + c1 = vx * (converted[3] - l[1]) - vy * (converted[0] - l[0]); + if (c1 * c <= 0) { + return 1; + } + else { + c = c1; + } + + c1 = vx * (converted[3] - l[1]) - vy * (converted[1] - l[0]); + if (c1 * c <= 0) { + return 1; + } + else { + c = c1; + } + + return 0; +} +static int lanpr_triangle_covers_bounding_area(LANPR_RenderBuffer *fb, + LANPR_RenderTriangle *rt, + LANPR_BoundingArea *ba) +{ + tnsVector2d p1, p2, p3, p4; + real *FBC1 = rt->v[0]->fbcoord, *FBC2 = rt->v[1]->fbcoord, *FBC3 = rt->v[2]->fbcoord; + + p3[0] = p1[0] = (real)ba->l; + p2[1] = p1[1] = (real)ba->b; + p2[0] = p4[0] = (real)ba->r; + p3[1] = p4[1] = (real)ba->u; + + if ((FBC1[0] >= p1[0] && FBC1[0] <= p2[0] && FBC1[1] >= p1[1] && FBC1[1] <= p3[1]) || + (FBC2[0] >= p1[0] && FBC2[0] <= p2[0] && FBC2[1] >= p1[1] && FBC2[1] <= p3[1]) || + (FBC3[0] >= p1[0] && FBC3[0] <= p2[0] && FBC3[1] >= p1[1] && FBC3[1] <= p3[1])) { + return 1; + } + + if (ED_lanpr_point_inside_triangled(p1, FBC1, FBC2, FBC3) || + ED_lanpr_point_inside_triangled(p2, FBC1, FBC2, FBC3) || + ED_lanpr_point_inside_triangled(p3, FBC1, FBC2, FBC3) || + ED_lanpr_point_inside_triangled(p4, FBC1, FBC2, FBC3)) { + return 1; + } + + if ((lanpr_line_crosses_bounding_area(fb, FBC1, FBC2, ba)) || + (lanpr_line_crosses_bounding_area(fb, FBC2, FBC3, ba)) || + (lanpr_line_crosses_bounding_area(fb, FBC3, FBC1, ba))) { + return 1; + } + + return 0; +} +static void lanpr_link_triangle_with_bounding_area(LANPR_RenderBuffer *rb, + LANPR_BoundingArea *RootBoundingArea, + LANPR_RenderTriangle *rt, + real *LRUB, + int Recursive) +{ + if (!lanpr_triangle_covers_bounding_area(rb, rt, RootBoundingArea)) { + return; + } + if (!RootBoundingArea->child) { + list_append_pointer_static_pool( + &rb->render_data_pool, &RootBoundingArea->linked_triangles, rt); + RootBoundingArea->triangle_count++; + if (RootBoundingArea->triangle_count > 200 && Recursive) { + lanpr_split_bounding_area(rb, RootBoundingArea); + } + if (Recursive && rb->enable_intersections) { + lanpr_triangle_calculate_intersections_in_bounding_area(rb, rt, RootBoundingArea); + } + } + else { + LANPR_BoundingArea *ba = RootBoundingArea->child; + real *B1 = LRUB; + real b[4]; + if (!LRUB) { + b[0] = MIN3(rt->v[0]->fbcoord[0], rt->v[1]->fbcoord[0], rt->v[2]->fbcoord[0]); + b[1] = MAX3(rt->v[0]->fbcoord[0], rt->v[1]->fbcoord[0], rt->v[2]->fbcoord[0]); + b[2] = MAX3(rt->v[0]->fbcoord[1], rt->v[1]->fbcoord[1], rt->v[2]->fbcoord[1]); + b[3] = MIN3(rt->v[0]->fbcoord[1], rt->v[1]->fbcoord[1], rt->v[2]->fbcoord[1]); + B1 = b; + } + if (TNS_BOUND_AREA_CROSSES(B1, &ba[0].l)) { + lanpr_link_triangle_with_bounding_area(rb, &ba[0], rt, B1, Recursive); + } + if (TNS_BOUND_AREA_CROSSES(B1, &ba[1].l)) { + lanpr_link_triangle_with_bounding_area(rb, &ba[1], rt, B1, Recursive); + } + if (TNS_BOUND_AREA_CROSSES(B1, &ba[2].l)) { + lanpr_link_triangle_with_bounding_area(rb, &ba[2], rt, B1, Recursive); + } + if (TNS_BOUND_AREA_CROSSES(B1, &ba[3].l)) { + lanpr_link_triangle_with_bounding_area(rb, &ba[3], rt, B1, Recursive); + } + } +} +static void lanpr_link_line_with_bounding_area(LANPR_RenderBuffer *rb, + LANPR_BoundingArea *RootBoundingArea, + LANPR_RenderLine *rl) +{ + if (!RootBoundingArea->child) { + list_append_pointer_static_pool(&rb->render_data_pool, &RootBoundingArea->linked_lines, rl); + } + else { + if (lanpr_line_crosses_bounding_area( + rb, rl->l->fbcoord, rl->r->fbcoord, &RootBoundingArea->child[0])) { + lanpr_link_line_with_bounding_area(rb, &RootBoundingArea->child[0], rl); + } + else if (lanpr_line_crosses_bounding_area( + rb, rl->l->fbcoord, rl->r->fbcoord, &RootBoundingArea->child[1])) { + lanpr_link_line_with_bounding_area(rb, &RootBoundingArea->child[1], rl); + } + else if (lanpr_line_crosses_bounding_area( + rb, rl->l->fbcoord, rl->r->fbcoord, &RootBoundingArea->child[2])) { + lanpr_link_line_with_bounding_area(rb, &RootBoundingArea->child[2], rl); + } + else if (lanpr_line_crosses_bounding_area( + rb, rl->l->fbcoord, rl->r->fbcoord, &RootBoundingArea->child[3])) { + lanpr_link_line_with_bounding_area(rb, &RootBoundingArea->child[3], rl); + } + } +} +static int lanpr_get_triangle_bounding_areas(LANPR_RenderBuffer *rb, + LANPR_RenderTriangle *rt, + int *rowBegin, + int *rowEnd, + int *colBegin, + int *colEnd) +{ + real sp_w = rb->width_per_tile, sp_h = rb->height_per_tile; + real b[4]; + + if (!rt->v[0] || !rt->v[1] || !rt->v[2]) { + return 0; + } + + b[0] = MIN3(rt->v[0]->fbcoord[0], rt->v[1]->fbcoord[0], rt->v[2]->fbcoord[0]); + b[1] = MAX3(rt->v[0]->fbcoord[0], rt->v[1]->fbcoord[0], rt->v[2]->fbcoord[0]); + b[2] = MIN3(rt->v[0]->fbcoord[1], rt->v[1]->fbcoord[1], rt->v[2]->fbcoord[1]); + b[3] = MAX3(rt->v[0]->fbcoord[1], rt->v[1]->fbcoord[1], rt->v[2]->fbcoord[1]); + + if (b[0] > 1 || b[1] < -1 || b[2] > 1 || b[3] < -1) { + return 0; + } + + (*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; + + if ((*colEnd) >= rb->tile_count_x) { + (*colEnd) = rb->tile_count_x - 1; + } + if ((*rowEnd) >= rb->tile_count_y) { + (*rowEnd) = rb->tile_count_y - 1; + } + if ((*colBegin) < 0) { + (*colBegin) = 0; + } + if ((*rowBegin) < 0) { + (*rowBegin) = 0; + } + + return 1; +} +static int lanpr_get_line_bounding_areas(LANPR_RenderBuffer *rb, + LANPR_RenderLine *rl, + int *rowBegin, + int *rowEnd, + int *colBegin, + int *colEnd) +{ + real sp_w = rb->width_per_tile, sp_h = rb->height_per_tile; + real b[4]; + + if (!rl->l || !rl->r) { + return 0; + } + + if (rl->l->fbcoord[0] != rl->l->fbcoord[0] || rl->r->fbcoord[0] != rl->r->fbcoord[0]) { + return 0; + } + + b[0] = MIN2(rl->l->fbcoord[0], rl->r->fbcoord[0]); + b[1] = MAX2(rl->l->fbcoord[0], rl->r->fbcoord[0]); + b[2] = MIN2(rl->l->fbcoord[1], rl->r->fbcoord[1]); + b[3] = MAX2(rl->l->fbcoord[1], rl->r->fbcoord[1]); + + if (b[0] > 1 || b[1] < -1 || b[2] > 1 || b[3] < -1) { + return 0; + } + + (*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; + + if ((*colEnd) >= rb->tile_count_x) { + (*colEnd) = rb->tile_count_x - 1; + } + if ((*rowEnd) >= rb->tile_count_y) { + (*rowEnd) = rb->tile_count_y - 1; + } + if ((*colBegin) < 0) { + (*colBegin) = 0; + } + if ((*rowBegin) < 0) { + (*rowBegin) = 0; + } + + return 1; +} +LANPR_BoundingArea *ED_lanpr_get_point_bounding_area(LANPR_RenderBuffer *rb, real x, real y) +{ + real sp_w = rb->width_per_tile, sp_h = rb->height_per_tile; + int col, row; + + if (x > 1 || x < -1 || y > 1 || y < -1) { + return 0; + } + + col = (int)((x + 1.0) / sp_w); + row = rb->tile_count_y - (int)((y + 1.0) / sp_h) - 1; + + if (col >= rb->tile_count_x) { + col = rb->tile_count_x - 1; + } + if (row >= rb->tile_count_y) { + row = rb->tile_count_y - 1; + } + if (col < 0) { + col = 0; + } + if (row < 0) { + row = 0; + } + + return &rb->initial_bounding_areas[row * 4 + col]; +} +static LANPR_BoundingArea *lanpr_get_point_bounding_area_recursive(LANPR_BoundingArea *ba, + real x, + real y) +{ + if (!ba->child) { + return ba; + } + else { + LANPR_BoundingArea *ch = ba->child; +#define IN_BOUND(i, x, y) \ + ba->child[i].l <= x && ba->child[i].r >= x && ba->child[i].b <= y && ba->child[i].u >= y + + if (IN_BOUND(0, x, y)) { + return lanpr_get_point_bounding_area_recursive(&ba->child[0], x, y); + } + else if (IN_BOUND(1, x, y)) { + return lanpr_get_point_bounding_area_recursive(&ba->child[1], x, y); + } + else if (IN_BOUND(2, x, y)) { + return lanpr_get_point_bounding_area_recursive(&ba->child[2], x, y); + } + else if (IN_BOUND(3, x, y)) { + return lanpr_get_point_bounding_area_recursive(&ba->child[3], x, y); + } + } + return NULL; +} +LANPR_BoundingArea *ED_lanpr_get_point_bounding_area_deep(LANPR_RenderBuffer *rb, real x, real y) +{ + LANPR_BoundingArea *ba; + if (ba = ED_lanpr_get_point_bounding_area(rb, x, y)) { + return lanpr_get_point_bounding_area_recursive(ba, x, y); + } + return NULL; +} + +static void lanpr_add_triangles(LANPR_RenderBuffer *rb) +{ + LANPR_RenderElementLinkNode *reln; + LANPR_RenderTriangle *rt; + /* tnsMatrix44d vP; */ + Camera *c = ((Camera *)rb->scene->camera); + int i, lim; + int x1, x2, y1, y2; + int r, co; + /* tnsMatrix44d proj, view, result, inv; */ + /* tmat_make_perspective_matrix_44d(proj, c->FOv, (real)fb->W / (real)fb->H, c->clipsta, */ + /* c->clipend); tmat_load_identity_44d(view); tObjApplyself_transformMatrix(c, 0); */ + /* tObjApplyGlobalTransformMatrixReverted(c); */ + /* tmat_inverse_44d(inv, c->Base.GlobalTransform); */ + /* tmat_multiply_44d(result, proj, inv); */ + /* memcpy(proj, result, sizeof(tnsMatrix44d)); */ + + /* tnsglobal_TriangleIntersectionCount = 0; */ + + /* tnsset_RenderOverallProgress(rb, NUL_MH2); */ + /* nulThreadNotifyUsers("tns.render_buffer_list.calculation_status"); */ + + for (reln = rb->triangle_buffer_pointers.first; reln; reln = reln->next) { + rt = reln->pointer; + lim = reln->element_count; + for (i = 0; i < lim; i++) { + if (rt->cull_status) { + rt = (void *)(((BYTE *)rt) + rb->triangle_size); + continue; + } + if (lanpr_get_triangle_bounding_areas(rb, rt, &y1, &y2, &x1, &x2)) { + for (co = x1; co <= x2; co++) { + for (r = y1; r <= y2; r++) { + lanpr_link_triangle_with_bounding_area( + rb, &rb->initial_bounding_areas[r * 4 + co], rt, 0, 1); + } + } + } + else { + ; /* throw away. */ + } + rt = (void *)(((BYTE *)rt) + rb->triangle_size); + /* if (tnsglobal_TriangleIntersectionCount >= 2000) { */ + /* tnsset_PlusRenderIntersectionCount(rb, tnsglobal_TriangleIntersectionCount); */ + /* tnsglobal_TriangleIntersectionCount = 0; */ + /* } */ + } + } + /* tnsset_PlusRenderIntersectionCount(rb, tnsglobal_TriangleIntersectionCount); */ +} +static LANPR_BoundingArea *lanpr_get_next_bounding_area(LANPR_BoundingArea *This, + LANPR_RenderLine *rl, + real x, + real y, + real k, + int PositiveX, + int PositiveY, + real *NextX, + real *NextY) +{ + real rx, ry, ux, uy, lx, ly, bx, by; + real r1, r2; + LANPR_BoundingArea *ba; + LinkData *lip; + if (PositiveX > 0) { + rx = This->r; + ry = y + k * (rx - x); + if (PositiveY > 0) { + uy = This->u; + ux = x + (uy - y) / k; + r1 = tMatGetLinearRatio(rl->l->fbcoord[0], rl->r->fbcoord[0], rx); + r2 = tMatGetLinearRatio(rl->l->fbcoord[0], rl->r->fbcoord[0], ux); + if (MIN2(r1, r2) > 1) { + return 0; + } + if (r1 <= r2) { + for (lip = This->rp.first; lip; lip = lip->next) { + ba = lip->data; + if (ba->u >= ry && ba->b < ry) { + *NextX = rx; + *NextY = ry; + return ba; + } + } + } + else { + for (lip = This->up.first; lip; lip = lip->next) { + ba = lip->data; + if (ba->r >= ux && ba->l < ux) { + *NextX = ux; + *NextY = uy; + return ba; + } + } + } + } + else if (PositiveY < 0) { + by = This->b; + bx = x + (by - y) / k; + r1 = tMatGetLinearRatio(rl->l->fbcoord[0], rl->r->fbcoord[0], rx); + r2 = tMatGetLinearRatio(rl->l->fbcoord[0], rl->r->fbcoord[0], bx); + if (MIN2(r1, r2) > 1) { + return 0; + } + if (r1 <= r2) { + for (lip = This->rp.first; lip; lip = lip->next) { + ba = lip->data; + if (ba->u >= ry && ba->b < ry) { + *NextX = rx; + *NextY = ry; + return ba; + } + } + } + else { + for (lip = This->bp.first; lip; lip = lip->next) { + ba = lip->data; + if (ba->r >= bx && ba->l < bx) { + *NextX = bx; + *NextY = by; + return ba; + } + } + } + } + else { /* Y diffence == 0 */ + r1 = tMatGetLinearRatio(rl->l->fbcoord[0], rl->r->fbcoord[0], This->r); + if (r1 > 1) { + return 0; + } + for (lip = This->rp.first; lip; lip = lip->next) { + ba = lip->data; + if (ba->u >= y && ba->b < y) { + *NextX = This->r; + *NextY = y; + return ba; + } + } + } + } + else if (PositiveX < 0) { /* X diffence < 0 */ + lx = This->l; + ly = y + k * (lx - x); + if (PositiveY > 0) { + uy = This->u; + ux = x + (uy - y) / k; + r1 = tMatGetLinearRatio(rl->l->fbcoord[0], rl->r->fbcoord[0], lx); + r2 = tMatGetLinearRatio(rl->l->fbcoord[0], rl->r->fbcoord[0], ux); + if (MIN2(r1, r2) > 1) { + return 0; + } + if (r1 <= r2) { + for (lip = This->lp.first; lip; lip = lip->next) { + ba = lip->data; + if (ba->u >= ly && ba->b < ly) { + *NextX = lx; + *NextY = ly; + return ba; + } + } + } + else { + for (lip = This->up.first; lip; lip = lip->next) { + ba = lip->data; + if (ba->r >= ux && ba->l < ux) { + *NextX = ux; + *NextY = uy; + return ba; + } + } + } + } + else if (PositiveY < 0) { + by = This->b; + bx = x + (by - y) / k; + r1 = tMatGetLinearRatio(rl->l->fbcoord[0], rl->r->fbcoord[0], lx); + r2 = tMatGetLinearRatio(rl->l->fbcoord[0], rl->r->fbcoord[0], bx); + if (MIN2(r1, r2) > 1) { + return 0; + } + if (r1 <= r2) { + for (lip = This->lp.first; lip; lip = lip->next) { + ba = lip->data; + if (ba->u >= ly && ba->b < ly) { + *NextX = lx; + *NextY = ly; + return ba; + } + } + } + else { + for (lip = This->bp.first; lip; lip = lip->next) { + ba = lip->data; + if (ba->r >= bx && ba->l < bx) { + *NextX = bx; + *NextY = by; + return ba; + } + } + } + } + else { /* Y diffence == 0 */ + r1 = tMatGetLinearRatio(rl->l->fbcoord[0], rl->r->fbcoord[0], This->l); + if (r1 > 1) { + return 0; + } + for (lip = This->lp.first; lip; lip = lip->next) { + ba = lip->data; + if (ba->u >= y && ba->b < y) { + *NextX = This->l; + *NextY = y; + return ba; + } + } + } + } + else { /* X difference == 0; */ + if (PositiveY > 0) { + r1 = tMatGetLinearRatio(rl->l->fbcoord[1], rl->r->fbcoord[1], This->u); + if (r1 > 1) { + return 0; + } + for (lip = This->up.first; lip; lip = lip->next) { + ba = lip->data; + if (ba->r > x && ba->l <= x) { + *NextX = x; + *NextY = This->u; + return ba; + } + } + } + else if (PositiveY < 0) { + r1 = tMatGetLinearRatio(rl->l->fbcoord[1], rl->r->fbcoord[1], This->b); + if (r1 > 1) { + return 0; + } + for (lip = This->bp.first; lip; lip = lip->next) { + ba = lip->data; + if (ba->r > x && ba->l <= x) { + *NextX = x; + *NextY = This->b; + return ba; + } + } + } + else + return 0; /* segment has no length */ + } + return 0; +} + +static LANPR_BoundingArea *lanpr_get_bounding_area(LANPR_RenderBuffer *rb, real x, real y) +{ + LANPR_BoundingArea *iba; + real sp_w = rb->width_per_tile, sp_h = rb->height_per_tile; + int c = (int)((x + 1.0) / sp_w); + int r = rb->tile_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 (c >= rb->tile_count_x) { + c = rb->tile_count_x - 1; + } + + iba = &rb->initial_bounding_areas[r * 4 + c]; + while (iba->child) { + if (x > iba->cx) { + if (y > iba->cy) { + iba = &iba->child[0]; + } + else { + iba = &iba->child[3]; + } + } + else { + if (y > iba->cy) { + iba = &iba->child[1]; + } + else { + iba = &iba->child[2]; + } + } + } + return iba; +} +static LANPR_BoundingArea *lanpr_get_first_possible_bounding_area(LANPR_RenderBuffer *rb, + LANPR_RenderLine *rl) +{ + LANPR_BoundingArea *iba; + real data[2] = {rl->l->fbcoord[0], rl->l->fbcoord[1]}; + tnsVector2d LU = {-1, 1}, RU = {1, 1}, LB = {-1, -1}, RB = {1, -1}; + real r = 1, sr = 1; + + if (data[0] > -1 && data[0] < 1 && data[1] > -1 && data[1] < 1) { + return lanpr_get_bounding_area(rb, data[0], data[1]); + } + else { + if ((lanpr_LineIntersectTest2d(rl->l->fbcoord, rl->r->fbcoord, LU, RU, &sr) && sr < r && + sr > 0) || + (lanpr_LineIntersectTest2d(rl->l->fbcoord, rl->r->fbcoord, LB, RB, &sr) && sr < r && + sr > 0) || + (lanpr_LineIntersectTest2d(rl->l->fbcoord, rl->r->fbcoord, LB, LU, &sr) && sr < r && + sr > 0) || + (lanpr_LineIntersectTest2d(rl->l->fbcoord, rl->r->fbcoord, RB, RU, &sr) && sr < r && + sr > 0)) { + r = sr; + } + interp_v2_v2v2_db(data, rl->l->fbcoord, rl->r->fbcoord, r); + + return lanpr_get_bounding_area(rb, data[0], data[1]); + } + + real sp_w = rb->width_per_tile, sp_h = rb->height_per_tile; + + return iba; +} + +/* Calculations */ + +int ED_lanpr_compute_feature_lines_internal(Depsgraph *depsgraph, int intersectons_only) +{ + LANPR_RenderBuffer *rb; + Scene *s = DEG_get_evaluated_scene(depsgraph); + SceneLANPR *lanpr = &s->lanpr; + int is_lanpr_engine = !strcmp(s->r.engine, RE_engine_id_BLENDER_LANPR); + + if (!is_lanpr_engine && !lanpr->enabled) { + return OPERATOR_CANCELLED; + } + + rb = ED_lanpr_create_render_buffer(); + + lanpr_share.render_buffer_shared = rb; + + rb->scene = s; + rb->w = s->r.xsch; + rb->h = s->r.ysch; + rb->enable_intersections = lanpr->enable_intersections; + + rb->triangle_size = lanpr_get_render_triangle_size(rb); + + rb->max_occlusion_level = lanpr_get_max_occlusion_level(depsgraph); + + lanpr_make_render_geometry_buffers(depsgraph, rb->scene, rb->scene->camera, rb); + + lanpr_compute_view_Vector(rb); + lanpr_cull_triangles(rb); + + lanpr_perspective_division(rb); + + lanpr_make_initial_bounding_areas(rb); + + if (!intersectons_only) { + lanpr_compute_scene_contours(rb, lanpr->crease_threshold); + } + + lanpr_add_triangles(rb); + + if (!intersectons_only) { + lanpr_THREAD_calculate_line_occlusion_begin(rb); + } + + /* When not using LANPR engine, chaining is forced in order to generate data for GPencil. */ + if ((lanpr->enable_chaining || !is_lanpr_engine) && (!intersectons_only)) { + float t_image = rb->scene->lanpr.chaining_image_threshold; + float t_geom = rb->scene->lanpr.chaining_geometry_threshold; + + ED_lanpr_NO_THREAD_chain_feature_lines(rb); + + if (is_lanpr_engine) { + /* Enough with it. We can provide an option after we have LANPR internal smoothing */ + return; + } + + /* Below are simply for better GPencil experience. */ + + ED_lanpr_split_chains_for_fixed_occlusion(rb); + + if (t_image < FLT_EPSILON && t_geom < FLT_EPSILON) { + t_geom = 0.0f; + t_image = 0.01f; + } + + ED_lanpr_connect_chains(rb, 1); + ED_lanpr_connect_chains(rb, 0); + + /* This configuration ensures there won't be accidental lost of short segments */ + ED_lanpr_discard_short_chains(rb, MIN3(t_image, t_geom, 0.01f) - FLT_EPSILON); + } + + rb->cached_for_frame = rb->scene->r.cfra; + + return OPERATOR_FINISHED; +} +static bool lanpr_camera_exists(struct bContext *c) +{ + Scene *s = CTX_data_scene(c); + return s->camera ? true : false; +} +static int lanpr_compute_feature_lines_exec(struct bContext *C, struct wmOperator *op) +{ + Scene *scene = CTX_data_scene(C); + SceneLANPR *lanpr = &scene->lanpr; + int result; + int is_lanpr_engine = !strcmp(scene->r.engine, RE_engine_id_BLENDER_LANPR); + + if (!is_lanpr_engine && !lanpr->enabled) { + return OPERATOR_CANCELLED; + } + + if (!scene->camera) { + BKE_report(op->reports, RPT_ERROR, "There is no active camera in this scene!"); + printf("LANPR Warning: There is no active camera in this scene!\n"); + return OPERATOR_FINISHED; + } + + int intersections_only = (is_lanpr_engine && lanpr->master_mode != LANPR_MASTER_MODE_SOFTWARE); + + result = ED_lanpr_compute_feature_lines_internal(CTX_data_depsgraph(C), intersections_only); + + lanpr_rebuild_all_command(lanpr); + + WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, NULL); + + return result; +} +static void lanpr_compute_feature_lines_cancel(struct bContext *C, struct wmOperator *op) +{ + + return; +} + +void SCENE_OT_lanpr_calculate_feature_lines(struct wmOperatorType *ot) +{ + + /* identifiers */ + ot->name = "Calculate Feature Lines"; + ot->description = "LANPR calculates feature line in current scene"; + ot->idname = "SCENE_OT_lanpr_calculate"; + + ot->poll = lanpr_camera_exists; + ot->cancel = lanpr_compute_feature_lines_cancel; + ot->exec = lanpr_compute_feature_lines_exec; +} + +/* SVG bindings */ + +static int lanpr_export_svg_exec(struct bContext *C, wmOperator *op) +{ + LANPR_RenderBuffer *rb = lanpr_share.render_buffer_shared; + SceneLANPR *lanpr = + &rb->scene->lanpr; /* XXX: This is not evaluated for copy_on_write stuff... */ + LANPR_LineLayer *ll; + + for (ll = lanpr->line_layers.first; ll; ll = ll->next) { + Text *ta = BKE_text_add(CTX_data_main(C), "exported_svg"); + ED_svg_data_from_lanpr_chain(ta, rb, ll); + } + + return OPERATOR_FINISHED; +} + +static bool lanpr_render_buffer_found(struct bContext *C) +{ + if (lanpr_share.render_buffer_shared) { + return true; + } + return false; +} + +void SCENE_OT_lanpr_export_svg(wmOperatorType *ot) +{ + PropertyRNA *prop; + + /* identifiers */ + ot->name = "Export LANPR to SVG"; + ot->description = "Export LANPR render result into a SVG file"; + ot->idname = "SCENE_OT_lanpr_export_svg"; + + /* callbacks */ + ot->exec = lanpr_export_svg_exec; + ot->poll = lanpr_render_buffer_found; + + /* flag */ + ot->flag = OPTYPE_USE_EVAL_DATA; + + /* properties */ + /* Should have: facing, layer, visibility, file split... */ +} + +/* Access */ + +bool ED_lanpr_dpix_shader_error() +{ + return lanpr_share.dpix_shader_error; +} +bool ED_lanpr_disable_edge_splits(Scene *s) +{ + return (s->lanpr.enabled && s->lanpr.disable_edge_splits); +} + +void ED_lanpr_copy_data(Scene *from, Scene *to) +{ + SceneLANPR *lanpr = &from->lanpr; + LANPR_RenderBuffer *rb = lanpr_share.render_buffer_shared, *new_rb; + LANPR_LineLayer *ll, *new_ll; + LANPR_LineLayerComponent *llc, *new_llc; + + list_handle_empty(&to->lanpr.line_layers); + + for (ll = lanpr->line_layers.first; ll; ll = ll->next) { + new_ll = MEM_callocN(sizeof(LANPR_LineLayer), "Copied Line Layer"); + memcpy(new_ll, ll, sizeof(LANPR_LineLayer)); + list_handle_empty(&new_ll->components); + new_ll->next = new_ll->prev = NULL; + BLI_addtail(&to->lanpr.line_layers, new_ll); + for (llc = ll->components.first; llc; llc = llc->next) { + new_llc = MEM_callocN(sizeof(LANPR_LineLayerComponent), "Copied Line Layer Component"); + memcpy(new_llc, llc, sizeof(LANPR_LineLayerComponent)); + new_llc->next = new_llc->prev = NULL; + BLI_addtail(&new_ll->components, new_llc); + } + } + + /* render_buffer now only accessible from lanpr_share */ +} + +void ED_lanpr_free_everything(Scene *s) +{ + SceneLANPR *lanpr = &s->lanpr; + LANPR_LineLayer *ll; + LANPR_LineLayerComponent *llc; + + while (ll = BLI_pophead(&lanpr->line_layers)) { + while (llc = BLI_pophead(&ll->components)) + MEM_freeN(llc); + MEM_freeN(ll); + } +} + +/* GPencil bindings */ + +static void lanpr_generate_gpencil_from_chain(Depsgraph *depsgraph, + Object *ob, + bGPDlayer *gpl, + bGPDframe *gpf, + int qi_begin, + int qi_end, + int material_nr, + Collection *col, + int types) +{ + Scene *scene = DEG_get_evaluated_scene(depsgraph); + LANPR_RenderBuffer *rb = lanpr_share.render_buffer_shared; + + if (rb == NULL) { + printf("NULL LANPR rb!\n"); + return; + } + if (scene->lanpr.master_mode != LANPR_MASTER_MODE_SOFTWARE) { + return; + } + + int color_idx = 0; + int tot_points = 0; + short thickness = 100; + + float mat[4][4]; + + unit_m4(mat); + + /* Split countour lines at occlution points and deselect occluded segment */ + LANPR_RenderLine *rl; + LANPR_RenderLineSegment *rls, *irls; + + LANPR_RenderLineChain *rlc; + LANPR_RenderLineChainItem *rlci; + for (rlc = rb->chains.first; rlc; rlc = rlc->next) { + + if (rlc->picked) { + continue; + } + if (ob && !rlc->object_ref) { + continue; /* intersection lines are all in the first collection running into here */ + } + if (!(rlc->type & types)) { + continue; + } + if (rlc->level > qi_end || rlc->level < qi_begin) { + continue; + } + if (ob && &ob->id != rlc->object_ref->id.orig_id) { + continue; + } + if (col && rlc->object_ref) { + if (!BKE_collection_has_object_recursive(col, (Object *)rlc->object_ref->id.orig_id)) { + continue; + } + } + + rlc->picked = 1; + + int array_idx = 0; + int count = ED_lanpr_count_chain(rlc); + bGPDstroke *gps = BKE_gpencil_add_stroke(gpf, color_idx, count, thickness); + + float *stroke_data = BLI_array_alloca(stroke_data, count * GP_PRIM_DATABUF_SIZE); + + for (rlci = rlc->chain.first; rlci; rlci = rlci->next) { + float opatity = 1.0f; /* rlci->occlusion ? 0.0f : 1.0f; */ + stroke_data[array_idx] = rlci->gpos[0]; + stroke_data[array_idx + 1] = rlci->gpos[1]; + stroke_data[array_idx + 2] = rlci->gpos[2]; + stroke_data[array_idx + 3] = 1; /* thickness */ + stroke_data[array_idx + 4] = opatity; /* hardness? */ + array_idx += 5; + } + + BKE_gpencil_stroke_add_points(gps, stroke_data, count, mat); + gps->mat_nr = material_nr; + } +} +static void lanpr_clear_gp_lanpr_flags(Depsgraph *dg, int frame) +{ + DEG_OBJECT_ITER_BEGIN (dg, + o, + DEG_ITER_OBJECT_FLAG_LINKED_DIRECTLY | DEG_ITER_OBJECT_FLAG_VISIBLE | + DEG_ITER_OBJECT_FLAG_DUPLI | DEG_ITER_OBJECT_FLAG_LINKED_VIA_SET) { + if (o->type == OB_GPENCIL) { + bGPdata *gpd = ((Object *)o->id.orig_id)->data; + bGPDlayer *gpl; + for (gpl = gpd->layers.first; gpl; gpl = gpl->next) { + bGPDframe *gpf = BKE_gpencil_layer_find_frame(gpl, frame); + if (!gpf) { + continue; + } + gpf->flag &= ~GP_FRAME_LANPR_CLEARED; + } + } + } + DEG_OBJECT_ITER_END; +} +static void lanpr_update_gp_strokes_recursive( + Depsgraph *dg, struct Collection *col, int frame, Object *source_only, Object *target_only) +{ + Object *ob; + Object *gpobj; + ModifierData *md; + bGPdata *gpd; + bGPDlayer *gpl; + bGPDframe *gpf; + CollectionObject *co; + CollectionChild *cc; + + for (co = col->gobject.first; co || source_only; co = co->next) { + ob = source_only ? source_only : co->ob; + for (md = ob->modifiers.first; md; md = md->next) { + if (md->type == eModifierType_FeatureLine) { + FeatureLineModifierData *flmd = (FeatureLineModifierData *)md; + if (flmd->target && flmd->target->type == OB_GPENCIL) { + gpobj = flmd->target; + + if (target_only && target_only != gpobj) { + continue; + } + + gpd = gpobj->data; + gpl = BKE_gpencil_layer_get_index(gpd, flmd->layer, 1); + if (!gpl) { + gpl = BKE_gpencil_layer_addnew(gpd, "lanpr_layer", true); + } + gpf = BKE_gpencil_layer_getframe(gpl, frame, GP_GETFRAME_ADD_NEW); + + if (gpf->strokes.first && + !lanpr_share.render_buffer_shared->scene->lanpr.gpencil_overwrite) { + continue; + } + + if (!(gpf->flag & GP_FRAME_LANPR_CLEARED)) { + BKE_gpencil_free_strokes(gpf); + gpf->flag |= GP_FRAME_LANPR_CLEARED; + } + + lanpr_generate_gpencil_from_chain(dg, + ob, + gpl, + gpf, + flmd->level_begin, + flmd->use_multiple_levels ? flmd->level_end : + flmd->level_begin, + flmd->material, + NULL, + flmd->types); + DEG_id_tag_update(&gpd->id, + ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_COPY_ON_WRITE); + } + } + } + if (source_only) { + return; + } + } + for (cc = col->children.first; cc; cc = cc->next) { + lanpr_update_gp_strokes_recursive(dg, cc->collection, frame, source_only, target_only); + } +} +static void lanpr_update_gp_strokes_collection( + Depsgraph *dg, struct Collection *col, int frame, int this_only, Object *target_only) +{ + Object *ob; + Object *gpobj; + ModifierData *md; + bGPdata *gpd; + bGPDlayer *gpl; + bGPDframe *gpf; + CollectionObject *co; + CollectionChild *cc; + + /* depth first */ + if (!this_only) { + for (cc = col->children.first; cc; cc = cc->next) { + lanpr_update_gp_strokes_collection(dg, cc->collection, frame, this_only, target_only); + } + } + + if (col->lanpr.usage != COLLECTION_LANPR_INCLUDE || !col->lanpr.target) { + return; + } + + gpobj = col->lanpr.target; + + if (target_only && target_only != gpobj) { + return; + } + + gpd = gpobj->data; + gpl = BKE_gpencil_layer_get_index(gpd, col->lanpr.layer, 1); + if (!gpl) { + gpl = BKE_gpencil_layer_addnew(gpd, "lanpr_layer", true); + } + gpf = BKE_gpencil_layer_getframe(gpl, frame, GP_GETFRAME_ADD_NEW); + + if (gpf->strokes.first && !lanpr_share.render_buffer_shared->scene->lanpr.gpencil_overwrite) { + return; + } + + if (!(gpf->flag & GP_FRAME_LANPR_CLEARED)) { + BKE_gpencil_free_strokes(gpf); + gpf->flag |= GP_FRAME_LANPR_CLEARED; + } + + lanpr_generate_gpencil_from_chain(dg, + NULL, + gpl, + gpf, + col->lanpr.level_begin, + col->lanpr.use_multiple_levels ? col->lanpr.level_end : + col->lanpr.level_begin, + col->lanpr.material, + col, + col->lanpr.types); + DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_COPY_ON_WRITE); +} +static void lanpr_update_gp_strokes_actual(Scene *scene, Depsgraph *dg) +{ + SceneLANPR *lanpr = &scene->lanpr; + int frame = scene->r.cfra; + + if (!lanpr_share.render_buffer_shared || + lanpr_share.render_buffer_shared->cached_for_frame != frame) { + ED_lanpr_compute_feature_lines_internal(dg, 0); + } + + ED_lanpr_chain_clear_picked_flag(lanpr_share.render_buffer_shared); + + lanpr_update_gp_strokes_recursive(dg, scene->master_collection, frame, NULL, NULL); + + lanpr_update_gp_strokes_collection(dg, scene->master_collection, frame, 0, NULL); + + lanpr_clear_gp_lanpr_flags(dg, frame); +} +static int lanpr_update_gp_strokes_exec(struct bContext *C, struct wmOperator *op) +{ + Scene *scene = CTX_data_scene(C); + Depsgraph *dg = CTX_data_depsgraph(C); + + lanpr_update_gp_strokes_actual(scene, dg); + + WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED | ND_SPACE_PROPERTIES, NULL); + + return OPERATOR_FINISHED; +} +static int lanpr_bake_gp_strokes_exec(struct bContext *C, struct wmOperator *op) +{ + Scene *scene = CTX_data_scene(C); + Depsgraph *dg = CTX_data_depsgraph(C); + SceneLANPR *lanpr = &scene->lanpr; + int frame, current_frame = scene->r.cfra; + int frame_begin = scene->r.sfra; + int frame_end = scene->r.efra; + + for (frame = frame_begin; frame <= frame_end; frame++) { + // BKE_scene_frame_set(scene,frame); + DEG_evaluate_on_framechange(CTX_data_main(C), dg, frame); + + ED_lanpr_compute_feature_lines_internal(dg, 0); + + ED_lanpr_chain_clear_picked_flag(lanpr_share.render_buffer_shared); + + lanpr_update_gp_strokes_recursive(dg, scene->master_collection, frame, NULL, NULL); + + lanpr_update_gp_strokes_collection(dg, scene->master_collection, frame, 0, NULL); + } + + WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED | ND_SPACE_PROPERTIES, NULL); + + return OPERATOR_FINISHED; +} +static int lanpr_update_gp_target_exec(struct bContext *C, struct wmOperator *op) +{ + Scene *scene = CTX_data_scene(C); + Depsgraph *dg = CTX_data_depsgraph(C); + SceneLANPR *lanpr = &scene->lanpr; + Object *gpo = CTX_data_active_object(C); + + int frame = scene->r.cfra; + + if (!lanpr_share.render_buffer_shared || + lanpr_share.render_buffer_shared->cached_for_frame != frame) { + ED_lanpr_compute_feature_lines_internal(dg, 0); + } + + ED_lanpr_chain_clear_picked_flag(lanpr_share.render_buffer_shared); + + lanpr_update_gp_strokes_recursive(dg, scene->master_collection, frame, NULL, gpo); + + lanpr_update_gp_strokes_collection(dg, scene->master_collection, frame, 0, gpo); + + lanpr_clear_gp_lanpr_flags(dg, frame); + + WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED | ND_SPACE_PROPERTIES, NULL); + + return OPERATOR_FINISHED; +} +static int lanpr_update_gp_source_exec(struct bContext *C, struct wmOperator *op) +{ + Scene *scene = CTX_data_scene(C); + Depsgraph *dg = CTX_data_depsgraph(C); + SceneLANPR *lanpr = &scene->lanpr; + Object *source_obj = CTX_data_active_object(C); + + int frame = scene->r.cfra; + + if (!lanpr_share.render_buffer_shared || + lanpr_share.render_buffer_shared->cached_for_frame != frame) { + ED_lanpr_compute_feature_lines_internal(dg, 0); + } + + ED_lanpr_chain_clear_picked_flag(lanpr_share.render_buffer_shared); + + lanpr_update_gp_strokes_recursive(dg, scene->master_collection, frame, source_obj, NULL); + + lanpr_update_gp_strokes_collection(dg, scene->master_collection, frame, 0, NULL); + + lanpr_clear_gp_lanpr_flags(dg, frame); + + WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED | ND_SPACE_PROPERTIES, NULL); + + return OPERATOR_FINISHED; +} + +static bool lanpr_active_is_gpencil_object(bContext *C) +{ + Object *o = CTX_data_active_object(C); + return o->type == OB_GPENCIL; +} +static bool lanpr_active_is_source_object(bContext *C) +{ + Object *o = CTX_data_active_object(C); + if (o->type != OB_MESH) { + return false; + } + else { + ModifierData *md; + for (md = o->modifiers.first; md; md = md->next) { + if (md->type == eModifierType_FeatureLine) { + return true; + } + } + } + return false; +} + +void SCENE_OT_lanpr_update_gp_strokes(struct wmOperatorType *ot) +{ + ot->name = "Update LANPR Strokes"; + ot->description = "Update strokes for LANPR grease pencil targets"; + ot->idname = "SCENE_OT_lanpr_update_gp_strokes"; + + ot->exec = lanpr_update_gp_strokes_exec; +} +void SCENE_OT_lanpr_bake_gp_strokes(struct wmOperatorType *ot) +{ + ot->name = "Bake LANPR Strokes"; + ot->description = "Bake strokes for LANPR grease pencil targets in all frames"; + ot->idname = "SCENE_OT_lanpr_bake_gp_strokes"; + + ot->exec = lanpr_bake_gp_strokes_exec; +} +void OBJECT_OT_lanpr_update_gp_target(struct wmOperatorType *ot) +{ + ot->name = "Update Strokes"; + ot->description = "Update LANPR strokes for selected GPencil object"; + ot->idname = "OBJECT_OT_lanpr_update_gp_target"; + + ot->poll = lanpr_active_is_gpencil_object; + ot->exec = lanpr_update_gp_target_exec; +} +/* Not working due to lack of GP flags for the object */ +void OBJECT_OT_lanpr_update_gp_source(struct wmOperatorType *ot) +{ + ot->name = "Update Strokes"; + ot->description = "Update LANPR strokes for selected Mesh object."; + ot->idname = "OBJECT_OT_lanpr_update_gp_source"; + + ot->poll = lanpr_active_is_source_object; + ot->exec = lanpr_update_gp_source_exec; +} + +/* Post-frame updater */ + +void ED_lanpr_post_frame_update_external(Scene *s, Depsgraph *dg) +{ + if (!s->lanpr.enabled || !s->lanpr.auto_update) { + return; + } + if (strcmp(s->r.engine, RE_engine_id_BLENDER_LANPR)) { + /* Not LANPR engine, do GPencil updates. */ + /* LANPR engine will automatically update when drawing the viewport. */ + if (!lanpr_share.render_buffer_shared || + lanpr_share.render_buffer_shared->cached_for_frame != s->r.cfra) { + ED_lanpr_compute_feature_lines_internal(dg, 0); + lanpr_update_gp_strokes_actual(s, dg); + } + } +} + +/* Inspect below */ +static void lanpr_post_frame_updater(struct Main *UNUSED(_1), struct ID *scene, void *UNUSED(_3)) +{ + Scene *s = (Scene *)scene; + if (s->lanpr.master_mode != LANPR_MASTER_MODE_SOFTWARE) { + return; + } + if (strcmp(s->r.engine, RE_engine_id_BLENDER_LANPR)) { + + /* No depsgraph reference here in the callback. Not working :? */ + } +} + +static bCallbackFuncStore lanpr_post_frame_callback = { + NULL, + NULL, /* next, prev */ + lanpr_post_frame_updater, /* func */ + NULL, /* arg */ + 0, /* alloc */ +}; + +static int lanpr_post_frame_regisetered = 0; + +void ED_register_lanpr_post_frame() +{ + if (!lanpr_post_frame_regisetered) { + BLI_callback_add(&lanpr_post_frame_callback, BLI_CB_EVT_FRAME_CHANGE_POST); + } +} diff --git a/source/blender/editors/lanpr/lanpr_ops.c b/source/blender/editors/lanpr/lanpr_ops.c index 33c041144a5..142ff131bab 100644 --- a/source/blender/editors/lanpr/lanpr_ops.c +++ b/source/blender/editors/lanpr/lanpr_ops.c @@ -1,4497 +1,39 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -/** \file - * \ingroup editor/lanpr - */ +#include <stdlib.h> -/* Test commit for investigating git problems. */ - -#include "ED_lanpr.h" - -#include "BLI_listbase.h" -#include "BLI_linklist.h" -#include "BLI_math_matrix.h" -#include "BLI_task.h" #include "BLI_utildefines.h" -#include "BLI_alloca.h" - -#include "BKE_object.h" -#include "DNA_mesh_types.h" -#include "DNA_camera_types.h" -#include "DNA_modifier_types.h" -#include "DNA_text_types.h" -#include "DNA_lanpr_types.h" -#include "DNA_scene_types.h" -#include "DNA_gpencil_types.h" -#include "DNA_meshdata_types.h" -#include "BKE_customdata.h" -#include "DEG_depsgraph_query.h" -#include "BKE_camera.h" -#include "BKE_gpencil.h" -#include "BKE_collection.h" -#include "BKE_report.h" -#include "BKE_screen.h" -#include "BKE_scene.h" -#include "BKE_text.h" -#include "BKE_context.h" -#include "MEM_guardedalloc.h" - -#include "RNA_access.h" -#include "RNA_define.h" - -#include "BLI_math.h" -#include "BLI_callbacks.h" -#include "BLI_string_utils.h" - -#include "bmesh.h" -#include "bmesh_class.h" -#include "bmesh_tools.h" -#include "WM_types.h" #include "WM_api.h" -#include "ED_svg.h" -#include "BKE_text.h" - -extern LANPR_SharedResource lanpr_share; -extern const char *RE_engine_id_BLENDER_LANPR; -struct Object; - -/* External defines */ - -void lanpr_rebuild_all_command(SceneLANPR *lanpr); - -/* Own functions */ - -static LANPR_BoundingArea *lanpr_get_first_possible_bounding_area(LANPR_RenderBuffer *rb, - LANPR_RenderLine *rl); - -static void lanpr_link_line_with_bounding_area(LANPR_RenderBuffer *rb, - LANPR_BoundingArea *RootBoundingArea, - LANPR_RenderLine *rl); - -static LANPR_BoundingArea *lanpr_get_next_bounding_area(LANPR_BoundingArea *This, - LANPR_RenderLine *rl, - real x, - real y, - real k, - int PositiveX, - int PositiveY, - real *NextX, - real *NextY); -static int lanpr_triangle_line_imagespace_intersection_v2(SpinLock *spl, - LANPR_RenderTriangle *rt, - LANPR_RenderLine *rl, - Object *cam, - tnsMatrix44d vp, - real *CameraDir, - double *From, - double *To); -static int lanpr_get_line_bounding_areas(LANPR_RenderBuffer *rb, - LANPR_RenderLine *rl, - int *rowBegin, - int *rowEnd, - int *colBegin, - int *colEnd); - -/* Layer operations */ - -static void lanpr_line_layer_unique_name(ListBase* list, LANPR_LineLayer* ll, const char *defname) -{ - BLI_uniquename(list,ll,defname,'.',offsetof(LANPR_LineLayer, name),sizeof(ll->name)); -} - -int ED_lanpr_max_occlusion_in_line_layers(SceneLANPR *lanpr) -{ - LANPR_LineLayer *lli; - int max_occ = -1, max; - for (lli = lanpr->line_layers.first; lli; lli = lli->next) { - if (lli->use_multiple_levels) { - max = MAX2(lli->qi_begin, lli->qi_end); - } - else { - max = lli->qi_begin; - } - max_occ = MAX2(max, max_occ); - } - return max_occ; -} -LANPR_LineLayer *ED_lanpr_new_line_layer(SceneLANPR *lanpr) -{ - LANPR_LineLayer *ll = MEM_callocN(sizeof(LANPR_LineLayer), "Line Layer"); - - lanpr_line_layer_unique_name(&lanpr->line_layers,ll,"Layer"); - - int max_occ = ED_lanpr_max_occlusion_in_line_layers(lanpr); - - ll->qi_begin = ll->qi_end = max_occ + 1; - ll->use_same_style = 1; - ll->thickness = 1.0f; - copy_v3_fl(ll->color, 0.8); - ll->color[3] = 1.0f; - ll->contour.enabled = 1; - ll->crease.enabled = 1; - ll->material_separate.enabled = 1; - ll->edge_mark.enabled = 1; - ll->intersection.enabled = 1; - - lanpr->active_layer = ll; - BLI_addtail(&lanpr->line_layers, ll); - - return ll; -} -LANPR_LineLayerComponent *ED_lanpr_new_line_component(SceneLANPR *lanpr) -{ - if (!lanpr->active_layer) { - return 0; - } - LANPR_LineLayer *ll = lanpr->active_layer; - - LANPR_LineLayerComponent *llc = MEM_callocN(sizeof(LANPR_LineLayerComponent), "Line Component"); - BLI_addtail(&ll->components, llc); - - return llc; -} -static int lanpr_add_line_layer_exec(struct bContext *C, struct wmOperator *UNUSED(op)) -{ - Scene *scene = CTX_data_scene(C); - SceneLANPR *lanpr = &scene->lanpr; - - ED_lanpr_new_line_layer(lanpr); - - DEG_id_tag_update(&scene->id, ID_RECALC_COPY_ON_WRITE); - - WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, NULL); - - return OPERATOR_FINISHED; -} -static int lanpr_delete_line_layer_exec(struct bContext *C, struct wmOperator *UNUSED(op)) -{ - Scene *scene = CTX_data_scene(C); - SceneLANPR *lanpr = &scene->lanpr; - - LANPR_LineLayer *ll = lanpr->active_layer; - - if (!ll) { - return OPERATOR_FINISHED; - } - - if (ll->prev) { - lanpr->active_layer = ll->prev; - } - else if (ll->next) { - lanpr->active_layer = ll->next; - } - else { - lanpr->active_layer = 0; - } - - BLI_remlink(&scene->lanpr.line_layers, ll); - - /* if (ll->batch) GPU_batch_discard(ll->batch); */ - - MEM_freeN(ll); - - DEG_id_tag_update(&scene->id, ID_RECALC_COPY_ON_WRITE); - - WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, NULL); - - return OPERATOR_FINISHED; -} -static int lanpr_move_line_layer_exec(struct bContext *C, struct wmOperator *op) -{ - Scene *scene = CTX_data_scene(C); - SceneLANPR *lanpr = &scene->lanpr; - - LANPR_LineLayer *ll = lanpr->active_layer; - - if (!ll) { - return OPERATOR_FINISHED; - } - - int dir = RNA_enum_get(op->ptr, "direction"); - - if (dir == 1 && ll->prev) { - BLI_remlink(&lanpr->line_layers, ll); - BLI_insertlinkbefore(&lanpr->line_layers, ll->prev, ll); - } - else if (dir == -1 && ll->next) { - BLI_remlink(&lanpr->line_layers, ll); - BLI_insertlinkafter(&lanpr->line_layers, ll->next, ll); - } - - DEG_id_tag_update(&scene->id, ID_RECALC_COPY_ON_WRITE); - - WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, NULL); - - return OPERATOR_FINISHED; -} -static int lanpr_add_line_component_exec(struct bContext *C, struct wmOperator *UNUSED(op)) -{ - Scene *scene = CTX_data_scene(C); - SceneLANPR *lanpr = &scene->lanpr; - - ED_lanpr_new_line_component(lanpr); - - return OPERATOR_FINISHED; -} -static int lanpr_delete_line_component_exec(struct bContext *C, struct wmOperator *op) -{ - Scene *scene = CTX_data_scene(C); - SceneLANPR *lanpr = &scene->lanpr; - LANPR_LineLayer *ll = lanpr->active_layer; - LANPR_LineLayerComponent *llc; - int i = 0; - - if (!ll) { - return OPERATOR_FINISHED; - } - - int index = RNA_int_get(op->ptr, "index"); - - for (llc = ll->components.first; llc; llc = llc->next) { - if (index == i) { - break; - } - i++; - } - - if (llc) { - BLI_remlink(&ll->components, llc); - MEM_freeN(llc); - } - - return OPERATOR_FINISHED; -} - -static int lanpr_rebuild_all_commands_exec(struct bContext *C, struct wmOperator *UNUSED(op)) -{ - Scene *scene = CTX_data_scene(C); - SceneLANPR *lanpr = &scene->lanpr; - - lanpr_rebuild_all_command(lanpr); - - DEG_id_tag_update(&scene->id, ID_RECALC_COPY_ON_WRITE); - - WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, NULL); - - return OPERATOR_FINISHED; -} -static int lanpr_enable_all_line_types_exec(struct bContext *C, struct wmOperator *UNUSED(op)) -{ - Scene *scene = CTX_data_scene(C); - SceneLANPR *lanpr = &scene->lanpr; - LANPR_LineLayer *ll; - - if (!(ll = lanpr->active_layer)) { - return OPERATOR_FINISHED; - } - - ll->contour.enabled = 1; - ll->crease.enabled = 1; - ll->edge_mark.enabled = 1; - ll->material_separate.enabled = 1; - ll->intersection.enabled = 1; - - copy_v3_v3(ll->contour.color, ll->color); - copy_v3_v3(ll->crease.color, ll->color); - copy_v3_v3(ll->edge_mark.color, ll->color); - copy_v3_v3(ll->material_separate.color, ll->color); - copy_v3_v3(ll->intersection.color, ll->color); - - ll->contour.thickness = 1; - ll->crease.thickness = 1; - ll->material_separate.thickness = 1; - ll->edge_mark.thickness = 1; - ll->intersection.thickness = 1; - - return OPERATOR_FINISHED; -} -static int lanpr_auto_create_line_layer_exec(struct bContext *C, struct wmOperator *op) -{ - Scene *scene = CTX_data_scene(C); - SceneLANPR *lanpr = &scene->lanpr; - - LANPR_LineLayer *ll; - - ll = ED_lanpr_new_line_layer(lanpr); - ll->thickness = 1.7; - - lanpr_enable_all_line_types_exec(C, op); - - ll = ED_lanpr_new_line_layer(lanpr); - ll->thickness = 0.9; - copy_v3_fl(ll->color, 0.6); - - lanpr_enable_all_line_types_exec(C, op); - - ll = ED_lanpr_new_line_layer(lanpr); - ll->thickness = 0.7; - copy_v3_fl(ll->color, 0.5); - - lanpr_enable_all_line_types_exec(C, op); - - lanpr_rebuild_all_command(lanpr); - - return OPERATOR_FINISHED; -} - -void SCENE_OT_lanpr_add_line_layer(struct wmOperatorType *ot) -{ - - ot->name = "Add Line Layer"; - ot->description = "Add a new line layer"; - ot->idname = "SCENE_OT_lanpr_add_line_layer"; - - ot->exec = lanpr_add_line_layer_exec; -} -void SCENE_OT_lanpr_delete_line_layer(struct wmOperatorType *ot) -{ - - ot->name = "Delete Line Layer"; - ot->description = "Delete selected line layer"; - ot->idname = "SCENE_OT_lanpr_delete_line_layer"; - - ot->exec = lanpr_delete_line_layer_exec; -} -void SCENE_OT_lanpr_rebuild_all_commands(struct wmOperatorType *ot) -{ - - ot->name = "Refresh Drawing Commands"; - ot->description = "Refresh LANPR line layer drawing commands"; - ot->idname = "SCENE_OT_lanpr_rebuild_all_commands"; - - ot->exec = lanpr_rebuild_all_commands_exec; -} -void SCENE_OT_lanpr_auto_create_line_layer(struct wmOperatorType *ot) -{ - - ot->name = "Auto Create Line Layer"; - ot->description = "Automatically create defalt line layer config"; - ot->idname = "SCENE_OT_lanpr_auto_create_line_layer"; - - ot->exec = lanpr_auto_create_line_layer_exec; -} -void SCENE_OT_lanpr_move_line_layer(struct wmOperatorType *ot) -{ - static const EnumPropertyItem line_layer_move[] = { - {1, "UP", 0, "Up", ""}, {-1, "DOWN", 0, "Down", ""}, {0, NULL, 0, NULL, NULL}}; - - ot->name = "Move Line Layer"; - ot->description = "Move LANPR line layer up and down"; - ot->idname = "SCENE_OT_lanpr_move_line_layer"; - - /* this need property to assign up/down direction */ - - ot->exec = lanpr_move_line_layer_exec; - - RNA_def_enum(ot->srna, - "direction", - line_layer_move, - 0, - "Direction", - "Direction to move the active line layer towards"); -} -void SCENE_OT_lanpr_enable_all_line_types(struct wmOperatorType *ot) -{ - ot->name = "Enable All Line Types"; - ot->description = "Enable All Line Types In This Line Layer"; - ot->idname = "SCENE_OT_lanpr_enable_all_line_types"; - - ot->exec = lanpr_enable_all_line_types_exec; -} -void SCENE_OT_lanpr_add_line_component(struct wmOperatorType *ot) -{ - - ot->name = "Add Line Component"; - ot->description = "Add a new line Component"; - ot->idname = "SCENE_OT_lanpr_add_line_component"; - - ot->exec = lanpr_add_line_component_exec; -} -void SCENE_OT_lanpr_delete_line_component(struct wmOperatorType *ot) -{ - - ot->name = "Delete Line Component"; - ot->description = "Delete selected line component"; - ot->idname = "SCENE_OT_lanpr_delete_line_component"; - - ot->exec = lanpr_delete_line_component_exec; - - RNA_def_int(ot->srna, "index", 0, 0, 10000, "index", "index of this line component", 0, 10000); -} - -/* Geometry */ - -int use_smooth_contour_modifier_contour = 0; /* debug purpose */ - -static void lanpr_cut_render_line(LANPR_RenderBuffer *rb, - LANPR_RenderLine *rl, - real Begin, - real End) -{ - LANPR_RenderLineSegment *rls = rl->segments.first, *irls; - LANPR_RenderLineSegment *begin_segment = 0, *end_segment = 0; - LANPR_RenderLineSegment *ns = 0, *ns2 = 0; - int untouched = 0; - - if (TNS_DOUBLE_CLOSE_ENOUGH(Begin, End)) { - return; - } - - if (Begin != Begin) { - Begin = 0; - } - if (End != End) { - End = 0; - } - - if (Begin > End) { - real t = Begin; - Begin = End; - End = t; - } - - for (rls = rl->segments.first; rls; rls = rls->next) { - if (TNS_DOUBLE_CLOSE_ENOUGH(rls->at, Begin)) { - begin_segment = rls; - ns = begin_segment; - break; - } - if (!rls->next) { - break; - } - irls = rls->next; - if (irls->at > Begin + 1e-09 && Begin > rls->at) { - begin_segment = irls; - ns = mem_static_aquire_thread(&rb->render_data_pool, sizeof(LANPR_RenderLineSegment)); - break; - } - } - if (!begin_segment && TNS_DOUBLE_CLOSE_ENOUGH(1, End)) { - untouched = 1; - } - for (rls = begin_segment; rls; rls = rls->next) { - if (TNS_DOUBLE_CLOSE_ENOUGH(rls->at, End)) { - end_segment = rls; - ns2 = end_segment; - break; - } - /* irls = rls->next; */ - /* added this to prevent rls->at == 1.0 (we don't need an end point for this) */ - if (!rls->next && TNS_DOUBLE_CLOSE_ENOUGH(1, End)) { - end_segment = rls; - ns2 = end_segment; - untouched = 1; - break; - } - else if (rls->at > End) { - end_segment = rls; - ns2 = mem_static_aquire_thread(&rb->render_data_pool, sizeof(LANPR_RenderLineSegment)); - break; - } - } - - if (!ns) { - ns = mem_static_aquire_thread(&rb->render_data_pool, sizeof(LANPR_RenderLineSegment)); - } - if (!ns2) { - if (untouched) { - ns2 = ns; - end_segment = ns2; - } - else - ns2 = mem_static_aquire_thread(&rb->render_data_pool, sizeof(LANPR_RenderLineSegment)); - } - - if (begin_segment) { - if (begin_segment != ns) { - ns->occlusion = begin_segment->prev ? (irls = begin_segment->prev)->occlusion : 0; - list_insert_item_before(&rl->segments, (void *)ns, (void *)begin_segment); - } - } - else { - ns->occlusion = (irls = rl->segments.last)->occlusion; - BLI_addtail(&rl->segments, ns); - } - if (end_segment) { - if (end_segment != ns2) { - ns2->occlusion = end_segment->prev ? (irls = end_segment->prev)->occlusion : 0; - list_insert_item_before(&rl->segments, (void *)ns2, (void *)end_segment); - } - } - else { - ns2->occlusion = (irls = rl->segments.last)->occlusion; - BLI_addtail(&rl->segments, ns2); - } - - ns->at = Begin; - if (!untouched) { - ns2->at = End; - } - else { - ns2 = ns2->next; - } - - for (rls = ns; rls && rls != ns2; rls = rls->next) { - rls->occlusion++; - } - - char min_occ = 127; - for (rls = rl->segments.first; rls; rls = rls->next) { - min_occ = MIN2(min_occ, rls->occlusion); - } - rl->min_occ = min_occ; -} -static int lanpr_make_next_occlusion_task_info(LANPR_RenderBuffer *rb, LANPR_RenderTaskInfo *rti) -{ - LinkData *data; - int i; - int res = 0; - - BLI_spin_lock(&rb->cs_management); - - if (rb->contour_managed) { - data = rb->contour_managed; - rti->contour = (void *)data; - rti->contour_pointers.first = data; - for (i = 0; i < TNS_THREAD_LINE_COUNT && data; i++) { - data = data->next; - } - rb->contour_managed = data; - rti->contour_pointers.last = data ? data->prev : rb->contours.last; - res = 1; - } - else { - list_handle_empty(&rti->contour_pointers); - rti->contour = 0; - } - - if (rb->intersection_managed) { - data = rb->intersection_managed; - rti->intersection = (void *)data; - rti->intersection_pointers.first = data; - for (i = 0; i < TNS_THREAD_LINE_COUNT && data; i++) { - data = data->next; - } - rb->intersection_managed = data; - rti->intersection_pointers.last = data ? data->prev : rb->intersection_lines.last; - res = 1; - } - else { - list_handle_empty(&rti->intersection_pointers); - rti->intersection = 0; - } - - if (rb->crease_managed) { - data = rb->crease_managed; - rti->crease = (void *)data; - rti->crease_pointers.first = data; - for (i = 0; i < TNS_THREAD_LINE_COUNT && data; i++) { - data = data->next; - } - rb->crease_managed = data; - rti->crease_pointers.last = data ? data->prev : rb->crease_lines.last; - res = 1; - } - else { - list_handle_empty(&rti->crease_pointers); - rti->crease = 0; - } - - if (rb->material_managed) { - data = rb->material_managed; - rti->material = (void *)data; - rti->material_pointers.first = data; - for (i = 0; i < TNS_THREAD_LINE_COUNT && data; i++) { - data = data->next; - } - rb->material_managed = data; - rti->material_pointers.last = data ? data->prev : rb->material_lines.last; - res = 1; - } - else { - list_handle_empty(&rti->material_pointers); - rti->material = 0; - } - - if (rb->edge_mark_managed) { - data = rb->edge_mark_managed; - rti->edge_mark = (void *)data; - rti->edge_mark_pointers.first = data; - for (i = 0; i < TNS_THREAD_LINE_COUNT && data; i++) { - data = data->next; - } - rb->edge_mark_managed = data; - rti->edge_mark_pointers.last = data ? data->prev : rb->edge_marks.last; - res = 1; - } - else { - list_handle_empty(&rti->edge_mark_pointers); - rti->edge_mark = 0; - } - - BLI_spin_unlock(&rb->cs_management); - - return res; -} -static void lanpr_calculate_single_line_occlusion(LANPR_RenderBuffer *rb, - LANPR_RenderLine *rl, - int thread_id) -{ - real x = rl->l->fbcoord[0], y = rl->l->fbcoord[1]; - LANPR_BoundingArea *ba = lanpr_get_first_possible_bounding_area(rb, rl); - LANPR_BoundingArea *nba = ba; - LANPR_RenderTriangleThread *rt; - LinkData *lip; - Object *c = rb->scene->camera; - real l, r; - real k = (rl->r->fbcoord[1] - rl->l->fbcoord[1]) / - (rl->r->fbcoord[0] - rl->l->fbcoord[0] + 1e-30); - int PositiveX = (rl->r->fbcoord[0] - rl->l->fbcoord[0]) > 0 ? - 1 : - (rl->r->fbcoord[0] == rl->l->fbcoord[0] ? 0 : -1); - int PositiveY = (rl->r->fbcoord[1] - rl->l->fbcoord[1]) > 0 ? - 1 : - (rl->r->fbcoord[1] == rl->l->fbcoord[1] ? 0 : -1); - - /* printf("PX %d %lf PY %d %lf\n", PositiveX, rl->r->fbcoord[0] - */ - /* rl->l->fbcoord[0], PositiveY, rl->r->fbcoord[1] - */ - /* rl->l->fbcoord[1]); */ - - while (nba) { - - for (lip = nba->linked_triangles.first; lip; lip = lip->next) { - rt = lip->data; - if (rt->testing[thread_id] == rl || rl->l->intersecting_with == (void *)rt || - rl->r->intersecting_with == (void *)rt) { - continue; - } - rt->testing[thread_id] = rl; - if (lanpr_triangle_line_imagespace_intersection_v2(&rb->cs_management, - (void *)rt, - rl, - c, - rb->view_projection, - rb->view_vector, - &l, - &r)) { - lanpr_cut_render_line(rb, rl, l, r); - if (rl->min_occ > rb->max_occlusion_level) { - return; /* No need to caluclate any longer. */ - } - } - } - - nba = lanpr_get_next_bounding_area(nba, rl, x, y, k, PositiveX, PositiveY, &x, &y); - } -} -static void lanpr_THREAD_calculate_line_occlusion(TaskPool *__restrict pool, - LANPR_RenderTaskInfo *rti, - int UNUSED(threadid)) -{ - LANPR_RenderBuffer *rb = lanpr_share.render_buffer_shared; - LinkData *lip; - - while (lanpr_make_next_occlusion_task_info(rb, rti)) { - - for (lip = (void *)rti->contour; lip && lip->prev != rti->contour_pointers.last; - lip = lip->next) { - lanpr_calculate_single_line_occlusion(rb, lip->data, rti->thread_id); - } - - for (lip = (void *)rti->crease; lip && lip->prev != rti->crease_pointers.last; - lip = lip->next) { - lanpr_calculate_single_line_occlusion(rb, lip->data, rti->thread_id); - } - - for (lip = (void *)rti->intersection; lip && lip->prev != rti->intersection_pointers.last; - lip = lip->next) { - lanpr_calculate_single_line_occlusion(rb, lip->data, rti->thread_id); - } - - for (lip = (void *)rti->material; lip && lip->prev != rti->material_pointers.last; - lip = lip->next) { - lanpr_calculate_single_line_occlusion(rb, lip->data, rti->thread_id); - } - - for (lip = (void *)rti->edge_mark; lip && lip->prev != rti->edge_mark_pointers.last; - lip = lip->next) { - lanpr_calculate_single_line_occlusion(rb, lip->data, rti->thread_id); - } - } -} -static void lanpr_THREAD_calculate_line_occlusion_begin(LANPR_RenderBuffer *rb) -{ - int thread_count = rb->thread_count; - LANPR_RenderTaskInfo *rti = MEM_callocN(sizeof(LANPR_RenderTaskInfo) * thread_count, - "Task Pool"); - TaskScheduler *scheduler = BLI_task_scheduler_get(); - int i; - - rb->contour_managed = rb->contours.first; - rb->crease_managed = rb->crease_lines.first; - rb->intersection_managed = rb->intersection_lines.first; - rb->material_managed = rb->material_lines.first; - rb->edge_mark_managed = rb->edge_marks.first; - - TaskPool *tp = BLI_task_pool_create(scheduler, 0); - - for (i = 0; i < thread_count; i++) { - rti[i].thread_id = i; - BLI_task_pool_push(tp, (TaskRunFunction)lanpr_THREAD_calculate_line_occlusion, &rti[i], 0, TASK_PRIORITY_HIGH); - } - BLI_task_pool_work_and_wait(tp); - BLI_task_pool_free(tp); - - MEM_freeN(rti); -} - -int ED_lanpr_point_inside_triangled(tnsVector2d v, tnsVector2d v0, tnsVector2d v1, tnsVector2d v2) -{ - double cl, c; - - cl = (v0[0] - v[0]) * (v1[1] - v[1]) - (v0[1] - v[1]) * (v1[0] - v[0]); - c = cl; - - cl = (v1[0] - v[0]) * (v2[1] - v[1]) - (v1[1] - v[1]) * (v2[0] - v[0]); - if (c * cl <= 0) { - return 0; - } - else - c = cl; - - cl = (v2[0] - v[0]) * (v0[1] - v[1]) - (v2[1] - v[1]) * (v0[0] - v[0]); - if (c * cl <= 0) { - return 0; - } - else - c = cl; - - cl = (v0[0] - v[0]) * (v1[1] - v[1]) - (v0[1] - v[1]) * (v1[0] - v[0]); - if (c * cl <= 0) { - return 0; - } - - return 1; -} -static int lanpr_point_on_lined(tnsVector2d v, tnsVector2d v0, tnsVector2d v1) -{ - real c1, c2; - - c1 = tMatGetLinearRatio(v0[0], v1[0], v[0]); - c2 = tMatGetLinearRatio(v0[1], v1[1], v[1]); - - if (TNS_DOUBLE_CLOSE_ENOUGH(c1, c2) && c1 >= 0 && c1 <= 1) { - return 1; - } - - return 0; -} -static int lanpr_point_triangle_relation(tnsVector2d v, - tnsVector2d v0, - tnsVector2d v1, - tnsVector2d v2) -{ - double cl, c; - real r; - if (lanpr_point_on_lined(v, v0, v1) || lanpr_point_on_lined(v, v1, v2) || - lanpr_point_on_lined(v, v2, v0)) { - return 1; - } - - cl = (v0[0] - v[0]) * (v1[1] - v[1]) - (v0[1] - v[1]) * (v1[0] - v[0]); - c = cl; - - cl = (v1[0] - v[0]) * (v2[1] - v[1]) - (v1[1] - v[1]) * (v2[0] - v[0]); - if ((r = c * cl) < 0) { - return 0; - } - /* else if(r == 0) return 1; // removed, point could still be on the extention line of some edge - */ - else - c = cl; - - cl = (v2[0] - v[0]) * (v0[1] - v[1]) - (v2[1] - v[1]) * (v0[0] - v[0]); - if ((r = c * cl) < 0) { - return 0; - } - /* else if(r == 0) return 1; */ - else - c = cl; - - cl = (v0[0] - v[0]) * (v1[1] - v[1]) - (v0[1] - v[1]) * (v1[0] - v[0]); - if ((r = c * cl) < 0) { - return 0; - } - else if (r == 0) { - return 1; - } - - return 2; -} -static int lanpr_point_inside_triangle3de(tnsVector3d v, - tnsVector3d v0, - tnsVector3d v1, - tnsVector3d v2) -{ - tnsVector3d l, r; - tnsVector3d N1, N2; - real d; - - tMatVectorMinus3d(l, v1, v0); - tMatVectorMinus3d(r, v, v1); - /* tmat_normalize_self_3d(l); */ - /* tmat_normalize_self_3d(r); */ - tmat_vector_cross_3d(N1, l, r); - - tMatVectorMinus3d(l, v2, v1); - tMatVectorMinus3d(r, v, v2); - /* tmat_normalize_self_3d(l); */ - /* tmat_normalize_self_3d(r); */ - tmat_vector_cross_3d(N2, l, r); - - if ((d = tmat_dot_3d(N1, N2, 0)) < 0) { - return 0; - } - /* if (d<DBL_EPSILON) return -1; */ - - tMatVectorMinus3d(l, v0, v2); - tMatVectorMinus3d(r, v, v0); - /* tmat_normalize_self_3d(l); */ - /* tmat_normalize_self_3d(r); */ - tmat_vector_cross_3d(N1, l, r); - - if ((d = tmat_dot_3d(N1, N2, 0)) < 0) { - return 0; - } - /* if (d<DBL_EPSILON) return -1; */ - - tMatVectorMinus3d(l, v1, v0); - tMatVectorMinus3d(r, v, v1); - /* tmat_normalize_self_3d(l); */ - /* tmat_normalize_self_3d(r); */ - tmat_vector_cross_3d(N2, l, r); - - if ((d = tmat_dot_3d(N1, N2, 0)) < 0) { - return 0; - } - /* if (d<DBL_EPSILON) return -1; */ - - return 1; -} - -static LANPR_RenderElementLinkNode *lanpr_new_cull_triangle_space64(LANPR_RenderBuffer *rb) -{ - LANPR_RenderElementLinkNode *reln; - - LANPR_RenderTriangle *RenderTriangles = mem_static_aquire( - &rb->render_data_pool, - 64 * rb->triangle_size); /* CreateNewBuffer(LANPR_RenderTriangle, 64); */ - - reln = list_append_pointer_static_sized(&rb->triangle_buffer_pointers, - &rb->render_data_pool, - RenderTriangles, - sizeof(LANPR_RenderElementLinkNode)); - reln->element_count = 64; - reln->additional = 1; - - return reln; -} -static LANPR_RenderElementLinkNode *lanpr_new_cull_point_space64(LANPR_RenderBuffer *rb) -{ - LANPR_RenderElementLinkNode *reln; - - LANPR_RenderVert *Rendervertices = mem_static_aquire( - &rb->render_data_pool, - sizeof(LANPR_RenderVert) * 64); /* CreateNewBuffer(LANPR_RenderVert, 64); */ - - reln = list_append_pointer_static_sized(&rb->vertex_buffer_pointers, - &rb->render_data_pool, - Rendervertices, - sizeof(LANPR_RenderElementLinkNode)); - reln->element_count = 64; - reln->additional = 1; - - return reln; -} -static void lanpr_calculate_render_triangle_normal(LANPR_RenderTriangle *rt); -static void lanpr_assign_render_line_with_triangle(LANPR_RenderTriangle *rt) -{ - if (!rt->rl[0]->tl) { - rt->rl[0]->tl = rt; - } - else if (!rt->rl[0]->tr) { - rt->rl[0]->tr = rt; - } - - if (!rt->rl[1]->tl) { - rt->rl[1]->tl = rt; - } - else if (!rt->rl[1]->tr) { - rt->rl[1]->tr = rt; - } - - if (!rt->rl[2]->tl) { - rt->rl[2]->tl = rt; - } - else if (!rt->rl[2]->tr) { - rt->rl[2]->tr = rt; - } -} -static void lanpr_post_triangle(LANPR_RenderTriangle *rt, LANPR_RenderTriangle *orig) -{ - if (rt->v[0]) { - tMatVectorAccum3d(rt->gc, rt->v[0]->fbcoord); - } - if (rt->v[1]) { - tMatVectorAccum3d(rt->gc, rt->v[1]->fbcoord); - } - if (rt->v[2]) { - tMatVectorAccum3d(rt->gc, rt->v[2]->fbcoord); - } - tMatVectorMultiSelf3d(rt->gc, 1.0f / 3.0f); - - tMatVectorCopy3d(orig->gn, rt->gn); -} - -#define RT_AT(head, rb, offset) ((BYTE *)head + offset * rb->triangle_size) - -static void lanpr_cull_triangles(LANPR_RenderBuffer *rb) -{ - LANPR_RenderLine *rl; - LANPR_RenderTriangle *rt, *rt1, *rt2; - LANPR_RenderVert *rv; - LANPR_RenderElementLinkNode *reln, *veln, *teln; - LANPR_RenderLineSegment *rls; - real *vp = rb->view_projection; - int i; - real a; - int v_count = 0, t_count = 0; - Object *o; - - real cam_pos[3]; - Object *cam = ((Object *)rb->scene->camera); - cam_pos[0] = cam->obmat[3][0]; - cam_pos[1] = cam->obmat[3][1]; - cam_pos[2] = cam->obmat[3][2]; - - real view_dir[3], clip_advance[3]; - tMatVectorCopy3d(rb->view_vector, view_dir); - tMatVectorCopy3d(rb->view_vector, clip_advance); - tMatVectorMultiSelf3d(clip_advance, -((Camera *)cam->data)->clip_start); - tMatVectorAccum3d(cam_pos, clip_advance); - - veln = lanpr_new_cull_point_space64(rb); - teln = lanpr_new_cull_triangle_space64(rb); - rv = &((LANPR_RenderVert *)veln->pointer)[v_count]; - rt1 = (void *)(((BYTE *)teln->pointer) + rb->triangle_size * t_count); - - for (reln = rb->triangle_buffer_pointers.first; reln; reln = reln->next) { - if (reln->additional) { - continue; - } - o = reln->object_ref; - for (i = 0; i < reln->element_count; i++) { - int In1 = 0, In2 = 0, In3 = 0; - rt = (void *)(((BYTE *)reln->pointer) + rb->triangle_size * i); - if (rt->v[0]->fbcoord[3] < ((Camera *)cam->data)->clip_start) { - In1 = 1; - } - if (rt->v[1]->fbcoord[3] < ((Camera *)cam->data)->clip_start) { - In2 = 1; - } - if (rt->v[2]->fbcoord[3] < ((Camera *)cam->data)->clip_start) { - In3 = 1; - } - - if (v_count > 60) { - veln->element_count = v_count; - veln = lanpr_new_cull_point_space64(rb); - v_count = 0; - } - - if (t_count > 60) { - teln->element_count = t_count; - teln = lanpr_new_cull_triangle_space64(rb); - t_count = 0; - } - - /* if ((!rt->rl[0]->next && !rt->rl[0]->prev) || */ - /* (!rt->rl[1]->next && !rt->rl[1]->prev) || */ - /* (!rt->rl[2]->next && !rt->rl[2]->prev)) { */ - /* printf("'"); // means this triangle is lonely???? */ - /* } */ - - rv = &((LANPR_RenderVert *)veln->pointer)[v_count]; - rt1 = (void *)(((BYTE *)teln->pointer) + rb->triangle_size * t_count); - rt2 = (void *)(((BYTE *)teln->pointer) + rb->triangle_size * (t_count + 1)); - - real vv1[3], vv2[3], dot1, dot2; - - switch (In1 + In2 + In3) { - case 0: - continue; - case 3: - rt->cull_status = LANPR_CULL_DISCARD; - BLI_remlink(&rb->all_render_lines, (void *)rt->rl[0]); - rt->rl[0]->next = rt->rl[0]->prev = 0; - BLI_remlink(&rb->all_render_lines, (void *)rt->rl[1]); - rt->rl[1]->next = rt->rl[1]->prev = 0; - BLI_remlink(&rb->all_render_lines, (void *)rt->rl[2]); - rt->rl[2]->next = rt->rl[2]->prev = 0; - continue; - case 2: - rt->cull_status = LANPR_CULL_USED; - if (!In1) { - tMatVectorMinus3d(vv1, rt->v[0]->gloc, cam_pos); - tMatVectorMinus3d(vv2, cam_pos, rt->v[2]->gloc); - dot1 = tmat_dot_3d(vv1, view_dir, 0); - dot2 = tmat_dot_3d(vv2, view_dir, 0); - a = dot1 / (dot1 + dot2); - interp_v3_v3v3_db(rv[0].gloc, rt->v[0]->gloc, rt->v[2]->gloc, a); - tmat_apply_transform_44d(rv[0].fbcoord, vp, rv[0].gloc); - - tMatVectorMinus3d(vv1, rt->v[0]->gloc, cam_pos); - tMatVectorMinus3d(vv2, cam_pos, rt->v[1]->gloc); - dot1 = tmat_dot_3d(vv1, view_dir, 0); - dot2 = tmat_dot_3d(vv2, view_dir, 0); - a = dot1 / (dot1 + dot2); - interp_v3_v3v3_db(rv[1].gloc, rt->v[0]->gloc, rt->v[1]->gloc, a); - tmat_apply_transform_44d(rv[1].fbcoord, vp, rv[1].gloc); - - BLI_remlink(&rb->all_render_lines, (void *)rt->rl[0]); - rt->rl[0]->next = rt->rl[0]->prev = 0; - BLI_remlink(&rb->all_render_lines, (void *)rt->rl[1]); - rt->rl[1]->next = rt->rl[1]->prev = 0; - BLI_remlink(&rb->all_render_lines, (void *)rt->rl[2]); - rt->rl[2]->next = rt->rl[2]->prev = 0; - - rl = mem_static_aquire(&rb->render_data_pool, sizeof(LANPR_RenderLine)); - rls = mem_static_aquire(&rb->render_data_pool, sizeof(LANPR_RenderLineSegment)); - BLI_addtail(&rl->segments, rls); - BLI_addtail(&rb->all_render_lines, rl); - rl->l = &rv[1]; - rl->r = &rv[0]; - rl->tl = rt1; - rt1->rl[1] = rl; - rl->object_ref = o; - - rl = mem_static_aquire(&rb->render_data_pool, sizeof(LANPR_RenderLine)); - rls = mem_static_aquire(&rb->render_data_pool, sizeof(LANPR_RenderLineSegment)); - BLI_addtail(&rl->segments, rls); - BLI_addtail(&rb->all_render_lines, rl); - rl->l = &rv[1]; - rl->r = rt->v[0]; - rl->tl = rt->rl[0]->tl == rt ? rt1 : rt->rl[0]->tl; - rl->tr = rt->rl[0]->tr == rt ? rt1 : rt->rl[0]->tr; - rt1->rl[0] = rl; - rl->object_ref = o; - - rl = mem_static_aquire(&rb->render_data_pool, sizeof(LANPR_RenderLine)); - rls = mem_static_aquire(&rb->render_data_pool, sizeof(LANPR_RenderLineSegment)); - BLI_addtail(&rl->segments, rls); - BLI_addtail(&rb->all_render_lines, rl); - rl->l = rt->v[0]; - rl->r = &rv[0]; - rl->tl = rt->rl[2]->tl == rt ? rt1 : rt->rl[2]->tl; - rl->tr = rt->rl[2]->tr == rt ? rt1 : rt->rl[2]->tr; - rt1->rl[2] = rl; - rl->object_ref = o; - - rt1->v[0] = rt->v[0]; - rt1->v[1] = &rv[1]; - rt1->v[2] = &rv[0]; - - lanpr_post_triangle(rt1, rt); - - v_count += 2; - t_count += 1; - continue; - } - else if (!In3) { - tMatVectorMinus3d(vv1, rt->v[2]->gloc, cam_pos); - tMatVectorMinus3d(vv2, cam_pos, rt->v[0]->gloc); - dot1 = tmat_dot_3d(vv1, view_dir, 0); - dot2 = tmat_dot_3d(vv2, view_dir, 0); - a = dot1 / (dot1 + dot2); - interp_v3_v3v3_db(rv[0].gloc, rt->v[2]->gloc, rt->v[0]->gloc, a); - tmat_apply_transform_44d(rv[0].fbcoord, vp, rv[0].gloc); - - tMatVectorMinus3d(vv1, rt->v[2]->gloc, cam_pos); - tMatVectorMinus3d(vv2, cam_pos, rt->v[1]->gloc); - dot1 = tmat_dot_3d(vv1, view_dir, 0); - dot2 = tmat_dot_3d(vv2, view_dir, 0); - a = dot1 / (dot1 + dot2); - interp_v3_v3v3_db(rv[1].gloc, rt->v[2]->gloc, rt->v[1]->gloc, a); - tmat_apply_transform_44d(rv[1].fbcoord, vp, rv[1].gloc); - - BLI_remlink(&rb->all_render_lines, (void *)rt->rl[0]); - rt->rl[0]->next = rt->rl[0]->prev = 0; - BLI_remlink(&rb->all_render_lines, (void *)rt->rl[1]); - rt->rl[1]->next = rt->rl[1]->prev = 0; - BLI_remlink(&rb->all_render_lines, (void *)rt->rl[2]); - rt->rl[2]->next = rt->rl[2]->prev = 0; - - rl = mem_static_aquire(&rb->render_data_pool, sizeof(LANPR_RenderLine)); - rls = mem_static_aquire(&rb->render_data_pool, sizeof(LANPR_RenderLineSegment)); - BLI_addtail(&rl->segments, rls); - BLI_addtail(&rb->all_render_lines, rl); - rl->l = &rv[0]; - rl->r = &rv[1]; - rl->tl = rt1; - rt1->rl[0] = rl; - rl->object_ref = o; - - rl = mem_static_aquire(&rb->render_data_pool, sizeof(LANPR_RenderLine)); - rls = mem_static_aquire(&rb->render_data_pool, sizeof(LANPR_RenderLineSegment)); - BLI_addtail(&rl->segments, rls); - BLI_addtail(&rb->all_render_lines, rl); - rl->l = &rv[1]; - rl->r = rt->v[2]; - rl->tl = rt->rl[1]->tl == rt ? rt1 : rt->rl[1]->tl; - rl->tr = rt->rl[1]->tr == rt ? rt1 : rt->rl[1]->tr; - rt1->rl[1] = rl; - rl->object_ref = o; - - rl = mem_static_aquire(&rb->render_data_pool, sizeof(LANPR_RenderLine)); - rls = mem_static_aquire(&rb->render_data_pool, sizeof(LANPR_RenderLineSegment)); - BLI_addtail(&rl->segments, rls); - BLI_addtail(&rb->all_render_lines, rl); - rl->l = rt->v[2]; - rl->r = &rv[0]; - rl->tl = rt->rl[2]->tl == rt ? rt1 : rt->rl[2]->tl; - rl->tr = rt->rl[2]->tr == rt ? rt1 : rt->rl[2]->tr; - rt1->rl[2] = rl; - rl->object_ref = o; - - rt1->v[0] = &rv[1]; - rt1->v[1] = rt->v[2]; - rt1->v[2] = &rv[0]; - - lanpr_post_triangle(rt1, rt); - - v_count += 2; - t_count += 1; - continue; - } - else if (!In2) { - tMatVectorMinus3d(vv1, rt->v[1]->gloc, cam_pos); - tMatVectorMinus3d(vv2, cam_pos, rt->v[2]->gloc); - dot1 = tmat_dot_3d(vv1, view_dir, 0); - dot2 = tmat_dot_3d(vv2, view_dir, 0); - a = dot1 / (dot1 + dot2); - interp_v3_v3v3_db(rv[0].gloc, rt->v[1]->gloc, rt->v[2]->gloc, a); - tmat_apply_transform_44d(rv[0].fbcoord, vp, rv[0].gloc); - - tMatVectorMinus3d(vv1, rt->v[1]->gloc, cam_pos); - tMatVectorMinus3d(vv2, cam_pos, rt->v[0]->gloc); - dot1 = tmat_dot_3d(vv1, view_dir, 0); - dot2 = tmat_dot_3d(vv2, view_dir, 0); - a = dot1 / (dot1 + dot2); - interp_v3_v3v3_db(rv[1].gloc, rt->v[1]->gloc, rt->v[0]->gloc, a); - tmat_apply_transform_44d(rv[1].fbcoord, vp, rv[1].gloc); - - BLI_remlink(&rb->all_render_lines, (void *)rt->rl[0]); - rt->rl[0]->next = rt->rl[0]->prev = 0; - BLI_remlink(&rb->all_render_lines, (void *)rt->rl[1]); - rt->rl[1]->next = rt->rl[1]->prev = 0; - BLI_remlink(&rb->all_render_lines, (void *)rt->rl[2]); - rt->rl[2]->next = rt->rl[2]->prev = 0; - - rl = mem_static_aquire(&rb->render_data_pool, sizeof(LANPR_RenderLine)); - rls = mem_static_aquire(&rb->render_data_pool, sizeof(LANPR_RenderLineSegment)); - BLI_addtail(&rl->segments, rls); - BLI_addtail(&rb->all_render_lines, rl); - rl->l = &rv[1]; - rl->r = &rv[0]; - rl->tl = rt1; - rt1->rl[2] = rl; - rl->object_ref = o; - - rl = mem_static_aquire(&rb->render_data_pool, sizeof(LANPR_RenderLine)); - rls = mem_static_aquire(&rb->render_data_pool, sizeof(LANPR_RenderLineSegment)); - BLI_addtail(&rl->segments, rls); - BLI_addtail(&rb->all_render_lines, rl); - rl->l = &rv[0]; - rl->r = rt->v[1]; - rl->tl = rt->rl[0]->tl == rt ? rt1 : rt->rl[0]->tl; - rl->tr = rt->rl[0]->tr == rt ? rt1 : rt->rl[0]->tr; - rt1->rl[0] = rl; - rl->object_ref = o; - - rl = mem_static_aquire(&rb->render_data_pool, sizeof(LANPR_RenderLine)); - rls = mem_static_aquire(&rb->render_data_pool, sizeof(LANPR_RenderLineSegment)); - BLI_addtail(&rl->segments, rls); - BLI_addtail(&rb->all_render_lines, rl); - rl->l = rt->v[1]; - rl->r = &rv[1]; - rl->tl = rt->rl[1]->tl == rt ? rt1 : rt->rl[1]->tl; - rl->tr = rt->rl[1]->tr == rt ? rt1 : rt->rl[1]->tr; - rt1->rl[1] = rl; - rl->object_ref = o; - - rt1->v[0] = rt->v[1]; - rt1->v[1] = &rv[1]; - rt1->v[2] = &rv[0]; - - lanpr_post_triangle(rt1, rt); - - v_count += 2; - t_count += 1; - continue; - } - break; - case 1: - rt->cull_status = LANPR_CULL_USED; - if (In1) { - tMatVectorMinus3d(vv1, rt->v[1]->gloc, cam_pos); - tMatVectorMinus3d(vv2, cam_pos, rt->v[0]->gloc); - dot1 = tmat_dot_3d(vv1, view_dir, 0); - dot2 = tmat_dot_3d(vv2, view_dir, 0); - a = dot2 / (dot1 + dot2); - interp_v3_v3v3_db(rv[0].gloc, rt->v[0]->gloc, rt->v[1]->gloc, a); - tmat_apply_transform_44d(rv[0].fbcoord, vp, rv[0].gloc); - - tMatVectorMinus3d(vv1, rt->v[2]->gloc, cam_pos); - tMatVectorMinus3d(vv2, cam_pos, rt->v[0]->gloc); - dot1 = tmat_dot_3d(vv1, view_dir, 0); - dot2 = tmat_dot_3d(vv2, view_dir, 0); - a = dot2 / (dot1 + dot2); - interp_v3_v3v3_db(rv[1].gloc, rt->v[0]->gloc, rt->v[2]->gloc, a); - tmat_apply_transform_44d(rv[1].fbcoord, vp, rv[1].gloc); - - BLI_remlink(&rb->all_render_lines, (void *)rt->rl[0]); - rt->rl[0]->next = rt->rl[0]->prev = 0; - BLI_remlink(&rb->all_render_lines, (void *)rt->rl[2]); - rt->rl[2]->next = rt->rl[2]->prev = 0; - - rl = mem_static_aquire(&rb->render_data_pool, sizeof(LANPR_RenderLine)); - rls = mem_static_aquire(&rb->render_data_pool, sizeof(LANPR_RenderLineSegment)); - BLI_addtail(&rl->segments, rls); - BLI_addtail(&rb->all_render_lines, rl); - rl->l = &rv[1]; - rl->r = &rv[0]; - rl->tl = rt1; - rt1->rl[1] = rl; - rl->object_ref = o; - - rl = mem_static_aquire(&rb->render_data_pool, sizeof(LANPR_RenderLine)); - rls = mem_static_aquire(&rb->render_data_pool, sizeof(LANPR_RenderLineSegment)); - BLI_addtail(&rl->segments, rls); - BLI_addtail(&rb->all_render_lines, rl); - rl->l = &rv[0]; - rl->r = rt->v[1]; - rl->tl = rt1; - rl->tr = rt->rl[0]->tr == rt ? rt->rl[0]->tl : rt->rl[0]->tr; - rt1->rl[2] = rl; - rl->object_ref = o; - - rl = mem_static_aquire(&rb->render_data_pool, sizeof(LANPR_RenderLine)); - rls = mem_static_aquire(&rb->render_data_pool, sizeof(LANPR_RenderLineSegment)); - BLI_addtail(&rl->segments, rls); - BLI_addtail(&rb->all_render_lines, rl); - rl->l = rt->v[1]; - rl->r = &rv[1]; - rl->tl = rt1; - rl->tr = rt2; - rt1->rl[0] = rl; - rt2->rl[0] = rl; - rl->object_ref = o; - - rt1->v[0] = rt->v[1]; - rt1->v[1] = &rv[1]; - rt1->v[2] = &rv[0]; - - rl = mem_static_aquire(&rb->render_data_pool, sizeof(LANPR_RenderLine)); - rls = mem_static_aquire(&rb->render_data_pool, sizeof(LANPR_RenderLineSegment)); - BLI_addtail(&rl->segments, rls); - BLI_addtail(&rb->all_render_lines, rl); - rl->l = rt->v[2]; - rl->r = &rv[1]; - rl->tl = rt2; - rl->tr = rt->rl[2]->tr == rt ? rt->rl[2]->tl : rt->rl[2]->tr; - rt2->rl[2] = rl; - rt2->rl[1] = rt->rl[1]; - rl->object_ref = o; - - rt2->v[0] = &rv[1]; - rt2->v[1] = rt->v[1]; - rt2->v[2] = rt->v[2]; - - lanpr_post_triangle(rt1, rt); - lanpr_post_triangle(rt2, rt); - - v_count += 2; - t_count += 2; - continue; - } - else if (In2) { - - tMatVectorMinus3d(vv1, rt->v[1]->gloc, cam_pos); - tMatVectorMinus3d(vv2, cam_pos, rt->v[2]->gloc); - dot1 = tmat_dot_3d(vv1, view_dir, 0); - dot2 = tmat_dot_3d(vv2, view_dir, 0); - a = dot1 / (dot1 + dot2); - interp_v3_v3v3_db(rv[0].gloc, rt->v[1]->gloc, rt->v[2]->gloc, a); - tmat_apply_transform_44d(rv[0].fbcoord, vp, rv[0].gloc); - - tMatVectorMinus3d(vv1, rt->v[1]->gloc, cam_pos); - tMatVectorMinus3d(vv2, cam_pos, rt->v[0]->gloc); - dot1 = tmat_dot_3d(vv1, view_dir, 0); - dot2 = tmat_dot_3d(vv2, view_dir, 0); - a = dot1 / (dot1 + dot2); - interp_v3_v3v3_db(rv[1].gloc, rt->v[1]->gloc, rt->v[0]->gloc, a); - tmat_apply_transform_44d(rv[1].fbcoord, vp, rv[1].gloc); - - BLI_remlink(&rb->all_render_lines, (void *)rt->rl[0]); - rt->rl[0]->next = rt->rl[0]->prev = 0; - BLI_remlink(&rb->all_render_lines, (void *)rt->rl[1]); - rt->rl[1]->next = rt->rl[1]->prev = 0; - - rl = mem_static_aquire(&rb->render_data_pool, sizeof(LANPR_RenderLine)); - rls = mem_static_aquire(&rb->render_data_pool, sizeof(LANPR_RenderLineSegment)); - BLI_addtail(&rl->segments, rls); - BLI_addtail(&rb->all_render_lines, rl); - rl->l = &rv[1]; - rl->r = &rv[0]; - rl->tl = rt1; - rt1->rl[1] = rl; - rl->object_ref = o; - - rl = mem_static_aquire(&rb->render_data_pool, sizeof(LANPR_RenderLine)); - rls = mem_static_aquire(&rb->render_data_pool, sizeof(LANPR_RenderLineSegment)); - BLI_addtail(&rl->segments, rls); - BLI_addtail(&rb->all_render_lines, rl); - rl->l = &rv[0]; - rl->r = rt->v[2]; - rl->tl = rt1; - rl->tr = rt->rl[1]->tl == rt ? rt->rl[1]->tr : rt->rl[1]->tl; - rt1->rl[2] = rl; - rl->object_ref = o; - - rl = mem_static_aquire(&rb->render_data_pool, sizeof(LANPR_RenderLine)); - rls = mem_static_aquire(&rb->render_data_pool, sizeof(LANPR_RenderLineSegment)); - BLI_addtail(&rl->segments, rls); - BLI_addtail(&rb->all_render_lines, rl); - rl->l = rt->v[2]; - rl->r = &rv[1]; - rl->tl = rt1; - rl->tr = rt2; - rt1->rl[0] = rl; - rt2->rl[0] = rl; - rl->object_ref = o; - - rt1->v[0] = rt->v[2]; - rt1->v[1] = &rv[1]; - rt1->v[2] = &rv[0]; - - rl = mem_static_aquire(&rb->render_data_pool, sizeof(LANPR_RenderLine)); - rls = mem_static_aquire(&rb->render_data_pool, sizeof(LANPR_RenderLineSegment)); - BLI_addtail(&rl->segments, rls); - BLI_addtail(&rb->all_render_lines, rl); - rl->l = rt->v[0]; - rl->r = &rv[1]; - rl->tl = rt2; - rl->tr = rt->rl[0]->tr == rt ? rt->rl[0]->tl : rt->rl[0]->tr; - rt2->rl[2] = rl; - rt2->rl[1] = rt->rl[2]; - rl->object_ref = o; - - rt2->v[0] = &rv[1]; - rt2->v[1] = rt->v[2]; - rt2->v[2] = rt->v[0]; - - lanpr_post_triangle(rt1, rt); - lanpr_post_triangle(rt2, rt); - - v_count += 2; - t_count += 2; - continue; - } - else if (In3) { - - tMatVectorMinus3d(vv1, rt->v[2]->gloc, cam_pos); - tMatVectorMinus3d(vv2, cam_pos, rt->v[0]->gloc); - dot1 = tmat_dot_3d(vv1, view_dir, 0); - dot2 = tmat_dot_3d(vv2, view_dir, 0); - a = dot1 / (dot1 + dot2); - interp_v3_v3v3_db(rv[0].gloc, rt->v[2]->gloc, rt->v[0]->gloc, a); - tmat_apply_transform_44d(rv[0].fbcoord, vp, rv[0].gloc); - - tMatVectorMinus3d(vv1, rt->v[2]->gloc, cam_pos); - tMatVectorMinus3d(vv2, cam_pos, rt->v[1]->gloc); - dot1 = tmat_dot_3d(vv1, view_dir, 0); - dot2 = tmat_dot_3d(vv2, view_dir, 0); - a = dot1 / (dot1 + dot2); - interp_v3_v3v3_db(rv[1].gloc, rt->v[2]->gloc, rt->v[1]->gloc, a); - tmat_apply_transform_44d(rv[1].fbcoord, vp, rv[1].gloc); - - BLI_remlink(&rb->all_render_lines, (void *)rt->rl[1]); - rt->rl[1]->next = rt->rl[1]->prev = 0; - BLI_remlink(&rb->all_render_lines, (void *)rt->rl[2]); - rt->rl[2]->next = rt->rl[2]->prev = 0; - - rl = mem_static_aquire(&rb->render_data_pool, sizeof(LANPR_RenderLine)); - rls = mem_static_aquire(&rb->render_data_pool, sizeof(LANPR_RenderLineSegment)); - BLI_addtail(&rl->segments, rls); - BLI_addtail(&rb->all_render_lines, rl); - rl->l = &rv[1]; - rl->r = &rv[0]; - rl->tl = rt1; - rt1->rl[1] = rl; - rl->object_ref = o; - - rl = mem_static_aquire(&rb->render_data_pool, sizeof(LANPR_RenderLine)); - rls = mem_static_aquire(&rb->render_data_pool, sizeof(LANPR_RenderLineSegment)); - BLI_addtail(&rl->segments, rls); - BLI_addtail(&rb->all_render_lines, rl); - rl->l = &rv[0]; - rl->r = rt->v[0]; - rl->tl = rt1; - rl->tr = rt->rl[2]->tl == rt ? rt->rl[2]->tr : rt->rl[2]->tl; - rt1->rl[2] = rl; - rl->object_ref = o; - - rl = mem_static_aquire(&rb->render_data_pool, sizeof(LANPR_RenderLine)); - rls = mem_static_aquire(&rb->render_data_pool, sizeof(LANPR_RenderLineSegment)); - BLI_addtail(&rl->segments, rls); - BLI_addtail(&rb->all_render_lines, rl); - rl->l = rt->v[0]; - rl->r = &rv[1]; - rl->tl = rt1; - rl->tr = rt2; - rt1->rl[0] = rl; - rt2->rl[0] = rl; - rl->object_ref = o; - - rt1->v[0] = rt->v[0]; - rt1->v[1] = &rv[1]; - rt1->v[2] = &rv[0]; - - rl = mem_static_aquire(&rb->render_data_pool, sizeof(LANPR_RenderLine)); - rls = mem_static_aquire(&rb->render_data_pool, sizeof(LANPR_RenderLineSegment)); - BLI_addtail(&rl->segments, rls); - BLI_addtail(&rb->all_render_lines, rl); - rl->l = rt->v[1]; - rl->r = &rv[1]; - rl->tl = rt2; - rl->tr = rt->rl[1]->tr == rt ? rt->rl[1]->tl : rt->rl[1]->tr; - rt2->rl[2] = rl; - rt2->rl[1] = rt->rl[0]; - rl->object_ref = o; - - rt2->v[0] = &rv[1]; - rt2->v[1] = rt->v[0]; - rt2->v[2] = rt->v[1]; - - lanpr_post_triangle(rt1, rt); - lanpr_post_triangle(rt2, rt); - - v_count += 2; - t_count += 2; - continue; - } - break; - } - } - teln->element_count = t_count; - veln->element_count = v_count; - } -} -static void lanpr_perspective_division(LANPR_RenderBuffer *rb) -{ - LANPR_RenderVert *rv; - LANPR_RenderElementLinkNode *reln; - Camera *cam = rb->scene->camera->data; - int i; - - if (cam->type != CAM_PERSP) { - return; - } - - for (reln = rb->vertex_buffer_pointers.first; reln; reln = reln->next) { - rv = reln->pointer; - for (i = 0; i < reln->element_count; i++) { - /* if (rv->fbcoord[2] < -DBL_EPSILON) continue; */ - tMatVectorMultiSelf3d(rv[i].fbcoord, 1 / rv[i].fbcoord[3]); - /* rv[i].fbcoord[2] = cam->clipsta * cam->clipend / (cam->clipend - */ - /* fabs(rv[i].fbcoord[2]) * (cam->clipend - cam->clipsta)); */ - - rv[i].fbcoord[0] -= cam->shiftx * 2; - rv[i].fbcoord[1] -= cam->shifty * 2; - } - } -} - -static void lanpr_transform_render_vert( - BMVert *v, int index, LANPR_RenderVert *RvBuf, real *MvMat, real *MvPMat, Camera *UNUSED(camera)) -{ /* real HeightMultiply, real clipsta, real clipend) { */ - LANPR_RenderVert *rv = &RvBuf[index]; - /* rv->v = v; */ - /* v->Rv = rv; */ - tmat_apply_transform_43df(rv->gloc, MvMat, v->co); - tmat_apply_transform_43dfND(rv->fbcoord, MvPMat, v->co); - - /* if(rv->fbcoord[2]>0)tMatVectorMultiSelf3d(rv->fbcoord, (1 / */ - /* rv->fbcoord[3])); else tMatVectorMultiSelf3d(rv->fbcoord, */ - /* -rv->fbcoord[3]); */ - /* rv->fbcoord[2] = Camera->clipsta* Camera->clipend / (Camera->clipend - */ - /* fabs(rv->fbcoord[2]) * (Camera->clipend - Camera->clipsta)); */ -} - -static void lanpr_make_render_geometry_buffers_object( - Object *o, real *MvMat, real *MvPMat, LANPR_RenderBuffer *rb, int override_usage) -{ - BMesh *bm; - BMVert *v; - BMFace *f; - BMEdge *e; - BMLoop *loop; - LANPR_RenderLine *rl; - LANPR_RenderTriangle *rt; - tnsMatrix44d new_mvp; - tnsMatrix44d new_mv; - tnsMatrix44d self_transform; - tnsMatrix44d Normal; - LANPR_RenderElementLinkNode *reln; - Object *cam_object = rb->scene->camera; - Camera *c = cam_object->data; - LANPR_RenderVert *orv; - LANPR_RenderLine *orl; - LANPR_RenderTriangle *ort; - FreestyleEdge *fe; - int CanFindFreestyle = 0; - int i; - - int usage = override_usage ? override_usage : o->lanpr.usage; - - if (usage == OBJECT_FEATURE_LINE_EXCLUDE) { - return; - } - - if (o->type == OB_MESH) { - - tmat_obmat_to_16d(o->obmat, self_transform); - - tmat_multiply_44d(new_mvp, MvPMat, self_transform); - tmat_multiply_44d(new_mv, MvMat, self_transform); - - invert_m4_m4(o->imat, o->obmat); - transpose_m4(o->imat); - tmat_obmat_to_16d(o->imat, Normal); - - const BMAllocTemplate allocsize = BMALLOC_TEMPLATE_FROM_ME(((Mesh *)(o->data))); - bm = BM_mesh_create(&allocsize, - &((struct BMeshCreateParams){ - .use_toolflags = true, - })); - BM_mesh_bm_from_me(bm, - o->data, - &((struct BMeshFromMeshParams){ - .calc_face_normal = true, - })); - BM_mesh_elem_hflag_disable_all(bm, BM_FACE | BM_EDGE, BM_ELEM_TAG, false); - BM_mesh_triangulate( - bm, MOD_TRIANGULATE_QUAD_BEAUTY, MOD_TRIANGULATE_NGON_BEAUTY, 4, false, NULL, NULL, NULL); - BM_mesh_normals_update(bm); - BM_mesh_elem_table_ensure(bm, BM_VERT | BM_EDGE | BM_FACE); - BM_mesh_elem_index_ensure(bm, BM_VERT | BM_EDGE | BM_FACE); - - if (CustomData_has_layer(&bm->edata, CD_LANPR_EDGE)) { - CanFindFreestyle = 1; - } - - orv = mem_static_aquire(&rb->render_data_pool, sizeof(LANPR_RenderVert) * bm->totvert); - ort = mem_static_aquire(&rb->render_data_pool, bm->totface * rb->triangle_size); - orl = mem_static_aquire(&rb->render_data_pool, sizeof(LANPR_RenderLine) * bm->totedge); - - reln = list_append_pointer_static_sized(&rb->vertex_buffer_pointers, - &rb->render_data_pool, - orv, - sizeof(LANPR_RenderElementLinkNode)); - reln->element_count = bm->totvert; - reln->object_ref = o; - - reln = list_append_pointer_static_sized(&rb->line_buffer_pointers, - &rb->render_data_pool, - orl, - sizeof(LANPR_RenderElementLinkNode)); - reln->element_count = bm->totedge; - reln->object_ref = o; - - reln = list_append_pointer_static_sized(&rb->triangle_buffer_pointers, - &rb->render_data_pool, - ort, - sizeof(LANPR_RenderElementLinkNode)); - reln->element_count = bm->totface; - reln->object_ref = o; - - for (i = 0; i < bm->totvert; i++) { - v = BM_vert_at_index(bm, i); - lanpr_transform_render_vert(v, i, orv, new_mv, new_mvp, c); - } - - rl = orl; - for (i = 0; i < bm->totedge; i++) { - e = BM_edge_at_index(bm, i); - if (CanFindFreestyle) { - fe = CustomData_bmesh_get(&bm->edata, e->head.data, CD_LANPR_EDGE); - if (fe->flag & FREESTYLE_EDGE_MARK) { - rl->flags |= LANPR_EDGE_FLAG_EDGE_MARK; - } - } - if (use_smooth_contour_modifier_contour) { - rl->edge_idx = i; - if (BM_elem_flag_test(e->v1, BM_ELEM_SELECT) && BM_elem_flag_test(e->v2, BM_ELEM_SELECT)) { - rl->flags |= LANPR_EDGE_FLAG_CONTOUR; - } - } - - rl->l = &orv[BM_elem_index_get(e->v1)]; - rl->r = &orv[BM_elem_index_get(e->v2)]; - - rl->object_ref = o; - - LANPR_RenderLineSegment *rls = mem_static_aquire(&rb->render_data_pool, - sizeof(LANPR_RenderLineSegment)); - BLI_addtail(&rl->segments, rls); - if (usage == OBJECT_FEATURE_LINE_INHERENT) { - BLI_addtail(&rb->all_render_lines, rl); - } - rl++; - } - - rt = ort; - for (i = 0; i < bm->totface; i++) { - f = BM_face_at_index(bm, i); - - loop = f->l_first; - rt->v[0] = &orv[BM_elem_index_get(loop->v)]; - rt->rl[0] = &orl[BM_elem_index_get(loop->e)]; - loop = loop->next; - rt->v[1] = &orv[BM_elem_index_get(loop->v)]; - rt->rl[1] = &orl[BM_elem_index_get(loop->e)]; - loop = loop->next; - rt->v[2] = &orv[BM_elem_index_get(loop->v)]; - rt->rl[2] = &orl[BM_elem_index_get(loop->e)]; - - rt->material_id = f->mat_nr; - rt->gn[0] = f->no[0]; - rt->gn[1] = f->no[1]; - rt->gn[2] = f->no[2]; - - tMatVectorAccum3d(rt->gc, rt->v[0]->fbcoord); - tMatVectorAccum3d(rt->gc, rt->v[1]->fbcoord); - tMatVectorAccum3d(rt->gc, rt->v[2]->fbcoord); - tMatVectorMultiSelf3d(rt->gc, 1.0f / 3.0f); - tmat_apply_normal_transform_43df(rt->gn, Normal, f->no); - tmat_normalize_self_3d(rt->gn); - lanpr_assign_render_line_with_triangle(rt); - /* m = tnsGetIndexedMaterial(rb->scene, f->material_id); */ - /* if(m) m->Previewv_count += (f->triangle_count*3); */ - - if (BM_elem_flag_test(f, BM_ELEM_SELECT)) { - rt->material_id = 1; - } - - rt = (LANPR_RenderTriangle *)(((unsigned char *)rt) + rb->triangle_size); - } - - BM_mesh_free(bm); - } -} - -static int lanpr_object_has_feature_line_modifier(Object *o) -{ - ModifierData *md; - for (md = o->modifiers.first; md; md = md->next) { - if (md->type == eModifierType_FeatureLine) { - return 1; - } - } - return 0; -} - -int ED_lanpr_object_collection_usage_check(Collection *c, Object *o) -{ - CollectionChild *cc; - int object_is_used = (lanpr_object_has_feature_line_modifier(o) && - o->lanpr.usage == OBJECT_FEATURE_LINE_INHERENT); - - if (object_is_used && c->lanpr.force && c->lanpr.usage != COLLECTION_FEATURE_LINE_INCLUDE) { - if (BKE_collection_has_object_recursive(c, o)) { - if (c->lanpr.usage == COLLECTION_FEATURE_LINE_EXCLUDE) { - return OBJECT_FEATURE_LINE_EXCLUDE; - } - else if (c->lanpr.usage == COLLECTION_FEATURE_LINE_OCCLUSION_ONLY) { - return OBJECT_FEATURE_LINE_OCCLUSION_ONLY; - } - } - } - - if (!c->children.first) { - if (BKE_collection_has_object(c, o)) { - if (o->lanpr.usage == OBJECT_FEATURE_LINE_INHERENT) { - if (c->lanpr.usage == COLLECTION_FEATURE_LINE_OCCLUSION_ONLY) { - return OBJECT_FEATURE_LINE_OCCLUSION_ONLY; - } - else if (c->lanpr.usage == COLLECTION_FEATURE_LINE_EXCLUDE) { - return OBJECT_FEATURE_LINE_EXCLUDE; - } - else { - return OBJECT_FEATURE_LINE_INHERENT; - } - } - else { - return o->lanpr.usage; - } - } - else { - return OBJECT_FEATURE_LINE_INHERENT; - } - } - - for (cc = c->children.first; cc; cc = cc->next) { - int result = ED_lanpr_object_collection_usage_check(cc->collection, o); - if (result > OBJECT_FEATURE_LINE_INHERENT) { - return result; - } - } - - return OBJECT_FEATURE_LINE_INHERENT; -} - -static void lanpr_make_render_geometry_buffers(Depsgraph *depsgraph, - Scene *s, - Object *c /*camera*/, - LANPR_RenderBuffer *rb) -{ - tnsMatrix44d obmat16; - tnsMatrix44d proj, view, result, inv; - Camera *cam = c->data; - - float sensor = BKE_camera_sensor_size(cam->sensor_fit, cam->sensor_x, cam->sensor_y); - real fov = focallength_to_fov(cam->lens, sensor); - - memset(rb->material_pointers, 0, sizeof(void *) * 2048); - - real asp = ((real)rb->w / (real)rb->h); - - if (cam->type == CAM_PERSP) { - tmat_make_perspective_matrix_44d(proj, fov, asp, cam->clip_start, cam->clip_end); - } - else if (cam->type == CAM_ORTHO) { - real w = cam->ortho_scale / 2; - tmat_make_ortho_matrix_44d(proj, -w, w, -w / asp, w / asp, cam->clip_start, cam->clip_end); - } - - tmat_load_identity_44d(view); - - /* tObjApplyself_transformMatrix(c, 0); */ - /* tObjApplyGlobalTransformMatrixReverted(c); */ - tmat_obmat_to_16d(c->obmat, obmat16); - tmat_inverse_44d(inv, obmat16); - tmat_multiply_44d(result, proj, inv); - memcpy(proj, result, sizeof(tnsMatrix44d)); - memcpy(rb->view_projection, proj, sizeof(tnsMatrix44d)); - - tmat_inverse_44d(rb->vp_inverse, rb->view_projection); - - list_handle_empty(&rb->triangle_buffer_pointers); - list_handle_empty(&rb->vertex_buffer_pointers); - - DEG_OBJECT_ITER_BEGIN (depsgraph, - o, - DEG_ITER_OBJECT_FLAG_LINKED_DIRECTLY | DEG_ITER_OBJECT_FLAG_VISIBLE | - DEG_ITER_OBJECT_FLAG_DUPLI | DEG_ITER_OBJECT_FLAG_LINKED_VIA_SET) { - int usage = ED_lanpr_object_collection_usage_check(s->master_collection, o); - - lanpr_make_render_geometry_buffers_object(o, view, proj, rb, usage); - } - DEG_OBJECT_ITER_END; - - /* for (collection = s->master_collection.first; collection; collection = collection->ID.next) { - */ - /* for (co = collection->gobject.first; co; co = co->next) { */ - /* //tObjApplyGlobalTransformMatrixRecursive(o); */ - /* lanpr_make_render_geometry_buffers_object(o, view, proj, rb); */ - /* } */ - /* } */ -} - -#define INTERSECT_SORT_MIN_TO_MAX_3(ia, ib, ic, lst) \ - { \ - lst[0] = TNS_MIN3_INDEX(ia, ib, ic); \ - lst[1] = (((ia <= ib && ib <= ic) || (ic <= ib && ib <= ia)) ? \ - 1 : \ - (((ic <= ia && ia <= ib) || (ib < ia && ia <= ic)) ? 0 : 2)); \ - lst[2] = TNS_MAX3_INDEX(ia, ib, ic); \ - } - -/* ia ib ic are ordered */ -#define INTERSECT_JUST_GREATER(is, order, num, index) \ - { \ - index = (num < is[order[0]] ? \ - order[0] : \ - (num < is[order[1]] ? order[1] : (num < is[order[2]] ? order[2] : order[2]))); \ - } - -/* ia ib ic are ordered */ -#define INTERSECT_JUST_SMALLER(is, order, num, index) \ - { \ - index = (num > is[order[2]] ? \ - order[2] : \ - (num > is[order[1]] ? order[1] : (num > is[order[0]] ? order[0] : order[0]))); \ - } - -static void lanpr_get_interpolate_point2d(tnsVector2d l, - tnsVector2d r, - real Ratio, - tnsVector2d Result) -{ - Result[0] = tnsLinearItp(l[0], r[0], Ratio); - Result[1] = tnsLinearItp(l[1], r[1], Ratio); -} - -static LANPR_RenderLine *lanpr_another_edge(LANPR_RenderTriangle *rt, LANPR_RenderVert *rv) -{ - if (rt->v[0] == rv) { - return rt->rl[1]; - } - else if (rt->v[1] == rv) { - return rt->rl[2]; - } - else if (rt->v[2] == rv) { - return rt->rl[0]; - } - return 0; -} -static int lanpr_share_edge(LANPR_RenderTriangle *rt, LANPR_RenderVert *rv, LANPR_RenderLine *rl) -{ - LANPR_RenderVert *another = rv == rl->l ? rl->r : rl->l; - - if (rt->v[0] == rv) { - if (another == rt->v[1] || another == rt->v[2]) { - return 1; - } - return 0; - } - else if (rt->v[1] == rv) { - if (another == rt->v[0] || another == rt->v[2]) { - return 1; - } - return 0; - } - else if (rt->v[2] == rv) { - if (another == rt->v[0] || another == rt->v[1]) { - return 1; - } - return 0; - } - return 0; -} -static int lanpr_share_edge_direct(LANPR_RenderTriangle *rt, LANPR_RenderLine *rl) -{ - if (rt->rl[0] == rl || rt->rl[1] == rl || rt->rl[2] == rl) { - return 1; - } - return 0; -} - -static int lanpr_triangle_line_imagespace_intersection_v2(SpinLock *UNUSED(spl), - LANPR_RenderTriangle *rt, - LANPR_RenderLine *rl, - Object *cam, - tnsMatrix44d vp, - real *CameraDir, - double *From, - double *To) -{ - double is[3] = {0}; - int order[3]; - int LCross = -1, RCross = -1; - int a, b, c; - int StL = 0, StR = 0, In; - - tnsVector3d Lv; - tnsVector3d Rv; - tnsVector4d vd4; - real Cv[3]; - real DotL, DotR, DotLA, DotRA; - real DotF; - tnsVector4d gloc, Trans; - real Cut = -1; - - double *LFBC = rl->l->fbcoord, *RFBC = rl->r->fbcoord, *FBC0 = rt->v[0]->fbcoord, - *FBC1 = rt->v[1]->fbcoord, *FBC2 = rt->v[2]->fbcoord; - - /* printf("(%f %f)(%f %f)(%f %f) (%f %f)(%f %f)\n", FBC0[0], FBC0[1], FBC1[0], FBC1[1], */ - /* FBC2[0], FBC2[1], LFBC[0], LFBC[1], RFBC[0], RFBC[1]); */ - - /* bound box. */ - /* if (MIN3(FBC0[2], FBC1[2], FBC2[2]) > MAX2(LFBC[2], RFBC[2])) */ - /* return 0; */ - if ((MAX3(FBC0[0], FBC1[0], FBC2[0]) < MIN2(LFBC[0], RFBC[0])) || - (MIN3(FBC0[0], FBC1[0], FBC2[0]) > MAX2(LFBC[0], RFBC[0])) || - (MAX3(FBC0[1], FBC1[1], FBC2[1]) < MIN2(LFBC[1], RFBC[1])) || - (MIN3(FBC0[1], FBC1[1], FBC2[1]) > MAX2(LFBC[1], RFBC[1]))) { - return 0; - } - - if (lanpr_share_edge_direct(rt, rl)) { - return 0; - } - - a = lanpr_LineIntersectTest2d(LFBC, RFBC, FBC0, FBC1, &is[0]); - b = lanpr_LineIntersectTest2d(LFBC, RFBC, FBC1, FBC2, &is[1]); - c = lanpr_LineIntersectTest2d(LFBC, RFBC, FBC2, FBC0, &is[2]); - - /* printf("abc: %d %d %d\n", a,b,c); */ - - INTERSECT_SORT_MIN_TO_MAX_3(is[0], is[1], is[2], order); - - tMatVectorMinus3d(Lv, rl->l->gloc, rt->v[0]->gloc); - tMatVectorMinus3d(Rv, rl->r->gloc, rt->v[0]->gloc); - - tMatVectorCopy3d(CameraDir, Cv); - - tMatVectorConvert4fd(cam->obmat[3], vd4); - if (((Camera *)cam->data)->type == CAM_PERSP) { - tMatVectorMinus3d(Cv, vd4, rt->v[0]->gloc); - } - - DotL = tmat_dot_3d(Lv, rt->gn, 0); - DotR = tmat_dot_3d(Rv, rt->gn, 0); - DotF = tmat_dot_3d(Cv, rt->gn, 0); - - if (!DotF) { - return 0; - } - - if (!a && !b && !c) { - if (!(StL = lanpr_point_triangle_relation(LFBC, FBC0, FBC1, FBC2)) && - !(StR = lanpr_point_triangle_relation(RFBC, FBC0, FBC1, FBC2))) { - return 0; /* not occluding */ - } - } - - StL = lanpr_point_triangle_relation(LFBC, FBC0, FBC1, FBC2); - StR = lanpr_point_triangle_relation(RFBC, FBC0, FBC1, FBC2); - - /* for (rv = rt->intersecting_verts.first; rv; rv = rv->next) { */ - /* if (rv->intersecting_with == rt && rv->intersecting_line == rl) { */ - /* Cut = tMatGetLinearRatio(rl->l->fbcoord[0], rl->r->fbcoord[0], */ - /* rv->fbcoord[0]); break; */ - /* } */ - /* } */ - - DotLA = fabs(DotL); - if (DotLA < DBL_EPSILON) { - DotLA = 0; - DotL = 0; - } - DotRA = fabs(DotR); - if (DotRA < DBL_EPSILON) { - DotRA = 0; - DotR = 0; - } - if (DotL - DotR == 0) { - Cut = 100000; - } - else if (DotL * DotR <= 0) { - Cut = DotLA / fabs(DotL - DotR); - } - else { - Cut = fabs(DotR + DotL) / fabs(DotL - DotR); - Cut = DotRA > DotLA ? 1 - Cut : Cut; - } - - if (((Camera *)cam->data)->type == CAM_PERSP) { - interp_v3_v3v3_db(gloc, rl->l->gloc, rl->r->gloc, Cut); - tmat_apply_transform_44d(Trans, vp, gloc); - tMatVectorMultiSelf3d(Trans, (1 / Trans[3]) /**HeightMultiply/2*/); - Camera *camera = cam->data; - Trans[0] -= camera->shiftx * 2; - Trans[1] -= camera->shifty * 2; - } - else { - interp_v3_v3v3_db(Trans, rl->l->fbcoord, rl->r->fbcoord, Cut); - /* tmat_apply_transform_44d(Trans, vp, gloc); */ - } - - /* Trans[2] = tmat_dist_3dv(gloc, cam->Base.gloc); */ - /* Trans[2] = cam->clipsta*cam->clipend / (cam->clipend - fabs(Trans[2]) * (cam->clipend - */ - /* cam->clipsta)); */ - - /* prevent vertical problem ? */ - if (rl->l->fbcoord[0] != rl->r->fbcoord[0]) { - Cut = tMatGetLinearRatio(rl->l->fbcoord[0], rl->r->fbcoord[0], Trans[0]); - } - else { - Cut = tMatGetLinearRatio(rl->l->fbcoord[1], rl->r->fbcoord[1], Trans[1]); - } - - In = ED_lanpr_point_inside_triangled( - Trans, rt->v[0]->fbcoord, rt->v[1]->fbcoord, rt->v[2]->fbcoord); - - if (StL == 2) { - if (StR == 2) { - INTERSECT_JUST_SMALLER(is, order, DBL_TRIANGLE_LIM, LCross); - INTERSECT_JUST_GREATER(is, order, 1 - DBL_TRIANGLE_LIM, RCross); - } - else if (StR == 1) { - INTERSECT_JUST_SMALLER(is, order, DBL_TRIANGLE_LIM, LCross); - INTERSECT_JUST_GREATER(is, order, 1 - DBL_TRIANGLE_LIM, RCross); - } - else if (StR == 0) { - INTERSECT_JUST_SMALLER(is, order, DBL_TRIANGLE_LIM, LCross); - INTERSECT_JUST_GREATER(is, order, 0, RCross); - } - } - else if (StL == 1) { - if (StR == 2) { - INTERSECT_JUST_SMALLER(is, order, DBL_TRIANGLE_LIM, LCross); - INTERSECT_JUST_GREATER(is, order, 1 - DBL_TRIANGLE_LIM, RCross); - } - else if (StR == 1) { - INTERSECT_JUST_SMALLER(is, order, DBL_TRIANGLE_LIM, LCross); - INTERSECT_JUST_GREATER(is, order, 1 - DBL_TRIANGLE_LIM, RCross); - } - else if (StR == 0) { - INTERSECT_JUST_GREATER(is, order, DBL_TRIANGLE_LIM, RCross); - if (TNS_ABC(RCross) && is[RCross] > (DBL_TRIANGLE_LIM)) { - INTERSECT_JUST_SMALLER(is, order, DBL_TRIANGLE_LIM, LCross); - } - else { - INTERSECT_JUST_SMALLER(is, order, -DBL_TRIANGLE_LIM, LCross); - INTERSECT_JUST_GREATER(is, order, -DBL_TRIANGLE_LIM, RCross); - } - } - } - else if (StL == 0) { - if (StR == 2) { - INTERSECT_JUST_SMALLER(is, order, 1 - DBL_TRIANGLE_LIM, LCross); - INTERSECT_JUST_GREATER(is, order, 1 - DBL_TRIANGLE_LIM, RCross); - } - else if (StR == 1) { - INTERSECT_JUST_SMALLER(is, order, 1 - DBL_TRIANGLE_LIM, LCross); - if (TNS_ABC(LCross) && is[LCross] < (1 - DBL_TRIANGLE_LIM)) { - INTERSECT_JUST_GREATER(is, order, 1 - DBL_TRIANGLE_LIM, RCross); - } - else { - INTERSECT_JUST_SMALLER(is, order, 1 + DBL_TRIANGLE_LIM, LCross); - INTERSECT_JUST_GREATER(is, order, 1 + DBL_TRIANGLE_LIM, RCross); - } - } - else if (StR == 0) { - INTERSECT_JUST_GREATER(is, order, 0, LCross); - if (TNS_ABC(LCross) && is[LCross] > 0) { - INTERSECT_JUST_GREATER(is, order, is[LCross], RCross); - } - else { - INTERSECT_JUST_GREATER(is, order, is[LCross], LCross); - INTERSECT_JUST_GREATER(is, order, is[LCross], RCross); - } - } - } - - real LF = DotL * DotF, RF = DotR * DotF; - /* int CrossCount = a + b + c; */ - /* if (CrossCount == 2) { */ - /* INTERSECT_JUST_GREATER(is, order, 0, LCross); */ - /* if (!TNS_ABC(LCross)) INTERSECT_JUST_GREATER(is, order, is[LCross], LCross); */ - /* INTERSECT_JUST_GREATER(is, order, is[LCross], RCross); */ - /* }else if(CrossCount == 1 || StL+StR==1) { */ - /* if (StL) { */ - /* INTERSECT_JUST_GREATER(is, order, DBL_TRIANGLE_LIM, RCross); */ - /* INTERSECT_JUST_SMALLER(is, order, is[RCross], LCross); */ - /* }else if(StR) { */ - /* INTERSECT_JUST_SMALLER(is, order, 1 - DBL_TRIANGLE_LIM, LCross); */ - /* INTERSECT_JUST_GREATER(is, order, is[LCross], RCross); */ - /* } */ - /* }else if(CrossCount == 0) { */ - /* INTERSECT_JUST_SMALLER(is, order, 0, LCross); */ - /* INTERSECT_JUST_GREATER(is, order, 1, RCross); */ - /* } */ - - if (LF <= 0 && RF <= 0 && (DotL || DotR)) { - - *From = MAX2(0, is[LCross]); - *To = MIN2(1, is[RCross]); - if (*From >= *To) { - return 0; - } - /* printf("1 From %f to %f\n",*From, *To); */ - return 1; - } - else if (LF >= 0 && RF <= 0 && (DotL || DotR)) { - *From = MAX2(Cut, is[LCross]); - *To = MIN2(1, is[RCross]); - if (*From >= *To) { - return 0; - } - /* printf("2 From %f to %f\n",*From, *To); */ - return 1; - } - else if (LF <= 0 && RF >= 0 && (DotL || DotR)) { - *From = MAX2(0, is[LCross]); - *To = MIN2(Cut, is[RCross]); - if (*From >= *To) { - return 0; - } - /* printf("3 From %f to %f\n",*From, *To); */ - return 1; - } - else - return 0; - return 1; -} - -static LANPR_RenderLine *lanpr_triangle_share_edge(LANPR_RenderTriangle *l, - LANPR_RenderTriangle *r) -{ - if (l->rl[0] == r->rl[0]) { - return r->rl[0]; - } - if (l->rl[0] == r->rl[1]) { - return r->rl[1]; - } - if (l->rl[0] == r->rl[2]) { - return r->rl[2]; - } - if (l->rl[1] == r->rl[0]) { - return r->rl[0]; - } - if (l->rl[1] == r->rl[1]) { - return r->rl[1]; - } - if (l->rl[1] == r->rl[2]) { - return r->rl[2]; - } - if (l->rl[2] == r->rl[0]) { - return r->rl[0]; - } - if (l->rl[2] == r->rl[1]) { - return r->rl[1]; - } - if (l->rl[2] == r->rl[2]) { - return r->rl[2]; - } - return 0; -} -static LANPR_RenderVert *lanpr_triangle_share_point(LANPR_RenderTriangle *l, - LANPR_RenderTriangle *r) -{ - if (l->v[0] == r->v[0]) { - return r->v[0]; - } - if (l->v[0] == r->v[1]) { - return r->v[1]; - } - if (l->v[0] == r->v[2]) { - return r->v[2]; - } - if (l->v[1] == r->v[0]) { - return r->v[0]; - } - if (l->v[1] == r->v[1]) { - return r->v[1]; - } - if (l->v[1] == r->v[2]) { - return r->v[2]; - } - if (l->v[2] == r->v[0]) { - return r->v[0]; - } - if (l->v[2] == r->v[1]) { - return r->v[1]; - } - if (l->v[2] == r->v[2]) { - return r->v[2]; - } - return 0; -} - -static LANPR_RenderVert *lanpr_triangle_line_intersection_test(LANPR_RenderBuffer *rb, - LANPR_RenderLine *rl, - LANPR_RenderTriangle *rt, - LANPR_RenderTriangle *testing, - LANPR_RenderVert *Last) -{ - tnsVector3d Lv; - tnsVector3d Rv; - real DotL, DotR; - LANPR_RenderVert *Result, *rv; - tnsVector3d gloc; - LANPR_RenderVert *l = rl->l, *r = rl->r; - int result; - - for (rv = testing->intersecting_verts.first; rv; rv = rv->next) { - if (rv->intersecting_with == rt && rv->intersecting_line == rl) { - return rv; - } - } - - tMatVectorMinus3d(Lv, l->gloc, testing->v[0]->gloc); - tMatVectorMinus3d(Rv, r->gloc, testing->v[0]->gloc); - - DotL = tmat_dot_3d(Lv, testing->gn, 0); - DotR = tmat_dot_3d(Rv, testing->gn, 0); - - if (DotL * DotR > 0 || (!DotL && !DotR)) { - return 0; - } - - DotL = fabs(DotL); - DotR = fabs(DotR); - - interp_v3_v3v3_db(gloc, l->gloc, r->gloc, DotL / (DotL + DotR)); - - if (Last && TNS_DOUBLE_CLOSE_ENOUGH(Last->gloc[0], gloc[0]) && - TNS_DOUBLE_CLOSE_ENOUGH(Last->gloc[1], gloc[1]) && - TNS_DOUBLE_CLOSE_ENOUGH(Last->gloc[2], gloc[2])) { - - Last->intersecting_line2 = rl; - return 0; - } - - if (!(result = lanpr_point_inside_triangle3de( - gloc, testing->v[0]->gloc, testing->v[1]->gloc, testing->v[2]->gloc))) { - return 0; - } - /*else if(result < 0) { - return 0; - }*/ - - Result = mem_static_aquire(&rb->render_data_pool, sizeof(LANPR_RenderVert)); - - if (DotL > 0 || DotR < 0) { - Result->positive = 1; - } - else { - Result->positive = 0; - } - - /* Result->IntersectingOnFace = testing; */ - Result->edge_used = 1; - /* Result->IntersectL = l; */ - Result->v = (void *)r; /* Caution! */ - /* Result->intersecting_with = rt; */ - tMatVectorCopy3d(gloc, Result->gloc); - - BLI_addtail(&testing->intersecting_verts, Result); - - return Result; -} -static LANPR_RenderLine *lanpr_triangle_generate_intersection_line_only( - LANPR_RenderBuffer *rb, LANPR_RenderTriangle *rt, LANPR_RenderTriangle *testing) -{ - LANPR_RenderVert *l = 0, *r = 0; - LANPR_RenderVert **Next = &l; - LANPR_RenderLine *Result; - LANPR_RenderVert *E0T = 0; - LANPR_RenderVert *E1T = 0; - LANPR_RenderVert *E2T = 0; - LANPR_RenderVert *TE0 = 0; - LANPR_RenderVert *TE1 = 0; - LANPR_RenderVert *TE2 = 0; - tnsVector3d cl; /* rb->scene->ActiveCamera->gloc; */ - real ZMax = ((Camera *)rb->scene->camera->data)->clip_end; - real ZMin = ((Camera *)rb->scene->camera->data)->clip_start; - LANPR_RenderVert *Share = lanpr_triangle_share_point(testing, rt); - Camera *cam = rb->scene->camera->data; - - tMatVectorConvert3fd(rb->scene->camera->obmat[3], cl); - - if (Share) { - LANPR_RenderVert *NewShare; - LANPR_RenderLine *rl = lanpr_another_edge(rt, Share); - - l = NewShare = mem_static_aquire(&rb->render_data_pool, (sizeof(LANPR_RenderVert))); - - NewShare->positive = 1; - NewShare->edge_used = 1; - /* NewShare->IntersectL = l; */ - NewShare->v = (void *)r; /* Caution! */ - /* Result->intersecting_with = rt; */ - tMatVectorCopy3d(Share->gloc, NewShare->gloc); - - r = lanpr_triangle_line_intersection_test(rb, rl, rt, testing, 0); - - if (!r) { - rl = lanpr_another_edge(testing, Share); - r = lanpr_triangle_line_intersection_test(rb, rl, testing, rt, 0); - if (!r) { - return 0; - } - BLI_addtail(&testing->intersecting_verts, NewShare); - } - else { - BLI_addtail(&rt->intersecting_verts, NewShare); - } - } - else { - if (!rt->rl[0] || !rt->rl[1] || !rt->rl[2]) { - return 0; /* shouldn't need this, there must be problems in culling. */ - } - E0T = lanpr_triangle_line_intersection_test(rb, rt->rl[0], rt, testing, 0); - if (E0T && (!(*Next))) { - (*Next) = E0T; - (*Next)->intersecting_line = rt->rl[0]; - Next = &r; - } - E1T = lanpr_triangle_line_intersection_test(rb, rt->rl[1], rt, testing, l); - if (E1T && (!(*Next))) { - (*Next) = E1T; - (*Next)->intersecting_line = rt->rl[1]; - Next = &r; - } - if (!(*Next)) { - E2T = lanpr_triangle_line_intersection_test(rb, rt->rl[2], rt, testing, l); - } - if (E2T && (!(*Next))) { - (*Next) = E2T; - (*Next)->intersecting_line = rt->rl[2]; - Next = &r; - } - - if (!(*Next)) { - TE0 = lanpr_triangle_line_intersection_test(rb, testing->rl[0], testing, rt, l); - } - if (TE0 && (!(*Next))) { - (*Next) = TE0; - (*Next)->intersecting_line = testing->rl[0]; - Next = &r; - } - if (!(*Next)) { - TE1 = lanpr_triangle_line_intersection_test(rb, testing->rl[1], testing, rt, l); - } - if (TE1 && (!(*Next))) { - (*Next) = TE1; - (*Next)->intersecting_line = testing->rl[1]; - Next = &r; - } - if (!(*Next)) { - TE2 = lanpr_triangle_line_intersection_test(rb, testing->rl[2], testing, rt, l); - } - if (TE2 && (!(*Next))) { - (*Next) = TE2; - (*Next)->intersecting_line = testing->rl[2]; - Next = &r; - } - - if (!(*Next)) { - return 0; - } - } - tmat_apply_transform_44d(l->fbcoord, rb->view_projection, l->gloc); - tmat_apply_transform_44d(r->fbcoord, rb->view_projection, r->gloc); - tMatVectorMultiSelf3d(l->fbcoord, (1 / l->fbcoord[3]) /**HeightMultiply/2*/); - tMatVectorMultiSelf3d(r->fbcoord, (1 / r->fbcoord[3]) /**HeightMultiply/2*/); - - l->fbcoord[0] -= cam->shiftx * 2; - l->fbcoord[1] -= cam->shifty * 2; - r->fbcoord[0] -= cam->shiftx * 2; - r->fbcoord[1] -= cam->shifty * 2; - - l->fbcoord[2] = ZMin * ZMax / (ZMax - fabs(l->fbcoord[2]) * (ZMax - ZMin)); - r->fbcoord[2] = ZMin * ZMax / (ZMax - fabs(r->fbcoord[2]) * (ZMax - ZMin)); - - l->intersecting_with = rt; - r->intersecting_with = testing; - - /* /*((1 / rl->l->fbcoord[3])*rb->FrameBuffer->H / 2) */ - - Result = mem_static_aquire(&rb->render_data_pool, sizeof(LANPR_RenderLine)); - Result->l = l; - Result->r = r; - Result->tl = rt; - Result->tr = testing; - LANPR_RenderLineSegment *rls = mem_static_aquire(&rb->render_data_pool, - sizeof(LANPR_RenderLineSegment)); - BLI_addtail(&Result->segments, rls); - BLI_addtail(&rb->all_render_lines, Result); - Result->flags |= LANPR_EDGE_FLAG_INTERSECTION; - list_append_pointer_static(&rb->intersection_lines, &rb->render_data_pool, Result); - int r1, r2, c1, c2, row, col; - if (lanpr_get_line_bounding_areas(rb, Result, &r1, &r2, &c1, &c2)) { - for (row = r1; row != r2 + 1; row++) { - for (col = c1; col != c2 + 1; col++) { - lanpr_link_line_with_bounding_area(rb, &rb->initial_bounding_areas[row * 4 + col], Result); - } - } - } - - rb->intersection_count++; - - return Result; -} -static void lanpr_triangle_calculate_intersections_in_bounding_area(LANPR_RenderBuffer *rb, - LANPR_RenderTriangle *rt, - LANPR_BoundingArea *ba) -{ - LANPR_RenderTriangle *TestingTriangle; - LinkData *lip, *next_lip; - - real *FBC0 = rt->v[0]->fbcoord, *FBC1 = rt->v[1]->fbcoord, *FBC2 = rt->v[2]->fbcoord; - - if (ba->child) { - lanpr_triangle_calculate_intersections_in_bounding_area(rb, rt, &ba->child[0]); - lanpr_triangle_calculate_intersections_in_bounding_area(rb, rt, &ba->child[1]); - lanpr_triangle_calculate_intersections_in_bounding_area(rb, rt, &ba->child[2]); - lanpr_triangle_calculate_intersections_in_bounding_area(rb, rt, &ba->child[3]); - return; - } - - for (lip = ba->linked_triangles.first; lip; lip = next_lip) { - next_lip = lip->next; - TestingTriangle = lip->data; - if (TestingTriangle == rt || TestingTriangle->testing == rt || - lanpr_triangle_share_edge(rt, TestingTriangle)) { - - continue; - } - - TestingTriangle->testing = rt; - real *RFBC0 = TestingTriangle->v[0]->fbcoord, *RFBC1 = TestingTriangle->v[1]->fbcoord, - *RFBC2 = TestingTriangle->v[2]->fbcoord; - - if ((MIN3(FBC0[2], FBC1[2], FBC2[2]) > MAX3(RFBC0[2], RFBC1[2], RFBC2[2])) || - (MAX3(FBC0[2], FBC1[2], FBC2[2]) < MIN3(RFBC0[2], RFBC1[2], RFBC2[2])) || - (MIN3(FBC0[0], FBC1[0], FBC2[0]) > MAX3(RFBC0[0], RFBC1[0], RFBC2[0])) || - (MAX3(FBC0[0], FBC1[0], FBC2[0]) < MIN3(RFBC0[0], RFBC1[0], RFBC2[0])) || - (MIN3(FBC0[1], FBC1[1], FBC2[1]) > MAX3(RFBC0[1], RFBC1[1], RFBC2[1])) || - (MAX3(FBC0[1], FBC1[1], FBC2[1]) < MIN3(RFBC0[1], RFBC1[1], RFBC2[1]))) { - continue; - } - - lanpr_triangle_generate_intersection_line_only(rb, rt, TestingTriangle); - } -} - -static int lanpr_line_crosses_frame(tnsVector2d l, tnsVector2d r) -{ - real vx, vy; - real c1, c; - - if ((-1 > MAX2(l[0], r[0])) || (1 < MIN2(l[0], r[0])) || (-1 > MAX2(l[1], r[1])) || - (1 < MIN2(l[1], r[1]))) { - return 0; - } - - vx = l[0] - r[0]; - vy = l[1] - r[1]; - - c1 = vx * (-1 - l[1]) - vy * (-1 - l[0]); - c = c1; - - c1 = vx * (-1 - l[1]) - vy * (1 - l[0]); - if (c1 * c <= 0) { - return 1; - } - else { - c = c1; - } - - c1 = vx * (1 - l[1]) - vy * (-1 - l[0]); - if (c1 * c <= 0) { - return 1; - } - else { - c = c1; - } - - c1 = vx * (1 - l[1]) - vy * (1 - l[0]); - if (c1 * c <= 0) { - return 1; - } - else { - c = c1; - } - - return 0; -} - -static void lanpr_compute_view_Vector(LANPR_RenderBuffer *rb) -{ - tnsVector3d Direction = {0, 0, 1}; - tnsVector3d Trans; - tnsMatrix44d inv; - tnsMatrix44d obmat; - - tmat_obmat_to_16d(rb->scene->camera->obmat, obmat); - tmat_inverse_44d(inv, obmat); - tmat_apply_rotation_43d(Trans, inv, Direction); - tMatVectorCopy3d(Trans, rb->view_vector); - /* tMatVectorMultiSelf3d(Trans, -1); */ - /* tMatVectorCopy3d(Trans, ((Camera*)rb->scene->camera)->RenderviewDir); */ -} - -static void lanpr_compute_scene_contours(LANPR_RenderBuffer *rb, float threshold) -{ - real *view_vector = rb->view_vector; - real Dot1 = 0, Dot2 = 0; - real Result; - tnsVector3d cam_location; - int Add = 0; - Object *cam_obj = rb->scene->camera; - Camera *c = cam_obj->data; - LANPR_RenderLine *rl; - int contour_count = 0; - int crease_count = 0; - int MaterialCount = 0; - - if (c->type == CAM_ORTHO) { - lanpr_compute_view_Vector(rb); - } - - for (rl = rb->all_render_lines.first; rl; rl = rl->next) { - /* if(rl->testing) */ - /* if (!lanpr_line_crosses_frame(rl->l->fbcoord, rl->r->fbcoord)) */ - /* continue; */ - - Add = 0; - Dot1 = 0; - Dot2 = 0; - - if (c->type == CAM_PERSP) { - tMatVectorConvert3fd(cam_obj->obmat[3], cam_location); - tMatVectorMinus3d(view_vector, rl->l->gloc, cam_location); - } - - if (use_smooth_contour_modifier_contour) { - if (rl->flags & LANPR_EDGE_FLAG_CONTOUR) { - Add = 1; - } - } - else { - if (rl->tl) { - Dot1 = tmat_dot_3d(view_vector, rl->tl->gn, 0); - } - else { - Add = 1; - } - if (rl->tr) { - Dot2 = tmat_dot_3d(view_vector, rl->tr->gn, 0); - } - else { - Add = 1; - } - } - - if (!Add) { - if ((Result = Dot1 * Dot2) <= 0 && (Dot1 + Dot2)) { - Add = 1; - } - else if (tmat_dot_3d(rl->tl->gn, rl->tr->gn, 0) < threshold) { - Add = 2; - } - else if (rl->tl && rl->tr && rl->tl->material_id != rl->tr->material_id) { - Add = 3; - } - } - - if (Add == 1) { - rl->flags |= LANPR_EDGE_FLAG_CONTOUR; - list_append_pointer_static(&rb->contours, &rb->render_data_pool, rl); - contour_count++; - } - else if (Add == 2) { - rl->flags |= LANPR_EDGE_FLAG_CREASE; - list_append_pointer_static(&rb->crease_lines, &rb->render_data_pool, rl); - crease_count++; - } - else if (Add == 3) { - rl->flags |= LANPR_EDGE_FLAG_MATERIAL; - list_append_pointer_static(&rb->material_lines, &rb->render_data_pool, rl); - MaterialCount++; - } - if (rl->flags & LANPR_EDGE_FLAG_EDGE_MARK) { - /* no need to mark again */ - Add = 4; - list_append_pointer_static(&rb->edge_marks, &rb->render_data_pool, rl); - /* continue; */ - } - if (Add) { - int r1, r2, c1, c2, row, col; - if (lanpr_get_line_bounding_areas(rb, rl, &r1, &r2, &c1, &c2)) { - for (row = r1; row != r2 + 1; row++) { - for (col = c1; col != c2 + 1; col++) { - lanpr_link_line_with_bounding_area(rb, &rb->initial_bounding_areas[row * 4 + col], rl); - } - } - } - } - - /* line count reserved for feature such as progress feedback */ - } -} - -static void lanpr_clear_render_state(LANPR_RenderBuffer *rb) -{ - rb->contour_count = 0; - rb->contour_managed = 0; - rb->intersection_count = 0; - rb->intersection_managed = 0; - rb->material_line_count = 0; - rb->material_managed = 0; - rb->crease_count = 0; - rb->crease_managed = 0; -} - -/* Buffer operations */ - -void ED_lanpr_destroy_render_data(LANPR_RenderBuffer *rb) -{ - if (!rb) { - return; - } - - rb->contour_count = 0; - rb->contour_managed = 0; - rb->intersection_count = 0; - rb->intersection_managed = 0; - rb->material_line_count = 0; - rb->material_managed = 0; - rb->crease_count = 0; - rb->crease_managed = 0; - rb->edge_mark_count = 0; - rb->edge_mark_managed = 0; - - list_handle_empty(&rb->contours); - list_handle_empty(&rb->intersection_lines); - list_handle_empty(&rb->crease_lines); - list_handle_empty(&rb->material_lines); - list_handle_empty(&rb->edge_marks); - list_handle_empty(&rb->all_render_lines); - list_handle_empty(&rb->chains); - - list_handle_empty(&rb->vertex_buffer_pointers); - list_handle_empty(&rb->line_buffer_pointers); - list_handle_empty(&rb->triangle_buffer_pointers); - - BLI_spin_end(&rb->cs_data); - BLI_spin_end(&rb->cs_info); - BLI_spin_end(&rb->cs_management); - BLI_spin_end(&rb->render_data_pool.cs_mem); - - mem_static_destroy(&rb->render_data_pool); -} -LANPR_RenderBuffer *ED_lanpr_create_render_buffer() -{ - if (lanpr_share.render_buffer_shared) { - ED_lanpr_destroy_render_data(lanpr_share.render_buffer_shared); - return lanpr_share.render_buffer_shared; - } - - LANPR_RenderBuffer *rb = MEM_callocN(sizeof(LANPR_RenderBuffer), "LANPR render buffer"); - - lanpr_share.render_buffer_shared = rb; - - rb->cached_for_frame = -1; - - BLI_spin_init(&rb->cs_data); - BLI_spin_init(&rb->cs_info); - BLI_spin_init(&rb->cs_management); - BLI_spin_init(&rb->render_data_pool.cs_mem); - - return rb; -} - -static int lanpr_max_occlusion_in_collections(Collection *c) -{ - CollectionChild *cc; - int max_occ = 0; - int max; - if (c->lanpr.use_multiple_levels) { - max = MAX2(c->lanpr.level_begin, c->lanpr.level_end); - } - else { - max = c->lanpr.level_begin; - } - max_occ = MAX2(max, max_occ); - - for (cc = c->children.first; cc; cc = cc->next) { - max = lanpr_max_occlusion_in_collections(cc->collection); - max_occ = MAX2(max, max_occ); - } - - return max_occ; -} -static int lanpr_max_occlusion_in_targets(Depsgraph *depsgraph) -{ - int max_occ = 0; - int max; - Scene *s = DEG_get_evaluated_scene(depsgraph); - - /* Objects */ - DEG_OBJECT_ITER_BEGIN (depsgraph, - o, - DEG_ITER_OBJECT_FLAG_LINKED_DIRECTLY | DEG_ITER_OBJECT_FLAG_VISIBLE | - DEG_ITER_OBJECT_FLAG_DUPLI | DEG_ITER_OBJECT_FLAG_LINKED_VIA_SET) { - ModifierData *md; - for (md = o->modifiers.first; md; md = md->next) { - if (md->type == eModifierType_FeatureLine) { - FeatureLineModifierData *flmd = (FeatureLineModifierData *)md; - if (flmd->target) { - if (flmd->use_multiple_levels) { - max = MAX2(flmd->level_begin, flmd->level_end); - } - else { - max = flmd->level_begin; - } - max_occ = MAX2(max, max_occ); - } - } - } - } - DEG_OBJECT_ITER_END; - - /* Collections */ - max = lanpr_max_occlusion_in_collections(s->master_collection); - - max_occ = MAX2(max, max_occ); - - return max_occ; -} -static int lanpr_get_max_occlusion_level(Depsgraph *dg) -{ - Scene *s = DEG_get_evaluated_scene(dg); - SceneLANPR *lanpr = &s->lanpr; - if (!strcmp(s->r.engine, RE_engine_id_BLENDER_LANPR)) { - /* Use the line layers in scene LANPR settings */ - return ED_lanpr_max_occlusion_in_line_layers(lanpr); - } - else { - /* Other engines, use GPencil configurations */ - return lanpr_max_occlusion_in_targets(dg); - } -} - -void lanpr_rebuild_render_draw_command(LANPR_RenderBuffer *rb, LANPR_LineLayer *ll); - -static int lanpr_get_render_triangle_size(LANPR_RenderBuffer *rb) -{ - if (rb->thread_count == 0) { - rb->thread_count = BKE_render_num_threads(&rb->scene->r); - } - return sizeof(LANPR_RenderTriangle) + (sizeof(LANPR_RenderLine *) * rb->thread_count); -} - -int lanpr_count_this_line(LANPR_RenderLine *rl, LANPR_LineLayer *ll) -{ - LANPR_LineLayerComponent *llc = ll->components.first; - int AndResult = 1, OrResult = 0; - if (!llc) { - return 1; - } - for (; llc; llc = llc->next) { - if (llc->component_mode == LANPR_COMPONENT_MODE_ALL) { - OrResult = 1; - } - else if (llc->component_mode == LANPR_COMPONENT_MODE_OBJECT && llc->object_select) { - if (rl->object_ref && rl->object_ref->id.orig_id == &llc->object_select->id) { - OrResult = 1; - } - else { - AndResult = 0; - } - } - else if (llc->component_mode == LANPR_COMPONENT_MODE_MATERIAL && llc->material_select) { - if ((rl->tl && rl->tl->material_id == llc->material_select->index) || - (rl->tr && rl->tr->material_id == llc->material_select->index) || - (!(rl->flags & LANPR_EDGE_FLAG_INTERSECTION))) { - OrResult = 1; - } - else { - AndResult = 0; - } - } - else if (llc->component_mode == LANPR_COMPONENT_MODE_COLLECTION && llc->collection_select) { - if (BKE_collection_has_object(llc->collection_select, - (Object *)rl->object_ref->id.orig_id)) { - OrResult = 1; - } - else { - AndResult = 0; - } - } - } - if (ll->logic_mode == LANPR_COMPONENT_LOGIG_OR) { - return OrResult; - } - else { - return AndResult; - } -} -long lanpr_count_leveled_edge_segment_count(ListBase *LineList, LANPR_LineLayer *ll) -{ - LinkData *lip; - LANPR_RenderLine *rl; - LANPR_RenderLineSegment *rls; - long Count = 0; - for (lip = LineList->first; lip; lip = lip->next) { - rl = lip->data; - if (!lanpr_count_this_line(rl, ll)) { - continue; - } - - for (rls = rl->segments.first; rls; rls = rls->next) { - - if (!ll->use_multiple_levels) { - if (rls->occlusion == ll->qi_begin) { - Count++; - } - } - else { - if (rls->occlusion >= ll->qi_begin && rls->occlusion <= ll->qi_end) { - Count++; - } - } - } - } - return Count; -} -long lanpr_count_intersection_segment_count(LANPR_RenderBuffer *rb) -{ - LANPR_RenderLine *rl; - LANPR_RenderLineSegment *rls; - long Count = 0; - for (rl = rb->intersection_lines.first; rl; rl = rl->next) { - Count++; - } - return Count; -} -void *lanpr_make_leveled_edge_vertex_array(LANPR_RenderBuffer *rb, - ListBase *LineList, - float *vertexArray, - float *NormalArray, - float **NextNormal, - LANPR_LineLayer *ll, - float componet_id) -{ - LinkData *lip; - LANPR_RenderLine *rl; - LANPR_RenderLineSegment *rls, *irls; - Object *o; - real W = rb->w / 2, H = rb->h / 2; - long i = 0; - float *v = vertexArray; - float *N = NormalArray; - for (lip = LineList->first; lip; lip = lip->next) { - rl = lip->data; - if (!lanpr_count_this_line(rl, ll)) { - continue; - } - - for (rls = rl->segments.first; rls; rls = rls->next) { - int use = 0; - if (!ll->use_multiple_levels) { - if (rls->occlusion == ll->qi_begin) { - use = 1; - } - } - else { - if (rls->occlusion >= ll->qi_begin && rls->occlusion <= ll->qi_end) { - use = 1; - } - } - - if (!use) - continue; - - if (rl->tl) { - N[0] += rl->tl->gn[0]; - N[1] += rl->tl->gn[1]; - N[2] += rl->tl->gn[2]; - } - if (rl->tr) { - N[0] += rl->tr->gn[0]; - N[1] += rl->tr->gn[1]; - N[2] += rl->tr->gn[2]; - } - if (rl->tl || rl->tr) { - normalize_v3(N); - copy_v3_v3(&N[3], N); - } - N += 6; - - CLAMP(rls->at, 0, 1); - if (irls = rls->next) { - CLAMP(irls->at, 0, 1); - } - - *v = tnsLinearItp(rl->l->fbcoord[0], rl->r->fbcoord[0], rls->at); - v++; - *v = tnsLinearItp(rl->l->fbcoord[1], rl->r->fbcoord[1], rls->at); - v++; - *v = componet_id; - v++; - *v = tnsLinearItp(rl->l->fbcoord[0], rl->r->fbcoord[0], irls ? irls->at : 1); - v++; - *v = tnsLinearItp(rl->l->fbcoord[1], rl->r->fbcoord[1], irls ? irls->at : 1); - v++; - *v = componet_id; - v++; - } - } - *NextNormal = N; - return v; -} - -void lanpr_chain_generate_draw_command(LANPR_RenderBuffer *rb); - -#define TNS_BOUND_AREA_CROSSES(b1, b2) \ - ((b1)[0] < (b2)[1] && (b1)[1] > (b2)[0] && (b1)[3] < (b2)[2] && (b1)[2] > (b2)[3]) - -static void lanpr_make_initial_bounding_areas(LANPR_RenderBuffer *rb) -{ - int sp_w = 4; /* 20; */ - int sp_h = 4; /* rb->H / (rb->W / sp_w); */ - int row, col; - LANPR_BoundingArea *ba; - real W = (real)rb->w; - real H = (real)rb->h; - real span_w = (real)1 / sp_w * 2.0; - real span_h = (real)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; - - rb->bounding_area_count = sp_w * sp_h; - rb->initial_bounding_areas = mem_static_aquire( - &rb->render_data_pool, sizeof(LANPR_BoundingArea) * rb->bounding_area_count); - - for (row = 0; row < sp_h; row++) { - for (col = 0; col < sp_w; col++) { - ba = &rb->initial_bounding_areas[row * 4 + col]; - - ba->l = span_w * col - 1.0; - ba->r = (col == sp_w - 1) ? 1.0 : (span_w * (col + 1) - 1.0); - ba->u = 1.0 - span_h * row; - ba->b = (row == sp_h - 1) ? -1.0 : (1.0 - span_h * (row + 1)); - - ba->cx = (ba->l + ba->r) / 2; - ba->cy = (ba->u + ba->b) / 2; - - if (row) { - list_append_pointer_static( - &ba->up, &rb->render_data_pool, &rb->initial_bounding_areas[(row - 1) * 4 + col]); - } - if (col) { - list_append_pointer_static( - &ba->lp, &rb->render_data_pool, &rb->initial_bounding_areas[row * 4 + col - 1]); - } - if (row != sp_h - 1) { - list_append_pointer_static( - &ba->bp, &rb->render_data_pool, &rb->initial_bounding_areas[(row + 1) * 4 + col]); - } - if (col != sp_w - 1) { - list_append_pointer_static( - &ba->rp, &rb->render_data_pool, &rb->initial_bounding_areas[row * 4 + col + 1]); - } - } - } -} -static void lanpr_connect_new_bounding_areas(LANPR_RenderBuffer *rb, LANPR_BoundingArea *Root) -{ - LANPR_BoundingArea *ba = Root->child, *tba; - LinkData *lip, *lip2, *next_lip; - LANPR_StaticMemPool *mph = &rb->render_data_pool; - - list_append_pointer_static_pool(mph, &ba[1].rp, &ba[0]); - list_append_pointer_static_pool(mph, &ba[0].lp, &ba[1]); - list_append_pointer_static_pool(mph, &ba[1].bp, &ba[2]); - list_append_pointer_static_pool(mph, &ba[2].up, &ba[1]); - list_append_pointer_static_pool(mph, &ba[2].rp, &ba[3]); - list_append_pointer_static_pool(mph, &ba[3].lp, &ba[2]); - list_append_pointer_static_pool(mph, &ba[3].up, &ba[0]); - list_append_pointer_static_pool(mph, &ba[0].bp, &ba[3]); - - for (lip = Root->lp.first; lip; lip = lip->next) { - tba = lip->data; - if (ba[1].u > tba->b && ba[1].b < tba->u) { - list_append_pointer_static_pool(mph, &ba[1].lp, tba); - list_append_pointer_static_pool(mph, &tba->rp, &ba[1]); - } - if (ba[2].u > tba->b && ba[2].b < tba->u) { - list_append_pointer_static_pool(mph, &ba[2].lp, tba); - list_append_pointer_static_pool(mph, &tba->rp, &ba[2]); - } - } - for (lip = Root->rp.first; lip; lip = lip->next) { - tba = lip->data; - if (ba[0].u > tba->b && ba[0].b < tba->u) { - list_append_pointer_static_pool(mph, &ba[0].rp, tba); - list_append_pointer_static_pool(mph, &tba->lp, &ba[0]); - } - if (ba[3].u > tba->b && ba[3].b < tba->u) { - list_append_pointer_static_pool(mph, &ba[3].rp, tba); - list_append_pointer_static_pool(mph, &tba->lp, &ba[3]); - } - } - for (lip = Root->up.first; lip; lip = lip->next) { - tba = lip->data; - if (ba[0].r > tba->l && ba[0].l < tba->r) { - list_append_pointer_static_pool(mph, &ba[0].up, tba); - list_append_pointer_static_pool(mph, &tba->bp, &ba[0]); - } - if (ba[1].r > tba->l && ba[1].l < tba->r) { - list_append_pointer_static_pool(mph, &ba[1].up, tba); - list_append_pointer_static_pool(mph, &tba->bp, &ba[1]); - } - } - for (lip = Root->bp.first; lip; lip = lip->next) { - tba = lip->data; - if (ba[2].r > tba->l && ba[2].l < tba->r) { - list_append_pointer_static_pool(mph, &ba[2].bp, tba); - list_append_pointer_static_pool(mph, &tba->up, &ba[2]); - } - if (ba[3].r > tba->l && ba[3].l < tba->r) { - list_append_pointer_static_pool(mph, &ba[3].bp, tba); - list_append_pointer_static_pool(mph, &tba->up, &ba[3]); - } - } - for (lip = Root->lp.first; lip; lip = lip->next) { - for (lip2 = ((LANPR_BoundingArea *)lip->data)->rp.first; lip2; lip2 = next_lip) { - next_lip = lip2->next; - tba = lip2->data; - if (tba == Root) { - list_remove_pointer_item_no_free(&((LANPR_BoundingArea *)lip->data)->rp, lip2); - if (ba[1].u > tba->b && ba[1].b < tba->u) { - list_append_pointer_static_pool(mph, &tba->rp, &ba[1]); - } - if (ba[2].u > tba->b && ba[2].b < tba->u) { - list_append_pointer_static_pool(mph, &tba->rp, &ba[2]); - } - } - } - } - for (lip = Root->rp.first; lip; lip = lip->next) { - for (lip2 = ((LANPR_BoundingArea *)lip->data)->lp.first; lip2; lip2 = next_lip) { - next_lip = lip2->next; - tba = lip2->data; - if (tba == Root) { - list_remove_pointer_item_no_free(&((LANPR_BoundingArea *)lip->data)->lp, lip2); - if (ba[0].u > tba->b && ba[0].b < tba->u) { - list_append_pointer_static_pool(mph, &tba->lp, &ba[0]); - } - if (ba[3].u > tba->b && ba[3].b < tba->u) { - list_append_pointer_static_pool(mph, &tba->lp, &ba[3]); - } - } - } - } - for (lip = Root->up.first; lip; lip = lip->next) { - for (lip2 = ((LANPR_BoundingArea *)lip->data)->bp.first; lip2; lip2 = next_lip) { - next_lip = lip2->next; - tba = lip2->data; - if (tba == Root) { - list_remove_pointer_item_no_free(&((LANPR_BoundingArea *)lip->data)->bp, lip2); - if (ba[0].r > tba->l && ba[0].l < tba->r) { - list_append_pointer_static_pool(mph, &tba->up, &ba[0]); - } - if (ba[1].r > tba->l && ba[1].l < tba->r) { - list_append_pointer_static_pool(mph, &tba->up, &ba[1]); - } - } - } - } - for (lip = Root->bp.first; lip; lip = lip->next) { - for (lip2 = ((LANPR_BoundingArea *)lip->data)->up.first; lip2; lip2 = next_lip) { - next_lip = lip2->next; - tba = lip2->data; - if (tba == Root) { - list_remove_pointer_item_no_free(&((LANPR_BoundingArea *)lip->data)->up, lip2); - if (ba[2].r > tba->l && ba[2].l < tba->r) { - list_append_pointer_static_pool(mph, &tba->bp, &ba[2]); - } - if (ba[3].r > tba->l && ba[3].l < tba->r) { - list_append_pointer_static_pool(mph, &tba->bp, &ba[3]); - } - } - } - } - while (list_pop_pointer_no_free(&Root->lp)) - ; - while (list_pop_pointer_no_free(&Root->rp)) - ; - while (list_pop_pointer_no_free(&Root->up)) - ; - while (list_pop_pointer_no_free(&Root->bp)) - ; -} -static void lanpr_link_triangle_with_bounding_area(LANPR_RenderBuffer *rb, - LANPR_BoundingArea *RootBoundingArea, - LANPR_RenderTriangle *rt, - real *LRUB, - int Recursive); -static void lanpr_triangle_calculate_intersections_in_bounding_area(LANPR_RenderBuffer *rb, - LANPR_RenderTriangle *rt, - LANPR_BoundingArea *ba); - -static void lanpr_split_bounding_area(LANPR_RenderBuffer *rb, LANPR_BoundingArea *Root) -{ - LANPR_BoundingArea *ba = mem_static_aquire(&rb->render_data_pool, - sizeof(LANPR_BoundingArea) * 4); - LANPR_RenderTriangle *rt; - - ba[0].l = Root->cx; - ba[0].r = Root->r; - ba[0].u = Root->u; - ba[0].b = Root->cy; - ba[0].cx = (ba[0].l + ba[0].r) / 2; - ba[0].cy = (ba[0].u + ba[0].b) / 2; - - ba[1].l = Root->l; - ba[1].r = Root->cx; - ba[1].u = Root->u; - ba[1].b = Root->cy; - ba[1].cx = (ba[1].l + ba[1].r) / 2; - ba[1].cy = (ba[1].u + ba[1].b) / 2; - - ba[2].l = Root->l; - ba[2].r = Root->cx; - ba[2].u = Root->cy; - ba[2].b = Root->b; - ba[2].cx = (ba[2].l + ba[2].r) / 2; - ba[2].cy = (ba[2].u + ba[2].b) / 2; - - ba[3].l = Root->cx; - ba[3].r = Root->r; - ba[3].u = Root->cy; - ba[3].b = Root->b; - ba[3].cx = (ba[3].l + ba[3].r) / 2; - ba[3].cy = (ba[3].u + ba[3].b) / 2; - - Root->child = ba; - - lanpr_connect_new_bounding_areas(rb, Root); - - while (rt = list_pop_pointer_no_free(&Root->linked_triangles)) { - LANPR_BoundingArea *ba = Root->child; - real b[4]; - b[0] = MIN3(rt->v[0]->fbcoord[0], rt->v[1]->fbcoord[0], rt->v[2]->fbcoord[0]); - b[1] = MAX3(rt->v[0]->fbcoord[0], rt->v[1]->fbcoord[0], rt->v[2]->fbcoord[0]); - b[2] = MAX3(rt->v[0]->fbcoord[1], rt->v[1]->fbcoord[1], rt->v[2]->fbcoord[1]); - b[3] = MIN3(rt->v[0]->fbcoord[1], rt->v[1]->fbcoord[1], rt->v[2]->fbcoord[1]); - if (TNS_BOUND_AREA_CROSSES(b, &ba[0].l)) { - lanpr_link_triangle_with_bounding_area(rb, &ba[0], rt, b, 0); - } - if (TNS_BOUND_AREA_CROSSES(b, &ba[1].l)) { - lanpr_link_triangle_with_bounding_area(rb, &ba[1], rt, b, 0); - } - if (TNS_BOUND_AREA_CROSSES(b, &ba[2].l)) { - lanpr_link_triangle_with_bounding_area(rb, &ba[2], rt, b, 0); - } - if (TNS_BOUND_AREA_CROSSES(b, &ba[3].l)) { - lanpr_link_triangle_with_bounding_area(rb, &ba[3], rt, b, 0); - } - } - - rb->bounding_area_count += 3; -} -static int lanpr_line_crosses_bounding_area(LANPR_RenderBuffer *fb, - tnsVector2d l, - tnsVector2d r, - LANPR_BoundingArea *ba) -{ - real vx, vy; - tnsVector4d converted; - real c1, c; - - if (((converted[0] = (real)ba->l) > MAX2(l[0], r[0])) || - ((converted[1] = (real)ba->r) < MIN2(l[0], r[0])) || - ((converted[2] = (real)ba->b) > MAX2(l[1], r[1])) || - ((converted[3] = (real)ba->u) < MIN2(l[1], r[1]))) { - return 0; - } - - vx = l[0] - r[0]; - vy = l[1] - r[1]; - - c1 = vx * (converted[2] - l[1]) - vy * (converted[0] - l[0]); - c = c1; - - c1 = vx * (converted[2] - l[1]) - vy * (converted[1] - l[0]); - if (c1 * c <= 0) { - return 1; - } - else { - c = c1; - } - - c1 = vx * (converted[3] - l[1]) - vy * (converted[0] - l[0]); - if (c1 * c <= 0) { - return 1; - } - else { - c = c1; - } - - c1 = vx * (converted[3] - l[1]) - vy * (converted[1] - l[0]); - if (c1 * c <= 0) { - return 1; - } - else { - c = c1; - } - - return 0; -} -static int lanpr_triangle_covers_bounding_area(LANPR_RenderBuffer *fb, - LANPR_RenderTriangle *rt, - LANPR_BoundingArea *ba) -{ - tnsVector2d p1, p2, p3, p4; - real *FBC1 = rt->v[0]->fbcoord, *FBC2 = rt->v[1]->fbcoord, *FBC3 = rt->v[2]->fbcoord; - - p3[0] = p1[0] = (real)ba->l; - p2[1] = p1[1] = (real)ba->b; - p2[0] = p4[0] = (real)ba->r; - p3[1] = p4[1] = (real)ba->u; - - if ((FBC1[0] >= p1[0] && FBC1[0] <= p2[0] && FBC1[1] >= p1[1] && FBC1[1] <= p3[1]) || - (FBC2[0] >= p1[0] && FBC2[0] <= p2[0] && FBC2[1] >= p1[1] && FBC2[1] <= p3[1]) || - (FBC3[0] >= p1[0] && FBC3[0] <= p2[0] && FBC3[1] >= p1[1] && FBC3[1] <= p3[1])) { - return 1; - } - - if (ED_lanpr_point_inside_triangled(p1, FBC1, FBC2, FBC3) || - ED_lanpr_point_inside_triangled(p2, FBC1, FBC2, FBC3) || - ED_lanpr_point_inside_triangled(p3, FBC1, FBC2, FBC3) || - ED_lanpr_point_inside_triangled(p4, FBC1, FBC2, FBC3)) { - return 1; - } - - if ((lanpr_line_crosses_bounding_area(fb, FBC1, FBC2, ba)) || - (lanpr_line_crosses_bounding_area(fb, FBC2, FBC3, ba)) || - (lanpr_line_crosses_bounding_area(fb, FBC3, FBC1, ba))) { - return 1; - } - - return 0; -} -static void lanpr_link_triangle_with_bounding_area(LANPR_RenderBuffer *rb, - LANPR_BoundingArea *RootBoundingArea, - LANPR_RenderTriangle *rt, - real *LRUB, - int Recursive) -{ - if (!lanpr_triangle_covers_bounding_area(rb, rt, RootBoundingArea)) { - return; - } - if (!RootBoundingArea->child) { - list_append_pointer_static_pool( - &rb->render_data_pool, &RootBoundingArea->linked_triangles, rt); - RootBoundingArea->triangle_count++; - if (RootBoundingArea->triangle_count > 200 && Recursive) { - lanpr_split_bounding_area(rb, RootBoundingArea); - } - if (Recursive && rb->enable_intersections) { - lanpr_triangle_calculate_intersections_in_bounding_area(rb, rt, RootBoundingArea); - } - } - else { - LANPR_BoundingArea *ba = RootBoundingArea->child; - real *B1 = LRUB; - real b[4]; - if (!LRUB) { - b[0] = MIN3(rt->v[0]->fbcoord[0], rt->v[1]->fbcoord[0], rt->v[2]->fbcoord[0]); - b[1] = MAX3(rt->v[0]->fbcoord[0], rt->v[1]->fbcoord[0], rt->v[2]->fbcoord[0]); - b[2] = MAX3(rt->v[0]->fbcoord[1], rt->v[1]->fbcoord[1], rt->v[2]->fbcoord[1]); - b[3] = MIN3(rt->v[0]->fbcoord[1], rt->v[1]->fbcoord[1], rt->v[2]->fbcoord[1]); - B1 = b; - } - if (TNS_BOUND_AREA_CROSSES(B1, &ba[0].l)) { - lanpr_link_triangle_with_bounding_area(rb, &ba[0], rt, B1, Recursive); - } - if (TNS_BOUND_AREA_CROSSES(B1, &ba[1].l)) { - lanpr_link_triangle_with_bounding_area(rb, &ba[1], rt, B1, Recursive); - } - if (TNS_BOUND_AREA_CROSSES(B1, &ba[2].l)) { - lanpr_link_triangle_with_bounding_area(rb, &ba[2], rt, B1, Recursive); - } - if (TNS_BOUND_AREA_CROSSES(B1, &ba[3].l)) { - lanpr_link_triangle_with_bounding_area(rb, &ba[3], rt, B1, Recursive); - } - } -} -static void lanpr_link_line_with_bounding_area(LANPR_RenderBuffer *rb, - LANPR_BoundingArea *RootBoundingArea, - LANPR_RenderLine *rl) -{ - if (!RootBoundingArea->child) { - list_append_pointer_static_pool(&rb->render_data_pool, &RootBoundingArea->linked_lines, rl); - } - else { - if (lanpr_line_crosses_bounding_area( - rb, rl->l->fbcoord, rl->r->fbcoord, &RootBoundingArea->child[0])) { - lanpr_link_line_with_bounding_area(rb, &RootBoundingArea->child[0], rl); - } - else if (lanpr_line_crosses_bounding_area( - rb, rl->l->fbcoord, rl->r->fbcoord, &RootBoundingArea->child[1])) { - lanpr_link_line_with_bounding_area(rb, &RootBoundingArea->child[1], rl); - } - else if (lanpr_line_crosses_bounding_area( - rb, rl->l->fbcoord, rl->r->fbcoord, &RootBoundingArea->child[2])) { - lanpr_link_line_with_bounding_area(rb, &RootBoundingArea->child[2], rl); - } - else if (lanpr_line_crosses_bounding_area( - rb, rl->l->fbcoord, rl->r->fbcoord, &RootBoundingArea->child[3])) { - lanpr_link_line_with_bounding_area(rb, &RootBoundingArea->child[3], rl); - } - } -} -static int lanpr_get_triangle_bounding_areas(LANPR_RenderBuffer *rb, - LANPR_RenderTriangle *rt, - int *rowBegin, - int *rowEnd, - int *colBegin, - int *colEnd) -{ - real sp_w = rb->width_per_tile, sp_h = rb->height_per_tile; - real b[4]; - - if (!rt->v[0] || !rt->v[1] || !rt->v[2]) { - return 0; - } - - b[0] = MIN3(rt->v[0]->fbcoord[0], rt->v[1]->fbcoord[0], rt->v[2]->fbcoord[0]); - b[1] = MAX3(rt->v[0]->fbcoord[0], rt->v[1]->fbcoord[0], rt->v[2]->fbcoord[0]); - b[2] = MIN3(rt->v[0]->fbcoord[1], rt->v[1]->fbcoord[1], rt->v[2]->fbcoord[1]); - b[3] = MAX3(rt->v[0]->fbcoord[1], rt->v[1]->fbcoord[1], rt->v[2]->fbcoord[1]); - - if (b[0] > 1 || b[1] < -1 || b[2] > 1 || b[3] < -1) { - return 0; - } - - (*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; - - if ((*colEnd) >= rb->tile_count_x) { - (*colEnd) = rb->tile_count_x - 1; - } - if ((*rowEnd) >= rb->tile_count_y) { - (*rowEnd) = rb->tile_count_y - 1; - } - if ((*colBegin) < 0) { - (*colBegin) = 0; - } - if ((*rowBegin) < 0) { - (*rowBegin) = 0; - } - - return 1; -} -static int lanpr_get_line_bounding_areas(LANPR_RenderBuffer *rb, - LANPR_RenderLine *rl, - int *rowBegin, - int *rowEnd, - int *colBegin, - int *colEnd) -{ - real sp_w = rb->width_per_tile, sp_h = rb->height_per_tile; - real b[4]; - - if (!rl->l || !rl->r) { - return 0; - } - - if (rl->l->fbcoord[0] != rl->l->fbcoord[0] || rl->r->fbcoord[0] != rl->r->fbcoord[0]) { - return 0; - } - - b[0] = MIN2(rl->l->fbcoord[0], rl->r->fbcoord[0]); - b[1] = MAX2(rl->l->fbcoord[0], rl->r->fbcoord[0]); - b[2] = MIN2(rl->l->fbcoord[1], rl->r->fbcoord[1]); - b[3] = MAX2(rl->l->fbcoord[1], rl->r->fbcoord[1]); - - if (b[0] > 1 || b[1] < -1 || b[2] > 1 || b[3] < -1) { - return 0; - } - - (*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; - - if ((*colEnd) >= rb->tile_count_x) { - (*colEnd) = rb->tile_count_x - 1; - } - if ((*rowEnd) >= rb->tile_count_y) { - (*rowEnd) = rb->tile_count_y - 1; - } - if ((*colBegin) < 0) { - (*colBegin) = 0; - } - if ((*rowBegin) < 0) { - (*rowBegin) = 0; - } - - return 1; -} -LANPR_BoundingArea *ED_lanpr_get_point_bounding_area(LANPR_RenderBuffer *rb, real x, real y) -{ - real sp_w = rb->width_per_tile, sp_h = rb->height_per_tile; - int col, row; - - if (x > 1 || x < -1 || y > 1 || y < -1) { - return 0; - } - - col = (int)((x + 1.0) / sp_w); - row = rb->tile_count_y - (int)((y + 1.0) / sp_h) - 1; - - if (col >= rb->tile_count_x) { - col = rb->tile_count_x - 1; - } - if (row >= rb->tile_count_y) { - row = rb->tile_count_y - 1; - } - if (col < 0) { - col = 0; - } - if (row < 0) { - row = 0; - } - - return &rb->initial_bounding_areas[row * 4 + col]; -} -static LANPR_BoundingArea *lanpr_get_point_bounding_area_recursive(LANPR_BoundingArea *ba, - real x, - real y) -{ - if (!ba->child) { - return ba; - } - else { - LANPR_BoundingArea *ch = ba->child; -#define IN_BOUND(i, x, y) \ - ba->child[i].l <= x && ba->child[i].r >= x && ba->child[i].b <= y && ba->child[i].u >= y - - if (IN_BOUND(0, x, y)) { - return lanpr_get_point_bounding_area_recursive(&ba->child[0], x, y); - } - else if (IN_BOUND(1, x, y)) { - return lanpr_get_point_bounding_area_recursive(&ba->child[1], x, y); - } - else if (IN_BOUND(2, x, y)) { - return lanpr_get_point_bounding_area_recursive(&ba->child[2], x, y); - } - else if (IN_BOUND(3, x, y)) { - return lanpr_get_point_bounding_area_recursive(&ba->child[3], x, y); - } - } - return NULL; -} -LANPR_BoundingArea *ED_lanpr_get_point_bounding_area_deep(LANPR_RenderBuffer *rb, real x, real y) -{ - LANPR_BoundingArea *ba; - if (ba = ED_lanpr_get_point_bounding_area(rb, x, y)) { - return lanpr_get_point_bounding_area_recursive(ba, x, y); - } - return NULL; -} - -static void lanpr_add_triangles(LANPR_RenderBuffer *rb) -{ - LANPR_RenderElementLinkNode *reln; - LANPR_RenderTriangle *rt; - /* tnsMatrix44d vP; */ - Camera *c = ((Camera *)rb->scene->camera); - int i, lim; - int x1, x2, y1, y2; - int r, co; - /* tnsMatrix44d proj, view, result, inv; */ - /* tmat_make_perspective_matrix_44d(proj, c->FOv, (real)fb->W / (real)fb->H, c->clipsta, */ - /* c->clipend); tmat_load_identity_44d(view); tObjApplyself_transformMatrix(c, 0); */ - /* tObjApplyGlobalTransformMatrixReverted(c); */ - /* tmat_inverse_44d(inv, c->Base.GlobalTransform); */ - /* tmat_multiply_44d(result, proj, inv); */ - /* memcpy(proj, result, sizeof(tnsMatrix44d)); */ - - /* tnsglobal_TriangleIntersectionCount = 0; */ - - /* tnsset_RenderOverallProgress(rb, NUL_MH2); */ - /* nulThreadNotifyUsers("tns.render_buffer_list.calculation_status"); */ - - for (reln = rb->triangle_buffer_pointers.first; reln; reln = reln->next) { - rt = reln->pointer; - lim = reln->element_count; - for (i = 0; i < lim; i++) { - if (rt->cull_status) { - rt = (void *)(((BYTE *)rt) + rb->triangle_size); - continue; - } - if (lanpr_get_triangle_bounding_areas(rb, rt, &y1, &y2, &x1, &x2)) { - for (co = x1; co <= x2; co++) { - for (r = y1; r <= y2; r++) { - lanpr_link_triangle_with_bounding_area( - rb, &rb->initial_bounding_areas[r * 4 + co], rt, 0, 1); - } - } - } - else { - ; /* throw away. */ - } - rt = (void *)(((BYTE *)rt) + rb->triangle_size); - /* if (tnsglobal_TriangleIntersectionCount >= 2000) { */ - /* tnsset_PlusRenderIntersectionCount(rb, tnsglobal_TriangleIntersectionCount); */ - /* tnsglobal_TriangleIntersectionCount = 0; */ - /* } */ - } - } - /* tnsset_PlusRenderIntersectionCount(rb, tnsglobal_TriangleIntersectionCount); */ -} -static LANPR_BoundingArea *lanpr_get_next_bounding_area(LANPR_BoundingArea *This, - LANPR_RenderLine *rl, - real x, - real y, - real k, - int PositiveX, - int PositiveY, - real *NextX, - real *NextY) -{ - real rx, ry, ux, uy, lx, ly, bx, by; - real r1, r2; - LANPR_BoundingArea *ba; - LinkData *lip; - if (PositiveX > 0) { - rx = This->r; - ry = y + k * (rx - x); - if (PositiveY > 0) { - uy = This->u; - ux = x + (uy - y) / k; - r1 = tMatGetLinearRatio(rl->l->fbcoord[0], rl->r->fbcoord[0], rx); - r2 = tMatGetLinearRatio(rl->l->fbcoord[0], rl->r->fbcoord[0], ux); - if (MIN2(r1, r2) > 1) { - return 0; - } - if (r1 <= r2) { - for (lip = This->rp.first; lip; lip = lip->next) { - ba = lip->data; - if (ba->u >= ry && ba->b < ry) { - *NextX = rx; - *NextY = ry; - return ba; - } - } - } - else { - for (lip = This->up.first; lip; lip = lip->next) { - ba = lip->data; - if (ba->r >= ux && ba->l < ux) { - *NextX = ux; - *NextY = uy; - return ba; - } - } - } - } - else if (PositiveY < 0) { - by = This->b; - bx = x + (by - y) / k; - r1 = tMatGetLinearRatio(rl->l->fbcoord[0], rl->r->fbcoord[0], rx); - r2 = tMatGetLinearRatio(rl->l->fbcoord[0], rl->r->fbcoord[0], bx); - if (MIN2(r1, r2) > 1) { - return 0; - } - if (r1 <= r2) { - for (lip = This->rp.first; lip; lip = lip->next) { - ba = lip->data; - if (ba->u >= ry && ba->b < ry) { - *NextX = rx; - *NextY = ry; - return ba; - } - } - } - else { - for (lip = This->bp.first; lip; lip = lip->next) { - ba = lip->data; - if (ba->r >= bx && ba->l < bx) { - *NextX = bx; - *NextY = by; - return ba; - } - } - } - } - else { /* Y diffence == 0 */ - r1 = tMatGetLinearRatio(rl->l->fbcoord[0], rl->r->fbcoord[0], This->r); - if (r1 > 1) { - return 0; - } - for (lip = This->rp.first; lip; lip = lip->next) { - ba = lip->data; - if (ba->u >= y && ba->b < y) { - *NextX = This->r; - *NextY = y; - return ba; - } - } - } - } - else if (PositiveX < 0) { /* X diffence < 0 */ - lx = This->l; - ly = y + k * (lx - x); - if (PositiveY > 0) { - uy = This->u; - ux = x + (uy - y) / k; - r1 = tMatGetLinearRatio(rl->l->fbcoord[0], rl->r->fbcoord[0], lx); - r2 = tMatGetLinearRatio(rl->l->fbcoord[0], rl->r->fbcoord[0], ux); - if (MIN2(r1, r2) > 1) { - return 0; - } - if (r1 <= r2) { - for (lip = This->lp.first; lip; lip = lip->next) { - ba = lip->data; - if (ba->u >= ly && ba->b < ly) { - *NextX = lx; - *NextY = ly; - return ba; - } - } - } - else { - for (lip = This->up.first; lip; lip = lip->next) { - ba = lip->data; - if (ba->r >= ux && ba->l < ux) { - *NextX = ux; - *NextY = uy; - return ba; - } - } - } - } - else if (PositiveY < 0) { - by = This->b; - bx = x + (by - y) / k; - r1 = tMatGetLinearRatio(rl->l->fbcoord[0], rl->r->fbcoord[0], lx); - r2 = tMatGetLinearRatio(rl->l->fbcoord[0], rl->r->fbcoord[0], bx); - if (MIN2(r1, r2) > 1) { - return 0; - } - if (r1 <= r2) { - for (lip = This->lp.first; lip; lip = lip->next) { - ba = lip->data; - if (ba->u >= ly && ba->b < ly) { - *NextX = lx; - *NextY = ly; - return ba; - } - } - } - else { - for (lip = This->bp.first; lip; lip = lip->next) { - ba = lip->data; - if (ba->r >= bx && ba->l < bx) { - *NextX = bx; - *NextY = by; - return ba; - } - } - } - } - else { /* Y diffence == 0 */ - r1 = tMatGetLinearRatio(rl->l->fbcoord[0], rl->r->fbcoord[0], This->l); - if (r1 > 1) { - return 0; - } - for (lip = This->lp.first; lip; lip = lip->next) { - ba = lip->data; - if (ba->u >= y && ba->b < y) { - *NextX = This->l; - *NextY = y; - return ba; - } - } - } - } - else { /* X difference == 0; */ - if (PositiveY > 0) { - r1 = tMatGetLinearRatio(rl->l->fbcoord[1], rl->r->fbcoord[1], This->u); - if (r1 > 1) { - return 0; - } - for (lip = This->up.first; lip; lip = lip->next) { - ba = lip->data; - if (ba->r > x && ba->l <= x) { - *NextX = x; - *NextY = This->u; - return ba; - } - } - } - else if (PositiveY < 0) { - r1 = tMatGetLinearRatio(rl->l->fbcoord[1], rl->r->fbcoord[1], This->b); - if (r1 > 1) { - return 0; - } - for (lip = This->bp.first; lip; lip = lip->next) { - ba = lip->data; - if (ba->r > x && ba->l <= x) { - *NextX = x; - *NextY = This->b; - return ba; - } - } - } - else - return 0; /* segment has no length */ - } - return 0; -} - -static LANPR_BoundingArea *lanpr_get_bounding_area(LANPR_RenderBuffer *rb, real x, real y) -{ - LANPR_BoundingArea *iba; - real sp_w = rb->width_per_tile, sp_h = rb->height_per_tile; - int c = (int)((x + 1.0) / sp_w); - int r = rb->tile_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 (c >= rb->tile_count_x) { - c = rb->tile_count_x - 1; - } - - iba = &rb->initial_bounding_areas[r * 4 + c]; - while (iba->child) { - if (x > iba->cx) { - if (y > iba->cy) { - iba = &iba->child[0]; - } - else { - iba = &iba->child[3]; - } - } - else { - if (y > iba->cy) { - iba = &iba->child[1]; - } - else { - iba = &iba->child[2]; - } - } - } - return iba; -} -static LANPR_BoundingArea *lanpr_get_first_possible_bounding_area(LANPR_RenderBuffer *rb, - LANPR_RenderLine *rl) -{ - LANPR_BoundingArea *iba; - real data[2] = {rl->l->fbcoord[0], rl->l->fbcoord[1]}; - tnsVector2d LU = {-1, 1}, RU = {1, 1}, LB = {-1, -1}, RB = {1, -1}; - real r = 1, sr = 1; - - if (data[0] > -1 && data[0] < 1 && data[1] > -1 && data[1] < 1) { - return lanpr_get_bounding_area(rb, data[0], data[1]); - } - else { - if ((lanpr_LineIntersectTest2d(rl->l->fbcoord, rl->r->fbcoord, LU, RU, &sr) && sr < r && - sr > 0) || - (lanpr_LineIntersectTest2d(rl->l->fbcoord, rl->r->fbcoord, LB, RB, &sr) && sr < r && - sr > 0) || - (lanpr_LineIntersectTest2d(rl->l->fbcoord, rl->r->fbcoord, LB, LU, &sr) && sr < r && - sr > 0) || - (lanpr_LineIntersectTest2d(rl->l->fbcoord, rl->r->fbcoord, RB, RU, &sr) && sr < r && - sr > 0)) { - r = sr; - } - interp_v2_v2v2_db(data, rl->l->fbcoord, rl->r->fbcoord, r); - - return lanpr_get_bounding_area(rb, data[0], data[1]); - } - - real sp_w = rb->width_per_tile, sp_h = rb->height_per_tile; - - return iba; -} - -/* Calculations */ - -int ED_lanpr_compute_feature_lines_internal(Depsgraph *depsgraph, int intersectons_only) -{ - LANPR_RenderBuffer *rb; - Scene *s = DEG_get_evaluated_scene(depsgraph); - SceneLANPR *lanpr = &s->lanpr; - int is_lanpr_engine = !strcmp(s->r.engine, RE_engine_id_BLENDER_LANPR); - - if (!is_lanpr_engine && !lanpr->enabled) { - return OPERATOR_CANCELLED; - } - - rb = ED_lanpr_create_render_buffer(); - - lanpr_share.render_buffer_shared = rb; - - rb->scene = s; - rb->w = s->r.xsch; - rb->h = s->r.ysch; - rb->enable_intersections = lanpr->enable_intersections; - - rb->triangle_size = lanpr_get_render_triangle_size(rb); - - rb->max_occlusion_level = lanpr_get_max_occlusion_level(depsgraph); - - lanpr_make_render_geometry_buffers(depsgraph, rb->scene, rb->scene->camera, rb); - - lanpr_compute_view_Vector(rb); - lanpr_cull_triangles(rb); - - lanpr_perspective_division(rb); - - lanpr_make_initial_bounding_areas(rb); - - if (!intersectons_only) { - lanpr_compute_scene_contours(rb, lanpr->crease_threshold); - } - - lanpr_add_triangles(rb); - - if (!intersectons_only) { - lanpr_THREAD_calculate_line_occlusion_begin(rb); - } - - /* When not using LANPR engine, chaining is forced in order to generate data for GPencil. */ - if ((lanpr->enable_chaining || !is_lanpr_engine) && (!intersectons_only)) { - float t_image = rb->scene->lanpr.chaining_image_threshold; - float t_geom = rb->scene->lanpr.chaining_geometry_threshold; - - ED_lanpr_NO_THREAD_chain_feature_lines(rb); - - if (is_lanpr_engine) { - /* Enough with it. We can provide an option after we have LANPR internal smoothing */ - return; - } - - /* Below are simply for better GPencil experience. */ - - ED_lanpr_split_chains_for_fixed_occlusion(rb); - - if (t_image < FLT_EPSILON && t_geom < FLT_EPSILON) { - t_geom = 0.0f; - t_image = 0.01f; - } - - ED_lanpr_connect_chains(rb, 1); - ED_lanpr_connect_chains(rb, 0); - - /* This configuration ensures there won't be accidental lost of short segments */ - ED_lanpr_discard_short_chains(rb, MIN3(t_image, t_geom, 0.01f) - FLT_EPSILON); - } - - rb->cached_for_frame = rb->scene->r.cfra; - - return OPERATOR_FINISHED; -} -static bool lanpr_camera_exists(struct bContext *c) -{ - Scene *s = CTX_data_scene(c); - return s->camera ? true : false; -} -static int lanpr_compute_feature_lines_exec(struct bContext *C, struct wmOperator *op) -{ - Scene *scene = CTX_data_scene(C); - SceneLANPR *lanpr = &scene->lanpr; - int result; - int is_lanpr_engine = !strcmp(scene->r.engine, RE_engine_id_BLENDER_LANPR); - - if (!is_lanpr_engine && !lanpr->enabled) { - return OPERATOR_CANCELLED; - } - - if (!scene->camera) { - BKE_report(op->reports, RPT_ERROR, "There is no active camera in this scene!"); - printf("LANPR Warning: There is no active camera in this scene!\n"); - return OPERATOR_FINISHED; - } - - int intersections_only = (is_lanpr_engine && lanpr->master_mode != LANPR_MASTER_MODE_SOFTWARE); - - result = ED_lanpr_compute_feature_lines_internal(CTX_data_depsgraph(C), intersections_only); - - lanpr_rebuild_all_command(lanpr); - - WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, NULL); - - return result; -} -static void lanpr_compute_feature_lines_cancel(struct bContext *C, struct wmOperator *op) -{ - - return; -} - -void SCENE_OT_lanpr_calculate_feature_lines(struct wmOperatorType *ot) -{ - - /* identifiers */ - ot->name = "Calculate Feature Lines"; - ot->description = "LANPR calculates feature line in current scene"; - ot->idname = "SCENE_OT_lanpr_calculate"; - - ot->poll = lanpr_camera_exists; - ot->cancel = lanpr_compute_feature_lines_cancel; - ot->exec = lanpr_compute_feature_lines_exec; -} - -/* SVG bindings */ - -static int lanpr_export_svg_exec(struct bContext *C, wmOperator *op) -{ - LANPR_RenderBuffer *rb = lanpr_share.render_buffer_shared; - SceneLANPR *lanpr = - &rb->scene->lanpr; /* XXX: This is not evaluated for copy_on_write stuff... */ - LANPR_LineLayer *ll; - - for (ll = lanpr->line_layers.first; ll; ll = ll->next) { - Text *ta = BKE_text_add(CTX_data_main(C), "exported_svg"); - ED_svg_data_from_lanpr_chain(ta, rb, ll); - } - - return OPERATOR_FINISHED; -} - -static bool lanpr_render_buffer_found(struct bContext *C) -{ - if (lanpr_share.render_buffer_shared) { - return true; - } - return false; -} - -void SCENE_OT_lanpr_export_svg(wmOperatorType *ot) -{ - PropertyRNA *prop; - - /* identifiers */ - ot->name = "Export LANPR to SVG"; - ot->description = "Export LANPR render result into a SVG file"; - ot->idname = "SCENE_OT_lanpr_export_svg"; - - /* callbacks */ - ot->exec = lanpr_export_svg_exec; - ot->poll = lanpr_render_buffer_found; - - /* flag */ - ot->flag = OPTYPE_USE_EVAL_DATA; - - /* properties */ - /* Should have: facing, layer, visibility, file split... */ -} - -/* Access */ - -bool ED_lanpr_dpix_shader_error() -{ - return lanpr_share.dpix_shader_error; -} -bool ED_lanpr_disable_edge_splits(Scene *s) -{ - return (s->lanpr.enabled && s->lanpr.disable_edge_splits); -} - -void ED_lanpr_copy_data(Scene *from, Scene *to) -{ - SceneLANPR *lanpr = &from->lanpr; - LANPR_RenderBuffer *rb = lanpr_share.render_buffer_shared, *new_rb; - LANPR_LineLayer *ll, *new_ll; - LANPR_LineLayerComponent *llc, *new_llc; - - list_handle_empty(&to->lanpr.line_layers); - - for (ll = lanpr->line_layers.first; ll; ll = ll->next) { - new_ll = MEM_callocN(sizeof(LANPR_LineLayer), "Copied Line Layer"); - memcpy(new_ll, ll, sizeof(LANPR_LineLayer)); - list_handle_empty(&new_ll->components); - new_ll->next = new_ll->prev = NULL; - BLI_addtail(&to->lanpr.line_layers, new_ll); - for (llc = ll->components.first; llc; llc = llc->next) { - new_llc = MEM_callocN(sizeof(LANPR_LineLayerComponent), "Copied Line Layer Component"); - memcpy(new_llc, llc, sizeof(LANPR_LineLayerComponent)); - new_llc->next = new_llc->prev = NULL; - BLI_addtail(&new_ll->components, new_llc); - } - } - - /* render_buffer now only accessible from lanpr_share */ -} - -void ED_lanpr_free_everything(Scene *s) -{ - SceneLANPR *lanpr = &s->lanpr; - LANPR_LineLayer *ll; - LANPR_LineLayerComponent *llc; - - while (ll = BLI_pophead(&lanpr->line_layers)) { - while (llc = BLI_pophead(&ll->components)) - MEM_freeN(llc); - MEM_freeN(ll); - } -} - -/* GPencil bindings */ - -static void lanpr_generate_gpencil_from_chain(Depsgraph *depsgraph, - Object *ob, - bGPDlayer *gpl, - bGPDframe *gpf, - int qi_begin, - int qi_end, - int material_nr, - Collection *col, - int types) -{ - Scene *scene = DEG_get_evaluated_scene(depsgraph); - LANPR_RenderBuffer *rb = lanpr_share.render_buffer_shared; - - if (rb == NULL) { - printf("NULL LANPR rb!\n"); - return; - } - if (scene->lanpr.master_mode != LANPR_MASTER_MODE_SOFTWARE) { - return; - } - - int color_idx = 0; - int tot_points = 0; - short thickness = 100; - - float mat[4][4]; - - unit_m4(mat); - - /* Split countour lines at occlution points and deselect occluded segment */ - LANPR_RenderLine *rl; - LANPR_RenderLineSegment *rls, *irls; - - LANPR_RenderLineChain *rlc; - LANPR_RenderLineChainItem *rlci; - for (rlc = rb->chains.first; rlc; rlc = rlc->next) { - - if (rlc->picked) { - continue; - } - if (ob && !rlc->object_ref) { - continue; /* intersection lines are all in the first collection running into here */ - } - if (!(rlc->type & types)) { - continue; - } - if (rlc->level > qi_end || rlc->level < qi_begin) { - continue; - } - if (ob && &ob->id != rlc->object_ref->id.orig_id) { - continue; - } - if (col && rlc->object_ref) { - if (!BKE_collection_has_object_recursive(col, (Object *)rlc->object_ref->id.orig_id)) { - continue; - } - } - - rlc->picked = 1; - - int array_idx = 0; - int count = ED_lanpr_count_chain(rlc); - bGPDstroke *gps = BKE_gpencil_add_stroke(gpf, color_idx, count, thickness); - - float *stroke_data = BLI_array_alloca(stroke_data, count * GP_PRIM_DATABUF_SIZE); - - for (rlci = rlc->chain.first; rlci; rlci = rlci->next) { - float opatity = 1.0f; /* rlci->occlusion ? 0.0f : 1.0f; */ - stroke_data[array_idx] = rlci->gpos[0]; - stroke_data[array_idx + 1] = rlci->gpos[1]; - stroke_data[array_idx + 2] = rlci->gpos[2]; - stroke_data[array_idx + 3] = 1; /* thickness */ - stroke_data[array_idx + 4] = opatity; /* hardness? */ - array_idx += 5; - } - - BKE_gpencil_stroke_add_points(gps, stroke_data, count, mat); - gps->mat_nr = material_nr; - } -} -static void lanpr_clear_gp_lanpr_flags(Depsgraph *dg, int frame) -{ - DEG_OBJECT_ITER_BEGIN (dg, - o, - DEG_ITER_OBJECT_FLAG_LINKED_DIRECTLY | DEG_ITER_OBJECT_FLAG_VISIBLE | - DEG_ITER_OBJECT_FLAG_DUPLI | DEG_ITER_OBJECT_FLAG_LINKED_VIA_SET) { - if (o->type == OB_GPENCIL) { - bGPdata *gpd = ((Object *)o->id.orig_id)->data; - bGPDlayer *gpl; - for (gpl = gpd->layers.first; gpl; gpl = gpl->next) { - bGPDframe *gpf = BKE_gpencil_layer_find_frame(gpl, frame); - if (!gpf) { - continue; - } - gpf->flag &= ~GP_FRAME_LANPR_CLEARED; - } - } - } - DEG_OBJECT_ITER_END; -} -static void lanpr_update_gp_strokes_recursive( - Depsgraph *dg, struct Collection *col, int frame, Object *source_only, Object *target_only) -{ - Object *ob; - Object *gpobj; - ModifierData *md; - bGPdata *gpd; - bGPDlayer *gpl; - bGPDframe *gpf; - CollectionObject *co; - CollectionChild *cc; - - for (co = col->gobject.first; co || source_only; co = co->next) { - ob = source_only ? source_only : co->ob; - for (md = ob->modifiers.first; md; md = md->next) { - if (md->type == eModifierType_FeatureLine) { - FeatureLineModifierData *flmd = (FeatureLineModifierData *)md; - if (flmd->target && flmd->target->type == OB_GPENCIL) { - gpobj = flmd->target; - - if (target_only && target_only != gpobj) { - continue; - } - - gpd = gpobj->data; - gpl = BKE_gpencil_layer_get_index(gpd, flmd->layer, 1); - if (!gpl) { - gpl = BKE_gpencil_layer_addnew(gpd, "lanpr_layer", true); - } - gpf = BKE_gpencil_layer_getframe(gpl, frame, GP_GETFRAME_ADD_NEW); - - if (gpf->strokes.first && - !lanpr_share.render_buffer_shared->scene->lanpr.gpencil_overwrite) { - continue; - } - - if (!(gpf->flag & GP_FRAME_LANPR_CLEARED)) { - BKE_gpencil_free_strokes(gpf); - gpf->flag |= GP_FRAME_LANPR_CLEARED; - } - - lanpr_generate_gpencil_from_chain(dg, - ob, - gpl, - gpf, - flmd->level_begin, - flmd->use_multiple_levels ? flmd->level_end : - flmd->level_begin, - flmd->material, - NULL, - flmd->types); - DEG_id_tag_update(&gpd->id, - ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_COPY_ON_WRITE); - } - } - } - if (source_only) { - return; - } - } - for (cc = col->children.first; cc; cc = cc->next) { - lanpr_update_gp_strokes_recursive(dg, cc->collection, frame, source_only, target_only); - } -} -static void lanpr_update_gp_strokes_collection( - Depsgraph *dg, struct Collection *col, int frame, int this_only, Object *target_only) -{ - Object *ob; - Object *gpobj; - ModifierData *md; - bGPdata *gpd; - bGPDlayer *gpl; - bGPDframe *gpf; - CollectionObject *co; - CollectionChild *cc; - - /* depth first */ - if (!this_only) { - for (cc = col->children.first; cc; cc = cc->next) { - lanpr_update_gp_strokes_collection(dg, cc->collection, frame, this_only, target_only); - } - } - - if (col->lanpr.usage != COLLECTION_LANPR_INCLUDE || !col->lanpr.target) { - return; - } - - gpobj = col->lanpr.target; - - if (target_only && target_only != gpobj) { - return; - } - - gpd = gpobj->data; - gpl = BKE_gpencil_layer_get_index(gpd, col->lanpr.layer, 1); - if (!gpl) { - gpl = BKE_gpencil_layer_addnew(gpd, "lanpr_layer", true); - } - gpf = BKE_gpencil_layer_getframe(gpl, frame, GP_GETFRAME_ADD_NEW); - - if (gpf->strokes.first && !lanpr_share.render_buffer_shared->scene->lanpr.gpencil_overwrite) { - return; - } - - if (!(gpf->flag & GP_FRAME_LANPR_CLEARED)) { - BKE_gpencil_free_strokes(gpf); - gpf->flag |= GP_FRAME_LANPR_CLEARED; - } - - lanpr_generate_gpencil_from_chain(dg, - NULL, - gpl, - gpf, - col->lanpr.level_begin, - col->lanpr.use_multiple_levels ? col->lanpr.level_end : - col->lanpr.level_begin, - col->lanpr.material, - col, - col->lanpr.types); - DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_COPY_ON_WRITE); -} -static void lanpr_update_gp_strokes_actual(Scene *scene, Depsgraph *dg) -{ - SceneLANPR *lanpr = &scene->lanpr; - int frame = scene->r.cfra; - - if (!lanpr_share.render_buffer_shared || - lanpr_share.render_buffer_shared->cached_for_frame != frame) { - ED_lanpr_compute_feature_lines_internal(dg, 0); - } - - ED_lanpr_chain_clear_picked_flag(lanpr_share.render_buffer_shared); - - lanpr_update_gp_strokes_recursive(dg, scene->master_collection, frame, NULL, NULL); - - lanpr_update_gp_strokes_collection(dg, scene->master_collection, frame, 0, NULL); - - lanpr_clear_gp_lanpr_flags(dg, frame); -} -static int lanpr_update_gp_strokes_exec(struct bContext *C, struct wmOperator *op) -{ - Scene *scene = CTX_data_scene(C); - Depsgraph *dg = CTX_data_depsgraph(C); - - lanpr_update_gp_strokes_actual(scene, dg); - - WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED | ND_SPACE_PROPERTIES, NULL); - - return OPERATOR_FINISHED; -} -static int lanpr_bake_gp_strokes_exec(struct bContext *C, struct wmOperator *op) -{ - Scene *scene = CTX_data_scene(C); - Depsgraph *dg = CTX_data_depsgraph(C); - SceneLANPR *lanpr = &scene->lanpr; - int frame, current_frame = scene->r.cfra; - int frame_begin = scene->r.sfra; - int frame_end = scene->r.efra; - - for (frame = frame_begin; frame <= frame_end; frame++) { - // BKE_scene_frame_set(scene,frame); - DEG_evaluate_on_framechange(CTX_data_main(C), dg, frame); - - ED_lanpr_compute_feature_lines_internal(dg, 0); - - ED_lanpr_chain_clear_picked_flag(lanpr_share.render_buffer_shared); - - lanpr_update_gp_strokes_recursive(dg, scene->master_collection, frame, NULL, NULL); - - lanpr_update_gp_strokes_collection(dg, scene->master_collection, frame, 0, NULL); - } - - WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED | ND_SPACE_PROPERTIES, NULL); - - return OPERATOR_FINISHED; -} -static int lanpr_update_gp_target_exec(struct bContext *C, struct wmOperator *op) -{ - Scene *scene = CTX_data_scene(C); - Depsgraph *dg = CTX_data_depsgraph(C); - SceneLANPR *lanpr = &scene->lanpr; - Object *gpo = CTX_data_active_object(C); - - int frame = scene->r.cfra; - - if (!lanpr_share.render_buffer_shared || - lanpr_share.render_buffer_shared->cached_for_frame != frame) { - ED_lanpr_compute_feature_lines_internal(dg, 0); - } - - ED_lanpr_chain_clear_picked_flag(lanpr_share.render_buffer_shared); - - lanpr_update_gp_strokes_recursive(dg, scene->master_collection, frame, NULL, gpo); - - lanpr_update_gp_strokes_collection(dg, scene->master_collection, frame, 0, gpo); - - lanpr_clear_gp_lanpr_flags(dg, frame); - - WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED | ND_SPACE_PROPERTIES, NULL); - - return OPERATOR_FINISHED; -} -static int lanpr_update_gp_source_exec(struct bContext *C, struct wmOperator *op) -{ - Scene *scene = CTX_data_scene(C); - Depsgraph *dg = CTX_data_depsgraph(C); - SceneLANPR *lanpr = &scene->lanpr; - Object *source_obj = CTX_data_active_object(C); - - int frame = scene->r.cfra; - - if (!lanpr_share.render_buffer_shared || - lanpr_share.render_buffer_shared->cached_for_frame != frame) { - ED_lanpr_compute_feature_lines_internal(dg, 0); - } - - ED_lanpr_chain_clear_picked_flag(lanpr_share.render_buffer_shared); - - lanpr_update_gp_strokes_recursive(dg, scene->master_collection, frame, source_obj, NULL); - - lanpr_update_gp_strokes_collection(dg, scene->master_collection, frame, 0, NULL); - - lanpr_clear_gp_lanpr_flags(dg, frame); - - WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED | ND_SPACE_PROPERTIES, NULL); - - return OPERATOR_FINISHED; -} - -static bool lanpr_active_is_gpencil_object(bContext *C) -{ - Object *o = CTX_data_active_object(C); - return o->type == OB_GPENCIL; -} -static bool lanpr_active_is_source_object(bContext *C) -{ - Object *o = CTX_data_active_object(C); - if (o->type != OB_MESH) { - return false; - } - else { - ModifierData *md; - for (md = o->modifiers.first; md; md = md->next) { - if (md->type == eModifierType_FeatureLine) { - return true; - } - } - } - return false; -} - -void SCENE_OT_lanpr_update_gp_strokes(struct wmOperatorType *ot) -{ - ot->name = "Update LANPR Strokes"; - ot->description = "Update strokes for LANPR grease pencil targets"; - ot->idname = "SCENE_OT_lanpr_update_gp_strokes"; - - ot->exec = lanpr_update_gp_strokes_exec; -} -void SCENE_OT_lanpr_bake_gp_strokes(struct wmOperatorType *ot) -{ - ot->name = "Bake LANPR Strokes"; - ot->description = "Bake strokes for LANPR grease pencil targets in all frames"; - ot->idname = "SCENE_OT_lanpr_bake_gp_strokes"; - - ot->exec = lanpr_bake_gp_strokes_exec; -} -void OBJECT_OT_lanpr_update_gp_target(struct wmOperatorType *ot) -{ - ot->name = "Update Strokes"; - ot->description = "Update LANPR strokes for selected GPencil object"; - ot->idname = "OBJECT_OT_lanpr_update_gp_target"; - - ot->poll = lanpr_active_is_gpencil_object; - ot->exec = lanpr_update_gp_target_exec; -} -/* Not working due to lack of GP flags for the object */ -void OBJECT_OT_lanpr_update_gp_source(struct wmOperatorType *ot) -{ - ot->name = "Update Strokes"; - ot->description = "Update LANPR strokes for selected Mesh object."; - ot->idname = "OBJECT_OT_lanpr_update_gp_source"; - - ot->poll = lanpr_active_is_source_object; - ot->exec = lanpr_update_gp_source_exec; -} - -/* Post-frame updater */ - -void ED_lanpr_post_frame_update_external(Scene *s, Depsgraph *dg) -{ - if (!s->lanpr.enabled || !s->lanpr.auto_update) { - return; - } - if (strcmp(s->r.engine, RE_engine_id_BLENDER_LANPR)) { - /* Not LANPR engine, do GPencil updates. */ - /* LANPR engine will automatically update when drawing the viewport. */ - if (!lanpr_share.render_buffer_shared || - lanpr_share.render_buffer_shared->cached_for_frame != s->r.cfra) { - ED_lanpr_compute_feature_lines_internal(dg, 0); - lanpr_update_gp_strokes_actual(s, dg); - } - } -} - -/* Inspect below */ -static void lanpr_post_frame_updater(struct Main *UNUSED(_1), struct ID *scene, void *UNUSED(_3)) -{ - Scene *s = (Scene *)scene; - if (s->lanpr.master_mode != LANPR_MASTER_MODE_SOFTWARE) { - return; - } - if (strcmp(s->r.engine, RE_engine_id_BLENDER_LANPR)) { - - /* No depsgraph reference here in the callback. Not working :? */ - } -} - -static bCallbackFuncStore lanpr_post_frame_callback = { - NULL, - NULL, /* next, prev */ - lanpr_post_frame_updater, /* func */ - NULL, /* arg */ - 0, /* alloc */ -}; - -static int lanpr_post_frame_regisetered = 0; +#include "ED_lanpr.h" -void ED_register_lanpr_post_frame() -{ - if (!lanpr_post_frame_regisetered) { - BLI_callback_add(&lanpr_post_frame_callback, BLI_CB_EVT_FRAME_CHANGE_POST); - } +/* lanpr_cpu.c */ +void SCENE_OT_lanpr_calculate_feature_lines(struct wmOperatorType *ot); +void SCENE_OT_lanpr_add_line_layer(struct wmOperatorType *ot); +void SCENE_OT_lanpr_delete_line_layer(struct wmOperatorType *ot); +void SCENE_OT_lanpr_rebuild_all_commands(struct wmOperatorType *ot); +void SCENE_OT_lanpr_auto_create_line_layer(struct wmOperatorType *ot); +void SCENE_OT_lanpr_move_line_layer(struct wmOperatorType *ot); +void SCENE_OT_lanpr_add_line_component(struct wmOperatorType *ot); +void SCENE_OT_lanpr_delete_line_component(struct wmOperatorType *ot); +void SCENE_OT_lanpr_enable_all_line_types(struct wmOperatorType *ot); +void SCENE_OT_lanpr_update_gp_strokes(struct wmOperatorType *ot); +void SCENE_OT_lanpr_bake_gp_strokes(struct wmOperatorType *ot); +void SCENE_OT_lanpr_export_svg(struct wmOperatorType *ot); + +void ED_operatortypes_lanpr(void) +{ + /* lanpr: */ + WM_operatortype_append(SCENE_OT_lanpr_calculate_feature_lines); + WM_operatortype_append(SCENE_OT_lanpr_add_line_layer); + WM_operatortype_append(SCENE_OT_lanpr_delete_line_layer); + WM_operatortype_append(SCENE_OT_lanpr_rebuild_all_commands); + WM_operatortype_append(SCENE_OT_lanpr_auto_create_line_layer); + WM_operatortype_append(SCENE_OT_lanpr_move_line_layer); + WM_operatortype_append(SCENE_OT_lanpr_add_line_component); + WM_operatortype_append(SCENE_OT_lanpr_delete_line_component); + WM_operatortype_append(SCENE_OT_lanpr_enable_all_line_types); + WM_operatortype_append(SCENE_OT_lanpr_update_gp_strokes); + WM_operatortype_append(SCENE_OT_lanpr_bake_gp_strokes); + WM_operatortype_append(SCENE_OT_lanpr_export_svg); } diff --git a/source/blender/editors/render/render_intern.h b/source/blender/editors/render/render_intern.h index d4e2ca84128..8e96e382328 100644 --- a/source/blender/editors/render/render_intern.h +++ b/source/blender/editors/render/render_intern.h @@ -76,20 +76,6 @@ void SCENE_OT_freestyle_modifier_copy(struct wmOperatorType *ot); void SCENE_OT_freestyle_stroke_material_create(struct wmOperatorType *ot); #endif -/* lanpr: lanpr_software_render.c */ -void SCENE_OT_lanpr_calculate_feature_lines(struct wmOperatorType *ot); -void SCENE_OT_lanpr_add_line_layer(struct wmOperatorType *ot); -void SCENE_OT_lanpr_delete_line_layer(struct wmOperatorType *ot); -void SCENE_OT_lanpr_rebuild_all_commands(struct wmOperatorType *ot); -void SCENE_OT_lanpr_auto_create_line_layer(struct wmOperatorType *ot); -void SCENE_OT_lanpr_move_line_layer(struct wmOperatorType *ot); -void SCENE_OT_lanpr_add_line_component(struct wmOperatorType *ot); -void SCENE_OT_lanpr_delete_line_component(struct wmOperatorType *ot); -void SCENE_OT_lanpr_enable_all_line_types(struct wmOperatorType *ot); -void SCENE_OT_lanpr_update_gp_strokes(struct wmOperatorType *ot); -void SCENE_OT_lanpr_bake_gp_strokes(struct wmOperatorType *ot); -void SCENE_OT_lanpr_export_svg(struct wmOperatorType *ot); - void OBJECT_OT_lanpr_update_gp_target(struct wmOperatorType *ot); void OBJECT_OT_lanpr_update_gp_source(struct wmOperatorType *ot); diff --git a/source/blender/editors/render/render_ops.c b/source/blender/editors/render/render_ops.c index 942f7aa6f29..c9b50302784 100644 --- a/source/blender/editors/render/render_ops.c +++ b/source/blender/editors/render/render_ops.c @@ -83,20 +83,6 @@ void ED_operatortypes_render(void) WM_operatortype_append(SCENE_OT_freestyle_stroke_material_create); #endif - /* lanpr: */ - WM_operatortype_append(SCENE_OT_lanpr_calculate_feature_lines); - WM_operatortype_append(SCENE_OT_lanpr_add_line_layer); - WM_operatortype_append(SCENE_OT_lanpr_delete_line_layer); - WM_operatortype_append(SCENE_OT_lanpr_rebuild_all_commands); - WM_operatortype_append(SCENE_OT_lanpr_auto_create_line_layer); - WM_operatortype_append(SCENE_OT_lanpr_move_line_layer); - WM_operatortype_append(SCENE_OT_lanpr_add_line_component); - WM_operatortype_append(SCENE_OT_lanpr_delete_line_component); - WM_operatortype_append(SCENE_OT_lanpr_enable_all_line_types); - WM_operatortype_append(SCENE_OT_lanpr_update_gp_strokes); - WM_operatortype_append(SCENE_OT_lanpr_bake_gp_strokes); - WM_operatortype_append(SCENE_OT_lanpr_export_svg); - WM_operatortype_append(TEXTURE_OT_slot_copy); WM_operatortype_append(TEXTURE_OT_slot_paste); WM_operatortype_append(TEXTURE_OT_slot_move); diff --git a/source/blender/editors/space_api/spacetypes.c b/source/blender/editors/space_api/spacetypes.c index 95775f80b50..a2f4ca37c08 100644 --- a/source/blender/editors/space_api/spacetypes.c +++ b/source/blender/editors/space_api/spacetypes.c @@ -64,6 +64,8 @@ #include "ED_gizmo_library.h" #include "ED_transform.h" +#include "ED_lanpr.h" + #include "io_ops.h" /* only call once on startup, storage is global in BKE kernel listbase */ @@ -123,6 +125,8 @@ void ED_spacetypes_init(void) ED_operatortypes_view2d(); ED_operatortypes_ui(); + ED_operatortypes_lanpr(); + ED_screen_user_menu_register(); /* gizmo types */ |