1
1

Compare commits

...

20 Commits

Author SHA1 Message Date
a12ab5b2ef Merge branch 'blender2.8' into tmp-b28-motionpath-drawing 2018-06-01 16:24:59 +02:00
e9e8f105d0 Cleanup: Remove old legacy immediate mode drawing code
This was not being used. At least from simple tests, all options seemed to be working ok
2018-06-01 14:01:35 +02:00
fea05c695a Cleanup: Fix compiler warning 2018-06-01 14:00:48 +02:00
83afc4e1a2 Draw motionpaths with thicker lines by default - Now 2px thick 2018-06-01 13:57:07 +02:00
6c177a7478 Copy object animviz settings when doing COW
It probably doesn't hurt to do an explicit copy here - it's done for pose too.
However, it still doesn't solve the problem of keyframe labels not showing up
at all on motionpaths from old files.
2018-06-01 13:54:41 +02:00
70b31c28b6 Fix: Motionpaths were not drawing for bones
As with the objects case earlier, the problem was that when doing COW for the
viewport, the pchan->mpath pointer was just getting set to NULL in the copying
code. It's unclear for now whether this will cause any problems down the track
somewhere else - the comment there was non-specific about why we were explicitly
not copying/keeping the old link.
2018-06-01 13:53:03 +02:00
71d02d8a35 Enable motion path overlay by default 2018-06-01 13:07:37 +02:00
cd6109fd4f Compile fix for previous commit: Forgot to reset these variables (were used when testing previous fix) 2018-06-01 13:04:40 +02:00
49a727a784 Fix: Motion path colors/frame indicator weren't updating on frame change
This should have been using DEG_get_ctime() to read time instead of CFRA.
In viewport code, Scene/Scene_Eval's current frame doesn't change ever.
2018-06-01 12:58:02 +02:00
959af5d69d Fix: The overlays option to turn motion paths on/off didn't work 2018-06-01 12:30:41 +02:00
d886fc0f40 Merge branch 'blender2.8' into tmp-b28-motionpath-drawing
# Conflicts:
#	source/blender/draw/intern/DRW_render.h
#	source/blender/draw/intern/draw_manager.c
#	source/blender/draw/intern/draw_manager_data.c
#	source/blender/makesdna/DNA_view3d_types.h
#	source/blender/makesrna/intern/rna_space.c
2018-06-01 12:19:59 +02:00
266c90dc17 COW Fix - Motion paths were not drawing as they weren't getting copied 2018-06-01 11:55:45 +02:00
bc4bfef209 Motion Path Update: Tag objects for copy on write flushing after calculating 2018-05-31 14:02:34 +02:00
113e5fdd81 DRW: Disable depth test for text drawing. 2018-05-31 00:26:16 +02:00
d8203b0422 Motion Paths: Port motion path to draw manager (1/2)
Add keyframe drawing by baking the keyframe position in the motion path vert
cache.

Only remaining problem is that toggling the pose bone MOTIONPATH_VIEW_KFACT
needs a motion path recalc now.
2018-05-31 00:25:23 +02:00
f12e22edca Motion Paths: Port motion path to draw manager (1/2)
Keyframe drawing is still missing but other than that it's pretty much
on part with what we had in 2.7.
2018-05-30 00:28:58 +02:00
28373293a2 DRW: Add new drawcall type DRW_CALL_RANGE 2018-05-30 00:22:41 +02:00
e781b7692a WIP setting up draw manager stuff... 2018-05-22 12:06:42 +02:00
2e2371b86e Add defines in Overlays popover for Motion Paths 2018-05-22 12:06:42 +02:00
1fd4b0bdf5 Restore editors/space_view3d/drawanimviz.c as draw/intern/draw_anim_viz.c
This was removed from the codebase with the Blender Internal removal,
but before the drawing code had been added to the new drawing engines.
2018-05-22 12:06:42 +02:00
25 changed files with 748 additions and 12 deletions

View File

@@ -3597,6 +3597,7 @@ class VIEW3D_PT_overlay(Panel):
col.prop(overlay, "show_outline_selected")
col.prop(overlay, "show_all_objects_origin")
col.prop(overlay, "show_relationship_lines")
col.prop(overlay, "show_motion_paths")
col.prop(overlay, "show_face_orientation")
col.prop(overlay, "show_wireframes")
col.prop(overlay, "show_backface_culling")

View File

@@ -48,6 +48,8 @@ struct Main;
void animviz_settings_init(struct bAnimVizSettings *avs);
struct bMotionPath *animviz_copy_motionpath(const struct bMotionPath *mpath_src);
void animviz_free_motionpath_cache(struct bMotionPath *mpath);
void animviz_free_motionpath(struct bMotionPath *mpath);

View File

