Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoshua Leung <aligorith@gmail.com>2018-06-01 17:38:21 +0300
committerJoshua Leung <aligorith@gmail.com>2018-06-01 17:38:21 +0300
commit72a360827bc47e68bf47a5aa4ad9185b031423c4 (patch)
treec0e27dc580fca576dc7e3fc0ee21db2559d0f80c /source/blender/draw/intern/draw_anim_viz.c
parent44a8070db3c03a4e12d1ec1ca15432ec2b36e2fc (diff)
T54991: Restore support for Motion Path drawing in 2.8
This commit restores support for Motion Path drawing in 2.8 (as it wasn't ported over to the new draw engines earlier, and the existing space_view3d/drawanimviz.c code was removed during the Blender Internal removal). Notes: * Motion Paths are now implemented as an overlay (enabled by default). Therefore, you can turn all of them on/off from the "Overlays" popover * By and large, we have kept the same draw style as was used in 2.7 Further changes can happen later following further design work. * One change from 2.7 is that thicker lines are used by default (2px vs 1px) Todo's: * There are some bad-level calls introduced here (i.e. the actgroup_to_keylist() stuff). These were introduced to optimise drawing performance (by avoiding full keyframes -> keylist conversion step on each drawcall). Instead, this has been moved to the calculation step (in blenkernel). Soon, there will be some cleanups/improvements with those functions, so until then, we'll keep the bad level calls. Credits: * Clément Foucault (fclem) - Draw Engine magic + Shader Conversion/Optimisation * Joshua Leung (Aligorith) - COW fixes, UI integration, etc. Revision History: See "tmp-b28-motionpath_drawing" branch (rBa12ab5b2ef49ccacae091ccb54d72de0d63f990d)
Diffstat (limited to 'source/blender/draw/intern/draw_anim_viz.c')
-rw-r--r--source/blender/draw/intern/draw_anim_viz.c351
1 files changed, 351 insertions, 0 deletions
diff --git a/source/blender/draw/intern/draw_anim_viz.c b/source/blender/draw/intern/draw_anim_viz.c
new file mode 100644
index 00000000000..ff1289b2a21
--- /dev/null
+++ b/source/blender/draw/intern/draw_anim_viz.c
@@ -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,
+};
+