LineArt: Custom Camera
Allows line art camera to be different from scene active camera, useful when baking multiple shots in different angle as well as for motion graphics effect. Reviewed By: Antonio Vazquez (antoniov) Differential Revision: https://developer.blender.org/D12047
This commit is contained in:
parent
773f5065f3
commit
efbd36429a
Notes:
blender-bot
2023-02-14 11:07:28 +01:00
Referenced by issue #87739, Line Art further improvement list
|
@ -264,6 +264,12 @@ static void updateDepsgraph(GpencilModifierData *md,
|
|||
else {
|
||||
add_this_collection(ctx->scene->master_collection, ctx, mode);
|
||||
}
|
||||
if (lmd->calculation_flags & LRT_USE_CUSTOM_CAMERA) {
|
||||
DEG_add_object_relation(
|
||||
ctx->node, lmd->source_camera, DEG_OB_COMP_TRANSFORM, "Line Art Modifier");
|
||||
DEG_add_object_relation(
|
||||
ctx->node, lmd->source_camera, DEG_OB_COMP_PARAMETERS, "Line Art Modifier");
|
||||
}
|
||||
if (ctx->scene->camera) {
|
||||
DEG_add_object_relation(
|
||||
ctx->node, ctx->scene->camera, DEG_OB_COMP_TRANSFORM, "Line Art Modifier");
|
||||
|
@ -280,6 +286,7 @@ static void foreachIDLink(GpencilModifierData *md, Object *ob, IDWalkFunc walk,
|
|||
walk(userData, ob, (ID **)&lmd->source_collection, IDWALK_CB_NOP);
|
||||
|
||||
walk(userData, ob, (ID **)&lmd->source_object, IDWALK_CB_NOP);
|
||||
walk(userData, ob, (ID **)&lmd->source_camera, IDWALK_CB_NOP);
|
||||
}
|
||||
|
||||
static void panel_draw(const bContext *UNUSED(C), Panel *panel)
|
||||
|
@ -385,7 +392,12 @@ static void options_panel_draw(const bContext *UNUSED(C), Panel *panel)
|
|||
return;
|
||||
}
|
||||
|
||||
uiItemR(layout, ptr, "overscan", 0, NULL, ICON_NONE);
|
||||
uiLayout *row = uiLayoutRowWithHeading(layout, false, IFACE_("Custom Camera"));
|
||||
uiItemR(row, ptr, "use_custom_camera", 0, "", 0);
|
||||
uiLayout *subrow = uiLayoutRow(row, true);
|
||||
uiLayoutSetActive(subrow, RNA_boolean_get(ptr, "use_custom_camera"));
|
||||
uiLayoutSetPropSep(subrow, true);
|
||||
uiItemR(subrow, ptr, "source_camera", 0, "", ICON_OBJECT_DATA);
|
||||
|
||||
uiLayout *col = uiLayoutColumn(layout, true);
|
||||
|
||||
|
@ -684,10 +696,11 @@ static void composition_panel_draw(const bContext *UNUSED(C), Panel *panel)
|
|||
uiItemL(layout, IFACE_("Object is shown in front"), ICON_ERROR);
|
||||
}
|
||||
|
||||
uiLayout *row = uiLayoutRow(layout, false);
|
||||
uiLayoutSetActive(row, !show_in_front);
|
||||
uiLayout *col = uiLayoutColumn(layout, false);
|
||||
uiLayoutSetActive(col, !show_in_front);
|
||||
|
||||
uiItemR(row, ptr, "stroke_depth_offset", UI_ITEM_R_SLIDER, IFACE_("Depth Offset"), ICON_NONE);
|
||||
uiItemR(col, ptr, "stroke_depth_offset", UI_ITEM_R_SLIDER, IFACE_("Depth Offset"), ICON_NONE);
|
||||
uiItemR(col, ptr, "offset_towards_custom_camera", 0, IFACE_("Towards Custom Camera"), ICON_NONE);
|
||||
}
|
||||
|
||||
static void panelRegister(ARegionType *region_type)
|
||||
|
|
|
@ -311,6 +311,7 @@ typedef struct LineartRenderBuffer {
|
|||
bool cam_is_persp;
|
||||
float cam_obmat[4][4];
|
||||
double camera_pos[3];
|
||||
double active_camera_pos[3]; /* Stroke offset calculation may use active or selected camera. */
|
||||
double near_clip, far_clip;
|
||||
float shift_x, shift_y;
|
||||
float crease_threshold;
|
||||
|
@ -595,7 +596,9 @@ void MOD_lineart_chain_connect(LineartRenderBuffer *rb);
|
|||
void MOD_lineart_chain_discard_short(LineartRenderBuffer *rb, const float threshold);
|
||||
void MOD_lineart_chain_split_angle(LineartRenderBuffer *rb, float angle_threshold_rad);
|
||||
void MOD_lineart_smooth_chains(LineartRenderBuffer *rb, float tolerance);
|
||||
void MOD_lineart_chain_offset_towards_camera(LineartRenderBuffer *rb, float dist);
|
||||
void MOD_lineart_chain_offset_towards_camera(LineartRenderBuffer *rb,
|
||||
float dist,
|
||||
bool use_custom_camera);
|
||||
|
||||
int MOD_lineart_chain_count(const LineartEdgeChain *ec);
|
||||
void MOD_lineart_chain_clear_picked_flag(LineartCache *lc);
|
||||
|
|
|
@ -1009,7 +1009,9 @@ void MOD_lineart_chain_split_angle(LineartRenderBuffer *rb, float angle_threshol
|
|||
}
|
||||
}
|
||||
|
||||
void MOD_lineart_chain_offset_towards_camera(LineartRenderBuffer *rb, float dist)
|
||||
void MOD_lineart_chain_offset_towards_camera(LineartRenderBuffer *rb,
|
||||
float dist,
|
||||
bool use_custom_camera)
|
||||
{
|
||||
float dir[3];
|
||||
float cam[3];
|
||||
|
@ -1017,6 +1019,14 @@ void MOD_lineart_chain_offset_towards_camera(LineartRenderBuffer *rb, float dist
|
|||
float view_clamp[3];
|
||||
copy_v3fl_v3db(cam, rb->camera_pos);
|
||||
copy_v3fl_v3db(view, rb->view_vector);
|
||||
|
||||
if (use_custom_camera) {
|
||||
copy_v3fl_v3db(cam, rb->camera_pos);
|
||||
}
|
||||
else {
|
||||
copy_v3fl_v3db(cam, rb->active_camera_pos);
|
||||
}
|
||||
|
||||
if (rb->cam_is_persp) {
|
||||
LISTBASE_FOREACH (LineartEdgeChain *, ec, &rb->chains) {
|
||||
LISTBASE_FOREACH (LineartEdgeChainItem *, eci, &ec->chain) {
|
||||
|
|
|
@ -2998,7 +2998,7 @@ void MOD_lineart_destroy_render_data(LineartGpencilModifierData *lmd)
|
|||
}
|
||||
}
|
||||
|
||||
static LineartCache *lineart_init_cache()
|
||||
static LineartCache *lineart_init_cache(void)
|
||||
{
|
||||
LineartCache *lc = MEM_callocN(sizeof(LineartCache), "Lineart Cache");
|
||||
return lc;
|
||||
|
@ -3016,6 +3016,8 @@ void MOD_lineart_clear_cache(struct LineartCache **lc)
|
|||
|
||||
static LineartRenderBuffer *lineart_create_render_buffer(Scene *scene,
|
||||
LineartGpencilModifierData *lmd,
|
||||
Object *camera,
|
||||
Object *active_camera,
|
||||
LineartCache *lc)
|
||||
{
|
||||
LineartRenderBuffer *rb = MEM_callocN(sizeof(LineartRenderBuffer), "Line Art render buffer");
|
||||
|
@ -3024,10 +3026,10 @@ static LineartRenderBuffer *lineart_create_render_buffer(Scene *scene,
|
|||
lmd->render_buffer_ptr = rb;
|
||||
lc->rb_edge_types = lmd->edge_types_override;
|
||||
|
||||
if (!scene || !scene->camera || !lc) {
|
||||
if (!scene || !camera || !lc) {
|
||||
return NULL;
|
||||
}
|
||||
Camera *c = scene->camera->data;
|
||||
Camera *c = camera->data;
|
||||
double clipping_offset = 0;
|
||||
|
||||
if (lmd->calculation_flags & LRT_ALLOW_CLIPPING_BOUNDARIES) {
|
||||
|
@ -3035,8 +3037,11 @@ static LineartRenderBuffer *lineart_create_render_buffer(Scene *scene,
|
|||
clipping_offset = 0.0001;
|
||||
}
|
||||
|
||||
copy_v3db_v3fl(rb->camera_pos, scene->camera->obmat[3]);
|
||||
copy_m4_m4(rb->cam_obmat, scene->camera->obmat);
|
||||
copy_v3db_v3fl(rb->camera_pos, camera->obmat[3]);
|
||||
if (active_camera) {
|
||||
copy_v3db_v3fl(rb->active_camera_pos, active_camera->obmat[3]);
|
||||
}
|
||||
copy_m4_m4(rb->cam_obmat, camera->obmat);
|
||||
rb->cam_is_persp = (c->type == CAM_PERSP);
|
||||
rb->near_clip = c->clip_start + clipping_offset;
|
||||
rb->far_clip = c->clip_end - clipping_offset;
|
||||
|
@ -4082,6 +4087,7 @@ bool MOD_lineart_compute_feature_lines(Depsgraph *depsgraph,
|
|||
LineartRenderBuffer *rb;
|
||||
Scene *scene = DEG_get_evaluated_scene(depsgraph);
|
||||
int intersections_only = 0; /* Not used right now, but preserve for future. */
|
||||
Object *use_camera;
|
||||
|
||||
double t_start;
|
||||
|
||||
|
@ -4091,14 +4097,24 @@ bool MOD_lineart_compute_feature_lines(Depsgraph *depsgraph,
|
|||
|
||||
BKE_scene_camera_switch_update(scene);
|
||||
|
||||
if (!scene->camera) {
|
||||
return false;
|
||||
if (lmd->calculation_flags & LRT_USE_CUSTOM_CAMERA) {
|
||||
if (!lmd->source_camera ||
|
||||
(use_camera = DEG_get_evaluated_object(depsgraph, lmd->source_camera))->type !=
|
||||
OB_CAMERA) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (!scene->camera) {
|
||||
return false;
|
||||
}
|
||||
use_camera = scene->camera;
|
||||
}
|
||||
|
||||
LineartCache *lc = lineart_init_cache();
|
||||
*cached_result = lc;
|
||||
|
||||
rb = lineart_create_render_buffer(scene, lmd, lc);
|
||||
rb = lineart_create_render_buffer(scene, lmd, use_camera, scene->camera, lc);
|
||||
|
||||
/* Triangle thread testing data size varies depending on the thread count.
|
||||
* See definition of LineartTriangleThread for details. */
|
||||
|
@ -4118,7 +4134,7 @@ bool MOD_lineart_compute_feature_lines(Depsgraph *depsgraph,
|
|||
/* Get view vector before loading geometries, because we detect feature lines there. */
|
||||
lineart_main_get_view_vector(rb);
|
||||
lineart_main_load_geometries(
|
||||
depsgraph, scene, scene->camera, rb, lmd->calculation_flags & LRT_ALLOW_DUPLI_OBJECTS);
|
||||
depsgraph, scene, use_camera, rb, lmd->calculation_flags & LRT_ALLOW_DUPLI_OBJECTS);
|
||||
|
||||
if (!rb->vertex_buffer_pointers.first) {
|
||||
/* No geometry loaded, return early. */
|
||||
|
@ -4191,7 +4207,8 @@ bool MOD_lineart_compute_feature_lines(Depsgraph *depsgraph,
|
|||
}
|
||||
|
||||
if (enable_stroke_depth_offset && lmd->stroke_depth_offset > FLT_EPSILON) {
|
||||
MOD_lineart_chain_offset_towards_camera(rb, lmd->stroke_depth_offset);
|
||||
MOD_lineart_chain_offset_towards_camera(
|
||||
rb, lmd->stroke_depth_offset, lmd->flags & LRT_GPENCIL_OFFSET_TOWARDS_CUSTOM_CAMERA);
|
||||
}
|
||||
|
||||
/* Finally transfer the result list into cache. */
|
||||
|
|
|
@ -978,6 +978,7 @@ typedef enum eLineArtGPencilModifierFlags {
|
|||
LRT_GPENCIL_BINARY_WEIGHTS = (1 << 2) /* Deprecated, this is removed for lack of use case. */,
|
||||
LRT_GPENCIL_IS_BAKED = (1 << 3),
|
||||
LRT_GPENCIL_USE_CACHE = (1 << 4),
|
||||
LRT_GPENCIL_OFFSET_TOWARDS_CUSTOM_CAMERA = (1 << 5),
|
||||
} eLineArtGPencilModifierFlags;
|
||||
|
||||
typedef enum eLineartGpencilMaskSwitches {
|
||||
|
@ -1004,6 +1005,8 @@ typedef struct LineartGpencilModifierData {
|
|||
short level_start;
|
||||
short level_end;
|
||||
|
||||
struct Object *source_camera;
|
||||
|
||||
struct Object *source_object;
|
||||
struct Collection *source_collection;
|
||||
|
||||
|
|
|
@ -49,6 +49,7 @@ typedef enum eLineartMainFlags {
|
|||
LRT_ALLOW_OVERLAP_EDGE_TYPES = (1 << 14),
|
||||
LRT_USE_CREASE_ON_SMOOTH_SURFACES = (1 << 15),
|
||||
LRT_USE_CREASE_ON_SHARP_EDGES = (1 << 16),
|
||||
LRT_USE_CUSTOM_CAMERA = (1 << 17),
|
||||
} eLineartMainFlags;
|
||||
|
||||
typedef enum eLineartEdgeFlag {
|
||||
|
|
|
@ -3073,6 +3073,12 @@ static void rna_def_modifier_gpencillineart(BlenderRNA *brna)
|
|||
|
||||
RNA_define_lib_overridable(true);
|
||||
|
||||
prop = RNA_def_property(srna, "use_custom_camera", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "calculation_flags", LRT_USE_CUSTOM_CAMERA);
|
||||
RNA_def_property_ui_text(
|
||||
prop, "Use Custom Camera", "Use custom camera instead of the active camera");
|
||||
RNA_def_property_update(prop, NC_SCENE, "rna_GpencilModifier_update");
|
||||
|
||||
prop = RNA_def_property(srna, "use_fuzzy_intersections", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "calculation_flags", LRT_INTERSECTION_AS_CONTOUR);
|
||||
RNA_def_property_ui_text(prop,
|
||||
|
@ -3209,6 +3215,21 @@ static void rna_def_modifier_gpencillineart(BlenderRNA *brna)
|
|||
RNA_def_property_ui_range(prop, 0.0f, 0.5f, 0.001f, 4);
|
||||
RNA_def_property_update(prop, NC_SCENE, "rna_GpencilModifier_update");
|
||||
|
||||
prop = RNA_def_property(srna, "offset_towards_custom_camera", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flags", LRT_GPENCIL_OFFSET_TOWARDS_CUSTOM_CAMERA);
|
||||
RNA_def_property_ui_text(prop,
|
||||
"Offset Towards Custom Camera",
|
||||
"Offset strokes towards selected camera instead of the active camera");
|
||||
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
|
||||
|
||||
prop = RNA_def_property(srna, "source_camera", PROP_POINTER, PROP_NONE);
|
||||
RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK);
|
||||
RNA_def_property_struct_type(prop, "Object");
|
||||
RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
|
||||
RNA_def_property_ui_text(
|
||||
prop, "Camera Object", "Use specified camera object for generating line art");
|
||||
RNA_def_property_update(prop, 0, "rna_GpencilModifier_dependency_update");
|
||||
|
||||
prop = RNA_def_property(srna, "source_type", PROP_ENUM, PROP_NONE);
|
||||
RNA_def_property_enum_items(prop, modifier_lineart_source_type);
|
||||
RNA_def_property_ui_text(prop, "Source Type", "Line art stroke source type");
|
||||
|
|
Loading…
Reference in New Issue