6ee6f59e5fa85125e0fa14d3a9ff001919c0e12c
[blender.git] / source / blender / draw / modes / pose_mode.c
1 /*
2  * Copyright 2016, Blender Foundation.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * Contributor(s): Blender Institute
19  *
20  */
21
22 /** \file blender/draw/modes/pose_mode.c
23  *  \ingroup draw
24  */
25 #include "BKE_modifier.h"
26
27 #include "DNA_modifier_types.h"
28 #include "DNA_view3d_types.h"
29
30 #include "DRW_engine.h"
31 #include "DRW_render.h"
32
33 /* If builtin shaders are needed */
34 #include "GPU_shader.h"
35
36 #include "draw_common.h"
37
38 #include "draw_mode_engines.h"
39
40 extern GlobalsUboStorage ts;
41
42 /* *********** LISTS *********** */
43 /* All lists are per viewport specific datas.
44  * They are all free when viewport changes engines
45  * or is free itself. Use POSE_engine_init() to
46  * initialize most of them and POSE_cache_init()
47  * for POSE_PassList */
48
49 typedef struct POSE_PassList {
50         struct DRWPass *bone_solid[2];
51         struct DRWPass *bone_outline[2];
52         struct DRWPass *bone_wire[2];
53         struct DRWPass *bone_envelope[2];
54         struct DRWPass *bone_axes;
55         struct DRWPass *relationship[2];
56         struct DRWPass *bone_selection;
57 } POSE_PassList;
58
59 typedef struct POSE_StorageList {
60         struct POSE_PrivateData *g_data;
61 } POSE_StorageList;
62
63 typedef struct POSE_Data {
64         void *engine_type;
65         DRWViewportEmptyList *fbl;
66         DRWViewportEmptyList *txl;
67         POSE_PassList *psl;
68         POSE_StorageList *stl;
69 } POSE_Data;
70
71 /* *********** STATIC *********** */
72
73 typedef struct POSE_PrivateData {
74         DRWShadingGroup *bone_selection_shgrp;
75         DRWShadingGroup *bone_selection_invert_shgrp;
76         float blend_color[4];
77         float blend_color_invert[4];
78         bool transparent_bones;
79 } POSE_PrivateData; /* Transient data */
80
81 static struct {
82         struct GPUShader *bone_selection_sh;
83 } e_data = {NULL};
84
85
86 /* *********** FUNCTIONS *********** */
87 static bool POSE_is_bone_selection_overlay_active(void)
88 {
89         const DRWContextState *draw_ctx = DRW_context_state_get();
90         const View3D *v3d = draw_ctx->v3d;
91         return v3d && (v3d->overlay.flag & V3D_OVERLAY_BONE_SELECT) && draw_ctx->object_pose;
92 }
93
94 static void POSE_engine_init(void *UNUSED(vedata))
95 {
96         if (!e_data.bone_selection_sh) {
97                 e_data.bone_selection_sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_UNIFORM_COLOR);
98         }
99 }
100
101 static void POSE_engine_free(void)
102 {
103 }
104
105 /* Here init all passes and shading groups
106  * Assume that all Passes are NULL */
107 static void POSE_cache_init(void *vedata)
108 {
109         POSE_PassList *psl = ((POSE_Data *)vedata)->psl;
110         POSE_StorageList *stl = ((POSE_Data *)vedata)->stl;
111         const DRWContextState *draw_ctx = DRW_context_state_get();
112         View3D *v3d = draw_ctx->v3d;
113
114         if (!stl->g_data) {
115                 /* Alloc transient pointers */
116                 stl->g_data = MEM_callocN(sizeof(*stl->g_data), __func__);
117         }
118         POSE_PrivateData *ppd = stl->g_data;
119         ppd->transparent_bones = (draw_ctx->v3d->overlay.arm_flag & V3D_OVERLAY_ARM_TRANSP_BONES) != 0;
120
121         for (int i = 0; i < 2; ++i) {
122                 /* Solid bones */
123                 DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_CULL_BACK;
124                 psl->bone_solid[i] = DRW_pass_create("Bone Solid Pass", state);
125
126                 /* Bones Outline */
127                 state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL;
128                 psl->bone_outline[i] = DRW_pass_create("Bone Outline Pass", state);
129
130                 /* Wire bones */
131                 state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_BLEND;
132                 psl->bone_wire[i] = DRW_pass_create("Bone Wire Pass", state);
133
134                 /* distance outline around envelope bones */
135                 state = DRW_STATE_ADDITIVE | DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_CULL_FRONT;
136                 psl->bone_envelope[i] = DRW_pass_create("Bone Envelope Outline Pass", state);
137
138                 state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL |
139                         DRW_STATE_BLEND | DRW_STATE_WIRE;
140                 psl->relationship[i] = DRW_pass_create("Bone Relationship Pass", state);
141         }
142
143         {
144                 DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WIRE_SMOOTH | DRW_STATE_BLEND;
145                 psl->bone_axes = DRW_pass_create("Bone Axes Pass", state);
146         }
147
148         {
149                 if (POSE_is_bone_selection_overlay_active()) {
150                         const float alpha = (draw_ctx->object_mode & OB_MODE_WEIGHT_PAINT) ? 0.0f : v3d->overlay.xray_alpha_bone;
151                         copy_v4_fl4(ppd->blend_color, 0.0f, 0.0f, 0.0f, alpha);
152                         copy_v4_fl4(ppd->blend_color_invert, 0.0f, 0.0f, 0.0f, pow(alpha, 4));
153                         DRWShadingGroup *grp;
154                         psl->bone_selection = DRW_pass_create(
155                                 "Bone Selection",
156                                 DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL | DRW_STATE_BLEND);
157                         grp = DRW_shgroup_create(e_data.bone_selection_sh, psl->bone_selection);
158                         DRW_shgroup_uniform_vec4(grp, "color", ppd->blend_color, 1);
159                         stl->g_data->bone_selection_shgrp = grp;
160                         grp = DRW_shgroup_create(e_data.bone_selection_sh, psl->bone_selection);
161                         DRW_shgroup_uniform_vec4(grp, "color", ppd->blend_color_invert, 1);
162                         stl->g_data->bone_selection_invert_shgrp = grp;
163                 }
164         }
165 }
166
167 static bool POSE_is_driven_by_active_armature(Object *ob)
168 {
169         Object *ob_arm = modifiers_isDeformedByArmature(ob);
170         if (ob_arm) {
171                 const DRWContextState *draw_ctx = DRW_context_state_get();
172                 bool is_active = DRW_pose_mode_armature(ob_arm, draw_ctx->obact);
173                 if (!is_active && ob_arm->proxy_from) {
174                         is_active = DRW_pose_mode_armature(ob_arm->proxy_from, draw_ctx->obact);
175                 }
176                 return is_active;
177         }
178         else {
179                 Object *ob_mesh_deform = modifiers_isDeformedByMeshDeform(ob);
180                 if (ob_mesh_deform) {
181                         return POSE_is_driven_by_active_armature(ob_mesh_deform);
182                 }
183         }
184         return false;
185 }
186
187 /* Add geometry to shading groups. Execute for each objects */
188 static void POSE_cache_populate(void *vedata, Object *ob)
189 {
190         POSE_PassList *psl = ((POSE_Data *)vedata)->psl;
191         POSE_PrivateData *ppd = ((POSE_Data *)vedata)->stl->g_data;
192         const DRWContextState *draw_ctx = DRW_context_state_get();
193
194         /* In the future this will allow us to implement face gizmos,
195          * and similar functionalities. For now we handle only pose bones. */
196
197         if (ob->type == OB_ARMATURE) {
198                 if ((draw_ctx->v3d->flag2 & V3D_RENDER_OVERRIDE) ||
199                     (draw_ctx->v3d->overlay.flag & V3D_OVERLAY_HIDE_BONES))
200                 {
201                         return;
202                 }
203                 if (DRW_pose_mode_armature(ob, draw_ctx->obact)) {
204                         int ghost = (ob->dtx & OB_DRAWXRAY) ? 1 : 0;
205
206                         DRWArmaturePasses passes = {
207                             .bone_solid = psl->bone_solid[ghost],
208                             .bone_outline = psl->bone_outline[ghost],
209                             .bone_wire = psl->bone_wire[ghost],
210                             .bone_envelope = psl->bone_envelope[ghost],
211                             .bone_axes = psl->bone_axes,
212                             .relationship_lines = psl->relationship[ghost],
213                         };
214                         DRW_shgroup_armature_pose(ob, passes, ppd->transparent_bones);
215                 }
216         }
217         else if (ob->type == OB_MESH &&
218                  !DRW_state_is_select() &&
219                  POSE_is_bone_selection_overlay_active())
220         {
221                 struct GPUBatch *geom = DRW_cache_object_surface_get(ob);
222                 if (geom) {
223                         if (POSE_is_driven_by_active_armature(ob)) {
224                                 DRW_shgroup_call_object_add(ppd->bone_selection_shgrp, geom, ob);
225                         }
226                         else {
227                                 DRW_shgroup_call_object_add(ppd->bone_selection_invert_shgrp, geom, ob);
228                         }
229                 }
230         }
231 }
232
233 /**
234  * Return true if armature should be handled by the pose mode engine.
235  */
236 bool DRW_pose_mode_armature(Object *ob, Object *active_ob)
237 {
238         const DRWContextState *draw_ctx = DRW_context_state_get();
239
240         /* Pose armature is handled by pose mode engine. */
241         if (((ob == active_ob) || (ob->mode & OB_MODE_POSE)) &&
242             ((draw_ctx->object_mode & OB_MODE_POSE) != 0))
243         {
244                 return true;
245         }
246
247         /* Armature parent is also handled by pose mode engine. */
248         if ((active_ob != NULL) && ((draw_ctx->object_mode & OB_MODE_WEIGHT_PAINT) != 0)) {
249                 if (ob == draw_ctx->object_pose) {
250                         return true;
251                 }
252         }
253
254         return false;
255 }
256
257 /* Draw time ! Control rendering pipeline from here */
258 static void POSE_draw_scene(void *vedata)
259 {
260         POSE_PassList *psl = ((POSE_Data *)vedata)->psl;
261         DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get();
262         DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
263         const DRWContextState *draw_ctx = DRW_context_state_get();
264         const bool transparent_bones = (draw_ctx->v3d->overlay.arm_flag & V3D_OVERLAY_ARM_TRANSP_BONES) != 0;
265         const bool bone_selection_overlay = POSE_is_bone_selection_overlay_active();
266
267         if (DRW_state_is_select()) {
268                 DRW_draw_pass(psl->bone_solid[0]);
269                 DRW_draw_pass(psl->bone_wire[0]);
270                 DRW_draw_pass(psl->bone_solid[1]);
271                 DRW_draw_pass(psl->bone_wire[1]);
272                 return;
273         }
274
275         if (bone_selection_overlay) {
276                 GPU_framebuffer_bind(dfbl->default_fb);
277                 DRW_draw_pass(psl->bone_selection);
278                 GPU_framebuffer_bind(dfbl->depth_only_fb);
279                 GPU_framebuffer_clear_depth(dfbl->depth_only_fb, 1.0);
280                 GPU_framebuffer_bind(dfbl->default_fb);
281         }
282
283         DRW_draw_pass(psl->bone_envelope[0]);
284
285         if (transparent_bones) {
286                 DRW_pass_state_add(psl->bone_solid[0], DRW_STATE_BLEND);
287                 DRW_pass_state_remove(psl->bone_solid[0], DRW_STATE_WRITE_DEPTH);
288                 DRW_draw_pass(psl->bone_solid[0]);
289         }
290
291         MULTISAMPLE_SYNC_ENABLE(dfbl, dtxl);
292
293         if (!transparent_bones) {
294                 DRW_draw_pass(psl->bone_solid[0]);
295         }
296
297         DRW_draw_pass(psl->bone_outline[0]);
298         DRW_draw_pass(psl->bone_wire[0]);
299         DRW_draw_pass(psl->relationship[0]);
300
301         MULTISAMPLE_SYNC_DISABLE(dfbl, dtxl);
302
303         if (!DRW_pass_is_empty(psl->bone_envelope[1]) ||
304             !DRW_pass_is_empty(psl->bone_solid[1]) ||
305             !DRW_pass_is_empty(psl->bone_outline[1]) ||
306             !DRW_pass_is_empty(psl->bone_wire[1]) ||
307             !DRW_pass_is_empty(psl->relationship[1]))
308         {
309                 if (DRW_state_is_fbo()) {
310                         GPU_framebuffer_bind(dfbl->default_fb);
311                         GPU_framebuffer_clear_depth(dfbl->default_fb, 1.0f);
312                 }
313
314                 if (transparent_bones) {
315                         DRW_pass_state_add(psl->bone_solid[1], DRW_STATE_BLEND);
316                         DRW_pass_state_remove(psl->bone_solid[1], DRW_STATE_WRITE_DEPTH);
317                 }
318
319                 DRW_draw_pass(psl->bone_envelope[1]);
320                 DRW_draw_pass(psl->bone_solid[1]);
321                 DRW_draw_pass(psl->bone_outline[1]);
322                 DRW_draw_pass(psl->bone_wire[1]);
323                 DRW_draw_pass(psl->relationship[1]);
324         }
325
326         /* Draw axes with linesmooth and outside of multisample buffer. */
327         DRW_draw_pass(psl->bone_axes);
328 }
329
330 static const DrawEngineDataSize POSE_data_size = DRW_VIEWPORT_DATA_SIZE(POSE_Data);
331
332 DrawEngineType draw_engine_pose_type = {
333         NULL, NULL,
334         N_("PoseMode"),
335         &POSE_data_size,
336         &POSE_engine_init,
337         &POSE_engine_free,
338         &POSE_cache_init,
339         &POSE_cache_populate,
340         NULL,
341         NULL,
342         &POSE_draw_scene,
343         NULL,
344         NULL,
345 };