@@ -582,7 +582,9 @@ void BKE_pose_copy_data_ex(bPose **dst, const bPose *src, const int flag, const
if (copy_constraints) {
BKE_constraints_copy_ex(&listb, &pchan->constraints, flag, true); // BKE_constraints_copy NULLs listb
pchan->constraints = listb;
pchan->mpath = NULL; /* motion paths should not get copied yet... */
/* XXX: This is needed for motionpath drawing to work. Dunno why it was setting to null before... */
pchan->mpath = animviz_copy_motionpath(pchan->mpath);
}
if (pchan->prop) {

View File

@@ -35,6 +35,7 @@
#include "BLI_listbase.h"
#include "BLI_math.h"
#include "BLI_dlrbTree.h"
#include "BLT_translation.h"
@@ -44,6 +45,7 @@
#include "DNA_scene_types.h"
#include "BKE_anim.h"
#include "BKE_animsys.h"
#include "BKE_action.h"
#include "BKE_context.h"
#include "BKE_curve.h"
@@ -59,7 +61,12 @@
#include "DEG_depsgraph_query.h"
#include "DEG_depsgraph_build.h"
#include "GPU_batch.h"
// XXX bad level call...
extern short compare_ak_cfraPtr(void *node, void *data);
extern void agroup_to_keylist(struct AnimData *adt, struct bActionGroup *agrp, struct DLRBT_Tree *keys, struct DLRBT_Tree *blocks);
extern void action_to_keylist(struct AnimData *adt, struct bAction *act, struct DLRBT_Tree *keys, struct DLRBT_Tree *blocks);
/* --------------------- */
/* forward declarations */
@@ -106,6 +113,10 @@ void animviz_free_motionpath_cache(bMotionPath *mpath)
/* free the path if necessary */
if (mpath->points)
MEM_freeN(mpath->points);
GWN_VERTBUF_DISCARD_SAFE(mpath->points_vbo);
GWN_BATCH_DISCARD_SAFE(mpath->batch_line);
GWN_BATCH_DISCARD_SAFE(mpath->batch_points);
/* reset the relevant parameters */
mpath->points = NULL;
@@ -130,6 +141,27 @@ void animviz_free_motionpath(bMotionPath *mpath)
/* ------------------- */
/* Make a copy of motionpath data, so that viewing with copy on write works */
bMotionPath *animviz_copy_motionpath(const bMotionPath *mpath_src)
{
bMotionPath *mpath_dst;
if (mpath_src == NULL)
return NULL;
mpath_dst = MEM_dupallocN(mpath_src);
mpath_dst->points = MEM_dupallocN(mpath_src->points);
/* should get recreated on draw... */
mpath_dst->points_vbo = NULL;
mpath_dst->batch_line = NULL;
mpath_dst->batch_points = NULL;
return mpath_dst;
}
/* ------------------- */
/**
* Setup motion paths for the given data.
* \note Only used when explicitly calculating paths on bones which may/may not be consider already
@@ -212,7 +244,7 @@ bMotionPath *animviz_verify_motionpaths(ReportList *reports, Scene *scene, Objec
mpath->color[1] = 0.0;
mpath->color[2] = 0.0;
mpath->line_thickness = 1;
mpath->line_thickness = 2;
mpath->flag |= MOTIONPATH_FLAG_LINES; /* draw lines by default */
/* allocate a cache */
@@ -232,6 +264,8 @@ typedef struct MPathTarget {
struct MPathTarget *next, *prev;
bMotionPath *mpath; /* motion path in question */
DLRBT_Tree keys; /* temp, to know where the keyframes are */
/* Original (Source Objects) */
Object *ob; /* source object */
@@ -344,6 +378,13 @@ static void motionpaths_calc_bake_targets(Scene *scene, ListBase *targets)
/* worldspace object location */
copy_v3_v3(mpv->co, ob_eval->obmat[3]);
}
float mframe = (float)(CFRA);
/* Tag if it's a keyframe */
if (BLI_dlrbTree_search_exact(&mpt->keys, compare_ak_cfraPtr, &mframe)) {
mpv->flag |= MOTIONPATH_VERT_KEY;
}
}
}
@@ -387,13 +428,44 @@ static void motionpaths_calc_bake_targets(Scene *scene, ListBase *targets)
if (mpt->pchan) {
mpt->pchan_eval = BKE_pose_channel_find_name(mpt->ob_eval->pose, mpt->pchan->name);
}
AnimData *adt = BKE_animdata_from_id(&mpt->ob_eval->id);
/* build list of all keyframes in active action for object or pchan */
BLI_dlrbTree_init(&mpt->keys);
if (adt) {
bAnimVizSettings *avs;
/* get pointer to animviz settings for each target */
if (mpt->pchan)
avs = &mpt->ob->pose->avs;
else
avs = &mpt->ob->avs;
/* it is assumed that keyframes for bones are all grouped in a single group
* unless an option is set to always use the whole action
*/
if ((mpt->pchan) && (avs->path_viewflag & MOTIONPATH_VIEW_KFACT) == 0) {
bActionGroup *agrp = BKE_action_group_find_name(adt->action, mpt->pchan->name);
if (agrp) {
agroup_to_keylist(adt, agrp, &mpt->keys, NULL);
BLI_dlrbTree_linkedlist_sync(&mpt->keys);
}
}
else {
action_to_keylist(adt, adt->action, &mpt->keys, NULL);
BLI_dlrbTree_linkedlist_sync(&mpt->keys);
}
}
}
/* calculate path over requested range */
for (CFRA = sfra; CFRA <= efra; CFRA++) {
/* update relevant data for new frame */
motionpaths_calc_update_scene(bmain, depsgraph);
/* perform baking for targets */
motionpaths_calc_bake_targets(scene, targets);
}
@@ -406,6 +478,7 @@ static void motionpaths_calc_bake_targets(Scene *scene, ListBase *targets)
/* clear recalc flags from targets */
for (mpt = targets->first; mpt; mpt = mpt->next) {
bAnimVizSettings *avs;
bMotionPath *mpath = mpt->mpath;
/* get pointer to animviz settings for each target */
if (mpt->pchan)
@@ -415,6 +488,14 @@ static void motionpaths_calc_bake_targets(Scene *scene, ListBase *targets)
/* clear the flag requesting recalculation of targets */
avs->recalc &= ~ANIMVIZ_RECALC_PATHS;
/* Clean temp data */
BLI_dlrbTree_free(&mpt->keys);
/* Free previous batches to force update. */
GWN_VERTBUF_DISCARD_SAFE(mpath->points_vbo);
GWN_BATCH_DISCARD_SAFE(mpath->batch_line);
GWN_BATCH_DISCARD_SAFE(mpath->batch_points);
}
}

View File

@@ -1228,7 +1228,8 @@ void BKE_object_copy_data(Main *UNUSED(bmain), Object *ob_dst, const Object *ob_
BLI_listbase_clear(&ob_dst->drawdata);
BLI_listbase_clear(&ob_dst->pc_ids);
ob_dst->mpath = NULL;
ob_dst->avs = ob_src->avs;
ob_dst->mpath = animviz_copy_motionpath(ob_src->mpath);
copy_object_lod(ob_dst, ob_src, flag_subdata);

View File

@@ -2965,6 +2965,10 @@ static void direct_link_motionpath(FileData *fd, bMotionPath *mpath)
/* relink points cache */
mpath->points = newdataadr(fd, mpath->points);
mpath->points_vbo = NULL;
mpath->batch_line = NULL;
mpath->batch_points = NULL;
}
/* ************ READ NODE TREE *************** */

View File

@@ -53,6 +53,7 @@ set(INC_SYS
)
set(SRC
intern/draw_anim_viz.c
intern/draw_armature.c
intern/draw_cache.c
intern/draw_cache_impl_curve.c
@@ -241,6 +242,9 @@ data_to_c_simple(modes/shaders/common_hair_refine_vert.glsl SRC)
data_to_c_simple(modes/shaders/common_view_lib.glsl SRC)
data_to_c_simple(modes/shaders/common_fxaa_lib.glsl SRC)
data_to_c_simple(modes/shaders/common_fullscreen_vert.glsl SRC)
data_to_c_simple(modes/shaders/animviz_mpath_lines_vert.glsl SRC)
data_to_c_simple(modes/shaders/animviz_mpath_lines_geom.glsl SRC)
data_to_c_simple(modes/shaders/animviz_mpath_points_vert.glsl SRC)
data_to_c_simple(modes/shaders/armature_axes_vert.glsl SRC)
data_to_c_simple(modes/shaders/armature_sphere_solid_vert.glsl SRC)
data_to_c_simple(modes/shaders/armature_sphere_solid_frag.glsl SRC)

View File

@@ -344,6 +344,8 @@ void DRW_shgroup_instance_batch(DRWShadingGroup *shgroup, struct Gwn_Batch *batc
void DRW_shgroup_free(struct DRWShadingGroup *shgroup);
void DRW_shgroup_call_add(DRWShadingGroup *shgroup, struct Gwn_Batch *geom, float (*obmat)[4]);
void DRW_shgroup_call_range_add(
DRWShadingGroup *shgroup, struct Gwn_Batch *geom, float (*obmat)[4], uint v_sta, uint v_count);
void DRW_shgroup_call_procedural_points_add(DRWShadingGroup *shgroup, unsigned int point_count, float (*obmat)[4]);
void DRW_shgroup_call_procedural_lines_add(DRWShadingGroup *shgroup, unsigned int line_count, float (*obmat)[4]);
void DRW_shgroup_call_procedural_triangles_add(DRWShadingGroup *shgroup, unsigned int tria_count, float (*obmat)[4]);

View File

@@ -0,0 +1,351 @@
/*
* ***** BEGIN GPL LICENSE BLOCK *****
*
* 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.
*
* The Original Code is Copyright (C) 2009/2018 by the Blender Foundation.
*
* Contributor(s): Joshua Leung
*
* ***** END GPL LICENSE BLOCK *****
*/
/** \file blender/draw/intern/draw_anim_viz.c
* \ingroup draw
*/
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include "BLI_sys_types.h"
#include "DNA_anim_types.h"
#include "DNA_armature_types.h"
#include "DNA_scene_types.h"
#include "DNA_screen_types.h"
#include "DNA_view3d_types.h"
#include "DNA_object_types.h"
#include "BLI_math.h"
#include "BLI_dlrbTree.h"
#include "BKE_animsys.h"
#include "BKE_action.h"
#include "ED_keyframes_draw.h"
#include "UI_resources.h"
#include "DEG_depsgraph_query.h"
#include "DRW_engine.h"
#include "DRW_render.h"
#include "GPU_shader.h"
#include "GPU_immediate.h"
#include "GPU_matrix.h"
#include "draw_common.h"
#include "draw_manager_text.h"
#include "draw_mode_engines.h"
extern struct GPUUniformBuffer *globals_ubo; /* draw_common.c */
/* ********************************* Lists ************************************** */
/* All lists are per viewport specific datas.
* They are all free when viewport changes engines
* or is free itself.
*/
/* XXX: How to show frame numbers, etc.? Currently only doing the dots and lines */
typedef struct MPATH_PassList {
struct DRWPass *lines;
struct DRWPass *points;
} MPATH_PassList;
typedef struct MPATH_StorageList {
struct MPATH_PrivateData *g_data;
} MPATH_StorageList;
typedef struct MPATH_Data {
void *engine_type;
DRWViewportEmptyList *fbl;
DRWViewportEmptyList *txl;
MPATH_PassList *psl;
MPATH_StorageList *stl;
} MPATH_Data;
struct {
GPUShader *mpath_line_sh;
GPUShader *mpath_points_sh;
} e_data = {0};
/* *************************** Path Cache *********************************** */
/* Just convert the CPU cache to GPU cache. */
static Gwn_VertBuf *mpath_vbo_get(bMotionPath *mpath)
{
if (!mpath->points_vbo) {
Gwn_VertFormat format = {0};
/* Match structure of bMotionPathVert. */
uint pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
GWN_vertformat_attr_add(&format, "flag", GWN_COMP_I32, 1, GWN_FETCH_INT);
mpath->points_vbo = GWN_vertbuf_create_with_format(&format);
GWN_vertbuf_data_alloc(mpath->points_vbo, mpath->length);
/* meh... a useless memcpy. */
Gwn_VertBufRaw raw_data;
GWN_vertbuf_attr_get_raw_data(mpath->points_vbo, pos, &raw_data);
memcpy(GWN_vertbuf_raw_step(&raw_data), mpath->points, sizeof(bMotionPathVert) * mpath->length);
}
return mpath->points_vbo;
}
static Gwn_Batch *mpath_batch_line_get(bMotionPath *mpath)
{
if (!mpath->batch_line) {
mpath->batch_line = GWN_batch_create(GWN_PRIM_LINE_STRIP, mpath_vbo_get(mpath), NULL);
}
return mpath->batch_line;
}
static Gwn_Batch *mpath_batch_points_get(bMotionPath *mpath)
{
if (!mpath->batch_points) {
mpath->batch_points = GWN_batch_create(GWN_PRIM_POINTS, mpath_vbo_get(mpath), NULL);
}
return mpath->batch_points;
}
/* *************************** Draw Engine Entrypoints ************************** */
static void MPATH_engine_init(void *UNUSED(vedata))
{
}
static void MPATH_engine_free(void)
{
}
/* Here init all passes and shading groups
* Assume that all Passes are NULL */
static void MPATH_cache_init(void *vedata)
{
MPATH_PassList *psl = ((MPATH_Data *)vedata)->psl;
{
DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS;
psl->lines = DRW_pass_create("Motionpath Line Pass", state);
}
{
DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS | DRW_STATE_POINT;
psl->points = DRW_pass_create("Motionpath Point Pass", state);
}
}
static void MPATH_cache_motion_path(MPATH_PassList *psl,
Object *ob, bPoseChannel *pchan,
bAnimVizSettings *avs, bMotionPath *mpath)
{
const DRWContextState *draw_ctx = DRW_context_state_get();
struct DRWTextStore *dt = DRW_text_cache_ensure();
int txt_flag = DRW_TEXT_CACHE_GLOBALSPACE | DRW_TEXT_CACHE_ASCII;
int stepsize = avs->path_step;
int sfra, efra, sind, len;
int cfra = (int)DEG_get_ctime(draw_ctx->depsgraph);
bool sel = (pchan) ? (pchan->bone->flag & BONE_SELECTED) : (ob->flag & SELECT);
bool show_keyframes = (avs->path_viewflag & MOTIONPATH_VIEW_KFRAS) != 0;
bMotionPathVert *mpv, *mpv_start;
/* get frame ranges */
if (avs->path_type == MOTIONPATH_TYPE_ACFRA) {
/* With "Around Current", we only choose frames from around
* the current frame to draw.
*/
sfra = cfra - avs->path_bc;
efra = cfra + avs->path_ac + 1;
}
else {
/* Use the current display range */
sfra = avs->path_sf;
efra = avs->path_ef;
}
/* no matter what, we can only show what is in the cache and no more
* - abort if whole range is past ends of path
* - otherwise clamp endpoints to extents of path
*/
if (sfra < mpath->start_frame) {
/* start clamp */
sfra = mpath->start_frame;
}
if (efra > mpath->end_frame) {
/* end clamp */
efra = mpath->end_frame;
}
if ((sfra > mpath->end_frame) || (efra < mpath->start_frame)) {
/* whole path is out of bounds */
return;
}
len = efra - sfra;
if ((len <= 0) || (mpath->points == NULL)) {
return;
}
sind = sfra - mpath->start_frame;
mpv_start = (mpath->points + sind);
bool use_custom_col = (mpath->flag & MOTIONPATH_FLAG_CUSTOM) != 0;
/* draw curve-line of path */
/* Draw lines only if line drawing option is enabled */
if (mpath->flag & MOTIONPATH_FLAG_LINES) {
DRWShadingGroup *shgrp = DRW_shgroup_create(mpath_line_shader_get(), psl->lines);
DRW_shgroup_uniform_int_copy(shgrp, "frameCurrent", cfra);
DRW_shgroup_uniform_int_copy(shgrp, "frameStart", sfra);
DRW_shgroup_uniform_int_copy(shgrp, "frameEnd", efra);
DRW_shgroup_uniform_int_copy(shgrp, "cacheStart", mpath->start_frame);
DRW_shgroup_uniform_int_copy(shgrp, "lineThickness", mpath->line_thickness);
DRW_shgroup_uniform_bool_copy(shgrp, "selected", sel);
DRW_shgroup_uniform_bool_copy(shgrp, "useCustomColor", use_custom_col);
DRW_shgroup_uniform_vec2(shgrp, "viewportSize", DRW_viewport_size_get(), 1);
DRW_shgroup_uniform_block(shgrp, "globalsBlock", globals_ubo);
if (use_custom_col) {
DRW_shgroup_uniform_vec3(shgrp, "customColor", mpath->color, 1);
}
/* Only draw the required range. */
DRW_shgroup_call_range_add(shgrp, mpath_batch_line_get(mpath), NULL, sind, len);
}
/* Draw points. */
DRWShadingGroup *shgrp = DRW_shgroup_create(mpath_points_shader_get(), psl->points);
DRW_shgroup_uniform_int_copy(shgrp, "frameCurrent", cfra);
DRW_shgroup_uniform_int_copy(shgrp, "cacheStart", mpath->start_frame);
DRW_shgroup_uniform_int_copy(shgrp, "pointSize", mpath->line_thickness);
DRW_shgroup_uniform_int_copy(shgrp, "stepSize", stepsize);
DRW_shgroup_uniform_bool_copy(shgrp, "selected", sel);
DRW_shgroup_uniform_bool_copy(shgrp, "showKeyFrames", show_keyframes);
DRW_shgroup_uniform_bool_copy(shgrp, "useCustomColor", use_custom_col);
DRW_shgroup_uniform_block(shgrp, "globalsBlock", globals_ubo);
if (use_custom_col) {
DRW_shgroup_uniform_vec3(shgrp, "customColor", mpath->color, 1);
}
/* Only draw the required range. */
DRW_shgroup_call_range_add(shgrp, mpath_batch_points_get(mpath), NULL, sind, len);
/* Draw frame numbers at each framestep value */
bool show_kf_no = (avs->path_viewflag & MOTIONPATH_VIEW_KFNOS) != 0;
if ((avs->path_viewflag & (MOTIONPATH_VIEW_FNUMS)) || (show_kf_no && show_keyframes)) {
int i;
unsigned char col[4], col_kf[4];
UI_GetThemeColor3ubv(TH_TEXT_HI, col);
UI_GetThemeColor3ubv(TH_VERTEX_SELECT, col_kf);
col[3] = col_kf[3] = 255;
for (i = 0, mpv = mpv_start; i < len; i += stepsize, mpv += stepsize) {
int frame = sfra + i;
char numstr[32];
size_t numstr_len;
float co[3];
bool is_keyframe = (mpv->flag & MOTIONPATH_VERT_KEY) != 0;
if ((show_keyframes && show_kf_no && is_keyframe) ||
((avs->path_viewflag & MOTIONPATH_VIEW_FNUMS) && (i == 0)))
{
numstr_len = sprintf(numstr, " %d", frame);
mul_v3_m4v3(co, ob->imat, mpv->co);
DRW_text_cache_add(dt, co, numstr, numstr_len, 0, txt_flag, (is_keyframe) ? col_kf : col);
}
else if (avs->path_viewflag & MOTIONPATH_VIEW_FNUMS) {
bMotionPathVert *mpvP = (mpv - stepsize);
bMotionPathVert *mpvN = (mpv + stepsize);
/* only draw framenum if several consecutive highlighted points don't occur on same point */
if ((equals_v3v3(mpv->co, mpvP->co) == 0) || (equals_v3v3(mpv->co, mpvN->co) == 0)) {
numstr_len = sprintf(numstr, " %d", frame);
mul_v3_m4v3(co, ob->imat, mpv->co);
DRW_text_cache_add(dt, co, numstr, numstr_len, 0, txt_flag, col);
}
}
}
}
}
/* Add geometry to shading groups. Execute for each objects */
static void MPATH_cache_populate(void *vedata, Object *ob)
{
MPATH_PassList *psl = ((MPATH_Data *)vedata)->psl;
const DRWContextState *draw_ctx = DRW_context_state_get();
if (draw_ctx->v3d->overlay.flag & V3D_OVERLAY_HIDE_MOTION_PATHS) {
return;
}
if (ob->type == OB_ARMATURE) {
if (DRW_pose_mode_armature(ob, draw_ctx->obact)) {
for (bPoseChannel *pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
if (pchan->mpath) {
MPATH_cache_motion_path(psl, ob, pchan, &ob->pose->avs, pchan->mpath);
}
}
}
}
else {
if (ob->mpath) {
MPATH_cache_motion_path(psl, ob, NULL, &ob->avs, ob->mpath);
}
}
}
/* Draw time! Control rendering pipeline from here */
static void MPATH_draw_scene(void *vedata)
{
MPATH_PassList *psl = ((MPATH_Data *)vedata)->psl;
DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get();
DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
MULTISAMPLE_SYNC_ENABLE(dfbl, dtxl)
DRW_draw_pass(psl->lines);
DRW_draw_pass(psl->points);
MULTISAMPLE_SYNC_DISABLE(dfbl, dtxl)
}
/* *************************** Draw Engine Defines ****************************** */
static const DrawEngineDataSize MPATH_data_size = DRW_VIEWPORT_DATA_SIZE(MPATH_Data);
DrawEngineType draw_engine_motion_path_type = {
NULL, NULL,
N_("MotionPath"),
&MPATH_data_size,
&MPATH_engine_init,
&MPATH_engine_free,
&MPATH_cache_init,
&MPATH_cache_populate,
NULL,
NULL,
&MPATH_draw_scene,
NULL,
NULL,
};

View File

@@ -92,6 +92,10 @@ void DRW_globals_update(void)
UI_GetThemeColor4fv(TH_NURB_SEL_ULINE, ts.colorNurbSelUline);
UI_GetThemeColor4fv(TH_ACTIVE_SPLINE, ts.colorActiveSpline);
UI_GetThemeColor4fv(TH_BONE_POSE, ts.colorBonePose);
UI_GetThemeColor4fv(TH_CFRAME, ts.colorCurrentFrame);
/* Grid */
UI_GetThemeColorShade4fv(TH_GRID, 10, ts.colorGrid);
/* emphasise division lines lighter instead of darker, if background is darker than grid */
@@ -153,6 +157,10 @@ void DRW_globals_update(void)
/* ********************************* SHGROUP ************************************* */
extern char datatoc_animviz_mpath_lines_vert_glsl[];
extern char datatoc_animviz_mpath_lines_geom_glsl[];
extern char datatoc_animviz_mpath_points_vert_glsl[];
extern char datatoc_armature_axes_vert_glsl[];
extern char datatoc_armature_sphere_solid_vert_glsl[];
extern char datatoc_armature_sphere_solid_frag_glsl[];
@@ -167,7 +175,12 @@ extern char datatoc_armature_shape_outline_vert_glsl[];
extern char datatoc_armature_shape_outline_geom_glsl[];
extern char datatoc_armature_stick_vert_glsl[];
extern char datatoc_armature_stick_frag_glsl[];
extern char datatoc_common_globals_lib_glsl[];
extern char datatoc_gpu_shader_flat_color_frag_glsl[];
extern char datatoc_gpu_shader_3D_smooth_color_frag_glsl[];
extern char datatoc_gpu_shader_point_varying_color_frag_glsl[];
extern char datatoc_object_mball_handles_vert_glsl[];
@@ -182,6 +195,9 @@ static struct {
struct GPUShader *bone_sphere_outline;
struct GPUShader *bone_stick;
struct GPUShader *mpath_line_sh;
struct GPUShader *mpath_points_sh;
struct GPUShader *mball_handles;
} g_shaders = {NULL};
@@ -692,6 +708,33 @@ DRWShadingGroup *shgroup_instance_bone_stick(DRWPass *pass)
return grp;
}
struct GPUShader *mpath_line_shader_get(void)
{
if (g_shaders.mpath_line_sh == NULL) {
g_shaders.mpath_line_sh = DRW_shader_create_with_lib(
datatoc_animviz_mpath_lines_vert_glsl,
datatoc_animviz_mpath_lines_geom_glsl,
datatoc_gpu_shader_3D_smooth_color_frag_glsl,
datatoc_common_globals_lib_glsl,
NULL);
}
return g_shaders.mpath_line_sh;
}
struct GPUShader *mpath_points_shader_get(void)
{
if (g_shaders.mpath_points_sh == NULL) {
g_shaders.mpath_points_sh = DRW_shader_create_with_lib(
datatoc_animviz_mpath_points_vert_glsl,
NULL,
datatoc_gpu_shader_point_varying_color_frag_glsl,
datatoc_common_globals_lib_glsl,
NULL);
}
return g_shaders.mpath_points_sh;
}
/* ******************************************** COLOR UTILS *********************************************** */
/* TODO FINISH */

View File

@@ -87,6 +87,10 @@ typedef struct GlobalsUboStorage {
float colorNurbSelUline[4];
float colorActiveSpline[4];
float colorBonePose[4];
float colorCurrentFrame[4];
float colorGrid[4];
float colorGridEmphasise[4];
float colorGridAxisX[4];
@@ -131,6 +135,9 @@ struct DRWShadingGroup *shgroup_instance_bone_sphere_outline(struct DRWPass *pas
struct DRWShadingGroup *shgroup_instance_bone_sphere_solid(struct DRWPass *pass);
struct DRWShadingGroup *shgroup_instance_bone_stick(struct DRWPass *pass);
struct GPUShader *mpath_line_shader_get(void);
struct GPUShader *mpath_points_shader_get(void);
int DRW_object_wire_theme_get(
struct Object *ob, struct ViewLayer *view_layer, float **r_color);
float *DRW_color_background_blend_get(int theme_id);

View File

@@ -1051,6 +1051,8 @@ static void drw_engines_enable_from_engine(RenderEngineType *engine_type, int dr
static void drw_engines_enable_from_object_mode(void)
{
use_drw_engine(&draw_engine_object_type);
/* TODO(fclem) remove this, it does not belong to it's own engine. */
use_drw_engine(&draw_engine_motion_path_type);
}
static void drw_engines_enable_from_mode(int mode)
@@ -1347,7 +1349,9 @@ void DRW_draw_render_loop_ex(
drw_debug_draw();
glDisable(GL_DEPTH_TEST);
drw_engines_draw_text();
glEnable(GL_DEPTH_TEST);
if (DST.draw_ctx.evil_C) {
/* needed so manipulator isn't obscured */
@@ -2047,6 +2051,7 @@ void DRW_engines_register(void)
DRW_engine_register(&draw_engine_edit_metaball_type);
DRW_engine_register(&draw_engine_edit_surface_type);
DRW_engine_register(&draw_engine_edit_text_type);
DRW_engine_register(&draw_engine_motion_path_type);
DRW_engine_register(&draw_engine_overlay_type);
DRW_engine_register(&draw_engine_paint_texture_type);
DRW_engine_register(&draw_engine_paint_vertex_type);

View File

@@ -126,6 +126,7 @@ typedef struct DRWCallState {
typedef enum {
DRW_CALL_SINGLE, /* A single batch */
DRW_CALL_RANGE, /* Like single but only draw a range of vertices/indices. */
DRW_CALL_INSTANCES, /* Draw instances without any instancing attribs. */
DRW_CALL_GENERATE, /* Uses a callback to draw with any number of batches. */
DRW_CALL_PROCEDURAL, /* Generate a drawcall without any Gwn_Batch. */
@@ -139,6 +140,10 @@ typedef struct DRWCall {
struct { /* type == DRW_CALL_SINGLE */
Gwn_Batch *geometry;
} single;
struct { /* type == DRW_CALL_RANGE */
Gwn_Batch *geometry;
uint start, count;
} range;
struct { /* type == DRW_CALL_INSTANCES */
Gwn_Batch *geometry;
/* Count can be adjusted between redraw. If needed, we can add fixed count. */

View File

@@ -366,6 +366,25 @@ void DRW_shgroup_call_add(DRWShadingGroup *shgroup, Gwn_Batch *geom, float (*obm
BLI_LINKS_APPEND(&shgroup->calls, call);
}
void DRW_shgroup_call_range_add(DRWShadingGroup *shgroup, Gwn_Batch *geom, float (*obmat)[4], uint v_sta, uint v_count)
{
BLI_assert(geom != NULL);
BLI_assert(ELEM(shgroup->type, DRW_SHG_NORMAL, DRW_SHG_FEEDBACK_TRANSFORM));
BLI_assert(v_count);
DRWCall *call = BLI_mempool_alloc(DST.vmempool->calls);
call->state = drw_call_state_create(shgroup, obmat, NULL);
call->type = DRW_CALL_RANGE;
call->range.geometry = geom;
call->range.start = v_sta;
call->range.count = v_count;
#ifdef USE_GPU_SELECT
call->select_id = DST.select_id;
#endif
BLI_LINKS_APPEND(&shgroup->calls, call);
}
static void drw_shgroup_call_procedural_add_ex(
DRWShadingGroup *shgroup, Gwn_PrimType prim_type, uint vert_count, float (*obmat)[4])
{
@@ -398,12 +417,11 @@ void DRW_shgroup_call_procedural_triangles_add(DRWShadingGroup *shgroup, uint tr
drw_shgroup_call_procedural_add_ex(shgroup, GWN_PRIM_TRIS, tria_count * 3, obmat);
}
/* These calls can be culled and are optimized for redraw */
void DRW_shgroup_call_object_add_ex(DRWShadingGroup *shgroup, Gwn_Batch *geom, Object *ob, bool bypass_culling)
{
BLI_assert(geom != NULL);
BLI_assert(shgroup->type == DRW_SHG_NORMAL);
BLI_assert(ELEM(shgroup->type, DRW_SHG_NORMAL, DRW_SHG_FEEDBACK_TRANSFORM));
DRWCall *call = BLI_mempool_alloc(DST.vmempool->calls);
call->state = drw_call_state_object(shgroup, ob->obmat, ob);
@@ -423,7 +441,7 @@ void DRW_shgroup_call_object_add_with_callback(
DRWCallVisibilityFn *callback, void *user_data)
{
BLI_assert(geom != NULL);
BLI_assert(shgroup->type == DRW_SHG_NORMAL);
BLI_assert(ELEM(shgroup->type, DRW_SHG_NORMAL, DRW_SHG_FEEDBACK_TRANSFORM));
DRWCall *call = BLI_mempool_alloc(DST.vmempool->calls);
call->state = drw_call_state_object(shgroup, ob->obmat, ob);
@@ -441,7 +459,7 @@ void DRW_shgroup_call_object_add_with_callback(
void DRW_shgroup_call_instances_add(DRWShadingGroup *shgroup, Gwn_Batch *geom, float (*obmat)[4], uint *count)
{
BLI_assert(geom != NULL);
BLI_assert(shgroup->type == DRW_SHG_NORMAL);
BLI_assert(ELEM(shgroup->type, DRW_SHG_NORMAL, DRW_SHG_FEEDBACK_TRANSFORM));
DRWCall *call = BLI_mempool_alloc(DST.vmempool->calls);
call->state = drw_call_state_create(shgroup, obmat, NULL);
@@ -459,7 +477,7 @@ void DRW_shgroup_call_instances_add(DRWShadingGroup *shgroup, Gwn_Batch *geom, f
void DRW_shgroup_call_object_instances_add(DRWShadingGroup *shgroup, Gwn_Batch *geom, Object *ob, uint *count)
{
BLI_assert(geom != NULL);
BLI_assert(shgroup->type == DRW_SHG_NORMAL);
BLI_assert(ELEM(shgroup->type, DRW_SHG_NORMAL, DRW_SHG_FEEDBACK_TRANSFORM));
DRWCall *call = BLI_mempool_alloc(DST.vmempool->calls);
call->state = drw_call_state_object(shgroup, ob->obmat, ob);
@@ -479,7 +497,7 @@ void DRW_shgroup_call_generate_add(
float (*obmat)[4])
{
BLI_assert(geometry_fn != NULL);
BLI_assert(shgroup->type == DRW_SHG_NORMAL);
BLI_assert(ELEM(shgroup->type, DRW_SHG_NORMAL, DRW_SHG_FEEDBACK_TRANSFORM));
DRWCall *call = BLI_mempool_alloc(DST.vmempool->calls);
call->state = drw_call_state_create(shgroup, obmat, NULL);

View File

@@ -1150,6 +1150,9 @@ static void draw_shgroup(DRWShadingGroup *shgroup, DRWState pass_state)
case DRW_CALL_SINGLE:
draw_geometry_execute(shgroup, call->single.geometry);
break;
case DRW_CALL_RANGE:
draw_geometry_execute_ex(shgroup, call->range.geometry, call->range.start, call->range.count, false);
break;
case DRW_CALL_INSTANCES:
draw_geometry_execute_ex(shgroup, call->instances.geometry, 0, *call->instances.count, true);
break;

View File

@@ -34,6 +34,7 @@ extern DrawEngineType draw_engine_edit_mesh_type;
extern DrawEngineType draw_engine_edit_metaball_type;
extern DrawEngineType draw_engine_edit_surface_type;
extern DrawEngineType draw_engine_edit_text_type;
extern DrawEngineType draw_engine_motion_path_type;
extern DrawEngineType draw_engine_paint_texture_type;
extern DrawEngineType draw_engine_paint_vertex_type;
extern DrawEngineType draw_engine_paint_weight_type;

View File

@@ -0,0 +1,38 @@
layout(lines) in;
layout(triangle_strip, max_vertices = 4) out;
uniform mat4 ProjectionMatrix;
uniform vec2 viewportSize;
uniform int lineThickness = 2;
in vec4 finalColor_geom[];
in vec2 ssPos[];
out vec4 finalColor;
vec2 compute_dir(vec2 v0, vec2 v1)
{
vec2 dir = normalize(v1 - v0 + 1e-8);
dir = vec2(-dir.y, dir.x);
return dir;
}
void main(void)
{
vec2 t;
vec2 edge_dir = compute_dir(ssPos[0], ssPos[1]) / viewportSize;
bool is_persp = (ProjectionMatrix[3][3] == 0.0);
finalColor = finalColor_geom[0];
t = edge_dir * (float(lineThickness) * (is_persp ? gl_in[0].gl_Position.w : 1.0));
gl_Position = gl_in[0].gl_Position + vec4(t, 0.0, 0.0); EmitVertex();
gl_Position = gl_in[0].gl_Position - vec4(t, 0.0, 0.0); EmitVertex();
finalColor = finalColor_geom[1];
t = edge_dir * (float(lineThickness) * (is_persp ? gl_in[1].gl_Position.w : 1.0));
gl_Position = gl_in[1].gl_Position + vec4(t, 0.0, 0.0); EmitVertex();
gl_Position = gl_in[1].gl_Position - vec4(t, 0.0, 0.0); EmitVertex();
EndPrimitive();
}

View File

@@ -0,0 +1,91 @@
uniform mat4 ViewMatrix;
uniform mat4 ViewProjectionMatrix;
uniform vec2 viewportSize;
uniform int frameCurrent;
uniform int frameStart;
uniform int frameEnd;
uniform int cacheStart;
uniform bool selected;
uniform bool useCustomColor;
uniform vec3 customColor;
in vec3 pos;
out vec2 ssPos;
out vec4 finalColor_geom;
/* project to screen space */
vec2 proj(vec4 pos)
{
return (0.5 * (pos.xy / pos.w) + 0.5) * viewportSize;
}
#define SET_INTENSITY(A, B, C, min, max) (((1.0 - (float(C - B) / float(C - A))) * (max - min)) + min)
void main()
{
gl_Position = ViewProjectionMatrix * vec4(pos, 1.0);
ssPos = proj(gl_Position);
int frame = gl_VertexID + cacheStart;
float intensity; /* how faint */
vec3 blend_base = (abs(frame - frameCurrent) == 1) ? colorCurrentFrame.rgb : colorBackground.rgb; /* "bleed" cframe color to ease color blending */
/* TODO: We might want something more consistent with custom color and standard colors. */
if (frame < frameCurrent) {
if (useCustomColor) {
/* Custom color: previous frames color is darker than current frame */
finalColor_geom.rgb = customColor * 0.25;
}
else {
/* black - before frameCurrent */
if (selected) {
intensity = SET_INTENSITY(frameStart, frame, frameCurrent, 0.25, 0.75);
}
else {
intensity = SET_INTENSITY(frameStart, frame, frameCurrent, 0.68, 0.92);
}
finalColor_geom.rgb = mix(colorWire.rgb, blend_base, intensity);
}
}
else if (frame > frameCurrent) {
if (useCustomColor) {
/* Custom color: next frames color is equal to user selected color */
finalColor_geom.rgb = customColor;
}
else {
/* blue - after frameCurrent */
if (selected) {
intensity = SET_INTENSITY(frameCurrent, frame, frameEnd, 0.25, 0.75);
}
else {
intensity = SET_INTENSITY(frameCurrent, frame, frameEnd, 0.68, 0.92);
}
finalColor_geom.rgb = mix(colorBonePose.rgb, blend_base, intensity);
}
}
else {
if (useCustomColor) {
/* Custom color: current frame color is slightly darker than user selected color */
finalColor_geom.rgb = customColor * 0.5;
}
else {
/* green - on frameCurrent */
if (selected) {
intensity = 0.5f;
}
else {
intensity = 0.99f;
}
finalColor_geom.rgb = clamp(mix(colorCurrentFrame.rgb, colorBackground.rgb, intensity) - 0.1, 0.0, 0.1);
}
}
finalColor_geom.a = 1.0;
}

View File

@@ -0,0 +1,47 @@
uniform mat4 ViewProjectionMatrix;
uniform int pointSize = 2;
uniform int frameCurrent;
uniform int cacheStart;
uniform bool showKeyFrames = true;
uniform bool useCustomColor;
uniform vec3 customColor;
in vec3 pos;
in int flag;
#define MOTIONPATH_VERT_SEL (1 << 0)
#define MOTIONPATH_VERT_KEY (1 << 1)
out vec4 finalColor;
void main()
{
gl_Position = ViewProjectionMatrix * vec4(pos, 1.0);
gl_PointSize = float(pointSize + 2);
int frame = gl_VertexID + cacheStart;
finalColor = (useCustomColor) ? vec4(customColor, 1.0) : vec4(1.0);
/* Bias to reduce z fighting with the path */
gl_Position.z -= 1e-4;
if (showKeyFrames) {
if ((flag & MOTIONPATH_VERT_KEY) != 0) {
gl_PointSize = float(pointSize + 5);
finalColor = colorVertexSelect;
/* Bias more to get these on top of regular points */
gl_Position.z -= 1e-4;
}
/* Draw big green dot where the current frame is.
* NOTE: this is only done when keyframes are shown, since this adds similar types of clutter
*/
if (frame == frameCurrent) {
gl_PointSize = float(pointSize + 8);
finalColor = colorCurrentFrame;
/* Bias more to get these on top of keyframes */
gl_Position.z -= 1e-4;
}
}
}

View File

@@ -48,6 +48,10 @@ layout(std140) uniform globalsBlock {
vec4 colorNurbSelUline;
vec4 colorActiveSpline;
vec4 colorBonePose;
vec4 colorCurrentFrame;
vec4 colorGrid;
vec4 colorGridEmphasise;
vec4 colorGridAxisX;

View File

@@ -193,6 +193,9 @@ void ED_pose_recalculate_paths(bContext *C, Scene *scene, Object *ob)
/* recalculate paths, then free */
animviz_calc_motionpaths(depsgraph, bmain, scene, &targets);
BLI_freelistN(&targets);
/* tag armature object for copy on write - so paths will draw/redraw */
DEG_id_tag_update(&ob->id, DEG_TAG_COPY_ON_WRITE);
}

View File

@@ -1004,6 +1004,15 @@ void ED_objects_recalculate_paths(bContext *C, Scene *scene)
/* recalculate paths, then free */
animviz_calc_motionpaths(depsgraph, bmain, scene, &targets);
BLI_freelistN(&targets);
/* tag objects for copy on write - so paths will draw/redraw */
CTX_DATA_BEGIN(C, Object *, ob, selected_editable_objects)
{
if (ob->mpath) {
DEG_id_tag_update(&ob->id, DEG_TAG_COPY_ON_WRITE);
}
}
CTX_DATA_END;
}

View File

@@ -61,7 +61,8 @@ typedef struct bMotionPathVert {
/* bMotionPathVert->flag */
typedef enum eMotionPathVert_Flag {
/* vert is selected */
MOTIONPATH_VERT_SEL = (1 << 0)
MOTIONPATH_VERT_SEL = (1 << 0),
MOTIONPATH_VERT_KEY = (1 << 1),
} eMotionPathVert_Flag;
/* ........ */
@@ -79,6 +80,12 @@ typedef struct bMotionPath {
float color[3]; /* optional custom color */
int line_thickness; /* line thickness */
int flag; /* baking settings - eMotionPath_Flag */
/* Used for drawing. */
struct Gwn_VertBuf *points_vbo;
struct Gwn_Batch *batch_line;
struct Gwn_Batch *batch_points;
void *pad;
} bMotionPath;
/* bMotionPath->flag */

View File

@@ -359,6 +359,7 @@ enum {
V3D_OVERLAY_LOOK_DEV = (1 << 3),
V3D_OVERLAY_WIREFRAMES = (1 << 4),
V3D_OVERLAY_HIDE_TEXT = (1 << 5),
V3D_OVERLAY_HIDE_MOTION_PATHS = (1 << 6),
};
/* View3DOverlay->edit_flag */

View File

@@ -2489,6 +2489,12 @@ static void rna_def_space_view3d_overlay(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Bone Selection", "Show the Bone Selection Overlay");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
prop = RNA_def_property(srna, "show_motion_paths", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_negative_sdna(prop, NULL, "overlay.flag", V3D_OVERLAY_HIDE_MOTION_PATHS);
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_ui_text(prop, "Motion Paths", "Show the Motion Paths Overlay");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
prop = RNA_def_property(srna, "show_look_dev", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "overlay.flag", V3D_OVERLAY_LOOK_DEV);
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);